ibex 0.1.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 +89 -123
- data/docs/architecture.md +477 -31
- 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 +106 -0
- data/docs/cst.md +237 -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 +306 -0
- data/docs/direct-ielr-decision.md +120 -0
- data/docs/direct-multi-entry-decision.md +82 -0
- data/docs/editor-setup.md +26 -0
- 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 +114 -0
- data/docs/getting-started.md +80 -0
- data/docs/grammar-reference.md +629 -18
- 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 +56 -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 +45 -6
- data/docs/release-readiness.md +221 -0
- data/docs/repair-semantics.md +123 -0
- data/docs/runtime-abi-evolution.md +307 -0
- data/docs/stability.md +234 -0
- 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/examples/README.md +60 -0
- data/examples/calculator.y +44 -0
- data/examples/csv.y +32 -0
- data/examples/ini.y +70 -0
- data/examples/json.y +48 -0
- data/examples/tiny_language.y +75 -0
- data/lib/ibex/analysis/digraph.rb +128 -0
- data/lib/ibex/analysis/sets.rb +5 -4
- data/lib/ibex/analysis.rb +1 -0
- data/lib/ibex/artifact_set.rb +63 -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 +75 -0
- 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/counterexample_options.rb +6 -2
- data/lib/ibex/cli/coverage.rb +173 -0
- data/lib/ibex/cli/debug.rb +106 -0
- data/lib/ibex/cli/diagnostics.rb +136 -0
- data/lib/ibex/cli/documentation.rb +70 -0
- data/lib/ibex/cli/equiv.rb +169 -0
- data/lib/ibex/cli/error_messages.rb +184 -0
- data/lib/ibex/cli/explain.rb +85 -0
- data/lib/ibex/cli/fix.rb +203 -0
- data/lib/ibex/cli/formatting.rb +387 -0
- data/lib/ibex/cli/fuzz.rb +200 -0
- data/lib/ibex/cli/fuzz_regressions.rb +145 -0
- data/lib/ibex/cli/generation_artifacts.rb +189 -0
- data/lib/ibex/cli/generation_error_messages.rb +39 -0
- data/lib/ibex/cli/grammar_tests.rb +140 -0
- data/lib/ibex/cli/ir_tools.rb +128 -0
- data/lib/ibex/cli/lsp.rb +33 -0
- data/lib/ibex/cli/outputs.rb +133 -23
- data/lib/ibex/cli/racc_migration.rb +87 -0
- data/lib/ibex/cli/reduce.rb +202 -0
- data/lib/ibex/cli/reduce_reporting.rb +71 -0
- data/lib/ibex/cli/samples.rb +118 -0
- data/lib/ibex/cli/verify.rb +116 -0
- data/lib/ibex/cli/watch.rb +104 -0
- data/lib/ibex/cli.rb +825 -55
- data/lib/ibex/codegen/action_locations.rb +103 -0
- data/lib/ibex/codegen/action_method_source.rb +209 -0
- data/lib/ibex/codegen/action_source.rb +119 -0
- data/lib/ibex/codegen/ambiguity.rb +174 -0
- data/lib/ibex/codegen/cst_metadata.rb +171 -0
- data/lib/ibex/codegen/documentation.rb +170 -0
- data/lib/ibex/codegen/explain.rb +380 -0
- data/lib/ibex/codegen/generated_action_abi.rb +293 -0
- data/lib/ibex/codegen/html.rb +94 -10
- data/lib/ibex/codegen/mermaid.rb +43 -0
- data/lib/ibex/codegen/railroad.rb +197 -0
- data/lib/ibex/codegen/railroad_documentation.rb +59 -0
- data/lib/ibex/codegen/rbs.rb +331 -2
- data/lib/ibex/codegen/report.rb +67 -15
- data/lib/ibex/codegen/ruby.rb +305 -66
- data/lib/ibex/codegen/ruby_actions.rb +146 -0
- data/lib/ibex/codegen/ruby_ast.rb +121 -0
- data/lib/ibex/codegen/ruby_error_messages.rb +28 -0
- data/lib/ibex/codegen/ruby_lexer.rb +83 -0
- data/lib/ibex/codegen/ruby_syntax.rb +96 -0
- data/lib/ibex/codegen/ruby_table_metadata.rb +57 -0
- data/lib/ibex/codegen/ruby_value_printers.rb +56 -0
- data/lib/ibex/codegen/symbol_labels.rb +1 -1
- 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 +198 -0
- data/lib/ibex/coverage/event_stream.rb +103 -0
- data/lib/ibex/coverage/report.rb +267 -0
- data/lib/ibex/coverage/runtime_event_validator.rb +169 -0
- data/lib/ibex/coverage.rb +13 -0
- 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/error_messages/parser.rb +159 -0
- data/lib/ibex/error_messages/parser_v2.rb +198 -0
- data/lib/ibex/error_messages/renderer.rb +65 -0
- data/lib/ibex/error_messages/sentence_search.rb +196 -0
- data/lib/ibex/error_messages/update.rb +169 -0
- data/lib/ibex/error_messages.rb +165 -0
- data/lib/ibex/fix.rb +557 -0
- data/lib/ibex/frontend/ast.rb +166 -7
- data/lib/ibex/frontend/bootstrap_parser.rb +40 -4
- data/lib/ibex/frontend/diagnostic.rb +81 -0
- data/lib/ibex/frontend/diagnostic_recovery.rb +268 -0
- data/lib/ibex/frontend/dsl.rb +66 -7
- data/lib/ibex/frontend/formatter.rb +453 -0
- data/lib/ibex/frontend/generated_parser.rb +644 -190
- data/lib/ibex/frontend/generated_parser_base.rb +170 -32
- data/lib/ibex/frontend/generated_parser_includes.rb +51 -0
- data/lib/ibex/frontend/generated_parser_metadata.rb +61 -0
- data/lib/ibex/frontend/generated_parser_parameters.rb +60 -0
- data/lib/ibex/frontend/generation.rb +33 -0
- data/lib/ibex/frontend/lexer.rb +162 -10
- data/lib/ibex/frontend/lexer_recovery.rb +84 -0
- data/lib/ibex/frontend/parser/declarations.rb +262 -11
- data/lib/ibex/frontend/parser/parameters.rb +82 -0
- data/lib/ibex/frontend/parser/rules.rb +43 -6
- data/lib/ibex/frontend/parser.rb +182 -4
- data/lib/ibex/frontend/parser_configuration_support.rb +56 -0
- data/lib/ibex/frontend/regenerator.rb +27 -1
- data/lib/ibex/frontend/resolution.rb +70 -0
- data/lib/ibex/frontend/resolver.rb +217 -0
- data/lib/ibex/frontend/rule_documentation.rb +104 -0
- data/lib/ibex/frontend/source_cursor.rb +133 -9
- data/lib/ibex/frontend/source_document.rb +229 -0
- data/lib/ibex/frontend/source_loader.rb +150 -0
- data/lib/ibex/frontend/source_span.rb +89 -0
- data/lib/ibex/frontend/token_adapter/declaration_document_state.rb +47 -0
- data/lib/ibex/frontend/token_adapter/declaration_lexer_state.rb +83 -0
- data/lib/ibex/frontend/token_adapter/declaration_state.rb +244 -22
- data/lib/ibex/frontend/token_adapter/delimiter_tracker.rb +8 -2
- data/lib/ibex/frontend/token_adapter/rule_state.rb +60 -2
- data/lib/ibex/frontend/token_adapter.rb +18 -3
- data/lib/ibex/frontend.rb +14 -2
- data/lib/ibex/fuzz.rb +219 -0
- data/lib/ibex/generation_input.rb +57 -0
- data/lib/ibex/generation_manifest.rb +211 -0
- data/lib/ibex/generation_transaction.rb +261 -0
- data/lib/ibex/generation_transaction_recovery.rb +109 -0
- data/lib/ibex/generation_transaction_validation.rb +196 -0
- data/lib/ibex/grammar_tests.rb +206 -0
- data/lib/ibex/ir/automaton_ir.rb +86 -11
- data/lib/ibex/ir/grammar_ir.rb +170 -26
- data/lib/ibex/ir/lexer_ir.rb +76 -0
- data/lib/ibex/ir/parser_contract.rb +135 -0
- data/lib/ibex/ir/serialize.rb +268 -50
- data/lib/ibex/ir/validator/automaton.rb +375 -0
- data/lib/ibex/ir/validator/base.rb +147 -0
- data/lib/ibex/ir/validator/grammar.rb +634 -0
- data/lib/ibex/ir/validator/lexer.rb +113 -0
- data/lib/ibex/ir/validator.rb +63 -0
- data/lib/ibex/ir.rb +71 -5
- data/lib/ibex/lalr/build_metrics.rb +71 -0
- data/lib/ibex/lalr/builder.rb +514 -52
- data/lib/ibex/lalr/conflict.rb +1 -0
- data/lib/ibex/lalr/conflict_search.rb +26 -9
- data/lib/ibex/lalr/counterexample.rb +38 -18
- data/lib/ibex/lalr/direct_lookaheads.rb +289 -0
- 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 +166 -0
- 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/on_error_reductions.rb +74 -0
- data/lib/ibex/lalr/unreachable_states.rb +80 -0
- data/lib/ibex/lalr.rb +59 -1
- data/lib/ibex/location.rb +129 -0
- data/lib/ibex/lsp/document_handlers.rb +68 -0
- data/lib/ibex/lsp/document_store.rb +264 -0
- data/lib/ibex/lsp/document_store_diagnostics.rb +44 -0
- data/lib/ibex/lsp/document_store_validation.rb +61 -0
- data/lib/ibex/lsp/initialization_handlers.rb +80 -0
- data/lib/ibex/lsp/navigation_handlers.rb +70 -0
- data/lib/ibex/lsp/parser_configuration_assistance.rb +149 -0
- data/lib/ibex/lsp/position_codec.rb +113 -0
- data/lib/ibex/lsp/protocol_error.rb +33 -0
- data/lib/ibex/lsp/request_handlers.rb +46 -0
- data/lib/ibex/lsp/request_support.rb +94 -0
- data/lib/ibex/lsp/server.rb +148 -0
- data/lib/ibex/lsp/symbol_index.rb +241 -0
- data/lib/ibex/lsp/symbol_index_builder.rb +277 -0
- data/lib/ibex/lsp/symbol_index_precedence_references.rb +44 -0
- data/lib/ibex/lsp/symbol_index_source_queries.rb +61 -0
- data/lib/ibex/lsp/symbol_occurrence.rb +23 -0
- data/lib/ibex/lsp/transport.rb +128 -0
- data/lib/ibex/lsp/workspace.rb +128 -0
- data/lib/ibex/lsp/workspace_analyzer.rb +199 -0
- data/lib/ibex/lsp.rb +33 -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 +142 -7
- data/lib/ibex/normalize/diagnostics.rb +94 -24
- data/lib/ibex/normalize/expander.rb +64 -59
- data/lib/ibex/normalize/expression.rb +63 -40
- data/lib/ibex/normalize/grammar_builder.rb +26 -0
- data/lib/ibex/normalize/inline_expansion.rb +465 -0
- data/lib/ibex/normalize/inline_validation.rb +174 -0
- data/lib/ibex/normalize/lexer.rb +131 -0
- data/lib/ibex/normalize/named_references.rb +60 -0
- data/lib/ibex/normalize/nodes.rb +46 -0
- data/lib/ibex/normalize/parameter_ebnf_lowering.rb +70 -0
- data/lib/ibex/normalize/parameter_lowering.rb +143 -0
- data/lib/ibex/normalize/parameter_substitution.rb +125 -0
- data/lib/ibex/normalize/parameter_validation.rb +140 -0
- data/lib/ibex/normalize/parameters.rb +226 -0
- data/lib/ibex/normalize/parser_configuration.rb +70 -0
- data/lib/ibex/normalize/recovery_declarations.rb +84 -0
- data/lib/ibex/normalize.rb +172 -17
- data/lib/ibex/racc_migration/checker.rb +122 -0
- data/lib/ibex/racc_migration/harness.rb +177 -0
- data/lib/ibex/racc_migration/report.rb +97 -0
- data/lib/ibex/racc_migration.rb +12 -0
- data/lib/ibex/rake_task.rb +116 -0
- data/lib/ibex/samples.rb +216 -0
- 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 +55 -0
- data/lib/ibex/table_simulation/simulator.rb +253 -0
- data/lib/ibex/table_simulation/step.rb +62 -0
- data/lib/ibex/table_simulation/text.rb +31 -0
- data/lib/ibex/table_simulation.rb +13 -0
- data/lib/ibex/tables.rb +22 -69
- 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 +181 -0
- data/lib/ibex/watch/source_snapshot.rb +98 -0
- data/lib/ibex/watch.rb +11 -0
- data/lib/ibex.rb +35 -1
- data/schema/automaton-ir-definitions.schema.json +401 -0
- data/schema/automaton-ir.schema.json +65 -0
- data/schema/benchmark-v1.schema.json +212 -0
- data/schema/benchmark-v2.schema.json +61 -0
- 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/cst-v1.json +170 -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/error-ux-v1.schema.json +258 -0
- data/schema/explain-v1.schema.json +495 -0
- 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/frontend-diagnostics-v1.schema.json +154 -0
- data/schema/fuzz-regression-v1.schema.json +79 -0
- data/schema/fuzz-v1.schema.json +114 -0
- data/schema/generation-manifest-v1.schema.json +115 -0
- data/schema/grammar-ir-extensions.schema.json +734 -0
- data/schema/grammar-ir-foundation.schema.json +426 -0
- data/schema/grammar-ir.schema.json +271 -0
- data/schema/ielr-benchmark-v1.schema.json +85 -0
- data/schema/lexer-ir-v1.schema.json +215 -0
- data/schema/lexer-profile-v1.schema.json +491 -0
- data/schema/metrics-v1.schema.json +60 -0
- data/schema/migration-check-v1.schema.json +60 -0
- data/schema/performance-comparison-v1.schema.json +395 -0
- data/schema/public-performance-comparison-v1.schema.json +506 -0
- data/schema/public-performance-profile-v1.schema.json +360 -0
- data/schema/reduce-v1.schema.json +22 -0
- data/schema/reduce-v2.schema.json +63 -0
- data/schema/runtime-coverage-v1.schema.json +86 -0
- data/schema/runtime-event-v1.schema.json +308 -0
- data/schema/table-artifact-v1.schema.json +377 -0
- data/schema/table-simulation-v1.schema.json +70 -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/artifact_set.rbs +37 -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 +28 -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/counterexample_options.rbs +2 -0
- data/sig/ibex/cli/coverage.rbs +53 -0
- data/sig/ibex/cli/debug.rbs +28 -0
- data/sig/ibex/cli/diagnostics.rbs +51 -0
- data/sig/ibex/cli/documentation.rbs +29 -0
- data/sig/ibex/cli/equiv.rbs +49 -0
- data/sig/ibex/cli/error_messages.rbs +63 -0
- data/sig/ibex/cli/explain.rbs +31 -0
- data/sig/ibex/cli/fix.rbs +53 -0
- data/sig/ibex/cli/formatting.rbs +107 -0
- data/sig/ibex/cli/fuzz.rbs +47 -0
- data/sig/ibex/cli/fuzz_regressions.rbs +40 -0
- data/sig/ibex/cli/generation_artifacts.rbs +69 -0
- data/sig/ibex/cli/generation_error_messages.rbs +19 -0
- data/sig/ibex/cli/grammar_tests.rbs +48 -0
- data/sig/ibex/cli/ir_tools.rbs +39 -0
- data/sig/ibex/cli/lsp.rbs +14 -0
- data/sig/ibex/cli/outputs.rbs +26 -3
- data/sig/ibex/cli/racc_migration.rbs +30 -0
- data/sig/ibex/cli/reduce.rbs +60 -0
- data/sig/ibex/cli/reduce_reporting.rbs +27 -0
- data/sig/ibex/cli/samples.rbs +38 -0
- data/sig/ibex/cli/verify.rbs +28 -0
- data/sig/ibex/cli/watch.rbs +43 -0
- data/sig/ibex/cli.rbs +182 -9
- data/sig/ibex/codegen/action_locations.rbs +45 -0
- data/sig/ibex/codegen/action_method_source.rbs +65 -0
- data/sig/ibex/codegen/action_source.rbs +50 -0
- data/sig/ibex/codegen/ambiguity.rbs +60 -0
- data/sig/ibex/codegen/cst_metadata.rbs +59 -0
- data/sig/ibex/codegen/documentation.rbs +50 -0
- data/sig/ibex/codegen/explain.rbs +105 -0
- data/sig/ibex/codegen/generated_action_abi.rbs +105 -0
- data/sig/ibex/codegen/html.rbs +18 -2
- data/sig/ibex/codegen/mermaid.rbs +16 -0
- data/sig/ibex/codegen/railroad.rbs +82 -0
- data/sig/ibex/codegen/railroad_documentation.rbs +31 -0
- data/sig/ibex/codegen/rbs.rbs +86 -4
- data/sig/ibex/codegen/report.rbs +16 -8
- data/sig/ibex/codegen/ruby.rbs +105 -28
- data/sig/ibex/codegen/ruby_actions.rbs +54 -0
- data/sig/ibex/codegen/ruby_ast.rbs +34 -0
- data/sig/ibex/codegen/ruby_error_messages.rbs +16 -0
- data/sig/ibex/codegen/ruby_lexer.rbs +25 -0
- data/sig/ibex/codegen/ruby_syntax.rbs +27 -0
- data/sig/ibex/codegen/ruby_table_metadata.rbs +26 -0
- data/sig/ibex/codegen/ruby_value_printers.rbs +28 -0
- 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 +78 -0
- data/sig/ibex/coverage/event_stream.rbs +44 -0
- data/sig/ibex/coverage/report.rbs +102 -0
- data/sig/ibex/coverage/runtime_event_validator.rbs +70 -0
- data/sig/ibex/coverage.rbs +7 -0
- 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/error_messages/parser.rbs +58 -0
- data/sig/ibex/error_messages/parser_v2.rbs +67 -0
- data/sig/ibex/error_messages/renderer.rbs +23 -0
- data/sig/ibex/error_messages/sentence_search.rbs +80 -0
- data/sig/ibex/error_messages/update.rbs +43 -0
- data/sig/ibex/error_messages.rbs +85 -0
- data/sig/ibex/fix.rbs +138 -0
- data/sig/ibex/frontend/ast.rbs +237 -22
- data/sig/ibex/frontend/bootstrap_parser.rbs +13 -0
- data/sig/ibex/frontend/diagnostic.rbs +53 -0
- data/sig/ibex/frontend/diagnostic_recovery.rbs +98 -0
- data/sig/ibex/frontend/dsl.rbs +33 -4
- data/sig/ibex/frontend/formatter.rbs +143 -0
- data/sig/ibex/frontend/generated_parser.rbs +228 -68
- data/sig/ibex/frontend/generated_parser_base.rbs +65 -12
- data/sig/ibex/frontend/generated_parser_includes.rbs +23 -0
- data/sig/ibex/frontend/generated_parser_metadata.rbs +23 -0
- data/sig/ibex/frontend/generated_parser_parameters.rbs +24 -0
- data/sig/ibex/frontend/generation.rbs +6 -0
- data/sig/ibex/frontend/lexer.rbs +49 -2
- data/sig/ibex/frontend/lexer_recovery.rbs +25 -0
- data/sig/ibex/frontend/parser/declarations.rbs +57 -0
- data/sig/ibex/frontend/parser/parameters.rbs +28 -0
- data/sig/ibex/frontend/parser/rules.rbs +3 -0
- data/sig/ibex/frontend/parser.rbs +66 -0
- data/sig/ibex/frontend/parser_configuration_support.rbs +27 -0
- data/sig/ibex/frontend/regenerator.rbs +11 -0
- data/sig/ibex/frontend/resolution.rbs +34 -0
- data/sig/ibex/frontend/resolver.rbs +91 -0
- data/sig/ibex/frontend/rule_documentation.rbs +42 -0
- data/sig/ibex/frontend/source_cursor.rbs +38 -5
- data/sig/ibex/frontend/source_document.rbs +119 -0
- data/sig/ibex/frontend/source_loader.rbs +66 -0
- data/sig/ibex/frontend/source_span.rbs +56 -0
- data/sig/ibex/frontend/token_adapter/declaration_document_state.rbs +21 -0
- data/sig/ibex/frontend/token_adapter/declaration_lexer_state.rbs +27 -0
- data/sig/ibex/frontend/token_adapter/declaration_state.rbs +83 -3
- data/sig/ibex/frontend/token_adapter/rule_state.rbs +20 -0
- data/sig/ibex/frontend/token_adapter.rbs +11 -2
- data/sig/ibex/frontend.rbs +1 -1
- data/sig/ibex/fuzz.rbs +71 -0
- data/sig/ibex/generation_input.rbs +37 -0
- data/sig/ibex/generation_manifest.rbs +70 -0
- data/sig/ibex/generation_transaction.rbs +82 -0
- data/sig/ibex/generation_transaction_recovery.rbs +36 -0
- data/sig/ibex/generation_transaction_validation.rbs +65 -0
- data/sig/ibex/grammar_tests.rbs +93 -0
- data/sig/ibex/ir/automaton_ir.rbs +35 -10
- data/sig/ibex/ir/grammar_ir.rbs +96 -22
- data/sig/ibex/ir/lexer_ir.rbs +57 -0
- data/sig/ibex/ir/parser_contract.rbs +69 -0
- data/sig/ibex/ir/serialize.rbs +75 -23
- data/sig/ibex/ir/validator/automaton.rbs +112 -0
- data/sig/ibex/ir/validator/base.rbs +69 -0
- data/sig/ibex/ir/validator/grammar.rbs +195 -0
- data/sig/ibex/ir/validator/lexer.rbs +37 -0
- data/sig/ibex/ir/validator.rbs +16 -0
- data/sig/ibex/ir.rbs +45 -5
- data/sig/ibex/lalr/build_metrics.rbs +60 -0
- data/sig/ibex/lalr/builder.rbs +150 -19
- data/sig/ibex/lalr/conflict_search.rbs +12 -5
- data/sig/ibex/lalr/counterexample.rbs +20 -14
- data/sig/ibex/lalr/direct_lookaheads.rbs +93 -0
- 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 +71 -0
- 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/on_error_reductions.rbs +22 -0
- data/sig/ibex/lalr/unreachable_states.rbs +25 -0
- data/sig/ibex/lalr.rbs +17 -1
- data/sig/ibex/location.rbs +67 -0
- data/sig/ibex/lsp/document_handlers.rbs +24 -0
- data/sig/ibex/lsp/document_store.rbs +94 -0
- data/sig/ibex/lsp/document_store_diagnostics.rbs +20 -0
- data/sig/ibex/lsp/document_store_validation.rbs +26 -0
- data/sig/ibex/lsp/initialization_handlers.rbs +30 -0
- data/sig/ibex/lsp/navigation_handlers.rbs +33 -0
- data/sig/ibex/lsp/parser_configuration_assistance.rbs +49 -0
- data/sig/ibex/lsp/position_codec.rbs +44 -0
- data/sig/ibex/lsp/protocol_error.rbs +32 -0
- data/sig/ibex/lsp/request_handlers.rbs +26 -0
- data/sig/ibex/lsp/request_support.rbs +40 -0
- data/sig/ibex/lsp/server.rbs +55 -0
- data/sig/ibex/lsp/symbol_index.rbs +77 -0
- data/sig/ibex/lsp/symbol_index_builder.rbs +88 -0
- data/sig/ibex/lsp/symbol_index_precedence_references.rbs +18 -0
- data/sig/ibex/lsp/symbol_index_source_queries.rbs +26 -0
- data/sig/ibex/lsp/symbol_occurrence.rbs +31 -0
- data/sig/ibex/lsp/transport.rbs +47 -0
- data/sig/ibex/lsp/workspace.rbs +42 -0
- data/sig/ibex/lsp/workspace_analyzer.rbs +69 -0
- data/sig/ibex/lsp.rbs +7 -0
- data/sig/ibex/messages.rbs +26 -0
- data/sig/ibex/metrics.rbs +50 -0
- data/sig/ibex/normalize/declarations.rbs +31 -0
- data/sig/ibex/normalize/diagnostics.rbs +13 -4
- data/sig/ibex/normalize/expander.rbs +22 -16
- data/sig/ibex/normalize/expression.rbs +11 -9
- data/sig/ibex/normalize/grammar_builder.rbs +11 -0
- data/sig/ibex/normalize/inline_expansion.rbs +129 -0
- data/sig/ibex/normalize/inline_validation.rbs +40 -0
- data/sig/ibex/normalize/lexer.rbs +37 -0
- data/sig/ibex/normalize/named_references.rbs +20 -0
- data/sig/ibex/normalize/nodes.rbs +14 -0
- data/sig/ibex/normalize/parameter_ebnf_lowering.rbs +33 -0
- data/sig/ibex/normalize/parameter_lowering.rbs +35 -0
- data/sig/ibex/normalize/parameter_substitution.rbs +42 -0
- data/sig/ibex/normalize/parameter_validation.rbs +44 -0
- data/sig/ibex/normalize/parameters.rbs +51 -0
- data/sig/ibex/normalize/parser_configuration.rbs +23 -0
- data/sig/ibex/normalize/recovery_declarations.rbs +24 -0
- data/sig/ibex/normalize.rbs +129 -18
- data/sig/ibex/racc_migration/checker.rbs +36 -0
- data/sig/ibex/racc_migration/harness.rbs +16 -0
- data/sig/ibex/racc_migration/report.rbs +55 -0
- data/sig/ibex/racc_migration.rbs +8 -0
- data/sig/ibex/rake_task.rbs +51 -0
- data/sig/ibex/samples.rbs +60 -0
- 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 +36 -0
- data/sig/ibex/table_simulation/simulator.rbs +98 -0
- data/sig/ibex/table_simulation/step.rbs +42 -0
- data/sig/ibex/table_simulation/text.rbs +14 -0
- data/sig/ibex/table_simulation.rbs +7 -0
- data/sig/ibex/tables.rbs +10 -35
- 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 +58 -0
- data/sig/ibex/watch/source_snapshot.rbs +46 -0
- data/sig/ibex/watch.rbs +7 -0
- data/sig/ibex.rbs +2 -0
- metadata +524 -19
- data/.rubocop.yml +0 -43
- data/CHANGELOG.md +0 -30
- data/Rakefile +0 -25
- data/Steepfile +0 -10
- data/docs/compat-notes.md +0 -37
- data/docs/lexer-coverage.md +0 -14
- data/docs/phase10-extensions.md +0 -27
- data/gemfiles/Gemfile +0 -7
- data/gemfiles/Gemfile.lock +0 -98
- data/lib/ibex/frontend/grammar.y +0 -156
- data/lib/ibex/runtime/parser.rb +0 -360
- data/lib/ibex/runtime.rb +0 -8
- data/sig/ibex/runtime/parser.rbs +0 -167
- data/sig/ibex/runtime.rbs +0 -6
data/docs/architecture.md
CHANGED
|
@@ -1,28 +1,258 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Architecture
|
|
3
|
+
description: Ibex's grammar, IR, parser construction, runtime, and verification boundaries.
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# Architecture and IR schemas
|
|
2
7
|
|
|
3
|
-
Ibex keeps syntax, grammar meaning, automaton construction, and output concerns behind two
|
|
8
|
+
Ibex keeps syntax, grammar meaning, automaton construction, and output concerns behind two immutable current contracts.
|
|
4
9
|
|
|
5
10
|
```text
|
|
6
|
-
.y
|
|
7
|
-
Ruby DSL
|
|
11
|
+
.y root/fragments -> Frontend Lexer/CST -> self-hosted LR Parser -> canonical Resolver ─┐
|
|
12
|
+
Ruby DSL ───────────────────────────────────────────────────────┴─> Grammar AST -> Normalizer -> Grammar IR
|
|
13
|
+
| |
|
|
14
|
+
| Lexer IR v1
|
|
8
15
|
|
|
|
9
|
-
|
|
16
|
+
set analysis
|
|
10
17
|
|
|
|
11
|
-
SLR/LALR/LR1 Builder -> Automaton IR
|
|
18
|
+
SLR/LALR/IELR/LR1 Builder -> Automaton IR
|
|
12
19
|
|
|
|
13
|
-
|
|
20
|
+
Ruby/RBS/action-shadow generators / report / DOT / Mermaid / HTML / counterexamples
|
|
14
21
|
```
|
|
15
22
|
|
|
16
23
|
Frontend changes stop at the Normalizer. Algorithm strategies consume Grammar IR and produce identical Automaton IR shapes.
|
|
17
24
|
Outputs consume Automaton IR and never call builder internals. The CLI only connects stages and supports JSON resumption.
|
|
18
25
|
|
|
26
|
+
IELR has two construction strategies. The conservative `partition` strategy
|
|
27
|
+
builds canonical LR(1) and partitions compatible isocores. The opt-in `direct`
|
|
28
|
+
strategy works from LR(0), goto-follow closures, lane annotations, and targeted
|
|
29
|
+
state splitting before rerunning lookahead propagation. Both use the shared
|
|
30
|
+
conflict resolver and downstream Automaton IR pipeline. See the [IELR guide](ielr.md).
|
|
31
|
+
|
|
32
|
+
## Execution trust boundary
|
|
33
|
+
|
|
34
|
+
`syntax-only` means that the LR runtime suppresses parser production actions.
|
|
35
|
+
It does not mean that no application Ruby executes.
|
|
36
|
+
|
|
37
|
+
| Execution path | Parser production actions | Generated lexer actions | User `header` / `inner` / `footer` | Trust |
|
|
38
|
+
| --- | --- | --- | --- | --- |
|
|
39
|
+
| Grammar parse/normalize, format, LSP, reports, conflict/diff/equiv/verify/debug, internal fuzz | No | No | No | Nonexecuting without an external-command option |
|
|
40
|
+
| Generated-lexer semantic: `parse`, `lex(...).do_parse`, `parse_with_syntax(source)` | Yes | Yes | May execute when the generated file loads | Trusted application code; not a sandbox |
|
|
41
|
+
| Handwritten pull semantic: `do_parse`, no-argument `parse_with_syntax` | Yes | No | May execute when the generated file loads | Trusted application code; not a sandbox |
|
|
42
|
+
| Caller-fed semantic: `yyparse`, `push` / `finish` | Yes | No | May execute when the generated file loads | Trusted application code; not a sandbox |
|
|
43
|
+
| Generated syntax-only parse | No | Yes | May execute when the generated file loads | Trusted application code; not a sandbox |
|
|
44
|
+
| Future safe syntax profile | No | Declarative built-ins only | No | Nonexecuting profile; not currently available |
|
|
45
|
+
|
|
46
|
+
Static paths operate on source, Grammar IR, Lexer IR, Automaton IR, or parser
|
|
47
|
+
tables without requiring the generated application parser. Parser actions,
|
|
48
|
+
lexer actions, conversions, and user sections remain opaque data on those
|
|
49
|
+
paths. Code generation may emit source that compiles them when the artifact is
|
|
50
|
+
loaded, but the generator does not load that artifact.
|
|
51
|
+
|
|
52
|
+
The static guarantee excludes explicit external-command options.
|
|
53
|
+
`ibex fuzz --against=COMMAND` and `ibex reduce --command=COMMAND` spawn the
|
|
54
|
+
supplied executable and may run arbitrary application code with host permissions.
|
|
55
|
+
Subprocess resource limits and process-group cleanup are not sandboxes and do
|
|
56
|
+
not confine side effects.
|
|
57
|
+
|
|
58
|
+
Semantic runtime entry points execute committed parser production actions.
|
|
59
|
+
Generated lexer actions execute only when tokens are pulled through
|
|
60
|
+
`GeneratedLexer#next_token`; handwritten `next_token`, `yyparse`, and
|
|
61
|
+
`push` / `finish` paths do not invoke that lexer. Syntax-only entry points
|
|
62
|
+
suppress parser actions but still use the generated lexer to emit tokens,
|
|
63
|
+
convert values, and mutate lexer state. Every generated runtime path crosses
|
|
64
|
+
the trusted application boundary because loading the generated Ruby file may
|
|
65
|
+
execute arbitrary user sections. Resource budgets and process-isolation
|
|
66
|
+
building blocks do not make those paths sandboxes.
|
|
67
|
+
|
|
68
|
+
A future profile for untrusted syntax work must use data-only parser tables, a
|
|
69
|
+
declarative lexer whose operations are restricted to built-ins, no parser
|
|
70
|
+
actions, no arbitrary conversions, and no `header`, `inner`, or `footer`
|
|
71
|
+
sections. The current generated parser API must not be described as that
|
|
72
|
+
profile.
|
|
73
|
+
|
|
74
|
+
An optional root-only `lexer` declaration normalizes to the independently versioned
|
|
75
|
+
Lexer IR and its flat rule list, which are embedded unchanged in the current Grammar IR.
|
|
76
|
+
records state, declaration id, pattern source/options, action, and provenance;
|
|
77
|
+
`--emit=lexer-ir` exposes the same document. Code generation compiles every
|
|
78
|
+
pattern with an internal current-position anchor and emits immutable,
|
|
79
|
+
state-indexed rules. Per-parser mutable input, position, emission, and state
|
|
80
|
+
stacks live in `Runtime::GeneratedLexer`, never in the tables. See
|
|
81
|
+
[ADR 0014](decisions/0014-versioned-generated-lexer.md).
|
|
82
|
+
|
|
83
|
+
`pragma cst` remains an optional current Grammar IR flag. Regenerated format-v6
|
|
84
|
+
tables add deterministic kind and normalized slot metadata. `Runtime::Parser`
|
|
85
|
+
builds a pure-syntax Green entry for every shift and reduction on a stack
|
|
86
|
+
parallel to the semantic stack, so tree shape no longer depends on semantic
|
|
87
|
+
actions. Generated lexer skips become token-owned trivia. Parser failure,
|
|
88
|
+
repair, and lexer failure remain explicit and lossless. See
|
|
89
|
+
[ADR 0016](decisions/0016-red-green-concrete-syntax.md) and the
|
|
90
|
+
[CST guide](cst.md). Batch CST, typed views, editing, and serialization form
|
|
91
|
+
the Stable v1 contract. The runtime accepts structured CST metadata only in
|
|
92
|
+
the current format and rejects older CST tables before reading input; see
|
|
93
|
+
[ADR 0008](decisions/0008-versioned-runtime-package-boundary.md).
|
|
94
|
+
|
|
95
|
+
## Red/Green CST v2
|
|
96
|
+
|
|
97
|
+
Green nodes and tokens contain no parents, source objects, absolute positions,
|
|
98
|
+
semantic values, or parser states. Their integer kinds, binary text, trivia,
|
|
99
|
+
flags, widths, children, and descendant counts are immutable and
|
|
100
|
+
Ractor-shareable. A session-owned `NodeCache` interns unannotated values. Lazy
|
|
101
|
+
Red wrappers add occurrence-specific parent, index, offset, span, location, and
|
|
102
|
+
typed-field navigation. The root is `source_file(start, EOF)`, and
|
|
103
|
+
`to_source` is byte exact for the `leading` and `balanced` trivia policies.
|
|
104
|
+
|
|
105
|
+
Generated `Parser::Syntax::<Name>` classes are typed views over Red nodes using
|
|
106
|
+
the same normalized `@node` metadata as Data AST generation. Persistent edits
|
|
107
|
+
replace one Green occurrence and copy its ancestor path; rewriters, batched
|
|
108
|
+
editors, annotations, and identity-skipping text diffing share that mechanism.
|
|
109
|
+
See [ADR 0017](decisions/0017-persistent-syntax-artifacts.md).
|
|
110
|
+
|
|
111
|
+
`ibex_cst` schema v1 serializes the Green root, kind metadata, compatibility
|
|
112
|
+
counts, and optional preorder parser memo independently of Grammar IR.
|
|
113
|
+
Validation reconstructs every derived width, flag, and descendant count.
|
|
114
|
+
Non-UTF-8 bytes use canonical Base64. See
|
|
115
|
+
[ADR 0017](decisions/0017-persistent-syntax-artifacts.md).
|
|
116
|
+
|
|
117
|
+
Incremental sessions are syntax-only: parser production actions do not run,
|
|
118
|
+
but generated lexer actions do. The generated lexer first validates token/state
|
|
119
|
+
resynchronization. `Blender`
|
|
120
|
+
then offers either a fresh token or an old Green nonterminal to the LR driver.
|
|
121
|
+
A subtree is pushed directly through `goto` only when damage, recorded
|
|
122
|
+
left-state, follow-token identity, error flags, and positive width satisfy the
|
|
123
|
+
conservative reuse proof. Token and parse memos remain preorder/occurrence
|
|
124
|
+
state owned by one session; resource exhaustion falls back to the fresh token
|
|
125
|
+
stream. See [ADR 0018](decisions/0018-conservative-incremental-syntax-reuse.md).
|
|
126
|
+
|
|
127
|
+
`Runtime::SyntaxSession` is a thin generated-language service boundary over
|
|
128
|
+
that same engine. Current generated classes expose only
|
|
129
|
+
`:trusted_application_code`, and callers must explicitly acknowledge that
|
|
130
|
+
profile because lexer actions still execute. Immutable operation snapshots add
|
|
131
|
+
expected-token and reuse/fallback evidence plus cooperative cancellation and
|
|
132
|
+
service bounds. The façade belongs to `ibex-runtime`; it defines neither LSP
|
|
133
|
+
nor workspace semantics. Its additive `repair` operation projects bounded
|
|
134
|
+
syntax repairs into byte edits and fresh syntax results without exposing
|
|
135
|
+
semantic values or invoking application repair callbacks. See
|
|
136
|
+
[ADR 0019](decisions/0019-runtime-syntax-session-boundary.md).
|
|
137
|
+
|
|
138
|
+
Alternative-level `@node` declarations are preserved in the current Grammar IR
|
|
139
|
+
production metadata. Runtime Ruby, static action-shadow Ruby, and generated
|
|
140
|
+
RBS all derive Data node classes and Visitor/Listener hooks from that same
|
|
141
|
+
metadata; action source is never inspected to infer a shape. Symbol semantic
|
|
142
|
+
types and fully annotated nonterminals supply field types.
|
|
143
|
+
|
|
19
144
|
The text frontend's canonical syntax is `lib/ibex/frontend/grammar.y`. Ibex generates and commits
|
|
20
145
|
`lib/ibex/frontend/generated_parser.rb`; the public `Frontend::Parser` always delegates to that class. Lexer `Token` objects remain
|
|
21
146
|
the semantic values passed through `TokenAdapter`, preserving their `Location` in AST nodes and diagnostics. The explicitly named
|
|
22
147
|
handwritten `BootstrapParser` is excluded from normal loading and exists only to break the regeneration cycle. See
|
|
23
|
-
[ADR
|
|
148
|
+
[ADR 0003](decisions/0003-self-hosted-grammar-frontend.md) for the update procedure and boundary.
|
|
149
|
+
`lib/ibex/frontend/shadow_grammar.y` describes the same frontend with parameterized list rules and an inline terminal wrapper.
|
|
150
|
+
It is generated only in tests and must match the production parser's AST across the canonical grammar and extended fixtures;
|
|
151
|
+
see the [development guide](development.md).
|
|
152
|
+
|
|
153
|
+
The lexer also retains an immutable lexical CST without changing the semantic token stream. `Frontend::Parser#parse_document`
|
|
154
|
+
returns a `SourceDocument` whose source, token-indexed segments, and AST come from that single lexer/parser pass.
|
|
155
|
+
`SourceSpan` uses half-open zero-based byte offsets and one-based Unicode-scalar line/column positions. Actions and user-code
|
|
156
|
+
bodies remain opaque segments; whitespace, line breaks, both comment forms, user-code markers, and EOF remain individually traversable.
|
|
157
|
+
`render`, byte slicing, and byte/line/column conversion provide the common source contract for formatter, documentation, include,
|
|
158
|
+
and language-server layers. `RuleDocumentation` correlates immediately preceding `##` comment-only lines with semantic rule
|
|
159
|
+
locations and copy-enriches generated Root/Fragment nodes; occupied opaque-segment lines are never scanned as comments. See
|
|
160
|
+
[ADR 0004](decisions/0004-shared-semantic-and-lossless-source-model.md).
|
|
161
|
+
|
|
162
|
+
`Frontend::Formatter` classifies the document's existing semantic tokens, replaces only whitespace/newline trivia, and protects
|
|
163
|
+
token, comment, action, heredoc, marker, and user-code bytes. It reparses the rendered root or fragment in the same frontend mode
|
|
164
|
+
and compares ASTs with an explicit work stack after removing location fields. The CLI's stdout, batch check, and transactional
|
|
165
|
+
in-place surfaces are therefore downstream consumers of `SourceDocument`, not an alternate grammar parser. Existing newline
|
|
166
|
+
segment spellings and blank-line counts survive required line boundaries; new boundaries use the first newline even when it is
|
|
167
|
+
inside opaque text. Batch stages and hard-link backups live beside each resolved target. Alias rejection, reverse rollback, and
|
|
168
|
+
all-directory synchronization preserve full file modes and relative or absolute symlink identities. Backups are synchronized
|
|
169
|
+
before installation; a failed restore preserves its backup, while post-commit cleanup problems are status-0 warnings. See
|
|
170
|
+
[ADR 0004](decisions/0004-shared-semantic-and-lossless-source-model.md).
|
|
171
|
+
|
|
172
|
+
`Frontend::SourceLoader` is the shared disk/overlay read boundary. Resolver's default loader retains canonical filesystem
|
|
173
|
+
behavior; LSP injects open buffers, including safe new files, while the resolver continues to enforce realpath containment,
|
|
174
|
+
symlink escape rejection, cycle identity, and diamond deduplication. `LSP::DocumentStore` layers monotonic open versions,
|
|
175
|
+
root/include closures, reverse dependencies, and disk restoration over that loader. `PositionCodec` is the only UTF-16 adapter
|
|
176
|
+
over frontend byte/scalar spans. `SymbolIndex` derives navigation and guarded rename edits from parsed nodes and lossless tokens,
|
|
177
|
+
never from opaque Ruby or textual scanning. Content-Length transport, lifecycle handling, and request handlers remain separate
|
|
178
|
+
from workspace semantics; see [ADR 0004](decisions/0004-shared-semantic-and-lossless-source-model.md).
|
|
179
|
+
|
|
180
|
+
CLI file generation renders every requested output into an immutable `ArtifactSet` before entering `GenerationTransaction`.
|
|
181
|
+
The transaction records the exact root, fragment, IR, and message bytes read through `GenerationInput`, rejects portable target
|
|
182
|
+
collisions and input aliases, takes stable sidecar locks, stages and synchronizes every file, and can restore hard-link backups
|
|
183
|
+
in reverse publication order. Ordinary companions publish first, the parser second, and an opt-in generation manifest last.
|
|
184
|
+
That manifest is the coherence marker: readers verify its listed paths, sizes, and SHA-256 digests and retry from a newly read
|
|
185
|
+
manifest on a mismatch. It is not a claim that several filesystem renames occur atomically. `--watch` feeds the same transaction
|
|
186
|
+
only candidates whose complete canonical source closure and failed include attempts remain unchanged across rendering and
|
|
187
|
+
publication. Portable polling, bounded debounce, failure deduplication, and cancellable nonblocking locks keep the last successful
|
|
188
|
+
generation usable while a source is invalid; see [ADR 0013](decisions/0013-transactional-generation-publication.md).
|
|
189
|
+
The executable's ordinary generation path declares this pipeline directly instead of loading the complete library and every
|
|
190
|
+
subcommand. Optional subcommands and generation outputs load at their invocation boundary while their public constants remain
|
|
191
|
+
autoloadable.
|
|
192
|
+
|
|
193
|
+
### Effective configuration boundary
|
|
24
194
|
|
|
25
|
-
|
|
195
|
+
`Ibex::Configuration` gives generation, grammar-test, and analysis paths one closed definition for parser construction and
|
|
196
|
+
build-policy concepts. Each immutable value records its canonical key, typed domain, owner, override policy, selected origin,
|
|
197
|
+
explicitness, and whether the selection is canonical. `Configuration::CLIAdapter` translates the existing internal option
|
|
198
|
+
hash into domain values such as `parser.entries=isolated`, `cst.trivia=leading`, and
|
|
199
|
+
`source.line_mapping=all`; code generators do not interpret legacy CLI shapes directly.
|
|
200
|
+
|
|
201
|
+
`Configuration::Resolver` applies fixed and monotone-minimum algebra without loading a grammar file or executing user code.
|
|
202
|
+
A fixed grammar declaration accepts a matching request and raises `Configuration::Conflict` for a contradiction. An explicit
|
|
203
|
+
analysis override remains noncanonical and serializes both the declared and selected values. Evidence JSON is emitted in
|
|
204
|
+
canonical-key order. This boundary intentionally adds neither grammar syntax nor a project configuration file; those adapters
|
|
205
|
+
must supply the same closed keys when their separately reviewed formats exist.
|
|
206
|
+
|
|
207
|
+
Extended grammar paths cross an explicit `Frontend::Resolver` boundary. The canonical `import` declaration and compatible
|
|
208
|
+
`include` spelling share this boundary. Roots retain class, start, options, and user code;
|
|
209
|
+
fragments contain composable declarations and rules. Canonical realpaths define DFS order, diamond deduplication, cycle identity,
|
|
210
|
+
and the Rake dependency closure. Canonical dirname ancestry keeps every resolved target below the root grammar directory after
|
|
211
|
+
symlink resolution, including when that directory is a filesystem or drive root. The source-only Parser never follows an
|
|
212
|
+
include. A `Resolution` recursively freezes its owned AST and defensive provenance copies while retaining rule identity for
|
|
213
|
+
include-chain lookup. Rake resolves this closure at task definition and refuses invalid graphs before timestamp checks can reuse
|
|
214
|
+
a stale output; see [ADR 0005](decisions/0005-contained-grammar-composition.md).
|
|
215
|
+
|
|
216
|
+
Extended parameterized definitions remain structural AST templates rather than grammar symbols. The Normalizer validates the
|
|
217
|
+
complete template graph, interns an impossible `$parameter_N` helper for each canonical call, records that helper in a memo
|
|
218
|
+
before expanding its body, and substitutes formals through nested EBNF and calls. Resumable alternative, item, and EBNF
|
|
219
|
+
continuations on an explicit depth-first worklist preserve ordinary lowering order and active-depth semantics without consuming
|
|
220
|
+
the Ruby call stack. Same-argument recursion therefore closes over the memo, while a configurable total-specialization budget
|
|
221
|
+
and structural constructor-growth detection bound argument-growing recursion without an arbitrary depth cutoff. Template actions,
|
|
222
|
+
precedence, metadata, documentation, locations, and definition include chains flow into the specialized productions; see
|
|
223
|
+
[ADR 0006](decisions/0006-bounded-structural-grammar-lowering.md).
|
|
224
|
+
|
|
225
|
+
Inline definitions are lowered temporarily, then a bounded deterministic post-pass substitutes marked alternatives through
|
|
226
|
+
ordinary, parameterized, and EBNF productions before diagnostics and LR construction. It removes every marked symbol and
|
|
227
|
+
production, remaps the dense symbol/production ids, and retains eliminated semantic reductions as a stable post-order
|
|
228
|
+
action plan. The plan addresses flattened physical values followed by earlier logical results, records a nullable semantic
|
|
229
|
+
`result_type` on every newly emitted step, reconstructs surrounding stack
|
|
230
|
+
prefixes and semantic spans, and remains executable after IR serialization. Cycle validation covers paths through ordinary
|
|
231
|
+
rules and templates; the default 10,000-production cartesian budget is configurable. See
|
|
232
|
+
[ADR 0006](decisions/0006-bounded-structural-grammar-lowering.md).
|
|
233
|
+
|
|
234
|
+
The strict generated frontend remains the grammar authority during batch diagnostics. A diagnostic parse retries it after
|
|
235
|
+
suppressing only a whole declaration, whole rule, or outer alternative at balanced delimiters. Each retry must remove a new
|
|
236
|
+
original token and both attempts and emitted diagnostics are bounded. Lexical and syntax phases collect independently before a
|
|
237
|
+
global source-order limit is applied, so an earlier syntax error cannot be hidden by a later lexical error. Machine-readable
|
|
238
|
+
diagnostics retain source spans, defensive locations, and stable codes. A repaired AST is marked partial by `ParseResult`, and
|
|
239
|
+
is not attached to the unchanged source document. After a successful root parse, the CLI reports the first resolver grammar
|
|
240
|
+
failure through the same diagnostic schema, while actual resolution I/O failures remain invocation errors. The CLI exposes this
|
|
241
|
+
analysis only through `ibex diagnose`; see [ADR 0004](decisions/0004-shared-semantic-and-lossless-source-model.md).
|
|
242
|
+
|
|
243
|
+
The RBS generator emits the generated class namespace, superclass, parser-table constants, `.parser_tables` contract, and
|
|
244
|
+
private reduction and composed-fragment signatures. Declared symbol types refine the RHS tuple and LHS result independently,
|
|
245
|
+
with `untyped` used at undeclared boundaries; composed inputs resolve either a physical symbol type or an earlier plan step's
|
|
246
|
+
`result_type`. Reduction methods also receive a location tuple, surrounding location stack, and optional
|
|
247
|
+
`Runtime::LocationSpan`. Generated tables mark whether actions require locations. The runtime leaves the location stack
|
|
248
|
+
unallocated for ordinary two-element-token parses and creates or backfills it only when an action, tooling observer, or
|
|
249
|
+
three-element token requires it. The public immutable `Ibex::Location` range and `loc`/`result_loc` action helpers sit above the
|
|
250
|
+
same stack contract.
|
|
251
|
+
Default source mapping compiles opaque action methods with `class_eval` when the generated class loads. The opt-in action-shadow
|
|
252
|
+
generator makes those exact method bodies visible to Steep without runtime loading: runtime and shadow output share one method
|
|
253
|
+
source builder, while the shadow omits parser infrastructure and every user-code section. Ibex only generates this source;
|
|
254
|
+
executing Steep remains an application/CI boundary. See
|
|
255
|
+
[ADR 0011](decisions/0011-versioned-semantic-action-boundary.md). The
|
|
26
256
|
gem also ships a one-to-one rbs-inline-generated signature tree under `sig/` for every Ruby source in `lib/`, including the
|
|
27
257
|
self-hosted parser. CI regenerates into an empty temporary directory, compares the complete trees, validates the RBS environment,
|
|
28
258
|
and runs Steep against the entire library. Token/location records, grammar AST nodes, parser classifier and bootstrap state, the
|
|
@@ -30,38 +260,91 @@ Ruby DSL, IR records, and automaton actions use concrete domain types. Generated
|
|
|
30
260
|
cells, decoded JSON values, and user methods embedded as opaque Ruby source remain `untyped`; applications can reopen the generated
|
|
31
261
|
class in their own RBS files to declare embedded methods.
|
|
32
262
|
|
|
33
|
-
## Grammar IR
|
|
263
|
+
## Current Grammar IR
|
|
264
|
+
|
|
265
|
+
<!-- stable:current-ir:v1 -->
|
|
34
266
|
|
|
35
267
|
Top-level fields:
|
|
36
268
|
|
|
37
269
|
| Field | Meaning |
|
|
38
270
|
|---|---|
|
|
39
|
-
| `ibex_ir`, `schema_version` | `"grammar"`,
|
|
271
|
+
| `ibex_ir`, `schema_version` | `"grammar"`, current format |
|
|
40
272
|
| `class_name`, `superclass` | Generated Ruby class contract |
|
|
41
|
-
| `start`, `expect`, `options` |
|
|
273
|
+
| `start`, optional `starts`, `expect`, `options` | Primary/ordered start names, unresolved S/R expectation, result/action flags |
|
|
274
|
+
| optional `params`, `printers` | Generated-constructor keywords and symbol-specific debug value formatters |
|
|
275
|
+
| optional `lexer` | Embedded independently versioned Lexer IR |
|
|
42
276
|
| `symbols` | Interned terminals and nonterminals; `$eof` id 0 and `error` id 1 |
|
|
43
277
|
| `productions` | Numeric LHS/RHS ids, action, precedence override, source origin |
|
|
44
278
|
| `user_code`, `conversions`, `warnings` | Concatenated code, external token expressions, structured diagnostics |
|
|
45
279
|
| `user_code_chunks` | Optional opaque chunks with first-code-line locations for compatible source mapping |
|
|
46
280
|
|
|
47
|
-
Warning records use
|
|
48
|
-
`duplicate_production`, and `empty_language
|
|
281
|
+
Warning records use the additive type vocabulary `undeclared_terminal`, `unused_terminal`, `unused_precedence`,
|
|
282
|
+
`unreachable_terminal`, `unreachable_nonterminal`, `duplicate_production`, and `empty_language`, and retain source locations.
|
|
283
|
+
The CLI applies display/error policy at the boundary;
|
|
49
284
|
normalization and IR serialization do not discard diagnostics.
|
|
50
285
|
|
|
51
|
-
A symbol has `id`, `name`, `kind`, `reserved`, optional `prec {associativity, level}`,
|
|
52
|
-
`
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
286
|
+
A symbol has `id`, `name`, `kind`, `reserved`, optional `prec {associativity, level}`, `loc`, `display_name`, and
|
|
287
|
+
`semantic_type`.
|
|
288
|
+
A production has `id`, `lhs`, `rhs`, optional `action`, optional `prec_override`, and `origin`. Synthetic EBNF origins include
|
|
289
|
+
an additive, deterministic `expression` label used by text, DOT, and HTML presentation while numeric symbol identities remain
|
|
290
|
+
unchanged. An action has opaque `code`, `loc`, `named_refs [{name,index}]`, and `context_length`; middle-action helpers use the
|
|
291
|
+
last field to view preceding stack values.
|
|
56
292
|
|
|
57
|
-
IR objects and nested collections are frozen. JSON keys have deterministic order, so dump/load/dump is byte-stable.
|
|
58
|
-
schema changes require a new version. The additive `user_code_chunks` field is optional so older schema-v1 JSON remains loadable;
|
|
59
|
-
new text-front-end IR retains it to make direct and resumed `--line-convert-all` generation identical.
|
|
293
|
+
IR objects and nested collections are frozen. JSON keys have deterministic order, so dump/load/dump is byte-stable.
|
|
60
294
|
|
|
61
|
-
|
|
295
|
+
Normalized grammars use the current format for declaration-free source and carry explicit nullable metadata:
|
|
62
296
|
|
|
63
|
-
|
|
64
|
-
|
|
297
|
+
| Record | Current-format metadata |
|
|
298
|
+
|---|---|
|
|
299
|
+
| grammar | `source_provenance {file, root, byte_span {start,end}}` |
|
|
300
|
+
| symbol | `doc` |
|
|
301
|
+
| production | `doc` and `expansion {parameter, inline, include_chain}` |
|
|
302
|
+
| action | `composition {strategy, fragments, plan {version, physical, steps}}`; new steps include nullable `result_type` |
|
|
303
|
+
|
|
304
|
+
The source-only text frontend supplies the source filename and leaves unknown metadata null. A resolved grammar also supplies its
|
|
305
|
+
canonical source root and each production's include chain while preserving its original-file origin. Lossless rule comments
|
|
306
|
+
populate symbol and user-production documentation, including through fragment resolution; synthetic EBNF helpers remain
|
|
307
|
+
undocumented. Parameterized specializations populate `expansion.parameter` with the template name and canonical structural
|
|
308
|
+
arguments while retaining the definition's include chain.
|
|
309
|
+
The current format adds one closed, root-owned `parser_contract`. Its `algorithm`, `entries`, and `cst_trivia` members each carry
|
|
310
|
+
`value`, `explicit`, and `loc`. An explicit member has an admitted value and source location; an unspecified member has all
|
|
311
|
+
three states fixed to `value: null`, `explicit: false`, and `loc: null`. Unspecified is not an encoding of the current built-in
|
|
312
|
+
default. The contract sits only at the root, so fragments cannot change parser-wide construction while their normalized
|
|
313
|
+
productions and source provenance remain composable.
|
|
314
|
+
|
|
315
|
+
Extended root grammars can populate `algorithm` and `entries` through one
|
|
316
|
+
domain-specific `parser ... end` declaration. The frontend rejects that block
|
|
317
|
+
in fragments and compatible mode, and rejects duplicate blocks, duplicate or
|
|
318
|
+
unknown keys, unknown values, and `algorithm auto` before normalization. The
|
|
319
|
+
typed configuration resolver treats those values as fixed grammar contracts:
|
|
320
|
+
canonical generation accepts only an absent or matching CLI request. Analysis
|
|
321
|
+
and grammar-test commands may move an explicitly different algorithm into a
|
|
322
|
+
reported noncanonical analysis origin; entry construction remains fixed. The
|
|
323
|
+
configuration inspector reads the same AST and import closure without running
|
|
324
|
+
actions or user sections.
|
|
325
|
+
|
|
326
|
+
`Serialize.load` and `Validator.validate` accept only the current Grammar IR format. Both declaration-free and
|
|
327
|
+
`parser`-declared sources write that same format, so there is no in-process migration path or compatibility reader.
|
|
328
|
+
Callers construct the current object directly through `IR::Grammar.new`; see
|
|
329
|
+
[ADR 0020](decisions/0020-grammar-ir-parser-contract.md).
|
|
330
|
+
|
|
331
|
+
The v1 stabilization freeze covers required core fields, meanings, ordering,
|
|
332
|
+
identity, and validation behavior. The future `x-` experimental namespace is
|
|
333
|
+
outside that freeze, but current schemas remain closed and reject unknown
|
|
334
|
+
fields. Experimental data must therefore begin in a new additive schema
|
|
335
|
+
version rather than weakening an existing document. See
|
|
336
|
+
[stability and deprecation](stability.md).
|
|
337
|
+
|
|
338
|
+
`Codegen::Documentation` renders normalized user rules and alternatives as escaped Markdown, self-contained accessible HTML, or
|
|
339
|
+
railroad SVG. The railroad renderer includes visible wrapped rule descriptions in its section-height calculation and exposes the
|
|
340
|
+
full escaped text through SVG descriptions. `ibex doc` resolves the same canonical include graph and writes to stdout or an
|
|
341
|
+
atomic file without generating or executing application parser code.
|
|
342
|
+
|
|
343
|
+
## Current Automaton IR
|
|
344
|
+
|
|
345
|
+
Top-level fields are `ibex_ir: "automaton"`, `schema_version`, `algorithm`, `grammar_digest`, embedded `grammar`, `states`,
|
|
346
|
+
optional `entry_states`, and `conflict_summary`. Embedding Grammar IR makes automaton JSON sufficient for code generation after
|
|
347
|
+
`--from=automaton-ir`. A multi-entry automaton maps every ordered grammar start name to its initial state.
|
|
65
348
|
|
|
66
349
|
Each state contains:
|
|
67
350
|
|
|
@@ -70,30 +353,193 @@ Each state contains:
|
|
|
70
353
|
- resolved terminal `actions` and nonterminal `gotos`;
|
|
71
354
|
- an optional reduce `default_action`, selected only when explicit error masks preserve every terminal lookup and reduce the
|
|
72
355
|
total encoded ACTION entries;
|
|
73
|
-
- every conflict, including precedence-resolved conflicts and the resolution reason
|
|
356
|
+
- every conflict, including precedence-resolved conflicts and the resolution reason; multi-entry conflicts also carry their
|
|
357
|
+
reachable `entries` and optional `composite` marker.
|
|
74
358
|
|
|
75
359
|
`conflict_summary.sr` counts unresolved default-shift conflicts for `expect`; `resolved_sr` counts retained precedence or
|
|
76
360
|
associativity decisions; `rr` counts reduce/reduce cells.
|
|
77
361
|
|
|
362
|
+
The current Automaton IR embeds the exact current Grammar IR, includes the parser contract in `grammar_digest`, and records
|
|
363
|
+
`entry_construction` as `shared` or `isolated`. Older documents are rejected rather than migrated. Callers construct the
|
|
364
|
+
current object directly through `IR::Automaton.new`.
|
|
365
|
+
|
|
366
|
+
`--from=grammar-ir` applies the current parser contract through the typed configuration resolver before constructing tables;
|
|
367
|
+
matching CLI values are allowed and conflicts are rejected with the contract location. `--from=automaton-ir` generates without
|
|
368
|
+
the original source and rejects algorithm/entry construction flags because its tables are already built. A generation
|
|
369
|
+
manifest records the grammar digest and contract separately from the embedded automaton's algorithm/entry facts and codegen-only
|
|
370
|
+
effective configuration. Static IR views validate opaque action strings but never execute them. Published Draft 2020-12
|
|
371
|
+
contracts for both current IR documents live under `schema/`; see
|
|
372
|
+
[ADR 0001](decisions/0001-separate-ir-pipeline.md).
|
|
373
|
+
|
|
374
|
+
`--emit=sets` is a deterministic analysis view rather than another IR: it emits lexically sorted nullable nonterminals and
|
|
375
|
+
FIRST/FOLLOW maps for nonterminals. DOT, Mermaid, and the self-contained searchable HTML report are deterministic presentation
|
|
376
|
+
views over Automaton IR.
|
|
377
|
+
|
|
378
|
+
## Construction algorithms and counterexamples
|
|
379
|
+
|
|
380
|
+
The `lalr` and `slr` strategies construct LR(0) states directly for a single entry. LALR lookaheads are the least fixed point of deterministic
|
|
381
|
+
shift, spontaneous-FIRST, and nullable-suffix propagation edges over item occurrences; SLR replaces completed lookaheads with
|
|
382
|
+
FOLLOW sets. Multiple entries seed distinct augmented canonical items and use canonical core merging because the direct
|
|
383
|
+
lookahead graph has a single-root contract. Canonical `lr1` retains the canonical collection. An explicit canonical-and-merge
|
|
384
|
+
LALR reference strategy proves byte equivalence without changing the Automaton IR algorithm label. `ielr` conservatively merges action-compatible canonical
|
|
385
|
+
states and refines partitions until outgoing transitions are congruent, avoiding LALR inadequacies without promising a minimum
|
|
386
|
+
state count. `--entry-isolation` instead constructs each start independently and concatenates the resulting state sets with
|
|
387
|
+
deterministic offsets. Shared builds attribute reachable entries to conflicts and compare isolated conflict fingerprints to
|
|
388
|
+
identify merge-created composite conflicts. All strategies use the same conflict resolver and default reduction pass. After a build, frozen diagnostic
|
|
389
|
+
`metrics` record the strategy and construction/final state counts, plus a canonical count only when one was actually built. See
|
|
390
|
+
[ADR 0007](decisions/0007-shared-parser-construction-pipeline.md).
|
|
391
|
+
|
|
392
|
+
`Ibex::LALR::Counterexample` consumes only Automaton IR. For each conflict it explores parser-stack configurations, forces the
|
|
393
|
+
competing actions, and searches for a common accepting suffix. A successful result contains both complete derivation trees and is
|
|
394
|
+
marked `unifying: true`. Search defaults to 32 tokens and 50,000 configurations; the Ruby and CLI APIs can set both positive
|
|
395
|
+
budgets. If no common sentence is found within them, the result is explicitly marked nonunifying and contains the deterministic
|
|
396
|
+
shortest reachability witness instead of claiming ambiguity.
|
|
397
|
+
|
|
398
|
+
`Ibex::Codegen::Explain` filters those immutable conflicts by state and canonical token identity before asking
|
|
399
|
+
`Counterexample#for_conflict` to search only the selected entries, then renders text or the versioned `explain` JSON analysis
|
|
400
|
+
shape. `Counterexample#all` retains its original all-conflict behavior. The view performs no additional parser analysis and does
|
|
401
|
+
not extend Grammar or Automaton IR.
|
|
402
|
+
|
|
403
|
+
`Ibex::Verify::Verifier` accepts validated Automaton IR and derives LR(0) or
|
|
404
|
+
canonical LR(1) collections from the embedded Grammar IR without calling the
|
|
405
|
+
parser builder. Default checks validate item/action soundness,
|
|
406
|
+
algorithm-specific lookaheads, expanded default reductions and error masks,
|
|
407
|
+
reachability, productivity, epsilon termination, resolver consistency, and
|
|
408
|
+
rebuilt plain/compact row equality. `--strict` adds collection completeness
|
|
409
|
+
and reports that same row equality as V5 rather than V4. The verifier does not
|
|
410
|
+
consume generated Ruby or a supplied executable table artifact. Strict IELR
|
|
411
|
+
verification also runs the bounded V9 canonical acceptance witness; this is
|
|
412
|
+
not an unbounded equivalence proof. Its exact
|
|
413
|
+
shared dependencies, algorithm limits, resource semantics, fault mapping, and
|
|
414
|
+
non-goals are documented in the [verifier trust boundary](verifier-trust-boundary.md).
|
|
415
|
+
`ibex verify` uses exit statuses 0 for valid, 1 for a violation, and 2 for
|
|
416
|
+
reference-budget exhaustion.
|
|
417
|
+
|
|
418
|
+
`Ibex::Equiv` first compares normalized grammar structure, then generates
|
|
419
|
+
sentences in both directions and explores the product of two immutable LR
|
|
420
|
+
state-stack machines in breadth-first order. The product key includes both
|
|
421
|
+
stacks, statuses, and consumed-action counts; a supplied rule map also adds
|
|
422
|
+
both postorder reduction traces. The first reported token witness is therefore
|
|
423
|
+
shortest within the declared token/configuration bounds. Simulation uses only
|
|
424
|
+
Automaton IR actions and gotos. It validates both inputs with the independent
|
|
425
|
+
verifier and does not evaluate semantic actions. A rule map requests bounded
|
|
426
|
+
tree comparison; without one, only accepted language is compared. Every
|
|
427
|
+
successful bounded report explicitly states that it is not an equivalence
|
|
428
|
+
proof.
|
|
429
|
+
|
|
430
|
+
`Ibex::Fix` composes those two read-only safety oracles around a finite repair
|
|
431
|
+
space. It rebuilds a candidate through the shared construction pipeline, but
|
|
432
|
+
accepts it only after the target fingerprint disappears, other fingerprints
|
|
433
|
+
do not increase, independent verification succeeds, and bounded language plus
|
|
434
|
+
identity-mapped reduction traces find no difference. User actions remain
|
|
435
|
+
opaque. Source proposals are whole-file deterministic edits; the CLI delegates
|
|
436
|
+
application to the existing transactional writer and refuses aliased inputs.
|
|
437
|
+
`Ibex::Diff` and `Ibex::Metrics` are deterministic views over the same frozen
|
|
438
|
+
Grammar and Automaton IR. They do not add an IR stage or alter generated
|
|
439
|
+
parsers.
|
|
440
|
+
|
|
441
|
+
`Ibex::BisonImport` is a clean-room adapter in front of that frozen pipeline.
|
|
442
|
+
Its iterative scanner recovers declarations, production alternatives, source
|
|
443
|
+
positions, and opaque C actions under byte/token/rule/action budgets, then
|
|
444
|
+
emits ordinary extended source. It adds no frontend syntax or IR field.
|
|
445
|
+
Deterministic terminal/nonterminal namespaces prevent Bison casing and keyword
|
|
446
|
+
rules from changing symbol kinds. The report separates unsupported directives
|
|
447
|
+
that leave the recovered production graph complete from structural gaps.
|
|
448
|
+
Analysis may continue across either result, but Ruby generation rejects the C
|
|
449
|
+
action sentinel and `Fix` rejects structurally incomplete source. Pinned
|
|
450
|
+
third-party grammars exist only in temporary external CI directories; see the
|
|
451
|
+
[import guide](bison-import.md).
|
|
452
|
+
|
|
453
|
+
The repository's self-authored representative grammar feeds the current versioned `ibex_benchmark` v2 document. Its JSON Schema
|
|
454
|
+
is shipped beside the IR schemas, while committed environment-specific observations live under the matching
|
|
455
|
+
`benchmark/results/vN` directory. Timing and peak RSS remain non-gating; CI reproduces only deterministic structure and digests.
|
|
456
|
+
See the [benchmark guide](../benchmark/README.md).
|
|
457
|
+
|
|
78
458
|
## Runtime table contract
|
|
79
459
|
|
|
80
460
|
Generated subclasses expose `.parser_tables` with a required `format_version`, external `tokens`, display `token_names`, ACTION
|
|
81
461
|
and GOTO tables, per-state default actions, and production `{lhs,length,action}` records. The runtime validates the version before
|
|
82
|
-
reading input and rejects missing or unsupported formats with a regeneration instruction
|
|
83
|
-
|
|
462
|
+
reading input and rejects missing or unsupported formats with a regeneration instruction. The generator emits v6. For non-CST
|
|
463
|
+
tables, the runtime accepts v1's two-argument actions, v2/v3 explicitly marked five-argument location actions, v3 explicitly
|
|
464
|
+
marked six-argument composed actions, v4 one-Array values actions, and v5/v6 positional actions. Marker contracts are validated
|
|
465
|
+
before input. A CST table is executable only when it uses current format-v6 structured metadata; older or boolean CST shapes
|
|
466
|
+
must be regenerated. See
|
|
467
|
+
[ADR 0008](decisions/0008-versioned-runtime-package-boundary.md). Plain tables are arrays of Hash rows. Compact tables use row
|
|
84
468
|
displacement with offsets, values, and row-ownership checks; both expose equivalent lookups. Default reductions are restricted
|
|
85
469
|
to known token ids, and explicit error masks preserve the pre-optimization result of every declared terminal cell, including
|
|
86
|
-
the synthetic `error` terminal.
|
|
87
|
-
|
|
470
|
+
the synthetic `error` terminal. Extended parser tables opt `expected_tokens` into lookahead correction: the runtime copies only
|
|
471
|
+
the state stack and simulates reductions and gotos for each declared terminal, without evaluating semantic actions. The explicit
|
|
472
|
+
`expected_tokens_exact` API exposes the same result for compatible tables. The deterministic size policy is fixed by
|
|
473
|
+
[ADR 0008](decisions/0008-versioned-runtime-package-boundary.md).
|
|
474
|
+
|
|
475
|
+
Runtime execution is packaged independently as `ibex-runtime`, with its own version and RBS tree. The generator package depends
|
|
476
|
+
on a compatible runtime series but does not duplicate runtime-owned files. Compact lookup values live in a runtime-safe leaf
|
|
477
|
+
file, while table construction remains generator-only. Normal output requires only `ibex/runtime`; `-E` embeds the same sources.
|
|
478
|
+
See [ADR 0008](decisions/0008-versioned-runtime-package-boundary.md).
|
|
88
479
|
|
|
89
480
|
The runtime maintains state and value stacks, pulls a lookahead only when required, and applies tagged `shift`, `reduce`,
|
|
90
481
|
`accept`, and `error` actions. Recovery pops to a state that shifts token id 1, suppresses repeated reports for three successful
|
|
91
|
-
shifts, and honors `yyerrok`. No-op
|
|
482
|
+
shifts, and honors `yyerrok`. No-op shift, reduce, recovery, location-aware, and discard extension points observe successfully
|
|
92
483
|
committed events without changing parser results; the recovery hook retains the pre-pop error context and is distinct from an
|
|
93
|
-
ordinary token shift. Their ordering and payload contract is
|
|
484
|
+
ordinary token shift. A configured value printer affects only human `yydebug` output. Their ordering and payload contract is
|
|
485
|
+
extended additively by
|
|
486
|
+
[ADR 0010](decisions/0010-committed-runtime-observation.md). Grammar-declared
|
|
487
|
+
symbol printers are optional current IR metadata compiled into private methods and
|
|
488
|
+
an id-indexed table.
|
|
489
|
+
|
|
490
|
+
Ordinary generated tables are recursively frozen and made Ractor-shareable. Threads and Ractors share those tables but parse
|
|
491
|
+
through distinct instances; stacks, lookahead, lexer state, callbacks, observers, and semantic values are session-owned. A
|
|
492
|
+
single instance rejects overlapping drivers. Immutable `Runtime::ResourceLimits` values bound every stack push and recovery
|
|
493
|
+
entry with finite defaults. Exhaustion raises the structured `ResourceLimitError`; see
|
|
494
|
+
[ADR 0009](decisions/0009-isolated-parser-sessions.md).
|
|
495
|
+
|
|
496
|
+
Extended current Grammar IR may additionally carry synchronization terminals and ordered `%on_error_reduce` groups. Table
|
|
497
|
+
construction fills only otherwise erroneous ACTION cells with a unique highest-priority completed declared production. At
|
|
498
|
+
runtime, an explicit shift of the synthetic `error` token always wins; only when it is unavailable does panic recovery discard
|
|
499
|
+
through a configured synchronization token and pop to a state that accepts that retained lookahead. Generated parsers without
|
|
500
|
+
sync declarations omit the optional table field. The pull/push ordering and observer contract are fixed by
|
|
501
|
+
the runtime and grammar reference documentation.
|
|
502
|
+
|
|
503
|
+
The separate `Runtime::Parser#observe` API publishes ordered, immutable schema-v1 events for tooling. Its bounded sanitizer
|
|
504
|
+
copies only JSON data and never retains application identities or private stacks. With no observer, parse transitions construct
|
|
505
|
+
no Event, payload summary, or dispatch snapshot; parser initialization still creates its ownership mutex. Generated tables
|
|
506
|
+
contribute grammar digest, table format, state count, and production count to the `start` event. `Runtime::EventJSONLTracer`
|
|
507
|
+
exposes the versioned stream. The protocol and
|
|
508
|
+
exception/threading behavior are fixed by
|
|
509
|
+
[ADR 0010](decisions/0010-committed-runtime-observation.md).
|
|
510
|
+
|
|
511
|
+
Optional `Runtime::RepairPolicy` drives a bounded Dijkstra search over copied state stacks and buffered token identities. Search
|
|
512
|
+
uses explicit/default ACTION, GOTO, and production shape only; it never executes semantic code. A selected immutable edit plan is
|
|
513
|
+
reported once, then replayed through the ordinary runtime so actions and hooks remain committed-path effects. Pull lookahead,
|
|
514
|
+
push buffering, deterministic tie-breaking, fallback to yacc recovery, and no-policy compatibility are fixed by
|
|
515
|
+
[ADR 0012](decisions/0012-bounded-nonexecuting-analysis.md).
|
|
516
|
+
|
|
517
|
+
`Coverage::Collector` accepts only contiguous, complete runtime-event sessions with generated parser metadata. It counts entries
|
|
518
|
+
to the initial, shift, reduce-goto, and recovery states and counts committed reductions by production id. `Coverage::Report`
|
|
519
|
+
publishes ascending sparse hit arrays under the versioned runtime-coverage schema. Merge requires identical full grammar digest,
|
|
520
|
+
table format, and totals and uses checked addition. The coverage CLI only reads bounded JSON/JSON Lines and never loads generated
|
|
521
|
+
Ruby or executes semantic actions; collection, merge, threshold, and atomic-output policy are fixed by
|
|
522
|
+
[ADR 0010](decisions/0010-committed-runtime-observation.md).
|
|
523
|
+
|
|
524
|
+
`TableSimulation::Simulator` is a separate state-stack interpreter over validated Automaton IR. It resolves an explicit ACTION
|
|
525
|
+
cell before a default action, so explicit error masks remain authoritative, and never evaluates the opaque semantic-action
|
|
526
|
+
source stored in Grammar IR. Immutable steps expose state, lookahead, selected action source, reduction/goto metadata, and stack
|
|
527
|
+
depth. Action and stack budgets bound default/epsilon cycles and growth. The text/JSON CLI and versioned output contract are
|
|
528
|
+
fixed by [ADR 0012](decisions/0012-bounded-nonexecuting-analysis.md).
|
|
529
|
+
|
|
530
|
+
The current Grammar IR may carry ordered accept/reject source tests without adding them to parser tables. `GrammarTests::Runner` generates
|
|
531
|
+
one embedded parser and executes fresh parser instances in a separate Ruby process, distinguishing `ParseError` rejection from
|
|
532
|
+
lexer/application errors and bounding the whole suite by a timeout. The separate runner loads the generated file, so guarded
|
|
533
|
+
footer programs stay inactive. The source contract, isolation boundary, and CI behavior are fixed by
|
|
534
|
+
the grammar reference documentation.
|
|
94
535
|
|
|
95
536
|
## Clean-room boundary
|
|
96
537
|
|
|
97
538
|
Implementation work uses public racc documentation, CLI black-box behavior, and published LR algorithms only. racc implementation
|
|
98
539
|
sources and generated source are not inputs to the design. Self-authored compatibility grammars execute both outputs in separate
|
|
99
540
|
processes and compare observable results.
|
|
541
|
+
|
|
542
|
+
`RaccMigration::Checker` treats grammar code as opaque while reporting default-mode parse/normalization errors and known runtime
|
|
543
|
+
coupling. The separate harness generator emits source only; its output refuses an empty corpus and makes bounded child-process
|
|
544
|
+
execution explicit. The boundary is fixed by
|
|
545
|
+
[ADR 0012](decisions/0012-bounded-nonexecuting-analysis.md).
|