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.
Files changed (603) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +89 -123
  3. data/docs/architecture.md +477 -31
  4. data/docs/bison-import.md +103 -0
  5. data/docs/comparison-policy.md +127 -0
  6. data/docs/configuration-model.md +59 -0
  7. data/docs/configuration-report.md +28 -0
  8. data/docs/conflict-explanation-reviews/v1/records/README.md +28 -0
  9. data/docs/conflict-explanation-study.md +62 -0
  10. data/docs/construction-profiling.md +157 -0
  11. data/docs/cst-migration.md +106 -0
  12. data/docs/cst.md +237 -0
  13. data/docs/decisions/0000-template.md +24 -0
  14. data/docs/decisions/0001-separate-ir-pipeline.md +34 -0
  15. data/docs/decisions/0002-opaque-user-code-boundary.md +32 -0
  16. data/docs/decisions/0003-self-hosted-grammar-frontend.md +32 -0
  17. data/docs/decisions/0004-shared-semantic-and-lossless-source-model.md +33 -0
  18. data/docs/decisions/0005-contained-grammar-composition.md +34 -0
  19. data/docs/decisions/0006-bounded-structural-grammar-lowering.md +32 -0
  20. data/docs/decisions/0007-shared-parser-construction-pipeline.md +33 -0
  21. data/docs/decisions/0008-versioned-runtime-package-boundary.md +36 -0
  22. data/docs/decisions/0009-isolated-parser-sessions.md +34 -0
  23. data/docs/decisions/0010-committed-runtime-observation.md +34 -0
  24. data/docs/decisions/0011-versioned-semantic-action-boundary.md +37 -0
  25. data/docs/decisions/0012-bounded-nonexecuting-analysis.md +37 -0
  26. data/docs/decisions/0013-transactional-generation-publication.md +37 -0
  27. data/docs/decisions/0014-versioned-generated-lexer.md +35 -0
  28. data/docs/decisions/0015-worker-isolated-browser-analysis.md +32 -0
  29. data/docs/decisions/0016-red-green-concrete-syntax.md +34 -0
  30. data/docs/decisions/0017-persistent-syntax-artifacts.md +35 -0
  31. data/docs/decisions/0018-conservative-incremental-syntax-reuse.md +38 -0
  32. data/docs/decisions/0019-runtime-syntax-session-boundary.md +51 -0
  33. data/docs/decisions/0020-grammar-ir-parser-contract.md +65 -0
  34. data/docs/decisions/0021-data-only-parser-table-sidecar.md +50 -0
  35. data/docs/decisions/0022-manifest-bound-verification-report.md +77 -0
  36. data/docs/decisions/0023-syntax-only-repair-results.md +48 -0
  37. data/docs/decisions/0024-direct-ielr-construction.md +42 -0
  38. data/docs/decisions/README.md +74 -0
  39. data/docs/declarative-configuration.md +262 -0
  40. data/docs/development.md +306 -0
  41. data/docs/direct-ielr-decision.md +120 -0
  42. data/docs/direct-multi-entry-decision.md +82 -0
  43. data/docs/editor-setup.md +26 -0
  44. data/docs/error-ux-review-rubric-v1.md +117 -0
  45. data/docs/error-ux-reviews/v1/records/README.md +22 -0
  46. data/docs/error-ux-round2-review-status-v1.json +27 -0
  47. data/docs/error-ux-round2-reviews/v1/records/README.md +30 -0
  48. data/docs/error-ux-round2-v1.json +1581 -0
  49. data/docs/error-ux-round2.md +111 -0
  50. data/docs/error-ux.md +114 -0
  51. data/docs/getting-started.md +80 -0
  52. data/docs/grammar-reference.md +629 -18
  53. data/docs/ielr-design.md +43 -0
  54. data/docs/ielr.md +92 -0
  55. data/docs/ja/bison-import.md +51 -0
  56. data/docs/ja/stable-api.md +53 -0
  57. data/docs/lexer-construction-profile.md +109 -0
  58. data/docs/lexer-migration.md +56 -0
  59. data/docs/maturity.md +128 -0
  60. data/docs/project-site-strategy.md +54 -0
  61. data/docs/racc-migration-evidence.md +45 -0
  62. data/docs/racc-migration.md +45 -6
  63. data/docs/release-readiness.md +221 -0
  64. data/docs/repair-semantics.md +123 -0
  65. data/docs/runtime-abi-evolution.md +307 -0
  66. data/docs/stability.md +234 -0
  67. data/docs/status.md +43 -0
  68. data/docs/syntax-sessions.md +183 -0
  69. data/docs/table-artifact.md +125 -0
  70. data/docs/test-interactions.md +219 -0
  71. data/docs/verification-report.md +137 -0
  72. data/docs/verifier-trust-boundary.md +199 -0
  73. data/docs/workloads.md +132 -0
  74. data/examples/README.md +60 -0
  75. data/examples/calculator.y +44 -0
  76. data/examples/csv.y +32 -0
  77. data/examples/ini.y +70 -0
  78. data/examples/json.y +48 -0
  79. data/examples/tiny_language.y +75 -0
  80. data/lib/ibex/analysis/digraph.rb +128 -0
  81. data/lib/ibex/analysis/sets.rb +5 -4
  82. data/lib/ibex/analysis.rb +1 -0
  83. data/lib/ibex/artifact_set.rb +63 -0
  84. data/lib/ibex/bison_import/importer.rb +516 -0
  85. data/lib/ibex/bison_import/tokenizer.rb +260 -0
  86. data/lib/ibex/bison_import.rb +200 -0
  87. data/lib/ibex/bounded_subprocess.rb +171 -0
  88. data/lib/ibex/cli/ambiguity.rb +75 -0
  89. data/lib/ibex/cli/analysis.rb +134 -0
  90. data/lib/ibex/cli/bison_import.rb +121 -0
  91. data/lib/ibex/cli/config.rb +128 -0
  92. data/lib/ibex/cli/counterexample_options.rb +6 -2
  93. data/lib/ibex/cli/coverage.rb +173 -0
  94. data/lib/ibex/cli/debug.rb +106 -0
  95. data/lib/ibex/cli/diagnostics.rb +136 -0
  96. data/lib/ibex/cli/documentation.rb +70 -0
  97. data/lib/ibex/cli/equiv.rb +169 -0
  98. data/lib/ibex/cli/error_messages.rb +184 -0
  99. data/lib/ibex/cli/explain.rb +85 -0
  100. data/lib/ibex/cli/fix.rb +203 -0
  101. data/lib/ibex/cli/formatting.rb +387 -0
  102. data/lib/ibex/cli/fuzz.rb +200 -0
  103. data/lib/ibex/cli/fuzz_regressions.rb +145 -0
  104. data/lib/ibex/cli/generation_artifacts.rb +189 -0
  105. data/lib/ibex/cli/generation_error_messages.rb +39 -0
  106. data/lib/ibex/cli/grammar_tests.rb +140 -0
  107. data/lib/ibex/cli/ir_tools.rb +128 -0
  108. data/lib/ibex/cli/lsp.rb +33 -0
  109. data/lib/ibex/cli/outputs.rb +133 -23
  110. data/lib/ibex/cli/racc_migration.rb +87 -0
  111. data/lib/ibex/cli/reduce.rb +202 -0
  112. data/lib/ibex/cli/reduce_reporting.rb +71 -0
  113. data/lib/ibex/cli/samples.rb +118 -0
  114. data/lib/ibex/cli/verify.rb +116 -0
  115. data/lib/ibex/cli/watch.rb +104 -0
  116. data/lib/ibex/cli.rb +825 -55
  117. data/lib/ibex/codegen/action_locations.rb +103 -0
  118. data/lib/ibex/codegen/action_method_source.rb +209 -0
  119. data/lib/ibex/codegen/action_source.rb +119 -0
  120. data/lib/ibex/codegen/ambiguity.rb +174 -0
  121. data/lib/ibex/codegen/cst_metadata.rb +171 -0
  122. data/lib/ibex/codegen/documentation.rb +170 -0
  123. data/lib/ibex/codegen/explain.rb +380 -0
  124. data/lib/ibex/codegen/generated_action_abi.rb +293 -0
  125. data/lib/ibex/codegen/html.rb +94 -10
  126. data/lib/ibex/codegen/mermaid.rb +43 -0
  127. data/lib/ibex/codegen/railroad.rb +197 -0
  128. data/lib/ibex/codegen/railroad_documentation.rb +59 -0
  129. data/lib/ibex/codegen/rbs.rb +331 -2
  130. data/lib/ibex/codegen/report.rb +67 -15
  131. data/lib/ibex/codegen/ruby.rb +305 -66
  132. data/lib/ibex/codegen/ruby_actions.rb +146 -0
  133. data/lib/ibex/codegen/ruby_ast.rb +121 -0
  134. data/lib/ibex/codegen/ruby_error_messages.rb +28 -0
  135. data/lib/ibex/codegen/ruby_lexer.rb +83 -0
  136. data/lib/ibex/codegen/ruby_syntax.rb +96 -0
  137. data/lib/ibex/codegen/ruby_table_metadata.rb +57 -0
  138. data/lib/ibex/codegen/ruby_value_printers.rb +56 -0
  139. data/lib/ibex/codegen/symbol_labels.rb +1 -1
  140. data/lib/ibex/configuration/analysis_grammar.rb +35 -0
  141. data/lib/ibex/configuration/explanation.rb +421 -0
  142. data/lib/ibex/configuration/inspector.rb +232 -0
  143. data/lib/ibex/configuration.rb +580 -0
  144. data/lib/ibex/coverage/collector.rb +198 -0
  145. data/lib/ibex/coverage/event_stream.rb +103 -0
  146. data/lib/ibex/coverage/report.rb +267 -0
  147. data/lib/ibex/coverage/runtime_event_validator.rb +169 -0
  148. data/lib/ibex/coverage.rb +13 -0
  149. data/lib/ibex/delta_reducer.rb +99 -0
  150. data/lib/ibex/diff.rb +140 -0
  151. data/lib/ibex/equiv/machine.rb +135 -0
  152. data/lib/ibex/equiv.rb +373 -0
  153. data/lib/ibex/error_messages/parser.rb +159 -0
  154. data/lib/ibex/error_messages/parser_v2.rb +198 -0
  155. data/lib/ibex/error_messages/renderer.rb +65 -0
  156. data/lib/ibex/error_messages/sentence_search.rb +196 -0
  157. data/lib/ibex/error_messages/update.rb +169 -0
  158. data/lib/ibex/error_messages.rb +165 -0
  159. data/lib/ibex/fix.rb +557 -0
  160. data/lib/ibex/frontend/ast.rb +166 -7
  161. data/lib/ibex/frontend/bootstrap_parser.rb +40 -4
  162. data/lib/ibex/frontend/diagnostic.rb +81 -0
  163. data/lib/ibex/frontend/diagnostic_recovery.rb +268 -0
  164. data/lib/ibex/frontend/dsl.rb +66 -7
  165. data/lib/ibex/frontend/formatter.rb +453 -0
  166. data/lib/ibex/frontend/generated_parser.rb +644 -190
  167. data/lib/ibex/frontend/generated_parser_base.rb +170 -32
  168. data/lib/ibex/frontend/generated_parser_includes.rb +51 -0
  169. data/lib/ibex/frontend/generated_parser_metadata.rb +61 -0
  170. data/lib/ibex/frontend/generated_parser_parameters.rb +60 -0
  171. data/lib/ibex/frontend/generation.rb +33 -0
  172. data/lib/ibex/frontend/lexer.rb +162 -10
  173. data/lib/ibex/frontend/lexer_recovery.rb +84 -0
  174. data/lib/ibex/frontend/parser/declarations.rb +262 -11
  175. data/lib/ibex/frontend/parser/parameters.rb +82 -0
  176. data/lib/ibex/frontend/parser/rules.rb +43 -6
  177. data/lib/ibex/frontend/parser.rb +182 -4
  178. data/lib/ibex/frontend/parser_configuration_support.rb +56 -0
  179. data/lib/ibex/frontend/regenerator.rb +27 -1
  180. data/lib/ibex/frontend/resolution.rb +70 -0
  181. data/lib/ibex/frontend/resolver.rb +217 -0
  182. data/lib/ibex/frontend/rule_documentation.rb +104 -0
  183. data/lib/ibex/frontend/source_cursor.rb +133 -9
  184. data/lib/ibex/frontend/source_document.rb +229 -0
  185. data/lib/ibex/frontend/source_loader.rb +150 -0
  186. data/lib/ibex/frontend/source_span.rb +89 -0
  187. data/lib/ibex/frontend/token_adapter/declaration_document_state.rb +47 -0
  188. data/lib/ibex/frontend/token_adapter/declaration_lexer_state.rb +83 -0
  189. data/lib/ibex/frontend/token_adapter/declaration_state.rb +244 -22
  190. data/lib/ibex/frontend/token_adapter/delimiter_tracker.rb +8 -2
  191. data/lib/ibex/frontend/token_adapter/rule_state.rb +60 -2
  192. data/lib/ibex/frontend/token_adapter.rb +18 -3
  193. data/lib/ibex/frontend.rb +14 -2
  194. data/lib/ibex/fuzz.rb +219 -0
  195. data/lib/ibex/generation_input.rb +57 -0
  196. data/lib/ibex/generation_manifest.rb +211 -0
  197. data/lib/ibex/generation_transaction.rb +261 -0
  198. data/lib/ibex/generation_transaction_recovery.rb +109 -0
  199. data/lib/ibex/generation_transaction_validation.rb +196 -0
  200. data/lib/ibex/grammar_tests.rb +206 -0
  201. data/lib/ibex/ir/automaton_ir.rb +86 -11
  202. data/lib/ibex/ir/grammar_ir.rb +170 -26
  203. data/lib/ibex/ir/lexer_ir.rb +76 -0
  204. data/lib/ibex/ir/parser_contract.rb +135 -0
  205. data/lib/ibex/ir/serialize.rb +268 -50
  206. data/lib/ibex/ir/validator/automaton.rb +375 -0
  207. data/lib/ibex/ir/validator/base.rb +147 -0
  208. data/lib/ibex/ir/validator/grammar.rb +634 -0
  209. data/lib/ibex/ir/validator/lexer.rb +113 -0
  210. data/lib/ibex/ir/validator.rb +63 -0
  211. data/lib/ibex/ir.rb +71 -5
  212. data/lib/ibex/lalr/build_metrics.rb +71 -0
  213. data/lib/ibex/lalr/builder.rb +514 -52
  214. data/lib/ibex/lalr/conflict.rb +1 -0
  215. data/lib/ibex/lalr/conflict_search.rb +26 -9
  216. data/lib/ibex/lalr/counterexample.rb +38 -18
  217. data/lib/ibex/lalr/direct_lookaheads.rb +289 -0
  218. data/lib/ibex/lalr/goto_follows.rb +229 -0
  219. data/lib/ibex/lalr/ielr/annotator.rb +214 -0
  220. data/lib/ibex/lalr/ielr/bits.rb +28 -0
  221. data/lib/ibex/lalr/ielr/inadequacy.rb +47 -0
  222. data/lib/ibex/lalr/ielr/item_lookaheads.rb +78 -0
  223. data/lib/ibex/lalr/ielr/pipeline.rb +75 -0
  224. data/lib/ibex/lalr/ielr/split_stability.rb +78 -0
  225. data/lib/ibex/lalr/ielr/split_state.rb +20 -0
  226. data/lib/ibex/lalr/ielr/state_splitter.rb +258 -0
  227. data/lib/ibex/lalr/ielr_partition.rb +166 -0
  228. data/lib/ibex/lalr/inadequacy_report.rb +50 -0
  229. data/lib/ibex/lalr/lookahead_propagation.rb +111 -0
  230. data/lib/ibex/lalr/lr0_collection.rb +121 -0
  231. data/lib/ibex/lalr/on_error_reductions.rb +74 -0
  232. data/lib/ibex/lalr/unreachable_states.rb +80 -0
  233. data/lib/ibex/lalr.rb +59 -1
  234. data/lib/ibex/location.rb +129 -0
  235. data/lib/ibex/lsp/document_handlers.rb +68 -0
  236. data/lib/ibex/lsp/document_store.rb +264 -0
  237. data/lib/ibex/lsp/document_store_diagnostics.rb +44 -0
  238. data/lib/ibex/lsp/document_store_validation.rb +61 -0
  239. data/lib/ibex/lsp/initialization_handlers.rb +80 -0
  240. data/lib/ibex/lsp/navigation_handlers.rb +70 -0
  241. data/lib/ibex/lsp/parser_configuration_assistance.rb +149 -0
  242. data/lib/ibex/lsp/position_codec.rb +113 -0
  243. data/lib/ibex/lsp/protocol_error.rb +33 -0
  244. data/lib/ibex/lsp/request_handlers.rb +46 -0
  245. data/lib/ibex/lsp/request_support.rb +94 -0
  246. data/lib/ibex/lsp/server.rb +148 -0
  247. data/lib/ibex/lsp/symbol_index.rb +241 -0
  248. data/lib/ibex/lsp/symbol_index_builder.rb +277 -0
  249. data/lib/ibex/lsp/symbol_index_precedence_references.rb +44 -0
  250. data/lib/ibex/lsp/symbol_index_source_queries.rb +61 -0
  251. data/lib/ibex/lsp/symbol_occurrence.rb +23 -0
  252. data/lib/ibex/lsp/transport.rb +128 -0
  253. data/lib/ibex/lsp/workspace.rb +128 -0
  254. data/lib/ibex/lsp/workspace_analyzer.rb +199 -0
  255. data/lib/ibex/lsp.rb +33 -0
  256. data/lib/ibex/messages/en.yml +28 -0
  257. data/lib/ibex/messages/ja.yml +28 -0
  258. data/lib/ibex/messages.rb +68 -0
  259. data/lib/ibex/metrics.rb +175 -0
  260. data/lib/ibex/normalize/declarations.rb +142 -7
  261. data/lib/ibex/normalize/diagnostics.rb +94 -24
  262. data/lib/ibex/normalize/expander.rb +64 -59
  263. data/lib/ibex/normalize/expression.rb +63 -40
  264. data/lib/ibex/normalize/grammar_builder.rb +26 -0
  265. data/lib/ibex/normalize/inline_expansion.rb +465 -0
  266. data/lib/ibex/normalize/inline_validation.rb +174 -0
  267. data/lib/ibex/normalize/lexer.rb +131 -0
  268. data/lib/ibex/normalize/named_references.rb +60 -0
  269. data/lib/ibex/normalize/nodes.rb +46 -0
  270. data/lib/ibex/normalize/parameter_ebnf_lowering.rb +70 -0
  271. data/lib/ibex/normalize/parameter_lowering.rb +143 -0
  272. data/lib/ibex/normalize/parameter_substitution.rb +125 -0
  273. data/lib/ibex/normalize/parameter_validation.rb +140 -0
  274. data/lib/ibex/normalize/parameters.rb +226 -0
  275. data/lib/ibex/normalize/parser_configuration.rb +70 -0
  276. data/lib/ibex/normalize/recovery_declarations.rb +84 -0
  277. data/lib/ibex/normalize.rb +172 -17
  278. data/lib/ibex/racc_migration/checker.rb +122 -0
  279. data/lib/ibex/racc_migration/harness.rb +177 -0
  280. data/lib/ibex/racc_migration/report.rb +97 -0
  281. data/lib/ibex/racc_migration.rb +12 -0
  282. data/lib/ibex/rake_task.rb +116 -0
  283. data/lib/ibex/samples.rb +216 -0
  284. data/lib/ibex/table_artifact/builder.rb +266 -0
  285. data/lib/ibex/table_artifact/cst_projection.rb +70 -0
  286. data/lib/ibex/table_artifact/document.rb +39 -0
  287. data/lib/ibex/table_artifact/executor.rb +187 -0
  288. data/lib/ibex/table_artifact/serializer.rb +57 -0
  289. data/lib/ibex/table_artifact/validator/metadata.rb +179 -0
  290. data/lib/ibex/table_artifact/validator/support.rb +86 -0
  291. data/lib/ibex/table_artifact/validator/tables.rb +238 -0
  292. data/lib/ibex/table_artifact/validator.rb +253 -0
  293. data/lib/ibex/table_artifact.rb +88 -0
  294. data/lib/ibex/table_simulation/result.rb +55 -0
  295. data/lib/ibex/table_simulation/simulator.rb +253 -0
  296. data/lib/ibex/table_simulation/step.rb +62 -0
  297. data/lib/ibex/table_simulation/text.rb +31 -0
  298. data/lib/ibex/table_simulation.rb +13 -0
  299. data/lib/ibex/tables.rb +22 -69
  300. data/lib/ibex/verifiable_generation_bundle.rb +86 -0
  301. data/lib/ibex/verification_report/builder.rb +159 -0
  302. data/lib/ibex/verification_report/canonical_ir.rb +123 -0
  303. data/lib/ibex/verification_report/logical_path.rb +68 -0
  304. data/lib/ibex/verification_report/validator.rb +329 -0
  305. data/lib/ibex/verification_report.rb +69 -0
  306. data/lib/ibex/verify/action_correspondence.rb +138 -0
  307. data/lib/ibex/verify/language_witness.rb +295 -0
  308. data/lib/ibex/verify/reference_collection.rb +190 -0
  309. data/lib/ibex/verify/result.rb +73 -0
  310. data/lib/ibex/verify/verifier.rb +598 -0
  311. data/lib/ibex/verify.rb +15 -0
  312. data/lib/ibex/version.rb +1 -1
  313. data/lib/ibex/watch/runner.rb +181 -0
  314. data/lib/ibex/watch/source_snapshot.rb +98 -0
  315. data/lib/ibex/watch.rb +11 -0
  316. data/lib/ibex.rb +35 -1
  317. data/schema/automaton-ir-definitions.schema.json +401 -0
  318. data/schema/automaton-ir.schema.json +65 -0
  319. data/schema/benchmark-v1.schema.json +212 -0
  320. data/schema/benchmark-v2.schema.json +61 -0
  321. data/schema/bison-import-v1.schema.json +106 -0
  322. data/schema/conflict-explanation-review-v1.schema.json +196 -0
  323. data/schema/conflict-explanation-study-v1.schema.json +528 -0
  324. data/schema/construction-profile-v1.schema.json +779 -0
  325. data/schema/cst-v1.json +170 -0
  326. data/schema/diff-v1.schema.json +41 -0
  327. data/schema/direct-ielr-decision-v1.schema.json +200 -0
  328. data/schema/equiv-v1.schema.json +64 -0
  329. data/schema/error-ux-review-v1.schema.json +609 -0
  330. data/schema/error-ux-round2-review-v1.schema.json +191 -0
  331. data/schema/error-ux-round2-v1.schema.json +519 -0
  332. data/schema/error-ux-v1.schema.json +258 -0
  333. data/schema/explain-v1.schema.json +495 -0
  334. data/schema/fix-v1.schema.json +64 -0
  335. data/schema/fix-v2.schema.json +66 -0
  336. data/schema/fix-v3.schema.json +101 -0
  337. data/schema/frontend-diagnostics-v1.schema.json +154 -0
  338. data/schema/fuzz-regression-v1.schema.json +79 -0
  339. data/schema/fuzz-v1.schema.json +114 -0
  340. data/schema/generation-manifest-v1.schema.json +115 -0
  341. data/schema/grammar-ir-extensions.schema.json +734 -0
  342. data/schema/grammar-ir-foundation.schema.json +426 -0
  343. data/schema/grammar-ir.schema.json +271 -0
  344. data/schema/ielr-benchmark-v1.schema.json +85 -0
  345. data/schema/lexer-ir-v1.schema.json +215 -0
  346. data/schema/lexer-profile-v1.schema.json +491 -0
  347. data/schema/metrics-v1.schema.json +60 -0
  348. data/schema/migration-check-v1.schema.json +60 -0
  349. data/schema/performance-comparison-v1.schema.json +395 -0
  350. data/schema/public-performance-comparison-v1.schema.json +506 -0
  351. data/schema/public-performance-profile-v1.schema.json +360 -0
  352. data/schema/reduce-v1.schema.json +22 -0
  353. data/schema/reduce-v2.schema.json +63 -0
  354. data/schema/runtime-coverage-v1.schema.json +86 -0
  355. data/schema/runtime-event-v1.schema.json +308 -0
  356. data/schema/table-artifact-v1.schema.json +377 -0
  357. data/schema/table-simulation-v1.schema.json +70 -0
  358. data/schema/verification-report-v1.schema.json +222 -0
  359. data/schema/verify-v1.schema.json +42 -0
  360. data/sig/ibex/analysis/digraph.rbs +19 -0
  361. data/sig/ibex/artifact_set.rbs +37 -0
  362. data/sig/ibex/bison_import/importer.rbs +140 -0
  363. data/sig/ibex/bison_import/tokenizer.rbs +91 -0
  364. data/sig/ibex/bison_import.rbs +95 -0
  365. data/sig/ibex/bounded_subprocess.rbs +76 -0
  366. data/sig/ibex/cli/ambiguity.rbs +28 -0
  367. data/sig/ibex/cli/analysis.rbs +43 -0
  368. data/sig/ibex/cli/bison_import.rbs +32 -0
  369. data/sig/ibex/cli/config.rbs +35 -0
  370. data/sig/ibex/cli/counterexample_options.rbs +2 -0
  371. data/sig/ibex/cli/coverage.rbs +53 -0
  372. data/sig/ibex/cli/debug.rbs +28 -0
  373. data/sig/ibex/cli/diagnostics.rbs +51 -0
  374. data/sig/ibex/cli/documentation.rbs +29 -0
  375. data/sig/ibex/cli/equiv.rbs +49 -0
  376. data/sig/ibex/cli/error_messages.rbs +63 -0
  377. data/sig/ibex/cli/explain.rbs +31 -0
  378. data/sig/ibex/cli/fix.rbs +53 -0
  379. data/sig/ibex/cli/formatting.rbs +107 -0
  380. data/sig/ibex/cli/fuzz.rbs +47 -0
  381. data/sig/ibex/cli/fuzz_regressions.rbs +40 -0
  382. data/sig/ibex/cli/generation_artifacts.rbs +69 -0
  383. data/sig/ibex/cli/generation_error_messages.rbs +19 -0
  384. data/sig/ibex/cli/grammar_tests.rbs +48 -0
  385. data/sig/ibex/cli/ir_tools.rbs +39 -0
  386. data/sig/ibex/cli/lsp.rbs +14 -0
  387. data/sig/ibex/cli/outputs.rbs +26 -3
  388. data/sig/ibex/cli/racc_migration.rbs +30 -0
  389. data/sig/ibex/cli/reduce.rbs +60 -0
  390. data/sig/ibex/cli/reduce_reporting.rbs +27 -0
  391. data/sig/ibex/cli/samples.rbs +38 -0
  392. data/sig/ibex/cli/verify.rbs +28 -0
  393. data/sig/ibex/cli/watch.rbs +43 -0
  394. data/sig/ibex/cli.rbs +182 -9
  395. data/sig/ibex/codegen/action_locations.rbs +45 -0
  396. data/sig/ibex/codegen/action_method_source.rbs +65 -0
  397. data/sig/ibex/codegen/action_source.rbs +50 -0
  398. data/sig/ibex/codegen/ambiguity.rbs +60 -0
  399. data/sig/ibex/codegen/cst_metadata.rbs +59 -0
  400. data/sig/ibex/codegen/documentation.rbs +50 -0
  401. data/sig/ibex/codegen/explain.rbs +105 -0
  402. data/sig/ibex/codegen/generated_action_abi.rbs +105 -0
  403. data/sig/ibex/codegen/html.rbs +18 -2
  404. data/sig/ibex/codegen/mermaid.rbs +16 -0
  405. data/sig/ibex/codegen/railroad.rbs +82 -0
  406. data/sig/ibex/codegen/railroad_documentation.rbs +31 -0
  407. data/sig/ibex/codegen/rbs.rbs +86 -4
  408. data/sig/ibex/codegen/report.rbs +16 -8
  409. data/sig/ibex/codegen/ruby.rbs +105 -28
  410. data/sig/ibex/codegen/ruby_actions.rbs +54 -0
  411. data/sig/ibex/codegen/ruby_ast.rbs +34 -0
  412. data/sig/ibex/codegen/ruby_error_messages.rbs +16 -0
  413. data/sig/ibex/codegen/ruby_lexer.rbs +25 -0
  414. data/sig/ibex/codegen/ruby_syntax.rbs +27 -0
  415. data/sig/ibex/codegen/ruby_table_metadata.rbs +26 -0
  416. data/sig/ibex/codegen/ruby_value_printers.rbs +28 -0
  417. data/sig/ibex/configuration/analysis_grammar.rbs +13 -0
  418. data/sig/ibex/configuration/explanation.rbs +195 -0
  419. data/sig/ibex/configuration/inspector.rbs +53 -0
  420. data/sig/ibex/configuration.rbs +242 -0
  421. data/sig/ibex/coverage/collector.rbs +78 -0
  422. data/sig/ibex/coverage/event_stream.rbs +44 -0
  423. data/sig/ibex/coverage/report.rbs +102 -0
  424. data/sig/ibex/coverage/runtime_event_validator.rbs +70 -0
  425. data/sig/ibex/coverage.rbs +7 -0
  426. data/sig/ibex/delta_reducer.rbs +38 -0
  427. data/sig/ibex/diff.rbs +47 -0
  428. data/sig/ibex/equiv/machine.rbs +54 -0
  429. data/sig/ibex/equiv.rbs +129 -0
  430. data/sig/ibex/error_messages/parser.rbs +58 -0
  431. data/sig/ibex/error_messages/parser_v2.rbs +67 -0
  432. data/sig/ibex/error_messages/renderer.rbs +23 -0
  433. data/sig/ibex/error_messages/sentence_search.rbs +80 -0
  434. data/sig/ibex/error_messages/update.rbs +43 -0
  435. data/sig/ibex/error_messages.rbs +85 -0
  436. data/sig/ibex/fix.rbs +138 -0
  437. data/sig/ibex/frontend/ast.rbs +237 -22
  438. data/sig/ibex/frontend/bootstrap_parser.rbs +13 -0
  439. data/sig/ibex/frontend/diagnostic.rbs +53 -0
  440. data/sig/ibex/frontend/diagnostic_recovery.rbs +98 -0
  441. data/sig/ibex/frontend/dsl.rbs +33 -4
  442. data/sig/ibex/frontend/formatter.rbs +143 -0
  443. data/sig/ibex/frontend/generated_parser.rbs +228 -68
  444. data/sig/ibex/frontend/generated_parser_base.rbs +65 -12
  445. data/sig/ibex/frontend/generated_parser_includes.rbs +23 -0
  446. data/sig/ibex/frontend/generated_parser_metadata.rbs +23 -0
  447. data/sig/ibex/frontend/generated_parser_parameters.rbs +24 -0
  448. data/sig/ibex/frontend/generation.rbs +6 -0
  449. data/sig/ibex/frontend/lexer.rbs +49 -2
  450. data/sig/ibex/frontend/lexer_recovery.rbs +25 -0
  451. data/sig/ibex/frontend/parser/declarations.rbs +57 -0
  452. data/sig/ibex/frontend/parser/parameters.rbs +28 -0
  453. data/sig/ibex/frontend/parser/rules.rbs +3 -0
  454. data/sig/ibex/frontend/parser.rbs +66 -0
  455. data/sig/ibex/frontend/parser_configuration_support.rbs +27 -0
  456. data/sig/ibex/frontend/regenerator.rbs +11 -0
  457. data/sig/ibex/frontend/resolution.rbs +34 -0
  458. data/sig/ibex/frontend/resolver.rbs +91 -0
  459. data/sig/ibex/frontend/rule_documentation.rbs +42 -0
  460. data/sig/ibex/frontend/source_cursor.rbs +38 -5
  461. data/sig/ibex/frontend/source_document.rbs +119 -0
  462. data/sig/ibex/frontend/source_loader.rbs +66 -0
  463. data/sig/ibex/frontend/source_span.rbs +56 -0
  464. data/sig/ibex/frontend/token_adapter/declaration_document_state.rbs +21 -0
  465. data/sig/ibex/frontend/token_adapter/declaration_lexer_state.rbs +27 -0
  466. data/sig/ibex/frontend/token_adapter/declaration_state.rbs +83 -3
  467. data/sig/ibex/frontend/token_adapter/rule_state.rbs +20 -0
  468. data/sig/ibex/frontend/token_adapter.rbs +11 -2
  469. data/sig/ibex/frontend.rbs +1 -1
  470. data/sig/ibex/fuzz.rbs +71 -0
  471. data/sig/ibex/generation_input.rbs +37 -0
  472. data/sig/ibex/generation_manifest.rbs +70 -0
  473. data/sig/ibex/generation_transaction.rbs +82 -0
  474. data/sig/ibex/generation_transaction_recovery.rbs +36 -0
  475. data/sig/ibex/generation_transaction_validation.rbs +65 -0
  476. data/sig/ibex/grammar_tests.rbs +93 -0
  477. data/sig/ibex/ir/automaton_ir.rbs +35 -10
  478. data/sig/ibex/ir/grammar_ir.rbs +96 -22
  479. data/sig/ibex/ir/lexer_ir.rbs +57 -0
  480. data/sig/ibex/ir/parser_contract.rbs +69 -0
  481. data/sig/ibex/ir/serialize.rbs +75 -23
  482. data/sig/ibex/ir/validator/automaton.rbs +112 -0
  483. data/sig/ibex/ir/validator/base.rbs +69 -0
  484. data/sig/ibex/ir/validator/grammar.rbs +195 -0
  485. data/sig/ibex/ir/validator/lexer.rbs +37 -0
  486. data/sig/ibex/ir/validator.rbs +16 -0
  487. data/sig/ibex/ir.rbs +45 -5
  488. data/sig/ibex/lalr/build_metrics.rbs +60 -0
  489. data/sig/ibex/lalr/builder.rbs +150 -19
  490. data/sig/ibex/lalr/conflict_search.rbs +12 -5
  491. data/sig/ibex/lalr/counterexample.rbs +20 -14
  492. data/sig/ibex/lalr/direct_lookaheads.rbs +93 -0
  493. data/sig/ibex/lalr/goto_follows.rbs +89 -0
  494. data/sig/ibex/lalr/ielr/annotator.rbs +67 -0
  495. data/sig/ibex/lalr/ielr/bits.rbs +14 -0
  496. data/sig/ibex/lalr/ielr/inadequacy.rbs +24 -0
  497. data/sig/ibex/lalr/ielr/item_lookaheads.rbs +35 -0
  498. data/sig/ibex/lalr/ielr/pipeline.rbs +17 -0
  499. data/sig/ibex/lalr/ielr/split_stability.rbs +27 -0
  500. data/sig/ibex/lalr/ielr/split_state.rbs +14 -0
  501. data/sig/ibex/lalr/ielr/state_splitter.rbs +76 -0
  502. data/sig/ibex/lalr/ielr_partition.rbs +71 -0
  503. data/sig/ibex/lalr/inadequacy_report.rbs +21 -0
  504. data/sig/ibex/lalr/lookahead_propagation.rbs +38 -0
  505. data/sig/ibex/lalr/lr0_collection.rbs +50 -0
  506. data/sig/ibex/lalr/on_error_reductions.rbs +22 -0
  507. data/sig/ibex/lalr/unreachable_states.rbs +25 -0
  508. data/sig/ibex/lalr.rbs +17 -1
  509. data/sig/ibex/location.rbs +67 -0
  510. data/sig/ibex/lsp/document_handlers.rbs +24 -0
  511. data/sig/ibex/lsp/document_store.rbs +94 -0
  512. data/sig/ibex/lsp/document_store_diagnostics.rbs +20 -0
  513. data/sig/ibex/lsp/document_store_validation.rbs +26 -0
  514. data/sig/ibex/lsp/initialization_handlers.rbs +30 -0
  515. data/sig/ibex/lsp/navigation_handlers.rbs +33 -0
  516. data/sig/ibex/lsp/parser_configuration_assistance.rbs +49 -0
  517. data/sig/ibex/lsp/position_codec.rbs +44 -0
  518. data/sig/ibex/lsp/protocol_error.rbs +32 -0
  519. data/sig/ibex/lsp/request_handlers.rbs +26 -0
  520. data/sig/ibex/lsp/request_support.rbs +40 -0
  521. data/sig/ibex/lsp/server.rbs +55 -0
  522. data/sig/ibex/lsp/symbol_index.rbs +77 -0
  523. data/sig/ibex/lsp/symbol_index_builder.rbs +88 -0
  524. data/sig/ibex/lsp/symbol_index_precedence_references.rbs +18 -0
  525. data/sig/ibex/lsp/symbol_index_source_queries.rbs +26 -0
  526. data/sig/ibex/lsp/symbol_occurrence.rbs +31 -0
  527. data/sig/ibex/lsp/transport.rbs +47 -0
  528. data/sig/ibex/lsp/workspace.rbs +42 -0
  529. data/sig/ibex/lsp/workspace_analyzer.rbs +69 -0
  530. data/sig/ibex/lsp.rbs +7 -0
  531. data/sig/ibex/messages.rbs +26 -0
  532. data/sig/ibex/metrics.rbs +50 -0
  533. data/sig/ibex/normalize/declarations.rbs +31 -0
  534. data/sig/ibex/normalize/diagnostics.rbs +13 -4
  535. data/sig/ibex/normalize/expander.rbs +22 -16
  536. data/sig/ibex/normalize/expression.rbs +11 -9
  537. data/sig/ibex/normalize/grammar_builder.rbs +11 -0
  538. data/sig/ibex/normalize/inline_expansion.rbs +129 -0
  539. data/sig/ibex/normalize/inline_validation.rbs +40 -0
  540. data/sig/ibex/normalize/lexer.rbs +37 -0
  541. data/sig/ibex/normalize/named_references.rbs +20 -0
  542. data/sig/ibex/normalize/nodes.rbs +14 -0
  543. data/sig/ibex/normalize/parameter_ebnf_lowering.rbs +33 -0
  544. data/sig/ibex/normalize/parameter_lowering.rbs +35 -0
  545. data/sig/ibex/normalize/parameter_substitution.rbs +42 -0
  546. data/sig/ibex/normalize/parameter_validation.rbs +44 -0
  547. data/sig/ibex/normalize/parameters.rbs +51 -0
  548. data/sig/ibex/normalize/parser_configuration.rbs +23 -0
  549. data/sig/ibex/normalize/recovery_declarations.rbs +24 -0
  550. data/sig/ibex/normalize.rbs +129 -18
  551. data/sig/ibex/racc_migration/checker.rbs +36 -0
  552. data/sig/ibex/racc_migration/harness.rbs +16 -0
  553. data/sig/ibex/racc_migration/report.rbs +55 -0
  554. data/sig/ibex/racc_migration.rbs +8 -0
  555. data/sig/ibex/rake_task.rbs +51 -0
  556. data/sig/ibex/samples.rbs +60 -0
  557. data/sig/ibex/table_artifact/builder.rbs +93 -0
  558. data/sig/ibex/table_artifact/cst_projection.rbs +20 -0
  559. data/sig/ibex/table_artifact/document.rbs +27 -0
  560. data/sig/ibex/table_artifact/executor.rbs +66 -0
  561. data/sig/ibex/table_artifact/serializer.rbs +25 -0
  562. data/sig/ibex/table_artifact/validator/metadata.rbs +52 -0
  563. data/sig/ibex/table_artifact/validator/support.rbs +46 -0
  564. data/sig/ibex/table_artifact/validator/tables.rbs +63 -0
  565. data/sig/ibex/table_artifact/validator.rbs +66 -0
  566. data/sig/ibex/table_artifact.rbs +32 -0
  567. data/sig/ibex/table_simulation/result.rbs +36 -0
  568. data/sig/ibex/table_simulation/simulator.rbs +98 -0
  569. data/sig/ibex/table_simulation/step.rbs +42 -0
  570. data/sig/ibex/table_simulation/text.rbs +14 -0
  571. data/sig/ibex/table_simulation.rbs +7 -0
  572. data/sig/ibex/tables.rbs +10 -35
  573. data/sig/ibex/verifiable_generation_bundle.rbs +24 -0
  574. data/sig/ibex/verification_report/builder.rbs +53 -0
  575. data/sig/ibex/verification_report/canonical_ir.rbs +41 -0
  576. data/sig/ibex/verification_report/logical_path.rbs +34 -0
  577. data/sig/ibex/verification_report/validator.rbs +114 -0
  578. data/sig/ibex/verification_report.rbs +44 -0
  579. data/sig/ibex/verify/action_correspondence.rbs +50 -0
  580. data/sig/ibex/verify/language_witness.rbs +112 -0
  581. data/sig/ibex/verify/reference_collection.rbs +63 -0
  582. data/sig/ibex/verify/result.rbs +52 -0
  583. data/sig/ibex/verify/verifier.rbs +170 -0
  584. data/sig/ibex/verify.rbs +6 -0
  585. data/sig/ibex/watch/runner.rbs +58 -0
  586. data/sig/ibex/watch/source_snapshot.rbs +46 -0
  587. data/sig/ibex/watch.rbs +7 -0
  588. data/sig/ibex.rbs +2 -0
  589. metadata +524 -19
  590. data/.rubocop.yml +0 -43
  591. data/CHANGELOG.md +0 -30
  592. data/Rakefile +0 -25
  593. data/Steepfile +0 -10
  594. data/docs/compat-notes.md +0 -37
  595. data/docs/lexer-coverage.md +0 -14
  596. data/docs/phase10-extensions.md +0 -27
  597. data/gemfiles/Gemfile +0 -7
  598. data/gemfiles/Gemfile.lock +0 -98
  599. data/lib/ibex/frontend/grammar.y +0 -156
  600. data/lib/ibex/runtime/parser.rb +0 -360
  601. data/lib/ibex/runtime.rb +0 -8
  602. data/sig/ibex/runtime/parser.rbs +0 -167
  603. 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[token prechigh preclow options expect start convert pragma rule].freeze #: Array[String]
8
- ASSOCIATIVITIES = %w[left right nonassoc].freeze #: Array[String]
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 parser 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 == "extended"
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] = keyword.location
33
37
  @mode = :extended
34
- seen = true
35
38
  end
36
39
  end
37
40
 
@@ -39,24 +42,77 @@ 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
61
+ when "parser" then parse_parser_configuration
48
62
  when "pragma" then fail_at(current.location, "expected rule, got pragma")
49
63
  else fail_expected("a declaration or rule")
50
64
  end
51
65
  end
52
66
 
67
+ # @rbs () -> AST::ParserConfiguration
68
+ def parse_parser_configuration
69
+ # @type self: BootstrapParser
70
+ keyword = advance
71
+ settings = [] #: Array[AST::ParserSetting]
72
+ until keyword?("end") || current.type == :eof
73
+ key = expect(:identifier)
74
+ value = expect(:identifier)
75
+ settings << build_parser_setting(key, value)
76
+ end
77
+ expect_keyword("end")
78
+ build_parser_configuration(keyword, settings)
79
+ end
80
+
81
+ # @rbs () -> AST::Include
82
+ def parse_import
83
+ # @type self: BootstrapParser
84
+ keyword = advance
85
+ extended_only!(keyword.location, "#{keyword.value}s")
86
+ path = expect(:literal)
87
+ value = token_string(path)
88
+ unless value.start_with?('"') && value.end_with?('"')
89
+ fail_at(path.location, "#{keyword.value} path must use a double-quoted string")
90
+ end
91
+
92
+ decoded = begin
93
+ value.undump
94
+ rescue RuntimeError => e
95
+ fail_at(path.location, "invalid #{keyword.value} path: #{e.message}")
96
+ end
97
+ AST::Include.new(path: decoded, loc: keyword.location)
98
+ end
99
+
53
100
  # @rbs () -> AST::Tokens
54
101
  def parse_tokens
55
102
  # @type self: BootstrapParser
56
103
  location = advance.location
57
104
  names = [] #: Array[String]
58
- names << parse_symbol_name until declaration_start?
59
- AST::Tokens.new(names: names, loc: location)
105
+ aliases = {} #: Hash[String, String]
106
+ until declaration_start?
107
+ name_token = expect_symbol
108
+ name = token_string(name_token)
109
+ names << name
110
+ next unless @mode == :extended && name_token.type == :identifier &&
111
+ current.type == :literal && current.location.line == name_token.location.line
112
+
113
+ aliases[name] = decode_quoted_literal(advance, "token alias")
114
+ end
115
+ AST::Tokens.new(names: names, aliases: aliases.empty? ? nil : aliases, loc: location)
60
116
  end
61
117
 
62
118
  # @rbs () -> AST::Precedence
@@ -77,6 +133,7 @@ module Ibex
77
133
  levels = [] #: Array[AST::PrecedenceLevel]
78
134
  until keyword?(closing) || current.type == :eof
79
135
  association = expect_one_of(ASSOCIATIVITIES)
136
+ extended_only!(association.location, "%precedence") if token_string(association) == "precedence"
80
137
  symbols = [] #: Array[String]
81
138
  symbols << parse_symbol_name until association_start? || keyword?(closing) || current.type == :eof
82
139
  fail_at(association.location, "expected at least one precedence symbol") if symbols.empty?
@@ -102,11 +159,152 @@ module Ibex
102
159
  AST::Expect.new(conflicts: token_integer(expect(:integer)), loc: location)
103
160
  end
104
161
 
162
+ # @rbs () -> AST::ExpectRR
163
+ def parse_expect_rr
164
+ # @type self: BootstrapParser
165
+ location = advance.location
166
+ extended_only!(location, "expect-rr declarations")
167
+ AST::ExpectRR.new(conflicts: token_integer(expect(:integer)), loc: location)
168
+ end
169
+
170
+ # @rbs () -> AST::Parameter
171
+ def parse_parameter
172
+ # @type self: BootstrapParser
173
+ keyword = advance
174
+ extended_only!(keyword.location, "%param")
175
+ name = expect(:identifier)
176
+ type = current.type == :literal ? advance : nil
177
+ if type && (keyword.location.line != name.location.line || name.location.line != type.location.line)
178
+ fail_at(keyword.location, "%param declaration must be written on one line")
179
+ end
180
+
181
+ semantic_type = type && decode_quoted_literal(type, "%param")
182
+ AST::Parameter.new(name: token_string(name), semantic_type: semantic_type, loc: keyword.location)
183
+ end
184
+
185
+ # @rbs () -> AST::Printer
186
+ def parse_printer
187
+ # @type self: BootstrapParser
188
+ keyword = advance
189
+ extended_only!(keyword.location, "%printer")
190
+ name = parse_symbol_name
191
+ action = expect(:action)
192
+ AST::Printer.new(name: name, code: token_string(action), loc: keyword.location)
193
+ end
194
+
105
195
  # @rbs () -> AST::Start
106
196
  def parse_start
107
197
  # @type self: BootstrapParser
108
198
  location = advance.location
109
- AST::Start.new(name: parse_symbol_name, loc: location)
199
+ names = [parse_symbol_name]
200
+ names << parse_symbol_name until declaration_start?
201
+ extended_only!(location, "multiple start symbols") if names.length > 1
202
+ AST::Start.new(names: names, loc: location)
203
+ end
204
+
205
+ # @rbs () -> AST::Recovery
206
+ def parse_recovery
207
+ # @type self: BootstrapParser
208
+ keyword = advance
209
+ extended_only!(keyword.location, "%recover")
210
+ kind = expect(:identifier)
211
+ fail_at(kind.location, "expected sync, got #{kind.value}") unless token_string(kind) == "sync"
212
+ expect(:":")
213
+ tokens = [parse_symbol_name]
214
+ tokens << parse_symbol_name until declaration_start?
215
+ AST::Recovery.new(sync_tokens: tokens, loc: keyword.location)
216
+ end
217
+
218
+ # @rbs () -> AST::OnErrorReduce
219
+ def parse_on_error_reduce
220
+ # @type self: BootstrapParser
221
+ keyword = advance
222
+ extended_only!(keyword.location, "%on_error_reduce")
223
+ names = [parse_symbol_name]
224
+ names << parse_symbol_name until declaration_start?
225
+ AST::OnErrorReduce.new(names: names, loc: keyword.location)
226
+ end
227
+
228
+ # @rbs () -> AST::GrammarTest
229
+ def parse_grammar_test
230
+ # @type self: BootstrapParser
231
+ keyword = advance
232
+ extended_only!(keyword.location, "%test")
233
+ expectation = token_string(expect(:identifier))
234
+ fail_at(keyword.location, "expected accept or reject, got #{expectation}") unless
235
+ %w[accept reject].include?(expectation)
236
+ source = expect(:literal)
237
+ literal = token_string(source)
238
+ fail_at(source.location, "%test source must use a double-quoted string") unless literal.start_with?('"')
239
+ decoded = begin
240
+ literal.undump
241
+ rescue RuntimeError => e
242
+ fail_at(source.location, "invalid %test source: #{e.message}")
243
+ end
244
+
245
+ AST::GrammarTest.new(expectation: expectation.to_sym, source: decoded, loc: keyword.location)
246
+ end
247
+
248
+ # @rbs () -> AST::Lexer
249
+ def parse_lexer
250
+ # @type self: BootstrapParser
251
+ keyword = advance
252
+ extended_only!(keyword.location, "lexer declarations")
253
+ entries = parse_lexer_entries
254
+ expect_keyword("end")
255
+ AST::Lexer.new(definitions: entries, loc: keyword.location)
256
+ end
257
+
258
+ # @rbs () -> Array[AST::lexer_entry]
259
+ def parse_lexer_entries
260
+ # @type self: BootstrapParser
261
+ entries = [] #: Array[AST::lexer_entry]
262
+ entries << parse_lexer_entry until keyword?("end") || current.type == :eof
263
+ entries
264
+ end
265
+
266
+ # @rbs () -> AST::lexer_entry
267
+ def parse_lexer_entry
268
+ # @type self: BootstrapParser
269
+ return parse_lexer_state if keyword?("state")
270
+
271
+ marker = expect(:identifier)
272
+ kind = case token_string(marker)
273
+ when "skip" then :skip
274
+ when "on" then :on
275
+ else :token
276
+ end
277
+ pattern = expect_lexer_pattern
278
+ action = current.type == :action ? advance : nil
279
+ fail_at(marker.location, "on lexer rules require an action") if kind == :on && !action
280
+ build_bootstrap_lexer_rule(kind, marker, pattern, action)
281
+ end
282
+
283
+ # @rbs () -> AST::LexerState
284
+ def parse_lexer_state
285
+ # @type self: BootstrapParser
286
+ marker = advance
287
+ name = expect(:identifier)
288
+ expect_keyword("do")
289
+ entries = parse_lexer_entries
290
+ expect_keyword("end")
291
+ AST::LexerState.new(name: token_string(name), definitions: entries, loc: marker.location)
292
+ end
293
+
294
+ # @rbs () -> Token
295
+ def expect_lexer_pattern
296
+ # @type self: BootstrapParser
297
+ return advance if %i[regexp literal].include?(current.type)
298
+
299
+ fail_expected("a regular expression or quoted literal")
300
+ end
301
+
302
+ # @rbs (Symbol kind, Token marker, Token pattern, Token? action) -> AST::LexerRule
303
+ def build_bootstrap_lexer_rule(kind, marker, pattern, action)
304
+ # @type self: BootstrapParser
305
+ token = kind == :token ? token_string(marker) : nil
306
+ AST::LexerRule.new(kind: kind, token: token, pattern: token_string(pattern),
307
+ pattern_kind: pattern.type, action: action && token_string(action), loc: marker.location)
110
308
  end
111
309
 
112
310
  # @rbs () -> AST::Convert
@@ -124,6 +322,27 @@ module Ibex
124
322
  AST::Convert.new(pairs: pairs, loc: location)
125
323
  end
126
324
 
325
+ # @rbs (singleton(AST::DisplayName) | singleton(AST::SemanticType) node_class, String feature) ->
326
+ # (AST::DisplayName | AST::SemanticType)
327
+ def parse_symbol_metadata(node_class, feature)
328
+ # @type self: BootstrapParser
329
+ keyword = advance
330
+ extended_only!(keyword.location, "#{feature} declarations")
331
+ name = expect_symbol
332
+ value = expect_metadata_value
333
+ validate_metadata_line(keyword, name, value, feature)
334
+ decoded = decode_quoted_literal(value, feature)
335
+ node_class.new(name: token_string(name), value: decoded, loc: keyword.location)
336
+ end
337
+
338
+ # @rbs () -> Token
339
+ def expect_metadata_value
340
+ # @type self: BootstrapParser
341
+ return advance if current.type == :literal
342
+
343
+ fail_expected("a quoted string")
344
+ end
345
+
127
346
  # @rbs (Integer line) -> Array[Token]
128
347
  def tokens_on_line(line)
129
348
  # @type self: BootstrapParser
@@ -147,10 +366,41 @@ module Ibex
147
366
  fail_at(location, "invalid conversion expression: #{e.message}")
148
367
  end
149
368
 
369
+ # @rbs (Token keyword, Token name, Token value, String feature) -> void
370
+ def validate_metadata_line(keyword, name, value, feature)
371
+ # @type self: BootstrapParser
372
+ return if keyword.location.line == name.location.line && name.location.line == value.location.line
373
+
374
+ fail_at(keyword.location, "#{feature} declaration must be written on one line")
375
+ end
376
+
377
+ # @rbs (Token token, String feature) -> String
378
+ def decode_quoted_literal(token, feature)
379
+ # @type self: BootstrapParser
380
+ literal = token_string(token)
381
+ decoded = if literal.start_with?('"')
382
+ literal.undump
383
+ else
384
+ (literal[1...-1] || "").gsub("\\'", "'").gsub("\\\\", "\\")
385
+ end
386
+ fail_at(token.location, "#{feature} value must not be empty") if decoded.strip.empty?
387
+ fail_at(token.location, "#{feature} value must be a single line") if decoded.match?(/[\r\n]/)
388
+ fail_at(token.location, "#{feature} value must not contain control characters") if
389
+ decoded.match?(/[[:cntrl:]]/)
390
+
391
+ decoded
392
+ rescue RuntimeError => e
393
+ fail_at(token.location, "invalid #{feature} value: #{e.message}")
394
+ end
395
+
150
396
  # @rbs () -> bool
151
397
  def declaration_start?
152
398
  # @type self: BootstrapParser
153
- current.type == :eof || (current.type == :identifier && DECLARATIONS.include?(current.value))
399
+ return true if current.type == :eof
400
+ return false unless current.type == :identifier && DECLARATIONS.include?(current.value)
401
+ return false if %w[display type param printer lexer].include?(current.value) && @mode != :extended
402
+
403
+ true
154
404
  end
155
405
 
156
406
  # @rbs () -> bool
@@ -159,5 +409,6 @@ module Ibex
159
409
  current.type == :identifier && ASSOCIATIVITIES.include?(current.value)
160
410
  end
161
411
  end
412
+ # rubocop:enable Metrics/ModuleLength, Metrics/CyclomaticComplexity
162
413
  end
163
414
  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 == :eof
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(lhs: token_string(lhs), alternatives: alternatives, loc: lhs.location)
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
- AST::Alternative.new(items: items, action: action, precedence: precedence, loc: location)
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 || keyword?("end")
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
- current.type == :identifier && lookahead.type == :":" && current.location.column <= lhs.location.column
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