ibex 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (384) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +247 -104
  3. data/docs/architecture.md +322 -28
  4. data/docs/cst-migration.md +107 -0
  5. data/docs/cst.md +213 -0
  6. data/docs/development.md +129 -0
  7. data/docs/editor-setup.md +25 -0
  8. data/docs/error-ux.md +60 -0
  9. data/docs/grammar-reference.md +458 -18
  10. data/docs/lexer-migration.md +51 -0
  11. data/docs/racc-migration.md +34 -6
  12. data/docs/release-readiness.md +163 -0
  13. data/docs/stability.md +124 -0
  14. data/examples/README.md +60 -0
  15. data/examples/calculator.y +44 -0
  16. data/examples/csv.y +32 -0
  17. data/examples/ini.y +70 -0
  18. data/examples/json.y +48 -0
  19. data/examples/tiny_language.y +75 -0
  20. data/lib/ibex/analysis/sets.rb +5 -4
  21. data/lib/ibex/artifact_set.rb +63 -0
  22. data/lib/ibex/cli/ambiguity.rb +66 -0
  23. data/lib/ibex/cli/counterexample_options.rb +6 -2
  24. data/lib/ibex/cli/coverage.rb +173 -0
  25. data/lib/ibex/cli/debug.rb +106 -0
  26. data/lib/ibex/cli/diagnostics.rb +116 -0
  27. data/lib/ibex/cli/documentation.rb +67 -0
  28. data/lib/ibex/cli/error_messages.rb +177 -0
  29. data/lib/ibex/cli/explain.rb +76 -0
  30. data/lib/ibex/cli/formatting.rb +386 -0
  31. data/lib/ibex/cli/generation_artifacts.rb +138 -0
  32. data/lib/ibex/cli/generation_error_messages.rb +39 -0
  33. data/lib/ibex/cli/grammar_tests.rb +122 -0
  34. data/lib/ibex/cli/ir_tools.rb +184 -0
  35. data/lib/ibex/cli/lsp.rb +33 -0
  36. data/lib/ibex/cli/outputs.rb +91 -8
  37. data/lib/ibex/cli/racc_migration.rb +87 -0
  38. data/lib/ibex/cli/samples.rb +92 -0
  39. data/lib/ibex/cli/watch.rb +103 -0
  40. data/lib/ibex/cli.rb +506 -37
  41. data/lib/ibex/codegen/action_locations.rb +103 -0
  42. data/lib/ibex/codegen/action_method_source.rb +210 -0
  43. data/lib/ibex/codegen/action_source.rb +118 -0
  44. data/lib/ibex/codegen/ambiguity.rb +173 -0
  45. data/lib/ibex/codegen/cst_metadata.rb +171 -0
  46. data/lib/ibex/codegen/documentation.rb +170 -0
  47. data/lib/ibex/codegen/explain.rb +312 -0
  48. data/lib/ibex/codegen/generated_action_abi.rb +288 -0
  49. data/lib/ibex/codegen/html.rb +94 -10
  50. data/lib/ibex/codegen/mermaid.rb +43 -0
  51. data/lib/ibex/codegen/railroad.rb +197 -0
  52. data/lib/ibex/codegen/railroad_documentation.rb +59 -0
  53. data/lib/ibex/codegen/rbs.rb +323 -2
  54. data/lib/ibex/codegen/report.rb +46 -6
  55. data/lib/ibex/codegen/ruby.rb +334 -59
  56. data/lib/ibex/codegen/ruby_actions.rb +143 -0
  57. data/lib/ibex/codegen/ruby_ast.rb +121 -0
  58. data/lib/ibex/codegen/ruby_error_messages.rb +28 -0
  59. data/lib/ibex/codegen/ruby_lexer.rb +83 -0
  60. data/lib/ibex/codegen/ruby_syntax.rb +90 -0
  61. data/lib/ibex/codegen/ruby_table_metadata.rb +57 -0
  62. data/lib/ibex/codegen/ruby_value_printers.rb +56 -0
  63. data/lib/ibex/codegen/symbol_labels.rb +1 -1
  64. data/lib/ibex/coverage/collector.rb +188 -0
  65. data/lib/ibex/coverage/event_stream.rb +97 -0
  66. data/lib/ibex/coverage/report.rb +259 -0
  67. data/lib/ibex/coverage/runtime_event_validator.rb +160 -0
  68. data/lib/ibex/coverage.rb +13 -0
  69. data/lib/ibex/error_messages/parser.rb +159 -0
  70. data/lib/ibex/error_messages/parser_v2.rb +198 -0
  71. data/lib/ibex/error_messages/renderer.rb +65 -0
  72. data/lib/ibex/error_messages/sentence_search.rb +196 -0
  73. data/lib/ibex/error_messages/update.rb +169 -0
  74. data/lib/ibex/error_messages.rb +165 -0
  75. data/lib/ibex/frontend/ast.rb +145 -6
  76. data/lib/ibex/frontend/bootstrap_parser.rb +47 -4
  77. data/lib/ibex/frontend/diagnostic.rb +81 -0
  78. data/lib/ibex/frontend/diagnostic_recovery.rb +268 -0
  79. data/lib/ibex/frontend/dsl.rb +66 -7
  80. data/lib/ibex/frontend/formatter.rb +407 -0
  81. data/lib/ibex/frontend/generated_parser.rb +614 -190
  82. data/lib/ibex/frontend/generated_parser_base.rb +164 -30
  83. data/lib/ibex/frontend/generated_parser_includes.rb +61 -0
  84. data/lib/ibex/frontend/generated_parser_metadata.rb +61 -0
  85. data/lib/ibex/frontend/generated_parser_parameters.rb +60 -0
  86. data/lib/ibex/frontend/generation.rb +33 -0
  87. data/lib/ibex/frontend/lexer.rb +162 -10
  88. data/lib/ibex/frontend/lexer_recovery.rb +84 -0
  89. data/lib/ibex/frontend/parser/declarations.rb +247 -11
  90. data/lib/ibex/frontend/parser/parameters.rb +82 -0
  91. data/lib/ibex/frontend/parser/rules.rb +43 -6
  92. data/lib/ibex/frontend/parser.rb +182 -4
  93. data/lib/ibex/frontend/regenerator.rb +26 -1
  94. data/lib/ibex/frontend/resolution.rb +69 -0
  95. data/lib/ibex/frontend/resolver.rb +217 -0
  96. data/lib/ibex/frontend/rule_documentation.rb +103 -0
  97. data/lib/ibex/frontend/source_cursor.rb +132 -8
  98. data/lib/ibex/frontend/source_document.rb +229 -0
  99. data/lib/ibex/frontend/source_loader.rb +150 -0
  100. data/lib/ibex/frontend/source_span.rb +81 -0
  101. data/lib/ibex/frontend/token_adapter/declaration_document_state.rb +47 -0
  102. data/lib/ibex/frontend/token_adapter/declaration_lexer_state.rb +83 -0
  103. data/lib/ibex/frontend/token_adapter/declaration_state.rb +216 -26
  104. data/lib/ibex/frontend/token_adapter/delimiter_tracker.rb +8 -2
  105. data/lib/ibex/frontend/token_adapter/rule_state.rb +60 -2
  106. data/lib/ibex/frontend/token_adapter.rb +8 -3
  107. data/lib/ibex/frontend.rb +13 -2
  108. data/lib/ibex/generation_input.rb +57 -0
  109. data/lib/ibex/generation_manifest.rb +200 -0
  110. data/lib/ibex/generation_transaction.rb +261 -0
  111. data/lib/ibex/generation_transaction_recovery.rb +109 -0
  112. data/lib/ibex/generation_transaction_validation.rb +196 -0
  113. data/lib/ibex/grammar_tests.rb +206 -0
  114. data/lib/ibex/ir/automaton_ir.rb +38 -5
  115. data/lib/ibex/ir/grammar_ir.rb +137 -24
  116. data/lib/ibex/ir/lexer_ir.rb +76 -0
  117. data/lib/ibex/ir/migration.rb +120 -0
  118. data/lib/ibex/ir/serialize.rb +110 -19
  119. data/lib/ibex/ir/validator/automaton.rb +345 -0
  120. data/lib/ibex/ir/validator/base.rb +129 -0
  121. data/lib/ibex/ir/validator/grammar.rb +604 -0
  122. data/lib/ibex/ir/validator/lexer.rb +113 -0
  123. data/lib/ibex/ir/validator.rb +62 -0
  124. data/lib/ibex/ir.rb +57 -4
  125. data/lib/ibex/lalr/build_metrics.rb +23 -0
  126. data/lib/ibex/lalr/builder.rb +379 -52
  127. data/lib/ibex/lalr/conflict.rb +1 -0
  128. data/lib/ibex/lalr/conflict_search.rb +11 -5
  129. data/lib/ibex/lalr/counterexample.rb +20 -5
  130. data/lib/ibex/lalr/direct_lookaheads.rb +236 -0
  131. data/lib/ibex/lalr/ielr_partition.rb +152 -0
  132. data/lib/ibex/lalr/on_error_reductions.rb +74 -0
  133. data/lib/ibex/lalr.rb +7 -0
  134. data/lib/ibex/location.rb +129 -0
  135. data/lib/ibex/lsp/document_handlers.rb +66 -0
  136. data/lib/ibex/lsp/document_store.rb +264 -0
  137. data/lib/ibex/lsp/document_store_diagnostics.rb +44 -0
  138. data/lib/ibex/lsp/document_store_validation.rb +61 -0
  139. data/lib/ibex/lsp/initialization_handlers.rb +78 -0
  140. data/lib/ibex/lsp/navigation_handlers.rb +56 -0
  141. data/lib/ibex/lsp/position_codec.rb +109 -0
  142. data/lib/ibex/lsp/protocol_error.rb +33 -0
  143. data/lib/ibex/lsp/request_handlers.rb +45 -0
  144. data/lib/ibex/lsp/request_support.rb +87 -0
  145. data/lib/ibex/lsp/server.rb +146 -0
  146. data/lib/ibex/lsp/symbol_index.rb +241 -0
  147. data/lib/ibex/lsp/symbol_index_builder.rb +267 -0
  148. data/lib/ibex/lsp/symbol_index_precedence_references.rb +44 -0
  149. data/lib/ibex/lsp/symbol_index_source_queries.rb +61 -0
  150. data/lib/ibex/lsp/symbol_occurrence.rb +17 -0
  151. data/lib/ibex/lsp/transport.rb +118 -0
  152. data/lib/ibex/lsp/workspace.rb +127 -0
  153. data/lib/ibex/lsp/workspace_analyzer.rb +199 -0
  154. data/lib/ibex/lsp.rb +32 -0
  155. data/lib/ibex/normalize/declarations.rb +140 -7
  156. data/lib/ibex/normalize/diagnostics.rb +50 -5
  157. data/lib/ibex/normalize/expander.rb +59 -55
  158. data/lib/ibex/normalize/expression.rb +60 -39
  159. data/lib/ibex/normalize/inline_expansion.rb +414 -0
  160. data/lib/ibex/normalize/inline_validation.rb +174 -0
  161. data/lib/ibex/normalize/lexer.rb +131 -0
  162. data/lib/ibex/normalize/named_references.rb +60 -0
  163. data/lib/ibex/normalize/nodes.rb +46 -0
  164. data/lib/ibex/normalize/parameter_ebnf_lowering.rb +69 -0
  165. data/lib/ibex/normalize/parameter_lowering.rb +126 -0
  166. data/lib/ibex/normalize/parameter_substitution.rb +125 -0
  167. data/lib/ibex/normalize/parameter_validation.rb +140 -0
  168. data/lib/ibex/normalize/parameters.rb +199 -0
  169. data/lib/ibex/normalize/recovery_declarations.rb +84 -0
  170. data/lib/ibex/normalize.rb +179 -14
  171. data/lib/ibex/racc_migration/checker.rb +122 -0
  172. data/lib/ibex/racc_migration/harness.rb +177 -0
  173. data/lib/ibex/racc_migration/report.rb +94 -0
  174. data/lib/ibex/racc_migration.rb +12 -0
  175. data/lib/ibex/rake_task.rb +116 -0
  176. data/lib/ibex/samples.rb +186 -0
  177. data/lib/ibex/table_simulation/result.rb +51 -0
  178. data/lib/ibex/table_simulation/simulator.rb +253 -0
  179. data/lib/ibex/table_simulation/step.rb +60 -0
  180. data/lib/ibex/table_simulation/text.rb +31 -0
  181. data/lib/ibex/table_simulation.rb +13 -0
  182. data/lib/ibex/tables.rb +9 -70
  183. data/lib/ibex/version.rb +1 -1
  184. data/lib/ibex/watch/runner.rb +172 -0
  185. data/lib/ibex/watch/source_snapshot.rb +93 -0
  186. data/lib/ibex/watch.rb +11 -0
  187. data/lib/ibex.rb +25 -1
  188. data/schema/automaton-ir-v1.schema.json +401 -0
  189. data/schema/automaton-ir-v2.schema.json +58 -0
  190. data/schema/benchmark-v1.schema.json +212 -0
  191. data/schema/benchmark-v2.schema.json +61 -0
  192. data/schema/cst-v1.json +170 -0
  193. data/schema/error-ux-v1.schema.json +258 -0
  194. data/schema/explain-v1.schema.json +433 -0
  195. data/schema/frontend-diagnostics-v1.schema.json +154 -0
  196. data/schema/generation-manifest-v1.schema.json +115 -0
  197. data/schema/grammar-ir-v1.schema.json +426 -0
  198. data/schema/grammar-ir-v2.schema.json +779 -0
  199. data/schema/lexer-ir-v1.schema.json +215 -0
  200. data/schema/migration-check-v1.schema.json +60 -0
  201. data/schema/performance-comparison-v1.schema.json +395 -0
  202. data/schema/public-performance-comparison-v1.schema.json +506 -0
  203. data/schema/public-performance-profile-v1.schema.json +360 -0
  204. data/schema/runtime-coverage-v1.schema.json +86 -0
  205. data/schema/runtime-event-v1.schema.json +308 -0
  206. data/schema/table-simulation-v1.schema.json +70 -0
  207. data/sig/ibex/artifact_set.rbs +37 -0
  208. data/sig/ibex/cli/ambiguity.rbs +22 -0
  209. data/sig/ibex/cli/counterexample_options.rbs +2 -0
  210. data/sig/ibex/cli/coverage.rbs +53 -0
  211. data/sig/ibex/cli/debug.rbs +28 -0
  212. data/sig/ibex/cli/diagnostics.rbs +38 -0
  213. data/sig/ibex/cli/documentation.rbs +25 -0
  214. data/sig/ibex/cli/error_messages.rbs +57 -0
  215. data/sig/ibex/cli/explain.rbs +25 -0
  216. data/sig/ibex/cli/formatting.rbs +103 -0
  217. data/sig/ibex/cli/generation_artifacts.rbs +50 -0
  218. data/sig/ibex/cli/generation_error_messages.rbs +19 -0
  219. data/sig/ibex/cli/grammar_tests.rbs +36 -0
  220. data/sig/ibex/cli/ir_tools.rbs +51 -0
  221. data/sig/ibex/cli/lsp.rbs +14 -0
  222. data/sig/ibex/cli/outputs.rbs +17 -0
  223. data/sig/ibex/cli/racc_migration.rbs +30 -0
  224. data/sig/ibex/cli/samples.rbs +30 -0
  225. data/sig/ibex/cli/watch.rbs +43 -0
  226. data/sig/ibex/cli.rbs +104 -5
  227. data/sig/ibex/codegen/action_locations.rbs +45 -0
  228. data/sig/ibex/codegen/action_method_source.rbs +65 -0
  229. data/sig/ibex/codegen/action_source.rbs +50 -0
  230. data/sig/ibex/codegen/ambiguity.rbs +60 -0
  231. data/sig/ibex/codegen/cst_metadata.rbs +59 -0
  232. data/sig/ibex/codegen/documentation.rbs +50 -0
  233. data/sig/ibex/codegen/explain.rbs +85 -0
  234. data/sig/ibex/codegen/generated_action_abi.rbs +101 -0
  235. data/sig/ibex/codegen/html.rbs +18 -2
  236. data/sig/ibex/codegen/mermaid.rbs +16 -0
  237. data/sig/ibex/codegen/railroad.rbs +82 -0
  238. data/sig/ibex/codegen/railroad_documentation.rbs +31 -0
  239. data/sig/ibex/codegen/rbs.rbs +84 -4
  240. data/sig/ibex/codegen/report.rbs +8 -0
  241. data/sig/ibex/codegen/ruby.rbs +97 -23
  242. data/sig/ibex/codegen/ruby_actions.rbs +54 -0
  243. data/sig/ibex/codegen/ruby_ast.rbs +34 -0
  244. data/sig/ibex/codegen/ruby_error_messages.rbs +16 -0
  245. data/sig/ibex/codegen/ruby_lexer.rbs +25 -0
  246. data/sig/ibex/codegen/ruby_syntax.rbs +25 -0
  247. data/sig/ibex/codegen/ruby_table_metadata.rbs +26 -0
  248. data/sig/ibex/codegen/ruby_value_printers.rbs +28 -0
  249. data/sig/ibex/coverage/collector.rbs +76 -0
  250. data/sig/ibex/coverage/event_stream.rbs +42 -0
  251. data/sig/ibex/coverage/report.rbs +100 -0
  252. data/sig/ibex/coverage/runtime_event_validator.rbs +68 -0
  253. data/sig/ibex/coverage.rbs +7 -0
  254. data/sig/ibex/error_messages/parser.rbs +58 -0
  255. data/sig/ibex/error_messages/parser_v2.rbs +67 -0
  256. data/sig/ibex/error_messages/renderer.rbs +23 -0
  257. data/sig/ibex/error_messages/sentence_search.rbs +80 -0
  258. data/sig/ibex/error_messages/update.rbs +43 -0
  259. data/sig/ibex/error_messages.rbs +85 -0
  260. data/sig/ibex/frontend/ast.rbs +208 -19
  261. data/sig/ibex/frontend/bootstrap_parser.rbs +11 -0
  262. data/sig/ibex/frontend/diagnostic.rbs +53 -0
  263. data/sig/ibex/frontend/diagnostic_recovery.rbs +98 -0
  264. data/sig/ibex/frontend/dsl.rbs +33 -4
  265. data/sig/ibex/frontend/formatter.rbs +135 -0
  266. data/sig/ibex/frontend/generated_parser.rbs +218 -68
  267. data/sig/ibex/frontend/generated_parser_base.rbs +61 -10
  268. data/sig/ibex/frontend/generated_parser_includes.rbs +23 -0
  269. data/sig/ibex/frontend/generated_parser_metadata.rbs +23 -0
  270. data/sig/ibex/frontend/generated_parser_parameters.rbs +24 -0
  271. data/sig/ibex/frontend/generation.rbs +6 -0
  272. data/sig/ibex/frontend/lexer.rbs +49 -2
  273. data/sig/ibex/frontend/lexer_recovery.rbs +25 -0
  274. data/sig/ibex/frontend/parser/declarations.rbs +54 -0
  275. data/sig/ibex/frontend/parser/parameters.rbs +28 -0
  276. data/sig/ibex/frontend/parser/rules.rbs +3 -0
  277. data/sig/ibex/frontend/parser.rbs +66 -0
  278. data/sig/ibex/frontend/regenerator.rbs +11 -0
  279. data/sig/ibex/frontend/resolution.rbs +33 -0
  280. data/sig/ibex/frontend/resolver.rbs +91 -0
  281. data/sig/ibex/frontend/rule_documentation.rbs +42 -0
  282. data/sig/ibex/frontend/source_cursor.rbs +36 -3
  283. data/sig/ibex/frontend/source_document.rbs +119 -0
  284. data/sig/ibex/frontend/source_loader.rbs +66 -0
  285. data/sig/ibex/frontend/source_span.rbs +53 -0
  286. data/sig/ibex/frontend/token_adapter/declaration_document_state.rbs +21 -0
  287. data/sig/ibex/frontend/token_adapter/declaration_lexer_state.rbs +27 -0
  288. data/sig/ibex/frontend/token_adapter/declaration_state.rbs +73 -5
  289. data/sig/ibex/frontend/token_adapter/rule_state.rbs +20 -0
  290. data/sig/ibex/frontend/token_adapter.rbs +5 -2
  291. data/sig/ibex/frontend.rbs +1 -1
  292. data/sig/ibex/generation_input.rbs +37 -0
  293. data/sig/ibex/generation_manifest.rbs +67 -0
  294. data/sig/ibex/generation_transaction.rbs +82 -0
  295. data/sig/ibex/generation_transaction_recovery.rbs +36 -0
  296. data/sig/ibex/generation_transaction_validation.rbs +65 -0
  297. data/sig/ibex/grammar_tests.rbs +93 -0
  298. data/sig/ibex/ir/automaton_ir.rbs +8 -2
  299. data/sig/ibex/ir/grammar_ir.rbs +75 -15
  300. data/sig/ibex/ir/lexer_ir.rbs +57 -0
  301. data/sig/ibex/ir/migration.rbs +34 -0
  302. data/sig/ibex/ir/serialize.rbs +23 -6
  303. data/sig/ibex/ir/validator/automaton.rbs +109 -0
  304. data/sig/ibex/ir/validator/base.rbs +65 -0
  305. data/sig/ibex/ir/validator/grammar.rbs +184 -0
  306. data/sig/ibex/ir/validator/lexer.rbs +37 -0
  307. data/sig/ibex/ir/validator.rbs +16 -0
  308. data/sig/ibex/ir.rbs +38 -4
  309. data/sig/ibex/lalr/build_metrics.rbs +20 -0
  310. data/sig/ibex/lalr/builder.rbs +95 -15
  311. data/sig/ibex/lalr/conflict_search.rbs +7 -3
  312. data/sig/ibex/lalr/counterexample.rbs +5 -2
  313. data/sig/ibex/lalr/direct_lookaheads.rbs +86 -0
  314. data/sig/ibex/lalr/ielr_partition.rbs +59 -0
  315. data/sig/ibex/lalr/on_error_reductions.rbs +22 -0
  316. data/sig/ibex/lalr.rbs +6 -0
  317. data/sig/ibex/location.rbs +67 -0
  318. data/sig/ibex/lsp/document_handlers.rbs +24 -0
  319. data/sig/ibex/lsp/document_store.rbs +94 -0
  320. data/sig/ibex/lsp/document_store_diagnostics.rbs +20 -0
  321. data/sig/ibex/lsp/document_store_validation.rbs +26 -0
  322. data/sig/ibex/lsp/initialization_handlers.rbs +30 -0
  323. data/sig/ibex/lsp/navigation_handlers.rbs +30 -0
  324. data/sig/ibex/lsp/position_codec.rbs +40 -0
  325. data/sig/ibex/lsp/protocol_error.rbs +32 -0
  326. data/sig/ibex/lsp/request_handlers.rbs +26 -0
  327. data/sig/ibex/lsp/request_support.rbs +40 -0
  328. data/sig/ibex/lsp/server.rbs +55 -0
  329. data/sig/ibex/lsp/symbol_index.rbs +78 -0
  330. data/sig/ibex/lsp/symbol_index_builder.rbs +87 -0
  331. data/sig/ibex/lsp/symbol_index_precedence_references.rbs +18 -0
  332. data/sig/ibex/lsp/symbol_index_source_queries.rbs +26 -0
  333. data/sig/ibex/lsp/symbol_occurrence.rbs +25 -0
  334. data/sig/ibex/lsp/transport.rbs +35 -0
  335. data/sig/ibex/lsp/workspace.rbs +41 -0
  336. data/sig/ibex/lsp/workspace_analyzer.rbs +69 -0
  337. data/sig/ibex/lsp.rbs +7 -0
  338. data/sig/ibex/normalize/declarations.rbs +31 -0
  339. data/sig/ibex/normalize/diagnostics.rbs +9 -0
  340. data/sig/ibex/normalize/expander.rbs +20 -14
  341. data/sig/ibex/normalize/expression.rbs +10 -10
  342. data/sig/ibex/normalize/inline_expansion.rbs +120 -0
  343. data/sig/ibex/normalize/inline_validation.rbs +40 -0
  344. data/sig/ibex/normalize/lexer.rbs +37 -0
  345. data/sig/ibex/normalize/named_references.rbs +20 -0
  346. data/sig/ibex/normalize/nodes.rbs +14 -0
  347. data/sig/ibex/normalize/parameter_ebnf_lowering.rbs +32 -0
  348. data/sig/ibex/normalize/parameter_lowering.rbs +35 -0
  349. data/sig/ibex/normalize/parameter_substitution.rbs +42 -0
  350. data/sig/ibex/normalize/parameter_validation.rbs +44 -0
  351. data/sig/ibex/normalize/parameters.rbs +46 -0
  352. data/sig/ibex/normalize/recovery_declarations.rbs +24 -0
  353. data/sig/ibex/normalize.rbs +123 -18
  354. data/sig/ibex/racc_migration/checker.rbs +36 -0
  355. data/sig/ibex/racc_migration/harness.rbs +16 -0
  356. data/sig/ibex/racc_migration/report.rbs +53 -0
  357. data/sig/ibex/racc_migration.rbs +8 -0
  358. data/sig/ibex/rake_task.rbs +51 -0
  359. data/sig/ibex/samples.rbs +51 -0
  360. data/sig/ibex/table_simulation/result.rbs +32 -0
  361. data/sig/ibex/table_simulation/simulator.rbs +98 -0
  362. data/sig/ibex/table_simulation/step.rbs +40 -0
  363. data/sig/ibex/table_simulation/text.rbs +14 -0
  364. data/sig/ibex/table_simulation.rbs +7 -0
  365. data/sig/ibex/tables.rbs +0 -26
  366. data/sig/ibex/watch/runner.rbs +48 -0
  367. data/sig/ibex/watch/source_snapshot.rbs +42 -0
  368. data/sig/ibex/watch.rbs +7 -0
  369. data/sig/ibex.rbs +2 -0
  370. metadata +301 -16
  371. data/.rubocop.yml +0 -43
  372. data/CHANGELOG.md +0 -30
  373. data/Rakefile +0 -25
  374. data/Steepfile +0 -10
  375. data/docs/compat-notes.md +0 -37
  376. data/docs/lexer-coverage.md +0 -14
  377. data/docs/phase10-extensions.md +0 -27
  378. data/gemfiles/Gemfile +0 -7
  379. data/gemfiles/Gemfile.lock +0 -98
  380. data/lib/ibex/frontend/grammar.y +0 -156
  381. data/lib/ibex/runtime/parser.rb +0 -360
  382. data/lib/ibex/runtime.rb +0 -8
  383. data/sig/ibex/runtime/parser.rbs +0 -167
  384. data/sig/ibex/runtime.rbs +0 -6
@@ -3,52 +3,73 @@
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
6
+ class << self
7
+ # @rbs (Frontend::AST::item item) -> String
8
+ def render(item)
9
+ pending = [item] #: Array[untyped]
10
+ output = [] #: Array[String]
11
+ until pending.empty?
12
+ current = pending.pop
13
+ if current.is_a?(String)
14
+ output << current
15
+ next
16
+ end
13
17
 
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"
18
+ push_render_item(pending, current)
19
+ end
20
+ output.join
24
21
  end
25
- end
26
- module_function :render
27
22
 
28
- # @rbs skip
29
- private
23
+ private
30
24
 
31
- # @rbs skip
32
- def render_reference(item)
33
- suffix = item.named_reference ? ":#{item.named_reference}" : ""
34
- "#{item.name}#{suffix}"
35
- end
25
+ # @rbs (Array[untyped] pending, Frontend::AST::item item) -> void
26
+ def push_render_item(pending, item)
27
+ case item
28
+ when Frontend::AST::SymbolReference
29
+ pending << "#{item.name}#{":#{item.named_reference}" if item.named_reference}"
30
+ when Frontend::AST::ParameterizedReference
31
+ push_render_parameterized_reference(pending, item)
32
+ when Frontend::AST::Group
33
+ push_render_group(pending, item)
34
+ when Frontend::AST::Optional
35
+ pending.push("?", item.item)
36
+ when Frontend::AST::Star
37
+ pending.push("*", item.item)
38
+ when Frontend::AST::Plus
39
+ pending.push("+", item.item)
40
+ when Frontend::AST::SeparatedList
41
+ name = item.nonempty ? "separated_nonempty_list" : "separated_list"
42
+ pending.push(")", item.separator, ", ", item.item, "(", name)
43
+ else
44
+ raise Ibex::Error, "#{item.loc}: cannot render unsupported EBNF expression"
45
+ end
46
+ end
36
47
 
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
48
+ # @rbs (Array[untyped] pending, Frontend::AST::ParameterizedReference item) -> void
49
+ def push_render_parameterized_reference(pending, item)
50
+ pending << ":#{item.named_reference}" if item.named_reference
51
+ pending << ")"
52
+ push_render_items(pending, item.arguments, ", ")
53
+ pending.push("(", item.name)
54
+ end
42
55
 
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
56
+ # @rbs (Array[untyped] pending, Frontend::AST::Group item) -> void
57
+ def push_render_group(pending, item)
58
+ pending << ")"
59
+ (item.alternatives.length - 1).downto(0) do |index|
60
+ pending << " | " if index < item.alternatives.length - 1
61
+ push_render_items(pending, item.alternatives.fetch(index), " ")
62
+ end
63
+ pending << "("
64
+ end
49
65
 
50
- class << self
51
- private :render_reference, :render_group, :render_separated_list
66
+ # @rbs (Array[untyped] pending, Array[Frontend::AST::item] items, String separator) -> void
67
+ def push_render_items(pending, items, separator)
68
+ (items.length - 1).downto(0) do |index|
69
+ pending << separator if index < items.length - 1
70
+ pending << items.fetch(index)
71
+ end
72
+ end
52
73
  end
53
74
  end
54
75
  end
@@ -0,0 +1,414 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibex
4
+ # Deterministically substitutes inline-rule productions before LR construction.
5
+ # rubocop:disable Metrics/ModuleLength -- expansion, action plans, and id remapping share one invariant.
6
+ module NormalizeInlineExpansion
7
+ private
8
+
9
+ # @rbs () -> void
10
+ def expand_inline_rules
11
+ # @type self: Normalizer
12
+ return if @inline_symbol_ids.empty?
13
+
14
+ definitions = @productions.group_by(&:lhs)
15
+ expanded = [] #: Array[IR::Production]
16
+ @productions.each do |production|
17
+ next if @inline_symbol_ids.include?(production.lhs)
18
+
19
+ variants = expand_inline_production(production, definitions)
20
+ variants.each do |variant|
21
+ if variant[:inline_used]
22
+ charge_inline_expansion!(production)
23
+ expanded << composed_inline_production(production, variant, expanded.length)
24
+ else
25
+ expanded << copy_inline_production(production, expanded.length)
26
+ end
27
+ end
28
+ end
29
+ rebuild_inline_symbols(expanded)
30
+ end
31
+
32
+ # Explicit heap frames avoid tying grammar depth to the Ruby call stack.
33
+ # The single-definition path reuses its accumulated arrays, so a long
34
+ # acyclic chain remains linear in the size of its final action plan.
35
+ # @rbs (IR::Production production, Hash[Integer, Array[IR::Production]] definitions) ->
36
+ # Array[Hash[Symbol, untyped]]
37
+ def expand_inline_production(production, definitions)
38
+ # @type self: Normalizer
39
+ variants = [] #: Array[Hash[Symbol, untyped]]
40
+ worklist = [[inline_expansion_frame(production, nil)]] #: Array[Array[Hash[Symbol, untyped]]]
41
+ until worklist.empty?
42
+ frames = worklist.pop || raise(Ibex::Error, "internal inline expansion worklist underflow")
43
+ drain_inline_expansion_frames(frames, definitions, worklist, variants, production.origin[:loc])
44
+ end
45
+ variants
46
+ end
47
+
48
+ # @rbs (Array[Hash[Symbol, untyped]] frames, Hash[Integer, Array[IR::Production]] definitions,
49
+ # Array[Array[Hash[Symbol, untyped]]] worklist, Array[Hash[Symbol, untyped]] variants,
50
+ # IR::location? location) -> void
51
+ def drain_inline_expansion_frames(frames, definitions, worklist, variants, location)
52
+ loop do
53
+ frame = frames.fetch(-1)
54
+ current = frame.fetch(:production)
55
+ if frame.fetch(:index) < current.rhs.length
56
+ return if advance_inline_expansion_frame?(frames, definitions, worklist, variants, location)
57
+ elsif complete_inline_expansion_frame?(frames, variants, worklist, location)
58
+ return
59
+ end
60
+ end
61
+ end
62
+
63
+ # @rbs (Array[Hash[Symbol, untyped]] frames, Hash[Integer, Array[IR::Production]] definitions,
64
+ # Array[Array[Hash[Symbol, untyped]]] worklist, Array[Hash[Symbol, untyped]] variants,
65
+ # IR::location? location) -> bool
66
+ def advance_inline_expansion_frame?(frames, definitions, worklist, variants, location)
67
+ frame = frames.fetch(-1)
68
+ current = frame.fetch(:production)
69
+ index = frame.fetch(:index)
70
+ symbol_id = current.rhs.fetch(index)
71
+ frame[:index] = index + 1
72
+ unless @inline_symbol_ids.include?(symbol_id)
73
+ frame[:variant] = append_inline_symbol(frame.fetch(:variant), symbol_id)
74
+ return false
75
+ end
76
+
77
+ choices = definitions.fetch(symbol_id)
78
+ if choices.one?
79
+ frames << inline_expansion_frame(choices.fetch(0), symbol_id)
80
+ return false
81
+ end
82
+
83
+ schedule_inline_choice_branches(frames, choices, symbol_id, worklist)
84
+ enforce_inline_choice_limit!(variants.length + worklist.length, location)
85
+ true
86
+ end
87
+
88
+ # @rbs (Array[Hash[Symbol, untyped]] frames, Array[IR::Production] choices, Integer symbol_id,
89
+ # Array[Array[Hash[Symbol, untyped]]] worklist) -> void
90
+ def schedule_inline_choice_branches(frames, choices, symbol_id, worklist)
91
+ choices.reverse_each do |choice|
92
+ branch = clone_inline_expansion_frames(frames)
93
+ branch << inline_expansion_frame(choice, symbol_id)
94
+ worklist << branch
95
+ end
96
+ end
97
+
98
+ # @rbs (Array[Hash[Symbol, untyped]] frames, Array[Hash[Symbol, untyped]] variants,
99
+ # Array[Array[Hash[Symbol, untyped]]] worklist, IR::location? location) -> bool
100
+ def complete_inline_expansion_frame?(frames, variants, worklist, location)
101
+ frame = frames.fetch(-1)
102
+ current = frame.fetch(:production)
103
+ completed = finish_inline_precedence(frame.fetch(:variant), current)
104
+ frames.pop
105
+ if frames.empty?
106
+ variants << completed
107
+ enforce_inline_choice_limit!(variants.length + worklist.length, location)
108
+ return true
109
+ end
110
+
111
+ choice = finish_inline_choice(completed, current, frame.fetch(:symbol_id))
112
+ parent = frames.fetch(-1)
113
+ parent[:variant] = combine_inline_variant(parent.fetch(:variant), choice)
114
+ false
115
+ end
116
+
117
+ # @rbs (IR::Production production, Integer? symbol_id) -> Hash[Symbol, untyped]
118
+ def inline_expansion_frame(production, symbol_id)
119
+ { production: production, symbol_id: symbol_id, index: 0, variant: empty_inline_variant(production) }
120
+ end
121
+
122
+ # @rbs (Array[Hash[Symbol, untyped]] frames) -> Array[Hash[Symbol, untyped]]
123
+ def clone_inline_expansion_frames(frames)
124
+ frames.map do |frame|
125
+ variant = frame.fetch(:variant)
126
+ frame.merge(
127
+ variant: variant.merge(
128
+ rhs: variant.fetch(:rhs).dup,
129
+ steps: variant.fetch(:steps).dup,
130
+ logical_refs: variant.fetch(:logical_refs).dup
131
+ )
132
+ )
133
+ end
134
+ end
135
+
136
+ # @rbs (IR::Production production) -> Hash[Symbol, untyped]
137
+ def empty_inline_variant(production)
138
+ {
139
+ rhs: [],
140
+ steps: [],
141
+ logical_refs: [],
142
+ output_ref: nil,
143
+ inline_used: false,
144
+ inline_rule: nil,
145
+ precedence_override: nil,
146
+ precedence_contributes: false,
147
+ parameter: production.expansion&.dig(:parameter)
148
+ }
149
+ end
150
+
151
+ # @rbs (Hash[Symbol, untyped] variant, Integer symbol_id) -> Hash[Symbol, untyped]
152
+ def append_inline_symbol(variant, symbol_id)
153
+ # @type self: Normalizer
154
+ rhs = variant.fetch(:rhs)
155
+ terminal = @symbols.fetch(symbol_id).terminal?
156
+ variant.merge(
157
+ rhs: rhs + [symbol_id],
158
+ logical_refs: variant.fetch(:logical_refs) + [[:physical, rhs.length]],
159
+ precedence_override: terminal ? nil : variant[:precedence_override],
160
+ precedence_contributes: terminal || variant.fetch(:precedence_contributes)
161
+ )
162
+ end
163
+
164
+ # @rbs (Hash[Symbol, untyped] parent, Hash[Symbol, untyped] child) -> Hash[Symbol, untyped]
165
+ def combine_inline_variant(parent, child)
166
+ physical_offset = parent.fetch(:rhs).length
167
+ step_offset = parent.fetch(:steps).length
168
+ steps = combined_inline_steps(parent, child, physical_offset, step_offset)
169
+ parent.merge(
170
+ rhs: append_inline_array(parent.fetch(:rhs), child.fetch(:rhs)),
171
+ steps: append_inline_array(parent.fetch(:steps), steps),
172
+ logical_refs: parent.fetch(:logical_refs) + [
173
+ remap_inline_reference(child.fetch(:output_ref), physical_offset, step_offset)
174
+ ],
175
+ inline_used: true,
176
+ inline_rule: parent[:inline_rule] || child[:inline_rule],
177
+ precedence_override: combined_inline_precedence(parent, child),
178
+ precedence_contributes: parent.fetch(:precedence_contributes) ||
179
+ child.fetch(:precedence_contributes),
180
+ parameter: parent[:parameter] || child[:parameter]
181
+ )
182
+ end
183
+
184
+ # @rbs (Hash[Symbol, untyped] parent, Hash[Symbol, untyped] child,
185
+ # Integer physical_offset, Integer step_offset) -> Array[Hash[Symbol, untyped]]
186
+ def combined_inline_steps(parent, child, physical_offset, step_offset)
187
+ return child.fetch(:steps) if physical_offset.zero? && step_offset.zero? && parent.fetch(:logical_refs).empty?
188
+
189
+ remap_inline_steps(parent, child, physical_offset, step_offset)
190
+ end
191
+
192
+ # @rbs (Array[untyped] left, Array[untyped] right) -> Array[untyped]
193
+ def append_inline_array(left, right)
194
+ left.empty? ? right : left + right
195
+ end
196
+
197
+ # @rbs (Hash[Symbol, untyped] parent, Hash[Symbol, untyped] child) -> Integer?
198
+ def combined_inline_precedence(parent, child)
199
+ return child[:precedence_override] if child.fetch(:precedence_contributes)
200
+
201
+ parent[:precedence_override]
202
+ end
203
+
204
+ # @rbs (Hash[Symbol, untyped] parent, Hash[Symbol, untyped] child,
205
+ # Integer physical_offset, Integer step_offset) -> Array[Hash[Symbol, untyped]]
206
+ def remap_inline_steps(parent, child, physical_offset, step_offset)
207
+ child.fetch(:steps).map do |step|
208
+ inputs = step.fetch(:inputs).map do |reference|
209
+ remap_inline_reference(reference, physical_offset, step_offset)
210
+ end
211
+ stack_inputs = step.fetch(:stack_inputs).map do |reference|
212
+ remap_inline_reference(reference, physical_offset, step_offset)
213
+ end
214
+ step.merge(
215
+ inputs: inputs,
216
+ stack_inputs: parent.fetch(:logical_refs) + stack_inputs,
217
+ lookahead: step.fetch(:lookahead) + physical_offset
218
+ )
219
+ end
220
+ end
221
+
222
+ # @rbs (Array[Symbol | Integer] reference, Integer physical_offset, Integer step_offset) ->
223
+ # Array[Symbol | Integer]
224
+ def remap_inline_reference(reference, physical_offset, step_offset)
225
+ kind, index = reference
226
+ raise Ibex::Error, "invalid inline slot kind" unless kind.is_a?(Symbol)
227
+ raise Ibex::Error, "invalid inline slot reference" unless index.is_a?(Integer)
228
+
229
+ [kind, index + (kind == :physical ? physical_offset : step_offset)]
230
+ end
231
+
232
+ # @rbs (Hash[Symbol, untyped] variant, IR::Production production) -> Hash[Symbol, untyped]
233
+ def finish_inline_precedence(variant, production)
234
+ explicit = production.precedence_override
235
+ variant.merge(
236
+ precedence_override: explicit || variant[:precedence_override],
237
+ precedence_contributes: !explicit.nil? || variant.fetch(:precedence_contributes)
238
+ )
239
+ end
240
+
241
+ # @rbs (Hash[Symbol, untyped] variant, IR::Production production, Integer symbol_id) ->
242
+ # Hash[Symbol, untyped]
243
+ def finish_inline_choice(variant, production, symbol_id)
244
+ steps = variant.fetch(:steps)
245
+ rule = @inline_rule_by_symbol.fetch(symbol_id)
246
+ step = inline_action_step(production, variant.fetch(:logical_refs), variant.fetch(:rhs).length, :inline, rule)
247
+ steps << step
248
+ variant.merge(
249
+ steps: steps,
250
+ output_ref: [:step, steps.length - 1],
251
+ inline_used: true,
252
+ inline_rule: rule
253
+ )
254
+ end
255
+
256
+ # @rbs (IR::Production production, Array[Array[Symbol | Integer]] inputs, Integer lookahead,
257
+ # Symbol kind, String? rule) -> Hash[Symbol, untyped]
258
+ def inline_action_step(production, inputs, lookahead, kind, rule)
259
+ action = production.action
260
+ {
261
+ kind: kind,
262
+ rule: rule,
263
+ code: action&.code,
264
+ loc: action&.location || production.origin.fetch(:loc),
265
+ named_refs: action&.named_refs || [],
266
+ context_length: action&.context_length || 0,
267
+ inputs: inputs,
268
+ stack_inputs: [],
269
+ lookahead: lookahead,
270
+ result_var: @options.fetch(:result_var),
271
+ result_type: @symbols.fetch(production.lhs).semantic_type
272
+ }
273
+ end
274
+
275
+ # @rbs (IR::Production production, Hash[Symbol, untyped] variant, Integer id) -> IR::Production
276
+ def composed_inline_production(production, variant, id)
277
+ steps = variant.fetch(:steps)
278
+ caller = inline_action_step(
279
+ production, variant.fetch(:logical_refs), variant.fetch(:rhs).length, :rule, nil
280
+ )
281
+ all_steps = steps + [caller]
282
+ action = composed_inline_action(production, variant.fetch(:rhs).length, all_steps)
283
+ IR::Production.new(
284
+ id: id, lhs: production.lhs, rhs: variant.fetch(:rhs), action: action,
285
+ precedence_override: variant[:precedence_override], origin: production.origin,
286
+ documentation: production.documentation,
287
+ expansion: inline_production_expansion(production, variant)
288
+ )
289
+ end
290
+
291
+ # @rbs (IR::Production production, Integer physical_length, Array[Hash[Symbol, untyped]]) -> IR::Action
292
+ def composed_inline_action(production, physical_length, steps)
293
+ action = production.action
294
+ fragments = steps.map do |step|
295
+ { kind: step.fetch(:kind), source: inline_source_provenance(step.fetch(:loc)) }
296
+ end
297
+ plan_steps = steps.map { |step| composition_plan_step(step, physical_length) }
298
+ composition = {
299
+ strategy: "sequence",
300
+ fragments: fragments,
301
+ plan: { version: 1, physical: physical_length, steps: plan_steps }
302
+ } #: IR::action_composition
303
+ IR::Action.new(
304
+ code: action&.code || inline_implicit_code(production.rhs.length),
305
+ location: action&.location || production.origin.fetch(:loc),
306
+ composition: composition
307
+ )
308
+ end
309
+
310
+ # @rbs (Hash[Symbol, untyped] step, Integer physical_length) -> Hash[Symbol, untyped]
311
+ def composition_plan_step(step, physical_length)
312
+ {
313
+ kind: step.fetch(:kind),
314
+ rule: step[:rule],
315
+ code: step[:code],
316
+ loc: step.fetch(:loc),
317
+ named_refs: step.fetch(:named_refs),
318
+ context_length: step.fetch(:context_length),
319
+ inputs: step.fetch(:inputs).map { |reference| resolve_inline_reference(reference, physical_length) },
320
+ stack_inputs: step.fetch(:stack_inputs).map do |reference|
321
+ resolve_inline_reference(reference, physical_length)
322
+ end,
323
+ lookahead: step.fetch(:lookahead) < physical_length ? step.fetch(:lookahead) : nil,
324
+ result_var: step.fetch(:result_var),
325
+ result_type: step[:result_type]
326
+ }
327
+ end
328
+
329
+ # @rbs (Array[Symbol | Integer] reference, Integer physical_length) -> Integer
330
+ def resolve_inline_reference(reference, physical_length)
331
+ kind, index = reference
332
+ raise Ibex::Error, "invalid inline slot reference" unless index.is_a?(Integer)
333
+
334
+ index + (kind == :step ? physical_length : 0)
335
+ end
336
+
337
+ # @rbs (Integer rhs_length) -> String
338
+ def inline_implicit_code(rhs_length)
339
+ expression = rhs_length.zero? ? "nil" : "val[0]"
340
+ @options.fetch(:result_var) ? " result = #{expression} " : " #{expression} "
341
+ end
342
+
343
+ # @rbs (IR::location location) -> IR::source_provenance
344
+ def inline_source_provenance(location)
345
+ { file: location[:file], root: @resolution&.root_directory, byte_span: nil }
346
+ end
347
+
348
+ # @rbs (IR::Production production, Hash[Symbol, untyped] variant) -> IR::production_expansion
349
+ def inline_production_expansion(production, variant)
350
+ existing = production.expansion
351
+ {
352
+ parameter: existing&.dig(:parameter) || variant[:parameter],
353
+ inline: { rule: variant.fetch(:inline_rule) },
354
+ include_chain: existing&.dig(:include_chain) || []
355
+ }
356
+ end
357
+
358
+ # @rbs (IR::Production production, Integer id) -> IR::Production
359
+ def copy_inline_production(production, id)
360
+ IR::Production.new(
361
+ id: id, lhs: production.lhs, rhs: production.rhs, action: production.action,
362
+ precedence_override: production.precedence_override, origin: production.origin,
363
+ documentation: production.documentation, expansion: production.expansion
364
+ )
365
+ end
366
+
367
+ # @rbs (IR::Production production) -> void
368
+ def charge_inline_expansion!(production)
369
+ @inline_expansion_count += 1
370
+ enforce_inline_choice_limit!(@inline_expansion_count, production.origin[:loc])
371
+ end
372
+
373
+ # @rbs (Integer count, IR::location? location) -> void
374
+ def enforce_inline_choice_limit!(count, location)
375
+ # @type self: Normalizer
376
+ return if count <= @max_inline_expansions
377
+
378
+ fail_hash(location, "inline expansion limit of #{@max_inline_expansions} exceeded")
379
+ end
380
+
381
+ # @rbs (Array[IR::Production] productions) -> void
382
+ def rebuild_inline_symbols(productions)
383
+ kept = @symbols.reject { |definition| @inline_symbol_ids.include?(definition.id) }
384
+ id_map = kept.each_with_index.to_h { |definition, id| [definition.id, id] }
385
+ @symbols = kept.each_with_index.map { |definition, id| remap_inline_symbol(definition, id) }
386
+ @symbols_by_name = @symbols.to_h { |definition| [definition.name, definition] }
387
+ @productions = productions.each_with_index.map do |production, id|
388
+ remap_inline_production(production, id, id_map)
389
+ end
390
+ end
391
+
392
+ # @rbs (IR::GrammarSymbol definition, Integer id) -> IR::GrammarSymbol
393
+ def remap_inline_symbol(definition, id)
394
+ IR::GrammarSymbol.new(
395
+ id: id, name: definition.name, kind: definition.kind, reserved: definition.reserved,
396
+ precedence: definition.precedence, location: definition.location,
397
+ display_name: definition.display_name, semantic_type: definition.semantic_type,
398
+ documentation: definition.documentation
399
+ )
400
+ end
401
+
402
+ # @rbs (IR::Production production, Integer id, Hash[Integer, Integer] id_map) -> IR::Production
403
+ def remap_inline_production(production, id, id_map)
404
+ IR::Production.new(
405
+ id: id, lhs: id_map.fetch(production.lhs),
406
+ rhs: production.rhs.map { |symbol_id| id_map.fetch(symbol_id) },
407
+ action: production.action,
408
+ precedence_override: production.precedence_override && id_map.fetch(production.precedence_override),
409
+ origin: production.origin, documentation: production.documentation, expansion: production.expansion
410
+ )
411
+ end
412
+ end
413
+ # rubocop:enable Metrics/ModuleLength
414
+ end