ibex 0.2.0 → 0.4.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 (461) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +100 -272
  3. data/docs/architecture.md +187 -35
  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 +3 -4
  12. data/docs/cst.md +24 -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 +274 -0
  40. data/docs/development.md +196 -2
  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 +2 -1
  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 +1617 -0
  49. data/docs/error-ux-round2.md +111 -0
  50. data/docs/error-ux.md +54 -0
  51. data/docs/getting-started.md +80 -0
  52. data/docs/grammar-reference.md +184 -13
  53. data/docs/ielr-design.md +43 -0
  54. data/docs/ielr.md +92 -0
  55. data/docs/impact.md +101 -0
  56. data/docs/ja/bison-import.md +51 -0
  57. data/docs/ja/stable-api.md +53 -0
  58. data/docs/lexer-construction-profile.md +109 -0
  59. data/docs/lexer-migration.md +5 -0
  60. data/docs/maturity.md +129 -0
  61. data/docs/project-site-strategy.md +54 -0
  62. data/docs/racc-migration-evidence.md +45 -0
  63. data/docs/racc-migration.md +11 -0
  64. data/docs/release-readiness.md +126 -68
  65. data/docs/repair-semantics.md +123 -0
  66. data/docs/runtime-abi-evolution.md +310 -0
  67. data/docs/stability.md +145 -34
  68. data/docs/status.md +43 -0
  69. data/docs/syntax-sessions.md +183 -0
  70. data/docs/table-artifact.md +125 -0
  71. data/docs/test-interactions.md +219 -0
  72. data/docs/verification-report.md +137 -0
  73. data/docs/verifier-trust-boundary.md +199 -0
  74. data/docs/workloads.md +132 -0
  75. data/lib/ibex/analysis/digraph.rb +128 -0
  76. data/lib/ibex/analysis/sets.rb +14 -0
  77. data/lib/ibex/analysis.rb +1 -0
  78. data/lib/ibex/bison_import/importer.rb +516 -0
  79. data/lib/ibex/bison_import/tokenizer.rb +260 -0
  80. data/lib/ibex/bison_import.rb +200 -0
  81. data/lib/ibex/bounded_subprocess.rb +171 -0
  82. data/lib/ibex/cli/ambiguity.rb +14 -5
  83. data/lib/ibex/cli/analysis.rb +134 -0
  84. data/lib/ibex/cli/bison_import.rb +121 -0
  85. data/lib/ibex/cli/config.rb +128 -0
  86. data/lib/ibex/cli/diagnostics.rb +31 -11
  87. data/lib/ibex/cli/documentation.rb +11 -8
  88. data/lib/ibex/cli/equiv.rb +169 -0
  89. data/lib/ibex/cli/error_messages.rb +11 -4
  90. data/lib/ibex/cli/explain.rb +14 -5
  91. data/lib/ibex/cli/fix.rb +203 -0
  92. data/lib/ibex/cli/formatting.rb +11 -10
  93. data/lib/ibex/cli/fuzz.rb +200 -0
  94. data/lib/ibex/cli/fuzz_regressions.rb +145 -0
  95. data/lib/ibex/cli/generation_artifacts.rb +53 -2
  96. data/lib/ibex/cli/generation_error_messages.rb +1 -1
  97. data/lib/ibex/cli/grammar_tests.rb +32 -14
  98. data/lib/ibex/cli/impact.rb +393 -0
  99. data/lib/ibex/cli/ir_tools.rb +5 -61
  100. data/lib/ibex/cli/outputs.rb +60 -33
  101. data/lib/ibex/cli/reduce.rb +202 -0
  102. data/lib/ibex/cli/reduce_reporting.rb +71 -0
  103. data/lib/ibex/cli/samples.rb +49 -23
  104. data/lib/ibex/cli/verify.rb +116 -0
  105. data/lib/ibex/cli/watch.rb +6 -5
  106. data/lib/ibex/cli.rb +362 -56
  107. data/lib/ibex/codegen/action_locations.rb +1 -1
  108. data/lib/ibex/codegen/action_method_source.rb +5 -6
  109. data/lib/ibex/codegen/action_source.rb +3 -2
  110. data/lib/ibex/codegen/ambiguity.rb +5 -4
  111. data/lib/ibex/codegen/explain.rb +123 -55
  112. data/lib/ibex/codegen/generated_action_abi.rb +10 -5
  113. data/lib/ibex/codegen/rbs.rb +15 -7
  114. data/lib/ibex/codegen/report.rb +25 -13
  115. data/lib/ibex/codegen/ruby.rb +28 -64
  116. data/lib/ibex/codegen/ruby_actions.rb +9 -6
  117. data/lib/ibex/codegen/ruby_syntax.rb +15 -9
  118. data/lib/ibex/configuration/analysis_grammar.rb +35 -0
  119. data/lib/ibex/configuration/explanation.rb +421 -0
  120. data/lib/ibex/configuration/inspector.rb +232 -0
  121. data/lib/ibex/configuration.rb +580 -0
  122. data/lib/ibex/coverage/collector.rb +21 -11
  123. data/lib/ibex/coverage/event_stream.rb +13 -7
  124. data/lib/ibex/coverage/report.rb +26 -18
  125. data/lib/ibex/coverage/runtime_event_validator.rb +30 -21
  126. data/lib/ibex/delta_reducer.rb +99 -0
  127. data/lib/ibex/diff.rb +141 -0
  128. data/lib/ibex/equiv/machine.rb +135 -0
  129. data/lib/ibex/equiv.rb +373 -0
  130. data/lib/ibex/fix.rb +557 -0
  131. data/lib/ibex/frontend/ast.rb +22 -2
  132. data/lib/ibex/frontend/bootstrap_parser.rb +6 -13
  133. data/lib/ibex/frontend/diagnostic.rb +1 -1
  134. data/lib/ibex/frontend/formatter.rb +72 -26
  135. data/lib/ibex/frontend/generated_parser.rb +147 -117
  136. data/lib/ibex/frontend/generated_parser_base.rb +7 -3
  137. data/lib/ibex/frontend/generated_parser_includes.rb +1 -11
  138. data/lib/ibex/frontend/generation.rb +1 -1
  139. data/lib/ibex/frontend/parser/declarations.rb +17 -2
  140. data/lib/ibex/frontend/parser_configuration_support.rb +56 -0
  141. data/lib/ibex/frontend/regenerator.rb +1 -0
  142. data/lib/ibex/frontend/resolution.rb +2 -1
  143. data/lib/ibex/frontend/resolver.rb +1 -1
  144. data/lib/ibex/frontend/rule_documentation.rb +2 -1
  145. data/lib/ibex/frontend/source_cursor.rb +2 -2
  146. data/lib/ibex/frontend/source_span.rb +9 -1
  147. data/lib/ibex/frontend/token_adapter/declaration_state.rb +38 -6
  148. data/lib/ibex/frontend/token_adapter.rb +10 -0
  149. data/lib/ibex/frontend.rb +1 -0
  150. data/lib/ibex/fuzz.rb +219 -0
  151. data/lib/ibex/generation_input.rb +1 -1
  152. data/lib/ibex/generation_manifest.rb +36 -25
  153. data/lib/ibex/generation_transaction.rb +1 -1
  154. data/lib/ibex/generation_transaction_recovery.rb +4 -4
  155. data/lib/ibex/generation_transaction_validation.rb +2 -2
  156. data/lib/ibex/grammar_tests.rb +1 -1
  157. data/lib/ibex/impact/action_impact.rb +148 -0
  158. data/lib/ibex/impact/automaton_impact.rb +57 -0
  159. data/lib/ibex/impact/coverage_impact.rb +53 -0
  160. data/lib/ibex/impact/graph.rb +132 -0
  161. data/lib/ibex/impact/propagation.rb +147 -0
  162. data/lib/ibex/impact/report.rb +273 -0
  163. data/lib/ibex/impact/seeds.rb +69 -0
  164. data/lib/ibex/impact/severity.rb +139 -0
  165. data/lib/ibex/impact.rb +16 -0
  166. data/lib/ibex/ir/automaton_ir.rb +61 -19
  167. data/lib/ibex/ir/grammar_ir.rb +76 -45
  168. data/lib/ibex/ir/lexer_ir.rb +5 -5
  169. data/lib/ibex/ir/parser_contract.rb +135 -0
  170. data/lib/ibex/ir/serialize.rb +203 -76
  171. data/lib/ibex/ir/validator/automaton.rb +64 -34
  172. data/lib/ibex/ir/validator/base.rb +51 -33
  173. data/lib/ibex/ir/validator/grammar.rb +113 -83
  174. data/lib/ibex/ir/validator/lexer.rb +2 -2
  175. data/lib/ibex/ir/validator.rb +2 -1
  176. data/lib/ibex/ir.rb +16 -3
  177. data/lib/ibex/lalr/build_metrics.rb +50 -2
  178. data/lib/ibex/lalr/builder.rb +191 -56
  179. data/lib/ibex/lalr/conflict_search.rb +15 -4
  180. data/lib/ibex/lalr/counterexample.rb +19 -14
  181. data/lib/ibex/lalr/direct_lookaheads.rb +110 -57
  182. data/lib/ibex/lalr/goto_follows.rb +229 -0
  183. data/lib/ibex/lalr/ielr/annotator.rb +214 -0
  184. data/lib/ibex/lalr/ielr/bits.rb +28 -0
  185. data/lib/ibex/lalr/ielr/inadequacy.rb +47 -0
  186. data/lib/ibex/lalr/ielr/item_lookaheads.rb +78 -0
  187. data/lib/ibex/lalr/ielr/pipeline.rb +75 -0
  188. data/lib/ibex/lalr/ielr/split_stability.rb +78 -0
  189. data/lib/ibex/lalr/ielr/split_state.rb +20 -0
  190. data/lib/ibex/lalr/ielr/state_splitter.rb +258 -0
  191. data/lib/ibex/lalr/ielr_partition.rb +22 -8
  192. data/lib/ibex/lalr/inadequacy_report.rb +50 -0
  193. data/lib/ibex/lalr/lookahead_propagation.rb +111 -0
  194. data/lib/ibex/lalr/lr0_collection.rb +121 -0
  195. data/lib/ibex/lalr/unreachable_states.rb +80 -0
  196. data/lib/ibex/lalr.rb +52 -1
  197. data/lib/ibex/location.rb +3 -3
  198. data/lib/ibex/lsp/document_handlers.rb +9 -7
  199. data/lib/ibex/lsp/initialization_handlers.rb +9 -7
  200. data/lib/ibex/lsp/navigation_handlers.rb +25 -11
  201. data/lib/ibex/lsp/parser_configuration_assistance.rb +149 -0
  202. data/lib/ibex/lsp/position_codec.rb +6 -2
  203. data/lib/ibex/lsp/request_handlers.rb +3 -2
  204. data/lib/ibex/lsp/request_support.rb +14 -7
  205. data/lib/ibex/lsp/server.rb +13 -11
  206. data/lib/ibex/lsp/symbol_index.rb +13 -13
  207. data/lib/ibex/lsp/symbol_index_builder.rb +30 -20
  208. data/lib/ibex/lsp/symbol_occurrence.rb +8 -2
  209. data/lib/ibex/lsp/transport.rb +13 -3
  210. data/lib/ibex/lsp/workspace.rb +5 -4
  211. data/lib/ibex/lsp/workspace_analyzer.rb +1 -1
  212. data/lib/ibex/lsp.rb +1 -0
  213. data/lib/ibex/messages/en.yml +28 -0
  214. data/lib/ibex/messages/ja.yml +28 -0
  215. data/lib/ibex/messages.rb +68 -0
  216. data/lib/ibex/metrics.rb +175 -0
  217. data/lib/ibex/normalize/declarations.rb +2 -0
  218. data/lib/ibex/normalize/diagnostics.rb +63 -38
  219. data/lib/ibex/normalize/expander.rb +5 -4
  220. data/lib/ibex/normalize/expression.rb +8 -6
  221. data/lib/ibex/normalize/grammar_builder.rb +26 -0
  222. data/lib/ibex/normalize/inline_expansion.rb +100 -49
  223. data/lib/ibex/normalize/lexer.rb +3 -3
  224. data/lib/ibex/normalize/parameter_ebnf_lowering.rb +11 -10
  225. data/lib/ibex/normalize/parameter_lowering.rb +40 -23
  226. data/lib/ibex/normalize/parameters.rb +31 -4
  227. data/lib/ibex/normalize/parser_configuration.rb +70 -0
  228. data/lib/ibex/normalize.rb +10 -20
  229. data/lib/ibex/racc_migration/report.rb +6 -3
  230. data/lib/ibex/rake_task.rb +1 -1
  231. data/lib/ibex/samples.rb +43 -13
  232. data/lib/ibex/table_artifact/builder.rb +266 -0
  233. data/lib/ibex/table_artifact/cst_projection.rb +70 -0
  234. data/lib/ibex/table_artifact/document.rb +39 -0
  235. data/lib/ibex/table_artifact/executor.rb +187 -0
  236. data/lib/ibex/table_artifact/serializer.rb +57 -0
  237. data/lib/ibex/table_artifact/validator/metadata.rb +179 -0
  238. data/lib/ibex/table_artifact/validator/support.rb +86 -0
  239. data/lib/ibex/table_artifact/validator/tables.rb +238 -0
  240. data/lib/ibex/table_artifact/validator.rb +253 -0
  241. data/lib/ibex/table_artifact.rb +88 -0
  242. data/lib/ibex/table_simulation/result.rb +6 -2
  243. data/lib/ibex/table_simulation/step.rb +3 -1
  244. data/lib/ibex/tables.rb +14 -0
  245. data/lib/ibex/verifiable_generation_bundle.rb +86 -0
  246. data/lib/ibex/verification_report/builder.rb +159 -0
  247. data/lib/ibex/verification_report/canonical_ir.rb +123 -0
  248. data/lib/ibex/verification_report/logical_path.rb +68 -0
  249. data/lib/ibex/verification_report/validator.rb +329 -0
  250. data/lib/ibex/verification_report.rb +69 -0
  251. data/lib/ibex/verify/action_correspondence.rb +138 -0
  252. data/lib/ibex/verify/language_witness.rb +295 -0
  253. data/lib/ibex/verify/reference_collection.rb +190 -0
  254. data/lib/ibex/verify/result.rb +73 -0
  255. data/lib/ibex/verify/verifier.rb +598 -0
  256. data/lib/ibex/verify.rb +15 -0
  257. data/lib/ibex/version.rb +1 -1
  258. data/lib/ibex/watch/runner.rb +10 -1
  259. data/lib/ibex/watch/source_snapshot.rb +13 -8
  260. data/lib/ibex.rb +11 -0
  261. data/schema/{automaton-ir-v1.schema.json → automaton-ir-definitions.schema.json} +6 -6
  262. data/schema/{automaton-ir-v2.schema.json → automaton-ir.schema.json} +14 -7
  263. data/schema/bison-import-v1.schema.json +106 -0
  264. data/schema/conflict-explanation-review-v1.schema.json +196 -0
  265. data/schema/conflict-explanation-study-v1.schema.json +528 -0
  266. data/schema/construction-profile-v1.schema.json +779 -0
  267. data/schema/diff-v1.schema.json +41 -0
  268. data/schema/direct-ielr-decision-v1.schema.json +200 -0
  269. data/schema/equiv-v1.schema.json +64 -0
  270. data/schema/error-ux-review-v1.schema.json +609 -0
  271. data/schema/error-ux-round2-review-v1.schema.json +191 -0
  272. data/schema/error-ux-round2-v1.schema.json +519 -0
  273. data/schema/explain-v1.schema.json +63 -1
  274. data/schema/fix-v1.schema.json +64 -0
  275. data/schema/fix-v2.schema.json +66 -0
  276. data/schema/fix-v3.schema.json +101 -0
  277. data/schema/fuzz-regression-v1.schema.json +79 -0
  278. data/schema/fuzz-v1.schema.json +114 -0
  279. data/schema/{grammar-ir-v2.schema.json → grammar-ir-extensions.schema.json} +20 -65
  280. data/schema/{grammar-ir-v1.schema.json → grammar-ir-foundation.schema.json} +3 -3
  281. data/schema/grammar-ir.schema.json +271 -0
  282. data/schema/ielr-benchmark-v1.schema.json +85 -0
  283. data/schema/impact-v1.schema.json +208 -0
  284. data/schema/lexer-profile-v1.schema.json +491 -0
  285. data/schema/metrics-v1.schema.json +60 -0
  286. data/schema/reduce-v1.schema.json +22 -0
  287. data/schema/reduce-v2.schema.json +63 -0
  288. data/schema/table-artifact-v1.schema.json +377 -0
  289. data/schema/verification-report-v1.schema.json +222 -0
  290. data/schema/verify-v1.schema.json +42 -0
  291. data/sig/ibex/analysis/digraph.rbs +19 -0
  292. data/sig/ibex/analysis/sets.rbs +10 -0
  293. data/sig/ibex/bison_import/importer.rbs +140 -0
  294. data/sig/ibex/bison_import/tokenizer.rbs +91 -0
  295. data/sig/ibex/bison_import.rbs +95 -0
  296. data/sig/ibex/bounded_subprocess.rbs +76 -0
  297. data/sig/ibex/cli/ambiguity.rbs +6 -0
  298. data/sig/ibex/cli/analysis.rbs +43 -0
  299. data/sig/ibex/cli/bison_import.rbs +32 -0
  300. data/sig/ibex/cli/config.rbs +35 -0
  301. data/sig/ibex/cli/diagnostics.rbs +16 -3
  302. data/sig/ibex/cli/documentation.rbs +5 -1
  303. data/sig/ibex/cli/equiv.rbs +49 -0
  304. data/sig/ibex/cli/error_messages.rbs +6 -0
  305. data/sig/ibex/cli/explain.rbs +6 -0
  306. data/sig/ibex/cli/fix.rbs +53 -0
  307. data/sig/ibex/cli/formatting.rbs +5 -1
  308. data/sig/ibex/cli/fuzz.rbs +47 -0
  309. data/sig/ibex/cli/fuzz_regressions.rbs +40 -0
  310. data/sig/ibex/cli/generation_artifacts.rbs +21 -2
  311. data/sig/ibex/cli/generation_error_messages.rbs +2 -2
  312. data/sig/ibex/cli/grammar_tests.rbs +15 -3
  313. data/sig/ibex/cli/impact.rbs +95 -0
  314. data/sig/ibex/cli/ir_tools.rbs +7 -19
  315. data/sig/ibex/cli/outputs.rbs +9 -3
  316. data/sig/ibex/cli/reduce.rbs +60 -0
  317. data/sig/ibex/cli/reduce_reporting.rbs +27 -0
  318. data/sig/ibex/cli/samples.rbs +8 -0
  319. data/sig/ibex/cli/verify.rbs +28 -0
  320. data/sig/ibex/cli/watch.rbs +2 -2
  321. data/sig/ibex/cli.rbs +79 -5
  322. data/sig/ibex/codegen/action_method_source.rbs +4 -4
  323. data/sig/ibex/codegen/explain.rbs +45 -25
  324. data/sig/ibex/codegen/generated_action_abi.rbs +14 -10
  325. data/sig/ibex/codegen/rbs.rbs +12 -10
  326. data/sig/ibex/codegen/report.rbs +12 -12
  327. data/sig/ibex/codegen/ruby.rbs +18 -15
  328. data/sig/ibex/codegen/ruby_actions.rbs +6 -6
  329. data/sig/ibex/codegen/ruby_syntax.rbs +10 -8
  330. data/sig/ibex/configuration/analysis_grammar.rbs +13 -0
  331. data/sig/ibex/configuration/explanation.rbs +195 -0
  332. data/sig/ibex/configuration/inspector.rbs +53 -0
  333. data/sig/ibex/configuration.rbs +242 -0
  334. data/sig/ibex/coverage/collector.rbs +16 -14
  335. data/sig/ibex/coverage/event_stream.rbs +12 -10
  336. data/sig/ibex/coverage/report.rbs +20 -18
  337. data/sig/ibex/coverage/runtime_event_validator.rbs +38 -36
  338. data/sig/ibex/delta_reducer.rbs +38 -0
  339. data/sig/ibex/diff.rbs +47 -0
  340. data/sig/ibex/equiv/machine.rbs +54 -0
  341. data/sig/ibex/equiv.rbs +129 -0
  342. data/sig/ibex/fix.rbs +138 -0
  343. data/sig/ibex/frontend/ast.rbs +33 -7
  344. data/sig/ibex/frontend/bootstrap_parser.rbs +2 -0
  345. data/sig/ibex/frontend/diagnostic.rbs +2 -2
  346. data/sig/ibex/frontend/formatter.rbs +38 -30
  347. data/sig/ibex/frontend/generated_parser.rbs +87 -77
  348. data/sig/ibex/frontend/generated_parser_base.rbs +4 -2
  349. data/sig/ibex/frontend/parser/declarations.rbs +3 -0
  350. data/sig/ibex/frontend/parser_configuration_support.rbs +27 -0
  351. data/sig/ibex/frontend/resolution.rbs +3 -2
  352. data/sig/ibex/frontend/source_cursor.rbs +2 -2
  353. data/sig/ibex/frontend/source_span.rbs +5 -2
  354. data/sig/ibex/frontend/token_adapter/declaration_state.rbs +13 -1
  355. data/sig/ibex/frontend/token_adapter.rbs +6 -0
  356. data/sig/ibex/fuzz.rbs +71 -0
  357. data/sig/ibex/generation_input.rbs +2 -2
  358. data/sig/ibex/generation_manifest.rbs +35 -32
  359. data/sig/ibex/generation_transaction_recovery.rbs +2 -2
  360. data/sig/ibex/generation_transaction_validation.rbs +2 -2
  361. data/sig/ibex/grammar_tests.rbs +2 -2
  362. data/sig/ibex/impact/action_impact.rbs +58 -0
  363. data/sig/ibex/impact/automaton_impact.rbs +37 -0
  364. data/sig/ibex/impact/coverage_impact.rbs +28 -0
  365. data/sig/ibex/impact/graph.rbs +67 -0
  366. data/sig/ibex/impact/propagation.rbs +56 -0
  367. data/sig/ibex/impact/report.rbs +107 -0
  368. data/sig/ibex/impact/seeds.rbs +36 -0
  369. data/sig/ibex/impact/severity.rbs +55 -0
  370. data/sig/ibex/impact.rbs +6 -0
  371. data/sig/ibex/ir/automaton_ir.rbs +30 -11
  372. data/sig/ibex/ir/grammar_ir.rbs +41 -27
  373. data/sig/ibex/ir/lexer_ir.rbs +8 -8
  374. data/sig/ibex/ir/parser_contract.rbs +69 -0
  375. data/sig/ibex/ir/serialize.rbs +63 -28
  376. data/sig/ibex/ir/validator/automaton.rbs +47 -44
  377. data/sig/ibex/ir/validator/base.rbs +35 -31
  378. data/sig/ibex/ir/validator/grammar.rbs +78 -67
  379. data/sig/ibex/ir/validator/lexer.rbs +4 -4
  380. data/sig/ibex/ir.rbs +9 -3
  381. data/sig/ibex/lalr/build_metrics.rbs +42 -2
  382. data/sig/ibex/lalr/builder.rbs +75 -24
  383. data/sig/ibex/lalr/conflict_search.rbs +5 -2
  384. data/sig/ibex/lalr/counterexample.rbs +17 -14
  385. data/sig/ibex/lalr/direct_lookaheads.rbs +35 -28
  386. data/sig/ibex/lalr/goto_follows.rbs +89 -0
  387. data/sig/ibex/lalr/ielr/annotator.rbs +67 -0
  388. data/sig/ibex/lalr/ielr/bits.rbs +14 -0
  389. data/sig/ibex/lalr/ielr/inadequacy.rbs +24 -0
  390. data/sig/ibex/lalr/ielr/item_lookaheads.rbs +35 -0
  391. data/sig/ibex/lalr/ielr/pipeline.rbs +17 -0
  392. data/sig/ibex/lalr/ielr/split_stability.rbs +27 -0
  393. data/sig/ibex/lalr/ielr/split_state.rbs +14 -0
  394. data/sig/ibex/lalr/ielr/state_splitter.rbs +76 -0
  395. data/sig/ibex/lalr/ielr_partition.rbs +17 -5
  396. data/sig/ibex/lalr/inadequacy_report.rbs +21 -0
  397. data/sig/ibex/lalr/lookahead_propagation.rbs +38 -0
  398. data/sig/ibex/lalr/lr0_collection.rbs +50 -0
  399. data/sig/ibex/lalr/unreachable_states.rbs +25 -0
  400. data/sig/ibex/lalr.rbs +11 -1
  401. data/sig/ibex/location.rbs +6 -6
  402. data/sig/ibex/lsp/document_handlers.rbs +8 -8
  403. data/sig/ibex/lsp/initialization_handlers.rbs +12 -12
  404. data/sig/ibex/lsp/navigation_handlers.rbs +15 -12
  405. data/sig/ibex/lsp/parser_configuration_assistance.rbs +49 -0
  406. data/sig/ibex/lsp/position_codec.rbs +8 -4
  407. data/sig/ibex/lsp/request_handlers.rbs +4 -4
  408. data/sig/ibex/lsp/request_support.rbs +8 -8
  409. data/sig/ibex/lsp/server.rbs +16 -16
  410. data/sig/ibex/lsp/symbol_index.rbs +20 -21
  411. data/sig/ibex/lsp/symbol_index_builder.rbs +9 -8
  412. data/sig/ibex/lsp/symbol_occurrence.rbs +11 -5
  413. data/sig/ibex/lsp/transport.rbs +18 -6
  414. data/sig/ibex/lsp/workspace.rbs +3 -2
  415. data/sig/ibex/lsp/workspace_analyzer.rbs +1 -1
  416. data/sig/ibex/messages.rbs +26 -0
  417. data/sig/ibex/metrics.rbs +50 -0
  418. data/sig/ibex/normalize/diagnostics.rbs +4 -4
  419. data/sig/ibex/normalize/expander.rbs +2 -2
  420. data/sig/ibex/normalize/expression.rbs +10 -8
  421. data/sig/ibex/normalize/grammar_builder.rbs +11 -0
  422. data/sig/ibex/normalize/inline_expansion.rbs +59 -50
  423. data/sig/ibex/normalize/lexer.rbs +4 -4
  424. data/sig/ibex/normalize/parameter_ebnf_lowering.rbs +15 -14
  425. data/sig/ibex/normalize/parameter_lowering.rbs +18 -18
  426. data/sig/ibex/normalize/parameters.rbs +13 -8
  427. data/sig/ibex/normalize/parser_configuration.rbs +23 -0
  428. data/sig/ibex/normalize.rbs +11 -5
  429. data/sig/ibex/racc_migration/report.rbs +8 -6
  430. data/sig/ibex/rake_task.rbs +1 -1
  431. data/sig/ibex/samples.rbs +13 -4
  432. data/sig/ibex/table_artifact/builder.rbs +93 -0
  433. data/sig/ibex/table_artifact/cst_projection.rbs +20 -0
  434. data/sig/ibex/table_artifact/document.rbs +27 -0
  435. data/sig/ibex/table_artifact/executor.rbs +66 -0
  436. data/sig/ibex/table_artifact/serializer.rbs +25 -0
  437. data/sig/ibex/table_artifact/validator/metadata.rbs +52 -0
  438. data/sig/ibex/table_artifact/validator/support.rbs +46 -0
  439. data/sig/ibex/table_artifact/validator/tables.rbs +63 -0
  440. data/sig/ibex/table_artifact/validator.rbs +66 -0
  441. data/sig/ibex/table_artifact.rbs +32 -0
  442. data/sig/ibex/table_simulation/result.rbs +8 -4
  443. data/sig/ibex/table_simulation/step.rbs +4 -2
  444. data/sig/ibex/tables.rbs +10 -9
  445. data/sig/ibex/verifiable_generation_bundle.rbs +24 -0
  446. data/sig/ibex/verification_report/builder.rbs +53 -0
  447. data/sig/ibex/verification_report/canonical_ir.rbs +41 -0
  448. data/sig/ibex/verification_report/logical_path.rbs +34 -0
  449. data/sig/ibex/verification_report/validator.rbs +114 -0
  450. data/sig/ibex/verification_report.rbs +44 -0
  451. data/sig/ibex/verify/action_correspondence.rbs +50 -0
  452. data/sig/ibex/verify/language_witness.rbs +112 -0
  453. data/sig/ibex/verify/reference_collection.rbs +63 -0
  454. data/sig/ibex/verify/result.rbs +52 -0
  455. data/sig/ibex/verify/verifier.rbs +170 -0
  456. data/sig/ibex/verify.rbs +6 -0
  457. data/sig/ibex/watch/runner.rbs +12 -2
  458. data/sig/ibex/watch/source_snapshot.rbs +13 -9
  459. metadata +254 -12
  460. data/lib/ibex/ir/migration.rb +0 -120
  461. data/sig/ibex/ir/migration.rbs +0 -34
@@ -3,22 +3,22 @@
3
3
  module Ibex
4
4
  module IR
5
5
  module Validator
6
- # Structural and referential validation for a versioned Grammar IR JSON object.
6
+ # Structural and referential validation for a current Grammar IR JSON object.
7
7
  # rubocop:disable Metrics/ClassLength -- inline type contracts accompany one cohesive document validator.
8
8
  class GrammarDocument < Base
9
9
  ROOT_REQUIRED = %w[
10
10
  ibex_ir schema_version class_name superclass start expect options symbols productions user_code
11
- conversions warnings
11
+ conversions warnings source_provenance parser_contract
12
+ ].freeze #: Array[String]
13
+ ROOT_OPTIONAL = %w[
14
+ user_code_chunks expect_rr params printers tests recovery lexer mode starts
12
15
  ].freeze #: Array[String]
13
- ROOT_OPTIONAL = %w[user_code_chunks expect_rr].freeze #: Array[String]
14
- V2_ROOT_REQUIRED = %w[source_provenance migration].freeze #: Array[String]
15
- V2_ROOT_OPTIONAL = %w[params printers tests recovery lexer mode starts].freeze #: Array[String]
16
16
  SYMBOL_REQUIRED = %w[id name kind reserved prec loc].freeze #: Array[String]
17
17
  SYMBOL_OPTIONAL = %w[display_name semantic_type].freeze #: Array[String]
18
- V2_SYMBOL_REQUIRED = %w[doc].freeze #: Array[String]
18
+ SYMBOL_METADATA_REQUIRED = %w[doc].freeze #: Array[String]
19
19
  PRODUCTION_REQUIRED = %w[id lhs rhs action prec_override origin].freeze #: Array[String]
20
- V2_PRODUCTION_REQUIRED = %w[doc expansion].freeze #: Array[String]
21
- V2_ACTION_REQUIRED = %w[composition].freeze #: Array[String]
20
+ PRODUCTION_METADATA_REQUIRED = %w[doc expansion].freeze #: Array[String]
21
+ ACTION_COMPOSITION_REQUIRED = %w[composition].freeze #: Array[String]
22
22
  ORIGIN_KINDS = %w[
23
23
  optional_expansion star_expansion plus_expansion separated_list_expansion group_expansion
24
24
  ].freeze #: Array[String]
@@ -27,15 +27,15 @@ module Ibex
27
27
  if in module next nil not or redo rescue retry return self super then true undef unless until when while yield
28
28
  ].freeze #: Array[String]
29
29
 
30
- attr_reader :symbols_by_id #: Hash[Integer, Hash[String, untyped]]
31
- attr_reader :symbols_by_name #: Hash[String, Hash[String, untyped]]
32
- attr_reader :productions_by_id #: Hash[Integer, Hash[String, untyped]]
30
+ attr_reader :symbols_by_id #: Hash[Integer, json_object]
31
+ attr_reader :symbols_by_name #: Hash[String, json_object]
32
+ attr_reader :productions_by_id #: Hash[Integer, json_object]
33
33
 
34
- # @rbs @data: Hash[String, untyped]
34
+ # @rbs @data: json_object
35
35
  # @rbs @path: String
36
36
  # @rbs @version: Integer
37
37
 
38
- # @rbs (Hash[String, untyped] data, ?path: String, ?version: Integer) -> void
38
+ # @rbs (json_object data, ?path: String, ?version: Integer) -> void
39
39
  def initialize(data, path: "$", version: data.fetch("schema_version"))
40
40
  super()
41
41
  @data = data
@@ -48,34 +48,50 @@ module Ibex
48
48
 
49
49
  # @rbs () -> self
50
50
  def validate
51
- required = ROOT_REQUIRED + (@version >= 2 ? V2_ROOT_REQUIRED : [])
52
- optional = ROOT_OPTIONAL + (@version >= 2 ? V2_ROOT_OPTIONAL : [])
53
- record(@data, @path, required, optional)
51
+ validate_root_record
54
52
  validate_envelope
55
53
  validate_header
56
54
  validate_options
57
- validate_parser_parameters if @data.key?("params")
55
+ validate_parser_parameters_if_present
58
56
  validate_symbols
59
- validate_value_printers if @data.key?("printers")
60
- validate_grammar_tests if @data.key?("tests")
57
+ validate_optional_parser_metadata
61
58
  validate_reserved_symbols
62
59
  validate_start
63
- validate_lexer if @data.key?("lexer")
64
- validate_recovery if @data.key?("recovery")
65
60
  validate_productions
66
61
  validate_string_map(@data["user_code"], "#{@path}.user_code")
67
62
  validate_string_map(@data["conversions"], "#{@path}.conversions")
68
63
  validate_warnings
69
- validate_user_code_chunks if @data.key?("user_code_chunks")
70
- if @version >= 2
71
- validate_source_provenance(@data["source_provenance"], "#{@path}.source_provenance")
72
- validate_migration
73
- end
64
+ validate_optional_source_metadata
74
65
  self
75
66
  end
76
67
 
77
68
  private
78
69
 
70
+ # @rbs () -> void
71
+ def validate_root_record
72
+ record(@data, @path, ROOT_REQUIRED, ROOT_OPTIONAL)
73
+ end
74
+
75
+ # @rbs () -> void
76
+ def validate_optional_parser_metadata
77
+ validate_value_printers if @data.key?("printers")
78
+ validate_grammar_tests if @data.key?("tests")
79
+ validate_lexer if @data.key?("lexer")
80
+ validate_recovery if @data.key?("recovery")
81
+ validate_parser_contract
82
+ end
83
+
84
+ # @rbs () -> void
85
+ def validate_parser_parameters_if_present
86
+ validate_parser_parameters if @data.key?("params")
87
+ end
88
+
89
+ # @rbs () -> void
90
+ def validate_optional_source_metadata
91
+ validate_user_code_chunks if @data.key?("user_code_chunks")
92
+ validate_source_provenance(@data["source_provenance"], "#{@path}.source_provenance")
93
+ end
94
+
79
95
  # @rbs () -> void
80
96
  def validate_envelope
81
97
  literal(@data["ibex_ir"], "#{@path}.ibex_ir", "grammar")
@@ -100,7 +116,6 @@ module Ibex
100
116
  boolean(options["omit_action_call"], "#{path}.omit_action_call")
101
117
  return unless options.key?("cst")
102
118
 
103
- invalid("#{path}.cst", "requires schema_version 2") unless @version >= 2
104
119
  literal(options["cst"], "#{path}.cst", true)
105
120
  invalid("#{@path}.mode", "must be extended when CST construction is enabled") unless
106
121
  @data["mode"] == "extended"
@@ -159,10 +174,10 @@ module Ibex
159
174
  end
160
175
  end
161
176
 
162
- # @rbs (untyped value, Integer index) -> void
177
+ # @rbs (json_value value, Integer index) -> void
163
178
  def validate_symbol(value, index)
164
179
  path = "#{@path}.symbols[#{index}]"
165
- required = SYMBOL_REQUIRED + (@version >= 2 ? V2_SYMBOL_REQUIRED : [])
180
+ required = SYMBOL_REQUIRED + SYMBOL_METADATA_REQUIRED
166
181
  symbol = record(value, path, required, SYMBOL_OPTIONAL)
167
182
  id = nonnegative_integer(symbol["id"], "#{path}.id")
168
183
  invalid("#{path}.id", "must equal its array index #{index}") unless id == index
@@ -175,10 +190,10 @@ module Ibex
175
190
  validate_precedence(symbol["prec"], "#{path}.prec")
176
191
  location(symbol["loc"], "#{path}.loc")
177
192
  SYMBOL_OPTIONAL.each { |key| metadata(symbol[key], "#{path}.#{key}") if symbol.key?(key) }
178
- nullable_string(symbol["doc"], "#{path}.doc") if @version >= 2
193
+ nullable_string(symbol["doc"], "#{path}.doc")
179
194
  end
180
195
 
181
- # @rbs (untyped value, String path) -> void
196
+ # @rbs (json_value value, String path) -> void
182
197
  def validate_precedence(value, path)
183
198
  return if value.nil?
184
199
 
@@ -203,7 +218,7 @@ module Ibex
203
218
 
204
219
  # @rbs () -> void
205
220
  def validate_start
206
- start = @data["start"]
221
+ start = nonempty_string(@data["start"], "#{@path}.start")
207
222
  symbol = @symbols_by_name[start]
208
223
  invalid("#{@path}.start", "references missing symbol #{start.inspect}") unless symbol
209
224
  invalid("#{@path}.start", "must reference a nonterminal") unless symbol["kind"] == "nonterminal"
@@ -253,7 +268,7 @@ module Ibex
253
268
  invalid(path, "must declare at least one recovery policy")
254
269
  end
255
270
 
256
- # @rbs (untyped values, String path, kind: String) -> void
271
+ # @rbs (json_value values, String path, kind: String) -> void
257
272
  def validate_recovery_symbols(values, path, kind:)
258
273
  seen = {} #: Hash[String, bool]
259
274
  array(values, path).each_with_index do |name, index|
@@ -261,7 +276,7 @@ module Ibex
261
276
  end
262
277
  end
263
278
 
264
- # @rbs (untyped value, String path, kind: String, seen: Hash[String, bool]) -> void
279
+ # @rbs (json_value value, String path, kind: String, seen: Hash[String, bool]) -> void
265
280
  def validate_recovery_symbol(value, path, kind:, seen:)
266
281
  name = nonempty_string(value, path)
267
282
  invalid(path, "duplicates symbol #{name.inspect}") if seen[name]
@@ -279,28 +294,27 @@ module Ibex
279
294
  end
280
295
  end
281
296
 
282
- # @rbs (untyped value, Integer index) -> void
297
+ # @rbs (json_value value, Integer index) -> void
283
298
  def validate_production(value, index)
284
299
  path = "#{@path}.productions[#{index}]"
285
- required = PRODUCTION_REQUIRED + (@version >= 2 ? V2_PRODUCTION_REQUIRED : [])
286
- optional = @version >= 2 ? %w[node] : Array.new(0) #: Array[String]
300
+ required = PRODUCTION_REQUIRED + PRODUCTION_METADATA_REQUIRED
301
+ optional = %w[node] #: Array[String]
287
302
  production = record(value, path, required, optional)
288
303
  id = nonnegative_integer(production["id"], "#{path}.id")
289
304
  invalid("#{path}.id", "must equal its array index #{index}") unless id == index
290
305
  @productions_by_id[id] = production
291
306
  validate_lhs(production["lhs"], "#{path}.lhs")
292
- validate_rhs(production["rhs"], "#{path}.rhs")
293
- validate_action(production["action"], "#{path}.action", rhs_length: production["rhs"].length)
307
+ rhs = array(production["rhs"], "#{path}.rhs")
308
+ validate_rhs(rhs, "#{path}.rhs")
309
+ validate_action(production["action"], "#{path}.action", rhs_length: rhs.length)
294
310
  validate_precedence_override(production["prec_override"], "#{path}.prec_override")
295
311
  validate_origin(production["origin"], "#{path}.origin")
296
- return unless @version >= 2
297
-
298
312
  nullable_string(production["doc"], "#{path}.doc")
299
313
  validate_expansion(production["expansion"], "#{path}.expansion")
300
- validate_node_annotation(production["node"], "#{path}.node", rhs_length: production["rhs"].length)
314
+ validate_node_annotation(production["node"], "#{path}.node", rhs_length: rhs.length)
301
315
  end
302
316
 
303
- # @rbs (untyped value, String path, rhs_length: Integer) -> void
317
+ # @rbs (json_value value, String path, rhs_length: Integer) -> void
304
318
  def validate_node_annotation(value, path, rhs_length:)
305
319
  return if value.nil?
306
320
 
@@ -320,7 +334,7 @@ module Ibex
320
334
  location(node["loc"], "#{path}.loc", nullable: false)
321
335
  end
322
336
 
323
- # @rbs (untyped value, String path) -> void
337
+ # @rbs (json_value value, String path) -> void
324
338
  def validate_lhs(value, path)
325
339
  id = nonnegative_integer(value, path)
326
340
  symbol = @symbols_by_id[id]
@@ -328,7 +342,7 @@ module Ibex
328
342
  invalid(path, "must reference a nonterminal") unless symbol["kind"] == "nonterminal"
329
343
  end
330
344
 
331
- # @rbs (untyped value, String path) -> void
345
+ # @rbs (json_value value, String path) -> void
332
346
  def validate_rhs(value, path)
333
347
  array(value, path).each_with_index do |id, index|
334
348
  id = nonnegative_integer(id, "#{path}[#{index}]")
@@ -336,24 +350,22 @@ module Ibex
336
350
  end
337
351
  end
338
352
 
339
- # @rbs (untyped value, String path, rhs_length: Integer) -> void
353
+ # @rbs (json_value value, String path, rhs_length: Integer) -> void
340
354
  def validate_action(value, path, rhs_length:)
341
355
  return if value.nil?
342
356
 
343
- required = %w[code loc named_refs context_length] + (@version >= 2 ? V2_ACTION_REQUIRED : [])
357
+ required = %w[code loc named_refs context_length] + ACTION_COMPOSITION_REQUIRED
344
358
  action = record(value, path, required)
345
359
  string(action["code"], "#{path}.code")
346
360
  location(action["loc"], "#{path}.loc", nullable: false)
347
361
  context_length = nonnegative_integer(action["context_length"], "#{path}.context_length")
348
362
  validate_named_refs(action["named_refs"], "#{path}.named_refs", limit: [rhs_length, context_length].max)
349
- return unless @version >= 2
350
-
351
363
  validate_action_composition(
352
364
  action["composition"], "#{path}.composition", rhs_length: rhs_length
353
365
  )
354
366
  end
355
367
 
356
- # @rbs (untyped value, String path, limit: Integer) -> void
368
+ # @rbs (json_value value, String path, limit: Integer) -> void
357
369
  def validate_named_refs(value, path, limit:)
358
370
  names = {} #: Hash[String, bool]
359
371
  array(value, path).each_with_index do |entry, index|
@@ -369,7 +381,7 @@ module Ibex
369
381
  end
370
382
  end
371
383
 
372
- # @rbs (untyped value, String path) -> void
384
+ # @rbs (json_value value, String path) -> void
373
385
  def validate_precedence_override(value, path)
374
386
  return if value.nil?
375
387
 
@@ -379,7 +391,7 @@ module Ibex
379
391
  invalid(path, "must reference a terminal") unless symbol["kind"] == "terminal"
380
392
  end
381
393
 
382
- # @rbs (untyped value, String path) -> void
394
+ # @rbs (json_value value, String path) -> void
383
395
  def validate_origin(value, path)
384
396
  origin = object(value, path)
385
397
  kind = string(field(origin, "kind", path), "#{path}.kind")
@@ -390,7 +402,7 @@ module Ibex
390
402
  location(origin["loc"], "#{path}.loc", nullable: false)
391
403
  end
392
404
 
393
- # @rbs (untyped value, String path) -> void
405
+ # @rbs (json_value value, String path) -> void
394
406
  def validate_string_map(value, path)
395
407
  object(value, path).each do |key, item|
396
408
  string(key, path)
@@ -405,7 +417,7 @@ module Ibex
405
417
  end
406
418
  end
407
419
 
408
- # @rbs (untyped value, String path) -> void
420
+ # @rbs (json_value value, String path) -> void
409
421
  def validate_warning(value, path)
410
422
  warning = record(value, path, %w[type loc], %w[symbol production original])
411
423
  nonempty_string(warning["type"], "#{path}.type")
@@ -415,13 +427,13 @@ module Ibex
415
427
  validate_warning_production(warning, "original", path) if warning.key?("original")
416
428
  end
417
429
 
418
- # @rbs (Hash[String, untyped] warning, String path) -> void
430
+ # @rbs (json_object warning, String path) -> void
419
431
  def validate_warning_symbol(warning, path)
420
432
  name = nonempty_string(warning["symbol"], "#{path}.symbol")
421
433
  invalid("#{path}.symbol", "references missing symbol #{name.inspect}") unless @symbols_by_name.key?(name)
422
434
  end
423
435
 
424
- # @rbs (Hash[String, untyped] warning, String field_name, String path) -> void
436
+ # @rbs (json_object warning, String field_name, String path) -> void
425
437
  def validate_warning_production(warning, field_name, path)
426
438
  id = nonnegative_integer(warning[field_name], "#{path}.#{field_name}")
427
439
  invalid("#{path}.#{field_name}", "references missing production id #{id}") unless @productions_by_id.key?(id)
@@ -430,11 +442,14 @@ module Ibex
430
442
  # @rbs () -> void
431
443
  def validate_lexer
432
444
  value = @data.fetch("lexer")
433
- LexerDocument.new(value, path: "#{@path}.lexer").validate
434
- value.fetch("rules").each_with_index do |rule, index|
435
- next unless rule["kind"] == "token"
436
-
437
- name = rule["token"]
445
+ lexer = value #: json_object
446
+ LexerDocument.new(lexer, path: "#{@path}.lexer").validate
447
+ rules = array(lexer.fetch("rules"), "#{@path}.lexer.rules")
448
+ rules.each_with_index do |rule, index|
449
+ rule_record = rule #: json_object
450
+ next unless rule_record["kind"] == "token"
451
+
452
+ name = nonempty_string(rule_record["token"], "#{@path}.lexer.rules[#{index}].token")
438
453
  symbol = @symbols_by_name[name]
439
454
  invalid("#{@path}.lexer.rules[#{index}].token", "references missing terminal #{name.inspect}") unless
440
455
  symbol&.fetch("kind") == "terminal"
@@ -455,7 +470,7 @@ module Ibex
455
470
  end
456
471
  end
457
472
 
458
- # @rbs (untyped value, String path, ?nullable: bool) -> void
473
+ # @rbs (json_value value, String path, ?nullable: bool) -> void
459
474
  def validate_source_provenance(value, path, nullable: true)
460
475
  return if nullable && value.nil?
461
476
 
@@ -465,7 +480,7 @@ module Ibex
465
480
  validate_byte_span(source["byte_span"], "#{path}.byte_span")
466
481
  end
467
482
 
468
- # @rbs (untyped value, String path) -> void
483
+ # @rbs (json_value value, String path) -> void
469
484
  def validate_byte_span(value, path)
470
485
  return if value.nil?
471
486
 
@@ -476,22 +491,35 @@ module Ibex
476
491
  end
477
492
 
478
493
  # @rbs () -> void
479
- def validate_migration
480
- path = "#{@path}.migration"
481
- value = @data["migration"]
482
- return if value.nil?
494
+ def validate_parser_contract
495
+ path = "#{@path}.parser_contract"
496
+ contract = record(@data["parser_contract"], path, %w[algorithm entries cst_trivia])
497
+ validate_contract_entry(contract["algorithm"], "#{path}.algorithm", %w[slr lalr ielr lr1])
498
+ validate_contract_entry(contract["entries"], "#{path}.entries", %w[shared isolated])
499
+ cst = validate_contract_entry(
500
+ contract["cst_trivia"], "#{path}.cst_trivia", %w[leading balanced drop]
501
+ )
502
+ return unless cst["explicit"]
503
+
504
+ invalid("#{path}.cst_trivia", "requires options.cst") unless @data.dig("options", "cst") == true
505
+ end
483
506
 
484
- migration = record(value, path, %w[from_schema_version unavailable])
485
- literal(migration["from_schema_version"], "#{path}.from_schema_version", 1)
486
- values = array(migration["unavailable"], "#{path}.unavailable")
487
- invalid("#{path}.unavailable", "must not be empty") if values.empty?
488
- values.each_with_index do |name, index|
489
- enum(name, "#{path}.unavailable[#{index}]", Migration::UNAVAILABLE_V1_METADATA)
507
+ # @rbs (untyped value, String, Array[String]) -> Hash[String, untyped]
508
+ def validate_contract_entry(value, path, allowed)
509
+ entry = record(value, path, %w[value explicit loc])
510
+ explicit = boolean(entry["explicit"], "#{path}.explicit")
511
+ unless explicit
512
+ literal(entry["value"], "#{path}.value", nil)
513
+ literal(entry["loc"], "#{path}.loc", nil)
514
+ return entry
490
515
  end
491
- invalid("#{path}.unavailable", "must contain unique names") unless values.uniq.length == values.length
516
+
517
+ enum(entry["value"], "#{path}.value", allowed)
518
+ location(entry["loc"], "#{path}.loc", nullable: false)
519
+ entry
492
520
  end
493
521
 
494
- # @rbs (untyped value, String path) -> void
522
+ # @rbs (json_value value, String path) -> void
495
523
  def validate_expansion(value, path)
496
524
  return if value.nil?
497
525
 
@@ -503,7 +531,7 @@ module Ibex
503
531
  end
504
532
  end
505
533
 
506
- # @rbs (untyped value, String path) -> void
534
+ # @rbs (json_value value, String path) -> void
507
535
  def validate_parameter_expansion(value, path)
508
536
  return if value.nil?
509
537
 
@@ -514,7 +542,7 @@ module Ibex
514
542
  end
515
543
  end
516
544
 
517
- # @rbs (untyped value, String path) -> void
545
+ # @rbs (json_value value, String path) -> void
518
546
  def validate_inline_expansion(value, path)
519
547
  return if value.nil?
520
548
 
@@ -522,7 +550,7 @@ module Ibex
522
550
  nonempty_string(inline["rule"], "#{path}.rule")
523
551
  end
524
552
 
525
- # @rbs (untyped value, String path, rhs_length: Integer) -> void
553
+ # @rbs (json_value value, String path, rhs_length: Integer) -> void
526
554
  def validate_action_composition(value, path, rhs_length:)
527
555
  return if value.nil?
528
556
 
@@ -540,7 +568,7 @@ module Ibex
540
568
  composition.key?("plan")
541
569
  end
542
570
 
543
- # @rbs (untyped value, String path, Integer rhs_length, Array[untyped] fragments) -> void
571
+ # @rbs (json_value value, String path, Integer rhs_length, Array[json_value] fragments) -> void
544
572
  def validate_action_composition_plan(value, path, rhs_length, fragments)
545
573
  plan = record(value, path, %w[version physical steps])
546
574
  literal(plan["version"], "#{path}.version", 1)
@@ -551,13 +579,15 @@ module Ibex
551
579
  invalid("#{path}.steps", "must align one-to-one with fragments") unless steps.length == fragments.length
552
580
  steps.each_with_index do |step, index|
553
581
  validate_action_composition_step(step, "#{path}.steps[#{index}]", physical, index)
554
- next if step["kind"] == fragments.fetch(index)["kind"]
582
+ step_record = step #: json_object
583
+ fragment_record = fragments.fetch(index) #: json_object
584
+ next if step_record["kind"] == fragment_record["kind"]
555
585
 
556
586
  invalid("#{path}.steps[#{index}].kind", "must match the corresponding fragment")
557
587
  end
558
588
  end
559
589
 
560
- # @rbs (untyped value, String path, Integer physical, Integer step_index) -> void
590
+ # @rbs (json_value value, String path, Integer physical, Integer step_index) -> void
561
591
  def validate_action_composition_step(value, path, physical, step_index)
562
592
  step = record(
563
593
  value, path,
@@ -581,7 +611,7 @@ module Ibex
581
611
  nullable_string(step["result_type"], "#{path}.result_type")
582
612
  end
583
613
 
584
- # @rbs (Array[untyped] inputs, String path, Integer limit) -> void
614
+ # @rbs (Array[json_value] inputs, String path, Integer limit) -> void
585
615
  def validate_action_slots(inputs, path, limit)
586
616
  inputs.each_with_index do |input, index|
587
617
  slot_path = "#{path}[#{index}]"
@@ -590,7 +620,7 @@ module Ibex
590
620
  end
591
621
  end
592
622
 
593
- # @rbs (untyped value, String path, Integer physical) -> void
623
+ # @rbs (json_value value, String path, Integer physical) -> void
594
624
  def validate_action_lookahead(value, path, physical)
595
625
  return if value.nil?
596
626
 
@@ -12,7 +12,7 @@ module Ibex
12
12
  id state kind token pattern pattern_kind options action loc
13
13
  ].freeze #: Array[String]
14
14
 
15
- # @rbs (Hash[String, untyped] data, ?path: String) -> void
15
+ # @rbs (json_object data, ?path: String) -> void
16
16
  def initialize(data, path: "$")
17
17
  super()
18
18
  @data = data
@@ -70,7 +70,7 @@ module Ibex
70
70
  end
71
71
  end
72
72
 
73
- # @rbs (Hash[String, untyped] rule, String path, String options) -> void
73
+ # @rbs (json_object rule, String path, String options) -> void
74
74
  def validate_pattern(rule, path, options)
75
75
  flags = 0
76
76
  flags |= Regexp::IGNORECASE if options.include?("i")
@@ -23,7 +23,8 @@ module Ibex
23
23
  supported = type == "lexer" ? SUPPORTED_LEXER_SCHEMA_VERSIONS : SUPPORTED_SCHEMA_VERSIONS
24
24
  unless supported.include?(version)
25
25
  expected = supported.join(", ")
26
- raise Ibex::Error, "#{POSITION}: unsupported schema_version #{version.inspect}; expected one of #{expected}"
26
+ raise Ibex::Error,
27
+ "#{POSITION}: unsupported schema_version #{version.inspect}; expected the current format (#{expected})"
27
28
  end
28
29
 
29
30
  case type
data/lib/ibex/ir.rb CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  require_relative "ir/grammar_ir"
4
4
  require_relative "ir/lexer_ir"
5
- require_relative "ir/migration"
6
5
  require_relative "ir/automaton_ir"
7
6
  require_relative "ir/serialize"
8
7
  require_relative "ir/validator"
@@ -11,6 +10,7 @@ module Ibex
11
10
  module IR
12
11
  # Shared static shapes used across analysis, automaton construction, and code generation.
13
12
  # @rbs!
13
+ # type serialized_value = untyped
14
14
  # type location = { file: String, line: Integer, column: Integer }
15
15
  # type precedence = { associativity: Symbol, level: Integer }
16
16
  # type named_ref = { name: String, index: Integer }
@@ -25,6 +25,9 @@ module Ibex
25
25
  # type grammar_test = { expectation: :accept | :reject, source: String, loc: location }
26
26
  # type node_annotation = { name: String, fields: Array[String], loc: location }
27
27
  # type lexer_warning = { type: :redos, rule: Integer, loc: location }
28
+ # type lexer_rule_document_value = Integer | String | Symbol | nil | location
29
+ # type lexer_document_value = String | Integer | Array[String] |
30
+ # Array[Hash[Symbol, lexer_rule_document_value]] | Array[lexer_warning] | source_provenance?
28
31
  # type parameter_expansion = { rule: String, arguments: Array[String] }
29
32
  # type inline_expansion = { rule: String }
30
33
  # type production_expansion = {
@@ -56,7 +59,6 @@ module Ibex
56
59
  # fragments: Array[action_fragment],
57
60
  # ?plan: action_composition_plan
58
61
  # }
59
- # type migration_metadata = { from_schema_version: Integer, unavailable: Array[String] }
60
62
  # type user_code_chunks = Hash[String, Array[UserCodeChunk]]
61
63
  # type grammar_options = { result_var: bool, omit_action_call: bool, ?cst: bool }
62
64
  # type grammar_mode = :default | :extended
@@ -92,7 +94,18 @@ module Ibex
92
94
  # ?expected_rr: Integer,
93
95
  # ?rr_expectation_met: bool
94
96
  # }
95
- # type interpretation = Hash[Symbol, untyped]
97
+ # type derivation_node = {
98
+ # symbol: String,
99
+ # ?token: String,
100
+ # ?production: Integer,
101
+ # ?children: Array[derivation_node]
102
+ # }
103
+ # type interpretation = {
104
+ # kind: Symbol,
105
+ # tree: derivation_node?,
106
+ # ?state: Integer,
107
+ # ?production: Integer
108
+ # }
96
109
  # type counterexample = {
97
110
  # state: Integer,
98
111
  # type: Symbol,
@@ -1,7 +1,10 @@
1
1
  # frozen_string_literal: true
2
+ # rbs_inline: enabled
2
3
 
3
4
  module Ibex
4
5
  module LALR
6
+ # Optional measurements are kept explicit for schema stability.
7
+ # rubocop:disable Metrics/ParameterLists
5
8
  # Immutable structural measurements from one automaton build. These counts
6
9
  # are intended for diagnostics and benchmarks, not parser behavior.
7
10
  class BuildMetrics
@@ -9,15 +12,60 @@ module Ibex
9
12
  attr_reader :canonical_states #: Integer?
10
13
  attr_reader :final_states #: Integer
11
14
  attr_reader :strategy #: Symbol
15
+ attr_reader :lr0_states #: Integer?
16
+ attr_reader :lr0_items #: Integer?
17
+ attr_reader :canonical_items #: Integer?
18
+ attr_reader :final_items #: Integer?
19
+ attr_reader :final_lookahead_items #: Integer?
20
+ attr_reader :propagation_edges #: Integer?
21
+ attr_reader :ielr_initial_partitions #: Integer?
22
+ attr_reader :ielr_final_partitions #: Integer?
23
+ attr_reader :ielr_annotations #: Integer?
24
+ attr_reader :ielr_annotated_states #: Integer?
25
+ attr_reader :ielr_inadequacies #: Integer?
26
+ attr_reader :ielr_split_stable_discarded #: Integer?
27
+ attr_reader :ielr_lalr_states #: Integer?
28
+ attr_reader :ielr_split_states #: Integer?
29
+ attr_reader :ielr_unreachable_removed #: Integer?
30
+ attr_reader :ielr_remergeable_candidates #: Integer?
12
31
 
13
- # @rbs (construction_states: Integer, canonical_states: Integer?, final_states: Integer, strategy: Symbol) -> void
14
- def initialize(construction_states:, canonical_states:, final_states:, strategy:)
32
+ # @rbs (construction_states: Integer, canonical_states: Integer?, final_states: Integer, strategy: Symbol,
33
+ # ?lr0_states: Integer?, ?lr0_items: Integer?, ?canonical_items: Integer?, ?final_items: Integer?,
34
+ # ?final_lookahead_items: Integer?, ?propagation_edges: Integer?, ?ielr_initial_partitions: Integer?,
35
+ # ?ielr_final_partitions: Integer?, ?ielr_annotations: Integer?, ?ielr_annotated_states: Integer?,
36
+ # ?ielr_inadequacies: Integer?, ?ielr_split_stable_discarded: Integer?, ?ielr_lalr_states: Integer?,
37
+ # ?ielr_split_states: Integer?, ?ielr_unreachable_removed: Integer?,
38
+ # ?ielr_remergeable_candidates: Integer?) -> void
39
+ def initialize(construction_states:, canonical_states:, final_states:, strategy:, lr0_states: nil, lr0_items: nil,
40
+ canonical_items: nil, final_items: nil, final_lookahead_items: nil, propagation_edges: nil,
41
+ ielr_initial_partitions: nil, ielr_final_partitions: nil, ielr_annotations: nil,
42
+ ielr_annotated_states: nil, ielr_inadequacies: nil, ielr_split_stable_discarded: nil,
43
+ ielr_lalr_states: nil, ielr_split_states: nil, ielr_unreachable_removed: nil,
44
+ ielr_remergeable_candidates: nil)
15
45
  @construction_states = construction_states
16
46
  @canonical_states = canonical_states
17
47
  @final_states = final_states
18
48
  @strategy = strategy
49
+ @lr0_states = lr0_states
50
+ @lr0_items = lr0_items
51
+ @canonical_items = canonical_items
52
+ @final_items = final_items
53
+ @final_lookahead_items = final_lookahead_items
54
+ @propagation_edges = propagation_edges
55
+ @ielr_initial_partitions = ielr_initial_partitions
56
+ @ielr_final_partitions = ielr_final_partitions
57
+ @ielr_annotations = ielr_annotations
58
+ @ielr_annotated_states = ielr_annotated_states
59
+ @ielr_inadequacies = ielr_inadequacies
60
+ @ielr_split_stable_discarded = ielr_split_stable_discarded
61
+ @ielr_lalr_states = ielr_lalr_states
62
+ @ielr_split_states = ielr_split_states
63
+ @ielr_unreachable_removed = ielr_unreachable_removed
64
+ @ielr_remergeable_candidates = ielr_remergeable_candidates
19
65
  freeze
20
66
  end
21
67
  end
22
68
  end
23
69
  end
70
+
71
+ # rubocop:enable Metrics/ParameterLists