parseman 0.45.0 → 0.47.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 (333) hide show
  1. package/README.md +8 -3
  2. package/dist/analysis/choice-cost-gate.d.ts +158 -0
  3. package/dist/analysis/choice-cost-gate.d.ts.map +1 -0
  4. package/dist/analysis/choice-cost-render.d.ts +96 -0
  5. package/dist/analysis/choice-cost-render.d.ts.map +1 -0
  6. package/dist/analysis/choice-cost.d.ts +383 -0
  7. package/dist/analysis/choice-cost.d.ts.map +1 -0
  8. package/dist/analysis/commitment.d.ts +131 -0
  9. package/dist/analysis/commitment.d.ts.map +1 -0
  10. package/dist/analysis/corpus.d.ts +73 -0
  11. package/dist/analysis/corpus.d.ts.map +1 -0
  12. package/dist/analysis/diagnose-render.d.ts +65 -0
  13. package/dist/analysis/diagnose-render.d.ts.map +1 -0
  14. package/dist/analysis/diagnose.d.ts +15 -0
  15. package/dist/analysis/diagnose.d.ts.map +1 -1
  16. package/dist/analysis/diagnostics.cjs +13736 -0
  17. package/dist/analysis/diagnostics.cjs.map +6 -0
  18. package/dist/analysis/diagnostics.d.ts +27 -0
  19. package/dist/analysis/diagnostics.d.ts.map +1 -0
  20. package/dist/analysis/diagnostics.js +13713 -0
  21. package/dist/analysis/diagnostics.js.map +6 -0
  22. package/dist/analysis/duplication.d.ts.map +1 -1
  23. package/dist/analysis/fix-render.d.ts +43 -0
  24. package/dist/analysis/fix-render.d.ts.map +1 -0
  25. package/dist/analysis/fix.d.ts +172 -0
  26. package/dist/analysis/fix.d.ts.map +1 -0
  27. package/dist/analysis/format-number.d.ts +23 -0
  28. package/dist/analysis/format-number.d.ts.map +1 -0
  29. package/dist/analysis/gating.d.ts +47 -2
  30. package/dist/analysis/gating.d.ts.map +1 -1
  31. package/dist/analysis/rebuild.d.ts +61 -0
  32. package/dist/analysis/rebuild.d.ts.map +1 -0
  33. package/dist/analysis/terminal.d.ts +145 -0
  34. package/dist/analysis/terminal.d.ts.map +1 -0
  35. package/dist/cli/index.cjs +14837 -0
  36. package/dist/cli/index.cjs.map +6 -0
  37. package/dist/cli/index.d.ts +3 -0
  38. package/dist/cli/index.d.ts.map +1 -0
  39. package/dist/cli/index.js +14814 -0
  40. package/dist/cli/index.js.map +6 -0
  41. package/dist/combinators/adjacency.d.ts +100 -0
  42. package/dist/combinators/adjacency.d.ts.map +1 -0
  43. package/dist/combinators/choice.d.ts.map +1 -1
  44. package/dist/combinators/completions.d.ts.map +1 -1
  45. package/dist/combinators/dispatch.d.ts +8 -1
  46. package/dist/combinators/dispatch.d.ts.map +1 -1
  47. package/dist/combinators/expect.d.ts.map +1 -1
  48. package/dist/combinators/first-set.d.ts.map +1 -1
  49. package/dist/combinators/gate.d.ts.map +1 -1
  50. package/dist/combinators/grammar.d.ts +22 -0
  51. package/dist/combinators/grammar.d.ts.map +1 -1
  52. package/dist/combinators/literal.d.ts +8 -0
  53. package/dist/combinators/literal.d.ts.map +1 -1
  54. package/dist/combinators/map.d.ts +0 -1
  55. package/dist/combinators/map.d.ts.map +1 -1
  56. package/dist/combinators/node.d.ts +13 -3
  57. package/dist/combinators/node.d.ts.map +1 -1
  58. package/dist/combinators/parser.d.ts +1 -1
  59. package/dist/combinators/parser.d.ts.map +1 -1
  60. package/dist/combinators/ref.d.ts.map +1 -1
  61. package/dist/combinators/regex.d.ts +1 -16
  62. package/dist/combinators/regex.d.ts.map +1 -1
  63. package/dist/combinators/repeat.d.ts +30 -2
  64. package/dist/combinators/repeat.d.ts.map +1 -1
  65. package/dist/combinators/scanTo.d.ts +71 -1
  66. package/dist/combinators/scanTo.d.ts.map +1 -1
  67. package/dist/combinators/sequence.d.ts.map +1 -1
  68. package/dist/combinators/token.d.ts.map +1 -1
  69. package/dist/combinators/trivia-boundary.d.ts +26 -0
  70. package/dist/combinators/trivia-boundary.d.ts.map +1 -0
  71. package/dist/combinators/trivia-skip.d.ts +40 -1
  72. package/dist/combinators/trivia-skip.d.ts.map +1 -1
  73. package/dist/combinators/withCtx.d.ts.map +1 -1
  74. package/dist/compiler/build-arity.d.ts.map +1 -1
  75. package/dist/compiler/compile-linkable-table.d.ts +104 -0
  76. package/dist/compiler/compile-linkable-table.d.ts.map +1 -0
  77. package/dist/compiler/degradation.d.ts +0 -2
  78. package/dist/compiler/degradation.d.ts.map +1 -1
  79. package/dist/compiler/fields.d.ts +13 -0
  80. package/dist/compiler/fields.d.ts.map +1 -1
  81. package/dist/compiler/grammar-coverage-ids.d.ts +5 -5
  82. package/dist/compiler/grammar-coverage-ids.d.ts.map +1 -1
  83. package/dist/compiler/ir-serialize.d.ts.map +1 -1
  84. package/dist/compiler/linker.d.ts +79 -47
  85. package/dist/compiler/linker.d.ts.map +1 -1
  86. package/dist/compiler/token-alphabet.d.ts +81 -0
  87. package/dist/compiler/token-alphabet.d.ts.map +1 -0
  88. package/dist/compiler/token-dispatch.d.ts +95 -0
  89. package/dist/compiler/token-dispatch.d.ts.map +1 -0
  90. package/dist/compiler/token-scanner.d.ts +53 -0
  91. package/dist/compiler/token-scanner.d.ts.map +1 -0
  92. package/dist/compiler/value-usage.d.ts.map +1 -1
  93. package/dist/coverage.d.ts +1 -1
  94. package/dist/coverage.d.ts.map +1 -1
  95. package/dist/cst/capture-buffer.d.ts +35 -0
  96. package/dist/cst/capture-buffer.d.ts.map +1 -1
  97. package/dist/cst/reflection-attach.d.ts +8 -0
  98. package/dist/cst/reflection-attach.d.ts.map +1 -0
  99. package/dist/cst/reflection-symbols.d.ts +10 -0
  100. package/dist/cst/reflection-symbols.d.ts.map +1 -0
  101. package/dist/cst/reflection.d.ts +2 -4
  102. package/dist/cst/reflection.d.ts.map +1 -1
  103. package/dist/cst/root-trivia-scope.d.ts +26 -0
  104. package/dist/cst/root-trivia-scope.d.ts.map +1 -0
  105. package/dist/cst/trivia-charscan.d.ts +18 -0
  106. package/dist/cst/trivia-charscan.d.ts.map +1 -0
  107. package/dist/cst/trivia-kinds.d.ts +19 -0
  108. package/dist/cst/trivia-kinds.d.ts.map +1 -1
  109. package/dist/functional/doc.d.ts.map +1 -1
  110. package/dist/functional/run-tabled.d.ts +12 -0
  111. package/dist/functional/run-tabled.d.ts.map +1 -0
  112. package/dist/functional/run.d.ts +25 -42
  113. package/dist/functional/run.d.ts.map +1 -1
  114. package/dist/grammar-metadata.d.ts +3 -0
  115. package/dist/grammar-metadata.d.ts.map +1 -0
  116. package/dist/index.cjs +10499 -7478
  117. package/dist/index.cjs.map +3 -4
  118. package/dist/index.d.ts +24 -9
  119. package/dist/index.d.ts.map +1 -1
  120. package/dist/index.js +10499 -7478
  121. package/dist/index.js.map +3 -4
  122. package/dist/language-service/index.cjs +311 -121
  123. package/dist/language-service/index.cjs.map +3 -4
  124. package/dist/language-service/index.js +311 -121
  125. package/dist/language-service/index.js.map +3 -4
  126. package/dist/oracle/index.cjs.map +0 -1
  127. package/dist/oracle/index.js.map +0 -1
  128. package/dist/parse-context.d.ts +49 -0
  129. package/dist/parse-context.d.ts.map +1 -0
  130. package/dist/plugin/evaluator.d.ts +41 -2
  131. package/dist/plugin/evaluator.d.ts.map +1 -1
  132. package/dist/plugin/free-identifiers.d.ts +23 -0
  133. package/dist/plugin/free-identifiers.d.ts.map +1 -0
  134. package/dist/plugin/index.cjs +11381 -9442
  135. package/dist/plugin/index.cjs.map +3 -4
  136. package/dist/plugin/index.d.ts.map +1 -1
  137. package/dist/plugin/index.js +11381 -9442
  138. package/dist/plugin/index.js.map +3 -4
  139. package/dist/plugin/reducer-resolver.d.ts +17 -1
  140. package/dist/plugin/reducer-resolver.d.ts.map +1 -1
  141. package/dist/regex/classes.d.ts +28 -0
  142. package/dist/regex/classes.d.ts.map +1 -1
  143. package/dist/regex/first-set.d.ts +14 -0
  144. package/dist/regex/first-set.d.ts.map +1 -1
  145. package/dist/run/index.cjs +136 -51
  146. package/dist/run/index.cjs.map +2 -3
  147. package/dist/run/index.js +136 -51
  148. package/dist/run/index.js.map +2 -3
  149. package/dist/spec/index.cjs +2898 -1622
  150. package/dist/spec/index.cjs.map +3 -4
  151. package/dist/spec/index.js +2898 -1622
  152. package/dist/spec/index.js.map +3 -4
  153. package/dist/spec/model.d.ts +8 -0
  154. package/dist/spec/model.d.ts.map +1 -1
  155. package/dist/table/assemble.d.ts +307 -0
  156. package/dist/table/assemble.d.ts.map +1 -0
  157. package/dist/table/cell.d.ts +42 -0
  158. package/dist/table/cell.d.ts.map +1 -0
  159. package/dist/table/child-slots.d.ts +30 -0
  160. package/dist/table/child-slots.d.ts.map +1 -0
  161. package/dist/table/compile-rule-map.d.ts +136 -0
  162. package/dist/table/compile-rule-map.d.ts.map +1 -0
  163. package/dist/table/compile.d.ts +56 -0
  164. package/dist/table/compile.d.ts.map +1 -0
  165. package/dist/table/duplication-hook.d.ts +32 -0
  166. package/dist/table/duplication-hook.d.ts.map +1 -0
  167. package/dist/table/emit-assembly.d.ts +139 -0
  168. package/dist/table/emit-assembly.d.ts.map +1 -0
  169. package/dist/table/emit.d.ts +113 -0
  170. package/dist/table/emit.d.ts.map +1 -0
  171. package/dist/table/encode-baseline.d.ts +16 -0
  172. package/dist/table/encode-baseline.d.ts.map +1 -0
  173. package/dist/table/encode.d.ts +71 -0
  174. package/dist/table/encode.d.ts.map +1 -0
  175. package/dist/table/exec-baseline.d.ts +9 -0
  176. package/dist/table/exec-baseline.d.ts.map +1 -0
  177. package/dist/table/exec.d.ts +72 -0
  178. package/dist/table/exec.d.ts.map +1 -0
  179. package/dist/table/fold.d.ts +25 -0
  180. package/dist/table/fold.d.ts.map +1 -0
  181. package/dist/table/index.cjs +11375 -0
  182. package/dist/table/index.cjs.map +6 -0
  183. package/dist/table/index.d.ts +100 -0
  184. package/dist/table/index.d.ts.map +1 -0
  185. package/dist/table/index.js +11352 -0
  186. package/dist/table/index.js.map +6 -0
  187. package/dist/table/inspect.d.ts +17 -0
  188. package/dist/table/inspect.d.ts.map +1 -0
  189. package/dist/table/ops.d.ts +446 -0
  190. package/dist/table/ops.d.ts.map +1 -0
  191. package/dist/table/program.d.ts +493 -0
  192. package/dist/table/program.d.ts.map +1 -0
  193. package/dist/table/run-support.d.ts +38 -0
  194. package/dist/table/run-support.d.ts.map +1 -0
  195. package/dist/{compiler/scannable-run.d.ts → table/scan-shapes.d.ts} +14 -13
  196. package/dist/table/scan-shapes.d.ts.map +1 -0
  197. package/dist/table/site-labels.d.ts +58 -0
  198. package/dist/table/site-labels.d.ts.map +1 -0
  199. package/dist/table/stamp.d.ts +70 -0
  200. package/dist/table/stamp.d.ts.map +1 -0
  201. package/dist/types.d.ts +80 -24
  202. package/dist/types.d.ts.map +1 -1
  203. package/dist/version.d.ts +1 -1
  204. package/package.json +41 -3
  205. package/src/analysis/choice-cost-gate.ts +359 -0
  206. package/src/analysis/choice-cost-render.ts +293 -0
  207. package/src/analysis/choice-cost.ts +1008 -0
  208. package/src/analysis/commitment.ts +557 -0
  209. package/src/analysis/corpus.ts +130 -0
  210. package/src/analysis/diagnose-render.ts +625 -0
  211. package/src/analysis/diagnose.ts +317 -0
  212. package/src/analysis/diagnostics.ts +33 -0
  213. package/src/analysis/duplication.ts +1955 -0
  214. package/src/analysis/fix-render.ts +217 -0
  215. package/src/analysis/fix.ts +669 -0
  216. package/src/analysis/format-number.ts +31 -0
  217. package/src/analysis/gating.ts +792 -0
  218. package/src/analysis/grammar.ts +72 -0
  219. package/src/analysis/rebuild.ts +287 -0
  220. package/src/analysis/terminal.ts +336 -0
  221. package/src/cli/index.ts +413 -0
  222. package/src/combinators/adjacency.ts +171 -0
  223. package/src/combinators/attempt.ts +41 -0
  224. package/src/combinators/case-fold.ts +90 -0
  225. package/src/combinators/choice.ts +466 -0
  226. package/src/combinators/completions.ts +64 -0
  227. package/src/combinators/dispatch.ts +358 -0
  228. package/src/combinators/expect.ts +159 -0
  229. package/src/combinators/first-set.ts +322 -0
  230. package/src/combinators/gate.ts +50 -0
  231. package/src/combinators/grammar.ts +272 -0
  232. package/src/combinators/keywords.ts +145 -0
  233. package/src/combinators/literal.ts +102 -0
  234. package/src/combinators/map.ts +106 -0
  235. package/src/combinators/node.ts +345 -0
  236. package/src/combinators/not.ts +55 -0
  237. package/src/combinators/parser.ts +266 -0
  238. package/src/combinators/peek.ts +63 -0
  239. package/src/combinators/probe.ts +25 -0
  240. package/src/combinators/ref.ts +109 -0
  241. package/src/combinators/regex.ts +170 -0
  242. package/src/combinators/repeat.ts +561 -0
  243. package/src/combinators/scanTo.ts +393 -0
  244. package/src/combinators/sequence.ts +221 -0
  245. package/src/combinators/token.ts +120 -0
  246. package/src/combinators/trivia-boundary.ts +48 -0
  247. package/src/combinators/trivia-skip.ts +821 -0
  248. package/src/combinators/withCtx.ts +45 -0
  249. package/src/compiler/build-arity.ts +330 -0
  250. package/src/compiler/compile-linkable-table.ts +209 -0
  251. package/src/compiler/degradation.ts +266 -0
  252. package/src/compiler/fields.ts +191 -0
  253. package/src/compiler/grammar-coverage-ids.ts +129 -0
  254. package/src/compiler/ir-serialize.ts +615 -0
  255. package/src/compiler/linker.ts +954 -0
  256. package/src/compiler/token-alphabet.ts +209 -0
  257. package/src/compiler/token-dispatch.ts +353 -0
  258. package/src/compiler/token-scanner.ts +318 -0
  259. package/src/compiler/value-usage.ts +147 -0
  260. package/src/coverage.ts +383 -0
  261. package/src/cst/capture-buffer.ts +297 -0
  262. package/src/cst/host-mode.ts +69 -0
  263. package/src/cst/reflection-attach.ts +11 -0
  264. package/src/cst/reflection-symbols.ts +9 -0
  265. package/src/cst/reflection.ts +149 -0
  266. package/src/cst/relative-spans.ts +207 -0
  267. package/src/cst/root-trivia-scope.ts +30 -0
  268. package/src/cst/trivia-charscan.ts +312 -0
  269. package/src/cst/trivia-entries.ts +285 -0
  270. package/src/cst/trivia-index.ts +131 -0
  271. package/src/cst/trivia-kinds.ts +358 -0
  272. package/src/cst/types.ts +76 -0
  273. package/src/cst/walk.ts +101 -0
  274. package/src/functional/doc.ts +959 -0
  275. package/src/functional/run-tabled.ts +153 -0
  276. package/src/functional/run.ts +558 -0
  277. package/src/grammar-metadata.ts +2 -0
  278. package/src/index.ts +189 -0
  279. package/src/language-service/index.ts +221 -0
  280. package/src/line-index.ts +131 -0
  281. package/src/oracle/digest.ts +620 -0
  282. package/src/oracle/index.ts +55 -0
  283. package/src/parse-context.ts +91 -0
  284. package/src/plugin/direct-builder-static.ts +102 -0
  285. package/src/plugin/evaluator.ts +1505 -0
  286. package/src/plugin/free-identifiers.ts +338 -0
  287. package/src/plugin/index.ts +2281 -0
  288. package/src/plugin/reducer-resolver.ts +606 -0
  289. package/src/recovery/scan.ts +155 -0
  290. package/src/regex/classes.ts +183 -0
  291. package/src/regex/first-set.ts +316 -0
  292. package/src/run/index.ts +31 -0
  293. package/src/spec/ebnf.ts +128 -0
  294. package/src/spec/index.ts +54 -0
  295. package/src/spec/model.ts +636 -0
  296. package/src/spec/railroad-lib.ts +559 -0
  297. package/src/spec/railroad.ts +256 -0
  298. package/src/table/assemble.ts +2994 -0
  299. package/src/table/cell.ts +42 -0
  300. package/src/table/child-slots.ts +113 -0
  301. package/src/table/compile-rule-map.ts +336 -0
  302. package/src/table/compile.ts +244 -0
  303. package/src/table/duplication-hook.ts +89 -0
  304. package/src/table/emit-assembly.ts +1766 -0
  305. package/src/table/emit.ts +418 -0
  306. package/src/table/encode-baseline.ts +340 -0
  307. package/src/table/encode.ts +1569 -0
  308. package/src/table/exec-baseline.ts +537 -0
  309. package/src/table/exec.ts +1672 -0
  310. package/src/table/fold.ts +38 -0
  311. package/src/table/index.ts +108 -0
  312. package/src/table/inspect.ts +52 -0
  313. package/src/table/ops.ts +459 -0
  314. package/src/table/program.ts +855 -0
  315. package/src/table/run-support.ts +66 -0
  316. package/src/table/scan-shapes.ts +1578 -0
  317. package/src/table/site-labels.ts +228 -0
  318. package/src/table/stamp.ts +229 -0
  319. package/src/types.ts +563 -0
  320. package/src/version.ts +16 -0
  321. package/dist/compiler/codegen.d.ts +0 -334
  322. package/dist/compiler/codegen.d.ts.map +0 -1
  323. package/dist/compiler/inline-build.d.ts +0 -11
  324. package/dist/compiler/inline-build.d.ts.map +0 -1
  325. package/dist/compiler/inline-callback.d.ts +0 -21
  326. package/dist/compiler/inline-callback.d.ts.map +0 -1
  327. package/dist/compiler/line-index.d.ts +0 -2
  328. package/dist/compiler/line-index.d.ts.map +0 -1
  329. package/dist/compiler/scannable-run.d.ts.map +0 -1
  330. package/dist/compiler/scannable-terminal.d.ts +0 -23
  331. package/dist/compiler/scannable-terminal.d.ts.map +0 -1
  332. package/dist/compiler/trivia-fast-path.d.ts +0 -38
  333. package/dist/compiler/trivia-fast-path.d.ts.map +0 -1
@@ -0,0 +1,558 @@
1
+ import type { Combinator, ParseContext, ParseError, ParseResult, Span } from '../types.ts'
2
+ import { REC } from '../recovery/scan.ts'
3
+ import { createParseContext } from '../parse-context.ts'
4
+ import { buildRootTriviaIndex, type RootTriviaIndex } from '../cst/trivia-entries.ts'
5
+ /* `cst/host-mode.ts` and `cst/trivia-entries.ts` are import-free by design, so
6
+ * this keeps the `parseman/run` closure minimal — see
7
+ * test/unit/run-entry-closure.test.ts. */
8
+ import { assertHostModeCompatible, FUSED_HOST_MODE, FUSED_HOST_ELIDED, type HostMode } from '../cst/host-mode.ts'
9
+
10
+ /**
11
+ * Run a compiled/interpreted grammar entry against an input and collect the raw
12
+ * outcome a tool needs to shape a parse result — WITHOUT the consumer having to
13
+ * hand-build a `ctx`, branch on function-vs-combinator, or scan for leftover
14
+ * input itself.
15
+ *
16
+ * A `compile()`/macro grammar hands you a map of bare parse FUNCTIONS; the
17
+ * interpreter hands you COMBINATORS. `run()` invokes either, threads the standard
18
+ * framework ctx (trivia log, recover/expect error sink, the `ctx.build` host,
19
+ * grammar state), and — given the grammar's trivia parser — reports where
20
+ * non-trivia input was left unconsumed. The consumer keeps only its own policy:
21
+ * how to shape the tree and how to turn diagnostics into its error type.
22
+ */
23
+
24
+ /** A compiled rule (macro/`compile()` output) OR an interpreter combinator. */
25
+ export type Runnable =
26
+ | ((input: string, pos: number, ctx: ParseContext) => ParseResult<unknown>)
27
+ | Combinator<unknown>
28
+
29
+ export type RunOptions = {
30
+ /** Optional hooks for a coverage-enabled compiled or macro parser. Ordinary
31
+ * parses omit this completely, so instrumentation has no normal-path cost.
32
+ * Table-backed 0.47 artifacts support `_grammarCoverage` but reject
33
+ * `_grammarTrace` explicitly; interpreted/source-lowered entries may support
34
+ * both. */
35
+ instrumentation?: {
36
+ _grammarCoverage?: (id: string) => void
37
+ _grammarTrace?: { write(event: { id: string; phase: 'enter' | 'attempt' | 'selected' | 'success' | 'failure' | 'backtrack' | 'rollback'; offset: number; end?: number }): void }
38
+ }
39
+ /** `ctx.build` host — makes structural `node()` rules build a CST / AST via the
40
+ * host instead of their own eval builders. Omit for a grammar's own builders. */
41
+ build?: ParseContext['build']
42
+ /** Initial grammar state threaded into `ctx.state`. */
43
+ state?: unknown
44
+ /**
45
+ * The grammar's trivia rule — an OVERRIDE, no longer a requirement.
46
+ *
47
+ * A root rule consumes trivia BETWEEN terms but not after the last one, so
48
+ * trailing whitespace/comments would otherwise look like unparsed input. `run`
49
+ * skips that tail before computing `unconsumedFrom` and before reporting
50
+ * `span`, so only real leftover is reported.
51
+ *
52
+ * The trivia used is the ENTRY's own ambient trivia — whatever
53
+ * `rules({ trivia })` / `parser({ trivia })` declared — resolved automatically
54
+ * (see `ambientTriviaFromRunnable`). Pass this only to use a DIFFERENT trivia
55
+ * for the document tail than the grammar parses with; it wins when given.
56
+ * Passing the grammar's own trivia is now a no-op, and remains supported.
57
+ *
58
+ * Either way it encodes dialect differences for free: CSS trivia leaves a
59
+ * trailing `//` as leftover, Less trivia (which treats `//` as a line comment)
60
+ * does not. An UNTERMINATED comment (which the trivia rule won't match)
61
+ * surfaces at its start.
62
+ */
63
+ trivia?: Runnable
64
+ /**
65
+ * Restrict PER-NODE CST trivia capture (the `triviaLog` a node's builder sees)
66
+ * to these trivia kinds — a bitmask over the grammar's `triviaKindLabels`
67
+ * indices (build it with `triviaKindMask(labels, ['comment', …])`). Unlisted
68
+ * kinds (e.g. whitespace) are skipped over but not recorded per node, so a host
69
+ * that only reads comments doesn't pay to log every whitespace run. Omit to
70
+ * capture every kind.
71
+ */
72
+ triviaCaptureMask?: number
73
+ /**
74
+ * Opt into sparse root trivia capture. `run()` retains no root trivia unless
75
+ * this is supplied. Capture records only the named labels, each with the one
76
+ * complete authored gap that owns it; ordinary whitespace has no root entry.
77
+ */
78
+ rootTrivia?: {
79
+ readonly select: readonly string[]
80
+ }
81
+ /**
82
+ * Activate automatic list recovery. When true, `many`/`sepBy`/`oneOrMore` recover
83
+ * from a failed element — skip to a sync point (a resume token inferred from the
84
+ * grammar's structure; the grammar carries no recovery config), emit a
85
+ * `ParseError` over the skipped span (collected in `errors`), and keep parsing the
86
+ * rest of the list — instead of stopping at the first bad element. Omit (the
87
+ * default) for the strict "one clean error and stop" behavior, byte-identical to a
88
+ * run with no recovery. Recovery is a cold path: on well-formed input nothing
89
+ * fails, so none of the machinery runs.
90
+ */
91
+ tolerant?: boolean
92
+ }
93
+
94
+ export type RootTriviaCapture = {
95
+ /** Packed `[gapStart, gapEnd, markerStart, markerEnd, selectedKindIndex]` rows. */
96
+ readonly rows: readonly number[]
97
+ /** Labels requested by this caller; row kind indices refer to this array. */
98
+ readonly select: readonly string[]
99
+ /** Lazy lookup over `rows`; no tokens or strings are materialized. */
100
+ readonly index: RootTriviaIndex
101
+ }
102
+
103
+ export type RunResult = {
104
+ ok: boolean
105
+ /** The entry's value on success; undefined on failure. */
106
+ value: unknown
107
+ span: { start: number; end: number }
108
+ /** Expected-token set when the TOP-LEVEL parse failed (empty on success). */
109
+ expected: string[]
110
+ /** Recovery diagnostics (tolerant lists / `expect()`) collected during the parse (in order). */
111
+ errors: ParseError[]
112
+ /**
113
+ * Sparse selected root trivia. This is present only when at least one requested
114
+ * category was actually retained; omitted means the parse retained no root
115
+ * trivia at all.
116
+ */
117
+ rootTrivia?: RootTriviaCapture
118
+ /** Offset where unparsed input begins — the first non-trivia character the parse
119
+ * left unconsumed (the document's trailing trivia is always skipped; see
120
+ * `RunOptions.trivia`), or null if the whole input was consumed. This is how you
121
+ * detect "the grammar stopped short, there's junk here". Only meaningful on
122
+ * success — a failed parse reports its own `span`/`expected`. */
123
+ unconsumedFrom: number | null
124
+ }
125
+
126
+ /**
127
+ * 0.44 dropped three `RunResult` fields — `triviaMap` and `triviaLog`, both
128
+ * MANDATORY in 0.43, and the optional `triviaKindLabels`. Removing them without
129
+ * a signal makes each read `undefined`, and `undefined` travels: it surfaces as
130
+ * a property access on nothing somewhere inside the CONSUMER's code, in a
131
+ * message naming neither parseman, the field, nor the replacement. That is the
132
+ * same defect as a diagnostic that reports a number when it means "I could not
133
+ * run" — the tool's inability wearing the costume of a result.
134
+ *
135
+ * `triviaKindLabels` is the worst of the three despite being optional: it fed
136
+ * `triviaKindMask`, which treats `undefined` as "capture everything", so its
137
+ * removal silently changes behaviour rather than producing so much as a crash.
138
+ *
139
+ * So the names are kept as accessors that throw the migration. They are
140
+ * NON-ENUMERABLE deliberately: absent from `Object.keys`, spreads,
141
+ * `JSON.stringify` and identity digests, so restoring them moves no output —
142
+ * they exist only to answer a read.
143
+ *
144
+ * ## They live on a SHARED PROTOTYPE, and that is the whole point
145
+ *
146
+ * "Costs nothing on the parse path" was ASSERTED here and was FALSE. Until
147
+ * 0.47 every `run()` called a `guardRemovedFields(result)` that ran three
148
+ * `Object.defineProperty` calls — three fresh getter closures, three
149
+ * AccessorPairs, three runtime calls — on the result of EVERY parse. Measured
150
+ * through `bench/ab-harness.ts` (both sides in one process, paired and
151
+ * order-alternated, sides rebuilt per pass, control pair measuring the null):
152
+ * removing it made `run()` **-42% on a 7-byte input and -18% on the 52-byte
153
+ * `SMALL_JSON`**, at 12/12 interleaved pairs in every pass against a null of
154
+ * 48-55%. It is a FIXED cost per run, so it vanishes into the noise by
155
+ * `MEDIUM_JSON` — which is exactly why no size-scaled benchmark ever saw it,
156
+ * and exactly why the smallest parses paid the most.
157
+ *
158
+ * The realised-map count was NOT the mechanism, and saying so matters because
159
+ * that was the first guess: `%HaveSameMap` over 2000 parses read **2** maps,
160
+ * not 2000 — V8 shares the accessor transition even though each result got its
161
+ * own closures. The cost was pure per-parse WORK.
162
+ *
163
+ * A prototype pays it once, at module load, and keeps the notice
164
+ * byte-for-byte. Every property the tests pin is preserved: a read still
165
+ * throws the migration `TypeError`, and non-enumerable prototype accessors are
166
+ * invisible to `Object.keys`, spread and `JSON.stringify` for the same reason
167
+ * non-enumerable own ones were. The one difference is that
168
+ * `Object.getOwnPropertyDescriptor(result, 'triviaLog')` is now `undefined`
169
+ * and the descriptor lives on the prototype — nothing reads these names except
170
+ * a stale consumer, and a stale consumer reads them, it does not describe them.
171
+ *
172
+ * The prototype is attached at CREATION — see `RunResultRecord` below for the
173
+ * measured cost of each way of doing that, and for why "attach a prototype" is
174
+ * not one decision but two.
175
+ */
176
+ const SELECT_EXAMPLE = "run(entry, input, { rootTrivia: { select: ['blockComment', 'lineComment'] } })"
177
+
178
+ const REMOVED_RUN_RESULT_FIELDS: ReadonlyArray<readonly [string, string]> = [
179
+ [
180
+ 'triviaMap',
181
+ 'It was a dense root-trivia index built on every parse; root trivia is now an OPT-IN sparse '
182
+ + 'capture, because most grammars paid for an index they never read. Migration: name the trivia '
183
+ + `labels your grammar defines — ${SELECT_EXAMPLE} — and read \`RunResult.rootTrivia\`, whose `
184
+ + '`.index` carries the labels and gap lookups `triviaMap` exposed.',
185
+ ],
186
+ [
187
+ 'triviaLog',
188
+ 'It was the flat `start, end[, kindIndex]` log every other trivia view was derived from, and it '
189
+ + 'is no longer allocated at all — not empty, absent. Migration: request the labels you need '
190
+ + `— ${SELECT_EXAMPLE} — and read \`RunResult.rootTrivia.rows\`. Do NOT reuse a stride-2/3 reader: `
191
+ + 'rows are a different width and a different unit (one row per SELECTED marker, not one per '
192
+ + 'trivia chunk), so an old loop reads confidently wrong offsets rather than failing.',
193
+ ],
194
+ [
195
+ 'triviaKindLabels',
196
+ 'It was already optional, so nothing ever flagged its disappearance — and `triviaKindMask(undefined, '
197
+ + '…)` means "capture everything", so reading it now silently WIDENS capture instead of erroring. '
198
+ + `Migration: request labels — ${SELECT_EXAMPLE} — then the set you asked for is `
199
+ + '`RunResult.rootTrivia.select` and the resolved table is `RunResult.rootTrivia.index.labels`.',
200
+ ],
201
+ ]
202
+
203
+ /**
204
+ * The two shapes a `RunResult` comes in, as constructors.
205
+ *
206
+ * TWO, because `rootTrivia` is ABSENT rather than empty when no requested
207
+ * category was retained and that is the contract — `RunResultWithRootTrivia`
208
+ * is not a wider `RunResultRecord`, it is the other case. Assignment order
209
+ * fixes `Object.keys` order, and plain assignment keeps every field an
210
+ * enumerable own property, so both are indistinguishable from the object
211
+ * literals they replace.
212
+ *
213
+ * CONSTRUCTORS rather than literals carrying `__proto__`, and the difference is
214
+ * not stylistic. Measured at 200k allocations of this exact shape, against a
215
+ * plain literal at 7.28 ms: three per-object `Object.defineProperty` calls
216
+ * (what 0.44-0.46 did) cost **105.27 ms**, a `{ __proto__: PROTO, … }` literal
217
+ * **25.58 ms**, and `new` on a constructor whose `.prototype` carries the
218
+ * accessors **8.72 ms**. `__proto__` in a literal is a runtime prototype set,
219
+ * about 91 ns per result; a constructor bakes the prototype into the initial
220
+ * map and costs about 7 ns. Both readings were confirmed end-to-end through
221
+ * `bench/ab-harness.ts` on `run()` itself.
222
+ */
223
+ class RunResultRecord {
224
+ declare ok: RunResult['ok']
225
+ declare value: RunResult['value']
226
+ declare span: RunResult['span']
227
+ declare expected: RunResult['expected']
228
+ declare errors: RunResult['errors']
229
+ declare unconsumedFrom: RunResult['unconsumedFrom']
230
+
231
+ constructor(
232
+ ok: RunResult['ok'],
233
+ value: RunResult['value'],
234
+ span: RunResult['span'],
235
+ expected: RunResult['expected'],
236
+ errors: RunResult['errors'],
237
+ unconsumedFrom: RunResult['unconsumedFrom'],
238
+ ) {
239
+ this.ok = ok
240
+ this.value = value
241
+ this.span = span
242
+ this.expected = expected
243
+ this.errors = errors
244
+ this.unconsumedFrom = unconsumedFrom
245
+ }
246
+ }
247
+
248
+ class RunResultWithRootTrivia {
249
+ declare ok: RunResult['ok']
250
+ declare value: RunResult['value']
251
+ declare span: RunResult['span']
252
+ declare expected: RunResult['expected']
253
+ declare errors: RunResult['errors']
254
+ declare rootTrivia: RootTriviaCapture
255
+ declare unconsumedFrom: RunResult['unconsumedFrom']
256
+
257
+ constructor(
258
+ ok: RunResult['ok'],
259
+ value: RunResult['value'],
260
+ span: RunResult['span'],
261
+ expected: RunResult['expected'],
262
+ errors: RunResult['errors'],
263
+ rootTrivia: RootTriviaCapture,
264
+ unconsumedFrom: RunResult['unconsumedFrom'],
265
+ ) {
266
+ this.ok = ok
267
+ this.value = value
268
+ this.span = span
269
+ this.expected = expected
270
+ this.errors = errors
271
+ this.rootTrivia = rootTrivia
272
+ this.unconsumedFrom = unconsumedFrom
273
+ }
274
+ }
275
+
276
+ /**
277
+ * Install the removed-field notices ONCE, at module load, on both prototypes.
278
+ *
279
+ * Non-enumerable, as they were as own properties, and for the same reason:
280
+ * invisible to `Object.keys`, spread, `JSON.stringify` and identity digests, so
281
+ * restoring the names moves no output. A read still throws the migration.
282
+ */
283
+ for (const proto of [RunResultRecord.prototype, RunResultWithRootTrivia.prototype]) {
284
+ for (const [name, detail] of REMOVED_RUN_RESULT_FIELDS) {
285
+ Object.defineProperty(proto, name, {
286
+ configurable: true,
287
+ enumerable: false,
288
+ get(): never {
289
+ throw new TypeError(
290
+ `RunResult.${name} was REMOVED in parseman 0.44.0 and has no default replacement. ${detail}`,
291
+ )
292
+ },
293
+ })
294
+ }
295
+ }
296
+
297
+ const invoke = (r: Runnable, input: string, pos: number, ctx: ParseContext): ParseResult<unknown> =>
298
+ typeof r === 'function' ? r(input, pos, ctx) : r.parse(input, pos, ctx)
299
+
300
+ type RunnableMeta = {
301
+ readonly _meta?: {
302
+ readonly triviaKindLabels?: readonly string[]
303
+ readonly rootTriviaClassified?: true
304
+ readonly grammarTrivia?: Runnable
305
+ }
306
+ }
307
+
308
+ /**
309
+ * THE DOCUMENT ROOT OWNS ITS TRAILING TRIVIA, and it is `run()` that decides
310
+ * which rule the document root is.
311
+ *
312
+ * `node({ trailingTrivia })` says the same thing per NODE, and its failure mode
313
+ * is a silent success: of jess's four shipping grammars two set it on
314
+ * `Stylesheet` and two did not, so a comment-only `.jess` document matched
315
+ * ZERO-WIDTH at the root and reported `ok: true` with `unconsumedFrom: 0` — 0 of
316
+ * 124 bytes consumed, no error, every gate green. 1626 of 2409 sass-spec inputs
317
+ * stopped exactly one byte short of the file for the same reason. An option
318
+ * every grammar author must remember, whose cost of forgetting is a parse that
319
+ * claims to have succeeded, is not an option.
320
+ *
321
+ * WHY THIS CANNOT BE A DEFAULT ON `node()`. A block bounded by a closing
322
+ * delimiter must NOT swallow the gap after its closer — that gap belongs to the
323
+ * parent, and handing it to the child mis-attributes trivia in the CST. That is
324
+ * a different silent defect, not a fix. Only the document root has no parent to
325
+ * take it.
326
+ *
327
+ * WHY IT CANNOT BE STAMPED BY `rules()` / `parser()` EITHER, which is the
328
+ * question this defect really turns on. A `rules()` map has many rules and ANY
329
+ * of them can be an entry; `compose()`/`linkable()` pieces bring their own. A
330
+ * rule is not a root — a rule is a root OF A PARSE. `Stylesheet` is the document
331
+ * root when you hand it to `run()`, and an ordinary interior rule when some
332
+ * other rule references it, and BOTH can be true of the same combinator object
333
+ * in the same process. Nothing at grammar-construction time can distinguish
334
+ * those two uses, which is exactly why this was made an opt-in in the first
335
+ * place. `run()` is the one place that knows: it is handed the entry.
336
+ *
337
+ * So there is no stamp and no per-rule flag. A referenced rule runs inside its
338
+ * referencing rule's body, `run()` never sees it, and the enclosing rule keeps
339
+ * ownership of the gap that follows it — unchanged, in every engine.
340
+ *
341
+ * THE THREE PLACES the ambient trivia can live are the same three
342
+ * `triviaKindLabelsFromRunnable` already reads, for the same reason: `rules({
343
+ * trivia }, …)` leaves it on `_meta.grammarTrivia`, `parser({ trivia }, …)`
344
+ * leaves it on `_def.triviaParser`, and a table/compiled entry is a FUNCTION
345
+ * that carries neither, so its rule map stamps `_meta.grammarTrivia` itself
346
+ * (`src/table/stamp.ts`). Reading fewer than three is how one engine's entry
347
+ * silently keeps the old behaviour while the others move.
348
+ */
349
+ function ambientTriviaFromRunnable(r: Runnable | undefined): Runnable | undefined {
350
+ if (!r) return undefined
351
+ if (typeof r === 'function') return (r as RunnableMeta)._meta?.grammarTrivia
352
+ // A trivia rule handed in as the entry parses trivia; it has no tail of its own.
353
+ if (r._meta.isTrivia) return undefined
354
+ return (r._meta as { grammarTrivia?: Combinator<unknown> }).grammarTrivia
355
+ ?? (r._def.tag === 'grammar' ? r._def.triviaParser : undefined)
356
+ }
357
+
358
+ function triviaKindLabelsFromRunnable(r: Runnable | undefined): readonly string[] | undefined {
359
+ if (!r) return undefined
360
+ if (typeof r === 'function') return (r as RunnableMeta)._meta?.triviaKindLabels
361
+ const grammarTrivia = (r._meta as { grammarTrivia?: Combinator<unknown> }).grammarTrivia
362
+ return grammarTrivia?._meta.triviaKindLabels
363
+ ?? r._meta.triviaKindLabels
364
+ ?? (r._def.tag === 'grammar' ? r._def.triviaParser?._meta.triviaKindLabels : undefined)
365
+ }
366
+
367
+ function rootTriviaClassifiedFromRunnable(r: Runnable | undefined): boolean {
368
+ if (!r) return false
369
+ if (typeof r === 'function') return (r as RunnableMeta)._meta?.rootTriviaClassified === true
370
+ const grammarTrivia = (r._meta as { grammarTrivia?: Combinator<unknown> }).grammarTrivia
371
+ return grammarTrivia?._meta.rootTriviaClassified === true || r._meta.rootTriviaClassified === true
372
+ }
373
+
374
+ function makeSelectedRootLabelIndex(labels: readonly string[]): Readonly<Record<string, number>> {
375
+ const index: Record<string, number> = Object.create(null) as Record<string, number>
376
+ for (let i = 0; i < labels.length; i++) {
377
+ if (index[labels[i]!] === undefined) index[labels[i]!] = i
378
+ }
379
+ return index
380
+ }
381
+
382
+ /**
383
+ * Extend a result span's END over the document's trailing trivia.
384
+ *
385
+ * A NEW object, never a mutation: the entry's span may be the very object a node
386
+ * already published to the tree, and growing that in place would move a node's
387
+ * span as a side effect of asking the driver a document-level question.
388
+ *
389
+ * When the run tracked lines, `endLine`/`endColumn` are re-derived rather than
390
+ * carried over. Leaving them describing the OLD end while `end` names the new
391
+ * one reports a position that is off by however much trivia the file ends with —
392
+ * the same class of quietly-wrong answer this whole change exists to remove. The
393
+ * scan is over the trailing trivia only, and only when the fields are present,
394
+ * so a run without line tracking does no work at all.
395
+ */
396
+ function growSpanEnd(span: Span, input: string, end: number): Span {
397
+ if (span.endLine === undefined || span.endColumn === undefined) {
398
+ return { start: span.start, end }
399
+ }
400
+ let line = span.endLine
401
+ let column = span.endColumn
402
+ for (let i = span.end; i < end; i++) {
403
+ if (input.charCodeAt(i) === 10) { line++; column = 1 } else { column++ }
404
+ }
405
+ return { ...span, end, endLine: line, endColumn: column }
406
+ }
407
+
408
+ /** Keep the run-entry closure independent from grammar-construction helpers. */
409
+ function runOnce(entry: Runnable, input: string, options: RunOptions): RunResult {
410
+ if (typeof entry !== 'function' && typeof (entry as Combinator<unknown> | undefined)?.parse !== 'function') {
411
+ throw new TypeError(
412
+ `run(): start production is ${entry === null ? 'null' : typeof entry}, not a rule — the requested grammar rule does not exist (check the rule name).`,
413
+ )
414
+ }
415
+ const rootTriviaSelection = options.rootTrivia?.select
416
+ const captureRootTrivia = rootTriviaSelection !== undefined && rootTriviaSelection.length > 0
417
+ const selectedRootLog = captureRootTrivia ? [] as number[] : undefined
418
+ const selectedRootLabelIndex = captureRootTrivia
419
+ ? makeSelectedRootLabelIndex(rootTriviaSelection)
420
+ : undefined
421
+ const errors: ParseError[] = []
422
+ // Grammar-level ambient trivia declared via rules({ trivia }, factory): install
423
+ // it as ctx.trivia so it's ambient for the whole parse (the interpreter path;
424
+ // a compiled entry has it baked in and carries no _meta). parser/noTrivia still
425
+ // override locally.
426
+ const grammarTrivia = typeof entry !== 'function' ? entry._meta.grammarTrivia : undefined
427
+ const grammarScanSkip = typeof entry !== 'function' ? entry._meta.grammarScanSkip : undefined
428
+ const triviaKindLabels = triviaKindLabelsFromRunnable(entry) ?? triviaKindLabelsFromRunnable(options.trivia)
429
+ if (captureRootTrivia && triviaKindLabels === undefined) {
430
+ throw new TypeError('run(): rootTrivia.select requires labeled grammar trivia.')
431
+ }
432
+ if (captureRootTrivia) {
433
+ for (const label of rootTriviaSelection) {
434
+ if (!triviaKindLabels!.includes(label)) {
435
+ throw new TypeError(`run(): rootTrivia.select contains unknown trivia label ${JSON.stringify(label)}.`)
436
+ }
437
+ }
438
+ }
439
+ if (captureRootTrivia
440
+ && !rootTriviaClassifiedFromRunnable(entry)
441
+ && !rootTriviaClassifiedFromRunnable(options.trivia)) {
442
+ throw new TypeError(
443
+ 'run(): rootTrivia.select requires classifiedTrivia() at the root.',
444
+ )
445
+ }
446
+ /*
447
+ * Refuse an artifact/host mismatch ONCE per parse, exactly as `parseDoc` and a
448
+ * compiled parser's `parseWithContext` already do. `run()` is handed a RULE, not the
449
+ * registry, so the fused rule functions carry the stamp themselves (see `fusedBody`);
450
+ * an interpreter entry carries it on `_meta`. Neither is on a hot path — this runs
451
+ * once, before `invoke`.
452
+ *
453
+ * Without this, `run()` was the one driver that could silently produce the wrong tree
454
+ * shape: an 'ast' artifact driven with a positioned-CST host returns its own AST
455
+ * objects where the caller asked for a CST, and a CST child filter then drops them
456
+ * and the node simply vanishes.
457
+ *
458
+ * The INTERPRETER passes `elided: false` unconditionally, and that is not a shortcut:
459
+ * it has no compile step, re-decides the host route per parse, and so has never
460
+ * dropped a branch. Only its `'cst'`-without-a-host half can be wrong.
461
+ */
462
+ const stamped = entry as Partial<Record<symbol, unknown>>
463
+ assertHostModeCompatible(
464
+ typeof entry === 'function'
465
+ ? ((stamped[FUSED_HOST_MODE] as HostMode | undefined) ?? 'ast')
466
+ : (entry._meta.grammarHostMode ?? 'ast'),
467
+ options.build,
468
+ typeof entry === 'function' && stamped[FUSED_HOST_ELIDED] === true,
469
+ )
470
+ // ONE shape, every configuration. These were six conditional spreads; see
471
+ // `createParseContext` for why that is a hidden-class hazard on the object
472
+ // every combinator reads. Assignments below are in-object stores to slots that
473
+ // already exist, so none of them transitions the map.
474
+ const ctx = createParseContext()
475
+ if (captureRootTrivia) {
476
+ ctx._rootTriviaLog = selectedRootLog!
477
+ ctx._rootTriviaKindIndex = selectedRootLabelIndex!
478
+ ctx._rootTriviaStrictScopes = true
479
+ }
480
+ ctx._errors = errors
481
+ ctx.build = options.build
482
+ ctx.state = options.state
483
+ if (grammarTrivia !== undefined) ctx.trivia = grammarTrivia
484
+ if (triviaKindLabels) ctx.triviaKindLabels = triviaKindLabels
485
+ if (grammarScanSkip !== undefined) ctx.scanSkip = grammarScanSkip
486
+ if (options.triviaCaptureMask !== undefined) ctx._triviaCaptureMask = options.triviaCaptureMask
487
+ if (options.tolerant) {
488
+ ctx._tolerant = true
489
+ ctx._rec = REC
490
+ }
491
+ if (options.instrumentation !== undefined) {
492
+ ctx._grammarCoverage = options.instrumentation._grammarCoverage
493
+ ctx._grammarTrace = options.instrumentation._grammarTrace
494
+ }
495
+ const r = invoke(entry, input, 0, ctx)
496
+
497
+ const value = r.ok ? (r as { value: unknown }).value : undefined
498
+ let span = r.span ?? { start: 0, end: 0 }
499
+ const expected = r.ok ? [] : ((r as { expected?: string[] }).expected ?? [])
500
+
501
+ let unconsumedFrom: number | null = null
502
+ if (r.ok) {
503
+ let pos = span.end
504
+ // The root's trailing trivia — see `ambientTriviaFromRunnable`. `options.trivia`
505
+ // wins because it is an explicit request to measure the tail with a DIFFERENT
506
+ // trivia than the grammar parses with.
507
+ const tail = options.trivia ?? ambientTriviaFromRunnable(entry)
508
+ if (tail !== undefined && pos < input.length) {
509
+ // Throwaway ctx: trailing trivia must NOT pollute the parse's trivia log.
510
+ // This is a POSITION question, and the root's per-node trivia log is the
511
+ // separate, node-scoped answer that `node({ trailingTrivia })` gives.
512
+ const t = invoke(tail, input, pos, createParseContext())
513
+ if (t.ok && t.span.end > pos) {
514
+ span = growSpanEnd(span, input, t.span.end)
515
+ pos = t.span.end
516
+ }
517
+ }
518
+ unconsumedFrom = pos < input.length ? pos : null
519
+ }
520
+
521
+ // `rootTrivia` is ABSENT rather than empty when no requested category was
522
+ // retained, so branch on it — do not index into it. The branch is spelled as
523
+ // two constructors rather than one literal with a
524
+ // `...(cond ? { rootTrivia } : {})` spread: the two arms produce exactly the
525
+ // two shapes the contract calls for, which is what the spread was silently
526
+ // doing anyway, and a conditional spread is the shape hazard this repo has
527
+ // an incident over.
528
+ return selectedRootLog !== undefined && selectedRootLog.length > 0
529
+ ? new RunResultWithRootTrivia(
530
+ r.ok,
531
+ value,
532
+ span,
533
+ expected,
534
+ errors,
535
+ {
536
+ rows: selectedRootLog,
537
+ select: rootTriviaSelection!,
538
+ index: buildRootTriviaIndex(selectedRootLog, rootTriviaSelection!),
539
+ },
540
+ unconsumedFrom,
541
+ )
542
+ : new RunResultRecord(r.ok, value, span, expected, errors, unconsumedFrom)
543
+ }
544
+
545
+ /* `RunOptions.profile` — the three-pass profiling boundary (recognizer /
546
+ * structuralCapture / hostConstruction) — is GONE, along with `RunResult.profile`,
547
+ * `RunProfile`, `RunProfilePass`, the `ProfilePhase`/`ProfileState` plumbing and
548
+ * `ParseContext._pmProfile`. The counters it read stopped being emitted into
549
+ * compiled artifacts in 9751cce (profiling is interpreted-mode only: the gates cost
550
+ * a `_ctx._pmProfile` read plus ~15 threaded ternaries on EVERY node), the
551
+ * interpreter never implemented them, and so the option only ever threw. A
552
+ * well-typed call into an unconditional throw is worse than no option at all.
553
+ * What a restoration would take is recorded in
554
+ * `docs/future/bench-typecheck-followups.md`. */
555
+
556
+ export function run(entry: Runnable, input: string, options: RunOptions = {}): RunResult {
557
+ return runOnce(entry, input, options)
558
+ }
@@ -0,0 +1,2 @@
1
+ /** Import-free keys shared by grammar construction and public metadata readers. */
2
+ export const GRAMMAR_COVERAGE_DEFINITIONS: symbol = Symbol.for('parseman.grammarCoverageDefinitions')