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
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ibex
|
|
4
|
+
module IR
|
|
5
|
+
module Validator
|
|
6
|
+
# Structural and referential validation for a current Automaton IR JSON object.
|
|
7
|
+
# rubocop:disable Metrics/ClassLength -- inline type contracts accompany one cohesive document validator.
|
|
8
|
+
class AutomatonDocument < Base
|
|
9
|
+
ROOT_REQUIRED = %w[
|
|
10
|
+
ibex_ir schema_version algorithm entry_construction grammar_digest grammar states conflict_summary
|
|
11
|
+
].freeze #: Array[String]
|
|
12
|
+
ROOT_OPTIONAL = %w[entry_states].freeze #: Array[String]
|
|
13
|
+
STATE_REQUIRED = %w[id items transitions actions gotos default_action conflicts].freeze #: Array[String]
|
|
14
|
+
ACTION_TYPES = %w[shift reduce accept error].freeze #: Array[String]
|
|
15
|
+
RESOLUTION_KINDS = %w[definition_order default_shift precedence associativity].freeze #: Array[String]
|
|
16
|
+
|
|
17
|
+
# @rbs @data: json_object
|
|
18
|
+
# @rbs @states_by_id: Hash[Integer, json_object]
|
|
19
|
+
# @rbs @grammar: GrammarDocument
|
|
20
|
+
# @rbs @version: Integer
|
|
21
|
+
|
|
22
|
+
# @rbs (json_object data, ?version: Integer) -> void
|
|
23
|
+
def initialize(data, version: data.fetch("schema_version"))
|
|
24
|
+
super()
|
|
25
|
+
@data = data
|
|
26
|
+
@version = version
|
|
27
|
+
@states_by_id = {} #: Hash[Integer, json_object]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @rbs () -> self
|
|
31
|
+
def validate
|
|
32
|
+
record(@data, "$", ROOT_REQUIRED, ROOT_OPTIONAL)
|
|
33
|
+
literal(@data["ibex_ir"], "$.ibex_ir", "automaton")
|
|
34
|
+
literal(@data["schema_version"], "$.schema_version", @version)
|
|
35
|
+
enum(@data["algorithm"], "$.algorithm", %w[slr lalr1 ielr1 lr1])
|
|
36
|
+
validate_digest
|
|
37
|
+
grammar = object(@data["grammar"], "$.grammar")
|
|
38
|
+
literal(grammar["schema_version"], "$.grammar.schema_version", @version)
|
|
39
|
+
@grammar = GrammarDocument.new(grammar, path: "$.grammar", version: @version).validate
|
|
40
|
+
validate_construction_contract(grammar)
|
|
41
|
+
validate_state_records
|
|
42
|
+
validate_entry_states
|
|
43
|
+
validate_state_contents
|
|
44
|
+
validate_conflict_summary
|
|
45
|
+
self
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
# @rbs () -> void
|
|
51
|
+
def validate_entry_states
|
|
52
|
+
value = @data["entry_states"]
|
|
53
|
+
if value.nil?
|
|
54
|
+
invalid("$.entry_states", "is required for multiple start symbols") if @data.dig("grammar", "starts")
|
|
55
|
+
return
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
entries = object(value, "$.entry_states")
|
|
59
|
+
expected = @data.dig("grammar", "starts") || [@data.dig("grammar", "start")]
|
|
60
|
+
invalid("$.entry_states", "keys must equal grammar starts in order") unless entries.keys == expected
|
|
61
|
+
entries.each do |name, state|
|
|
62
|
+
state_id = nonnegative_integer(state, "$.entry_states.#{name}")
|
|
63
|
+
invalid("$.entry_states.#{name}", "references missing state #{state_id}") unless @states_by_id[state_id]
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# @rbs (Hash[String, untyped] grammar) -> void
|
|
68
|
+
def validate_construction_contract(grammar)
|
|
69
|
+
entry_construction = enum(
|
|
70
|
+
@data["entry_construction"], "$.entry_construction", %w[shared isolated]
|
|
71
|
+
)
|
|
72
|
+
contract = grammar.fetch("parser_contract")
|
|
73
|
+
algorithm = contract.fetch("algorithm")
|
|
74
|
+
expected_algorithm = { "lalr" => "lalr1", "ielr" => "ielr1" }.fetch(
|
|
75
|
+
algorithm["value"], algorithm["value"]
|
|
76
|
+
)
|
|
77
|
+
if algorithm["explicit"] && @data["algorithm"] != expected_algorithm
|
|
78
|
+
invalid("$.algorithm", "must match the embedded parser contract")
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
entries = contract.fetch("entries")
|
|
82
|
+
return unless entries["explicit"] && entry_construction != entries["value"]
|
|
83
|
+
|
|
84
|
+
invalid("$.entry_construction", "must match the embedded parser contract")
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# @rbs () -> void
|
|
88
|
+
def validate_digest
|
|
89
|
+
digest = string(@data["grammar_digest"], "$.grammar_digest")
|
|
90
|
+
invalid("$.grammar_digest", "must be a sha256 digest") unless digest.match?(/\Asha256:[0-9a-f]{64}\z/)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# @rbs () -> void
|
|
94
|
+
def validate_state_records
|
|
95
|
+
states = array(@data["states"], "$.states")
|
|
96
|
+
invalid("$.states", "must contain at least one state") if states.empty?
|
|
97
|
+
states.each_with_index do |value, index|
|
|
98
|
+
path = "$.states[#{index}]"
|
|
99
|
+
state = record(value, path, STATE_REQUIRED)
|
|
100
|
+
id = nonnegative_integer(state["id"], "#{path}.id")
|
|
101
|
+
invalid("#{path}.id", "must equal its array index #{index}") unless id == index
|
|
102
|
+
@states_by_id[id] = state
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# @rbs () -> void
|
|
107
|
+
def validate_state_contents
|
|
108
|
+
@states_by_id.each do |id, state|
|
|
109
|
+
path = "$.states[#{id}]"
|
|
110
|
+
validate_items(state["items"], "#{path}.items")
|
|
111
|
+
validate_transitions(state["transitions"], "#{path}.transitions")
|
|
112
|
+
validate_actions(state["actions"], "#{path}.actions")
|
|
113
|
+
validate_gotos(state["gotos"], "#{path}.gotos")
|
|
114
|
+
validate_parser_action(state["default_action"], "#{path}.default_action", nullable: true)
|
|
115
|
+
validate_conflicts(state["conflicts"], "#{path}.conflicts")
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# @rbs (json_value value, String path) -> void
|
|
120
|
+
def validate_items(value, path)
|
|
121
|
+
array(value, path).each_with_index do |item, index|
|
|
122
|
+
item_path = "#{path}[#{index}]"
|
|
123
|
+
item = record(item, item_path, %w[production dot lookaheads])
|
|
124
|
+
production = integer(item["production"], "#{item_path}.production")
|
|
125
|
+
validate_item_production(production, item["dot"], item_path)
|
|
126
|
+
validate_lookaheads(item["lookaheads"], "#{item_path}.lookaheads")
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# @rbs (Integer production_id, json_value dot_value, String path) -> void
|
|
131
|
+
def validate_item_production(production_id, dot_value, path)
|
|
132
|
+
dot = nonnegative_integer(dot_value, "#{path}.dot")
|
|
133
|
+
if production_id == -1
|
|
134
|
+
invalid("#{path}.dot", "must not exceed 1 for the augmented production") if dot > 1
|
|
135
|
+
return
|
|
136
|
+
end
|
|
137
|
+
production = @grammar.productions_by_id[production_id]
|
|
138
|
+
invalid("#{path}.production", "references missing production id #{production_id}") unless production
|
|
139
|
+
rhs = array(production["rhs"], "#{path}.production.rhs")
|
|
140
|
+
invalid("#{path}.dot", "exceeds production #{production_id} length") if dot > rhs.length
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# @rbs (json_value value, String path) -> void
|
|
144
|
+
def validate_lookaheads(value, path)
|
|
145
|
+
array(value, path).each_with_index do |name, index|
|
|
146
|
+
name = string(name, "#{path}[#{index}]")
|
|
147
|
+
symbol = @grammar.symbols_by_name[name]
|
|
148
|
+
invalid("#{path}[#{index}]", "references missing symbol #{name.inspect}") unless symbol
|
|
149
|
+
invalid("#{path}[#{index}]", "must reference a terminal") unless symbol["kind"] == "terminal"
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# @rbs (json_value value, String path) -> void
|
|
154
|
+
def validate_transitions(value, path)
|
|
155
|
+
symbol_map(value, path) do |target, target_path, _symbol|
|
|
156
|
+
validate_state_reference(target, target_path)
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# @rbs (json_value value, String path) -> void
|
|
161
|
+
def validate_actions(value, path)
|
|
162
|
+
symbol_map(value, path, kind: "terminal") do |action, action_path, _symbol|
|
|
163
|
+
validate_parser_action(action, action_path)
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# @rbs (json_value value, String path) -> void
|
|
168
|
+
def validate_gotos(value, path)
|
|
169
|
+
symbol_map(value, path, kind: "nonterminal") do |target, target_path, _symbol|
|
|
170
|
+
validate_state_reference(target, target_path)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# @rbs (json_value value, String path, ?kind: String?) { (json_value, String, json_object) -> void } -> void
|
|
175
|
+
def symbol_map(value, path, kind: nil, &block)
|
|
176
|
+
object(value, path).each do |name, item|
|
|
177
|
+
item_path = child_path(path, name)
|
|
178
|
+
symbol = @grammar.symbols_by_name[name]
|
|
179
|
+
invalid(item_path, "references missing symbol #{name.inspect}") unless symbol
|
|
180
|
+
invalid(item_path, "must reference a #{kind}") if kind && symbol["kind"] != kind
|
|
181
|
+
block.call(item, item_path, symbol)
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# @rbs (json_value value, String path) -> void
|
|
186
|
+
def validate_state_reference(value, path)
|
|
187
|
+
id = nonnegative_integer(value, path)
|
|
188
|
+
invalid(path, "references missing state id #{id}") unless @states_by_id.key?(id)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# @rbs (json_value value, String path, ?nullable: bool) -> void
|
|
192
|
+
def validate_parser_action(value, path, nullable: false)
|
|
193
|
+
return if nullable && value.nil?
|
|
194
|
+
|
|
195
|
+
action = object(value, path)
|
|
196
|
+
type = enum(field(action, "type", path), "#{path}.type", ACTION_TYPES)
|
|
197
|
+
required = case type
|
|
198
|
+
when "shift" then %w[type state]
|
|
199
|
+
when "reduce" then %w[type production]
|
|
200
|
+
else %w[type]
|
|
201
|
+
end
|
|
202
|
+
record(action, path, required)
|
|
203
|
+
validate_state_reference(action["state"], "#{path}.state") if type == "shift"
|
|
204
|
+
validate_production_reference(action["production"], "#{path}.production") if type == "reduce"
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# @rbs (json_value value, String path) -> void
|
|
208
|
+
def validate_production_reference(value, path)
|
|
209
|
+
id = nonnegative_integer(value, path)
|
|
210
|
+
invalid(path, "references missing production id #{id}") unless @grammar.productions_by_id.key?(id)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# @rbs (json_value value, String path) -> void
|
|
214
|
+
def validate_conflicts(value, path)
|
|
215
|
+
array(value, path).each_with_index do |conflict, index|
|
|
216
|
+
conflict_path = "#{path}[#{index}]"
|
|
217
|
+
conflict = object(conflict, conflict_path)
|
|
218
|
+
type = enum(field(conflict, "type", conflict_path), "#{conflict_path}.type",
|
|
219
|
+
%w[shift_reduce reduce_reduce])
|
|
220
|
+
if type == "shift_reduce"
|
|
221
|
+
validate_shift_reduce(conflict, conflict_path)
|
|
222
|
+
else
|
|
223
|
+
validate_reduce_reduce(conflict, conflict_path)
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# @rbs (json_object conflict, String path) -> void
|
|
229
|
+
def validate_shift_reduce(conflict, path)
|
|
230
|
+
record(conflict, path, %w[type symbol shift_to reduce resolution], %w[midrule_origins entries composite])
|
|
231
|
+
validate_conflict_symbol(conflict["symbol"], "#{path}.symbol")
|
|
232
|
+
validate_state_reference(conflict["shift_to"], "#{path}.shift_to")
|
|
233
|
+
validate_production_reference(conflict["reduce"], "#{path}.reduce")
|
|
234
|
+
validate_resolution(conflict["resolution"], "#{path}.resolution")
|
|
235
|
+
validate_midrule_origins(conflict["midrule_origins"], "#{path}.midrule_origins") if
|
|
236
|
+
conflict.key?("midrule_origins")
|
|
237
|
+
validate_conflict_entries(conflict, path)
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# @rbs (json_object conflict, String path) -> void
|
|
241
|
+
def validate_reduce_reduce(conflict, path)
|
|
242
|
+
record(conflict, path, %w[type symbol reductions resolution], %w[midrule_origins entries composite])
|
|
243
|
+
validate_conflict_symbol(conflict["symbol"], "#{path}.symbol")
|
|
244
|
+
reductions = array(conflict["reductions"], "#{path}.reductions").map.with_index do |id, index|
|
|
245
|
+
nonnegative_integer(id, "#{path}.reductions[#{index}]")
|
|
246
|
+
end
|
|
247
|
+
invalid("#{path}.reductions", "must contain at least two productions") if reductions.length < 2
|
|
248
|
+
reductions.each_with_index do |id, index|
|
|
249
|
+
validate_production_reference(id, "#{path}.reductions[#{index}]")
|
|
250
|
+
end
|
|
251
|
+
if reductions.uniq.length != reductions.length
|
|
252
|
+
invalid("#{path}.reductions", "must contain unique production ids")
|
|
253
|
+
end
|
|
254
|
+
validate_resolution(conflict["resolution"], "#{path}.resolution", reductions: reductions)
|
|
255
|
+
validate_midrule_origins(conflict["midrule_origins"], "#{path}.midrule_origins") if
|
|
256
|
+
conflict.key?("midrule_origins")
|
|
257
|
+
validate_conflict_entries(conflict, path)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# @rbs (json_object conflict, String path) -> void
|
|
261
|
+
def validate_conflict_entries(conflict, path)
|
|
262
|
+
if conflict.key?("entries")
|
|
263
|
+
starts = @data.dig("grammar", "starts") || [@data.dig("grammar", "start")]
|
|
264
|
+
entries = array(conflict["entries"], "#{path}.entries")
|
|
265
|
+
invalid("#{path}.entries", "must not be empty") if entries.empty?
|
|
266
|
+
entries.each_with_index do |name, index|
|
|
267
|
+
name = nonempty_string(name, "#{path}.entries[#{index}]")
|
|
268
|
+
invalid("#{path}.entries[#{index}]", "is not a grammar start symbol") unless starts.include?(name)
|
|
269
|
+
end
|
|
270
|
+
invalid("#{path}.entries", "must be unique") unless entries.uniq.length == entries.length
|
|
271
|
+
end
|
|
272
|
+
boolean(conflict["composite"], "#{path}.composite") if conflict.key?("composite")
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
# @rbs (json_value value, String path) -> void
|
|
276
|
+
def validate_midrule_origins(value, path)
|
|
277
|
+
origins = array(value, path)
|
|
278
|
+
invalid(path, "must not be empty") if origins.empty?
|
|
279
|
+
origins.each_with_index { |origin, index| location(origin, "#{path}[#{index}]") }
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
# @rbs (json_value value, String path) -> void
|
|
283
|
+
def validate_conflict_symbol(value, path)
|
|
284
|
+
name = string(value, path)
|
|
285
|
+
symbol = @grammar.symbols_by_name[name]
|
|
286
|
+
invalid(path, "references missing symbol #{name.inspect}") unless symbol
|
|
287
|
+
invalid(path, "must reference a terminal") unless symbol["kind"] == "terminal"
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
# @rbs (json_value value, String path, ?reductions: Array[Integer]?) -> void
|
|
291
|
+
def validate_resolution(value, path, reductions: nil)
|
|
292
|
+
resolution = record(value, path, %w[by chose], %w[associativity])
|
|
293
|
+
enum(resolution["by"], "#{path}.by", RESOLUTION_KINDS)
|
|
294
|
+
if reductions
|
|
295
|
+
chosen = resolution["chose"]
|
|
296
|
+
validate_production_reference(chosen, "#{path}.chose")
|
|
297
|
+
invalid("#{path}.chose", "must be one of the reductions") unless reductions.include?(chosen)
|
|
298
|
+
else
|
|
299
|
+
enum(resolution["chose"], "#{path}.chose", %w[shift reduce error])
|
|
300
|
+
end
|
|
301
|
+
return unless resolution.key?("associativity")
|
|
302
|
+
|
|
303
|
+
enum(resolution["associativity"], "#{path}.associativity", %w[left right nonassoc])
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
# @rbs () -> void
|
|
307
|
+
def validate_conflict_summary
|
|
308
|
+
path = "$.conflict_summary"
|
|
309
|
+
summary = record(
|
|
310
|
+
@data["conflict_summary"], path, %w[sr resolved_sr rr expected_sr expectation_met],
|
|
311
|
+
%w[expected_rr rr_expectation_met]
|
|
312
|
+
)
|
|
313
|
+
%w[sr resolved_sr rr expected_sr].each do |key|
|
|
314
|
+
nonnegative_integer(summary[key], "#{path}.#{key}")
|
|
315
|
+
end
|
|
316
|
+
boolean(summary["expectation_met"], "#{path}.expectation_met")
|
|
317
|
+
if summary.key?("expected_rr") || summary.key?("rr_expectation_met")
|
|
318
|
+
nonnegative_integer(summary["expected_rr"], "#{path}.expected_rr")
|
|
319
|
+
boolean(summary["rr_expectation_met"], "#{path}.rr_expectation_met")
|
|
320
|
+
end
|
|
321
|
+
validate_conflict_counts(summary, path)
|
|
322
|
+
validate_expectation(summary, path)
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
# @rbs (json_object summary, String path) -> void
|
|
326
|
+
def validate_conflict_counts(summary, path)
|
|
327
|
+
conflicts = @states_by_id.values.flat_map do |state|
|
|
328
|
+
array(state["conflicts"], "$.states.conflicts").map do |conflict|
|
|
329
|
+
record = conflict #: json_object
|
|
330
|
+
record
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
shift_reduce = conflicts.select { |conflict| conflict["type"] == "shift_reduce" }
|
|
334
|
+
counts = {
|
|
335
|
+
"sr" => shift_reduce.count { |conflict| conflict.dig("resolution", "by") == "default_shift" },
|
|
336
|
+
"resolved_sr" => shift_reduce.count { |conflict| conflict.dig("resolution", "by") != "default_shift" },
|
|
337
|
+
"rr" => conflicts.count { |conflict| conflict["type"] == "reduce_reduce" }
|
|
338
|
+
}
|
|
339
|
+
counts.each do |key, actual|
|
|
340
|
+
next if summary[key] == actual
|
|
341
|
+
|
|
342
|
+
label = key == "rr" ? "reduce/reduce" : "shift/reduce"
|
|
343
|
+
invalid("#{path}.#{key}", "must equal the #{actual} recorded #{label} conflicts")
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
# @rbs (json_object summary, String path) -> void
|
|
348
|
+
def validate_expectation(summary, path)
|
|
349
|
+
grammar = @data.fetch("grammar") #: json_object
|
|
350
|
+
grammar_expect = grammar.fetch("expect")
|
|
351
|
+
unless summary["expected_sr"] == grammar_expect
|
|
352
|
+
invalid("#{path}.expected_sr", "must equal embedded grammar expect #{grammar_expect}")
|
|
353
|
+
end
|
|
354
|
+
expected_met = summary["sr"] == summary["expected_sr"]
|
|
355
|
+
unless summary["expectation_met"] == expected_met
|
|
356
|
+
invalid("#{path}.expectation_met", "must be #{expected_met} for the recorded shift/reduce count")
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
grammar_expect_rr = grammar["expect_rr"]
|
|
360
|
+
return if grammar_expect_rr.nil?
|
|
361
|
+
|
|
362
|
+
unless summary["expected_rr"] == grammar_expect_rr
|
|
363
|
+
invalid("#{path}.expected_rr", "must equal embedded grammar expect_rr #{grammar_expect_rr}")
|
|
364
|
+
end
|
|
365
|
+
rr_expected_met = summary["rr"] == summary["expected_rr"]
|
|
366
|
+
return if summary["rr_expectation_met"] == rr_expected_met
|
|
367
|
+
|
|
368
|
+
invalid("#{path}.rr_expectation_met",
|
|
369
|
+
"must be #{rr_expected_met} for the recorded reduce/reduce count")
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
# rubocop:enable Metrics/ClassLength
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
end
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ibex
|
|
4
|
+
module IR
|
|
5
|
+
module Validator
|
|
6
|
+
# @rbs!
|
|
7
|
+
# type json_value = String | Integer | Float | bool | nil | Array[json_value] | Hash[String, json_value]
|
|
8
|
+
# type json_object = Hash[String, json_value]
|
|
9
|
+
|
|
10
|
+
# Shared JSON-shape checks for current IR documents.
|
|
11
|
+
class Base
|
|
12
|
+
POSITION = "(ir):1:1"
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
# @rbs (json_value value, String path, Array[String] required, ?Array[String] optional) -> json_object
|
|
17
|
+
def record(value, path, required, optional = [])
|
|
18
|
+
value = object(value, path)
|
|
19
|
+
missing = required.reject { |key| value.key?(key) }
|
|
20
|
+
invalid(path, "is missing required field #{missing.first.inspect}") unless missing.empty?
|
|
21
|
+
unknown = value.keys - required - optional
|
|
22
|
+
invalid(path, "has unsupported field #{unknown.first.inspect}") unless unknown.empty?
|
|
23
|
+
value
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# @rbs (json_value value, String path) -> json_object
|
|
27
|
+
def object(value, path)
|
|
28
|
+
if value.is_a?(Hash)
|
|
29
|
+
object = value #: json_object
|
|
30
|
+
return object
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
invalid(path, "must be an object")
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @rbs (json_value value, String path) -> Array[json_value]
|
|
37
|
+
def array(value, path)
|
|
38
|
+
if value.is_a?(Array)
|
|
39
|
+
array = value #: Array[json_value]
|
|
40
|
+
return array
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
invalid(path, "must be an array")
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# @rbs (json_value value, String path) -> String
|
|
47
|
+
def string(value, path)
|
|
48
|
+
return value if value.is_a?(String)
|
|
49
|
+
|
|
50
|
+
invalid(path, "must be a string")
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# @rbs (json_value value, String path) -> String
|
|
54
|
+
def nonempty_string(value, path)
|
|
55
|
+
value = string(value, path)
|
|
56
|
+
invalid(path, "must not be empty") if value.empty?
|
|
57
|
+
value
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# @rbs (json_value value, String path) -> Integer
|
|
61
|
+
def integer(value, path)
|
|
62
|
+
return value if value.is_a?(Integer)
|
|
63
|
+
|
|
64
|
+
invalid(path, "must be an integer")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# @rbs (json_value value, String path) -> Integer
|
|
68
|
+
def nonnegative_integer(value, path)
|
|
69
|
+
value = integer(value, path)
|
|
70
|
+
invalid(path, "must be greater than or equal to 0") if value.negative?
|
|
71
|
+
value
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# @rbs (json_value value, String path) -> bool
|
|
75
|
+
def boolean(value, path)
|
|
76
|
+
if [true, false].include?(value)
|
|
77
|
+
result = value #: bool
|
|
78
|
+
return result
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
invalid(path, "must be a boolean")
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# @rbs (json_value value, String path, json_value expected) -> void
|
|
85
|
+
def literal(value, path, expected)
|
|
86
|
+
invalid(path, "must be #{expected.inspect}") unless value == expected
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# @rbs (json_value value, String path, Array[String] values) -> String
|
|
90
|
+
def enum(value, path, values)
|
|
91
|
+
value = string(value, path)
|
|
92
|
+
invalid(path, "must be one of #{values.join(', ')}") unless values.include?(value)
|
|
93
|
+
value
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# @rbs (json_value value, String path, ?nullable: bool) -> void
|
|
97
|
+
def location(value, path, nullable: true)
|
|
98
|
+
return if nullable && value.nil?
|
|
99
|
+
|
|
100
|
+
value = record(value, path, %w[file line column])
|
|
101
|
+
string(value["file"], "#{path}.file")
|
|
102
|
+
positive_integer(value["line"], "#{path}.line")
|
|
103
|
+
positive_integer(value["column"], "#{path}.column")
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# @rbs (json_value value, String path) -> Integer
|
|
107
|
+
def positive_integer(value, path)
|
|
108
|
+
value = integer(value, path)
|
|
109
|
+
invalid(path, "must be greater than or equal to 1") unless value.positive?
|
|
110
|
+
value
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# @rbs (json_value value, String path) -> String?
|
|
114
|
+
def nullable_string(value, path)
|
|
115
|
+
return nil if value.nil?
|
|
116
|
+
|
|
117
|
+
string(value, path)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# @rbs (json_value value, String path) -> void
|
|
121
|
+
def metadata(value, path)
|
|
122
|
+
return if value.nil?
|
|
123
|
+
|
|
124
|
+
value = string(value, path)
|
|
125
|
+
invalid(path, "must not be empty") if value.strip.empty?
|
|
126
|
+
invalid(path, "must be a single line") if value.match?(/[\r\n]/)
|
|
127
|
+
invalid(path, "must not contain control characters") if value.match?(/[[:cntrl:]]/)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# @rbs (json_object value, String key, String path) -> json_value
|
|
131
|
+
def field(value, key, path)
|
|
132
|
+
value.fetch(key) { invalid(path, "is missing required field #{key.inspect}") }
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# @rbs (String path, String key) -> String
|
|
136
|
+
def child_path(path, key)
|
|
137
|
+
key.match?(/\A[$A-Za-z_][$A-Za-z0-9_]*\z/) ? "#{path}.#{key}" : "#{path}[#{key.inspect}]"
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# @rbs (String path, String message) -> bot
|
|
141
|
+
def invalid(path, message)
|
|
142
|
+
raise Ibex::Error, "#{POSITION}: #{path} #{message}"
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|