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,52 +3,75 @@
3
3
  module Ibex
4
4
  # Deterministically renders frontend EBNF items for production origin metadata.
5
5
  module NormalizeExpression
6
- # @rbs!
7
- # private def render_reference: (Frontend::AST::SymbolReference item) -> String
8
- # private def self.render_reference: (Frontend::AST::SymbolReference item) -> String
9
- # private def render_group: (Frontend::AST::Group item) -> String
10
- # private def self.render_group: (Frontend::AST::Group item) -> String
11
- # private def render_separated_list: (Frontend::AST::SeparatedList item) -> String
12
- # private def self.render_separated_list: (Frontend::AST::SeparatedList item) -> String
13
-
14
- # @rbs (Frontend::AST::item item) -> String
15
- def render(item)
16
- case item
17
- when Frontend::AST::SymbolReference then render_reference(item)
18
- when Frontend::AST::Group then render_group(item)
19
- when Frontend::AST::Optional then "#{render(item.item)}?"
20
- when Frontend::AST::Star then "#{render(item.item)}*"
21
- when Frontend::AST::Plus then "#{render(item.item)}+"
22
- when Frontend::AST::SeparatedList then render_separated_list(item)
23
- else raise Ibex::Error, "#{item.loc}: cannot render unsupported EBNF expression"
6
+ # @rbs! type pending_item = String | Frontend::AST::item
7
+
8
+ class << self
9
+ # @rbs (Frontend::AST::item item) -> String
10
+ def render(item)
11
+ pending = [item] #: Array[pending_item]
12
+ output = [] #: Array[String]
13
+ until pending.empty?
14
+ current = pending.pop || raise(ArgumentError, "expression stack unexpectedly empty")
15
+ if current.is_a?(String)
16
+ output << current
17
+ next
18
+ end
19
+
20
+ push_render_item(pending, current)
21
+ end
22
+ output.join
24
23
  end
25
- end
26
- module_function :render
27
24
 
28
- # @rbs skip
29
- private
25
+ private
30
26
 
31
- # @rbs skip
32
- def render_reference(item)
33
- suffix = item.named_reference ? ":#{item.named_reference}" : ""
34
- "#{item.name}#{suffix}"
35
- end
27
+ # @rbs (Array[pending_item] pending, Frontend::AST::item item) -> void
28
+ def push_render_item(pending, item)
29
+ case item
30
+ when Frontend::AST::SymbolReference
31
+ pending << "#{item.name}#{":#{item.named_reference}" if item.named_reference}"
32
+ when Frontend::AST::ParameterizedReference
33
+ push_render_parameterized_reference(pending, item)
34
+ when Frontend::AST::Group
35
+ push_render_group(pending, item)
36
+ when Frontend::AST::Optional
37
+ pending.push("?", item.item)
38
+ when Frontend::AST::Star
39
+ pending.push("*", item.item)
40
+ when Frontend::AST::Plus
41
+ pending.push("+", item.item)
42
+ when Frontend::AST::SeparatedList
43
+ name = item.nonempty ? "separated_nonempty_list" : "separated_list"
44
+ pending.push(")", item.separator, ", ", item.item, "(", name)
45
+ else
46
+ raise Ibex::Error, "#{item.loc}: cannot render unsupported EBNF expression"
47
+ end
48
+ end
36
49
 
37
- # @rbs skip
38
- def render_group(item)
39
- alternatives = item.alternatives.map { |items| items.map { |child| render(child) }.join(" ") }
40
- "(#{alternatives.join(' | ')})"
41
- end
50
+ # @rbs (Array[pending_item] pending, Frontend::AST::ParameterizedReference item) -> void
51
+ def push_render_parameterized_reference(pending, item)
52
+ pending << ":#{item.named_reference}" if item.named_reference
53
+ pending << ")"
54
+ push_render_items(pending, item.arguments, ", ")
55
+ pending.push("(", item.name)
56
+ end
42
57
 
43
- # @rbs skip
44
- def render_separated_list(item)
45
- name = item.nonempty ? "separated_nonempty_list" : "separated_list"
46
- "#{name}(#{render(item.item)}, #{render(item.separator)})"
47
- end
48
- module_function :render_reference, :render_group, :render_separated_list
58
+ # @rbs (Array[pending_item] pending, Frontend::AST::Group item) -> void
59
+ def push_render_group(pending, item)
60
+ pending << ")"
61
+ (item.alternatives.length - 1).downto(0) do |index|
62
+ pending << " | " if index < item.alternatives.length - 1
63
+ push_render_items(pending, item.alternatives.fetch(index), " ")
64
+ end
65
+ pending << "("
66
+ end
49
67
 
50
- class << self
51
- private :render_reference, :render_group, :render_separated_list
68
+ # @rbs (Array[pending_item] pending, Array[Frontend::AST::item] items, String separator) -> void
69
+ def push_render_items(pending, items, separator)
70
+ (items.length - 1).downto(0) do |index|
71
+ pending << separator if index < items.length - 1
72
+ pending << items.fetch(index)
73
+ end
74
+ end
52
75
  end
53
76
  end
54
77
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibex
4
+ # Builds the single current Grammar IR format for every normalized source.
5
+ module NormalizeGrammarBuilder
6
+ private
7
+
8
+ # @rbs (IR::ParserContract? parser_contract) -> IR::Grammar
9
+ def build_grammar(parser_contract)
10
+ # @type self: Normalizer
11
+ keywords = {
12
+ class_name: @ast.class_name, superclass: @ast.superclass, start: @start_name,
13
+ expect: @expected_conflicts, options: @options, symbols: @symbols,
14
+ mode: @mode, starts: @start_names, expect_rr: @expected_rr_conflicts,
15
+ parser_parameters: @parser_parameters, value_printers: @value_printers.values,
16
+ grammar_tests: @grammar_tests, lexer: normalize_lexer,
17
+ recovery: { sync_tokens: @recovery_sync_tokens, on_error_reduce: @on_error_reduce_groups },
18
+ productions: @productions, user_code: normalized_user_code,
19
+ conversions: @conversions, warnings: @warnings, user_code_chunks: normalized_user_code_chunks,
20
+ source_provenance: { file: @ast.loc.file, root: @resolution&.root_directory, byte_span: nil }
21
+ } #: { class_name: String, superclass: String?, start: String, expect: Integer, options: IR::grammar_options, symbols: Array[IR::GrammarSymbol], productions: Array[IR::Production], user_code: Hash[String, String], conversions: Hash[String, String], warnings: Array[IR::grammar_warning] } # rubocop:disable Layout/LineLength -- inline Steep shape mirrors the normalized builder contract.
22
+
23
+ IR::Grammar.new(**keywords, parser_contract: parser_contract || IR::ParserContract.new) # steep:ignore Ruby::InsufficientKeywordArguments
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,465 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ module Ibex
5
+ # Deterministically substitutes inline-rule productions before LR construction.
6
+ # rubocop:disable Metrics/ModuleLength -- expansion, action plans, and id remapping share one invariant.
7
+ module NormalizeInlineExpansion
8
+ # @rbs!
9
+ # type inline_reference = [:physical | :step, Integer]
10
+ # type inline_step = {
11
+ # kind: :inline | :rule,
12
+ # rule: String?,
13
+ # code: String?,
14
+ # loc: IR::location,
15
+ # named_refs: Array[IR::named_ref],
16
+ # context_length: Integer,
17
+ # inputs: Array[inline_reference],
18
+ # stack_inputs: Array[inline_reference],
19
+ # lookahead: Integer,
20
+ # result_var: bool,
21
+ # result_type: String?
22
+ # }
23
+ # type inline_variant = {
24
+ # rhs: Array[Integer],
25
+ # steps: Array[inline_step],
26
+ # logical_refs: Array[inline_reference],
27
+ # output_ref: inline_reference?,
28
+ # inline_used: bool,
29
+ # inline_rule: String?,
30
+ # precedence_override: Integer?,
31
+ # precedence_contributes: bool,
32
+ # parameter: IR::parameter_expansion?
33
+ # }
34
+ # type inline_frame = {
35
+ # production: IR::Production,
36
+ # symbol_id: Integer?,
37
+ # index: Integer,
38
+ # variant: inline_variant
39
+ # }
40
+
41
+ private
42
+
43
+ # @rbs () -> void
44
+ def expand_inline_rules
45
+ # @type self: Normalizer
46
+ return if @inline_symbol_ids.empty?
47
+
48
+ definitions = @productions.group_by(&:lhs)
49
+ expanded = [] #: Array[IR::Production]
50
+ @productions.each do |production|
51
+ next if @inline_symbol_ids.include?(production.lhs)
52
+
53
+ variants = expand_inline_production(production, definitions)
54
+ variants.each do |variant|
55
+ if variant[:inline_used]
56
+ charge_inline_expansion!(production)
57
+ expanded << composed_inline_production(production, variant, expanded.length)
58
+ else
59
+ expanded << copy_inline_production(production, expanded.length)
60
+ end
61
+ end
62
+ end
63
+ rebuild_inline_symbols(expanded)
64
+ end
65
+
66
+ # Explicit heap frames avoid tying grammar depth to the Ruby call stack.
67
+ # The single-definition path reuses its accumulated arrays, so a long
68
+ # acyclic chain remains linear in the size of its final action plan.
69
+ # @rbs (IR::Production production, Hash[Integer, Array[IR::Production]] definitions) ->
70
+ # Array[inline_variant]
71
+ def expand_inline_production(production, definitions)
72
+ # @type self: Normalizer
73
+ variants = [] #: Array[inline_variant]
74
+ worklist = [[inline_expansion_frame(production, nil)]] #: Array[Array[inline_frame]]
75
+ until worklist.empty?
76
+ frames = worklist.pop || raise(Ibex::Error, "internal inline expansion worklist underflow")
77
+ location = production.origin[:loc] #: IR::location?
78
+ drain_inline_expansion_frames(frames, definitions, worklist, variants, location)
79
+ end
80
+ variants
81
+ end
82
+
83
+ # @rbs (Array[inline_frame] frames, Hash[Integer, Array[IR::Production]] definitions,
84
+ # Array[Array[inline_frame]] worklist, Array[inline_variant] variants,
85
+ # IR::location? location) -> void
86
+ def drain_inline_expansion_frames(frames, definitions, worklist, variants, location)
87
+ loop do
88
+ frame = frames.fetch(-1)
89
+ current = frame.fetch(:production)
90
+ if frame.fetch(:index) < current.rhs.length
91
+ return if advance_inline_expansion_frame?(frames, definitions, worklist, variants, location)
92
+ elsif complete_inline_expansion_frame?(frames, variants, worklist, location)
93
+ return
94
+ end
95
+ end
96
+ end
97
+
98
+ # @rbs (Array[inline_frame] frames, Hash[Integer, Array[IR::Production]] definitions,
99
+ # Array[Array[inline_frame]] worklist, Array[inline_variant] variants,
100
+ # IR::location? location) -> bool
101
+ def advance_inline_expansion_frame?(frames, definitions, worklist, variants, location)
102
+ frame = frames.fetch(-1)
103
+ current = frame.fetch(:production)
104
+ index = frame.fetch(:index)
105
+ symbol_id = current.rhs.fetch(index)
106
+ frame[:index] = index + 1
107
+ unless @inline_symbol_ids.include?(symbol_id)
108
+ frame[:variant] = append_inline_symbol(frame.fetch(:variant), symbol_id)
109
+ return false
110
+ end
111
+
112
+ choices = definitions.fetch(symbol_id)
113
+ if choices.one?
114
+ frames << inline_expansion_frame(choices.fetch(0), symbol_id)
115
+ return false
116
+ end
117
+
118
+ schedule_inline_choice_branches(frames, choices, symbol_id, worklist)
119
+ enforce_inline_choice_limit!(variants.length + worklist.length, location)
120
+ true
121
+ end
122
+
123
+ # @rbs (Array[inline_frame] frames, Array[IR::Production] choices, Integer symbol_id,
124
+ # Array[Array[inline_frame]] worklist) -> void
125
+ def schedule_inline_choice_branches(frames, choices, symbol_id, worklist)
126
+ choices.reverse_each do |choice|
127
+ branch = clone_inline_expansion_frames(frames)
128
+ branch << inline_expansion_frame(choice, symbol_id)
129
+ worklist << branch
130
+ end
131
+ end
132
+
133
+ # @rbs (Array[inline_frame] frames, Array[inline_variant] variants,
134
+ # Array[Array[inline_frame]] worklist, IR::location? location) -> bool
135
+ def complete_inline_expansion_frame?(frames, variants, worklist, location)
136
+ frame = frames.fetch(-1)
137
+ current = frame.fetch(:production)
138
+ completed = finish_inline_precedence(frame.fetch(:variant), current)
139
+ frames.pop
140
+ if frames.empty?
141
+ variants << completed
142
+ enforce_inline_choice_limit!(variants.length + worklist.length, location)
143
+ return true
144
+ end
145
+
146
+ symbol_id = frame.fetch(:symbol_id) || raise(Ibex::Error, "inline expansion frame is missing its symbol")
147
+ choice = finish_inline_choice(completed, current, symbol_id)
148
+ parent = frames.fetch(-1)
149
+ parent[:variant] = combine_inline_variant(parent.fetch(:variant), choice)
150
+ false
151
+ end
152
+
153
+ # @rbs (IR::Production production, Integer? symbol_id) -> inline_frame
154
+ def inline_expansion_frame(production, symbol_id)
155
+ { production: production, symbol_id: symbol_id, index: 0, variant: empty_inline_variant(production) }
156
+ end
157
+
158
+ # @rbs (Array[inline_frame] frames) -> Array[inline_frame]
159
+ def clone_inline_expansion_frames(frames)
160
+ frames.map do |frame|
161
+ variant = frame.fetch(:variant)
162
+ cloned = frame.merge(
163
+ variant: variant.merge(
164
+ rhs: variant.fetch(:rhs).dup,
165
+ steps: variant.fetch(:steps).dup,
166
+ logical_refs: variant.fetch(:logical_refs).dup
167
+ )
168
+ )
169
+ cloned #: inline_frame
170
+ end
171
+ end
172
+
173
+ # @rbs (IR::Production production) -> inline_variant
174
+ def empty_inline_variant(production)
175
+ {
176
+ rhs: [],
177
+ steps: [],
178
+ logical_refs: [],
179
+ output_ref: nil,
180
+ inline_used: false,
181
+ inline_rule: nil,
182
+ precedence_override: nil,
183
+ precedence_contributes: false,
184
+ parameter: production.expansion&.dig(:parameter)
185
+ }
186
+ end
187
+
188
+ # @rbs (inline_variant variant, Integer symbol_id) -> inline_variant
189
+ def append_inline_symbol(variant, symbol_id)
190
+ # @type self: Normalizer
191
+ rhs = variant.fetch(:rhs)
192
+ terminal = @symbols.fetch(symbol_id).terminal?
193
+ reference = [:physical, rhs.length] #: inline_reference
194
+ logical_refs = variant.fetch(:logical_refs) + [reference] #: Array[inline_reference]
195
+ variant.merge(
196
+ rhs: rhs + [symbol_id],
197
+ logical_refs: logical_refs,
198
+ precedence_override: terminal ? nil : variant[:precedence_override],
199
+ precedence_contributes: terminal || variant.fetch(:precedence_contributes)
200
+ ) #: inline_variant
201
+ end
202
+
203
+ # @rbs (inline_variant parent, inline_variant child) -> inline_variant
204
+ def combine_inline_variant(parent, child)
205
+ physical_offset = parent.fetch(:rhs).length
206
+ step_offset = parent.fetch(:steps).length
207
+ steps = combined_inline_steps(parent, child, physical_offset, step_offset)
208
+ output_ref = child.fetch(:output_ref) || raise(Ibex::Error, "inline choice has no output reference")
209
+ rhs = append_inline_array(parent.fetch(:rhs), child.fetch(:rhs)) #: Array[Integer]
210
+ combined_steps = append_inline_array(parent.fetch(:steps), steps) #: Array[inline_step]
211
+ logical_refs = parent.fetch(:logical_refs) + [
212
+ remap_inline_reference(output_ref, physical_offset, step_offset)
213
+ ] #: Array[inline_reference]
214
+ parent.merge(
215
+ rhs: rhs,
216
+ steps: combined_steps,
217
+ logical_refs: logical_refs,
218
+ inline_used: true,
219
+ inline_rule: parent[:inline_rule] || child[:inline_rule],
220
+ precedence_override: combined_inline_precedence(parent, child),
221
+ precedence_contributes: parent.fetch(:precedence_contributes) ||
222
+ child.fetch(:precedence_contributes),
223
+ parameter: parent[:parameter] || child[:parameter]
224
+ ) #: inline_variant
225
+ end
226
+
227
+ # @rbs (inline_variant parent, inline_variant child,
228
+ # Integer physical_offset, Integer step_offset) -> Array[inline_step]
229
+ def combined_inline_steps(parent, child, physical_offset, step_offset)
230
+ return child.fetch(:steps) if physical_offset.zero? && step_offset.zero? && parent.fetch(:logical_refs).empty?
231
+
232
+ remap_inline_steps(parent, child, physical_offset, step_offset)
233
+ end
234
+
235
+ # The helper is shared by homogeneous integer and step arrays; callers
236
+ # assert the concrete element type at each use site.
237
+ # @rbs (Array[Object?] left, Array[Object?] right) -> Array[Object?]
238
+ def append_inline_array(left, right)
239
+ left.empty? ? right : left + right
240
+ end
241
+
242
+ # @rbs (inline_variant parent, inline_variant child) -> Integer?
243
+ def combined_inline_precedence(parent, child)
244
+ return child[:precedence_override] if child.fetch(:precedence_contributes)
245
+
246
+ parent[:precedence_override]
247
+ end
248
+
249
+ # @rbs (inline_variant parent, inline_variant child,
250
+ # Integer physical_offset, Integer step_offset) -> Array[inline_step]
251
+ def remap_inline_steps(parent, child, physical_offset, step_offset)
252
+ child.fetch(:steps).map do |step|
253
+ inputs = step.fetch(:inputs).map do |reference|
254
+ remap_inline_reference(reference, physical_offset, step_offset)
255
+ end
256
+ stack_inputs = step.fetch(:stack_inputs).map do |reference|
257
+ remap_inline_reference(reference, physical_offset, step_offset)
258
+ end
259
+ remapped = step.merge(
260
+ inputs: inputs,
261
+ stack_inputs: parent.fetch(:logical_refs) + stack_inputs,
262
+ lookahead: step.fetch(:lookahead) + physical_offset
263
+ )
264
+ remapped #: inline_step
265
+ end
266
+ end
267
+
268
+ # @rbs (Array[Symbol | Integer] reference, Integer physical_offset, Integer step_offset) ->
269
+ # Array[Symbol | Integer]
270
+ def remap_inline_reference(reference, physical_offset, step_offset)
271
+ kind, index = reference
272
+ raise Ibex::Error, "invalid inline slot kind" unless kind.is_a?(Symbol)
273
+ raise Ibex::Error, "invalid inline slot reference" unless index.is_a?(Integer)
274
+
275
+ [kind, index + (kind == :physical ? physical_offset : step_offset)]
276
+ end
277
+
278
+ # @rbs (inline_variant variant, IR::Production production) -> inline_variant
279
+ def finish_inline_precedence(variant, production)
280
+ explicit = production.precedence_override
281
+ variant.merge(
282
+ precedence_override: explicit || variant[:precedence_override],
283
+ precedence_contributes: !explicit.nil? || variant.fetch(:precedence_contributes)
284
+ ) #: inline_variant
285
+ end
286
+
287
+ # @rbs (inline_variant variant, IR::Production production, Integer symbol_id) -> inline_variant
288
+ def finish_inline_choice(variant, production, symbol_id)
289
+ steps = variant.fetch(:steps)
290
+ rule = @inline_rule_by_symbol.fetch(symbol_id)
291
+ step = inline_action_step(production, variant.fetch(:logical_refs), variant.fetch(:rhs).length, :inline, rule)
292
+ steps << step
293
+ variant.merge(
294
+ steps: steps,
295
+ output_ref: [:step, steps.length - 1],
296
+ inline_used: true,
297
+ inline_rule: rule
298
+ ) #: inline_variant
299
+ end
300
+
301
+ # @rbs (IR::Production production, Array[inline_reference] inputs, Integer lookahead,
302
+ # :inline | :rule kind, String? rule) -> inline_step
303
+ def inline_action_step(production, inputs, lookahead, kind, rule)
304
+ action = production.action
305
+ location = action&.location || production.origin.fetch(:loc)
306
+ typed_location = location #: IR::location
307
+ {
308
+ kind: kind,
309
+ rule: rule,
310
+ code: action&.code,
311
+ loc: typed_location,
312
+ named_refs: action&.named_refs || [],
313
+ context_length: action&.context_length || 0,
314
+ inputs: inputs,
315
+ stack_inputs: [],
316
+ lookahead: lookahead,
317
+ result_var: @options.fetch(:result_var),
318
+ result_type: @symbols.fetch(production.lhs).semantic_type
319
+ }
320
+ end
321
+
322
+ # @rbs (IR::Production production, inline_variant variant, Integer id) -> IR::Production
323
+ def composed_inline_production(production, variant, id)
324
+ steps = variant.fetch(:steps)
325
+ caller = inline_action_step(
326
+ production, variant.fetch(:logical_refs), variant.fetch(:rhs).length, :rule, nil
327
+ )
328
+ all_steps = steps + [caller]
329
+ action = composed_inline_action(production, variant.fetch(:rhs).length, all_steps)
330
+ IR::Production.new(
331
+ id: id, lhs: production.lhs, rhs: variant.fetch(:rhs), action: action,
332
+ precedence_override: variant[:precedence_override], origin: production.origin,
333
+ documentation: production.documentation,
334
+ expansion: inline_production_expansion(production, variant)
335
+ )
336
+ end
337
+
338
+ # @rbs (IR::Production production, Integer physical_length, Array[inline_step]) -> IR::Action
339
+ def composed_inline_action(production, physical_length, steps)
340
+ action = production.action
341
+ location = action&.location || production.origin.fetch(:loc)
342
+ typed_location = location #: IR::location
343
+ fragments = steps.map do |step|
344
+ { kind: step.fetch(:kind), source: inline_source_provenance(step.fetch(:loc)) }
345
+ end
346
+ plan_steps = steps.map { |step| composition_plan_step(step, physical_length) }
347
+ composition = {
348
+ strategy: "sequence",
349
+ fragments: fragments,
350
+ plan: { version: 1, physical: physical_length, steps: plan_steps }
351
+ } #: IR::action_composition
352
+ IR::Action.new(
353
+ code: action&.code || inline_implicit_code(production.rhs.length),
354
+ location: typed_location,
355
+ composition: composition
356
+ )
357
+ end
358
+
359
+ # @rbs (inline_step step, Integer physical_length) -> IR::action_composition_step
360
+ def composition_plan_step(step, physical_length)
361
+ {
362
+ kind: step.fetch(:kind),
363
+ rule: step[:rule],
364
+ code: step[:code],
365
+ loc: step.fetch(:loc),
366
+ named_refs: step.fetch(:named_refs),
367
+ context_length: step.fetch(:context_length),
368
+ inputs: step.fetch(:inputs).map { |reference| resolve_inline_reference(reference, physical_length) },
369
+ stack_inputs: step.fetch(:stack_inputs).map do |reference|
370
+ resolve_inline_reference(reference, physical_length)
371
+ end,
372
+ lookahead: step.fetch(:lookahead) < physical_length ? step.fetch(:lookahead) : nil,
373
+ result_var: step.fetch(:result_var),
374
+ result_type: step[:result_type]
375
+ }
376
+ end
377
+
378
+ # @rbs (Array[Symbol | Integer] reference, Integer physical_length) -> Integer
379
+ def resolve_inline_reference(reference, physical_length)
380
+ kind, index = reference
381
+ raise Ibex::Error, "invalid inline slot reference" unless index.is_a?(Integer)
382
+
383
+ index + (kind == :step ? physical_length : 0)
384
+ end
385
+
386
+ # @rbs (Integer rhs_length) -> String
387
+ def inline_implicit_code(rhs_length)
388
+ expression = rhs_length.zero? ? "nil" : "val[0]"
389
+ @options.fetch(:result_var) ? " result = #{expression} " : " #{expression} "
390
+ end
391
+
392
+ # @rbs (IR::location location) -> IR::source_provenance
393
+ def inline_source_provenance(location)
394
+ { file: location[:file], root: @resolution&.root_directory, byte_span: nil }
395
+ end
396
+
397
+ # @rbs (IR::Production production, inline_variant variant) -> IR::production_expansion
398
+ def inline_production_expansion(production, variant)
399
+ existing = production.expansion
400
+ inline_rule = variant.fetch(:inline_rule) || raise(Ibex::Error, "inline expansion has no rule")
401
+ {
402
+ parameter: existing&.dig(:parameter) || variant[:parameter],
403
+ inline: { rule: inline_rule },
404
+ include_chain: existing&.dig(:include_chain) || []
405
+ }
406
+ end
407
+
408
+ # @rbs (IR::Production production, Integer id) -> IR::Production
409
+ def copy_inline_production(production, id)
410
+ IR::Production.new(
411
+ id: id, lhs: production.lhs, rhs: production.rhs, action: production.action,
412
+ precedence_override: production.precedence_override, origin: production.origin,
413
+ documentation: production.documentation, expansion: production.expansion
414
+ )
415
+ end
416
+
417
+ # @rbs (IR::Production production) -> void
418
+ def charge_inline_expansion!(production)
419
+ @inline_expansion_count += 1
420
+ location = production.origin[:loc] #: IR::location?
421
+ enforce_inline_choice_limit!(@inline_expansion_count, location)
422
+ end
423
+
424
+ # @rbs (Integer count, IR::location? location) -> void
425
+ def enforce_inline_choice_limit!(count, location)
426
+ # @type self: Normalizer
427
+ return if count <= @max_inline_expansions
428
+
429
+ fail_hash(location, "inline expansion limit of #{@max_inline_expansions} exceeded")
430
+ end
431
+
432
+ # @rbs (Array[IR::Production] productions) -> void
433
+ def rebuild_inline_symbols(productions)
434
+ kept = @symbols.reject { |definition| @inline_symbol_ids.include?(definition.id) }
435
+ id_map = kept.each_with_index.to_h { |definition, id| [definition.id, id] }
436
+ @symbols = kept.each_with_index.map { |definition, id| remap_inline_symbol(definition, id) }
437
+ @symbols_by_name = @symbols.to_h { |definition| [definition.name, definition] }
438
+ @productions = productions.each_with_index.map do |production, id|
439
+ remap_inline_production(production, id, id_map)
440
+ end
441
+ end
442
+
443
+ # @rbs (IR::GrammarSymbol definition, Integer id) -> IR::GrammarSymbol
444
+ def remap_inline_symbol(definition, id)
445
+ IR::GrammarSymbol.new(
446
+ id: id, name: definition.name, kind: definition.kind, reserved: definition.reserved,
447
+ precedence: definition.precedence, location: definition.location,
448
+ display_name: definition.display_name, semantic_type: definition.semantic_type,
449
+ documentation: definition.documentation
450
+ )
451
+ end
452
+
453
+ # @rbs (IR::Production production, Integer id, Hash[Integer, Integer] id_map) -> IR::Production
454
+ def remap_inline_production(production, id, id_map)
455
+ IR::Production.new(
456
+ id: id, lhs: id_map.fetch(production.lhs),
457
+ rhs: production.rhs.map { |symbol_id| id_map.fetch(symbol_id) },
458
+ action: production.action,
459
+ precedence_override: production.precedence_override && id_map.fetch(production.precedence_override),
460
+ origin: production.origin, documentation: production.documentation, expansion: production.expansion
461
+ )
462
+ end
463
+ end
464
+ # rubocop:enable Metrics/ModuleLength
465
+ end