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
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibex
4
+ # Structural, sharing-preserving substitution for parameterized user rules.
5
+ module NormalizeParameterSubstitution
6
+ private
7
+
8
+ # @rbs (Frontend::AST::Alternative alternative, Hash[String, Frontend::AST::item] bindings) ->
9
+ # Frontend::AST::Alternative
10
+ def substitute_parameter_alternative(alternative, bindings)
11
+ # @type self: Normalizer
12
+ Frontend::AST::Alternative.new(
13
+ items: alternative.items.map { |item| substitute_parameter_item(item, bindings) },
14
+ action: alternative.action, precedence: substitute_parameter_precedence(alternative, bindings),
15
+ node_annotation: alternative.node_annotation, loc: alternative.loc
16
+ )
17
+ end
18
+
19
+ # @rbs (Frontend::AST::Alternative alternative, Hash[String, Frontend::AST::item] bindings) -> String?
20
+ def substitute_parameter_precedence(alternative, bindings)
21
+ # @type self: Normalizer
22
+ precedence = alternative.precedence
23
+ return precedence unless precedence && bindings.key?(precedence)
24
+
25
+ argument = bindings.fetch(precedence)
26
+ unless argument.is_a?(Frontend::AST::SymbolReference) && !argument.named_reference
27
+ fail_at(alternative.loc, "formal precedence #{precedence} requires one plain symbol argument")
28
+ end
29
+ argument.name
30
+ end
31
+
32
+ # @rbs (Frontend::AST::item item, Hash[String, Frontend::AST::item] bindings) -> Frontend::AST::item
33
+ def substitute_parameter_item(item, bindings)
34
+ # @type self: Normalizer
35
+ if item.is_a?(Frontend::AST::SymbolReference) && bindings.key?(item.name)
36
+ return substitute_formal_reference(item, bindings.fetch(item.name))
37
+ end
38
+
39
+ clone_parameter_item(item, bindings)
40
+ end
41
+
42
+ # @rbs (Frontend::AST::SymbolReference formal, Frontend::AST::item argument) -> Frontend::AST::item
43
+ def substitute_formal_reference(formal, argument)
44
+ # @type self: Normalizer
45
+ name = formal.named_reference
46
+ return argument unless name
47
+
48
+ case argument
49
+ when Frontend::AST::SymbolReference
50
+ Frontend::AST::SymbolReference.new(name: argument.name, named_reference: name, loc: argument.loc)
51
+ when Frontend::AST::ParameterizedReference
52
+ Frontend::AST::ParameterizedReference.new(
53
+ name: argument.name, arguments: argument.arguments, named_reference: name, loc: argument.loc
54
+ )
55
+ else
56
+ fail_at(formal.loc, "named formal #{formal.name} requires a plain symbol or parameterized argument")
57
+ end
58
+ end
59
+
60
+ # @rbs (Frontend::AST::item item, ?Hash[String, Frontend::AST::item] bindings) -> Frontend::AST::item
61
+ def clone_parameter_item(item, bindings = {})
62
+ # @type self: Normalizer
63
+ case item
64
+ when Frontend::AST::SymbolReference
65
+ clone_parameter_symbol(item, bindings)
66
+ when Frontend::AST::ParameterizedReference
67
+ clone_parameter_call(item, bindings)
68
+ when Frontend::AST::Group
69
+ clone_parameter_group(item, bindings)
70
+ when Frontend::AST::Optional, Frontend::AST::Star, Frontend::AST::Plus
71
+ clone_parameter_suffix(item, bindings)
72
+ when Frontend::AST::SeparatedList
73
+ clone_parameter_separated_list(item, bindings)
74
+ else
75
+ item
76
+ end
77
+ end
78
+
79
+ # @rbs (Frontend::AST::SymbolReference item, Hash[String, Frontend::AST::item] bindings) -> Frontend::AST::item
80
+ def clone_parameter_symbol(item, bindings)
81
+ # @type self: Normalizer
82
+ return substitute_parameter_item(item, bindings) if bindings.key?(item.name)
83
+
84
+ Frontend::AST::SymbolReference.new(name: item.name, named_reference: item.named_reference, loc: item.loc)
85
+ end
86
+
87
+ # @rbs (Frontend::AST::ParameterizedReference item, Hash[String, Frontend::AST::item] bindings) ->
88
+ # Frontend::AST::ParameterizedReference
89
+ def clone_parameter_call(item, bindings)
90
+ # @type self: Normalizer
91
+ fail_at(item.loc, "formal #{item.name} cannot be used as a parameterized rule name") if bindings.key?(item.name)
92
+ Frontend::AST::ParameterizedReference.new(
93
+ name: item.name, arguments: item.arguments.map { |argument| substitute_parameter_item(argument, bindings) },
94
+ named_reference: item.named_reference, loc: item.loc
95
+ )
96
+ end
97
+
98
+ # @rbs (Frontend::AST::Group item, Hash[String, Frontend::AST::item] bindings) -> Frontend::AST::Group
99
+ def clone_parameter_group(item, bindings)
100
+ # @type self: Normalizer
101
+ alternatives = item.alternatives.map do |items|
102
+ items.map { |child| substitute_parameter_item(child, bindings) }
103
+ end
104
+ Frontend::AST::Group.new(alternatives: alternatives, loc: item.loc)
105
+ end
106
+
107
+ # @rbs (Frontend::AST::Optional | Frontend::AST::Star | Frontend::AST::Plus item,
108
+ # Hash[String, Frontend::AST::item] bindings) -> Frontend::AST::item
109
+ def clone_parameter_suffix(item, bindings)
110
+ # @type self: Normalizer
111
+ item.class.new(item: substitute_parameter_item(item.item, bindings), loc: item.loc)
112
+ end
113
+
114
+ # @rbs (Frontend::AST::SeparatedList item, Hash[String, Frontend::AST::item] bindings) ->
115
+ # Frontend::AST::SeparatedList
116
+ def clone_parameter_separated_list(item, bindings)
117
+ # @type self: Normalizer
118
+ Frontend::AST::SeparatedList.new(
119
+ item: substitute_parameter_item(item.item, bindings),
120
+ separator: substitute_parameter_item(item.separator, bindings),
121
+ nonempty: item.nonempty, loc: item.loc
122
+ )
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibex
4
+ # Static validation and collection of parameterized user rule definitions.
5
+ module NormalizeParameterValidation
6
+ private
7
+
8
+ # @rbs () -> void
9
+ def gather_parameter_templates
10
+ # @type self: Normalizer
11
+ @parameter_templates = {} #: Hash[String, Array[Frontend::AST::Rule]]
12
+ @parameter_formals = {} #: Hash[String, Array[String]]
13
+ plain_rules = {} #: Hash[String, Frontend::AST::Rule]
14
+ @rule_documentation = validated_rule_documentation
15
+
16
+ @ast.rules.each do |rule|
17
+ if parameterized_rule?(rule)
18
+ gather_parameterized_rule(rule, plain_rules)
19
+ else
20
+ reject_mixed_parameterized_rule(rule) if @parameter_templates.key?(rule.lhs)
21
+ plain_rules[rule.lhs] ||= rule
22
+ end
23
+ end
24
+ validate_parameter_terminal_collisions
25
+ @ast.rules.each { |rule| validate_parameter_references(rule) }
26
+ end
27
+
28
+ # @rbs (Frontend::AST::Rule rule, Hash[String, Frontend::AST::Rule] plain_rules) -> void
29
+ def gather_parameterized_rule(rule, plain_rules)
30
+ # @type self: Normalizer
31
+ reject_mixed_parameterized_rule(rule) if plain_rules.key?(rule.lhs)
32
+ duplicate = rule.parameters.tally.find { |_name, count| count > 1 }&.first
33
+ fail_at(rule.loc, "duplicate parameter #{duplicate} in rule #{rule.lhs}") if duplicate
34
+
35
+ validate_parameter_formals(rule)
36
+ @parameter_formals[rule.lhs] ||= rule.parameters
37
+ (@parameter_templates[rule.lhs] ||= Array.new(0)) << rule
38
+ end
39
+
40
+ # @rbs (Frontend::AST::Rule rule) -> void
41
+ def validate_parameter_formals(rule)
42
+ # @type self: Normalizer
43
+ expected = @parameter_formals[rule.lhs]
44
+ return unless expected && expected != rule.parameters
45
+
46
+ fail_at(
47
+ rule.loc,
48
+ "parameterized rule #{rule.lhs} uses inconsistent parameters " \
49
+ "(expected #{expected.join(', ')}, got #{rule.parameters.join(', ')})"
50
+ )
51
+ end
52
+
53
+ # @rbs (Frontend::AST::Rule rule) -> bot
54
+ def reject_mixed_parameterized_rule(rule)
55
+ # @type self: Normalizer
56
+ fail_at(rule.loc, "rule #{rule.lhs} has both plain and parameterized definitions")
57
+ end
58
+
59
+ # @rbs () -> void
60
+ def validate_parameter_terminal_collisions
61
+ # @type self: Normalizer
62
+ @parameter_templates.each do |name, rules|
63
+ next unless @declared_tokens.key?(name) || @precedence.key?(name)
64
+
65
+ fail_at(rules.fetch(0).loc, "parameterized rule #{name} collides with terminal #{name}")
66
+ end
67
+ end
68
+
69
+ # @rbs (Frontend::AST::Rule rule) -> void
70
+ def validate_parameter_references(rule)
71
+ # @type self: Normalizer
72
+ rule.alternatives.each do |alternative|
73
+ alternative.items.each do |item|
74
+ validate_parameter_item(item, rule.parameters, inside_argument: false)
75
+ end
76
+ end
77
+ end
78
+
79
+ # @rbs (Frontend::AST::item item, Array[String] formals, inside_argument: bool) -> void
80
+ def validate_parameter_item(item, formals, inside_argument:)
81
+ # @type self: Normalizer
82
+ case item
83
+ when Frontend::AST::ParameterizedReference
84
+ validate_parameterized_item(item, formals, inside_argument: inside_argument)
85
+ when Frontend::AST::SymbolReference
86
+ reject_argument_named_reference(item) if inside_argument && item.named_reference
87
+ when Frontend::AST::Group
88
+ item.alternatives.flatten.each do |child|
89
+ validate_parameter_item(child, formals, inside_argument: inside_argument)
90
+ end
91
+ when Frontend::AST::Optional, Frontend::AST::Star, Frontend::AST::Plus
92
+ validate_parameter_item(item.item, formals, inside_argument: inside_argument)
93
+ when Frontend::AST::SeparatedList
94
+ validate_parameter_item(item.item, formals, inside_argument: inside_argument)
95
+ validate_parameter_item(item.separator, formals, inside_argument: inside_argument)
96
+ end
97
+ end
98
+
99
+ # @rbs (Frontend::AST::ParameterizedReference item, Array[String] formals, inside_argument: bool) -> void
100
+ def validate_parameterized_item(item, formals, inside_argument:)
101
+ # @type self: Normalizer
102
+ if formals.include?(item.name)
103
+ fail_at(item.loc, "formal #{item.name} cannot be used as a parameterized rule name")
104
+ end
105
+ validate_parameter_call(item)
106
+ reject_argument_named_reference(item) if inside_argument && item.named_reference
107
+ item.arguments.each { |argument| validate_parameter_item(argument, formals, inside_argument: true) }
108
+ end
109
+
110
+ # @rbs (Frontend::AST::SymbolReference | Frontend::AST::ParameterizedReference item) -> bot
111
+ def reject_argument_named_reference(item)
112
+ # @type self: Normalizer
113
+ fail_at(item.loc, "named references are not allowed in parameter arguments")
114
+ end
115
+
116
+ # @rbs (Frontend::AST::ParameterizedReference reference) -> void
117
+ def validate_parameter_call(reference)
118
+ # @type self: Normalizer
119
+ formals = @parameter_formals[reference.name]
120
+ fail_at(reference.loc, "undefined parameterized rule #{reference.name}") unless formals
121
+ return if reference.arguments.length == formals.length
122
+
123
+ fail_at(
124
+ reference.loc,
125
+ "parameterized rule #{reference.name} expects #{formals.length} arguments, " \
126
+ "got #{reference.arguments.length}"
127
+ )
128
+ end
129
+
130
+ # @rbs (Frontend::AST::Rule rule) -> bool
131
+ def parameterized_rule?(rule)
132
+ !rule.parameters.empty?
133
+ end
134
+
135
+ # @rbs (String name) -> bool
136
+ def parameter_template?(name)
137
+ @parameter_templates.key?(name)
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,226 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibex
4
+ # Iterative, hygienic specialization of validated parameterized user rules.
5
+ # rubocop:disable Metrics/ModuleLength -- parameter-frame transitions are kept together for auditability.
6
+ module NormalizeParameters
7
+ # @rbs!
8
+ # type parameter_operation =
9
+ # [:item | :finish_item, Frontend::AST::item] |
10
+ # [:value, String] |
11
+ # [:finish_suffix, Frontend::AST::Optional | Frontend::AST::Star | Frontend::AST::Plus] |
12
+ # [:finish_separated, Frontend::AST::SeparatedList] |
13
+ # [:group_alternative, String, Frontend::AST::Group, Array[Frontend::AST::item]] |
14
+ # [:finish_group_alternative, String, Frontend::AST::Group, Integer]
15
+ # type parameter_frame = {
16
+ # reference: Frontend::AST::ParameterizedReference,
17
+ # arguments: Array[Frontend::AST::item],
18
+ # helper: String,
19
+ # bindings: Hash[String, Frontend::AST::item],
20
+ # rendered_arguments: Array[String],
21
+ # templates: Array[Frontend::AST::Rule],
22
+ # template_index: Integer,
23
+ # alternative_index: Integer,
24
+ # current: [Frontend::AST::Rule, Frontend::AST::Rule, Frontend::AST::Alternative]?,
25
+ # item_index: Integer,
26
+ # rhs: Array[String],
27
+ # named_refs: Array[IR::named_ref],
28
+ # operations: Array[parameter_operation],
29
+ # values: Array[String]
30
+ # }
31
+
32
+ private
33
+
34
+ # @rbs (Frontend::AST::ParameterizedReference reference) -> String
35
+ def specialize_parameterized_reference(reference)
36
+ # @type self: Normalizer
37
+ helper, scheduled = schedule_parameter_specialization(reference)
38
+ if scheduled && @parameter_worklist_active
39
+ raise Ibex::Error, "#{reference.loc}: internal parameter worklist ordering failure"
40
+ end
41
+
42
+ drain_parameter_worklist unless @parameter_worklist_active
43
+ helper
44
+ end
45
+
46
+ # @rbs (Frontend::AST::ParameterizedReference reference) -> [String, bool]
47
+ def schedule_parameter_specialization(reference)
48
+ # @type self: Normalizer
49
+ arguments = reference.arguments
50
+ rendered_arguments = arguments.map { |argument| NormalizeExpression.render(argument) }
51
+ key = [reference.name, rendered_arguments] #: [String, Array[String]]
52
+ existing = @parameter_specializations[key]
53
+ return [existing, false] if existing
54
+
55
+ enforce_parameter_limits!(reference)
56
+ helper = new_parameter_helper(reference)
57
+ @parameter_specializations[key] = helper
58
+ @parameter_worklist << parameter_frame(reference, helper, arguments, rendered_arguments)
59
+ [helper, true]
60
+ end
61
+
62
+ # @rbs (Frontend::AST::ParameterizedReference reference) -> void
63
+ def enforce_parameter_limits!(reference)
64
+ # @type self: Normalizer
65
+ cyclic = @parameter_worklist.reverse.find do |frame|
66
+ frame.fetch(:reference).name == reference.name &&
67
+ growing_parameter_arguments?(reference.arguments, frame.fetch(:arguments))
68
+ end
69
+ if cyclic
70
+ path = (@parameter_worklist.drop_while { |frame| frame != cyclic } + [{ reference: reference }])
71
+ .map { |frame| frame.fetch(:reference).name }
72
+ fail_at(reference.loc, "cyclic parameter specialization #{path.join(' -> ')}")
73
+ end
74
+ return unless @parameter_specializations.length >= @max_parameter_specializations
75
+
76
+ fail_at(
77
+ reference.loc,
78
+ "parameter specialization limit of #{@max_parameter_specializations} exceeded"
79
+ )
80
+ end
81
+
82
+ # A constructor-growing recursive call can create infinitely many distinct
83
+ # specializations. Calls whose arguments shrink or merely change are
84
+ # allowed; they may reach a memoized fixed point after finite expansion.
85
+ # @rbs (Array[Frontend::AST::item] candidates, Array[Frontend::AST::item] ancestors) -> bool
86
+ def growing_parameter_arguments?(candidates, ancestors)
87
+ return false unless candidates.length == ancestors.length
88
+
89
+ contained = candidates.each_index.all? do |index|
90
+ candidate = candidates.fetch(index)
91
+ ancestor = ancestors.fetch(index)
92
+ parameter_argument_contains?(candidate, NormalizeExpression.render(ancestor))
93
+ end
94
+ contained && candidates.each_index.any? do |index|
95
+ candidate = candidates.fetch(index)
96
+ ancestor = ancestors.fetch(index)
97
+ NormalizeExpression.render(candidate) != NormalizeExpression.render(ancestor)
98
+ end
99
+ end
100
+
101
+ # @rbs (Frontend::AST::item candidate, String target) -> bool
102
+ def parameter_argument_contains?(candidate, target)
103
+ pending = [candidate] #: Array[Frontend::AST::item]
104
+ until pending.empty?
105
+ item = pending.pop
106
+ raise Ibex::Error, "missing parameter argument" unless item
107
+
108
+ return true if NormalizeExpression.render(item) == target
109
+
110
+ case item
111
+ when Frontend::AST::ParameterizedReference then pending.concat(item.arguments)
112
+ when Frontend::AST::Group then item.alternatives.each { |alternative| pending.concat(alternative) }
113
+ when Frontend::AST::Optional, Frontend::AST::Star, Frontend::AST::Plus then pending << item.item
114
+ when Frontend::AST::SeparatedList then pending.push(item.item, item.separator)
115
+ end
116
+ end
117
+ false
118
+ end
119
+
120
+ # @rbs (Frontend::AST::ParameterizedReference reference) -> String
121
+ def new_parameter_helper(reference)
122
+ # @type self: Normalizer
123
+ @helper_sequence += 1
124
+ name = "$parameter_#{@helper_sequence}"
125
+ definition = intern(
126
+ name, :nonterminal,
127
+ location: reference.loc.to_h,
128
+ documentation: @rule_documentation[reference.name],
129
+ metadata_name: reference.name
130
+ )
131
+ if @inline_rule_names.include?(reference.name)
132
+ @inline_symbol_ids << definition.id
133
+ @inline_rule_by_symbol[definition.id] = reference.name
134
+ end
135
+ name
136
+ end
137
+
138
+ # @rbs (Frontend::AST::ParameterizedReference reference, String helper,
139
+ # Array[Frontend::AST::item] arguments, Array[String] rendered_arguments) ->
140
+ # NormalizeParameters::parameter_frame
141
+ def parameter_frame(reference, helper, arguments, rendered_arguments)
142
+ # @type self: Normalizer
143
+ formals = @parameter_formals.fetch(reference.name)
144
+ {
145
+ reference: reference,
146
+ arguments: arguments,
147
+ helper: helper,
148
+ bindings: formals.zip(arguments).to_h,
149
+ rendered_arguments: rendered_arguments,
150
+ templates: @parameter_templates.fetch(reference.name),
151
+ template_index: 0,
152
+ alternative_index: 0,
153
+ current: nil,
154
+ item_index: 0,
155
+ rhs: [],
156
+ named_refs: [],
157
+ operations: [],
158
+ values: []
159
+ }
160
+ end
161
+
162
+ # @rbs () -> void
163
+ def drain_parameter_worklist
164
+ # @type self: Normalizer
165
+ @parameter_worklist_active = true
166
+ until @parameter_worklist.empty?
167
+ frame = @parameter_worklist.last
168
+ unless frame[:current] || prepare_parameter_alternative?(frame)
169
+ @parameter_worklist.pop
170
+ next
171
+ end
172
+
173
+ advance_parameter_alternative(frame)
174
+ end
175
+ ensure
176
+ @parameter_worklist_active = false
177
+ end
178
+
179
+ # @rbs (NormalizeParameters::parameter_frame frame) -> bool
180
+ def prepare_parameter_alternative?(frame)
181
+ # @type self: Normalizer
182
+ templates = frame.fetch(:templates)
183
+ while frame.fetch(:template_index) < templates.length
184
+ template = templates.fetch(frame.fetch(:template_index))
185
+ index = frame.fetch(:alternative_index)
186
+ if index < template.alternatives.length
187
+ prepare_parameter_alternative_entry(frame, template, index)
188
+ return true
189
+ end
190
+ frame[:template_index] += 1
191
+ frame[:alternative_index] = 0
192
+ end
193
+ false
194
+ end
195
+
196
+ # @rbs (NormalizeParameters::parameter_frame frame, Frontend::AST::Rule template, Integer index) -> void
197
+ def prepare_parameter_alternative_entry(frame, template, index)
198
+ # @type self: Normalizer
199
+ alternative = substitute_parameter_alternative(
200
+ template.alternatives.fetch(index), frame.fetch(:bindings)
201
+ )
202
+ rule = Frontend::AST::Rule.new(
203
+ lhs: frame.fetch(:helper), parameters: [], alternatives: [alternative], loc: template.loc,
204
+ documentation: template.documentation, inline: false
205
+ )
206
+ frame[:alternative_index] = index + 1
207
+ frame[:current] = [template, rule, alternative]
208
+ frame[:item_index] = 0
209
+ frame[:rhs] = []
210
+ frame[:named_refs] = []
211
+ frame[:operations] = []
212
+ frame[:values] = []
213
+ end
214
+
215
+ # @rbs (NormalizeParameters::parameter_frame frame) -> void
216
+ def clear_parameter_alternative(frame)
217
+ frame[:current] = nil
218
+ frame[:item_index] = 0
219
+ frame[:rhs] = []
220
+ frame[:named_refs] = []
221
+ frame[:operations] = []
222
+ frame[:values] = []
223
+ end
224
+ end
225
+ # rubocop:enable Metrics/ModuleLength
226
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibex
4
+ # Converts a root parser declaration into the explicit current Grammar IR contract.
5
+ module NormalizeParserConfiguration
6
+ private
7
+
8
+ # @rbs (Frontend::AST::ParserConfiguration declaration) -> void
9
+ def read_parser_configuration(declaration)
10
+ # @type self: Normalizer
11
+ fail_at(declaration.loc, "parser declarations require extended mode") unless @mode == :extended
12
+ fail_at(declaration.loc, "duplicate parser declaration") if @parser_configuration
13
+
14
+ @parser_configuration = declaration
15
+ end
16
+
17
+ # @rbs () -> IR::ParserContract?
18
+ def normalized_parser_contract
19
+ # @type self: Normalizer
20
+ declaration = @parser_configuration
21
+ return unless declaration
22
+
23
+ entries = {} #: Hash[Symbol, IR::ParserContract::Entry]
24
+ declaration.settings.each do |setting|
25
+ validated_parser_setting_definition(setting)
26
+ fail_at(setting.loc, "duplicate parser setting #{setting.key}") if entries.key?(setting.key)
27
+
28
+ if setting.key == :cst_trivia && @options[:cst] != true
29
+ fail_at(setting.loc, "parser.cst_trivia requires pragma cst")
30
+ end
31
+
32
+ entries[setting.key] = IR::ParserContract::Entry.new(
33
+ setting.key, value: setting.value, location: parser_setting_location(setting), explicit: true
34
+ )
35
+ end
36
+ validate_isolated_entries(declaration)
37
+ IR::ParserContract.new(**entries)
38
+ end
39
+
40
+ # @rbs (Frontend::AST::ParserSetting setting) -> Hash[Symbol, Object?]
41
+ def validated_parser_setting_definition(setting)
42
+ # @type self: Normalizer
43
+ definition = IR::ParserContract::DEFINITIONS[setting.key]
44
+ unless %i[algorithm entries cst_trivia].include?(setting.key) && definition
45
+ fail_at(setting.loc, "unknown parser setting #{setting.key}")
46
+ end
47
+ unless definition.fetch(:values).include?(setting.value)
48
+ allowed = definition.fetch(:values).join(", ")
49
+ fail_at(setting.loc, "parser.#{setting.key} must be one of #{allowed}; got #{setting.value}")
50
+ end
51
+ definition
52
+ end
53
+
54
+ # @rbs (Frontend::AST::ParserConfiguration declaration) -> void
55
+ def validate_isolated_entries(declaration)
56
+ # @type self: Normalizer
57
+ setting = declaration.settings.find { |candidate| candidate.key == :entries && candidate.value == :isolated }
58
+ return unless setting && @start_names.length < 2
59
+
60
+ fail_at(setting.loc, "parser.entries isolated requires at least two start symbols")
61
+ end
62
+
63
+ # @rbs (Frontend::AST::ParserSetting setting) -> Location
64
+ def parser_setting_location(setting)
65
+ # @type self: Normalizer
66
+ location = setting.loc
67
+ Location.new(file: location.file, line: location.line, column: location.column)
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibex
4
+ # Recovery declaration extraction and post-interning symbol validation.
5
+ module NormalizeRecoveryDeclarations
6
+ private
7
+
8
+ # @rbs (Frontend::AST::Start | Frontend::AST::Recovery | Frontend::AST::OnErrorReduce |
9
+ # Frontend::AST::GrammarTest declaration) -> void
10
+ def read_parser_control_declaration(declaration)
11
+ # @type self: Normalizer
12
+ case declaration
13
+ when Frontend::AST::Start then read_start_declaration(declaration)
14
+ when Frontend::AST::Recovery then read_recovery_declaration(declaration)
15
+ when Frontend::AST::OnErrorReduce then read_on_error_reduce_declaration(declaration)
16
+ when Frontend::AST::GrammarTest then read_grammar_test(declaration)
17
+ end
18
+ end
19
+
20
+ # @rbs (Frontend::AST::GrammarTest declaration) -> void
21
+ def read_grammar_test(declaration)
22
+ # @type self: Normalizer
23
+ fail_at(declaration.loc, "%test requires extended mode") unless @mode == :extended
24
+ unless %i[accept reject].include?(declaration.expectation)
25
+ fail_at(declaration.loc, "unknown %test expectation #{declaration.expectation.inspect}")
26
+ end
27
+ if @grammar_tests.any? do |test|
28
+ test[:expectation] == declaration.expectation && test[:source] == declaration.source
29
+ end
30
+ fail_at(declaration.loc, "duplicate %test #{declaration.expectation} source")
31
+ end
32
+
33
+ @grammar_tests << {
34
+ expectation: declaration.expectation,
35
+ source: declaration.source,
36
+ loc: declaration.loc.to_h
37
+ }
38
+ end
39
+
40
+ # @rbs (Frontend::AST::Recovery declaration) -> void
41
+ def read_recovery_declaration(declaration)
42
+ # @type self: Normalizer
43
+ fail_at(declaration.loc, "duplicate %recover declaration") if @recovery_sync_location
44
+ fail_at(declaration.loc, "%recover sync requires at least one token") if declaration.sync_tokens.empty?
45
+ unless declaration.sync_tokens.uniq.length == declaration.sync_tokens.length
46
+ fail_at(declaration.loc, "%recover sync tokens must be unique")
47
+ end
48
+
49
+ @recovery_sync_tokens = declaration.sync_tokens
50
+ @recovery_sync_location = declaration.loc
51
+ end
52
+
53
+ # @rbs (Frontend::AST::OnErrorReduce declaration) -> void
54
+ def read_on_error_reduce_declaration(declaration)
55
+ # @type self: Normalizer
56
+ fail_at(declaration.loc, "%on_error_reduce requires at least one nonterminal") if declaration.names.empty?
57
+ declaration.names.each do |name|
58
+ fail_at(declaration.loc, "duplicate %on_error_reduce symbol #{name}") if
59
+ @on_error_reduce_locations.key?(name)
60
+
61
+ @on_error_reduce_locations[name] = declaration.loc
62
+ end
63
+ @on_error_reduce_groups << declaration.names
64
+ end
65
+
66
+ # @rbs () -> void
67
+ def validate_recovery_declarations
68
+ # @type self: Normalizer
69
+ @recovery_sync_tokens.each do |name|
70
+ definition = @symbols_by_name[name]
71
+ unless definition&.terminal? && definition.name != "error"
72
+ fail_at(@recovery_sync_location || @ast.loc, "%recover sync references nonterminal or missing token #{name}")
73
+ end
74
+ end
75
+ @on_error_reduce_groups.flatten.each do |name|
76
+ definition = @symbols_by_name[name]
77
+ unless definition&.nonterminal?
78
+ location = @on_error_reduce_locations.fetch(name)
79
+ fail_at(location, "%on_error_reduce references terminal or missing nonterminal #{name}")
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end