expressir 2.4.29-arm-linux
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 +7 -0
- data/.cargo/config.toml +3 -0
- data/.github/scripts/test_installed_gem.rb +34 -0
- data/.github/workflows/codeql.yml +35 -0
- data/.github/workflows/docs.yml +99 -0
- data/.github/workflows/links.yml +100 -0
- data/.github/workflows/native-gems.yml +201 -0
- data/.github/workflows/rake.yml +19 -0
- data/.github/workflows/release.yml +37 -0
- data/.github/workflows/rust-ext.yml +41 -0
- data/.github/workflows/stress.yml +36 -0
- data/.github/workflows/validate_schemas.yml +48 -0
- data/.github/workflows/verify_remarks.yml +33 -0
- data/.gitignore +55 -0
- data/.hound.yml +3 -0
- data/.rspec +2 -0
- data/.rubocop.yml +18 -0
- data/.rubocop_todo.yml +297 -0
- data/CHANGELOG.md +159 -0
- data/Gemfile +18 -0
- data/README.adoc +2783 -0
- data/Rakefile +41 -0
- 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 +36 -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/TODO.parity-ee/00-overview.md +76 -0
- data/TODO.parity-ee/01-annex-g-rule-extraction.md +41 -0
- data/TODO.parity-ee/02-eeng-algorithm-inventory.md +8 -0
- data/TODO.parity-ee/03-eeng-oracle-harness.md +33 -0
- data/TODO.parity-ee/04-shtolo-concatenate.md +44 -0
- data/TODO.parity-ee/05-shtolo-longform-flatten.md +53 -0
- data/TODO.parity-ee/06-interface-scheduling-parity.md +47 -0
- data/TODO.parity-ee/07-semantic-checks-port.md +35 -0
- data/TODO.parity-ee/08-pretty-roundtrip-gate.md +27 -0
- data/TODO.parity-ee/09-smrl-index-and-listing.md +22 -0
- data/TODO.parity-ee/10-interface-dot-graph.md +21 -0
- data/TODO.parity-ee/11-import-eeng-tests.md +79 -0
- data/TODO.parity-ee/12-full-check-catalog.md +67 -0
- data/TODO.parity-ee/13-population-p21.md +54 -0
- data/TODO.parity-ee/14-shtolo-completion.md +44 -0
- data/TODO.parity-ee/15-part28-xml.md +51 -0
- data/TODO.parity-ee/16-compare-patch.md +48 -0
- data/TODO.parity-ee/17-official-tests.md +42 -0
- data/TODO.parity-ee/18-mim-mapping.md +47 -0
- data/TODO.parity-ee/19-architecture.md +97 -0
- data/TODO.parity-ee/parity-matrix.md +108 -0
- data/TODO.refpath-v2/00-overview.md +64 -0
- data/TODO.suma-improvements/00-overview.md +23 -0
- data/TODO.suma-improvements/01-prebuilt-platform-gems.md +33 -0
- data/TODO.suma-improvements/02-suma-e2e.md +39 -0
- data/TODO.suma-improvements/03-item-graph.md +22 -0
- data/TODO.suma-improvements/04-compiled-set-default.md +16 -0
- data/TODO.suma-improvements/05-validation-in-docs.md +17 -0
- data/TODO.suma-improvements/06-memory-remeasure.md +36 -0
- data/TODO.suma-improvements/07-part28-xml.md +15 -0
- data/TODO.suma-improvements/08-windows-gnu-toolchain.md +15 -0
- data/TODO.suma-improvements/09-checker-tranche3.md +13 -0
- data/TODO.suma-improvements/10-expressdoc.md +8 -0
- data/benchmark/srl_benchmark.rb +458 -0
- data/benchmark/srl_native_benchmark.rb +146 -0
- data/benchmark/srl_ruby_benchmark.rb +132 -0
- data/bin/console +11 -0
- data/bin/rspec +30 -0
- data/bin/setup +8 -0
- data/docs/Gemfile +12 -0
- data/docs/_config.yml +141 -0
- data/docs/_guides/changes/changes-format.adoc +778 -0
- data/docs/_guides/changes/importing-eengine.adoc +898 -0
- data/docs/_guides/changes/index.adoc +396 -0
- data/docs/_guides/changes/programmatic-usage.adoc +1038 -0
- data/docs/_guides/changes/validating-changes.adoc +681 -0
- data/docs/_guides/cli/benchmark-performance.adoc +834 -0
- data/docs/_guides/cli/coverage-analysis.adoc +921 -0
- data/docs/_guides/cli/format-schemas.adoc +547 -0
- data/docs/_guides/cli/index.adoc +8 -0
- data/docs/_guides/cli/managing-changes.adoc +927 -0
- data/docs/_guides/cli/validate-ascii.adoc +645 -0
- data/docs/_guides/cli/validate-schemas.adoc +534 -0
- data/docs/_guides/formatter/formatter-architecture.adoc +401 -0
- data/docs/_guides/index.adoc +165 -0
- data/docs/_guides/ler/creating-packages.adoc +664 -0
- data/docs/_guides/ler/index.adoc +305 -0
- data/docs/_guides/ler/loading-packages.adoc +707 -0
- data/docs/_guides/ler/package-formats.adoc +748 -0
- data/docs/_guides/ler/querying-packages.adoc +826 -0
- data/docs/_guides/ler/step-packages.adoc +385 -0
- data/docs/_guides/ler/validating-packages.adoc +750 -0
- data/docs/_guides/liquid/basic-templates.adoc +813 -0
- data/docs/_guides/liquid/documentation-generation.adoc +1042 -0
- data/docs/_guides/liquid/drops-reference.adoc +829 -0
- data/docs/_guides/liquid/filters-and-tags.adoc +912 -0
- data/docs/_guides/liquid/index.adoc +468 -0
- data/docs/_guides/manifests/creating-manifests.adoc +483 -0
- data/docs/_guides/manifests/index.adoc +307 -0
- data/docs/_guides/manifests/resolving-manifests.adoc +557 -0
- data/docs/_guides/manifests/validating-manifests.adoc +713 -0
- data/docs/_guides/ruby-api/formatting-schemas.adoc +605 -0
- data/docs/_guides/ruby-api/index.adoc +257 -0
- data/docs/_guides/ruby-api/parsing-files.adoc +421 -0
- data/docs/_guides/ruby-api/search-engine.adoc +609 -0
- data/docs/_guides/ruby-api/working-with-repository.adoc +577 -0
- data/docs/_pages/data-model.adoc +665 -0
- data/docs/_pages/express-language.adoc +506 -0
- data/docs/_pages/getting-started.adoc +414 -0
- data/docs/_pages/index.adoc +116 -0
- data/docs/_pages/introduction.adoc +256 -0
- data/docs/_pages/ler-packages.adoc +837 -0
- data/docs/_pages/parsers.adoc +709 -0
- data/docs/_pages/schema-manifests.adoc +431 -0
- data/docs/_references/index.adoc +228 -0
- data/docs/_tutorials/creating-ler-package.adoc +735 -0
- data/docs/_tutorials/documentation-coverage.adoc +795 -0
- data/docs/_tutorials/formatting-schemas.adoc +89 -0
- data/docs/_tutorials/index.adoc +231 -0
- data/docs/_tutorials/liquid-templates.adoc +806 -0
- data/docs/_tutorials/parsing-your-first-schema.adoc +522 -0
- data/docs/_tutorials/querying-schemas.adoc +751 -0
- data/docs/_tutorials/working-with-multiple-schemas.adoc +676 -0
- data/docs/index.adoc +242 -0
- data/docs/lychee.toml +90 -0
- data/examples/demo_ler_usage.sh +86 -0
- data/examples/ler/README.md +111 -0
- data/examples/ler/simple_example.ler +0 -0
- data/examples/ler/simple_schema.exp +33 -0
- data/examples/ler_build.rb +75 -0
- data/examples/ler_cli.rb +79 -0
- data/examples/ler_demo_complete.rb +276 -0
- data/examples/ler_query.rb +91 -0
- data/examples/ler_query_examples.rb +305 -0
- data/examples/ler_stats.rb +81 -0
- data/examples/phase3_demo.rb +159 -0
- data/examples/query_demo_simple.rb +131 -0
- data/exe/expressir +11 -0
- data/exe/expressir-format +14 -0
- data/exe/expressir-format-test +82 -0
- data/expressir.gemspec +61 -0
- data/lib/expressir/3.2/expressir_core.so +0 -0
- data/lib/expressir/3.3/expressir_core.so +0 -0
- data/lib/expressir/3.4/expressir_core.so +0 -0
- data/lib/expressir/4.0/expressir_core.so +0 -0
- data/lib/expressir/benchmark.rb +310 -0
- data/lib/expressir/changes/item_change.rb +20 -0
- data/lib/expressir/changes/mapping_change.rb +16 -0
- data/lib/expressir/changes/schema_change.rb +85 -0
- data/lib/expressir/changes/version_change.rb +26 -0
- data/lib/expressir/changes.rb +9 -0
- data/lib/expressir/cli.rb +148 -0
- data/lib/expressir/commands/base.rb +25 -0
- data/lib/expressir/commands/benchmark.rb +59 -0
- data/lib/expressir/commands/benchmark_cache.rb +80 -0
- data/lib/expressir/commands/changes.rb +34 -0
- data/lib/expressir/commands/changes_import_eengine.rb +146 -0
- data/lib/expressir/commands/changes_validate.rb +63 -0
- data/lib/expressir/commands/check.rb +56 -0
- data/lib/expressir/commands/clean.rb +20 -0
- data/lib/expressir/commands/coverage.rb +458 -0
- data/lib/expressir/commands/expand.rb +26 -0
- data/lib/expressir/commands/file_violations.rb +70 -0
- data/lib/expressir/commands/fix.rb +33 -0
- data/lib/expressir/commands/flatten.rb +29 -0
- data/lib/expressir/commands/format.rb +43 -0
- data/lib/expressir/commands/manifest.rb +420 -0
- data/lib/expressir/commands/mapping_validate.rb +68 -0
- 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 +1222 -0
- data/lib/expressir/commands/parity_inputs.rb +160 -0
- data/lib/expressir/commands/validate.rb +106 -0
- data/lib/expressir/commands/validate_ascii.rb +94 -0
- data/lib/expressir/commands/validate_load.rb +91 -0
- data/lib/expressir/commands/version.rb +9 -0
- data/lib/expressir/commands/xsd.rb +23 -0
- data/lib/expressir/commands.rb +30 -0
- data/lib/expressir/config.rb +60 -0
- data/lib/expressir/coverage.rb +510 -0
- data/lib/expressir/eengine/arm_compare_report.rb +23 -0
- data/lib/expressir/eengine/changes_section.rb +16 -0
- data/lib/expressir/eengine/compare_report.rb +69 -0
- data/lib/expressir/eengine/mim_compare_report.rb +23 -0
- data/lib/expressir/eengine/modified_object.rb +21 -0
- data/lib/expressir/eengine.rb +9 -0
- data/lib/expressir/errors.rb +113 -0
- data/lib/expressir/express/adoc_hyperlink_formatter.rb +30 -0
- data/lib/expressir/express/adoc_source_formatter.rb +12 -0
- data/lib/expressir/express/ast_key_converter.rb +114 -0
- data/lib/expressir/express/builder.rb +277 -0
- data/lib/expressir/express/builder_context.rb +22 -0
- data/lib/expressir/express/builder_registry.rb +397 -0
- data/lib/expressir/express/builders/attribute_decl_builder.rb +32 -0
- data/lib/expressir/express/builders/built_in_builder.rb +75 -0
- data/lib/expressir/express/builders/constant_builder.rb +108 -0
- data/lib/expressir/express/builders/declaration_builder.rb +20 -0
- data/lib/expressir/express/builders/derive_clause_builder.rb +14 -0
- data/lib/expressir/express/builders/derived_attr_builder.rb +28 -0
- data/lib/expressir/express/builders/domain_rule_builder.rb +21 -0
- data/lib/expressir/express/builders/entity_decl_builder.rb +116 -0
- data/lib/expressir/express/builders/explicit_attr_builder.rb +49 -0
- data/lib/expressir/express/builders/expression_builder.rb +416 -0
- data/lib/expressir/express/builders/function_decl_builder.rb +86 -0
- data/lib/expressir/express/builders/helpers.rb +148 -0
- data/lib/expressir/express/builders/interface_builder.rb +151 -0
- data/lib/expressir/express/builders/inverse_attr_builder.rb +43 -0
- data/lib/expressir/express/builders/inverse_attr_type_builder.rb +30 -0
- data/lib/expressir/express/builders/inverse_clause_builder.rb +14 -0
- data/lib/expressir/express/builders/literal_builder.rb +93 -0
- data/lib/expressir/express/builders/procedure_decl_builder.rb +82 -0
- data/lib/expressir/express/builders/qualifier_builder.rb +102 -0
- data/lib/expressir/express/builders/reference_builder.rb +18 -0
- data/lib/expressir/express/builders/rule_decl_builder.rb +97 -0
- data/lib/expressir/express/builders/schema_body_decl_builder.rb +18 -0
- data/lib/expressir/express/builders/schema_decl_builder.rb +56 -0
- data/lib/expressir/express/builders/schema_version_builder.rb +34 -0
- data/lib/expressir/express/builders/simple_id_builder.rb +17 -0
- data/lib/expressir/express/builders/statement_builder.rb +243 -0
- data/lib/expressir/express/builders/subtype_constraint_builder.rb +166 -0
- data/lib/expressir/express/builders/syntax_builder.rb +30 -0
- data/lib/expressir/express/builders/type_builder.rb +238 -0
- data/lib/expressir/express/builders/type_decl_builder.rb +26 -0
- data/lib/expressir/express/builders/unique_clause_builder.rb +20 -0
- data/lib/expressir/express/builders/unique_rule_builder.rb +41 -0
- data/lib/expressir/express/builders/where_clause_builder.rb +20 -0
- data/lib/expressir/express/builders.rb +55 -0
- data/lib/expressir/express/cache.rb +76 -0
- data/lib/expressir/express/checker.rb +812 -0
- data/lib/expressir/express/concatenator.rb +79 -0
- data/lib/expressir/express/core.rb +95 -0
- data/lib/expressir/express/error.rb +124 -0
- data/lib/expressir/express/formatter.rb +149 -0
- data/lib/expressir/express/formatters/data_types_formatter.rb +362 -0
- data/lib/expressir/express/formatters/declarations_formatter.rb +753 -0
- data/lib/expressir/express/formatters/expressions_formatter.rb +180 -0
- data/lib/expressir/express/formatters/literals_formatter.rb +55 -0
- data/lib/expressir/express/formatters/references_formatter.rb +53 -0
- data/lib/expressir/express/formatters/remark_formatter.rb +270 -0
- data/lib/expressir/express/formatters/remark_item_formatter.rb +28 -0
- data/lib/expressir/express/formatters/statements_formatter.rb +272 -0
- data/lib/expressir/express/formatters/supertype_expressions_formatter.rb +54 -0
- data/lib/expressir/express/formatters.rb +22 -0
- data/lib/expressir/express/grammar/parser.rb +712 -0
- data/lib/expressir/express/grammar.rb +11 -0
- data/lib/expressir/express/hyperlink_formatter.rb +35 -0
- data/lib/expressir/express/interface_dot.rb +105 -0
- data/lib/expressir/express/lazy_repository.rb +211 -0
- data/lib/expressir/express/line_map.rb +48 -0
- data/lib/expressir/express/listing.rb +174 -0
- data/lib/expressir/express/model_traversal.rb +42 -0
- data/lib/expressir/express/model_visitor.rb +25 -0
- data/lib/expressir/express/node_position_index.rb +342 -0
- data/lib/expressir/express/parallel_files.rb +229 -0
- data/lib/expressir/express/parser.rb +523 -0
- data/lib/expressir/express/pretty_formatter.rb +586 -0
- data/lib/expressir/express/pretty_gate.rb +61 -0
- data/lib/expressir/express/refs_overlay.rb +47 -0
- data/lib/expressir/express/remark_attacher.rb +1098 -0
- data/lib/expressir/express/remark_overlay.rb +86 -0
- data/lib/expressir/express/remark_scanner.rb +245 -0
- data/lib/expressir/express/resolve_references_model_visitor.rb +29 -0
- data/lib/expressir/express/schema_block_scanner.rb +137 -0
- data/lib/expressir/express/schema_head_formatter.rb +22 -0
- data/lib/expressir/express/schema_plain_source_formatter.rb +11 -0
- data/lib/expressir/express/schema_source_formatter.rb +15 -0
- data/lib/expressir/express/scope_resolver.rb +223 -0
- data/lib/expressir/express/self_schema_reference.rb +126 -0
- data/lib/expressir/express/shtolo.rb +679 -0
- data/lib/expressir/express/smrl_xml.rb +125 -0
- data/lib/expressir/express/source_formatter.rb +15 -0
- data/lib/expressir/express/streaming_builder.rb +435 -0
- data/lib/expressir/express/xsd.rb +259 -0
- data/lib/expressir/express.rb +53 -0
- data/lib/expressir/liquid.rb +1 -0
- data/lib/expressir/manifest/resolver.rb +210 -0
- data/lib/expressir/manifest/validator.rb +192 -0
- data/lib/expressir/manifest.rb +6 -0
- data/lib/expressir/mapping/refpath.rb +857 -0
- data/lib/expressir/mapping.rb +253 -0
- data/lib/expressir/model/cache.rb +18 -0
- data/lib/expressir/model/concerns.rb +42 -0
- data/lib/expressir/model/data_types/aggregate.rb +26 -0
- data/lib/expressir/model/data_types/array.rb +25 -0
- data/lib/expressir/model/data_types/bag.rb +21 -0
- data/lib/expressir/model/data_types/binary.rb +19 -0
- data/lib/expressir/model/data_types/boolean.rb +15 -0
- data/lib/expressir/model/data_types/enumeration.rb +21 -0
- data/lib/expressir/model/data_types/enumeration_item.rb +24 -0
- data/lib/expressir/model/data_types/generic.rb +24 -0
- data/lib/expressir/model/data_types/generic_entity.rb +24 -0
- data/lib/expressir/model/data_types/integer.rb +15 -0
- data/lib/expressir/model/data_types/list.rb +23 -0
- data/lib/expressir/model/data_types/logical.rb +15 -0
- data/lib/expressir/model/data_types/number.rb +15 -0
- data/lib/expressir/model/data_types/real.rb +17 -0
- data/lib/expressir/model/data_types/select.rb +23 -0
- data/lib/expressir/model/data_types/set.rb +21 -0
- data/lib/expressir/model/data_types/string.rb +19 -0
- data/lib/expressir/model/data_types.rb +25 -0
- data/lib/expressir/model/declarations/attribute.rb +38 -0
- data/lib/expressir/model/declarations/constant.rb +28 -0
- data/lib/expressir/model/declarations/derived_attribute.rb +25 -0
- data/lib/expressir/model/declarations/entity.rb +62 -0
- data/lib/expressir/model/declarations/function.rb +59 -0
- data/lib/expressir/model/declarations/informal_proposition_rule.rb +25 -0
- data/lib/expressir/model/declarations/interface.rb +37 -0
- data/lib/expressir/model/declarations/interface_item.rb +21 -0
- data/lib/expressir/model/declarations/interfaced_item.rb +33 -0
- data/lib/expressir/model/declarations/inverse_attribute.rb +25 -0
- data/lib/expressir/model/declarations/parameter.rb +28 -0
- data/lib/expressir/model/declarations/procedure.rb +57 -0
- data/lib/expressir/model/declarations/remark_item.rb +21 -0
- data/lib/expressir/model/declarations/rule.rb +66 -0
- data/lib/expressir/model/declarations/schema.rb +215 -0
- data/lib/expressir/model/declarations/schema_version.rb +19 -0
- data/lib/expressir/model/declarations/schema_version_item.rb +19 -0
- data/lib/expressir/model/declarations/subtype_constraint.rb +32 -0
- data/lib/expressir/model/declarations/type.rb +45 -0
- data/lib/expressir/model/declarations/unique_rule.rb +26 -0
- data/lib/expressir/model/declarations/variable.rb +28 -0
- data/lib/expressir/model/declarations/where_rule.rb +26 -0
- data/lib/expressir/model/declarations.rb +31 -0
- data/lib/expressir/model/dependency_resolver.rb +268 -0
- data/lib/expressir/model/exp_file.rb +42 -0
- data/lib/expressir/model/expressions/aggregate_initializer.rb +18 -0
- data/lib/expressir/model/expressions/aggregate_initializer_item.rb +20 -0
- data/lib/expressir/model/expressions/binary_expression.rb +59 -0
- data/lib/expressir/model/expressions/entity_constructor.rb +20 -0
- data/lib/expressir/model/expressions/function_call.rb +20 -0
- data/lib/expressir/model/expressions/interval.rb +29 -0
- data/lib/expressir/model/expressions/query_expression.rb +31 -0
- data/lib/expressir/model/expressions/unary_expression.rb +25 -0
- data/lib/expressir/model/expressions.rb +18 -0
- data/lib/expressir/model/identifier.rb +26 -0
- data/lib/expressir/model/indexes/entity_index.rb +103 -0
- data/lib/expressir/model/indexes/item_graph.rb +185 -0
- data/lib/expressir/model/indexes/reference_index.rb +148 -0
- data/lib/expressir/model/indexes/type_index.rb +149 -0
- data/lib/expressir/model/indexes.rb +12 -0
- data/lib/expressir/model/interface_validator.rb +384 -0
- data/lib/expressir/model/literals/binary.rb +17 -0
- data/lib/expressir/model/literals/integer.rb +17 -0
- data/lib/expressir/model/literals/logical.rb +21 -0
- data/lib/expressir/model/literals/real.rb +17 -0
- data/lib/expressir/model/literals/string.rb +20 -0
- data/lib/expressir/model/literals.rb +13 -0
- data/lib/expressir/model/model_element.rb +377 -0
- data/lib/expressir/model/references/attribute_reference.rb +19 -0
- data/lib/expressir/model/references/group_reference.rb +19 -0
- data/lib/expressir/model/references/index_reference.rb +23 -0
- data/lib/expressir/model/references/simple_reference.rb +21 -0
- data/lib/expressir/model/references.rb +12 -0
- data/lib/expressir/model/remark_format.rb +17 -0
- data/lib/expressir/model/remark_info.rb +92 -0
- data/lib/expressir/model/remark_placement.rb +42 -0
- data/lib/expressir/model/repository.rb +483 -0
- data/lib/expressir/model/repository_validator.rb +293 -0
- data/lib/expressir/model/search_engine.rb +551 -0
- data/lib/expressir/model/statements/alias.rb +31 -0
- data/lib/expressir/model/statements/assignment.rb +23 -0
- data/lib/expressir/model/statements/case.rb +42 -0
- data/lib/expressir/model/statements/case_action.rb +20 -0
- data/lib/expressir/model/statements/compound.rb +21 -0
- data/lib/expressir/model/statements/escape.rb +18 -0
- data/lib/expressir/model/statements/if.rb +26 -0
- data/lib/expressir/model/statements/null.rb +18 -0
- data/lib/expressir/model/statements/procedure_call.rb +22 -0
- data/lib/expressir/model/statements/repeat.rb +40 -0
- data/lib/expressir/model/statements/return.rb +20 -0
- data/lib/expressir/model/statements/skip.rb +18 -0
- data/lib/expressir/model/statements.rb +20 -0
- data/lib/expressir/model/supertype_expressions/binary_supertype_expression.rb +25 -0
- data/lib/expressir/model/supertype_expressions/oneof_supertype_expression.rb +17 -0
- data/lib/expressir/model/supertype_expressions.rb +12 -0
- data/lib/expressir/model.rb +39 -0
- data/lib/expressir/package/builder.rb +231 -0
- data/lib/expressir/package/metadata.rb +79 -0
- data/lib/expressir/package/reader.rb +149 -0
- data/lib/expressir/package.rb +8 -0
- data/lib/expressir/schema_manifest.rb +159 -0
- data/lib/expressir/schema_manifest_entry.rb +15 -0
- data/lib/expressir/version.rb +8 -0
- data/lib/expressir.rb +94 -0
- data/lib/tasks/verify_remarks.rake +16 -0
- data/rakelib/native.rake +24 -0
- data/rakelib/oracle.rake +52 -0
- data/rakelib/verify_remarks.rake +16 -0
- metadata +692 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Expressir
|
|
4
|
+
module Express
|
|
5
|
+
# SMRL index XML writer — the shape eengine's wo-smrl-xml.lisp
|
|
6
|
+
# produces (the data layer of the STEP Module Resource Library
|
|
7
|
+
# document set, expressir #276 / TODO.parity-ee 15), built with
|
|
8
|
+
# moxml's node API — no hand-serialized XML strings.
|
|
9
|
+
#
|
|
10
|
+
# Per schema: downcased <schema> id, <schema_version> when
|
|
11
|
+
# present, per-kind count comments, <use_from> per interface
|
|
12
|
+
# (item-list marker), sorted <constant> names, then declarations
|
|
13
|
+
# in eeng's kind order (types, entities, subtype_constraints,
|
|
14
|
+
# functions, rules, procedures), alphabetical inside each kind,
|
|
15
|
+
# schema-qualified names; ARM mode upcases entity names.
|
|
16
|
+
#
|
|
17
|
+
# format — one document with an <smrl> root, one <schema>
|
|
18
|
+
# element per repository schema.
|
|
19
|
+
# format_schema — a standalone document whose root is the schema
|
|
20
|
+
# element (the per-file fragment eeng emits).
|
|
21
|
+
module SmrlXml
|
|
22
|
+
module_function
|
|
23
|
+
|
|
24
|
+
def format(repository, mode: :resource)
|
|
25
|
+
schemas = repository.respond_to?(:schemas) ? repository.schemas : Array(repository)
|
|
26
|
+
ctx = Moxml::Context.new
|
|
27
|
+
doc = ctx.create_document
|
|
28
|
+
root = doc.create_element("smrl")
|
|
29
|
+
doc.add_child(root)
|
|
30
|
+
schemas.each { |schema| root.add_child(schema_element(doc, schema, mode)) }
|
|
31
|
+
doc.to_xml
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def format_schema(schema, mode: :resource)
|
|
35
|
+
ctx = Moxml::Context.new
|
|
36
|
+
doc = ctx.create_document
|
|
37
|
+
doc.add_child(schema_element(doc, schema, mode))
|
|
38
|
+
doc.to_xml
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def schema_element(doc, schema, mode)
|
|
42
|
+
element = doc.create_element("schema")
|
|
43
|
+
element.add_child(doc.create_text(schema.id.downcase))
|
|
44
|
+
if schema.version&.value
|
|
45
|
+
version = doc.create_element("schema_version")
|
|
46
|
+
version.add_child(doc.create_text(schema.version.value))
|
|
47
|
+
element.add_child(version)
|
|
48
|
+
end
|
|
49
|
+
counts = declaration_counts(schema)
|
|
50
|
+
%i[type entity function procedure rule subtype_constraint].each do |kind|
|
|
51
|
+
label = kind.to_s.split("_").map(&:upcase).join("_")
|
|
52
|
+
element.add_child(doc.create_comment(Kernel.format("%-19s %4d",
|
|
53
|
+
label, counts[kind])))
|
|
54
|
+
end
|
|
55
|
+
interfaces(schema).each do |iface|
|
|
56
|
+
items = iface.items.to_a.empty? ? "" : "(...)"
|
|
57
|
+
add_text_element(doc, element, "use-from",
|
|
58
|
+
"#{iface.schema.id.downcase}#{items}")
|
|
59
|
+
end
|
|
60
|
+
constants(schema).each do |decl|
|
|
61
|
+
add_text_element(doc, element, "constant", decl.id.downcase)
|
|
62
|
+
end
|
|
63
|
+
declarations(schema).each do |kind, decls|
|
|
64
|
+
tag = kind.to_s.tr("_", "-")
|
|
65
|
+
decls.each do |decl|
|
|
66
|
+
add_text_element(doc, element, tag,
|
|
67
|
+
"#{schema.id}.#{name_for(kind, decl.id, mode)}")
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
element
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def add_text_element(doc, parent, tag, text)
|
|
74
|
+
node = doc.create_element(tag)
|
|
75
|
+
node.add_child(doc.create_text(text))
|
|
76
|
+
parent.add_child(node)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# eeng's entity casing: ARM mode upcases entity names; every
|
|
80
|
+
# other kind and mode is downcased.
|
|
81
|
+
def name_for(kind, id, mode)
|
|
82
|
+
kind == :entity && mode == :arm ? id.upcase : id.downcase
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def declaration_counts(schema)
|
|
86
|
+
{
|
|
87
|
+
type: schema.types.to_a.size,
|
|
88
|
+
entity: schema.entities.to_a.size,
|
|
89
|
+
function: schema.functions.to_a.size,
|
|
90
|
+
procedure: schema.procedures.to_a.size,
|
|
91
|
+
rule: schema.rules.to_a.size,
|
|
92
|
+
subtype_constraint: schema.subtype_constraints.to_a.size,
|
|
93
|
+
}
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def interfaces(schema)
|
|
97
|
+
Array(schema.interfaces)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def constants(schema)
|
|
101
|
+
schema.constants.to_a.sort_by(&:id)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# eeng order: types, entities, subtype_constraints, functions,
|
|
105
|
+
# rules, procedures — alphabetical (byte order) inside each.
|
|
106
|
+
COLL_BY_KIND = {
|
|
107
|
+
types: :type,
|
|
108
|
+
entities: :entity,
|
|
109
|
+
subtype_constraints: :subtype_constraint,
|
|
110
|
+
functions: :function,
|
|
111
|
+
rules: :rule,
|
|
112
|
+
procedures: :procedure,
|
|
113
|
+
}.freeze
|
|
114
|
+
|
|
115
|
+
def declarations(schema)
|
|
116
|
+
COLL_BY_KIND.filter_map do |coll, kind|
|
|
117
|
+
decls = schema.public_send(coll).to_a.sort_by(&:id)
|
|
118
|
+
next if decls.empty?
|
|
119
|
+
|
|
120
|
+
[kind, decls]
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Expressir
|
|
4
|
+
module Express
|
|
5
|
+
# Pre-built Formatter subclass that mixes in HyperlinkFormatter.
|
|
6
|
+
#
|
|
7
|
+
# Used by ModelElement#source to format an element back into EXPRESS
|
|
8
|
+
# source text with hyperlinks. Allocated once at load time rather than
|
|
9
|
+
# per #source call (which was the previous behaviour — wasteful and
|
|
10
|
+
# rebuilt the format_registry on every call).
|
|
11
|
+
class SourceFormatter < Formatter
|
|
12
|
+
include HyperlinkFormatter
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Expressir
|
|
4
|
+
module Express
|
|
5
|
+
# Streaming builder that receives parse events from Parsanol native parser.
|
|
6
|
+
#
|
|
7
|
+
# This builder implements the Parsanol::BuilderCallbacks interface and
|
|
8
|
+
# reconstructs the AST from streaming events, then uses the existing
|
|
9
|
+
# Builder to convert to Model objects.
|
|
10
|
+
#
|
|
11
|
+
# The key insight is that when a value starts (HASH_START, ARRAY_START),
|
|
12
|
+
# we must FIRST add it to the parent with the pending key, THEN push it
|
|
13
|
+
# to the stack so nested values are added to the correct container.
|
|
14
|
+
#
|
|
15
|
+
class StreamingBuilder
|
|
16
|
+
# Include Parsanol callbacks if available
|
|
17
|
+
if defined?(Parsanol::BuilderCallbacks)
|
|
18
|
+
include Parsanol::BuilderCallbacks
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# @return [String, nil] Original source code for position tracking
|
|
22
|
+
attr_accessor :source
|
|
23
|
+
|
|
24
|
+
# @return [Boolean] Whether to include source in model elements
|
|
25
|
+
attr_reader :include_source
|
|
26
|
+
|
|
27
|
+
# Initialize the streaming builder
|
|
28
|
+
#
|
|
29
|
+
# @param source [String, nil] Original source code
|
|
30
|
+
# @param include_source [Boolean] Whether to include source in model elements
|
|
31
|
+
def initialize(source: nil, include_source: nil)
|
|
32
|
+
@source = source
|
|
33
|
+
@include_source = include_source
|
|
34
|
+
@stack = [] # Stack of containers (Hash or Array)
|
|
35
|
+
@pending_key = nil
|
|
36
|
+
@final_ast = nil
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Called when parsing starts
|
|
40
|
+
#
|
|
41
|
+
# @param input [String] The input being parsed
|
|
42
|
+
def on_start(input)
|
|
43
|
+
@on_start ||= input
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Called when parsing succeeds
|
|
47
|
+
def on_success
|
|
48
|
+
# Parsing completed
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Called when parsing fails
|
|
52
|
+
#
|
|
53
|
+
# @param message [String] The error message
|
|
54
|
+
def on_error(message)
|
|
55
|
+
raise Error::SchemaParseFailure.new("(streaming)", message)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Called when a string value is matched
|
|
59
|
+
#
|
|
60
|
+
# @param value [String] The matched string value
|
|
61
|
+
# @param offset [Integer] Byte offset
|
|
62
|
+
# @param length [Integer] Length
|
|
63
|
+
def on_string(value, _offset, _length)
|
|
64
|
+
add_value_to_current_container(value)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Called when an integer value is matched
|
|
68
|
+
#
|
|
69
|
+
# @param value [Integer] The matched integer value
|
|
70
|
+
def on_int(value)
|
|
71
|
+
add_value_to_current_container(value)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Called when a float value is matched
|
|
75
|
+
#
|
|
76
|
+
# @param value [Float] The matched float value
|
|
77
|
+
def on_float(value)
|
|
78
|
+
add_value_to_current_container(value)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Called when a boolean value is matched
|
|
82
|
+
#
|
|
83
|
+
# @param value [Boolean] The matched boolean value
|
|
84
|
+
def on_bool(value)
|
|
85
|
+
add_value_to_current_container(value)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Called when a nil/null value is matched
|
|
89
|
+
def on_nil
|
|
90
|
+
add_value_to_current_container(nil)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Called when starting to parse a hash/object
|
|
94
|
+
#
|
|
95
|
+
# @param size [Integer, nil] Expected number of entries
|
|
96
|
+
def on_hash_start(_size = nil)
|
|
97
|
+
new_hash = {}
|
|
98
|
+
|
|
99
|
+
# First add this hash to the parent (if any) with the pending key
|
|
100
|
+
if @stack.any?
|
|
101
|
+
add_value_to_current_container(new_hash)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Then push to stack so nested values go into this hash
|
|
105
|
+
@stack.push(new_hash)
|
|
106
|
+
# Clear pending key - we're starting a new hash context
|
|
107
|
+
@pending_key = nil
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Called when a hash key is encountered
|
|
111
|
+
#
|
|
112
|
+
# @param key [String] The hash key name
|
|
113
|
+
def on_hash_key(key)
|
|
114
|
+
# Convert string key to symbol to match existing parser AST format
|
|
115
|
+
@pending_key = key.to_sym
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Called when a hash value is about to be parsed
|
|
119
|
+
#
|
|
120
|
+
# @param key [String] The hash key name
|
|
121
|
+
def on_hash_value(_key)
|
|
122
|
+
@pending_key = nil
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Called when finishing parsing a hash/object
|
|
126
|
+
#
|
|
127
|
+
# @param size [Integer] Actual number of entries
|
|
128
|
+
def on_hash_end(_size)
|
|
129
|
+
return if @stack.empty?
|
|
130
|
+
|
|
131
|
+
finished_hash = @stack.pop
|
|
132
|
+
|
|
133
|
+
if @stack.empty?
|
|
134
|
+
# This is the top-level hash, save it as final AST
|
|
135
|
+
@final_ast = finished_hash
|
|
136
|
+
end
|
|
137
|
+
# If there's a parent, the hash was already added in on_hash_start
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Called when starting to parse an array
|
|
141
|
+
#
|
|
142
|
+
# @param size [Integer, nil] Expected number of elements
|
|
143
|
+
def on_array_start(_size = nil)
|
|
144
|
+
new_array = []
|
|
145
|
+
|
|
146
|
+
# First add this array to the parent (if any) with the pending key
|
|
147
|
+
if @stack.any?
|
|
148
|
+
add_value_to_current_container(new_array)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Then push to stack
|
|
152
|
+
@stack.push(new_array)
|
|
153
|
+
# Clear pending key - we're starting a new array context
|
|
154
|
+
@pending_key = nil
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Called when an array element is about to be parsed
|
|
158
|
+
#
|
|
159
|
+
# @param index [Integer] The index of the element
|
|
160
|
+
def on_array_element(index)
|
|
161
|
+
# Element processed - no action needed
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Called when finishing parsing an array
|
|
165
|
+
#
|
|
166
|
+
# @param size [Integer] Actual number of elements
|
|
167
|
+
def on_array_end(_size)
|
|
168
|
+
return if @stack.empty?
|
|
169
|
+
|
|
170
|
+
finished_array = @stack.pop
|
|
171
|
+
|
|
172
|
+
if @stack.empty?
|
|
173
|
+
# Top-level array, save as final AST
|
|
174
|
+
@final_ast = finished_array
|
|
175
|
+
end
|
|
176
|
+
# If there's a parent, the array was already added in on_array_start
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# Called when starting to parse a named rule
|
|
180
|
+
#
|
|
181
|
+
# @param name [String] The rule name
|
|
182
|
+
def on_named_start(name)
|
|
183
|
+
# Named captures are handled via hash wrapping - no action needed
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Called when finishing parsing a named rule
|
|
187
|
+
#
|
|
188
|
+
# @param name [String] The rule name
|
|
189
|
+
def on_named_end(name)
|
|
190
|
+
# Named captures are handled via hash wrapping - no action needed
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Called when parsing is complete. Returns the built Repository.
|
|
194
|
+
#
|
|
195
|
+
# @return [Model::Repository, nil] The final result
|
|
196
|
+
def finish
|
|
197
|
+
return nil unless @final_ast
|
|
198
|
+
|
|
199
|
+
# Convert Parsanol native AST format to Builder-compatible format
|
|
200
|
+
# Parsanol native: {"key" => [{:a => ...}, {:b => ...}]} (Array of single-key hashes)
|
|
201
|
+
# Builder: {:key => {:a => ..., :b => ...}} (Hash with multiple keys)
|
|
202
|
+
converted_ast = convert_ast_format(@final_ast)
|
|
203
|
+
|
|
204
|
+
# Pass to the existing Builder
|
|
205
|
+
Builder.build_with_remarks(converted_ast, source: @source,
|
|
206
|
+
include_source: @include_source)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
private
|
|
210
|
+
|
|
211
|
+
# Process a hash, concatenating :str and :spaces arrays
|
|
212
|
+
# This is called after merging single-key hashes
|
|
213
|
+
def process_str_and_spaces(hash)
|
|
214
|
+
result = {}
|
|
215
|
+
hash.each do |key, value|
|
|
216
|
+
result[key] = if %i[str spaces].include?(key) && value.is_a?(Array)
|
|
217
|
+
value.compact.join
|
|
218
|
+
else
|
|
219
|
+
value
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
result
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# Convert Parsanol native AST format to Builder-compatible format
|
|
226
|
+
#
|
|
227
|
+
# Parsanol native represents:
|
|
228
|
+
# - Sequences as arrays of single-key hashes: [{:a => 1}, {:b => 2}, []]
|
|
229
|
+
# - Strings as arrays of characters: {:str => ["a", "b", "c", nil]}
|
|
230
|
+
# - Spaces as arrays of whitespace: {:spaces => [" ", "\\n"]}
|
|
231
|
+
#
|
|
232
|
+
# Builder expects:
|
|
233
|
+
# - Sequences as hashes with multiple keys: {:a => 1, :b => 2}
|
|
234
|
+
# - Strings as concatenated strings: {:str => "abc"}
|
|
235
|
+
# - Spaces as concatenated strings: {:spaces => " "}
|
|
236
|
+
#
|
|
237
|
+
# @param obj [Object] The AST node to convert
|
|
238
|
+
# @return [Object] The converted AST
|
|
239
|
+
def convert_ast_format(obj)
|
|
240
|
+
case obj
|
|
241
|
+
when Hash
|
|
242
|
+
convert_hash_node(obj)
|
|
243
|
+
when Array
|
|
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
|
|
290
|
+
end
|
|
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
|
|
307
|
+
|
|
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)
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
result
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
def expand_single_array_key(item, key, result)
|
|
359
|
+
values = item[key]
|
|
360
|
+
other_keys = item.keys - [key]
|
|
361
|
+
|
|
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
|
|
368
|
+
|
|
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
|
|
372
|
+
|
|
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]
|
|
394
|
+
end
|
|
395
|
+
else
|
|
396
|
+
merged[key] = value
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
end
|
|
400
|
+
process_str_and_spaces(merged)
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
# Add a value to the current container on top of the stack
|
|
404
|
+
#
|
|
405
|
+
# @param value The value to add
|
|
406
|
+
def add_value_to_current_container(value)
|
|
407
|
+
return if @stack.empty?
|
|
408
|
+
|
|
409
|
+
container = @stack.last
|
|
410
|
+
|
|
411
|
+
if container.is_a?(Hash)
|
|
412
|
+
if @pending_key
|
|
413
|
+
container[@pending_key] = value
|
|
414
|
+
end
|
|
415
|
+
elsif container.is_a?(Array)
|
|
416
|
+
container << value
|
|
417
|
+
else
|
|
418
|
+
# This handles unexpected container types (debugging)
|
|
419
|
+
if ENV["DEBUG_STREAMING"]
|
|
420
|
+
puts " Container value: #{container.inspect[0..200]}"
|
|
421
|
+
puts " Pending key: #{@pending_key.inspect}"
|
|
422
|
+
puts " Stack depth: #{@stack.length}"
|
|
423
|
+
puts " Stack: #{@stack.map(&:class).inspect}"
|
|
424
|
+
end
|
|
425
|
+
raise "Unexpected container type: #{container.class}"
|
|
426
|
+
end
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
# Get the final AST (for debugging)
|
|
430
|
+
def final_ast
|
|
431
|
+
@final_ast
|
|
432
|
+
end
|
|
433
|
+
end
|
|
434
|
+
end
|
|
435
|
+
end
|