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,106 @@
1
+ # CST Red/Green migration
2
+
3
+ The runtime supports only the current format-v6 Red/Green representation for
4
+ `pragma cst`. CST parser tables from formats v1 through v5, boolean
5
+ `cst: true` tables without structured metadata, and all v1-v5 non-CST tables
6
+ fail before the first token is read and instruct the application to regenerate.
7
+
8
+ Regenerate with the same command used for the grammar, for example:
9
+
10
+ ```sh
11
+ ibex grammar.y -o parser.rb
12
+ ```
13
+
14
+ Upgrade the generator and runtime together, regenerate the parser, and update
15
+ consumers to the current APIs below. The removed `CST::Trivia`, `CST::Token`,
16
+ `CST::Missing`, `CST::Error`, and `CST::Node` constants are not defined.
17
+
18
+ ## Parsing
19
+
20
+ Use `parse_with_syntax` when both the semantic result and syntax are needed:
21
+
22
+ ```ruby
23
+ result = parser.parse_with_syntax(source, file: "input.txt")
24
+ value = result.value
25
+ root = result.syntax_root
26
+ diagnostics = result.diagnostics
27
+ ```
28
+
29
+ `parse`, `do_parse`, and `yyparse` keep returning the semantic result. After a
30
+ CST parse, `syntax_root` exposes the most recently built Red root.
31
+
32
+ ## Changed tree shape
33
+
34
+ The new root is always `source_file`:
35
+
36
+ ```text
37
+ source_file
38
+ ├── selected start-symbol node
39
+ └── $eof
40
+ ```
41
+
42
+ The EOF token owns final trivia. Code that previously treated the returned CST
43
+ as the start node should use `result.syntax_root.children.fetch(0)`.
44
+
45
+ The legacy implementation exposed semantic values inside an actionless
46
+ parent. For example, an action-bearing `term` could appear as a `CST::Token`
47
+ whose symbol was `"term"` and whose value was the action result. Format v6
48
+ always exposes the physical `term` syntax node in that position. Read the
49
+ semantic result from `result.value`; syntax children never contain semantic
50
+ values.
51
+
52
+ These are the primary incompatible shapes found by the migration
53
+ characterization suite. `deconstruct` continues to return syntax children and
54
+ `deconstruct_keys` retains the compatibility keys. Typed field keys are added
55
+ from `@node` slot metadata.
56
+
57
+ ## Removed public API mapping
58
+
59
+ The inventory below records the removed values and their format-v6
60
+ replacements.
61
+
62
+ | Removed value and members | Previous use | Format-v6 replacement |
63
+ | --- | --- | --- |
64
+ | `CST::Trivia#text`, `#location`, `#to_h` | leading/trailing trivia assertions | `GreenTrivia#text` and `#kind`; obtain absolute location from the owning Red token |
65
+ | `CST::Token#symbol`, `#value`, `#location`, `#leading_trivia` | terminal names, lexer action values, positions, skipped text | `SyntaxToken#kind_name`/`#symbol`, `#location`, and `#leading_trivia`; compatibility `#value` returns the same source bytes as `#text`, while semantic lexer values stay in the normal action/value path |
66
+ | `CST::Token#kind`, `#children`, `#deconstruct`, `#deconstruct_keys`, `#to_h` | error classification and pattern matching | integer `#kind`, `#error?`/`#missing?`, empty `#children`/`#deconstruct`, and compatibility pattern/hash keys |
67
+ | `CST::Missing` | bounded-repair insertion checks | `SyntaxToken#missing?`, `GreenToken#expected_kind`, and `CONTAINS_MISSING` |
68
+ | `CST::Error#reason` | lexical, syntax, delete, and discard checks | `SyntaxToken#error?`, `SyntaxNode#error?`, diagnostics, and Green error/skipped flags |
69
+ | `CST::Node#symbol`, `#production_id`, `#children`, `#location`, `#trailing_trivia` | root/reduction shape, source position, final trivia | `SyntaxNode#symbol`, `#children`, `#location`, and compatibility `#trailing_trivia`; `#production_id` is the `-1` sentinel because kinds/slot metadata replace occurrence-local production identity |
70
+ | `CST::Node#each`, `#deconstruct`, `#deconstruct_keys`, `#to_h`, `#with_trailing_trivia` | enumeration, pattern matching, final-trivia attachment | Red `Enumerable`/pattern/hash methods; persistent trivia changes use the owning token's `with_leading`/`with_trailing` |
71
+
72
+ Current pure-syntax shape and compatibility accessors are executable in
73
+ `test/codegen/cst_characterization_test.rb`. Rejection of obsolete CST table
74
+ shapes is covered by `test/runtime/table_format_test.rb` and
75
+ `test/codegen/cst_runtime_integration_test.rb`. The semantic-value removal is
76
+ the C1 change; the `source_file` root is C2.
77
+
78
+ ## Trivia
79
+
80
+ `--cst-trivia=attach` remains accepted and means `leading`.
81
+
82
+ - `leading`: skipped lexer text belongs to the next token.
83
+ - `balanced`: text through the first newline belongs to the preceding token,
84
+ with the remainder leading the next token.
85
+ - `drop`: trivia is omitted; source-coordinate and incremental APIs raise
86
+ because offsets no longer correspond to the original source.
87
+
88
+ Use `to_source` for a binary-exact reconstruction. On early `yyaccept`,
89
+ `incomplete_input?` is true and `to_source` is the consumed prefix.
90
+
91
+ ## Errors and repair
92
+
93
+ Lexical failures, yacc recovery, panic discards, and bounded repair return a
94
+ syntax result rather than changing the semantic action contract. Inspect
95
+ `diagnostics`, `contains_error?`, `each_error`, missing tokens, and Green flags
96
+ for skipped input. Unrecoverable input is retained under `synthetic_root`.
97
+
98
+ ## New capabilities
99
+
100
+ Format v6 provides typed `Parser::Syntax` views, persistent
101
+ path-copy editing, annotations, structural text diffing, `ibex_cst` v1
102
+ serialization, and syntax-only incremental sessions. These APIs have no
103
+ equivalent on the removed mixed semantic/syntax tree. Batch CST, views,
104
+ editing, and serialization are Stable; incremental sessions remain
105
+ Experimental. See the [CST guide](cst.md) for examples and the incremental
106
+ action contract.
data/docs/cst.md ADDED
@@ -0,0 +1,237 @@
1
+ ---
2
+ title: Concrete syntax trees
3
+ description: Lossless Red/Green CSTs, typed views, editing, and incremental session boundaries.
4
+ ---
5
+
6
+ # Red/Green concrete syntax trees
7
+
8
+ <!-- stable:batch-cst:v1 -->
9
+
10
+ `pragma cst` generates a lossless, error-tolerant syntax tree alongside the
11
+ ordinary semantic result. Regenerate the parser with the current generator to
12
+ receive parser-table format v6 and this API. Batch parsing, typed views,
13
+ editing, diffing, and `ibex_cst` serialization are Stable for v1; syntax-only
14
+ incremental sessions are Experimental.
15
+
16
+ ```text
17
+ class Calculator
18
+ pragma cst
19
+ token NUM PLUS
20
+ lexer
21
+ skip /[[:space:]]+/
22
+ NUM /[0-9]+/ { lexeme.to_i }
23
+ PLUS '+'
24
+ end
25
+ rule
26
+ start: expression
27
+ expression: NUM PLUS NUM @node Addition(left, operator, right)
28
+ end
29
+ ```
30
+
31
+ ## Parsing and tree shape
32
+
33
+ `parse_with_syntax` runs semantic actions normally and returns both results:
34
+
35
+ ```ruby
36
+ result = Calculator.new.parse_with_syntax("1 + 2", file: "input.txt")
37
+ value = result.value
38
+ root = result.syntax_root
39
+ diagnostics = result.diagnostics
40
+ ```
41
+
42
+ This is a trusted application runtime path. Parser production actions and
43
+ generated lexer actions execute, and loading the generated Ruby file may run
44
+ `header`, `inner`, or `footer` code. `parse_with_syntax` is not a sandbox.
45
+
46
+ `parse`, `do_parse`, and `yyparse` keep their semantic return values.
47
+ `parser.syntax_root` exposes the most recent syntax root. Every successful root
48
+ has this physical shape:
49
+
50
+ ```text
51
+ source_file
52
+ ├── selected start-symbol node
53
+ └── $eof
54
+ ```
55
+
56
+ The immutable Green layer stores kind ids, source bytes, trivia, flags, widths,
57
+ and children without parents or absolute positions. It is Ractor-shareable.
58
+ The Red `SyntaxNode`/`SyntaxToken` layer adds lazy parent, child-index, offset,
59
+ span, and location navigation for one occurrence. Equal Green values can
60
+ therefore appear at several positions without sharing Red coordinates.
61
+
62
+ `root.to_source` reconstructs the consumed bytes exactly. Early `yyaccept`
63
+ marks `root.incomplete_input?` and reconstructs the consumed prefix.
64
+
65
+ ## Trivia and coordinates
66
+
67
+ Select trivia ownership while generating:
68
+
69
+ - `leading` owns skipped text on the following token;
70
+ - `balanced` owns text through the first newline on the preceding token and
71
+ the remainder on the following token;
72
+ - `drop` omits trivia.
73
+
74
+ Pass the policy explicitly when needed:
75
+
76
+ ```sh
77
+ ibex --cst-trivia=leading grammar.y
78
+ ibex --cst-trivia=balanced grammar.y
79
+ ibex --cst-trivia=drop grammar.y
80
+ ```
81
+
82
+ `attach` is accepted as an alias for `leading`. EOF owns final leading trivia.
83
+ `drop` trees deliberately reject span, location, and incremental APIs because
84
+ their offsets cannot describe the original source.
85
+
86
+ Spans are zero-based, half-open byte ranges. `SourceText#position` and
87
+ `#location` convert them to one-based Unicode-scalar lines and columns while
88
+ preserving byte offsets.
89
+
90
+ ## Typed syntax views
91
+
92
+ An `@node` annotation generates a view in `Parser::Syntax` without changing the
93
+ physical tree:
94
+
95
+ ```ruby
96
+ addition = Calculator::Syntax::Addition.cast(
97
+ result.syntax_root.children.fetch(0).children.fetch(0)
98
+ )
99
+ addition.left
100
+ addition.operator
101
+ addition.right
102
+ ```
103
+
104
+ Accessors use normalized physical RHS slots. Lowered repetitions add element
105
+ enumerators; separated lists also expose separators. These views are distinct
106
+ from generated `Parser::AST` Data values: syntax views retain punctuation and
107
+ trivia, while AST values are semantic-action results.
108
+
109
+ ## Errors and repair
110
+
111
+ Lexical failure, yacc recovery, panic discard, and bounded repair all produce a
112
+ tree. Inspect `diagnostics`, `contains_error?`, error nodes, missing tokens, and
113
+ Green flags. Inserted tokens are zero-width `missing_token` values. Discarded
114
+ input remains under error nodes or `skipped_tokens` trivia. An unrecoverable
115
+ parse uses `synthetic_root`.
116
+
117
+ ## Persistent editing and diffing
118
+
119
+ Editing returns a new Red root and path-copies only changed ancestors:
120
+
121
+ ```ruby
122
+ old_root = result.syntax_root
123
+ first = old_root.first_token
124
+ new_root = first.with_text("10")
125
+ edits = Ibex::Runtime::CST::Diff.text_edits(old_root, new_root)
126
+ new_source = old_root.source_text.apply(edits)
127
+ ```
128
+
129
+ Nodes support `replace_with`, `with_child`, `insert_child`, and `remove_child`.
130
+ Tokens support `replace_with`, `with_text`, `with_leading`, and
131
+ `with_trailing`. `SyntaxRewriter` performs bottom-up kind dispatch;
132
+ `SyntaxEditor` applies several occurrence-addressed replacements in one pass.
133
+ `SyntaxAnnotation` marks one occurrence and excludes annotated Green values
134
+ from interning.
135
+
136
+ ## Incremental syntax sessions
137
+
138
+ Incremental parsing is Experimental and deliberately syntax-only:
139
+
140
+ ```ruby
141
+ source = Ibex::Runtime::CST::SourceText.new("1 + 2", file: "input.txt")
142
+ session = Calculator.incremental_session(source)
143
+ result = session.edit([
144
+ Ibex::Runtime::CST::TextEdit.new(
145
+ start: 4,
146
+ delete_length: 1,
147
+ insert_text: "3"
148
+ )
149
+ ])
150
+ ```
151
+
152
+ The initial parse and every edit suppress parser production actions.
153
+ `SyntaxResult` therefore has `syntax_root`, `diagnostics`, and `reused_ratio`,
154
+ but no semantic value. Generated lexer actions still run because they define
155
+ token emission and lexer-state changes. Run a normal parse separately when a
156
+ semantic value or side effect is required.
157
+
158
+ Consequently, `parse_syntax` and `incremental_session` are syntax-only but not
159
+ "no user code" APIs. Loading the generated class may execute user sections,
160
+ and lexer actions may perform arbitrary Ruby side effects. Treat the generated
161
+ class as trusted application code. A future nonexecuting syntax profile would
162
+ require a declarative built-in-only lexer and no `header`, `inner`, or `footer`
163
+ sections; the current API does not provide that profile.
164
+
165
+ Sessions require `SourceText`, a generated lexer, format-v6 CST metadata, and
166
+ non-`drop` trivia. Handwritten token sources and push input are unsupported.
167
+ Parser actions that alone switch lexer state are also unavailable because the
168
+ syntax-only contract forbids executing them.
169
+
170
+ The default Stage B path relexes soundly from the beginning, validates old
171
+ token boundaries/states, and directly reuses only subtrees whose LR state,
172
+ follow token, flags, width, and damage range are safe. Pass `blender: false` to
173
+ retain the Stage A full LR drive. `ResourceLimits` bounds decomposition and
174
+ memo bytes; a bound failure deterministically falls back to the fresh token
175
+ stream. Observe `cst_built`, `cst_reuse`, and `cst_fallback` runtime events for
176
+ metrics.
177
+
178
+ Applications that need an explicit generated-language service boundary can use
179
+ the Experimental [`syntax_session` façade](syntax-sessions.md). It adds
180
+ trust-profile acknowledgement, immutable operation snapshots, expected tokens,
181
+ reuse/fallback metrics, cancellation, and service resource bounds while using
182
+ this same incremental engine. It does not add LSP or workspace semantics.
183
+
184
+ ## Serialization
185
+
186
+ `ibex_cst` schema v1 is independent from Grammar IR:
187
+
188
+ ```ruby
189
+ tables = Calculator.parser_tables
190
+ json = Ibex::Runtime::CST::Serialize.dump(
191
+ session.result.syntax_root,
192
+ grammar_digest: tables.fetch(:grammar_digest),
193
+ table_format: tables.fetch(:format_version),
194
+ state_count: tables.fetch(:state_count),
195
+ production_count: tables.fetch(:production_count),
196
+ memo: session.parse_memo
197
+ )
198
+ loaded = Ibex::Runtime::CST::Serialize.load(
199
+ json,
200
+ grammar_digest: tables.fetch(:grammar_digest),
201
+ state_count: tables.fetch(:state_count),
202
+ production_count: tables.fetch(:production_count)
203
+ )
204
+ ```
205
+
206
+ Valid UTF-8 bytes use JSON strings; other bytes use canonical Base64 objects.
207
+ Loading rebuilds widths, aggregate flags, and descendant counts. A grammar
208
+ digest mismatch raises `ValidationError`. State or production count mismatch
209
+ silently discards only the optional parse memo. Annotations are session-local
210
+ and cannot be serialized.
211
+
212
+ ## Invariants and test coverage
213
+
214
+ The Red/Green contract is continuously exercised by the following repository
215
+ tests:
216
+
217
+ | Invariant | Automated evidence |
218
+ | --- | --- |
219
+ | I1 consumed-input fidelity | `test/runtime/cst_fidelity_property_test.rb` is PT1 over random grammars and valid, lexical-error, recovery, repair, and early-accept inputs; `test/fixtures/cst/runtime-paths-v1.json` fixes every error/trivia path, including long unmatched remainders and repair deletion. |
220
+ | I2 Green purity | `test/runtime/cst_green_test.rb` checks derived-only immutable state and Ractor shareability; `test/codegen/cst_characterization_test.rb` keeps semantic values outside syntax children. |
221
+ | I3 lazy Red navigation | `test/runtime/cst_red_test.rb` checks occurrence-local memoization, offsets, parents, cursors, and deterministic traversal. |
222
+ | I4 determinism | PT3 in `test/runtime/cst_green_test.rb` compares cache-on/off structure, source, and dump; PT6 in `test/runtime/cst_serialize_test.rb` checks byte-stable dump/load/dump; generated Ruby and RBS have golden tests. |
223
+ | I5 unchanged action contract | `test/codegen/cst_contract_test.rb` compares CST/no-CST `parse`, `do_parse`, `yyparse`, hooks, observer order, and non-CST table shape; characterization and obsolete-CST-table rejection regressions remain active. |
224
+ | I6 sharing boundary | PT5 in `test/runtime/cst_green_test.rb` checks Green shareability and concurrent Ractor reads; editing and parser-table tests keep Red/session state occurrence-owned. |
225
+ | I7 versioned contracts | `test/runtime/cst_serialize_test.rb`, `test/runtime/table_format_test.rb`, and `test/packaging/schema_files_test.rb` cover schema validation, memo compatibility, old table readers, and schema packaging. |
226
+ | I8 type soundness | CI regenerates the `sig/` tree, runs Steep and RBS validation, and rejects a type-statistics regression. |
227
+
228
+ `test/runtime/cst_incremental_property_test.rb` is the large PT2 authority. Its
229
+ fixed seed generates four grammar shapes and executes 20,000 random edits
230
+ through Stage A plus 20,000 through Stage B, comparing fresh syntax sessions in
231
+ Green structure, bytes, flags, diagnostics, and memo cardinality after every
232
+ edit. `test/runtime/cst_incremental_test.rb` adds focused stateful-lexer,
233
+ fallback, sharing, minimal-diff, action-suppression, no-value, and unsupported
234
+ configuration cases.
235
+
236
+ See [the migration guide](cst-migration.md) for removed tree-shape changes and
237
+ [the stability policy](stability.md) for support levels.
@@ -0,0 +1,24 @@
1
+ # ADR NNNN: Implementation decision title
2
+
3
+ - Status: Proposed
4
+ - Date: YYYY-MM-DD
5
+
6
+ ## Context
7
+
8
+ Describe the concrete implementation question and its compatibility, data,
9
+ runtime, or component constraints. Operational workflow and release policy do
10
+ not belong in this directory; see [the scope](README.md).
11
+
12
+ Name the credible alternatives. If there was no meaningful alternative, record
13
+ the behavior in reference documentation instead of creating an ADR.
14
+
15
+ ## Decision
16
+
17
+ Describe the durable boundary or architecture choice. Leave command syntax,
18
+ field-by-field formats, test evidence, benchmark results, and migration steps
19
+ in their authoritative documents.
20
+
21
+ ## Consequences
22
+
23
+ Describe the important positive and negative trade-offs, including what would
24
+ make this decision worth revisiting.
@@ -0,0 +1,34 @@
1
+ # ADR 0001: Separate pipeline stages with current IR
2
+
3
+ - Status: Accepted
4
+ - Date: 2026-07-28
5
+
6
+ ## Context
7
+
8
+ Frontend parsing, normalization, automaton construction, and code generation
9
+ must be independently testable and resumable. Passing frontend objects between
10
+ all stages would couple later stages to source syntax and make serialized
11
+ artifacts ambiguous.
12
+
13
+ ## Decision
14
+
15
+ Normalization produces immutable Grammar IR. Parser construction consumes
16
+ Grammar IR and produces immutable Automaton IR. Automaton IR embeds the Grammar
17
+ IR required to resume code generation; later stages do not reach back into
18
+ frontend AST objects.
19
+
20
+ Both IRs have deterministic JSON encodings and shipped closed schemas. Their
21
+ current schema contract is explicit and validated. Untrusted JSON crosses a
22
+ validator that checks both shape and cross-record references before constructing
23
+ Ruby objects. A pre-v1 change that alters the meaning or required shape is
24
+ coordinated across writers, readers, schemas, fixtures, and downstream
25
+ consumers; no legacy reader is retained solely to preserve an obsolete format.
26
+
27
+ ## Consequences
28
+
29
+ - Source, resumed Grammar IR, and resumed Automaton IR use the same downstream
30
+ implementations.
31
+ - Incompatibility is detected at the document boundary rather than deep in
32
+ generation.
33
+ - Presentation views and operational reports are not additional IRs unless
34
+ another tool must consume them as durable data.
@@ -0,0 +1,32 @@
1
+ # ADR 0002: Keep grammar-embedded Ruby opaque until code generation
2
+
3
+ - Status: Accepted
4
+ - Date: 2026-07-28
5
+
6
+ ## Context
7
+
8
+ Semantic actions and user-code sections contain Ruby constructs whose braces,
9
+ quotes, regular expressions, interpolation, and heredocs overlap grammar
10
+ delimiters. Parsing Ruby in the grammar frontend would add a second language
11
+ implementation and would still not validate parser-local bindings correctly.
12
+
13
+ ## Decision
14
+
15
+ The grammar lexer delegates action bodies to a balanced source scanner. That
16
+ scanner recognizes only the Ruby lexical structure needed to find the matching
17
+ grammar boundary and preserves the original bytes and source location.
18
+ User-code sections are likewise retained as ordered opaque chunks.
19
+
20
+ The frontend, normalizer, IR tools, reports, and static analysis never evaluate
21
+ or rewrite the opaque body. Ruby compilation occurs only when generated parser
22
+ methods are loaded. Tools that promise not to execute application code must
23
+ operate entirely before that boundary.
24
+
25
+ ## Consequences
26
+
27
+ - Grammar parsing is independent of a Ruby parser and preserves exact user
28
+ source for mapping and generation.
29
+ - The balanced scanner has an explicit lexical coverage obligation; unsupported
30
+ Ruby syntax must fail instead of being silently truncated.
31
+ - Features that need meaning from an action must use conservative lexical
32
+ evidence or decline the optimization.
@@ -0,0 +1,32 @@
1
+ # ADR 0003: Self-host the grammar parser behind an explicit bootstrap
2
+
3
+ - Status: Accepted
4
+ - Date: 2026-07-28
5
+
6
+ ## Context
7
+
8
+ Keeping grammar syntax in a handwritten parser makes the generator unable to
9
+ exercise its own parser pipeline. Direct self-hosting creates a cycle because
10
+ the generated grammar parser is needed to regenerate itself.
11
+
12
+ ## Decision
13
+
14
+ `lib/ibex/frontend/grammar.y` is the canonical grammar syntax. Its generated
15
+ parser is committed and is the normal frontend implementation. A specialized
16
+ lexer remains outside that grammar because opaque Ruby scanning and source
17
+ locations are lexical responsibilities.
18
+
19
+ An explicitly named bootstrap parser exists only to regenerate the committed
20
+ parser when that parser is absent. The regeneration path loads the minimum
21
+ frontend and generation components directly and does not load the normal
22
+ generated frontend. Normal library loading does not use the bootstrap.
23
+
24
+ No racc implementation or racc-generated source participates in bootstrap or
25
+ normal execution.
26
+
27
+ ## Consequences
28
+
29
+ - Ordinary grammar parsing continuously exercises Ibex-generated code.
30
+ - Grammar syntax changes must keep the canonical grammar, bootstrap capability,
31
+ and generated parser deterministic and mutually consistent.
32
+ - The bootstrap is recovery infrastructure, not a second supported frontend.
@@ -0,0 +1,33 @@
1
+ # ADR 0004: Derive semantic and lossless source views from one lexing pass
2
+
3
+ - Status: Accepted
4
+ - Date: 2026-07-28
5
+
6
+ ## Context
7
+
8
+ Generation needs a semantic AST, while formatting, diagnostics, documentation,
9
+ and editor features need comments, trivia, opaque bodies, and exact byte
10
+ ranges. Re-lexing independently for each tool can disagree with the token
11
+ stream that defined grammar meaning.
12
+
13
+ ## Decision
14
+
15
+ One frontend lexing pass produces semantic tokens and immutable lossless
16
+ segments over the same UTF-8 source. A source document correlates those views
17
+ with half-open byte spans and reproduces the accepted input exactly. The
18
+ self-hosted parser remains the authority for the semantic AST.
19
+
20
+ Recovering diagnostics are bounded and may expose a clearly marked partial AST,
21
+ but never attach that projection to the unchanged source as if it were a
22
+ complete parse. Formatting changes trivia only, then reparses and rejects any
23
+ semantic difference. Filesystem and unsaved-buffer access are supplied through
24
+ an injected source loader; the parser itself performs no I/O.
25
+
26
+ ## Consequences
27
+
28
+ - Formatter, documentation, resolver, and LSP features share one interpretation
29
+ of tokens, opaque Ruby, locations, and source bytes.
30
+ - Exact byte coordinates remain distinct from editor-specific coordinate
31
+ encodings such as UTF-16.
32
+ - Error recovery and overlays are tool boundaries around the strict parser,
33
+ not alternative grammar semantics.
@@ -0,0 +1,34 @@
1
+ # ADR 0005: Resolve grammar composition in a contained filesystem boundary
2
+
3
+ - Status: Accepted
4
+ - Date: 2026-07-28
5
+
6
+ ## Context
7
+
8
+ Composing grammar fragments introduces file identity, traversal order, cycles,
9
+ diamonds, source provenance, and symlink escape. Textual concatenation loses
10
+ those properties and makes programmatic source parsing perform implicit I/O.
11
+
12
+ ## Decision
13
+
14
+ Root and fragment files have distinct syntax and ownership. Parsing records
15
+ `import` nodes without reading their targets. A resolver is the sole filesystem
16
+ boundary and returns one immutable resolution containing the merged AST,
17
+ canonical dependency closure, and include provenance.
18
+
19
+ Canonical real paths define identity. Imports are resolved in deterministic
20
+ depth-first order, a completed canonical file is merged once, and cycles are
21
+ reported by canonical path. Targets must remain below the canonical root
22
+ directory after symlink resolution; absolute paths, parent traversal, and
23
+ ambiguous path forms are rejected.
24
+
25
+ Every CLI and build integration that accepts a grammar path uses this resolver.
26
+ Programmatic source-string parsing must opt into it explicitly.
27
+
28
+ ## Consequences
29
+
30
+ - All consumers observe the same merge order and dependency closure.
31
+ - Diamonds are deterministic and symlink aliases cannot hide a cycle or escape
32
+ the root.
33
+ - Composition is intentionally a flat merge; namespaces and re-export policy
34
+ require a separate design.
@@ -0,0 +1,32 @@
1
+ # ADR 0006: Lower grammar extensions structurally and under explicit bounds
2
+
3
+ - Status: Accepted
4
+ - Date: 2026-07-28
5
+
6
+ ## Context
7
+
8
+ EBNF, parameterized rules, and inline rules can be represented as textual
9
+ macros, frontend-only closures, or structural transformations. Textual
10
+ expansion loses locations and can capture names; unbounded recursive expansion
11
+ can exhaust the Ruby stack or memory.
12
+
13
+ ## Decision
14
+
15
+ The frontend represents extensions as AST structure. Normalization lowers them
16
+ into ordinary symbols, productions, and serializable action-composition plans
17
+ before automaton construction. Synthetic names cannot collide with source
18
+ identifiers, and generated productions retain source and expansion provenance.
19
+
20
+ Parameterized specializations are memoized by structural arguments. Recursive
21
+ work uses explicit worklists, rejects structurally growing cycles, and has a
22
+ total specialization bound. Inline substitution rejects recursive dependency
23
+ cycles and has a separate materialization bound for alternative products.
24
+ Opaque action fragments remain ordered data in Grammar IR rather than
25
+ generator-only closures.
26
+
27
+ ## Consequences
28
+
29
+ - Every parser-construction algorithm consumes the same lowered Grammar IR.
30
+ - Resumed IR preserves extension semantics and source mapping.
31
+ - Some theoretically finite expansions may be rejected by conservative cycle
32
+ or resource bounds; callers can raise size bounds deliberately.
@@ -0,0 +1,33 @@
1
+ # ADR 0007: Share one downstream pipeline across parser algorithms
2
+
3
+ - Status: Accepted
4
+ - Date: 2026-07-28
5
+
6
+ ## Context
7
+
8
+ SLR, LALR, IELR, and canonical LR(1) differ in state construction and
9
+ lookahead precision. Separate conflict resolution, table generation, or code
10
+ generation paths would make algorithm selection change more than the automaton.
11
+
12
+ ## Decision
13
+
14
+ All algorithms consume Grammar IR and produce the same Automaton IR contract.
15
+ They share action candidate construction, conflict resolution, default-action
16
+ selection, reporting, table generation, and code generation.
17
+
18
+ LALR is the default and computes lookaheads directly over deterministic LR(0)
19
+ item occurrences. SLR uses the same LR(0) collection with FOLLOW sets.
20
+ Canonical LR(1) retains distinct contexts. IELR conservatively merges
21
+ compatible canonical states and prefers extra states whenever equivalence is
22
+ uncertain; it does not claim a minimum state count.
23
+
24
+ Reference strategies may remain for equivalence testing, but they are not
25
+ additional public algorithm identities when their output contract is the same.
26
+
27
+ ## Consequences
28
+
29
+ - Algorithm choice changes automaton precision without changing downstream
30
+ semantics or generated APIs.
31
+ - LALR avoids canonical state explosion in the default path.
32
+ - IELR can avoid LALR merge inadequacies but may pay canonical construction
33
+ cost and retain more states than a lane-tracing implementation.
@@ -0,0 +1,36 @@
1
+ # ADR 0008: Separate the runtime behind a versioned parser-table ABI
2
+
3
+ - Status: Accepted
4
+ - Date: 2026-07-28
5
+
6
+ ## Context
7
+
8
+ Applications executing a generated parser do not need the grammar frontend or
9
+ generator. Independently installed generated code and runtime code still need a
10
+ precise compatibility boundary; otherwise a table-shape change can fail or be
11
+ misinterpreted during a parse.
12
+
13
+ ## Decision
14
+
15
+ The dependency-free parser runtime ships as `ibex-runtime`; the generator
16
+ depends on it but runtime deployments do not depend on generator code. Normal
17
+ generated parsers require the runtime package, while embedded output carries
18
+ the same runtime implementation.
19
+
20
+ Every generated table declares a parser-table format version. The runtime
21
+ validates the version and marker combinations before consuming input. Changes
22
+ to required shape, action calling convention, or table meaning increment that
23
+ version.
24
+
25
+ Plain and compact tables are two encodings of the same lookup contract.
26
+ Compression may change representation only when every declared and unknown
27
+ token retains the same shift, reduce, accept, or error result. In particular,
28
+ explicit error cells must mask default reductions.
29
+
30
+ ## Consequences
31
+
32
+ - Generator and runtime packaging can evolve independently within the declared
33
+ dependency and table-format contracts.
34
+ - Unsupported generated parsers fail before lexer or semantic side effects.
35
+ - Compact representation remains replaceable and optimizable without becoming
36
+ a second parser semantics.
@@ -0,0 +1,34 @@
1
+ # ADR 0009: Isolate mutable parser sessions from immutable parser data
2
+
3
+ - Status: Accepted
4
+ - Date: 2026-07-28
5
+
6
+ ## Context
7
+
8
+ Generated tables are immutable program data, while LR stacks, lexer state,
9
+ lookahead, recovery state, observers, and incremental caches are per parse.
10
+ Supporting pull, yielding, and push input through separate engines would make
11
+ their recovery and callback behavior drift.
12
+
13
+ ## Decision
14
+
15
+ Generated parser classes own recursively frozen tables. Each parser instance
16
+ owns one mutable session and permits only one active driver. Pull, yielding, and
17
+ push APIs feed the same LR transition and recovery machinery; nested or mixed
18
+ drivers fail before mutating state.
19
+
20
+ State, semantic value, optional location, and optional Green stacks remain
21
+ index-aligned. Capabilities allocate their parallel state only when the
22
+ generated grammar or runtime tooling requires it.
23
+
24
+ Per-instance resource limits bound stack growth, recovery attempts, and other
25
+ session-owned search or memo structures. Exceeding a bound produces a
26
+ structured failure rather than unbounded work. Sharing a parser instance or
27
+ its application callbacks across concurrent parses is outside the contract.
28
+
29
+ ## Consequences
30
+
31
+ - Parser classes and eligible table graphs can be shared while sessions remain
32
+ independently mutable.
33
+ - All input lifecycles preserve one action, recovery, and callback ordering.
34
+ - Applications choose stricter or larger limits without regenerating tables.