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.
- checksums.yaml +4 -4
- data/TODO.bugs/01-stale-transformer-autoload.md +39 -0
- data/TODO.bugs/02-parser-class-instance-vars.md +36 -0
- data/TODO.bugs/03-builder-mutable-state.md +43 -0
- data/TODO.bugs/04-formatter-public-send-dispatch.md +53 -0
- data/TODO.bugs/05-anonymous-formatter-subclass.md +45 -0
- data/TODO.bugs/06-collection-registry-single-source.md +53 -0
- data/TODO.bugs/07-require-relative-cleanup.md +42 -0
- data/TODO.bugs/08-require-expressir-in-commands.md +34 -0
- data/TODO.bugs/09-parser-split.md +53 -0
- data/TODO.bugs/10-to-s-override.md +42 -0
- data/TODO.bugs/11-parser-class-variables.md +39 -0
- data/TODO.bugs/12-marker-modules-vs-registry.md +64 -0
- data/TODO.bugs/13-string-literal-scanner-limitation.md +52 -0
- data/TODO.bugs/14-model-formatting-leak.md +30 -0
- data/TODO.bugs/15-expression-children-macro.md +27 -0
- data/TODO.bugs/16-pretty-formatter-duplication.md +28 -0
- data/TODO.bugs/17-snake-case-cache-mutable-constant.md +28 -0
- data/TODO.bugs/18-const-get-private-constants.md +30 -0
- data/TODO.bugs/19-format-methods-public.md +22 -0
- data/TODO.bugs/20-coverage-nested-entities-dedup.md +20 -0
- data/TODO.bugs/21-operator-tokens-secondary-dispatch.md +21 -0
- data/TODO.bugs/22-builder-fast-path-wrappers.md +32 -0
- data/TODO.bugs/23-coverage-inverse-maps.md +21 -0
- data/TODO.bugs/24-streaming-builder-complexity.md +19 -0
- data/TODO.bugs/25-debug-puts-in-production.md +21 -0
- data/TODO.bugs/26-generic-entity-children-misplaced.md +21 -0
- data/TODO.bugs/27-package-build-god-method.md +19 -0
- data/TODO.bugs/28-package-god-class.md +30 -0
- data/TODO.bugs/29-validate-ascii-god-class.md +24 -0
- data/TODO.bugs/30-unicode-map-extraction.md +19 -0
- data/TODO.bugs/README.md +43 -0
- data/TODO.max-perf/01-restore-ci-green.md +29 -0
- data/TODO.max-perf/02-streaming-parse-path.md +31 -0
- data/TODO.max-perf/03-cli-parallel-opt-in.md +27 -0
- data/TODO.max-perf/04-benchmark-harness.md +28 -0
- data/TODO.max-perf/05-parallel-fidelity-specs.md +22 -0
- data/TODO.max-perf/06-builder-cpu-audit.md +41 -0
- data/TODO.max-perf/07-upstream-parsanol-roadmap.md +27 -0
- data/TODO.max-perf/08-builder-build-perf.md +45 -0
- data/TODO.max-perf/09-grammar-cold-start.md +25 -0
- data/TODO.max-perf/10-parser-facade-hygiene.md +23 -0
- data/TODO.max-perf/11-ci-green-closeout.md +25 -0
- data/TODO.max-perf/12-require-boot-profile.md +25 -0
- data/TODO.max-perf/13-key-conversion-specs.md +26 -0
- data/TODO.max-perf/14-builder-call-handler-audit.md +28 -0
- data/benchmark/srl_benchmark.rb +76 -17
- data/docs/_tutorials/formatting-schemas.adoc +89 -0
- data/docs/_tutorials/index.adoc +10 -0
- data/docs/lychee.toml +3 -0
- data/expressir.gemspec +4 -2
- data/lib/expressir/cli.rb +3 -0
- data/lib/expressir/commands/changes_import_eengine.rb +0 -6
- data/lib/expressir/commands/changes_validate.rb +0 -2
- data/lib/expressir/commands/clean.rb +1 -1
- data/lib/expressir/commands/coverage.rb +6 -2
- data/lib/expressir/commands/file_violations.rb +70 -0
- data/lib/expressir/commands/format.rb +1 -1
- data/lib/expressir/commands/non_ascii_character.rb +49 -0
- data/lib/expressir/commands/non_ascii_violation_collection.rb +301 -0
- data/lib/expressir/commands/package.rb +143 -187
- data/lib/expressir/commands/validate_ascii.rb +0 -510
- data/lib/expressir/commands/version.rb +1 -1
- data/lib/expressir/commands.rb +3 -0
- data/lib/expressir/coverage.rb +49 -117
- data/lib/expressir/express/ast_key_converter.rb +114 -0
- data/lib/expressir/express/builder.rb +71 -194
- data/lib/expressir/express/builder_context.rb +22 -0
- data/lib/expressir/express/builders/expression_builder.rb +16 -16
- data/lib/expressir/express/cache.rb +35 -8
- data/lib/expressir/express/error.rb +24 -0
- data/lib/expressir/express/formatter.rb +33 -18
- data/lib/expressir/express/formatters/declarations_formatter.rb +24 -2
- data/lib/expressir/express/formatters/remark_formatter.rb +75 -2
- data/lib/expressir/express/formatters/statements_formatter.rb +20 -3
- data/lib/expressir/express/grammar/parser.rb +705 -0
- data/lib/expressir/express/grammar.rb +11 -0
- data/lib/expressir/express/node_position_index.rb +215 -0
- data/lib/expressir/express/parallel_files.rb +229 -0
- data/lib/expressir/express/parser.rb +138 -950
- data/lib/expressir/express/pretty_formatter.rb +23 -5
- data/lib/expressir/express/remark_attacher.rb +497 -581
- data/lib/expressir/express/remark_scanner.rb +84 -19
- data/lib/expressir/express/schema_block_scanner.rb +137 -0
- data/lib/expressir/express/schema_source_formatter.rb +15 -0
- data/lib/expressir/express/scope_resolver.rb +223 -0
- data/lib/expressir/express/source_formatter.rb +15 -0
- data/lib/expressir/express/streaming_builder.rb +147 -176
- data/lib/expressir/express.rb +10 -6
- data/lib/expressir/model/concerns.rb +3 -0
- data/lib/expressir/model/data_types/generic_entity.rb +6 -6
- data/lib/expressir/model/declarations/entity.rb +5 -0
- data/lib/expressir/model/declarations/function.rb +5 -0
- data/lib/expressir/model/declarations/procedure.rb +5 -0
- data/lib/expressir/model/declarations/rule.rb +6 -0
- data/lib/expressir/model/declarations/schema.rb +21 -8
- data/lib/expressir/model/declarations/type.rb +3 -0
- data/lib/expressir/model/exp_file.rb +2 -0
- data/lib/expressir/model/expressions/aggregate_initializer.rb +1 -0
- data/lib/expressir/model/expressions/aggregate_initializer_item.rb +1 -0
- data/lib/expressir/model/expressions/binary_expression.rb +1 -0
- data/lib/expressir/model/expressions/entity_constructor.rb +1 -0
- data/lib/expressir/model/expressions/function_call.rb +1 -0
- data/lib/expressir/model/expressions/interval.rb +1 -0
- data/lib/expressir/model/expressions/query_expression.rb +2 -0
- data/lib/expressir/model/expressions/unary_expression.rb +1 -0
- data/lib/expressir/model/model_element.rb +133 -14
- data/lib/expressir/model/remark_format.rb +17 -0
- data/lib/expressir/model/remark_info.rb +31 -3
- data/lib/expressir/model/remark_placement.rb +29 -0
- data/lib/expressir/model/repository.rb +18 -5
- data/lib/expressir/model/statements/alias.rb +2 -0
- data/lib/expressir/model/statements/assignment.rb +4 -0
- data/lib/expressir/model/statements/case.rb +21 -0
- data/lib/expressir/model/statements/case_action.rb +1 -0
- data/lib/expressir/model/statements/compound.rb +4 -0
- data/lib/expressir/model/statements/escape.rb +3 -0
- data/lib/expressir/model/statements/if.rb +5 -0
- data/lib/expressir/model/statements/null.rb +3 -0
- data/lib/expressir/model/statements/procedure_call.rb +3 -0
- data/lib/expressir/model/statements/repeat.rb +3 -0
- data/lib/expressir/model/statements/return.rb +3 -0
- data/lib/expressir/model/statements/skip.rb +3 -0
- data/lib/expressir/model.rb +12 -3
- data/lib/expressir/package/builder.rb +2 -2
- data/lib/expressir/version.rb +6 -1
- data/lib/expressir.rb +56 -3
- metadata +81 -7
- data/lib/expressir/express/transformer/remark_handling.rb +0 -194
|
@@ -112,15 +112,13 @@ module Expressir
|
|
|
112
112
|
# @param key [String] The hash key name
|
|
113
113
|
def on_hash_key(key)
|
|
114
114
|
# Convert string key to symbol to match existing parser AST format
|
|
115
|
-
puts "DEBUG on_hash_key: #{key.inspect} (#{key.class})" if ENV["DEBUG_STREAMING"]
|
|
116
115
|
@pending_key = key.to_sym
|
|
117
116
|
end
|
|
118
117
|
|
|
119
118
|
# Called when a hash value is about to be parsed
|
|
120
119
|
#
|
|
121
120
|
# @param key [String] The hash key name
|
|
122
|
-
def on_hash_value(
|
|
123
|
-
puts "DEBUG on_hash_value: #{key.inspect} (#{key.class})" if ENV["DEBUG_STREAMING"]
|
|
121
|
+
def on_hash_value(_key)
|
|
124
122
|
@pending_key = nil
|
|
125
123
|
end
|
|
126
124
|
|
|
@@ -241,191 +239,165 @@ module Expressir
|
|
|
241
239
|
def convert_ast_format(obj)
|
|
242
240
|
case obj
|
|
243
241
|
when Hash
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
# Process each key-value pair
|
|
247
|
-
result = {}
|
|
248
|
-
obj.each do |key, value|
|
|
249
|
-
# Check if this is a str or spaces key with an array value
|
|
250
|
-
result[key] = if %i[str spaces].include?(key) && value.is_a?(Array)
|
|
251
|
-
# Concatenate character arrays
|
|
252
|
-
value.compact.join
|
|
253
|
-
else
|
|
254
|
-
# Recursively convert the value
|
|
255
|
-
convert_ast_format(value)
|
|
256
|
-
end
|
|
257
|
-
end
|
|
258
|
-
result
|
|
242
|
+
convert_hash_node(obj)
|
|
259
243
|
when Array
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
244
|
+
convert_array_node(obj)
|
|
245
|
+
else
|
|
246
|
+
obj
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def convert_hash_node(hash)
|
|
251
|
+
return hash if hash.empty?
|
|
252
|
+
|
|
253
|
+
result = {}
|
|
254
|
+
hash.each do |key, value|
|
|
255
|
+
result[key] = if %i[str spaces].include?(key) && value.is_a?(Array)
|
|
256
|
+
value.compact.join
|
|
257
|
+
else
|
|
258
|
+
convert_ast_format(value)
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
result
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def convert_array_node(array)
|
|
265
|
+
return array if array.empty?
|
|
266
|
+
|
|
267
|
+
converted_items = array.map { |item| convert_ast_format(item) }
|
|
268
|
+
|
|
269
|
+
# Flatten nested arrays from grammar repetition (.repeat)
|
|
270
|
+
flattened = flatten_nested_arrays(converted_items)
|
|
271
|
+
|
|
272
|
+
non_empty = flattened.reject { |item| item.nil? || (item.is_a?(Array) && item.empty?) }
|
|
273
|
+
|
|
274
|
+
if non_empty.empty?
|
|
275
|
+
{}
|
|
276
|
+
elsif non_empty.all?(Hash)
|
|
277
|
+
merge_or_preserve_sequence(non_empty, flattened)
|
|
278
|
+
else
|
|
279
|
+
flattened
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def flatten_nested_arrays(items)
|
|
284
|
+
result = []
|
|
285
|
+
items.each do |item|
|
|
286
|
+
if item.is_a?(Array)
|
|
287
|
+
result.concat(item)
|
|
288
|
+
else
|
|
289
|
+
result << item
|
|
278
290
|
end
|
|
279
|
-
|
|
291
|
+
end
|
|
292
|
+
result
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def merge_or_preserve_sequence(non_empty, converted)
|
|
296
|
+
# Check for repetition patterns that should stay as arrays
|
|
297
|
+
return converted if same_key_repetition?(non_empty)
|
|
298
|
+
return converted if duplicate_key_repetition?(non_empty)
|
|
299
|
+
|
|
300
|
+
# Check for grouped repetition that needs unzipping
|
|
301
|
+
unzipped = try_unzip_repetition(non_empty)
|
|
302
|
+
return unzipped if unzipped
|
|
303
|
+
|
|
304
|
+
# Default: merge all single-key hashes into one hash
|
|
305
|
+
merge_sequence_hashes(non_empty)
|
|
306
|
+
end
|
|
280
307
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
308
|
+
def same_key_repetition?(items)
|
|
309
|
+
first_keys = items.first.keys
|
|
310
|
+
first_keys.length == 1 &&
|
|
311
|
+
items.length > 1 &&
|
|
312
|
+
items.all? { |item| item.keys.length == 1 && item.keys.first == first_keys.first }
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
def duplicate_key_repetition?(items)
|
|
316
|
+
all_keys = items.flat_map(&:keys)
|
|
317
|
+
key_counts = all_keys.tally
|
|
318
|
+
key_counts.any? { |_, count| count > 1 }
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
def try_unzip_repetition(items)
|
|
322
|
+
return nil unless items.length >= 2
|
|
323
|
+
|
|
324
|
+
first_item = items[0]
|
|
325
|
+
later_items = items[1..]
|
|
326
|
+
return nil unless first_item.keys.length == 1 && !first_item.values.first.is_a?(Array)
|
|
327
|
+
|
|
328
|
+
first_key = first_item.keys.first
|
|
329
|
+
repetition_item = later_items.find do |item|
|
|
330
|
+
item.key?(first_key) &&
|
|
331
|
+
item[first_key].is_a?(Array) &&
|
|
332
|
+
item[first_key].length > 1 &&
|
|
333
|
+
item.keys.length >= 2
|
|
334
|
+
end
|
|
335
|
+
return nil unless repetition_item
|
|
336
|
+
|
|
337
|
+
unzip_grouped_repetition(first_item, later_items)
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
def unzip_grouped_repetition(first_item, later_items)
|
|
341
|
+
result = [first_item]
|
|
342
|
+
|
|
343
|
+
later_items.each do |item|
|
|
344
|
+
array_keys = item.select { |_, v| v.is_a?(Array) && v.length > 1 }.keys
|
|
345
|
+
|
|
346
|
+
if array_keys.empty?
|
|
347
|
+
result << item
|
|
348
|
+
elsif array_keys.length == 1
|
|
349
|
+
expand_single_array_key(item, array_keys.first, result)
|
|
350
|
+
else
|
|
351
|
+
expand_multiple_array_keys(item, array_keys, result)
|
|
286
352
|
end
|
|
353
|
+
end
|
|
287
354
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
{}
|
|
291
|
-
elsif non_empty_items.all?(Hash)
|
|
292
|
-
# Check if this is a repetition pattern where all hashes have the SAME single key
|
|
293
|
-
first_keys = non_empty_items.first.keys
|
|
294
|
-
|
|
295
|
-
if first_keys.length == 1 &&
|
|
296
|
-
non_empty_items.length > 1 &&
|
|
297
|
-
non_empty_items.all? do |item|
|
|
298
|
-
item.keys.length == 1 && item.keys.first == first_keys.first
|
|
299
|
-
end
|
|
300
|
-
# Multiple items with the same single key - this is a repetition pattern
|
|
301
|
-
# Keep as array (each element is already a single-key hash)
|
|
302
|
-
return converted_items
|
|
303
|
-
end
|
|
355
|
+
result
|
|
356
|
+
end
|
|
304
357
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
all_keys = non_empty_items.flat_map(&:keys)
|
|
309
|
-
key_counts = all_keys.tally
|
|
310
|
-
if key_counts.any? { |_, count| count > 1 }
|
|
311
|
-
# At least one key appears multiple times - this is a repetition pattern
|
|
312
|
-
# Keep as array
|
|
313
|
-
return converted_items
|
|
314
|
-
end
|
|
358
|
+
def expand_single_array_key(item, key, result)
|
|
359
|
+
values = item[key]
|
|
360
|
+
other_keys = item.keys - [key]
|
|
315
361
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
# 2. A later item has the SAME key with an array value (the grouped repetitions)
|
|
323
|
-
# 3. The later item also has a "separator" key (like op_comma)
|
|
324
|
-
|
|
325
|
-
if non_empty_items.length >= 2
|
|
326
|
-
first_item = non_empty_items[0]
|
|
327
|
-
later_items = non_empty_items[1..]
|
|
328
|
-
|
|
329
|
-
# Check if first item is simple (single key, non-array value)
|
|
330
|
-
if first_item.keys.length == 1 && !first_item.values.first.is_a?(Array)
|
|
331
|
-
first_key = first_item.keys.first
|
|
332
|
-
|
|
333
|
-
# Look for a later item that:
|
|
334
|
-
# 1. Has the same key as the first item
|
|
335
|
-
# 2. That key has an array value with length > 1
|
|
336
|
-
# 3. Also has at least one other key (the separator)
|
|
337
|
-
repetition_item = later_items.find do |item|
|
|
338
|
-
item.key?(first_key) &&
|
|
339
|
-
item[first_key].is_a?(Array) &&
|
|
340
|
-
item[first_key].length > 1 &&
|
|
341
|
-
item.keys.length >= 2
|
|
342
|
-
end
|
|
343
|
-
|
|
344
|
-
if repetition_item
|
|
345
|
-
# This is a repetition pattern - unzip it
|
|
346
|
-
# Build interleaved result
|
|
347
|
-
result = [first_item]
|
|
348
|
-
|
|
349
|
-
later_items.each do |item|
|
|
350
|
-
# Find keys with array values
|
|
351
|
-
array_keys = item.select do |_, v|
|
|
352
|
-
v.is_a?(Array) && v.length > 1
|
|
353
|
-
end.keys
|
|
354
|
-
|
|
355
|
-
if array_keys.empty?
|
|
356
|
-
# No array values - add as-is
|
|
357
|
-
result << item
|
|
358
|
-
elsif array_keys.length == 1
|
|
359
|
-
# Single array key - expand it
|
|
360
|
-
key = array_keys.first
|
|
361
|
-
values = item[key]
|
|
362
|
-
other_keys = item.keys - [key]
|
|
363
|
-
|
|
364
|
-
values.each_with_index do |val, _idx|
|
|
365
|
-
new_item = { key => val }
|
|
366
|
-
other_keys.each do |ok|
|
|
367
|
-
new_item[ok] = item[ok]
|
|
368
|
-
end
|
|
369
|
-
result << new_item
|
|
370
|
-
end
|
|
371
|
-
else
|
|
372
|
-
# Multiple array keys - interleave them
|
|
373
|
-
# All arrays should have the same length
|
|
374
|
-
len = array_keys.map { |k| item[k].length }.max
|
|
375
|
-
other_keys = item.keys - array_keys
|
|
376
|
-
|
|
377
|
-
len.times do |idx|
|
|
378
|
-
new_item = {}
|
|
379
|
-
array_keys.each do |k|
|
|
380
|
-
values = item[k]
|
|
381
|
-
new_item[k] = values[idx] if idx < values.length
|
|
382
|
-
end
|
|
383
|
-
other_keys.each do |ok|
|
|
384
|
-
new_item[ok] = item[ok]
|
|
385
|
-
end
|
|
386
|
-
result << new_item
|
|
387
|
-
end
|
|
388
|
-
end
|
|
389
|
-
end
|
|
362
|
+
values.each do |val|
|
|
363
|
+
new_item = { key => val }
|
|
364
|
+
other_keys.each { |ok| new_item[ok] = item[ok] }
|
|
365
|
+
result << new_item
|
|
366
|
+
end
|
|
367
|
+
end
|
|
390
368
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
end
|
|
369
|
+
def expand_multiple_array_keys(item, array_keys, result)
|
|
370
|
+
len = array_keys.map { |k| item[k].length }.max
|
|
371
|
+
other_keys = item.keys - array_keys
|
|
395
372
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
373
|
+
len.times do |idx|
|
|
374
|
+
new_item = {}
|
|
375
|
+
array_keys.each do |k|
|
|
376
|
+
values = item[k]
|
|
377
|
+
new_item[k] = values[idx] if idx < values.length
|
|
378
|
+
end
|
|
379
|
+
other_keys.each { |ok| new_item[ok] = item[ok] }
|
|
380
|
+
result << new_item
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
def merge_sequence_hashes(items)
|
|
385
|
+
merged = {}
|
|
386
|
+
items.each do |item|
|
|
387
|
+
item.each do |key, value|
|
|
388
|
+
if merged.key?(key)
|
|
389
|
+
existing = merged[key]
|
|
390
|
+
if existing.is_a?(Array)
|
|
391
|
+
existing.is_a?(Array) && value.is_a?(Array) ? existing.concat(value) : existing << value
|
|
392
|
+
else
|
|
393
|
+
merged[key] = [existing, value]
|
|
417
394
|
end
|
|
395
|
+
else
|
|
396
|
+
merged[key] = value
|
|
418
397
|
end
|
|
419
|
-
|
|
420
|
-
# Process the merged hash for :str/:spaces concatenation
|
|
421
|
-
process_str_and_spaces(merged)
|
|
422
|
-
else
|
|
423
|
-
# Regular array - return the converted items
|
|
424
|
-
converted_items
|
|
425
398
|
end
|
|
426
|
-
else
|
|
427
|
-
obj
|
|
428
399
|
end
|
|
400
|
+
process_str_and_spaces(merged)
|
|
429
401
|
end
|
|
430
402
|
|
|
431
403
|
# Add a value to the current container on top of the stack
|
|
@@ -445,7 +417,6 @@ module Expressir
|
|
|
445
417
|
else
|
|
446
418
|
# This handles unexpected container types (debugging)
|
|
447
419
|
if ENV["DEBUG_STREAMING"]
|
|
448
|
-
puts "DEBUG: Unknown container type: #{container.class}"
|
|
449
420
|
puts " Container value: #{container.inspect[0..200]}"
|
|
450
421
|
puts " Pending key: #{@pending_key.inspect}"
|
|
451
422
|
puts " Stack depth: #{@stack.length}"
|
data/lib/expressir/express.rb
CHANGED
|
@@ -2,30 +2,34 @@
|
|
|
2
2
|
|
|
3
3
|
module Expressir
|
|
4
4
|
module Express
|
|
5
|
+
autoload :AstKeyConverter, "#{__dir__}/express/ast_key_converter"
|
|
5
6
|
autoload :Builder, "#{__dir__}/express/builder"
|
|
7
|
+
autoload :BuilderContext, "#{__dir__}/express/builder_context"
|
|
8
|
+
autoload :BuilderRegistry, "#{__dir__}/express/builder_registry"
|
|
6
9
|
autoload :Builders, "#{__dir__}/express/builders"
|
|
7
|
-
# autoload :BuilderRegistry, "#{__dir__}/express/builder_registry"
|
|
8
10
|
|
|
9
11
|
# Core classes (autoloaded for lazy loading)
|
|
10
12
|
autoload :Cache, "#{__dir__}/express/cache"
|
|
11
13
|
autoload :Error, "#{__dir__}/express/error"
|
|
12
14
|
autoload :Formatter, "#{__dir__}/express/formatter"
|
|
13
15
|
autoload :Formatters, "#{__dir__}/express/formatters"
|
|
16
|
+
autoload :Grammar, "#{__dir__}/express/grammar"
|
|
14
17
|
autoload :HyperlinkFormatter, "#{__dir__}/express/hyperlink_formatter"
|
|
15
18
|
autoload :LineMap, "#{__dir__}/express/line_map"
|
|
16
19
|
autoload :ModelVisitor, "#{__dir__}/express/model_visitor"
|
|
20
|
+
autoload :NodePositionIndex, "#{__dir__}/express/node_position_index"
|
|
21
|
+
autoload :ParallelFiles, "#{__dir__}/express/parallel_files"
|
|
17
22
|
autoload :Parser, "#{__dir__}/express/parser"
|
|
18
23
|
autoload :PrettyFormatter, "#{__dir__}/express/pretty_formatter"
|
|
19
24
|
autoload :RemarkAttacher, "#{__dir__}/express/remark_attacher"
|
|
20
25
|
autoload :RemarkScanner, "#{__dir__}/express/remark_scanner"
|
|
21
26
|
autoload :ResolveReferencesModelVisitor,
|
|
22
27
|
"#{__dir__}/express/resolve_references_model_visitor"
|
|
28
|
+
autoload :SchemaBlockScanner, "#{__dir__}/express/schema_block_scanner"
|
|
23
29
|
autoload :SchemaHeadFormatter, "#{__dir__}/express/schema_head_formatter"
|
|
30
|
+
autoload :SchemaSourceFormatter, "#{__dir__}/express/schema_source_formatter"
|
|
31
|
+
autoload :ScopeResolver, "#{__dir__}/express/scope_resolver"
|
|
32
|
+
autoload :SourceFormatter, "#{__dir__}/express/source_formatter"
|
|
24
33
|
autoload :StreamingBuilder, "#{__dir__}/express/streaming_builder"
|
|
25
|
-
|
|
26
|
-
autoload :Transformer, "#{__dir__}/express/transformer"
|
|
27
34
|
end
|
|
28
35
|
end
|
|
29
|
-
|
|
30
|
-
# Eagerly load builders (they register themselves at load time)
|
|
31
|
-
require_relative "express/builder_registry"
|
|
@@ -11,13 +11,13 @@ module Expressir
|
|
|
11
11
|
key_value do
|
|
12
12
|
map "_class", to: :_class, render_default: true
|
|
13
13
|
end
|
|
14
|
-
end
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
# @return [Array<Declaration>]
|
|
16
|
+
def children
|
|
17
|
+
[
|
|
18
|
+
*remark_items,
|
|
19
|
+
]
|
|
20
|
+
end
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
end
|
|
@@ -9,6 +9,11 @@ module Expressir
|
|
|
9
9
|
include HasInformalPropositions
|
|
10
10
|
include HasWhereRules
|
|
11
11
|
|
|
12
|
+
collection_attributes :attributes, :derived_attributes,
|
|
13
|
+
:inverse_attributes, :unique_rules,
|
|
14
|
+
:where_rules, :informal_propositions,
|
|
15
|
+
:remark_items
|
|
16
|
+
|
|
12
17
|
attribute :abstract, :boolean
|
|
13
18
|
attribute :supertype_expression, ModelElement
|
|
14
19
|
attribute :subtype_of, ModelElement, collection: true
|
|
@@ -7,6 +7,11 @@ module Expressir
|
|
|
7
7
|
include Identifier
|
|
8
8
|
include ScopeContainer
|
|
9
9
|
|
|
10
|
+
collection_attributes :parameters, :types, :entities,
|
|
11
|
+
:subtype_constraints, :functions, :procedures,
|
|
12
|
+
:constants, :variables, :statements,
|
|
13
|
+
:remark_items
|
|
14
|
+
|
|
10
15
|
attribute :parameters, Parameter, collection: true
|
|
11
16
|
attribute :return_type, ModelElement
|
|
12
17
|
attribute :types, ModelElement, collection: true
|
|
@@ -7,6 +7,11 @@ module Expressir
|
|
|
7
7
|
include Identifier
|
|
8
8
|
include ScopeContainer
|
|
9
9
|
|
|
10
|
+
collection_attributes :parameters, :types, :entities,
|
|
11
|
+
:subtype_constraints, :functions, :procedures,
|
|
12
|
+
:constants, :variables, :statements,
|
|
13
|
+
:remark_items
|
|
14
|
+
|
|
10
15
|
attribute :parameters, Parameter, collection: true
|
|
11
16
|
attribute :types, ModelElement, collection: true
|
|
12
17
|
attribute :entities, Entity, collection: true
|
|
@@ -9,6 +9,12 @@ module Expressir
|
|
|
9
9
|
include HasInformalPropositions
|
|
10
10
|
include HasWhereRules
|
|
11
11
|
|
|
12
|
+
collection_attributes :applies_to, :types, :entities,
|
|
13
|
+
:subtype_constraints, :functions, :procedures,
|
|
14
|
+
:constants, :variables, :statements,
|
|
15
|
+
:where_rules, :informal_propositions,
|
|
16
|
+
:remark_items
|
|
17
|
+
|
|
12
18
|
attribute :applies_to, ModelElement, collection: true
|
|
13
19
|
attribute :types, ModelElement, collection: true
|
|
14
20
|
attribute :entities, Entity, collection: true
|
|
@@ -7,6 +7,22 @@ module Expressir
|
|
|
7
7
|
include Identifier
|
|
8
8
|
include ScopeContainer
|
|
9
9
|
|
|
10
|
+
# Tree-walker collection attributes (TODO.bugs/12 — single source
|
|
11
|
+
# of truth; NodePositionIndex derives COLLECTION_REGISTRY from this).
|
|
12
|
+
collection_attributes :constants, :types, :entities,
|
|
13
|
+
:subtype_constraints, :functions, :rules,
|
|
14
|
+
:procedures, :remark_items
|
|
15
|
+
|
|
16
|
+
# Subset of this schema's collection attributes that hold named
|
|
17
|
+
# scope declarations (Function, Procedure, Rule, Entity, Type).
|
|
18
|
+
# Used by ScopeResolver to enumerate scope-capable children without
|
|
19
|
+
# duplicating the list. Single source of truth: this is the subset
|
|
20
|
+
# of NodePositionIndex::COLLECTION_REGISTRY[Schema] that holds
|
|
21
|
+
# scopes rather than remark_items / constants / subtype_constraints.
|
|
22
|
+
SCOPE_DECL_COLLECTIONS = %i[
|
|
23
|
+
functions procedures rules entities types
|
|
24
|
+
].freeze
|
|
25
|
+
|
|
10
26
|
attribute :file, :string
|
|
11
27
|
attribute :version, SchemaVersion
|
|
12
28
|
attribute :interfaces, Interface, collection: true
|
|
@@ -17,6 +33,7 @@ module Expressir
|
|
|
17
33
|
attribute :functions, Function, collection: true
|
|
18
34
|
attribute :rules, Rule, collection: true
|
|
19
35
|
attribute :procedures, Procedure, collection: true
|
|
36
|
+
attribute :header, :string
|
|
20
37
|
attribute :_class, :string, default: -> { self.class.name }
|
|
21
38
|
attribute :selected, :boolean, default: false
|
|
22
39
|
attribute :file_basename, :string
|
|
@@ -25,6 +42,7 @@ module Expressir
|
|
|
25
42
|
map "_class", to: :_class, render_default: true
|
|
26
43
|
map "id", to: :id
|
|
27
44
|
map "file", to: :file
|
|
45
|
+
map "header", to: :header
|
|
28
46
|
map "remarks", to: :remarks
|
|
29
47
|
map "remark_items", to: :remark_items
|
|
30
48
|
map "version", to: :version
|
|
@@ -39,6 +57,7 @@ module Expressir
|
|
|
39
57
|
end
|
|
40
58
|
|
|
41
59
|
liquid do
|
|
60
|
+
map :header, to: :header
|
|
42
61
|
map :formatted, to: :formatted
|
|
43
62
|
map :source, to: :source
|
|
44
63
|
map :full_source, to: :full_source
|
|
@@ -74,17 +93,11 @@ module Expressir
|
|
|
74
93
|
end
|
|
75
94
|
|
|
76
95
|
def formatted
|
|
77
|
-
@formatted ||=
|
|
96
|
+
@formatted ||= format(no_remarks: false)
|
|
78
97
|
end
|
|
79
98
|
|
|
80
99
|
def source
|
|
81
|
-
@source ||=
|
|
82
|
-
formatter = Class.new(Expressir::Express::Formatter) do
|
|
83
|
-
include Expressir::Express::SchemaHeadFormatter
|
|
84
|
-
include Expressir::Express::HyperlinkFormatter
|
|
85
|
-
end
|
|
86
|
-
formatter.format(self)
|
|
87
|
-
end
|
|
100
|
+
@source ||= Expressir::Express::SchemaSourceFormatter.format(self)
|
|
88
101
|
end
|
|
89
102
|
|
|
90
103
|
private
|
|
@@ -9,6 +9,9 @@ module Expressir
|
|
|
9
9
|
include HasInformalPropositions
|
|
10
10
|
include HasWhereRules
|
|
11
11
|
|
|
12
|
+
collection_attributes :where_rules, :informal_propositions,
|
|
13
|
+
:remark_items
|
|
14
|
+
|
|
12
15
|
attribute :underlying_type, ModelElement
|
|
13
16
|
attribute :where_rules, WhereRule, collection: true
|
|
14
17
|
attribute :informal_propositions, InformalPropositionRule,
|
|
@@ -4,6 +4,7 @@ module Expressir
|
|
|
4
4
|
# Specified in ISO 10303-11:2004
|
|
5
5
|
# - section 12.9 Aggregate initializer
|
|
6
6
|
class AggregateInitializer < ModelElement
|
|
7
|
+
child_attributes :items
|
|
7
8
|
attribute :items, ModelElement, collection: true
|
|
8
9
|
attribute :_class, :string, default: -> { self.class.name }
|
|
9
10
|
|
|
@@ -4,6 +4,7 @@ module Expressir
|
|
|
4
4
|
# Specified in ISO 10303-11:2004
|
|
5
5
|
# - section 12.9 Aggregate initializer
|
|
6
6
|
class AggregateInitializerItem < ModelElement
|
|
7
|
+
child_attributes :expression, :repetition
|
|
7
8
|
attribute :expression, ModelElement
|
|
8
9
|
attribute :repetition, ModelElement
|
|
9
10
|
attribute :_class, :string, default: -> { self.class.name }
|
|
@@ -10,6 +10,7 @@ module Expressir
|
|
|
10
10
|
# - section 12.6 Aggregate operators
|
|
11
11
|
# - section 12.10 Complex entity instance construction operator
|
|
12
12
|
class BinaryExpression < ModelElement
|
|
13
|
+
child_attributes :operand1, :operand2
|
|
13
14
|
ADDITION = "ADDITION".freeze
|
|
14
15
|
AND = "AND".freeze
|
|
15
16
|
COMBINE = "COMBINE".freeze
|
|
@@ -4,6 +4,7 @@ module Expressir
|
|
|
4
4
|
# Specified in ISO 10303-11:2004
|
|
5
5
|
# - section 9.2.6 Implicit declarations
|
|
6
6
|
class EntityConstructor < ModelElement
|
|
7
|
+
child_attributes :parameters
|
|
7
8
|
attribute :entity, ModelElement
|
|
8
9
|
attribute :parameters, ModelElement, collection: true
|
|
9
10
|
attribute :_class, :string, default: -> { self.class.name }
|
|
@@ -4,6 +4,7 @@ module Expressir
|
|
|
4
4
|
# Specified in ISO 10303-11:2004
|
|
5
5
|
# - section 12.8 Function call
|
|
6
6
|
class FunctionCall < ModelElement
|
|
7
|
+
child_attributes :parameters
|
|
7
8
|
attribute :function, ModelElement
|
|
8
9
|
attribute :parameters, ModelElement, collection: true
|
|
9
10
|
attribute :_class, :string, default: -> { self.class.name }
|
|
@@ -6,6 +6,8 @@ module Expressir
|
|
|
6
6
|
class QueryExpression < ModelElement
|
|
7
7
|
include Identifier
|
|
8
8
|
|
|
9
|
+
child_attributes :expression, :aggregate_source
|
|
10
|
+
|
|
9
11
|
attribute :aggregate_source, ModelElement
|
|
10
12
|
attribute :expression, ModelElement
|
|
11
13
|
attribute :_class, :string, default: -> { self.class.name }
|