ibex 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +95 -272
- data/docs/architecture.md +187 -35
- data/docs/bison-import.md +103 -0
- data/docs/comparison-policy.md +127 -0
- data/docs/configuration-model.md +59 -0
- data/docs/configuration-report.md +28 -0
- data/docs/conflict-explanation-reviews/v1/records/README.md +28 -0
- data/docs/conflict-explanation-study.md +62 -0
- data/docs/construction-profiling.md +157 -0
- data/docs/cst-migration.md +3 -4
- data/docs/cst.md +24 -0
- data/docs/decisions/0000-template.md +24 -0
- data/docs/decisions/0001-separate-ir-pipeline.md +34 -0
- data/docs/decisions/0002-opaque-user-code-boundary.md +32 -0
- data/docs/decisions/0003-self-hosted-grammar-frontend.md +32 -0
- data/docs/decisions/0004-shared-semantic-and-lossless-source-model.md +33 -0
- data/docs/decisions/0005-contained-grammar-composition.md +34 -0
- data/docs/decisions/0006-bounded-structural-grammar-lowering.md +32 -0
- data/docs/decisions/0007-shared-parser-construction-pipeline.md +33 -0
- data/docs/decisions/0008-versioned-runtime-package-boundary.md +36 -0
- data/docs/decisions/0009-isolated-parser-sessions.md +34 -0
- data/docs/decisions/0010-committed-runtime-observation.md +34 -0
- data/docs/decisions/0011-versioned-semantic-action-boundary.md +37 -0
- data/docs/decisions/0012-bounded-nonexecuting-analysis.md +37 -0
- data/docs/decisions/0013-transactional-generation-publication.md +37 -0
- data/docs/decisions/0014-versioned-generated-lexer.md +35 -0
- data/docs/decisions/0015-worker-isolated-browser-analysis.md +32 -0
- data/docs/decisions/0016-red-green-concrete-syntax.md +34 -0
- data/docs/decisions/0017-persistent-syntax-artifacts.md +35 -0
- data/docs/decisions/0018-conservative-incremental-syntax-reuse.md +38 -0
- data/docs/decisions/0019-runtime-syntax-session-boundary.md +51 -0
- data/docs/decisions/0020-grammar-ir-parser-contract.md +65 -0
- data/docs/decisions/0021-data-only-parser-table-sidecar.md +50 -0
- data/docs/decisions/0022-manifest-bound-verification-report.md +77 -0
- data/docs/decisions/0023-syntax-only-repair-results.md +48 -0
- data/docs/decisions/0024-direct-ielr-construction.md +42 -0
- data/docs/decisions/README.md +74 -0
- data/docs/declarative-configuration.md +262 -0
- data/docs/development.md +179 -2
- data/docs/direct-ielr-decision.md +120 -0
- data/docs/direct-multi-entry-decision.md +82 -0
- data/docs/editor-setup.md +2 -1
- data/docs/error-ux-review-rubric-v1.md +117 -0
- data/docs/error-ux-reviews/v1/records/README.md +22 -0
- data/docs/error-ux-round2-review-status-v1.json +27 -0
- data/docs/error-ux-round2-reviews/v1/records/README.md +30 -0
- data/docs/error-ux-round2-v1.json +1581 -0
- data/docs/error-ux-round2.md +111 -0
- data/docs/error-ux.md +54 -0
- data/docs/getting-started.md +80 -0
- data/docs/grammar-reference.md +184 -13
- data/docs/ielr-design.md +43 -0
- data/docs/ielr.md +92 -0
- data/docs/ja/bison-import.md +51 -0
- data/docs/ja/stable-api.md +53 -0
- data/docs/lexer-construction-profile.md +109 -0
- data/docs/lexer-migration.md +5 -0
- data/docs/maturity.md +128 -0
- data/docs/project-site-strategy.md +54 -0
- data/docs/racc-migration-evidence.md +45 -0
- data/docs/racc-migration.md +11 -0
- data/docs/release-readiness.md +126 -68
- data/docs/repair-semantics.md +123 -0
- data/docs/runtime-abi-evolution.md +307 -0
- data/docs/stability.md +144 -34
- data/docs/status.md +43 -0
- data/docs/syntax-sessions.md +183 -0
- data/docs/table-artifact.md +125 -0
- data/docs/test-interactions.md +219 -0
- data/docs/verification-report.md +137 -0
- data/docs/verifier-trust-boundary.md +199 -0
- data/docs/workloads.md +132 -0
- data/lib/ibex/analysis/digraph.rb +128 -0
- data/lib/ibex/analysis.rb +1 -0
- data/lib/ibex/bison_import/importer.rb +516 -0
- data/lib/ibex/bison_import/tokenizer.rb +260 -0
- data/lib/ibex/bison_import.rb +200 -0
- data/lib/ibex/bounded_subprocess.rb +171 -0
- data/lib/ibex/cli/ambiguity.rb +14 -5
- data/lib/ibex/cli/analysis.rb +134 -0
- data/lib/ibex/cli/bison_import.rb +121 -0
- data/lib/ibex/cli/config.rb +128 -0
- data/lib/ibex/cli/diagnostics.rb +31 -11
- data/lib/ibex/cli/documentation.rb +11 -8
- data/lib/ibex/cli/equiv.rb +169 -0
- data/lib/ibex/cli/error_messages.rb +11 -4
- data/lib/ibex/cli/explain.rb +14 -5
- data/lib/ibex/cli/fix.rb +203 -0
- data/lib/ibex/cli/formatting.rb +11 -10
- data/lib/ibex/cli/fuzz.rb +200 -0
- data/lib/ibex/cli/fuzz_regressions.rb +145 -0
- data/lib/ibex/cli/generation_artifacts.rb +53 -2
- data/lib/ibex/cli/generation_error_messages.rb +1 -1
- data/lib/ibex/cli/grammar_tests.rb +32 -14
- data/lib/ibex/cli/ir_tools.rb +5 -61
- data/lib/ibex/cli/outputs.rb +60 -33
- data/lib/ibex/cli/reduce.rb +202 -0
- data/lib/ibex/cli/reduce_reporting.rb +71 -0
- data/lib/ibex/cli/samples.rb +49 -23
- data/lib/ibex/cli/verify.rb +116 -0
- data/lib/ibex/cli/watch.rb +6 -5
- data/lib/ibex/cli.rb +357 -56
- data/lib/ibex/codegen/action_locations.rb +1 -1
- data/lib/ibex/codegen/action_method_source.rb +5 -6
- data/lib/ibex/codegen/action_source.rb +3 -2
- data/lib/ibex/codegen/ambiguity.rb +5 -4
- data/lib/ibex/codegen/explain.rb +123 -55
- data/lib/ibex/codegen/generated_action_abi.rb +10 -5
- data/lib/ibex/codegen/rbs.rb +15 -7
- data/lib/ibex/codegen/report.rb +25 -13
- data/lib/ibex/codegen/ruby.rb +28 -64
- data/lib/ibex/codegen/ruby_actions.rb +9 -6
- data/lib/ibex/codegen/ruby_syntax.rb +15 -9
- data/lib/ibex/configuration/analysis_grammar.rb +35 -0
- data/lib/ibex/configuration/explanation.rb +421 -0
- data/lib/ibex/configuration/inspector.rb +232 -0
- data/lib/ibex/configuration.rb +580 -0
- data/lib/ibex/coverage/collector.rb +21 -11
- data/lib/ibex/coverage/event_stream.rb +13 -7
- data/lib/ibex/coverage/report.rb +26 -18
- data/lib/ibex/coverage/runtime_event_validator.rb +30 -21
- data/lib/ibex/delta_reducer.rb +99 -0
- data/lib/ibex/diff.rb +140 -0
- data/lib/ibex/equiv/machine.rb +135 -0
- data/lib/ibex/equiv.rb +373 -0
- data/lib/ibex/fix.rb +557 -0
- data/lib/ibex/frontend/ast.rb +22 -2
- data/lib/ibex/frontend/bootstrap_parser.rb +6 -13
- data/lib/ibex/frontend/diagnostic.rb +1 -1
- data/lib/ibex/frontend/formatter.rb +72 -26
- data/lib/ibex/frontend/generated_parser.rb +147 -117
- data/lib/ibex/frontend/generated_parser_base.rb +7 -3
- data/lib/ibex/frontend/generated_parser_includes.rb +1 -11
- data/lib/ibex/frontend/generation.rb +1 -1
- data/lib/ibex/frontend/parser/declarations.rb +17 -2
- data/lib/ibex/frontend/parser_configuration_support.rb +56 -0
- data/lib/ibex/frontend/regenerator.rb +1 -0
- data/lib/ibex/frontend/resolution.rb +2 -1
- data/lib/ibex/frontend/resolver.rb +1 -1
- data/lib/ibex/frontend/rule_documentation.rb +2 -1
- data/lib/ibex/frontend/source_cursor.rb +2 -2
- data/lib/ibex/frontend/source_span.rb +9 -1
- data/lib/ibex/frontend/token_adapter/declaration_state.rb +38 -6
- data/lib/ibex/frontend/token_adapter.rb +10 -0
- data/lib/ibex/frontend.rb +1 -0
- data/lib/ibex/fuzz.rb +219 -0
- data/lib/ibex/generation_input.rb +1 -1
- data/lib/ibex/generation_manifest.rb +36 -25
- data/lib/ibex/generation_transaction.rb +1 -1
- data/lib/ibex/generation_transaction_recovery.rb +4 -4
- data/lib/ibex/generation_transaction_validation.rb +2 -2
- data/lib/ibex/grammar_tests.rb +1 -1
- data/lib/ibex/ir/automaton_ir.rb +61 -19
- data/lib/ibex/ir/grammar_ir.rb +76 -45
- data/lib/ibex/ir/lexer_ir.rb +5 -5
- data/lib/ibex/ir/parser_contract.rb +135 -0
- data/lib/ibex/ir/serialize.rb +203 -76
- data/lib/ibex/ir/validator/automaton.rb +64 -34
- data/lib/ibex/ir/validator/base.rb +51 -33
- data/lib/ibex/ir/validator/grammar.rb +113 -83
- data/lib/ibex/ir/validator/lexer.rb +2 -2
- data/lib/ibex/ir/validator.rb +2 -1
- data/lib/ibex/ir.rb +16 -3
- data/lib/ibex/lalr/build_metrics.rb +50 -2
- data/lib/ibex/lalr/builder.rb +191 -56
- data/lib/ibex/lalr/conflict_search.rb +15 -4
- data/lib/ibex/lalr/counterexample.rb +19 -14
- data/lib/ibex/lalr/direct_lookaheads.rb +110 -57
- data/lib/ibex/lalr/goto_follows.rb +229 -0
- data/lib/ibex/lalr/ielr/annotator.rb +214 -0
- data/lib/ibex/lalr/ielr/bits.rb +28 -0
- data/lib/ibex/lalr/ielr/inadequacy.rb +47 -0
- data/lib/ibex/lalr/ielr/item_lookaheads.rb +78 -0
- data/lib/ibex/lalr/ielr/pipeline.rb +75 -0
- data/lib/ibex/lalr/ielr/split_stability.rb +78 -0
- data/lib/ibex/lalr/ielr/split_state.rb +20 -0
- data/lib/ibex/lalr/ielr/state_splitter.rb +258 -0
- data/lib/ibex/lalr/ielr_partition.rb +22 -8
- data/lib/ibex/lalr/inadequacy_report.rb +50 -0
- data/lib/ibex/lalr/lookahead_propagation.rb +111 -0
- data/lib/ibex/lalr/lr0_collection.rb +121 -0
- data/lib/ibex/lalr/unreachable_states.rb +80 -0
- data/lib/ibex/lalr.rb +52 -1
- data/lib/ibex/location.rb +3 -3
- data/lib/ibex/lsp/document_handlers.rb +9 -7
- data/lib/ibex/lsp/initialization_handlers.rb +9 -7
- data/lib/ibex/lsp/navigation_handlers.rb +25 -11
- data/lib/ibex/lsp/parser_configuration_assistance.rb +149 -0
- data/lib/ibex/lsp/position_codec.rb +6 -2
- data/lib/ibex/lsp/request_handlers.rb +3 -2
- data/lib/ibex/lsp/request_support.rb +14 -7
- data/lib/ibex/lsp/server.rb +13 -11
- data/lib/ibex/lsp/symbol_index.rb +13 -13
- data/lib/ibex/lsp/symbol_index_builder.rb +30 -20
- data/lib/ibex/lsp/symbol_occurrence.rb +8 -2
- data/lib/ibex/lsp/transport.rb +13 -3
- data/lib/ibex/lsp/workspace.rb +5 -4
- data/lib/ibex/lsp/workspace_analyzer.rb +1 -1
- data/lib/ibex/lsp.rb +1 -0
- data/lib/ibex/messages/en.yml +28 -0
- data/lib/ibex/messages/ja.yml +28 -0
- data/lib/ibex/messages.rb +68 -0
- data/lib/ibex/metrics.rb +175 -0
- data/lib/ibex/normalize/declarations.rb +2 -0
- data/lib/ibex/normalize/diagnostics.rb +63 -38
- data/lib/ibex/normalize/expander.rb +5 -4
- data/lib/ibex/normalize/expression.rb +8 -6
- data/lib/ibex/normalize/grammar_builder.rb +26 -0
- data/lib/ibex/normalize/inline_expansion.rb +100 -49
- data/lib/ibex/normalize/lexer.rb +3 -3
- data/lib/ibex/normalize/parameter_ebnf_lowering.rb +11 -10
- data/lib/ibex/normalize/parameter_lowering.rb +40 -23
- data/lib/ibex/normalize/parameters.rb +31 -4
- data/lib/ibex/normalize/parser_configuration.rb +70 -0
- data/lib/ibex/normalize.rb +10 -20
- data/lib/ibex/racc_migration/report.rb +6 -3
- data/lib/ibex/rake_task.rb +1 -1
- data/lib/ibex/samples.rb +43 -13
- data/lib/ibex/table_artifact/builder.rb +266 -0
- data/lib/ibex/table_artifact/cst_projection.rb +70 -0
- data/lib/ibex/table_artifact/document.rb +39 -0
- data/lib/ibex/table_artifact/executor.rb +187 -0
- data/lib/ibex/table_artifact/serializer.rb +57 -0
- data/lib/ibex/table_artifact/validator/metadata.rb +179 -0
- data/lib/ibex/table_artifact/validator/support.rb +86 -0
- data/lib/ibex/table_artifact/validator/tables.rb +238 -0
- data/lib/ibex/table_artifact/validator.rb +253 -0
- data/lib/ibex/table_artifact.rb +88 -0
- data/lib/ibex/table_simulation/result.rb +6 -2
- data/lib/ibex/table_simulation/step.rb +3 -1
- data/lib/ibex/tables.rb +14 -0
- data/lib/ibex/verifiable_generation_bundle.rb +86 -0
- data/lib/ibex/verification_report/builder.rb +159 -0
- data/lib/ibex/verification_report/canonical_ir.rb +123 -0
- data/lib/ibex/verification_report/logical_path.rb +68 -0
- data/lib/ibex/verification_report/validator.rb +329 -0
- data/lib/ibex/verification_report.rb +69 -0
- data/lib/ibex/verify/action_correspondence.rb +138 -0
- data/lib/ibex/verify/language_witness.rb +295 -0
- data/lib/ibex/verify/reference_collection.rb +190 -0
- data/lib/ibex/verify/result.rb +73 -0
- data/lib/ibex/verify/verifier.rb +598 -0
- data/lib/ibex/verify.rb +15 -0
- data/lib/ibex/version.rb +1 -1
- data/lib/ibex/watch/runner.rb +10 -1
- data/lib/ibex/watch/source_snapshot.rb +13 -8
- data/lib/ibex.rb +10 -0
- data/schema/{automaton-ir-v1.schema.json → automaton-ir-definitions.schema.json} +6 -6
- data/schema/{automaton-ir-v2.schema.json → automaton-ir.schema.json} +14 -7
- data/schema/bison-import-v1.schema.json +106 -0
- data/schema/conflict-explanation-review-v1.schema.json +196 -0
- data/schema/conflict-explanation-study-v1.schema.json +528 -0
- data/schema/construction-profile-v1.schema.json +779 -0
- data/schema/diff-v1.schema.json +41 -0
- data/schema/direct-ielr-decision-v1.schema.json +200 -0
- data/schema/equiv-v1.schema.json +64 -0
- data/schema/error-ux-review-v1.schema.json +609 -0
- data/schema/error-ux-round2-review-v1.schema.json +191 -0
- data/schema/error-ux-round2-v1.schema.json +519 -0
- data/schema/explain-v1.schema.json +63 -1
- data/schema/fix-v1.schema.json +64 -0
- data/schema/fix-v2.schema.json +66 -0
- data/schema/fix-v3.schema.json +101 -0
- data/schema/fuzz-regression-v1.schema.json +79 -0
- data/schema/fuzz-v1.schema.json +114 -0
- data/schema/{grammar-ir-v2.schema.json → grammar-ir-extensions.schema.json} +20 -65
- data/schema/{grammar-ir-v1.schema.json → grammar-ir-foundation.schema.json} +3 -3
- data/schema/grammar-ir.schema.json +271 -0
- data/schema/ielr-benchmark-v1.schema.json +85 -0
- data/schema/lexer-profile-v1.schema.json +491 -0
- data/schema/metrics-v1.schema.json +60 -0
- data/schema/reduce-v1.schema.json +22 -0
- data/schema/reduce-v2.schema.json +63 -0
- data/schema/table-artifact-v1.schema.json +377 -0
- data/schema/verification-report-v1.schema.json +222 -0
- data/schema/verify-v1.schema.json +42 -0
- data/sig/ibex/analysis/digraph.rbs +19 -0
- data/sig/ibex/bison_import/importer.rbs +140 -0
- data/sig/ibex/bison_import/tokenizer.rbs +91 -0
- data/sig/ibex/bison_import.rbs +95 -0
- data/sig/ibex/bounded_subprocess.rbs +76 -0
- data/sig/ibex/cli/ambiguity.rbs +6 -0
- data/sig/ibex/cli/analysis.rbs +43 -0
- data/sig/ibex/cli/bison_import.rbs +32 -0
- data/sig/ibex/cli/config.rbs +35 -0
- data/sig/ibex/cli/diagnostics.rbs +16 -3
- data/sig/ibex/cli/documentation.rbs +5 -1
- data/sig/ibex/cli/equiv.rbs +49 -0
- data/sig/ibex/cli/error_messages.rbs +6 -0
- data/sig/ibex/cli/explain.rbs +6 -0
- data/sig/ibex/cli/fix.rbs +53 -0
- data/sig/ibex/cli/formatting.rbs +5 -1
- data/sig/ibex/cli/fuzz.rbs +47 -0
- data/sig/ibex/cli/fuzz_regressions.rbs +40 -0
- data/sig/ibex/cli/generation_artifacts.rbs +21 -2
- data/sig/ibex/cli/generation_error_messages.rbs +2 -2
- data/sig/ibex/cli/grammar_tests.rbs +15 -3
- data/sig/ibex/cli/ir_tools.rbs +7 -19
- data/sig/ibex/cli/outputs.rbs +9 -3
- data/sig/ibex/cli/reduce.rbs +60 -0
- data/sig/ibex/cli/reduce_reporting.rbs +27 -0
- data/sig/ibex/cli/samples.rbs +8 -0
- data/sig/ibex/cli/verify.rbs +28 -0
- data/sig/ibex/cli/watch.rbs +2 -2
- data/sig/ibex/cli.rbs +79 -5
- data/sig/ibex/codegen/action_method_source.rbs +4 -4
- data/sig/ibex/codegen/explain.rbs +45 -25
- data/sig/ibex/codegen/generated_action_abi.rbs +14 -10
- data/sig/ibex/codegen/rbs.rbs +12 -10
- data/sig/ibex/codegen/report.rbs +12 -12
- data/sig/ibex/codegen/ruby.rbs +18 -15
- data/sig/ibex/codegen/ruby_actions.rbs +6 -6
- data/sig/ibex/codegen/ruby_syntax.rbs +10 -8
- data/sig/ibex/configuration/analysis_grammar.rbs +13 -0
- data/sig/ibex/configuration/explanation.rbs +195 -0
- data/sig/ibex/configuration/inspector.rbs +53 -0
- data/sig/ibex/configuration.rbs +242 -0
- data/sig/ibex/coverage/collector.rbs +16 -14
- data/sig/ibex/coverage/event_stream.rbs +12 -10
- data/sig/ibex/coverage/report.rbs +20 -18
- data/sig/ibex/coverage/runtime_event_validator.rbs +38 -36
- data/sig/ibex/delta_reducer.rbs +38 -0
- data/sig/ibex/diff.rbs +47 -0
- data/sig/ibex/equiv/machine.rbs +54 -0
- data/sig/ibex/equiv.rbs +129 -0
- data/sig/ibex/fix.rbs +138 -0
- data/sig/ibex/frontend/ast.rbs +33 -7
- data/sig/ibex/frontend/bootstrap_parser.rbs +2 -0
- data/sig/ibex/frontend/diagnostic.rbs +2 -2
- data/sig/ibex/frontend/formatter.rbs +38 -30
- data/sig/ibex/frontend/generated_parser.rbs +87 -77
- data/sig/ibex/frontend/generated_parser_base.rbs +4 -2
- data/sig/ibex/frontend/parser/declarations.rbs +3 -0
- data/sig/ibex/frontend/parser_configuration_support.rbs +27 -0
- data/sig/ibex/frontend/resolution.rbs +3 -2
- data/sig/ibex/frontend/source_cursor.rbs +2 -2
- data/sig/ibex/frontend/source_span.rbs +5 -2
- data/sig/ibex/frontend/token_adapter/declaration_state.rbs +13 -1
- data/sig/ibex/frontend/token_adapter.rbs +6 -0
- data/sig/ibex/fuzz.rbs +71 -0
- data/sig/ibex/generation_input.rbs +2 -2
- data/sig/ibex/generation_manifest.rbs +35 -32
- data/sig/ibex/generation_transaction_recovery.rbs +2 -2
- data/sig/ibex/generation_transaction_validation.rbs +2 -2
- data/sig/ibex/grammar_tests.rbs +2 -2
- data/sig/ibex/ir/automaton_ir.rbs +30 -11
- data/sig/ibex/ir/grammar_ir.rbs +41 -27
- data/sig/ibex/ir/lexer_ir.rbs +8 -8
- data/sig/ibex/ir/parser_contract.rbs +69 -0
- data/sig/ibex/ir/serialize.rbs +63 -28
- data/sig/ibex/ir/validator/automaton.rbs +47 -44
- data/sig/ibex/ir/validator/base.rbs +35 -31
- data/sig/ibex/ir/validator/grammar.rbs +78 -67
- data/sig/ibex/ir/validator/lexer.rbs +4 -4
- data/sig/ibex/ir.rbs +9 -3
- data/sig/ibex/lalr/build_metrics.rbs +42 -2
- data/sig/ibex/lalr/builder.rbs +75 -24
- data/sig/ibex/lalr/conflict_search.rbs +5 -2
- data/sig/ibex/lalr/counterexample.rbs +17 -14
- data/sig/ibex/lalr/direct_lookaheads.rbs +35 -28
- data/sig/ibex/lalr/goto_follows.rbs +89 -0
- data/sig/ibex/lalr/ielr/annotator.rbs +67 -0
- data/sig/ibex/lalr/ielr/bits.rbs +14 -0
- data/sig/ibex/lalr/ielr/inadequacy.rbs +24 -0
- data/sig/ibex/lalr/ielr/item_lookaheads.rbs +35 -0
- data/sig/ibex/lalr/ielr/pipeline.rbs +17 -0
- data/sig/ibex/lalr/ielr/split_stability.rbs +27 -0
- data/sig/ibex/lalr/ielr/split_state.rbs +14 -0
- data/sig/ibex/lalr/ielr/state_splitter.rbs +76 -0
- data/sig/ibex/lalr/ielr_partition.rbs +17 -5
- data/sig/ibex/lalr/inadequacy_report.rbs +21 -0
- data/sig/ibex/lalr/lookahead_propagation.rbs +38 -0
- data/sig/ibex/lalr/lr0_collection.rbs +50 -0
- data/sig/ibex/lalr/unreachable_states.rbs +25 -0
- data/sig/ibex/lalr.rbs +11 -1
- data/sig/ibex/location.rbs +6 -6
- data/sig/ibex/lsp/document_handlers.rbs +8 -8
- data/sig/ibex/lsp/initialization_handlers.rbs +12 -12
- data/sig/ibex/lsp/navigation_handlers.rbs +15 -12
- data/sig/ibex/lsp/parser_configuration_assistance.rbs +49 -0
- data/sig/ibex/lsp/position_codec.rbs +8 -4
- data/sig/ibex/lsp/request_handlers.rbs +4 -4
- data/sig/ibex/lsp/request_support.rbs +8 -8
- data/sig/ibex/lsp/server.rbs +16 -16
- data/sig/ibex/lsp/symbol_index.rbs +20 -21
- data/sig/ibex/lsp/symbol_index_builder.rbs +9 -8
- data/sig/ibex/lsp/symbol_occurrence.rbs +11 -5
- data/sig/ibex/lsp/transport.rbs +18 -6
- data/sig/ibex/lsp/workspace.rbs +3 -2
- data/sig/ibex/lsp/workspace_analyzer.rbs +1 -1
- data/sig/ibex/messages.rbs +26 -0
- data/sig/ibex/metrics.rbs +50 -0
- data/sig/ibex/normalize/diagnostics.rbs +4 -4
- data/sig/ibex/normalize/expander.rbs +2 -2
- data/sig/ibex/normalize/expression.rbs +10 -8
- data/sig/ibex/normalize/grammar_builder.rbs +11 -0
- data/sig/ibex/normalize/inline_expansion.rbs +59 -50
- data/sig/ibex/normalize/lexer.rbs +4 -4
- data/sig/ibex/normalize/parameter_ebnf_lowering.rbs +15 -14
- data/sig/ibex/normalize/parameter_lowering.rbs +18 -18
- data/sig/ibex/normalize/parameters.rbs +13 -8
- data/sig/ibex/normalize/parser_configuration.rbs +23 -0
- data/sig/ibex/normalize.rbs +11 -5
- data/sig/ibex/racc_migration/report.rbs +8 -6
- data/sig/ibex/rake_task.rbs +1 -1
- data/sig/ibex/samples.rbs +13 -4
- data/sig/ibex/table_artifact/builder.rbs +93 -0
- data/sig/ibex/table_artifact/cst_projection.rbs +20 -0
- data/sig/ibex/table_artifact/document.rbs +27 -0
- data/sig/ibex/table_artifact/executor.rbs +66 -0
- data/sig/ibex/table_artifact/serializer.rbs +25 -0
- data/sig/ibex/table_artifact/validator/metadata.rbs +52 -0
- data/sig/ibex/table_artifact/validator/support.rbs +46 -0
- data/sig/ibex/table_artifact/validator/tables.rbs +63 -0
- data/sig/ibex/table_artifact/validator.rbs +66 -0
- data/sig/ibex/table_artifact.rbs +32 -0
- data/sig/ibex/table_simulation/result.rbs +8 -4
- data/sig/ibex/table_simulation/step.rbs +4 -2
- data/sig/ibex/tables.rbs +10 -9
- data/sig/ibex/verifiable_generation_bundle.rbs +24 -0
- data/sig/ibex/verification_report/builder.rbs +53 -0
- data/sig/ibex/verification_report/canonical_ir.rbs +41 -0
- data/sig/ibex/verification_report/logical_path.rbs +34 -0
- data/sig/ibex/verification_report/validator.rbs +114 -0
- data/sig/ibex/verification_report.rbs +44 -0
- data/sig/ibex/verify/action_correspondence.rbs +50 -0
- data/sig/ibex/verify/language_witness.rbs +112 -0
- data/sig/ibex/verify/reference_collection.rbs +63 -0
- data/sig/ibex/verify/result.rbs +52 -0
- data/sig/ibex/verify/verifier.rbs +170 -0
- data/sig/ibex/verify.rbs +6 -0
- data/sig/ibex/watch/runner.rbs +12 -2
- data/sig/ibex/watch/source_snapshot.rbs +13 -9
- metadata +232 -12
- data/lib/ibex/ir/migration.rb +0 -120
- data/sig/ibex/ir/migration.rbs +0 -34
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ibex
|
|
4
|
+
module TableArtifact
|
|
5
|
+
class MetadataValidator
|
|
6
|
+
include ValidationSupport
|
|
7
|
+
|
|
8
|
+
# @rbs (Hash[String, ValidationSupport::json_value] payload, symbols: Array[Hash[String, ValidationSupport::json_value]],
|
|
9
|
+
# productions: Array[Hash[String, ValidationSupport::json_value]]) -> void
|
|
10
|
+
def initialize(payload, symbols:, productions:)
|
|
11
|
+
@payload = payload
|
|
12
|
+
@symbols = symbols
|
|
13
|
+
@productions = productions
|
|
14
|
+
@terminal_ids = ids_for_kind(symbols, "terminal")
|
|
15
|
+
@nonterminal_ids = ids_for_kind(symbols, "nonterminal")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# @rbs () -> void
|
|
19
|
+
def validate!
|
|
20
|
+
validate_semantic_actions(@payload.fetch("semantic_actions"))
|
|
21
|
+
validate_recovery(@payload.fetch("recovery"))
|
|
22
|
+
validate_cst(@payload.fetch("cst"))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
# @rbs (Array[Hash[String, ValidationSupport::json_value]] symbols, String kind) -> Set[Integer]
|
|
28
|
+
def ids_for_kind(symbols, kind)
|
|
29
|
+
symbols.filter_map do |symbol|
|
|
30
|
+
next unless symbol.fetch("kind") == kind
|
|
31
|
+
|
|
32
|
+
symbol.fetch("id") #: Integer
|
|
33
|
+
end.to_set
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @rbs (ValidationSupport::json_value data) -> void
|
|
37
|
+
def validate_semantic_actions(data)
|
|
38
|
+
path = "$.payload.semantic_actions"
|
|
39
|
+
data = record(data, path, %w[binding verified slots])
|
|
40
|
+
enum(data.fetch("binding"), "#{path}.binding", ["opaque-wrapper-production-id-v1"])
|
|
41
|
+
invalid("#{path}.verified", "must be false") unless boolean(data.fetch("verified"), "#{path}.verified") == false
|
|
42
|
+
slots = integer_ids(data.fetch("slots"), "#{path}.slots")
|
|
43
|
+
expected = @productions.filter_map { |production| production.fetch("action_slot") }
|
|
44
|
+
invalid("#{path}.slots", "must match production action slots") unless slots == expected
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# @rbs (ValidationSupport::json_value data) -> void
|
|
48
|
+
def validate_recovery(data)
|
|
49
|
+
path = "$.payload.recovery"
|
|
50
|
+
data = record(data, path, %w[sync_token_ids on_error_reduce_symbol_ids])
|
|
51
|
+
sync_ids = integer_ids(data.fetch("sync_token_ids"), "#{path}.sync_token_ids", sorted: false)
|
|
52
|
+
sync_ids.each do |id|
|
|
53
|
+
invalid("#{path}.sync_token_ids", "must reference terminals") unless @terminal_ids.include?(id)
|
|
54
|
+
end
|
|
55
|
+
groups = array(data.fetch("on_error_reduce_symbol_ids"), "#{path}.on_error_reduce_symbol_ids")
|
|
56
|
+
groups.each_with_index do |group, index|
|
|
57
|
+
ids = integer_ids(group, "#{path}.on_error_reduce_symbol_ids[#{index}]", sorted: false)
|
|
58
|
+
invalid("#{path}.on_error_reduce_symbol_ids[#{index}]", "must not be empty") if ids.empty?
|
|
59
|
+
ids.each do |id|
|
|
60
|
+
invalid("#{path}.on_error_reduce_symbol_ids[#{index}]", "must reference nonterminals") unless
|
|
61
|
+
@nonterminal_ids.include?(id)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# @rbs (ValidationSupport::json_value data) -> void
|
|
67
|
+
def validate_cst(data)
|
|
68
|
+
return if data.nil?
|
|
69
|
+
|
|
70
|
+
path = "$.payload.cst"
|
|
71
|
+
data = record(data, path, %w[version trivia_policy kinds slots])
|
|
72
|
+
invalid("#{path}.version", "must be 1") unless integer(data.fetch("version"), "#{path}.version") == 1
|
|
73
|
+
enum(data.fetch("trivia_policy"), "#{path}.trivia_policy", %w[leading balanced drop])
|
|
74
|
+
kind_count = validate_cst_kinds(data.fetch("kinds"), "#{path}.kinds")
|
|
75
|
+
validate_cst_slots(data.fetch("slots"), "#{path}.slots", kind_count)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# @rbs (ValidationSupport::json_value data, String path) -> Integer
|
|
79
|
+
def validate_cst_kinds(data, path)
|
|
80
|
+
keys = %w[names terminal_range nonterminal_range named named_nonterminals trivia synthetic]
|
|
81
|
+
data = record(data, path, keys)
|
|
82
|
+
names = array(data.fetch("names"), "#{path}.names") #: Array[String]
|
|
83
|
+
names.each_with_index { |name, index| string(name, "#{path}.names[#{index}]") }
|
|
84
|
+
validate_range(data.fetch("terminal_range"), "#{path}.terminal_range", names.length)
|
|
85
|
+
validate_range(data.fetch("nonterminal_range"), "#{path}.nonterminal_range", names.length)
|
|
86
|
+
%w[named trivia synthetic].each { |key| validate_named_kinds(data.fetch(key), "#{path}.#{key}", names) }
|
|
87
|
+
validate_named_nonterminals(data.fetch("named_nonterminals"), "#{path}.named_nonterminals", names.length)
|
|
88
|
+
names.length
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# @rbs (ValidationSupport::json_value data, String path, Integer limit) -> void
|
|
92
|
+
def validate_range(data, path, limit)
|
|
93
|
+
values = array(data, path)
|
|
94
|
+
invalid(path, "must contain two bounds") unless values.length == 2
|
|
95
|
+
start = integer(values.fetch(0), "#{path}[0]", minimum: 0)
|
|
96
|
+
finish = integer(values.fetch(1), "#{path}[1]", minimum: 0)
|
|
97
|
+
invalid(path, "must be an ordered half-open range") unless finish.between?(start, limit)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# @rbs (ValidationSupport::json_value data, String path, Array[String] names) -> void
|
|
101
|
+
def validate_named_kinds(data, path, names)
|
|
102
|
+
entries = array(data, path)
|
|
103
|
+
ids = entries.map.with_index do |entry, index|
|
|
104
|
+
entry_path = "#{path}[#{index}]"
|
|
105
|
+
entry = record(entry, entry_path, %w[name id])
|
|
106
|
+
name = string(entry.fetch("name"), "#{entry_path}.name")
|
|
107
|
+
id = integer(entry.fetch("id"), "#{entry_path}.id", minimum: 0)
|
|
108
|
+
invalid(entry_path, "does not match the kind name table") unless names[id] == name
|
|
109
|
+
id
|
|
110
|
+
end
|
|
111
|
+
sorted_unique!(ids, path)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# @rbs (ValidationSupport::json_value data, String path, Integer kind_count) -> void
|
|
115
|
+
def validate_named_nonterminals(data, path, kind_count)
|
|
116
|
+
pairs = array(data, path).map.with_index do |entry, index|
|
|
117
|
+
entry_path = "#{path}[#{index}]"
|
|
118
|
+
entry = record(entry, entry_path, %w[kind_id symbol_id])
|
|
119
|
+
kind_id = integer(entry.fetch("kind_id"), "#{entry_path}.kind_id", minimum: 0)
|
|
120
|
+
invalid("#{entry_path}.kind_id", "references a missing kind") unless kind_id < kind_count
|
|
121
|
+
symbol_id = integer(entry.fetch("symbol_id"), "#{entry_path}.symbol_id", minimum: 0)
|
|
122
|
+
invalid("#{entry_path}.symbol_id", "must reference a nonterminal") unless @nonterminal_ids.include?(symbol_id)
|
|
123
|
+
[kind_id, symbol_id]
|
|
124
|
+
end
|
|
125
|
+
return if pairs == pairs.sort && pairs.map(&:first).uniq.length == pairs.length
|
|
126
|
+
|
|
127
|
+
invalid(path,
|
|
128
|
+
"must be sorted with unique kind ids")
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# @rbs (ValidationSupport::json_value data, String path, Integer kind_count) -> void
|
|
132
|
+
def validate_cst_slots(data, path, kind_count)
|
|
133
|
+
production_ids = array(data, path).map.with_index do |slot, index|
|
|
134
|
+
slot_path = "#{path}[#{index}]"
|
|
135
|
+
slot = record(slot, slot_path, %w[production_id node_kind_id node_name fields])
|
|
136
|
+
production_id = integer(slot.fetch("production_id"), "#{slot_path}.production_id", minimum: 0)
|
|
137
|
+
unless production_id < @productions.length
|
|
138
|
+
invalid("#{slot_path}.production_id",
|
|
139
|
+
"references a missing production")
|
|
140
|
+
end
|
|
141
|
+
node_kind = integer(slot.fetch("node_kind_id"), "#{slot_path}.node_kind_id", minimum: 0)
|
|
142
|
+
invalid("#{slot_path}.node_kind_id", "references a missing kind") unless node_kind < kind_count
|
|
143
|
+
string(slot.fetch("node_name"), "#{slot_path}.node_name")
|
|
144
|
+
validate_fields(slot.fetch("fields"), "#{slot_path}.fields", @productions.fetch(production_id))
|
|
145
|
+
production_id
|
|
146
|
+
end
|
|
147
|
+
sorted_unique!(production_ids, path)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# @rbs (ValidationSupport::json_value data, String path,
|
|
151
|
+
# Hash[String, ValidationSupport::json_value] production) -> void
|
|
152
|
+
def validate_fields(data, path, production)
|
|
153
|
+
names = array(data, path).map.with_index do |field, index|
|
|
154
|
+
field_path = "#{path}[#{index}]"
|
|
155
|
+
field = record(field, field_path, %w[name index extraction])
|
|
156
|
+
name = string(field.fetch("name"), "#{field_path}.name")
|
|
157
|
+
field_index = integer(field.fetch("index"), "#{field_path}.index", minimum: 0)
|
|
158
|
+
rhs_length = production.fetch("rhs_length") #: Integer
|
|
159
|
+
invalid("#{field_path}.index", "exceeds production rhs") unless field_index < rhs_length
|
|
160
|
+
extraction = field.fetch("extraction")
|
|
161
|
+
enum(extraction, "#{field_path}.extraction", %w[repetition separated_list]) unless extraction.nil?
|
|
162
|
+
name
|
|
163
|
+
end
|
|
164
|
+
invalid(path, "must have unique field names") unless names.uniq.length == names.length
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# @rbs (ValidationSupport::json_value data, String path, ?sorted: bool) -> Array[Integer]
|
|
168
|
+
def integer_ids(data, path, sorted: true)
|
|
169
|
+
ids = array(data, path).map.with_index { |id, index| integer(id, "#{path}[#{index}]", minimum: 0) }
|
|
170
|
+
if sorted
|
|
171
|
+
sorted_unique!(ids, path)
|
|
172
|
+
else
|
|
173
|
+
invalid(path, "must contain unique ids") unless ids.uniq.length == ids.length
|
|
174
|
+
end
|
|
175
|
+
ids
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ibex
|
|
4
|
+
module TableArtifact
|
|
5
|
+
module ValidationSupport
|
|
6
|
+
# @rbs!
|
|
7
|
+
# type json_value = String | Integer | Float | bool | nil | Array[json_value] | Hash[String, json_value]
|
|
8
|
+
|
|
9
|
+
DIGEST = /\Asha256:[0-9a-f]{64}\z/ #: Regexp
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
# @rbs (json_value value, String path, Array[String] keys) -> Hash[String, json_value]
|
|
14
|
+
def record(value, path, keys)
|
|
15
|
+
invalid(path, "must be an object") unless value.is_a?(Hash)
|
|
16
|
+
invalid(path, "must use string keys") unless value.keys.all?(String)
|
|
17
|
+
|
|
18
|
+
missing = keys - value.keys
|
|
19
|
+
extra = value.keys - keys
|
|
20
|
+
invalid(path, "is missing #{missing.join(', ')}") unless missing.empty?
|
|
21
|
+
invalid(path, "contains unknown fields #{extra.join(', ')}") unless extra.empty?
|
|
22
|
+
value #: Hash[String, json_value]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @rbs (json_value value, String path) -> Array[json_value]
|
|
26
|
+
def array(value, path)
|
|
27
|
+
invalid(path, "must be an array") unless value.is_a?(Array)
|
|
28
|
+
value #: Array[json_value]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @rbs (json_value value, String path, ?allow_empty: bool) -> String
|
|
32
|
+
def string(value, path, allow_empty: false)
|
|
33
|
+
invalid(path, "must be a string") unless value.is_a?(String)
|
|
34
|
+
invalid(path, "must not be empty") if !allow_empty && value.empty?
|
|
35
|
+
value #: String
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# @rbs (json_value value, String path, ?minimum: Integer?) -> Integer
|
|
39
|
+
def integer(value, path, minimum: nil)
|
|
40
|
+
invalid(path, "must be an integer") unless value.is_a?(Integer)
|
|
41
|
+
invalid(path, "must be at least #{minimum}") if minimum && value < minimum
|
|
42
|
+
value #: Integer
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# @rbs (json_value value, String path) -> bool
|
|
46
|
+
def boolean(value, path)
|
|
47
|
+
invalid(path, "must be true or false") unless [true, false].include?(value)
|
|
48
|
+
value #: bool
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# @rbs [T] (T value, String path, Array[T] values) -> T
|
|
52
|
+
def enum(value, path, values)
|
|
53
|
+
invalid(path, "must be one of #{values.join(', ')}") unless values.include?(value)
|
|
54
|
+
value
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# @rbs (json_value value, String path) -> String
|
|
58
|
+
def digest(value, path)
|
|
59
|
+
invalid(path, "must be a sha256 digest") unless value.is_a?(String) && DIGEST.match?(value)
|
|
60
|
+
value
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# @rbs (json_value value, String path) -> String?
|
|
64
|
+
def nullable_string(value, path)
|
|
65
|
+
string(value, path, allow_empty: true) unless value.nil?
|
|
66
|
+
value #: String?
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# @rbs (json_value value, String path, ?minimum: Integer?) -> Integer?
|
|
70
|
+
def nullable_integer(value, path, minimum: nil)
|
|
71
|
+
integer(value, path, minimum: minimum) unless value.nil?
|
|
72
|
+
value #: Integer?
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# @rbs (Array[json_value] values, String path) -> void
|
|
76
|
+
def sorted_unique!(values, path)
|
|
77
|
+
invalid(path, "must be sorted and unique") unless values == values.sort.uniq
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# @rbs (String path, String message) -> bot
|
|
81
|
+
def invalid(path, message)
|
|
82
|
+
raise ValidationError, "#{path} #{message}"
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ibex
|
|
4
|
+
module TableArtifact
|
|
5
|
+
class TableValidator
|
|
6
|
+
include ValidationSupport
|
|
7
|
+
|
|
8
|
+
# @rbs!
|
|
9
|
+
# private def integer_array: (ValidationSupport::json_value value, String path,
|
|
10
|
+
# allow_nil: false, minimum: Integer?) -> Array[Integer]
|
|
11
|
+
# | (ValidationSupport::json_value value, String path,
|
|
12
|
+
# allow_nil: true, minimum: Integer?) -> Array[Integer?]
|
|
13
|
+
|
|
14
|
+
# @rbs (Hash[String, ValidationSupport::json_value] data, state_count: Integer, production_count: Integer,
|
|
15
|
+
# terminal_ids: Set[Integer], nonterminal_ids: Set[Integer], representation: String) -> void
|
|
16
|
+
def initialize(data, state_count:, production_count:, terminal_ids:, nonterminal_ids:, representation:)
|
|
17
|
+
@data = data
|
|
18
|
+
@state_count = state_count
|
|
19
|
+
@production_count = production_count
|
|
20
|
+
@terminal_ids = terminal_ids
|
|
21
|
+
@nonterminal_ids = nonterminal_ids
|
|
22
|
+
@representation = representation
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @rbs () -> void
|
|
26
|
+
def validate!
|
|
27
|
+
record(@data, "$.payload.tables", %w[actions gotos default_actions])
|
|
28
|
+
validate_actions(@data.fetch("actions"))
|
|
29
|
+
validate_gotos(@data.fetch("gotos"))
|
|
30
|
+
validate_defaults(@data.fetch("default_actions"))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
# @rbs (ValidationSupport::json_value table) -> void
|
|
36
|
+
def validate_actions(table)
|
|
37
|
+
invalid("$.payload.tables.actions", "must be an object") unless table.is_a?(Hash)
|
|
38
|
+
table_data = table #: Hash[String, ValidationSupport::json_value]
|
|
39
|
+
encoding = table_data["encoding"]
|
|
40
|
+
expected = @representation == "compact" ? "signed-row-displacement-v1" : "signed-sparse-rows-v1"
|
|
41
|
+
invalid("$.payload.tables.actions.encoding", "does not match table representation") unless encoding == expected
|
|
42
|
+
case encoding
|
|
43
|
+
when "signed-sparse-rows-v1" then validate_sparse_actions(table_data)
|
|
44
|
+
when "signed-row-displacement-v1" then validate_compact_actions(table_data)
|
|
45
|
+
else invalid("$.payload.tables.actions.encoding", "is unsupported")
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# @rbs (Hash[String, ValidationSupport::json_value] table) -> void
|
|
50
|
+
def validate_sparse_actions(table)
|
|
51
|
+
record(table, "$.payload.tables.actions", %w[encoding rows])
|
|
52
|
+
rows = array(table.fetch("rows"), "$.payload.tables.actions.rows")
|
|
53
|
+
invalid("$.payload.tables.actions.rows", "must contain one row per state") unless rows.length == @state_count
|
|
54
|
+
rows.each_with_index do |row, state|
|
|
55
|
+
token_ids = array(row, "$.payload.tables.actions.rows[#{state}]").map.with_index do |cell, index|
|
|
56
|
+
path = "$.payload.tables.actions.rows[#{state}][#{index}]"
|
|
57
|
+
cell = record(cell, path, %w[token_id code])
|
|
58
|
+
token_id = integer(cell.fetch("token_id"), "#{path}.token_id", minimum: 0)
|
|
59
|
+
invalid("#{path}.token_id", "must reference a terminal") unless @terminal_ids.include?(token_id)
|
|
60
|
+
validate_token_action(cell.fetch("code"), token_id, "#{path}.code")
|
|
61
|
+
token_id
|
|
62
|
+
end
|
|
63
|
+
sorted_unique!(token_ids, "$.payload.tables.actions.rows[#{state}]")
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# @rbs (Hash[String, ValidationSupport::json_value] table) -> void
|
|
68
|
+
def validate_compact_actions(table)
|
|
69
|
+
keys = %w[encoding row_count column_count offsets codes checks]
|
|
70
|
+
record(table, "$.payload.tables.actions", keys)
|
|
71
|
+
enum(table.fetch("encoding"), "$.payload.tables.actions.encoding", ["signed-row-displacement-v1"])
|
|
72
|
+
validate_row_count(table, "$.payload.tables.actions")
|
|
73
|
+
column_count = nullable_integer(table.fetch("column_count"), "$.payload.tables.actions.column_count",
|
|
74
|
+
minimum: 1)
|
|
75
|
+
rows = validate_displacement(table, value_key: "codes", path: "$.payload.tables.actions") do |column, code,
|
|
76
|
+
cell_path|
|
|
77
|
+
invalid(cell_path, "column must reference a terminal") unless @terminal_ids.include?(column)
|
|
78
|
+
invalid(cell_path, "column exceeds column_count") if column_count && column >= column_count
|
|
79
|
+
validate_token_action(code, column, "#{cell_path}.code")
|
|
80
|
+
end
|
|
81
|
+
validate_canonical_displacement(
|
|
82
|
+
table, rows, value_key: "codes", width_key: "column_count", width: column_count, dense: false,
|
|
83
|
+
path: "$.payload.tables.actions"
|
|
84
|
+
)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# @rbs (ValidationSupport::json_value table) -> void
|
|
88
|
+
def validate_gotos(table)
|
|
89
|
+
invalid("$.payload.tables.gotos", "must be an object") unless table.is_a?(Hash)
|
|
90
|
+
table_data = table #: Hash[String, ValidationSupport::json_value]
|
|
91
|
+
encoding = table_data["encoding"]
|
|
92
|
+
expected = @representation == "compact" ? "row-displacement-v1" : "sparse-rows-v1"
|
|
93
|
+
invalid("$.payload.tables.gotos.encoding", "does not match table representation") unless encoding == expected
|
|
94
|
+
case encoding
|
|
95
|
+
when "sparse-rows-v1" then validate_sparse_gotos(table_data)
|
|
96
|
+
when "row-displacement-v1" then validate_compact_gotos(table_data)
|
|
97
|
+
else invalid("$.payload.tables.gotos.encoding", "is unsupported")
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# @rbs (Hash[String, ValidationSupport::json_value] table) -> void
|
|
102
|
+
def validate_sparse_gotos(table)
|
|
103
|
+
record(table, "$.payload.tables.gotos", %w[encoding rows])
|
|
104
|
+
rows = array(table.fetch("rows"), "$.payload.tables.gotos.rows")
|
|
105
|
+
invalid("$.payload.tables.gotos.rows", "must contain one row per state") unless rows.length == @state_count
|
|
106
|
+
rows.each_with_index do |row, state|
|
|
107
|
+
symbol_ids = array(row, "$.payload.tables.gotos.rows[#{state}]").map.with_index do |cell, index|
|
|
108
|
+
path = "$.payload.tables.gotos.rows[#{state}][#{index}]"
|
|
109
|
+
cell = record(cell, path, %w[symbol_id state])
|
|
110
|
+
symbol_id = integer(cell.fetch("symbol_id"), "#{path}.symbol_id", minimum: 0)
|
|
111
|
+
invalid("#{path}.symbol_id", "must reference a nonterminal") unless @nonterminal_ids.include?(symbol_id)
|
|
112
|
+
validate_state(cell.fetch("state"), "#{path}.state")
|
|
113
|
+
symbol_id
|
|
114
|
+
end
|
|
115
|
+
sorted_unique!(symbol_ids, "$.payload.tables.gotos.rows[#{state}]")
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# @rbs (Hash[String, ValidationSupport::json_value] table) -> void
|
|
120
|
+
def validate_compact_gotos(table)
|
|
121
|
+
keys = %w[encoding row_count dense_width offsets values checks]
|
|
122
|
+
record(table, "$.payload.tables.gotos", keys)
|
|
123
|
+
enum(table.fetch("encoding"), "$.payload.tables.gotos.encoding", ["row-displacement-v1"])
|
|
124
|
+
validate_row_count(table, "$.payload.tables.gotos")
|
|
125
|
+
dense_width = nullable_integer(table.fetch("dense_width"), "$.payload.tables.gotos.dense_width", minimum: 1)
|
|
126
|
+
rows = validate_displacement(table, value_key: "values", path: "$.payload.tables.gotos") do |column, state,
|
|
127
|
+
cell_path|
|
|
128
|
+
invalid(cell_path, "column must reference a nonterminal") unless @nonterminal_ids.include?(column)
|
|
129
|
+
invalid(cell_path, "column exceeds dense_width") if dense_width && column >= dense_width
|
|
130
|
+
validate_state(state, "#{cell_path}.state")
|
|
131
|
+
end
|
|
132
|
+
validate_canonical_displacement(
|
|
133
|
+
table, rows, value_key: "values", width_key: "dense_width", width: dense_width, dense: true,
|
|
134
|
+
path: "$.payload.tables.gotos"
|
|
135
|
+
)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# @rbs (Hash[String, ValidationSupport::json_value] table, String path) -> void
|
|
139
|
+
def validate_row_count(table, path)
|
|
140
|
+
count = integer(table.fetch("row_count"), "#{path}.row_count", minimum: 1)
|
|
141
|
+
invalid("#{path}.row_count", "must equal state_count") unless count == @state_count
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# @rbs (Hash[String, ValidationSupport::json_value] table, value_key: String, path: String)
|
|
145
|
+
# { (Integer, ValidationSupport::json_value, String) -> void } -> Array[Hash[Integer, ValidationSupport::json_value]]
|
|
146
|
+
def validate_displacement(table, value_key:, path:)
|
|
147
|
+
offsets = integer_array(table.fetch("offsets"), "#{path}.offsets", allow_nil: false, minimum: 0)
|
|
148
|
+
invalid("#{path}.offsets", "must contain one offset per state") unless offsets.length == @state_count
|
|
149
|
+
minimum = value_key == "codes" ? nil : 0
|
|
150
|
+
values = integer_array(table.fetch(value_key), "#{path}.#{value_key}", allow_nil: true, minimum: minimum)
|
|
151
|
+
checks = integer_array(table.fetch("checks"), "#{path}.checks", allow_nil: true, minimum: 0)
|
|
152
|
+
invalid(path, "#{value_key} and checks must have equal length") unless values.length == checks.length
|
|
153
|
+
|
|
154
|
+
rows = Array.new(@state_count) { {} } #: Array[Hash[Integer, ValidationSupport::json_value]]
|
|
155
|
+
checks.each_index do |index|
|
|
156
|
+
row = checks[index]
|
|
157
|
+
value = values[index]
|
|
158
|
+
invalid("#{path}[#{index}]", "value and check occupancy must match") unless row.nil? == value.nil?
|
|
159
|
+
next unless row
|
|
160
|
+
|
|
161
|
+
invalid("#{path}.checks[#{index}]", "references a missing state") unless row.between?(0, @state_count - 1)
|
|
162
|
+
column = index - offsets.fetch(row)
|
|
163
|
+
invalid("#{path}[#{index}]", "has a negative column") if column.negative?
|
|
164
|
+
yield(column, value, "#{path}[#{index}]")
|
|
165
|
+
rows.fetch(row)[column] = value
|
|
166
|
+
end
|
|
167
|
+
rows
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# @rbs (Hash[String, ValidationSupport::json_value] table,
|
|
171
|
+
# Array[Hash[Integer, ValidationSupport::json_value]] rows, value_key: String,
|
|
172
|
+
# width_key: String, width: Integer?, dense: bool, path: String) -> void
|
|
173
|
+
def validate_canonical_displacement(table, rows, value_key:, width_key:, width:, dense:, path:)
|
|
174
|
+
canonical = Tables::Compact.build(rows, dense: dense)
|
|
175
|
+
expected = [canonical.offsets, canonical.values, canonical.checks]
|
|
176
|
+
actual = [table.fetch("offsets"), table.fetch(value_key), table.fetch("checks")]
|
|
177
|
+
invalid(path, "must use the canonical minimal row-displacement layout") unless actual == expected
|
|
178
|
+
|
|
179
|
+
expected_width = if width_key == "column_count"
|
|
180
|
+
rows.flat_map(&:keys).max.to_i + 1
|
|
181
|
+
else
|
|
182
|
+
canonical.dense_width
|
|
183
|
+
end
|
|
184
|
+
expected_width = nil if expected_width && (@state_count * expected_width) > Tables::Compact::DENSE_CELL_LIMIT
|
|
185
|
+
invalid("#{path}.#{width_key}", "does not match the canonical table width") unless width == expected_width
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# @rbs skip
|
|
189
|
+
def integer_array(value, path, allow_nil:, minimum:)
|
|
190
|
+
array(value, path).map.with_index do |item, index|
|
|
191
|
+
next if allow_nil && item.nil?
|
|
192
|
+
|
|
193
|
+
integer(item, "#{path}[#{index}]", minimum: minimum)
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# @rbs (ValidationSupport::json_value defaults) -> void
|
|
198
|
+
def validate_defaults(defaults)
|
|
199
|
+
values = array(defaults, "$.payload.tables.default_actions")
|
|
200
|
+
unless values.length == @state_count
|
|
201
|
+
invalid("$.payload.tables.default_actions",
|
|
202
|
+
"must contain one entry per state")
|
|
203
|
+
end
|
|
204
|
+
values.each_with_index do |code, state|
|
|
205
|
+
next if code.nil?
|
|
206
|
+
|
|
207
|
+
path = "$.payload.tables.default_actions[#{state}]"
|
|
208
|
+
code = integer(code, path)
|
|
209
|
+
invalid(path, "must be an error or reduction") if code >= 0
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# @rbs (ValidationSupport::json_value code, Integer token_id, String path) -> void
|
|
214
|
+
def validate_token_action(code, token_id, path)
|
|
215
|
+
code = integer(code, path)
|
|
216
|
+
invalid(path, "accept is only valid for $eof") if code.zero? && !token_id.zero?
|
|
217
|
+
invalid(path, "$eof cannot be shifted") if token_id.zero? && code.positive?
|
|
218
|
+
validate_action_code(code, path)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# @rbs (ValidationSupport::json_value code, String path) -> void
|
|
222
|
+
def validate_action_code(code, path)
|
|
223
|
+
code = integer(code, path)
|
|
224
|
+
return if [0, -1].include?(code)
|
|
225
|
+
return validate_state(code - 1, path) if code.positive?
|
|
226
|
+
|
|
227
|
+
production = -2 - code
|
|
228
|
+
invalid(path, "references a missing production") unless production.between?(0, @production_count - 1)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# @rbs (ValidationSupport::json_value state, String path) -> void
|
|
232
|
+
def validate_state(state, path)
|
|
233
|
+
state = integer(state, path, minimum: 0)
|
|
234
|
+
invalid(path, "references a missing state") unless state.between?(0, @state_count - 1)
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|