summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorConstantin Jucovschi <cj@ubuntu.localdomain>2009-03-31 06:18:54 -0400
committerConstantin Jucovschi <cj@ubuntu.localdomain>2009-03-31 06:18:54 -0400
commit0f1055b8d7f97d86c66fa602c17666bc2ff9c437 (patch)
tree9c68fa99a97063bbe4a4231e04fc09329541ac71 /src
Initial commit
Diffstat (limited to 'src')
-rw-r--r--src/grammar/AxisIterator.java34
-rw-r--r--src/grammar/AxisIteratorList.java44
-rw-r--r--src/grammar/BooleanExpr.java37
-rw-r--r--src/grammar/BooleanScalarExpr.java74
-rw-r--r--src/grammar/CastExpr.java24
-rw-r--r--src/grammar/ComplexConst.java37
-rw-r--r--src/grammar/CondenseExpr.java22
-rw-r--r--src/grammar/CondenseOperationType.java36
-rw-r--r--src/grammar/ConstantList.java36
-rw-r--r--src/grammar/CoverageConstantExpr.java31
-rw-r--r--src/grammar/CoverageConstructorExpr.java31
-rw-r--r--src/grammar/CoverageExpr.java112
-rw-r--r--src/grammar/CoverageList.java37
-rw-r--r--src/grammar/CrsList.java41
-rw-r--r--src/grammar/CrsTransformExpr.java30
-rw-r--r--src/grammar/DimensionIntervalElement.java40
-rw-r--r--src/grammar/DimensionIntervalExpr.java44
-rw-r--r--src/grammar/DimensionIntervalList.java37
-rw-r--r--src/grammar/DimensionPointElement.java39
-rw-r--r--src/grammar/DimensionPointList.java37
-rw-r--r--src/grammar/DomainExpr.java27
-rw-r--r--src/grammar/EncodedCoverageExpr.java49
-rw-r--r--src/grammar/ExponentialExpr.java24
-rw-r--r--src/grammar/ExtendExpr.java20
-rw-r--r--src/grammar/FieldInterpolationElement.java26
-rw-r--r--src/grammar/FieldInterpolationList.java37
-rw-r--r--src/grammar/ForClause.java21
-rw-r--r--src/grammar/ForClauseElements.java44
-rw-r--r--src/grammar/GeneralCondenseExpr.java46
-rw-r--r--src/grammar/IParseTreeNode.java10
-rw-r--r--src/grammar/ImageCrsDomainMetadataExpr.java25
-rw-r--r--src/grammar/IndexExpr.java50
-rw-r--r--src/grammar/InterpolationMethod.java26
-rw-r--r--src/grammar/InterpolationMethodList.java36
-rw-r--r--src/grammar/IntervalExpr.java35
-rw-r--r--src/grammar/Main.java21
-rw-r--r--src/grammar/MetaDataExpr.java81
-rw-r--r--src/grammar/NOTES17
-rw-r--r--src/grammar/NumericScalarExpr.java96
-rw-r--r--src/grammar/ProcessingExpr.java22
-rw-r--r--src/grammar/RangeConstructorExpr.java41
-rw-r--r--src/grammar/RangeConstructorTerm.java29
-rw-r--r--src/grammar/RangeExpr.java35
-rw-r--r--src/grammar/RangeExprList.java32
-rw-r--r--src/grammar/ReduceExpr.java25
-rw-r--r--src/grammar/ReturnClause.java21
-rw-r--r--src/grammar/ScalarExpr.java20
-rw-r--r--src/grammar/ScaleExpr.java27
-rw-r--r--src/grammar/SelectExpr.java25
-rw-r--r--src/grammar/SetMetaDataExpr.java109
-rw-r--r--src/grammar/SliceExpr.java20
-rw-r--r--src/grammar/StoreExpr.java22
-rw-r--r--src/grammar/StringScalarExpr.java39
-rw-r--r--src/grammar/SubsetExpr.java21
-rw-r--r--src/grammar/TrigonometricExpr.java23
-rw-r--r--src/grammar/TrimExpr.java23
-rw-r--r--src/grammar/VariableList.java38
-rw-r--r--src/grammar/WCPSRequest.java52
-rw-r--r--src/grammar/WhereClause.java20
-rw-r--r--src/grammar/wcps.g500
-rw-r--r--src/input-output.txt5
-rw-r--r--src/java_cup/compile_java_cup2
-rw-r--r--src/java_cup/java_cup/Main.java854
-rw-r--r--src/java_cup/java_cup/action_part.java93
-rw-r--r--src/java_cup/java_cup/action_production.java39
-rw-r--r--src/java_cup/java_cup/assoc.java16
-rw-r--r--src/java_cup/java_cup/emit.java897
-rw-r--r--src/java_cup/java_cup/internal_error.java22
-rw-r--r--src/java_cup/java_cup/lalr_item.java330
-rw-r--r--src/java_cup/java_cup/lalr_item_set.java371
-rw-r--r--src/java_cup/java_cup/lalr_state.java884
-rw-r--r--src/java_cup/java_cup/lalr_transition.java93
-rw-r--r--src/java_cup/java_cup/lexer.java543
-rw-r--r--src/java_cup/java_cup/log345
-rw-r--r--src/java_cup/java_cup/lr_item_core.java280
-rw-r--r--src/java_cup/java_cup/non_terminal.java301
-rw-r--r--src/java_cup/java_cup/nonassoc_action.java71
-rw-r--r--src/java_cup/java_cup/parse_action.java92
-rw-r--r--src/java_cup/java_cup/parse_action_row.java106
-rw-r--r--src/java_cup/java_cup/parse_action_table.java143
-rw-r--r--src/java_cup/java_cup/parse_reduce_row.java41
-rw-r--r--src/java_cup/java_cup/parse_reduce_table.java99
-rw-r--r--src/java_cup/java_cup/parser.cup863
-rw-r--r--src/java_cup/java_cup/parser.java1849
-rw-r--r--src/java_cup/java_cup/production.java756
-rw-r--r--src/java_cup/java_cup/production_part.java94
-rw-r--r--src/java_cup/java_cup/reduce_action.java84
-rw-r--r--src/java_cup/java_cup/runtime/Scanner.java25
-rw-r--r--src/java_cup/java_cup/runtime/Symbol.java105
-rw-r--r--src/java_cup/java_cup/runtime/lr_parser.java1238
-rw-r--r--src/java_cup/java_cup/runtime/virtual_parse_stack.java145
-rw-r--r--src/java_cup/java_cup/shift_action.java82
-rw-r--r--src/java_cup/java_cup/sym.java43
-rw-r--r--src/java_cup/java_cup/symbol.java107
-rw-r--r--src/java_cup/java_cup/symbol_part.java100
-rw-r--r--src/java_cup/java_cup/symbol_set.java231
-rw-r--r--src/java_cup/java_cup/terminal.java169
-rw-r--r--src/java_cup/java_cup/terminal_set.java253
-rw-r--r--src/java_cup/java_cup/version.java55
-rw-r--r--src/java_cup/parser.cup863
-rw-r--r--src/java_cup/runtime/Scanner.classbin0 -> 211 bytes
-rw-r--r--src/java_cup/runtime/Scanner.java25
-rw-r--r--src/java_cup/runtime/Symbol.classbin0 -> 1364 bytes
-rw-r--r--src/java_cup/runtime/Symbol.java105
-rw-r--r--src/java_cup/runtime/lr_parser.classbin0 -> 12335 bytes
-rw-r--r--src/java_cup/runtime/lr_parser.java1238
-rw-r--r--src/java_cup/runtime/virtual_parse_stack.classbin0 -> 1856 bytes
-rw-r--r--src/java_cup/runtime/virtual_parse_stack.java145
-rw-r--r--src/java_cup/simple_calc/Main.java32
-rw-r--r--src/java_cup/simple_calc/parser.cup55
-rw-r--r--src/java_cup/simple_calc/parser.java318
-rw-r--r--src/java_cup/simple_calc/scanner.java63
-rw-r--r--src/java_cup/simple_calc/sym.java25
-rw-r--r--src/syntaxParser/AtomicLit.java56
-rw-r--r--src/syntaxParser/AxisCrsElement.java19
-rw-r--r--src/syntaxParser/AxisCrsList.java7
-rw-r--r--src/syntaxParser/AxisIntervalElement.java32
-rw-r--r--src/syntaxParser/AxisIntervalList.java6
-rw-r--r--src/syntaxParser/AxisPointElement.java30
-rw-r--r--src/syntaxParser/AxisPointList.java8
-rw-r--r--src/syntaxParser/BinaryInducedExpr.java38
-rw-r--r--src/syntaxParser/BooleanExpr.java33
-rw-r--r--src/syntaxParser/BooleanScalarExpr.java38
-rw-r--r--src/syntaxParser/CastExpr.java24
-rw-r--r--src/syntaxParser/ComplexLit.java33
-rw-r--r--src/syntaxParser/CondenseExpr.java22
-rw-r--r--src/syntaxParser/CoverageConstructorExpr.java21
-rw-r--r--src/syntaxParser/CoverageExpr.java61
-rw-r--r--src/syntaxParser/CoverageList.java33
-rw-r--r--src/syntaxParser/CrsList.java33
-rw-r--r--src/syntaxParser/CrsTransformExpr.java23
-rw-r--r--src/syntaxParser/EncodedCoverageExpr.java42
-rw-r--r--src/syntaxParser/ExponentialExpr.java22
-rw-r--r--src/syntaxParser/ExtendExpr.java20
-rw-r--r--src/syntaxParser/FieldInterpolationElement.java18
-rw-r--r--src/syntaxParser/FieldInterpolationList.java9
-rw-r--r--src/syntaxParser/FieldInterpolationMethod.java20
-rw-r--r--src/syntaxParser/ForClause.java17
-rw-r--r--src/syntaxParser/ForClauseElements.java39
-rw-r--r--src/syntaxParser/GeneralCondenseExpr.java37
-rw-r--r--src/syntaxParser/GetMetaDataExpr.java50
-rw-r--r--src/syntaxParser/IParseTreeNode.java9
-rw-r--r--src/syntaxParser/InducedExpr.java21
-rw-r--r--src/syntaxParser/InterpolationMethodList.java6
-rw-r--r--src/syntaxParser/JLex/CAccept.classbin0 -> 641 bytes
-rw-r--r--src/syntaxParser/JLex/CAcceptAnchor.classbin0 -> 297 bytes
-rw-r--r--src/syntaxParser/JLex/CAlloc.classbin0 -> 1377 bytes
-rw-r--r--src/syntaxParser/JLex/CBunch.classbin0 -> 455 bytes
-rw-r--r--src/syntaxParser/JLex/CDTrans.classbin0 -> 479 bytes
-rw-r--r--src/syntaxParser/JLex/CDfa.classbin0 -> 530 bytes
-rw-r--r--src/syntaxParser/JLex/CEmit.classbin0 -> 19867 bytes
-rw-r--r--src/syntaxParser/JLex/CError.classbin0 -> 2694 bytes
-rw-r--r--src/syntaxParser/JLex/CInput.classbin0 -> 1366 bytes
-rw-r--r--src/syntaxParser/JLex/CLexGen.classbin0 -> 25971 bytes
-rw-r--r--src/syntaxParser/JLex/CMakeNfa.classbin0 -> 6169 bytes
-rw-r--r--src/syntaxParser/JLex/CMinimize.classbin0 -> 5862 bytes
-rw-r--r--src/syntaxParser/JLex/CNfa.classbin0 -> 1031 bytes
-rw-r--r--src/syntaxParser/JLex/CNfa2Dfa.classbin0 -> 5215 bytes
-rw-r--r--src/syntaxParser/JLex/CNfaPair.classbin0 -> 281 bytes
-rw-r--r--src/syntaxParser/JLex/CSet.classbin0 -> 1297 bytes
-rw-r--r--src/syntaxParser/JLex/CSimplifyNfa.classbin0 -> 2472 bytes
-rw-r--r--src/syntaxParser/JLex/CSpec.classbin0 -> 2939 bytes
-rw-r--r--src/syntaxParser/JLex/CUtility.classbin0 -> 2681 bytes
-rw-r--r--src/syntaxParser/JLex/Main.classbin0 -> 670 bytes
-rw-r--r--src/syntaxParser/JLex/Main.java7841
-rw-r--r--src/syntaxParser/JLex/SparseBitSet$1.classbin0 -> 384 bytes
-rw-r--r--src/syntaxParser/JLex/SparseBitSet$2.classbin0 -> 384 bytes
-rw-r--r--src/syntaxParser/JLex/SparseBitSet$3.classbin0 -> 384 bytes
-rw-r--r--src/syntaxParser/JLex/SparseBitSet$4.classbin0 -> 961 bytes
-rw-r--r--src/syntaxParser/JLex/SparseBitSet$BinOp.classbin0 -> 191 bytes
-rw-r--r--src/syntaxParser/JLex/SparseBitSet.classbin0 -> 5958 bytes
-rw-r--r--src/syntaxParser/List.java42
-rw-r--r--src/syntaxParser/Makefile34
-rw-r--r--src/syntaxParser/NumericScalarExpr.java51
-rw-r--r--src/syntaxParser/ProcessingExpr.java18
-rw-r--r--src/syntaxParser/README97
-rw-r--r--src/syntaxParser/RangeValue.java17
-rw-r--r--src/syntaxParser/RangeValueList.java10
-rw-r--r--src/syntaxParser/ReduceExpr.java19
-rw-r--r--src/syntaxParser/ReturnClause.java16
-rw-r--r--src/syntaxParser/SAMPLE_REQUESTS.txt52
-rw-r--r--src/syntaxParser/ScalarExpr.java18
-rw-r--r--src/syntaxParser/ScalarLit.java42
-rw-r--r--src/syntaxParser/ScalarLitList.java52
-rw-r--r--src/syntaxParser/ScaleExpr.java24
-rw-r--r--src/syntaxParser/SelectExpr.java22
-rw-r--r--src/syntaxParser/SetMetaDataExpr.java54
-rw-r--r--src/syntaxParser/SliceExpr.java20
-rw-r--r--src/syntaxParser/StoreExpr.java15
-rw-r--r--src/syntaxParser/StructuredLiteral.java15
-rw-r--r--src/syntaxParser/SubsetExpr.java21
-rw-r--r--src/syntaxParser/SyntaxErrorException.java26
-rw-r--r--src/syntaxParser/TrigonometricExpr.java23
-rw-r--r--src/syntaxParser/TrimExpr.java21
-rw-r--r--src/syntaxParser/UnaryArithMeticExpr.java31
-rw-r--r--src/syntaxParser/UnaryInducedExpr.java23
-rw-r--r--src/syntaxParser/VariableList.java37
-rw-r--r--src/syntaxParser/WCPSRequest.java42
-rw-r--r--src/syntaxParser/WCPSRequestProcessor.java46
-rw-r--r--src/syntaxParser/WhereClause.java14
-rw-r--r--src/syntaxParser/java-cup-11a.jarbin0 -> 96121 bytes
-rw-r--r--src/syntaxParser/java_cup/CUP$parser$actions.classbin0 -> 15551 bytes
-rw-r--r--src/syntaxParser/java_cup/Main.classbin0 -> 14726 bytes
-rw-r--r--src/syntaxParser/java_cup/Main.java854
-rw-r--r--src/syntaxParser/java_cup/SAVE/Main.java854
-rw-r--r--src/syntaxParser/java_cup/SAVE/action_part.java93
-rw-r--r--src/syntaxParser/java_cup/SAVE/action_production.java39
-rw-r--r--src/syntaxParser/java_cup/SAVE/assoc.java16
-rw-r--r--src/syntaxParser/java_cup/SAVE/emit.java897
-rw-r--r--src/syntaxParser/java_cup/SAVE/internal_error.java22
-rw-r--r--src/syntaxParser/java_cup/SAVE/lalr_item.java330
-rw-r--r--src/syntaxParser/java_cup/SAVE/lalr_item_set.java371
-rw-r--r--src/syntaxParser/java_cup/SAVE/lalr_state.java884
-rw-r--r--src/syntaxParser/java_cup/SAVE/lalr_transition.java93
-rw-r--r--src/syntaxParser/java_cup/SAVE/lexer.java543
-rw-r--r--src/syntaxParser/java_cup/SAVE/lr_item_core.java280
-rw-r--r--src/syntaxParser/java_cup/SAVE/non_terminal.java301
-rw-r--r--src/syntaxParser/java_cup/SAVE/nonassoc_action.java71
-rw-r--r--src/syntaxParser/java_cup/SAVE/parse_action.java92
-rw-r--r--src/syntaxParser/java_cup/SAVE/parse_action_row.java106
-rw-r--r--src/syntaxParser/java_cup/SAVE/parse_action_table.java143
-rw-r--r--src/syntaxParser/java_cup/SAVE/parse_reduce_row.java41
-rw-r--r--src/syntaxParser/java_cup/SAVE/parse_reduce_table.java99
-rw-r--r--src/syntaxParser/java_cup/SAVE/parser.cup863
-rw-r--r--src/syntaxParser/java_cup/SAVE/parser.java1849
-rw-r--r--src/syntaxParser/java_cup/SAVE/production.java756
-rw-r--r--src/syntaxParser/java_cup/SAVE/production_part.java94
-rw-r--r--src/syntaxParser/java_cup/SAVE/reduce_action.java84
-rw-r--r--src/syntaxParser/java_cup/SAVE/shift_action.java82
-rw-r--r--src/syntaxParser/java_cup/SAVE/sym.java43
-rw-r--r--src/syntaxParser/java_cup/SAVE/symbol.java107
-rw-r--r--src/syntaxParser/java_cup/SAVE/symbol_part.java100
-rw-r--r--src/syntaxParser/java_cup/SAVE/symbol_set.java231
-rw-r--r--src/syntaxParser/java_cup/SAVE/terminal.java169
-rw-r--r--src/syntaxParser/java_cup/SAVE/terminal_set.java253
-rw-r--r--src/syntaxParser/java_cup/SAVE/version.java55
-rw-r--r--src/syntaxParser/java_cup/action_part.classbin0 -> 1107 bytes
-rw-r--r--src/syntaxParser/java_cup/action_part.java93
-rw-r--r--src/syntaxParser/java_cup/action_production.classbin0 -> 604 bytes
-rw-r--r--src/syntaxParser/java_cup/action_production.java39
-rw-r--r--src/syntaxParser/java_cup/assoc.classbin0 -> 333 bytes
-rw-r--r--src/syntaxParser/java_cup/assoc.java16
-rw-r--r--src/syntaxParser/java_cup/emit.classbin0 -> 13969 bytes
-rw-r--r--src/syntaxParser/java_cup/emit.java897
-rw-r--r--src/syntaxParser/java_cup/internal_error.classbin0 -> 580 bytes
-rw-r--r--src/syntaxParser/java_cup/internal_error.java22
-rw-r--r--src/syntaxParser/java_cup/lalr_item.classbin0 -> 3741 bytes
-rw-r--r--src/syntaxParser/java_cup/lalr_item.java330
-rw-r--r--src/syntaxParser/java_cup/lalr_item_set.classbin0 -> 3937 bytes
-rw-r--r--src/syntaxParser/java_cup/lalr_item_set.java371
-rw-r--r--src/syntaxParser/java_cup/lalr_state.classbin0 -> 9664 bytes
-rw-r--r--src/syntaxParser/java_cup/lalr_state.java884
-rw-r--r--src/syntaxParser/java_cup/lalr_transition.classbin0 -> 1508 bytes
-rw-r--r--src/syntaxParser/java_cup/lalr_transition.java93
-rw-r--r--src/syntaxParser/java_cup/lexer.classbin0 -> 5258 bytes
-rw-r--r--src/syntaxParser/java_cup/lexer.java543
-rw-r--r--src/syntaxParser/java_cup/lr_item_core.classbin0 -> 3158 bytes
-rw-r--r--src/syntaxParser/java_cup/lr_item_core.java280
-rw-r--r--src/syntaxParser/java_cup/non_terminal.classbin0 -> 3759 bytes
-rw-r--r--src/syntaxParser/java_cup/non_terminal.java301
-rw-r--r--src/syntaxParser/java_cup/nonassoc_action.classbin0 -> 675 bytes
-rw-r--r--src/syntaxParser/java_cup/nonassoc_action.java71
-rw-r--r--src/syntaxParser/java_cup/parse_action.classbin0 -> 740 bytes
-rw-r--r--src/syntaxParser/java_cup/parse_action.java92
-rw-r--r--src/syntaxParser/java_cup/parse_action_row.classbin0 -> 1035 bytes
-rw-r--r--src/syntaxParser/java_cup/parse_action_row.java106
-rw-r--r--src/syntaxParser/java_cup/parse_action_table.classbin0 -> 2258 bytes
-rw-r--r--src/syntaxParser/java_cup/parse_action_table.java143
-rw-r--r--src/syntaxParser/java_cup/parse_reduce_row.classbin0 -> 529 bytes
-rw-r--r--src/syntaxParser/java_cup/parse_reduce_row.java41
-rw-r--r--src/syntaxParser/java_cup/parse_reduce_table.classbin0 -> 1295 bytes
-rw-r--r--src/syntaxParser/java_cup/parse_reduce_table.java99
-rw-r--r--src/syntaxParser/java_cup/parser.classbin0 -> 7471 bytes
-rw-r--r--src/syntaxParser/java_cup/parser.cup863
-rw-r--r--src/syntaxParser/java_cup/parser.java1849
-rw-r--r--src/syntaxParser/java_cup/production.classbin0 -> 8084 bytes
-rw-r--r--src/syntaxParser/java_cup/production.java756
-rw-r--r--src/syntaxParser/java_cup/production_part.classbin0 -> 966 bytes
-rw-r--r--src/syntaxParser/java_cup/production_part.java94
-rw-r--r--src/syntaxParser/java_cup/reduce_action.classbin0 -> 1218 bytes
-rw-r--r--src/syntaxParser/java_cup/reduce_action.java84
-rw-r--r--src/syntaxParser/java_cup/runtime/Scanner.classbin0 -> 211 bytes
-rw-r--r--src/syntaxParser/java_cup/runtime/Scanner.java25
-rw-r--r--src/syntaxParser/java_cup/runtime/Symbol.classbin0 -> 1045 bytes
-rw-r--r--src/syntaxParser/java_cup/runtime/Symbol.java105
-rw-r--r--src/syntaxParser/java_cup/runtime/lr_parser.classbin0 -> 9907 bytes
-rw-r--r--src/syntaxParser/java_cup/runtime/lr_parser.java1238
-rw-r--r--src/syntaxParser/java_cup/runtime/virtual_parse_stack.classbin0 -> 1508 bytes
-rw-r--r--src/syntaxParser/java_cup/runtime/virtual_parse_stack.java145
-rw-r--r--src/syntaxParser/java_cup/shift_action.classbin0 -> 1199 bytes
-rw-r--r--src/syntaxParser/java_cup/shift_action.java82
-rw-r--r--src/syntaxParser/java_cup/simple_calc/Main.java32
-rw-r--r--src/syntaxParser/java_cup/simple_calc/parser.cup55
-rw-r--r--src/syntaxParser/java_cup/simple_calc/parser.java318
-rw-r--r--src/syntaxParser/java_cup/simple_calc/scanner.java63
-rw-r--r--src/syntaxParser/java_cup/simple_calc/sym.java25
-rw-r--r--src/syntaxParser/java_cup/sym.classbin0 -> 1111 bytes
-rw-r--r--src/syntaxParser/java_cup/sym.java43
-rw-r--r--src/syntaxParser/java_cup/symbol.classbin0 -> 925 bytes
-rw-r--r--src/syntaxParser/java_cup/symbol.java107
-rw-r--r--src/syntaxParser/java_cup/symbol_part.classbin0 -> 1431 bytes
-rw-r--r--src/syntaxParser/java_cup/symbol_part.java100
-rw-r--r--src/syntaxParser/java_cup/symbol_set.classbin0 -> 2608 bytes
-rw-r--r--src/syntaxParser/java_cup/symbol_set.java231
-rw-r--r--src/syntaxParser/java_cup/terminal.classbin0 -> 2196 bytes
-rw-r--r--src/syntaxParser/java_cup/terminal.java169
-rw-r--r--src/syntaxParser/java_cup/terminal_set.classbin0 -> 2459 bytes
-rw-r--r--src/syntaxParser/java_cup/terminal_set.java253
-rw-r--r--src/syntaxParser/java_cup/version.classbin0 -> 549 bytes
-rw-r--r--src/syntaxParser/java_cup/version.java55
-rw-r--r--src/syntaxParser/processcoverage.xsd189
-rw-r--r--src/syntaxParser/request.wcps1
-rw-r--r--src/syntaxParser/run.bat8
-rw-r--r--src/syntaxParser/test_requests.txt101
-rw-r--r--src/syntaxParser/tmp/META-INF/MANIFEST.MF6
-rw-r--r--src/syntaxParser/wcps.cup415
-rw-r--r--src/syntaxParser/wcps.lex157
-rw-r--r--src/syntaxParser/wcps.lex_ORIG141
-rw-r--r--src/syntaxParser/wcpsRequest.xml11
-rw-r--r--src/wcps/server/cli/WCPService.java104
-rw-r--r--src/wcps/server/core/BinaryOperationCoverageExprType.java111
-rw-r--r--src/wcps/server/core/BooleanScalarExprType.java36
-rw-r--r--src/wcps/server/core/CachedMetadataSource.java73
-rw-r--r--src/wcps/server/core/CellDomainElement.java54
-rw-r--r--src/wcps/server/core/CombineRangeCoverageExprType.java14
-rw-r--r--src/wcps/server/core/CoordinateType.java27
-rw-r--r--src/wcps/server/core/CoverageExprType.java109
-rw-r--r--src/wcps/server/core/CoverageInfo.java116
-rw-r--r--src/wcps/server/core/CoverageIterator.java55
-rw-r--r--src/wcps/server/core/CrsTransformCoverageExprType.java14
-rw-r--r--src/wcps/server/core/DbMetadataSource.java291
-rw-r--r--src/wcps/server/core/DomainElement.java138
-rw-r--r--src/wcps/server/core/EncodeDataExprType.java60
-rw-r--r--src/wcps/server/core/ExtendCoverageExprType.java94
-rw-r--r--src/wcps/server/core/ICoverageInfo.java6
-rw-r--r--src/wcps/server/core/IRasNode.java5
-rw-r--r--src/wcps/server/core/InterpolationMethod.java53
-rw-r--r--src/wcps/server/core/InvalidMetadataException.java15
-rw-r--r--src/wcps/server/core/InvalidRequestException.java21
-rw-r--r--src/wcps/server/core/Metadata.java617
-rw-r--r--src/wcps/server/core/MetadataSource.java13
-rw-r--r--src/wcps/server/core/ProcessCoverageRequest.java175
-rw-r--r--src/wcps/server/core/RangeElement.java126
-rw-r--r--src/wcps/server/core/ReduceScalarExprType.java29
-rw-r--r--src/wcps/server/core/ResourceException.java19
-rw-r--r--src/wcps/server/core/SDU.java156
-rw-r--r--src/wcps/server/core/ScalarExprType.java78
-rw-r--r--src/wcps/server/core/SliceCoverageExprType.java95
-rw-r--r--src/wcps/server/core/TrimCoverageExprType.java102
-rw-r--r--src/wcps/server/core/UnaryOperationCoverageExprType.java96
-rw-r--r--src/wcps/server/core/WCPS.java134
-rw-r--r--src/wcps/server/core/WCPSException.java19
-rw-r--r--src/wcps/server/servlet/WCPService.java244
-rw-r--r--src/wcs/server/cli/CLI.java183
-rw-r--r--src/wcs/server/core/MetadataDb.java100
-rw-r--r--src/wcs/server/core/WCSException.java73
-rw-r--r--src/wcs/server/core/convertGetCoverage.java737
-rw-r--r--src/wcs/server/core/executeDescribeCoverage.java292
-rw-r--r--src/wcs/server/core/executeGetCapabilities.java264
-rw-r--r--src/wcs/server/servlet/WCS.java277
-rw-r--r--src/wcs/server/servlet/WCSTest.java210
-rw-r--r--src/wcs/server/servlet/newWcsServlet.java244
362 files changed, 55559 insertions, 0 deletions
diff --git a/src/grammar/AxisIterator.java b/src/grammar/AxisIterator.java
new file mode 100644
index 0000000..f9c7894
--- /dev/null
+++ b/src/grammar/AxisIterator.java
@@ -0,0 +1,34 @@
+package grammar;
+
+/** AxisIterator
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class AxisIterator implements IParseTreeNode
+{
+ String var;
+ String axis;
+ NumericScalarExpr hi, lo;
+ IntervalExpr interval;
+
+ public AxisIterator(String var, String axis, IntervalExpr interval)
+ {
+ this.var = var;
+ this.axis = axis;
+ this.interval = interval;
+ }
+
+ public String toXML()
+ {
+ String result = "";
+
+ result += "<axisIterator>";
+ result += "<iteratorVar>" + var + "</iteratorVar>";
+ result += "<axis>" + axis + "</axis>";
+ result += interval.toXML();
+ result += "</axisIterator>";
+
+ return result;
+ }
+
+}
diff --git a/src/grammar/AxisIteratorList.java b/src/grammar/AxisIteratorList.java
new file mode 100644
index 0000000..afe8722
--- /dev/null
+++ b/src/grammar/AxisIteratorList.java
@@ -0,0 +1,44 @@
+package grammar;
+
+/** AxisIteratorList
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class AxisIteratorList implements IParseTreeNode
+{
+ private String tag;
+ private AxisIterator it;
+ private AxisIteratorList next;
+
+ public AxisIteratorList(AxisIterator it)
+ {
+ this.it = it;
+ next=null;
+ tag = "";
+ }
+
+ public AxisIteratorList(AxisIterator it, AxisIteratorList n)
+ {
+ this.it = it;
+ next = n;
+ tag = "";
+ }
+
+ public void setTag(String tag)
+ {
+ this.tag = tag;
+ }
+
+ public String toXML()
+ {
+ String tag1 = "<" + tag + ">";
+ String tag2 = "</" + tag + ">";
+
+ if (tag.equals(""))
+ tag1 = tag2 = "";
+
+ String result = tag1 + it.toXML() + tag2
+ + next.toXML();
+ return result;
+ }
+}
diff --git a/src/grammar/BooleanExpr.java b/src/grammar/BooleanExpr.java
new file mode 100644
index 0000000..131ae62
--- /dev/null
+++ b/src/grammar/BooleanExpr.java
@@ -0,0 +1,37 @@
+package grammar;
+
+/** BooleanExpr
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class BooleanExpr implements IParseTreeNode
+{
+ IParseTreeNode e1, e2;
+ String op;
+
+ public BooleanExpr(String op, CoverageExpr cov)
+ {
+ this.op = op;
+ e1 = cov;
+ }
+
+ public BooleanExpr(String op, CoverageExpr cov, IndexExpr i)
+ {
+ this.op = op;
+ e1 = cov;
+ e2 = i;
+ }
+
+ public String toXML()
+ {
+ String result = "";
+ if (op.equalsIgnoreCase("not"))
+ result = e1.toXML();
+ else if (op.equalsIgnoreCase("bit"))
+ result = e1.toXML() + e2.toXML();
+
+ result = "<" + op + ">" + result + "</" + op + ">";
+ return result;
+ }
+
+}
diff --git a/src/grammar/BooleanScalarExpr.java b/src/grammar/BooleanScalarExpr.java
new file mode 100644
index 0000000..1123eda
--- /dev/null
+++ b/src/grammar/BooleanScalarExpr.java
@@ -0,0 +1,74 @@
+package grammar;
+
+/**
+ * BooleanScalarExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara, Andrei Aiordachioaie
+ */
+
+public class BooleanScalarExpr implements IParseTreeNode
+{
+ BooleanScalarExpr leftBooleanScalarExpr, rightBooleanScalarExpr;
+ NumericScalarExpr leftNumericScalar, rightNumericScalar;
+ IParseTreeNode left, right;
+ String booleanConstant;
+ String op;
+ String node1, node2;
+
+ public BooleanScalarExpr(String bc) {
+ op = null;
+ booleanConstant = bc;
+ }
+
+ public BooleanScalarExpr(String op, BooleanScalarExpr be){
+ this.op = op;
+ left = be ;
+ }
+
+ public BooleanScalarExpr(String op, BooleanScalarExpr lbe, BooleanScalarExpr rbe){
+ this.op = op;
+ left = lbe ;
+ right = rbe ;
+ }
+
+ public BooleanScalarExpr(String op, NumericScalarExpr left, NumericScalarExpr right)
+ {
+ this.op = op;
+ this.left = left;
+ this.right = right;
+ }
+
+ public BooleanScalarExpr(String op, StringScalarExpr e1, StringScalarExpr e2)
+ {
+ this.op = op;
+ left = e1;
+ right = e2;
+ }
+
+ public String toXML(){
+ if (op == null) return "<booleanConstant>" + booleanConstant + "</booleanConstant>";
+ else if (op.equals("not")) return "<booleanNot>" + left.toXML() + "</booleanNot>";
+ else
+ {
+ if (this.left != null)
+ node1 = this.left.toXML();
+ if (this.right != null)
+ node2 = this.right.toXML();
+
+ if (op.equals("and")) op = "booleanAnd";
+ else if (op.equals("or")) op = "booleanOr";
+ else if (op.equals("xor")) op = "booleanXor";
+
+ else if (op.equals("=")) op = "booleanEqualNumeric";
+ else if (op.equals("!=")) op = "booleanNotEqualNumeric";
+ else if (op.equals("<")) op = "booleanLessThan";
+ else if (op.equals(">")) op = "booleanGreaterThan";
+ else if (op.equals("<=")) op = "booleanLessOrEqual";
+ else if (op.equals(">=")) op = "booleanGreaterOrEqual";
+
+ return "<" + op + ">" + node1 + node2 + "</" + op + ">";
+ }
+
+ }
+
+}
diff --git a/src/grammar/CastExpr.java b/src/grammar/CastExpr.java
new file mode 100644
index 0000000..119e412
--- /dev/null
+++ b/src/grammar/CastExpr.java
@@ -0,0 +1,24 @@
+package grammar;
+/**
+ * CastExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara, Andrei Aiordachioaie
+ */
+public class CastExpr implements IParseTreeNode {
+ String castType;
+ CoverageExpr coverageExpr;
+
+ public CastExpr( CoverageExpr ce, String ct){
+ castType = ct;
+ coverageExpr = ce;
+ }
+
+ public String toXML(){
+ String result= "" ;
+ result += "<cast>";
+ result += coverageExpr.toXML();
+ result += "<type>" + castType + "</type>";
+ result += "</cast>";
+ return result;
+ }
+}
diff --git a/src/grammar/ComplexConst.java b/src/grammar/ComplexConst.java
new file mode 100644
index 0000000..d05e279
--- /dev/null
+++ b/src/grammar/ComplexConst.java
@@ -0,0 +1,37 @@
+package grammar;
+
+/**
+ * ComplexConst
+ * @author: Andrei Aiordachioaie
+ */
+public class ComplexConst
+{
+ String re, im;
+
+ /**
+ * ComplexLit constructor comment.
+ */
+ public ComplexConst()
+ {
+ super();
+ }
+
+ public ComplexConst(String val)
+ {
+ int pos = val.indexOf("+i", 0);
+
+ if (pos != -1)
+ {
+ re = val.substring(0, pos - 1);
+ im = val.substring(pos + 2, val.length());
+ }
+ }
+
+ public String toXML()
+ {
+ return "<complexConstant><re>" + re + "</re><im>" + im + "</im></complexConstant";
+ }
+}
+
+
+//~ Formatted by Jindent --- http://www.jindent.com
diff --git a/src/grammar/CondenseExpr.java b/src/grammar/CondenseExpr.java
new file mode 100644
index 0000000..718b5a1
--- /dev/null
+++ b/src/grammar/CondenseExpr.java
@@ -0,0 +1,22 @@
+package grammar;
+/**
+ * CondenseExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara, Andrei Aiordachioaie
+ */
+
+public class CondenseExpr implements IParseTreeNode{
+
+ IParseTreeNode expr;
+ String fun;
+
+ public CondenseExpr(IParseTreeNode re)
+ {
+ expr = re;
+ }
+
+ public String toXML()
+ {
+ return expr.toXML();
+ }
+}
diff --git a/src/grammar/CondenseOperationType.java b/src/grammar/CondenseOperationType.java
new file mode 100644
index 0000000..8cd3c5b
--- /dev/null
+++ b/src/grammar/CondenseOperationType.java
@@ -0,0 +1,36 @@
+package grammar;
+
+/** CondenseOperationType
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class CondenseOperationType implements IParseTreeNode
+{
+ String op;
+
+ public CondenseOperationType(String op)
+ {
+ this.op = op;
+ }
+
+ public String toXML()
+ {
+ String result = "";
+
+ if (op.equalsIgnoreCase("plus"))
+ result = "opPlus";
+ else if (op.equalsIgnoreCase("mult"))
+ result = "opMult";
+ else if (op.equalsIgnoreCase("max"))
+ result = "opMax";
+ else if (op.equalsIgnoreCase("min"))
+ result = "opMin";
+ else if (op.equalsIgnoreCase("and"))
+ result = "opAnd";
+ else if (op.equalsIgnoreCase("or"))
+ result = "opOr";
+
+ return result;
+ }
+
+}
diff --git a/src/grammar/ConstantList.java b/src/grammar/ConstantList.java
new file mode 100644
index 0000000..e40d99f
--- /dev/null
+++ b/src/grammar/ConstantList.java
@@ -0,0 +1,36 @@
+package grammar;
+
+import java.util.*;
+
+/** ConstantList
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class ConstantList implements IParseTreeNode
+{
+ LinkedList<String> list;
+
+ public ConstantList(String val)
+ {
+ list = new LinkedList<String>();
+ list.add(val);
+ }
+
+ public void add(String val)
+ {
+ list.add(val);
+ }
+
+ public String toXML()
+ {
+ String result = "";
+ Iterator<String> it = list.iterator();
+ while (it.hasNext())
+ {
+ result += "<value>" + it.next() + "</value>";
+ }
+
+ return result;
+ }
+
+}
diff --git a/src/grammar/CoverageConstantExpr.java b/src/grammar/CoverageConstantExpr.java
new file mode 100644
index 0000000..95ea7ab
--- /dev/null
+++ b/src/grammar/CoverageConstantExpr.java
@@ -0,0 +1,31 @@
+package grammar;
+
+/** CoverageConstantExpr
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class CoverageConstantExpr implements IParseTreeNode {
+
+ String name;
+ AxisIteratorList alist;
+ ConstantList clist;
+
+ public CoverageConstantExpr(String name, AxisIteratorList alist, ConstantList clist)
+ {
+ this.name = name;
+ this.alist = alist;
+ this.clist = clist;
+ }
+
+ public String toXML()
+ {
+ String result = "";
+
+ result += "<name>" + name + "</name>";
+ result += alist.toXML();
+ result += clist.toXML();
+
+ result = "<const>" + result + "</const>";
+ return result;
+ }
+}
diff --git a/src/grammar/CoverageConstructorExpr.java b/src/grammar/CoverageConstructorExpr.java
new file mode 100644
index 0000000..a80e9fe
--- /dev/null
+++ b/src/grammar/CoverageConstructorExpr.java
@@ -0,0 +1,31 @@
+package grammar;
+
+/** CoverageConstructorExpr
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class CoverageConstructorExpr implements IParseTreeNode {
+
+ String name;
+ AxisIteratorList alist;
+ ScalarExpr expr;
+
+ public CoverageConstructorExpr(String name, AxisIteratorList alist, ScalarExpr expr)
+ {
+ this.name = name;
+ this.alist = alist;
+ this.expr = expr;
+ }
+
+ public String toXML()
+ {
+ String result = "";
+
+ result += "<name>" + name + "</name>";
+ result += alist.toXML();
+ result += expr.toXML();
+
+ result = "<construct>" + result + "</construct>";
+ return result;
+ }
+}
diff --git a/src/grammar/CoverageExpr.java b/src/grammar/CoverageExpr.java
new file mode 100644
index 0000000..bbe57d7
--- /dev/null
+++ b/src/grammar/CoverageExpr.java
@@ -0,0 +1,112 @@
+package grammar;
+/**
+ * CoverageExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara, Andrei Aiordachioaie
+ */
+public class CoverageExpr implements IParseTreeNode
+{
+
+ String coverageName;
+ IParseTreeNode expr, e1, e2;
+ String function;
+ String op;
+
+ public CoverageExpr( String n )
+ {
+ coverageName = n;
+ function = "coverage";
+ }
+
+ public CoverageExpr(IParseTreeNode n)
+ {
+ expr = n;
+ function = "child";
+ }
+
+ /* Unary Induced Expressions */
+ public CoverageExpr (String op, CoverageExpr ce)
+ {
+ expr = ce;
+ function = "unaryOp";
+ this.op = op;
+ }
+
+ public CoverageExpr (String op, CoverageExpr e1, CoverageExpr e2)
+ {
+ function = "binaryOp";
+ this.op = op;
+ this.e1 = e1;
+ this.e2 = e2;
+ }
+
+ public String toXML()
+ {
+ String result = "";
+
+ if (function.equals("coverage"))
+ {
+ result = "<coverage>" + coverageName + "</coverage>";
+ }
+ else if (function.equals("binaryOp"))
+ {
+ result = "<" + op + ">" + e1.toXML() + e2.toXML() + "</" + op + ">";
+ }
+ else if (function.equals("unaryOp"))
+ result = expr.toXML();
+ else if (function.equals("child"))
+ result = expr.toXML();
+
+ return result;
+ }
+
+/*
+ public CoverageExpr( CoverageConstantExpr cce)
+ {
+ expr = cce;
+ function = "coverageConstantExpr";
+ }
+
+ public CoverageExpr( CoverageConstructorExpr ce ){
+ expr = ce;
+ function = "coverageConstructorExpr";
+ }
+
+ public CoverageExpr( SetMetaDataExpr smde ){
+ expr = smde;
+ function = "setMetaDataExpr";
+ }
+
+ public CoverageExpr( RangeConstructorExpr rce)
+ {
+ expr = rce;
+ function = "rangeConstructorExpr";
+ }
+
+ public CoverageExpr( CoverageExpr ce ){
+ expr = ce;
+ function = "coverageExpr";
+ }
+
+ public CoverageExpr( CrsTransformExpr cte ){
+ expr = cte;
+ function = "crsTransformExpr";
+ }
+
+ public CoverageExpr( ScaleExpr se ){
+ expr = se;
+ function = "scaleExpr";
+ }
+
+ public CoverageExpr( ScalarExpr se ){
+ expr = se;
+ function = "scalarExpr";
+ }
+
+ public CoverageExpr( SubsetExpr se ){
+ expr = se;
+ function = "subsetExpr";
+ }
+
+*/
+}
diff --git a/src/grammar/CoverageList.java b/src/grammar/CoverageList.java
new file mode 100644
index 0000000..38f1bdb
--- /dev/null
+++ b/src/grammar/CoverageList.java
@@ -0,0 +1,37 @@
+package grammar;
+
+/**
+ * CoverageList class represents a CoverageList.
+ * Creation date: (3/3/2003 2:52:55 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara, Andrei Aiordachioaie
+ */
+
+public class CoverageList implements IParseTreeNode
+{
+ private String coverageName;
+ private CoverageList next;
+
+ public CoverageList(String c)
+ {
+ coverageName = c;
+ next = null;
+ }
+
+ public CoverageList(String c, CoverageList l)
+ {
+ coverageName = c;
+ next = l;
+ }
+
+ public String toXML()
+ {
+ String result = "<coverageName>" + coverageName + "</coverageName>";
+
+ if (next != null)
+ {
+ result += next.toXML();
+ }
+
+ return result;
+ }
+} \ No newline at end of file
diff --git a/src/grammar/CrsList.java b/src/grammar/CrsList.java
new file mode 100644
index 0000000..0d148fa
--- /dev/null
+++ b/src/grammar/CrsList.java
@@ -0,0 +1,41 @@
+package grammar;
+
+import java.util.*;
+
+/** CrsList
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class CrsList implements IParseTreeNode
+{
+ LinkedList<String> list;
+
+ public CrsList(String crs)
+ {
+ list = new LinkedList<String>();
+ list.add(crs);
+ }
+
+ public CrsList()
+ {
+ list = new LinkedList<String>();
+ }
+
+ public void add(String crs)
+ {
+ list.add(crs);
+ }
+
+ public String toXML()
+ {
+ String result = "";
+ Iterator<String> it = list.iterator();
+ while (it.hasNext())
+ {
+ result += "<crs>" + it.next() + "</crs>";
+ }
+
+ return result;
+ }
+
+}
diff --git a/src/grammar/CrsTransformExpr.java b/src/grammar/CrsTransformExpr.java
new file mode 100644
index 0000000..f31bc63
--- /dev/null
+++ b/src/grammar/CrsTransformExpr.java
@@ -0,0 +1,30 @@
+package grammar;
+
+/** CrsTransformExpr
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class CrsTransformExpr implements IParseTreeNode
+{
+ IParseTreeNode e1, e2, e3;
+
+ public CrsTransformExpr(CoverageExpr expr, DimensionIntervalList list1, FieldInterpolationList list2)
+ {
+ e1 = expr;
+ e2 = list1;
+ e3 = list2;
+ }
+
+ public String toXML()
+ {
+ String result = "";
+
+ result += e1.toXML();
+ result += e2.toXML();
+ result += e3.toXML();
+
+ result = "<crsTransform>" + result + "</crsTransform>";
+ return result;
+ }
+
+}
diff --git a/src/grammar/DimensionIntervalElement.java b/src/grammar/DimensionIntervalElement.java
new file mode 100644
index 0000000..2f36afe
--- /dev/null
+++ b/src/grammar/DimensionIntervalElement.java
@@ -0,0 +1,40 @@
+package grammar;
+
+/** DimensionIntervalElement
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class DimensionIntervalElement implements IParseTreeNode
+{
+ String axis;
+ String crs;
+ DimensionIntervalExpr expr;
+
+ public DimensionIntervalElement(String a)
+ {
+ axis = a;
+ }
+
+ public void setCrs(String c)
+ {
+ crs = c;
+ }
+
+ public void setIntervalExpr(DimensionIntervalExpr e)
+ {
+ expr = e;
+ }
+
+ public String toXML()
+ {
+ String result = "";
+
+ result += "<axis>" + axis + "</axis>";
+ if (crs != null)
+ result += "<crs>" + crs + "</crs>";
+ result += expr.toXML();
+
+ return result;
+ }
+
+}
diff --git a/src/grammar/DimensionIntervalExpr.java b/src/grammar/DimensionIntervalExpr.java
new file mode 100644
index 0000000..a310ae4
--- /dev/null
+++ b/src/grammar/DimensionIntervalExpr.java
@@ -0,0 +1,44 @@
+package grammar;
+
+/** DimensionIntervalExpr
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class DimensionIntervalExpr implements IParseTreeNode
+{
+
+ IParseTreeNode e1, e2;
+ String fun;
+ String str;
+
+ public DimensionIntervalExpr(ScalarExpr exp1, ScalarExpr exp2)
+ {
+ fun = "scalars";
+ e1 = exp1;
+ e2 = exp2;
+ }
+
+ public DimensionIntervalExpr(String cov, String axis, String crs)
+ {
+ fun = "domain metadata";
+ str = "<coverage>" + cov + "</coverage>";
+ str += "<axis>" + axis + "</axis>";
+ str += "<crs>" + crs + "</crs>";
+ }
+
+ public String toXML()
+ {
+ String result = "";
+
+ if (fun.equals("scalars"))
+ {
+ result += "<lowerBound>" + e1.toXML() + "</lowerBound>";
+ result += "<uppedBound>" + e2.toXML() + "</upperBound>";
+ }
+ else if (fun.equals("domain metadata"))
+ result = str;
+
+ return result;
+ }
+
+}
diff --git a/src/grammar/DimensionIntervalList.java b/src/grammar/DimensionIntervalList.java
new file mode 100644
index 0000000..6a60373
--- /dev/null
+++ b/src/grammar/DimensionIntervalList.java
@@ -0,0 +1,37 @@
+package grammar;
+
+import java.util.*;
+
+/** DimensionIntervalList
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class DimensionIntervalList implements IParseTreeNode
+{
+
+ LinkedList<DimensionIntervalElement> list;
+
+ public DimensionIntervalList(DimensionIntervalElement e)
+ {
+ list = new LinkedList();
+ list.add(e);
+ }
+
+ public void add(DimensionIntervalElement meth)
+ {
+ list.add(meth);
+ }
+
+ public String toXML()
+ {
+ String result = "";
+ Iterator<DimensionIntervalElement> it = list.iterator();
+ while (it.hasNext())
+ {
+ result += it.next().toXML();
+ }
+
+ return result;
+ }
+
+}
diff --git a/src/grammar/DimensionPointElement.java b/src/grammar/DimensionPointElement.java
new file mode 100644
index 0000000..d37f22b
--- /dev/null
+++ b/src/grammar/DimensionPointElement.java
@@ -0,0 +1,39 @@
+package grammar;
+
+/** DimensionPointElement
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class DimensionPointElement implements IParseTreeNode
+{
+ String axis;
+ String crs;
+ ScalarExpr point;
+
+ public DimensionPointElement(String a, ScalarExpr dp)
+ {
+ axis = a;
+ point = dp;
+ }
+
+ public DimensionPointElement(String a, String c, ScalarExpr dp)
+ {
+ axis = a;
+ crs = c;
+ point = dp;
+ }
+
+
+ public String toXML()
+ {
+ String result = "";
+
+ result += "<axis>" + axis + "</axis>";
+ if (crs != null)
+ result += "<crs>" + crs + "</crs>";
+ result += "<slicingPoint>" + point.toXML() + "</slicingPoint>";
+
+ return result;
+ }
+
+}
diff --git a/src/grammar/DimensionPointList.java b/src/grammar/DimensionPointList.java
new file mode 100644
index 0000000..63a4e1b
--- /dev/null
+++ b/src/grammar/DimensionPointList.java
@@ -0,0 +1,37 @@
+package grammar;
+
+import java.util.*;
+
+/** DimensionPointList
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class DimensionPointList implements IParseTreeNode
+{
+
+ LinkedList<DimensionPointElement> list;
+
+ public DimensionPointList(DimensionPointElement e)
+ {
+ list = new LinkedList();
+ list.add(e);
+ }
+
+ public void add(DimensionPointElement meth)
+ {
+ list.add(meth);
+ }
+
+ public String toXML()
+ {
+ String result = "";
+ Iterator<DimensionPointElement> it = list.iterator();
+ while (it.hasNext())
+ {
+ result += it.next().toXML();
+ }
+
+ return result;
+ }
+
+}
diff --git a/src/grammar/DomainExpr.java b/src/grammar/DomainExpr.java
new file mode 100644
index 0000000..63744e4
--- /dev/null
+++ b/src/grammar/DomainExpr.java
@@ -0,0 +1,27 @@
+package grammar;
+
+/** DomainExpr
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class DomainExpr implements IParseTreeNode
+{
+ String var, axis, crs;
+
+ public DomainExpr(String v, String a, String c)
+ {
+ var = v;
+ axis = a;
+ crs = c;
+ }
+
+ public String toXML()
+ {
+ String result = "";
+ result += "<coverage>" + var + "</coverage>";
+ result += "<axis>" + axis + "</axis>";
+ result += "<crs>" + crs + "</crs>";
+ return result;
+ }
+
+}
diff --git a/src/grammar/EncodedCoverageExpr.java b/src/grammar/EncodedCoverageExpr.java
new file mode 100644
index 0000000..77cc1a1
--- /dev/null
+++ b/src/grammar/EncodedCoverageExpr.java
@@ -0,0 +1,49 @@
+package grammar;
+/**
+ * EncodedCoverageExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara, Andrei Aiordachioaie
+ */
+public class EncodedCoverageExpr implements IParseTreeNode
+{
+ CoverageExpr expr;
+ String format;
+ String extraParams;
+ boolean store;
+
+ public EncodedCoverageExpr( CoverageExpr ce , String fn )
+ {
+ expr = ce;
+ format = fn;
+ extraParams = null;
+ store = false;
+ }
+
+ public void setParams(String params)
+ {
+ extraParams = params;
+ }
+
+ public void setStoreFlag()
+ {
+ store = true;
+ }
+
+ public String toXML()
+ {
+ String result = "";
+ if (store)
+ result = "<encode store=\"true\">";
+ else
+ result = "<encode store=\"false\">";
+
+ result += expr.toXML();
+ result += "<format>" + format + "</format>" ;
+ if (extraParams != null )
+ result += "<extraParams>" + extraParams + "</extraParams>";
+
+ result+= "</encode>" ;
+
+ return result;
+ }
+}
diff --git a/src/grammar/ExponentialExpr.java b/src/grammar/ExponentialExpr.java
new file mode 100644
index 0000000..eada09f
--- /dev/null
+++ b/src/grammar/ExponentialExpr.java
@@ -0,0 +1,24 @@
+package grammar;
+/**
+ * ExponentialExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara, Andrei Aiordachioaie
+ */
+public class ExponentialExpr implements IParseTreeNode
+{
+ String expOperator;
+ CoverageExpr coverageExpr;
+
+ public ExponentialExpr(String op, CoverageExpr ce)
+ {
+ expOperator = op;
+ coverageExpr = ce;
+ }
+ public String toXML(){
+ String result= "" ;
+ result += "<" + expOperator + ">";
+ result += coverageExpr.toXML() ;
+ result += "</" + expOperator + ">";
+ return result;
+ }
+}
diff --git a/src/grammar/ExtendExpr.java b/src/grammar/ExtendExpr.java
new file mode 100644
index 0000000..31e8f1b
--- /dev/null
+++ b/src/grammar/ExtendExpr.java
@@ -0,0 +1,20 @@
+package grammar;
+/**
+ * ExtendExpr
+ * Creation date: (8/2/2008)
+ * @author: Sorin Stancu-Mara, Andrei Aiordachioaie
+ */
+public class ExtendExpr implements IParseTreeNode
+{
+
+ CoverageExpr coverageExpr;
+ DimensionIntervalList intervalList;
+ public ExtendExpr( CoverageExpr ce, DimensionIntervalList apl){
+ coverageExpr = ce;
+ intervalList = apl;
+ }
+
+ public String toXML(){
+ return "<extend>" + intervalList.toXML() + coverageExpr.toXML() + "</extend>";
+ }
+}
diff --git a/src/grammar/FieldInterpolationElement.java b/src/grammar/FieldInterpolationElement.java
new file mode 100644
index 0000000..26c65c5
--- /dev/null
+++ b/src/grammar/FieldInterpolationElement.java
@@ -0,0 +1,26 @@
+package grammar;
+
+/** FieldInterpolationElement
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class FieldInterpolationElement implements IParseTreeNode
+{
+
+ String name;
+ IParseTreeNode node;
+
+ public FieldInterpolationElement(String name, InterpolationMethod method)
+ {
+ this.name = name;
+ node = method;
+ }
+
+ public String toXML()
+ {
+ String result = "<name>" + name + "</name>" + node.toXML();
+
+ return result;
+ }
+
+}
diff --git a/src/grammar/FieldInterpolationList.java b/src/grammar/FieldInterpolationList.java
new file mode 100644
index 0000000..99dcb00
--- /dev/null
+++ b/src/grammar/FieldInterpolationList.java
@@ -0,0 +1,37 @@
+package grammar;
+
+import java.util.*;
+
+/** FieldInterpolationList
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class FieldInterpolationList implements IParseTreeNode
+{
+
+ LinkedList<FieldInterpolationElement> list;
+
+ public FieldInterpolationList(FieldInterpolationElement e)
+ {
+ list = new LinkedList();
+ list.add(e);
+ }
+
+ public void add(FieldInterpolationElement meth)
+ {
+ list.add(meth);
+ }
+
+ public String toXML()
+ {
+ String result = "";
+ Iterator<FieldInterpolationElement> it = list.iterator();
+ while (it.hasNext())
+ {
+ result += it.next().toXML();
+ }
+
+ return result;
+ }
+
+}
diff --git a/src/grammar/ForClause.java b/src/grammar/ForClause.java
new file mode 100644
index 0000000..5a4900e
--- /dev/null
+++ b/src/grammar/ForClause.java
@@ -0,0 +1,21 @@
+package grammar;
+
+/**
+ * ForClause
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara, Andrei Aiordachioaie
+ */
+
+public class ForClause implements IParseTreeNode {
+ ForClauseElements forClauseElements;
+
+ public ForClause( ForClauseElements fce )
+ {
+ forClauseElements = fce;
+ }
+
+ public String toXML()
+ {
+ return forClauseElements.toXML();
+ }
+}
diff --git a/src/grammar/ForClauseElements.java b/src/grammar/ForClauseElements.java
new file mode 100644
index 0000000..f8eed6d
--- /dev/null
+++ b/src/grammar/ForClauseElements.java
@@ -0,0 +1,44 @@
+package grammar;
+
+/**
+ * ForClauseElements
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara, Andrei Aiordachioaie
+ */
+
+public class ForClauseElements implements IParseTreeNode
+{
+ CoverageList coverageList;
+ ForClauseElements next;
+ String var;
+
+ public ForClauseElements(String v, CoverageList c)
+ {
+ var = v;
+ coverageList = c;
+ }
+
+ public ForClauseElements(String v, CoverageList c, ForClauseElements next)
+ {
+ var = v;
+ coverageList = c;
+ this.next = next;
+ }
+
+ public String toXML()
+ {
+ String result = "";
+
+ result += "<coverageIterator>";
+ result += "<iteratorVar>" + var + "</iteratorVar>";
+ result += coverageList.toXML();
+ result += "</coverageIterator>";
+
+ if (next != null)
+ {
+ result += next.toXML();
+ }
+
+ return result;
+ }
+}
diff --git a/src/grammar/GeneralCondenseExpr.java b/src/grammar/GeneralCondenseExpr.java
new file mode 100644
index 0000000..5a8b791
--- /dev/null
+++ b/src/grammar/GeneralCondenseExpr.java
@@ -0,0 +1,46 @@
+package grammar;
+
+/** GeneralCondenseExpr
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class GeneralCondenseExpr implements IParseTreeNode
+{
+ CondenseOperationType op;
+ AxisIteratorList alist;
+ BooleanScalarExpr where;
+ ScalarExpr using;
+
+ public GeneralCondenseExpr(CondenseOperationType op, AxisIteratorList al)
+ {
+ this.op = op;
+ alist = al;
+ alist.setTag("iterator");
+ where = null;
+ using = null;
+ }
+
+ public void setWhere(BooleanScalarExpr bse)
+ {
+ where = bse;
+ }
+
+ public void setUsing(ScalarExpr se)
+ {
+ using = se;
+ }
+
+ public String toXML()
+ {
+ String result = "";
+
+ result += op.toXML();
+ result += alist.toXML();
+ if (where != null)
+ result += "<where>" + where.toXML() + "</where>";
+ result += using.toXML();
+
+ return result;
+ }
+
+}
diff --git a/src/grammar/IParseTreeNode.java b/src/grammar/IParseTreeNode.java
new file mode 100644
index 0000000..639693c
--- /dev/null
+++ b/src/grammar/IParseTreeNode.java
@@ -0,0 +1,10 @@
+package grammar;
+
+/* Author: Sorin Stancu-Mara
+Date: 7 FEB 2007
+Interface that all nodes implement to simplify some of the complex nodes
+*/
+public interface IParseTreeNode
+{
+ public String toXML();
+} \ No newline at end of file
diff --git a/src/grammar/ImageCrsDomainMetadataExpr.java b/src/grammar/ImageCrsDomainMetadataExpr.java
new file mode 100644
index 0000000..4cb72d2
--- /dev/null
+++ b/src/grammar/ImageCrsDomainMetadataExpr.java
@@ -0,0 +1,25 @@
+package grammar;
+
+/** ImageCrsDomainMetadataExpr Group
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class ImageCrsDomainMetadataExpr implements IParseTreeNode
+{
+ CoverageExpr cov;
+ String axis;
+ NumericScalarExpr n1, n2;
+
+ public ImageCrsDomainMetadataExpr(String covName, String axis)
+ {
+ this.cov = new CoverageExpr(covName);
+ this.axis = axis;
+ }
+
+ public String toXML()
+ {
+ String result = cov.toXML() + "<axis>" + axis + "</axis>";
+ return result;
+ }
+
+}
diff --git a/src/grammar/IndexExpr.java b/src/grammar/IndexExpr.java
new file mode 100644
index 0000000..38ba6d4
--- /dev/null
+++ b/src/grammar/IndexExpr.java
@@ -0,0 +1,50 @@
+package grammar;
+
+/** IndexExpr
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class IndexExpr implements IParseTreeNode
+{
+
+ String op;
+ IParseTreeNode e1, e2;
+ String constant;
+ String function;
+
+ public IndexExpr(String op, IndexExpr e1, IndexExpr e2)
+ {
+ this.op = op;
+ this.e1 = e1;
+ this.e2 = e2;
+ function = "op2";
+ }
+
+ public IndexExpr(String constant)
+ {
+ function = "constant";
+ this.constant = constant;
+ }
+
+ public IndexExpr(String op, NumericScalarExpr e1)
+ {
+ this.op = op;
+ this.e1 = e1;
+ function = "op1";
+ }
+
+ public String toXML()
+ {
+ String result = "";
+ String tag1 = "<" + op + ">", tag2 = "</" + op + ">";
+ if (function.equals("constant"))
+ result = "<numericConstant>" + constant + "</numericConstant>";
+ else if (function.equals("op1"))
+ result = tag1 + e1.toXML() + tag2;
+ else if (function.equals("op2"))
+ result = tag1 + e1.toXML() + e2.toXML() + tag2;
+
+ return result;
+ }
+
+}
diff --git a/src/grammar/InterpolationMethod.java b/src/grammar/InterpolationMethod.java
new file mode 100644
index 0000000..72619c5
--- /dev/null
+++ b/src/grammar/InterpolationMethod.java
@@ -0,0 +1,26 @@
+package grammar;
+
+/** InterpolationMethod
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class InterpolationMethod implements IParseTreeNode
+{
+
+ String interp, resistance;
+
+ public InterpolationMethod(String interp, String resist)
+ {
+ this.interp = interp;
+ this.resistance = resist;
+ }
+
+ public String toXML()
+ {
+ String result = "";
+ result += "<interpolationMethod>" + interp + "</interpolationMethod>";
+ result += "<nullResistance>" + resistance + "</nullResistance>";
+ return result;
+ }
+
+}
diff --git a/src/grammar/InterpolationMethodList.java b/src/grammar/InterpolationMethodList.java
new file mode 100644
index 0000000..4edd4e6
--- /dev/null
+++ b/src/grammar/InterpolationMethodList.java
@@ -0,0 +1,36 @@
+package grammar;
+
+import java.util.*;
+
+/** InterpolationMethodList
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class InterpolationMethodList implements IParseTreeNode
+{
+
+ LinkedList<InterpolationMethod> list;
+
+ public InterpolationMethodList()
+ {
+ list = new LinkedList();
+ }
+
+ public void add(InterpolationMethod meth)
+ {
+ list.add(meth);
+ }
+
+ public String toXML()
+ {
+ String result = "";
+ Iterator<InterpolationMethod> it = list.iterator();
+ while (it.hasNext())
+ {
+ result += it.next().toXML();
+ }
+
+ return result;
+ }
+
+}
diff --git a/src/grammar/IntervalExpr.java b/src/grammar/IntervalExpr.java
new file mode 100644
index 0000000..8bca05f
--- /dev/null
+++ b/src/grammar/IntervalExpr.java
@@ -0,0 +1,35 @@
+package grammar;
+
+/** IntervalExpr
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class IntervalExpr implements IParseTreeNode
+{
+ String function;
+ IParseTreeNode e1, e2;
+
+ public IntervalExpr(IndexExpr n1, IndexExpr n2)
+ {
+ this.e1 = n1;
+ this.e2 = n2;
+ function = "two indexes";
+ }
+
+ public IntervalExpr(String coverage, String axis)
+ {
+ function = "crs metadata";
+ this.e1 = new ImageCrsDomainMetadataExpr(coverage, axis);
+ }
+
+ public String toXML()
+ {
+ String result = "";
+ if (function.equals("two indexes"))
+ result = e1.toXML() + e2.toXML();
+ else if (function.equals("crs metadata"))
+ result = e1.toXML();
+ return result;
+ }
+
+}
diff --git a/src/grammar/Main.java b/src/grammar/Main.java
new file mode 100644
index 0000000..12d852e
--- /dev/null
+++ b/src/grammar/Main.java
@@ -0,0 +1,21 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package grammar;
+
+/**
+ *
+ * @author andrei
+ */
+public class Main {
+
+ /**
+ * @param args the command line arguments
+ */
+ public static void main(String[] args) {
+ // TODO code application logic here
+ }
+
+}
diff --git a/src/grammar/MetaDataExpr.java b/src/grammar/MetaDataExpr.java
new file mode 100644
index 0000000..86795af
--- /dev/null
+++ b/src/grammar/MetaDataExpr.java
@@ -0,0 +1,81 @@
+package grammar;
+
+/**
+ * MetaDataExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara, Andrei Aiordachioaie
+ */
+public class MetaDataExpr implements IParseTreeNode {
+
+ String function;
+ CoverageExpr expr;
+ IParseTreeNode param;
+ String field;
+
+ // Identifier, ImageCRS, ImageCRSDomain, CrsSet, NullSet
+ public MetaDataExpr(String op, CoverageExpr expr)
+ {
+ function = op;
+ this.expr = expr;
+ }
+
+ // ImageCRSDomain, interpolationDefault, interpolationSet
+ public MetaDataExpr(String op, CoverageExpr expr, String str)
+ {
+ function = op;
+ this.expr = expr;
+ this.field = str;
+ }
+
+ public MetaDataExpr(DomainExpr dom)
+ {
+ function = "domain";
+ param = dom;
+ }
+
+ public String toXML()
+ {
+ String result = "";
+
+ if (function.equalsIgnoreCase("imageCrsDomain"))
+ {
+ result += "<imageCrsDomain>";
+ result += expr.toXML();
+ if (field != null)
+ result += "<axis>" + field + "</axis>";
+ result += "</imageCrsDomain>";
+ }
+ else if (function.equalsIgnoreCase("domain"))
+ {
+ result = "<DomainMetadata>" + param.toXML() + "</DomainMetadata>";
+ }
+ else if (function.equalsIgnoreCase("interpolationDefault"))
+ {
+ result += "<interpolationDefault>";
+ result += expr.toXML();
+ result += "<name>" + param + "</param>";
+ result += "</interpolationDefault>";
+ }
+ else if (function.equalsIgnoreCase("interpolationSet"))
+ {
+ result += "<interpolationSet>";
+ result += expr.toXML();
+ result += "<name>" + param + "</param>";
+ result += "</interpolationSet>";
+ }
+ else if (function.equalsIgnoreCase("identifier") || function.equalsIgnoreCase("imageCRS")
+ || function.equalsIgnoreCase("crsSet") || function.equalsIgnoreCase("nullSet"))
+ {
+ result += "<" + function + ">";
+ result += expr.toXML();
+ result += "</" + function + ">";
+ }
+ else
+ {
+ System.err.println("Unknown MetadataExpr operation: " + function);
+ }
+
+ return result;
+ }
+
+}
diff --git a/src/grammar/NOTES b/src/grammar/NOTES
new file mode 100644
index 0000000..6f3a9c1
--- /dev/null
+++ b/src/grammar/NOTES
@@ -0,0 +1,17 @@
+- SetMetaDataExpr -> SetIdentifier is inconsistent:
+ * DONE - update the schema
+ * TODO - update the abstract syntax in the specification document (08-068r2)
+
+- UnaryOperationCoverageExprType ?should? have operations "re", "im" ?
+ * DONE - Add the complex number operations to the XML schema
+ ** re and im ARE in the wcps.g file
+ ** NOT present in the abstract syntax grammar
+
+- CondenseScalarExprType should contain the node "ReduceScalarExprType"
+ * DONE - update the XML schema
+ ** It is so in the abstract syntax grammar
+ ** NOT in the XML schema
+
+- Bad choice of node name (GeneralCondenseExpr -> iteratorVar -> iteratorVar)
+ * DONE - Rename the top level node into "iterator"
+ ** GeneralCondenseExpr -> iterator -> list of "iteratorVar" nodes is now ok. \ No newline at end of file
diff --git a/src/grammar/NumericScalarExpr.java b/src/grammar/NumericScalarExpr.java
new file mode 100644
index 0000000..2527f21
--- /dev/null
+++ b/src/grammar/NumericScalarExpr.java
@@ -0,0 +1,96 @@
+package grammar;
+
+/**
+ * NumericScalarExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara, Andrei Aiordachioaie
+ */
+public class NumericScalarExpr implements IParseTreeNode
+{
+ String constValue;
+ String function;
+ NumericScalarExpr leftNumericScalarExpr, rightNumericScalarExpr;
+ CondenseExpr condense;
+
+ public NumericScalarExpr(String val)
+ {
+ if (val.contains("+i"))
+ {
+ ComplexConst cc = new ComplexConst(val);
+
+ constValue = cc.toXML();
+ function = "complexConstant";
+ }
+ else
+ {
+ constValue = val;
+ function = "numericConstant";
+ }
+ }
+
+ public NumericScalarExpr(String op, NumericScalarExpr expr)
+ {
+ leftNumericScalarExpr = expr;
+
+ if (op.equals("-"))
+ function = "numericUnaryMinus";
+ else
+ System.err.println("Unary Operator " + op + " is not recognized!");
+ }
+
+ public NumericScalarExpr(String op, NumericScalarExpr lbe, NumericScalarExpr rbe)
+ {
+ leftNumericScalarExpr = lbe;
+ rightNumericScalarExpr = rbe;
+
+ if (op.equals("+"))
+ {
+ function = "numericAdd";
+ }
+ else if (op.equals("-"))
+ {
+ function = "numericMinus";
+ }
+ else if (op.equals("*"))
+ {
+ function = "numericMult";
+ }
+ else if (op.equals("/"))
+ {
+ function = "numericDiv";
+ }
+ else
+ {
+ System.err.println("Operator " + op + " is not recognized!");
+ }
+ }
+
+ public NumericScalarExpr(CondenseExpr c)
+ {
+ condense = c;
+ function = "condense";
+ }
+
+ public String toXML()
+ {
+ String result;
+
+ if (function.equals("complexConstant"))
+ return constValue;
+
+ result = "<" + function + ">";
+
+ if (function.equals("numericConstant"))
+ result += constValue;
+ else
+ {
+ result += leftNumericScalarExpr.toXML();
+ if (rightNumericScalarExpr != null)
+ result += rightNumericScalarExpr.toXML();
+ }
+
+ result += "</" + function + ">";
+
+ return result;
+ }
+}
diff --git a/src/grammar/ProcessingExpr.java b/src/grammar/ProcessingExpr.java
new file mode 100644
index 0000000..fd1e9d5
--- /dev/null
+++ b/src/grammar/ProcessingExpr.java
@@ -0,0 +1,22 @@
+package grammar;
+/**
+ * ProcessingExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara, Andrei Aiordachioaie
+ */
+
+public class ProcessingExpr implements IParseTreeNode
+{
+ IParseTreeNode expr;
+
+ public ProcessingExpr( IParseTreeNode e )
+ {
+ expr = e;
+ }
+
+ public String toXML()
+ {
+ return expr.toXML();
+ }
+
+}
diff --git a/src/grammar/RangeConstructorExpr.java b/src/grammar/RangeConstructorExpr.java
new file mode 100644
index 0000000..44303d5
--- /dev/null
+++ b/src/grammar/RangeConstructorExpr.java
@@ -0,0 +1,41 @@
+package grammar;
+
+import java.util.*;
+
+/** RangeConstructorExpr
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class RangeConstructorExpr implements IParseTreeNode
+{
+ LinkedList<RangeConstructorTerm> list;
+
+ public RangeConstructorExpr()
+ {
+ list = new LinkedList();
+ }
+
+ public RangeConstructorExpr(String field, CoverageExpr expr)
+ {
+ this();
+ add(field, expr);
+ }
+
+ public void add(String field, CoverageExpr expr)
+ {
+ list.add(new RangeConstructorTerm(field, expr));
+ }
+
+ public String toXML()
+ {
+ String result = "";
+ Iterator<RangeConstructorTerm> it = list.iterator();
+
+ while (it.hasNext())
+ result += it.next().toXML();
+
+ result = "<rangeConstructor>" + result + "</rangeConstructor>";
+ return result;
+ }
+
+}
diff --git a/src/grammar/RangeConstructorTerm.java b/src/grammar/RangeConstructorTerm.java
new file mode 100644
index 0000000..84a9491
--- /dev/null
+++ b/src/grammar/RangeConstructorTerm.java
@@ -0,0 +1,29 @@
+package grammar;
+
+/** RangeConstructorTerm, part of a RangeConstructorExpr
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class RangeConstructorTerm implements IParseTreeNode
+{
+
+ String field;
+ CoverageExpr expr;
+
+ public RangeConstructorTerm(String f, CoverageExpr c)
+ {
+ field = f;
+ expr = c;
+ }
+
+ public String toXML()
+ {
+ String result = "";
+ result += "<field>" + field + "</field>";
+ result += expr.toXML();
+
+ result = "<component>" + result + "</component>";
+ return result;
+ }
+
+}
diff --git a/src/grammar/RangeExpr.java b/src/grammar/RangeExpr.java
new file mode 100644
index 0000000..c3c6a46
--- /dev/null
+++ b/src/grammar/RangeExpr.java
@@ -0,0 +1,35 @@
+package grammar;
+
+/** RangeExpr
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class RangeExpr implements IParseTreeNode
+{
+ String xml;
+
+ public RangeExpr()
+ {
+ this.xml = "";
+ }
+
+ public RangeExpr(String field, ScalarExpr expr)
+ {
+ this();
+ add(field, expr);
+ }
+
+ public void add(String field, ScalarExpr expr)
+ {
+ String tmp = "";
+ tmp += "<field>" + field + "</field>";
+ tmp += expr.toXML();
+ xml += "<componen>" + tmp + "</component>";
+ }
+
+ public String toXML()
+ {
+ return xml;
+ }
+
+}
diff --git a/src/grammar/RangeExprList.java b/src/grammar/RangeExprList.java
new file mode 100644
index 0000000..d4e555a
--- /dev/null
+++ b/src/grammar/RangeExprList.java
@@ -0,0 +1,32 @@
+package grammar;
+
+import java.util.*;
+
+/** RangeExprList
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class RangeExprList implements IParseTreeNode
+{
+ LinkedList<RangeExpr> list;
+
+ public RangeExprList()
+ {
+ list = new LinkedList();
+ }
+
+ public void add(RangeExpr expr)
+ {
+ list.add(expr);
+ }
+
+ public String toXML()
+ {
+ String result = "";
+
+ Iterator<RangeExpr> it = list.iterator();
+ while (it.hasNext())
+ result += "<null>" + it.next().toXML() + "</xml>";
+ return result;
+ }
+} \ No newline at end of file
diff --git a/src/grammar/ReduceExpr.java b/src/grammar/ReduceExpr.java
new file mode 100644
index 0000000..1b5f8c1
--- /dev/null
+++ b/src/grammar/ReduceExpr.java
@@ -0,0 +1,25 @@
+package grammar;
+
+/** ReduceExpr
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class ReduceExpr implements IParseTreeNode
+{
+ String op;
+ CoverageExpr expr;
+
+ public ReduceExpr(String op, CoverageExpr e)
+ {
+ this.op = op;
+ this.expr = e;
+ }
+
+ public String toXML()
+ {
+ String result = "<" + op + ">" + expr.toXML() + "</" + op + ">";
+
+ return result;
+ }
+
+}
diff --git a/src/grammar/ReturnClause.java b/src/grammar/ReturnClause.java
new file mode 100644
index 0000000..50d61ce
--- /dev/null
+++ b/src/grammar/ReturnClause.java
@@ -0,0 +1,21 @@
+package grammar;
+
+/** ReturnClause
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class ReturnClause implements IParseTreeNode
+{
+ IParseTreeNode expr;
+
+ public ReturnClause(IParseTreeNode e)
+ {
+ expr = e;
+ }
+
+ public String toXML()
+ {
+ return expr.toXML();
+ }
+
+}
diff --git a/src/grammar/ScalarExpr.java b/src/grammar/ScalarExpr.java
new file mode 100644
index 0000000..e6ca26c
--- /dev/null
+++ b/src/grammar/ScalarExpr.java
@@ -0,0 +1,20 @@
+package grammar;
+
+/**
+ * ScalarExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara, Andrei Aiordachioaie
+ */
+
+public class ScalarExpr implements IParseTreeNode {
+ IParseTreeNode expr;
+
+ public ScalarExpr(IParseTreeNode e) {
+ expr = e;
+ }
+
+ public String toXML(){
+ return expr.toXML();
+ }
+
+}
diff --git a/src/grammar/ScaleExpr.java b/src/grammar/ScaleExpr.java
new file mode 100644
index 0000000..9de84e2
--- /dev/null
+++ b/src/grammar/ScaleExpr.java
@@ -0,0 +1,27 @@
+package grammar;
+/**
+ * ScaleExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara, Andrei Aiordachioaie
+ */
+public class ScaleExpr implements IParseTreeNode {
+
+ CoverageExpr coverageExpr;
+ DimensionIntervalList intervalList;
+ FieldInterpolationList interpMethods;
+
+ public ScaleExpr( CoverageExpr ce, DimensionIntervalList ail, FieldInterpolationList iml){
+ coverageExpr = ce;
+ intervalList = ail;
+ interpMethods = iml;
+ }
+
+ public String toXML(){
+ String result = "";
+
+ result += coverageExpr.toXML() + intervalList.toXML() + interpMethods.toXML();
+ result = "<scale>" + result + "</scale>";
+
+ return result;
+ }
+}
diff --git a/src/grammar/SelectExpr.java b/src/grammar/SelectExpr.java
new file mode 100644
index 0000000..ca7636b
--- /dev/null
+++ b/src/grammar/SelectExpr.java
@@ -0,0 +1,25 @@
+package grammar;
+/**
+ * SelectExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara, Andrei Aiordachioaie
+ */
+public class SelectExpr implements IParseTreeNode
+{
+ CoverageExpr coverageExpr;
+ String field;
+
+ public SelectExpr( CoverageExpr ce, String se)
+ {
+ coverageExpr = ce;
+ field = se;
+ }
+
+ public String toXML(){
+ String result="<fieldSelect>" ;
+ result += coverageExpr.toXML();
+ result += "<field>" + field + "</field>";
+ result += "</fieldSelect>";
+ return result;
+ }
+}
diff --git a/src/grammar/SetMetaDataExpr.java b/src/grammar/SetMetaDataExpr.java
new file mode 100644
index 0000000..1902e84
--- /dev/null
+++ b/src/grammar/SetMetaDataExpr.java
@@ -0,0 +1,109 @@
+package grammar;
+
+/**
+ * SetMetaDataExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara, Andrei Aiordachioaie
+ */
+public class SetMetaDataExpr implements IParseTreeNode {
+
+ String function;
+ CoverageExpr expr;
+ IParseTreeNode param;
+ String field;
+
+ // Set Identifier
+ public SetMetaDataExpr(String op, CoverageExpr expr, String constant)
+ {
+ function = op;
+ this.expr = expr;
+ this.field = constant;
+ }
+
+ // Set Crs Set
+ public SetMetaDataExpr(String op, CoverageExpr expr, CrsList clist)
+ {
+ function = op;
+ this.expr = expr;
+ this.param = clist;
+ }
+
+ // Set Null Set
+ public SetMetaDataExpr(String op, CoverageExpr expr, RangeExprList param)
+ {
+ function = op;
+ this.expr = expr;
+ this.param = param;
+ }
+
+ // Set Interpolation Default
+ public SetMetaDataExpr(String op, CoverageExpr expr, InterpolationMethod param, String field)
+ {
+ function = op;
+ this.expr = expr;
+ this.param = param;
+ this.field = field;
+ }
+
+ // Set Interpolation Set
+ public SetMetaDataExpr(String op, CoverageExpr expr, InterpolationMethodList param, String field)
+ {
+ function = op;
+ this.expr = expr;
+ this.param = param;
+ this.field = field;
+ }
+
+
+ public String toXML()
+ {
+ String result = "";
+
+ if (function.equalsIgnoreCase("setIdentifier"))
+ {
+ result += "<identifier>" + field + "</identifier>";
+ result += expr.toXML();
+
+ result = "<setIdentifier>" + result + "</setIdentifier>";
+ }
+ else if (function.equalsIgnoreCase("setCrsSet"))
+ {
+ result += expr.toXML();
+ if (param != null)
+ result += param.toXML();
+
+ result = "<setCrsSet>" + result + "</setCrsSet>";
+ }
+ else if (function.equalsIgnoreCase("setNullSet"))
+ {
+ result += expr.toXML();
+ if (param != null)
+ result += param.toXML();
+
+ result = "<setNullSet>" + result + "</setNullSet>";
+ }
+ else if (function.equalsIgnoreCase("setInterpolationDefault"))
+ {
+ result += expr.toXML();
+ result += "<field>" + field + "</field>";
+ result += param.toXML();
+
+ result = "<setInterpolationDefault>" + result + "</setInterpolationDefault>";
+ }
+ else if (function.equalsIgnoreCase("setInterpolationSet"))
+ {
+ result += expr.toXML();
+ result += "<field>" + field + "</field>";
+ result += param.toXML();
+
+ result = "<setInterpolationSet>" + result + "</setInterpolationSet>";
+ }
+ else
+ {
+ System.err.println("Unknown SetMetadataExpr operation: " + function);
+ }
+
+ return result;
+ }
+
+}
diff --git a/src/grammar/SliceExpr.java b/src/grammar/SliceExpr.java
new file mode 100644
index 0000000..a6c8747
--- /dev/null
+++ b/src/grammar/SliceExpr.java
@@ -0,0 +1,20 @@
+package grammar;
+/**
+ * SliceExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara, Andrei Aiordachioaie
+ */
+public class SliceExpr implements IParseTreeNode {
+
+ CoverageExpr expr;
+ DimensionPointList list;
+
+ public SliceExpr( CoverageExpr ce, DimensionPointList apl){
+ expr = ce;
+ list = apl;
+ }
+
+ public String toXML(){
+ return "<slice>" + expr.toXML() + list.toXML() + "</slice>";
+ }
+}
diff --git a/src/grammar/StoreExpr.java b/src/grammar/StoreExpr.java
new file mode 100644
index 0000000..34f8f8c
--- /dev/null
+++ b/src/grammar/StoreExpr.java
@@ -0,0 +1,22 @@
+package grammar;
+
+/*
+Author: Sorin Stancu-Mara, Andrei Aiordachioaie
+Date: 7 Feb 2007
+*/
+
+public class StoreExpr implements IParseTreeNode
+{
+ private EncodedCoverageExpr expr;
+
+ public StoreExpr(EncodedCoverageExpr e)
+ {
+ expr = e;
+ expr.setStoreFlag();
+ }
+
+ public String toXML()
+ {
+ return expr.toXML();
+ }
+}
diff --git a/src/grammar/StringScalarExpr.java b/src/grammar/StringScalarExpr.java
new file mode 100644
index 0000000..d16ea60
--- /dev/null
+++ b/src/grammar/StringScalarExpr.java
@@ -0,0 +1,39 @@
+package grammar;
+
+/**
+ * @author: Andrei Aiordachioaie
+ */
+
+public class StringScalarExpr implements IParseTreeNode
+{
+ String val;
+ String function;
+ CoverageExpr cov;
+ String op;
+
+ public StringScalarExpr(String val)
+ {
+ this.val = val;
+ this.function = "stringConstant";
+ }
+
+ public StringScalarExpr(String op, CoverageExpr cov)
+ {
+ this.cov = cov;
+ function = "stringIdentifier";
+ this.op = op;
+ }
+
+ public String toXML()
+ {
+ String result = "<" + function + ">";
+
+ if (function.equals("stringConstant"))
+ result += val;
+ else if (function.equals("stringIdentifier"))
+ result += cov.toXML();
+ result += "</" + function + ">";
+
+ return result;
+ }
+}
diff --git a/src/grammar/SubsetExpr.java b/src/grammar/SubsetExpr.java
new file mode 100644
index 0000000..98280e0
--- /dev/null
+++ b/src/grammar/SubsetExpr.java
@@ -0,0 +1,21 @@
+package grammar;
+/**
+ * SubsetExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara, Andrei Aiordachioaie
+ */
+public class SubsetExpr implements IParseTreeNode {
+
+ IParseTreeNode expr;
+
+ public SubsetExpr( IParseTreeNode e ){
+ expr = e;
+ }
+
+ public String toXML(){
+ return expr.toXML();
+ }
+
+
+
+}
diff --git a/src/grammar/TrigonometricExpr.java b/src/grammar/TrigonometricExpr.java
new file mode 100644
index 0000000..a8c0271
--- /dev/null
+++ b/src/grammar/TrigonometricExpr.java
@@ -0,0 +1,23 @@
+package grammar;
+/**
+ * TrigonometricExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+public class TrigonometricExpr implements IParseTreeNode {
+ String trigOperator;
+ CoverageExpr coverageExpr;
+
+ public TrigonometricExpr(String op, CoverageExpr ce){
+ trigOperator = op;
+ coverageExpr = ce;
+ }
+
+ public String toXML(){
+ String result= "" ;
+ result += "<" + trigOperator + ">";
+ result += coverageExpr.toXML() ;
+ result += "</" + trigOperator + ">";
+ return result;
+ }
+}
diff --git a/src/grammar/TrimExpr.java b/src/grammar/TrimExpr.java
new file mode 100644
index 0000000..272c0f7
--- /dev/null
+++ b/src/grammar/TrimExpr.java
@@ -0,0 +1,23 @@
+package grammar;
+/**
+ * TrimExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara, Andrei Aiordachioaie
+ */
+public class TrimExpr implements IParseTreeNode
+{
+
+ CoverageExpr expr;
+ DimensionIntervalList list;
+
+ public TrimExpr( CoverageExpr ce, DimensionIntervalList al )
+ {
+ expr = ce;
+ list = al;
+ }
+
+ public String toXML()
+ {
+ return "<trim>" + expr.toXML() + list.toXML() + "</trim>";
+ }
+}
diff --git a/src/grammar/VariableList.java b/src/grammar/VariableList.java
new file mode 100644
index 0000000..874b398
--- /dev/null
+++ b/src/grammar/VariableList.java
@@ -0,0 +1,38 @@
+package grammar;
+
+/* Author: Sorin Stancu-Mara, Andrei Aiordachioaie
+ * Date: 8 Feb 2008
+ */
+
+public class VariableList implements IParseTreeNode {
+ String axisType, iteratorName;
+ String lo,hi;
+ VariableList next;
+
+ public VariableList(String type, String name, String lo, String hi) {
+ axisType = type;
+ iteratorName = name;
+ this.lo = lo;
+ this.hi = hi;
+ next = null;
+ }
+
+ public VariableList(String type, String name, String lo, String hi, VariableList next) {
+ axisType = type;
+ iteratorName = name;
+ this.lo = lo;
+ this.hi = hi;
+ this.next = next;
+ }
+
+ public String toXML() {
+ String result = "<axisIterator><axisType>" + axisType + "</axisType>" +
+ "<iteratorVar>" + iteratorName + "</iteratorVar>" +
+ "<coord>" + lo + "</coord>" +
+ "<coord>" + hi + "</coord></axisIterator>";
+
+ if (next != null) result += next.toXML();
+ return result;
+ }
+
+}
diff --git a/src/grammar/WCPSRequest.java b/src/grammar/WCPSRequest.java
new file mode 100644
index 0000000..7838e1f
--- /dev/null
+++ b/src/grammar/WCPSRequest.java
@@ -0,0 +1,52 @@
+package grammar;
+
+/**
+ * WCPSRequest class represents a WCPSRequest.
+ * Creation date: (3/3/2003 2:52:55 AM)
+ * @author: *, Sorin Stancu-Mara, Andrei Aiordachioaie
+ */
+
+public class WCPSRequest implements IParseTreeNode
+{
+ private ForClause forClause;
+ private ReturnClause returnClause;
+ private WhereClause whereClause;
+
+ public WCPSRequest()
+ {
+ super();
+ }
+
+ public WCPSRequest(ForClauseElements f)
+ {
+ forClause = new ForClause(f);
+ whereClause = null;
+ returnClause = null;
+ }
+
+ public void setWhere(WhereClause w)
+ {
+ whereClause = w;
+ }
+
+ public void setReturn(ReturnClause r)
+ {
+ returnClause = r;
+ }
+
+ public String toXML()
+ {
+ String result = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
+ result += "<processCoverage xmlns=\"http://www.opengis.net/wcps/1.0\" service=\"WCPS\" version=\"1.0.2\">\n";
+
+ result += forClause.toXML();
+ if (whereClause != null)
+ result += whereClause.toXML();
+ if (returnClause != null)
+ result += returnClause.toXML();
+
+ result += "</processCoverage>";
+
+ return result;
+ }
+}
diff --git a/src/grammar/WhereClause.java b/src/grammar/WhereClause.java
new file mode 100644
index 0000000..d0d998a
--- /dev/null
+++ b/src/grammar/WhereClause.java
@@ -0,0 +1,20 @@
+package grammar;
+
+/* Author: Sorin Stancu-Mara, Andrei Aiordachioaie
+Date: 7 Feb 2007
+*/
+
+public class WhereClause implements IParseTreeNode
+{
+ private BooleanScalarExpr expr;
+
+ public WhereClause(BooleanScalarExpr e)
+ {
+ expr = e;
+ }
+
+ public String toXML()
+ {
+ return "<where>" + expr.toXML() + "</where>";
+ }
+} \ No newline at end of file
diff --git a/src/grammar/wcps.g b/src/grammar/wcps.g
new file mode 100644
index 0000000..1fd7b40
--- /dev/null
+++ b/src/grammar/wcps.g
@@ -0,0 +1,500 @@
+/*
+Author: *, Sorin Stancu-Mara, Andrei Aiordachioaie
+Date (last update): 12 Feb 2009
+History:
+07 02 2007 smsorin Updated to WCPS 1.0.0
+27 01 2009 smsorin Moved to ANTLR
+11 02 2009 andrei Updated to new grammar (spec 08-068r2)
+13 02 2009 andrei Fixed small bugs in grammar. Now it can fully compile.
+*/
+grammar wcps;
+options{
+backtrack=true;
+memoize=true;
+k=2;
+language=Java;
+output=AST;
+}
+
+/* Parser Rules */
+
+wcpsRequest returns[WCPSRequest value]
+ : e1=forClause { $value= new WCPSRequest($e1.value); }
+ (e2=whereClause { $value.setWhere($e2.value); } )?
+ e3=returnClause { $value.setReturn($e3.value); }
+ ;
+forClause returns[ForClauseElements value]
+ : FOR v=variableName IN LPAREN list=coverageList RPAREN
+ { $value = new ForClauseElements($v.value, $list.value); }
+ (COMMA v=variableName IN LPAREN list=coverageList RPAREN
+ { $value = new ForClauseElements($v.value, $list.value, $value); })*
+ ;
+whereClause returns[WhereClause value]
+ : WHERE e1=booleanScalarExpr { $value = new WhereClause($e1.value); }
+ ;
+returnClause returns[ReturnClause value]
+ : RETURN e1=processingExpr { $value = new ReturnClause($e1.value); }
+ ;
+coverageList returns[CoverageList value]
+ : cname=coverageName { $value = new CoverageList($cname.value); }
+ (COMMA next=coverageName { $value = new CoverageList($next.value, $value); })*
+ ;
+processingExpr returns[ProcessingExpr value]
+ : e1=encodedCoverageExpr { $value = new ProcessingExpr($e1.value); }
+ | e2=storeExpr { $value = new ProcessingExpr($e2.value); }
+ | e3=scalarExpr { $value = new ProcessingExpr($e3.value); }
+ ;
+encodedCoverageExpr returns[EncodedCoverageExpr value]
+ : ENCODE LPAREN cov=coverageExpr COMMA format=stringConstant { $value = new EncodedCoverageExpr($cov.value, $format.text); }
+ (COMMA params=stringConstant { $value.setParams($params.text); })? RPAREN
+ ;
+storeExpr returns[StoreExpr value]
+ : STORE LPAREN e1=encodedCoverageExpr RPAREN { $value = new StoreExpr($e1.value); }
+ ;
+scalarExpr returns[ScalarExpr value]
+ : e1=metaDataExpr { $value = new ScalarExpr($e1.value); }
+ | e2=condenseExpr { $value = new ScalarExpr($e2.value); }
+ | e3=booleanScalarExpr { $value = new ScalarExpr($e3.value); }
+ | e4=numericScalarExpr { $value = new ScalarExpr($e4.value); }
+ | e5=stringScalarExpr { $value = new ScalarExpr($e5.value); }
+ | LPAREN e6=scalarExpr RPAREN { $value = $e6.value; }
+ ;
+// NOTE: The following rules are equivalent to the grammar rules in document 08-068r2
+// They have been rewritten in order to prioritize the boolean operators
+booleanScalarExpr returns[BooleanScalarExpr value]
+ : e1=booleanScalarTerm { $value = $e1.value; }
+ (op=(OR^|XOR^) e2=booleanScalarTerm { $value = new BooleanScalarExpr($op.text, $value, $e2.value);})*
+ ;
+booleanScalarTerm returns[BooleanScalarExpr value]
+ : e1=booleanScalarFactor { $value = $e1.value; }
+ (op=AND e2=booleanScalarFactor { $value = new BooleanScalarExpr($op.text, $value, $e2.value); })*
+ ;
+booleanScalarFactor returns[BooleanScalarExpr value]
+ : n1=numericScalarExpr cop=compOp n2=numericScalarExpr { $value = new BooleanScalarExpr($cop.value, $n1.value, $n2.value); }
+ | s1=stringScalarExpr cop=compOp s2=stringScalarExpr { $value = new BooleanScalarExpr($cop.value, $s1.value, $s2.value); }
+ | op=NOT e1=booleanScalarExpr { $value = new BooleanScalarExpr($op.text, $e1.value); }
+ | LPAREN e1=booleanScalarExpr RPAREN { $value = $e1.value; }
+ | e=BOOLEANCONSTANT { $value = new BooleanScalarExpr($e.text); }
+ ;
+numericScalarExpr returns[NumericScalarExpr value]
+ : e1=numericScalarTerm {$value = $e1.value; }
+ (op=(PLUS^|MINUS^) e2=numericScalarTerm { $value = new NumericScalarExpr($op.text, $value, $e2.value); })*
+ ;
+numericScalarTerm returns[NumericScalarExpr value]
+ : e1=numericScalarFactor { $value = $e1.value; }
+ (op=(MULT^|DIVIDE^) e2=numericScalarFactor { $value = new NumericScalarExpr($op.text, $value, $e2.value); })*
+ ;
+numericScalarFactor returns[NumericScalarExpr value]
+ : LPAREN e1=numericScalarExpr RPAREN { $value = $e1.value; }
+ | op=MINUS^ e10=numericScalarFactor { $value = new NumericScalarExpr($op.text, $e10.value); }
+ | op=ROUND LPAREN e1=numericScalarExpr RPAREN { $value = new NumericScalarExpr($op.text, $e1.value); }
+ | e=INTEGERCONSTANT { $value = new NumericScalarExpr($e.text); }
+ | e=FLOATCONSTANT { $value = new NumericScalarExpr($e.text); }
+ | e2=complexConstant { $value = new NumericScalarExpr($e2.value); }
+ | e3=condenseExpr { $value = new NumericScalarExpr($e3.value); }
+ ;
+compOp returns[String value]
+ : EQUALS { $value = new String("equals"); }
+ | NOTEQUALS { $value = new String("notEqual"); }
+ | LT { $value = new String("lessThan"); }
+ | GT { $value = new String("greaterThan"); }
+ | LTE { $value = new String("lessOrEqual"); }
+ | GTE { $value = new String("greaterOrEqual"); }
+ ;
+stringScalarExpr returns[StringScalarExpr value]
+// The first rule should be "metaDataExpr", but currently only a variable "identifier" is allowed.
+ : op=IDENTIFIER LPAREN e1=coverageExpr RPAREN { $value = new StringScalarExpr($op.text, $e1.value); }
+ | e=STRING{ $value = new StringScalarExpr($e.text); }
+ ;
+metaDataExpr returns[MetaDataExpr value]
+ : op=IDENTIFIER LPAREN e1=coverageExpr RPAREN { $value = new MetaDataExpr($op.text, $e1.value); }
+ | op=IMAGECRS LPAREN e1=coverageExpr RPAREN { $value = new MetaDataExpr($op.text, $e1.value); }
+ | op=IMAGECRSDOMAIN LPAREN e1=coverageExpr (COMMA e2=axisName)? RPAREN { $value = new MetaDataExpr($op.text, $e1.value, $e2.value); }
+ | op=CRSSET LPAREN e1=coverageExpr RPAREN { $value = new MetaDataExpr($op.text, $e1.value); }
+ | de=domainExpr { $value = new MetaDataExpr($de.value); }
+ | op=NULLSET LPAREN e1=coverageExpr RPAREN { $value = new MetaDataExpr($op.text,$e1.value); }
+ | op=INTERPOLATIONDEFAULT LPAREN e1=coverageExpr COMMA f1=fieldName RPAREN { $value = new MetaDataExpr($op.text, $e1.value, $f1.value); }
+ | op=INTERPOLATIONSET LPAREN e1=coverageExpr COMMA f1=fieldName RPAREN { $value = new MetaDataExpr($op.text, $e1.value, $f1.value); }
+ ;
+domainExpr returns[DomainExpr value]
+ : DOMAIN LPAREN var=variableName COMMA axis=axisName COMMA crs=crsName RPAREN { $value = new DomainExpr($var.value, $axis.value, $crs.value); }
+ ;
+setMetaDataExpr returns[SetMetaDataExpr value]
+ : op=SETIDENTIFIER LPAREN s=stringConstant COMMA e1=coverageExpr RPAREN
+ { $value = new SetMetaDataExpr($op.text, $e1.value, $s.value); }
+ | op=SETCRSSET LPAREN e1=coverageExpr COMMA crs=crsList RPAREN
+ { $value = new SetMetaDataExpr($op.text, $e1.value, $crs.value); }
+ | op=SETNULLSET LPAREN e1=coverageExpr COMMA rel=rangeExprList RPAREN
+ { $value = new SetMetaDataExpr($op.text, $e1.value, $rel.value); }
+ | op=SETINTERPOLATIONDEFAULT LPAREN e1=coverageExpr COMMA fn=fieldName COMMA im=interpolationMethod RPAREN
+ { $value = new SetMetaDataExpr($op.text, $e1.value, $im.value, $fn.value); }
+ | op=SETINTERPOLATIONSET LPAREN e1=coverageExpr COMMA fn=fieldName COMMA iml=interpolationMethodList RPAREN
+ { $value = new SetMetaDataExpr($op.text, $e1.value, $iml.value, $fn.value); }
+ ;
+crsList returns[CrsList value]
+ : LBRACE {$value = new CrsList();} (crs=crsName { $value.add($crs.value); } (COMMA crs=crsName { $value.add($crs.value); })* )? RBRACE
+ ;
+rangeExprList returns[RangeExprList value]
+ : LBRACE { $value = new RangeExprList(); } (re1=rangeExpr { $value.add($re1.value); } (COMMA re2=rangeExpr { $value.add($re2.value); })* )? RBRACE
+ ;
+interpolationMethodList returns[InterpolationMethodList value]
+ : LBRACE {$value = new InterpolationMethodList();} (e=interpolationMethod { $value.add($e.value); } (COMMA e=interpolationMethod { $value.add($e.value); })*)? RBRACE
+ ;
+rangeExpr returns[RangeExpr value]
+ : STRUCT LBRACE { $value=new RangeExpr(); }
+ (field=fieldName COLON expr=scalarExpr { $value.add($field.value, $expr.value); }
+ (COLON field=fieldName COLON expr=scalarExpr { $value.add($field.value, $expr.value); })*
+ )? RBRACE
+ ;
+coverageExpr returns[CoverageExpr value]
+ : e1=coverageLogicTerm { $value = $e1.value; }
+ (op=(OR^|XOR^) e2=coverageLogicTerm { $value = new CoverageExpr($op.text, $value, $e2.value); })*
+ ;
+coverageLogicTerm returns[CoverageExpr value]
+ : e1=coverageLogicFactor { $value = $e1.value; }
+ (op=(AND^) e2=coverageLogicFactor { $value = new CoverageExpr($op.text, $value, $e2.value); })*
+ ;
+coverageLogicFactor returns[CoverageExpr value]
+ : e1=coverageArithmeticExpr {$value = $e1.value;}
+ (op=(EQUALS|NOTEQUALS|LT|GT|LTE|GTE) e2=coverageArithmeticExpr { $value = new CoverageExpr($op.text, $value, $e2.value); } )?
+ ;
+coverageArithmeticExpr returns[CoverageExpr value]
+ : e1=coverageArithmeticTerm {$value = $e1.value; }
+ (op=(PLUS^|MINUS^) e2=coverageArithmeticTerm { $value = new CoverageExpr($op.text, $value, $e2.value); } )*
+ ;
+coverageArithmeticTerm returns[CoverageExpr value]
+ : e1=coverageArithmeticFactor { $value = $e1.value; }
+ (op=(MULT^|DIVIDE^) e2=coverageArithmeticFactor { $value = new CoverageExpr($op.text, $value, $e2.value); } )*
+ ;
+coverageArithmeticFactor returns[CoverageExpr value]
+ : e1=coverageValue { $value = $e1.value; }
+ (op=(OVERLAY^) e2=coverageValue { $value = new CoverageExpr($op.text, $value, $e2.value); } )*
+ ;
+coverageValue returns[CoverageExpr value]
+ : e1=coverageAtom { $value = $e1.value; }
+ | e2=unaryInducedExpr { $value = $e2.value; }
+ | e3=crsTransformExpr { $value = new CoverageExpr($e3.value); }
+ | e4=scaleExpr { $value = new CoverageExpr($e4.value); }
+ | e5=subsetExpr { $value = new CoverageExpr($e5.value); }
+ ;
+coverageAtom returns[CoverageExpr value]
+ : e1=variableName { $value = new CoverageExpr($e1.value); }
+ | e2=scalarExpr { $value = new CoverageExpr($e2.value); }
+ | e3=coverageConstantExpr { $value = new CoverageExpr($e3.value); }
+ | e4=coverageConstructorExpr { $value = new CoverageExpr($e4.value); }
+ | e5=setMetaDataExpr { $value = new CoverageExpr($e5.value); }
+ | e6=rangeConstructorExpr { $value = new CoverageExpr($e6.value); }
+ | LPAREN e7=coverageExpr RPAREN { $value = new CoverageExpr($e7.value); }
+ ;
+unaryInducedExpr returns[CoverageExpr value]
+ : e1=unaryArithmeticExpr { $value = $e1.value; }
+ | e2=exponentialExpr { $value = new CoverageExpr($e2.value); }
+ | e3=trigonometricExpr { $value = new CoverageExpr($e3.value); }
+ | e4=booleanExpr { $value = new CoverageExpr($e4.value); }
+ | e5=castExpr { $value = new CoverageExpr($e5.value); }
+ | e6=fieldExpr { $value = new CoverageExpr($e6.value); }
+ | e7=rangeConstructorExpr { $value = new CoverageExpr($e7.value); }
+ ;
+unaryArithmeticExpr returns[CoverageExpr value]
+ : op=(MINUS|PLUS) e1=coverageAtom { $value = new CoverageExpr($op.text, $e1.value); }
+ | op=(SQRT|ABS|RE|IM) LPAREN e2=coverageExpr RPAREN { $value = new CoverageExpr($op.text, $e2.value); }
+ ;
+exponentialExpr returns[ExponentialExpr value]
+ : op=(EXP|LOG|LN) LPAREN e1=coverageExpr RPAREN { $value = new ExponentialExpr($op.text, $e1.value); }
+ ;
+trigonometricExpr returns[TrigonometricExpr value]
+ : op=(SIN|COS|TAN|SINH|COSH|TANH|ARCSIN|ARCCOS|ARCTAN) LPAREN e1=coverageExpr RPAREN { $value = new TrigonometricExpr($op.text, $e1.value); }
+ ;
+booleanExpr returns[BooleanExpr value]
+ : op=NOT e1=coverageExpr { $value = new BooleanExpr($op.text, $e1.value); }
+ | op=BIT LPAREN e1=coverageExpr COMMA e2=indexExpr RPAREN { $value = new BooleanExpr($op.text, $e1.value, $e2.value); }
+ ;
+castExpr returns[CastExpr value]
+ : LPAREN e1=rangeType RPAREN e2=coverageExpr { $value = new CastExpr($e2.value, $e1.value); }
+ ;
+rangeType returns[String value]
+ : type=(BOOLEAN|CHAR|SHORT|LONG|FLOAT|DOUBLE|COMPLEX|COMPLEX2) { $value = new String($type.text); }
+ | UNSIGNED type=(CHAR|SHORT|LONG) { $value = new String("unsigned " + $type.text); }
+ ;
+fieldExpr returns[SelectExpr value]
+ : e1=coverageAtom DOT e2=fieldName { $value = new SelectExpr($e1.value, $e2.value); }
+ ;
+indexExpr returns[IndexExpr value]
+ : e1=indexTerm { $value = $e1.value; } (op=(PLUS^|MINUS^) e2=indexTerm { $value = new IndexExpr($op.text, $value, $e2.value); })*
+ ;
+indexTerm returns[IndexExpr value]
+ : e1=indexFactor { $value = $e1.value; } (op=(PLUS^|MINUS^) e2=indexFactor { $value = new IndexExpr($op.text, $value, $e2.value); })*
+ ;
+indexFactor returns[IndexExpr value]
+ : e=INTEGERCONSTANT { $value = new IndexExpr($e.text); }
+ | op=ROUND LPAREN e1=numericScalarExpr RPAREN { $value = new IndexExpr($op.text, $e1.value); }
+ | LPAREN e2=indexExpr RPAREN { $value = $e2.value; }
+ ;
+subsetExpr returns[SubsetExpr value]
+ : e1=trimExpr { $value = new SubsetExpr($e1.value); }
+ | e2=sliceExpr { $value = new SubsetExpr($e2.value); }
+ | e3=extendExpr { $value = new SubsetExpr($e3.value); }
+ ;
+trimExpr returns[TrimExpr value]
+ : e1=coverageAtom LBRACKET dil=dimensionIntervalList RBRACKET { $value = new TrimExpr($e1.value, $dil.value); }
+ | TRIM LPAREN e2=coverageExpr COMMA LBRACE dil=dimensionIntervalList RBRACE RPAREN { $value = new TrimExpr($e2.value, $dil.value); }
+ ;
+sliceExpr returns[SliceExpr value]
+ : e1=coverageAtom LBRACKET dpl=dimensionPointList RBRACKET { $value = new SliceExpr($e1.value, $dpl.value); }
+ | SLICE LPAREN e2=coverageExpr COMMA LBRACE dpl=dimensionPointList RBRACE RPAREN { $value = new SliceExpr($e2.value, $dpl.value); }
+ ;
+extendExpr returns[ExtendExpr value]
+ : EXTEND LPAREN e1=coverageExpr COMMA dil=dimensionIntervalList RPAREN { $value = new ExtendExpr($e1.value, $dil.value); }
+ ;
+scaleExpr returns[ScaleExpr value]
+ : SCALE LPAREN e1=coverageExpr COMMA dil=dimensionIntervalList COMMA fil=fieldInterpolationList RPAREN
+ { $value = new ScaleExpr($e1.value, $dil.value, $fil.value); }
+ ;
+rangeConstructorExpr returns[RangeConstructorExpr value]
+ : (STRUCT)? LBRACE field=fieldName COLON expr=coverageExpr { $value = new RangeConstructorExpr($field.value, $expr.value); }
+ (SEMICOLON field=fieldName COLON expr=coverageExpr { $value.add($field.value, $expr.value); })* RBRACE
+ ;
+crsTransformExpr returns[CrsTransformExpr value]
+ : CRSTRANSFORM LPAREN e1=coverageExpr COMMA dcl=dimensionIntervalList COMMA fil=fieldInterpolationList RPAREN
+ { $value = new CrsTransformExpr($e1.value, $dcl.value, $fil.value); }
+ ;
+dimensionPointList returns[DimensionPointList value]
+ : elem1=dimensionPointElement { $value = new DimensionPointList($elem1.value); }
+ (COMMA elem2=dimensionPointElement { $value.add($elem2.value); })*
+ ;
+dimensionPointElement returns[DimensionPointElement value]
+ : aname=axisName LPAREN dpe=dimensionPoint RPAREN { $value = new DimensionPointElement($aname.value, $dpe.value); }
+ | aname=axisName COLON crs=crsName LPAREN dpe=dimensionPoint RPAREN { $value = new DimensionPointElement($aname.value, $crs.value, $dpe.value); }
+ ;
+dimensionPoint returns[ScalarExpr value]
+ : e1=scalarExpr { $value = $e1.value; }
+ ;
+dimensionIntervalList returns[DimensionIntervalList value]
+ : elem=dimensionIntervalElement { $value = new DimensionIntervalList($elem.value); }
+ (COMMA elem=dimensionIntervalElement { $value.add($elem.value); })*
+ ;
+dimensionIntervalElement returns[DimensionIntervalElement value]
+ : aname=axisName { $value = new DimensionIntervalElement($aname.value); } (COLON crs=crsName {$value.setCrs($crs.value); })?
+ LPAREN die=dimensionIntervalExpr RPAREN { $value.setIntervalExpr($die.value); }
+ ;
+dimensionIntervalExpr returns[DimensionIntervalExpr value]
+ : e1=scalarExpr COLON e2=scalarExpr { $value = new DimensionIntervalExpr($e1.value, $e2.value); }
+ | DOMAIN LPAREN e3=coverageName COLON e4=axisName COLON e5=crsName RPAREN { $value = new DimensionIntervalExpr($e3.value, $e4.value, $e5.value); }
+ ;
+/*
+dimensionCrsList returns[DimensionCrsList value]
+ : LBRACE elem=dimensionCrsElement { $value = new DimensionCrsList($elem.value); }
+ (COMMA elem=dimensionCrsElement { $value.add($elem.value); } )* RBRACE
+ ;
+
+dimensionCrsElement returns[DimensionCrsElement value]
+ : aname=axisName COLON crs=crsName { $value = new DimensionCrsElement($aname.value, $crs.value); }
+ ;
+*/
+fieldInterpolationList returns[FieldInterpolationList value]
+ : LBRACE elem=fieldInterpolationElement { $value = new FieldInterpolationList($elem.value); }
+ (COMMA elem=fieldInterpolationElement { $value.add($elem.value); }) * RBRACE
+ ;
+fieldInterpolationElement returns[FieldInterpolationElement value]
+ : aname=fieldName method=interpolationMethod { $value = new FieldInterpolationElement($aname.value, $method.value); }
+ ;
+interpolationMethod returns[InterpolationMethod value]
+ : LPAREN type=interpolationType COLON res=nullResistence RPAREN { $value = new InterpolationMethod($type.value, $res.value); }
+ ;
+interpolationType returns[String value]
+ : type=(NEAREST|LINEAR|QUADRATIC|CUBIC) { $value = new String($type.text); }
+ ;
+nullResistence returns[String value]
+ : resistance=(FULL|NONE|HALF|OTHER) { $value = new String($resistance.text); }
+ ;
+coverageConstructorExpr returns[CoverageConstructorExpr value]
+ : COVERAGE coverage=coverageName OVER ail=axisIteratorList VALUES se=scalarExpr
+ { $value = new CoverageConstructorExpr($coverage.value, $ail.value, $se.value); }
+ ;
+axisIteratorList returns[AxisIteratorList value]
+ : vn=variableName an=axisName LPAREN ie=intervalExpr RPAREN
+ { $value = new AxisIteratorList(new AxisIterator($vn.value, $an.value, $ie.value)); }
+ (COMMA vn2=variableName an2=axisName LPAREN ie2=intervalExpr RPAREN
+ { $value = new AxisIteratorList(new AxisIterator($vn2.value, $an2.value, $ie2.value), $value); })*
+ ;
+intervalExpr returns[IntervalExpr value]
+ : lo=indexExpr COLON hi=indexExpr
+ { $value = new IntervalExpr($lo.value, $hi.value); }
+ | IMAGECRSDOMAIN LPAREN e1=coverageName COMMA e2=axisName RPAREN
+ { $value = new IntervalExpr($e1.value, $e2.value); }
+ ;
+coverageConstantExpr returns[CoverageConstantExpr value]
+ : COVERAGE aname=coverageName OVER iter=axisIteratorList VALUE LIST LT values=constantList GT
+ { $value = new CoverageConstantExpr($aname.value, $iter.value, $values.value); }
+ ;
+/*
+axisSpecList returns[AxisSpecList value]
+ : n=axisName LPAREN r=intervalExpr RPAREN { $value = new AxisSpecList($n.value, $r.value); }
+ (COMMA n2=axisName LPAREN r2=intervalExpr RPAREN { $value.add($n2.value, $r2.value); })*
+ ;
+*/
+constantList returns[ConstantList value]
+ : c=constant { $value = new ConstantList($c.value); } (SEMICOLON c=constant { $value.add($c.value); })*
+ ;
+condenseExpr returns[CondenseExpr value]
+ : e1=reduceExpr { $value = new CondenseExpr($e1.value); }
+ | e2=generalCondenseExpr { $value = new CondenseExpr($e2.value); }
+ ;
+reduceExpr returns[ReduceExpr value]
+ : op=(ALL|SOME|COUNT|ADD|AVG|MIN|MAX) LPAREN e1=coverageExpr RPAREN { $value = new ReduceExpr($op.text, $e1.value); }
+ ;
+generalCondenseExpr returns[GeneralCondenseExpr value]
+ : CONDENSE op=condenseOpType OVER ail=axisIteratorList { $value = new GeneralCondenseExpr($op.value, $ail.value); }
+ (WHERE cond=booleanScalarExpr { $value.setWhere($cond.value); })?
+ USING se=scalarExpr { $value.setUsing($se.value); }
+ ;
+condenseOpType returns[CondenseOperationType value]
+ : op=(PLUS|MULT|MAX|MIN|AND|OR) { $value = new CondenseOperationType($op.text); }
+ ;
+coverageName returns[String value]
+ : name { $value = $name.value; }
+ ;
+crsName returns[String value]
+ : s=stringConstant { $value = $s.value; }
+ ;
+axisName returns[String value]
+ : type=(X|Y|Z|PHI|R|T) { $value = new String($type.text); }
+ | type1=name { $value = new String($type1.value); }
+ ;
+fieldName returns[String value]
+ : name { $value = new String($name.value);}
+ ;
+constant returns[String value]
+ : e=(STRING|BOOLEANCONSTANT|INTEGERCONSTANT|FLOATCONSTANT) { $value = $e.text; }
+ | e1=complexConstant { $value = $e1.value; }
+ ;
+complexConstant returns[String value]
+ : LPAREN re1=FLOATCONSTANT COMMA im1=FLOATCONSTANT RPAREN { $value = new String($re1.text +"+i"+$im1.text); }
+ ;
+stringConstant returns[String value]
+ : s=STRING { $value = $s.text; }
+ ;
+variableName returns[String value]
+ : s=(VARIABLE|NAME) { $value = $s.text; }
+ ;
+name returns[String value]
+ : s=(NAME|STRING) { $value = $s.text; }
+ ;
+
+
+/* Lexer rules */
+PLUS: '+';
+MINUS: '-';
+DIVIDE: '/';
+MULT: '*';
+EQUALS: '=';
+NOTEQUALS: '!=';
+LT: '<';
+GT: '>';
+LTE: '<=';
+GTE: '>=';
+DOT: '.';
+LPAREN: '(';
+RPAREN: ')';
+LBRACKET: '[';
+RBRACKET: ']';
+LBRACE: '{';
+RBRACE: '}';
+COMMA: ',';
+COLON: ':';
+SEMICOLON: ';';
+FOR: ('f'|'F')('o'|'O')('r'|'R');
+IN: ('i'|'I')('n'|'N');
+WHERE: ('w'|'W')('h'|'H')('e'|'E')('r'|'R')('e'|'E');
+RETURN: ('r'|'R')('e'|'E')('t'|'T')('u'|'U')('r'|'R')('n'|'N');
+STORE: ('s'|'S')('t'|'T')('o'|'O')('r'|'R')('e'|'E');
+ENCODE: ('e'|'E')('n'|'N')('c'|'C')('o'|'O')('d'|'D')('e'|'E');
+SQRT: ('s'|'S')('q'|'Q')('r'|'R')('t'|'T');
+SIN: ('s'|'S')('i'|'I')('n'|'N');
+COS: ('c'|'C')('o'|'O')('s'|'S');
+TAN: ('t'|'T')('a'|'A')('n'|'N');
+SINH: ('s'|'S')('i'|'I')('n'|'N')('h'|'H');
+COSH: ('c'|'C')('o'|'O')('s'|'S')('h'|'H');
+TANH: ('t'|'T')('a'|'A')('n'|'N')('h'|'H');
+ARCSIN: ('a'|'A')('r'|'R')('c'|'C')('s'|'S')('i'|'I')('n'|'N');
+ARCCOS: ('a'|'A')('r'|'R')('c'|'C')('c'|'C')('o'|'O')('s'|'S');
+ARCTAN: ('a'|'A')('r'|'R')('c'|'C')('t'|'T')('a'|'A')('n'|'N');
+EXP: ('e'|'E')('x'|'X')('p'|'P');
+LN: ('l'|'L')('n'|'N');
+LOG: ('l'|'L')('o'|'O')('g'|'G');
+ROUND: ('r'|'R')('o'|'O')('u'|'U')('n'|'N')('d'|'D');
+ABS: ('a'|'A')('b'|'B')('s'|'S');
+OVERLAY: ('o'|'O')('v'|'V')('e'|'E')('r'|'R')('l'|'L')('a'|'A')('y'|'Y');
+STRUCT: ('s'|'S')('t'|'T')('r'|'R')('u'|'U')('c'|'C')('t'|'T');
+RE: ('r'|'R')('e'|'E');
+IM: ('i'|'I')('m'|'M');
+AND: ('a'|'A')('n'|'N')('d'|'D');
+OR: ('o'|'O')('r'|'R');
+XOR: ('x'|'X')('o'|'O')('r'|'R');
+NOT: ('n'|'N')('o'|'O')('t'|'T');
+IDENTIFIER: ('i'|'I')('d'|'D')('e'|'E')('n'|'N')('t'|'T')('i'|'I')('f'|'F')('i'|'I')('e'|'E')('r'|'R');
+IMAGECRS: ('i'|'I')('m'|'M')('a'|'A')('g'|'G')('e'|'E')('c'|'C')('r'|'R')('s'|'S');
+IMAGECRSDOMAIN: ('i'|'I')('m'|'M')('a'|'A')('g'|'G')('e'|'E')('c'|'C')('r'|'R')('s'|'S')('d'|'D')('o'|'O')('m'|'M')('a'|'A')('i'|'I')('n'|'N');
+CRSSET: ('c'|'C')('r'|'R')('s'|'S')('s'|'S')('e'|'E')('t'|'T');
+DOMAIN: ('d'|'D')('o'|'O')('m'|'M')('a'|'A')('i'|'I')('n'|'N');
+NULLSET: ('n'|'N')('u'|'U')('l'|'L')('l'|'L')('s'|'S')('e'|'E')('t'|'T');
+NULLDEFAULT: ('n'|'N')('u'|'U')('l'|'L')('l'|'L')('d'|'D')('e'|'E')('f'|'F')('a'|'A')('u'|'U')('l'|'L')('t'|'T');
+INTERPOLATIONDEFAULT: ('i'|'I')('n'|'N')('t'|'T')('e'|'E')('r'|'R')('p'|'P')('o'|'O')('l'|'L')('a'|'A')('t'|'T')('i'|'I')('o'|'O')('n'|'N')('d'|'D')('e'|'E')('f'|'F')('a'|'A')('u'|'U')('l'|'L')('t'|'T');
+INTERPOLATIONSET: ('i'|'I')('n'|'N')('t'|'T')('e'|'E')('r'|'R')('p'|'P')('o'|'O')('l'|'L')('a'|'A')('t'|'T')('i'|'I')('o'|'O')('n'|'N')('s'|'S')('e'|'E')('t'|'T');
+SETIDENTIFIER: ('s'|'S')('e'|'E')('t'|'T')('i'|'I')('d'|'D')('e'|'E')('n'|'N')('t'|'T')('i'|'I')('f'|'F')('i'|'I')('e'|'E')('r'|'R');
+SETNULLSET: ('s'|'S')('e'|'E')('t'|'T')('n'|'N')('u'|'U')('l'|'L')('l'|'L')('s'|'S')('e'|'E')('t'|'T');
+SETINTERPOLATIONDEFAULT: ('s'|'S')('e'|'E')('t'|'T')('i'|'I')('n'|'N')('t'|'T')('e'|'E')('r'|'R')('p'|'P')('o'|'O')('l'|'L')('a'|'A')('t'|'T')('i'|'I')('o'|'O')('n'|'N')('d'|'D')('e'|'E')('f'|'F')('a'|'A')('u'|'U')('l'|'L')('t'|'T');
+SETINTERPOLATIONSET:('s'|'S')('e'|'E')('t'|'T')('i'|'I')('n'|'N')('t'|'T')('e'|'E')('r'|'R')('p'|'P')('o'|'O')('l'|'L')('a'|'A')('t'|'T')('i'|'I')('o'|'O')('n'|'N')('s'|'S')('e'|'E')('t'|'T');
+SETCRSSET: ('s'|'S')('e'|'E')('t'|'T')('c'|'C')('r'|'R')('s'|'S')('s'|'S')('e'|'E')('t'|'T');
+TRIM: ('t'|'T')('r'|'R')('i'|'I')('m'|'M');
+SLICE: ('s'|'S')('l'|'L')('i'|'I')('c'|'C')('e'|'E');
+EXTEND: ('e'|'E')('x'|'X')('t'|'T')('e'|'E')('n'|'N')('d'|'D');
+SCALE: ('s'|'S')('c'|'C')('a'|'A')('l'|'L')('e'|'E');
+CRSTRANSFORM: ('c'|'C')('r'|'R')('s'|'S')('t'|'T')('r'|'R')('a'|'A')('n'|'N')('s'|'S')('f'|'F')('o'|'O')('r'|'R')('m'|'M');
+COUNT: ('c'|'C')('o'|'O')('u'|'U')('n'|'N')('t'|'T');
+ADD: ('a'|'A')('d'|'D')('d'|'D');
+AVG: ('a'|'A')('v'|'V')('g'|'G');
+MAX: ('m'|'M')('a'|'A')('x'|'X');
+MIN: ('m'|'M')('i'|'I')('n'|'N');
+SOME: ('s'|'S')('o'|'O')('m'|'M')('e'|'E');
+ALL: ('a'|'A')('l'|'L')('l'|'L');
+COVERAGE: ('c'|'C')('o'|'O')('v'|'V')('e'|'E')('r'|'R')('a'|'A')('g'|'G')('e'|'E');
+OVER: ('o'|'O')('v'|'V')('e'|'E')('r'|'R');
+VALUE: ('v'|'V')('a'|'A')('l'|'L')('u'|'U')('e'|'E');
+VALUES: ('v'|'V')('a'|'A')('l'|'L')('u'|'U')('e'|'E')('s'|'S');
+LIST: ('l'|'L')('i'|'I')('s'|'S')('t'|'T');
+CONDENSE: ('c'|'C')('o'|'O')('n'|'N')('d'|'D')('e'|'E')('n'|'N')('s'|'S')('e'|'E');
+USING: ('u'|'U')('s'|'S')('i'|'I')('n'|'N')('g'|'G');
+NEAREST: ('n'|'N')('e'|'E')('a'|'A')('r'|'R')('e'|'E')('s'|'S')('t'|'T');
+LINEAR: ('l'|'L')('i'|'I')('n'|'N')('e'|'E')('a'|'A')('r'|'R');
+QUADRATIC: ('q'|'Q')('u'|'U')('a'|'A')('d'|'D')('r'|'R')('a'|'A')('t'|'T')('i'|'I')('c'|'C');
+CUBIC: ('c'|'C')('u'|'U')('b'|'B')('i'|'I')('c'|'C');
+FULL: ('f'|'F')('u'|'U')('l'|'L')('l'|'L');
+NONE: ('n'|'N')('o'|'O')('n'|'N')('e'|'E');
+HALF: ('h'|'H')('a'|'A')('l'|'L')('f'|'F');
+OTHER: ('o'|'O')('t'|'T')('h'|'H')('e'|'E')('r'|'R');
+X: ('x'|'X');
+Y: ('y'|'Y');
+Z: ('z'|'Z');
+R: ('r'|'R');
+T: ('t'|'T');
+PHI: ('p'|'P')('h'|'H')('i'|'I');
+BIT: ('b'|'B')('i'|'I')('t'|'T');
+UNSIGNED: ('u'|'U')('n'|'N')('s'|'S')('i'|'I')('g'|'G')('n'|'N')('e'|'E')('d'|'D');
+BOOLEAN: ('b'|'B')('o'|'O')('o'|'O')('l'|'L')('e'|'E')('a'|'A')('n'|'N');
+CHAR: ('c'|'C')('h'|'H')('a'|'A')('r'|'R');
+SHORT: ('s'|'S')('h'|'H')('o'|'O')('r'|'R')('t'|'T');
+LONG: ('l'|'L')('o'|'O')('n'|'N')('g'|'G');
+FLOAT: ('f'|'F')('l'|'L')('o'|'O')('a'|'A')('t'|'T');
+DOUBLE: ('d'|'D')('o'|'O')('u'|'U')('b'|'B')('l'|'L')('e'|'E');
+COMPLEX: ('c'|'C')('o'|'O')('m'|'M')('p'|'P')('l'|'L')('e'|'E')('x'|'X');
+COMPLEX2: ('c'|'C')('o'|'O')('m'|'M')('p'|'P')('l'|'L')('e'|'E')('x'|'X')'2';
+BOOLEANCONSTANT: (('t'|'T')('r'|'R')('u'|'U')('e'|'E'))|(('f'|'F')('a'|'A')('l'|'L')('s'|'S')('e'|'E'));
+INTEGERCONSTANT: ('0x'|'0X'|'0')?('0'|(('1'..'9'|'a'..'f'|'A'..'F')(('0'..'9'|'a'..'f'|'A'..'F')*)));
+FLOATCONSTANT:('0'..'9'*)('.')('0'..'9'+)(('e'|'E')(('-'|'+')?)('0'..'9'+))?|INTEGERCONSTANT;
+STRING: '"' ( options {greedy=false;} : . )* '"';
+NAME: ('a'..'z'|'A'..'Z'|'_')(('a'..'z'|'A'..'Z'|'0'..'9'|'_')*);
+VARIABLE: '$'(('a'..'z'|'A'..'Z'|'0'..'9'|'_')*) | NAME;
+WHITESPACE: (' ' | '\t' | '\r' | '\n' | '\u000C')+ { skip(); };
+
+
diff --git a/src/input-output.txt b/src/input-output.txt
new file mode 100644
index 0000000..524646d
--- /dev/null
+++ b/src/input-output.txt
@@ -0,0 +1,5 @@
+inputFile = ../testing/wcs_test/input/GetCoverage1.xml
+outputFile = ../testing/wcs_test/output/ProcessCoverage1.xml
+metadataSettingsFile = /home/andrei/Job/WCPS Update/WCPS_Project/wcps/dbparams.properties
+printOutputFile = true
+printLogMessages = true
diff --git a/src/java_cup/compile_java_cup b/src/java_cup/compile_java_cup
new file mode 100644
index 0000000..e0f3ff8
--- /dev/null
+++ b/src/java_cup/compile_java_cup
@@ -0,0 +1,2 @@
+#!/bin/bash
+javac java_cup/*.java runtime/*.java
diff --git a/src/java_cup/java_cup/Main.java b/src/java_cup/java_cup/Main.java
new file mode 100644
index 0000000..50811b5
--- /dev/null
+++ b/src/java_cup/java_cup/Main.java
@@ -0,0 +1,854 @@
+
+package java_cup;
+
+import java.util.Enumeration;
+import java.io.*;
+
+/** This class serves as the main driver for the JavaCup system.
+ * It accepts user options and coordinates overall control flow.
+ * The main flow of control includes the following activities:
+ * <ul>
+ * <li> Parse user supplied arguments and options.
+ * <li> Open output files.
+ * <li> Parse the specification from standard input.
+ * <li> Check for unused terminals, non-terminals, and productions.
+ * <li> Build the state machine, tables, etc.
+ * <li> Output the generated code.
+ * <li> Close output files.
+ * <li> Print a summary if requested.
+ * </ul>
+ *
+ * Options to the main program include: <dl>
+ * <dt> -package name
+ * <dd> specify package generated classes go in [default none]
+ * <dt> -parser name
+ * <dd> specify parser class name [default "parser"]
+ * <dt> -symbols name
+ * <dd> specify name for symbol constant class [default "sym"]
+ * <dt> -interface
+ * <dd> emit symbol constant <i>interface</i>, rather than class
+ * <dt> -nonterms
+ * <dd> put non terminals in symbol constant class
+ * <dt> -expect #
+ * <dd> number of conflicts expected/allowed [default 0]
+ * <dt> -compact_red
+ * <dd> compact tables by defaulting to most frequent reduce
+ * <dt> -nowarn
+ * <dd> don't warn about useless productions, etc.
+ * <dt> -nosummary
+ * <dd> don't print the usual summary of parse states, etc.
+ * <dt> -progress
+ * <dd> print messages to indicate progress of the system
+ * <dt> -time
+ * <dd> print time usage summary
+ * <dt> -dump_grammar
+ * <dd> produce a dump of the symbols and grammar
+ * <dt> -dump_states
+ * <dd> produce a dump of parse state machine
+ * <dt> -dump_tables
+ * <dd> produce a dump of the parse tables
+ * <dt> -dump
+ * <dd> produce a dump of all of the above
+ * <dt> -debug
+ * <dd> turn on debugging messages within JavaCup
+ * <dt> -nopositions
+ * <dd> don't generate the positions code
+ * <dt> -noscanner
+ * <dd> don't refer to java_cup.runtime.Scanner in the parser
+ * (for compatibility with old runtimes)
+ * <dt> -version
+ * <dd> print version information for JavaCUP and halt.
+ * </dl>
+ *
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+
+public class Main {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+ /** Only constructor is private, so we do not allocate any instances of this
+ class. */
+ private Main() { }
+
+ /*-------------------------*/
+ /* Options set by the user */
+ /*-------------------------*/
+ /** User option -- do we print progress messages. */
+ protected static boolean print_progress = true;
+ /** User option -- do we produce a dump of the state machine */
+ protected static boolean opt_dump_states = false;
+ /** User option -- do we produce a dump of the parse tables */
+ protected static boolean opt_dump_tables = false;
+ /** User option -- do we produce a dump of the grammar */
+ protected static boolean opt_dump_grammar = false;
+ /** User option -- do we show timing information as a part of the summary */
+ protected static boolean opt_show_timing = false;
+ /** User option -- do we run produce extra debugging messages */
+ protected static boolean opt_do_debug = false;
+ /** User option -- do we compact tables by making most common reduce the
+ default action */
+ protected static boolean opt_compact_red = false;
+ /** User option -- should we include non terminal symbol numbers in the
+ symbol constant class. */
+ protected static boolean include_non_terms = false;
+ /** User option -- do not print a summary. */
+ protected static boolean no_summary = false;
+ /** User option -- number of conflicts to expect */
+ protected static int expect_conflicts = 0;
+
+ /* frankf added this 6/18/96 */
+ /** User option -- should generator generate code for left/right values? */
+ protected static boolean lr_values = true;
+
+ /** User option -- should symbols be put in a class or an interface? [CSA]*/
+ protected static boolean sym_interface = false;
+
+ /** User option -- should generator suppress references to
+ * java_cup.runtime.Scanner for compatibility with old runtimes? */
+ protected static boolean suppress_scanner = false;
+
+ /*----------------------------------------------------------------------*/
+ /* Timing data (not all of these time intervals are mutually exclusive) */
+ /*----------------------------------------------------------------------*/
+ /** Timing data -- when did we start */
+ protected static long start_time = 0;
+ /** Timing data -- when did we end preliminaries */
+ protected static long prelim_end = 0;
+ /** Timing data -- when did we end parsing */
+ protected static long parse_end = 0;
+ /** Timing data -- when did we end checking */
+ protected static long check_end = 0;
+ /** Timing data -- when did we end dumping */
+ protected static long dump_end = 0;
+ /** Timing data -- when did we end state and table building */
+ protected static long build_end = 0;
+ /** Timing data -- when did we end nullability calculation */
+ protected static long nullability_end = 0;
+ /** Timing data -- when did we end first set calculation */
+ protected static long first_end = 0;
+ /** Timing data -- when did we end state machine construction */
+ protected static long machine_end = 0;
+ /** Timing data -- when did we end table construction */
+ protected static long table_end = 0;
+ /** Timing data -- when did we end checking for non-reduced productions */
+ protected static long reduce_check_end = 0;
+ /** Timing data -- when did we finish emitting code */
+ protected static long emit_end = 0;
+ /** Timing data -- when were we completely done */
+ protected static long final_time = 0;
+
+ /* Additional timing information is also collected in emit */
+
+ /*-----------------------------------------------------------*/
+ /*--- Main Program ------------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The main driver for the system.
+ * @param argv an array of strings containing command line arguments.
+ */
+ public static void main(String argv[])
+ throws internal_error, java.io.IOException, java.lang.Exception
+ {
+ boolean did_output = false;
+
+ start_time = System.currentTimeMillis();
+
+ /* process user options and arguments */
+ parse_args(argv);
+
+ /* frankf 6/18/96
+ hackish, yes, but works */
+ emit.set_lr_values(lr_values);
+ /* open output files */
+ if (print_progress) System.err.println("Opening files...");
+ /* use a buffered version of standard input */
+ input_file = new BufferedInputStream(System.in);
+
+ prelim_end = System.currentTimeMillis();
+
+ /* parse spec into internal data structures */
+ if (print_progress)
+ System.err.println("Parsing specification from standard input...");
+ parse_grammar_spec();
+
+ parse_end = System.currentTimeMillis();
+
+ /* don't proceed unless we are error free */
+ if (lexer.error_count == 0)
+ {
+ /* check for unused bits */
+ if (print_progress) System.err.println("Checking specification...");
+ check_unused();
+
+ check_end = System.currentTimeMillis();
+
+ /* build the state machine and parse tables */
+ if (print_progress) System.err.println("Building parse tables...");
+ build_parser();
+
+ build_end = System.currentTimeMillis();
+
+ /* output the generated code, if # of conflicts permits */
+ if (lexer.error_count != 0) {
+ // conflicts! don't emit code, don't dump tables.
+ opt_dump_tables = false;
+ } else { // everything's okay, emit parser.
+ if (print_progress) System.err.println("Writing parser...");
+ open_files();
+ emit_parser();
+ did_output = true;
+ }
+ }
+ /* fix up the times to make the summary easier */
+ emit_end = System.currentTimeMillis();
+
+ /* do requested dumps */
+ if (opt_dump_grammar) dump_grammar();
+ if (opt_dump_states) dump_machine();
+ if (opt_dump_tables) dump_tables();
+
+ dump_end = System.currentTimeMillis();
+
+ /* close input/output files */
+ if (print_progress) System.err.println("Closing files...");
+ close_files();
+
+ /* produce a summary if desired */
+ if (!no_summary) emit_summary(did_output);
+
+ /* If there were errors during the run,
+ * exit with non-zero status (makefile-friendliness). --CSA */
+ if (lexer.error_count != 0)
+ System.exit(100);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Print a "usage message" that described possible command line options,
+ * then exit.
+ * @param message a specific error message to preface the usage message by.
+ */
+ protected static void usage(String message)
+ {
+ System.err.println();
+ System.err.println(message);
+ System.err.println();
+ System.err.println(
+"Usage: " + version.program_name + " [options] [filename]\n" +
+" and expects a specification file on standard input if no filename is given.\n" +
+" Legal options include:\n" +
+" -package name specify package generated classes go in [default none]\n" +
+" -parser name specify parser class name [default \"parser\"]\n" +
+" -symbols name specify name for symbol constant class [default \"sym\"]\n"+
+" -interface put symbols in an interface, rather than a class\n" +
+" -nonterms put non terminals in symbol constant class\n" +
+" -expect # number of conflicts expected/allowed [default 0]\n" +
+" -compact_red compact tables by defaulting to most frequent reduce\n" +
+" -nowarn don't warn about useless productions, etc.\n" +
+" -nosummary don't print the usual summary of parse states, etc.\n" +
+" -nopositions don't propagate the left and right token position values\n" +
+" -noscanner don't refer to java_cup.runtime.Scanner\n" +
+" -progress print messages to indicate progress of the system\n" +
+" -time print time usage summary\n" +
+" -dump_grammar produce a human readable dump of the symbols and grammar\n"+
+" -dump_states produce a dump of parse state machine\n"+
+" -dump_tables produce a dump of the parse tables\n"+
+" -dump produce a dump of all of the above\n"+
+" -version print the version information for CUP and exit\n"
+ );
+ System.exit(1);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Parse command line options and arguments to set various user-option
+ * flags and variables.
+ * @param argv the command line arguments to be parsed.
+ */
+ protected static void parse_args(String argv[])
+ {
+ int len = argv.length;
+ int i;
+
+ /* parse the options */
+ for (i=0; i<len; i++)
+ {
+ /* try to get the various options */
+ if (argv[i].equals("-package"))
+ {
+ /* must have an arg */
+ if (++i >= len || argv[i].startsWith("-") ||
+ argv[i].endsWith(".cup"))
+ usage("-package must have a name argument");
+
+ /* record the name */
+ emit.package_name = argv[i];
+ }
+ else if (argv[i].equals("-parser"))
+ {
+ /* must have an arg */
+ if (++i >= len || argv[i].startsWith("-") ||
+ argv[i].endsWith(".cup"))
+ usage("-parser must have a name argument");
+
+ /* record the name */
+ emit.parser_class_name = argv[i];
+ }
+ else if (argv[i].equals("-symbols"))
+ {
+ /* must have an arg */
+ if (++i >= len || argv[i].startsWith("-") ||
+ argv[i].endsWith(".cup"))
+ usage("-symbols must have a name argument");
+
+ /* record the name */
+ emit.symbol_const_class_name = argv[i];
+ }
+ else if (argv[i].equals("-nonterms"))
+ {
+ include_non_terms = true;
+ }
+ else if (argv[i].equals("-expect"))
+ {
+ /* must have an arg */
+ if (++i >= len || argv[i].startsWith("-") ||
+ argv[i].endsWith(".cup"))
+ usage("-expect must have a name argument");
+
+ /* record the number */
+ try {
+ expect_conflicts = Integer.parseInt(argv[i]);
+ } catch (NumberFormatException e) {
+ usage("-expect must be followed by a decimal integer");
+ }
+ }
+ else if (argv[i].equals("-compact_red")) opt_compact_red = true;
+ else if (argv[i].equals("-nosummary")) no_summary = true;
+ else if (argv[i].equals("-nowarn")) emit.nowarn = true;
+ else if (argv[i].equals("-dump_states")) opt_dump_states = true;
+ else if (argv[i].equals("-dump_tables")) opt_dump_tables = true;
+ else if (argv[i].equals("-progress")) print_progress = true;
+ else if (argv[i].equals("-dump_grammar")) opt_dump_grammar = true;
+ else if (argv[i].equals("-dump"))
+ opt_dump_states = opt_dump_tables = opt_dump_grammar = true;
+ else if (argv[i].equals("-time")) opt_show_timing = true;
+ else if (argv[i].equals("-debug")) opt_do_debug = true;
+ /* frankf 6/18/96 */
+ else if (argv[i].equals("-nopositions")) lr_values = false;
+ /* CSA 12/21/97 */
+ else if (argv[i].equals("-interface")) sym_interface = true;
+ /* CSA 23-Jul-1999 */
+ else if (argv[i].equals("-noscanner")) suppress_scanner = true;
+ /* CSA 23-Jul-1999 */
+ else if (argv[i].equals("-version")) {
+ System.out.println(version.title_str);
+ System.exit(1);
+ }
+ /* CSA 24-Jul-1999; suggestion by Jean Vaucher */
+ else if (!argv[i].startsWith("-") && i==len-1) {
+ /* use input from file. */
+ try {
+ System.setIn(new FileInputStream(argv[i]));
+ } catch (java.io.FileNotFoundException e) {
+ usage("Unable to open \"" + argv[i] +"\" for input");
+ }
+ }
+ else
+ {
+ usage("Unrecognized option \"" + argv[i] + "\"");
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /*-------*/
+ /* Files */
+ /*-------*/
+
+ /** Input file. This is a buffered version of System.in. */
+ protected static BufferedInputStream input_file;
+
+ /** Output file for the parser class. */
+ protected static PrintWriter parser_class_file;
+
+ /** Output file for the symbol constant class. */
+ protected static PrintWriter symbol_class_file;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Open various files used by the system. */
+ protected static void open_files()
+ {
+ File fil;
+ String out_name;
+
+ /* open each of the output files */
+
+ /* parser class */
+ out_name = emit.parser_class_name + ".java";
+ fil = new File(out_name);
+ try {
+ parser_class_file = new PrintWriter(
+ new BufferedOutputStream(new FileOutputStream(fil), 4096));
+ } catch(Exception e) {
+ System.err.println("Can't open \"" + out_name + "\" for output");
+ System.exit(3);
+ }
+
+ /* symbol constants class */
+ out_name = emit.symbol_const_class_name + ".java";
+ fil = new File(out_name);
+ try {
+ symbol_class_file = new PrintWriter(
+ new BufferedOutputStream(new FileOutputStream(fil), 4096));
+ } catch(Exception e) {
+ System.err.println("Can't open \"" + out_name + "\" for output");
+ System.exit(4);
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Close various files used by the system. */
+ protected static void close_files() throws java.io.IOException
+ {
+ if (input_file != null) input_file.close();
+ if (parser_class_file != null) parser_class_file.close();
+ if (symbol_class_file != null) symbol_class_file.close();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Parse the grammar specification from standard input. This produces
+ * sets of terminal, non-terminals, and productions which can be accessed
+ * via static variables of the respective classes, as well as the setting
+ * of various variables (mostly in the emit class) for small user supplied
+ * items such as the code to scan with.
+ */
+ protected static void parse_grammar_spec() throws java.lang.Exception
+ {
+ parser parser_obj;
+
+ /* create a parser and parse with it */
+ parser_obj = new parser();
+ try {
+ if (opt_do_debug)
+ parser_obj.debug_parse();
+ else
+ parser_obj.parse();
+ } catch (Exception e)
+ {
+ /* something threw an exception. catch it and emit a message so we
+ have a line number to work with, then re-throw it */
+ lexer.emit_error("Internal error: Unexpected exception");
+ throw e;
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Check for unused symbols. Unreduced productions get checked when
+ * tables are created.
+ */
+ protected static void check_unused()
+ {
+ terminal term;
+ non_terminal nt;
+
+ /* check for unused terminals */
+ for (Enumeration t = terminal.all(); t.hasMoreElements(); )
+ {
+ term = (terminal)t.nextElement();
+
+ /* don't issue a message for EOF */
+ if (term == terminal.EOF) continue;
+
+ /* or error */
+ if (term == terminal.error) continue;
+
+ /* is this one unused */
+ if (term.use_count() == 0)
+ {
+ /* count it and warn if we are doing warnings */
+ emit.unused_term++;
+ if (!emit.nowarn)
+ {
+ System.err.println("Warning: Terminal \"" + term.name() +
+ "\" was declared but never used");
+ lexer.warning_count++;
+ }
+ }
+ }
+
+ /* check for unused non terminals */
+ for (Enumeration n = non_terminal.all(); n.hasMoreElements(); )
+ {
+ nt = (non_terminal)n.nextElement();
+
+ /* is this one unused */
+ if (nt.use_count() == 0)
+ {
+ /* count and warn if we are doing warnings */
+ emit.unused_term++;
+ if (!emit.nowarn)
+ {
+ System.err.println("Warning: Non terminal \"" + nt.name() +
+ "\" was declared but never used");
+ lexer.warning_count++;
+ }
+ }
+ }
+
+ }
+
+ /* . . . . . . . . . . . . . . . . . . . . . . . . .*/
+ /* . . Internal Results of Generating the Parser . .*/
+ /* . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Start state in the overall state machine. */
+ protected static lalr_state start_state;
+
+ /** Resulting parse action table. */
+ protected static parse_action_table action_table;
+
+ /** Resulting reduce-goto table. */
+ protected static parse_reduce_table reduce_table;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Build the (internal) parser from the previously parsed specification.
+ * This includes:<ul>
+ * <li> Computing nullability of non-terminals.
+ * <li> Computing first sets of non-terminals and productions.
+ * <li> Building the viable prefix recognizer machine.
+ * <li> Filling in the (internal) parse tables.
+ * <li> Checking for unreduced productions.
+ * </ul>
+ */
+ protected static void build_parser() throws internal_error
+ {
+ /* compute nullability of all non terminals */
+ if (opt_do_debug || print_progress)
+ System.err.println(" Computing non-terminal nullability...");
+ non_terminal.compute_nullability();
+
+ nullability_end = System.currentTimeMillis();
+
+ /* compute first sets of all non terminals */
+ if (opt_do_debug || print_progress)
+ System.err.println(" Computing first sets...");
+ non_terminal.compute_first_sets();
+
+ first_end = System.currentTimeMillis();
+
+ /* build the LR viable prefix recognition machine */
+ if (opt_do_debug || print_progress)
+ System.err.println(" Building state machine...");
+ start_state = lalr_state.build_machine(emit.start_production);
+
+ machine_end = System.currentTimeMillis();
+
+ /* build the LR parser action and reduce-goto tables */
+ if (opt_do_debug || print_progress)
+ System.err.println(" Filling in tables...");
+ action_table = new parse_action_table();
+ reduce_table = new parse_reduce_table();
+ for (Enumeration st = lalr_state.all(); st.hasMoreElements(); )
+ {
+ lalr_state lst = (lalr_state)st.nextElement();
+ lst.build_table_entries(
+ action_table, reduce_table);
+ }
+
+ table_end = System.currentTimeMillis();
+
+ /* check and warn for non-reduced productions */
+ if (opt_do_debug || print_progress)
+ System.err.println(" Checking for non-reduced productions...");
+ action_table.check_reductions();
+
+ reduce_check_end = System.currentTimeMillis();
+
+ /* if we have more conflicts than we expected issue a message and die */
+ if (emit.num_conflicts > expect_conflicts)
+ {
+ System.err.println("*** More conflicts encountered than expected " +
+ "-- parser generation aborted");
+ lexer.error_count++; // indicate the problem.
+ // we'll die on return, after clean up.
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Call the emit routines necessary to write out the generated parser. */
+ protected static void emit_parser() throws internal_error
+ {
+ emit.symbols(symbol_class_file, include_non_terms, sym_interface);
+ emit.parser(parser_class_file, action_table, reduce_table,
+ start_state.index(), emit.start_production, opt_compact_red,
+ suppress_scanner);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Helper routine to optionally return a plural or non-plural ending.
+ * @param val the numerical value determining plurality.
+ */
+ protected static String plural(int val)
+ {
+ if (val == 1)
+ return "";
+ else
+ return "s";
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit a long summary message to standard error (System.err) which
+ * summarizes what was found in the specification, how many states were
+ * produced, how many conflicts were found, etc. A detailed timing
+ * summary is also produced if it was requested by the user.
+ * @param output_produced did the system get far enough to generate code.
+ */
+ protected static void emit_summary(boolean output_produced)
+ {
+ final_time = System.currentTimeMillis();
+
+ if (no_summary) return;
+
+ System.err.println("------- " + version.title_str +
+ " Parser Generation Summary -------");
+
+ /* error and warning count */
+ System.err.println(" " + lexer.error_count + " error" +
+ plural(lexer.error_count) + " and " + lexer.warning_count +
+ " warning" + plural(lexer.warning_count));
+
+ /* basic stats */
+ System.err.print(" " + terminal.number() + " terminal" +
+ plural(terminal.number()) + ", ");
+ System.err.print(non_terminal.number() + " non-terminal" +
+ plural(non_terminal.number()) + ", and ");
+ System.err.println(production.number() + " production" +
+ plural(production.number()) + " declared, ");
+ System.err.println(" producing " + lalr_state.number() +
+ " unique parse states.");
+
+ /* unused symbols */
+ System.err.println(" " + emit.unused_term + " terminal" +
+ plural(emit.unused_term) + " declared but not used.");
+ System.err.println(" " + emit.unused_non_term + " non-terminal" +
+ plural(emit.unused_term) + " declared but not used.");
+
+ /* productions that didn't reduce */
+ System.err.println(" " + emit.not_reduced + " production" +
+ plural(emit.not_reduced) + " never reduced.");
+
+ /* conflicts */
+ System.err.println(" " + emit.num_conflicts + " conflict" +
+ plural(emit.num_conflicts) + " detected" +
+ " (" + expect_conflicts + " expected).");
+
+ /* code location */
+ if (output_produced)
+ System.err.println(" Code written to \"" + emit.parser_class_name +
+ ".java\", and \"" + emit.symbol_const_class_name + ".java\".");
+ else
+ System.err.println(" No code produced.");
+
+ if (opt_show_timing) show_times();
+
+ System.err.println(
+ "---------------------------------------------------- (" +
+ version.version_str + ")");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce the optional timing summary as part of an overall summary. */
+ protected static void show_times()
+ {
+ long total_time = final_time - start_time;
+
+ System.err.println(". . . . . . . . . . . . . . . . . . . . . . . . . ");
+ System.err.println(" Timing Summary");
+ System.err.println(" Total time "
+ + timestr(final_time-start_time, total_time));
+ System.err.println(" Startup "
+ + timestr(prelim_end-start_time, total_time));
+ System.err.println(" Parse "
+ + timestr(parse_end-prelim_end, total_time) );
+ if (check_end != 0)
+ System.err.println(" Checking "
+ + timestr(check_end-parse_end, total_time));
+ if (check_end != 0 && build_end != 0)
+ System.err.println(" Parser Build "
+ + timestr(build_end-check_end, total_time));
+ if (nullability_end != 0 && check_end != 0)
+ System.err.println(" Nullability "
+ + timestr(nullability_end-check_end, total_time));
+ if (first_end != 0 && nullability_end != 0)
+ System.err.println(" First sets "
+ + timestr(first_end-nullability_end, total_time));
+ if (machine_end != 0 && first_end != 0)
+ System.err.println(" State build "
+ + timestr(machine_end-first_end, total_time));
+ if (table_end != 0 && machine_end != 0)
+ System.err.println(" Table build "
+ + timestr(table_end-machine_end, total_time));
+ if (reduce_check_end != 0 && table_end != 0)
+ System.err.println(" Checking "
+ + timestr(reduce_check_end-table_end, total_time));
+ if (emit_end != 0 && build_end != 0)
+ System.err.println(" Code Output "
+ + timestr(emit_end-build_end, total_time));
+ if (emit.symbols_time != 0)
+ System.err.println(" Symbols "
+ + timestr(emit.symbols_time, total_time));
+ if (emit.parser_time != 0)
+ System.err.println(" Parser class "
+ + timestr(emit.parser_time, total_time));
+ if (emit.action_code_time != 0)
+ System.err.println(" Actions "
+ + timestr(emit.action_code_time, total_time));
+ if (emit.production_table_time != 0)
+ System.err.println(" Prod table "
+ + timestr(emit.production_table_time, total_time));
+ if (emit.action_table_time != 0)
+ System.err.println(" Action tab "
+ + timestr(emit.action_table_time, total_time));
+ if (emit.goto_table_time != 0)
+ System.err.println(" Reduce tab "
+ + timestr(emit.goto_table_time, total_time));
+
+ System.err.println(" Dump Output "
+ + timestr(dump_end-emit_end, total_time));
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Helper routine to format a decimal based display of seconds and
+ * percentage of total time given counts of milliseconds. Note: this
+ * is broken for use with some instances of negative time (since we don't
+ * use any negative time here, we let if be for now).
+ * @param time_val the value being formatted (in ms).
+ * @param total_time total time percentages are calculated against (in ms).
+ */
+ protected static String timestr(long time_val, long total_time)
+ {
+ boolean neg;
+ long ms = 0;
+ long sec = 0;
+ long percent10;
+ String pad;
+
+ /* work with positives only */
+ neg = time_val < 0;
+ if (neg) time_val = -time_val;
+
+ /* pull out seconds and ms */
+ ms = time_val % 1000;
+ sec = time_val / 1000;
+
+ /* construct a pad to blank fill seconds out to 4 places */
+ if (sec < 10)
+ pad = " ";
+ else if (sec < 100)
+ pad = " ";
+ else if (sec < 1000)
+ pad = " ";
+ else
+ pad = "";
+
+ /* calculate 10 times the percentage of total */
+ percent10 = (time_val*1000)/total_time;
+
+ /* build and return the output string */
+ return (neg ? "-" : "") + pad + sec + "." +
+ ((ms%1000)/100) + ((ms%100)/10) + (ms%10) + "sec" +
+ " (" + percent10/10 + "." + percent10%10 + "%)";
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a human readable dump of the grammar. */
+ public static void dump_grammar() throws internal_error
+ {
+ System.err.println("===== Terminals =====");
+ for (int tidx=0, cnt=0; tidx < terminal.number(); tidx++, cnt++)
+ {
+ System.err.print("["+tidx+"]"+terminal.find(tidx).name()+" ");
+ if ((cnt+1) % 5 == 0) System.err.println();
+ }
+ System.err.println();
+ System.err.println();
+
+ System.err.println("===== Non terminals =====");
+ for (int nidx=0, cnt=0; nidx < non_terminal.number(); nidx++, cnt++)
+ {
+ System.err.print("["+nidx+"]"+non_terminal.find(nidx).name()+" ");
+ if ((cnt+1) % 5 == 0) System.err.println();
+ }
+ System.err.println();
+ System.err.println();
+
+
+ System.err.println("===== Productions =====");
+ for (int pidx=0; pidx < production.number(); pidx++)
+ {
+ production prod = production.find(pidx);
+ System.err.print("["+pidx+"] "+prod.lhs().the_symbol().name() + " ::= ");
+ for (int i=0; i<prod.rhs_length(); i++)
+ if (prod.rhs(i).is_action())
+ System.err.print("{action} ");
+ else
+ System.err.print(
+ ((symbol_part)prod.rhs(i)).the_symbol().name() + " ");
+ System.err.println();
+ }
+ System.err.println();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a (semi-) human readable dump of the complete viable prefix
+ * recognition state machine.
+ */
+ public static void dump_machine()
+ {
+ lalr_state ordered[] = new lalr_state[lalr_state.number()];
+
+ /* put the states in sorted order for a nicer display */
+ for (Enumeration s = lalr_state.all(); s.hasMoreElements(); )
+ {
+ lalr_state st = (lalr_state)s.nextElement();
+ ordered[st.index()] = st;
+ }
+
+ System.err.println("===== Viable Prefix Recognizer =====");
+ for (int i = 0; i<lalr_state.number(); i++)
+ {
+ if (ordered[i] == start_state) System.err.print("START ");
+ System.err.println(ordered[i]);
+ System.err.println("-------------------");
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a (semi-) human readable dumps of the parse tables */
+ public static void dump_tables()
+ {
+ System.err.println(action_table);
+ System.err.println(reduce_table);
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
diff --git a/src/java_cup/java_cup/action_part.java b/src/java_cup/java_cup/action_part.java
new file mode 100644
index 0000000..69e98f5
--- /dev/null
+++ b/src/java_cup/java_cup/action_part.java
@@ -0,0 +1,93 @@
+
+package java_cup;
+
+/**
+ * This class represents a part of a production which contains an
+ * action. These are eventually eliminated from productions and converted
+ * to trailing actions by factoring out with a production that derives the
+ * empty string (and ends with this action).
+ *
+ * @see java_cup.production
+ * @version last update: 11/25/95
+ * @author Scott Hudson
+ */
+
+public class action_part extends production_part {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructors ------------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor.
+ * @param code_str string containing the actual user code.
+ */
+ public action_part(String code_str)
+ {
+ super(/* never have a label on code */null);
+ _code_string = code_str;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** String containing code for the action in question. */
+ protected String _code_string;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** String containing code for the action in question. */
+ public String code_string() {return _code_string;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Set the code string. */
+ public void set_code_string(String new_str) {_code_string = new_str;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Override to report this object as an action. */
+ public boolean is_action() { return true; }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison for properly typed object. */
+ public boolean equals(action_part other)
+ {
+ /* compare the strings */
+ return other != null && super.equals(other) &&
+ other.code_string().equals(code_string());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof action_part))
+ return false;
+ else
+ return equals((action_part)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a hash code. */
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ (code_string()==null ? 0 : code_string().hashCode());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ return super.toString() + "{" + code_string() + "}";
+ }
+
+ /*-----------------------------------------------------------*/
+}
diff --git a/src/java_cup/java_cup/action_production.java b/src/java_cup/java_cup/action_production.java
new file mode 100644
index 0000000..3c0845f
--- /dev/null
+++ b/src/java_cup/java_cup/action_production.java
@@ -0,0 +1,39 @@
+
+package java_cup;
+
+/** A specialized version of a production used when we split an existing
+ * production in order to remove an embedded action. Here we keep a bit
+ * of extra bookkeeping so that we know where we came from.
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+
+public class action_production extends production {
+
+ /** Constructor.
+ * @param base the production we are being factored out of.
+ * @param lhs_sym the LHS symbol for this production.
+ * @param rhs_parts array of production parts for the RHS.
+ * @param rhs_len how much of the rhs_parts array is valid.
+ * @param action_str the trailing reduce action for this production.
+ */
+ public action_production(
+ production base,
+ non_terminal lhs_sym,
+ production_part rhs_parts[],
+ int rhs_len,
+ String action_str)
+ throws internal_error
+ {
+ super(lhs_sym, rhs_parts, rhs_len, action_str);
+ _base_production = base;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The production we were taken out of. */
+ protected production _base_production;
+
+ /** The production we were taken out of. */
+ public production base_production() {return _base_production;}
+}
diff --git a/src/java_cup/java_cup/assoc.java b/src/java_cup/java_cup/assoc.java
new file mode 100644
index 0000000..8d0b50e
--- /dev/null
+++ b/src/java_cup/java_cup/assoc.java
@@ -0,0 +1,16 @@
+package java_cup;
+
+/* Defines integers that represent the associativity of terminals
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+
+public class assoc {
+
+ /* various associativities, no_prec being the default value */
+ public final static int left = 0;
+ public final static int right = 1;
+ public final static int nonassoc = 2;
+ public final static int no_prec = -1;
+
+} \ No newline at end of file
diff --git a/src/java_cup/java_cup/emit.java b/src/java_cup/java_cup/emit.java
new file mode 100644
index 0000000..9db9014
--- /dev/null
+++ b/src/java_cup/java_cup/emit.java
@@ -0,0 +1,897 @@
+package java_cup;
+
+import java.io.PrintWriter;
+import java.util.Stack;
+import java.util.Enumeration;
+import java.util.Date;
+
+/**
+ * This class handles emitting generated code for the resulting parser.
+ * The various parse tables must be constructed, etc. before calling any
+ * routines in this class.<p>
+ *
+ * Three classes are produced by this code:
+ * <dl>
+ * <dt> symbol constant class
+ * <dd> this contains constant declarations for each terminal (and
+ * optionally each non-terminal).
+ * <dt> action class
+ * <dd> this non-public class contains code to invoke all the user actions
+ * that were embedded in the parser specification.
+ * <dt> parser class
+ * <dd> the specialized parser class consisting primarily of some user
+ * supplied general and initialization code, and the parse tables.
+ * </dl><p>
+ *
+ * Three parse tables are created as part of the parser class:
+ * <dl>
+ * <dt> production table
+ * <dd> lists the LHS non terminal number, and the length of the RHS of
+ * each production.
+ * <dt> action table
+ * <dd> for each state of the parse machine, gives the action to be taken
+ * (shift, reduce, or error) under each lookahead symbol.<br>
+ * <dt> reduce-goto table
+ * <dd> when a reduce on a given production is taken, the parse stack is
+ * popped back a number of elements corresponding to the RHS of the
+ * production. This reveals a prior state, which we transition out
+ * of under the LHS non terminal symbol for the production (as if we
+ * had seen the LHS symbol rather than all the symbols matching the
+ * RHS). This table is indexed by non terminal numbers and indicates
+ * how to make these transitions.
+ * </dl><p>
+ *
+ * In addition to the method interface, this class maintains a series of
+ * public global variables and flags indicating how misc. parts of the code
+ * and other output is to be produced, and counting things such as number of
+ * conflicts detected (see the source code and public variables below for
+ * more details).<p>
+ *
+ * This class is "static" (contains only static data and methods).<p>
+ *
+ * @see java_cup.main
+ * @version last update: 11/25/95
+ * @author Scott Hudson
+ */
+
+/* Major externally callable routines here include:
+ symbols - emit the symbol constant class
+ parser - emit the parser class
+
+ In addition the following major internal routines are provided:
+ emit_package - emit a package declaration
+ emit_action_code - emit the class containing the user's actions
+ emit_production_table - emit declaration and init for the production table
+ do_action_table - emit declaration and init for the action table
+ do_reduce_table - emit declaration and init for the reduce-goto table
+
+ Finally, this class uses a number of public instance variables to communicate
+ optional parameters and flags used to control how code is generated,
+ as well as to report counts of various things (such as number of conflicts
+ detected). These include:
+
+ prefix - a prefix string used to prefix names that would
+ otherwise "pollute" someone else's name space.
+ package_name - name of the package emitted code is placed in
+ (or null for an unnamed package.
+ symbol_const_class_name - name of the class containing symbol constants.
+ parser_class_name - name of the class for the resulting parser.
+ action_code - user supplied declarations and other code to be
+ placed in action class.
+ parser_code - user supplied declarations and other code to be
+ placed in parser class.
+ init_code - user supplied code to be executed as the parser
+ is being initialized.
+ scan_code - user supplied code to get the next Symbol.
+ start_production - the start production for the grammar.
+ import_list - list of imports for use with action class.
+ num_conflicts - number of conflicts detected.
+ nowarn - true if we are not to issue warning messages.
+ not_reduced - count of number of productions that never reduce.
+ unused_term - count of unused terminal symbols.
+ unused_non_term - count of unused non terminal symbols.
+ *_time - a series of symbols indicating how long various
+ sub-parts of code generation took (used to produce
+ optional time reports in main).
+*/
+
+public class emit {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Only constructor is private so no instances can be created. */
+ private emit() { }
+
+ /*-----------------------------------------------------------*/
+ /*--- Static (Class) Variables ------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The prefix placed on names that pollute someone else's name space. */
+ public static String prefix = "CUP$";
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Package that the resulting code goes into (null is used for unnamed). */
+ public static String package_name = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Name of the generated class for symbol constants. */
+ public static String symbol_const_class_name = "sym";
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Name of the generated parser class. */
+ public static String parser_class_name = "parser";
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** User declarations for direct inclusion in user action class. */
+ public static String action_code = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** User declarations for direct inclusion in parser class. */
+ public static String parser_code = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** User code for user_init() which is called during parser initialization. */
+ public static String init_code = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** User code for scan() which is called to get the next Symbol. */
+ public static String scan_code = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The start production of the grammar. */
+ public static production start_production = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** List of imports (Strings containing class names) to go with actions. */
+ public static Stack import_list = new Stack();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Number of conflict found while building tables. */
+ public static int num_conflicts = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Do we skip warnings? */
+ public static boolean nowarn = false;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of the number on non-reduced productions found. */
+ public static int not_reduced = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of unused terminals. */
+ public static int unused_term = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of unused non terminals. */
+ public static int unused_non_term = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /* Timing values used to produce timing report in main.*/
+
+ /** Time to produce symbol constant class. */
+ public static long symbols_time = 0;
+
+ /** Time to produce parser class. */
+ public static long parser_time = 0;
+
+ /** Time to produce action code class. */
+ public static long action_code_time = 0;
+
+ /** Time to produce the production table. */
+ public static long production_table_time = 0;
+
+ /** Time to produce the action table. */
+ public static long action_table_time = 0;
+
+ /** Time to produce the reduce-goto table. */
+ public static long goto_table_time = 0;
+
+ /* frankf 6/18/96 */
+ protected static boolean _lr_values;
+
+ /** whether or not to emit code for left and right values */
+ public static boolean lr_values() {return _lr_values;}
+ protected static void set_lr_values(boolean b) { _lr_values = b;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Build a string with the standard prefix.
+ * @param str string to prefix.
+ */
+ protected static String pre(String str) {
+ return prefix + parser_class_name + "$" + str;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit a package spec if the user wants one.
+ * @param out stream to produce output on.
+ */
+ protected static void emit_package(PrintWriter out)
+ {
+ /* generate a package spec if we have a name for one */
+ if (package_name != null) {
+ out.println("package " + package_name + ";"); out.println();
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit code for the symbol constant class, optionally including non terms,
+ * if they have been requested.
+ * @param out stream to produce output on.
+ * @param emit_non_terms do we emit constants for non terminals?
+ * @param sym_interface should we emit an interface, rather than a class?
+ */
+ public static void symbols(PrintWriter out,
+ boolean emit_non_terms, boolean sym_interface)
+ {
+ terminal term;
+ non_terminal nt;
+ String class_or_interface = (sym_interface)?"interface":"class";
+
+ long start_time = System.currentTimeMillis();
+
+ /* top of file */
+ out.println();
+ out.println("//----------------------------------------------------");
+ out.println("// The following code was generated by " +
+ version.title_str);
+ out.println("// " + new Date());
+ out.println("//----------------------------------------------------");
+ out.println();
+ emit_package(out);
+
+ /* class header */
+ out.println("/** CUP generated " + class_or_interface +
+ " containing symbol constants. */");
+ out.println("public " + class_or_interface + " " +
+ symbol_const_class_name + " {");
+
+ out.println(" /* terminals */");
+
+ /* walk over the terminals */ /* later might sort these */
+ for (Enumeration e = terminal.all(); e.hasMoreElements(); )
+ {
+ term = (terminal)e.nextElement();
+
+ /* output a constant decl for the terminal */
+ out.println(" public static final int " + term.name() + " = " +
+ term.index() + ";");
+ }
+
+ /* do the non terminals if they want them (parser doesn't need them) */
+ if (emit_non_terms)
+ {
+ out.println();
+ out.println(" /* non terminals */");
+
+ /* walk over the non terminals */ /* later might sort these */
+ for (Enumeration e = non_terminal.all(); e.hasMoreElements(); )
+ {
+ nt = (non_terminal)e.nextElement();
+
+ /* output a constant decl for the terminal */
+ out.println(" static final int " + nt.name() + " = " +
+ nt.index() + ";");
+ }
+ }
+
+ /* end of class */
+ out.println("}");
+ out.println();
+
+ symbols_time = System.currentTimeMillis() - start_time;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit code for the non-public class holding the actual action code.
+ * @param out stream to produce output on.
+ * @param start_prod the start production of the grammar.
+ */
+ protected static void emit_action_code(PrintWriter out, production start_prod)
+ throws internal_error
+ {
+ production prod;
+
+ long start_time = System.currentTimeMillis();
+
+ /* class header */
+ out.println();
+ out.println(
+ "/** Cup generated class to encapsulate user supplied action code.*/"
+ );
+ out.println("class " + pre("actions") + " {");
+
+ /* user supplied code */
+ if (action_code != null)
+ {
+ out.println();
+ out.println(action_code);
+ }
+
+ /* field for parser object */
+ out.println(" private final "+parser_class_name+" parser;");
+
+ /* constructor */
+ out.println();
+ out.println(" /** Constructor */");
+ out.println(" " + pre("actions") + "("+parser_class_name+" parser) {");
+ out.println(" this.parser = parser;");
+ out.println(" }");
+
+ /* action method head */
+ out.println();
+ out.println(" /** Method with the actual generated action code. */");
+ out.println(" public final java_cup.runtime.Symbol " +
+ pre("do_action") + "(");
+ out.println(" int " + pre("act_num,"));
+ out.println(" java_cup.runtime.lr_parser " + pre("parser,"));
+ out.println(" java.util.Stack " + pre("stack,"));
+ out.println(" int " + pre("top)"));
+ out.println(" throws java.lang.Exception");
+ out.println(" {");
+
+ /* declaration of result symbol */
+ /* New declaration!! now return Symbol
+ 6/13/96 frankf */
+ out.println(" /* Symbol object for return from actions */");
+ out.println(" java_cup.runtime.Symbol " + pre("result") + ";");
+ out.println();
+
+ /* switch top */
+ out.println(" /* select the action based on the action number */");
+ out.println(" switch (" + pre("act_num") + ")");
+ out.println(" {");
+
+ /* emit action code for each production as a separate case */
+ for (Enumeration p = production.all(); p.hasMoreElements(); )
+ {
+ prod = (production)p.nextElement();
+
+ /* case label */
+ out.println(" /*. . . . . . . . . . . . . . . . . . . .*/");
+ out.println(" case " + prod.index() + ": // " +
+ prod.to_simple_string());
+
+ /* give them their own block to work in */
+ out.println(" {");
+
+ /* create the result symbol */
+ /*make the variable RESULT which will point to the new Symbol (see below)
+ and be changed by action code
+ 6/13/96 frankf */
+ out.println(" " + prod.lhs().the_symbol().stack_type() +
+ " RESULT = null;");
+
+ /* Add code to propagate RESULT assignments that occur in
+ * action code embedded in a production (ie, non-rightmost
+ * action code). 24-Mar-1998 CSA
+ */
+ for (int i=0; i<prod.rhs_length(); i++) {
+ // only interested in non-terminal symbols.
+ if (!(prod.rhs(i) instanceof symbol_part)) continue;
+ symbol s = ((symbol_part)prod.rhs(i)).the_symbol();
+ if (!(s instanceof non_terminal)) continue;
+ // skip this non-terminal unless it corresponds to
+ // an embedded action production.
+ if (((non_terminal)s).is_embedded_action == false) continue;
+ // OK, it fits. Make a conditional assignment to RESULT.
+ int index = prod.rhs_length() - i - 1; // last rhs is on top.
+ out.println(" " + "// propagate RESULT from " +
+ s.name());
+ out.println(" " + "if ( " +
+ "((java_cup.runtime.Symbol) " + emit.pre("stack") + ".elementAt("
+ + emit.pre("top") + "-" + index + ")).value != null )");
+ out.println(" " + "RESULT = " +
+ "(" + prod.lhs().the_symbol().stack_type() + ") " +
+ "((java_cup.runtime.Symbol) " + emit.pre("stack") + ".elementAt("
+ + emit.pre("top") + "-" + index + ")).value;");
+ }
+
+ /* if there is an action string, emit it */
+ if (prod.action() != null && prod.action().code_string() != null &&
+ !prod.action().equals(""))
+ out.println(prod.action().code_string());
+
+ /* here we have the left and right values being propagated.
+ must make this a command line option.
+ frankf 6/18/96 */
+
+ /* Create the code that assigns the left and right values of
+ the new Symbol that the production is reducing to */
+ if (emit.lr_values()) {
+ int loffset;
+ String leftstring, rightstring;
+ int roffset = 0;
+ rightstring = "((java_cup.runtime.Symbol)" + emit.pre("stack") + ".elementAt(" +
+ emit.pre("top") + "-" + roffset + ")).right";
+ if (prod.rhs_length() == 0)
+ leftstring = rightstring;
+ else {
+ loffset = prod.rhs_length() - 1;
+ leftstring = "((java_cup.runtime.Symbol)" + emit.pre("stack") + ".elementAt(" +
+ emit.pre("top") + "-" + loffset + ")).left";
+ }
+ out.println(" " + pre("result") + " = new java_cup.runtime.Symbol(" +
+ prod.lhs().the_symbol().index() + "/*" +
+ prod.lhs().the_symbol().name() + "*/" +
+ ", " + leftstring + ", " + rightstring + ", RESULT);");
+ } else {
+ out.println(" " + pre("result") + " = new java_cup.runtime.Symbol(" +
+ prod.lhs().the_symbol().index() + "/*" +
+ prod.lhs().the_symbol().name() + "*/" +
+ ", RESULT);");
+ }
+
+ /* end of their block */
+ out.println(" }");
+
+ /* if this was the start production, do action for accept */
+ if (prod == start_prod)
+ {
+ out.println(" /* ACCEPT */");
+ out.println(" " + pre("parser") + ".done_parsing();");
+ }
+
+ /* code to return lhs symbol */
+ out.println(" return " + pre("result") + ";");
+ out.println();
+ }
+
+ /* end of switch */
+ out.println(" /* . . . . . .*/");
+ out.println(" default:");
+ out.println(" throw new Exception(");
+ out.println(" \"Invalid action number found in " +
+ "internal parse table\");");
+ out.println();
+ out.println(" }");
+
+ /* end of method */
+ out.println(" }");
+
+ /* end of class */
+ out.println("}");
+ out.println();
+
+ action_code_time = System.currentTimeMillis() - start_time;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit the production table.
+ * @param out stream to produce output on.
+ */
+ protected static void emit_production_table(PrintWriter out)
+ {
+ production all_prods[];
+ production prod;
+
+ long start_time = System.currentTimeMillis();
+
+ /* collect up the productions in order */
+ all_prods = new production[production.number()];
+ for (Enumeration p = production.all(); p.hasMoreElements(); )
+ {
+ prod = (production)p.nextElement();
+ all_prods[prod.index()] = prod;
+ }
+
+ // make short[][]
+ short[][] prod_table = new short[production.number()][2];
+ for (int i = 0; i<production.number(); i++)
+ {
+ prod = all_prods[i];
+ // { lhs symbol , rhs size }
+ prod_table[i][0] = (short) prod.lhs().the_symbol().index();
+ prod_table[i][1] = (short) prod.rhs_length();
+ }
+ /* do the top of the table */
+ out.println();
+ out.println(" /** Production table. */");
+ out.println(" protected static final short _production_table[][] = ");
+ out.print (" unpackFromStrings(");
+ do_table_as_string(out, prod_table);
+ out.println(");");
+
+ /* do the public accessor method */
+ out.println();
+ out.println(" /** Access to production table. */");
+ out.println(" public short[][] production_table() " +
+ "{return _production_table;}");
+
+ production_table_time = System.currentTimeMillis() - start_time;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit the action table.
+ * @param out stream to produce output on.
+ * @param act_tab the internal representation of the action table.
+ * @param compact_reduces do we use the most frequent reduce as default?
+ */
+ protected static void do_action_table(
+ PrintWriter out,
+ parse_action_table act_tab,
+ boolean compact_reduces)
+ throws internal_error
+ {
+ parse_action_row row;
+ parse_action act;
+ int red;
+
+ long start_time = System.currentTimeMillis();
+
+ /* collect values for the action table */
+ short[][] action_table = new short[act_tab.num_states()][];
+ /* do each state (row) of the action table */
+ for (int i = 0; i < act_tab.num_states(); i++)
+ {
+ /* get the row */
+ row = act_tab.under_state[i];
+
+ /* determine the default for the row */
+ if (compact_reduces)
+ row.compute_default();
+ else
+ row.default_reduce = -1;
+
+ /* make temporary table for the row. */
+ short[] temp_table = new short[2*row.size()];
+ int nentries = 0;
+
+ /* do each column */
+ for (int j = 0; j < row.size(); j++)
+ {
+ /* extract the action from the table */
+ act = row.under_term[j];
+
+ /* skip error entries these are all defaulted out */
+ if (act.kind() != parse_action.ERROR)
+ {
+ /* first put in the symbol index, then the actual entry */
+
+ /* shifts get positive entries of state number + 1 */
+ if (act.kind() == parse_action.SHIFT)
+ {
+ /* make entry */
+ temp_table[nentries++] = (short) j;
+ temp_table[nentries++] = (short)
+ (((shift_action)act).shift_to().index() + 1);
+ }
+
+ /* reduce actions get negated entries of production# + 1 */
+ else if (act.kind() == parse_action.REDUCE)
+ {
+ /* if its the default entry let it get defaulted out */
+ red = ((reduce_action)act).reduce_with().index();
+ if (red != row.default_reduce) {
+ /* make entry */
+ temp_table[nentries++] = (short) j;
+ temp_table[nentries++] = (short) (-(red+1));
+ }
+ } else if (act.kind() == parse_action.NONASSOC)
+ {
+ /* do nothing, since we just want a syntax error */
+ }
+ /* shouldn't be anything else */
+ else
+ throw new internal_error("Unrecognized action code " +
+ act.kind() + " found in parse table");
+ }
+ }
+
+ /* now we know how big to make the row */
+ action_table[i] = new short[nentries + 2];
+ System.arraycopy(temp_table, 0, action_table[i], 0, nentries);
+
+ /* finish off the row with a default entry */
+ action_table[i][nentries++] = -1;
+ if (row.default_reduce != -1)
+ action_table[i][nentries++] = (short) (-(row.default_reduce+1));
+ else
+ action_table[i][nentries++] = 0;
+ }
+
+ /* finish off the init of the table */
+ out.println();
+ out.println(" /** Parse-action table. */");
+ out.println(" protected static final short[][] _action_table = ");
+ out.print (" unpackFromStrings(");
+ do_table_as_string(out, action_table);
+ out.println(");");
+
+ /* do the public accessor method */
+ out.println();
+ out.println(" /** Access to parse-action table. */");
+ out.println(" public short[][] action_table() {return _action_table;}");
+
+ action_table_time = System.currentTimeMillis() - start_time;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit the reduce-goto table.
+ * @param out stream to produce output on.
+ * @param red_tab the internal representation of the reduce-goto table.
+ */
+ protected static void do_reduce_table(
+ PrintWriter out,
+ parse_reduce_table red_tab)
+ {
+ lalr_state goto_st;
+ parse_action act;
+
+ long start_time = System.currentTimeMillis();
+
+ /* collect values for reduce-goto table */
+ short[][] reduce_goto_table = new short[red_tab.num_states()][];
+ /* do each row of the reduce-goto table */
+ for (int i=0; i<red_tab.num_states(); i++)
+ {
+ /* make temporary table for the row. */
+ short[] temp_table = new short[2*red_tab.under_state[i].size()];
+ int nentries = 0;
+ /* do each entry in the row */
+ for (int j=0; j<red_tab.under_state[i].size(); j++)
+ {
+ /* get the entry */
+ goto_st = red_tab.under_state[i].under_non_term[j];
+
+ /* if we have none, skip it */
+ if (goto_st != null)
+ {
+ /* make entries for the index and the value */
+ temp_table[nentries++] = (short) j;
+ temp_table[nentries++] = (short) goto_st.index();
+ }
+ }
+ /* now we know how big to make the row. */
+ reduce_goto_table[i] = new short[nentries+2];
+ System.arraycopy(temp_table, 0, reduce_goto_table[i], 0, nentries);
+
+ /* end row with default value */
+ reduce_goto_table[i][nentries++] = -1;
+ reduce_goto_table[i][nentries++] = -1;
+ }
+
+ /* emit the table. */
+ out.println();
+ out.println(" /** <code>reduce_goto</code> table. */");
+ out.println(" protected static final short[][] _reduce_table = ");
+ out.print (" unpackFromStrings(");
+ do_table_as_string(out, reduce_goto_table);
+ out.println(");");
+
+ /* do the public accessor method */
+ out.println();
+ out.println(" /** Access to <code>reduce_goto</code> table. */");
+ out.println(" public short[][] reduce_table() {return _reduce_table;}");
+ out.println();
+
+ goto_table_time = System.currentTimeMillis() - start_time;
+ }
+
+ // print a string array encoding the given short[][] array.
+ protected static void do_table_as_string(PrintWriter out, short[][] sa) {
+ out.println("new String[] {");
+ out.print(" \"");
+ int nchar=0, nbytes=0;
+ nbytes+=do_escaped(out, (char)(sa.length>>16));
+ nchar =do_newline(out, nchar, nbytes);
+ nbytes+=do_escaped(out, (char)(sa.length&0xFFFF));
+ nchar =do_newline(out, nchar, nbytes);
+ for (int i=0; i<sa.length; i++) {
+ nbytes+=do_escaped(out, (char)(sa[i].length>>16));
+ nchar =do_newline(out, nchar, nbytes);
+ nbytes+=do_escaped(out, (char)(sa[i].length&0xFFFF));
+ nchar =do_newline(out, nchar, nbytes);
+ for (int j=0; j<sa[i].length; j++) {
+ // contents of string are (value+2) to allow for common -1, 0 cases
+ // (UTF-8 encoding is most efficient for 0<c<0x80)
+ nbytes+=do_escaped(out, (char)(2+sa[i][j]));
+ nchar =do_newline(out, nchar, nbytes);
+ }
+ }
+ out.print("\" }");
+ }
+ // split string if it is very long; start new line occasionally for neatness
+ protected static int do_newline(PrintWriter out, int nchar, int nbytes) {
+ if (nbytes > 65500) { out.println("\", "); out.print(" \""); }
+ else if (nchar > 11) { out.println("\" +"); out.print(" \""); }
+ else return nchar+1;
+ return 0;
+ }
+ // output an escape sequence for the given character code.
+ protected static int do_escaped(PrintWriter out, char c) {
+ StringBuffer escape = new StringBuffer();
+ if (c <= 0xFF) {
+ escape.append(Integer.toOctalString(c));
+ while(escape.length() < 3) escape.insert(0, '0');
+ } else {
+ escape.append(Integer.toHexString(c));
+ while(escape.length() < 4) escape.insert(0, '0');
+ escape.insert(0, 'u');
+ }
+ escape.insert(0, '\\');
+ out.print(escape.toString());
+
+ // return number of bytes this takes up in UTF-8 encoding.
+ if (c == 0) return 2;
+ if (c >= 0x01 && c <= 0x7F) return 1;
+ if (c >= 0x80 && c <= 0x7FF) return 2;
+ return 3;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit the parser subclass with embedded tables.
+ * @param out stream to produce output on.
+ * @param action_table internal representation of the action table.
+ * @param reduce_table internal representation of the reduce-goto table.
+ * @param start_st start state of the parse machine.
+ * @param start_prod start production of the grammar.
+ * @param compact_reduces do we use most frequent reduce as default?
+ * @param suppress_scanner should scanner be suppressed for compatibility?
+ */
+ public static void parser(
+ PrintWriter out,
+ parse_action_table action_table,
+ parse_reduce_table reduce_table,
+ int start_st,
+ production start_prod,
+ boolean compact_reduces,
+ boolean suppress_scanner)
+ throws internal_error
+ {
+ long start_time = System.currentTimeMillis();
+
+ /* top of file */
+ out.println();
+ out.println("//----------------------------------------------------");
+ out.println("// The following code was generated by " +
+ version.title_str);
+ out.println("// " + new Date());
+ out.println("//----------------------------------------------------");
+ out.println();
+ emit_package(out);
+
+ /* user supplied imports */
+ for (int i = 0; i < import_list.size(); i++)
+ out.println("import " + import_list.elementAt(i) + ";");
+
+ /* class header */
+ out.println();
+ out.println("/** "+version.title_str+" generated parser.");
+ out.println(" * @version " + new Date());
+ out.println(" */");
+ out.println("public class " + parser_class_name +
+ " extends java_cup.runtime.lr_parser {");
+
+ /* constructors [CSA/davidm, 24-jul-99] */
+ out.println();
+ out.println(" /** Default constructor. */");
+ out.println(" public " + parser_class_name + "() {super();}");
+ if (!suppress_scanner) {
+ out.println();
+ out.println(" /** Constructor which sets the default scanner. */");
+ out.println(" public " + parser_class_name +
+ "(java_cup.runtime.Scanner s) {super(s);}");
+ }
+
+ /* emit the various tables */
+ emit_production_table(out);
+ do_action_table(out, action_table, compact_reduces);
+ do_reduce_table(out, reduce_table);
+
+ /* instance of the action encapsulation class */
+ out.println(" /** Instance of action encapsulation class. */");
+ out.println(" protected " + pre("actions") + " action_obj;");
+ out.println();
+
+ /* action object initializer */
+ out.println(" /** Action encapsulation object initializer. */");
+ out.println(" protected void init_actions()");
+ out.println(" {");
+ out.println(" action_obj = new " + pre("actions") + "(this);");
+ out.println(" }");
+ out.println();
+
+ /* access to action code */
+ out.println(" /** Invoke a user supplied parse action. */");
+ out.println(" public java_cup.runtime.Symbol do_action(");
+ out.println(" int act_num,");
+ out.println(" java_cup.runtime.lr_parser parser,");
+ out.println(" java.util.Stack stack,");
+ out.println(" int top)");
+ out.println(" throws java.lang.Exception");
+ out.println(" {");
+ out.println(" /* call code in generated class */");
+ out.println(" return action_obj." + pre("do_action(") +
+ "act_num, parser, stack, top);");
+ out.println(" }");
+ out.println("");
+
+
+ /* method to tell the parser about the start state */
+ out.println(" /** Indicates start state. */");
+ out.println(" public int start_state() {return " + start_st + ";}");
+
+ /* method to indicate start production */
+ out.println(" /** Indicates start production. */");
+ out.println(" public int start_production() {return " +
+ start_production.index() + ";}");
+ out.println();
+
+ /* methods to indicate EOF and error symbol indexes */
+ out.println(" /** <code>EOF</code> Symbol index. */");
+ out.println(" public int EOF_sym() {return " + terminal.EOF.index() +
+ ";}");
+ out.println();
+ out.println(" /** <code>error</code> Symbol index. */");
+ out.println(" public int error_sym() {return " + terminal.error.index() +
+ ";}");
+ out.println();
+
+ /* user supplied code for user_init() */
+ if (init_code != null)
+ {
+ out.println();
+ out.println(" /** User initialization code. */");
+ out.println(" public void user_init() throws java.lang.Exception");
+ out.println(" {");
+ out.println(init_code);
+ out.println(" }");
+ }
+
+ /* user supplied code for scan */
+ if (scan_code != null)
+ {
+ out.println();
+ out.println(" /** Scan to get the next Symbol. */");
+ out.println(" public java_cup.runtime.Symbol scan()");
+ out.println(" throws java.lang.Exception");
+ out.println(" {");
+ out.println(scan_code);
+ out.println(" }");
+ }
+
+ /* user supplied code */
+ if (parser_code != null)
+ {
+ out.println();
+ out.println(parser_code);
+ }
+
+ /* end of class */
+ out.println("}");
+
+ /* put out the action code class */
+ emit_action_code(out, start_prod);
+
+ parser_time = System.currentTimeMillis() - start_time;
+ }
+
+ /*-----------------------------------------------------------*/
+}
diff --git a/src/java_cup/java_cup/internal_error.java b/src/java_cup/java_cup/internal_error.java
new file mode 100644
index 0000000..4d3e7c2
--- /dev/null
+++ b/src/java_cup/java_cup/internal_error.java
@@ -0,0 +1,22 @@
+
+package java_cup;
+
+/** Exception subclass for reporting internal errors in JavaCup. */
+public class internal_error extends Exception
+ {
+ /** Constructor with a message */
+ public internal_error(String msg)
+ {
+ super(msg);
+ }
+
+ /** Method called to do a forced error exit on an internal error
+ for cases when we can't actually throw the exception. */
+ public void crash()
+ {
+ System.err.println("JavaCUP Fatal Internal Error Detected");
+ System.err.println(getMessage());
+ printStackTrace();
+ System.exit(-1);
+ }
+ }
diff --git a/src/java_cup/java_cup/lalr_item.java b/src/java_cup/java_cup/lalr_item.java
new file mode 100644
index 0000000..fe92054
--- /dev/null
+++ b/src/java_cup/java_cup/lalr_item.java
@@ -0,0 +1,330 @@
+package java_cup;
+
+import java.util.Stack;
+import java.util.Enumeration;
+
+/** This class represents an LALR item. Each LALR item consists of
+ * a production, a "dot" at a position within that production, and
+ * a set of lookahead symbols (terminal). (The first two of these parts
+ * are provide by the super class). An item is designed to represent a
+ * configuration that the parser may be in. For example, an item of the
+ * form: <pre>
+ * [A ::= B * C d E , {a,b,c}]
+ * </pre>
+ * indicates that the parser is in the middle of parsing the production <pre>
+ * A ::= B C d E
+ * </pre>
+ * that B has already been parsed, and that we will expect to see a lookahead
+ * of either a, b, or c once the complete RHS of this production has been
+ * found.<p>
+ *
+ * Items may initially be missing some items from their lookahead sets.
+ * Links are maintained from each item to the set of items that would need
+ * to be updated if symbols are added to its lookahead set. During
+ * "lookahead propagation", we add symbols to various lookahead sets and
+ * propagate these changes across these dependency links as needed.
+ *
+ * @see java_cup.lalr_item_set
+ * @see java_cup.lalr_state
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class lalr_item extends lr_item_core {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param prod the production for the item.
+ * @param pos the position of the "dot" within the production.
+ * @param look the set of lookahead symbols.
+ */
+ public lalr_item(production prod, int pos, terminal_set look)
+ throws internal_error
+ {
+ super(prod, pos);
+ _lookahead = look;
+ _propagate_items = new Stack();
+ needs_propagation = true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with default position (dot at start).
+ * @param prod the production for the item.
+ * @param look the set of lookahead symbols.
+ */
+ public lalr_item(production prod, terminal_set look) throws internal_error
+ {
+ this(prod,0,look);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with default position and empty lookahead set.
+ * @param prod the production for the item.
+ */
+ public lalr_item(production prod) throws internal_error
+ {
+ this(prod,0,new terminal_set());
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The lookahead symbols of the item. */
+ protected terminal_set _lookahead;
+
+ /** The lookahead symbols of the item. */
+ public terminal_set lookahead() {return _lookahead;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Links to items that the lookahead needs to be propagated to. */
+ protected Stack _propagate_items;
+
+ /** Links to items that the lookahead needs to be propagated to */
+ public Stack propagate_items() {return _propagate_items;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Flag to indicate that this item needs to propagate its lookahead
+ * (whether it has changed or not).
+ */
+ protected boolean needs_propagation;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a new item to the set of items we propagate to. */
+ public void add_propagate(lalr_item prop_to)
+ {
+ _propagate_items.push(prop_to);
+ needs_propagation = true;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Propagate incoming lookaheads through this item to others need to
+ * be changed.
+ * @params incoming symbols to potentially be added to lookahead of this item.
+ */
+ public void propagate_lookaheads(terminal_set incoming) throws internal_error
+ {
+ boolean change = false;
+
+ /* if we don't need to propagate, then bail out now */
+ if (!needs_propagation && (incoming == null || incoming.empty()))
+ return;
+
+ /* if we have null incoming, treat as an empty set */
+ if (incoming != null)
+ {
+ /* add the incoming to the lookahead of this item */
+ change = lookahead().add(incoming);
+ }
+
+ /* if we changed or need it anyway, propagate across our links */
+ if (change || needs_propagation)
+ {
+ /* don't need to propagate again */
+ needs_propagation = false;
+
+ /* propagate our lookahead into each item we are linked to */
+ for (int i = 0; i < propagate_items().size(); i++)
+ ((lalr_item)propagate_items().elementAt(i))
+ .propagate_lookaheads(lookahead());
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce the new lalr_item that results from shifting the dot one position
+ * to the right.
+ */
+ public lalr_item shift() throws internal_error
+ {
+ lalr_item result;
+
+ /* can't shift if we have dot already at the end */
+ if (dot_at_end())
+ throw new internal_error("Attempt to shift past end of an lalr_item");
+
+ /* create the new item w/ the dot shifted by one */
+ result = new lalr_item(the_production(), dot_pos()+1,
+ new terminal_set(lookahead()));
+
+ /* change in our lookahead needs to be propagated to this item */
+ add_propagate(result);
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Calculate lookahead representing symbols that could appear after the
+ * symbol that the dot is currently in front of. Note: this routine must
+ * not be invoked before first sets and nullability has been calculated
+ * for all non terminals.
+ */
+ public terminal_set calc_lookahead(terminal_set lookahead_after)
+ throws internal_error
+ {
+ terminal_set result;
+ int pos;
+ production_part part;
+ symbol sym;
+
+ /* sanity check */
+ if (dot_at_end())
+ throw new internal_error(
+ "Attempt to calculate a lookahead set with a completed item");
+
+ /* start with an empty result */
+ result = new terminal_set();
+
+ /* consider all nullable symbols after the one to the right of the dot */
+ for (pos = dot_pos()+1; pos < the_production().rhs_length(); pos++)
+ {
+ part = the_production().rhs(pos);
+
+ /* consider what kind of production part it is -- skip actions */
+ if (!part.is_action())
+ {
+ sym = ((symbol_part)part).the_symbol();
+
+ /* if its a terminal add it in and we are done */
+ if (!sym.is_non_term())
+ {
+ result.add((terminal)sym);
+ return result;
+ }
+ else
+ {
+ /* otherwise add in first set of the non terminal */
+ result.add(((non_terminal)sym).first_set());
+
+ /* if its nullable we continue adding, if not, we are done */
+ if (!((non_terminal)sym).nullable())
+ return result;
+ }
+ }
+ }
+
+ /* if we get here everything past the dot was nullable
+ we add in the lookahead for after the production and we are done */
+ result.add(lookahead_after);
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if everything from the symbol one beyond the dot all the
+ * way to the end of the right hand side is nullable. This would indicate
+ * that the lookahead of this item must be included in the lookaheads of
+ * all items produced as a closure of this item. Note: this routine should
+ * not be invoked until after first sets and nullability have been
+ * calculated for all non terminals.
+ */
+ public boolean lookahead_visible() throws internal_error
+ {
+ production_part part;
+ symbol sym;
+
+ /* if the dot is at the end, we have a problem, but the cleanest thing
+ to do is just return true. */
+ if (dot_at_end()) return true;
+
+ /* walk down the rhs and bail if we get a non-nullable symbol */
+ for (int pos = dot_pos() + 1; pos < the_production().rhs_length(); pos++)
+ {
+ part = the_production().rhs(pos);
+
+ /* skip actions */
+ if (!part.is_action())
+ {
+ sym = ((symbol_part)part).the_symbol();
+
+ /* if its a terminal we fail */
+ if (!sym.is_non_term()) return false;
+
+ /* if its not nullable we fail */
+ if (!((non_terminal)sym).nullable()) return false;
+ }
+ }
+
+ /* if we get here its all nullable */
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison -- here we only require the cores to be equal since
+ * we need to do sets of items based only on core equality (ignoring
+ * lookahead sets).
+ */
+ public boolean equals(lalr_item other)
+ {
+ if (other == null) return false;
+ return super.equals(other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof lalr_item))
+ return false;
+ else
+ return equals((lalr_item)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return a hash code -- here we only hash the core since we only test core
+ * matching in LALR items.
+ */
+ public int hashCode()
+ {
+ return super.hashCode();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to string. */
+ public String toString()
+ {
+ String result = "";
+
+ // additional output for debugging:
+ // result += "(" + obj_hash() + ")";
+ result += "[";
+ result += super.toString();
+ result += ", ";
+ if (lookahead() != null)
+ {
+ result += "{";
+ for (int t = 0; t < terminal.number(); t++)
+ if (lookahead().contains(t))
+ result += terminal.find(t).name() + " ";
+ result += "}";
+ }
+ else
+ result += "NULL LOOKAHEAD!!";
+ result += "]";
+
+ // additional output for debugging:
+ // result += " -> ";
+ // for (int i = 0; i<propagate_items().size(); i++)
+ // result+=((lalr_item)(propagate_items().elementAt(i))).obj_hash()+" ";
+ //
+ // if (needs_propagation) result += " NP";
+
+ return result;
+ }
+ /*-----------------------------------------------------------*/
+}
diff --git a/src/java_cup/java_cup/lalr_item_set.java b/src/java_cup/java_cup/lalr_item_set.java
new file mode 100644
index 0000000..233a68f
--- /dev/null
+++ b/src/java_cup/java_cup/lalr_item_set.java
@@ -0,0 +1,371 @@
+
+package java_cup;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/** This class represents a set of LALR items. For purposes of building
+ * these sets, items are considered unique only if they have unique cores
+ * (i.e., ignoring differences in their lookahead sets).<p>
+ *
+ * This class provides fairly conventional set oriented operations (union,
+ * sub/super-set tests, etc.), as well as an LALR "closure" operation (see
+ * compute_closure()).
+ *
+ * @see java_cup.lalr_item
+ * @see java_cup.lalr_state
+ * @version last updated: 3/6/96
+ * @author Scott Hudson
+ */
+
+public class lalr_item_set {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constructor for an empty set. */
+ public lalr_item_set() { }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor for cloning from another set.
+ * @param other indicates set we should copy from.
+ */
+ public lalr_item_set(lalr_item_set other)
+ throws internal_error
+ {
+ not_null(other);
+ _all = (Hashtable)other._all.clone();
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** A hash table to implement the set. We store the items using themselves
+ * as keys.
+ */
+ protected Hashtable _all = new Hashtable(11);
+
+ /** Access to all elements of the set. */
+ public Enumeration all() {return _all.elements();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Cached hashcode for this set. */
+ protected Integer hashcode_cache = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Size of the set */
+ public int size() {return _all.size();}
+
+ /*-----------------------------------------------------------*/
+ /*--- Set Operation Methods ---------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Does the set contain a particular item?
+ * @param itm the item in question.
+ */
+ public boolean contains(lalr_item itm) {return _all.containsKey(itm);}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return the item in the set matching a particular item (or null if not
+ * found)
+ * @param itm the item we are looking for.
+ */
+ public lalr_item find(lalr_item itm) {return (lalr_item)_all.get(itm);}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Is this set an (improper) subset of another?
+ * @param other the other set in question.
+ */
+ public boolean is_subset_of(lalr_item_set other) throws internal_error
+ {
+ not_null(other);
+
+ /* walk down our set and make sure every element is in the other */
+ for (Enumeration e = all(); e.hasMoreElements(); )
+ if (!other.contains((lalr_item)e.nextElement()))
+ return false;
+
+ /* they were all there */
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Is this set an (improper) superset of another?
+ * @param other the other set in question.
+ */
+ public boolean is_superset_of(lalr_item_set other) throws internal_error
+ {
+ not_null(other);
+ return other.is_subset_of(this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a singleton item, merging lookahead sets if the item is already
+ * part of the set. returns the element of the set that was added or
+ * merged into.
+ * @param itm the item being added.
+ */
+ public lalr_item add(lalr_item itm) throws internal_error
+ {
+ lalr_item other;
+
+ not_null(itm);
+
+ /* see if an item with a matching core is already there */
+ other = (lalr_item)_all.get(itm);
+
+ /* if so, merge this lookahead into the original and leave it */
+ if (other != null)
+ {
+ other.lookahead().add(itm.lookahead());
+ return other;
+ }
+ /* otherwise we just go in the set */
+ else
+ {
+ /* invalidate cached hashcode */
+ hashcode_cache = null;
+
+ _all.put(itm,itm);
+ return itm;
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove a single item if it is in the set.
+ * @param itm the item to remove.
+ */
+ public void remove(lalr_item itm) throws internal_error
+ {
+ not_null(itm);
+
+ /* invalidate cached hashcode */
+ hashcode_cache = null;
+
+ /* remove it from hash table implementing set */
+ _all.remove(itm);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a complete set, merging lookaheads where items are already in
+ * the set
+ * @param other the set to be added.
+ */
+ public void add(lalr_item_set other) throws internal_error
+ {
+ not_null(other);
+
+ /* walk down the other set and do the adds individually */
+ for (Enumeration e = other.all(); e.hasMoreElements(); )
+ add((lalr_item)e.nextElement());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove (set subtract) a complete set.
+ * @param other the set to remove.
+ */
+ public void remove(lalr_item_set other) throws internal_error
+ {
+ not_null(other);
+
+ /* walk down the other set and do the removes individually */
+ for (Enumeration e = other.all(); e.hasMoreElements(); )
+ remove((lalr_item)e.nextElement());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove and return one item from the set (done in hash order). */
+ public lalr_item get_one() throws internal_error
+ {
+ Enumeration the_set;
+ lalr_item result;
+
+ the_set = all();
+ if (the_set.hasMoreElements())
+ {
+ result = (lalr_item)the_set.nextElement();
+ remove(result);
+ return result;
+ }
+ else
+ return null;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Helper function for null test. Throws an interal_error exception if its
+ * parameter is null.
+ * @param obj the object we are testing.
+ */
+ protected void not_null(Object obj) throws internal_error
+ {
+ if (obj == null)
+ throw new internal_error("Null object used in set operation");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute the closure of the set using the LALR closure rules. Basically
+ * for every item of the form: <pre>
+ * [L ::= a *N alpha, l]
+ * </pre>
+ * (where N is a a non terminal and alpha is a string of symbols) make
+ * sure there are also items of the form: <pre>
+ * [N ::= *beta, first(alpha l)]
+ * </pre>
+ * corresponding to each production of N. Items with identical cores but
+ * differing lookahead sets are merged by creating a new item with the same
+ * core and the union of the lookahead sets (the LA in LALR stands for
+ * "lookahead merged" and this is where the merger is). This routine
+ * assumes that nullability and first sets have been computed for all
+ * productions before it is called.
+ */
+ public void compute_closure()
+ throws internal_error
+ {
+ lalr_item_set consider;
+ lalr_item itm, new_itm, add_itm;
+ non_terminal nt;
+ terminal_set new_lookaheads;
+ Enumeration p;
+ production prod;
+ boolean need_prop;
+
+
+
+ /* invalidate cached hashcode */
+ hashcode_cache = null;
+
+ /* each current element needs to be considered */
+ consider = new lalr_item_set(this);
+
+ /* repeat this until there is nothing else to consider */
+ while (consider.size() > 0)
+ {
+ /* get one item to consider */
+ itm = consider.get_one();
+
+ /* do we have a dot before a non terminal */
+ nt = itm.dot_before_nt();
+ if (nt != null)
+ {
+ /* create the lookahead set based on first after dot */
+ new_lookaheads = itm.calc_lookahead(itm.lookahead());
+
+ /* are we going to need to propagate our lookahead to new item */
+ need_prop = itm.lookahead_visible();
+
+ /* create items for each production of that non term */
+ for (p = nt.productions(); p.hasMoreElements(); )
+ {
+ prod = (production)p.nextElement();
+
+ /* create new item with dot at start and that lookahead */
+ new_itm = new lalr_item(prod,
+ new terminal_set(new_lookaheads));
+
+ /* add/merge item into the set */
+ add_itm = add(new_itm);
+ /* if propagation is needed link to that item */
+ if (need_prop)
+ itm.add_propagate(add_itm);
+
+ /* was this was a new item*/
+ if (add_itm == new_itm)
+ {
+ /* that may need further closure, consider it also */
+ consider.add(new_itm);
+ }
+ }
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(lalr_item_set other)
+ {
+ if (other == null || other.size() != size()) return false;
+
+ /* once we know they are the same size, then improper subset does test */
+ try {
+ return is_subset_of(other);
+ } catch (internal_error e) {
+ /* can't throw error from here (because superclass doesn't) so crash */
+ e.crash();
+ return false;
+ }
+
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof lalr_item_set))
+ return false;
+ else
+ return equals((lalr_item_set)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return hash code. */
+ public int hashCode()
+ {
+ int result = 0;
+ Enumeration e;
+ int cnt;
+
+ /* only compute a new one if we don't have it cached */
+ if (hashcode_cache == null)
+ {
+ /* hash together codes from at most first 5 elements */
+ // CSA fix! we'd *like* to hash just a few elements, but
+ // that means equal sets will have inequal hashcodes, which
+ // we're not allowed (by contract) to do. So hash them all.
+ for (e = all(), cnt=0 ; e.hasMoreElements() /*&& cnt<5*/; cnt++)
+ result ^= ((lalr_item)e.nextElement()).hashCode();
+
+ hashcode_cache = new Integer(result);
+ }
+
+ return hashcode_cache.intValue();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to string. */
+ public String toString()
+ {
+ StringBuffer result = new StringBuffer();
+
+ result.append("{\n");
+ for (Enumeration e=all(); e.hasMoreElements(); )
+ {
+ result.append(" " + (lalr_item)e.nextElement() + "\n");
+ }
+ result.append("}");
+
+ return result.toString();
+ }
+ /*-----------------------------------------------------------*/
+}
+
diff --git a/src/java_cup/java_cup/lalr_state.java b/src/java_cup/java_cup/lalr_state.java
new file mode 100644
index 0000000..5298e87
--- /dev/null
+++ b/src/java_cup/java_cup/lalr_state.java
@@ -0,0 +1,884 @@
+
+package java_cup;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+import java.util.Stack;
+
+/** This class represents a state in the LALR viable prefix recognition machine.
+ * A state consists of an LALR item set and a set of transitions to other
+ * states under terminal and non-terminal symbols. Each state represents
+ * a potential configuration of the parser. If the item set of a state
+ * includes an item such as: <pre>
+ * [A ::= B * C d E , {a,b,c}]
+ * </pre>
+ * this indicates that when the parser is in this state it is currently
+ * looking for an A of the given form, has already seen the B, and would
+ * expect to see an a, b, or c after this sequence is complete. Note that
+ * the parser is normally looking for several things at once (represented
+ * by several items). In our example above, the state would also include
+ * items such as: <pre>
+ * [C ::= * X e Z, {d}]
+ * [X ::= * f, {e}]
+ * </pre>
+ * to indicate that it was currently looking for a C followed by a d (which
+ * would be reduced into a C, matching the first symbol in our production
+ * above), and the terminal f followed by e.<p>
+ *
+ * At runtime, the parser uses a viable prefix recognition machine made up
+ * of these states to parse. The parser has two operations, shift and reduce.
+ * In a shift, it consumes one Symbol and makes a transition to a new state.
+ * This corresponds to "moving the dot past" a terminal in one or more items
+ * in the state (these new shifted items will then be found in the state at
+ * the end of the transition). For a reduce operation, the parser is
+ * signifying that it is recognizing the RHS of some production. To do this
+ * it first "backs up" by popping a stack of previously saved states. It
+ * pops off the same number of states as are found in the RHS of the
+ * production. This leaves the machine in the same state is was in when the
+ * parser first attempted to find the RHS. From this state it makes a
+ * transition based on the non-terminal on the LHS of the production. This
+ * corresponds to placing the parse in a configuration equivalent to having
+ * replaced all the symbols from the the input corresponding to the RHS with
+ * the symbol on the LHS.
+ *
+ * @see java_cup.lalr_item
+ * @see java_cup.lalr_item_set
+ * @see java_cup.lalr_transition
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ *
+ */
+
+public class lalr_state {
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constructor for building a state from a set of items.
+ * @param itms the set of items that makes up this state.
+ */
+ public lalr_state(lalr_item_set itms) throws internal_error
+ {
+ /* don't allow null or duplicate item sets */
+ if (itms == null)
+ throw new internal_error(
+ "Attempt to construct an LALR state from a null item set");
+
+ if (find_state(itms) != null)
+ throw new internal_error(
+ "Attempt to construct a duplicate LALR state");
+
+ /* assign a unique index */
+ _index = next_index++;
+
+ /* store the items */
+ _items = itms;
+
+ /* add to the global collection, keyed with its item set */
+ _all.put(_items,this);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Collection of all states. */
+ protected static Hashtable _all = new Hashtable();
+
+ /** Collection of all states. */
+ public static Enumeration all() {return _all.elements();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Indicate total number of states there are. */
+ public static int number() {return _all.size();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Hash table to find states by their kernels (i.e, the original,
+ * unclosed, set of items -- which uniquely define the state). This table
+ * stores state objects using (a copy of) their kernel item sets as keys.
+ */
+ protected static Hashtable _all_kernels = new Hashtable();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Find and return state with a given a kernel item set (or null if not
+ * found). The kernel item set is the subset of items that were used to
+ * originally create the state. These items are formed by "shifting the
+ * dot" within items of other states that have a transition to this one.
+ * The remaining elements of this state's item set are added during closure.
+ * @param itms the kernel set of the state we are looking for.
+ */
+ public static lalr_state find_state(lalr_item_set itms)
+ {
+ if (itms == null)
+ return null;
+ else
+ return (lalr_state)_all.get(itms);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Static counter for assigning unique state indexes. */
+ protected static int next_index = 0;
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The item set for this state. */
+ protected lalr_item_set _items;
+
+ /** The item set for this state. */
+ public lalr_item_set items() {return _items;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** List of transitions out of this state. */
+ protected lalr_transition _transitions = null;
+
+ /** List of transitions out of this state. */
+ public lalr_transition transitions() {return _transitions;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Index of this state in the parse tables */
+ protected int _index;
+
+ /** Index of this state in the parse tables */
+ public int index() {return _index;}
+
+ /*-----------------------------------------------------------*/
+ /*--- Static Methods ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Helper routine for debugging -- produces a dump of the given state
+ * onto System.out.
+ */
+ protected static void dump_state(lalr_state st) throws internal_error
+ {
+ lalr_item_set itms;
+ lalr_item itm;
+ production_part part;
+
+ if (st == null)
+ {
+ System.out.println("NULL lalr_state");
+ return;
+ }
+
+ System.out.println("lalr_state [" + st.index() + "] {");
+ itms = st.items();
+ for (Enumeration e = itms.all(); e.hasMoreElements(); )
+ {
+ itm = (lalr_item)e.nextElement();
+ System.out.print(" [");
+ System.out.print(itm.the_production().lhs().the_symbol().name());
+ System.out.print(" ::= ");
+ for (int i = 0; i<itm.the_production().rhs_length(); i++)
+ {
+ if (i == itm.dot_pos()) System.out.print("(*) ");
+ part = itm.the_production().rhs(i);
+ if (part.is_action())
+ System.out.print("{action} ");
+ else
+ System.out.print(((symbol_part)part).the_symbol().name() + " ");
+ }
+ if (itm.dot_at_end()) System.out.print("(*) ");
+ System.out.println("]");
+ }
+ System.out.println("}");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Propagate lookahead sets through the constructed viable prefix
+ * recognizer. When the machine is constructed, each item that results
+ in the creation of another such that its lookahead is included in the
+ other's will have a propagate link set up for it. This allows additions
+ to the lookahead of one item to be included in other items that it
+ was used to directly or indirectly create.
+ */
+ protected static void propagate_all_lookaheads() throws internal_error
+ {
+ /* iterate across all states */
+ for (Enumeration st = all(); st.hasMoreElements(); )
+ {
+ /* propagate lookaheads out of that state */
+ ((lalr_state)st.nextElement()).propagate_lookaheads();
+ }
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Add a transition out of this state to another.
+ * @param on_sym the symbol the transition is under.
+ * @param to_st the state the transition goes to.
+ */
+ public void add_transition(symbol on_sym, lalr_state to_st)
+ throws internal_error
+ {
+ lalr_transition trans;
+
+ /* create a new transition object and put it in our list */
+ trans = new lalr_transition(on_sym, to_st, _transitions);
+ _transitions = trans;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Build an LALR viable prefix recognition machine given a start
+ * production. This method operates by first building a start state
+ * from the start production (based on a single item with the dot at
+ * the beginning and EOF as expected lookahead). Then for each state
+ * it attempts to extend the machine by creating transitions out of
+ * the state to new or existing states. When considering extension
+ * from a state we make a transition on each symbol that appears before
+ * the dot in some item. For example, if we have the items: <pre>
+ * [A ::= a b * X c, {d,e}]
+ * [B ::= a b * X d, {a,b}]
+ * </pre>
+ * in some state, then we would be making a transition under X to a new
+ * state. This new state would be formed by a "kernel" of items
+ * corresponding to moving the dot past the X. In this case: <pre>
+ * [A ::= a b X * c, {d,e}]
+ * [B ::= a b X * Y, {a,b}]
+ * </pre>
+ * The full state would then be formed by "closing" this kernel set of
+ * items so that it included items that represented productions of things
+ * the parser was now looking for. In this case we would items
+ * corresponding to productions of Y, since various forms of Y are expected
+ * next when in this state (see lalr_item_set.compute_closure() for details
+ * on closure). <p>
+ *
+ * The process of building the viable prefix recognizer terminates when no
+ * new states can be added. However, in order to build a smaller number of
+ * states (i.e., corresponding to LALR rather than canonical LR) the state
+ * building process does not maintain full loookaheads in all items.
+ * Consequently, after the machine is built, we go back and propagate
+ * lookaheads through the constructed machine using a call to
+ * propagate_all_lookaheads(). This makes use of propagation links
+ * constructed during the closure and transition process.
+ *
+ * @param start_prod the start production of the grammar
+ * @see java_cup.lalr_item_set#compute_closure
+ * @see java_cup.lalr_state#propagate_all_lookaheads
+ */
+
+ public static lalr_state build_machine(production start_prod)
+ throws internal_error
+ {
+ lalr_state start_state;
+ lalr_item_set start_items;
+ lalr_item_set new_items;
+ lalr_item_set linked_items;
+ lalr_item_set kernel;
+ Stack work_stack = new Stack();
+ lalr_state st, new_st;
+ symbol_set outgoing;
+ lalr_item itm, new_itm, existing, fix_itm;
+ symbol sym, sym2;
+ Enumeration i, s, fix;
+
+ /* sanity check */
+ if (start_prod == null)
+ throw new internal_error(
+ "Attempt to build viable prefix recognizer using a null production");
+
+ /* build item with dot at front of start production and EOF lookahead */
+ start_items = new lalr_item_set();
+
+ itm = new lalr_item(start_prod);
+ itm.lookahead().add(terminal.EOF);
+
+ start_items.add(itm);
+
+ /* create copy the item set to form the kernel */
+ kernel = new lalr_item_set(start_items);
+
+ /* create the closure from that item set */
+ start_items.compute_closure();
+
+ /* build a state out of that item set and put it in our work set */
+ start_state = new lalr_state(start_items);
+ work_stack.push(start_state);
+
+ /* enter the state using the kernel as the key */
+ _all_kernels.put(kernel, start_state);
+
+ /* continue looking at new states until we have no more work to do */
+ while (!work_stack.empty())
+ {
+ /* remove a state from the work set */
+ st = (lalr_state)work_stack.pop();
+
+ /* gather up all the symbols that appear before dots */
+ outgoing = new symbol_set();
+ for (i = st.items().all(); i.hasMoreElements(); )
+ {
+ itm = (lalr_item)i.nextElement();
+
+ /* add the symbol before the dot (if any) to our collection */
+ sym = itm.symbol_after_dot();
+ if (sym != null) outgoing.add(sym);
+ }
+
+ /* now create a transition out for each individual symbol */
+ for (s = outgoing.all(); s.hasMoreElements(); )
+ {
+ sym = (symbol)s.nextElement();
+
+ /* will be keeping the set of items with propagate links */
+ linked_items = new lalr_item_set();
+
+ /* gather up shifted versions of all the items that have this
+ symbol before the dot */
+ new_items = new lalr_item_set();
+ for (i = st.items().all(); i.hasMoreElements();)
+ {
+ itm = (lalr_item)i.nextElement();
+
+ /* if this is the symbol we are working on now, add to set */
+ sym2 = itm.symbol_after_dot();
+ if (sym.equals(sym2))
+ {
+ /* add to the kernel of the new state */
+ new_items.add(itm.shift());
+
+ /* remember that itm has propagate link to it */
+ linked_items.add(itm);
+ }
+ }
+
+ /* use new items as state kernel */
+ kernel = new lalr_item_set(new_items);
+
+ /* have we seen this one already? */
+ new_st = (lalr_state)_all_kernels.get(kernel);
+
+ /* if we haven't, build a new state out of the item set */
+ if (new_st == null)
+ {
+ /* compute closure of the kernel for the full item set */
+ new_items.compute_closure();
+
+ /* build the new state */
+ new_st = new lalr_state(new_items);
+
+ /* add the new state to our work set */
+ work_stack.push(new_st);
+
+ /* put it in our kernel table */
+ _all_kernels.put(kernel, new_st);
+ }
+ /* otherwise relink propagation to items in existing state */
+ else
+ {
+ /* walk through the items that have links to the new state */
+ for (fix = linked_items.all(); fix.hasMoreElements(); )
+ {
+ fix_itm = (lalr_item)fix.nextElement();
+
+ /* look at each propagate link out of that item */
+ for (int l =0; l < fix_itm.propagate_items().size(); l++)
+ {
+ /* pull out item linked to in the new state */
+ new_itm =
+ (lalr_item)fix_itm.propagate_items().elementAt(l);
+
+ /* find corresponding item in the existing state */
+ existing = new_st.items().find(new_itm);
+
+ /* fix up the item so it points to the existing set */
+ if (existing != null)
+ fix_itm.propagate_items().setElementAt(existing ,l);
+ }
+ }
+ }
+
+ /* add a transition from current state to that state */
+ st.add_transition(sym, new_st);
+ }
+ }
+
+ /* all done building states */
+
+ /* propagate complete lookahead sets throughout the states */
+ propagate_all_lookaheads();
+
+ return start_state;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Propagate lookahead sets out of this state. This recursively
+ * propagates to all items that have propagation links from some item
+ * in this state.
+ */
+ protected void propagate_lookaheads() throws internal_error
+ {
+ /* recursively propagate out from each item in the state */
+ for (Enumeration itm = items().all(); itm.hasMoreElements(); )
+ ((lalr_item)itm.nextElement()).propagate_lookaheads(null);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Fill in the parse table entries for this state. There are two
+ * parse tables that encode the viable prefix recognition machine, an
+ * action table and a reduce-goto table. The rows in each table
+ * correspond to states of the machine. The columns of the action table
+ * are indexed by terminal symbols and correspond to either transitions
+ * out of the state (shift entries) or reductions from the state to some
+ * previous state saved on the stack (reduce entries). All entries in the
+ * action table that are not shifts or reduces, represent errors. The
+ * reduce-goto table is indexed by non terminals and represents transitions
+ * out of a state on that non-terminal.<p>
+ * Conflicts occur if more than one action needs to go in one entry of the
+ * action table (this cannot happen with the reduce-goto table). Conflicts
+ * are resolved by always shifting for shift/reduce conflicts and choosing
+ * the lowest numbered production (hence the one that appeared first in
+ * the specification) in reduce/reduce conflicts. All conflicts are
+ * reported and if more conflicts are detected than were declared by the
+ * user, code generation is aborted.
+ *
+ * @param act_table the action table to put entries in.
+ * @param reduce_table the reduce-goto table to put entries in.
+ */
+ public void build_table_entries(
+ parse_action_table act_table,
+ parse_reduce_table reduce_table)
+ throws internal_error
+ {
+ parse_action_row our_act_row;
+ parse_reduce_row our_red_row;
+ lalr_item itm;
+ parse_action act, other_act;
+ symbol sym;
+ terminal_set conflict_set = new terminal_set();
+
+ /* pull out our rows from the tables */
+ our_act_row = act_table.under_state[index()];
+ our_red_row = reduce_table.under_state[index()];
+
+ /* consider each item in our state */
+ for (Enumeration i = items().all(); i.hasMoreElements(); )
+ {
+ itm = (lalr_item)i.nextElement();
+
+
+ /* if its completed (dot at end) then reduce under the lookahead */
+ if (itm.dot_at_end())
+ {
+ act = new reduce_action(itm.the_production());
+
+ /* consider each lookahead symbol */
+ for (int t = 0; t < terminal.number(); t++)
+ {
+ /* skip over the ones not in the lookahead */
+ if (!itm.lookahead().contains(t)) continue;
+
+ /* if we don't already have an action put this one in */
+ if (our_act_row.under_term[t].kind() ==
+ parse_action.ERROR)
+ {
+ our_act_row.under_term[t] = act;
+ }
+ else
+ {
+ /* we now have at least one conflict */
+ terminal term = terminal.find(t);
+ other_act = our_act_row.under_term[t];
+
+ /* if the other act was not a shift */
+ if ((other_act.kind() != parse_action.SHIFT) &&
+ (other_act.kind() != parse_action.NONASSOC))
+ {
+ /* if we have lower index hence priority, replace it*/
+ if (itm.the_production().index() <
+ ((reduce_action)other_act).reduce_with().index())
+ {
+ /* replace the action */
+ our_act_row.under_term[t] = act;
+ }
+ } else {
+ /* Check precedences,see if problem is correctable */
+ if(fix_with_precedence(itm.the_production(),
+ t, our_act_row, act)) {
+ term = null;
+ }
+ }
+ if(term!=null) {
+
+ conflict_set.add(term);
+ }
+ }
+ }
+ }
+ }
+
+ /* consider each outgoing transition */
+ for (lalr_transition trans=transitions(); trans!=null; trans=trans.next())
+ {
+ /* if its on an terminal add a shift entry */
+ sym = trans.on_symbol();
+ if (!sym.is_non_term())
+ {
+ act = new shift_action(trans.to_state());
+
+ /* if we don't already have an action put this one in */
+ if ( our_act_row.under_term[sym.index()].kind() ==
+ parse_action.ERROR)
+ {
+ our_act_row.under_term[sym.index()] = act;
+ }
+ else
+ {
+ /* we now have at least one conflict */
+ production p = ((reduce_action)our_act_row.under_term[sym.index()]).reduce_with();
+
+ /* shift always wins */
+ if (!fix_with_precedence(p, sym.index(), our_act_row, act)) {
+ our_act_row.under_term[sym.index()] = act;
+ conflict_set.add(terminal.find(sym.index()));
+ }
+ }
+ }
+ else
+ {
+ /* for non terminals add an entry to the reduce-goto table */
+ our_red_row.under_non_term[sym.index()] = trans.to_state();
+ }
+ }
+
+ /* if we end up with conflict(s), report them */
+ if (!conflict_set.empty())
+ report_conflicts(conflict_set);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+
+ /** Procedure that attempts to fix a shift/reduce error by using
+ * precedences. --frankf 6/26/96
+ *
+ * if a production (also called rule) or the lookahead terminal
+ * has a precedence, then the table can be fixed. if the rule
+ * has greater precedence than the terminal, a reduce by that rule
+ * in inserted in the table. If the terminal has a higher precedence,
+ * it is shifted. if they have equal precedence, then the associativity
+ * of the precedence is used to determine what to put in the table:
+ * if the precedence is left associative, the action is to reduce.
+ * if the precedence is right associative, the action is to shift.
+ * if the precedence is non associative, then it is a syntax error.
+ *
+ * @param p the production
+ * @param term_index the index of the lokahead terminal
+ * @param parse_action_row a row of the action table
+ * @param act the rule in conflict with the table entry
+ */
+
+ protected boolean fix_with_precedence(
+ production p,
+ int term_index,
+ parse_action_row table_row,
+ parse_action act)
+
+ throws internal_error {
+
+ terminal term = terminal.find(term_index);
+
+ /* if the production has a precedence number, it can be fixed */
+ if (p.precedence_num() > assoc.no_prec) {
+
+ /* if production precedes terminal, put reduce in table */
+ if (p.precedence_num() > term.precedence_num()) {
+ table_row.under_term[term_index] =
+ insert_reduce(table_row.under_term[term_index],act);
+ return true;
+ }
+
+ /* if terminal precedes rule, put shift in table */
+ else if (p.precedence_num() < term.precedence_num()) {
+ table_row.under_term[term_index] =
+ insert_shift(table_row.under_term[term_index],act);
+ return true;
+ }
+ else { /* they are == precedence */
+
+ /* equal precedences have equal sides, so only need to
+ look at one: if it is right, put shift in table */
+ if (term.precedence_side() == assoc.right) {
+ table_row.under_term[term_index] =
+ insert_shift(table_row.under_term[term_index],act);
+ return true;
+ }
+
+ /* if it is left, put reduce in table */
+ else if (term.precedence_side() == assoc.left) {
+ table_row.under_term[term_index] =
+ insert_reduce(table_row.under_term[term_index],act);
+ return true;
+ }
+
+ /* if it is nonassoc, we're not allowed to have two nonassocs
+ of equal precedence in a row, so put in NONASSOC */
+ else if (term.precedence_side() == assoc.nonassoc) {
+ table_row.under_term[term_index] = new nonassoc_action();
+ return true;
+ } else {
+ /* something really went wrong */
+ throw new internal_error("Unable to resolve conflict correctly");
+ }
+ }
+ }
+ /* check if terminal has precedence, if so, shift, since
+ rule does not have precedence */
+ else if (term.precedence_num() > assoc.no_prec) {
+ table_row.under_term[term_index] =
+ insert_shift(table_row.under_term[term_index],act);
+ return true;
+ }
+
+ /* otherwise, neither the rule nor the terminal has a precedence,
+ so it can't be fixed. */
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+
+ /* given two actions, and an action type, return the
+ action of that action type. give an error if they are of
+ the same action, because that should never have tried
+ to be fixed
+
+ */
+ protected parse_action insert_action(
+ parse_action a1,
+ parse_action a2,
+ int act_type)
+ throws internal_error
+ {
+ if ((a1.kind() == act_type) && (a2.kind() == act_type)) {
+ throw new internal_error("Conflict resolution of bogus actions");
+ } else if (a1.kind() == act_type) {
+ return a1;
+ } else if (a2.kind() == act_type) {
+ return a2;
+ } else {
+ throw new internal_error("Conflict resolution of bogus actions");
+ }
+ }
+
+ /* find the shift in the two actions */
+ protected parse_action insert_shift(
+ parse_action a1,
+ parse_action a2)
+ throws internal_error
+ {
+ return insert_action(a1, a2, parse_action.SHIFT);
+ }
+
+ /* find the reduce in the two actions */
+ protected parse_action insert_reduce(
+ parse_action a1,
+ parse_action a2)
+ throws internal_error
+ {
+ return insert_action(a1, a2, parse_action.REDUCE);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce warning messages for all conflicts found in this state. */
+ protected void report_conflicts(terminal_set conflict_set)
+ throws internal_error
+ {
+ lalr_item itm, compare;
+ symbol shift_sym;
+
+ boolean after_itm;
+
+ /* consider each element */
+ for (Enumeration itms = items().all(); itms.hasMoreElements(); )
+ {
+ itm = (lalr_item)itms.nextElement();
+
+ /* clear the S/R conflict set for this item */
+
+ /* if it results in a reduce, it could be a conflict */
+ if (itm.dot_at_end())
+ {
+ /* not yet after itm */
+ after_itm = false;
+
+ /* compare this item against all others looking for conflicts */
+ for (Enumeration comps = items().all(); comps.hasMoreElements(); )
+ {
+ compare = (lalr_item)comps.nextElement();
+
+ /* if this is the item, next one is after it */
+ if (itm == compare) after_itm = true;
+
+ /* only look at it if its not the same item */
+ if (itm != compare)
+ {
+ /* is it a reduce */
+ if (compare.dot_at_end())
+ {
+ /* only look at reduces after itm */
+ if (after_itm)
+ /* does the comparison item conflict? */
+ if (compare.lookahead().intersects(itm.lookahead()))
+ /* report a reduce/reduce conflict */
+ report_reduce_reduce(itm, compare);
+ }
+ }
+ }
+ /* report S/R conflicts under all the symbols we conflict under */
+ for (int t = 0; t < terminal.number(); t++)
+ if (conflict_set.contains(t))
+ report_shift_reduce(itm,t);
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a warning message for one reduce/reduce conflict.
+ *
+ * @param itm1 first item in conflict.
+ * @param itm2 second item in conflict.
+ */
+ protected void report_reduce_reduce(lalr_item itm1, lalr_item itm2)
+ throws internal_error
+ {
+ boolean comma_flag = false;
+
+ System.err.println("*** Reduce/Reduce conflict found in state #"+index());
+ System.err.print (" between ");
+ System.err.println(itm1.to_simple_string());
+ System.err.print (" and ");
+ System.err.println(itm2.to_simple_string());
+ System.err.print(" under symbols: {" );
+ for (int t = 0; t < terminal.number(); t++)
+ {
+ if (itm1.lookahead().contains(t) && itm2.lookahead().contains(t))
+ {
+ if (comma_flag) System.err.print(", "); else comma_flag = true;
+ System.err.print(terminal.find(t).name());
+ }
+ }
+ System.err.println("}");
+ System.err.print(" Resolved in favor of ");
+ if (itm1.the_production().index() < itm2.the_production().index())
+ System.err.println("the first production.\n");
+ else
+ System.err.println("the second production.\n");
+
+ /* count the conflict */
+ emit.num_conflicts++;
+ lexer.warning_count++;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a warning message for one shift/reduce conflict.
+ *
+ * @param red_itm the item with the reduce.
+ * @param conflict_sym the index of the symbol conflict occurs under.
+ */
+ protected void report_shift_reduce(
+ lalr_item red_itm,
+ int conflict_sym)
+ throws internal_error
+ {
+ lalr_item itm;
+ symbol shift_sym;
+
+ /* emit top part of message including the reduce item */
+ System.err.println("*** Shift/Reduce conflict found in state #"+index());
+ System.err.print (" between ");
+ System.err.println(red_itm.to_simple_string());
+
+ /* find and report on all items that shift under our conflict symbol */
+ for (Enumeration itms = items().all(); itms.hasMoreElements(); )
+ {
+ itm = (lalr_item)itms.nextElement();
+
+ /* only look if its not the same item and not a reduce */
+ if (itm != red_itm && !itm.dot_at_end())
+ {
+ /* is it a shift on our conflicting terminal */
+ shift_sym = itm.symbol_after_dot();
+ if (!shift_sym.is_non_term() && shift_sym.index() == conflict_sym)
+ {
+ /* yes, report on it */
+ System.err.println(" and " + itm.to_simple_string());
+ }
+ }
+ }
+ System.err.println(" under symbol "+ terminal.find(conflict_sym).name());
+ System.err.println(" Resolved in favor of shifting.\n");
+
+ /* count the conflict */
+ emit.num_conflicts++;
+ lexer.warning_count++;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(lalr_state other)
+ {
+ /* we are equal if our item sets are equal */
+ return other != null && items().equals(other.items());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof lalr_state))
+ return false;
+ else
+ return equals((lalr_state)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a hash code. */
+ public int hashCode()
+ {
+ /* just use the item set hash code */
+ return items().hashCode();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+ lalr_transition tr;
+
+ /* dump the item set */
+ result = "lalr_state [" + index() + "]: " + _items + "\n";
+
+ /* do the transitions */
+ for (tr = transitions(); tr != null; tr = tr.next())
+ {
+ result += tr;
+ result += "\n";
+ }
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+}
diff --git a/src/java_cup/java_cup/lalr_transition.java b/src/java_cup/java_cup/lalr_transition.java
new file mode 100644
index 0000000..1c941bd
--- /dev/null
+++ b/src/java_cup/java_cup/lalr_transition.java
@@ -0,0 +1,93 @@
+package java_cup;
+
+/** This class represents a transition in an LALR viable prefix recognition
+ * machine. Transitions can be under terminals for non-terminals. They are
+ * internally linked together into singly linked lists containing all the
+ * transitions out of a single state via the _next field.
+ *
+ * @see java_cup.lalr_state
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ *
+ */
+public class lalr_transition {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param on_sym symbol we are transitioning on.
+ * @param to_st state we transition to.
+ * @param nxt next transition in linked list.
+ */
+ public lalr_transition(symbol on_sym, lalr_state to_st, lalr_transition nxt)
+ throws internal_error
+ {
+ /* sanity checks */
+ if (on_sym == null)
+ throw new internal_error("Attempt to create transition on null symbol");
+ if (to_st == null)
+ throw new internal_error("Attempt to create transition to null state");
+
+ /* initialize */
+ _on_symbol = on_sym;
+ _to_state = to_st;
+ _next = nxt;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with null next.
+ * @param on_sym symbol we are transitioning on.
+ * @param to_st state we transition to.
+ */
+ public lalr_transition(symbol on_sym, lalr_state to_st) throws internal_error
+ {
+ this(on_sym, to_st, null);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The symbol we make the transition on. */
+ protected symbol _on_symbol;
+
+ /** The symbol we make the transition on. */
+ public symbol on_symbol() {return _on_symbol;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The state we transition to. */
+ protected lalr_state _to_state;
+
+ /** The state we transition to. */
+ public lalr_state to_state() {return _to_state;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Next transition in linked list of transitions out of a state */
+ protected lalr_transition _next;
+
+ /** Next transition in linked list of transitions out of a state */
+ public lalr_transition next() {return _next;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+
+ result = "transition on " + on_symbol().name() + " to state [";
+ result += _to_state.index();
+ result += "]";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+}
diff --git a/src/java_cup/java_cup/lexer.java b/src/java_cup/java_cup/lexer.java
new file mode 100644
index 0000000..2230d12
--- /dev/null
+++ b/src/java_cup/java_cup/lexer.java
@@ -0,0 +1,543 @@
+package java_cup;
+
+import java_cup.runtime.Symbol;
+import java.util.Hashtable;
+
+/** This class implements a small scanner (aka lexical analyzer or lexer) for
+ * the JavaCup specification. This scanner reads characters from standard
+ * input (System.in) and returns integers corresponding to the terminal
+ * number of the next Symbol. Once end of input is reached the EOF Symbol is
+ * returned on every subsequent call.<p>
+ * Symbols currently returned include: <pre>
+ * Symbol Constant Returned Symbol Constant Returned
+ * ------ ----------------- ------ -----------------
+ * "package" PACKAGE "import" IMPORT
+ * "code" CODE "action" ACTION
+ * "parser" PARSER "terminal" TERMINAL
+ * "non" NON "init" INIT
+ * "scan" SCAN "with" WITH
+ * "start" START "precedence" PRECEDENCE
+ * "left" LEFT "right" RIGHT
+ * "nonassoc" NONASSOC "%prec PRECENT_PREC
+ * [ LBRACK ] RBRACK
+ * ; SEMI
+ * , COMMA * STAR
+ * . DOT : COLON
+ * ::= COLON_COLON_EQUALS | BAR
+ * identifier ID {:...:} CODE_STRING
+ * "nonterminal" NONTERMINAL
+ * </pre>
+ * All symbol constants are defined in sym.java which is generated by
+ * JavaCup from parser.cup.<p>
+ *
+ * In addition to the scanner proper (called first via init() then with
+ * next_token() to get each Symbol) this class provides simple error and
+ * warning routines and keeps a count of errors and warnings that is
+ * publicly accessible.<p>
+ *
+ * This class is "static" (i.e., it has only static members and methods).
+ *
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+public class lexer {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The only constructor is private, so no instances can be created. */
+ private lexer() { }
+
+ /*-----------------------------------------------------------*/
+ /*--- Static (Class) Variables ------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** First character of lookahead. */
+ protected static int next_char;
+
+ /** Second character of lookahead. */
+ protected static int next_char2;
+
+ /** Second character of lookahead. */
+ protected static int next_char3;
+
+ /** Second character of lookahead. */
+ protected static int next_char4;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** EOF constant. */
+ protected static final int EOF_CHAR = -1;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Table of keywords. Keywords are initially treated as identifiers.
+ * Just before they are returned we look them up in this table to see if
+ * they match one of the keywords. The string of the name is the key here,
+ * which indexes Integer objects holding the symbol number.
+ */
+ protected static Hashtable keywords = new Hashtable(23);
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Table of single character symbols. For ease of implementation, we
+ * store all unambiguous single character Symbols in this table of Integer
+ * objects keyed by Integer objects with the numerical value of the
+ * appropriate char (currently Character objects have a bug which precludes
+ * their use in tables).
+ */
+ protected static Hashtable char_symbols = new Hashtable(11);
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Current line number for use in error messages. */
+ protected static int current_line = 1;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Character position in current line. */
+ protected static int current_position = 1;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Character position in current line. */
+ protected static int absolute_position = 1;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of total errors detected so far. */
+ public static int error_count = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of warnings issued so far */
+ public static int warning_count = 0;
+
+ /*-----------------------------------------------------------*/
+ /*--- Static Methods ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Initialize the scanner. This sets up the keywords and char_symbols
+ * tables and reads the first two characters of lookahead.
+ */
+ public static void init() throws java.io.IOException
+ {
+ /* set up the keyword table */
+ keywords.put("package", new Integer(sym.PACKAGE));
+ keywords.put("import", new Integer(sym.IMPORT));
+ keywords.put("code", new Integer(sym.CODE));
+ keywords.put("action", new Integer(sym.ACTION));
+ keywords.put("parser", new Integer(sym.PARSER));
+ keywords.put("terminal", new Integer(sym.TERMINAL));
+ keywords.put("non", new Integer(sym.NON));
+ keywords.put("nonterminal",new Integer(sym.NONTERMINAL));// [CSA]
+ keywords.put("init", new Integer(sym.INIT));
+ keywords.put("scan", new Integer(sym.SCAN));
+ keywords.put("with", new Integer(sym.WITH));
+ keywords.put("start", new Integer(sym.START));
+ keywords.put("precedence", new Integer(sym.PRECEDENCE));
+ keywords.put("left", new Integer(sym.LEFT));
+ keywords.put("right", new Integer(sym.RIGHT));
+ keywords.put("nonassoc", new Integer(sym.NONASSOC));
+
+ /* set up the table of single character symbols */
+ char_symbols.put(new Integer(';'), new Integer(sym.SEMI));
+ char_symbols.put(new Integer(','), new Integer(sym.COMMA));
+ char_symbols.put(new Integer('*'), new Integer(sym.STAR));
+ char_symbols.put(new Integer('.'), new Integer(sym.DOT));
+ char_symbols.put(new Integer('|'), new Integer(sym.BAR));
+ char_symbols.put(new Integer('['), new Integer(sym.LBRACK));
+ char_symbols.put(new Integer(']'), new Integer(sym.RBRACK));
+
+ /* read two characters of lookahead */
+ next_char = System.in.read();
+ if (next_char == EOF_CHAR) {
+ next_char2 = EOF_CHAR;
+ next_char3 = EOF_CHAR;
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char2 = System.in.read();
+ if (next_char2 == EOF_CHAR) {
+ next_char3 = EOF_CHAR;
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char3 = System.in.read();
+ if (next_char3 == EOF_CHAR) {
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char4 = System.in.read();
+ }
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Advance the scanner one character in the input stream. This moves
+ * next_char2 to next_char and then reads a new next_char2.
+ */
+ protected static void advance() throws java.io.IOException
+ {
+ int old_char;
+
+ old_char = next_char;
+ next_char = next_char2;
+ if (next_char == EOF_CHAR) {
+ next_char2 = EOF_CHAR;
+ next_char3 = EOF_CHAR;
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char2 = next_char3;
+ if (next_char2 == EOF_CHAR) {
+ next_char3 = EOF_CHAR;
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char3 = next_char4;
+ if (next_char3 == EOF_CHAR) {
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char4 = System.in.read();
+ }
+ }
+ }
+
+ /* count this */
+ absolute_position++;
+ current_position++;
+ if (old_char == '\n' || (old_char == '\r' && next_char!='\n'))
+ {
+ current_line++;
+ current_position = 1;
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit an error message. The message will be marked with both the
+ * current line number and the position in the line. Error messages
+ * are printed on standard error (System.err).
+ * @param message the message to print.
+ */
+ public static void emit_error(String message)
+ {
+ System.err.println("Error at " + current_line + "(" + current_position +
+ "): " + message);
+ error_count++;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit a warning message. The message will be marked with both the
+ * current line number and the position in the line. Messages are
+ * printed on standard error (System.err).
+ * @param message the message to print.
+ */
+ public static void emit_warn(String message)
+ {
+ System.err.println("Warning at " + current_line + "(" + current_position +
+ "): " + message);
+ warning_count++;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if a character is ok to start an id.
+ * @param ch the character in question.
+ */
+ protected static boolean id_start_char(int ch)
+ {
+ /* allow for % in identifiers. a hack to allow my
+ %prec in. Should eventually make lex spec for this
+ frankf */
+ return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
+ (ch == '_');
+
+ // later need to deal with non-8-bit chars here
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if a character is ok for the middle of an id.
+ * @param ch the character in question.
+ */
+ protected static boolean id_char(int ch)
+ {
+ return id_start_char(ch) || (ch >= '0' && ch <= '9');
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Try to look up a single character symbol, returns -1 for not found.
+ * @param ch the character in question.
+ */
+ protected static int find_single_char(int ch)
+ {
+ Integer result;
+
+ result = (Integer)char_symbols.get(new Integer((char)ch));
+ if (result == null)
+ return -1;
+ else
+ return result.intValue();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Handle swallowing up a comment. Both old style C and new style C++
+ * comments are handled.
+ */
+ protected static void swallow_comment() throws java.io.IOException
+ {
+ /* next_char == '/' at this point */
+
+ /* is it a traditional comment */
+ if (next_char2 == '*')
+ {
+ /* swallow the opener */
+ advance(); advance();
+
+ /* swallow the comment until end of comment or EOF */
+ for (;;)
+ {
+ /* if its EOF we have an error */
+ if (next_char == EOF_CHAR)
+ {
+ emit_error("Specification file ends inside a comment");
+ return;
+ }
+
+ /* if we can see the closer we are done */
+ if (next_char == '*' && next_char2 == '/')
+ {
+ advance();
+ advance();
+ return;
+ }
+
+ /* otherwise swallow char and move on */
+ advance();
+ }
+ }
+
+ /* is its a new style comment */
+ if (next_char2 == '/')
+ {
+ /* swallow the opener */
+ advance(); advance();
+
+ /* swallow to '\n', '\r', '\f', or EOF */
+ while (next_char != '\n' && next_char != '\r' &&
+ next_char != '\f' && next_char!=EOF_CHAR)
+ advance();
+
+ return;
+
+ }
+
+ /* shouldn't get here, but... if we get here we have an error */
+ emit_error("Malformed comment in specification -- ignored");
+ advance();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Swallow up a code string. Code strings begin with "{:" and include
+ all characters up to the first occurrence of ":}" (there is no way to
+ include ":}" inside a code string). The routine returns a String
+ object suitable for return by the scanner.
+ */
+ protected static Symbol do_code_string() throws java.io.IOException
+ {
+ StringBuffer result = new StringBuffer();
+
+ /* at this point we have lookahead of "{:" -- swallow that */
+ advance(); advance();
+
+ /* save chars until we see ":}" */
+ while (!(next_char == ':' && next_char2 == '}'))
+ {
+ /* if we have run off the end issue a message and break out of loop */
+ if (next_char == EOF_CHAR)
+ {
+ emit_error("Specification file ends inside a code string");
+ break;
+ }
+
+ /* otherwise record the char and move on */
+ result.append(new Character((char)next_char));
+ advance();
+ }
+
+ /* advance past the closer and build a return Symbol */
+ advance(); advance();
+ return new Symbol(sym.CODE_STRING, result.toString());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Process an identifier. Identifiers begin with a letter, underscore,
+ * or dollar sign, which is followed by zero or more letters, numbers,
+ * underscores or dollar signs. This routine returns a String suitable
+ * for return by the scanner.
+ */
+ protected static Symbol do_id() throws java.io.IOException
+ {
+ StringBuffer result = new StringBuffer();
+ String result_str;
+ Integer keyword_num;
+ char buffer[] = new char[1];
+
+ /* next_char holds first character of id */
+ buffer[0] = (char)next_char;
+ result.append(buffer,0,1);
+ advance();
+
+ /* collect up characters while they fit in id */
+ while(id_char(next_char))
+ {
+ buffer[0] = (char)next_char;
+ result.append(buffer,0,1);
+ advance();
+ }
+
+ /* extract a string and try to look it up as a keyword */
+ result_str = result.toString();
+ keyword_num = (Integer)keywords.get(result_str);
+
+ /* if we found something, return that keyword */
+ if (keyword_num != null)
+ return new Symbol(keyword_num.intValue());
+
+ /* otherwise build and return an id Symbol with an attached string */
+ return new Symbol(sym.ID, result_str);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return one Symbol. This is the main external interface to the scanner.
+ * It consumes sufficient characters to determine the next input Symbol
+ * and returns it. To help with debugging, this routine actually calls
+ * real_next_token() which does the work. If you need to debug the
+ * parser, this can be changed to call debug_next_token() which prints
+ * a debugging message before returning the Symbol.
+ */
+ public static Symbol next_token() throws java.io.IOException
+ {
+ return real_next_token();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Debugging version of next_token(). This routine calls the real scanning
+ * routine, prints a message on System.out indicating what the Symbol is,
+ * then returns it.
+ */
+ public static Symbol debug_next_token() throws java.io.IOException
+ {
+ Symbol result = real_next_token();
+ System.out.println("# next_Symbol() => " + result.sym);
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The actual routine to return one Symbol. This is normally called from
+ * next_token(), but for debugging purposes can be called indirectly from
+ * debug_next_token().
+ */
+ protected static Symbol real_next_token() throws java.io.IOException
+ {
+ int sym_num;
+
+ for (;;)
+ {
+ /* look for white space */
+ if (next_char == ' ' || next_char == '\t' || next_char == '\n' ||
+ next_char == '\f' || next_char == '\r')
+ {
+ /* advance past it and try the next character */
+ advance();
+ continue;
+ }
+
+ /* look for a single character symbol */
+ sym_num = find_single_char(next_char);
+ if (sym_num != -1)
+ {
+ /* found one -- advance past it and return a Symbol for it */
+ advance();
+ return new Symbol(sym_num);
+ }
+
+ /* look for : or ::= */
+ if (next_char == ':')
+ {
+ /* if we don't have a second ':' return COLON */
+ if (next_char2 != ':')
+ {
+ advance();
+ return new Symbol(sym.COLON);
+ }
+
+ /* move forward and look for the '=' */
+ advance();
+ if (next_char2 == '=')
+ {
+ advance(); advance();
+ return new Symbol(sym.COLON_COLON_EQUALS);
+ }
+ else
+ {
+ /* return just the colon (already consumed) */
+ return new Symbol(sym.COLON);
+ }
+ }
+
+ /* find a "%prec" string and return it. otherwise, a '%' was found,
+ which has no right being in the specification otherwise */
+ if (next_char == '%') {
+ advance();
+ if ((next_char == 'p') && (next_char2 == 'r') && (next_char3 == 'e') &&
+ (next_char4 == 'c')) {
+ advance();
+ advance();
+ advance();
+ advance();
+ return new Symbol(sym.PERCENT_PREC);
+ } else {
+ emit_error("Found extraneous percent sign");
+ }
+ }
+
+ /* look for a comment */
+ if (next_char == '/' && (next_char2 == '*' || next_char2 == '/'))
+ {
+ /* swallow then continue the scan */
+ swallow_comment();
+ continue;
+ }
+
+ /* look for start of code string */
+ if (next_char == '{' && next_char2 == ':')
+ return do_code_string();
+
+ /* look for an id or keyword */
+ if (id_start_char(next_char)) return do_id();
+
+ /* look for EOF */
+ if (next_char == EOF_CHAR) return new Symbol(sym.EOF);
+
+ /* if we get here, we have an unrecognized character */
+ emit_warn("Unrecognized character '" +
+ new Character((char)next_char) + "'(" + next_char +
+ ") -- ignored");
+
+ /* advance past it */
+ advance();
+ }
+ }
+
+ /*-----------------------------------------------------------*/
+}
+
diff --git a/src/java_cup/java_cup/log b/src/java_cup/java_cup/log
new file mode 100644
index 0000000..2b5a839
--- /dev/null
+++ b/src/java_cup/java_cup/log
@@ -0,0 +1,345 @@
+lexer.java:3: package java_cup.runtime does not exist
+import java_cup.runtime.Symbol;
+ ^
+lexer.java:350: cannot find symbol
+symbol : class Symbol
+location: class java_cup.lexer
+ protected static Symbol do_code_string() throws java.io.IOException
+ ^
+lexer.java:384: cannot find symbol
+symbol : class Symbol
+location: class java_cup.lexer
+ protected static Symbol do_id() throws java.io.IOException
+ ^
+lexer.java:425: cannot find symbol
+symbol : class Symbol
+location: class java_cup.lexer
+ public static Symbol next_token() throws java.io.IOException
+ ^
+lexer.java:436: cannot find symbol
+symbol : class Symbol
+location: class java_cup.lexer
+ public static Symbol debug_next_token() throws java.io.IOException
+ ^
+lexer.java:449: cannot find symbol
+symbol : class Symbol
+location: class java_cup.lexer
+ protected static Symbol real_next_token() throws java.io.IOException
+ ^
+parser.java:9: package java_cup.runtime does not exist
+import java_cup.runtime.*;
+^
+parser.java:15: package java_cup.runtime does not exist
+public class parser extends java_cup.runtime.lr_parser {
+ ^
+parser.java:21: package java_cup.runtime does not exist
+ public parser(java_cup.runtime.Scanner s) {super(s);}
+ ^
+parser.java:340: package java_cup.runtime does not exist
+ java_cup.runtime.lr_parser parser,
+ ^
+parser.java:338: package java_cup.runtime does not exist
+ public java_cup.runtime.Symbol do_action(
+ ^
+parser.java:368: package java_cup.runtime does not exist
+ public java_cup.runtime.Symbol scan()
+ ^
+parser.java:497: package java_cup.runtime does not exist
+ java_cup.runtime.lr_parser CUP$parser$parser,
+ ^
+parser.java:495: package java_cup.runtime does not exist
+ public final java_cup.runtime.Symbol CUP$parser$do_action(
+ ^
+lexer.java:374: cannot find symbol
+symbol : class Symbol
+location: class java_cup.lexer
+ return new Symbol(sym.CODE_STRING, result.toString());
+ ^
+lexer.java:410: cannot find symbol
+symbol : class Symbol
+location: class java_cup.lexer
+ return new Symbol(keyword_num.intValue());
+ ^
+lexer.java:413: cannot find symbol
+symbol : class Symbol
+location: class java_cup.lexer
+ return new Symbol(sym.ID, result_str);
+ ^
+lexer.java:438: cannot find symbol
+symbol : class Symbol
+location: class java_cup.lexer
+ Symbol result = real_next_token();
+ ^
+lexer.java:470: cannot find symbol
+symbol : class Symbol
+location: class java_cup.lexer
+ return new Symbol(sym_num);
+ ^
+lexer.java:480: cannot find symbol
+symbol : class Symbol
+location: class java_cup.lexer
+ return new Symbol(sym.COLON);
+ ^
+lexer.java:488: cannot find symbol
+symbol : class Symbol
+location: class java_cup.lexer
+ return new Symbol(sym.COLON_COLON_EQUALS);
+ ^
+lexer.java:493: cannot find symbol
+symbol : class Symbol
+location: class java_cup.lexer
+ return new Symbol(sym.COLON);
+ ^
+lexer.java:507: cannot find symbol
+symbol : class Symbol
+location: class java_cup.lexer
+ return new Symbol(sym.PERCENT_PREC);
+ ^
+lexer.java:529: cannot find symbol
+symbol : class Symbol
+location: class java_cup.lexer
+ if (next_char == EOF_CHAR) return new Symbol(sym.EOF);
+ ^
+Main.java:440: cannot find symbol
+symbol : method debug_parse()
+location: class java_cup.parser
+ parser_obj.debug_parse();
+ ^
+Main.java:442: cannot find symbol
+symbol : method parse()
+location: class java_cup.parser
+ parser_obj.parse();
+ ^
+parser.java:25: cannot find symbol
+symbol : method unpackFromStrings(java.lang.String[])
+location: class java_cup.parser
+ unpackFromStrings(new String[] {
+ ^
+parser.java:66: cannot find symbol
+symbol : method unpackFromStrings(java.lang.String[])
+location: class java_cup.parser
+ unpackFromStrings(new String[] {
+ ^
+parser.java:252: cannot find symbol
+symbol : method unpackFromStrings(java.lang.String[])
+location: class java_cup.parser
+ unpackFromStrings(new String[] {
+ ^
+parser.java:382: cannot find symbol
+symbol : method done_parsing()
+location: class java_cup.parser
+ done_parsing();
+ ^
+parser.java:503: package java_cup.runtime does not exist
+ java_cup.runtime.Symbol CUP$parser$result;
+ ^
+parser.java:513: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(29/*empty*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:513: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(29/*empty*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:513: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(29/*empty*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:522: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(7/*opt_semi*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:522: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(7/*opt_semi*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:522: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(7/*opt_semi*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:531: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(7/*opt_semi*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:531: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(7/*opt_semi*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:531: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(7/*opt_semi*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:540: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(8/*non_terminal*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:540: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(8/*non_terminal*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:540: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(8/*non_terminal*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:549: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(8/*non_terminal*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:549: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(8/*non_terminal*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:549: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(8/*non_terminal*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:561: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:561: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:561: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:570: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:570: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:570: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:579: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:579: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:579: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:588: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:588: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:588: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:597: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:597: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:597: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:606: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:606: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:606: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:615: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:615: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:615: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:624: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:624: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:624: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:633: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:633: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:633: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:642: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:642: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:642: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:651: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:651: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:651: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:660: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:660: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:660: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:669: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:669: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:669: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:678: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:678: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:678: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:687: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:687: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:687: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:695: package java_cup.runtime does not exist
+ int the_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ ^
+parser.java:696: package java_cup.runtime does not exist
+ int the_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ ^
+parser.java:697: package java_cup.runtime does not exist
+ String the_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ ^
+parser.java:699: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:699: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:699: package java_cup.runtime does not exist
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ ^
+parser.java:707: package java_cup.runtime does not exist
+ int the_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ ^
+parser.java:708: package java_cup.runtime does not exist
+ int the_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ ^
+parser.java:709: package java_cup.runtime does not exist
+ String the_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ ^
+Note: Some input files use unchecked or unsafe operations.
+Note: Recompile with -Xlint:unchecked for details.
+100 errors
diff --git a/src/java_cup/java_cup/lr_item_core.java b/src/java_cup/java_cup/lr_item_core.java
new file mode 100644
index 0000000..c0fa656
--- /dev/null
+++ b/src/java_cup/java_cup/lr_item_core.java
@@ -0,0 +1,280 @@
+
+package java_cup;
+
+/** The "core" of an LR item. This includes a production and the position
+ * of a marker (the "dot") within the production. Typically item cores
+ * are written using a production with an embedded "dot" to indicate their
+ * position. For example: <pre>
+ * A ::= B * C d E
+ * </pre>
+ * This represents a point in a parse where the parser is trying to match
+ * the given production, and has succeeded in matching everything before the
+ * "dot" (and hence is expecting to see the symbols after the dot next). See
+ * lalr_item, lalr_item_set, and lalr_start for full details on the meaning
+ * and use of items.
+ *
+ * @see java_cup.lalr_item
+ * @see java_cup.lalr_item_set
+ * @see java_cup.lalr_state
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+*/
+
+public class lr_item_core {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param prod production this item uses.
+ * @param pos position of the "dot" within the item.
+ */
+ public lr_item_core(production prod, int pos) throws internal_error
+ {
+ symbol after_dot = null;
+ production_part part;
+
+ if (prod == null)
+ throw new internal_error(
+ "Attempt to create an lr_item_core with a null production");
+
+ _the_production = prod;
+
+ if (pos < 0 || pos > _the_production.rhs_length())
+ throw new internal_error(
+ "Attempt to create an lr_item_core with a bad dot position");
+
+ _dot_pos = pos;
+
+ /* compute and cache hash code now */
+ _core_hash_cache = 13*_the_production.hashCode() + pos;
+
+ /* cache the symbol after the dot */
+ if (_dot_pos < _the_production.rhs_length())
+ {
+ part = _the_production.rhs(_dot_pos);
+ if (!part.is_action())
+ _symbol_after_dot = ((symbol_part)part).the_symbol();
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor for dot at start of right hand side.
+ * @param prod production this item uses.
+ */
+ public lr_item_core(production prod) throws internal_error
+ {
+ this(prod,0);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The production for the item. */
+ protected production _the_production;
+
+ /** The production for the item. */
+ public production the_production() {return _the_production;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The position of the "dot" -- this indicates the part of the production
+ * that the marker is before, so 0 indicates a dot at the beginning of
+ * the RHS.
+ */
+ protected int _dot_pos;
+
+ /** The position of the "dot" -- this indicates the part of the production
+ * that the marker is before, so 0 indicates a dot at the beginning of
+ * the RHS.
+ */
+ public int dot_pos() {return _dot_pos;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Cache of the hash code. */
+ protected int _core_hash_cache;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Cache of symbol after the dot. */
+ protected symbol _symbol_after_dot = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Is the dot at the end of the production? */
+ public boolean dot_at_end()
+ {
+ return _dot_pos >= _the_production.rhs_length();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return the symbol after the dot. If there is no symbol after the dot
+ * we return null. */
+ public symbol symbol_after_dot()
+ {
+ /* use the cached symbol */
+ return _symbol_after_dot;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if we have a dot before a non terminal, and if so which one
+ * (return null or the non terminal).
+ */
+ public non_terminal dot_before_nt()
+ {
+ symbol sym;
+
+ /* get the symbol after the dot */
+ sym = symbol_after_dot();
+
+ /* if it exists and is a non terminal, return it */
+ if (sym != null && sym.is_non_term())
+ return (non_terminal)sym;
+ else
+ return null;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a new lr_item_core that results from shifting the dot one
+ * position to the right.
+ */
+ public lr_item_core shift_core() throws internal_error
+ {
+ if (dot_at_end())
+ throw new internal_error(
+ "Attempt to shift past end of an lr_item_core");
+
+ return new lr_item_core(_the_production, _dot_pos+1);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison for the core only. This is separate out because we
+ * need separate access in a super class.
+ */
+ public boolean core_equals(lr_item_core other)
+ {
+ return other != null &&
+ _the_production.equals(other._the_production) &&
+ _dot_pos == other._dot_pos;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(lr_item_core other) {return core_equals(other);}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof lr_item_core))
+ return false;
+ else
+ return equals((lr_item_core)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Hash code for the core (separated so we keep non overridden version). */
+ public int core_hashCode()
+ {
+ return _core_hash_cache;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Hash code for the item. */
+ public int hashCode()
+ {
+ return _core_hash_cache;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return the hash code that object would have provided for us so we have
+ * a (nearly) unique id for debugging.
+ */
+ protected int obj_hash()
+ {
+ return super.hashCode();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string (separated out from toString() so we can call it
+ * from subclass that overrides toString()).
+ */
+ public String to_simple_string() throws internal_error
+ {
+ String result;
+ production_part part;
+
+ if (_the_production.lhs() != null &&
+ _the_production.lhs().the_symbol() != null &&
+ _the_production.lhs().the_symbol().name() != null)
+ result = _the_production.lhs().the_symbol().name();
+ else
+ result = "$$NULL$$";
+
+ result += " ::= ";
+
+ for (int i = 0; i<_the_production.rhs_length(); i++)
+ {
+ /* do we need the dot before this one? */
+ if (i == _dot_pos)
+ result += "(*) ";
+
+ /* print the name of the part */
+ if (_the_production.rhs(i) == null)
+ {
+ result += "$$NULL$$ ";
+ }
+ else
+ {
+ part = _the_production.rhs(i);
+ if (part == null)
+ result += "$$NULL$$ ";
+ else if (part.is_action())
+ result += "{ACTION} ";
+ else if (((symbol_part)part).the_symbol() != null &&
+ ((symbol_part)part).the_symbol().name() != null)
+ result += ((symbol_part)part).the_symbol().name() + " ";
+ else
+ result += "$$NULL$$ ";
+ }
+ }
+
+ /* put the dot after if needed */
+ if (_dot_pos == _the_production.rhs_length())
+ result += "(*) ";
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string */
+ public String toString()
+ {
+ /* can't throw here since super class doesn't, so we crash instead */
+ try {
+ return to_simple_string();
+ } catch(internal_error e) {
+ e.crash();
+ return null;
+ }
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
diff --git a/src/java_cup/java_cup/non_terminal.java b/src/java_cup/java_cup/non_terminal.java
new file mode 100644
index 0000000..9354a7f
--- /dev/null
+++ b/src/java_cup/java_cup/non_terminal.java
@@ -0,0 +1,301 @@
+package java_cup;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/** This class represents a non-terminal symbol in the grammar. Each
+ * non terminal has a textual name, an index, and a string which indicates
+ * the type of object it will be implemented with at runtime (i.e. the class
+ * of object that will be pushed on the parse stack to represent it).
+ *
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+
+public class non_terminal extends symbol {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param nm the name of the non terminal.
+ * @param tp the type string for the non terminal.
+ */
+ public non_terminal(String nm, String tp)
+ {
+ /* super class does most of the work */
+ super(nm, tp);
+
+ /* add to set of all non terminals and check for duplicates */
+ Object conflict = _all.put(nm,this);
+ if (conflict != null)
+ // can't throw an exception here because these are used in static
+ // initializers, so we crash instead
+ // was:
+ // throw new internal_error("Duplicate non-terminal ("+nm+") created");
+ (new internal_error("Duplicate non-terminal ("+nm+") created")).crash();
+
+ /* assign a unique index */
+ _index = next_index++;
+
+ /* add to by_index set */
+ _all_by_index.put(new Integer(_index), this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with default type.
+ * @param nm the name of the non terminal.
+ */
+ public non_terminal(String nm)
+ {
+ this(nm, null);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Table of all non-terminals -- elements are stored using name strings
+ * as the key
+ */
+ protected static Hashtable _all = new Hashtable();
+
+ /** Access to all non-terminals. */
+ public static Enumeration all() {return _all.elements();}
+
+ /** lookup a non terminal by name string */
+ public static non_terminal find(String with_name)
+ {
+ if (with_name == null)
+ return null;
+ else
+ return (non_terminal)_all.get(with_name);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Table of all non terminals indexed by their index number. */
+ protected static Hashtable _all_by_index = new Hashtable();
+
+ /** Lookup a non terminal by index. */
+ public static non_terminal find(int indx)
+ {
+ Integer the_indx = new Integer(indx);
+
+ return (non_terminal)_all_by_index.get(the_indx);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Total number of non-terminals. */
+ public static int number() {return _all.size();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Static counter to assign unique indexes. */
+ protected static int next_index = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Static counter for creating unique non-terminal names */
+ static protected int next_nt = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** special non-terminal for start symbol */
+ public static final non_terminal START_nt = new non_terminal("$START");
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** flag non-terminals created to embed action productions */
+ public boolean is_embedded_action = false; /* added 24-Mar-1998, CSA */
+
+ /*-----------------------------------------------------------*/
+ /*--- Static Methods ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Method for creating a new uniquely named hidden non-terminal using
+ * the given string as a base for the name (or "NT$" if null is passed).
+ * @param prefix base name to construct unique name from.
+ */
+ static non_terminal create_new(String prefix) throws internal_error
+ {
+ if (prefix == null) prefix = "NT$";
+ return new non_terminal(prefix + next_nt++);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** static routine for creating a new uniquely named hidden non-terminal */
+ static non_terminal create_new() throws internal_error
+ {
+ return create_new(null);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute nullability of all non-terminals. */
+ public static void compute_nullability() throws internal_error
+ {
+ boolean change = true;
+ non_terminal nt;
+ Enumeration e;
+ production prod;
+
+ /* repeat this process until there is no change */
+ while (change)
+ {
+ /* look for a new change */
+ change = false;
+
+ /* consider each non-terminal */
+ for (e=all(); e.hasMoreElements(); )
+ {
+ nt = (non_terminal)e.nextElement();
+
+ /* only look at things that aren't already marked nullable */
+ if (!nt.nullable())
+ {
+ if (nt.looks_nullable())
+ {
+ nt._nullable = true;
+ change = true;
+ }
+ }
+ }
+ }
+
+ /* do one last pass over the productions to finalize all of them */
+ for (e=production.all(); e.hasMoreElements(); )
+ {
+ prod = (production)e.nextElement();
+ prod.set_nullable(prod.check_nullable());
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute first sets for all non-terminals. This assumes nullability has
+ * already computed.
+ */
+ public static void compute_first_sets() throws internal_error
+ {
+ boolean change = true;
+ Enumeration n;
+ Enumeration p;
+ non_terminal nt;
+ production prod;
+ terminal_set prod_first;
+
+ /* repeat this process until we have no change */
+ while (change)
+ {
+ /* look for a new change */
+ change = false;
+
+ /* consider each non-terminal */
+ for (n = all(); n.hasMoreElements(); )
+ {
+ nt = (non_terminal)n.nextElement();
+
+ /* consider every production of that non terminal */
+ for (p = nt.productions(); p.hasMoreElements(); )
+ {
+ prod = (production)p.nextElement();
+
+ /* get the updated first of that production */
+ prod_first = prod.check_first_set();
+
+ /* if this going to add anything, add it */
+ if (!prod_first.is_subset_of(nt._first_set))
+ {
+ change = true;
+ nt._first_set.add(prod_first);
+ }
+ }
+ }
+ }
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Table of all productions with this non terminal on the LHS. */
+ protected Hashtable _productions = new Hashtable(11);
+
+ /** Access to productions with this non terminal on the LHS. */
+ public Enumeration productions() {return _productions.elements();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Total number of productions with this non terminal on the LHS. */
+ public int num_productions() {return _productions.size();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a production to our set of productions. */
+ public void add_production(production prod) throws internal_error
+ {
+ /* catch improper productions */
+ if (prod == null || prod.lhs() == null || prod.lhs().the_symbol() != this)
+ throw new internal_error(
+ "Attempt to add invalid production to non terminal production table");
+
+ /* add it to the table, keyed with itself */
+ _productions.put(prod,prod);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Nullability of this non terminal. */
+ protected boolean _nullable;
+
+ /** Nullability of this non terminal. */
+ public boolean nullable() {return _nullable;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** First set for this non-terminal. */
+ protected terminal_set _first_set = new terminal_set();
+
+ /** First set for this non-terminal. */
+ public terminal_set first_set() {return _first_set;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Indicate that this symbol is a non-terminal. */
+ public boolean is_non_term()
+ {
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Test to see if this non terminal currently looks nullable. */
+ protected boolean looks_nullable() throws internal_error
+ {
+ /* look and see if any of the productions now look nullable */
+ for (Enumeration e = productions(); e.hasMoreElements(); )
+ /* if the production can go to empty, we are nullable */
+ if (((production)e.nextElement()).check_nullable())
+ return true;
+
+ /* none of the productions can go to empty, so we are not nullable */
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** convert to string */
+ public String toString()
+ {
+ return super.toString() + "[" + index() + "]" + (nullable() ? "*" : "");
+ }
+
+ /*-----------------------------------------------------------*/
+}
diff --git a/src/java_cup/java_cup/nonassoc_action.java b/src/java_cup/java_cup/nonassoc_action.java
new file mode 100644
index 0000000..3882324
--- /dev/null
+++ b/src/java_cup/java_cup/nonassoc_action.java
@@ -0,0 +1,71 @@
+
+package java_cup;
+
+/** This class represents a shift/reduce nonassociative error within the
+ * parse table. If action_table element is assign to type
+ * nonassoc_action, it cannot be changed, and signifies that there
+ * is a conflict between shifting and reducing a production and a
+ * terminal that shouldn't be next to each other.
+ *
+ * @version last updated: 7/2/96
+ * @author Frank Flannery
+ */
+public class nonassoc_action extends parse_action {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor.
+ */
+ public nonassoc_action() throws internal_error
+ {
+ /* don't need to set anything, since it signifies error */
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Quick access to type of action. */
+ public int kind() {return NONASSOC;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality test. */
+ public boolean equals(parse_action other)
+ {
+ return other != null && other.kind() == NONASSOC;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality test. */
+ public boolean equals(Object other)
+ {
+ if (other instanceof parse_action)
+ return equals((parse_action)other);
+ else
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute a hash code. */
+ public int hashCode()
+ {
+ /* all objects of this class hash together */
+ return 0xCafe321;
+ }
+
+
+
+ /** Convert to string. */
+ public String toString()
+ {
+ return "NONASSOC";
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/java_cup/java_cup/parse_action.java b/src/java_cup/java_cup/parse_action.java
new file mode 100644
index 0000000..9228663
--- /dev/null
+++ b/src/java_cup/java_cup/parse_action.java
@@ -0,0 +1,92 @@
+
+package java_cup;
+
+/** This class serves as the base class for entries in a parse action table.
+ * Full entries will either be SHIFT(state_num), REDUCE(production), NONASSOC,
+ * or ERROR. Objects of this base class will default to ERROR, while
+ * the other three types will be represented by subclasses.
+ *
+ * @see java_cup.reduce_action
+ * @see java_cup.shift_action
+ * @version last updated: 7/2/96
+ * @author Frank Flannery
+ */
+
+public class parse_action {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. */
+ public parse_action()
+ {
+ /* nothing to do in the base class */
+ }
+
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constant for action type -- error action. */
+ public static final int ERROR = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constant for action type -- shift action. */
+ public static final int SHIFT = 1;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constants for action type -- reduce action. */
+ public static final int REDUCE = 2;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constants for action type -- reduce action. */
+ public static final int NONASSOC = 3;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Quick access to the type -- base class defaults to error. */
+ public int kind() {return ERROR;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality test. */
+ public boolean equals(parse_action other)
+ {
+ /* we match all error actions */
+ return other != null && other.kind() == ERROR;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality test. */
+ public boolean equals(Object other)
+ {
+ if (other instanceof parse_action)
+ return equals((parse_action)other);
+ else
+ return false;
+ }
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute a hash code. */
+ public int hashCode()
+ {
+ /* all objects of this class hash together */
+ return 0xCafe123;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to string. */
+ public String toString() {return "ERROR";}
+
+ /*-----------------------------------------------------------*/
+}
+
diff --git a/src/java_cup/java_cup/parse_action_row.java b/src/java_cup/java_cup/parse_action_row.java
new file mode 100644
index 0000000..817b8c5
--- /dev/null
+++ b/src/java_cup/java_cup/parse_action_row.java
@@ -0,0 +1,106 @@
+
+package java_cup;
+
+/** This class represents one row (corresponding to one machine state) of the
+ * parse action table.
+ */
+public class parse_action_row {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. Note: this should not be used until the number of
+ * terminals in the grammar has been established.
+ */
+ public parse_action_row()
+ {
+ /* make sure the size is set */
+ if (_size <= 0 ) _size = terminal.number();
+
+ /* allocate the array */
+ under_term = new parse_action[size()];
+
+ /* set each element to an error action */
+ for (int i=0; i<_size; i++)
+ under_term[i] = new parse_action();
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Number of columns (terminals) in every row. */
+ protected static int _size = 0;
+
+ /** Number of columns (terminals) in every row. */
+ public static int size() {return _size;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Table of reduction counts (reused by compute_default()). */
+ protected static int reduction_count[] = null;
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Actual action entries for the row. */
+ public parse_action under_term[];
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Default (reduce) action for this row. -1 will represent default
+ * of error.
+ */
+ public int default_reduce;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Compute the default (reduce) action for this row and store it in
+ * default_reduce. In the case of non-zero default we will have the
+ * effect of replacing all errors by that reduction. This may cause
+ * us to do erroneous reduces, but will never cause us to shift past
+ * the point of the error and never cause an incorrect parse. -1 will
+ * be used to encode the fact that no reduction can be used as a
+ * default (in which case error will be used).
+ */
+ public void compute_default()
+ {
+ int i, prod, max_prod, max_red;
+
+ /* if we haven't allocated the count table, do so now */
+ if (reduction_count == null)
+ reduction_count = new int[production.number()];
+
+ /* clear the reduction count table and maximums */
+ for (i = 0; i < production.number(); i++)
+ reduction_count[i] = 0;
+ max_prod = -1;
+ max_red = 0;
+
+ /* walk down the row and look at the reduces */
+ for (i = 0; i < size(); i++)
+ if (under_term[i].kind() == parse_action.REDUCE)
+ {
+ /* count the reduce in the proper production slot and keep the
+ max up to date */
+ prod = ((reduce_action)under_term[i]).reduce_with().index();
+ reduction_count[prod]++;
+ if (reduction_count[prod] > max_red)
+ {
+ max_red = reduction_count[prod];
+ max_prod = prod;
+ }
+ }
+
+ /* record the max as the default (or -1 for not found) */
+ default_reduce = max_prod;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
diff --git a/src/java_cup/java_cup/parse_action_table.java b/src/java_cup/java_cup/parse_action_table.java
new file mode 100644
index 0000000..1e0edb2
--- /dev/null
+++ b/src/java_cup/java_cup/parse_action_table.java
@@ -0,0 +1,143 @@
+
+package java_cup;
+
+import java.util.Enumeration;
+
+/** This class represents the complete "action" table of the parser.
+ * It has one row for each state in the parse machine, and a column for
+ * each terminal symbol. Each entry in the table represents a shift,
+ * reduce, or an error.
+ *
+ * @see java_cup.parse_action
+ * @see java_cup.parse_action_row
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class parse_action_table {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. All terminals, non-terminals, and productions must
+ * already have been entered, and the viable prefix recognizer should
+ * have been constructed before this is called.
+ */
+ public parse_action_table()
+ {
+ /* determine how many states we are working with */
+ _num_states = lalr_state.number();
+
+ /* allocate the array and fill it in with empty rows */
+ under_state = new parse_action_row[_num_states];
+ for (int i=0; i<_num_states; i++)
+ under_state[i] = new parse_action_row();
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** How many rows/states are in the machine/table. */
+ protected int _num_states;
+
+ /** How many rows/states are in the machine/table. */
+ public int num_states() {return _num_states;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Actual array of rows, one per state. */
+ public parse_action_row[] under_state;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Check the table to ensure that all productions have been reduced.
+ * Issue a warning message (to System.err) for each production that
+ * is never reduced.
+ */
+ public void check_reductions()
+ throws internal_error
+ {
+ parse_action act;
+ production prod;
+
+ /* tabulate reductions -- look at every table entry */
+ for (int row = 0; row < num_states(); row++)
+ {
+ for (int col = 0; col < under_state[row].size(); col++)
+ {
+ /* look at the action entry to see if its a reduce */
+ act = under_state[row].under_term[col];
+ if (act != null && act.kind() == parse_action.REDUCE)
+ {
+ /* tell production that we used it */
+ ((reduce_action)act).reduce_with().note_reduction_use();
+ }
+ }
+ }
+
+ /* now go across every production and make sure we hit it */
+ for (Enumeration p = production.all(); p.hasMoreElements(); )
+ {
+ prod = (production)p.nextElement();
+
+ /* if we didn't hit it give a warning */
+ if (prod.num_reductions() == 0)
+ {
+ /* count it *
+ emit.not_reduced++;
+
+ /* give a warning if they haven't been turned off */
+ if (!emit.nowarn)
+ {
+ System.err.println("*** Production \"" +
+ prod.to_simple_string() + "\" never reduced");
+ lexer.warning_count++;
+ }
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+ int cnt;
+
+ result = "-------- ACTION_TABLE --------\n";
+ for (int row = 0; row < num_states(); row++)
+ {
+ result += "From state #" + row + "\n";
+ cnt = 0;
+ for (int col = 0; col < under_state[row].size(); col++)
+ {
+ /* if the action is not an error print it */
+ if (under_state[row].under_term[col].kind() != parse_action.ERROR)
+ {
+ result += " [term " + col + ":" + under_state[row].under_term[col] + "]";
+
+ /* end the line after the 2nd one */
+ cnt++;
+ if (cnt == 2)
+ {
+ result += "\n";
+ cnt = 0;
+ }
+ }
+ }
+ /* finish the line if we haven't just done that */
+ if (cnt != 0) result += "\n";
+ }
+ result += "------------------------------";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
diff --git a/src/java_cup/java_cup/parse_reduce_row.java b/src/java_cup/java_cup/parse_reduce_row.java
new file mode 100644
index 0000000..57d978e
--- /dev/null
+++ b/src/java_cup/java_cup/parse_reduce_row.java
@@ -0,0 +1,41 @@
+
+package java_cup;
+
+/** This class represents one row (corresponding to one machine state) of the
+ * reduce-goto parse table.
+ */
+public class parse_reduce_row {
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. Note: this should not be used until the number
+ * of terminals in the grammar has been established.
+ */
+ public parse_reduce_row()
+ {
+ /* make sure the size is set */
+ if (_size <= 0 ) _size = non_terminal.number();
+
+ /* allocate the array */
+ under_non_term = new lalr_state[size()];
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Number of columns (non terminals) in every row. */
+ protected static int _size = 0;
+
+ /** Number of columns (non terminals) in every row. */
+ public static int size() {return _size;}
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Actual entries for the row. */
+ public lalr_state under_non_term[];
+}
+
diff --git a/src/java_cup/java_cup/parse_reduce_table.java b/src/java_cup/java_cup/parse_reduce_table.java
new file mode 100644
index 0000000..9ac1b11
--- /dev/null
+++ b/src/java_cup/java_cup/parse_reduce_table.java
@@ -0,0 +1,99 @@
+
+package java_cup;
+
+import java.util.Enumeration;
+
+/** This class represents the complete "reduce-goto" table of the parser.
+ * It has one row for each state in the parse machines, and a column for
+ * each terminal symbol. Each entry contains a state number to shift to
+ * as the last step of a reduce.
+ *
+ * @see java_cup.parse_reduce_row
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class parse_reduce_table {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. Note: all terminals, non-terminals, and productions
+ * must already have been entered, and the viable prefix recognizer should
+ * have been constructed before this is called.
+ */
+ public parse_reduce_table()
+ {
+ /* determine how many states we are working with */
+ _num_states = lalr_state.number();
+
+ /* allocate the array and fill it in with empty rows */
+ under_state = new parse_reduce_row[_num_states];
+ for (int i=0; i<_num_states; i++)
+ under_state[i] = new parse_reduce_row();
+ }
+
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** How many rows/states in the machine/table. */
+ protected int _num_states;
+
+ /** How many rows/states in the machine/table. */
+ public int num_states() {return _num_states;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Actual array of rows, one per state */
+ public parse_reduce_row[] under_state;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+ lalr_state goto_st;
+ int cnt;
+
+ result = "-------- REDUCE_TABLE --------\n";
+ for (int row = 0; row < num_states(); row++)
+ {
+ result += "From state #" + row + "\n";
+ cnt = 0;
+ for (int col = 0; col < under_state[row].size(); col++)
+ {
+ /* pull out the table entry */
+ goto_st = under_state[row].under_non_term[col];
+
+ /* if it has action in it, print it */
+ if (goto_st != null)
+ {
+ result += " [non term " + col + "->";
+ result += "state " + goto_st.index() + "]";
+
+ /* end the line after the 3rd one */
+ cnt++;
+ if (cnt == 3)
+ {
+ result += "\n";
+ cnt = 0;
+ }
+ }
+ }
+ /* finish the line if we haven't just done that */
+ if (cnt != 0) result += "\n";
+ }
+ result += "-----------------------------";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
diff --git a/src/java_cup/java_cup/parser.cup b/src/java_cup/java_cup/parser.cup
new file mode 100644
index 0000000..8af0d05
--- /dev/null
+++ b/src/java_cup/java_cup/parser.cup
@@ -0,0 +1,863 @@
+
+/*================================================================*/
+/*
+ JavaCup Specification for the JavaCup Specification Language
+ by Scott Hudson, GVU Center, Georgia Tech, August 1995
+ and Frank Flannery, Department of Computer Science, Princeton Univ,
+ July 1996
+ Bug Fixes: C. Scott Ananian, Dept of Electrical Engineering, Princeton
+ University, October 1996. [later Massachusetts Institute of Technology]
+
+
+ This JavaCup specification is used to implement JavaCup itself.
+ It specifies the parser for the JavaCup specification language.
+ (It also serves as a reasonable example of what a typical JavaCup
+ spec looks like).
+
+ The specification has the following parts:
+ Package and import declarations
+ These serve the same purpose as in a normal Java source file
+ (and will appear in the generated code for the parser). In this
+ case we are part of the java_cup package and we import both the
+ java_cup runtime system and Hashtable from the standard Java
+ utilities package.
+
+ Action code
+ This section provides code that is included with the class encapsulating
+ the various pieces of user code embedded in the grammar (i.e., the
+ semantic actions). This provides a series of helper routines and
+ data structures that the semantic actions use.
+
+ Parser code
+ This section provides code included in the parser class itself. In
+ this case we override the default error reporting routines.
+
+ Init with and scan with
+ These sections provide small bits of code that initialize, then
+ indicate how to invoke the scanner.
+
+ Symbols and grammar
+ These sections declare all the terminal and non terminal symbols
+ and the types of objects that they will be represented by at runtime,
+ then indicate the start symbol of the grammar (), and finally provide
+ the grammar itself (with embedded actions).
+
+ Operation of the parser
+ The parser acts primarily by accumulating data structures representing
+ various parts of the specification. Various small parts (e.g., single
+ code strings) are stored as static variables of the emit class and
+ in a few cases as variables declared in the action code section.
+ Terminals, non terminals, and productions, are maintained as collection
+ accessible via static methods of those classes. In addition, two
+ symbol tables are kept:
+ symbols maintains the name to object mapping for all symbols
+ non_terms maintains a separate mapping containing only the non terms
+
+ Several intermediate working structures are also declared in the action
+ code section. These include: rhs_parts, rhs_pos, and lhs_nt which
+ build up parts of the current production while it is being parsed.
+
+ Author(s)
+ Scott Hudson, GVU Center, Georgia Tech.
+ Frank Flannery, Department of Computer Science, Princeton Univ.
+ C. Scott Ananian, Department of Electrical Engineering, Princeton Univ.
+
+ Revisions
+ v0.9a First released version [SEH] 8/29/95
+ v0.9b Updated for beta language (throws clauses) [SEH] 11/25/95
+ v0.10a Made many improvements/changes. now offers:
+ return value
+ left/right positions and propagations
+ cleaner label references
+ precedence and associativity for terminals
+ contextual precedence for productions
+ [FF] 7/3/96
+ v0.10b Fixed %prec directive so it works like it's supposed to.
+ [CSA] 10/10/96
+ v0.10g Added support for array types on symbols.
+ [CSA] 03/23/98
+ v0.10i Broaden set of IDs allowed in multipart_id and label_id so
+ that only java reserved words (and not CUP reserved words like
+ 'parser' and 'start') are prohibited. Allow reordering of
+ action code, parser code, init code, and scan with sections,
+ and made closing semicolon optional for these sections.
+ Added 'nonterminal' as a terminal symbol, finally fixing a
+ spelling mistake that's been around since the beginning.
+ For backwards compatibility, you can still misspell the
+ word if you like.
+*/
+/*================================================================*/
+
+package java_cup;
+import java_cup.runtime.*;
+import java.util.Hashtable;
+
+/*----------------------------------------------------------------*/
+
+action code {:
+ /** helper routine to clone a new production part adding a given label */
+ protected production_part add_lab(production_part part, String lab)
+ throws internal_error
+ {
+ /* if there is no label, or this is an action, just return the original */
+ if (lab == null || part.is_action()) return part;
+
+ /* otherwise build a new one with the given label attached */
+ return new symbol_part(((symbol_part)part).the_symbol(),lab);
+ }
+
+ /** max size of right hand side we will support */
+ protected final int MAX_RHS = 200;
+
+ /** array for accumulating right hand side parts */
+ protected production_part[] rhs_parts = new production_part[MAX_RHS];
+
+ /** where we are currently in building a right hand side */
+ protected int rhs_pos = 0;
+
+ /** start a new right hand side */
+ protected void new_rhs() {rhs_pos = 0; }
+
+ /** add a new right hand side part */
+ protected void add_rhs_part(production_part part) throws java.lang.Exception
+ {
+ if (rhs_pos >= MAX_RHS)
+ throw new Exception("Internal Error: Productions limited to " +
+ MAX_RHS + " symbols and actions");
+
+ rhs_parts[rhs_pos] = part;
+ rhs_pos++;
+ }
+
+ /** string to build up multiple part names */
+ protected String multipart_name = new String();
+
+ /** append a new name segment to the accumulated multipart name */
+ protected void append_multipart(String name)
+ {
+ String dot = "";
+
+ /* if we aren't just starting out, put on a dot */
+ if (multipart_name.length() != 0) dot = ".";
+
+ multipart_name = multipart_name.concat(dot + name);
+ }
+
+ /** table of declared symbols -- contains production parts indexed by name */
+ protected Hashtable symbols = new Hashtable();
+
+ /** table of just non terminals -- contains non_terminals indexed by name */
+ protected Hashtable non_terms = new Hashtable();
+
+ /** declared start non_terminal */
+ protected non_terminal start_nt = null;
+
+ /** left hand side non terminal of the current production */
+ protected non_terminal lhs_nt;
+
+ /** Current precedence number */
+ int _cur_prec = 0;
+
+ /** Current precedence side */
+ int _cur_side = assoc.no_prec;
+
+ /** update the precedences we are declaring */
+ protected void update_precedence(int p) {
+ _cur_side = p;
+ _cur_prec++;
+ }
+ /** add relevant data to terminals */
+ protected void add_precedence(String term) {
+ if (term == null) {
+ System.err.println("Unable to add precedence to nonexistent terminal");
+ } else {
+ symbol_part sp = (symbol_part)symbols.get(term);
+ if (sp == null) {
+ System.err.println("Could find terminal " + term + " while declaring precedence");
+ } else {
+ java_cup.symbol sym = sp.the_symbol();
+ if (sym instanceof terminal)
+ ((terminal)sym).set_precedence(_cur_side, _cur_prec);
+ else System.err.println("Precedence declaration: Can't find terminal " + term);
+ }
+ }
+ }
+:};
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+parser code {:
+
+ /* override error routines */
+
+ public void report_fatal_error(
+ String message,
+ Object info)
+ {
+ done_parsing();
+ lexer.emit_error(message);
+ System.err.println("Can't recover from previous error(s), giving up.");
+ System.exit(1);
+ }
+
+ public void report_error(String message, Object info)
+ {
+ lexer.emit_error(message);
+ }
+:};
+
+/*----------------------------------------------------------------*/
+
+init with {: lexer.init(); :};
+scan with {: return lexer.next_token(); :};
+
+/*----------------------------------------------------------------*/
+
+terminal
+ PACKAGE, IMPORT, CODE, ACTION, PARSER, TERMINAL, NON, INIT, SCAN, WITH,
+ START, SEMI, COMMA, STAR, DOT, COLON, COLON_COLON_EQUALS, BAR, PRECEDENCE,
+ LEFT, RIGHT, NONASSOC, PERCENT_PREC, LBRACK, RBRACK, NONTERMINAL;
+
+terminal String ID, CODE_STRING;
+
+non terminal
+ spec, package_spec, import_list, action_code_part,
+ code_parts, code_part, opt_semi, non_terminal,
+ parser_code_part, symbol_list, start_spec, production_list,
+ multipart_id, import_spec, import_id, init_code, scan_code, symbol,
+ type_id, term_name_list, non_term_name_list, production, prod_part_list,
+ prod_part, new_term_id, new_non_term_id, rhs_list, rhs, empty,
+ precedence_list, preced, terminal_list, precedence_l, declares_term,
+ declares_non_term;
+
+non terminal String nt_id, symbol_id, label_id, opt_label, terminal_id,
+ term_id, robust_id;
+
+/*----------------------------------------------------------------*/
+
+start with spec;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+spec ::=
+ {:
+ /* declare "error" as a terminal */
+ symbols.put("error", new symbol_part(terminal.error));
+
+ /* declare start non terminal */
+ non_terms.put("$START", non_terminal.START_nt);
+ :}
+ package_spec
+ import_list
+ code_parts
+ symbol_list
+ precedence_list
+ start_spec
+ production_list
+ |
+ /* error recovery assuming something went wrong before symbols
+ and we have TERMINAL or NON TERMINAL to sync on. if we get
+ an error after that, we recover inside symbol_list or
+ production_list
+ */
+ error
+ symbol_list
+ precedence_list
+ start_spec
+ production_list
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+package_spec ::=
+ PACKAGE
+ multipart_id
+ {:
+ /* save the package name */
+ emit.package_name = multipart_name;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+import_list ::=
+ import_list
+ import_spec
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+import_spec ::=
+ IMPORT
+ import_id
+ {:
+ /* save this import on the imports list */
+ emit.import_list.push(multipart_name);
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+// allow any order; all parts are optional. [CSA, 23-Jul-1999]
+// (we check in the part action to make sure we don't have 2 of any part)
+code_part ::=
+ action_code_part | parser_code_part | init_code | scan_code ;
+code_parts ::=
+ | code_parts code_part;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+action_code_part ::=
+ ACTION CODE CODE_STRING:user_code opt_semi
+ {:
+ if (emit.action_code!=null)
+ lexer.emit_error("Redundant action code (skipping)");
+ else /* save the user included code string */
+ emit.action_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+parser_code_part ::=
+ PARSER CODE CODE_STRING:user_code opt_semi
+ {:
+ if (emit.parser_code!=null)
+ lexer.emit_error("Redundant parser code (skipping)");
+ else /* save the user included code string */
+ emit.parser_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+init_code ::=
+ INIT WITH CODE_STRING:user_code opt_semi
+ {:
+ if (emit.init_code!=null)
+ lexer.emit_error("Redundant init code (skipping)");
+ else /* save the user code */
+ emit.init_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+scan_code ::=
+ SCAN WITH CODE_STRING:user_code opt_semi
+ {:
+ if (emit.scan_code!=null)
+ lexer.emit_error("Redundant scan code (skipping)");
+ else /* save the user code */
+ emit.scan_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+symbol_list ::= symbol_list symbol | symbol;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+symbol ::=
+ TERMINAL
+ type_id
+ declares_term
+ |
+ TERMINAL
+ declares_term
+ |
+ non_terminal
+ type_id
+ declares_non_term
+ |
+ non_terminal
+ declares_non_term
+ |
+ /* error recovery productions -- sync on semicolon */
+
+ TERMINAL
+ error
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ |
+ non_terminal
+ error
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+declares_term ::=
+ term_name_list
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+declares_non_term ::=
+ non_term_name_list
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+term_name_list ::= term_name_list COMMA new_term_id | new_term_id;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+non_term_name_list ::=
+ non_term_name_list
+ COMMA
+ new_non_term_id
+ |
+ new_non_term_id
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+
+precedence_list ::= precedence_l | empty;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+precedence_l ::= precedence_l preced | preced;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+preced ::=
+ PRECEDENCE LEFT
+ {:
+ update_precedence(assoc.left);
+ :}
+ terminal_list SEMI
+ |
+ PRECEDENCE RIGHT
+ {:
+ update_precedence(assoc.right);
+ :}
+ terminal_list SEMI
+ |
+ PRECEDENCE NONASSOC
+ {:
+ update_precedence(assoc.nonassoc);
+ :}
+ terminal_list SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+terminal_list ::= terminal_list COMMA terminal_id
+ |
+ terminal_id
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+terminal_id ::= term_id:sym
+ {:
+ add_precedence(sym);
+ RESULT = sym;
+ :};
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+term_id ::= symbol_id:sym
+ {:
+ /* check that the symbol_id is a terminal */
+ if (symbols.get(sym) == null)
+ {
+ /* issue a message */
+ lexer.emit_error("Terminal \"" + sym +
+ "\" has not been declared");
+ }
+ RESULT = sym;
+ :};
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+start_spec ::=
+ START WITH nt_id:start_name
+ {:
+ /* verify that the name has been declared as a non terminal */
+ non_terminal nt = (non_terminal)non_terms.get(start_name);
+ if (nt == null)
+ {
+ lexer.emit_error( "Start non terminal \"" + start_name +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* remember the non-terminal for later */
+ start_nt = nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt), "start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+ new_rhs();
+ }
+ :}
+ SEMI
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+production_list ::= production_list production | production;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+production ::=
+ nt_id:lhs_id
+ {:
+ /* lookup the lhs nt */
+ lhs_nt = (non_terminal)non_terms.get(lhs_id);
+
+ /* if it wasn't declared, emit a message */
+ if (lhs_nt == null)
+ {
+ if (lexer.error_count == 0)
+ lexer.emit_error("LHS non terminal \"" + lhs_id +
+ "\" has not been declared");
+ }
+
+ /* reset the rhs accumulation */
+ new_rhs();
+ :}
+ COLON_COLON_EQUALS
+ {: :}
+ rhs_list
+ SEMI
+ |
+ error
+ {: lexer.emit_error("Syntax Error"); :}
+ SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+rhs_list ::= rhs_list BAR rhs | rhs;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+rhs ::=
+ prod_part_list PERCENT_PREC term_id:term_name
+ {:
+ java_cup.symbol sym = null;
+ if (lhs_nt != null)
+ {
+ /* Find the precedence symbol */
+ if (term_name == null) {
+ System.err.println("No terminal for contextual precedence");
+ sym = null;
+ } else {
+ sym = ((symbol_part)symbols.get(term_name)).the_symbol();
+ }
+ /* build the production */
+ production p;
+ if ((sym!=null) && (sym instanceof terminal)) {
+ p = new production(lhs_nt, rhs_parts, rhs_pos,
+ ((terminal)sym).precedence_num(),
+ ((terminal)sym).precedence_side());
+ ((symbol_part)symbols.get(term_name)).the_symbol().note_use();
+ } else {
+ System.err.println("Invalid terminal " + term_name +
+ " for contextual precedence assignment");
+ p = new production(lhs_nt, rhs_parts, rhs_pos);
+ }
+
+ /* if we have no start non-terminal declared and this is
+ the first production, make its lhs nt the start_nt
+ and build a special start production for it. */
+ if (start_nt == null)
+ {
+ start_nt = lhs_nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt),"start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ if ((sym!=null) && (sym instanceof terminal)) {
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts,
+ rhs_pos, ((terminal)sym).precedence_num(),
+ ((terminal)sym).precedence_side());
+ } else {
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+ }
+ new_rhs();
+ }
+ }
+
+ /* reset the rhs accumulation in any case */
+ new_rhs();
+ :}
+ |
+ prod_part_list
+ {:
+ if (lhs_nt != null)
+ {
+ /* build the production */
+ production p = new production(lhs_nt, rhs_parts, rhs_pos);
+
+ /* if we have no start non-terminal declared and this is
+ the first production, make its lhs nt the start_nt
+ and build a special start production for it. */
+ if (start_nt == null)
+ {
+ start_nt = lhs_nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt),"start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+
+ new_rhs();
+ }
+ }
+
+ /* reset the rhs accumulation in any case */
+ new_rhs();
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+prod_part_list ::= prod_part_list prod_part | empty;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+prod_part ::=
+ symbol_id:symid opt_label:labid
+ {:
+ /* try to look up the id */
+ production_part symb = (production_part)symbols.get(symid);
+
+ /* if that fails, symbol is undeclared */
+ if (symb == null)
+ {
+ if (lexer.error_count == 0)
+ lexer.emit_error("java_cup.runtime.Symbol \"" + symid +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* add a labeled production part */
+ add_rhs_part(add_lab(symb, labid));
+ }
+ :}
+ |
+ CODE_STRING:code_str
+ {:
+ /* add a new production part */
+ add_rhs_part(new action_part(code_str));
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+opt_label ::=
+ COLON label_id:labid
+ {: RESULT = labid; :}
+ |
+ empty
+ {: RESULT = null; :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+multipart_id ::=
+ multipart_id DOT robust_id:another_id
+ {: append_multipart(another_id); :}
+ |
+ robust_id:an_id
+ {: append_multipart(an_id); :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+import_id ::=
+ multipart_id DOT STAR
+ {: append_multipart("*"); :}
+ |
+ multipart_id
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+type_id ::= multipart_id
+ | type_id LBRACK RBRACK
+ {: multipart_name = multipart_name.concat("[]"); :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+new_term_id ::=
+ ID:term_id
+ {:
+ /* see if this terminal has been declared before */
+ if (symbols.get(term_id) != null)
+ {
+ /* issue a message */
+ lexer.emit_error("java_cup.runtime.Symbol \"" + term_id +
+ "\" has already been declared");
+ }
+ else
+ {
+ /* if no type declared, declare one */
+ if (multipart_name.equals("")) {
+ append_multipart("Object");
+ }
+ /* build a production_part and put it in the table */
+ symbols.put(term_id,
+ new symbol_part(new terminal(term_id, multipart_name)));
+ }
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+new_non_term_id ::=
+ ID:non_term_id
+ {:
+ /* see if this non terminal has been declared before */
+ if (symbols.get(non_term_id) != null)
+ {
+ /* issue a message */
+ lexer.emit_error( "java_cup.runtime.Symbol \"" + non_term_id +
+ "\" has already been declared");
+ }
+ else
+ {
+ if (multipart_name.equals("")) {
+ append_multipart("Object");
+ }
+ /* build the non terminal object */
+ non_terminal this_nt =
+ new non_terminal(non_term_id, multipart_name);
+
+ /* put it in the non_terms table */
+ non_terms.put(non_term_id, this_nt);
+
+ /* build a production_part and put it in the symbols table */
+ symbols.put(non_term_id, new symbol_part(this_nt));
+ }
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+nt_id ::=
+ ID:the_id
+ {: RESULT = the_id; :}
+ | error
+ {:
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+symbol_id ::=
+ ID:the_id
+ {: RESULT = the_id; :}
+ | error
+ {:
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+label_id ::=
+ robust_id:the_id
+ {: RESULT = the_id; :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+robust_id ::= /* all ids that aren't reserved words in Java */
+ ID:the_id {: RESULT = the_id; :}
+ /* package is reserved. */
+ /* import is reserved. */
+ | CODE {: RESULT = "code"; :}
+ | ACTION {: RESULT = "action"; :}
+ | PARSER {: RESULT = "parser"; :}
+ | TERMINAL {: RESULT = "terminal"; :}
+ | NON {: RESULT = "non"; :}
+ | NONTERMINAL {: RESULT = "nonterminal"; :}
+ | INIT {: RESULT = "init"; :}
+ | SCAN {: RESULT = "scan"; :}
+ | WITH {: RESULT = "with"; :}
+ | START {: RESULT = "start"; :}
+ | PRECEDENCE {: RESULT = "precedence"; :}
+ | LEFT {: RESULT = "left"; :}
+ | RIGHT {: RESULT = "right"; :}
+ | NONASSOC {: RESULT = "nonassoc"; :}
+ | error
+ {:
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+non_terminal ::= NON TERMINAL | NONTERMINAL;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+opt_semi ::= /* nothing */
+ | SEMI;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+empty ::= /* nothing */;
+
+/*----------------------------------------------------------------*/
+
+
+
+
+
+
+
+
+
diff --git a/src/java_cup/java_cup/parser.java b/src/java_cup/java_cup/parser.java
new file mode 100644
index 0000000..163968e
--- /dev/null
+++ b/src/java_cup/java_cup/parser.java
@@ -0,0 +1,1849 @@
+
+//----------------------------------------------------
+// The following code was generated by CUP v0.10k
+// Sun Jul 25 13:35:26 EDT 1999
+//----------------------------------------------------
+
+package java_cup;
+
+import java_cup.runtime.*;
+import java.util.Hashtable;
+
+/** CUP v0.10k generated parser.
+ * @version Sun Jul 25 13:35:26 EDT 1999
+ */
+public class parser extends java_cup.runtime.lr_parser {
+
+ /** Default constructor. */
+ public parser() {super();}
+
+ /** Constructor which sets the default scanner. */
+ public parser(java_cup.runtime.Scanner s) {super(s);}
+
+ /** Production table. */
+ protected static final short _production_table[][] =
+ unpackFromStrings(new String[] {
+ "\000\153\000\002\002\004\000\002\055\002\000\002\003" +
+ "\012\000\002\003\007\000\002\056\002\000\002\004\006" +
+ "\000\002\004\003\000\002\005\004\000\002\005\003\000" +
+ "\002\057\002\000\002\020\006\000\002\010\003\000\002" +
+ "\010\003\000\002\010\003\000\002\010\003\000\002\007" +
+ "\002\000\002\007\004\000\002\006\006\000\002\013\006" +
+ "\000\002\022\006\000\002\023\006\000\002\014\004\000" +
+ "\002\014\003\000\002\024\005\000\002\024\004\000\002" +
+ "\024\005\000\002\024\004\000\002\060\002\000\002\024" +
+ "\006\000\002\061\002\000\002\024\006\000\002\062\002" +
+ "\000\002\044\005\000\002\063\002\000\002\045\005\000" +
+ "\002\026\005\000\002\026\003\000\002\027\005\000\002" +
+ "\027\003\000\002\040\003\000\002\040\003\000\002\043" +
+ "\004\000\002\043\003\000\002\064\002\000\002\041\007" +
+ "\000\002\065\002\000\002\041\007\000\002\066\002\000" +
+ "\002\041\007\000\002\042\005\000\002\042\003\000\002" +
+ "\052\003\000\002\053\003\000\002\067\002\000\002\015" +
+ "\007\000\002\015\003\000\002\016\004\000\002\016\003" +
+ "\000\002\070\002\000\002\071\002\000\002\030\010\000" +
+ "\002\072\002\000\002\030\005\000\002\035\005\000\002" +
+ "\035\003\000\002\036\005\000\002\036\003\000\002\031" +
+ "\004\000\002\031\003\000\002\032\004\000\002\032\003" +
+ "\000\002\051\004\000\002\051\003\000\002\017\005\000" +
+ "\002\017\003\000\002\021\005\000\002\021\003\000\002" +
+ "\025\003\000\002\025\005\000\002\033\003\000\002\034" +
+ "\003\000\002\046\003\000\002\046\003\000\002\047\003" +
+ "\000\002\047\003\000\002\050\003\000\002\054\003\000" +
+ "\002\054\003\000\002\054\003\000\002\054\003\000\002" +
+ "\054\003\000\002\054\003\000\002\054\003\000\002\054" +
+ "\003\000\002\054\003\000\002\054\003\000\002\054\003" +
+ "\000\002\054\003\000\002\054\003\000\002\054\003\000" +
+ "\002\054\003\000\002\054\003\000\002\012\004\000\002" +
+ "\012\003\000\002\011\002\000\002\011\003\000\002\037" +
+ "\002" });
+
+ /** Access to production table. */
+ public short[][] production_table() {return _production_table;}
+
+ /** Parse-action table. */
+ protected static final short[][] _action_table =
+ unpackFromStrings(new String[] {
+ "\000\247\000\026\003\006\004\000\005\000\007\000\010" +
+ "\000\011\000\012\000\013\000\014\000\035\000\001\002" +
+ "\000\004\002\251\001\002\000\024\004\200\005\uff97\007" +
+ "\uff97\010\uff97\011\uff97\012\uff97\013\uff97\014\uff97\035\uff97" +
+ "\001\002\000\010\011\007\012\012\035\014\001\002\000" +
+ "\042\003\163\006\026\007\027\010\040\011\036\012\022" +
+ "\013\042\014\030\015\017\016\015\026\033\027\023\030" +
+ "\035\031\041\035\025\036\160\001\002\000\020\003\uffeb" +
+ "\011\uffeb\012\uffeb\016\uffeb\026\uffeb\035\uffeb\036\uffeb\001" +
+ "\002\000\020\003\uff97\011\007\012\012\016\uff97\026\065" +
+ "\035\014\036\uff97\001\002\000\004\011\061\001\002\000" +
+ "\042\003\034\006\026\007\027\010\040\011\036\012\022" +
+ "\013\042\014\030\015\017\016\015\026\033\027\023\030" +
+ "\035\031\041\035\025\036\016\001\002\000\042\003\uff9a" +
+ "\006\uff9a\007\uff9a\010\uff9a\011\uff9a\012\uff9a\013\uff9a\014" +
+ "\uff9a\015\uff9a\016\uff9a\026\uff9a\027\uff9a\030\uff9a\031\uff9a" +
+ "\035\uff9a\036\uff9a\001\002\000\022\003\uffa1\017\uffa1\022" +
+ "\uffa1\025\uffa1\032\uffa1\033\uffa1\036\uffa1\037\uffa1\001\002" +
+ "\000\014\017\uffb1\020\uffb1\022\uffab\033\uffab\036\uffab\001" +
+ "\002\000\022\003\uffa2\017\uffa2\022\uffa2\025\uffa2\032\uffa2" +
+ "\033\uffa2\036\uffa2\037\uffa2\001\002\000\006\017\uffe0\020" +
+ "\055\001\002\000\010\022\051\033\uffb4\036\uffb4\001\002" +
+ "\000\022\003\uffa6\017\uffa6\022\uffa6\025\uffa6\032\uffa6\033" +
+ "\uffa6\036\uffa6\037\uffa6\001\002\000\022\003\uff9f\017\uff9f" +
+ "\022\uff9f\025\uff9f\032\uff9f\033\uff9f\036\uff9f\037\uff9f\001" +
+ "\002\000\006\033\047\036\045\001\002\000\022\003\uffa5" +
+ "\017\uffa5\022\uffa5\025\uffa5\032\uffa5\033\uffa5\036\uffa5\037" +
+ "\uffa5\001\002\000\022\003\uffaa\017\uffaa\022\uffaa\025\uffaa" +
+ "\032\uffaa\033\uffaa\036\uffaa\037\uffaa\001\002\000\022\003" +
+ "\uffa9\017\uffa9\022\uffa9\025\uffa9\032\uffa9\033\uffa9\036\uffa9" +
+ "\037\uffa9\001\002\000\022\003\uffa3\017\uffa3\022\uffa3\025" +
+ "\uffa3\032\uffa3\033\uffa3\036\uffa3\037\uffa3\001\002\000\012" +
+ "\017\uffb7\022\uffb7\033\uffb7\036\uffb7\001\002\000\020\003" +
+ "\uffe7\011\uffe7\012\uffe7\016\uffe7\026\uffe7\035\uffe7\036\uffe7" +
+ "\001\002\000\022\003\uffa0\017\uffa0\022\uffa0\025\uffa0\032" +
+ "\uffa0\033\uffa0\036\uffa0\037\uffa0\001\002\000\012\017\uffe4" +
+ "\022\uff9c\033\uff9c\036\uff9c\001\002\000\022\003\uff9e\017" +
+ "\uff9e\022\uff9e\025\uff9e\032\uff9e\033\uff9e\036\uff9e\037\uff9e" +
+ "\001\002\000\022\003\uffa7\017\uffa7\022\uffa7\025\uffa7\032" +
+ "\uffa7\033\uffa7\036\uffa7\037\uffa7\001\002\000\006\017\uffdb" +
+ "\020\uffdb\001\002\000\022\003\uffa8\017\uffa8\022\uffa8\025" +
+ "\uffa8\032\uffa8\033\uffa8\036\uffa8\037\uffa8\001\002\000\022" +
+ "\003\uff9d\017\uff9d\022\uff9d\025\uff9d\032\uff9d\033\uff9d\036" +
+ "\uff9d\037\uff9d\001\002\000\022\003\uffa4\017\uffa4\022\uffa4" +
+ "\025\uffa4\032\uffa4\033\uffa4\036\uffa4\037\uffa4\001\002\000" +
+ "\004\017\044\001\002\000\020\003\uffe3\011\uffe3\012\uffe3" +
+ "\016\uffe3\026\uffe3\035\uffe3\036\uffe3\001\002\000\006\017" +
+ "\uffb1\020\uffb1\001\002\000\020\003\uffe8\011\uffe8\012\uffe8" +
+ "\016\uffe8\026\uffe8\035\uffe8\036\uffe8\001\002\000\004\034" +
+ "\050\001\002\000\006\033\uffb3\036\uffb3\001\002\000\042" +
+ "\003\054\006\026\007\027\010\040\011\036\012\022\013" +
+ "\042\014\030\015\017\016\015\026\033\027\023\030\035" +
+ "\031\041\035\025\036\053\001\002\000\012\017\uffb8\022" +
+ "\uffb8\033\uffb8\036\uffb8\001\002\000\022\003\uffab\017\uffab" +
+ "\022\uffab\025\uffab\032\uffab\033\uffab\036\uffab\037\uffab\001" +
+ "\002\000\022\003\uff9c\017\uff9c\022\uff9c\025\uff9c\032\uff9c" +
+ "\033\uff9c\036\uff9c\037\uff9c\001\002\000\004\036\045\001" +
+ "\002\000\004\017\057\001\002\000\020\003\uffdf\011\uffdf" +
+ "\012\uffdf\016\uffdf\026\uffdf\035\uffdf\036\uffdf\001\002\000" +
+ "\006\017\uffdc\020\uffdc\001\002\000\042\003\uff9b\006\uff9b" +
+ "\007\uff9b\010\uff9b\011\uff9b\012\uff9b\013\uff9b\014\uff9b\015" +
+ "\uff9b\016\uff9b\026\uff9b\027\uff9b\030\uff9b\031\uff9b\035\uff9b" +
+ "\036\uff9b\001\002\000\010\003\uff97\016\116\036\uff97\001" +
+ "\002\000\012\003\uffda\016\uffda\026\065\036\uffda\001\002" +
+ "\000\010\003\uffd9\016\uffd9\036\uffd9\001\002\000\010\027" +
+ "\071\030\072\031\070\001\002\000\020\003\uffec\011\uffec" +
+ "\012\uffec\016\uffec\026\uffec\035\uffec\036\uffec\001\002\000" +
+ "\012\003\uffd7\016\uffd7\026\uffd7\036\uffd7\001\002\000\006" +
+ "\003\uffd2\036\uffd2\001\002\000\006\003\uffd6\036\uffd6\001" +
+ "\002\000\006\003\uffd4\036\uffd4\001\002\000\006\003\077" +
+ "\036\074\001\002\000\022\003\uffae\017\uffae\020\uffae\023" +
+ "\uffae\025\uffae\032\uffae\036\uffae\037\uffae\001\002\000\010" +
+ "\017\uffcd\020\uffcd\025\uffcd\001\002\000\006\017\uffce\020" +
+ "\uffce\001\002\000\022\003\uffad\017\uffad\020\uffad\023\uffad" +
+ "\025\uffad\032\uffad\036\uffad\037\uffad\001\002\000\006\017" +
+ "\102\020\103\001\002\000\006\017\uffcf\020\uffcf\001\002" +
+ "\000\012\003\uffd3\016\uffd3\026\uffd3\036\uffd3\001\002\000" +
+ "\006\003\077\036\074\001\002\000\006\017\uffd0\020\uffd0" +
+ "\001\002\000\006\003\077\036\074\001\002\000\006\017" +
+ "\107\020\103\001\002\000\012\003\uffd5\016\uffd5\026\uffd5" +
+ "\036\uffd5\001\002\000\006\003\077\036\074\001\002\000" +
+ "\006\017\112\020\103\001\002\000\012\003\uffd1\016\uffd1" +
+ "\026\uffd1\036\uffd1\001\002\000\012\003\uffd8\016\uffd8\026" +
+ "\uffd8\036\uffd8\001\002\000\006\003\uffca\036\uffca\001\002" +
+ "\000\006\003\126\036\120\001\002\000\004\015\117\001" +
+ "\002\000\006\003\122\036\120\001\002\000\006\017\uffb0" +
+ "\024\uffb0\001\002\000\004\017\uffcc\001\002\000\004\017" +
+ "\uffaf\001\002\000\004\017\124\001\002\000\006\003\uffcb" +
+ "\036\uffcb\001\002\000\004\024\uffc7\001\002\000\006\017" +
+ "\uffc4\024\uffaf\001\002\000\010\002\ufffe\003\126\036\120" +
+ "\001\002\000\010\002\uffc8\003\uffc8\036\uffc8\001\002\000" +
+ "\010\002\uffc9\003\uffc9\036\uffc9\001\002\000\004\017\133" +
+ "\001\002\000\010\002\uffc3\003\uffc3\036\uffc3\001\002\000" +
+ "\004\024\135\001\002\000\016\003\uffc6\017\uffc6\025\uffc6" +
+ "\032\uffc6\036\uffc6\037\uffc6\001\002\000\016\003\uff97\017" +
+ "\uff97\025\uff97\032\uff97\036\uff97\037\uff97\001\002\000\016" +
+ "\003\uffbd\017\uffbd\025\uffbd\032\uffbd\036\uffbd\037\uffbd\001" +
+ "\002\000\016\003\077\017\uffbf\025\uffbf\032\147\036\074" +
+ "\037\146\001\002\000\006\017\uffc1\025\uffc1\001\002\000" +
+ "\006\017\143\025\144\001\002\000\010\002\uffc5\003\uffc5" +
+ "\036\uffc5\001\002\000\016\003\uff97\017\uff97\025\uff97\032" +
+ "\uff97\036\uff97\037\uff97\001\002\000\006\017\uffc2\025\uffc2" +
+ "\001\002\000\016\003\uffbb\017\uffbb\025\uffbb\032\uffbb\036" +
+ "\uffbb\037\uffbb\001\002\000\006\003\077\036\074\001\002" +
+ "\000\020\003\uff97\017\uff97\023\154\025\uff97\032\uff97\036" +
+ "\uff97\037\uff97\001\002\000\016\003\uffbe\017\uffbe\025\uffbe" +
+ "\032\uffbe\036\uffbe\037\uffbe\001\002\000\016\003\uffb9\017" +
+ "\uffb9\025\uffb9\032\uffb9\036\uffb9\037\uffb9\001\002\000\016" +
+ "\003\uffbc\017\uffbc\025\uffbc\032\uffbc\036\uffbc\037\uffbc\001" +
+ "\002\000\042\003\054\006\026\007\027\010\040\011\036" +
+ "\012\022\013\042\014\030\015\017\016\015\026\033\027" +
+ "\023\030\035\031\041\035\025\036\053\001\002\000\016" +
+ "\003\uffba\017\uffba\025\uffba\032\uffba\036\uffba\037\uffba\001" +
+ "\002\000\016\003\uffac\017\uffac\025\uffac\032\uffac\036\uffac" +
+ "\037\uffac\001\002\000\006\017\uffc0\025\uffc0\001\002\000" +
+ "\014\017\uffb2\020\uffb2\022\uffab\033\uffab\036\uffab\001\002" +
+ "\000\006\033\047\036\170\001\002\000\006\017\uffdd\020" +
+ "\uffdd\001\002\000\012\017\uffe6\022\uff9c\033\uff9c\036\uff9c" +
+ "\001\002\000\020\003\uffe9\011\uffe9\012\uffe9\016\uffe9\026" +
+ "\uffe9\035\uffe9\036\uffe9\001\002\000\006\017\uffe2\020\167" +
+ "\001\002\000\004\017\172\001\002\000\004\036\170\001" +
+ "\002\000\006\017\uffb2\020\uffb2\001\002\000\006\017\uffde" +
+ "\020\uffde\001\002\000\020\003\uffe1\011\uffe1\012\uffe1\016" +
+ "\uffe1\026\uffe1\035\uffe1\036\uffe1\001\002\000\004\017\174" +
+ "\001\002\000\020\003\uffe5\011\uffe5\012\uffe5\016\uffe5\026" +
+ "\uffe5\035\uffe5\036\uffe5\001\002\000\020\003\uffea\011\uffea" +
+ "\012\uffea\016\uffea\026\uffea\035\uffea\036\uffea\001\002\000" +
+ "\022\005\ufffb\007\ufffb\010\ufffb\011\ufffb\012\ufffb\013\ufffb" +
+ "\014\ufffb\035\ufffb\001\002\000\022\005\uff97\007\uff97\010" +
+ "\uff97\011\uff97\012\uff97\013\uff97\014\uff97\035\uff97\001\002" +
+ "\000\042\003\054\006\026\007\027\010\040\011\036\012" +
+ "\022\013\042\014\030\015\017\016\015\026\033\027\023" +
+ "\030\035\031\041\035\025\036\053\001\002\000\006\017" +
+ "\ufffd\022\051\001\002\000\004\017\203\001\002\000\022" +
+ "\005\ufffc\007\ufffc\010\ufffc\011\ufffc\012\ufffc\013\ufffc\014" +
+ "\ufffc\035\ufffc\001\002\000\022\005\210\007\ufff2\010\ufff2" +
+ "\011\ufff2\012\ufff2\013\ufff2\014\ufff2\035\ufff2\001\002\000" +
+ "\022\005\ufff9\007\ufff9\010\ufff9\011\ufff9\012\ufff9\013\ufff9" +
+ "\014\ufff9\035\ufff9\001\002\000\020\007\223\010\224\011" +
+ "\007\012\012\013\227\014\225\035\014\001\002\000\022" +
+ "\005\ufffa\007\ufffa\010\ufffa\011\ufffa\012\ufffa\013\ufffa\014" +
+ "\ufffa\035\ufffa\001\002\000\042\003\054\006\026\007\027" +
+ "\010\040\011\036\012\022\013\042\014\030\015\017\016" +
+ "\015\026\033\027\023\030\035\031\041\035\025\036\053" +
+ "\001\002\000\006\017\uffb5\022\215\001\002\000\004\017" +
+ "\ufff8\001\002\000\004\017\214\001\002\000\022\005\ufff7" +
+ "\007\ufff7\010\ufff7\011\ufff7\012\ufff7\013\ufff7\014\ufff7\035" +
+ "\ufff7\001\002\000\044\003\054\006\026\007\027\010\040" +
+ "\011\036\012\022\013\042\014\030\015\017\016\015\021" +
+ "\216\026\033\027\023\030\035\031\041\035\025\036\053" +
+ "\001\002\000\004\017\uffb6\001\002\000\020\007\ufff3\010" +
+ "\ufff3\011\ufff3\012\ufff3\013\ufff3\014\ufff3\035\ufff3\001\002" +
+ "\000\020\007\ufff5\010\ufff5\011\ufff5\012\ufff5\013\ufff5\014" +
+ "\ufff5\035\ufff5\001\002\000\020\007\ufff1\010\ufff1\011\ufff1" +
+ "\012\ufff1\013\ufff1\014\ufff1\035\ufff1\001\002\000\020\007" +
+ "\ufff4\010\ufff4\011\ufff4\012\ufff4\013\ufff4\014\ufff4\035\ufff4" +
+ "\001\002\000\004\006\246\001\002\000\004\006\243\001" +
+ "\002\000\004\015\240\001\002\000\020\007\ufff6\010\ufff6" +
+ "\011\ufff6\012\ufff6\013\ufff6\014\ufff6\035\ufff6\001\002\000" +
+ "\004\015\234\001\002\000\020\003\uff97\011\007\012\012" +
+ "\016\uff97\026\065\035\014\036\uff97\001\002\000\010\003" +
+ "\uff97\016\116\036\uff97\001\002\000\006\003\126\036\120" +
+ "\001\002\000\010\002\uffff\003\126\036\120\001\002\000" +
+ "\004\037\235\001\002\000\022\007\uff99\010\uff99\011\uff99" +
+ "\012\uff99\013\uff99\014\uff99\017\236\035\uff99\001\002\000" +
+ "\020\007\uff98\010\uff98\011\uff98\012\uff98\013\uff98\014\uff98" +
+ "\035\uff98\001\002\000\020\007\uffee\010\uffee\011\uffee\012" +
+ "\uffee\013\uffee\014\uffee\035\uffee\001\002\000\004\037\241" +
+ "\001\002\000\022\007\uff99\010\uff99\011\uff99\012\uff99\013" +
+ "\uff99\014\uff99\017\236\035\uff99\001\002\000\020\007\uffed" +
+ "\010\uffed\011\uffed\012\uffed\013\uffed\014\uffed\035\uffed\001" +
+ "\002\000\004\037\244\001\002\000\022\007\uff99\010\uff99" +
+ "\011\uff99\012\uff99\013\uff99\014\uff99\017\236\035\uff99\001" +
+ "\002\000\020\007\uffef\010\uffef\011\uffef\012\uffef\013\uffef" +
+ "\014\uffef\035\uffef\001\002\000\004\037\247\001\002\000" +
+ "\022\007\uff99\010\uff99\011\uff99\012\uff99\013\uff99\014\uff99" +
+ "\017\236\035\uff99\001\002\000\020\007\ufff0\010\ufff0\011" +
+ "\ufff0\012\ufff0\013\ufff0\014\ufff0\035\ufff0\001\002\000\004" +
+ "\002\001\001\002" });
+
+ /** Access to parse-action table. */
+ public short[][] action_table() {return _action_table;}
+
+ /** <code>reduce_goto</code> table. */
+ protected static final short[][] _reduce_table =
+ unpackFromStrings(new String[] {
+ "\000\247\000\006\003\003\055\004\001\001\000\002\001" +
+ "\001\000\006\004\176\037\175\001\001\000\010\012\012" +
+ "\014\010\024\007\001\001\000\016\017\020\025\160\026" +
+ "\164\033\161\044\163\054\030\001\001\000\002\001\001" +
+ "\000\016\012\012\024\065\037\063\040\061\041\066\043" +
+ "\062\001\001\000\002\001\001\000\016\017\020\025\023" +
+ "\027\017\034\036\045\031\054\030\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\004\063\055\001\001\000\002\001\001\000\002\001" +
+ "\001\000\002\001\001\000\010\027\017\034\036\045\045" +
+ "\001\001\000\002\001\001\000\002\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\002\001\001\000\004\061\042\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\002\001\001\000\002\001\001\000\002\001\001\000" +
+ "\002\001\001\000\002\001\001\000\002\001\001\000\002" +
+ "\001\001\000\002\001\001\000\004\054\051\001\001\000" +
+ "\002\001\001\000\002\001\001\000\002\001\001\000\004" +
+ "\034\057\001\001\000\002\001\001\000\002\001\001\000" +
+ "\002\001\001\000\002\001\001\000\006\015\114\037\113" +
+ "\001\001\000\004\041\112\001\001\000\002\001\001\000" +
+ "\002\001\001\000\002\001\001\000\002\001\001\000\004" +
+ "\066\107\001\001\000\004\064\104\001\001\000\004\065" +
+ "\072\001\001\000\012\042\077\047\074\052\100\053\075" +
+ "\001\001\000\002\001\001\000\002\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\002\001\001\000\010\047\074\052\103\053\075\001" +
+ "\001\000\002\001\001\000\012\042\105\047\074\052\100" +
+ "\053\075\001\001\000\002\001\001\000\002\001\001\000" +
+ "\012\042\110\047\074\052\100\053\075\001\001\000\002" +
+ "\001\001\000\002\001\001\000\002\001\001\000\002\001" +
+ "\001\000\010\016\126\030\127\046\124\001\001\000\002" +
+ "\001\001\000\004\046\120\001\001\000\002\001\001\000" +
+ "\004\067\122\001\001\000\002\001\001\000\002\001\001" +
+ "\000\002\001\001\000\004\070\133\001\001\000\004\072" +
+ "\131\001\001\000\006\030\130\046\124\001\001\000\002" +
+ "\001\001\000\002\001\001\000\002\001\001\000\002\001" +
+ "\001\000\002\001\001\000\004\071\135\001\001\000\012" +
+ "\031\137\035\141\036\140\037\136\001\001\000\002\001" +
+ "\001\000\006\032\150\047\147\001\001\000\002\001\001" +
+ "\000\002\001\001\000\002\001\001\000\010\031\137\036" +
+ "\144\037\136\001\001\000\002\001\001\000\002\001\001" +
+ "\000\006\047\074\053\156\001\001\000\006\037\151\051" +
+ "\152\001\001\000\002\001\001\000\002\001\001\000\002" +
+ "\001\001\000\006\050\154\054\155\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\010\026\164\033\161\044\174\001\001\000\002\001" +
+ "\001\000\004\060\172\001\001\000\002\001\001\000\004" +
+ "\062\165\001\001\000\002\001\001\000\004\033\170\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\002\001\001\000\002\001\001\000\002\001\001\000" +
+ "\002\001\001\000\006\005\203\037\204\001\001\000\006" +
+ "\017\200\054\030\001\001\000\004\056\201\001\001\000" +
+ "\002\001\001\000\002\001\001\000\006\007\205\020\206" +
+ "\001\001\000\002\001\001\000\022\006\225\010\220\012" +
+ "\012\013\217\014\227\022\221\023\216\024\007\001\001" +
+ "\000\002\001\001\000\010\017\210\021\211\054\030\001" +
+ "\001\000\002\001\001\000\004\057\212\001\001\000\002" +
+ "\001\001\000\002\001\001\000\004\054\051\001\001\000" +
+ "\002\001\001\000\002\001\001\000\002\001\001\000\002" +
+ "\001\001\000\002\001\001\000\002\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\016\012\012\024\065\037\063\040\230\041\066\043" +
+ "\062\001\001\000\006\015\231\037\113\001\001\000\010" +
+ "\016\232\030\127\046\124\001\001\000\006\030\130\046" +
+ "\124\001\001\000\002\001\001\000\004\011\236\001\001" +
+ "\000\002\001\001\000\002\001\001\000\002\001\001\000" +
+ "\004\011\241\001\001\000\002\001\001\000\002\001\001" +
+ "\000\004\011\244\001\001\000\002\001\001\000\002\001" +
+ "\001\000\004\011\247\001\001\000\002\001\001\000\002" +
+ "\001\001" });
+
+ /** Access to <code>reduce_goto</code> table. */
+ public short[][] reduce_table() {return _reduce_table;}
+
+ /** Instance of action encapsulation class. */
+ protected CUP$parser$actions action_obj;
+
+ /** Action encapsulation object initializer. */
+ protected void init_actions()
+ {
+ action_obj = new CUP$parser$actions(this);
+ }
+
+ /** Invoke a user supplied parse action. */
+ public java_cup.runtime.Symbol do_action(
+ int act_num,
+ java_cup.runtime.lr_parser parser,
+ java.util.Stack stack,
+ int top)
+ throws java.lang.Exception
+ {
+ /* call code in generated class */
+ return action_obj.CUP$parser$do_action(act_num, parser, stack, top);
+ }
+
+ /** Indicates start state. */
+ public int start_state() {return 0;}
+ /** Indicates start production. */
+ public int start_production() {return 0;}
+
+ /** <code>EOF</code> Symbol index. */
+ public int EOF_sym() {return 0;}
+
+ /** <code>error</code> Symbol index. */
+ public int error_sym() {return 1;}
+
+
+ /** User initialization code. */
+ public void user_init() throws java.lang.Exception
+ {
+ lexer.init();
+ }
+
+ /** Scan to get the next Symbol. */
+ public java_cup.runtime.Symbol scan()
+ throws java.lang.Exception
+ {
+ return lexer.next_token();
+ }
+
+
+
+ /* override error routines */
+
+ public void report_fatal_error(
+ String message,
+ Object info)
+ {
+ done_parsing();
+ lexer.emit_error(message);
+ System.err.println("Can't recover from previous error(s), giving up.");
+ System.exit(1);
+ }
+
+ public void report_error(String message, Object info)
+ {
+ lexer.emit_error(message);
+ }
+
+}
+
+/** Cup generated class to encapsulate user supplied action code.*/
+class CUP$parser$actions {
+
+
+ /** helper routine to clone a new production part adding a given label */
+ protected production_part add_lab(production_part part, String lab)
+ throws internal_error
+ {
+ /* if there is no label, or this is an action, just return the original */
+ if (lab == null || part.is_action()) return part;
+
+ /* otherwise build a new one with the given label attached */
+ return new symbol_part(((symbol_part)part).the_symbol(),lab);
+ }
+
+ /** max size of right hand side we will support */
+ protected final int MAX_RHS = 200;
+
+ /** array for accumulating right hand side parts */
+ protected production_part[] rhs_parts = new production_part[MAX_RHS];
+
+ /** where we are currently in building a right hand side */
+ protected int rhs_pos = 0;
+
+ /** start a new right hand side */
+ protected void new_rhs() {rhs_pos = 0; }
+
+ /** add a new right hand side part */
+ protected void add_rhs_part(production_part part) throws java.lang.Exception
+ {
+ if (rhs_pos >= MAX_RHS)
+ throw new Exception("Internal Error: Productions limited to " +
+ MAX_RHS + " symbols and actions");
+
+ rhs_parts[rhs_pos] = part;
+ rhs_pos++;
+ }
+
+ /** string to build up multiple part names */
+ protected String multipart_name = new String();
+
+ /** append a new name segment to the accumulated multipart name */
+ protected void append_multipart(String name)
+ {
+ String dot = "";
+
+ /* if we aren't just starting out, put on a dot */
+ if (multipart_name.length() != 0) dot = ".";
+
+ multipart_name = multipart_name.concat(dot + name);
+ }
+
+ /** table of declared symbols -- contains production parts indexed by name */
+ protected Hashtable symbols = new Hashtable();
+
+ /** table of just non terminals -- contains non_terminals indexed by name */
+ protected Hashtable non_terms = new Hashtable();
+
+ /** declared start non_terminal */
+ protected non_terminal start_nt = null;
+
+ /** left hand side non terminal of the current production */
+ protected non_terminal lhs_nt;
+
+ /** Current precedence number */
+ int _cur_prec = 0;
+
+ /** Current precedence side */
+ int _cur_side = assoc.no_prec;
+
+ /** update the precedences we are declaring */
+ protected void update_precedence(int p) {
+ _cur_side = p;
+ _cur_prec++;
+ }
+ /** add relevant data to terminals */
+ protected void add_precedence(String term) {
+ if (term == null) {
+ System.err.println("Unable to add precedence to nonexistent terminal");
+ } else {
+ symbol_part sp = (symbol_part)symbols.get(term);
+ if (sp == null) {
+ System.err.println("Could find terminal " + term + " while declaring precedence");
+ } else {
+ java_cup.symbol sym = sp.the_symbol();
+ if (sym instanceof terminal)
+ ((terminal)sym).set_precedence(_cur_side, _cur_prec);
+ else System.err.println("Precedence declaration: Can't find terminal " + term);
+ }
+ }
+ }
+
+ private final parser parser;
+
+ /** Constructor */
+ CUP$parser$actions(parser parser) {
+ this.parser = parser;
+ }
+
+ /** Method with the actual generated action code. */
+ public final java_cup.runtime.Symbol CUP$parser$do_action(
+ int CUP$parser$act_num,
+ java_cup.runtime.lr_parser CUP$parser$parser,
+ java.util.Stack CUP$parser$stack,
+ int CUP$parser$top)
+ throws java.lang.Exception
+ {
+ /* Symbol object for return from actions */
+ java_cup.runtime.Symbol CUP$parser$result;
+
+ /* select the action based on the action number */
+ switch (CUP$parser$act_num)
+ {
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 106: // empty ::=
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(29/*empty*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 105: // opt_semi ::= SEMI
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(7/*opt_semi*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 104: // opt_semi ::=
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(7/*opt_semi*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 103: // non_terminal ::= NONTERMINAL
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(8/*non_terminal*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 102: // non_terminal ::= NON TERMINAL
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(8/*non_terminal*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 101: // robust_id ::= error
+ {
+ String RESULT = null;
+
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 100: // robust_id ::= NONASSOC
+ {
+ String RESULT = null;
+ RESULT = "nonassoc";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 99: // robust_id ::= RIGHT
+ {
+ String RESULT = null;
+ RESULT = "right";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 98: // robust_id ::= LEFT
+ {
+ String RESULT = null;
+ RESULT = "left";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 97: // robust_id ::= PRECEDENCE
+ {
+ String RESULT = null;
+ RESULT = "precedence";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 96: // robust_id ::= START
+ {
+ String RESULT = null;
+ RESULT = "start";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 95: // robust_id ::= WITH
+ {
+ String RESULT = null;
+ RESULT = "with";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 94: // robust_id ::= SCAN
+ {
+ String RESULT = null;
+ RESULT = "scan";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 93: // robust_id ::= INIT
+ {
+ String RESULT = null;
+ RESULT = "init";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 92: // robust_id ::= NONTERMINAL
+ {
+ String RESULT = null;
+ RESULT = "nonterminal";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 91: // robust_id ::= NON
+ {
+ String RESULT = null;
+ RESULT = "non";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 90: // robust_id ::= TERMINAL
+ {
+ String RESULT = null;
+ RESULT = "terminal";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 89: // robust_id ::= PARSER
+ {
+ String RESULT = null;
+ RESULT = "parser";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 88: // robust_id ::= ACTION
+ {
+ String RESULT = null;
+ RESULT = "action";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 87: // robust_id ::= CODE
+ {
+ String RESULT = null;
+ RESULT = "code";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 86: // robust_id ::= ID
+ {
+ String RESULT = null;
+ int the_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int the_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String the_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = the_id;
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 85: // label_id ::= robust_id
+ {
+ String RESULT = null;
+ int the_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int the_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String the_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = the_id;
+ CUP$parser$result = new java_cup.runtime.Symbol(38/*label_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 84: // symbol_id ::= error
+ {
+ String RESULT = null;
+
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+
+ CUP$parser$result = new java_cup.runtime.Symbol(37/*symbol_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 83: // symbol_id ::= ID
+ {
+ String RESULT = null;
+ int the_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int the_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String the_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = the_id;
+ CUP$parser$result = new java_cup.runtime.Symbol(37/*symbol_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 82: // nt_id ::= error
+ {
+ String RESULT = null;
+
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+
+ CUP$parser$result = new java_cup.runtime.Symbol(36/*nt_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 81: // nt_id ::= ID
+ {
+ String RESULT = null;
+ int the_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int the_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String the_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = the_id;
+ CUP$parser$result = new java_cup.runtime.Symbol(36/*nt_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 80: // new_non_term_id ::= ID
+ {
+ Object RESULT = null;
+ int non_term_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int non_term_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String non_term_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* see if this non terminal has been declared before */
+ if (symbols.get(non_term_id) != null)
+ {
+ /* issue a message */
+ lexer.emit_error( "java_cup.runtime.Symbol \"" + non_term_id +
+ "\" has already been declared");
+ }
+ else
+ {
+ if (multipart_name.equals("")) {
+ append_multipart("Object");
+ }
+ /* build the non terminal object */
+ non_terminal this_nt =
+ new non_terminal(non_term_id, multipart_name);
+
+ /* put it in the non_terms table */
+ non_terms.put(non_term_id, this_nt);
+
+ /* build a production_part and put it in the symbols table */
+ symbols.put(non_term_id, new symbol_part(this_nt));
+ }
+
+ CUP$parser$result = new java_cup.runtime.Symbol(26/*new_non_term_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 79: // new_term_id ::= ID
+ {
+ Object RESULT = null;
+ int term_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int term_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String term_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* see if this terminal has been declared before */
+ if (symbols.get(term_id) != null)
+ {
+ /* issue a message */
+ lexer.emit_error("java_cup.runtime.Symbol \"" + term_id +
+ "\" has already been declared");
+ }
+ else
+ {
+ /* if no type declared, declare one */
+ if (multipart_name.equals("")) {
+ append_multipart("Object");
+ }
+ /* build a production_part and put it in the table */
+ symbols.put(term_id,
+ new symbol_part(new terminal(term_id, multipart_name)));
+ }
+
+ CUP$parser$result = new java_cup.runtime.Symbol(25/*new_term_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 78: // type_id ::= type_id LBRACK RBRACK
+ {
+ Object RESULT = null;
+ multipart_name = multipart_name.concat("[]");
+ CUP$parser$result = new java_cup.runtime.Symbol(19/*type_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 77: // type_id ::= multipart_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(19/*type_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 76: // import_id ::= multipart_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(15/*import_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 75: // import_id ::= multipart_id DOT STAR
+ {
+ Object RESULT = null;
+ append_multipart("*");
+ CUP$parser$result = new java_cup.runtime.Symbol(15/*import_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 74: // multipart_id ::= robust_id
+ {
+ Object RESULT = null;
+ int an_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int an_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String an_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ append_multipart(an_id);
+ CUP$parser$result = new java_cup.runtime.Symbol(13/*multipart_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 73: // multipart_id ::= multipart_id DOT robust_id
+ {
+ Object RESULT = null;
+ int another_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int another_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String another_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ append_multipart(another_id);
+ CUP$parser$result = new java_cup.runtime.Symbol(13/*multipart_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 72: // opt_label ::= empty
+ {
+ String RESULT = null;
+ RESULT = null;
+ CUP$parser$result = new java_cup.runtime.Symbol(39/*opt_label*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 71: // opt_label ::= COLON label_id
+ {
+ String RESULT = null;
+ int labidleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int labidright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String labid = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = labid;
+ CUP$parser$result = new java_cup.runtime.Symbol(39/*opt_label*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 70: // prod_part ::= CODE_STRING
+ {
+ Object RESULT = null;
+ int code_strleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int code_strright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String code_str = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* add a new production part */
+ add_rhs_part(new action_part(code_str));
+
+ CUP$parser$result = new java_cup.runtime.Symbol(24/*prod_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 69: // prod_part ::= symbol_id opt_label
+ {
+ Object RESULT = null;
+ int symidleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int symidright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ String symid = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+ int labidleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int labidright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String labid = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* try to look up the id */
+ production_part symb = (production_part)symbols.get(symid);
+
+ /* if that fails, symbol is undeclared */
+ if (symb == null)
+ {
+ if (lexer.error_count == 0)
+ lexer.emit_error("java_cup.runtime.Symbol \"" + symid +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* add a labeled production part */
+ add_rhs_part(add_lab(symb, labid));
+ }
+
+ CUP$parser$result = new java_cup.runtime.Symbol(24/*prod_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 68: // prod_part_list ::= empty
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(23/*prod_part_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 67: // prod_part_list ::= prod_part_list prod_part
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(23/*prod_part_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 66: // rhs ::= prod_part_list
+ {
+ Object RESULT = null;
+
+ if (lhs_nt != null)
+ {
+ /* build the production */
+ production p = new production(lhs_nt, rhs_parts, rhs_pos);
+
+ /* if we have no start non-terminal declared and this is
+ the first production, make its lhs nt the start_nt
+ and build a special start production for it. */
+ if (start_nt == null)
+ {
+ start_nt = lhs_nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt),"start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+
+ new_rhs();
+ }
+ }
+
+ /* reset the rhs accumulation in any case */
+ new_rhs();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(28/*rhs*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 65: // rhs ::= prod_part_list PERCENT_PREC term_id
+ {
+ Object RESULT = null;
+ int term_nameleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int term_nameright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String term_name = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ java_cup.symbol sym = null;
+ if (lhs_nt != null)
+ {
+ /* Find the precedence symbol */
+ if (term_name == null) {
+ System.err.println("No terminal for contextual precedence");
+ sym = null;
+ } else {
+ sym = ((symbol_part)symbols.get(term_name)).the_symbol();
+ }
+ /* build the production */
+ production p;
+ if ((sym!=null) && (sym instanceof terminal)) {
+ p = new production(lhs_nt, rhs_parts, rhs_pos,
+ ((terminal)sym).precedence_num(),
+ ((terminal)sym).precedence_side());
+ ((symbol_part)symbols.get(term_name)).the_symbol().note_use();
+ } else {
+ System.err.println("Invalid terminal " + term_name +
+ " for contextual precedence assignment");
+ p = new production(lhs_nt, rhs_parts, rhs_pos);
+ }
+
+ /* if we have no start non-terminal declared and this is
+ the first production, make its lhs nt the start_nt
+ and build a special start production for it. */
+ if (start_nt == null)
+ {
+ start_nt = lhs_nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt),"start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ if ((sym!=null) && (sym instanceof terminal)) {
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts,
+ rhs_pos, ((terminal)sym).precedence_num(),
+ ((terminal)sym).precedence_side());
+ } else {
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+ }
+ new_rhs();
+ }
+ }
+
+ /* reset the rhs accumulation in any case */
+ new_rhs();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(28/*rhs*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 64: // rhs_list ::= rhs
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(27/*rhs_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 63: // rhs_list ::= rhs_list BAR rhs
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(27/*rhs_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 62: // production ::= error NT$13 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$13
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(22/*production*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 61: // NT$13 ::=
+ {
+ Object RESULT = null;
+ lexer.emit_error("Syntax Error");
+ CUP$parser$result = new java_cup.runtime.Symbol(56/*NT$13*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 60: // production ::= nt_id NT$11 COLON_COLON_EQUALS NT$12 rhs_list SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$11
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-4)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-4)).value;
+ // propagate RESULT from NT$12
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+ int lhs_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-5)).left;
+ int lhs_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-5)).right;
+ String lhs_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-5)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(22/*production*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-5)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 59: // NT$12 ::=
+ {
+ Object RESULT = null;
+ int lhs_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left;
+ int lhs_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right;
+ String lhs_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(55/*NT$12*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 58: // NT$11 ::=
+ {
+ Object RESULT = null;
+ int lhs_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int lhs_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String lhs_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* lookup the lhs nt */
+ lhs_nt = (non_terminal)non_terms.get(lhs_id);
+
+ /* if it wasn't declared, emit a message */
+ if (lhs_nt == null)
+ {
+ if (lexer.error_count == 0)
+ lexer.emit_error("LHS non terminal \"" + lhs_id +
+ "\" has not been declared");
+ }
+
+ /* reset the rhs accumulation */
+ new_rhs();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(54/*NT$11*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 57: // production_list ::= production
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(12/*production_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 56: // production_list ::= production_list production
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(12/*production_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 55: // start_spec ::= empty
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(11/*start_spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 54: // start_spec ::= START WITH nt_id NT$10 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$10
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+ int start_nameleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left;
+ int start_nameright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right;
+ String start_name = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(11/*start_spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-4)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 53: // NT$10 ::=
+ {
+ Object RESULT = null;
+ int start_nameleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int start_nameright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String start_name = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* verify that the name has been declared as a non terminal */
+ non_terminal nt = (non_terminal)non_terms.get(start_name);
+ if (nt == null)
+ {
+ lexer.emit_error( "Start non terminal \"" + start_name +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* remember the non-terminal for later */
+ start_nt = nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt), "start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+ new_rhs();
+ }
+
+ CUP$parser$result = new java_cup.runtime.Symbol(53/*NT$10*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 52: // term_id ::= symbol_id
+ {
+ String RESULT = null;
+ int symleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int symright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String sym = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* check that the symbol_id is a terminal */
+ if (symbols.get(sym) == null)
+ {
+ /* issue a message */
+ lexer.emit_error("Terminal \"" + sym +
+ "\" has not been declared");
+ }
+ RESULT = sym;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(41/*term_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 51: // terminal_id ::= term_id
+ {
+ String RESULT = null;
+ int symleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int symright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String sym = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ add_precedence(sym);
+ RESULT = sym;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(40/*terminal_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 50: // terminal_list ::= terminal_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(32/*terminal_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 49: // terminal_list ::= terminal_list COMMA terminal_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(32/*terminal_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 48: // preced ::= PRECEDENCE NONASSOC NT$9 terminal_list SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$9
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(31/*preced*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-4)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 47: // NT$9 ::=
+ {
+ Object RESULT = null;
+
+ update_precedence(assoc.nonassoc);
+
+ CUP$parser$result = new java_cup.runtime.Symbol(52/*NT$9*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 46: // preced ::= PRECEDENCE RIGHT NT$8 terminal_list SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$8
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(31/*preced*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-4)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 45: // NT$8 ::=
+ {
+ Object RESULT = null;
+
+ update_precedence(assoc.right);
+
+ CUP$parser$result = new java_cup.runtime.Symbol(51/*NT$8*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 44: // preced ::= PRECEDENCE LEFT NT$7 terminal_list SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$7
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(31/*preced*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-4)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 43: // NT$7 ::=
+ {
+ Object RESULT = null;
+
+ update_precedence(assoc.left);
+
+ CUP$parser$result = new java_cup.runtime.Symbol(50/*NT$7*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 42: // precedence_l ::= preced
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(33/*precedence_l*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 41: // precedence_l ::= precedence_l preced
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(33/*precedence_l*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 40: // precedence_list ::= empty
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(30/*precedence_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 39: // precedence_list ::= precedence_l
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(30/*precedence_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 38: // non_term_name_list ::= new_non_term_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(21/*non_term_name_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 37: // non_term_name_list ::= non_term_name_list COMMA new_non_term_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(21/*non_term_name_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 36: // term_name_list ::= new_term_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(20/*term_name_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 35: // term_name_list ::= term_name_list COMMA new_term_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(20/*term_name_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 34: // declares_non_term ::= non_term_name_list NT$6 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$6
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(35/*declares_non_term*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 33: // NT$6 ::=
+ {
+ Object RESULT = null;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(49/*NT$6*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 32: // declares_term ::= term_name_list NT$5 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$5
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(34/*declares_term*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 31: // NT$5 ::=
+ {
+ Object RESULT = null;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(48/*NT$5*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 30: // symbol ::= non_terminal error NT$4 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$4
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 29: // NT$4 ::=
+ {
+ Object RESULT = null;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(47/*NT$4*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 28: // symbol ::= TERMINAL error NT$3 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$3
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 27: // NT$3 ::=
+ {
+ Object RESULT = null;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(46/*NT$3*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 26: // symbol ::= non_terminal declares_non_term
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 25: // symbol ::= non_terminal type_id declares_non_term
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 24: // symbol ::= TERMINAL declares_term
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 23: // symbol ::= TERMINAL type_id declares_term
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 22: // symbol_list ::= symbol
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(10/*symbol_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 21: // symbol_list ::= symbol_list symbol
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(10/*symbol_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 20: // scan_code ::= SCAN WITH CODE_STRING opt_semi
+ {
+ Object RESULT = null;
+ int user_codeleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int user_coderight = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ String user_code = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ if (emit.scan_code!=null)
+ lexer.emit_error("Redundant scan code (skipping)");
+ else /* save the user code */
+ emit.scan_code = user_code;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(17/*scan_code*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 19: // init_code ::= INIT WITH CODE_STRING opt_semi
+ {
+ Object RESULT = null;
+ int user_codeleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int user_coderight = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ String user_code = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ if (emit.init_code!=null)
+ lexer.emit_error("Redundant init code (skipping)");
+ else /* save the user code */
+ emit.init_code = user_code;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(16/*init_code*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 18: // parser_code_part ::= PARSER CODE CODE_STRING opt_semi
+ {
+ Object RESULT = null;
+ int user_codeleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int user_coderight = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ String user_code = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ if (emit.parser_code!=null)
+ lexer.emit_error("Redundant parser code (skipping)");
+ else /* save the user included code string */
+ emit.parser_code = user_code;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(9/*parser_code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 17: // action_code_part ::= ACTION CODE CODE_STRING opt_semi
+ {
+ Object RESULT = null;
+ int user_codeleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int user_coderight = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ String user_code = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ if (emit.action_code!=null)
+ lexer.emit_error("Redundant action code (skipping)");
+ else /* save the user included code string */
+ emit.action_code = user_code;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(4/*action_code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 16: // code_parts ::= code_parts code_part
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(5/*code_parts*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 15: // code_parts ::=
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(5/*code_parts*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 14: // code_part ::= scan_code
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(6/*code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 13: // code_part ::= init_code
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(6/*code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 12: // code_part ::= parser_code_part
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(6/*code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 11: // code_part ::= action_code_part
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(6/*code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 10: // import_spec ::= IMPORT import_id NT$2 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$2
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(14/*import_spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 9: // NT$2 ::=
+ {
+ Object RESULT = null;
+
+ /* save this import on the imports list */
+ emit.import_list.push(multipart_name);
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(45/*NT$2*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 8: // import_list ::= empty
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*import_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 7: // import_list ::= import_list import_spec
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*import_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 6: // package_spec ::= empty
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(2/*package_spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 5: // package_spec ::= PACKAGE multipart_id NT$1 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$1
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(2/*package_spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 4: // NT$1 ::=
+ {
+ Object RESULT = null;
+
+ /* save the package name */
+ emit.package_name = multipart_name;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(44/*NT$1*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 3: // spec ::= error symbol_list precedence_list start_spec production_list
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(1/*spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-4)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 2: // spec ::= NT$0 package_spec import_list code_parts symbol_list precedence_list start_spec production_list
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$0
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-7)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-7)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(1/*spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-7)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 1: // NT$0 ::=
+ {
+ Object RESULT = null;
+
+ /* declare "error" as a terminal */
+ symbols.put("error", new symbol_part(terminal.error));
+
+ /* declare start non terminal */
+ non_terms.put("$START", non_terminal.START_nt);
+
+ CUP$parser$result = new java_cup.runtime.Symbol(43/*NT$0*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 0: // $START ::= spec EOF
+ {
+ Object RESULT = null;
+ int start_valleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int start_valright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ Object start_val = (Object)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+ RESULT = start_val;
+ CUP$parser$result = new java_cup.runtime.Symbol(0/*$START*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ /* ACCEPT */
+ CUP$parser$parser.done_parsing();
+ return CUP$parser$result;
+
+ /* . . . . . .*/
+ default:
+ throw new Exception(
+ "Invalid action number found in internal parse table");
+
+ }
+ }
+}
+
diff --git a/src/java_cup/java_cup/production.java b/src/java_cup/java_cup/production.java
new file mode 100644
index 0000000..5a41287
--- /dev/null
+++ b/src/java_cup/java_cup/production.java
@@ -0,0 +1,756 @@
+
+package java_cup;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/** This class represents a production in the grammar. It contains
+ * a LHS non terminal, and an array of RHS symbols. As various
+ * transformations are done on the RHS of the production, it may shrink.
+ * As a result a separate length is always maintained to indicate how much
+ * of the RHS array is still valid.<p>
+ *
+ * I addition to construction and manipulation operations, productions provide
+ * methods for factoring out actions (see remove_embedded_actions()), for
+ * computing the nullability of the production (i.e., can it derive the empty
+ * string, see check_nullable()), and operations for computing its first
+ * set (i.e., the set of terminals that could appear at the beginning of some
+ * string derived from the production, see check_first_set()).
+ *
+ * @see java_cup.production_part
+ * @see java_cup.symbol_part
+ * @see java_cup.action_part
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+
+public class production {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor. This constructor accepts a LHS non terminal,
+ * an array of RHS parts (including terminals, non terminals, and
+ * actions), and a string for a final reduce action. It does several
+ * manipulations in the process of creating a production object.
+ * After some validity checking it translates labels that appear in
+ * actions into code for accessing objects on the runtime parse stack.
+ * It them merges adjacent actions if they appear and moves any trailing
+ * action into the final reduce actions string. Next it removes any
+ * embedded actions by factoring them out with new action productions.
+ * Finally it assigns a unique index to the production.<p>
+ *
+ * Factoring out of actions is accomplished by creating new "hidden"
+ * non terminals. For example if the production was originally: <pre>
+ * A ::= B {action} C D
+ * </pre>
+ * then it is factored into two productions:<pre>
+ * A ::= B X C D
+ * X ::= {action}
+ * </pre>
+ * (where X is a unique new non terminal). This has the effect of placing
+ * all actions at the end where they can be handled as part of a reduce by
+ * the parser.
+ */
+ public production(
+ non_terminal lhs_sym,
+ production_part rhs_parts[],
+ int rhs_l,
+ String action_str)
+ throws internal_error
+ {
+ int i;
+ action_part tail_action;
+ String declare_str;
+ int rightlen = rhs_l;
+
+ /* remember the length */
+ if (rhs_l >= 0)
+ _rhs_length = rhs_l;
+ else if (rhs_parts != null)
+ _rhs_length = rhs_parts.length;
+ else
+ _rhs_length = 0;
+
+ /* make sure we have a valid left-hand-side */
+ if (lhs_sym == null)
+ throw new internal_error(
+ "Attempt to construct a production with a null LHS");
+
+ /* I'm not translating labels anymore, I'm adding code to declare
+ labels as valid variables. This way, the users code string is
+ untouched
+ 6/96 frankf */
+
+ /* check if the last part of the right hand side is an action. If
+ it is, it won't be on the stack, so we don't want to count it
+ in the rightlen. Then when we search down the stack for a
+ Symbol, we don't try to search past action */
+
+ if (rhs_l > 0) {
+ if (rhs_parts[rhs_l - 1].is_action()) {
+ rightlen = rhs_l - 1;
+ } else {
+ rightlen = rhs_l;
+ }
+ }
+
+ /* get the generated declaration code for the necessary labels. */
+ declare_str = declare_labels(
+ rhs_parts, rightlen, action_str);
+
+ if (action_str == null)
+ action_str = declare_str;
+ else
+ action_str = declare_str + action_str;
+
+ /* count use of lhs */
+ lhs_sym.note_use();
+
+ /* create the part for left-hand-side */
+ _lhs = new symbol_part(lhs_sym);
+
+ /* merge adjacent actions (if any) */
+ _rhs_length = merge_adjacent_actions(rhs_parts, _rhs_length);
+
+ /* strip off any trailing action */
+ tail_action = strip_trailing_action(rhs_parts, _rhs_length);
+ if (tail_action != null) _rhs_length--;
+
+ /* Why does this run through the right hand side happen
+ over and over? here a quick combination of two
+ prior runs plus one I wanted of my own
+ frankf 6/25/96 */
+ /* allocate and copy over the right-hand-side */
+ /* count use of each rhs symbol */
+ _rhs = new production_part[_rhs_length];
+ for (i=0; i<_rhs_length; i++) {
+ _rhs[i] = rhs_parts[i];
+ if (!_rhs[i].is_action()) {
+ ((symbol_part)_rhs[i]).the_symbol().note_use();
+ if (((symbol_part)_rhs[i]).the_symbol() instanceof terminal) {
+ _rhs_prec =
+ ((terminal)((symbol_part)_rhs[i]).the_symbol()).precedence_num();
+ _rhs_assoc =
+ ((terminal)((symbol_part)_rhs[i]).the_symbol()).precedence_side();
+ }
+ }
+ }
+
+ /*now action string is really declaration string, so put it in front!
+ 6/14/96 frankf */
+ if (action_str == null) action_str = "";
+ if (tail_action != null && tail_action.code_string() != null)
+ action_str = action_str + "\t\t" + tail_action.code_string();
+
+ /* stash the action */
+ _action = new action_part(action_str);
+
+ /* rewrite production to remove any embedded actions */
+ remove_embedded_actions();
+
+ /* assign an index */
+ _index = next_index++;
+
+ /* put us in the global collection of productions */
+ _all.put(new Integer(_index),this);
+
+ /* put us in the production list of the lhs non terminal */
+ lhs_sym.add_production(this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with no action string. */
+ public production(
+ non_terminal lhs_sym,
+ production_part rhs_parts[],
+ int rhs_l)
+ throws internal_error
+ {
+ this(lhs_sym,rhs_parts,rhs_l,null);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /* Constructor with precedence and associativity of production
+ contextually define */
+ public production(
+ non_terminal lhs_sym,
+ production_part rhs_parts[],
+ int rhs_l,
+ String action_str,
+ int prec_num,
+ int prec_side)
+ throws internal_error
+ {
+ this(lhs_sym,rhs_parts,rhs_l,action_str);
+
+ /* set the precedence */
+ set_precedence_num(prec_num);
+ set_precedence_side(prec_side);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /* Constructor w/ no action string and contextual precedence
+ defined */
+ public production(
+ non_terminal lhs_sym,
+ production_part rhs_parts[],
+ int rhs_l,
+ int prec_num,
+ int prec_side)
+ throws internal_error
+ {
+ this(lhs_sym,rhs_parts,rhs_l,null);
+ /* set the precedence */
+ set_precedence_num(prec_num);
+ set_precedence_side(prec_side);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+
+ /** Table of all productions. Elements are stored using their index as
+ * the key.
+ */
+ protected static Hashtable _all = new Hashtable();
+
+ /** Access to all productions. */
+ public static Enumeration all() {return _all.elements();}
+
+ /** Lookup a production by index. */
+ public static production find(int indx) {
+ return (production) _all.get(new Integer(indx));
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Total number of productions. */
+ public static int number() {return _all.size();}
+
+ /** Static counter for assigning unique index numbers. */
+ protected static int next_index;
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The left hand side non-terminal. */
+ protected symbol_part _lhs;
+
+ /** The left hand side non-terminal. */
+ public symbol_part lhs() {return _lhs;}
+
+
+ /** The precedence of the rule */
+ protected int _rhs_prec = -1;
+ protected int _rhs_assoc = -1;
+
+ /** Access to the precedence of the rule */
+ public int precedence_num() { return _rhs_prec; }
+ public int precedence_side() { return _rhs_assoc; }
+
+ /** Setting the precedence of a rule */
+ public void set_precedence_num(int prec_num) {
+ _rhs_prec = prec_num;
+ }
+ public void set_precedence_side(int prec_side) {
+ _rhs_assoc = prec_side;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** A collection of parts for the right hand side. */
+ protected production_part _rhs[];
+
+ /** Access to the collection of parts for the right hand side. */
+ public production_part rhs(int indx) throws internal_error
+ {
+ if (indx >= 0 && indx < _rhs_length)
+ return _rhs[indx];
+ else
+ throw new internal_error(
+ "Index out of range for right hand side of production");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** How much of the right hand side array we are presently using. */
+ protected int _rhs_length;
+
+ /** How much of the right hand side array we are presently using. */
+ public int rhs_length() {return _rhs_length;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** An action_part containing code for the action to be performed when we
+ * reduce with this production.
+ */
+ protected action_part _action;
+
+ /** An action_part containing code for the action to be performed when we
+ * reduce with this production.
+ */
+ public action_part action() {return _action;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Index number of the production. */
+ protected int _index;
+
+ /** Index number of the production. */
+ public int index() {return _index;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of number of reductions using this production. */
+ protected int _num_reductions = 0;
+
+ /** Count of number of reductions using this production. */
+ public int num_reductions() {return _num_reductions;}
+
+ /** Increment the count of reductions with this non-terminal */
+ public void note_reduction_use() {_num_reductions++;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Is the nullability of the production known or unknown? */
+ protected boolean _nullable_known = false;
+
+ /** Is the nullability of the production known or unknown? */
+ public boolean nullable_known() {return _nullable_known;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Nullability of the production (can it derive the empty string). */
+ protected boolean _nullable = false;
+
+ /** Nullability of the production (can it derive the empty string). */
+ public boolean nullable() {return _nullable;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** First set of the production. This is the set of terminals that
+ * could appear at the front of some string derived from this production.
+ */
+ protected terminal_set _first_set = new terminal_set();
+
+ /** First set of the production. This is the set of terminals that
+ * could appear at the front of some string derived from this production.
+ */
+ public terminal_set first_set() {return _first_set;}
+
+ /*-----------------------------------------------------------*/
+ /*--- Static Methods ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Determine if a given character can be a label id starter.
+ * @param c the character in question.
+ */
+ protected static boolean is_id_start(char c)
+ {
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_');
+
+ //later need to handle non-8-bit chars here
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if a character can be in a label id.
+ * @param c the character in question.
+ */
+ protected static boolean is_id_char(char c)
+ {
+ return is_id_start(c) || (c >= '0' && c <= '9');
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+
+ /** Return label declaration code
+ * @param labelname the label name
+ * @param stack_type the stack type of label?
+ * @author frankf
+ */
+ protected String make_declaration(
+ String labelname,
+ String stack_type,
+ int offset)
+ {
+ String ret;
+
+ /* Put in the left/right value labels */
+ if (emit.lr_values())
+ ret = "\t\tint " + labelname + "left = ((java_cup.runtime.Symbol)" +
+ emit.pre("stack") + ".elementAt(" + emit.pre("top") +
+ "-" + offset + ")).left;\n" +
+ "\t\tint " + labelname + "right = ((java_cup.runtime.Symbol)" +
+ emit.pre("stack") + ".elementAt(" + emit.pre("top") +
+ "-" + offset + ")).right;\n";
+ else ret = "";
+
+ /* otherwise, just declare label. */
+ return ret + "\t\t" + stack_type + " " + labelname + " = (" + stack_type +
+ ")((" + "java_cup.runtime.Symbol) " + emit.pre("stack") + ".elementAt(" + emit.pre("top")
+ + "-" + offset + ")).value;\n";
+
+ }
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Declare label names as valid variables within the action string
+ * @param rhs array of RHS parts.
+ * @param rhs_len how much of rhs to consider valid.
+ * @param final_action the final action string of the production.
+ * @param lhs_type the object type associated with the LHS symbol.
+ */
+ protected String declare_labels(
+ production_part rhs[],
+ int rhs_len,
+ String final_action)
+ {
+ String declaration = "";
+
+ symbol_part part;
+ action_part act_part;
+ int pos;
+
+ /* walk down the parts and extract the labels */
+ for (pos = 0; pos < rhs_len; pos++)
+ {
+ if (!rhs[pos].is_action())
+ {
+ part = (symbol_part)rhs[pos];
+
+ /* if it has a label, make declaration! */
+ if (part.label() != null)
+ {
+ declaration = declaration +
+ make_declaration(part.label(), part.the_symbol().stack_type(),
+ rhs_len-pos-1);
+ }
+ }
+ }
+ return declaration;
+ }
+
+
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Helper routine to merge adjacent actions in a set of RHS parts
+ * @param rhs_parts array of RHS parts.
+ * @param len amount of that array that is valid.
+ * @return remaining valid length.
+ */
+ protected int merge_adjacent_actions(production_part rhs_parts[], int len)
+ {
+ int from_loc, to_loc, merge_cnt;
+
+ /* bail out early if we have no work to do */
+ if (rhs_parts == null || len == 0) return 0;
+
+ merge_cnt = 0;
+ to_loc = -1;
+ for (from_loc=0; from_loc<len; from_loc++)
+ {
+ /* do we go in the current position or one further */
+ if (to_loc < 0 || !rhs_parts[to_loc].is_action()
+ || !rhs_parts[from_loc].is_action())
+ {
+ /* next one */
+ to_loc++;
+
+ /* clear the way for it */
+ if (to_loc != from_loc) rhs_parts[to_loc] = null;
+ }
+
+ /* if this is not trivial? */
+ if (to_loc != from_loc)
+ {
+ /* do we merge or copy? */
+ if (rhs_parts[to_loc] != null && rhs_parts[to_loc].is_action() &&
+ rhs_parts[from_loc].is_action())
+ {
+ /* merge */
+ rhs_parts[to_loc] = new action_part(
+ ((action_part)rhs_parts[to_loc]).code_string() +
+ ((action_part)rhs_parts[from_loc]).code_string());
+ merge_cnt++;
+ }
+ else
+ {
+ /* copy */
+ rhs_parts[to_loc] = rhs_parts[from_loc];
+ }
+ }
+ }
+
+ /* return the used length */
+ return len - merge_cnt;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Helper routine to strip a trailing action off rhs and return it
+ * @param rhs_parts array of RHS parts.
+ * @param len how many of those are valid.
+ * @return the removed action part.
+ */
+ protected action_part strip_trailing_action(
+ production_part rhs_parts[],
+ int len)
+ {
+ action_part result;
+
+ /* bail out early if we have nothing to do */
+ if (rhs_parts == null || len == 0) return null;
+
+ /* see if we have a trailing action */
+ if (rhs_parts[len-1].is_action())
+ {
+ /* snip it out and return it */
+ result = (action_part)rhs_parts[len-1];
+ rhs_parts[len-1] = null;
+ return result;
+ }
+ else
+ return null;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove all embedded actions from a production by factoring them
+ * out into individual action production using new non terminals.
+ * if the original production was: <pre>
+ * A ::= B {action1} C {action2} D
+ * </pre>
+ * then it will be factored into: <pre>
+ * A ::= B NT$1 C NT$2 D
+ * NT$1 ::= {action1}
+ * NT$2 ::= {action2}
+ * </pre>
+ * where NT$1 and NT$2 are new system created non terminals.
+ */
+
+ /* the declarations added to the parent production are also passed along,
+ as they should be perfectly valid in this code string, since it
+ was originally a code string in the parent, not on its own.
+ frank 6/20/96 */
+ protected void remove_embedded_actions(
+
+ ) throws internal_error
+ {
+ non_terminal new_nt;
+ production new_prod;
+ String declare_str;
+
+ /* walk over the production and process each action */
+ for (int act_loc = 0; act_loc < rhs_length(); act_loc++)
+ if (rhs(act_loc).is_action())
+ {
+
+
+ declare_str = declare_labels(
+ _rhs, act_loc, "");
+ /* create a new non terminal for the action production */
+ new_nt = non_terminal.create_new();
+ new_nt.is_embedded_action = true; /* 24-Mar-1998, CSA */
+
+ /* create a new production with just the action */
+ new_prod = new action_production(this, new_nt, null, 0,
+ declare_str + ((action_part)rhs(act_loc)).code_string());
+
+ /* replace the action with the generated non terminal */
+ _rhs[act_loc] = new symbol_part(new_nt);
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Check to see if the production (now) appears to be nullable.
+ * A production is nullable if its RHS could derive the empty string.
+ * This results when the RHS is empty or contains only non terminals
+ * which themselves are nullable.
+ */
+ public boolean check_nullable() throws internal_error
+ {
+ production_part part;
+ symbol sym;
+ int pos;
+
+ /* if we already know bail out early */
+ if (nullable_known()) return nullable();
+
+ /* if we have a zero size RHS we are directly nullable */
+ if (rhs_length() == 0)
+ {
+ /* stash and return the result */
+ return set_nullable(true);
+ }
+
+ /* otherwise we need to test all of our parts */
+ for (pos=0; pos<rhs_length(); pos++)
+ {
+ part = rhs(pos);
+
+ /* only look at non-actions */
+ if (!part.is_action())
+ {
+ sym = ((symbol_part)part).the_symbol();
+
+ /* if its a terminal we are definitely not nullable */
+ if (!sym.is_non_term())
+ return set_nullable(false);
+ /* its a non-term, is it marked nullable */
+ else if (!((non_terminal)sym).nullable())
+ /* this one not (yet) nullable, so we aren't */
+ return false;
+ }
+ }
+
+ /* if we make it here all parts are nullable */
+ return set_nullable(true);
+ }
+
+ /** set (and return) nullability */
+ boolean set_nullable(boolean v)
+ {
+ _nullable_known = true;
+ _nullable = v;
+ return v;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Update (and return) the first set based on current NT firsts.
+ * This assumes that nullability has already been computed for all non
+ * terminals and productions.
+ */
+ public terminal_set check_first_set() throws internal_error
+ {
+ int part;
+ symbol sym;
+
+ /* walk down the right hand side till we get past all nullables */
+ for (part=0; part<rhs_length(); part++)
+ {
+ /* only look at non-actions */
+ if (!rhs(part).is_action())
+ {
+ sym = ((symbol_part)rhs(part)).the_symbol();
+
+ /* is it a non-terminal?*/
+ if (sym.is_non_term())
+ {
+ /* add in current firsts from that NT */
+ _first_set.add(((non_terminal)sym).first_set());
+
+ /* if its not nullable, we are done */
+ if (!((non_terminal)sym).nullable())
+ break;
+ }
+ else
+ {
+ /* its a terminal -- add that to the set */
+ _first_set.add((terminal)sym);
+
+ /* we are done */
+ break;
+ }
+ }
+ }
+
+ /* return our updated first set */
+ return first_set();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(production other)
+ {
+ if (other == null) return false;
+ return other._index == _index;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof production))
+ return false;
+ else
+ return equals((production)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a hash code. */
+ public int hashCode()
+ {
+ /* just use a simple function of the index */
+ return _index*13;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+
+ /* catch any internal errors */
+ try {
+ result = "production [" + index() + "]: ";
+ result += ((lhs() != null) ? lhs().toString() : "$$NULL-LHS$$");
+ result += " :: = ";
+ for (int i = 0; i<rhs_length(); i++)
+ result += rhs(i) + " ";
+ result += ";";
+ if (action() != null && action().code_string() != null)
+ result += " {" + action().code_string() + "}";
+
+ if (nullable_known())
+ if (nullable())
+ result += "[NULLABLE]";
+ else
+ result += "[NOT NULLABLE]";
+ } catch (internal_error e) {
+ /* crash on internal error since we can't throw it from here (because
+ superclass does not throw anything. */
+ e.crash();
+ result = null;
+ }
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a simpler string. */
+ public String to_simple_string() throws internal_error
+ {
+ String result;
+
+ result = ((lhs() != null) ? lhs().the_symbol().name() : "NULL_LHS");
+ result += " ::= ";
+ for (int i = 0; i < rhs_length(); i++)
+ if (!rhs(i).is_action())
+ result += ((symbol_part)rhs(i)).the_symbol().name() + " ";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/java_cup/java_cup/production_part.java b/src/java_cup/java_cup/production_part.java
new file mode 100644
index 0000000..a790ec0
--- /dev/null
+++ b/src/java_cup/java_cup/production_part.java
@@ -0,0 +1,94 @@
+package java_cup;
+
+/** This class represents one part (either a symbol or an action) of a
+ * production. In this base class it contains only an optional label
+ * string that the user can use to refer to the part within actions.<p>
+ *
+ * This is an abstract class.
+ *
+ * @see java_cup.production
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public abstract class production_part {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. */
+ public production_part(String lab)
+ {
+ _label = lab;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Optional label for referring to the part within an action (null for
+ * no label).
+ */
+ protected String _label;
+
+ /** Optional label for referring to the part within an action (null for
+ * no label).
+ */
+ public String label() {return _label;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Indicate if this is an action (rather than a symbol). Here in the
+ * base class, we don't this know yet, so its an abstract method.
+ */
+ public abstract boolean is_action();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(production_part other)
+ {
+ if (other == null) return false;
+
+ /* compare the labels */
+ if (label() != null)
+ return label().equals(other.label());
+ else
+ return other.label() == null;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof production_part))
+ return false;
+ else
+ return equals((production_part)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a hash code. */
+ public int hashCode()
+ {
+ return label()==null ? 0 : label().hashCode();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ if (label() != null)
+ return label() + ":";
+ else
+ return " ";
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/java_cup/java_cup/reduce_action.java b/src/java_cup/java_cup/reduce_action.java
new file mode 100644
index 0000000..e8f4c84
--- /dev/null
+++ b/src/java_cup/java_cup/reduce_action.java
@@ -0,0 +1,84 @@
+
+package java_cup;
+
+/** This class represents a reduce action within the parse table.
+ * The action simply stores the production that it reduces with and
+ * responds to queries about its type.
+ *
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class reduce_action extends parse_action {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor.
+ * @param prod the production this action reduces with.
+ */
+ public reduce_action(production prod ) throws internal_error
+ {
+ /* sanity check */
+ if (prod == null)
+ throw new internal_error(
+ "Attempt to create a reduce_action with a null production");
+
+ _reduce_with = prod;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The production we reduce with. */
+ protected production _reduce_with;
+
+ /** The production we reduce with. */
+ public production reduce_with() {return _reduce_with;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Quick access to type of action. */
+ public int kind() {return REDUCE;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality test. */
+ public boolean equals(reduce_action other)
+ {
+ return other != null && other.reduce_with() == reduce_with();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality test. */
+ public boolean equals(Object other)
+ {
+ if (other instanceof reduce_action)
+ return equals((reduce_action)other);
+ else
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute a hash code. */
+ public int hashCode()
+ {
+ /* use the hash code of the production we are reducing with */
+ return reduce_with().hashCode();
+ }
+
+
+ /** Convert to string. */
+ public String toString()
+ {
+ return "REDUCE(with prod " + reduce_with().index() + ")";
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/java_cup/java_cup/runtime/Scanner.java b/src/java_cup/java_cup/runtime/Scanner.java
new file mode 100644
index 0000000..3233551
--- /dev/null
+++ b/src/java_cup/java_cup/runtime/Scanner.java
@@ -0,0 +1,25 @@
+package java_cup.runtime;
+
+/**
+ * Defines the Scanner interface, which CUP uses in the default
+ * implementation of <code>lr_parser.scan()</code>. Integration
+ * of scanners implementing <code>Scanner</code> is facilitated.
+ *
+ * @version last updated 23-Jul-1999
+ * @author David MacMahon <davidm@smartsc.com>
+ */
+
+/* *************************************************
+ Interface Scanner
+
+ Declares the next_token() method that should be
+ implemented by scanners. This method is typically
+ called by lr_parser.scan(). End-of-file can be
+ indicated either by returning
+ <code>new Symbol(lr_parser.EOF_sym())</code> or
+ <code>null</code>.
+ ***************************************************/
+public interface Scanner {
+ /** Return the next token, or <code>null</code> on end-of-file. */
+ public Symbol next_token() throws java.lang.Exception;
+}
diff --git a/src/java_cup/java_cup/runtime/Symbol.java b/src/java_cup/java_cup/runtime/Symbol.java
new file mode 100644
index 0000000..eeb6a0b
--- /dev/null
+++ b/src/java_cup/java_cup/runtime/Symbol.java
@@ -0,0 +1,105 @@
+package java_cup.runtime;
+
+/**
+ * Defines the Symbol class, which is used to represent all terminals
+ * and nonterminals while parsing. The lexer should pass CUP Symbols
+ * and CUP returns a Symbol.
+ *
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+
+/* ****************************************************************
+ Class Symbol
+ what the parser expects to receive from the lexer.
+ the token is identified as follows:
+ sym: the symbol type
+ parse_state: the parse state.
+ value: is the lexical value of type Object
+ left : is the left position in the original input file
+ right: is the right position in the original input file
+******************************************************************/
+
+public class Symbol {
+
+/*******************************
+ Constructor for l,r values
+ *******************************/
+
+ public Symbol(int id, int l, int r, Object o) {
+ this(id);
+ left = l;
+ right = r;
+ value = o;
+ }
+
+/*******************************
+ Constructor for no l,r values
+********************************/
+
+ public Symbol(int id, Object o) {
+ this(id, -1, -1, o);
+ }
+
+/*****************************
+ Constructor for no value
+ ***************************/
+
+ public Symbol(int id, int l, int r) {
+ this(id, l, r, null);
+ }
+
+/***********************************
+ Constructor for no value or l,r
+***********************************/
+
+ public Symbol(int sym_num) {
+ this(sym_num, -1);
+ left = -1;
+ right = -1;
+ value = null;
+ }
+
+/***********************************
+ Constructor to give a start state
+***********************************/
+ Symbol(int sym_num, int state)
+ {
+ sym = sym_num;
+ parse_state = state;
+ }
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The symbol number of the terminal or non terminal being represented */
+ public int sym;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The parse state to be recorded on the parse stack with this symbol.
+ * This field is for the convenience of the parser and shouldn't be
+ * modified except by the parser.
+ */
+ public int parse_state;
+ /** This allows us to catch some errors caused by scanners recycling
+ * symbols. For the use of the parser only. [CSA, 23-Jul-1999] */
+ boolean used_by_parser = false;
+
+/*******************************
+ The data passed to parser
+ *******************************/
+
+ public int left, right;
+ public Object value;
+
+ /*****************************
+ Printing this token out. (Override for pretty-print).
+ ****************************/
+ public String toString() { return "#"+sym; }
+}
+
+
+
+
+
+
diff --git a/src/java_cup/java_cup/runtime/lr_parser.java b/src/java_cup/java_cup/runtime/lr_parser.java
new file mode 100644
index 0000000..3c8335c
--- /dev/null
+++ b/src/java_cup/java_cup/runtime/lr_parser.java
@@ -0,0 +1,1238 @@
+
+package java_cup.runtime;
+
+import java.util.Stack;
+
+/** This class implements a skeleton table driven LR parser. In general,
+ * LR parsers are a form of bottom up shift-reduce parsers. Shift-reduce
+ * parsers act by shifting input onto a parse stack until the Symbols
+ * matching the right hand side of a production appear on the top of the
+ * stack. Once this occurs, a reduce is performed. This involves removing
+ * the Symbols corresponding to the right hand side of the production
+ * (the so called "handle") and replacing them with the non-terminal from
+ * the left hand side of the production. <p>
+ *
+ * To control the decision of whether to shift or reduce at any given point,
+ * the parser uses a state machine (the "viable prefix recognition machine"
+ * built by the parser generator). The current state of the machine is placed
+ * on top of the parse stack (stored as part of a Symbol object representing
+ * a terminal or non terminal). The parse action table is consulted
+ * (using the current state and the current lookahead Symbol as indexes) to
+ * determine whether to shift or to reduce. When the parser shifts, it
+ * changes to a new state by pushing a new Symbol (containing a new state)
+ * onto the stack. When the parser reduces, it pops the handle (right hand
+ * side of a production) off the stack. This leaves the parser in the state
+ * it was in before any of those Symbols were matched. Next the reduce-goto
+ * table is consulted (using the new state and current lookahead Symbol as
+ * indexes) to determine a new state to go to. The parser then shifts to
+ * this goto state by pushing the left hand side Symbol of the production
+ * (also containing the new state) onto the stack.<p>
+ *
+ * This class actually provides four LR parsers. The methods parse() and
+ * debug_parse() provide two versions of the main parser (the only difference
+ * being that debug_parse() emits debugging trace messages as it parses).
+ * In addition to these main parsers, the error recovery mechanism uses two
+ * more. One of these is used to simulate "parsing ahead" in the input
+ * without carrying out actions (to verify that a potential error recovery
+ * has worked), and the other is used to parse through buffered "parse ahead"
+ * input in order to execute all actions and re-synchronize the actual parser
+ * configuration.<p>
+ *
+ * This is an abstract class which is normally filled out by a subclass
+ * generated by the JavaCup parser generator. In addition to supplying
+ * the actual parse tables, generated code also supplies methods which
+ * invoke various pieces of user supplied code, provide access to certain
+ * special Symbols (e.g., EOF and error), etc. Specifically, the following
+ * abstract methods are normally supplied by generated code:
+ * <dl compact>
+ * <dt> short[][] production_table()
+ * <dd> Provides a reference to the production table (indicating the index of
+ * the left hand side non terminal and the length of the right hand side
+ * for each production in the grammar).
+ * <dt> short[][] action_table()
+ * <dd> Provides a reference to the parse action table.
+ * <dt> short[][] reduce_table()
+ * <dd> Provides a reference to the reduce-goto table.
+ * <dt> int start_state()
+ * <dd> Indicates the index of the start state.
+ * <dt> int start_production()
+ * <dd> Indicates the index of the starting production.
+ * <dt> int EOF_sym()
+ * <dd> Indicates the index of the EOF Symbol.
+ * <dt> int error_sym()
+ * <dd> Indicates the index of the error Symbol.
+ * <dt> Symbol do_action()
+ * <dd> Executes a piece of user supplied action code. This always comes at
+ * the point of a reduce in the parse, so this code also allocates and
+ * fills in the left hand side non terminal Symbol object that is to be
+ * pushed onto the stack for the reduce.
+ * <dt> void init_actions()
+ * <dd> Code to initialize a special object that encapsulates user supplied
+ * actions (this object is used by do_action() to actually carry out the
+ * actions).
+ * </dl>
+ *
+ * In addition to these routines that <i>must</i> be supplied by the
+ * generated subclass there are also a series of routines that <i>may</i>
+ * be supplied. These include:
+ * <dl>
+ * <dt> Symbol scan()
+ * <dd> Used to get the next input Symbol from the scanner.
+ * <dt> Scanner getScanner()
+ * <dd> Used to provide a scanner for the default implementation of
+ * scan().
+ * <dt> int error_sync_size()
+ * <dd> This determines how many Symbols past the point of an error
+ * must be parsed without error in order to consider a recovery to
+ * be valid. This defaults to 3. Values less than 2 are not
+ * recommended.
+ * <dt> void report_error(String message, Object info)
+ * <dd> This method is called to report an error. The default implementation
+ * simply prints a message to System.err and where the error occurred.
+ * This method is often replaced in order to provide a more sophisticated
+ * error reporting mechanism.
+ * <dt> void report_fatal_error(String message, Object info)
+ * <dd> This method is called when a fatal error that cannot be recovered from
+ * is encountered. In the default implementation, it calls
+ * report_error() to emit a message, then throws an exception.
+ * <dt> void syntax_error(Symbol cur_token)
+ * <dd> This method is called as soon as syntax error is detected (but
+ * before recovery is attempted). In the default implementation it
+ * invokes: report_error("Syntax error", null);
+ * <dt> void unrecovered_syntax_error(Symbol cur_token)
+ * <dd> This method is called if syntax error recovery fails. In the default
+ * implementation it invokes:<br>
+ * report_fatal_error("Couldn't repair and continue parse", null);
+ * </dl>
+ *
+ * @see java_cup.runtime.Symbol
+ * @see java_cup.runtime.Symbol
+ * @see java_cup.runtime.virtual_parse_stack
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+
+public abstract class lr_parser {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. */
+ public lr_parser()
+ {
+ /* nothing to do here */
+ }
+
+ /** Constructor that sets the default scanner. [CSA/davidm] */
+ public lr_parser(Scanner s) {
+ this(); /* in case default constructor someday does something */
+ setScanner(s);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The default number of Symbols after an error we much match to consider
+ * it recovered from.
+ */
+ protected final static int _error_sync_size = 3;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The number of Symbols after an error we much match to consider it
+ * recovered from.
+ */
+ protected int error_sync_size() {return _error_sync_size; }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Table of production information (supplied by generated subclass).
+ * This table contains one entry per production and is indexed by
+ * the negative-encoded values (reduce actions) in the action_table.
+ * Each entry has two parts, the index of the non-terminal on the
+ * left hand side of the production, and the number of Symbols
+ * on the right hand side.
+ */
+ public abstract short[][] production_table();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The action table (supplied by generated subclass). This table is
+ * indexed by state and terminal number indicating what action is to
+ * be taken when the parser is in the given state (i.e., the given state
+ * is on top of the stack) and the given terminal is next on the input.
+ * States are indexed using the first dimension, however, the entries for
+ * a given state are compacted and stored in adjacent index, value pairs
+ * which are searched for rather than accessed directly (see get_action()).
+ * The actions stored in the table will be either shifts, reduces, or
+ * errors. Shifts are encoded as positive values (one greater than the
+ * state shifted to). Reduces are encoded as negative values (one less
+ * than the production reduced by). Error entries are denoted by zero.
+ *
+ * @see java_cup.runtime.lr_parser#get_action
+ */
+ public abstract short[][] action_table();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The reduce-goto table (supplied by generated subclass). This
+ * table is indexed by state and non-terminal number and contains
+ * state numbers. States are indexed using the first dimension, however,
+ * the entries for a given state are compacted and stored in adjacent
+ * index, value pairs which are searched for rather than accessed
+ * directly (see get_reduce()). When a reduce occurs, the handle
+ * (corresponding to the RHS of the matched production) is popped off
+ * the stack. The new top of stack indicates a state. This table is
+ * then indexed by that state and the LHS of the reducing production to
+ * indicate where to "shift" to.
+ *
+ * @see java_cup.runtime.lr_parser#get_reduce
+ */
+ public abstract short[][] reduce_table();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The index of the start state (supplied by generated subclass). */
+ public abstract int start_state();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The index of the start production (supplied by generated subclass). */
+ public abstract int start_production();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The index of the end of file terminal Symbol (supplied by generated
+ * subclass).
+ */
+ public abstract int EOF_sym();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The index of the special error Symbol (supplied by generated subclass). */
+ public abstract int error_sym();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Internal flag to indicate when parser should quit. */
+ protected boolean _done_parsing = false;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** This method is called to indicate that the parser should quit. This is
+ * normally called by an accept action, but can be used to cancel parsing
+ * early in other circumstances if desired.
+ */
+ public void done_parsing()
+ {
+ _done_parsing = true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+ /* Global parse state shared by parse(), error recovery, and
+ * debugging routines */
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Indication of the index for top of stack (for use by actions). */
+ protected int tos;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The current lookahead Symbol. */
+ protected Symbol cur_token;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The parse stack itself. */
+ protected Stack stack = new Stack();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Direct reference to the production table. */
+ protected short[][] production_tab;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Direct reference to the action table. */
+ protected short[][] action_tab;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Direct reference to the reduce-goto table. */
+ protected short[][] reduce_tab;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** This is the scanner object used by the default implementation
+ * of scan() to get Symbols. To avoid name conflicts with existing
+ * code, this field is private. [CSA/davidm] */
+ private Scanner _scanner;
+
+ /**
+ * Simple accessor method to set the default scanner.
+ */
+ public void setScanner(Scanner s) { _scanner = s; }
+
+ /**
+ * Simple accessor method to get the default scanner.
+ */
+ public Scanner getScanner() { return _scanner; }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Perform a bit of user supplied action code (supplied by generated
+ * subclass). Actions are indexed by an internal action number assigned
+ * at parser generation time.
+ *
+ * @param act_num the internal index of the action to be performed.
+ * @param parser the parser object we are acting for.
+ * @param stack the parse stack of that object.
+ * @param top the index of the top element of the parse stack.
+ */
+ public abstract Symbol do_action(
+ int act_num,
+ lr_parser parser,
+ Stack stack,
+ int top)
+ throws java.lang.Exception;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** User code for initialization inside the parser. Typically this
+ * initializes the scanner. This is called before the parser requests
+ * the first Symbol. Here this is just a placeholder for subclasses that
+ * might need this and we perform no action. This method is normally
+ * overridden by the generated code using this contents of the "init with"
+ * clause as its body.
+ */
+ public void user_init() throws java.lang.Exception { }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Initialize the action object. This is called before the parser does
+ * any parse actions. This is filled in by generated code to create
+ * an object that encapsulates all action code.
+ */
+ protected abstract void init_actions() throws java.lang.Exception;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Get the next Symbol from the input (supplied by generated subclass).
+ * Once end of file has been reached, all subsequent calls to scan
+ * should return an EOF Symbol (which is Symbol number 0). By default
+ * this method returns getScanner().next_token(); this implementation
+ * can be overriden by the generated parser using the code declared in
+ * the "scan with" clause. Do not recycle objects; every call to
+ * scan() should return a fresh object.
+ */
+ public Symbol scan() throws java.lang.Exception {
+ Symbol sym = getScanner().next_token();
+ return (sym!=null) ? sym : new Symbol(EOF_sym());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Report a fatal error. This method takes a message string and an
+ * additional object (to be used by specializations implemented in
+ * subclasses). Here in the base class a very simple implementation
+ * is provided which reports the error then throws an exception.
+ *
+ * @param message an error message.
+ * @param info an extra object reserved for use by specialized subclasses.
+ */
+ public void report_fatal_error(
+ String message,
+ Object info)
+ throws java.lang.Exception
+ {
+ /* stop parsing (not really necessary since we throw an exception, but) */
+ done_parsing();
+
+ /* use the normal error message reporting to put out the message */
+ report_error(message, info);
+
+ /* throw an exception */
+ throw new Exception("Can't recover from previous error(s)");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Report a non fatal error (or warning). This method takes a message
+ * string and an additional object (to be used by specializations
+ * implemented in subclasses). Here in the base class a very simple
+ * implementation is provided which simply prints the message to
+ * System.err.
+ *
+ * @param message an error message.
+ * @param info an extra object reserved for use by specialized subclasses.
+ */
+ public void report_error(String message, Object info)
+ {
+ System.err.print(message);
+ if (info instanceof Symbol)
+ if (((Symbol)info).left != -1)
+ System.err.println(" at character " + ((Symbol)info).left +
+ " of input");
+ else System.err.println("");
+ else System.err.println("");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** This method is called when a syntax error has been detected and recovery
+ * is about to be invoked. Here in the base class we just emit a
+ * "Syntax error" error message.
+ *
+ * @param cur_token the current lookahead Symbol.
+ */
+ public void syntax_error(Symbol cur_token)
+ {
+ report_error("Syntax error", cur_token);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** This method is called if it is determined that syntax error recovery
+ * has been unsuccessful. Here in the base class we report a fatal error.
+ *
+ * @param cur_token the current lookahead Symbol.
+ */
+ public void unrecovered_syntax_error(Symbol cur_token)
+ throws java.lang.Exception
+ {
+ report_fatal_error("Couldn't repair and continue parse", cur_token);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Fetch an action from the action table. The table is broken up into
+ * rows, one per state (rows are indexed directly by state number).
+ * Within each row, a list of index, value pairs are given (as sequential
+ * entries in the table), and the list is terminated by a default entry
+ * (denoted with a Symbol index of -1). To find the proper entry in a row
+ * we do a linear or binary search (depending on the size of the row).
+ *
+ * @param state the state index of the action being accessed.
+ * @param sym the Symbol index of the action being accessed.
+ */
+ protected final short get_action(int state, int sym)
+ {
+ short tag;
+ int first, last, probe;
+ short[] row = action_tab[state];
+
+ /* linear search if we are < 10 entries */
+ if (row.length < 20)
+ for (probe = 0; probe < row.length; probe++)
+ {
+ /* is this entry labeled with our Symbol or the default? */
+ tag = row[probe++];
+ if (tag == sym || tag == -1)
+ {
+ /* return the next entry */
+ return row[probe];
+ }
+ }
+ /* otherwise binary search */
+ else
+ {
+ first = 0;
+ last = (row.length-1)/2 - 1; /* leave out trailing default entry */
+ while (first <= last)
+ {
+ probe = (first+last)/2;
+ if (sym == row[probe*2])
+ return row[probe*2+1];
+ else if (sym > row[probe*2])
+ first = probe+1;
+ else
+ last = probe-1;
+ }
+
+ /* not found, use the default at the end */
+ return row[row.length-1];
+ }
+
+ /* shouldn't happened, but if we run off the end we return the
+ default (error == 0) */
+ return 0;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Fetch a state from the reduce-goto table. The table is broken up into
+ * rows, one per state (rows are indexed directly by state number).
+ * Within each row, a list of index, value pairs are given (as sequential
+ * entries in the table), and the list is terminated by a default entry
+ * (denoted with a Symbol index of -1). To find the proper entry in a row
+ * we do a linear search.
+ *
+ * @param state the state index of the entry being accessed.
+ * @param sym the Symbol index of the entry being accessed.
+ */
+ protected final short get_reduce(int state, int sym)
+ {
+ short tag;
+ short[] row = reduce_tab[state];
+
+ /* if we have a null row we go with the default */
+ if (row == null)
+ return -1;
+
+ for (int probe = 0; probe < row.length; probe++)
+ {
+ /* is this entry labeled with our Symbol or the default? */
+ tag = row[probe++];
+ if (tag == sym || tag == -1)
+ {
+ /* return the next entry */
+ return row[probe];
+ }
+ }
+ /* if we run off the end we return the default (error == -1) */
+ return -1;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** This method provides the main parsing routine. It returns only when
+ * done_parsing() has been called (typically because the parser has
+ * accepted, or a fatal error has been reported). See the header
+ * documentation for the class regarding how shift/reduce parsers operate
+ * and how the various tables are used.
+ */
+ public Symbol parse() throws java.lang.Exception
+ {
+ /* the current action code */
+ int act;
+
+ /* the Symbol/stack element returned by a reduce */
+ Symbol lhs_sym = null;
+
+ /* information about production being reduced with */
+ short handle_size, lhs_sym_num;
+
+ /* set up direct reference to tables to drive the parser */
+
+ production_tab = production_table();
+ action_tab = action_table();
+ reduce_tab = reduce_table();
+
+ /* initialize the action encapsulation object */
+ init_actions();
+
+ /* do user initialization */
+ user_init();
+
+ /* get the first token */
+ cur_token = scan();
+
+ /* push dummy Symbol with start state to get us underway */
+ stack.removeAllElements();
+ stack.push(new Symbol(0, start_state()));
+ tos = 0;
+
+ /* continue until we are told to stop */
+ for (_done_parsing = false; !_done_parsing; )
+ {
+ /* Check current token for freshness. */
+ if (cur_token.used_by_parser)
+ throw new Error("Symbol recycling detected (fix your scanner).");
+
+ /* current state is always on the top of the stack */
+
+ /* look up action out of the current state with the current input */
+ act = get_action(((Symbol)stack.peek()).parse_state, cur_token.sym);
+
+ /* decode the action -- > 0 encodes shift */
+ if (act > 0)
+ {
+ /* shift to the encoded state by pushing it on the stack */
+ cur_token.parse_state = act-1;
+ cur_token.used_by_parser = true;
+ stack.push(cur_token);
+ tos++;
+
+ /* advance to the next Symbol */
+ cur_token = scan();
+ }
+ /* if its less than zero, then it encodes a reduce action */
+ else if (act < 0)
+ {
+ /* perform the action for the reduce */
+ lhs_sym = do_action((-act)-1, this, stack, tos);
+
+ /* look up information about the production */
+ lhs_sym_num = production_tab[(-act)-1][0];
+ handle_size = production_tab[(-act)-1][1];
+
+ /* pop the handle off the stack */
+ for (int i = 0; i < handle_size; i++)
+ {
+ stack.pop();
+ tos--;
+ }
+
+ /* look up the state to go to from the one popped back to */
+ act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num);
+
+ /* shift to that state */
+ lhs_sym.parse_state = act;
+ lhs_sym.used_by_parser = true;
+ stack.push(lhs_sym);
+ tos++;
+ }
+ /* finally if the entry is zero, we have an error */
+ else if (act == 0)
+ {
+ /* call user syntax error reporting routine */
+ syntax_error(cur_token);
+
+ /* try to error recover */
+ if (!error_recovery(false))
+ {
+ /* if that fails give up with a fatal syntax error */
+ unrecovered_syntax_error(cur_token);
+
+ /* just in case that wasn't fatal enough, end parse */
+ done_parsing();
+ } else {
+ lhs_sym = (Symbol)stack.peek();
+ }
+ }
+ }
+ return lhs_sym;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Write a debugging message to System.err for the debugging version
+ * of the parser.
+ *
+ * @param mess the text of the debugging message.
+ */
+ public void debug_message(String mess)
+ {
+ System.err.println(mess);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Dump the parse stack for debugging purposes. */
+ public void dump_stack()
+ {
+ if (stack == null)
+ {
+ debug_message("# Stack dump requested, but stack is null");
+ return;
+ }
+
+ debug_message("============ Parse Stack Dump ============");
+
+ /* dump the stack */
+ for (int i=0; i<stack.size(); i++)
+ {
+ debug_message("Symbol: " + ((Symbol)stack.elementAt(i)).sym +
+ " State: " + ((Symbol)stack.elementAt(i)).parse_state);
+ }
+ debug_message("==========================================");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Do debug output for a reduce.
+ *
+ * @param prod_num the production we are reducing with.
+ * @param nt_num the index of the LHS non terminal.
+ * @param rhs_size the size of the RHS.
+ */
+ public void debug_reduce(int prod_num, int nt_num, int rhs_size)
+ {
+ debug_message("# Reduce with prod #" + prod_num + " [NT=" + nt_num +
+ ", " + "SZ=" + rhs_size + "]");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Do debug output for shift.
+ *
+ * @param shift_tkn the Symbol being shifted onto the stack.
+ */
+ public void debug_shift(Symbol shift_tkn)
+ {
+ debug_message("# Shift under term #" + shift_tkn.sym +
+ " to state #" + shift_tkn.parse_state);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Do debug output for stack state. [CSA]
+ */
+ public void debug_stack() {
+ StringBuffer sb=new StringBuffer("## STACK:");
+ for (int i=0; i<stack.size(); i++) {
+ Symbol s = (Symbol) stack.elementAt(i);
+ sb.append(" <state "+s.parse_state+", sym "+s.sym+">");
+ if ((i%3)==2 || (i==(stack.size()-1))) {
+ debug_message(sb.toString());
+ sb = new StringBuffer(" ");
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Perform a parse with debugging output. This does exactly the
+ * same things as parse(), except that it calls debug_shift() and
+ * debug_reduce() when shift and reduce moves are taken by the parser
+ * and produces various other debugging messages.
+ */
+ public Symbol debug_parse()
+ throws java.lang.Exception
+ {
+ /* the current action code */
+ int act;
+
+ /* the Symbol/stack element returned by a reduce */
+ Symbol lhs_sym = null;
+
+ /* information about production being reduced with */
+ short handle_size, lhs_sym_num;
+
+ /* set up direct reference to tables to drive the parser */
+ production_tab = production_table();
+ action_tab = action_table();
+ reduce_tab = reduce_table();
+
+ debug_message("# Initializing parser");
+
+ /* initialize the action encapsulation object */
+ init_actions();
+
+ /* do user initialization */
+ user_init();
+
+ /* the current Symbol */
+ cur_token = scan();
+
+ debug_message("# Current Symbol is #" + cur_token.sym);
+
+ /* push dummy Symbol with start state to get us underway */
+ stack.removeAllElements();
+ stack.push(new Symbol(0, start_state()));
+ tos = 0;
+
+ /* continue until we are told to stop */
+ for (_done_parsing = false; !_done_parsing; )
+ {
+ /* Check current token for freshness. */
+ if (cur_token.used_by_parser)
+ throw new Error("Symbol recycling detected (fix your scanner).");
+
+ /* current state is always on the top of the stack */
+ //debug_stack();
+
+ /* look up action out of the current state with the current input */
+ act = get_action(((Symbol)stack.peek()).parse_state, cur_token.sym);
+
+ /* decode the action -- > 0 encodes shift */
+ if (act > 0)
+ {
+ /* shift to the encoded state by pushing it on the stack */
+ cur_token.parse_state = act-1;
+ cur_token.used_by_parser = true;
+ debug_shift(cur_token);
+ stack.push(cur_token);
+ tos++;
+
+ /* advance to the next Symbol */
+ cur_token = scan();
+ debug_message("# Current token is " + cur_token);
+ }
+ /* if its less than zero, then it encodes a reduce action */
+ else if (act < 0)
+ {
+ /* perform the action for the reduce */
+ lhs_sym = do_action((-act)-1, this, stack, tos);
+
+ /* look up information about the production */
+ lhs_sym_num = production_tab[(-act)-1][0];
+ handle_size = production_tab[(-act)-1][1];
+
+ debug_reduce((-act)-1, lhs_sym_num, handle_size);
+
+ /* pop the handle off the stack */
+ for (int i = 0; i < handle_size; i++)
+ {
+ stack.pop();
+ tos--;
+ }
+
+ /* look up the state to go to from the one popped back to */
+ act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num);
+ debug_message("# Reduce rule: top state " +
+ ((Symbol)stack.peek()).parse_state +
+ ", lhs sym " + lhs_sym_num + " -> state " + act);
+
+ /* shift to that state */
+ lhs_sym.parse_state = act;
+ lhs_sym.used_by_parser = true;
+ stack.push(lhs_sym);
+ tos++;
+
+ debug_message("# Goto state #" + act);
+ }
+ /* finally if the entry is zero, we have an error */
+ else if (act == 0)
+ {
+ /* call user syntax error reporting routine */
+ syntax_error(cur_token);
+
+ /* try to error recover */
+ if (!error_recovery(true))
+ {
+ /* if that fails give up with a fatal syntax error */
+ unrecovered_syntax_error(cur_token);
+
+ /* just in case that wasn't fatal enough, end parse */
+ done_parsing();
+ } else {
+ lhs_sym = (Symbol)stack.peek();
+ }
+ }
+ }
+ return lhs_sym;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+ /* Error recovery code */
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Attempt to recover from a syntax error. This returns false if recovery
+ * fails, true if it succeeds. Recovery happens in 4 steps. First we
+ * pop the parse stack down to a point at which we have a shift out
+ * of the top-most state on the error Symbol. This represents the
+ * initial error recovery configuration. If no such configuration is
+ * found, then we fail. Next a small number of "lookahead" or "parse
+ * ahead" Symbols are read into a buffer. The size of this buffer is
+ * determined by error_sync_size() and determines how many Symbols beyond
+ * the error must be matched to consider the recovery a success. Next,
+ * we begin to discard Symbols in attempt to get past the point of error
+ * to a point where we can continue parsing. After each Symbol, we attempt
+ * to "parse ahead" though the buffered lookahead Symbols. The "parse ahead"
+ * process simulates that actual parse, but does not modify the real
+ * parser's configuration, nor execute any actions. If we can parse all
+ * the stored Symbols without error, then the recovery is considered a
+ * success. Once a successful recovery point is determined, we do an
+ * actual parse over the stored input -- modifying the real parse
+ * configuration and executing all actions. Finally, we return the the
+ * normal parser to continue with the overall parse.
+ *
+ * @param debug should we produce debugging messages as we parse.
+ */
+ protected boolean error_recovery(boolean debug)
+ throws java.lang.Exception
+ {
+ if (debug) debug_message("# Attempting error recovery");
+
+ /* first pop the stack back into a state that can shift on error and
+ do that shift (if that fails, we fail) */
+ if (!find_recovery_config(debug))
+ {
+ if (debug) debug_message("# Error recovery fails");
+ return false;
+ }
+
+ /* read ahead to create lookahead we can parse multiple times */
+ read_lookahead();
+
+ /* repeatedly try to parse forward until we make it the required dist */
+ for (;;)
+ {
+ /* try to parse forward, if it makes it, bail out of loop */
+ if (debug) debug_message("# Trying to parse ahead");
+ if (try_parse_ahead(debug))
+ {
+ break;
+ }
+
+ /* if we are now at EOF, we have failed */
+ if (lookahead[0].sym == EOF_sym())
+ {
+ if (debug) debug_message("# Error recovery fails at EOF");
+ return false;
+ }
+
+ /* otherwise, we consume another Symbol and try again */
+ // BUG FIX by Bruce Hutton
+ // Computer Science Department, University of Auckland,
+ // Auckland, New Zealand.
+ // It is the first token that is being consumed, not the one
+ // we were up to parsing
+ if (debug)
+ debug_message("# Consuming Symbol #" + lookahead[ 0 ].sym);
+ restart_lookahead();
+ }
+
+ /* we have consumed to a point where we can parse forward */
+ if (debug) debug_message("# Parse-ahead ok, going back to normal parse");
+
+ /* do the real parse (including actions) across the lookahead */
+ parse_lookahead(debug);
+
+ /* we have success */
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if we can shift under the special error Symbol out of the
+ * state currently on the top of the (real) parse stack.
+ */
+ protected boolean shift_under_error()
+ {
+ /* is there a shift under error Symbol */
+ return get_action(((Symbol)stack.peek()).parse_state, error_sym()) > 0;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Put the (real) parse stack into error recovery configuration by
+ * popping the stack down to a state that can shift on the special
+ * error Symbol, then doing the shift. If no suitable state exists on
+ * the stack we return false
+ *
+ * @param debug should we produce debugging messages as we parse.
+ */
+ protected boolean find_recovery_config(boolean debug)
+ {
+ Symbol error_token;
+ int act;
+
+ if (debug) debug_message("# Finding recovery state on stack");
+
+ /* Remember the right-position of the top symbol on the stack */
+ int right_pos = ((Symbol)stack.peek()).right;
+ int left_pos = ((Symbol)stack.peek()).left;
+
+ /* pop down until we can shift under error Symbol */
+ while (!shift_under_error())
+ {
+ /* pop the stack */
+ if (debug)
+ debug_message("# Pop stack by one, state was # " +
+ ((Symbol)stack.peek()).parse_state);
+ left_pos = ((Symbol)stack.pop()).left;
+ tos--;
+
+ /* if we have hit bottom, we fail */
+ if (stack.empty())
+ {
+ if (debug) debug_message("# No recovery state found on stack");
+ return false;
+ }
+ }
+
+ /* state on top of the stack can shift under error, find the shift */
+ act = get_action(((Symbol)stack.peek()).parse_state, error_sym());
+ if (debug)
+ {
+ debug_message("# Recover state found (#" +
+ ((Symbol)stack.peek()).parse_state + ")");
+ debug_message("# Shifting on error to state #" + (act-1));
+ }
+
+ /* build and shift a special error Symbol */
+ error_token = new Symbol(error_sym(), left_pos, right_pos);
+ error_token.parse_state = act-1;
+ error_token.used_by_parser = true;
+ stack.push(error_token);
+ tos++;
+
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Lookahead Symbols used for attempting error recovery "parse aheads". */
+ protected Symbol lookahead[];
+
+ /** Position in lookahead input buffer used for "parse ahead". */
+ protected int lookahead_pos;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Read from input to establish our buffer of "parse ahead" lookahead
+ * Symbols.
+ */
+ protected void read_lookahead() throws java.lang.Exception
+ {
+ /* create the lookahead array */
+ lookahead = new Symbol[error_sync_size()];
+
+ /* fill in the array */
+ for (int i = 0; i < error_sync_size(); i++)
+ {
+ lookahead[i] = cur_token;
+ cur_token = scan();
+ }
+
+ /* start at the beginning */
+ lookahead_pos = 0;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return the current lookahead in our error "parse ahead" buffer. */
+ protected Symbol cur_err_token() { return lookahead[lookahead_pos]; }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Advance to next "parse ahead" input Symbol. Return true if we have
+ * input to advance to, false otherwise.
+ */
+ protected boolean advance_lookahead()
+ {
+ /* advance the input location */
+ lookahead_pos++;
+
+ /* return true if we didn't go off the end */
+ return lookahead_pos < error_sync_size();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Reset the parse ahead input to one Symbol past where we started error
+ * recovery (this consumes one new Symbol from the real input).
+ */
+ protected void restart_lookahead() throws java.lang.Exception
+ {
+ /* move all the existing input over */
+ for (int i = 1; i < error_sync_size(); i++)
+ lookahead[i-1] = lookahead[i];
+
+ /* read a new Symbol into the last spot */
+ // BUG Fix by Bruce Hutton
+ // Computer Science Department, University of Auckland,
+ // Auckland, New Zealand. [applied 5-sep-1999 by csa]
+ // The following two lines were out of order!!
+ lookahead[error_sync_size()-1] = cur_token;
+ cur_token = scan();
+
+ /* reset our internal position marker */
+ lookahead_pos = 0;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Do a simulated parse forward (a "parse ahead") from the current
+ * stack configuration using stored lookahead input and a virtual parse
+ * stack. Return true if we make it all the way through the stored
+ * lookahead input without error. This basically simulates the action of
+ * parse() using only our saved "parse ahead" input, and not executing any
+ * actions.
+ *
+ * @param debug should we produce debugging messages as we parse.
+ */
+ protected boolean try_parse_ahead(boolean debug)
+ throws java.lang.Exception
+ {
+ int act;
+ short lhs, rhs_size;
+
+ /* create a virtual stack from the real parse stack */
+ virtual_parse_stack vstack = new virtual_parse_stack(stack);
+
+ /* parse until we fail or get past the lookahead input */
+ for (;;)
+ {
+ /* look up the action from the current state (on top of stack) */
+ act = get_action(vstack.top(), cur_err_token().sym);
+
+ /* if its an error, we fail */
+ if (act == 0) return false;
+
+ /* > 0 encodes a shift */
+ if (act > 0)
+ {
+ /* push the new state on the stack */
+ vstack.push(act-1);
+
+ if (debug) debug_message("# Parse-ahead shifts Symbol #" +
+ cur_err_token().sym + " into state #" + (act-1));
+
+ /* advance simulated input, if we run off the end, we are done */
+ if (!advance_lookahead()) return true;
+ }
+ /* < 0 encodes a reduce */
+ else
+ {
+ /* if this is a reduce with the start production we are done */
+ if ((-act)-1 == start_production())
+ {
+ if (debug) debug_message("# Parse-ahead accepts");
+ return true;
+ }
+
+ /* get the lhs Symbol and the rhs size */
+ lhs = production_tab[(-act)-1][0];
+ rhs_size = production_tab[(-act)-1][1];
+
+ /* pop handle off the stack */
+ for (int i = 0; i < rhs_size; i++)
+ vstack.pop();
+
+ if (debug)
+ debug_message("# Parse-ahead reduces: handle size = " +
+ rhs_size + " lhs = #" + lhs + " from state #" + vstack.top());
+
+ /* look up goto and push it onto the stack */
+ vstack.push(get_reduce(vstack.top(), lhs));
+ if (debug)
+ debug_message("# Goto state #" + vstack.top());
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Parse forward using stored lookahead Symbols. In this case we have
+ * already verified that parsing will make it through the stored lookahead
+ * Symbols and we are now getting back to the point at which we can hand
+ * control back to the normal parser. Consequently, this version of the
+ * parser performs all actions and modifies the real parse configuration.
+ * This returns once we have consumed all the stored input or we accept.
+ *
+ * @param debug should we produce debugging messages as we parse.
+ */
+ protected void parse_lookahead(boolean debug)
+ throws java.lang.Exception
+ {
+ /* the current action code */
+ int act;
+
+ /* the Symbol/stack element returned by a reduce */
+ Symbol lhs_sym = null;
+
+ /* information about production being reduced with */
+ short handle_size, lhs_sym_num;
+
+ /* restart the saved input at the beginning */
+ lookahead_pos = 0;
+
+ if (debug)
+ {
+ debug_message("# Reparsing saved input with actions");
+ debug_message("# Current Symbol is #" + cur_err_token().sym);
+ debug_message("# Current state is #" +
+ ((Symbol)stack.peek()).parse_state);
+ }
+
+ /* continue until we accept or have read all lookahead input */
+ while(!_done_parsing)
+ {
+ /* current state is always on the top of the stack */
+
+ /* look up action out of the current state with the current input */
+ act =
+ get_action(((Symbol)stack.peek()).parse_state, cur_err_token().sym);
+
+ /* decode the action -- > 0 encodes shift */
+ if (act > 0)
+ {
+ /* shift to the encoded state by pushing it on the stack */
+ cur_err_token().parse_state = act-1;
+ cur_err_token().used_by_parser = true;
+ if (debug) debug_shift(cur_err_token());
+ stack.push(cur_err_token());
+ tos++;
+
+ /* advance to the next Symbol, if there is none, we are done */
+ if (!advance_lookahead())
+ {
+ if (debug) debug_message("# Completed reparse");
+
+ /* scan next Symbol so we can continue parse */
+ // BUGFIX by Chris Harris <ckharris@ucsd.edu>:
+ // correct a one-off error by commenting out
+ // this next line.
+ /*cur_token = scan();*/
+
+ /* go back to normal parser */
+ return;
+ }
+
+ if (debug)
+ debug_message("# Current Symbol is #" + cur_err_token().sym);
+ }
+ /* if its less than zero, then it encodes a reduce action */
+ else if (act < 0)
+ {
+ /* perform the action for the reduce */
+ lhs_sym = do_action((-act)-1, this, stack, tos);
+
+ /* look up information about the production */
+ lhs_sym_num = production_tab[(-act)-1][0];
+ handle_size = production_tab[(-act)-1][1];
+
+ if (debug) debug_reduce((-act)-1, lhs_sym_num, handle_size);
+
+ /* pop the handle off the stack */
+ for (int i = 0; i < handle_size; i++)
+ {
+ stack.pop();
+ tos--;
+ }
+
+ /* look up the state to go to from the one popped back to */
+ act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num);
+
+ /* shift to that state */
+ lhs_sym.parse_state = act;
+ lhs_sym.used_by_parser = true;
+ stack.push(lhs_sym);
+ tos++;
+
+ if (debug) debug_message("# Goto state #" + act);
+
+ }
+ /* finally if the entry is zero, we have an error
+ (shouldn't happen here, but...)*/
+ else if (act == 0)
+ {
+ report_fatal_error("Syntax error", lhs_sym);
+ return;
+ }
+ }
+
+
+ }
+
+ /*-----------------------------------------------------------*/
+
+ /** Utility function: unpacks parse tables from strings */
+ protected static short[][] unpackFromStrings(String[] sa)
+ {
+ // Concatanate initialization strings.
+ StringBuffer sb = new StringBuffer(sa[0]);
+ for (int i=1; i<sa.length; i++)
+ sb.append(sa[i]);
+ int n=0; // location in initialization string
+ int size1 = (((int)sb.charAt(n))<<16) | ((int)sb.charAt(n+1)); n+=2;
+ short[][] result = new short[size1][];
+ for (int i=0; i<size1; i++) {
+ int size2 = (((int)sb.charAt(n))<<16) | ((int)sb.charAt(n+1)); n+=2;
+ result[i] = new short[size2];
+ for (int j=0; j<size2; j++)
+ result[i][j] = (short) (sb.charAt(n++)-2);
+ }
+ return result;
+ }
+}
+
diff --git a/src/java_cup/java_cup/runtime/virtual_parse_stack.java b/src/java_cup/java_cup/runtime/virtual_parse_stack.java
new file mode 100644
index 0000000..a4386aa
--- /dev/null
+++ b/src/java_cup/java_cup/runtime/virtual_parse_stack.java
@@ -0,0 +1,145 @@
+
+package java_cup.runtime;
+
+import java.util.Stack;
+
+/** This class implements a temporary or "virtual" parse stack that
+ * replaces the top portion of the actual parse stack (the part that
+ * has been changed by some set of operations) while maintaining its
+ * original contents. This data structure is used when the parse needs
+ * to "parse ahead" to determine if a given error recovery attempt will
+ * allow the parse to continue far enough to consider it successful. Once
+ * success or failure of parse ahead is determined the system then
+ * reverts to the original parse stack (which has not actually been
+ * modified). Since parse ahead does not execute actions, only parse
+ * state is maintained on the virtual stack, not full Symbol objects.
+ *
+ * @see java_cup.runtime.lr_parser
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+
+public class virtual_parse_stack {
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constructor to build a virtual stack out of a real stack. */
+ public virtual_parse_stack(Stack shadowing_stack) throws java.lang.Exception
+ {
+ /* sanity check */
+ if (shadowing_stack == null)
+ throw new Exception(
+ "Internal parser error: attempt to create null virtual stack");
+
+ /* set up our internals */
+ real_stack = shadowing_stack;
+ vstack = new Stack();
+ real_next = 0;
+
+ /* get one element onto the virtual portion of the stack */
+ get_from_real();
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The real stack that we shadow. This is accessed when we move off
+ * the bottom of the virtual portion of the stack, but is always left
+ * unmodified.
+ */
+ protected Stack real_stack;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Top of stack indicator for where we leave off in the real stack.
+ * This is measured from top of stack, so 0 would indicate that no
+ * elements have been "moved" from the real to virtual stack.
+ */
+ protected int real_next;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The virtual top portion of the stack. This stack contains Integer
+ * objects with state numbers. This stack shadows the top portion
+ * of the real stack within the area that has been modified (via operations
+ * on the virtual stack). When this portion of the stack becomes empty we
+ * transfer elements from the underlying stack onto this stack.
+ */
+ protected Stack vstack;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Transfer an element from the real to the virtual stack. This assumes
+ * that the virtual stack is currently empty.
+ */
+ protected void get_from_real()
+ {
+ Symbol stack_sym;
+
+ /* don't transfer if the real stack is empty */
+ if (real_next >= real_stack.size()) return;
+
+ /* get a copy of the first Symbol we have not transfered */
+ stack_sym = (Symbol)real_stack.elementAt(real_stack.size()-1-real_next);
+
+ /* record the transfer */
+ real_next++;
+
+ /* put the state number from the Symbol onto the virtual stack */
+ vstack.push(new Integer(stack_sym.parse_state));
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Indicate whether the stack is empty. */
+ public boolean empty()
+ {
+ /* if vstack is empty then we were unable to transfer onto it and
+ the whole thing is empty. */
+ return vstack.empty();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return value on the top of the stack (without popping it). */
+ public int top() throws java.lang.Exception
+ {
+ if (vstack.empty())
+ throw new Exception(
+ "Internal parser error: top() called on empty virtual stack");
+
+ return ((Integer)vstack.peek()).intValue();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Pop the stack. */
+ public void pop() throws java.lang.Exception
+ {
+ if (vstack.empty())
+ throw new Exception(
+ "Internal parser error: pop from empty virtual stack");
+
+ /* pop it */
+ vstack.pop();
+
+ /* if we are now empty transfer an element (if there is one) */
+ if (vstack.empty())
+ get_from_real();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Push a state number onto the stack. */
+ public void push(int state_num)
+ {
+ vstack.push(new Integer(state_num));
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/java_cup/java_cup/shift_action.java b/src/java_cup/java_cup/shift_action.java
new file mode 100644
index 0000000..33fc17a
--- /dev/null
+++ b/src/java_cup/java_cup/shift_action.java
@@ -0,0 +1,82 @@
+
+package java_cup;
+
+/** This class represents a shift action within the parse table.
+ * The action simply stores the state that it shifts to and responds
+ * to queries about its type.
+ *
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class shift_action extends parse_action {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor.
+ * @param shft_to the state that this action shifts to.
+ */
+ public shift_action(lalr_state shft_to) throws internal_error
+ {
+ /* sanity check */
+ if (shft_to == null)
+ throw new internal_error(
+ "Attempt to create a shift_action to a null state");
+
+ _shift_to = shft_to;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The state we shift to. */
+ protected lalr_state _shift_to;
+
+ /** The state we shift to. */
+ public lalr_state shift_to() {return _shift_to;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Quick access to type of action. */
+ public int kind() {return SHIFT;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality test. */
+ public boolean equals(shift_action other)
+ {
+ return other != null && other.shift_to() == shift_to();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality test. */
+ public boolean equals(Object other)
+ {
+ if (other instanceof shift_action)
+ return equals((shift_action)other);
+ else
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute a hash code. */
+ public int hashCode()
+ {
+ /* use the hash code of the state we are shifting to */
+ return shift_to().hashCode();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString() {return "SHIFT(to state " + shift_to().index() + ")";}
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/java_cup/java_cup/sym.java b/src/java_cup/java_cup/sym.java
new file mode 100644
index 0000000..9810a3d
--- /dev/null
+++ b/src/java_cup/java_cup/sym.java
@@ -0,0 +1,43 @@
+
+//----------------------------------------------------
+// The following code was generated by CUP v0.10k
+// Sun Jul 25 13:35:26 EDT 1999
+//----------------------------------------------------
+
+package java_cup;
+
+/** CUP generated class containing symbol constants. */
+public class sym {
+ /* terminals */
+ public static final int NON = 8;
+ public static final int NONTERMINAL = 27;
+ public static final int STAR = 15;
+ public static final int SEMI = 13;
+ public static final int CODE = 4;
+ public static final int EOF = 0;
+ public static final int NONASSOC = 23;
+ public static final int LEFT = 21;
+ public static final int PACKAGE = 2;
+ public static final int COLON = 17;
+ public static final int WITH = 11;
+ public static final int IMPORT = 3;
+ public static final int error = 1;
+ public static final int COLON_COLON_EQUALS = 18;
+ public static final int COMMA = 14;
+ public static final int DOT = 16;
+ public static final int SCAN = 10;
+ public static final int ID = 28;
+ public static final int INIT = 9;
+ public static final int PARSER = 6;
+ public static final int TERMINAL = 7;
+ public static final int PRECEDENCE = 20;
+ public static final int LBRACK = 25;
+ public static final int RBRACK = 26;
+ public static final int PERCENT_PREC = 24;
+ public static final int START = 12;
+ public static final int RIGHT = 22;
+ public static final int BAR = 19;
+ public static final int ACTION = 5;
+ public static final int CODE_STRING = 29;
+}
+
diff --git a/src/java_cup/java_cup/symbol.java b/src/java_cup/java_cup/symbol.java
new file mode 100644
index 0000000..94d8b7d
--- /dev/null
+++ b/src/java_cup/java_cup/symbol.java
@@ -0,0 +1,107 @@
+package java_cup;
+
+/** This abstract class serves as the base class for grammar symbols (i.e.,
+ * both terminals and non-terminals). Each symbol has a name string, and
+ * a string giving the type of object that the symbol will be represented by
+ * on the runtime parse stack. In addition, each symbol maintains a use count
+ * in order to detect symbols that are declared but never used, and an index
+ * number that indicates where it appears in parse tables (index numbers are
+ * unique within terminals or non terminals, but not across both).
+ *
+ * @see java_cup.terminal
+ * @see java_cup.non_terminal
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+public abstract class symbol {
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param nm the name of the symbol.
+ * @param tp a string with the type name.
+ */
+ public symbol(String nm, String tp)
+ {
+ /* sanity check */
+ if (nm == null) nm = "";
+
+ /* apply default if no type given */
+ if (tp == null) tp = "Object";
+
+ _name = nm;
+ _stack_type = tp;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with default type.
+ * @param nm the name of the symbol.
+ */
+ public symbol(String nm)
+ {
+ this(nm, null);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** String for the human readable name of the symbol. */
+ protected String _name;
+
+ /** String for the human readable name of the symbol. */
+ public String name() {return _name;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** String for the type of object used for the symbol on the parse stack. */
+ protected String _stack_type;
+
+ /** String for the type of object used for the symbol on the parse stack. */
+ public String stack_type() {return _stack_type;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of how many times the symbol appears in productions. */
+ protected int _use_count = 0;
+
+ /** Count of how many times the symbol appears in productions. */
+ public int use_count() {return _use_count;}
+
+ /** Increment the use count. */
+ public void note_use() {_use_count++;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Index of this symbol (terminal or non terminal) in the parse tables.
+ * Note: indexes are unique among terminals and unique among non terminals,
+ * however, a terminal may have the same index as a non-terminal, etc.
+ */
+ protected int _index;
+
+ /** Index of this symbol (terminal or non terminal) in the parse tables.
+ * Note: indexes are unique among terminals and unique among non terminals,
+ * however, a terminal may have the same index as a non-terminal, etc.
+ */
+ public int index() {return _index;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Indicate if this is a non-terminal. Here in the base class we
+ * don't know, so this is abstract.
+ */
+ public abstract boolean is_non_term();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ return name();
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/java_cup/java_cup/symbol_part.java b/src/java_cup/java_cup/symbol_part.java
new file mode 100644
index 0000000..9142b5f
--- /dev/null
+++ b/src/java_cup/java_cup/symbol_part.java
@@ -0,0 +1,100 @@
+package java_cup;
+
+/** This class represents a part of a production which is a symbol (terminal
+ * or non terminal). This simply maintains a reference to the symbol in
+ * question.
+ *
+ * @see java_cup.production
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class symbol_part extends production_part {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param sym the symbol that this part is made up of.
+ * @param lab an optional label string for the part.
+ */
+ public symbol_part(symbol sym, String lab) throws internal_error
+ {
+ super(lab);
+
+ if (sym == null)
+ throw new internal_error(
+ "Attempt to construct a symbol_part with a null symbol");
+ _the_symbol = sym;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with no label.
+ * @param sym the symbol that this part is made up of.
+ */
+ public symbol_part(symbol sym) throws internal_error
+ {
+ this(sym,null);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The symbol that this part is made up of. */
+ protected symbol _the_symbol;
+
+ /** The symbol that this part is made up of. */
+ public symbol the_symbol() {return _the_symbol;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Respond that we are not an action part. */
+ public boolean is_action() { return false; }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(symbol_part other)
+ {
+ return other != null && super.equals(other) &&
+ the_symbol().equals(other.the_symbol());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof symbol_part))
+ return false;
+ else
+ return equals((symbol_part)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a hash code. */
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ (the_symbol()==null ? 0 : the_symbol().hashCode());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ if (the_symbol() != null)
+ return super.toString() + the_symbol();
+ else
+ return super.toString() + "$$MISSING-SYMBOL$$";
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/java_cup/java_cup/symbol_set.java b/src/java_cup/java_cup/symbol_set.java
new file mode 100644
index 0000000..a1aec10
--- /dev/null
+++ b/src/java_cup/java_cup/symbol_set.java
@@ -0,0 +1,231 @@
+
+package java_cup;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/** This class represents a set of symbols and provides a series of
+ * set operations to manipulate them.
+ *
+ * @see java_cup.symbol
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class symbol_set {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constructor for an empty set. */
+ public symbol_set() { }
+
+ /** Constructor for cloning from another set.
+ * @param other the set we are cloning from.
+ */
+ public symbol_set(symbol_set other) throws internal_error
+ {
+ not_null(other);
+ _all = (Hashtable)other._all.clone();
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** A hash table to hold the set. Symbols are keyed using their name string.
+ */
+ protected Hashtable _all = new Hashtable(11);
+
+ /** Access to all elements of the set. */
+ public Enumeration all() {return _all.elements();}
+
+ /** size of the set */
+ public int size() {return _all.size();}
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Helper function to test for a null object and throw an exception
+ * if one is found.
+ * @param obj the object we are testing.
+ */
+ protected void not_null(Object obj) throws internal_error
+ {
+ if (obj == null)
+ throw new internal_error("Null object used in set operation");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if the set contains a particular symbol.
+ * @param sym the symbol we are looking for.
+ */
+ public boolean contains(symbol sym) {return _all.containsKey(sym.name());}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if this set is an (improper) subset of another.
+ * @param other the set we are testing against.
+ */
+ public boolean is_subset_of(symbol_set other) throws internal_error
+ {
+ not_null(other);
+
+ /* walk down our set and make sure every element is in the other */
+ for (Enumeration e = all(); e.hasMoreElements(); )
+ if (!other.contains((symbol)e.nextElement()))
+ return false;
+
+ /* they were all there */
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if this set is an (improper) superset of another.
+ * @param other the set we are are testing against.
+ */
+ public boolean is_superset_of(symbol_set other) throws internal_error
+ {
+ not_null(other);
+ return other.is_subset_of(this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a single symbol to the set.
+ * @param sym the symbol we are adding.
+ * @return true if this changes the set.
+ */
+ public boolean add(symbol sym) throws internal_error
+ {
+ Object previous;
+
+ not_null(sym);
+
+ /* put the object in */
+ previous = _all.put(sym.name(),sym);
+
+ /* if we had a previous, this is no change */
+ return previous == null;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove a single symbol if it is in the set.
+ * @param sym the symbol we are removing.
+ */
+ public void remove(symbol sym) throws internal_error
+ {
+ not_null(sym);
+ _all.remove(sym.name());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add (union) in a complete set.
+ * @param other the set we are adding in.
+ * @return true if this changes the set.
+ */
+ public boolean add(symbol_set other) throws internal_error
+ {
+ boolean result = false;
+
+ not_null(other);
+
+ /* walk down the other set and do the adds individually */
+ for (Enumeration e = other.all(); e.hasMoreElements(); )
+ result = add((symbol)e.nextElement()) || result;
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove (set subtract) a complete set.
+ * @param other the set we are removing.
+ */
+ public void remove(symbol_set other) throws internal_error
+ {
+ not_null(other);
+
+ /* walk down the other set and do the removes individually */
+ for (Enumeration e = other.all(); e.hasMoreElements(); )
+ remove((symbol)e.nextElement());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(symbol_set other)
+ {
+ if (other == null || other.size() != size()) return false;
+
+ /* once we know they are the same size, then improper subset does test */
+ try {
+ return is_subset_of(other);
+ } catch (internal_error e) {
+ /* can't throw the error (because super class doesn't), so we crash */
+ e.crash();
+ return false;
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof symbol_set))
+ return false;
+ else
+ return equals((symbol_set)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute a hash code. */
+ public int hashCode()
+ {
+ int result = 0;
+ int cnt;
+ Enumeration e;
+
+ /* hash together codes from at most first 5 elements */
+ for (e = all(), cnt=0 ; e.hasMoreElements() && cnt<5; cnt++)
+ result ^= ((symbol)e.nextElement()).hashCode();
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+ boolean comma_flag;
+
+ result = "{";
+ comma_flag = false;
+ for (Enumeration e = all(); e.hasMoreElements(); )
+ {
+ if (comma_flag)
+ result += ", ";
+ else
+ comma_flag = true;
+
+ result += ((symbol)e.nextElement()).name();
+ }
+ result += "}";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
+
diff --git a/src/java_cup/java_cup/terminal.java b/src/java_cup/java_cup/terminal.java
new file mode 100644
index 0000000..e1a40aa
--- /dev/null
+++ b/src/java_cup/java_cup/terminal.java
@@ -0,0 +1,169 @@
+package java_cup;
+
+import java_cup.assoc;
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/** This class represents a terminal symbol in the grammar. Each terminal
+ * has a textual name, an index, and a string which indicates the type of
+ * object it will be implemented with at runtime (i.e. the class of object
+ * that will be returned by the scanner and pushed on the parse stack to
+ * represent it).
+ *
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+public class terminal extends symbol {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param nm the name of the terminal.
+ * @param tp the type of the terminal.
+ */
+ public terminal(String nm, String tp, int precedence_side, int precedence_num)
+ {
+ /* superclass does most of the work */
+ super(nm, tp);
+
+ /* add to set of all terminals and check for duplicates */
+ Object conflict = _all.put(nm,this);
+ if (conflict != null)
+ // can't throw an execption here because this is used in static
+ // initializers, so we do a crash instead
+ // was:
+ // throw new internal_error("Duplicate terminal (" + nm + ") created");
+ (new internal_error("Duplicate terminal (" + nm + ") created")).crash();
+
+ /* assign a unique index */
+ _index = next_index++;
+
+ /* set the precedence */
+ _precedence_num = precedence_num;
+ _precedence_side = precedence_side;
+
+ /* add to by_index set */
+ _all_by_index.put(new Integer(_index), this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor for non-precedented terminal
+ */
+
+ public terminal(String nm, String tp)
+ {
+ this(nm, tp, assoc.no_prec, -1);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with default type.
+ * @param nm the name of the terminal.
+ */
+ public terminal(String nm)
+ {
+ this(nm, null);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*------------------- Class Variables ---------------------*/
+ /*-----------------------------------------------------------*/
+
+ private int _precedence_num;
+ private int _precedence_side;
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Table of all terminals. Elements are stored using name strings as
+ * the key
+ */
+ protected static Hashtable _all = new Hashtable();
+
+ /** Access to all terminals. */
+ public static Enumeration all() {return _all.elements();}
+
+ /** Lookup a terminal by name string. */
+ public static terminal find(String with_name)
+ {
+ if (with_name == null)
+ return null;
+ else
+ return (terminal)_all.get(with_name);
+ }
+
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Table of all terminals indexed by their index number. */
+ protected static Hashtable _all_by_index = new Hashtable();
+
+ /** Lookup a terminal by index. */
+ public static terminal find(int indx)
+ {
+ Integer the_indx = new Integer(indx);
+
+ return (terminal)_all_by_index.get(the_indx);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Total number of terminals. */
+ public static int number() {return _all.size();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Static counter to assign unique index. */
+ protected static int next_index = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Special terminal for end of input. */
+ public static final terminal EOF = new terminal("EOF");
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** special terminal used for error recovery */
+ public static final terminal error = new terminal("error");
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Report this symbol as not being a non-terminal. */
+ public boolean is_non_term()
+ {
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ return super.toString() + "[" + index() + "]";
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** get the precedence of a terminal */
+ public int precedence_num() {
+ return _precedence_num;
+ }
+ public int precedence_side() {
+ return _precedence_side;
+ }
+
+ /** set the precedence of a terminal */
+ public void set_precedence(int p, int new_prec) {
+ _precedence_side = p;
+ _precedence_num = new_prec;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/java_cup/java_cup/terminal_set.java b/src/java_cup/java_cup/terminal_set.java
new file mode 100644
index 0000000..e921cb5
--- /dev/null
+++ b/src/java_cup/java_cup/terminal_set.java
@@ -0,0 +1,253 @@
+
+package java_cup;
+
+import java.util.BitSet;
+
+/** A set of terminals implemented as a bitset.
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class terminal_set {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constructor for an empty set. */
+ public terminal_set()
+ {
+ /* allocate the bitset at what is probably the right size */
+ _elements = new BitSet(terminal.number());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor for cloning from another set.
+ * @param other the set we are cloning from.
+ */
+ public terminal_set(terminal_set other)
+ throws internal_error
+ {
+ not_null(other);
+ _elements = (BitSet)other._elements.clone();
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constant for the empty set. */
+ public static final terminal_set EMPTY = new terminal_set();
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Bitset to implement the actual set. */
+ protected BitSet _elements;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Helper function to test for a null object and throw an exception if
+ * one is found.
+ * @param obj the object we are testing.
+ */
+ protected void not_null(Object obj) throws internal_error
+ {
+ if (obj == null)
+ throw new internal_error("Null object used in set operation");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if the set is empty. */
+ public boolean empty()
+ {
+ return equals(EMPTY);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if the set contains a particular terminal.
+ * @param sym the terminal symbol we are looking for.
+ */
+ public boolean contains(terminal sym)
+ throws internal_error
+ {
+ not_null(sym);
+ return _elements.get(sym.index());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Given its index determine if the set contains a particular terminal.
+ * @param indx the index of the terminal in question.
+ */
+ public boolean contains(int indx)
+ {
+ return _elements.get(indx);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if this set is an (improper) subset of another.
+ * @param other the set we are testing against.
+ */
+ public boolean is_subset_of(terminal_set other)
+ throws internal_error
+ {
+ not_null(other);
+
+ /* make a copy of the other set */
+ BitSet copy_other = (BitSet)other._elements.clone();
+
+ /* and or in */
+ copy_other.or(_elements);
+
+ /* if it hasn't changed, we were a subset */
+ return copy_other.equals(other._elements);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if this set is an (improper) superset of another.
+ * @param other the set we are testing against.
+ */
+ public boolean is_superset_of(terminal_set other)
+ throws internal_error
+ {
+ not_null(other);
+ return other.is_subset_of(this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a single terminal to the set.
+ * @param sym the terminal being added.
+ * @return true if this changes the set.
+ */
+ public boolean add(terminal sym)
+ throws internal_error
+ {
+ boolean result;
+
+ not_null(sym);
+
+ /* see if we already have this */
+ result = _elements.get(sym.index());
+
+ /* if not we add it */
+ if (!result)
+ _elements.set(sym.index());
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove a terminal if it is in the set.
+ * @param sym the terminal being removed.
+ */
+ public void remove(terminal sym)
+ throws internal_error
+ {
+ not_null(sym);
+ _elements.clear(sym.index());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add (union) in a complete set.
+ * @param other the set being added.
+ * @return true if this changes the set.
+ */
+ public boolean add(terminal_set other)
+ throws internal_error
+ {
+ not_null(other);
+
+ /* make a copy */
+ BitSet copy = (BitSet)_elements.clone();
+
+ /* or in the other set */
+ _elements.or(other._elements);
+
+ /* changed if we are not the same as the copy */
+ return !_elements.equals(copy);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if this set intersects another.
+ * @param other the other set in question.
+ */
+ public boolean intersects(terminal_set other)
+ throws internal_error
+ {
+ not_null(other);
+
+ /* make a copy of the other set */
+ BitSet copy = (BitSet)other._elements.clone();
+
+ /* xor out our values */
+ copy.xor(this._elements);
+
+ /* see if its different */
+ return !copy.equals(other._elements);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(terminal_set other)
+ {
+ if (other == null)
+ return false;
+ else
+ return _elements.equals(other._elements);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof terminal_set))
+ return false;
+ else
+ return equals((terminal_set)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to string. */
+ public String toString()
+ {
+ String result;
+ boolean comma_flag;
+
+ result = "{";
+ comma_flag = false;
+ for (int t = 0; t < terminal.number(); t++)
+ {
+ if (_elements.get(t))
+ {
+ if (comma_flag)
+ result += ", ";
+ else
+ comma_flag = true;
+
+ result += terminal.find(t).name();
+ }
+ }
+ result += "}";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
diff --git a/src/java_cup/java_cup/version.java b/src/java_cup/java_cup/version.java
new file mode 100644
index 0000000..06600b5
--- /dev/null
+++ b/src/java_cup/java_cup/version.java
@@ -0,0 +1,55 @@
+
+package java_cup;
+
+/** This class contains version and authorship information.
+ * It contains only static data elements and basically just a central
+ * place to put this kind of information so it can be updated easily
+ * for each release.
+ *
+ * Version numbers used here are broken into 3 parts: major, minor, and
+ * update, and are written as v<major>.<minor>.<update> (e.g. v0.10a).
+ * Major numbers will change at the time of major reworking of some
+ * part of the system. Minor numbers for each public release or
+ * change big enough to cause incompatibilities. Finally update
+ * letter will be incremented for small bug fixes and changes that
+ * probably wouldn't be noticed by a user.
+ *
+ * @version last updated: 12/22/97 [CSA]
+ * @author Frank Flannery
+ */
+
+public class version {
+ /** The major version number. */
+ public static final int major = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The minor version number. */
+ public static final int minor = 10;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The update letter. */
+ public static final char update = 'k';
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** String for the current version. */
+ public static final String version_str = "v" + major + "." + minor + update;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Full title of the system */
+ public static final String title_str = "CUP " + version_str;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Name of the author */
+ public static final String author_str =
+ "Scott E. Hudson, Frank Flannery, and C. Scott Ananian";
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The command name normally used to invoke this program */
+ public static final String program_name = "java_cup";
+}
diff --git a/src/java_cup/parser.cup b/src/java_cup/parser.cup
new file mode 100644
index 0000000..8af0d05
--- /dev/null
+++ b/src/java_cup/parser.cup
@@ -0,0 +1,863 @@
+
+/*================================================================*/
+/*
+ JavaCup Specification for the JavaCup Specification Language
+ by Scott Hudson, GVU Center, Georgia Tech, August 1995
+ and Frank Flannery, Department of Computer Science, Princeton Univ,
+ July 1996
+ Bug Fixes: C. Scott Ananian, Dept of Electrical Engineering, Princeton
+ University, October 1996. [later Massachusetts Institute of Technology]
+
+
+ This JavaCup specification is used to implement JavaCup itself.
+ It specifies the parser for the JavaCup specification language.
+ (It also serves as a reasonable example of what a typical JavaCup
+ spec looks like).
+
+ The specification has the following parts:
+ Package and import declarations
+ These serve the same purpose as in a normal Java source file
+ (and will appear in the generated code for the parser). In this
+ case we are part of the java_cup package and we import both the
+ java_cup runtime system and Hashtable from the standard Java
+ utilities package.
+
+ Action code
+ This section provides code that is included with the class encapsulating
+ the various pieces of user code embedded in the grammar (i.e., the
+ semantic actions). This provides a series of helper routines and
+ data structures that the semantic actions use.
+
+ Parser code
+ This section provides code included in the parser class itself. In
+ this case we override the default error reporting routines.
+
+ Init with and scan with
+ These sections provide small bits of code that initialize, then
+ indicate how to invoke the scanner.
+
+ Symbols and grammar
+ These sections declare all the terminal and non terminal symbols
+ and the types of objects that they will be represented by at runtime,
+ then indicate the start symbol of the grammar (), and finally provide
+ the grammar itself (with embedded actions).
+
+ Operation of the parser
+ The parser acts primarily by accumulating data structures representing
+ various parts of the specification. Various small parts (e.g., single
+ code strings) are stored as static variables of the emit class and
+ in a few cases as variables declared in the action code section.
+ Terminals, non terminals, and productions, are maintained as collection
+ accessible via static methods of those classes. In addition, two
+ symbol tables are kept:
+ symbols maintains the name to object mapping for all symbols
+ non_terms maintains a separate mapping containing only the non terms
+
+ Several intermediate working structures are also declared in the action
+ code section. These include: rhs_parts, rhs_pos, and lhs_nt which
+ build up parts of the current production while it is being parsed.
+
+ Author(s)
+ Scott Hudson, GVU Center, Georgia Tech.
+ Frank Flannery, Department of Computer Science, Princeton Univ.
+ C. Scott Ananian, Department of Electrical Engineering, Princeton Univ.
+
+ Revisions
+ v0.9a First released version [SEH] 8/29/95
+ v0.9b Updated for beta language (throws clauses) [SEH] 11/25/95
+ v0.10a Made many improvements/changes. now offers:
+ return value
+ left/right positions and propagations
+ cleaner label references
+ precedence and associativity for terminals
+ contextual precedence for productions
+ [FF] 7/3/96
+ v0.10b Fixed %prec directive so it works like it's supposed to.
+ [CSA] 10/10/96
+ v0.10g Added support for array types on symbols.
+ [CSA] 03/23/98
+ v0.10i Broaden set of IDs allowed in multipart_id and label_id so
+ that only java reserved words (and not CUP reserved words like
+ 'parser' and 'start') are prohibited. Allow reordering of
+ action code, parser code, init code, and scan with sections,
+ and made closing semicolon optional for these sections.
+ Added 'nonterminal' as a terminal symbol, finally fixing a
+ spelling mistake that's been around since the beginning.
+ For backwards compatibility, you can still misspell the
+ word if you like.
+*/
+/*================================================================*/
+
+package java_cup;
+import java_cup.runtime.*;
+import java.util.Hashtable;
+
+/*----------------------------------------------------------------*/
+
+action code {:
+ /** helper routine to clone a new production part adding a given label */
+ protected production_part add_lab(production_part part, String lab)
+ throws internal_error
+ {
+ /* if there is no label, or this is an action, just return the original */
+ if (lab == null || part.is_action()) return part;
+
+ /* otherwise build a new one with the given label attached */
+ return new symbol_part(((symbol_part)part).the_symbol(),lab);
+ }
+
+ /** max size of right hand side we will support */
+ protected final int MAX_RHS = 200;
+
+ /** array for accumulating right hand side parts */
+ protected production_part[] rhs_parts = new production_part[MAX_RHS];
+
+ /** where we are currently in building a right hand side */
+ protected int rhs_pos = 0;
+
+ /** start a new right hand side */
+ protected void new_rhs() {rhs_pos = 0; }
+
+ /** add a new right hand side part */
+ protected void add_rhs_part(production_part part) throws java.lang.Exception
+ {
+ if (rhs_pos >= MAX_RHS)
+ throw new Exception("Internal Error: Productions limited to " +
+ MAX_RHS + " symbols and actions");
+
+ rhs_parts[rhs_pos] = part;
+ rhs_pos++;
+ }
+
+ /** string to build up multiple part names */
+ protected String multipart_name = new String();
+
+ /** append a new name segment to the accumulated multipart name */
+ protected void append_multipart(String name)
+ {
+ String dot = "";
+
+ /* if we aren't just starting out, put on a dot */
+ if (multipart_name.length() != 0) dot = ".";
+
+ multipart_name = multipart_name.concat(dot + name);
+ }
+
+ /** table of declared symbols -- contains production parts indexed by name */
+ protected Hashtable symbols = new Hashtable();
+
+ /** table of just non terminals -- contains non_terminals indexed by name */
+ protected Hashtable non_terms = new Hashtable();
+
+ /** declared start non_terminal */
+ protected non_terminal start_nt = null;
+
+ /** left hand side non terminal of the current production */
+ protected non_terminal lhs_nt;
+
+ /** Current precedence number */
+ int _cur_prec = 0;
+
+ /** Current precedence side */
+ int _cur_side = assoc.no_prec;
+
+ /** update the precedences we are declaring */
+ protected void update_precedence(int p) {
+ _cur_side = p;
+ _cur_prec++;
+ }
+ /** add relevant data to terminals */
+ protected void add_precedence(String term) {
+ if (term == null) {
+ System.err.println("Unable to add precedence to nonexistent terminal");
+ } else {
+ symbol_part sp = (symbol_part)symbols.get(term);
+ if (sp == null) {
+ System.err.println("Could find terminal " + term + " while declaring precedence");
+ } else {
+ java_cup.symbol sym = sp.the_symbol();
+ if (sym instanceof terminal)
+ ((terminal)sym).set_precedence(_cur_side, _cur_prec);
+ else System.err.println("Precedence declaration: Can't find terminal " + term);
+ }
+ }
+ }
+:};
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+parser code {:
+
+ /* override error routines */
+
+ public void report_fatal_error(
+ String message,
+ Object info)
+ {
+ done_parsing();
+ lexer.emit_error(message);
+ System.err.println("Can't recover from previous error(s), giving up.");
+ System.exit(1);
+ }
+
+ public void report_error(String message, Object info)
+ {
+ lexer.emit_error(message);
+ }
+:};
+
+/*----------------------------------------------------------------*/
+
+init with {: lexer.init(); :};
+scan with {: return lexer.next_token(); :};
+
+/*----------------------------------------------------------------*/
+
+terminal
+ PACKAGE, IMPORT, CODE, ACTION, PARSER, TERMINAL, NON, INIT, SCAN, WITH,
+ START, SEMI, COMMA, STAR, DOT, COLON, COLON_COLON_EQUALS, BAR, PRECEDENCE,
+ LEFT, RIGHT, NONASSOC, PERCENT_PREC, LBRACK, RBRACK, NONTERMINAL;
+
+terminal String ID, CODE_STRING;
+
+non terminal
+ spec, package_spec, import_list, action_code_part,
+ code_parts, code_part, opt_semi, non_terminal,
+ parser_code_part, symbol_list, start_spec, production_list,
+ multipart_id, import_spec, import_id, init_code, scan_code, symbol,
+ type_id, term_name_list, non_term_name_list, production, prod_part_list,
+ prod_part, new_term_id, new_non_term_id, rhs_list, rhs, empty,
+ precedence_list, preced, terminal_list, precedence_l, declares_term,
+ declares_non_term;
+
+non terminal String nt_id, symbol_id, label_id, opt_label, terminal_id,
+ term_id, robust_id;
+
+/*----------------------------------------------------------------*/
+
+start with spec;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+spec ::=
+ {:
+ /* declare "error" as a terminal */
+ symbols.put("error", new symbol_part(terminal.error));
+
+ /* declare start non terminal */
+ non_terms.put("$START", non_terminal.START_nt);
+ :}
+ package_spec
+ import_list
+ code_parts
+ symbol_list
+ precedence_list
+ start_spec
+ production_list
+ |
+ /* error recovery assuming something went wrong before symbols
+ and we have TERMINAL or NON TERMINAL to sync on. if we get
+ an error after that, we recover inside symbol_list or
+ production_list
+ */
+ error
+ symbol_list
+ precedence_list
+ start_spec
+ production_list
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+package_spec ::=
+ PACKAGE
+ multipart_id
+ {:
+ /* save the package name */
+ emit.package_name = multipart_name;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+import_list ::=
+ import_list
+ import_spec
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+import_spec ::=
+ IMPORT
+ import_id
+ {:
+ /* save this import on the imports list */
+ emit.import_list.push(multipart_name);
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+// allow any order; all parts are optional. [CSA, 23-Jul-1999]
+// (we check in the part action to make sure we don't have 2 of any part)
+code_part ::=
+ action_code_part | parser_code_part | init_code | scan_code ;
+code_parts ::=
+ | code_parts code_part;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+action_code_part ::=
+ ACTION CODE CODE_STRING:user_code opt_semi
+ {:
+ if (emit.action_code!=null)
+ lexer.emit_error("Redundant action code (skipping)");
+ else /* save the user included code string */
+ emit.action_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+parser_code_part ::=
+ PARSER CODE CODE_STRING:user_code opt_semi
+ {:
+ if (emit.parser_code!=null)
+ lexer.emit_error("Redundant parser code (skipping)");
+ else /* save the user included code string */
+ emit.parser_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+init_code ::=
+ INIT WITH CODE_STRING:user_code opt_semi
+ {:
+ if (emit.init_code!=null)
+ lexer.emit_error("Redundant init code (skipping)");
+ else /* save the user code */
+ emit.init_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+scan_code ::=
+ SCAN WITH CODE_STRING:user_code opt_semi
+ {:
+ if (emit.scan_code!=null)
+ lexer.emit_error("Redundant scan code (skipping)");
+ else /* save the user code */
+ emit.scan_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+symbol_list ::= symbol_list symbol | symbol;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+symbol ::=
+ TERMINAL
+ type_id
+ declares_term
+ |
+ TERMINAL
+ declares_term
+ |
+ non_terminal
+ type_id
+ declares_non_term
+ |
+ non_terminal
+ declares_non_term
+ |
+ /* error recovery productions -- sync on semicolon */
+
+ TERMINAL
+ error
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ |
+ non_terminal
+ error
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+declares_term ::=
+ term_name_list
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+declares_non_term ::=
+ non_term_name_list
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+term_name_list ::= term_name_list COMMA new_term_id | new_term_id;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+non_term_name_list ::=
+ non_term_name_list
+ COMMA
+ new_non_term_id
+ |
+ new_non_term_id
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+
+precedence_list ::= precedence_l | empty;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+precedence_l ::= precedence_l preced | preced;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+preced ::=
+ PRECEDENCE LEFT
+ {:
+ update_precedence(assoc.left);
+ :}
+ terminal_list SEMI
+ |
+ PRECEDENCE RIGHT
+ {:
+ update_precedence(assoc.right);
+ :}
+ terminal_list SEMI
+ |
+ PRECEDENCE NONASSOC
+ {:
+ update_precedence(assoc.nonassoc);
+ :}
+ terminal_list SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+terminal_list ::= terminal_list COMMA terminal_id
+ |
+ terminal_id
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+terminal_id ::= term_id:sym
+ {:
+ add_precedence(sym);
+ RESULT = sym;
+ :};
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+term_id ::= symbol_id:sym
+ {:
+ /* check that the symbol_id is a terminal */
+ if (symbols.get(sym) == null)
+ {
+ /* issue a message */
+ lexer.emit_error("Terminal \"" + sym +
+ "\" has not been declared");
+ }
+ RESULT = sym;
+ :};
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+start_spec ::=
+ START WITH nt_id:start_name
+ {:
+ /* verify that the name has been declared as a non terminal */
+ non_terminal nt = (non_terminal)non_terms.get(start_name);
+ if (nt == null)
+ {
+ lexer.emit_error( "Start non terminal \"" + start_name +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* remember the non-terminal for later */
+ start_nt = nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt), "start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+ new_rhs();
+ }
+ :}
+ SEMI
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+production_list ::= production_list production | production;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+production ::=
+ nt_id:lhs_id
+ {:
+ /* lookup the lhs nt */
+ lhs_nt = (non_terminal)non_terms.get(lhs_id);
+
+ /* if it wasn't declared, emit a message */
+ if (lhs_nt == null)
+ {
+ if (lexer.error_count == 0)
+ lexer.emit_error("LHS non terminal \"" + lhs_id +
+ "\" has not been declared");
+ }
+
+ /* reset the rhs accumulation */
+ new_rhs();
+ :}
+ COLON_COLON_EQUALS
+ {: :}
+ rhs_list
+ SEMI
+ |
+ error
+ {: lexer.emit_error("Syntax Error"); :}
+ SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+rhs_list ::= rhs_list BAR rhs | rhs;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+rhs ::=
+ prod_part_list PERCENT_PREC term_id:term_name
+ {:
+ java_cup.symbol sym = null;
+ if (lhs_nt != null)
+ {
+ /* Find the precedence symbol */
+ if (term_name == null) {
+ System.err.println("No terminal for contextual precedence");
+ sym = null;
+ } else {
+ sym = ((symbol_part)symbols.get(term_name)).the_symbol();
+ }
+ /* build the production */
+ production p;
+ if ((sym!=null) && (sym instanceof terminal)) {
+ p = new production(lhs_nt, rhs_parts, rhs_pos,
+ ((terminal)sym).precedence_num(),
+ ((terminal)sym).precedence_side());
+ ((symbol_part)symbols.get(term_name)).the_symbol().note_use();
+ } else {
+ System.err.println("Invalid terminal " + term_name +
+ " for contextual precedence assignment");
+ p = new production(lhs_nt, rhs_parts, rhs_pos);
+ }
+
+ /* if we have no start non-terminal declared and this is
+ the first production, make its lhs nt the start_nt
+ and build a special start production for it. */
+ if (start_nt == null)
+ {
+ start_nt = lhs_nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt),"start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ if ((sym!=null) && (sym instanceof terminal)) {
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts,
+ rhs_pos, ((terminal)sym).precedence_num(),
+ ((terminal)sym).precedence_side());
+ } else {
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+ }
+ new_rhs();
+ }
+ }
+
+ /* reset the rhs accumulation in any case */
+ new_rhs();
+ :}
+ |
+ prod_part_list
+ {:
+ if (lhs_nt != null)
+ {
+ /* build the production */
+ production p = new production(lhs_nt, rhs_parts, rhs_pos);
+
+ /* if we have no start non-terminal declared and this is
+ the first production, make its lhs nt the start_nt
+ and build a special start production for it. */
+ if (start_nt == null)
+ {
+ start_nt = lhs_nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt),"start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+
+ new_rhs();
+ }
+ }
+
+ /* reset the rhs accumulation in any case */
+ new_rhs();
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+prod_part_list ::= prod_part_list prod_part | empty;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+prod_part ::=
+ symbol_id:symid opt_label:labid
+ {:
+ /* try to look up the id */
+ production_part symb = (production_part)symbols.get(symid);
+
+ /* if that fails, symbol is undeclared */
+ if (symb == null)
+ {
+ if (lexer.error_count == 0)
+ lexer.emit_error("java_cup.runtime.Symbol \"" + symid +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* add a labeled production part */
+ add_rhs_part(add_lab(symb, labid));
+ }
+ :}
+ |
+ CODE_STRING:code_str
+ {:
+ /* add a new production part */
+ add_rhs_part(new action_part(code_str));
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+opt_label ::=
+ COLON label_id:labid
+ {: RESULT = labid; :}
+ |
+ empty
+ {: RESULT = null; :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+multipart_id ::=
+ multipart_id DOT robust_id:another_id
+ {: append_multipart(another_id); :}
+ |
+ robust_id:an_id
+ {: append_multipart(an_id); :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+import_id ::=
+ multipart_id DOT STAR
+ {: append_multipart("*"); :}
+ |
+ multipart_id
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+type_id ::= multipart_id
+ | type_id LBRACK RBRACK
+ {: multipart_name = multipart_name.concat("[]"); :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+new_term_id ::=
+ ID:term_id
+ {:
+ /* see if this terminal has been declared before */
+ if (symbols.get(term_id) != null)
+ {
+ /* issue a message */
+ lexer.emit_error("java_cup.runtime.Symbol \"" + term_id +
+ "\" has already been declared");
+ }
+ else
+ {
+ /* if no type declared, declare one */
+ if (multipart_name.equals("")) {
+ append_multipart("Object");
+ }
+ /* build a production_part and put it in the table */
+ symbols.put(term_id,
+ new symbol_part(new terminal(term_id, multipart_name)));
+ }
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+new_non_term_id ::=
+ ID:non_term_id
+ {:
+ /* see if this non terminal has been declared before */
+ if (symbols.get(non_term_id) != null)
+ {
+ /* issue a message */
+ lexer.emit_error( "java_cup.runtime.Symbol \"" + non_term_id +
+ "\" has already been declared");
+ }
+ else
+ {
+ if (multipart_name.equals("")) {
+ append_multipart("Object");
+ }
+ /* build the non terminal object */
+ non_terminal this_nt =
+ new non_terminal(non_term_id, multipart_name);
+
+ /* put it in the non_terms table */
+ non_terms.put(non_term_id, this_nt);
+
+ /* build a production_part and put it in the symbols table */
+ symbols.put(non_term_id, new symbol_part(this_nt));
+ }
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+nt_id ::=
+ ID:the_id
+ {: RESULT = the_id; :}
+ | error
+ {:
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+symbol_id ::=
+ ID:the_id
+ {: RESULT = the_id; :}
+ | error
+ {:
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+label_id ::=
+ robust_id:the_id
+ {: RESULT = the_id; :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+robust_id ::= /* all ids that aren't reserved words in Java */
+ ID:the_id {: RESULT = the_id; :}
+ /* package is reserved. */
+ /* import is reserved. */
+ | CODE {: RESULT = "code"; :}
+ | ACTION {: RESULT = "action"; :}
+ | PARSER {: RESULT = "parser"; :}
+ | TERMINAL {: RESULT = "terminal"; :}
+ | NON {: RESULT = "non"; :}
+ | NONTERMINAL {: RESULT = "nonterminal"; :}
+ | INIT {: RESULT = "init"; :}
+ | SCAN {: RESULT = "scan"; :}
+ | WITH {: RESULT = "with"; :}
+ | START {: RESULT = "start"; :}
+ | PRECEDENCE {: RESULT = "precedence"; :}
+ | LEFT {: RESULT = "left"; :}
+ | RIGHT {: RESULT = "right"; :}
+ | NONASSOC {: RESULT = "nonassoc"; :}
+ | error
+ {:
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+non_terminal ::= NON TERMINAL | NONTERMINAL;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+opt_semi ::= /* nothing */
+ | SEMI;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+empty ::= /* nothing */;
+
+/*----------------------------------------------------------------*/
+
+
+
+
+
+
+
+
+
diff --git a/src/java_cup/runtime/Scanner.class b/src/java_cup/runtime/Scanner.class
new file mode 100644
index 0000000..60df2f1
--- /dev/null
+++ b/src/java_cup/runtime/Scanner.class
Binary files differ
diff --git a/src/java_cup/runtime/Scanner.java b/src/java_cup/runtime/Scanner.java
new file mode 100644
index 0000000..3233551
--- /dev/null
+++ b/src/java_cup/runtime/Scanner.java
@@ -0,0 +1,25 @@
+package java_cup.runtime;
+
+/**
+ * Defines the Scanner interface, which CUP uses in the default
+ * implementation of <code>lr_parser.scan()</code>. Integration
+ * of scanners implementing <code>Scanner</code> is facilitated.
+ *
+ * @version last updated 23-Jul-1999
+ * @author David MacMahon <davidm@smartsc.com>
+ */
+
+/* *************************************************
+ Interface Scanner
+
+ Declares the next_token() method that should be
+ implemented by scanners. This method is typically
+ called by lr_parser.scan(). End-of-file can be
+ indicated either by returning
+ <code>new Symbol(lr_parser.EOF_sym())</code> or
+ <code>null</code>.
+ ***************************************************/
+public interface Scanner {
+ /** Return the next token, or <code>null</code> on end-of-file. */
+ public Symbol next_token() throws java.lang.Exception;
+}
diff --git a/src/java_cup/runtime/Symbol.class b/src/java_cup/runtime/Symbol.class
new file mode 100644
index 0000000..0d96da9
--- /dev/null
+++ b/src/java_cup/runtime/Symbol.class
Binary files differ
diff --git a/src/java_cup/runtime/Symbol.java b/src/java_cup/runtime/Symbol.java
new file mode 100644
index 0000000..eeb6a0b
--- /dev/null
+++ b/src/java_cup/runtime/Symbol.java
@@ -0,0 +1,105 @@
+package java_cup.runtime;
+
+/**
+ * Defines the Symbol class, which is used to represent all terminals
+ * and nonterminals while parsing. The lexer should pass CUP Symbols
+ * and CUP returns a Symbol.
+ *
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+
+/* ****************************************************************
+ Class Symbol
+ what the parser expects to receive from the lexer.
+ the token is identified as follows:
+ sym: the symbol type
+ parse_state: the parse state.
+ value: is the lexical value of type Object
+ left : is the left position in the original input file
+ right: is the right position in the original input file
+******************************************************************/
+
+public class Symbol {
+
+/*******************************
+ Constructor for l,r values
+ *******************************/
+
+ public Symbol(int id, int l, int r, Object o) {
+ this(id);
+ left = l;
+ right = r;
+ value = o;
+ }
+
+/*******************************
+ Constructor for no l,r values
+********************************/
+
+ public Symbol(int id, Object o) {
+ this(id, -1, -1, o);
+ }
+
+/*****************************
+ Constructor for no value
+ ***************************/
+
+ public Symbol(int id, int l, int r) {
+ this(id, l, r, null);
+ }
+
+/***********************************
+ Constructor for no value or l,r
+***********************************/
+
+ public Symbol(int sym_num) {
+ this(sym_num, -1);
+ left = -1;
+ right = -1;
+ value = null;
+ }
+
+/***********************************
+ Constructor to give a start state
+***********************************/
+ Symbol(int sym_num, int state)
+ {
+ sym = sym_num;
+ parse_state = state;
+ }
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The symbol number of the terminal or non terminal being represented */
+ public int sym;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The parse state to be recorded on the parse stack with this symbol.
+ * This field is for the convenience of the parser and shouldn't be
+ * modified except by the parser.
+ */
+ public int parse_state;
+ /** This allows us to catch some errors caused by scanners recycling
+ * symbols. For the use of the parser only. [CSA, 23-Jul-1999] */
+ boolean used_by_parser = false;
+
+/*******************************
+ The data passed to parser
+ *******************************/
+
+ public int left, right;
+ public Object value;
+
+ /*****************************
+ Printing this token out. (Override for pretty-print).
+ ****************************/
+ public String toString() { return "#"+sym; }
+}
+
+
+
+
+
+
diff --git a/src/java_cup/runtime/lr_parser.class b/src/java_cup/runtime/lr_parser.class
new file mode 100644
index 0000000..521178b
--- /dev/null
+++ b/src/java_cup/runtime/lr_parser.class
Binary files differ
diff --git a/src/java_cup/runtime/lr_parser.java b/src/java_cup/runtime/lr_parser.java
new file mode 100644
index 0000000..3c8335c
--- /dev/null
+++ b/src/java_cup/runtime/lr_parser.java
@@ -0,0 +1,1238 @@
+
+package java_cup.runtime;
+
+import java.util.Stack;
+
+/** This class implements a skeleton table driven LR parser. In general,
+ * LR parsers are a form of bottom up shift-reduce parsers. Shift-reduce
+ * parsers act by shifting input onto a parse stack until the Symbols
+ * matching the right hand side of a production appear on the top of the
+ * stack. Once this occurs, a reduce is performed. This involves removing
+ * the Symbols corresponding to the right hand side of the production
+ * (the so called "handle") and replacing them with the non-terminal from
+ * the left hand side of the production. <p>
+ *
+ * To control the decision of whether to shift or reduce at any given point,
+ * the parser uses a state machine (the "viable prefix recognition machine"
+ * built by the parser generator). The current state of the machine is placed
+ * on top of the parse stack (stored as part of a Symbol object representing
+ * a terminal or non terminal). The parse action table is consulted
+ * (using the current state and the current lookahead Symbol as indexes) to
+ * determine whether to shift or to reduce. When the parser shifts, it
+ * changes to a new state by pushing a new Symbol (containing a new state)
+ * onto the stack. When the parser reduces, it pops the handle (right hand
+ * side of a production) off the stack. This leaves the parser in the state
+ * it was in before any of those Symbols were matched. Next the reduce-goto
+ * table is consulted (using the new state and current lookahead Symbol as
+ * indexes) to determine a new state to go to. The parser then shifts to
+ * this goto state by pushing the left hand side Symbol of the production
+ * (also containing the new state) onto the stack.<p>
+ *
+ * This class actually provides four LR parsers. The methods parse() and
+ * debug_parse() provide two versions of the main parser (the only difference
+ * being that debug_parse() emits debugging trace messages as it parses).
+ * In addition to these main parsers, the error recovery mechanism uses two
+ * more. One of these is used to simulate "parsing ahead" in the input
+ * without carrying out actions (to verify that a potential error recovery
+ * has worked), and the other is used to parse through buffered "parse ahead"
+ * input in order to execute all actions and re-synchronize the actual parser
+ * configuration.<p>
+ *
+ * This is an abstract class which is normally filled out by a subclass
+ * generated by the JavaCup parser generator. In addition to supplying
+ * the actual parse tables, generated code also supplies methods which
+ * invoke various pieces of user supplied code, provide access to certain
+ * special Symbols (e.g., EOF and error), etc. Specifically, the following
+ * abstract methods are normally supplied by generated code:
+ * <dl compact>
+ * <dt> short[][] production_table()
+ * <dd> Provides a reference to the production table (indicating the index of
+ * the left hand side non terminal and the length of the right hand side
+ * for each production in the grammar).
+ * <dt> short[][] action_table()
+ * <dd> Provides a reference to the parse action table.
+ * <dt> short[][] reduce_table()
+ * <dd> Provides a reference to the reduce-goto table.
+ * <dt> int start_state()
+ * <dd> Indicates the index of the start state.
+ * <dt> int start_production()
+ * <dd> Indicates the index of the starting production.
+ * <dt> int EOF_sym()
+ * <dd> Indicates the index of the EOF Symbol.
+ * <dt> int error_sym()
+ * <dd> Indicates the index of the error Symbol.
+ * <dt> Symbol do_action()
+ * <dd> Executes a piece of user supplied action code. This always comes at
+ * the point of a reduce in the parse, so this code also allocates and
+ * fills in the left hand side non terminal Symbol object that is to be
+ * pushed onto the stack for the reduce.
+ * <dt> void init_actions()
+ * <dd> Code to initialize a special object that encapsulates user supplied
+ * actions (this object is used by do_action() to actually carry out the
+ * actions).
+ * </dl>
+ *
+ * In addition to these routines that <i>must</i> be supplied by the
+ * generated subclass there are also a series of routines that <i>may</i>
+ * be supplied. These include:
+ * <dl>
+ * <dt> Symbol scan()
+ * <dd> Used to get the next input Symbol from the scanner.
+ * <dt> Scanner getScanner()
+ * <dd> Used to provide a scanner for the default implementation of
+ * scan().
+ * <dt> int error_sync_size()
+ * <dd> This determines how many Symbols past the point of an error
+ * must be parsed without error in order to consider a recovery to
+ * be valid. This defaults to 3. Values less than 2 are not
+ * recommended.
+ * <dt> void report_error(String message, Object info)
+ * <dd> This method is called to report an error. The default implementation
+ * simply prints a message to System.err and where the error occurred.
+ * This method is often replaced in order to provide a more sophisticated
+ * error reporting mechanism.
+ * <dt> void report_fatal_error(String message, Object info)
+ * <dd> This method is called when a fatal error that cannot be recovered from
+ * is encountered. In the default implementation, it calls
+ * report_error() to emit a message, then throws an exception.
+ * <dt> void syntax_error(Symbol cur_token)
+ * <dd> This method is called as soon as syntax error is detected (but
+ * before recovery is attempted). In the default implementation it
+ * invokes: report_error("Syntax error", null);
+ * <dt> void unrecovered_syntax_error(Symbol cur_token)
+ * <dd> This method is called if syntax error recovery fails. In the default
+ * implementation it invokes:<br>
+ * report_fatal_error("Couldn't repair and continue parse", null);
+ * </dl>
+ *
+ * @see java_cup.runtime.Symbol
+ * @see java_cup.runtime.Symbol
+ * @see java_cup.runtime.virtual_parse_stack
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+
+public abstract class lr_parser {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. */
+ public lr_parser()
+ {
+ /* nothing to do here */
+ }
+
+ /** Constructor that sets the default scanner. [CSA/davidm] */
+ public lr_parser(Scanner s) {
+ this(); /* in case default constructor someday does something */
+ setScanner(s);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The default number of Symbols after an error we much match to consider
+ * it recovered from.
+ */
+ protected final static int _error_sync_size = 3;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The number of Symbols after an error we much match to consider it
+ * recovered from.
+ */
+ protected int error_sync_size() {return _error_sync_size; }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Table of production information (supplied by generated subclass).
+ * This table contains one entry per production and is indexed by
+ * the negative-encoded values (reduce actions) in the action_table.
+ * Each entry has two parts, the index of the non-terminal on the
+ * left hand side of the production, and the number of Symbols
+ * on the right hand side.
+ */
+ public abstract short[][] production_table();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The action table (supplied by generated subclass). This table is
+ * indexed by state and terminal number indicating what action is to
+ * be taken when the parser is in the given state (i.e., the given state
+ * is on top of the stack) and the given terminal is next on the input.
+ * States are indexed using the first dimension, however, the entries for
+ * a given state are compacted and stored in adjacent index, value pairs
+ * which are searched for rather than accessed directly (see get_action()).
+ * The actions stored in the table will be either shifts, reduces, or
+ * errors. Shifts are encoded as positive values (one greater than the
+ * state shifted to). Reduces are encoded as negative values (one less
+ * than the production reduced by). Error entries are denoted by zero.
+ *
+ * @see java_cup.runtime.lr_parser#get_action
+ */
+ public abstract short[][] action_table();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The reduce-goto table (supplied by generated subclass). This
+ * table is indexed by state and non-terminal number and contains
+ * state numbers. States are indexed using the first dimension, however,
+ * the entries for a given state are compacted and stored in adjacent
+ * index, value pairs which are searched for rather than accessed
+ * directly (see get_reduce()). When a reduce occurs, the handle
+ * (corresponding to the RHS of the matched production) is popped off
+ * the stack. The new top of stack indicates a state. This table is
+ * then indexed by that state and the LHS of the reducing production to
+ * indicate where to "shift" to.
+ *
+ * @see java_cup.runtime.lr_parser#get_reduce
+ */
+ public abstract short[][] reduce_table();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The index of the start state (supplied by generated subclass). */
+ public abstract int start_state();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The index of the start production (supplied by generated subclass). */
+ public abstract int start_production();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The index of the end of file terminal Symbol (supplied by generated
+ * subclass).
+ */
+ public abstract int EOF_sym();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The index of the special error Symbol (supplied by generated subclass). */
+ public abstract int error_sym();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Internal flag to indicate when parser should quit. */
+ protected boolean _done_parsing = false;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** This method is called to indicate that the parser should quit. This is
+ * normally called by an accept action, but can be used to cancel parsing
+ * early in other circumstances if desired.
+ */
+ public void done_parsing()
+ {
+ _done_parsing = true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+ /* Global parse state shared by parse(), error recovery, and
+ * debugging routines */
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Indication of the index for top of stack (for use by actions). */
+ protected int tos;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The current lookahead Symbol. */
+ protected Symbol cur_token;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The parse stack itself. */
+ protected Stack stack = new Stack();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Direct reference to the production table. */
+ protected short[][] production_tab;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Direct reference to the action table. */
+ protected short[][] action_tab;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Direct reference to the reduce-goto table. */
+ protected short[][] reduce_tab;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** This is the scanner object used by the default implementation
+ * of scan() to get Symbols. To avoid name conflicts with existing
+ * code, this field is private. [CSA/davidm] */
+ private Scanner _scanner;
+
+ /**
+ * Simple accessor method to set the default scanner.
+ */
+ public void setScanner(Scanner s) { _scanner = s; }
+
+ /**
+ * Simple accessor method to get the default scanner.
+ */
+ public Scanner getScanner() { return _scanner; }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Perform a bit of user supplied action code (supplied by generated
+ * subclass). Actions are indexed by an internal action number assigned
+ * at parser generation time.
+ *
+ * @param act_num the internal index of the action to be performed.
+ * @param parser the parser object we are acting for.
+ * @param stack the parse stack of that object.
+ * @param top the index of the top element of the parse stack.
+ */
+ public abstract Symbol do_action(
+ int act_num,
+ lr_parser parser,
+ Stack stack,
+ int top)
+ throws java.lang.Exception;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** User code for initialization inside the parser. Typically this
+ * initializes the scanner. This is called before the parser requests
+ * the first Symbol. Here this is just a placeholder for subclasses that
+ * might need this and we perform no action. This method is normally
+ * overridden by the generated code using this contents of the "init with"
+ * clause as its body.
+ */
+ public void user_init() throws java.lang.Exception { }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Initialize the action object. This is called before the parser does
+ * any parse actions. This is filled in by generated code to create
+ * an object that encapsulates all action code.
+ */
+ protected abstract void init_actions() throws java.lang.Exception;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Get the next Symbol from the input (supplied by generated subclass).
+ * Once end of file has been reached, all subsequent calls to scan
+ * should return an EOF Symbol (which is Symbol number 0). By default
+ * this method returns getScanner().next_token(); this implementation
+ * can be overriden by the generated parser using the code declared in
+ * the "scan with" clause. Do not recycle objects; every call to
+ * scan() should return a fresh object.
+ */
+ public Symbol scan() throws java.lang.Exception {
+ Symbol sym = getScanner().next_token();
+ return (sym!=null) ? sym : new Symbol(EOF_sym());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Report a fatal error. This method takes a message string and an
+ * additional object (to be used by specializations implemented in
+ * subclasses). Here in the base class a very simple implementation
+ * is provided which reports the error then throws an exception.
+ *
+ * @param message an error message.
+ * @param info an extra object reserved for use by specialized subclasses.
+ */
+ public void report_fatal_error(
+ String message,
+ Object info)
+ throws java.lang.Exception
+ {
+ /* stop parsing (not really necessary since we throw an exception, but) */
+ done_parsing();
+
+ /* use the normal error message reporting to put out the message */
+ report_error(message, info);
+
+ /* throw an exception */
+ throw new Exception("Can't recover from previous error(s)");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Report a non fatal error (or warning). This method takes a message
+ * string and an additional object (to be used by specializations
+ * implemented in subclasses). Here in the base class a very simple
+ * implementation is provided which simply prints the message to
+ * System.err.
+ *
+ * @param message an error message.
+ * @param info an extra object reserved for use by specialized subclasses.
+ */
+ public void report_error(String message, Object info)
+ {
+ System.err.print(message);
+ if (info instanceof Symbol)
+ if (((Symbol)info).left != -1)
+ System.err.println(" at character " + ((Symbol)info).left +
+ " of input");
+ else System.err.println("");
+ else System.err.println("");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** This method is called when a syntax error has been detected and recovery
+ * is about to be invoked. Here in the base class we just emit a
+ * "Syntax error" error message.
+ *
+ * @param cur_token the current lookahead Symbol.
+ */
+ public void syntax_error(Symbol cur_token)
+ {
+ report_error("Syntax error", cur_token);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** This method is called if it is determined that syntax error recovery
+ * has been unsuccessful. Here in the base class we report a fatal error.
+ *
+ * @param cur_token the current lookahead Symbol.
+ */
+ public void unrecovered_syntax_error(Symbol cur_token)
+ throws java.lang.Exception
+ {
+ report_fatal_error("Couldn't repair and continue parse", cur_token);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Fetch an action from the action table. The table is broken up into
+ * rows, one per state (rows are indexed directly by state number).
+ * Within each row, a list of index, value pairs are given (as sequential
+ * entries in the table), and the list is terminated by a default entry
+ * (denoted with a Symbol index of -1). To find the proper entry in a row
+ * we do a linear or binary search (depending on the size of the row).
+ *
+ * @param state the state index of the action being accessed.
+ * @param sym the Symbol index of the action being accessed.
+ */
+ protected final short get_action(int state, int sym)
+ {
+ short tag;
+ int first, last, probe;
+ short[] row = action_tab[state];
+
+ /* linear search if we are < 10 entries */
+ if (row.length < 20)
+ for (probe = 0; probe < row.length; probe++)
+ {
+ /* is this entry labeled with our Symbol or the default? */
+ tag = row[probe++];
+ if (tag == sym || tag == -1)
+ {
+ /* return the next entry */
+ return row[probe];
+ }
+ }
+ /* otherwise binary search */
+ else
+ {
+ first = 0;
+ last = (row.length-1)/2 - 1; /* leave out trailing default entry */
+ while (first <= last)
+ {
+ probe = (first+last)/2;
+ if (sym == row[probe*2])
+ return row[probe*2+1];
+ else if (sym > row[probe*2])
+ first = probe+1;
+ else
+ last = probe-1;
+ }
+
+ /* not found, use the default at the end */
+ return row[row.length-1];
+ }
+
+ /* shouldn't happened, but if we run off the end we return the
+ default (error == 0) */
+ return 0;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Fetch a state from the reduce-goto table. The table is broken up into
+ * rows, one per state (rows are indexed directly by state number).
+ * Within each row, a list of index, value pairs are given (as sequential
+ * entries in the table), and the list is terminated by a default entry
+ * (denoted with a Symbol index of -1). To find the proper entry in a row
+ * we do a linear search.
+ *
+ * @param state the state index of the entry being accessed.
+ * @param sym the Symbol index of the entry being accessed.
+ */
+ protected final short get_reduce(int state, int sym)
+ {
+ short tag;
+ short[] row = reduce_tab[state];
+
+ /* if we have a null row we go with the default */
+ if (row == null)
+ return -1;
+
+ for (int probe = 0; probe < row.length; probe++)
+ {
+ /* is this entry labeled with our Symbol or the default? */
+ tag = row[probe++];
+ if (tag == sym || tag == -1)
+ {
+ /* return the next entry */
+ return row[probe];
+ }
+ }
+ /* if we run off the end we return the default (error == -1) */
+ return -1;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** This method provides the main parsing routine. It returns only when
+ * done_parsing() has been called (typically because the parser has
+ * accepted, or a fatal error has been reported). See the header
+ * documentation for the class regarding how shift/reduce parsers operate
+ * and how the various tables are used.
+ */
+ public Symbol parse() throws java.lang.Exception
+ {
+ /* the current action code */
+ int act;
+
+ /* the Symbol/stack element returned by a reduce */
+ Symbol lhs_sym = null;
+
+ /* information about production being reduced with */
+ short handle_size, lhs_sym_num;
+
+ /* set up direct reference to tables to drive the parser */
+
+ production_tab = production_table();
+ action_tab = action_table();
+ reduce_tab = reduce_table();
+
+ /* initialize the action encapsulation object */
+ init_actions();
+
+ /* do user initialization */
+ user_init();
+
+ /* get the first token */
+ cur_token = scan();
+
+ /* push dummy Symbol with start state to get us underway */
+ stack.removeAllElements();
+ stack.push(new Symbol(0, start_state()));
+ tos = 0;
+
+ /* continue until we are told to stop */
+ for (_done_parsing = false; !_done_parsing; )
+ {
+ /* Check current token for freshness. */
+ if (cur_token.used_by_parser)
+ throw new Error("Symbol recycling detected (fix your scanner).");
+
+ /* current state is always on the top of the stack */
+
+ /* look up action out of the current state with the current input */
+ act = get_action(((Symbol)stack.peek()).parse_state, cur_token.sym);
+
+ /* decode the action -- > 0 encodes shift */
+ if (act > 0)
+ {
+ /* shift to the encoded state by pushing it on the stack */
+ cur_token.parse_state = act-1;
+ cur_token.used_by_parser = true;
+ stack.push(cur_token);
+ tos++;
+
+ /* advance to the next Symbol */
+ cur_token = scan();
+ }
+ /* if its less than zero, then it encodes a reduce action */
+ else if (act < 0)
+ {
+ /* perform the action for the reduce */
+ lhs_sym = do_action((-act)-1, this, stack, tos);
+
+ /* look up information about the production */
+ lhs_sym_num = production_tab[(-act)-1][0];
+ handle_size = production_tab[(-act)-1][1];
+
+ /* pop the handle off the stack */
+ for (int i = 0; i < handle_size; i++)
+ {
+ stack.pop();
+ tos--;
+ }
+
+ /* look up the state to go to from the one popped back to */
+ act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num);
+
+ /* shift to that state */
+ lhs_sym.parse_state = act;
+ lhs_sym.used_by_parser = true;
+ stack.push(lhs_sym);
+ tos++;
+ }
+ /* finally if the entry is zero, we have an error */
+ else if (act == 0)
+ {
+ /* call user syntax error reporting routine */
+ syntax_error(cur_token);
+
+ /* try to error recover */
+ if (!error_recovery(false))
+ {
+ /* if that fails give up with a fatal syntax error */
+ unrecovered_syntax_error(cur_token);
+
+ /* just in case that wasn't fatal enough, end parse */
+ done_parsing();
+ } else {
+ lhs_sym = (Symbol)stack.peek();
+ }
+ }
+ }
+ return lhs_sym;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Write a debugging message to System.err for the debugging version
+ * of the parser.
+ *
+ * @param mess the text of the debugging message.
+ */
+ public void debug_message(String mess)
+ {
+ System.err.println(mess);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Dump the parse stack for debugging purposes. */
+ public void dump_stack()
+ {
+ if (stack == null)
+ {
+ debug_message("# Stack dump requested, but stack is null");
+ return;
+ }
+
+ debug_message("============ Parse Stack Dump ============");
+
+ /* dump the stack */
+ for (int i=0; i<stack.size(); i++)
+ {
+ debug_message("Symbol: " + ((Symbol)stack.elementAt(i)).sym +
+ " State: " + ((Symbol)stack.elementAt(i)).parse_state);
+ }
+ debug_message("==========================================");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Do debug output for a reduce.
+ *
+ * @param prod_num the production we are reducing with.
+ * @param nt_num the index of the LHS non terminal.
+ * @param rhs_size the size of the RHS.
+ */
+ public void debug_reduce(int prod_num, int nt_num, int rhs_size)
+ {
+ debug_message("# Reduce with prod #" + prod_num + " [NT=" + nt_num +
+ ", " + "SZ=" + rhs_size + "]");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Do debug output for shift.
+ *
+ * @param shift_tkn the Symbol being shifted onto the stack.
+ */
+ public void debug_shift(Symbol shift_tkn)
+ {
+ debug_message("# Shift under term #" + shift_tkn.sym +
+ " to state #" + shift_tkn.parse_state);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Do debug output for stack state. [CSA]
+ */
+ public void debug_stack() {
+ StringBuffer sb=new StringBuffer("## STACK:");
+ for (int i=0; i<stack.size(); i++) {
+ Symbol s = (Symbol) stack.elementAt(i);
+ sb.append(" <state "+s.parse_state+", sym "+s.sym+">");
+ if ((i%3)==2 || (i==(stack.size()-1))) {
+ debug_message(sb.toString());
+ sb = new StringBuffer(" ");
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Perform a parse with debugging output. This does exactly the
+ * same things as parse(), except that it calls debug_shift() and
+ * debug_reduce() when shift and reduce moves are taken by the parser
+ * and produces various other debugging messages.
+ */
+ public Symbol debug_parse()
+ throws java.lang.Exception
+ {
+ /* the current action code */
+ int act;
+
+ /* the Symbol/stack element returned by a reduce */
+ Symbol lhs_sym = null;
+
+ /* information about production being reduced with */
+ short handle_size, lhs_sym_num;
+
+ /* set up direct reference to tables to drive the parser */
+ production_tab = production_table();
+ action_tab = action_table();
+ reduce_tab = reduce_table();
+
+ debug_message("# Initializing parser");
+
+ /* initialize the action encapsulation object */
+ init_actions();
+
+ /* do user initialization */
+ user_init();
+
+ /* the current Symbol */
+ cur_token = scan();
+
+ debug_message("# Current Symbol is #" + cur_token.sym);
+
+ /* push dummy Symbol with start state to get us underway */
+ stack.removeAllElements();
+ stack.push(new Symbol(0, start_state()));
+ tos = 0;
+
+ /* continue until we are told to stop */
+ for (_done_parsing = false; !_done_parsing; )
+ {
+ /* Check current token for freshness. */
+ if (cur_token.used_by_parser)
+ throw new Error("Symbol recycling detected (fix your scanner).");
+
+ /* current state is always on the top of the stack */
+ //debug_stack();
+
+ /* look up action out of the current state with the current input */
+ act = get_action(((Symbol)stack.peek()).parse_state, cur_token.sym);
+
+ /* decode the action -- > 0 encodes shift */
+ if (act > 0)
+ {
+ /* shift to the encoded state by pushing it on the stack */
+ cur_token.parse_state = act-1;
+ cur_token.used_by_parser = true;
+ debug_shift(cur_token);
+ stack.push(cur_token);
+ tos++;
+
+ /* advance to the next Symbol */
+ cur_token = scan();
+ debug_message("# Current token is " + cur_token);
+ }
+ /* if its less than zero, then it encodes a reduce action */
+ else if (act < 0)
+ {
+ /* perform the action for the reduce */
+ lhs_sym = do_action((-act)-1, this, stack, tos);
+
+ /* look up information about the production */
+ lhs_sym_num = production_tab[(-act)-1][0];
+ handle_size = production_tab[(-act)-1][1];
+
+ debug_reduce((-act)-1, lhs_sym_num, handle_size);
+
+ /* pop the handle off the stack */
+ for (int i = 0; i < handle_size; i++)
+ {
+ stack.pop();
+ tos--;
+ }
+
+ /* look up the state to go to from the one popped back to */
+ act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num);
+ debug_message("# Reduce rule: top state " +
+ ((Symbol)stack.peek()).parse_state +
+ ", lhs sym " + lhs_sym_num + " -> state " + act);
+
+ /* shift to that state */
+ lhs_sym.parse_state = act;
+ lhs_sym.used_by_parser = true;
+ stack.push(lhs_sym);
+ tos++;
+
+ debug_message("# Goto state #" + act);
+ }
+ /* finally if the entry is zero, we have an error */
+ else if (act == 0)
+ {
+ /* call user syntax error reporting routine */
+ syntax_error(cur_token);
+
+ /* try to error recover */
+ if (!error_recovery(true))
+ {
+ /* if that fails give up with a fatal syntax error */
+ unrecovered_syntax_error(cur_token);
+
+ /* just in case that wasn't fatal enough, end parse */
+ done_parsing();
+ } else {
+ lhs_sym = (Symbol)stack.peek();
+ }
+ }
+ }
+ return lhs_sym;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+ /* Error recovery code */
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Attempt to recover from a syntax error. This returns false if recovery
+ * fails, true if it succeeds. Recovery happens in 4 steps. First we
+ * pop the parse stack down to a point at which we have a shift out
+ * of the top-most state on the error Symbol. This represents the
+ * initial error recovery configuration. If no such configuration is
+ * found, then we fail. Next a small number of "lookahead" or "parse
+ * ahead" Symbols are read into a buffer. The size of this buffer is
+ * determined by error_sync_size() and determines how many Symbols beyond
+ * the error must be matched to consider the recovery a success. Next,
+ * we begin to discard Symbols in attempt to get past the point of error
+ * to a point where we can continue parsing. After each Symbol, we attempt
+ * to "parse ahead" though the buffered lookahead Symbols. The "parse ahead"
+ * process simulates that actual parse, but does not modify the real
+ * parser's configuration, nor execute any actions. If we can parse all
+ * the stored Symbols without error, then the recovery is considered a
+ * success. Once a successful recovery point is determined, we do an
+ * actual parse over the stored input -- modifying the real parse
+ * configuration and executing all actions. Finally, we return the the
+ * normal parser to continue with the overall parse.
+ *
+ * @param debug should we produce debugging messages as we parse.
+ */
+ protected boolean error_recovery(boolean debug)
+ throws java.lang.Exception
+ {
+ if (debug) debug_message("# Attempting error recovery");
+
+ /* first pop the stack back into a state that can shift on error and
+ do that shift (if that fails, we fail) */
+ if (!find_recovery_config(debug))
+ {
+ if (debug) debug_message("# Error recovery fails");
+ return false;
+ }
+
+ /* read ahead to create lookahead we can parse multiple times */
+ read_lookahead();
+
+ /* repeatedly try to parse forward until we make it the required dist */
+ for (;;)
+ {
+ /* try to parse forward, if it makes it, bail out of loop */
+ if (debug) debug_message("# Trying to parse ahead");
+ if (try_parse_ahead(debug))
+ {
+ break;
+ }
+
+ /* if we are now at EOF, we have failed */
+ if (lookahead[0].sym == EOF_sym())
+ {
+ if (debug) debug_message("# Error recovery fails at EOF");
+ return false;
+ }
+
+ /* otherwise, we consume another Symbol and try again */
+ // BUG FIX by Bruce Hutton
+ // Computer Science Department, University of Auckland,
+ // Auckland, New Zealand.
+ // It is the first token that is being consumed, not the one
+ // we were up to parsing
+ if (debug)
+ debug_message("# Consuming Symbol #" + lookahead[ 0 ].sym);
+ restart_lookahead();
+ }
+
+ /* we have consumed to a point where we can parse forward */
+ if (debug) debug_message("# Parse-ahead ok, going back to normal parse");
+
+ /* do the real parse (including actions) across the lookahead */
+ parse_lookahead(debug);
+
+ /* we have success */
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if we can shift under the special error Symbol out of the
+ * state currently on the top of the (real) parse stack.
+ */
+ protected boolean shift_under_error()
+ {
+ /* is there a shift under error Symbol */
+ return get_action(((Symbol)stack.peek()).parse_state, error_sym()) > 0;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Put the (real) parse stack into error recovery configuration by
+ * popping the stack down to a state that can shift on the special
+ * error Symbol, then doing the shift. If no suitable state exists on
+ * the stack we return false
+ *
+ * @param debug should we produce debugging messages as we parse.
+ */
+ protected boolean find_recovery_config(boolean debug)
+ {
+ Symbol error_token;
+ int act;
+
+ if (debug) debug_message("# Finding recovery state on stack");
+
+ /* Remember the right-position of the top symbol on the stack */
+ int right_pos = ((Symbol)stack.peek()).right;
+ int left_pos = ((Symbol)stack.peek()).left;
+
+ /* pop down until we can shift under error Symbol */
+ while (!shift_under_error())
+ {
+ /* pop the stack */
+ if (debug)
+ debug_message("# Pop stack by one, state was # " +
+ ((Symbol)stack.peek()).parse_state);
+ left_pos = ((Symbol)stack.pop()).left;
+ tos--;
+
+ /* if we have hit bottom, we fail */
+ if (stack.empty())
+ {
+ if (debug) debug_message("# No recovery state found on stack");
+ return false;
+ }
+ }
+
+ /* state on top of the stack can shift under error, find the shift */
+ act = get_action(((Symbol)stack.peek()).parse_state, error_sym());
+ if (debug)
+ {
+ debug_message("# Recover state found (#" +
+ ((Symbol)stack.peek()).parse_state + ")");
+ debug_message("# Shifting on error to state #" + (act-1));
+ }
+
+ /* build and shift a special error Symbol */
+ error_token = new Symbol(error_sym(), left_pos, right_pos);
+ error_token.parse_state = act-1;
+ error_token.used_by_parser = true;
+ stack.push(error_token);
+ tos++;
+
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Lookahead Symbols used for attempting error recovery "parse aheads". */
+ protected Symbol lookahead[];
+
+ /** Position in lookahead input buffer used for "parse ahead". */
+ protected int lookahead_pos;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Read from input to establish our buffer of "parse ahead" lookahead
+ * Symbols.
+ */
+ protected void read_lookahead() throws java.lang.Exception
+ {
+ /* create the lookahead array */
+ lookahead = new Symbol[error_sync_size()];
+
+ /* fill in the array */
+ for (int i = 0; i < error_sync_size(); i++)
+ {
+ lookahead[i] = cur_token;
+ cur_token = scan();
+ }
+
+ /* start at the beginning */
+ lookahead_pos = 0;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return the current lookahead in our error "parse ahead" buffer. */
+ protected Symbol cur_err_token() { return lookahead[lookahead_pos]; }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Advance to next "parse ahead" input Symbol. Return true if we have
+ * input to advance to, false otherwise.
+ */
+ protected boolean advance_lookahead()
+ {
+ /* advance the input location */
+ lookahead_pos++;
+
+ /* return true if we didn't go off the end */
+ return lookahead_pos < error_sync_size();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Reset the parse ahead input to one Symbol past where we started error
+ * recovery (this consumes one new Symbol from the real input).
+ */
+ protected void restart_lookahead() throws java.lang.Exception
+ {
+ /* move all the existing input over */
+ for (int i = 1; i < error_sync_size(); i++)
+ lookahead[i-1] = lookahead[i];
+
+ /* read a new Symbol into the last spot */
+ // BUG Fix by Bruce Hutton
+ // Computer Science Department, University of Auckland,
+ // Auckland, New Zealand. [applied 5-sep-1999 by csa]
+ // The following two lines were out of order!!
+ lookahead[error_sync_size()-1] = cur_token;
+ cur_token = scan();
+
+ /* reset our internal position marker */
+ lookahead_pos = 0;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Do a simulated parse forward (a "parse ahead") from the current
+ * stack configuration using stored lookahead input and a virtual parse
+ * stack. Return true if we make it all the way through the stored
+ * lookahead input without error. This basically simulates the action of
+ * parse() using only our saved "parse ahead" input, and not executing any
+ * actions.
+ *
+ * @param debug should we produce debugging messages as we parse.
+ */
+ protected boolean try_parse_ahead(boolean debug)
+ throws java.lang.Exception
+ {
+ int act;
+ short lhs, rhs_size;
+
+ /* create a virtual stack from the real parse stack */
+ virtual_parse_stack vstack = new virtual_parse_stack(stack);
+
+ /* parse until we fail or get past the lookahead input */
+ for (;;)
+ {
+ /* look up the action from the current state (on top of stack) */
+ act = get_action(vstack.top(), cur_err_token().sym);
+
+ /* if its an error, we fail */
+ if (act == 0) return false;
+
+ /* > 0 encodes a shift */
+ if (act > 0)
+ {
+ /* push the new state on the stack */
+ vstack.push(act-1);
+
+ if (debug) debug_message("# Parse-ahead shifts Symbol #" +
+ cur_err_token().sym + " into state #" + (act-1));
+
+ /* advance simulated input, if we run off the end, we are done */
+ if (!advance_lookahead()) return true;
+ }
+ /* < 0 encodes a reduce */
+ else
+ {
+ /* if this is a reduce with the start production we are done */
+ if ((-act)-1 == start_production())
+ {
+ if (debug) debug_message("# Parse-ahead accepts");
+ return true;
+ }
+
+ /* get the lhs Symbol and the rhs size */
+ lhs = production_tab[(-act)-1][0];
+ rhs_size = production_tab[(-act)-1][1];
+
+ /* pop handle off the stack */
+ for (int i = 0; i < rhs_size; i++)
+ vstack.pop();
+
+ if (debug)
+ debug_message("# Parse-ahead reduces: handle size = " +
+ rhs_size + " lhs = #" + lhs + " from state #" + vstack.top());
+
+ /* look up goto and push it onto the stack */
+ vstack.push(get_reduce(vstack.top(), lhs));
+ if (debug)
+ debug_message("# Goto state #" + vstack.top());
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Parse forward using stored lookahead Symbols. In this case we have
+ * already verified that parsing will make it through the stored lookahead
+ * Symbols and we are now getting back to the point at which we can hand
+ * control back to the normal parser. Consequently, this version of the
+ * parser performs all actions and modifies the real parse configuration.
+ * This returns once we have consumed all the stored input or we accept.
+ *
+ * @param debug should we produce debugging messages as we parse.
+ */
+ protected void parse_lookahead(boolean debug)
+ throws java.lang.Exception
+ {
+ /* the current action code */
+ int act;
+
+ /* the Symbol/stack element returned by a reduce */
+ Symbol lhs_sym = null;
+
+ /* information about production being reduced with */
+ short handle_size, lhs_sym_num;
+
+ /* restart the saved input at the beginning */
+ lookahead_pos = 0;
+
+ if (debug)
+ {
+ debug_message("# Reparsing saved input with actions");
+ debug_message("# Current Symbol is #" + cur_err_token().sym);
+ debug_message("# Current state is #" +
+ ((Symbol)stack.peek()).parse_state);
+ }
+
+ /* continue until we accept or have read all lookahead input */
+ while(!_done_parsing)
+ {
+ /* current state is always on the top of the stack */
+
+ /* look up action out of the current state with the current input */
+ act =
+ get_action(((Symbol)stack.peek()).parse_state, cur_err_token().sym);
+
+ /* decode the action -- > 0 encodes shift */
+ if (act > 0)
+ {
+ /* shift to the encoded state by pushing it on the stack */
+ cur_err_token().parse_state = act-1;
+ cur_err_token().used_by_parser = true;
+ if (debug) debug_shift(cur_err_token());
+ stack.push(cur_err_token());
+ tos++;
+
+ /* advance to the next Symbol, if there is none, we are done */
+ if (!advance_lookahead())
+ {
+ if (debug) debug_message("# Completed reparse");
+
+ /* scan next Symbol so we can continue parse */
+ // BUGFIX by Chris Harris <ckharris@ucsd.edu>:
+ // correct a one-off error by commenting out
+ // this next line.
+ /*cur_token = scan();*/
+
+ /* go back to normal parser */
+ return;
+ }
+
+ if (debug)
+ debug_message("# Current Symbol is #" + cur_err_token().sym);
+ }
+ /* if its less than zero, then it encodes a reduce action */
+ else if (act < 0)
+ {
+ /* perform the action for the reduce */
+ lhs_sym = do_action((-act)-1, this, stack, tos);
+
+ /* look up information about the production */
+ lhs_sym_num = production_tab[(-act)-1][0];
+ handle_size = production_tab[(-act)-1][1];
+
+ if (debug) debug_reduce((-act)-1, lhs_sym_num, handle_size);
+
+ /* pop the handle off the stack */
+ for (int i = 0; i < handle_size; i++)
+ {
+ stack.pop();
+ tos--;
+ }
+
+ /* look up the state to go to from the one popped back to */
+ act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num);
+
+ /* shift to that state */
+ lhs_sym.parse_state = act;
+ lhs_sym.used_by_parser = true;
+ stack.push(lhs_sym);
+ tos++;
+
+ if (debug) debug_message("# Goto state #" + act);
+
+ }
+ /* finally if the entry is zero, we have an error
+ (shouldn't happen here, but...)*/
+ else if (act == 0)
+ {
+ report_fatal_error("Syntax error", lhs_sym);
+ return;
+ }
+ }
+
+
+ }
+
+ /*-----------------------------------------------------------*/
+
+ /** Utility function: unpacks parse tables from strings */
+ protected static short[][] unpackFromStrings(String[] sa)
+ {
+ // Concatanate initialization strings.
+ StringBuffer sb = new StringBuffer(sa[0]);
+ for (int i=1; i<sa.length; i++)
+ sb.append(sa[i]);
+ int n=0; // location in initialization string
+ int size1 = (((int)sb.charAt(n))<<16) | ((int)sb.charAt(n+1)); n+=2;
+ short[][] result = new short[size1][];
+ for (int i=0; i<size1; i++) {
+ int size2 = (((int)sb.charAt(n))<<16) | ((int)sb.charAt(n+1)); n+=2;
+ result[i] = new short[size2];
+ for (int j=0; j<size2; j++)
+ result[i][j] = (short) (sb.charAt(n++)-2);
+ }
+ return result;
+ }
+}
+
diff --git a/src/java_cup/runtime/virtual_parse_stack.class b/src/java_cup/runtime/virtual_parse_stack.class
new file mode 100644
index 0000000..1228873
--- /dev/null
+++ b/src/java_cup/runtime/virtual_parse_stack.class
Binary files differ
diff --git a/src/java_cup/runtime/virtual_parse_stack.java b/src/java_cup/runtime/virtual_parse_stack.java
new file mode 100644
index 0000000..a4386aa
--- /dev/null
+++ b/src/java_cup/runtime/virtual_parse_stack.java
@@ -0,0 +1,145 @@
+
+package java_cup.runtime;
+
+import java.util.Stack;
+
+/** This class implements a temporary or "virtual" parse stack that
+ * replaces the top portion of the actual parse stack (the part that
+ * has been changed by some set of operations) while maintaining its
+ * original contents. This data structure is used when the parse needs
+ * to "parse ahead" to determine if a given error recovery attempt will
+ * allow the parse to continue far enough to consider it successful. Once
+ * success or failure of parse ahead is determined the system then
+ * reverts to the original parse stack (which has not actually been
+ * modified). Since parse ahead does not execute actions, only parse
+ * state is maintained on the virtual stack, not full Symbol objects.
+ *
+ * @see java_cup.runtime.lr_parser
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+
+public class virtual_parse_stack {
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constructor to build a virtual stack out of a real stack. */
+ public virtual_parse_stack(Stack shadowing_stack) throws java.lang.Exception
+ {
+ /* sanity check */
+ if (shadowing_stack == null)
+ throw new Exception(
+ "Internal parser error: attempt to create null virtual stack");
+
+ /* set up our internals */
+ real_stack = shadowing_stack;
+ vstack = new Stack();
+ real_next = 0;
+
+ /* get one element onto the virtual portion of the stack */
+ get_from_real();
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The real stack that we shadow. This is accessed when we move off
+ * the bottom of the virtual portion of the stack, but is always left
+ * unmodified.
+ */
+ protected Stack real_stack;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Top of stack indicator for where we leave off in the real stack.
+ * This is measured from top of stack, so 0 would indicate that no
+ * elements have been "moved" from the real to virtual stack.
+ */
+ protected int real_next;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The virtual top portion of the stack. This stack contains Integer
+ * objects with state numbers. This stack shadows the top portion
+ * of the real stack within the area that has been modified (via operations
+ * on the virtual stack). When this portion of the stack becomes empty we
+ * transfer elements from the underlying stack onto this stack.
+ */
+ protected Stack vstack;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Transfer an element from the real to the virtual stack. This assumes
+ * that the virtual stack is currently empty.
+ */
+ protected void get_from_real()
+ {
+ Symbol stack_sym;
+
+ /* don't transfer if the real stack is empty */
+ if (real_next >= real_stack.size()) return;
+
+ /* get a copy of the first Symbol we have not transfered */
+ stack_sym = (Symbol)real_stack.elementAt(real_stack.size()-1-real_next);
+
+ /* record the transfer */
+ real_next++;
+
+ /* put the state number from the Symbol onto the virtual stack */
+ vstack.push(new Integer(stack_sym.parse_state));
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Indicate whether the stack is empty. */
+ public boolean empty()
+ {
+ /* if vstack is empty then we were unable to transfer onto it and
+ the whole thing is empty. */
+ return vstack.empty();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return value on the top of the stack (without popping it). */
+ public int top() throws java.lang.Exception
+ {
+ if (vstack.empty())
+ throw new Exception(
+ "Internal parser error: top() called on empty virtual stack");
+
+ return ((Integer)vstack.peek()).intValue();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Pop the stack. */
+ public void pop() throws java.lang.Exception
+ {
+ if (vstack.empty())
+ throw new Exception(
+ "Internal parser error: pop from empty virtual stack");
+
+ /* pop it */
+ vstack.pop();
+
+ /* if we are now empty transfer an element (if there is one) */
+ if (vstack.empty())
+ get_from_real();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Push a state number onto the stack. */
+ public void push(int state_num)
+ {
+ vstack.push(new Integer(state_num));
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/java_cup/simple_calc/Main.java b/src/java_cup/simple_calc/Main.java
new file mode 100644
index 0000000..21ff5aa
--- /dev/null
+++ b/src/java_cup/simple_calc/Main.java
@@ -0,0 +1,32 @@
+// Driver for parser
+
+package java_cup.simple_calc;
+
+import java_cup.simple_calc.parser;
+import java_cup.runtime.Symbol;
+
+class Main {
+
+ static boolean do_debug_parse = false;
+
+ static public void main(String[] args) throws java.io.IOException {
+
+ /* create a parsing object */
+ parser parser_obj = new parser(new scanner());
+
+ /* open input files, etc. here */
+ Symbol parse_tree = null;
+
+ try {
+ if (do_debug_parse)
+ parse_tree = parser_obj.debug_parse();
+ else
+ parse_tree = parser_obj.parse();
+ } catch (Exception e) {
+ /* do cleanup here -- possibly rethrow e */
+ } finally {
+ /* do close out here */
+ }
+ }
+}
+
diff --git a/src/java_cup/simple_calc/parser.cup b/src/java_cup/simple_calc/parser.cup
new file mode 100644
index 0000000..a88d900
--- /dev/null
+++ b/src/java_cup/simple_calc/parser.cup
@@ -0,0 +1,55 @@
+// JavaCup specification for a simple expression evaluator (w/ actions)
+
+package java_cup.simple_calc;
+
+import java_cup.runtime.*;
+
+/* Terminals (tokens returned by the scanner). */
+terminal SEMI, PLUS, MINUS, TIMES, DIVIDE, MOD;
+terminal UMINUS, LPAREN, RPAREN;
+terminal Integer NUMBER;
+
+/* Non terminals */
+non terminal Object expr_list, expr_part;
+non terminal Integer expr;
+
+/* Precedences */
+precedence left PLUS, MINUS;
+precedence left TIMES, DIVIDE, MOD;
+precedence left UMINUS, LPAREN;
+
+/* The grammar */
+expr_list ::= expr_list expr_part
+ |
+ expr_part;
+
+expr_part ::= expr:e
+ {: System.out.println("= " + e); :}
+ SEMI
+ ;
+
+expr ::= expr:e1 PLUS expr:e2
+ {: RESULT = new Integer(e1.intValue() + e2.intValue()); :}
+ |
+ expr:e1 MINUS expr:e2
+ {: RESULT = new Integer(e1.intValue() - e2.intValue()); :}
+ |
+ expr:e1 TIMES expr:e2
+ {: RESULT = new Integer(e1.intValue() * e2.intValue()); :}
+ |
+ expr:e1 DIVIDE expr:e2
+ {: RESULT = new Integer(e1.intValue() / e2.intValue()); :}
+ |
+ expr:e1 MOD expr:e2
+ {: RESULT = new Integer(e1.intValue() % e2.intValue()); :}
+ |
+ NUMBER:n
+ {: RESULT = n; :}
+ |
+ MINUS expr:e
+ {: RESULT = new Integer(0 - e.intValue()); :}
+ %prec UMINUS
+ |
+ LPAREN expr:e RPAREN
+ {: RESULT = e; :}
+ ;
diff --git a/src/java_cup/simple_calc/parser.java b/src/java_cup/simple_calc/parser.java
new file mode 100644
index 0000000..d6003c7
--- /dev/null
+++ b/src/java_cup/simple_calc/parser.java
@@ -0,0 +1,318 @@
+
+//----------------------------------------------------
+// The following code was generated by CUP v0.10k
+// Sun Jul 25 13:36:02 EDT 1999
+//----------------------------------------------------
+
+package java_cup.simple_calc;
+
+import java_cup.runtime.*;
+
+/** CUP v0.10k generated parser.
+ * @version Sun Jul 25 13:36:02 EDT 1999
+ */
+public class parser extends java_cup.runtime.lr_parser {
+
+ /** Default constructor. */
+ public parser() {super();}
+
+ /** Constructor which sets the default scanner. */
+ public parser(java_cup.runtime.Scanner s) {super(s);}
+
+ /** Production table. */
+ protected static final short _production_table[][] =
+ unpackFromStrings(new String[] {
+ "\000\015\000\002\003\004\000\002\002\004\000\002\003" +
+ "\003\000\002\006\002\000\002\004\005\000\002\005\005" +
+ "\000\002\005\005\000\002\005\005\000\002\005\005\000" +
+ "\002\005\005\000\002\005\003\000\002\005\004\000\002" +
+ "\005\005" });
+
+ /** Access to production table. */
+ public short[][] production_table() {return _production_table;}
+
+ /** Parse-action table. */
+ protected static final short[][] _action_table =
+ unpackFromStrings(new String[] {
+ "\000\030\000\010\006\004\013\011\015\005\001\002\000" +
+ "\010\006\004\013\011\015\005\001\002\000\020\004\ufff7" +
+ "\005\ufff7\006\ufff7\007\ufff7\010\ufff7\011\ufff7\014\ufff7\001" +
+ "\002\000\012\002\uffff\006\uffff\013\uffff\015\uffff\001\002" +
+ "\000\016\004\ufffe\005\016\006\014\007\020\010\017\011" +
+ "\013\001\002\000\012\002\027\006\004\013\011\015\005" +
+ "\001\002\000\010\006\004\013\011\015\005\001\002\000" +
+ "\016\005\016\006\014\007\020\010\017\011\013\014\015" +
+ "\001\002\000\010\006\004\013\011\015\005\001\002\000" +
+ "\010\006\004\013\011\015\005\001\002\000\020\004\ufff5" +
+ "\005\ufff5\006\ufff5\007\ufff5\010\ufff5\011\ufff5\014\ufff5\001" +
+ "\002\000\010\006\004\013\011\015\005\001\002\000\010" +
+ "\006\004\013\011\015\005\001\002\000\010\006\004\013" +
+ "\011\015\005\001\002\000\020\004\ufffa\005\ufffa\006\ufffa" +
+ "\007\ufffa\010\ufffa\011\ufffa\014\ufffa\001\002\000\020\004" +
+ "\ufff9\005\ufff9\006\ufff9\007\ufff9\010\ufff9\011\ufff9\014\ufff9" +
+ "\001\002\000\020\004\ufffc\005\ufffc\006\ufffc\007\020\010" +
+ "\017\011\013\014\ufffc\001\002\000\020\004\ufffb\005\ufffb" +
+ "\006\ufffb\007\020\010\017\011\013\014\ufffb\001\002\000" +
+ "\020\004\ufff8\005\ufff8\006\ufff8\007\ufff8\010\ufff8\011\ufff8" +
+ "\014\ufff8\001\002\000\012\002\001\006\001\013\001\015" +
+ "\001\001\002\000\004\002\000\001\002\000\004\004\031" +
+ "\001\002\000\012\002\ufffd\006\ufffd\013\ufffd\015\ufffd\001" +
+ "\002\000\020\004\ufff6\005\ufff6\006\ufff6\007\ufff6\010\ufff6" +
+ "\011\ufff6\014\ufff6\001\002" });
+
+ /** Access to parse-action table. */
+ public short[][] action_table() {return _action_table;}
+
+ /** <code>reduce_goto</code> table. */
+ protected static final short[][] _reduce_table =
+ unpackFromStrings(new String[] {
+ "\000\030\000\010\003\007\004\005\005\006\001\001\000" +
+ "\004\005\031\001\001\000\002\001\001\000\002\001\001" +
+ "\000\004\006\027\001\001\000\006\004\025\005\006\001" +
+ "\001\000\004\005\011\001\001\000\002\001\001\000\004" +
+ "\005\024\001\001\000\004\005\023\001\001\000\002\001" +
+ "\001\000\004\005\022\001\001\000\004\005\021\001\001" +
+ "\000\004\005\020\001\001\000\002\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\002\001\001\000\002\001\001\000\002\001\001\000" +
+ "\002\001\001\000\002\001\001" });
+
+ /** Access to <code>reduce_goto</code> table. */
+ public short[][] reduce_table() {return _reduce_table;}
+
+ /** Instance of action encapsulation class. */
+ protected CUP$parser$actions action_obj;
+
+ /** Action encapsulation object initializer. */
+ protected void init_actions()
+ {
+ action_obj = new CUP$parser$actions(this);
+ }
+
+ /** Invoke a user supplied parse action. */
+ public java_cup.runtime.Symbol do_action(
+ int act_num,
+ java_cup.runtime.lr_parser parser,
+ java.util.Stack stack,
+ int top)
+ throws java.lang.Exception
+ {
+ /* call code in generated class */
+ return action_obj.CUP$parser$do_action(act_num, parser, stack, top);
+ }
+
+ /** Indicates start state. */
+ public int start_state() {return 0;}
+ /** Indicates start production. */
+ public int start_production() {return 1;}
+
+ /** <code>EOF</code> Symbol index. */
+ public int EOF_sym() {return 0;}
+
+ /** <code>error</code> Symbol index. */
+ public int error_sym() {return 1;}
+
+}
+
+/** Cup generated class to encapsulate user supplied action code.*/
+class CUP$parser$actions {
+ private final parser parser;
+
+ /** Constructor */
+ CUP$parser$actions(parser parser) {
+ this.parser = parser;
+ }
+
+ /** Method with the actual generated action code. */
+ public final java_cup.runtime.Symbol CUP$parser$do_action(
+ int CUP$parser$act_num,
+ java_cup.runtime.lr_parser CUP$parser$parser,
+ java.util.Stack CUP$parser$stack,
+ int CUP$parser$top)
+ throws java.lang.Exception
+ {
+ /* Symbol object for return from actions */
+ java_cup.runtime.Symbol CUP$parser$result;
+
+ /* select the action based on the action number */
+ switch (CUP$parser$act_num)
+ {
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 12: // expr ::= LPAREN expr RPAREN
+ {
+ Integer RESULT = null;
+ int eleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int eright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ Integer e = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+ RESULT = e;
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 11: // expr ::= MINUS expr
+ {
+ Integer RESULT = null;
+ int eleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int eright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ Integer e = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = new Integer(0 - e.intValue());
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 10: // expr ::= NUMBER
+ {
+ Integer RESULT = null;
+ int nleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int nright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ Integer n = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = n;
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 9: // expr ::= expr MOD expr
+ {
+ Integer RESULT = null;
+ int e1left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left;
+ int e1right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right;
+ Integer e1 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+ int e2left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int e2right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ Integer e2 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = new Integer(e1.intValue() % e2.intValue());
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 8: // expr ::= expr DIVIDE expr
+ {
+ Integer RESULT = null;
+ int e1left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left;
+ int e1right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right;
+ Integer e1 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+ int e2left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int e2right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ Integer e2 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = new Integer(e1.intValue() / e2.intValue());
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 7: // expr ::= expr TIMES expr
+ {
+ Integer RESULT = null;
+ int e1left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left;
+ int e1right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right;
+ Integer e1 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+ int e2left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int e2right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ Integer e2 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = new Integer(e1.intValue() * e2.intValue());
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 6: // expr ::= expr MINUS expr
+ {
+ Integer RESULT = null;
+ int e1left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left;
+ int e1right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right;
+ Integer e1 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+ int e2left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int e2right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ Integer e2 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = new Integer(e1.intValue() - e2.intValue());
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 5: // expr ::= expr PLUS expr
+ {
+ Integer RESULT = null;
+ int e1left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left;
+ int e1right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right;
+ Integer e1 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+ int e2left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int e2right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ Integer e2 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = new Integer(e1.intValue() + e2.intValue());
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 4: // expr_part ::= expr NT$0 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$0
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+ int eleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left;
+ int eright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right;
+ Integer e = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(2/*expr_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 3: // NT$0 ::=
+ {
+ Object RESULT = null;
+ int eleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int eright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ Integer e = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ System.out.println("= " + e);
+ CUP$parser$result = new java_cup.runtime.Symbol(4/*NT$0*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 2: // expr_list ::= expr_part
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(1/*expr_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 1: // $START ::= expr_list EOF
+ {
+ Object RESULT = null;
+ int start_valleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int start_valright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ Object start_val = (Object)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+ RESULT = start_val;
+ CUP$parser$result = new java_cup.runtime.Symbol(0/*$START*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ /* ACCEPT */
+ CUP$parser$parser.done_parsing();
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 0: // expr_list ::= expr_list expr_part
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(1/*expr_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /* . . . . . .*/
+ default:
+ throw new Exception(
+ "Invalid action number found in internal parse table");
+
+ }
+ }
+}
+
diff --git a/src/java_cup/simple_calc/scanner.java b/src/java_cup/simple_calc/scanner.java
new file mode 100644
index 0000000..f8f850a
--- /dev/null
+++ b/src/java_cup/simple_calc/scanner.java
@@ -0,0 +1,63 @@
+// Simple Example Scanner Class
+
+package java_cup.simple_calc;
+
+import java_cup.runtime.Symbol;
+
+public class scanner implements java_cup.runtime.Scanner {
+ final java.io.InputStream instream;
+
+ public scanner(java.io.InputStream is) throws java.io.IOException {
+ instream = is;
+ }
+ public scanner() throws java.io.IOException { this(System.in); }
+
+ /* single lookahead character */
+ protected int next_char = -2;
+
+ /* advance input by one character */
+ protected void advance()
+ throws java.io.IOException
+ { next_char = instream.read(); }
+
+ /* initialize the scanner */
+ private void init()
+ throws java.io.IOException
+ { advance(); }
+
+ /* recognize and return the next complete token */
+ public Symbol next_token()
+ throws java.io.IOException
+ {
+ if (next_char==-2) init(); // set stuff up first time we are called.
+ for (;;)
+ switch (next_char)
+ {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ /* parse a decimal integer */
+ int i_val = 0;
+ do {
+ i_val = i_val * 10 + (next_char - '0');
+ advance();
+ } while (next_char >= '0' && next_char <= '9');
+ return new Symbol(sym.NUMBER, new Integer(i_val));
+
+ case ';': advance(); return new Symbol(sym.SEMI);
+ case '+': advance(); return new Symbol(sym.PLUS);
+ case '-': advance(); return new Symbol(sym.MINUS);
+ case '*': advance(); return new Symbol(sym.TIMES);
+ case '/': advance(); return new Symbol(sym.DIVIDE);
+ case '%': advance(); return new Symbol(sym.MOD);
+ case '(': advance(); return new Symbol(sym.LPAREN);
+ case ')': advance(); return new Symbol(sym.RPAREN);
+
+ case -1: return new Symbol(sym.EOF);
+
+ default:
+ /* in this simple scanner we just ignore everything else */
+ advance();
+ break;
+ }
+ }
+};
diff --git a/src/java_cup/simple_calc/sym.java b/src/java_cup/simple_calc/sym.java
new file mode 100644
index 0000000..2584f2f
--- /dev/null
+++ b/src/java_cup/simple_calc/sym.java
@@ -0,0 +1,25 @@
+
+//----------------------------------------------------
+// The following code was generated by CUP v0.10k
+// Sun Jul 25 13:36:02 EDT 1999
+//----------------------------------------------------
+
+package java_cup.simple_calc;
+
+/** CUP generated class containing symbol constants. */
+public class sym {
+ /* terminals */
+ public static final int SEMI = 2;
+ public static final int EOF = 0;
+ public static final int DIVIDE = 6;
+ public static final int NUMBER = 11;
+ public static final int error = 1;
+ public static final int UMINUS = 8;
+ public static final int MINUS = 4;
+ public static final int TIMES = 5;
+ public static final int LPAREN = 9;
+ public static final int RPAREN = 10;
+ public static final int MOD = 7;
+ public static final int PLUS = 3;
+}
+
diff --git a/src/syntaxParser/AtomicLit.java b/src/syntaxParser/AtomicLit.java
new file mode 100644
index 0000000..b4b8409
--- /dev/null
+++ b/src/syntaxParser/AtomicLit.java
@@ -0,0 +1,56 @@
+package syntaxParser;
+/**
+ * AtomicLit
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani
+ */
+class AtomicLit {
+
+
+ BooleanExpr booleanExpr;
+ int integerExpr;
+ float floatExpr;
+ String stringExpr;
+
+ String flag;
+
+ /**
+ * AtomicLit constructor comment.
+ */
+ public AtomicLit() {
+ super();
+ }
+ public AtomicLit( BooleanExpr be){
+ booleanExpr = be;
+ flag = "boolean";
+ }
+
+ public AtomicLit( int ie){
+ stringExpr = ie.toString();
+ flag = "int";
+ }
+
+ public AtomicLit( float fe){
+ stringExpr = fe.toString();
+ flag = "float";
+ }
+
+ public AtomicLit( String se){
+ stringExpr = se;
+ flag = "string";
+ }
+
+ String toXML(){
+ String result="" ;
+ try {
+ if (flag.equals("boolean")) {
+ result += "<boolean>" + booleanExpr.toXML() + "</boolean>";
+ } else if (flag.equals("int") || flag.equals("float") || flag.equals("string")) {
+ result += "<scalar>" + stringExpr + "</scalar>
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+}
diff --git a/src/syntaxParser/AxisCrsElement.java b/src/syntaxParser/AxisCrsElement.java
new file mode 100644
index 0000000..152bea1
--- /dev/null
+++ b/src/syntaxParser/AxisCrsElement.java
@@ -0,0 +1,19 @@
+package syntaxParser;
+/* Author: Sorin Stancu-Mara
+ * Date: 8 Feb 2008
+ */
+
+class AxisCrsElement implements IParseTreeNode {
+ String axis;
+ String crs;
+
+ public AxisCrsElement(String name, String crs) {
+ axis = name;
+ this.crs = crs;
+ }
+
+ public String toXML() {
+ return "<axis>" + axis + "</axis><crs>" + crs + "</crs>";
+ }
+
+}
diff --git a/src/syntaxParser/AxisCrsList.java b/src/syntaxParser/AxisCrsList.java
new file mode 100644
index 0000000..2bcfdc9
--- /dev/null
+++ b/src/syntaxParser/AxisCrsList.java
@@ -0,0 +1,7 @@
+package syntaxParser;
+
+class AxisCrsList extends List {
+ public AxisCrsList(AxisCrsElement elem) { super((IParseTreeNode)elem); }
+ public AxisCrsList(AxisCrsElement elem, AxisCrsList next) { super((IParseTreeNode)elem, (List)next); }
+}
+
diff --git a/src/syntaxParser/AxisIntervalElement.java b/src/syntaxParser/AxisIntervalElement.java
new file mode 100644
index 0000000..4c0b4e7
--- /dev/null
+++ b/src/syntaxParser/AxisIntervalElement.java
@@ -0,0 +1,32 @@
+package syntaxParser;
+/* Author: Sorin Stancu-Mara
+ * Date: 8 Feb 2008
+ */
+
+class AxisIntervalElement implements IParseTreeNode {
+ String axisName;
+ String lo, hi;
+ String crs;
+
+ public AxisIntervalElement(String name, String lo, String hi) {
+ axisName = name;
+ this.lo = lo;
+ this.hi = hi;
+ }
+
+ public AxisIntervalElement(String name,String crs, String lo, String hi) {
+ axisName = name;
+ this.crs = crs;
+ this.lo = lo;
+ this.hi = hi;
+ }
+
+ public String toXML() {
+ String result = "<axis>" + axisName + "</axis>";
+ if (crs != null)
+ result += "<crs>" + crs + "</crs>";
+ result += "<coord>" + lo + "</coord><coord>" + hi +
+ "</coord>";
+ return result;
+ }
+}
diff --git a/src/syntaxParser/AxisIntervalList.java b/src/syntaxParser/AxisIntervalList.java
new file mode 100644
index 0000000..d610c53
--- /dev/null
+++ b/src/syntaxParser/AxisIntervalList.java
@@ -0,0 +1,6 @@
+package syntaxParser;
+
+class AxisIntervalList extends List {
+ public AxisIntervalList(AxisIntervalElement elem) { super((IParseTreeNode)elem); }
+ public AxisIntervalList(AxisIntervalElement elem, AxisIntervalList next) { super((IParseTreeNode)elem, (List)next); }
+} \ No newline at end of file
diff --git a/src/syntaxParser/AxisPointElement.java b/src/syntaxParser/AxisPointElement.java
new file mode 100644
index 0000000..37e4911
--- /dev/null
+++ b/src/syntaxParser/AxisPointElement.java
@@ -0,0 +1,30 @@
+package syntaxParser;
+/* Author: Sorin Stancu-Mara
+ * Date: 8 Feb 2008
+ */
+
+class AxisPointElement implements IParseTreeNode {
+ String axis;
+ String crs;
+ String point;
+
+ public AxisPointElement(String name, String p) {
+ axis = name;
+ point = p;
+ }
+
+ public AxisPointElement(String name, String crs, String p) {
+ axis = name;
+ point = p;
+ this.crs = crs;
+ }
+
+ public String toXML() {
+ String result = "<axis>" + axis + "</axis>";
+ if (crs != null)
+ result += "<crs>" + crs + "</crs>";
+ result += "<coord>" + point + "</coord>";
+ return result;
+ }
+
+}
diff --git a/src/syntaxParser/AxisPointList.java b/src/syntaxParser/AxisPointList.java
new file mode 100644
index 0000000..84d5c23
--- /dev/null
+++ b/src/syntaxParser/AxisPointList.java
@@ -0,0 +1,8 @@
+package syntaxParser;
+
+class AxisPointList extends List {
+ public AxisPointList(AxisPointElement elem) { super((IParseTreeNode)elem); }
+ public AxisPointList(AxisPointElement elem, AxisPointList next) { super((IParseTreeNode)elem, (List)next); }
+}
+
+
diff --git a/src/syntaxParser/BinaryInducedExpr.java b/src/syntaxParser/BinaryInducedExpr.java
new file mode 100644
index 0000000..fd34bda
--- /dev/null
+++ b/src/syntaxParser/BinaryInducedExpr.java
@@ -0,0 +1,38 @@
+package syntaxParser;
+/**
+ * BinaryInducedExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class BinaryInducedExpr implements IParseTreeNode {
+
+ IParseTreeNode leftCoverageExpr;
+ IParseTreeNode rightCoverageExpr;
+ int wrapInScalar;
+ String operator;
+
+ public BinaryInducedExpr( String o, IParseTreeNode le, IParseTreeNode re ){
+ leftCoverageExpr = le;
+ rightCoverageExpr = re;
+ wrapInScalar = 0;
+ operator = o;
+ }
+ public BinaryInducedExpr( String o, IParseTreeNode le, IParseTreeNode re, int wis ){
+ leftCoverageExpr = le;
+ rightCoverageExpr = re;
+ wrapInScalar = wis;
+ operator = o;
+ }
+ public String toXML(){
+ String result="";
+ result = "<" + operator + ">";
+ if (wrapInScalar == -1) result += "<scalar>";
+ result += leftCoverageExpr.toXML();
+ if (wrapInScalar == -1) result += "</scalar>";
+ if (wrapInScalar == 1) result += "<scalar>";
+ result += rightCoverageExpr.toXML();
+ if (wrapInScalar == 1) result += "</scalar>";
+ result += "</" + operator + ">";
+ return result;
+ }
+}
diff --git a/src/syntaxParser/BooleanExpr.java b/src/syntaxParser/BooleanExpr.java
new file mode 100644
index 0000000..5d013f4
--- /dev/null
+++ b/src/syntaxParser/BooleanExpr.java
@@ -0,0 +1,33 @@
+package syntaxParser;
+/**
+ * BooleanExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class BooleanExpr implements IParseTreeNode {
+ CoverageExpr coverageExpr;
+ String operator;
+ int integerExpr;
+
+ public BooleanExpr( CoverageExpr ce, String op ){
+ coverageExpr = ce;
+ operator = op;
+ }
+
+ public BooleanExpr( CoverageExpr ce, int ie, String op ){
+ coverageExpr = ce;
+ integerExpr = ie;
+ operator = op;
+ }
+
+ public String toXML(){
+ String result="";
+ result += "<"+operator+">";
+ if (operator.equals("bit")) {
+ result += "<position>" + integerExpr +"<position>";
+ }
+ result += coverageExpr.toXML();
+ result += "</"+operator+">";
+ return result;
+ }
+}
diff --git a/src/syntaxParser/BooleanScalarExpr.java b/src/syntaxParser/BooleanScalarExpr.java
new file mode 100644
index 0000000..6b2278d
--- /dev/null
+++ b/src/syntaxParser/BooleanScalarExpr.java
@@ -0,0 +1,38 @@
+package syntaxParser;
+/**
+ * BooleanScalarExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class BooleanScalarExpr implements IParseTreeNode {
+ BooleanScalarExpr leftBooleanScalarExpr, rightBooleanScalarExpr;
+ String booleanConstant;
+ String op;
+ public BooleanScalarExpr(String bc) {
+ booleanConstant = bc;
+ }
+
+ public BooleanScalarExpr(String op, BooleanScalarExpr be){
+ this.op = op;
+ leftBooleanScalarExpr = be ;
+ }
+
+ public BooleanScalarExpr(String op, BooleanScalarExpr lbe, BooleanScalarExpr rbe){
+ this.op = op;
+ leftBooleanScalarExpr = lbe ;
+ rightBooleanScalarExpr = rbe ;
+ }
+
+ public String toXML(){
+ if (op == null) return "<boolean>" + booleanConstant + "</boolean>";
+ else if (op.equals("not")) return "<scalarNot>" + leftBooleanScalarExpr.toXML() + "</scalarNot>";
+ else {
+ if (op.equals("and")) op = "scalarAnd";
+ else if (op.equals("or")) op = "scalarOr";
+ else if (op.equals("xor")) op = "scalarXor";
+ return "<" + op + ">" + leftBooleanScalarExpr.toXML() + rightBooleanScalarExpr.toXML() + "</" + op + ">";
+ }
+
+ }
+
+}
diff --git a/src/syntaxParser/CastExpr.java b/src/syntaxParser/CastExpr.java
new file mode 100644
index 0000000..dddaa0e
--- /dev/null
+++ b/src/syntaxParser/CastExpr.java
@@ -0,0 +1,24 @@
+package syntaxParser;
+/**
+ * CastExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class CastExpr implements IParseTreeNode {
+ String castType;
+ CoverageExpr coverageExpr;
+
+ public CastExpr( CoverageExpr ce, String ct){
+ castType = ct;
+ coverageExpr = ce;
+ }
+
+ public String toXML(){
+ String result= "" ;
+ result += "<cast>";
+ result += "<type>" + castType + "</type>";
+ result += coverageExpr.toXML();
+ result += "</cast>";
+ return result;
+ }
+}
diff --git a/src/syntaxParser/ComplexLit.java b/src/syntaxParser/ComplexLit.java
new file mode 100644
index 0000000..a75b495
--- /dev/null
+++ b/src/syntaxParser/ComplexLit.java
@@ -0,0 +1,33 @@
+package syntaxParser;
+/**
+ * ComplexLit
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani
+ */
+class ComplexLit {
+
+ ScalarLitList scalarLitList;
+
+ /**
+ * ComplexLit constructor comment.
+ */
+
+ public ComplexLit() {
+ super();
+ }
+ public ComplexLit( ScalarLitList l ){
+ scalarLitList = l;
+ }
+
+
+ String toXML(){
+ String result="" ;
+ try {
+ result += "complex literal not defined XSD";
+ } catch (Exception e ) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+}
diff --git a/src/syntaxParser/CondenseExpr.java b/src/syntaxParser/CondenseExpr.java
new file mode 100644
index 0000000..a5fdb3f
--- /dev/null
+++ b/src/syntaxParser/CondenseExpr.java
@@ -0,0 +1,22 @@
+package syntaxParser;
+/**
+ * CondenseExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class CondenseExpr implements IParseTreeNode{
+
+
+ IParseTreeNode expr;
+
+ public CondenseExpr( IParseTreeNode re ){
+ expr = re;
+ }
+
+ public String toXML() {
+ return expr.toXML();
+ }
+
+
+
+}
diff --git a/src/syntaxParser/CoverageConstructorExpr.java b/src/syntaxParser/CoverageConstructorExpr.java
new file mode 100644
index 0000000..2f6d89e
--- /dev/null
+++ b/src/syntaxParser/CoverageConstructorExpr.java
@@ -0,0 +1,21 @@
+package syntaxParser;
+/* Author: Sorin Stancu-Mara
+ * Date: 8 Feb 2008
+ */
+
+class CoverageConstructorExpr implements IParseTreeNode {
+ String name;
+ VariableList variables;
+ ScalarExpr expr;
+
+ public CoverageConstructorExpr(String name, VariableList vl, ScalarExpr expr) {
+ this.name = name;
+ this.variables = vl;
+ this.expr = expr;
+ }
+
+ public String toXML() {
+ return "<construct><coverage>" + name + "</coverage>" + variables.toXML() + expr.toXML() + "</construct>";
+ }
+
+}
diff --git a/src/syntaxParser/CoverageExpr.java b/src/syntaxParser/CoverageExpr.java
new file mode 100644
index 0000000..516c061
--- /dev/null
+++ b/src/syntaxParser/CoverageExpr.java
@@ -0,0 +1,61 @@
+package syntaxParser;
+/**
+ * CoverageExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class CoverageExpr implements IParseTreeNode {
+
+ String coverageName;
+ IParseTreeNode expr;
+ String function;
+
+ public CoverageExpr( String n ){
+ coverageName = n;
+ function = "name";
+ }
+
+ public CoverageExpr( SetMetaDataExpr smde ){
+ expr = smde;
+ function = "setMetaDataExpr";
+ }
+
+ public CoverageExpr( InducedExpr ie ){
+ expr = ie;
+ function = "inducedExpr";
+ }
+
+ public CoverageExpr( SubsetExpr se ){
+ expr = se;
+ function = "subsetExpr";
+ }
+
+ public CoverageExpr( CrsTransformExpr cte ){
+ expr = cte;
+ function = "crsTransformExpr";
+ }
+
+ public CoverageExpr( ScaleExpr se ){
+ expr = se;
+ function = "scaleExpr";
+ }
+
+ public CoverageExpr( CoverageExpr ce ){
+ expr = ce;
+ function = "coverageExpr";
+ }
+
+ public CoverageExpr( CoverageConstructorExpr ce ){
+ expr = ce;
+ function = "coverageConstructorExpr";
+ }
+
+ public String toXML(){
+ String result= "" ;
+ if (function.equals("name")) {
+ result = "<coverage>" + coverageName + "</coverage>";
+ } else
+ result = expr.toXML();
+ return result;
+ }
+}
diff --git a/src/syntaxParser/CoverageList.java b/src/syntaxParser/CoverageList.java
new file mode 100644
index 0000000..9ee476d
--- /dev/null
+++ b/src/syntaxParser/CoverageList.java
@@ -0,0 +1,33 @@
+package syntaxParser;
+/**
+ * CoverageList class represents a CoverageList.
+ * Creation date: (3/3/2003 2:52:55 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+import java.util.*;
+public class CoverageList implements IParseTreeNode {
+ private String coverageName;
+ private CoverageList next;
+
+ public CoverageList(String c) {
+ coverageName = c;
+ next = null;
+ }
+
+ public CoverageList(String c, CoverageList l) {
+ coverageName = c;
+ next = l;
+ }
+
+
+ public String toXML(){
+ String result = "<coverageName>" + coverageName + "</coverageName>";
+ if (next != null) {
+ result += next.toXML();
+ }
+ return result;
+ }
+
+
+
+}
diff --git a/src/syntaxParser/CrsList.java b/src/syntaxParser/CrsList.java
new file mode 100644
index 0000000..d10834e
--- /dev/null
+++ b/src/syntaxParser/CrsList.java
@@ -0,0 +1,33 @@
+package syntaxParser;
+/* Author: Sorin Stancu-Mara
+ * Date: 9 Feb 2008
+ * Outside the other Lists becasuse this one works with strings.
+ */
+
+class CrsList implements IParseTreeNode {
+ String elem;
+ String tag;
+ CrsList next;
+ public CrsList(String e) {
+ elem = e;
+ }
+ public CrsList(String e, CrsList n) {
+ elem = e;
+ next = n;
+ }
+ public void setTag(String newTag) {
+ tag =newTag;
+ if (next != null) {
+ next.setTag(tag);
+ }
+ }
+ public String toXML() {
+ String result = "";
+ if (tag != null) result += "<" + tag + ">" + elem + "</" + tag + ">";
+ else result += elem;
+ if (next != null)
+ result += next.toXML();
+ return result;
+
+ }
+}
diff --git a/src/syntaxParser/CrsTransformExpr.java b/src/syntaxParser/CrsTransformExpr.java
new file mode 100644
index 0000000..ea214bc
--- /dev/null
+++ b/src/syntaxParser/CrsTransformExpr.java
@@ -0,0 +1,23 @@
+package syntaxParser;
+/**
+ * CrsTransformExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class CrsTransformExpr implements IParseTreeNode {
+ CoverageExpr coverageExpr;
+ AxisCrsList axisCrsList;
+ FieldInterpolationList interpList;
+
+ public CrsTransformExpr( CoverageExpr ce, AxisCrsList axisList, FieldInterpolationList fil ){
+ coverageExpr = ce;
+ axisCrsList = axisList;
+ axisCrsList.setTag("crsTransformAxisSpec");
+ interpList = fil;
+ interpList.setTag("crsTransformFieldSpec");
+ }
+ public String toXML(){
+ return "<crsTransform>" + axisCrsList.toXML() + interpList.toXML() +
+ coverageExpr.toXML() + "</crsTransform>";
+ }
+}
diff --git a/src/syntaxParser/EncodedCoverageExpr.java b/src/syntaxParser/EncodedCoverageExpr.java
new file mode 100644
index 0000000..3f5f283
--- /dev/null
+++ b/src/syntaxParser/EncodedCoverageExpr.java
@@ -0,0 +1,42 @@
+package syntaxParser;
+/**
+ * EncodedCoverageExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class EncodedCoverageExpr implements IParseTreeNode {
+ CoverageExpr coverageExpr;
+ String formatName;
+ String extraParams;
+ boolean store;
+ public EncodedCoverageExpr( CoverageExpr ce , String fn ){
+ coverageExpr = ce;
+ formatName = fn;
+ extraParams = null;
+ store = false;
+ }
+
+ public EncodedCoverageExpr( CoverageExpr ce , String fn, String ep ){
+ coverageExpr = ce;
+ formatName = fn;
+ extraParams = ep;
+ store = false;
+ }
+
+ public void setStoreFlag() {
+ store = true;
+ }
+
+ public String toXML(){
+ String result= "<encode>" ;
+ if (store) result = "<encode store=\"true\">";
+
+ result += "<format>" + formatName + "</format>" ;
+ if (extraParams != null ) {
+ result += "<extraParams>" + extraParams + "</extraParams>" ;
+ }
+ result += coverageExpr.toXML() ;
+ result+= "</encode>" ;
+ return result;
+ }
+}
diff --git a/src/syntaxParser/ExponentialExpr.java b/src/syntaxParser/ExponentialExpr.java
new file mode 100644
index 0000000..469657e
--- /dev/null
+++ b/src/syntaxParser/ExponentialExpr.java
@@ -0,0 +1,22 @@
+package syntaxParser;
+/**
+ * ExponentialExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class ExponentialExpr implements IParseTreeNode {
+ String expOperator;
+ CoverageExpr coverageExpr;
+
+ public ExponentialExpr( CoverageExpr ce, String op){
+ expOperator = op;
+ coverageExpr = ce;
+ }
+ public String toXML(){
+ String result= "" ;
+ result += "<" + expOperator + ">";
+ result += coverageExpr.toXML() ;
+ result += "</" + expOperator + ">";
+ return result;
+ }
+}
diff --git a/src/syntaxParser/ExtendExpr.java b/src/syntaxParser/ExtendExpr.java
new file mode 100644
index 0000000..8a43b48
--- /dev/null
+++ b/src/syntaxParser/ExtendExpr.java
@@ -0,0 +1,20 @@
+package syntaxParser;
+/**
+ * ExtendExpr
+ * Creation date: (8/2/2008)
+ * @author: Sorin Stancu-Mara
+ */
+class ExtendExpr implements IParseTreeNode {
+
+ CoverageExpr coverageExpr;
+ AxisIntervalList intervalList;
+ public ExtendExpr( CoverageExpr ce, AxisIntervalList apl){
+ coverageExpr = ce;
+ intervalList = apl;
+ intervalList.setTag("extendAxisSpec");
+ }
+
+ public String toXML(){
+ return "<extend>" + intervalList.toXML() + coverageExpr.toXML() + "</extend>";
+ }
+}
diff --git a/src/syntaxParser/FieldInterpolationElement.java b/src/syntaxParser/FieldInterpolationElement.java
new file mode 100644
index 0000000..28ab51f
--- /dev/null
+++ b/src/syntaxParser/FieldInterpolationElement.java
@@ -0,0 +1,18 @@
+package syntaxParser;
+/* Authod: Sorin Stancu-Mara
+ * Date: 8 Feb 2008
+ */
+
+class FieldInterpolationElement implements IParseTreeNode {
+ String field;
+ FieldInterpolationMethod method;
+
+ public FieldInterpolationElement(String field, FieldInterpolationMethod m) {
+ this.field = field;
+ this.method = m;
+ }
+
+ public String toXML() {
+ return "<field>" + field + "</field>" + method.toXML();
+ }
+}
diff --git a/src/syntaxParser/FieldInterpolationList.java b/src/syntaxParser/FieldInterpolationList.java
new file mode 100644
index 0000000..12d81e2
--- /dev/null
+++ b/src/syntaxParser/FieldInterpolationList.java
@@ -0,0 +1,9 @@
+package syntaxParser;
+
+class FieldInterpolationList extends List {
+ public FieldInterpolationList(FieldInterpolationElement elem) { super((IParseTreeNode)elem); }
+ public FieldInterpolationList(FieldInterpolationElement elem, FieldInterpolationList next) { super((IParseTreeNode)elem, (List)next); }
+}
+
+
+
diff --git a/src/syntaxParser/FieldInterpolationMethod.java b/src/syntaxParser/FieldInterpolationMethod.java
new file mode 100644
index 0000000..da54fea
--- /dev/null
+++ b/src/syntaxParser/FieldInterpolationMethod.java
@@ -0,0 +1,20 @@
+package syntaxParser;
+/**
+ * InterpMethod
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class FieldInterpolationMethod implements IParseTreeNode {
+ String type;
+ String nullresistence;
+
+ public FieldInterpolationMethod(String type, String nr ) {
+ this.type = type;
+ nullresistence = nr;
+ }
+
+ public String toXML(){
+ return "<interpolationMethod>" + type + "</interpolationMethod>" +
+ "<nullResistence>" + nullresistence + "</nullResistence>";
+ }
+}
diff --git a/src/syntaxParser/ForClause.java b/src/syntaxParser/ForClause.java
new file mode 100644
index 0000000..f0203f5
--- /dev/null
+++ b/src/syntaxParser/ForClause.java
@@ -0,0 +1,17 @@
+package syntaxParser;
+/**
+ * ForClause
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class ForClause implements IParseTreeNode {
+ ForClauseElements forClauseElements;
+ public ForClause( ForClauseElements fce ){
+
+ forClauseElements = fce;
+ }
+
+ public String toXML(){
+ return forClauseElements.toXML();
+ }
+}
diff --git a/src/syntaxParser/ForClauseElements.java b/src/syntaxParser/ForClauseElements.java
new file mode 100644
index 0000000..ffb48d0
--- /dev/null
+++ b/src/syntaxParser/ForClauseElements.java
@@ -0,0 +1,39 @@
+package syntaxParser;
+/**
+ * ForClauseElements
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+
+import java.util.*;
+
+class ForClauseElements implements IParseTreeNode{
+ String var;
+ CoverageList coverageList;
+ ForClauseElements next;
+
+
+ public ForClauseElements( String v, CoverageList c ){
+ var = v;
+ coverageList = c;
+ }
+
+ public ForClauseElements( String v, CoverageList c, ForClauseElements next ){
+ var = v;
+ coverageList = c;
+ this.next = next;
+ }
+
+ public String toXML(){
+
+ String result="";
+ result += "<coverageIterator>";
+ result +="<iteratorVar>" + var + "</iteratorVar>" ;
+ result += coverageList.toXML() ;
+ result += "</coverageIterator>";
+ if (next != null) {
+ result += next.toXML();
+ }
+ return result;
+ }
+}
diff --git a/src/syntaxParser/GeneralCondenseExpr.java b/src/syntaxParser/GeneralCondenseExpr.java
new file mode 100644
index 0000000..397e36a
--- /dev/null
+++ b/src/syntaxParser/GeneralCondenseExpr.java
@@ -0,0 +1,37 @@
+package syntaxParser;
+/**
+ * GeneralCondenseExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin stancu-Mara
+ */
+class GeneralCondenseExpr implements IParseTreeNode {
+
+ String condenseOpType;
+ ScalarExpr scalarExpr;
+ VariableList variables;
+ BooleanScalarExpr condition;
+
+ public GeneralCondenseExpr(String op, VariableList vars, ScalarExpr val) {
+ condenseOpType = op;
+ variables = vars;
+ scalarExpr = val;
+ }
+
+ public GeneralCondenseExpr(String op, VariableList vars, BooleanScalarExpr cond, ScalarExpr val) {
+ condenseOpType = op;
+ variables = vars;
+ scalarExpr = val;
+ condition = cond;
+ }
+
+ public String toXML(){
+ String result = "<condense>" + variables.toXML();
+ if (condition != null)
+ result += "<where>" + condition.toXML() + "</where>";
+ result += scalarExpr.toXML() + "</condense>";
+ return result;
+ }
+
+
+
+}
diff --git a/src/syntaxParser/GetMetaDataExpr.java b/src/syntaxParser/GetMetaDataExpr.java
new file mode 100644
index 0000000..a3f5c33
--- /dev/null
+++ b/src/syntaxParser/GetMetaDataExpr.java
@@ -0,0 +1,50 @@
+package syntaxParser;
+/**
+ * GetMetaDataExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani
+ */
+class GetMetaDataExpr implements IParseTreeNode {
+ CoverageExpr coverageExpr;
+ String function;
+ String field;
+
+ /**
+ * GetMetaDataExpr constructor comment.
+ */
+ public GetMetaDataExpr() {
+ super();
+ }
+
+ public GetMetaDataExpr( String f, CoverageExpr ce){
+ coverageExpr = ce ;
+ function =f;
+ field = null;
+ }
+ public GetMetaDataExpr( String f, CoverageExpr exp, String field) {
+ coverageExpr = exp;
+ function = f;
+ this.field = field;
+ }
+
+ public String toXML() {
+ String op = "operationNotSet";
+ if (function.equals("identifier")) op = "getIdentifier";
+ if (function.equals("imageCrs")) op = "getImageCrs";
+ if (function.equals("imageCrsDomain")) op = "getImageCrsDomain"; //TODO(smsorin): The schema requires an extra parameter axis not documented in the protocol specfication
+ if (function.equals("crsSet")) op = "crsSet";
+ if (function.equals("generalDomain")) op = "getGeneralDomain"; //TODO(smsorin): The schema requires an extra parameter axis and optional* parameter crs
+ if (function.equals("nullDefault")) op = "getNullDefault";
+ if (function.equals("nullSet")) op = "getNullSet";
+ if (function.equals("interpolationDefault")) op = "getInterpolationDefault";
+ if (function.equals("interpolationSet")) op = "getInterpolationSet";
+ String result = "<" + op + ">";
+ result += coverageExpr.toXML();
+ if (field != null) {
+ result += "<field>" + field + "</field>";
+ }
+ result += "</" + op + ">";
+ return result;
+ }
+
+}
diff --git a/src/syntaxParser/IParseTreeNode.java b/src/syntaxParser/IParseTreeNode.java
new file mode 100644
index 0000000..4f59d37
--- /dev/null
+++ b/src/syntaxParser/IParseTreeNode.java
@@ -0,0 +1,9 @@
+package syntaxParser;
+/* Author: Sorin Stancu-Mara
+Date: 7 FEB 2007
+Interface that all nodes implement to simply some of the complex nodes
+*/
+
+interface IParseTreeNode {
+ public String toXML();
+}
diff --git a/src/syntaxParser/InducedExpr.java b/src/syntaxParser/InducedExpr.java
new file mode 100644
index 0000000..84c8967
--- /dev/null
+++ b/src/syntaxParser/InducedExpr.java
@@ -0,0 +1,21 @@
+package syntaxParser;
+/**
+ * InducedExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class InducedExpr implements IParseTreeNode {
+
+ IParseTreeNode expr;
+
+ public InducedExpr( IParseTreeNode e ){
+ expr =e;
+ }
+
+ public String toXML(){
+ return expr.toXML();
+ }
+
+
+
+}
diff --git a/src/syntaxParser/InterpolationMethodList.java b/src/syntaxParser/InterpolationMethodList.java
new file mode 100644
index 0000000..bfec142
--- /dev/null
+++ b/src/syntaxParser/InterpolationMethodList.java
@@ -0,0 +1,6 @@
+package syntaxParser;
+
+class InterpolationMethodList extends List {
+ public InterpolationMethodList(FieldInterpolationMethod elem) { super((IParseTreeNode)elem); }
+ public InterpolationMethodList(FieldInterpolationMethod elem, InterpolationMethodList next) { super((IParseTreeNode)elem, (List)next); }
+}
diff --git a/src/syntaxParser/JLex/CAccept.class b/src/syntaxParser/JLex/CAccept.class
new file mode 100644
index 0000000..2516677
--- /dev/null
+++ b/src/syntaxParser/JLex/CAccept.class
Binary files differ
diff --git a/src/syntaxParser/JLex/CAcceptAnchor.class b/src/syntaxParser/JLex/CAcceptAnchor.class
new file mode 100644
index 0000000..394e070
--- /dev/null
+++ b/src/syntaxParser/JLex/CAcceptAnchor.class
Binary files differ
diff --git a/src/syntaxParser/JLex/CAlloc.class b/src/syntaxParser/JLex/CAlloc.class
new file mode 100644
index 0000000..127dae9
--- /dev/null
+++ b/src/syntaxParser/JLex/CAlloc.class
Binary files differ
diff --git a/src/syntaxParser/JLex/CBunch.class b/src/syntaxParser/JLex/CBunch.class
new file mode 100644
index 0000000..f63af6f
--- /dev/null
+++ b/src/syntaxParser/JLex/CBunch.class
Binary files differ
diff --git a/src/syntaxParser/JLex/CDTrans.class b/src/syntaxParser/JLex/CDTrans.class
new file mode 100644
index 0000000..e1a8fba
--- /dev/null
+++ b/src/syntaxParser/JLex/CDTrans.class
Binary files differ
diff --git a/src/syntaxParser/JLex/CDfa.class b/src/syntaxParser/JLex/CDfa.class
new file mode 100644
index 0000000..22eb5bf
--- /dev/null
+++ b/src/syntaxParser/JLex/CDfa.class
Binary files differ
diff --git a/src/syntaxParser/JLex/CEmit.class b/src/syntaxParser/JLex/CEmit.class
new file mode 100644
index 0000000..3d0d93c
--- /dev/null
+++ b/src/syntaxParser/JLex/CEmit.class
Binary files differ
diff --git a/src/syntaxParser/JLex/CError.class b/src/syntaxParser/JLex/CError.class
new file mode 100644
index 0000000..f2f8f9d
--- /dev/null
+++ b/src/syntaxParser/JLex/CError.class
Binary files differ
diff --git a/src/syntaxParser/JLex/CInput.class b/src/syntaxParser/JLex/CInput.class
new file mode 100644
index 0000000..f83ce01
--- /dev/null
+++ b/src/syntaxParser/JLex/CInput.class
Binary files differ
diff --git a/src/syntaxParser/JLex/CLexGen.class b/src/syntaxParser/JLex/CLexGen.class
new file mode 100644
index 0000000..c26935d
--- /dev/null
+++ b/src/syntaxParser/JLex/CLexGen.class
Binary files differ
diff --git a/src/syntaxParser/JLex/CMakeNfa.class b/src/syntaxParser/JLex/CMakeNfa.class
new file mode 100644
index 0000000..7d1a6b0
--- /dev/null
+++ b/src/syntaxParser/JLex/CMakeNfa.class
Binary files differ
diff --git a/src/syntaxParser/JLex/CMinimize.class b/src/syntaxParser/JLex/CMinimize.class
new file mode 100644
index 0000000..73e0a30
--- /dev/null
+++ b/src/syntaxParser/JLex/CMinimize.class
Binary files differ
diff --git a/src/syntaxParser/JLex/CNfa.class b/src/syntaxParser/JLex/CNfa.class
new file mode 100644
index 0000000..1cdac1f
--- /dev/null
+++ b/src/syntaxParser/JLex/CNfa.class
Binary files differ
diff --git a/src/syntaxParser/JLex/CNfa2Dfa.class b/src/syntaxParser/JLex/CNfa2Dfa.class
new file mode 100644
index 0000000..691fcaf
--- /dev/null
+++ b/src/syntaxParser/JLex/CNfa2Dfa.class
Binary files differ
diff --git a/src/syntaxParser/JLex/CNfaPair.class b/src/syntaxParser/JLex/CNfaPair.class
new file mode 100644
index 0000000..b51d958
--- /dev/null
+++ b/src/syntaxParser/JLex/CNfaPair.class
Binary files differ
diff --git a/src/syntaxParser/JLex/CSet.class b/src/syntaxParser/JLex/CSet.class
new file mode 100644
index 0000000..747e900
--- /dev/null
+++ b/src/syntaxParser/JLex/CSet.class
Binary files differ
diff --git a/src/syntaxParser/JLex/CSimplifyNfa.class b/src/syntaxParser/JLex/CSimplifyNfa.class
new file mode 100644
index 0000000..67110fa
--- /dev/null
+++ b/src/syntaxParser/JLex/CSimplifyNfa.class
Binary files differ
diff --git a/src/syntaxParser/JLex/CSpec.class b/src/syntaxParser/JLex/CSpec.class
new file mode 100644
index 0000000..279418a
--- /dev/null
+++ b/src/syntaxParser/JLex/CSpec.class
Binary files differ
diff --git a/src/syntaxParser/JLex/CUtility.class b/src/syntaxParser/JLex/CUtility.class
new file mode 100644
index 0000000..a48a826
--- /dev/null
+++ b/src/syntaxParser/JLex/CUtility.class
Binary files differ
diff --git a/src/syntaxParser/JLex/Main.class b/src/syntaxParser/JLex/Main.class
new file mode 100644
index 0000000..c6fb41a
--- /dev/null
+++ b/src/syntaxParser/JLex/Main.class
Binary files differ
diff --git a/src/syntaxParser/JLex/Main.java b/src/syntaxParser/JLex/Main.java
new file mode 100644
index 0000000..89ba5bb
--- /dev/null
+++ b/src/syntaxParser/JLex/Main.java
@@ -0,0 +1,7841 @@
+/**************************************************************
+ JLex: A Lexical Analyzer Generator for Java(TM)
+ Written by Elliot Berk <ejberk@cs.princeton.edu>. Copyright 1996.
+ Maintained by C. Scott Ananian <cananian@alumni.princeton.edu>.
+ See below for copyright notice, license, and disclaimer.
+ New releases from http://www.cs.princeton.edu/~appel/modern/java/JLex/
+
+ Version 1.2.6, 2/7/03, [C. Scott Ananian]
+ Renamed 'assert' function 'ASSERT' to accomodate Java 1.4's new keyword.
+ Fixed a bug which certain forms of comment in the JLex directives section
+ (which are not allowed) to be incorrectly parsed as macro definitions.
+ Version 1.2.5, 7/25/99-5/16/00, [C. Scott Ananian]
+ Stomped on one more 8-bit character bug. Should work now (really!).
+ Added unicode support, including unicode escape sequences.
+ Rewrote internal JavaLexBitSet class as SparseBitSet for efficient
+ unicoding.
+ Added an NFA character class simplification pass for unicode efficiency.
+ Changed byte- and stream-oriented I/O routines to use characters and
+ java.io.Reader and java.io.Writer instead --- which means we read in
+ unicode specifications correctly and write out a proper unicode java
+ source file. As a happy side-effect, the output java file is written
+ with your platform's preferred newline character(s).
+ Rewrote CInput to fix bugs with line-counting in the specification file
+ and "unusual behaviour" when the last line of the specification wasn't
+ terminated with a newline. Thanks to Matt Hanna <mhanna@cs.caltech.edu>
+ for pointing out the bug.
+ Fixed a bug that would cause JLex not to terminate given certain input
+ specifications. Thanks to Mark Greenstreet <mrg@cs.ubc.ca> and
+ Frank B. Brokken <frank@suffix.icce.rug.nl> for reporting this.
+ CUP parser integration improved according to suggestions made by
+ David MacMahon <davidm@smartsc.com>. The %cup directive now tells
+ JLex to generate a parser conforming to the java_cup.runtime.Scanner
+ interface; see manual for more details.
+ Fixed bug with null string literals ("") in regexps. Reported by
+ Charles Fischer <fischer@cs.wisc.edu>.
+ Rewrote start-of-line and end-of-line handling, closing active bug #5.
+ Also fixed line-counting code, closing active bug #12. All
+ new-line handling is now platform-independent.
+ Used unpackFromString more extensively to allow larger cmap, etc,
+ tables. This helps unicode support work reliably. It's also
+ prettier now if you happen to read the source to the generated
+ lexer.
+ Generated lexer now accepts unicode LS (U+2028) and PS (U+2029) as
+ line separators for strict unicode compliance; see
+ http://www.unicode.org/unicode/reports/tr18/
+ Fixed bug with character constants in action strings. Reported by
+ Andrew Appel against 1.2.5b3.
+ Fixed bug with illegal \^C-style escape sequences. Reported by
+ Toshiya Iwai <iwai@isdnet.co.jp> against 1.2.5b4.
+ Fixed "newline in quoted string" error when unpaired single- or
+ double-quotes were present in comments in the action phrase.
+ Reported by Stephen Ostermiller <1010JLex@ostermiller.com>
+ against 1.2.5b4. Reported by Eric Esposito <eric.esposito@unh.edu>
+ against 1.2.4 and 1.2.5b2.
+ Fixed "newline in quoted string" error when /* or // appeared
+ in quoted strings in the action phrase. Reported by
+ David Eichmann <david-eichmann@uiowa.edu> against 1.2.5b5.
+ Fixed 'illegal constant' errors in case statements caused by
+ Sun's JDK 1.3 more closely adhering to the Java Language
+ Specification. Reported by a number of people, but
+ Harold Grovesteen <hgrovesteen@home.com> was the first to direct me to
+ a Sun bug report (4119776) which quoted the relevant section of the
+ JLS (15.27) to convince me that the JLex construction actually was
+ illegal. Reported against 1.2.5b6, but this bit of code has been
+ present since the very first version of JLex (1.1.1).
+
+ Version 1.2.4, 7/24/99, [C. Scott Ananian]
+ Correct the parsing of '-' in character classes, closing active
+ bug #1. Behaviour follows egrep: leading and trailing dashes in
+ a character class lose their special meaning, so [-+] and [+-] do
+ what you would expect them to.
+ New %ignorecase directive for generating case-insensitive lexers by
+ expanding matched character classes in a unicode-friendly way.
+ Handle unmatched braces in quoted strings or comments within
+ action code blocks.
+ Fixed input lexer to allow whitespace in character classes, closing
+ active bug #9. Whitespace in quotes had been previously fixed.
+ Made Yylex.YYEOF and %yyeof work like the manual says they should.
+
+ Version 1.2.3, 6/26/97, [Raimondas Lencevicius]
+ Fixed the yy_nxt[][] assignment that has generated huge code
+ exceeding 64K method size limit. Now the assignment
+ is handled by unpacking a string encoding of integer array.
+ To achieve that, added
+ "private int [][] unpackFromString(int size1, int size2, String st)"
+ function and coded the yy_nxt[][] values into a string
+ by printing integers into a string and representing
+ integer sequences as "value:length" pairs.
+ Improvement: generated .java file reduced 2 times, .class file
+ reduced 6 times for sample grammar. No 64K errors.
+ Possible negatives: Some editors and OSs may not be able to handle
+ the huge one-line generated string. String unpacking may be slower
+ than direct array initialization.
+
+ Version 1.2.2, 10/24/97, [Martin Dirichs]
+ Notes:
+ Changed yy_instream to yy_reader of type BufferedReader. This reflects
+ the improvements in the JDK 1.1 concerning InputStreams. As a
+ consequence, changed yy_buffer from byte[] to char[].
+ The lexer can now be initialized with either an InputStream
+ or a Reader. A third, private constructor is called by the other
+ two to execute user specified constructor code.
+
+ Version 1.2.1, 9/15/97 [A. Appel]
+ Fixed bugs 6 (character codes > 127) and 10 (deprecated String constructor).
+
+ Version 1.2, 5/5/97, [Elliot Berk]
+ Notes:
+ Simply changed the name from JavaLex to JLex. No other changes.
+
+ Version 1.1.5, 2/25/97, [Elliot Berk]
+ Notes:
+ Simple optimization to the creation of the source files.
+ Added a BufferedOutputStream in the creation of the DataOutputStream
+ field m_outstream of the class CLexGen. This helps performance by
+ doing some buffering, and was suggested by Max Hailperin,
+ Associate Professor of Computer Science, Gustavus Adolphus College.
+
+ Version 1.1.4, 12/12/96, [Elliot Berk]
+ Notes:
+ Added %public directive to make generated class public.
+
+ Version 1.1.3, 12/11/96, [Elliot Berk]
+ Notes:
+ Converted assertion failure on invalid character class
+ when a dash '-' is not preceded with a start-of-range character.
+ Converted this into parse error E_DASH.
+
+ Version 1.1.2, October 30, 1996 [Elliot Berk]
+ Fixed BitSet bugs by installing a BitSet class of my own,
+ called JavaLexBitSet. Fixed support for '\r', non-UNIX
+ sequences. Added try/catch block around lexer generation
+ in main routine to moderate error information presented
+ to user. Fixed macro expansion, so that macros following
+ quotes are expanded correctly in regular expressions.
+ Fixed dynamic reallocation of accept action buffers.
+
+ Version 1.1.1, September 3, 1996 [Andrew Appel]
+ Made the class "Main" instead of "JavaLex",
+ improved the installation instructions to reflect this.
+
+ Version 1.1, August 15, 1996 [Andrew Appel]
+ Made yychar, yyline, yytext global to the lexer so that
+ auxiliary functions can access them.
+ **************************************************************/
+
+/***************************************************************
+ JLEX COPYRIGHT NOTICE, LICENSE, AND DISCLAIMER
+ Copyright 1996-2000 by Elliot Joel Berk and C. Scott Ananian
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose and without fee is hereby granted,
+ provided that the above copyright notice appear in all copies and that
+ both the copyright notice and this permission notice and warranty
+ disclaimer appear in supporting documentation, and that the name of
+ the authors or their employers not be used in advertising or publicity
+ pertaining to distribution of the software without specific, written
+ prior permission.
+
+ The authors and their employers disclaim all warranties with regard to
+ this software, including all implied warranties of merchantability and
+ fitness. In no event shall the authors or their employers be liable
+ for any special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether in an
+ action of contract, negligence or other tortious action, arising out
+ of or in connection with the use or performance of this software.
+ **************************************************************/
+
+/***************************************************************
+ Package Declaration
+ **************************************************************/
+package JLex;
+
+/***************************************************************
+ Imported Packages
+ **************************************************************/
+import java.lang.System;
+import java.lang.Integer;
+import java.lang.Character;
+
+import java.util.Enumeration;
+import java.util.Stack;
+import java.util.Hashtable;
+import java.util.Vector;
+
+/******************************
+ Questions:
+ 2) How should I use the Java package system
+ to make my tool more modularized and
+ coherent?
+
+ Unimplemented:
+ !) Fix BitSet issues -- expand only when necessary.
+ 2) Repeated accept rules.
+ 6) Clean up the CAlloc class and use buffered
+ allocation.
+ 9) Add to spec about extending character set.
+ 11) m_verbose -- what should be done with it?
+ 12) turn lexical analyzer into a coherent
+ Java package
+ 13) turn lexical analyzer generator into a
+ coherent Java package
+ 16) pretty up generated code
+ 17) make it possible to have white space in
+ regular expressions
+ 18) clean up all of the class files the lexer
+ generator produces when it is compiled,
+ and reduce this number in some way.
+ 24) character format to and from file: writeup
+ and implementation
+ 25) Debug by testing all arcane regular expression cases.
+ 26) Look for and fix all UNDONE comments below.
+ 27) Fix package system.
+ 28) Clean up unnecessary classes.
+ *****************************/
+
+/***************************************************************
+ Class: CSpec
+ **************************************************************/
+class CSpec
+{
+ /***************************************************************
+ Member Variables
+ **************************************************************/
+
+ /* Lexical States. */
+ Hashtable m_states; /* Hashtable taking state indices (Integer)
+ to state name (String). */
+
+ /* Regular Expression Macros. */
+ Hashtable m_macros; /* Hashtable taking macro name (String)
+ to corresponding char buffer that
+ holds macro definition. */
+
+ /* NFA Machine. */
+ CNfa m_nfa_start; /* Start state of NFA machine. */
+ Vector m_nfa_states; /* Vector of states, with index
+ corresponding to label. */
+
+ Vector m_state_rules[]; /* An array of Vectors of Integers.
+ The ith Vector represents the lexical state
+ with index i. The contents of the ith
+ Vector are the indices of the NFA start
+ states that can be matched while in
+ the ith lexical state. */
+
+
+ int m_state_dtrans[];
+
+ /* DFA Machine. */
+ Vector m_dfa_states; /* Vector of states, with index
+ corresponding to label. */
+ Hashtable m_dfa_sets; /* Hashtable taking set of NFA states
+ to corresponding DFA state,
+ if the latter exists. */
+
+ /* Accept States and Corresponding Anchors. */
+ Vector m_accept_vector;
+ int m_anchor_array[];
+
+ /* Transition Table. */
+ Vector m_dtrans_vector;
+ int m_dtrans_ncols;
+ int m_row_map[];
+ int m_col_map[];
+
+ /* Special pseudo-characters for beginning-of-line and end-of-file. */
+ static final int NUM_PSEUDO=2;
+ int BOL; // beginning-of-line
+ int EOF; // end-of-line
+
+ /** NFA character class minimization map. */
+ int m_ccls_map[];
+
+ /* Regular expression token variables. */
+ int m_current_token;
+ char m_lexeme;
+ boolean m_in_quote;
+ boolean m_in_ccl;
+
+ /* Verbose execution flag. */
+ boolean m_verbose;
+
+ /* JLex directives flags. */
+ boolean m_integer_type;
+ boolean m_intwrap_type;
+ boolean m_yyeof;
+ boolean m_count_chars;
+ boolean m_count_lines;
+ boolean m_cup_compatible;
+ boolean m_unix;
+ boolean m_public;
+ boolean m_ignorecase;
+
+ char m_init_code[];
+ int m_init_read;
+
+ char m_init_throw_code[];
+ int m_init_throw_read;
+
+ char m_class_code[];
+ int m_class_read;
+
+ char m_eof_code[];
+ int m_eof_read;
+
+ char m_eof_value_code[];
+ int m_eof_value_read;
+
+ char m_eof_throw_code[];
+ int m_eof_throw_read;
+
+ char m_yylex_throw_code[];
+ int m_yylex_throw_read;
+
+ /* Class, function, type names. */
+ char m_class_name[] = {
+ 'Y', 'y', 'l',
+ 'e', 'x'
+ };
+ char m_implements_name[] = {};
+ char m_function_name[] = {
+ 'y', 'y', 'l',
+ 'e', 'x'
+ };
+ char m_type_name[] = {
+ 'Y', 'y', 't',
+ 'o', 'k', 'e',
+ 'n'
+ };
+
+ /* Lexical Generator. */
+ private CLexGen m_lexGen;
+
+ /***************************************************************
+ Constants
+ ***********************************************************/
+ static final int NONE = 0;
+ static final int START = 1;
+ static final int END = 2;
+
+ /***************************************************************
+ Function: CSpec
+ Description: Constructor.
+ **************************************************************/
+ CSpec
+ (
+ CLexGen lexGen
+ )
+ {
+ m_lexGen = lexGen;
+
+ /* Initialize regular expression token variables. */
+ m_current_token = m_lexGen.EOS;
+ m_lexeme = '\0';
+ m_in_quote = false;
+ m_in_ccl = false;
+
+ /* Initialize hashtable for lexer states. */
+ m_states = new Hashtable();
+ m_states.put(new String("YYINITIAL"),new Integer(m_states.size()));
+
+ /* Initialize hashtable for lexical macros. */
+ m_macros = new Hashtable();
+
+ /* Initialize variables for lexer options. */
+ m_integer_type = false;
+ m_intwrap_type = false;
+ m_count_lines = false;
+ m_count_chars = false;
+ m_cup_compatible = false;
+ m_unix = true;
+ m_public = false;
+ m_yyeof = false;
+ m_ignorecase = false;
+
+ /* Initialize variables for JLex runtime options. */
+ m_verbose = true;
+
+ m_nfa_start = null;
+ m_nfa_states = new Vector();
+
+ m_dfa_states = new Vector();
+ m_dfa_sets = new Hashtable();
+
+ m_dtrans_vector = new Vector();
+ m_dtrans_ncols = CUtility.MAX_SEVEN_BIT + 1;
+ m_row_map = null;
+ m_col_map = null;
+
+ m_accept_vector = null;
+ m_anchor_array = null;
+
+ m_init_code = null;
+ m_init_read = 0;
+
+ m_init_throw_code = null;
+ m_init_throw_read = 0;
+
+ m_yylex_throw_code = null;
+ m_yylex_throw_read = 0;
+
+ m_class_code = null;
+ m_class_read = 0;
+
+ m_eof_code = null;
+ m_eof_read = 0;
+
+ m_eof_value_code = null;
+ m_eof_value_read = 0;
+
+ m_eof_throw_code = null;
+ m_eof_throw_read = 0;
+
+ m_state_dtrans = null;
+
+ m_state_rules = null;
+ }
+}
+
+/***************************************************************
+ Class: CEmit
+ **************************************************************/
+class CEmit
+{
+ /***************************************************************
+ Member Variables
+ **************************************************************/
+ private CSpec m_spec;
+ private java.io.PrintWriter m_outstream;
+
+ /***************************************************************
+ Constants: Anchor Types
+ **************************************************************/
+ private final int START = 1;
+ private final int END = 2;
+ private final int NONE = 4;
+
+ /***************************************************************
+ Constants
+ **************************************************************/
+ private final boolean EDBG = true;
+ private final boolean NOT_EDBG = false;
+
+ /***************************************************************
+ Function: CEmit
+ Description: Constructor.
+ **************************************************************/
+ CEmit
+ (
+ )
+ {
+ reset();
+ }
+
+ /***************************************************************
+ Function: reset
+ Description: Clears member variables.
+ **************************************************************/
+ private void reset
+ (
+ )
+ {
+ m_spec = null;
+ m_outstream = null;
+ }
+
+ /***************************************************************
+ Function: set
+ Description: Initializes member variables.
+ **************************************************************/
+ private void set
+ (
+ CSpec spec,
+ java.io.PrintWriter outstream
+ )
+ {
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != spec);
+ CUtility.ASSERT(null != outstream);
+ }
+
+ m_spec = spec;
+ m_outstream = outstream;
+ }
+
+ /***************************************************************
+ Function: emit_imports
+ Description: Emits import packages at top of
+ generated source file.
+ **************************************************************/
+ /*void emit_imports
+ (
+ CSpec spec,
+ OutputStream outstream
+ )
+ throws java.io.IOException
+ {
+ set(spec,outstream);
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != m_spec);
+ CUtility.ASSERT(null != m_outstream);
+ }*/
+
+ /*m_outstream.println("import java.lang.String;");
+ m_outstream.println("import java.lang.System;");
+ m_outstream.println("import java.io.BufferedReader;");
+ m_outstream.println("import java.io.InputStream;");*/
+ /*
+ reset();
+ }*/
+
+ /***************************************************************
+ Function: print_details
+ Description: Debugging output.
+ **************************************************************/
+ private void print_details
+ (
+ )
+ {
+ int i;
+ int j;
+ int next;
+ int state;
+ CDTrans dtrans;
+ CAccept accept;
+ boolean tr;
+
+ System.out.println("---------------------- Transition Table "
+ + "----------------------");
+
+ for (i = 0; i < m_spec.m_row_map.length; ++i)
+ {
+ System.out.print("State " + i);
+
+ accept = (CAccept) m_spec.m_accept_vector.elementAt(i);
+ if (null == accept)
+ {
+ System.out.println(" [nonaccepting]");
+ }
+ else
+ {
+ System.out.println(" [accepting, line "
+ + accept.m_line_number
+ + " <"
+ + (new java.lang.String(accept.m_action,0,
+ accept.m_action_read))
+ + ">]");
+ }
+ dtrans = (CDTrans) m_spec.m_dtrans_vector.elementAt(m_spec.m_row_map[i]);
+
+ tr = false;
+ state = dtrans.m_dtrans[m_spec.m_col_map[0]];
+ if (CDTrans.F != state)
+ {
+ tr = true;
+ System.out.print("\tgoto " + state + " on [" + ((char) 0));
+ }
+ for (j = 1; j < m_spec.m_dtrans_ncols; ++j)
+ {
+ next = dtrans.m_dtrans[m_spec.m_col_map[j]];
+ if (state == next)
+ {
+ if (CDTrans.F != state)
+ {
+ System.out.print((char) j);
+ }
+ }
+ else
+ {
+ state = next;
+ if (tr)
+ {
+ System.out.println("]");
+ tr = false;
+ }
+ if (CDTrans.F != state)
+ {
+ tr = true;
+ System.out.print("\tgoto " + state + " on [" + ((char) j));
+ }
+ }
+ }
+ if (tr)
+ {
+ System.out.println("]");
+ }
+ }
+
+ System.out.println("---------------------- Transition Table "
+ + "----------------------");
+ }
+
+ /***************************************************************
+ Function: emit
+ Description: High-level access function to module.
+ **************************************************************/
+ void emit
+ (
+ CSpec spec,
+ java.io.PrintWriter outstream
+ )
+ throws java.io.IOException
+ {
+ set(spec,outstream);
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != m_spec);
+ CUtility.ASSERT(null != m_outstream);
+ }
+
+ if (CUtility.OLD_DEBUG) {
+ print_details();
+ }
+
+ emit_header();
+ emit_construct();
+ emit_helpers();
+ emit_driver();
+ emit_footer();
+
+ reset();
+ }
+
+ /***************************************************************
+ Function: emit_construct
+ Description: Emits constructor, member variables,
+ and constants.
+ **************************************************************/
+ private void emit_construct
+ (
+ )
+ throws java.io.IOException
+ {
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != m_spec);
+ CUtility.ASSERT(null != m_outstream);
+ }
+
+ /* Constants */
+ m_outstream.println("\tprivate final int YY_BUFFER_SIZE = 512;");
+
+ m_outstream.println("\tprivate final int YY_F = -1;");
+ m_outstream.println("\tprivate final int YY_NO_STATE = -1;");
+
+ m_outstream.println("\tprivate final int YY_NOT_ACCEPT = 0;");
+ m_outstream.println("\tprivate final int YY_START = 1;");
+ m_outstream.println("\tprivate final int YY_END = 2;");
+ m_outstream.println("\tprivate final int YY_NO_ANCHOR = 4;");
+
+ // internal
+ m_outstream.println("\tprivate final int YY_BOL = "+m_spec.BOL+";");
+ m_outstream.println("\tprivate final int YY_EOF = "+m_spec.EOF+";");
+ // external
+ if (m_spec.m_integer_type || true == m_spec.m_yyeof)
+ m_outstream.println("\tpublic final int YYEOF = -1;");
+
+ /* User specified class code. */
+ if (null != m_spec.m_class_code)
+ {
+ m_outstream.print(new String(m_spec.m_class_code,0,
+ m_spec.m_class_read));
+ }
+
+ /* Member Variables */
+ m_outstream.println("\tprivate java.io.BufferedReader yy_reader;");
+ m_outstream.println("\tprivate int yy_buffer_index;");
+ m_outstream.println("\tprivate int yy_buffer_read;");
+ m_outstream.println("\tprivate int yy_buffer_start;");
+ m_outstream.println("\tprivate int yy_buffer_end;");
+ m_outstream.println("\tprivate char yy_buffer[];");
+ if (m_spec.m_count_chars)
+ {
+ m_outstream.println("\tprivate int yychar;");
+ }
+ if (m_spec.m_count_lines)
+ {
+ m_outstream.println("\tprivate int yyline;");
+ }
+ m_outstream.println("\tprivate boolean yy_at_bol;");
+ m_outstream.println("\tprivate int yy_lexical_state;");
+ /*if (m_spec.m_count_lines || true == m_spec.m_count_chars)
+ {
+ m_outstream.println("\tprivate int yy_buffer_prev_start;");
+ }*/
+ m_outstream.println();
+
+
+ /* Function: first constructor (Reader) */
+ m_outstream.print("\t");
+ if (true == m_spec.m_public) {
+ m_outstream.print("public ");
+ }
+ m_outstream.print(new String(m_spec.m_class_name));
+ m_outstream.print(" (java.io.Reader reader)");
+
+ if (null != m_spec.m_init_throw_code)
+ {
+ m_outstream.println();
+ m_outstream.print("\t\tthrows ");
+ m_outstream.print(new String(m_spec.m_init_throw_code,0,
+ m_spec.m_init_throw_read));
+ m_outstream.println();
+ m_outstream.println("\t\t{");
+ }
+ else
+ {
+ m_outstream.println(" {");
+ }
+
+ m_outstream.println("\t\tthis ();");
+ m_outstream.println("\t\tif (null == reader) {");
+ m_outstream.println("\t\t\tthrow (new Error(\"Error: Bad input "
+ + "stream initializer.\"));");
+ m_outstream.println("\t\t}");
+ m_outstream.println("\t\tyy_reader = new java.io.BufferedReader(reader);");
+ m_outstream.println("\t}");
+ m_outstream.println();
+
+
+ /* Function: second constructor (InputStream) */
+ m_outstream.print("\t");
+ if (true == m_spec.m_public) {
+ m_outstream.print("public ");
+ }
+ m_outstream.print(new String(m_spec.m_class_name));
+ m_outstream.print(" (java.io.InputStream instream)");
+
+ if (null != m_spec.m_init_throw_code)
+ {
+ m_outstream.println();
+ m_outstream.print("\t\tthrows ");
+ m_outstream.println(new String(m_spec.m_init_throw_code,0,
+ m_spec.m_init_throw_read));
+ m_outstream.println("\t\t{");
+ }
+ else
+ {
+ m_outstream.println(" {");
+ }
+
+ m_outstream.println("\t\tthis ();");
+ m_outstream.println("\t\tif (null == instream) {");
+ m_outstream.println("\t\t\tthrow (new Error(\"Error: Bad input "
+ + "stream initializer.\"));");
+ m_outstream.println("\t\t}");
+ m_outstream.println("\t\tyy_reader = new java.io.BufferedReader(new java.io.InputStreamReader(instream));");
+ m_outstream.println("\t}");
+ m_outstream.println();
+
+
+ /* Function: third, private constructor - only for internal use */
+ m_outstream.print("\tprivate ");
+ m_outstream.print(new String(m_spec.m_class_name));
+ m_outstream.print(" ()");
+
+ if (null != m_spec.m_init_throw_code)
+ {
+ m_outstream.println();
+ m_outstream.print("\t\tthrows ");
+ m_outstream.println(new String(m_spec.m_init_throw_code,0,
+ m_spec.m_init_throw_read));
+ m_outstream.println("\t\t{");
+ }
+ else
+ {
+ m_outstream.println(" {");
+ }
+
+ m_outstream.println("\t\tyy_buffer = new char[YY_BUFFER_SIZE];");
+ m_outstream.println("\t\tyy_buffer_read = 0;");
+ m_outstream.println("\t\tyy_buffer_index = 0;");
+ m_outstream.println("\t\tyy_buffer_start = 0;");
+ m_outstream.println("\t\tyy_buffer_end = 0;");
+ if (m_spec.m_count_chars)
+ {
+ m_outstream.println("\t\tyychar = 0;");
+ }
+ if (m_spec.m_count_lines)
+ {
+ m_outstream.println("\t\tyyline = 0;");
+ }
+ m_outstream.println("\t\tyy_at_bol = true;");
+ m_outstream.println("\t\tyy_lexical_state = YYINITIAL;");
+ /*if (m_spec.m_count_lines || true == m_spec.m_count_chars)
+ {
+ m_outstream.println("\t\tyy_buffer_prev_start = 0;");
+ }*/
+
+ /* User specified constructor code. */
+ if (null != m_spec.m_init_code)
+ {
+ m_outstream.print(new String(m_spec.m_init_code,0,
+ m_spec.m_init_read));
+ }
+
+ m_outstream.println("\t}");
+ m_outstream.println();
+
+ }
+
+ /***************************************************************
+ Function: emit_states
+ Description: Emits constants that serve as lexical states,
+ including YYINITIAL.
+ **************************************************************/
+ private void emit_states
+ (
+ )
+ throws java.io.IOException
+ {
+ Enumeration states;
+ String state;
+ int index;
+
+ states = m_spec.m_states.keys();
+ /*index = 0;*/
+ while (states.hasMoreElements())
+ {
+ state = (String) states.nextElement();
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != state);
+ }
+
+ m_outstream.println("\tprivate final int "
+ + state
+ + " = "
+ + (m_spec.m_states.get(state)).toString()
+ + ";");
+ /*++index;*/
+ }
+
+ m_outstream.println("\tprivate final int yy_state_dtrans[] = {");
+ for (index = 0; index < m_spec.m_state_dtrans.length; ++index)
+ {
+ m_outstream.print("\t\t" + m_spec.m_state_dtrans[index]);
+ if (index < m_spec.m_state_dtrans.length - 1)
+ {
+ m_outstream.println(",");
+ }
+ else
+ {
+ m_outstream.println();
+ }
+ }
+ m_outstream.println("\t};");
+ }
+
+ /***************************************************************
+ Function: emit_helpers
+ Description: Emits helper functions, particularly
+ error handling and input buffering.
+ **************************************************************/
+ private void emit_helpers
+ (
+ )
+ throws java.io.IOException
+ {
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != m_spec);
+ CUtility.ASSERT(null != m_outstream);
+ }
+
+ /* Function: yy_do_eof */
+ m_outstream.println("\tprivate boolean yy_eof_done = false;");
+ if (null != m_spec.m_eof_code)
+ {
+ m_outstream.print("\tprivate void yy_do_eof ()");
+
+ if (null != m_spec.m_eof_throw_code)
+ {
+ m_outstream.println();
+ m_outstream.print("\t\tthrows ");
+ m_outstream.println(new String(m_spec.m_eof_throw_code,0,
+ m_spec.m_eof_throw_read));
+ m_outstream.println("\t\t{");
+ }
+ else
+ {
+ m_outstream.println(" {");
+ }
+
+ m_outstream.println("\t\tif (false == yy_eof_done) {");
+ m_outstream.print(new String(m_spec.m_eof_code,0,
+ m_spec.m_eof_read));
+ m_outstream.println("\t\t}");
+ m_outstream.println("\t\tyy_eof_done = true;");
+ m_outstream.println("\t}");
+ }
+
+ emit_states();
+
+ /* Function: yybegin */
+ m_outstream.println("\tprivate void yybegin (int state) {");
+ m_outstream.println("\t\tyy_lexical_state = state;");
+ m_outstream.println("\t}");
+
+ /* Function: yy_initial_dtrans */
+ /*m_outstream.println("\tprivate int yy_initial_dtrans (int state) {");
+ m_outstream.println("\t\treturn yy_state_dtrans[state];");
+ m_outstream.println("\t}");*/
+
+ /* Function: yy_advance */
+ m_outstream.println("\tprivate int yy_advance ()");
+ m_outstream.println("\t\tthrows java.io.IOException {");
+ /*m_outstream.println("\t\t{");*/
+ m_outstream.println("\t\tint next_read;");
+ m_outstream.println("\t\tint i;");
+ m_outstream.println("\t\tint j;");
+ m_outstream.println();
+
+ m_outstream.println("\t\tif (yy_buffer_index < yy_buffer_read) {");
+ m_outstream.println("\t\t\treturn yy_buffer[yy_buffer_index++];");
+ /*m_outstream.println("\t\t\t++yy_buffer_index;");*/
+ m_outstream.println("\t\t}");
+ m_outstream.println();
+
+ m_outstream.println("\t\tif (0 != yy_buffer_start) {");
+ m_outstream.println("\t\t\ti = yy_buffer_start;");
+ m_outstream.println("\t\t\tj = 0;");
+ m_outstream.println("\t\t\twhile (i < yy_buffer_read) {");
+ m_outstream.println("\t\t\t\tyy_buffer[j] = yy_buffer[i];");
+ m_outstream.println("\t\t\t\t++i;");
+ m_outstream.println("\t\t\t\t++j;");
+ m_outstream.println("\t\t\t}");
+ m_outstream.println("\t\t\tyy_buffer_end = yy_buffer_end - yy_buffer_start;");
+ m_outstream.println("\t\t\tyy_buffer_start = 0;");
+ m_outstream.println("\t\t\tyy_buffer_read = j;");
+ m_outstream.println("\t\t\tyy_buffer_index = j;");
+ m_outstream.println("\t\t\tnext_read = yy_reader.read(yy_buffer,");
+ m_outstream.println("\t\t\t\t\tyy_buffer_read,");
+ m_outstream.println("\t\t\t\t\tyy_buffer.length - yy_buffer_read);");
+ m_outstream.println("\t\t\tif (-1 == next_read) {");
+ m_outstream.println("\t\t\t\treturn YY_EOF;");
+ m_outstream.println("\t\t\t}");
+ m_outstream.println("\t\t\tyy_buffer_read = yy_buffer_read + next_read;");
+ m_outstream.println("\t\t}");
+ m_outstream.println();
+
+ m_outstream.println("\t\twhile (yy_buffer_index >= yy_buffer_read) {");
+ m_outstream.println("\t\t\tif (yy_buffer_index >= yy_buffer.length) {");
+ m_outstream.println("\t\t\t\tyy_buffer = yy_double(yy_buffer);");
+ m_outstream.println("\t\t\t}");
+ m_outstream.println("\t\t\tnext_read = yy_reader.read(yy_buffer,");
+ m_outstream.println("\t\t\t\t\tyy_buffer_read,");
+ m_outstream.println("\t\t\t\t\tyy_buffer.length - yy_buffer_read);");
+ m_outstream.println("\t\t\tif (-1 == next_read) {");
+ m_outstream.println("\t\t\t\treturn YY_EOF;");
+ m_outstream.println("\t\t\t}");
+ m_outstream.println("\t\t\tyy_buffer_read = yy_buffer_read + next_read;");
+ m_outstream.println("\t\t}");
+
+ m_outstream.println("\t\treturn yy_buffer[yy_buffer_index++];");
+ m_outstream.println("\t}");
+
+ /* Function: yy_move_end */
+ m_outstream.println("\tprivate void yy_move_end () {");
+ m_outstream.println("\t\tif (yy_buffer_end > yy_buffer_start &&");
+ m_outstream.println("\t\t '\\n' == yy_buffer[yy_buffer_end-1])");
+ m_outstream.println("\t\t\tyy_buffer_end--;");
+ m_outstream.println("\t\tif (yy_buffer_end > yy_buffer_start &&");
+ m_outstream.println("\t\t '\\r' == yy_buffer[yy_buffer_end-1])");
+ m_outstream.println("\t\t\tyy_buffer_end--;");
+ m_outstream.println("\t}");
+
+ /* Function: yy_mark_start */
+ m_outstream.println("\tprivate boolean yy_last_was_cr=false;");
+ m_outstream.println("\tprivate void yy_mark_start () {");
+ if (m_spec.m_count_lines || true == m_spec.m_count_chars)
+ {
+ if (m_spec.m_count_lines)
+ {
+ m_outstream.println("\t\tint i;");
+ m_outstream.println("\t\tfor (i = yy_buffer_start; "
+ + "i < yy_buffer_index; ++i) {");
+ m_outstream.println("\t\t\tif ('\\n' == yy_buffer[i] && !yy_last_was_cr) {");
+ m_outstream.println("\t\t\t\t++yyline;");
+ m_outstream.println("\t\t\t}");
+ m_outstream.println("\t\t\tif ('\\r' == yy_buffer[i]) {");
+ m_outstream.println("\t\t\t\t++yyline;");
+ m_outstream.println("\t\t\t\tyy_last_was_cr=true;");
+ m_outstream.println("\t\t\t} else yy_last_was_cr=false;");
+ m_outstream.println("\t\t}");
+ }
+ if (m_spec.m_count_chars)
+ {
+ m_outstream.println("\t\tyychar = yychar");
+ m_outstream.println("\t\t\t+ yy_buffer_index - yy_buffer_start;");
+ }
+ }
+ m_outstream.println("\t\tyy_buffer_start = yy_buffer_index;");
+ m_outstream.println("\t}");
+
+ /* Function: yy_mark_end */
+ m_outstream.println("\tprivate void yy_mark_end () {");
+ m_outstream.println("\t\tyy_buffer_end = yy_buffer_index;");
+ m_outstream.println("\t}");
+
+ /* Function: yy_to_mark */
+ m_outstream.println("\tprivate void yy_to_mark () {");
+ m_outstream.println("\t\tyy_buffer_index = yy_buffer_end;");
+ m_outstream.println("\t\tyy_at_bol = "+
+ "(yy_buffer_end > yy_buffer_start) &&");
+ m_outstream.println("\t\t "+
+ "('\\r' == yy_buffer[yy_buffer_end-1] ||");
+ m_outstream.println("\t\t "+
+ " '\\n' == yy_buffer[yy_buffer_end-1] ||");
+ m_outstream.println("\t\t "+ /* unicode LS */
+ " 2028/*LS*/ == yy_buffer[yy_buffer_end-1] ||");
+ m_outstream.println("\t\t "+ /* unicode PS */
+ " 2029/*PS*/ == yy_buffer[yy_buffer_end-1]);");
+ m_outstream.println("\t}");
+
+ /* Function: yytext */
+ m_outstream.println("\tprivate java.lang.String yytext () {");
+ m_outstream.println("\t\treturn (new java.lang.String(yy_buffer,");
+ m_outstream.println("\t\t\tyy_buffer_start,");
+ m_outstream.println("\t\t\tyy_buffer_end - yy_buffer_start));");
+ m_outstream.println("\t}");
+
+ /* Function: yylength */
+ m_outstream.println("\tprivate int yylength () {");
+ m_outstream.println("\t\treturn yy_buffer_end - yy_buffer_start;");
+ m_outstream.println("\t}");
+
+ /* Function: yy_double */
+ m_outstream.println("\tprivate char[] yy_double (char buf[]) {");
+ m_outstream.println("\t\tint i;");
+ m_outstream.println("\t\tchar newbuf[];");
+ m_outstream.println("\t\tnewbuf = new char[2*buf.length];");
+ m_outstream.println("\t\tfor (i = 0; i < buf.length; ++i) {");
+ m_outstream.println("\t\t\tnewbuf[i] = buf[i];");
+ m_outstream.println("\t\t}");
+ m_outstream.println("\t\treturn newbuf;");
+ m_outstream.println("\t}");
+
+ /* Function: yy_error */
+ m_outstream.println("\tprivate final int YY_E_INTERNAL = 0;");
+ m_outstream.println("\tprivate final int YY_E_MATCH = 1;");
+ m_outstream.println("\tprivate java.lang.String yy_error_string[] = {");
+ m_outstream.println("\t\t\"Error: Internal error.\\n\",");
+ m_outstream.println("\t\t\"Error: Unmatched input.\\n\"");
+ m_outstream.println("\t};");
+ m_outstream.println("\tprivate void yy_error (int code,boolean fatal) {");
+ m_outstream.println("\t\tjava.lang.System.out.print(yy_error_string[code]);");
+ m_outstream.println("\t\tjava.lang.System.out.flush();");
+ m_outstream.println("\t\tif (fatal) {");
+ m_outstream.println("\t\t\tthrow new Error(\"Fatal Error.\\n\");");
+ m_outstream.println("\t\t}");
+ m_outstream.println("\t}");
+
+ /* Function: yy_next */
+ /*m_outstream.println("\tprivate int yy_next (int current,char lookahead) {");
+ m_outstream.println("\t\treturn yy_nxt[yy_rmap[current]][yy_cmap[lookahead]];");
+ m_outstream.println("\t}");*/
+
+ /* Function: yy_accept */
+ /*m_outstream.println("\tprivate int yy_accept (int current) {");
+ m_outstream.println("\t\treturn yy_acpt[current];");
+ m_outstream.println("\t}");*/
+
+
+ // Function: private int [][] unpackFromString(int size1, int size2, String st)
+ // Added 6/24/98 Raimondas Lencevicius
+ // May be made more efficient by replacing String operations
+ // Assumes correctly formed input String. Performs no error checking
+ m_outstream.println("\tprivate int[][] unpackFromString"+
+ "(int size1, int size2, String st) {");
+ m_outstream.println("\t\tint colonIndex = -1;");
+ m_outstream.println("\t\tString lengthString;");
+ m_outstream.println("\t\tint sequenceLength = 0;");
+ m_outstream.println("\t\tint sequenceInteger = 0;");
+ m_outstream.println();
+ m_outstream.println("\t\tint commaIndex;");
+ m_outstream.println("\t\tString workString;");
+ m_outstream.println();
+ m_outstream.println("\t\tint res[][] = new int[size1][size2];");
+ m_outstream.println("\t\tfor (int i= 0; i < size1; i++) {");
+ m_outstream.println("\t\t\tfor (int j= 0; j < size2; j++) {");
+ m_outstream.println("\t\t\t\tif (sequenceLength != 0) {");
+ m_outstream.println("\t\t\t\t\tres[i][j] = sequenceInteger;");
+ m_outstream.println("\t\t\t\t\tsequenceLength--;");
+ m_outstream.println("\t\t\t\t\tcontinue;");
+ m_outstream.println("\t\t\t\t}");
+ m_outstream.println("\t\t\t\tcommaIndex = st.indexOf(',');");
+ m_outstream.println("\t\t\t\tworkString = (commaIndex==-1) ? st :");
+ m_outstream.println("\t\t\t\t\tst.substring(0, commaIndex);");
+ m_outstream.println("\t\t\t\tst = st.substring(commaIndex+1);");
+ m_outstream.println("\t\t\t\tcolonIndex = workString.indexOf(':');");
+ m_outstream.println("\t\t\t\tif (colonIndex == -1) {");
+ m_outstream.println("\t\t\t\t\tres[i][j]=Integer.parseInt(workString);");
+ m_outstream.println("\t\t\t\t\tcontinue;");
+ m_outstream.println("\t\t\t\t}");
+ m_outstream.println("\t\t\t\tlengthString =");
+ m_outstream.println("\t\t\t\t\tworkString.substring(colonIndex+1);");
+ m_outstream.println("\t\t\t\tsequenceLength="+
+ "Integer.parseInt(lengthString);");
+ m_outstream.println("\t\t\t\tworkString="+
+ "workString.substring(0,colonIndex);");
+ m_outstream.println("\t\t\t\tsequenceInteger="+
+ "Integer.parseInt(workString);");
+ m_outstream.println("\t\t\t\tres[i][j] = sequenceInteger;");
+ m_outstream.println("\t\t\t\tsequenceLength--;");
+ m_outstream.println("\t\t\t}");
+ m_outstream.println("\t\t}");
+ m_outstream.println("\t\treturn res;");
+ m_outstream.println("\t}");
+ }
+
+ /***************************************************************
+ Function: emit_header
+ Description: Emits class header.
+ **************************************************************/
+ private void emit_header
+ (
+ )
+ throws java.io.IOException
+ {
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != m_spec);
+ CUtility.ASSERT(null != m_outstream);
+ }
+
+ m_outstream.println();
+ m_outstream.println();
+ if (true == m_spec.m_public) {
+ m_outstream.print("public ");
+ }
+ m_outstream.print("class ");
+ m_outstream.print(new String(m_spec.m_class_name,0,
+ m_spec.m_class_name.length));
+ if (m_spec.m_implements_name.length > 0) {
+ m_outstream.print(" implements ");
+ m_outstream.print(new String(m_spec.m_implements_name,0,
+ m_spec.m_implements_name.length));
+ }
+ m_outstream.println(" {");
+ }
+
+ /***************************************************************
+ Function: emit_table
+ Description: Emits transition table.
+ **************************************************************/
+ private void emit_table
+ (
+ )
+ throws java.io.IOException
+ {
+ int i;
+ int elem;
+ int size;
+ CDTrans dtrans;
+ boolean is_start;
+ boolean is_end;
+ CAccept accept;
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != m_spec);
+ CUtility.ASSERT(null != m_outstream);
+ }
+
+ m_outstream.println("\tprivate int yy_acpt[] = {");
+ size = m_spec.m_accept_vector.size();
+ for (elem = 0; elem < size; ++elem)
+ {
+ accept = (CAccept) m_spec.m_accept_vector.elementAt(elem);
+
+ m_outstream.print("\t\t/* "+elem+" */ ");
+ if (null != accept)
+ {
+ is_start = (0 != (m_spec.m_anchor_array[elem] & CSpec.START));
+ is_end = (0 != (m_spec.m_anchor_array[elem] & CSpec.END));
+
+ if (is_start && true == is_end)
+ {
+ m_outstream.print("YY_START | YY_END");
+ }
+ else if (is_start)
+ {
+ m_outstream.print("YY_START");
+ }
+ else if (is_end)
+ {
+ m_outstream.print("YY_END");
+ }
+ else
+ {
+ m_outstream.print("YY_NO_ANCHOR");
+ }
+ }
+ else
+ {
+ m_outstream.print("YY_NOT_ACCEPT");
+ }
+
+ if (elem < size - 1)
+ {
+ m_outstream.print(",");
+ }
+
+ m_outstream.println();
+ }
+ m_outstream.println("\t};");
+
+ // CSA: modified yy_cmap to use string packing 9-Aug-1999
+ int[] yy_cmap = new int[m_spec.m_ccls_map.length];
+ for (i = 0; i < m_spec.m_ccls_map.length; ++i)
+ yy_cmap[i] = m_spec.m_col_map[m_spec.m_ccls_map[i]];
+ m_outstream.print("\tprivate int yy_cmap[] = unpackFromString(");
+ emit_table_as_string(new int[][] { yy_cmap });
+ m_outstream.println(")[0];");
+ m_outstream.println();
+
+ // CSA: modified yy_rmap to use string packing 9-Aug-1999
+ m_outstream.print("\tprivate int yy_rmap[] = unpackFromString(");
+ emit_table_as_string(new int[][] { m_spec.m_row_map });
+ m_outstream.println(")[0];");
+ m_outstream.println();
+
+ // 6/24/98 Raimondas Lencevicius
+ // modified to use
+ // int[][] unpackFromString(int size1, int size2, String st)
+ size = m_spec.m_dtrans_vector.size();
+ int[][] yy_nxt = new int[size][];
+ for (elem=0; elem<size; elem++) {
+ dtrans = (CDTrans) m_spec.m_dtrans_vector.elementAt(elem);
+ CUtility.ASSERT(dtrans.m_dtrans.length==m_spec.m_dtrans_ncols);
+ yy_nxt[elem] = dtrans.m_dtrans;
+ }
+ m_outstream.print
+ ("\tprivate int yy_nxt[][] = unpackFromString(");
+ emit_table_as_string(yy_nxt);
+ m_outstream.println(");");
+ m_outstream.println();
+ }
+
+ /***************************************************************
+ Function: emit_driver
+ Description: Output an integer table as a string. Written by
+ Raimondas Lencevicius 6/24/98; reorganized by CSA 9-Aug-1999.
+ From his original comments:
+ yy_nxt[][] values are coded into a string
+ by printing integers and representing
+ integer sequences as "value:length" pairs.
+ **************************************************************/
+ private void emit_table_as_string(int[][] ia) {
+ int sequenceLength = 0; // RL - length of the number sequence
+ boolean sequenceStarted = false; // RL - has number sequence started?
+ int previousInt = -20; // RL - Bogus -20 state.
+
+ // RL - Output matrix size
+ m_outstream.print(ia.length);
+ m_outstream.print(",");
+ m_outstream.print(ia.length>0?ia[0].length:0);
+ m_outstream.println(",");
+
+ StringBuffer outstr = new StringBuffer();
+
+ // RL - Output matrix
+ for (int elem = 0; elem < ia.length; ++elem)
+ {
+ for (int i = 0; i < ia[elem].length; ++i)
+ {
+ int writeInt = ia[elem][i];
+ if (writeInt == previousInt) // RL - sequence?
+ {
+ if (sequenceStarted)
+ {
+ sequenceLength++;
+ }
+ else
+ {
+ outstr.append(writeInt);
+ outstr.append(":");
+ sequenceLength = 2;
+ sequenceStarted = true;
+ }
+ }
+ else // RL - no sequence or end sequence
+ {
+ if (sequenceStarted)
+ {
+ outstr.append(sequenceLength);
+ outstr.append(",");
+ sequenceLength = 0;
+ sequenceStarted = false;
+ }
+ else
+ {
+ if (previousInt != -20)
+ {
+ outstr.append(previousInt);
+ outstr.append(",");
+ }
+ }
+ }
+ previousInt = writeInt;
+ // CSA: output in 75 character chunks.
+ if (outstr.length() > 75) {
+ String s = outstr.toString();
+ m_outstream.println("\""+s.substring(0,75)+"\" +");
+ outstr = new StringBuffer(s.substring(75));
+ }
+ }
+ }
+ if (sequenceStarted)
+ {
+ outstr.append(sequenceLength);
+ }
+ else
+ {
+ outstr.append(previousInt);
+ }
+ // CSA: output in 75 character chunks.
+ if (outstr.length() > 75) {
+ String s = outstr.toString();
+ m_outstream.println("\""+s.substring(0,75)+"\" +");
+ outstr = new StringBuffer(s.substring(75));
+ }
+ m_outstream.print("\""+outstr+"\"");
+ }
+
+ /***************************************************************
+ Function: emit_driver
+ Description:
+ **************************************************************/
+ private void emit_driver
+ (
+ )
+ throws java.io.IOException
+ {
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != m_spec);
+ CUtility.ASSERT(null != m_outstream);
+ }
+
+ emit_table();
+
+ if (m_spec.m_integer_type)
+ {
+ m_outstream.print("\tpublic int ");
+ m_outstream.print(new String(m_spec.m_function_name));
+ m_outstream.println(" ()");
+ }
+ else if (m_spec.m_intwrap_type)
+ {
+ m_outstream.print("\tpublic java.lang.Integer ");
+ m_outstream.print(new String(m_spec.m_function_name));
+ m_outstream.println(" ()");
+ }
+ else
+ {
+ m_outstream.print("\tpublic ");
+ m_outstream.print(new String(m_spec.m_type_name));
+ m_outstream.print(" ");
+ m_outstream.print(new String(m_spec.m_function_name));
+ m_outstream.println(" ()");
+ }
+
+ /*m_outstream.println("\t\tthrows java.io.IOException {");*/
+ m_outstream.print("\t\tthrows java.io.IOException");
+ if (null != m_spec.m_yylex_throw_code)
+ {
+ m_outstream.print(", ");
+ m_outstream.print(new String(m_spec.m_yylex_throw_code,0,
+ m_spec.m_yylex_throw_read));
+ m_outstream.println();
+ m_outstream.println("\t\t{");
+ }
+ else
+ {
+ m_outstream.println(" {");
+ }
+
+ m_outstream.println("\t\tint yy_lookahead;");
+ m_outstream.println("\t\tint yy_anchor = YY_NO_ANCHOR;");
+ /*m_outstream.println("\t\tint yy_state "
+ + "= yy_initial_dtrans(yy_lexical_state);");*/
+ m_outstream.println("\t\tint yy_state "
+ + "= yy_state_dtrans[yy_lexical_state];");
+ m_outstream.println("\t\tint yy_next_state = YY_NO_STATE;");
+ /*m_outstream.println("\t\tint yy_prev_stave = YY_NO_STATE;");*/
+ m_outstream.println("\t\tint yy_last_accept_state = YY_NO_STATE;");
+ m_outstream.println("\t\tboolean yy_initial = true;");
+ m_outstream.println("\t\tint yy_this_accept;");
+ m_outstream.println();
+
+ m_outstream.println("\t\tyy_mark_start();");
+ /*m_outstream.println("\t\tyy_this_accept = yy_accept(yy_state);");*/
+ m_outstream.println("\t\tyy_this_accept = yy_acpt[yy_state];");
+ m_outstream.println("\t\tif (YY_NOT_ACCEPT != yy_this_accept) {");
+ m_outstream.println("\t\t\tyy_last_accept_state = yy_state;");
+ m_outstream.println("\t\t\tyy_mark_end();");
+ m_outstream.println("\t\t}");
+
+ if (NOT_EDBG)
+ {
+ m_outstream.println("\t\tjava.lang.System.out.println(\"Begin\");");
+ }
+
+ m_outstream.println("\t\twhile (true) {");
+
+ m_outstream.println("\t\t\tif (yy_initial && yy_at_bol) "+
+ "yy_lookahead = YY_BOL;");
+ m_outstream.println("\t\t\telse yy_lookahead = yy_advance();");
+ m_outstream.println("\t\t\tyy_next_state = YY_F;");
+ /*m_outstream.println("\t\t\t\tyy_next_state = "
+ + "yy_next(yy_state,yy_lookahead);");*/
+ m_outstream.println("\t\t\tyy_next_state = "
+ + "yy_nxt[yy_rmap[yy_state]][yy_cmap[yy_lookahead]];");
+
+ if (NOT_EDBG)
+ {
+ m_outstream.println("java.lang.System.out.println(\"Current state: \""
+ + " + yy_state");
+ m_outstream.println("+ \"\tCurrent input: \"");
+ m_outstream.println(" + ((char) yy_lookahead));");
+ }
+ if (NOT_EDBG)
+ {
+ m_outstream.println("\t\t\tjava.lang.System.out.println(\"State = \""
+ + "+ yy_state);");
+ m_outstream.println("\t\t\tjava.lang.System.out.println(\"Accepting status = \""
+ + "+ yy_this_accept);");
+ m_outstream.println("\t\t\tjava.lang.System.out.println(\"Last accepting state = \""
+ + "+ yy_last_accept_state);");
+ m_outstream.println("\t\t\tjava.lang.System.out.println(\"Next state = \""
+ + "+ yy_next_state);");
+ m_outstream.println("\t\t\tjava.lang.System.out.println(\"Lookahead input = \""
+ + "+ ((char) yy_lookahead));");
+ }
+
+ // handle bare EOF.
+ m_outstream.println("\t\t\tif (YY_EOF == yy_lookahead "
+ + "&& true == yy_initial) {");
+ if (null != m_spec.m_eof_code)
+ {
+ m_outstream.println("\t\t\t\tyy_do_eof();");
+ }
+ if (true == m_spec.m_integer_type)
+ {
+ m_outstream.println("\t\t\t\treturn YYEOF;");
+ }
+ else if (null != m_spec.m_eof_value_code)
+ {
+ m_outstream.print(new String(m_spec.m_eof_value_code,0,
+ m_spec.m_eof_value_read));
+ }
+ else
+ {
+ m_outstream.println("\t\t\t\treturn null;");
+ }
+ m_outstream.println("\t\t\t}");
+
+ m_outstream.println("\t\t\tif (YY_F != yy_next_state) {");
+ m_outstream.println("\t\t\t\tyy_state = yy_next_state;");
+ m_outstream.println("\t\t\t\tyy_initial = false;");
+ /*m_outstream.println("\t\t\t\tyy_this_accept = yy_accept(yy_state);");*/
+ m_outstream.println("\t\t\t\tyy_this_accept = yy_acpt[yy_state];");
+ m_outstream.println("\t\t\t\tif (YY_NOT_ACCEPT != yy_this_accept) {");
+ m_outstream.println("\t\t\t\t\tyy_last_accept_state = yy_state;");
+ m_outstream.println("\t\t\t\t\tyy_mark_end();");
+ m_outstream.println("\t\t\t\t}");
+ /*m_outstream.println("\t\t\t\tyy_prev_state = yy_state;");*/
+ /*m_outstream.println("\t\t\t\tyy_state = yy_next_state;");*/
+ m_outstream.println("\t\t\t}");
+
+ m_outstream.println("\t\t\telse {");
+
+ m_outstream.println("\t\t\t\tif (YY_NO_STATE == yy_last_accept_state) {");
+
+
+ /*m_outstream.println("\t\t\t\t\tyy_error(YY_E_MATCH,false);");
+ m_outstream.println("\t\t\t\t\tyy_initial = true;");
+ m_outstream.println("\t\t\t\t\tyy_state "
+ + "= yy_state_dtrans[yy_lexical_state];");
+ m_outstream.println("\t\t\t\t\tyy_next_state = YY_NO_STATE;");*/
+ /*m_outstream.println("\t\t\t\t\tyy_prev_state = YY_NO_STATE;");*/
+ /*m_outstream.println("\t\t\t\t\tyy_last_accept_state = YY_NO_STATE;");
+ m_outstream.println("\t\t\t\t\tyy_mark_start();");*/
+ /*m_outstream.println("\t\t\t\t\tyy_this_accept = yy_accept(yy_state);");*/
+ /*m_outstream.println("\t\t\t\t\tyy_this_accept = yy_acpt[yy_state];");
+ m_outstream.println("\t\t\t\t\tif (YY_NOT_ACCEPT != yy_this_accept) {");
+ m_outstream.println("\t\t\t\t\t\tyy_last_accept_state = yy_state;");
+ m_outstream.println("\t\t\t\t\t}");*/
+
+ m_outstream.println("\t\t\t\t\tthrow (new Error(\"Lexical Error: Unmatched Input.\"));");
+ m_outstream.println("\t\t\t\t}");
+
+ m_outstream.println("\t\t\t\telse {");
+
+ m_outstream.println("\t\t\t\t\tyy_anchor = yy_acpt[yy_last_accept_state];");
+ /*m_outstream.println("\t\t\t\t\tyy_anchor "
+ + "= yy_accept(yy_last_accept_state);");*/
+ m_outstream.println("\t\t\t\t\tif (0 != (YY_END & yy_anchor)) {");
+ m_outstream.println("\t\t\t\t\t\tyy_move_end();");
+ m_outstream.println("\t\t\t\t\t}");
+ m_outstream.println("\t\t\t\t\tyy_to_mark();");
+
+ m_outstream.println("\t\t\t\t\tswitch (yy_last_accept_state) {");
+
+ emit_actions("\t\t\t\t\t");
+
+ m_outstream.println("\t\t\t\t\tdefault:");
+ m_outstream.println("\t\t\t\t\t\tyy_error(YY_E_INTERNAL,false);");
+ /*m_outstream.println("\t\t\t\t\t\treturn null;");*/
+ m_outstream.println("\t\t\t\t\tcase -1:");
+ m_outstream.println("\t\t\t\t\t}");
+
+ m_outstream.println("\t\t\t\t\tyy_initial = true;");
+ m_outstream.println("\t\t\t\t\tyy_state "
+ + "= yy_state_dtrans[yy_lexical_state];");
+ m_outstream.println("\t\t\t\t\tyy_next_state = YY_NO_STATE;");
+ /*m_outstream.println("\t\t\t\t\tyy_prev_state = YY_NO_STATE;");*/
+ m_outstream.println("\t\t\t\t\tyy_last_accept_state = YY_NO_STATE;");
+
+ m_outstream.println("\t\t\t\t\tyy_mark_start();");
+
+ /*m_outstream.println("\t\t\t\t\tyy_this_accept = yy_accept(yy_state);");*/
+ m_outstream.println("\t\t\t\t\tyy_this_accept = yy_acpt[yy_state];");
+ m_outstream.println("\t\t\t\t\tif (YY_NOT_ACCEPT != yy_this_accept) {");
+ m_outstream.println("\t\t\t\t\t\tyy_last_accept_state = yy_state;");
+ m_outstream.println("\t\t\t\t\t\tyy_mark_end();");
+ m_outstream.println("\t\t\t\t\t}");
+
+ m_outstream.println("\t\t\t\t}");
+ m_outstream.println("\t\t\t}");
+ m_outstream.println("\t\t}");
+ m_outstream.println("\t}");
+
+ /*m_outstream.println("\t\t\t\t");
+ m_outstream.println("\t\t\t");
+ m_outstream.println("\t\t\t");
+ m_outstream.println("\t\t\t");
+ m_outstream.println("\t\t\t");
+ m_outstream.println("\t\t}");*/
+ }
+
+ /***************************************************************
+ Function: emit_actions
+ Description:
+ **************************************************************/
+ private void emit_actions
+ (
+ String tabs
+ )
+ throws java.io.IOException
+ {
+ int elem;
+ int size;
+ int bogus_index;
+ CAccept accept;
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(m_spec.m_accept_vector.size()
+ == m_spec.m_anchor_array.length);
+ }
+
+ bogus_index = -2;
+ size = m_spec.m_accept_vector.size();
+ for (elem = 0; elem < size; ++elem)
+ {
+ accept = (CAccept) m_spec.m_accept_vector.elementAt(elem);
+ if (null != accept)
+ {
+ m_outstream.println(tabs + "case " + elem
+ + ":");
+ m_outstream.print(tabs + "\t");
+ m_outstream.print(new String(accept.m_action,0,
+ accept.m_action_read));
+ m_outstream.println();
+ m_outstream.println(tabs + "case " + bogus_index + ":");
+ m_outstream.println(tabs + "\tbreak;");
+ --bogus_index;
+ }
+ }
+ }
+
+ /***************************************************************
+ Function: emit_footer
+ Description:
+ **************************************************************/
+ private void emit_footer
+ (
+ )
+ throws java.io.IOException
+ {
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != m_spec);
+ CUtility.ASSERT(null != m_outstream);
+ }
+
+ m_outstream.println("}");
+ }
+}
+
+/***************************************************************
+ Class: CBunch
+ **************************************************************/
+class CBunch
+{
+ /***************************************************************
+ Member Variables
+ **************************************************************/
+ Vector m_nfa_set; /* Vector of CNfa states in dfa state. */
+ SparseBitSet m_nfa_bit; /* BitSet representation of CNfa labels. */
+ CAccept m_accept; /* Accepting actions, or null if nonaccepting state. */
+ int m_anchor; /* Anchors on regular expression. */
+ int m_accept_index; /* CNfa index corresponding to accepting actions. */
+
+ /***************************************************************
+ Function: CBunch
+ Description: Constructor.
+ **************************************************************/
+ CBunch
+ (
+ )
+ {
+ m_nfa_set = null;
+ m_nfa_bit = null;
+ m_accept = null;
+ m_anchor = CSpec.NONE;
+ m_accept_index = -1;
+ }
+}
+
+/***************************************************************
+ Class: CMakeNfa
+ **************************************************************/
+class CMakeNfa
+{
+ /***************************************************************
+ Member Variables
+ **************************************************************/
+ private CSpec m_spec;
+ private CLexGen m_lexGen;
+ private CInput m_input;
+
+ /***************************************************************
+ Function: CMakeNfa
+ Description: Constructor.
+ **************************************************************/
+ CMakeNfa
+ (
+ )
+ {
+ reset();
+ }
+
+ /***************************************************************
+ Function: reset
+ Description: Resets CMakeNfa member variables.
+ **************************************************************/
+ private void reset
+ (
+ )
+ {
+ m_input = null;
+ m_lexGen = null;
+ m_spec = null;
+ }
+
+ /***************************************************************
+ Function: set
+ Description: Sets CMakeNfa member variables.
+ **************************************************************/
+ private void set
+ (
+ CLexGen lexGen,
+ CSpec spec,
+ CInput input
+ )
+ {
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != input);
+ CUtility.ASSERT(null != lexGen);
+ CUtility.ASSERT(null != spec);
+ }
+
+ m_input = input;
+ m_lexGen = lexGen;
+ m_spec = spec;
+ }
+
+ /***************************************************************
+ Function: allocate_BOL_EOF
+ Description: Expands character class to include special BOL and
+ EOF characters. Puts numeric index of these characters in
+ input CSpec.
+ **************************************************************/
+ void allocate_BOL_EOF
+ (
+ CSpec spec
+ )
+ {
+ CUtility.ASSERT(CSpec.NUM_PSEUDO==2);
+ spec.BOL = spec.m_dtrans_ncols++;
+ spec.EOF = spec.m_dtrans_ncols++;
+ }
+
+ /***************************************************************
+ Function: thompson
+ Description: High level access function to module.
+ Deposits result in input CSpec.
+ **************************************************************/
+ void thompson
+ (
+ CLexGen lexGen,
+ CSpec spec,
+ CInput input
+ )
+ throws java.io.IOException
+ {
+ int i;
+ CNfa elem;
+ int size;
+
+ /* Set member variables. */
+ reset();
+ set(lexGen,spec,input);
+
+ size = m_spec.m_states.size();
+ m_spec.m_state_rules = new Vector[size];
+ for (i = 0; i < size; ++i)
+ {
+ m_spec.m_state_rules[i] = new Vector();
+ }
+
+ /* Initialize current token variable
+ and create nfa. */
+ /*m_spec.m_current_token = m_lexGen.EOS;
+ m_lexGen.advance();*/
+
+ m_spec.m_nfa_start = machine();
+
+ /* Set labels in created nfa machine. */
+ size = m_spec.m_nfa_states.size();
+ for (i = 0; i < size; ++i)
+ {
+ elem = (CNfa) m_spec.m_nfa_states.elementAt(i);
+ elem.m_label = i;
+ }
+
+ /* Debugging output. */
+ if (CUtility.DO_DEBUG)
+ {
+ m_lexGen.print_nfa();
+ }
+
+ if (m_spec.m_verbose)
+ {
+ System.out.println("NFA comprised of "
+ + (m_spec.m_nfa_states.size() + 1)
+ + " states.");
+ }
+
+ reset();
+ }
+
+ /***************************************************************
+ Function: discardCNfa
+ Description:
+ **************************************************************/
+ private void discardCNfa
+ (
+ CNfa nfa
+ )
+ {
+ m_spec.m_nfa_states.removeElement(nfa);
+ }
+
+ /***************************************************************
+ Function: processStates
+ Description:
+ **************************************************************/
+ private void processStates
+ (
+ SparseBitSet states,
+ CNfa current
+ )
+ {
+ int size;
+ int i;
+
+ size = m_spec.m_states.size();
+ for (i = 0; i < size; ++i)
+ {
+ if (states.get(i))
+ {
+ m_spec.m_state_rules[i].addElement(current);
+ }
+ }
+ }
+
+ /***************************************************************
+ Function: machine
+ Description: Recursive descent regular expression parser.
+ **************************************************************/
+ private CNfa machine
+ (
+ )
+ throws java.io.IOException
+ {
+ CNfa start;
+ CNfa p;
+ SparseBitSet states;
+
+ if (CUtility.DESCENT_DEBUG)
+ {
+ CUtility.enter("machine",m_spec.m_lexeme,m_spec.m_current_token);
+ }
+
+ start = CAlloc.newCNfa(m_spec);
+ p = start;
+
+ states = m_lexGen.getStates();
+
+ /* Begin: Added for states. */
+ m_spec.m_current_token = m_lexGen.EOS;
+ m_lexGen.advance();
+ /* End: Added for states. */
+
+ if (m_lexGen.END_OF_INPUT != m_spec.m_current_token) // CSA fix.
+ {
+ p.m_next = rule();
+
+ processStates(states,p.m_next);
+ }
+
+ while (m_lexGen.END_OF_INPUT != m_spec.m_current_token)
+ {
+ /* Make state changes HERE. */
+ states = m_lexGen.getStates();
+
+ /* Begin: Added for states. */
+ m_lexGen.advance();
+ if (m_lexGen.END_OF_INPUT == m_spec.m_current_token)
+ {
+ break;
+ }
+ /* End: Added for states. */
+
+ p.m_next2 = CAlloc.newCNfa(m_spec);
+ p = p.m_next2;
+ p.m_next = rule();
+
+ processStates(states,p.m_next);
+ }
+
+ // CSA: add pseudo-rules for BOL and EOF
+ SparseBitSet all_states = new SparseBitSet();
+ for (int i = 0; i < m_spec.m_states.size(); ++i)
+ all_states.set(i);
+ p.m_next2 = CAlloc.newCNfa(m_spec);
+ p = p.m_next2;
+ p.m_next = CAlloc.newCNfa(m_spec);
+ p.m_next.m_edge = CNfa.CCL;
+ p.m_next.m_next = CAlloc.newCNfa(m_spec);
+ p.m_next.m_set = new CSet();
+ p.m_next.m_set.add(m_spec.BOL);
+ p.m_next.m_set.add(m_spec.EOF);
+ p.m_next.m_next.m_accept = // do-nothing accept rule
+ new CAccept(new char[0], 0, m_input.m_line_number+1);
+ processStates(all_states,p.m_next);
+ // CSA: done.
+
+ if (CUtility.DESCENT_DEBUG)
+ {
+ CUtility.leave("machine",m_spec.m_lexeme,m_spec.m_current_token);
+ }
+
+ return start;
+ }
+
+ /***************************************************************
+ Function: rule
+ Description: Recursive descent regular expression parser.
+ **************************************************************/
+ private CNfa rule
+ (
+ )
+ throws java.io.IOException
+ {
+ CNfaPair pair;
+ CNfa p;
+ CNfa start = null;
+ CNfa end = null;
+ int anchor = CSpec.NONE;
+
+ if (CUtility.DESCENT_DEBUG)
+ {
+ CUtility.enter("rule",m_spec.m_lexeme,m_spec.m_current_token);
+ }
+
+ pair = CAlloc.newCNfaPair();
+
+ if (m_lexGen.AT_BOL == m_spec.m_current_token)
+ {
+ anchor = anchor | CSpec.START;
+ m_lexGen.advance();
+ expr(pair);
+
+ // CSA: fixed beginning-of-line operator. 8-aug-1999
+ start = CAlloc.newCNfa(m_spec);
+ start.m_edge = m_spec.BOL;
+ start.m_next = pair.m_start;
+ end = pair.m_end;
+ }
+ else
+ {
+ expr(pair);
+ start = pair.m_start;
+ end = pair.m_end;
+ }
+
+ if (m_lexGen.AT_EOL == m_spec.m_current_token)
+ {
+ m_lexGen.advance();
+ // CSA: fixed end-of-line operator. 8-aug-1999
+ CNfaPair nlpair = CAlloc.newNLPair(m_spec);
+ end.m_next = CAlloc.newCNfa(m_spec);
+ end.m_next.m_next = nlpair.m_start;
+ end.m_next.m_next2 = CAlloc.newCNfa(m_spec);
+ end.m_next.m_next2.m_edge = m_spec.EOF;
+ end.m_next.m_next2.m_next = nlpair.m_end;
+ end = nlpair.m_end;
+ anchor = anchor | CSpec.END;
+ }
+
+ /* Check for null rules. Charles Fischer found this bug. [CSA] */
+ if (end==null)
+ CError.parse_error(CError.E_ZERO, m_input.m_line_number);
+
+ /* Handle end of regular expression. See page 103. */
+ end.m_accept = m_lexGen.packAccept();
+ end.m_anchor = anchor;
+
+ /* Begin: Removed for states. */
+ /*m_lexGen.advance();*/
+ /* End: Removed for states. */
+
+ if (CUtility.DESCENT_DEBUG)
+ {
+ CUtility.leave("rule",m_spec.m_lexeme,m_spec.m_current_token);
+ }
+
+ return start;
+ }
+
+ /***************************************************************
+ Function: expr
+ Description: Recursive descent regular expression parser.
+ **************************************************************/
+ private void expr
+ (
+ CNfaPair pair
+ )
+ throws java.io.IOException
+ {
+ CNfaPair e2_pair;
+ CNfa p;
+
+ if (CUtility.DESCENT_DEBUG)
+ {
+ CUtility.enter("expr",m_spec.m_lexeme,m_spec.m_current_token);
+ }
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != pair);
+ }
+
+ e2_pair = CAlloc.newCNfaPair();
+
+ cat_expr(pair);
+
+ while (m_lexGen.OR == m_spec.m_current_token)
+ {
+ m_lexGen.advance();
+ cat_expr(e2_pair);
+
+ p = CAlloc.newCNfa(m_spec);
+ p.m_next2 = e2_pair.m_start;
+ p.m_next = pair.m_start;
+ pair.m_start = p;
+
+ p = CAlloc.newCNfa(m_spec);
+ pair.m_end.m_next = p;
+ e2_pair.m_end.m_next = p;
+ pair.m_end = p;
+ }
+
+ if (CUtility.DESCENT_DEBUG)
+ {
+ CUtility.leave("expr",m_spec.m_lexeme,m_spec.m_current_token);
+ }
+ }
+
+ /***************************************************************
+ Function: cat_expr
+ Description: Recursive descent regular expression parser.
+ **************************************************************/
+ private void cat_expr
+ (
+ CNfaPair pair
+ )
+ throws java.io.IOException
+ {
+ CNfaPair e2_pair;
+
+ if (CUtility.DESCENT_DEBUG)
+ {
+ CUtility.enter("cat_expr",m_spec.m_lexeme,m_spec.m_current_token);
+ }
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != pair);
+ }
+
+ e2_pair = CAlloc.newCNfaPair();
+
+ if (first_in_cat(m_spec.m_current_token))
+ {
+ factor(pair);
+ }
+
+ while (first_in_cat(m_spec.m_current_token))
+ {
+ factor(e2_pair);
+
+ /* Destroy */
+ pair.m_end.mimic(e2_pair.m_start);
+ discardCNfa(e2_pair.m_start);
+
+ pair.m_end = e2_pair.m_end;
+ }
+
+ if (CUtility.DESCENT_DEBUG)
+ {
+ CUtility.leave("cat_expr",m_spec.m_lexeme,m_spec.m_current_token);
+ }
+ }
+
+ /***************************************************************
+ Function: first_in_cat
+ Description: Recursive descent regular expression parser.
+ **************************************************************/
+ private boolean first_in_cat
+ (
+ int token
+ )
+ {
+ switch (token)
+ {
+ case CLexGen.CLOSE_PAREN:
+ case CLexGen.AT_EOL:
+ case CLexGen.OR:
+ case CLexGen.EOS:
+ return false;
+
+ case CLexGen.CLOSURE:
+ case CLexGen.PLUS_CLOSE:
+ case CLexGen.OPTIONAL:
+ CError.parse_error(CError.E_CLOSE,m_input.m_line_number);
+ return false;
+
+ case CLexGen.CCL_END:
+ CError.parse_error(CError.E_BRACKET,m_input.m_line_number);
+ return false;
+
+ case CLexGen.AT_BOL:
+ CError.parse_error(CError.E_BOL,m_input.m_line_number);
+ return false;
+
+ default:
+ break;
+ }
+
+ return true;
+ }
+
+ /***************************************************************
+ Function: factor
+ Description: Recursive descent regular expression parser.
+ **************************************************************/
+ private void factor
+ (
+ CNfaPair pair
+ )
+ throws java.io.IOException
+ {
+ CNfa start = null;
+ CNfa end = null;
+
+ if (CUtility.DESCENT_DEBUG)
+ {
+ CUtility.enter("factor",m_spec.m_lexeme,m_spec.m_current_token);
+ }
+
+ term(pair);
+
+ if (m_lexGen.CLOSURE == m_spec.m_current_token
+ || m_lexGen.PLUS_CLOSE == m_spec.m_current_token
+ || m_lexGen.OPTIONAL == m_spec.m_current_token)
+ {
+ start = CAlloc.newCNfa(m_spec);
+ end = CAlloc.newCNfa(m_spec);
+
+ start.m_next = pair.m_start;
+ pair.m_end.m_next = end;
+
+ if (m_lexGen.CLOSURE == m_spec.m_current_token
+ || m_lexGen.OPTIONAL == m_spec.m_current_token)
+ {
+ start.m_next2 = end;
+ }
+
+ if (m_lexGen.CLOSURE == m_spec.m_current_token
+ || m_lexGen.PLUS_CLOSE == m_spec.m_current_token)
+ {
+ pair.m_end.m_next2 = pair.m_start;
+ }
+
+ pair.m_start = start;
+ pair.m_end = end;
+ m_lexGen.advance();
+ }
+
+ if (CUtility.DESCENT_DEBUG)
+ {
+ CUtility.leave("factor",m_spec.m_lexeme,m_spec.m_current_token);
+ }
+ }
+
+ /***************************************************************
+ Function: term
+ Description: Recursive descent regular expression parser.
+ **************************************************************/
+ private void term
+ (
+ CNfaPair pair
+ )
+ throws java.io.IOException
+ {
+ CNfa start;
+ boolean isAlphaL;
+ int c;
+
+ if (CUtility.DESCENT_DEBUG)
+ {
+ CUtility.enter("term",m_spec.m_lexeme,m_spec.m_current_token);
+ }
+
+ if (m_lexGen.OPEN_PAREN == m_spec.m_current_token)
+ {
+ m_lexGen.advance();
+ expr(pair);
+
+ if (m_lexGen.CLOSE_PAREN == m_spec.m_current_token)
+ {
+ m_lexGen.advance();
+ }
+ else
+ {
+ CError.parse_error(CError.E_SYNTAX,m_input.m_line_number);
+ }
+ }
+ else
+ {
+ start = CAlloc.newCNfa(m_spec);
+ pair.m_start = start;
+
+ start.m_next = CAlloc.newCNfa(m_spec);
+ pair.m_end = start.m_next;
+
+ if (m_lexGen.L == m_spec.m_current_token &&
+ Character.isLetter(m_spec.m_lexeme))
+ {
+ isAlphaL = true;
+ }
+ else
+ {
+ isAlphaL = false;
+ }
+ if (false == (m_lexGen.ANY == m_spec.m_current_token
+ || m_lexGen.CCL_START == m_spec.m_current_token
+ || (m_spec.m_ignorecase && isAlphaL)))
+ {
+ start.m_edge = m_spec.m_lexeme;
+ m_lexGen.advance();
+ }
+ else
+ {
+ start.m_edge = CNfa.CCL;
+
+ start.m_set = new CSet();
+
+ /* Match case-insensitive letters using character class. */
+ if (m_spec.m_ignorecase && isAlphaL)
+ {
+ start.m_set.addncase(m_spec.m_lexeme);
+ }
+ /* Match dot (.) using character class. */
+ else if (m_lexGen.ANY == m_spec.m_current_token)
+ {
+ start.m_set.add('\n');
+ start.m_set.add('\r');
+ // CSA: exclude BOL and EOF from character classes
+ start.m_set.add(m_spec.BOL);
+ start.m_set.add(m_spec.EOF);
+ start.m_set.complement();
+ }
+ else
+ {
+ m_lexGen.advance();
+ if (m_lexGen.AT_BOL == m_spec.m_current_token)
+ {
+ m_lexGen.advance();
+
+ // CSA: exclude BOL and EOF from character classes
+ start.m_set.add(m_spec.BOL);
+ start.m_set.add(m_spec.EOF);
+ start.m_set.complement();
+ }
+ if (false == (m_lexGen.CCL_END == m_spec.m_current_token))
+ {
+ dodash(start.m_set);
+ }
+ /*else
+ {
+ for (c = 0; c <= ' '; ++c)
+ {
+ start.m_set.add((byte) c);
+ }
+ }*/
+ }
+ m_lexGen.advance();
+ }
+ }
+
+ if (CUtility.DESCENT_DEBUG)
+ {
+ CUtility.leave("term",m_spec.m_lexeme,m_spec.m_current_token);
+ }
+ }
+
+ /***************************************************************
+ Function: dodash
+ Description: Recursive descent regular expression parser.
+ **************************************************************/
+ private void dodash
+ (
+ CSet set
+ )
+ throws java.io.IOException
+ {
+ int first = -1;
+
+ if (CUtility.DESCENT_DEBUG)
+ {
+ CUtility.enter("dodash",m_spec.m_lexeme,m_spec.m_current_token);
+ }
+
+ while (m_lexGen.EOS != m_spec.m_current_token
+ && m_lexGen.CCL_END != m_spec.m_current_token)
+ {
+ // DASH loses its special meaning if it is first in class.
+ if (m_lexGen.DASH == m_spec.m_current_token && -1 != first)
+ {
+ m_lexGen.advance();
+ // DASH loses its special meaning if it is last in class.
+ if (m_spec.m_current_token == m_lexGen.CCL_END)
+ {
+ // 'first' already in set.
+ set.add('-');
+ break;
+ }
+ for ( ; first <= m_spec.m_lexeme; ++first)
+ {
+ if (m_spec.m_ignorecase)
+ set.addncase((char)first);
+ else
+ set.add(first);
+ }
+ }
+ else
+ {
+ first = m_spec.m_lexeme;
+ if (m_spec.m_ignorecase)
+ set.addncase(m_spec.m_lexeme);
+ else
+ set.add(m_spec.m_lexeme);
+ }
+
+ m_lexGen.advance();
+ }
+
+ if (CUtility.DESCENT_DEBUG)
+ {
+ CUtility.leave("dodash",m_spec.m_lexeme,m_spec.m_current_token);
+ }
+ }
+}
+
+/**
+ * Extract character classes from NFA and simplify.
+ * @author C. Scott Ananian 25-Jul-1999
+ */
+class CSimplifyNfa
+{
+ private int[] ccls; // character class mapping.
+ private int original_charset_size; // original charset size
+ private int mapped_charset_size; // reduced charset size
+
+ void simplify(CSpec m_spec) {
+ computeClasses(m_spec); // initialize fields.
+
+ // now rewrite the NFA using our character class mapping.
+ for (Enumeration e=m_spec.m_nfa_states.elements(); e.hasMoreElements(); ) {
+ CNfa nfa = (CNfa) e.nextElement();
+ if (nfa.m_edge==CNfa.EMPTY || nfa.m_edge==CNfa.EPSILON)
+ continue; // no change.
+ if (nfa.m_edge==CNfa.CCL) {
+ CSet ncset = new CSet();
+ ncset.map(nfa.m_set, ccls); // map it.
+ nfa.m_set = ncset;
+ } else { // single character
+ nfa.m_edge = ccls[nfa.m_edge]; // map it.
+ }
+ }
+
+ // now update m_spec with the mapping.
+ m_spec.m_ccls_map = ccls;
+ m_spec.m_dtrans_ncols = mapped_charset_size;
+ }
+ /** Compute minimum set of character classes needed to disambiguate
+ * edges. We optimistically assume that every character belongs to
+ * a single character class, and then incrementally split classes
+ * as we see edges that require discrimination between characters in
+ * the class. [CSA, 25-Jul-1999] */
+ private void computeClasses(CSpec m_spec) {
+ this.original_charset_size = m_spec.m_dtrans_ncols;
+ this.ccls = new int[original_charset_size]; // initially all zero.
+
+ int nextcls = 1;
+ SparseBitSet clsA = new SparseBitSet(), clsB = new SparseBitSet();
+ Hashtable h = new Hashtable();
+
+ System.out.print("Working on character classes.");
+ for (Enumeration e=m_spec.m_nfa_states.elements(); e.hasMoreElements(); ) {
+ CNfa nfa = (CNfa) e.nextElement();
+ if (nfa.m_edge==CNfa.EMPTY || nfa.m_edge==CNfa.EPSILON)
+ continue; // no discriminatory information.
+ clsA.clearAll(); clsB.clearAll();
+ for (int i=0; i<ccls.length; i++)
+ if (nfa.m_edge==i || // edge labeled with a character
+ nfa.m_edge==CNfa.CCL && nfa.m_set.contains(i)) // set of characters
+ clsA.set(ccls[i]);
+ else
+ clsB.set(ccls[i]);
+ // now figure out which character classes we need to split.
+ clsA.and(clsB); // split the classes which show up on both sides of edge
+ System.out.print(clsA.size()==0?".":":");
+ if (clsA.size()==0) continue; // nothing to do.
+ // and split them.
+ h.clear(); // h will map old to new class name
+ for (int i=0; i<ccls.length; i++)
+ if (clsA.get(ccls[i])) // a split class
+ if (nfa.m_edge==i ||
+ nfa.m_edge==CNfa.CCL && nfa.m_set.contains(i)) { // on A side
+ Integer split = new Integer(ccls[i]);
+ if (!h.containsKey(split))
+ h.put(split, new Integer(nextcls++)); // make new class
+ ccls[i] = ((Integer)h.get(split)).intValue();
+ }
+ }
+ System.out.println();
+ System.out.println("NFA has "+nextcls+" distinct character classes.");
+
+ this.mapped_charset_size = nextcls;
+ }
+}
+
+/***************************************************************
+ Class: CMinimize
+ **************************************************************/
+class CMinimize
+{
+ /***************************************************************
+ Member Variables
+ **************************************************************/
+ CSpec m_spec;
+ Vector m_group;
+ int m_ingroup[];
+
+ /***************************************************************
+ Function: CMinimize
+ Description: Constructor.
+ **************************************************************/
+ CMinimize
+ (
+ )
+ {
+ reset();
+ }
+
+ /***************************************************************
+ Function: reset
+ Description: Resets member variables.
+ **************************************************************/
+ private void reset
+ (
+ )
+ {
+ m_spec = null;
+ m_group = null;
+ m_ingroup = null;
+ }
+
+ /***************************************************************
+ Function: set
+ Description: Sets member variables.
+ **************************************************************/
+ private void set
+ (
+ CSpec spec
+ )
+ {
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != spec);
+ }
+
+ m_spec = spec;
+ m_group = null;
+ m_ingroup = null;
+ }
+
+ /***************************************************************
+ Function: min_dfa
+ Description: High-level access function to module.
+ **************************************************************/
+ void min_dfa
+ (
+ CSpec spec
+ )
+ {
+ set(spec);
+
+ /* Remove redundant states. */
+ minimize();
+
+ /* Column and row compression.
+ Save accept states in auxilary vector. */
+ reduce();
+
+ reset();
+ }
+
+ /***************************************************************
+ Function: col_copy
+ Description: Copies source column into destination column.
+ **************************************************************/
+ private void col_copy
+ (
+ int dest,
+ int src
+ )
+ {
+ int n;
+ int i;
+ CDTrans dtrans;
+
+ n = m_spec.m_dtrans_vector.size();
+ for (i = 0; i < n; ++i)
+ {
+ dtrans = (CDTrans) m_spec.m_dtrans_vector.elementAt(i);
+ dtrans.m_dtrans[dest] = dtrans.m_dtrans[src];
+ }
+ }
+
+ /***************************************************************
+ Function: trunc_col
+ Description: Truncates each column to the 'correct' length.
+ **************************************************************/
+ private void trunc_col
+ (
+ )
+ {
+ int n;
+ int i;
+ CDTrans dtrans;
+
+ n = m_spec.m_dtrans_vector.size();
+ for (i = 0; i < n; ++i)
+ {
+ int[] ndtrans = new int[m_spec.m_dtrans_ncols];
+ dtrans = (CDTrans) m_spec.m_dtrans_vector.elementAt(i);
+ System.arraycopy(dtrans.m_dtrans, 0, ndtrans, 0, ndtrans.length);
+ dtrans.m_dtrans = ndtrans;
+ }
+ }
+ /***************************************************************
+ Function: row_copy
+ Description: Copies source row into destination row.
+ **************************************************************/
+ private void row_copy
+ (
+ int dest,
+ int src
+ )
+ {
+ CDTrans dtrans;
+
+ dtrans = (CDTrans) m_spec.m_dtrans_vector.elementAt(src);
+ m_spec.m_dtrans_vector.setElementAt(dtrans,dest);
+ }
+
+ /***************************************************************
+ Function: col_equiv
+ Description:
+ **************************************************************/
+ private boolean col_equiv
+ (
+ int col1,
+ int col2
+ )
+ {
+ int n;
+ int i;
+ CDTrans dtrans;
+
+ n = m_spec.m_dtrans_vector.size();
+ for (i = 0; i < n; ++i)
+ {
+ dtrans = (CDTrans) m_spec.m_dtrans_vector.elementAt(i);
+ if (dtrans.m_dtrans[col1] != dtrans.m_dtrans[col2])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /***************************************************************
+ Function: row_equiv
+ Description:
+ **************************************************************/
+ private boolean row_equiv
+ (
+ int row1,
+ int row2
+ )
+ {
+ int i;
+ CDTrans dtrans1;
+ CDTrans dtrans2;
+
+ dtrans1 = (CDTrans) m_spec.m_dtrans_vector.elementAt(row1);
+ dtrans2 = (CDTrans) m_spec.m_dtrans_vector.elementAt(row2);
+
+ for (i = 0; i < m_spec.m_dtrans_ncols; ++i)
+ {
+ if (dtrans1.m_dtrans[i] != dtrans2.m_dtrans[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /***************************************************************
+ Function: reduce
+ Description:
+ **************************************************************/
+ private void reduce
+ (
+ )
+ {
+ int i;
+ int j;
+ int k;
+ int nrows;
+ int reduced_ncols;
+ int reduced_nrows;
+ SparseBitSet set;
+ CDTrans dtrans;
+ int size;
+
+ set = new SparseBitSet();
+
+ /* Save accept nodes and anchor entries. */
+ size = m_spec.m_dtrans_vector.size();
+ m_spec.m_anchor_array = new int[size];
+ m_spec.m_accept_vector = new Vector();
+ for (i = 0; i < size; ++i)
+ {
+ dtrans = (CDTrans) m_spec.m_dtrans_vector.elementAt(i);
+ m_spec.m_accept_vector.addElement(dtrans.m_accept);
+ m_spec.m_anchor_array[i] = dtrans.m_anchor;
+ dtrans.m_accept = null;
+ }
+
+ /* Allocate column map. */
+ m_spec.m_col_map = new int[m_spec.m_dtrans_ncols];
+ for (i = 0; i < m_spec.m_dtrans_ncols; ++i)
+ {
+ m_spec.m_col_map[i] = -1;
+ }
+
+ /* Process columns for reduction. */
+ for (reduced_ncols = 0; ; ++reduced_ncols)
+ {
+ if (CUtility.DEBUG)
+ {
+ for (i = 0; i < reduced_ncols; ++i)
+ {
+ CUtility.ASSERT(-1 != m_spec.m_col_map[i]);
+ }
+ }
+
+ for (i = reduced_ncols; i < m_spec.m_dtrans_ncols; ++i)
+ {
+ if (-1 == m_spec.m_col_map[i])
+ {
+ break;
+ }
+ }
+
+ if (i >= m_spec.m_dtrans_ncols)
+ {
+ break;
+ }
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(false == set.get(i));
+ CUtility.ASSERT(-1 == m_spec.m_col_map[i]);
+ }
+
+ set.set(i);
+
+ m_spec.m_col_map[i] = reduced_ncols;
+
+ /* UNDONE: Optimize by doing all comparisons in one batch. */
+ for (j = i + 1; j < m_spec.m_dtrans_ncols; ++j)
+ {
+ if (-1 == m_spec.m_col_map[j] && true == col_equiv(i,j))
+ {
+ m_spec.m_col_map[j] = reduced_ncols;
+ }
+ }
+ }
+
+ /* Reduce columns. */
+ k = 0;
+ for (i = 0; i < m_spec.m_dtrans_ncols; ++i)
+ {
+ if (set.get(i))
+ {
+ ++k;
+
+ set.clear(i);
+
+ j = m_spec.m_col_map[i];
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(j <= i);
+ }
+
+ if (j == i)
+ {
+ continue;
+ }
+
+ col_copy(j,i);
+ }
+ }
+ m_spec.m_dtrans_ncols = reduced_ncols;
+ /* truncate m_dtrans at proper length (freeing extra) */
+ trunc_col();
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(k == reduced_ncols);
+ }
+
+ /* Allocate row map. */
+ nrows = m_spec.m_dtrans_vector.size();
+ m_spec.m_row_map = new int[nrows];
+ for (i = 0; i < nrows; ++i)
+ {
+ m_spec.m_row_map[i] = -1;
+ }
+
+ /* Process rows to reduce. */
+ for (reduced_nrows = 0; ; ++reduced_nrows)
+ {
+ if (CUtility.DEBUG)
+ {
+ for (i = 0; i < reduced_nrows; ++i)
+ {
+ CUtility.ASSERT(-1 != m_spec.m_row_map[i]);
+ }
+ }
+
+ for (i = reduced_nrows; i < nrows; ++i)
+ {
+ if (-1 == m_spec.m_row_map[i])
+ {
+ break;
+ }
+ }
+
+ if (i >= nrows)
+ {
+ break;
+ }
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(false == set.get(i));
+ CUtility.ASSERT(-1 == m_spec.m_row_map[i]);
+ }
+
+ set.set(i);
+
+ m_spec.m_row_map[i] = reduced_nrows;
+
+ /* UNDONE: Optimize by doing all comparisons in one batch. */
+ for (j = i + 1; j < nrows; ++j)
+ {
+ if (-1 == m_spec.m_row_map[j] && true == row_equiv(i,j))
+ {
+ m_spec.m_row_map[j] = reduced_nrows;
+ }
+ }
+ }
+
+ /* Reduce rows. */
+ k = 0;
+ for (i = 0; i < nrows; ++i)
+ {
+ if (set.get(i))
+ {
+ ++k;
+
+ set.clear(i);
+
+ j = m_spec.m_row_map[i];
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(j <= i);
+ }
+
+ if (j == i)
+ {
+ continue;
+ }
+
+ row_copy(j,i);
+ }
+ }
+ m_spec.m_dtrans_vector.setSize(reduced_nrows);
+
+ if (CUtility.DEBUG)
+ {
+ /*System.out.println("k = " + k + "\nreduced_nrows = " + reduced_nrows + "");*/
+ CUtility.ASSERT(k == reduced_nrows);
+ }
+ }
+
+ /***************************************************************
+ Function: fix_dtrans
+ Description: Updates CDTrans table after minimization
+ using groups, removing redundant transition table states.
+ **************************************************************/
+ private void fix_dtrans
+ (
+ )
+ {
+ Vector new_vector;
+ int i;
+ int size;
+ Vector dtrans_group;
+ CDTrans first;
+ int c;
+
+ new_vector = new Vector();
+
+ size = m_spec.m_state_dtrans.length;
+ for (i = 0; i < size; ++i)
+ {
+ if (CDTrans.F != m_spec.m_state_dtrans[i])
+ {
+ m_spec.m_state_dtrans[i] = m_ingroup[m_spec.m_state_dtrans[i]];
+ }
+ }
+
+ size = m_group.size();
+ for (i = 0; i < size; ++i)
+ {
+ dtrans_group = (Vector) m_group.elementAt(i);
+ first = (CDTrans) dtrans_group.elementAt(0);
+ new_vector.addElement(first);
+
+ for (c = 0; c < m_spec.m_dtrans_ncols; ++c)
+ {
+ if (CDTrans.F != first.m_dtrans[c])
+ {
+ first.m_dtrans[c] = m_ingroup[first.m_dtrans[c]];
+ }
+ }
+ }
+
+ m_group = null;
+ m_spec.m_dtrans_vector = new_vector;
+ }
+
+ /***************************************************************
+ Function: minimize
+ Description: Removes redundant transition table states.
+ **************************************************************/
+ private void minimize
+ (
+ )
+ {
+ Vector dtrans_group;
+ Vector new_group;
+ int i;
+ int j;
+ int old_group_count;
+ int group_count;
+ CDTrans next;
+ CDTrans first;
+ int goto_first;
+ int goto_next;
+ int c;
+ int group_size;
+ boolean added;
+
+ init_groups();
+
+ group_count = m_group.size();
+ old_group_count = group_count - 1;
+
+ while (old_group_count != group_count)
+ {
+ old_group_count = group_count;
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(m_group.size() == group_count);
+ }
+
+ for (i = 0; i < group_count; ++i)
+ {
+ dtrans_group = (Vector) m_group.elementAt(i);
+
+ group_size = dtrans_group.size();
+ if (group_size <= 1)
+ {
+ continue;
+ }
+
+ new_group = new Vector();
+ added = false;
+
+ first = (CDTrans) dtrans_group.elementAt(0);
+ for (j = 1; j < group_size; ++j)
+ {
+ next = (CDTrans) dtrans_group.elementAt(j);
+
+ for (c = 0; c < m_spec.m_dtrans_ncols; ++c)
+ {
+ goto_first = first.m_dtrans[c];
+ goto_next = next.m_dtrans[c];
+
+ if (goto_first != goto_next
+ && (goto_first == CDTrans.F
+ || goto_next == CDTrans.F
+ || m_ingroup[goto_next] != m_ingroup[goto_first]))
+ {
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(dtrans_group.elementAt(j) == next);
+ }
+
+ dtrans_group.removeElementAt(j);
+ --j;
+ --group_size;
+ new_group.addElement(next);
+ if (false == added)
+ {
+ added = true;
+ ++group_count;
+ m_group.addElement(new_group);
+ }
+ m_ingroup[next.m_label] = m_group.size() - 1;
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(m_group.contains(new_group)
+ == true);
+ CUtility.ASSERT(m_group.contains(dtrans_group)
+ == true);
+ CUtility.ASSERT(dtrans_group.contains(first)
+ == true);
+ CUtility.ASSERT(dtrans_group.contains(next)
+ == false);
+ CUtility.ASSERT(new_group.contains(first)
+ == false);
+ CUtility.ASSERT(new_group.contains(next)
+ == true);
+ CUtility.ASSERT(dtrans_group.size() == group_size);
+ CUtility.ASSERT(i == m_ingroup[first.m_label]);
+ CUtility.ASSERT((m_group.size() - 1)
+ == m_ingroup[next.m_label]);
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ System.out.println(m_group.size() + " states after removal of redundant states.");
+
+ if (m_spec.m_verbose
+ && true == CUtility.OLD_DUMP_DEBUG)
+ {
+ System.out.println();
+ System.out.println("States grouped as follows after minimization");
+ pgroups();
+ }
+
+ fix_dtrans();
+ }
+
+ /***************************************************************
+ Function: init_groups
+ Description:
+ **************************************************************/
+ private void init_groups
+ (
+ )
+ {
+ int i;
+ int j;
+ int group_count;
+ int size;
+ CAccept accept;
+ CDTrans dtrans;
+ Vector dtrans_group;
+ CDTrans first;
+ boolean group_found;
+
+ m_group = new Vector();
+ group_count = 0;
+
+ size = m_spec.m_dtrans_vector.size();
+ m_ingroup = new int[size];
+
+ for (i = 0; i < size; ++i)
+ {
+ group_found = false;
+ dtrans = (CDTrans) m_spec.m_dtrans_vector.elementAt(i);
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(i == dtrans.m_label);
+ CUtility.ASSERT(false == group_found);
+ CUtility.ASSERT(group_count == m_group.size());
+ }
+
+ for (j = 0; j < group_count; ++j)
+ {
+ dtrans_group = (Vector) m_group.elementAt(j);
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(false == group_found);
+ CUtility.ASSERT(0 < dtrans_group.size());
+ }
+
+ first = (CDTrans) dtrans_group.elementAt(0);
+
+ if (CUtility.SLOW_DEBUG)
+ {
+ CDTrans check;
+ int k;
+ int s;
+
+ s = dtrans_group.size();
+ CUtility.ASSERT(0 < s);
+
+ for (k = 1; k < s; ++k)
+ {
+ check = (CDTrans) dtrans_group.elementAt(k);
+ CUtility.ASSERT(check.m_accept == first.m_accept);
+ }
+ }
+
+ if (first.m_accept == dtrans.m_accept)
+ {
+ dtrans_group.addElement(dtrans);
+ m_ingroup[i] = j;
+ group_found = true;
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(j == m_ingroup[dtrans.m_label]);
+ }
+
+ break;
+ }
+ }
+
+ if (false == group_found)
+ {
+ dtrans_group = new Vector();
+ dtrans_group.addElement(dtrans);
+ m_ingroup[i] = m_group.size();
+ m_group.addElement(dtrans_group);
+ ++group_count;
+ }
+ }
+
+ if (m_spec.m_verbose
+ && true == CUtility.OLD_DUMP_DEBUG)
+ {
+ System.out.println("Initial grouping:");
+ pgroups();
+ System.out.println();
+ }
+ }
+
+ /***************************************************************
+ Function: pset
+ **************************************************************/
+ private void pset
+ (
+ Vector dtrans_group
+ )
+ {
+ int i;
+ int size;
+ CDTrans dtrans;
+
+ size = dtrans_group.size();
+ for (i = 0; i < size; ++i)
+ {
+ dtrans = (CDTrans) dtrans_group.elementAt(i);
+ System.out.print(dtrans.m_label + " ");
+ }
+ }
+
+ /***************************************************************
+ Function: pgroups
+ **************************************************************/
+ private void pgroups
+ (
+ )
+ {
+ int i;
+ int dtrans_size;
+ int group_size;
+
+ group_size = m_group.size();
+ for (i = 0; i < group_size; ++i)
+ {
+ System.out.print("\tGroup " + i + " {");
+ pset((Vector) m_group.elementAt(i));
+ System.out.println("}");
+ System.out.println();
+ }
+
+ System.out.println();
+ dtrans_size = m_spec.m_dtrans_vector.size();
+ for (i = 0; i < dtrans_size; ++i)
+ {
+ System.out.println("\tstate " + i
+ + " is in group "
+ + m_ingroup[i]);
+ }
+ }
+}
+
+/***************************************************************
+ Class: CNfa2Dfa
+ **************************************************************/
+class CNfa2Dfa
+{
+ /***************************************************************
+ Member Variables
+ **************************************************************/
+ private CSpec m_spec;
+ private int m_unmarked_dfa;
+ private CLexGen m_lexGen;
+
+ /***************************************************************
+ Constants
+ **************************************************************/
+ private static final int NOT_IN_DSTATES = -1;
+
+ /***************************************************************
+ Function: CNfa2Dfa
+ **************************************************************/
+ CNfa2Dfa
+ (
+ )
+ {
+ reset();
+ }
+
+ /***************************************************************
+ Function: set
+ Description:
+ **************************************************************/
+ private void set
+ (
+ CLexGen lexGen,
+ CSpec spec
+ )
+ {
+ m_lexGen = lexGen;
+ m_spec = spec;
+ m_unmarked_dfa = 0;
+ }
+
+ /***************************************************************
+ Function: reset
+ Description:
+ **************************************************************/
+ private void reset
+ (
+ )
+ {
+ m_lexGen = null;
+ m_spec = null;
+ m_unmarked_dfa = 0;
+ }
+
+ /***************************************************************
+ Function: make_dfa
+ Description: High-level access function to module.
+ **************************************************************/
+ void make_dfa
+ (
+ CLexGen lexGen,
+ CSpec spec
+ )
+ {
+ int i;
+
+ reset();
+ set(lexGen,spec);
+
+ make_dtrans();
+ free_nfa_states();
+
+ if (m_spec.m_verbose && true == CUtility.OLD_DUMP_DEBUG)
+ {
+ System.out.println(m_spec.m_dfa_states.size()
+ + " DFA states in original machine.");
+ }
+
+ free_dfa_states();
+ }
+
+ /***************************************************************
+ Function: make_dtrans
+ Description: Creates uncompressed CDTrans transition table.
+ **************************************************************/
+ private void make_dtrans
+ (
+ )
+ /* throws java.lang.CloneNotSupportedException*/
+ {
+ CDfa next;
+ CDfa dfa;
+ CBunch bunch;
+ int i;
+ int nextstate;
+ int size;
+ CDTrans dtrans;
+ CNfa nfa;
+ int istate;
+ int nstates;
+
+ System.out.print("Working on DFA states.");
+
+ /* Reference passing type and initializations. */
+ bunch = new CBunch();
+ m_unmarked_dfa = 0;
+
+ /* Allocate mapping array. */
+ nstates = m_spec.m_state_rules.length;
+ m_spec.m_state_dtrans = new int[nstates];
+
+ for (istate = 0; nstates > istate; ++istate)
+ {
+ /* CSA bugfix: if we skip all zero size rules, then
+ an specification with no rules produces an illegal
+ lexer (0 states) instead of a lexer that rejects
+ everything (1 nonaccepting state). [27-Jul-1999]
+ if (0 == m_spec.m_state_rules[istate].size())
+ {
+ m_spec.m_state_dtrans[istate] = CDTrans.F;
+ continue;
+ }
+ */
+
+ /* Create start state and initialize fields. */
+ bunch.m_nfa_set = (Vector) m_spec.m_state_rules[istate].clone();
+ sortStates(bunch.m_nfa_set);
+
+ bunch.m_nfa_bit = new SparseBitSet();
+
+ /* Initialize bit set. */
+ size = bunch.m_nfa_set.size();
+ for (i = 0; size > i; ++i)
+ {
+ nfa = (CNfa) bunch.m_nfa_set.elementAt(i);
+ bunch.m_nfa_bit.set(nfa.m_label);
+ }
+
+ bunch.m_accept = null;
+ bunch.m_anchor = CSpec.NONE;
+ bunch.m_accept_index = CUtility.INT_MAX;
+
+ e_closure(bunch);
+ add_to_dstates(bunch);
+
+ m_spec.m_state_dtrans[istate] = m_spec.m_dtrans_vector.size();
+
+ /* Main loop of CDTrans creation. */
+ while (null != (dfa = get_unmarked()))
+ {
+ System.out.print(".");
+ System.out.flush();
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(false == dfa.m_mark);
+ }
+
+ /* Get first unmarked node, then mark it. */
+ dfa.m_mark = true;
+
+ /* Allocate new CDTrans, then initialize fields. */
+ dtrans = new CDTrans(m_spec.m_dtrans_vector.size(),m_spec);
+ dtrans.m_accept = dfa.m_accept;
+ dtrans.m_anchor = dfa.m_anchor;
+
+ /* Set CDTrans array for each character transition. */
+ for (i = 0; i < m_spec.m_dtrans_ncols; ++i)
+ {
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(0 <= i);
+ CUtility.ASSERT(m_spec.m_dtrans_ncols > i);
+ }
+
+ /* Create new dfa set by attempting character transition. */
+ move(dfa.m_nfa_set,dfa.m_nfa_bit,i,bunch);
+ if (null != bunch.m_nfa_set)
+ {
+ e_closure(bunch);
+ }
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT((null == bunch.m_nfa_set
+ && null == bunch.m_nfa_bit)
+ || (null != bunch.m_nfa_set
+ && null != bunch.m_nfa_bit));
+ }
+
+ /* Create new state or set state to empty. */
+ if (null == bunch.m_nfa_set)
+ {
+ nextstate = CDTrans.F;
+ }
+ else
+ {
+ nextstate = in_dstates(bunch);
+
+ if (NOT_IN_DSTATES == nextstate)
+ {
+ nextstate = add_to_dstates(bunch);
+ }
+ }
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(nextstate < m_spec.m_dfa_states.size());
+ }
+
+ dtrans.m_dtrans[i] = nextstate;
+ }
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(m_spec.m_dtrans_vector.size() == dfa.m_label);
+ }
+
+ m_spec.m_dtrans_vector.addElement(dtrans);
+ }
+ }
+
+ System.out.println();
+ }
+
+ /***************************************************************
+ Function: free_dfa_states
+ **************************************************************/
+ private void free_dfa_states
+ (
+ )
+ {
+ m_spec.m_dfa_states = null;
+ m_spec.m_dfa_sets = null;
+ }
+
+ /***************************************************************
+ Function: free_nfa_states
+ **************************************************************/
+ private void free_nfa_states
+ (
+ )
+ {
+ /* UNDONE: Remove references to nfas from within dfas. */
+ /* UNDONE: Don't free CAccepts. */
+
+ m_spec.m_nfa_states = null;
+ m_spec.m_nfa_start = null;
+ m_spec.m_state_rules = null;
+ }
+
+ /***************************************************************
+ Function: e_closure
+ Description: Alters and returns input set.
+ **************************************************************/
+ private void e_closure
+ (
+ CBunch bunch
+ )
+ {
+ Stack nfa_stack;
+ int size;
+ int i;
+ CNfa state;
+
+ /* Debug checks. */
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != bunch);
+ CUtility.ASSERT(null != bunch.m_nfa_set);
+ CUtility.ASSERT(null != bunch.m_nfa_bit);
+ }
+
+ bunch.m_accept = null;
+ bunch.m_anchor = CSpec.NONE;
+ bunch.m_accept_index = CUtility.INT_MAX;
+
+ /* Create initial stack. */
+ nfa_stack = new Stack();
+ size = bunch.m_nfa_set.size();
+ for (i = 0; i < size; ++i)
+ {
+ state = (CNfa) bunch.m_nfa_set.elementAt(i);
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(bunch.m_nfa_bit.get(state.m_label));
+ }
+
+ nfa_stack.push(state);
+ }
+
+ /* Main loop. */
+ while (false == nfa_stack.empty())
+ {
+ state = (CNfa) nfa_stack.pop();
+
+ if (CUtility.OLD_DUMP_DEBUG)
+ {
+ if (null != state.m_accept)
+ {
+ System.out.println("Looking at accepting state " + state.m_label
+ + " with <"
+ + (new String(state.m_accept.m_action,0,
+ state.m_accept.m_action_read))
+ + ">");
+ }
+ }
+
+ if (null != state.m_accept
+ && state.m_label < bunch.m_accept_index)
+ {
+ bunch.m_accept_index = state.m_label;
+ bunch.m_accept = state.m_accept;
+ bunch.m_anchor = state.m_anchor;
+
+ if (CUtility.OLD_DUMP_DEBUG)
+ {
+ System.out.println("Found accepting state " + state.m_label
+ + " with <"
+ + (new String(state.m_accept.m_action,0,
+ state.m_accept.m_action_read))
+ + ">");
+ }
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != bunch.m_accept);
+ CUtility.ASSERT(CSpec.NONE == bunch.m_anchor
+ || 0 != (bunch.m_anchor & CSpec.END)
+ || 0 != (bunch.m_anchor & CSpec.START));
+ }
+ }
+
+ if (CNfa.EPSILON == state.m_edge)
+ {
+ if (null != state.m_next)
+ {
+ if (false == bunch.m_nfa_set.contains(state.m_next))
+ {
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(false == bunch.m_nfa_bit.get(state.m_next.m_label));
+ }
+
+ bunch.m_nfa_bit.set(state.m_next.m_label);
+ bunch.m_nfa_set.addElement(state.m_next);
+ nfa_stack.push(state.m_next);
+ }
+ }
+
+ if (null != state.m_next2)
+ {
+ if (false == bunch.m_nfa_set.contains(state.m_next2))
+ {
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(false == bunch.m_nfa_bit.get(state.m_next2.m_label));
+ }
+
+ bunch.m_nfa_bit.set(state.m_next2.m_label);
+ bunch.m_nfa_set.addElement(state.m_next2);
+ nfa_stack.push(state.m_next2);
+ }
+ }
+ }
+ }
+
+ if (null != bunch.m_nfa_set)
+ {
+ sortStates(bunch.m_nfa_set);
+ }
+
+ return;
+ }
+
+ /***************************************************************
+ Function: move
+ Description: Returns null if resulting NFA set is empty.
+ **************************************************************/
+ void move
+ (
+ Vector nfa_set,
+ SparseBitSet nfa_bit,
+ int b,
+ CBunch bunch
+ )
+ {
+ int size;
+ int index;
+ CNfa state;
+
+ bunch.m_nfa_set = null;
+ bunch.m_nfa_bit = null;
+
+ size = nfa_set.size();
+ for (index = 0; index < size; ++index)
+ {
+ state = (CNfa) nfa_set.elementAt(index);
+
+ if (b == state.m_edge
+ || (CNfa.CCL == state.m_edge
+ && true == state.m_set.contains(b)))
+ {
+ if (null == bunch.m_nfa_set)
+ {
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null == bunch.m_nfa_bit);
+ }
+
+ bunch.m_nfa_set = new Vector();
+ /*bunch.m_nfa_bit
+ = new SparseBitSet(m_spec.m_nfa_states.size());*/
+ bunch.m_nfa_bit = new SparseBitSet();
+ }
+
+ bunch.m_nfa_set.addElement(state.m_next);
+ /*System.out.println("Size of bitset: " + bunch.m_nfa_bit.size());
+ System.out.println("Reference index: " + state.m_next.m_label);
+ System.out.flush();*/
+ bunch.m_nfa_bit.set(state.m_next.m_label);
+ }
+ }
+
+ if (null != bunch.m_nfa_set)
+ {
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != bunch.m_nfa_bit);
+ }
+
+ sortStates(bunch.m_nfa_set);
+ }
+
+ return;
+ }
+
+ /***************************************************************
+ Function: sortStates
+ **************************************************************/
+ private void sortStates
+ (
+ Vector nfa_set
+ )
+ {
+ CNfa elem;
+ int begin;
+ int size;
+ int index;
+ int value;
+ int smallest_index;
+ int smallest_value;
+ CNfa begin_elem;
+
+ size = nfa_set.size();
+ for (begin = 0; begin < size; ++begin)
+ {
+ elem = (CNfa) nfa_set.elementAt(begin);
+ smallest_value = elem.m_label;
+ smallest_index = begin;
+
+ for (index = begin + 1; index < size; ++index)
+ {
+ elem = (CNfa) nfa_set.elementAt(index);
+ value = elem.m_label;
+
+ if (value < smallest_value)
+ {
+ smallest_index = index;
+ smallest_value = value;
+ }
+ }
+
+ begin_elem = (CNfa) nfa_set.elementAt(begin);
+ elem = (CNfa) nfa_set.elementAt(smallest_index);
+ nfa_set.setElementAt(elem,begin);
+ nfa_set.setElementAt(begin_elem,smallest_index);
+ }
+
+ if (CUtility.OLD_DEBUG)
+ {
+ System.out.print("NFA vector indices: ");
+
+ for (index = 0; index < size; ++index)
+ {
+ elem = (CNfa) nfa_set.elementAt(index);
+ System.out.print(elem.m_label + " ");
+ }
+ System.out.println();
+ }
+
+ return;
+ }
+
+ /***************************************************************
+ Function: get_unmarked
+ Description: Returns next unmarked DFA state.
+ **************************************************************/
+ private CDfa get_unmarked
+ (
+ )
+ {
+ int size;
+ CDfa dfa;
+
+ size = m_spec.m_dfa_states.size();
+ while (m_unmarked_dfa < size)
+ {
+ dfa = (CDfa) m_spec.m_dfa_states.elementAt(m_unmarked_dfa);
+
+ if (false == dfa.m_mark)
+ {
+ if (CUtility.OLD_DUMP_DEBUG)
+ {
+ System.out.print("*");
+ System.out.flush();
+ }
+
+ if (m_spec.m_verbose && true == CUtility.OLD_DUMP_DEBUG)
+ {
+ System.out.println("---------------");
+ System.out.print("working on DFA state "
+ + m_unmarked_dfa
+ + " = NFA states: ");
+ m_lexGen.print_set(dfa.m_nfa_set);
+ System.out.println();
+ }
+
+ return dfa;
+ }
+
+ ++m_unmarked_dfa;
+ }
+
+ return null;
+ }
+
+ /***************************************************************
+ function: add_to_dstates
+ Description: Takes as input a CBunch with details of
+ a dfa state that needs to be created.
+ 1) Allocates a new dfa state and saves it in
+ the appropriate CSpec vector.
+ 2) Initializes the fields of the dfa state
+ with the information in the CBunch.
+ 3) Returns index of new dfa.
+ **************************************************************/
+ private int add_to_dstates
+ (
+ CBunch bunch
+ )
+ {
+ CDfa dfa;
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != bunch.m_nfa_set);
+ CUtility.ASSERT(null != bunch.m_nfa_bit);
+ CUtility.ASSERT(null != bunch.m_accept
+ || CSpec.NONE == bunch.m_anchor);
+ }
+
+ /* Allocate, passing CSpec so dfa label can be set. */
+ dfa = CAlloc.newCDfa(m_spec);
+
+ /* Initialize fields, including the mark field. */
+ dfa.m_nfa_set = (Vector) bunch.m_nfa_set.clone();
+ dfa.m_nfa_bit = (SparseBitSet) bunch.m_nfa_bit.clone();
+ dfa.m_accept = bunch.m_accept;
+ dfa.m_anchor = bunch.m_anchor;
+ dfa.m_mark = false;
+
+ /* Register dfa state using BitSet in CSpec Hashtable. */
+ m_spec.m_dfa_sets.put(dfa.m_nfa_bit,dfa);
+ /*registerCDfa(dfa);*/
+
+ if (CUtility.OLD_DUMP_DEBUG)
+ {
+ System.out.print("Registering set : ");
+ m_lexGen.print_set(dfa.m_nfa_set);
+ System.out.println();
+ }
+
+ return dfa.m_label;
+ }
+
+ /***************************************************************
+ Function: in_dstates
+ **************************************************************/
+ private int in_dstates
+ (
+ CBunch bunch
+ )
+ {
+ CDfa dfa;
+
+ if (CUtility.OLD_DEBUG)
+ {
+ System.out.print("Looking for set : ");
+ m_lexGen.print_set(bunch.m_nfa_set);
+ }
+
+ dfa = (CDfa) m_spec.m_dfa_sets.get(bunch.m_nfa_bit);
+
+ if (null != dfa)
+ {
+ if (CUtility.OLD_DUMP_DEBUG)
+ {
+ System.out.println(" FOUND!");
+ }
+
+ return dfa.m_label;
+ }
+
+ if (CUtility.OLD_DUMP_DEBUG)
+ {
+ System.out.println(" NOT FOUND!");
+ }
+ return NOT_IN_DSTATES;
+ }
+
+}
+
+/***************************************************************
+ Class: CAlloc
+ **************************************************************/
+class CAlloc
+{
+ /***************************************************************
+ Function: newCDfa
+ **************************************************************/
+ static CDfa newCDfa
+ (
+ CSpec spec
+ )
+ {
+ CDfa dfa;
+
+ dfa = new CDfa(spec.m_dfa_states.size());
+ spec.m_dfa_states.addElement(dfa);
+
+ return dfa;
+ }
+
+ /***************************************************************
+ Function: newCNfaPair
+ Description:
+ **************************************************************/
+ static CNfaPair newCNfaPair
+ (
+ )
+ {
+ CNfaPair pair = new CNfaPair();
+
+ return pair;
+ }
+ /***************************************************************
+ Function: newNLPair
+ Description: return a new CNfaPair that matches a new
+ line: (\r\n?|[\n\uu2028\uu2029])
+ Added by CSA 8-Aug-1999, updated 10-Aug-1999
+ **************************************************************/
+ static CNfaPair newNLPair(CSpec spec) {
+ CNfaPair pair = newCNfaPair();
+ pair.m_end=newCNfa(spec); // newline accepting state
+ pair.m_start=newCNfa(spec); // new state with two epsilon edges
+ pair.m_start.m_next = newCNfa(spec);
+ pair.m_start.m_next.m_edge = CNfa.CCL;
+ pair.m_start.m_next.m_set = new CSet();
+ pair.m_start.m_next.m_set.add('\n');
+ if (spec.m_dtrans_ncols-CSpec.NUM_PSEUDO > 2029) {
+ pair.m_start.m_next.m_set.add(2028); /*U+2028 is LS, the line separator*/
+ pair.m_start.m_next.m_set.add(2029); /*U+2029 is PS, the paragraph sep.*/
+ }
+ pair.m_start.m_next.m_next = pair.m_end; // accept '\n', U+2028, or U+2029
+ pair.m_start.m_next2 = newCNfa(spec);
+ pair.m_start.m_next2.m_edge = '\r';
+ pair.m_start.m_next2.m_next = newCNfa(spec);
+ pair.m_start.m_next2.m_next.m_next = pair.m_end; // accept '\r';
+ pair.m_start.m_next2.m_next.m_next2 = newCNfa(spec);
+ pair.m_start.m_next2.m_next.m_next2.m_edge = '\n';
+ pair.m_start.m_next2.m_next.m_next2.m_next = pair.m_end; // accept '\r\n';
+ return pair;
+ }
+
+ /***************************************************************
+ Function: newCNfa
+ Description:
+ **************************************************************/
+ static CNfa newCNfa
+ (
+ CSpec spec
+ )
+ {
+ CNfa p;
+
+ /* UNDONE: Buffer this? */
+
+ p = new CNfa();
+
+ /*p.m_label = spec.m_nfa_states.size();*/
+ spec.m_nfa_states.addElement(p);
+ p.m_edge = CNfa.EPSILON;
+
+ return p;
+ }
+}
+
+/***************************************************************
+ Class: Main
+ Description: Top-level lexical analyzer generator function.
+ **************************************************************/
+public class Main
+{
+ /***************************************************************
+ Function: main
+ **************************************************************/
+ public static void main
+ (
+ String arg[]
+ )
+ throws java.io.IOException
+ {
+ CLexGen lg;
+
+ if (arg.length < 1)
+ {
+ System.out.println("Usage: JLex.Main <filename>");
+ return;
+ }
+
+ /* Note: For debuging, it may be helpful to remove the try/catch
+ block and permit the Exception to propagate to the top level.
+ This gives more information. */
+ try
+ {
+ lg = new CLexGen(arg[0]);
+ lg.generate();
+ }
+ catch (Error e)
+ {
+ System.out.println(e.getMessage());
+ }
+ }
+}
+
+/***************************************************************
+ Class: CDTrans
+ **************************************************************/
+class CDTrans
+{
+ /*************************************************************
+ Member Variables
+ ***********************************************************/
+ int m_dtrans[];
+ CAccept m_accept;
+ int m_anchor;
+ int m_label;
+
+ /*************************************************************
+ Constants
+ ***********************************************************/
+ static final int F = -1;
+
+ /*************************************************************
+ Function: CTrans
+ ***********************************************************/
+ CDTrans
+ (
+ int label,
+ CSpec spec
+ )
+ {
+ m_dtrans = new int[spec.m_dtrans_ncols];
+ m_accept = null;
+ m_anchor = CSpec.NONE;
+ m_label = label;
+ }
+}
+
+/***************************************************************
+ Class: CDfa
+ **************************************************************/
+class CDfa
+{
+ /***************************************************************
+ Member Variables
+ ***********************************************************/
+ int m_group;
+ boolean m_mark;
+ CAccept m_accept;
+ int m_anchor;
+ Vector m_nfa_set;
+ SparseBitSet m_nfa_bit;
+ int m_label;
+
+ /***************************************************************
+ Function: CDfa
+ **************************************************************/
+ CDfa
+ (
+ int label
+ )
+ {
+ m_group = 0;
+ m_mark = false;
+
+ m_accept = null;
+ m_anchor = CSpec.NONE;
+
+ m_nfa_set = null;
+ m_nfa_bit = null;
+
+ m_label = label;
+ }
+}
+
+/***************************************************************
+ Class: CAccept
+ **************************************************************/
+class CAccept
+{
+ /***************************************************************
+ Member Variables
+ **************************************************************/
+ char m_action[];
+ int m_action_read;
+ int m_line_number;
+
+ /***************************************************************
+ Function: CAccept
+ **************************************************************/
+ CAccept
+ (
+ char action[],
+ int action_read,
+ int line_number
+ )
+ {
+ int elem;
+
+ m_action_read = action_read;
+
+ m_action = new char[m_action_read];
+ for (elem = 0; elem < m_action_read; ++elem)
+ {
+ m_action[elem] = action[elem];
+ }
+
+ m_line_number = line_number;
+ }
+
+ /***************************************************************
+ Function: CAccept
+ **************************************************************/
+ CAccept
+ (
+ CAccept accept
+ )
+ {
+ int elem;
+
+ m_action_read = accept.m_action_read;
+
+ m_action = new char[m_action_read];
+ for (elem = 0; elem < m_action_read; ++elem)
+ {
+ m_action[elem] = accept.m_action[elem];
+ }
+
+ m_line_number = accept.m_line_number;
+ }
+
+ /***************************************************************
+ Function: mimic
+ **************************************************************/
+ void mimic
+ (
+ CAccept accept
+ )
+ {
+ int elem;
+
+ m_action_read = accept.m_action_read;
+
+ m_action = new char[m_action_read];
+ for (elem = 0; elem < m_action_read; ++elem)
+ {
+ m_action[elem] = accept.m_action[elem];
+ }
+ }
+}
+
+/***************************************************************
+ Class: CAcceptAnchor
+ **************************************************************/
+class CAcceptAnchor
+{
+ /***************************************************************
+ Member Variables
+ **************************************************************/
+ CAccept m_accept;
+ int m_anchor;
+
+ /***************************************************************
+ Function: CAcceptAnchor
+ **************************************************************/
+ CAcceptAnchor
+ (
+ )
+ {
+ m_accept = null;
+ m_anchor = CSpec.NONE;
+ }
+}
+
+/***************************************************************
+ Class: CNfaPair
+ **************************************************************/
+class CNfaPair
+{
+ /***************************************************************
+ Member Variables
+ **************************************************************/
+ CNfa m_start;
+ CNfa m_end;
+
+ /***************************************************************
+ Function: CNfaPair
+ **************************************************************/
+ CNfaPair
+ (
+ )
+ {
+ m_start = null;
+ m_end = null;
+ }
+}
+
+/***************************************************************
+ Class: CInput
+ Description:
+ **************************************************************/
+class CInput
+{
+ /***************************************************************
+ Member Variables
+ **************************************************************/
+ private java.io.BufferedReader m_input; /* JLex specification file. */
+
+ boolean m_eof_reached; /* Whether EOF has been encountered. */
+ boolean m_pushback_line;
+
+ char m_line[]; /* Line buffer. */
+ int m_line_read; /* Number of bytes read into line buffer. */
+ int m_line_index; /* Current index into line buffer. */
+
+ int m_line_number; /* Current line number. */
+
+ /***************************************************************
+ Constants
+ **************************************************************/
+ static final boolean EOF = true;
+ static final boolean NOT_EOF = false;
+
+ /***************************************************************
+ Function: CInput
+ Description:
+ **************************************************************/
+ CInput
+ (
+ java.io.Reader input
+ )
+ {
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != input);
+ }
+
+ /* Initialize input stream. */
+ m_input = new java.io.BufferedReader(input);
+
+ /* Initialize buffers and index counters. */
+ m_line = null;
+ m_line_read = 0;
+ m_line_index = 0;
+
+ /* Initialize state variables. */
+ m_eof_reached = false;
+ m_line_number = 0;
+ m_pushback_line = false;
+ }
+
+ /***************************************************************
+ Function: getLine
+ Description: Returns true on EOF, false otherwise.
+ Guarantees not to return a blank line, or a line
+ of zero length.
+ **************************************************************/
+ boolean getLine
+ (
+ )
+ throws java.io.IOException
+ {
+ String lineStr;
+ int elem;
+
+ /* Has EOF already been reached? */
+ if (m_eof_reached)
+ {
+ return EOF;
+ }
+
+ /* Pushback current line? */
+ if (m_pushback_line)
+ {
+ m_pushback_line = false;
+
+ /* Check for empty line. */
+ for (elem = 0; elem < m_line_read; ++elem)
+ {
+ if (false == CUtility.isspace(m_line[elem]))
+ {
+ break;
+ }
+ }
+
+ /* Nonempty? */
+ if (elem < m_line_read)
+ {
+ m_line_index = 0;
+ return NOT_EOF;
+ }
+ }
+
+ while (true)
+ {
+ if (null == (lineStr = m_input.readLine()))
+ {
+ m_eof_reached = true;
+ m_line_index = 0;
+ return EOF;
+ }
+ m_line = (lineStr + "\n").toCharArray();
+ m_line_read=m_line.length;
+ ++m_line_number;
+
+ /* Check for empty lines and discard them. */
+ elem = 0;
+ while (CUtility.isspace(m_line[elem]))
+ {
+ ++elem;
+ if (elem == m_line_read)
+ {
+ break;
+ }
+ }
+
+ if (elem < m_line_read)
+ {
+ break;
+ }
+ }
+
+ m_line_index = 0;
+ return NOT_EOF;
+ }
+}
+
+/********************************************************
+ Class: Utility
+ *******************************************************/
+class CUtility
+{
+ /********************************************************
+ Constants
+ *******************************************************/
+ static final boolean DEBUG = true;
+ static final boolean SLOW_DEBUG = true;
+ static final boolean DUMP_DEBUG = true;
+ /*static final boolean DEBUG = false;
+ static final boolean SLOW_DEBUG = false;
+ static final boolean DUMP_DEBUG = false;*/
+ static final boolean DESCENT_DEBUG = false;
+ static final boolean OLD_DEBUG = false;
+ static final boolean OLD_DUMP_DEBUG = false;
+ static final boolean FOODEBUG = false;
+ static final boolean DO_DEBUG = false;
+
+ /********************************************************
+ Constants: Integer Bounds
+ *******************************************************/
+ static final int INT_MAX = 2147483647;
+
+ static final int MAX_SEVEN_BIT = 127;
+ static final int MAX_EIGHT_BIT = 255;
+ static final int MAX_SIXTEEN_BIT=65535;
+
+ /********************************************************
+ Function: enter
+ Description: Debugging routine.
+ *******************************************************/
+ static void enter
+ (
+ String descent,
+ char lexeme,
+ int token
+ )
+ {
+ System.out.println("Entering " + descent
+ + " [lexeme: " + lexeme
+ + "] [token: " + token + "]");
+ }
+
+ /********************************************************
+ Function: leave
+ Description: Debugging routine.
+ *******************************************************/
+ static void leave
+ (
+ String descent,
+ char lexeme,
+ int token
+ )
+ {
+ System.out.println("Leaving " + descent
+ + " [lexeme:" + lexeme
+ + "] [token:" + token + "]");
+ }
+
+ /********************************************************
+ Function: ASSERT
+ Description: Debugging routine.
+ *******************************************************/
+ static void ASSERT
+ (
+ boolean expr
+ )
+ {
+ if (DEBUG && false == expr)
+ {
+ System.out.println("Assertion Failed");
+ throw new Error("Assertion Failed.");
+ }
+ }
+
+ /***************************************************************
+ Function: doubleSize
+ **************************************************************/
+ static char[] doubleSize
+ (
+ char oldBuffer[]
+ )
+ {
+ char newBuffer[] = new char[2 * oldBuffer.length];
+ int elem;
+
+ for (elem = 0; elem < oldBuffer.length; ++elem)
+ {
+ newBuffer[elem] = oldBuffer[elem];
+ }
+
+ return newBuffer;
+ }
+
+ /***************************************************************
+ Function: doubleSize
+ **************************************************************/
+ static byte[] doubleSize
+ (
+ byte oldBuffer[]
+ )
+ {
+ byte newBuffer[] = new byte[2 * oldBuffer.length];
+ int elem;
+
+ for (elem = 0; elem < oldBuffer.length; ++elem)
+ {
+ newBuffer[elem] = oldBuffer[elem];
+ }
+
+ return newBuffer;
+ }
+
+ /********************************************************
+ Function: hex2bin
+ *******************************************************/
+ static char hex2bin
+ (
+ char c
+ )
+ {
+ if ('0' <= c && '9' >= c)
+ {
+ return (char) (c - '0');
+ }
+ else if ('a' <= c && 'f' >= c)
+ {
+ return (char) (c - 'a' + 10);
+ }
+ else if ('A' <= c && 'F' >= c)
+ {
+ return (char) (c - 'A' + 10);
+ }
+
+ CError.impos("Bad hexidecimal digit" + c);
+ return 0;
+ }
+
+ /********************************************************
+ Function: ishexdigit
+ *******************************************************/
+ static boolean ishexdigit
+ (
+ char c
+ )
+ {
+ if (('0' <= c && '9' >= c)
+ || ('a' <= c && 'f' >= c)
+ || ('A' <= c && 'F' >= c))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /********************************************************
+ Function: oct2bin
+ *******************************************************/
+ static char oct2bin
+ (
+ char c
+ )
+ {
+ if ('0' <= c && '7' >= c)
+ {
+ return (char) (c - '0');
+ }
+
+ CError.impos("Bad octal digit " + c);
+ return 0;
+ }
+
+ /********************************************************
+ Function: isoctdigit
+ *******************************************************/
+ static boolean isoctdigit
+ (
+ char c
+ )
+ {
+ if ('0' <= c && '7' >= c)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /********************************************************
+ Function: isspace
+ *******************************************************/
+ static boolean isspace
+ (
+ char c
+ )
+ {
+ if ('\b' == c
+ || '\t' == c
+ || '\n' == c
+ || '\f' == c
+ || '\r' == c
+ || ' ' == c)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /********************************************************
+ Function: isnewline
+ *******************************************************/
+ static boolean isnewline
+ (
+ char c
+ )
+ {
+ if ('\n' == c
+ || '\r' == c)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /********************************************************
+ Function: bytencmp
+ Description: Compares up to n elements of
+ byte array a[] against byte array b[].
+ The first byte comparison is made between
+ a[a_first] and b[b_first]. Comparisons continue
+ until the null terminating byte '\0' is reached
+ or until n bytes are compared.
+ Return Value: Returns 0 if arrays are the
+ same up to and including the null terminating byte
+ or up to and including the first n bytes,
+ whichever comes first.
+ *******************************************************/
+ static int bytencmp
+ (
+ byte a[],
+ int a_first,
+ byte b[],
+ int b_first,
+ int n
+ )
+ {
+ int elem;
+
+ for (elem = 0; elem < n; ++elem)
+ {
+ /*System.out.print((char) a[a_first + elem]);
+ System.out.print((char) b[b_first + elem]);*/
+
+ if ('\0' == a[a_first + elem] && '\0' == b[b_first + elem])
+ {
+ /*System.out.println("return 0");*/
+ return 0;
+ }
+ if (a[a_first + elem] < b[b_first + elem])
+ {
+ /*System.out.println("return 1");*/
+ return 1;
+ }
+ else if (a[a_first + elem] > b[b_first + elem])
+ {
+ /*System.out.println("return -1");*/
+ return -1;
+ }
+ }
+
+ /*System.out.println("return 0");*/
+ return 0;
+ }
+
+ /********************************************************
+ Function: charncmp
+ *******************************************************/
+ static int charncmp
+ (
+ char a[],
+ int a_first,
+ char b[],
+ int b_first,
+ int n
+ )
+ {
+ int elem;
+
+ for (elem = 0; elem < n; ++elem)
+ {
+ if ('\0' == a[a_first + elem] && '\0' == b[b_first + elem])
+ {
+ return 0;
+ }
+ if (a[a_first + elem] < b[b_first + elem])
+ {
+ return 1;
+ }
+ else if (a[a_first + elem] > b[b_first + elem])
+ {
+ return -1;
+ }
+ }
+
+ return 0;
+ }
+}
+
+/********************************************************
+ Class: CError
+ *******************************************************/
+class CError
+{
+ /********************************************************
+ Function: impos
+ Description:
+ *******************************************************/
+ static void impos
+ (
+ String message
+ )
+ {
+ System.out.println("JLex Error: " + message);
+ }
+
+ /********************************************************
+ Constants
+ Description: Error codes for parse_error().
+ *******************************************************/
+ static final int E_BADEXPR = 0;
+ static final int E_PAREN = 1;
+ static final int E_LENGTH = 2;
+ static final int E_BRACKET = 3;
+ static final int E_BOL = 4;
+ static final int E_CLOSE = 5;
+ static final int E_NEWLINE = 6;
+ static final int E_BADMAC = 7;
+ static final int E_NOMAC = 8;
+ static final int E_MACDEPTH = 9;
+ static final int E_INIT = 10;
+ static final int E_EOF = 11;
+ static final int E_DIRECT = 12;
+ static final int E_INTERNAL = 13;
+ static final int E_STATE = 14;
+ static final int E_MACDEF = 15;
+ static final int E_SYNTAX = 16;
+ static final int E_BRACE = 17;
+ static final int E_DASH = 18;
+ static final int E_ZERO = 19;
+ static final int E_BADCTRL = 20;
+
+ /********************************************************
+ Constants
+ Description: String messages for parse_error();
+ *******************************************************/
+ static final String errmsg[] =
+ {
+ "Malformed regular expression.",
+ "Missing close parenthesis.",
+ "Too many regular expressions or expression too long.",
+ "Missing [ in character class.",
+ "^ must be at start of expression or after [.",
+ "+ ? or * must follow an expression or subexpression.",
+ "Newline in quoted string.",
+ "Missing } in macro expansion.",
+ "Macro does not exist.",
+ "Macro expansions nested too deeply.",
+ "JLex has not been successfully initialized.",
+ "Unexpected end-of-file found.",
+ "Undefined or badly-formed JLex directive.",
+ "Internal JLex error.",
+ "Unitialized state name.",
+ "Badly formed macro definition.",
+ "Syntax error.",
+ "Missing brace at start of lexical action.",
+ "Special character dash - in character class [...] must\n"
+ + "\tbe preceded by start-of-range character.",
+ "Zero-length regular expression.",
+ "Illegal \\^C-style escape sequence (character following caret must\n"
+ + "\tbe alphabetic).",
+ };
+
+ /********************************************************
+ Function: parse_error
+ Description:
+ *******************************************************/
+ static void parse_error
+ (
+ int error_code,
+ int line_number
+ )
+ {
+ System.out.println("Error: Parse error at line "
+ + line_number + ".");
+ System.out.println("Description: " + errmsg[error_code]);
+ throw new Error("Parse error.");
+ }
+}
+
+/********************************************************
+ Class: CSet
+ *******************************************************/
+class CSet
+{
+ /********************************************************
+ Member Variables
+ *******************************************************/
+ private SparseBitSet m_set;
+ private boolean m_complement;
+
+ /********************************************************
+ Function: CSet
+ *******************************************************/
+ CSet
+ (
+ )
+ {
+ m_set = new SparseBitSet();
+ m_complement = false;
+ }
+
+ /********************************************************
+ Function: complement
+ *******************************************************/
+ void complement
+ (
+ )
+ {
+ m_complement = true;
+ }
+
+ /********************************************************
+ Function: add
+ *******************************************************/
+ void add
+ (
+ int i
+ )
+ {
+ m_set.set(i);
+ }
+
+ /********************************************************
+ Function: addncase
+ *******************************************************/
+ void addncase // add, ignoring case.
+ (
+ char c
+ )
+ {
+ /* Do this in a Unicode-friendly way. */
+ /* (note that duplicate adds have no effect) */
+ add(c);
+ add(Character.toLowerCase(c));
+ add(Character.toTitleCase(c));
+ add(Character.toUpperCase(c));
+ }
+
+ /********************************************************
+ Function: contains
+ *******************************************************/
+ boolean contains
+ (
+ int i
+ )
+ {
+ boolean result;
+
+ result = m_set.get(i);
+
+ if (m_complement)
+ {
+ return (false == result);
+ }
+
+ return result;
+ }
+
+ /********************************************************
+ Function: mimic
+ *******************************************************/
+ void mimic
+ (
+ CSet set
+ )
+ {
+ m_complement = set.m_complement;
+ m_set = (SparseBitSet) set.m_set.clone();
+ }
+
+ /** Map set using character classes [CSA] */
+ void map(CSet set, int[] mapping) {
+ m_complement = set.m_complement;
+ m_set.clearAll();
+ for (Enumeration e=set.m_set.elements(); e.hasMoreElements(); ) {
+ int old_value =((Integer)e.nextElement()).intValue();
+ if (old_value<mapping.length) // skip unmapped characters
+ m_set.set(mapping[old_value]);
+ }
+ }
+}
+
+/********************************************************
+ Class: CNfa
+ *******************************************************/
+class CNfa
+{
+ /********************************************************
+ Member Variables
+ *******************************************************/
+ int m_edge; /* Label for edge type:
+ character code,
+ CCL (character class),
+ [STATE,
+ SCL (state class),]
+ EMPTY,
+ EPSILON. */
+
+ CSet m_set; /* Set to store character classes. */
+ CNfa m_next; /* Next state (or null if none). */
+
+ CNfa m_next2; /* Another state with type == EPSILON
+ and null if not used.
+ The NFA construction should result in two
+ outgoing edges only if both are EPSILON edges. */
+
+ CAccept m_accept; /* Set to null if nonaccepting state. */
+ int m_anchor; /* Says if and where pattern is anchored. */
+
+ int m_label;
+
+ SparseBitSet m_states;
+
+ /********************************************************
+ Constants
+ *******************************************************/
+ static final int NO_LABEL = -1;
+
+ /********************************************************
+ Constants: Edge Types
+ Note: Edge transitions on one specific character
+ are labelled with the character Ascii (Unicode)
+ codes. So none of the constants below should
+ overlap with the natural character codes.
+ *******************************************************/
+ static final int CCL = -1;
+ static final int EMPTY = -2;
+ static final int EPSILON = -3;
+
+ /********************************************************
+ Function: CNfa
+ *******************************************************/
+ CNfa
+ (
+ )
+ {
+ m_edge = EMPTY;
+ m_set = null;
+ m_next = null;
+ m_next2 = null;
+ m_accept = null;
+ m_anchor = CSpec.NONE;
+ m_label = NO_LABEL;
+ m_states = null;
+ }
+
+ /********************************************************
+ Function: mimic
+ Description: Converts this NFA state into a copy of
+ the input one.
+ *******************************************************/
+ void mimic
+ (
+ CNfa nfa
+ )
+ {
+ m_edge = nfa.m_edge;
+
+ if (null != nfa.m_set)
+ {
+ if (null == m_set)
+ {
+ m_set = new CSet();
+ }
+ m_set.mimic(nfa.m_set);
+ }
+ else
+ {
+ m_set = null;
+ }
+
+ m_next = nfa.m_next;
+ m_next2 = nfa.m_next2;
+ m_accept = nfa.m_accept;
+ m_anchor = nfa.m_anchor;
+
+ if (null != nfa.m_states)
+ {
+ m_states = (SparseBitSet) nfa.m_states.clone();
+ }
+ else
+ {
+ m_states = null;
+ }
+ }
+}
+
+/***************************************************************
+ Class: CLexGen
+ **************************************************************/
+class CLexGen
+{
+ /***************************************************************
+ Member Variables
+ **************************************************************/
+ private java.io.Reader m_instream; /* JLex specification file. */
+ private java.io.PrintWriter m_outstream; /* Lexical analyzer source file. */
+
+ private CInput m_input; /* Input buffer class. */
+
+ private Hashtable m_tokens; /* Hashtable that maps characters to their
+ corresponding lexical code for
+ the internal lexical analyzer. */
+ private CSpec m_spec; /* Spec class holds information
+ about the generated lexer. */
+ private boolean m_init_flag; /* Flag set to true only upon
+ successful initialization. */
+
+ private CMakeNfa m_makeNfa; /* NFA machine generator module. */
+ private CNfa2Dfa m_nfa2dfa; /* NFA to DFA machine (transition table)
+ conversion module. */
+ private CMinimize m_minimize; /* Transition table compressor. */
+ private CSimplifyNfa m_simplifyNfa; /* NFA simplifier using char classes */
+ private CEmit m_emit; /* Output module that emits source code
+ into the generated lexer file. */
+
+
+ /********************************************************
+ Constants
+ *******************************************************/
+ private static final boolean ERROR = false;
+ private static final boolean NOT_ERROR = true;
+ private static final int BUFFER_SIZE = 1024;
+
+ /********************************************************
+ Constants: Token Types
+ *******************************************************/
+ static final int EOS = 1;
+ static final int ANY = 2;
+ static final int AT_BOL = 3;
+ static final int AT_EOL = 4;
+ static final int CCL_END = 5;
+ static final int CCL_START = 6;
+ static final int CLOSE_CURLY = 7;
+ static final int CLOSE_PAREN = 8;
+ static final int CLOSURE = 9;
+ static final int DASH = 10;
+ static final int END_OF_INPUT = 11;
+ static final int L = 12;
+ static final int OPEN_CURLY = 13;
+ static final int OPEN_PAREN = 14;
+ static final int OPTIONAL = 15;
+ static final int OR = 16;
+ static final int PLUS_CLOSE = 17;
+
+ /***************************************************************
+ Function: CLexGen
+ **************************************************************/
+ CLexGen
+ (
+ String filename
+ )
+ throws java.io.FileNotFoundException, java.io.IOException
+ {
+ /* Successful initialization flag. */
+ m_init_flag = false;
+
+ /* Open input stream. */
+ m_instream = new java.io.FileReader(filename);
+ if (null == m_instream)
+ {
+ System.out.println("Error: Unable to open input file "
+ + filename + ".");
+ return;
+ }
+
+ /* Open output stream. */
+ m_outstream
+ = new java.io.PrintWriter(new java.io.BufferedWriter(
+ new java.io.FileWriter(filename + ".java")));
+ if (null == m_outstream)
+ {
+ System.out.println("Error: Unable to open output file "
+ + filename + ".java.");
+ return;
+ }
+
+ /* Create input buffer class. */
+ m_input = new CInput(m_instream);
+
+ /* Initialize character hash table. */
+ m_tokens = new Hashtable();
+ m_tokens.put(new Character('$'),new Integer(AT_EOL));
+ m_tokens.put(new Character('('),new Integer(OPEN_PAREN));
+ m_tokens.put(new Character(')'),new Integer(CLOSE_PAREN));
+ m_tokens.put(new Character('*'),new Integer(CLOSURE));
+ m_tokens.put(new Character('+'),new Integer(PLUS_CLOSE));
+ m_tokens.put(new Character('-'),new Integer(DASH));
+ m_tokens.put(new Character('.'),new Integer(ANY));
+ m_tokens.put(new Character('?'),new Integer(OPTIONAL));
+ m_tokens.put(new Character('['),new Integer(CCL_START));
+ m_tokens.put(new Character(']'),new Integer(CCL_END));
+ m_tokens.put(new Character('^'),new Integer(AT_BOL));
+ m_tokens.put(new Character('{'),new Integer(OPEN_CURLY));
+ m_tokens.put(new Character('|'),new Integer(OR));
+ m_tokens.put(new Character('}'),new Integer(CLOSE_CURLY));
+
+ /* Initialize spec structure. */
+ m_spec = new CSpec(this);
+
+ /* Nfa to dfa converter. */
+ m_nfa2dfa = new CNfa2Dfa();
+ m_minimize = new CMinimize();
+ m_makeNfa = new CMakeNfa();
+ m_simplifyNfa = new CSimplifyNfa();
+
+ m_emit = new CEmit();
+
+ /* Successful initialization flag. */
+ m_init_flag = true;
+ }
+
+ /***************************************************************
+ Function: generate
+ Description:
+ **************************************************************/
+ void generate
+ (
+ )
+ throws java.io.IOException, java.io.FileNotFoundException
+ {
+ if (false == m_init_flag)
+ {
+ CError.parse_error(CError.E_INIT,0);
+ }
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != this);
+ CUtility.ASSERT(null != m_outstream);
+ CUtility.ASSERT(null != m_input);
+ CUtility.ASSERT(null != m_tokens);
+ CUtility.ASSERT(null != m_spec);
+ CUtility.ASSERT(m_init_flag);
+ }
+
+ /*m_emit.emit_imports(m_spec,m_outstream);*/
+
+ if (m_spec.m_verbose)
+ {
+ System.out.println("Processing first section -- user code.");
+ }
+ userCode();
+ if (m_input.m_eof_reached)
+ {
+ CError.parse_error(CError.E_EOF,m_input.m_line_number);
+ }
+
+ if (m_spec.m_verbose)
+ {
+ System.out.println("Processing second section -- "
+ + "JLex declarations.");
+ }
+ userDeclare();
+ if (m_input.m_eof_reached)
+ {
+ CError.parse_error(CError.E_EOF,m_input.m_line_number);
+ }
+
+ if (m_spec.m_verbose)
+ {
+ System.out.println("Processing third section -- lexical rules.");
+ }
+ userRules();
+ if (CUtility.DO_DEBUG)
+ {
+ print_header();
+ }
+
+ if (m_spec.m_verbose)
+ {
+ System.out.println("Outputting lexical analyzer code.");
+ }
+ m_emit.emit(m_spec,m_outstream);
+
+ if (m_spec.m_verbose && true == CUtility.OLD_DUMP_DEBUG)
+ {
+ details();
+ }
+
+ m_outstream.close();
+ }
+
+ /***************************************************************
+ Function: userCode
+ Description: Process first section of specification,
+ echoing it into output file.
+ **************************************************************/
+ private void userCode
+ (
+ )
+ throws java.io.IOException
+ {
+ int count = 0;
+
+ if (false == m_init_flag)
+ {
+ CError.parse_error(CError.E_INIT,0);
+ }
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != this);
+ CUtility.ASSERT(null != m_outstream);
+ CUtility.ASSERT(null != m_input);
+ CUtility.ASSERT(null != m_tokens);
+ CUtility.ASSERT(null != m_spec);
+ }
+
+ if (m_input.m_eof_reached)
+ {
+ CError.parse_error(CError.E_EOF,0);
+ }
+
+ while (true)
+ {
+ if (m_input.getLine())
+ {
+ /* Eof reached. */
+ CError.parse_error(CError.E_EOF,0);
+ }
+
+ if (2 <= m_input.m_line_read
+ && '%' == m_input.m_line[0]
+ && '%' == m_input.m_line[1])
+ {
+ /* Discard remainder of line. */
+ m_input.m_line_index = m_input.m_line_read;
+ return;
+ }
+
+ m_outstream.print(new String(m_input.m_line,0,
+ m_input.m_line_read));
+ }
+ }
+
+ /***************************************************************
+ Function: getName
+ **************************************************************/
+ private char[] getName
+ (
+ )
+ {
+ char buffer[];
+ int elem;
+
+ /* Skip white space. */
+ while (m_input.m_line_index < m_input.m_line_read
+ && true == CUtility.isspace(m_input.m_line[m_input.m_line_index]))
+ {
+ ++m_input.m_line_index;
+ }
+
+ /* No name? */
+ if (m_input.m_line_index >= m_input.m_line_read)
+ {
+ CError.parse_error(CError.E_DIRECT,0);
+ }
+
+ /* Determine length. */
+ elem = m_input.m_line_index;
+ while (elem < m_input.m_line_read
+ && false == CUtility.isnewline(m_input.m_line[elem]))
+ {
+ ++elem;
+ }
+
+ /* Allocate non-terminated buffer of exact length. */
+ buffer = new char[elem - m_input.m_line_index];
+
+ /* Copy. */
+ elem = 0;
+ while (m_input.m_line_index < m_input.m_line_read
+ && false == CUtility.isnewline(m_input.m_line[m_input.m_line_index]))
+ {
+ buffer[elem] = m_input.m_line[m_input.m_line_index];
+ ++elem;
+ ++m_input.m_line_index;
+ }
+
+ return buffer;
+ }
+
+ private final int CLASS_CODE = 0;
+ private final int INIT_CODE = 1;
+ private final int EOF_CODE = 2;
+ private final int INIT_THROW_CODE = 3;
+ private final int YYLEX_THROW_CODE = 4;
+ private final int EOF_THROW_CODE = 5;
+ private final int EOF_VALUE_CODE = 6;
+
+ /***************************************************************
+ Function: packCode
+ Description:
+ **************************************************************/
+ private char[] packCode
+ (
+ char start_dir[],
+ char end_dir[],
+ char prev_code[],
+ int prev_read,
+ int specified
+ )
+ throws java.io.IOException
+ {
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(INIT_CODE == specified
+ || CLASS_CODE == specified
+ || EOF_CODE == specified
+ || EOF_VALUE_CODE == specified
+ || INIT_THROW_CODE == specified
+ || YYLEX_THROW_CODE == specified
+ || EOF_THROW_CODE == specified);
+ }
+
+ if (0 != CUtility.charncmp(m_input.m_line,
+ 0,
+ start_dir,
+ 0,
+ start_dir.length - 1))
+ {
+ CError.parse_error(CError.E_INTERNAL,0);
+ }
+
+ if (null == prev_code)
+ {
+ prev_code = new char[BUFFER_SIZE];
+ prev_read = 0;
+ }
+
+ if (prev_read >= prev_code.length)
+ {
+ prev_code = CUtility.doubleSize(prev_code);
+ }
+
+ m_input.m_line_index = start_dir.length - 1;
+ while (true)
+ {
+ while (m_input.m_line_index >= m_input.m_line_read)
+ {
+ if (m_input.getLine())
+ {
+ CError.parse_error(CError.E_EOF,m_input.m_line_number);
+ }
+
+ if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ end_dir,
+ 0,
+ end_dir.length - 1))
+ {
+ m_input.m_line_index = end_dir.length - 1;
+
+ switch (specified)
+ {
+ case CLASS_CODE:
+ m_spec.m_class_read = prev_read;
+ break;
+
+ case INIT_CODE:
+ m_spec.m_init_read = prev_read;
+ break;
+
+ case EOF_CODE:
+ m_spec.m_eof_read = prev_read;
+ break;
+
+ case EOF_VALUE_CODE:
+ m_spec.m_eof_value_read = prev_read;
+ break;
+
+ case INIT_THROW_CODE:
+ m_spec.m_init_throw_read = prev_read;
+ break;
+
+ case YYLEX_THROW_CODE:
+ m_spec.m_yylex_throw_read = prev_read;
+ break;
+
+ case EOF_THROW_CODE:
+ m_spec.m_eof_throw_read = prev_read;
+ break;
+
+ default:
+ CError.parse_error(CError.E_INTERNAL,m_input.m_line_number);
+ break;
+ }
+
+ return prev_code;
+ }
+ }
+
+ while (m_input.m_line_index < m_input.m_line_read)
+ {
+ prev_code[prev_read] = m_input.m_line[m_input.m_line_index];
+ ++prev_read;
+ ++m_input.m_line_index;
+
+ if (prev_read >= prev_code.length)
+ {
+ prev_code = CUtility.doubleSize(prev_code);
+ }
+ }
+ }
+ }
+
+ /***************************************************************
+ Member Variables: JLex directives.
+ **************************************************************/
+ private char m_state_dir[] = {
+ '%', 's', 't',
+ 'a', 't', 'e',
+ '\0'
+ };
+
+ private char m_char_dir[] = {
+ '%', 'c', 'h',
+ 'a', 'r',
+ '\0'
+ };
+
+ private char m_line_dir[] = {
+ '%', 'l', 'i',
+ 'n', 'e',
+ '\0'
+ };
+
+ private char m_cup_dir[] = {
+ '%', 'c', 'u',
+ 'p',
+ '\0'
+ };
+
+ private char m_class_dir[] = {
+ '%', 'c', 'l',
+ 'a', 's', 's',
+ '\0'
+ };
+
+ private char m_implements_dir[] = {
+ '%', 'i', 'm', 'p', 'l', 'e', 'm', 'e', 'n', 't', 's',
+ '\0'
+ };
+
+ private char m_function_dir[] = {
+ '%', 'f', 'u',
+ 'n', 'c', 't',
+ 'i', 'o', 'n',
+ '\0'
+ };
+
+ private char m_type_dir[] = {
+ '%', 't', 'y',
+ 'p', 'e',
+ '\0'
+ };
+
+ private char m_integer_dir[] = {
+ '%', 'i', 'n',
+ 't', 'e', 'g',
+ 'e', 'r',
+ '\0'
+ };
+
+ private char m_intwrap_dir[] = {
+ '%', 'i', 'n',
+ 't', 'w', 'r',
+ 'a', 'p',
+ '\0'
+ };
+
+ private char m_full_dir[] = {
+ '%', 'f', 'u',
+ 'l', 'l',
+ '\0'
+ };
+
+ private char m_unicode_dir[] = {
+ '%', 'u', 'n',
+ 'i', 'c', 'o',
+ 'd', 'e',
+ '\0'
+ };
+
+ private char m_ignorecase_dir[] = {
+ '%', 'i', 'g',
+ 'n', 'o', 'r',
+ 'e', 'c', 'a',
+ 's', 'e',
+ '\0'
+ };
+
+ private char m_notunix_dir[] = {
+ '%', 'n', 'o',
+ 't', 'u', 'n',
+ 'i', 'x',
+ '\0'
+ };
+
+ private char m_init_code_dir[] = {
+ '%', 'i', 'n',
+ 'i', 't', '{',
+ '\0'
+ };
+
+ private char m_init_code_end_dir[] = {
+ '%', 'i', 'n',
+ 'i', 't', '}',
+ '\0'
+ };
+
+ private char m_init_throw_code_dir[] = {
+ '%', 'i', 'n',
+ 'i', 't', 't',
+ 'h', 'r', 'o',
+ 'w', '{',
+ '\0'
+ };
+
+ private char m_init_throw_code_end_dir[] = {
+ '%', 'i', 'n',
+ 'i', 't', 't',
+ 'h', 'r', 'o',
+ 'w', '}',
+ '\0'
+ };
+
+ private char m_yylex_throw_code_dir[] = {
+ '%', 'y', 'y', 'l',
+ 'e', 'x', 't',
+ 'h', 'r', 'o',
+ 'w', '{',
+ '\0'
+ };
+
+ private char m_yylex_throw_code_end_dir[] = {
+ '%', 'y', 'y', 'l',
+ 'e', 'x', 't',
+ 'h', 'r', 'o',
+ 'w', '}',
+ '\0'
+ };
+
+ private char m_eof_code_dir[] = {
+ '%', 'e', 'o',
+ 'f', '{',
+ '\0'
+ };
+
+ private char m_eof_code_end_dir[] = {
+ '%', 'e', 'o',
+ 'f', '}',
+ '\0'
+ };
+
+ private char m_eof_value_code_dir[] = {
+ '%', 'e', 'o',
+ 'f', 'v', 'a',
+ 'l', '{',
+ '\0'
+ };
+
+ private char m_eof_value_code_end_dir[] = {
+ '%', 'e', 'o',
+ 'f', 'v', 'a',
+ 'l', '}',
+ '\0'
+ };
+
+ private char m_eof_throw_code_dir[] = {
+ '%', 'e', 'o',
+ 'f', 't', 'h',
+ 'r', 'o', 'w',
+ '{',
+ '\0'
+ };
+
+ private char m_eof_throw_code_end_dir[] = {
+ '%', 'e', 'o',
+ 'f', 't', 'h',
+ 'r', 'o', 'w',
+ '}',
+ '\0'
+ };
+
+ private char m_class_code_dir[] = {
+ '%', '{',
+ '\0'
+ };
+
+ private char m_class_code_end_dir[] = {
+ '%', '}',
+ '\0'
+ };
+
+ private char m_yyeof_dir[] = {
+ '%', 'y', 'y',
+ 'e', 'o', 'f',
+ '\0'
+ };
+
+ private char m_public_dir[] = {
+ '%', 'p', 'u',
+ 'b', 'l', 'i',
+ 'c', '\0'
+ };
+
+ /***************************************************************
+ Function: userDeclare
+ Description:
+ **************************************************************/
+ private void userDeclare
+ (
+ )
+ throws java.io.IOException
+ {
+ int elem;
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != this);
+ CUtility.ASSERT(null != m_outstream);
+ CUtility.ASSERT(null != m_input);
+ CUtility.ASSERT(null != m_tokens);
+ CUtility.ASSERT(null != m_spec);
+ }
+
+ if (m_input.m_eof_reached)
+ {
+ /* End-of-file. */
+ CError.parse_error(CError.E_EOF,
+ m_input.m_line_number);
+ }
+
+ while (false == m_input.getLine())
+ {
+ /* Look for double percent. */
+ if (2 <= m_input.m_line_read
+ && '%' == m_input.m_line[0]
+ && '%' == m_input.m_line[1])
+ {
+ /* Mess around with line. */
+ m_input.m_line_read -= 2;
+ System.arraycopy(m_input.m_line, 2,
+ m_input.m_line, 0, m_input.m_line_read);
+
+ m_input.m_pushback_line = true;
+ /* Check for and discard empty line. */
+ if (0 == m_input.m_line_read
+ || '\n' == m_input.m_line[0])
+ {
+ m_input.m_pushback_line = false;
+ }
+
+ return;
+ }
+
+ if (0 == m_input.m_line_read)
+ {
+ continue;
+ }
+
+ if ('%' == m_input.m_line[0])
+ {
+ /* Special lex declarations. */
+ if (1 >= m_input.m_line_read)
+ {
+ CError.parse_error(CError.E_DIRECT,
+ m_input.m_line_number);
+ continue;
+ }
+
+ switch (m_input.m_line[1])
+ {
+ case '{':
+ if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_class_code_dir,
+ 0,
+ m_class_code_dir.length - 1))
+ {
+ m_spec.m_class_code = packCode(m_class_code_dir,
+ m_class_code_end_dir,
+ m_spec.m_class_code,
+ m_spec.m_class_read,
+ CLASS_CODE);
+ break;
+ }
+
+ /* Bad directive. */
+ CError.parse_error(CError.E_DIRECT,
+ m_input.m_line_number);
+ break;
+
+ case 'c':
+ if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_char_dir,
+ 0,
+ m_char_dir.length - 1))
+ {
+ /* Set line counting to ON. */
+ m_input.m_line_index = m_char_dir.length;
+ m_spec.m_count_chars = true;
+ break;
+ }
+ else if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_class_dir,
+ 0,
+ m_class_dir.length - 1))
+ {
+ m_input.m_line_index = m_class_dir.length;
+ m_spec.m_class_name = getName();
+ break;
+ }
+ else if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_cup_dir,
+ 0,
+ m_cup_dir.length - 1))
+ {
+ /* Set Java CUP compatibility to ON. */
+ m_input.m_line_index = m_cup_dir.length;
+ m_spec.m_cup_compatible = true;
+ // this is what %cup does: [CSA, 27-Jul-1999]
+ m_spec.m_implements_name =
+ "java_cup.runtime.Scanner".toCharArray();
+ m_spec.m_function_name =
+ "next_token".toCharArray();
+ m_spec.m_type_name =
+ "java_cup.runtime.Symbol".toCharArray();
+ break;
+ }
+
+ /* Bad directive. */
+ CError.parse_error(CError.E_DIRECT,
+ m_input.m_line_number);
+ break;
+
+ case 'e':
+ if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_eof_code_dir,
+ 0,
+ m_eof_code_dir.length - 1))
+ {
+ m_spec.m_eof_code = packCode(m_eof_code_dir,
+ m_eof_code_end_dir,
+ m_spec.m_eof_code,
+ m_spec.m_eof_read,
+ EOF_CODE);
+ break;
+ }
+ else if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_eof_value_code_dir,
+ 0,
+ m_eof_value_code_dir.length - 1))
+ {
+ m_spec.m_eof_value_code = packCode(m_eof_value_code_dir,
+ m_eof_value_code_end_dir,
+ m_spec.m_eof_value_code,
+ m_spec.m_eof_value_read,
+ EOF_VALUE_CODE);
+ break;
+ }
+ else if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_eof_throw_code_dir,
+ 0,
+ m_eof_throw_code_dir.length - 1))
+ {
+ m_spec.m_eof_throw_code = packCode(m_eof_throw_code_dir,
+ m_eof_throw_code_end_dir,
+ m_spec.m_eof_throw_code,
+ m_spec.m_eof_throw_read,
+ EOF_THROW_CODE);
+ break;
+ }
+
+ /* Bad directive. */
+ CError.parse_error(CError.E_DIRECT,
+ m_input.m_line_number);
+ break;
+
+ case 'f':
+ if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_function_dir,
+ 0,
+ m_function_dir.length - 1))
+ {
+ /* Set line counting to ON. */
+ m_input.m_line_index = m_function_dir.length;
+ m_spec.m_function_name = getName();
+ break;
+ }
+ else if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_full_dir,
+ 0,
+ m_full_dir.length - 1))
+ {
+ m_input.m_line_index = m_full_dir.length;
+ m_spec.m_dtrans_ncols = CUtility.MAX_EIGHT_BIT + 1;
+ break;
+ }
+
+ /* Bad directive. */
+ CError.parse_error(CError.E_DIRECT,
+ m_input.m_line_number);
+ break;
+
+ case 'i':
+ if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_integer_dir,
+ 0,
+ m_integer_dir.length - 1))
+ {
+ /* Set line counting to ON. */
+ m_input.m_line_index = m_integer_dir.length;
+ m_spec.m_integer_type = true;
+ break;
+ }
+ else if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_intwrap_dir,
+ 0,
+ m_intwrap_dir.length - 1))
+ {
+ /* Set line counting to ON. */
+ m_input.m_line_index = m_integer_dir.length;
+ m_spec.m_intwrap_type = true;
+ break;
+ }
+ else if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_init_code_dir,
+ 0,
+ m_init_code_dir.length - 1))
+ {
+ m_spec.m_init_code = packCode(m_init_code_dir,
+ m_init_code_end_dir,
+ m_spec.m_init_code,
+ m_spec.m_init_read,
+ INIT_CODE);
+ break;
+ }
+ else if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_init_throw_code_dir,
+ 0,
+ m_init_throw_code_dir.length - 1))
+ {
+ m_spec.m_init_throw_code = packCode(m_init_throw_code_dir,
+ m_init_throw_code_end_dir,
+ m_spec.m_init_throw_code,
+ m_spec.m_init_throw_read,
+ INIT_THROW_CODE);
+ break;
+ }
+ else if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_implements_dir,
+ 0,
+ m_implements_dir.length - 1))
+ {
+ m_input.m_line_index = m_implements_dir.length;
+ m_spec.m_implements_name = getName();
+ break;
+ }
+ else if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_ignorecase_dir,
+ 0,
+ m_ignorecase_dir.length-1))
+ {
+ /* Set m_ignorecase to ON. */
+ m_input.m_line_index = m_ignorecase_dir.length;
+ m_spec.m_ignorecase = true;
+ break;
+ }
+
+ /* Bad directive. */
+ CError.parse_error(CError.E_DIRECT,
+ m_input.m_line_number);
+ break;
+
+ case 'l':
+ if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_line_dir,
+ 0,
+ m_line_dir.length - 1))
+ {
+ /* Set line counting to ON. */
+ m_input.m_line_index = m_line_dir.length;
+ m_spec.m_count_lines = true;
+ break;
+ }
+
+ /* Bad directive. */
+ CError.parse_error(CError.E_DIRECT,
+ m_input.m_line_number);
+ break;
+
+ case 'n':
+ if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_notunix_dir,
+ 0,
+ m_notunix_dir.length - 1))
+ {
+ /* Set line counting to ON. */
+ m_input.m_line_index = m_notunix_dir.length;
+ m_spec.m_unix = false;
+ break;
+ }
+
+ /* Bad directive. */
+ CError.parse_error(CError.E_DIRECT,
+ m_input.m_line_number);
+ break;
+
+ case 'p':
+ if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_public_dir,
+ 0,
+ m_public_dir.length - 1))
+ {
+ /* Set public flag. */
+ m_input.m_line_index = m_public_dir.length;
+ m_spec.m_public = true;
+ break;
+ }
+
+ /* Bad directive. */
+ CError.parse_error(CError.E_DIRECT,
+ m_input.m_line_number);
+ break;
+
+ case 's':
+ if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_state_dir,
+ 0,
+ m_state_dir.length - 1))
+ {
+ /* Recognize state list. */
+ m_input.m_line_index = m_state_dir.length;
+ saveStates();
+ break;
+ }
+
+ /* Undefined directive. */
+ CError.parse_error(CError.E_DIRECT,
+ m_input.m_line_number);
+ break;
+
+ case 't':
+ if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_type_dir,
+ 0,
+ m_type_dir.length - 1))
+ {
+ /* Set Java CUP compatibility to ON. */
+ m_input.m_line_index = m_type_dir.length;
+ m_spec.m_type_name = getName();
+ break;
+ }
+
+ /* Undefined directive. */
+ CError.parse_error(CError.E_DIRECT,
+ m_input.m_line_number);
+ break;
+
+ case 'u':
+ if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_unicode_dir,
+ 0,
+ m_unicode_dir.length - 1))
+ {
+ m_input.m_line_index = m_unicode_dir.length;
+ m_spec.m_dtrans_ncols= CUtility.MAX_SIXTEEN_BIT + 1;
+ break;
+ }
+
+ /* Bad directive. */
+ CError.parse_error(CError.E_DIRECT,
+ m_input.m_line_number);
+ break;
+
+ case 'y':
+ if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_yyeof_dir,
+ 0,
+ m_yyeof_dir.length - 1))
+ {
+ m_input.m_line_index = m_yyeof_dir.length;
+ m_spec.m_yyeof = true;
+ break;
+ } else if (0 == CUtility.charncmp(m_input.m_line,
+ 0,
+ m_yylex_throw_code_dir,
+ 0,
+ m_yylex_throw_code_dir.length - 1))
+ {
+ m_spec.m_yylex_throw_code = packCode(m_yylex_throw_code_dir,
+ m_yylex_throw_code_end_dir,
+ m_spec.m_yylex_throw_code,
+ m_spec.m_yylex_throw_read,
+ YYLEX_THROW_CODE);
+ break;
+ }
+
+
+ /* Bad directive. */
+ CError.parse_error(CError.E_DIRECT,
+ m_input.m_line_number);
+ break;
+
+ default:
+ /* Undefined directive. */
+ CError.parse_error(CError.E_DIRECT,
+ m_input.m_line_number);
+ break;
+ }
+ }
+ else
+ {
+ /* Regular expression macro. */
+ m_input.m_line_index = 0;
+ saveMacro();
+ }
+
+ if (CUtility.OLD_DEBUG)
+ {
+ System.out.println("Line number "
+ + m_input.m_line_number + ":");
+ System.out.print(new String(m_input.m_line,
+ 0,m_input.m_line_read));
+ }
+ }
+ }
+
+ /***************************************************************
+ Function: userRules
+ Description: Processes third section of JLex
+ specification and creates minimized transition table.
+ **************************************************************/
+ private void userRules
+ (
+ )
+ throws java.io.IOException
+ {
+ int code;
+
+ if (false == m_init_flag)
+ {
+ CError.parse_error(CError.E_INIT,0);
+ }
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != this);
+ CUtility.ASSERT(null != m_outstream);
+ CUtility.ASSERT(null != m_input);
+ CUtility.ASSERT(null != m_tokens);
+ CUtility.ASSERT(null != m_spec);
+ }
+
+ /* UNDONE: Need to handle states preceding rules. */
+
+ if (m_spec.m_verbose)
+ {
+ System.out.println("Creating NFA machine representation.");
+ }
+ m_makeNfa.allocate_BOL_EOF(m_spec);
+ m_makeNfa.thompson(this,m_spec,m_input);
+
+ m_simplifyNfa.simplify(m_spec);
+
+ /*print_nfa();*/
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(END_OF_INPUT == m_spec.m_current_token);
+ }
+
+ if (m_spec.m_verbose)
+ {
+ System.out.println("Creating DFA transition table.");
+ }
+ m_nfa2dfa.make_dfa(this,m_spec);
+
+ if (CUtility.FOODEBUG) {
+ print_header();
+ }
+
+ if (m_spec.m_verbose)
+ {
+ System.out.println("Minimizing DFA transition table.");
+ }
+ m_minimize.min_dfa(m_spec);
+ }
+
+ /***************************************************************
+ Function: printccl
+ Description: Debugging routine that outputs readable form
+ of character class.
+ **************************************************************/
+ private void printccl
+ (
+ CSet set
+ )
+ {
+ int i;
+
+ System.out.print(" [");
+ for (i = 0; i < m_spec.m_dtrans_ncols; ++i)
+ {
+ if (set.contains(i))
+ {
+ System.out.print(interp_int(i));
+ }
+ }
+ System.out.print(']');
+ }
+
+ /***************************************************************
+ Function: plab
+ Description:
+ **************************************************************/
+ private String plab
+ (
+ CNfa state
+ )
+ {
+ int index;
+
+ if (null == state)
+ {
+ return (new String("--"));
+ }
+
+ index = m_spec.m_nfa_states.indexOf(state);
+
+ return ((new Integer(index)).toString());
+ }
+
+ /***************************************************************
+ Function: interp_int
+ Description:
+ **************************************************************/
+ private String interp_int
+ (
+ int i
+ )
+ {
+ switch (i)
+ {
+ case (int) '\b':
+ return (new String("\\b"));
+
+ case (int) '\t':
+ return (new String("\\t"));
+
+ case (int) '\n':
+ return (new String("\\n"));
+
+ case (int) '\f':
+ return (new String("\\f"));
+
+ case (int) '\r':
+ return (new String("\\r"));
+
+ case (int) ' ':
+ return (new String("\\ "));
+
+ default:
+ return ((new Character((char) i)).toString());
+ }
+ }
+
+ /***************************************************************
+ Function: print_nfa
+ Description:
+ **************************************************************/
+ void print_nfa
+ (
+ )
+ {
+ int elem;
+ CNfa nfa;
+ int size;
+ Enumeration states;
+ Integer index;
+ int i;
+ int j;
+ int vsize;
+ String state;
+
+ System.out.println("--------------------- NFA -----------------------");
+
+ size = m_spec.m_nfa_states.size();
+ for (elem = 0; elem < size; ++elem)
+ {
+ nfa = (CNfa) m_spec.m_nfa_states.elementAt(elem);
+
+ System.out.print("Nfa state " + plab(nfa) + ": ");
+
+ if (null == nfa.m_next)
+ {
+ System.out.print("(TERMINAL)");
+ }
+ else
+ {
+ System.out.print("--> " + plab(nfa.m_next));
+ System.out.print("--> " + plab(nfa.m_next2));
+
+ switch (nfa.m_edge)
+ {
+ case CNfa.CCL:
+ printccl(nfa.m_set);
+ break;
+
+ case CNfa.EPSILON:
+ System.out.print(" EPSILON ");
+ break;
+
+ default:
+ System.out.print(" " + interp_int(nfa.m_edge));
+ break;
+ }
+ }
+
+ if (0 == elem)
+ {
+ System.out.print(" (START STATE)");
+ }
+
+ if (null != nfa.m_accept)
+ {
+ System.out.print(" accepting "
+ + ((0 != (nfa.m_anchor & CSpec.START)) ? "^" : "")
+ + "<"
+ + (new String(nfa.m_accept.m_action,0,
+ nfa.m_accept.m_action_read))
+ + ">"
+ + ((0 != (nfa.m_anchor & CSpec.END)) ? "$" : ""));
+ }
+
+ System.out.println();
+ }
+
+ states = m_spec.m_states.keys();
+ while (states.hasMoreElements())
+ {
+ state = (String) states.nextElement();
+ index = (Integer) m_spec.m_states.get(state);
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != state);
+ CUtility.ASSERT(null != index);
+ }
+
+ System.out.println("State \"" + state
+ + "\" has identifying index "
+ + index.toString() + ".");
+ System.out.print("\tStart states of matching rules: ");
+
+ i = index.intValue();
+ vsize = m_spec.m_state_rules[i].size();
+
+ for (j = 0; j < vsize; ++j)
+ {
+ nfa = (CNfa) m_spec.m_state_rules[i].elementAt(j);
+
+ System.out.print(m_spec.m_nfa_states.indexOf(nfa) + " ");
+ }
+
+ System.out.println();
+ }
+
+ System.out.println("-------------------- NFA ----------------------");
+ }
+
+ /***************************************************************
+ Function: getStates
+ Description: Parses the state area of a rule,
+ from the beginning of a line.
+ < state1, state2 ... > regular_expression { action }
+ Returns null on only EOF. Returns all_states,
+ initialied properly to correspond to all states,
+ if no states are found.
+ Special Notes: This function treats commas as optional
+ and permits states to be spread over multiple lines.
+ **************************************************************/
+ private SparseBitSet all_states = null;
+ SparseBitSet getStates
+ (
+ )
+ throws java.io.IOException
+ {
+ int start_state;
+ int count_state;
+ SparseBitSet states;
+ String name;
+ Integer index;
+ int i;
+ int size;
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != this);
+ CUtility.ASSERT(null != m_outstream);
+ CUtility.ASSERT(null != m_input);
+ CUtility.ASSERT(null != m_tokens);
+ CUtility.ASSERT(null != m_spec);
+ }
+
+ states = null;
+
+ /* Skip white space. */
+ while (CUtility.isspace(m_input.m_line[m_input.m_line_index]))
+ {
+ ++m_input.m_line_index;
+
+ while (m_input.m_line_index >= m_input.m_line_read)
+ {
+ /* Must just be an empty line. */
+ if (m_input.getLine())
+ {
+ /* EOF found. */
+ return null;
+ }
+ }
+ }
+
+ /* Look for states. */
+ if ('<' == m_input.m_line[m_input.m_line_index])
+ {
+ ++m_input.m_line_index;
+
+ states = new SparseBitSet();
+
+ /* Parse states. */
+ while (true)
+ {
+ /* We may have reached the end of the line. */
+ while (m_input.m_line_index >= m_input.m_line_read)
+ {
+ if (m_input.getLine())
+ {
+ /* EOF found. */
+ CError.parse_error(CError.E_EOF,m_input.m_line_number);
+ return states;
+ }
+ }
+
+ while (true)
+ {
+ /* Skip white space. */
+ while (CUtility.isspace(m_input.m_line[m_input.m_line_index]))
+ {
+ ++m_input.m_line_index;
+
+ while (m_input.m_line_index >= m_input.m_line_read)
+ {
+ if (m_input.getLine())
+ {
+ /* EOF found. */
+ CError.parse_error(CError.E_EOF,m_input.m_line_number);
+ return states;
+ }
+ }
+ }
+
+ if (',' != m_input.m_line[m_input.m_line_index])
+ {
+ break;
+ }
+
+ ++m_input.m_line_index;
+ }
+
+ if ('>' == m_input.m_line[m_input.m_line_index])
+ {
+ ++m_input.m_line_index;
+ if (m_input.m_line_index < m_input.m_line_read)
+ {
+ m_advance_stop = true;
+ }
+ return states;
+ }
+
+ /* Read in state name. */
+ start_state = m_input.m_line_index;
+ while (false == CUtility.isspace(m_input.m_line[m_input.m_line_index])
+ && ',' != m_input.m_line[m_input.m_line_index]
+ && '>' != m_input.m_line[m_input.m_line_index])
+ {
+ ++m_input.m_line_index;
+
+ if (m_input.m_line_index >= m_input.m_line_read)
+ {
+ /* End of line means end of state name. */
+ break;
+ }
+ }
+ count_state = m_input.m_line_index - start_state;
+
+ /* Save name after checking definition. */
+ name = new String(m_input.m_line,
+ start_state,
+ count_state);
+ index = (Integer) m_spec.m_states.get(name);
+ if (null == index)
+ {
+ /* Uninitialized state. */
+ System.out.println("Uninitialized State Name: " + name);
+ CError.parse_error(CError.E_STATE,m_input.m_line_number);
+ }
+ states.set(index.intValue());
+ }
+ }
+
+ if (null == all_states)
+ {
+ all_states = new SparseBitSet();
+
+ size = m_spec.m_states.size();
+ for (i = 0; i < size; ++i)
+ {
+ all_states.set(i);
+ }
+ }
+
+ if (m_input.m_line_index < m_input.m_line_read)
+ {
+ m_advance_stop = true;
+ }
+ return all_states;
+ }
+
+ /********************************************************
+ Function: expandMacro
+ Description: Returns false on error, true otherwise.
+ *******************************************************/
+ private boolean expandMacro
+ (
+ )
+ {
+ int elem;
+ int start_macro;
+ int end_macro;
+ int start_name;
+ int count_name;
+ String def;
+ int def_elem;
+ String name;
+ char replace[];
+ int rep_elem;
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != this);
+ CUtility.ASSERT(null != m_outstream);
+ CUtility.ASSERT(null != m_input);
+ CUtility.ASSERT(null != m_tokens);
+ CUtility.ASSERT(null != m_spec);
+ }
+
+ /* Check for macro. */
+ if ('{' != m_input.m_line[m_input.m_line_index])
+ {
+ CError.parse_error(CError.E_INTERNAL,m_input.m_line_number);
+ return ERROR;
+ }
+
+ start_macro = m_input.m_line_index;
+ elem = m_input.m_line_index + 1;
+ if (elem >= m_input.m_line_read)
+ {
+ CError.impos("Unfinished macro name");
+ return ERROR;
+ }
+
+ /* Get macro name. */
+ start_name = elem;
+ while ('}' != m_input.m_line[elem])
+ {
+ ++elem;
+ if (elem >= m_input.m_line_read)
+ {
+ CError.impos("Unfinished macro name at line "
+ + m_input.m_line_number);
+ return ERROR;
+ }
+ }
+ count_name = elem - start_name;
+ end_macro = elem;
+
+ /* Check macro name. */
+ if (0 == count_name)
+ {
+ CError.impos("Nonexistent macro name");
+ return ERROR;
+ }
+
+ /* Debug checks. */
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(0 < count_name);
+ }
+
+ /* Retrieve macro definition. */
+ name = new String(m_input.m_line,start_name,count_name);
+ def = (String) m_spec.m_macros.get(name);
+ if (null == def)
+ {
+ /*CError.impos("Undefined macro \"" + name + "\".");*/
+ System.out.println("Error: Undefined macro \"" + name + "\".");
+ CError.parse_error(CError.E_NOMAC, m_input.m_line_number);
+ return ERROR;
+ }
+ if (CUtility.OLD_DUMP_DEBUG)
+ {
+ System.out.println("expanded escape: " + def);
+ }
+
+ /* Replace macro in new buffer,
+ beginning by copying first part of line buffer. */
+ replace = new char[m_input.m_line.length];
+ for (rep_elem = 0; rep_elem < start_macro; ++rep_elem)
+ {
+ replace[rep_elem] = m_input.m_line[rep_elem];
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(rep_elem < replace.length);
+ }
+ }
+
+ /* Copy macro definition. */
+ if (rep_elem >= replace.length)
+ {
+ replace = CUtility.doubleSize(replace);
+ }
+ for (def_elem = 0; def_elem < def.length(); ++def_elem)
+ {
+ replace[rep_elem] = def.charAt(def_elem);
+
+ ++rep_elem;
+ if (rep_elem >= replace.length)
+ {
+ replace = CUtility.doubleSize(replace);
+ }
+ }
+
+ /* Copy last part of line. */
+ if (rep_elem >= replace.length)
+ {
+ replace = CUtility.doubleSize(replace);
+ }
+ for (elem = end_macro + 1; elem < m_input.m_line_read; ++elem)
+ {
+ replace[rep_elem] = m_input.m_line[elem];
+
+ ++rep_elem;
+ if (rep_elem >= replace.length)
+ {
+ replace = CUtility.doubleSize(replace);
+ }
+ }
+
+ /* Replace buffer. */
+ m_input.m_line = replace;
+ m_input.m_line_read = rep_elem;
+
+ if (CUtility.OLD_DEBUG)
+ {
+ System.out.println(new String(m_input.m_line,0,m_input.m_line_read));
+ }
+ return NOT_ERROR;
+ }
+
+ /***************************************************************
+ Function: saveMacro
+ Description: Saves macro definition of form:
+ macro_name = macro_definition
+ **************************************************************/
+ private void saveMacro
+ (
+ )
+ {
+ int elem;
+ int start_name;
+ int count_name;
+ int start_def;
+ int count_def;
+ boolean saw_escape;
+ boolean in_quote;
+ boolean in_ccl;
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != this);
+ CUtility.ASSERT(null != m_outstream);
+ CUtility.ASSERT(null != m_input);
+ CUtility.ASSERT(null != m_tokens);
+ CUtility.ASSERT(null != m_spec);
+ }
+
+ /* Macro declarations are of the following form:
+ macro_name macro_definition */
+
+ elem = 0;
+
+ /* Skip white space preceding macro name. */
+ while (CUtility.isspace(m_input.m_line[elem]))
+ {
+ ++elem;
+ if (elem >= m_input.m_line_read)
+ {
+ /* End of line has been reached,
+ and line was found to be empty. */
+ return;
+ }
+ }
+
+ /* Read macro name. */
+ start_name = elem;
+ while (false == CUtility.isspace(m_input.m_line[elem])
+ && '=' != m_input.m_line[elem])
+ {
+ ++elem;
+ if (elem >= m_input.m_line_read)
+ {
+ /* Macro name but no associated definition. */
+ CError.parse_error(CError.E_MACDEF,m_input.m_line_number);
+ }
+ }
+ count_name = elem - start_name;
+
+ /* Check macro name. */
+ if (0 == count_name)
+ {
+ /* Nonexistent macro name. */
+ CError.parse_error(CError.E_MACDEF,m_input.m_line_number);
+ }
+
+ /* Skip white space between name and definition. */
+ while (CUtility.isspace(m_input.m_line[elem]))
+ {
+ ++elem;
+ if (elem >= m_input.m_line_read)
+ {
+ /* Macro name but no associated definition. */
+ CError.parse_error(CError.E_MACDEF,m_input.m_line_number);
+ }
+ }
+
+ if ('=' == m_input.m_line[elem])
+ {
+ ++elem;
+ if (elem >= m_input.m_line_read)
+ {
+ /* Macro name but no associated definition. */
+ CError.parse_error(CError.E_MACDEF,m_input.m_line_number);
+ }
+ }
+ else /* macro definition without = */
+ CError.parse_error(CError.E_MACDEF,m_input.m_line_number);
+
+ /* Skip white space between name and definition. */
+ while (CUtility.isspace(m_input.m_line[elem]))
+ {
+ ++elem;
+ if (elem >= m_input.m_line_read)
+ {
+ /* Macro name but no associated definition. */
+ CError.parse_error(CError.E_MACDEF,m_input.m_line_number);
+ }
+ }
+
+ /* Read macro definition. */
+ start_def = elem;
+ in_quote = false;
+ in_ccl = false;
+ saw_escape = false;
+ while (false == CUtility.isspace(m_input.m_line[elem])
+ || true == in_quote
+ || true == in_ccl
+ || true == saw_escape)
+ {
+ if ('\"' == m_input.m_line[elem] && false == saw_escape)
+ {
+ in_quote = !in_quote;
+ }
+
+ if ('\\' == m_input.m_line[elem] && false == saw_escape)
+ {
+ saw_escape = true;
+ }
+ else
+ {
+ saw_escape = false;
+ }
+ if (false == saw_escape && false == in_quote) { // CSA, 24-jul-99
+ if ('[' == m_input.m_line[elem] && false == in_ccl)
+ in_ccl = true;
+ if (']' == m_input.m_line[elem] && true == in_ccl)
+ in_ccl = false;
+ }
+
+ ++elem;
+ if (elem >= m_input.m_line_read)
+ {
+ /* End of line. */
+ break;
+ }
+ }
+ count_def = elem - start_def;
+
+ /* Check macro definition. */
+ if (0 == count_def)
+ {
+ /* Nonexistent macro name. */
+ CError.parse_error(CError.E_MACDEF,m_input.m_line_number);
+ }
+
+ /* Debug checks. */
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(0 < count_def);
+ CUtility.ASSERT(0 < count_name);
+ CUtility.ASSERT(null != m_spec.m_macros);
+ }
+
+ if (CUtility.OLD_DEBUG)
+ {
+ System.out.println("macro name \""
+ + new String(m_input.m_line,start_name,count_name)
+ + "\".");
+ System.out.println("macro definition \""
+ + new String(m_input.m_line,start_def,count_def)
+ + "\".");
+ }
+
+ /* Add macro name and definition to table. */
+ m_spec.m_macros.put(new String(m_input.m_line,start_name,count_name),
+ new String(m_input.m_line,start_def,count_def));
+ }
+
+ /***************************************************************
+ Function: saveStates
+ Description: Takes state declaration and makes entries
+ for them in state hashtable in CSpec structure.
+ State declaration should be of the form:
+ %state name0[, name1, name2 ...]
+ (But commas are actually optional as long as there is
+ white space in between them.)
+ **************************************************************/
+ private void saveStates
+ (
+ )
+ {
+ int start_state;
+ int count_state;
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != this);
+ CUtility.ASSERT(null != m_outstream);
+ CUtility.ASSERT(null != m_input);
+ CUtility.ASSERT(null != m_tokens);
+ CUtility.ASSERT(null != m_spec);
+ }
+
+ /* EOF found? */
+ if (m_input.m_eof_reached)
+ {
+ return;
+ }
+
+ /* Debug checks. */
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT('%' == m_input.m_line[0]);
+ CUtility.ASSERT('s' == m_input.m_line[1]);
+ CUtility.ASSERT(m_input.m_line_index <= m_input.m_line_read);
+ CUtility.ASSERT(0 <= m_input.m_line_index);
+ CUtility.ASSERT(0 <= m_input.m_line_read);
+ }
+
+ /* Blank line? No states? */
+ if (m_input.m_line_index >= m_input.m_line_read)
+ {
+ return;
+ }
+
+ while (m_input.m_line_index < m_input.m_line_read)
+ {
+ if (CUtility.OLD_DEBUG)
+ {
+ System.out.println("line read " + m_input.m_line_read
+ + "\tline index = " + m_input.m_line_index);
+ }
+
+ /* Skip white space. */
+ while (CUtility.isspace(m_input.m_line[m_input.m_line_index]))
+ {
+ ++m_input.m_line_index;
+ if (m_input.m_line_index >= m_input.m_line_read)
+ {
+ /* No more states to be found. */
+ return;
+ }
+ }
+
+ /* Look for state name. */
+ start_state = m_input.m_line_index;
+ while (false == CUtility.isspace(m_input.m_line[m_input.m_line_index])
+ && ',' != m_input.m_line[m_input.m_line_index])
+ {
+ ++m_input.m_line_index;
+ if (m_input.m_line_index >= m_input.m_line_read)
+ {
+ /* End of line and end of state name. */
+ break;
+ }
+ }
+ count_state = m_input.m_line_index - start_state;
+
+ if (CUtility.OLD_DEBUG)
+ {
+ System.out.println("State name \""
+ + new String(m_input.m_line,start_state,count_state)
+ + "\".");
+ System.out.println("Integer index \""
+ + m_spec.m_states.size()
+ + "\".");
+ }
+
+ /* Enter new state name, along with unique index. */
+ m_spec.m_states.put(new String(m_input.m_line,start_state,count_state),
+ new Integer(m_spec.m_states.size()));
+
+ /* Skip comma. */
+ if (',' == m_input.m_line[m_input.m_line_index])
+ {
+ ++m_input.m_line_index;
+ if (m_input.m_line_index >= m_input.m_line_read)
+ {
+ /* End of line. */
+ return;
+ }
+ }
+ }
+ }
+
+ /********************************************************
+ Function: expandEscape
+ Description: Takes escape sequence and returns
+ corresponding character code.
+ *******************************************************/
+ private char expandEscape
+ (
+ )
+ {
+ char r;
+
+ /* Debug checks. */
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(m_input.m_line_index < m_input.m_line_read);
+ CUtility.ASSERT(0 < m_input.m_line_read);
+ CUtility.ASSERT(0 <= m_input.m_line_index);
+ }
+
+ if ('\\' != m_input.m_line[m_input.m_line_index])
+ {
+ ++m_input.m_line_index;
+ return m_input.m_line[m_input.m_line_index - 1];
+ }
+ else
+ {
+ boolean unicode_escape = false;
+ ++m_input.m_line_index;
+ switch (m_input.m_line[m_input.m_line_index])
+ {
+ case 'b':
+ ++m_input.m_line_index;
+ return '\b';
+
+ case 't':
+ ++m_input.m_line_index;
+ return '\t';
+
+ case 'n':
+ ++m_input.m_line_index;
+ return '\n';
+
+ case 'f':
+ ++m_input.m_line_index;
+ return '\f';
+
+ case 'r':
+ ++m_input.m_line_index;
+ return '\r';
+
+ case '^':
+ ++m_input.m_line_index;
+ r=Character.toUpperCase(m_input.m_line[m_input.m_line_index]);
+ if (r<'@' || r>'Z') // non-fatal
+ CError.parse_error(CError.E_BADCTRL,m_input.m_line_number);
+ r = (char) (r - '@');
+ ++m_input.m_line_index;
+ return r;
+
+ case 'u':
+ unicode_escape = true;
+ case 'x':
+ ++m_input.m_line_index;
+ r = 0;
+ for (int i=0; i<(unicode_escape?4:2); i++)
+ if (CUtility.ishexdigit(m_input.m_line[m_input.m_line_index]))
+ {
+ r = (char) (r << 4);
+ r = (char) (r | CUtility.hex2bin(m_input.m_line[m_input.m_line_index]));
+ ++m_input.m_line_index;
+ }
+ else break;
+
+ return r;
+
+ default:
+ if (false == CUtility.isoctdigit(m_input.m_line[m_input.m_line_index]))
+ {
+ r = m_input.m_line[m_input.m_line_index];
+ ++m_input.m_line_index;
+ }
+ else
+ {
+ r = 0;
+ for (int i=0; i<3; i++)
+ if (CUtility.isoctdigit(m_input.m_line[m_input.m_line_index]))
+ {
+ r = (char) (r << 3);
+ r = (char) (r | CUtility.oct2bin(m_input.m_line[m_input.m_line_index]));
+ ++m_input.m_line_index;
+ }
+ else break;
+ }
+ return r;
+ }
+ }
+ }
+
+ /********************************************************
+ Function: packAccept
+ Description: Packages and returns CAccept
+ for action next in input stream.
+ *******************************************************/
+ CAccept packAccept
+ (
+ )
+ throws java.io.IOException
+ {
+ CAccept accept;
+ char action[];
+ int action_index;
+ int brackets;
+ boolean insinglequotes;
+ boolean indoublequotes;
+ boolean instarcomment;
+ boolean inslashcomment;
+ boolean escaped;
+ boolean slashed;
+
+ action = new char[BUFFER_SIZE];
+ action_index = 0;
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != this);
+ CUtility.ASSERT(null != m_outstream);
+ CUtility.ASSERT(null != m_input);
+ CUtility.ASSERT(null != m_tokens);
+ CUtility.ASSERT(null != m_spec);
+ }
+
+ /* Get a new line, if needed. */
+ while (m_input.m_line_index >= m_input.m_line_read)
+ {
+ if (m_input.getLine())
+ {
+ CError.parse_error(CError.E_EOF,m_input.m_line_number);
+ return null;
+ }
+ }
+
+ /* Look for beginning of action. */
+ while (CUtility.isspace(m_input.m_line[m_input.m_line_index]))
+ {
+ ++m_input.m_line_index;
+
+ /* Get a new line, if needed. */
+ while (m_input.m_line_index >= m_input.m_line_read)
+ {
+ if (m_input.getLine())
+ {
+ CError.parse_error(CError.E_EOF,m_input.m_line_number);
+ return null;
+ }
+ }
+ }
+
+ /* Look for brackets. */
+ if ('{' != m_input.m_line[m_input.m_line_index])
+ {
+ CError.parse_error(CError.E_BRACE,m_input.m_line_number);
+ }
+
+ /* Copy new line into action buffer. */
+ brackets = 0;
+ insinglequotes = indoublequotes = inslashcomment = instarcomment =
+ escaped = slashed = false;
+ while (true)
+ {
+ action[action_index] = m_input.m_line[m_input.m_line_index];
+
+ /* Look for quotes. */
+ if ((insinglequotes || indoublequotes) && escaped)
+ escaped=false; // only protects one char, but this is enough.
+ else if ((insinglequotes || indoublequotes) &&
+ '\\' == m_input.m_line[m_input.m_line_index])
+ escaped=true;
+ else if (!(insinglequotes || inslashcomment || instarcomment) &&
+ '\"' == m_input.m_line[m_input.m_line_index])
+ indoublequotes=!indoublequotes; // unescaped double quote.
+ else if (!(indoublequotes || inslashcomment || instarcomment) &&
+ '\'' == m_input.m_line[m_input.m_line_index])
+ insinglequotes=!insinglequotes; // unescaped single quote.
+ /* Look for comments. */
+ if (instarcomment) { // inside "/*" comment; look for "*/"
+ if (slashed && '/' == m_input.m_line[m_input.m_line_index])
+ instarcomment = slashed = false;
+ else // note that inside a star comment, slashed means starred
+ slashed = ('*' == m_input.m_line[m_input.m_line_index]);
+ } else if (!inslashcomment && !insinglequotes && !indoublequotes) {
+ // not in comment, look for /* or //
+ inslashcomment =
+ (slashed && '/' == m_input.m_line[m_input.m_line_index]);
+ instarcomment =
+ (slashed && '*' == m_input.m_line[m_input.m_line_index]);
+ slashed = ('/' == m_input.m_line[m_input.m_line_index]);
+ }
+
+ /* Look for brackets. */
+ if (!insinglequotes && !indoublequotes &&
+ !instarcomment && !inslashcomment) {
+ if ('{' == m_input.m_line[m_input.m_line_index])
+ {
+ ++brackets;
+ }
+ else if ('}' == m_input.m_line[m_input.m_line_index])
+ {
+ --brackets;
+
+ if (0 == brackets)
+ {
+ ++action_index;
+ ++m_input.m_line_index;
+
+ break;
+ }
+ }
+ }
+
+ ++action_index;
+ /* Double the buffer size, if needed. */
+ if (action_index >= action.length)
+ {
+ action = CUtility.doubleSize(action);
+ }
+
+ ++m_input.m_line_index;
+ /* Get a new line, if needed. */
+ while (m_input.m_line_index >= m_input.m_line_read)
+ {
+ inslashcomment = slashed = false;
+ if (insinglequotes || indoublequotes) { // non-fatal
+ CError.parse_error(CError.E_NEWLINE,m_input.m_line_number);
+ insinglequotes = indoublequotes = false;
+ }
+ if (m_input.getLine())
+ {
+ CError.parse_error(CError.E_SYNTAX,m_input.m_line_number);
+ return null;
+ }
+ }
+ }
+
+ accept = new CAccept(action,action_index,m_input.m_line_number);
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != accept);
+ }
+
+ if (CUtility.DESCENT_DEBUG)
+ {
+ System.out.print("Accepting action:");
+ System.out.println(new String(accept.m_action,0,accept.m_action_read));
+ }
+
+ return accept;
+ }
+
+ /********************************************************
+ Function: advance
+ Description: Returns code for next token.
+ *******************************************************/
+ private boolean m_advance_stop = false;
+ int advance
+ (
+ )
+ throws java.io.IOException
+ {
+ boolean saw_escape = false;
+ Integer code;
+
+ /*if (m_input.m_line_index > m_input.m_line_read) {
+ System.out.println("m_input.m_line_index = " + m_input.m_line_index);
+ System.out.println("m_input.m_line_read = " + m_input.m_line_read);
+ CUtility.ASSERT(m_input.m_line_index <= m_input.m_line_read);
+ }*/
+
+ if (m_input.m_eof_reached)
+ {
+ /* EOF has already been reached,
+ so return appropriate code. */
+
+ m_spec.m_current_token = END_OF_INPUT;
+ m_spec.m_lexeme = '\0';
+ return m_spec.m_current_token;
+ }
+
+ /* End of previous regular expression?
+ Refill line buffer? */
+ if (EOS == m_spec.m_current_token
+ /* ADDED */
+ || m_input.m_line_index >= m_input.m_line_read)
+ /* ADDED */
+ {
+ if (m_spec.m_in_quote)
+ {
+ CError.parse_error(CError.E_SYNTAX,m_input.m_line_number);
+ }
+
+ while (true)
+ {
+ if (false == m_advance_stop
+ || m_input.m_line_index >= m_input.m_line_read)
+ {
+ if (m_input.getLine())
+ {
+ /* EOF has already been reached,
+ so return appropriate code. */
+
+ m_spec.m_current_token = END_OF_INPUT;
+ m_spec.m_lexeme = '\0';
+ return m_spec.m_current_token;
+ }
+ m_input.m_line_index = 0;
+ }
+ else
+ {
+ m_advance_stop = false;
+ }
+
+ while (m_input.m_line_index < m_input.m_line_read
+ && true == CUtility.isspace(m_input.m_line[m_input.m_line_index]))
+ {
+ ++m_input.m_line_index;
+ }
+
+ if (m_input.m_line_index < m_input.m_line_read)
+ {
+ break;
+ }
+ }
+ }
+
+ if (CUtility.DEBUG) {
+ CUtility.ASSERT(m_input.m_line_index <= m_input.m_line_read);
+ }
+
+ while (true)
+ {
+ if (false == m_spec.m_in_quote
+ && '{' == m_input.m_line[m_input.m_line_index])
+ {
+ if (false == expandMacro())
+ {
+ break;
+ }
+
+ if (m_input.m_line_index >= m_input.m_line_read)
+ {
+ m_spec.m_current_token = EOS;
+ m_spec.m_lexeme = '\0';
+ return m_spec.m_current_token;
+ }
+ }
+ else if ('\"' == m_input.m_line[m_input.m_line_index])
+ {
+ m_spec.m_in_quote = !m_spec.m_in_quote;
+ ++m_input.m_line_index;
+
+ if (m_input.m_line_index >= m_input.m_line_read)
+ {
+ m_spec.m_current_token = EOS;
+ m_spec.m_lexeme = '\0';
+ return m_spec.m_current_token;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (m_input.m_line_index > m_input.m_line_read) {
+ System.out.println("m_input.m_line_index = " + m_input.m_line_index);
+ System.out.println("m_input.m_line_read = " + m_input.m_line_read);
+ CUtility.ASSERT(m_input.m_line_index <= m_input.m_line_read);
+ }
+
+ /* Look for backslash, and corresponding
+ escape sequence. */
+ if ('\\' == m_input.m_line[m_input.m_line_index])
+ {
+ saw_escape = true;
+ }
+ else
+ {
+ saw_escape = false;
+ }
+
+ if (false == m_spec.m_in_quote)
+ {
+ if (false == m_spec.m_in_ccl &&
+ CUtility.isspace(m_input.m_line[m_input.m_line_index]))
+ {
+ /* White space means the end of
+ the current regular expression. */
+
+ m_spec.m_current_token = EOS;
+ m_spec.m_lexeme = '\0';
+ return m_spec.m_current_token;
+ }
+
+ /* Process escape sequence, if needed. */
+ if (saw_escape)
+ {
+ m_spec.m_lexeme = expandEscape();
+ }
+ else
+ {
+ m_spec.m_lexeme = m_input.m_line[m_input.m_line_index];
+ ++m_input.m_line_index;
+ }
+ }
+ else
+ {
+ if (saw_escape
+ && (m_input.m_line_index + 1) < m_input.m_line_read
+ && '\"' == m_input.m_line[m_input.m_line_index + 1])
+ {
+ m_spec.m_lexeme = '\"';
+ m_input.m_line_index = m_input.m_line_index + 2;
+ }
+ else
+ {
+ m_spec.m_lexeme = m_input.m_line[m_input.m_line_index];
+ ++m_input.m_line_index;
+ }
+ }
+
+ code = (Integer) m_tokens.get(new Character(m_spec.m_lexeme));
+ if (m_spec.m_in_quote || true == saw_escape)
+ {
+ m_spec.m_current_token = L;
+ }
+ else
+ {
+ if (null == code)
+ {
+ m_spec.m_current_token = L;
+ }
+ else
+ {
+ m_spec.m_current_token = code.intValue();
+ }
+ }
+
+ if (CCL_START == m_spec.m_current_token) m_spec.m_in_ccl = true;
+ if (CCL_END == m_spec.m_current_token) m_spec.m_in_ccl = false;
+
+ if (CUtility.FOODEBUG)
+ {
+ System.out.println("Lexeme: " + m_spec.m_lexeme
+ + "\tToken: " + m_spec.m_current_token
+ + "\tIndex: " + m_input.m_line_index);
+ }
+
+ return m_spec.m_current_token;
+ }
+
+ /***************************************************************
+ Function: details
+ Description: High level debugging routine.
+ **************************************************************/
+ private void details
+ (
+ )
+ {
+ Enumeration names;
+ String name;
+ String def;
+ Enumeration states;
+ String state;
+ Integer index;
+ int elem;
+ int size;
+
+ System.out.println();
+ System.out.println("\t** Macros **");
+ names = m_spec.m_macros.keys();
+ while (names.hasMoreElements())
+ {
+ name = (String) names.nextElement();
+ def = (String) m_spec.m_macros.get(name);
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != name);
+ CUtility.ASSERT(null != def);
+ }
+
+ System.out.println("Macro name \"" + name
+ + "\" has definition \""
+ + def + "\".");
+ }
+
+ System.out.println();
+ System.out.println("\t** States **");
+ states = m_spec.m_states.keys();
+ while (states.hasMoreElements())
+ {
+ state = (String) states.nextElement();
+ index = (Integer) m_spec.m_states.get(state);
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != state);
+ CUtility.ASSERT(null != index);
+ }
+
+ System.out.println("State \"" + state
+ + "\" has identifying index "
+ + index.toString() + ".");
+ }
+
+ System.out.println();
+ System.out.println("\t** Character Counting **");
+ if (false == m_spec.m_count_chars)
+ {
+ System.out.println("Character counting is off.");
+ }
+ else
+ {
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(m_spec.m_count_lines);
+ }
+
+ System.out.println("Character counting is on.");
+ }
+
+ System.out.println();
+ System.out.println("\t** Line Counting **");
+ if (false == m_spec.m_count_lines)
+ {
+ System.out.println("Line counting is off.");
+ }
+ else
+ {
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(m_spec.m_count_lines);
+ }
+
+ System.out.println("Line counting is on.");
+ }
+
+ System.out.println();
+ System.out.println("\t** Operating System Specificity **");
+ if (false == m_spec.m_unix)
+ {
+ System.out.println("Not generating UNIX-specific code.");
+ System.out.println("(This means that \"\\r\\n\" is a "
+ + "newline, rather than \"\\n\".)");
+ }
+ else
+ {
+ System.out.println("Generating UNIX-specific code.");
+ System.out.println("(This means that \"\\n\" is a "
+ + "newline, rather than \"\\r\\n\".)");
+ }
+
+ System.out.println();
+ System.out.println("\t** Java CUP Compatibility **");
+ if (false == m_spec.m_cup_compatible)
+ {
+ System.out.println("Generating CUP compatible code.");
+ System.out.println("(Scanner implements "
+ + "java_cup.runtime.Scanner.)");
+ }
+ else
+ {
+ System.out.println("Not generating CUP compatible code.");
+ }
+
+ if (CUtility.FOODEBUG) {
+ if (null != m_spec.m_nfa_states && null != m_spec.m_nfa_start)
+ {
+ System.out.println();
+ System.out.println("\t** NFA machine **");
+ print_nfa();
+ }
+ }
+
+ if (null != m_spec.m_dtrans_vector)
+ {
+ System.out.println();
+ System.out.println("\t** DFA transition table **");
+ /*print_header();*/
+ }
+
+ /*if (null != m_spec.m_accept_vector && null != m_spec.m_anchor_array)
+ {
+ System.out.println();
+ System.out.println("\t** Accept States and Anchor Vector **");
+ print_accept();
+ }*/
+ }
+
+ /***************************************************************
+ function: print_set
+ **************************************************************/
+ void print_set
+ (
+ Vector nfa_set
+ )
+ {
+ int size;
+ int elem;
+ CNfa nfa;
+
+ size = nfa_set.size();
+
+ if (0 == size)
+ {
+ System.out.print("empty ");
+ }
+
+ for (elem = 0; elem < size; ++elem)
+ {
+ nfa = (CNfa) nfa_set.elementAt(elem);
+ /*System.out.print(m_spec.m_nfa_states.indexOf(nfa) + " ");*/
+ System.out.print(nfa.m_label + " ");
+ }
+ }
+
+ /***************************************************************
+ Function: print_header
+ **************************************************************/
+ private void print_header
+ (
+ )
+ {
+ Enumeration states;
+ int i;
+ int j;
+ int chars_printed=0;
+ CDTrans dtrans;
+ int last_transition;
+ String str;
+ CAccept accept;
+ String state;
+ Integer index;
+
+ System.out.println("/*---------------------- DFA -----------------------");
+
+ states = m_spec.m_states.keys();
+ while (states.hasMoreElements())
+ {
+ state = (String) states.nextElement();
+ index = (Integer) m_spec.m_states.get(state);
+
+ if (CUtility.DEBUG)
+ {
+ CUtility.ASSERT(null != state);
+ CUtility.ASSERT(null != index);
+ }
+
+ System.out.println("State \"" + state
+ + "\" has identifying index "
+ + index.toString() + ".");
+
+ i = index.intValue();
+ if (CDTrans.F != m_spec.m_state_dtrans[i])
+ {
+ System.out.println("\tStart index in transition table: "
+ + m_spec.m_state_dtrans[i]);
+ }
+ else
+ {
+ System.out.println("\tNo associated transition states.");
+ }
+ }
+
+ for (i = 0; i < m_spec.m_dtrans_vector.size(); ++i)
+ {
+ dtrans = (CDTrans) m_spec.m_dtrans_vector.elementAt(i);
+
+ if (null == m_spec.m_accept_vector && null == m_spec.m_anchor_array)
+ {
+ if (null == dtrans.m_accept)
+ {
+ System.out.print(" * State " + i + " [nonaccepting]");
+ }
+ else
+ {
+ System.out.print(" * State " + i
+ + " [accepting, line "
+ + dtrans.m_accept.m_line_number
+ + " <"
+ + (new String(dtrans.m_accept.m_action,0,
+ dtrans.m_accept.m_action_read))
+ + ">]");
+ if (CSpec.NONE != dtrans.m_anchor)
+ {
+ System.out.print(" Anchor: "
+ + ((0 != (dtrans.m_anchor & CSpec.START))
+ ? "start " : "")
+ + ((0 != (dtrans.m_anchor & CSpec.END))
+ ? "end " : ""));
+ }
+ }
+ }
+ else
+ {
+ accept = (CAccept) m_spec.m_accept_vector.elementAt(i);
+
+ if (null == accept)
+ {
+ System.out.print(" * State " + i + " [nonaccepting]");
+ }
+ else
+ {
+ System.out.print(" * State " + i
+ + " [accepting, line "
+ + accept.m_line_number
+ + " <"
+ + (new String(accept.m_action,0,
+ accept.m_action_read))
+ + ">]");
+ if (CSpec.NONE != m_spec.m_anchor_array[i])
+ {
+ System.out.print(" Anchor: "
+ + ((0 != (m_spec.m_anchor_array[i] & CSpec.START))
+ ? "start " : "")
+ + ((0 != (m_spec.m_anchor_array[i] & CSpec.END))
+ ? "end " : ""));
+ }
+ }
+ }
+
+ last_transition = -1;
+ for (j = 0; j < m_spec.m_dtrans_ncols; ++j)
+ {
+ if (CDTrans.F != dtrans.m_dtrans[j])
+ {
+ if (last_transition != dtrans.m_dtrans[j])
+ {
+ System.out.println();
+ System.out.print(" * goto " + dtrans.m_dtrans[j]
+ + " on ");
+ chars_printed = 0;
+ }
+
+ str = interp_int((int) j);
+ System.out.print(str);
+
+ chars_printed = chars_printed + str.length();
+ if (56 < chars_printed)
+ {
+ System.out.println();
+ System.out.print(" * ");
+ chars_printed = 0;
+ }
+
+ last_transition = dtrans.m_dtrans[j];
+ }
+ }
+ System.out.println();
+ }
+ System.out.println(" */");
+ System.out.println();
+ }
+}
+
+/*
+ * SparseBitSet 25-Jul-1999.
+ * C. Scott Ananian <cananian@alumni.princeton.edu>
+ *
+ * Re-implementation of the standard java.util.BitSet to support sparse
+ * sets, which we need to efficiently support unicode character classes.
+ */
+
+/**
+ * A set of bits. The set automatically grows as more bits are
+ * needed.
+ *
+ * @version 1.00, 25 Jul 1999
+ * @author C. Scott Ananian
+ */
+final class SparseBitSet implements Cloneable {
+ /** Sorted array of bit-block offsets. */
+ int offs[];
+ /** Array of bit-blocks; each holding BITS bits. */
+ long bits[];
+ /** Number of blocks currently in use. */
+ int size;
+ /** log base 2 of BITS, for the identity: x/BITS == x >> LG_BITS */
+ static final private int LG_BITS = 6;
+ /** Number of bits in a block. */
+ static final private int BITS = 1<<LG_BITS;
+ /** BITS-1, using the identity: x % BITS == x & (BITS-1) */
+ static final private int BITS_M1 = BITS-1;
+
+ /**
+ * Creates an empty set.
+ */
+ public SparseBitSet() {
+ bits = new long[4];
+ offs = new int [4];
+ size = 0;
+ }
+
+ /**
+ * Creates an empty set with the specified size.
+ * @param nbits the size of the set
+ */
+ public SparseBitSet(int nbits) {
+ this();
+ }
+
+ /**
+ * Creates an empty set with the same size as the given set.
+ */
+ public SparseBitSet(SparseBitSet set) {
+ bits = new long[set.size];
+ offs = new int [set.size];
+ size = 0;
+ }
+
+ private void new_block(int bnum) {
+ new_block(bsearch(bnum), bnum);
+ }
+ private void new_block(int idx, int bnum) {
+ if (size==bits.length) { // resize
+ long[] nbits = new long[size*3];
+ int [] noffs = new int [size*3];
+ System.arraycopy(bits, 0, nbits, 0, size);
+ System.arraycopy(offs, 0, noffs, 0, size);
+ bits = nbits;
+ offs = noffs;
+ }
+ CUtility.ASSERT(size<bits.length);
+ insert_block(idx, bnum);
+ }
+ private void insert_block(int idx, int bnum) {
+ CUtility.ASSERT(idx<=size);
+ CUtility.ASSERT(idx==size || offs[idx]!=bnum);
+ System.arraycopy(bits, idx, bits, idx+1, size-idx);
+ System.arraycopy(offs, idx, offs, idx+1, size-idx);
+ offs[idx]=bnum;
+ bits[idx]=0; //clear them bits.
+ size++;
+ }
+ private int bsearch(int bnum) {
+ int l=0, r=size; // search interval is [l, r)
+ while (l<r) {
+ int p = (l+r)/2;
+ if (bnum<offs[p]) r=p;
+ else if (bnum>offs[p]) l=p+1;
+ else return p;
+ }
+ CUtility.ASSERT(l==r);
+ return l; // index at which the bnum *should* be, if it's not.
+ }
+
+ /**
+ * Sets a bit.
+ * @param bit the bit to be set
+ */
+ public void set(int bit) {
+ int bnum = bit >> LG_BITS;
+ int idx = bsearch(bnum);
+ if (idx >= size || offs[idx]!=bnum)
+ new_block(idx, bnum);
+ bits[idx] |= (1L << (bit & BITS_M1) );
+ }
+
+ /**
+ * Clears a bit.
+ * @param bit the bit to be cleared
+ */
+ public void clear(int bit) {
+ int bnum = bit >> LG_BITS;
+ int idx = bsearch(bnum);
+ if (idx >= size || offs[idx]!=bnum)
+ new_block(idx, bnum);
+ bits[idx] &= ~(1L << (bit & BITS_M1) );
+ }
+
+ /**
+ * Clears all bits.
+ */
+ public void clearAll() {
+ size = 0;
+ }
+
+ /**
+ * Gets a bit.
+ * @param bit the bit to be gotten
+ */
+ public boolean get(int bit) {
+ int bnum = bit >> LG_BITS;
+ int idx = bsearch(bnum);
+ if (idx >= size || offs[idx]!=bnum)
+ return false;
+ return 0 != ( bits[idx] & (1L << (bit & BITS_M1) ) );
+ }
+
+ /**
+ * Logically ANDs this bit set with the specified set of bits.
+ * @param set the bit set to be ANDed with
+ */
+ public void and(SparseBitSet set) {
+ binop(this, set, AND);
+ }
+
+ /**
+ * Logically ORs this bit set with the specified set of bits.
+ * @param set the bit set to be ORed with
+ */
+ public void or(SparseBitSet set) {
+ binop(this, set, OR);
+ }
+
+ /**
+ * Logically XORs this bit set with the specified set of bits.
+ * @param set the bit set to be XORed with
+ */
+ public void xor(SparseBitSet set) {
+ binop(this, set, XOR);
+ }
+
+ // BINARY OPERATION MACHINERY
+ private static interface BinOp {
+ public long op(long a, long b);
+ }
+ private static final BinOp AND = new BinOp() {
+ public final long op(long a, long b) { return a & b; }
+ };
+ private static final BinOp OR = new BinOp() {
+ public final long op(long a, long b) { return a | b; }
+ };
+ private static final BinOp XOR = new BinOp() {
+ public final long op(long a, long b) { return a ^ b; }
+ };
+ private static final void binop(SparseBitSet a, SparseBitSet b, BinOp op) {
+ int nsize = a.size + b.size;
+ long[] nbits;
+ int [] noffs;
+ int a_zero, a_size;
+ // be very clever and avoid allocating more memory if we can.
+ if (a.bits.length < nsize) { // oh well, have to make working space.
+ nbits = new long[nsize];
+ noffs = new int [nsize];
+ a_zero = 0; a_size = a.size;
+ } else { // reduce, reuse, recycle!
+ nbits = a.bits;
+ noffs = a.offs;
+ a_zero = a.bits.length - a.size; a_size = a.bits.length;
+ System.arraycopy(a.bits, 0, a.bits, a_zero, a.size);
+ System.arraycopy(a.offs, 0, a.offs, a_zero, a.size);
+ }
+ // ok, crunch through and binop those sets!
+ nsize = 0;
+ for (int i=a_zero, j=0; i<a_size || j<b.size; ) {
+ long nb; int no;
+ if (i<a_size && (j>=b.size || a.offs[i] < b.offs[j])) {
+ nb = op.op(a.bits[i], 0);
+ no = a.offs[i];
+ i++;
+ } else if (j<b.size && (i>=a_size || a.offs[i] > b.offs[j])) {
+ nb = op.op(0, b.bits[j]);
+ no = b.offs[j];
+ j++;
+ } else { // equal keys; merge.
+ nb = op.op(a.bits[i], b.bits[j]);
+ no = a.offs[i];
+ i++; j++;
+ }
+ if (nb!=0) {
+ nbits[nsize] = nb;
+ noffs[nsize] = no;
+ nsize++;
+ }
+ }
+ a.bits = nbits;
+ a.offs = noffs;
+ a.size = nsize;
+ }
+
+ /**
+ * Gets the hashcode.
+ */
+ public int hashCode() {
+ long h = 1234;
+ for (int i=0; i<size; i++)
+ h ^= bits[i] * offs[i];
+ return (int)((h >> 32) ^ h);
+ }
+
+ /**
+ * Calculates and returns the set's size
+ */
+ public int size() {
+ return (size==0)?0:((1+offs[size-1]) << LG_BITS);
+ }
+
+ /**
+ * Compares this object against the specified object.
+ * @param obj the object to commpare with
+ * @return true if the objects are the same; false otherwise.
+ */
+ public boolean equals(Object obj) {
+ if ((obj != null) && (obj instanceof SparseBitSet))
+ return equals(this, (SparseBitSet)obj);
+ return false;
+ }
+ /**
+ * Compares two SparseBitSets for equality.
+ * @return true if the objects are the same; false otherwise.
+ */
+ public static boolean equals(SparseBitSet a, SparseBitSet b) {
+ for (int i=0, j=0; i<a.size || j<b.size; ) {
+ if (i<a.size && (j>=b.size || a.offs[i] < b.offs[j])) {
+ if (a.bits[i++]!=0) return false;
+ } else if (j<b.size && (i>=a.size || a.offs[i] > b.offs[j])) {
+ if (b.bits[j++]!=0) return false;
+ } else { // equal keys
+ if (a.bits[i++]!=b.bits[j++]) return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Clones the SparseBitSet.
+ */
+ public Object clone() {
+ try {
+ SparseBitSet set = (SparseBitSet)super.clone();
+ set.bits = (long[]) bits.clone();
+ set.offs = (int []) offs.clone();
+ return set;
+ } catch (CloneNotSupportedException e) {
+ // this shouldn't happen, since we are Cloneable
+ throw new InternalError();
+ }
+ }
+
+ /**
+ * Return an <code>Enumeration</code> of <code>Integer</code>s
+ * which represent set bit indices in this SparseBitSet.
+ */
+ public Enumeration elements() {
+ return new Enumeration() {
+ int idx=-1, bit=BITS;
+ { advance(); }
+ public boolean hasMoreElements() {
+ return (idx<size);
+ }
+ public Object nextElement() {
+ int r = bit + (offs[idx] << LG_BITS);
+ advance();
+ return new Integer(r);
+ }
+ private void advance() {
+ while (idx<size) {
+ while (++bit<BITS)
+ if (0!=(bits[idx] & (1L<<bit)))
+ return;
+ idx++; bit=-1;
+ }
+ }
+ };
+ }
+ /**
+ * Converts the SparseBitSet to a String.
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append('{');
+ for (Enumeration e=elements(); e.hasMoreElements(); ) {
+ if (sb.length() > 1) sb.append(", ");
+ sb.append(e.nextElement());
+ }
+ sb.append('}');
+ return sb.toString();
+ }
+
+ /** Check validity. */
+ private boolean isValid() {
+ if (bits.length!=offs.length) return false;
+ if (size>bits.length) return false;
+ if (size!=0 && 0<=offs[0]) return false;
+ for (int i=1; i<size; i++)
+ if (offs[i] < offs[i-1])
+ return false;
+ return true;
+ }
+ /** Self-test. */
+ public static void main(String[] args) {
+ final int ITER = 500;
+ final int RANGE= 65536;
+ SparseBitSet a = new SparseBitSet();
+ CUtility.ASSERT(!a.get(0) && !a.get(1));
+ CUtility.ASSERT(!a.get(123329));
+ a.set(0); CUtility.ASSERT(a.get(0) && !a.get(1));
+ a.set(1); CUtility.ASSERT(a.get(0) && a.get(1));
+ a.clearAll();
+ CUtility.ASSERT(!a.get(0) && !a.get(1));
+ java.util.Random r = new java.util.Random();
+ java.util.Vector v = new java.util.Vector();
+ for (int n=0; n<ITER; n++) {
+ int rr = ((r.nextInt()>>>1) % RANGE) << 1;
+ a.set(rr); v.addElement(new Integer(rr));
+ // check that all the numbers are there.
+ CUtility.ASSERT(a.get(rr) && !a.get(rr+1) && !a.get(rr-1));
+ for (int i=0; i<v.size(); i++)
+ CUtility.ASSERT(a.get(((Integer)v.elementAt(i)).intValue()));
+ }
+ SparseBitSet b = (SparseBitSet) a.clone();
+ CUtility.ASSERT(a.equals(b) && b.equals(a));
+ for (int n=0; n<ITER/2; n++) {
+ int rr = (r.nextInt()>>>1) % v.size();
+ int m = ((Integer)v.elementAt(rr)).intValue();
+ b.clear(m); v.removeElementAt(rr);
+ // check that numbers are removed properly.
+ CUtility.ASSERT(!b.get(m));
+ }
+ CUtility.ASSERT(!a.equals(b));
+ SparseBitSet c = (SparseBitSet) a.clone();
+ SparseBitSet d = (SparseBitSet) a.clone();
+ c.and(a);
+ CUtility.ASSERT(c.equals(a) && a.equals(c));
+ c.xor(a);
+ CUtility.ASSERT(!c.equals(a) && c.size()==0);
+ d.or(b);
+ CUtility.ASSERT(d.equals(a) && !b.equals(d));
+ d.and(b);
+ CUtility.ASSERT(!d.equals(a) && b.equals(d));
+ d.xor(a);
+ CUtility.ASSERT(!d.equals(a) && !b.equals(d));
+ c.or(d); c.or(b);
+ CUtility.ASSERT(c.equals(a) && a.equals(c));
+ c = (SparseBitSet) d.clone();
+ c.and(b);
+ CUtility.ASSERT(c.size()==0);
+ System.out.println("Success.");
+ }
+}
+
+/************************************************************************
+ JLEX COPYRIGHT NOTICE, LICENSE AND DISCLAIMER.
+
+ Copyright 1996 by Elliot Joel Berk
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose and without fee is hereby granted,
+ provided that the above copyright notice appear in all copies and that
+ both the copyright notice and this permission notice and warranty
+ disclaimer appear in supporting documentation, and that the name of
+ Elliot Joel Berk not be used in advertising or publicity pertaining
+ to distribution of the software without specific, written prior permission.
+
+ Elliot Joel Berk disclaims all warranties with regard to this software,
+ including all implied warranties of merchantability and fitness. In no event
+ shall Elliot Joel Berk be liable for any special, indirect or consequential
+ damages or any damages whatsoever resulting from loss of use, data or
+ profits, whether in an action of contract, negligence or other
+ tortious action, arising out of or in connection with the use or
+ performance of this software.
+ ***********************************************************************/
+// set emacs indentation
+// Local Variables:
+// c-basic-offset:2
+// End:
diff --git a/src/syntaxParser/JLex/SparseBitSet$1.class b/src/syntaxParser/JLex/SparseBitSet$1.class
new file mode 100644
index 0000000..57af847
--- /dev/null
+++ b/src/syntaxParser/JLex/SparseBitSet$1.class
Binary files differ
diff --git a/src/syntaxParser/JLex/SparseBitSet$2.class b/src/syntaxParser/JLex/SparseBitSet$2.class
new file mode 100644
index 0000000..6a97a1a
--- /dev/null
+++ b/src/syntaxParser/JLex/SparseBitSet$2.class
Binary files differ
diff --git a/src/syntaxParser/JLex/SparseBitSet$3.class b/src/syntaxParser/JLex/SparseBitSet$3.class
new file mode 100644
index 0000000..ed0d5a0
--- /dev/null
+++ b/src/syntaxParser/JLex/SparseBitSet$3.class
Binary files differ
diff --git a/src/syntaxParser/JLex/SparseBitSet$4.class b/src/syntaxParser/JLex/SparseBitSet$4.class
new file mode 100644
index 0000000..3fe8e9b
--- /dev/null
+++ b/src/syntaxParser/JLex/SparseBitSet$4.class
Binary files differ
diff --git a/src/syntaxParser/JLex/SparseBitSet$BinOp.class b/src/syntaxParser/JLex/SparseBitSet$BinOp.class
new file mode 100644
index 0000000..279caed
--- /dev/null
+++ b/src/syntaxParser/JLex/SparseBitSet$BinOp.class
Binary files differ
diff --git a/src/syntaxParser/JLex/SparseBitSet.class b/src/syntaxParser/JLex/SparseBitSet.class
new file mode 100644
index 0000000..fb750ec
--- /dev/null
+++ b/src/syntaxParser/JLex/SparseBitSet.class
Binary files differ
diff --git a/src/syntaxParser/List.java b/src/syntaxParser/List.java
new file mode 100644
index 0000000..685c504
--- /dev/null
+++ b/src/syntaxParser/List.java
@@ -0,0 +1,42 @@
+package syntaxParser;
+/* Author: Sorin stancu-Mara
+ * date: 8 feb 2008
+ * All the lists have the same caracteristics, therfore all of them derive from this class
+ * No need to verify that the list contain same type of elements since they are created using the grammar.
+ */
+
+class List implements IParseTreeNode {
+ IParseTreeNode element;
+ List next;
+ String tag;
+
+ public List(IParseTreeNode elem) {
+ element = elem;
+ next = null;
+ }
+
+ public List(IParseTreeNode elem, List next) {
+ element = elem;
+ this.next = next;
+ }
+
+ public void setTag(String tagName) {
+ tag = tagName;
+ if (next != null) {
+ next.setTag(tag);
+ }
+ }
+
+ public String toXML() {
+ String result = "";
+ if (tag != null) {
+ result += "<" + tag + ">";
+ result += element.toXML();
+ result += "</" + tag + ">";
+ } else
+ result += element.toXML();
+ if (next != null)
+ result += next.toXML();
+ return result;
+ }
+}
diff --git a/src/syntaxParser/Makefile b/src/syntaxParser/Makefile
new file mode 100644
index 0000000..0869ac7
--- /dev/null
+++ b/src/syntaxParser/Makefile
@@ -0,0 +1,34 @@
+# Author: Sorin Stancu-Mara
+# Date: 5 Feb 2007
+# Based on readme.txt provided by Mattia Parigiani
+
+JAR=jar
+JAVA=java
+JAVAC=javac
+
+all: SyntaxErrorException.class List.class WCPSParser.class WCPSSymbol.class WCPSScanner.class \
+ WCPSRequestProcessor.class
+
+%.class: %.java
+ cd .. ; $(JAVAC) syntaxParser/$<
+
+WCPSScanner.java: wcps.lex
+ $(JAVA) JLex.Main wcps.lex
+ mv wcps.lex.java WCPSScanner.java
+
+.PHONY:
+parser: wcps.cup
+ $(JAVA) java_cup.Main -parser WCPSParser -symbols WCPSSymbol -package syntaxParser <wcps.cup
+
+WCPSParser.java: parser
+
+
+WCPSSymbol.java: parser
+
+.PHONY:
+clean:
+ rm -f *.class WCPSScanner.java WCPSParser.java WCPSSymbol.java
+
+
+
+
diff --git a/src/syntaxParser/NumericScalarExpr.java b/src/syntaxParser/NumericScalarExpr.java
new file mode 100644
index 0000000..049c3b9
--- /dev/null
+++ b/src/syntaxParser/NumericScalarExpr.java
@@ -0,0 +1,51 @@
+package syntaxParser;
+/**
+ * NumericScalarExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class NumericScalarExpr implements IParseTreeNode {
+ NumericScalarExpr leftNumericScalarExpr, rightNumericScalarExpr;
+ String function;
+ String constValue;
+
+ public NumericScalarExpr(String scalar){
+ constValue = scalar;
+ function = "scalar";
+ }
+
+
+ public NumericScalarExpr(String op, NumericScalarExpr expr) throws Exception{
+ leftNumericScalarExpr = expr;
+ if (op.equals("+")) function = "scalarUnaryPlus";
+ else if (op.equals("-")) function = "scalarUnaryMinus";
+ else if (op.equals("abs")) function = "scalarAbs";
+ else throw new Exception("Operator " + op + " is not recognized!");
+ }
+
+ public NumericScalarExpr(String op, NumericScalarExpr lbe, NumericScalarExpr rbe) throws Exception {
+ leftNumericScalarExpr = lbe ;
+ rightNumericScalarExpr = rbe ;
+ if (op.equals("+")) function = "scalarPlus";
+ else if (op.equals("-")) function = "scalarMinus";
+ else if (op.equals("*")) function = "scalarMult";
+ else if (op.equals("/")) function = "scalarDiv";
+ else throw new Exception("Operator " + op + " is not recognized!");
+ }
+
+ public String toXML() {
+ String result;
+ result = "<" + function + ">";
+ if (function.equals("scalar")) {
+ result += constValue;
+ } else {
+ result += leftNumericScalarExpr.toXML();
+ if (rightNumericScalarExpr != null) {
+ result += rightNumericScalarExpr.toXML();
+ }
+ }
+ result += "</" + function + ">";
+ return result;
+ }
+
+}
diff --git a/src/syntaxParser/ProcessingExpr.java b/src/syntaxParser/ProcessingExpr.java
new file mode 100644
index 0000000..738ad8f
--- /dev/null
+++ b/src/syntaxParser/ProcessingExpr.java
@@ -0,0 +1,18 @@
+package syntaxParser;
+/**
+ * ProcessingExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class ProcessingExpr implements IParseTreeNode {
+ IParseTreeNode expr;
+ public ProcessingExpr( IParseTreeNode e ) {
+ expr = e;
+ }
+ public String toXML() {
+ return expr.toXML();
+ }
+
+
+
+}
diff --git a/src/syntaxParser/README b/src/syntaxParser/README
new file mode 100644
index 0000000..56a50da
--- /dev/null
+++ b/src/syntaxParser/README
@@ -0,0 +1,97 @@
+============================================================= README file =============================================================
+
+WCPS Abstract Parser and ProcessCoverage XML transformer tool
+Author: Mattia Parigiani
+
+
+
+
+The application folder contains the following:
+
+- Java CUP grammar specification file: "wcps.cup"
+- JLex Lexycal Analyzer / Scanner specification file: "wpcs.lex"
+- Utility Java classes for non-terminal symbols of grammar needed for XML conversion routines
+- batch file for parser generation under Windows OS: "run.bat"
+- Text files containing sample tested WCPS requests: "SAMPLE_REQUESTS.txt", "test_requests.txt"
+- JLex runtime executables directory: in sub directory "./JLex"
+- Java CUP runtime jar library : "java-cup-11a.jar"
+- Java CUP runtime executables directory: in sub directory "./java_cup"
+- Lexycal scanner generated source code and executable: respectevely "wcps.lex.java" and "WCPSScanner.class"
+- Parser generated source code and executable: respectevely "WCPSParser.java" and "WCPSParser.class"
+- Symbols generate source code and executable: respectevely "WCPSSymbol.java" and "WCPSSymbol.class"
+- README.txt file
+
+
+
+
+
+The tool may be used in the following two ways:
+1) Simple Usage
+2) Further developments
+
+
+
+======================================================================================================================================
+1) Simple Usage:
+
+Users that want to only use the WCPS Parser/Transformer utility need to do the following operations:
+
+ - Edit the "request.wcps" file and enter a valid WCPS request
+ The syntax will be considered to be valid if it can be parsed with no errors and if it is conformant to the
+ Java CUP grammar specification.
+
+ - Execute the WCPSRequestProcessor program:
+ This will produce the appropriate ProcessCoverage XMl request file is the parsed request does not contain
+ any syntax errors.
+
+ - Open the "wcpsRequest.xml" to see the output XML request file.
+
+ - Optionally connect to the WCPS service at http://mango.eecs.jacob-university.de:8080/wcps_0.3.5/ and submit the XML file
+ using the file upload field.
+ The coverage data will be returned only if the specified sets in the request exist on the server side.
+
+
+
+
+======================================================================================================================================
+2) Further Development:
+
+Users that may want to bring modification to the utility will mainly need to edit the CUP specification file and the JLex specification.
+- The CUP specification is within the "wcps.cup" file
+- The JLex specification is within the "wcps.lex" file
+
+Once modifications have been made the new parser can be generated by executing the following sequence of commands:
+
+- java JLex.Main wcps.lex
+ This generates the lexycal analyzer and scanner using JLex technology
+
+- java java_cup.Main -parser WCPSParser -symbols WCPSSymbol <wcps.cup
+ This generates the source for the parser and symbol class using Java CUP technology.
+ The sources are renamed WCPSParser.java and WCPSSymbol.java.
+ Different names may be used as long as the calling program also considers these changes
+
+- javac wcps.lex.java
+ This compiles the Scanner class generated by the JLex technology. The class is named wcps.lex.java by default.
+ This name is conventional and comes directly from the fact that the JLex specification file is called "wcps.lex"
+
+- javac WCPSParser.java WCPSSymbol.java WCPSRequestProcessor.java
+ This compiles the parser and the symbol sources together with the calling program (WCPSRequestProcessor).
+ Please see the source code for WCPSRequestProcessor.java to see the exact usage.
+
+At this moment, the parser is ready for any WCPS request. The WCPSRequestProcessor.java code is an example for how the parser can be invoked by
+reading a WCPS request string from a file (namely, "request.wcps"). To invoke the WCPSRequestProcessor.java example program simply call:
+
+- java WCPSRequestProcessor
+
+This is mainly what is specified in the previous section of this README file (Simple Usage)
+
+
+NOTE:
+Windows users can get the cascading effect of executing all these commands in a row by using the provided batch file (namely, "run.bat" ).
+From the windows command prompt, enter the application folder and type:
+
+- run
+
+Please have a look at the "run.bat" for further clarification
+
+====================================================================================================================================== \ No newline at end of file
diff --git a/src/syntaxParser/RangeValue.java b/src/syntaxParser/RangeValue.java
new file mode 100644
index 0000000..c8d4739
--- /dev/null
+++ b/src/syntaxParser/RangeValue.java
@@ -0,0 +1,17 @@
+package syntaxParser;
+/* Author: Sorin stancu-Mara
+ * Date: 9 Feb 2008
+ */
+
+class RangeValue implements IParseTreeNode {
+ String value;
+ public RangeValue(String value) {
+ this.value = value;
+ }
+ public RangeValue(StructuredLiteral value) {
+ this.value = value.toXML();
+ }
+ public String toXML() {
+ return value;
+ }
+}
diff --git a/src/syntaxParser/RangeValueList.java b/src/syntaxParser/RangeValueList.java
new file mode 100644
index 0000000..79630b0
--- /dev/null
+++ b/src/syntaxParser/RangeValueList.java
@@ -0,0 +1,10 @@
+package syntaxParser;
+
+class RangeValueList extends List {
+ public RangeValueList(RangeValue elem) { super((IParseTreeNode)elem); }
+ public RangeValueList(RangeValue elem, RangeValueList next) { super((IParseTreeNode)elem, (List)next); }
+}
+
+
+
+
diff --git a/src/syntaxParser/ReduceExpr.java b/src/syntaxParser/ReduceExpr.java
new file mode 100644
index 0000000..031921e
--- /dev/null
+++ b/src/syntaxParser/ReduceExpr.java
@@ -0,0 +1,19 @@
+package syntaxParser;
+/**
+ * ReduceExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class ReduceExpr implements IParseTreeNode{
+ CoverageExpr coverageExpr;
+ String operator;
+
+ public ReduceExpr( CoverageExpr ce, String op){
+ coverageExpr = ce;
+ operator = op;
+ }
+
+ public String toXML(){
+ return "<" + operator + ">" + coverageExpr.toXML() + "</" + operator + ">";
+ }
+}
diff --git a/src/syntaxParser/ReturnClause.java b/src/syntaxParser/ReturnClause.java
new file mode 100644
index 0000000..36af7bb
--- /dev/null
+++ b/src/syntaxParser/ReturnClause.java
@@ -0,0 +1,16 @@
+package syntaxParser;
+/**
+ * ReturnClause
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class ReturnClause implements IParseTreeNode {
+ private ProcessingExpr processingExpr;
+ public ReturnClause( ProcessingExpr pr){
+ processingExpr =pr;
+ }
+
+ public String toXML(){
+ return processingExpr.toXML();
+ }
+}
diff --git a/src/syntaxParser/SAMPLE_REQUESTS.txt b/src/syntaxParser/SAMPLE_REQUESTS.txt
new file mode 100644
index 0000000..df8942a
--- /dev/null
+++ b/src/syntaxParser/SAMPLE_REQUESTS.txt
@@ -0,0 +1,52 @@
+
+
+
+
+ This file contains some sampled and tested WCPS requests as translated from their original ProcessCoverage.xml form.
+ The corresponding ProcesseCoverage.xml files where created and used in the development of the WCPS service.
+
+ The current test WCPS service is found at http://mango.eecs.jacobs-university.de:8080/wcps_0.3.5/
+
+ There are two ways to use them
+ 1) Directly from command line >> copy the request into the file "request.wcps" and run the java command:
+ java WCPSRequestProcessor
+ This supposes that the parser has already been generated and all binaries are already available in the application folder.
+ If this is not true, please refer to the README/INSTALL file for help on how to generate the parser/translater.
+ The application will generate the ProcessCoverage.xml file.
+ Now connect to http://mango.eecs.jacobs-university.de:8080/wcps_0.3.5/ and submit the xml request file.
+ The coverage response data will be displayed from the WCPS service servlet.
+
+ 2) From the Request Servlet >> This is still under development. The idea is that the user will be presented with a web interface
+ where to insert the request, he will submit such request and automagically get the relative coverage response data.
+
+
+
+
+
+
+
+extract request:
+
+ for m in (rgb) return encode(m, png)
+
+
+
+
+extract green channel request:
+
+ for m in (rgb) return encode ( m.green , png)
+
+
+
+
+scale request:
+
+ for m in (rgb) return encode ( scale ( scale( m,1,0,130,nearest neighbor ) , 0,0,640,nearest neighbor ) , png)
+
+
+
+
+
+scale and extract green channel request:
+
+ for m in (rgb) return encode ( scale ( scale( m,1,0,130,nearest neighbor ) , 0,0,640,nearest neighbor ).green , png) \ No newline at end of file
diff --git a/src/syntaxParser/ScalarExpr.java b/src/syntaxParser/ScalarExpr.java
new file mode 100644
index 0000000..e5b72a8
--- /dev/null
+++ b/src/syntaxParser/ScalarExpr.java
@@ -0,0 +1,18 @@
+package syntaxParser;
+/**
+ * ScalarExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class ScalarExpr implements IParseTreeNode {
+ IParseTreeNode expr;
+
+ public ScalarExpr(IParseTreeNode e) {
+ expr = e;
+ }
+
+ public String toXML(){
+ return expr.toXML();
+ }
+
+}
diff --git a/src/syntaxParser/ScalarLit.java b/src/syntaxParser/ScalarLit.java
new file mode 100644
index 0000000..c9810a8
--- /dev/null
+++ b/src/syntaxParser/ScalarLit.java
@@ -0,0 +1,42 @@
+package syntaxParser;
+/**
+ * ScalarLit
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani
+ */
+class ScalarLit {
+
+ AtomicLit atomicLit;
+ ComplexLit complexLit;
+ String flag;
+
+ /**
+ * ScalarLit constructor comment.
+ */
+ public ScalarLit() {
+ super();
+ }
+ public ScalarLit( AtomicLit al){
+ atomicLit = al;
+ flag = "atomicLit";
+ }
+
+ public ScalarLit( ComplexLit cl){
+ complexLit = cl;
+ flag = "complexLit";
+ }
+
+ String toXML(){
+ String result="" ;
+ try {
+ if (flag.equals("complexLit")) {
+ result += complexLit.toXML();
+ } else if (flag.equals("atomicLit")) {
+ result += atomicLit.toXML();
+ }
+ } catch (Exception e ) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+}
diff --git a/src/syntaxParser/ScalarLitList.java b/src/syntaxParser/ScalarLitList.java
new file mode 100644
index 0000000..49e187b
--- /dev/null
+++ b/src/syntaxParser/ScalarLitList.java
@@ -0,0 +1,52 @@
+package syntaxParser;
+/**
+ * ScalarLitList class represents a CoverageList.
+ * Creation date: (3/3/2003 2:52:55 AM)
+ * @author: mattia parigiani
+ */
+import java.util.*;
+public class ScalarLitList {
+ private Vector scalarLits;
+
+
+ /**
+ * CoverageList constructor comment.
+ */
+ public ScalarLitList() {
+ super();
+ }
+ public ScalarLitList(ScalarLit sl) {
+ scalarLits = new Vector();
+ scalarLits.add(sl);
+ }
+
+ public ScalarLitList(ScalarLit sl, ScalarLitList l) {
+ scalarLits = l.getScalarLits();
+ scalarLits.add(sl);
+ }
+
+
+ public Vector getScalarLits(){
+ return scalarLits;
+ }
+
+ String toXML(){
+ String result="" ;
+
+
+ for (Enumeration e=scalarLits.elements(); e.hasMoreElements(); ){
+ /*String s= (String)e.nextElement();
+ result += "\n<coverageOrSetName>";
+ result += (s instanceof String)? s: " ";
+ result += "</coverageOrSetName>\n";
+ */
+ }
+
+
+ result += "just parsing";
+ return result;
+ }
+
+
+
+}
diff --git a/src/syntaxParser/ScaleExpr.java b/src/syntaxParser/ScaleExpr.java
new file mode 100644
index 0000000..990a976
--- /dev/null
+++ b/src/syntaxParser/ScaleExpr.java
@@ -0,0 +1,24 @@
+package syntaxParser;
+/**
+ * ScaleExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class ScaleExpr implements IParseTreeNode {
+
+ CoverageExpr coverageExpr;
+ AxisIntervalList intervalList;
+ FieldInterpolationList interpMethods;
+
+ public ScaleExpr( CoverageExpr ce, AxisIntervalList ail, FieldInterpolationList iml){
+ coverageExpr = ce;
+ intervalList = ail;
+ intervalList.setTag("scaleAxisSpec");
+ interpMethods = iml;
+ interpMethods.setTag("scaleFieldSpec");
+ }
+
+ public String toXML(){
+ return "<scale>" + intervalList.toXML() + interpMethods.toXML() + coverageExpr.toXML() + "</scale>";
+ }
+}
diff --git a/src/syntaxParser/SelectExpr.java b/src/syntaxParser/SelectExpr.java
new file mode 100644
index 0000000..aa8d23d
--- /dev/null
+++ b/src/syntaxParser/SelectExpr.java
@@ -0,0 +1,22 @@
+package syntaxParser;
+/**
+ * SelectExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class SelectExpr implements IParseTreeNode {
+ CoverageExpr coverageExpr;
+ String field;
+
+ public SelectExpr( CoverageExpr ce, String se){
+ coverageExpr = ce;
+ field = se;
+ }
+ public String toXML(){
+ String result="<select>" ;
+ result += "<field>" + field + "</field>";
+ result += coverageExpr.toXML();
+ result += "</select>";
+ return result;
+ }
+}
diff --git a/src/syntaxParser/SetMetaDataExpr.java b/src/syntaxParser/SetMetaDataExpr.java
new file mode 100644
index 0000000..e8624b7
--- /dev/null
+++ b/src/syntaxParser/SetMetaDataExpr.java
@@ -0,0 +1,54 @@
+package syntaxParser;
+/**
+ * SetMetaDataExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class SetMetaDataExpr implements IParseTreeNode {
+
+ String function;
+ CoverageExpr expr;
+ IParseTreeNode param;
+ String field;
+
+ public SetMetaDataExpr(String op, CoverageExpr expr,IParseTreeNode param) {
+ function = op;
+ this.expr = expr;
+ this.param = param;
+ }
+ public SetMetaDataExpr(String op, CoverageExpr expr, IParseTreeNode param, String field) {
+ function = op;
+ this.expr = expr;
+ this.param = param;
+ }
+
+ public String toXML(){
+ String result= "" ;
+
+ if (function.equals("setNullDefault")) {
+ result = "<setNullDefault>" + "<null>" + param.toXML() + "</null>"
+ + expr.toXML()
+ + "</setNullDefault>";
+ } else if (function.equals("setNullSet")) {
+ result = "<setNullSet>";
+ RangeValueList list = (RangeValueList) param;
+ list.setTag("null");
+ result += list.toXML();
+ result += expr.toXML() + "</setNullSet>";
+ } else if (function.equals("setInterpolationDefault")) {
+ result = "<setInterpolationDefault><field>" + field + "</field>"
+ + param.toXML() + expr.toXML() + "</setInterpolationDefault>";
+ } else if (function.equals("setInterpolationSet")) {
+ result = "<setInterpolationSet><field>" + field + "</field>" + param.toXML() +
+ expr.toXML() + "</setInterpolationSet>";
+ } else if (function.equals("setCrsSet")) {
+ // TODO(smsorin): schema/grammar inconsistencies
+ result += "<setCrsSet>" + expr.toXML()
+ + "</setCrsSet>";
+ }
+
+ result+= "";
+ return result;
+ }
+
+}
diff --git a/src/syntaxParser/SliceExpr.java b/src/syntaxParser/SliceExpr.java
new file mode 100644
index 0000000..58a69a5
--- /dev/null
+++ b/src/syntaxParser/SliceExpr.java
@@ -0,0 +1,20 @@
+package syntaxParser;
+/**
+ * SliceExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class SliceExpr implements IParseTreeNode {
+
+ CoverageExpr coverageExpr;
+ AxisPointList pointList;
+ public SliceExpr( CoverageExpr ce, AxisPointList apl){
+ coverageExpr = ce;
+ pointList = apl;
+ pointList.setTag("sliceAxisSpec");
+ }
+
+ public String toXML(){
+ return "<slice>" + pointList.toXML() + coverageExpr.toXML() + "</slice>";
+ }
+}
diff --git a/src/syntaxParser/StoreExpr.java b/src/syntaxParser/StoreExpr.java
new file mode 100644
index 0000000..0848053
--- /dev/null
+++ b/src/syntaxParser/StoreExpr.java
@@ -0,0 +1,15 @@
+package syntaxParser;
+/* Author: Sorin Stancu-Mara
+Date: 7 Feb 2007
+*/
+
+class StoreExpr implements IParseTreeNode {
+ private EncodedCoverageExpr expr;
+ public StoreExpr(EncodedCoverageExpr e) {
+ expr = e;
+ expr.setStoreFlag();
+ }
+ public String toXML() {
+ return expr.toXML();
+ }
+}
diff --git a/src/syntaxParser/StructuredLiteral.java b/src/syntaxParser/StructuredLiteral.java
new file mode 100644
index 0000000..f6db33c
--- /dev/null
+++ b/src/syntaxParser/StructuredLiteral.java
@@ -0,0 +1,15 @@
+package syntaxParser;
+/* Author: Sorin Stancu-Mara
+ * Date 9 Feb 2007
+ */
+
+class StructuredLiteral implements IParseTreeNode {
+ RangeValueList values;
+ public StructuredLiteral(RangeValueList rvl) {
+ values = rvl;
+ }
+
+ public String toXML() {
+ return values.toXML();
+ }
+}
diff --git a/src/syntaxParser/SubsetExpr.java b/src/syntaxParser/SubsetExpr.java
new file mode 100644
index 0000000..d9020d3
--- /dev/null
+++ b/src/syntaxParser/SubsetExpr.java
@@ -0,0 +1,21 @@
+package syntaxParser;
+/**
+ * SubsetExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class SubsetExpr implements IParseTreeNode {
+
+ IParseTreeNode expr;
+
+ public SubsetExpr( IParseTreeNode e ){
+ expr = e;
+ }
+
+ public String toXML(){
+ return expr.toXML();
+ }
+
+
+
+}
diff --git a/src/syntaxParser/SyntaxErrorException.java b/src/syntaxParser/SyntaxErrorException.java
new file mode 100644
index 0000000..e1aa32a
--- /dev/null
+++ b/src/syntaxParser/SyntaxErrorException.java
@@ -0,0 +1,26 @@
+package syntaxParser;
+
+public class SyntaxErrorException extends Exception {
+ private int line;
+ private int column;
+
+ public SyntaxErrorException(int line, int column) {
+ super("Syntax Error");
+ this.line = line;
+ this.column = column;
+ }
+
+ public SyntaxErrorException(int line, int column, String message) {
+ super(message);
+ this.line = line;
+ this.column = column;
+ }
+
+ public int getLine() {
+ return line;
+ }
+
+ public int getColumn() {
+ return column;
+ }
+}
diff --git a/src/syntaxParser/TrigonometricExpr.java b/src/syntaxParser/TrigonometricExpr.java
new file mode 100644
index 0000000..d1a4d06
--- /dev/null
+++ b/src/syntaxParser/TrigonometricExpr.java
@@ -0,0 +1,23 @@
+package syntaxParser;
+/**
+ * TrigonometricExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class TrigonometricExpr implements IParseTreeNode {
+ String trigOperator;
+ CoverageExpr coverageExpr;
+
+ public TrigonometricExpr( CoverageExpr ce, String op){
+ trigOperator = op;
+ coverageExpr = ce;
+ }
+
+ public String toXML(){
+ String result= "" ;
+ result += "<" + trigOperator + ">";
+ result += coverageExpr.toXML() ;
+ result += "</" + trigOperator + ">";
+ return result;
+ }
+}
diff --git a/src/syntaxParser/TrimExpr.java b/src/syntaxParser/TrimExpr.java
new file mode 100644
index 0000000..359d139
--- /dev/null
+++ b/src/syntaxParser/TrimExpr.java
@@ -0,0 +1,21 @@
+package syntaxParser;
+/**
+ * TrimExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class TrimExpr implements IParseTreeNode {
+
+ CoverageExpr coverageExpr;
+ AxisIntervalList axisIntervals;
+
+ public TrimExpr( CoverageExpr ce, AxisIntervalList al ){
+ coverageExpr = ce;
+ axisIntervals = al;
+ axisIntervals.setTag("trimAxisSpec");
+ }
+
+ public String toXML(){
+ return "<trim>" + axisIntervals.toXML() + coverageExpr.toXML() + "</trim>";
+ }
+}
diff --git a/src/syntaxParser/UnaryArithMeticExpr.java b/src/syntaxParser/UnaryArithMeticExpr.java
new file mode 100644
index 0000000..94d4167
--- /dev/null
+++ b/src/syntaxParser/UnaryArithMeticExpr.java
@@ -0,0 +1,31 @@
+package syntaxParser;
+/**
+ * UnaryArithmeticExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class UnaryArithMeticExpr implements IParseTreeNode {
+
+ String operator;
+ CoverageExpr coverageExpr;
+
+ public UnaryArithMeticExpr( CoverageExpr ce, String op){
+ operator = op;
+ coverageExpr = ce;
+ }
+ public String toXML(){
+ String result= "" ;
+ String op;
+ if (operator.equals("+")) {
+ op = "unaryPlus";
+ } else if (operator.equals("-")) {
+ op = "unaryMinus";
+ } else {
+ op = operator;
+ }
+ result += "<" + op + ">\n";
+ result += coverageExpr.toXML() ;
+ result += "</" + op + ">\n";
+ return result;
+ }
+}
diff --git a/src/syntaxParser/UnaryInducedExpr.java b/src/syntaxParser/UnaryInducedExpr.java
new file mode 100644
index 0000000..2c0b9eb
--- /dev/null
+++ b/src/syntaxParser/UnaryInducedExpr.java
@@ -0,0 +1,23 @@
+package syntaxParser;
+/**
+ * UnaryInducedExpr
+ * Creation date: (3/3/2003 2:28:43 AM)
+ * @author: mattia parigiani, Sorin Stancu-Mara
+ */
+class UnaryInducedExpr implements IParseTreeNode {
+
+ IParseTreeNode expr;
+ String flag;
+
+ public UnaryInducedExpr( IParseTreeNode e ){
+ expr = e;
+ }
+
+
+ public String toXML(){
+ return expr.toXML();
+ }
+
+
+
+}
diff --git a/src/syntaxParser/VariableList.java b/src/syntaxParser/VariableList.java
new file mode 100644
index 0000000..f41d0a7
--- /dev/null
+++ b/src/syntaxParser/VariableList.java
@@ -0,0 +1,37 @@
+package syntaxParser;
+/* Author: Sorin Stancu-Mara
+ * Date: 8 Feb 2008
+ */
+
+class VariableList implements IParseTreeNode {
+ String axisType, iteratorName;
+ String lo,hi;
+ VariableList next;
+
+ public VariableList(String type, String name, String lo, String hi) {
+ axisType = type;
+ iteratorName = name;
+ this.lo = lo;
+ this.hi = hi;
+ next = null;
+ }
+
+ public VariableList(String type, String name, String lo, String hi, VariableList next) {
+ axisType = type;
+ iteratorName = name;
+ this.lo = lo;
+ this.hi = hi;
+ this.next = next;
+ }
+
+ public String toXML() {
+ String result = "<axisIterator><axisType>" + axisType + "</axisType>" +
+ "<iteratorVar>" + iteratorName + "</iteratorVar>" +
+ "<coord>" + lo + "</coord>" +
+ "<coord>" + hi + "</coord></axisIterator>";
+
+ if (next != null) result += next.toXML();
+ return result;
+ }
+
+}
diff --git a/src/syntaxParser/WCPSRequest.java b/src/syntaxParser/WCPSRequest.java
new file mode 100644
index 0000000..381244b
--- /dev/null
+++ b/src/syntaxParser/WCPSRequest.java
@@ -0,0 +1,42 @@
+package syntaxParser;
+/**
+ * WCPSRequest class represents a WCPSRequest.
+ * Creation date: (3/3/2003 2:52:55 AM)
+ * @author: *, Sorin Stancu-Mara
+ */
+import java.util.*;
+public class WCPSRequest implements IParseTreeNode {
+ private ForClause forClause;
+ private WhereClause whereClause;
+ private ReturnClause returnClause;
+
+ /**
+ * WCPSRequest constructor comment.
+ */
+ public WCPSRequest() {
+ super();
+ }
+ public WCPSRequest(ForClause f, ReturnClause r) {
+ forClause = f;
+ whereClause = null;
+ returnClause = r;
+ }
+ public WCPSRequest(ForClause f, WhereClause w, ReturnClause r) {
+ forClause = f;
+ whereClause = w;
+ returnClause = r;
+ }
+
+ public String toXML(){
+ String result="<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
+ result += "<processCoverage xmlns=\"http://www.opengis.net/wcps/1.0.0\" service=\"WCPS\" version=\"1.0.0\">\n";
+ result += forClause.toXML();
+ if (whereClause != null) {
+ result += whereClause.toXML();
+ }
+ result += returnClause.toXML();
+ result += "</processCoverage>";
+ return result;
+ }
+
+}
diff --git a/src/syntaxParser/WCPSRequestProcessor.java b/src/syntaxParser/WCPSRequestProcessor.java
new file mode 100644
index 0000000..c6fc86f
--- /dev/null
+++ b/src/syntaxParser/WCPSRequestProcessor.java
@@ -0,0 +1,46 @@
+package syntaxParser;
+/**
+ * WCPSRequestProcessor = Sample source code which makes use of the generated parser to parse a WCPS request stored in script file (request.wcps)
+ * The result XML ProcessCoverage file is stored in the file wcpsRequest.xml
+ * Creation date: (3/3/2003 3:22:26 AM)
+ * @author: mattia parigiani
+ */
+import java.io.*;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.*;
+import javax.xml.parsers.*;
+import javax.xml.transform.dom.*;
+import javax.xml.transform.stream.StreamResult;
+import org.w3c.dom.*;
+
+class WCPSRequestProcessor {
+
+ public static void main(String[] args){
+ try {
+ File inputFile = new File ("request.wcps");
+ WCPSParser parser= new WCPSParser(new WCPSScanner(new FileInputStream(inputFile)));
+ WCPSRequest pm= (WCPSRequest)parser.parse().value;
+ String xmlString=pm.toXML();
+
+ TransformerFactory factory = TransformerFactory.newInstance();
+ factory.setAttribute("indent-number", new Integer(4));
+ DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ Document doc = docBuilder.parse(new ByteArrayInputStream(xmlString.getBytes()));
+ Transformer transformer = factory.newTransformer();
+ transformer.setOutputProperty("omit-xml-declaration","no");
+ transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ StringWriter sw = new StringWriter();
+ transformer.transform(new DOMSource(doc), new StreamResult(sw));
+ String formattedXML = sw.toString();
+
+ FileWriter fstream = new FileWriter("wcpsRequest.xml");
+ BufferedWriter out = new BufferedWriter(fstream);
+ out.write(formattedXML);
+ out.close();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/syntaxParser/WhereClause.java b/src/syntaxParser/WhereClause.java
new file mode 100644
index 0000000..12eb97e
--- /dev/null
+++ b/src/syntaxParser/WhereClause.java
@@ -0,0 +1,14 @@
+package syntaxParser;
+/* Author: Sorin Stancu-Mara
+Date: 7 Feb 2007
+*/
+
+class WhereClause implements IParseTreeNode {
+ private BooleanScalarExpr expr;
+ public WhereClause(BooleanScalarExpr e) {
+ expr = e;
+ }
+ public String toXML() {
+ return "<where>" + expr.toXML() + "</where>";
+ }
+}
diff --git a/src/syntaxParser/java-cup-11a.jar b/src/syntaxParser/java-cup-11a.jar
new file mode 100644
index 0000000..73ffa0b
--- /dev/null
+++ b/src/syntaxParser/java-cup-11a.jar
Binary files differ
diff --git a/src/syntaxParser/java_cup/CUP$parser$actions.class b/src/syntaxParser/java_cup/CUP$parser$actions.class
new file mode 100644
index 0000000..b0b50b0
--- /dev/null
+++ b/src/syntaxParser/java_cup/CUP$parser$actions.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/Main.class b/src/syntaxParser/java_cup/Main.class
new file mode 100644
index 0000000..2947306
--- /dev/null
+++ b/src/syntaxParser/java_cup/Main.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/Main.java b/src/syntaxParser/java_cup/Main.java
new file mode 100644
index 0000000..50811b5
--- /dev/null
+++ b/src/syntaxParser/java_cup/Main.java
@@ -0,0 +1,854 @@
+
+package java_cup;
+
+import java.util.Enumeration;
+import java.io.*;
+
+/** This class serves as the main driver for the JavaCup system.
+ * It accepts user options and coordinates overall control flow.
+ * The main flow of control includes the following activities:
+ * <ul>
+ * <li> Parse user supplied arguments and options.
+ * <li> Open output files.
+ * <li> Parse the specification from standard input.
+ * <li> Check for unused terminals, non-terminals, and productions.
+ * <li> Build the state machine, tables, etc.
+ * <li> Output the generated code.
+ * <li> Close output files.
+ * <li> Print a summary if requested.
+ * </ul>
+ *
+ * Options to the main program include: <dl>
+ * <dt> -package name
+ * <dd> specify package generated classes go in [default none]
+ * <dt> -parser name
+ * <dd> specify parser class name [default "parser"]
+ * <dt> -symbols name
+ * <dd> specify name for symbol constant class [default "sym"]
+ * <dt> -interface
+ * <dd> emit symbol constant <i>interface</i>, rather than class
+ * <dt> -nonterms
+ * <dd> put non terminals in symbol constant class
+ * <dt> -expect #
+ * <dd> number of conflicts expected/allowed [default 0]
+ * <dt> -compact_red
+ * <dd> compact tables by defaulting to most frequent reduce
+ * <dt> -nowarn
+ * <dd> don't warn about useless productions, etc.
+ * <dt> -nosummary
+ * <dd> don't print the usual summary of parse states, etc.
+ * <dt> -progress
+ * <dd> print messages to indicate progress of the system
+ * <dt> -time
+ * <dd> print time usage summary
+ * <dt> -dump_grammar
+ * <dd> produce a dump of the symbols and grammar
+ * <dt> -dump_states
+ * <dd> produce a dump of parse state machine
+ * <dt> -dump_tables
+ * <dd> produce a dump of the parse tables
+ * <dt> -dump
+ * <dd> produce a dump of all of the above
+ * <dt> -debug
+ * <dd> turn on debugging messages within JavaCup
+ * <dt> -nopositions
+ * <dd> don't generate the positions code
+ * <dt> -noscanner
+ * <dd> don't refer to java_cup.runtime.Scanner in the parser
+ * (for compatibility with old runtimes)
+ * <dt> -version
+ * <dd> print version information for JavaCUP and halt.
+ * </dl>
+ *
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+
+public class Main {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+ /** Only constructor is private, so we do not allocate any instances of this
+ class. */
+ private Main() { }
+
+ /*-------------------------*/
+ /* Options set by the user */
+ /*-------------------------*/
+ /** User option -- do we print progress messages. */
+ protected static boolean print_progress = true;
+ /** User option -- do we produce a dump of the state machine */
+ protected static boolean opt_dump_states = false;
+ /** User option -- do we produce a dump of the parse tables */
+ protected static boolean opt_dump_tables = false;
+ /** User option -- do we produce a dump of the grammar */
+ protected static boolean opt_dump_grammar = false;
+ /** User option -- do we show timing information as a part of the summary */
+ protected static boolean opt_show_timing = false;
+ /** User option -- do we run produce extra debugging messages */
+ protected static boolean opt_do_debug = false;
+ /** User option -- do we compact tables by making most common reduce the
+ default action */
+ protected static boolean opt_compact_red = false;
+ /** User option -- should we include non terminal symbol numbers in the
+ symbol constant class. */
+ protected static boolean include_non_terms = false;
+ /** User option -- do not print a summary. */
+ protected static boolean no_summary = false;
+ /** User option -- number of conflicts to expect */
+ protected static int expect_conflicts = 0;
+
+ /* frankf added this 6/18/96 */
+ /** User option -- should generator generate code for left/right values? */
+ protected static boolean lr_values = true;
+
+ /** User option -- should symbols be put in a class or an interface? [CSA]*/
+ protected static boolean sym_interface = false;
+
+ /** User option -- should generator suppress references to
+ * java_cup.runtime.Scanner for compatibility with old runtimes? */
+ protected static boolean suppress_scanner = false;
+
+ /*----------------------------------------------------------------------*/
+ /* Timing data (not all of these time intervals are mutually exclusive) */
+ /*----------------------------------------------------------------------*/
+ /** Timing data -- when did we start */
+ protected static long start_time = 0;
+ /** Timing data -- when did we end preliminaries */
+ protected static long prelim_end = 0;
+ /** Timing data -- when did we end parsing */
+ protected static long parse_end = 0;
+ /** Timing data -- when did we end checking */
+ protected static long check_end = 0;
+ /** Timing data -- when did we end dumping */
+ protected static long dump_end = 0;
+ /** Timing data -- when did we end state and table building */
+ protected static long build_end = 0;
+ /** Timing data -- when did we end nullability calculation */
+ protected static long nullability_end = 0;
+ /** Timing data -- when did we end first set calculation */
+ protected static long first_end = 0;
+ /** Timing data -- when did we end state machine construction */
+ protected static long machine_end = 0;
+ /** Timing data -- when did we end table construction */
+ protected static long table_end = 0;
+ /** Timing data -- when did we end checking for non-reduced productions */
+ protected static long reduce_check_end = 0;
+ /** Timing data -- when did we finish emitting code */
+ protected static long emit_end = 0;
+ /** Timing data -- when were we completely done */
+ protected static long final_time = 0;
+
+ /* Additional timing information is also collected in emit */
+
+ /*-----------------------------------------------------------*/
+ /*--- Main Program ------------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The main driver for the system.
+ * @param argv an array of strings containing command line arguments.
+ */
+ public static void main(String argv[])
+ throws internal_error, java.io.IOException, java.lang.Exception
+ {
+ boolean did_output = false;
+
+ start_time = System.currentTimeMillis();
+
+ /* process user options and arguments */
+ parse_args(argv);
+
+ /* frankf 6/18/96
+ hackish, yes, but works */
+ emit.set_lr_values(lr_values);
+ /* open output files */
+ if (print_progress) System.err.println("Opening files...");
+ /* use a buffered version of standard input */
+ input_file = new BufferedInputStream(System.in);
+
+ prelim_end = System.currentTimeMillis();
+
+ /* parse spec into internal data structures */
+ if (print_progress)
+ System.err.println("Parsing specification from standard input...");
+ parse_grammar_spec();
+
+ parse_end = System.currentTimeMillis();
+
+ /* don't proceed unless we are error free */
+ if (lexer.error_count == 0)
+ {
+ /* check for unused bits */
+ if (print_progress) System.err.println("Checking specification...");
+ check_unused();
+
+ check_end = System.currentTimeMillis();
+
+ /* build the state machine and parse tables */
+ if (print_progress) System.err.println("Building parse tables...");
+ build_parser();
+
+ build_end = System.currentTimeMillis();
+
+ /* output the generated code, if # of conflicts permits */
+ if (lexer.error_count != 0) {
+ // conflicts! don't emit code, don't dump tables.
+ opt_dump_tables = false;
+ } else { // everything's okay, emit parser.
+ if (print_progress) System.err.println("Writing parser...");
+ open_files();
+ emit_parser();
+ did_output = true;
+ }
+ }
+ /* fix up the times to make the summary easier */
+ emit_end = System.currentTimeMillis();
+
+ /* do requested dumps */
+ if (opt_dump_grammar) dump_grammar();
+ if (opt_dump_states) dump_machine();
+ if (opt_dump_tables) dump_tables();
+
+ dump_end = System.currentTimeMillis();
+
+ /* close input/output files */
+ if (print_progress) System.err.println("Closing files...");
+ close_files();
+
+ /* produce a summary if desired */
+ if (!no_summary) emit_summary(did_output);
+
+ /* If there were errors during the run,
+ * exit with non-zero status (makefile-friendliness). --CSA */
+ if (lexer.error_count != 0)
+ System.exit(100);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Print a "usage message" that described possible command line options,
+ * then exit.
+ * @param message a specific error message to preface the usage message by.
+ */
+ protected static void usage(String message)
+ {
+ System.err.println();
+ System.err.println(message);
+ System.err.println();
+ System.err.println(
+"Usage: " + version.program_name + " [options] [filename]\n" +
+" and expects a specification file on standard input if no filename is given.\n" +
+" Legal options include:\n" +
+" -package name specify package generated classes go in [default none]\n" +
+" -parser name specify parser class name [default \"parser\"]\n" +
+" -symbols name specify name for symbol constant class [default \"sym\"]\n"+
+" -interface put symbols in an interface, rather than a class\n" +
+" -nonterms put non terminals in symbol constant class\n" +
+" -expect # number of conflicts expected/allowed [default 0]\n" +
+" -compact_red compact tables by defaulting to most frequent reduce\n" +
+" -nowarn don't warn about useless productions, etc.\n" +
+" -nosummary don't print the usual summary of parse states, etc.\n" +
+" -nopositions don't propagate the left and right token position values\n" +
+" -noscanner don't refer to java_cup.runtime.Scanner\n" +
+" -progress print messages to indicate progress of the system\n" +
+" -time print time usage summary\n" +
+" -dump_grammar produce a human readable dump of the symbols and grammar\n"+
+" -dump_states produce a dump of parse state machine\n"+
+" -dump_tables produce a dump of the parse tables\n"+
+" -dump produce a dump of all of the above\n"+
+" -version print the version information for CUP and exit\n"
+ );
+ System.exit(1);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Parse command line options and arguments to set various user-option
+ * flags and variables.
+ * @param argv the command line arguments to be parsed.
+ */
+ protected static void parse_args(String argv[])
+ {
+ int len = argv.length;
+ int i;
+
+ /* parse the options */
+ for (i=0; i<len; i++)
+ {
+ /* try to get the various options */
+ if (argv[i].equals("-package"))
+ {
+ /* must have an arg */
+ if (++i >= len || argv[i].startsWith("-") ||
+ argv[i].endsWith(".cup"))
+ usage("-package must have a name argument");
+
+ /* record the name */
+ emit.package_name = argv[i];
+ }
+ else if (argv[i].equals("-parser"))
+ {
+ /* must have an arg */
+ if (++i >= len || argv[i].startsWith("-") ||
+ argv[i].endsWith(".cup"))
+ usage("-parser must have a name argument");
+
+ /* record the name */
+ emit.parser_class_name = argv[i];
+ }
+ else if (argv[i].equals("-symbols"))
+ {
+ /* must have an arg */
+ if (++i >= len || argv[i].startsWith("-") ||
+ argv[i].endsWith(".cup"))
+ usage("-symbols must have a name argument");
+
+ /* record the name */
+ emit.symbol_const_class_name = argv[i];
+ }
+ else if (argv[i].equals("-nonterms"))
+ {
+ include_non_terms = true;
+ }
+ else if (argv[i].equals("-expect"))
+ {
+ /* must have an arg */
+ if (++i >= len || argv[i].startsWith("-") ||
+ argv[i].endsWith(".cup"))
+ usage("-expect must have a name argument");
+
+ /* record the number */
+ try {
+ expect_conflicts = Integer.parseInt(argv[i]);
+ } catch (NumberFormatException e) {
+ usage("-expect must be followed by a decimal integer");
+ }
+ }
+ else if (argv[i].equals("-compact_red")) opt_compact_red = true;
+ else if (argv[i].equals("-nosummary")) no_summary = true;
+ else if (argv[i].equals("-nowarn")) emit.nowarn = true;
+ else if (argv[i].equals("-dump_states")) opt_dump_states = true;
+ else if (argv[i].equals("-dump_tables")) opt_dump_tables = true;
+ else if (argv[i].equals("-progress")) print_progress = true;
+ else if (argv[i].equals("-dump_grammar")) opt_dump_grammar = true;
+ else if (argv[i].equals("-dump"))
+ opt_dump_states = opt_dump_tables = opt_dump_grammar = true;
+ else if (argv[i].equals("-time")) opt_show_timing = true;
+ else if (argv[i].equals("-debug")) opt_do_debug = true;
+ /* frankf 6/18/96 */
+ else if (argv[i].equals("-nopositions")) lr_values = false;
+ /* CSA 12/21/97 */
+ else if (argv[i].equals("-interface")) sym_interface = true;
+ /* CSA 23-Jul-1999 */
+ else if (argv[i].equals("-noscanner")) suppress_scanner = true;
+ /* CSA 23-Jul-1999 */
+ else if (argv[i].equals("-version")) {
+ System.out.println(version.title_str);
+ System.exit(1);
+ }
+ /* CSA 24-Jul-1999; suggestion by Jean Vaucher */
+ else if (!argv[i].startsWith("-") && i==len-1) {
+ /* use input from file. */
+ try {
+ System.setIn(new FileInputStream(argv[i]));
+ } catch (java.io.FileNotFoundException e) {
+ usage("Unable to open \"" + argv[i] +"\" for input");
+ }
+ }
+ else
+ {
+ usage("Unrecognized option \"" + argv[i] + "\"");
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /*-------*/
+ /* Files */
+ /*-------*/
+
+ /** Input file. This is a buffered version of System.in. */
+ protected static BufferedInputStream input_file;
+
+ /** Output file for the parser class. */
+ protected static PrintWriter parser_class_file;
+
+ /** Output file for the symbol constant class. */
+ protected static PrintWriter symbol_class_file;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Open various files used by the system. */
+ protected static void open_files()
+ {
+ File fil;
+ String out_name;
+
+ /* open each of the output files */
+
+ /* parser class */
+ out_name = emit.parser_class_name + ".java";
+ fil = new File(out_name);
+ try {
+ parser_class_file = new PrintWriter(
+ new BufferedOutputStream(new FileOutputStream(fil), 4096));
+ } catch(Exception e) {
+ System.err.println("Can't open \"" + out_name + "\" for output");
+ System.exit(3);
+ }
+
+ /* symbol constants class */
+ out_name = emit.symbol_const_class_name + ".java";
+ fil = new File(out_name);
+ try {
+ symbol_class_file = new PrintWriter(
+ new BufferedOutputStream(new FileOutputStream(fil), 4096));
+ } catch(Exception e) {
+ System.err.println("Can't open \"" + out_name + "\" for output");
+ System.exit(4);
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Close various files used by the system. */
+ protected static void close_files() throws java.io.IOException
+ {
+ if (input_file != null) input_file.close();
+ if (parser_class_file != null) parser_class_file.close();
+ if (symbol_class_file != null) symbol_class_file.close();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Parse the grammar specification from standard input. This produces
+ * sets of terminal, non-terminals, and productions which can be accessed
+ * via static variables of the respective classes, as well as the setting
+ * of various variables (mostly in the emit class) for small user supplied
+ * items such as the code to scan with.
+ */
+ protected static void parse_grammar_spec() throws java.lang.Exception
+ {
+ parser parser_obj;
+
+ /* create a parser and parse with it */
+ parser_obj = new parser();
+ try {
+ if (opt_do_debug)
+ parser_obj.debug_parse();
+ else
+ parser_obj.parse();
+ } catch (Exception e)
+ {
+ /* something threw an exception. catch it and emit a message so we
+ have a line number to work with, then re-throw it */
+ lexer.emit_error("Internal error: Unexpected exception");
+ throw e;
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Check for unused symbols. Unreduced productions get checked when
+ * tables are created.
+ */
+ protected static void check_unused()
+ {
+ terminal term;
+ non_terminal nt;
+
+ /* check for unused terminals */
+ for (Enumeration t = terminal.all(); t.hasMoreElements(); )
+ {
+ term = (terminal)t.nextElement();
+
+ /* don't issue a message for EOF */
+ if (term == terminal.EOF) continue;
+
+ /* or error */
+ if (term == terminal.error) continue;
+
+ /* is this one unused */
+ if (term.use_count() == 0)
+ {
+ /* count it and warn if we are doing warnings */
+ emit.unused_term++;
+ if (!emit.nowarn)
+ {
+ System.err.println("Warning: Terminal \"" + term.name() +
+ "\" was declared but never used");
+ lexer.warning_count++;
+ }
+ }
+ }
+
+ /* check for unused non terminals */
+ for (Enumeration n = non_terminal.all(); n.hasMoreElements(); )
+ {
+ nt = (non_terminal)n.nextElement();
+
+ /* is this one unused */
+ if (nt.use_count() == 0)
+ {
+ /* count and warn if we are doing warnings */
+ emit.unused_term++;
+ if (!emit.nowarn)
+ {
+ System.err.println("Warning: Non terminal \"" + nt.name() +
+ "\" was declared but never used");
+ lexer.warning_count++;
+ }
+ }
+ }
+
+ }
+
+ /* . . . . . . . . . . . . . . . . . . . . . . . . .*/
+ /* . . Internal Results of Generating the Parser . .*/
+ /* . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Start state in the overall state machine. */
+ protected static lalr_state start_state;
+
+ /** Resulting parse action table. */
+ protected static parse_action_table action_table;
+
+ /** Resulting reduce-goto table. */
+ protected static parse_reduce_table reduce_table;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Build the (internal) parser from the previously parsed specification.
+ * This includes:<ul>
+ * <li> Computing nullability of non-terminals.
+ * <li> Computing first sets of non-terminals and productions.
+ * <li> Building the viable prefix recognizer machine.
+ * <li> Filling in the (internal) parse tables.
+ * <li> Checking for unreduced productions.
+ * </ul>
+ */
+ protected static void build_parser() throws internal_error
+ {
+ /* compute nullability of all non terminals */
+ if (opt_do_debug || print_progress)
+ System.err.println(" Computing non-terminal nullability...");
+ non_terminal.compute_nullability();
+
+ nullability_end = System.currentTimeMillis();
+
+ /* compute first sets of all non terminals */
+ if (opt_do_debug || print_progress)
+ System.err.println(" Computing first sets...");
+ non_terminal.compute_first_sets();
+
+ first_end = System.currentTimeMillis();
+
+ /* build the LR viable prefix recognition machine */
+ if (opt_do_debug || print_progress)
+ System.err.println(" Building state machine...");
+ start_state = lalr_state.build_machine(emit.start_production);
+
+ machine_end = System.currentTimeMillis();
+
+ /* build the LR parser action and reduce-goto tables */
+ if (opt_do_debug || print_progress)
+ System.err.println(" Filling in tables...");
+ action_table = new parse_action_table();
+ reduce_table = new parse_reduce_table();
+ for (Enumeration st = lalr_state.all(); st.hasMoreElements(); )
+ {
+ lalr_state lst = (lalr_state)st.nextElement();
+ lst.build_table_entries(
+ action_table, reduce_table);
+ }
+
+ table_end = System.currentTimeMillis();
+
+ /* check and warn for non-reduced productions */
+ if (opt_do_debug || print_progress)
+ System.err.println(" Checking for non-reduced productions...");
+ action_table.check_reductions();
+
+ reduce_check_end = System.currentTimeMillis();
+
+ /* if we have more conflicts than we expected issue a message and die */
+ if (emit.num_conflicts > expect_conflicts)
+ {
+ System.err.println("*** More conflicts encountered than expected " +
+ "-- parser generation aborted");
+ lexer.error_count++; // indicate the problem.
+ // we'll die on return, after clean up.
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Call the emit routines necessary to write out the generated parser. */
+ protected static void emit_parser() throws internal_error
+ {
+ emit.symbols(symbol_class_file, include_non_terms, sym_interface);
+ emit.parser(parser_class_file, action_table, reduce_table,
+ start_state.index(), emit.start_production, opt_compact_red,
+ suppress_scanner);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Helper routine to optionally return a plural or non-plural ending.
+ * @param val the numerical value determining plurality.
+ */
+ protected static String plural(int val)
+ {
+ if (val == 1)
+ return "";
+ else
+ return "s";
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit a long summary message to standard error (System.err) which
+ * summarizes what was found in the specification, how many states were
+ * produced, how many conflicts were found, etc. A detailed timing
+ * summary is also produced if it was requested by the user.
+ * @param output_produced did the system get far enough to generate code.
+ */
+ protected static void emit_summary(boolean output_produced)
+ {
+ final_time = System.currentTimeMillis();
+
+ if (no_summary) return;
+
+ System.err.println("------- " + version.title_str +
+ " Parser Generation Summary -------");
+
+ /* error and warning count */
+ System.err.println(" " + lexer.error_count + " error" +
+ plural(lexer.error_count) + " and " + lexer.warning_count +
+ " warning" + plural(lexer.warning_count));
+
+ /* basic stats */
+ System.err.print(" " + terminal.number() + " terminal" +
+ plural(terminal.number()) + ", ");
+ System.err.print(non_terminal.number() + " non-terminal" +
+ plural(non_terminal.number()) + ", and ");
+ System.err.println(production.number() + " production" +
+ plural(production.number()) + " declared, ");
+ System.err.println(" producing " + lalr_state.number() +
+ " unique parse states.");
+
+ /* unused symbols */
+ System.err.println(" " + emit.unused_term + " terminal" +
+ plural(emit.unused_term) + " declared but not used.");
+ System.err.println(" " + emit.unused_non_term + " non-terminal" +
+ plural(emit.unused_term) + " declared but not used.");
+
+ /* productions that didn't reduce */
+ System.err.println(" " + emit.not_reduced + " production" +
+ plural(emit.not_reduced) + " never reduced.");
+
+ /* conflicts */
+ System.err.println(" " + emit.num_conflicts + " conflict" +
+ plural(emit.num_conflicts) + " detected" +
+ " (" + expect_conflicts + " expected).");
+
+ /* code location */
+ if (output_produced)
+ System.err.println(" Code written to \"" + emit.parser_class_name +
+ ".java\", and \"" + emit.symbol_const_class_name + ".java\".");
+ else
+ System.err.println(" No code produced.");
+
+ if (opt_show_timing) show_times();
+
+ System.err.println(
+ "---------------------------------------------------- (" +
+ version.version_str + ")");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce the optional timing summary as part of an overall summary. */
+ protected static void show_times()
+ {
+ long total_time = final_time - start_time;
+
+ System.err.println(". . . . . . . . . . . . . . . . . . . . . . . . . ");
+ System.err.println(" Timing Summary");
+ System.err.println(" Total time "
+ + timestr(final_time-start_time, total_time));
+ System.err.println(" Startup "
+ + timestr(prelim_end-start_time, total_time));
+ System.err.println(" Parse "
+ + timestr(parse_end-prelim_end, total_time) );
+ if (check_end != 0)
+ System.err.println(" Checking "
+ + timestr(check_end-parse_end, total_time));
+ if (check_end != 0 && build_end != 0)
+ System.err.println(" Parser Build "
+ + timestr(build_end-check_end, total_time));
+ if (nullability_end != 0 && check_end != 0)
+ System.err.println(" Nullability "
+ + timestr(nullability_end-check_end, total_time));
+ if (first_end != 0 && nullability_end != 0)
+ System.err.println(" First sets "
+ + timestr(first_end-nullability_end, total_time));
+ if (machine_end != 0 && first_end != 0)
+ System.err.println(" State build "
+ + timestr(machine_end-first_end, total_time));
+ if (table_end != 0 && machine_end != 0)
+ System.err.println(" Table build "
+ + timestr(table_end-machine_end, total_time));
+ if (reduce_check_end != 0 && table_end != 0)
+ System.err.println(" Checking "
+ + timestr(reduce_check_end-table_end, total_time));
+ if (emit_end != 0 && build_end != 0)
+ System.err.println(" Code Output "
+ + timestr(emit_end-build_end, total_time));
+ if (emit.symbols_time != 0)
+ System.err.println(" Symbols "
+ + timestr(emit.symbols_time, total_time));
+ if (emit.parser_time != 0)
+ System.err.println(" Parser class "
+ + timestr(emit.parser_time, total_time));
+ if (emit.action_code_time != 0)
+ System.err.println(" Actions "
+ + timestr(emit.action_code_time, total_time));
+ if (emit.production_table_time != 0)
+ System.err.println(" Prod table "
+ + timestr(emit.production_table_time, total_time));
+ if (emit.action_table_time != 0)
+ System.err.println(" Action tab "
+ + timestr(emit.action_table_time, total_time));
+ if (emit.goto_table_time != 0)
+ System.err.println(" Reduce tab "
+ + timestr(emit.goto_table_time, total_time));
+
+ System.err.println(" Dump Output "
+ + timestr(dump_end-emit_end, total_time));
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Helper routine to format a decimal based display of seconds and
+ * percentage of total time given counts of milliseconds. Note: this
+ * is broken for use with some instances of negative time (since we don't
+ * use any negative time here, we let if be for now).
+ * @param time_val the value being formatted (in ms).
+ * @param total_time total time percentages are calculated against (in ms).
+ */
+ protected static String timestr(long time_val, long total_time)
+ {
+ boolean neg;
+ long ms = 0;
+ long sec = 0;
+ long percent10;
+ String pad;
+
+ /* work with positives only */
+ neg = time_val < 0;
+ if (neg) time_val = -time_val;
+
+ /* pull out seconds and ms */
+ ms = time_val % 1000;
+ sec = time_val / 1000;
+
+ /* construct a pad to blank fill seconds out to 4 places */
+ if (sec < 10)
+ pad = " ";
+ else if (sec < 100)
+ pad = " ";
+ else if (sec < 1000)
+ pad = " ";
+ else
+ pad = "";
+
+ /* calculate 10 times the percentage of total */
+ percent10 = (time_val*1000)/total_time;
+
+ /* build and return the output string */
+ return (neg ? "-" : "") + pad + sec + "." +
+ ((ms%1000)/100) + ((ms%100)/10) + (ms%10) + "sec" +
+ " (" + percent10/10 + "." + percent10%10 + "%)";
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a human readable dump of the grammar. */
+ public static void dump_grammar() throws internal_error
+ {
+ System.err.println("===== Terminals =====");
+ for (int tidx=0, cnt=0; tidx < terminal.number(); tidx++, cnt++)
+ {
+ System.err.print("["+tidx+"]"+terminal.find(tidx).name()+" ");
+ if ((cnt+1) % 5 == 0) System.err.println();
+ }
+ System.err.println();
+ System.err.println();
+
+ System.err.println("===== Non terminals =====");
+ for (int nidx=0, cnt=0; nidx < non_terminal.number(); nidx++, cnt++)
+ {
+ System.err.print("["+nidx+"]"+non_terminal.find(nidx).name()+" ");
+ if ((cnt+1) % 5 == 0) System.err.println();
+ }
+ System.err.println();
+ System.err.println();
+
+
+ System.err.println("===== Productions =====");
+ for (int pidx=0; pidx < production.number(); pidx++)
+ {
+ production prod = production.find(pidx);
+ System.err.print("["+pidx+"] "+prod.lhs().the_symbol().name() + " ::= ");
+ for (int i=0; i<prod.rhs_length(); i++)
+ if (prod.rhs(i).is_action())
+ System.err.print("{action} ");
+ else
+ System.err.print(
+ ((symbol_part)prod.rhs(i)).the_symbol().name() + " ");
+ System.err.println();
+ }
+ System.err.println();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a (semi-) human readable dump of the complete viable prefix
+ * recognition state machine.
+ */
+ public static void dump_machine()
+ {
+ lalr_state ordered[] = new lalr_state[lalr_state.number()];
+
+ /* put the states in sorted order for a nicer display */
+ for (Enumeration s = lalr_state.all(); s.hasMoreElements(); )
+ {
+ lalr_state st = (lalr_state)s.nextElement();
+ ordered[st.index()] = st;
+ }
+
+ System.err.println("===== Viable Prefix Recognizer =====");
+ for (int i = 0; i<lalr_state.number(); i++)
+ {
+ if (ordered[i] == start_state) System.err.print("START ");
+ System.err.println(ordered[i]);
+ System.err.println("-------------------");
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a (semi-) human readable dumps of the parse tables */
+ public static void dump_tables()
+ {
+ System.err.println(action_table);
+ System.err.println(reduce_table);
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
diff --git a/src/syntaxParser/java_cup/SAVE/Main.java b/src/syntaxParser/java_cup/SAVE/Main.java
new file mode 100644
index 0000000..50811b5
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/Main.java
@@ -0,0 +1,854 @@
+
+package java_cup;
+
+import java.util.Enumeration;
+import java.io.*;
+
+/** This class serves as the main driver for the JavaCup system.
+ * It accepts user options and coordinates overall control flow.
+ * The main flow of control includes the following activities:
+ * <ul>
+ * <li> Parse user supplied arguments and options.
+ * <li> Open output files.
+ * <li> Parse the specification from standard input.
+ * <li> Check for unused terminals, non-terminals, and productions.
+ * <li> Build the state machine, tables, etc.
+ * <li> Output the generated code.
+ * <li> Close output files.
+ * <li> Print a summary if requested.
+ * </ul>
+ *
+ * Options to the main program include: <dl>
+ * <dt> -package name
+ * <dd> specify package generated classes go in [default none]
+ * <dt> -parser name
+ * <dd> specify parser class name [default "parser"]
+ * <dt> -symbols name
+ * <dd> specify name for symbol constant class [default "sym"]
+ * <dt> -interface
+ * <dd> emit symbol constant <i>interface</i>, rather than class
+ * <dt> -nonterms
+ * <dd> put non terminals in symbol constant class
+ * <dt> -expect #
+ * <dd> number of conflicts expected/allowed [default 0]
+ * <dt> -compact_red
+ * <dd> compact tables by defaulting to most frequent reduce
+ * <dt> -nowarn
+ * <dd> don't warn about useless productions, etc.
+ * <dt> -nosummary
+ * <dd> don't print the usual summary of parse states, etc.
+ * <dt> -progress
+ * <dd> print messages to indicate progress of the system
+ * <dt> -time
+ * <dd> print time usage summary
+ * <dt> -dump_grammar
+ * <dd> produce a dump of the symbols and grammar
+ * <dt> -dump_states
+ * <dd> produce a dump of parse state machine
+ * <dt> -dump_tables
+ * <dd> produce a dump of the parse tables
+ * <dt> -dump
+ * <dd> produce a dump of all of the above
+ * <dt> -debug
+ * <dd> turn on debugging messages within JavaCup
+ * <dt> -nopositions
+ * <dd> don't generate the positions code
+ * <dt> -noscanner
+ * <dd> don't refer to java_cup.runtime.Scanner in the parser
+ * (for compatibility with old runtimes)
+ * <dt> -version
+ * <dd> print version information for JavaCUP and halt.
+ * </dl>
+ *
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+
+public class Main {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+ /** Only constructor is private, so we do not allocate any instances of this
+ class. */
+ private Main() { }
+
+ /*-------------------------*/
+ /* Options set by the user */
+ /*-------------------------*/
+ /** User option -- do we print progress messages. */
+ protected static boolean print_progress = true;
+ /** User option -- do we produce a dump of the state machine */
+ protected static boolean opt_dump_states = false;
+ /** User option -- do we produce a dump of the parse tables */
+ protected static boolean opt_dump_tables = false;
+ /** User option -- do we produce a dump of the grammar */
+ protected static boolean opt_dump_grammar = false;
+ /** User option -- do we show timing information as a part of the summary */
+ protected static boolean opt_show_timing = false;
+ /** User option -- do we run produce extra debugging messages */
+ protected static boolean opt_do_debug = false;
+ /** User option -- do we compact tables by making most common reduce the
+ default action */
+ protected static boolean opt_compact_red = false;
+ /** User option -- should we include non terminal symbol numbers in the
+ symbol constant class. */
+ protected static boolean include_non_terms = false;
+ /** User option -- do not print a summary. */
+ protected static boolean no_summary = false;
+ /** User option -- number of conflicts to expect */
+ protected static int expect_conflicts = 0;
+
+ /* frankf added this 6/18/96 */
+ /** User option -- should generator generate code for left/right values? */
+ protected static boolean lr_values = true;
+
+ /** User option -- should symbols be put in a class or an interface? [CSA]*/
+ protected static boolean sym_interface = false;
+
+ /** User option -- should generator suppress references to
+ * java_cup.runtime.Scanner for compatibility with old runtimes? */
+ protected static boolean suppress_scanner = false;
+
+ /*----------------------------------------------------------------------*/
+ /* Timing data (not all of these time intervals are mutually exclusive) */
+ /*----------------------------------------------------------------------*/
+ /** Timing data -- when did we start */
+ protected static long start_time = 0;
+ /** Timing data -- when did we end preliminaries */
+ protected static long prelim_end = 0;
+ /** Timing data -- when did we end parsing */
+ protected static long parse_end = 0;
+ /** Timing data -- when did we end checking */
+ protected static long check_end = 0;
+ /** Timing data -- when did we end dumping */
+ protected static long dump_end = 0;
+ /** Timing data -- when did we end state and table building */
+ protected static long build_end = 0;
+ /** Timing data -- when did we end nullability calculation */
+ protected static long nullability_end = 0;
+ /** Timing data -- when did we end first set calculation */
+ protected static long first_end = 0;
+ /** Timing data -- when did we end state machine construction */
+ protected static long machine_end = 0;
+ /** Timing data -- when did we end table construction */
+ protected static long table_end = 0;
+ /** Timing data -- when did we end checking for non-reduced productions */
+ protected static long reduce_check_end = 0;
+ /** Timing data -- when did we finish emitting code */
+ protected static long emit_end = 0;
+ /** Timing data -- when were we completely done */
+ protected static long final_time = 0;
+
+ /* Additional timing information is also collected in emit */
+
+ /*-----------------------------------------------------------*/
+ /*--- Main Program ------------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The main driver for the system.
+ * @param argv an array of strings containing command line arguments.
+ */
+ public static void main(String argv[])
+ throws internal_error, java.io.IOException, java.lang.Exception
+ {
+ boolean did_output = false;
+
+ start_time = System.currentTimeMillis();
+
+ /* process user options and arguments */
+ parse_args(argv);
+
+ /* frankf 6/18/96
+ hackish, yes, but works */
+ emit.set_lr_values(lr_values);
+ /* open output files */
+ if (print_progress) System.err.println("Opening files...");
+ /* use a buffered version of standard input */
+ input_file = new BufferedInputStream(System.in);
+
+ prelim_end = System.currentTimeMillis();
+
+ /* parse spec into internal data structures */
+ if (print_progress)
+ System.err.println("Parsing specification from standard input...");
+ parse_grammar_spec();
+
+ parse_end = System.currentTimeMillis();
+
+ /* don't proceed unless we are error free */
+ if (lexer.error_count == 0)
+ {
+ /* check for unused bits */
+ if (print_progress) System.err.println("Checking specification...");
+ check_unused();
+
+ check_end = System.currentTimeMillis();
+
+ /* build the state machine and parse tables */
+ if (print_progress) System.err.println("Building parse tables...");
+ build_parser();
+
+ build_end = System.currentTimeMillis();
+
+ /* output the generated code, if # of conflicts permits */
+ if (lexer.error_count != 0) {
+ // conflicts! don't emit code, don't dump tables.
+ opt_dump_tables = false;
+ } else { // everything's okay, emit parser.
+ if (print_progress) System.err.println("Writing parser...");
+ open_files();
+ emit_parser();
+ did_output = true;
+ }
+ }
+ /* fix up the times to make the summary easier */
+ emit_end = System.currentTimeMillis();
+
+ /* do requested dumps */
+ if (opt_dump_grammar) dump_grammar();
+ if (opt_dump_states) dump_machine();
+ if (opt_dump_tables) dump_tables();
+
+ dump_end = System.currentTimeMillis();
+
+ /* close input/output files */
+ if (print_progress) System.err.println("Closing files...");
+ close_files();
+
+ /* produce a summary if desired */
+ if (!no_summary) emit_summary(did_output);
+
+ /* If there were errors during the run,
+ * exit with non-zero status (makefile-friendliness). --CSA */
+ if (lexer.error_count != 0)
+ System.exit(100);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Print a "usage message" that described possible command line options,
+ * then exit.
+ * @param message a specific error message to preface the usage message by.
+ */
+ protected static void usage(String message)
+ {
+ System.err.println();
+ System.err.println(message);
+ System.err.println();
+ System.err.println(
+"Usage: " + version.program_name + " [options] [filename]\n" +
+" and expects a specification file on standard input if no filename is given.\n" +
+" Legal options include:\n" +
+" -package name specify package generated classes go in [default none]\n" +
+" -parser name specify parser class name [default \"parser\"]\n" +
+" -symbols name specify name for symbol constant class [default \"sym\"]\n"+
+" -interface put symbols in an interface, rather than a class\n" +
+" -nonterms put non terminals in symbol constant class\n" +
+" -expect # number of conflicts expected/allowed [default 0]\n" +
+" -compact_red compact tables by defaulting to most frequent reduce\n" +
+" -nowarn don't warn about useless productions, etc.\n" +
+" -nosummary don't print the usual summary of parse states, etc.\n" +
+" -nopositions don't propagate the left and right token position values\n" +
+" -noscanner don't refer to java_cup.runtime.Scanner\n" +
+" -progress print messages to indicate progress of the system\n" +
+" -time print time usage summary\n" +
+" -dump_grammar produce a human readable dump of the symbols and grammar\n"+
+" -dump_states produce a dump of parse state machine\n"+
+" -dump_tables produce a dump of the parse tables\n"+
+" -dump produce a dump of all of the above\n"+
+" -version print the version information for CUP and exit\n"
+ );
+ System.exit(1);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Parse command line options and arguments to set various user-option
+ * flags and variables.
+ * @param argv the command line arguments to be parsed.
+ */
+ protected static void parse_args(String argv[])
+ {
+ int len = argv.length;
+ int i;
+
+ /* parse the options */
+ for (i=0; i<len; i++)
+ {
+ /* try to get the various options */
+ if (argv[i].equals("-package"))
+ {
+ /* must have an arg */
+ if (++i >= len || argv[i].startsWith("-") ||
+ argv[i].endsWith(".cup"))
+ usage("-package must have a name argument");
+
+ /* record the name */
+ emit.package_name = argv[i];
+ }
+ else if (argv[i].equals("-parser"))
+ {
+ /* must have an arg */
+ if (++i >= len || argv[i].startsWith("-") ||
+ argv[i].endsWith(".cup"))
+ usage("-parser must have a name argument");
+
+ /* record the name */
+ emit.parser_class_name = argv[i];
+ }
+ else if (argv[i].equals("-symbols"))
+ {
+ /* must have an arg */
+ if (++i >= len || argv[i].startsWith("-") ||
+ argv[i].endsWith(".cup"))
+ usage("-symbols must have a name argument");
+
+ /* record the name */
+ emit.symbol_const_class_name = argv[i];
+ }
+ else if (argv[i].equals("-nonterms"))
+ {
+ include_non_terms = true;
+ }
+ else if (argv[i].equals("-expect"))
+ {
+ /* must have an arg */
+ if (++i >= len || argv[i].startsWith("-") ||
+ argv[i].endsWith(".cup"))
+ usage("-expect must have a name argument");
+
+ /* record the number */
+ try {
+ expect_conflicts = Integer.parseInt(argv[i]);
+ } catch (NumberFormatException e) {
+ usage("-expect must be followed by a decimal integer");
+ }
+ }
+ else if (argv[i].equals("-compact_red")) opt_compact_red = true;
+ else if (argv[i].equals("-nosummary")) no_summary = true;
+ else if (argv[i].equals("-nowarn")) emit.nowarn = true;
+ else if (argv[i].equals("-dump_states")) opt_dump_states = true;
+ else if (argv[i].equals("-dump_tables")) opt_dump_tables = true;
+ else if (argv[i].equals("-progress")) print_progress = true;
+ else if (argv[i].equals("-dump_grammar")) opt_dump_grammar = true;
+ else if (argv[i].equals("-dump"))
+ opt_dump_states = opt_dump_tables = opt_dump_grammar = true;
+ else if (argv[i].equals("-time")) opt_show_timing = true;
+ else if (argv[i].equals("-debug")) opt_do_debug = true;
+ /* frankf 6/18/96 */
+ else if (argv[i].equals("-nopositions")) lr_values = false;
+ /* CSA 12/21/97 */
+ else if (argv[i].equals("-interface")) sym_interface = true;
+ /* CSA 23-Jul-1999 */
+ else if (argv[i].equals("-noscanner")) suppress_scanner = true;
+ /* CSA 23-Jul-1999 */
+ else if (argv[i].equals("-version")) {
+ System.out.println(version.title_str);
+ System.exit(1);
+ }
+ /* CSA 24-Jul-1999; suggestion by Jean Vaucher */
+ else if (!argv[i].startsWith("-") && i==len-1) {
+ /* use input from file. */
+ try {
+ System.setIn(new FileInputStream(argv[i]));
+ } catch (java.io.FileNotFoundException e) {
+ usage("Unable to open \"" + argv[i] +"\" for input");
+ }
+ }
+ else
+ {
+ usage("Unrecognized option \"" + argv[i] + "\"");
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /*-------*/
+ /* Files */
+ /*-------*/
+
+ /** Input file. This is a buffered version of System.in. */
+ protected static BufferedInputStream input_file;
+
+ /** Output file for the parser class. */
+ protected static PrintWriter parser_class_file;
+
+ /** Output file for the symbol constant class. */
+ protected static PrintWriter symbol_class_file;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Open various files used by the system. */
+ protected static void open_files()
+ {
+ File fil;
+ String out_name;
+
+ /* open each of the output files */
+
+ /* parser class */
+ out_name = emit.parser_class_name + ".java";
+ fil = new File(out_name);
+ try {
+ parser_class_file = new PrintWriter(
+ new BufferedOutputStream(new FileOutputStream(fil), 4096));
+ } catch(Exception e) {
+ System.err.println("Can't open \"" + out_name + "\" for output");
+ System.exit(3);
+ }
+
+ /* symbol constants class */
+ out_name = emit.symbol_const_class_name + ".java";
+ fil = new File(out_name);
+ try {
+ symbol_class_file = new PrintWriter(
+ new BufferedOutputStream(new FileOutputStream(fil), 4096));
+ } catch(Exception e) {
+ System.err.println("Can't open \"" + out_name + "\" for output");
+ System.exit(4);
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Close various files used by the system. */
+ protected static void close_files() throws java.io.IOException
+ {
+ if (input_file != null) input_file.close();
+ if (parser_class_file != null) parser_class_file.close();
+ if (symbol_class_file != null) symbol_class_file.close();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Parse the grammar specification from standard input. This produces
+ * sets of terminal, non-terminals, and productions which can be accessed
+ * via static variables of the respective classes, as well as the setting
+ * of various variables (mostly in the emit class) for small user supplied
+ * items such as the code to scan with.
+ */
+ protected static void parse_grammar_spec() throws java.lang.Exception
+ {
+ parser parser_obj;
+
+ /* create a parser and parse with it */
+ parser_obj = new parser();
+ try {
+ if (opt_do_debug)
+ parser_obj.debug_parse();
+ else
+ parser_obj.parse();
+ } catch (Exception e)
+ {
+ /* something threw an exception. catch it and emit a message so we
+ have a line number to work with, then re-throw it */
+ lexer.emit_error("Internal error: Unexpected exception");
+ throw e;
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Check for unused symbols. Unreduced productions get checked when
+ * tables are created.
+ */
+ protected static void check_unused()
+ {
+ terminal term;
+ non_terminal nt;
+
+ /* check for unused terminals */
+ for (Enumeration t = terminal.all(); t.hasMoreElements(); )
+ {
+ term = (terminal)t.nextElement();
+
+ /* don't issue a message for EOF */
+ if (term == terminal.EOF) continue;
+
+ /* or error */
+ if (term == terminal.error) continue;
+
+ /* is this one unused */
+ if (term.use_count() == 0)
+ {
+ /* count it and warn if we are doing warnings */
+ emit.unused_term++;
+ if (!emit.nowarn)
+ {
+ System.err.println("Warning: Terminal \"" + term.name() +
+ "\" was declared but never used");
+ lexer.warning_count++;
+ }
+ }
+ }
+
+ /* check for unused non terminals */
+ for (Enumeration n = non_terminal.all(); n.hasMoreElements(); )
+ {
+ nt = (non_terminal)n.nextElement();
+
+ /* is this one unused */
+ if (nt.use_count() == 0)
+ {
+ /* count and warn if we are doing warnings */
+ emit.unused_term++;
+ if (!emit.nowarn)
+ {
+ System.err.println("Warning: Non terminal \"" + nt.name() +
+ "\" was declared but never used");
+ lexer.warning_count++;
+ }
+ }
+ }
+
+ }
+
+ /* . . . . . . . . . . . . . . . . . . . . . . . . .*/
+ /* . . Internal Results of Generating the Parser . .*/
+ /* . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Start state in the overall state machine. */
+ protected static lalr_state start_state;
+
+ /** Resulting parse action table. */
+ protected static parse_action_table action_table;
+
+ /** Resulting reduce-goto table. */
+ protected static parse_reduce_table reduce_table;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Build the (internal) parser from the previously parsed specification.
+ * This includes:<ul>
+ * <li> Computing nullability of non-terminals.
+ * <li> Computing first sets of non-terminals and productions.
+ * <li> Building the viable prefix recognizer machine.
+ * <li> Filling in the (internal) parse tables.
+ * <li> Checking for unreduced productions.
+ * </ul>
+ */
+ protected static void build_parser() throws internal_error
+ {
+ /* compute nullability of all non terminals */
+ if (opt_do_debug || print_progress)
+ System.err.println(" Computing non-terminal nullability...");
+ non_terminal.compute_nullability();
+
+ nullability_end = System.currentTimeMillis();
+
+ /* compute first sets of all non terminals */
+ if (opt_do_debug || print_progress)
+ System.err.println(" Computing first sets...");
+ non_terminal.compute_first_sets();
+
+ first_end = System.currentTimeMillis();
+
+ /* build the LR viable prefix recognition machine */
+ if (opt_do_debug || print_progress)
+ System.err.println(" Building state machine...");
+ start_state = lalr_state.build_machine(emit.start_production);
+
+ machine_end = System.currentTimeMillis();
+
+ /* build the LR parser action and reduce-goto tables */
+ if (opt_do_debug || print_progress)
+ System.err.println(" Filling in tables...");
+ action_table = new parse_action_table();
+ reduce_table = new parse_reduce_table();
+ for (Enumeration st = lalr_state.all(); st.hasMoreElements(); )
+ {
+ lalr_state lst = (lalr_state)st.nextElement();
+ lst.build_table_entries(
+ action_table, reduce_table);
+ }
+
+ table_end = System.currentTimeMillis();
+
+ /* check and warn for non-reduced productions */
+ if (opt_do_debug || print_progress)
+ System.err.println(" Checking for non-reduced productions...");
+ action_table.check_reductions();
+
+ reduce_check_end = System.currentTimeMillis();
+
+ /* if we have more conflicts than we expected issue a message and die */
+ if (emit.num_conflicts > expect_conflicts)
+ {
+ System.err.println("*** More conflicts encountered than expected " +
+ "-- parser generation aborted");
+ lexer.error_count++; // indicate the problem.
+ // we'll die on return, after clean up.
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Call the emit routines necessary to write out the generated parser. */
+ protected static void emit_parser() throws internal_error
+ {
+ emit.symbols(symbol_class_file, include_non_terms, sym_interface);
+ emit.parser(parser_class_file, action_table, reduce_table,
+ start_state.index(), emit.start_production, opt_compact_red,
+ suppress_scanner);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Helper routine to optionally return a plural or non-plural ending.
+ * @param val the numerical value determining plurality.
+ */
+ protected static String plural(int val)
+ {
+ if (val == 1)
+ return "";
+ else
+ return "s";
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit a long summary message to standard error (System.err) which
+ * summarizes what was found in the specification, how many states were
+ * produced, how many conflicts were found, etc. A detailed timing
+ * summary is also produced if it was requested by the user.
+ * @param output_produced did the system get far enough to generate code.
+ */
+ protected static void emit_summary(boolean output_produced)
+ {
+ final_time = System.currentTimeMillis();
+
+ if (no_summary) return;
+
+ System.err.println("------- " + version.title_str +
+ " Parser Generation Summary -------");
+
+ /* error and warning count */
+ System.err.println(" " + lexer.error_count + " error" +
+ plural(lexer.error_count) + " and " + lexer.warning_count +
+ " warning" + plural(lexer.warning_count));
+
+ /* basic stats */
+ System.err.print(" " + terminal.number() + " terminal" +
+ plural(terminal.number()) + ", ");
+ System.err.print(non_terminal.number() + " non-terminal" +
+ plural(non_terminal.number()) + ", and ");
+ System.err.println(production.number() + " production" +
+ plural(production.number()) + " declared, ");
+ System.err.println(" producing " + lalr_state.number() +
+ " unique parse states.");
+
+ /* unused symbols */
+ System.err.println(" " + emit.unused_term + " terminal" +
+ plural(emit.unused_term) + " declared but not used.");
+ System.err.println(" " + emit.unused_non_term + " non-terminal" +
+ plural(emit.unused_term) + " declared but not used.");
+
+ /* productions that didn't reduce */
+ System.err.println(" " + emit.not_reduced + " production" +
+ plural(emit.not_reduced) + " never reduced.");
+
+ /* conflicts */
+ System.err.println(" " + emit.num_conflicts + " conflict" +
+ plural(emit.num_conflicts) + " detected" +
+ " (" + expect_conflicts + " expected).");
+
+ /* code location */
+ if (output_produced)
+ System.err.println(" Code written to \"" + emit.parser_class_name +
+ ".java\", and \"" + emit.symbol_const_class_name + ".java\".");
+ else
+ System.err.println(" No code produced.");
+
+ if (opt_show_timing) show_times();
+
+ System.err.println(
+ "---------------------------------------------------- (" +
+ version.version_str + ")");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce the optional timing summary as part of an overall summary. */
+ protected static void show_times()
+ {
+ long total_time = final_time - start_time;
+
+ System.err.println(". . . . . . . . . . . . . . . . . . . . . . . . . ");
+ System.err.println(" Timing Summary");
+ System.err.println(" Total time "
+ + timestr(final_time-start_time, total_time));
+ System.err.println(" Startup "
+ + timestr(prelim_end-start_time, total_time));
+ System.err.println(" Parse "
+ + timestr(parse_end-prelim_end, total_time) );
+ if (check_end != 0)
+ System.err.println(" Checking "
+ + timestr(check_end-parse_end, total_time));
+ if (check_end != 0 && build_end != 0)
+ System.err.println(" Parser Build "
+ + timestr(build_end-check_end, total_time));
+ if (nullability_end != 0 && check_end != 0)
+ System.err.println(" Nullability "
+ + timestr(nullability_end-check_end, total_time));
+ if (first_end != 0 && nullability_end != 0)
+ System.err.println(" First sets "
+ + timestr(first_end-nullability_end, total_time));
+ if (machine_end != 0 && first_end != 0)
+ System.err.println(" State build "
+ + timestr(machine_end-first_end, total_time));
+ if (table_end != 0 && machine_end != 0)
+ System.err.println(" Table build "
+ + timestr(table_end-machine_end, total_time));
+ if (reduce_check_end != 0 && table_end != 0)
+ System.err.println(" Checking "
+ + timestr(reduce_check_end-table_end, total_time));
+ if (emit_end != 0 && build_end != 0)
+ System.err.println(" Code Output "
+ + timestr(emit_end-build_end, total_time));
+ if (emit.symbols_time != 0)
+ System.err.println(" Symbols "
+ + timestr(emit.symbols_time, total_time));
+ if (emit.parser_time != 0)
+ System.err.println(" Parser class "
+ + timestr(emit.parser_time, total_time));
+ if (emit.action_code_time != 0)
+ System.err.println(" Actions "
+ + timestr(emit.action_code_time, total_time));
+ if (emit.production_table_time != 0)
+ System.err.println(" Prod table "
+ + timestr(emit.production_table_time, total_time));
+ if (emit.action_table_time != 0)
+ System.err.println(" Action tab "
+ + timestr(emit.action_table_time, total_time));
+ if (emit.goto_table_time != 0)
+ System.err.println(" Reduce tab "
+ + timestr(emit.goto_table_time, total_time));
+
+ System.err.println(" Dump Output "
+ + timestr(dump_end-emit_end, total_time));
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Helper routine to format a decimal based display of seconds and
+ * percentage of total time given counts of milliseconds. Note: this
+ * is broken for use with some instances of negative time (since we don't
+ * use any negative time here, we let if be for now).
+ * @param time_val the value being formatted (in ms).
+ * @param total_time total time percentages are calculated against (in ms).
+ */
+ protected static String timestr(long time_val, long total_time)
+ {
+ boolean neg;
+ long ms = 0;
+ long sec = 0;
+ long percent10;
+ String pad;
+
+ /* work with positives only */
+ neg = time_val < 0;
+ if (neg) time_val = -time_val;
+
+ /* pull out seconds and ms */
+ ms = time_val % 1000;
+ sec = time_val / 1000;
+
+ /* construct a pad to blank fill seconds out to 4 places */
+ if (sec < 10)
+ pad = " ";
+ else if (sec < 100)
+ pad = " ";
+ else if (sec < 1000)
+ pad = " ";
+ else
+ pad = "";
+
+ /* calculate 10 times the percentage of total */
+ percent10 = (time_val*1000)/total_time;
+
+ /* build and return the output string */
+ return (neg ? "-" : "") + pad + sec + "." +
+ ((ms%1000)/100) + ((ms%100)/10) + (ms%10) + "sec" +
+ " (" + percent10/10 + "." + percent10%10 + "%)";
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a human readable dump of the grammar. */
+ public static void dump_grammar() throws internal_error
+ {
+ System.err.println("===== Terminals =====");
+ for (int tidx=0, cnt=0; tidx < terminal.number(); tidx++, cnt++)
+ {
+ System.err.print("["+tidx+"]"+terminal.find(tidx).name()+" ");
+ if ((cnt+1) % 5 == 0) System.err.println();
+ }
+ System.err.println();
+ System.err.println();
+
+ System.err.println("===== Non terminals =====");
+ for (int nidx=0, cnt=0; nidx < non_terminal.number(); nidx++, cnt++)
+ {
+ System.err.print("["+nidx+"]"+non_terminal.find(nidx).name()+" ");
+ if ((cnt+1) % 5 == 0) System.err.println();
+ }
+ System.err.println();
+ System.err.println();
+
+
+ System.err.println("===== Productions =====");
+ for (int pidx=0; pidx < production.number(); pidx++)
+ {
+ production prod = production.find(pidx);
+ System.err.print("["+pidx+"] "+prod.lhs().the_symbol().name() + " ::= ");
+ for (int i=0; i<prod.rhs_length(); i++)
+ if (prod.rhs(i).is_action())
+ System.err.print("{action} ");
+ else
+ System.err.print(
+ ((symbol_part)prod.rhs(i)).the_symbol().name() + " ");
+ System.err.println();
+ }
+ System.err.println();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a (semi-) human readable dump of the complete viable prefix
+ * recognition state machine.
+ */
+ public static void dump_machine()
+ {
+ lalr_state ordered[] = new lalr_state[lalr_state.number()];
+
+ /* put the states in sorted order for a nicer display */
+ for (Enumeration s = lalr_state.all(); s.hasMoreElements(); )
+ {
+ lalr_state st = (lalr_state)s.nextElement();
+ ordered[st.index()] = st;
+ }
+
+ System.err.println("===== Viable Prefix Recognizer =====");
+ for (int i = 0; i<lalr_state.number(); i++)
+ {
+ if (ordered[i] == start_state) System.err.print("START ");
+ System.err.println(ordered[i]);
+ System.err.println("-------------------");
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a (semi-) human readable dumps of the parse tables */
+ public static void dump_tables()
+ {
+ System.err.println(action_table);
+ System.err.println(reduce_table);
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
diff --git a/src/syntaxParser/java_cup/SAVE/action_part.java b/src/syntaxParser/java_cup/SAVE/action_part.java
new file mode 100644
index 0000000..69e98f5
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/action_part.java
@@ -0,0 +1,93 @@
+
+package java_cup;
+
+/**
+ * This class represents a part of a production which contains an
+ * action. These are eventually eliminated from productions and converted
+ * to trailing actions by factoring out with a production that derives the
+ * empty string (and ends with this action).
+ *
+ * @see java_cup.production
+ * @version last update: 11/25/95
+ * @author Scott Hudson
+ */
+
+public class action_part extends production_part {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructors ------------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor.
+ * @param code_str string containing the actual user code.
+ */
+ public action_part(String code_str)
+ {
+ super(/* never have a label on code */null);
+ _code_string = code_str;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** String containing code for the action in question. */
+ protected String _code_string;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** String containing code for the action in question. */
+ public String code_string() {return _code_string;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Set the code string. */
+ public void set_code_string(String new_str) {_code_string = new_str;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Override to report this object as an action. */
+ public boolean is_action() { return true; }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison for properly typed object. */
+ public boolean equals(action_part other)
+ {
+ /* compare the strings */
+ return other != null && super.equals(other) &&
+ other.code_string().equals(code_string());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof action_part))
+ return false;
+ else
+ return equals((action_part)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a hash code. */
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ (code_string()==null ? 0 : code_string().hashCode());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ return super.toString() + "{" + code_string() + "}";
+ }
+
+ /*-----------------------------------------------------------*/
+}
diff --git a/src/syntaxParser/java_cup/SAVE/action_production.java b/src/syntaxParser/java_cup/SAVE/action_production.java
new file mode 100644
index 0000000..3c0845f
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/action_production.java
@@ -0,0 +1,39 @@
+
+package java_cup;
+
+/** A specialized version of a production used when we split an existing
+ * production in order to remove an embedded action. Here we keep a bit
+ * of extra bookkeeping so that we know where we came from.
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+
+public class action_production extends production {
+
+ /** Constructor.
+ * @param base the production we are being factored out of.
+ * @param lhs_sym the LHS symbol for this production.
+ * @param rhs_parts array of production parts for the RHS.
+ * @param rhs_len how much of the rhs_parts array is valid.
+ * @param action_str the trailing reduce action for this production.
+ */
+ public action_production(
+ production base,
+ non_terminal lhs_sym,
+ production_part rhs_parts[],
+ int rhs_len,
+ String action_str)
+ throws internal_error
+ {
+ super(lhs_sym, rhs_parts, rhs_len, action_str);
+ _base_production = base;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The production we were taken out of. */
+ protected production _base_production;
+
+ /** The production we were taken out of. */
+ public production base_production() {return _base_production;}
+}
diff --git a/src/syntaxParser/java_cup/SAVE/assoc.java b/src/syntaxParser/java_cup/SAVE/assoc.java
new file mode 100644
index 0000000..8d0b50e
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/assoc.java
@@ -0,0 +1,16 @@
+package java_cup;
+
+/* Defines integers that represent the associativity of terminals
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+
+public class assoc {
+
+ /* various associativities, no_prec being the default value */
+ public final static int left = 0;
+ public final static int right = 1;
+ public final static int nonassoc = 2;
+ public final static int no_prec = -1;
+
+} \ No newline at end of file
diff --git a/src/syntaxParser/java_cup/SAVE/emit.java b/src/syntaxParser/java_cup/SAVE/emit.java
new file mode 100644
index 0000000..9db9014
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/emit.java
@@ -0,0 +1,897 @@
+package java_cup;
+
+import java.io.PrintWriter;
+import java.util.Stack;
+import java.util.Enumeration;
+import java.util.Date;
+
+/**
+ * This class handles emitting generated code for the resulting parser.
+ * The various parse tables must be constructed, etc. before calling any
+ * routines in this class.<p>
+ *
+ * Three classes are produced by this code:
+ * <dl>
+ * <dt> symbol constant class
+ * <dd> this contains constant declarations for each terminal (and
+ * optionally each non-terminal).
+ * <dt> action class
+ * <dd> this non-public class contains code to invoke all the user actions
+ * that were embedded in the parser specification.
+ * <dt> parser class
+ * <dd> the specialized parser class consisting primarily of some user
+ * supplied general and initialization code, and the parse tables.
+ * </dl><p>
+ *
+ * Three parse tables are created as part of the parser class:
+ * <dl>
+ * <dt> production table
+ * <dd> lists the LHS non terminal number, and the length of the RHS of
+ * each production.
+ * <dt> action table
+ * <dd> for each state of the parse machine, gives the action to be taken
+ * (shift, reduce, or error) under each lookahead symbol.<br>
+ * <dt> reduce-goto table
+ * <dd> when a reduce on a given production is taken, the parse stack is
+ * popped back a number of elements corresponding to the RHS of the
+ * production. This reveals a prior state, which we transition out
+ * of under the LHS non terminal symbol for the production (as if we
+ * had seen the LHS symbol rather than all the symbols matching the
+ * RHS). This table is indexed by non terminal numbers and indicates
+ * how to make these transitions.
+ * </dl><p>
+ *
+ * In addition to the method interface, this class maintains a series of
+ * public global variables and flags indicating how misc. parts of the code
+ * and other output is to be produced, and counting things such as number of
+ * conflicts detected (see the source code and public variables below for
+ * more details).<p>
+ *
+ * This class is "static" (contains only static data and methods).<p>
+ *
+ * @see java_cup.main
+ * @version last update: 11/25/95
+ * @author Scott Hudson
+ */
+
+/* Major externally callable routines here include:
+ symbols - emit the symbol constant class
+ parser - emit the parser class
+
+ In addition the following major internal routines are provided:
+ emit_package - emit a package declaration
+ emit_action_code - emit the class containing the user's actions
+ emit_production_table - emit declaration and init for the production table
+ do_action_table - emit declaration and init for the action table
+ do_reduce_table - emit declaration and init for the reduce-goto table
+
+ Finally, this class uses a number of public instance variables to communicate
+ optional parameters and flags used to control how code is generated,
+ as well as to report counts of various things (such as number of conflicts
+ detected). These include:
+
+ prefix - a prefix string used to prefix names that would
+ otherwise "pollute" someone else's name space.
+ package_name - name of the package emitted code is placed in
+ (or null for an unnamed package.
+ symbol_const_class_name - name of the class containing symbol constants.
+ parser_class_name - name of the class for the resulting parser.
+ action_code - user supplied declarations and other code to be
+ placed in action class.
+ parser_code - user supplied declarations and other code to be
+ placed in parser class.
+ init_code - user supplied code to be executed as the parser
+ is being initialized.
+ scan_code - user supplied code to get the next Symbol.
+ start_production - the start production for the grammar.
+ import_list - list of imports for use with action class.
+ num_conflicts - number of conflicts detected.
+ nowarn - true if we are not to issue warning messages.
+ not_reduced - count of number of productions that never reduce.
+ unused_term - count of unused terminal symbols.
+ unused_non_term - count of unused non terminal symbols.
+ *_time - a series of symbols indicating how long various
+ sub-parts of code generation took (used to produce
+ optional time reports in main).
+*/
+
+public class emit {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Only constructor is private so no instances can be created. */
+ private emit() { }
+
+ /*-----------------------------------------------------------*/
+ /*--- Static (Class) Variables ------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The prefix placed on names that pollute someone else's name space. */
+ public static String prefix = "CUP$";
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Package that the resulting code goes into (null is used for unnamed). */
+ public static String package_name = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Name of the generated class for symbol constants. */
+ public static String symbol_const_class_name = "sym";
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Name of the generated parser class. */
+ public static String parser_class_name = "parser";
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** User declarations for direct inclusion in user action class. */
+ public static String action_code = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** User declarations for direct inclusion in parser class. */
+ public static String parser_code = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** User code for user_init() which is called during parser initialization. */
+ public static String init_code = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** User code for scan() which is called to get the next Symbol. */
+ public static String scan_code = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The start production of the grammar. */
+ public static production start_production = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** List of imports (Strings containing class names) to go with actions. */
+ public static Stack import_list = new Stack();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Number of conflict found while building tables. */
+ public static int num_conflicts = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Do we skip warnings? */
+ public static boolean nowarn = false;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of the number on non-reduced productions found. */
+ public static int not_reduced = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of unused terminals. */
+ public static int unused_term = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of unused non terminals. */
+ public static int unused_non_term = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /* Timing values used to produce timing report in main.*/
+
+ /** Time to produce symbol constant class. */
+ public static long symbols_time = 0;
+
+ /** Time to produce parser class. */
+ public static long parser_time = 0;
+
+ /** Time to produce action code class. */
+ public static long action_code_time = 0;
+
+ /** Time to produce the production table. */
+ public static long production_table_time = 0;
+
+ /** Time to produce the action table. */
+ public static long action_table_time = 0;
+
+ /** Time to produce the reduce-goto table. */
+ public static long goto_table_time = 0;
+
+ /* frankf 6/18/96 */
+ protected static boolean _lr_values;
+
+ /** whether or not to emit code for left and right values */
+ public static boolean lr_values() {return _lr_values;}
+ protected static void set_lr_values(boolean b) { _lr_values = b;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Build a string with the standard prefix.
+ * @param str string to prefix.
+ */
+ protected static String pre(String str) {
+ return prefix + parser_class_name + "$" + str;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit a package spec if the user wants one.
+ * @param out stream to produce output on.
+ */
+ protected static void emit_package(PrintWriter out)
+ {
+ /* generate a package spec if we have a name for one */
+ if (package_name != null) {
+ out.println("package " + package_name + ";"); out.println();
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit code for the symbol constant class, optionally including non terms,
+ * if they have been requested.
+ * @param out stream to produce output on.
+ * @param emit_non_terms do we emit constants for non terminals?
+ * @param sym_interface should we emit an interface, rather than a class?
+ */
+ public static void symbols(PrintWriter out,
+ boolean emit_non_terms, boolean sym_interface)
+ {
+ terminal term;
+ non_terminal nt;
+ String class_or_interface = (sym_interface)?"interface":"class";
+
+ long start_time = System.currentTimeMillis();
+
+ /* top of file */
+ out.println();
+ out.println("//----------------------------------------------------");
+ out.println("// The following code was generated by " +
+ version.title_str);
+ out.println("// " + new Date());
+ out.println("//----------------------------------------------------");
+ out.println();
+ emit_package(out);
+
+ /* class header */
+ out.println("/** CUP generated " + class_or_interface +
+ " containing symbol constants. */");
+ out.println("public " + class_or_interface + " " +
+ symbol_const_class_name + " {");
+
+ out.println(" /* terminals */");
+
+ /* walk over the terminals */ /* later might sort these */
+ for (Enumeration e = terminal.all(); e.hasMoreElements(); )
+ {
+ term = (terminal)e.nextElement();
+
+ /* output a constant decl for the terminal */
+ out.println(" public static final int " + term.name() + " = " +
+ term.index() + ";");
+ }
+
+ /* do the non terminals if they want them (parser doesn't need them) */
+ if (emit_non_terms)
+ {
+ out.println();
+ out.println(" /* non terminals */");
+
+ /* walk over the non terminals */ /* later might sort these */
+ for (Enumeration e = non_terminal.all(); e.hasMoreElements(); )
+ {
+ nt = (non_terminal)e.nextElement();
+
+ /* output a constant decl for the terminal */
+ out.println(" static final int " + nt.name() + " = " +
+ nt.index() + ";");
+ }
+ }
+
+ /* end of class */
+ out.println("}");
+ out.println();
+
+ symbols_time = System.currentTimeMillis() - start_time;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit code for the non-public class holding the actual action code.
+ * @param out stream to produce output on.
+ * @param start_prod the start production of the grammar.
+ */
+ protected static void emit_action_code(PrintWriter out, production start_prod)
+ throws internal_error
+ {
+ production prod;
+
+ long start_time = System.currentTimeMillis();
+
+ /* class header */
+ out.println();
+ out.println(
+ "/** Cup generated class to encapsulate user supplied action code.*/"
+ );
+ out.println("class " + pre("actions") + " {");
+
+ /* user supplied code */
+ if (action_code != null)
+ {
+ out.println();
+ out.println(action_code);
+ }
+
+ /* field for parser object */
+ out.println(" private final "+parser_class_name+" parser;");
+
+ /* constructor */
+ out.println();
+ out.println(" /** Constructor */");
+ out.println(" " + pre("actions") + "("+parser_class_name+" parser) {");
+ out.println(" this.parser = parser;");
+ out.println(" }");
+
+ /* action method head */
+ out.println();
+ out.println(" /** Method with the actual generated action code. */");
+ out.println(" public final java_cup.runtime.Symbol " +
+ pre("do_action") + "(");
+ out.println(" int " + pre("act_num,"));
+ out.println(" java_cup.runtime.lr_parser " + pre("parser,"));
+ out.println(" java.util.Stack " + pre("stack,"));
+ out.println(" int " + pre("top)"));
+ out.println(" throws java.lang.Exception");
+ out.println(" {");
+
+ /* declaration of result symbol */
+ /* New declaration!! now return Symbol
+ 6/13/96 frankf */
+ out.println(" /* Symbol object for return from actions */");
+ out.println(" java_cup.runtime.Symbol " + pre("result") + ";");
+ out.println();
+
+ /* switch top */
+ out.println(" /* select the action based on the action number */");
+ out.println(" switch (" + pre("act_num") + ")");
+ out.println(" {");
+
+ /* emit action code for each production as a separate case */
+ for (Enumeration p = production.all(); p.hasMoreElements(); )
+ {
+ prod = (production)p.nextElement();
+
+ /* case label */
+ out.println(" /*. . . . . . . . . . . . . . . . . . . .*/");
+ out.println(" case " + prod.index() + ": // " +
+ prod.to_simple_string());
+
+ /* give them their own block to work in */
+ out.println(" {");
+
+ /* create the result symbol */
+ /*make the variable RESULT which will point to the new Symbol (see below)
+ and be changed by action code
+ 6/13/96 frankf */
+ out.println(" " + prod.lhs().the_symbol().stack_type() +
+ " RESULT = null;");
+
+ /* Add code to propagate RESULT assignments that occur in
+ * action code embedded in a production (ie, non-rightmost
+ * action code). 24-Mar-1998 CSA
+ */
+ for (int i=0; i<prod.rhs_length(); i++) {
+ // only interested in non-terminal symbols.
+ if (!(prod.rhs(i) instanceof symbol_part)) continue;
+ symbol s = ((symbol_part)prod.rhs(i)).the_symbol();
+ if (!(s instanceof non_terminal)) continue;
+ // skip this non-terminal unless it corresponds to
+ // an embedded action production.
+ if (((non_terminal)s).is_embedded_action == false) continue;
+ // OK, it fits. Make a conditional assignment to RESULT.
+ int index = prod.rhs_length() - i - 1; // last rhs is on top.
+ out.println(" " + "// propagate RESULT from " +
+ s.name());
+ out.println(" " + "if ( " +
+ "((java_cup.runtime.Symbol) " + emit.pre("stack") + ".elementAt("
+ + emit.pre("top") + "-" + index + ")).value != null )");
+ out.println(" " + "RESULT = " +
+ "(" + prod.lhs().the_symbol().stack_type() + ") " +
+ "((java_cup.runtime.Symbol) " + emit.pre("stack") + ".elementAt("
+ + emit.pre("top") + "-" + index + ")).value;");
+ }
+
+ /* if there is an action string, emit it */
+ if (prod.action() != null && prod.action().code_string() != null &&
+ !prod.action().equals(""))
+ out.println(prod.action().code_string());
+
+ /* here we have the left and right values being propagated.
+ must make this a command line option.
+ frankf 6/18/96 */
+
+ /* Create the code that assigns the left and right values of
+ the new Symbol that the production is reducing to */
+ if (emit.lr_values()) {
+ int loffset;
+ String leftstring, rightstring;
+ int roffset = 0;
+ rightstring = "((java_cup.runtime.Symbol)" + emit.pre("stack") + ".elementAt(" +
+ emit.pre("top") + "-" + roffset + ")).right";
+ if (prod.rhs_length() == 0)
+ leftstring = rightstring;
+ else {
+ loffset = prod.rhs_length() - 1;
+ leftstring = "((java_cup.runtime.Symbol)" + emit.pre("stack") + ".elementAt(" +
+ emit.pre("top") + "-" + loffset + ")).left";
+ }
+ out.println(" " + pre("result") + " = new java_cup.runtime.Symbol(" +
+ prod.lhs().the_symbol().index() + "/*" +
+ prod.lhs().the_symbol().name() + "*/" +
+ ", " + leftstring + ", " + rightstring + ", RESULT);");
+ } else {
+ out.println(" " + pre("result") + " = new java_cup.runtime.Symbol(" +
+ prod.lhs().the_symbol().index() + "/*" +
+ prod.lhs().the_symbol().name() + "*/" +
+ ", RESULT);");
+ }
+
+ /* end of their block */
+ out.println(" }");
+
+ /* if this was the start production, do action for accept */
+ if (prod == start_prod)
+ {
+ out.println(" /* ACCEPT */");
+ out.println(" " + pre("parser") + ".done_parsing();");
+ }
+
+ /* code to return lhs symbol */
+ out.println(" return " + pre("result") + ";");
+ out.println();
+ }
+
+ /* end of switch */
+ out.println(" /* . . . . . .*/");
+ out.println(" default:");
+ out.println(" throw new Exception(");
+ out.println(" \"Invalid action number found in " +
+ "internal parse table\");");
+ out.println();
+ out.println(" }");
+
+ /* end of method */
+ out.println(" }");
+
+ /* end of class */
+ out.println("}");
+ out.println();
+
+ action_code_time = System.currentTimeMillis() - start_time;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit the production table.
+ * @param out stream to produce output on.
+ */
+ protected static void emit_production_table(PrintWriter out)
+ {
+ production all_prods[];
+ production prod;
+
+ long start_time = System.currentTimeMillis();
+
+ /* collect up the productions in order */
+ all_prods = new production[production.number()];
+ for (Enumeration p = production.all(); p.hasMoreElements(); )
+ {
+ prod = (production)p.nextElement();
+ all_prods[prod.index()] = prod;
+ }
+
+ // make short[][]
+ short[][] prod_table = new short[production.number()][2];
+ for (int i = 0; i<production.number(); i++)
+ {
+ prod = all_prods[i];
+ // { lhs symbol , rhs size }
+ prod_table[i][0] = (short) prod.lhs().the_symbol().index();
+ prod_table[i][1] = (short) prod.rhs_length();
+ }
+ /* do the top of the table */
+ out.println();
+ out.println(" /** Production table. */");
+ out.println(" protected static final short _production_table[][] = ");
+ out.print (" unpackFromStrings(");
+ do_table_as_string(out, prod_table);
+ out.println(");");
+
+ /* do the public accessor method */
+ out.println();
+ out.println(" /** Access to production table. */");
+ out.println(" public short[][] production_table() " +
+ "{return _production_table;}");
+
+ production_table_time = System.currentTimeMillis() - start_time;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit the action table.
+ * @param out stream to produce output on.
+ * @param act_tab the internal representation of the action table.
+ * @param compact_reduces do we use the most frequent reduce as default?
+ */
+ protected static void do_action_table(
+ PrintWriter out,
+ parse_action_table act_tab,
+ boolean compact_reduces)
+ throws internal_error
+ {
+ parse_action_row row;
+ parse_action act;
+ int red;
+
+ long start_time = System.currentTimeMillis();
+
+ /* collect values for the action table */
+ short[][] action_table = new short[act_tab.num_states()][];
+ /* do each state (row) of the action table */
+ for (int i = 0; i < act_tab.num_states(); i++)
+ {
+ /* get the row */
+ row = act_tab.under_state[i];
+
+ /* determine the default for the row */
+ if (compact_reduces)
+ row.compute_default();
+ else
+ row.default_reduce = -1;
+
+ /* make temporary table for the row. */
+ short[] temp_table = new short[2*row.size()];
+ int nentries = 0;
+
+ /* do each column */
+ for (int j = 0; j < row.size(); j++)
+ {
+ /* extract the action from the table */
+ act = row.under_term[j];
+
+ /* skip error entries these are all defaulted out */
+ if (act.kind() != parse_action.ERROR)
+ {
+ /* first put in the symbol index, then the actual entry */
+
+ /* shifts get positive entries of state number + 1 */
+ if (act.kind() == parse_action.SHIFT)
+ {
+ /* make entry */
+ temp_table[nentries++] = (short) j;
+ temp_table[nentries++] = (short)
+ (((shift_action)act).shift_to().index() + 1);
+ }
+
+ /* reduce actions get negated entries of production# + 1 */
+ else if (act.kind() == parse_action.REDUCE)
+ {
+ /* if its the default entry let it get defaulted out */
+ red = ((reduce_action)act).reduce_with().index();
+ if (red != row.default_reduce) {
+ /* make entry */
+ temp_table[nentries++] = (short) j;
+ temp_table[nentries++] = (short) (-(red+1));
+ }
+ } else if (act.kind() == parse_action.NONASSOC)
+ {
+ /* do nothing, since we just want a syntax error */
+ }
+ /* shouldn't be anything else */
+ else
+ throw new internal_error("Unrecognized action code " +
+ act.kind() + " found in parse table");
+ }
+ }
+
+ /* now we know how big to make the row */
+ action_table[i] = new short[nentries + 2];
+ System.arraycopy(temp_table, 0, action_table[i], 0, nentries);
+
+ /* finish off the row with a default entry */
+ action_table[i][nentries++] = -1;
+ if (row.default_reduce != -1)
+ action_table[i][nentries++] = (short) (-(row.default_reduce+1));
+ else
+ action_table[i][nentries++] = 0;
+ }
+
+ /* finish off the init of the table */
+ out.println();
+ out.println(" /** Parse-action table. */");
+ out.println(" protected static final short[][] _action_table = ");
+ out.print (" unpackFromStrings(");
+ do_table_as_string(out, action_table);
+ out.println(");");
+
+ /* do the public accessor method */
+ out.println();
+ out.println(" /** Access to parse-action table. */");
+ out.println(" public short[][] action_table() {return _action_table;}");
+
+ action_table_time = System.currentTimeMillis() - start_time;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit the reduce-goto table.
+ * @param out stream to produce output on.
+ * @param red_tab the internal representation of the reduce-goto table.
+ */
+ protected static void do_reduce_table(
+ PrintWriter out,
+ parse_reduce_table red_tab)
+ {
+ lalr_state goto_st;
+ parse_action act;
+
+ long start_time = System.currentTimeMillis();
+
+ /* collect values for reduce-goto table */
+ short[][] reduce_goto_table = new short[red_tab.num_states()][];
+ /* do each row of the reduce-goto table */
+ for (int i=0; i<red_tab.num_states(); i++)
+ {
+ /* make temporary table for the row. */
+ short[] temp_table = new short[2*red_tab.under_state[i].size()];
+ int nentries = 0;
+ /* do each entry in the row */
+ for (int j=0; j<red_tab.under_state[i].size(); j++)
+ {
+ /* get the entry */
+ goto_st = red_tab.under_state[i].under_non_term[j];
+
+ /* if we have none, skip it */
+ if (goto_st != null)
+ {
+ /* make entries for the index and the value */
+ temp_table[nentries++] = (short) j;
+ temp_table[nentries++] = (short) goto_st.index();
+ }
+ }
+ /* now we know how big to make the row. */
+ reduce_goto_table[i] = new short[nentries+2];
+ System.arraycopy(temp_table, 0, reduce_goto_table[i], 0, nentries);
+
+ /* end row with default value */
+ reduce_goto_table[i][nentries++] = -1;
+ reduce_goto_table[i][nentries++] = -1;
+ }
+
+ /* emit the table. */
+ out.println();
+ out.println(" /** <code>reduce_goto</code> table. */");
+ out.println(" protected static final short[][] _reduce_table = ");
+ out.print (" unpackFromStrings(");
+ do_table_as_string(out, reduce_goto_table);
+ out.println(");");
+
+ /* do the public accessor method */
+ out.println();
+ out.println(" /** Access to <code>reduce_goto</code> table. */");
+ out.println(" public short[][] reduce_table() {return _reduce_table;}");
+ out.println();
+
+ goto_table_time = System.currentTimeMillis() - start_time;
+ }
+
+ // print a string array encoding the given short[][] array.
+ protected static void do_table_as_string(PrintWriter out, short[][] sa) {
+ out.println("new String[] {");
+ out.print(" \"");
+ int nchar=0, nbytes=0;
+ nbytes+=do_escaped(out, (char)(sa.length>>16));
+ nchar =do_newline(out, nchar, nbytes);
+ nbytes+=do_escaped(out, (char)(sa.length&0xFFFF));
+ nchar =do_newline(out, nchar, nbytes);
+ for (int i=0; i<sa.length; i++) {
+ nbytes+=do_escaped(out, (char)(sa[i].length>>16));
+ nchar =do_newline(out, nchar, nbytes);
+ nbytes+=do_escaped(out, (char)(sa[i].length&0xFFFF));
+ nchar =do_newline(out, nchar, nbytes);
+ for (int j=0; j<sa[i].length; j++) {
+ // contents of string are (value+2) to allow for common -1, 0 cases
+ // (UTF-8 encoding is most efficient for 0<c<0x80)
+ nbytes+=do_escaped(out, (char)(2+sa[i][j]));
+ nchar =do_newline(out, nchar, nbytes);
+ }
+ }
+ out.print("\" }");
+ }
+ // split string if it is very long; start new line occasionally for neatness
+ protected static int do_newline(PrintWriter out, int nchar, int nbytes) {
+ if (nbytes > 65500) { out.println("\", "); out.print(" \""); }
+ else if (nchar > 11) { out.println("\" +"); out.print(" \""); }
+ else return nchar+1;
+ return 0;
+ }
+ // output an escape sequence for the given character code.
+ protected static int do_escaped(PrintWriter out, char c) {
+ StringBuffer escape = new StringBuffer();
+ if (c <= 0xFF) {
+ escape.append(Integer.toOctalString(c));
+ while(escape.length() < 3) escape.insert(0, '0');
+ } else {
+ escape.append(Integer.toHexString(c));
+ while(escape.length() < 4) escape.insert(0, '0');
+ escape.insert(0, 'u');
+ }
+ escape.insert(0, '\\');
+ out.print(escape.toString());
+
+ // return number of bytes this takes up in UTF-8 encoding.
+ if (c == 0) return 2;
+ if (c >= 0x01 && c <= 0x7F) return 1;
+ if (c >= 0x80 && c <= 0x7FF) return 2;
+ return 3;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit the parser subclass with embedded tables.
+ * @param out stream to produce output on.
+ * @param action_table internal representation of the action table.
+ * @param reduce_table internal representation of the reduce-goto table.
+ * @param start_st start state of the parse machine.
+ * @param start_prod start production of the grammar.
+ * @param compact_reduces do we use most frequent reduce as default?
+ * @param suppress_scanner should scanner be suppressed for compatibility?
+ */
+ public static void parser(
+ PrintWriter out,
+ parse_action_table action_table,
+ parse_reduce_table reduce_table,
+ int start_st,
+ production start_prod,
+ boolean compact_reduces,
+ boolean suppress_scanner)
+ throws internal_error
+ {
+ long start_time = System.currentTimeMillis();
+
+ /* top of file */
+ out.println();
+ out.println("//----------------------------------------------------");
+ out.println("// The following code was generated by " +
+ version.title_str);
+ out.println("// " + new Date());
+ out.println("//----------------------------------------------------");
+ out.println();
+ emit_package(out);
+
+ /* user supplied imports */
+ for (int i = 0; i < import_list.size(); i++)
+ out.println("import " + import_list.elementAt(i) + ";");
+
+ /* class header */
+ out.println();
+ out.println("/** "+version.title_str+" generated parser.");
+ out.println(" * @version " + new Date());
+ out.println(" */");
+ out.println("public class " + parser_class_name +
+ " extends java_cup.runtime.lr_parser {");
+
+ /* constructors [CSA/davidm, 24-jul-99] */
+ out.println();
+ out.println(" /** Default constructor. */");
+ out.println(" public " + parser_class_name + "() {super();}");
+ if (!suppress_scanner) {
+ out.println();
+ out.println(" /** Constructor which sets the default scanner. */");
+ out.println(" public " + parser_class_name +
+ "(java_cup.runtime.Scanner s) {super(s);}");
+ }
+
+ /* emit the various tables */
+ emit_production_table(out);
+ do_action_table(out, action_table, compact_reduces);
+ do_reduce_table(out, reduce_table);
+
+ /* instance of the action encapsulation class */
+ out.println(" /** Instance of action encapsulation class. */");
+ out.println(" protected " + pre("actions") + " action_obj;");
+ out.println();
+
+ /* action object initializer */
+ out.println(" /** Action encapsulation object initializer. */");
+ out.println(" protected void init_actions()");
+ out.println(" {");
+ out.println(" action_obj = new " + pre("actions") + "(this);");
+ out.println(" }");
+ out.println();
+
+ /* access to action code */
+ out.println(" /** Invoke a user supplied parse action. */");
+ out.println(" public java_cup.runtime.Symbol do_action(");
+ out.println(" int act_num,");
+ out.println(" java_cup.runtime.lr_parser parser,");
+ out.println(" java.util.Stack stack,");
+ out.println(" int top)");
+ out.println(" throws java.lang.Exception");
+ out.println(" {");
+ out.println(" /* call code in generated class */");
+ out.println(" return action_obj." + pre("do_action(") +
+ "act_num, parser, stack, top);");
+ out.println(" }");
+ out.println("");
+
+
+ /* method to tell the parser about the start state */
+ out.println(" /** Indicates start state. */");
+ out.println(" public int start_state() {return " + start_st + ";}");
+
+ /* method to indicate start production */
+ out.println(" /** Indicates start production. */");
+ out.println(" public int start_production() {return " +
+ start_production.index() + ";}");
+ out.println();
+
+ /* methods to indicate EOF and error symbol indexes */
+ out.println(" /** <code>EOF</code> Symbol index. */");
+ out.println(" public int EOF_sym() {return " + terminal.EOF.index() +
+ ";}");
+ out.println();
+ out.println(" /** <code>error</code> Symbol index. */");
+ out.println(" public int error_sym() {return " + terminal.error.index() +
+ ";}");
+ out.println();
+
+ /* user supplied code for user_init() */
+ if (init_code != null)
+ {
+ out.println();
+ out.println(" /** User initialization code. */");
+ out.println(" public void user_init() throws java.lang.Exception");
+ out.println(" {");
+ out.println(init_code);
+ out.println(" }");
+ }
+
+ /* user supplied code for scan */
+ if (scan_code != null)
+ {
+ out.println();
+ out.println(" /** Scan to get the next Symbol. */");
+ out.println(" public java_cup.runtime.Symbol scan()");
+ out.println(" throws java.lang.Exception");
+ out.println(" {");
+ out.println(scan_code);
+ out.println(" }");
+ }
+
+ /* user supplied code */
+ if (parser_code != null)
+ {
+ out.println();
+ out.println(parser_code);
+ }
+
+ /* end of class */
+ out.println("}");
+
+ /* put out the action code class */
+ emit_action_code(out, start_prod);
+
+ parser_time = System.currentTimeMillis() - start_time;
+ }
+
+ /*-----------------------------------------------------------*/
+}
diff --git a/src/syntaxParser/java_cup/SAVE/internal_error.java b/src/syntaxParser/java_cup/SAVE/internal_error.java
new file mode 100644
index 0000000..4d3e7c2
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/internal_error.java
@@ -0,0 +1,22 @@
+
+package java_cup;
+
+/** Exception subclass for reporting internal errors in JavaCup. */
+public class internal_error extends Exception
+ {
+ /** Constructor with a message */
+ public internal_error(String msg)
+ {
+ super(msg);
+ }
+
+ /** Method called to do a forced error exit on an internal error
+ for cases when we can't actually throw the exception. */
+ public void crash()
+ {
+ System.err.println("JavaCUP Fatal Internal Error Detected");
+ System.err.println(getMessage());
+ printStackTrace();
+ System.exit(-1);
+ }
+ }
diff --git a/src/syntaxParser/java_cup/SAVE/lalr_item.java b/src/syntaxParser/java_cup/SAVE/lalr_item.java
new file mode 100644
index 0000000..fe92054
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/lalr_item.java
@@ -0,0 +1,330 @@
+package java_cup;
+
+import java.util.Stack;
+import java.util.Enumeration;
+
+/** This class represents an LALR item. Each LALR item consists of
+ * a production, a "dot" at a position within that production, and
+ * a set of lookahead symbols (terminal). (The first two of these parts
+ * are provide by the super class). An item is designed to represent a
+ * configuration that the parser may be in. For example, an item of the
+ * form: <pre>
+ * [A ::= B * C d E , {a,b,c}]
+ * </pre>
+ * indicates that the parser is in the middle of parsing the production <pre>
+ * A ::= B C d E
+ * </pre>
+ * that B has already been parsed, and that we will expect to see a lookahead
+ * of either a, b, or c once the complete RHS of this production has been
+ * found.<p>
+ *
+ * Items may initially be missing some items from their lookahead sets.
+ * Links are maintained from each item to the set of items that would need
+ * to be updated if symbols are added to its lookahead set. During
+ * "lookahead propagation", we add symbols to various lookahead sets and
+ * propagate these changes across these dependency links as needed.
+ *
+ * @see java_cup.lalr_item_set
+ * @see java_cup.lalr_state
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class lalr_item extends lr_item_core {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param prod the production for the item.
+ * @param pos the position of the "dot" within the production.
+ * @param look the set of lookahead symbols.
+ */
+ public lalr_item(production prod, int pos, terminal_set look)
+ throws internal_error
+ {
+ super(prod, pos);
+ _lookahead = look;
+ _propagate_items = new Stack();
+ needs_propagation = true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with default position (dot at start).
+ * @param prod the production for the item.
+ * @param look the set of lookahead symbols.
+ */
+ public lalr_item(production prod, terminal_set look) throws internal_error
+ {
+ this(prod,0,look);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with default position and empty lookahead set.
+ * @param prod the production for the item.
+ */
+ public lalr_item(production prod) throws internal_error
+ {
+ this(prod,0,new terminal_set());
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The lookahead symbols of the item. */
+ protected terminal_set _lookahead;
+
+ /** The lookahead symbols of the item. */
+ public terminal_set lookahead() {return _lookahead;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Links to items that the lookahead needs to be propagated to. */
+ protected Stack _propagate_items;
+
+ /** Links to items that the lookahead needs to be propagated to */
+ public Stack propagate_items() {return _propagate_items;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Flag to indicate that this item needs to propagate its lookahead
+ * (whether it has changed or not).
+ */
+ protected boolean needs_propagation;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a new item to the set of items we propagate to. */
+ public void add_propagate(lalr_item prop_to)
+ {
+ _propagate_items.push(prop_to);
+ needs_propagation = true;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Propagate incoming lookaheads through this item to others need to
+ * be changed.
+ * @params incoming symbols to potentially be added to lookahead of this item.
+ */
+ public void propagate_lookaheads(terminal_set incoming) throws internal_error
+ {
+ boolean change = false;
+
+ /* if we don't need to propagate, then bail out now */
+ if (!needs_propagation && (incoming == null || incoming.empty()))
+ return;
+
+ /* if we have null incoming, treat as an empty set */
+ if (incoming != null)
+ {
+ /* add the incoming to the lookahead of this item */
+ change = lookahead().add(incoming);
+ }
+
+ /* if we changed or need it anyway, propagate across our links */
+ if (change || needs_propagation)
+ {
+ /* don't need to propagate again */
+ needs_propagation = false;
+
+ /* propagate our lookahead into each item we are linked to */
+ for (int i = 0; i < propagate_items().size(); i++)
+ ((lalr_item)propagate_items().elementAt(i))
+ .propagate_lookaheads(lookahead());
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce the new lalr_item that results from shifting the dot one position
+ * to the right.
+ */
+ public lalr_item shift() throws internal_error
+ {
+ lalr_item result;
+
+ /* can't shift if we have dot already at the end */
+ if (dot_at_end())
+ throw new internal_error("Attempt to shift past end of an lalr_item");
+
+ /* create the new item w/ the dot shifted by one */
+ result = new lalr_item(the_production(), dot_pos()+1,
+ new terminal_set(lookahead()));
+
+ /* change in our lookahead needs to be propagated to this item */
+ add_propagate(result);
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Calculate lookahead representing symbols that could appear after the
+ * symbol that the dot is currently in front of. Note: this routine must
+ * not be invoked before first sets and nullability has been calculated
+ * for all non terminals.
+ */
+ public terminal_set calc_lookahead(terminal_set lookahead_after)
+ throws internal_error
+ {
+ terminal_set result;
+ int pos;
+ production_part part;
+ symbol sym;
+
+ /* sanity check */
+ if (dot_at_end())
+ throw new internal_error(
+ "Attempt to calculate a lookahead set with a completed item");
+
+ /* start with an empty result */
+ result = new terminal_set();
+
+ /* consider all nullable symbols after the one to the right of the dot */
+ for (pos = dot_pos()+1; pos < the_production().rhs_length(); pos++)
+ {
+ part = the_production().rhs(pos);
+
+ /* consider what kind of production part it is -- skip actions */
+ if (!part.is_action())
+ {
+ sym = ((symbol_part)part).the_symbol();
+
+ /* if its a terminal add it in and we are done */
+ if (!sym.is_non_term())
+ {
+ result.add((terminal)sym);
+ return result;
+ }
+ else
+ {
+ /* otherwise add in first set of the non terminal */
+ result.add(((non_terminal)sym).first_set());
+
+ /* if its nullable we continue adding, if not, we are done */
+ if (!((non_terminal)sym).nullable())
+ return result;
+ }
+ }
+ }
+
+ /* if we get here everything past the dot was nullable
+ we add in the lookahead for after the production and we are done */
+ result.add(lookahead_after);
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if everything from the symbol one beyond the dot all the
+ * way to the end of the right hand side is nullable. This would indicate
+ * that the lookahead of this item must be included in the lookaheads of
+ * all items produced as a closure of this item. Note: this routine should
+ * not be invoked until after first sets and nullability have been
+ * calculated for all non terminals.
+ */
+ public boolean lookahead_visible() throws internal_error
+ {
+ production_part part;
+ symbol sym;
+
+ /* if the dot is at the end, we have a problem, but the cleanest thing
+ to do is just return true. */
+ if (dot_at_end()) return true;
+
+ /* walk down the rhs and bail if we get a non-nullable symbol */
+ for (int pos = dot_pos() + 1; pos < the_production().rhs_length(); pos++)
+ {
+ part = the_production().rhs(pos);
+
+ /* skip actions */
+ if (!part.is_action())
+ {
+ sym = ((symbol_part)part).the_symbol();
+
+ /* if its a terminal we fail */
+ if (!sym.is_non_term()) return false;
+
+ /* if its not nullable we fail */
+ if (!((non_terminal)sym).nullable()) return false;
+ }
+ }
+
+ /* if we get here its all nullable */
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison -- here we only require the cores to be equal since
+ * we need to do sets of items based only on core equality (ignoring
+ * lookahead sets).
+ */
+ public boolean equals(lalr_item other)
+ {
+ if (other == null) return false;
+ return super.equals(other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof lalr_item))
+ return false;
+ else
+ return equals((lalr_item)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return a hash code -- here we only hash the core since we only test core
+ * matching in LALR items.
+ */
+ public int hashCode()
+ {
+ return super.hashCode();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to string. */
+ public String toString()
+ {
+ String result = "";
+
+ // additional output for debugging:
+ // result += "(" + obj_hash() + ")";
+ result += "[";
+ result += super.toString();
+ result += ", ";
+ if (lookahead() != null)
+ {
+ result += "{";
+ for (int t = 0; t < terminal.number(); t++)
+ if (lookahead().contains(t))
+ result += terminal.find(t).name() + " ";
+ result += "}";
+ }
+ else
+ result += "NULL LOOKAHEAD!!";
+ result += "]";
+
+ // additional output for debugging:
+ // result += " -> ";
+ // for (int i = 0; i<propagate_items().size(); i++)
+ // result+=((lalr_item)(propagate_items().elementAt(i))).obj_hash()+" ";
+ //
+ // if (needs_propagation) result += " NP";
+
+ return result;
+ }
+ /*-----------------------------------------------------------*/
+}
diff --git a/src/syntaxParser/java_cup/SAVE/lalr_item_set.java b/src/syntaxParser/java_cup/SAVE/lalr_item_set.java
new file mode 100644
index 0000000..233a68f
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/lalr_item_set.java
@@ -0,0 +1,371 @@
+
+package java_cup;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/** This class represents a set of LALR items. For purposes of building
+ * these sets, items are considered unique only if they have unique cores
+ * (i.e., ignoring differences in their lookahead sets).<p>
+ *
+ * This class provides fairly conventional set oriented operations (union,
+ * sub/super-set tests, etc.), as well as an LALR "closure" operation (see
+ * compute_closure()).
+ *
+ * @see java_cup.lalr_item
+ * @see java_cup.lalr_state
+ * @version last updated: 3/6/96
+ * @author Scott Hudson
+ */
+
+public class lalr_item_set {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constructor for an empty set. */
+ public lalr_item_set() { }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor for cloning from another set.
+ * @param other indicates set we should copy from.
+ */
+ public lalr_item_set(lalr_item_set other)
+ throws internal_error
+ {
+ not_null(other);
+ _all = (Hashtable)other._all.clone();
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** A hash table to implement the set. We store the items using themselves
+ * as keys.
+ */
+ protected Hashtable _all = new Hashtable(11);
+
+ /** Access to all elements of the set. */
+ public Enumeration all() {return _all.elements();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Cached hashcode for this set. */
+ protected Integer hashcode_cache = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Size of the set */
+ public int size() {return _all.size();}
+
+ /*-----------------------------------------------------------*/
+ /*--- Set Operation Methods ---------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Does the set contain a particular item?
+ * @param itm the item in question.
+ */
+ public boolean contains(lalr_item itm) {return _all.containsKey(itm);}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return the item in the set matching a particular item (or null if not
+ * found)
+ * @param itm the item we are looking for.
+ */
+ public lalr_item find(lalr_item itm) {return (lalr_item)_all.get(itm);}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Is this set an (improper) subset of another?
+ * @param other the other set in question.
+ */
+ public boolean is_subset_of(lalr_item_set other) throws internal_error
+ {
+ not_null(other);
+
+ /* walk down our set and make sure every element is in the other */
+ for (Enumeration e = all(); e.hasMoreElements(); )
+ if (!other.contains((lalr_item)e.nextElement()))
+ return false;
+
+ /* they were all there */
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Is this set an (improper) superset of another?
+ * @param other the other set in question.
+ */
+ public boolean is_superset_of(lalr_item_set other) throws internal_error
+ {
+ not_null(other);
+ return other.is_subset_of(this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a singleton item, merging lookahead sets if the item is already
+ * part of the set. returns the element of the set that was added or
+ * merged into.
+ * @param itm the item being added.
+ */
+ public lalr_item add(lalr_item itm) throws internal_error
+ {
+ lalr_item other;
+
+ not_null(itm);
+
+ /* see if an item with a matching core is already there */
+ other = (lalr_item)_all.get(itm);
+
+ /* if so, merge this lookahead into the original and leave it */
+ if (other != null)
+ {
+ other.lookahead().add(itm.lookahead());
+ return other;
+ }
+ /* otherwise we just go in the set */
+ else
+ {
+ /* invalidate cached hashcode */
+ hashcode_cache = null;
+
+ _all.put(itm,itm);
+ return itm;
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove a single item if it is in the set.
+ * @param itm the item to remove.
+ */
+ public void remove(lalr_item itm) throws internal_error
+ {
+ not_null(itm);
+
+ /* invalidate cached hashcode */
+ hashcode_cache = null;
+
+ /* remove it from hash table implementing set */
+ _all.remove(itm);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a complete set, merging lookaheads where items are already in
+ * the set
+ * @param other the set to be added.
+ */
+ public void add(lalr_item_set other) throws internal_error
+ {
+ not_null(other);
+
+ /* walk down the other set and do the adds individually */
+ for (Enumeration e = other.all(); e.hasMoreElements(); )
+ add((lalr_item)e.nextElement());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove (set subtract) a complete set.
+ * @param other the set to remove.
+ */
+ public void remove(lalr_item_set other) throws internal_error
+ {
+ not_null(other);
+
+ /* walk down the other set and do the removes individually */
+ for (Enumeration e = other.all(); e.hasMoreElements(); )
+ remove((lalr_item)e.nextElement());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove and return one item from the set (done in hash order). */
+ public lalr_item get_one() throws internal_error
+ {
+ Enumeration the_set;
+ lalr_item result;
+
+ the_set = all();
+ if (the_set.hasMoreElements())
+ {
+ result = (lalr_item)the_set.nextElement();
+ remove(result);
+ return result;
+ }
+ else
+ return null;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Helper function for null test. Throws an interal_error exception if its
+ * parameter is null.
+ * @param obj the object we are testing.
+ */
+ protected void not_null(Object obj) throws internal_error
+ {
+ if (obj == null)
+ throw new internal_error("Null object used in set operation");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute the closure of the set using the LALR closure rules. Basically
+ * for every item of the form: <pre>
+ * [L ::= a *N alpha, l]
+ * </pre>
+ * (where N is a a non terminal and alpha is a string of symbols) make
+ * sure there are also items of the form: <pre>
+ * [N ::= *beta, first(alpha l)]
+ * </pre>
+ * corresponding to each production of N. Items with identical cores but
+ * differing lookahead sets are merged by creating a new item with the same
+ * core and the union of the lookahead sets (the LA in LALR stands for
+ * "lookahead merged" and this is where the merger is). This routine
+ * assumes that nullability and first sets have been computed for all
+ * productions before it is called.
+ */
+ public void compute_closure()
+ throws internal_error
+ {
+ lalr_item_set consider;
+ lalr_item itm, new_itm, add_itm;
+ non_terminal nt;
+ terminal_set new_lookaheads;
+ Enumeration p;
+ production prod;
+ boolean need_prop;
+
+
+
+ /* invalidate cached hashcode */
+ hashcode_cache = null;
+
+ /* each current element needs to be considered */
+ consider = new lalr_item_set(this);
+
+ /* repeat this until there is nothing else to consider */
+ while (consider.size() > 0)
+ {
+ /* get one item to consider */
+ itm = consider.get_one();
+
+ /* do we have a dot before a non terminal */
+ nt = itm.dot_before_nt();
+ if (nt != null)
+ {
+ /* create the lookahead set based on first after dot */
+ new_lookaheads = itm.calc_lookahead(itm.lookahead());
+
+ /* are we going to need to propagate our lookahead to new item */
+ need_prop = itm.lookahead_visible();
+
+ /* create items for each production of that non term */
+ for (p = nt.productions(); p.hasMoreElements(); )
+ {
+ prod = (production)p.nextElement();
+
+ /* create new item with dot at start and that lookahead */
+ new_itm = new lalr_item(prod,
+ new terminal_set(new_lookaheads));
+
+ /* add/merge item into the set */
+ add_itm = add(new_itm);
+ /* if propagation is needed link to that item */
+ if (need_prop)
+ itm.add_propagate(add_itm);
+
+ /* was this was a new item*/
+ if (add_itm == new_itm)
+ {
+ /* that may need further closure, consider it also */
+ consider.add(new_itm);
+ }
+ }
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(lalr_item_set other)
+ {
+ if (other == null || other.size() != size()) return false;
+
+ /* once we know they are the same size, then improper subset does test */
+ try {
+ return is_subset_of(other);
+ } catch (internal_error e) {
+ /* can't throw error from here (because superclass doesn't) so crash */
+ e.crash();
+ return false;
+ }
+
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof lalr_item_set))
+ return false;
+ else
+ return equals((lalr_item_set)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return hash code. */
+ public int hashCode()
+ {
+ int result = 0;
+ Enumeration e;
+ int cnt;
+
+ /* only compute a new one if we don't have it cached */
+ if (hashcode_cache == null)
+ {
+ /* hash together codes from at most first 5 elements */
+ // CSA fix! we'd *like* to hash just a few elements, but
+ // that means equal sets will have inequal hashcodes, which
+ // we're not allowed (by contract) to do. So hash them all.
+ for (e = all(), cnt=0 ; e.hasMoreElements() /*&& cnt<5*/; cnt++)
+ result ^= ((lalr_item)e.nextElement()).hashCode();
+
+ hashcode_cache = new Integer(result);
+ }
+
+ return hashcode_cache.intValue();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to string. */
+ public String toString()
+ {
+ StringBuffer result = new StringBuffer();
+
+ result.append("{\n");
+ for (Enumeration e=all(); e.hasMoreElements(); )
+ {
+ result.append(" " + (lalr_item)e.nextElement() + "\n");
+ }
+ result.append("}");
+
+ return result.toString();
+ }
+ /*-----------------------------------------------------------*/
+}
+
diff --git a/src/syntaxParser/java_cup/SAVE/lalr_state.java b/src/syntaxParser/java_cup/SAVE/lalr_state.java
new file mode 100644
index 0000000..5298e87
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/lalr_state.java
@@ -0,0 +1,884 @@
+
+package java_cup;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+import java.util.Stack;
+
+/** This class represents a state in the LALR viable prefix recognition machine.
+ * A state consists of an LALR item set and a set of transitions to other
+ * states under terminal and non-terminal symbols. Each state represents
+ * a potential configuration of the parser. If the item set of a state
+ * includes an item such as: <pre>
+ * [A ::= B * C d E , {a,b,c}]
+ * </pre>
+ * this indicates that when the parser is in this state it is currently
+ * looking for an A of the given form, has already seen the B, and would
+ * expect to see an a, b, or c after this sequence is complete. Note that
+ * the parser is normally looking for several things at once (represented
+ * by several items). In our example above, the state would also include
+ * items such as: <pre>
+ * [C ::= * X e Z, {d}]
+ * [X ::= * f, {e}]
+ * </pre>
+ * to indicate that it was currently looking for a C followed by a d (which
+ * would be reduced into a C, matching the first symbol in our production
+ * above), and the terminal f followed by e.<p>
+ *
+ * At runtime, the parser uses a viable prefix recognition machine made up
+ * of these states to parse. The parser has two operations, shift and reduce.
+ * In a shift, it consumes one Symbol and makes a transition to a new state.
+ * This corresponds to "moving the dot past" a terminal in one or more items
+ * in the state (these new shifted items will then be found in the state at
+ * the end of the transition). For a reduce operation, the parser is
+ * signifying that it is recognizing the RHS of some production. To do this
+ * it first "backs up" by popping a stack of previously saved states. It
+ * pops off the same number of states as are found in the RHS of the
+ * production. This leaves the machine in the same state is was in when the
+ * parser first attempted to find the RHS. From this state it makes a
+ * transition based on the non-terminal on the LHS of the production. This
+ * corresponds to placing the parse in a configuration equivalent to having
+ * replaced all the symbols from the the input corresponding to the RHS with
+ * the symbol on the LHS.
+ *
+ * @see java_cup.lalr_item
+ * @see java_cup.lalr_item_set
+ * @see java_cup.lalr_transition
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ *
+ */
+
+public class lalr_state {
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constructor for building a state from a set of items.
+ * @param itms the set of items that makes up this state.
+ */
+ public lalr_state(lalr_item_set itms) throws internal_error
+ {
+ /* don't allow null or duplicate item sets */
+ if (itms == null)
+ throw new internal_error(
+ "Attempt to construct an LALR state from a null item set");
+
+ if (find_state(itms) != null)
+ throw new internal_error(
+ "Attempt to construct a duplicate LALR state");
+
+ /* assign a unique index */
+ _index = next_index++;
+
+ /* store the items */
+ _items = itms;
+
+ /* add to the global collection, keyed with its item set */
+ _all.put(_items,this);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Collection of all states. */
+ protected static Hashtable _all = new Hashtable();
+
+ /** Collection of all states. */
+ public static Enumeration all() {return _all.elements();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Indicate total number of states there are. */
+ public static int number() {return _all.size();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Hash table to find states by their kernels (i.e, the original,
+ * unclosed, set of items -- which uniquely define the state). This table
+ * stores state objects using (a copy of) their kernel item sets as keys.
+ */
+ protected static Hashtable _all_kernels = new Hashtable();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Find and return state with a given a kernel item set (or null if not
+ * found). The kernel item set is the subset of items that were used to
+ * originally create the state. These items are formed by "shifting the
+ * dot" within items of other states that have a transition to this one.
+ * The remaining elements of this state's item set are added during closure.
+ * @param itms the kernel set of the state we are looking for.
+ */
+ public static lalr_state find_state(lalr_item_set itms)
+ {
+ if (itms == null)
+ return null;
+ else
+ return (lalr_state)_all.get(itms);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Static counter for assigning unique state indexes. */
+ protected static int next_index = 0;
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The item set for this state. */
+ protected lalr_item_set _items;
+
+ /** The item set for this state. */
+ public lalr_item_set items() {return _items;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** List of transitions out of this state. */
+ protected lalr_transition _transitions = null;
+
+ /** List of transitions out of this state. */
+ public lalr_transition transitions() {return _transitions;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Index of this state in the parse tables */
+ protected int _index;
+
+ /** Index of this state in the parse tables */
+ public int index() {return _index;}
+
+ /*-----------------------------------------------------------*/
+ /*--- Static Methods ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Helper routine for debugging -- produces a dump of the given state
+ * onto System.out.
+ */
+ protected static void dump_state(lalr_state st) throws internal_error
+ {
+ lalr_item_set itms;
+ lalr_item itm;
+ production_part part;
+
+ if (st == null)
+ {
+ System.out.println("NULL lalr_state");
+ return;
+ }
+
+ System.out.println("lalr_state [" + st.index() + "] {");
+ itms = st.items();
+ for (Enumeration e = itms.all(); e.hasMoreElements(); )
+ {
+ itm = (lalr_item)e.nextElement();
+ System.out.print(" [");
+ System.out.print(itm.the_production().lhs().the_symbol().name());
+ System.out.print(" ::= ");
+ for (int i = 0; i<itm.the_production().rhs_length(); i++)
+ {
+ if (i == itm.dot_pos()) System.out.print("(*) ");
+ part = itm.the_production().rhs(i);
+ if (part.is_action())
+ System.out.print("{action} ");
+ else
+ System.out.print(((symbol_part)part).the_symbol().name() + " ");
+ }
+ if (itm.dot_at_end()) System.out.print("(*) ");
+ System.out.println("]");
+ }
+ System.out.println("}");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Propagate lookahead sets through the constructed viable prefix
+ * recognizer. When the machine is constructed, each item that results
+ in the creation of another such that its lookahead is included in the
+ other's will have a propagate link set up for it. This allows additions
+ to the lookahead of one item to be included in other items that it
+ was used to directly or indirectly create.
+ */
+ protected static void propagate_all_lookaheads() throws internal_error
+ {
+ /* iterate across all states */
+ for (Enumeration st = all(); st.hasMoreElements(); )
+ {
+ /* propagate lookaheads out of that state */
+ ((lalr_state)st.nextElement()).propagate_lookaheads();
+ }
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Add a transition out of this state to another.
+ * @param on_sym the symbol the transition is under.
+ * @param to_st the state the transition goes to.
+ */
+ public void add_transition(symbol on_sym, lalr_state to_st)
+ throws internal_error
+ {
+ lalr_transition trans;
+
+ /* create a new transition object and put it in our list */
+ trans = new lalr_transition(on_sym, to_st, _transitions);
+ _transitions = trans;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Build an LALR viable prefix recognition machine given a start
+ * production. This method operates by first building a start state
+ * from the start production (based on a single item with the dot at
+ * the beginning and EOF as expected lookahead). Then for each state
+ * it attempts to extend the machine by creating transitions out of
+ * the state to new or existing states. When considering extension
+ * from a state we make a transition on each symbol that appears before
+ * the dot in some item. For example, if we have the items: <pre>
+ * [A ::= a b * X c, {d,e}]
+ * [B ::= a b * X d, {a,b}]
+ * </pre>
+ * in some state, then we would be making a transition under X to a new
+ * state. This new state would be formed by a "kernel" of items
+ * corresponding to moving the dot past the X. In this case: <pre>
+ * [A ::= a b X * c, {d,e}]
+ * [B ::= a b X * Y, {a,b}]
+ * </pre>
+ * The full state would then be formed by "closing" this kernel set of
+ * items so that it included items that represented productions of things
+ * the parser was now looking for. In this case we would items
+ * corresponding to productions of Y, since various forms of Y are expected
+ * next when in this state (see lalr_item_set.compute_closure() for details
+ * on closure). <p>
+ *
+ * The process of building the viable prefix recognizer terminates when no
+ * new states can be added. However, in order to build a smaller number of
+ * states (i.e., corresponding to LALR rather than canonical LR) the state
+ * building process does not maintain full loookaheads in all items.
+ * Consequently, after the machine is built, we go back and propagate
+ * lookaheads through the constructed machine using a call to
+ * propagate_all_lookaheads(). This makes use of propagation links
+ * constructed during the closure and transition process.
+ *
+ * @param start_prod the start production of the grammar
+ * @see java_cup.lalr_item_set#compute_closure
+ * @see java_cup.lalr_state#propagate_all_lookaheads
+ */
+
+ public static lalr_state build_machine(production start_prod)
+ throws internal_error
+ {
+ lalr_state start_state;
+ lalr_item_set start_items;
+ lalr_item_set new_items;
+ lalr_item_set linked_items;
+ lalr_item_set kernel;
+ Stack work_stack = new Stack();
+ lalr_state st, new_st;
+ symbol_set outgoing;
+ lalr_item itm, new_itm, existing, fix_itm;
+ symbol sym, sym2;
+ Enumeration i, s, fix;
+
+ /* sanity check */
+ if (start_prod == null)
+ throw new internal_error(
+ "Attempt to build viable prefix recognizer using a null production");
+
+ /* build item with dot at front of start production and EOF lookahead */
+ start_items = new lalr_item_set();
+
+ itm = new lalr_item(start_prod);
+ itm.lookahead().add(terminal.EOF);
+
+ start_items.add(itm);
+
+ /* create copy the item set to form the kernel */
+ kernel = new lalr_item_set(start_items);
+
+ /* create the closure from that item set */
+ start_items.compute_closure();
+
+ /* build a state out of that item set and put it in our work set */
+ start_state = new lalr_state(start_items);
+ work_stack.push(start_state);
+
+ /* enter the state using the kernel as the key */
+ _all_kernels.put(kernel, start_state);
+
+ /* continue looking at new states until we have no more work to do */
+ while (!work_stack.empty())
+ {
+ /* remove a state from the work set */
+ st = (lalr_state)work_stack.pop();
+
+ /* gather up all the symbols that appear before dots */
+ outgoing = new symbol_set();
+ for (i = st.items().all(); i.hasMoreElements(); )
+ {
+ itm = (lalr_item)i.nextElement();
+
+ /* add the symbol before the dot (if any) to our collection */
+ sym = itm.symbol_after_dot();
+ if (sym != null) outgoing.add(sym);
+ }
+
+ /* now create a transition out for each individual symbol */
+ for (s = outgoing.all(); s.hasMoreElements(); )
+ {
+ sym = (symbol)s.nextElement();
+
+ /* will be keeping the set of items with propagate links */
+ linked_items = new lalr_item_set();
+
+ /* gather up shifted versions of all the items that have this
+ symbol before the dot */
+ new_items = new lalr_item_set();
+ for (i = st.items().all(); i.hasMoreElements();)
+ {
+ itm = (lalr_item)i.nextElement();
+
+ /* if this is the symbol we are working on now, add to set */
+ sym2 = itm.symbol_after_dot();
+ if (sym.equals(sym2))
+ {
+ /* add to the kernel of the new state */
+ new_items.add(itm.shift());
+
+ /* remember that itm has propagate link to it */
+ linked_items.add(itm);
+ }
+ }
+
+ /* use new items as state kernel */
+ kernel = new lalr_item_set(new_items);
+
+ /* have we seen this one already? */
+ new_st = (lalr_state)_all_kernels.get(kernel);
+
+ /* if we haven't, build a new state out of the item set */
+ if (new_st == null)
+ {
+ /* compute closure of the kernel for the full item set */
+ new_items.compute_closure();
+
+ /* build the new state */
+ new_st = new lalr_state(new_items);
+
+ /* add the new state to our work set */
+ work_stack.push(new_st);
+
+ /* put it in our kernel table */
+ _all_kernels.put(kernel, new_st);
+ }
+ /* otherwise relink propagation to items in existing state */
+ else
+ {
+ /* walk through the items that have links to the new state */
+ for (fix = linked_items.all(); fix.hasMoreElements(); )
+ {
+ fix_itm = (lalr_item)fix.nextElement();
+
+ /* look at each propagate link out of that item */
+ for (int l =0; l < fix_itm.propagate_items().size(); l++)
+ {
+ /* pull out item linked to in the new state */
+ new_itm =
+ (lalr_item)fix_itm.propagate_items().elementAt(l);
+
+ /* find corresponding item in the existing state */
+ existing = new_st.items().find(new_itm);
+
+ /* fix up the item so it points to the existing set */
+ if (existing != null)
+ fix_itm.propagate_items().setElementAt(existing ,l);
+ }
+ }
+ }
+
+ /* add a transition from current state to that state */
+ st.add_transition(sym, new_st);
+ }
+ }
+
+ /* all done building states */
+
+ /* propagate complete lookahead sets throughout the states */
+ propagate_all_lookaheads();
+
+ return start_state;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Propagate lookahead sets out of this state. This recursively
+ * propagates to all items that have propagation links from some item
+ * in this state.
+ */
+ protected void propagate_lookaheads() throws internal_error
+ {
+ /* recursively propagate out from each item in the state */
+ for (Enumeration itm = items().all(); itm.hasMoreElements(); )
+ ((lalr_item)itm.nextElement()).propagate_lookaheads(null);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Fill in the parse table entries for this state. There are two
+ * parse tables that encode the viable prefix recognition machine, an
+ * action table and a reduce-goto table. The rows in each table
+ * correspond to states of the machine. The columns of the action table
+ * are indexed by terminal symbols and correspond to either transitions
+ * out of the state (shift entries) or reductions from the state to some
+ * previous state saved on the stack (reduce entries). All entries in the
+ * action table that are not shifts or reduces, represent errors. The
+ * reduce-goto table is indexed by non terminals and represents transitions
+ * out of a state on that non-terminal.<p>
+ * Conflicts occur if more than one action needs to go in one entry of the
+ * action table (this cannot happen with the reduce-goto table). Conflicts
+ * are resolved by always shifting for shift/reduce conflicts and choosing
+ * the lowest numbered production (hence the one that appeared first in
+ * the specification) in reduce/reduce conflicts. All conflicts are
+ * reported and if more conflicts are detected than were declared by the
+ * user, code generation is aborted.
+ *
+ * @param act_table the action table to put entries in.
+ * @param reduce_table the reduce-goto table to put entries in.
+ */
+ public void build_table_entries(
+ parse_action_table act_table,
+ parse_reduce_table reduce_table)
+ throws internal_error
+ {
+ parse_action_row our_act_row;
+ parse_reduce_row our_red_row;
+ lalr_item itm;
+ parse_action act, other_act;
+ symbol sym;
+ terminal_set conflict_set = new terminal_set();
+
+ /* pull out our rows from the tables */
+ our_act_row = act_table.under_state[index()];
+ our_red_row = reduce_table.under_state[index()];
+
+ /* consider each item in our state */
+ for (Enumeration i = items().all(); i.hasMoreElements(); )
+ {
+ itm = (lalr_item)i.nextElement();
+
+
+ /* if its completed (dot at end) then reduce under the lookahead */
+ if (itm.dot_at_end())
+ {
+ act = new reduce_action(itm.the_production());
+
+ /* consider each lookahead symbol */
+ for (int t = 0; t < terminal.number(); t++)
+ {
+ /* skip over the ones not in the lookahead */
+ if (!itm.lookahead().contains(t)) continue;
+
+ /* if we don't already have an action put this one in */
+ if (our_act_row.under_term[t].kind() ==
+ parse_action.ERROR)
+ {
+ our_act_row.under_term[t] = act;
+ }
+ else
+ {
+ /* we now have at least one conflict */
+ terminal term = terminal.find(t);
+ other_act = our_act_row.under_term[t];
+
+ /* if the other act was not a shift */
+ if ((other_act.kind() != parse_action.SHIFT) &&
+ (other_act.kind() != parse_action.NONASSOC))
+ {
+ /* if we have lower index hence priority, replace it*/
+ if (itm.the_production().index() <
+ ((reduce_action)other_act).reduce_with().index())
+ {
+ /* replace the action */
+ our_act_row.under_term[t] = act;
+ }
+ } else {
+ /* Check precedences,see if problem is correctable */
+ if(fix_with_precedence(itm.the_production(),
+ t, our_act_row, act)) {
+ term = null;
+ }
+ }
+ if(term!=null) {
+
+ conflict_set.add(term);
+ }
+ }
+ }
+ }
+ }
+
+ /* consider each outgoing transition */
+ for (lalr_transition trans=transitions(); trans!=null; trans=trans.next())
+ {
+ /* if its on an terminal add a shift entry */
+ sym = trans.on_symbol();
+ if (!sym.is_non_term())
+ {
+ act = new shift_action(trans.to_state());
+
+ /* if we don't already have an action put this one in */
+ if ( our_act_row.under_term[sym.index()].kind() ==
+ parse_action.ERROR)
+ {
+ our_act_row.under_term[sym.index()] = act;
+ }
+ else
+ {
+ /* we now have at least one conflict */
+ production p = ((reduce_action)our_act_row.under_term[sym.index()]).reduce_with();
+
+ /* shift always wins */
+ if (!fix_with_precedence(p, sym.index(), our_act_row, act)) {
+ our_act_row.under_term[sym.index()] = act;
+ conflict_set.add(terminal.find(sym.index()));
+ }
+ }
+ }
+ else
+ {
+ /* for non terminals add an entry to the reduce-goto table */
+ our_red_row.under_non_term[sym.index()] = trans.to_state();
+ }
+ }
+
+ /* if we end up with conflict(s), report them */
+ if (!conflict_set.empty())
+ report_conflicts(conflict_set);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+
+ /** Procedure that attempts to fix a shift/reduce error by using
+ * precedences. --frankf 6/26/96
+ *
+ * if a production (also called rule) or the lookahead terminal
+ * has a precedence, then the table can be fixed. if the rule
+ * has greater precedence than the terminal, a reduce by that rule
+ * in inserted in the table. If the terminal has a higher precedence,
+ * it is shifted. if they have equal precedence, then the associativity
+ * of the precedence is used to determine what to put in the table:
+ * if the precedence is left associative, the action is to reduce.
+ * if the precedence is right associative, the action is to shift.
+ * if the precedence is non associative, then it is a syntax error.
+ *
+ * @param p the production
+ * @param term_index the index of the lokahead terminal
+ * @param parse_action_row a row of the action table
+ * @param act the rule in conflict with the table entry
+ */
+
+ protected boolean fix_with_precedence(
+ production p,
+ int term_index,
+ parse_action_row table_row,
+ parse_action act)
+
+ throws internal_error {
+
+ terminal term = terminal.find(term_index);
+
+ /* if the production has a precedence number, it can be fixed */
+ if (p.precedence_num() > assoc.no_prec) {
+
+ /* if production precedes terminal, put reduce in table */
+ if (p.precedence_num() > term.precedence_num()) {
+ table_row.under_term[term_index] =
+ insert_reduce(table_row.under_term[term_index],act);
+ return true;
+ }
+
+ /* if terminal precedes rule, put shift in table */
+ else if (p.precedence_num() < term.precedence_num()) {
+ table_row.under_term[term_index] =
+ insert_shift(table_row.under_term[term_index],act);
+ return true;
+ }
+ else { /* they are == precedence */
+
+ /* equal precedences have equal sides, so only need to
+ look at one: if it is right, put shift in table */
+ if (term.precedence_side() == assoc.right) {
+ table_row.under_term[term_index] =
+ insert_shift(table_row.under_term[term_index],act);
+ return true;
+ }
+
+ /* if it is left, put reduce in table */
+ else if (term.precedence_side() == assoc.left) {
+ table_row.under_term[term_index] =
+ insert_reduce(table_row.under_term[term_index],act);
+ return true;
+ }
+
+ /* if it is nonassoc, we're not allowed to have two nonassocs
+ of equal precedence in a row, so put in NONASSOC */
+ else if (term.precedence_side() == assoc.nonassoc) {
+ table_row.under_term[term_index] = new nonassoc_action();
+ return true;
+ } else {
+ /* something really went wrong */
+ throw new internal_error("Unable to resolve conflict correctly");
+ }
+ }
+ }
+ /* check if terminal has precedence, if so, shift, since
+ rule does not have precedence */
+ else if (term.precedence_num() > assoc.no_prec) {
+ table_row.under_term[term_index] =
+ insert_shift(table_row.under_term[term_index],act);
+ return true;
+ }
+
+ /* otherwise, neither the rule nor the terminal has a precedence,
+ so it can't be fixed. */
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+
+ /* given two actions, and an action type, return the
+ action of that action type. give an error if they are of
+ the same action, because that should never have tried
+ to be fixed
+
+ */
+ protected parse_action insert_action(
+ parse_action a1,
+ parse_action a2,
+ int act_type)
+ throws internal_error
+ {
+ if ((a1.kind() == act_type) && (a2.kind() == act_type)) {
+ throw new internal_error("Conflict resolution of bogus actions");
+ } else if (a1.kind() == act_type) {
+ return a1;
+ } else if (a2.kind() == act_type) {
+ return a2;
+ } else {
+ throw new internal_error("Conflict resolution of bogus actions");
+ }
+ }
+
+ /* find the shift in the two actions */
+ protected parse_action insert_shift(
+ parse_action a1,
+ parse_action a2)
+ throws internal_error
+ {
+ return insert_action(a1, a2, parse_action.SHIFT);
+ }
+
+ /* find the reduce in the two actions */
+ protected parse_action insert_reduce(
+ parse_action a1,
+ parse_action a2)
+ throws internal_error
+ {
+ return insert_action(a1, a2, parse_action.REDUCE);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce warning messages for all conflicts found in this state. */
+ protected void report_conflicts(terminal_set conflict_set)
+ throws internal_error
+ {
+ lalr_item itm, compare;
+ symbol shift_sym;
+
+ boolean after_itm;
+
+ /* consider each element */
+ for (Enumeration itms = items().all(); itms.hasMoreElements(); )
+ {
+ itm = (lalr_item)itms.nextElement();
+
+ /* clear the S/R conflict set for this item */
+
+ /* if it results in a reduce, it could be a conflict */
+ if (itm.dot_at_end())
+ {
+ /* not yet after itm */
+ after_itm = false;
+
+ /* compare this item against all others looking for conflicts */
+ for (Enumeration comps = items().all(); comps.hasMoreElements(); )
+ {
+ compare = (lalr_item)comps.nextElement();
+
+ /* if this is the item, next one is after it */
+ if (itm == compare) after_itm = true;
+
+ /* only look at it if its not the same item */
+ if (itm != compare)
+ {
+ /* is it a reduce */
+ if (compare.dot_at_end())
+ {
+ /* only look at reduces after itm */
+ if (after_itm)
+ /* does the comparison item conflict? */
+ if (compare.lookahead().intersects(itm.lookahead()))
+ /* report a reduce/reduce conflict */
+ report_reduce_reduce(itm, compare);
+ }
+ }
+ }
+ /* report S/R conflicts under all the symbols we conflict under */
+ for (int t = 0; t < terminal.number(); t++)
+ if (conflict_set.contains(t))
+ report_shift_reduce(itm,t);
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a warning message for one reduce/reduce conflict.
+ *
+ * @param itm1 first item in conflict.
+ * @param itm2 second item in conflict.
+ */
+ protected void report_reduce_reduce(lalr_item itm1, lalr_item itm2)
+ throws internal_error
+ {
+ boolean comma_flag = false;
+
+ System.err.println("*** Reduce/Reduce conflict found in state #"+index());
+ System.err.print (" between ");
+ System.err.println(itm1.to_simple_string());
+ System.err.print (" and ");
+ System.err.println(itm2.to_simple_string());
+ System.err.print(" under symbols: {" );
+ for (int t = 0; t < terminal.number(); t++)
+ {
+ if (itm1.lookahead().contains(t) && itm2.lookahead().contains(t))
+ {
+ if (comma_flag) System.err.print(", "); else comma_flag = true;
+ System.err.print(terminal.find(t).name());
+ }
+ }
+ System.err.println("}");
+ System.err.print(" Resolved in favor of ");
+ if (itm1.the_production().index() < itm2.the_production().index())
+ System.err.println("the first production.\n");
+ else
+ System.err.println("the second production.\n");
+
+ /* count the conflict */
+ emit.num_conflicts++;
+ lexer.warning_count++;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a warning message for one shift/reduce conflict.
+ *
+ * @param red_itm the item with the reduce.
+ * @param conflict_sym the index of the symbol conflict occurs under.
+ */
+ protected void report_shift_reduce(
+ lalr_item red_itm,
+ int conflict_sym)
+ throws internal_error
+ {
+ lalr_item itm;
+ symbol shift_sym;
+
+ /* emit top part of message including the reduce item */
+ System.err.println("*** Shift/Reduce conflict found in state #"+index());
+ System.err.print (" between ");
+ System.err.println(red_itm.to_simple_string());
+
+ /* find and report on all items that shift under our conflict symbol */
+ for (Enumeration itms = items().all(); itms.hasMoreElements(); )
+ {
+ itm = (lalr_item)itms.nextElement();
+
+ /* only look if its not the same item and not a reduce */
+ if (itm != red_itm && !itm.dot_at_end())
+ {
+ /* is it a shift on our conflicting terminal */
+ shift_sym = itm.symbol_after_dot();
+ if (!shift_sym.is_non_term() && shift_sym.index() == conflict_sym)
+ {
+ /* yes, report on it */
+ System.err.println(" and " + itm.to_simple_string());
+ }
+ }
+ }
+ System.err.println(" under symbol "+ terminal.find(conflict_sym).name());
+ System.err.println(" Resolved in favor of shifting.\n");
+
+ /* count the conflict */
+ emit.num_conflicts++;
+ lexer.warning_count++;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(lalr_state other)
+ {
+ /* we are equal if our item sets are equal */
+ return other != null && items().equals(other.items());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof lalr_state))
+ return false;
+ else
+ return equals((lalr_state)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a hash code. */
+ public int hashCode()
+ {
+ /* just use the item set hash code */
+ return items().hashCode();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+ lalr_transition tr;
+
+ /* dump the item set */
+ result = "lalr_state [" + index() + "]: " + _items + "\n";
+
+ /* do the transitions */
+ for (tr = transitions(); tr != null; tr = tr.next())
+ {
+ result += tr;
+ result += "\n";
+ }
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+}
diff --git a/src/syntaxParser/java_cup/SAVE/lalr_transition.java b/src/syntaxParser/java_cup/SAVE/lalr_transition.java
new file mode 100644
index 0000000..1c941bd
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/lalr_transition.java
@@ -0,0 +1,93 @@
+package java_cup;
+
+/** This class represents a transition in an LALR viable prefix recognition
+ * machine. Transitions can be under terminals for non-terminals. They are
+ * internally linked together into singly linked lists containing all the
+ * transitions out of a single state via the _next field.
+ *
+ * @see java_cup.lalr_state
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ *
+ */
+public class lalr_transition {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param on_sym symbol we are transitioning on.
+ * @param to_st state we transition to.
+ * @param nxt next transition in linked list.
+ */
+ public lalr_transition(symbol on_sym, lalr_state to_st, lalr_transition nxt)
+ throws internal_error
+ {
+ /* sanity checks */
+ if (on_sym == null)
+ throw new internal_error("Attempt to create transition on null symbol");
+ if (to_st == null)
+ throw new internal_error("Attempt to create transition to null state");
+
+ /* initialize */
+ _on_symbol = on_sym;
+ _to_state = to_st;
+ _next = nxt;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with null next.
+ * @param on_sym symbol we are transitioning on.
+ * @param to_st state we transition to.
+ */
+ public lalr_transition(symbol on_sym, lalr_state to_st) throws internal_error
+ {
+ this(on_sym, to_st, null);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The symbol we make the transition on. */
+ protected symbol _on_symbol;
+
+ /** The symbol we make the transition on. */
+ public symbol on_symbol() {return _on_symbol;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The state we transition to. */
+ protected lalr_state _to_state;
+
+ /** The state we transition to. */
+ public lalr_state to_state() {return _to_state;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Next transition in linked list of transitions out of a state */
+ protected lalr_transition _next;
+
+ /** Next transition in linked list of transitions out of a state */
+ public lalr_transition next() {return _next;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+
+ result = "transition on " + on_symbol().name() + " to state [";
+ result += _to_state.index();
+ result += "]";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+}
diff --git a/src/syntaxParser/java_cup/SAVE/lexer.java b/src/syntaxParser/java_cup/SAVE/lexer.java
new file mode 100644
index 0000000..2230d12
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/lexer.java
@@ -0,0 +1,543 @@
+package java_cup;
+
+import java_cup.runtime.Symbol;
+import java.util.Hashtable;
+
+/** This class implements a small scanner (aka lexical analyzer or lexer) for
+ * the JavaCup specification. This scanner reads characters from standard
+ * input (System.in) and returns integers corresponding to the terminal
+ * number of the next Symbol. Once end of input is reached the EOF Symbol is
+ * returned on every subsequent call.<p>
+ * Symbols currently returned include: <pre>
+ * Symbol Constant Returned Symbol Constant Returned
+ * ------ ----------------- ------ -----------------
+ * "package" PACKAGE "import" IMPORT
+ * "code" CODE "action" ACTION
+ * "parser" PARSER "terminal" TERMINAL
+ * "non" NON "init" INIT
+ * "scan" SCAN "with" WITH
+ * "start" START "precedence" PRECEDENCE
+ * "left" LEFT "right" RIGHT
+ * "nonassoc" NONASSOC "%prec PRECENT_PREC
+ * [ LBRACK ] RBRACK
+ * ; SEMI
+ * , COMMA * STAR
+ * . DOT : COLON
+ * ::= COLON_COLON_EQUALS | BAR
+ * identifier ID {:...:} CODE_STRING
+ * "nonterminal" NONTERMINAL
+ * </pre>
+ * All symbol constants are defined in sym.java which is generated by
+ * JavaCup from parser.cup.<p>
+ *
+ * In addition to the scanner proper (called first via init() then with
+ * next_token() to get each Symbol) this class provides simple error and
+ * warning routines and keeps a count of errors and warnings that is
+ * publicly accessible.<p>
+ *
+ * This class is "static" (i.e., it has only static members and methods).
+ *
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+public class lexer {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The only constructor is private, so no instances can be created. */
+ private lexer() { }
+
+ /*-----------------------------------------------------------*/
+ /*--- Static (Class) Variables ------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** First character of lookahead. */
+ protected static int next_char;
+
+ /** Second character of lookahead. */
+ protected static int next_char2;
+
+ /** Second character of lookahead. */
+ protected static int next_char3;
+
+ /** Second character of lookahead. */
+ protected static int next_char4;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** EOF constant. */
+ protected static final int EOF_CHAR = -1;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Table of keywords. Keywords are initially treated as identifiers.
+ * Just before they are returned we look them up in this table to see if
+ * they match one of the keywords. The string of the name is the key here,
+ * which indexes Integer objects holding the symbol number.
+ */
+ protected static Hashtable keywords = new Hashtable(23);
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Table of single character symbols. For ease of implementation, we
+ * store all unambiguous single character Symbols in this table of Integer
+ * objects keyed by Integer objects with the numerical value of the
+ * appropriate char (currently Character objects have a bug which precludes
+ * their use in tables).
+ */
+ protected static Hashtable char_symbols = new Hashtable(11);
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Current line number for use in error messages. */
+ protected static int current_line = 1;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Character position in current line. */
+ protected static int current_position = 1;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Character position in current line. */
+ protected static int absolute_position = 1;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of total errors detected so far. */
+ public static int error_count = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of warnings issued so far */
+ public static int warning_count = 0;
+
+ /*-----------------------------------------------------------*/
+ /*--- Static Methods ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Initialize the scanner. This sets up the keywords and char_symbols
+ * tables and reads the first two characters of lookahead.
+ */
+ public static void init() throws java.io.IOException
+ {
+ /* set up the keyword table */
+ keywords.put("package", new Integer(sym.PACKAGE));
+ keywords.put("import", new Integer(sym.IMPORT));
+ keywords.put("code", new Integer(sym.CODE));
+ keywords.put("action", new Integer(sym.ACTION));
+ keywords.put("parser", new Integer(sym.PARSER));
+ keywords.put("terminal", new Integer(sym.TERMINAL));
+ keywords.put("non", new Integer(sym.NON));
+ keywords.put("nonterminal",new Integer(sym.NONTERMINAL));// [CSA]
+ keywords.put("init", new Integer(sym.INIT));
+ keywords.put("scan", new Integer(sym.SCAN));
+ keywords.put("with", new Integer(sym.WITH));
+ keywords.put("start", new Integer(sym.START));
+ keywords.put("precedence", new Integer(sym.PRECEDENCE));
+ keywords.put("left", new Integer(sym.LEFT));
+ keywords.put("right", new Integer(sym.RIGHT));
+ keywords.put("nonassoc", new Integer(sym.NONASSOC));
+
+ /* set up the table of single character symbols */
+ char_symbols.put(new Integer(';'), new Integer(sym.SEMI));
+ char_symbols.put(new Integer(','), new Integer(sym.COMMA));
+ char_symbols.put(new Integer('*'), new Integer(sym.STAR));
+ char_symbols.put(new Integer('.'), new Integer(sym.DOT));
+ char_symbols.put(new Integer('|'), new Integer(sym.BAR));
+ char_symbols.put(new Integer('['), new Integer(sym.LBRACK));
+ char_symbols.put(new Integer(']'), new Integer(sym.RBRACK));
+
+ /* read two characters of lookahead */
+ next_char = System.in.read();
+ if (next_char == EOF_CHAR) {
+ next_char2 = EOF_CHAR;
+ next_char3 = EOF_CHAR;
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char2 = System.in.read();
+ if (next_char2 == EOF_CHAR) {
+ next_char3 = EOF_CHAR;
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char3 = System.in.read();
+ if (next_char3 == EOF_CHAR) {
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char4 = System.in.read();
+ }
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Advance the scanner one character in the input stream. This moves
+ * next_char2 to next_char and then reads a new next_char2.
+ */
+ protected static void advance() throws java.io.IOException
+ {
+ int old_char;
+
+ old_char = next_char;
+ next_char = next_char2;
+ if (next_char == EOF_CHAR) {
+ next_char2 = EOF_CHAR;
+ next_char3 = EOF_CHAR;
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char2 = next_char3;
+ if (next_char2 == EOF_CHAR) {
+ next_char3 = EOF_CHAR;
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char3 = next_char4;
+ if (next_char3 == EOF_CHAR) {
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char4 = System.in.read();
+ }
+ }
+ }
+
+ /* count this */
+ absolute_position++;
+ current_position++;
+ if (old_char == '\n' || (old_char == '\r' && next_char!='\n'))
+ {
+ current_line++;
+ current_position = 1;
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit an error message. The message will be marked with both the
+ * current line number and the position in the line. Error messages
+ * are printed on standard error (System.err).
+ * @param message the message to print.
+ */
+ public static void emit_error(String message)
+ {
+ System.err.println("Error at " + current_line + "(" + current_position +
+ "): " + message);
+ error_count++;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit a warning message. The message will be marked with both the
+ * current line number and the position in the line. Messages are
+ * printed on standard error (System.err).
+ * @param message the message to print.
+ */
+ public static void emit_warn(String message)
+ {
+ System.err.println("Warning at " + current_line + "(" + current_position +
+ "): " + message);
+ warning_count++;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if a character is ok to start an id.
+ * @param ch the character in question.
+ */
+ protected static boolean id_start_char(int ch)
+ {
+ /* allow for % in identifiers. a hack to allow my
+ %prec in. Should eventually make lex spec for this
+ frankf */
+ return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
+ (ch == '_');
+
+ // later need to deal with non-8-bit chars here
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if a character is ok for the middle of an id.
+ * @param ch the character in question.
+ */
+ protected static boolean id_char(int ch)
+ {
+ return id_start_char(ch) || (ch >= '0' && ch <= '9');
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Try to look up a single character symbol, returns -1 for not found.
+ * @param ch the character in question.
+ */
+ protected static int find_single_char(int ch)
+ {
+ Integer result;
+
+ result = (Integer)char_symbols.get(new Integer((char)ch));
+ if (result == null)
+ return -1;
+ else
+ return result.intValue();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Handle swallowing up a comment. Both old style C and new style C++
+ * comments are handled.
+ */
+ protected static void swallow_comment() throws java.io.IOException
+ {
+ /* next_char == '/' at this point */
+
+ /* is it a traditional comment */
+ if (next_char2 == '*')
+ {
+ /* swallow the opener */
+ advance(); advance();
+
+ /* swallow the comment until end of comment or EOF */
+ for (;;)
+ {
+ /* if its EOF we have an error */
+ if (next_char == EOF_CHAR)
+ {
+ emit_error("Specification file ends inside a comment");
+ return;
+ }
+
+ /* if we can see the closer we are done */
+ if (next_char == '*' && next_char2 == '/')
+ {
+ advance();
+ advance();
+ return;
+ }
+
+ /* otherwise swallow char and move on */
+ advance();
+ }
+ }
+
+ /* is its a new style comment */
+ if (next_char2 == '/')
+ {
+ /* swallow the opener */
+ advance(); advance();
+
+ /* swallow to '\n', '\r', '\f', or EOF */
+ while (next_char != '\n' && next_char != '\r' &&
+ next_char != '\f' && next_char!=EOF_CHAR)
+ advance();
+
+ return;
+
+ }
+
+ /* shouldn't get here, but... if we get here we have an error */
+ emit_error("Malformed comment in specification -- ignored");
+ advance();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Swallow up a code string. Code strings begin with "{:" and include
+ all characters up to the first occurrence of ":}" (there is no way to
+ include ":}" inside a code string). The routine returns a String
+ object suitable for return by the scanner.
+ */
+ protected static Symbol do_code_string() throws java.io.IOException
+ {
+ StringBuffer result = new StringBuffer();
+
+ /* at this point we have lookahead of "{:" -- swallow that */
+ advance(); advance();
+
+ /* save chars until we see ":}" */
+ while (!(next_char == ':' && next_char2 == '}'))
+ {
+ /* if we have run off the end issue a message and break out of loop */
+ if (next_char == EOF_CHAR)
+ {
+ emit_error("Specification file ends inside a code string");
+ break;
+ }
+
+ /* otherwise record the char and move on */
+ result.append(new Character((char)next_char));
+ advance();
+ }
+
+ /* advance past the closer and build a return Symbol */
+ advance(); advance();
+ return new Symbol(sym.CODE_STRING, result.toString());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Process an identifier. Identifiers begin with a letter, underscore,
+ * or dollar sign, which is followed by zero or more letters, numbers,
+ * underscores or dollar signs. This routine returns a String suitable
+ * for return by the scanner.
+ */
+ protected static Symbol do_id() throws java.io.IOException
+ {
+ StringBuffer result = new StringBuffer();
+ String result_str;
+ Integer keyword_num;
+ char buffer[] = new char[1];
+
+ /* next_char holds first character of id */
+ buffer[0] = (char)next_char;
+ result.append(buffer,0,1);
+ advance();
+
+ /* collect up characters while they fit in id */
+ while(id_char(next_char))
+ {
+ buffer[0] = (char)next_char;
+ result.append(buffer,0,1);
+ advance();
+ }
+
+ /* extract a string and try to look it up as a keyword */
+ result_str = result.toString();
+ keyword_num = (Integer)keywords.get(result_str);
+
+ /* if we found something, return that keyword */
+ if (keyword_num != null)
+ return new Symbol(keyword_num.intValue());
+
+ /* otherwise build and return an id Symbol with an attached string */
+ return new Symbol(sym.ID, result_str);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return one Symbol. This is the main external interface to the scanner.
+ * It consumes sufficient characters to determine the next input Symbol
+ * and returns it. To help with debugging, this routine actually calls
+ * real_next_token() which does the work. If you need to debug the
+ * parser, this can be changed to call debug_next_token() which prints
+ * a debugging message before returning the Symbol.
+ */
+ public static Symbol next_token() throws java.io.IOException
+ {
+ return real_next_token();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Debugging version of next_token(). This routine calls the real scanning
+ * routine, prints a message on System.out indicating what the Symbol is,
+ * then returns it.
+ */
+ public static Symbol debug_next_token() throws java.io.IOException
+ {
+ Symbol result = real_next_token();
+ System.out.println("# next_Symbol() => " + result.sym);
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The actual routine to return one Symbol. This is normally called from
+ * next_token(), but for debugging purposes can be called indirectly from
+ * debug_next_token().
+ */
+ protected static Symbol real_next_token() throws java.io.IOException
+ {
+ int sym_num;
+
+ for (;;)
+ {
+ /* look for white space */
+ if (next_char == ' ' || next_char == '\t' || next_char == '\n' ||
+ next_char == '\f' || next_char == '\r')
+ {
+ /* advance past it and try the next character */
+ advance();
+ continue;
+ }
+
+ /* look for a single character symbol */
+ sym_num = find_single_char(next_char);
+ if (sym_num != -1)
+ {
+ /* found one -- advance past it and return a Symbol for it */
+ advance();
+ return new Symbol(sym_num);
+ }
+
+ /* look for : or ::= */
+ if (next_char == ':')
+ {
+ /* if we don't have a second ':' return COLON */
+ if (next_char2 != ':')
+ {
+ advance();
+ return new Symbol(sym.COLON);
+ }
+
+ /* move forward and look for the '=' */
+ advance();
+ if (next_char2 == '=')
+ {
+ advance(); advance();
+ return new Symbol(sym.COLON_COLON_EQUALS);
+ }
+ else
+ {
+ /* return just the colon (already consumed) */
+ return new Symbol(sym.COLON);
+ }
+ }
+
+ /* find a "%prec" string and return it. otherwise, a '%' was found,
+ which has no right being in the specification otherwise */
+ if (next_char == '%') {
+ advance();
+ if ((next_char == 'p') && (next_char2 == 'r') && (next_char3 == 'e') &&
+ (next_char4 == 'c')) {
+ advance();
+ advance();
+ advance();
+ advance();
+ return new Symbol(sym.PERCENT_PREC);
+ } else {
+ emit_error("Found extraneous percent sign");
+ }
+ }
+
+ /* look for a comment */
+ if (next_char == '/' && (next_char2 == '*' || next_char2 == '/'))
+ {
+ /* swallow then continue the scan */
+ swallow_comment();
+ continue;
+ }
+
+ /* look for start of code string */
+ if (next_char == '{' && next_char2 == ':')
+ return do_code_string();
+
+ /* look for an id or keyword */
+ if (id_start_char(next_char)) return do_id();
+
+ /* look for EOF */
+ if (next_char == EOF_CHAR) return new Symbol(sym.EOF);
+
+ /* if we get here, we have an unrecognized character */
+ emit_warn("Unrecognized character '" +
+ new Character((char)next_char) + "'(" + next_char +
+ ") -- ignored");
+
+ /* advance past it */
+ advance();
+ }
+ }
+
+ /*-----------------------------------------------------------*/
+}
+
diff --git a/src/syntaxParser/java_cup/SAVE/lr_item_core.java b/src/syntaxParser/java_cup/SAVE/lr_item_core.java
new file mode 100644
index 0000000..c0fa656
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/lr_item_core.java
@@ -0,0 +1,280 @@
+
+package java_cup;
+
+/** The "core" of an LR item. This includes a production and the position
+ * of a marker (the "dot") within the production. Typically item cores
+ * are written using a production with an embedded "dot" to indicate their
+ * position. For example: <pre>
+ * A ::= B * C d E
+ * </pre>
+ * This represents a point in a parse where the parser is trying to match
+ * the given production, and has succeeded in matching everything before the
+ * "dot" (and hence is expecting to see the symbols after the dot next). See
+ * lalr_item, lalr_item_set, and lalr_start for full details on the meaning
+ * and use of items.
+ *
+ * @see java_cup.lalr_item
+ * @see java_cup.lalr_item_set
+ * @see java_cup.lalr_state
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+*/
+
+public class lr_item_core {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param prod production this item uses.
+ * @param pos position of the "dot" within the item.
+ */
+ public lr_item_core(production prod, int pos) throws internal_error
+ {
+ symbol after_dot = null;
+ production_part part;
+
+ if (prod == null)
+ throw new internal_error(
+ "Attempt to create an lr_item_core with a null production");
+
+ _the_production = prod;
+
+ if (pos < 0 || pos > _the_production.rhs_length())
+ throw new internal_error(
+ "Attempt to create an lr_item_core with a bad dot position");
+
+ _dot_pos = pos;
+
+ /* compute and cache hash code now */
+ _core_hash_cache = 13*_the_production.hashCode() + pos;
+
+ /* cache the symbol after the dot */
+ if (_dot_pos < _the_production.rhs_length())
+ {
+ part = _the_production.rhs(_dot_pos);
+ if (!part.is_action())
+ _symbol_after_dot = ((symbol_part)part).the_symbol();
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor for dot at start of right hand side.
+ * @param prod production this item uses.
+ */
+ public lr_item_core(production prod) throws internal_error
+ {
+ this(prod,0);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The production for the item. */
+ protected production _the_production;
+
+ /** The production for the item. */
+ public production the_production() {return _the_production;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The position of the "dot" -- this indicates the part of the production
+ * that the marker is before, so 0 indicates a dot at the beginning of
+ * the RHS.
+ */
+ protected int _dot_pos;
+
+ /** The position of the "dot" -- this indicates the part of the production
+ * that the marker is before, so 0 indicates a dot at the beginning of
+ * the RHS.
+ */
+ public int dot_pos() {return _dot_pos;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Cache of the hash code. */
+ protected int _core_hash_cache;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Cache of symbol after the dot. */
+ protected symbol _symbol_after_dot = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Is the dot at the end of the production? */
+ public boolean dot_at_end()
+ {
+ return _dot_pos >= _the_production.rhs_length();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return the symbol after the dot. If there is no symbol after the dot
+ * we return null. */
+ public symbol symbol_after_dot()
+ {
+ /* use the cached symbol */
+ return _symbol_after_dot;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if we have a dot before a non terminal, and if so which one
+ * (return null or the non terminal).
+ */
+ public non_terminal dot_before_nt()
+ {
+ symbol sym;
+
+ /* get the symbol after the dot */
+ sym = symbol_after_dot();
+
+ /* if it exists and is a non terminal, return it */
+ if (sym != null && sym.is_non_term())
+ return (non_terminal)sym;
+ else
+ return null;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a new lr_item_core that results from shifting the dot one
+ * position to the right.
+ */
+ public lr_item_core shift_core() throws internal_error
+ {
+ if (dot_at_end())
+ throw new internal_error(
+ "Attempt to shift past end of an lr_item_core");
+
+ return new lr_item_core(_the_production, _dot_pos+1);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison for the core only. This is separate out because we
+ * need separate access in a super class.
+ */
+ public boolean core_equals(lr_item_core other)
+ {
+ return other != null &&
+ _the_production.equals(other._the_production) &&
+ _dot_pos == other._dot_pos;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(lr_item_core other) {return core_equals(other);}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof lr_item_core))
+ return false;
+ else
+ return equals((lr_item_core)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Hash code for the core (separated so we keep non overridden version). */
+ public int core_hashCode()
+ {
+ return _core_hash_cache;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Hash code for the item. */
+ public int hashCode()
+ {
+ return _core_hash_cache;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return the hash code that object would have provided for us so we have
+ * a (nearly) unique id for debugging.
+ */
+ protected int obj_hash()
+ {
+ return super.hashCode();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string (separated out from toString() so we can call it
+ * from subclass that overrides toString()).
+ */
+ public String to_simple_string() throws internal_error
+ {
+ String result;
+ production_part part;
+
+ if (_the_production.lhs() != null &&
+ _the_production.lhs().the_symbol() != null &&
+ _the_production.lhs().the_symbol().name() != null)
+ result = _the_production.lhs().the_symbol().name();
+ else
+ result = "$$NULL$$";
+
+ result += " ::= ";
+
+ for (int i = 0; i<_the_production.rhs_length(); i++)
+ {
+ /* do we need the dot before this one? */
+ if (i == _dot_pos)
+ result += "(*) ";
+
+ /* print the name of the part */
+ if (_the_production.rhs(i) == null)
+ {
+ result += "$$NULL$$ ";
+ }
+ else
+ {
+ part = _the_production.rhs(i);
+ if (part == null)
+ result += "$$NULL$$ ";
+ else if (part.is_action())
+ result += "{ACTION} ";
+ else if (((symbol_part)part).the_symbol() != null &&
+ ((symbol_part)part).the_symbol().name() != null)
+ result += ((symbol_part)part).the_symbol().name() + " ";
+ else
+ result += "$$NULL$$ ";
+ }
+ }
+
+ /* put the dot after if needed */
+ if (_dot_pos == _the_production.rhs_length())
+ result += "(*) ";
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string */
+ public String toString()
+ {
+ /* can't throw here since super class doesn't, so we crash instead */
+ try {
+ return to_simple_string();
+ } catch(internal_error e) {
+ e.crash();
+ return null;
+ }
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
diff --git a/src/syntaxParser/java_cup/SAVE/non_terminal.java b/src/syntaxParser/java_cup/SAVE/non_terminal.java
new file mode 100644
index 0000000..9354a7f
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/non_terminal.java
@@ -0,0 +1,301 @@
+package java_cup;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/** This class represents a non-terminal symbol in the grammar. Each
+ * non terminal has a textual name, an index, and a string which indicates
+ * the type of object it will be implemented with at runtime (i.e. the class
+ * of object that will be pushed on the parse stack to represent it).
+ *
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+
+public class non_terminal extends symbol {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param nm the name of the non terminal.
+ * @param tp the type string for the non terminal.
+ */
+ public non_terminal(String nm, String tp)
+ {
+ /* super class does most of the work */
+ super(nm, tp);
+
+ /* add to set of all non terminals and check for duplicates */
+ Object conflict = _all.put(nm,this);
+ if (conflict != null)
+ // can't throw an exception here because these are used in static
+ // initializers, so we crash instead
+ // was:
+ // throw new internal_error("Duplicate non-terminal ("+nm+") created");
+ (new internal_error("Duplicate non-terminal ("+nm+") created")).crash();
+
+ /* assign a unique index */
+ _index = next_index++;
+
+ /* add to by_index set */
+ _all_by_index.put(new Integer(_index), this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with default type.
+ * @param nm the name of the non terminal.
+ */
+ public non_terminal(String nm)
+ {
+ this(nm, null);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Table of all non-terminals -- elements are stored using name strings
+ * as the key
+ */
+ protected static Hashtable _all = new Hashtable();
+
+ /** Access to all non-terminals. */
+ public static Enumeration all() {return _all.elements();}
+
+ /** lookup a non terminal by name string */
+ public static non_terminal find(String with_name)
+ {
+ if (with_name == null)
+ return null;
+ else
+ return (non_terminal)_all.get(with_name);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Table of all non terminals indexed by their index number. */
+ protected static Hashtable _all_by_index = new Hashtable();
+
+ /** Lookup a non terminal by index. */
+ public static non_terminal find(int indx)
+ {
+ Integer the_indx = new Integer(indx);
+
+ return (non_terminal)_all_by_index.get(the_indx);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Total number of non-terminals. */
+ public static int number() {return _all.size();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Static counter to assign unique indexes. */
+ protected static int next_index = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Static counter for creating unique non-terminal names */
+ static protected int next_nt = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** special non-terminal for start symbol */
+ public static final non_terminal START_nt = new non_terminal("$START");
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** flag non-terminals created to embed action productions */
+ public boolean is_embedded_action = false; /* added 24-Mar-1998, CSA */
+
+ /*-----------------------------------------------------------*/
+ /*--- Static Methods ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Method for creating a new uniquely named hidden non-terminal using
+ * the given string as a base for the name (or "NT$" if null is passed).
+ * @param prefix base name to construct unique name from.
+ */
+ static non_terminal create_new(String prefix) throws internal_error
+ {
+ if (prefix == null) prefix = "NT$";
+ return new non_terminal(prefix + next_nt++);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** static routine for creating a new uniquely named hidden non-terminal */
+ static non_terminal create_new() throws internal_error
+ {
+ return create_new(null);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute nullability of all non-terminals. */
+ public static void compute_nullability() throws internal_error
+ {
+ boolean change = true;
+ non_terminal nt;
+ Enumeration e;
+ production prod;
+
+ /* repeat this process until there is no change */
+ while (change)
+ {
+ /* look for a new change */
+ change = false;
+
+ /* consider each non-terminal */
+ for (e=all(); e.hasMoreElements(); )
+ {
+ nt = (non_terminal)e.nextElement();
+
+ /* only look at things that aren't already marked nullable */
+ if (!nt.nullable())
+ {
+ if (nt.looks_nullable())
+ {
+ nt._nullable = true;
+ change = true;
+ }
+ }
+ }
+ }
+
+ /* do one last pass over the productions to finalize all of them */
+ for (e=production.all(); e.hasMoreElements(); )
+ {
+ prod = (production)e.nextElement();
+ prod.set_nullable(prod.check_nullable());
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute first sets for all non-terminals. This assumes nullability has
+ * already computed.
+ */
+ public static void compute_first_sets() throws internal_error
+ {
+ boolean change = true;
+ Enumeration n;
+ Enumeration p;
+ non_terminal nt;
+ production prod;
+ terminal_set prod_first;
+
+ /* repeat this process until we have no change */
+ while (change)
+ {
+ /* look for a new change */
+ change = false;
+
+ /* consider each non-terminal */
+ for (n = all(); n.hasMoreElements(); )
+ {
+ nt = (non_terminal)n.nextElement();
+
+ /* consider every production of that non terminal */
+ for (p = nt.productions(); p.hasMoreElements(); )
+ {
+ prod = (production)p.nextElement();
+
+ /* get the updated first of that production */
+ prod_first = prod.check_first_set();
+
+ /* if this going to add anything, add it */
+ if (!prod_first.is_subset_of(nt._first_set))
+ {
+ change = true;
+ nt._first_set.add(prod_first);
+ }
+ }
+ }
+ }
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Table of all productions with this non terminal on the LHS. */
+ protected Hashtable _productions = new Hashtable(11);
+
+ /** Access to productions with this non terminal on the LHS. */
+ public Enumeration productions() {return _productions.elements();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Total number of productions with this non terminal on the LHS. */
+ public int num_productions() {return _productions.size();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a production to our set of productions. */
+ public void add_production(production prod) throws internal_error
+ {
+ /* catch improper productions */
+ if (prod == null || prod.lhs() == null || prod.lhs().the_symbol() != this)
+ throw new internal_error(
+ "Attempt to add invalid production to non terminal production table");
+
+ /* add it to the table, keyed with itself */
+ _productions.put(prod,prod);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Nullability of this non terminal. */
+ protected boolean _nullable;
+
+ /** Nullability of this non terminal. */
+ public boolean nullable() {return _nullable;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** First set for this non-terminal. */
+ protected terminal_set _first_set = new terminal_set();
+
+ /** First set for this non-terminal. */
+ public terminal_set first_set() {return _first_set;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Indicate that this symbol is a non-terminal. */
+ public boolean is_non_term()
+ {
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Test to see if this non terminal currently looks nullable. */
+ protected boolean looks_nullable() throws internal_error
+ {
+ /* look and see if any of the productions now look nullable */
+ for (Enumeration e = productions(); e.hasMoreElements(); )
+ /* if the production can go to empty, we are nullable */
+ if (((production)e.nextElement()).check_nullable())
+ return true;
+
+ /* none of the productions can go to empty, so we are not nullable */
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** convert to string */
+ public String toString()
+ {
+ return super.toString() + "[" + index() + "]" + (nullable() ? "*" : "");
+ }
+
+ /*-----------------------------------------------------------*/
+}
diff --git a/src/syntaxParser/java_cup/SAVE/nonassoc_action.java b/src/syntaxParser/java_cup/SAVE/nonassoc_action.java
new file mode 100644
index 0000000..3882324
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/nonassoc_action.java
@@ -0,0 +1,71 @@
+
+package java_cup;
+
+/** This class represents a shift/reduce nonassociative error within the
+ * parse table. If action_table element is assign to type
+ * nonassoc_action, it cannot be changed, and signifies that there
+ * is a conflict between shifting and reducing a production and a
+ * terminal that shouldn't be next to each other.
+ *
+ * @version last updated: 7/2/96
+ * @author Frank Flannery
+ */
+public class nonassoc_action extends parse_action {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor.
+ */
+ public nonassoc_action() throws internal_error
+ {
+ /* don't need to set anything, since it signifies error */
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Quick access to type of action. */
+ public int kind() {return NONASSOC;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality test. */
+ public boolean equals(parse_action other)
+ {
+ return other != null && other.kind() == NONASSOC;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality test. */
+ public boolean equals(Object other)
+ {
+ if (other instanceof parse_action)
+ return equals((parse_action)other);
+ else
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute a hash code. */
+ public int hashCode()
+ {
+ /* all objects of this class hash together */
+ return 0xCafe321;
+ }
+
+
+
+ /** Convert to string. */
+ public String toString()
+ {
+ return "NONASSOC";
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/syntaxParser/java_cup/SAVE/parse_action.java b/src/syntaxParser/java_cup/SAVE/parse_action.java
new file mode 100644
index 0000000..9228663
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/parse_action.java
@@ -0,0 +1,92 @@
+
+package java_cup;
+
+/** This class serves as the base class for entries in a parse action table.
+ * Full entries will either be SHIFT(state_num), REDUCE(production), NONASSOC,
+ * or ERROR. Objects of this base class will default to ERROR, while
+ * the other three types will be represented by subclasses.
+ *
+ * @see java_cup.reduce_action
+ * @see java_cup.shift_action
+ * @version last updated: 7/2/96
+ * @author Frank Flannery
+ */
+
+public class parse_action {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. */
+ public parse_action()
+ {
+ /* nothing to do in the base class */
+ }
+
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constant for action type -- error action. */
+ public static final int ERROR = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constant for action type -- shift action. */
+ public static final int SHIFT = 1;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constants for action type -- reduce action. */
+ public static final int REDUCE = 2;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constants for action type -- reduce action. */
+ public static final int NONASSOC = 3;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Quick access to the type -- base class defaults to error. */
+ public int kind() {return ERROR;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality test. */
+ public boolean equals(parse_action other)
+ {
+ /* we match all error actions */
+ return other != null && other.kind() == ERROR;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality test. */
+ public boolean equals(Object other)
+ {
+ if (other instanceof parse_action)
+ return equals((parse_action)other);
+ else
+ return false;
+ }
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute a hash code. */
+ public int hashCode()
+ {
+ /* all objects of this class hash together */
+ return 0xCafe123;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to string. */
+ public String toString() {return "ERROR";}
+
+ /*-----------------------------------------------------------*/
+}
+
diff --git a/src/syntaxParser/java_cup/SAVE/parse_action_row.java b/src/syntaxParser/java_cup/SAVE/parse_action_row.java
new file mode 100644
index 0000000..817b8c5
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/parse_action_row.java
@@ -0,0 +1,106 @@
+
+package java_cup;
+
+/** This class represents one row (corresponding to one machine state) of the
+ * parse action table.
+ */
+public class parse_action_row {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. Note: this should not be used until the number of
+ * terminals in the grammar has been established.
+ */
+ public parse_action_row()
+ {
+ /* make sure the size is set */
+ if (_size <= 0 ) _size = terminal.number();
+
+ /* allocate the array */
+ under_term = new parse_action[size()];
+
+ /* set each element to an error action */
+ for (int i=0; i<_size; i++)
+ under_term[i] = new parse_action();
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Number of columns (terminals) in every row. */
+ protected static int _size = 0;
+
+ /** Number of columns (terminals) in every row. */
+ public static int size() {return _size;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Table of reduction counts (reused by compute_default()). */
+ protected static int reduction_count[] = null;
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Actual action entries for the row. */
+ public parse_action under_term[];
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Default (reduce) action for this row. -1 will represent default
+ * of error.
+ */
+ public int default_reduce;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Compute the default (reduce) action for this row and store it in
+ * default_reduce. In the case of non-zero default we will have the
+ * effect of replacing all errors by that reduction. This may cause
+ * us to do erroneous reduces, but will never cause us to shift past
+ * the point of the error and never cause an incorrect parse. -1 will
+ * be used to encode the fact that no reduction can be used as a
+ * default (in which case error will be used).
+ */
+ public void compute_default()
+ {
+ int i, prod, max_prod, max_red;
+
+ /* if we haven't allocated the count table, do so now */
+ if (reduction_count == null)
+ reduction_count = new int[production.number()];
+
+ /* clear the reduction count table and maximums */
+ for (i = 0; i < production.number(); i++)
+ reduction_count[i] = 0;
+ max_prod = -1;
+ max_red = 0;
+
+ /* walk down the row and look at the reduces */
+ for (i = 0; i < size(); i++)
+ if (under_term[i].kind() == parse_action.REDUCE)
+ {
+ /* count the reduce in the proper production slot and keep the
+ max up to date */
+ prod = ((reduce_action)under_term[i]).reduce_with().index();
+ reduction_count[prod]++;
+ if (reduction_count[prod] > max_red)
+ {
+ max_red = reduction_count[prod];
+ max_prod = prod;
+ }
+ }
+
+ /* record the max as the default (or -1 for not found) */
+ default_reduce = max_prod;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
diff --git a/src/syntaxParser/java_cup/SAVE/parse_action_table.java b/src/syntaxParser/java_cup/SAVE/parse_action_table.java
new file mode 100644
index 0000000..1e0edb2
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/parse_action_table.java
@@ -0,0 +1,143 @@
+
+package java_cup;
+
+import java.util.Enumeration;
+
+/** This class represents the complete "action" table of the parser.
+ * It has one row for each state in the parse machine, and a column for
+ * each terminal symbol. Each entry in the table represents a shift,
+ * reduce, or an error.
+ *
+ * @see java_cup.parse_action
+ * @see java_cup.parse_action_row
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class parse_action_table {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. All terminals, non-terminals, and productions must
+ * already have been entered, and the viable prefix recognizer should
+ * have been constructed before this is called.
+ */
+ public parse_action_table()
+ {
+ /* determine how many states we are working with */
+ _num_states = lalr_state.number();
+
+ /* allocate the array and fill it in with empty rows */
+ under_state = new parse_action_row[_num_states];
+ for (int i=0; i<_num_states; i++)
+ under_state[i] = new parse_action_row();
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** How many rows/states are in the machine/table. */
+ protected int _num_states;
+
+ /** How many rows/states are in the machine/table. */
+ public int num_states() {return _num_states;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Actual array of rows, one per state. */
+ public parse_action_row[] under_state;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Check the table to ensure that all productions have been reduced.
+ * Issue a warning message (to System.err) for each production that
+ * is never reduced.
+ */
+ public void check_reductions()
+ throws internal_error
+ {
+ parse_action act;
+ production prod;
+
+ /* tabulate reductions -- look at every table entry */
+ for (int row = 0; row < num_states(); row++)
+ {
+ for (int col = 0; col < under_state[row].size(); col++)
+ {
+ /* look at the action entry to see if its a reduce */
+ act = under_state[row].under_term[col];
+ if (act != null && act.kind() == parse_action.REDUCE)
+ {
+ /* tell production that we used it */
+ ((reduce_action)act).reduce_with().note_reduction_use();
+ }
+ }
+ }
+
+ /* now go across every production and make sure we hit it */
+ for (Enumeration p = production.all(); p.hasMoreElements(); )
+ {
+ prod = (production)p.nextElement();
+
+ /* if we didn't hit it give a warning */
+ if (prod.num_reductions() == 0)
+ {
+ /* count it *
+ emit.not_reduced++;
+
+ /* give a warning if they haven't been turned off */
+ if (!emit.nowarn)
+ {
+ System.err.println("*** Production \"" +
+ prod.to_simple_string() + "\" never reduced");
+ lexer.warning_count++;
+ }
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+ int cnt;
+
+ result = "-------- ACTION_TABLE --------\n";
+ for (int row = 0; row < num_states(); row++)
+ {
+ result += "From state #" + row + "\n";
+ cnt = 0;
+ for (int col = 0; col < under_state[row].size(); col++)
+ {
+ /* if the action is not an error print it */
+ if (under_state[row].under_term[col].kind() != parse_action.ERROR)
+ {
+ result += " [term " + col + ":" + under_state[row].under_term[col] + "]";
+
+ /* end the line after the 2nd one */
+ cnt++;
+ if (cnt == 2)
+ {
+ result += "\n";
+ cnt = 0;
+ }
+ }
+ }
+ /* finish the line if we haven't just done that */
+ if (cnt != 0) result += "\n";
+ }
+ result += "------------------------------";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
diff --git a/src/syntaxParser/java_cup/SAVE/parse_reduce_row.java b/src/syntaxParser/java_cup/SAVE/parse_reduce_row.java
new file mode 100644
index 0000000..57d978e
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/parse_reduce_row.java
@@ -0,0 +1,41 @@
+
+package java_cup;
+
+/** This class represents one row (corresponding to one machine state) of the
+ * reduce-goto parse table.
+ */
+public class parse_reduce_row {
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. Note: this should not be used until the number
+ * of terminals in the grammar has been established.
+ */
+ public parse_reduce_row()
+ {
+ /* make sure the size is set */
+ if (_size <= 0 ) _size = non_terminal.number();
+
+ /* allocate the array */
+ under_non_term = new lalr_state[size()];
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Number of columns (non terminals) in every row. */
+ protected static int _size = 0;
+
+ /** Number of columns (non terminals) in every row. */
+ public static int size() {return _size;}
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Actual entries for the row. */
+ public lalr_state under_non_term[];
+}
+
diff --git a/src/syntaxParser/java_cup/SAVE/parse_reduce_table.java b/src/syntaxParser/java_cup/SAVE/parse_reduce_table.java
new file mode 100644
index 0000000..9ac1b11
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/parse_reduce_table.java
@@ -0,0 +1,99 @@
+
+package java_cup;
+
+import java.util.Enumeration;
+
+/** This class represents the complete "reduce-goto" table of the parser.
+ * It has one row for each state in the parse machines, and a column for
+ * each terminal symbol. Each entry contains a state number to shift to
+ * as the last step of a reduce.
+ *
+ * @see java_cup.parse_reduce_row
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class parse_reduce_table {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. Note: all terminals, non-terminals, and productions
+ * must already have been entered, and the viable prefix recognizer should
+ * have been constructed before this is called.
+ */
+ public parse_reduce_table()
+ {
+ /* determine how many states we are working with */
+ _num_states = lalr_state.number();
+
+ /* allocate the array and fill it in with empty rows */
+ under_state = new parse_reduce_row[_num_states];
+ for (int i=0; i<_num_states; i++)
+ under_state[i] = new parse_reduce_row();
+ }
+
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** How many rows/states in the machine/table. */
+ protected int _num_states;
+
+ /** How many rows/states in the machine/table. */
+ public int num_states() {return _num_states;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Actual array of rows, one per state */
+ public parse_reduce_row[] under_state;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+ lalr_state goto_st;
+ int cnt;
+
+ result = "-------- REDUCE_TABLE --------\n";
+ for (int row = 0; row < num_states(); row++)
+ {
+ result += "From state #" + row + "\n";
+ cnt = 0;
+ for (int col = 0; col < under_state[row].size(); col++)
+ {
+ /* pull out the table entry */
+ goto_st = under_state[row].under_non_term[col];
+
+ /* if it has action in it, print it */
+ if (goto_st != null)
+ {
+ result += " [non term " + col + "->";
+ result += "state " + goto_st.index() + "]";
+
+ /* end the line after the 3rd one */
+ cnt++;
+ if (cnt == 3)
+ {
+ result += "\n";
+ cnt = 0;
+ }
+ }
+ }
+ /* finish the line if we haven't just done that */
+ if (cnt != 0) result += "\n";
+ }
+ result += "-----------------------------";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
diff --git a/src/syntaxParser/java_cup/SAVE/parser.cup b/src/syntaxParser/java_cup/SAVE/parser.cup
new file mode 100644
index 0000000..8af0d05
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/parser.cup
@@ -0,0 +1,863 @@
+
+/*================================================================*/
+/*
+ JavaCup Specification for the JavaCup Specification Language
+ by Scott Hudson, GVU Center, Georgia Tech, August 1995
+ and Frank Flannery, Department of Computer Science, Princeton Univ,
+ July 1996
+ Bug Fixes: C. Scott Ananian, Dept of Electrical Engineering, Princeton
+ University, October 1996. [later Massachusetts Institute of Technology]
+
+
+ This JavaCup specification is used to implement JavaCup itself.
+ It specifies the parser for the JavaCup specification language.
+ (It also serves as a reasonable example of what a typical JavaCup
+ spec looks like).
+
+ The specification has the following parts:
+ Package and import declarations
+ These serve the same purpose as in a normal Java source file
+ (and will appear in the generated code for the parser). In this
+ case we are part of the java_cup package and we import both the
+ java_cup runtime system and Hashtable from the standard Java
+ utilities package.
+
+ Action code
+ This section provides code that is included with the class encapsulating
+ the various pieces of user code embedded in the grammar (i.e., the
+ semantic actions). This provides a series of helper routines and
+ data structures that the semantic actions use.
+
+ Parser code
+ This section provides code included in the parser class itself. In
+ this case we override the default error reporting routines.
+
+ Init with and scan with
+ These sections provide small bits of code that initialize, then
+ indicate how to invoke the scanner.
+
+ Symbols and grammar
+ These sections declare all the terminal and non terminal symbols
+ and the types of objects that they will be represented by at runtime,
+ then indicate the start symbol of the grammar (), and finally provide
+ the grammar itself (with embedded actions).
+
+ Operation of the parser
+ The parser acts primarily by accumulating data structures representing
+ various parts of the specification. Various small parts (e.g., single
+ code strings) are stored as static variables of the emit class and
+ in a few cases as variables declared in the action code section.
+ Terminals, non terminals, and productions, are maintained as collection
+ accessible via static methods of those classes. In addition, two
+ symbol tables are kept:
+ symbols maintains the name to object mapping for all symbols
+ non_terms maintains a separate mapping containing only the non terms
+
+ Several intermediate working structures are also declared in the action
+ code section. These include: rhs_parts, rhs_pos, and lhs_nt which
+ build up parts of the current production while it is being parsed.
+
+ Author(s)
+ Scott Hudson, GVU Center, Georgia Tech.
+ Frank Flannery, Department of Computer Science, Princeton Univ.
+ C. Scott Ananian, Department of Electrical Engineering, Princeton Univ.
+
+ Revisions
+ v0.9a First released version [SEH] 8/29/95
+ v0.9b Updated for beta language (throws clauses) [SEH] 11/25/95
+ v0.10a Made many improvements/changes. now offers:
+ return value
+ left/right positions and propagations
+ cleaner label references
+ precedence and associativity for terminals
+ contextual precedence for productions
+ [FF] 7/3/96
+ v0.10b Fixed %prec directive so it works like it's supposed to.
+ [CSA] 10/10/96
+ v0.10g Added support for array types on symbols.
+ [CSA] 03/23/98
+ v0.10i Broaden set of IDs allowed in multipart_id and label_id so
+ that only java reserved words (and not CUP reserved words like
+ 'parser' and 'start') are prohibited. Allow reordering of
+ action code, parser code, init code, and scan with sections,
+ and made closing semicolon optional for these sections.
+ Added 'nonterminal' as a terminal symbol, finally fixing a
+ spelling mistake that's been around since the beginning.
+ For backwards compatibility, you can still misspell the
+ word if you like.
+*/
+/*================================================================*/
+
+package java_cup;
+import java_cup.runtime.*;
+import java.util.Hashtable;
+
+/*----------------------------------------------------------------*/
+
+action code {:
+ /** helper routine to clone a new production part adding a given label */
+ protected production_part add_lab(production_part part, String lab)
+ throws internal_error
+ {
+ /* if there is no label, or this is an action, just return the original */
+ if (lab == null || part.is_action()) return part;
+
+ /* otherwise build a new one with the given label attached */
+ return new symbol_part(((symbol_part)part).the_symbol(),lab);
+ }
+
+ /** max size of right hand side we will support */
+ protected final int MAX_RHS = 200;
+
+ /** array for accumulating right hand side parts */
+ protected production_part[] rhs_parts = new production_part[MAX_RHS];
+
+ /** where we are currently in building a right hand side */
+ protected int rhs_pos = 0;
+
+ /** start a new right hand side */
+ protected void new_rhs() {rhs_pos = 0; }
+
+ /** add a new right hand side part */
+ protected void add_rhs_part(production_part part) throws java.lang.Exception
+ {
+ if (rhs_pos >= MAX_RHS)
+ throw new Exception("Internal Error: Productions limited to " +
+ MAX_RHS + " symbols and actions");
+
+ rhs_parts[rhs_pos] = part;
+ rhs_pos++;
+ }
+
+ /** string to build up multiple part names */
+ protected String multipart_name = new String();
+
+ /** append a new name segment to the accumulated multipart name */
+ protected void append_multipart(String name)
+ {
+ String dot = "";
+
+ /* if we aren't just starting out, put on a dot */
+ if (multipart_name.length() != 0) dot = ".";
+
+ multipart_name = multipart_name.concat(dot + name);
+ }
+
+ /** table of declared symbols -- contains production parts indexed by name */
+ protected Hashtable symbols = new Hashtable();
+
+ /** table of just non terminals -- contains non_terminals indexed by name */
+ protected Hashtable non_terms = new Hashtable();
+
+ /** declared start non_terminal */
+ protected non_terminal start_nt = null;
+
+ /** left hand side non terminal of the current production */
+ protected non_terminal lhs_nt;
+
+ /** Current precedence number */
+ int _cur_prec = 0;
+
+ /** Current precedence side */
+ int _cur_side = assoc.no_prec;
+
+ /** update the precedences we are declaring */
+ protected void update_precedence(int p) {
+ _cur_side = p;
+ _cur_prec++;
+ }
+ /** add relevant data to terminals */
+ protected void add_precedence(String term) {
+ if (term == null) {
+ System.err.println("Unable to add precedence to nonexistent terminal");
+ } else {
+ symbol_part sp = (symbol_part)symbols.get(term);
+ if (sp == null) {
+ System.err.println("Could find terminal " + term + " while declaring precedence");
+ } else {
+ java_cup.symbol sym = sp.the_symbol();
+ if (sym instanceof terminal)
+ ((terminal)sym).set_precedence(_cur_side, _cur_prec);
+ else System.err.println("Precedence declaration: Can't find terminal " + term);
+ }
+ }
+ }
+:};
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+parser code {:
+
+ /* override error routines */
+
+ public void report_fatal_error(
+ String message,
+ Object info)
+ {
+ done_parsing();
+ lexer.emit_error(message);
+ System.err.println("Can't recover from previous error(s), giving up.");
+ System.exit(1);
+ }
+
+ public void report_error(String message, Object info)
+ {
+ lexer.emit_error(message);
+ }
+:};
+
+/*----------------------------------------------------------------*/
+
+init with {: lexer.init(); :};
+scan with {: return lexer.next_token(); :};
+
+/*----------------------------------------------------------------*/
+
+terminal
+ PACKAGE, IMPORT, CODE, ACTION, PARSER, TERMINAL, NON, INIT, SCAN, WITH,
+ START, SEMI, COMMA, STAR, DOT, COLON, COLON_COLON_EQUALS, BAR, PRECEDENCE,
+ LEFT, RIGHT, NONASSOC, PERCENT_PREC, LBRACK, RBRACK, NONTERMINAL;
+
+terminal String ID, CODE_STRING;
+
+non terminal
+ spec, package_spec, import_list, action_code_part,
+ code_parts, code_part, opt_semi, non_terminal,
+ parser_code_part, symbol_list, start_spec, production_list,
+ multipart_id, import_spec, import_id, init_code, scan_code, symbol,
+ type_id, term_name_list, non_term_name_list, production, prod_part_list,
+ prod_part, new_term_id, new_non_term_id, rhs_list, rhs, empty,
+ precedence_list, preced, terminal_list, precedence_l, declares_term,
+ declares_non_term;
+
+non terminal String nt_id, symbol_id, label_id, opt_label, terminal_id,
+ term_id, robust_id;
+
+/*----------------------------------------------------------------*/
+
+start with spec;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+spec ::=
+ {:
+ /* declare "error" as a terminal */
+ symbols.put("error", new symbol_part(terminal.error));
+
+ /* declare start non terminal */
+ non_terms.put("$START", non_terminal.START_nt);
+ :}
+ package_spec
+ import_list
+ code_parts
+ symbol_list
+ precedence_list
+ start_spec
+ production_list
+ |
+ /* error recovery assuming something went wrong before symbols
+ and we have TERMINAL or NON TERMINAL to sync on. if we get
+ an error after that, we recover inside symbol_list or
+ production_list
+ */
+ error
+ symbol_list
+ precedence_list
+ start_spec
+ production_list
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+package_spec ::=
+ PACKAGE
+ multipart_id
+ {:
+ /* save the package name */
+ emit.package_name = multipart_name;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+import_list ::=
+ import_list
+ import_spec
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+import_spec ::=
+ IMPORT
+ import_id
+ {:
+ /* save this import on the imports list */
+ emit.import_list.push(multipart_name);
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+// allow any order; all parts are optional. [CSA, 23-Jul-1999]
+// (we check in the part action to make sure we don't have 2 of any part)
+code_part ::=
+ action_code_part | parser_code_part | init_code | scan_code ;
+code_parts ::=
+ | code_parts code_part;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+action_code_part ::=
+ ACTION CODE CODE_STRING:user_code opt_semi
+ {:
+ if (emit.action_code!=null)
+ lexer.emit_error("Redundant action code (skipping)");
+ else /* save the user included code string */
+ emit.action_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+parser_code_part ::=
+ PARSER CODE CODE_STRING:user_code opt_semi
+ {:
+ if (emit.parser_code!=null)
+ lexer.emit_error("Redundant parser code (skipping)");
+ else /* save the user included code string */
+ emit.parser_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+init_code ::=
+ INIT WITH CODE_STRING:user_code opt_semi
+ {:
+ if (emit.init_code!=null)
+ lexer.emit_error("Redundant init code (skipping)");
+ else /* save the user code */
+ emit.init_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+scan_code ::=
+ SCAN WITH CODE_STRING:user_code opt_semi
+ {:
+ if (emit.scan_code!=null)
+ lexer.emit_error("Redundant scan code (skipping)");
+ else /* save the user code */
+ emit.scan_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+symbol_list ::= symbol_list symbol | symbol;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+symbol ::=
+ TERMINAL
+ type_id
+ declares_term
+ |
+ TERMINAL
+ declares_term
+ |
+ non_terminal
+ type_id
+ declares_non_term
+ |
+ non_terminal
+ declares_non_term
+ |
+ /* error recovery productions -- sync on semicolon */
+
+ TERMINAL
+ error
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ |
+ non_terminal
+ error
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+declares_term ::=
+ term_name_list
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+declares_non_term ::=
+ non_term_name_list
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+term_name_list ::= term_name_list COMMA new_term_id | new_term_id;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+non_term_name_list ::=
+ non_term_name_list
+ COMMA
+ new_non_term_id
+ |
+ new_non_term_id
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+
+precedence_list ::= precedence_l | empty;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+precedence_l ::= precedence_l preced | preced;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+preced ::=
+ PRECEDENCE LEFT
+ {:
+ update_precedence(assoc.left);
+ :}
+ terminal_list SEMI
+ |
+ PRECEDENCE RIGHT
+ {:
+ update_precedence(assoc.right);
+ :}
+ terminal_list SEMI
+ |
+ PRECEDENCE NONASSOC
+ {:
+ update_precedence(assoc.nonassoc);
+ :}
+ terminal_list SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+terminal_list ::= terminal_list COMMA terminal_id
+ |
+ terminal_id
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+terminal_id ::= term_id:sym
+ {:
+ add_precedence(sym);
+ RESULT = sym;
+ :};
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+term_id ::= symbol_id:sym
+ {:
+ /* check that the symbol_id is a terminal */
+ if (symbols.get(sym) == null)
+ {
+ /* issue a message */
+ lexer.emit_error("Terminal \"" + sym +
+ "\" has not been declared");
+ }
+ RESULT = sym;
+ :};
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+start_spec ::=
+ START WITH nt_id:start_name
+ {:
+ /* verify that the name has been declared as a non terminal */
+ non_terminal nt = (non_terminal)non_terms.get(start_name);
+ if (nt == null)
+ {
+ lexer.emit_error( "Start non terminal \"" + start_name +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* remember the non-terminal for later */
+ start_nt = nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt), "start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+ new_rhs();
+ }
+ :}
+ SEMI
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+production_list ::= production_list production | production;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+production ::=
+ nt_id:lhs_id
+ {:
+ /* lookup the lhs nt */
+ lhs_nt = (non_terminal)non_terms.get(lhs_id);
+
+ /* if it wasn't declared, emit a message */
+ if (lhs_nt == null)
+ {
+ if (lexer.error_count == 0)
+ lexer.emit_error("LHS non terminal \"" + lhs_id +
+ "\" has not been declared");
+ }
+
+ /* reset the rhs accumulation */
+ new_rhs();
+ :}
+ COLON_COLON_EQUALS
+ {: :}
+ rhs_list
+ SEMI
+ |
+ error
+ {: lexer.emit_error("Syntax Error"); :}
+ SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+rhs_list ::= rhs_list BAR rhs | rhs;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+rhs ::=
+ prod_part_list PERCENT_PREC term_id:term_name
+ {:
+ java_cup.symbol sym = null;
+ if (lhs_nt != null)
+ {
+ /* Find the precedence symbol */
+ if (term_name == null) {
+ System.err.println("No terminal for contextual precedence");
+ sym = null;
+ } else {
+ sym = ((symbol_part)symbols.get(term_name)).the_symbol();
+ }
+ /* build the production */
+ production p;
+ if ((sym!=null) && (sym instanceof terminal)) {
+ p = new production(lhs_nt, rhs_parts, rhs_pos,
+ ((terminal)sym).precedence_num(),
+ ((terminal)sym).precedence_side());
+ ((symbol_part)symbols.get(term_name)).the_symbol().note_use();
+ } else {
+ System.err.println("Invalid terminal " + term_name +
+ " for contextual precedence assignment");
+ p = new production(lhs_nt, rhs_parts, rhs_pos);
+ }
+
+ /* if we have no start non-terminal declared and this is
+ the first production, make its lhs nt the start_nt
+ and build a special start production for it. */
+ if (start_nt == null)
+ {
+ start_nt = lhs_nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt),"start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ if ((sym!=null) && (sym instanceof terminal)) {
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts,
+ rhs_pos, ((terminal)sym).precedence_num(),
+ ((terminal)sym).precedence_side());
+ } else {
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+ }
+ new_rhs();
+ }
+ }
+
+ /* reset the rhs accumulation in any case */
+ new_rhs();
+ :}
+ |
+ prod_part_list
+ {:
+ if (lhs_nt != null)
+ {
+ /* build the production */
+ production p = new production(lhs_nt, rhs_parts, rhs_pos);
+
+ /* if we have no start non-terminal declared and this is
+ the first production, make its lhs nt the start_nt
+ and build a special start production for it. */
+ if (start_nt == null)
+ {
+ start_nt = lhs_nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt),"start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+
+ new_rhs();
+ }
+ }
+
+ /* reset the rhs accumulation in any case */
+ new_rhs();
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+prod_part_list ::= prod_part_list prod_part | empty;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+prod_part ::=
+ symbol_id:symid opt_label:labid
+ {:
+ /* try to look up the id */
+ production_part symb = (production_part)symbols.get(symid);
+
+ /* if that fails, symbol is undeclared */
+ if (symb == null)
+ {
+ if (lexer.error_count == 0)
+ lexer.emit_error("java_cup.runtime.Symbol \"" + symid +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* add a labeled production part */
+ add_rhs_part(add_lab(symb, labid));
+ }
+ :}
+ |
+ CODE_STRING:code_str
+ {:
+ /* add a new production part */
+ add_rhs_part(new action_part(code_str));
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+opt_label ::=
+ COLON label_id:labid
+ {: RESULT = labid; :}
+ |
+ empty
+ {: RESULT = null; :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+multipart_id ::=
+ multipart_id DOT robust_id:another_id
+ {: append_multipart(another_id); :}
+ |
+ robust_id:an_id
+ {: append_multipart(an_id); :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+import_id ::=
+ multipart_id DOT STAR
+ {: append_multipart("*"); :}
+ |
+ multipart_id
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+type_id ::= multipart_id
+ | type_id LBRACK RBRACK
+ {: multipart_name = multipart_name.concat("[]"); :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+new_term_id ::=
+ ID:term_id
+ {:
+ /* see if this terminal has been declared before */
+ if (symbols.get(term_id) != null)
+ {
+ /* issue a message */
+ lexer.emit_error("java_cup.runtime.Symbol \"" + term_id +
+ "\" has already been declared");
+ }
+ else
+ {
+ /* if no type declared, declare one */
+ if (multipart_name.equals("")) {
+ append_multipart("Object");
+ }
+ /* build a production_part and put it in the table */
+ symbols.put(term_id,
+ new symbol_part(new terminal(term_id, multipart_name)));
+ }
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+new_non_term_id ::=
+ ID:non_term_id
+ {:
+ /* see if this non terminal has been declared before */
+ if (symbols.get(non_term_id) != null)
+ {
+ /* issue a message */
+ lexer.emit_error( "java_cup.runtime.Symbol \"" + non_term_id +
+ "\" has already been declared");
+ }
+ else
+ {
+ if (multipart_name.equals("")) {
+ append_multipart("Object");
+ }
+ /* build the non terminal object */
+ non_terminal this_nt =
+ new non_terminal(non_term_id, multipart_name);
+
+ /* put it in the non_terms table */
+ non_terms.put(non_term_id, this_nt);
+
+ /* build a production_part and put it in the symbols table */
+ symbols.put(non_term_id, new symbol_part(this_nt));
+ }
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+nt_id ::=
+ ID:the_id
+ {: RESULT = the_id; :}
+ | error
+ {:
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+symbol_id ::=
+ ID:the_id
+ {: RESULT = the_id; :}
+ | error
+ {:
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+label_id ::=
+ robust_id:the_id
+ {: RESULT = the_id; :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+robust_id ::= /* all ids that aren't reserved words in Java */
+ ID:the_id {: RESULT = the_id; :}
+ /* package is reserved. */
+ /* import is reserved. */
+ | CODE {: RESULT = "code"; :}
+ | ACTION {: RESULT = "action"; :}
+ | PARSER {: RESULT = "parser"; :}
+ | TERMINAL {: RESULT = "terminal"; :}
+ | NON {: RESULT = "non"; :}
+ | NONTERMINAL {: RESULT = "nonterminal"; :}
+ | INIT {: RESULT = "init"; :}
+ | SCAN {: RESULT = "scan"; :}
+ | WITH {: RESULT = "with"; :}
+ | START {: RESULT = "start"; :}
+ | PRECEDENCE {: RESULT = "precedence"; :}
+ | LEFT {: RESULT = "left"; :}
+ | RIGHT {: RESULT = "right"; :}
+ | NONASSOC {: RESULT = "nonassoc"; :}
+ | error
+ {:
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+non_terminal ::= NON TERMINAL | NONTERMINAL;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+opt_semi ::= /* nothing */
+ | SEMI;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+empty ::= /* nothing */;
+
+/*----------------------------------------------------------------*/
+
+
+
+
+
+
+
+
+
diff --git a/src/syntaxParser/java_cup/SAVE/parser.java b/src/syntaxParser/java_cup/SAVE/parser.java
new file mode 100644
index 0000000..163968e
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/parser.java
@@ -0,0 +1,1849 @@
+
+//----------------------------------------------------
+// The following code was generated by CUP v0.10k
+// Sun Jul 25 13:35:26 EDT 1999
+//----------------------------------------------------
+
+package java_cup;
+
+import java_cup.runtime.*;
+import java.util.Hashtable;
+
+/** CUP v0.10k generated parser.
+ * @version Sun Jul 25 13:35:26 EDT 1999
+ */
+public class parser extends java_cup.runtime.lr_parser {
+
+ /** Default constructor. */
+ public parser() {super();}
+
+ /** Constructor which sets the default scanner. */
+ public parser(java_cup.runtime.Scanner s) {super(s);}
+
+ /** Production table. */
+ protected static final short _production_table[][] =
+ unpackFromStrings(new String[] {
+ "\000\153\000\002\002\004\000\002\055\002\000\002\003" +
+ "\012\000\002\003\007\000\002\056\002\000\002\004\006" +
+ "\000\002\004\003\000\002\005\004\000\002\005\003\000" +
+ "\002\057\002\000\002\020\006\000\002\010\003\000\002" +
+ "\010\003\000\002\010\003\000\002\010\003\000\002\007" +
+ "\002\000\002\007\004\000\002\006\006\000\002\013\006" +
+ "\000\002\022\006\000\002\023\006\000\002\014\004\000" +
+ "\002\014\003\000\002\024\005\000\002\024\004\000\002" +
+ "\024\005\000\002\024\004\000\002\060\002\000\002\024" +
+ "\006\000\002\061\002\000\002\024\006\000\002\062\002" +
+ "\000\002\044\005\000\002\063\002\000\002\045\005\000" +
+ "\002\026\005\000\002\026\003\000\002\027\005\000\002" +
+ "\027\003\000\002\040\003\000\002\040\003\000\002\043" +
+ "\004\000\002\043\003\000\002\064\002\000\002\041\007" +
+ "\000\002\065\002\000\002\041\007\000\002\066\002\000" +
+ "\002\041\007\000\002\042\005\000\002\042\003\000\002" +
+ "\052\003\000\002\053\003\000\002\067\002\000\002\015" +
+ "\007\000\002\015\003\000\002\016\004\000\002\016\003" +
+ "\000\002\070\002\000\002\071\002\000\002\030\010\000" +
+ "\002\072\002\000\002\030\005\000\002\035\005\000\002" +
+ "\035\003\000\002\036\005\000\002\036\003\000\002\031" +
+ "\004\000\002\031\003\000\002\032\004\000\002\032\003" +
+ "\000\002\051\004\000\002\051\003\000\002\017\005\000" +
+ "\002\017\003\000\002\021\005\000\002\021\003\000\002" +
+ "\025\003\000\002\025\005\000\002\033\003\000\002\034" +
+ "\003\000\002\046\003\000\002\046\003\000\002\047\003" +
+ "\000\002\047\003\000\002\050\003\000\002\054\003\000" +
+ "\002\054\003\000\002\054\003\000\002\054\003\000\002" +
+ "\054\003\000\002\054\003\000\002\054\003\000\002\054" +
+ "\003\000\002\054\003\000\002\054\003\000\002\054\003" +
+ "\000\002\054\003\000\002\054\003\000\002\054\003\000" +
+ "\002\054\003\000\002\054\003\000\002\012\004\000\002" +
+ "\012\003\000\002\011\002\000\002\011\003\000\002\037" +
+ "\002" });
+
+ /** Access to production table. */
+ public short[][] production_table() {return _production_table;}
+
+ /** Parse-action table. */
+ protected static final short[][] _action_table =
+ unpackFromStrings(new String[] {
+ "\000\247\000\026\003\006\004\000\005\000\007\000\010" +
+ "\000\011\000\012\000\013\000\014\000\035\000\001\002" +
+ "\000\004\002\251\001\002\000\024\004\200\005\uff97\007" +
+ "\uff97\010\uff97\011\uff97\012\uff97\013\uff97\014\uff97\035\uff97" +
+ "\001\002\000\010\011\007\012\012\035\014\001\002\000" +
+ "\042\003\163\006\026\007\027\010\040\011\036\012\022" +
+ "\013\042\014\030\015\017\016\015\026\033\027\023\030" +
+ "\035\031\041\035\025\036\160\001\002\000\020\003\uffeb" +
+ "\011\uffeb\012\uffeb\016\uffeb\026\uffeb\035\uffeb\036\uffeb\001" +
+ "\002\000\020\003\uff97\011\007\012\012\016\uff97\026\065" +
+ "\035\014\036\uff97\001\002\000\004\011\061\001\002\000" +
+ "\042\003\034\006\026\007\027\010\040\011\036\012\022" +
+ "\013\042\014\030\015\017\016\015\026\033\027\023\030" +
+ "\035\031\041\035\025\036\016\001\002\000\042\003\uff9a" +
+ "\006\uff9a\007\uff9a\010\uff9a\011\uff9a\012\uff9a\013\uff9a\014" +
+ "\uff9a\015\uff9a\016\uff9a\026\uff9a\027\uff9a\030\uff9a\031\uff9a" +
+ "\035\uff9a\036\uff9a\001\002\000\022\003\uffa1\017\uffa1\022" +
+ "\uffa1\025\uffa1\032\uffa1\033\uffa1\036\uffa1\037\uffa1\001\002" +
+ "\000\014\017\uffb1\020\uffb1\022\uffab\033\uffab\036\uffab\001" +
+ "\002\000\022\003\uffa2\017\uffa2\022\uffa2\025\uffa2\032\uffa2" +
+ "\033\uffa2\036\uffa2\037\uffa2\001\002\000\006\017\uffe0\020" +
+ "\055\001\002\000\010\022\051\033\uffb4\036\uffb4\001\002" +
+ "\000\022\003\uffa6\017\uffa6\022\uffa6\025\uffa6\032\uffa6\033" +
+ "\uffa6\036\uffa6\037\uffa6\001\002\000\022\003\uff9f\017\uff9f" +
+ "\022\uff9f\025\uff9f\032\uff9f\033\uff9f\036\uff9f\037\uff9f\001" +
+ "\002\000\006\033\047\036\045\001\002\000\022\003\uffa5" +
+ "\017\uffa5\022\uffa5\025\uffa5\032\uffa5\033\uffa5\036\uffa5\037" +
+ "\uffa5\001\002\000\022\003\uffaa\017\uffaa\022\uffaa\025\uffaa" +
+ "\032\uffaa\033\uffaa\036\uffaa\037\uffaa\001\002\000\022\003" +
+ "\uffa9\017\uffa9\022\uffa9\025\uffa9\032\uffa9\033\uffa9\036\uffa9" +
+ "\037\uffa9\001\002\000\022\003\uffa3\017\uffa3\022\uffa3\025" +
+ "\uffa3\032\uffa3\033\uffa3\036\uffa3\037\uffa3\001\002\000\012" +
+ "\017\uffb7\022\uffb7\033\uffb7\036\uffb7\001\002\000\020\003" +
+ "\uffe7\011\uffe7\012\uffe7\016\uffe7\026\uffe7\035\uffe7\036\uffe7" +
+ "\001\002\000\022\003\uffa0\017\uffa0\022\uffa0\025\uffa0\032" +
+ "\uffa0\033\uffa0\036\uffa0\037\uffa0\001\002\000\012\017\uffe4" +
+ "\022\uff9c\033\uff9c\036\uff9c\001\002\000\022\003\uff9e\017" +
+ "\uff9e\022\uff9e\025\uff9e\032\uff9e\033\uff9e\036\uff9e\037\uff9e" +
+ "\001\002\000\022\003\uffa7\017\uffa7\022\uffa7\025\uffa7\032" +
+ "\uffa7\033\uffa7\036\uffa7\037\uffa7\001\002\000\006\017\uffdb" +
+ "\020\uffdb\001\002\000\022\003\uffa8\017\uffa8\022\uffa8\025" +
+ "\uffa8\032\uffa8\033\uffa8\036\uffa8\037\uffa8\001\002\000\022" +
+ "\003\uff9d\017\uff9d\022\uff9d\025\uff9d\032\uff9d\033\uff9d\036" +
+ "\uff9d\037\uff9d\001\002\000\022\003\uffa4\017\uffa4\022\uffa4" +
+ "\025\uffa4\032\uffa4\033\uffa4\036\uffa4\037\uffa4\001\002\000" +
+ "\004\017\044\001\002\000\020\003\uffe3\011\uffe3\012\uffe3" +
+ "\016\uffe3\026\uffe3\035\uffe3\036\uffe3\001\002\000\006\017" +
+ "\uffb1\020\uffb1\001\002\000\020\003\uffe8\011\uffe8\012\uffe8" +
+ "\016\uffe8\026\uffe8\035\uffe8\036\uffe8\001\002\000\004\034" +
+ "\050\001\002\000\006\033\uffb3\036\uffb3\001\002\000\042" +
+ "\003\054\006\026\007\027\010\040\011\036\012\022\013" +
+ "\042\014\030\015\017\016\015\026\033\027\023\030\035" +
+ "\031\041\035\025\036\053\001\002\000\012\017\uffb8\022" +
+ "\uffb8\033\uffb8\036\uffb8\001\002\000\022\003\uffab\017\uffab" +
+ "\022\uffab\025\uffab\032\uffab\033\uffab\036\uffab\037\uffab\001" +
+ "\002\000\022\003\uff9c\017\uff9c\022\uff9c\025\uff9c\032\uff9c" +
+ "\033\uff9c\036\uff9c\037\uff9c\001\002\000\004\036\045\001" +
+ "\002\000\004\017\057\001\002\000\020\003\uffdf\011\uffdf" +
+ "\012\uffdf\016\uffdf\026\uffdf\035\uffdf\036\uffdf\001\002\000" +
+ "\006\017\uffdc\020\uffdc\001\002\000\042\003\uff9b\006\uff9b" +
+ "\007\uff9b\010\uff9b\011\uff9b\012\uff9b\013\uff9b\014\uff9b\015" +
+ "\uff9b\016\uff9b\026\uff9b\027\uff9b\030\uff9b\031\uff9b\035\uff9b" +
+ "\036\uff9b\001\002\000\010\003\uff97\016\116\036\uff97\001" +
+ "\002\000\012\003\uffda\016\uffda\026\065\036\uffda\001\002" +
+ "\000\010\003\uffd9\016\uffd9\036\uffd9\001\002\000\010\027" +
+ "\071\030\072\031\070\001\002\000\020\003\uffec\011\uffec" +
+ "\012\uffec\016\uffec\026\uffec\035\uffec\036\uffec\001\002\000" +
+ "\012\003\uffd7\016\uffd7\026\uffd7\036\uffd7\001\002\000\006" +
+ "\003\uffd2\036\uffd2\001\002\000\006\003\uffd6\036\uffd6\001" +
+ "\002\000\006\003\uffd4\036\uffd4\001\002\000\006\003\077" +
+ "\036\074\001\002\000\022\003\uffae\017\uffae\020\uffae\023" +
+ "\uffae\025\uffae\032\uffae\036\uffae\037\uffae\001\002\000\010" +
+ "\017\uffcd\020\uffcd\025\uffcd\001\002\000\006\017\uffce\020" +
+ "\uffce\001\002\000\022\003\uffad\017\uffad\020\uffad\023\uffad" +
+ "\025\uffad\032\uffad\036\uffad\037\uffad\001\002\000\006\017" +
+ "\102\020\103\001\002\000\006\017\uffcf\020\uffcf\001\002" +
+ "\000\012\003\uffd3\016\uffd3\026\uffd3\036\uffd3\001\002\000" +
+ "\006\003\077\036\074\001\002\000\006\017\uffd0\020\uffd0" +
+ "\001\002\000\006\003\077\036\074\001\002\000\006\017" +
+ "\107\020\103\001\002\000\012\003\uffd5\016\uffd5\026\uffd5" +
+ "\036\uffd5\001\002\000\006\003\077\036\074\001\002\000" +
+ "\006\017\112\020\103\001\002\000\012\003\uffd1\016\uffd1" +
+ "\026\uffd1\036\uffd1\001\002\000\012\003\uffd8\016\uffd8\026" +
+ "\uffd8\036\uffd8\001\002\000\006\003\uffca\036\uffca\001\002" +
+ "\000\006\003\126\036\120\001\002\000\004\015\117\001" +
+ "\002\000\006\003\122\036\120\001\002\000\006\017\uffb0" +
+ "\024\uffb0\001\002\000\004\017\uffcc\001\002\000\004\017" +
+ "\uffaf\001\002\000\004\017\124\001\002\000\006\003\uffcb" +
+ "\036\uffcb\001\002\000\004\024\uffc7\001\002\000\006\017" +
+ "\uffc4\024\uffaf\001\002\000\010\002\ufffe\003\126\036\120" +
+ "\001\002\000\010\002\uffc8\003\uffc8\036\uffc8\001\002\000" +
+ "\010\002\uffc9\003\uffc9\036\uffc9\001\002\000\004\017\133" +
+ "\001\002\000\010\002\uffc3\003\uffc3\036\uffc3\001\002\000" +
+ "\004\024\135\001\002\000\016\003\uffc6\017\uffc6\025\uffc6" +
+ "\032\uffc6\036\uffc6\037\uffc6\001\002\000\016\003\uff97\017" +
+ "\uff97\025\uff97\032\uff97\036\uff97\037\uff97\001\002\000\016" +
+ "\003\uffbd\017\uffbd\025\uffbd\032\uffbd\036\uffbd\037\uffbd\001" +
+ "\002\000\016\003\077\017\uffbf\025\uffbf\032\147\036\074" +
+ "\037\146\001\002\000\006\017\uffc1\025\uffc1\001\002\000" +
+ "\006\017\143\025\144\001\002\000\010\002\uffc5\003\uffc5" +
+ "\036\uffc5\001\002\000\016\003\uff97\017\uff97\025\uff97\032" +
+ "\uff97\036\uff97\037\uff97\001\002\000\006\017\uffc2\025\uffc2" +
+ "\001\002\000\016\003\uffbb\017\uffbb\025\uffbb\032\uffbb\036" +
+ "\uffbb\037\uffbb\001\002\000\006\003\077\036\074\001\002" +
+ "\000\020\003\uff97\017\uff97\023\154\025\uff97\032\uff97\036" +
+ "\uff97\037\uff97\001\002\000\016\003\uffbe\017\uffbe\025\uffbe" +
+ "\032\uffbe\036\uffbe\037\uffbe\001\002\000\016\003\uffb9\017" +
+ "\uffb9\025\uffb9\032\uffb9\036\uffb9\037\uffb9\001\002\000\016" +
+ "\003\uffbc\017\uffbc\025\uffbc\032\uffbc\036\uffbc\037\uffbc\001" +
+ "\002\000\042\003\054\006\026\007\027\010\040\011\036" +
+ "\012\022\013\042\014\030\015\017\016\015\026\033\027" +
+ "\023\030\035\031\041\035\025\036\053\001\002\000\016" +
+ "\003\uffba\017\uffba\025\uffba\032\uffba\036\uffba\037\uffba\001" +
+ "\002\000\016\003\uffac\017\uffac\025\uffac\032\uffac\036\uffac" +
+ "\037\uffac\001\002\000\006\017\uffc0\025\uffc0\001\002\000" +
+ "\014\017\uffb2\020\uffb2\022\uffab\033\uffab\036\uffab\001\002" +
+ "\000\006\033\047\036\170\001\002\000\006\017\uffdd\020" +
+ "\uffdd\001\002\000\012\017\uffe6\022\uff9c\033\uff9c\036\uff9c" +
+ "\001\002\000\020\003\uffe9\011\uffe9\012\uffe9\016\uffe9\026" +
+ "\uffe9\035\uffe9\036\uffe9\001\002\000\006\017\uffe2\020\167" +
+ "\001\002\000\004\017\172\001\002\000\004\036\170\001" +
+ "\002\000\006\017\uffb2\020\uffb2\001\002\000\006\017\uffde" +
+ "\020\uffde\001\002\000\020\003\uffe1\011\uffe1\012\uffe1\016" +
+ "\uffe1\026\uffe1\035\uffe1\036\uffe1\001\002\000\004\017\174" +
+ "\001\002\000\020\003\uffe5\011\uffe5\012\uffe5\016\uffe5\026" +
+ "\uffe5\035\uffe5\036\uffe5\001\002\000\020\003\uffea\011\uffea" +
+ "\012\uffea\016\uffea\026\uffea\035\uffea\036\uffea\001\002\000" +
+ "\022\005\ufffb\007\ufffb\010\ufffb\011\ufffb\012\ufffb\013\ufffb" +
+ "\014\ufffb\035\ufffb\001\002\000\022\005\uff97\007\uff97\010" +
+ "\uff97\011\uff97\012\uff97\013\uff97\014\uff97\035\uff97\001\002" +
+ "\000\042\003\054\006\026\007\027\010\040\011\036\012" +
+ "\022\013\042\014\030\015\017\016\015\026\033\027\023" +
+ "\030\035\031\041\035\025\036\053\001\002\000\006\017" +
+ "\ufffd\022\051\001\002\000\004\017\203\001\002\000\022" +
+ "\005\ufffc\007\ufffc\010\ufffc\011\ufffc\012\ufffc\013\ufffc\014" +
+ "\ufffc\035\ufffc\001\002\000\022\005\210\007\ufff2\010\ufff2" +
+ "\011\ufff2\012\ufff2\013\ufff2\014\ufff2\035\ufff2\001\002\000" +
+ "\022\005\ufff9\007\ufff9\010\ufff9\011\ufff9\012\ufff9\013\ufff9" +
+ "\014\ufff9\035\ufff9\001\002\000\020\007\223\010\224\011" +
+ "\007\012\012\013\227\014\225\035\014\001\002\000\022" +
+ "\005\ufffa\007\ufffa\010\ufffa\011\ufffa\012\ufffa\013\ufffa\014" +
+ "\ufffa\035\ufffa\001\002\000\042\003\054\006\026\007\027" +
+ "\010\040\011\036\012\022\013\042\014\030\015\017\016" +
+ "\015\026\033\027\023\030\035\031\041\035\025\036\053" +
+ "\001\002\000\006\017\uffb5\022\215\001\002\000\004\017" +
+ "\ufff8\001\002\000\004\017\214\001\002\000\022\005\ufff7" +
+ "\007\ufff7\010\ufff7\011\ufff7\012\ufff7\013\ufff7\014\ufff7\035" +
+ "\ufff7\001\002\000\044\003\054\006\026\007\027\010\040" +
+ "\011\036\012\022\013\042\014\030\015\017\016\015\021" +
+ "\216\026\033\027\023\030\035\031\041\035\025\036\053" +
+ "\001\002\000\004\017\uffb6\001\002\000\020\007\ufff3\010" +
+ "\ufff3\011\ufff3\012\ufff3\013\ufff3\014\ufff3\035\ufff3\001\002" +
+ "\000\020\007\ufff5\010\ufff5\011\ufff5\012\ufff5\013\ufff5\014" +
+ "\ufff5\035\ufff5\001\002\000\020\007\ufff1\010\ufff1\011\ufff1" +
+ "\012\ufff1\013\ufff1\014\ufff1\035\ufff1\001\002\000\020\007" +
+ "\ufff4\010\ufff4\011\ufff4\012\ufff4\013\ufff4\014\ufff4\035\ufff4" +
+ "\001\002\000\004\006\246\001\002\000\004\006\243\001" +
+ "\002\000\004\015\240\001\002\000\020\007\ufff6\010\ufff6" +
+ "\011\ufff6\012\ufff6\013\ufff6\014\ufff6\035\ufff6\001\002\000" +
+ "\004\015\234\001\002\000\020\003\uff97\011\007\012\012" +
+ "\016\uff97\026\065\035\014\036\uff97\001\002\000\010\003" +
+ "\uff97\016\116\036\uff97\001\002\000\006\003\126\036\120" +
+ "\001\002\000\010\002\uffff\003\126\036\120\001\002\000" +
+ "\004\037\235\001\002\000\022\007\uff99\010\uff99\011\uff99" +
+ "\012\uff99\013\uff99\014\uff99\017\236\035\uff99\001\002\000" +
+ "\020\007\uff98\010\uff98\011\uff98\012\uff98\013\uff98\014\uff98" +
+ "\035\uff98\001\002\000\020\007\uffee\010\uffee\011\uffee\012" +
+ "\uffee\013\uffee\014\uffee\035\uffee\001\002\000\004\037\241" +
+ "\001\002\000\022\007\uff99\010\uff99\011\uff99\012\uff99\013" +
+ "\uff99\014\uff99\017\236\035\uff99\001\002\000\020\007\uffed" +
+ "\010\uffed\011\uffed\012\uffed\013\uffed\014\uffed\035\uffed\001" +
+ "\002\000\004\037\244\001\002\000\022\007\uff99\010\uff99" +
+ "\011\uff99\012\uff99\013\uff99\014\uff99\017\236\035\uff99\001" +
+ "\002\000\020\007\uffef\010\uffef\011\uffef\012\uffef\013\uffef" +
+ "\014\uffef\035\uffef\001\002\000\004\037\247\001\002\000" +
+ "\022\007\uff99\010\uff99\011\uff99\012\uff99\013\uff99\014\uff99" +
+ "\017\236\035\uff99\001\002\000\020\007\ufff0\010\ufff0\011" +
+ "\ufff0\012\ufff0\013\ufff0\014\ufff0\035\ufff0\001\002\000\004" +
+ "\002\001\001\002" });
+
+ /** Access to parse-action table. */
+ public short[][] action_table() {return _action_table;}
+
+ /** <code>reduce_goto</code> table. */
+ protected static final short[][] _reduce_table =
+ unpackFromStrings(new String[] {
+ "\000\247\000\006\003\003\055\004\001\001\000\002\001" +
+ "\001\000\006\004\176\037\175\001\001\000\010\012\012" +
+ "\014\010\024\007\001\001\000\016\017\020\025\160\026" +
+ "\164\033\161\044\163\054\030\001\001\000\002\001\001" +
+ "\000\016\012\012\024\065\037\063\040\061\041\066\043" +
+ "\062\001\001\000\002\001\001\000\016\017\020\025\023" +
+ "\027\017\034\036\045\031\054\030\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\004\063\055\001\001\000\002\001\001\000\002\001" +
+ "\001\000\002\001\001\000\010\027\017\034\036\045\045" +
+ "\001\001\000\002\001\001\000\002\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\002\001\001\000\004\061\042\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\002\001\001\000\002\001\001\000\002\001\001\000" +
+ "\002\001\001\000\002\001\001\000\002\001\001\000\002" +
+ "\001\001\000\002\001\001\000\004\054\051\001\001\000" +
+ "\002\001\001\000\002\001\001\000\002\001\001\000\004" +
+ "\034\057\001\001\000\002\001\001\000\002\001\001\000" +
+ "\002\001\001\000\002\001\001\000\006\015\114\037\113" +
+ "\001\001\000\004\041\112\001\001\000\002\001\001\000" +
+ "\002\001\001\000\002\001\001\000\002\001\001\000\004" +
+ "\066\107\001\001\000\004\064\104\001\001\000\004\065" +
+ "\072\001\001\000\012\042\077\047\074\052\100\053\075" +
+ "\001\001\000\002\001\001\000\002\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\002\001\001\000\010\047\074\052\103\053\075\001" +
+ "\001\000\002\001\001\000\012\042\105\047\074\052\100" +
+ "\053\075\001\001\000\002\001\001\000\002\001\001\000" +
+ "\012\042\110\047\074\052\100\053\075\001\001\000\002" +
+ "\001\001\000\002\001\001\000\002\001\001\000\002\001" +
+ "\001\000\010\016\126\030\127\046\124\001\001\000\002" +
+ "\001\001\000\004\046\120\001\001\000\002\001\001\000" +
+ "\004\067\122\001\001\000\002\001\001\000\002\001\001" +
+ "\000\002\001\001\000\004\070\133\001\001\000\004\072" +
+ "\131\001\001\000\006\030\130\046\124\001\001\000\002" +
+ "\001\001\000\002\001\001\000\002\001\001\000\002\001" +
+ "\001\000\002\001\001\000\004\071\135\001\001\000\012" +
+ "\031\137\035\141\036\140\037\136\001\001\000\002\001" +
+ "\001\000\006\032\150\047\147\001\001\000\002\001\001" +
+ "\000\002\001\001\000\002\001\001\000\010\031\137\036" +
+ "\144\037\136\001\001\000\002\001\001\000\002\001\001" +
+ "\000\006\047\074\053\156\001\001\000\006\037\151\051" +
+ "\152\001\001\000\002\001\001\000\002\001\001\000\002" +
+ "\001\001\000\006\050\154\054\155\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\010\026\164\033\161\044\174\001\001\000\002\001" +
+ "\001\000\004\060\172\001\001\000\002\001\001\000\004" +
+ "\062\165\001\001\000\002\001\001\000\004\033\170\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\002\001\001\000\002\001\001\000\002\001\001\000" +
+ "\002\001\001\000\006\005\203\037\204\001\001\000\006" +
+ "\017\200\054\030\001\001\000\004\056\201\001\001\000" +
+ "\002\001\001\000\002\001\001\000\006\007\205\020\206" +
+ "\001\001\000\002\001\001\000\022\006\225\010\220\012" +
+ "\012\013\217\014\227\022\221\023\216\024\007\001\001" +
+ "\000\002\001\001\000\010\017\210\021\211\054\030\001" +
+ "\001\000\002\001\001\000\004\057\212\001\001\000\002" +
+ "\001\001\000\002\001\001\000\004\054\051\001\001\000" +
+ "\002\001\001\000\002\001\001\000\002\001\001\000\002" +
+ "\001\001\000\002\001\001\000\002\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\016\012\012\024\065\037\063\040\230\041\066\043" +
+ "\062\001\001\000\006\015\231\037\113\001\001\000\010" +
+ "\016\232\030\127\046\124\001\001\000\006\030\130\046" +
+ "\124\001\001\000\002\001\001\000\004\011\236\001\001" +
+ "\000\002\001\001\000\002\001\001\000\002\001\001\000" +
+ "\004\011\241\001\001\000\002\001\001\000\002\001\001" +
+ "\000\004\011\244\001\001\000\002\001\001\000\002\001" +
+ "\001\000\004\011\247\001\001\000\002\001\001\000\002" +
+ "\001\001" });
+
+ /** Access to <code>reduce_goto</code> table. */
+ public short[][] reduce_table() {return _reduce_table;}
+
+ /** Instance of action encapsulation class. */
+ protected CUP$parser$actions action_obj;
+
+ /** Action encapsulation object initializer. */
+ protected void init_actions()
+ {
+ action_obj = new CUP$parser$actions(this);
+ }
+
+ /** Invoke a user supplied parse action. */
+ public java_cup.runtime.Symbol do_action(
+ int act_num,
+ java_cup.runtime.lr_parser parser,
+ java.util.Stack stack,
+ int top)
+ throws java.lang.Exception
+ {
+ /* call code in generated class */
+ return action_obj.CUP$parser$do_action(act_num, parser, stack, top);
+ }
+
+ /** Indicates start state. */
+ public int start_state() {return 0;}
+ /** Indicates start production. */
+ public int start_production() {return 0;}
+
+ /** <code>EOF</code> Symbol index. */
+ public int EOF_sym() {return 0;}
+
+ /** <code>error</code> Symbol index. */
+ public int error_sym() {return 1;}
+
+
+ /** User initialization code. */
+ public void user_init() throws java.lang.Exception
+ {
+ lexer.init();
+ }
+
+ /** Scan to get the next Symbol. */
+ public java_cup.runtime.Symbol scan()
+ throws java.lang.Exception
+ {
+ return lexer.next_token();
+ }
+
+
+
+ /* override error routines */
+
+ public void report_fatal_error(
+ String message,
+ Object info)
+ {
+ done_parsing();
+ lexer.emit_error(message);
+ System.err.println("Can't recover from previous error(s), giving up.");
+ System.exit(1);
+ }
+
+ public void report_error(String message, Object info)
+ {
+ lexer.emit_error(message);
+ }
+
+}
+
+/** Cup generated class to encapsulate user supplied action code.*/
+class CUP$parser$actions {
+
+
+ /** helper routine to clone a new production part adding a given label */
+ protected production_part add_lab(production_part part, String lab)
+ throws internal_error
+ {
+ /* if there is no label, or this is an action, just return the original */
+ if (lab == null || part.is_action()) return part;
+
+ /* otherwise build a new one with the given label attached */
+ return new symbol_part(((symbol_part)part).the_symbol(),lab);
+ }
+
+ /** max size of right hand side we will support */
+ protected final int MAX_RHS = 200;
+
+ /** array for accumulating right hand side parts */
+ protected production_part[] rhs_parts = new production_part[MAX_RHS];
+
+ /** where we are currently in building a right hand side */
+ protected int rhs_pos = 0;
+
+ /** start a new right hand side */
+ protected void new_rhs() {rhs_pos = 0; }
+
+ /** add a new right hand side part */
+ protected void add_rhs_part(production_part part) throws java.lang.Exception
+ {
+ if (rhs_pos >= MAX_RHS)
+ throw new Exception("Internal Error: Productions limited to " +
+ MAX_RHS + " symbols and actions");
+
+ rhs_parts[rhs_pos] = part;
+ rhs_pos++;
+ }
+
+ /** string to build up multiple part names */
+ protected String multipart_name = new String();
+
+ /** append a new name segment to the accumulated multipart name */
+ protected void append_multipart(String name)
+ {
+ String dot = "";
+
+ /* if we aren't just starting out, put on a dot */
+ if (multipart_name.length() != 0) dot = ".";
+
+ multipart_name = multipart_name.concat(dot + name);
+ }
+
+ /** table of declared symbols -- contains production parts indexed by name */
+ protected Hashtable symbols = new Hashtable();
+
+ /** table of just non terminals -- contains non_terminals indexed by name */
+ protected Hashtable non_terms = new Hashtable();
+
+ /** declared start non_terminal */
+ protected non_terminal start_nt = null;
+
+ /** left hand side non terminal of the current production */
+ protected non_terminal lhs_nt;
+
+ /** Current precedence number */
+ int _cur_prec = 0;
+
+ /** Current precedence side */
+ int _cur_side = assoc.no_prec;
+
+ /** update the precedences we are declaring */
+ protected void update_precedence(int p) {
+ _cur_side = p;
+ _cur_prec++;
+ }
+ /** add relevant data to terminals */
+ protected void add_precedence(String term) {
+ if (term == null) {
+ System.err.println("Unable to add precedence to nonexistent terminal");
+ } else {
+ symbol_part sp = (symbol_part)symbols.get(term);
+ if (sp == null) {
+ System.err.println("Could find terminal " + term + " while declaring precedence");
+ } else {
+ java_cup.symbol sym = sp.the_symbol();
+ if (sym instanceof terminal)
+ ((terminal)sym).set_precedence(_cur_side, _cur_prec);
+ else System.err.println("Precedence declaration: Can't find terminal " + term);
+ }
+ }
+ }
+
+ private final parser parser;
+
+ /** Constructor */
+ CUP$parser$actions(parser parser) {
+ this.parser = parser;
+ }
+
+ /** Method with the actual generated action code. */
+ public final java_cup.runtime.Symbol CUP$parser$do_action(
+ int CUP$parser$act_num,
+ java_cup.runtime.lr_parser CUP$parser$parser,
+ java.util.Stack CUP$parser$stack,
+ int CUP$parser$top)
+ throws java.lang.Exception
+ {
+ /* Symbol object for return from actions */
+ java_cup.runtime.Symbol CUP$parser$result;
+
+ /* select the action based on the action number */
+ switch (CUP$parser$act_num)
+ {
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 106: // empty ::=
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(29/*empty*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 105: // opt_semi ::= SEMI
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(7/*opt_semi*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 104: // opt_semi ::=
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(7/*opt_semi*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 103: // non_terminal ::= NONTERMINAL
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(8/*non_terminal*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 102: // non_terminal ::= NON TERMINAL
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(8/*non_terminal*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 101: // robust_id ::= error
+ {
+ String RESULT = null;
+
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 100: // robust_id ::= NONASSOC
+ {
+ String RESULT = null;
+ RESULT = "nonassoc";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 99: // robust_id ::= RIGHT
+ {
+ String RESULT = null;
+ RESULT = "right";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 98: // robust_id ::= LEFT
+ {
+ String RESULT = null;
+ RESULT = "left";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 97: // robust_id ::= PRECEDENCE
+ {
+ String RESULT = null;
+ RESULT = "precedence";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 96: // robust_id ::= START
+ {
+ String RESULT = null;
+ RESULT = "start";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 95: // robust_id ::= WITH
+ {
+ String RESULT = null;
+ RESULT = "with";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 94: // robust_id ::= SCAN
+ {
+ String RESULT = null;
+ RESULT = "scan";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 93: // robust_id ::= INIT
+ {
+ String RESULT = null;
+ RESULT = "init";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 92: // robust_id ::= NONTERMINAL
+ {
+ String RESULT = null;
+ RESULT = "nonterminal";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 91: // robust_id ::= NON
+ {
+ String RESULT = null;
+ RESULT = "non";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 90: // robust_id ::= TERMINAL
+ {
+ String RESULT = null;
+ RESULT = "terminal";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 89: // robust_id ::= PARSER
+ {
+ String RESULT = null;
+ RESULT = "parser";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 88: // robust_id ::= ACTION
+ {
+ String RESULT = null;
+ RESULT = "action";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 87: // robust_id ::= CODE
+ {
+ String RESULT = null;
+ RESULT = "code";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 86: // robust_id ::= ID
+ {
+ String RESULT = null;
+ int the_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int the_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String the_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = the_id;
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 85: // label_id ::= robust_id
+ {
+ String RESULT = null;
+ int the_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int the_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String the_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = the_id;
+ CUP$parser$result = new java_cup.runtime.Symbol(38/*label_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 84: // symbol_id ::= error
+ {
+ String RESULT = null;
+
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+
+ CUP$parser$result = new java_cup.runtime.Symbol(37/*symbol_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 83: // symbol_id ::= ID
+ {
+ String RESULT = null;
+ int the_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int the_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String the_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = the_id;
+ CUP$parser$result = new java_cup.runtime.Symbol(37/*symbol_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 82: // nt_id ::= error
+ {
+ String RESULT = null;
+
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+
+ CUP$parser$result = new java_cup.runtime.Symbol(36/*nt_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 81: // nt_id ::= ID
+ {
+ String RESULT = null;
+ int the_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int the_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String the_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = the_id;
+ CUP$parser$result = new java_cup.runtime.Symbol(36/*nt_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 80: // new_non_term_id ::= ID
+ {
+ Object RESULT = null;
+ int non_term_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int non_term_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String non_term_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* see if this non terminal has been declared before */
+ if (symbols.get(non_term_id) != null)
+ {
+ /* issue a message */
+ lexer.emit_error( "java_cup.runtime.Symbol \"" + non_term_id +
+ "\" has already been declared");
+ }
+ else
+ {
+ if (multipart_name.equals("")) {
+ append_multipart("Object");
+ }
+ /* build the non terminal object */
+ non_terminal this_nt =
+ new non_terminal(non_term_id, multipart_name);
+
+ /* put it in the non_terms table */
+ non_terms.put(non_term_id, this_nt);
+
+ /* build a production_part and put it in the symbols table */
+ symbols.put(non_term_id, new symbol_part(this_nt));
+ }
+
+ CUP$parser$result = new java_cup.runtime.Symbol(26/*new_non_term_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 79: // new_term_id ::= ID
+ {
+ Object RESULT = null;
+ int term_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int term_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String term_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* see if this terminal has been declared before */
+ if (symbols.get(term_id) != null)
+ {
+ /* issue a message */
+ lexer.emit_error("java_cup.runtime.Symbol \"" + term_id +
+ "\" has already been declared");
+ }
+ else
+ {
+ /* if no type declared, declare one */
+ if (multipart_name.equals("")) {
+ append_multipart("Object");
+ }
+ /* build a production_part and put it in the table */
+ symbols.put(term_id,
+ new symbol_part(new terminal(term_id, multipart_name)));
+ }
+
+ CUP$parser$result = new java_cup.runtime.Symbol(25/*new_term_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 78: // type_id ::= type_id LBRACK RBRACK
+ {
+ Object RESULT = null;
+ multipart_name = multipart_name.concat("[]");
+ CUP$parser$result = new java_cup.runtime.Symbol(19/*type_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 77: // type_id ::= multipart_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(19/*type_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 76: // import_id ::= multipart_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(15/*import_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 75: // import_id ::= multipart_id DOT STAR
+ {
+ Object RESULT = null;
+ append_multipart("*");
+ CUP$parser$result = new java_cup.runtime.Symbol(15/*import_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 74: // multipart_id ::= robust_id
+ {
+ Object RESULT = null;
+ int an_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int an_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String an_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ append_multipart(an_id);
+ CUP$parser$result = new java_cup.runtime.Symbol(13/*multipart_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 73: // multipart_id ::= multipart_id DOT robust_id
+ {
+ Object RESULT = null;
+ int another_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int another_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String another_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ append_multipart(another_id);
+ CUP$parser$result = new java_cup.runtime.Symbol(13/*multipart_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 72: // opt_label ::= empty
+ {
+ String RESULT = null;
+ RESULT = null;
+ CUP$parser$result = new java_cup.runtime.Symbol(39/*opt_label*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 71: // opt_label ::= COLON label_id
+ {
+ String RESULT = null;
+ int labidleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int labidright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String labid = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = labid;
+ CUP$parser$result = new java_cup.runtime.Symbol(39/*opt_label*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 70: // prod_part ::= CODE_STRING
+ {
+ Object RESULT = null;
+ int code_strleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int code_strright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String code_str = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* add a new production part */
+ add_rhs_part(new action_part(code_str));
+
+ CUP$parser$result = new java_cup.runtime.Symbol(24/*prod_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 69: // prod_part ::= symbol_id opt_label
+ {
+ Object RESULT = null;
+ int symidleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int symidright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ String symid = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+ int labidleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int labidright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String labid = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* try to look up the id */
+ production_part symb = (production_part)symbols.get(symid);
+
+ /* if that fails, symbol is undeclared */
+ if (symb == null)
+ {
+ if (lexer.error_count == 0)
+ lexer.emit_error("java_cup.runtime.Symbol \"" + symid +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* add a labeled production part */
+ add_rhs_part(add_lab(symb, labid));
+ }
+
+ CUP$parser$result = new java_cup.runtime.Symbol(24/*prod_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 68: // prod_part_list ::= empty
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(23/*prod_part_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 67: // prod_part_list ::= prod_part_list prod_part
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(23/*prod_part_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 66: // rhs ::= prod_part_list
+ {
+ Object RESULT = null;
+
+ if (lhs_nt != null)
+ {
+ /* build the production */
+ production p = new production(lhs_nt, rhs_parts, rhs_pos);
+
+ /* if we have no start non-terminal declared and this is
+ the first production, make its lhs nt the start_nt
+ and build a special start production for it. */
+ if (start_nt == null)
+ {
+ start_nt = lhs_nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt),"start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+
+ new_rhs();
+ }
+ }
+
+ /* reset the rhs accumulation in any case */
+ new_rhs();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(28/*rhs*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 65: // rhs ::= prod_part_list PERCENT_PREC term_id
+ {
+ Object RESULT = null;
+ int term_nameleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int term_nameright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String term_name = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ java_cup.symbol sym = null;
+ if (lhs_nt != null)
+ {
+ /* Find the precedence symbol */
+ if (term_name == null) {
+ System.err.println("No terminal for contextual precedence");
+ sym = null;
+ } else {
+ sym = ((symbol_part)symbols.get(term_name)).the_symbol();
+ }
+ /* build the production */
+ production p;
+ if ((sym!=null) && (sym instanceof terminal)) {
+ p = new production(lhs_nt, rhs_parts, rhs_pos,
+ ((terminal)sym).precedence_num(),
+ ((terminal)sym).precedence_side());
+ ((symbol_part)symbols.get(term_name)).the_symbol().note_use();
+ } else {
+ System.err.println("Invalid terminal " + term_name +
+ " for contextual precedence assignment");
+ p = new production(lhs_nt, rhs_parts, rhs_pos);
+ }
+
+ /* if we have no start non-terminal declared and this is
+ the first production, make its lhs nt the start_nt
+ and build a special start production for it. */
+ if (start_nt == null)
+ {
+ start_nt = lhs_nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt),"start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ if ((sym!=null) && (sym instanceof terminal)) {
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts,
+ rhs_pos, ((terminal)sym).precedence_num(),
+ ((terminal)sym).precedence_side());
+ } else {
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+ }
+ new_rhs();
+ }
+ }
+
+ /* reset the rhs accumulation in any case */
+ new_rhs();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(28/*rhs*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 64: // rhs_list ::= rhs
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(27/*rhs_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 63: // rhs_list ::= rhs_list BAR rhs
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(27/*rhs_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 62: // production ::= error NT$13 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$13
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(22/*production*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 61: // NT$13 ::=
+ {
+ Object RESULT = null;
+ lexer.emit_error("Syntax Error");
+ CUP$parser$result = new java_cup.runtime.Symbol(56/*NT$13*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 60: // production ::= nt_id NT$11 COLON_COLON_EQUALS NT$12 rhs_list SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$11
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-4)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-4)).value;
+ // propagate RESULT from NT$12
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+ int lhs_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-5)).left;
+ int lhs_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-5)).right;
+ String lhs_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-5)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(22/*production*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-5)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 59: // NT$12 ::=
+ {
+ Object RESULT = null;
+ int lhs_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left;
+ int lhs_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right;
+ String lhs_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(55/*NT$12*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 58: // NT$11 ::=
+ {
+ Object RESULT = null;
+ int lhs_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int lhs_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String lhs_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* lookup the lhs nt */
+ lhs_nt = (non_terminal)non_terms.get(lhs_id);
+
+ /* if it wasn't declared, emit a message */
+ if (lhs_nt == null)
+ {
+ if (lexer.error_count == 0)
+ lexer.emit_error("LHS non terminal \"" + lhs_id +
+ "\" has not been declared");
+ }
+
+ /* reset the rhs accumulation */
+ new_rhs();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(54/*NT$11*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 57: // production_list ::= production
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(12/*production_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 56: // production_list ::= production_list production
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(12/*production_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 55: // start_spec ::= empty
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(11/*start_spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 54: // start_spec ::= START WITH nt_id NT$10 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$10
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+ int start_nameleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left;
+ int start_nameright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right;
+ String start_name = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(11/*start_spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-4)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 53: // NT$10 ::=
+ {
+ Object RESULT = null;
+ int start_nameleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int start_nameright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String start_name = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* verify that the name has been declared as a non terminal */
+ non_terminal nt = (non_terminal)non_terms.get(start_name);
+ if (nt == null)
+ {
+ lexer.emit_error( "Start non terminal \"" + start_name +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* remember the non-terminal for later */
+ start_nt = nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt), "start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+ new_rhs();
+ }
+
+ CUP$parser$result = new java_cup.runtime.Symbol(53/*NT$10*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 52: // term_id ::= symbol_id
+ {
+ String RESULT = null;
+ int symleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int symright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String sym = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* check that the symbol_id is a terminal */
+ if (symbols.get(sym) == null)
+ {
+ /* issue a message */
+ lexer.emit_error("Terminal \"" + sym +
+ "\" has not been declared");
+ }
+ RESULT = sym;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(41/*term_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 51: // terminal_id ::= term_id
+ {
+ String RESULT = null;
+ int symleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int symright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String sym = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ add_precedence(sym);
+ RESULT = sym;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(40/*terminal_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 50: // terminal_list ::= terminal_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(32/*terminal_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 49: // terminal_list ::= terminal_list COMMA terminal_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(32/*terminal_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 48: // preced ::= PRECEDENCE NONASSOC NT$9 terminal_list SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$9
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(31/*preced*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-4)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 47: // NT$9 ::=
+ {
+ Object RESULT = null;
+
+ update_precedence(assoc.nonassoc);
+
+ CUP$parser$result = new java_cup.runtime.Symbol(52/*NT$9*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 46: // preced ::= PRECEDENCE RIGHT NT$8 terminal_list SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$8
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(31/*preced*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-4)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 45: // NT$8 ::=
+ {
+ Object RESULT = null;
+
+ update_precedence(assoc.right);
+
+ CUP$parser$result = new java_cup.runtime.Symbol(51/*NT$8*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 44: // preced ::= PRECEDENCE LEFT NT$7 terminal_list SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$7
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(31/*preced*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-4)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 43: // NT$7 ::=
+ {
+ Object RESULT = null;
+
+ update_precedence(assoc.left);
+
+ CUP$parser$result = new java_cup.runtime.Symbol(50/*NT$7*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 42: // precedence_l ::= preced
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(33/*precedence_l*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 41: // precedence_l ::= precedence_l preced
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(33/*precedence_l*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 40: // precedence_list ::= empty
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(30/*precedence_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 39: // precedence_list ::= precedence_l
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(30/*precedence_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 38: // non_term_name_list ::= new_non_term_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(21/*non_term_name_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 37: // non_term_name_list ::= non_term_name_list COMMA new_non_term_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(21/*non_term_name_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 36: // term_name_list ::= new_term_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(20/*term_name_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 35: // term_name_list ::= term_name_list COMMA new_term_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(20/*term_name_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 34: // declares_non_term ::= non_term_name_list NT$6 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$6
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(35/*declares_non_term*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 33: // NT$6 ::=
+ {
+ Object RESULT = null;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(49/*NT$6*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 32: // declares_term ::= term_name_list NT$5 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$5
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(34/*declares_term*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 31: // NT$5 ::=
+ {
+ Object RESULT = null;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(48/*NT$5*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 30: // symbol ::= non_terminal error NT$4 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$4
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 29: // NT$4 ::=
+ {
+ Object RESULT = null;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(47/*NT$4*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 28: // symbol ::= TERMINAL error NT$3 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$3
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 27: // NT$3 ::=
+ {
+ Object RESULT = null;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(46/*NT$3*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 26: // symbol ::= non_terminal declares_non_term
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 25: // symbol ::= non_terminal type_id declares_non_term
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 24: // symbol ::= TERMINAL declares_term
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 23: // symbol ::= TERMINAL type_id declares_term
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 22: // symbol_list ::= symbol
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(10/*symbol_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 21: // symbol_list ::= symbol_list symbol
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(10/*symbol_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 20: // scan_code ::= SCAN WITH CODE_STRING opt_semi
+ {
+ Object RESULT = null;
+ int user_codeleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int user_coderight = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ String user_code = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ if (emit.scan_code!=null)
+ lexer.emit_error("Redundant scan code (skipping)");
+ else /* save the user code */
+ emit.scan_code = user_code;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(17/*scan_code*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 19: // init_code ::= INIT WITH CODE_STRING opt_semi
+ {
+ Object RESULT = null;
+ int user_codeleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int user_coderight = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ String user_code = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ if (emit.init_code!=null)
+ lexer.emit_error("Redundant init code (skipping)");
+ else /* save the user code */
+ emit.init_code = user_code;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(16/*init_code*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 18: // parser_code_part ::= PARSER CODE CODE_STRING opt_semi
+ {
+ Object RESULT = null;
+ int user_codeleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int user_coderight = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ String user_code = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ if (emit.parser_code!=null)
+ lexer.emit_error("Redundant parser code (skipping)");
+ else /* save the user included code string */
+ emit.parser_code = user_code;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(9/*parser_code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 17: // action_code_part ::= ACTION CODE CODE_STRING opt_semi
+ {
+ Object RESULT = null;
+ int user_codeleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int user_coderight = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ String user_code = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ if (emit.action_code!=null)
+ lexer.emit_error("Redundant action code (skipping)");
+ else /* save the user included code string */
+ emit.action_code = user_code;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(4/*action_code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 16: // code_parts ::= code_parts code_part
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(5/*code_parts*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 15: // code_parts ::=
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(5/*code_parts*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 14: // code_part ::= scan_code
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(6/*code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 13: // code_part ::= init_code
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(6/*code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 12: // code_part ::= parser_code_part
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(6/*code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 11: // code_part ::= action_code_part
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(6/*code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 10: // import_spec ::= IMPORT import_id NT$2 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$2
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(14/*import_spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 9: // NT$2 ::=
+ {
+ Object RESULT = null;
+
+ /* save this import on the imports list */
+ emit.import_list.push(multipart_name);
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(45/*NT$2*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 8: // import_list ::= empty
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*import_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 7: // import_list ::= import_list import_spec
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*import_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 6: // package_spec ::= empty
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(2/*package_spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 5: // package_spec ::= PACKAGE multipart_id NT$1 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$1
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(2/*package_spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 4: // NT$1 ::=
+ {
+ Object RESULT = null;
+
+ /* save the package name */
+ emit.package_name = multipart_name;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(44/*NT$1*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 3: // spec ::= error symbol_list precedence_list start_spec production_list
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(1/*spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-4)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 2: // spec ::= NT$0 package_spec import_list code_parts symbol_list precedence_list start_spec production_list
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$0
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-7)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-7)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(1/*spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-7)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 1: // NT$0 ::=
+ {
+ Object RESULT = null;
+
+ /* declare "error" as a terminal */
+ symbols.put("error", new symbol_part(terminal.error));
+
+ /* declare start non terminal */
+ non_terms.put("$START", non_terminal.START_nt);
+
+ CUP$parser$result = new java_cup.runtime.Symbol(43/*NT$0*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 0: // $START ::= spec EOF
+ {
+ Object RESULT = null;
+ int start_valleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int start_valright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ Object start_val = (Object)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+ RESULT = start_val;
+ CUP$parser$result = new java_cup.runtime.Symbol(0/*$START*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ /* ACCEPT */
+ CUP$parser$parser.done_parsing();
+ return CUP$parser$result;
+
+ /* . . . . . .*/
+ default:
+ throw new Exception(
+ "Invalid action number found in internal parse table");
+
+ }
+ }
+}
+
diff --git a/src/syntaxParser/java_cup/SAVE/production.java b/src/syntaxParser/java_cup/SAVE/production.java
new file mode 100644
index 0000000..5a41287
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/production.java
@@ -0,0 +1,756 @@
+
+package java_cup;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/** This class represents a production in the grammar. It contains
+ * a LHS non terminal, and an array of RHS symbols. As various
+ * transformations are done on the RHS of the production, it may shrink.
+ * As a result a separate length is always maintained to indicate how much
+ * of the RHS array is still valid.<p>
+ *
+ * I addition to construction and manipulation operations, productions provide
+ * methods for factoring out actions (see remove_embedded_actions()), for
+ * computing the nullability of the production (i.e., can it derive the empty
+ * string, see check_nullable()), and operations for computing its first
+ * set (i.e., the set of terminals that could appear at the beginning of some
+ * string derived from the production, see check_first_set()).
+ *
+ * @see java_cup.production_part
+ * @see java_cup.symbol_part
+ * @see java_cup.action_part
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+
+public class production {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor. This constructor accepts a LHS non terminal,
+ * an array of RHS parts (including terminals, non terminals, and
+ * actions), and a string for a final reduce action. It does several
+ * manipulations in the process of creating a production object.
+ * After some validity checking it translates labels that appear in
+ * actions into code for accessing objects on the runtime parse stack.
+ * It them merges adjacent actions if they appear and moves any trailing
+ * action into the final reduce actions string. Next it removes any
+ * embedded actions by factoring them out with new action productions.
+ * Finally it assigns a unique index to the production.<p>
+ *
+ * Factoring out of actions is accomplished by creating new "hidden"
+ * non terminals. For example if the production was originally: <pre>
+ * A ::= B {action} C D
+ * </pre>
+ * then it is factored into two productions:<pre>
+ * A ::= B X C D
+ * X ::= {action}
+ * </pre>
+ * (where X is a unique new non terminal). This has the effect of placing
+ * all actions at the end where they can be handled as part of a reduce by
+ * the parser.
+ */
+ public production(
+ non_terminal lhs_sym,
+ production_part rhs_parts[],
+ int rhs_l,
+ String action_str)
+ throws internal_error
+ {
+ int i;
+ action_part tail_action;
+ String declare_str;
+ int rightlen = rhs_l;
+
+ /* remember the length */
+ if (rhs_l >= 0)
+ _rhs_length = rhs_l;
+ else if (rhs_parts != null)
+ _rhs_length = rhs_parts.length;
+ else
+ _rhs_length = 0;
+
+ /* make sure we have a valid left-hand-side */
+ if (lhs_sym == null)
+ throw new internal_error(
+ "Attempt to construct a production with a null LHS");
+
+ /* I'm not translating labels anymore, I'm adding code to declare
+ labels as valid variables. This way, the users code string is
+ untouched
+ 6/96 frankf */
+
+ /* check if the last part of the right hand side is an action. If
+ it is, it won't be on the stack, so we don't want to count it
+ in the rightlen. Then when we search down the stack for a
+ Symbol, we don't try to search past action */
+
+ if (rhs_l > 0) {
+ if (rhs_parts[rhs_l - 1].is_action()) {
+ rightlen = rhs_l - 1;
+ } else {
+ rightlen = rhs_l;
+ }
+ }
+
+ /* get the generated declaration code for the necessary labels. */
+ declare_str = declare_labels(
+ rhs_parts, rightlen, action_str);
+
+ if (action_str == null)
+ action_str = declare_str;
+ else
+ action_str = declare_str + action_str;
+
+ /* count use of lhs */
+ lhs_sym.note_use();
+
+ /* create the part for left-hand-side */
+ _lhs = new symbol_part(lhs_sym);
+
+ /* merge adjacent actions (if any) */
+ _rhs_length = merge_adjacent_actions(rhs_parts, _rhs_length);
+
+ /* strip off any trailing action */
+ tail_action = strip_trailing_action(rhs_parts, _rhs_length);
+ if (tail_action != null) _rhs_length--;
+
+ /* Why does this run through the right hand side happen
+ over and over? here a quick combination of two
+ prior runs plus one I wanted of my own
+ frankf 6/25/96 */
+ /* allocate and copy over the right-hand-side */
+ /* count use of each rhs symbol */
+ _rhs = new production_part[_rhs_length];
+ for (i=0; i<_rhs_length; i++) {
+ _rhs[i] = rhs_parts[i];
+ if (!_rhs[i].is_action()) {
+ ((symbol_part)_rhs[i]).the_symbol().note_use();
+ if (((symbol_part)_rhs[i]).the_symbol() instanceof terminal) {
+ _rhs_prec =
+ ((terminal)((symbol_part)_rhs[i]).the_symbol()).precedence_num();
+ _rhs_assoc =
+ ((terminal)((symbol_part)_rhs[i]).the_symbol()).precedence_side();
+ }
+ }
+ }
+
+ /*now action string is really declaration string, so put it in front!
+ 6/14/96 frankf */
+ if (action_str == null) action_str = "";
+ if (tail_action != null && tail_action.code_string() != null)
+ action_str = action_str + "\t\t" + tail_action.code_string();
+
+ /* stash the action */
+ _action = new action_part(action_str);
+
+ /* rewrite production to remove any embedded actions */
+ remove_embedded_actions();
+
+ /* assign an index */
+ _index = next_index++;
+
+ /* put us in the global collection of productions */
+ _all.put(new Integer(_index),this);
+
+ /* put us in the production list of the lhs non terminal */
+ lhs_sym.add_production(this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with no action string. */
+ public production(
+ non_terminal lhs_sym,
+ production_part rhs_parts[],
+ int rhs_l)
+ throws internal_error
+ {
+ this(lhs_sym,rhs_parts,rhs_l,null);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /* Constructor with precedence and associativity of production
+ contextually define */
+ public production(
+ non_terminal lhs_sym,
+ production_part rhs_parts[],
+ int rhs_l,
+ String action_str,
+ int prec_num,
+ int prec_side)
+ throws internal_error
+ {
+ this(lhs_sym,rhs_parts,rhs_l,action_str);
+
+ /* set the precedence */
+ set_precedence_num(prec_num);
+ set_precedence_side(prec_side);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /* Constructor w/ no action string and contextual precedence
+ defined */
+ public production(
+ non_terminal lhs_sym,
+ production_part rhs_parts[],
+ int rhs_l,
+ int prec_num,
+ int prec_side)
+ throws internal_error
+ {
+ this(lhs_sym,rhs_parts,rhs_l,null);
+ /* set the precedence */
+ set_precedence_num(prec_num);
+ set_precedence_side(prec_side);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+
+ /** Table of all productions. Elements are stored using their index as
+ * the key.
+ */
+ protected static Hashtable _all = new Hashtable();
+
+ /** Access to all productions. */
+ public static Enumeration all() {return _all.elements();}
+
+ /** Lookup a production by index. */
+ public static production find(int indx) {
+ return (production) _all.get(new Integer(indx));
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Total number of productions. */
+ public static int number() {return _all.size();}
+
+ /** Static counter for assigning unique index numbers. */
+ protected static int next_index;
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The left hand side non-terminal. */
+ protected symbol_part _lhs;
+
+ /** The left hand side non-terminal. */
+ public symbol_part lhs() {return _lhs;}
+
+
+ /** The precedence of the rule */
+ protected int _rhs_prec = -1;
+ protected int _rhs_assoc = -1;
+
+ /** Access to the precedence of the rule */
+ public int precedence_num() { return _rhs_prec; }
+ public int precedence_side() { return _rhs_assoc; }
+
+ /** Setting the precedence of a rule */
+ public void set_precedence_num(int prec_num) {
+ _rhs_prec = prec_num;
+ }
+ public void set_precedence_side(int prec_side) {
+ _rhs_assoc = prec_side;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** A collection of parts for the right hand side. */
+ protected production_part _rhs[];
+
+ /** Access to the collection of parts for the right hand side. */
+ public production_part rhs(int indx) throws internal_error
+ {
+ if (indx >= 0 && indx < _rhs_length)
+ return _rhs[indx];
+ else
+ throw new internal_error(
+ "Index out of range for right hand side of production");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** How much of the right hand side array we are presently using. */
+ protected int _rhs_length;
+
+ /** How much of the right hand side array we are presently using. */
+ public int rhs_length() {return _rhs_length;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** An action_part containing code for the action to be performed when we
+ * reduce with this production.
+ */
+ protected action_part _action;
+
+ /** An action_part containing code for the action to be performed when we
+ * reduce with this production.
+ */
+ public action_part action() {return _action;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Index number of the production. */
+ protected int _index;
+
+ /** Index number of the production. */
+ public int index() {return _index;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of number of reductions using this production. */
+ protected int _num_reductions = 0;
+
+ /** Count of number of reductions using this production. */
+ public int num_reductions() {return _num_reductions;}
+
+ /** Increment the count of reductions with this non-terminal */
+ public void note_reduction_use() {_num_reductions++;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Is the nullability of the production known or unknown? */
+ protected boolean _nullable_known = false;
+
+ /** Is the nullability of the production known or unknown? */
+ public boolean nullable_known() {return _nullable_known;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Nullability of the production (can it derive the empty string). */
+ protected boolean _nullable = false;
+
+ /** Nullability of the production (can it derive the empty string). */
+ public boolean nullable() {return _nullable;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** First set of the production. This is the set of terminals that
+ * could appear at the front of some string derived from this production.
+ */
+ protected terminal_set _first_set = new terminal_set();
+
+ /** First set of the production. This is the set of terminals that
+ * could appear at the front of some string derived from this production.
+ */
+ public terminal_set first_set() {return _first_set;}
+
+ /*-----------------------------------------------------------*/
+ /*--- Static Methods ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Determine if a given character can be a label id starter.
+ * @param c the character in question.
+ */
+ protected static boolean is_id_start(char c)
+ {
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_');
+
+ //later need to handle non-8-bit chars here
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if a character can be in a label id.
+ * @param c the character in question.
+ */
+ protected static boolean is_id_char(char c)
+ {
+ return is_id_start(c) || (c >= '0' && c <= '9');
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+
+ /** Return label declaration code
+ * @param labelname the label name
+ * @param stack_type the stack type of label?
+ * @author frankf
+ */
+ protected String make_declaration(
+ String labelname,
+ String stack_type,
+ int offset)
+ {
+ String ret;
+
+ /* Put in the left/right value labels */
+ if (emit.lr_values())
+ ret = "\t\tint " + labelname + "left = ((java_cup.runtime.Symbol)" +
+ emit.pre("stack") + ".elementAt(" + emit.pre("top") +
+ "-" + offset + ")).left;\n" +
+ "\t\tint " + labelname + "right = ((java_cup.runtime.Symbol)" +
+ emit.pre("stack") + ".elementAt(" + emit.pre("top") +
+ "-" + offset + ")).right;\n";
+ else ret = "";
+
+ /* otherwise, just declare label. */
+ return ret + "\t\t" + stack_type + " " + labelname + " = (" + stack_type +
+ ")((" + "java_cup.runtime.Symbol) " + emit.pre("stack") + ".elementAt(" + emit.pre("top")
+ + "-" + offset + ")).value;\n";
+
+ }
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Declare label names as valid variables within the action string
+ * @param rhs array of RHS parts.
+ * @param rhs_len how much of rhs to consider valid.
+ * @param final_action the final action string of the production.
+ * @param lhs_type the object type associated with the LHS symbol.
+ */
+ protected String declare_labels(
+ production_part rhs[],
+ int rhs_len,
+ String final_action)
+ {
+ String declaration = "";
+
+ symbol_part part;
+ action_part act_part;
+ int pos;
+
+ /* walk down the parts and extract the labels */
+ for (pos = 0; pos < rhs_len; pos++)
+ {
+ if (!rhs[pos].is_action())
+ {
+ part = (symbol_part)rhs[pos];
+
+ /* if it has a label, make declaration! */
+ if (part.label() != null)
+ {
+ declaration = declaration +
+ make_declaration(part.label(), part.the_symbol().stack_type(),
+ rhs_len-pos-1);
+ }
+ }
+ }
+ return declaration;
+ }
+
+
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Helper routine to merge adjacent actions in a set of RHS parts
+ * @param rhs_parts array of RHS parts.
+ * @param len amount of that array that is valid.
+ * @return remaining valid length.
+ */
+ protected int merge_adjacent_actions(production_part rhs_parts[], int len)
+ {
+ int from_loc, to_loc, merge_cnt;
+
+ /* bail out early if we have no work to do */
+ if (rhs_parts == null || len == 0) return 0;
+
+ merge_cnt = 0;
+ to_loc = -1;
+ for (from_loc=0; from_loc<len; from_loc++)
+ {
+ /* do we go in the current position or one further */
+ if (to_loc < 0 || !rhs_parts[to_loc].is_action()
+ || !rhs_parts[from_loc].is_action())
+ {
+ /* next one */
+ to_loc++;
+
+ /* clear the way for it */
+ if (to_loc != from_loc) rhs_parts[to_loc] = null;
+ }
+
+ /* if this is not trivial? */
+ if (to_loc != from_loc)
+ {
+ /* do we merge or copy? */
+ if (rhs_parts[to_loc] != null && rhs_parts[to_loc].is_action() &&
+ rhs_parts[from_loc].is_action())
+ {
+ /* merge */
+ rhs_parts[to_loc] = new action_part(
+ ((action_part)rhs_parts[to_loc]).code_string() +
+ ((action_part)rhs_parts[from_loc]).code_string());
+ merge_cnt++;
+ }
+ else
+ {
+ /* copy */
+ rhs_parts[to_loc] = rhs_parts[from_loc];
+ }
+ }
+ }
+
+ /* return the used length */
+ return len - merge_cnt;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Helper routine to strip a trailing action off rhs and return it
+ * @param rhs_parts array of RHS parts.
+ * @param len how many of those are valid.
+ * @return the removed action part.
+ */
+ protected action_part strip_trailing_action(
+ production_part rhs_parts[],
+ int len)
+ {
+ action_part result;
+
+ /* bail out early if we have nothing to do */
+ if (rhs_parts == null || len == 0) return null;
+
+ /* see if we have a trailing action */
+ if (rhs_parts[len-1].is_action())
+ {
+ /* snip it out and return it */
+ result = (action_part)rhs_parts[len-1];
+ rhs_parts[len-1] = null;
+ return result;
+ }
+ else
+ return null;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove all embedded actions from a production by factoring them
+ * out into individual action production using new non terminals.
+ * if the original production was: <pre>
+ * A ::= B {action1} C {action2} D
+ * </pre>
+ * then it will be factored into: <pre>
+ * A ::= B NT$1 C NT$2 D
+ * NT$1 ::= {action1}
+ * NT$2 ::= {action2}
+ * </pre>
+ * where NT$1 and NT$2 are new system created non terminals.
+ */
+
+ /* the declarations added to the parent production are also passed along,
+ as they should be perfectly valid in this code string, since it
+ was originally a code string in the parent, not on its own.
+ frank 6/20/96 */
+ protected void remove_embedded_actions(
+
+ ) throws internal_error
+ {
+ non_terminal new_nt;
+ production new_prod;
+ String declare_str;
+
+ /* walk over the production and process each action */
+ for (int act_loc = 0; act_loc < rhs_length(); act_loc++)
+ if (rhs(act_loc).is_action())
+ {
+
+
+ declare_str = declare_labels(
+ _rhs, act_loc, "");
+ /* create a new non terminal for the action production */
+ new_nt = non_terminal.create_new();
+ new_nt.is_embedded_action = true; /* 24-Mar-1998, CSA */
+
+ /* create a new production with just the action */
+ new_prod = new action_production(this, new_nt, null, 0,
+ declare_str + ((action_part)rhs(act_loc)).code_string());
+
+ /* replace the action with the generated non terminal */
+ _rhs[act_loc] = new symbol_part(new_nt);
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Check to see if the production (now) appears to be nullable.
+ * A production is nullable if its RHS could derive the empty string.
+ * This results when the RHS is empty or contains only non terminals
+ * which themselves are nullable.
+ */
+ public boolean check_nullable() throws internal_error
+ {
+ production_part part;
+ symbol sym;
+ int pos;
+
+ /* if we already know bail out early */
+ if (nullable_known()) return nullable();
+
+ /* if we have a zero size RHS we are directly nullable */
+ if (rhs_length() == 0)
+ {
+ /* stash and return the result */
+ return set_nullable(true);
+ }
+
+ /* otherwise we need to test all of our parts */
+ for (pos=0; pos<rhs_length(); pos++)
+ {
+ part = rhs(pos);
+
+ /* only look at non-actions */
+ if (!part.is_action())
+ {
+ sym = ((symbol_part)part).the_symbol();
+
+ /* if its a terminal we are definitely not nullable */
+ if (!sym.is_non_term())
+ return set_nullable(false);
+ /* its a non-term, is it marked nullable */
+ else if (!((non_terminal)sym).nullable())
+ /* this one not (yet) nullable, so we aren't */
+ return false;
+ }
+ }
+
+ /* if we make it here all parts are nullable */
+ return set_nullable(true);
+ }
+
+ /** set (and return) nullability */
+ boolean set_nullable(boolean v)
+ {
+ _nullable_known = true;
+ _nullable = v;
+ return v;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Update (and return) the first set based on current NT firsts.
+ * This assumes that nullability has already been computed for all non
+ * terminals and productions.
+ */
+ public terminal_set check_first_set() throws internal_error
+ {
+ int part;
+ symbol sym;
+
+ /* walk down the right hand side till we get past all nullables */
+ for (part=0; part<rhs_length(); part++)
+ {
+ /* only look at non-actions */
+ if (!rhs(part).is_action())
+ {
+ sym = ((symbol_part)rhs(part)).the_symbol();
+
+ /* is it a non-terminal?*/
+ if (sym.is_non_term())
+ {
+ /* add in current firsts from that NT */
+ _first_set.add(((non_terminal)sym).first_set());
+
+ /* if its not nullable, we are done */
+ if (!((non_terminal)sym).nullable())
+ break;
+ }
+ else
+ {
+ /* its a terminal -- add that to the set */
+ _first_set.add((terminal)sym);
+
+ /* we are done */
+ break;
+ }
+ }
+ }
+
+ /* return our updated first set */
+ return first_set();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(production other)
+ {
+ if (other == null) return false;
+ return other._index == _index;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof production))
+ return false;
+ else
+ return equals((production)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a hash code. */
+ public int hashCode()
+ {
+ /* just use a simple function of the index */
+ return _index*13;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+
+ /* catch any internal errors */
+ try {
+ result = "production [" + index() + "]: ";
+ result += ((lhs() != null) ? lhs().toString() : "$$NULL-LHS$$");
+ result += " :: = ";
+ for (int i = 0; i<rhs_length(); i++)
+ result += rhs(i) + " ";
+ result += ";";
+ if (action() != null && action().code_string() != null)
+ result += " {" + action().code_string() + "}";
+
+ if (nullable_known())
+ if (nullable())
+ result += "[NULLABLE]";
+ else
+ result += "[NOT NULLABLE]";
+ } catch (internal_error e) {
+ /* crash on internal error since we can't throw it from here (because
+ superclass does not throw anything. */
+ e.crash();
+ result = null;
+ }
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a simpler string. */
+ public String to_simple_string() throws internal_error
+ {
+ String result;
+
+ result = ((lhs() != null) ? lhs().the_symbol().name() : "NULL_LHS");
+ result += " ::= ";
+ for (int i = 0; i < rhs_length(); i++)
+ if (!rhs(i).is_action())
+ result += ((symbol_part)rhs(i)).the_symbol().name() + " ";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/syntaxParser/java_cup/SAVE/production_part.java b/src/syntaxParser/java_cup/SAVE/production_part.java
new file mode 100644
index 0000000..a790ec0
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/production_part.java
@@ -0,0 +1,94 @@
+package java_cup;
+
+/** This class represents one part (either a symbol or an action) of a
+ * production. In this base class it contains only an optional label
+ * string that the user can use to refer to the part within actions.<p>
+ *
+ * This is an abstract class.
+ *
+ * @see java_cup.production
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public abstract class production_part {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. */
+ public production_part(String lab)
+ {
+ _label = lab;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Optional label for referring to the part within an action (null for
+ * no label).
+ */
+ protected String _label;
+
+ /** Optional label for referring to the part within an action (null for
+ * no label).
+ */
+ public String label() {return _label;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Indicate if this is an action (rather than a symbol). Here in the
+ * base class, we don't this know yet, so its an abstract method.
+ */
+ public abstract boolean is_action();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(production_part other)
+ {
+ if (other == null) return false;
+
+ /* compare the labels */
+ if (label() != null)
+ return label().equals(other.label());
+ else
+ return other.label() == null;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof production_part))
+ return false;
+ else
+ return equals((production_part)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a hash code. */
+ public int hashCode()
+ {
+ return label()==null ? 0 : label().hashCode();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ if (label() != null)
+ return label() + ":";
+ else
+ return " ";
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/syntaxParser/java_cup/SAVE/reduce_action.java b/src/syntaxParser/java_cup/SAVE/reduce_action.java
new file mode 100644
index 0000000..e8f4c84
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/reduce_action.java
@@ -0,0 +1,84 @@
+
+package java_cup;
+
+/** This class represents a reduce action within the parse table.
+ * The action simply stores the production that it reduces with and
+ * responds to queries about its type.
+ *
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class reduce_action extends parse_action {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor.
+ * @param prod the production this action reduces with.
+ */
+ public reduce_action(production prod ) throws internal_error
+ {
+ /* sanity check */
+ if (prod == null)
+ throw new internal_error(
+ "Attempt to create a reduce_action with a null production");
+
+ _reduce_with = prod;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The production we reduce with. */
+ protected production _reduce_with;
+
+ /** The production we reduce with. */
+ public production reduce_with() {return _reduce_with;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Quick access to type of action. */
+ public int kind() {return REDUCE;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality test. */
+ public boolean equals(reduce_action other)
+ {
+ return other != null && other.reduce_with() == reduce_with();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality test. */
+ public boolean equals(Object other)
+ {
+ if (other instanceof reduce_action)
+ return equals((reduce_action)other);
+ else
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute a hash code. */
+ public int hashCode()
+ {
+ /* use the hash code of the production we are reducing with */
+ return reduce_with().hashCode();
+ }
+
+
+ /** Convert to string. */
+ public String toString()
+ {
+ return "REDUCE(with prod " + reduce_with().index() + ")";
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/syntaxParser/java_cup/SAVE/shift_action.java b/src/syntaxParser/java_cup/SAVE/shift_action.java
new file mode 100644
index 0000000..33fc17a
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/shift_action.java
@@ -0,0 +1,82 @@
+
+package java_cup;
+
+/** This class represents a shift action within the parse table.
+ * The action simply stores the state that it shifts to and responds
+ * to queries about its type.
+ *
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class shift_action extends parse_action {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor.
+ * @param shft_to the state that this action shifts to.
+ */
+ public shift_action(lalr_state shft_to) throws internal_error
+ {
+ /* sanity check */
+ if (shft_to == null)
+ throw new internal_error(
+ "Attempt to create a shift_action to a null state");
+
+ _shift_to = shft_to;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The state we shift to. */
+ protected lalr_state _shift_to;
+
+ /** The state we shift to. */
+ public lalr_state shift_to() {return _shift_to;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Quick access to type of action. */
+ public int kind() {return SHIFT;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality test. */
+ public boolean equals(shift_action other)
+ {
+ return other != null && other.shift_to() == shift_to();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality test. */
+ public boolean equals(Object other)
+ {
+ if (other instanceof shift_action)
+ return equals((shift_action)other);
+ else
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute a hash code. */
+ public int hashCode()
+ {
+ /* use the hash code of the state we are shifting to */
+ return shift_to().hashCode();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString() {return "SHIFT(to state " + shift_to().index() + ")";}
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/syntaxParser/java_cup/SAVE/sym.java b/src/syntaxParser/java_cup/SAVE/sym.java
new file mode 100644
index 0000000..9810a3d
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/sym.java
@@ -0,0 +1,43 @@
+
+//----------------------------------------------------
+// The following code was generated by CUP v0.10k
+// Sun Jul 25 13:35:26 EDT 1999
+//----------------------------------------------------
+
+package java_cup;
+
+/** CUP generated class containing symbol constants. */
+public class sym {
+ /* terminals */
+ public static final int NON = 8;
+ public static final int NONTERMINAL = 27;
+ public static final int STAR = 15;
+ public static final int SEMI = 13;
+ public static final int CODE = 4;
+ public static final int EOF = 0;
+ public static final int NONASSOC = 23;
+ public static final int LEFT = 21;
+ public static final int PACKAGE = 2;
+ public static final int COLON = 17;
+ public static final int WITH = 11;
+ public static final int IMPORT = 3;
+ public static final int error = 1;
+ public static final int COLON_COLON_EQUALS = 18;
+ public static final int COMMA = 14;
+ public static final int DOT = 16;
+ public static final int SCAN = 10;
+ public static final int ID = 28;
+ public static final int INIT = 9;
+ public static final int PARSER = 6;
+ public static final int TERMINAL = 7;
+ public static final int PRECEDENCE = 20;
+ public static final int LBRACK = 25;
+ public static final int RBRACK = 26;
+ public static final int PERCENT_PREC = 24;
+ public static final int START = 12;
+ public static final int RIGHT = 22;
+ public static final int BAR = 19;
+ public static final int ACTION = 5;
+ public static final int CODE_STRING = 29;
+}
+
diff --git a/src/syntaxParser/java_cup/SAVE/symbol.java b/src/syntaxParser/java_cup/SAVE/symbol.java
new file mode 100644
index 0000000..94d8b7d
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/symbol.java
@@ -0,0 +1,107 @@
+package java_cup;
+
+/** This abstract class serves as the base class for grammar symbols (i.e.,
+ * both terminals and non-terminals). Each symbol has a name string, and
+ * a string giving the type of object that the symbol will be represented by
+ * on the runtime parse stack. In addition, each symbol maintains a use count
+ * in order to detect symbols that are declared but never used, and an index
+ * number that indicates where it appears in parse tables (index numbers are
+ * unique within terminals or non terminals, but not across both).
+ *
+ * @see java_cup.terminal
+ * @see java_cup.non_terminal
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+public abstract class symbol {
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param nm the name of the symbol.
+ * @param tp a string with the type name.
+ */
+ public symbol(String nm, String tp)
+ {
+ /* sanity check */
+ if (nm == null) nm = "";
+
+ /* apply default if no type given */
+ if (tp == null) tp = "Object";
+
+ _name = nm;
+ _stack_type = tp;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with default type.
+ * @param nm the name of the symbol.
+ */
+ public symbol(String nm)
+ {
+ this(nm, null);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** String for the human readable name of the symbol. */
+ protected String _name;
+
+ /** String for the human readable name of the symbol. */
+ public String name() {return _name;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** String for the type of object used for the symbol on the parse stack. */
+ protected String _stack_type;
+
+ /** String for the type of object used for the symbol on the parse stack. */
+ public String stack_type() {return _stack_type;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of how many times the symbol appears in productions. */
+ protected int _use_count = 0;
+
+ /** Count of how many times the symbol appears in productions. */
+ public int use_count() {return _use_count;}
+
+ /** Increment the use count. */
+ public void note_use() {_use_count++;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Index of this symbol (terminal or non terminal) in the parse tables.
+ * Note: indexes are unique among terminals and unique among non terminals,
+ * however, a terminal may have the same index as a non-terminal, etc.
+ */
+ protected int _index;
+
+ /** Index of this symbol (terminal or non terminal) in the parse tables.
+ * Note: indexes are unique among terminals and unique among non terminals,
+ * however, a terminal may have the same index as a non-terminal, etc.
+ */
+ public int index() {return _index;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Indicate if this is a non-terminal. Here in the base class we
+ * don't know, so this is abstract.
+ */
+ public abstract boolean is_non_term();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ return name();
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/syntaxParser/java_cup/SAVE/symbol_part.java b/src/syntaxParser/java_cup/SAVE/symbol_part.java
new file mode 100644
index 0000000..9142b5f
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/symbol_part.java
@@ -0,0 +1,100 @@
+package java_cup;
+
+/** This class represents a part of a production which is a symbol (terminal
+ * or non terminal). This simply maintains a reference to the symbol in
+ * question.
+ *
+ * @see java_cup.production
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class symbol_part extends production_part {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param sym the symbol that this part is made up of.
+ * @param lab an optional label string for the part.
+ */
+ public symbol_part(symbol sym, String lab) throws internal_error
+ {
+ super(lab);
+
+ if (sym == null)
+ throw new internal_error(
+ "Attempt to construct a symbol_part with a null symbol");
+ _the_symbol = sym;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with no label.
+ * @param sym the symbol that this part is made up of.
+ */
+ public symbol_part(symbol sym) throws internal_error
+ {
+ this(sym,null);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The symbol that this part is made up of. */
+ protected symbol _the_symbol;
+
+ /** The symbol that this part is made up of. */
+ public symbol the_symbol() {return _the_symbol;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Respond that we are not an action part. */
+ public boolean is_action() { return false; }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(symbol_part other)
+ {
+ return other != null && super.equals(other) &&
+ the_symbol().equals(other.the_symbol());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof symbol_part))
+ return false;
+ else
+ return equals((symbol_part)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a hash code. */
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ (the_symbol()==null ? 0 : the_symbol().hashCode());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ if (the_symbol() != null)
+ return super.toString() + the_symbol();
+ else
+ return super.toString() + "$$MISSING-SYMBOL$$";
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/syntaxParser/java_cup/SAVE/symbol_set.java b/src/syntaxParser/java_cup/SAVE/symbol_set.java
new file mode 100644
index 0000000..a1aec10
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/symbol_set.java
@@ -0,0 +1,231 @@
+
+package java_cup;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/** This class represents a set of symbols and provides a series of
+ * set operations to manipulate them.
+ *
+ * @see java_cup.symbol
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class symbol_set {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constructor for an empty set. */
+ public symbol_set() { }
+
+ /** Constructor for cloning from another set.
+ * @param other the set we are cloning from.
+ */
+ public symbol_set(symbol_set other) throws internal_error
+ {
+ not_null(other);
+ _all = (Hashtable)other._all.clone();
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** A hash table to hold the set. Symbols are keyed using their name string.
+ */
+ protected Hashtable _all = new Hashtable(11);
+
+ /** Access to all elements of the set. */
+ public Enumeration all() {return _all.elements();}
+
+ /** size of the set */
+ public int size() {return _all.size();}
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Helper function to test for a null object and throw an exception
+ * if one is found.
+ * @param obj the object we are testing.
+ */
+ protected void not_null(Object obj) throws internal_error
+ {
+ if (obj == null)
+ throw new internal_error("Null object used in set operation");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if the set contains a particular symbol.
+ * @param sym the symbol we are looking for.
+ */
+ public boolean contains(symbol sym) {return _all.containsKey(sym.name());}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if this set is an (improper) subset of another.
+ * @param other the set we are testing against.
+ */
+ public boolean is_subset_of(symbol_set other) throws internal_error
+ {
+ not_null(other);
+
+ /* walk down our set and make sure every element is in the other */
+ for (Enumeration e = all(); e.hasMoreElements(); )
+ if (!other.contains((symbol)e.nextElement()))
+ return false;
+
+ /* they were all there */
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if this set is an (improper) superset of another.
+ * @param other the set we are are testing against.
+ */
+ public boolean is_superset_of(symbol_set other) throws internal_error
+ {
+ not_null(other);
+ return other.is_subset_of(this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a single symbol to the set.
+ * @param sym the symbol we are adding.
+ * @return true if this changes the set.
+ */
+ public boolean add(symbol sym) throws internal_error
+ {
+ Object previous;
+
+ not_null(sym);
+
+ /* put the object in */
+ previous = _all.put(sym.name(),sym);
+
+ /* if we had a previous, this is no change */
+ return previous == null;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove a single symbol if it is in the set.
+ * @param sym the symbol we are removing.
+ */
+ public void remove(symbol sym) throws internal_error
+ {
+ not_null(sym);
+ _all.remove(sym.name());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add (union) in a complete set.
+ * @param other the set we are adding in.
+ * @return true if this changes the set.
+ */
+ public boolean add(symbol_set other) throws internal_error
+ {
+ boolean result = false;
+
+ not_null(other);
+
+ /* walk down the other set and do the adds individually */
+ for (Enumeration e = other.all(); e.hasMoreElements(); )
+ result = add((symbol)e.nextElement()) || result;
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove (set subtract) a complete set.
+ * @param other the set we are removing.
+ */
+ public void remove(symbol_set other) throws internal_error
+ {
+ not_null(other);
+
+ /* walk down the other set and do the removes individually */
+ for (Enumeration e = other.all(); e.hasMoreElements(); )
+ remove((symbol)e.nextElement());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(symbol_set other)
+ {
+ if (other == null || other.size() != size()) return false;
+
+ /* once we know they are the same size, then improper subset does test */
+ try {
+ return is_subset_of(other);
+ } catch (internal_error e) {
+ /* can't throw the error (because super class doesn't), so we crash */
+ e.crash();
+ return false;
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof symbol_set))
+ return false;
+ else
+ return equals((symbol_set)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute a hash code. */
+ public int hashCode()
+ {
+ int result = 0;
+ int cnt;
+ Enumeration e;
+
+ /* hash together codes from at most first 5 elements */
+ for (e = all(), cnt=0 ; e.hasMoreElements() && cnt<5; cnt++)
+ result ^= ((symbol)e.nextElement()).hashCode();
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+ boolean comma_flag;
+
+ result = "{";
+ comma_flag = false;
+ for (Enumeration e = all(); e.hasMoreElements(); )
+ {
+ if (comma_flag)
+ result += ", ";
+ else
+ comma_flag = true;
+
+ result += ((symbol)e.nextElement()).name();
+ }
+ result += "}";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
+
diff --git a/src/syntaxParser/java_cup/SAVE/terminal.java b/src/syntaxParser/java_cup/SAVE/terminal.java
new file mode 100644
index 0000000..e1a40aa
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/terminal.java
@@ -0,0 +1,169 @@
+package java_cup;
+
+import java_cup.assoc;
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/** This class represents a terminal symbol in the grammar. Each terminal
+ * has a textual name, an index, and a string which indicates the type of
+ * object it will be implemented with at runtime (i.e. the class of object
+ * that will be returned by the scanner and pushed on the parse stack to
+ * represent it).
+ *
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+public class terminal extends symbol {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param nm the name of the terminal.
+ * @param tp the type of the terminal.
+ */
+ public terminal(String nm, String tp, int precedence_side, int precedence_num)
+ {
+ /* superclass does most of the work */
+ super(nm, tp);
+
+ /* add to set of all terminals and check for duplicates */
+ Object conflict = _all.put(nm,this);
+ if (conflict != null)
+ // can't throw an execption here because this is used in static
+ // initializers, so we do a crash instead
+ // was:
+ // throw new internal_error("Duplicate terminal (" + nm + ") created");
+ (new internal_error("Duplicate terminal (" + nm + ") created")).crash();
+
+ /* assign a unique index */
+ _index = next_index++;
+
+ /* set the precedence */
+ _precedence_num = precedence_num;
+ _precedence_side = precedence_side;
+
+ /* add to by_index set */
+ _all_by_index.put(new Integer(_index), this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor for non-precedented terminal
+ */
+
+ public terminal(String nm, String tp)
+ {
+ this(nm, tp, assoc.no_prec, -1);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with default type.
+ * @param nm the name of the terminal.
+ */
+ public terminal(String nm)
+ {
+ this(nm, null);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*------------------- Class Variables ---------------------*/
+ /*-----------------------------------------------------------*/
+
+ private int _precedence_num;
+ private int _precedence_side;
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Table of all terminals. Elements are stored using name strings as
+ * the key
+ */
+ protected static Hashtable _all = new Hashtable();
+
+ /** Access to all terminals. */
+ public static Enumeration all() {return _all.elements();}
+
+ /** Lookup a terminal by name string. */
+ public static terminal find(String with_name)
+ {
+ if (with_name == null)
+ return null;
+ else
+ return (terminal)_all.get(with_name);
+ }
+
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Table of all terminals indexed by their index number. */
+ protected static Hashtable _all_by_index = new Hashtable();
+
+ /** Lookup a terminal by index. */
+ public static terminal find(int indx)
+ {
+ Integer the_indx = new Integer(indx);
+
+ return (terminal)_all_by_index.get(the_indx);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Total number of terminals. */
+ public static int number() {return _all.size();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Static counter to assign unique index. */
+ protected static int next_index = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Special terminal for end of input. */
+ public static final terminal EOF = new terminal("EOF");
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** special terminal used for error recovery */
+ public static final terminal error = new terminal("error");
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Report this symbol as not being a non-terminal. */
+ public boolean is_non_term()
+ {
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ return super.toString() + "[" + index() + "]";
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** get the precedence of a terminal */
+ public int precedence_num() {
+ return _precedence_num;
+ }
+ public int precedence_side() {
+ return _precedence_side;
+ }
+
+ /** set the precedence of a terminal */
+ public void set_precedence(int p, int new_prec) {
+ _precedence_side = p;
+ _precedence_num = new_prec;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/syntaxParser/java_cup/SAVE/terminal_set.java b/src/syntaxParser/java_cup/SAVE/terminal_set.java
new file mode 100644
index 0000000..e921cb5
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/terminal_set.java
@@ -0,0 +1,253 @@
+
+package java_cup;
+
+import java.util.BitSet;
+
+/** A set of terminals implemented as a bitset.
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class terminal_set {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constructor for an empty set. */
+ public terminal_set()
+ {
+ /* allocate the bitset at what is probably the right size */
+ _elements = new BitSet(terminal.number());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor for cloning from another set.
+ * @param other the set we are cloning from.
+ */
+ public terminal_set(terminal_set other)
+ throws internal_error
+ {
+ not_null(other);
+ _elements = (BitSet)other._elements.clone();
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constant for the empty set. */
+ public static final terminal_set EMPTY = new terminal_set();
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Bitset to implement the actual set. */
+ protected BitSet _elements;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Helper function to test for a null object and throw an exception if
+ * one is found.
+ * @param obj the object we are testing.
+ */
+ protected void not_null(Object obj) throws internal_error
+ {
+ if (obj == null)
+ throw new internal_error("Null object used in set operation");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if the set is empty. */
+ public boolean empty()
+ {
+ return equals(EMPTY);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if the set contains a particular terminal.
+ * @param sym the terminal symbol we are looking for.
+ */
+ public boolean contains(terminal sym)
+ throws internal_error
+ {
+ not_null(sym);
+ return _elements.get(sym.index());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Given its index determine if the set contains a particular terminal.
+ * @param indx the index of the terminal in question.
+ */
+ public boolean contains(int indx)
+ {
+ return _elements.get(indx);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if this set is an (improper) subset of another.
+ * @param other the set we are testing against.
+ */
+ public boolean is_subset_of(terminal_set other)
+ throws internal_error
+ {
+ not_null(other);
+
+ /* make a copy of the other set */
+ BitSet copy_other = (BitSet)other._elements.clone();
+
+ /* and or in */
+ copy_other.or(_elements);
+
+ /* if it hasn't changed, we were a subset */
+ return copy_other.equals(other._elements);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if this set is an (improper) superset of another.
+ * @param other the set we are testing against.
+ */
+ public boolean is_superset_of(terminal_set other)
+ throws internal_error
+ {
+ not_null(other);
+ return other.is_subset_of(this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a single terminal to the set.
+ * @param sym the terminal being added.
+ * @return true if this changes the set.
+ */
+ public boolean add(terminal sym)
+ throws internal_error
+ {
+ boolean result;
+
+ not_null(sym);
+
+ /* see if we already have this */
+ result = _elements.get(sym.index());
+
+ /* if not we add it */
+ if (!result)
+ _elements.set(sym.index());
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove a terminal if it is in the set.
+ * @param sym the terminal being removed.
+ */
+ public void remove(terminal sym)
+ throws internal_error
+ {
+ not_null(sym);
+ _elements.clear(sym.index());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add (union) in a complete set.
+ * @param other the set being added.
+ * @return true if this changes the set.
+ */
+ public boolean add(terminal_set other)
+ throws internal_error
+ {
+ not_null(other);
+
+ /* make a copy */
+ BitSet copy = (BitSet)_elements.clone();
+
+ /* or in the other set */
+ _elements.or(other._elements);
+
+ /* changed if we are not the same as the copy */
+ return !_elements.equals(copy);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if this set intersects another.
+ * @param other the other set in question.
+ */
+ public boolean intersects(terminal_set other)
+ throws internal_error
+ {
+ not_null(other);
+
+ /* make a copy of the other set */
+ BitSet copy = (BitSet)other._elements.clone();
+
+ /* xor out our values */
+ copy.xor(this._elements);
+
+ /* see if its different */
+ return !copy.equals(other._elements);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(terminal_set other)
+ {
+ if (other == null)
+ return false;
+ else
+ return _elements.equals(other._elements);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof terminal_set))
+ return false;
+ else
+ return equals((terminal_set)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to string. */
+ public String toString()
+ {
+ String result;
+ boolean comma_flag;
+
+ result = "{";
+ comma_flag = false;
+ for (int t = 0; t < terminal.number(); t++)
+ {
+ if (_elements.get(t))
+ {
+ if (comma_flag)
+ result += ", ";
+ else
+ comma_flag = true;
+
+ result += terminal.find(t).name();
+ }
+ }
+ result += "}";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
diff --git a/src/syntaxParser/java_cup/SAVE/version.java b/src/syntaxParser/java_cup/SAVE/version.java
new file mode 100644
index 0000000..06600b5
--- /dev/null
+++ b/src/syntaxParser/java_cup/SAVE/version.java
@@ -0,0 +1,55 @@
+
+package java_cup;
+
+/** This class contains version and authorship information.
+ * It contains only static data elements and basically just a central
+ * place to put this kind of information so it can be updated easily
+ * for each release.
+ *
+ * Version numbers used here are broken into 3 parts: major, minor, and
+ * update, and are written as v<major>.<minor>.<update> (e.g. v0.10a).
+ * Major numbers will change at the time of major reworking of some
+ * part of the system. Minor numbers for each public release or
+ * change big enough to cause incompatibilities. Finally update
+ * letter will be incremented for small bug fixes and changes that
+ * probably wouldn't be noticed by a user.
+ *
+ * @version last updated: 12/22/97 [CSA]
+ * @author Frank Flannery
+ */
+
+public class version {
+ /** The major version number. */
+ public static final int major = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The minor version number. */
+ public static final int minor = 10;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The update letter. */
+ public static final char update = 'k';
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** String for the current version. */
+ public static final String version_str = "v" + major + "." + minor + update;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Full title of the system */
+ public static final String title_str = "CUP " + version_str;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Name of the author */
+ public static final String author_str =
+ "Scott E. Hudson, Frank Flannery, and C. Scott Ananian";
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The command name normally used to invoke this program */
+ public static final String program_name = "java_cup";
+}
diff --git a/src/syntaxParser/java_cup/action_part.class b/src/syntaxParser/java_cup/action_part.class
new file mode 100644
index 0000000..419eefb
--- /dev/null
+++ b/src/syntaxParser/java_cup/action_part.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/action_part.java b/src/syntaxParser/java_cup/action_part.java
new file mode 100644
index 0000000..69e98f5
--- /dev/null
+++ b/src/syntaxParser/java_cup/action_part.java
@@ -0,0 +1,93 @@
+
+package java_cup;
+
+/**
+ * This class represents a part of a production which contains an
+ * action. These are eventually eliminated from productions and converted
+ * to trailing actions by factoring out with a production that derives the
+ * empty string (and ends with this action).
+ *
+ * @see java_cup.production
+ * @version last update: 11/25/95
+ * @author Scott Hudson
+ */
+
+public class action_part extends production_part {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructors ------------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor.
+ * @param code_str string containing the actual user code.
+ */
+ public action_part(String code_str)
+ {
+ super(/* never have a label on code */null);
+ _code_string = code_str;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** String containing code for the action in question. */
+ protected String _code_string;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** String containing code for the action in question. */
+ public String code_string() {return _code_string;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Set the code string. */
+ public void set_code_string(String new_str) {_code_string = new_str;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Override to report this object as an action. */
+ public boolean is_action() { return true; }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison for properly typed object. */
+ public boolean equals(action_part other)
+ {
+ /* compare the strings */
+ return other != null && super.equals(other) &&
+ other.code_string().equals(code_string());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof action_part))
+ return false;
+ else
+ return equals((action_part)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a hash code. */
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ (code_string()==null ? 0 : code_string().hashCode());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ return super.toString() + "{" + code_string() + "}";
+ }
+
+ /*-----------------------------------------------------------*/
+}
diff --git a/src/syntaxParser/java_cup/action_production.class b/src/syntaxParser/java_cup/action_production.class
new file mode 100644
index 0000000..01329be
--- /dev/null
+++ b/src/syntaxParser/java_cup/action_production.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/action_production.java b/src/syntaxParser/java_cup/action_production.java
new file mode 100644
index 0000000..3c0845f
--- /dev/null
+++ b/src/syntaxParser/java_cup/action_production.java
@@ -0,0 +1,39 @@
+
+package java_cup;
+
+/** A specialized version of a production used when we split an existing
+ * production in order to remove an embedded action. Here we keep a bit
+ * of extra bookkeeping so that we know where we came from.
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+
+public class action_production extends production {
+
+ /** Constructor.
+ * @param base the production we are being factored out of.
+ * @param lhs_sym the LHS symbol for this production.
+ * @param rhs_parts array of production parts for the RHS.
+ * @param rhs_len how much of the rhs_parts array is valid.
+ * @param action_str the trailing reduce action for this production.
+ */
+ public action_production(
+ production base,
+ non_terminal lhs_sym,
+ production_part rhs_parts[],
+ int rhs_len,
+ String action_str)
+ throws internal_error
+ {
+ super(lhs_sym, rhs_parts, rhs_len, action_str);
+ _base_production = base;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The production we were taken out of. */
+ protected production _base_production;
+
+ /** The production we were taken out of. */
+ public production base_production() {return _base_production;}
+}
diff --git a/src/syntaxParser/java_cup/assoc.class b/src/syntaxParser/java_cup/assoc.class
new file mode 100644
index 0000000..b81980a
--- /dev/null
+++ b/src/syntaxParser/java_cup/assoc.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/assoc.java b/src/syntaxParser/java_cup/assoc.java
new file mode 100644
index 0000000..8d0b50e
--- /dev/null
+++ b/src/syntaxParser/java_cup/assoc.java
@@ -0,0 +1,16 @@
+package java_cup;
+
+/* Defines integers that represent the associativity of terminals
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+
+public class assoc {
+
+ /* various associativities, no_prec being the default value */
+ public final static int left = 0;
+ public final static int right = 1;
+ public final static int nonassoc = 2;
+ public final static int no_prec = -1;
+
+} \ No newline at end of file
diff --git a/src/syntaxParser/java_cup/emit.class b/src/syntaxParser/java_cup/emit.class
new file mode 100644
index 0000000..602be0c
--- /dev/null
+++ b/src/syntaxParser/java_cup/emit.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/emit.java b/src/syntaxParser/java_cup/emit.java
new file mode 100644
index 0000000..9db9014
--- /dev/null
+++ b/src/syntaxParser/java_cup/emit.java
@@ -0,0 +1,897 @@
+package java_cup;
+
+import java.io.PrintWriter;
+import java.util.Stack;
+import java.util.Enumeration;
+import java.util.Date;
+
+/**
+ * This class handles emitting generated code for the resulting parser.
+ * The various parse tables must be constructed, etc. before calling any
+ * routines in this class.<p>
+ *
+ * Three classes are produced by this code:
+ * <dl>
+ * <dt> symbol constant class
+ * <dd> this contains constant declarations for each terminal (and
+ * optionally each non-terminal).
+ * <dt> action class
+ * <dd> this non-public class contains code to invoke all the user actions
+ * that were embedded in the parser specification.
+ * <dt> parser class
+ * <dd> the specialized parser class consisting primarily of some user
+ * supplied general and initialization code, and the parse tables.
+ * </dl><p>
+ *
+ * Three parse tables are created as part of the parser class:
+ * <dl>
+ * <dt> production table
+ * <dd> lists the LHS non terminal number, and the length of the RHS of
+ * each production.
+ * <dt> action table
+ * <dd> for each state of the parse machine, gives the action to be taken
+ * (shift, reduce, or error) under each lookahead symbol.<br>
+ * <dt> reduce-goto table
+ * <dd> when a reduce on a given production is taken, the parse stack is
+ * popped back a number of elements corresponding to the RHS of the
+ * production. This reveals a prior state, which we transition out
+ * of under the LHS non terminal symbol for the production (as if we
+ * had seen the LHS symbol rather than all the symbols matching the
+ * RHS). This table is indexed by non terminal numbers and indicates
+ * how to make these transitions.
+ * </dl><p>
+ *
+ * In addition to the method interface, this class maintains a series of
+ * public global variables and flags indicating how misc. parts of the code
+ * and other output is to be produced, and counting things such as number of
+ * conflicts detected (see the source code and public variables below for
+ * more details).<p>
+ *
+ * This class is "static" (contains only static data and methods).<p>
+ *
+ * @see java_cup.main
+ * @version last update: 11/25/95
+ * @author Scott Hudson
+ */
+
+/* Major externally callable routines here include:
+ symbols - emit the symbol constant class
+ parser - emit the parser class
+
+ In addition the following major internal routines are provided:
+ emit_package - emit a package declaration
+ emit_action_code - emit the class containing the user's actions
+ emit_production_table - emit declaration and init for the production table
+ do_action_table - emit declaration and init for the action table
+ do_reduce_table - emit declaration and init for the reduce-goto table
+
+ Finally, this class uses a number of public instance variables to communicate
+ optional parameters and flags used to control how code is generated,
+ as well as to report counts of various things (such as number of conflicts
+ detected). These include:
+
+ prefix - a prefix string used to prefix names that would
+ otherwise "pollute" someone else's name space.
+ package_name - name of the package emitted code is placed in
+ (or null for an unnamed package.
+ symbol_const_class_name - name of the class containing symbol constants.
+ parser_class_name - name of the class for the resulting parser.
+ action_code - user supplied declarations and other code to be
+ placed in action class.
+ parser_code - user supplied declarations and other code to be
+ placed in parser class.
+ init_code - user supplied code to be executed as the parser
+ is being initialized.
+ scan_code - user supplied code to get the next Symbol.
+ start_production - the start production for the grammar.
+ import_list - list of imports for use with action class.
+ num_conflicts - number of conflicts detected.
+ nowarn - true if we are not to issue warning messages.
+ not_reduced - count of number of productions that never reduce.
+ unused_term - count of unused terminal symbols.
+ unused_non_term - count of unused non terminal symbols.
+ *_time - a series of symbols indicating how long various
+ sub-parts of code generation took (used to produce
+ optional time reports in main).
+*/
+
+public class emit {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Only constructor is private so no instances can be created. */
+ private emit() { }
+
+ /*-----------------------------------------------------------*/
+ /*--- Static (Class) Variables ------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The prefix placed on names that pollute someone else's name space. */
+ public static String prefix = "CUP$";
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Package that the resulting code goes into (null is used for unnamed). */
+ public static String package_name = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Name of the generated class for symbol constants. */
+ public static String symbol_const_class_name = "sym";
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Name of the generated parser class. */
+ public static String parser_class_name = "parser";
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** User declarations for direct inclusion in user action class. */
+ public static String action_code = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** User declarations for direct inclusion in parser class. */
+ public static String parser_code = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** User code for user_init() which is called during parser initialization. */
+ public static String init_code = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** User code for scan() which is called to get the next Symbol. */
+ public static String scan_code = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The start production of the grammar. */
+ public static production start_production = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** List of imports (Strings containing class names) to go with actions. */
+ public static Stack import_list = new Stack();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Number of conflict found while building tables. */
+ public static int num_conflicts = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Do we skip warnings? */
+ public static boolean nowarn = false;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of the number on non-reduced productions found. */
+ public static int not_reduced = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of unused terminals. */
+ public static int unused_term = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of unused non terminals. */
+ public static int unused_non_term = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /* Timing values used to produce timing report in main.*/
+
+ /** Time to produce symbol constant class. */
+ public static long symbols_time = 0;
+
+ /** Time to produce parser class. */
+ public static long parser_time = 0;
+
+ /** Time to produce action code class. */
+ public static long action_code_time = 0;
+
+ /** Time to produce the production table. */
+ public static long production_table_time = 0;
+
+ /** Time to produce the action table. */
+ public static long action_table_time = 0;
+
+ /** Time to produce the reduce-goto table. */
+ public static long goto_table_time = 0;
+
+ /* frankf 6/18/96 */
+ protected static boolean _lr_values;
+
+ /** whether or not to emit code for left and right values */
+ public static boolean lr_values() {return _lr_values;}
+ protected static void set_lr_values(boolean b) { _lr_values = b;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Build a string with the standard prefix.
+ * @param str string to prefix.
+ */
+ protected static String pre(String str) {
+ return prefix + parser_class_name + "$" + str;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit a package spec if the user wants one.
+ * @param out stream to produce output on.
+ */
+ protected static void emit_package(PrintWriter out)
+ {
+ /* generate a package spec if we have a name for one */
+ if (package_name != null) {
+ out.println("package " + package_name + ";"); out.println();
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit code for the symbol constant class, optionally including non terms,
+ * if they have been requested.
+ * @param out stream to produce output on.
+ * @param emit_non_terms do we emit constants for non terminals?
+ * @param sym_interface should we emit an interface, rather than a class?
+ */
+ public static void symbols(PrintWriter out,
+ boolean emit_non_terms, boolean sym_interface)
+ {
+ terminal term;
+ non_terminal nt;
+ String class_or_interface = (sym_interface)?"interface":"class";
+
+ long start_time = System.currentTimeMillis();
+
+ /* top of file */
+ out.println();
+ out.println("//----------------------------------------------------");
+ out.println("// The following code was generated by " +
+ version.title_str);
+ out.println("// " + new Date());
+ out.println("//----------------------------------------------------");
+ out.println();
+ emit_package(out);
+
+ /* class header */
+ out.println("/** CUP generated " + class_or_interface +
+ " containing symbol constants. */");
+ out.println("public " + class_or_interface + " " +
+ symbol_const_class_name + " {");
+
+ out.println(" /* terminals */");
+
+ /* walk over the terminals */ /* later might sort these */
+ for (Enumeration e = terminal.all(); e.hasMoreElements(); )
+ {
+ term = (terminal)e.nextElement();
+
+ /* output a constant decl for the terminal */
+ out.println(" public static final int " + term.name() + " = " +
+ term.index() + ";");
+ }
+
+ /* do the non terminals if they want them (parser doesn't need them) */
+ if (emit_non_terms)
+ {
+ out.println();
+ out.println(" /* non terminals */");
+
+ /* walk over the non terminals */ /* later might sort these */
+ for (Enumeration e = non_terminal.all(); e.hasMoreElements(); )
+ {
+ nt = (non_terminal)e.nextElement();
+
+ /* output a constant decl for the terminal */
+ out.println(" static final int " + nt.name() + " = " +
+ nt.index() + ";");
+ }
+ }
+
+ /* end of class */
+ out.println("}");
+ out.println();
+
+ symbols_time = System.currentTimeMillis() - start_time;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit code for the non-public class holding the actual action code.
+ * @param out stream to produce output on.
+ * @param start_prod the start production of the grammar.
+ */
+ protected static void emit_action_code(PrintWriter out, production start_prod)
+ throws internal_error
+ {
+ production prod;
+
+ long start_time = System.currentTimeMillis();
+
+ /* class header */
+ out.println();
+ out.println(
+ "/** Cup generated class to encapsulate user supplied action code.*/"
+ );
+ out.println("class " + pre("actions") + " {");
+
+ /* user supplied code */
+ if (action_code != null)
+ {
+ out.println();
+ out.println(action_code);
+ }
+
+ /* field for parser object */
+ out.println(" private final "+parser_class_name+" parser;");
+
+ /* constructor */
+ out.println();
+ out.println(" /** Constructor */");
+ out.println(" " + pre("actions") + "("+parser_class_name+" parser) {");
+ out.println(" this.parser = parser;");
+ out.println(" }");
+
+ /* action method head */
+ out.println();
+ out.println(" /** Method with the actual generated action code. */");
+ out.println(" public final java_cup.runtime.Symbol " +
+ pre("do_action") + "(");
+ out.println(" int " + pre("act_num,"));
+ out.println(" java_cup.runtime.lr_parser " + pre("parser,"));
+ out.println(" java.util.Stack " + pre("stack,"));
+ out.println(" int " + pre("top)"));
+ out.println(" throws java.lang.Exception");
+ out.println(" {");
+
+ /* declaration of result symbol */
+ /* New declaration!! now return Symbol
+ 6/13/96 frankf */
+ out.println(" /* Symbol object for return from actions */");
+ out.println(" java_cup.runtime.Symbol " + pre("result") + ";");
+ out.println();
+
+ /* switch top */
+ out.println(" /* select the action based on the action number */");
+ out.println(" switch (" + pre("act_num") + ")");
+ out.println(" {");
+
+ /* emit action code for each production as a separate case */
+ for (Enumeration p = production.all(); p.hasMoreElements(); )
+ {
+ prod = (production)p.nextElement();
+
+ /* case label */
+ out.println(" /*. . . . . . . . . . . . . . . . . . . .*/");
+ out.println(" case " + prod.index() + ": // " +
+ prod.to_simple_string());
+
+ /* give them their own block to work in */
+ out.println(" {");
+
+ /* create the result symbol */
+ /*make the variable RESULT which will point to the new Symbol (see below)
+ and be changed by action code
+ 6/13/96 frankf */
+ out.println(" " + prod.lhs().the_symbol().stack_type() +
+ " RESULT = null;");
+
+ /* Add code to propagate RESULT assignments that occur in
+ * action code embedded in a production (ie, non-rightmost
+ * action code). 24-Mar-1998 CSA
+ */
+ for (int i=0; i<prod.rhs_length(); i++) {
+ // only interested in non-terminal symbols.
+ if (!(prod.rhs(i) instanceof symbol_part)) continue;
+ symbol s = ((symbol_part)prod.rhs(i)).the_symbol();
+ if (!(s instanceof non_terminal)) continue;
+ // skip this non-terminal unless it corresponds to
+ // an embedded action production.
+ if (((non_terminal)s).is_embedded_action == false) continue;
+ // OK, it fits. Make a conditional assignment to RESULT.
+ int index = prod.rhs_length() - i - 1; // last rhs is on top.
+ out.println(" " + "// propagate RESULT from " +
+ s.name());
+ out.println(" " + "if ( " +
+ "((java_cup.runtime.Symbol) " + emit.pre("stack") + ".elementAt("
+ + emit.pre("top") + "-" + index + ")).value != null )");
+ out.println(" " + "RESULT = " +
+ "(" + prod.lhs().the_symbol().stack_type() + ") " +
+ "((java_cup.runtime.Symbol) " + emit.pre("stack") + ".elementAt("
+ + emit.pre("top") + "-" + index + ")).value;");
+ }
+
+ /* if there is an action string, emit it */
+ if (prod.action() != null && prod.action().code_string() != null &&
+ !prod.action().equals(""))
+ out.println(prod.action().code_string());
+
+ /* here we have the left and right values being propagated.
+ must make this a command line option.
+ frankf 6/18/96 */
+
+ /* Create the code that assigns the left and right values of
+ the new Symbol that the production is reducing to */
+ if (emit.lr_values()) {
+ int loffset;
+ String leftstring, rightstring;
+ int roffset = 0;
+ rightstring = "((java_cup.runtime.Symbol)" + emit.pre("stack") + ".elementAt(" +
+ emit.pre("top") + "-" + roffset + ")).right";
+ if (prod.rhs_length() == 0)
+ leftstring = rightstring;
+ else {
+ loffset = prod.rhs_length() - 1;
+ leftstring = "((java_cup.runtime.Symbol)" + emit.pre("stack") + ".elementAt(" +
+ emit.pre("top") + "-" + loffset + ")).left";
+ }
+ out.println(" " + pre("result") + " = new java_cup.runtime.Symbol(" +
+ prod.lhs().the_symbol().index() + "/*" +
+ prod.lhs().the_symbol().name() + "*/" +
+ ", " + leftstring + ", " + rightstring + ", RESULT);");
+ } else {
+ out.println(" " + pre("result") + " = new java_cup.runtime.Symbol(" +
+ prod.lhs().the_symbol().index() + "/*" +
+ prod.lhs().the_symbol().name() + "*/" +
+ ", RESULT);");
+ }
+
+ /* end of their block */
+ out.println(" }");
+
+ /* if this was the start production, do action for accept */
+ if (prod == start_prod)
+ {
+ out.println(" /* ACCEPT */");
+ out.println(" " + pre("parser") + ".done_parsing();");
+ }
+
+ /* code to return lhs symbol */
+ out.println(" return " + pre("result") + ";");
+ out.println();
+ }
+
+ /* end of switch */
+ out.println(" /* . . . . . .*/");
+ out.println(" default:");
+ out.println(" throw new Exception(");
+ out.println(" \"Invalid action number found in " +
+ "internal parse table\");");
+ out.println();
+ out.println(" }");
+
+ /* end of method */
+ out.println(" }");
+
+ /* end of class */
+ out.println("}");
+ out.println();
+
+ action_code_time = System.currentTimeMillis() - start_time;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit the production table.
+ * @param out stream to produce output on.
+ */
+ protected static void emit_production_table(PrintWriter out)
+ {
+ production all_prods[];
+ production prod;
+
+ long start_time = System.currentTimeMillis();
+
+ /* collect up the productions in order */
+ all_prods = new production[production.number()];
+ for (Enumeration p = production.all(); p.hasMoreElements(); )
+ {
+ prod = (production)p.nextElement();
+ all_prods[prod.index()] = prod;
+ }
+
+ // make short[][]
+ short[][] prod_table = new short[production.number()][2];
+ for (int i = 0; i<production.number(); i++)
+ {
+ prod = all_prods[i];
+ // { lhs symbol , rhs size }
+ prod_table[i][0] = (short) prod.lhs().the_symbol().index();
+ prod_table[i][1] = (short) prod.rhs_length();
+ }
+ /* do the top of the table */
+ out.println();
+ out.println(" /** Production table. */");
+ out.println(" protected static final short _production_table[][] = ");
+ out.print (" unpackFromStrings(");
+ do_table_as_string(out, prod_table);
+ out.println(");");
+
+ /* do the public accessor method */
+ out.println();
+ out.println(" /** Access to production table. */");
+ out.println(" public short[][] production_table() " +
+ "{return _production_table;}");
+
+ production_table_time = System.currentTimeMillis() - start_time;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit the action table.
+ * @param out stream to produce output on.
+ * @param act_tab the internal representation of the action table.
+ * @param compact_reduces do we use the most frequent reduce as default?
+ */
+ protected static void do_action_table(
+ PrintWriter out,
+ parse_action_table act_tab,
+ boolean compact_reduces)
+ throws internal_error
+ {
+ parse_action_row row;
+ parse_action act;
+ int red;
+
+ long start_time = System.currentTimeMillis();
+
+ /* collect values for the action table */
+ short[][] action_table = new short[act_tab.num_states()][];
+ /* do each state (row) of the action table */
+ for (int i = 0; i < act_tab.num_states(); i++)
+ {
+ /* get the row */
+ row = act_tab.under_state[i];
+
+ /* determine the default for the row */
+ if (compact_reduces)
+ row.compute_default();
+ else
+ row.default_reduce = -1;
+
+ /* make temporary table for the row. */
+ short[] temp_table = new short[2*row.size()];
+ int nentries = 0;
+
+ /* do each column */
+ for (int j = 0; j < row.size(); j++)
+ {
+ /* extract the action from the table */
+ act = row.under_term[j];
+
+ /* skip error entries these are all defaulted out */
+ if (act.kind() != parse_action.ERROR)
+ {
+ /* first put in the symbol index, then the actual entry */
+
+ /* shifts get positive entries of state number + 1 */
+ if (act.kind() == parse_action.SHIFT)
+ {
+ /* make entry */
+ temp_table[nentries++] = (short) j;
+ temp_table[nentries++] = (short)
+ (((shift_action)act).shift_to().index() + 1);
+ }
+
+ /* reduce actions get negated entries of production# + 1 */
+ else if (act.kind() == parse_action.REDUCE)
+ {
+ /* if its the default entry let it get defaulted out */
+ red = ((reduce_action)act).reduce_with().index();
+ if (red != row.default_reduce) {
+ /* make entry */
+ temp_table[nentries++] = (short) j;
+ temp_table[nentries++] = (short) (-(red+1));
+ }
+ } else if (act.kind() == parse_action.NONASSOC)
+ {
+ /* do nothing, since we just want a syntax error */
+ }
+ /* shouldn't be anything else */
+ else
+ throw new internal_error("Unrecognized action code " +
+ act.kind() + " found in parse table");
+ }
+ }
+
+ /* now we know how big to make the row */
+ action_table[i] = new short[nentries + 2];
+ System.arraycopy(temp_table, 0, action_table[i], 0, nentries);
+
+ /* finish off the row with a default entry */
+ action_table[i][nentries++] = -1;
+ if (row.default_reduce != -1)
+ action_table[i][nentries++] = (short) (-(row.default_reduce+1));
+ else
+ action_table[i][nentries++] = 0;
+ }
+
+ /* finish off the init of the table */
+ out.println();
+ out.println(" /** Parse-action table. */");
+ out.println(" protected static final short[][] _action_table = ");
+ out.print (" unpackFromStrings(");
+ do_table_as_string(out, action_table);
+ out.println(");");
+
+ /* do the public accessor method */
+ out.println();
+ out.println(" /** Access to parse-action table. */");
+ out.println(" public short[][] action_table() {return _action_table;}");
+
+ action_table_time = System.currentTimeMillis() - start_time;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit the reduce-goto table.
+ * @param out stream to produce output on.
+ * @param red_tab the internal representation of the reduce-goto table.
+ */
+ protected static void do_reduce_table(
+ PrintWriter out,
+ parse_reduce_table red_tab)
+ {
+ lalr_state goto_st;
+ parse_action act;
+
+ long start_time = System.currentTimeMillis();
+
+ /* collect values for reduce-goto table */
+ short[][] reduce_goto_table = new short[red_tab.num_states()][];
+ /* do each row of the reduce-goto table */
+ for (int i=0; i<red_tab.num_states(); i++)
+ {
+ /* make temporary table for the row. */
+ short[] temp_table = new short[2*red_tab.under_state[i].size()];
+ int nentries = 0;
+ /* do each entry in the row */
+ for (int j=0; j<red_tab.under_state[i].size(); j++)
+ {
+ /* get the entry */
+ goto_st = red_tab.under_state[i].under_non_term[j];
+
+ /* if we have none, skip it */
+ if (goto_st != null)
+ {
+ /* make entries for the index and the value */
+ temp_table[nentries++] = (short) j;
+ temp_table[nentries++] = (short) goto_st.index();
+ }
+ }
+ /* now we know how big to make the row. */
+ reduce_goto_table[i] = new short[nentries+2];
+ System.arraycopy(temp_table, 0, reduce_goto_table[i], 0, nentries);
+
+ /* end row with default value */
+ reduce_goto_table[i][nentries++] = -1;
+ reduce_goto_table[i][nentries++] = -1;
+ }
+
+ /* emit the table. */
+ out.println();
+ out.println(" /** <code>reduce_goto</code> table. */");
+ out.println(" protected static final short[][] _reduce_table = ");
+ out.print (" unpackFromStrings(");
+ do_table_as_string(out, reduce_goto_table);
+ out.println(");");
+
+ /* do the public accessor method */
+ out.println();
+ out.println(" /** Access to <code>reduce_goto</code> table. */");
+ out.println(" public short[][] reduce_table() {return _reduce_table;}");
+ out.println();
+
+ goto_table_time = System.currentTimeMillis() - start_time;
+ }
+
+ // print a string array encoding the given short[][] array.
+ protected static void do_table_as_string(PrintWriter out, short[][] sa) {
+ out.println("new String[] {");
+ out.print(" \"");
+ int nchar=0, nbytes=0;
+ nbytes+=do_escaped(out, (char)(sa.length>>16));
+ nchar =do_newline(out, nchar, nbytes);
+ nbytes+=do_escaped(out, (char)(sa.length&0xFFFF));
+ nchar =do_newline(out, nchar, nbytes);
+ for (int i=0; i<sa.length; i++) {
+ nbytes+=do_escaped(out, (char)(sa[i].length>>16));
+ nchar =do_newline(out, nchar, nbytes);
+ nbytes+=do_escaped(out, (char)(sa[i].length&0xFFFF));
+ nchar =do_newline(out, nchar, nbytes);
+ for (int j=0; j<sa[i].length; j++) {
+ // contents of string are (value+2) to allow for common -1, 0 cases
+ // (UTF-8 encoding is most efficient for 0<c<0x80)
+ nbytes+=do_escaped(out, (char)(2+sa[i][j]));
+ nchar =do_newline(out, nchar, nbytes);
+ }
+ }
+ out.print("\" }");
+ }
+ // split string if it is very long; start new line occasionally for neatness
+ protected static int do_newline(PrintWriter out, int nchar, int nbytes) {
+ if (nbytes > 65500) { out.println("\", "); out.print(" \""); }
+ else if (nchar > 11) { out.println("\" +"); out.print(" \""); }
+ else return nchar+1;
+ return 0;
+ }
+ // output an escape sequence for the given character code.
+ protected static int do_escaped(PrintWriter out, char c) {
+ StringBuffer escape = new StringBuffer();
+ if (c <= 0xFF) {
+ escape.append(Integer.toOctalString(c));
+ while(escape.length() < 3) escape.insert(0, '0');
+ } else {
+ escape.append(Integer.toHexString(c));
+ while(escape.length() < 4) escape.insert(0, '0');
+ escape.insert(0, 'u');
+ }
+ escape.insert(0, '\\');
+ out.print(escape.toString());
+
+ // return number of bytes this takes up in UTF-8 encoding.
+ if (c == 0) return 2;
+ if (c >= 0x01 && c <= 0x7F) return 1;
+ if (c >= 0x80 && c <= 0x7FF) return 2;
+ return 3;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit the parser subclass with embedded tables.
+ * @param out stream to produce output on.
+ * @param action_table internal representation of the action table.
+ * @param reduce_table internal representation of the reduce-goto table.
+ * @param start_st start state of the parse machine.
+ * @param start_prod start production of the grammar.
+ * @param compact_reduces do we use most frequent reduce as default?
+ * @param suppress_scanner should scanner be suppressed for compatibility?
+ */
+ public static void parser(
+ PrintWriter out,
+ parse_action_table action_table,
+ parse_reduce_table reduce_table,
+ int start_st,
+ production start_prod,
+ boolean compact_reduces,
+ boolean suppress_scanner)
+ throws internal_error
+ {
+ long start_time = System.currentTimeMillis();
+
+ /* top of file */
+ out.println();
+ out.println("//----------------------------------------------------");
+ out.println("// The following code was generated by " +
+ version.title_str);
+ out.println("// " + new Date());
+ out.println("//----------------------------------------------------");
+ out.println();
+ emit_package(out);
+
+ /* user supplied imports */
+ for (int i = 0; i < import_list.size(); i++)
+ out.println("import " + import_list.elementAt(i) + ";");
+
+ /* class header */
+ out.println();
+ out.println("/** "+version.title_str+" generated parser.");
+ out.println(" * @version " + new Date());
+ out.println(" */");
+ out.println("public class " + parser_class_name +
+ " extends java_cup.runtime.lr_parser {");
+
+ /* constructors [CSA/davidm, 24-jul-99] */
+ out.println();
+ out.println(" /** Default constructor. */");
+ out.println(" public " + parser_class_name + "() {super();}");
+ if (!suppress_scanner) {
+ out.println();
+ out.println(" /** Constructor which sets the default scanner. */");
+ out.println(" public " + parser_class_name +
+ "(java_cup.runtime.Scanner s) {super(s);}");
+ }
+
+ /* emit the various tables */
+ emit_production_table(out);
+ do_action_table(out, action_table, compact_reduces);
+ do_reduce_table(out, reduce_table);
+
+ /* instance of the action encapsulation class */
+ out.println(" /** Instance of action encapsulation class. */");
+ out.println(" protected " + pre("actions") + " action_obj;");
+ out.println();
+
+ /* action object initializer */
+ out.println(" /** Action encapsulation object initializer. */");
+ out.println(" protected void init_actions()");
+ out.println(" {");
+ out.println(" action_obj = new " + pre("actions") + "(this);");
+ out.println(" }");
+ out.println();
+
+ /* access to action code */
+ out.println(" /** Invoke a user supplied parse action. */");
+ out.println(" public java_cup.runtime.Symbol do_action(");
+ out.println(" int act_num,");
+ out.println(" java_cup.runtime.lr_parser parser,");
+ out.println(" java.util.Stack stack,");
+ out.println(" int top)");
+ out.println(" throws java.lang.Exception");
+ out.println(" {");
+ out.println(" /* call code in generated class */");
+ out.println(" return action_obj." + pre("do_action(") +
+ "act_num, parser, stack, top);");
+ out.println(" }");
+ out.println("");
+
+
+ /* method to tell the parser about the start state */
+ out.println(" /** Indicates start state. */");
+ out.println(" public int start_state() {return " + start_st + ";}");
+
+ /* method to indicate start production */
+ out.println(" /** Indicates start production. */");
+ out.println(" public int start_production() {return " +
+ start_production.index() + ";}");
+ out.println();
+
+ /* methods to indicate EOF and error symbol indexes */
+ out.println(" /** <code>EOF</code> Symbol index. */");
+ out.println(" public int EOF_sym() {return " + terminal.EOF.index() +
+ ";}");
+ out.println();
+ out.println(" /** <code>error</code> Symbol index. */");
+ out.println(" public int error_sym() {return " + terminal.error.index() +
+ ";}");
+ out.println();
+
+ /* user supplied code for user_init() */
+ if (init_code != null)
+ {
+ out.println();
+ out.println(" /** User initialization code. */");
+ out.println(" public void user_init() throws java.lang.Exception");
+ out.println(" {");
+ out.println(init_code);
+ out.println(" }");
+ }
+
+ /* user supplied code for scan */
+ if (scan_code != null)
+ {
+ out.println();
+ out.println(" /** Scan to get the next Symbol. */");
+ out.println(" public java_cup.runtime.Symbol scan()");
+ out.println(" throws java.lang.Exception");
+ out.println(" {");
+ out.println(scan_code);
+ out.println(" }");
+ }
+
+ /* user supplied code */
+ if (parser_code != null)
+ {
+ out.println();
+ out.println(parser_code);
+ }
+
+ /* end of class */
+ out.println("}");
+
+ /* put out the action code class */
+ emit_action_code(out, start_prod);
+
+ parser_time = System.currentTimeMillis() - start_time;
+ }
+
+ /*-----------------------------------------------------------*/
+}
diff --git a/src/syntaxParser/java_cup/internal_error.class b/src/syntaxParser/java_cup/internal_error.class
new file mode 100644
index 0000000..77c69e1
--- /dev/null
+++ b/src/syntaxParser/java_cup/internal_error.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/internal_error.java b/src/syntaxParser/java_cup/internal_error.java
new file mode 100644
index 0000000..4d3e7c2
--- /dev/null
+++ b/src/syntaxParser/java_cup/internal_error.java
@@ -0,0 +1,22 @@
+
+package java_cup;
+
+/** Exception subclass for reporting internal errors in JavaCup. */
+public class internal_error extends Exception
+ {
+ /** Constructor with a message */
+ public internal_error(String msg)
+ {
+ super(msg);
+ }
+
+ /** Method called to do a forced error exit on an internal error
+ for cases when we can't actually throw the exception. */
+ public void crash()
+ {
+ System.err.println("JavaCUP Fatal Internal Error Detected");
+ System.err.println(getMessage());
+ printStackTrace();
+ System.exit(-1);
+ }
+ }
diff --git a/src/syntaxParser/java_cup/lalr_item.class b/src/syntaxParser/java_cup/lalr_item.class
new file mode 100644
index 0000000..2d539f9
--- /dev/null
+++ b/src/syntaxParser/java_cup/lalr_item.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/lalr_item.java b/src/syntaxParser/java_cup/lalr_item.java
new file mode 100644
index 0000000..fe92054
--- /dev/null
+++ b/src/syntaxParser/java_cup/lalr_item.java
@@ -0,0 +1,330 @@
+package java_cup;
+
+import java.util.Stack;
+import java.util.Enumeration;
+
+/** This class represents an LALR item. Each LALR item consists of
+ * a production, a "dot" at a position within that production, and
+ * a set of lookahead symbols (terminal). (The first two of these parts
+ * are provide by the super class). An item is designed to represent a
+ * configuration that the parser may be in. For example, an item of the
+ * form: <pre>
+ * [A ::= B * C d E , {a,b,c}]
+ * </pre>
+ * indicates that the parser is in the middle of parsing the production <pre>
+ * A ::= B C d E
+ * </pre>
+ * that B has already been parsed, and that we will expect to see a lookahead
+ * of either a, b, or c once the complete RHS of this production has been
+ * found.<p>
+ *
+ * Items may initially be missing some items from their lookahead sets.
+ * Links are maintained from each item to the set of items that would need
+ * to be updated if symbols are added to its lookahead set. During
+ * "lookahead propagation", we add symbols to various lookahead sets and
+ * propagate these changes across these dependency links as needed.
+ *
+ * @see java_cup.lalr_item_set
+ * @see java_cup.lalr_state
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class lalr_item extends lr_item_core {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param prod the production for the item.
+ * @param pos the position of the "dot" within the production.
+ * @param look the set of lookahead symbols.
+ */
+ public lalr_item(production prod, int pos, terminal_set look)
+ throws internal_error
+ {
+ super(prod, pos);
+ _lookahead = look;
+ _propagate_items = new Stack();
+ needs_propagation = true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with default position (dot at start).
+ * @param prod the production for the item.
+ * @param look the set of lookahead symbols.
+ */
+ public lalr_item(production prod, terminal_set look) throws internal_error
+ {
+ this(prod,0,look);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with default position and empty lookahead set.
+ * @param prod the production for the item.
+ */
+ public lalr_item(production prod) throws internal_error
+ {
+ this(prod,0,new terminal_set());
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The lookahead symbols of the item. */
+ protected terminal_set _lookahead;
+
+ /** The lookahead symbols of the item. */
+ public terminal_set lookahead() {return _lookahead;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Links to items that the lookahead needs to be propagated to. */
+ protected Stack _propagate_items;
+
+ /** Links to items that the lookahead needs to be propagated to */
+ public Stack propagate_items() {return _propagate_items;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Flag to indicate that this item needs to propagate its lookahead
+ * (whether it has changed or not).
+ */
+ protected boolean needs_propagation;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a new item to the set of items we propagate to. */
+ public void add_propagate(lalr_item prop_to)
+ {
+ _propagate_items.push(prop_to);
+ needs_propagation = true;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Propagate incoming lookaheads through this item to others need to
+ * be changed.
+ * @params incoming symbols to potentially be added to lookahead of this item.
+ */
+ public void propagate_lookaheads(terminal_set incoming) throws internal_error
+ {
+ boolean change = false;
+
+ /* if we don't need to propagate, then bail out now */
+ if (!needs_propagation && (incoming == null || incoming.empty()))
+ return;
+
+ /* if we have null incoming, treat as an empty set */
+ if (incoming != null)
+ {
+ /* add the incoming to the lookahead of this item */
+ change = lookahead().add(incoming);
+ }
+
+ /* if we changed or need it anyway, propagate across our links */
+ if (change || needs_propagation)
+ {
+ /* don't need to propagate again */
+ needs_propagation = false;
+
+ /* propagate our lookahead into each item we are linked to */
+ for (int i = 0; i < propagate_items().size(); i++)
+ ((lalr_item)propagate_items().elementAt(i))
+ .propagate_lookaheads(lookahead());
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce the new lalr_item that results from shifting the dot one position
+ * to the right.
+ */
+ public lalr_item shift() throws internal_error
+ {
+ lalr_item result;
+
+ /* can't shift if we have dot already at the end */
+ if (dot_at_end())
+ throw new internal_error("Attempt to shift past end of an lalr_item");
+
+ /* create the new item w/ the dot shifted by one */
+ result = new lalr_item(the_production(), dot_pos()+1,
+ new terminal_set(lookahead()));
+
+ /* change in our lookahead needs to be propagated to this item */
+ add_propagate(result);
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Calculate lookahead representing symbols that could appear after the
+ * symbol that the dot is currently in front of. Note: this routine must
+ * not be invoked before first sets and nullability has been calculated
+ * for all non terminals.
+ */
+ public terminal_set calc_lookahead(terminal_set lookahead_after)
+ throws internal_error
+ {
+ terminal_set result;
+ int pos;
+ production_part part;
+ symbol sym;
+
+ /* sanity check */
+ if (dot_at_end())
+ throw new internal_error(
+ "Attempt to calculate a lookahead set with a completed item");
+
+ /* start with an empty result */
+ result = new terminal_set();
+
+ /* consider all nullable symbols after the one to the right of the dot */
+ for (pos = dot_pos()+1; pos < the_production().rhs_length(); pos++)
+ {
+ part = the_production().rhs(pos);
+
+ /* consider what kind of production part it is -- skip actions */
+ if (!part.is_action())
+ {
+ sym = ((symbol_part)part).the_symbol();
+
+ /* if its a terminal add it in and we are done */
+ if (!sym.is_non_term())
+ {
+ result.add((terminal)sym);
+ return result;
+ }
+ else
+ {
+ /* otherwise add in first set of the non terminal */
+ result.add(((non_terminal)sym).first_set());
+
+ /* if its nullable we continue adding, if not, we are done */
+ if (!((non_terminal)sym).nullable())
+ return result;
+ }
+ }
+ }
+
+ /* if we get here everything past the dot was nullable
+ we add in the lookahead for after the production and we are done */
+ result.add(lookahead_after);
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if everything from the symbol one beyond the dot all the
+ * way to the end of the right hand side is nullable. This would indicate
+ * that the lookahead of this item must be included in the lookaheads of
+ * all items produced as a closure of this item. Note: this routine should
+ * not be invoked until after first sets and nullability have been
+ * calculated for all non terminals.
+ */
+ public boolean lookahead_visible() throws internal_error
+ {
+ production_part part;
+ symbol sym;
+
+ /* if the dot is at the end, we have a problem, but the cleanest thing
+ to do is just return true. */
+ if (dot_at_end()) return true;
+
+ /* walk down the rhs and bail if we get a non-nullable symbol */
+ for (int pos = dot_pos() + 1; pos < the_production().rhs_length(); pos++)
+ {
+ part = the_production().rhs(pos);
+
+ /* skip actions */
+ if (!part.is_action())
+ {
+ sym = ((symbol_part)part).the_symbol();
+
+ /* if its a terminal we fail */
+ if (!sym.is_non_term()) return false;
+
+ /* if its not nullable we fail */
+ if (!((non_terminal)sym).nullable()) return false;
+ }
+ }
+
+ /* if we get here its all nullable */
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison -- here we only require the cores to be equal since
+ * we need to do sets of items based only on core equality (ignoring
+ * lookahead sets).
+ */
+ public boolean equals(lalr_item other)
+ {
+ if (other == null) return false;
+ return super.equals(other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof lalr_item))
+ return false;
+ else
+ return equals((lalr_item)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return a hash code -- here we only hash the core since we only test core
+ * matching in LALR items.
+ */
+ public int hashCode()
+ {
+ return super.hashCode();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to string. */
+ public String toString()
+ {
+ String result = "";
+
+ // additional output for debugging:
+ // result += "(" + obj_hash() + ")";
+ result += "[";
+ result += super.toString();
+ result += ", ";
+ if (lookahead() != null)
+ {
+ result += "{";
+ for (int t = 0; t < terminal.number(); t++)
+ if (lookahead().contains(t))
+ result += terminal.find(t).name() + " ";
+ result += "}";
+ }
+ else
+ result += "NULL LOOKAHEAD!!";
+ result += "]";
+
+ // additional output for debugging:
+ // result += " -> ";
+ // for (int i = 0; i<propagate_items().size(); i++)
+ // result+=((lalr_item)(propagate_items().elementAt(i))).obj_hash()+" ";
+ //
+ // if (needs_propagation) result += " NP";
+
+ return result;
+ }
+ /*-----------------------------------------------------------*/
+}
diff --git a/src/syntaxParser/java_cup/lalr_item_set.class b/src/syntaxParser/java_cup/lalr_item_set.class
new file mode 100644
index 0000000..ff55488
--- /dev/null
+++ b/src/syntaxParser/java_cup/lalr_item_set.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/lalr_item_set.java b/src/syntaxParser/java_cup/lalr_item_set.java
new file mode 100644
index 0000000..233a68f
--- /dev/null
+++ b/src/syntaxParser/java_cup/lalr_item_set.java
@@ -0,0 +1,371 @@
+
+package java_cup;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/** This class represents a set of LALR items. For purposes of building
+ * these sets, items are considered unique only if they have unique cores
+ * (i.e., ignoring differences in their lookahead sets).<p>
+ *
+ * This class provides fairly conventional set oriented operations (union,
+ * sub/super-set tests, etc.), as well as an LALR "closure" operation (see
+ * compute_closure()).
+ *
+ * @see java_cup.lalr_item
+ * @see java_cup.lalr_state
+ * @version last updated: 3/6/96
+ * @author Scott Hudson
+ */
+
+public class lalr_item_set {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constructor for an empty set. */
+ public lalr_item_set() { }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor for cloning from another set.
+ * @param other indicates set we should copy from.
+ */
+ public lalr_item_set(lalr_item_set other)
+ throws internal_error
+ {
+ not_null(other);
+ _all = (Hashtable)other._all.clone();
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** A hash table to implement the set. We store the items using themselves
+ * as keys.
+ */
+ protected Hashtable _all = new Hashtable(11);
+
+ /** Access to all elements of the set. */
+ public Enumeration all() {return _all.elements();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Cached hashcode for this set. */
+ protected Integer hashcode_cache = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Size of the set */
+ public int size() {return _all.size();}
+
+ /*-----------------------------------------------------------*/
+ /*--- Set Operation Methods ---------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Does the set contain a particular item?
+ * @param itm the item in question.
+ */
+ public boolean contains(lalr_item itm) {return _all.containsKey(itm);}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return the item in the set matching a particular item (or null if not
+ * found)
+ * @param itm the item we are looking for.
+ */
+ public lalr_item find(lalr_item itm) {return (lalr_item)_all.get(itm);}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Is this set an (improper) subset of another?
+ * @param other the other set in question.
+ */
+ public boolean is_subset_of(lalr_item_set other) throws internal_error
+ {
+ not_null(other);
+
+ /* walk down our set and make sure every element is in the other */
+ for (Enumeration e = all(); e.hasMoreElements(); )
+ if (!other.contains((lalr_item)e.nextElement()))
+ return false;
+
+ /* they were all there */
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Is this set an (improper) superset of another?
+ * @param other the other set in question.
+ */
+ public boolean is_superset_of(lalr_item_set other) throws internal_error
+ {
+ not_null(other);
+ return other.is_subset_of(this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a singleton item, merging lookahead sets if the item is already
+ * part of the set. returns the element of the set that was added or
+ * merged into.
+ * @param itm the item being added.
+ */
+ public lalr_item add(lalr_item itm) throws internal_error
+ {
+ lalr_item other;
+
+ not_null(itm);
+
+ /* see if an item with a matching core is already there */
+ other = (lalr_item)_all.get(itm);
+
+ /* if so, merge this lookahead into the original and leave it */
+ if (other != null)
+ {
+ other.lookahead().add(itm.lookahead());
+ return other;
+ }
+ /* otherwise we just go in the set */
+ else
+ {
+ /* invalidate cached hashcode */
+ hashcode_cache = null;
+
+ _all.put(itm,itm);
+ return itm;
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove a single item if it is in the set.
+ * @param itm the item to remove.
+ */
+ public void remove(lalr_item itm) throws internal_error
+ {
+ not_null(itm);
+
+ /* invalidate cached hashcode */
+ hashcode_cache = null;
+
+ /* remove it from hash table implementing set */
+ _all.remove(itm);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a complete set, merging lookaheads where items are already in
+ * the set
+ * @param other the set to be added.
+ */
+ public void add(lalr_item_set other) throws internal_error
+ {
+ not_null(other);
+
+ /* walk down the other set and do the adds individually */
+ for (Enumeration e = other.all(); e.hasMoreElements(); )
+ add((lalr_item)e.nextElement());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove (set subtract) a complete set.
+ * @param other the set to remove.
+ */
+ public void remove(lalr_item_set other) throws internal_error
+ {
+ not_null(other);
+
+ /* walk down the other set and do the removes individually */
+ for (Enumeration e = other.all(); e.hasMoreElements(); )
+ remove((lalr_item)e.nextElement());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove and return one item from the set (done in hash order). */
+ public lalr_item get_one() throws internal_error
+ {
+ Enumeration the_set;
+ lalr_item result;
+
+ the_set = all();
+ if (the_set.hasMoreElements())
+ {
+ result = (lalr_item)the_set.nextElement();
+ remove(result);
+ return result;
+ }
+ else
+ return null;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Helper function for null test. Throws an interal_error exception if its
+ * parameter is null.
+ * @param obj the object we are testing.
+ */
+ protected void not_null(Object obj) throws internal_error
+ {
+ if (obj == null)
+ throw new internal_error("Null object used in set operation");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute the closure of the set using the LALR closure rules. Basically
+ * for every item of the form: <pre>
+ * [L ::= a *N alpha, l]
+ * </pre>
+ * (where N is a a non terminal and alpha is a string of symbols) make
+ * sure there are also items of the form: <pre>
+ * [N ::= *beta, first(alpha l)]
+ * </pre>
+ * corresponding to each production of N. Items with identical cores but
+ * differing lookahead sets are merged by creating a new item with the same
+ * core and the union of the lookahead sets (the LA in LALR stands for
+ * "lookahead merged" and this is where the merger is). This routine
+ * assumes that nullability and first sets have been computed for all
+ * productions before it is called.
+ */
+ public void compute_closure()
+ throws internal_error
+ {
+ lalr_item_set consider;
+ lalr_item itm, new_itm, add_itm;
+ non_terminal nt;
+ terminal_set new_lookaheads;
+ Enumeration p;
+ production prod;
+ boolean need_prop;
+
+
+
+ /* invalidate cached hashcode */
+ hashcode_cache = null;
+
+ /* each current element needs to be considered */
+ consider = new lalr_item_set(this);
+
+ /* repeat this until there is nothing else to consider */
+ while (consider.size() > 0)
+ {
+ /* get one item to consider */
+ itm = consider.get_one();
+
+ /* do we have a dot before a non terminal */
+ nt = itm.dot_before_nt();
+ if (nt != null)
+ {
+ /* create the lookahead set based on first after dot */
+ new_lookaheads = itm.calc_lookahead(itm.lookahead());
+
+ /* are we going to need to propagate our lookahead to new item */
+ need_prop = itm.lookahead_visible();
+
+ /* create items for each production of that non term */
+ for (p = nt.productions(); p.hasMoreElements(); )
+ {
+ prod = (production)p.nextElement();
+
+ /* create new item with dot at start and that lookahead */
+ new_itm = new lalr_item(prod,
+ new terminal_set(new_lookaheads));
+
+ /* add/merge item into the set */
+ add_itm = add(new_itm);
+ /* if propagation is needed link to that item */
+ if (need_prop)
+ itm.add_propagate(add_itm);
+
+ /* was this was a new item*/
+ if (add_itm == new_itm)
+ {
+ /* that may need further closure, consider it also */
+ consider.add(new_itm);
+ }
+ }
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(lalr_item_set other)
+ {
+ if (other == null || other.size() != size()) return false;
+
+ /* once we know they are the same size, then improper subset does test */
+ try {
+ return is_subset_of(other);
+ } catch (internal_error e) {
+ /* can't throw error from here (because superclass doesn't) so crash */
+ e.crash();
+ return false;
+ }
+
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof lalr_item_set))
+ return false;
+ else
+ return equals((lalr_item_set)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return hash code. */
+ public int hashCode()
+ {
+ int result = 0;
+ Enumeration e;
+ int cnt;
+
+ /* only compute a new one if we don't have it cached */
+ if (hashcode_cache == null)
+ {
+ /* hash together codes from at most first 5 elements */
+ // CSA fix! we'd *like* to hash just a few elements, but
+ // that means equal sets will have inequal hashcodes, which
+ // we're not allowed (by contract) to do. So hash them all.
+ for (e = all(), cnt=0 ; e.hasMoreElements() /*&& cnt<5*/; cnt++)
+ result ^= ((lalr_item)e.nextElement()).hashCode();
+
+ hashcode_cache = new Integer(result);
+ }
+
+ return hashcode_cache.intValue();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to string. */
+ public String toString()
+ {
+ StringBuffer result = new StringBuffer();
+
+ result.append("{\n");
+ for (Enumeration e=all(); e.hasMoreElements(); )
+ {
+ result.append(" " + (lalr_item)e.nextElement() + "\n");
+ }
+ result.append("}");
+
+ return result.toString();
+ }
+ /*-----------------------------------------------------------*/
+}
+
diff --git a/src/syntaxParser/java_cup/lalr_state.class b/src/syntaxParser/java_cup/lalr_state.class
new file mode 100644
index 0000000..ce9b2bd
--- /dev/null
+++ b/src/syntaxParser/java_cup/lalr_state.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/lalr_state.java b/src/syntaxParser/java_cup/lalr_state.java
new file mode 100644
index 0000000..5298e87
--- /dev/null
+++ b/src/syntaxParser/java_cup/lalr_state.java
@@ -0,0 +1,884 @@
+
+package java_cup;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+import java.util.Stack;
+
+/** This class represents a state in the LALR viable prefix recognition machine.
+ * A state consists of an LALR item set and a set of transitions to other
+ * states under terminal and non-terminal symbols. Each state represents
+ * a potential configuration of the parser. If the item set of a state
+ * includes an item such as: <pre>
+ * [A ::= B * C d E , {a,b,c}]
+ * </pre>
+ * this indicates that when the parser is in this state it is currently
+ * looking for an A of the given form, has already seen the B, and would
+ * expect to see an a, b, or c after this sequence is complete. Note that
+ * the parser is normally looking for several things at once (represented
+ * by several items). In our example above, the state would also include
+ * items such as: <pre>
+ * [C ::= * X e Z, {d}]
+ * [X ::= * f, {e}]
+ * </pre>
+ * to indicate that it was currently looking for a C followed by a d (which
+ * would be reduced into a C, matching the first symbol in our production
+ * above), and the terminal f followed by e.<p>
+ *
+ * At runtime, the parser uses a viable prefix recognition machine made up
+ * of these states to parse. The parser has two operations, shift and reduce.
+ * In a shift, it consumes one Symbol and makes a transition to a new state.
+ * This corresponds to "moving the dot past" a terminal in one or more items
+ * in the state (these new shifted items will then be found in the state at
+ * the end of the transition). For a reduce operation, the parser is
+ * signifying that it is recognizing the RHS of some production. To do this
+ * it first "backs up" by popping a stack of previously saved states. It
+ * pops off the same number of states as are found in the RHS of the
+ * production. This leaves the machine in the same state is was in when the
+ * parser first attempted to find the RHS. From this state it makes a
+ * transition based on the non-terminal on the LHS of the production. This
+ * corresponds to placing the parse in a configuration equivalent to having
+ * replaced all the symbols from the the input corresponding to the RHS with
+ * the symbol on the LHS.
+ *
+ * @see java_cup.lalr_item
+ * @see java_cup.lalr_item_set
+ * @see java_cup.lalr_transition
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ *
+ */
+
+public class lalr_state {
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constructor for building a state from a set of items.
+ * @param itms the set of items that makes up this state.
+ */
+ public lalr_state(lalr_item_set itms) throws internal_error
+ {
+ /* don't allow null or duplicate item sets */
+ if (itms == null)
+ throw new internal_error(
+ "Attempt to construct an LALR state from a null item set");
+
+ if (find_state(itms) != null)
+ throw new internal_error(
+ "Attempt to construct a duplicate LALR state");
+
+ /* assign a unique index */
+ _index = next_index++;
+
+ /* store the items */
+ _items = itms;
+
+ /* add to the global collection, keyed with its item set */
+ _all.put(_items,this);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Collection of all states. */
+ protected static Hashtable _all = new Hashtable();
+
+ /** Collection of all states. */
+ public static Enumeration all() {return _all.elements();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Indicate total number of states there are. */
+ public static int number() {return _all.size();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Hash table to find states by their kernels (i.e, the original,
+ * unclosed, set of items -- which uniquely define the state). This table
+ * stores state objects using (a copy of) their kernel item sets as keys.
+ */
+ protected static Hashtable _all_kernels = new Hashtable();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Find and return state with a given a kernel item set (or null if not
+ * found). The kernel item set is the subset of items that were used to
+ * originally create the state. These items are formed by "shifting the
+ * dot" within items of other states that have a transition to this one.
+ * The remaining elements of this state's item set are added during closure.
+ * @param itms the kernel set of the state we are looking for.
+ */
+ public static lalr_state find_state(lalr_item_set itms)
+ {
+ if (itms == null)
+ return null;
+ else
+ return (lalr_state)_all.get(itms);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Static counter for assigning unique state indexes. */
+ protected static int next_index = 0;
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The item set for this state. */
+ protected lalr_item_set _items;
+
+ /** The item set for this state. */
+ public lalr_item_set items() {return _items;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** List of transitions out of this state. */
+ protected lalr_transition _transitions = null;
+
+ /** List of transitions out of this state. */
+ public lalr_transition transitions() {return _transitions;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Index of this state in the parse tables */
+ protected int _index;
+
+ /** Index of this state in the parse tables */
+ public int index() {return _index;}
+
+ /*-----------------------------------------------------------*/
+ /*--- Static Methods ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Helper routine for debugging -- produces a dump of the given state
+ * onto System.out.
+ */
+ protected static void dump_state(lalr_state st) throws internal_error
+ {
+ lalr_item_set itms;
+ lalr_item itm;
+ production_part part;
+
+ if (st == null)
+ {
+ System.out.println("NULL lalr_state");
+ return;
+ }
+
+ System.out.println("lalr_state [" + st.index() + "] {");
+ itms = st.items();
+ for (Enumeration e = itms.all(); e.hasMoreElements(); )
+ {
+ itm = (lalr_item)e.nextElement();
+ System.out.print(" [");
+ System.out.print(itm.the_production().lhs().the_symbol().name());
+ System.out.print(" ::= ");
+ for (int i = 0; i<itm.the_production().rhs_length(); i++)
+ {
+ if (i == itm.dot_pos()) System.out.print("(*) ");
+ part = itm.the_production().rhs(i);
+ if (part.is_action())
+ System.out.print("{action} ");
+ else
+ System.out.print(((symbol_part)part).the_symbol().name() + " ");
+ }
+ if (itm.dot_at_end()) System.out.print("(*) ");
+ System.out.println("]");
+ }
+ System.out.println("}");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Propagate lookahead sets through the constructed viable prefix
+ * recognizer. When the machine is constructed, each item that results
+ in the creation of another such that its lookahead is included in the
+ other's will have a propagate link set up for it. This allows additions
+ to the lookahead of one item to be included in other items that it
+ was used to directly or indirectly create.
+ */
+ protected static void propagate_all_lookaheads() throws internal_error
+ {
+ /* iterate across all states */
+ for (Enumeration st = all(); st.hasMoreElements(); )
+ {
+ /* propagate lookaheads out of that state */
+ ((lalr_state)st.nextElement()).propagate_lookaheads();
+ }
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Add a transition out of this state to another.
+ * @param on_sym the symbol the transition is under.
+ * @param to_st the state the transition goes to.
+ */
+ public void add_transition(symbol on_sym, lalr_state to_st)
+ throws internal_error
+ {
+ lalr_transition trans;
+
+ /* create a new transition object and put it in our list */
+ trans = new lalr_transition(on_sym, to_st, _transitions);
+ _transitions = trans;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Build an LALR viable prefix recognition machine given a start
+ * production. This method operates by first building a start state
+ * from the start production (based on a single item with the dot at
+ * the beginning and EOF as expected lookahead). Then for each state
+ * it attempts to extend the machine by creating transitions out of
+ * the state to new or existing states. When considering extension
+ * from a state we make a transition on each symbol that appears before
+ * the dot in some item. For example, if we have the items: <pre>
+ * [A ::= a b * X c, {d,e}]
+ * [B ::= a b * X d, {a,b}]
+ * </pre>
+ * in some state, then we would be making a transition under X to a new
+ * state. This new state would be formed by a "kernel" of items
+ * corresponding to moving the dot past the X. In this case: <pre>
+ * [A ::= a b X * c, {d,e}]
+ * [B ::= a b X * Y, {a,b}]
+ * </pre>
+ * The full state would then be formed by "closing" this kernel set of
+ * items so that it included items that represented productions of things
+ * the parser was now looking for. In this case we would items
+ * corresponding to productions of Y, since various forms of Y are expected
+ * next when in this state (see lalr_item_set.compute_closure() for details
+ * on closure). <p>
+ *
+ * The process of building the viable prefix recognizer terminates when no
+ * new states can be added. However, in order to build a smaller number of
+ * states (i.e., corresponding to LALR rather than canonical LR) the state
+ * building process does not maintain full loookaheads in all items.
+ * Consequently, after the machine is built, we go back and propagate
+ * lookaheads through the constructed machine using a call to
+ * propagate_all_lookaheads(). This makes use of propagation links
+ * constructed during the closure and transition process.
+ *
+ * @param start_prod the start production of the grammar
+ * @see java_cup.lalr_item_set#compute_closure
+ * @see java_cup.lalr_state#propagate_all_lookaheads
+ */
+
+ public static lalr_state build_machine(production start_prod)
+ throws internal_error
+ {
+ lalr_state start_state;
+ lalr_item_set start_items;
+ lalr_item_set new_items;
+ lalr_item_set linked_items;
+ lalr_item_set kernel;
+ Stack work_stack = new Stack();
+ lalr_state st, new_st;
+ symbol_set outgoing;
+ lalr_item itm, new_itm, existing, fix_itm;
+ symbol sym, sym2;
+ Enumeration i, s, fix;
+
+ /* sanity check */
+ if (start_prod == null)
+ throw new internal_error(
+ "Attempt to build viable prefix recognizer using a null production");
+
+ /* build item with dot at front of start production and EOF lookahead */
+ start_items = new lalr_item_set();
+
+ itm = new lalr_item(start_prod);
+ itm.lookahead().add(terminal.EOF);
+
+ start_items.add(itm);
+
+ /* create copy the item set to form the kernel */
+ kernel = new lalr_item_set(start_items);
+
+ /* create the closure from that item set */
+ start_items.compute_closure();
+
+ /* build a state out of that item set and put it in our work set */
+ start_state = new lalr_state(start_items);
+ work_stack.push(start_state);
+
+ /* enter the state using the kernel as the key */
+ _all_kernels.put(kernel, start_state);
+
+ /* continue looking at new states until we have no more work to do */
+ while (!work_stack.empty())
+ {
+ /* remove a state from the work set */
+ st = (lalr_state)work_stack.pop();
+
+ /* gather up all the symbols that appear before dots */
+ outgoing = new symbol_set();
+ for (i = st.items().all(); i.hasMoreElements(); )
+ {
+ itm = (lalr_item)i.nextElement();
+
+ /* add the symbol before the dot (if any) to our collection */
+ sym = itm.symbol_after_dot();
+ if (sym != null) outgoing.add(sym);
+ }
+
+ /* now create a transition out for each individual symbol */
+ for (s = outgoing.all(); s.hasMoreElements(); )
+ {
+ sym = (symbol)s.nextElement();
+
+ /* will be keeping the set of items with propagate links */
+ linked_items = new lalr_item_set();
+
+ /* gather up shifted versions of all the items that have this
+ symbol before the dot */
+ new_items = new lalr_item_set();
+ for (i = st.items().all(); i.hasMoreElements();)
+ {
+ itm = (lalr_item)i.nextElement();
+
+ /* if this is the symbol we are working on now, add to set */
+ sym2 = itm.symbol_after_dot();
+ if (sym.equals(sym2))
+ {
+ /* add to the kernel of the new state */
+ new_items.add(itm.shift());
+
+ /* remember that itm has propagate link to it */
+ linked_items.add(itm);
+ }
+ }
+
+ /* use new items as state kernel */
+ kernel = new lalr_item_set(new_items);
+
+ /* have we seen this one already? */
+ new_st = (lalr_state)_all_kernels.get(kernel);
+
+ /* if we haven't, build a new state out of the item set */
+ if (new_st == null)
+ {
+ /* compute closure of the kernel for the full item set */
+ new_items.compute_closure();
+
+ /* build the new state */
+ new_st = new lalr_state(new_items);
+
+ /* add the new state to our work set */
+ work_stack.push(new_st);
+
+ /* put it in our kernel table */
+ _all_kernels.put(kernel, new_st);
+ }
+ /* otherwise relink propagation to items in existing state */
+ else
+ {
+ /* walk through the items that have links to the new state */
+ for (fix = linked_items.all(); fix.hasMoreElements(); )
+ {
+ fix_itm = (lalr_item)fix.nextElement();
+
+ /* look at each propagate link out of that item */
+ for (int l =0; l < fix_itm.propagate_items().size(); l++)
+ {
+ /* pull out item linked to in the new state */
+ new_itm =
+ (lalr_item)fix_itm.propagate_items().elementAt(l);
+
+ /* find corresponding item in the existing state */
+ existing = new_st.items().find(new_itm);
+
+ /* fix up the item so it points to the existing set */
+ if (existing != null)
+ fix_itm.propagate_items().setElementAt(existing ,l);
+ }
+ }
+ }
+
+ /* add a transition from current state to that state */
+ st.add_transition(sym, new_st);
+ }
+ }
+
+ /* all done building states */
+
+ /* propagate complete lookahead sets throughout the states */
+ propagate_all_lookaheads();
+
+ return start_state;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Propagate lookahead sets out of this state. This recursively
+ * propagates to all items that have propagation links from some item
+ * in this state.
+ */
+ protected void propagate_lookaheads() throws internal_error
+ {
+ /* recursively propagate out from each item in the state */
+ for (Enumeration itm = items().all(); itm.hasMoreElements(); )
+ ((lalr_item)itm.nextElement()).propagate_lookaheads(null);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Fill in the parse table entries for this state. There are two
+ * parse tables that encode the viable prefix recognition machine, an
+ * action table and a reduce-goto table. The rows in each table
+ * correspond to states of the machine. The columns of the action table
+ * are indexed by terminal symbols and correspond to either transitions
+ * out of the state (shift entries) or reductions from the state to some
+ * previous state saved on the stack (reduce entries). All entries in the
+ * action table that are not shifts or reduces, represent errors. The
+ * reduce-goto table is indexed by non terminals and represents transitions
+ * out of a state on that non-terminal.<p>
+ * Conflicts occur if more than one action needs to go in one entry of the
+ * action table (this cannot happen with the reduce-goto table). Conflicts
+ * are resolved by always shifting for shift/reduce conflicts and choosing
+ * the lowest numbered production (hence the one that appeared first in
+ * the specification) in reduce/reduce conflicts. All conflicts are
+ * reported and if more conflicts are detected than were declared by the
+ * user, code generation is aborted.
+ *
+ * @param act_table the action table to put entries in.
+ * @param reduce_table the reduce-goto table to put entries in.
+ */
+ public void build_table_entries(
+ parse_action_table act_table,
+ parse_reduce_table reduce_table)
+ throws internal_error
+ {
+ parse_action_row our_act_row;
+ parse_reduce_row our_red_row;
+ lalr_item itm;
+ parse_action act, other_act;
+ symbol sym;
+ terminal_set conflict_set = new terminal_set();
+
+ /* pull out our rows from the tables */
+ our_act_row = act_table.under_state[index()];
+ our_red_row = reduce_table.under_state[index()];
+
+ /* consider each item in our state */
+ for (Enumeration i = items().all(); i.hasMoreElements(); )
+ {
+ itm = (lalr_item)i.nextElement();
+
+
+ /* if its completed (dot at end) then reduce under the lookahead */
+ if (itm.dot_at_end())
+ {
+ act = new reduce_action(itm.the_production());
+
+ /* consider each lookahead symbol */
+ for (int t = 0; t < terminal.number(); t++)
+ {
+ /* skip over the ones not in the lookahead */
+ if (!itm.lookahead().contains(t)) continue;
+
+ /* if we don't already have an action put this one in */
+ if (our_act_row.under_term[t].kind() ==
+ parse_action.ERROR)
+ {
+ our_act_row.under_term[t] = act;
+ }
+ else
+ {
+ /* we now have at least one conflict */
+ terminal term = terminal.find(t);
+ other_act = our_act_row.under_term[t];
+
+ /* if the other act was not a shift */
+ if ((other_act.kind() != parse_action.SHIFT) &&
+ (other_act.kind() != parse_action.NONASSOC))
+ {
+ /* if we have lower index hence priority, replace it*/
+ if (itm.the_production().index() <
+ ((reduce_action)other_act).reduce_with().index())
+ {
+ /* replace the action */
+ our_act_row.under_term[t] = act;
+ }
+ } else {
+ /* Check precedences,see if problem is correctable */
+ if(fix_with_precedence(itm.the_production(),
+ t, our_act_row, act)) {
+ term = null;
+ }
+ }
+ if(term!=null) {
+
+ conflict_set.add(term);
+ }
+ }
+ }
+ }
+ }
+
+ /* consider each outgoing transition */
+ for (lalr_transition trans=transitions(); trans!=null; trans=trans.next())
+ {
+ /* if its on an terminal add a shift entry */
+ sym = trans.on_symbol();
+ if (!sym.is_non_term())
+ {
+ act = new shift_action(trans.to_state());
+
+ /* if we don't already have an action put this one in */
+ if ( our_act_row.under_term[sym.index()].kind() ==
+ parse_action.ERROR)
+ {
+ our_act_row.under_term[sym.index()] = act;
+ }
+ else
+ {
+ /* we now have at least one conflict */
+ production p = ((reduce_action)our_act_row.under_term[sym.index()]).reduce_with();
+
+ /* shift always wins */
+ if (!fix_with_precedence(p, sym.index(), our_act_row, act)) {
+ our_act_row.under_term[sym.index()] = act;
+ conflict_set.add(terminal.find(sym.index()));
+ }
+ }
+ }
+ else
+ {
+ /* for non terminals add an entry to the reduce-goto table */
+ our_red_row.under_non_term[sym.index()] = trans.to_state();
+ }
+ }
+
+ /* if we end up with conflict(s), report them */
+ if (!conflict_set.empty())
+ report_conflicts(conflict_set);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+
+ /** Procedure that attempts to fix a shift/reduce error by using
+ * precedences. --frankf 6/26/96
+ *
+ * if a production (also called rule) or the lookahead terminal
+ * has a precedence, then the table can be fixed. if the rule
+ * has greater precedence than the terminal, a reduce by that rule
+ * in inserted in the table. If the terminal has a higher precedence,
+ * it is shifted. if they have equal precedence, then the associativity
+ * of the precedence is used to determine what to put in the table:
+ * if the precedence is left associative, the action is to reduce.
+ * if the precedence is right associative, the action is to shift.
+ * if the precedence is non associative, then it is a syntax error.
+ *
+ * @param p the production
+ * @param term_index the index of the lokahead terminal
+ * @param parse_action_row a row of the action table
+ * @param act the rule in conflict with the table entry
+ */
+
+ protected boolean fix_with_precedence(
+ production p,
+ int term_index,
+ parse_action_row table_row,
+ parse_action act)
+
+ throws internal_error {
+
+ terminal term = terminal.find(term_index);
+
+ /* if the production has a precedence number, it can be fixed */
+ if (p.precedence_num() > assoc.no_prec) {
+
+ /* if production precedes terminal, put reduce in table */
+ if (p.precedence_num() > term.precedence_num()) {
+ table_row.under_term[term_index] =
+ insert_reduce(table_row.under_term[term_index],act);
+ return true;
+ }
+
+ /* if terminal precedes rule, put shift in table */
+ else if (p.precedence_num() < term.precedence_num()) {
+ table_row.under_term[term_index] =
+ insert_shift(table_row.under_term[term_index],act);
+ return true;
+ }
+ else { /* they are == precedence */
+
+ /* equal precedences have equal sides, so only need to
+ look at one: if it is right, put shift in table */
+ if (term.precedence_side() == assoc.right) {
+ table_row.under_term[term_index] =
+ insert_shift(table_row.under_term[term_index],act);
+ return true;
+ }
+
+ /* if it is left, put reduce in table */
+ else if (term.precedence_side() == assoc.left) {
+ table_row.under_term[term_index] =
+ insert_reduce(table_row.under_term[term_index],act);
+ return true;
+ }
+
+ /* if it is nonassoc, we're not allowed to have two nonassocs
+ of equal precedence in a row, so put in NONASSOC */
+ else if (term.precedence_side() == assoc.nonassoc) {
+ table_row.under_term[term_index] = new nonassoc_action();
+ return true;
+ } else {
+ /* something really went wrong */
+ throw new internal_error("Unable to resolve conflict correctly");
+ }
+ }
+ }
+ /* check if terminal has precedence, if so, shift, since
+ rule does not have precedence */
+ else if (term.precedence_num() > assoc.no_prec) {
+ table_row.under_term[term_index] =
+ insert_shift(table_row.under_term[term_index],act);
+ return true;
+ }
+
+ /* otherwise, neither the rule nor the terminal has a precedence,
+ so it can't be fixed. */
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+
+ /* given two actions, and an action type, return the
+ action of that action type. give an error if they are of
+ the same action, because that should never have tried
+ to be fixed
+
+ */
+ protected parse_action insert_action(
+ parse_action a1,
+ parse_action a2,
+ int act_type)
+ throws internal_error
+ {
+ if ((a1.kind() == act_type) && (a2.kind() == act_type)) {
+ throw new internal_error("Conflict resolution of bogus actions");
+ } else if (a1.kind() == act_type) {
+ return a1;
+ } else if (a2.kind() == act_type) {
+ return a2;
+ } else {
+ throw new internal_error("Conflict resolution of bogus actions");
+ }
+ }
+
+ /* find the shift in the two actions */
+ protected parse_action insert_shift(
+ parse_action a1,
+ parse_action a2)
+ throws internal_error
+ {
+ return insert_action(a1, a2, parse_action.SHIFT);
+ }
+
+ /* find the reduce in the two actions */
+ protected parse_action insert_reduce(
+ parse_action a1,
+ parse_action a2)
+ throws internal_error
+ {
+ return insert_action(a1, a2, parse_action.REDUCE);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce warning messages for all conflicts found in this state. */
+ protected void report_conflicts(terminal_set conflict_set)
+ throws internal_error
+ {
+ lalr_item itm, compare;
+ symbol shift_sym;
+
+ boolean after_itm;
+
+ /* consider each element */
+ for (Enumeration itms = items().all(); itms.hasMoreElements(); )
+ {
+ itm = (lalr_item)itms.nextElement();
+
+ /* clear the S/R conflict set for this item */
+
+ /* if it results in a reduce, it could be a conflict */
+ if (itm.dot_at_end())
+ {
+ /* not yet after itm */
+ after_itm = false;
+
+ /* compare this item against all others looking for conflicts */
+ for (Enumeration comps = items().all(); comps.hasMoreElements(); )
+ {
+ compare = (lalr_item)comps.nextElement();
+
+ /* if this is the item, next one is after it */
+ if (itm == compare) after_itm = true;
+
+ /* only look at it if its not the same item */
+ if (itm != compare)
+ {
+ /* is it a reduce */
+ if (compare.dot_at_end())
+ {
+ /* only look at reduces after itm */
+ if (after_itm)
+ /* does the comparison item conflict? */
+ if (compare.lookahead().intersects(itm.lookahead()))
+ /* report a reduce/reduce conflict */
+ report_reduce_reduce(itm, compare);
+ }
+ }
+ }
+ /* report S/R conflicts under all the symbols we conflict under */
+ for (int t = 0; t < terminal.number(); t++)
+ if (conflict_set.contains(t))
+ report_shift_reduce(itm,t);
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a warning message for one reduce/reduce conflict.
+ *
+ * @param itm1 first item in conflict.
+ * @param itm2 second item in conflict.
+ */
+ protected void report_reduce_reduce(lalr_item itm1, lalr_item itm2)
+ throws internal_error
+ {
+ boolean comma_flag = false;
+
+ System.err.println("*** Reduce/Reduce conflict found in state #"+index());
+ System.err.print (" between ");
+ System.err.println(itm1.to_simple_string());
+ System.err.print (" and ");
+ System.err.println(itm2.to_simple_string());
+ System.err.print(" under symbols: {" );
+ for (int t = 0; t < terminal.number(); t++)
+ {
+ if (itm1.lookahead().contains(t) && itm2.lookahead().contains(t))
+ {
+ if (comma_flag) System.err.print(", "); else comma_flag = true;
+ System.err.print(terminal.find(t).name());
+ }
+ }
+ System.err.println("}");
+ System.err.print(" Resolved in favor of ");
+ if (itm1.the_production().index() < itm2.the_production().index())
+ System.err.println("the first production.\n");
+ else
+ System.err.println("the second production.\n");
+
+ /* count the conflict */
+ emit.num_conflicts++;
+ lexer.warning_count++;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a warning message for one shift/reduce conflict.
+ *
+ * @param red_itm the item with the reduce.
+ * @param conflict_sym the index of the symbol conflict occurs under.
+ */
+ protected void report_shift_reduce(
+ lalr_item red_itm,
+ int conflict_sym)
+ throws internal_error
+ {
+ lalr_item itm;
+ symbol shift_sym;
+
+ /* emit top part of message including the reduce item */
+ System.err.println("*** Shift/Reduce conflict found in state #"+index());
+ System.err.print (" between ");
+ System.err.println(red_itm.to_simple_string());
+
+ /* find and report on all items that shift under our conflict symbol */
+ for (Enumeration itms = items().all(); itms.hasMoreElements(); )
+ {
+ itm = (lalr_item)itms.nextElement();
+
+ /* only look if its not the same item and not a reduce */
+ if (itm != red_itm && !itm.dot_at_end())
+ {
+ /* is it a shift on our conflicting terminal */
+ shift_sym = itm.symbol_after_dot();
+ if (!shift_sym.is_non_term() && shift_sym.index() == conflict_sym)
+ {
+ /* yes, report on it */
+ System.err.println(" and " + itm.to_simple_string());
+ }
+ }
+ }
+ System.err.println(" under symbol "+ terminal.find(conflict_sym).name());
+ System.err.println(" Resolved in favor of shifting.\n");
+
+ /* count the conflict */
+ emit.num_conflicts++;
+ lexer.warning_count++;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(lalr_state other)
+ {
+ /* we are equal if our item sets are equal */
+ return other != null && items().equals(other.items());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof lalr_state))
+ return false;
+ else
+ return equals((lalr_state)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a hash code. */
+ public int hashCode()
+ {
+ /* just use the item set hash code */
+ return items().hashCode();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+ lalr_transition tr;
+
+ /* dump the item set */
+ result = "lalr_state [" + index() + "]: " + _items + "\n";
+
+ /* do the transitions */
+ for (tr = transitions(); tr != null; tr = tr.next())
+ {
+ result += tr;
+ result += "\n";
+ }
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+}
diff --git a/src/syntaxParser/java_cup/lalr_transition.class b/src/syntaxParser/java_cup/lalr_transition.class
new file mode 100644
index 0000000..4d33e8d
--- /dev/null
+++ b/src/syntaxParser/java_cup/lalr_transition.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/lalr_transition.java b/src/syntaxParser/java_cup/lalr_transition.java
new file mode 100644
index 0000000..1c941bd
--- /dev/null
+++ b/src/syntaxParser/java_cup/lalr_transition.java
@@ -0,0 +1,93 @@
+package java_cup;
+
+/** This class represents a transition in an LALR viable prefix recognition
+ * machine. Transitions can be under terminals for non-terminals. They are
+ * internally linked together into singly linked lists containing all the
+ * transitions out of a single state via the _next field.
+ *
+ * @see java_cup.lalr_state
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ *
+ */
+public class lalr_transition {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param on_sym symbol we are transitioning on.
+ * @param to_st state we transition to.
+ * @param nxt next transition in linked list.
+ */
+ public lalr_transition(symbol on_sym, lalr_state to_st, lalr_transition nxt)
+ throws internal_error
+ {
+ /* sanity checks */
+ if (on_sym == null)
+ throw new internal_error("Attempt to create transition on null symbol");
+ if (to_st == null)
+ throw new internal_error("Attempt to create transition to null state");
+
+ /* initialize */
+ _on_symbol = on_sym;
+ _to_state = to_st;
+ _next = nxt;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with null next.
+ * @param on_sym symbol we are transitioning on.
+ * @param to_st state we transition to.
+ */
+ public lalr_transition(symbol on_sym, lalr_state to_st) throws internal_error
+ {
+ this(on_sym, to_st, null);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The symbol we make the transition on. */
+ protected symbol _on_symbol;
+
+ /** The symbol we make the transition on. */
+ public symbol on_symbol() {return _on_symbol;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The state we transition to. */
+ protected lalr_state _to_state;
+
+ /** The state we transition to. */
+ public lalr_state to_state() {return _to_state;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Next transition in linked list of transitions out of a state */
+ protected lalr_transition _next;
+
+ /** Next transition in linked list of transitions out of a state */
+ public lalr_transition next() {return _next;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+
+ result = "transition on " + on_symbol().name() + " to state [";
+ result += _to_state.index();
+ result += "]";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+}
diff --git a/src/syntaxParser/java_cup/lexer.class b/src/syntaxParser/java_cup/lexer.class
new file mode 100644
index 0000000..87e0073
--- /dev/null
+++ b/src/syntaxParser/java_cup/lexer.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/lexer.java b/src/syntaxParser/java_cup/lexer.java
new file mode 100644
index 0000000..2230d12
--- /dev/null
+++ b/src/syntaxParser/java_cup/lexer.java
@@ -0,0 +1,543 @@
+package java_cup;
+
+import java_cup.runtime.Symbol;
+import java.util.Hashtable;
+
+/** This class implements a small scanner (aka lexical analyzer or lexer) for
+ * the JavaCup specification. This scanner reads characters from standard
+ * input (System.in) and returns integers corresponding to the terminal
+ * number of the next Symbol. Once end of input is reached the EOF Symbol is
+ * returned on every subsequent call.<p>
+ * Symbols currently returned include: <pre>
+ * Symbol Constant Returned Symbol Constant Returned
+ * ------ ----------------- ------ -----------------
+ * "package" PACKAGE "import" IMPORT
+ * "code" CODE "action" ACTION
+ * "parser" PARSER "terminal" TERMINAL
+ * "non" NON "init" INIT
+ * "scan" SCAN "with" WITH
+ * "start" START "precedence" PRECEDENCE
+ * "left" LEFT "right" RIGHT
+ * "nonassoc" NONASSOC "%prec PRECENT_PREC
+ * [ LBRACK ] RBRACK
+ * ; SEMI
+ * , COMMA * STAR
+ * . DOT : COLON
+ * ::= COLON_COLON_EQUALS | BAR
+ * identifier ID {:...:} CODE_STRING
+ * "nonterminal" NONTERMINAL
+ * </pre>
+ * All symbol constants are defined in sym.java which is generated by
+ * JavaCup from parser.cup.<p>
+ *
+ * In addition to the scanner proper (called first via init() then with
+ * next_token() to get each Symbol) this class provides simple error and
+ * warning routines and keeps a count of errors and warnings that is
+ * publicly accessible.<p>
+ *
+ * This class is "static" (i.e., it has only static members and methods).
+ *
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+public class lexer {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The only constructor is private, so no instances can be created. */
+ private lexer() { }
+
+ /*-----------------------------------------------------------*/
+ /*--- Static (Class) Variables ------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** First character of lookahead. */
+ protected static int next_char;
+
+ /** Second character of lookahead. */
+ protected static int next_char2;
+
+ /** Second character of lookahead. */
+ protected static int next_char3;
+
+ /** Second character of lookahead. */
+ protected static int next_char4;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** EOF constant. */
+ protected static final int EOF_CHAR = -1;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Table of keywords. Keywords are initially treated as identifiers.
+ * Just before they are returned we look them up in this table to see if
+ * they match one of the keywords. The string of the name is the key here,
+ * which indexes Integer objects holding the symbol number.
+ */
+ protected static Hashtable keywords = new Hashtable(23);
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Table of single character symbols. For ease of implementation, we
+ * store all unambiguous single character Symbols in this table of Integer
+ * objects keyed by Integer objects with the numerical value of the
+ * appropriate char (currently Character objects have a bug which precludes
+ * their use in tables).
+ */
+ protected static Hashtable char_symbols = new Hashtable(11);
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Current line number for use in error messages. */
+ protected static int current_line = 1;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Character position in current line. */
+ protected static int current_position = 1;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Character position in current line. */
+ protected static int absolute_position = 1;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of total errors detected so far. */
+ public static int error_count = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of warnings issued so far */
+ public static int warning_count = 0;
+
+ /*-----------------------------------------------------------*/
+ /*--- Static Methods ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Initialize the scanner. This sets up the keywords and char_symbols
+ * tables and reads the first two characters of lookahead.
+ */
+ public static void init() throws java.io.IOException
+ {
+ /* set up the keyword table */
+ keywords.put("package", new Integer(sym.PACKAGE));
+ keywords.put("import", new Integer(sym.IMPORT));
+ keywords.put("code", new Integer(sym.CODE));
+ keywords.put("action", new Integer(sym.ACTION));
+ keywords.put("parser", new Integer(sym.PARSER));
+ keywords.put("terminal", new Integer(sym.TERMINAL));
+ keywords.put("non", new Integer(sym.NON));
+ keywords.put("nonterminal",new Integer(sym.NONTERMINAL));// [CSA]
+ keywords.put("init", new Integer(sym.INIT));
+ keywords.put("scan", new Integer(sym.SCAN));
+ keywords.put("with", new Integer(sym.WITH));
+ keywords.put("start", new Integer(sym.START));
+ keywords.put("precedence", new Integer(sym.PRECEDENCE));
+ keywords.put("left", new Integer(sym.LEFT));
+ keywords.put("right", new Integer(sym.RIGHT));
+ keywords.put("nonassoc", new Integer(sym.NONASSOC));
+
+ /* set up the table of single character symbols */
+ char_symbols.put(new Integer(';'), new Integer(sym.SEMI));
+ char_symbols.put(new Integer(','), new Integer(sym.COMMA));
+ char_symbols.put(new Integer('*'), new Integer(sym.STAR));
+ char_symbols.put(new Integer('.'), new Integer(sym.DOT));
+ char_symbols.put(new Integer('|'), new Integer(sym.BAR));
+ char_symbols.put(new Integer('['), new Integer(sym.LBRACK));
+ char_symbols.put(new Integer(']'), new Integer(sym.RBRACK));
+
+ /* read two characters of lookahead */
+ next_char = System.in.read();
+ if (next_char == EOF_CHAR) {
+ next_char2 = EOF_CHAR;
+ next_char3 = EOF_CHAR;
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char2 = System.in.read();
+ if (next_char2 == EOF_CHAR) {
+ next_char3 = EOF_CHAR;
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char3 = System.in.read();
+ if (next_char3 == EOF_CHAR) {
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char4 = System.in.read();
+ }
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Advance the scanner one character in the input stream. This moves
+ * next_char2 to next_char and then reads a new next_char2.
+ */
+ protected static void advance() throws java.io.IOException
+ {
+ int old_char;
+
+ old_char = next_char;
+ next_char = next_char2;
+ if (next_char == EOF_CHAR) {
+ next_char2 = EOF_CHAR;
+ next_char3 = EOF_CHAR;
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char2 = next_char3;
+ if (next_char2 == EOF_CHAR) {
+ next_char3 = EOF_CHAR;
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char3 = next_char4;
+ if (next_char3 == EOF_CHAR) {
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char4 = System.in.read();
+ }
+ }
+ }
+
+ /* count this */
+ absolute_position++;
+ current_position++;
+ if (old_char == '\n' || (old_char == '\r' && next_char!='\n'))
+ {
+ current_line++;
+ current_position = 1;
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit an error message. The message will be marked with both the
+ * current line number and the position in the line. Error messages
+ * are printed on standard error (System.err).
+ * @param message the message to print.
+ */
+ public static void emit_error(String message)
+ {
+ System.err.println("Error at " + current_line + "(" + current_position +
+ "): " + message);
+ error_count++;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit a warning message. The message will be marked with both the
+ * current line number and the position in the line. Messages are
+ * printed on standard error (System.err).
+ * @param message the message to print.
+ */
+ public static void emit_warn(String message)
+ {
+ System.err.println("Warning at " + current_line + "(" + current_position +
+ "): " + message);
+ warning_count++;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if a character is ok to start an id.
+ * @param ch the character in question.
+ */
+ protected static boolean id_start_char(int ch)
+ {
+ /* allow for % in identifiers. a hack to allow my
+ %prec in. Should eventually make lex spec for this
+ frankf */
+ return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
+ (ch == '_');
+
+ // later need to deal with non-8-bit chars here
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if a character is ok for the middle of an id.
+ * @param ch the character in question.
+ */
+ protected static boolean id_char(int ch)
+ {
+ return id_start_char(ch) || (ch >= '0' && ch <= '9');
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Try to look up a single character symbol, returns -1 for not found.
+ * @param ch the character in question.
+ */
+ protected static int find_single_char(int ch)
+ {
+ Integer result;
+
+ result = (Integer)char_symbols.get(new Integer((char)ch));
+ if (result == null)
+ return -1;
+ else
+ return result.intValue();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Handle swallowing up a comment. Both old style C and new style C++
+ * comments are handled.
+ */
+ protected static void swallow_comment() throws java.io.IOException
+ {
+ /* next_char == '/' at this point */
+
+ /* is it a traditional comment */
+ if (next_char2 == '*')
+ {
+ /* swallow the opener */
+ advance(); advance();
+
+ /* swallow the comment until end of comment or EOF */
+ for (;;)
+ {
+ /* if its EOF we have an error */
+ if (next_char == EOF_CHAR)
+ {
+ emit_error("Specification file ends inside a comment");
+ return;
+ }
+
+ /* if we can see the closer we are done */
+ if (next_char == '*' && next_char2 == '/')
+ {
+ advance();
+ advance();
+ return;
+ }
+
+ /* otherwise swallow char and move on */
+ advance();
+ }
+ }
+
+ /* is its a new style comment */
+ if (next_char2 == '/')
+ {
+ /* swallow the opener */
+ advance(); advance();
+
+ /* swallow to '\n', '\r', '\f', or EOF */
+ while (next_char != '\n' && next_char != '\r' &&
+ next_char != '\f' && next_char!=EOF_CHAR)
+ advance();
+
+ return;
+
+ }
+
+ /* shouldn't get here, but... if we get here we have an error */
+ emit_error("Malformed comment in specification -- ignored");
+ advance();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Swallow up a code string. Code strings begin with "{:" and include
+ all characters up to the first occurrence of ":}" (there is no way to
+ include ":}" inside a code string). The routine returns a String
+ object suitable for return by the scanner.
+ */
+ protected static Symbol do_code_string() throws java.io.IOException
+ {
+ StringBuffer result = new StringBuffer();
+
+ /* at this point we have lookahead of "{:" -- swallow that */
+ advance(); advance();
+
+ /* save chars until we see ":}" */
+ while (!(next_char == ':' && next_char2 == '}'))
+ {
+ /* if we have run off the end issue a message and break out of loop */
+ if (next_char == EOF_CHAR)
+ {
+ emit_error("Specification file ends inside a code string");
+ break;
+ }
+
+ /* otherwise record the char and move on */
+ result.append(new Character((char)next_char));
+ advance();
+ }
+
+ /* advance past the closer and build a return Symbol */
+ advance(); advance();
+ return new Symbol(sym.CODE_STRING, result.toString());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Process an identifier. Identifiers begin with a letter, underscore,
+ * or dollar sign, which is followed by zero or more letters, numbers,
+ * underscores or dollar signs. This routine returns a String suitable
+ * for return by the scanner.
+ */
+ protected static Symbol do_id() throws java.io.IOException
+ {
+ StringBuffer result = new StringBuffer();
+ String result_str;
+ Integer keyword_num;
+ char buffer[] = new char[1];
+
+ /* next_char holds first character of id */
+ buffer[0] = (char)next_char;
+ result.append(buffer,0,1);
+ advance();
+
+ /* collect up characters while they fit in id */
+ while(id_char(next_char))
+ {
+ buffer[0] = (char)next_char;
+ result.append(buffer,0,1);
+ advance();
+ }
+
+ /* extract a string and try to look it up as a keyword */
+ result_str = result.toString();
+ keyword_num = (Integer)keywords.get(result_str);
+
+ /* if we found something, return that keyword */
+ if (keyword_num != null)
+ return new Symbol(keyword_num.intValue());
+
+ /* otherwise build and return an id Symbol with an attached string */
+ return new Symbol(sym.ID, result_str);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return one Symbol. This is the main external interface to the scanner.
+ * It consumes sufficient characters to determine the next input Symbol
+ * and returns it. To help with debugging, this routine actually calls
+ * real_next_token() which does the work. If you need to debug the
+ * parser, this can be changed to call debug_next_token() which prints
+ * a debugging message before returning the Symbol.
+ */
+ public static Symbol next_token() throws java.io.IOException
+ {
+ return real_next_token();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Debugging version of next_token(). This routine calls the real scanning
+ * routine, prints a message on System.out indicating what the Symbol is,
+ * then returns it.
+ */
+ public static Symbol debug_next_token() throws java.io.IOException
+ {
+ Symbol result = real_next_token();
+ System.out.println("# next_Symbol() => " + result.sym);
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The actual routine to return one Symbol. This is normally called from
+ * next_token(), but for debugging purposes can be called indirectly from
+ * debug_next_token().
+ */
+ protected static Symbol real_next_token() throws java.io.IOException
+ {
+ int sym_num;
+
+ for (;;)
+ {
+ /* look for white space */
+ if (next_char == ' ' || next_char == '\t' || next_char == '\n' ||
+ next_char == '\f' || next_char == '\r')
+ {
+ /* advance past it and try the next character */
+ advance();
+ continue;
+ }
+
+ /* look for a single character symbol */
+ sym_num = find_single_char(next_char);
+ if (sym_num != -1)
+ {
+ /* found one -- advance past it and return a Symbol for it */
+ advance();
+ return new Symbol(sym_num);
+ }
+
+ /* look for : or ::= */
+ if (next_char == ':')
+ {
+ /* if we don't have a second ':' return COLON */
+ if (next_char2 != ':')
+ {
+ advance();
+ return new Symbol(sym.COLON);
+ }
+
+ /* move forward and look for the '=' */
+ advance();
+ if (next_char2 == '=')
+ {
+ advance(); advance();
+ return new Symbol(sym.COLON_COLON_EQUALS);
+ }
+ else
+ {
+ /* return just the colon (already consumed) */
+ return new Symbol(sym.COLON);
+ }
+ }
+
+ /* find a "%prec" string and return it. otherwise, a '%' was found,
+ which has no right being in the specification otherwise */
+ if (next_char == '%') {
+ advance();
+ if ((next_char == 'p') && (next_char2 == 'r') && (next_char3 == 'e') &&
+ (next_char4 == 'c')) {
+ advance();
+ advance();
+ advance();
+ advance();
+ return new Symbol(sym.PERCENT_PREC);
+ } else {
+ emit_error("Found extraneous percent sign");
+ }
+ }
+
+ /* look for a comment */
+ if (next_char == '/' && (next_char2 == '*' || next_char2 == '/'))
+ {
+ /* swallow then continue the scan */
+ swallow_comment();
+ continue;
+ }
+
+ /* look for start of code string */
+ if (next_char == '{' && next_char2 == ':')
+ return do_code_string();
+
+ /* look for an id or keyword */
+ if (id_start_char(next_char)) return do_id();
+
+ /* look for EOF */
+ if (next_char == EOF_CHAR) return new Symbol(sym.EOF);
+
+ /* if we get here, we have an unrecognized character */
+ emit_warn("Unrecognized character '" +
+ new Character((char)next_char) + "'(" + next_char +
+ ") -- ignored");
+
+ /* advance past it */
+ advance();
+ }
+ }
+
+ /*-----------------------------------------------------------*/
+}
+
diff --git a/src/syntaxParser/java_cup/lr_item_core.class b/src/syntaxParser/java_cup/lr_item_core.class
new file mode 100644
index 0000000..047e002
--- /dev/null
+++ b/src/syntaxParser/java_cup/lr_item_core.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/lr_item_core.java b/src/syntaxParser/java_cup/lr_item_core.java
new file mode 100644
index 0000000..c0fa656
--- /dev/null
+++ b/src/syntaxParser/java_cup/lr_item_core.java
@@ -0,0 +1,280 @@
+
+package java_cup;
+
+/** The "core" of an LR item. This includes a production and the position
+ * of a marker (the "dot") within the production. Typically item cores
+ * are written using a production with an embedded "dot" to indicate their
+ * position. For example: <pre>
+ * A ::= B * C d E
+ * </pre>
+ * This represents a point in a parse where the parser is trying to match
+ * the given production, and has succeeded in matching everything before the
+ * "dot" (and hence is expecting to see the symbols after the dot next). See
+ * lalr_item, lalr_item_set, and lalr_start for full details on the meaning
+ * and use of items.
+ *
+ * @see java_cup.lalr_item
+ * @see java_cup.lalr_item_set
+ * @see java_cup.lalr_state
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+*/
+
+public class lr_item_core {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param prod production this item uses.
+ * @param pos position of the "dot" within the item.
+ */
+ public lr_item_core(production prod, int pos) throws internal_error
+ {
+ symbol after_dot = null;
+ production_part part;
+
+ if (prod == null)
+ throw new internal_error(
+ "Attempt to create an lr_item_core with a null production");
+
+ _the_production = prod;
+
+ if (pos < 0 || pos > _the_production.rhs_length())
+ throw new internal_error(
+ "Attempt to create an lr_item_core with a bad dot position");
+
+ _dot_pos = pos;
+
+ /* compute and cache hash code now */
+ _core_hash_cache = 13*_the_production.hashCode() + pos;
+
+ /* cache the symbol after the dot */
+ if (_dot_pos < _the_production.rhs_length())
+ {
+ part = _the_production.rhs(_dot_pos);
+ if (!part.is_action())
+ _symbol_after_dot = ((symbol_part)part).the_symbol();
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor for dot at start of right hand side.
+ * @param prod production this item uses.
+ */
+ public lr_item_core(production prod) throws internal_error
+ {
+ this(prod,0);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The production for the item. */
+ protected production _the_production;
+
+ /** The production for the item. */
+ public production the_production() {return _the_production;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The position of the "dot" -- this indicates the part of the production
+ * that the marker is before, so 0 indicates a dot at the beginning of
+ * the RHS.
+ */
+ protected int _dot_pos;
+
+ /** The position of the "dot" -- this indicates the part of the production
+ * that the marker is before, so 0 indicates a dot at the beginning of
+ * the RHS.
+ */
+ public int dot_pos() {return _dot_pos;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Cache of the hash code. */
+ protected int _core_hash_cache;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Cache of symbol after the dot. */
+ protected symbol _symbol_after_dot = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Is the dot at the end of the production? */
+ public boolean dot_at_end()
+ {
+ return _dot_pos >= _the_production.rhs_length();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return the symbol after the dot. If there is no symbol after the dot
+ * we return null. */
+ public symbol symbol_after_dot()
+ {
+ /* use the cached symbol */
+ return _symbol_after_dot;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if we have a dot before a non terminal, and if so which one
+ * (return null or the non terminal).
+ */
+ public non_terminal dot_before_nt()
+ {
+ symbol sym;
+
+ /* get the symbol after the dot */
+ sym = symbol_after_dot();
+
+ /* if it exists and is a non terminal, return it */
+ if (sym != null && sym.is_non_term())
+ return (non_terminal)sym;
+ else
+ return null;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a new lr_item_core that results from shifting the dot one
+ * position to the right.
+ */
+ public lr_item_core shift_core() throws internal_error
+ {
+ if (dot_at_end())
+ throw new internal_error(
+ "Attempt to shift past end of an lr_item_core");
+
+ return new lr_item_core(_the_production, _dot_pos+1);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison for the core only. This is separate out because we
+ * need separate access in a super class.
+ */
+ public boolean core_equals(lr_item_core other)
+ {
+ return other != null &&
+ _the_production.equals(other._the_production) &&
+ _dot_pos == other._dot_pos;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(lr_item_core other) {return core_equals(other);}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof lr_item_core))
+ return false;
+ else
+ return equals((lr_item_core)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Hash code for the core (separated so we keep non overridden version). */
+ public int core_hashCode()
+ {
+ return _core_hash_cache;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Hash code for the item. */
+ public int hashCode()
+ {
+ return _core_hash_cache;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return the hash code that object would have provided for us so we have
+ * a (nearly) unique id for debugging.
+ */
+ protected int obj_hash()
+ {
+ return super.hashCode();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string (separated out from toString() so we can call it
+ * from subclass that overrides toString()).
+ */
+ public String to_simple_string() throws internal_error
+ {
+ String result;
+ production_part part;
+
+ if (_the_production.lhs() != null &&
+ _the_production.lhs().the_symbol() != null &&
+ _the_production.lhs().the_symbol().name() != null)
+ result = _the_production.lhs().the_symbol().name();
+ else
+ result = "$$NULL$$";
+
+ result += " ::= ";
+
+ for (int i = 0; i<_the_production.rhs_length(); i++)
+ {
+ /* do we need the dot before this one? */
+ if (i == _dot_pos)
+ result += "(*) ";
+
+ /* print the name of the part */
+ if (_the_production.rhs(i) == null)
+ {
+ result += "$$NULL$$ ";
+ }
+ else
+ {
+ part = _the_production.rhs(i);
+ if (part == null)
+ result += "$$NULL$$ ";
+ else if (part.is_action())
+ result += "{ACTION} ";
+ else if (((symbol_part)part).the_symbol() != null &&
+ ((symbol_part)part).the_symbol().name() != null)
+ result += ((symbol_part)part).the_symbol().name() + " ";
+ else
+ result += "$$NULL$$ ";
+ }
+ }
+
+ /* put the dot after if needed */
+ if (_dot_pos == _the_production.rhs_length())
+ result += "(*) ";
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string */
+ public String toString()
+ {
+ /* can't throw here since super class doesn't, so we crash instead */
+ try {
+ return to_simple_string();
+ } catch(internal_error e) {
+ e.crash();
+ return null;
+ }
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
diff --git a/src/syntaxParser/java_cup/non_terminal.class b/src/syntaxParser/java_cup/non_terminal.class
new file mode 100644
index 0000000..ba6079c
--- /dev/null
+++ b/src/syntaxParser/java_cup/non_terminal.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/non_terminal.java b/src/syntaxParser/java_cup/non_terminal.java
new file mode 100644
index 0000000..9354a7f
--- /dev/null
+++ b/src/syntaxParser/java_cup/non_terminal.java
@@ -0,0 +1,301 @@
+package java_cup;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/** This class represents a non-terminal symbol in the grammar. Each
+ * non terminal has a textual name, an index, and a string which indicates
+ * the type of object it will be implemented with at runtime (i.e. the class
+ * of object that will be pushed on the parse stack to represent it).
+ *
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+
+public class non_terminal extends symbol {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param nm the name of the non terminal.
+ * @param tp the type string for the non terminal.
+ */
+ public non_terminal(String nm, String tp)
+ {
+ /* super class does most of the work */
+ super(nm, tp);
+
+ /* add to set of all non terminals and check for duplicates */
+ Object conflict = _all.put(nm,this);
+ if (conflict != null)
+ // can't throw an exception here because these are used in static
+ // initializers, so we crash instead
+ // was:
+ // throw new internal_error("Duplicate non-terminal ("+nm+") created");
+ (new internal_error("Duplicate non-terminal ("+nm+") created")).crash();
+
+ /* assign a unique index */
+ _index = next_index++;
+
+ /* add to by_index set */
+ _all_by_index.put(new Integer(_index), this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with default type.
+ * @param nm the name of the non terminal.
+ */
+ public non_terminal(String nm)
+ {
+ this(nm, null);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Table of all non-terminals -- elements are stored using name strings
+ * as the key
+ */
+ protected static Hashtable _all = new Hashtable();
+
+ /** Access to all non-terminals. */
+ public static Enumeration all() {return _all.elements();}
+
+ /** lookup a non terminal by name string */
+ public static non_terminal find(String with_name)
+ {
+ if (with_name == null)
+ return null;
+ else
+ return (non_terminal)_all.get(with_name);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Table of all non terminals indexed by their index number. */
+ protected static Hashtable _all_by_index = new Hashtable();
+
+ /** Lookup a non terminal by index. */
+ public static non_terminal find(int indx)
+ {
+ Integer the_indx = new Integer(indx);
+
+ return (non_terminal)_all_by_index.get(the_indx);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Total number of non-terminals. */
+ public static int number() {return _all.size();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Static counter to assign unique indexes. */
+ protected static int next_index = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Static counter for creating unique non-terminal names */
+ static protected int next_nt = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** special non-terminal for start symbol */
+ public static final non_terminal START_nt = new non_terminal("$START");
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** flag non-terminals created to embed action productions */
+ public boolean is_embedded_action = false; /* added 24-Mar-1998, CSA */
+
+ /*-----------------------------------------------------------*/
+ /*--- Static Methods ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Method for creating a new uniquely named hidden non-terminal using
+ * the given string as a base for the name (or "NT$" if null is passed).
+ * @param prefix base name to construct unique name from.
+ */
+ static non_terminal create_new(String prefix) throws internal_error
+ {
+ if (prefix == null) prefix = "NT$";
+ return new non_terminal(prefix + next_nt++);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** static routine for creating a new uniquely named hidden non-terminal */
+ static non_terminal create_new() throws internal_error
+ {
+ return create_new(null);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute nullability of all non-terminals. */
+ public static void compute_nullability() throws internal_error
+ {
+ boolean change = true;
+ non_terminal nt;
+ Enumeration e;
+ production prod;
+
+ /* repeat this process until there is no change */
+ while (change)
+ {
+ /* look for a new change */
+ change = false;
+
+ /* consider each non-terminal */
+ for (e=all(); e.hasMoreElements(); )
+ {
+ nt = (non_terminal)e.nextElement();
+
+ /* only look at things that aren't already marked nullable */
+ if (!nt.nullable())
+ {
+ if (nt.looks_nullable())
+ {
+ nt._nullable = true;
+ change = true;
+ }
+ }
+ }
+ }
+
+ /* do one last pass over the productions to finalize all of them */
+ for (e=production.all(); e.hasMoreElements(); )
+ {
+ prod = (production)e.nextElement();
+ prod.set_nullable(prod.check_nullable());
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute first sets for all non-terminals. This assumes nullability has
+ * already computed.
+ */
+ public static void compute_first_sets() throws internal_error
+ {
+ boolean change = true;
+ Enumeration n;
+ Enumeration p;
+ non_terminal nt;
+ production prod;
+ terminal_set prod_first;
+
+ /* repeat this process until we have no change */
+ while (change)
+ {
+ /* look for a new change */
+ change = false;
+
+ /* consider each non-terminal */
+ for (n = all(); n.hasMoreElements(); )
+ {
+ nt = (non_terminal)n.nextElement();
+
+ /* consider every production of that non terminal */
+ for (p = nt.productions(); p.hasMoreElements(); )
+ {
+ prod = (production)p.nextElement();
+
+ /* get the updated first of that production */
+ prod_first = prod.check_first_set();
+
+ /* if this going to add anything, add it */
+ if (!prod_first.is_subset_of(nt._first_set))
+ {
+ change = true;
+ nt._first_set.add(prod_first);
+ }
+ }
+ }
+ }
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Table of all productions with this non terminal on the LHS. */
+ protected Hashtable _productions = new Hashtable(11);
+
+ /** Access to productions with this non terminal on the LHS. */
+ public Enumeration productions() {return _productions.elements();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Total number of productions with this non terminal on the LHS. */
+ public int num_productions() {return _productions.size();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a production to our set of productions. */
+ public void add_production(production prod) throws internal_error
+ {
+ /* catch improper productions */
+ if (prod == null || prod.lhs() == null || prod.lhs().the_symbol() != this)
+ throw new internal_error(
+ "Attempt to add invalid production to non terminal production table");
+
+ /* add it to the table, keyed with itself */
+ _productions.put(prod,prod);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Nullability of this non terminal. */
+ protected boolean _nullable;
+
+ /** Nullability of this non terminal. */
+ public boolean nullable() {return _nullable;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** First set for this non-terminal. */
+ protected terminal_set _first_set = new terminal_set();
+
+ /** First set for this non-terminal. */
+ public terminal_set first_set() {return _first_set;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Indicate that this symbol is a non-terminal. */
+ public boolean is_non_term()
+ {
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Test to see if this non terminal currently looks nullable. */
+ protected boolean looks_nullable() throws internal_error
+ {
+ /* look and see if any of the productions now look nullable */
+ for (Enumeration e = productions(); e.hasMoreElements(); )
+ /* if the production can go to empty, we are nullable */
+ if (((production)e.nextElement()).check_nullable())
+ return true;
+
+ /* none of the productions can go to empty, so we are not nullable */
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** convert to string */
+ public String toString()
+ {
+ return super.toString() + "[" + index() + "]" + (nullable() ? "*" : "");
+ }
+
+ /*-----------------------------------------------------------*/
+}
diff --git a/src/syntaxParser/java_cup/nonassoc_action.class b/src/syntaxParser/java_cup/nonassoc_action.class
new file mode 100644
index 0000000..fcb75a7
--- /dev/null
+++ b/src/syntaxParser/java_cup/nonassoc_action.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/nonassoc_action.java b/src/syntaxParser/java_cup/nonassoc_action.java
new file mode 100644
index 0000000..3882324
--- /dev/null
+++ b/src/syntaxParser/java_cup/nonassoc_action.java
@@ -0,0 +1,71 @@
+
+package java_cup;
+
+/** This class represents a shift/reduce nonassociative error within the
+ * parse table. If action_table element is assign to type
+ * nonassoc_action, it cannot be changed, and signifies that there
+ * is a conflict between shifting and reducing a production and a
+ * terminal that shouldn't be next to each other.
+ *
+ * @version last updated: 7/2/96
+ * @author Frank Flannery
+ */
+public class nonassoc_action extends parse_action {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor.
+ */
+ public nonassoc_action() throws internal_error
+ {
+ /* don't need to set anything, since it signifies error */
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Quick access to type of action. */
+ public int kind() {return NONASSOC;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality test. */
+ public boolean equals(parse_action other)
+ {
+ return other != null && other.kind() == NONASSOC;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality test. */
+ public boolean equals(Object other)
+ {
+ if (other instanceof parse_action)
+ return equals((parse_action)other);
+ else
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute a hash code. */
+ public int hashCode()
+ {
+ /* all objects of this class hash together */
+ return 0xCafe321;
+ }
+
+
+
+ /** Convert to string. */
+ public String toString()
+ {
+ return "NONASSOC";
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/syntaxParser/java_cup/parse_action.class b/src/syntaxParser/java_cup/parse_action.class
new file mode 100644
index 0000000..63c0ffa
--- /dev/null
+++ b/src/syntaxParser/java_cup/parse_action.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/parse_action.java b/src/syntaxParser/java_cup/parse_action.java
new file mode 100644
index 0000000..9228663
--- /dev/null
+++ b/src/syntaxParser/java_cup/parse_action.java
@@ -0,0 +1,92 @@
+
+package java_cup;
+
+/** This class serves as the base class for entries in a parse action table.
+ * Full entries will either be SHIFT(state_num), REDUCE(production), NONASSOC,
+ * or ERROR. Objects of this base class will default to ERROR, while
+ * the other three types will be represented by subclasses.
+ *
+ * @see java_cup.reduce_action
+ * @see java_cup.shift_action
+ * @version last updated: 7/2/96
+ * @author Frank Flannery
+ */
+
+public class parse_action {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. */
+ public parse_action()
+ {
+ /* nothing to do in the base class */
+ }
+
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constant for action type -- error action. */
+ public static final int ERROR = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constant for action type -- shift action. */
+ public static final int SHIFT = 1;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constants for action type -- reduce action. */
+ public static final int REDUCE = 2;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constants for action type -- reduce action. */
+ public static final int NONASSOC = 3;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Quick access to the type -- base class defaults to error. */
+ public int kind() {return ERROR;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality test. */
+ public boolean equals(parse_action other)
+ {
+ /* we match all error actions */
+ return other != null && other.kind() == ERROR;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality test. */
+ public boolean equals(Object other)
+ {
+ if (other instanceof parse_action)
+ return equals((parse_action)other);
+ else
+ return false;
+ }
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute a hash code. */
+ public int hashCode()
+ {
+ /* all objects of this class hash together */
+ return 0xCafe123;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to string. */
+ public String toString() {return "ERROR";}
+
+ /*-----------------------------------------------------------*/
+}
+
diff --git a/src/syntaxParser/java_cup/parse_action_row.class b/src/syntaxParser/java_cup/parse_action_row.class
new file mode 100644
index 0000000..5c407fb
--- /dev/null
+++ b/src/syntaxParser/java_cup/parse_action_row.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/parse_action_row.java b/src/syntaxParser/java_cup/parse_action_row.java
new file mode 100644
index 0000000..817b8c5
--- /dev/null
+++ b/src/syntaxParser/java_cup/parse_action_row.java
@@ -0,0 +1,106 @@
+
+package java_cup;
+
+/** This class represents one row (corresponding to one machine state) of the
+ * parse action table.
+ */
+public class parse_action_row {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. Note: this should not be used until the number of
+ * terminals in the grammar has been established.
+ */
+ public parse_action_row()
+ {
+ /* make sure the size is set */
+ if (_size <= 0 ) _size = terminal.number();
+
+ /* allocate the array */
+ under_term = new parse_action[size()];
+
+ /* set each element to an error action */
+ for (int i=0; i<_size; i++)
+ under_term[i] = new parse_action();
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Number of columns (terminals) in every row. */
+ protected static int _size = 0;
+
+ /** Number of columns (terminals) in every row. */
+ public static int size() {return _size;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Table of reduction counts (reused by compute_default()). */
+ protected static int reduction_count[] = null;
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Actual action entries for the row. */
+ public parse_action under_term[];
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Default (reduce) action for this row. -1 will represent default
+ * of error.
+ */
+ public int default_reduce;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Compute the default (reduce) action for this row and store it in
+ * default_reduce. In the case of non-zero default we will have the
+ * effect of replacing all errors by that reduction. This may cause
+ * us to do erroneous reduces, but will never cause us to shift past
+ * the point of the error and never cause an incorrect parse. -1 will
+ * be used to encode the fact that no reduction can be used as a
+ * default (in which case error will be used).
+ */
+ public void compute_default()
+ {
+ int i, prod, max_prod, max_red;
+
+ /* if we haven't allocated the count table, do so now */
+ if (reduction_count == null)
+ reduction_count = new int[production.number()];
+
+ /* clear the reduction count table and maximums */
+ for (i = 0; i < production.number(); i++)
+ reduction_count[i] = 0;
+ max_prod = -1;
+ max_red = 0;
+
+ /* walk down the row and look at the reduces */
+ for (i = 0; i < size(); i++)
+ if (under_term[i].kind() == parse_action.REDUCE)
+ {
+ /* count the reduce in the proper production slot and keep the
+ max up to date */
+ prod = ((reduce_action)under_term[i]).reduce_with().index();
+ reduction_count[prod]++;
+ if (reduction_count[prod] > max_red)
+ {
+ max_red = reduction_count[prod];
+ max_prod = prod;
+ }
+ }
+
+ /* record the max as the default (or -1 for not found) */
+ default_reduce = max_prod;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
diff --git a/src/syntaxParser/java_cup/parse_action_table.class b/src/syntaxParser/java_cup/parse_action_table.class
new file mode 100644
index 0000000..43bfea8
--- /dev/null
+++ b/src/syntaxParser/java_cup/parse_action_table.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/parse_action_table.java b/src/syntaxParser/java_cup/parse_action_table.java
new file mode 100644
index 0000000..1e0edb2
--- /dev/null
+++ b/src/syntaxParser/java_cup/parse_action_table.java
@@ -0,0 +1,143 @@
+
+package java_cup;
+
+import java.util.Enumeration;
+
+/** This class represents the complete "action" table of the parser.
+ * It has one row for each state in the parse machine, and a column for
+ * each terminal symbol. Each entry in the table represents a shift,
+ * reduce, or an error.
+ *
+ * @see java_cup.parse_action
+ * @see java_cup.parse_action_row
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class parse_action_table {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. All terminals, non-terminals, and productions must
+ * already have been entered, and the viable prefix recognizer should
+ * have been constructed before this is called.
+ */
+ public parse_action_table()
+ {
+ /* determine how many states we are working with */
+ _num_states = lalr_state.number();
+
+ /* allocate the array and fill it in with empty rows */
+ under_state = new parse_action_row[_num_states];
+ for (int i=0; i<_num_states; i++)
+ under_state[i] = new parse_action_row();
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** How many rows/states are in the machine/table. */
+ protected int _num_states;
+
+ /** How many rows/states are in the machine/table. */
+ public int num_states() {return _num_states;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Actual array of rows, one per state. */
+ public parse_action_row[] under_state;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Check the table to ensure that all productions have been reduced.
+ * Issue a warning message (to System.err) for each production that
+ * is never reduced.
+ */
+ public void check_reductions()
+ throws internal_error
+ {
+ parse_action act;
+ production prod;
+
+ /* tabulate reductions -- look at every table entry */
+ for (int row = 0; row < num_states(); row++)
+ {
+ for (int col = 0; col < under_state[row].size(); col++)
+ {
+ /* look at the action entry to see if its a reduce */
+ act = under_state[row].under_term[col];
+ if (act != null && act.kind() == parse_action.REDUCE)
+ {
+ /* tell production that we used it */
+ ((reduce_action)act).reduce_with().note_reduction_use();
+ }
+ }
+ }
+
+ /* now go across every production and make sure we hit it */
+ for (Enumeration p = production.all(); p.hasMoreElements(); )
+ {
+ prod = (production)p.nextElement();
+
+ /* if we didn't hit it give a warning */
+ if (prod.num_reductions() == 0)
+ {
+ /* count it *
+ emit.not_reduced++;
+
+ /* give a warning if they haven't been turned off */
+ if (!emit.nowarn)
+ {
+ System.err.println("*** Production \"" +
+ prod.to_simple_string() + "\" never reduced");
+ lexer.warning_count++;
+ }
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+ int cnt;
+
+ result = "-------- ACTION_TABLE --------\n";
+ for (int row = 0; row < num_states(); row++)
+ {
+ result += "From state #" + row + "\n";
+ cnt = 0;
+ for (int col = 0; col < under_state[row].size(); col++)
+ {
+ /* if the action is not an error print it */
+ if (under_state[row].under_term[col].kind() != parse_action.ERROR)
+ {
+ result += " [term " + col + ":" + under_state[row].under_term[col] + "]";
+
+ /* end the line after the 2nd one */
+ cnt++;
+ if (cnt == 2)
+ {
+ result += "\n";
+ cnt = 0;
+ }
+ }
+ }
+ /* finish the line if we haven't just done that */
+ if (cnt != 0) result += "\n";
+ }
+ result += "------------------------------";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
diff --git a/src/syntaxParser/java_cup/parse_reduce_row.class b/src/syntaxParser/java_cup/parse_reduce_row.class
new file mode 100644
index 0000000..f62f13a
--- /dev/null
+++ b/src/syntaxParser/java_cup/parse_reduce_row.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/parse_reduce_row.java b/src/syntaxParser/java_cup/parse_reduce_row.java
new file mode 100644
index 0000000..57d978e
--- /dev/null
+++ b/src/syntaxParser/java_cup/parse_reduce_row.java
@@ -0,0 +1,41 @@
+
+package java_cup;
+
+/** This class represents one row (corresponding to one machine state) of the
+ * reduce-goto parse table.
+ */
+public class parse_reduce_row {
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. Note: this should not be used until the number
+ * of terminals in the grammar has been established.
+ */
+ public parse_reduce_row()
+ {
+ /* make sure the size is set */
+ if (_size <= 0 ) _size = non_terminal.number();
+
+ /* allocate the array */
+ under_non_term = new lalr_state[size()];
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Number of columns (non terminals) in every row. */
+ protected static int _size = 0;
+
+ /** Number of columns (non terminals) in every row. */
+ public static int size() {return _size;}
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Actual entries for the row. */
+ public lalr_state under_non_term[];
+}
+
diff --git a/src/syntaxParser/java_cup/parse_reduce_table.class b/src/syntaxParser/java_cup/parse_reduce_table.class
new file mode 100644
index 0000000..44211d2
--- /dev/null
+++ b/src/syntaxParser/java_cup/parse_reduce_table.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/parse_reduce_table.java b/src/syntaxParser/java_cup/parse_reduce_table.java
new file mode 100644
index 0000000..9ac1b11
--- /dev/null
+++ b/src/syntaxParser/java_cup/parse_reduce_table.java
@@ -0,0 +1,99 @@
+
+package java_cup;
+
+import java.util.Enumeration;
+
+/** This class represents the complete "reduce-goto" table of the parser.
+ * It has one row for each state in the parse machines, and a column for
+ * each terminal symbol. Each entry contains a state number to shift to
+ * as the last step of a reduce.
+ *
+ * @see java_cup.parse_reduce_row
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class parse_reduce_table {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. Note: all terminals, non-terminals, and productions
+ * must already have been entered, and the viable prefix recognizer should
+ * have been constructed before this is called.
+ */
+ public parse_reduce_table()
+ {
+ /* determine how many states we are working with */
+ _num_states = lalr_state.number();
+
+ /* allocate the array and fill it in with empty rows */
+ under_state = new parse_reduce_row[_num_states];
+ for (int i=0; i<_num_states; i++)
+ under_state[i] = new parse_reduce_row();
+ }
+
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** How many rows/states in the machine/table. */
+ protected int _num_states;
+
+ /** How many rows/states in the machine/table. */
+ public int num_states() {return _num_states;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Actual array of rows, one per state */
+ public parse_reduce_row[] under_state;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+ lalr_state goto_st;
+ int cnt;
+
+ result = "-------- REDUCE_TABLE --------\n";
+ for (int row = 0; row < num_states(); row++)
+ {
+ result += "From state #" + row + "\n";
+ cnt = 0;
+ for (int col = 0; col < under_state[row].size(); col++)
+ {
+ /* pull out the table entry */
+ goto_st = under_state[row].under_non_term[col];
+
+ /* if it has action in it, print it */
+ if (goto_st != null)
+ {
+ result += " [non term " + col + "->";
+ result += "state " + goto_st.index() + "]";
+
+ /* end the line after the 3rd one */
+ cnt++;
+ if (cnt == 3)
+ {
+ result += "\n";
+ cnt = 0;
+ }
+ }
+ }
+ /* finish the line if we haven't just done that */
+ if (cnt != 0) result += "\n";
+ }
+ result += "-----------------------------";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
diff --git a/src/syntaxParser/java_cup/parser.class b/src/syntaxParser/java_cup/parser.class
new file mode 100644
index 0000000..05af393
--- /dev/null
+++ b/src/syntaxParser/java_cup/parser.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/parser.cup b/src/syntaxParser/java_cup/parser.cup
new file mode 100644
index 0000000..8af0d05
--- /dev/null
+++ b/src/syntaxParser/java_cup/parser.cup
@@ -0,0 +1,863 @@
+
+/*================================================================*/
+/*
+ JavaCup Specification for the JavaCup Specification Language
+ by Scott Hudson, GVU Center, Georgia Tech, August 1995
+ and Frank Flannery, Department of Computer Science, Princeton Univ,
+ July 1996
+ Bug Fixes: C. Scott Ananian, Dept of Electrical Engineering, Princeton
+ University, October 1996. [later Massachusetts Institute of Technology]
+
+
+ This JavaCup specification is used to implement JavaCup itself.
+ It specifies the parser for the JavaCup specification language.
+ (It also serves as a reasonable example of what a typical JavaCup
+ spec looks like).
+
+ The specification has the following parts:
+ Package and import declarations
+ These serve the same purpose as in a normal Java source file
+ (and will appear in the generated code for the parser). In this
+ case we are part of the java_cup package and we import both the
+ java_cup runtime system and Hashtable from the standard Java
+ utilities package.
+
+ Action code
+ This section provides code that is included with the class encapsulating
+ the various pieces of user code embedded in the grammar (i.e., the
+ semantic actions). This provides a series of helper routines and
+ data structures that the semantic actions use.
+
+ Parser code
+ This section provides code included in the parser class itself. In
+ this case we override the default error reporting routines.
+
+ Init with and scan with
+ These sections provide small bits of code that initialize, then
+ indicate how to invoke the scanner.
+
+ Symbols and grammar
+ These sections declare all the terminal and non terminal symbols
+ and the types of objects that they will be represented by at runtime,
+ then indicate the start symbol of the grammar (), and finally provide
+ the grammar itself (with embedded actions).
+
+ Operation of the parser
+ The parser acts primarily by accumulating data structures representing
+ various parts of the specification. Various small parts (e.g., single
+ code strings) are stored as static variables of the emit class and
+ in a few cases as variables declared in the action code section.
+ Terminals, non terminals, and productions, are maintained as collection
+ accessible via static methods of those classes. In addition, two
+ symbol tables are kept:
+ symbols maintains the name to object mapping for all symbols
+ non_terms maintains a separate mapping containing only the non terms
+
+ Several intermediate working structures are also declared in the action
+ code section. These include: rhs_parts, rhs_pos, and lhs_nt which
+ build up parts of the current production while it is being parsed.
+
+ Author(s)
+ Scott Hudson, GVU Center, Georgia Tech.
+ Frank Flannery, Department of Computer Science, Princeton Univ.
+ C. Scott Ananian, Department of Electrical Engineering, Princeton Univ.
+
+ Revisions
+ v0.9a First released version [SEH] 8/29/95
+ v0.9b Updated for beta language (throws clauses) [SEH] 11/25/95
+ v0.10a Made many improvements/changes. now offers:
+ return value
+ left/right positions and propagations
+ cleaner label references
+ precedence and associativity for terminals
+ contextual precedence for productions
+ [FF] 7/3/96
+ v0.10b Fixed %prec directive so it works like it's supposed to.
+ [CSA] 10/10/96
+ v0.10g Added support for array types on symbols.
+ [CSA] 03/23/98
+ v0.10i Broaden set of IDs allowed in multipart_id and label_id so
+ that only java reserved words (and not CUP reserved words like
+ 'parser' and 'start') are prohibited. Allow reordering of
+ action code, parser code, init code, and scan with sections,
+ and made closing semicolon optional for these sections.
+ Added 'nonterminal' as a terminal symbol, finally fixing a
+ spelling mistake that's been around since the beginning.
+ For backwards compatibility, you can still misspell the
+ word if you like.
+*/
+/*================================================================*/
+
+package java_cup;
+import java_cup.runtime.*;
+import java.util.Hashtable;
+
+/*----------------------------------------------------------------*/
+
+action code {:
+ /** helper routine to clone a new production part adding a given label */
+ protected production_part add_lab(production_part part, String lab)
+ throws internal_error
+ {
+ /* if there is no label, or this is an action, just return the original */
+ if (lab == null || part.is_action()) return part;
+
+ /* otherwise build a new one with the given label attached */
+ return new symbol_part(((symbol_part)part).the_symbol(),lab);
+ }
+
+ /** max size of right hand side we will support */
+ protected final int MAX_RHS = 200;
+
+ /** array for accumulating right hand side parts */
+ protected production_part[] rhs_parts = new production_part[MAX_RHS];
+
+ /** where we are currently in building a right hand side */
+ protected int rhs_pos = 0;
+
+ /** start a new right hand side */
+ protected void new_rhs() {rhs_pos = 0; }
+
+ /** add a new right hand side part */
+ protected void add_rhs_part(production_part part) throws java.lang.Exception
+ {
+ if (rhs_pos >= MAX_RHS)
+ throw new Exception("Internal Error: Productions limited to " +
+ MAX_RHS + " symbols and actions");
+
+ rhs_parts[rhs_pos] = part;
+ rhs_pos++;
+ }
+
+ /** string to build up multiple part names */
+ protected String multipart_name = new String();
+
+ /** append a new name segment to the accumulated multipart name */
+ protected void append_multipart(String name)
+ {
+ String dot = "";
+
+ /* if we aren't just starting out, put on a dot */
+ if (multipart_name.length() != 0) dot = ".";
+
+ multipart_name = multipart_name.concat(dot + name);
+ }
+
+ /** table of declared symbols -- contains production parts indexed by name */
+ protected Hashtable symbols = new Hashtable();
+
+ /** table of just non terminals -- contains non_terminals indexed by name */
+ protected Hashtable non_terms = new Hashtable();
+
+ /** declared start non_terminal */
+ protected non_terminal start_nt = null;
+
+ /** left hand side non terminal of the current production */
+ protected non_terminal lhs_nt;
+
+ /** Current precedence number */
+ int _cur_prec = 0;
+
+ /** Current precedence side */
+ int _cur_side = assoc.no_prec;
+
+ /** update the precedences we are declaring */
+ protected void update_precedence(int p) {
+ _cur_side = p;
+ _cur_prec++;
+ }
+ /** add relevant data to terminals */
+ protected void add_precedence(String term) {
+ if (term == null) {
+ System.err.println("Unable to add precedence to nonexistent terminal");
+ } else {
+ symbol_part sp = (symbol_part)symbols.get(term);
+ if (sp == null) {
+ System.err.println("Could find terminal " + term + " while declaring precedence");
+ } else {
+ java_cup.symbol sym = sp.the_symbol();
+ if (sym instanceof terminal)
+ ((terminal)sym).set_precedence(_cur_side, _cur_prec);
+ else System.err.println("Precedence declaration: Can't find terminal " + term);
+ }
+ }
+ }
+:};
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+parser code {:
+
+ /* override error routines */
+
+ public void report_fatal_error(
+ String message,
+ Object info)
+ {
+ done_parsing();
+ lexer.emit_error(message);
+ System.err.println("Can't recover from previous error(s), giving up.");
+ System.exit(1);
+ }
+
+ public void report_error(String message, Object info)
+ {
+ lexer.emit_error(message);
+ }
+:};
+
+/*----------------------------------------------------------------*/
+
+init with {: lexer.init(); :};
+scan with {: return lexer.next_token(); :};
+
+/*----------------------------------------------------------------*/
+
+terminal
+ PACKAGE, IMPORT, CODE, ACTION, PARSER, TERMINAL, NON, INIT, SCAN, WITH,
+ START, SEMI, COMMA, STAR, DOT, COLON, COLON_COLON_EQUALS, BAR, PRECEDENCE,
+ LEFT, RIGHT, NONASSOC, PERCENT_PREC, LBRACK, RBRACK, NONTERMINAL;
+
+terminal String ID, CODE_STRING;
+
+non terminal
+ spec, package_spec, import_list, action_code_part,
+ code_parts, code_part, opt_semi, non_terminal,
+ parser_code_part, symbol_list, start_spec, production_list,
+ multipart_id, import_spec, import_id, init_code, scan_code, symbol,
+ type_id, term_name_list, non_term_name_list, production, prod_part_list,
+ prod_part, new_term_id, new_non_term_id, rhs_list, rhs, empty,
+ precedence_list, preced, terminal_list, precedence_l, declares_term,
+ declares_non_term;
+
+non terminal String nt_id, symbol_id, label_id, opt_label, terminal_id,
+ term_id, robust_id;
+
+/*----------------------------------------------------------------*/
+
+start with spec;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+spec ::=
+ {:
+ /* declare "error" as a terminal */
+ symbols.put("error", new symbol_part(terminal.error));
+
+ /* declare start non terminal */
+ non_terms.put("$START", non_terminal.START_nt);
+ :}
+ package_spec
+ import_list
+ code_parts
+ symbol_list
+ precedence_list
+ start_spec
+ production_list
+ |
+ /* error recovery assuming something went wrong before symbols
+ and we have TERMINAL or NON TERMINAL to sync on. if we get
+ an error after that, we recover inside symbol_list or
+ production_list
+ */
+ error
+ symbol_list
+ precedence_list
+ start_spec
+ production_list
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+package_spec ::=
+ PACKAGE
+ multipart_id
+ {:
+ /* save the package name */
+ emit.package_name = multipart_name;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+import_list ::=
+ import_list
+ import_spec
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+import_spec ::=
+ IMPORT
+ import_id
+ {:
+ /* save this import on the imports list */
+ emit.import_list.push(multipart_name);
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+// allow any order; all parts are optional. [CSA, 23-Jul-1999]
+// (we check in the part action to make sure we don't have 2 of any part)
+code_part ::=
+ action_code_part | parser_code_part | init_code | scan_code ;
+code_parts ::=
+ | code_parts code_part;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+action_code_part ::=
+ ACTION CODE CODE_STRING:user_code opt_semi
+ {:
+ if (emit.action_code!=null)
+ lexer.emit_error("Redundant action code (skipping)");
+ else /* save the user included code string */
+ emit.action_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+parser_code_part ::=
+ PARSER CODE CODE_STRING:user_code opt_semi
+ {:
+ if (emit.parser_code!=null)
+ lexer.emit_error("Redundant parser code (skipping)");
+ else /* save the user included code string */
+ emit.parser_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+init_code ::=
+ INIT WITH CODE_STRING:user_code opt_semi
+ {:
+ if (emit.init_code!=null)
+ lexer.emit_error("Redundant init code (skipping)");
+ else /* save the user code */
+ emit.init_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+scan_code ::=
+ SCAN WITH CODE_STRING:user_code opt_semi
+ {:
+ if (emit.scan_code!=null)
+ lexer.emit_error("Redundant scan code (skipping)");
+ else /* save the user code */
+ emit.scan_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+symbol_list ::= symbol_list symbol | symbol;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+symbol ::=
+ TERMINAL
+ type_id
+ declares_term
+ |
+ TERMINAL
+ declares_term
+ |
+ non_terminal
+ type_id
+ declares_non_term
+ |
+ non_terminal
+ declares_non_term
+ |
+ /* error recovery productions -- sync on semicolon */
+
+ TERMINAL
+ error
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ |
+ non_terminal
+ error
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+declares_term ::=
+ term_name_list
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+declares_non_term ::=
+ non_term_name_list
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+term_name_list ::= term_name_list COMMA new_term_id | new_term_id;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+non_term_name_list ::=
+ non_term_name_list
+ COMMA
+ new_non_term_id
+ |
+ new_non_term_id
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+
+precedence_list ::= precedence_l | empty;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+precedence_l ::= precedence_l preced | preced;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+preced ::=
+ PRECEDENCE LEFT
+ {:
+ update_precedence(assoc.left);
+ :}
+ terminal_list SEMI
+ |
+ PRECEDENCE RIGHT
+ {:
+ update_precedence(assoc.right);
+ :}
+ terminal_list SEMI
+ |
+ PRECEDENCE NONASSOC
+ {:
+ update_precedence(assoc.nonassoc);
+ :}
+ terminal_list SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+terminal_list ::= terminal_list COMMA terminal_id
+ |
+ terminal_id
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+terminal_id ::= term_id:sym
+ {:
+ add_precedence(sym);
+ RESULT = sym;
+ :};
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+term_id ::= symbol_id:sym
+ {:
+ /* check that the symbol_id is a terminal */
+ if (symbols.get(sym) == null)
+ {
+ /* issue a message */
+ lexer.emit_error("Terminal \"" + sym +
+ "\" has not been declared");
+ }
+ RESULT = sym;
+ :};
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+start_spec ::=
+ START WITH nt_id:start_name
+ {:
+ /* verify that the name has been declared as a non terminal */
+ non_terminal nt = (non_terminal)non_terms.get(start_name);
+ if (nt == null)
+ {
+ lexer.emit_error( "Start non terminal \"" + start_name +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* remember the non-terminal for later */
+ start_nt = nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt), "start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+ new_rhs();
+ }
+ :}
+ SEMI
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+production_list ::= production_list production | production;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+production ::=
+ nt_id:lhs_id
+ {:
+ /* lookup the lhs nt */
+ lhs_nt = (non_terminal)non_terms.get(lhs_id);
+
+ /* if it wasn't declared, emit a message */
+ if (lhs_nt == null)
+ {
+ if (lexer.error_count == 0)
+ lexer.emit_error("LHS non terminal \"" + lhs_id +
+ "\" has not been declared");
+ }
+
+ /* reset the rhs accumulation */
+ new_rhs();
+ :}
+ COLON_COLON_EQUALS
+ {: :}
+ rhs_list
+ SEMI
+ |
+ error
+ {: lexer.emit_error("Syntax Error"); :}
+ SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+rhs_list ::= rhs_list BAR rhs | rhs;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+rhs ::=
+ prod_part_list PERCENT_PREC term_id:term_name
+ {:
+ java_cup.symbol sym = null;
+ if (lhs_nt != null)
+ {
+ /* Find the precedence symbol */
+ if (term_name == null) {
+ System.err.println("No terminal for contextual precedence");
+ sym = null;
+ } else {
+ sym = ((symbol_part)symbols.get(term_name)).the_symbol();
+ }
+ /* build the production */
+ production p;
+ if ((sym!=null) && (sym instanceof terminal)) {
+ p = new production(lhs_nt, rhs_parts, rhs_pos,
+ ((terminal)sym).precedence_num(),
+ ((terminal)sym).precedence_side());
+ ((symbol_part)symbols.get(term_name)).the_symbol().note_use();
+ } else {
+ System.err.println("Invalid terminal " + term_name +
+ " for contextual precedence assignment");
+ p = new production(lhs_nt, rhs_parts, rhs_pos);
+ }
+
+ /* if we have no start non-terminal declared and this is
+ the first production, make its lhs nt the start_nt
+ and build a special start production for it. */
+ if (start_nt == null)
+ {
+ start_nt = lhs_nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt),"start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ if ((sym!=null) && (sym instanceof terminal)) {
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts,
+ rhs_pos, ((terminal)sym).precedence_num(),
+ ((terminal)sym).precedence_side());
+ } else {
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+ }
+ new_rhs();
+ }
+ }
+
+ /* reset the rhs accumulation in any case */
+ new_rhs();
+ :}
+ |
+ prod_part_list
+ {:
+ if (lhs_nt != null)
+ {
+ /* build the production */
+ production p = new production(lhs_nt, rhs_parts, rhs_pos);
+
+ /* if we have no start non-terminal declared and this is
+ the first production, make its lhs nt the start_nt
+ and build a special start production for it. */
+ if (start_nt == null)
+ {
+ start_nt = lhs_nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt),"start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+
+ new_rhs();
+ }
+ }
+
+ /* reset the rhs accumulation in any case */
+ new_rhs();
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+prod_part_list ::= prod_part_list prod_part | empty;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+prod_part ::=
+ symbol_id:symid opt_label:labid
+ {:
+ /* try to look up the id */
+ production_part symb = (production_part)symbols.get(symid);
+
+ /* if that fails, symbol is undeclared */
+ if (symb == null)
+ {
+ if (lexer.error_count == 0)
+ lexer.emit_error("java_cup.runtime.Symbol \"" + symid +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* add a labeled production part */
+ add_rhs_part(add_lab(symb, labid));
+ }
+ :}
+ |
+ CODE_STRING:code_str
+ {:
+ /* add a new production part */
+ add_rhs_part(new action_part(code_str));
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+opt_label ::=
+ COLON label_id:labid
+ {: RESULT = labid; :}
+ |
+ empty
+ {: RESULT = null; :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+multipart_id ::=
+ multipart_id DOT robust_id:another_id
+ {: append_multipart(another_id); :}
+ |
+ robust_id:an_id
+ {: append_multipart(an_id); :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+import_id ::=
+ multipart_id DOT STAR
+ {: append_multipart("*"); :}
+ |
+ multipart_id
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+type_id ::= multipart_id
+ | type_id LBRACK RBRACK
+ {: multipart_name = multipart_name.concat("[]"); :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+new_term_id ::=
+ ID:term_id
+ {:
+ /* see if this terminal has been declared before */
+ if (symbols.get(term_id) != null)
+ {
+ /* issue a message */
+ lexer.emit_error("java_cup.runtime.Symbol \"" + term_id +
+ "\" has already been declared");
+ }
+ else
+ {
+ /* if no type declared, declare one */
+ if (multipart_name.equals("")) {
+ append_multipart("Object");
+ }
+ /* build a production_part and put it in the table */
+ symbols.put(term_id,
+ new symbol_part(new terminal(term_id, multipart_name)));
+ }
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+new_non_term_id ::=
+ ID:non_term_id
+ {:
+ /* see if this non terminal has been declared before */
+ if (symbols.get(non_term_id) != null)
+ {
+ /* issue a message */
+ lexer.emit_error( "java_cup.runtime.Symbol \"" + non_term_id +
+ "\" has already been declared");
+ }
+ else
+ {
+ if (multipart_name.equals("")) {
+ append_multipart("Object");
+ }
+ /* build the non terminal object */
+ non_terminal this_nt =
+ new non_terminal(non_term_id, multipart_name);
+
+ /* put it in the non_terms table */
+ non_terms.put(non_term_id, this_nt);
+
+ /* build a production_part and put it in the symbols table */
+ symbols.put(non_term_id, new symbol_part(this_nt));
+ }
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+nt_id ::=
+ ID:the_id
+ {: RESULT = the_id; :}
+ | error
+ {:
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+symbol_id ::=
+ ID:the_id
+ {: RESULT = the_id; :}
+ | error
+ {:
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+label_id ::=
+ robust_id:the_id
+ {: RESULT = the_id; :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+robust_id ::= /* all ids that aren't reserved words in Java */
+ ID:the_id {: RESULT = the_id; :}
+ /* package is reserved. */
+ /* import is reserved. */
+ | CODE {: RESULT = "code"; :}
+ | ACTION {: RESULT = "action"; :}
+ | PARSER {: RESULT = "parser"; :}
+ | TERMINAL {: RESULT = "terminal"; :}
+ | NON {: RESULT = "non"; :}
+ | NONTERMINAL {: RESULT = "nonterminal"; :}
+ | INIT {: RESULT = "init"; :}
+ | SCAN {: RESULT = "scan"; :}
+ | WITH {: RESULT = "with"; :}
+ | START {: RESULT = "start"; :}
+ | PRECEDENCE {: RESULT = "precedence"; :}
+ | LEFT {: RESULT = "left"; :}
+ | RIGHT {: RESULT = "right"; :}
+ | NONASSOC {: RESULT = "nonassoc"; :}
+ | error
+ {:
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+non_terminal ::= NON TERMINAL | NONTERMINAL;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+opt_semi ::= /* nothing */
+ | SEMI;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+empty ::= /* nothing */;
+
+/*----------------------------------------------------------------*/
+
+
+
+
+
+
+
+
+
diff --git a/src/syntaxParser/java_cup/parser.java b/src/syntaxParser/java_cup/parser.java
new file mode 100644
index 0000000..163968e
--- /dev/null
+++ b/src/syntaxParser/java_cup/parser.java
@@ -0,0 +1,1849 @@
+
+//----------------------------------------------------
+// The following code was generated by CUP v0.10k
+// Sun Jul 25 13:35:26 EDT 1999
+//----------------------------------------------------
+
+package java_cup;
+
+import java_cup.runtime.*;
+import java.util.Hashtable;
+
+/** CUP v0.10k generated parser.
+ * @version Sun Jul 25 13:35:26 EDT 1999
+ */
+public class parser extends java_cup.runtime.lr_parser {
+
+ /** Default constructor. */
+ public parser() {super();}
+
+ /** Constructor which sets the default scanner. */
+ public parser(java_cup.runtime.Scanner s) {super(s);}
+
+ /** Production table. */
+ protected static final short _production_table[][] =
+ unpackFromStrings(new String[] {
+ "\000\153\000\002\002\004\000\002\055\002\000\002\003" +
+ "\012\000\002\003\007\000\002\056\002\000\002\004\006" +
+ "\000\002\004\003\000\002\005\004\000\002\005\003\000" +
+ "\002\057\002\000\002\020\006\000\002\010\003\000\002" +
+ "\010\003\000\002\010\003\000\002\010\003\000\002\007" +
+ "\002\000\002\007\004\000\002\006\006\000\002\013\006" +
+ "\000\002\022\006\000\002\023\006\000\002\014\004\000" +
+ "\002\014\003\000\002\024\005\000\002\024\004\000\002" +
+ "\024\005\000\002\024\004\000\002\060\002\000\002\024" +
+ "\006\000\002\061\002\000\002\024\006\000\002\062\002" +
+ "\000\002\044\005\000\002\063\002\000\002\045\005\000" +
+ "\002\026\005\000\002\026\003\000\002\027\005\000\002" +
+ "\027\003\000\002\040\003\000\002\040\003\000\002\043" +
+ "\004\000\002\043\003\000\002\064\002\000\002\041\007" +
+ "\000\002\065\002\000\002\041\007\000\002\066\002\000" +
+ "\002\041\007\000\002\042\005\000\002\042\003\000\002" +
+ "\052\003\000\002\053\003\000\002\067\002\000\002\015" +
+ "\007\000\002\015\003\000\002\016\004\000\002\016\003" +
+ "\000\002\070\002\000\002\071\002\000\002\030\010\000" +
+ "\002\072\002\000\002\030\005\000\002\035\005\000\002" +
+ "\035\003\000\002\036\005\000\002\036\003\000\002\031" +
+ "\004\000\002\031\003\000\002\032\004\000\002\032\003" +
+ "\000\002\051\004\000\002\051\003\000\002\017\005\000" +
+ "\002\017\003\000\002\021\005\000\002\021\003\000\002" +
+ "\025\003\000\002\025\005\000\002\033\003\000\002\034" +
+ "\003\000\002\046\003\000\002\046\003\000\002\047\003" +
+ "\000\002\047\003\000\002\050\003\000\002\054\003\000" +
+ "\002\054\003\000\002\054\003\000\002\054\003\000\002" +
+ "\054\003\000\002\054\003\000\002\054\003\000\002\054" +
+ "\003\000\002\054\003\000\002\054\003\000\002\054\003" +
+ "\000\002\054\003\000\002\054\003\000\002\054\003\000" +
+ "\002\054\003\000\002\054\003\000\002\012\004\000\002" +
+ "\012\003\000\002\011\002\000\002\011\003\000\002\037" +
+ "\002" });
+
+ /** Access to production table. */
+ public short[][] production_table() {return _production_table;}
+
+ /** Parse-action table. */
+ protected static final short[][] _action_table =
+ unpackFromStrings(new String[] {
+ "\000\247\000\026\003\006\004\000\005\000\007\000\010" +
+ "\000\011\000\012\000\013\000\014\000\035\000\001\002" +
+ "\000\004\002\251\001\002\000\024\004\200\005\uff97\007" +
+ "\uff97\010\uff97\011\uff97\012\uff97\013\uff97\014\uff97\035\uff97" +
+ "\001\002\000\010\011\007\012\012\035\014\001\002\000" +
+ "\042\003\163\006\026\007\027\010\040\011\036\012\022" +
+ "\013\042\014\030\015\017\016\015\026\033\027\023\030" +
+ "\035\031\041\035\025\036\160\001\002\000\020\003\uffeb" +
+ "\011\uffeb\012\uffeb\016\uffeb\026\uffeb\035\uffeb\036\uffeb\001" +
+ "\002\000\020\003\uff97\011\007\012\012\016\uff97\026\065" +
+ "\035\014\036\uff97\001\002\000\004\011\061\001\002\000" +
+ "\042\003\034\006\026\007\027\010\040\011\036\012\022" +
+ "\013\042\014\030\015\017\016\015\026\033\027\023\030" +
+ "\035\031\041\035\025\036\016\001\002\000\042\003\uff9a" +
+ "\006\uff9a\007\uff9a\010\uff9a\011\uff9a\012\uff9a\013\uff9a\014" +
+ "\uff9a\015\uff9a\016\uff9a\026\uff9a\027\uff9a\030\uff9a\031\uff9a" +
+ "\035\uff9a\036\uff9a\001\002\000\022\003\uffa1\017\uffa1\022" +
+ "\uffa1\025\uffa1\032\uffa1\033\uffa1\036\uffa1\037\uffa1\001\002" +
+ "\000\014\017\uffb1\020\uffb1\022\uffab\033\uffab\036\uffab\001" +
+ "\002\000\022\003\uffa2\017\uffa2\022\uffa2\025\uffa2\032\uffa2" +
+ "\033\uffa2\036\uffa2\037\uffa2\001\002\000\006\017\uffe0\020" +
+ "\055\001\002\000\010\022\051\033\uffb4\036\uffb4\001\002" +
+ "\000\022\003\uffa6\017\uffa6\022\uffa6\025\uffa6\032\uffa6\033" +
+ "\uffa6\036\uffa6\037\uffa6\001\002\000\022\003\uff9f\017\uff9f" +
+ "\022\uff9f\025\uff9f\032\uff9f\033\uff9f\036\uff9f\037\uff9f\001" +
+ "\002\000\006\033\047\036\045\001\002\000\022\003\uffa5" +
+ "\017\uffa5\022\uffa5\025\uffa5\032\uffa5\033\uffa5\036\uffa5\037" +
+ "\uffa5\001\002\000\022\003\uffaa\017\uffaa\022\uffaa\025\uffaa" +
+ "\032\uffaa\033\uffaa\036\uffaa\037\uffaa\001\002\000\022\003" +
+ "\uffa9\017\uffa9\022\uffa9\025\uffa9\032\uffa9\033\uffa9\036\uffa9" +
+ "\037\uffa9\001\002\000\022\003\uffa3\017\uffa3\022\uffa3\025" +
+ "\uffa3\032\uffa3\033\uffa3\036\uffa3\037\uffa3\001\002\000\012" +
+ "\017\uffb7\022\uffb7\033\uffb7\036\uffb7\001\002\000\020\003" +
+ "\uffe7\011\uffe7\012\uffe7\016\uffe7\026\uffe7\035\uffe7\036\uffe7" +
+ "\001\002\000\022\003\uffa0\017\uffa0\022\uffa0\025\uffa0\032" +
+ "\uffa0\033\uffa0\036\uffa0\037\uffa0\001\002\000\012\017\uffe4" +
+ "\022\uff9c\033\uff9c\036\uff9c\001\002\000\022\003\uff9e\017" +
+ "\uff9e\022\uff9e\025\uff9e\032\uff9e\033\uff9e\036\uff9e\037\uff9e" +
+ "\001\002\000\022\003\uffa7\017\uffa7\022\uffa7\025\uffa7\032" +
+ "\uffa7\033\uffa7\036\uffa7\037\uffa7\001\002\000\006\017\uffdb" +
+ "\020\uffdb\001\002\000\022\003\uffa8\017\uffa8\022\uffa8\025" +
+ "\uffa8\032\uffa8\033\uffa8\036\uffa8\037\uffa8\001\002\000\022" +
+ "\003\uff9d\017\uff9d\022\uff9d\025\uff9d\032\uff9d\033\uff9d\036" +
+ "\uff9d\037\uff9d\001\002\000\022\003\uffa4\017\uffa4\022\uffa4" +
+ "\025\uffa4\032\uffa4\033\uffa4\036\uffa4\037\uffa4\001\002\000" +
+ "\004\017\044\001\002\000\020\003\uffe3\011\uffe3\012\uffe3" +
+ "\016\uffe3\026\uffe3\035\uffe3\036\uffe3\001\002\000\006\017" +
+ "\uffb1\020\uffb1\001\002\000\020\003\uffe8\011\uffe8\012\uffe8" +
+ "\016\uffe8\026\uffe8\035\uffe8\036\uffe8\001\002\000\004\034" +
+ "\050\001\002\000\006\033\uffb3\036\uffb3\001\002\000\042" +
+ "\003\054\006\026\007\027\010\040\011\036\012\022\013" +
+ "\042\014\030\015\017\016\015\026\033\027\023\030\035" +
+ "\031\041\035\025\036\053\001\002\000\012\017\uffb8\022" +
+ "\uffb8\033\uffb8\036\uffb8\001\002\000\022\003\uffab\017\uffab" +
+ "\022\uffab\025\uffab\032\uffab\033\uffab\036\uffab\037\uffab\001" +
+ "\002\000\022\003\uff9c\017\uff9c\022\uff9c\025\uff9c\032\uff9c" +
+ "\033\uff9c\036\uff9c\037\uff9c\001\002\000\004\036\045\001" +
+ "\002\000\004\017\057\001\002\000\020\003\uffdf\011\uffdf" +
+ "\012\uffdf\016\uffdf\026\uffdf\035\uffdf\036\uffdf\001\002\000" +
+ "\006\017\uffdc\020\uffdc\001\002\000\042\003\uff9b\006\uff9b" +
+ "\007\uff9b\010\uff9b\011\uff9b\012\uff9b\013\uff9b\014\uff9b\015" +
+ "\uff9b\016\uff9b\026\uff9b\027\uff9b\030\uff9b\031\uff9b\035\uff9b" +
+ "\036\uff9b\001\002\000\010\003\uff97\016\116\036\uff97\001" +
+ "\002\000\012\003\uffda\016\uffda\026\065\036\uffda\001\002" +
+ "\000\010\003\uffd9\016\uffd9\036\uffd9\001\002\000\010\027" +
+ "\071\030\072\031\070\001\002\000\020\003\uffec\011\uffec" +
+ "\012\uffec\016\uffec\026\uffec\035\uffec\036\uffec\001\002\000" +
+ "\012\003\uffd7\016\uffd7\026\uffd7\036\uffd7\001\002\000\006" +
+ "\003\uffd2\036\uffd2\001\002\000\006\003\uffd6\036\uffd6\001" +
+ "\002\000\006\003\uffd4\036\uffd4\001\002\000\006\003\077" +
+ "\036\074\001\002\000\022\003\uffae\017\uffae\020\uffae\023" +
+ "\uffae\025\uffae\032\uffae\036\uffae\037\uffae\001\002\000\010" +
+ "\017\uffcd\020\uffcd\025\uffcd\001\002\000\006\017\uffce\020" +
+ "\uffce\001\002\000\022\003\uffad\017\uffad\020\uffad\023\uffad" +
+ "\025\uffad\032\uffad\036\uffad\037\uffad\001\002\000\006\017" +
+ "\102\020\103\001\002\000\006\017\uffcf\020\uffcf\001\002" +
+ "\000\012\003\uffd3\016\uffd3\026\uffd3\036\uffd3\001\002\000" +
+ "\006\003\077\036\074\001\002\000\006\017\uffd0\020\uffd0" +
+ "\001\002\000\006\003\077\036\074\001\002\000\006\017" +
+ "\107\020\103\001\002\000\012\003\uffd5\016\uffd5\026\uffd5" +
+ "\036\uffd5\001\002\000\006\003\077\036\074\001\002\000" +
+ "\006\017\112\020\103\001\002\000\012\003\uffd1\016\uffd1" +
+ "\026\uffd1\036\uffd1\001\002\000\012\003\uffd8\016\uffd8\026" +
+ "\uffd8\036\uffd8\001\002\000\006\003\uffca\036\uffca\001\002" +
+ "\000\006\003\126\036\120\001\002\000\004\015\117\001" +
+ "\002\000\006\003\122\036\120\001\002\000\006\017\uffb0" +
+ "\024\uffb0\001\002\000\004\017\uffcc\001\002\000\004\017" +
+ "\uffaf\001\002\000\004\017\124\001\002\000\006\003\uffcb" +
+ "\036\uffcb\001\002\000\004\024\uffc7\001\002\000\006\017" +
+ "\uffc4\024\uffaf\001\002\000\010\002\ufffe\003\126\036\120" +
+ "\001\002\000\010\002\uffc8\003\uffc8\036\uffc8\001\002\000" +
+ "\010\002\uffc9\003\uffc9\036\uffc9\001\002\000\004\017\133" +
+ "\001\002\000\010\002\uffc3\003\uffc3\036\uffc3\001\002\000" +
+ "\004\024\135\001\002\000\016\003\uffc6\017\uffc6\025\uffc6" +
+ "\032\uffc6\036\uffc6\037\uffc6\001\002\000\016\003\uff97\017" +
+ "\uff97\025\uff97\032\uff97\036\uff97\037\uff97\001\002\000\016" +
+ "\003\uffbd\017\uffbd\025\uffbd\032\uffbd\036\uffbd\037\uffbd\001" +
+ "\002\000\016\003\077\017\uffbf\025\uffbf\032\147\036\074" +
+ "\037\146\001\002\000\006\017\uffc1\025\uffc1\001\002\000" +
+ "\006\017\143\025\144\001\002\000\010\002\uffc5\003\uffc5" +
+ "\036\uffc5\001\002\000\016\003\uff97\017\uff97\025\uff97\032" +
+ "\uff97\036\uff97\037\uff97\001\002\000\006\017\uffc2\025\uffc2" +
+ "\001\002\000\016\003\uffbb\017\uffbb\025\uffbb\032\uffbb\036" +
+ "\uffbb\037\uffbb\001\002\000\006\003\077\036\074\001\002" +
+ "\000\020\003\uff97\017\uff97\023\154\025\uff97\032\uff97\036" +
+ "\uff97\037\uff97\001\002\000\016\003\uffbe\017\uffbe\025\uffbe" +
+ "\032\uffbe\036\uffbe\037\uffbe\001\002\000\016\003\uffb9\017" +
+ "\uffb9\025\uffb9\032\uffb9\036\uffb9\037\uffb9\001\002\000\016" +
+ "\003\uffbc\017\uffbc\025\uffbc\032\uffbc\036\uffbc\037\uffbc\001" +
+ "\002\000\042\003\054\006\026\007\027\010\040\011\036" +
+ "\012\022\013\042\014\030\015\017\016\015\026\033\027" +
+ "\023\030\035\031\041\035\025\036\053\001\002\000\016" +
+ "\003\uffba\017\uffba\025\uffba\032\uffba\036\uffba\037\uffba\001" +
+ "\002\000\016\003\uffac\017\uffac\025\uffac\032\uffac\036\uffac" +
+ "\037\uffac\001\002\000\006\017\uffc0\025\uffc0\001\002\000" +
+ "\014\017\uffb2\020\uffb2\022\uffab\033\uffab\036\uffab\001\002" +
+ "\000\006\033\047\036\170\001\002\000\006\017\uffdd\020" +
+ "\uffdd\001\002\000\012\017\uffe6\022\uff9c\033\uff9c\036\uff9c" +
+ "\001\002\000\020\003\uffe9\011\uffe9\012\uffe9\016\uffe9\026" +
+ "\uffe9\035\uffe9\036\uffe9\001\002\000\006\017\uffe2\020\167" +
+ "\001\002\000\004\017\172\001\002\000\004\036\170\001" +
+ "\002\000\006\017\uffb2\020\uffb2\001\002\000\006\017\uffde" +
+ "\020\uffde\001\002\000\020\003\uffe1\011\uffe1\012\uffe1\016" +
+ "\uffe1\026\uffe1\035\uffe1\036\uffe1\001\002\000\004\017\174" +
+ "\001\002\000\020\003\uffe5\011\uffe5\012\uffe5\016\uffe5\026" +
+ "\uffe5\035\uffe5\036\uffe5\001\002\000\020\003\uffea\011\uffea" +
+ "\012\uffea\016\uffea\026\uffea\035\uffea\036\uffea\001\002\000" +
+ "\022\005\ufffb\007\ufffb\010\ufffb\011\ufffb\012\ufffb\013\ufffb" +
+ "\014\ufffb\035\ufffb\001\002\000\022\005\uff97\007\uff97\010" +
+ "\uff97\011\uff97\012\uff97\013\uff97\014\uff97\035\uff97\001\002" +
+ "\000\042\003\054\006\026\007\027\010\040\011\036\012" +
+ "\022\013\042\014\030\015\017\016\015\026\033\027\023" +
+ "\030\035\031\041\035\025\036\053\001\002\000\006\017" +
+ "\ufffd\022\051\001\002\000\004\017\203\001\002\000\022" +
+ "\005\ufffc\007\ufffc\010\ufffc\011\ufffc\012\ufffc\013\ufffc\014" +
+ "\ufffc\035\ufffc\001\002\000\022\005\210\007\ufff2\010\ufff2" +
+ "\011\ufff2\012\ufff2\013\ufff2\014\ufff2\035\ufff2\001\002\000" +
+ "\022\005\ufff9\007\ufff9\010\ufff9\011\ufff9\012\ufff9\013\ufff9" +
+ "\014\ufff9\035\ufff9\001\002\000\020\007\223\010\224\011" +
+ "\007\012\012\013\227\014\225\035\014\001\002\000\022" +
+ "\005\ufffa\007\ufffa\010\ufffa\011\ufffa\012\ufffa\013\ufffa\014" +
+ "\ufffa\035\ufffa\001\002\000\042\003\054\006\026\007\027" +
+ "\010\040\011\036\012\022\013\042\014\030\015\017\016" +
+ "\015\026\033\027\023\030\035\031\041\035\025\036\053" +
+ "\001\002\000\006\017\uffb5\022\215\001\002\000\004\017" +
+ "\ufff8\001\002\000\004\017\214\001\002\000\022\005\ufff7" +
+ "\007\ufff7\010\ufff7\011\ufff7\012\ufff7\013\ufff7\014\ufff7\035" +
+ "\ufff7\001\002\000\044\003\054\006\026\007\027\010\040" +
+ "\011\036\012\022\013\042\014\030\015\017\016\015\021" +
+ "\216\026\033\027\023\030\035\031\041\035\025\036\053" +
+ "\001\002\000\004\017\uffb6\001\002\000\020\007\ufff3\010" +
+ "\ufff3\011\ufff3\012\ufff3\013\ufff3\014\ufff3\035\ufff3\001\002" +
+ "\000\020\007\ufff5\010\ufff5\011\ufff5\012\ufff5\013\ufff5\014" +
+ "\ufff5\035\ufff5\001\002\000\020\007\ufff1\010\ufff1\011\ufff1" +
+ "\012\ufff1\013\ufff1\014\ufff1\035\ufff1\001\002\000\020\007" +
+ "\ufff4\010\ufff4\011\ufff4\012\ufff4\013\ufff4\014\ufff4\035\ufff4" +
+ "\001\002\000\004\006\246\001\002\000\004\006\243\001" +
+ "\002\000\004\015\240\001\002\000\020\007\ufff6\010\ufff6" +
+ "\011\ufff6\012\ufff6\013\ufff6\014\ufff6\035\ufff6\001\002\000" +
+ "\004\015\234\001\002\000\020\003\uff97\011\007\012\012" +
+ "\016\uff97\026\065\035\014\036\uff97\001\002\000\010\003" +
+ "\uff97\016\116\036\uff97\001\002\000\006\003\126\036\120" +
+ "\001\002\000\010\002\uffff\003\126\036\120\001\002\000" +
+ "\004\037\235\001\002\000\022\007\uff99\010\uff99\011\uff99" +
+ "\012\uff99\013\uff99\014\uff99\017\236\035\uff99\001\002\000" +
+ "\020\007\uff98\010\uff98\011\uff98\012\uff98\013\uff98\014\uff98" +
+ "\035\uff98\001\002\000\020\007\uffee\010\uffee\011\uffee\012" +
+ "\uffee\013\uffee\014\uffee\035\uffee\001\002\000\004\037\241" +
+ "\001\002\000\022\007\uff99\010\uff99\011\uff99\012\uff99\013" +
+ "\uff99\014\uff99\017\236\035\uff99\001\002\000\020\007\uffed" +
+ "\010\uffed\011\uffed\012\uffed\013\uffed\014\uffed\035\uffed\001" +
+ "\002\000\004\037\244\001\002\000\022\007\uff99\010\uff99" +
+ "\011\uff99\012\uff99\013\uff99\014\uff99\017\236\035\uff99\001" +
+ "\002\000\020\007\uffef\010\uffef\011\uffef\012\uffef\013\uffef" +
+ "\014\uffef\035\uffef\001\002\000\004\037\247\001\002\000" +
+ "\022\007\uff99\010\uff99\011\uff99\012\uff99\013\uff99\014\uff99" +
+ "\017\236\035\uff99\001\002\000\020\007\ufff0\010\ufff0\011" +
+ "\ufff0\012\ufff0\013\ufff0\014\ufff0\035\ufff0\001\002\000\004" +
+ "\002\001\001\002" });
+
+ /** Access to parse-action table. */
+ public short[][] action_table() {return _action_table;}
+
+ /** <code>reduce_goto</code> table. */
+ protected static final short[][] _reduce_table =
+ unpackFromStrings(new String[] {
+ "\000\247\000\006\003\003\055\004\001\001\000\002\001" +
+ "\001\000\006\004\176\037\175\001\001\000\010\012\012" +
+ "\014\010\024\007\001\001\000\016\017\020\025\160\026" +
+ "\164\033\161\044\163\054\030\001\001\000\002\001\001" +
+ "\000\016\012\012\024\065\037\063\040\061\041\066\043" +
+ "\062\001\001\000\002\001\001\000\016\017\020\025\023" +
+ "\027\017\034\036\045\031\054\030\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\004\063\055\001\001\000\002\001\001\000\002\001" +
+ "\001\000\002\001\001\000\010\027\017\034\036\045\045" +
+ "\001\001\000\002\001\001\000\002\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\002\001\001\000\004\061\042\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\002\001\001\000\002\001\001\000\002\001\001\000" +
+ "\002\001\001\000\002\001\001\000\002\001\001\000\002" +
+ "\001\001\000\002\001\001\000\004\054\051\001\001\000" +
+ "\002\001\001\000\002\001\001\000\002\001\001\000\004" +
+ "\034\057\001\001\000\002\001\001\000\002\001\001\000" +
+ "\002\001\001\000\002\001\001\000\006\015\114\037\113" +
+ "\001\001\000\004\041\112\001\001\000\002\001\001\000" +
+ "\002\001\001\000\002\001\001\000\002\001\001\000\004" +
+ "\066\107\001\001\000\004\064\104\001\001\000\004\065" +
+ "\072\001\001\000\012\042\077\047\074\052\100\053\075" +
+ "\001\001\000\002\001\001\000\002\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\002\001\001\000\010\047\074\052\103\053\075\001" +
+ "\001\000\002\001\001\000\012\042\105\047\074\052\100" +
+ "\053\075\001\001\000\002\001\001\000\002\001\001\000" +
+ "\012\042\110\047\074\052\100\053\075\001\001\000\002" +
+ "\001\001\000\002\001\001\000\002\001\001\000\002\001" +
+ "\001\000\010\016\126\030\127\046\124\001\001\000\002" +
+ "\001\001\000\004\046\120\001\001\000\002\001\001\000" +
+ "\004\067\122\001\001\000\002\001\001\000\002\001\001" +
+ "\000\002\001\001\000\004\070\133\001\001\000\004\072" +
+ "\131\001\001\000\006\030\130\046\124\001\001\000\002" +
+ "\001\001\000\002\001\001\000\002\001\001\000\002\001" +
+ "\001\000\002\001\001\000\004\071\135\001\001\000\012" +
+ "\031\137\035\141\036\140\037\136\001\001\000\002\001" +
+ "\001\000\006\032\150\047\147\001\001\000\002\001\001" +
+ "\000\002\001\001\000\002\001\001\000\010\031\137\036" +
+ "\144\037\136\001\001\000\002\001\001\000\002\001\001" +
+ "\000\006\047\074\053\156\001\001\000\006\037\151\051" +
+ "\152\001\001\000\002\001\001\000\002\001\001\000\002" +
+ "\001\001\000\006\050\154\054\155\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\010\026\164\033\161\044\174\001\001\000\002\001" +
+ "\001\000\004\060\172\001\001\000\002\001\001\000\004" +
+ "\062\165\001\001\000\002\001\001\000\004\033\170\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\002\001\001\000\002\001\001\000\002\001\001\000" +
+ "\002\001\001\000\006\005\203\037\204\001\001\000\006" +
+ "\017\200\054\030\001\001\000\004\056\201\001\001\000" +
+ "\002\001\001\000\002\001\001\000\006\007\205\020\206" +
+ "\001\001\000\002\001\001\000\022\006\225\010\220\012" +
+ "\012\013\217\014\227\022\221\023\216\024\007\001\001" +
+ "\000\002\001\001\000\010\017\210\021\211\054\030\001" +
+ "\001\000\002\001\001\000\004\057\212\001\001\000\002" +
+ "\001\001\000\002\001\001\000\004\054\051\001\001\000" +
+ "\002\001\001\000\002\001\001\000\002\001\001\000\002" +
+ "\001\001\000\002\001\001\000\002\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\016\012\012\024\065\037\063\040\230\041\066\043" +
+ "\062\001\001\000\006\015\231\037\113\001\001\000\010" +
+ "\016\232\030\127\046\124\001\001\000\006\030\130\046" +
+ "\124\001\001\000\002\001\001\000\004\011\236\001\001" +
+ "\000\002\001\001\000\002\001\001\000\002\001\001\000" +
+ "\004\011\241\001\001\000\002\001\001\000\002\001\001" +
+ "\000\004\011\244\001\001\000\002\001\001\000\002\001" +
+ "\001\000\004\011\247\001\001\000\002\001\001\000\002" +
+ "\001\001" });
+
+ /** Access to <code>reduce_goto</code> table. */
+ public short[][] reduce_table() {return _reduce_table;}
+
+ /** Instance of action encapsulation class. */
+ protected CUP$parser$actions action_obj;
+
+ /** Action encapsulation object initializer. */
+ protected void init_actions()
+ {
+ action_obj = new CUP$parser$actions(this);
+ }
+
+ /** Invoke a user supplied parse action. */
+ public java_cup.runtime.Symbol do_action(
+ int act_num,
+ java_cup.runtime.lr_parser parser,
+ java.util.Stack stack,
+ int top)
+ throws java.lang.Exception
+ {
+ /* call code in generated class */
+ return action_obj.CUP$parser$do_action(act_num, parser, stack, top);
+ }
+
+ /** Indicates start state. */
+ public int start_state() {return 0;}
+ /** Indicates start production. */
+ public int start_production() {return 0;}
+
+ /** <code>EOF</code> Symbol index. */
+ public int EOF_sym() {return 0;}
+
+ /** <code>error</code> Symbol index. */
+ public int error_sym() {return 1;}
+
+
+ /** User initialization code. */
+ public void user_init() throws java.lang.Exception
+ {
+ lexer.init();
+ }
+
+ /** Scan to get the next Symbol. */
+ public java_cup.runtime.Symbol scan()
+ throws java.lang.Exception
+ {
+ return lexer.next_token();
+ }
+
+
+
+ /* override error routines */
+
+ public void report_fatal_error(
+ String message,
+ Object info)
+ {
+ done_parsing();
+ lexer.emit_error(message);
+ System.err.println("Can't recover from previous error(s), giving up.");
+ System.exit(1);
+ }
+
+ public void report_error(String message, Object info)
+ {
+ lexer.emit_error(message);
+ }
+
+}
+
+/** Cup generated class to encapsulate user supplied action code.*/
+class CUP$parser$actions {
+
+
+ /** helper routine to clone a new production part adding a given label */
+ protected production_part add_lab(production_part part, String lab)
+ throws internal_error
+ {
+ /* if there is no label, or this is an action, just return the original */
+ if (lab == null || part.is_action()) return part;
+
+ /* otherwise build a new one with the given label attached */
+ return new symbol_part(((symbol_part)part).the_symbol(),lab);
+ }
+
+ /** max size of right hand side we will support */
+ protected final int MAX_RHS = 200;
+
+ /** array for accumulating right hand side parts */
+ protected production_part[] rhs_parts = new production_part[MAX_RHS];
+
+ /** where we are currently in building a right hand side */
+ protected int rhs_pos = 0;
+
+ /** start a new right hand side */
+ protected void new_rhs() {rhs_pos = 0; }
+
+ /** add a new right hand side part */
+ protected void add_rhs_part(production_part part) throws java.lang.Exception
+ {
+ if (rhs_pos >= MAX_RHS)
+ throw new Exception("Internal Error: Productions limited to " +
+ MAX_RHS + " symbols and actions");
+
+ rhs_parts[rhs_pos] = part;
+ rhs_pos++;
+ }
+
+ /** string to build up multiple part names */
+ protected String multipart_name = new String();
+
+ /** append a new name segment to the accumulated multipart name */
+ protected void append_multipart(String name)
+ {
+ String dot = "";
+
+ /* if we aren't just starting out, put on a dot */
+ if (multipart_name.length() != 0) dot = ".";
+
+ multipart_name = multipart_name.concat(dot + name);
+ }
+
+ /** table of declared symbols -- contains production parts indexed by name */
+ protected Hashtable symbols = new Hashtable();
+
+ /** table of just non terminals -- contains non_terminals indexed by name */
+ protected Hashtable non_terms = new Hashtable();
+
+ /** declared start non_terminal */
+ protected non_terminal start_nt = null;
+
+ /** left hand side non terminal of the current production */
+ protected non_terminal lhs_nt;
+
+ /** Current precedence number */
+ int _cur_prec = 0;
+
+ /** Current precedence side */
+ int _cur_side = assoc.no_prec;
+
+ /** update the precedences we are declaring */
+ protected void update_precedence(int p) {
+ _cur_side = p;
+ _cur_prec++;
+ }
+ /** add relevant data to terminals */
+ protected void add_precedence(String term) {
+ if (term == null) {
+ System.err.println("Unable to add precedence to nonexistent terminal");
+ } else {
+ symbol_part sp = (symbol_part)symbols.get(term);
+ if (sp == null) {
+ System.err.println("Could find terminal " + term + " while declaring precedence");
+ } else {
+ java_cup.symbol sym = sp.the_symbol();
+ if (sym instanceof terminal)
+ ((terminal)sym).set_precedence(_cur_side, _cur_prec);
+ else System.err.println("Precedence declaration: Can't find terminal " + term);
+ }
+ }
+ }
+
+ private final parser parser;
+
+ /** Constructor */
+ CUP$parser$actions(parser parser) {
+ this.parser = parser;
+ }
+
+ /** Method with the actual generated action code. */
+ public final java_cup.runtime.Symbol CUP$parser$do_action(
+ int CUP$parser$act_num,
+ java_cup.runtime.lr_parser CUP$parser$parser,
+ java.util.Stack CUP$parser$stack,
+ int CUP$parser$top)
+ throws java.lang.Exception
+ {
+ /* Symbol object for return from actions */
+ java_cup.runtime.Symbol CUP$parser$result;
+
+ /* select the action based on the action number */
+ switch (CUP$parser$act_num)
+ {
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 106: // empty ::=
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(29/*empty*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 105: // opt_semi ::= SEMI
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(7/*opt_semi*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 104: // opt_semi ::=
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(7/*opt_semi*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 103: // non_terminal ::= NONTERMINAL
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(8/*non_terminal*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 102: // non_terminal ::= NON TERMINAL
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(8/*non_terminal*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 101: // robust_id ::= error
+ {
+ String RESULT = null;
+
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 100: // robust_id ::= NONASSOC
+ {
+ String RESULT = null;
+ RESULT = "nonassoc";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 99: // robust_id ::= RIGHT
+ {
+ String RESULT = null;
+ RESULT = "right";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 98: // robust_id ::= LEFT
+ {
+ String RESULT = null;
+ RESULT = "left";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 97: // robust_id ::= PRECEDENCE
+ {
+ String RESULT = null;
+ RESULT = "precedence";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 96: // robust_id ::= START
+ {
+ String RESULT = null;
+ RESULT = "start";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 95: // robust_id ::= WITH
+ {
+ String RESULT = null;
+ RESULT = "with";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 94: // robust_id ::= SCAN
+ {
+ String RESULT = null;
+ RESULT = "scan";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 93: // robust_id ::= INIT
+ {
+ String RESULT = null;
+ RESULT = "init";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 92: // robust_id ::= NONTERMINAL
+ {
+ String RESULT = null;
+ RESULT = "nonterminal";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 91: // robust_id ::= NON
+ {
+ String RESULT = null;
+ RESULT = "non";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 90: // robust_id ::= TERMINAL
+ {
+ String RESULT = null;
+ RESULT = "terminal";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 89: // robust_id ::= PARSER
+ {
+ String RESULT = null;
+ RESULT = "parser";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 88: // robust_id ::= ACTION
+ {
+ String RESULT = null;
+ RESULT = "action";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 87: // robust_id ::= CODE
+ {
+ String RESULT = null;
+ RESULT = "code";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 86: // robust_id ::= ID
+ {
+ String RESULT = null;
+ int the_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int the_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String the_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = the_id;
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 85: // label_id ::= robust_id
+ {
+ String RESULT = null;
+ int the_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int the_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String the_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = the_id;
+ CUP$parser$result = new java_cup.runtime.Symbol(38/*label_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 84: // symbol_id ::= error
+ {
+ String RESULT = null;
+
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+
+ CUP$parser$result = new java_cup.runtime.Symbol(37/*symbol_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 83: // symbol_id ::= ID
+ {
+ String RESULT = null;
+ int the_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int the_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String the_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = the_id;
+ CUP$parser$result = new java_cup.runtime.Symbol(37/*symbol_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 82: // nt_id ::= error
+ {
+ String RESULT = null;
+
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+
+ CUP$parser$result = new java_cup.runtime.Symbol(36/*nt_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 81: // nt_id ::= ID
+ {
+ String RESULT = null;
+ int the_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int the_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String the_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = the_id;
+ CUP$parser$result = new java_cup.runtime.Symbol(36/*nt_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 80: // new_non_term_id ::= ID
+ {
+ Object RESULT = null;
+ int non_term_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int non_term_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String non_term_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* see if this non terminal has been declared before */
+ if (symbols.get(non_term_id) != null)
+ {
+ /* issue a message */
+ lexer.emit_error( "java_cup.runtime.Symbol \"" + non_term_id +
+ "\" has already been declared");
+ }
+ else
+ {
+ if (multipart_name.equals("")) {
+ append_multipart("Object");
+ }
+ /* build the non terminal object */
+ non_terminal this_nt =
+ new non_terminal(non_term_id, multipart_name);
+
+ /* put it in the non_terms table */
+ non_terms.put(non_term_id, this_nt);
+
+ /* build a production_part and put it in the symbols table */
+ symbols.put(non_term_id, new symbol_part(this_nt));
+ }
+
+ CUP$parser$result = new java_cup.runtime.Symbol(26/*new_non_term_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 79: // new_term_id ::= ID
+ {
+ Object RESULT = null;
+ int term_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int term_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String term_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* see if this terminal has been declared before */
+ if (symbols.get(term_id) != null)
+ {
+ /* issue a message */
+ lexer.emit_error("java_cup.runtime.Symbol \"" + term_id +
+ "\" has already been declared");
+ }
+ else
+ {
+ /* if no type declared, declare one */
+ if (multipart_name.equals("")) {
+ append_multipart("Object");
+ }
+ /* build a production_part and put it in the table */
+ symbols.put(term_id,
+ new symbol_part(new terminal(term_id, multipart_name)));
+ }
+
+ CUP$parser$result = new java_cup.runtime.Symbol(25/*new_term_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 78: // type_id ::= type_id LBRACK RBRACK
+ {
+ Object RESULT = null;
+ multipart_name = multipart_name.concat("[]");
+ CUP$parser$result = new java_cup.runtime.Symbol(19/*type_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 77: // type_id ::= multipart_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(19/*type_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 76: // import_id ::= multipart_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(15/*import_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 75: // import_id ::= multipart_id DOT STAR
+ {
+ Object RESULT = null;
+ append_multipart("*");
+ CUP$parser$result = new java_cup.runtime.Symbol(15/*import_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 74: // multipart_id ::= robust_id
+ {
+ Object RESULT = null;
+ int an_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int an_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String an_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ append_multipart(an_id);
+ CUP$parser$result = new java_cup.runtime.Symbol(13/*multipart_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 73: // multipart_id ::= multipart_id DOT robust_id
+ {
+ Object RESULT = null;
+ int another_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int another_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String another_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ append_multipart(another_id);
+ CUP$parser$result = new java_cup.runtime.Symbol(13/*multipart_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 72: // opt_label ::= empty
+ {
+ String RESULT = null;
+ RESULT = null;
+ CUP$parser$result = new java_cup.runtime.Symbol(39/*opt_label*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 71: // opt_label ::= COLON label_id
+ {
+ String RESULT = null;
+ int labidleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int labidright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String labid = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = labid;
+ CUP$parser$result = new java_cup.runtime.Symbol(39/*opt_label*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 70: // prod_part ::= CODE_STRING
+ {
+ Object RESULT = null;
+ int code_strleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int code_strright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String code_str = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* add a new production part */
+ add_rhs_part(new action_part(code_str));
+
+ CUP$parser$result = new java_cup.runtime.Symbol(24/*prod_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 69: // prod_part ::= symbol_id opt_label
+ {
+ Object RESULT = null;
+ int symidleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int symidright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ String symid = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+ int labidleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int labidright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String labid = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* try to look up the id */
+ production_part symb = (production_part)symbols.get(symid);
+
+ /* if that fails, symbol is undeclared */
+ if (symb == null)
+ {
+ if (lexer.error_count == 0)
+ lexer.emit_error("java_cup.runtime.Symbol \"" + symid +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* add a labeled production part */
+ add_rhs_part(add_lab(symb, labid));
+ }
+
+ CUP$parser$result = new java_cup.runtime.Symbol(24/*prod_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 68: // prod_part_list ::= empty
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(23/*prod_part_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 67: // prod_part_list ::= prod_part_list prod_part
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(23/*prod_part_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 66: // rhs ::= prod_part_list
+ {
+ Object RESULT = null;
+
+ if (lhs_nt != null)
+ {
+ /* build the production */
+ production p = new production(lhs_nt, rhs_parts, rhs_pos);
+
+ /* if we have no start non-terminal declared and this is
+ the first production, make its lhs nt the start_nt
+ and build a special start production for it. */
+ if (start_nt == null)
+ {
+ start_nt = lhs_nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt),"start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+
+ new_rhs();
+ }
+ }
+
+ /* reset the rhs accumulation in any case */
+ new_rhs();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(28/*rhs*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 65: // rhs ::= prod_part_list PERCENT_PREC term_id
+ {
+ Object RESULT = null;
+ int term_nameleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int term_nameright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String term_name = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ java_cup.symbol sym = null;
+ if (lhs_nt != null)
+ {
+ /* Find the precedence symbol */
+ if (term_name == null) {
+ System.err.println("No terminal for contextual precedence");
+ sym = null;
+ } else {
+ sym = ((symbol_part)symbols.get(term_name)).the_symbol();
+ }
+ /* build the production */
+ production p;
+ if ((sym!=null) && (sym instanceof terminal)) {
+ p = new production(lhs_nt, rhs_parts, rhs_pos,
+ ((terminal)sym).precedence_num(),
+ ((terminal)sym).precedence_side());
+ ((symbol_part)symbols.get(term_name)).the_symbol().note_use();
+ } else {
+ System.err.println("Invalid terminal " + term_name +
+ " for contextual precedence assignment");
+ p = new production(lhs_nt, rhs_parts, rhs_pos);
+ }
+
+ /* if we have no start non-terminal declared and this is
+ the first production, make its lhs nt the start_nt
+ and build a special start production for it. */
+ if (start_nt == null)
+ {
+ start_nt = lhs_nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt),"start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ if ((sym!=null) && (sym instanceof terminal)) {
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts,
+ rhs_pos, ((terminal)sym).precedence_num(),
+ ((terminal)sym).precedence_side());
+ } else {
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+ }
+ new_rhs();
+ }
+ }
+
+ /* reset the rhs accumulation in any case */
+ new_rhs();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(28/*rhs*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 64: // rhs_list ::= rhs
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(27/*rhs_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 63: // rhs_list ::= rhs_list BAR rhs
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(27/*rhs_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 62: // production ::= error NT$13 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$13
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(22/*production*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 61: // NT$13 ::=
+ {
+ Object RESULT = null;
+ lexer.emit_error("Syntax Error");
+ CUP$parser$result = new java_cup.runtime.Symbol(56/*NT$13*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 60: // production ::= nt_id NT$11 COLON_COLON_EQUALS NT$12 rhs_list SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$11
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-4)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-4)).value;
+ // propagate RESULT from NT$12
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+ int lhs_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-5)).left;
+ int lhs_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-5)).right;
+ String lhs_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-5)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(22/*production*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-5)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 59: // NT$12 ::=
+ {
+ Object RESULT = null;
+ int lhs_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left;
+ int lhs_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right;
+ String lhs_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(55/*NT$12*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 58: // NT$11 ::=
+ {
+ Object RESULT = null;
+ int lhs_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int lhs_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String lhs_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* lookup the lhs nt */
+ lhs_nt = (non_terminal)non_terms.get(lhs_id);
+
+ /* if it wasn't declared, emit a message */
+ if (lhs_nt == null)
+ {
+ if (lexer.error_count == 0)
+ lexer.emit_error("LHS non terminal \"" + lhs_id +
+ "\" has not been declared");
+ }
+
+ /* reset the rhs accumulation */
+ new_rhs();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(54/*NT$11*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 57: // production_list ::= production
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(12/*production_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 56: // production_list ::= production_list production
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(12/*production_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 55: // start_spec ::= empty
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(11/*start_spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 54: // start_spec ::= START WITH nt_id NT$10 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$10
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+ int start_nameleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left;
+ int start_nameright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right;
+ String start_name = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(11/*start_spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-4)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 53: // NT$10 ::=
+ {
+ Object RESULT = null;
+ int start_nameleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int start_nameright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String start_name = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* verify that the name has been declared as a non terminal */
+ non_terminal nt = (non_terminal)non_terms.get(start_name);
+ if (nt == null)
+ {
+ lexer.emit_error( "Start non terminal \"" + start_name +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* remember the non-terminal for later */
+ start_nt = nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt), "start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+ new_rhs();
+ }
+
+ CUP$parser$result = new java_cup.runtime.Symbol(53/*NT$10*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 52: // term_id ::= symbol_id
+ {
+ String RESULT = null;
+ int symleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int symright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String sym = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* check that the symbol_id is a terminal */
+ if (symbols.get(sym) == null)
+ {
+ /* issue a message */
+ lexer.emit_error("Terminal \"" + sym +
+ "\" has not been declared");
+ }
+ RESULT = sym;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(41/*term_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 51: // terminal_id ::= term_id
+ {
+ String RESULT = null;
+ int symleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int symright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String sym = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ add_precedence(sym);
+ RESULT = sym;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(40/*terminal_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 50: // terminal_list ::= terminal_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(32/*terminal_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 49: // terminal_list ::= terminal_list COMMA terminal_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(32/*terminal_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 48: // preced ::= PRECEDENCE NONASSOC NT$9 terminal_list SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$9
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(31/*preced*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-4)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 47: // NT$9 ::=
+ {
+ Object RESULT = null;
+
+ update_precedence(assoc.nonassoc);
+
+ CUP$parser$result = new java_cup.runtime.Symbol(52/*NT$9*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 46: // preced ::= PRECEDENCE RIGHT NT$8 terminal_list SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$8
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(31/*preced*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-4)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 45: // NT$8 ::=
+ {
+ Object RESULT = null;
+
+ update_precedence(assoc.right);
+
+ CUP$parser$result = new java_cup.runtime.Symbol(51/*NT$8*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 44: // preced ::= PRECEDENCE LEFT NT$7 terminal_list SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$7
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(31/*preced*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-4)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 43: // NT$7 ::=
+ {
+ Object RESULT = null;
+
+ update_precedence(assoc.left);
+
+ CUP$parser$result = new java_cup.runtime.Symbol(50/*NT$7*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 42: // precedence_l ::= preced
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(33/*precedence_l*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 41: // precedence_l ::= precedence_l preced
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(33/*precedence_l*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 40: // precedence_list ::= empty
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(30/*precedence_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 39: // precedence_list ::= precedence_l
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(30/*precedence_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 38: // non_term_name_list ::= new_non_term_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(21/*non_term_name_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 37: // non_term_name_list ::= non_term_name_list COMMA new_non_term_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(21/*non_term_name_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 36: // term_name_list ::= new_term_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(20/*term_name_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 35: // term_name_list ::= term_name_list COMMA new_term_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(20/*term_name_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 34: // declares_non_term ::= non_term_name_list NT$6 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$6
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(35/*declares_non_term*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 33: // NT$6 ::=
+ {
+ Object RESULT = null;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(49/*NT$6*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 32: // declares_term ::= term_name_list NT$5 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$5
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(34/*declares_term*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 31: // NT$5 ::=
+ {
+ Object RESULT = null;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(48/*NT$5*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 30: // symbol ::= non_terminal error NT$4 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$4
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 29: // NT$4 ::=
+ {
+ Object RESULT = null;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(47/*NT$4*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 28: // symbol ::= TERMINAL error NT$3 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$3
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 27: // NT$3 ::=
+ {
+ Object RESULT = null;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(46/*NT$3*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 26: // symbol ::= non_terminal declares_non_term
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 25: // symbol ::= non_terminal type_id declares_non_term
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 24: // symbol ::= TERMINAL declares_term
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 23: // symbol ::= TERMINAL type_id declares_term
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 22: // symbol_list ::= symbol
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(10/*symbol_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 21: // symbol_list ::= symbol_list symbol
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(10/*symbol_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 20: // scan_code ::= SCAN WITH CODE_STRING opt_semi
+ {
+ Object RESULT = null;
+ int user_codeleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int user_coderight = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ String user_code = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ if (emit.scan_code!=null)
+ lexer.emit_error("Redundant scan code (skipping)");
+ else /* save the user code */
+ emit.scan_code = user_code;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(17/*scan_code*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 19: // init_code ::= INIT WITH CODE_STRING opt_semi
+ {
+ Object RESULT = null;
+ int user_codeleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int user_coderight = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ String user_code = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ if (emit.init_code!=null)
+ lexer.emit_error("Redundant init code (skipping)");
+ else /* save the user code */
+ emit.init_code = user_code;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(16/*init_code*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 18: // parser_code_part ::= PARSER CODE CODE_STRING opt_semi
+ {
+ Object RESULT = null;
+ int user_codeleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int user_coderight = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ String user_code = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ if (emit.parser_code!=null)
+ lexer.emit_error("Redundant parser code (skipping)");
+ else /* save the user included code string */
+ emit.parser_code = user_code;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(9/*parser_code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 17: // action_code_part ::= ACTION CODE CODE_STRING opt_semi
+ {
+ Object RESULT = null;
+ int user_codeleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int user_coderight = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ String user_code = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ if (emit.action_code!=null)
+ lexer.emit_error("Redundant action code (skipping)");
+ else /* save the user included code string */
+ emit.action_code = user_code;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(4/*action_code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 16: // code_parts ::= code_parts code_part
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(5/*code_parts*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 15: // code_parts ::=
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(5/*code_parts*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 14: // code_part ::= scan_code
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(6/*code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 13: // code_part ::= init_code
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(6/*code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 12: // code_part ::= parser_code_part
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(6/*code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 11: // code_part ::= action_code_part
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(6/*code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 10: // import_spec ::= IMPORT import_id NT$2 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$2
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(14/*import_spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 9: // NT$2 ::=
+ {
+ Object RESULT = null;
+
+ /* save this import on the imports list */
+ emit.import_list.push(multipart_name);
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(45/*NT$2*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 8: // import_list ::= empty
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*import_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 7: // import_list ::= import_list import_spec
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*import_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 6: // package_spec ::= empty
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(2/*package_spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 5: // package_spec ::= PACKAGE multipart_id NT$1 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$1
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(2/*package_spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 4: // NT$1 ::=
+ {
+ Object RESULT = null;
+
+ /* save the package name */
+ emit.package_name = multipart_name;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(44/*NT$1*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 3: // spec ::= error symbol_list precedence_list start_spec production_list
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(1/*spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-4)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 2: // spec ::= NT$0 package_spec import_list code_parts symbol_list precedence_list start_spec production_list
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$0
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-7)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-7)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(1/*spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-7)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 1: // NT$0 ::=
+ {
+ Object RESULT = null;
+
+ /* declare "error" as a terminal */
+ symbols.put("error", new symbol_part(terminal.error));
+
+ /* declare start non terminal */
+ non_terms.put("$START", non_terminal.START_nt);
+
+ CUP$parser$result = new java_cup.runtime.Symbol(43/*NT$0*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 0: // $START ::= spec EOF
+ {
+ Object RESULT = null;
+ int start_valleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int start_valright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ Object start_val = (Object)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+ RESULT = start_val;
+ CUP$parser$result = new java_cup.runtime.Symbol(0/*$START*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ /* ACCEPT */
+ CUP$parser$parser.done_parsing();
+ return CUP$parser$result;
+
+ /* . . . . . .*/
+ default:
+ throw new Exception(
+ "Invalid action number found in internal parse table");
+
+ }
+ }
+}
+
diff --git a/src/syntaxParser/java_cup/production.class b/src/syntaxParser/java_cup/production.class
new file mode 100644
index 0000000..eb46236
--- /dev/null
+++ b/src/syntaxParser/java_cup/production.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/production.java b/src/syntaxParser/java_cup/production.java
new file mode 100644
index 0000000..5a41287
--- /dev/null
+++ b/src/syntaxParser/java_cup/production.java
@@ -0,0 +1,756 @@
+
+package java_cup;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/** This class represents a production in the grammar. It contains
+ * a LHS non terminal, and an array of RHS symbols. As various
+ * transformations are done on the RHS of the production, it may shrink.
+ * As a result a separate length is always maintained to indicate how much
+ * of the RHS array is still valid.<p>
+ *
+ * I addition to construction and manipulation operations, productions provide
+ * methods for factoring out actions (see remove_embedded_actions()), for
+ * computing the nullability of the production (i.e., can it derive the empty
+ * string, see check_nullable()), and operations for computing its first
+ * set (i.e., the set of terminals that could appear at the beginning of some
+ * string derived from the production, see check_first_set()).
+ *
+ * @see java_cup.production_part
+ * @see java_cup.symbol_part
+ * @see java_cup.action_part
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+
+public class production {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor. This constructor accepts a LHS non terminal,
+ * an array of RHS parts (including terminals, non terminals, and
+ * actions), and a string for a final reduce action. It does several
+ * manipulations in the process of creating a production object.
+ * After some validity checking it translates labels that appear in
+ * actions into code for accessing objects on the runtime parse stack.
+ * It them merges adjacent actions if they appear and moves any trailing
+ * action into the final reduce actions string. Next it removes any
+ * embedded actions by factoring them out with new action productions.
+ * Finally it assigns a unique index to the production.<p>
+ *
+ * Factoring out of actions is accomplished by creating new "hidden"
+ * non terminals. For example if the production was originally: <pre>
+ * A ::= B {action} C D
+ * </pre>
+ * then it is factored into two productions:<pre>
+ * A ::= B X C D
+ * X ::= {action}
+ * </pre>
+ * (where X is a unique new non terminal). This has the effect of placing
+ * all actions at the end where they can be handled as part of a reduce by
+ * the parser.
+ */
+ public production(
+ non_terminal lhs_sym,
+ production_part rhs_parts[],
+ int rhs_l,
+ String action_str)
+ throws internal_error
+ {
+ int i;
+ action_part tail_action;
+ String declare_str;
+ int rightlen = rhs_l;
+
+ /* remember the length */
+ if (rhs_l >= 0)
+ _rhs_length = rhs_l;
+ else if (rhs_parts != null)
+ _rhs_length = rhs_parts.length;
+ else
+ _rhs_length = 0;
+
+ /* make sure we have a valid left-hand-side */
+ if (lhs_sym == null)
+ throw new internal_error(
+ "Attempt to construct a production with a null LHS");
+
+ /* I'm not translating labels anymore, I'm adding code to declare
+ labels as valid variables. This way, the users code string is
+ untouched
+ 6/96 frankf */
+
+ /* check if the last part of the right hand side is an action. If
+ it is, it won't be on the stack, so we don't want to count it
+ in the rightlen. Then when we search down the stack for a
+ Symbol, we don't try to search past action */
+
+ if (rhs_l > 0) {
+ if (rhs_parts[rhs_l - 1].is_action()) {
+ rightlen = rhs_l - 1;
+ } else {
+ rightlen = rhs_l;
+ }
+ }
+
+ /* get the generated declaration code for the necessary labels. */
+ declare_str = declare_labels(
+ rhs_parts, rightlen, action_str);
+
+ if (action_str == null)
+ action_str = declare_str;
+ else
+ action_str = declare_str + action_str;
+
+ /* count use of lhs */
+ lhs_sym.note_use();
+
+ /* create the part for left-hand-side */
+ _lhs = new symbol_part(lhs_sym);
+
+ /* merge adjacent actions (if any) */
+ _rhs_length = merge_adjacent_actions(rhs_parts, _rhs_length);
+
+ /* strip off any trailing action */
+ tail_action = strip_trailing_action(rhs_parts, _rhs_length);
+ if (tail_action != null) _rhs_length--;
+
+ /* Why does this run through the right hand side happen
+ over and over? here a quick combination of two
+ prior runs plus one I wanted of my own
+ frankf 6/25/96 */
+ /* allocate and copy over the right-hand-side */
+ /* count use of each rhs symbol */
+ _rhs = new production_part[_rhs_length];
+ for (i=0; i<_rhs_length; i++) {
+ _rhs[i] = rhs_parts[i];
+ if (!_rhs[i].is_action()) {
+ ((symbol_part)_rhs[i]).the_symbol().note_use();
+ if (((symbol_part)_rhs[i]).the_symbol() instanceof terminal) {
+ _rhs_prec =
+ ((terminal)((symbol_part)_rhs[i]).the_symbol()).precedence_num();
+ _rhs_assoc =
+ ((terminal)((symbol_part)_rhs[i]).the_symbol()).precedence_side();
+ }
+ }
+ }
+
+ /*now action string is really declaration string, so put it in front!
+ 6/14/96 frankf */
+ if (action_str == null) action_str = "";
+ if (tail_action != null && tail_action.code_string() != null)
+ action_str = action_str + "\t\t" + tail_action.code_string();
+
+ /* stash the action */
+ _action = new action_part(action_str);
+
+ /* rewrite production to remove any embedded actions */
+ remove_embedded_actions();
+
+ /* assign an index */
+ _index = next_index++;
+
+ /* put us in the global collection of productions */
+ _all.put(new Integer(_index),this);
+
+ /* put us in the production list of the lhs non terminal */
+ lhs_sym.add_production(this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with no action string. */
+ public production(
+ non_terminal lhs_sym,
+ production_part rhs_parts[],
+ int rhs_l)
+ throws internal_error
+ {
+ this(lhs_sym,rhs_parts,rhs_l,null);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /* Constructor with precedence and associativity of production
+ contextually define */
+ public production(
+ non_terminal lhs_sym,
+ production_part rhs_parts[],
+ int rhs_l,
+ String action_str,
+ int prec_num,
+ int prec_side)
+ throws internal_error
+ {
+ this(lhs_sym,rhs_parts,rhs_l,action_str);
+
+ /* set the precedence */
+ set_precedence_num(prec_num);
+ set_precedence_side(prec_side);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /* Constructor w/ no action string and contextual precedence
+ defined */
+ public production(
+ non_terminal lhs_sym,
+ production_part rhs_parts[],
+ int rhs_l,
+ int prec_num,
+ int prec_side)
+ throws internal_error
+ {
+ this(lhs_sym,rhs_parts,rhs_l,null);
+ /* set the precedence */
+ set_precedence_num(prec_num);
+ set_precedence_side(prec_side);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+
+ /** Table of all productions. Elements are stored using their index as
+ * the key.
+ */
+ protected static Hashtable _all = new Hashtable();
+
+ /** Access to all productions. */
+ public static Enumeration all() {return _all.elements();}
+
+ /** Lookup a production by index. */
+ public static production find(int indx) {
+ return (production) _all.get(new Integer(indx));
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Total number of productions. */
+ public static int number() {return _all.size();}
+
+ /** Static counter for assigning unique index numbers. */
+ protected static int next_index;
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The left hand side non-terminal. */
+ protected symbol_part _lhs;
+
+ /** The left hand side non-terminal. */
+ public symbol_part lhs() {return _lhs;}
+
+
+ /** The precedence of the rule */
+ protected int _rhs_prec = -1;
+ protected int _rhs_assoc = -1;
+
+ /** Access to the precedence of the rule */
+ public int precedence_num() { return _rhs_prec; }
+ public int precedence_side() { return _rhs_assoc; }
+
+ /** Setting the precedence of a rule */
+ public void set_precedence_num(int prec_num) {
+ _rhs_prec = prec_num;
+ }
+ public void set_precedence_side(int prec_side) {
+ _rhs_assoc = prec_side;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** A collection of parts for the right hand side. */
+ protected production_part _rhs[];
+
+ /** Access to the collection of parts for the right hand side. */
+ public production_part rhs(int indx) throws internal_error
+ {
+ if (indx >= 0 && indx < _rhs_length)
+ return _rhs[indx];
+ else
+ throw new internal_error(
+ "Index out of range for right hand side of production");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** How much of the right hand side array we are presently using. */
+ protected int _rhs_length;
+
+ /** How much of the right hand side array we are presently using. */
+ public int rhs_length() {return _rhs_length;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** An action_part containing code for the action to be performed when we
+ * reduce with this production.
+ */
+ protected action_part _action;
+
+ /** An action_part containing code for the action to be performed when we
+ * reduce with this production.
+ */
+ public action_part action() {return _action;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Index number of the production. */
+ protected int _index;
+
+ /** Index number of the production. */
+ public int index() {return _index;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of number of reductions using this production. */
+ protected int _num_reductions = 0;
+
+ /** Count of number of reductions using this production. */
+ public int num_reductions() {return _num_reductions;}
+
+ /** Increment the count of reductions with this non-terminal */
+ public void note_reduction_use() {_num_reductions++;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Is the nullability of the production known or unknown? */
+ protected boolean _nullable_known = false;
+
+ /** Is the nullability of the production known or unknown? */
+ public boolean nullable_known() {return _nullable_known;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Nullability of the production (can it derive the empty string). */
+ protected boolean _nullable = false;
+
+ /** Nullability of the production (can it derive the empty string). */
+ public boolean nullable() {return _nullable;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** First set of the production. This is the set of terminals that
+ * could appear at the front of some string derived from this production.
+ */
+ protected terminal_set _first_set = new terminal_set();
+
+ /** First set of the production. This is the set of terminals that
+ * could appear at the front of some string derived from this production.
+ */
+ public terminal_set first_set() {return _first_set;}
+
+ /*-----------------------------------------------------------*/
+ /*--- Static Methods ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Determine if a given character can be a label id starter.
+ * @param c the character in question.
+ */
+ protected static boolean is_id_start(char c)
+ {
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_');
+
+ //later need to handle non-8-bit chars here
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if a character can be in a label id.
+ * @param c the character in question.
+ */
+ protected static boolean is_id_char(char c)
+ {
+ return is_id_start(c) || (c >= '0' && c <= '9');
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+
+ /** Return label declaration code
+ * @param labelname the label name
+ * @param stack_type the stack type of label?
+ * @author frankf
+ */
+ protected String make_declaration(
+ String labelname,
+ String stack_type,
+ int offset)
+ {
+ String ret;
+
+ /* Put in the left/right value labels */
+ if (emit.lr_values())
+ ret = "\t\tint " + labelname + "left = ((java_cup.runtime.Symbol)" +
+ emit.pre("stack") + ".elementAt(" + emit.pre("top") +
+ "-" + offset + ")).left;\n" +
+ "\t\tint " + labelname + "right = ((java_cup.runtime.Symbol)" +
+ emit.pre("stack") + ".elementAt(" + emit.pre("top") +
+ "-" + offset + ")).right;\n";
+ else ret = "";
+
+ /* otherwise, just declare label. */
+ return ret + "\t\t" + stack_type + " " + labelname + " = (" + stack_type +
+ ")((" + "java_cup.runtime.Symbol) " + emit.pre("stack") + ".elementAt(" + emit.pre("top")
+ + "-" + offset + ")).value;\n";
+
+ }
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Declare label names as valid variables within the action string
+ * @param rhs array of RHS parts.
+ * @param rhs_len how much of rhs to consider valid.
+ * @param final_action the final action string of the production.
+ * @param lhs_type the object type associated with the LHS symbol.
+ */
+ protected String declare_labels(
+ production_part rhs[],
+ int rhs_len,
+ String final_action)
+ {
+ String declaration = "";
+
+ symbol_part part;
+ action_part act_part;
+ int pos;
+
+ /* walk down the parts and extract the labels */
+ for (pos = 0; pos < rhs_len; pos++)
+ {
+ if (!rhs[pos].is_action())
+ {
+ part = (symbol_part)rhs[pos];
+
+ /* if it has a label, make declaration! */
+ if (part.label() != null)
+ {
+ declaration = declaration +
+ make_declaration(part.label(), part.the_symbol().stack_type(),
+ rhs_len-pos-1);
+ }
+ }
+ }
+ return declaration;
+ }
+
+
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Helper routine to merge adjacent actions in a set of RHS parts
+ * @param rhs_parts array of RHS parts.
+ * @param len amount of that array that is valid.
+ * @return remaining valid length.
+ */
+ protected int merge_adjacent_actions(production_part rhs_parts[], int len)
+ {
+ int from_loc, to_loc, merge_cnt;
+
+ /* bail out early if we have no work to do */
+ if (rhs_parts == null || len == 0) return 0;
+
+ merge_cnt = 0;
+ to_loc = -1;
+ for (from_loc=0; from_loc<len; from_loc++)
+ {
+ /* do we go in the current position or one further */
+ if (to_loc < 0 || !rhs_parts[to_loc].is_action()
+ || !rhs_parts[from_loc].is_action())
+ {
+ /* next one */
+ to_loc++;
+
+ /* clear the way for it */
+ if (to_loc != from_loc) rhs_parts[to_loc] = null;
+ }
+
+ /* if this is not trivial? */
+ if (to_loc != from_loc)
+ {
+ /* do we merge or copy? */
+ if (rhs_parts[to_loc] != null && rhs_parts[to_loc].is_action() &&
+ rhs_parts[from_loc].is_action())
+ {
+ /* merge */
+ rhs_parts[to_loc] = new action_part(
+ ((action_part)rhs_parts[to_loc]).code_string() +
+ ((action_part)rhs_parts[from_loc]).code_string());
+ merge_cnt++;
+ }
+ else
+ {
+ /* copy */
+ rhs_parts[to_loc] = rhs_parts[from_loc];
+ }
+ }
+ }
+
+ /* return the used length */
+ return len - merge_cnt;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Helper routine to strip a trailing action off rhs and return it
+ * @param rhs_parts array of RHS parts.
+ * @param len how many of those are valid.
+ * @return the removed action part.
+ */
+ protected action_part strip_trailing_action(
+ production_part rhs_parts[],
+ int len)
+ {
+ action_part result;
+
+ /* bail out early if we have nothing to do */
+ if (rhs_parts == null || len == 0) return null;
+
+ /* see if we have a trailing action */
+ if (rhs_parts[len-1].is_action())
+ {
+ /* snip it out and return it */
+ result = (action_part)rhs_parts[len-1];
+ rhs_parts[len-1] = null;
+ return result;
+ }
+ else
+ return null;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove all embedded actions from a production by factoring them
+ * out into individual action production using new non terminals.
+ * if the original production was: <pre>
+ * A ::= B {action1} C {action2} D
+ * </pre>
+ * then it will be factored into: <pre>
+ * A ::= B NT$1 C NT$2 D
+ * NT$1 ::= {action1}
+ * NT$2 ::= {action2}
+ * </pre>
+ * where NT$1 and NT$2 are new system created non terminals.
+ */
+
+ /* the declarations added to the parent production are also passed along,
+ as they should be perfectly valid in this code string, since it
+ was originally a code string in the parent, not on its own.
+ frank 6/20/96 */
+ protected void remove_embedded_actions(
+
+ ) throws internal_error
+ {
+ non_terminal new_nt;
+ production new_prod;
+ String declare_str;
+
+ /* walk over the production and process each action */
+ for (int act_loc = 0; act_loc < rhs_length(); act_loc++)
+ if (rhs(act_loc).is_action())
+ {
+
+
+ declare_str = declare_labels(
+ _rhs, act_loc, "");
+ /* create a new non terminal for the action production */
+ new_nt = non_terminal.create_new();
+ new_nt.is_embedded_action = true; /* 24-Mar-1998, CSA */
+
+ /* create a new production with just the action */
+ new_prod = new action_production(this, new_nt, null, 0,
+ declare_str + ((action_part)rhs(act_loc)).code_string());
+
+ /* replace the action with the generated non terminal */
+ _rhs[act_loc] = new symbol_part(new_nt);
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Check to see if the production (now) appears to be nullable.
+ * A production is nullable if its RHS could derive the empty string.
+ * This results when the RHS is empty or contains only non terminals
+ * which themselves are nullable.
+ */
+ public boolean check_nullable() throws internal_error
+ {
+ production_part part;
+ symbol sym;
+ int pos;
+
+ /* if we already know bail out early */
+ if (nullable_known()) return nullable();
+
+ /* if we have a zero size RHS we are directly nullable */
+ if (rhs_length() == 0)
+ {
+ /* stash and return the result */
+ return set_nullable(true);
+ }
+
+ /* otherwise we need to test all of our parts */
+ for (pos=0; pos<rhs_length(); pos++)
+ {
+ part = rhs(pos);
+
+ /* only look at non-actions */
+ if (!part.is_action())
+ {
+ sym = ((symbol_part)part).the_symbol();
+
+ /* if its a terminal we are definitely not nullable */
+ if (!sym.is_non_term())
+ return set_nullable(false);
+ /* its a non-term, is it marked nullable */
+ else if (!((non_terminal)sym).nullable())
+ /* this one not (yet) nullable, so we aren't */
+ return false;
+ }
+ }
+
+ /* if we make it here all parts are nullable */
+ return set_nullable(true);
+ }
+
+ /** set (and return) nullability */
+ boolean set_nullable(boolean v)
+ {
+ _nullable_known = true;
+ _nullable = v;
+ return v;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Update (and return) the first set based on current NT firsts.
+ * This assumes that nullability has already been computed for all non
+ * terminals and productions.
+ */
+ public terminal_set check_first_set() throws internal_error
+ {
+ int part;
+ symbol sym;
+
+ /* walk down the right hand side till we get past all nullables */
+ for (part=0; part<rhs_length(); part++)
+ {
+ /* only look at non-actions */
+ if (!rhs(part).is_action())
+ {
+ sym = ((symbol_part)rhs(part)).the_symbol();
+
+ /* is it a non-terminal?*/
+ if (sym.is_non_term())
+ {
+ /* add in current firsts from that NT */
+ _first_set.add(((non_terminal)sym).first_set());
+
+ /* if its not nullable, we are done */
+ if (!((non_terminal)sym).nullable())
+ break;
+ }
+ else
+ {
+ /* its a terminal -- add that to the set */
+ _first_set.add((terminal)sym);
+
+ /* we are done */
+ break;
+ }
+ }
+ }
+
+ /* return our updated first set */
+ return first_set();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(production other)
+ {
+ if (other == null) return false;
+ return other._index == _index;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof production))
+ return false;
+ else
+ return equals((production)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a hash code. */
+ public int hashCode()
+ {
+ /* just use a simple function of the index */
+ return _index*13;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+
+ /* catch any internal errors */
+ try {
+ result = "production [" + index() + "]: ";
+ result += ((lhs() != null) ? lhs().toString() : "$$NULL-LHS$$");
+ result += " :: = ";
+ for (int i = 0; i<rhs_length(); i++)
+ result += rhs(i) + " ";
+ result += ";";
+ if (action() != null && action().code_string() != null)
+ result += " {" + action().code_string() + "}";
+
+ if (nullable_known())
+ if (nullable())
+ result += "[NULLABLE]";
+ else
+ result += "[NOT NULLABLE]";
+ } catch (internal_error e) {
+ /* crash on internal error since we can't throw it from here (because
+ superclass does not throw anything. */
+ e.crash();
+ result = null;
+ }
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a simpler string. */
+ public String to_simple_string() throws internal_error
+ {
+ String result;
+
+ result = ((lhs() != null) ? lhs().the_symbol().name() : "NULL_LHS");
+ result += " ::= ";
+ for (int i = 0; i < rhs_length(); i++)
+ if (!rhs(i).is_action())
+ result += ((symbol_part)rhs(i)).the_symbol().name() + " ";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/syntaxParser/java_cup/production_part.class b/src/syntaxParser/java_cup/production_part.class
new file mode 100644
index 0000000..80e74a5
--- /dev/null
+++ b/src/syntaxParser/java_cup/production_part.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/production_part.java b/src/syntaxParser/java_cup/production_part.java
new file mode 100644
index 0000000..a790ec0
--- /dev/null
+++ b/src/syntaxParser/java_cup/production_part.java
@@ -0,0 +1,94 @@
+package java_cup;
+
+/** This class represents one part (either a symbol or an action) of a
+ * production. In this base class it contains only an optional label
+ * string that the user can use to refer to the part within actions.<p>
+ *
+ * This is an abstract class.
+ *
+ * @see java_cup.production
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public abstract class production_part {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. */
+ public production_part(String lab)
+ {
+ _label = lab;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Optional label for referring to the part within an action (null for
+ * no label).
+ */
+ protected String _label;
+
+ /** Optional label for referring to the part within an action (null for
+ * no label).
+ */
+ public String label() {return _label;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Indicate if this is an action (rather than a symbol). Here in the
+ * base class, we don't this know yet, so its an abstract method.
+ */
+ public abstract boolean is_action();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(production_part other)
+ {
+ if (other == null) return false;
+
+ /* compare the labels */
+ if (label() != null)
+ return label().equals(other.label());
+ else
+ return other.label() == null;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof production_part))
+ return false;
+ else
+ return equals((production_part)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a hash code. */
+ public int hashCode()
+ {
+ return label()==null ? 0 : label().hashCode();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ if (label() != null)
+ return label() + ":";
+ else
+ return " ";
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/syntaxParser/java_cup/reduce_action.class b/src/syntaxParser/java_cup/reduce_action.class
new file mode 100644
index 0000000..14379c2
--- /dev/null
+++ b/src/syntaxParser/java_cup/reduce_action.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/reduce_action.java b/src/syntaxParser/java_cup/reduce_action.java
new file mode 100644
index 0000000..e8f4c84
--- /dev/null
+++ b/src/syntaxParser/java_cup/reduce_action.java
@@ -0,0 +1,84 @@
+
+package java_cup;
+
+/** This class represents a reduce action within the parse table.
+ * The action simply stores the production that it reduces with and
+ * responds to queries about its type.
+ *
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class reduce_action extends parse_action {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor.
+ * @param prod the production this action reduces with.
+ */
+ public reduce_action(production prod ) throws internal_error
+ {
+ /* sanity check */
+ if (prod == null)
+ throw new internal_error(
+ "Attempt to create a reduce_action with a null production");
+
+ _reduce_with = prod;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The production we reduce with. */
+ protected production _reduce_with;
+
+ /** The production we reduce with. */
+ public production reduce_with() {return _reduce_with;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Quick access to type of action. */
+ public int kind() {return REDUCE;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality test. */
+ public boolean equals(reduce_action other)
+ {
+ return other != null && other.reduce_with() == reduce_with();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality test. */
+ public boolean equals(Object other)
+ {
+ if (other instanceof reduce_action)
+ return equals((reduce_action)other);
+ else
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute a hash code. */
+ public int hashCode()
+ {
+ /* use the hash code of the production we are reducing with */
+ return reduce_with().hashCode();
+ }
+
+
+ /** Convert to string. */
+ public String toString()
+ {
+ return "REDUCE(with prod " + reduce_with().index() + ")";
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/syntaxParser/java_cup/runtime/Scanner.class b/src/syntaxParser/java_cup/runtime/Scanner.class
new file mode 100644
index 0000000..29ef66b
--- /dev/null
+++ b/src/syntaxParser/java_cup/runtime/Scanner.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/runtime/Scanner.java b/src/syntaxParser/java_cup/runtime/Scanner.java
new file mode 100644
index 0000000..3233551
--- /dev/null
+++ b/src/syntaxParser/java_cup/runtime/Scanner.java
@@ -0,0 +1,25 @@
+package java_cup.runtime;
+
+/**
+ * Defines the Scanner interface, which CUP uses in the default
+ * implementation of <code>lr_parser.scan()</code>. Integration
+ * of scanners implementing <code>Scanner</code> is facilitated.
+ *
+ * @version last updated 23-Jul-1999
+ * @author David MacMahon <davidm@smartsc.com>
+ */
+
+/* *************************************************
+ Interface Scanner
+
+ Declares the next_token() method that should be
+ implemented by scanners. This method is typically
+ called by lr_parser.scan(). End-of-file can be
+ indicated either by returning
+ <code>new Symbol(lr_parser.EOF_sym())</code> or
+ <code>null</code>.
+ ***************************************************/
+public interface Scanner {
+ /** Return the next token, or <code>null</code> on end-of-file. */
+ public Symbol next_token() throws java.lang.Exception;
+}
diff --git a/src/syntaxParser/java_cup/runtime/Symbol.class b/src/syntaxParser/java_cup/runtime/Symbol.class
new file mode 100644
index 0000000..4831d12
--- /dev/null
+++ b/src/syntaxParser/java_cup/runtime/Symbol.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/runtime/Symbol.java b/src/syntaxParser/java_cup/runtime/Symbol.java
new file mode 100644
index 0000000..eeb6a0b
--- /dev/null
+++ b/src/syntaxParser/java_cup/runtime/Symbol.java
@@ -0,0 +1,105 @@
+package java_cup.runtime;
+
+/**
+ * Defines the Symbol class, which is used to represent all terminals
+ * and nonterminals while parsing. The lexer should pass CUP Symbols
+ * and CUP returns a Symbol.
+ *
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+
+/* ****************************************************************
+ Class Symbol
+ what the parser expects to receive from the lexer.
+ the token is identified as follows:
+ sym: the symbol type
+ parse_state: the parse state.
+ value: is the lexical value of type Object
+ left : is the left position in the original input file
+ right: is the right position in the original input file
+******************************************************************/
+
+public class Symbol {
+
+/*******************************
+ Constructor for l,r values
+ *******************************/
+
+ public Symbol(int id, int l, int r, Object o) {
+ this(id);
+ left = l;
+ right = r;
+ value = o;
+ }
+
+/*******************************
+ Constructor for no l,r values
+********************************/
+
+ public Symbol(int id, Object o) {
+ this(id, -1, -1, o);
+ }
+
+/*****************************
+ Constructor for no value
+ ***************************/
+
+ public Symbol(int id, int l, int r) {
+ this(id, l, r, null);
+ }
+
+/***********************************
+ Constructor for no value or l,r
+***********************************/
+
+ public Symbol(int sym_num) {
+ this(sym_num, -1);
+ left = -1;
+ right = -1;
+ value = null;
+ }
+
+/***********************************
+ Constructor to give a start state
+***********************************/
+ Symbol(int sym_num, int state)
+ {
+ sym = sym_num;
+ parse_state = state;
+ }
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The symbol number of the terminal or non terminal being represented */
+ public int sym;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The parse state to be recorded on the parse stack with this symbol.
+ * This field is for the convenience of the parser and shouldn't be
+ * modified except by the parser.
+ */
+ public int parse_state;
+ /** This allows us to catch some errors caused by scanners recycling
+ * symbols. For the use of the parser only. [CSA, 23-Jul-1999] */
+ boolean used_by_parser = false;
+
+/*******************************
+ The data passed to parser
+ *******************************/
+
+ public int left, right;
+ public Object value;
+
+ /*****************************
+ Printing this token out. (Override for pretty-print).
+ ****************************/
+ public String toString() { return "#"+sym; }
+}
+
+
+
+
+
+
diff --git a/src/syntaxParser/java_cup/runtime/lr_parser.class b/src/syntaxParser/java_cup/runtime/lr_parser.class
new file mode 100644
index 0000000..338bdd8
--- /dev/null
+++ b/src/syntaxParser/java_cup/runtime/lr_parser.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/runtime/lr_parser.java b/src/syntaxParser/java_cup/runtime/lr_parser.java
new file mode 100644
index 0000000..3c8335c
--- /dev/null
+++ b/src/syntaxParser/java_cup/runtime/lr_parser.java
@@ -0,0 +1,1238 @@
+
+package java_cup.runtime;
+
+import java.util.Stack;
+
+/** This class implements a skeleton table driven LR parser. In general,
+ * LR parsers are a form of bottom up shift-reduce parsers. Shift-reduce
+ * parsers act by shifting input onto a parse stack until the Symbols
+ * matching the right hand side of a production appear on the top of the
+ * stack. Once this occurs, a reduce is performed. This involves removing
+ * the Symbols corresponding to the right hand side of the production
+ * (the so called "handle") and replacing them with the non-terminal from
+ * the left hand side of the production. <p>
+ *
+ * To control the decision of whether to shift or reduce at any given point,
+ * the parser uses a state machine (the "viable prefix recognition machine"
+ * built by the parser generator). The current state of the machine is placed
+ * on top of the parse stack (stored as part of a Symbol object representing
+ * a terminal or non terminal). The parse action table is consulted
+ * (using the current state and the current lookahead Symbol as indexes) to
+ * determine whether to shift or to reduce. When the parser shifts, it
+ * changes to a new state by pushing a new Symbol (containing a new state)
+ * onto the stack. When the parser reduces, it pops the handle (right hand
+ * side of a production) off the stack. This leaves the parser in the state
+ * it was in before any of those Symbols were matched. Next the reduce-goto
+ * table is consulted (using the new state and current lookahead Symbol as
+ * indexes) to determine a new state to go to. The parser then shifts to
+ * this goto state by pushing the left hand side Symbol of the production
+ * (also containing the new state) onto the stack.<p>
+ *
+ * This class actually provides four LR parsers. The methods parse() and
+ * debug_parse() provide two versions of the main parser (the only difference
+ * being that debug_parse() emits debugging trace messages as it parses).
+ * In addition to these main parsers, the error recovery mechanism uses two
+ * more. One of these is used to simulate "parsing ahead" in the input
+ * without carrying out actions (to verify that a potential error recovery
+ * has worked), and the other is used to parse through buffered "parse ahead"
+ * input in order to execute all actions and re-synchronize the actual parser
+ * configuration.<p>
+ *
+ * This is an abstract class which is normally filled out by a subclass
+ * generated by the JavaCup parser generator. In addition to supplying
+ * the actual parse tables, generated code also supplies methods which
+ * invoke various pieces of user supplied code, provide access to certain
+ * special Symbols (e.g., EOF and error), etc. Specifically, the following
+ * abstract methods are normally supplied by generated code:
+ * <dl compact>
+ * <dt> short[][] production_table()
+ * <dd> Provides a reference to the production table (indicating the index of
+ * the left hand side non terminal and the length of the right hand side
+ * for each production in the grammar).
+ * <dt> short[][] action_table()
+ * <dd> Provides a reference to the parse action table.
+ * <dt> short[][] reduce_table()
+ * <dd> Provides a reference to the reduce-goto table.
+ * <dt> int start_state()
+ * <dd> Indicates the index of the start state.
+ * <dt> int start_production()
+ * <dd> Indicates the index of the starting production.
+ * <dt> int EOF_sym()
+ * <dd> Indicates the index of the EOF Symbol.
+ * <dt> int error_sym()
+ * <dd> Indicates the index of the error Symbol.
+ * <dt> Symbol do_action()
+ * <dd> Executes a piece of user supplied action code. This always comes at
+ * the point of a reduce in the parse, so this code also allocates and
+ * fills in the left hand side non terminal Symbol object that is to be
+ * pushed onto the stack for the reduce.
+ * <dt> void init_actions()
+ * <dd> Code to initialize a special object that encapsulates user supplied
+ * actions (this object is used by do_action() to actually carry out the
+ * actions).
+ * </dl>
+ *
+ * In addition to these routines that <i>must</i> be supplied by the
+ * generated subclass there are also a series of routines that <i>may</i>
+ * be supplied. These include:
+ * <dl>
+ * <dt> Symbol scan()
+ * <dd> Used to get the next input Symbol from the scanner.
+ * <dt> Scanner getScanner()
+ * <dd> Used to provide a scanner for the default implementation of
+ * scan().
+ * <dt> int error_sync_size()
+ * <dd> This determines how many Symbols past the point of an error
+ * must be parsed without error in order to consider a recovery to
+ * be valid. This defaults to 3. Values less than 2 are not
+ * recommended.
+ * <dt> void report_error(String message, Object info)
+ * <dd> This method is called to report an error. The default implementation
+ * simply prints a message to System.err and where the error occurred.
+ * This method is often replaced in order to provide a more sophisticated
+ * error reporting mechanism.
+ * <dt> void report_fatal_error(String message, Object info)
+ * <dd> This method is called when a fatal error that cannot be recovered from
+ * is encountered. In the default implementation, it calls
+ * report_error() to emit a message, then throws an exception.
+ * <dt> void syntax_error(Symbol cur_token)
+ * <dd> This method is called as soon as syntax error is detected (but
+ * before recovery is attempted). In the default implementation it
+ * invokes: report_error("Syntax error", null);
+ * <dt> void unrecovered_syntax_error(Symbol cur_token)
+ * <dd> This method is called if syntax error recovery fails. In the default
+ * implementation it invokes:<br>
+ * report_fatal_error("Couldn't repair and continue parse", null);
+ * </dl>
+ *
+ * @see java_cup.runtime.Symbol
+ * @see java_cup.runtime.Symbol
+ * @see java_cup.runtime.virtual_parse_stack
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+
+public abstract class lr_parser {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. */
+ public lr_parser()
+ {
+ /* nothing to do here */
+ }
+
+ /** Constructor that sets the default scanner. [CSA/davidm] */
+ public lr_parser(Scanner s) {
+ this(); /* in case default constructor someday does something */
+ setScanner(s);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The default number of Symbols after an error we much match to consider
+ * it recovered from.
+ */
+ protected final static int _error_sync_size = 3;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The number of Symbols after an error we much match to consider it
+ * recovered from.
+ */
+ protected int error_sync_size() {return _error_sync_size; }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Table of production information (supplied by generated subclass).
+ * This table contains one entry per production and is indexed by
+ * the negative-encoded values (reduce actions) in the action_table.
+ * Each entry has two parts, the index of the non-terminal on the
+ * left hand side of the production, and the number of Symbols
+ * on the right hand side.
+ */
+ public abstract short[][] production_table();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The action table (supplied by generated subclass). This table is
+ * indexed by state and terminal number indicating what action is to
+ * be taken when the parser is in the given state (i.e., the given state
+ * is on top of the stack) and the given terminal is next on the input.
+ * States are indexed using the first dimension, however, the entries for
+ * a given state are compacted and stored in adjacent index, value pairs
+ * which are searched for rather than accessed directly (see get_action()).
+ * The actions stored in the table will be either shifts, reduces, or
+ * errors. Shifts are encoded as positive values (one greater than the
+ * state shifted to). Reduces are encoded as negative values (one less
+ * than the production reduced by). Error entries are denoted by zero.
+ *
+ * @see java_cup.runtime.lr_parser#get_action
+ */
+ public abstract short[][] action_table();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The reduce-goto table (supplied by generated subclass). This
+ * table is indexed by state and non-terminal number and contains
+ * state numbers. States are indexed using the first dimension, however,
+ * the entries for a given state are compacted and stored in adjacent
+ * index, value pairs which are searched for rather than accessed
+ * directly (see get_reduce()). When a reduce occurs, the handle
+ * (corresponding to the RHS of the matched production) is popped off
+ * the stack. The new top of stack indicates a state. This table is
+ * then indexed by that state and the LHS of the reducing production to
+ * indicate where to "shift" to.
+ *
+ * @see java_cup.runtime.lr_parser#get_reduce
+ */
+ public abstract short[][] reduce_table();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The index of the start state (supplied by generated subclass). */
+ public abstract int start_state();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The index of the start production (supplied by generated subclass). */
+ public abstract int start_production();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The index of the end of file terminal Symbol (supplied by generated
+ * subclass).
+ */
+ public abstract int EOF_sym();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The index of the special error Symbol (supplied by generated subclass). */
+ public abstract int error_sym();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Internal flag to indicate when parser should quit. */
+ protected boolean _done_parsing = false;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** This method is called to indicate that the parser should quit. This is
+ * normally called by an accept action, but can be used to cancel parsing
+ * early in other circumstances if desired.
+ */
+ public void done_parsing()
+ {
+ _done_parsing = true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+ /* Global parse state shared by parse(), error recovery, and
+ * debugging routines */
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Indication of the index for top of stack (for use by actions). */
+ protected int tos;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The current lookahead Symbol. */
+ protected Symbol cur_token;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The parse stack itself. */
+ protected Stack stack = new Stack();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Direct reference to the production table. */
+ protected short[][] production_tab;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Direct reference to the action table. */
+ protected short[][] action_tab;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Direct reference to the reduce-goto table. */
+ protected short[][] reduce_tab;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** This is the scanner object used by the default implementation
+ * of scan() to get Symbols. To avoid name conflicts with existing
+ * code, this field is private. [CSA/davidm] */
+ private Scanner _scanner;
+
+ /**
+ * Simple accessor method to set the default scanner.
+ */
+ public void setScanner(Scanner s) { _scanner = s; }
+
+ /**
+ * Simple accessor method to get the default scanner.
+ */
+ public Scanner getScanner() { return _scanner; }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Perform a bit of user supplied action code (supplied by generated
+ * subclass). Actions are indexed by an internal action number assigned
+ * at parser generation time.
+ *
+ * @param act_num the internal index of the action to be performed.
+ * @param parser the parser object we are acting for.
+ * @param stack the parse stack of that object.
+ * @param top the index of the top element of the parse stack.
+ */
+ public abstract Symbol do_action(
+ int act_num,
+ lr_parser parser,
+ Stack stack,
+ int top)
+ throws java.lang.Exception;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** User code for initialization inside the parser. Typically this
+ * initializes the scanner. This is called before the parser requests
+ * the first Symbol. Here this is just a placeholder for subclasses that
+ * might need this and we perform no action. This method is normally
+ * overridden by the generated code using this contents of the "init with"
+ * clause as its body.
+ */
+ public void user_init() throws java.lang.Exception { }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Initialize the action object. This is called before the parser does
+ * any parse actions. This is filled in by generated code to create
+ * an object that encapsulates all action code.
+ */
+ protected abstract void init_actions() throws java.lang.Exception;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Get the next Symbol from the input (supplied by generated subclass).
+ * Once end of file has been reached, all subsequent calls to scan
+ * should return an EOF Symbol (which is Symbol number 0). By default
+ * this method returns getScanner().next_token(); this implementation
+ * can be overriden by the generated parser using the code declared in
+ * the "scan with" clause. Do not recycle objects; every call to
+ * scan() should return a fresh object.
+ */
+ public Symbol scan() throws java.lang.Exception {
+ Symbol sym = getScanner().next_token();
+ return (sym!=null) ? sym : new Symbol(EOF_sym());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Report a fatal error. This method takes a message string and an
+ * additional object (to be used by specializations implemented in
+ * subclasses). Here in the base class a very simple implementation
+ * is provided which reports the error then throws an exception.
+ *
+ * @param message an error message.
+ * @param info an extra object reserved for use by specialized subclasses.
+ */
+ public void report_fatal_error(
+ String message,
+ Object info)
+ throws java.lang.Exception
+ {
+ /* stop parsing (not really necessary since we throw an exception, but) */
+ done_parsing();
+
+ /* use the normal error message reporting to put out the message */
+ report_error(message, info);
+
+ /* throw an exception */
+ throw new Exception("Can't recover from previous error(s)");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Report a non fatal error (or warning). This method takes a message
+ * string and an additional object (to be used by specializations
+ * implemented in subclasses). Here in the base class a very simple
+ * implementation is provided which simply prints the message to
+ * System.err.
+ *
+ * @param message an error message.
+ * @param info an extra object reserved for use by specialized subclasses.
+ */
+ public void report_error(String message, Object info)
+ {
+ System.err.print(message);
+ if (info instanceof Symbol)
+ if (((Symbol)info).left != -1)
+ System.err.println(" at character " + ((Symbol)info).left +
+ " of input");
+ else System.err.println("");
+ else System.err.println("");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** This method is called when a syntax error has been detected and recovery
+ * is about to be invoked. Here in the base class we just emit a
+ * "Syntax error" error message.
+ *
+ * @param cur_token the current lookahead Symbol.
+ */
+ public void syntax_error(Symbol cur_token)
+ {
+ report_error("Syntax error", cur_token);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** This method is called if it is determined that syntax error recovery
+ * has been unsuccessful. Here in the base class we report a fatal error.
+ *
+ * @param cur_token the current lookahead Symbol.
+ */
+ public void unrecovered_syntax_error(Symbol cur_token)
+ throws java.lang.Exception
+ {
+ report_fatal_error("Couldn't repair and continue parse", cur_token);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Fetch an action from the action table. The table is broken up into
+ * rows, one per state (rows are indexed directly by state number).
+ * Within each row, a list of index, value pairs are given (as sequential
+ * entries in the table), and the list is terminated by a default entry
+ * (denoted with a Symbol index of -1). To find the proper entry in a row
+ * we do a linear or binary search (depending on the size of the row).
+ *
+ * @param state the state index of the action being accessed.
+ * @param sym the Symbol index of the action being accessed.
+ */
+ protected final short get_action(int state, int sym)
+ {
+ short tag;
+ int first, last, probe;
+ short[] row = action_tab[state];
+
+ /* linear search if we are < 10 entries */
+ if (row.length < 20)
+ for (probe = 0; probe < row.length; probe++)
+ {
+ /* is this entry labeled with our Symbol or the default? */
+ tag = row[probe++];
+ if (tag == sym || tag == -1)
+ {
+ /* return the next entry */
+ return row[probe];
+ }
+ }
+ /* otherwise binary search */
+ else
+ {
+ first = 0;
+ last = (row.length-1)/2 - 1; /* leave out trailing default entry */
+ while (first <= last)
+ {
+ probe = (first+last)/2;
+ if (sym == row[probe*2])
+ return row[probe*2+1];
+ else if (sym > row[probe*2])
+ first = probe+1;
+ else
+ last = probe-1;
+ }
+
+ /* not found, use the default at the end */
+ return row[row.length-1];
+ }
+
+ /* shouldn't happened, but if we run off the end we return the
+ default (error == 0) */
+ return 0;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Fetch a state from the reduce-goto table. The table is broken up into
+ * rows, one per state (rows are indexed directly by state number).
+ * Within each row, a list of index, value pairs are given (as sequential
+ * entries in the table), and the list is terminated by a default entry
+ * (denoted with a Symbol index of -1). To find the proper entry in a row
+ * we do a linear search.
+ *
+ * @param state the state index of the entry being accessed.
+ * @param sym the Symbol index of the entry being accessed.
+ */
+ protected final short get_reduce(int state, int sym)
+ {
+ short tag;
+ short[] row = reduce_tab[state];
+
+ /* if we have a null row we go with the default */
+ if (row == null)
+ return -1;
+
+ for (int probe = 0; probe < row.length; probe++)
+ {
+ /* is this entry labeled with our Symbol or the default? */
+ tag = row[probe++];
+ if (tag == sym || tag == -1)
+ {
+ /* return the next entry */
+ return row[probe];
+ }
+ }
+ /* if we run off the end we return the default (error == -1) */
+ return -1;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** This method provides the main parsing routine. It returns only when
+ * done_parsing() has been called (typically because the parser has
+ * accepted, or a fatal error has been reported). See the header
+ * documentation for the class regarding how shift/reduce parsers operate
+ * and how the various tables are used.
+ */
+ public Symbol parse() throws java.lang.Exception
+ {
+ /* the current action code */
+ int act;
+
+ /* the Symbol/stack element returned by a reduce */
+ Symbol lhs_sym = null;
+
+ /* information about production being reduced with */
+ short handle_size, lhs_sym_num;
+
+ /* set up direct reference to tables to drive the parser */
+
+ production_tab = production_table();
+ action_tab = action_table();
+ reduce_tab = reduce_table();
+
+ /* initialize the action encapsulation object */
+ init_actions();
+
+ /* do user initialization */
+ user_init();
+
+ /* get the first token */
+ cur_token = scan();
+
+ /* push dummy Symbol with start state to get us underway */
+ stack.removeAllElements();
+ stack.push(new Symbol(0, start_state()));
+ tos = 0;
+
+ /* continue until we are told to stop */
+ for (_done_parsing = false; !_done_parsing; )
+ {
+ /* Check current token for freshness. */
+ if (cur_token.used_by_parser)
+ throw new Error("Symbol recycling detected (fix your scanner).");
+
+ /* current state is always on the top of the stack */
+
+ /* look up action out of the current state with the current input */
+ act = get_action(((Symbol)stack.peek()).parse_state, cur_token.sym);
+
+ /* decode the action -- > 0 encodes shift */
+ if (act > 0)
+ {
+ /* shift to the encoded state by pushing it on the stack */
+ cur_token.parse_state = act-1;
+ cur_token.used_by_parser = true;
+ stack.push(cur_token);
+ tos++;
+
+ /* advance to the next Symbol */
+ cur_token = scan();
+ }
+ /* if its less than zero, then it encodes a reduce action */
+ else if (act < 0)
+ {
+ /* perform the action for the reduce */
+ lhs_sym = do_action((-act)-1, this, stack, tos);
+
+ /* look up information about the production */
+ lhs_sym_num = production_tab[(-act)-1][0];
+ handle_size = production_tab[(-act)-1][1];
+
+ /* pop the handle off the stack */
+ for (int i = 0; i < handle_size; i++)
+ {
+ stack.pop();
+ tos--;
+ }
+
+ /* look up the state to go to from the one popped back to */
+ act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num);
+
+ /* shift to that state */
+ lhs_sym.parse_state = act;
+ lhs_sym.used_by_parser = true;
+ stack.push(lhs_sym);
+ tos++;
+ }
+ /* finally if the entry is zero, we have an error */
+ else if (act == 0)
+ {
+ /* call user syntax error reporting routine */
+ syntax_error(cur_token);
+
+ /* try to error recover */
+ if (!error_recovery(false))
+ {
+ /* if that fails give up with a fatal syntax error */
+ unrecovered_syntax_error(cur_token);
+
+ /* just in case that wasn't fatal enough, end parse */
+ done_parsing();
+ } else {
+ lhs_sym = (Symbol)stack.peek();
+ }
+ }
+ }
+ return lhs_sym;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Write a debugging message to System.err for the debugging version
+ * of the parser.
+ *
+ * @param mess the text of the debugging message.
+ */
+ public void debug_message(String mess)
+ {
+ System.err.println(mess);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Dump the parse stack for debugging purposes. */
+ public void dump_stack()
+ {
+ if (stack == null)
+ {
+ debug_message("# Stack dump requested, but stack is null");
+ return;
+ }
+
+ debug_message("============ Parse Stack Dump ============");
+
+ /* dump the stack */
+ for (int i=0; i<stack.size(); i++)
+ {
+ debug_message("Symbol: " + ((Symbol)stack.elementAt(i)).sym +
+ " State: " + ((Symbol)stack.elementAt(i)).parse_state);
+ }
+ debug_message("==========================================");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Do debug output for a reduce.
+ *
+ * @param prod_num the production we are reducing with.
+ * @param nt_num the index of the LHS non terminal.
+ * @param rhs_size the size of the RHS.
+ */
+ public void debug_reduce(int prod_num, int nt_num, int rhs_size)
+ {
+ debug_message("# Reduce with prod #" + prod_num + " [NT=" + nt_num +
+ ", " + "SZ=" + rhs_size + "]");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Do debug output for shift.
+ *
+ * @param shift_tkn the Symbol being shifted onto the stack.
+ */
+ public void debug_shift(Symbol shift_tkn)
+ {
+ debug_message("# Shift under term #" + shift_tkn.sym +
+ " to state #" + shift_tkn.parse_state);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Do debug output for stack state. [CSA]
+ */
+ public void debug_stack() {
+ StringBuffer sb=new StringBuffer("## STACK:");
+ for (int i=0; i<stack.size(); i++) {
+ Symbol s = (Symbol) stack.elementAt(i);
+ sb.append(" <state "+s.parse_state+", sym "+s.sym+">");
+ if ((i%3)==2 || (i==(stack.size()-1))) {
+ debug_message(sb.toString());
+ sb = new StringBuffer(" ");
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Perform a parse with debugging output. This does exactly the
+ * same things as parse(), except that it calls debug_shift() and
+ * debug_reduce() when shift and reduce moves are taken by the parser
+ * and produces various other debugging messages.
+ */
+ public Symbol debug_parse()
+ throws java.lang.Exception
+ {
+ /* the current action code */
+ int act;
+
+ /* the Symbol/stack element returned by a reduce */
+ Symbol lhs_sym = null;
+
+ /* information about production being reduced with */
+ short handle_size, lhs_sym_num;
+
+ /* set up direct reference to tables to drive the parser */
+ production_tab = production_table();
+ action_tab = action_table();
+ reduce_tab = reduce_table();
+
+ debug_message("# Initializing parser");
+
+ /* initialize the action encapsulation object */
+ init_actions();
+
+ /* do user initialization */
+ user_init();
+
+ /* the current Symbol */
+ cur_token = scan();
+
+ debug_message("# Current Symbol is #" + cur_token.sym);
+
+ /* push dummy Symbol with start state to get us underway */
+ stack.removeAllElements();
+ stack.push(new Symbol(0, start_state()));
+ tos = 0;
+
+ /* continue until we are told to stop */
+ for (_done_parsing = false; !_done_parsing; )
+ {
+ /* Check current token for freshness. */
+ if (cur_token.used_by_parser)
+ throw new Error("Symbol recycling detected (fix your scanner).");
+
+ /* current state is always on the top of the stack */
+ //debug_stack();
+
+ /* look up action out of the current state with the current input */
+ act = get_action(((Symbol)stack.peek()).parse_state, cur_token.sym);
+
+ /* decode the action -- > 0 encodes shift */
+ if (act > 0)
+ {
+ /* shift to the encoded state by pushing it on the stack */
+ cur_token.parse_state = act-1;
+ cur_token.used_by_parser = true;
+ debug_shift(cur_token);
+ stack.push(cur_token);
+ tos++;
+
+ /* advance to the next Symbol */
+ cur_token = scan();
+ debug_message("# Current token is " + cur_token);
+ }
+ /* if its less than zero, then it encodes a reduce action */
+ else if (act < 0)
+ {
+ /* perform the action for the reduce */
+ lhs_sym = do_action((-act)-1, this, stack, tos);
+
+ /* look up information about the production */
+ lhs_sym_num = production_tab[(-act)-1][0];
+ handle_size = production_tab[(-act)-1][1];
+
+ debug_reduce((-act)-1, lhs_sym_num, handle_size);
+
+ /* pop the handle off the stack */
+ for (int i = 0; i < handle_size; i++)
+ {
+ stack.pop();
+ tos--;
+ }
+
+ /* look up the state to go to from the one popped back to */
+ act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num);
+ debug_message("# Reduce rule: top state " +
+ ((Symbol)stack.peek()).parse_state +
+ ", lhs sym " + lhs_sym_num + " -> state " + act);
+
+ /* shift to that state */
+ lhs_sym.parse_state = act;
+ lhs_sym.used_by_parser = true;
+ stack.push(lhs_sym);
+ tos++;
+
+ debug_message("# Goto state #" + act);
+ }
+ /* finally if the entry is zero, we have an error */
+ else if (act == 0)
+ {
+ /* call user syntax error reporting routine */
+ syntax_error(cur_token);
+
+ /* try to error recover */
+ if (!error_recovery(true))
+ {
+ /* if that fails give up with a fatal syntax error */
+ unrecovered_syntax_error(cur_token);
+
+ /* just in case that wasn't fatal enough, end parse */
+ done_parsing();
+ } else {
+ lhs_sym = (Symbol)stack.peek();
+ }
+ }
+ }
+ return lhs_sym;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+ /* Error recovery code */
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Attempt to recover from a syntax error. This returns false if recovery
+ * fails, true if it succeeds. Recovery happens in 4 steps. First we
+ * pop the parse stack down to a point at which we have a shift out
+ * of the top-most state on the error Symbol. This represents the
+ * initial error recovery configuration. If no such configuration is
+ * found, then we fail. Next a small number of "lookahead" or "parse
+ * ahead" Symbols are read into a buffer. The size of this buffer is
+ * determined by error_sync_size() and determines how many Symbols beyond
+ * the error must be matched to consider the recovery a success. Next,
+ * we begin to discard Symbols in attempt to get past the point of error
+ * to a point where we can continue parsing. After each Symbol, we attempt
+ * to "parse ahead" though the buffered lookahead Symbols. The "parse ahead"
+ * process simulates that actual parse, but does not modify the real
+ * parser's configuration, nor execute any actions. If we can parse all
+ * the stored Symbols without error, then the recovery is considered a
+ * success. Once a successful recovery point is determined, we do an
+ * actual parse over the stored input -- modifying the real parse
+ * configuration and executing all actions. Finally, we return the the
+ * normal parser to continue with the overall parse.
+ *
+ * @param debug should we produce debugging messages as we parse.
+ */
+ protected boolean error_recovery(boolean debug)
+ throws java.lang.Exception
+ {
+ if (debug) debug_message("# Attempting error recovery");
+
+ /* first pop the stack back into a state that can shift on error and
+ do that shift (if that fails, we fail) */
+ if (!find_recovery_config(debug))
+ {
+ if (debug) debug_message("# Error recovery fails");
+ return false;
+ }
+
+ /* read ahead to create lookahead we can parse multiple times */
+ read_lookahead();
+
+ /* repeatedly try to parse forward until we make it the required dist */
+ for (;;)
+ {
+ /* try to parse forward, if it makes it, bail out of loop */
+ if (debug) debug_message("# Trying to parse ahead");
+ if (try_parse_ahead(debug))
+ {
+ break;
+ }
+
+ /* if we are now at EOF, we have failed */
+ if (lookahead[0].sym == EOF_sym())
+ {
+ if (debug) debug_message("# Error recovery fails at EOF");
+ return false;
+ }
+
+ /* otherwise, we consume another Symbol and try again */
+ // BUG FIX by Bruce Hutton
+ // Computer Science Department, University of Auckland,
+ // Auckland, New Zealand.
+ // It is the first token that is being consumed, not the one
+ // we were up to parsing
+ if (debug)
+ debug_message("# Consuming Symbol #" + lookahead[ 0 ].sym);
+ restart_lookahead();
+ }
+
+ /* we have consumed to a point where we can parse forward */
+ if (debug) debug_message("# Parse-ahead ok, going back to normal parse");
+
+ /* do the real parse (including actions) across the lookahead */
+ parse_lookahead(debug);
+
+ /* we have success */
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if we can shift under the special error Symbol out of the
+ * state currently on the top of the (real) parse stack.
+ */
+ protected boolean shift_under_error()
+ {
+ /* is there a shift under error Symbol */
+ return get_action(((Symbol)stack.peek()).parse_state, error_sym()) > 0;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Put the (real) parse stack into error recovery configuration by
+ * popping the stack down to a state that can shift on the special
+ * error Symbol, then doing the shift. If no suitable state exists on
+ * the stack we return false
+ *
+ * @param debug should we produce debugging messages as we parse.
+ */
+ protected boolean find_recovery_config(boolean debug)
+ {
+ Symbol error_token;
+ int act;
+
+ if (debug) debug_message("# Finding recovery state on stack");
+
+ /* Remember the right-position of the top symbol on the stack */
+ int right_pos = ((Symbol)stack.peek()).right;
+ int left_pos = ((Symbol)stack.peek()).left;
+
+ /* pop down until we can shift under error Symbol */
+ while (!shift_under_error())
+ {
+ /* pop the stack */
+ if (debug)
+ debug_message("# Pop stack by one, state was # " +
+ ((Symbol)stack.peek()).parse_state);
+ left_pos = ((Symbol)stack.pop()).left;
+ tos--;
+
+ /* if we have hit bottom, we fail */
+ if (stack.empty())
+ {
+ if (debug) debug_message("# No recovery state found on stack");
+ return false;
+ }
+ }
+
+ /* state on top of the stack can shift under error, find the shift */
+ act = get_action(((Symbol)stack.peek()).parse_state, error_sym());
+ if (debug)
+ {
+ debug_message("# Recover state found (#" +
+ ((Symbol)stack.peek()).parse_state + ")");
+ debug_message("# Shifting on error to state #" + (act-1));
+ }
+
+ /* build and shift a special error Symbol */
+ error_token = new Symbol(error_sym(), left_pos, right_pos);
+ error_token.parse_state = act-1;
+ error_token.used_by_parser = true;
+ stack.push(error_token);
+ tos++;
+
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Lookahead Symbols used for attempting error recovery "parse aheads". */
+ protected Symbol lookahead[];
+
+ /** Position in lookahead input buffer used for "parse ahead". */
+ protected int lookahead_pos;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Read from input to establish our buffer of "parse ahead" lookahead
+ * Symbols.
+ */
+ protected void read_lookahead() throws java.lang.Exception
+ {
+ /* create the lookahead array */
+ lookahead = new Symbol[error_sync_size()];
+
+ /* fill in the array */
+ for (int i = 0; i < error_sync_size(); i++)
+ {
+ lookahead[i] = cur_token;
+ cur_token = scan();
+ }
+
+ /* start at the beginning */
+ lookahead_pos = 0;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return the current lookahead in our error "parse ahead" buffer. */
+ protected Symbol cur_err_token() { return lookahead[lookahead_pos]; }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Advance to next "parse ahead" input Symbol. Return true if we have
+ * input to advance to, false otherwise.
+ */
+ protected boolean advance_lookahead()
+ {
+ /* advance the input location */
+ lookahead_pos++;
+
+ /* return true if we didn't go off the end */
+ return lookahead_pos < error_sync_size();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Reset the parse ahead input to one Symbol past where we started error
+ * recovery (this consumes one new Symbol from the real input).
+ */
+ protected void restart_lookahead() throws java.lang.Exception
+ {
+ /* move all the existing input over */
+ for (int i = 1; i < error_sync_size(); i++)
+ lookahead[i-1] = lookahead[i];
+
+ /* read a new Symbol into the last spot */
+ // BUG Fix by Bruce Hutton
+ // Computer Science Department, University of Auckland,
+ // Auckland, New Zealand. [applied 5-sep-1999 by csa]
+ // The following two lines were out of order!!
+ lookahead[error_sync_size()-1] = cur_token;
+ cur_token = scan();
+
+ /* reset our internal position marker */
+ lookahead_pos = 0;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Do a simulated parse forward (a "parse ahead") from the current
+ * stack configuration using stored lookahead input and a virtual parse
+ * stack. Return true if we make it all the way through the stored
+ * lookahead input without error. This basically simulates the action of
+ * parse() using only our saved "parse ahead" input, and not executing any
+ * actions.
+ *
+ * @param debug should we produce debugging messages as we parse.
+ */
+ protected boolean try_parse_ahead(boolean debug)
+ throws java.lang.Exception
+ {
+ int act;
+ short lhs, rhs_size;
+
+ /* create a virtual stack from the real parse stack */
+ virtual_parse_stack vstack = new virtual_parse_stack(stack);
+
+ /* parse until we fail or get past the lookahead input */
+ for (;;)
+ {
+ /* look up the action from the current state (on top of stack) */
+ act = get_action(vstack.top(), cur_err_token().sym);
+
+ /* if its an error, we fail */
+ if (act == 0) return false;
+
+ /* > 0 encodes a shift */
+ if (act > 0)
+ {
+ /* push the new state on the stack */
+ vstack.push(act-1);
+
+ if (debug) debug_message("# Parse-ahead shifts Symbol #" +
+ cur_err_token().sym + " into state #" + (act-1));
+
+ /* advance simulated input, if we run off the end, we are done */
+ if (!advance_lookahead()) return true;
+ }
+ /* < 0 encodes a reduce */
+ else
+ {
+ /* if this is a reduce with the start production we are done */
+ if ((-act)-1 == start_production())
+ {
+ if (debug) debug_message("# Parse-ahead accepts");
+ return true;
+ }
+
+ /* get the lhs Symbol and the rhs size */
+ lhs = production_tab[(-act)-1][0];
+ rhs_size = production_tab[(-act)-1][1];
+
+ /* pop handle off the stack */
+ for (int i = 0; i < rhs_size; i++)
+ vstack.pop();
+
+ if (debug)
+ debug_message("# Parse-ahead reduces: handle size = " +
+ rhs_size + " lhs = #" + lhs + " from state #" + vstack.top());
+
+ /* look up goto and push it onto the stack */
+ vstack.push(get_reduce(vstack.top(), lhs));
+ if (debug)
+ debug_message("# Goto state #" + vstack.top());
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Parse forward using stored lookahead Symbols. In this case we have
+ * already verified that parsing will make it through the stored lookahead
+ * Symbols and we are now getting back to the point at which we can hand
+ * control back to the normal parser. Consequently, this version of the
+ * parser performs all actions and modifies the real parse configuration.
+ * This returns once we have consumed all the stored input or we accept.
+ *
+ * @param debug should we produce debugging messages as we parse.
+ */
+ protected void parse_lookahead(boolean debug)
+ throws java.lang.Exception
+ {
+ /* the current action code */
+ int act;
+
+ /* the Symbol/stack element returned by a reduce */
+ Symbol lhs_sym = null;
+
+ /* information about production being reduced with */
+ short handle_size, lhs_sym_num;
+
+ /* restart the saved input at the beginning */
+ lookahead_pos = 0;
+
+ if (debug)
+ {
+ debug_message("# Reparsing saved input with actions");
+ debug_message("# Current Symbol is #" + cur_err_token().sym);
+ debug_message("# Current state is #" +
+ ((Symbol)stack.peek()).parse_state);
+ }
+
+ /* continue until we accept or have read all lookahead input */
+ while(!_done_parsing)
+ {
+ /* current state is always on the top of the stack */
+
+ /* look up action out of the current state with the current input */
+ act =
+ get_action(((Symbol)stack.peek()).parse_state, cur_err_token().sym);
+
+ /* decode the action -- > 0 encodes shift */
+ if (act > 0)
+ {
+ /* shift to the encoded state by pushing it on the stack */
+ cur_err_token().parse_state = act-1;
+ cur_err_token().used_by_parser = true;
+ if (debug) debug_shift(cur_err_token());
+ stack.push(cur_err_token());
+ tos++;
+
+ /* advance to the next Symbol, if there is none, we are done */
+ if (!advance_lookahead())
+ {
+ if (debug) debug_message("# Completed reparse");
+
+ /* scan next Symbol so we can continue parse */
+ // BUGFIX by Chris Harris <ckharris@ucsd.edu>:
+ // correct a one-off error by commenting out
+ // this next line.
+ /*cur_token = scan();*/
+
+ /* go back to normal parser */
+ return;
+ }
+
+ if (debug)
+ debug_message("# Current Symbol is #" + cur_err_token().sym);
+ }
+ /* if its less than zero, then it encodes a reduce action */
+ else if (act < 0)
+ {
+ /* perform the action for the reduce */
+ lhs_sym = do_action((-act)-1, this, stack, tos);
+
+ /* look up information about the production */
+ lhs_sym_num = production_tab[(-act)-1][0];
+ handle_size = production_tab[(-act)-1][1];
+
+ if (debug) debug_reduce((-act)-1, lhs_sym_num, handle_size);
+
+ /* pop the handle off the stack */
+ for (int i = 0; i < handle_size; i++)
+ {
+ stack.pop();
+ tos--;
+ }
+
+ /* look up the state to go to from the one popped back to */
+ act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num);
+
+ /* shift to that state */
+ lhs_sym.parse_state = act;
+ lhs_sym.used_by_parser = true;
+ stack.push(lhs_sym);
+ tos++;
+
+ if (debug) debug_message("# Goto state #" + act);
+
+ }
+ /* finally if the entry is zero, we have an error
+ (shouldn't happen here, but...)*/
+ else if (act == 0)
+ {
+ report_fatal_error("Syntax error", lhs_sym);
+ return;
+ }
+ }
+
+
+ }
+
+ /*-----------------------------------------------------------*/
+
+ /** Utility function: unpacks parse tables from strings */
+ protected static short[][] unpackFromStrings(String[] sa)
+ {
+ // Concatanate initialization strings.
+ StringBuffer sb = new StringBuffer(sa[0]);
+ for (int i=1; i<sa.length; i++)
+ sb.append(sa[i]);
+ int n=0; // location in initialization string
+ int size1 = (((int)sb.charAt(n))<<16) | ((int)sb.charAt(n+1)); n+=2;
+ short[][] result = new short[size1][];
+ for (int i=0; i<size1; i++) {
+ int size2 = (((int)sb.charAt(n))<<16) | ((int)sb.charAt(n+1)); n+=2;
+ result[i] = new short[size2];
+ for (int j=0; j<size2; j++)
+ result[i][j] = (short) (sb.charAt(n++)-2);
+ }
+ return result;
+ }
+}
+
diff --git a/src/syntaxParser/java_cup/runtime/virtual_parse_stack.class b/src/syntaxParser/java_cup/runtime/virtual_parse_stack.class
new file mode 100644
index 0000000..1c3435c
--- /dev/null
+++ b/src/syntaxParser/java_cup/runtime/virtual_parse_stack.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/runtime/virtual_parse_stack.java b/src/syntaxParser/java_cup/runtime/virtual_parse_stack.java
new file mode 100644
index 0000000..a4386aa
--- /dev/null
+++ b/src/syntaxParser/java_cup/runtime/virtual_parse_stack.java
@@ -0,0 +1,145 @@
+
+package java_cup.runtime;
+
+import java.util.Stack;
+
+/** This class implements a temporary or "virtual" parse stack that
+ * replaces the top portion of the actual parse stack (the part that
+ * has been changed by some set of operations) while maintaining its
+ * original contents. This data structure is used when the parse needs
+ * to "parse ahead" to determine if a given error recovery attempt will
+ * allow the parse to continue far enough to consider it successful. Once
+ * success or failure of parse ahead is determined the system then
+ * reverts to the original parse stack (which has not actually been
+ * modified). Since parse ahead does not execute actions, only parse
+ * state is maintained on the virtual stack, not full Symbol objects.
+ *
+ * @see java_cup.runtime.lr_parser
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+
+public class virtual_parse_stack {
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constructor to build a virtual stack out of a real stack. */
+ public virtual_parse_stack(Stack shadowing_stack) throws java.lang.Exception
+ {
+ /* sanity check */
+ if (shadowing_stack == null)
+ throw new Exception(
+ "Internal parser error: attempt to create null virtual stack");
+
+ /* set up our internals */
+ real_stack = shadowing_stack;
+ vstack = new Stack();
+ real_next = 0;
+
+ /* get one element onto the virtual portion of the stack */
+ get_from_real();
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The real stack that we shadow. This is accessed when we move off
+ * the bottom of the virtual portion of the stack, but is always left
+ * unmodified.
+ */
+ protected Stack real_stack;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Top of stack indicator for where we leave off in the real stack.
+ * This is measured from top of stack, so 0 would indicate that no
+ * elements have been "moved" from the real to virtual stack.
+ */
+ protected int real_next;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The virtual top portion of the stack. This stack contains Integer
+ * objects with state numbers. This stack shadows the top portion
+ * of the real stack within the area that has been modified (via operations
+ * on the virtual stack). When this portion of the stack becomes empty we
+ * transfer elements from the underlying stack onto this stack.
+ */
+ protected Stack vstack;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Transfer an element from the real to the virtual stack. This assumes
+ * that the virtual stack is currently empty.
+ */
+ protected void get_from_real()
+ {
+ Symbol stack_sym;
+
+ /* don't transfer if the real stack is empty */
+ if (real_next >= real_stack.size()) return;
+
+ /* get a copy of the first Symbol we have not transfered */
+ stack_sym = (Symbol)real_stack.elementAt(real_stack.size()-1-real_next);
+
+ /* record the transfer */
+ real_next++;
+
+ /* put the state number from the Symbol onto the virtual stack */
+ vstack.push(new Integer(stack_sym.parse_state));
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Indicate whether the stack is empty. */
+ public boolean empty()
+ {
+ /* if vstack is empty then we were unable to transfer onto it and
+ the whole thing is empty. */
+ return vstack.empty();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return value on the top of the stack (without popping it). */
+ public int top() throws java.lang.Exception
+ {
+ if (vstack.empty())
+ throw new Exception(
+ "Internal parser error: top() called on empty virtual stack");
+
+ return ((Integer)vstack.peek()).intValue();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Pop the stack. */
+ public void pop() throws java.lang.Exception
+ {
+ if (vstack.empty())
+ throw new Exception(
+ "Internal parser error: pop from empty virtual stack");
+
+ /* pop it */
+ vstack.pop();
+
+ /* if we are now empty transfer an element (if there is one) */
+ if (vstack.empty())
+ get_from_real();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Push a state number onto the stack. */
+ public void push(int state_num)
+ {
+ vstack.push(new Integer(state_num));
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/syntaxParser/java_cup/shift_action.class b/src/syntaxParser/java_cup/shift_action.class
new file mode 100644
index 0000000..db961ff
--- /dev/null
+++ b/src/syntaxParser/java_cup/shift_action.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/shift_action.java b/src/syntaxParser/java_cup/shift_action.java
new file mode 100644
index 0000000..33fc17a
--- /dev/null
+++ b/src/syntaxParser/java_cup/shift_action.java
@@ -0,0 +1,82 @@
+
+package java_cup;
+
+/** This class represents a shift action within the parse table.
+ * The action simply stores the state that it shifts to and responds
+ * to queries about its type.
+ *
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class shift_action extends parse_action {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor.
+ * @param shft_to the state that this action shifts to.
+ */
+ public shift_action(lalr_state shft_to) throws internal_error
+ {
+ /* sanity check */
+ if (shft_to == null)
+ throw new internal_error(
+ "Attempt to create a shift_action to a null state");
+
+ _shift_to = shft_to;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The state we shift to. */
+ protected lalr_state _shift_to;
+
+ /** The state we shift to. */
+ public lalr_state shift_to() {return _shift_to;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Quick access to type of action. */
+ public int kind() {return SHIFT;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality test. */
+ public boolean equals(shift_action other)
+ {
+ return other != null && other.shift_to() == shift_to();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality test. */
+ public boolean equals(Object other)
+ {
+ if (other instanceof shift_action)
+ return equals((shift_action)other);
+ else
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute a hash code. */
+ public int hashCode()
+ {
+ /* use the hash code of the state we are shifting to */
+ return shift_to().hashCode();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString() {return "SHIFT(to state " + shift_to().index() + ")";}
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/syntaxParser/java_cup/simple_calc/Main.java b/src/syntaxParser/java_cup/simple_calc/Main.java
new file mode 100644
index 0000000..21ff5aa
--- /dev/null
+++ b/src/syntaxParser/java_cup/simple_calc/Main.java
@@ -0,0 +1,32 @@
+// Driver for parser
+
+package java_cup.simple_calc;
+
+import java_cup.simple_calc.parser;
+import java_cup.runtime.Symbol;
+
+class Main {
+
+ static boolean do_debug_parse = false;
+
+ static public void main(String[] args) throws java.io.IOException {
+
+ /* create a parsing object */
+ parser parser_obj = new parser(new scanner());
+
+ /* open input files, etc. here */
+ Symbol parse_tree = null;
+
+ try {
+ if (do_debug_parse)
+ parse_tree = parser_obj.debug_parse();
+ else
+ parse_tree = parser_obj.parse();
+ } catch (Exception e) {
+ /* do cleanup here -- possibly rethrow e */
+ } finally {
+ /* do close out here */
+ }
+ }
+}
+
diff --git a/src/syntaxParser/java_cup/simple_calc/parser.cup b/src/syntaxParser/java_cup/simple_calc/parser.cup
new file mode 100644
index 0000000..a88d900
--- /dev/null
+++ b/src/syntaxParser/java_cup/simple_calc/parser.cup
@@ -0,0 +1,55 @@
+// JavaCup specification for a simple expression evaluator (w/ actions)
+
+package java_cup.simple_calc;
+
+import java_cup.runtime.*;
+
+/* Terminals (tokens returned by the scanner). */
+terminal SEMI, PLUS, MINUS, TIMES, DIVIDE, MOD;
+terminal UMINUS, LPAREN, RPAREN;
+terminal Integer NUMBER;
+
+/* Non terminals */
+non terminal Object expr_list, expr_part;
+non terminal Integer expr;
+
+/* Precedences */
+precedence left PLUS, MINUS;
+precedence left TIMES, DIVIDE, MOD;
+precedence left UMINUS, LPAREN;
+
+/* The grammar */
+expr_list ::= expr_list expr_part
+ |
+ expr_part;
+
+expr_part ::= expr:e
+ {: System.out.println("= " + e); :}
+ SEMI
+ ;
+
+expr ::= expr:e1 PLUS expr:e2
+ {: RESULT = new Integer(e1.intValue() + e2.intValue()); :}
+ |
+ expr:e1 MINUS expr:e2
+ {: RESULT = new Integer(e1.intValue() - e2.intValue()); :}
+ |
+ expr:e1 TIMES expr:e2
+ {: RESULT = new Integer(e1.intValue() * e2.intValue()); :}
+ |
+ expr:e1 DIVIDE expr:e2
+ {: RESULT = new Integer(e1.intValue() / e2.intValue()); :}
+ |
+ expr:e1 MOD expr:e2
+ {: RESULT = new Integer(e1.intValue() % e2.intValue()); :}
+ |
+ NUMBER:n
+ {: RESULT = n; :}
+ |
+ MINUS expr:e
+ {: RESULT = new Integer(0 - e.intValue()); :}
+ %prec UMINUS
+ |
+ LPAREN expr:e RPAREN
+ {: RESULT = e; :}
+ ;
diff --git a/src/syntaxParser/java_cup/simple_calc/parser.java b/src/syntaxParser/java_cup/simple_calc/parser.java
new file mode 100644
index 0000000..d6003c7
--- /dev/null
+++ b/src/syntaxParser/java_cup/simple_calc/parser.java
@@ -0,0 +1,318 @@
+
+//----------------------------------------------------
+// The following code was generated by CUP v0.10k
+// Sun Jul 25 13:36:02 EDT 1999
+//----------------------------------------------------
+
+package java_cup.simple_calc;
+
+import java_cup.runtime.*;
+
+/** CUP v0.10k generated parser.
+ * @version Sun Jul 25 13:36:02 EDT 1999
+ */
+public class parser extends java_cup.runtime.lr_parser {
+
+ /** Default constructor. */
+ public parser() {super();}
+
+ /** Constructor which sets the default scanner. */
+ public parser(java_cup.runtime.Scanner s) {super(s);}
+
+ /** Production table. */
+ protected static final short _production_table[][] =
+ unpackFromStrings(new String[] {
+ "\000\015\000\002\003\004\000\002\002\004\000\002\003" +
+ "\003\000\002\006\002\000\002\004\005\000\002\005\005" +
+ "\000\002\005\005\000\002\005\005\000\002\005\005\000" +
+ "\002\005\005\000\002\005\003\000\002\005\004\000\002" +
+ "\005\005" });
+
+ /** Access to production table. */
+ public short[][] production_table() {return _production_table;}
+
+ /** Parse-action table. */
+ protected static final short[][] _action_table =
+ unpackFromStrings(new String[] {
+ "\000\030\000\010\006\004\013\011\015\005\001\002\000" +
+ "\010\006\004\013\011\015\005\001\002\000\020\004\ufff7" +
+ "\005\ufff7\006\ufff7\007\ufff7\010\ufff7\011\ufff7\014\ufff7\001" +
+ "\002\000\012\002\uffff\006\uffff\013\uffff\015\uffff\001\002" +
+ "\000\016\004\ufffe\005\016\006\014\007\020\010\017\011" +
+ "\013\001\002\000\012\002\027\006\004\013\011\015\005" +
+ "\001\002\000\010\006\004\013\011\015\005\001\002\000" +
+ "\016\005\016\006\014\007\020\010\017\011\013\014\015" +
+ "\001\002\000\010\006\004\013\011\015\005\001\002\000" +
+ "\010\006\004\013\011\015\005\001\002\000\020\004\ufff5" +
+ "\005\ufff5\006\ufff5\007\ufff5\010\ufff5\011\ufff5\014\ufff5\001" +
+ "\002\000\010\006\004\013\011\015\005\001\002\000\010" +
+ "\006\004\013\011\015\005\001\002\000\010\006\004\013" +
+ "\011\015\005\001\002\000\020\004\ufffa\005\ufffa\006\ufffa" +
+ "\007\ufffa\010\ufffa\011\ufffa\014\ufffa\001\002\000\020\004" +
+ "\ufff9\005\ufff9\006\ufff9\007\ufff9\010\ufff9\011\ufff9\014\ufff9" +
+ "\001\002\000\020\004\ufffc\005\ufffc\006\ufffc\007\020\010" +
+ "\017\011\013\014\ufffc\001\002\000\020\004\ufffb\005\ufffb" +
+ "\006\ufffb\007\020\010\017\011\013\014\ufffb\001\002\000" +
+ "\020\004\ufff8\005\ufff8\006\ufff8\007\ufff8\010\ufff8\011\ufff8" +
+ "\014\ufff8\001\002\000\012\002\001\006\001\013\001\015" +
+ "\001\001\002\000\004\002\000\001\002\000\004\004\031" +
+ "\001\002\000\012\002\ufffd\006\ufffd\013\ufffd\015\ufffd\001" +
+ "\002\000\020\004\ufff6\005\ufff6\006\ufff6\007\ufff6\010\ufff6" +
+ "\011\ufff6\014\ufff6\001\002" });
+
+ /** Access to parse-action table. */
+ public short[][] action_table() {return _action_table;}
+
+ /** <code>reduce_goto</code> table. */
+ protected static final short[][] _reduce_table =
+ unpackFromStrings(new String[] {
+ "\000\030\000\010\003\007\004\005\005\006\001\001\000" +
+ "\004\005\031\001\001\000\002\001\001\000\002\001\001" +
+ "\000\004\006\027\001\001\000\006\004\025\005\006\001" +
+ "\001\000\004\005\011\001\001\000\002\001\001\000\004" +
+ "\005\024\001\001\000\004\005\023\001\001\000\002\001" +
+ "\001\000\004\005\022\001\001\000\004\005\021\001\001" +
+ "\000\004\005\020\001\001\000\002\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\002\001\001\000\002\001\001\000\002\001\001\000" +
+ "\002\001\001\000\002\001\001" });
+
+ /** Access to <code>reduce_goto</code> table. */
+ public short[][] reduce_table() {return _reduce_table;}
+
+ /** Instance of action encapsulation class. */
+ protected CUP$parser$actions action_obj;
+
+ /** Action encapsulation object initializer. */
+ protected void init_actions()
+ {
+ action_obj = new CUP$parser$actions(this);
+ }
+
+ /** Invoke a user supplied parse action. */
+ public java_cup.runtime.Symbol do_action(
+ int act_num,
+ java_cup.runtime.lr_parser parser,
+ java.util.Stack stack,
+ int top)
+ throws java.lang.Exception
+ {
+ /* call code in generated class */
+ return action_obj.CUP$parser$do_action(act_num, parser, stack, top);
+ }
+
+ /** Indicates start state. */
+ public int start_state() {return 0;}
+ /** Indicates start production. */
+ public int start_production() {return 1;}
+
+ /** <code>EOF</code> Symbol index. */
+ public int EOF_sym() {return 0;}
+
+ /** <code>error</code> Symbol index. */
+ public int error_sym() {return 1;}
+
+}
+
+/** Cup generated class to encapsulate user supplied action code.*/
+class CUP$parser$actions {
+ private final parser parser;
+
+ /** Constructor */
+ CUP$parser$actions(parser parser) {
+ this.parser = parser;
+ }
+
+ /** Method with the actual generated action code. */
+ public final java_cup.runtime.Symbol CUP$parser$do_action(
+ int CUP$parser$act_num,
+ java_cup.runtime.lr_parser CUP$parser$parser,
+ java.util.Stack CUP$parser$stack,
+ int CUP$parser$top)
+ throws java.lang.Exception
+ {
+ /* Symbol object for return from actions */
+ java_cup.runtime.Symbol CUP$parser$result;
+
+ /* select the action based on the action number */
+ switch (CUP$parser$act_num)
+ {
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 12: // expr ::= LPAREN expr RPAREN
+ {
+ Integer RESULT = null;
+ int eleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int eright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ Integer e = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+ RESULT = e;
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 11: // expr ::= MINUS expr
+ {
+ Integer RESULT = null;
+ int eleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int eright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ Integer e = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = new Integer(0 - e.intValue());
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 10: // expr ::= NUMBER
+ {
+ Integer RESULT = null;
+ int nleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int nright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ Integer n = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = n;
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 9: // expr ::= expr MOD expr
+ {
+ Integer RESULT = null;
+ int e1left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left;
+ int e1right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right;
+ Integer e1 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+ int e2left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int e2right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ Integer e2 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = new Integer(e1.intValue() % e2.intValue());
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 8: // expr ::= expr DIVIDE expr
+ {
+ Integer RESULT = null;
+ int e1left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left;
+ int e1right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right;
+ Integer e1 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+ int e2left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int e2right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ Integer e2 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = new Integer(e1.intValue() / e2.intValue());
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 7: // expr ::= expr TIMES expr
+ {
+ Integer RESULT = null;
+ int e1left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left;
+ int e1right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right;
+ Integer e1 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+ int e2left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int e2right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ Integer e2 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = new Integer(e1.intValue() * e2.intValue());
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 6: // expr ::= expr MINUS expr
+ {
+ Integer RESULT = null;
+ int e1left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left;
+ int e1right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right;
+ Integer e1 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+ int e2left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int e2right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ Integer e2 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = new Integer(e1.intValue() - e2.intValue());
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 5: // expr ::= expr PLUS expr
+ {
+ Integer RESULT = null;
+ int e1left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left;
+ int e1right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right;
+ Integer e1 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+ int e2left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int e2right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ Integer e2 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = new Integer(e1.intValue() + e2.intValue());
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 4: // expr_part ::= expr NT$0 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$0
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+ int eleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left;
+ int eright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right;
+ Integer e = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(2/*expr_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 3: // NT$0 ::=
+ {
+ Object RESULT = null;
+ int eleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int eright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ Integer e = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ System.out.println("= " + e);
+ CUP$parser$result = new java_cup.runtime.Symbol(4/*NT$0*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 2: // expr_list ::= expr_part
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(1/*expr_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 1: // $START ::= expr_list EOF
+ {
+ Object RESULT = null;
+ int start_valleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int start_valright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ Object start_val = (Object)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+ RESULT = start_val;
+ CUP$parser$result = new java_cup.runtime.Symbol(0/*$START*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ /* ACCEPT */
+ CUP$parser$parser.done_parsing();
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 0: // expr_list ::= expr_list expr_part
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(1/*expr_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /* . . . . . .*/
+ default:
+ throw new Exception(
+ "Invalid action number found in internal parse table");
+
+ }
+ }
+}
+
diff --git a/src/syntaxParser/java_cup/simple_calc/scanner.java b/src/syntaxParser/java_cup/simple_calc/scanner.java
new file mode 100644
index 0000000..f8f850a
--- /dev/null
+++ b/src/syntaxParser/java_cup/simple_calc/scanner.java
@@ -0,0 +1,63 @@
+// Simple Example Scanner Class
+
+package java_cup.simple_calc;
+
+import java_cup.runtime.Symbol;
+
+public class scanner implements java_cup.runtime.Scanner {
+ final java.io.InputStream instream;
+
+ public scanner(java.io.InputStream is) throws java.io.IOException {
+ instream = is;
+ }
+ public scanner() throws java.io.IOException { this(System.in); }
+
+ /* single lookahead character */
+ protected int next_char = -2;
+
+ /* advance input by one character */
+ protected void advance()
+ throws java.io.IOException
+ { next_char = instream.read(); }
+
+ /* initialize the scanner */
+ private void init()
+ throws java.io.IOException
+ { advance(); }
+
+ /* recognize and return the next complete token */
+ public Symbol next_token()
+ throws java.io.IOException
+ {
+ if (next_char==-2) init(); // set stuff up first time we are called.
+ for (;;)
+ switch (next_char)
+ {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ /* parse a decimal integer */
+ int i_val = 0;
+ do {
+ i_val = i_val * 10 + (next_char - '0');
+ advance();
+ } while (next_char >= '0' && next_char <= '9');
+ return new Symbol(sym.NUMBER, new Integer(i_val));
+
+ case ';': advance(); return new Symbol(sym.SEMI);
+ case '+': advance(); return new Symbol(sym.PLUS);
+ case '-': advance(); return new Symbol(sym.MINUS);
+ case '*': advance(); return new Symbol(sym.TIMES);
+ case '/': advance(); return new Symbol(sym.DIVIDE);
+ case '%': advance(); return new Symbol(sym.MOD);
+ case '(': advance(); return new Symbol(sym.LPAREN);
+ case ')': advance(); return new Symbol(sym.RPAREN);
+
+ case -1: return new Symbol(sym.EOF);
+
+ default:
+ /* in this simple scanner we just ignore everything else */
+ advance();
+ break;
+ }
+ }
+};
diff --git a/src/syntaxParser/java_cup/simple_calc/sym.java b/src/syntaxParser/java_cup/simple_calc/sym.java
new file mode 100644
index 0000000..2584f2f
--- /dev/null
+++ b/src/syntaxParser/java_cup/simple_calc/sym.java
@@ -0,0 +1,25 @@
+
+//----------------------------------------------------
+// The following code was generated by CUP v0.10k
+// Sun Jul 25 13:36:02 EDT 1999
+//----------------------------------------------------
+
+package java_cup.simple_calc;
+
+/** CUP generated class containing symbol constants. */
+public class sym {
+ /* terminals */
+ public static final int SEMI = 2;
+ public static final int EOF = 0;
+ public static final int DIVIDE = 6;
+ public static final int NUMBER = 11;
+ public static final int error = 1;
+ public static final int UMINUS = 8;
+ public static final int MINUS = 4;
+ public static final int TIMES = 5;
+ public static final int LPAREN = 9;
+ public static final int RPAREN = 10;
+ public static final int MOD = 7;
+ public static final int PLUS = 3;
+}
+
diff --git a/src/syntaxParser/java_cup/sym.class b/src/syntaxParser/java_cup/sym.class
new file mode 100644
index 0000000..97397bd
--- /dev/null
+++ b/src/syntaxParser/java_cup/sym.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/sym.java b/src/syntaxParser/java_cup/sym.java
new file mode 100644
index 0000000..9810a3d
--- /dev/null
+++ b/src/syntaxParser/java_cup/sym.java
@@ -0,0 +1,43 @@
+
+//----------------------------------------------------
+// The following code was generated by CUP v0.10k
+// Sun Jul 25 13:35:26 EDT 1999
+//----------------------------------------------------
+
+package java_cup;
+
+/** CUP generated class containing symbol constants. */
+public class sym {
+ /* terminals */
+ public static final int NON = 8;
+ public static final int NONTERMINAL = 27;
+ public static final int STAR = 15;
+ public static final int SEMI = 13;
+ public static final int CODE = 4;
+ public static final int EOF = 0;
+ public static final int NONASSOC = 23;
+ public static final int LEFT = 21;
+ public static final int PACKAGE = 2;
+ public static final int COLON = 17;
+ public static final int WITH = 11;
+ public static final int IMPORT = 3;
+ public static final int error = 1;
+ public static final int COLON_COLON_EQUALS = 18;
+ public static final int COMMA = 14;
+ public static final int DOT = 16;
+ public static final int SCAN = 10;
+ public static final int ID = 28;
+ public static final int INIT = 9;
+ public static final int PARSER = 6;
+ public static final int TERMINAL = 7;
+ public static final int PRECEDENCE = 20;
+ public static final int LBRACK = 25;
+ public static final int RBRACK = 26;
+ public static final int PERCENT_PREC = 24;
+ public static final int START = 12;
+ public static final int RIGHT = 22;
+ public static final int BAR = 19;
+ public static final int ACTION = 5;
+ public static final int CODE_STRING = 29;
+}
+
diff --git a/src/syntaxParser/java_cup/symbol.class b/src/syntaxParser/java_cup/symbol.class
new file mode 100644
index 0000000..04d222d
--- /dev/null
+++ b/src/syntaxParser/java_cup/symbol.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/symbol.java b/src/syntaxParser/java_cup/symbol.java
new file mode 100644
index 0000000..94d8b7d
--- /dev/null
+++ b/src/syntaxParser/java_cup/symbol.java
@@ -0,0 +1,107 @@
+package java_cup;
+
+/** This abstract class serves as the base class for grammar symbols (i.e.,
+ * both terminals and non-terminals). Each symbol has a name string, and
+ * a string giving the type of object that the symbol will be represented by
+ * on the runtime parse stack. In addition, each symbol maintains a use count
+ * in order to detect symbols that are declared but never used, and an index
+ * number that indicates where it appears in parse tables (index numbers are
+ * unique within terminals or non terminals, but not across both).
+ *
+ * @see java_cup.terminal
+ * @see java_cup.non_terminal
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+public abstract class symbol {
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param nm the name of the symbol.
+ * @param tp a string with the type name.
+ */
+ public symbol(String nm, String tp)
+ {
+ /* sanity check */
+ if (nm == null) nm = "";
+
+ /* apply default if no type given */
+ if (tp == null) tp = "Object";
+
+ _name = nm;
+ _stack_type = tp;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with default type.
+ * @param nm the name of the symbol.
+ */
+ public symbol(String nm)
+ {
+ this(nm, null);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** String for the human readable name of the symbol. */
+ protected String _name;
+
+ /** String for the human readable name of the symbol. */
+ public String name() {return _name;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** String for the type of object used for the symbol on the parse stack. */
+ protected String _stack_type;
+
+ /** String for the type of object used for the symbol on the parse stack. */
+ public String stack_type() {return _stack_type;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of how many times the symbol appears in productions. */
+ protected int _use_count = 0;
+
+ /** Count of how many times the symbol appears in productions. */
+ public int use_count() {return _use_count;}
+
+ /** Increment the use count. */
+ public void note_use() {_use_count++;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Index of this symbol (terminal or non terminal) in the parse tables.
+ * Note: indexes are unique among terminals and unique among non terminals,
+ * however, a terminal may have the same index as a non-terminal, etc.
+ */
+ protected int _index;
+
+ /** Index of this symbol (terminal or non terminal) in the parse tables.
+ * Note: indexes are unique among terminals and unique among non terminals,
+ * however, a terminal may have the same index as a non-terminal, etc.
+ */
+ public int index() {return _index;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Indicate if this is a non-terminal. Here in the base class we
+ * don't know, so this is abstract.
+ */
+ public abstract boolean is_non_term();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ return name();
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/syntaxParser/java_cup/symbol_part.class b/src/syntaxParser/java_cup/symbol_part.class
new file mode 100644
index 0000000..1b81faa
--- /dev/null
+++ b/src/syntaxParser/java_cup/symbol_part.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/symbol_part.java b/src/syntaxParser/java_cup/symbol_part.java
new file mode 100644
index 0000000..9142b5f
--- /dev/null
+++ b/src/syntaxParser/java_cup/symbol_part.java
@@ -0,0 +1,100 @@
+package java_cup;
+
+/** This class represents a part of a production which is a symbol (terminal
+ * or non terminal). This simply maintains a reference to the symbol in
+ * question.
+ *
+ * @see java_cup.production
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class symbol_part extends production_part {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param sym the symbol that this part is made up of.
+ * @param lab an optional label string for the part.
+ */
+ public symbol_part(symbol sym, String lab) throws internal_error
+ {
+ super(lab);
+
+ if (sym == null)
+ throw new internal_error(
+ "Attempt to construct a symbol_part with a null symbol");
+ _the_symbol = sym;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with no label.
+ * @param sym the symbol that this part is made up of.
+ */
+ public symbol_part(symbol sym) throws internal_error
+ {
+ this(sym,null);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The symbol that this part is made up of. */
+ protected symbol _the_symbol;
+
+ /** The symbol that this part is made up of. */
+ public symbol the_symbol() {return _the_symbol;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Respond that we are not an action part. */
+ public boolean is_action() { return false; }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(symbol_part other)
+ {
+ return other != null && super.equals(other) &&
+ the_symbol().equals(other.the_symbol());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof symbol_part))
+ return false;
+ else
+ return equals((symbol_part)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a hash code. */
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ (the_symbol()==null ? 0 : the_symbol().hashCode());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ if (the_symbol() != null)
+ return super.toString() + the_symbol();
+ else
+ return super.toString() + "$$MISSING-SYMBOL$$";
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/syntaxParser/java_cup/symbol_set.class b/src/syntaxParser/java_cup/symbol_set.class
new file mode 100644
index 0000000..903718d
--- /dev/null
+++ b/src/syntaxParser/java_cup/symbol_set.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/symbol_set.java b/src/syntaxParser/java_cup/symbol_set.java
new file mode 100644
index 0000000..a1aec10
--- /dev/null
+++ b/src/syntaxParser/java_cup/symbol_set.java
@@ -0,0 +1,231 @@
+
+package java_cup;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/** This class represents a set of symbols and provides a series of
+ * set operations to manipulate them.
+ *
+ * @see java_cup.symbol
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class symbol_set {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constructor for an empty set. */
+ public symbol_set() { }
+
+ /** Constructor for cloning from another set.
+ * @param other the set we are cloning from.
+ */
+ public symbol_set(symbol_set other) throws internal_error
+ {
+ not_null(other);
+ _all = (Hashtable)other._all.clone();
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** A hash table to hold the set. Symbols are keyed using their name string.
+ */
+ protected Hashtable _all = new Hashtable(11);
+
+ /** Access to all elements of the set. */
+ public Enumeration all() {return _all.elements();}
+
+ /** size of the set */
+ public int size() {return _all.size();}
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Helper function to test for a null object and throw an exception
+ * if one is found.
+ * @param obj the object we are testing.
+ */
+ protected void not_null(Object obj) throws internal_error
+ {
+ if (obj == null)
+ throw new internal_error("Null object used in set operation");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if the set contains a particular symbol.
+ * @param sym the symbol we are looking for.
+ */
+ public boolean contains(symbol sym) {return _all.containsKey(sym.name());}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if this set is an (improper) subset of another.
+ * @param other the set we are testing against.
+ */
+ public boolean is_subset_of(symbol_set other) throws internal_error
+ {
+ not_null(other);
+
+ /* walk down our set and make sure every element is in the other */
+ for (Enumeration e = all(); e.hasMoreElements(); )
+ if (!other.contains((symbol)e.nextElement()))
+ return false;
+
+ /* they were all there */
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if this set is an (improper) superset of another.
+ * @param other the set we are are testing against.
+ */
+ public boolean is_superset_of(symbol_set other) throws internal_error
+ {
+ not_null(other);
+ return other.is_subset_of(this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a single symbol to the set.
+ * @param sym the symbol we are adding.
+ * @return true if this changes the set.
+ */
+ public boolean add(symbol sym) throws internal_error
+ {
+ Object previous;
+
+ not_null(sym);
+
+ /* put the object in */
+ previous = _all.put(sym.name(),sym);
+
+ /* if we had a previous, this is no change */
+ return previous == null;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove a single symbol if it is in the set.
+ * @param sym the symbol we are removing.
+ */
+ public void remove(symbol sym) throws internal_error
+ {
+ not_null(sym);
+ _all.remove(sym.name());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add (union) in a complete set.
+ * @param other the set we are adding in.
+ * @return true if this changes the set.
+ */
+ public boolean add(symbol_set other) throws internal_error
+ {
+ boolean result = false;
+
+ not_null(other);
+
+ /* walk down the other set and do the adds individually */
+ for (Enumeration e = other.all(); e.hasMoreElements(); )
+ result = add((symbol)e.nextElement()) || result;
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove (set subtract) a complete set.
+ * @param other the set we are removing.
+ */
+ public void remove(symbol_set other) throws internal_error
+ {
+ not_null(other);
+
+ /* walk down the other set and do the removes individually */
+ for (Enumeration e = other.all(); e.hasMoreElements(); )
+ remove((symbol)e.nextElement());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(symbol_set other)
+ {
+ if (other == null || other.size() != size()) return false;
+
+ /* once we know they are the same size, then improper subset does test */
+ try {
+ return is_subset_of(other);
+ } catch (internal_error e) {
+ /* can't throw the error (because super class doesn't), so we crash */
+ e.crash();
+ return false;
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof symbol_set))
+ return false;
+ else
+ return equals((symbol_set)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute a hash code. */
+ public int hashCode()
+ {
+ int result = 0;
+ int cnt;
+ Enumeration e;
+
+ /* hash together codes from at most first 5 elements */
+ for (e = all(), cnt=0 ; e.hasMoreElements() && cnt<5; cnt++)
+ result ^= ((symbol)e.nextElement()).hashCode();
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+ boolean comma_flag;
+
+ result = "{";
+ comma_flag = false;
+ for (Enumeration e = all(); e.hasMoreElements(); )
+ {
+ if (comma_flag)
+ result += ", ";
+ else
+ comma_flag = true;
+
+ result += ((symbol)e.nextElement()).name();
+ }
+ result += "}";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
+
diff --git a/src/syntaxParser/java_cup/terminal.class b/src/syntaxParser/java_cup/terminal.class
new file mode 100644
index 0000000..8f9b423
--- /dev/null
+++ b/src/syntaxParser/java_cup/terminal.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/terminal.java b/src/syntaxParser/java_cup/terminal.java
new file mode 100644
index 0000000..e1a40aa
--- /dev/null
+++ b/src/syntaxParser/java_cup/terminal.java
@@ -0,0 +1,169 @@
+package java_cup;
+
+import java_cup.assoc;
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/** This class represents a terminal symbol in the grammar. Each terminal
+ * has a textual name, an index, and a string which indicates the type of
+ * object it will be implemented with at runtime (i.e. the class of object
+ * that will be returned by the scanner and pushed on the parse stack to
+ * represent it).
+ *
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+public class terminal extends symbol {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param nm the name of the terminal.
+ * @param tp the type of the terminal.
+ */
+ public terminal(String nm, String tp, int precedence_side, int precedence_num)
+ {
+ /* superclass does most of the work */
+ super(nm, tp);
+
+ /* add to set of all terminals and check for duplicates */
+ Object conflict = _all.put(nm,this);
+ if (conflict != null)
+ // can't throw an execption here because this is used in static
+ // initializers, so we do a crash instead
+ // was:
+ // throw new internal_error("Duplicate terminal (" + nm + ") created");
+ (new internal_error("Duplicate terminal (" + nm + ") created")).crash();
+
+ /* assign a unique index */
+ _index = next_index++;
+
+ /* set the precedence */
+ _precedence_num = precedence_num;
+ _precedence_side = precedence_side;
+
+ /* add to by_index set */
+ _all_by_index.put(new Integer(_index), this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor for non-precedented terminal
+ */
+
+ public terminal(String nm, String tp)
+ {
+ this(nm, tp, assoc.no_prec, -1);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with default type.
+ * @param nm the name of the terminal.
+ */
+ public terminal(String nm)
+ {
+ this(nm, null);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*------------------- Class Variables ---------------------*/
+ /*-----------------------------------------------------------*/
+
+ private int _precedence_num;
+ private int _precedence_side;
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Table of all terminals. Elements are stored using name strings as
+ * the key
+ */
+ protected static Hashtable _all = new Hashtable();
+
+ /** Access to all terminals. */
+ public static Enumeration all() {return _all.elements();}
+
+ /** Lookup a terminal by name string. */
+ public static terminal find(String with_name)
+ {
+ if (with_name == null)
+ return null;
+ else
+ return (terminal)_all.get(with_name);
+ }
+
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Table of all terminals indexed by their index number. */
+ protected static Hashtable _all_by_index = new Hashtable();
+
+ /** Lookup a terminal by index. */
+ public static terminal find(int indx)
+ {
+ Integer the_indx = new Integer(indx);
+
+ return (terminal)_all_by_index.get(the_indx);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Total number of terminals. */
+ public static int number() {return _all.size();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Static counter to assign unique index. */
+ protected static int next_index = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Special terminal for end of input. */
+ public static final terminal EOF = new terminal("EOF");
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** special terminal used for error recovery */
+ public static final terminal error = new terminal("error");
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Report this symbol as not being a non-terminal. */
+ public boolean is_non_term()
+ {
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ return super.toString() + "[" + index() + "]";
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** get the precedence of a terminal */
+ public int precedence_num() {
+ return _precedence_num;
+ }
+ public int precedence_side() {
+ return _precedence_side;
+ }
+
+ /** set the precedence of a terminal */
+ public void set_precedence(int p, int new_prec) {
+ _precedence_side = p;
+ _precedence_num = new_prec;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
diff --git a/src/syntaxParser/java_cup/terminal_set.class b/src/syntaxParser/java_cup/terminal_set.class
new file mode 100644
index 0000000..fd0453e
--- /dev/null
+++ b/src/syntaxParser/java_cup/terminal_set.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/terminal_set.java b/src/syntaxParser/java_cup/terminal_set.java
new file mode 100644
index 0000000..e921cb5
--- /dev/null
+++ b/src/syntaxParser/java_cup/terminal_set.java
@@ -0,0 +1,253 @@
+
+package java_cup;
+
+import java.util.BitSet;
+
+/** A set of terminals implemented as a bitset.
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class terminal_set {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constructor for an empty set. */
+ public terminal_set()
+ {
+ /* allocate the bitset at what is probably the right size */
+ _elements = new BitSet(terminal.number());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor for cloning from another set.
+ * @param other the set we are cloning from.
+ */
+ public terminal_set(terminal_set other)
+ throws internal_error
+ {
+ not_null(other);
+ _elements = (BitSet)other._elements.clone();
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constant for the empty set. */
+ public static final terminal_set EMPTY = new terminal_set();
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Bitset to implement the actual set. */
+ protected BitSet _elements;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Helper function to test for a null object and throw an exception if
+ * one is found.
+ * @param obj the object we are testing.
+ */
+ protected void not_null(Object obj) throws internal_error
+ {
+ if (obj == null)
+ throw new internal_error("Null object used in set operation");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if the set is empty. */
+ public boolean empty()
+ {
+ return equals(EMPTY);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if the set contains a particular terminal.
+ * @param sym the terminal symbol we are looking for.
+ */
+ public boolean contains(terminal sym)
+ throws internal_error
+ {
+ not_null(sym);
+ return _elements.get(sym.index());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Given its index determine if the set contains a particular terminal.
+ * @param indx the index of the terminal in question.
+ */
+ public boolean contains(int indx)
+ {
+ return _elements.get(indx);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if this set is an (improper) subset of another.
+ * @param other the set we are testing against.
+ */
+ public boolean is_subset_of(terminal_set other)
+ throws internal_error
+ {
+ not_null(other);
+
+ /* make a copy of the other set */
+ BitSet copy_other = (BitSet)other._elements.clone();
+
+ /* and or in */
+ copy_other.or(_elements);
+
+ /* if it hasn't changed, we were a subset */
+ return copy_other.equals(other._elements);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if this set is an (improper) superset of another.
+ * @param other the set we are testing against.
+ */
+ public boolean is_superset_of(terminal_set other)
+ throws internal_error
+ {
+ not_null(other);
+ return other.is_subset_of(this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a single terminal to the set.
+ * @param sym the terminal being added.
+ * @return true if this changes the set.
+ */
+ public boolean add(terminal sym)
+ throws internal_error
+ {
+ boolean result;
+
+ not_null(sym);
+
+ /* see if we already have this */
+ result = _elements.get(sym.index());
+
+ /* if not we add it */
+ if (!result)
+ _elements.set(sym.index());
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove a terminal if it is in the set.
+ * @param sym the terminal being removed.
+ */
+ public void remove(terminal sym)
+ throws internal_error
+ {
+ not_null(sym);
+ _elements.clear(sym.index());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add (union) in a complete set.
+ * @param other the set being added.
+ * @return true if this changes the set.
+ */
+ public boolean add(terminal_set other)
+ throws internal_error
+ {
+ not_null(other);
+
+ /* make a copy */
+ BitSet copy = (BitSet)_elements.clone();
+
+ /* or in the other set */
+ _elements.or(other._elements);
+
+ /* changed if we are not the same as the copy */
+ return !_elements.equals(copy);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if this set intersects another.
+ * @param other the other set in question.
+ */
+ public boolean intersects(terminal_set other)
+ throws internal_error
+ {
+ not_null(other);
+
+ /* make a copy of the other set */
+ BitSet copy = (BitSet)other._elements.clone();
+
+ /* xor out our values */
+ copy.xor(this._elements);
+
+ /* see if its different */
+ return !copy.equals(other._elements);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(terminal_set other)
+ {
+ if (other == null)
+ return false;
+ else
+ return _elements.equals(other._elements);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof terminal_set))
+ return false;
+ else
+ return equals((terminal_set)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to string. */
+ public String toString()
+ {
+ String result;
+ boolean comma_flag;
+
+ result = "{";
+ comma_flag = false;
+ for (int t = 0; t < terminal.number(); t++)
+ {
+ if (_elements.get(t))
+ {
+ if (comma_flag)
+ result += ", ";
+ else
+ comma_flag = true;
+
+ result += terminal.find(t).name();
+ }
+ }
+ result += "}";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
diff --git a/src/syntaxParser/java_cup/version.class b/src/syntaxParser/java_cup/version.class
new file mode 100644
index 0000000..336e099
--- /dev/null
+++ b/src/syntaxParser/java_cup/version.class
Binary files differ
diff --git a/src/syntaxParser/java_cup/version.java b/src/syntaxParser/java_cup/version.java
new file mode 100644
index 0000000..06600b5
--- /dev/null
+++ b/src/syntaxParser/java_cup/version.java
@@ -0,0 +1,55 @@
+
+package java_cup;
+
+/** This class contains version and authorship information.
+ * It contains only static data elements and basically just a central
+ * place to put this kind of information so it can be updated easily
+ * for each release.
+ *
+ * Version numbers used here are broken into 3 parts: major, minor, and
+ * update, and are written as v<major>.<minor>.<update> (e.g. v0.10a).
+ * Major numbers will change at the time of major reworking of some
+ * part of the system. Minor numbers for each public release or
+ * change big enough to cause incompatibilities. Finally update
+ * letter will be incremented for small bug fixes and changes that
+ * probably wouldn't be noticed by a user.
+ *
+ * @version last updated: 12/22/97 [CSA]
+ * @author Frank Flannery
+ */
+
+public class version {
+ /** The major version number. */
+ public static final int major = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The minor version number. */
+ public static final int minor = 10;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The update letter. */
+ public static final char update = 'k';
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** String for the current version. */
+ public static final String version_str = "v" + major + "." + minor + update;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Full title of the system */
+ public static final String title_str = "CUP " + version_str;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Name of the author */
+ public static final String author_str =
+ "Scott E. Hudson, Frank Flannery, and C. Scott Ananian";
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The command name normally used to invoke this program */
+ public static final String program_name = "java_cup";
+}
diff --git a/src/syntaxParser/processcoverage.xsd b/src/syntaxParser/processcoverage.xsd
new file mode 100644
index 0000000..77fbb93
--- /dev/null
+++ b/src/syntaxParser/processcoverage.xsd
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:gml="http://www.opengis.net/gml" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified" version="0.0.1" xml:lang="en">
+
+
+
+
+
+
+
+
+
+
+
+ <!-- REMOVE EVERYTHING ALREADY IMPLEMENTED FOR VISUAL SIMPLICITY -->
+
+
+
+
+
+
+
+
+
+ <xs:complexType name="CoverageAxisType">
+ <xs:annotation>
+ <xs:documentation/>
+ </xs:annotation>
+ <xs:choice>
+ <xs:element name="coverageExpr" type="CoverageExprType"/>
+ <xs:element name="axis" type="xs:integer"/>
+ </xs:choice>
+ </xs:complexType>
+
+
+
+
+
+
+ <!-- =========================================================== -->
+ <xs:complexType name="CondenseExprType">
+ <xs:annotation>
+ <xs:documentation/>
+ </xs:annotation>
+ <xs:choice>
+ <xs:element name="generalCondenseExpr" type="GeneralCondenseExprType"/>
+ </xs:choice>
+ </xs:complexType>
+
+
+
+
+ <xs:complexType name="GeneralCondenseExprType">
+ <xs:annotation>
+ <xs:documentation/>
+ </xs:annotation>
+ <xs:sequence>
+ <!-- FIXME: tbd -->
+ <xs:element name="condenseVar" type="NameType"/>
+ <xs:element name="condenseOp" type="CondenseOpType"/>
+ <xs:element name="coverageExpr" type="CoverageExprType"/>
+ </xs:sequence>
+ </xs:complexType>
+
+
+ <!-- =========================================================== -->
+ <xs:simpleType name="CondenseOpType">
+ <xs:annotation>
+ <xs:documentation/>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="plus"/>
+ <xs:enumeration value="max"/>
+ <xs:enumeration value="min"/>
+ <xs:enumeration value="and"/>
+ <xs:enumeration value="or"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+
+ <!-- =========================================================== -->
+ <xs:complexType name="CoordinateTransformExprType">
+ <xs:annotation>
+ <xs:documentation/>
+ </xs:annotation>
+ <xs:choice>
+ <xs:element name="spatialTransformExpr" type="SpatialTransformExprType"/>
+ <xs:element name="temporalTransformExpr" type="TemporalTransformExprType"/>
+ </xs:choice>
+ </xs:complexType>
+
+
+
+ <!-- =========================================================== -->
+ <xs:complexType name="SpatialTransformExprType">
+ <xs:annotation>
+ <xs:documentation/>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="coverageExpr" type="CoverageExprType"/>
+ <xs:element name="point" type="SpatialPointType"/>
+ <!-- FIXME: ref="gml:Point" -->
+ <xs:element name="crsName" type="xs:string"/>
+ <!-- FIXME: gml:CodeListType -->
+ </xs:sequence>
+ </xs:complexType>
+
+
+ <!-- =========================================================== -->
+ <xs:complexType name="TemporalTransformExprType">
+ <xs:annotation>
+ <xs:documentation/>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="coverageExpr" type="CoverageExprType"/>
+ <xs:element name="point" type="xs:string"/>
+ </xs:sequence>
+ </xs:complexType>
+ <!-- =========================================================== -->
+
+
+
+
+
+
+
+ <!-- FIXME: should use ows:Point; have scratched something, TBR -->
+ <xs:complexType name="GridPointType">
+ <xs:annotation>
+ <xs:documentation/>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element type="GridCoordinateElementType" maxOccurs="unbounded" name="coordinate"/>
+ </xs:sequence>
+ </xs:complexType>
+ <!-- =========================================================== -->
+ <!-- FIXME: TBR -->
+ <xs:complexType name="GridCoordinateElementType">
+ <xs:annotation>
+ <xs:documentation/>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="axisName" type="NameType"/>
+ <xs:element name="value" type="xs:integer"/>
+ </xs:sequence>
+ </xs:complexType>
+ <!-- =========================================================== -->
+ <!-- FIXME: should use ows:Point; have scratched something, TBR -->
+ <xs:complexType name="SpatialPointType">
+ <xs:annotation>
+ <xs:documentation/>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element type="SpatialCoordinateElementType" maxOccurs="unbounded" name="coordinate"/>
+ </xs:sequence>
+ </xs:complexType>
+ <!-- =========================================================== -->
+ <!-- FIXME: TBR -->
+ <xs:complexType name="SpatialCoordinateElementType">
+ <xs:annotation>
+ <xs:documentation/>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="axisName" type="NameType"/>
+ <xs:element name="value" type="xs:double"/>
+ </xs:sequence>
+ </xs:complexType>
+ <!-- =========================================================== -->
+ <!-- FIXME: TBR -->
+ <!-- note that we don't need the above sequence as there is always at most 1 time axis -->
+ <xs:complexType name="TemporalCoordinateType">
+ <xs:annotation>
+ <xs:documentation/>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="axisName" type="NameType"/>
+ <xs:element name="value" type="xs:string"/>
+ <!-- FIXME: ows:time or so -->
+ </xs:sequence>
+ </xs:complexType>
+
+
+
+
+
+
+
+
+
+</xs:schema>
diff --git a/src/syntaxParser/request.wcps b/src/syntaxParser/request.wcps
new file mode 100644
index 0000000..a38e04a
--- /dev/null
+++ b/src/syntaxParser/request.wcps
@@ -0,0 +1 @@
+for m in (climate_temperature) return encode ( m , png )
diff --git a/src/syntaxParser/run.bat b/src/syntaxParser/run.bat
new file mode 100644
index 0000000..3e61552
--- /dev/null
+++ b/src/syntaxParser/run.bat
@@ -0,0 +1,8 @@
+java JLex.Main wcps.lex
+java java_cup.Main -parser WCPSParser -symbols WCPSSymbol <wcps.cup
+javac wcps.lex.java
+javac WCPSParser.java WCPSSymbol.java WCPSRequestProcessor.java
+java WCPSRequestProcessor
+
+
+
diff --git a/src/syntaxParser/test_requests.txt b/src/syntaxParser/test_requests.txt
new file mode 100644
index 0000000..4cd3050
--- /dev/null
+++ b/src/syntaxParser/test_requests.txt
@@ -0,0 +1,101 @@
+for F in (CD, C) return encode( A, B)
+
+for F in (CD, C), C in (Q,S,R) return encode( A, B)
+
+for F in (CD, C), C in (Q,S,R) return encode( A, B, blah)
+
+
+
+for F in (CD, C), C in (Q,S,R) return res( simple )
+
+for F in (CD, C), C in (Q,S,R) return dim( simple )
+
+for F in (CD, C), C in (Q,S,R) return null( simple )
+
+for F in (CD, C), C in (Q,S,R) return cellType( simple )
+
+for F in (CD, C), C in (Q,S,R) return crs( simple )
+
+
+
+
+for F in (CD, C), C in (Q,S,R) return crs( encode( A, B) )
+
+for F in (CD, C), C in (Q,S,R) return crs( encode( A, B, param) )
+
+
+
+
+for F in (CD, C), C in (Q,S,R) return ( crs( encode( A, B) ) )
+
+for F in (CD, C), C in (Q,S,R) return (( crs( encode( A, B) ) ))
+
+
+
+
+
+
+
+for F in (CD, C), C in (Q,S,R) return crs( setNull( simple, 454 ) )
+
+for F in (CD, C), C in (Q,S,R) return crs( setNull( simple, 41.6666 ) )
+
+for F in (CD, C), C in (Q,S,R) return crs( setNull( simple, TRUE ) )
+
+
+
+
+for F in (CD, C), C in (Q,S,R) return crs( setInterpolation( simple, nearest-neighbor ) )
+
+for F in (CD, C), C in (Q,S,R) return crs( setInterpolation( simple, bilinear ) )
+
+for F in (CD, C), C in (Q,S,R) return crs( setInterpolation( simple, lost-area ) )
+
+for F in (CD, C), C in (Q,S,R) return crs( setInterpolation( simple, bicubic ) )
+
+for F in (CD, C), C in (Q,S,R) return crs( setInterpolation( simple, barycentric ) )
+
+for F in (CD, C), C in (Q,S,R) return crs( setInterpolation( setNull( simple, 41.6666 ), barycentric ) )
+
+
+
+
+
+// wont take it now because of the crsName given as a simple String
+for F in (CD, C), C in (Q,S,R) return crs( setCrs( tan(angle), WGS:84 )
+
+// instead (plain String)
+for F in (CD, C), C in (Q,S,R) return crs( setCrs( tan(angle), CRSNAME )
+
+
+
+for F in (CD, C), C in (Q,S,R) return crs( setAxis( tan(angle), x, 3.3, 5.5432 ) )
+
+for F in (CD, C), C in (Q,S,R) return crs( setAxis( tan(angle), y, 345.3, 12.5432 ) )
+
+
+
+
+for F in (CD, C), C in (Q,S,R) return crs( setAxis( tan(cos(sin(arctan(arccos(arcsin(sinh(tanh(cosh(angle))))))))), x, 3.3, 5.5432 ) )
+
+
+for F in (CD, C), C in (Q,S,R) return crs( setAxis( ln(exp(log(valuevalue))), y, 345.3, 12.5432 ) )
+
+
+
+
+for F in (CD, C), C in (Q,S,R) return encode ( FGF + A * WE, format)
+
+for F in (CD, C), C in (Q,S,R) return encode ( FGF + A * WE and this or that xor those, format)
+
+
+
+
+
+for F in (CD, C), C in (Q,S,R) return encode ( trim(FGF + A * WE, z,4,78888), format)
+
+for F in (CD, C), C in (Q,S,R) return encode ( sect(FGF + A * WE, y, 4), format, extraP)
+
+
+
+
diff --git a/src/syntaxParser/tmp/META-INF/MANIFEST.MF b/src/syntaxParser/tmp/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..8ade325
--- /dev/null
+++ b/src/syntaxParser/tmp/META-INF/MANIFEST.MF
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+Ant-Version: Apache Ant 1.6.2
+Created-By: 1.5.0_07-b03 (Sun Microsystems Inc.)
+Main-Class: java_cup/Main
+Class-Path: java-cup-11a-runtime.jar
+
diff --git a/src/syntaxParser/wcps.cup b/src/syntaxParser/wcps.cup
new file mode 100644
index 0000000..a6dfb95
--- /dev/null
+++ b/src/syntaxParser/wcps.cup
@@ -0,0 +1,415 @@
+/*
+Author: *, Sorin Stancu-Mara
+Date (last update): 7 Feb 2007
+History:
+07 02 2007 smsorin Updated to WCPS 1.0.0
+This file contains the Java CUP implementation for the WCPS language parser and ProcessCoverage XML request
+generator.
+Sections include:
+ * Terminal symbols declaration from the JLex Lexycal declaration file
+ * Non Terminal symbols definitions
+ * Precedence rules to avoid Shift/Reduce conflicts in the grammar projections
+ * The grammar specification itself
+
+
+
+things to check / todo :
+ * crsName production : its now just as a simple string; CRS NAMES have certain formats, eg: EPSG:NNN
+ * axisName production : its now just as a simple integer; this was adapted from the example XML processCoverage request available for
+ testing.
+ * structSelection one item missing ????
+ * condende expression not specified in the grammar as current implementation in WCPS is not usable
+ * String are not specified by using "" characters ("string"). The parser will work anyways as a string with "" characters will
+ be recognized as a string anyway
+
+Terminals (tokens returned by the lexycal scanner). */
+package syntaxParser;
+import java_cup.runtime.*;
+import syntaxParser.SyntaxErrorException;
+
+parser code {:
+/* public void syntax_error(Symbol cur_token) {
+ report_error("Syntax error at line " + (cur_token.left+1) +
+ ", column " + cur_token.right,
+ new SyntaxErrorException(cur_token.left + 1, cur_token.right +1));
+ }*/
+ public void report_fatal_error(String message,
+ Object token) throws Exception {
+ report_error(message, null);
+ Symbol sym = (Symbol) token;
+ throw new SyntaxErrorException(sym.left + 1, sym.right + 1, message);
+ }
+:}
+
+terminal String ID, LPAREN, RPAREN, PLUS, MULTI, MINUS, DIVIDE, FOR, IN, RETURN, COMMA, ENCODE, STORE, CONDENSE, OVER, USING, MAX, MIN, AND, OR, COLON,
+STRUCT, LBRACE, RBRACE, NEAREST, CTRANSFORM,
+SIN , COS , TAN , SINH , COSH , TANH , ARCSIN , ARCCOS , ARCTAN,EXP , LOG , LN, ABS, SQRT, DOT, BOOL, CHAR,
+UNSIGNEDCHAR, SHORT, UNSIGNEDSHORT, LONG, UNSIGNEDLONG, FLOAT, DOUBLE, NOT, BIT, XOR, EQUALS, NOTEQUALS, OVERLAY, GT,LT,GTE,LTE, LBRACKET, RBRACKET, TRIM,
+SCALE, SOME, ADD, ALL, COUNT, AVG,TRUE, FALSE, WHERE, IDENTIFIER, IMAGECRS, IMAGECRSDOMAIN, CRSSET, GENERALDOMAIN, NULLDEFAULT, NULLSET,
+INTERPOLATIONDEFAULT, INTERPOLATIONSET, STRING, SETNULLDEFAULT, SETNULLSET, SETINTERPOLATIONDEFAULT, SETINTERPOLATIONSET, COMPLEX, COMPLEX2, SLICE, EXTEND,
+LINEAR, QUADRATIC, CUBIC, FULL, NONE, HALF, OTHER, COVERAGE, VALUES, X, Y, Z, TIME, ABSTRACT, SETCRSSET;
+
+terminal Integer NUMBER;
+terminal Float FLOATNUMBER;
+
+/* Non terminals */
+non terminal WCPSRequest wcpsRequest ;
+non terminal ForClause forClause;
+non terminal ForClauseElements forClauseElements;
+non terminal WhereClause whereClause;
+non terminal ReturnClause returnClause;
+non terminal CoverageList coverageList;
+non terminal ProcessingExpr processingExpr;
+non terminal EncodedCoverageExpr encodedCoverageExpr;
+non terminal StoreExpr storeExpr;
+non terminal ScalarExpr scalarExpr;
+non terminal GetMetaDataExpr getMetaDataExpr;
+non terminal BooleanScalarExpr booleanScalarExpr;
+non terminal String booleanLiteral;
+non terminal NumericScalarExpr numericScalarExpr;
+non terminal CoverageExpr coverageExpr;
+non terminal SetMetaDataExpr setMetaDataExpr;
+non terminal InducedExpr inducedExpr;
+non terminal UnaryInducedExpr unaryInducedExpr;
+non terminal UnaryArithMeticExpr unaryArithMeticExpr;
+non terminal ExponentialExpr exponentialExpr;
+non terminal TrigonometricExpr trigonometricExpr;
+non terminal BooleanExpr booleanExpr;
+non terminal CastExpr castExpr;
+non terminal SelectExpr fieldExpr;
+non terminal BinaryInducedExpr binaryInducedExpr;
+non terminal String binaryInducedOp;
+non terminal SubsetExpr subsetExpr;
+non terminal TrimExpr trimExpr;
+non terminal SliceExpr sliceExpr;
+non terminal ExtendExpr extendExpr;
+non terminal ScaleExpr scaleExpr;
+non terminal CrsTransformExpr crsTransformExpr;
+non terminal AxisIntervalList axisIntervalList;
+non terminal AxisIntervalElement axisIntervalElement;
+non terminal AxisPointList axisPointList;
+non terminal AxisPointList axisPointEnum;
+non terminal AxisPointElement axisPointElement;
+non terminal String axisPoint;
+non terminal AxisCrsList axisCrsList;
+non terminal AxisCrsList axisCrsEnum;
+non terminal AxisCrsElement axisCrsElement;
+non terminal FieldInterpolationList fieldInterpolationList;
+non terminal FieldInterpolationList fieldInterpolationEnum;
+non terminal FieldInterpolationElement fieldInterpolationElement;
+non terminal InterpolationMethodList interpolationMethodList;
+non terminal InterpolationMethodList interpolationMethodEnum;
+non terminal FieldInterpolationMethod interpolationMethod;
+non terminal String interpolationType;
+non terminal String nullResistence;
+non terminal CoverageConstructorExpr coverageConstructorExpr;
+non terminal VariableList variableList;
+non terminal String axisType;
+non terminal CondenseExpr condenseExpr;
+non terminal ReduceExpr reduceExpr;
+non terminal GeneralCondenseExpr generalCondenseExpr;
+non terminal String condenseOpType;
+non terminal RangeValue rangeValue;
+non terminal StructuredLiteral structuredLiteral;
+non terminal RangeValueList rangeValueList;
+non terminal String atomicLiteral;
+non terminal String complexLiteral;
+non terminal String fieldName;
+non terminal CrsList crsList;
+non terminal CrsList crsEnum;
+non terminal String cellType;
+non terminal String generalId;
+
+//non terminal CoverageConstExpr converageConstExpr; // TODO(smsorin): not defined in WCPS !!
+
+
+
+/* Precedence rules to avoid Shift/Reduce conflicts*/
+precedence left AND, OR, XOR;
+precedence left PLUS, MINUS;
+precedence left MULTI, DIVIDE;
+precedence nonassoc EQUALS, LT, GT, LTE, GTE, NOTEQUALS;
+precedence nonassoc NOT, DOT, OVERLAY;
+precedence left LBRACKET, LBRACE, COMMA, RBRACKET, RBRACE;
+
+/* The grammar specification */
+
+wcpsRequest ::= forClause:e1 returnClause:e2 {: RESULT = new WCPSRequest(e1,e2); :}
+ | forClause:e1 whereClause:e2 returnClause:e3 {: RESULT = new WCPSRequest(e1,e2,e3); :}
+ ;
+forClause ::= FOR forClauseElements:e1 {: RESULT = new ForClause(e1); :}
+ ;
+forClauseElements ::= ID:e1 IN LPAREN coverageList:e2 RPAREN {: RESULT = new ForClauseElements(e1,e2); :}
+ | ID:e1 IN LPAREN coverageList:e2 RPAREN COMMA forClauseElements:e3 {: RESULT = new ForClauseElements(e1,e2,e3); :}
+ ;
+whereClause ::= WHERE booleanScalarExpr:e1 {: RESULT = new WhereClause(e1); :}
+ ;
+returnClause ::= RETURN processingExpr:e1 {: RESULT = new ReturnClause(e1); :}
+ ;
+coverageList ::= ID:e1 {: RESULT = new CoverageList(e1); :}
+ | ID:e1 COMMA coverageList:e2 {: RESULT = new CoverageList(e1,e2); :}
+ ;
+processingExpr ::= encodedCoverageExpr:e1 {: RESULT = new ProcessingExpr(e1); :}
+ | storeExpr:e1 {: RESULT = new ProcessingExpr(e1); :}
+ | scalarExpr:e1 {: RESULT = new ProcessingExpr(e1); :}
+ ;
+encodedCoverageExpr ::= ENCODE LPAREN coverageExpr:e1 COMMA ID:e2 RPAREN {: RESULT = new EncodedCoverageExpr(e1,e2); :}
+ | ENCODE LPAREN coverageExpr:e1 COMMA ID:e2 COMMA ID:e3 RPAREN {: RESULT = new EncodedCoverageExpr(e1,e2,e3); :}
+ ;
+storeExpr ::= STORE LPAREN encodedCoverageExpr:e1 RPAREN {: RESULT = new StoreExpr(e1); :}
+ ;
+scalarExpr ::= getMetaDataExpr:e1 {: RESULT = new ScalarExpr(e1); :}
+ | condenseExpr:e1 {: RESULT = new ScalarExpr(e1); :}
+ | booleanScalarExpr:e1 {: RESULT = new ScalarExpr(e1); :}
+ | numericScalarExpr:e1 {: RESULT = new ScalarExpr(e1); :}
+ | LPAREN scalarExpr:e1 RPAREN {: RESULT = new ScalarExpr(e1); :}
+ ;
+getMetaDataExpr ::= IDENTIFIER:op LPAREN coverageExpr:e1 RPAREN {: RESULT = new GetMetaDataExpr(op, e1); :}
+ | IMAGECRS:op LPAREN coverageExpr:e1 RPAREN {: RESULT = new GetMetaDataExpr(op, e1); :}
+ | IMAGECRSDOMAIN:op LPAREN coverageExpr:e1 RPAREN {: RESULT = new GetMetaDataExpr(op, e1); :}
+ | CRSSET:op LPAREN coverageExpr:e1 RPAREN {: RESULT = new GetMetaDataExpr(op, e1); :}
+ | GENERALDOMAIN:op LPAREN coverageExpr:e1 RPAREN {: RESULT = new GetMetaDataExpr(op, e1); :}
+ | NULLDEFAULT:op LPAREN coverageExpr:e1 RPAREN {: RESULT = new GetMetaDataExpr(op, e1); :}
+ | NULLSET:op LPAREN coverageExpr:e1 RPAREN {: RESULT = new GetMetaDataExpr(op,e1); :}
+ | INTERPOLATIONDEFAULT:op LPAREN coverageExpr:e1 COMMA fieldName:f1 RPAREN {: RESULT = new GetMetaDataExpr(op,e1,f1); :}
+ | INTERPOLATIONSET:op LPAREN coverageExpr:e1 COMMA fieldName:f1 RPAREN {: RESULT = new GetMetaDataExpr(op, e1,f1); :}
+ ;
+booleanScalarExpr ::= booleanLiteral:e {: RESULT = new BooleanScalarExpr(e); :}
+ | NOT:op booleanScalarExpr:e {: RESULT = new BooleanScalarExpr(op,e); :}
+ | booleanScalarExpr:e1 AND:op booleanScalarExpr:e2 {: RESULT = new BooleanScalarExpr(op,e1,e2); :}
+ | booleanScalarExpr:e1 OR:op booleanScalarExpr:e2 {: RESULT = new BooleanScalarExpr(op,e1,e2); :}
+ | booleanScalarExpr:e1 XOR:op booleanScalarExpr:e2 {: RESULT = new BooleanScalarExpr(op,e1,e2); :}
+ ;
+booleanLiteral ::= TRUE:e {: RESULT = new String(e); :}
+ | FALSE:e {: RESULT = new String(e); :}
+ ;
+
+numericScalarExpr ::= NUMBER:e {: RESULT = new NumericScalarExpr(e.toString()); :}
+ | FLOATNUMBER:e {: RESULT = new NumericScalarExpr(e.toString()); :}
+ | MINUS:op numericScalarExpr:e1 {: RESULT = new NumericScalarExpr(op, e1); :}
+ | PLUS:op numericScalarExpr:e1 {: RESULT = new NumericScalarExpr(op,e1); :}
+ | numericScalarExpr:e1 PLUS:op numericScalarExpr:e2 {: RESULT = new NumericScalarExpr(op,e1,e2); :}
+ | numericScalarExpr:e1 MINUS:op numericScalarExpr:e2 {: RESULT = new NumericScalarExpr(op,e1,e2); :}
+ | numericScalarExpr:e1 DIVIDE:op numericScalarExpr:e2 {: RESULT = new NumericScalarExpr(op,e1,e2); :}
+ | numericScalarExpr:e1 MULTI:op numericScalarExpr:e2 {: RESULT = new NumericScalarExpr(op,e1,e2); :}
+ | ABS:op LPAREN numericScalarExpr:e1 RPAREN {: RESULT = new NumericScalarExpr(op,e1); :}
+ ;
+coverageExpr ::= ID:e1 {: RESULT = new CoverageExpr(e1); :}
+ | setMetaDataExpr:e2 {: RESULT = new CoverageExpr(e2); :}
+ | inducedExpr:e2 {: RESULT = new CoverageExpr(e2); :}
+ | subsetExpr:e2 {: RESULT = new CoverageExpr(e2); :}
+ | crsTransformExpr:e2 {: RESULT = new CoverageExpr(e2); :}
+ | scaleExpr:e2 {: RESULT = new CoverageExpr(e2); :}
+// TODO(smsorin): Update once the definition is available. | coverageConstExpr:e1 {: RESULT = new CoverageExpr(e1); :}
+ | coverageConstructorExpr:e1 {: RESULT = new CoverageExpr(e1); :}
+ | LPAREN coverageExpr:e2 RPAREN {: RESULT = new CoverageExpr(e2); :}
+ ;
+setMetaDataExpr ::= SETNULLDEFAULT:op LPAREN coverageExpr:e1 COMMA rangeValue:r1 RPAREN {: RESULT = new SetMetaDataExpr(op, e1,r1); :}
+ | SETNULLSET:op LPAREN coverageExpr:e1 COMMA rangeValueList:r1 RPAREN {: RESULT = new SetMetaDataExpr(op,e1,r1); :}
+ | SETINTERPOLATIONDEFAULT:op LPAREN coverageExpr:e1 COMMA fieldName:f1 COMMA interpolationMethod:i1 RPAREN
+ {: RESULT = new SetMetaDataExpr(op, e1,(IParseTreeNode)i1, f1); :}
+ | SETINTERPOLATIONSET:op LPAREN coverageExpr:e1 COMMA fieldName:f1 COMMA interpolationMethodList:i1 RPAREN
+ {: RESULT = new SetMetaDataExpr(op, e1,(IParseTreeNode)i1, f1); :}
+ | SETCRSSET:op LPAREN coverageExpr:e1 COMMA crsList:cs1 RPAREN {: RESULT = new SetMetaDataExpr(op, e1,cs1); :}
+ ;
+crsList ::= LBRACE crsEnum:list RBRACE {: RESULT = list; :}
+ ;
+crsEnum ::= ID:crs {: RESULT = new CrsList(crs); :}
+ | ID:crs COMMA crsEnum:n {: RESULT = new CrsList(crs, n); :}
+ ;
+inducedExpr ::= unaryInducedExpr:e1 {: RESULT = new InducedExpr(e1); :}
+ | binaryInducedExpr:e1 {: RESULT = new InducedExpr(e1); :}
+ ;
+unaryInducedExpr ::= unaryArithMeticExpr:e1 {: RESULT = new UnaryInducedExpr(e1); :}
+ | exponentialExpr:e1 {: RESULT = new UnaryInducedExpr(e1); :}
+ | trigonometricExpr:e1 {: RESULT = new UnaryInducedExpr(e1); :}
+ | booleanExpr:e1 {: RESULT = new UnaryInducedExpr(e1); :}
+ | castExpr:e1 {: RESULT = new UnaryInducedExpr(e1); :}
+ | fieldExpr:e1 {: RESULT = new UnaryInducedExpr(e1); :}
+ ;
+unaryArithMeticExpr ::= PLUS:e coverageExpr:e1 {: RESULT = new UnaryArithMeticExpr(e1,e); :}
+ | MINUS:e coverageExpr:e1 {: RESULT = new UnaryArithMeticExpr(e1,e); :}
+ | SQRT:e LPAREN coverageExpr:e1 RPAREN {: RESULT = new UnaryArithMeticExpr(e1,e); :}
+ | ABS:e LPAREN coverageExpr:e1 RPAREN {: RESULT = new UnaryArithMeticExpr(e1,e); :}
+ ;
+exponentialExpr ::= EXP:e LPAREN coverageExpr:e1 RPAREN {: RESULT = new ExponentialExpr(e1,e); :}
+ | LOG:e LPAREN coverageExpr:e1 RPAREN {: RESULT = new ExponentialExpr(e1,e); :}
+ | LN:e LPAREN coverageExpr:e1 RPAREN {: RESULT = new ExponentialExpr(e1,e); :}
+ ;
+trigonometricExpr ::= SIN:e LPAREN coverageExpr:e1 RPAREN {: RESULT = new TrigonometricExpr(e1,e); :}
+ | COS:e LPAREN coverageExpr:e1 RPAREN {: RESULT = new TrigonometricExpr(e1,e); :}
+ | TAN:e LPAREN coverageExpr:e1 RPAREN {: RESULT = new TrigonometricExpr(e1,e); :}
+ | SINH:e LPAREN coverageExpr:e1 RPAREN {: RESULT = new TrigonometricExpr(e1,e); :}
+ | COSH:e LPAREN coverageExpr:e1 RPAREN {: RESULT = new TrigonometricExpr(e1,e); :}
+ | TANH:e LPAREN coverageExpr:e1 RPAREN {: RESULT = new TrigonometricExpr(e1,e); :}
+ | ARCSIN:e LPAREN coverageExpr:e1 RPAREN {: RESULT = new TrigonometricExpr(e1,e); :}
+ | ARCCOS:e LPAREN coverageExpr:e1 RPAREN {: RESULT = new TrigonometricExpr(e1,e); :}
+ | ARCTAN:e LPAREN coverageExpr:e1 RPAREN {: RESULT = new TrigonometricExpr(e1,e); :}
+ ;
+booleanExpr ::= NOT:e coverageExpr:e1 {: RESULT = new BooleanExpr(e1,e); :}
+ | BIT:e LPAREN coverageExpr:e1 COMMA NUMBER:e2 RPAREN {: RESULT = new BooleanExpr(e1,e2,e); :}
+ ;
+castExpr ::= LPAREN cellType:e1 RPAREN coverageExpr:e2 {: RESULT = new CastExpr(e2,e1); :}
+ ;
+cellType ::= BOOL:e {: RESULT = new String(e); :}
+ | CHAR:e {: RESULT = new String(e); :}
+ | UNSIGNEDCHAR:e {: RESULT = new String(e); :}
+ | SHORT:e {: RESULT = new String(e); :}
+ | UNSIGNEDSHORT:e {: RESULT = new String(e); :}
+ | LONG:e {: RESULT = new String(e); :}
+ | UNSIGNEDLONG:e {: RESULT = new String(e); :}
+ | FLOAT:e {: RESULT = e.toString(); :}
+ | DOUBLE:e {: RESULT = new String(e); :}
+ | COMPLEX:e {: RESULT = new String(e); :}
+ | COMPLEX2:e {: RESULT = new String(e); :}
+ ;
+fieldExpr ::= coverageExpr:e1 DOT fieldName:e2 {: RESULT = new SelectExpr(e1,e2); :}
+ ;
+fieldName ::= NUMBER:e {: RESULT = e.toString(); :}
+ | ID:e {: RESULT = new String(e); :}
+ ;
+binaryInducedExpr ::= coverageExpr:e1 binaryInducedOp:op coverageExpr:e2 {: RESULT = new BinaryInducedExpr(op, e1, e2); :}
+ | coverageExpr:e1 binaryInducedOp:op rangeValue:rv1 {: RESULT = new BinaryInducedExpr(op, e1, rv1, 1); :}
+ | rangeValue:rv1 binaryInducedOp:op coverageExpr:e1 {: RESULT = new BinaryInducedExpr(op, rv1, e1, -1); :}
+ ;
+binaryInducedOp ::= PLUS {: RESULT = new String("plus"); :}
+ | MINUS {: RESULT = new String("minus"); :}
+ | MULTI {: RESULT = new String("mult"); :}
+ | DIVIDE {: RESULT = new String("div"); :}
+ | AND {: RESULT = new String("and"); :}
+ | OR {: RESULT = new String("or"); :}
+ | XOR {: RESULT = new String("xor"); :}
+ | EQUALS {: RESULT = new String("equals"); :}
+ | LT {: RESULT = new String("lessThan"); :}
+ | GT {: RESULT = new String("greaterThan"); :}
+ | LTE {: RESULT = new String("lessOrEqual"); :}
+ | GTE {: RESULT = new String("greaterOrEqual"); :}
+ | NOTEQUALS {: RESULT = new String("notEqual"); :}
+ | OVERLAY {: RESULT = new String("overlay"); :}
+ ;
+subsetExpr ::= trimExpr:e1 {: RESULT = new SubsetExpr(e1); :}
+ | sliceExpr:e1 {: RESULT = new SubsetExpr(e1); :}
+ | extendExpr:e1 {: RESULT = new SubsetExpr(e1); :}
+ ;
+trimExpr ::= coverageExpr:e1 LBRACKET axisIntervalList:ail RBRACKET {: RESULT = new TrimExpr(e1, ail); :}
+ | TRIM LPAREN coverageExpr:e1 COMMA axisIntervalList:ail RPAREN {: RESULT = new TrimExpr(e1,ail); :}
+ ;
+sliceExpr ::= coverageExpr:e1 LBRACKET axisPointList:apl RBRACKET {: RESULT = new SliceExpr(e1, apl); :}
+ | SLICE LPAREN coverageExpr:e1 COMMA LBRACE axisPointList:apl RBRACE RPAREN {: RESULT = new SliceExpr(e1, apl); :}
+ ;
+extendExpr ::= EXTEND LPAREN coverageExpr:e1 COMMA axisIntervalList:ail RPAREN {: RESULT = new ExtendExpr(e1, ail); :}
+ ;
+scaleExpr ::= SCALE LPAREN coverageExpr:e1 COMMA axisIntervalList:ail COMMA fieldInterpolationList:fil RPAREN
+ {: RESULT = new ScaleExpr(e1,ail,fil); :}
+ ;
+crsTransformExpr ::= CTRANSFORM LPAREN coverageExpr:e1 COMMA axisCrsList:ail COMMA fieldInterpolationList:fil RPAREN
+ {: RESULT = new CrsTransformExpr(e1,ail,fil); :}
+ ;
+axisIntervalList ::= axisIntervalElement:elem COMMA axisIntervalList:n {: RESULT = new AxisIntervalList(elem, n); :}
+ | axisIntervalElement:elem {: RESULT = new AxisIntervalList(elem); :}
+ ;
+axisIntervalElement ::= generalId:name LPAREN axisPoint:lo COLON axisPoint:hi RPAREN {: RESULT = new AxisIntervalElement(name, lo, hi); :}
+ | generalId:name COLON ID:crsName LPAREN axisPoint:lo COLON axisPoint:hi RPAREN {: RESULT = new AxisIntervalElement(name, crsName, lo, hi); :}
+ ;
+axisPointList ::= axisPointElement:elem {: RESULT = new AxisPointList(elem); :}
+ | axisPointElement:elem COMMA axisPointList:n {: RESULT = new AxisPointList(elem, n); :}
+ ;
+axisPointElement ::= generalId:axisName LPAREN axisPoint:ap RPAREN {: RESULT = new AxisPointElement(axisName, ap); :}
+ | generalId:axisName COLON ID:crsName LPAREN axisPoint:ap RPAREN {: RESULT = new AxisPointElement(axisName, crsName, ap); :}
+ ;
+axisPoint ::= NUMBER:e {: RESULT = e.toString(); :}
+// numericScalarExpr:e {: RESULT = e.toXML(); :} The schema doesn't actually allow this
+// | STRING:e {: RESULT = new String(e); :}
+ ;
+
+axisCrsList ::= LBRACE axisCrsEnum:ace RBRACE {: RESULT = ace; :}
+ ;
+axisCrsEnum ::= axisCrsElement:elem {: RESULT = new AxisCrsList(elem); :}
+ | axisCrsElement:elem COMMA axisCrsEnum:n {: RESULT = new AxisCrsList(elem, n); :}
+ ;
+axisCrsElement ::= ID:axis COLON ID:crs {: RESULT = new AxisCrsElement(axis, crs); :}
+ ;
+fieldInterpolationList ::= LBRACE fieldInterpolationEnum:fie RBRACE {: RESULT = fie; :}
+ ;
+fieldInterpolationEnum ::= fieldInterpolationElement:elem {: RESULT = new FieldInterpolationList(elem); :}
+ | fieldInterpolationElement:elem COMMA fieldInterpolationEnum:n {: RESULT = new FieldInterpolationList(elem, n); :}
+ ;
+fieldInterpolationElement ::= fieldName:name COLON interpolationMethod:method {: RESULT = new FieldInterpolationElement(name, method); :}
+ ;
+interpolationMethodList ::= LBRACE interpolationMethodEnum:list RBRACE {: RESULT = list; :}
+ ;
+interpolationMethodEnum ::= interpolationMethod:elem {: RESULT = new InterpolationMethodList(elem); :}
+ | interpolationMethod:elem COMMA interpolationMethodEnum:n {: RESULT = new InterpolationMethodList(elem,n); :}
+ ;
+interpolationMethod ::= LPAREN interpolationType:type COLON nullResistence:resistence RPAREN {: RESULT = new FieldInterpolationMethod(type, resistence); :}
+ ;
+interpolationType ::= NEAREST:e {: RESULT = new String(e); :}
+ | LINEAR:e {: RESULT = new String(e); :}
+ | QUADRATIC:e {: RESULT = new String(e); :}
+ | CUBIC:e {: RESULT = new String(e); :}
+ ;
+nullResistence ::= FULL:e {: RESULT = new String(e); :}
+ | NONE:e {: RESULT = new String(e); :}
+ | HALF:e {: RESULT = new String(e); :}
+ | OTHER:e {: RESULT = new String(e); :}
+ ;
+coverageConstructorExpr ::= COVERAGE fieldName:f OVER variableList:vl VALUES scalarExpr:se {: RESULT = new CoverageConstructorExpr(f, vl, se); :}
+ ;
+variableList ::= axisType:at ID:varName IN LPAREN NUMBER:lo COLON NUMBER:hi RPAREN COMMA variableList:n
+ {: RESULT = new VariableList(at,varName, lo.toString(), hi.toString(), n); :}
+ | axisType:at ID:varName IN LPAREN NUMBER:lo COLON NUMBER:hi RPAREN
+ {: RESULT = new VariableList(at,varName, lo.toString(), hi.toString()); :}
+
+ ;
+axisType ::= X:t {: RESULT = new String(t); :}
+ | Y:t {: RESULT = new String(t); :}
+ | Z:t {: RESULT = new String(t); :}
+ | TIME:t {: RESULT = new String(t); :}
+ | ABSTRACT:t {: RESULT = new String(t); :}
+ ;
+condenseExpr ::= reduceExpr:e {: RESULT = new CondenseExpr(e); :}
+ | generalCondenseExpr:e {: RESULT = new CondenseExpr(e); :}
+ ;
+reduceExpr ::= ALL:e1 LPAREN coverageExpr:e RPAREN {: RESULT = new ReduceExpr(e,e1); :}
+ | SOME:e1 LPAREN coverageExpr:e RPAREN {: RESULT = new ReduceExpr(e,e1); :}
+ | ADD:e1 LPAREN coverageExpr:e RPAREN {: RESULT = new ReduceExpr(e,e1); :}
+ | COUNT:e1 LPAREN coverageExpr:e RPAREN {: RESULT = new ReduceExpr(e,e1); :}
+ | AVG:e1 LPAREN coverageExpr:e RPAREN {: RESULT = new ReduceExpr(e,e1); :}
+ | MIN:e1 LPAREN coverageExpr:e RPAREN {: RESULT = new ReduceExpr(e,e1); :}
+ | MAX:e1 LPAREN coverageExpr:e RPAREN {: RESULT = new ReduceExpr(e,e1); :}
+ ;
+generalCondenseExpr ::= CONDENSE condenseOpType:op OVER variableList:vl USING scalarExpr:se {: RESULT = new GeneralCondenseExpr(op, vl, se); :}
+ | CONDENSE condenseOpType:op OVER variableList:vl WHERE booleanScalarExpr:be USING scalarExpr:se
+ {: RESULT = new GeneralCondenseExpr(op, vl, be, se); :}
+ ;
+condenseOpType ::= PLUS:op {: RESULT = new String(op); :}
+ | MULTI:op {: RESULT = new String(op); :}
+ | MAX:op {: RESULT = new String(op); :}
+ | MIN:op {: RESULT = new String(op); :}
+ | AND:op {: RESULT = new String(op); :}
+ | OR:op {: RESULT = new String(op); :}
+ ;
+rangeValue ::= structuredLiteral:sl {: RESULT = new RangeValue(sl); :}
+ | atomicLiteral:al {: RESULT = new RangeValue(al); :}
+ ;
+structuredLiteral ::= LBRACE rangeValueList:rvl RBRACE {: RESULT = new StructuredLiteral(rvl); :}
+ | STRUCT LBRACE rangeValueList:rvl RBRACE {: RESULT = new StructuredLiteral(rvl); :}
+ ;
+rangeValueList ::= rangeValue:elem {: RESULT = new RangeValueList(elem); :}
+ | rangeValue:elem COMMA rangeValueList:next {: RESULT = new RangeValueList(elem, next); :}
+ ;
+atomicLiteral ::= booleanLiteral:e {: RESULT = new String(e); :}
+ | NUMBER:e {: RESULT = e.toString(); :}
+ | FLOATNUMBER:e {: RESULT = e.toString(); :}
+ | complexLiteral:e {: RESULT = new String(e); :}
+// | STRING:e {: RESULT = new String(e); :}
+ ;
+complexLiteral ::= COMPLEX LPAREN FLOATNUMBER:f1 COMMA FLOATNUMBER:f2 RPAREN {: RESULT = new String(f1 + " + " + f2 + "i"); :}
+ ;
+
+generalId ::= ID:s {: RESULT = new String(s); :}
+ | X:s {: RESULT = new String(s); :}
+ | Y:s {: RESULT = new String(s); :}
+ | Z:s {: RESULT = new String(s); :}
+ | TIME:s {: RESULT = new String(s); :}
+ ;
diff --git a/src/syntaxParser/wcps.lex b/src/syntaxParser/wcps.lex
new file mode 100644
index 0000000..94fad48
--- /dev/null
+++ b/src/syntaxParser/wcps.lex
@@ -0,0 +1,157 @@
+/*
+ WCPS JLex specification - author: Mattia Parigiani
+
+ This is the JLex specification file for the WCPS abstract grammar. The JLex executable produces a Scanner.java source file which encapsulated
+ all symbol and token definition and which is needed by the Java CUP parser
+
+ This file specifies all possible tokens / symbols that may appear in a WCPS request
+
+ New symbols may be added following the same syntax standard
+
+*/
+
+
+
+
+
+/*
+ Required declarations for source generator.
+ Make sure you know what you are doing if you wish to modify these declarations
+*/
+
+package syntaxParser;
+import java_cup.runtime.*;
+import java.io.*;
+%%
+%notunix
+%implements java_cup.runtime.Scanner
+%type Symbol
+%function next_token
+%public
+%class WCPSScanner
+%eofval{ return null;
+%eofval}
+%line
+%char
+
+IDENTIFIER = [a-zA-Z][a-zA-Z0-9_]*
+FLOATNUMBER = [-+]?[0-9]+[.]?[0-9]+
+NUMBER = [0-9]+
+STRING = [a-zA-Z]*
+
+
+%%
+"+" { return new Symbol(WCPSSymbol.PLUS, yyline, yychar, yytext()); }
+"*" { return new Symbol(WCPSSymbol.MULTI, yyline, yychar, yytext()); }
+"/" { return new Symbol(WCPSSymbol.DIVIDE, yyline, yychar, yytext()); }
+"-" { return new Symbol(WCPSSymbol.MINUS, yyline, yychar, yytext()); }
+"(" { return new Symbol(WCPSSymbol.LPAREN, yyline, yychar, yytext()); }
+")" { return new Symbol(WCPSSymbol.RPAREN, yyline, yychar, yytext()); }
+"{" { return new Symbol(WCPSSymbol.LBRACE, yyline, yychar, yytext()); }
+"}" { return new Symbol(WCPSSymbol.RBRACE, yyline, yychar, yytext()); }
+"struct" { return new Symbol(WCPSSymbol.STRUCT, yyline, yychar, yytext()); }
+"sin" { return new Symbol(WCPSSymbol.SIN, yyline, yychar, yytext()); }
+"cos" { return new Symbol(WCPSSymbol.COS, yyline, yychar, yytext()); }
+"tan" { return new Symbol(WCPSSymbol.TAN, yyline, yychar, yytext()); }
+"sinh" { return new Symbol(WCPSSymbol.SINH, yyline, yychar, yytext()); }
+"cosh" { return new Symbol(WCPSSymbol.COSH, yyline, yychar, yytext()); }
+"tanh" { return new Symbol(WCPSSymbol.TANH, yyline, yychar, yytext()); }
+"arcsin" { return new Symbol(WCPSSymbol.ARCSIN, yyline, yychar, yytext()); }
+"arccos" { return new Symbol(WCPSSymbol.ARCCOS, yyline, yychar, yytext()); }
+"arctan" { return new Symbol(WCPSSymbol.ARCTAN, yyline, yychar, yytext()); }
+"exp" { return new Symbol(WCPSSymbol.EXP, yyline, yychar, yytext()); }
+"log" { return new Symbol(WCPSSymbol.LOG, yyline, yychar, yytext()); }
+"ln" { return new Symbol(WCPSSymbol.LN, yyline, yychar, yytext()); }
+"abs" { return new Symbol(WCPSSymbol.ABS, yyline, yychar, yytext()); }
+"sqrt" { return new Symbol(WCPSSymbol.SQRT, yyline, yychar, yytext()); }
+":" { return new Symbol(WCPSSymbol.COLON, yyline, yychar, yytext()); }
+"." { return new Symbol(WCPSSymbol.DOT, yyline, yychar, yytext()); }
+"return" { return new Symbol(WCPSSymbol.RETURN, yyline, yychar, yytext()) ;}
+"for" { return new Symbol(WCPSSymbol.FOR, yyline, yychar, yytext()) ;}
+"in" { return new Symbol(WCPSSymbol.IN, yyline, yychar, yytext()) ; }
+"," { return new Symbol(WCPSSymbol.COMMA, yyline, yychar, yytext()); }
+"encode" { return new Symbol(WCPSSymbol.ENCODE, yyline, yychar, yytext()) ; }
+"condense" { return new Symbol(WCPSSymbol.CONDENSE, yyline, yychar, yytext()) ; }
+"over" { return new Symbol(WCPSSymbol.OVER, yyline, yychar, yytext()) ; }
+"using" { return new Symbol(WCPSSymbol.USING, yyline, yychar, yytext()) ; }
+"max" { return new Symbol(WCPSSymbol.MAX, yyline, yychar, yytext()) ; }
+"min" { return new Symbol(WCPSSymbol.MIN, yyline, yychar, yytext()) ; }
+"and" { return new Symbol(WCPSSymbol.AND, yyline, yychar, yytext()) ; }
+"or" { return new Symbol(WCPSSymbol.OR, yyline, yychar, yytext()) ; }
+"setCrsSet" { return new Symbol(WCPSSymbol.SETCRSSET, yyline, yychar, yytext()); }
+"nearest" { return new Symbol(WCPSSymbol.NEAREST, yyline, yychar, yytext()) ; }
+"cTransform" { return new Symbol(WCPSSymbol.CTRANSFORM, yyline, yychar, yytext()) ; }
+"scale" { return new Symbol(WCPSSymbol.SCALE, yyline, yychar, yytext()) ; }
+"count" { return new Symbol(WCPSSymbol.COUNT, yyline, yychar, yytext()) ; }
+"all" { return new Symbol(WCPSSymbol.ALL, yyline, yychar, yytext()) ; }
+"add" { return new Symbol(WCPSSymbol.ADD, yyline, yychar, yytext()) ; }
+"some" { return new Symbol(WCPSSymbol.SOME, yyline, yychar, yytext()) ; }
+"avg" { return new Symbol(WCPSSymbol.AVG, yyline, yychar, yytext()) ; }
+"bool" { return new Symbol(WCPSSymbol.BOOL, yyline, yychar, yytext()) ; }
+"char" { return new Symbol(WCPSSymbol.CHAR, yyline, yychar, yytext()) ; }
+"unsigned char" { return new Symbol(WCPSSymbol.UNSIGNEDCHAR, yyline, yychar, yytext()) ; }
+"unsigned short" { return new Symbol(WCPSSymbol.UNSIGNEDSHORT, yyline, yychar, yytext()) ; }
+"short" { return new Symbol(WCPSSymbol.SHORT, yyline, yychar, yytext()) ; }
+"long" { return new Symbol(WCPSSymbol.LONG, yyline, yychar, yytext()) ; }
+"unsigned long" { return new Symbol(WCPSSymbol.UNSIGNEDLONG, yyline, yychar, yytext()) ; }
+"float" { return new Symbol(WCPSSymbol.FLOAT, yyline, yychar, yytext()) ; }
+"double" { return new Symbol(WCPSSymbol.DOUBLE, yyline, yychar, yytext()) ; }
+"not" { return new Symbol(WCPSSymbol.NOT, yyline, yychar, yytext()) ; }
+"bit" { return new Symbol(WCPSSymbol.BIT, yyline, yychar, yytext()) ; }
+"xor" { return new Symbol(WCPSSymbol.XOR, yyline, yychar, yytext()) ; }
+"=" { return new Symbol(WCPSSymbol.EQUALS, yyline, yychar, yytext()) ; }
+"!=" { return new Symbol(WCPSSymbol.NOTEQUALS, yyline, yychar, yytext()) ; }
+"overlay" { return new Symbol(WCPSSymbol.OVERLAY, yyline, yychar, yytext()) ; }
+">" { return new Symbol(WCPSSymbol.GT, yyline, yychar, yytext()) ; }
+"<" { return new Symbol(WCPSSymbol.LT, yyline, yychar, yytext()) ; }
+"<=" { return new Symbol(WCPSSymbol.LTE, yyline, yychar, yytext()) ; }
+">=" { return new Symbol(WCPSSymbol.GTE, yyline, yychar, yytext()) ; }
+"[" { return new Symbol(WCPSSymbol.LBRACKET, yyline, yychar, yytext()) ; }
+"]" { return new Symbol(WCPSSymbol.RBRACKET, yyline, yychar, yytext()) ; }
+"trim" { return new Symbol(WCPSSymbol.TRIM, yyline, yychar, yytext()) ; }
+"true" { return new Symbol(WCPSSymbol.TRUE, yyline, yychar, yytext()) ; }
+"false" { return new Symbol(WCPSSymbol.FALSE, yyline, yychar, yytext()) ; }
+"where" { return new Symbol(WCPSSymbol.WHERE, yyline, yychar, yytext()); }
+"store" { return new Symbol(WCPSSymbol.STORE, yyline, yychar, yytext()); }
+"identifier" { return new Symbol(WCPSSymbol.IDENTIFIER, yyline, yychar, yytext()); }
+"imageCrs" { return new Symbol(WCPSSymbol.IMAGECRS, yyline, yychar, yytext()); }
+"imageCrsDomain" { return new Symbol(WCPSSymbol.IMAGECRSDOMAIN, yyline, yychar, yytext()); }
+"crsSet" { return new Symbol(WCPSSymbol.CRSSET, yyline, yychar, yytext()); }
+"generalDomain" { return new Symbol(WCPSSymbol.GENERALDOMAIN, yyline, yychar, yytext()); }
+"nullDefault" { return new Symbol(WCPSSymbol.NULLDEFAULT, yyline, yychar, yytext()); }
+"nullSet" { return new Symbol(WCPSSymbol.NULLSET, yyline, yychar, yytext()); }
+"interpolationDefault" { return new Symbol(WCPSSymbol.INTERPOLATIONDEFAULT, yyline, yychar, yytext()); }
+"interpolationSet" { return new Symbol(WCPSSymbol.INTERPOLATIONSET, yyline, yychar, yytext()); }
+"setNullDefault" { return new Symbol(WCPSSymbol.SETNULLDEFAULT, yyline, yychar, yytext()); }
+"setNullSet" { return new Symbol(WCPSSymbol.SETNULLSET, yyline, yychar, yytext()); }
+"setInterpolationDefault" { return new Symbol(WCPSSymbol.SETINTERPOLATIONDEFAULT, yyline, yychar, yytext()); }
+"setInterpolationSet" { return new Symbol(WCPSSymbol.SETINTERPOLATIONSET, yyline, yychar, yytext()); }
+"complex" { return new Symbol(WCPSSymbol.COMPLEX, yyline, yychar, yytext()); }
+"complex2" { return new Symbol(WCPSSymbol.COMPLEX2, yyline, yychar, yytext()); }
+"slice" { return new Symbol(WCPSSymbol.SLICE, yyline, yychar, yytext()); }
+"extend" { return new Symbol(WCPSSymbol.EXTEND, yyline, yychar, yytext()); }
+"linear" { return new Symbol(WCPSSymbol.LINEAR, yyline, yychar, yytext()) ; }
+"quadratic" { return new Symbol(WCPSSymbol.QUADRATIC, yyline, yychar, yytext()); }
+"cubic" { return new Symbol(WCPSSymbol.CUBIC, yyline, yychar, yytext()); }
+"full" { return new Symbol(WCPSSymbol.FULL, yyline, yychar, yytext()); }
+"none" { return new Symbol(WCPSSymbol.NONE, yyline, yychar, yytext()); }
+"half" { return new Symbol(WCPSSymbol.HALF, yyline, yychar, yytext()); }
+"other" { return new Symbol(WCPSSymbol.OTHER, yyline, yychar, yytext()); }
+"coverage" { return new Symbol(WCPSSymbol.COVERAGE, yyline, yychar, yytext()); }
+"values" { return new Symbol(WCPSSymbol.VALUES, yyline, yychar, yytext()); }
+"x" { return new Symbol(WCPSSymbol.X, yyline, yychar, yytext()); }
+"y" { return new Symbol(WCPSSymbol.Y, yyline, yychar, yytext()); }
+"z" { return new Symbol(WCPSSymbol.Z, yyline, yychar, yytext()); }
+"time" { return new Symbol(WCPSSymbol.TIME, yyline, yychar, yytext()); }
+"abstract" { return new Symbol(WCPSSymbol.ABSTRACT, yyline, yychar, yytext()); }
+
+{IDENTIFIER} { System.out.println("Got an Identifier: '" + yytext() + "'"); return new Symbol(WCPSSymbol.ID, yyline, yychar, yytext()); }
+{NUMBER} { System.out.println("Got an int: '" + yytext() + "'"); return new Symbol(WCPSSymbol.NUMBER, yyline, yychar, new Integer(yytext()));}
+{FLOATNUMBER} { System.out.println("Got a float: '" + yytext() + "'"); return new Symbol(WCPSSymbol.FLOATNUMBER, yyline, yychar, new Float(yytext()));}
+{STRING} { System.out.println("Got a string: '" + yytext() + "'"); return new Symbol(WCPSSymbol.STRING, yyline, yychar, yytext()); }
+
+
+
+
+\n {System.out.println("newline" + yytext()); return null; }
+. {System.out.println("illegal input: '" + yytext() +"'"); }
diff --git a/src/syntaxParser/wcps.lex_ORIG b/src/syntaxParser/wcps.lex_ORIG
new file mode 100644
index 0000000..c477710
--- /dev/null
+++ b/src/syntaxParser/wcps.lex_ORIG
@@ -0,0 +1,141 @@
+/*
+ WCPS JLex specification - author: Mattia Parigiani
+
+ This is the JLex specification file for the WCPS abstract grammar. The JLex executable produces a Scanner.java source file which encapsulated
+ all symbol and token definition and which is needed by the Java CUP parser
+
+ This file specifies all possible tokens / symbols that may appear in a WCPS request
+
+ New symbols may be added following the same syntax standard
+
+*/
+
+
+
+
+
+/*
+ Required declarations for source generator.
+ Make sure you know what you are doing if you wish to modify these declarations
+*/
+
+
+import java_cup.runtime.*;
+import java.io.*;
+%%
+
+%notunix
+%implements java_cup.runtime.Scanner
+%type Symbol
+%function next_token
+%class WCPSScanner
+%eofval{ return null;
+%eofval}
+
+/*
+ WCPS data types specification
+*/
+
+IDENTIFIER = [a-zA-Z][a-zA-Z0-9]*
+NUMBER = [0-9]+
+FLOATNUMBER = [-+]?[0-9]*\.?[0-9]+
+
+
+/*
+ WCPS Tokens specification
+
+*/
+
+
+%%
+"+" { return new Symbol(WCPSSymbol.PLUS, yytext()); }
+"*" { return new Symbol(WCPSSymbol.MULTI, yytext()); }
+"/" { return new Symbol(WCPSSymbol.DIVIDE, yytext()); }
+"-" { return new Symbol(WCPSSymbol.MINUS, yytext()); }
+"(" { return new Symbol(WCPSSymbol.LPAREN, yytext()); }
+")" { return new Symbol(WCPSSymbol.RPAREN, yytext()); }
+"{" { return new Symbol(WCPSSymbol.LBRACE, yytext()); }
+"}" { return new Symbol(WCPSSymbol.RBRACE, yytext()); }
+"struct" { return new Symbol(WCPSSymbol.STRUCT, yytext()); }
+"sin" { return new Symbol(WCPSSymbol.SIN, yytext()); }
+"cos" { return new Symbol(WCPSSymbol.COS, yytext()); }
+"tan" { return new Symbol(WCPSSymbol.TAN, yytext()); }
+"sinh" { return new Symbol(WCPSSymbol.SINH, yytext()); }
+"cosh" { return new Symbol(WCPSSymbol.COSH, yytext()); }
+"tanh" { return new Symbol(WCPSSymbol.TANH, yytext()); }
+"arcsin" { return new Symbol(WCPSSymbol.ARCSIN, yytext()); }
+"arccos" { return new Symbol(WCPSSymbol.ARCCOS, yytext()); }
+"arctan" { return new Symbol(WCPSSymbol.ARCTAN, yytext()); }
+"exp" { return new Symbol(WCPSSymbol.EXP, yytext()); }
+"log" { return new Symbol(WCPSSymbol.LOG, yytext()); }
+"ln" { return new Symbol(WCPSSymbol.LN, yytext()); }
+"abs" { return new Symbol(WCPSSymbol.ABS, yytext()); }
+"sqrt" { return new Symbol(WCPSSymbol.SQRT, yytext()); }
+":" { return new Symbol(WCPSSymbol.COLON, yytext()); }
+"." { return new Symbol(WCPSSymbol.DOT, yytext()); }
+"return" { return new Symbol(WCPSSymbol.RETURN, yytext()) ;}
+"for" { return new Symbol(WCPSSymbol.FOR, yytext()) ;}
+"in" { return new Symbol(WCPSSymbol.IN, yytext()) ; }
+"," { return new Symbol(WCPSSymbol.COMMA, yytext()); }
+"encode" { return new Symbol(WCPSSymbol.ENCODE, yytext()) ; }
+"condense" { return new Symbol(WCPSSymbol.CONDENSE, yytext()) ; }
+"over" { return new Symbol(WCPSSymbol.OVER, yytext()) ; }
+"using" { return new Symbol(WCPSSymbol.USING, yytext()) ; }
+"max" { return new Symbol(WCPSSymbol.MAX, yytext()) ; }
+"min" { return new Symbol(WCPSSymbol.MIN, yytext()) ; }
+"and" { return new Symbol(WCPSSymbol.AND, yytext()) ; }
+"or" { return new Symbol(WCPSSymbol.OR, yytext()) ; }
+"setNull" { return new Symbol(WCPSSymbol.SETNULL, yytext()) ; }
+"setInterpolation" { return new Symbol(WCPSSymbol.SETINTERPOLATION, yytext()) ; }
+"setCrs" { return new Symbol(WCPSSymbol.SETCRS, yytext()) ; }
+"setAxis" { return new Symbol(WCPSSymbol.SETAXIS, yytext()) ; }
+"nearest neighbor" { return new Symbol(WCPSSymbol.NEAREST, yytext()) ; }
+"bilinear" { return new Symbol(WCPSSymbol.BILINEAR, yytext()) ; }
+"barycentric" { return new Symbol(WCPSSymbol.BARYCENTRIC, yytext()) ; }
+"bicubic" { return new Symbol(WCPSSymbol.BICUBIC, yytext()) ; }
+"lost-area" { return new Symbol(WCPSSymbol.LOSTAREA, yytext()) ; }
+"yDomain" { return new Symbol(WCPSSymbol.YDOMAIN, yytext()) ; }
+"xDomain" { return new Symbol(WCPSSymbol.XDOMAIN, yytext()) ; }
+"sDomain" { return new Symbol(WCPSSymbol.SDOMAIN, yytext()) ; }
+"tDomain" { return new Symbol(WCPSSymbol.TDOMAIN, yytext()) ; }
+"cTransform" { return new Symbol(WCPSSymbol.CTRANSFORM, yytext()) ; }
+"scale" { return new Symbol(WCPSSymbol.SCALE, yytext()) ; }
+"res" { return new Symbol(WCPSSymbol.RES, yytext()) ; }
+"dim" { return new Symbol(WCPSSymbol.DIM, yytext()) ; }
+"cellType" { return new Symbol(WCPSSymbol.CELLTYPE, yytext()) ; }
+"crs" { return new Symbol(WCPSSymbol.CRS, yytext()) ; }
+"count" { return new Symbol(WCPSSymbol.COUNT, yytext()) ; }
+"all" { return new Symbol(WCPSSymbol.ALL, yytext()) ; }
+"add" { return new Symbol(WCPSSymbol.ADD, yytext()) ; }
+"some" { return new Symbol(WCPSSymbol.SOME, yytext()) ; }
+"avg" { return new Symbol(WCPSSymbol.AVG, yytext()) ; }
+"bool" { return new Symbol(WCPSSymbol.BOOL, yytext()) ; }
+"char" { return new Symbol(WCPSSymbol.CHAR, yytext()) ; }
+"unsigned char" { return new Symbol(WCPSSymbol.UNSIGNEDCHAR, yytext()) ; }
+"unsigned short" { return new Symbol(WCPSSymbol.UNSIGNEDSHORT, yytext()) ; }
+"short" { return new Symbol(WCPSSymbol.SHORT, yytext()) ; }
+"long" { return new Symbol(WCPSSymbol.LONG, yytext()) ; }
+"unsigned long" { return new Symbol(WCPSSymbol.UNSIGNEDLONG, yytext()) ; }
+"float" { return new Symbol(WCPSSymbol.FLOAT, yytext()) ; }
+"double" { return new Symbol(WCPSSymbol.DOUBLE, yytext()) ; }
+"not" { return new Symbol(WCPSSymbol.NOT, yytext()) ; }
+"bit" { return new Symbol(WCPSSymbol.BIT, yytext()) ; }
+"xor" { return new Symbol(WCPSSymbol.XOR, yytext()) ; }
+"=" { return new Symbol(WCPSSymbol.EQUALS, yytext()) ; }
+"!=" { return new Symbol(WCPSSymbol.NOTEQUALS, yytext()) ; }
+"overlay" { return new Symbol(WCPSSymbol.OVERLAY, yytext()) ; }
+">" { return new Symbol(WCPSSymbol.GT, yytext()) ; }
+"<" { return new Symbol(WCPSSymbol.LT, yytext()) ; }
+"<=" { return new Symbol(WCPSSymbol.LTE, yytext()) ; }
+">=" { return new Symbol(WCPSSymbol.GTE, yytext()) ; }
+"[" { return new Symbol(WCPSSymbol.LBRACKET, yytext()) ; }
+"]" { return new Symbol(WCPSSymbol.RBRACKET, yytext()) ; }
+"trim" { return new Symbol(WCPSSymbol.TRIM, yytext()) ; }
+"sect" { return new Symbol(WCPSSymbol.SECT, yytext()) ; }
+"true" { return new Symbol(WCPSSymbol.TRUE, yytext()) ; }
+"false" { return new Symbol(WCPSSymbol.FALSE, yytext()) ; }
+{IDENTIFIER} {return new Symbol(WCPSSymbol.ID, yytext()); }
+{NUMBER} { return new Symbol(WCPSSymbol.NUMBER, new Integer(yytext()));}
+{FLOATNUMBER} { return new Symbol(WCPSSymbol.FLOATNUMBER, new Float(yytext()));}
+\n {System.out.println("newline" + yytext()); }
+. {System.out.println("illegal input" + yytext()); }
diff --git a/src/syntaxParser/wcpsRequest.xml b/src/syntaxParser/wcpsRequest.xml
new file mode 100644
index 0000000..a88e313
--- /dev/null
+++ b/src/syntaxParser/wcpsRequest.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<processCoverage xmlns="http://www.opengis.net/wcps/1.0.0" service="WCPS" version="1.0.0">
+<coverageIterator>
+ <iteratorVar>m</iteratorVar>
+ <coverageName>climate_temperature</coverageName>
+ </coverageIterator>
+ <encode>
+ <format>png</format>
+ <coverage>m</coverage>
+ </encode>
+</processCoverage>
diff --git a/src/wcps/server/cli/WCPService.java b/src/wcps/server/cli/WCPService.java
new file mode 100644
index 0000000..0f12e8f
--- /dev/null
+++ b/src/wcps/server/cli/WCPService.java
@@ -0,0 +1,104 @@
+package wcps.server.cli;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+
+import wcps.server.core.CachedMetadataSource;
+import wcps.server.core.DbMetadataSource;
+import wcps.server.core.ProcessCoverageRequest;
+import wcps.server.core.WCPS;
+
+// This is a small application around the WCPS core. It takes XML requests as files and runs them through WCPS. The resulting radaman queries are displayed, but not executed. This is very useful for testing whether your metadata is valid.
+
+public class WCPService {
+
+ private static WCPS wcps;
+
+ public static void main( String[] args ) {
+
+ if( args.length != 1 ) {
+ System.err.println( "WCPS: no input files" );
+ System.exit( 1 );
+ }
+
+ String pcSchemaFileName = ".." + File.separator + "xml" + File.separator + "ogc" + File.separator + "wcps" + File.separator + "1.0.0" + File.separator + "wcpsProcessCoverage.xsd";
+ File pcSchemaFile = new File( pcSchemaFileName );
+ if( !pcSchemaFile.exists() ) {
+ System.err.println( "WCPS: could not find the WCPS ProcessCoverage schema (" + pcSchemaFileName + ")" );
+ System.exit( 1 );
+ }
+
+ DbMetadataSource metadataSource = null;
+ try {
+ Properties dbParams = new Properties();
+ dbParams.load( new FileInputStream( ".." + File.separator + "dbparams.properties" ) );
+ metadataSource = new DbMetadataSource( dbParams.getProperty( "metadata_driver" ), dbParams.getProperty( "metadata_url" ), dbParams.getProperty( "metadata_user" ), dbParams.getProperty( "metadata_pass" ), false );
+ wcps = new WCPS( pcSchemaFile, new CachedMetadataSource( metadataSource ) );
+ }
+ catch( Exception e ) {
+ System.err.println( "WCPS: could not initialize WCPS:" );
+ e.printStackTrace( System.err );
+ System.exit( 1 );
+ }
+
+ for( int i = 0; i < args.length; i++ ) {
+ File fileIn = null;
+ try {
+ fileIn = new File( args[i] );
+ }
+ catch( Exception fnfe ) {
+ System.err.println( "WCPS: " + args[i] + ": no such file or directory" + fnfe );
+ System.exit( 1 );
+ }
+ boolean ok = processCoverage( fileIn, i );
+ if( !ok ) {
+ System.err.println( "WCPS: " + args[i] + " failed" );
+ System.exit( 1 );
+ }
+ }
+
+ metadataSource.close();
+ System.exit( 0 );
+
+ }
+
+ // TODO: Here's a fun idea: make this function multithreaded! ;)
+ private static boolean processCoverage( File in, int i ) {
+
+ try {
+
+ ProcessCoverageRequest r = wcps.pcPrepare("http://kahlua.eecs.jacobs-university.de:7001", "RASSERVICE", in );
+
+ System.err.println( "Request " + i );
+
+ System.out.println( r.getQuery() );
+
+
+/* Iterator<byte[]> results = r.execute().iterator();
+
+ int j = 0;
+ while( results.hasNext() ) {
+ String outFileName = "WCPS-" + i + "-" + j++;
+ FileOutputStream out = new FileOutputStream( outFileName );
+ out.write( results.next() );
+ out.close();
+ System.out.println( "WCPS: " + outFileName + " written" );
+ }*/
+
+ }
+ catch( Exception e ) {
+ System.err.println( "WCPS: request " + i + " failed with the following exception:" );
+ e.printStackTrace( System.err );
+ }
+
+ return true;
+
+ }
+
+}
diff --git a/src/wcps/server/core/BinaryOperationCoverageExprType.java b/src/wcps/server/core/BinaryOperationCoverageExprType.java
new file mode 100644
index 0000000..66aeba2
--- /dev/null
+++ b/src/wcps/server/core/BinaryOperationCoverageExprType.java
@@ -0,0 +1,111 @@
+package wcps.server.core;
+
+import org.w3c.dom.*;
+
+public class BinaryOperationCoverageExprType implements IRasNode, ICoverageInfo {
+
+ private IRasNode first, second;
+ private String operation;
+ private CoverageInfo info;
+
+ public BinaryOperationCoverageExprType(Node node, ProcessCoverageRequest pcr) throws WCPSException {
+ String nodeName = node.getNodeName();
+ System.err.println("Trying to parse binary operation: " + nodeName);
+ boolean okay = false; // will be true if the node is recognized
+ if (nodeName.equals("plus")) {
+ operation = "+";
+ okay = true;
+ }
+ if (nodeName.equals("minus")) {
+ operation = "-";
+ okay = true;
+ }
+ if (nodeName.equals("mult")) {
+ operation = "*";
+ okay = true;
+ }
+ if (nodeName.equals("div")) {
+ operation = "/";
+ okay = true;
+ }
+
+ if (nodeName.equals("and") || nodeName.equals("or") || nodeName.equals("xor")) {
+ operation = nodeName;
+ okay = true;
+ }
+
+ if (nodeName.equals("equals")) {
+ operation = "=";
+ okay = true;
+ }
+ if (nodeName.equals("lessThan")) {
+ operation = "<";
+ okay = true;
+ }
+ if (nodeName.equals("greaterThan")) {
+ operation = ">";
+ okay = true;
+ }
+ if (nodeName.equals("lessOrEqual")) {
+ operation = "<=";
+ okay = true;
+ }
+ if (nodeName.equals("greaterOrEqual")) {
+ operation = ">=";
+ okay = true;
+ }
+ if (nodeName.equals("notEqual")) {
+ operation = "!=";
+ okay = true;
+ }
+ if (nodeName.equals("overlay")) {
+ operation = "overlay";
+ okay = true;
+ }
+
+ if (!okay)
+ throw new WCPSException("Unexpected binary operation : " + nodeName);
+
+ Node operand = node.getFirstChild();
+ while (operand.getNodeName().equals("#text")) operand = operand.getNextSibling();
+ try {
+ first = new ScalarExprType(operand, pcr);
+ System.err.println("Matched scalar expression in binary operation " + nodeName + ": " + operand.getNodeName());
+
+ } catch (WCPSException e) {
+ System.err.println("Failed to match scalar expression in binary operation " + nodeName + ": " + operand.getNodeName());
+ }
+ if (first == null) {
+ first = new CoverageExprType(operand, pcr);
+ info = new CoverageInfo(((ICoverageInfo)first).getCoverageInfo());
+ operand = operand.getNextSibling();
+ while (operand.getNodeName().equals("#text"))
+ operand = operand.getNextSibling();
+ try {
+ second = new ScalarExprType(operand, pcr);
+ System.err.println("Matched scalar expression in binary operation " + nodeName + ": " + operand.getNodeName());
+ } catch (WCPSException e) {
+ System.err.println("Failed to match scalar expression in binary operation " + nodeName + ": " + operand.getNodeName());
+ }
+ if (second == null) {
+ second = new CoverageExprType(operand, pcr);
+ if (!((ICoverageInfo)first).getCoverageInfo().isCompatible(((ICoverageInfo)second).getCoverageInfo()))
+ throw new WCPSException("Coverages are not compatible");
+ }
+ } else {
+ operand = operand.getNextSibling();
+ while (operand.getNodeName().equals("#text")) operand = operand.getNextSibling();
+ second = new CoverageExprType(operand, pcr);
+ info = new CoverageInfo(((ICoverageInfo)second).getCoverageInfo());
+ }
+ }
+
+ public CoverageInfo getCoverageInfo() {
+ return info;
+ }
+
+ public String toRasQL() {
+ return "(" + first.toRasQL() + ")" + operation + "(" + second.toRasQL() + ")";
+ }
+
+}
diff --git a/src/wcps/server/core/BooleanScalarExprType.java b/src/wcps/server/core/BooleanScalarExprType.java
new file mode 100644
index 0000000..34d2596
--- /dev/null
+++ b/src/wcps/server/core/BooleanScalarExprType.java
@@ -0,0 +1,36 @@
+package wcps.server.core;
+
+import org.w3c.dom.*;
+
+public class BooleanScalarExprType implements IRasNode {
+ private boolean simple; // true if the expression is just a value
+ private String value;
+ private String op;
+ private BooleanScalarExprType first, second;
+
+ public BooleanScalarExprType(Node node, ProcessCoverageRequest pcr) throws WCPSException {
+ String nodeName = node.getNodeName();
+ simple = false;
+ if (nodeName.equals("boolean")) {
+ simple = true;
+ value = node.getFirstChild().getNodeValue();
+ } else if (nodeName.equals("scalarAnd") || nodeName.equals("scalarOr") || nodeName.equals("scalarXor")) {
+ if (nodeName.equals("scalarAnd")) op = "and";
+ if (nodeName.equals("scalarOr")) op = "or";
+ if (nodeName.equals("scalarXor")) op = "xor";
+ Node child = node.getFirstChild();
+ first = new BooleanScalarExprType(child, pcr);
+ child = child.getNextSibling();
+ second = new BooleanScalarExprType(child, pcr);
+ } else if (nodeName.equals("scalarNot")) {
+ op = "not";
+ first = new BooleanScalarExprType(node.getFirstChild(), pcr);
+ } else throw new WCPSException("Unexpected Binary Expression node : " + node.getNodeName());
+ }
+
+ public String toRasQL() {
+ if (simple) return value;
+ if (op.equals("not")) return "not(" + first.toRasQL() + ")";
+ return "(" + first.toRasQL() + ")" + op + "(" + second.toRasQL() + ")";
+ }
+} \ No newline at end of file
diff --git a/src/wcps/server/core/CachedMetadataSource.java b/src/wcps/server/core/CachedMetadataSource.java
new file mode 100644
index 0000000..fd2a7a3
--- /dev/null
+++ b/src/wcps/server/core/CachedMetadataSource.java
@@ -0,0 +1,73 @@
+package wcps.server.core;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+// A MetadataSource that caches reads from another MetadataSource. It reads and caches all coverages at startup, in order to make reads faster and so that WCPS will continue to work once it initializes correctly, even if the database cannot be accessed, or metadata is changed into an invalid state.
+
+public class CachedMetadataSource implements MetadataSource {
+
+ private Set<String> coverageNames;
+ private MetadataSource metadataSource;
+ private Map<String,Metadata> metadata;
+ private Map<String,String> supportedFormats;
+
+ public CachedMetadataSource( MetadataSource metadataSource ) throws ResourceException, InvalidMetadataException {
+
+ this.metadataSource = metadataSource;
+
+ coverageNames = metadataSource.coverages();
+ metadata = new HashMap<String,Metadata>( coverageNames.size() );
+ supportedFormats = new HashMap<String,String>();
+ Iterator<String> i = coverageNames.iterator();
+ try {
+ while( i.hasNext() ) {
+ String coverage = i.next();
+ metadata.put( coverage, metadataSource.read( coverage ) );
+ }
+ }
+ catch( InvalidRequestException ire ) {
+ throw (InvalidMetadataException) ire.getCause();
+ }
+
+ }
+
+ public Set<String> coverages() {
+
+ return coverageNames;
+
+ }
+
+ public String mimetype( String format ) {
+
+ if( supportedFormats.containsKey( format ) ) {
+ return supportedFormats.get( format );
+ }
+ else {
+ String mimetype = metadataSource.mimetype( format );
+ synchronized( this ) {
+ supportedFormats.put( format, mimetype );
+ }
+ return mimetype;
+ }
+
+ }
+
+ public Metadata read( String coverageName ) throws InvalidRequestException {
+
+ if( coverageName == null || coverageName.equals( "" ) ) {
+ throw new InvalidRequestException( "Cannot retrieve coverage with null or empty name" );
+ }
+
+ if( !coverageNames.contains( coverageName ) ) {
+ throw new InvalidRequestException( "Coverage '" + coverageName + "' is not served by this server" );
+ }
+
+ return metadata.get( coverageName ).clone();
+
+ }
+
+}
diff --git a/src/wcps/server/core/CellDomainElement.java b/src/wcps/server/core/CellDomainElement.java
new file mode 100644
index 0000000..fff1b2c
--- /dev/null
+++ b/src/wcps/server/core/CellDomainElement.java
@@ -0,0 +1,54 @@
+package wcps.server.core;
+
+import java.math.BigInteger;
+
+// A coverage axis in pixel coordinates. See the WCPS standard.
+
+class CellDomainElement implements Cloneable {
+
+ private BigInteger hi;
+ private BigInteger lo;
+
+ public CellDomainElement( BigInteger lo, BigInteger hi ) throws InvalidMetadataException {
+
+ if( lo == null || hi == null ) {
+ throw new InvalidMetadataException( "Invalid cell domain element: Bounds may not be null" );
+ }
+ if( lo.compareTo( hi ) == 1 ) {
+ throw new InvalidMetadataException( "Invalid cell domain element: Lower bound cannot be larger than upper bound" );
+ }
+ this.lo = lo;
+ this.hi = hi;
+
+ }
+
+ public CellDomainElement clone() {
+
+ try {
+ return new CellDomainElement( BigInteger.ZERO.add( lo ), BigInteger.ZERO.add( hi ) );
+ }
+ catch( InvalidMetadataException ime ) {
+ throw new RuntimeException( "Invalid metadata while cloning CellDomainElement. This is a software bug in WCPS.", ime );
+ }
+
+ }
+
+ public boolean equals( CellDomainElement cde ) {
+
+ return lo.equals( cde.lo ) && hi.equals( cde.hi );
+
+ }
+
+ public BigInteger getHi() {
+
+ return hi;
+
+ }
+
+ public BigInteger getLo() {
+
+ return lo;
+
+ }
+
+}
diff --git a/src/wcps/server/core/CombineRangeCoverageExprType.java b/src/wcps/server/core/CombineRangeCoverageExprType.java
new file mode 100644
index 0000000..67410aa
--- /dev/null
+++ b/src/wcps/server/core/CombineRangeCoverageExprType.java
@@ -0,0 +1,14 @@
+package wcps.server.core;
+
+import org.w3c.dom.*;
+
+// TODO(smsorin): how do we do combine this ?
+public class CombineRangeCoverageExprType implements IRasNode, ICoverageInfo {
+
+ public CombineRangeCoverageExprType(Node node, ProcessCoverageRequest pcr) throws WCPSException{
+ throw new WCPSException("Method not implemented");
+ }
+
+ public String toRasQL() { return ""; }
+ public CoverageInfo getCoverageInfo() { return null; }
+} \ No newline at end of file
diff --git a/src/wcps/server/core/CoordinateType.java b/src/wcps/server/core/CoordinateType.java
new file mode 100644
index 0000000..6b1a2e8
--- /dev/null
+++ b/src/wcps/server/core/CoordinateType.java
@@ -0,0 +1,27 @@
+package wcps.server.core;
+
+import org.w3c.dom.*;
+import java.util.List;
+import java.util.Iterator;
+
+public class CoordinateType implements IRasNode {
+ private int value;
+
+ public CoordinateType(Node node) throws WCPSException {
+ if (!node.getNodeName().equals("cellCoord") &&
+ !node.getNodeName().equals("domainCoord"))
+ throw new WCPSException("Expected cellCoord or domainCoord, found " + node.getNodeName());
+
+ System.out.println("CoordinateType: node name: " + node.getNodeName());
+ System.out.println("CoordinateType: node child 1: " + node.getFirstChild().getNodeName());
+ value = Integer.parseInt(node.getFirstChild().getNodeValue());
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public String toRasQL() {
+ return ""+value;
+ }
+};
diff --git a/src/wcps/server/core/CoverageExprType.java b/src/wcps/server/core/CoverageExprType.java
new file mode 100644
index 0000000..5bef286
--- /dev/null
+++ b/src/wcps/server/core/CoverageExprType.java
@@ -0,0 +1,109 @@
+package wcps.server.core;
+
+import org.w3c.dom.*;
+import java.util.Iterator;
+
+public class CoverageExprType implements IRasNode, ICoverageInfo {
+
+ private boolean simpleCoverage; // True is the coverage is just a string
+ private IRasNode child;
+ private String childInfo;
+ private CoverageInfo info;
+
+ public CoverageInfo getCoverageInfo() {
+ return info;
+ }
+
+ public CoverageExprType (Node node, ProcessCoverageRequest pcr) throws WCPSException {
+ while (node != null && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+
+ if (node == null) throw new WCPSException("CoverageExprType parsing error!");
+ String nodeName = node.getNodeName();
+ simpleCoverage = false;
+ System.err.println("CoverageExprType: node " + nodeName);
+
+ if (nodeName.equals("coverage")) {
+ simpleCoverage = true;
+ childInfo = node.getFirstChild().getNodeValue();
+ if (!pcr.isIteratorDefined(childInfo))
+ throw new WCPSException("Iterator " + childInfo + " not defined!");
+
+ Iterator<String> coverages = pcr.getCoverages(childInfo);
+
+ info = new CoverageInfo(pcr.getMetadataSource().read(coverages.next()));
+
+ while (coverages.hasNext()) { // Check if all the coverages are compatible
+ CoverageInfo tmp = new CoverageInfo(pcr.getMetadataSource().read(coverages.next()));
+ if (!tmp.isCompatible(info))
+ throw new WCPSException("Incompatible coverages within the same iterator");
+ }
+ System.err.println("Found simple coverage definition: " + childInfo + ", " + info.toString());
+ } else if (nodeName.equals("trim")) {
+ child = new TrimCoverageExprType(node, pcr);
+ } else if (nodeName.equals("extend")) {
+ //child = new ExtendCoverageExprType(node, pcr);
+ // TODO: add the class and remove this
+ throw new WCPSException("Feature not yet implemented");
+ } else if (nodeName.equals("slice")) {
+ child = new SliceCoverageExprType(node, pcr);
+ } else if (nodeName.equals("scale")) {
+ //child = new ScaleCoverageExprType(node, pcr);
+ // TODO: add the class and remove this
+ throw new WCPSException("Feature not yet implemented");
+ } else if (nodeName.equals("combine")) {
+ child = new CombineRangeCoverageExprType(node, pcr);
+ } else if (nodeName.equals("crsTransform")) {
+ child = new CrsTransformCoverageExprType(node, pcr);
+ } else if (nodeName.equals("construct")) {
+ //child = new ConstructcoverageExprType(node, pcr);
+ // TODO: add the class and remove this
+ throw new WCPSException("Feature not yet implemented");
+
+ } else { // Try one of the groups
+ try {
+ child = new UnaryOperationCoverageExprType(node, pcr);
+ System.err.println("Matched unary operation.");
+ } catch (WCPSException e) {
+ System.err.println("Failed to match Unary operation: " + e.toString() + "\nRetrying");
+ child = null;
+ }
+
+ if (child == null) {
+ try {
+ child = new BinaryOperationCoverageExprType(node, pcr);
+ System.err.println("Matched binary operation.");
+ } catch (WCPSException e) {
+ System.err.println("Failed to match binary operation: " + e.toString() + "\nRetrying");
+ child = null;
+ }
+ }
+
+ // TODO: implement the class and remove this
+ /* if (child == null) {
+ try {
+ child = new SetMetadataCoverageExprType(node, pcr);
+ } catch (WCPSException e) {
+ child = null;
+ }
+ }*/
+
+ }
+ if (!simpleCoverage && child == null) {
+ throw new WCPSException("Invalid coverage Expression, next node: " + node.getNodeName());
+ }
+ if (info == null) {
+ System.err.println(node.getNodeName());
+ info = new CoverageInfo(((ICoverageInfo)child).getCoverageInfo());
+ }
+ }
+
+ public String toRasQL() {
+ if (simpleCoverage)
+ return childInfo;
+ else
+ return child.toRasQL();
+ }
+
+};
diff --git a/src/wcps/server/core/CoverageInfo.java b/src/wcps/server/core/CoverageInfo.java
new file mode 100644
index 0000000..b118bb1
--- /dev/null
+++ b/src/wcps/server/core/CoverageInfo.java
@@ -0,0 +1,116 @@
+package wcps.server.core;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Iterator;
+
+public class CoverageInfo {
+
+ private List<CellDomainElement> cellDomains;
+ private List<DomainElement> domains;
+
+
+ public CoverageInfo(CoverageInfo other) {
+ cellDomains = new ArrayList<CellDomainElement>();
+ domains = new ArrayList<DomainElement>();
+ int N = other.getNumDimensions();
+ for (int i = 0; i < N; ++i) {
+ cellDomains.add(other.getCellDomainElement(i));
+ domains.add(other.getDomainElement(i));
+ }
+ }
+
+ public CoverageInfo(Metadata m) {
+ cellDomains = new ArrayList<CellDomainElement>();
+ domains = new ArrayList<DomainElement>();
+ Iterator<CellDomainElement> itcde = m.getCellDomainIterator();
+
+ while (itcde.hasNext())
+ cellDomains.add (itcde.next());
+
+ Iterator<DomainElement> itde = m.getDomainIterator();
+ while (itde.hasNext())
+ domains.add(itde.next());
+ }
+
+ public boolean isCompatible(CoverageInfo other) {
+ if (getNumDimensions() != other.getNumDimensions()) {
+ System.err.println("The number of dimensions doesn't match");
+ return false;
+ }
+ {
+ Iterator<CellDomainElement> it = cellDomains.iterator();
+ int index = 0;
+ while (it.hasNext()) {
+ CellDomainElement me, you;
+ me = it.next();
+ you = other.getCellDomainElement(index ++);
+ if (!me.getHi().equals(you.getHi())) {
+ System.err.println("High values don't match: " + me.getHi().toString() + ", " + you.getHi().toString());
+ return false;
+ }
+ if (!me.getLo().equals(you.getLo())) {
+ System.err.println("Low values don't match: " + me.getLo().toString() + ", " + you.getLo().toString());
+ return false;
+ }
+ }
+ }
+ {
+ Iterator<DomainElement> it = domains.iterator();
+ int index = 0;
+ while (it.hasNext()) {
+ DomainElement me, you;
+ me = it.next();
+ you = other.getDomainElement(index ++);
+ if (!me.getName().equals(you.getName())) {
+ System.err.println("Domain element names don't match: '" + me.getName() + "' and '"+
+ you.getName() + "'.");
+ return false;
+ }
+ //if (me.getName() != you.getName()) return false;
+ }
+ }
+ return true;
+ }
+
+
+
+ int getNumDimensions() {
+ return cellDomains.size();
+ }
+
+ public CellDomainElement getCellDomainElement(int dim) {
+ return cellDomains.get(dim);
+ }
+
+ public DomainElement getDomainElement(int dim) {
+ return domains.get(dim);
+ }
+
+ public void removeDimension(int dim) {
+ cellDomains.remove(dim);
+ domains.remove(dim);
+ }
+
+ public void setDimension(int dim,CellDomainElement cde, DomainElement de) {
+ cellDomains.set(dim, cde);
+ domains.set(dim, de);
+ }
+
+ public void setCellDimension(int dim, CellDomainElement cde) {
+ cellDomains.set(dim, cde);
+ }
+
+ public int getDomainIndexByName(String name) throws WCPSException {
+ Iterator<DomainElement> it = domains.iterator();
+ int index = 0;
+ while (it.hasNext() ) {
+ if (name.equals(it.next().getName())) {
+ return index;
+ }
+ index ++;
+ }
+ throw new WCPSException("Domain name not found :" + name);
+ }
+
+}
diff --git a/src/wcps/server/core/CoverageIterator.java b/src/wcps/server/core/CoverageIterator.java
new file mode 100644
index 0000000..2aa9579
--- /dev/null
+++ b/src/wcps/server/core/CoverageIterator.java
@@ -0,0 +1,55 @@
+package wcps.server.core;
+
+import org.w3c.dom.*;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+public class CoverageIterator implements IRasNode {
+
+ private String iteratorName;
+
+ private List<String> coverageNames;
+
+ public CoverageIterator(Node x, ProcessCoverageRequest pcr) throws WCPSException {
+ MetadataSource source = pcr.getMetadataSource();
+ coverageNames = new ArrayList<String>();
+ if (x.getNodeName() != "coverageIterator")
+ throw new WCPSException("Invalid cast form " + x.getNodeName() + " XML node to CoverageIterator class");
+ Node it = x.getFirstChild();
+ while(it != null) {
+ if (it.getNodeName().equals("#text")) {
+ it = it.getNextSibling();
+ continue;
+ }
+ if (it.getNodeName().equals("iteratorVar")) {
+ iteratorName = it.getFirstChild().getNodeValue();
+ System.err.println("Found iterator name : " + iteratorName);
+ } else if (it.getNodeName().equals("coverageName")) {
+ String cn = it.getFirstChild().getNodeValue();
+ System.err.println("Found coverage reference : " + cn);
+ try {
+ if (!source.coverages().contains(cn))
+ throw new WCPSException("Unknown coverage " + cn);
+ } catch (ResourceException e) {
+ throw new WCPSException("Cannot load coverage information!", e);
+ }
+ coverageNames.add(cn);
+ }
+ it = it.getNextSibling();
+ }
+ }
+
+ public Iterator<String> getCoverages() {
+ return coverageNames.iterator();
+ }
+
+ public String getIteratorName() {
+ return iteratorName;
+ }
+
+ public String toRasQL() {
+ // TODO(smsorin) : How to translate multiple coverages?
+ return coverageNames.get(0) + " AS " + iteratorName;
+ }
+}
diff --git a/src/wcps/server/core/CrsTransformCoverageExprType.java b/src/wcps/server/core/CrsTransformCoverageExprType.java
new file mode 100644
index 0000000..926ab53
--- /dev/null
+++ b/src/wcps/server/core/CrsTransformCoverageExprType.java
@@ -0,0 +1,14 @@
+package wcps.server.core;
+
+import org.w3c.dom.*;
+
+// TODO(smsorin): how do we do combine this ?
+public class CrsTransformCoverageExprType implements IRasNode, ICoverageInfo {
+
+ public CrsTransformCoverageExprType(Node node, ProcessCoverageRequest pcr) throws WCPSException{
+ throw new WCPSException("Method not implemented");
+ }
+
+ public String toRasQL() { return ""; }
+ public CoverageInfo getCoverageInfo() { return null; }
+} \ No newline at end of file
diff --git a/src/wcps/server/core/DbMetadataSource.java b/src/wcps/server/core/DbMetadataSource.java
new file mode 100644
index 0000000..fb982dd
--- /dev/null
+++ b/src/wcps/server/core/DbMetadataSource.java
@@ -0,0 +1,291 @@
+package wcps.server.core;
+
+import java.math.BigInteger;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+// The DbMetadataSource is a MetadataSource that uses a relational database. It keeps a global connection which is reused on future requests, as well as between threads. Before each read, the connection is verified to be valid, and recreated if necessary. This MetadataSource is not particularly efficient, because it accesses the database at least once for every read. To increase efficiency, wrap a CachedMetadataSource around this one.
+
+public class DbMetadataSource implements MetadataSource {
+
+ private static final int CONNECTION_TIMEOUT = 4;
+
+ private Map<Integer,String> axisTypes;
+ private boolean checkAtInit;
+ private Connection connection;
+ private Map<Integer,String> crss;
+ private Map<Integer,String> dataTypes;
+ private String driver;
+ private boolean initializing;
+ private Map<Integer,String> interpolationTypes;
+ private Map<Integer,String> nullResistances;
+ private String pass;
+ private Map<String,String> supportedFormats;
+ private String url;
+ private String user;
+
+ public DbMetadataSource( String driver, String url, String user, String pass ) throws ResourceException, InvalidMetadataException {
+
+ this( driver, url, user, pass, true );
+
+ }
+
+ public DbMetadataSource( String driver, String url, String user, String pass, boolean checkAtInit ) throws ResourceException, InvalidMetadataException {
+
+ try {
+ Class.forName( driver ).newInstance();
+ }
+ catch( ClassNotFoundException e ) {
+ throw new ResourceException( "Metadata database error: Could not find JDBC driver: " + driver, e );
+ }
+ catch( InstantiationException e ) {
+ throw new ResourceException( "Metadata database error: Could not instantiate JDBC driver: " + driver, e );
+ }
+ catch( IllegalAccessException e ) {
+ throw new ResourceException( "Metadata database error: Access denied to JDBC driver: " + driver, e );
+ }
+ this.driver = driver;
+ this.url = url;
+ this.user = user;
+ this.pass = pass;
+ Statement s = null;
+
+ try {
+ ensureConnection();
+
+ axisTypes = new HashMap<Integer,String>( 5 );
+ s = connection.createStatement();
+ ResultSet r = s.executeQuery( "SELECT id, axisType FROM WCPS_AxisType" );
+ while( r.next() ) {
+ axisTypes.put( r.getInt( "id" ), r.getString( "axisType" ) );
+ }
+
+ dataTypes = new HashMap<Integer,String>( 13 );
+ r = s.executeQuery( "SELECT id, dataType FROM WCPS_Datatype" );
+ while( r.next() ) {
+ dataTypes.put( r.getInt( "id" ), r.getString( "dataType" ) );
+ }
+
+ interpolationTypes = new HashMap<Integer,String>( 5 );
+ r = s.executeQuery( "SELECT id, interpolationType FROM WCPS_InterpolationType" );
+ while( r.next() ) {
+ interpolationTypes.put( r.getInt( "id" ), r.getString( "interpolationType" ) );
+ }
+
+ nullResistances = new HashMap<Integer,String>( 4 );
+ r = s.executeQuery( "SELECT id, nullResistance FROM WCPS_NullResistance" );
+ while( r.next() ) {
+ nullResistances.put( r.getInt( "id" ), r.getString( "nullResistance" ) );
+ }
+
+ crss = new HashMap<Integer,String>();
+ r = s.executeQuery( "SELECT id, name FROM WCPS_Crs" );
+ while( r.next() ) {
+ crss.put( r.getInt( "id" ), r.getString( "name" ) );
+ }
+
+ supportedFormats = new HashMap<String,String>( 6 );
+ r = s.executeQuery( "SELECT name, mimetype FROM WCPS_Format" );
+ while( r.next() ) {
+ supportedFormats.put( r.getString( "name" ), r.getString( "mimetype" ) );
+ }
+
+ s.close();
+
+ this.checkAtInit = checkAtInit;
+ if( checkAtInit ) {
+ initializing = true;
+ boolean coveragesOk = false;
+ while( !coveragesOk ) {
+ try {
+ Iterator<String> coverages = coverages().iterator();
+ while( coverages.hasNext() ) {
+ read( coverages.next() );
+ }
+ }
+ catch( InvalidRequestException ire ) {
+ throw (InvalidMetadataException) ire.getCause();
+ }
+ coveragesOk = true;
+ }
+ initializing = false;
+ }
+ }
+ catch( SQLException sqle ) {
+ if( s != null ) {
+ try {
+ s.close();
+ }
+ catch( SQLException e ) {}
+ }
+ close();
+ throw new ResourceException( "Metadata database error", sqle );
+ }
+
+ }
+
+ public void close() {
+
+ synchronized( this ) {
+ if( connection != null ) {
+ try {
+ connection.close();
+ }
+ catch( SQLException sqle ) {}
+ }
+ }
+
+ }
+
+ public Set<String> coverages() throws ResourceException {
+
+ Statement s = null;
+ Set<String> coverages;
+
+ try {
+ ensureConnection();
+ s = connection.createStatement();
+
+ ResultSet r = s.executeQuery( "SELECT name FROM WCPS_Coverage" );
+ coverages = new HashSet<String>( r.getFetchSize() );
+ while( r.next() ) {
+ coverages.add( r.getString( "name" ) );
+ }
+
+ s.close();
+ return coverages;
+ }
+ catch( SQLException sqle ) {
+ if( s != null ) {
+ try {
+ s.close();
+ }
+ catch( SQLException f ) {}
+ }
+ close();
+ throw new ResourceException( "Metadata database error", sqle );
+ }
+
+ }
+
+ public String mimetype( String format ) {
+
+ return supportedFormats.get( format );
+
+ }
+
+ public Metadata read( String coverageName ) throws InvalidRequestException, ResourceException {
+
+ System.err.println( "DB: " + coverageName );
+
+ if( coverageName == null || coverageName.equals( "" ) ) {
+ throw new InvalidRequestException( "Cannot retrieve coverage with null or empty name" );
+ }
+ Statement s = null;
+
+ try {
+ ensureConnection();
+ s = connection.createStatement();
+
+ ResultSet r = s.executeQuery( "SELECT id, nullDefault, interpolationTypeDefault, nullResistanceDefault FROM WCPS_Coverage WHERE name = '" + coverageName + "'" );
+ if( !r.next() ) {
+ throw new InvalidRequestException( "Coverage '" + coverageName + "' is not served by this server" );
+ }
+ int coverage = r.getInt( "id" );
+ String nullDefault = r.getString( "nullDefault" );
+ String interpolationTypeDefault = interpolationTypes.get( r.getInt( "interpolationTypeDefault" ) );
+ String nullResistanceDefault = nullResistances.get( r.getInt( "nullResistanceDefault" ) );
+
+ r = s.executeQuery( "SELECT lo, hi FROM WCPS_CellDomain WHERE coverage = '" + coverage + "' ORDER BY i ASC" );
+ List<CellDomainElement> cellDomain = new ArrayList<CellDomainElement>( r.getFetchSize() );
+ while( r.next() ) {
+ cellDomain.add( new CellDomainElement( BigInteger.valueOf( r.getInt( "lo" ) ), BigInteger.valueOf( r.getInt( "hi" ) ) ) );
+ }
+
+ r = s.executeQuery( "SELECT name, type FROM WCPS_Range WHERE coverage = '" + coverage + "' ORDER BY i ASC" );
+ List<RangeElement> range = new ArrayList<RangeElement>( r.getFetchSize() );
+ while( r.next() ) {
+ range.add( new RangeElement( r.getString( "name" ), dataTypes.get( r.getInt( "type" ) ) ) );
+ }
+
+ r = s.executeQuery( "SELECT interpolationType, nullResistance FROM WCPS_InterpolationSet WHERE coverage = '" + coverage + "'" );
+ Set<InterpolationMethod> interpolationSet = new HashSet<InterpolationMethod>( r.getFetchSize() );
+ while( r.next() ) {
+ interpolationSet.add( new InterpolationMethod( interpolationTypes.get( r.getInt( "interpolationType" ) ), nullResistances.get( r.getInt( "nullResistance" ) ) ) );
+ }
+
+ r = s.executeQuery( "SELECT nullValue FROM WCPS_NullSet WHERE coverage = '" + coverage + "'" );
+ Set<String> nullSet = new HashSet<String>( r.getFetchSize() );
+ while( r.next() ) {
+ nullSet.add( r.getString( "nullValue" ) );
+ }
+
+ r = s.executeQuery( "SELECT id, name, type, numLo, numHi, strLo, strHi FROM WCPS_Domain WHERE coverage = '" + coverage + "' ORDER BY i ASC" );
+ List<DomainElement> domain = new ArrayList<DomainElement>( r.getFetchSize() );
+ Statement ss = connection.createStatement();
+ while( r.next() ) {
+ Double numLo = r.getDouble( "numLo" );
+ if( r.wasNull() ) {
+ numLo = null;
+ }
+ Double numHi = r.getDouble( "numHi" );
+ if( r.wasNull() ) {
+ numHi = null;
+ }
+ ResultSet rr = ss.executeQuery( "SELECT crs FROM WCPS_CrsSet WHERE axis = '" + r.getInt( "id" ) + "'" );
+ Set<String> crsSet = new HashSet<String>( rr.getFetchSize() );
+ while( rr.next() ) {
+ crsSet.add( crss.get( rr.getInt( "crs" ) ) );
+ }
+ crsSet.add( DomainElement.IMAGE_CRS );
+ domain.add( new DomainElement( r.getString( "name" ), axisTypes.get( r.getInt( "type" ) ), numLo, numHi, r.getString( "strLo" ), r.getString( "strHi" ), crsSet ) );
+ }
+
+ s.close();
+
+ return new Metadata( cellDomain, range, nullSet, nullDefault, interpolationSet, new InterpolationMethod( interpolationTypeDefault, nullResistanceDefault ), coverageName, domain );
+ }
+ catch( InvalidMetadataException ime ) {
+ if( checkAtInit && !initializing ) {
+ throw new ResourceException( "Previously valid metadata is now invalid. The metadata for coverage '" + coverageName + "' has been modified incorrectly.", ime );
+ }
+ else {
+ throw new InvalidRequestException( "Coverage '" + coverageName + "' has invalid metadata", ime );
+ }
+ }
+ catch( SQLException sqle ) {
+ if( s != null ) {
+ try {
+ s.close();
+ }
+ catch( SQLException f ) {}
+ }
+ close();
+ throw new ResourceException( "Metadata database error", sqle );
+ }
+
+ }
+
+ private void ensureConnection() throws SQLException {
+
+ synchronized (this) {
+// if( connection == null || !connection.isValid( CONNECTION_TIMEOUT ) ) { // Not implemented by PostgreSQL yet.
+ if( connection == null || !connection.isClosed() ) {
+ close();
+ connection = DriverManager.getConnection( url, user, pass );
+ }
+ }
+
+ }
+
+}
diff --git a/src/wcps/server/core/DomainElement.java b/src/wcps/server/core/DomainElement.java
new file mode 100644
index 0000000..dd19b04
--- /dev/null
+++ b/src/wcps/server/core/DomainElement.java
@@ -0,0 +1,138 @@
+package wcps.server.core;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+// This is an axis i geographic coordinates. See the WCPS standard.
+
+class DomainElement implements Cloneable {
+
+ public static final String IMAGE_CRS = "CRS:1";
+
+ private Set<String> crss;
+ private String name;
+ private Double numHi;
+ private Double numLo;
+ private String strHi;
+ private String strLo;
+ private String type;
+
+ public DomainElement( String name, String type, Double numLo, Double numHi, String strLo, String strHi, Set<String> crss ) throws InvalidMetadataException {
+
+ if( name == null || type == null ) {
+ throw new InvalidMetadataException( "Invalid domain element: Element name and type cannot be null" );
+ }
+ if( name.equals( "" ) ) {
+ throw new InvalidMetadataException( "Invalid domain element: Element name cannot be empty" );
+ }
+
+ if( !( type.equals( "x" ) || type.equals( "y" ) || type.equals( "temporal" ) || type.equals( "elevation" ) || type.equals( "other" )) ) {
+ throw new InvalidMetadataException( "Invalid domain element: Invlaid element type: " + type );
+ }
+
+ if( numLo != null && numHi != null && strLo == null && strHi == null ) {
+ if( numLo.compareTo( numHi ) == 1 ) {
+ throw new InvalidMetadataException( "Invalid domain element: Lower integer bound cannot be larger than upper integer bound" );
+ }
+ this.numLo = numLo;
+ this.numHi = numHi;
+ }
+ else if( strLo != null && numHi != null && numLo == null && numHi == null ) {
+ if( strLo.equals( "" ) || strHi.equals( "" ) ) {
+ throw new InvalidMetadataException( "Invalid domain element: String bounds cannot be empty" );
+ }
+ this.strLo = strLo;
+ this.strHi = strHi;
+ }
+ else {
+ throw new InvalidMetadataException( "Invalid domain element: Integer bounds must both be non-null if string bounds are null, and vice versa at " + name + ":" + type );
+ }
+ if( (type.equals( "x" ) || type.equals( "y" )) && numLo == null ) {
+ throw new InvalidMetadataException( "Invalid domain element: A spatial axis must have integer extent" );
+ }
+ else if( type.equals( "temporal" ) && strLo == null ) {
+ throw new InvalidMetadataException( "Invalid domain element: A temporal axis must have string extent" );
+ }
+
+ this.name = name;
+ this.type = type;
+
+ if( crss == null || !crss.contains( IMAGE_CRS ) ) {
+ throw new InvalidMetadataException( "Invalid domain element: CRS set does not contain image CRS '" + IMAGE_CRS + "'" );
+ }
+ this.crss = crss;
+
+ }
+
+ public DomainElement clone() {
+
+ Set<String> c = new HashSet<String>( crss.size() );
+ Iterator<String> i = crss.iterator();
+ while( i.hasNext() ) {
+ c.add( new String( i.next() ) );
+ }
+
+ try {
+ if( numLo != null ) {
+ return new DomainElement( new String( name ), new String( type ), new Double( numLo ), new Double( numHi ), null, null, c );
+ }
+ else {
+ return new DomainElement( new String( name ), new String( type ), null, null, new String( strLo ), new String( strHi ), c );
+ }
+ }
+ catch( InvalidMetadataException ime ) {
+ throw new RuntimeException( "Invalid metadata while cloning DomainElement. This is a software bug in WCPS.", ime );
+ }
+
+ }
+
+ public boolean equals( DomainElement de ) {
+
+ if( numLo == null && de.numLo == null ) {
+ return strLo.equals( de.strLo ) && strHi.equals( strHi ) && name.equals( de.name ) && type.equals( de.type );
+ }
+ else if( strLo == null && de.strLo == null ) {
+ return numLo.equals( de.numLo ) && numHi.equals( numHi ) && name.equals( de.name ) && type.equals( de.type );
+ }
+ else return false;
+
+ }
+
+ public String getName() {
+
+ return name;
+
+ }
+
+ public Double getNumHi() {
+
+ return numHi;
+
+ }
+
+ public Double getNumLo() {
+
+ return numLo;
+
+ }
+
+ public String getStrHi() {
+
+ return strHi;
+
+ }
+
+ public String getStrLo() {
+
+ return strLo;
+
+ }
+
+ public String getType() {
+
+ return type;
+
+ }
+
+}
diff --git a/src/wcps/server/core/EncodeDataExprType.java b/src/wcps/server/core/EncodeDataExprType.java
new file mode 100644
index 0000000..5bb74ff
--- /dev/null
+++ b/src/wcps/server/core/EncodeDataExprType.java
@@ -0,0 +1,60 @@
+package wcps.server.core;
+
+import org.w3c.dom.*;
+
+public class EncodeDataExprType implements IRasNode{
+
+ private String format;
+ private String extraParams;
+ private IRasNode coverageExprType;
+ private Boolean store;
+ private String mime;
+
+ public EncodeDataExprType (Node node, ProcessCoverageRequest request) throws WCPSException {
+ Node child;
+ String nodeName;
+
+ for (child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
+ nodeName = child.getNodeName();
+
+ if (nodeName.equals("#text")) continue;
+ System.err.println("Encode : node : " + child.getNodeName());
+
+ if (nodeName.equals("format")) {
+ format = child.getFirstChild().getNodeValue();
+ mime = request.getMetadataSource().mimetype(format);
+ continue;
+ }
+
+ if (nodeName.equals("extraParameters")) {
+ extraParams = child.getFirstChild().getNodeValue();
+ continue;
+ }
+
+ coverageExprType = new CoverageExprType(child, request);
+ }
+
+ Node _store = node.getAttributes().getNamedItem("store");
+ if (_store != null)
+ store = _store.getNodeValue().equals("true");
+ }
+
+ public String getMime() {
+ return mime;
+ }
+
+ public String toRasQL() {
+ // TODO: cjucovschi - implement store
+
+ String result;
+ if (format.equals("raw"))
+ result = coverageExprType.toRasQL();
+ else {
+ result = format + "(" + coverageExprType.toRasQL();
+ if (extraParams != null)
+ result = result + ", " + extraParams;
+ result = result + ")";
+ }
+ return result;
+ }
+};
diff --git a/src/wcps/server/core/ExtendCoverageExprType.java b/src/wcps/server/core/ExtendCoverageExprType.java
new file mode 100644
index 0000000..57e3b27
--- /dev/null
+++ b/src/wcps/server/core/ExtendCoverageExprType.java
@@ -0,0 +1,94 @@
+package wcps.server.core;
+
+import org.w3c.dom.*;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.math.BigInteger;
+
+
+public class ExtendCoverageExprType implements IRasNode, ICoverageInfo {
+
+ private class axisSpec {
+ public String axisName;
+ public String crs;
+ public List<Integer> coords = new ArrayList<Integer> ();
+ };
+
+ private List <axisSpec> axisList;
+ private CoverageExprType coverageExprType;
+ private CoverageInfo coverageInfo;
+ private int dims;
+ private String [] dim;
+
+ public CoverageInfo getCoverageInfo() {
+ return coverageInfo;
+ }
+
+ public ExtendCoverageExprType (Node node, ProcessCoverageRequest source) throws WCPSException{
+ Node child, axisNode;
+ String nodeName;
+ axisList = new ArrayList<axisSpec> ();
+
+ for (child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
+ nodeName = child.getNodeName();
+ if (nodeName.equals("#text")) continue;
+
+ if (nodeName.equals("extendAxisSpec")) {
+ axisSpec axis = new axisSpec();
+ String childName;
+ for (axisNode = child.getFirstChild(); axisNode != null; axisNode = axisNode.getNextSibling()) {
+ childName = axisNode.getNodeName();
+ if (childName.equals("axis")) {
+ axis.axisName = axisNode.getFirstChild().getNodeValue();
+ continue;
+ }
+ if (childName.equals("crs")) {
+ axis.crs = axisNode.getFirstChild().getNodeValue();
+ continue;
+ }
+ if (childName.equals("coord")) {
+ CoordinateType coord = new CoordinateType(axisNode);
+ axis.coords.add(coord.getValue());
+ }
+ }
+ axisList.add(axis);
+ continue;
+ }
+
+ // else is a coverage expression type
+ coverageExprType = new CoverageExprType(child, source);
+ coverageInfo = coverageExprType.getCoverageInfo();
+ }
+
+ dims = coverageInfo.getNumDimensions();
+ dim = new String[dims];
+ for (int j=0; j<dims; ++j)
+ dim[j]="*:*";
+
+
+ Iterator <axisSpec> i = axisList.iterator();
+ axisSpec axis;
+ int axisId;
+ int axisLo, axisHi;
+ while (i.hasNext()) {
+ axis = i.next();
+ axisId = coverageInfo.getDomainIndexByName(axis.axisName);
+ axisLo = axis.coords.get(0);
+ axisHi = axis.coords.get(1);
+ dim[axisId]=axisLo+":"+axisHi;
+ coverageInfo.setCellDimension(axisId, new CellDomainElement(BigInteger.valueOf(axisLo), BigInteger.valueOf(axisHi)));
+ }
+ }
+
+ public String toRasQL() {
+ String result = "extend("+coverageExprType.toRasQL()+",[";
+ for (int j=0; j<dims; ++j) {
+ if (j>0)
+ result += ",";
+ result += dim[j];
+ }
+ result += "])";
+ return result;
+ }
+};
diff --git a/src/wcps/server/core/ICoverageInfo.java b/src/wcps/server/core/ICoverageInfo.java
new file mode 100644
index 0000000..bfc1bef
--- /dev/null
+++ b/src/wcps/server/core/ICoverageInfo.java
@@ -0,0 +1,6 @@
+package wcps.server.core;
+
+interface ICoverageInfo {
+ public CoverageInfo getCoverageInfo();
+
+}
diff --git a/src/wcps/server/core/IRasNode.java b/src/wcps/server/core/IRasNode.java
new file mode 100644
index 0000000..3fe38e7
--- /dev/null
+++ b/src/wcps/server/core/IRasNode.java
@@ -0,0 +1,5 @@
+package wcps.server.core;
+
+interface IRasNode {
+ public String toRasQL();
+} \ No newline at end of file
diff --git a/src/wcps/server/core/InterpolationMethod.java b/src/wcps/server/core/InterpolationMethod.java
new file mode 100644
index 0000000..2c582eb
--- /dev/null
+++ b/src/wcps/server/core/InterpolationMethod.java
@@ -0,0 +1,53 @@
+package wcps.server.core;
+
+// A pair of an interpolation type and a null resistance. See the WCPS standard for an explanation of these.
+
+class InterpolationMethod implements Cloneable {
+
+ private String interpolationType;
+ private String nullResistance;
+
+ public InterpolationMethod( String interpolationType, String nullResistance ) throws InvalidMetadataException {
+
+ if( interpolationType == null || !(interpolationType.equals( "nearest" ) || interpolationType.equals( "linear" ) || interpolationType.equals( "cubic" ) || interpolationType.equals( "quadratic" ) || interpolationType.equals( "none" )) ) {
+ throw new InvalidMetadataException( "Invalid interpolation method: " + interpolationType + " is not a legal interpolation type" );
+ }
+ this.interpolationType = interpolationType;
+
+ if( nullResistance == null || !(nullResistance.equals( "full" ) || nullResistance.equals( "none" ) || nullResistance.equals( "half" ) || nullResistance.equals( "other" )) ) {
+ throw new InvalidMetadataException( "Invalid interpolation method: " + nullResistance + " is not a legal null resistance" );
+ }
+ this.nullResistance = nullResistance;
+
+ }
+
+ public InterpolationMethod clone() {
+
+ try {
+ return new InterpolationMethod( interpolationType, nullResistance );
+ }
+ catch( InvalidMetadataException ime ) {
+ throw new RuntimeException( "Invalid metadata while cloning InterpolationMethod. This is a software bug in WCPS.", ime );
+ }
+
+ }
+
+ public boolean equals( InterpolationMethod im ) {
+
+ return interpolationType.equals( im.interpolationType ) && nullResistance.equals( im.nullResistance );
+
+ }
+
+ public String getInterpolationType() {
+
+ return interpolationType;
+
+ }
+
+ public String getNullResistance() {
+
+ return nullResistance;
+
+ }
+
+}
diff --git a/src/wcps/server/core/InvalidMetadataException.java b/src/wcps/server/core/InvalidMetadataException.java
new file mode 100644
index 0000000..27c2615
--- /dev/null
+++ b/src/wcps/server/core/InvalidMetadataException.java
@@ -0,0 +1,15 @@
+package wcps.server.core;
+
+// Thrown when WCPS received a request, but could not evaluate it because the metadata for some coverage does not conform to the WCPS standard.
+
+public class InvalidMetadataException extends WCPSException {
+
+ private static final long serialVersionUID = 48924938L;
+
+ public InvalidMetadataException( String message ) {
+
+ super( message, null );
+
+ }
+
+}
diff --git a/src/wcps/server/core/InvalidRequestException.java b/src/wcps/server/core/InvalidRequestException.java
new file mode 100644
index 0000000..ce0acad
--- /dev/null
+++ b/src/wcps/server/core/InvalidRequestException.java
@@ -0,0 +1,21 @@
+package wcps.server.core;
+
+// This exception is throws whenever a user submits a request that is not valid in some way.
+
+public class InvalidRequestException extends WCPSException {
+
+ private static final long serialVersionUID = 65492846L;
+
+ public InvalidRequestException( String message ) {
+
+ super( message, null );
+
+ }
+
+ public InvalidRequestException( String message, Throwable cause ) {
+
+ super( message, cause );
+
+ }
+
+}
diff --git a/src/wcps/server/core/Metadata.java b/src/wcps/server/core/Metadata.java
new file mode 100644
index 0000000..0f86a6f
--- /dev/null
+++ b/src/wcps/server/core/Metadata.java
@@ -0,0 +1,617 @@
+package wcps.server.core;
+
+import java.math.BigInteger;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+// This class implements WCPS metadata. For information on what each field means, see the WCPS standard. This class provides extensive error cheching and well as various utility functions.
+
+class Metadata implements Cloneable {
+
+ private static final DateFormat iso8601 = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss" );
+
+ private List<CellDomainElement> cellDomain;
+ private String coverageName;
+ private List<DomainElement> domain;
+ private InterpolationMethod interpolationDefault;
+ private Set<InterpolationMethod> interpolationSet;
+ private String nullDefault;
+ private Set<String> nullSet;
+ private List<RangeElement> range;
+
+ public Metadata( List<CellDomainElement> cellDomain, List<RangeElement> range, Set<String> nullSet, String nullDefault, Set<InterpolationMethod> interpolationSet, InterpolationMethod interpolationDefault, String coverageName, List<DomainElement> domain ) throws InvalidMetadataException {
+
+ if( cellDomain == null || range == null || coverageName == null || nullSet == null || interpolationSet == null ) {
+ throw new InvalidMetadataException( "Cell domain, range list, coverage name, null set, and interpolation set cannot be null" );
+ }
+
+ if( cellDomain.size() == 0 ) {
+ throw new InvalidMetadataException( "Invalid cell domain: At least one element is required" );
+ }
+ this.cellDomain = cellDomain;
+
+ if( range.size() == 0 ) {
+ throw new InvalidMetadataException( "At least one range element is required" );
+ }
+ this.range = new ArrayList<RangeElement>( range.size() );
+ Iterator<RangeElement> ir = range.iterator();
+ while( ir.hasNext() ) {
+ RangeElement next = ir.next();
+ Iterator<RangeElement> j = this.range.iterator();
+ while( j.hasNext() ) {
+ if( j.next().getName().equals( next.getName() ) ) {
+ throw new InvalidMetadataException( "Duplicate range element name encountered" );
+ }
+ }
+ this.range.add( next );
+ }
+
+ if( nullSet.size() == 0 ) { // TODO: check with Peter
+ throw new InvalidMetadataException( "Invalid null set: At least one null value is required" );
+ }
+ if( nullDefault == null ) {
+ throw new InvalidMetadataException( "Invalid null default: Null default cannot be null" );
+ }
+ if( !nullSet.contains( nullDefault ) ) {
+ throw new InvalidMetadataException( "Invalid null default: Default null value " + nullDefault + " is not part of the null set" );
+ }
+ Iterator<String> ns = nullSet.iterator();
+ while( ns.hasNext() ) {
+ String nullVal = ns.next();
+ List<String> nulls = SDU.str2string( nullVal );
+ if( nulls.size() != range.size() ) {
+ throw new InvalidMetadataException( "Invalid null value: " + nullVal + " must have " + range.size() + " axes according to the range specified for coverage " + coverageName );
+ }
+ Iterator<String> i = nulls.iterator();
+ Iterator<RangeElement> j = range.iterator();
+ while( j.hasNext() ) {
+ RangeElement re = j.next();
+ if( re.isBoolean() ) {
+ SDU.str2boolean( i.next() );
+ }
+ else if( re.isIntegral() ) {
+ SDU.str2integer( i.next() );
+ }
+ else if( re.isFloating() ) {
+ SDU.str2double( i.next() );
+ }
+ else if( re.isComplex() ) {
+ SDU.str2complex( i.next() );
+ }
+ }
+ }
+ this.nullSet = nullSet;
+ this.nullDefault = nullDefault;
+
+ if( interpolationSet.size() == 0 ) { // TODO: check with Peter
+ throw new InvalidMetadataException( "Invalid interpolation set: At least one interpolation method is required" );
+ }
+ if( interpolationDefault == null ) {
+ interpolationDefault = new InterpolationMethod( "none", "none" );
+ }
+ boolean defaultContainedInSet = false;
+ Iterator<InterpolationMethod> is = interpolationSet.iterator();
+ while( is.hasNext() ) {
+ if( interpolationDefault.equals( is.next() ) ) {
+ defaultContainedInSet = true;
+ }
+ }
+ if( !defaultContainedInSet ) {
+ throw new InvalidMetadataException( "Ivanlid interpolation default: Default interpolation method (" + interpolationDefault.getInterpolationType() + "," + interpolationDefault.getNullResistance() + ") is not part of the interpolation set" );
+ }
+ this.interpolationSet = interpolationSet;
+ this.interpolationDefault = interpolationDefault;
+
+ this.coverageName = coverageName;
+
+ if( domain != null ) {
+ if( domain.size() != cellDomain.size() ) {
+ throw new InvalidMetadataException( "Domain and cell domain must have equal number of elements" );
+ }
+ this.domain = new ArrayList<DomainElement>( domain.size() );
+ Iterator<DomainElement> i = domain.iterator();
+ while( i.hasNext() ) {
+ DomainElement next = i.next();
+ Iterator<DomainElement> j = this.domain.iterator();
+ while( j.hasNext() ) {
+ DomainElement previous = j.next();
+ if( previous.getName().equals( next.getName() ) ) {
+ throw new InvalidMetadataException( "Duplicate domain element name encountered" );
+ }
+ if( previous.getType().equals( "temporal" ) && next.getType().equals( "temporal" ) ) {
+ throw new InvalidMetadataException( "Domain can contain at most one temporal axis" );
+ }
+ if( previous.getType().equals( "elevation" ) && next.getType().equals( "elevation" ) ) {
+ throw new InvalidMetadataException( "Domain can contain at most one elevation axis" );
+ }
+ if( previous.getType().equals( "x" ) && next.getType().equals( "x" ) ) {
+ throw new InvalidMetadataException( "Domain can contain at most one x axis" );
+ }
+ if( previous.getType().equals( "y" ) && next.getType().equals( "y" ) ) {
+ throw new InvalidMetadataException( "Domain can contain at most one y axis" );
+ }
+ if( next.getType().equals( "x" ) ) {
+ boolean l = false;
+ Iterator<DomainElement> k = domain.iterator();
+ while( k.hasNext() ) {
+ if( k.next().getType().equals( "y" ) ) {
+ l = true;
+ }
+ }
+ if( l == false ) {
+ throw new InvalidMetadataException( "If domain contains a x axis, it must contain a y axis as well" );
+ }
+ }
+ else if( next.getType().equals( "y" ) ) {
+ boolean l = false;
+ Iterator<DomainElement> k = domain.iterator();
+ while( k.hasNext() ) {
+ if( k.next().getType().equals( "x" ) ) {
+ l = true;
+ }
+ }
+ if( l == false ) {
+ throw new InvalidMetadataException( "If domain contains a y axis, it must contain a x axis as well" );
+ }
+ }
+ }
+ this.domain.add( next );
+ }
+ }
+
+ }
+
+ public Metadata clone() {
+
+ try {
+ List<CellDomainElement> cd = new ArrayList<CellDomainElement>( cellDomain.size() );
+ Iterator<CellDomainElement> i = cellDomain.iterator();
+ while( i.hasNext() ) {
+ cd.add( i.next().clone() );
+ }
+
+ List<RangeElement> r = new ArrayList<RangeElement>( range.size() );
+ Iterator<RangeElement> j = range.iterator();
+ while( j.hasNext() ) {
+ r.add( j.next().clone() );
+ }
+
+ List<DomainElement> d = new ArrayList<DomainElement>( domain.size() );
+ Iterator<DomainElement> k = domain.iterator();
+ while( k.hasNext() ) {
+ d.add( k.next().clone() );
+ }
+
+ Set<String> ns = new HashSet<String>( nullSet.size() );
+ Iterator<String> l = nullSet.iterator();
+ while( l.hasNext() ) {
+ ns.add( new String( l.next() ) );
+ }
+
+ Set<InterpolationMethod> is = new HashSet<InterpolationMethod>( interpolationSet.size() );
+ Iterator<InterpolationMethod> m = interpolationSet.iterator();
+ while( m.hasNext() ) {
+ is.add( m.next().clone() );
+ }
+
+ return new Metadata( cd, r, ns, new String( nullDefault ), is, interpolationDefault.clone(), new String( coverageName ), d );
+ }
+ catch( InvalidMetadataException ime ) {
+ throw new RuntimeException( "Invalid metadata while cloning Metadata. This is a software bug in WCPS.", ime );
+ }
+
+ }
+
+
+// public CellDomainElement getCellDomain( int index ) {
+//
+// return cellDomain.get( index );
+//
+// }
+
+ public Iterator<CellDomainElement> getCellDomainIterator() {
+
+ return cellDomain.iterator();
+
+ }
+
+ public Iterator<DomainElement> getDomainIterator() {
+ return domain.iterator();
+ }
+
+ public int getDimension() {
+
+ return cellDomain.size();
+
+ }
+
+
+// public DomainElement getDomainByType( String type ) {
+//
+// Iterator<DomainElement> i = domain.iterator();
+// DomainElement de;
+// while( i.hasNext() ) {
+// de = i.next();
+// if( de.getType().equals( type ) ) {
+// return de;
+// }
+// }
+// return null;
+//
+// }
+
+ public int getDomainIndexByName( String name ) {
+
+ Iterator<DomainElement> i = domain.iterator();
+ for( int index = 0; i.hasNext(); index++ ) {
+ if( i.next().getName().equals( name ) ) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+// public int getDomainIndexByType( String type ) {
+//
+// Iterator<DomainElement> i = domain.iterator();
+// for( int index = 0; i.hasNext(); index++ ) {
+// if( i.next().getName().equals( type ) ) {
+// return index;
+// }
+// }
+// return -1;
+//
+// }
+
+// public String getDomainType( int index ) {
+//
+// return domain.get( index ).getType();
+//
+// }
+
+ public String getNullDefault() {
+
+ return nullDefault;
+
+ }
+
+ public Set<String> getNullSet() {
+
+ return nullSet;
+
+ }
+
+// public String getRangeType( int index ) {
+//
+// return range.get( index ).getType();
+//
+// }
+
+// public String getRangeType( String name ) {
+//
+// String type = null;
+// Iterator<RangeElement> i = range.iterator();
+// RangeElement re;
+// while( i.hasNext() ) {
+// re = i.next();
+// if( re.getName().equals( name ) ) {
+// type = re.getType();
+// }
+// }
+// return type;
+//
+// }
+
+// public double getResolution( int i ) {
+//
+// DomainElement de = domain.get( i );
+// Double deLo = de.getNumLo();
+// Double deHi = de.getNumHi();
+// if( deLo == null ) {
+// return -1;
+// }
+//
+// CellDomainElement cde = cellDomain.get( i );
+// BigInteger cdeLo = cde.getLo();
+// BigInteger cdeHi = cde.getHi();
+//
+// return (deHi - deLo) / (cdeHi.subtract( cdeLo ).doubleValue() + 1);
+//
+// }
+
+// public boolean isCellDomainEqualTo( Metadata m ) {
+//
+// if( m == null ) {
+// return false;
+// }
+//
+// Iterator<CellDomainElement> i = cellDomain.iterator();
+// Iterator<CellDomainElement> j = m.cellDomain.iterator();
+// while( i.hasNext() && j.hasNext() ) {
+// if( !i.next().equals( j.next() ) ) {
+// return false;
+// }
+// }
+// if( i.hasNext() || j.hasNext() ) {
+// return false;
+// }
+// return true;
+//
+// }
+
+// public boolean isCrsValid( String crs ) {
+// return crs != null && (crs.equals( "" ) || crs.startsWith( "urn:ogc:def:crs:EPSG::" ));
+// }
+
+// public boolean isDomainEqualTo (Metadata m) {
+//
+// if( m == null ) {
+// return false;
+// }
+//
+// Iterator<DomainElement> i = domain.iterator();
+// Iterator<DomainElement> j = m.domain.iterator();
+// while( i.hasNext() && j.hasNext() ) {
+// if( !i.next().equals( j.next() ) ) {
+// return false;
+// }
+// }
+// if( i.hasNext() || j.hasNext() ) {
+// return false;
+// }
+// return true;
+//
+// }
+
+// public boolean isInterpolationMethodValid( String im ) {
+//
+// return im != null && im.equals( "nearest neighbor" );
+//
+// }
+
+ public boolean isRangeBoolean() {
+
+ Iterator<RangeElement> i = range.iterator();
+ while( i.hasNext() ) {
+ if( !i.next().isBoolean() ) {
+ return false;
+ }
+ }
+ return true;
+
+ }
+
+ public boolean isRangeComplex() {
+
+ Iterator<RangeElement> i = range.iterator();
+ while( i.hasNext() ) {
+ if( !i.next().isComplex() ) {
+ return false;
+ }
+ }
+ return true;
+
+ }
+
+ public boolean isRangeIntegral() {
+
+ Iterator<RangeElement> i = range.iterator();
+ while( i.hasNext() ) {
+ if( !i.next().isIntegral() ) {
+ return false;
+ }
+ }
+ return true;
+
+ }
+
+// public boolean isRangeEqualTo (Metadata m) {
+//
+// if( m == null ) {
+// return false;
+// }
+//
+// Iterator<RangeElement> i = range.iterator();
+// Iterator<RangeElement> j = m.range.iterator();
+// while( i.hasNext() && j.hasNext() ) {
+// if( !i.next().equals( j.next() ) ) {
+// return false;
+// }
+// }
+// if( i.hasNext() || j.hasNext() ) {
+// return false;
+// }
+// return true;
+//
+// }
+
+ public boolean isRangeFloating() {
+
+ Iterator<RangeElement> i = range.iterator();
+ while( i.hasNext() ) {
+ if( !i.next().isFloating() ) {
+ return false;
+ }
+ }
+ return true;
+
+ }
+
+ public boolean isRangeNumeric() {
+
+ Iterator<RangeElement> i = range.iterator();
+ while( i.hasNext() ) {
+ if( !i.next().isNumeric() ) {
+ return false;
+ }
+ }
+ return true;
+
+ }
+
+// public boolean isResolutionEqualTo( Metadata m ) {
+//
+// if( m == null || getDimension() != m.getDimension() ) {
+// return false;
+// }
+//
+// Iterator<CellDomainElement> cdIterator1 = cellDomain.iterator();
+// Iterator<CellDomainElement> cdIterator2 = m.cellDomain.iterator();
+// Iterator<DomainElement> dIterator1 = domain.iterator();
+// Iterator<DomainElement> dIterator2 = m.domain.iterator();
+// double resolution1;
+// double resolution2;
+// CellDomainElement cde;
+// DomainElement de;
+// Double deLo;
+// Double deHi;
+// BigInteger cdeLo;
+// BigInteger cdeHi;
+// while( cdIterator1.hasNext() ) {
+// cde = cdIterator1.next();
+// de = dIterator1.next();
+// deLo = de.getNumLo();
+// deHi = de.getNumHi();
+// if( deLo == null ) {
+// resolution1 = -1;
+// }
+// cdeLo = cde.getLo();
+// cdeHi = cde.getHi();
+// resolution1 = (deHi - deLo) / (cdeHi.subtract( cdeLo ).doubleValue() + 1);
+// cde = cdIterator1.next();
+// de = dIterator1.next();
+// deLo = de.getNumLo();
+// deHi = de.getNumHi();
+// if( deLo == null ) {
+// resolution2 = -1;
+// }
+// cdeLo = cde.getLo();
+// cdeHi = cde.getHi();
+// resolution2 = (deHi - deLo) / (cdeHi.subtract( cdeLo ).doubleValue() + 1);
+// if( resolution1 != resolution2 ) {
+// return false;
+// }
+// }
+// return true;
+//
+// }
+
+// public boolean isTypeValid( String type ) {
+// return type != null && (type.equals( "char" ) || type.equals( "unsigned char" ) || type.equals( "short" ) || type.equals( "unsigned short" ) || type.equals( "int" ) || type.equals( "unsigned int" ) || type.equals( "long" ) || type.equals( "unsigned long" ) || type.equals( "float" ) || type.equals( "double" )); // TODO: fix
+// }
+
+// public void removeFromCellDomain( int index ) throws InvalidMetadataException {
+//
+// cellDomain.remove( index );
+// if( cellDomain.size() == 0 ) {
+// throw new InvalidMetadataException( "Metadata transformation: Cell domain cannot be empty" );
+// }
+//
+// }
+
+// public void removeFromDomain( int index ) throws InvalidMetadataException {
+//
+// domain.remove( index );
+// if( domain.size() == 0 ) {
+// throw new InvalidMetadataException( "Metadata transformation: Domain cannot be empty" );
+// }
+//
+// }
+
+ public void setCoverageName( String coverageName ) throws InvalidMetadataException {
+
+ if( coverageName == null ) {
+ throw new InvalidMetadataException( "Metadata transformation: Coverage name cannot be null" );
+ }
+ this.coverageName = coverageName;
+
+ }
+
+// public void setCrs( String crs ) throws InvalidMetadataException {
+//
+// if( crs == null ) {
+// throw new InvalidMetadataException( "Metadata transformation: CRS cannot be null" );
+// }
+// if( !(crs.equals( "" ) || crs.startsWith( "urn:ogc:def:crs:EPSG::" )) ) {
+// throw new InvalidMetadataException( "Metadata transformation: Invalid CRS" );
+// }
+// this.crs = crs;
+//
+// }
+
+// public void setInterpolationMethodList( List<String> interpolationMethodList ) throws InvalidMetadataException {
+//
+// this.interpolationMethodList = interpolationMethodList;
+// Iterator<String> is = interpolationMethodList.iterator();
+// while( is.hasNext() ) {
+// String next = is.next();
+// if( !(next.equals( "nearest neighbor" ) || next.equals( "bilinear" ) || next.equals( "bicubic" ) || next.equals( "lost area" ) || next.equals( "barycentric" )) ) {
+// throw new InvalidMetadataException( "Metadata transformation: Invalid interpolation method" );
+// }
+// }
+//
+// }
+
+// public void setNullValue( String nullValue ) {
+//
+// this.nullValue = nullValue;
+//
+// }
+
+ public void setRangeType( String type ) throws InvalidMetadataException {
+
+ Iterator<RangeElement> i = range.iterator();
+ while( i.hasNext() ) {
+ i.next().setType( type );
+ }
+
+ }
+
+// public void setRangeType( List<String> types ) throws InvalidMetadataException {
+//
+// if( types.size() != range.size() ) {
+// throw new InvalidMetadataException( "Invalid range type: New type has " + types.size() + " elements, but range has " + range.size() + " elements" );
+// }
+// Iterator<RangeElement> i = range.iterator();
+// Iterator<String> j = types.iterator();
+// while( i.hasNext() ) {
+// i.next().setType( j.next() );
+// }
+//
+// }
+
+// public void updateCellDomain( int index, BigInteger lo, BigInteger hi ) throws InvalidMetadataException {
+//
+// cellDomain.set( index, new CellDomainElement( lo, hi ) );
+//
+// }
+
+// public void updateDomain( int index, Double numLo, Double numHi, String strLo, String strHi ) throws InvalidMetadataException {
+//
+// DomainElement old = domain.get( index );
+// domain.set( index, new DomainElement( old.getName(), old.getType(), numLo, numHi, strLo, strHi ) );
+//
+// }
+
+ public void updateNulls( Set<String> nullSet, String nullDefault ) throws InvalidMetadataException {
+
+ if( nullSet.size() == 0 ) { // TODO: check with Peter
+ throw new InvalidMetadataException( "Invalid null set: At least one null value is required" );
+ }
+ if( nullDefault == null ) {
+ nullDefault = "0"; // TODO: "false" for booleans, but check whether it is supported by rasdaman
+ }
+ if( !nullSet.contains( nullDefault ) ) {
+ throw new InvalidMetadataException( "Invalid null default: Default null value " + nullDefault + " is not part of the null set" );
+ }
+ this.nullSet = nullSet;
+ this.nullDefault = nullDefault;
+
+ }
+
+}
diff --git a/src/wcps/server/core/MetadataSource.java b/src/wcps/server/core/MetadataSource.java
new file mode 100644
index 0000000..5403a15
--- /dev/null
+++ b/src/wcps/server/core/MetadataSource.java
@@ -0,0 +1,13 @@
+package wcps.server.core;
+
+import java.util.Set;
+
+// A MetadataSource is anything that can read metadata for a given coverage name. It must be able to list all coverages which it knows, return Metadata for each one, and also map a format (e.g. "png") to its mimetype (e.g. "image/png").
+
+public interface MetadataSource {
+
+ public Set<String> coverages() throws ResourceException;
+ public String mimetype( String format );
+ public Metadata read( String coverageName ) throws InvalidRequestException, ResourceException;
+
+}
diff --git a/src/wcps/server/core/ProcessCoverageRequest.java b/src/wcps/server/core/ProcessCoverageRequest.java
new file mode 100644
index 0000000..08cb076
--- /dev/null
+++ b/src/wcps/server/core/ProcessCoverageRequest.java
@@ -0,0 +1,175 @@
+package wcps.server.core;
+import org.w3c.dom.*;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+
+import org.odmg.Database;
+import org.odmg.DBag;
+import org.odmg.Implementation;
+import org.odmg.ODMGException;
+import org.odmg.OQLQuery;
+import org.odmg.QueryException;
+import org.odmg.Transaction;
+import org.xml.sax.SAXException;
+import rasj.RasGMArray;
+import rasj.RasImplementation;
+
+
+// A ProcessCoverage request is just a list of rasdaman queries.
+
+public class ProcessCoverageRequest {
+
+ private ArrayList<CoverageIterator> iterators;
+ private IRasNode where;
+ private IRasNode coverageExpr;
+ private MetadataSource source;
+ private String url;
+ private String database;
+ private String mime;
+
+ public ProcessCoverageRequest(String url, String database, Node node, MetadataSource source) throws WCPSException {
+ super();
+ this.source = source;
+ this.url = url;
+ this.database = database;
+ Node x = node.getFirstChild();
+ if (!x.getNodeName().equals("processCoverage"))
+ throw new WCPSException("The document contains an unrecognized node : " + x.getNodeName());
+ x = x.getFirstChild();
+ iterators = new ArrayList<CoverageIterator>();
+ while (x != null) {
+ if (x.getNodeName().equals("#text")) {
+ x = x.getNextSibling();
+ continue;
+ }
+ System.err.println("The current node is: " + x.getNodeName());
+ if (x.getNodeName().equals("coverageIterator")) {
+ iterators.add(new CoverageIterator(x, this));
+ } else if (x.getNodeName().equals("where")) {
+ where = new BooleanScalarExprType(x.getFirstChild(), this);
+ } else if (x.getNodeName().equals("encode")) {
+ EncodeDataExprType encode;
+ encode = new EncodeDataExprType(x, this);
+ coverageExpr = encode;
+ mime = encode.getMime();
+ } else {
+ // It has to be a scalar Expr Type
+ coverageExpr = new ScalarExprType(x, this);
+ mime = "text/plain";
+ }
+ x = x.getNextSibling();
+ }
+ }
+
+
+ public String getMime() {
+ return mime;
+ }
+
+ public MetadataSource getMetadataSource() {
+ return source;
+ }
+
+ public Boolean isIteratorDefined(String iteratorName) {
+ Iterator<CoverageIterator> it = iterators.iterator();
+ while (it.hasNext()) {
+ CoverageIterator tmp = it.next();
+ if (iteratorName.equals(tmp.getIteratorName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public String getQuery() {
+ String result = "select " + coverageExpr.toRasQL() + " from ";
+ Iterator<CoverageIterator> it = iterators.iterator();
+ boolean first = true;
+ while (it.hasNext()) {
+ if (first) {
+ first = false;
+ } else {
+ result += ", ";
+ }
+ result += it.next().toRasQL();
+ }
+ if (where != null)
+ result += " where " + where.toRasQL();
+ return result;
+
+ }
+
+ public Iterator<String> getCoverages(String iteratorName) throws WCPSException {
+ for (int i = 0; i< iterators.size(); ++i) {
+ if (iterators.get(i).getIteratorName().equals(iteratorName)) {
+ return iterators.get(i).getCoverages();
+ }
+ }
+ throw new WCPSException("Iterator " + iteratorName + " not defined");
+ }
+
+ public List<byte[]> execute() throws ResourceException {
+ ArrayList<byte[]> results = new ArrayList<byte[]>();
+ if (coverageExpr != null) {
+ Implementation impl = new RasImplementation( url );
+ Database db = impl.newDatabase();
+ try {
+ db.open( database, Database.OPEN_READ_ONLY );
+ } catch( ODMGException odmge ) {
+ try {
+ db.close();
+ }
+ catch (ODMGException e) {}
+ throw new ResourceException( "Could not connect to rasdaman at " + url + ", database " + database, odmge );
+ }
+ Transaction tr = impl.newTransaction();
+ tr.begin();
+ OQLQuery q = impl.newOQLQuery();
+ DBag resultSet;
+ try {
+ q.create( this.getQuery() );
+ resultSet = (DBag) q.execute();
+ if( resultSet != null ) {
+ Iterator resultIterator = resultSet.iterator();
+ while( resultIterator.hasNext() ) {
+ Object current = resultIterator.next();
+ try{
+ RasGMArray resultArray = (RasGMArray) current;
+ results.add( resultArray.getArray() );
+ } catch (ClassCastException e) { // not a RasGMarray
+ if (!mime.equals("text/plain"))
+ throw new ResourceException("Incompatible mime and data type!");
+ System.err.println("result="+current.toString());
+ results.add( current.toString().getBytes() );
+
+ }
+
+
+/* if (mime.equals("text/plain")) {
+ System.err.println("dataType is :" + resultArray.getBaseTypeSchema().toString());
+ }*/
+
+ }
+ }
+ } catch (QueryException qe) {
+ tr.commit();
+ try {
+ db.close();
+ } catch (ODMGException odmge) {}
+ throw new ResourceException ( "Could not evaluate rasdaman query: '" + getQuery() + "'", qe );
+ }
+ tr.commit();
+ try {
+ db.close();
+ } catch (ODMGException odmge) {}
+ }
+ if (mime.equals("text/plain")) {
+
+ }
+ return results;
+
+ }
+
+}
diff --git a/src/wcps/server/core/RangeElement.java b/src/wcps/server/core/RangeElement.java
new file mode 100644
index 0000000..7d38753
--- /dev/null
+++ b/src/wcps/server/core/RangeElement.java
@@ -0,0 +1,126 @@
+package wcps.server.core;
+
+// A single component of a coverage's range. See the WCPS standard for more information.
+
+class RangeElement implements Cloneable {
+
+ private String name;
+ private String type;
+
+ public RangeElement( String name, String type ) throws InvalidMetadataException {
+
+ if( name == null || type == null ) {
+ throw new InvalidMetadataException( "Invalid range element: Element name and type cannot be null" );
+ }
+ if( name.equals( "" ) ) {
+ throw new InvalidMetadataException( "Invalid range element: Element name cannot be empty" );
+ }
+
+ if( !(type.equals( "boolean" ) || type.equals( "char" ) || type.equals( "unsigned char" ) || type.equals( "short" ) || type.equals( "unsigned short" ) || type.equals( "int" ) || type.equals( "unsigned int" ) || type.equals( "long" ) || type.equals( "unsigned long" ) || type.equals( "float" ) || type.equals( "double" ) || type.equals( "complex" ) || type.equals( "complex2" )) ) {
+ throw new InvalidMetadataException( "Invalid range element: Invalid element type:" + type );
+ }
+
+ this.name = name;
+ this.type = type;
+
+ }
+
+ public RangeElement clone() {
+
+ try {
+ return new RangeElement( new String( name ), new String( type ) );
+ }
+ catch( InvalidMetadataException ime ) {
+ throw new RuntimeException( "Invalid metadata while cloning RangeElement. This is a software bug in WCPS.", ime );
+ }
+
+ }
+
+ public boolean equals( RangeElement re ) {
+
+ return name.equals( re.type );
+
+ }
+
+ public String getName() {
+
+ return name;
+
+ }
+
+ public String getType() {
+
+ return type;
+
+ }
+
+ public boolean isBoolean() {
+
+ return type.equals( "boolean" );
+
+ }
+
+ public static boolean isBoolean( String type ) {
+
+ return type.equals( "boolean" );
+
+ }
+
+ public boolean isComplex() {
+
+ return type.equals( "complex" ) || type.equals( "complex2" );
+
+ }
+
+ public static boolean isComplex( String type ) {
+
+ return type.equals( "complex" ) || type.equals( "complex2" );
+
+ }
+
+ public boolean isIntegral() {
+
+ return type.equals( "char" ) || type.equals( "short" ) || type.equals( "unsigned short" ) || type.equals( "int" ) || type.equals( "unsigned int" ) || type.equals( "long" ) || type.equals( "unsigend long" );
+
+ }
+
+ public static boolean isIntegral( String type ) {
+
+ return type.equals( "char" ) || type.equals( "short" ) || type.equals( "unsigned short" ) || type.equals( "int" ) || type.equals( "unsigned int" ) || type.equals( "long" ) || type.equals( "unsigend long" );
+
+ }
+
+ public boolean isFloating() {
+
+ return type.equals( "float" ) || type.equals( "double" );
+
+ }
+
+ public static boolean isFloating( String type ) {
+
+ return type.equals( "float" ) || type.equals( "double" );
+
+ }
+
+ public boolean isNumeric() {
+
+ return type.equals( "char" ) || type.equals( "short" ) || type.equals( "unsigned short" ) || type.equals( "int" ) || type.equals( "unsigned int" ) || type.equals( "long" ) || type.equals( "unsigend long" ) || type.equals( "float" ) || type.equals( "double" ) || type.equals( "complex" ) || type.equals( "complex2" );
+
+ }
+
+ public static boolean isNumeric( String type ) {
+
+ return type.equals( "char" ) || type.equals( "short" ) || type.equals( "unsigned short" ) || type.equals( "int" ) || type.equals( "unsigned int" ) || type.equals( "long" ) || type.equals( "unsigend long" ) || type.equals( "float" ) || type.equals( "double" ) || type.equals( "complex" ) || type.equals( "complex2" );
+
+ }
+
+ public void setType( String type ) throws InvalidMetadataException {
+
+ if( !(type.equals( "boolean" ) || type.equals( "char" ) || type.equals( "unsigned char" ) || type.equals( "short" ) || type.equals( "unsigned short" ) || type.equals( "int" ) || type.equals( "unsigned int" ) || type.equals( "long" ) || type.equals( "unsigned long" ) || type.equals( "float" ) || type.equals( "double" ) || type.equals( "complex" ) || type.equals( "complex2" )) ) {
+ throw new InvalidMetadataException( "Invalid range element: Invalid element type:" + type);
+ }
+ this.type = type;
+
+ }
+
+}
diff --git a/src/wcps/server/core/ReduceScalarExprType.java b/src/wcps/server/core/ReduceScalarExprType.java
new file mode 100644
index 0000000..2cbbe08
--- /dev/null
+++ b/src/wcps/server/core/ReduceScalarExprType.java
@@ -0,0 +1,29 @@
+package wcps.server.core;
+
+import org.w3c.dom.*;
+
+public class ReduceScalarExprType implements IRasNode {
+
+ CoverageExprType expr;
+ String op;
+
+ public ReduceScalarExprType(Node node, ProcessCoverageRequest pcr) throws WCPSException {
+ String nodeName = node.getNodeName();
+ if (nodeName.equals("all") || nodeName.equals("some") || nodeName.equals("count") || nodeName.equals("add") || nodeName.equals("avg") ||
+ nodeName.equals("min") || nodeName.equals("max")) {
+ op = nodeName;
+ if (!op.equals("all") && !op.equals("some"))
+ op = op + "_cells";
+ node = node.getFirstChild();
+ while (node != null && node.getNodeName() == "#text")
+ node = node.getNextSibling();
+ expr = new CoverageExprType(node, pcr);
+ } else
+ throw new WCPSException("invalid ReduceScalarExprType node : " + nodeName);
+ }
+
+ public String toRasQL() {
+
+ return op + "(" + expr.toRasQL() +")";
+ }
+} \ No newline at end of file
diff --git a/src/wcps/server/core/ResourceException.java b/src/wcps/server/core/ResourceException.java
new file mode 100644
index 0000000..44bf7b3
--- /dev/null
+++ b/src/wcps/server/core/ResourceException.java
@@ -0,0 +1,19 @@
+package wcps.server.core;
+
+// This exception is thrown whenever some required resource is not available - a database connection, file, whatever.
+
+public class ResourceException extends WCPSException {
+
+ private static final long serialVersionUID = 45562458L;
+
+ public ResourceException( String message) {
+ super (message);
+ }
+
+ public ResourceException( String message, Throwable cause ) {
+
+ super( message, cause );
+
+ }
+
+}
diff --git a/src/wcps/server/core/SDU.java b/src/wcps/server/core/SDU.java
new file mode 100644
index 0000000..d0ca9de
--- /dev/null
+++ b/src/wcps/server/core/SDU.java
@@ -0,0 +1,156 @@
+package wcps.server.core;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.commons.math.complex.Complex;
+
+// This is a static utility class, which provides encoding and decoding of various datatypes from/to strings. It also handles packing and unpacking of structures.
+
+// TODO: fix complex conversion
+
+class SDU { // String Data Utility
+
+ public static String boolean2str( List<Boolean> boolea ) {
+
+ List<String> strings = new ArrayList<String>( boolea.size() );
+ Iterator<Boolean> i = boolea.iterator();
+ while( i.hasNext() ) {
+ strings.add( i.next().toString() );
+ }
+
+ return string2str( strings );
+
+ }
+
+ public static String complex2str( List<Complex> complex ) {
+
+ List<String> strings = new ArrayList<String>( complex.size() );
+ Iterator<Complex> i = complex.iterator();
+ while( i.hasNext() ) {
+ Complex c = i.next();
+ strings.add( c.getReal() + "#" + c.getImaginary() );
+ }
+
+ return string2str( strings );
+
+ }
+
+ public static String double2str( List<Double> doubl ) {
+
+ List<String> strings = new ArrayList<String>( doubl.size() );
+ Iterator<Double> i = doubl.iterator();
+ while( i.hasNext() ) {
+ strings.add( i.next().toString() );
+ }
+
+ return string2str( strings );
+
+ }
+
+ public static String integer2str( List<BigInteger> integer ) {
+
+ List<String> strings = new ArrayList<String>( integer.size() );
+ Iterator<BigInteger> i = integer.iterator();
+ while( i.hasNext() ) {
+ strings.add( i.next().toString() );
+ }
+
+ return string2str( strings );
+
+ }
+
+ public static List<Boolean> str2boolean( String string ) {
+
+ List<String> strings = str2string( string );
+
+ List<Boolean> booleans = new ArrayList<Boolean>( strings.size() );
+ Iterator<String> i = strings.iterator();
+ while( i.hasNext() ) {
+ booleans.add( new Boolean( i.next().equals( "true" ) ) );
+ }
+
+ return booleans;
+
+ }
+
+ public static List<Complex> str2complex( String string ) {
+
+ List<String> strings = str2string( string );
+
+ List<Complex> complexes = new ArrayList<Complex>( strings.size() );
+ Iterator<String> i = strings.iterator();
+ while( i.hasNext() ) {
+ String[] complex = i.next().split( "#" );
+ complexes.add( new Complex( new Double( complex[0] ), new Double( complex[1] ) ) );
+ }
+
+ return complexes;
+
+ }
+
+ public static List<Double> str2double( String string ) {
+
+ List<String> strings = str2string( string );
+
+ List<Double> doubles = new ArrayList<Double>( strings.size() );
+ Iterator<String> i = strings.iterator();
+ while( i.hasNext() ) {
+ doubles.add( new Double( i.next() ) );
+ }
+
+ return doubles;
+
+ }
+
+ public static List<BigInteger> str2integer( String string ) {
+
+ List<String> strings = str2string( string );
+
+ List<BigInteger> integers = new ArrayList<BigInteger>( strings.size() );
+ Iterator<String> i = strings.iterator();
+ while( i.hasNext() ) {
+ integers.add( new BigInteger( i.next() ) );
+ }
+
+ return integers;
+
+ }
+
+ public static List<String> str2string( String string ) {
+
+ List<String> strings;
+
+ if( string.startsWith( "{" ) && string.contains( "," ) && string.endsWith( "}" ) ) {
+ String[] components = string.substring( 1, string.length() - 1 ).split( "," );
+
+ strings = new ArrayList<String>( components.length );
+ for( int i = 0; i < components.length; i++ ) {
+ strings.add( new String( components[i] ) );
+ }
+
+ return strings;
+ }
+ else {
+ strings = new ArrayList<String>( 1 );
+ strings.add( new String( string ) );
+
+ return strings;
+ }
+
+ }
+
+ public static String string2str( List<String> strin ) {
+
+ String string = "{";
+ Iterator<String> i = strin.iterator();
+ while( i.hasNext() ) {
+ string += i.next() + (i.hasNext() ? "," : "}" );
+ }
+
+ return string;
+
+ }
+
+}
diff --git a/src/wcps/server/core/ScalarExprType.java b/src/wcps/server/core/ScalarExprType.java
new file mode 100644
index 0000000..4c3a57d
--- /dev/null
+++ b/src/wcps/server/core/ScalarExprType.java
@@ -0,0 +1,78 @@
+package wcps.server.core;
+
+import org.w3c.dom.*;
+
+public class ScalarExprType implements IRasNode {
+ private String type; // can be simple (just a value), unary, binary, function or defered
+ private String value;
+ private String op;
+ private IRasNode first,second;
+
+ public ScalarExprType(Node node, ProcessCoverageRequest pcr) throws WCPSException {
+ while (node.getNodeName().equals("#text")) node = node.getNextSibling();
+ String nodeName = node.getNodeName();
+
+ if (nodeName.equals("scalar")) {
+ type = "simple";
+ value = node.getFirstChild().getNodeValue();
+ } else if (nodeName.equals("scalarUnaryPlus") || nodeName.equals("scalarUnaryMinus")) {
+ type = "unary";
+ op = (nodeName.equals("scalarUnaryPlus") ? "+" : "-");
+ first = new ScalarExprType(node.getFirstChild(), pcr);
+ } else if (nodeName.equals("scalarPlus") || nodeName.equals("scalarMinus") || nodeName.equals("scalarMult") || nodeName.equals("scalarDiv")) {
+ type = "binary";
+ if (nodeName.equals("scalarPlus")) op = "+";
+ if (nodeName.equals("scalarMinus")) op = "-";
+ if (nodeName.equals("scalarMult")) op = "*";
+ if (nodeName.equals("scalarDiv")) op = "/";
+ Node child = node.getFirstChild();
+ first = new ScalarExprType(child, pcr);
+ child = child.getNextSibling();
+ second = new ScalarExprType(child, pcr);
+ } else if (nodeName.equals("scalarAbs")) {
+ type= "function";
+ op = "abs";
+ first = new ScalarExprType(node.getFirstChild(), pcr);
+ } else {
+ type = "defered";
+ try {
+ first = new BooleanScalarExprType(node, pcr);
+ } catch (WCPSException e) {}
+
+ if (first == null) {
+ try {
+ first = new ReduceScalarExprType(node, pcr);
+ } catch (WCPSException e) {}
+ }
+// TODO(smsorin): This should be added, eventually...
+/* if (first == null) {
+ try {
+ first = new CondenseScalarExprType(Node, pcr);
+ } catch (WCPSException e) {}
+ }
+
+ if (first == null) {
+ try {
+ first = new GetMetadataScalarExprType(Node, pcr);
+ } catch (WCPSException e) {}
+ }*/
+
+ if (first == null)
+ throw new WCPSException("Unexpected Scalar Expression node : " + node.getNodeName());
+ }
+ }
+
+ public String toRasQL() {
+ if (type.equals("simple"))
+ return value;
+ if (type.equals("unary"))
+ return op + "(" + first.toRasQL() + ")";
+ if (type.equals("binary"))
+ return "(" + first.toRasQL() + ")" + op + "(" + second.toRasQL() + ")";
+ if (type.equals("function"))
+ return op + "(" + first.toRasQL() + ")";
+ if (type.equals("defered"))
+ return first.toRasQL();
+ return "";
+ }
+}
diff --git a/src/wcps/server/core/SliceCoverageExprType.java b/src/wcps/server/core/SliceCoverageExprType.java
new file mode 100644
index 0000000..86b3513
--- /dev/null
+++ b/src/wcps/server/core/SliceCoverageExprType.java
@@ -0,0 +1,95 @@
+package wcps.server.core;
+
+import org.w3c.dom.*;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.math.BigInteger;
+
+public class SliceCoverageExprType implements IRasNode, ICoverageInfo {
+
+ private class axisSpec {
+ public String axisName;
+ public String crs;
+ public int sliceId;
+ };
+
+ private List <axisSpec> axisList;
+ private CoverageExprType coverageExprType;
+ private CoverageInfo coverageInfo;
+ private int dims;
+ private String [] dim;
+
+ public CoverageInfo getCoverageInfo() {
+ return coverageInfo;
+ }
+
+ public SliceCoverageExprType (Node node, ProcessCoverageRequest source) throws WCPSException{
+ Node child, axisNode;
+ String nodeName;
+ axisList = new ArrayList<axisSpec> ();
+
+ for (child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
+ nodeName = child.getNodeName();
+ if (nodeName.equals("#text"))
+ continue;
+
+ if (nodeName.equals("sliceAxisSpec")) {
+ axisSpec axis = new axisSpec();
+ String childName;
+ for (axisNode = child.getFirstChild(); axisNode != null; axisNode = axisNode.getNextSibling()) {
+ childName = axisNode.getNodeName();
+ if (childName.equals("#text")) continue;
+
+ if (childName.equals("axis")) {
+ axis.axisName = axisNode.getFirstChild().getNodeValue();
+ continue;
+ }
+ if (childName.equals("crs")) {
+ axis.crs = axisNode.getFirstChild().getNodeValue();
+ continue;
+ }
+ if (childName.equals("coord")) {
+ CoordinateType coord = new CoordinateType(axisNode);
+ axis.sliceId = coord.getValue();
+ }
+ }
+ axisList.add(axis);
+ continue;
+ }
+
+ // else is a coverage expression type
+ coverageExprType = new CoverageExprType(child, source);
+ coverageInfo = new CoverageInfo(coverageExprType.getCoverageInfo());
+ }
+ dims = coverageInfo.getNumDimensions();
+ dim = new String[dims];
+ for (int j=0; j<dims; ++j)
+ dim[j]="*:*";
+
+ Iterator <axisSpec> i = axisList.iterator();
+ axisSpec axis;
+ int axisId;
+ int axisLo, axisHi;
+ while (i.hasNext()) {
+ axis = i.next();
+ axisId = coverageInfo.getDomainIndexByName(axis.axisName);
+ axisLo = axis.sliceId;
+ axisHi = axis.sliceId;
+ dim[axisId]=""+axisLo;
+ coverageInfo.setCellDimension(axisId, new CellDomainElement(BigInteger.valueOf(axisLo), BigInteger.valueOf(axisHi)));
+ }
+
+ }
+
+ public String toRasQL() {
+ String result = coverageExprType.toRasQL()+"[";
+ for (int j=0; j<dims; ++j) {
+ if (j>0)
+ result += ",";
+ result += dim[j];
+ }
+ result += "]";
+ return result;
+ }
+};
diff --git a/src/wcps/server/core/TrimCoverageExprType.java b/src/wcps/server/core/TrimCoverageExprType.java
new file mode 100644
index 0000000..8b222ff
--- /dev/null
+++ b/src/wcps/server/core/TrimCoverageExprType.java
@@ -0,0 +1,102 @@
+package wcps.server.core;
+
+import org.w3c.dom.*;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.math.BigInteger;
+
+
+public class TrimCoverageExprType implements IRasNode, ICoverageInfo {
+
+ private class axisSpec {
+ public String axisName;
+ public String crs;
+ public List<Integer> coords = new ArrayList<Integer> ();
+ };
+
+ private List <axisSpec> axisList;
+ private CoverageExprType coverageExprType;
+ private CoverageInfo coverageInfo;
+ private int dims;
+ private String [] dim;
+
+ public CoverageInfo getCoverageInfo() {
+ return coverageInfo;
+ }
+
+ public TrimCoverageExprType (Node node, ProcessCoverageRequest source) throws WCPSException{
+ Node child, axisNode;
+ String nodeName;
+ axisList = new ArrayList<axisSpec> ();
+
+ for (child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
+ nodeName = child.getNodeName();
+ if (nodeName.equals("#text")) continue;
+
+ if (nodeName.equals("trimAxisSpec")) {
+ axisSpec axis = new axisSpec();
+ String childName;
+ for (axisNode = child.getFirstChild(); axisNode != null; axisNode = axisNode.getNextSibling()) {
+ childName = axisNode.getNodeName();
+ if (childName.equals("axis")) {
+ axis.axisName = axisNode.getFirstChild().getNodeValue();
+ continue;
+ }
+ if (childName.equals("crs")) {
+ axis.crs = axisNode.getFirstChild().getNodeValue();
+ continue;
+ }
+ if (childName.equals("cellCoord") || childName.equals("domainCoord")) {
+ CoordinateType coord = new CoordinateType(axisNode);
+ axis.coords.add(coord.getValue());
+ }
+ }
+ axisList.add(axis);
+ continue;
+ }
+
+ // else is a coverage expression type
+ coverageExprType = new CoverageExprType(child, source);
+ coverageInfo = coverageExprType.getCoverageInfo();
+ }
+
+ dims = coverageInfo.getNumDimensions();
+ dim = new String[dims];
+ for (int j=0; j<dims; ++j)
+ dim[j]="*:*";
+
+
+ Iterator <axisSpec> i = axisList.iterator();
+ System.out.println("AxisList count:" + axisList.size());
+ axisSpec axis;
+ int axisId;
+ int axisLo, axisHi;
+ while (i.hasNext()) {
+ axis = i.next();
+ axisId = coverageInfo.getDomainIndexByName(axis.axisName);
+ System.out.println("Axis ID: " + axisId);
+ System.out.println("Axis name: " + axis.axisName);
+ System.out.println("Axis coords size: " + axis.coords.size());
+ System.out.print("Axis coords: ");
+ for (int ii=0; ii < axis.coords.size(); ii++)
+ System.out.print(axis.coords.get(ii) + ", ");
+
+ axisLo = axis.coords.get(0);
+ axisHi = axis.coords.get(1);
+ dim[axisId]=axisLo+":"+axisHi;
+ coverageInfo.setCellDimension(axisId, new CellDomainElement(BigInteger.valueOf(axisLo), BigInteger.valueOf(axisHi)));
+ }
+ }
+
+ public String toRasQL() {
+ String result = coverageExprType.toRasQL()+"[";
+ for (int j=0; j<dims; ++j) {
+ if (j>0)
+ result += ",";
+ result += dim[j];
+ }
+ result += "]";
+ return result;
+ }
+};
diff --git a/src/wcps/server/core/UnaryOperationCoverageExprType.java b/src/wcps/server/core/UnaryOperationCoverageExprType.java
new file mode 100644
index 0000000..9f412ee
--- /dev/null
+++ b/src/wcps/server/core/UnaryOperationCoverageExprType.java
@@ -0,0 +1,96 @@
+package wcps.server.core;
+
+import org.w3c.dom.*;
+
+public class UnaryOperationCoverageExprType implements IRasNode, ICoverageInfo {
+
+ private String operation;
+ private CoverageExprType child;
+ private String params;
+ private CoverageInfo info;
+
+ public UnaryOperationCoverageExprType(Node node, ProcessCoverageRequest pcr) throws WCPSException {
+ String nodeName = node.getNodeName();
+ System.err.println("Trying to parse unary operation: " + nodeName);
+ if (nodeName.equals("unaryPlus")) {
+ operation = "+";
+ child = new CoverageExprType(node.getFirstChild(), pcr);
+ } else if (nodeName.equals("unaryMinus")) {
+ operation = "-";
+ child = new CoverageExprType(node.getFirstChild(), pcr);
+ } else if (nodeName.equals("sqrt") || nodeName.equals("abs") || nodeName.equals("exp") || nodeName.equals("log") ||
+ nodeName.equals("ln") || nodeName.equals("sin") || nodeName.equals("cos") || nodeName.equals("tan") ||
+ nodeName.equals("sinh") || nodeName.equals("cosh") || nodeName.equals("tanh") || nodeName.equals("arcsin") ||
+ nodeName.equals("arccos") || nodeName.equals("arctan") || nodeName.equals("not")) {
+ operation = nodeName;
+ child = new CoverageExprType(node.getFirstChild(), pcr);
+ } else if (nodeName.equals("bit")) {
+ operation = "bit";
+ Node c = node.getFirstChild();
+ while (c != null) {
+ if (c.getNodeName().equals("#text")) {
+ c = c.getNextSibling();
+ continue;
+ }
+ if (c.getNodeName().equals("position")) {
+ params = c.getFirstChild().getNodeValue();
+ } else {
+ child = new CoverageExprType(c, pcr);
+ }
+ c = c.getNextSibling();
+ }
+ } else if (nodeName.equals("cast")) {
+ operation = "cast";
+ Node c = node.getFirstChild();
+ while (c != null) {
+ if (c.getNodeName().equals("#text")) {
+ c = c.getNextSibling();
+ continue;
+ }
+ if (c.getNodeName().equals("type")) {
+ params = c.getFirstChild().getNodeValue();
+ } else {
+ child = new CoverageExprType(c, pcr);
+ }
+ c = c.getNextSibling();
+ }
+ } else if (nodeName.equals("select")) {
+ operation = "select";
+ Node c = node.getFirstChild();
+ while (c != null) {
+ if (c.getNodeName().equals("#text")) {
+ c = c.getNextSibling();
+ continue;
+ }
+ if (c.getNodeName().equals("field")) {
+ params = c.getFirstChild().getNodeValue();
+ } else {
+ child = new CoverageExprType(c, pcr);
+ }
+ c = c.getNextSibling();
+ }
+ } else throw new WCPSException("Unknown unary operation: " + nodeName);
+ info = new CoverageInfo(child.getCoverageInfo());
+ }
+
+ public CoverageInfo getCoverageInfo() {
+ return info;
+ }
+
+ public String toRasQL() {
+ if (operation.equals("sqrt") || operation.equals("abs") || operation.equals("exp") || operation.equals("log") ||
+ operation.equals("ln") || operation.equals("sin") || operation.equals("cos") || operation.equals("tan") ||
+ operation.equals("sinh") || operation.equals("cosh") || operation.equals("tanh") || operation.equals("arcsin") ||
+ operation.equals("arccos") || operation.equals("arctan") || operation.equals("not") || operation.equals("+") || operation.equals("-")) {
+ return operation + "(" + child.toRasQL() + ")";
+ } else if (operation.equals("cast")) {
+ return "(" + params + ")(" + child.toRasQL() + ")";
+ } else if (operation.equals("select")) {
+ return "(" + child.toRasQL() + ")." + params;
+ } else if (operation.equals("bit")) {
+ return "bit(" + child.toRasQL() + "," + params +")";
+ }
+ return " error ";
+ }
+
+}
diff --git a/src/wcps/server/core/WCPS.java b/src/wcps/server/core/WCPS.java
new file mode 100644
index 0000000..d644198
--- /dev/null
+++ b/src/wcps/server/core/WCPS.java
@@ -0,0 +1,134 @@
+package wcps.server.core;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import javax.xml.XMLConstants;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.xml.sax.*;
+import org.odmg.Database;
+import org.odmg.DBag;
+import org.odmg.Implementation;
+import org.odmg.ODMGException;
+import org.odmg.OQLQuery;
+import org.odmg.QueryException;
+import org.odmg.Transaction;
+import org.w3c.dom.*;
+import org.xml.sax.SAXException;
+import rasj.RasGMArray;
+import rasj.RasImplementation;
+
+// This is the WCPS entry point. Processing a ProcessCoverage request happens in two stages. The first stage is the various pcPrepare functions, where XML is parsed, metadata is loaded, and the request is translated into an instance of a ProcessCoverageRequest. This data structure, for the time being, is just a list of rasdaman queries (RasQuery). The second stage is pcExecute, which executes a ProcessCoverageRequests and returns data.
+
+public class WCPS {
+
+ private static final String SCHEMA_PACKAGE_PROCESSCOVERAGE = "wcps.xml.processcoverage";
+
+ private MetadataSource metadataSource;
+ private DocumentBuilder wcpsDocumentBuilder;
+
+ public WCPS( File pcSchema, MetadataSource metadataSource ) throws WCPSException {
+ try {
+ DocumentBuilderFactory dbconfig = DocumentBuilderFactory.newInstance();
+ dbconfig.setValidating(false); // use XML schema not DTD
+ dbconfig.setIgnoringComments(true); // comments are not relevant
+ dbconfig.setIgnoringElementContentWhitespace(true); // remve the ignorable whitespace
+ Schema wcpsProcessCoverageSchema = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI ).newSchema( pcSchema );
+ dbconfig.setSchema(wcpsProcessCoverageSchema);
+ wcpsDocumentBuilder = dbconfig.newDocumentBuilder();
+ } catch (Exception e) {
+ throw new WCPSException("Error while loading the document builder interface!", e);
+ }
+
+ this.metadataSource = metadataSource;
+ }
+
+ public List<byte[]> pcExecute( String url, String database, ProcessCoverageRequest pcRequest ) throws ResourceException {
+ throw new ResourceException("Mothod not implemented! pcExecute");
+/* List<RasQuery> queries = pcRequest.getQueries();
+ List<byte[]> results = new ArrayList<byte[]>( queries.size() );
+ synchronized( this ) {
+ Implementation impl = new RasImplementation( url );
+ Database db = impl.newDatabase();
+ try {
+ db.open( database, Database.OPEN_READ_ONLY );
+ }
+ catch( ODMGException odmge ) {
+ try {
+ db.close();
+ }
+ catch (ODMGException e) {}
+ throw new ResourceException( "Could not connect to rasdaman at " + url + ", database " + database, odmge );
+ }
+ Transaction tr = impl.newTransaction();
+ tr.begin();
+ Iterator<RasQuery> queryIterator = queries.iterator();
+ while( queryIterator.hasNext() ) {
+ String query = queryIterator.next().toString();
+ OQLQuery q = impl.newOQLQuery();
+ DBag resultSet;
+ try {
+ q.create( query );
+ resultSet = (DBag) q.execute();
+ if( resultSet != null ) {
+ Iterator resultIterator = resultSet.iterator();
+ while( resultIterator.hasNext() ) {
+ RasGMArray result = (RasGMArray) resultIterator.next();
+ results.add( result.getArray() );
+ }
+ }
+ }
+ catch (QueryException qe) {
+ tr.commit();
+ try {
+ db.close();
+ }
+ catch (ODMGException odmge) {}
+ throw new ResourceException ( "Could not evaluate rasdaman query: '" + query + "'", qe );
+ }
+ }
+ tr.commit();
+ try {
+ db.close();
+ }
+ catch (ODMGException odmge) {}
+ }
+ return results;
+*/
+ }
+
+ public ProcessCoverageRequest pcPrepare(String url, String database, File f) throws WCPSException, InvalidRequestException, ResourceException, SAXException, IOException {
+ return pcPrepare(url, database, wcpsDocumentBuilder.parse(f));
+ }
+
+ public ProcessCoverageRequest pcPrepare(String url, String database, InputStream is, String systemId ) throws WCPSException, InvalidRequestException, ResourceException, SAXException, IOException {
+ return pcPrepare(url, database, wcpsDocumentBuilder.parse(is, systemId));
+ }
+
+ public ProcessCoverageRequest pcPrepare(String url, String database, String uri) throws WCPSException, InvalidRequestException, ResourceException, SAXException, IOException {
+ return pcPrepare(url, database, wcpsDocumentBuilder.parse(uri));
+ }
+
+ public ProcessCoverageRequest pcPrepare(String url, String database, InputSource is) throws WCPSException, InvalidRequestException, ResourceException, SAXException, IOException {
+ return pcPrepare(url, database, wcpsDocumentBuilder.parse(is));
+ }
+
+ private ProcessCoverageRequest pcPrepare(String url, String database, Document doc ) throws WCPSException, InvalidRequestException, ResourceException {
+ return new ProcessCoverageRequest(url, database, doc, metadataSource);
+ }
+
+}
diff --git a/src/wcps/server/core/WCPSException.java b/src/wcps/server/core/WCPSException.java
new file mode 100644
index 0000000..0ccc769
--- /dev/null
+++ b/src/wcps/server/core/WCPSException.java
@@ -0,0 +1,19 @@
+package wcps.server.core;
+
+// This is the superclass of all WCPS exceptions.
+
+public class WCPSException extends Exception {
+
+ private static final long serialVersionUID = 113213254L;
+
+ public WCPSException( String message) {
+ super(message);
+ }
+
+ public WCPSException( String message, Throwable cause ) {
+
+ super( message, cause );
+
+ }
+
+}
diff --git a/src/wcps/server/servlet/WCPService.java b/src/wcps/server/servlet/WCPService.java
new file mode 100644
index 0000000..60e5b14
--- /dev/null
+++ b/src/wcps/server/servlet/WCPService.java
@@ -0,0 +1,244 @@
+package wcps.server.servlet;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.StringBufferInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.ServletException;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+
+import wcps.server.core.CachedMetadataSource;
+import wcps.server.core.DbMetadataSource;
+import wcps.server.core.ProcessCoverageRequest;
+import wcps.server.core.WCPS;
+import syntaxParser.WCPSParser;
+import syntaxParser.WCPSScanner;
+import syntaxParser.WCPSRequest;
+import syntaxParser.SyntaxErrorException;
+import java.io.StringBufferInputStream;
+import org.xml.sax.InputSource;
+// This is the servlet interface of WCPS. It mostly consists of sanity checks ana initialization, the meat is onyl a few lines. The WCPS class does the actual work.
+
+// Note an important limitation: this will only return the first result if several are available. The reason is that WCPS currently has no standardized way to return multiple byte streams to the user.
+
+public class WCPService extends HttpServlet {
+
+ private static final long serialVersionUID = 84786549L;
+
+ private Properties dbParams;
+ private DbMetadataSource metadataSource;
+ private String rasdamanUrl;
+ private String rasdamanDatabase;
+ private WCPS wcps;
+
+ public void init() throws ServletException {
+
+ try {
+ dbParams = new Properties();
+ System.out.println ("WCPS: loading database properties");
+ dbParams.load( new FileInputStream( getServletContext().getRealPath( "/dbparams.properties" ) ) );
+ rasdamanUrl = dbParams.getProperty( "rasdaman_url" );
+ rasdamanDatabase = dbParams.getProperty( "rasdaman_database" );
+
+ System.out.println ("WCPS: initializing metadata database");
+ metadataSource = new DbMetadataSource( dbParams.getProperty( "metadata_driver" ), dbParams.getProperty( "metadata_url" ), dbParams.getProperty( "metadata_user" ), dbParams.getProperty( "metadata_pass" ), false );
+
+ System.out.println( "WCPS: initializing WCPS core" );
+ wcps = new WCPS( new File( getServletContext().getRealPath( "/xml/ogc/wcps/1.0.0/wcpsProcessCoverage.xsd" ) ), new CachedMetadataSource( metadataSource ) );
+
+ System.out.println( "WCPS: initialization complete" );
+ }
+ catch( Exception e ) {
+ System.out.println( "WCPS: initialization error" );
+ System.out.println( "WCPS: closing metadata database" );
+ if (metadataSource != null) {
+ metadataSource.close();
+ }
+ System.out.println( "WCPS: done with init error" );
+ throw new ServletException( "WCPS initialization error", e );
+ }
+
+ }
+
+ public void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException {
+
+ System.out.println( "WCPS: invoked with GET" );
+ printUsage( response );
+
+ }
+
+ public void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ System.out.println ("WCPS: invoked with POST");
+ OutputStream webOut = null;
+ try {
+ String xmlRequest = null;
+
+ if( ServletFileUpload.isMultipartContent( request ) ) {
+ @SuppressWarnings( "unchecked" ) Iterator<FileItem> fileItems = (Iterator<FileItem>) (new ServletFileUpload( new DiskFileItemFactory() )).parseRequest( request ).iterator();
+ if( !fileItems.hasNext() ) {
+ throw new IOException( "Multipart POST request contains no parts" );
+ }
+ FileItem fileItem = fileItems.next();
+ if( fileItems.hasNext() ) {
+ throw new IOException( "Multipart POST request contains too many parts" );
+ }
+ if( !fileItem.isFormField() && fileItem.getContentType().equals( "text/xml" ) ) {
+ xmlRequest = fileItem.getString ();
+ }
+ if( xmlRequest == null ) {
+ System.out.println ("WCPS: no XML file was uploaded within multipart POST request");
+ printUsage( response );
+ return;
+ }
+ System.out.println ("WCPS: received XML via a multipart POST request");
+ }
+
+ else {
+ String xml = request.getParameter( "xml" );
+ String query = request.getParameter( "query" );
+ if( xml != null ) {
+ System.out.println( "WCPS: received XML via a 'xml' parameter in a POST request" );
+ xmlRequest = xml;
+ }
+ else if( query != null ) {
+ System.out.println( "WCPS: received the following query via a 'query' parameter in a POST request:" );
+ System.out.println( query );
+ /* The JLex doesn't handle newlines well.
+ We consider them as whitespace anyway so we substitute them here.
+ */
+ query = query.replace('\n', ' ');
+ query = query.replace('\r', ' ');
+ query = query.replace('\t', ' ');
+ log(query);
+ // Initialize the parser
+ WCPSParser parser = new WCPSParser(new WCPSScanner(new StringBufferInputStream(query)));
+ try {
+ WCPSRequest wcpsRequest = (WCPSRequest)parser.debug_parse().value;
+ xmlRequest = wcpsRequest.toXML();
+ } catch (SyntaxErrorException e) {
+ FormatSyntaxException(e, response, query);
+ return;
+ }
+ System.out.println("The XML is: " + xmlRequest);
+ }
+ else {
+ System.out.println( "WCPS: no request was received" );
+ printUsage (response);
+ return;
+ }
+ }
+ System.out.println( "WCPS: received the following request:" );
+ System.out.println( xmlRequest );
+
+ System.out.println( "WCPS: preparing request" );
+ ProcessCoverageRequest processCoverageRequest = wcps.pcPrepare(rasdamanUrl, rasdamanDatabase, new InputSource(new StringBufferInputStream(xmlRequest)));
+ System.out.println( "[" + processCoverageRequest.getMime() + "] " + processCoverageRequest.getQuery());
+
+ String query = processCoverageRequest.getQuery();
+ log("Resulting RasQL query: " + query);
+ String mimetype = processCoverageRequest.getMime();
+ System.out.println( "WCPS: executing request" );
+
+ List<byte[]> results = processCoverageRequest.execute();
+
+ System.out.println( "WCPS: setting response mimetype to " + mimetype );
+ response.setContentType( mimetype );
+ System.out.println( "WCPS: returning response" );
+ webOut = response.getOutputStream();
+ webOut.write( results.get( 0 ) );
+ System.out.println( "WCPS: done" );
+ }
+ catch( Exception e ) {
+ printError( response, "Error: " + e.getMessage(), e );
+ }
+ finally {
+ if( webOut != null ) {
+ try {
+ webOut.close();
+ }
+ catch( IOException e ) {}
+ }
+ }
+ }
+
+ public void destroy() {
+
+ super.destroy();
+
+ }
+
+ public String getServletInfo() {
+
+ return "Web Coverage Processing Service";
+
+ }
+
+ private void printError( HttpServletResponse response, String message, Exception e ) throws IOException {
+
+ System.out.println( "WCPS: error" );
+ System.out.println( "WCPS: setting response mimetype to text/html; charset=utf-8" );
+ response.setContentType( "text/html; charset=utf-8" );
+ System.out.println( "WCPS: returning the following error message" );
+ e.printStackTrace( System.out );
+ System.out.println( "WCPS: end of error message" );
+ PrintWriter out = new PrintWriter( response.getOutputStream() );
+ out.println( "<html><head><title>Web Coverage Processing Service</title></head><body>" );
+ out.println( "<h1>An error has occured</h1>" );
+ out.println( "<p>" + message + "</p>" );
+ out.println( "<p>Stack trace:<br/><small>" );
+ e.printStackTrace( out );
+ out.println( "</small></p></body></html>" );
+ out.close();
+ System.out.println( "WCPS: done with error" );
+
+ }
+
+ private void printUsage( HttpServletResponse response ) throws IOException {
+
+ System.out.println( "WCPS: setting response mimetype to text/html; charset=utf-8" );
+ System.out.println( "WCPS: returning usage message" );
+ response.setContentType( "text/html; charset=utf-8" );
+ PrintWriter out = new PrintWriter( response.getOutputStream() );
+ out.println( "<html><head><title>Web Coverage Processing Service</title></head><body>" );
+ out.println( "<h1>Hello</h1>" );
+ out.println( "<p>There are 3 ways to invoke this service:</p>" );
+ out.println( "<p>1. Upload a ProcessCoverage XML request as a multupart/form-data POST request containing a file. You can use the form below.</p>" );
+ out.println( "<form action=\"\" method=\"post\" enctype=\"multipart/form-data\"><input type=\"file\" accept=\"text/xml\" size=\"64\" name=\"xmlfile\"/> <input type=\"submit\" value=\"Send\"/></form>" );
+ out.println( "<p>2. Enter a ProcessCoverage XML request and submit it as a POST request with a parameter named <b>xml</b>. You can use the form below.</p>" );
+ out.println( "<form action=\"\" method=\"post\"><textarea cols=\"64\" rows=\"16\" name=\"xml\"></textarea><input type=\"submit\" value=\"Send\"/></form>" );
+ out.println( "<p>3. Enter a ProcessCoverage request in WCPS abstract syntax and submit it as a POST request with a parameter named <b>query</b>. You can use the form below.</p>" );
+ out.println( "<form action=\"\" method=\"post\"><textarea cols=\"64\" rows=\"4\" name=\"query\"></textarea><input type=\"submit\" value=\"Send\"/></form>" );
+ out.println( "</body></html>" );
+ out.close();
+ System.out.println( "WCPS: done nothing" );
+
+ }
+
+ void FormatSyntaxException(SyntaxErrorException e,
+ HttpServletResponse response,
+ String query) throws IOException {
+// response.setStatus(response.SC_INTERNAL_SERVER_ERROR);
+ response.setContentType("text/html; charset=utf-8");
+ PrintWriter o = new PrintWriter(response.getOutputStream());
+ o.println("<html><head><title>Web Coverage Processing Service</title></head><body>" );
+ o.println("<p>There seems to be a syntax problem with your query:</p>");
+ o.println("<p><font color='00FF00'>" + query.substring(0, e.getColumn()-1) +
+ "</font><font color='FF0000'>" + query.substring(e.getColumn()-1) +
+ "</font></p>");
+ o.println("<p>Please correct it and try again.</p></body></html>");
+ o.close();
+ System.out.println( "WCPS: Syntax Error reported");
+ }
+
+}
diff --git a/src/wcs/server/cli/CLI.java b/src/wcs/server/cli/CLI.java
new file mode 100644
index 0000000..2a23be4
--- /dev/null
+++ b/src/wcs/server/cli/CLI.java
@@ -0,0 +1,183 @@
+package wcs.server.cli;
+
+import wcs.server.core.executeGetCapabilities;
+import wcs.server.core.WCSException;
+import wcs.server.core.convertGetCoverage;
+import wcs.server.core.executeDescribeCoverage;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Unmarshaller;
+import net.opengis.ows.v_1_0_0.ExceptionReport;
+import net.opengis.wcs.v_1_1_0.Capabilities;
+import net.opengis.wcs.v_1_1_0.CoverageDescriptions;
+import net.opengis.wcs.v_1_1_0.DescribeCoverage;
+import net.opengis.wcs.v_1_1_0.GetCapabilities;
+import net.opengis.wcs.v_1_1_0.GetCoverage;
+import wcs.server.core.ProcessCoverage;
+
+/**
+ * Command Line Interface class, for testing the WCS Server operation
+ * Converts an WCS XML input file into a WCPS XML input file.<br />
+ * Settings are read from the file "input-output.txt", in the current folder.
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class CLI {
+
+ private static final String settingsFile = "input-output.txt";
+
+ private static String inputFile;
+ private static String outputFile;
+ private static String metadataSettingsFile;
+ private static Boolean ok;
+ private static Boolean printOutput;
+ private static Boolean printLog = true;
+
+ public static void log(String msg)
+ {
+ if (printLog)
+ System.out.println(msg);
+ }
+
+ public static boolean init()
+ {
+ ok = true;
+ printOutput = true;
+
+ Properties set = new Properties();
+ try {
+ set.load(new FileInputStream(settingsFile));
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ ok = false;
+ }
+
+ inputFile = set.getProperty("inputFile");
+ outputFile = set.getProperty("outputFile");
+ metadataSettingsFile = set.getProperty("metadataSettingsFile");
+ printOutput = Boolean.parseBoolean(set.getProperty("printOutputFile"));
+ printLog = Boolean.parseBoolean(set.getProperty("printLogMessages"));
+
+ return ok;
+ }
+
+ /**
+ * Converts a WCS XML input file into a WCPS XML input file
+ * @param args the command line arguments
+ */
+ public static void main(String[] args)
+ {
+ if ( ! init())
+ return;
+
+ try
+ {
+ // read the input XML
+ log(">>> Reading the input XML file ... ");
+ JAXBContext context = JAXBContext.newInstance("net.opengis.wcs.v_1_1_0");
+ Unmarshaller unmarshaller = context.createUnmarshaller() ;
+ Object xml = unmarshaller.unmarshal(new FileInputStream(inputFile));
+ // Find out which class to execute ...
+ log(">>> It is a " + xml.getClass().getSimpleName() + " request.");
+ if (xml instanceof GetCoverage)
+ {
+ //Convert the WCS into WCPS
+ log(">>> Converting to WCPS ... please wait");
+ GetCoverage wcs = (GetCoverage) xml;
+ ProcessCoverage wcps = new convertGetCoverage(wcs, metadataSettingsFile).get();
+ // Write the output WCPS request
+ try {
+ log(">>> Writing the WCPS XML request");
+ javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(wcps.getClass().getPackage().getName());
+ javax.xml.bind.Marshaller marshaller = jaxbCtx.createMarshaller();
+ marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_ENCODING, "UTF-8"); //NOI18N
+ marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+ if (printOutput)
+ marshaller.marshal(wcps, System.out);
+ marshaller.marshal(wcps, new FileOutputStream(outputFile));
+ } catch (javax.xml.bind.JAXBException ex) {
+ // XXXTODO Handle exception
+ java.util.logging.Logger.getLogger("global").log(java.util.logging.Level.SEVERE, null, ex); //NOI18N
+ ex.printStackTrace();
+ }
+ }
+ else
+ if (xml instanceof GetCapabilities)
+ {
+ log(">>> Compiling data into XML format for GetCapabilities ... ");
+ GetCapabilities input = (GetCapabilities) xml;
+ Capabilities cap = new executeGetCapabilities(input, metadataSettingsFile).get();
+ // Write the output file (WCS)
+ try {
+ javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(cap.getClass().getPackage().getName());
+ javax.xml.bind.Marshaller marshaller = jaxbCtx.createMarshaller();
+ marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_ENCODING, "UTF-8"); //NOI18N
+ marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+ if (printOutput)
+ marshaller.marshal(cap, System.out);
+ marshaller.marshal(cap, new FileOutputStream(outputFile));
+
+ } catch (javax.xml.bind.JAXBException ex) {
+ // XXXTODO Handle exception
+ java.util.logging.Logger.getLogger("global").log(java.util.logging.Level.SEVERE, null, ex); //NOI18N
+ ex.printStackTrace();
+ }
+ }
+ else
+ if (xml instanceof DescribeCoverage)
+ {
+ log(">>> Querying the WCPS architecture for the details on this coverage ...");
+ DescribeCoverage input = (DescribeCoverage) xml;
+ CoverageDescriptions output = new executeDescribeCoverage(input, metadataSettingsFile).get();
+ // Write the output file (WCS)
+ try {
+ javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(output.getClass().getPackage().getName());
+ javax.xml.bind.Marshaller marshaller = jaxbCtx.createMarshaller();
+ marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_ENCODING, "UTF-8"); //NOI18N
+ marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+ if (printOutput)
+ marshaller.marshal(output, System.out);
+ marshaller.marshal(output, new FileOutputStream(outputFile));
+ } catch (javax.xml.bind.JAXBException ex) {
+ // XXXTODO Handle exception
+ java.util.logging.Logger.getLogger("global").log(java.util.logging.Level.SEVERE, null, ex); //NOI18N
+ ex.printStackTrace();
+ }
+ }
+ else
+ throw new Exception("ERROR ! Unrecognized request type " + xml.getClass().getSimpleName());
+ }
+ catch (WCSException e)
+ {
+ ExceptionReport report = e.getReport();
+ try {
+ javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(report.getClass().getPackage().getName());
+ javax.xml.bind.Marshaller marshaller = jaxbCtx.createMarshaller();
+ marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_ENCODING, "UTF-8"); //NOI18N
+ marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+ if (printOutput)
+ marshaller.marshal(report, System.err);
+ marshaller.marshal(report, new FileOutputStream(outputFile));
+ } catch (javax.xml.bind.JAXBException ex) {
+ // XXXTODO Handle exception
+ java.util.logging.Logger.getLogger("global").log(java.util.logging.Level.SEVERE, null, ex); //NOI18N
+ ex.printStackTrace();
+ }
+ catch (Exception e2)
+ {
+ e2.printStackTrace();
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ log(">>> Done !");
+
+ }
+
+
+}
diff --git a/src/wcs/server/core/MetadataDb.java b/src/wcs/server/core/MetadataDb.java
new file mode 100644
index 0000000..de6056f
--- /dev/null
+++ b/src/wcs/server/core/MetadataDb.java
@@ -0,0 +1,100 @@
+package wcs.server.core;
+
+import java.io.FileInputStream;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Properties;
+
+/**
+ * Class to facilitate access to the PostgreSQL metadata database.
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class MetadataDb {
+
+ Connection con;
+ Statement sta;
+ ResultSet result;
+ String driver, url, user, pass;
+
+ private void log(String msg)
+ {
+ System.out.println(msg);
+ }
+
+ /**
+ * Default Constructor. Initializes the database access information from a file on disk
+ *
+ * @param dbParamsFile path to the properties file
+ */
+ public MetadataDb(String dbParamsFile) throws WCSException
+ {
+
+ Properties dbParams = new Properties();
+ try
+ {
+ dbParams.load(new FileInputStream(dbParamsFile));
+
+ driver = dbParams.getProperty("metadata_driver");
+ url = dbParams.getProperty("metadata_url");
+ user = dbParams.getProperty("metadata_user");
+ pass = dbParams.getProperty("metadata_pass");
+
+ Class.forName(driver);
+ con = DriverManager.getConnection(url, user, pass);
+ }
+ catch(Exception e)
+ {
+ log("User = " + user);
+ log("Pass = " + pass);
+ log("URL = " + url);
+ log("Driver = " + driver);
+ throw new WCSException("NoApplicableCode",
+ "Could not connect to the metadata database!",
+ "Could not connect to the metadata database!");
+ }
+ }
+
+ /**
+ * Makes sure the connection to the database is alive. Reconnects if needed.
+ */
+ private void ensureConnection()
+ {
+ synchronized (this) {
+ try {
+ if (con == null || !con.isClosed()) {
+ con.close();
+ con = DriverManager.getConnection(url, user, pass);
+ }
+ } catch (SQLException ex) {
+ System.err.println("SQLException: " + ex.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Execute a query on the database that is currently open.
+ * @param query SQL of the query
+ * @return a ResultSet object, with the results of the query
+ */
+ public ResultSet executeQuery(String query)
+ {
+ try
+ {
+ ensureConnection();
+ sta = con.createStatement();
+ result = sta.executeQuery(query);
+ }
+ catch(SQLException ex)
+ {
+ System.err.println("SQLException: " + ex.getMessage());
+ result = null;
+ }
+
+ return result;
+ }
+
+}
diff --git a/src/wcs/server/core/WCSException.java b/src/wcs/server/core/WCSException.java
new file mode 100644
index 0000000..9f46a07
--- /dev/null
+++ b/src/wcs/server/core/WCSException.java
@@ -0,0 +1,73 @@
+package wcs.server.core;
+import net.opengis.ows.v_1_0_0.ExceptionReport;
+import net.opengis.ows.v_1_0_0.ExceptionType;
+
+/**
+ * Exception class for the WCS server.
+ * This class can return an error report, than can be marshalled into a
+ * WCS-standard compliant XML structure describing the error that has happened.
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class WCSException extends Exception {
+
+ private static final long serialVersionUID = 847843429L;
+
+ private ExceptionReport report;
+ private ExceptionType item;
+
+ /**
+ * Default (minimal) constructor
+ * @param error Error Code
+ * @param detail Detailed message about the error
+ */
+ public WCSException(String error, String detail)
+ {
+ report = new ExceptionReport();
+ report.setLanguage("en");
+ report.setVersion("1.0.0");
+ if (error.equalsIgnoreCase("MissingParameterValue") ||
+ error.equalsIgnoreCase("InvalidParameterValue") ||
+ error.equalsIgnoreCase("NoApplicableCode") ||
+ error.equalsIgnoreCase("UnsupportedCombination") ||
+ error.equalsIgnoreCase("NotEnoughStorage"))
+ {
+ item = new ExceptionType();
+ item.setExceptionCode(error);
+ item.setLocator(detail);
+ report.getException().add(item);
+ }
+ else
+ {
+ /* This WCS Exception code is not recognized. But should still be
+ able to provide an XML ErrorReport */
+ item = new ExceptionType();
+ item.setExceptionCode("NoApplicableCode");
+ item.setLocator("Internal Error Code: " + error + " ... Internal Error Message: " + detail);
+ report.getException().add(item);
+ }
+ }
+
+ /**
+ * Convenience Constructor
+ * @param error Error Code
+ * @param detail Detailed message about the error
+ * @param msg A message that will be output on *System.err*
+ */
+ public WCSException(String error, String detail, String msg)
+ {
+ this(error, detail);
+
+ System.err.println(msg);
+ }
+
+ /**
+ * Retrieves a data structure that can be later marshalled into a XML
+ * "ExceptionReport" document.
+ * @return ExceptionReport object
+ */
+ public ExceptionReport getReport()
+ {
+ return report;
+ }
+} \ No newline at end of file
diff --git a/src/wcs/server/core/convertGetCoverage.java b/src/wcs/server/core/convertGetCoverage.java
new file mode 100644
index 0000000..412b0f1
--- /dev/null
+++ b/src/wcs/server/core/convertGetCoverage.java
@@ -0,0 +1,737 @@
+package wcs.server.core;
+
+import java.io.File;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Stack;
+import net.opengis.gml.v_3_1_1.TimePositionType;
+import net.opengis.ows.v_1_0_0.BoundingBoxType;
+import net.opengis.wcs.v_1_1_0.DomainSubsetType;
+import net.opengis.wcs.v_1_1_0.GetCoverage;
+import net.opengis.wcs.v_1_1_0.GridCrsType;
+import net.opengis.wcs.v_1_1_0.RangeSubsetType;
+import net.opengis.wcs.v_1_1_0.TimePeriodType;
+import wcs.server.core.SliceCoverageExprType.SetInterpolationDefault;
+
+
+/**
+ * This class takes a WCS GetCoverage XML request and converts this request into
+ * a WCPS ProcessCoverage XML request. It is the user's responsibility to pass
+ * the WCPS request to a WCPS server in order to view to result.
+ * NOTE: This class was tested with the WCPS server developed at Jacobs University,
+ * with a web client available at http://kahlua.eecs.jacobs-university.de/wcps-maitai/.
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class convertGetCoverage{
+
+ private GetCoverage wcs;
+ private ProcessCoverage wcps;
+ private EncodeDataExprType encoding;
+ private Stack<Object> stack;
+ private boolean finished;
+ private static String varname = "var";
+ private static boolean printLog = false;
+ private String pathDbSettings; // Path to the "dbparams.properties" file
+ private MetadataDb meta;
+
+ /**
+ * Record a log message to System.out
+ * @param str Text of the message
+ */
+ static private void log(String str)
+ {
+ if (printLog)
+ System.out.println(str);
+ }
+
+ /**
+ * Default constructor
+ * @param cov GetCoverage object, the input WCS request for retrieving a coverage
+ * @param metadataDbPath Path to the "dbparams.properties" file
+ */
+ public convertGetCoverage(GetCoverage cov, String MetadataDbPath) throws WCSException
+ {
+ wcs = cov;
+ finished = false;
+ wcps = new ProcessCoverage();
+ encoding = new EncodeDataExprType();
+ stack = new Stack<Object>();
+ pathDbSettings = MetadataDbPath;
+ meta = new MetadataDb(pathDbSettings);
+ }
+
+ /*** Main method of this class. Retrieves the WCPS request object that is
+ * equivalent to the WCS request. If it is not yet converted, it will
+ * perform the conversion.
+ *
+ * @return the ProcessCoverage XML structure for WCPS
+ * @throws wcs_web_service.WCSException
+ */
+ public ProcessCoverage get() throws WCSException
+ {
+ try
+ {
+ if (!finished)
+ process();
+ }
+ catch (WCSException e)
+ {
+ System.err.println("ERROR ! Could not convert the WCS xml into WCPS xml !!!");
+ e.printStackTrace();
+ throw e;
+ }
+ catch (Exception e)
+ {
+ System.err.println("Runtime ERROR ! ... see below!");
+ e.printStackTrace();
+ }
+
+ return wcps;
+ }
+
+ /**
+ * Converts WCS node 1 (Coverage Identifier) to WCPS info
+ * @throws wcs_web_service.WCSException
+ */
+ private void convField1() throws WCSException
+ {
+ if (! wcs.isSetIdentifier())
+ throw new WCSException("MissingParameterValue", "Identifier",
+ "Identifier must be a child of GetCoverage !");
+ wcps.coverageIterator = new ArrayList<ProcessCoverage.CoverageIterator>();
+ ProcessCoverage.CoverageIterator var = new ProcessCoverage.CoverageIterator();
+ var.setIteratorVar(varname);
+ var.coverageName = new ArrayList<String>();
+ String cname = wcs.getIdentifier().getValue();
+ var.coverageName.add(cname);
+ wcps.coverageIterator.add(var);
+ }
+
+ /**
+ * Converts WCS node 2 (Domain subsetting) to WCPS info
+ * @throws wcs_web_service.WCSException
+ */
+ private void convField2() throws WCSException
+ {
+ if (! wcs.isSetDomainSubset())
+ throw new WCSException("MissingParameterValue", "DomainSubset",
+ "DomainSubset must be a child element of GetCoverage !");
+ if (! wcs.getDomainSubset().isSetBoundingBox())
+ throw new WCSException("MissingParameterValue", "BoundingBox",
+ "BoundingBox must be a child element of DomainSubset !");
+
+ DomainSubsetType domain = wcs.getDomainSubset();
+ // DomainSubset->BoundingBox
+ if (domain.isSetBoundingBox())
+ {
+ BoundingBoxType bbox = (BoundingBoxType) domain.getBoundingBox().getValue();
+ if (bbox.getLowerCorner().size() != 2)
+ throw new WCSException("InvalidParameterValue", "LowerCorner",
+ "BoundingBox -> LowerCorner should have exactly two " +
+ "values, not " + bbox.getLowerCorner().size());
+ if (bbox.getUpperCorner().size() != 2)
+ throw new WCSException("InvalidParameterValue", "UpperCorner",
+ "BoundingBox -> UpperCorner should have exactly two " +
+ "values, not " + bbox.getUpperCorner().size());
+
+ // Set up trimming along X axis
+ TrimCoverageExprType exprx = new TrimCoverageExprType();
+ exprx.trimAxisSpec = new ArrayList<TrimCoverageExprType.TrimAxisSpec>();
+ TrimCoverageExprType.TrimAxisSpec xaxis = new TrimCoverageExprType.TrimAxisSpec();
+ xaxis.axis = "x";
+
+ int strx1 = bbox.getLowerCorner().get(0).intValue();
+ int strx2 = bbox.getUpperCorner().get(0).intValue();
+ xaxis.getCoordinateType().add(strx1);
+ xaxis.getCoordinateType().add(strx2);
+ exprx.getTrimAxisSpec().add(xaxis);
+
+ // Add the X-axis trimming to the stack
+ stack.push(exprx);
+// log("WCPS>>> Added X-axis trimming ! (DomainSubset->BoundingBox)" + exprx.trimAxisSpec.get(0).getAxis());
+
+ // Set up trimming along Y axis
+ TrimCoverageExprType expry = new TrimCoverageExprType();
+ expry.trimAxisSpec = new ArrayList<TrimCoverageExprType.TrimAxisSpec>();
+ TrimCoverageExprType.TrimAxisSpec yaxis = new TrimCoverageExprType.TrimAxisSpec();
+ yaxis.axis = "y";
+
+ Integer stry1 = bbox.getLowerCorner().get(1).intValue();
+ Integer stry2 = bbox.getUpperCorner().get(1).intValue();
+ yaxis.getCoordinateType().add(stry1);
+ yaxis.getCoordinateType().add(stry2);
+ expry.getTrimAxisSpec().add(yaxis);
+
+ // Add Y-axis trimming to the stack
+ stack.push(expry);
+// log("WCPS>>> Added Y-axis trimming ! (DomainSubset->BoundingBox)" + expry.trimAxisSpec.get(0).getAxis());
+
+ // If BoundingBox CRS is defined, then we need to convert the image to the specified CRS first,
+ // before doing the trimming
+ // NOTE! This assumes that the bounding box always spans axis "x" and "y". Check this !
+ log("WCPS>>> Bounding Box CRS is : " + bbox.getCrs());
+ if (bbox.getCrs() != null)
+ {
+ CrsTransformCoverageExprType tr = new CrsTransformCoverageExprType();
+ CrsTransformCoverageExprType.CrsTransformAxisSpec axis1 = new CrsTransformCoverageExprType.CrsTransformAxisSpec();
+ CrsTransformCoverageExprType.CrsTransformAxisSpec axis2 = new CrsTransformCoverageExprType.CrsTransformAxisSpec();
+ axis1.setAxis("x");
+ axis1.setCrs(bbox.getCrs());
+ axis2.setAxis("y");
+ axis2.setCrs(bbox.getCrs());
+ tr.getCrsTransformAxisSpec().add(axis1);
+ tr.getCrsTransformAxisSpec().add(axis2);
+ // NOTE that since the fields are not known in advance, this "transform field spec" is left empty
+ CrsTransformCoverageExprType.CrsTransformFieldSpec field = new CrsTransformCoverageExprType.CrsTransformFieldSpec();
+ tr.getCrsTransformFieldSpec().add(field);
+ stack.push(tr);
+ }
+ }
+ // DomainSubset->TemporalSubset
+ if (domain.isSetTemporalSubset())
+ {
+ // TemporalSubset is of type TimeSequenceType = choice(gml:TimePosition, wcs:TimePeriodType)
+ Object one = domain.getTemporalSubset().getTimePositionOrTimePeriod().get(0);
+ log("Inside TemporalSubset there is " + one.getClass());
+ if (one instanceof net.opengis.gml.v_3_1_1.TimePositionType)
+ {
+ // TemporalSubset = gml:TimePosition
+ // use WCPS:slice
+ SliceCoverageExprType expr = new SliceCoverageExprType();
+ expr.sliceAxisSpec = new ArrayList<SliceCoverageExprType.SliceAxisSpec>();
+ SliceCoverageExprType.SliceAxisSpec axis = new SliceCoverageExprType.SliceAxisSpec();
+ axis.axis = "time";
+
+ TimePositionType pos = (TimePositionType) one;
+ log("TimePosition has length " + pos.getValue().size());
+ if (pos.getValue().size() != 1)
+// throw new Exception("ERROR ! The TimePosition element should have exactly one item!");
+ throw new WCSException("InvalidParameterValue", "TimePosition", "ERROR ! The TimePosition element should have exactly one item, and not " + pos.getValue().size());
+ String str = pos.getValue().get(0);
+ axis.setDomainCoord(str);
+
+ // Add this slicing expression to the stack
+ expr.sliceAxisSpec.add(axis);
+ stack.push(expr);
+// log("WCPS>>> Added time-axis slicing ! ( DomainSubset->TemporalSubset->gml:TimePositionType)" + expr.sliceAxisSpec.get(0).getAxis());
+ }
+ else
+ if (one instanceof net.opengis.wcs.v_1_1_0.TimePeriodType)
+ {
+ // TemporalSubset = wcs:TimePeriodType
+ // use WCPS:trim
+ TrimCoverageExprType expr = new TrimCoverageExprType();
+ expr.trimAxisSpec = new ArrayList<TrimCoverageExprType.TrimAxisSpec>();
+ TrimCoverageExprType.TrimAxisSpec timeaxis = new TrimCoverageExprType.TrimAxisSpec();
+ timeaxis.axis = "time";
+
+ TimePeriodType period = (TimePeriodType) one;
+
+ TimePositionType pos1 = period.getBeginPosition();
+ TimePositionType pos2 = period.getEndPosition();
+ log("TimePeriod -> Start position, has length " + pos1.getValue().size());
+ log("TimePeriod -> End position, has length " + pos2.getValue().size());
+ if (pos1.getValue().size() != 1 || pos2.getValue().size() != 1)
+// throw new Exception("ERROR ! The TimePeriod->TimePosition element should have exactly one item!");
+ throw new WCSException("InvalidParameterValue", "TimePosition",
+ "ERROR ! The TimePeriod->TimePosition element should have exactly one item !");
+ String str1 = pos1.getValue().get(0);
+ String str2 = pos2.getValue().get(0);
+ timeaxis.getCoordinateType().add(str1);
+ timeaxis.getCoordinateType().add(str2);
+ expr.trimAxisSpec.add(timeaxis);
+
+ // Add this trimming expression to the stack
+ stack.push(expr);
+// log("WCPS>>> Added time-axis trimming ! ( DomainSubset->TemporalSubset->wcs:TimePeriodType)" + expr.trimAxisSpec.get(0).getAxis());
+ }
+
+ }
+
+
+ }
+
+ /**
+ * Converts WCS node 3 (Range subsetting) to WCPS info
+ */
+ private void convField3() throws WCSException
+ {
+
+ if (wcs.isSetRangeSubset())
+ {
+ RangeSubsetType range = wcs.getRangeSubset();
+ // combine several fields of the coverage together
+ CombineRangeCoverageExprType combination = new CombineRangeCoverageExprType();
+
+ Iterator<RangeSubsetType.FieldSubset> it = range.getFieldSubset().iterator();
+ while (it.hasNext())
+ {
+ RangeSubsetType.FieldSubset field = it.next();
+ CombineRangeCoverageExprType.Component component = new CombineRangeCoverageExprType.Component();
+ component.setField(field.getIdentifier().getValue());
+ component.setCoverage(varname);
+ log("WCPS>>> RangeSubsetType->FieldSubset->Identifier is " + component.getField());
+ log("WCPS>>> RangeSubsetType->FieldSubset->Interpolation is " + field.getInterpolationType());
+ // Set the medatada for interpolating current field
+ SetInterpolationDefault interp = new SetInterpolationDefault();
+ interp.setField(component.getField());
+
+ // Set up default values for interpolation method and null resistance
+ interp.setInterpolationMethod("nearest neighbor");
+ interp.setNullResistance("full");
+ // Get null resistance from the DB for the current coverage, if available
+ String query = "SELECT c.name, n.nullresistance FROM wcps_coverage AS c " +
+ "JOIN wcps_nullresistance AS n ON n.id = nullresistancedefault " +
+ "WHERE c.name = '" + wcs.getIdentifier().getValue() + "'";
+ log(query);
+ try
+ {
+ ResultSet r = meta.executeQuery(query);
+ if (r.next())
+ {
+ String res = r.getString("nullresistance");
+ interp.setNullResistance(res);
+ log(" *** Null resistance = " + res);
+ }
+ }
+ catch (SQLException se)
+ {
+ log("Error fetching default null resistance for coverage. See query below:");
+ log("SQL Error in query:\n " + query);
+ }
+
+ // Get default interpolation method from DB, if available
+ query = "SELECT im.interpolationmethod FROM wcps_coverage AS c " +
+ "JOIN wcps_interpolationmethodlist AS iml ON iml.coverage = c.id " +
+ "JOIN wcps_interpolationmethod AS im ON iml.interpolationmethod = im.id " +
+ "WHERE c.name = '" + wcs.getIdentifier().getValue() + "'";
+ log(query);
+ try
+ {
+ ResultSet r = meta.executeQuery(query);
+ if (r.next())
+ {
+ String inttype = r.getString("interpolationmethod");
+ interp.setInterpolationMethod(inttype);
+ log(" *** Interpolation type = " + inttype);
+ }
+ }
+ catch (SQLException se)
+ {
+
+ log("Error fetching default interpolation method for coverage. See query below:");
+ log("SQL Error in query:\n " + query);
+ }
+
+ // Add the interpolation details
+// stack.push(interp);
+
+ // FieldSubset->AxisSubset is optional, and will not be translated here
+
+ // Select this field too in the combination (of fields of a given coverage)
+ combination.getComponent().add(component);
+ }
+
+ stack.push(combination);
+ }
+
+ }
+
+ /**
+ * Converts WCS node 4 (Output) to WCPS info
+ * @throws wcs_web_service.WCSException
+ */
+ private void convField4() throws WCSException
+ {
+ String query = "";
+ if (! wcs.isSetOutput())
+ throw new WCSException("MissingParameterValue", "Output",
+ "Output must be a child of GetCoverage !");
+
+ if (wcs.getOutput().isSetGridCRS())
+ {
+ GridCrsType crs = wcs.getOutput().getGridCRS();
+ throw new WCSException("NoApplicableCode",
+ "Currently, the Output->GridCRS node is not supported !",
+ "Currently, the Output->GridCRS node is not supported !");
+ }
+
+ // encoding is initialized in convField2()
+ try
+ {
+ File pwd = new File(".");
+ String wcsFormat = wcs.getOutput().getFormat();
+ query = "SELECT name FROM wcps_format WHERE mimetype='" + wcsFormat + "'";
+ ResultSet r = meta.executeQuery(query);
+ if (r.next())
+ {
+ String ename = r.getString("name");
+ // Small hack: rasdaman does not recognize jpg, only jpeg
+ if (ename.equals("jpg"))
+ ename = "jpeg";
+ encoding.setFormat(ename);
+ log("*** Output format is " + encoding.getFormat());
+ }
+ else
+ {
+ // error fetching the mimetype from the db ... try using the mimetype directly
+ encoding.setFormat(wcs.getOutput().getFormat());
+ log("Error fetching the image type from the database ... Continuing ...");
+ }
+ }
+ catch (SQLException se)
+ {
+ encoding.setFormat(wcs.getOutput().getFormat());
+ log("SQL Error while trying to find mimetype '" + wcs.getOutput().getFormat() + "' in the database! Continuing ...");
+ throw new WCSException("NoApplicableCode",
+ "SQL Exception on the following query: " + query,
+ "SQL Exception on the following query: " + query);
+ }
+ catch (Exception e)
+ {
+ encoding.setFormat(wcs.getOutput().getFormat());
+ log("Strange error while trying to find mimetype '" + wcs.getOutput().getFormat() + "' in the database! Continuing ...");
+ throw new WCSException("NoApplicableCode",
+ "Exception with the following message: " + e.getMessage(),
+ "Exception with the following message: " + e.getMessage());
+ }
+
+ log("issetstore = " + wcs.getOutput().isSetStore());
+ log("isstore = " + wcs.getOutput().isStore());
+ if (wcs.getOutput().isSetStore())
+ {
+ if (wcs.getOutput().isStore())
+ encoding.setStore(true);
+ else
+ encoding.setStore(false);
+ }
+ else
+ encoding.setStore(false);
+ }
+
+ /**
+ * Performs the conversion of the WCS request into a WCPS request.
+ * @throws wcs_web_service.WCSException
+ */
+ @SuppressWarnings("static-access")
+ public void process() throws WCSException
+ {
+ /*** Processing starts here ... with the nodes of the WCS ***/
+ // Service Description
+ wcps.setService("WCPS");
+ wcps.setVersion("1.0.0");
+ log("WCS service: \"" + wcs.SERVICE + "\"");
+ log("WCS version: \"" + wcs.VERSION + "\"");
+ if ( !wcs.SERVICE.equalsIgnoreCase("WCS"))
+ throw new WCSException("InvalidParameterValue", "Service", "Only the WCS service is supported !!!");
+ if ( !wcs.VERSION.equals("1.1.0") && ( !wcs.VERSION.equals("1.0.0")))
+ throw new WCSException("InvalidParameterValue", "Version", "Only Version 1.1.0 is currently supported !!!");
+
+ // First of all, error checking: is the coverage offered by the server?
+ if (!existsCoverage(wcs.getIdentifier().getValue()))
+ throw new WCSException("InvalidParameterValue", "Identifier",
+ "Coverage " + wcs.getIdentifier().getValue() + " is not served by this server !");
+
+ // Convert all the child nodes of WCS GetCoverage XML node
+ log("*** Going to build WCPS node 1 ...");
+ convField1();
+ log("*** Going to build WCPS node 2 ...");
+ convField2();
+ log("*** Going to build WCPS node 3 ...");
+ convField3();
+ log("*** Going to build WCPS node 4 ...");
+ convField4();
+ log("*** Last touches to the WCPS XML structure ...");
+ buildWcpsStructure();
+ log("*** Done with building the WCPS XML !");
+
+ wcps.setEncode(encoding);
+
+ /* Done processing */
+ finished = true;
+ log(">>> Done Converting WCS GetCoverage into WCPS ProcessCoverage...");
+ }
+
+ /*** Now we have a list of operations that we want the WCPS to perform,
+ * stored in "stack". We need to add the variable name to the structure on
+ * top of the stack, and then we can build the structure to pass to WCPS.
+ * NOTE: This function should be called after all details of the WCS request
+ * have been processed.
+ *
+ * @throws wcs_web_service.WCSException
+ */
+ private void buildWcpsStructure() throws WCSException
+ {
+
+ // Print the stack
+ log(" --------- STACK BOTTOM ----------");
+ Iterator<Object> i = stack.iterator();
+ while (i.hasNext())
+ {
+ Object o = i.next();
+ if (o instanceof TrimCoverageExprType)
+ {
+ TrimCoverageExprType trim = (TrimCoverageExprType) o;
+ log(" - Trim " + trim.trimAxisSpec.get(0).getAxis());
+ }
+ else if (o instanceof SliceCoverageExprType)
+ {
+ SliceCoverageExprType slice = (SliceCoverageExprType) o;
+ log(" - Slice " + slice.sliceAxisSpec.get(0).getAxis());
+ }
+ else if (o instanceof CrsTransformCoverageExprType)
+ {
+ CrsTransformCoverageExprType tr = (CrsTransformCoverageExprType) o;
+ log(" - CRS Transform into crs " + tr.getCrsTransformAxisSpec().get(0).getCrs());
+ }
+ else if (o instanceof CombineRangeCoverageExprType)
+ {
+ CombineRangeCoverageExprType comb = (CombineRangeCoverageExprType) o;
+ log(" - Combination between several fields: ");
+ Iterator<CombineRangeCoverageExprType.Component> it = comb.getComponent().iterator();
+ while (it.hasNext())
+ {
+ log(" \t * Component " + it.next().getField());
+ }
+ }
+ else if (o instanceof SetInterpolationDefault)
+ {
+ SetInterpolationDefault interp = (SetInterpolationDefault) o;
+ log(" - Interpolation Default for field " + interp.getField() + ": interp="
+ + interp.getInterpolationMethod() + ", null resistance=" + interp.getNullResistance());
+ }
+ }
+ log(" --------- STACK TOP ----------");
+
+ // Add the variable name to the top of the stack
+ Object obj, newObj;
+ TrimCoverageExprType trim = null, newTrim;
+ SliceCoverageExprType slice = null, newSlice;
+ CrsTransformCoverageExprType tr = null, newTr;
+ CombineRangeCoverageExprType comb = null, newComb;
+ SetInterpolationDefault interp = null, newInterp;
+
+ obj = stack.pop();
+ if (obj instanceof TrimCoverageExprType)
+ {
+ trim = (TrimCoverageExprType)obj;
+ trim.setCoverage(varname);
+ log("WCPS>>> (1) Popped a trim expression from stack !" + trim.trimAxisSpec.get(0).getAxis());
+ }
+ else
+ if (obj instanceof SliceCoverageExprType)
+ {
+ slice = (SliceCoverageExprType)obj;
+ slice.setCoverage(varname);
+ log("WCPS>>> (1) Popped a slice expression from stack !" + slice.sliceAxisSpec.get(0).getAxis());
+ }
+ else
+ if (obj instanceof CrsTransformCoverageExprType)
+ {
+ tr = (CrsTransformCoverageExprType) obj;
+ tr.setCoverage(varname);
+ log("WCPS>>> (1) CRS Transform into crs " + tr.getCrsTransformAxisSpec().get(0).getCrs());
+ }
+ else
+ if (obj instanceof CombineRangeCoverageExprType)
+ {
+ comb = (CombineRangeCoverageExprType) obj;
+ // Variable name already set in convField3()
+ log("WCPS>>> (1) Combining different range fields for thing with first element "
+ + comb.getComponent().get(0).getField() + ". HOWTO !!!??? Don't know how to work with this !!!");
+ log("WCPS>>> Component has coverage " + comb.getComponent().get(0).getCoverage() + "." + comb.getComponent().get(0).getField());
+ }
+ else
+ if (obj instanceof SetInterpolationDefault)
+ {
+ interp = (SetInterpolationDefault) obj;
+ interp.setCoverage(varname);
+ log("WCPS>>> (1) Interpolation Default for field " + interp.getField()
+ + ": interp=" + interp.getInterpolationMethod()
+ + ", null resistance=" + interp.getNullResistance());
+ }
+ else
+ throw new WCSException("NoApplicableCode", "",
+ "INTERNAL ERROR! Unknown datatype while popping stack !");
+ // Pop the stack element by element, to construct the expression
+ while (! stack.empty())
+ {
+ newSlice = null;
+ newTrim = null;
+ newTr = null;
+ newComb = null;
+ newInterp = null;
+ newObj = stack.pop();
+ if (newObj instanceof TrimCoverageExprType)
+ {
+ newTrim = (TrimCoverageExprType)newObj;
+ log("WCPS>>> Popped a trim expression from stack !" + newTrim.trimAxisSpec.get(0).getAxis());
+ if (trim != null)
+ newTrim.setTrim(trim);
+ else
+ if (slice != null)
+ newTrim.setSlice(slice);
+ else
+ if (tr != null)
+ newTrim.setCrsTransform(tr);
+ else
+ if (comb != null)
+ newTrim.setCombine(comb);
+ else
+ if (interp != null)
+ newTrim.setSetInterpolationDefault(interp);
+ }
+ else
+ if (newObj instanceof SliceCoverageExprType)
+ {
+ newSlice = (SliceCoverageExprType)newObj;
+ log("WCPS>>> Popped a slice expression from stack !" + newSlice.sliceAxisSpec.get(0).getAxis());
+ if (trim != null)
+ newSlice.setTrim(trim);
+ else
+ if (slice != null)
+ newSlice.setSlice(slice);
+ else
+ if (tr != null)
+ newSlice.setCrsTransform(tr);
+ else
+ if (comb != null)
+ newSlice.setCombine(comb);
+ else
+ if (interp != null)
+ newSlice.setSetInterpolationDefault(interp);
+ }
+ else
+ if (newObj instanceof CrsTransformCoverageExprType)
+ {
+ newTr = (CrsTransformCoverageExprType) newObj;
+ log("WCPS>>> Popped a CRS Transform into crs " + newTr.getCrsTransformAxisSpec().get(0).getCrs());
+ if (trim != null)
+ newTr.setTrim(trim);
+ else
+ if (slice != null)
+ newTr.setSlice(slice);
+ else
+ if (tr != null)
+ newTr.setCrsTransform(tr);
+ else
+ if (comb != null)
+ newTr.setCombine(comb);
+ else
+ if (interp != null)
+ newTr.setSetInterpolationDefault(interp);
+ }
+ else
+ if (newObj instanceof CombineRangeCoverageExprType)
+ {
+ newComb = (CombineRangeCoverageExprType) newObj;
+ if (trim != null)
+ newComb.getComponent().get(0).setTrim(trim);
+ else
+ if (slice != null)
+ newComb.getComponent().get(0).setSlice(slice);
+ else
+ if (tr != null)
+ newComb.getComponent().get(0).setCrsTransform(tr);
+ else
+ if (comb != null)
+ newComb.getComponent().get(0).setCombine(comb);
+ else
+ if (interp != null)
+ newComb.getComponent().get(0).setSetInterpolationDefault(interp);
+
+ log("WCPS>>> Combining different range fields for thing with first element "
+ + newComb.getComponent().get(0).getField() + ". Don't know how to work with this !!!");
+ }
+ else
+ if (newObj instanceof SetInterpolationDefault)
+ {
+ newInterp = (SetInterpolationDefault) newObj;
+ log("WCPS>>> Interpolation Default for field " + newInterp.getField()
+ + ": interp=" + newInterp.getInterpolationMethod()
+ + ", null resistance=" + newInterp.getNullResistance());
+ if (trim != null)
+ newInterp.setTrim(trim);
+ else
+ if (slice != null)
+ newInterp.setSlice(slice);
+ else
+ if (tr != null)
+ newInterp.setCrsTransform(tr);
+ else
+ if (comb != null)
+ newInterp.setCombine(comb);
+ else
+ if (interp != null)
+ newInterp.setSetInterpolationDefault(interp);
+ }
+
+ else
+ throw new WCSException("NoApplicableCode", "",
+ "INTERNAL ERROR! Unknown datatype while popping stack !");
+
+ slice = newSlice;
+ trim = newTrim;
+ tr = newTr;
+ comb = newComb;
+ interp = newInterp;
+ }
+
+ // Add the structure represented on the stack to the class variable "encoding"
+ if (trim != null)
+ encoding.setTrim(trim);
+ else
+ if (slice != null)
+ encoding.setSlice(slice);
+ else
+ if (tr != null)
+ encoding.setCrsTransform(tr);
+ else
+ if (comb != null)
+ encoding.setCombine(comb);
+ else
+ if (interp != null)
+ encoding.setSetInterpolationDefault(interp);
+ else
+ throw new WCSException("NoApplicableCode", "", "ERROR ! Unknown " +
+ "datatype after processing the whole stack !");
+
+ log("WCPS>>> Added the final processing structure to the XML tree... ");
+ }
+
+ /**
+ * Checks the metadata DB to ,ake sure that the WCPS server has coverage "name"
+ * @param name the name of the coverage to check
+ * @return boolean whether the coverage is available
+ */
+ private boolean existsCoverage(String name)
+ {
+
+ String query = "SELECT * FROM wcps_coverage AS cov " +
+ "WHERE cov.name='" + name + "'";
+ try
+ {
+ ResultSet r = meta.executeQuery(query);
+ log(query);
+ if (r.next())
+ {
+ log("Coverage " + name + " is in the database !");
+ }
+ else
+ {
+ log("Coverage " + name + " is NOT in the database !");
+ return false;
+ }
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+}
diff --git a/src/wcs/server/core/executeDescribeCoverage.java b/src/wcs/server/core/executeDescribeCoverage.java
new file mode 100644
index 0000000..fb75bda
--- /dev/null
+++ b/src/wcs/server/core/executeDescribeCoverage.java
@@ -0,0 +1,292 @@
+package wcs.server.core;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import javax.xml.bind.JAXBElement;
+import javax.xml.namespace.QName;
+import net.opengis.ows.v_1_0_0.BoundingBoxType;
+import net.opengis.wcs.ows.v_1_1_0.DomainMetadataType;
+import net.opengis.wcs.ows.v_1_1_0.InterpolationMethodType;
+import net.opengis.wcs.ows.v_1_1_0.InterpolationMethods;
+import net.opengis.wcs.ows.v_1_1_0.UnNamedDomainType;
+import net.opengis.wcs.v_1_1_0.CoverageDescriptionType;
+import net.opengis.wcs.v_1_1_0.CoverageDescriptions;
+import net.opengis.wcs.v_1_1_0.CoverageDomainType;
+import net.opengis.wcs.v_1_1_0.DescribeCoverage;
+import net.opengis.wcs.v_1_1_0.FieldType;
+import net.opengis.wcs.v_1_1_0.RangeType;
+import net.opengis.wcs.v_1_1_0.SpatialDomainType;
+
+/**
+ * This class takes a WCS DescribeCoverage XML request and executes request,
+ * building the corresponding XML respose.
+ * NOTE: Since the WCPS and WCS services share the format of DescribeCoverage
+ * request and response, this class can also answer WCPS DescribeCoverage
+ * requests. In fact, this is what it does!
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class executeDescribeCoverage {
+
+ private DescribeCoverage input;
+ private CoverageDescriptions output;
+ private boolean finished;
+ private static boolean printLog = true;
+ private MetadataDb meta;
+ private String pathDbSettings; // Path to the "dbparams.properties" file
+
+ /**
+ * Log a message to System.out
+ * @param str Text of the message
+ */
+ static void log(String str)
+ {
+ if (printLog)
+ System.out.println("<WCS DescribeCoverage> " + str);
+ }
+
+ /**
+ * Default constructor
+ * @param cap DescribeCoverage object, a WCS (or WCPS) request
+ * @param metadataDbPath Path to the "dbparams.properties" file
+ */
+ public executeDescribeCoverage(DescribeCoverage cap, String metadataDbPath) throws WCSException
+ {
+ input = cap;
+ output = new CoverageDescriptions();
+ finished = false;
+ pathDbSettings = metadataDbPath;
+ meta = new MetadataDb(pathDbSettings);
+ }
+
+ /**
+ * Main method of this class. Retrieves the response to the DescribeCoverage
+ * request given to the constructor. If needed, it also calls <b>process()</b>
+ * @return a CoverageDescriptions object.
+ * @throws wcs_web_service.WCSException
+ */
+ public CoverageDescriptions get() throws WCSException
+ {
+ try
+ {
+ if (finished == false)
+ process();
+ }
+ catch (WCSException e)
+ {
+ System.err.println("ERROR ! Could not convert the WCS xml into WCPS xml !!!");
+ e.printStackTrace();
+ throw e;
+ }
+ if (finished == false)
+ throw new WCSException("NoApplicableCode", "Could not execute the GetCapabilities request! " +
+ "Please see the other errors...");
+ return output;
+ }
+
+ /**
+ * Computes the response to the GetCapabilities request given to the constructor.
+ */
+ public void process() throws WCSException
+ {
+ String id;
+ for (int i = 0; i < input.getIdentifier().size(); i++)
+ {
+ id = input.getIdentifier().get(i);
+ output.getCoverageDescription().add(getCoverageDescription(id));
+ }
+ finished = true;
+ }
+
+ /**
+ * Retrieve details for one coverage.
+ * @param name Name of the coverage
+ * @return CoverageDescriptionType object, that can just be plugged in the respose object
+ */
+ private CoverageDescriptionType getCoverageDescription(String name) throws WCSException
+ {
+ String query;
+ CoverageDescriptionType desc = new CoverageDescriptionType();
+
+ // Error checking: is the coverage available?
+ if (!this.existsCoverage(name))
+ throw new WCSException("InvalidParameterValue", "Identifier",
+ "Coverage " + name + " is not served by this server !");
+
+
+ desc.setIdentifier(name);
+ desc.setTitle("Coverage " + name);
+ desc.setAbstract("Available coverage, fetched from the database");
+
+ // Read the coverage Domain from the database
+ CoverageDomainType domain = null;
+ boolean ok1 = false;
+ query = "SELECT d.name, lo, hi FROM " +
+ "wcps_celldomain AS cd JOIN wcps_coverage AS cov ON cd.coverage = cov.id " +
+ "JOIN wcps_domain AS d ON d.coverage = cov.id AND d.i = cd.i " +
+ "WHERE cov.name='" + name + "'" +
+ " ORDER BY cd.i ASC";
+ try
+ {
+ ResultSet r = meta.executeQuery(query);
+ log(query);
+ Double lo0=0.0, lo1=0.0, hi0=0.0, hi1=0.0;
+ if (r.next() && ! r.getString("name").equals("t"))
+ {
+ log(r.getString("name"));
+ lo0 = r.getDouble("lo");
+ hi0 = r.getDouble("hi");
+ if (r.next() && ! r.getString("name").equals("t"))
+ {
+ log(r.getString("name"));
+ lo1 = r.getDouble("lo");
+ hi1 = r.getDouble("hi");
+ ok1 = true;
+ }
+ }
+
+ domain = new CoverageDomainType();
+ SpatialDomainType spatial = new SpatialDomainType();
+ BoundingBoxType bbox = new BoundingBoxType();
+ bbox.getLowerCorner().add(lo0);
+ bbox.getLowerCorner().add(lo1);
+ bbox.getUpperCorner().add(hi0);
+ bbox.getUpperCorner().add(hi1);
+ spatial.getBoundingBox().add(new JAXBElement<BoundingBoxType>(new QName("BoundingBox"), BoundingBoxType.class, bbox));
+ domain.setSpatialDomain(spatial);
+ }
+ catch (SQLException se)
+ {
+ System.err.println("SQL Error in query:\n " + query);
+ se.printStackTrace();
+ throw new WCSException("NoApplicableCode",
+ "SQL Error in query:\n " + query, "SQL Error in query:\n " + query);
+ }
+
+ log("ok1 = " + String.valueOf(ok1));
+ if (ok1)
+ desc.setDomain(domain);
+
+ // Read the coverage Range from the database
+ RangeType range = new RangeType();
+ boolean ok2 = false;
+ FieldType field;
+ query = "SELECT c.name AS cov, r.name AS field , d.datatype AS definterp, n.nullresistance AS defnull, d2.datatype " +
+ "FROM wcps_range AS r JOIN wcps_coverage AS c ON r.coverage = c.id " +
+ "JOIN wcps_datatype AS d ON interpolationtypedefault = d.id " +
+ "JOIN wcps_nullresistance AS n ON n.id = nullresistancedefault " +
+ "JOIN wcps_datatype AS d2 ON r.type = d2.id " +
+ "WHERE c.name = '" + name + "' " +
+ "ORDER BY r.i ASC";
+ try
+ {
+ ResultSet r = meta.executeQuery(query);
+ log(query);
+ while (r.next())
+ {
+ field = new FieldType();
+
+ field.setIdentifier(r.getString("field"));
+ UnNamedDomainType domtype = new UnNamedDomainType();
+ DomainMetadataType dommeta = new DomainMetadataType();
+ dommeta.setValue(r.getString("datatype"));
+ domtype.setDataType(dommeta);
+ field.setDefinition(domtype);
+
+ InterpolationMethods interp = new InterpolationMethods();
+
+ InterpolationMethodType meth = new InterpolationMethodType();
+ meth.setValue(r.getString("definterp"));
+ meth.setNullResistance(r.getString("defnull"));
+ interp.setDefaultMethod(meth);
+
+ query = "SELECT c.name, datatype AS interp, n.nullresistance " +
+ "FROM wcps_interpolationset AS i JOIN wcps_coverage AS c ON i.coverage = c.id " +
+ "JOIN wcps_datatype AS d ON interpolationtypedefault = d.id " +
+ "JOIN wcps_nullresistance AS n ON n.id = nullresistancedefault " +
+ "WHERE c.name = '" + name + "' " +
+ "ORDER BY coverage";
+ ResultSet r2 = meta.executeQuery(query);
+ while (r2.next())
+ {
+ meth = new InterpolationMethodType();
+ meth.setValue(r2.getString("interp"));
+ meth.setNullResistance(r2.getString("nullresistance"));
+ if ( ! (meth.getValue().equalsIgnoreCase(interp.getDefaultMethod().getValue())
+ && meth.getNullResistance().equalsIgnoreCase(interp.getDefaultMethod().getNullResistance())) )
+ interp.getOtherMethod().add(meth);
+ ok2 = true;
+ }
+ field.setInterpolationMethods(interp);
+ range.getField().add(field);
+ }
+
+ }
+ catch (SQLException se)
+ {
+ System.err.println("SQL Error in query:\n " + query);
+ se.printStackTrace();
+ ok2 = false;
+ throw new WCSException("NoApplicableCode",
+ "SQL Error in query:\n " + query, "SQL Error in query:\n " + query);
+ }
+
+ log("ok2 = " + String.valueOf(ok2));
+ if (ok2)
+ desc.setRange(range);
+
+ // Supported format for GetCoverage
+ desc.getSupportedFormat().add("text/xml");
+
+ // Available CRSs for current coverage
+ try
+ {
+ query = "SELECT crs FROM wcps_coverage WHERE name='" + name + "'";
+ ResultSet r = meta.executeQuery(query);
+ if (r.next())
+ {
+ desc.getSupportedCRS().add(r.getString("crs"));
+ }
+ }
+ catch (SQLException se)
+ {
+ se.printStackTrace();
+ throw new WCSException("NoApplicableCode",
+ "SQL Error in query:\n " + query, "SQL Error in query:\n " + query);
+ }
+
+ return desc;
+ }
+
+ /**
+ * Checks the metadata DB to ,ake sure that the WCPS server has coverage "name"
+ * @param name the name of the coverage to check
+ * @return boolean whether the coverage is available
+ */
+ private boolean existsCoverage(String name)
+ {
+
+ String query = "SELECT * FROM wcps_coverage AS cov " +
+ "WHERE cov.name='" + name + "'";
+ try
+ {
+ ResultSet r = meta.executeQuery(query);
+ log(query);
+ if (r.next())
+ {
+ log("Coverage " + name + " is in the database !");
+ }
+ else
+ {
+ log("Coverage " + name + " is NOT in the database !");
+ return false;
+ }
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/src/wcs/server/core/executeGetCapabilities.java b/src/wcs/server/core/executeGetCapabilities.java
new file mode 100644
index 0000000..0acca03
--- /dev/null
+++ b/src/wcs/server/core/executeGetCapabilities.java
@@ -0,0 +1,264 @@
+package wcs.server.core;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import javax.xml.bind.JAXBElement;
+import javax.xml.namespace.QName;
+import net.opengis.wcs.v_1_1_0.Capabilities;
+import net.opengis.ows.v_1_0_0.CodeType;
+import net.opengis.ows.v_1_0_0.OnlineResourceType;
+import net.opengis.wcs.ows.v_1_1_0.OperationsMetadata;
+import net.opengis.wcs.ows.v_1_1_0.ServiceIdentification;
+import net.opengis.ows.v_1_0_0.ServiceProvider;
+import net.opengis.wcs.ows.v_1_1_0.AllowedValues;
+import net.opengis.wcs.ows.v_1_1_0.DCP;
+import net.opengis.wcs.ows.v_1_1_0.DomainType;
+import net.opengis.wcs.ows.v_1_1_0.HTTP;
+import net.opengis.wcs.ows.v_1_1_0.Operation;
+import net.opengis.wcs.ows.v_1_1_0.RequestMethodType;
+import net.opengis.wcs.ows.v_1_1_0.ValueType;
+import net.opengis.wcs.v_1_1_0.Contents;
+import net.opengis.wcs.v_1_1_0.CoverageSummaryType;
+import net.opengis.wcs.v_1_1_0.GetCapabilities;
+
+/**
+ * This class takes a WCS GetCapabilities XML request and executes request,
+ * building the corresponding XML respose.
+ * NOTE: Since the WCPS and WCS services share the format of GetCapabilities
+ * request and response, this class can also answer WCPS GetCapabilities
+ * requests. In fact, this is what it does!
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class executeGetCapabilities {
+
+ private final static String SERVLET_URL = "http://kahlua.eecs.jacobs-university.de/wcs-andrei/";
+
+ private GetCapabilities input;
+ private Capabilities output;
+ private boolean finished;
+ private static boolean printLog = true;
+ private MetadataDb meta;
+ private String pathDbSettings; // Path to the "dbparams.properties" file
+
+ /**
+ * Log a message to System.out
+ * @param str Text of the message
+ */
+ static private void log(String str)
+ {
+ if (printLog)
+ System.out.println("<WCS GetCapabilities> " + str);
+ }
+
+ /**
+ * Default constructor
+ * @param cap GetCapabilities object, a WCS (or WCPS) request
+ * @param metadataDbPath Path to the "dbparams.properties" file
+ */
+ public executeGetCapabilities(GetCapabilities cap, String metadataDbPath) throws WCSException
+ {
+ input = cap;
+ output = new Capabilities();
+ pathDbSettings = metadataDbPath;
+ meta = new MetadataDb(pathDbSettings);
+ finished = false;
+ }
+
+ /**
+ * Main method of this class. Retrieves the response to the GetCapabilities
+ * request given to the constructor. If needed, it also calls <b>process()</b>
+ * @return a Capabilities object.
+ * @throws wcs_web_service.WCSException
+ */
+ public Capabilities get() throws WCSException
+ {
+ if (finished == false)
+ process();
+ if (finished == false)
+ throw new WCSException("NoApplicableCode", "Could not execute the GetCapabilities request! " +
+ "Please see the other errors...");
+ return output;
+ }
+
+ /**
+ * Computes the response to the GetCapabilities request given to the constructor.
+ * @throws wcs_web_service.WCSException
+ */
+ @SuppressWarnings("static-access")
+ public void process() throws WCSException
+ {
+ if (! input.SERVICE.equalsIgnoreCase("WCS"))
+ throw new WCSException("InvalidParameterValue", "Service",
+ "Identifier must be a child of GetCoverage !");
+
+ try
+ {
+ buildField1(); // Service Identification
+ buildField2(); // Service Provider
+ buildField3(); // Operations Metadata
+ buildField4(); // Contents
+
+ finishBuild(); // Add the remaining required attributes
+ finished = true;
+ }
+ catch (SQLException se)
+ {
+ se.printStackTrace();
+ finished = false;
+ }
+
+ }
+
+ /**
+ * Builds the output node "Service Identification"
+ */
+ private void buildField1() {
+ ServiceIdentification ident = new ServiceIdentification();
+ ident.setTitle("WCS Coverage Server @ Jacobs University");
+ ident.setAbstract("WCS Server developed at jacobs University");
+ CodeType code = new CodeType();
+ code.setValue("OGC WCS");
+ ident.setServiceType(code);
+ ident.setFees("NONE");
+
+ output.setServiceIdentification(ident);
+ }
+
+ /**
+ * Builds the output node "Service Provider"
+ */
+ private void buildField2() {
+ ServiceProvider prov = new ServiceProvider();
+ prov.setProviderName("Jacobs University Bremen");
+ OnlineResourceType site = new OnlineResourceType();
+ site.setHref("http://www.jacobs-university.de/");
+ prov.setProviderSite(site);
+
+ output.setServiceProvider(prov);
+ }
+
+ /**
+ * Builds the output node "Operations Metadata"
+ * @throws java.sql.SQLException
+ */
+ private void buildField3() throws SQLException
+ {
+ OperationsMetadata opmeta = new OperationsMetadata();
+
+ Operation op1 = new Operation();
+ op1.setName("GetCapabilities");
+ DCP dcp = new DCP();
+ HTTP http = new HTTP();
+ /*
+ // What is the URL for SOAP?
+ RequestMethodType soap = new RequestMethodType();
+ soap.setHref("http://localhost/SOAP/URL/for/GetCapabalities");
+ http.getGetOrPost().add(new JAXBElement<RequestMethodType>(new QName("Soap"), RequestMethodType.class, soap));
+ */
+ RequestMethodType post = new RequestMethodType();
+ post.setHref(SERVLET_URL);
+ // TODO: Add "Get" request type once KVP encoding is supported
+ http.getGetOrPost().add(new JAXBElement<RequestMethodType>(new QName("Post"), RequestMethodType.class, post));
+ dcp.setHTTP(http);
+ op1.getDCP().add(dcp);
+ opmeta.getOperation().add(op1);
+
+ Operation op2 = new Operation();
+ op2.setName("GetCoverage");
+ dcp = new DCP();
+ http = new HTTP();
+ /*
+ // What is the URL for SOAP?
+ soap = new RequestMethodType();
+ soap.setHref("http://localhost/SOAP/URL/for/GetCapabalities");
+ http.getGetOrPost().add(new JAXBElement<RequestMethodType>(new QName("Soap"), RequestMethodType.class, soap));
+ */
+ post = new RequestMethodType();
+ post.setHref(SERVLET_URL);
+ // TODO: Add "Get" request type once KVP encoding is supported
+ http.getGetOrPost().add(new JAXBElement<RequestMethodType>(new QName("Post"), RequestMethodType.class, post));
+ dcp.setHTTP(http);
+ op2.getDCP().add(dcp);
+ DomainType param = new DomainType();
+ param.setName("Format");
+ AllowedValues vals = new AllowedValues();
+ ValueType val;
+ ResultSet set = this.meta.executeQuery("SELECT * FROM wcps_format;");
+ while (set.next())
+ {
+ val = new ValueType();
+ val.setValue(set.getString("mimetype"));
+ vals.getValueOrRange().add((Object)val);
+ }
+ param.setAllowedValues(vals);
+ op2.getConstraint().add(param);
+ opmeta.getOperation().add(op2);
+
+ Operation op3 = new Operation();
+ op3.setName("DescribeCoverage");
+ dcp = new DCP();
+ http = new HTTP();
+ /*
+ // What is the URL for SOAP ?
+ soap = new RequestMethodType();
+ soap.setHref("http://localhost/SOAP/URL/for/GetCapabalities");
+ http.getGetOrPost().add(new JAXBElement<RequestMethodType>(new QName("Soap"), RequestMethodType.class, soap));
+ */
+ post = new RequestMethodType();
+ post.setHref(SERVLET_URL);
+ // TODO: Add "Get" request type once KVP encoding is supported
+ http.getGetOrPost().add(new JAXBElement<RequestMethodType>(new QName("Post"), RequestMethodType.class, post));
+ dcp.setHTTP(http);
+ op3.getDCP().add(dcp);
+ param = new DomainType();
+ param.setName("Format");
+ vals = new AllowedValues();
+ val = new ValueType();
+ val.setValue("text/xml");
+ vals.getValueOrRange().add((Object)val);
+ param.setAllowedValues(vals);
+ op2.getConstraint().add(param);
+ opmeta.getOperation().add(op3);
+
+ output.setOperationsMetadata(opmeta);
+ }
+
+ /**
+ * Builds the output node "Contents"
+ * @throws java.sql.SQLException
+ */
+ private void buildField4() throws SQLException {
+ Contents cont = new Contents();
+
+ ResultSet set = meta.executeQuery("SELECT name FROM wcps_coverage;");
+ while (set.next())
+ {
+ String covName = set.getString("name");
+ CoverageSummaryType sum = new CoverageSummaryType();
+ sum.setAbstract("Available coverage, fetched from the database");
+ sum.setTitle("Coverage " + covName);
+
+ // code holds the coverage value
+ net.opengis.gml.v_3_1_1.CodeType code = new net.opengis.gml.v_3_1_1.CodeType();
+ code.setValue(covName);
+ // code is encapsulated in JAXBElement "jelem"
+ JAXBElement<net.opengis.gml.v_3_1_1.CodeType> jelem =
+ new JAXBElement<net.opengis.gml.v_3_1_1.CodeType>(new QName("Identifier"),
+ net.opengis.gml.v_3_1_1.CodeType.class, code);
+ jelem.setValue(code);
+ // Insert "jelem" into this coveragesummary
+ sum.getRest().add(jelem);
+
+ // Add this CoverageSummary to the list of coverage summaries, to make up the Contents
+ cont.getCoverageSummary().add(sum);
+ }
+
+ output.setContents(cont);
+ }
+
+ private void finishBuild() {
+ output.setVersion("1.1.0");
+ }
+
+}
diff --git a/src/wcs/server/servlet/WCS.java b/src/wcs/server/servlet/WCS.java
new file mode 100644
index 0000000..67dfd67
--- /dev/null
+++ b/src/wcs/server/servlet/WCS.java
@@ -0,0 +1,277 @@
+package wcs.server.servlet;
+
+import wcs.server.core.*;
+import java.io.StringReader;
+import java.io.StringWriter;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Unmarshaller;
+import net.opengis.ows.v_1_0_0.ExceptionReport;
+import net.opengis.wcs.v_1_1_0.Capabilities;
+import net.opengis.wcs.v_1_1_0.CoverageDescriptions;
+import net.opengis.wcs.v_1_1_0.DescribeCoverage;
+import net.opengis.wcs.v_1_1_0.GetCapabilities;
+import net.opengis.wcs.v_1_1_0.GetCoverage;
+
+/**
+ * The Web Coverage Service (WCS)
+ * This class provides methods for each of the WCS operations:
+ * - GetCapabilities
+ * - DescribeCoverage
+ * - GetCoverage
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class WCS {
+
+ private static Boolean ok;
+ private static Boolean printOutput;
+ private static Boolean printLog;
+ private static String metaDbPath;
+
+ /**
+ * Public minimal constructor
+ * @param metadataDbPath path to the "dbparams.properties" file
+ */
+ public WCS(String metadataDbPath)
+ {
+ printLog = true;
+ printOutput = true;
+ ok = true;
+ metaDbPath = metadataDbPath;
+ }
+
+ /**
+ * Record a log message
+ * @param msg Text of the message
+ */
+ public static void log(String msg)
+ {
+ if (printLog)
+ System.err.println(msg);
+ }
+
+ /**
+ * WCS GetCapabilities operation
+ */
+ public String GetCapabilities(String stringXml)
+ {
+ String output = "Default output. ";
+ String errmsg = "No error. ";
+ ok = false;
+
+ try
+ {
+ // read the input XML
+ log(">>> Reading the input XML file ... ");
+ JAXBContext context = JAXBContext.newInstance("net.opengis.wcs.v_1_1_0");
+ Unmarshaller unmarshaller = context.createUnmarshaller() ;
+ Object xml = unmarshaller.unmarshal(new StringReader(stringXml));
+ // Find out which class to execute ...
+ log(">>> It is a " + xml.getClass().getSimpleName() + " request.");
+
+ log(">>> Compiling data into XML format for GetCapabilities ... ");
+ GetCapabilities input = (GetCapabilities) xml;
+ Capabilities cap = new executeGetCapabilities(input,metaDbPath).get();
+
+ // Write the output
+ javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(cap.getClass().getPackage().getName());
+ javax.xml.bind.Marshaller marshaller = jaxbCtx.createMarshaller();
+ marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_ENCODING, "UTF-8"); //NOI18N
+ marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+ StringWriter strWriter = new StringWriter();
+ marshaller.marshal(cap, strWriter);
+ output = strWriter.toString();
+ log(">>> Done! User has the GetCapabilities result !");
+ ok = true;
+
+
+ }
+ catch (javax.xml.bind.JAXBException ex) {
+ java.util.logging.Logger.getLogger("global").log(java.util.logging.Level.SEVERE, null, ex); //NOI18N
+ ex.printStackTrace();
+ errmsg = ex.toString();
+ log("ERROR 1 ");
+ }
+ catch (WCSException e)
+ {
+ log("*** GOT WCS EXCEPTION !");
+ ExceptionReport report = e.getReport();
+ try
+ {
+ javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(report.getClass().getPackage().getName());
+ javax.xml.bind.Marshaller marshaller = jaxbCtx.createMarshaller();
+ marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_ENCODING, "UTF-8"); //NOI18N
+ marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+ marshaller.marshal(report, System.err);
+ StringWriter strWriter = new StringWriter();
+ marshaller.marshal(report, strWriter);
+ output = strWriter.toString();
+ ok = true;
+ log("Done with the Error Report !");
+ }
+ catch (Exception e2)
+ {
+ e2.printStackTrace();
+ errmsg = e2.toString();
+ log("ERROR 2");
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ errmsg = e.toString();
+ log("ERROR 3");
+ }
+
+ if (ok == false)
+ output = errmsg;
+ if (printOutput)
+ System.out.println("*****************\nOUTPUT IS \n" + output);
+
+ return output;
+ }
+
+ /**
+ * WCS GetCoverage operation
+ */
+ public String GetCoverage(String stringXml)
+ {
+ String output = "Default output. ";
+ String errmsg = "No error. ";
+ ok = false;
+
+ try
+ {
+ // read the input XML
+ log(">>> Reading the input XML file ... ");
+ JAXBContext context = JAXBContext.newInstance("net.opengis.wcs.v_1_1_0");
+ Unmarshaller unmarshaller = context.createUnmarshaller() ;
+ Object xml = unmarshaller.unmarshal(new StringReader(stringXml));
+ log(">>> It is a " + xml.getClass().getSimpleName() + " request.");
+
+ //Convert the WCS into WCPS
+ log(">>> Converting to WCPS ... please wait");
+ GetCoverage wcs = (GetCoverage) xml;
+ ProcessCoverage wcps = new convertGetCoverage(wcs, metaDbPath).get();
+ // Write the output WCPS request
+ log(">>> Writing the WCPS XML request ...");
+ javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(wcps.getClass().getPackage().getName());
+ javax.xml.bind.Marshaller marshaller = jaxbCtx.createMarshaller();
+ marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_ENCODING, "UTF-8"); //NOI18N
+ marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+ StringWriter strWriter = new StringWriter();
+ marshaller.marshal(wcps, strWriter);
+ output = strWriter.toString();
+ log(">>> Done! User has his WCPS request !");
+ ok = true;
+ }
+ catch (WCSException e)
+ {
+ ExceptionReport report = e.getReport();
+ try
+ {
+ javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(report.getClass().getPackage().getName());
+ javax.xml.bind.Marshaller marshaller = jaxbCtx.createMarshaller();
+ marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_ENCODING, "UTF-8"); //NOI18N
+ marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+ marshaller.marshal(report, System.err);
+ StringWriter strWriter = new StringWriter();
+ marshaller.marshal(report, strWriter);
+ output = strWriter.toString();
+ ok = true;
+ log("Done with the Error Report !");
+ }
+ catch (Exception e2)
+ {
+ e2.printStackTrace();
+ errmsg = e2.toString();
+ log("ERROR 4");
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ errmsg = e.toString();
+ log("ERROR 5");
+ }
+
+ if (ok == false)
+ output = errmsg;
+ if (printOutput)
+ System.out.println("*****************\nOUTPUT IS \n" + output);
+
+ return output;
+ }
+
+ /**
+ * WCS DescribeCoverage operation
+ */
+ public String DescribeCoverage(String stringXml)
+ {
+ String output = "Default output. ";
+ String errmsg = "No error. ";
+ ok = false;
+
+ try
+ {
+ // read the input XML
+ log(">>> Reading the input XML file ... ");
+ JAXBContext context = JAXBContext.newInstance("net.opengis.wcs.v_1_1_0");
+ Unmarshaller unmarshaller = context.createUnmarshaller() ;
+ Object xml = unmarshaller.unmarshal(new StringReader(stringXml));
+ log(">>> It is a " + xml.getClass().getSimpleName() + " request.");
+
+ log(">>> Querying the WCPS architecture for the details on this coverage ...");
+ DescribeCoverage input = (DescribeCoverage) xml;
+ CoverageDescriptions covs = new executeDescribeCoverage(input, metaDbPath).get();
+
+ // Write the output file
+ javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(covs.getClass().getPackage().getName());
+ javax.xml.bind.Marshaller marshaller = jaxbCtx.createMarshaller();
+ marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_ENCODING, "UTF-8"); //NOI18N
+ marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+ StringWriter strWriter = new StringWriter();
+ marshaller.marshal(covs, strWriter);
+ output = strWriter.toString();
+ log(">>> Done! User has the DescribeCoverage result !");
+ ok = true;
+ }
+ catch (WCSException e)
+ {
+ ExceptionReport report = e.getReport();
+ try {
+ javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(report.getClass().getPackage().getName());
+ javax.xml.bind.Marshaller marshaller = jaxbCtx.createMarshaller();
+ marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_ENCODING, "UTF-8"); //NOI18N
+ marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+ marshaller.marshal(report, System.err);
+ StringWriter strWriter = new StringWriter();
+ marshaller.marshal(report, strWriter);
+ output = strWriter.toString();
+ ok = true;
+ log("Done with the Error Report !");
+ }
+ catch (Exception e2)
+ {
+ e2.printStackTrace();
+ errmsg = e2.toString();
+ log("ERROR 6");
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ errmsg = e.toString();
+ log("ERROR 7");
+ }
+
+
+ if (ok == false)
+ output = errmsg;
+ if (printOutput)
+ System.out.println("*****************\nOUTPUT IS \n" + output);
+
+ return output;
+ }
+
+}
diff --git a/src/wcs/server/servlet/WCSTest.java b/src/wcs/server/servlet/WCSTest.java
new file mode 100644
index 0000000..f66d77a
--- /dev/null
+++ b/src/wcs/server/servlet/WCSTest.java
@@ -0,0 +1,210 @@
+package wcs.server.servlet;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+import net.opengis.ows.v_1_0_0.ExceptionReport;
+import org.apache.commons.io.FileUtils;
+import org.junit.*;
+import org.junit.Assert;
+
+/**
+ *
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class WCSTest {
+
+ // Location of the input files, relative to the project folder root
+ private String pathPrefix = "../testing/wcs_test/input/";
+ // Path to "dbparams.properties" file
+ private String metadataDbSettings = "/home/andrei/Job/WCPS Update/WCPS_Project/wcps/dbparams.properties";
+
+ public WCSTest()
+ {
+ }
+
+ /**
+ * Test of GetCoverage method, of class WCS, with input file "GetCoverage1.xml"
+ * Output should be an ProcessCoverage XML, not a ExceptionReport XML
+ */
+ @Test
+// Uncomment the following line to skip this test
+// @Ignore
+ public void testGetCoverage1() throws IOException {
+ System.out.println("*** Testing GetCoverage1.xml");
+ String stringXml = "";
+ boolean gotWcsException = false;
+ stringXml = FileUtils.readFileToString(new File(pathPrefix + "GetCoverage1.xml"));
+
+ WCS instance = new WCS(metadataDbSettings);
+ String result = instance.GetCoverage(stringXml);
+
+ ExceptionReport report = new ExceptionReport();
+ // Try reading the exception report
+ try {
+ javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(ExceptionReport.class.getPackage().getName());
+ javax.xml.bind.Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();
+ report = (ExceptionReport) unmarshaller.unmarshal(new StringReader(result));
+ gotWcsException = true;
+ } catch (Exception e) {
+
+ }
+
+ Assert.assertEquals(false, gotWcsException);
+
+ }
+
+
+ /**
+ * Test of GetCoverage method, of class WCS, with input file "GetCoverage2.xml"
+ * Output should be ProcessCoverage XML, not a ExceptionReport XML
+ */
+ @Test
+// Uncomment the following line to skip this test
+// @Ignore
+ public void testGetCoverage2() throws IOException {
+ System.out.println("*** Testing GetCoverage2.xml");
+ String stringXml = "";
+ boolean gotWcsException = false;
+ stringXml = FileUtils.readFileToString(new File(pathPrefix + "GetCoverage2.xml"));
+
+ WCS instance = new WCS(metadataDbSettings);
+ String result = instance.GetCoverage(stringXml);
+
+ ExceptionReport report = new ExceptionReport();
+ // Try reading the exception report
+ try {
+ javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(ExceptionReport.class.getPackage().getName());
+ javax.xml.bind.Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();
+ report = (ExceptionReport) unmarshaller.unmarshal(new StringReader(result));
+ gotWcsException = true;
+ } catch (Exception e) {
+
+ }
+
+ Assert.assertEquals(false, gotWcsException);
+ }
+
+
+ /**
+ * Test of GetCoverage method, of class WCS, with input file "GetCoverage3.xml"
+ * Output should be ProcessCoverage XML, not a ExceptionReport XML
+ */
+ @Test
+// Uncomment the following line to skip this test
+// @Ignore
+ public void testGetCoverage3() throws IOException {
+ System.out.println("*** Testing GetCoverage3.xml");
+ String stringXml = "";
+ boolean gotWcsException = false;
+ stringXml = FileUtils.readFileToString(new File(pathPrefix + "GetCoverage3.xml"));
+
+ WCS instance = new WCS(metadataDbSettings);
+ String result = instance.GetCoverage(stringXml);
+
+ ExceptionReport report = new ExceptionReport();
+ // Try reading the exception report
+ try {
+ javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(ExceptionReport.class.getPackage().getName());
+ javax.xml.bind.Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();
+ report = (ExceptionReport) unmarshaller.unmarshal(new StringReader(result));
+ gotWcsException = true;
+ } catch (Exception e) {
+
+ }
+
+ Assert.assertEquals(false, gotWcsException);
+ }
+
+ /**
+ * Test of GetCoverage method, of class WCS, with input file "GetCoverage4.xml"
+ * Output should be an ExceptionReport XML, not a ProcessCoverage XML
+ */
+ @Test
+// Uncomment the following line to skip this test
+// @Ignore
+ public void testGetCoverage4() throws IOException {
+ System.out.println("*** Testing GetCoverage4.xml");
+ String stringXml = "";
+ boolean gotWcsException = false;
+ stringXml = FileUtils.readFileToString(new File(pathPrefix + "GetCoverage4.xml"));
+
+ WCS instance = new WCS(metadataDbSettings);
+ String result = instance.GetCoverage(stringXml);
+
+ ExceptionReport report = new ExceptionReport();
+ // Read the ExceptionReport from the "result"
+ try {
+ javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(ExceptionReport.class.getPackage().getName());
+ javax.xml.bind.Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();
+ report = (ExceptionReport) unmarshaller.unmarshal(new StringReader(result));
+ gotWcsException = true;
+ } catch (Exception e) {
+
+ }
+
+ Assert.assertEquals(true, gotWcsException);
+ }
+
+ /**
+ * Test of DescribeCoverage method, of class WCS, with file DescribeCoverage1.xml
+ * Output should be an ExceptionReport XML, not a CoverageDescriptions XML
+ */
+ @Test
+// Uncomment the following line to skip this test
+// @Ignore
+ public void testDescribeCoverage1() throws IOException {
+ System.out.println("*** Testing DescribeCoverage1.xml");
+ String stringXml = "";
+ boolean gotWcsException = false;
+ stringXml = FileUtils.readFileToString(new File(pathPrefix + "DescribeCoverage1.xml"));
+
+ WCS instance = new WCS(metadataDbSettings);
+ String result = instance.DescribeCoverage(stringXml);
+
+ ExceptionReport report = new ExceptionReport();
+ // Read the ExceptionReport from the "result"
+ try {
+ javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(ExceptionReport.class.getPackage().getName());
+ javax.xml.bind.Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();
+ report = (ExceptionReport) unmarshaller.unmarshal(new StringReader(result));
+ gotWcsException = true;
+ } catch (Exception e) {
+
+ }
+
+ Assert.assertEquals(true, gotWcsException);
+ }
+
+ /**
+ * Test of DescribeCoverage method, of class WCS, with file DescribeCoverage2.xml
+ * Output should be a CoverageDescriptions XML, not an ExceptionReport XML
+ */
+ @Test
+// Uncomment the following line to skip this test
+// @Ignore
+ public void testDescribeCoverage2() throws IOException {
+ System.out.println("*** Testing DescribeCoverage2.xml");
+ String stringXml = "";
+ boolean gotWcsException = false;
+ stringXml = FileUtils.readFileToString(new File(pathPrefix + "DescribeCoverage2.xml"));
+
+ WCS instance = new WCS(metadataDbSettings);
+ String result = instance.DescribeCoverage(stringXml);
+
+ ExceptionReport report = new ExceptionReport();
+ // Read the ExceptionReport from the "result"
+ try {
+ javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(ExceptionReport.class.getPackage().getName());
+ javax.xml.bind.Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();
+ report = (ExceptionReport) unmarshaller.unmarshal(new StringReader(result));
+ gotWcsException = true;
+ } catch (Exception e) {
+
+ }
+
+ Assert.assertEquals(false, gotWcsException);
+ }
+
+}
diff --git a/src/wcs/server/servlet/newWcsServlet.java b/src/wcs/server/servlet/newWcsServlet.java
new file mode 100644
index 0000000..64288d6
--- /dev/null
+++ b/src/wcs/server/servlet/newWcsServlet.java
@@ -0,0 +1,244 @@
+package wcs.server.servlet;
+
+import java.io.File;
+import java.io.FileInputStream;
+import org.apache.commons.io.FileUtils;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringBufferInputStream;
+import java.io.StringReader;
+import java.util.List;
+import java.util.Properties;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import net.opengis.ows.v_1_0_0.ExceptionReport;
+import org.xml.sax.InputSource;
+import wcps.server.core.ProcessCoverageRequest;
+import wcps.server.core.CachedMetadataSource;
+import wcps.server.core.DbMetadataSource;
+import wcps.server.core.WCPS;
+
+/**
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class newWcsServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 84786549L;
+
+ private Properties dbParams;
+ private DbMetadataSource metadataSource;
+ private String rasdamanUrl;
+ private String rasdamanDatabase;
+ private String servletHtmlPath; // path to the default HTML response of the servlet
+ private String defaultHtmlResponse; // String containing the HTML code for the default response
+ private WCPS wcps;
+ private String metaDbPath;
+
+ @Override
+ public void init() throws ServletException {
+
+ try {
+ metaDbPath = getServletContext().getRealPath("/dbparams.properties");
+
+ dbParams = new Properties();
+ System.out.println ("WCPS: loading database properties");
+ dbParams.load( new FileInputStream( metaDbPath ) );
+ rasdamanUrl = dbParams.getProperty( "rasdaman_url" );
+ rasdamanDatabase = dbParams.getProperty( "rasdaman_database" );
+
+ servletHtmlPath = getServletContext().getRealPath("/misc/wcs-servlet-default.html");
+ this.defaultHtmlResponse = FileUtils.readFileToString(new File(servletHtmlPath));
+
+ System.out.println ("WCPS: initializing metadata database");
+ metadataSource = new DbMetadataSource( dbParams.getProperty( "metadata_driver" ), dbParams.getProperty( "metadata_url" ), dbParams.getProperty( "metadata_user" ), dbParams.getProperty( "metadata_pass" ), false );
+
+ System.out.println( "WCPS: initializing WCPS core" );
+ wcps = new WCPS( new File( getServletContext().getRealPath( "/xml/ogc/wcps/1.0.1/wcpsProcessCoverage.xsd" ) ), new CachedMetadataSource( metadataSource ) );
+
+ System.out.println( "WCPS: initialization complete" );
+ }
+ catch( Exception e ) {
+ System.out.println( "WCPS: initialization error" );
+ System.out.println( "WCPS: closing metadata database" );
+ if (metadataSource != null) {
+ metadataSource.close();
+ }
+ System.out.println( "WCPS: done with init error" );
+ throw new ServletException( "WCPS initialization error", e );
+ }
+
+ }
+
+
+ /**
+ * Handles the HTTP <code>GET</code> method.
+ * @param request servlet request
+ * @param response servlet response
+ * @throws ServletException if a servlet-specific error occurs
+ * @throws IOException if an I/O error occurs
+ */
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException
+ {
+ System.out.println( "WCS: invoked with GET" );
+ printUsage( response );
+ }
+
+ /**
+ * Handles the HTTP <code>POST</code> method.
+ * @param request servlet request
+ * @param response servlet response
+ * @throws ServletException if a servlet-specific error occurs
+ * @throws IOException if an I/O error occurs
+ */
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException
+ {
+ // Select the operation
+ int op = -1;
+ if (request.getParameter("GetCapabilitiesXML") != null)
+ op = 3;
+ if (request.getParameter("DescribeCoverageXML") != null)
+ op = 2;
+ if (request.getParameter("GetCoverageXML") != null)
+ op = 1;
+
+ // Convert the WCS request into a WCPS request
+ WCS wcs = new WCS(metaDbPath);
+ try
+ {
+ // initialize WebService operation arguments here
+ String inputXML, wcpsXml;
+ PrintWriter out;
+ switch (op)
+ {
+ case 1:
+ inputXML = request.getParameter("GetCoverageXML");
+ wcpsXml = wcs.GetCoverage(inputXML);
+ // Check if this result is an ExceptionReport
+ // Try reading the exception report
+ ExceptionReport report = new ExceptionReport();
+ boolean gotWcsException = false;
+ try
+ {
+ javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(ExceptionReport.class.getPackage().getName());
+ javax.xml.bind.Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();
+ report = (ExceptionReport) unmarshaller.unmarshal(new StringReader(wcpsXml));
+ gotWcsException = true;
+ } catch (Exception e)
+ {
+ gotWcsException = false;
+ }
+
+ // If output is ProcessCOverage, send the WCPS xml to the WCPS servlet
+ if (gotWcsException == false)
+ response = processWcpsRequest(wcpsXml, response);
+ else
+ {
+ out = new PrintWriter(response.getOutputStream());
+ out.write(wcpsXml);
+ out.flush();
+ }
+ break;
+ case 2:
+ inputXML = request.getParameter("DescribeCoverageXML");
+ wcpsXml = wcs.DescribeCoverage(inputXML);
+ out = new PrintWriter(response.getOutputStream());
+ out.write(wcpsXml);
+ out.flush();
+ break;
+ case 3:
+ inputXML = request.getParameter("GetCapabilitiesXML");
+ wcpsXml = wcs.GetCapabilities(inputXML);
+ out = new PrintWriter(response.getOutputStream());
+ out.write(wcpsXml);
+ out.flush();
+ break;
+ default:
+ throw new Exception("No valid operation specified !");
+ }
+
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ throw new ServletException("WCS servlet error !");
+ }
+ }
+
+ /**
+ * Returns a short description of the servlet.
+ * @return a String containing servlet description
+ */
+ @Override
+ public String getServletInfo() {
+ return "Web Coverage Service @ Jacobs University";
+ }
+
+
+ private void printUsage( HttpServletResponse response ) throws IOException
+ {
+
+ System.out.println( "WCS: setting response mimetype to text/html; charset=utf-8" );
+ System.out.println( "WPS: returning usage message" );
+ response.setContentType( "text/html; charset=utf-8" );
+ PrintWriter out = new PrintWriter( response.getOutputStream() );
+
+ System.err.println(this.defaultHtmlResponse);
+ out.println(defaultHtmlResponse);
+
+ out.close();
+ System.out.println( "WCPS: done nothing" );
+
+ }
+
+ /***
+ * Sends a request to the WCPS service.
+ * The source code is copied from the WCPS servlet, WCPService.java.
+ * Make sure to update it if the WCPS code changes.
+ */
+ private HttpServletResponse processWcpsRequest(String xmlRequest, HttpServletResponse response) throws IOException, Exception
+ {
+ try
+ {
+ System.out.println( "WCPS: received the following request:" );
+ System.out.println( xmlRequest );
+
+ System.out.println( "WCPS: preparing request" );
+ ProcessCoverageRequest processCoverageRequest = wcps.pcPrepare(this.rasdamanUrl, this.rasdamanDatabase, new InputSource(new StringBufferInputStream(xmlRequest)));
+ System.out.println( "[" + processCoverageRequest.getMime() + "] " + processCoverageRequest.getQuery());
+
+ String query = processCoverageRequest.getQuery();
+ String mimetype = processCoverageRequest.getMime();
+ System.out.println( "WCPS: executing request" );
+
+ List<byte[]> results = processCoverageRequest.execute();
+
+ System.out.println( "WCPS: setting response mimetype to " + mimetype );
+ response.setContentType( mimetype );
+ System.out.println( "WCPS: returning response" );
+ ServletOutputStream webOut = response.getOutputStream();
+ webOut.write( results.get( 0 ) );
+ System.out.println( "WCPS: done" );
+ }
+ catch (Exception e)
+ {
+ System.out.println("WCPS Error !");
+ PrintWriter webOut = new PrintWriter(response.getOutputStream());
+ webOut.write("WCPS Processing error !\n");
+ webOut.write("xmlRequest is:\n");
+ webOut.write(xmlRequest);
+ webOut.write("\n\n\n");
+ e.printStackTrace(webOut);
+ webOut.flush();
+ }
+ return response;
+ }
+
+}