ibex 0.2.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 (437) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +95 -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 +262 -0
  40. data/docs/development.md +179 -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 +1581 -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/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 +5 -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 +11 -0
  63. data/docs/release-readiness.md +126 -68
  64. data/docs/repair-semantics.md +123 -0
  65. data/docs/runtime-abi-evolution.md +307 -0
  66. data/docs/stability.md +144 -34
  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/lib/ibex/analysis/digraph.rb +128 -0
  75. data/lib/ibex/analysis.rb +1 -0
  76. data/lib/ibex/bison_import/importer.rb +516 -0
  77. data/lib/ibex/bison_import/tokenizer.rb +260 -0
  78. data/lib/ibex/bison_import.rb +200 -0
  79. data/lib/ibex/bounded_subprocess.rb +171 -0
  80. data/lib/ibex/cli/ambiguity.rb +14 -5
  81. data/lib/ibex/cli/analysis.rb +134 -0
  82. data/lib/ibex/cli/bison_import.rb +121 -0
  83. data/lib/ibex/cli/config.rb +128 -0
  84. data/lib/ibex/cli/diagnostics.rb +31 -11
  85. data/lib/ibex/cli/documentation.rb +11 -8
  86. data/lib/ibex/cli/equiv.rb +169 -0
  87. data/lib/ibex/cli/error_messages.rb +11 -4
  88. data/lib/ibex/cli/explain.rb +14 -5
  89. data/lib/ibex/cli/fix.rb +203 -0
  90. data/lib/ibex/cli/formatting.rb +11 -10
  91. data/lib/ibex/cli/fuzz.rb +200 -0
  92. data/lib/ibex/cli/fuzz_regressions.rb +145 -0
  93. data/lib/ibex/cli/generation_artifacts.rb +53 -2
  94. data/lib/ibex/cli/generation_error_messages.rb +1 -1
  95. data/lib/ibex/cli/grammar_tests.rb +32 -14
  96. data/lib/ibex/cli/ir_tools.rb +5 -61
  97. data/lib/ibex/cli/outputs.rb +60 -33
  98. data/lib/ibex/cli/reduce.rb +202 -0
  99. data/lib/ibex/cli/reduce_reporting.rb +71 -0
  100. data/lib/ibex/cli/samples.rb +49 -23
  101. data/lib/ibex/cli/verify.rb +116 -0
  102. data/lib/ibex/cli/watch.rb +6 -5
  103. data/lib/ibex/cli.rb +357 -56
  104. data/lib/ibex/codegen/action_locations.rb +1 -1
  105. data/lib/ibex/codegen/action_method_source.rb +5 -6
  106. data/lib/ibex/codegen/action_source.rb +3 -2
  107. data/lib/ibex/codegen/ambiguity.rb +5 -4
  108. data/lib/ibex/codegen/explain.rb +123 -55
  109. data/lib/ibex/codegen/generated_action_abi.rb +10 -5
  110. data/lib/ibex/codegen/rbs.rb +15 -7
  111. data/lib/ibex/codegen/report.rb +25 -13
  112. data/lib/ibex/codegen/ruby.rb +28 -64
  113. data/lib/ibex/codegen/ruby_actions.rb +9 -6
  114. data/lib/ibex/codegen/ruby_syntax.rb +15 -9
  115. data/lib/ibex/configuration/analysis_grammar.rb +35 -0
  116. data/lib/ibex/configuration/explanation.rb +421 -0
  117. data/lib/ibex/configuration/inspector.rb +232 -0
  118. data/lib/ibex/configuration.rb +580 -0
  119. data/lib/ibex/coverage/collector.rb +21 -11
  120. data/lib/ibex/coverage/event_stream.rb +13 -7
  121. data/lib/ibex/coverage/report.rb +26 -18
  122. data/lib/ibex/coverage/runtime_event_validator.rb +30 -21
  123. data/lib/ibex/delta_reducer.rb +99 -0
  124. data/lib/ibex/diff.rb +140 -0
  125. data/lib/ibex/equiv/machine.rb +135 -0
  126. data/lib/ibex/equiv.rb +373 -0
  127. data/lib/ibex/fix.rb +557 -0
  128. data/lib/ibex/frontend/ast.rb +22 -2
  129. data/lib/ibex/frontend/bootstrap_parser.rb +6 -13
  130. data/lib/ibex/frontend/diagnostic.rb +1 -1
  131. data/lib/ibex/frontend/formatter.rb +72 -26
  132. data/lib/ibex/frontend/generated_parser.rb +147 -117
  133. data/lib/ibex/frontend/generated_parser_base.rb +7 -3
  134. data/lib/ibex/frontend/generated_parser_includes.rb +1 -11
  135. data/lib/ibex/frontend/generation.rb +1 -1
  136. data/lib/ibex/frontend/parser/declarations.rb +17 -2
  137. data/lib/ibex/frontend/parser_configuration_support.rb +56 -0
  138. data/lib/ibex/frontend/regenerator.rb +1 -0
  139. data/lib/ibex/frontend/resolution.rb +2 -1
  140. data/lib/ibex/frontend/resolver.rb +1 -1
  141. data/lib/ibex/frontend/rule_documentation.rb +2 -1
  142. data/lib/ibex/frontend/source_cursor.rb +2 -2
  143. data/lib/ibex/frontend/source_span.rb +9 -1
  144. data/lib/ibex/frontend/token_adapter/declaration_state.rb +38 -6
  145. data/lib/ibex/frontend/token_adapter.rb +10 -0
  146. data/lib/ibex/frontend.rb +1 -0
  147. data/lib/ibex/fuzz.rb +219 -0
  148. data/lib/ibex/generation_input.rb +1 -1
  149. data/lib/ibex/generation_manifest.rb +36 -25
  150. data/lib/ibex/generation_transaction.rb +1 -1
  151. data/lib/ibex/generation_transaction_recovery.rb +4 -4
  152. data/lib/ibex/generation_transaction_validation.rb +2 -2
  153. data/lib/ibex/grammar_tests.rb +1 -1
  154. data/lib/ibex/ir/automaton_ir.rb +61 -19
  155. data/lib/ibex/ir/grammar_ir.rb +76 -45
  156. data/lib/ibex/ir/lexer_ir.rb +5 -5
  157. data/lib/ibex/ir/parser_contract.rb +135 -0
  158. data/lib/ibex/ir/serialize.rb +203 -76
  159. data/lib/ibex/ir/validator/automaton.rb +64 -34
  160. data/lib/ibex/ir/validator/base.rb +51 -33
  161. data/lib/ibex/ir/validator/grammar.rb +113 -83
  162. data/lib/ibex/ir/validator/lexer.rb +2 -2
  163. data/lib/ibex/ir/validator.rb +2 -1
  164. data/lib/ibex/ir.rb +16 -3
  165. data/lib/ibex/lalr/build_metrics.rb +50 -2
  166. data/lib/ibex/lalr/builder.rb +191 -56
  167. data/lib/ibex/lalr/conflict_search.rb +15 -4
  168. data/lib/ibex/lalr/counterexample.rb +19 -14
  169. data/lib/ibex/lalr/direct_lookaheads.rb +110 -57
  170. data/lib/ibex/lalr/goto_follows.rb +229 -0
  171. data/lib/ibex/lalr/ielr/annotator.rb +214 -0
  172. data/lib/ibex/lalr/ielr/bits.rb +28 -0
  173. data/lib/ibex/lalr/ielr/inadequacy.rb +47 -0
  174. data/lib/ibex/lalr/ielr/item_lookaheads.rb +78 -0
  175. data/lib/ibex/lalr/ielr/pipeline.rb +75 -0
  176. data/lib/ibex/lalr/ielr/split_stability.rb +78 -0
  177. data/lib/ibex/lalr/ielr/split_state.rb +20 -0
  178. data/lib/ibex/lalr/ielr/state_splitter.rb +258 -0
  179. data/lib/ibex/lalr/ielr_partition.rb +22 -8
  180. data/lib/ibex/lalr/inadequacy_report.rb +50 -0
  181. data/lib/ibex/lalr/lookahead_propagation.rb +111 -0
  182. data/lib/ibex/lalr/lr0_collection.rb +121 -0
  183. data/lib/ibex/lalr/unreachable_states.rb +80 -0
  184. data/lib/ibex/lalr.rb +52 -1
  185. data/lib/ibex/location.rb +3 -3
  186. data/lib/ibex/lsp/document_handlers.rb +9 -7
  187. data/lib/ibex/lsp/initialization_handlers.rb +9 -7
  188. data/lib/ibex/lsp/navigation_handlers.rb +25 -11
  189. data/lib/ibex/lsp/parser_configuration_assistance.rb +149 -0
  190. data/lib/ibex/lsp/position_codec.rb +6 -2
  191. data/lib/ibex/lsp/request_handlers.rb +3 -2
  192. data/lib/ibex/lsp/request_support.rb +14 -7
  193. data/lib/ibex/lsp/server.rb +13 -11
  194. data/lib/ibex/lsp/symbol_index.rb +13 -13
  195. data/lib/ibex/lsp/symbol_index_builder.rb +30 -20
  196. data/lib/ibex/lsp/symbol_occurrence.rb +8 -2
  197. data/lib/ibex/lsp/transport.rb +13 -3
  198. data/lib/ibex/lsp/workspace.rb +5 -4
  199. data/lib/ibex/lsp/workspace_analyzer.rb +1 -1
  200. data/lib/ibex/lsp.rb +1 -0
  201. data/lib/ibex/messages/en.yml +28 -0
  202. data/lib/ibex/messages/ja.yml +28 -0
  203. data/lib/ibex/messages.rb +68 -0
  204. data/lib/ibex/metrics.rb +175 -0
  205. data/lib/ibex/normalize/declarations.rb +2 -0
  206. data/lib/ibex/normalize/diagnostics.rb +63 -38
  207. data/lib/ibex/normalize/expander.rb +5 -4
  208. data/lib/ibex/normalize/expression.rb +8 -6
  209. data/lib/ibex/normalize/grammar_builder.rb +26 -0
  210. data/lib/ibex/normalize/inline_expansion.rb +100 -49
  211. data/lib/ibex/normalize/lexer.rb +3 -3
  212. data/lib/ibex/normalize/parameter_ebnf_lowering.rb +11 -10
  213. data/lib/ibex/normalize/parameter_lowering.rb +40 -23
  214. data/lib/ibex/normalize/parameters.rb +31 -4
  215. data/lib/ibex/normalize/parser_configuration.rb +70 -0
  216. data/lib/ibex/normalize.rb +10 -20
  217. data/lib/ibex/racc_migration/report.rb +6 -3
  218. data/lib/ibex/rake_task.rb +1 -1
  219. data/lib/ibex/samples.rb +43 -13
  220. data/lib/ibex/table_artifact/builder.rb +266 -0
  221. data/lib/ibex/table_artifact/cst_projection.rb +70 -0
  222. data/lib/ibex/table_artifact/document.rb +39 -0
  223. data/lib/ibex/table_artifact/executor.rb +187 -0
  224. data/lib/ibex/table_artifact/serializer.rb +57 -0
  225. data/lib/ibex/table_artifact/validator/metadata.rb +179 -0
  226. data/lib/ibex/table_artifact/validator/support.rb +86 -0
  227. data/lib/ibex/table_artifact/validator/tables.rb +238 -0
  228. data/lib/ibex/table_artifact/validator.rb +253 -0
  229. data/lib/ibex/table_artifact.rb +88 -0
  230. data/lib/ibex/table_simulation/result.rb +6 -2
  231. data/lib/ibex/table_simulation/step.rb +3 -1
  232. data/lib/ibex/tables.rb +14 -0
  233. data/lib/ibex/verifiable_generation_bundle.rb +86 -0
  234. data/lib/ibex/verification_report/builder.rb +159 -0
  235. data/lib/ibex/verification_report/canonical_ir.rb +123 -0
  236. data/lib/ibex/verification_report/logical_path.rb +68 -0
  237. data/lib/ibex/verification_report/validator.rb +329 -0
  238. data/lib/ibex/verification_report.rb +69 -0
  239. data/lib/ibex/verify/action_correspondence.rb +138 -0
  240. data/lib/ibex/verify/language_witness.rb +295 -0
  241. data/lib/ibex/verify/reference_collection.rb +190 -0
  242. data/lib/ibex/verify/result.rb +73 -0
  243. data/lib/ibex/verify/verifier.rb +598 -0
  244. data/lib/ibex/verify.rb +15 -0
  245. data/lib/ibex/version.rb +1 -1
  246. data/lib/ibex/watch/runner.rb +10 -1
  247. data/lib/ibex/watch/source_snapshot.rb +13 -8
  248. data/lib/ibex.rb +10 -0
  249. data/schema/{automaton-ir-v1.schema.json → automaton-ir-definitions.schema.json} +6 -6
  250. data/schema/{automaton-ir-v2.schema.json → automaton-ir.schema.json} +14 -7
  251. data/schema/bison-import-v1.schema.json +106 -0
  252. data/schema/conflict-explanation-review-v1.schema.json +196 -0
  253. data/schema/conflict-explanation-study-v1.schema.json +528 -0
  254. data/schema/construction-profile-v1.schema.json +779 -0
  255. data/schema/diff-v1.schema.json +41 -0
  256. data/schema/direct-ielr-decision-v1.schema.json +200 -0
  257. data/schema/equiv-v1.schema.json +64 -0
  258. data/schema/error-ux-review-v1.schema.json +609 -0
  259. data/schema/error-ux-round2-review-v1.schema.json +191 -0
  260. data/schema/error-ux-round2-v1.schema.json +519 -0
  261. data/schema/explain-v1.schema.json +63 -1
  262. data/schema/fix-v1.schema.json +64 -0
  263. data/schema/fix-v2.schema.json +66 -0
  264. data/schema/fix-v3.schema.json +101 -0
  265. data/schema/fuzz-regression-v1.schema.json +79 -0
  266. data/schema/fuzz-v1.schema.json +114 -0
  267. data/schema/{grammar-ir-v2.schema.json → grammar-ir-extensions.schema.json} +20 -65
  268. data/schema/{grammar-ir-v1.schema.json → grammar-ir-foundation.schema.json} +3 -3
  269. data/schema/grammar-ir.schema.json +271 -0
  270. data/schema/ielr-benchmark-v1.schema.json +85 -0
  271. data/schema/lexer-profile-v1.schema.json +491 -0
  272. data/schema/metrics-v1.schema.json +60 -0
  273. data/schema/reduce-v1.schema.json +22 -0
  274. data/schema/reduce-v2.schema.json +63 -0
  275. data/schema/table-artifact-v1.schema.json +377 -0
  276. data/schema/verification-report-v1.schema.json +222 -0
  277. data/schema/verify-v1.schema.json +42 -0
  278. data/sig/ibex/analysis/digraph.rbs +19 -0
  279. data/sig/ibex/bison_import/importer.rbs +140 -0
  280. data/sig/ibex/bison_import/tokenizer.rbs +91 -0
  281. data/sig/ibex/bison_import.rbs +95 -0
  282. data/sig/ibex/bounded_subprocess.rbs +76 -0
  283. data/sig/ibex/cli/ambiguity.rbs +6 -0
  284. data/sig/ibex/cli/analysis.rbs +43 -0
  285. data/sig/ibex/cli/bison_import.rbs +32 -0
  286. data/sig/ibex/cli/config.rbs +35 -0
  287. data/sig/ibex/cli/diagnostics.rbs +16 -3
  288. data/sig/ibex/cli/documentation.rbs +5 -1
  289. data/sig/ibex/cli/equiv.rbs +49 -0
  290. data/sig/ibex/cli/error_messages.rbs +6 -0
  291. data/sig/ibex/cli/explain.rbs +6 -0
  292. data/sig/ibex/cli/fix.rbs +53 -0
  293. data/sig/ibex/cli/formatting.rbs +5 -1
  294. data/sig/ibex/cli/fuzz.rbs +47 -0
  295. data/sig/ibex/cli/fuzz_regressions.rbs +40 -0
  296. data/sig/ibex/cli/generation_artifacts.rbs +21 -2
  297. data/sig/ibex/cli/generation_error_messages.rbs +2 -2
  298. data/sig/ibex/cli/grammar_tests.rbs +15 -3
  299. data/sig/ibex/cli/ir_tools.rbs +7 -19
  300. data/sig/ibex/cli/outputs.rbs +9 -3
  301. data/sig/ibex/cli/reduce.rbs +60 -0
  302. data/sig/ibex/cli/reduce_reporting.rbs +27 -0
  303. data/sig/ibex/cli/samples.rbs +8 -0
  304. data/sig/ibex/cli/verify.rbs +28 -0
  305. data/sig/ibex/cli/watch.rbs +2 -2
  306. data/sig/ibex/cli.rbs +79 -5
  307. data/sig/ibex/codegen/action_method_source.rbs +4 -4
  308. data/sig/ibex/codegen/explain.rbs +45 -25
  309. data/sig/ibex/codegen/generated_action_abi.rbs +14 -10
  310. data/sig/ibex/codegen/rbs.rbs +12 -10
  311. data/sig/ibex/codegen/report.rbs +12 -12
  312. data/sig/ibex/codegen/ruby.rbs +18 -15
  313. data/sig/ibex/codegen/ruby_actions.rbs +6 -6
  314. data/sig/ibex/codegen/ruby_syntax.rbs +10 -8
  315. data/sig/ibex/configuration/analysis_grammar.rbs +13 -0
  316. data/sig/ibex/configuration/explanation.rbs +195 -0
  317. data/sig/ibex/configuration/inspector.rbs +53 -0
  318. data/sig/ibex/configuration.rbs +242 -0
  319. data/sig/ibex/coverage/collector.rbs +16 -14
  320. data/sig/ibex/coverage/event_stream.rbs +12 -10
  321. data/sig/ibex/coverage/report.rbs +20 -18
  322. data/sig/ibex/coverage/runtime_event_validator.rbs +38 -36
  323. data/sig/ibex/delta_reducer.rbs +38 -0
  324. data/sig/ibex/diff.rbs +47 -0
  325. data/sig/ibex/equiv/machine.rbs +54 -0
  326. data/sig/ibex/equiv.rbs +129 -0
  327. data/sig/ibex/fix.rbs +138 -0
  328. data/sig/ibex/frontend/ast.rbs +33 -7
  329. data/sig/ibex/frontend/bootstrap_parser.rbs +2 -0
  330. data/sig/ibex/frontend/diagnostic.rbs +2 -2
  331. data/sig/ibex/frontend/formatter.rbs +38 -30
  332. data/sig/ibex/frontend/generated_parser.rbs +87 -77
  333. data/sig/ibex/frontend/generated_parser_base.rbs +4 -2
  334. data/sig/ibex/frontend/parser/declarations.rbs +3 -0
  335. data/sig/ibex/frontend/parser_configuration_support.rbs +27 -0
  336. data/sig/ibex/frontend/resolution.rbs +3 -2
  337. data/sig/ibex/frontend/source_cursor.rbs +2 -2
  338. data/sig/ibex/frontend/source_span.rbs +5 -2
  339. data/sig/ibex/frontend/token_adapter/declaration_state.rbs +13 -1
  340. data/sig/ibex/frontend/token_adapter.rbs +6 -0
  341. data/sig/ibex/fuzz.rbs +71 -0
  342. data/sig/ibex/generation_input.rbs +2 -2
  343. data/sig/ibex/generation_manifest.rbs +35 -32
  344. data/sig/ibex/generation_transaction_recovery.rbs +2 -2
  345. data/sig/ibex/generation_transaction_validation.rbs +2 -2
  346. data/sig/ibex/grammar_tests.rbs +2 -2
  347. data/sig/ibex/ir/automaton_ir.rbs +30 -11
  348. data/sig/ibex/ir/grammar_ir.rbs +41 -27
  349. data/sig/ibex/ir/lexer_ir.rbs +8 -8
  350. data/sig/ibex/ir/parser_contract.rbs +69 -0
  351. data/sig/ibex/ir/serialize.rbs +63 -28
  352. data/sig/ibex/ir/validator/automaton.rbs +47 -44
  353. data/sig/ibex/ir/validator/base.rbs +35 -31
  354. data/sig/ibex/ir/validator/grammar.rbs +78 -67
  355. data/sig/ibex/ir/validator/lexer.rbs +4 -4
  356. data/sig/ibex/ir.rbs +9 -3
  357. data/sig/ibex/lalr/build_metrics.rbs +42 -2
  358. data/sig/ibex/lalr/builder.rbs +75 -24
  359. data/sig/ibex/lalr/conflict_search.rbs +5 -2
  360. data/sig/ibex/lalr/counterexample.rbs +17 -14
  361. data/sig/ibex/lalr/direct_lookaheads.rbs +35 -28
  362. data/sig/ibex/lalr/goto_follows.rbs +89 -0
  363. data/sig/ibex/lalr/ielr/annotator.rbs +67 -0
  364. data/sig/ibex/lalr/ielr/bits.rbs +14 -0
  365. data/sig/ibex/lalr/ielr/inadequacy.rbs +24 -0
  366. data/sig/ibex/lalr/ielr/item_lookaheads.rbs +35 -0
  367. data/sig/ibex/lalr/ielr/pipeline.rbs +17 -0
  368. data/sig/ibex/lalr/ielr/split_stability.rbs +27 -0
  369. data/sig/ibex/lalr/ielr/split_state.rbs +14 -0
  370. data/sig/ibex/lalr/ielr/state_splitter.rbs +76 -0
  371. data/sig/ibex/lalr/ielr_partition.rbs +17 -5
  372. data/sig/ibex/lalr/inadequacy_report.rbs +21 -0
  373. data/sig/ibex/lalr/lookahead_propagation.rbs +38 -0
  374. data/sig/ibex/lalr/lr0_collection.rbs +50 -0
  375. data/sig/ibex/lalr/unreachable_states.rbs +25 -0
  376. data/sig/ibex/lalr.rbs +11 -1
  377. data/sig/ibex/location.rbs +6 -6
  378. data/sig/ibex/lsp/document_handlers.rbs +8 -8
  379. data/sig/ibex/lsp/initialization_handlers.rbs +12 -12
  380. data/sig/ibex/lsp/navigation_handlers.rbs +15 -12
  381. data/sig/ibex/lsp/parser_configuration_assistance.rbs +49 -0
  382. data/sig/ibex/lsp/position_codec.rbs +8 -4
  383. data/sig/ibex/lsp/request_handlers.rbs +4 -4
  384. data/sig/ibex/lsp/request_support.rbs +8 -8
  385. data/sig/ibex/lsp/server.rbs +16 -16
  386. data/sig/ibex/lsp/symbol_index.rbs +20 -21
  387. data/sig/ibex/lsp/symbol_index_builder.rbs +9 -8
  388. data/sig/ibex/lsp/symbol_occurrence.rbs +11 -5
  389. data/sig/ibex/lsp/transport.rbs +18 -6
  390. data/sig/ibex/lsp/workspace.rbs +3 -2
  391. data/sig/ibex/lsp/workspace_analyzer.rbs +1 -1
  392. data/sig/ibex/messages.rbs +26 -0
  393. data/sig/ibex/metrics.rbs +50 -0
  394. data/sig/ibex/normalize/diagnostics.rbs +4 -4
  395. data/sig/ibex/normalize/expander.rbs +2 -2
  396. data/sig/ibex/normalize/expression.rbs +10 -8
  397. data/sig/ibex/normalize/grammar_builder.rbs +11 -0
  398. data/sig/ibex/normalize/inline_expansion.rbs +59 -50
  399. data/sig/ibex/normalize/lexer.rbs +4 -4
  400. data/sig/ibex/normalize/parameter_ebnf_lowering.rbs +15 -14
  401. data/sig/ibex/normalize/parameter_lowering.rbs +18 -18
  402. data/sig/ibex/normalize/parameters.rbs +13 -8
  403. data/sig/ibex/normalize/parser_configuration.rbs +23 -0
  404. data/sig/ibex/normalize.rbs +11 -5
  405. data/sig/ibex/racc_migration/report.rbs +8 -6
  406. data/sig/ibex/rake_task.rbs +1 -1
  407. data/sig/ibex/samples.rbs +13 -4
  408. data/sig/ibex/table_artifact/builder.rbs +93 -0
  409. data/sig/ibex/table_artifact/cst_projection.rbs +20 -0
  410. data/sig/ibex/table_artifact/document.rbs +27 -0
  411. data/sig/ibex/table_artifact/executor.rbs +66 -0
  412. data/sig/ibex/table_artifact/serializer.rbs +25 -0
  413. data/sig/ibex/table_artifact/validator/metadata.rbs +52 -0
  414. data/sig/ibex/table_artifact/validator/support.rbs +46 -0
  415. data/sig/ibex/table_artifact/validator/tables.rbs +63 -0
  416. data/sig/ibex/table_artifact/validator.rbs +66 -0
  417. data/sig/ibex/table_artifact.rbs +32 -0
  418. data/sig/ibex/table_simulation/result.rbs +8 -4
  419. data/sig/ibex/table_simulation/step.rbs +4 -2
  420. data/sig/ibex/tables.rbs +10 -9
  421. data/sig/ibex/verifiable_generation_bundle.rbs +24 -0
  422. data/sig/ibex/verification_report/builder.rbs +53 -0
  423. data/sig/ibex/verification_report/canonical_ir.rbs +41 -0
  424. data/sig/ibex/verification_report/logical_path.rbs +34 -0
  425. data/sig/ibex/verification_report/validator.rbs +114 -0
  426. data/sig/ibex/verification_report.rbs +44 -0
  427. data/sig/ibex/verify/action_correspondence.rbs +50 -0
  428. data/sig/ibex/verify/language_witness.rbs +112 -0
  429. data/sig/ibex/verify/reference_collection.rbs +63 -0
  430. data/sig/ibex/verify/result.rbs +52 -0
  431. data/sig/ibex/verify/verifier.rbs +170 -0
  432. data/sig/ibex/verify.rbs +6 -0
  433. data/sig/ibex/watch/runner.rbs +12 -2
  434. data/sig/ibex/watch/source_snapshot.rbs +13 -9
  435. metadata +232 -12
  436. data/lib/ibex/ir/migration.rb +0 -120
  437. data/sig/ibex/ir/migration.rbs +0 -34
@@ -13,7 +13,7 @@ module Ibex
13
13
 
14
14
  states = ["INITIAL"] #: Array[String]
15
15
  rules = [] #: Array[IR::LexerRule]
16
- warnings = [] #: Array[Hash[Symbol, untyped]]
16
+ warnings = [] #: Array[IR::lexer_warning]
17
17
  declaration.definitions.each do |definition|
18
18
  if definition.is_a?(Frontend::AST::LexerState)
19
19
  normalize_lexer_state(definition, states, rules, warnings)
@@ -29,7 +29,7 @@ module Ibex
29
29
  end
30
30
 
31
31
  # @rbs (Frontend::AST::LexerState definition, Array[String] states, Array[IR::LexerRule] rules,
32
- # Array[Hash[Symbol, untyped]] warnings) -> void
32
+ # Array[IR::lexer_warning] warnings) -> void
33
33
  def normalize_lexer_state(definition, states, rules, warnings)
34
34
  # @type self: Normalizer
35
35
  fail_at(definition.loc, "lexer state INITIAL is reserved") if definition.name == "INITIAL"
@@ -43,7 +43,7 @@ module Ibex
43
43
  end
44
44
 
45
45
  # @rbs (Frontend::AST::LexerRule definition, String state, Integer id,
46
- # Array[Hash[Symbol, untyped]] warnings) -> IR::LexerRule
46
+ # Array[IR::lexer_warning] warnings) -> IR::LexerRule
47
47
  def normalize_lexer_rule(definition, state, id, warnings)
48
48
  # @type self: Normalizer
49
49
  validate_lexer_token(definition)
@@ -5,17 +5,17 @@ module Ibex
5
5
  module NormalizeParameterEbnfLowering
6
6
  private
7
7
 
8
- # @rbs (Hash[Symbol, untyped] frame,
8
+ # @rbs (NormalizeParameters::parameter_frame frame,
9
9
  # Frontend::AST::Optional | Frontend::AST::Star | Frontend::AST::Plus item) -> void
10
10
  def lower_parameter_suffix(frame, item)
11
11
  frame.fetch(:operations).push([:finish_suffix, item], [:item, item.item])
12
12
  end
13
13
 
14
- # @rbs (Hash[Symbol, untyped] frame,
14
+ # @rbs (NormalizeParameters::parameter_frame frame,
15
15
  # Frontend::AST::Optional | Frontend::AST::Star | Frontend::AST::Plus item) -> void
16
16
  def finish_parameter_suffix(frame, item)
17
17
  # @type self: Normalizer
18
- base = frame.fetch(:values).pop
18
+ base = frame.fetch(:values).pop || raise(Ibex::Error, "missing parameter value")
19
19
  helper = case item
20
20
  when Frontend::AST::Optional then build_optional(item, base)
21
21
  when Frontend::AST::Star then build_star(item, base)
@@ -24,22 +24,22 @@ module Ibex
24
24
  frame.fetch(:values) << helper
25
25
  end
26
26
 
27
- # @rbs (Hash[Symbol, untyped] frame, Frontend::AST::SeparatedList item) -> void
27
+ # @rbs (NormalizeParameters::parameter_frame frame, Frontend::AST::SeparatedList item) -> void
28
28
  def lower_parameter_separated_list(frame, item)
29
29
  frame.fetch(:operations).push(
30
30
  [:finish_separated, item], [:item, item.separator], [:item, item.item]
31
31
  )
32
32
  end
33
33
 
34
- # @rbs (Hash[Symbol, untyped] frame, Frontend::AST::SeparatedList item) -> void
34
+ # @rbs (NormalizeParameters::parameter_frame frame, Frontend::AST::SeparatedList item) -> void
35
35
  def finish_parameter_separated_list(frame, item)
36
36
  # @type self: Normalizer
37
- separator = frame.fetch(:values).pop
38
- base = frame.fetch(:values).pop
37
+ separator = frame.fetch(:values).pop || raise(Ibex::Error, "missing parameter value")
38
+ base = frame.fetch(:values).pop || raise(Ibex::Error, "missing parameter value")
39
39
  frame.fetch(:values) << build_separated_list(item, base, separator)
40
40
  end
41
41
 
42
- # @rbs (Hash[Symbol, untyped] frame, Frontend::AST::Group item) -> void
42
+ # @rbs (NormalizeParameters::parameter_frame frame, Frontend::AST::Group item) -> void
43
43
  def lower_parameter_group(frame, item)
44
44
  # @type self: Normalizer
45
45
  reject_group_named_references(item)
@@ -51,7 +51,7 @@ module Ibex
51
51
  end
52
52
  end
53
53
 
54
- # @rbs (Hash[Symbol, untyped] frame, String helper, Frontend::AST::Group item,
54
+ # @rbs (NormalizeParameters::parameter_frame frame, String helper, Frontend::AST::Group item,
55
55
  # Array[Frontend::AST::item] alternative) -> void
56
56
  def start_parameter_group_alternative(frame, helper, item, alternative)
57
57
  operations = frame.fetch(:operations)
@@ -59,7 +59,8 @@ module Ibex
59
59
  alternative.reverse_each { |child| operations << [:item, child] }
60
60
  end
61
61
 
62
- # @rbs (Hash[Symbol, untyped] frame, String helper, Frontend::AST::Group item, Integer length) -> void
62
+ # @rbs (NormalizeParameters::parameter_frame frame, String helper,
63
+ # Frontend::AST::Group item, Integer length) -> void
63
64
  def finish_parameter_group_alternative(frame, helper, item, length)
64
65
  # @type self: Normalizer
65
66
  rhs = frame.fetch(:values).pop(length)
@@ -5,13 +5,14 @@ module Ibex
5
5
  module NormalizeParameterLowering
6
6
  private
7
7
 
8
- # @rbs (Hash[Symbol, untyped] frame) -> void
8
+ # @rbs (NormalizeParameters::parameter_frame frame) -> void
9
9
  def advance_parameter_alternative(frame)
10
10
  # @type self: Normalizer
11
11
  with_parameter_frame_context(frame) do
12
12
  operations = frame.fetch(:operations)
13
13
  if operations.any?
14
- process_parameter_operation(frame, operations.pop)
14
+ operation = operations.pop #: NormalizeParameters::parameter_operation
15
+ process_parameter_operation(frame, operation)
15
16
  elsif parameter_items_remaining?(frame)
16
17
  start_parameter_item(frame)
17
18
  else
@@ -20,10 +21,10 @@ module Ibex
20
21
  end
21
22
  end
22
23
 
23
- # @rbs (Hash[Symbol, untyped] frame) { () -> void } -> void
24
+ # @rbs (NormalizeParameters::parameter_frame frame) { () -> void } -> void
24
25
  def with_parameter_frame_context(frame)
25
26
  # @type self: Normalizer
26
- template, = frame.fetch(:current)
27
+ template, = frame.fetch(:current) || raise(Ibex::Error, "missing parameter alternative")
27
28
  previous_chain = @current_include_chain
28
29
  previous_expansion = @current_parameter_expansion
29
30
  reference = frame.fetch(:reference)
@@ -37,16 +38,16 @@ module Ibex
37
38
  @current_parameter_expansion = previous_expansion
38
39
  end
39
40
 
40
- # @rbs (Hash[Symbol, untyped] frame) -> bool
41
+ # @rbs (NormalizeParameters::parameter_frame frame) -> bool
41
42
  def parameter_items_remaining?(frame)
42
- _template, _rule, alternative = frame.fetch(:current)
43
+ _template, _rule, alternative = frame.fetch(:current) || raise(Ibex::Error, "missing parameter alternative")
43
44
  frame.fetch(:item_index) < alternative.items.length
44
45
  end
45
46
 
46
- # @rbs (Hash[Symbol, untyped] frame) -> void
47
+ # @rbs (NormalizeParameters::parameter_frame frame) -> void
47
48
  def start_parameter_item(frame)
48
49
  # @type self: Normalizer
49
- _template, _rule, alternative = frame.fetch(:current)
50
+ _template, _rule, alternative = frame.fetch(:current) || raise(Ibex::Error, "missing parameter alternative")
50
51
  index = frame.fetch(:item_index)
51
52
  item = alternative.items.fetch(index)
52
53
  frame[:item_index] = index + 1
@@ -59,25 +60,41 @@ module Ibex
59
60
  end
60
61
  end
61
62
 
62
- # @rbs (Hash[Symbol, untyped] frame, Array[untyped] operation) -> void
63
+ # @rbs (NormalizeParameters::parameter_frame frame, NormalizeParameters::parameter_operation operation) -> void
63
64
  def process_parameter_operation(frame, operation)
64
65
  # @type self: Normalizer
65
- kind, *arguments = operation
66
+ kind = operation.fetch(0) #: Symbol
66
67
  case kind
67
- when :item then lower_parameter_item(frame, arguments.fetch(0))
68
- when :finish_item then finish_parameter_item(frame, arguments.fetch(0))
69
- when :value then frame.fetch(:values) << arguments.fetch(0)
70
- when :finish_suffix then finish_parameter_suffix(frame, arguments.fetch(0))
71
- when :finish_separated then finish_parameter_separated_list(frame, arguments.fetch(0))
68
+ when :item
69
+ item = operation.fetch(1) #: Frontend::AST::item
70
+ lower_parameter_item(frame, item)
71
+ when :finish_item
72
+ item = operation.fetch(1) #: Frontend::AST::item
73
+ finish_parameter_item(frame, item)
74
+ when :value
75
+ value = operation.fetch(1) #: String
76
+ frame.fetch(:values) << value
77
+ when :finish_suffix
78
+ item = operation.fetch(1) #: Frontend::AST::Optional | Frontend::AST::Star | Frontend::AST::Plus
79
+ finish_parameter_suffix(frame, item)
80
+ when :finish_separated
81
+ item = operation.fetch(1) #: Frontend::AST::SeparatedList
82
+ finish_parameter_separated_list(frame, item)
72
83
  when :group_alternative
73
- start_parameter_group_alternative(frame, arguments.fetch(0), arguments.fetch(1), arguments.fetch(2))
84
+ helper = operation.fetch(1) #: String
85
+ item = operation.fetch(2) #: Frontend::AST::Group
86
+ alternative = operation.fetch(3) #: Array[Frontend::AST::item]
87
+ start_parameter_group_alternative(frame, helper, item, alternative)
74
88
  when :finish_group_alternative
75
- finish_parameter_group_alternative(frame, arguments.fetch(0), arguments.fetch(1), arguments.fetch(2))
89
+ helper = operation.fetch(1) #: String
90
+ item = operation.fetch(2) #: Frontend::AST::Group
91
+ length = operation.fetch(3) #: Integer
92
+ finish_parameter_group_alternative(frame, helper, item, length)
76
93
  else raise Ibex::Error, "internal parameter lowering operation #{kind.inspect}"
77
94
  end
78
95
  end
79
96
 
80
- # @rbs (Hash[Symbol, untyped] frame, Frontend::AST::item item) -> void
97
+ # @rbs (NormalizeParameters::parameter_frame frame, Frontend::AST::item item) -> void
81
98
  def lower_parameter_item(frame, item)
82
99
  # @type self: Normalizer
83
100
  case item
@@ -96,25 +113,25 @@ module Ibex
96
113
  end
97
114
  end
98
115
 
99
- # @rbs (Hash[Symbol, untyped] frame, Frontend::AST::ParameterizedReference item) -> void
116
+ # @rbs (NormalizeParameters::parameter_frame frame, Frontend::AST::ParameterizedReference item) -> void
100
117
  def lower_parameter_call(frame, item)
101
118
  # @type self: Normalizer
102
119
  helper, = schedule_parameter_specialization(item)
103
120
  frame.fetch(:values) << helper
104
121
  end
105
122
 
106
- # @rbs (Hash[Symbol, untyped] frame, Frontend::AST::item item) -> void
123
+ # @rbs (NormalizeParameters::parameter_frame frame, Frontend::AST::item item) -> void
107
124
  def finish_parameter_item(frame, item)
108
125
  # @type self: Normalizer
109
126
  rhs = frame.fetch(:rhs)
110
- rhs << frame.fetch(:values).pop
127
+ rhs << (frame.fetch(:values).pop || raise(Ibex::Error, "missing parameter value"))
111
128
  add_named_reference(item, frame.fetch(:named_refs), rhs.length - 1)
112
129
  end
113
130
 
114
- # @rbs (Hash[Symbol, untyped] frame) -> void
131
+ # @rbs (NormalizeParameters::parameter_frame frame) -> void
115
132
  def finish_parameter_alternative(frame)
116
133
  # @type self: Normalizer
117
- _template, rule, alternative = frame.fetch(:current)
134
+ _template, rule, alternative = frame.fetch(:current) || raise(Ibex::Error, "missing parameter alternative")
118
135
  action = normalize_action(alternative.action, frame.fetch(:named_refs))
119
136
  add_production(
120
137
  rule.lhs, frame.fetch(:rhs), action, alternative.precedence,
@@ -2,7 +2,33 @@
2
2
 
3
3
  module Ibex
4
4
  # Iterative, hygienic specialization of validated parameterized user rules.
5
+ # rubocop:disable Metrics/ModuleLength -- parameter-frame transitions are kept together for auditability.
5
6
  module NormalizeParameters
7
+ # @rbs!
8
+ # type parameter_operation =
9
+ # [:item | :finish_item, Frontend::AST::item] |
10
+ # [:value, String] |
11
+ # [:finish_suffix, Frontend::AST::Optional | Frontend::AST::Star | Frontend::AST::Plus] |
12
+ # [:finish_separated, Frontend::AST::SeparatedList] |
13
+ # [:group_alternative, String, Frontend::AST::Group, Array[Frontend::AST::item]] |
14
+ # [:finish_group_alternative, String, Frontend::AST::Group, Integer]
15
+ # type parameter_frame = {
16
+ # reference: Frontend::AST::ParameterizedReference,
17
+ # arguments: Array[Frontend::AST::item],
18
+ # helper: String,
19
+ # bindings: Hash[String, Frontend::AST::item],
20
+ # rendered_arguments: Array[String],
21
+ # templates: Array[Frontend::AST::Rule],
22
+ # template_index: Integer,
23
+ # alternative_index: Integer,
24
+ # current: [Frontend::AST::Rule, Frontend::AST::Rule, Frontend::AST::Alternative]?,
25
+ # item_index: Integer,
26
+ # rhs: Array[String],
27
+ # named_refs: Array[IR::named_ref],
28
+ # operations: Array[parameter_operation],
29
+ # values: Array[String]
30
+ # }
31
+
6
32
  private
7
33
 
8
34
  # @rbs (Frontend::AST::ParameterizedReference reference) -> String
@@ -111,7 +137,7 @@ module Ibex
111
137
 
112
138
  # @rbs (Frontend::AST::ParameterizedReference reference, String helper,
113
139
  # Array[Frontend::AST::item] arguments, Array[String] rendered_arguments) ->
114
- # Hash[Symbol, untyped]
140
+ # NormalizeParameters::parameter_frame
115
141
  def parameter_frame(reference, helper, arguments, rendered_arguments)
116
142
  # @type self: Normalizer
117
143
  formals = @parameter_formals.fetch(reference.name)
@@ -150,7 +176,7 @@ module Ibex
150
176
  @parameter_worklist_active = false
151
177
  end
152
178
 
153
- # @rbs (Hash[Symbol, untyped] frame) -> bool
179
+ # @rbs (NormalizeParameters::parameter_frame frame) -> bool
154
180
  def prepare_parameter_alternative?(frame)
155
181
  # @type self: Normalizer
156
182
  templates = frame.fetch(:templates)
@@ -167,7 +193,7 @@ module Ibex
167
193
  false
168
194
  end
169
195
 
170
- # @rbs (Hash[Symbol, untyped] frame, Frontend::AST::Rule template, Integer index) -> void
196
+ # @rbs (NormalizeParameters::parameter_frame frame, Frontend::AST::Rule template, Integer index) -> void
171
197
  def prepare_parameter_alternative_entry(frame, template, index)
172
198
  # @type self: Normalizer
173
199
  alternative = substitute_parameter_alternative(
@@ -186,7 +212,7 @@ module Ibex
186
212
  frame[:values] = []
187
213
  end
188
214
 
189
- # @rbs (Hash[Symbol, untyped] frame) -> void
215
+ # @rbs (NormalizeParameters::parameter_frame frame) -> void
190
216
  def clear_parameter_alternative(frame)
191
217
  frame[:current] = nil
192
218
  frame[:item_index] = 0
@@ -196,4 +222,5 @@ module Ibex
196
222
  frame[:values] = []
197
223
  end
198
224
  end
225
+ # rubocop:enable Metrics/ModuleLength
199
226
  end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibex
4
+ # Converts a root parser declaration into the explicit current Grammar IR contract.
5
+ module NormalizeParserConfiguration
6
+ private
7
+
8
+ # @rbs (Frontend::AST::ParserConfiguration declaration) -> void
9
+ def read_parser_configuration(declaration)
10
+ # @type self: Normalizer
11
+ fail_at(declaration.loc, "parser declarations require extended mode") unless @mode == :extended
12
+ fail_at(declaration.loc, "duplicate parser declaration") if @parser_configuration
13
+
14
+ @parser_configuration = declaration
15
+ end
16
+
17
+ # @rbs () -> IR::ParserContract?
18
+ def normalized_parser_contract
19
+ # @type self: Normalizer
20
+ declaration = @parser_configuration
21
+ return unless declaration
22
+
23
+ entries = {} #: Hash[Symbol, IR::ParserContract::Entry]
24
+ declaration.settings.each do |setting|
25
+ validated_parser_setting_definition(setting)
26
+ fail_at(setting.loc, "duplicate parser setting #{setting.key}") if entries.key?(setting.key)
27
+
28
+ if setting.key == :cst_trivia && @options[:cst] != true
29
+ fail_at(setting.loc, "parser.cst_trivia requires pragma cst")
30
+ end
31
+
32
+ entries[setting.key] = IR::ParserContract::Entry.new(
33
+ setting.key, value: setting.value, location: parser_setting_location(setting), explicit: true
34
+ )
35
+ end
36
+ validate_isolated_entries(declaration)
37
+ IR::ParserContract.new(**entries)
38
+ end
39
+
40
+ # @rbs (Frontend::AST::ParserSetting setting) -> Hash[Symbol, Object?]
41
+ def validated_parser_setting_definition(setting)
42
+ # @type self: Normalizer
43
+ definition = IR::ParserContract::DEFINITIONS[setting.key]
44
+ unless %i[algorithm entries cst_trivia].include?(setting.key) && definition
45
+ fail_at(setting.loc, "unknown parser setting #{setting.key}")
46
+ end
47
+ unless definition.fetch(:values).include?(setting.value)
48
+ allowed = definition.fetch(:values).join(", ")
49
+ fail_at(setting.loc, "parser.#{setting.key} must be one of #{allowed}; got #{setting.value}")
50
+ end
51
+ definition
52
+ end
53
+
54
+ # @rbs (Frontend::AST::ParserConfiguration declaration) -> void
55
+ def validate_isolated_entries(declaration)
56
+ # @type self: Normalizer
57
+ setting = declaration.settings.find { |candidate| candidate.key == :entries && candidate.value == :isolated }
58
+ return unless setting && @start_names.length < 2
59
+
60
+ fail_at(setting.loc, "parser.entries isolated requires at least two start symbols")
61
+ end
62
+
63
+ # @rbs (Frontend::AST::ParserSetting setting) -> Location
64
+ def parser_setting_location(setting)
65
+ # @type self: Normalizer
66
+ location = setting.loc
67
+ Location.new(file: location.file, line: location.line, column: location.column)
68
+ end
69
+ end
70
+ end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "normalize/declarations"
4
+ require_relative "normalize/parser_configuration"
5
+ require_relative "normalize/grammar_builder"
4
6
  require_relative "normalize/lexer"
5
7
  require_relative "normalize/recovery_declarations"
6
8
  require_relative "normalize/expression"
@@ -21,6 +23,8 @@ module Ibex
21
23
  # Converts a frontend AST into immutable Grammar IR.
22
24
  class Normalizer
23
25
  include NormalizeDeclarations
26
+ include NormalizeParserConfiguration
27
+ include NormalizeGrammarBuilder
24
28
  include NormalizeLexer
25
29
  include NormalizeRecoveryDeclarations
26
30
  include NormalizeParameterValidation
@@ -69,6 +73,7 @@ module Ibex
69
73
  # @rbs @on_error_reduce_groups: Array[Array[String]]
70
74
  # @rbs @grammar_tests: Array[IR::grammar_test]
71
75
  # @rbs @lexer_declaration: Frontend::AST::Lexer?
76
+ # @rbs @parser_configuration: Frontend::AST::ParserConfiguration?
72
77
  # @rbs @explicit_starts: Array[String]?
73
78
  # @rbs @start_names: Array[String]
74
79
  # @rbs @start_name: String
@@ -76,7 +81,7 @@ module Ibex
76
81
  # @rbs @parameter_templates: Hash[String, Array[Frontend::AST::Rule]]
77
82
  # @rbs @parameter_formals: Hash[String, Array[String]]
78
83
  # @rbs @parameter_specializations: Hash[[String, Array[String]], String]
79
- # @rbs @parameter_worklist: Array[Hash[Symbol, untyped]]
84
+ # @rbs @parameter_worklist: Array[NormalizeParameters::parameter_frame]
80
85
  # @rbs @parameter_worklist_active: bool
81
86
  # @rbs @max_parameter_specializations: Integer
82
87
  # @rbs @current_parameter_expansion: IR::parameter_expansion?
@@ -114,7 +119,7 @@ module Ibex
114
119
  @helper_sequence = 0
115
120
  @current_include_chain = [] #: Array[IR::source_provenance]
116
121
  @parameter_specializations = {} #: Hash[[String, Array[String]], String]
117
- @parameter_worklist = [] #: Array[Hash[Symbol, untyped]]
122
+ @parameter_worklist = [] #: Array[NormalizeParameters::parameter_frame]
118
123
  @parameter_worklist_active = false
119
124
  @max_parameter_specializations = max_parameter_specializations
120
125
  @max_inline_expansions = max_inline_expansions
@@ -131,33 +136,18 @@ module Ibex
131
136
  intern_reserved_symbols
132
137
  intern_declared_terminals
133
138
  intern_user_nonterminals
139
+ parser_contract = normalized_parser_contract
134
140
  normalize_user_productions
135
141
  expand_inline_rules
136
142
  validate_value_printers
137
143
  validate_recovery_declarations
138
144
  validate_grammar
139
- IR::Grammar.new(class_name: @ast.class_name, superclass: @ast.superclass, start: @start_name,
140
- expect: @expected_conflicts, options: @options, symbols: @symbols,
141
- mode: @mode, starts: @start_names,
142
- expect_rr: @expected_rr_conflicts,
143
- parser_parameters: @parser_parameters,
144
- value_printers: @value_printers.values,
145
- grammar_tests: @grammar_tests,
146
- lexer: normalize_lexer,
147
- recovery: {
148
- sync_tokens: @recovery_sync_tokens,
149
- on_error_reduce: @on_error_reduce_groups
150
- },
151
- productions: @productions, user_code: normalized_user_code,
152
- conversions: @conversions, warnings: @warnings, user_code_chunks: normalized_user_code_chunks,
153
- source_provenance: {
154
- file: @ast.loc.file, root: @resolution&.root_directory, byte_span: nil
155
- })
145
+ build_grammar(parser_contract)
156
146
  end
157
147
 
158
148
  private
159
149
 
160
- # @rbs (Symbol name, untyped value) -> void
150
+ # @rbs (Symbol name, Object value) -> void
161
151
  def validate_positive_limit!(name, value)
162
152
  return if value.is_a?(Integer) && value.positive?
163
153
 
@@ -5,6 +5,9 @@ require "json"
5
5
 
6
6
  module Ibex
7
7
  module RaccMigration
8
+ # @rbs!
9
+ # type json_value = String | Integer | Float | bool | nil | Array[json_value] | Hash[String, json_value]
10
+
8
11
  # One immutable migration compatibility observation.
9
12
  class Finding
10
13
  SEVERITIES = %i[error warning info].freeze #: Array[Symbol]
@@ -30,7 +33,7 @@ module Ibex
30
33
  freeze
31
34
  end
32
35
 
33
- # @rbs () -> Hash[String, untyped]
36
+ # @rbs () -> Hash[String, json_value]
34
37
  def to_h
35
38
  {
36
39
  "code" => @code,
@@ -61,7 +64,7 @@ module Ibex
61
64
  # @rbs () -> bool
62
65
  def compatible? = @findings.none? { |finding| finding.severity == :error }
63
66
 
64
- # @rbs () -> Hash[String, untyped]
67
+ # @rbs () -> Hash[String, json_value]
65
68
  def to_h
66
69
  {
67
70
  "ibex_migration_check" => "racc",
@@ -73,7 +76,7 @@ module Ibex
73
76
  }
74
77
  end
75
78
 
76
- # @rbs (*untyped) -> String
79
+ # @rbs (*Object?) -> String
77
80
  def to_json(*) = JSON.pretty_generate(to_h)
78
81
 
79
82
  # @rbs () -> String
@@ -13,7 +13,7 @@ require_relative "cli"
13
13
  # class Task
14
14
  # def self.define_task: (Hash[String | Symbol, String | Array[String]]) -> Task
15
15
  # | (Hash[String | Symbol, String | Array[String]]) {
16
- # (untyped, untyped) -> void
16
+ # (Object?, Object?) -> void
17
17
  # } -> Task
18
18
  # end
19
19
  #
data/lib/ibex/samples.rb CHANGED
@@ -7,17 +7,27 @@ module Ibex
7
7
  DEFAULT_MAX_EXPANSIONS = 100_000 #: Integer
8
8
 
9
9
  # @rbs (IR::Grammar grammar, ?seed: Integer, ?max_tokens: Integer, ?max_depth: Integer,
10
- # ?max_expansions: Integer) -> void
11
- def initialize(grammar, seed: 0, max_tokens: 32, max_depth: 16, max_expansions: DEFAULT_MAX_EXPANSIONS)
10
+ # ?max_expansions: Integer, ?strategy: Symbol | String, ?path_length: Integer) -> void
11
+ def initialize(grammar, seed: 0, max_tokens: 32, max_depth: 16, max_expansions: DEFAULT_MAX_EXPANSIONS,
12
+ strategy: :random, path_length: 1)
12
13
  raise ArgumentError, "max_tokens must be positive" unless max_tokens.positive?
13
14
  raise ArgumentError, "max_depth must be positive" unless max_depth.positive?
14
15
  raise ArgumentError, "max_expansions must be positive" unless max_expansions.positive?
15
16
 
17
+ normalized_strategy = strategy.to_sym
18
+ unless %i[random coverage].include?(normalized_strategy)
19
+ raise ArgumentError, "strategy must be :random or :coverage"
20
+ end
21
+ raise ArgumentError, "path_length must be 1 or 2" unless [1, 2].include?(path_length)
22
+
16
23
  @grammar = grammar
17
24
  @random = Random.new(seed)
18
25
  @max_tokens = max_tokens
19
26
  @max_depth = max_depth
20
27
  @max_expansions = max_expansions
28
+ @strategy = normalized_strategy
29
+ @path_length = path_length
30
+ @path_coverage = Hash.new(0) #: Hash[Array[Integer], Integer]
21
31
  @productions = grammar.productions.group_by(&:lhs)
22
32
  @minimum_costs = compute_minimum_costs
23
33
  @minimum_heights = compute_minimum_heights
@@ -120,7 +130,7 @@ module Ibex
120
130
  # @rbs (IR::GrammarSymbol start, Integer remaining_expansions) -> [Array[String], Integer]
121
131
  def expand(start, remaining_expansions)
122
132
  result = [] #: Array[String]
123
- work = [[start.id, 0]] #: Array[[Integer, Integer]]
133
+ work = [[start.id, 0, []]] #: Array[[Integer, Integer, Array[Integer]]]
124
134
  pending_minimum = minimum_cost!(start.id)
125
135
 
126
136
  while (entry = work.pop)
@@ -129,7 +139,7 @@ module Ibex
129
139
  end
130
140
 
131
141
  remaining_expansions -= 1
132
- symbol_id, depth = entry
142
+ symbol_id, depth, path = entry
133
143
  pending_minimum -= minimum_cost!(symbol_id)
134
144
  symbol = @grammar.symbol_by_id(symbol_id) ||
135
145
  raise(Ibex::Error, "(samples):1:1: missing symbol #{symbol_id}")
@@ -139,17 +149,30 @@ module Ibex
139
149
  end
140
150
 
141
151
  budget = @max_tokens - result.length - pending_minimum
142
- production = choose_production(symbol_id, budget, depth)
152
+ production = choose_production(symbol_id, budget, depth, path)
153
+ production_path = (path + [production.id]).last(@path_length)
154
+ @path_coverage[production_path] += 1
143
155
  pending_minimum += production_cost(production) ||
144
156
  raise(Ibex::Error, "(samples):1:1: no bounded derivation for symbol #{symbol_id}")
145
- production.rhs.reverse_each { |child_id| work << [child_id, depth + 1] }
157
+ production.rhs.reverse_each { |child_id| work << [child_id, depth + 1, production_path] }
146
158
  end
147
159
 
148
160
  [result, remaining_expansions]
149
161
  end
150
162
 
151
- # @rbs (Integer nonterminal_id, Integer budget, Integer depth) -> IR::Production
152
- def choose_production(nonterminal_id, budget, depth)
163
+ # @rbs (Integer nonterminal_id, Integer budget, Integer depth, Array[Integer] path) -> IR::Production
164
+ def choose_production(nonterminal_id, budget, depth, path)
165
+ candidates = bounded_productions(nonterminal_id, budget)
166
+ candidates = minimum_height_productions(candidates) if depth >= @max_depth
167
+ return candidates.fetch(@random.rand(candidates.length)) if @strategy == :random
168
+
169
+ minimum_coverage = candidates.map { |production| path_count(path, production) }.min
170
+ least_covered = candidates.select { |production| path_count(path, production) == minimum_coverage }
171
+ least_covered.fetch(@random.rand(least_covered.length))
172
+ end
173
+
174
+ # @rbs (Integer nonterminal_id, Integer budget) -> Array[IR::Production]
175
+ def bounded_productions(nonterminal_id, budget)
153
176
  productions = @productions[nonterminal_id]
154
177
  raise Ibex::Error, "(samples):1:1: no bounded derivation for symbol #{nonterminal_id}" unless productions
155
178
 
@@ -159,11 +182,18 @@ module Ibex
159
182
  end
160
183
  raise Ibex::Error, "(samples):1:1: no bounded derivation for symbol #{nonterminal_id}" if candidates.empty?
161
184
 
162
- if depth >= @max_depth
163
- minimum = candidates.filter_map { |production| production_height(production) }.min
164
- candidates = candidates.select { |production| production_height(production) == minimum }
165
- end
166
- candidates.fetch(@random.rand(candidates.length))
185
+ candidates
186
+ end
187
+
188
+ # @rbs (Array[IR::Production] candidates) -> Array[IR::Production]
189
+ def minimum_height_productions(candidates)
190
+ minimum = candidates.filter_map { |production| production_height(production) }.min
191
+ candidates.select { |production| production_height(production) == minimum }
192
+ end
193
+
194
+ # @rbs (Array[Integer] path, IR::Production production) -> Integer
195
+ def path_count(path, production)
196
+ @path_coverage[(path + [production.id]).last(@path_length)]
167
197
  end
168
198
 
169
199
  # @rbs (Integer symbol_id) -> Integer