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,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibex
4
+ module TableArtifact
5
+ # An immutable, validated table artifact document.
6
+ class Document
7
+ # @rbs!
8
+ # type json_value = String | Integer | Float | bool | nil | Array[json_value] | Hash[String, json_value]
9
+
10
+ attr_reader :data #: Hash[String, json_value]
11
+
12
+ # @rbs (Hash[String, json_value] data) -> void
13
+ def initialize(data)
14
+ Validator.validate!(data)
15
+ @data = Serializer.deep_freeze(data)
16
+ end
17
+
18
+ # @rbs () -> String
19
+ def dump
20
+ Serializer.dump(@data)
21
+ end
22
+
23
+ # @rbs () -> Hash[String, json_value]
24
+ def payload
25
+ @data.fetch("payload") #: Hash[String, json_value]
26
+ end
27
+
28
+ # @rbs () -> Hash[String, String]
29
+ def identity
30
+ @data.fetch("identity") #: Hash[String, String]
31
+ end
32
+
33
+ # @rbs () -> Hash[String, json_value]
34
+ def cost
35
+ @data.fetch("cost") #: Hash[String, json_value]
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,187 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibex
4
+ module TableArtifact
5
+ # Recognition-only driver over internal token ids; it never loads wrapper code.
6
+ class Executor
7
+ class Result
8
+ attr_reader :status #: Symbol
9
+ attr_reader :steps #: Integer
10
+ attr_reader :consumed_tokens #: Integer
11
+ attr_reader :reason #: String?
12
+
13
+ # @rbs (status: Symbol, steps: Integer, consumed_tokens: Integer, reason: String?) -> void
14
+ def initialize(status:, steps:, consumed_tokens:, reason:)
15
+ @status = status
16
+ @steps = steps
17
+ @consumed_tokens = consumed_tokens
18
+ @reason = reason
19
+ freeze
20
+ end
21
+
22
+ # @rbs () -> bool
23
+ def accepted? = status == :accepted
24
+ # @rbs () -> bool
25
+ def rejected? = status == :rejected
26
+ # @rbs () -> bool
27
+ def exhausted? = status == :exhausted
28
+ end
29
+
30
+ # @rbs (Document | Hash[String, ValidationSupport::json_value] document) -> void
31
+ def initialize(document)
32
+ @payload = document.is_a?(Document) ? document.payload : Document.new(document).payload
33
+ @tables = @payload.fetch("tables") #: Hash[String, ValidationSupport::json_value]
34
+ @productions = @payload.fetch("productions") #: Array[Hash[String, ValidationSupport::json_value]]
35
+ tokens = @payload.fetch("tokens") #: Array[Hash[String, ValidationSupport::json_value]]
36
+ @terminal_ids = tokens.map do |token|
37
+ token.fetch("id") #: Integer
38
+ end
39
+ end
40
+
41
+ # @rbs (Array[Integer] token_ids, ?entry: String | Symbol?, ?max_steps: Integer) -> Result
42
+ def recognize(token_ids, entry: nil, max_steps: 1_000_000)
43
+ raise ArgumentError, "max_steps must be positive" unless max_steps.is_a?(Integer) && max_steps.positive?
44
+
45
+ input = validate_input(token_ids)
46
+ input << 0 unless input.last&.zero?
47
+ stack = [entry_state(entry)]
48
+ execute(input, stack, max_steps)
49
+ end
50
+
51
+ private
52
+
53
+ # @rbs (Array[Integer] input, Array[Integer] stack, Integer max_steps) -> Result
54
+ def execute(input, stack, max_steps)
55
+ cursor = 0
56
+ max_steps.times do |step|
57
+ return result(:rejected, step + 1, cursor, "parser shifted past end of input") if cursor >= input.length
58
+
59
+ code = action(stack.last, input.fetch(cursor))
60
+ immediate = immediate_result(code, input.fetch(cursor), step, cursor)
61
+ return immediate if immediate
62
+
63
+ code ||= -1
64
+ if code.positive?
65
+ stack << (code - 1)
66
+ cursor += 1
67
+ next
68
+ end
69
+
70
+ reason = reduce_stack(stack, code)
71
+ return result(:rejected, step + 1, cursor, reason) if reason
72
+ end
73
+ result(:exhausted, max_steps, cursor, "max_steps exceeded")
74
+ end
75
+
76
+ # @rbs (Integer? code, Integer token_id, Integer step, Integer cursor) -> Result?
77
+ def immediate_result(code, token_id, step, cursor)
78
+ return result(:rejected, step + 1, cursor, "no parser action") if code.nil? || code == -1
79
+ return unless code.zero?
80
+ return result(:rejected, step + 1, cursor, "accept action before end of input") unless token_id.zero?
81
+
82
+ result(:accepted, step + 1, cursor, nil)
83
+ end
84
+
85
+ # @rbs (Array[Integer] token_ids) -> Array[Integer]
86
+ def validate_input(token_ids)
87
+ raise ArgumentError, "token_ids must be an array" unless token_ids.is_a?(Array)
88
+
89
+ token_ids.map.with_index do |token_id, index|
90
+ raise ArgumentError, "token_ids[#{index}] must be an internal terminal id" unless
91
+ token_id.is_a?(Integer) && @terminal_ids.include?(token_id)
92
+ raise ArgumentError, "$eof may only appear at the end" if token_id.zero? && index != token_ids.length - 1
93
+
94
+ token_id
95
+ end
96
+ end
97
+
98
+ # @rbs (String | Symbol? requested) -> Integer
99
+ def entry_state(requested)
100
+ entries = @payload.fetch("entry_states") #: Array[Hash[String, ValidationSupport::json_value]]
101
+ default_state = entries.first.fetch("state") #: Integer
102
+ return default_state unless requested
103
+
104
+ entry = entries.find { |candidate| candidate.fetch("name") == requested.to_s }
105
+ raise ArgumentError, "unknown parser entry #{requested.inspect}" unless entry
106
+
107
+ entry.fetch("state") #: Integer
108
+ end
109
+
110
+ # @rbs (Integer row, Integer column) -> Integer?
111
+ def action(row, column)
112
+ table = @tables.fetch("actions") #: Hash[String, ValidationSupport::json_value]
113
+ code = if table.fetch("encoding") == "signed-sparse-rows-v1"
114
+ rows = table.fetch("rows") #: Array[Array[Hash[String, ValidationSupport::json_value]]]
115
+ cells = rows.fetch(row)
116
+ cell = cells.bsearch do |candidate|
117
+ token_id = candidate.fetch("token_id") #: Integer
118
+ token_id >= column
119
+ end
120
+ if cell
121
+ token_id = cell.fetch("token_id") #: Integer
122
+ if token_id == column
123
+ cell.fetch("code") #: Integer
124
+ end
125
+ end
126
+ else
127
+ displacement_lookup(table, row, column, "codes")
128
+ end
129
+ defaults = @tables.fetch("default_actions") #: Array[Integer?]
130
+ code.nil? ? defaults.fetch(row) : code
131
+ end
132
+
133
+ # @rbs (Integer row, Integer column) -> Integer?
134
+ def goto_state(row, column)
135
+ table = @tables.fetch("gotos") #: Hash[String, ValidationSupport::json_value]
136
+ if table.fetch("encoding") == "sparse-rows-v1"
137
+ rows = table.fetch("rows") #: Array[Array[Hash[String, ValidationSupport::json_value]]]
138
+ cells = rows.fetch(row)
139
+ cell = cells.bsearch do |candidate|
140
+ symbol_id = candidate.fetch("symbol_id") #: Integer
141
+ symbol_id >= column
142
+ end
143
+ if cell
144
+ symbol_id = cell.fetch("symbol_id") #: Integer
145
+ if symbol_id == column
146
+ cell.fetch("state") #: Integer
147
+ end
148
+ end
149
+ else
150
+ displacement_lookup(table, row, column, "values")
151
+ end
152
+ end
153
+
154
+ # @rbs (Hash[String, ValidationSupport::json_value] table, Integer row, Integer column,
155
+ # String value_key) -> Integer?
156
+ def displacement_lookup(table, row, column, value_key)
157
+ offsets = table.fetch("offsets") #: Array[Integer]
158
+ index = offsets.fetch(row) + column
159
+ checks = table.fetch("checks") #: Array[Integer?]
160
+ return if index.negative? || index >= checks.length || checks[index] != row
161
+
162
+ values = table.fetch(value_key) #: Array[Integer?]
163
+ values.fetch(index)
164
+ end
165
+
166
+ # @rbs (Array[Integer] stack, Integer code) -> String?
167
+ def reduce_stack(stack, code)
168
+ production = @productions.fetch(-2 - code)
169
+ length = production.fetch("rhs_length") #: Integer
170
+ return "reduction underflow" if length >= stack.length
171
+
172
+ stack.pop(length)
173
+ lhs = production.fetch("lhs") #: Integer
174
+ state = goto_state(stack.last, lhs)
175
+ return "missing goto after reduction" unless state
176
+
177
+ stack << state
178
+ nil
179
+ end
180
+
181
+ # @rbs (Symbol status, Integer steps, Integer consumed, String? reason) -> Result
182
+ def result(status, steps, consumed, reason)
183
+ Result.new(status: status, steps: steps, consumed_tokens: consumed, reason: reason)
184
+ end
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibex
4
+ module TableArtifact
5
+ # Canonical JSON ordering and digest primitives shared by writer and loader.
6
+ module Serializer
7
+ # @rbs!
8
+ # type json_value = String | Integer | Float | bool | nil | Array[json_value] | Hash[json_value, json_value]
9
+
10
+ class << self
11
+ # @rbs (json_value value) -> json_value
12
+ def canonical(value)
13
+ case value
14
+ when Hash
15
+ value.keys.sort.to_h { |key| [key, canonical(value.fetch(key))] }
16
+ when Array
17
+ value.map { |item| canonical(item) }
18
+ when String
19
+ normalized = value.dup.force_encoding(Encoding::UTF_8)
20
+ normalized.valid_encoding? ? normalized : normalized.scrub
21
+ else
22
+ value
23
+ end
24
+ end
25
+
26
+ # @rbs (json_value value) -> String
27
+ def compact(value)
28
+ JSON.generate(canonical(value))
29
+ end
30
+
31
+ # @rbs (json_value value) -> String
32
+ def dump(value)
33
+ "#{JSON.pretty_generate(canonical(value))}\n"
34
+ end
35
+
36
+ # @rbs (json_value value) -> String
37
+ def digest(value)
38
+ "sha256:#{Digest::SHA256.hexdigest(compact(value))}"
39
+ end
40
+
41
+ # @rbs (json_value value) -> json_value
42
+ def deep_freeze(value)
43
+ case value
44
+ when Hash
45
+ value.each do |key, item|
46
+ deep_freeze(key)
47
+ deep_freeze(item)
48
+ end
49
+ when Array
50
+ value.each { |item| deep_freeze(item) }
51
+ end
52
+ value.freeze
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,179 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibex
4
+ module TableArtifact
5
+ class MetadataValidator
6
+ include ValidationSupport
7
+
8
+ # @rbs (Hash[String, ValidationSupport::json_value] payload, symbols: Array[Hash[String, ValidationSupport::json_value]],
9
+ # productions: Array[Hash[String, ValidationSupport::json_value]]) -> void
10
+ def initialize(payload, symbols:, productions:)
11
+ @payload = payload
12
+ @symbols = symbols
13
+ @productions = productions
14
+ @terminal_ids = ids_for_kind(symbols, "terminal")
15
+ @nonterminal_ids = ids_for_kind(symbols, "nonterminal")
16
+ end
17
+
18
+ # @rbs () -> void
19
+ def validate!
20
+ validate_semantic_actions(@payload.fetch("semantic_actions"))
21
+ validate_recovery(@payload.fetch("recovery"))
22
+ validate_cst(@payload.fetch("cst"))
23
+ end
24
+
25
+ private
26
+
27
+ # @rbs (Array[Hash[String, ValidationSupport::json_value]] symbols, String kind) -> Set[Integer]
28
+ def ids_for_kind(symbols, kind)
29
+ symbols.filter_map do |symbol|
30
+ next unless symbol.fetch("kind") == kind
31
+
32
+ symbol.fetch("id") #: Integer
33
+ end.to_set
34
+ end
35
+
36
+ # @rbs (ValidationSupport::json_value data) -> void
37
+ def validate_semantic_actions(data)
38
+ path = "$.payload.semantic_actions"
39
+ data = record(data, path, %w[binding verified slots])
40
+ enum(data.fetch("binding"), "#{path}.binding", ["opaque-wrapper-production-id-v1"])
41
+ invalid("#{path}.verified", "must be false") unless boolean(data.fetch("verified"), "#{path}.verified") == false
42
+ slots = integer_ids(data.fetch("slots"), "#{path}.slots")
43
+ expected = @productions.filter_map { |production| production.fetch("action_slot") }
44
+ invalid("#{path}.slots", "must match production action slots") unless slots == expected
45
+ end
46
+
47
+ # @rbs (ValidationSupport::json_value data) -> void
48
+ def validate_recovery(data)
49
+ path = "$.payload.recovery"
50
+ data = record(data, path, %w[sync_token_ids on_error_reduce_symbol_ids])
51
+ sync_ids = integer_ids(data.fetch("sync_token_ids"), "#{path}.sync_token_ids", sorted: false)
52
+ sync_ids.each do |id|
53
+ invalid("#{path}.sync_token_ids", "must reference terminals") unless @terminal_ids.include?(id)
54
+ end
55
+ groups = array(data.fetch("on_error_reduce_symbol_ids"), "#{path}.on_error_reduce_symbol_ids")
56
+ groups.each_with_index do |group, index|
57
+ ids = integer_ids(group, "#{path}.on_error_reduce_symbol_ids[#{index}]", sorted: false)
58
+ invalid("#{path}.on_error_reduce_symbol_ids[#{index}]", "must not be empty") if ids.empty?
59
+ ids.each do |id|
60
+ invalid("#{path}.on_error_reduce_symbol_ids[#{index}]", "must reference nonterminals") unless
61
+ @nonterminal_ids.include?(id)
62
+ end
63
+ end
64
+ end
65
+
66
+ # @rbs (ValidationSupport::json_value data) -> void
67
+ def validate_cst(data)
68
+ return if data.nil?
69
+
70
+ path = "$.payload.cst"
71
+ data = record(data, path, %w[version trivia_policy kinds slots])
72
+ invalid("#{path}.version", "must be 1") unless integer(data.fetch("version"), "#{path}.version") == 1
73
+ enum(data.fetch("trivia_policy"), "#{path}.trivia_policy", %w[leading balanced drop])
74
+ kind_count = validate_cst_kinds(data.fetch("kinds"), "#{path}.kinds")
75
+ validate_cst_slots(data.fetch("slots"), "#{path}.slots", kind_count)
76
+ end
77
+
78
+ # @rbs (ValidationSupport::json_value data, String path) -> Integer
79
+ def validate_cst_kinds(data, path)
80
+ keys = %w[names terminal_range nonterminal_range named named_nonterminals trivia synthetic]
81
+ data = record(data, path, keys)
82
+ names = array(data.fetch("names"), "#{path}.names") #: Array[String]
83
+ names.each_with_index { |name, index| string(name, "#{path}.names[#{index}]") }
84
+ validate_range(data.fetch("terminal_range"), "#{path}.terminal_range", names.length)
85
+ validate_range(data.fetch("nonterminal_range"), "#{path}.nonterminal_range", names.length)
86
+ %w[named trivia synthetic].each { |key| validate_named_kinds(data.fetch(key), "#{path}.#{key}", names) }
87
+ validate_named_nonterminals(data.fetch("named_nonterminals"), "#{path}.named_nonterminals", names.length)
88
+ names.length
89
+ end
90
+
91
+ # @rbs (ValidationSupport::json_value data, String path, Integer limit) -> void
92
+ def validate_range(data, path, limit)
93
+ values = array(data, path)
94
+ invalid(path, "must contain two bounds") unless values.length == 2
95
+ start = integer(values.fetch(0), "#{path}[0]", minimum: 0)
96
+ finish = integer(values.fetch(1), "#{path}[1]", minimum: 0)
97
+ invalid(path, "must be an ordered half-open range") unless finish.between?(start, limit)
98
+ end
99
+
100
+ # @rbs (ValidationSupport::json_value data, String path, Array[String] names) -> void
101
+ def validate_named_kinds(data, path, names)
102
+ entries = array(data, path)
103
+ ids = entries.map.with_index do |entry, index|
104
+ entry_path = "#{path}[#{index}]"
105
+ entry = record(entry, entry_path, %w[name id])
106
+ name = string(entry.fetch("name"), "#{entry_path}.name")
107
+ id = integer(entry.fetch("id"), "#{entry_path}.id", minimum: 0)
108
+ invalid(entry_path, "does not match the kind name table") unless names[id] == name
109
+ id
110
+ end
111
+ sorted_unique!(ids, path)
112
+ end
113
+
114
+ # @rbs (ValidationSupport::json_value data, String path, Integer kind_count) -> void
115
+ def validate_named_nonterminals(data, path, kind_count)
116
+ pairs = array(data, path).map.with_index do |entry, index|
117
+ entry_path = "#{path}[#{index}]"
118
+ entry = record(entry, entry_path, %w[kind_id symbol_id])
119
+ kind_id = integer(entry.fetch("kind_id"), "#{entry_path}.kind_id", minimum: 0)
120
+ invalid("#{entry_path}.kind_id", "references a missing kind") unless kind_id < kind_count
121
+ symbol_id = integer(entry.fetch("symbol_id"), "#{entry_path}.symbol_id", minimum: 0)
122
+ invalid("#{entry_path}.symbol_id", "must reference a nonterminal") unless @nonterminal_ids.include?(symbol_id)
123
+ [kind_id, symbol_id]
124
+ end
125
+ return if pairs == pairs.sort && pairs.map(&:first).uniq.length == pairs.length
126
+
127
+ invalid(path,
128
+ "must be sorted with unique kind ids")
129
+ end
130
+
131
+ # @rbs (ValidationSupport::json_value data, String path, Integer kind_count) -> void
132
+ def validate_cst_slots(data, path, kind_count)
133
+ production_ids = array(data, path).map.with_index do |slot, index|
134
+ slot_path = "#{path}[#{index}]"
135
+ slot = record(slot, slot_path, %w[production_id node_kind_id node_name fields])
136
+ production_id = integer(slot.fetch("production_id"), "#{slot_path}.production_id", minimum: 0)
137
+ unless production_id < @productions.length
138
+ invalid("#{slot_path}.production_id",
139
+ "references a missing production")
140
+ end
141
+ node_kind = integer(slot.fetch("node_kind_id"), "#{slot_path}.node_kind_id", minimum: 0)
142
+ invalid("#{slot_path}.node_kind_id", "references a missing kind") unless node_kind < kind_count
143
+ string(slot.fetch("node_name"), "#{slot_path}.node_name")
144
+ validate_fields(slot.fetch("fields"), "#{slot_path}.fields", @productions.fetch(production_id))
145
+ production_id
146
+ end
147
+ sorted_unique!(production_ids, path)
148
+ end
149
+
150
+ # @rbs (ValidationSupport::json_value data, String path,
151
+ # Hash[String, ValidationSupport::json_value] production) -> void
152
+ def validate_fields(data, path, production)
153
+ names = array(data, path).map.with_index do |field, index|
154
+ field_path = "#{path}[#{index}]"
155
+ field = record(field, field_path, %w[name index extraction])
156
+ name = string(field.fetch("name"), "#{field_path}.name")
157
+ field_index = integer(field.fetch("index"), "#{field_path}.index", minimum: 0)
158
+ rhs_length = production.fetch("rhs_length") #: Integer
159
+ invalid("#{field_path}.index", "exceeds production rhs") unless field_index < rhs_length
160
+ extraction = field.fetch("extraction")
161
+ enum(extraction, "#{field_path}.extraction", %w[repetition separated_list]) unless extraction.nil?
162
+ name
163
+ end
164
+ invalid(path, "must have unique field names") unless names.uniq.length == names.length
165
+ end
166
+
167
+ # @rbs (ValidationSupport::json_value data, String path, ?sorted: bool) -> Array[Integer]
168
+ def integer_ids(data, path, sorted: true)
169
+ ids = array(data, path).map.with_index { |id, index| integer(id, "#{path}[#{index}]", minimum: 0) }
170
+ if sorted
171
+ sorted_unique!(ids, path)
172
+ else
173
+ invalid(path, "must contain unique ids") unless ids.uniq.length == ids.length
174
+ end
175
+ ids
176
+ end
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibex
4
+ module TableArtifact
5
+ module ValidationSupport
6
+ # @rbs!
7
+ # type json_value = String | Integer | Float | bool | nil | Array[json_value] | Hash[String, json_value]
8
+
9
+ DIGEST = /\Asha256:[0-9a-f]{64}\z/ #: Regexp
10
+
11
+ private
12
+
13
+ # @rbs (json_value value, String path, Array[String] keys) -> Hash[String, json_value]
14
+ def record(value, path, keys)
15
+ invalid(path, "must be an object") unless value.is_a?(Hash)
16
+ invalid(path, "must use string keys") unless value.keys.all?(String)
17
+
18
+ missing = keys - value.keys
19
+ extra = value.keys - keys
20
+ invalid(path, "is missing #{missing.join(', ')}") unless missing.empty?
21
+ invalid(path, "contains unknown fields #{extra.join(', ')}") unless extra.empty?
22
+ value #: Hash[String, json_value]
23
+ end
24
+
25
+ # @rbs (json_value value, String path) -> Array[json_value]
26
+ def array(value, path)
27
+ invalid(path, "must be an array") unless value.is_a?(Array)
28
+ value #: Array[json_value]
29
+ end
30
+
31
+ # @rbs (json_value value, String path, ?allow_empty: bool) -> String
32
+ def string(value, path, allow_empty: false)
33
+ invalid(path, "must be a string") unless value.is_a?(String)
34
+ invalid(path, "must not be empty") if !allow_empty && value.empty?
35
+ value #: String
36
+ end
37
+
38
+ # @rbs (json_value value, String path, ?minimum: Integer?) -> Integer
39
+ def integer(value, path, minimum: nil)
40
+ invalid(path, "must be an integer") unless value.is_a?(Integer)
41
+ invalid(path, "must be at least #{minimum}") if minimum && value < minimum
42
+ value #: Integer
43
+ end
44
+
45
+ # @rbs (json_value value, String path) -> bool
46
+ def boolean(value, path)
47
+ invalid(path, "must be true or false") unless [true, false].include?(value)
48
+ value #: bool
49
+ end
50
+
51
+ # @rbs [T] (T value, String path, Array[T] values) -> T
52
+ def enum(value, path, values)
53
+ invalid(path, "must be one of #{values.join(', ')}") unless values.include?(value)
54
+ value
55
+ end
56
+
57
+ # @rbs (json_value value, String path) -> String
58
+ def digest(value, path)
59
+ invalid(path, "must be a sha256 digest") unless value.is_a?(String) && DIGEST.match?(value)
60
+ value
61
+ end
62
+
63
+ # @rbs (json_value value, String path) -> String?
64
+ def nullable_string(value, path)
65
+ string(value, path, allow_empty: true) unless value.nil?
66
+ value #: String?
67
+ end
68
+
69
+ # @rbs (json_value value, String path, ?minimum: Integer?) -> Integer?
70
+ def nullable_integer(value, path, minimum: nil)
71
+ integer(value, path, minimum: minimum) unless value.nil?
72
+ value #: Integer?
73
+ end
74
+
75
+ # @rbs (Array[json_value] values, String path) -> void
76
+ def sorted_unique!(values, path)
77
+ invalid(path, "must be sorted and unique") unless values == values.sort.uniq
78
+ end
79
+
80
+ # @rbs (String path, String message) -> bot
81
+ def invalid(path, message)
82
+ raise ValidationError, "#{path} #{message}"
83
+ end
84
+ end
85
+ end
86
+ end