ibex 0.2.0 → 0.3.0
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/README.md +95 -272
- data/docs/architecture.md +187 -35
- data/docs/bison-import.md +103 -0
- data/docs/comparison-policy.md +127 -0
- data/docs/configuration-model.md +59 -0
- data/docs/configuration-report.md +28 -0
- data/docs/conflict-explanation-reviews/v1/records/README.md +28 -0
- data/docs/conflict-explanation-study.md +62 -0
- data/docs/construction-profiling.md +157 -0
- data/docs/cst-migration.md +3 -4
- data/docs/cst.md +24 -0
- data/docs/decisions/0000-template.md +24 -0
- data/docs/decisions/0001-separate-ir-pipeline.md +34 -0
- data/docs/decisions/0002-opaque-user-code-boundary.md +32 -0
- data/docs/decisions/0003-self-hosted-grammar-frontend.md +32 -0
- data/docs/decisions/0004-shared-semantic-and-lossless-source-model.md +33 -0
- data/docs/decisions/0005-contained-grammar-composition.md +34 -0
- data/docs/decisions/0006-bounded-structural-grammar-lowering.md +32 -0
- data/docs/decisions/0007-shared-parser-construction-pipeline.md +33 -0
- data/docs/decisions/0008-versioned-runtime-package-boundary.md +36 -0
- data/docs/decisions/0009-isolated-parser-sessions.md +34 -0
- data/docs/decisions/0010-committed-runtime-observation.md +34 -0
- data/docs/decisions/0011-versioned-semantic-action-boundary.md +37 -0
- data/docs/decisions/0012-bounded-nonexecuting-analysis.md +37 -0
- data/docs/decisions/0013-transactional-generation-publication.md +37 -0
- data/docs/decisions/0014-versioned-generated-lexer.md +35 -0
- data/docs/decisions/0015-worker-isolated-browser-analysis.md +32 -0
- data/docs/decisions/0016-red-green-concrete-syntax.md +34 -0
- data/docs/decisions/0017-persistent-syntax-artifacts.md +35 -0
- data/docs/decisions/0018-conservative-incremental-syntax-reuse.md +38 -0
- data/docs/decisions/0019-runtime-syntax-session-boundary.md +51 -0
- data/docs/decisions/0020-grammar-ir-parser-contract.md +65 -0
- data/docs/decisions/0021-data-only-parser-table-sidecar.md +50 -0
- data/docs/decisions/0022-manifest-bound-verification-report.md +77 -0
- data/docs/decisions/0023-syntax-only-repair-results.md +48 -0
- data/docs/decisions/0024-direct-ielr-construction.md +42 -0
- data/docs/decisions/README.md +74 -0
- data/docs/declarative-configuration.md +262 -0
- data/docs/development.md +179 -2
- data/docs/direct-ielr-decision.md +120 -0
- data/docs/direct-multi-entry-decision.md +82 -0
- data/docs/editor-setup.md +2 -1
- data/docs/error-ux-review-rubric-v1.md +117 -0
- data/docs/error-ux-reviews/v1/records/README.md +22 -0
- data/docs/error-ux-round2-review-status-v1.json +27 -0
- data/docs/error-ux-round2-reviews/v1/records/README.md +30 -0
- data/docs/error-ux-round2-v1.json +1581 -0
- data/docs/error-ux-round2.md +111 -0
- data/docs/error-ux.md +54 -0
- data/docs/getting-started.md +80 -0
- data/docs/grammar-reference.md +184 -13
- data/docs/ielr-design.md +43 -0
- data/docs/ielr.md +92 -0
- data/docs/ja/bison-import.md +51 -0
- data/docs/ja/stable-api.md +53 -0
- data/docs/lexer-construction-profile.md +109 -0
- data/docs/lexer-migration.md +5 -0
- data/docs/maturity.md +128 -0
- data/docs/project-site-strategy.md +54 -0
- data/docs/racc-migration-evidence.md +45 -0
- data/docs/racc-migration.md +11 -0
- data/docs/release-readiness.md +126 -68
- data/docs/repair-semantics.md +123 -0
- data/docs/runtime-abi-evolution.md +307 -0
- data/docs/stability.md +144 -34
- data/docs/status.md +43 -0
- data/docs/syntax-sessions.md +183 -0
- data/docs/table-artifact.md +125 -0
- data/docs/test-interactions.md +219 -0
- data/docs/verification-report.md +137 -0
- data/docs/verifier-trust-boundary.md +199 -0
- data/docs/workloads.md +132 -0
- data/lib/ibex/analysis/digraph.rb +128 -0
- data/lib/ibex/analysis.rb +1 -0
- data/lib/ibex/bison_import/importer.rb +516 -0
- data/lib/ibex/bison_import/tokenizer.rb +260 -0
- data/lib/ibex/bison_import.rb +200 -0
- data/lib/ibex/bounded_subprocess.rb +171 -0
- data/lib/ibex/cli/ambiguity.rb +14 -5
- data/lib/ibex/cli/analysis.rb +134 -0
- data/lib/ibex/cli/bison_import.rb +121 -0
- data/lib/ibex/cli/config.rb +128 -0
- data/lib/ibex/cli/diagnostics.rb +31 -11
- data/lib/ibex/cli/documentation.rb +11 -8
- data/lib/ibex/cli/equiv.rb +169 -0
- data/lib/ibex/cli/error_messages.rb +11 -4
- data/lib/ibex/cli/explain.rb +14 -5
- data/lib/ibex/cli/fix.rb +203 -0
- data/lib/ibex/cli/formatting.rb +11 -10
- data/lib/ibex/cli/fuzz.rb +200 -0
- data/lib/ibex/cli/fuzz_regressions.rb +145 -0
- data/lib/ibex/cli/generation_artifacts.rb +53 -2
- data/lib/ibex/cli/generation_error_messages.rb +1 -1
- data/lib/ibex/cli/grammar_tests.rb +32 -14
- data/lib/ibex/cli/ir_tools.rb +5 -61
- data/lib/ibex/cli/outputs.rb +60 -33
- data/lib/ibex/cli/reduce.rb +202 -0
- data/lib/ibex/cli/reduce_reporting.rb +71 -0
- data/lib/ibex/cli/samples.rb +49 -23
- data/lib/ibex/cli/verify.rb +116 -0
- data/lib/ibex/cli/watch.rb +6 -5
- data/lib/ibex/cli.rb +357 -56
- data/lib/ibex/codegen/action_locations.rb +1 -1
- data/lib/ibex/codegen/action_method_source.rb +5 -6
- data/lib/ibex/codegen/action_source.rb +3 -2
- data/lib/ibex/codegen/ambiguity.rb +5 -4
- data/lib/ibex/codegen/explain.rb +123 -55
- data/lib/ibex/codegen/generated_action_abi.rb +10 -5
- data/lib/ibex/codegen/rbs.rb +15 -7
- data/lib/ibex/codegen/report.rb +25 -13
- data/lib/ibex/codegen/ruby.rb +28 -64
- data/lib/ibex/codegen/ruby_actions.rb +9 -6
- data/lib/ibex/codegen/ruby_syntax.rb +15 -9
- data/lib/ibex/configuration/analysis_grammar.rb +35 -0
- data/lib/ibex/configuration/explanation.rb +421 -0
- data/lib/ibex/configuration/inspector.rb +232 -0
- data/lib/ibex/configuration.rb +580 -0
- data/lib/ibex/coverage/collector.rb +21 -11
- data/lib/ibex/coverage/event_stream.rb +13 -7
- data/lib/ibex/coverage/report.rb +26 -18
- data/lib/ibex/coverage/runtime_event_validator.rb +30 -21
- data/lib/ibex/delta_reducer.rb +99 -0
- data/lib/ibex/diff.rb +140 -0
- data/lib/ibex/equiv/machine.rb +135 -0
- data/lib/ibex/equiv.rb +373 -0
- data/lib/ibex/fix.rb +557 -0
- data/lib/ibex/frontend/ast.rb +22 -2
- data/lib/ibex/frontend/bootstrap_parser.rb +6 -13
- data/lib/ibex/frontend/diagnostic.rb +1 -1
- data/lib/ibex/frontend/formatter.rb +72 -26
- data/lib/ibex/frontend/generated_parser.rb +147 -117
- data/lib/ibex/frontend/generated_parser_base.rb +7 -3
- data/lib/ibex/frontend/generated_parser_includes.rb +1 -11
- data/lib/ibex/frontend/generation.rb +1 -1
- data/lib/ibex/frontend/parser/declarations.rb +17 -2
- data/lib/ibex/frontend/parser_configuration_support.rb +56 -0
- data/lib/ibex/frontend/regenerator.rb +1 -0
- data/lib/ibex/frontend/resolution.rb +2 -1
- data/lib/ibex/frontend/resolver.rb +1 -1
- data/lib/ibex/frontend/rule_documentation.rb +2 -1
- data/lib/ibex/frontend/source_cursor.rb +2 -2
- data/lib/ibex/frontend/source_span.rb +9 -1
- data/lib/ibex/frontend/token_adapter/declaration_state.rb +38 -6
- data/lib/ibex/frontend/token_adapter.rb +10 -0
- data/lib/ibex/frontend.rb +1 -0
- data/lib/ibex/fuzz.rb +219 -0
- data/lib/ibex/generation_input.rb +1 -1
- data/lib/ibex/generation_manifest.rb +36 -25
- data/lib/ibex/generation_transaction.rb +1 -1
- data/lib/ibex/generation_transaction_recovery.rb +4 -4
- data/lib/ibex/generation_transaction_validation.rb +2 -2
- data/lib/ibex/grammar_tests.rb +1 -1
- data/lib/ibex/ir/automaton_ir.rb +61 -19
- data/lib/ibex/ir/grammar_ir.rb +76 -45
- data/lib/ibex/ir/lexer_ir.rb +5 -5
- data/lib/ibex/ir/parser_contract.rb +135 -0
- data/lib/ibex/ir/serialize.rb +203 -76
- data/lib/ibex/ir/validator/automaton.rb +64 -34
- data/lib/ibex/ir/validator/base.rb +51 -33
- data/lib/ibex/ir/validator/grammar.rb +113 -83
- data/lib/ibex/ir/validator/lexer.rb +2 -2
- data/lib/ibex/ir/validator.rb +2 -1
- data/lib/ibex/ir.rb +16 -3
- data/lib/ibex/lalr/build_metrics.rb +50 -2
- data/lib/ibex/lalr/builder.rb +191 -56
- data/lib/ibex/lalr/conflict_search.rb +15 -4
- data/lib/ibex/lalr/counterexample.rb +19 -14
- data/lib/ibex/lalr/direct_lookaheads.rb +110 -57
- data/lib/ibex/lalr/goto_follows.rb +229 -0
- data/lib/ibex/lalr/ielr/annotator.rb +214 -0
- data/lib/ibex/lalr/ielr/bits.rb +28 -0
- data/lib/ibex/lalr/ielr/inadequacy.rb +47 -0
- data/lib/ibex/lalr/ielr/item_lookaheads.rb +78 -0
- data/lib/ibex/lalr/ielr/pipeline.rb +75 -0
- data/lib/ibex/lalr/ielr/split_stability.rb +78 -0
- data/lib/ibex/lalr/ielr/split_state.rb +20 -0
- data/lib/ibex/lalr/ielr/state_splitter.rb +258 -0
- data/lib/ibex/lalr/ielr_partition.rb +22 -8
- data/lib/ibex/lalr/inadequacy_report.rb +50 -0
- data/lib/ibex/lalr/lookahead_propagation.rb +111 -0
- data/lib/ibex/lalr/lr0_collection.rb +121 -0
- data/lib/ibex/lalr/unreachable_states.rb +80 -0
- data/lib/ibex/lalr.rb +52 -1
- data/lib/ibex/location.rb +3 -3
- data/lib/ibex/lsp/document_handlers.rb +9 -7
- data/lib/ibex/lsp/initialization_handlers.rb +9 -7
- data/lib/ibex/lsp/navigation_handlers.rb +25 -11
- data/lib/ibex/lsp/parser_configuration_assistance.rb +149 -0
- data/lib/ibex/lsp/position_codec.rb +6 -2
- data/lib/ibex/lsp/request_handlers.rb +3 -2
- data/lib/ibex/lsp/request_support.rb +14 -7
- data/lib/ibex/lsp/server.rb +13 -11
- data/lib/ibex/lsp/symbol_index.rb +13 -13
- data/lib/ibex/lsp/symbol_index_builder.rb +30 -20
- data/lib/ibex/lsp/symbol_occurrence.rb +8 -2
- data/lib/ibex/lsp/transport.rb +13 -3
- data/lib/ibex/lsp/workspace.rb +5 -4
- data/lib/ibex/lsp/workspace_analyzer.rb +1 -1
- data/lib/ibex/lsp.rb +1 -0
- data/lib/ibex/messages/en.yml +28 -0
- data/lib/ibex/messages/ja.yml +28 -0
- data/lib/ibex/messages.rb +68 -0
- data/lib/ibex/metrics.rb +175 -0
- data/lib/ibex/normalize/declarations.rb +2 -0
- data/lib/ibex/normalize/diagnostics.rb +63 -38
- data/lib/ibex/normalize/expander.rb +5 -4
- data/lib/ibex/normalize/expression.rb +8 -6
- data/lib/ibex/normalize/grammar_builder.rb +26 -0
- data/lib/ibex/normalize/inline_expansion.rb +100 -49
- data/lib/ibex/normalize/lexer.rb +3 -3
- data/lib/ibex/normalize/parameter_ebnf_lowering.rb +11 -10
- data/lib/ibex/normalize/parameter_lowering.rb +40 -23
- data/lib/ibex/normalize/parameters.rb +31 -4
- data/lib/ibex/normalize/parser_configuration.rb +70 -0
- data/lib/ibex/normalize.rb +10 -20
- data/lib/ibex/racc_migration/report.rb +6 -3
- data/lib/ibex/rake_task.rb +1 -1
- data/lib/ibex/samples.rb +43 -13
- data/lib/ibex/table_artifact/builder.rb +266 -0
- data/lib/ibex/table_artifact/cst_projection.rb +70 -0
- data/lib/ibex/table_artifact/document.rb +39 -0
- data/lib/ibex/table_artifact/executor.rb +187 -0
- data/lib/ibex/table_artifact/serializer.rb +57 -0
- data/lib/ibex/table_artifact/validator/metadata.rb +179 -0
- data/lib/ibex/table_artifact/validator/support.rb +86 -0
- data/lib/ibex/table_artifact/validator/tables.rb +238 -0
- data/lib/ibex/table_artifact/validator.rb +253 -0
- data/lib/ibex/table_artifact.rb +88 -0
- data/lib/ibex/table_simulation/result.rb +6 -2
- data/lib/ibex/table_simulation/step.rb +3 -1
- data/lib/ibex/tables.rb +14 -0
- data/lib/ibex/verifiable_generation_bundle.rb +86 -0
- data/lib/ibex/verification_report/builder.rb +159 -0
- data/lib/ibex/verification_report/canonical_ir.rb +123 -0
- data/lib/ibex/verification_report/logical_path.rb +68 -0
- data/lib/ibex/verification_report/validator.rb +329 -0
- data/lib/ibex/verification_report.rb +69 -0
- data/lib/ibex/verify/action_correspondence.rb +138 -0
- data/lib/ibex/verify/language_witness.rb +295 -0
- data/lib/ibex/verify/reference_collection.rb +190 -0
- data/lib/ibex/verify/result.rb +73 -0
- data/lib/ibex/verify/verifier.rb +598 -0
- data/lib/ibex/verify.rb +15 -0
- data/lib/ibex/version.rb +1 -1
- data/lib/ibex/watch/runner.rb +10 -1
- data/lib/ibex/watch/source_snapshot.rb +13 -8
- data/lib/ibex.rb +10 -0
- data/schema/{automaton-ir-v1.schema.json → automaton-ir-definitions.schema.json} +6 -6
- data/schema/{automaton-ir-v2.schema.json → automaton-ir.schema.json} +14 -7
- data/schema/bison-import-v1.schema.json +106 -0
- data/schema/conflict-explanation-review-v1.schema.json +196 -0
- data/schema/conflict-explanation-study-v1.schema.json +528 -0
- data/schema/construction-profile-v1.schema.json +779 -0
- data/schema/diff-v1.schema.json +41 -0
- data/schema/direct-ielr-decision-v1.schema.json +200 -0
- data/schema/equiv-v1.schema.json +64 -0
- data/schema/error-ux-review-v1.schema.json +609 -0
- data/schema/error-ux-round2-review-v1.schema.json +191 -0
- data/schema/error-ux-round2-v1.schema.json +519 -0
- data/schema/explain-v1.schema.json +63 -1
- data/schema/fix-v1.schema.json +64 -0
- data/schema/fix-v2.schema.json +66 -0
- data/schema/fix-v3.schema.json +101 -0
- data/schema/fuzz-regression-v1.schema.json +79 -0
- data/schema/fuzz-v1.schema.json +114 -0
- data/schema/{grammar-ir-v2.schema.json → grammar-ir-extensions.schema.json} +20 -65
- data/schema/{grammar-ir-v1.schema.json → grammar-ir-foundation.schema.json} +3 -3
- data/schema/grammar-ir.schema.json +271 -0
- data/schema/ielr-benchmark-v1.schema.json +85 -0
- data/schema/lexer-profile-v1.schema.json +491 -0
- data/schema/metrics-v1.schema.json +60 -0
- data/schema/reduce-v1.schema.json +22 -0
- data/schema/reduce-v2.schema.json +63 -0
- data/schema/table-artifact-v1.schema.json +377 -0
- data/schema/verification-report-v1.schema.json +222 -0
- data/schema/verify-v1.schema.json +42 -0
- data/sig/ibex/analysis/digraph.rbs +19 -0
- data/sig/ibex/bison_import/importer.rbs +140 -0
- data/sig/ibex/bison_import/tokenizer.rbs +91 -0
- data/sig/ibex/bison_import.rbs +95 -0
- data/sig/ibex/bounded_subprocess.rbs +76 -0
- data/sig/ibex/cli/ambiguity.rbs +6 -0
- data/sig/ibex/cli/analysis.rbs +43 -0
- data/sig/ibex/cli/bison_import.rbs +32 -0
- data/sig/ibex/cli/config.rbs +35 -0
- data/sig/ibex/cli/diagnostics.rbs +16 -3
- data/sig/ibex/cli/documentation.rbs +5 -1
- data/sig/ibex/cli/equiv.rbs +49 -0
- data/sig/ibex/cli/error_messages.rbs +6 -0
- data/sig/ibex/cli/explain.rbs +6 -0
- data/sig/ibex/cli/fix.rbs +53 -0
- data/sig/ibex/cli/formatting.rbs +5 -1
- data/sig/ibex/cli/fuzz.rbs +47 -0
- data/sig/ibex/cli/fuzz_regressions.rbs +40 -0
- data/sig/ibex/cli/generation_artifacts.rbs +21 -2
- data/sig/ibex/cli/generation_error_messages.rbs +2 -2
- data/sig/ibex/cli/grammar_tests.rbs +15 -3
- data/sig/ibex/cli/ir_tools.rbs +7 -19
- data/sig/ibex/cli/outputs.rbs +9 -3
- data/sig/ibex/cli/reduce.rbs +60 -0
- data/sig/ibex/cli/reduce_reporting.rbs +27 -0
- data/sig/ibex/cli/samples.rbs +8 -0
- data/sig/ibex/cli/verify.rbs +28 -0
- data/sig/ibex/cli/watch.rbs +2 -2
- data/sig/ibex/cli.rbs +79 -5
- data/sig/ibex/codegen/action_method_source.rbs +4 -4
- data/sig/ibex/codegen/explain.rbs +45 -25
- data/sig/ibex/codegen/generated_action_abi.rbs +14 -10
- data/sig/ibex/codegen/rbs.rbs +12 -10
- data/sig/ibex/codegen/report.rbs +12 -12
- data/sig/ibex/codegen/ruby.rbs +18 -15
- data/sig/ibex/codegen/ruby_actions.rbs +6 -6
- data/sig/ibex/codegen/ruby_syntax.rbs +10 -8
- data/sig/ibex/configuration/analysis_grammar.rbs +13 -0
- data/sig/ibex/configuration/explanation.rbs +195 -0
- data/sig/ibex/configuration/inspector.rbs +53 -0
- data/sig/ibex/configuration.rbs +242 -0
- data/sig/ibex/coverage/collector.rbs +16 -14
- data/sig/ibex/coverage/event_stream.rbs +12 -10
- data/sig/ibex/coverage/report.rbs +20 -18
- data/sig/ibex/coverage/runtime_event_validator.rbs +38 -36
- data/sig/ibex/delta_reducer.rbs +38 -0
- data/sig/ibex/diff.rbs +47 -0
- data/sig/ibex/equiv/machine.rbs +54 -0
- data/sig/ibex/equiv.rbs +129 -0
- data/sig/ibex/fix.rbs +138 -0
- data/sig/ibex/frontend/ast.rbs +33 -7
- data/sig/ibex/frontend/bootstrap_parser.rbs +2 -0
- data/sig/ibex/frontend/diagnostic.rbs +2 -2
- data/sig/ibex/frontend/formatter.rbs +38 -30
- data/sig/ibex/frontend/generated_parser.rbs +87 -77
- data/sig/ibex/frontend/generated_parser_base.rbs +4 -2
- data/sig/ibex/frontend/parser/declarations.rbs +3 -0
- data/sig/ibex/frontend/parser_configuration_support.rbs +27 -0
- data/sig/ibex/frontend/resolution.rbs +3 -2
- data/sig/ibex/frontend/source_cursor.rbs +2 -2
- data/sig/ibex/frontend/source_span.rbs +5 -2
- data/sig/ibex/frontend/token_adapter/declaration_state.rbs +13 -1
- data/sig/ibex/frontend/token_adapter.rbs +6 -0
- data/sig/ibex/fuzz.rbs +71 -0
- data/sig/ibex/generation_input.rbs +2 -2
- data/sig/ibex/generation_manifest.rbs +35 -32
- data/sig/ibex/generation_transaction_recovery.rbs +2 -2
- data/sig/ibex/generation_transaction_validation.rbs +2 -2
- data/sig/ibex/grammar_tests.rbs +2 -2
- data/sig/ibex/ir/automaton_ir.rbs +30 -11
- data/sig/ibex/ir/grammar_ir.rbs +41 -27
- data/sig/ibex/ir/lexer_ir.rbs +8 -8
- data/sig/ibex/ir/parser_contract.rbs +69 -0
- data/sig/ibex/ir/serialize.rbs +63 -28
- data/sig/ibex/ir/validator/automaton.rbs +47 -44
- data/sig/ibex/ir/validator/base.rbs +35 -31
- data/sig/ibex/ir/validator/grammar.rbs +78 -67
- data/sig/ibex/ir/validator/lexer.rbs +4 -4
- data/sig/ibex/ir.rbs +9 -3
- data/sig/ibex/lalr/build_metrics.rbs +42 -2
- data/sig/ibex/lalr/builder.rbs +75 -24
- data/sig/ibex/lalr/conflict_search.rbs +5 -2
- data/sig/ibex/lalr/counterexample.rbs +17 -14
- data/sig/ibex/lalr/direct_lookaheads.rbs +35 -28
- data/sig/ibex/lalr/goto_follows.rbs +89 -0
- data/sig/ibex/lalr/ielr/annotator.rbs +67 -0
- data/sig/ibex/lalr/ielr/bits.rbs +14 -0
- data/sig/ibex/lalr/ielr/inadequacy.rbs +24 -0
- data/sig/ibex/lalr/ielr/item_lookaheads.rbs +35 -0
- data/sig/ibex/lalr/ielr/pipeline.rbs +17 -0
- data/sig/ibex/lalr/ielr/split_stability.rbs +27 -0
- data/sig/ibex/lalr/ielr/split_state.rbs +14 -0
- data/sig/ibex/lalr/ielr/state_splitter.rbs +76 -0
- data/sig/ibex/lalr/ielr_partition.rbs +17 -5
- data/sig/ibex/lalr/inadequacy_report.rbs +21 -0
- data/sig/ibex/lalr/lookahead_propagation.rbs +38 -0
- data/sig/ibex/lalr/lr0_collection.rbs +50 -0
- data/sig/ibex/lalr/unreachable_states.rbs +25 -0
- data/sig/ibex/lalr.rbs +11 -1
- data/sig/ibex/location.rbs +6 -6
- data/sig/ibex/lsp/document_handlers.rbs +8 -8
- data/sig/ibex/lsp/initialization_handlers.rbs +12 -12
- data/sig/ibex/lsp/navigation_handlers.rbs +15 -12
- data/sig/ibex/lsp/parser_configuration_assistance.rbs +49 -0
- data/sig/ibex/lsp/position_codec.rbs +8 -4
- data/sig/ibex/lsp/request_handlers.rbs +4 -4
- data/sig/ibex/lsp/request_support.rbs +8 -8
- data/sig/ibex/lsp/server.rbs +16 -16
- data/sig/ibex/lsp/symbol_index.rbs +20 -21
- data/sig/ibex/lsp/symbol_index_builder.rbs +9 -8
- data/sig/ibex/lsp/symbol_occurrence.rbs +11 -5
- data/sig/ibex/lsp/transport.rbs +18 -6
- data/sig/ibex/lsp/workspace.rbs +3 -2
- data/sig/ibex/lsp/workspace_analyzer.rbs +1 -1
- data/sig/ibex/messages.rbs +26 -0
- data/sig/ibex/metrics.rbs +50 -0
- data/sig/ibex/normalize/diagnostics.rbs +4 -4
- data/sig/ibex/normalize/expander.rbs +2 -2
- data/sig/ibex/normalize/expression.rbs +10 -8
- data/sig/ibex/normalize/grammar_builder.rbs +11 -0
- data/sig/ibex/normalize/inline_expansion.rbs +59 -50
- data/sig/ibex/normalize/lexer.rbs +4 -4
- data/sig/ibex/normalize/parameter_ebnf_lowering.rbs +15 -14
- data/sig/ibex/normalize/parameter_lowering.rbs +18 -18
- data/sig/ibex/normalize/parameters.rbs +13 -8
- data/sig/ibex/normalize/parser_configuration.rbs +23 -0
- data/sig/ibex/normalize.rbs +11 -5
- data/sig/ibex/racc_migration/report.rbs +8 -6
- data/sig/ibex/rake_task.rbs +1 -1
- data/sig/ibex/samples.rbs +13 -4
- data/sig/ibex/table_artifact/builder.rbs +93 -0
- data/sig/ibex/table_artifact/cst_projection.rbs +20 -0
- data/sig/ibex/table_artifact/document.rbs +27 -0
- data/sig/ibex/table_artifact/executor.rbs +66 -0
- data/sig/ibex/table_artifact/serializer.rbs +25 -0
- data/sig/ibex/table_artifact/validator/metadata.rbs +52 -0
- data/sig/ibex/table_artifact/validator/support.rbs +46 -0
- data/sig/ibex/table_artifact/validator/tables.rbs +63 -0
- data/sig/ibex/table_artifact/validator.rbs +66 -0
- data/sig/ibex/table_artifact.rbs +32 -0
- data/sig/ibex/table_simulation/result.rbs +8 -4
- data/sig/ibex/table_simulation/step.rbs +4 -2
- data/sig/ibex/tables.rbs +10 -9
- data/sig/ibex/verifiable_generation_bundle.rbs +24 -0
- data/sig/ibex/verification_report/builder.rbs +53 -0
- data/sig/ibex/verification_report/canonical_ir.rbs +41 -0
- data/sig/ibex/verification_report/logical_path.rbs +34 -0
- data/sig/ibex/verification_report/validator.rbs +114 -0
- data/sig/ibex/verification_report.rbs +44 -0
- data/sig/ibex/verify/action_correspondence.rbs +50 -0
- data/sig/ibex/verify/language_witness.rbs +112 -0
- data/sig/ibex/verify/reference_collection.rbs +63 -0
- data/sig/ibex/verify/result.rbs +52 -0
- data/sig/ibex/verify/verifier.rbs +170 -0
- data/sig/ibex/verify.rbs +6 -0
- data/sig/ibex/watch/runner.rbs +12 -2
- data/sig/ibex/watch/source_snapshot.rbs +13 -9
- metadata +232 -12
- data/lib/ibex/ir/migration.rb +0 -120
- data/sig/ibex/ir/migration.rbs +0 -34
|
@@ -6,7 +6,11 @@ require "json"
|
|
|
6
6
|
|
|
7
7
|
module Ibex
|
|
8
8
|
# Deterministic description of one published parser generation.
|
|
9
|
+
# rubocop:disable Metrics/ModuleLength -- manifest schema validation is kept in one auditable unit.
|
|
9
10
|
module GenerationManifest
|
|
11
|
+
# @rbs!
|
|
12
|
+
# type json_value = String | Integer | Float | bool | nil | Array[json_value] | Hash[String, json_value]
|
|
13
|
+
|
|
10
14
|
SCHEMA_VERSION = 1 #: Integer
|
|
11
15
|
IDENTIFIER = "generation" #: String
|
|
12
16
|
ROOT_KEYS = %w[ibex_manifest schema_version input options artifacts].freeze #: Array[String]
|
|
@@ -16,7 +20,7 @@ module Ibex
|
|
|
16
20
|
|
|
17
21
|
module_function
|
|
18
22
|
|
|
19
|
-
# @rbs (ArtifactSet artifacts, source_records: Array[GenerationInput], options: Hash[String,
|
|
23
|
+
# @rbs (ArtifactSet artifacts, source_records: Array[GenerationInput], options: Hash[String, Object?]) -> String
|
|
20
24
|
def render(artifacts, source_records:, options:)
|
|
21
25
|
files = source_records.map(&:to_h)
|
|
22
26
|
document = {
|
|
@@ -34,24 +38,26 @@ module Ibex
|
|
|
34
38
|
end
|
|
35
39
|
|
|
36
40
|
# Validate the manifest shape and, by default, every published artifact digest.
|
|
37
|
-
# @rbs (String source, ?verify_artifacts: bool) -> Hash[String,
|
|
41
|
+
# @rbs (String source, ?verify_artifacts: bool) -> Hash[String, json_value]
|
|
38
42
|
def validate(source, verify_artifacts: true)
|
|
39
|
-
document = JSON.parse(source)
|
|
43
|
+
document = JSON.parse(source) #: Object?
|
|
40
44
|
validate_document(document)
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
document_hash = document #: Hash[String, json_value]
|
|
46
|
+
artifacts = document_hash.fetch("artifacts") #: Array[Object?]
|
|
47
|
+
verify_entries(artifacts) if verify_artifacts
|
|
48
|
+
document_hash
|
|
43
49
|
rescue JSON::ParserError, KeyError, TypeError, ArgumentError => e
|
|
44
50
|
raise Ibex::Error, "(manifest):1:1: invalid generation manifest: #{e.message}"
|
|
45
51
|
end
|
|
46
52
|
|
|
47
|
-
# @rbs (String path, ?verify_artifacts: bool) -> Hash[String,
|
|
53
|
+
# @rbs (String path, ?verify_artifacts: bool) -> Hash[String, json_value]
|
|
48
54
|
def validate_file(path, verify_artifacts: true)
|
|
49
55
|
validate(File.binread(path), verify_artifacts: verify_artifacts)
|
|
50
56
|
rescue SystemCallError, ArgumentError => e
|
|
51
57
|
raise Ibex::Error, "#{path}:1:1: cannot read generation manifest: #{e.message}"
|
|
52
58
|
end
|
|
53
59
|
|
|
54
|
-
# @rbs (Artifact artifact) -> Hash[String,
|
|
60
|
+
# @rbs (Artifact artifact) -> Hash[String, json_value]
|
|
55
61
|
def artifact_entry(artifact)
|
|
56
62
|
{
|
|
57
63
|
"kind" => artifact.kind.to_s,
|
|
@@ -62,19 +68,20 @@ module Ibex
|
|
|
62
68
|
end
|
|
63
69
|
private_class_method :artifact_entry
|
|
64
70
|
|
|
65
|
-
# @rbs (Array[Hash[String,
|
|
71
|
+
# @rbs (Array[Hash[String, json_value]] files) -> String
|
|
66
72
|
def input_digest(files)
|
|
67
73
|
digest = Digest::SHA256.new
|
|
68
74
|
files.each do |entry|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
75
|
+
path = entry.fetch("path") # @type var path: String
|
|
76
|
+
sha256 = entry.fetch("sha256") # @type var sha256: String
|
|
77
|
+
bytesize = entry.fetch("bytesize") # @type var bytesize: Integer
|
|
78
|
+
digest << path << "\0" << sha256 << "\0" << bytesize.to_s << "\0"
|
|
72
79
|
end
|
|
73
80
|
digest.hexdigest
|
|
74
81
|
end
|
|
75
82
|
private_class_method :input_digest
|
|
76
83
|
|
|
77
|
-
# @rbs (Hash[String,
|
|
84
|
+
# @rbs (Hash[String, Object?] value) -> Hash[String, Object?]
|
|
78
85
|
def sorted_hash(value)
|
|
79
86
|
value.keys.sort.to_h do |key|
|
|
80
87
|
child = value.fetch(key)
|
|
@@ -84,7 +91,7 @@ module Ibex
|
|
|
84
91
|
end
|
|
85
92
|
private_class_method :sorted_hash
|
|
86
93
|
|
|
87
|
-
# @rbs (
|
|
94
|
+
# @rbs (Object? document) -> void
|
|
88
95
|
def validate_document(document)
|
|
89
96
|
raise TypeError, "document must be an object" unless document.is_a?(Hash)
|
|
90
97
|
|
|
@@ -100,14 +107,14 @@ module Ibex
|
|
|
100
107
|
end
|
|
101
108
|
private_class_method :validate_document
|
|
102
109
|
|
|
103
|
-
# @rbs (Hash[
|
|
110
|
+
# @rbs (Hash[Object?, Object?] document) -> void
|
|
104
111
|
def validate_identity(document)
|
|
105
112
|
raise TypeError, "unsupported manifest identifier" unless document["ibex_manifest"] == IDENTIFIER
|
|
106
113
|
raise TypeError, "unsupported schema_version" unless document["schema_version"] == SCHEMA_VERSION
|
|
107
114
|
end
|
|
108
115
|
private_class_method :validate_identity
|
|
109
116
|
|
|
110
|
-
# @rbs (
|
|
117
|
+
# @rbs (Object? input) -> void
|
|
111
118
|
def validate_input(input)
|
|
112
119
|
raise TypeError, "input must be an object" unless input.is_a?(Hash)
|
|
113
120
|
|
|
@@ -125,13 +132,13 @@ module Ibex
|
|
|
125
132
|
end
|
|
126
133
|
private_class_method :validate_input
|
|
127
134
|
|
|
128
|
-
# @rbs (Array[
|
|
135
|
+
# @rbs (Array[Object?] entries, String label, ?require_kind: bool) -> void
|
|
129
136
|
def validate_entries(entries, label, require_kind: false)
|
|
130
137
|
entries.each { |entry| validate_entry(entry, label, require_kind) }
|
|
131
138
|
end
|
|
132
139
|
private_class_method :validate_entries
|
|
133
140
|
|
|
134
|
-
# @rbs (
|
|
141
|
+
# @rbs (Object? entry, String label, bool require_kind) -> void
|
|
135
142
|
def validate_entry(entry, label, require_kind)
|
|
136
143
|
raise TypeError, "#{label} must be an object" unless entry.is_a?(Hash)
|
|
137
144
|
|
|
@@ -146,7 +153,7 @@ module Ibex
|
|
|
146
153
|
end
|
|
147
154
|
private_class_method :validate_entry
|
|
148
155
|
|
|
149
|
-
# @rbs (
|
|
156
|
+
# @rbs (Object? path, String label) -> void
|
|
150
157
|
def validate_path(path, label)
|
|
151
158
|
raise TypeError, "#{label} path must be a non-empty string" unless path.is_a?(String) && !path.empty?
|
|
152
159
|
return unless path.include?("\0") || path.match?(/[[:cntrl:]]/)
|
|
@@ -155,7 +162,7 @@ module Ibex
|
|
|
155
162
|
end
|
|
156
163
|
private_class_method :validate_path
|
|
157
164
|
|
|
158
|
-
# @rbs (
|
|
165
|
+
# @rbs (Object? kind, String label) -> void
|
|
159
166
|
def validate_kind(kind, label)
|
|
160
167
|
return if kind.is_a?(String) && !kind.empty?
|
|
161
168
|
|
|
@@ -163,7 +170,7 @@ module Ibex
|
|
|
163
170
|
end
|
|
164
171
|
private_class_method :validate_kind
|
|
165
172
|
|
|
166
|
-
# @rbs (
|
|
173
|
+
# @rbs (Object? digest, String label) -> void
|
|
167
174
|
def validate_digest(digest, label)
|
|
168
175
|
return if digest.is_a?(String) && digest.match?(/\A[0-9a-f]{64}\z/)
|
|
169
176
|
|
|
@@ -171,7 +178,7 @@ module Ibex
|
|
|
171
178
|
end
|
|
172
179
|
private_class_method :validate_digest
|
|
173
180
|
|
|
174
|
-
# @rbs (Hash[
|
|
181
|
+
# @rbs (Hash[Object?, Object?] value, Array[String] expected, String label) -> void
|
|
175
182
|
def exact_keys!(value, expected, label)
|
|
176
183
|
keys = value.keys
|
|
177
184
|
raise TypeError, "#{label} keys must be strings" unless keys.all?(String)
|
|
@@ -183,18 +190,22 @@ module Ibex
|
|
|
183
190
|
end
|
|
184
191
|
private_class_method :exact_keys!
|
|
185
192
|
|
|
186
|
-
# @rbs (Array[
|
|
193
|
+
# @rbs (Array[Object?] entries) -> void
|
|
187
194
|
def verify_entries(entries)
|
|
188
195
|
entries.each do |entry|
|
|
189
|
-
|
|
196
|
+
entry_hash = entry #: Hash[String, json_value]
|
|
197
|
+
path = entry_hash.fetch("path") #: String
|
|
190
198
|
source = File.binread(path)
|
|
191
|
-
|
|
199
|
+
bytesize = entry_hash.fetch("bytesize") #: Integer
|
|
200
|
+
sha256 = entry_hash.fetch("sha256") #: String
|
|
201
|
+
raise TypeError, "artifact bytesize mismatch for #{path}" unless source.bytesize == bytesize
|
|
192
202
|
raise TypeError, "artifact digest mismatch for #{path}" unless
|
|
193
|
-
Digest::SHA256.hexdigest(source) ==
|
|
203
|
+
Digest::SHA256.hexdigest(source) == sha256
|
|
194
204
|
end
|
|
195
205
|
rescue SystemCallError => e
|
|
196
206
|
raise TypeError, "cannot read artifact: #{e.message}"
|
|
197
207
|
end
|
|
198
208
|
private_class_method :verify_entries
|
|
199
209
|
end
|
|
210
|
+
# rubocop:enable Metrics/ModuleLength
|
|
200
211
|
end
|
|
@@ -37,7 +37,7 @@ module Ibex
|
|
|
37
37
|
@lock_sleeper = lock_sleeper
|
|
38
38
|
@locks = [] #: Array[File]
|
|
39
39
|
@locked_paths = [] #: Array[String]
|
|
40
|
-
@records = [] #: Array[Hash[Symbol,
|
|
40
|
+
@records = [] #: Array[Hash[Symbol, Object?]]
|
|
41
41
|
@committed = false
|
|
42
42
|
@temporary_sequence = 0
|
|
43
43
|
end
|
|
@@ -57,14 +57,14 @@ module Ibex
|
|
|
57
57
|
failures
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
-
# @rbs (Hash[Symbol,
|
|
60
|
+
# @rbs (Hash[Symbol, Object?] record) -> void
|
|
61
61
|
def rollback_record(record)
|
|
62
|
-
target = record.fetch(:target)
|
|
62
|
+
target = record.fetch(:target) #: String
|
|
63
63
|
if record.fetch(:backed_up)
|
|
64
64
|
if record.fetch(:installed)
|
|
65
|
-
File.rename(record.fetch(:backup), target)
|
|
65
|
+
File.rename(record.fetch(:backup).to_s, target)
|
|
66
66
|
else
|
|
67
|
-
File.unlink(record.fetch(:backup))
|
|
67
|
+
File.unlink(record.fetch(:backup).to_s)
|
|
68
68
|
end
|
|
69
69
|
record[:backup] = nil
|
|
70
70
|
record[:backed_up] = false
|
|
@@ -170,9 +170,9 @@ module Ibex
|
|
|
170
170
|
"(generation):1:1: cannot revalidate artifact target #{phase}: #{e.message}"
|
|
171
171
|
end
|
|
172
172
|
|
|
173
|
-
# @rbs (Hash[Symbol,
|
|
173
|
+
# @rbs (Hash[Symbol, Object?] record, Array[String] sources, String phase) -> void
|
|
174
174
|
def validate_current_target!(record, sources, phase)
|
|
175
|
-
artifact = record.fetch(:artifact)
|
|
175
|
+
artifact = record.fetch(:artifact) #: Artifact
|
|
176
176
|
current = resolved_target(artifact.path, validate_links: false)
|
|
177
177
|
unless current == record.fetch(:target)
|
|
178
178
|
raise GenerationTransaction::SourceChanged,
|
data/lib/ibex/grammar_tests.rb
CHANGED
|
@@ -182,7 +182,7 @@ module Ibex
|
|
|
182
182
|
raise Ibex::Error, "(test):1:1: invalid grammar test process result: #{e.message}"
|
|
183
183
|
end
|
|
184
184
|
|
|
185
|
-
# @rbs (IR::grammar_test test,
|
|
185
|
+
# @rbs (IR::grammar_test test, Object? document) -> Result
|
|
186
186
|
def build_result(test, document)
|
|
187
187
|
unless document.is_a?(Hash) && %w[accept reject error].include?(document["actual"])
|
|
188
188
|
raise Ibex::Error, "(test):1:1: grammar test process returned an invalid case result"
|
data/lib/ibex/ir/automaton_ir.rb
CHANGED
|
@@ -16,7 +16,7 @@ module Ibex
|
|
|
16
16
|
freeze
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
# @rbs (Grammar grammar) -> Hash[Symbol,
|
|
19
|
+
# @rbs (Grammar grammar) -> Hash[Symbol, Object?]
|
|
20
20
|
def to_h(grammar)
|
|
21
21
|
{ production: @production, dot: @dot,
|
|
22
22
|
lookaheads: @lookaheads.map do |id|
|
|
@@ -50,7 +50,7 @@ module Ibex
|
|
|
50
50
|
freeze
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
-
# @rbs (Grammar grammar) -> Hash[Symbol,
|
|
53
|
+
# @rbs (Grammar grammar) -> Hash[Symbol, Object?]
|
|
54
54
|
def to_h(grammar)
|
|
55
55
|
{ id: @id, items: @items.map { |item| item.to_h(grammar) },
|
|
56
56
|
transitions: named_keys(@transitions, grammar), actions: named_keys(@actions, grammar),
|
|
@@ -59,7 +59,7 @@ module Ibex
|
|
|
59
59
|
|
|
60
60
|
private
|
|
61
61
|
|
|
62
|
-
# @rbs (Hash[Integer,
|
|
62
|
+
# @rbs (Hash[Integer, Object?] values, Grammar grammar) -> Hash[String, Object?]
|
|
63
63
|
def named_keys(values, grammar)
|
|
64
64
|
values.to_h do |symbol_id, value|
|
|
65
65
|
symbol = grammar.symbol_by_id(symbol_id) || raise(Ibex::Error, "missing grammar symbol id #{symbol_id}")
|
|
@@ -77,42 +77,55 @@ module Ibex
|
|
|
77
77
|
attr_reader :entry_states #: Hash[String, Integer]
|
|
78
78
|
attr_reader :conflict_summary #: conflict_summary
|
|
79
79
|
attr_reader :schema_version #: Integer
|
|
80
|
+
attr_reader :entry_construction #: String
|
|
80
81
|
|
|
81
82
|
# @rbs (grammar: Grammar, states: Array[AutomatonState], conflict_summary: conflict_summary,
|
|
82
|
-
# ?algorithm: String, ?grammar_digest: String?, ?
|
|
83
|
-
# ?
|
|
83
|
+
# ?algorithm: String, ?grammar_digest: String?, ?entry_states: Hash[String, Integer]?,
|
|
84
|
+
# ?entry_construction: String) -> void
|
|
84
85
|
def initialize(grammar:, states:, conflict_summary:, algorithm: "lalr1", grammar_digest: nil,
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
entry_states: nil, entry_construction: "shared")
|
|
87
|
+
initialize_current(
|
|
88
|
+
grammar: grammar, states: states, conflict_summary: conflict_summary, algorithm: algorithm,
|
|
89
|
+
grammar_digest: grammar_digest, entry_states: entry_states, entry_construction: entry_construction
|
|
90
|
+
)
|
|
91
|
+
end
|
|
89
92
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
# @rbs (grammar: Grammar, states: Array[AutomatonState], conflict_summary: conflict_summary,
|
|
94
|
+
# algorithm: String, grammar_digest: String?, entry_states: Hash[String, Integer]?,
|
|
95
|
+
# entry_construction: String) -> void
|
|
96
|
+
def initialize_current(grammar:, states:, conflict_summary:, algorithm:, grammar_digest:, entry_states:,
|
|
97
|
+
entry_construction:)
|
|
98
|
+
unless grammar.schema_version == SCHEMA_VERSION
|
|
99
|
+
raise Ibex::Error, "automaton requires the current Grammar IR format"
|
|
96
100
|
end
|
|
97
101
|
|
|
98
102
|
@algorithm = algorithm.freeze
|
|
99
103
|
@grammar = grammar
|
|
100
|
-
|
|
104
|
+
expected_digest = digest_for(grammar)
|
|
105
|
+
if grammar_digest && grammar_digest != expected_digest
|
|
106
|
+
raise Ibex::Error,
|
|
107
|
+
"(ir):1:1: $.grammar_digest does not match the embedded grammar; expected #{expected_digest.inspect}"
|
|
108
|
+
end
|
|
109
|
+
@grammar_digest = (grammar_digest || expected_digest).freeze
|
|
101
110
|
@states = states.freeze
|
|
102
111
|
@entry_states = IR.deep_freeze(entry_states || { grammar.start => 0 })
|
|
103
112
|
validate_entry_states
|
|
104
113
|
@conflict_summary = IR.deep_freeze(conflict_summary)
|
|
105
|
-
@schema_version =
|
|
114
|
+
@schema_version = SCHEMA_VERSION
|
|
115
|
+
@entry_construction = validate_entry_construction(entry_construction)
|
|
116
|
+
validate_parser_contract
|
|
106
117
|
freeze
|
|
107
118
|
end
|
|
119
|
+
private :initialize_current
|
|
108
120
|
|
|
109
|
-
# @rbs () -> Hash[Symbol,
|
|
121
|
+
# @rbs () -> Hash[Symbol, Object?]
|
|
110
122
|
def to_h
|
|
111
123
|
value = { ibex_ir: "automaton", schema_version: @schema_version, algorithm: @algorithm,
|
|
112
124
|
grammar_digest: @grammar_digest, grammar: @grammar.to_h,
|
|
113
125
|
states: @states.map { |state| state.to_h(@grammar) },
|
|
114
|
-
conflict_summary: @conflict_summary } #: Hash[Symbol,
|
|
126
|
+
conflict_summary: @conflict_summary } #: Hash[Symbol, Object?]
|
|
115
127
|
value[:entry_states] = @entry_states unless @entry_states == { @grammar.start => 0 }
|
|
128
|
+
value[:entry_construction] = @entry_construction
|
|
116
129
|
value
|
|
117
130
|
end
|
|
118
131
|
|
|
@@ -137,6 +150,35 @@ module Ibex
|
|
|
137
150
|
require "digest"
|
|
138
151
|
"sha256:#{Digest::SHA256.hexdigest(IR::Serialize.dump(grammar))}"
|
|
139
152
|
end
|
|
153
|
+
|
|
154
|
+
# @rbs (String value) -> String
|
|
155
|
+
def validate_entry_construction(value)
|
|
156
|
+
raise Ibex::Error, "entry construction must be shared or isolated" unless %w[shared isolated].include?(value)
|
|
157
|
+
|
|
158
|
+
value.dup.freeze
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# @rbs () -> void
|
|
162
|
+
def validate_parser_contract
|
|
163
|
+
contract = @grammar.parser_contract
|
|
164
|
+
validate_parser_algorithm(contract)
|
|
165
|
+
validate_parser_entries(contract)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# @rbs (ParserContract contract) -> void
|
|
169
|
+
def validate_parser_algorithm(contract)
|
|
170
|
+
selected_algorithm = { "lalr1" => :lalr, "ielr1" => :ielr }.fetch(@algorithm, @algorithm.to_sym)
|
|
171
|
+
return unless contract.algorithm.explicit && contract.algorithm.value != selected_algorithm
|
|
172
|
+
|
|
173
|
+
raise Ibex::Error, "automaton algorithm conflicts with the embedded parser contract"
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# @rbs (ParserContract contract) -> void
|
|
177
|
+
def validate_parser_entries(contract)
|
|
178
|
+
return unless contract.entries.explicit && contract.entries.value.to_s != @entry_construction
|
|
179
|
+
|
|
180
|
+
raise Ibex::Error, "automaton entry construction conflicts with the embedded parser contract"
|
|
181
|
+
end
|
|
140
182
|
end
|
|
141
183
|
end
|
|
142
184
|
end
|
data/lib/ibex/ir/grammar_ir.rb
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "parser_contract"
|
|
4
|
+
|
|
3
5
|
module Ibex
|
|
4
6
|
module IR
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
# Grammar IR has one active wire format. A future incompatible format
|
|
8
|
+
# change may advance this number, but the runtime never treats old
|
|
9
|
+
# formats as an alternate compatibility surface.
|
|
10
|
+
SCHEMA_VERSION = 1
|
|
11
|
+
SUPPORTED_SCHEMA_VERSIONS = [SCHEMA_VERSION].freeze #: Array[Integer]
|
|
7
12
|
|
|
8
|
-
# @rbs (
|
|
13
|
+
# @rbs (Object? value) -> Object?
|
|
9
14
|
def deep_freeze(value)
|
|
10
15
|
case value
|
|
11
16
|
when Array then value.each { |item| deep_freeze(item) }
|
|
@@ -52,13 +57,13 @@ module Ibex
|
|
|
52
57
|
# @rbs () -> bool
|
|
53
58
|
def nonterminal? = @kind == :nonterminal
|
|
54
59
|
|
|
55
|
-
# @rbs (
|
|
56
|
-
def to_h
|
|
60
|
+
# @rbs () -> Hash[Symbol, Object?]
|
|
61
|
+
def to_h
|
|
57
62
|
value = { id: @id, name: @name, kind: @kind, reserved: @reserved,
|
|
58
|
-
prec: @precedence, loc: @location } #: Hash[Symbol,
|
|
63
|
+
prec: @precedence, loc: @location } #: Hash[Symbol, Object?]
|
|
59
64
|
value[:display_name] = @display_name if @display_name
|
|
60
65
|
value[:semantic_type] = @semantic_type if @semantic_type
|
|
61
|
-
value[:doc] = @documentation
|
|
66
|
+
value[:doc] = @documentation
|
|
62
67
|
value
|
|
63
68
|
end
|
|
64
69
|
end
|
|
@@ -82,11 +87,11 @@ module Ibex
|
|
|
82
87
|
freeze
|
|
83
88
|
end
|
|
84
89
|
|
|
85
|
-
# @rbs (
|
|
86
|
-
def to_h
|
|
90
|
+
# @rbs () -> Hash[Symbol, Object?]
|
|
91
|
+
def to_h
|
|
87
92
|
value = { code: @code, loc: @location, named_refs: @named_refs,
|
|
88
|
-
context_length: @context_length } #: Hash[Symbol,
|
|
89
|
-
value[:composition] = @composition
|
|
93
|
+
context_length: @context_length } #: Hash[Symbol, Object?]
|
|
94
|
+
value[:composition] = @composition
|
|
90
95
|
value
|
|
91
96
|
end
|
|
92
97
|
end
|
|
@@ -98,13 +103,13 @@ module Ibex
|
|
|
98
103
|
attr_reader :rhs #: Array[Integer]
|
|
99
104
|
attr_reader :action #: Action?
|
|
100
105
|
attr_reader :precedence_override #: Integer?
|
|
101
|
-
attr_reader :origin #: Hash[Symbol,
|
|
106
|
+
attr_reader :origin #: Hash[Symbol, Object?]
|
|
102
107
|
attr_reader :documentation #: String?
|
|
103
108
|
attr_reader :expansion #: production_expansion?
|
|
104
109
|
attr_reader :node #: node_annotation?
|
|
105
110
|
|
|
106
111
|
# @rbs (id: Integer, lhs: Integer, rhs: Array[Integer], action: Action?, precedence_override: Integer?,
|
|
107
|
-
# origin: Hash[Symbol,
|
|
112
|
+
# origin: Hash[Symbol, Object?], ?documentation: String?, ?expansion: production_expansion?,
|
|
108
113
|
# ?node: node_annotation?) -> void
|
|
109
114
|
def initialize(id:, lhs:, rhs:, action:, precedence_override:, origin:, documentation: nil, expansion: nil,
|
|
110
115
|
node: nil)
|
|
@@ -120,15 +125,13 @@ module Ibex
|
|
|
120
125
|
freeze
|
|
121
126
|
end
|
|
122
127
|
|
|
123
|
-
# @rbs (
|
|
124
|
-
def to_h
|
|
125
|
-
value = { id: @id, lhs: @lhs, rhs: @rhs, action: @action&.to_h
|
|
126
|
-
prec_override: @precedence_override, origin: @origin } #: Hash[Symbol,
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
value[:node] = @node if @node
|
|
131
|
-
end
|
|
128
|
+
# @rbs () -> Hash[Symbol, Object?]
|
|
129
|
+
def to_h
|
|
130
|
+
value = { id: @id, lhs: @lhs, rhs: @rhs, action: @action&.to_h,
|
|
131
|
+
prec_override: @precedence_override, origin: @origin } #: Hash[Symbol, Object?]
|
|
132
|
+
value[:doc] = @documentation
|
|
133
|
+
value[:expansion] = @expansion
|
|
134
|
+
value[:node] = @node if @node
|
|
132
135
|
value
|
|
133
136
|
end
|
|
134
137
|
end
|
|
@@ -145,7 +148,7 @@ module Ibex
|
|
|
145
148
|
freeze
|
|
146
149
|
end
|
|
147
150
|
|
|
148
|
-
# @rbs () -> Hash[Symbol,
|
|
151
|
+
# @rbs () -> Hash[Symbol, Object?]
|
|
149
152
|
def to_h
|
|
150
153
|
{ code: @code, loc: @location }
|
|
151
154
|
end
|
|
@@ -174,25 +177,47 @@ module Ibex
|
|
|
174
177
|
attr_reader :warnings #: Array[grammar_warning]
|
|
175
178
|
attr_reader :schema_version #: Integer
|
|
176
179
|
attr_reader :source_provenance #: source_provenance?
|
|
177
|
-
attr_reader :
|
|
180
|
+
attr_reader :parser_contract #: ParserContract
|
|
178
181
|
|
|
179
182
|
# @rbs (class_name: String, superclass: String?, start: String, expect: Integer, ?expect_rr: Integer?,
|
|
180
183
|
# options: grammar_options,
|
|
181
184
|
# symbols: Array[GrammarSymbol], productions: Array[Production], user_code: Hash[String, String],
|
|
182
185
|
# conversions: Hash[String, String], warnings: Array[grammar_warning], ?user_code_chunks: user_code_chunks?,
|
|
183
|
-
# ?
|
|
184
|
-
# ?migration: migration_metadata?, ?parser_parameters: Array[parser_parameter],
|
|
186
|
+
# ?parser_parameters: Array[parser_parameter],
|
|
185
187
|
# ?value_printers: Array[value_printer], ?grammar_tests: Array[grammar_test],
|
|
186
188
|
# ?recovery: recovery_policy?, ?lexer: Lexer?,
|
|
187
|
-
# ?mode: grammar_mode, ?starts: Array[String]?
|
|
189
|
+
# ?mode: grammar_mode, ?starts: Array[String]?, ?parser_contract: ParserContract,
|
|
190
|
+
# ?source_provenance: source_provenance?) -> void
|
|
188
191
|
# rubocop:disable Metrics/AbcSize, Metrics/ParameterLists
|
|
189
|
-
# Immutable
|
|
192
|
+
# Immutable current IR is constructed from explicit public fields.
|
|
190
193
|
def initialize(class_name:, superclass:, start:, expect:, options:, symbols:, productions:, user_code:,
|
|
191
|
-
conversions:, warnings:, user_code_chunks: nil,
|
|
192
|
-
source_provenance: nil,
|
|
193
|
-
grammar_tests: [], recovery: nil, lexer: nil, mode: :default, starts: nil
|
|
194
|
+
conversions:, warnings:, user_code_chunks: nil,
|
|
195
|
+
source_provenance: nil, expect_rr: nil, parser_parameters: [], value_printers: [],
|
|
196
|
+
grammar_tests: [], recovery: nil, lexer: nil, mode: :default, starts: nil,
|
|
197
|
+
parser_contract: ParserContract.new)
|
|
198
|
+
initialize_current(
|
|
199
|
+
class_name: class_name, superclass: superclass, start: start, expect: expect, options: options,
|
|
200
|
+
symbols: symbols, productions: productions, user_code: user_code, conversions: conversions,
|
|
201
|
+
warnings: warnings, user_code_chunks: user_code_chunks,
|
|
202
|
+
source_provenance: source_provenance, expect_rr: expect_rr,
|
|
203
|
+
parser_parameters: parser_parameters, value_printers: value_printers, grammar_tests: grammar_tests,
|
|
204
|
+
recovery: recovery, lexer: lexer, mode: mode, starts: starts, parser_contract: parser_contract
|
|
205
|
+
)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# @rbs (class_name: String, superclass: String?, start: String, expect: Integer, options: grammar_options,
|
|
209
|
+
# symbols: Array[GrammarSymbol], productions: Array[Production], user_code: Hash[String, String],
|
|
210
|
+
# conversions: Hash[String, String], warnings: Array[grammar_warning], user_code_chunks: user_code_chunks?,
|
|
211
|
+
# source_provenance: source_provenance?, expect_rr: Integer?, parser_parameters: Array[parser_parameter],
|
|
212
|
+
# value_printers: Array[value_printer], grammar_tests: Array[grammar_test], recovery: recovery_policy?,
|
|
213
|
+
# lexer: Lexer?, mode: grammar_mode, starts: Array[String]?, parser_contract: ParserContract) -> void
|
|
214
|
+
def initialize_current(class_name:, superclass:, start:, expect:, options:, symbols:, productions:, user_code:,
|
|
215
|
+
conversions:, warnings:, user_code_chunks:, source_provenance:, expect_rr:,
|
|
216
|
+
parser_parameters:, value_printers:, grammar_tests:, recovery:, lexer:, mode:, starts:,
|
|
217
|
+
parser_contract:)
|
|
194
218
|
validate_mode(mode)
|
|
195
219
|
normalized_starts = validate_starts(start, starts, mode)
|
|
220
|
+
validate_current_metadata(parser_contract)
|
|
196
221
|
|
|
197
222
|
@class_name = class_name.freeze
|
|
198
223
|
@superclass = superclass&.freeze
|
|
@@ -214,14 +239,15 @@ module Ibex
|
|
|
214
239
|
validate_user_code_chunks
|
|
215
240
|
@conversions = IR.deep_freeze(conversions)
|
|
216
241
|
@warnings = IR.deep_freeze(warnings)
|
|
217
|
-
@schema_version =
|
|
242
|
+
@schema_version = SCHEMA_VERSION
|
|
218
243
|
@source_provenance = IR.deep_freeze(source_provenance)
|
|
219
|
-
@
|
|
244
|
+
@parser_contract = IR.deep_freeze(parser_contract)
|
|
220
245
|
@symbols_by_name = @symbols.to_h { |symbol| [symbol.name, symbol] }.freeze
|
|
221
246
|
@symbols_by_id = @symbols.to_h { |symbol| [symbol.id, symbol] }.freeze
|
|
222
247
|
freeze
|
|
223
248
|
end
|
|
224
249
|
# rubocop:enable Metrics/AbcSize, Metrics/ParameterLists
|
|
250
|
+
private :initialize_current
|
|
225
251
|
|
|
226
252
|
# @rbs (String name) -> GrammarSymbol?
|
|
227
253
|
def symbol(name) = @symbols_by_name[name]
|
|
@@ -232,14 +258,14 @@ module Ibex
|
|
|
232
258
|
# @rbs () -> Array[GrammarSymbol]
|
|
233
259
|
def nonterminals = @symbols.select(&:nonterminal?)
|
|
234
260
|
|
|
235
|
-
# @rbs () -> Hash[Symbol,
|
|
261
|
+
# @rbs () -> Hash[Symbol, Object?]
|
|
236
262
|
def to_h
|
|
237
263
|
value = { ibex_ir: "grammar", schema_version: @schema_version, class_name: @class_name, superclass: @superclass,
|
|
238
264
|
start: @start, expect: @expect, options: @options,
|
|
239
|
-
symbols: @symbols.map
|
|
240
|
-
productions: @productions.map
|
|
265
|
+
symbols: @symbols.map(&:to_h),
|
|
266
|
+
productions: @productions.map(&:to_h),
|
|
241
267
|
user_code: @user_code, conversions: @conversions,
|
|
242
|
-
warnings: @warnings } #: Hash[Symbol,
|
|
268
|
+
warnings: @warnings } #: Hash[Symbol, Object?]
|
|
243
269
|
append_optional_metadata(value)
|
|
244
270
|
value
|
|
245
271
|
end
|
|
@@ -262,30 +288,28 @@ module Ibex
|
|
|
262
288
|
values
|
|
263
289
|
end
|
|
264
290
|
|
|
265
|
-
# @rbs (Hash[Symbol,
|
|
291
|
+
# @rbs (Hash[Symbol, Object?] value) -> void
|
|
266
292
|
def append_optional_metadata(value)
|
|
267
293
|
append_parser_metadata(value)
|
|
268
294
|
append_recovery_metadata(value)
|
|
269
295
|
value[:user_code_chunks] = @user_code_chunks.transform_values { |chunks| chunks.map(&:to_h) } \
|
|
270
296
|
unless @user_code_chunks.empty?
|
|
271
|
-
return unless @schema_version >= 2
|
|
272
|
-
|
|
273
297
|
value[:source_provenance] = @source_provenance
|
|
274
|
-
value[:
|
|
298
|
+
value[:parser_contract] = @parser_contract.to_h
|
|
275
299
|
end
|
|
276
300
|
|
|
277
|
-
# @rbs (Hash[Symbol,
|
|
301
|
+
# @rbs (Hash[Symbol, Object?] value) -> void
|
|
278
302
|
def append_parser_metadata(value)
|
|
279
303
|
value[:expect_rr] = @expect_rr unless @expect_rr.nil?
|
|
280
304
|
value[:mode] = @mode if @mode == :extended
|
|
281
305
|
value[:starts] = @starts if @starts.length > 1
|
|
282
306
|
value[:params] = @parser_parameters unless @parser_parameters.empty?
|
|
283
307
|
value[:printers] = @value_printers unless @value_printers.empty?
|
|
284
|
-
value[:tests] = @grammar_tests unless @grammar_tests.empty?
|
|
285
|
-
value[:lexer] = @lexer.to_h if @lexer
|
|
308
|
+
value[:tests] = @grammar_tests unless @grammar_tests.empty?
|
|
309
|
+
value[:lexer] = @lexer.to_h if @lexer
|
|
286
310
|
end
|
|
287
311
|
|
|
288
|
-
# @rbs (Hash[Symbol,
|
|
312
|
+
# @rbs (Hash[Symbol, Object?] value) -> void
|
|
289
313
|
def append_recovery_metadata(value)
|
|
290
314
|
return if @recovery[:sync_tokens].empty? && @recovery[:on_error_reduce].empty?
|
|
291
315
|
|
|
@@ -300,6 +324,13 @@ module Ibex
|
|
|
300
324
|
raise Ibex::Error, "(ir):1:1: user-code chunks do not match the concatenated #{name} section"
|
|
301
325
|
end
|
|
302
326
|
end
|
|
327
|
+
|
|
328
|
+
# @rbs (ParserContract parser_contract) -> void
|
|
329
|
+
def validate_current_metadata(parser_contract)
|
|
330
|
+
return if parser_contract.is_a?(ParserContract)
|
|
331
|
+
|
|
332
|
+
raise ArgumentError, "parser_contract must be a ParserContract"
|
|
333
|
+
end
|
|
303
334
|
end
|
|
304
335
|
end
|
|
305
336
|
end
|
data/lib/ibex/ir/lexer_ir.rb
CHANGED
|
@@ -32,7 +32,7 @@ module Ibex
|
|
|
32
32
|
freeze
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
# @rbs () -> Hash[Symbol,
|
|
35
|
+
# @rbs () -> Hash[Symbol, lexer_rule_document_value]
|
|
36
36
|
def to_h
|
|
37
37
|
{
|
|
38
38
|
id: @id, state: @state, kind: @kind, token: @token, pattern: @pattern,
|
|
@@ -41,15 +41,15 @@ module Ibex
|
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
# Independently versioned lexer contract embedded by Grammar IR
|
|
44
|
+
# Independently versioned lexer contract embedded by the current Grammar IR.
|
|
45
45
|
class Lexer
|
|
46
46
|
attr_reader :states #: Array[String]
|
|
47
47
|
attr_reader :rules #: Array[LexerRule]
|
|
48
|
-
attr_reader :warnings #: Array[
|
|
48
|
+
attr_reader :warnings #: Array[lexer_warning]
|
|
49
49
|
attr_reader :schema_version #: Integer
|
|
50
50
|
attr_reader :source_provenance #: source_provenance?
|
|
51
51
|
|
|
52
|
-
# @rbs (states: Array[String], rules: Array[LexerRule], warnings: Array[
|
|
52
|
+
# @rbs (states: Array[String], rules: Array[LexerRule], warnings: Array[lexer_warning],
|
|
53
53
|
# ?schema_version: Integer, ?source_provenance: source_provenance?) -> void
|
|
54
54
|
def initialize(states:, rules:, warnings:, schema_version: LEXER_SCHEMA_VERSION, source_provenance: nil)
|
|
55
55
|
raise ArgumentError, "lexer states must start with INITIAL" unless states.first == "INITIAL"
|
|
@@ -63,7 +63,7 @@ module Ibex
|
|
|
63
63
|
freeze
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
-
# @rbs () -> Hash[Symbol,
|
|
66
|
+
# @rbs () -> Hash[Symbol, lexer_document_value]
|
|
67
67
|
def to_h
|
|
68
68
|
{
|
|
69
69
|
ibex_ir: "lexer", schema_version: @schema_version, initial_state: "INITIAL",
|