ibex 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (603) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +89 -123
  3. data/docs/architecture.md +477 -31
  4. data/docs/bison-import.md +103 -0
  5. data/docs/comparison-policy.md +127 -0
  6. data/docs/configuration-model.md +59 -0
  7. data/docs/configuration-report.md +28 -0
  8. data/docs/conflict-explanation-reviews/v1/records/README.md +28 -0
  9. data/docs/conflict-explanation-study.md +62 -0
  10. data/docs/construction-profiling.md +157 -0
  11. data/docs/cst-migration.md +106 -0
  12. data/docs/cst.md +237 -0
  13. data/docs/decisions/0000-template.md +24 -0
  14. data/docs/decisions/0001-separate-ir-pipeline.md +34 -0
  15. data/docs/decisions/0002-opaque-user-code-boundary.md +32 -0
  16. data/docs/decisions/0003-self-hosted-grammar-frontend.md +32 -0
  17. data/docs/decisions/0004-shared-semantic-and-lossless-source-model.md +33 -0
  18. data/docs/decisions/0005-contained-grammar-composition.md +34 -0
  19. data/docs/decisions/0006-bounded-structural-grammar-lowering.md +32 -0
  20. data/docs/decisions/0007-shared-parser-construction-pipeline.md +33 -0
  21. data/docs/decisions/0008-versioned-runtime-package-boundary.md +36 -0
  22. data/docs/decisions/0009-isolated-parser-sessions.md +34 -0
  23. data/docs/decisions/0010-committed-runtime-observation.md +34 -0
  24. data/docs/decisions/0011-versioned-semantic-action-boundary.md +37 -0
  25. data/docs/decisions/0012-bounded-nonexecuting-analysis.md +37 -0
  26. data/docs/decisions/0013-transactional-generation-publication.md +37 -0
  27. data/docs/decisions/0014-versioned-generated-lexer.md +35 -0
  28. data/docs/decisions/0015-worker-isolated-browser-analysis.md +32 -0
  29. data/docs/decisions/0016-red-green-concrete-syntax.md +34 -0
  30. data/docs/decisions/0017-persistent-syntax-artifacts.md +35 -0
  31. data/docs/decisions/0018-conservative-incremental-syntax-reuse.md +38 -0
  32. data/docs/decisions/0019-runtime-syntax-session-boundary.md +51 -0
  33. data/docs/decisions/0020-grammar-ir-parser-contract.md +65 -0
  34. data/docs/decisions/0021-data-only-parser-table-sidecar.md +50 -0
  35. data/docs/decisions/0022-manifest-bound-verification-report.md +77 -0
  36. data/docs/decisions/0023-syntax-only-repair-results.md +48 -0
  37. data/docs/decisions/0024-direct-ielr-construction.md +42 -0
  38. data/docs/decisions/README.md +74 -0
  39. data/docs/declarative-configuration.md +262 -0
  40. data/docs/development.md +306 -0
  41. data/docs/direct-ielr-decision.md +120 -0
  42. data/docs/direct-multi-entry-decision.md +82 -0
  43. data/docs/editor-setup.md +26 -0
  44. data/docs/error-ux-review-rubric-v1.md +117 -0
  45. data/docs/error-ux-reviews/v1/records/README.md +22 -0
  46. data/docs/error-ux-round2-review-status-v1.json +27 -0
  47. data/docs/error-ux-round2-reviews/v1/records/README.md +30 -0
  48. data/docs/error-ux-round2-v1.json +1581 -0
  49. data/docs/error-ux-round2.md +111 -0
  50. data/docs/error-ux.md +114 -0
  51. data/docs/getting-started.md +80 -0
  52. data/docs/grammar-reference.md +629 -18
  53. data/docs/ielr-design.md +43 -0
  54. data/docs/ielr.md +92 -0
  55. data/docs/ja/bison-import.md +51 -0
  56. data/docs/ja/stable-api.md +53 -0
  57. data/docs/lexer-construction-profile.md +109 -0
  58. data/docs/lexer-migration.md +56 -0
  59. data/docs/maturity.md +128 -0
  60. data/docs/project-site-strategy.md +54 -0
  61. data/docs/racc-migration-evidence.md +45 -0
  62. data/docs/racc-migration.md +45 -6
  63. data/docs/release-readiness.md +221 -0
  64. data/docs/repair-semantics.md +123 -0
  65. data/docs/runtime-abi-evolution.md +307 -0
  66. data/docs/stability.md +234 -0
  67. data/docs/status.md +43 -0
  68. data/docs/syntax-sessions.md +183 -0
  69. data/docs/table-artifact.md +125 -0
  70. data/docs/test-interactions.md +219 -0
  71. data/docs/verification-report.md +137 -0
  72. data/docs/verifier-trust-boundary.md +199 -0
  73. data/docs/workloads.md +132 -0
  74. data/examples/README.md +60 -0
  75. data/examples/calculator.y +44 -0
  76. data/examples/csv.y +32 -0
  77. data/examples/ini.y +70 -0
  78. data/examples/json.y +48 -0
  79. data/examples/tiny_language.y +75 -0
  80. data/lib/ibex/analysis/digraph.rb +128 -0
  81. data/lib/ibex/analysis/sets.rb +5 -4
  82. data/lib/ibex/analysis.rb +1 -0
  83. data/lib/ibex/artifact_set.rb +63 -0
  84. data/lib/ibex/bison_import/importer.rb +516 -0
  85. data/lib/ibex/bison_import/tokenizer.rb +260 -0
  86. data/lib/ibex/bison_import.rb +200 -0
  87. data/lib/ibex/bounded_subprocess.rb +171 -0
  88. data/lib/ibex/cli/ambiguity.rb +75 -0
  89. data/lib/ibex/cli/analysis.rb +134 -0
  90. data/lib/ibex/cli/bison_import.rb +121 -0
  91. data/lib/ibex/cli/config.rb +128 -0
  92. data/lib/ibex/cli/counterexample_options.rb +6 -2
  93. data/lib/ibex/cli/coverage.rb +173 -0
  94. data/lib/ibex/cli/debug.rb +106 -0
  95. data/lib/ibex/cli/diagnostics.rb +136 -0
  96. data/lib/ibex/cli/documentation.rb +70 -0
  97. data/lib/ibex/cli/equiv.rb +169 -0
  98. data/lib/ibex/cli/error_messages.rb +184 -0
  99. data/lib/ibex/cli/explain.rb +85 -0
  100. data/lib/ibex/cli/fix.rb +203 -0
  101. data/lib/ibex/cli/formatting.rb +387 -0
  102. data/lib/ibex/cli/fuzz.rb +200 -0
  103. data/lib/ibex/cli/fuzz_regressions.rb +145 -0
  104. data/lib/ibex/cli/generation_artifacts.rb +189 -0
  105. data/lib/ibex/cli/generation_error_messages.rb +39 -0
  106. data/lib/ibex/cli/grammar_tests.rb +140 -0
  107. data/lib/ibex/cli/ir_tools.rb +128 -0
  108. data/lib/ibex/cli/lsp.rb +33 -0
  109. data/lib/ibex/cli/outputs.rb +133 -23
  110. data/lib/ibex/cli/racc_migration.rb +87 -0
  111. data/lib/ibex/cli/reduce.rb +202 -0
  112. data/lib/ibex/cli/reduce_reporting.rb +71 -0
  113. data/lib/ibex/cli/samples.rb +118 -0
  114. data/lib/ibex/cli/verify.rb +116 -0
  115. data/lib/ibex/cli/watch.rb +104 -0
  116. data/lib/ibex/cli.rb +825 -55
  117. data/lib/ibex/codegen/action_locations.rb +103 -0
  118. data/lib/ibex/codegen/action_method_source.rb +209 -0
  119. data/lib/ibex/codegen/action_source.rb +119 -0
  120. data/lib/ibex/codegen/ambiguity.rb +174 -0
  121. data/lib/ibex/codegen/cst_metadata.rb +171 -0
  122. data/lib/ibex/codegen/documentation.rb +170 -0
  123. data/lib/ibex/codegen/explain.rb +380 -0
  124. data/lib/ibex/codegen/generated_action_abi.rb +293 -0
  125. data/lib/ibex/codegen/html.rb +94 -10
  126. data/lib/ibex/codegen/mermaid.rb +43 -0
  127. data/lib/ibex/codegen/railroad.rb +197 -0
  128. data/lib/ibex/codegen/railroad_documentation.rb +59 -0
  129. data/lib/ibex/codegen/rbs.rb +331 -2
  130. data/lib/ibex/codegen/report.rb +67 -15
  131. data/lib/ibex/codegen/ruby.rb +305 -66
  132. data/lib/ibex/codegen/ruby_actions.rb +146 -0
  133. data/lib/ibex/codegen/ruby_ast.rb +121 -0
  134. data/lib/ibex/codegen/ruby_error_messages.rb +28 -0
  135. data/lib/ibex/codegen/ruby_lexer.rb +83 -0
  136. data/lib/ibex/codegen/ruby_syntax.rb +96 -0
  137. data/lib/ibex/codegen/ruby_table_metadata.rb +57 -0
  138. data/lib/ibex/codegen/ruby_value_printers.rb +56 -0
  139. data/lib/ibex/codegen/symbol_labels.rb +1 -1
  140. data/lib/ibex/configuration/analysis_grammar.rb +35 -0
  141. data/lib/ibex/configuration/explanation.rb +421 -0
  142. data/lib/ibex/configuration/inspector.rb +232 -0
  143. data/lib/ibex/configuration.rb +580 -0
  144. data/lib/ibex/coverage/collector.rb +198 -0
  145. data/lib/ibex/coverage/event_stream.rb +103 -0
  146. data/lib/ibex/coverage/report.rb +267 -0
  147. data/lib/ibex/coverage/runtime_event_validator.rb +169 -0
  148. data/lib/ibex/coverage.rb +13 -0
  149. data/lib/ibex/delta_reducer.rb +99 -0
  150. data/lib/ibex/diff.rb +140 -0
  151. data/lib/ibex/equiv/machine.rb +135 -0
  152. data/lib/ibex/equiv.rb +373 -0
  153. data/lib/ibex/error_messages/parser.rb +159 -0
  154. data/lib/ibex/error_messages/parser_v2.rb +198 -0
  155. data/lib/ibex/error_messages/renderer.rb +65 -0
  156. data/lib/ibex/error_messages/sentence_search.rb +196 -0
  157. data/lib/ibex/error_messages/update.rb +169 -0
  158. data/lib/ibex/error_messages.rb +165 -0
  159. data/lib/ibex/fix.rb +557 -0
  160. data/lib/ibex/frontend/ast.rb +166 -7
  161. data/lib/ibex/frontend/bootstrap_parser.rb +40 -4
  162. data/lib/ibex/frontend/diagnostic.rb +81 -0
  163. data/lib/ibex/frontend/diagnostic_recovery.rb +268 -0
  164. data/lib/ibex/frontend/dsl.rb +66 -7
  165. data/lib/ibex/frontend/formatter.rb +453 -0
  166. data/lib/ibex/frontend/generated_parser.rb +644 -190
  167. data/lib/ibex/frontend/generated_parser_base.rb +170 -32
  168. data/lib/ibex/frontend/generated_parser_includes.rb +51 -0
  169. data/lib/ibex/frontend/generated_parser_metadata.rb +61 -0
  170. data/lib/ibex/frontend/generated_parser_parameters.rb +60 -0
  171. data/lib/ibex/frontend/generation.rb +33 -0
  172. data/lib/ibex/frontend/lexer.rb +162 -10
  173. data/lib/ibex/frontend/lexer_recovery.rb +84 -0
  174. data/lib/ibex/frontend/parser/declarations.rb +262 -11
  175. data/lib/ibex/frontend/parser/parameters.rb +82 -0
  176. data/lib/ibex/frontend/parser/rules.rb +43 -6
  177. data/lib/ibex/frontend/parser.rb +182 -4
  178. data/lib/ibex/frontend/parser_configuration_support.rb +56 -0
  179. data/lib/ibex/frontend/regenerator.rb +27 -1
  180. data/lib/ibex/frontend/resolution.rb +70 -0
  181. data/lib/ibex/frontend/resolver.rb +217 -0
  182. data/lib/ibex/frontend/rule_documentation.rb +104 -0
  183. data/lib/ibex/frontend/source_cursor.rb +133 -9
  184. data/lib/ibex/frontend/source_document.rb +229 -0
  185. data/lib/ibex/frontend/source_loader.rb +150 -0
  186. data/lib/ibex/frontend/source_span.rb +89 -0
  187. data/lib/ibex/frontend/token_adapter/declaration_document_state.rb +47 -0
  188. data/lib/ibex/frontend/token_adapter/declaration_lexer_state.rb +83 -0
  189. data/lib/ibex/frontend/token_adapter/declaration_state.rb +244 -22
  190. data/lib/ibex/frontend/token_adapter/delimiter_tracker.rb +8 -2
  191. data/lib/ibex/frontend/token_adapter/rule_state.rb +60 -2
  192. data/lib/ibex/frontend/token_adapter.rb +18 -3
  193. data/lib/ibex/frontend.rb +14 -2
  194. data/lib/ibex/fuzz.rb +219 -0
  195. data/lib/ibex/generation_input.rb +57 -0
  196. data/lib/ibex/generation_manifest.rb +211 -0
  197. data/lib/ibex/generation_transaction.rb +261 -0
  198. data/lib/ibex/generation_transaction_recovery.rb +109 -0
  199. data/lib/ibex/generation_transaction_validation.rb +196 -0
  200. data/lib/ibex/grammar_tests.rb +206 -0
  201. data/lib/ibex/ir/automaton_ir.rb +86 -11
  202. data/lib/ibex/ir/grammar_ir.rb +170 -26
  203. data/lib/ibex/ir/lexer_ir.rb +76 -0
  204. data/lib/ibex/ir/parser_contract.rb +135 -0
  205. data/lib/ibex/ir/serialize.rb +268 -50
  206. data/lib/ibex/ir/validator/automaton.rb +375 -0
  207. data/lib/ibex/ir/validator/base.rb +147 -0
  208. data/lib/ibex/ir/validator/grammar.rb +634 -0
  209. data/lib/ibex/ir/validator/lexer.rb +113 -0
  210. data/lib/ibex/ir/validator.rb +63 -0
  211. data/lib/ibex/ir.rb +71 -5
  212. data/lib/ibex/lalr/build_metrics.rb +71 -0
  213. data/lib/ibex/lalr/builder.rb +514 -52
  214. data/lib/ibex/lalr/conflict.rb +1 -0
  215. data/lib/ibex/lalr/conflict_search.rb +26 -9
  216. data/lib/ibex/lalr/counterexample.rb +38 -18
  217. data/lib/ibex/lalr/direct_lookaheads.rb +289 -0
  218. data/lib/ibex/lalr/goto_follows.rb +229 -0
  219. data/lib/ibex/lalr/ielr/annotator.rb +214 -0
  220. data/lib/ibex/lalr/ielr/bits.rb +28 -0
  221. data/lib/ibex/lalr/ielr/inadequacy.rb +47 -0
  222. data/lib/ibex/lalr/ielr/item_lookaheads.rb +78 -0
  223. data/lib/ibex/lalr/ielr/pipeline.rb +75 -0
  224. data/lib/ibex/lalr/ielr/split_stability.rb +78 -0
  225. data/lib/ibex/lalr/ielr/split_state.rb +20 -0
  226. data/lib/ibex/lalr/ielr/state_splitter.rb +258 -0
  227. data/lib/ibex/lalr/ielr_partition.rb +166 -0
  228. data/lib/ibex/lalr/inadequacy_report.rb +50 -0
  229. data/lib/ibex/lalr/lookahead_propagation.rb +111 -0
  230. data/lib/ibex/lalr/lr0_collection.rb +121 -0
  231. data/lib/ibex/lalr/on_error_reductions.rb +74 -0
  232. data/lib/ibex/lalr/unreachable_states.rb +80 -0
  233. data/lib/ibex/lalr.rb +59 -1
  234. data/lib/ibex/location.rb +129 -0
  235. data/lib/ibex/lsp/document_handlers.rb +68 -0
  236. data/lib/ibex/lsp/document_store.rb +264 -0
  237. data/lib/ibex/lsp/document_store_diagnostics.rb +44 -0
  238. data/lib/ibex/lsp/document_store_validation.rb +61 -0
  239. data/lib/ibex/lsp/initialization_handlers.rb +80 -0
  240. data/lib/ibex/lsp/navigation_handlers.rb +70 -0
  241. data/lib/ibex/lsp/parser_configuration_assistance.rb +149 -0
  242. data/lib/ibex/lsp/position_codec.rb +113 -0
  243. data/lib/ibex/lsp/protocol_error.rb +33 -0
  244. data/lib/ibex/lsp/request_handlers.rb +46 -0
  245. data/lib/ibex/lsp/request_support.rb +94 -0
  246. data/lib/ibex/lsp/server.rb +148 -0
  247. data/lib/ibex/lsp/symbol_index.rb +241 -0
  248. data/lib/ibex/lsp/symbol_index_builder.rb +277 -0
  249. data/lib/ibex/lsp/symbol_index_precedence_references.rb +44 -0
  250. data/lib/ibex/lsp/symbol_index_source_queries.rb +61 -0
  251. data/lib/ibex/lsp/symbol_occurrence.rb +23 -0
  252. data/lib/ibex/lsp/transport.rb +128 -0
  253. data/lib/ibex/lsp/workspace.rb +128 -0
  254. data/lib/ibex/lsp/workspace_analyzer.rb +199 -0
  255. data/lib/ibex/lsp.rb +33 -0
  256. data/lib/ibex/messages/en.yml +28 -0
  257. data/lib/ibex/messages/ja.yml +28 -0
  258. data/lib/ibex/messages.rb +68 -0
  259. data/lib/ibex/metrics.rb +175 -0
  260. data/lib/ibex/normalize/declarations.rb +142 -7
  261. data/lib/ibex/normalize/diagnostics.rb +94 -24
  262. data/lib/ibex/normalize/expander.rb +64 -59
  263. data/lib/ibex/normalize/expression.rb +63 -40
  264. data/lib/ibex/normalize/grammar_builder.rb +26 -0
  265. data/lib/ibex/normalize/inline_expansion.rb +465 -0
  266. data/lib/ibex/normalize/inline_validation.rb +174 -0
  267. data/lib/ibex/normalize/lexer.rb +131 -0
  268. data/lib/ibex/normalize/named_references.rb +60 -0
  269. data/lib/ibex/normalize/nodes.rb +46 -0
  270. data/lib/ibex/normalize/parameter_ebnf_lowering.rb +70 -0
  271. data/lib/ibex/normalize/parameter_lowering.rb +143 -0
  272. data/lib/ibex/normalize/parameter_substitution.rb +125 -0
  273. data/lib/ibex/normalize/parameter_validation.rb +140 -0
  274. data/lib/ibex/normalize/parameters.rb +226 -0
  275. data/lib/ibex/normalize/parser_configuration.rb +70 -0
  276. data/lib/ibex/normalize/recovery_declarations.rb +84 -0
  277. data/lib/ibex/normalize.rb +172 -17
  278. data/lib/ibex/racc_migration/checker.rb +122 -0
  279. data/lib/ibex/racc_migration/harness.rb +177 -0
  280. data/lib/ibex/racc_migration/report.rb +97 -0
  281. data/lib/ibex/racc_migration.rb +12 -0
  282. data/lib/ibex/rake_task.rb +116 -0
  283. data/lib/ibex/samples.rb +216 -0
  284. data/lib/ibex/table_artifact/builder.rb +266 -0
  285. data/lib/ibex/table_artifact/cst_projection.rb +70 -0
  286. data/lib/ibex/table_artifact/document.rb +39 -0
  287. data/lib/ibex/table_artifact/executor.rb +187 -0
  288. data/lib/ibex/table_artifact/serializer.rb +57 -0
  289. data/lib/ibex/table_artifact/validator/metadata.rb +179 -0
  290. data/lib/ibex/table_artifact/validator/support.rb +86 -0
  291. data/lib/ibex/table_artifact/validator/tables.rb +238 -0
  292. data/lib/ibex/table_artifact/validator.rb +253 -0
  293. data/lib/ibex/table_artifact.rb +88 -0
  294. data/lib/ibex/table_simulation/result.rb +55 -0
  295. data/lib/ibex/table_simulation/simulator.rb +253 -0
  296. data/lib/ibex/table_simulation/step.rb +62 -0
  297. data/lib/ibex/table_simulation/text.rb +31 -0
  298. data/lib/ibex/table_simulation.rb +13 -0
  299. data/lib/ibex/tables.rb +22 -69
  300. data/lib/ibex/verifiable_generation_bundle.rb +86 -0
  301. data/lib/ibex/verification_report/builder.rb +159 -0
  302. data/lib/ibex/verification_report/canonical_ir.rb +123 -0
  303. data/lib/ibex/verification_report/logical_path.rb +68 -0
  304. data/lib/ibex/verification_report/validator.rb +329 -0
  305. data/lib/ibex/verification_report.rb +69 -0
  306. data/lib/ibex/verify/action_correspondence.rb +138 -0
  307. data/lib/ibex/verify/language_witness.rb +295 -0
  308. data/lib/ibex/verify/reference_collection.rb +190 -0
  309. data/lib/ibex/verify/result.rb +73 -0
  310. data/lib/ibex/verify/verifier.rb +598 -0
  311. data/lib/ibex/verify.rb +15 -0
  312. data/lib/ibex/version.rb +1 -1
  313. data/lib/ibex/watch/runner.rb +181 -0
  314. data/lib/ibex/watch/source_snapshot.rb +98 -0
  315. data/lib/ibex/watch.rb +11 -0
  316. data/lib/ibex.rb +35 -1
  317. data/schema/automaton-ir-definitions.schema.json +401 -0
  318. data/schema/automaton-ir.schema.json +65 -0
  319. data/schema/benchmark-v1.schema.json +212 -0
  320. data/schema/benchmark-v2.schema.json +61 -0
  321. data/schema/bison-import-v1.schema.json +106 -0
  322. data/schema/conflict-explanation-review-v1.schema.json +196 -0
  323. data/schema/conflict-explanation-study-v1.schema.json +528 -0
  324. data/schema/construction-profile-v1.schema.json +779 -0
  325. data/schema/cst-v1.json +170 -0
  326. data/schema/diff-v1.schema.json +41 -0
  327. data/schema/direct-ielr-decision-v1.schema.json +200 -0
  328. data/schema/equiv-v1.schema.json +64 -0
  329. data/schema/error-ux-review-v1.schema.json +609 -0
  330. data/schema/error-ux-round2-review-v1.schema.json +191 -0
  331. data/schema/error-ux-round2-v1.schema.json +519 -0
  332. data/schema/error-ux-v1.schema.json +258 -0
  333. data/schema/explain-v1.schema.json +495 -0
  334. data/schema/fix-v1.schema.json +64 -0
  335. data/schema/fix-v2.schema.json +66 -0
  336. data/schema/fix-v3.schema.json +101 -0
  337. data/schema/frontend-diagnostics-v1.schema.json +154 -0
  338. data/schema/fuzz-regression-v1.schema.json +79 -0
  339. data/schema/fuzz-v1.schema.json +114 -0
  340. data/schema/generation-manifest-v1.schema.json +115 -0
  341. data/schema/grammar-ir-extensions.schema.json +734 -0
  342. data/schema/grammar-ir-foundation.schema.json +426 -0
  343. data/schema/grammar-ir.schema.json +271 -0
  344. data/schema/ielr-benchmark-v1.schema.json +85 -0
  345. data/schema/lexer-ir-v1.schema.json +215 -0
  346. data/schema/lexer-profile-v1.schema.json +491 -0
  347. data/schema/metrics-v1.schema.json +60 -0
  348. data/schema/migration-check-v1.schema.json +60 -0
  349. data/schema/performance-comparison-v1.schema.json +395 -0
  350. data/schema/public-performance-comparison-v1.schema.json +506 -0
  351. data/schema/public-performance-profile-v1.schema.json +360 -0
  352. data/schema/reduce-v1.schema.json +22 -0
  353. data/schema/reduce-v2.schema.json +63 -0
  354. data/schema/runtime-coverage-v1.schema.json +86 -0
  355. data/schema/runtime-event-v1.schema.json +308 -0
  356. data/schema/table-artifact-v1.schema.json +377 -0
  357. data/schema/table-simulation-v1.schema.json +70 -0
  358. data/schema/verification-report-v1.schema.json +222 -0
  359. data/schema/verify-v1.schema.json +42 -0
  360. data/sig/ibex/analysis/digraph.rbs +19 -0
  361. data/sig/ibex/artifact_set.rbs +37 -0
  362. data/sig/ibex/bison_import/importer.rbs +140 -0
  363. data/sig/ibex/bison_import/tokenizer.rbs +91 -0
  364. data/sig/ibex/bison_import.rbs +95 -0
  365. data/sig/ibex/bounded_subprocess.rbs +76 -0
  366. data/sig/ibex/cli/ambiguity.rbs +28 -0
  367. data/sig/ibex/cli/analysis.rbs +43 -0
  368. data/sig/ibex/cli/bison_import.rbs +32 -0
  369. data/sig/ibex/cli/config.rbs +35 -0
  370. data/sig/ibex/cli/counterexample_options.rbs +2 -0
  371. data/sig/ibex/cli/coverage.rbs +53 -0
  372. data/sig/ibex/cli/debug.rbs +28 -0
  373. data/sig/ibex/cli/diagnostics.rbs +51 -0
  374. data/sig/ibex/cli/documentation.rbs +29 -0
  375. data/sig/ibex/cli/equiv.rbs +49 -0
  376. data/sig/ibex/cli/error_messages.rbs +63 -0
  377. data/sig/ibex/cli/explain.rbs +31 -0
  378. data/sig/ibex/cli/fix.rbs +53 -0
  379. data/sig/ibex/cli/formatting.rbs +107 -0
  380. data/sig/ibex/cli/fuzz.rbs +47 -0
  381. data/sig/ibex/cli/fuzz_regressions.rbs +40 -0
  382. data/sig/ibex/cli/generation_artifacts.rbs +69 -0
  383. data/sig/ibex/cli/generation_error_messages.rbs +19 -0
  384. data/sig/ibex/cli/grammar_tests.rbs +48 -0
  385. data/sig/ibex/cli/ir_tools.rbs +39 -0
  386. data/sig/ibex/cli/lsp.rbs +14 -0
  387. data/sig/ibex/cli/outputs.rbs +26 -3
  388. data/sig/ibex/cli/racc_migration.rbs +30 -0
  389. data/sig/ibex/cli/reduce.rbs +60 -0
  390. data/sig/ibex/cli/reduce_reporting.rbs +27 -0
  391. data/sig/ibex/cli/samples.rbs +38 -0
  392. data/sig/ibex/cli/verify.rbs +28 -0
  393. data/sig/ibex/cli/watch.rbs +43 -0
  394. data/sig/ibex/cli.rbs +182 -9
  395. data/sig/ibex/codegen/action_locations.rbs +45 -0
  396. data/sig/ibex/codegen/action_method_source.rbs +65 -0
  397. data/sig/ibex/codegen/action_source.rbs +50 -0
  398. data/sig/ibex/codegen/ambiguity.rbs +60 -0
  399. data/sig/ibex/codegen/cst_metadata.rbs +59 -0
  400. data/sig/ibex/codegen/documentation.rbs +50 -0
  401. data/sig/ibex/codegen/explain.rbs +105 -0
  402. data/sig/ibex/codegen/generated_action_abi.rbs +105 -0
  403. data/sig/ibex/codegen/html.rbs +18 -2
  404. data/sig/ibex/codegen/mermaid.rbs +16 -0
  405. data/sig/ibex/codegen/railroad.rbs +82 -0
  406. data/sig/ibex/codegen/railroad_documentation.rbs +31 -0
  407. data/sig/ibex/codegen/rbs.rbs +86 -4
  408. data/sig/ibex/codegen/report.rbs +16 -8
  409. data/sig/ibex/codegen/ruby.rbs +105 -28
  410. data/sig/ibex/codegen/ruby_actions.rbs +54 -0
  411. data/sig/ibex/codegen/ruby_ast.rbs +34 -0
  412. data/sig/ibex/codegen/ruby_error_messages.rbs +16 -0
  413. data/sig/ibex/codegen/ruby_lexer.rbs +25 -0
  414. data/sig/ibex/codegen/ruby_syntax.rbs +27 -0
  415. data/sig/ibex/codegen/ruby_table_metadata.rbs +26 -0
  416. data/sig/ibex/codegen/ruby_value_printers.rbs +28 -0
  417. data/sig/ibex/configuration/analysis_grammar.rbs +13 -0
  418. data/sig/ibex/configuration/explanation.rbs +195 -0
  419. data/sig/ibex/configuration/inspector.rbs +53 -0
  420. data/sig/ibex/configuration.rbs +242 -0
  421. data/sig/ibex/coverage/collector.rbs +78 -0
  422. data/sig/ibex/coverage/event_stream.rbs +44 -0
  423. data/sig/ibex/coverage/report.rbs +102 -0
  424. data/sig/ibex/coverage/runtime_event_validator.rbs +70 -0
  425. data/sig/ibex/coverage.rbs +7 -0
  426. data/sig/ibex/delta_reducer.rbs +38 -0
  427. data/sig/ibex/diff.rbs +47 -0
  428. data/sig/ibex/equiv/machine.rbs +54 -0
  429. data/sig/ibex/equiv.rbs +129 -0
  430. data/sig/ibex/error_messages/parser.rbs +58 -0
  431. data/sig/ibex/error_messages/parser_v2.rbs +67 -0
  432. data/sig/ibex/error_messages/renderer.rbs +23 -0
  433. data/sig/ibex/error_messages/sentence_search.rbs +80 -0
  434. data/sig/ibex/error_messages/update.rbs +43 -0
  435. data/sig/ibex/error_messages.rbs +85 -0
  436. data/sig/ibex/fix.rbs +138 -0
  437. data/sig/ibex/frontend/ast.rbs +237 -22
  438. data/sig/ibex/frontend/bootstrap_parser.rbs +13 -0
  439. data/sig/ibex/frontend/diagnostic.rbs +53 -0
  440. data/sig/ibex/frontend/diagnostic_recovery.rbs +98 -0
  441. data/sig/ibex/frontend/dsl.rbs +33 -4
  442. data/sig/ibex/frontend/formatter.rbs +143 -0
  443. data/sig/ibex/frontend/generated_parser.rbs +228 -68
  444. data/sig/ibex/frontend/generated_parser_base.rbs +65 -12
  445. data/sig/ibex/frontend/generated_parser_includes.rbs +23 -0
  446. data/sig/ibex/frontend/generated_parser_metadata.rbs +23 -0
  447. data/sig/ibex/frontend/generated_parser_parameters.rbs +24 -0
  448. data/sig/ibex/frontend/generation.rbs +6 -0
  449. data/sig/ibex/frontend/lexer.rbs +49 -2
  450. data/sig/ibex/frontend/lexer_recovery.rbs +25 -0
  451. data/sig/ibex/frontend/parser/declarations.rbs +57 -0
  452. data/sig/ibex/frontend/parser/parameters.rbs +28 -0
  453. data/sig/ibex/frontend/parser/rules.rbs +3 -0
  454. data/sig/ibex/frontend/parser.rbs +66 -0
  455. data/sig/ibex/frontend/parser_configuration_support.rbs +27 -0
  456. data/sig/ibex/frontend/regenerator.rbs +11 -0
  457. data/sig/ibex/frontend/resolution.rbs +34 -0
  458. data/sig/ibex/frontend/resolver.rbs +91 -0
  459. data/sig/ibex/frontend/rule_documentation.rbs +42 -0
  460. data/sig/ibex/frontend/source_cursor.rbs +38 -5
  461. data/sig/ibex/frontend/source_document.rbs +119 -0
  462. data/sig/ibex/frontend/source_loader.rbs +66 -0
  463. data/sig/ibex/frontend/source_span.rbs +56 -0
  464. data/sig/ibex/frontend/token_adapter/declaration_document_state.rbs +21 -0
  465. data/sig/ibex/frontend/token_adapter/declaration_lexer_state.rbs +27 -0
  466. data/sig/ibex/frontend/token_adapter/declaration_state.rbs +83 -3
  467. data/sig/ibex/frontend/token_adapter/rule_state.rbs +20 -0
  468. data/sig/ibex/frontend/token_adapter.rbs +11 -2
  469. data/sig/ibex/frontend.rbs +1 -1
  470. data/sig/ibex/fuzz.rbs +71 -0
  471. data/sig/ibex/generation_input.rbs +37 -0
  472. data/sig/ibex/generation_manifest.rbs +70 -0
  473. data/sig/ibex/generation_transaction.rbs +82 -0
  474. data/sig/ibex/generation_transaction_recovery.rbs +36 -0
  475. data/sig/ibex/generation_transaction_validation.rbs +65 -0
  476. data/sig/ibex/grammar_tests.rbs +93 -0
  477. data/sig/ibex/ir/automaton_ir.rbs +35 -10
  478. data/sig/ibex/ir/grammar_ir.rbs +96 -22
  479. data/sig/ibex/ir/lexer_ir.rbs +57 -0
  480. data/sig/ibex/ir/parser_contract.rbs +69 -0
  481. data/sig/ibex/ir/serialize.rbs +75 -23
  482. data/sig/ibex/ir/validator/automaton.rbs +112 -0
  483. data/sig/ibex/ir/validator/base.rbs +69 -0
  484. data/sig/ibex/ir/validator/grammar.rbs +195 -0
  485. data/sig/ibex/ir/validator/lexer.rbs +37 -0
  486. data/sig/ibex/ir/validator.rbs +16 -0
  487. data/sig/ibex/ir.rbs +45 -5
  488. data/sig/ibex/lalr/build_metrics.rbs +60 -0
  489. data/sig/ibex/lalr/builder.rbs +150 -19
  490. data/sig/ibex/lalr/conflict_search.rbs +12 -5
  491. data/sig/ibex/lalr/counterexample.rbs +20 -14
  492. data/sig/ibex/lalr/direct_lookaheads.rbs +93 -0
  493. data/sig/ibex/lalr/goto_follows.rbs +89 -0
  494. data/sig/ibex/lalr/ielr/annotator.rbs +67 -0
  495. data/sig/ibex/lalr/ielr/bits.rbs +14 -0
  496. data/sig/ibex/lalr/ielr/inadequacy.rbs +24 -0
  497. data/sig/ibex/lalr/ielr/item_lookaheads.rbs +35 -0
  498. data/sig/ibex/lalr/ielr/pipeline.rbs +17 -0
  499. data/sig/ibex/lalr/ielr/split_stability.rbs +27 -0
  500. data/sig/ibex/lalr/ielr/split_state.rbs +14 -0
  501. data/sig/ibex/lalr/ielr/state_splitter.rbs +76 -0
  502. data/sig/ibex/lalr/ielr_partition.rbs +71 -0
  503. data/sig/ibex/lalr/inadequacy_report.rbs +21 -0
  504. data/sig/ibex/lalr/lookahead_propagation.rbs +38 -0
  505. data/sig/ibex/lalr/lr0_collection.rbs +50 -0
  506. data/sig/ibex/lalr/on_error_reductions.rbs +22 -0
  507. data/sig/ibex/lalr/unreachable_states.rbs +25 -0
  508. data/sig/ibex/lalr.rbs +17 -1
  509. data/sig/ibex/location.rbs +67 -0
  510. data/sig/ibex/lsp/document_handlers.rbs +24 -0
  511. data/sig/ibex/lsp/document_store.rbs +94 -0
  512. data/sig/ibex/lsp/document_store_diagnostics.rbs +20 -0
  513. data/sig/ibex/lsp/document_store_validation.rbs +26 -0
  514. data/sig/ibex/lsp/initialization_handlers.rbs +30 -0
  515. data/sig/ibex/lsp/navigation_handlers.rbs +33 -0
  516. data/sig/ibex/lsp/parser_configuration_assistance.rbs +49 -0
  517. data/sig/ibex/lsp/position_codec.rbs +44 -0
  518. data/sig/ibex/lsp/protocol_error.rbs +32 -0
  519. data/sig/ibex/lsp/request_handlers.rbs +26 -0
  520. data/sig/ibex/lsp/request_support.rbs +40 -0
  521. data/sig/ibex/lsp/server.rbs +55 -0
  522. data/sig/ibex/lsp/symbol_index.rbs +77 -0
  523. data/sig/ibex/lsp/symbol_index_builder.rbs +88 -0
  524. data/sig/ibex/lsp/symbol_index_precedence_references.rbs +18 -0
  525. data/sig/ibex/lsp/symbol_index_source_queries.rbs +26 -0
  526. data/sig/ibex/lsp/symbol_occurrence.rbs +31 -0
  527. data/sig/ibex/lsp/transport.rbs +47 -0
  528. data/sig/ibex/lsp/workspace.rbs +42 -0
  529. data/sig/ibex/lsp/workspace_analyzer.rbs +69 -0
  530. data/sig/ibex/lsp.rbs +7 -0
  531. data/sig/ibex/messages.rbs +26 -0
  532. data/sig/ibex/metrics.rbs +50 -0
  533. data/sig/ibex/normalize/declarations.rbs +31 -0
  534. data/sig/ibex/normalize/diagnostics.rbs +13 -4
  535. data/sig/ibex/normalize/expander.rbs +22 -16
  536. data/sig/ibex/normalize/expression.rbs +11 -9
  537. data/sig/ibex/normalize/grammar_builder.rbs +11 -0
  538. data/sig/ibex/normalize/inline_expansion.rbs +129 -0
  539. data/sig/ibex/normalize/inline_validation.rbs +40 -0
  540. data/sig/ibex/normalize/lexer.rbs +37 -0
  541. data/sig/ibex/normalize/named_references.rbs +20 -0
  542. data/sig/ibex/normalize/nodes.rbs +14 -0
  543. data/sig/ibex/normalize/parameter_ebnf_lowering.rbs +33 -0
  544. data/sig/ibex/normalize/parameter_lowering.rbs +35 -0
  545. data/sig/ibex/normalize/parameter_substitution.rbs +42 -0
  546. data/sig/ibex/normalize/parameter_validation.rbs +44 -0
  547. data/sig/ibex/normalize/parameters.rbs +51 -0
  548. data/sig/ibex/normalize/parser_configuration.rbs +23 -0
  549. data/sig/ibex/normalize/recovery_declarations.rbs +24 -0
  550. data/sig/ibex/normalize.rbs +129 -18
  551. data/sig/ibex/racc_migration/checker.rbs +36 -0
  552. data/sig/ibex/racc_migration/harness.rbs +16 -0
  553. data/sig/ibex/racc_migration/report.rbs +55 -0
  554. data/sig/ibex/racc_migration.rbs +8 -0
  555. data/sig/ibex/rake_task.rbs +51 -0
  556. data/sig/ibex/samples.rbs +60 -0
  557. data/sig/ibex/table_artifact/builder.rbs +93 -0
  558. data/sig/ibex/table_artifact/cst_projection.rbs +20 -0
  559. data/sig/ibex/table_artifact/document.rbs +27 -0
  560. data/sig/ibex/table_artifact/executor.rbs +66 -0
  561. data/sig/ibex/table_artifact/serializer.rbs +25 -0
  562. data/sig/ibex/table_artifact/validator/metadata.rbs +52 -0
  563. data/sig/ibex/table_artifact/validator/support.rbs +46 -0
  564. data/sig/ibex/table_artifact/validator/tables.rbs +63 -0
  565. data/sig/ibex/table_artifact/validator.rbs +66 -0
  566. data/sig/ibex/table_artifact.rbs +32 -0
  567. data/sig/ibex/table_simulation/result.rbs +36 -0
  568. data/sig/ibex/table_simulation/simulator.rbs +98 -0
  569. data/sig/ibex/table_simulation/step.rbs +42 -0
  570. data/sig/ibex/table_simulation/text.rbs +14 -0
  571. data/sig/ibex/table_simulation.rbs +7 -0
  572. data/sig/ibex/tables.rbs +10 -35
  573. data/sig/ibex/verifiable_generation_bundle.rbs +24 -0
  574. data/sig/ibex/verification_report/builder.rbs +53 -0
  575. data/sig/ibex/verification_report/canonical_ir.rbs +41 -0
  576. data/sig/ibex/verification_report/logical_path.rbs +34 -0
  577. data/sig/ibex/verification_report/validator.rbs +114 -0
  578. data/sig/ibex/verification_report.rbs +44 -0
  579. data/sig/ibex/verify/action_correspondence.rbs +50 -0
  580. data/sig/ibex/verify/language_witness.rbs +112 -0
  581. data/sig/ibex/verify/reference_collection.rbs +63 -0
  582. data/sig/ibex/verify/result.rbs +52 -0
  583. data/sig/ibex/verify/verifier.rbs +170 -0
  584. data/sig/ibex/verify.rbs +6 -0
  585. data/sig/ibex/watch/runner.rbs +58 -0
  586. data/sig/ibex/watch/source_snapshot.rbs +46 -0
  587. data/sig/ibex/watch.rbs +7 -0
  588. data/sig/ibex.rbs +2 -0
  589. metadata +524 -19
  590. data/.rubocop.yml +0 -43
  591. data/CHANGELOG.md +0 -30
  592. data/Rakefile +0 -25
  593. data/Steepfile +0 -10
  594. data/docs/compat-notes.md +0 -37
  595. data/docs/lexer-coverage.md +0 -14
  596. data/docs/phase10-extensions.md +0 -27
  597. data/gemfiles/Gemfile +0 -7
  598. data/gemfiles/Gemfile.lock +0 -98
  599. data/lib/ibex/frontend/grammar.y +0 -156
  600. data/lib/ibex/runtime/parser.rb +0 -360
  601. data/lib/ibex/runtime.rb +0 -8
  602. data/sig/ibex/runtime/parser.rbs +0 -167
  603. data/sig/ibex/runtime.rbs +0 -6
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ # steep:ignore:start
5
+
6
+ require "set"
7
+
8
+ module Ibex
9
+ module LALR
10
+ # Constructs only the LR(0) core collection. Keeping this separate from
11
+ # lookahead propagation makes the direct IELR phases reusable and gives
12
+ # them a stable, canonical-free input representation.
13
+ class LR0Collection
14
+ AUGMENTED_PRODUCTION = -1 #: Integer
15
+
16
+ # @rbs @grammar: IR::Grammar
17
+ # @rbs @productions_by_lhs: Hash[Integer, Array[IR::Production]]
18
+ # @rbs @starts: Array[String]
19
+ # @rbs @augmented_rhs: Hash[Integer, Array[Integer]]
20
+ # @rbs @production_rhs: Array[Array[Integer]]
21
+ # @rbs @item_key_stride: Integer
22
+
23
+ # @rbs (IR::Grammar grammar, ?starts: Array[String]?) -> void
24
+ def initialize(grammar, starts: nil)
25
+ @grammar = grammar
26
+ @starts = (starts || grammar.starts).dup
27
+ raise ArgumentError, "starts must be a nonempty subset of grammar starts" if
28
+ @starts.empty? || (@starts - grammar.starts).any?
29
+
30
+ @productions_by_lhs = grammar.productions.group_by(&:lhs)
31
+ @production_rhs = grammar.productions.map(&:rhs).freeze
32
+ @augmented_production_ids = @starts.map { |name| AUGMENTED_PRODUCTION - grammar.starts.index(name) }
33
+ @augmented_rhs = @starts.each_with_index.to_h do |name, index|
34
+ symbol = grammar.symbol(name) || raise(Ibex::Error, "missing start symbol #{name}")
35
+ [@augmented_production_ids.fetch(index), [symbol.id].freeze]
36
+ end.freeze
37
+ @item_key_stride = [*@production_rhs, *@augmented_rhs.values].map(&:length).max.to_i + 1
38
+ end
39
+
40
+ # @rbs () -> [Array[core_set], transitions]
41
+ def build
42
+ states = @starts.map { |name| closure(Set[[augmented_production(@starts.index(name)), 0]]) }
43
+ transitions = [] #: transitions
44
+ indexes = {}
45
+ states.each_with_index { |items, index| indexes[item_key(items)] = index }
46
+ cursor = 0
47
+ while cursor < states.length
48
+ transitions[cursor] = {}
49
+ shifted_kernels(states.fetch(cursor)).keys.sort.each do |symbol_id|
50
+ target = closure(shifted_kernels(states.fetch(cursor)).fetch(symbol_id))
51
+ target_id = indexes[item_key(target)] ||= begin
52
+ states << target
53
+ states.length - 1
54
+ end
55
+ transitions.fetch(cursor)[symbol_id] = target_id
56
+ end
57
+ cursor += 1
58
+ end
59
+ [states, transitions]
60
+ end
61
+
62
+ # @rbs (Integer index) -> Integer
63
+ def augmented_production(index)
64
+ @augmented_production_ids.fetch(index)
65
+ end
66
+
67
+ # @rbs (Integer production_id) -> Array[Integer]
68
+ def rhs_for(production_id)
69
+ return @augmented_rhs.fetch(production_id) if production_id.negative?
70
+
71
+ @production_rhs.fetch(production_id)
72
+ end
73
+
74
+ # @rbs (Integer production_id) -> Integer
75
+ def lhs_for(production_id)
76
+ return rhs_for(production_id).fetch(0) if production_id.negative?
77
+
78
+ @grammar.productions.fetch(production_id).lhs
79
+ end
80
+
81
+ # @rbs (core_set items) -> Hash[Integer, core_set]
82
+ def shifted_kernels(items)
83
+ kernels = Hash.new { |hash, key| hash[key] = Set.new } #: Hash[Integer, core_set]
84
+ items.each do |production_id, dot|
85
+ symbol_id = rhs_for(production_id)[dot]
86
+ kernels[symbol_id] << [production_id, dot + 1].freeze if symbol_id
87
+ end
88
+ kernels
89
+ end
90
+
91
+ private
92
+
93
+ # @rbs (core_set seed) -> core_set
94
+ def closure(seed)
95
+ items = seed.dup
96
+ queue = seed.to_a
97
+ cursor = 0
98
+ while cursor < queue.length
99
+ production_id, dot = queue.fetch(cursor)
100
+ cursor += 1
101
+ symbol = @grammar.symbol_by_id(rhs_for(production_id)[dot])
102
+ next unless symbol&.nonterminal?
103
+
104
+ @productions_by_lhs.fetch(symbol.id, []).each do |production|
105
+ item = [production.id, 0].freeze
106
+ queue << item if items.add?(item)
107
+ end
108
+ end
109
+ items
110
+ end
111
+
112
+ # @rbs (core_set items) -> Array[Integer]
113
+ def item_key(items)
114
+ items.map do |production_id, dot|
115
+ ((production_id + @grammar.starts.length) * @item_key_stride) + dot
116
+ end.sort
117
+ end
118
+ end
119
+ end
120
+ end
121
+ # steep:ignore:end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibex
4
+ module LALR
5
+ # Delays syntax-error detection by filling only otherwise erroneous table
6
+ # cells with one uniquely highest-priority declared reduction.
7
+ module OnErrorReductions
8
+ # @rbs (IR::Grammar grammar, Array[IR::AutomatonState] states) -> Array[IR::AutomatonState]
9
+ def apply(grammar, states)
10
+ priorities = reduction_priorities(grammar)
11
+ return states if priorities.empty?
12
+
13
+ terminal_ids = grammar.terminals.reject { |terminal| terminal.name == "error" }.map(&:id)
14
+ states.map { |state| apply_state(grammar, state, priorities, terminal_ids) }
15
+ end
16
+ module_function :apply
17
+
18
+ # @rbs (IR::Grammar grammar) -> Hash[Integer, Integer]
19
+ def reduction_priorities(grammar)
20
+ priorities = {} #: Hash[Integer, Integer]
21
+ grammar.recovery[:on_error_reduce].each_with_index do |names, priority|
22
+ names.each do |name|
23
+ symbol = grammar.symbol(name) || raise(Ibex::Error, "missing on-error reduction symbol #{name}")
24
+ priorities[symbol.id] = priority
25
+ end
26
+ end
27
+ priorities
28
+ end
29
+
30
+ # @rbs (IR::Grammar grammar, IR::AutomatonState state, Hash[Integer, Integer] priorities,
31
+ # Array[Integer] terminal_ids) -> IR::AutomatonState
32
+ def apply_state(grammar, state, priorities, terminal_ids)
33
+ production_id = selected_production(grammar, state, priorities)
34
+ return state unless production_id
35
+
36
+ reduction = { type: :reduce, production: production_id } #: IR::reduce_action
37
+ actions = state.actions.dup
38
+ terminal_ids.each do |token_id|
39
+ action = actions[token_id]
40
+ actions[token_id] = reduction if action.nil? || action[:type] == :error
41
+ end
42
+ IR::AutomatonState.new(
43
+ id: state.id, items: state.items, transitions: state.transitions,
44
+ actions: actions, gotos: state.gotos, default_action: state.default_action,
45
+ conflicts: state.conflicts
46
+ )
47
+ end
48
+
49
+ # @rbs (IR::Grammar grammar, IR::AutomatonState state, Hash[Integer, Integer] priorities) -> Integer?
50
+ def selected_production(grammar, state, priorities)
51
+ candidates = state.items.filter_map do |item|
52
+ next if item.production.negative?
53
+
54
+ production = grammar.productions.fetch(item.production)
55
+ next unless item.dot == production.rhs.length
56
+
57
+ priority = priorities[production.lhs]
58
+ [priority, production.id] if priority
59
+ end.uniq
60
+ highest = candidates.filter_map(&:first).max
61
+ return unless highest
62
+
63
+ productions = candidates.filter_map { |priority, production| production if priority == highest }.uniq
64
+ productions.one? ? productions.fetch(0) : nil
65
+ end
66
+
67
+ module_function :reduction_priorities, :apply_state, :selected_production
68
+
69
+ class << self
70
+ private :reduction_priorities, :apply_state, :selected_production
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ # steep:ignore:start
5
+
6
+ module Ibex
7
+ module LALR
8
+ # Optional post-resolution compaction. It is intentionally off by
9
+ # default because state numbers are part of diagnostics and golden output.
10
+ module UnreachableStates
11
+ module_function
12
+
13
+ # @rbs (Array[IR::AutomatonState] states, Array[Integer] start_states) ->
14
+ # [Array[IR::AutomatonState], Hash[Integer, Integer]]
15
+ def remove(states, start_states)
16
+ reachable = reachable_states(states, start_states)
17
+ mapping = reachable.each_with_index.to_h { |old_id, new_id| [old_id, new_id] }
18
+ return [states, mapping] if reachable.length == states.length
19
+
20
+ compacted = reachable.map do |old_id|
21
+ state = states.fetch(old_id)
22
+ transitions = remap_edges(state.transitions, mapping)
23
+ gotos = remap_edges(state.gotos, mapping)
24
+ actions = state.actions.transform_values { |action| remap_action(action, mapping) }
25
+ default_action = remap_action(state.default_action, mapping)
26
+ conflicts = state.conflicts.map { |conflict| remap_conflict(conflict, mapping) }
27
+ IR::AutomatonState.new(
28
+ id: mapping.fetch(old_id), items: state.items, transitions: transitions,
29
+ actions: actions, gotos: gotos, default_action: default_action, conflicts: conflicts
30
+ )
31
+ end
32
+ [compacted, mapping]
33
+ end
34
+
35
+ # @rbs (Array[IR::AutomatonState], Array[Integer]) -> Array[Integer]
36
+ def reachable_states(states, start_states)
37
+ visited = {}
38
+ queue = start_states.dup
39
+ until queue.empty?
40
+ state_id = queue.shift
41
+ next if visited[state_id]
42
+
43
+ visited[state_id] = true
44
+ state = states.fetch(state_id)
45
+ state.gotos.each_value { |target| queue << target }
46
+ state.actions.each_value do |action|
47
+ queue << action[:state] if action[:type] == :shift
48
+ end
49
+ end
50
+ visited.keys.sort
51
+ end
52
+
53
+ # @rbs (Hash[Integer, Integer], Hash[Integer, Integer]) -> Hash[Integer, Integer]
54
+ def remap_edges(edges, mapping)
55
+ edges.each_with_object({}) do |(symbol_id, target), result|
56
+ result[symbol_id] = mapping[target] if mapping.key?(target)
57
+ end
58
+ end
59
+
60
+ # @rbs (IR::parser_action?, Hash[Integer, Integer]) -> IR::parser_action?
61
+ def remap_action(action, mapping)
62
+ return nil unless action
63
+ return action unless action[:type] == :shift
64
+ return { type: :shift, state: mapping.fetch(action[:state]) } if mapping.key?(action[:state])
65
+
66
+ { type: :error }
67
+ end
68
+
69
+ # @rbs (IR::conflict, Hash[Integer, Integer]) -> IR::conflict
70
+ def remap_conflict(conflict, mapping)
71
+ result = conflict.dup
72
+ if result[:type] == :shift_reduce && mapping.key?(result[:shift_to])
73
+ result[:shift_to] = mapping.fetch(result[:shift_to])
74
+ end
75
+ result
76
+ end
77
+ end
78
+ end
79
+ end
80
+ # steep:ignore:end
data/lib/ibex/lalr.rb CHANGED
@@ -1,7 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "lalr/conflict"
4
+ require_relative "lalr/on_error_reductions"
4
5
  require_relative "lalr/default_reductions"
6
+ require_relative "lalr/build_metrics"
7
+ require_relative "lalr/lr0_collection"
8
+ require_relative "lalr/goto_follows"
9
+ require_relative "lalr/lookahead_propagation"
10
+ require_relative "lalr/unreachable_states"
11
+ require_relative "lalr/ielr/bits"
12
+ require_relative "lalr/ielr/inadequacy"
13
+ require_relative "lalr/ielr/item_lookaheads"
14
+ require_relative "lalr/ielr/split_stability"
15
+ require_relative "lalr/ielr/annotator"
16
+ require_relative "lalr/ielr/split_state"
17
+ require_relative "lalr/ielr/state_splitter"
18
+ require_relative "lalr/ielr/pipeline"
19
+ require_relative "lalr/direct_lookaheads"
20
+ require_relative "lalr/ielr_partition"
5
21
  require_relative "lalr/builder"
6
22
  require_relative "lalr/conflict_search_limits"
7
23
  require_relative "lalr/conflict_search"
@@ -12,10 +28,33 @@ module Ibex
12
28
  # @rbs!
13
29
  # type lr_item = [Integer, Integer, Integer]
14
30
  # type item_core = [Integer, Integer]
31
+ # type core_set = Set[item_core]
15
32
  # type item_set = Set[lr_item]
16
33
  # type packed_items = Hash[item_core, Set[Integer]]
17
34
  # type transitions = Array[Hash[Integer, Integer]]
18
- # type derivation_node = Hash[Symbol, untyped]
35
+ # type build_collection = {
36
+ # construction_states: Integer,
37
+ # canonical_states: Integer?,
38
+ # strategy: Symbol,
39
+ # lr0_states: Integer?,
40
+ # lr0_items: Integer?,
41
+ # canonical_items: Integer?,
42
+ # propagation_edges: Integer?,
43
+ # ielr_initial_partitions: Integer?,
44
+ # ielr_final_partitions: Integer?,
45
+ # ielr_annotations: Integer?,
46
+ # ielr_annotated_states: Integer?,
47
+ # ielr_inadequacies: Integer?,
48
+ # ielr_split_stable_discarded: Integer?,
49
+ # ielr_lalr_states: Integer?,
50
+ # ielr_split_states: Integer?,
51
+ # ielr_unreachable_removed: Integer?,
52
+ # ielr_remergeable_candidates: Integer?
53
+ # }
54
+ # type conflict_fingerprint = [Symbol, String, Array[Integer]]
55
+ # type lookahead_node = [Integer, Integer, Integer]
56
+ # type state_partition = Array[Integer]
57
+ # type derivation_node = Hash[Symbol, Object?]
19
58
  # type search_status = :conflict | :shifted | :accepted
20
59
  # type search_entry = [search_status, ConflictSearch::Configuration]
21
60
  # type search_result = {
@@ -23,5 +62,24 @@ module Ibex
23
62
  # lookahead_index: Integer,
24
63
  # interpretations: Array[IR::interpretation]
25
64
  # }
65
+ # type search_bounds = { max_tokens: Integer, max_configurations: Integer }
66
+ # type search_outcome = {
67
+ # status: :found | :not_found | :exhausted,
68
+ # result: search_result?,
69
+ # explored: Integer,
70
+ # exhausted: bool,
71
+ # bounds: search_bounds
72
+ # }
73
+ # type search_counterexample = {
74
+ # state: Integer,
75
+ # type: Symbol,
76
+ # symbol_path: Array[String],
77
+ # sentence: Array[String],
78
+ # lookahead_index: Integer,
79
+ # unifying: bool,
80
+ # inconclusive: bool,
81
+ # search: search_outcome,
82
+ # interpretations: Array[IR::interpretation]
83
+ # }
26
84
  end
27
85
  end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ module Ibex
5
+ # Immutable source range suitable for lexer tokens and parser diagnostics.
6
+ #
7
+ # Coordinates are one-based. Byte offsets are optional, zero-based, and
8
+ # half-open. Keeping both forms lets Unicode-aware lexers report human
9
+ # columns without losing an exact source slice.
10
+ class Location
11
+ attr_reader :file #: String?
12
+ attr_reader :line #: Integer
13
+ attr_reader :column #: Integer
14
+ attr_reader :end_line #: Integer
15
+ attr_reader :end_column #: Integer
16
+ attr_reader :start_byte #: Integer?
17
+ attr_reader :end_byte #: Integer?
18
+ attr_reader :source_line #: String?
19
+
20
+ # @rbs (?file: String?, line: Integer, column: Integer, ?end_line: Integer?,
21
+ # ?end_column: Integer?, ?start_byte: Integer?, ?end_byte: Integer?, ?source_line: String?) -> void
22
+ def initialize(line:, column:, file: nil, end_line: nil, end_column: nil,
23
+ start_byte: nil, end_byte: nil, source_line: nil)
24
+ @file = file&.dup&.freeze
25
+ @line = positive_coordinate(:line, line)
26
+ @column = positive_coordinate(:column, column)
27
+ @end_line = positive_coordinate(:end_line, end_line || line)
28
+ @end_column = positive_coordinate(:end_column, end_column || column)
29
+ @start_byte = optional_offset(:start_byte, start_byte)
30
+ @end_byte = optional_offset(:end_byte, end_byte)
31
+ @source_line = source_line&.dup&.freeze
32
+ validate_order!
33
+ freeze
34
+ end
35
+
36
+ # Return the smallest range covering both locations.
37
+ # @rbs (Location other) -> Location
38
+ def join(other)
39
+ raise ArgumentError, "location files differ" unless file == other.file
40
+
41
+ first = before_or_equal?(self, other) ? self : other
42
+ ending = before_or_equal_end?(self, other) ? other : self
43
+ self.class.new(
44
+ file: file, line: first.line, column: first.column,
45
+ end_line: ending.end_line, end_column: ending.end_column,
46
+ start_byte: joined_start_byte(other), end_byte: joined_end_byte(other),
47
+ source_line: first.source_line
48
+ )
49
+ end
50
+
51
+ # Fold a nonempty collection into one covering range.
52
+ # @rbs (Enumerable[Location] locations) -> Location
53
+ def self.join(locations)
54
+ values = locations.to_a
55
+ first = values.shift || raise(ArgumentError, "locations must not be empty")
56
+ values.reduce(first) { |combined, location| combined.join(location) }
57
+ end
58
+
59
+ # @rbs () -> bool
60
+ def empty?
61
+ @line == @end_line && @column == @end_column &&
62
+ (@start_byte.nil? || @end_byte.nil? || @start_byte == @end_byte)
63
+ end
64
+
65
+ # @rbs () -> Hash[Symbol, String | Integer]
66
+ def to_h
67
+ {
68
+ file: @file, line: @line, column: @column,
69
+ end_line: @end_line, end_column: @end_column,
70
+ start_byte: @start_byte, end_byte: @end_byte
71
+ }.compact
72
+ end
73
+
74
+ private
75
+
76
+ # @rbs (Symbol name, Object? value) -> Integer
77
+ def positive_coordinate(name, value)
78
+ return value if value.is_a?(Integer) && value.positive?
79
+
80
+ raise ArgumentError, "#{name} must be a positive Integer"
81
+ end
82
+
83
+ # @rbs (Symbol name, Object? value) -> Integer?
84
+ def optional_offset(name, value)
85
+ return if value.nil?
86
+ return value if value.is_a?(Integer) && value >= 0
87
+
88
+ raise ArgumentError, "#{name} must be a nonnegative Integer or nil"
89
+ end
90
+
91
+ # @rbs () -> void
92
+ def validate_order!
93
+ if @end_line < @line || (@end_line == @line && @end_column < @column)
94
+ raise ArgumentError, "end position precedes start position"
95
+ end
96
+
97
+ start_byte = @start_byte
98
+ end_byte = @end_byte
99
+ return unless start_byte && end_byte && end_byte < start_byte
100
+
101
+ raise ArgumentError, "end_byte precedes start_byte"
102
+ end
103
+
104
+ # @rbs (Location left, Location right) -> bool
105
+ def before_or_equal?(left, right)
106
+ left.line < right.line || (left.line == right.line && left.column <= right.column)
107
+ end
108
+
109
+ # @rbs (Location left, Location right) -> bool
110
+ def before_or_equal_end?(left, right)
111
+ left.end_line < right.end_line ||
112
+ (left.end_line == right.end_line && left.end_column <= right.end_column)
113
+ end
114
+
115
+ # @rbs (Location other) -> Integer?
116
+ def joined_start_byte(other)
117
+ return unless @start_byte && other.start_byte
118
+
119
+ [@start_byte, other.start_byte].min
120
+ end
121
+
122
+ # @rbs (Location other) -> Integer?
123
+ def joined_end_byte(other)
124
+ return unless @end_byte && other.end_byte
125
+
126
+ [@end_byte, other.end_byte].max
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibex
4
+ module LSP
5
+ # Applies full-text LSP document notifications to the overlay-backed store.
6
+ module DocumentHandlers
7
+ include RequestSupport
8
+
9
+ private
10
+
11
+ # @rbs (lsp_value? raw_params) -> nil
12
+ def did_open(raw_params)
13
+ require_running!
14
+ params = params_hash(raw_params)
15
+ document = hash_member(params, "textDocument")
16
+ publications = store.open(
17
+ string_member(document, "uri"), integer_member(document, "version"), string_member(document, "text")
18
+ )
19
+ publish(publications)
20
+ nil
21
+ end
22
+
23
+ # @rbs (lsp_value? raw_params) -> nil
24
+ def did_change(raw_params)
25
+ require_running!
26
+ params = params_hash(raw_params)
27
+ document = hash_member(params, "textDocument")
28
+ changes = params["contentChanges"]
29
+ first_change = changes.is_a?(Array) ? changes.first : nil
30
+ unless changes.is_a?(Array) && changes.one? && first_change.is_a?(Hash) &&
31
+ !first_change.key?("range") && !first_change.key?("rangeLength")
32
+ raise ProtocolError.new("full sync requires exactly one range-free content change", code: -32_602)
33
+ end
34
+
35
+ change = changes.fetch(0) #: lsp_object
36
+ source = string_member(change, "text")
37
+ publications = store.change(
38
+ string_member(document, "uri"), integer_member(document, "version"), source
39
+ )
40
+ publish(publications)
41
+ nil
42
+ end
43
+
44
+ # @rbs (lsp_value? raw_params) -> nil
45
+ def did_save(raw_params)
46
+ require_running!
47
+ params = params_hash(raw_params)
48
+ document = hash_member(params, "textDocument")
49
+ source = params["text"]
50
+ unless source.nil? || source.is_a?(String)
51
+ raise ProtocolError.new("saved document text must be a string", code: -32_602)
52
+ end
53
+
54
+ publish(store.save(string_member(document, "uri"), source: source))
55
+ nil
56
+ end
57
+
58
+ # @rbs (lsp_value? raw_params) -> nil
59
+ def did_close(raw_params)
60
+ require_running!
61
+ params = params_hash(raw_params)
62
+ document = hash_member(params, "textDocument")
63
+ publish(store.close(string_member(document, "uri")))
64
+ nil
65
+ end
66
+ end
67
+ end
68
+ end