expressir 2.4.0 → 2.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. checksums.yaml +4 -4
  2. data/TODO.bugs/01-stale-transformer-autoload.md +39 -0
  3. data/TODO.bugs/02-parser-class-instance-vars.md +36 -0
  4. data/TODO.bugs/03-builder-mutable-state.md +43 -0
  5. data/TODO.bugs/04-formatter-public-send-dispatch.md +53 -0
  6. data/TODO.bugs/05-anonymous-formatter-subclass.md +45 -0
  7. data/TODO.bugs/06-collection-registry-single-source.md +53 -0
  8. data/TODO.bugs/07-require-relative-cleanup.md +42 -0
  9. data/TODO.bugs/08-require-expressir-in-commands.md +34 -0
  10. data/TODO.bugs/09-parser-split.md +53 -0
  11. data/TODO.bugs/10-to-s-override.md +42 -0
  12. data/TODO.bugs/11-parser-class-variables.md +39 -0
  13. data/TODO.bugs/12-marker-modules-vs-registry.md +64 -0
  14. data/TODO.bugs/13-string-literal-scanner-limitation.md +52 -0
  15. data/TODO.bugs/14-model-formatting-leak.md +30 -0
  16. data/TODO.bugs/15-expression-children-macro.md +27 -0
  17. data/TODO.bugs/16-pretty-formatter-duplication.md +28 -0
  18. data/TODO.bugs/17-snake-case-cache-mutable-constant.md +28 -0
  19. data/TODO.bugs/18-const-get-private-constants.md +30 -0
  20. data/TODO.bugs/19-format-methods-public.md +22 -0
  21. data/TODO.bugs/20-coverage-nested-entities-dedup.md +20 -0
  22. data/TODO.bugs/21-operator-tokens-secondary-dispatch.md +21 -0
  23. data/TODO.bugs/22-builder-fast-path-wrappers.md +32 -0
  24. data/TODO.bugs/23-coverage-inverse-maps.md +21 -0
  25. data/TODO.bugs/24-streaming-builder-complexity.md +19 -0
  26. data/TODO.bugs/25-debug-puts-in-production.md +21 -0
  27. data/TODO.bugs/26-generic-entity-children-misplaced.md +21 -0
  28. data/TODO.bugs/27-package-build-god-method.md +19 -0
  29. data/TODO.bugs/28-package-god-class.md +30 -0
  30. data/TODO.bugs/29-validate-ascii-god-class.md +24 -0
  31. data/TODO.bugs/30-unicode-map-extraction.md +19 -0
  32. data/TODO.bugs/README.md +43 -0
  33. data/TODO.max-perf/01-restore-ci-green.md +29 -0
  34. data/TODO.max-perf/02-streaming-parse-path.md +31 -0
  35. data/TODO.max-perf/03-cli-parallel-opt-in.md +27 -0
  36. data/TODO.max-perf/04-benchmark-harness.md +28 -0
  37. data/TODO.max-perf/05-parallel-fidelity-specs.md +22 -0
  38. data/TODO.max-perf/06-builder-cpu-audit.md +41 -0
  39. data/TODO.max-perf/07-upstream-parsanol-roadmap.md +27 -0
  40. data/TODO.max-perf/08-builder-build-perf.md +45 -0
  41. data/TODO.max-perf/09-grammar-cold-start.md +25 -0
  42. data/TODO.max-perf/10-parser-facade-hygiene.md +23 -0
  43. data/TODO.max-perf/11-ci-green-closeout.md +25 -0
  44. data/TODO.max-perf/12-require-boot-profile.md +25 -0
  45. data/TODO.max-perf/13-key-conversion-specs.md +26 -0
  46. data/TODO.max-perf/14-builder-call-handler-audit.md +28 -0
  47. data/benchmark/srl_benchmark.rb +76 -17
  48. data/docs/_tutorials/formatting-schemas.adoc +89 -0
  49. data/docs/_tutorials/index.adoc +10 -0
  50. data/docs/lychee.toml +3 -0
  51. data/expressir.gemspec +4 -2
  52. data/lib/expressir/cli.rb +3 -0
  53. data/lib/expressir/commands/changes_import_eengine.rb +0 -6
  54. data/lib/expressir/commands/changes_validate.rb +0 -2
  55. data/lib/expressir/commands/clean.rb +1 -1
  56. data/lib/expressir/commands/coverage.rb +6 -2
  57. data/lib/expressir/commands/file_violations.rb +70 -0
  58. data/lib/expressir/commands/format.rb +1 -1
  59. data/lib/expressir/commands/non_ascii_character.rb +49 -0
  60. data/lib/expressir/commands/non_ascii_violation_collection.rb +301 -0
  61. data/lib/expressir/commands/package.rb +143 -187
  62. data/lib/expressir/commands/validate_ascii.rb +0 -510
  63. data/lib/expressir/commands/version.rb +1 -1
  64. data/lib/expressir/commands.rb +3 -0
  65. data/lib/expressir/coverage.rb +49 -117
  66. data/lib/expressir/express/ast_key_converter.rb +114 -0
  67. data/lib/expressir/express/builder.rb +71 -194
  68. data/lib/expressir/express/builder_context.rb +22 -0
  69. data/lib/expressir/express/builders/expression_builder.rb +16 -16
  70. data/lib/expressir/express/cache.rb +35 -8
  71. data/lib/expressir/express/error.rb +24 -0
  72. data/lib/expressir/express/formatter.rb +33 -18
  73. data/lib/expressir/express/formatters/declarations_formatter.rb +24 -2
  74. data/lib/expressir/express/formatters/remark_formatter.rb +75 -2
  75. data/lib/expressir/express/formatters/statements_formatter.rb +20 -3
  76. data/lib/expressir/express/grammar/parser.rb +705 -0
  77. data/lib/expressir/express/grammar.rb +11 -0
  78. data/lib/expressir/express/node_position_index.rb +215 -0
  79. data/lib/expressir/express/parallel_files.rb +229 -0
  80. data/lib/expressir/express/parser.rb +138 -950
  81. data/lib/expressir/express/pretty_formatter.rb +23 -5
  82. data/lib/expressir/express/remark_attacher.rb +497 -581
  83. data/lib/expressir/express/remark_scanner.rb +84 -19
  84. data/lib/expressir/express/schema_block_scanner.rb +137 -0
  85. data/lib/expressir/express/schema_source_formatter.rb +15 -0
  86. data/lib/expressir/express/scope_resolver.rb +223 -0
  87. data/lib/expressir/express/source_formatter.rb +15 -0
  88. data/lib/expressir/express/streaming_builder.rb +147 -176
  89. data/lib/expressir/express.rb +10 -6
  90. data/lib/expressir/model/concerns.rb +3 -0
  91. data/lib/expressir/model/data_types/generic_entity.rb +6 -6
  92. data/lib/expressir/model/declarations/entity.rb +5 -0
  93. data/lib/expressir/model/declarations/function.rb +5 -0
  94. data/lib/expressir/model/declarations/procedure.rb +5 -0
  95. data/lib/expressir/model/declarations/rule.rb +6 -0
  96. data/lib/expressir/model/declarations/schema.rb +21 -8
  97. data/lib/expressir/model/declarations/type.rb +3 -0
  98. data/lib/expressir/model/exp_file.rb +2 -0
  99. data/lib/expressir/model/expressions/aggregate_initializer.rb +1 -0
  100. data/lib/expressir/model/expressions/aggregate_initializer_item.rb +1 -0
  101. data/lib/expressir/model/expressions/binary_expression.rb +1 -0
  102. data/lib/expressir/model/expressions/entity_constructor.rb +1 -0
  103. data/lib/expressir/model/expressions/function_call.rb +1 -0
  104. data/lib/expressir/model/expressions/interval.rb +1 -0
  105. data/lib/expressir/model/expressions/query_expression.rb +2 -0
  106. data/lib/expressir/model/expressions/unary_expression.rb +1 -0
  107. data/lib/expressir/model/model_element.rb +133 -14
  108. data/lib/expressir/model/remark_format.rb +17 -0
  109. data/lib/expressir/model/remark_info.rb +31 -3
  110. data/lib/expressir/model/remark_placement.rb +29 -0
  111. data/lib/expressir/model/repository.rb +18 -5
  112. data/lib/expressir/model/statements/alias.rb +2 -0
  113. data/lib/expressir/model/statements/assignment.rb +4 -0
  114. data/lib/expressir/model/statements/case.rb +21 -0
  115. data/lib/expressir/model/statements/case_action.rb +1 -0
  116. data/lib/expressir/model/statements/compound.rb +4 -0
  117. data/lib/expressir/model/statements/escape.rb +3 -0
  118. data/lib/expressir/model/statements/if.rb +5 -0
  119. data/lib/expressir/model/statements/null.rb +3 -0
  120. data/lib/expressir/model/statements/procedure_call.rb +3 -0
  121. data/lib/expressir/model/statements/repeat.rb +3 -0
  122. data/lib/expressir/model/statements/return.rb +3 -0
  123. data/lib/expressir/model/statements/skip.rb +3 -0
  124. data/lib/expressir/model.rb +12 -3
  125. data/lib/expressir/package/builder.rb +2 -2
  126. data/lib/expressir/version.rb +6 -1
  127. data/lib/expressir.rb +56 -3
  128. metadata +81 -7
  129. data/lib/expressir/express/transformer/remark_handling.rb +0 -194
@@ -0,0 +1,705 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "parsanol"
4
+
5
+ module Expressir
6
+ module Express
7
+ module Grammar
8
+ # EXPRESS grammar definition: ~250 Parsanol rules implementing
9
+ # ISO 10303-11 concrete syntax.
10
+ #
11
+ # Extracted from the outer Parser class so grammar changes land in
12
+ # one focused file, separate from the I/O orchestration on the
13
+ # Parser facade (lib/expressir/express/parser.rb).
14
+ class Parser < Parsanol::Parser
15
+ root(:syntax)
16
+
17
+ # Class instance variables for caching (not @@ class variables,
18
+ # which are shared across the entire hierarchy). These are scoped
19
+ # to this class only. Accessed via @var within class methods.
20
+ @cached_grammar_json = nil
21
+ @cached_grammar_atom_id = nil
22
+ @cached_parser = nil
23
+ @parser_mutex = Mutex.new
24
+ @cached_schema_grammar_json = nil
25
+
26
+ # Threshold for using memory-bounded fresh parse (bytes)
27
+ # Files above this use parse_fresh which has no packrat cache
28
+ LARGE_FILE_THRESHOLD = 1024 * 1024 # 1 MB
29
+
30
+ # Get cached parser instance (thread-safe)
31
+ # Reusing the parser avoids the overhead of reinitializing all rule definitions
32
+ def self.cached_parser
33
+ return @cached_parser if @cached_parser
34
+
35
+ @parser_mutex.synchronize do
36
+ @cached_parser ||= new
37
+ end
38
+ end
39
+
40
+ # Clear the cached parser (useful for testing or after grammar changes)
41
+ def self.clear_parser_cache
42
+ @parser_mutex.synchronize do
43
+ @cached_parser = nil
44
+ end
45
+ end
46
+
47
+ # Check if native parsing is available
48
+ def self.native_available?
49
+ return @native_available unless @native_available.nil?
50
+
51
+ @native_available = begin
52
+ require "parsanol/native"
53
+ Parsanol::Native.available?
54
+ rescue LoadError
55
+ false
56
+ end
57
+ end
58
+
59
+ # Get cached grammar JSON for native parsing
60
+ def self.cached_grammar_json
61
+ return @cached_grammar_json if @cached_grammar_json
62
+
63
+ parser = new
64
+ atom = parser.syntax
65
+
66
+ # Cache by atom object_id
67
+ if atom.object_id != @cached_grammar_atom_id
68
+ @cached_grammar_atom_id = atom.object_id
69
+ @cached_grammar_json = Parsanol::Native.serialize_grammar(atom)
70
+ end
71
+
72
+ @cached_grammar_json
73
+ end
74
+
75
+ # Get cached grammar JSON for schemaDecl (used for streaming parse)
76
+ def self.cached_schema_grammar_json
77
+ return @cached_schema_grammar_json if @cached_schema_grammar_json
78
+
79
+ schema_atom = cached_parser.schemaDecl
80
+ @cached_schema_grammar_json = Parsanol::Native.serialize_grammar(schema_atom)
81
+ @cached_schema_grammar_json
82
+ end
83
+
84
+ # Parse using native engine with Rust-side transformation (fastest)
85
+ #
86
+ # This method provides ~17x speedup over pure Ruby parsing.
87
+ # The transformation happens in Rust using to_parslet_compatible,
88
+ # producing Parslet-compatible output that Builder.build can consume directly.
89
+ #
90
+ # @param source [String] EXPRESS source code to parse
91
+ # @return [Hash, Array] Transformed AST in Parslet-compatible format
92
+ # @raise [LoadError] If native parser is not available
93
+ def self.parse_native(source)
94
+ unless native_available?
95
+ raise LoadError, "Native parser not available"
96
+ end
97
+
98
+ grammar_atom = cached_parser.syntax
99
+ # Use fresh-parse (no cache) for large files to bound memory
100
+ if source.bytesize > LARGE_FILE_THRESHOLD
101
+ Parsanol::Native.parse_fresh(grammar_atom, source)
102
+ else
103
+ Parsanol::Native.parse(grammar_atom, source)
104
+ end
105
+ end
106
+
107
+ def cts(atom)
108
+ spaces >> atom
109
+ end
110
+
111
+ def cstr(atom)
112
+ cts(str(atom).as(:str))
113
+ end
114
+
115
+ KEYWORDS = %i[
116
+ ABS ABSTRACT ACOS AGGREGATE ALIAS AND ANDOR ARRAY AS ASIN ATAN BAG BASED_ON
117
+ BEGIN BINARY BLENGTH BOOLEAN BY CASE CONSTANT CONST_E COS DERIVE DIV ELSE
118
+ END END_ALIAS END_CASE END_CONSTANT END_ENTITY END_FUNCTION END_IF
119
+ END_LOCAL END_PROCEDURE END_REPEAT END_RULE END_SCHEMA
120
+ END_SUBTYPE_CONSTRAINT END_TYPE ENTITY ENUMERATION ESCAPE EXISTS EXP
121
+ EXTENSIBLE FALSE FIXED FOR FORMAT FROM FUNCTION GENERIC GENERIC_ENTITY
122
+ HIBOUND HIINDEX IF IN INSERT INTEGER INVERSE LENGTH LIKE LIST LOBOUND LOCAL
123
+ LOG LOG10 LOG2 LOGICAL LOINDEX MOD NOT NUMBER NVL ODD OF ONEOF OPTIONAL OR
124
+ OTHERWISE PI PROCEDURE QUERY REAL REFERENCE REMOVE RENAMED REPEAT RETURN
125
+ ROLESOF RULE SCHEMA SELECT SELF SET SIN SIZEOF SKIP SQRT STRING SUBTYPE
126
+ SUBTYPE_CONSTRAINT SUPERTYPE TAN THEN TO TRUE TYPE TYPEOF TOTAL_OVER UNIQUE
127
+ UNKNOWN UNTIL USE USEDIN VALUE VALUE_IN VALUE_UNIQUE VAR WITH WHERE WHILE
128
+ XOR
129
+ ].freeze
130
+
131
+ def keyword_rule(str)
132
+ key_chars = str.to_s.chars
133
+ key_chars
134
+ .collect! { |char| match("[#{char}#{char.downcase}]") }
135
+ .reduce(:>>) >> match["a-zA-Z0-9_"].absent?
136
+ end
137
+
138
+ KEYWORDS.each do |keyword|
139
+ sym = :"t#{keyword}"
140
+ rule(sym) { cts(keyword_rule(keyword).as(:str)).as(sym) }
141
+ end
142
+
143
+ rule(:abstractEntityDeclaration) do
144
+ tABSTRACT.as(:abstractEntityDeclaration)
145
+ end
146
+ rule(:abstractSupertypeDeclaration) do
147
+ (tABSTRACT >> tSUPERTYPE >> subtypeConstraint.maybe).as(:abstractSupertypeDeclaration)
148
+ end
149
+ rule(:abstractSupertype) do
150
+ (tABSTRACT >> tSUPERTYPE >> op_delim).as(:abstractSupertype)
151
+ end
152
+ rule(:actualParameterList) do
153
+ (op_leftparen >> (parameter >> (op_comma >> parameter).repeat).as(:listOf_parameter).maybe >> op_rightparen)
154
+ .as(:actualParameterList)
155
+ end
156
+ rule(:addLikeOp) { (op_plus | op_minus | tOR | tXOR).as(:addLikeOp) }
157
+ rule(:aggregateInitializer) do
158
+ (op_leftbracket >> (element >> (op_comma >> element).repeat).as(:listOf_element).maybe >> op_rightbracket)
159
+ .as(:aggregateInitializer)
160
+ end
161
+ rule(:aggregateSource) { simpleExpression.as(:aggregateSource) }
162
+ rule(:aggregateType) do
163
+ (tAGGREGATE >> (op_colon >> typeLabel).maybe >> tOF >> parameterType).as(:aggregateType)
164
+ end
165
+ rule(:aggregationTypes) do
166
+ (arrayType | bagType | listType | setType).as(:aggregationTypes)
167
+ end
168
+ rule(:algorithmHead) do
169
+ (declaration.repeat.as(:declaration) >> constantDecl.maybe >> localDecl.maybe).as(:algorithmHead)
170
+ end
171
+ rule(:aliasStmt) do
172
+ (tALIAS >> variableId >> tFOR >> generalRef >> qualifier.repeat.as(:qualifier) >>
173
+ op_delim >> stmt.repeat(1).as(:stmt) >> tEND_ALIAS >> op_delim.as(:op_delim2)).as(:aliasStmt)
174
+ end
175
+ rule(:anyKeyword) { KEYWORDS.map { |kw| send("t#{kw}") }.inject(:|) }
176
+ rule(:arrayType) do
177
+ (tARRAY >> boundSpec >> tOF >> tOPTIONAL.maybe >> tUNIQUE.maybe >> instantiableType).as(:arrayType)
178
+ end
179
+ rule(:assignmentStmt) do
180
+ (generalRef >> qualifier.repeat.as(:qualifier) >> op_decl >> expression >> op_delim).as(:assignmentStmt)
181
+ end
182
+ rule(:attributeDecl) do
183
+ (attributeId | redeclaredAttribute).as(:attributeDecl)
184
+ end
185
+ rule(:attributeId) { simpleId.as(:attributeId) }
186
+ rule(:attributeQualifier) do
187
+ (op_period >> attributeRef).as(:attributeQualifier)
188
+ end
189
+ rule(:attributeRef) { attributeId.as(:attributeRef) }
190
+ rule(:bagType) do
191
+ (tBAG >> boundSpec.maybe >> tOF >> instantiableType).as(:bagType)
192
+ end
193
+ rule(:binaryLiteral) do
194
+ cts((str("%") >> bit.repeat(1)).as(:str)).as(:binaryLiteral)
195
+ end
196
+ rule(:binaryType) { (tBINARY >> widthSpec.maybe).as(:binaryType) }
197
+ rule(:bit) { match["0-1"] }
198
+ rule(:booleanType) { tBOOLEAN.as(:booleanType) }
199
+ rule(:bound1) { numericExpression.as(:bound1) }
200
+ rule(:bound2) { numericExpression.as(:bound2) }
201
+ rule(:boundSpec) do
202
+ (op_leftbracket >> bound1 >> op_colon >> bound2 >> op_rightbracket).as(:boundSpec)
203
+ end
204
+ rule(:builtInConstant) do
205
+ (tCONST_E | tPI | tSELF | op_question_mark).as(:builtInConstant)
206
+ end
207
+ rule(:builtInFunction) do
208
+ (tABS | tACOS | tASIN | tATAN | tBLENGTH | tCOS | tEXISTS | tEXP | tFORMAT | tHIBOUND | tHIINDEX | tLENGTH |
209
+ tLOBOUND | tLOINDEX | tLOG2 | tLOG10 | tLOG | tNVL | tODD | tROLESOF | tSIN | tSIZEOF | tSQRT | tTAN |
210
+ tTYPEOF | tUSEDIN | tVALUE_IN | tVALUE_UNIQUE | tVALUE).as(:builtInFunction)
211
+ end
212
+ rule(:builtInProcedure) { (tINSERT | tREMOVE).as(:builtInProcedure) }
213
+ rule(:caseAction) do
214
+ ((caseLabel >> (op_comma >> caseLabel).repeat).as(:listOf_caseLabel) >> op_colon >> stmt).as(:caseAction)
215
+ end
216
+ rule(:caseLabel) { expression.as(:caseLabel) }
217
+ rule(:caseStmt) do
218
+ (tCASE >> selector >> tOF >> caseAction.repeat.as(:caseAction) >> (tOTHERWISE >> op_colon >> stmt).maybe >> tEND_CASE >> op_delim).as(:caseStmt)
219
+ end
220
+ rule(:compoundStmt) do
221
+ (tBEGIN >> stmt.repeat(1).as(:stmt) >> tEND >> op_delim).as(:compoundStmt)
222
+ end
223
+ rule(:concreteTypes) do
224
+ (aggregationTypes | simpleTypes | typeRef).as(:concreteTypes)
225
+ end
226
+ rule(:constantBody) do
227
+ (constantId >> op_colon >> instantiableType >> op_decl >> expression >> op_delim).as(:constantBody)
228
+ end
229
+ rule(:constantDecl) do
230
+ (tCONSTANT >> constantBody.repeat(1).as(:constantBody) >> tEND_CONSTANT >> op_delim).as(:constantDecl)
231
+ end
232
+ rule(:constantFactor) do
233
+ (builtInConstant | constantRef).as(:constantFactor)
234
+ end
235
+ rule(:constantId) { simpleId.as(:constantId) }
236
+ rule(:constantRef) { constantId.as(:constantRef) }
237
+ rule(:constructedTypes) do
238
+ (enumerationType | selectType).as(:constructedTypes)
239
+ end
240
+ rule(:declaration) do
241
+ (entityDecl | functionDecl | procedureDecl | subtypeConstraintDecl | typeDecl).as(:declaration)
242
+ end
243
+ rule(:delim) { cts(str(";").as(:delim)) }
244
+ rule(:deriveClause) do
245
+ (tDERIVE >> derivedAttr.repeat(1).as(:derivedAttr)).as(:deriveClause)
246
+ end
247
+ rule(:derivedAttr) do
248
+ (attributeDecl >> op_colon >> parameterType >> op_decl >> expression >> op_delim).as(:derivedAttr)
249
+ end
250
+ rule(:digit) { match["0-9"] }
251
+ rule(:digits) { digit >> digit.repeat }
252
+ rule(:domainRule) do
253
+ ((ruleLabelId >> op_colon).maybe >> expression).as(:domainRule)
254
+ end
255
+ rule(:element) do
256
+ (expression >> (op_colon >> repetition).maybe).as(:element)
257
+ end
258
+ rule(:embeddedRemark) do
259
+ (
260
+ # `(*)` is a 3-character empty embedded remark: the opener `(*`
261
+ # and closer `*)` share the `*`. Per strict ISO 10303-11 §7.1.6
262
+ # grammar the opener and closer are distinct tokens and cannot
263
+ # share characters, so `(*)` is technically invalid. We accept
264
+ # it for robustness (issue #126).
265
+ str("(*)") |
266
+ (str("(*") >> (str("*)").absent? >> (embeddedRemark | any)).repeat >> str("*)"))
267
+ ).as(:embeddedRemark)
268
+ end
269
+ rule(:encodedCharacter) { octet >> octet >> octet >> octet }
270
+ rule(:encodedStringLiteral) do
271
+ cts((str('"') >> encodedCharacter.repeat(1) >> str('"')).as(:str)).as(:encodedStringLiteral)
272
+ end
273
+ rule(:entityBody) do
274
+ (explicitAttr.repeat.as(:explicitAttr) >> deriveClause.maybe >> inverseClause.maybe >> uniqueClause.maybe >> whereClause.maybe).as(:entityBody)
275
+ end
276
+ rule(:entityConstructor) do
277
+ (entityRef >> op_leftparen >> (expression >> (op_comma >> expression).repeat).as(:listOf_expression).maybe >> op_rightparen).as(:entityConstructor)
278
+ end
279
+ rule(:entityDecl) do
280
+ (entityHead >> entityBody >> tEND_ENTITY >> op_delim).as(:entityDecl)
281
+ end
282
+ rule(:entityHead) do
283
+ (tENTITY >> entityId >> subsuper >> op_delim).as(:entityHead)
284
+ end
285
+ rule(:entityId) { simpleId.as(:entityId) }
286
+ rule(:entityRef) { entityId.as(:entityRef) }
287
+ rule(:enumerationExtension) do
288
+ (tBASED_ON >> typeRef >> (tWITH >> enumerationItems).maybe).as(:enumerationExtension)
289
+ end
290
+ rule(:enumerationId) { simpleId.as(:enumerationId) }
291
+ rule(:enumerationItem) { enumerationId.as(:enumerationItem) }
292
+ rule(:enumerationItems) do
293
+ (op_leftparen >> (enumerationItem >> (op_comma >> enumerationItem).repeat).as(:listOf_enumerationItem) >> op_rightparen).as(:enumerationItems)
294
+ end
295
+ rule(:enumerationRef) { enumerationId.as(:enumerationRef) }
296
+ rule(:enumerationReference) do
297
+ ((typeRef >> op_period).maybe >> enumerationRef).as(:enumerationReference)
298
+ end
299
+ rule(:enumerationType) do
300
+ (tEXTENSIBLE.maybe >> tENUMERATION >> ((tOF >> enumerationItems) | enumerationExtension).maybe).as(:enumerationType)
301
+ end
302
+ rule(:escapeStmt) { (tESCAPE >> op_delim).as(:escapeStmt) }
303
+ rule(:explicitAttr) do
304
+ ((attributeDecl >> (op_comma >> attributeDecl).repeat).as(:listOf_attributeDecl) >> op_colon >>
305
+ tOPTIONAL.maybe >> parameterType >> op_delim).as(:explicitAttr)
306
+ end
307
+ rule(:expression) do
308
+ (simpleExpression >> (relOpExtended >> simpleExpression.as(:rhs)).maybe).as(:expression)
309
+ end
310
+ rule(:factor) do
311
+ (simpleFactor >> (op_double_asterisk >> simpleFactor.as(:rhs)).maybe).as(:factor)
312
+ end
313
+ rule(:formalParameter) do
314
+ ((parameterId >> (op_comma >> parameterId).repeat).as(:listOf_parameterId) >> op_colon >> parameterType).as(:formalParameter)
315
+ end
316
+ rule(:functionCall) do
317
+ ((builtInFunction | functionRef) >> actualParameterList.maybe).as(:functionCall)
318
+ end
319
+ rule(:functionDecl) do
320
+ (functionHead >> algorithmHead >> stmt.repeat(1).as(:stmt) >> tEND_FUNCTION >> op_delim).as(:functionDecl)
321
+ end
322
+ rule(:functionHead) do
323
+ (tFUNCTION >> functionId >>
324
+ (op_leftparen >> (formalParameter >> (op_delim >> formalParameter).repeat).as(:listOf_formalParameter) >> op_rightparen).maybe >>
325
+ op_colon >> parameterType >> op_delim.as(:op_delim2)).as(:functionHead)
326
+ end
327
+ rule(:functionId) { simpleId.as(:functionId) }
328
+ rule(:functionRef) { functionId.as(:functionRef) }
329
+ rule(:generalAggregationTypes) do
330
+ (generalArrayType | generalBagType | generalListType | generalSetType).as(:generalAggregationTypes)
331
+ end
332
+ rule(:generalArrayType) do
333
+ (tARRAY >> boundSpec.maybe >> tOF >> tOPTIONAL.maybe >> tUNIQUE.maybe >> parameterType).as(:generalArrayType)
334
+ end
335
+ rule(:generalBagType) do
336
+ (tBAG >> boundSpec.maybe >> tOF >> parameterType).as(:generalBagType)
337
+ end
338
+ rule(:generalizedTypes) do
339
+ (aggregateType | generalAggregationTypes | genericEntityType | genericType).as(:generalizedTypes)
340
+ end
341
+ rule(:generalListType) do
342
+ (tLIST >> boundSpec.maybe >> tOF >> tUNIQUE.maybe >> parameterType).as(:generalListType)
343
+ end
344
+ rule(:generalRef) { (parameterRef | variableId).as(:generalRef) }
345
+ rule(:generalSetType) do
346
+ (tSET >> boundSpec.maybe >> tOF >> parameterType).as(:generalSetType)
347
+ end
348
+ rule(:genericEntityType) do
349
+ (tGENERIC_ENTITY >> (op_colon >> typeLabel).maybe).as(:genericEntityType)
350
+ end
351
+ rule(:genericType) do
352
+ (tGENERIC >> (op_colon >> typeLabel).maybe).as(:genericType)
353
+ end
354
+ rule(:groupQualifier) do
355
+ (op_double_backslash >> entityRef).as(:groupQualifier)
356
+ end
357
+ rule(:hexDigit) { match["0-9a-fA-F"] }
358
+ rule(:ifStmtElseStatements) do
359
+ stmt.repeat(1).as(:stmt).as(:ifStmtElseStatements)
360
+ end
361
+ rule(:ifStmtStatements) do
362
+ stmt.repeat(1).as(:stmt).as(:ifStmtStatements)
363
+ end
364
+ rule(:ifStmt) do
365
+ (tIF >> logicalExpression >> tTHEN >> ifStmtStatements >> (tELSE >> ifStmtElseStatements).maybe >> tEND_IF >> op_delim).as(:ifStmt)
366
+ end
367
+ rule(:incrementControl) do
368
+ (variableId >> op_decl >> bound1 >> tTO >> bound2 >> (tBY >> increment).maybe).as(:incrementControl)
369
+ end
370
+ rule(:increment) { numericExpression.as(:increment) }
371
+ rule(:index1) { index.as(:index1) }
372
+ rule(:index2) { index.as(:index2) }
373
+ rule(:index) { numericExpression.as(:index) }
374
+ rule(:indexQualifier) do
375
+ (op_leftbracket >> index1 >> (op_colon >> index2).maybe >> op_rightbracket).as(:indexQualifier)
376
+ end
377
+ rule(:instantiableType) do
378
+ (concreteTypes | entityRef).as(:instantiableType)
379
+ end
380
+ rule(:integerLiteral) { cts(digits.as(:str)).as(:integerLiteral) }
381
+ rule(:integerType) { tINTEGER.as(:integerType) }
382
+ rule(:interfaceSpecification) do
383
+ (referenceClause | useClause).as(:interfaceSpecification)
384
+ end
385
+ rule(:intervalHigh) { simpleExpression.as(:intervalHigh) }
386
+ rule(:intervalItem) { simpleExpression.as(:intervalItem) }
387
+ rule(:intervalLow) { simpleExpression.as(:intervalLow) }
388
+ rule(:interval) do
389
+ (op_left_curly_brace >> intervalLow >> intervalOp >> intervalItem >> intervalOp.as(:intervalOp2) >>
390
+ intervalHigh >> op_right_curly_brace).as(:interval)
391
+ end
392
+ rule(:intervalOp) { (op_less_equal | op_less_than).as(:intervalOp) }
393
+ rule(:inverseAttr) do
394
+ (attributeDecl >> op_colon >> inverseAttrType >> tFOR >> (entityRef >> op_period).maybe >> attributeRef >> op_delim).as(:inverseAttr)
395
+ end
396
+ rule(:inverseAttrType) do
397
+ (((tSET | tBAG) >> boundSpec.maybe >> tOF).maybe >> entityRef).as(:inverseAttrType)
398
+ end
399
+ rule(:inverseClause) do
400
+ (tINVERSE >> inverseAttr.repeat(1).as(:inverseAttr)).as(:inverseClause)
401
+ end
402
+ rule(:letter) { match["a-zA-Z"] }
403
+ rule(:listType) do
404
+ (tLIST >> boundSpec.maybe >> tOF >> tUNIQUE.maybe >> instantiableType).as(:listType)
405
+ end
406
+ rule(:literal) do
407
+ (binaryLiteral | logicalLiteral | realLiteral | integerLiteral | stringLiteral).as(:literal)
408
+ end
409
+ rule(:localDecl) do
410
+ (tLOCAL >> localVariable.repeat(1).as(:localVariable) >> tEND_LOCAL >> op_delim).as(:localDecl)
411
+ end
412
+ rule(:localVariable) do
413
+ ((variableId >> (op_comma >> variableId).repeat).as(:listOf_variableId) >>
414
+ op_colon >> parameterType >>
415
+ (op_decl >> expression).maybe >> op_delim).as(:localVariable)
416
+ end
417
+ rule(:logicalExpression) { expression.as(:logicalExpression) }
418
+ rule(:logicalLiteral) do
419
+ (tFALSE | tTRUE | tUNKNOWN).as(:logicalLiteral)
420
+ end
421
+ rule(:logicalType) { tLOGICAL.as(:logicalType) }
422
+ rule(:multiplicationLikeOp) do
423
+ (op_asterisk | op_slash | tDIV | tMOD | tAND | op_double_pipe).as(:multiplicationLikeOp)
424
+ end
425
+ rule(:namedTypeOrRename) do
426
+ (namedTypes >> (tAS >> (entityId | typeId)).maybe).as(:namedTypeOrRename)
427
+ end
428
+ rule(:namedTypes) { (entityRef | typeRef).as(:namedTypes) }
429
+ rule(:nullStmt) { op_delim.as(:nullStmt) }
430
+ rule(:numberType) { tNUMBER.as(:numberType) }
431
+ rule(:numericExpression) { simpleExpression.as(:numericExpression) }
432
+ rule(:octet) { hexDigit >> hexDigit }
433
+ rule(:oneOf) do
434
+ (tONEOF >> op_leftparen >> (supertypeExpression >>
435
+ (op_comma >> supertypeExpression).repeat).as(:listOf_supertypeExpression) >> op_rightparen).as(:oneOf)
436
+ end
437
+ rule(:op_asterisk) { cstr("*").as(:op_asterisk) }
438
+ rule(:op_colon) { cstr(":").as(:op_colon) }
439
+ rule(:op_colon_equals_colon) { cstr(":=:").as(:op_colon_equals_colon) }
440
+ rule(:op_colon_less_greater_colon) do
441
+ cstr(":<>:").as(:op_colon_less_greater_colon)
442
+ end
443
+ rule(:op_comma) { cstr(",").as(:op_comma) }
444
+ rule(:op_decl) { cstr(":=").as(:op_decl) }
445
+ rule(:op_delim) { cstr(";").as(:op_delim) }
446
+ rule(:op_double_asterisk) { cstr("**").as(:op_double_asterisk) }
447
+ rule(:op_double_backslash) { cstr("\\").as(:op_double_backslash) }
448
+ rule(:op_double_pipe) { cstr("||").as(:op_double_pipe) }
449
+ rule(:op_equals) { cstr("=").as(:op_equals) }
450
+ rule(:op_greater_equal) { cstr(">=").as(:op_greater_equal) }
451
+ rule(:op_greater_than) { cstr(">").as(:op_greater_than) }
452
+ rule(:op_leftbracket) { cstr("[").as(:op_leftbracket) }
453
+ rule(:op_left_curly_brace) { cstr("{").as(:op_left_curly_brace) }
454
+ rule(:op_leftparen) { cstr("(").as(:op_leftparen) }
455
+ rule(:op_less_equal) { cstr("<=").as(:op_less_equal) }
456
+ rule(:op_less_greater) { cstr("<>").as(:op_less_greater) }
457
+ rule(:op_less_than) { cstr("<").as(:op_less_than) }
458
+ rule(:op_minus) { cstr("-").as(:op_minus) }
459
+ rule(:op_period) { cstr(".").as(:op_period) }
460
+ rule(:op_pipe) { cstr("|").as(:op_pipe) }
461
+ rule(:op_plus) { cstr("+").as(:op_plus) }
462
+ rule(:op_query_begin) { cstr("<*").as(:op_query_begin) }
463
+ rule(:op_query_end) { cstr("*>").as(:op_query_end) }
464
+ rule(:op_question_mark) { cstr("?").as(:op_question_mark) }
465
+ rule(:op_rightbracket) { cstr("]").as(:op_rightbracket) }
466
+ rule(:op_right_curly_brace) { cstr("}").as(:op_right_curly_brace) }
467
+ rule(:op_rightparen) { cstr(")").as(:op_rightparen) }
468
+ rule(:op_slash) { cstr("/").as(:op_slash) }
469
+ rule(:parameter) { expression.as(:parameter) }
470
+ rule(:parameterId) { simpleId.as(:parameterId) }
471
+ rule(:parameterRef) { parameterId.as(:parameterRef) }
472
+ rule(:parameterType) do
473
+ (generalizedTypes | namedTypes | simpleTypes).as(:parameterType)
474
+ end
475
+ rule(:population) { entityRef.as(:population) }
476
+ rule(:precisionSpec) { numericExpression.as(:precisionSpec) }
477
+ rule(:primary) do
478
+ (literal | (qualifiableFactor >> qualifier.repeat.as(:qualifier))).as(:primary)
479
+ end
480
+ rule(:procedureCallStmt) do
481
+ ((builtInProcedure | procedureRef) >> actualParameterList.maybe >> op_delim).as(:procedureCallStmt)
482
+ end
483
+ rule(:procedureDecl) do
484
+ (procedureHead >> algorithmHead >> stmt.repeat.as(:stmt) >> tEND_PROCEDURE >> op_delim).as(:procedureDecl)
485
+ end
486
+ rule(:procedureHeadParameter) do
487
+ (tVAR.maybe >> formalParameter).as(:procedureHeadParameter)
488
+ end
489
+ rule(:procedureHead) do
490
+ (tPROCEDURE >> procedureId >>
491
+ (op_leftparen >> (procedureHeadParameter >>
492
+ (op_delim >> procedureHeadParameter).repeat).as(:listOf_procedureHeadParameter) >> op_rightparen).maybe >> op_delim.as(:op_delim2)).as(:procedureHead)
493
+ end
494
+ rule(:procedureId) { simpleId.as(:procedureId) }
495
+ rule(:procedureRef) { procedureId.as(:procedureRef) }
496
+ rule(:qualifiableFactor) do
497
+ (functionCall | attributeRef | constantFactor | generalRef | population).as(:qualifiableFactor)
498
+ end
499
+ rule(:qualifiedAttribute) do
500
+ (tSELF >> groupQualifier >> attributeQualifier).as(:qualifiedAttribute)
501
+ end
502
+ rule(:qualifier) do
503
+ (attributeQualifier | groupQualifier | indexQualifier).as(:qualifier)
504
+ end
505
+ rule(:queryExpression) do
506
+ (tQUERY >> op_leftparen >> variableId >> op_query_begin >> aggregateSource >> op_pipe >> logicalExpression >> op_rightparen).as(:queryExpression)
507
+ end
508
+ rule(:realLiteral) do
509
+ cts((digits >> str(".") >> digits.maybe >> (match["eE"] >> sign.maybe >> digits).maybe).as(:str)).as(:realLiteral)
510
+ end
511
+ rule(:realType) do
512
+ (tREAL >> (op_leftparen >> precisionSpec >> op_rightparen).maybe).as(:realType)
513
+ end
514
+ rule(:redeclaredAttribute) do
515
+ (qualifiedAttribute >> (tRENAMED >> attributeId).maybe).as(:redeclaredAttribute)
516
+ end
517
+ rule(:referenceClause) do
518
+ (tREFERENCE >> tFROM >> schemaRef >>
519
+ (op_leftparen >> (resourceOrRename >> (op_comma >> resourceOrRename).repeat).as(:listOf_resourceOrRename) >> op_rightparen).maybe >> op_delim).as(:referenceClause)
520
+ end
521
+ rule(:referencedAttribute) do
522
+ (attributeRef | qualifiedAttribute).as(:referencedAttribute)
523
+ end
524
+ rule(:relOpExtended) { (relOp | tIN | tLIKE).as(:relOpExtended) }
525
+ rule(:relOp) do
526
+ (op_less_equal | op_greater_equal | op_less_greater | op_less_than | op_greater_than | op_equals |
527
+ op_colon_less_greater_colon | op_colon_equals_colon).as(:relOp)
528
+ end
529
+ rule(:renameId) do
530
+ (constantId | entityId | functionId | procedureId | typeId).as(:renameId)
531
+ end
532
+ rule(:repeatControl) do
533
+ (incrementControl.maybe >> whileControl.maybe >> untilControl.maybe).as(:repeatControl)
534
+ end
535
+ rule(:repeatStmt) do
536
+ (tREPEAT >> repeatControl >> op_delim >> stmt.repeat(1).as(:stmt) >> tEND_REPEAT >> op_delim.as(:op_delim2)).as(:repeatStmt)
537
+ end
538
+ rule(:repetition) { numericExpression.as(:repetition) }
539
+ rule(:resourceOrRename) do
540
+ (resourceRef >> (tAS >> renameId).maybe).as(:resourceOrRename)
541
+ end
542
+ rule(:resourceRef) do
543
+ (constantRef | entityRef | functionRef | procedureRef | typeRef).as(:resourceRef)
544
+ end
545
+ rule(:returnStmt) do
546
+ (tRETURN >> (op_leftparen >> expression >> op_rightparen).maybe >> op_delim).as(:returnStmt)
547
+ end
548
+ rule(:ruleDecl) do
549
+ (ruleHead >> algorithmHead >> stmt.repeat.as(:stmt) >> whereClause >> tEND_RULE >> op_delim).as(:ruleDecl)
550
+ end
551
+ rule(:ruleHead) do
552
+ (tRULE >> ruleId >> tFOR >> op_leftparen >>
553
+ (entityRef >> (op_comma >> entityRef).repeat).as(:listOf_entityRef) >> op_rightparen >> op_delim).as(:ruleHead)
554
+ end
555
+ rule(:ruleId) { simpleId.as(:ruleId) }
556
+ rule(:ruleLabelId) { simpleId.as(:ruleLabelId) }
557
+ rule(:ruleLabelRef) { ruleLabelId.as(:ruleLabelRef) }
558
+ rule(:ruleRef) { ruleId.as(:ruleRef) }
559
+ rule(:schemaBodyDeclaration) do
560
+ (declaration | ruleDecl).as(:schemaBodyDeclaration)
561
+ end
562
+ rule(:schemaBody) do
563
+ (interfaceSpecification.repeat.as(:interfaceSpecification) >> constantDecl.maybe >>
564
+ schemaBodyDeclaration.repeat.as(:schemaBodyDeclaration)).as(:schemaBody)
565
+ end
566
+ rule(:schemaDecl) do
567
+ (tSCHEMA >> schemaId >> schemaVersionId.maybe >> op_delim >> schemaBody >> tEND_SCHEMA >> op_delim.as(:op_delim2)).as(:schemaDecl)
568
+ end
569
+ rule(:schemaId) { simpleId.as(:schemaId) }
570
+ rule(:schemaRef) { schemaId.as(:schemaRef) }
571
+ rule(:schemaVersionId) { stringLiteral.as(:schemaVersionId) }
572
+ rule(:selectExtension) do
573
+ (tBASED_ON >> typeRef >> (tWITH >> selectList).maybe).as(:selectExtension)
574
+ end
575
+ rule(:selectList) do
576
+ (op_leftparen >> (namedTypes >> (op_comma >> namedTypes).repeat).as(:listOf_namedTypes) >> op_rightparen).as(:selectList)
577
+ end
578
+ rule(:selector) { expression.as(:selector) }
579
+ rule(:selectType) do
580
+ ((tEXTENSIBLE >> tGENERIC_ENTITY.maybe).maybe >> tSELECT >> (selectList | selectExtension).maybe).as(:selectType)
581
+ end
582
+ rule(:setType) do
583
+ (tSET >> boundSpec.maybe >> tOF >> instantiableType).as(:setType)
584
+ end
585
+ rule(:sign) { match["+-"] }
586
+ rule(:simpleExpression) do
587
+ (term >> (addLikeOp.as(:operator) >> term).as(:item).repeat.as(:rhs)).as(:simpleExpression)
588
+ end
589
+ rule(:simpleFactor) do
590
+ (simpleFactorExpression | aggregateInitializer | entityConstructor | interval | queryExpression | stringLiteral |
591
+ simpleFactorUnaryExpression | enumerationReference).as(:simpleFactor)
592
+ end
593
+ rule(:simpleFactorExpression) do
594
+ ((op_leftparen >> expression >> op_rightparen) | primary).as(:simpleFactorExpression)
595
+ end
596
+ rule(:simpleFactorUnaryExpression) do
597
+ (unaryOp >> simpleFactorExpression).as(:simpleFactorUnaryExpression)
598
+ end
599
+ rule(:simpleId) do
600
+ anyKeyword.absent? >> cts((match["a-zA-Z_"] >> match["a-zA-Z0-9_"].repeat).as(:str)).as(:simpleId)
601
+ end
602
+ rule(:simpleStringLiteral) do
603
+ cts((str("'") >> (str("'").absent? >> any).repeat >> str("'")).as(:str)).as(:simpleStringLiteral)
604
+ end
605
+ rule(:simpleTypes) do
606
+ (binaryType | booleanType | integerType | logicalType | numberType | realType | stringType).as(:simpleTypes)
607
+ end
608
+ rule(:skipStmt) { (tSKIP >> op_delim).as(:skipStmt) }
609
+ rule(:space) { match[" \r\n\t\f"] | embeddedRemark | tailRemark }
610
+ rule(:spaces) { space.repeat.as(:spaces) }
611
+ rule(:stmt) do
612
+ (aliasStmt | assignmentStmt | caseStmt | compoundStmt | escapeStmt | ifStmt |
613
+ nullStmt | procedureCallStmt | repeatStmt | returnStmt | skipStmt).as(:stmt)
614
+ end
615
+ rule(:stringLiteral) do
616
+ (simpleStringLiteral | encodedStringLiteral).as(:stringLiteral)
617
+ end
618
+ rule(:stringType) { (tSTRING >> widthSpec.maybe).as(:stringType) }
619
+ rule(:subsuper) do
620
+ (supertypeConstraint.maybe >> subtypeDeclaration.maybe).as(:subsuper)
621
+ end
622
+ rule(:subtypeConstraintBody) do
623
+ (abstractSupertype.maybe >> totalOver.maybe >> (supertypeExpression >> op_delim).maybe).as(:subtypeConstraintBody)
624
+ end
625
+ rule(:subtypeConstraintDecl) do
626
+ (subtypeConstraintHead >> subtypeConstraintBody >> tEND_SUBTYPE_CONSTRAINT >> op_delim).as(:subtypeConstraintDecl)
627
+ end
628
+ rule(:subtypeConstraintHead) do
629
+ (tSUBTYPE_CONSTRAINT >> subtypeConstraintId >> tFOR >> entityRef >> op_delim).as(:subtypeConstraintHead)
630
+ end
631
+ rule(:subtypeConstraintId) { simpleId.as(:subtypeConstraintId) }
632
+ rule(:subtypeConstraintRef) do
633
+ subtypeConstraintId.as(:subtypeConstraintRef)
634
+ end
635
+ rule(:subtypeConstraint) do
636
+ (tOF >> op_leftparen >> supertypeExpression >> op_rightparen).as(:subtypeConstraint)
637
+ end
638
+ rule(:subtypeDeclaration) do
639
+ (tSUBTYPE >> tOF >> op_leftparen >> entityRef >> (op_comma >> entityRef).repeat >> op_rightparen).as(:listOf_entityRef).as(:subtypeDeclaration)
640
+ end
641
+ rule(:supertypeConstraint) do
642
+ (abstractSupertypeDeclaration | abstractEntityDeclaration | supertypeRule).as(:supertypeConstraint)
643
+ end
644
+ rule(:supertypeExpression) do
645
+ (supertypeFactor >> (tANDOR.as(:operator) >> supertypeFactor).as(:item).repeat.as(:rhs)).as(:supertypeExpression)
646
+ end
647
+ rule(:supertypeFactor) do
648
+ (supertypeTerm >> (tAND.as(:operator) >> supertypeTerm).as(:item).repeat.as(:rhs)).as(:supertypeFactor)
649
+ end
650
+ rule(:supertypeRule) do
651
+ (tSUPERTYPE >> subtypeConstraint).as(:supertypeRule)
652
+ end
653
+ rule(:supertypeTerm) do
654
+ (entityRef | oneOf | (op_leftparen >> supertypeExpression >> op_rightparen)).as(:supertypeTerm)
655
+ end
656
+ rule(:syntax) do
657
+ (spaces.as(:spaces) >> schemaDecl.repeat(1).as(:schemaDecl) >> spaces.as(:trailer)).as(:syntax)
658
+ end
659
+ rule(:tailRemark) do
660
+ (str("--") >> (str("\n").absent? >> any).repeat >> str("\n").maybe).as(:tailRemark)
661
+ end
662
+ rule(:term) do
663
+ (factor >> (multiplicationLikeOp >> factor).as(:item).repeat.as(:rhs)).as(:term)
664
+ end
665
+ rule(:totalOver) do
666
+ (tTOTAL_OVER >> op_leftparen >> (entityRef >> (op_comma >> entityRef).repeat).as(:listOf_entityRef) >> op_rightparen >> op_delim).as(:totalOver)
667
+ end
668
+ rule(:typeDecl) do
669
+ (tTYPE >> typeId >> op_equals >> underlyingType >> op_delim >> whereClause.maybe >> tEND_TYPE >> op_delim.as(:op_delim2)).as(:typeDecl)
670
+ end
671
+ rule(:typeId) { simpleId.as(:typeId) }
672
+ rule(:typeLabelId) { simpleId.as(:typeLabelId) }
673
+ rule(:typeLabelRef) { typeLabelId.as(:typeLabelRef) }
674
+ rule(:typeLabel) { (typeLabelId | typeLabelRef).as(:typeLabel) }
675
+ rule(:typeRef) { typeId.as(:typeRef) }
676
+ rule(:unaryOp) { (op_plus | op_minus | tNOT).as(:unaryOp) }
677
+ rule(:underlyingType) do
678
+ (concreteTypes | constructedTypes).as(:underlyingType)
679
+ end
680
+ rule(:uniqueClause) do
681
+ (tUNIQUE >> (uniqueRule >> op_delim >> (uniqueRule >> op_delim.as(:op_delim2)).repeat).as(:listOf_uniqueRule)).as(:uniqueClause)
682
+ end
683
+ rule(:uniqueRule) do
684
+ ((ruleLabelId >> op_colon).maybe >> (referencedAttribute >> (op_comma >> referencedAttribute).repeat).as(:listOf_referencedAttribute)).as(:uniqueRule)
685
+ end
686
+ rule(:untilControl) { (tUNTIL >> logicalExpression).as(:untilControl) }
687
+ rule(:useClause) do
688
+ (tUSE >> tFROM >> schemaRef >>
689
+ (op_leftparen >> (namedTypeOrRename >> (op_comma >>
690
+ namedTypeOrRename).repeat).as(:listOf_namedTypeOrRename) >> op_rightparen).maybe >> op_delim).as(:useClause)
691
+ end
692
+ rule(:variableId) { simpleId.as(:variableId) }
693
+ rule(:variableRef) { variableId.as(:variableRef) }
694
+ rule(:whereClause) do
695
+ (tWHERE >> (domainRule >> op_delim).repeat.as(:listOf_domainRule)).as(:whereClause)
696
+ end
697
+ rule(:whileControl) { (tWHILE >> logicalExpression).as(:whileControl) }
698
+ rule(:width) { numericExpression.as(:width) }
699
+ rule(:widthSpec) do
700
+ (op_leftparen >> width >> op_rightparen >> tFIXED.maybe).as(:widthSpec)
701
+ end
702
+ end
703
+ end
704
+ end
705
+ end