ibex 0.1.0 → 0.2.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 +247 -104
- data/docs/architecture.md +322 -28
- data/docs/cst-migration.md +107 -0
- data/docs/cst.md +213 -0
- data/docs/development.md +129 -0
- data/docs/editor-setup.md +25 -0
- data/docs/error-ux.md +60 -0
- data/docs/grammar-reference.md +458 -18
- data/docs/lexer-migration.md +51 -0
- data/docs/racc-migration.md +34 -6
- data/docs/release-readiness.md +163 -0
- data/docs/stability.md +124 -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/sets.rb +5 -4
- data/lib/ibex/artifact_set.rb +63 -0
- data/lib/ibex/cli/ambiguity.rb +66 -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 +116 -0
- data/lib/ibex/cli/documentation.rb +67 -0
- data/lib/ibex/cli/error_messages.rb +177 -0
- data/lib/ibex/cli/explain.rb +76 -0
- data/lib/ibex/cli/formatting.rb +386 -0
- data/lib/ibex/cli/generation_artifacts.rb +138 -0
- data/lib/ibex/cli/generation_error_messages.rb +39 -0
- data/lib/ibex/cli/grammar_tests.rb +122 -0
- data/lib/ibex/cli/ir_tools.rb +184 -0
- data/lib/ibex/cli/lsp.rb +33 -0
- data/lib/ibex/cli/outputs.rb +91 -8
- data/lib/ibex/cli/racc_migration.rb +87 -0
- data/lib/ibex/cli/samples.rb +92 -0
- data/lib/ibex/cli/watch.rb +103 -0
- data/lib/ibex/cli.rb +506 -37
- data/lib/ibex/codegen/action_locations.rb +103 -0
- data/lib/ibex/codegen/action_method_source.rb +210 -0
- data/lib/ibex/codegen/action_source.rb +118 -0
- data/lib/ibex/codegen/ambiguity.rb +173 -0
- data/lib/ibex/codegen/cst_metadata.rb +171 -0
- data/lib/ibex/codegen/documentation.rb +170 -0
- data/lib/ibex/codegen/explain.rb +312 -0
- data/lib/ibex/codegen/generated_action_abi.rb +288 -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 +323 -2
- data/lib/ibex/codegen/report.rb +46 -6
- data/lib/ibex/codegen/ruby.rb +334 -59
- data/lib/ibex/codegen/ruby_actions.rb +143 -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 +90 -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/coverage/collector.rb +188 -0
- data/lib/ibex/coverage/event_stream.rb +97 -0
- data/lib/ibex/coverage/report.rb +259 -0
- data/lib/ibex/coverage/runtime_event_validator.rb +160 -0
- data/lib/ibex/coverage.rb +13 -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/frontend/ast.rb +145 -6
- data/lib/ibex/frontend/bootstrap_parser.rb +47 -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 +407 -0
- data/lib/ibex/frontend/generated_parser.rb +614 -190
- data/lib/ibex/frontend/generated_parser_base.rb +164 -30
- data/lib/ibex/frontend/generated_parser_includes.rb +61 -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 +247 -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/regenerator.rb +26 -1
- data/lib/ibex/frontend/resolution.rb +69 -0
- data/lib/ibex/frontend/resolver.rb +217 -0
- data/lib/ibex/frontend/rule_documentation.rb +103 -0
- data/lib/ibex/frontend/source_cursor.rb +132 -8
- 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 +81 -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 +216 -26
- 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 +8 -3
- data/lib/ibex/frontend.rb +13 -2
- data/lib/ibex/generation_input.rb +57 -0
- data/lib/ibex/generation_manifest.rb +200 -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 +38 -5
- data/lib/ibex/ir/grammar_ir.rb +137 -24
- data/lib/ibex/ir/lexer_ir.rb +76 -0
- data/lib/ibex/ir/migration.rb +120 -0
- data/lib/ibex/ir/serialize.rb +110 -19
- data/lib/ibex/ir/validator/automaton.rb +345 -0
- data/lib/ibex/ir/validator/base.rb +129 -0
- data/lib/ibex/ir/validator/grammar.rb +604 -0
- data/lib/ibex/ir/validator/lexer.rb +113 -0
- data/lib/ibex/ir/validator.rb +62 -0
- data/lib/ibex/ir.rb +57 -4
- data/lib/ibex/lalr/build_metrics.rb +23 -0
- data/lib/ibex/lalr/builder.rb +379 -52
- data/lib/ibex/lalr/conflict.rb +1 -0
- data/lib/ibex/lalr/conflict_search.rb +11 -5
- data/lib/ibex/lalr/counterexample.rb +20 -5
- data/lib/ibex/lalr/direct_lookaheads.rb +236 -0
- data/lib/ibex/lalr/ielr_partition.rb +152 -0
- data/lib/ibex/lalr/on_error_reductions.rb +74 -0
- data/lib/ibex/lalr.rb +7 -0
- data/lib/ibex/location.rb +129 -0
- data/lib/ibex/lsp/document_handlers.rb +66 -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 +78 -0
- data/lib/ibex/lsp/navigation_handlers.rb +56 -0
- data/lib/ibex/lsp/position_codec.rb +109 -0
- data/lib/ibex/lsp/protocol_error.rb +33 -0
- data/lib/ibex/lsp/request_handlers.rb +45 -0
- data/lib/ibex/lsp/request_support.rb +87 -0
- data/lib/ibex/lsp/server.rb +146 -0
- data/lib/ibex/lsp/symbol_index.rb +241 -0
- data/lib/ibex/lsp/symbol_index_builder.rb +267 -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 +17 -0
- data/lib/ibex/lsp/transport.rb +118 -0
- data/lib/ibex/lsp/workspace.rb +127 -0
- data/lib/ibex/lsp/workspace_analyzer.rb +199 -0
- data/lib/ibex/lsp.rb +32 -0
- data/lib/ibex/normalize/declarations.rb +140 -7
- data/lib/ibex/normalize/diagnostics.rb +50 -5
- data/lib/ibex/normalize/expander.rb +59 -55
- data/lib/ibex/normalize/expression.rb +60 -39
- data/lib/ibex/normalize/inline_expansion.rb +414 -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 +69 -0
- data/lib/ibex/normalize/parameter_lowering.rb +126 -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 +199 -0
- data/lib/ibex/normalize/recovery_declarations.rb +84 -0
- data/lib/ibex/normalize.rb +179 -14
- 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 +94 -0
- data/lib/ibex/racc_migration.rb +12 -0
- data/lib/ibex/rake_task.rb +116 -0
- data/lib/ibex/samples.rb +186 -0
- data/lib/ibex/table_simulation/result.rb +51 -0
- data/lib/ibex/table_simulation/simulator.rb +253 -0
- data/lib/ibex/table_simulation/step.rb +60 -0
- data/lib/ibex/table_simulation/text.rb +31 -0
- data/lib/ibex/table_simulation.rb +13 -0
- data/lib/ibex/tables.rb +9 -70
- data/lib/ibex/version.rb +1 -1
- data/lib/ibex/watch/runner.rb +172 -0
- data/lib/ibex/watch/source_snapshot.rb +93 -0
- data/lib/ibex/watch.rb +11 -0
- data/lib/ibex.rb +25 -1
- data/schema/automaton-ir-v1.schema.json +401 -0
- data/schema/automaton-ir-v2.schema.json +58 -0
- data/schema/benchmark-v1.schema.json +212 -0
- data/schema/benchmark-v2.schema.json +61 -0
- data/schema/cst-v1.json +170 -0
- data/schema/error-ux-v1.schema.json +258 -0
- data/schema/explain-v1.schema.json +433 -0
- data/schema/frontend-diagnostics-v1.schema.json +154 -0
- data/schema/generation-manifest-v1.schema.json +115 -0
- data/schema/grammar-ir-v1.schema.json +426 -0
- data/schema/grammar-ir-v2.schema.json +779 -0
- data/schema/lexer-ir-v1.schema.json +215 -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/runtime-coverage-v1.schema.json +86 -0
- data/schema/runtime-event-v1.schema.json +308 -0
- data/schema/table-simulation-v1.schema.json +70 -0
- data/sig/ibex/artifact_set.rbs +37 -0
- data/sig/ibex/cli/ambiguity.rbs +22 -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 +38 -0
- data/sig/ibex/cli/documentation.rbs +25 -0
- data/sig/ibex/cli/error_messages.rbs +57 -0
- data/sig/ibex/cli/explain.rbs +25 -0
- data/sig/ibex/cli/formatting.rbs +103 -0
- data/sig/ibex/cli/generation_artifacts.rbs +50 -0
- data/sig/ibex/cli/generation_error_messages.rbs +19 -0
- data/sig/ibex/cli/grammar_tests.rbs +36 -0
- data/sig/ibex/cli/ir_tools.rbs +51 -0
- data/sig/ibex/cli/lsp.rbs +14 -0
- data/sig/ibex/cli/outputs.rbs +17 -0
- data/sig/ibex/cli/racc_migration.rbs +30 -0
- data/sig/ibex/cli/samples.rbs +30 -0
- data/sig/ibex/cli/watch.rbs +43 -0
- data/sig/ibex/cli.rbs +104 -5
- 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 +85 -0
- data/sig/ibex/codegen/generated_action_abi.rbs +101 -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 +84 -4
- data/sig/ibex/codegen/report.rbs +8 -0
- data/sig/ibex/codegen/ruby.rbs +97 -23
- 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 +25 -0
- data/sig/ibex/codegen/ruby_table_metadata.rbs +26 -0
- data/sig/ibex/codegen/ruby_value_printers.rbs +28 -0
- data/sig/ibex/coverage/collector.rbs +76 -0
- data/sig/ibex/coverage/event_stream.rbs +42 -0
- data/sig/ibex/coverage/report.rbs +100 -0
- data/sig/ibex/coverage/runtime_event_validator.rbs +68 -0
- data/sig/ibex/coverage.rbs +7 -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/frontend/ast.rbs +208 -19
- data/sig/ibex/frontend/bootstrap_parser.rbs +11 -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 +135 -0
- data/sig/ibex/frontend/generated_parser.rbs +218 -68
- data/sig/ibex/frontend/generated_parser_base.rbs +61 -10
- 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 +54 -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/regenerator.rbs +11 -0
- data/sig/ibex/frontend/resolution.rbs +33 -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 +36 -3
- 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 +53 -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 +73 -5
- data/sig/ibex/frontend/token_adapter/rule_state.rbs +20 -0
- data/sig/ibex/frontend/token_adapter.rbs +5 -2
- data/sig/ibex/frontend.rbs +1 -1
- data/sig/ibex/generation_input.rbs +37 -0
- data/sig/ibex/generation_manifest.rbs +67 -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 +8 -2
- data/sig/ibex/ir/grammar_ir.rbs +75 -15
- data/sig/ibex/ir/lexer_ir.rbs +57 -0
- data/sig/ibex/ir/migration.rbs +34 -0
- data/sig/ibex/ir/serialize.rbs +23 -6
- data/sig/ibex/ir/validator/automaton.rbs +109 -0
- data/sig/ibex/ir/validator/base.rbs +65 -0
- data/sig/ibex/ir/validator/grammar.rbs +184 -0
- data/sig/ibex/ir/validator/lexer.rbs +37 -0
- data/sig/ibex/ir/validator.rbs +16 -0
- data/sig/ibex/ir.rbs +38 -4
- data/sig/ibex/lalr/build_metrics.rbs +20 -0
- data/sig/ibex/lalr/builder.rbs +95 -15
- data/sig/ibex/lalr/conflict_search.rbs +7 -3
- data/sig/ibex/lalr/counterexample.rbs +5 -2
- data/sig/ibex/lalr/direct_lookaheads.rbs +86 -0
- data/sig/ibex/lalr/ielr_partition.rbs +59 -0
- data/sig/ibex/lalr/on_error_reductions.rbs +22 -0
- data/sig/ibex/lalr.rbs +6 -0
- 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 +30 -0
- data/sig/ibex/lsp/position_codec.rbs +40 -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 +78 -0
- data/sig/ibex/lsp/symbol_index_builder.rbs +87 -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 +25 -0
- data/sig/ibex/lsp/transport.rbs +35 -0
- data/sig/ibex/lsp/workspace.rbs +41 -0
- data/sig/ibex/lsp/workspace_analyzer.rbs +69 -0
- data/sig/ibex/lsp.rbs +7 -0
- data/sig/ibex/normalize/declarations.rbs +31 -0
- data/sig/ibex/normalize/diagnostics.rbs +9 -0
- data/sig/ibex/normalize/expander.rbs +20 -14
- data/sig/ibex/normalize/expression.rbs +10 -10
- data/sig/ibex/normalize/inline_expansion.rbs +120 -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 +32 -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 +46 -0
- data/sig/ibex/normalize/recovery_declarations.rbs +24 -0
- data/sig/ibex/normalize.rbs +123 -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 +53 -0
- data/sig/ibex/racc_migration.rbs +8 -0
- data/sig/ibex/rake_task.rbs +51 -0
- data/sig/ibex/samples.rbs +51 -0
- data/sig/ibex/table_simulation/result.rbs +32 -0
- data/sig/ibex/table_simulation/simulator.rbs +98 -0
- data/sig/ibex/table_simulation/step.rbs +40 -0
- data/sig/ibex/table_simulation/text.rbs +14 -0
- data/sig/ibex/table_simulation.rbs +7 -0
- data/sig/ibex/tables.rbs +0 -26
- data/sig/ibex/watch/runner.rbs +48 -0
- data/sig/ibex/watch/source_snapshot.rbs +42 -0
- data/sig/ibex/watch.rbs +7 -0
- data/sig/ibex.rbs +2 -0
- metadata +301 -16
- 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
|
@@ -3,9 +3,14 @@
|
|
|
3
3
|
module Ibex
|
|
4
4
|
module Frontend
|
|
5
5
|
# Parses the declaration section of a grammar.
|
|
6
|
+
# rubocop:disable Metrics/ModuleLength, Metrics/CyclomaticComplexity
|
|
7
|
+
# Bootstrap declarations intentionally mirror the generated frontend's complete declaration vocabulary.
|
|
6
8
|
module BootstrapParserDeclarations
|
|
7
|
-
DECLARATIONS = %w[
|
|
8
|
-
|
|
9
|
+
DECLARATIONS = %w[
|
|
10
|
+
include import token prechigh preclow options expect expect_rr start recover on_error_reduce
|
|
11
|
+
test lexer convert display type param printer pragma rule
|
|
12
|
+
].freeze #: Array[String]
|
|
13
|
+
ASSOCIATIVITIES = %w[left right nonassoc precedence].freeze #: Array[String]
|
|
9
14
|
|
|
10
15
|
private
|
|
11
16
|
|
|
@@ -20,18 +25,16 @@ module Ibex
|
|
|
20
25
|
# @rbs () -> void
|
|
21
26
|
def parse_pragmas
|
|
22
27
|
# @type self: BootstrapParser
|
|
23
|
-
seen = false
|
|
24
28
|
while keyword?("pragma")
|
|
25
29
|
keyword = current
|
|
26
|
-
fail_at(keyword.location, "duplicate pragma extended") if seen
|
|
27
|
-
|
|
28
30
|
advance
|
|
29
31
|
value = expect(:identifier)
|
|
30
32
|
name = token_string(value)
|
|
31
|
-
fail_at(value.location, "unknown pragma #{name}") unless name
|
|
33
|
+
fail_at(value.location, "unknown pragma #{name}") unless %w[extended cst].include?(name)
|
|
34
|
+
fail_at(keyword.location, "duplicate pragma #{name}") if @pragmas[name]
|
|
32
35
|
|
|
36
|
+
@pragmas[name] = true
|
|
33
37
|
@mode = :extended
|
|
34
|
-
seen = true
|
|
35
38
|
end
|
|
36
39
|
end
|
|
37
40
|
|
|
@@ -39,24 +42,62 @@ module Ibex
|
|
|
39
42
|
def parse_declaration
|
|
40
43
|
# @type self: BootstrapParser
|
|
41
44
|
case current.value
|
|
45
|
+
when "include", "import" then parse_import
|
|
42
46
|
when "token" then parse_tokens
|
|
43
47
|
when "prechigh", "preclow" then parse_precedence
|
|
44
48
|
when "options" then parse_options
|
|
45
49
|
when "expect" then parse_expect
|
|
50
|
+
when "expect_rr" then parse_expect_rr
|
|
46
51
|
when "start" then parse_start
|
|
52
|
+
when "recover" then parse_recovery
|
|
53
|
+
when "on_error_reduce" then parse_on_error_reduce
|
|
54
|
+
when "test" then parse_grammar_test
|
|
55
|
+
when "lexer" then parse_lexer
|
|
47
56
|
when "convert" then parse_convert
|
|
57
|
+
when "display" then parse_symbol_metadata(AST::DisplayName, "display")
|
|
58
|
+
when "type" then parse_symbol_metadata(AST::SemanticType, "type")
|
|
59
|
+
when "param" then parse_parameter
|
|
60
|
+
when "printer" then parse_printer
|
|
48
61
|
when "pragma" then fail_at(current.location, "expected rule, got pragma")
|
|
49
62
|
else fail_expected("a declaration or rule")
|
|
50
63
|
end
|
|
51
64
|
end
|
|
52
65
|
|
|
66
|
+
# @rbs () -> AST::Include
|
|
67
|
+
def parse_import
|
|
68
|
+
# @type self: BootstrapParser
|
|
69
|
+
keyword = advance
|
|
70
|
+
extended_only!(keyword.location, "#{keyword.value}s")
|
|
71
|
+
path = expect(:literal)
|
|
72
|
+
value = token_string(path)
|
|
73
|
+
unless value.start_with?('"') && value.end_with?('"')
|
|
74
|
+
fail_at(path.location, "#{keyword.value} path must use a double-quoted string")
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
decoded = begin
|
|
78
|
+
value.undump
|
|
79
|
+
rescue RuntimeError => e
|
|
80
|
+
fail_at(path.location, "invalid #{keyword.value} path: #{e.message}")
|
|
81
|
+
end
|
|
82
|
+
AST::Include.new(path: decoded, loc: keyword.location)
|
|
83
|
+
end
|
|
84
|
+
|
|
53
85
|
# @rbs () -> AST::Tokens
|
|
54
86
|
def parse_tokens
|
|
55
87
|
# @type self: BootstrapParser
|
|
56
88
|
location = advance.location
|
|
57
89
|
names = [] #: Array[String]
|
|
58
|
-
|
|
59
|
-
|
|
90
|
+
aliases = {} #: Hash[String, String]
|
|
91
|
+
until declaration_start?
|
|
92
|
+
name_token = expect_symbol
|
|
93
|
+
name = token_string(name_token)
|
|
94
|
+
names << name
|
|
95
|
+
next unless @mode == :extended && name_token.type == :identifier &&
|
|
96
|
+
current.type == :literal && current.location.line == name_token.location.line
|
|
97
|
+
|
|
98
|
+
aliases[name] = decode_quoted_literal(advance, "token alias")
|
|
99
|
+
end
|
|
100
|
+
AST::Tokens.new(names: names, aliases: aliases.empty? ? nil : aliases, loc: location)
|
|
60
101
|
end
|
|
61
102
|
|
|
62
103
|
# @rbs () -> AST::Precedence
|
|
@@ -77,6 +118,7 @@ module Ibex
|
|
|
77
118
|
levels = [] #: Array[AST::PrecedenceLevel]
|
|
78
119
|
until keyword?(closing) || current.type == :eof
|
|
79
120
|
association = expect_one_of(ASSOCIATIVITIES)
|
|
121
|
+
extended_only!(association.location, "%precedence") if token_string(association) == "precedence"
|
|
80
122
|
symbols = [] #: Array[String]
|
|
81
123
|
symbols << parse_symbol_name until association_start? || keyword?(closing) || current.type == :eof
|
|
82
124
|
fail_at(association.location, "expected at least one precedence symbol") if symbols.empty?
|
|
@@ -102,11 +144,152 @@ module Ibex
|
|
|
102
144
|
AST::Expect.new(conflicts: token_integer(expect(:integer)), loc: location)
|
|
103
145
|
end
|
|
104
146
|
|
|
147
|
+
# @rbs () -> AST::ExpectRR
|
|
148
|
+
def parse_expect_rr
|
|
149
|
+
# @type self: BootstrapParser
|
|
150
|
+
location = advance.location
|
|
151
|
+
extended_only!(location, "expect-rr declarations")
|
|
152
|
+
AST::ExpectRR.new(conflicts: token_integer(expect(:integer)), loc: location)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# @rbs () -> AST::Parameter
|
|
156
|
+
def parse_parameter
|
|
157
|
+
# @type self: BootstrapParser
|
|
158
|
+
keyword = advance
|
|
159
|
+
extended_only!(keyword.location, "%param")
|
|
160
|
+
name = expect(:identifier)
|
|
161
|
+
type = current.type == :literal ? advance : nil
|
|
162
|
+
if type && (keyword.location.line != name.location.line || name.location.line != type.location.line)
|
|
163
|
+
fail_at(keyword.location, "%param declaration must be written on one line")
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
semantic_type = type && decode_quoted_literal(type, "%param")
|
|
167
|
+
AST::Parameter.new(name: token_string(name), semantic_type: semantic_type, loc: keyword.location)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# @rbs () -> AST::Printer
|
|
171
|
+
def parse_printer
|
|
172
|
+
# @type self: BootstrapParser
|
|
173
|
+
keyword = advance
|
|
174
|
+
extended_only!(keyword.location, "%printer")
|
|
175
|
+
name = parse_symbol_name
|
|
176
|
+
action = expect(:action)
|
|
177
|
+
AST::Printer.new(name: name, code: token_string(action), loc: keyword.location)
|
|
178
|
+
end
|
|
179
|
+
|
|
105
180
|
# @rbs () -> AST::Start
|
|
106
181
|
def parse_start
|
|
107
182
|
# @type self: BootstrapParser
|
|
108
183
|
location = advance.location
|
|
109
|
-
|
|
184
|
+
names = [parse_symbol_name]
|
|
185
|
+
names << parse_symbol_name until declaration_start?
|
|
186
|
+
extended_only!(location, "multiple start symbols") if names.length > 1
|
|
187
|
+
AST::Start.new(names: names, loc: location)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# @rbs () -> AST::Recovery
|
|
191
|
+
def parse_recovery
|
|
192
|
+
# @type self: BootstrapParser
|
|
193
|
+
keyword = advance
|
|
194
|
+
extended_only!(keyword.location, "%recover")
|
|
195
|
+
kind = expect(:identifier)
|
|
196
|
+
fail_at(kind.location, "expected sync, got #{kind.value}") unless token_string(kind) == "sync"
|
|
197
|
+
expect(:":")
|
|
198
|
+
tokens = [parse_symbol_name]
|
|
199
|
+
tokens << parse_symbol_name until declaration_start?
|
|
200
|
+
AST::Recovery.new(sync_tokens: tokens, loc: keyword.location)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# @rbs () -> AST::OnErrorReduce
|
|
204
|
+
def parse_on_error_reduce
|
|
205
|
+
# @type self: BootstrapParser
|
|
206
|
+
keyword = advance
|
|
207
|
+
extended_only!(keyword.location, "%on_error_reduce")
|
|
208
|
+
names = [parse_symbol_name]
|
|
209
|
+
names << parse_symbol_name until declaration_start?
|
|
210
|
+
AST::OnErrorReduce.new(names: names, loc: keyword.location)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# @rbs () -> AST::GrammarTest
|
|
214
|
+
def parse_grammar_test
|
|
215
|
+
# @type self: BootstrapParser
|
|
216
|
+
keyword = advance
|
|
217
|
+
extended_only!(keyword.location, "%test")
|
|
218
|
+
expectation = token_string(expect(:identifier))
|
|
219
|
+
fail_at(keyword.location, "expected accept or reject, got #{expectation}") unless
|
|
220
|
+
%w[accept reject].include?(expectation)
|
|
221
|
+
source = expect(:literal)
|
|
222
|
+
literal = token_string(source)
|
|
223
|
+
fail_at(source.location, "%test source must use a double-quoted string") unless literal.start_with?('"')
|
|
224
|
+
decoded = begin
|
|
225
|
+
literal.undump
|
|
226
|
+
rescue RuntimeError => e
|
|
227
|
+
fail_at(source.location, "invalid %test source: #{e.message}")
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
AST::GrammarTest.new(expectation: expectation.to_sym, source: decoded, loc: keyword.location)
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# @rbs () -> AST::Lexer
|
|
234
|
+
def parse_lexer
|
|
235
|
+
# @type self: BootstrapParser
|
|
236
|
+
keyword = advance
|
|
237
|
+
extended_only!(keyword.location, "lexer declarations")
|
|
238
|
+
entries = parse_lexer_entries
|
|
239
|
+
expect_keyword("end")
|
|
240
|
+
AST::Lexer.new(definitions: entries, loc: keyword.location)
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# @rbs () -> Array[AST::lexer_entry]
|
|
244
|
+
def parse_lexer_entries
|
|
245
|
+
# @type self: BootstrapParser
|
|
246
|
+
entries = [] #: Array[AST::lexer_entry]
|
|
247
|
+
entries << parse_lexer_entry until keyword?("end") || current.type == :eof
|
|
248
|
+
entries
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# @rbs () -> AST::lexer_entry
|
|
252
|
+
def parse_lexer_entry
|
|
253
|
+
# @type self: BootstrapParser
|
|
254
|
+
return parse_lexer_state if keyword?("state")
|
|
255
|
+
|
|
256
|
+
marker = expect(:identifier)
|
|
257
|
+
kind = case token_string(marker)
|
|
258
|
+
when "skip" then :skip
|
|
259
|
+
when "on" then :on
|
|
260
|
+
else :token
|
|
261
|
+
end
|
|
262
|
+
pattern = expect_lexer_pattern
|
|
263
|
+
action = current.type == :action ? advance : nil
|
|
264
|
+
fail_at(marker.location, "on lexer rules require an action") if kind == :on && !action
|
|
265
|
+
build_bootstrap_lexer_rule(kind, marker, pattern, action)
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# @rbs () -> AST::LexerState
|
|
269
|
+
def parse_lexer_state
|
|
270
|
+
# @type self: BootstrapParser
|
|
271
|
+
marker = advance
|
|
272
|
+
name = expect(:identifier)
|
|
273
|
+
expect_keyword("do")
|
|
274
|
+
entries = parse_lexer_entries
|
|
275
|
+
expect_keyword("end")
|
|
276
|
+
AST::LexerState.new(name: token_string(name), definitions: entries, loc: marker.location)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# @rbs () -> Token
|
|
280
|
+
def expect_lexer_pattern
|
|
281
|
+
# @type self: BootstrapParser
|
|
282
|
+
return advance if %i[regexp literal].include?(current.type)
|
|
283
|
+
|
|
284
|
+
fail_expected("a regular expression or quoted literal")
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
# @rbs (Symbol kind, Token marker, Token pattern, Token? action) -> AST::LexerRule
|
|
288
|
+
def build_bootstrap_lexer_rule(kind, marker, pattern, action)
|
|
289
|
+
# @type self: BootstrapParser
|
|
290
|
+
token = kind == :token ? token_string(marker) : nil
|
|
291
|
+
AST::LexerRule.new(kind: kind, token: token, pattern: token_string(pattern),
|
|
292
|
+
pattern_kind: pattern.type, action: action && token_string(action), loc: marker.location)
|
|
110
293
|
end
|
|
111
294
|
|
|
112
295
|
# @rbs () -> AST::Convert
|
|
@@ -124,6 +307,27 @@ module Ibex
|
|
|
124
307
|
AST::Convert.new(pairs: pairs, loc: location)
|
|
125
308
|
end
|
|
126
309
|
|
|
310
|
+
# @rbs (singleton(AST::DisplayName) | singleton(AST::SemanticType) node_class, String feature) ->
|
|
311
|
+
# (AST::DisplayName | AST::SemanticType)
|
|
312
|
+
def parse_symbol_metadata(node_class, feature)
|
|
313
|
+
# @type self: BootstrapParser
|
|
314
|
+
keyword = advance
|
|
315
|
+
extended_only!(keyword.location, "#{feature} declarations")
|
|
316
|
+
name = expect_symbol
|
|
317
|
+
value = expect_metadata_value
|
|
318
|
+
validate_metadata_line(keyword, name, value, feature)
|
|
319
|
+
decoded = decode_quoted_literal(value, feature)
|
|
320
|
+
node_class.new(name: token_string(name), value: decoded, loc: keyword.location)
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
# @rbs () -> Token
|
|
324
|
+
def expect_metadata_value
|
|
325
|
+
# @type self: BootstrapParser
|
|
326
|
+
return advance if current.type == :literal
|
|
327
|
+
|
|
328
|
+
fail_expected("a quoted string")
|
|
329
|
+
end
|
|
330
|
+
|
|
127
331
|
# @rbs (Integer line) -> Array[Token]
|
|
128
332
|
def tokens_on_line(line)
|
|
129
333
|
# @type self: BootstrapParser
|
|
@@ -147,10 +351,41 @@ module Ibex
|
|
|
147
351
|
fail_at(location, "invalid conversion expression: #{e.message}")
|
|
148
352
|
end
|
|
149
353
|
|
|
354
|
+
# @rbs (Token keyword, Token name, Token value, String feature) -> void
|
|
355
|
+
def validate_metadata_line(keyword, name, value, feature)
|
|
356
|
+
# @type self: BootstrapParser
|
|
357
|
+
return if keyword.location.line == name.location.line && name.location.line == value.location.line
|
|
358
|
+
|
|
359
|
+
fail_at(keyword.location, "#{feature} declaration must be written on one line")
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
# @rbs (Token token, String feature) -> String
|
|
363
|
+
def decode_quoted_literal(token, feature)
|
|
364
|
+
# @type self: BootstrapParser
|
|
365
|
+
literal = token_string(token)
|
|
366
|
+
decoded = if literal.start_with?('"')
|
|
367
|
+
literal.undump
|
|
368
|
+
else
|
|
369
|
+
(literal[1...-1] || "").gsub("\\'", "'").gsub("\\\\", "\\")
|
|
370
|
+
end
|
|
371
|
+
fail_at(token.location, "#{feature} value must not be empty") if decoded.strip.empty?
|
|
372
|
+
fail_at(token.location, "#{feature} value must be a single line") if decoded.match?(/[\r\n]/)
|
|
373
|
+
fail_at(token.location, "#{feature} value must not contain control characters") if
|
|
374
|
+
decoded.match?(/[[:cntrl:]]/)
|
|
375
|
+
|
|
376
|
+
decoded
|
|
377
|
+
rescue RuntimeError => e
|
|
378
|
+
fail_at(token.location, "invalid #{feature} value: #{e.message}")
|
|
379
|
+
end
|
|
380
|
+
|
|
150
381
|
# @rbs () -> bool
|
|
151
382
|
def declaration_start?
|
|
152
383
|
# @type self: BootstrapParser
|
|
153
|
-
|
|
384
|
+
return true if current.type == :eof
|
|
385
|
+
return false unless current.type == :identifier && DECLARATIONS.include?(current.value)
|
|
386
|
+
return false if %w[display type param printer lexer].include?(current.value) && @mode != :extended
|
|
387
|
+
|
|
388
|
+
true
|
|
154
389
|
end
|
|
155
390
|
|
|
156
391
|
# @rbs () -> bool
|
|
@@ -159,5 +394,6 @@ module Ibex
|
|
|
159
394
|
current.type == :identifier && ASSOCIATIVITIES.include?(current.value)
|
|
160
395
|
end
|
|
161
396
|
end
|
|
397
|
+
# rubocop:enable Metrics/ModuleLength, Metrics/CyclomaticComplexity
|
|
162
398
|
end
|
|
163
399
|
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ibex
|
|
4
|
+
module Frontend
|
|
5
|
+
# Parses extended-mode parameter lists and parameterized references during bootstrap.
|
|
6
|
+
module BootstrapParserParameters
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
# @rbs (Token lhs) -> Array[String]
|
|
10
|
+
def parse_rule_parameters(lhs)
|
|
11
|
+
# @type self: BootstrapParser
|
|
12
|
+
return [] unless current.type == :"(" && adjacent_tokens?(lhs, current)
|
|
13
|
+
|
|
14
|
+
opening = advance
|
|
15
|
+
extended_only!(opening.location, "parameterized rules")
|
|
16
|
+
parameters = [token_string(expect(:identifier))]
|
|
17
|
+
parameters << token_string(expect(:identifier)) while accept(:",")
|
|
18
|
+
expect(:")")
|
|
19
|
+
parameters
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @rbs () -> AST::item
|
|
23
|
+
def parse_parameterized_reference
|
|
24
|
+
# @type self: BootstrapParser
|
|
25
|
+
callee = advance
|
|
26
|
+
opening = expect(:"(")
|
|
27
|
+
extended_only!(opening.location, "parameterized rules")
|
|
28
|
+
arguments = [] #: Array[AST::item]
|
|
29
|
+
unless current.type == :")"
|
|
30
|
+
loop do
|
|
31
|
+
fail_at(current.location, "actions are not valid parameter arguments") if current.type == :action
|
|
32
|
+
|
|
33
|
+
arguments << parse_item
|
|
34
|
+
break unless accept(:",")
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
expect(:")")
|
|
38
|
+
item = AST::ParameterizedReference.new(
|
|
39
|
+
name: token_string(callee), arguments: arguments, named_reference: parse_named_reference, loc: callee.location
|
|
40
|
+
)
|
|
41
|
+
parse_suffix(item)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# @rbs () -> bool
|
|
45
|
+
def parameterized_call?
|
|
46
|
+
# @type self: BootstrapParser
|
|
47
|
+
current.type == :identifier && lookahead.type == :"(" && adjacent_tokens?(current, lookahead)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @rbs () -> bool
|
|
51
|
+
def parameterized_rule_start?
|
|
52
|
+
# @type self: BootstrapParser
|
|
53
|
+
opening = lookahead
|
|
54
|
+
return false unless opening.type == :"(" && adjacent_tokens?(current, opening)
|
|
55
|
+
|
|
56
|
+
parameter_definition_tail?(@tokens.drop(@index + 2))
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @rbs (Array[Token] tail) -> bool
|
|
60
|
+
def parameter_definition_tail?(tail)
|
|
61
|
+
# @type self: BootstrapParser
|
|
62
|
+
closing = tail.index { |token| token.type == :")" }
|
|
63
|
+
return false unless closing && tail[closing + 1]&.type == :":"
|
|
64
|
+
|
|
65
|
+
formals = tail.take(closing)
|
|
66
|
+
!formals.empty? && formals.length.odd? &&
|
|
67
|
+
formals.each_with_index.all? { |token, index| token.type == (index.even? ? :identifier : :",") }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# @rbs (Token left, Token right) -> bool
|
|
71
|
+
def adjacent_tokens?(left, right)
|
|
72
|
+
# @type self: BootstrapParser
|
|
73
|
+
left_span = left.span
|
|
74
|
+
right_span = right.span
|
|
75
|
+
return left_span.end_byte == right_span.start_byte if left_span && right_span
|
|
76
|
+
|
|
77
|
+
left.location.line == right.location.line &&
|
|
78
|
+
left.location.column + token_string(left).length == right.location.column
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -14,7 +14,7 @@ module Ibex
|
|
|
14
14
|
def parse_rules
|
|
15
15
|
# @type self: BootstrapParser
|
|
16
16
|
rules = [] #: Array[AST::Rule]
|
|
17
|
-
rules << parse_rule until keyword?("end") || current.type
|
|
17
|
+
rules << parse_rule until keyword?("end") || %i[eof user_code].include?(current.type)
|
|
18
18
|
fail_expected("at least one rule") if rules.empty?
|
|
19
19
|
rules
|
|
20
20
|
end
|
|
@@ -22,7 +22,10 @@ module Ibex
|
|
|
22
22
|
# @rbs () -> AST::Rule
|
|
23
23
|
def parse_rule
|
|
24
24
|
# @type self: BootstrapParser
|
|
25
|
+
inline = accept(:inline)
|
|
26
|
+
extended_only!(inline.location, "inline rules") if inline
|
|
25
27
|
lhs = expect(:identifier)
|
|
28
|
+
parameters = parse_rule_parameters(lhs)
|
|
26
29
|
expect(:":")
|
|
27
30
|
alternatives = [] #: Array[AST::Alternative]
|
|
28
31
|
loop do
|
|
@@ -32,7 +35,10 @@ module Ibex
|
|
|
32
35
|
accept(:";")
|
|
33
36
|
break
|
|
34
37
|
end
|
|
35
|
-
AST::Rule.new(
|
|
38
|
+
AST::Rule.new(
|
|
39
|
+
lhs: token_string(lhs), parameters: parameters, alternatives: alternatives, loc: lhs.location,
|
|
40
|
+
inline: !!inline
|
|
41
|
+
)
|
|
36
42
|
end
|
|
37
43
|
|
|
38
44
|
# @rbs (Token lhs) -> AST::Alternative
|
|
@@ -54,14 +60,42 @@ module Ibex
|
|
|
54
60
|
items.pop
|
|
55
61
|
action = last_item
|
|
56
62
|
end
|
|
57
|
-
|
|
63
|
+
node_annotation = parse_node_annotation
|
|
64
|
+
AST::Alternative.new(
|
|
65
|
+
items: items, action: action, precedence: precedence, node_annotation: node_annotation, loc: location
|
|
66
|
+
)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# @rbs () -> AST::NodeAnnotation?
|
|
70
|
+
def parse_node_annotation
|
|
71
|
+
# @type self: BootstrapParser
|
|
72
|
+
marker = accept(:node)
|
|
73
|
+
return unless marker
|
|
74
|
+
|
|
75
|
+
extended_only!(marker.location, "@node")
|
|
76
|
+
name = expect(:identifier)
|
|
77
|
+
expect(:"(")
|
|
78
|
+
fields = [] #: Array[String]
|
|
79
|
+
unless current.type == :")"
|
|
80
|
+
fields << token_string(expect(:identifier))
|
|
81
|
+
fields << token_string(expect(:identifier)) while accept(:",")
|
|
82
|
+
end
|
|
83
|
+
expect(:")")
|
|
84
|
+
AST::NodeAnnotation.new(name: token_string(name), fields: fields, loc: marker.location)
|
|
58
85
|
end
|
|
59
86
|
|
|
60
87
|
# @rbs () -> AST::item
|
|
61
88
|
def parse_item
|
|
62
89
|
# @type self: BootstrapParser
|
|
63
90
|
return parse_action if current.type == :action
|
|
91
|
+
|
|
92
|
+
if current.type == :empty
|
|
93
|
+
token = advance
|
|
94
|
+
extended_only!(token.location, "%empty")
|
|
95
|
+
return AST::Empty.new(loc: token.location)
|
|
96
|
+
end
|
|
64
97
|
return parse_separated_list if separated_list?
|
|
98
|
+
return parse_parameterized_reference if parameterized_call?
|
|
65
99
|
return parse_group if current.type == :"("
|
|
66
100
|
|
|
67
101
|
token = expect_symbol
|
|
@@ -105,7 +139,7 @@ module Ibex
|
|
|
105
139
|
extended_only!(opening.location, "EBNF groups")
|
|
106
140
|
alternatives = [[]] #: Array[Array[AST::item]]
|
|
107
141
|
until current.type == :")"
|
|
108
|
-
fail_at(opening.location, "unterminated EBNF group") if current.type == :eof
|
|
142
|
+
fail_at(opening.location, "unterminated EBNF group") if current.type == :eof
|
|
109
143
|
if accept(:|)
|
|
110
144
|
alternatives << []
|
|
111
145
|
next
|
|
@@ -135,13 +169,16 @@ module Ibex
|
|
|
135
169
|
# @rbs (Token lhs) -> bool
|
|
136
170
|
def alternative_end?(lhs)
|
|
137
171
|
# @type self: BootstrapParser
|
|
138
|
-
%i[| ; eof].include?(current.type) || keyword?("end") || rule_start?(lhs)
|
|
172
|
+
%i[| ; inline node eof user_code].include?(current.type) || keyword?("end") || rule_start?(lhs)
|
|
139
173
|
end
|
|
140
174
|
|
|
141
175
|
# @rbs (Token lhs) -> bool
|
|
142
176
|
def rule_start?(lhs)
|
|
143
177
|
# @type self: BootstrapParser
|
|
144
|
-
|
|
178
|
+
return false unless current.type == :identifier && current.location.column <= lhs.location.column
|
|
179
|
+
return true if lookahead.type == :":"
|
|
180
|
+
|
|
181
|
+
parameterized_rule_start?
|
|
145
182
|
end
|
|
146
183
|
|
|
147
184
|
# @rbs () -> bool
|