parseman 0.56.0 → 0.58.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 (106) hide show
  1. package/dist/analysis/diagnostics.js +2232 -1088
  2. package/dist/analysis/diagnostics.js.map +3 -3
  3. package/dist/cli/index.js +2247 -1103
  4. package/dist/cli/index.js.map +3 -3
  5. package/dist/combinators/dispatch.d.ts.map +1 -1
  6. package/dist/combinators/node.d.ts +1 -1
  7. package/dist/compiler/build-arity.d.ts +1 -1
  8. package/dist/compiler/build-arity.d.ts.map +1 -1
  9. package/dist/compiler/token-alphabet.d.ts +11 -1
  10. package/dist/compiler/token-alphabet.d.ts.map +1 -1
  11. package/dist/compiler/token-capability.js +69 -16
  12. package/dist/compiler/token-capability.js.map +2 -2
  13. package/dist/cst/capture-buffer.d.ts +6 -0
  14. package/dist/cst/capture-buffer.d.ts.map +1 -1
  15. package/dist/cst/trivia-kinds.d.ts +9 -1
  16. package/dist/cst/trivia-kinds.d.ts.map +1 -1
  17. package/dist/index.js +1446 -236
  18. package/dist/index.js.map +3 -3
  19. package/dist/language-service/index.js +1 -0
  20. package/dist/language-service/index.js.map +1 -1
  21. package/dist/parse-context.d.ts.map +1 -1
  22. package/dist/plugin/entry-supercompiler.d.ts +1 -1
  23. package/dist/plugin/entry-supercompiler.d.ts.map +1 -1
  24. package/dist/plugin/index.d.ts +51 -1
  25. package/dist/plugin/index.d.ts.map +1 -1
  26. package/dist/plugin/index.js +2126 -380
  27. package/dist/plugin/index.js.map +3 -3
  28. package/dist/plugin/ir-eval.d.ts +2 -0
  29. package/dist/plugin/ir-eval.d.ts.map +1 -1
  30. package/dist/regex/classes.d.ts.map +1 -1
  31. package/dist/run/index.js +1 -0
  32. package/dist/run/index.js.map +1 -1
  33. package/dist/table/assemble.d.ts +9 -0
  34. package/dist/table/assemble.d.ts.map +1 -1
  35. package/dist/table/child-slots.d.ts +4 -6
  36. package/dist/table/child-slots.d.ts.map +1 -1
  37. package/dist/table/compile-rule-map.d.ts +14 -2
  38. package/dist/table/compile-rule-map.d.ts.map +1 -1
  39. package/dist/table/emit-assembly.d.ts +17 -2
  40. package/dist/table/emit-assembly.d.ts.map +1 -1
  41. package/dist/table/emit.d.ts +5 -1
  42. package/dist/table/emit.d.ts.map +1 -1
  43. package/dist/table/encode.d.ts.map +1 -1
  44. package/dist/table/exec-baseline.d.ts.map +1 -1
  45. package/dist/table/exec.d.ts.map +1 -1
  46. package/dist/table/factor-choice.d.ts +42 -0
  47. package/dist/table/factor-choice.d.ts.map +1 -0
  48. package/dist/table/fail-clean.d.ts +3 -0
  49. package/dist/table/fail-clean.d.ts.map +1 -0
  50. package/dist/table/hold-gap.d.ts +8 -0
  51. package/dist/table/hold-gap.d.ts.map +1 -0
  52. package/dist/table/index.js +1798 -316
  53. package/dist/table/index.js.map +3 -3
  54. package/dist/table/lex-program.d.ts +7 -3
  55. package/dist/table/lex-program.d.ts.map +1 -1
  56. package/dist/table/ops.d.ts +17 -6
  57. package/dist/table/ops.d.ts.map +1 -1
  58. package/dist/table/program.d.ts +13 -0
  59. package/dist/table/program.d.ts.map +1 -1
  60. package/dist/table/run-support.d.ts +19 -0
  61. package/dist/table/run-support.d.ts.map +1 -1
  62. package/dist/table/scalar-terminal.d.ts +2 -0
  63. package/dist/table/scalar-terminal.d.ts.map +1 -1
  64. package/dist/table/select-hot.d.ts +6 -0
  65. package/dist/table/select-hot.d.ts.map +1 -0
  66. package/dist/table/site-labels.d.ts +66 -0
  67. package/dist/table/site-labels.d.ts.map +1 -1
  68. package/dist/table/trivia-gap.d.ts +31 -0
  69. package/dist/table/trivia-gap.d.ts.map +1 -0
  70. package/dist/types.d.ts +17 -0
  71. package/dist/types.d.ts.map +1 -1
  72. package/dist/version.d.ts +1 -1
  73. package/package.json +4 -1
  74. package/src/combinators/dispatch.ts +12 -3
  75. package/src/combinators/node.ts +6 -13
  76. package/src/combinators/trivia-skip.ts +44 -1
  77. package/src/compiler/build-arity.ts +3 -3
  78. package/src/compiler/token-alphabet.ts +57 -17
  79. package/src/cst/capture-buffer.ts +25 -0
  80. package/src/cst/trivia-kinds.ts +12 -1
  81. package/src/parse-context.ts +1 -0
  82. package/src/plugin/entry-supercompiler.ts +8 -9
  83. package/src/plugin/index.ts +362 -42
  84. package/src/plugin/ir-eval.ts +7 -1
  85. package/src/regex/classes.ts +3 -0
  86. package/src/table/assemble.ts +371 -83
  87. package/src/table/child-slots.ts +6 -8
  88. package/src/table/compile-rule-map.ts +64 -15
  89. package/src/table/emit-assembly.ts +244 -42
  90. package/src/table/emit.ts +11 -8
  91. package/src/table/encode.ts +149 -35
  92. package/src/table/exec-baseline.ts +1 -3
  93. package/src/table/exec.ts +34 -14
  94. package/src/table/factor-choice.ts +173 -0
  95. package/src/table/fail-clean.ts +130 -0
  96. package/src/table/hold-gap.ts +68 -0
  97. package/src/table/lex-program.ts +197 -43
  98. package/src/table/ops.ts +18 -7
  99. package/src/table/program.ts +24 -0
  100. package/src/table/run-support.ts +35 -0
  101. package/src/table/scalar-terminal.ts +8 -0
  102. package/src/table/select-hot.ts +70 -0
  103. package/src/table/site-labels.ts +135 -4
  104. package/src/table/trivia-gap.ts +109 -0
  105. package/src/types.ts +18 -0
  106. package/src/version.ts +1 -1
@@ -329,6 +329,7 @@ function createParseContext() {
329
329
  _rootTriviaKindIndex: void 0,
330
330
  _rootTriviaStrictScopes: void 0,
331
331
  _rootTriviaCapture: void 0,
332
+ _gap: void 0,
332
333
  _cstTriviaLog: void 0,
333
334
  _fields: void 0,
334
335
  _cstBuf: void 0,
@@ -348,6 +349,9 @@ function createDetachedParseContext(trackLines, state) {
348
349
  }
349
350
 
350
351
  // src/line-index.ts
352
+ function createLineIndex() {
353
+ return { lineStarts: [0] };
354
+ }
351
355
  function recordLineRange(index, input, start, end) {
352
356
  const lineStarts = index.lineStarts;
353
357
  for (let i = start; i < end; i++) {
@@ -363,6 +367,18 @@ function recordLineRangeFromContext(ctx, input, _startHint, end) {
363
367
  recordLineRange(index, input, from, end);
364
368
  ctx._lineScannedTo = end;
365
369
  }
370
+ function normalizeLineIndex(index) {
371
+ const starts = index.lineStarts;
372
+ starts.sort((a, b) => a - b);
373
+ let write = 0;
374
+ for (let read = 0; read < starts.length; read++) {
375
+ const value = starts[read];
376
+ if (write === 0 || starts[write - 1] !== value) starts[write++] = value;
377
+ }
378
+ starts.length = write;
379
+ if (starts.length === 0 || starts[0] !== 0) starts.unshift(0);
380
+ return index;
381
+ }
366
382
  function offsetToLineCol(index, offset) {
367
383
  const { lineStarts } = index;
368
384
  let lo = 0;
@@ -592,12 +608,12 @@ function rebuildLineScan(s, subtree) {
592
608
  function cstCaptureActive(ctx) {
593
609
  return ctx._cstBuf !== void 0 || ctx._cstLeaves !== void 0;
594
610
  }
595
- function pushCstLeaf(ctx, leaf) {
611
+ function pushCstLeaf(ctx, leaf2) {
596
612
  if (!ctx.trackLines) {
597
- pushCstChild(ctx, leaf, leaf);
613
+ pushCstChild(ctx, leaf2, leaf2);
598
614
  return;
599
615
  }
600
- const annotated = leaf && typeof leaf === "object" && leaf.span ? { ...leaf, span: annotateSpanFromLineContext(leaf.span, ctx) } : leaf;
616
+ const annotated = leaf2 && typeof leaf2 === "object" && leaf2.span ? { ...leaf2, span: annotateSpanFromLineContext(leaf2.span, ctx) } : leaf2;
601
617
  pushCstChild(ctx, annotated, annotated);
602
618
  }
603
619
  function pushCstChild(ctx, built, rawEntry2) {
@@ -622,6 +638,31 @@ function pushCstChild(ctx, built, rawEntry2) {
622
638
  else if (ctx._cstLeaves) ctx._cstLeaves.push(built);
623
639
  if (ctx._cstRawChildren) ctx._cstRawChildren.push(rawEntry2);
624
640
  }
641
+ function popCstChild(ctx) {
642
+ const b = ctx._cstBuf;
643
+ if (b) {
644
+ const ch2 = b.ch;
645
+ if (b.rawOnly !== true && ch2) {
646
+ ch2.pop();
647
+ if (ch2.length === 1) {
648
+ b.single = ch2[0];
649
+ b.ch = void 0;
650
+ }
651
+ }
652
+ if (b.noRaw === true) b.rawLen = (b.rawLen ?? 1) - 1;
653
+ else if (b.raw) {
654
+ b.raw.pop();
655
+ if (b.raw.length === 1) {
656
+ b.rawSingle = b.raw[0];
657
+ b.raw = void 0;
658
+ }
659
+ } else b.rawSingle = void 0;
660
+ return;
661
+ }
662
+ if (ctx._cstChildren) ctx._cstChildren.pop();
663
+ else if (ctx._cstLeaves) ctx._cstLeaves.pop();
664
+ if (ctx._cstRawChildren) ctx._cstRawChildren.pop();
665
+ }
625
666
  function cstRawLen(ctx) {
626
667
  const b = ctx._cstBuf;
627
668
  if (b) {
@@ -780,6 +821,7 @@ function literalCodePoints(frag) {
780
821
  if (ch2 === "\\") {
781
822
  const e = frag[i + 1];
782
823
  if (e === void 0) return null;
824
+ if (!(e in CLASS_ESCAPES) && /\w/.test(e)) return null;
783
825
  out.push(e in CLASS_ESCAPES ? CLASS_ESCAPES[e] : e.codePointAt(0));
784
826
  i += 2;
785
827
  continue;
@@ -1326,7 +1368,10 @@ function labeledTriviaSpec(arms, minRepeats) {
1326
1368
  arms,
1327
1369
  minRepeats,
1328
1370
  visitor: commonLabeledTriviaVisitor({ arms, minRepeats }),
1329
- charArms: charArmsFor({ arms, minRepeats })
1371
+ charArms: charArmsFor({ arms, minRepeats }),
1372
+ rootKinds: void 0,
1373
+ rootLeaders: [],
1374
+ rootScan: null
1330
1375
  };
1331
1376
  }
1332
1377
  function matchArmAt(input, pos, arm, state) {
@@ -1463,6 +1508,15 @@ function triviaKindMaskAt(input, pos, spec, state) {
1463
1508
  }
1464
1509
  return mask;
1465
1510
  }
1511
+ function triviaKindMask(labels, keep) {
1512
+ if (!labels) return void 0;
1513
+ let mask = 0;
1514
+ for (const name of keep) {
1515
+ const idx = labels.indexOf(name);
1516
+ if (idx >= 0) mask |= 1 << idx;
1517
+ }
1518
+ return mask;
1519
+ }
1466
1520
 
1467
1521
  // src/recovery/scan.ts
1468
1522
  function probeAt(sentinel, input, pos, ctx) {
@@ -1964,8 +2018,8 @@ function buildFastTriviaScanner(trivia2) {
1964
2018
  if (arms.some((s) => s === null)) return null;
1965
2019
  return loopScanner(arms);
1966
2020
  }
1967
- function triviaRegexSource(parser) {
1968
- const d = parser._def.tag === "label" ? parser._def.parser._def : parser._def;
2021
+ function triviaRegexSource(parser2) {
2022
+ const d = parser2._def.tag === "label" ? parser2._def.parser._def : parser2._def;
1969
2023
  return d.tag === "regex" && d.flags === "" ? d.source : null;
1970
2024
  }
1971
2025
  function loopScanner(arms) {
@@ -1984,11 +2038,53 @@ function loopScanner(arms) {
1984
2038
  return pos;
1985
2039
  };
1986
2040
  }
1987
- function regexTriviaScanner(parser) {
1988
- const d = parser._def.tag === "label" ? parser._def.parser._def : parser._def;
2041
+ function regexTriviaScanner(parser2) {
2042
+ const d = parser2._def.tag === "label" ? parser2._def.parser._def : parser2._def;
1989
2043
  if (d.tag !== "regex" || d.flags) return null;
1990
- const source = d.source;
1991
- return classRunSource(source) ?? altStarSource(source) ?? prefixRunSource(source) ?? delimitedSource(source);
2044
+ return sourceScanner(d.source);
2045
+ }
2046
+ function sourceScanner(source) {
2047
+ return classRunSource(source) ?? altStarSource(source) ?? prefixRunSource(source) ?? delimitedSource(source) ?? sharedPrefixAltSource(source);
2048
+ }
2049
+ function sharedPrefixAltSource(source) {
2050
+ const m = /^((?:\\.|[^\\[\]()*+?|^$.{}])+)\(\?:(.*)\)$/.exec(source);
2051
+ if (!m) return null;
2052
+ const alts = [];
2053
+ const body = m[2];
2054
+ let depth = 0;
2055
+ let start = 0;
2056
+ for (let i = 0; i < body.length; i++) {
2057
+ const c = body[i];
2058
+ if (c === "\\") {
2059
+ i++;
2060
+ continue;
2061
+ }
2062
+ if (c === "[") {
2063
+ while (i < body.length && body[i] !== "]") i += body[i] === "\\" ? 2 : 1;
2064
+ continue;
2065
+ }
2066
+ if (c === "(") depth++;
2067
+ else if (c === ")" && --depth < 0) return null;
2068
+ else if (c === "|" && depth === 0) {
2069
+ alts.push(body.slice(start, i));
2070
+ start = i + 1;
2071
+ }
2072
+ }
2073
+ if (depth !== 0 || alts.length === 0) return null;
2074
+ alts.push(body.slice(start));
2075
+ const scanners = [];
2076
+ for (const alt of alts) {
2077
+ const scanner = sourceScanner(m[1] + alt);
2078
+ if (scanner === null) return null;
2079
+ scanners.push(scanner);
2080
+ }
2081
+ return (input, cur) => {
2082
+ for (const scanner of scanners) {
2083
+ const end = scanner(input, cur);
2084
+ if (end > cur) return end;
2085
+ }
2086
+ return cur;
2087
+ };
1992
2088
  }
1993
2089
  function bmpString(cps) {
1994
2090
  if (!cps) return null;
@@ -2251,9 +2347,26 @@ function altStarSource(source) {
2251
2347
  }
2252
2348
 
2253
2349
  // src/combinators/scalar.ts
2350
+ var SCALAR_TAG = /^(?:literal|regex|keywords|sequence|choice|many|oneOrMore|optional|transform|trivia|grammar|sepBy|lazy)$/;
2254
2351
  function scalarOf(combinator) {
2255
2352
  return combinator._parseScalar;
2256
2353
  }
2354
+ function scalarTree(parser2, seen) {
2355
+ if (seen.has(parser2)) return true;
2356
+ if (parser2._parseScalar === void 0) return false;
2357
+ seen.add(parser2);
2358
+ const def = parser2._def;
2359
+ if (!SCALAR_TAG.test(def.tag)) return false;
2360
+ if ("parsers" in def && !def.parsers.every((child) => scalarTree(child, seen))) return false;
2361
+ if ("parser" in def && !scalarTree(def.parser, seen)) return false;
2362
+ if ("separator" in def && !scalarTree(def.separator, seen)) return false;
2363
+ return def.tag !== "lazy" || scalarTree(def.thunk(), seen);
2364
+ }
2365
+ function scalarRootOf(combinator) {
2366
+ const scalar = combinator._parseScalar;
2367
+ const def = combinator._def;
2368
+ return scalar !== void 0 && def.tag === "grammar" && scalarTree(def.parser, /* @__PURE__ */ new Set()) ? scalar : void 0;
2369
+ }
2257
2370
 
2258
2371
  // src/combinators/choice.ts
2259
2372
  function choice(...args) {
@@ -2401,7 +2514,7 @@ function choice(...args) {
2401
2514
  return result;
2402
2515
  }
2403
2516
  if (expected.length === 0) {
2404
- for (const parser of parsers) expected.push(...deriveExpected(parser));
2517
+ for (const parser2 of parsers) expected.push(...deriveExpected(parser2));
2405
2518
  }
2406
2519
  return { ok: false, expected, span: { start: pos, end: pos } };
2407
2520
  }
@@ -3292,17 +3405,59 @@ function buildLexBodyRecognizer(spec, constants) {
3292
3405
  };
3293
3406
  }
3294
3407
 
3408
+ // src/table/run-support.ts
3409
+ function lineCol(ctx, offset) {
3410
+ const starts = ctx._lineStarts ?? [0];
3411
+ let lo = 0, hi = starts.length - 1;
3412
+ while (lo < hi) {
3413
+ const mid = lo + hi + 1 >> 1;
3414
+ if (starts[mid] <= offset) lo = mid;
3415
+ else hi = mid - 1;
3416
+ }
3417
+ return [lo + 1, offset - starts[lo] + 1];
3418
+ }
3419
+ function spanLines(ctx, start, end) {
3420
+ const s = lineCol(ctx, start), e = lineCol(ctx, end);
3421
+ return { start, end, startLine: s[0], startColumn: s[1], endLine: e[0], endColumn: e[1] };
3422
+ }
3423
+ function rawEntry(v, input, s, e) {
3424
+ if (typeof v === "object" && v !== null) {
3425
+ const tg = v._tag;
3426
+ if (tg === "node" || tg === "leaf" || tg === "parseError") return v;
3427
+ }
3428
+ return {
3429
+ _tag: "leaf",
3430
+ value: typeof v === "string" ? v : typeof v === "object" && v !== null ? input.slice(s, e) : "",
3431
+ span: { start: s, end: e }
3432
+ };
3433
+ }
3434
+ function lead(input, pos) {
3435
+ if (pos >= input.length) return -1;
3436
+ const c = input.charCodeAt(pos);
3437
+ if (c < 55296 || c > 56319) return c;
3438
+ return input.codePointAt(pos) ?? c;
3439
+ }
3440
+ var EMPTY_KIDS = Object.freeze([]);
3441
+ var EMPTY_TRIVIA = Object.freeze([]);
3442
+ function collapseEmpty(ctx, build, input, pos, end, readsRaw) {
3443
+ const collected = ctx._cstBuf !== void 0 || ctx._cstChildren !== void 0;
3444
+ if (collected) popCstChild(ctx);
3445
+ const raw = readsRaw ? [rawEntry(void 0, input, pos, end)] : EMPTY_KIDS;
3446
+ const nd = build(EMPTY_KIDS, void 0, { start: pos, end }, raw, EMPTY_TRIVIA, void 0);
3447
+ if (collected) pushCstChild(ctx, nd, ctx._cstBuf?.noRaw === true ? void 0 : rawEntry(nd, input, pos, end));
3448
+ return nd;
3449
+ }
3450
+
3295
3451
  // src/table/lex-program.ts
3296
3452
  var LEX_NODE_TERMINAL = 0;
3297
3453
  var LEX_NODE_SEQUENCE2 = 1;
3298
3454
  var LEX_NODE_SEQUENCE3 = 2;
3299
3455
  var LEX_NODE_SEQUENCE4 = 3;
3300
3456
  var LEX_NODE_SEQUENCE5 = 4;
3301
- var LEX_NODE_CHOICE2 = 5;
3302
- var LEX_NODE_CHOICE4 = 6;
3303
- var LEX_NODE_CHOICE8 = 7;
3457
+ var LEX_NODE_CHOICE = 5;
3304
3458
  var LEX_NODE_NOT = 8;
3305
3459
  var LEX_NODE_OPTIONAL = 9;
3460
+ var LEX_NODE_REPEAT = 10;
3306
3461
  function lexProgramDigest(words) {
3307
3462
  let hash = 2166136261;
3308
3463
  for (const word of words) {
@@ -3331,85 +3486,114 @@ function trackLexLines(ctx, input, end) {
3331
3486
  ctx._lineScannedTo = end;
3332
3487
  }
3333
3488
  function terminalNode(matcher, failure, tracksLines) {
3334
- const match = (input, pos) => {
3335
- const result = matcher(input, pos);
3336
- return result < 0 ? -1 : result / 2;
3337
- };
3338
3489
  return {
3339
- match,
3490
+ match: (input, pos) => {
3491
+ const result = matcher(input, pos);
3492
+ return result < 0 ? -1 : result / 2;
3493
+ },
3340
3494
  run: (input, pos, ctx) => {
3341
- const end = match(input, pos);
3342
- if (end < 0) {
3495
+ const result = matcher(input, pos);
3496
+ if (result < 0) {
3343
3497
  ctx._fe = pos;
3344
3498
  ctx._fx = failure;
3345
3499
  if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
3346
3500
  return -1;
3347
3501
  }
3502
+ const end = result / 2;
3348
3503
  if (tracksLines) trackLexLines(ctx, input, end);
3349
3504
  return end;
3350
3505
  }
3351
3506
  };
3352
3507
  }
3353
3508
  function sequence2(a, b) {
3509
+ const am = a.match, bm = b.match, ar = a.run, br = b.run;
3354
3510
  return {
3355
3511
  match: (input, pos) => {
3356
- const e0 = a.match(input, pos);
3357
- return e0 < 0 ? -1 : b.match(input, e0);
3512
+ const e0 = am(input, pos);
3513
+ return e0 < 0 ? -1 : bm(input, e0);
3358
3514
  },
3359
3515
  run: (input, pos, ctx) => {
3360
- const e0 = a.run(input, pos, ctx);
3516
+ const e0 = ar(input, pos, ctx);
3361
3517
  if (e0 < 0) return -1;
3362
3518
  ctx._fc = false;
3363
- return b.run(input, e0, ctx);
3519
+ return br(input, e0, ctx);
3364
3520
  }
3365
3521
  };
3366
3522
  }
3367
3523
  function sequence3(a, b, c) {
3524
+ const am = a.match, bm = b.match, cm = c.match, ar = a.run, br = b.run, cr = c.run;
3368
3525
  return {
3369
3526
  match: (input, pos) => {
3370
- const e0 = a.match(input, pos);
3527
+ const e0 = am(input, pos);
3371
3528
  if (e0 < 0) return -1;
3372
- const e1 = b.match(input, e0);
3373
- return e1 < 0 ? -1 : c.match(input, e1);
3529
+ const e1 = bm(input, e0);
3530
+ return e1 < 0 ? -1 : cm(input, e1);
3374
3531
  },
3375
3532
  run: (input, pos, ctx) => {
3376
- const e0 = a.run(input, pos, ctx);
3533
+ const e0 = ar(input, pos, ctx);
3377
3534
  if (e0 < 0) return -1;
3378
3535
  ctx._fc = false;
3379
- const e1 = b.run(input, e0, ctx);
3536
+ const e1 = br(input, e0, ctx);
3380
3537
  if (e1 < 0) return -1;
3381
3538
  ctx._fc = false;
3382
- return c.run(input, e1, ctx);
3539
+ return cr(input, e1, ctx);
3383
3540
  }
3384
3541
  };
3385
3542
  }
3386
3543
  function sequence4(a, b, c, d) {
3387
- const abc = sequence3(a, b, c);
3544
+ const am = a.match, bm = b.match, cm = c.match, dm = d.match;
3545
+ const ar = a.run, br = b.run, cr = c.run, dr = d.run;
3388
3546
  return {
3389
3547
  match: (input, pos) => {
3390
- const end = abc.match(input, pos);
3391
- return end < 0 ? -1 : d.match(input, end);
3548
+ const e0 = am(input, pos);
3549
+ if (e0 < 0) return -1;
3550
+ const e1 = bm(input, e0);
3551
+ if (e1 < 0) return -1;
3552
+ const e2 = cm(input, e1);
3553
+ return e2 < 0 ? -1 : dm(input, e2);
3392
3554
  },
3393
3555
  run: (input, pos, ctx) => {
3394
- const end = abc.run(input, pos, ctx);
3395
- if (end < 0) return -1;
3556
+ const e0 = ar(input, pos, ctx);
3557
+ if (e0 < 0) return -1;
3558
+ ctx._fc = false;
3559
+ const e1 = br(input, e0, ctx);
3560
+ if (e1 < 0) return -1;
3561
+ ctx._fc = false;
3562
+ const e2 = cr(input, e1, ctx);
3563
+ if (e2 < 0) return -1;
3396
3564
  ctx._fc = false;
3397
- return d.run(input, end, ctx);
3565
+ return dr(input, e2, ctx);
3398
3566
  }
3399
3567
  };
3400
3568
  }
3401
3569
  function sequence5(a, b, c, d, e) {
3402
- const abcd = sequence4(a, b, c, d);
3570
+ const am = a.match, bm = b.match, cm = c.match, dm = d.match, em = e.match;
3571
+ const ar = a.run, br = b.run, cr = c.run, dr = d.run, er = e.run;
3403
3572
  return {
3404
3573
  match: (input, pos) => {
3405
- const end = abcd.match(input, pos);
3406
- return end < 0 ? -1 : e.match(input, end);
3574
+ const e0 = am(input, pos);
3575
+ if (e0 < 0) return -1;
3576
+ const e1 = bm(input, e0);
3577
+ if (e1 < 0) return -1;
3578
+ const e2 = cm(input, e1);
3579
+ if (e2 < 0) return -1;
3580
+ const e3 = dm(input, e2);
3581
+ return e3 < 0 ? -1 : em(input, e3);
3407
3582
  },
3408
3583
  run: (input, pos, ctx) => {
3409
- const end = abcd.run(input, pos, ctx);
3410
- if (end < 0) return -1;
3584
+ const e0 = ar(input, pos, ctx);
3585
+ if (e0 < 0) return -1;
3586
+ ctx._fc = false;
3587
+ const e1 = br(input, e0, ctx);
3588
+ if (e1 < 0) return -1;
3411
3589
  ctx._fc = false;
3412
- return e.run(input, end, ctx);
3590
+ const e2 = cr(input, e1, ctx);
3591
+ if (e2 < 0) return -1;
3592
+ ctx._fc = false;
3593
+ const e3 = dr(input, e2, ctx);
3594
+ if (e3 < 0) return -1;
3595
+ ctx._fc = false;
3596
+ return er(input, e3, ctx);
3413
3597
  }
3414
3598
  };
3415
3599
  }
@@ -3422,9 +3606,9 @@ function appendExpected(acc, values) {
3422
3606
  function choiceNode(arms, classes, armExpected, choiceExpected) {
3423
3607
  let matchTail = () => -1;
3424
3608
  for (let i = arms.length - 1; i >= 0; i--) {
3425
- const arm = arms[i], next = matchTail;
3609
+ const armMatch = arms[i].match, next = matchTail;
3426
3610
  matchTail = (input, pos) => {
3427
- const end = arm.match(input, pos);
3611
+ const end = armMatch(input, pos);
3428
3612
  return end < 0 ? next(input, pos) : end;
3429
3613
  };
3430
3614
  }
@@ -3434,7 +3618,7 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
3434
3618
  return -1;
3435
3619
  };
3436
3620
  for (let i = arms.length - 1; i >= 0; i--) {
3437
- const arm = arms[i], cls = classes[i], staticExpected = armExpected[i], next = tail;
3621
+ const armRun = arms[i].run, cls = classes[i], staticExpected = armExpected[i], next = tail;
3438
3622
  tail = (input, pos, ctx, lead2, acc, best) => {
3439
3623
  if (cls !== void 0 && !classHas(cls, lead2)) {
3440
3624
  return next(
@@ -3447,7 +3631,7 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
3447
3631
  );
3448
3632
  }
3449
3633
  ctx._fc = false;
3450
- const end = arm.run(input, pos, ctx);
3634
+ const end = armRun(input, pos, ctx);
3451
3635
  if (end >= 0) return end;
3452
3636
  const at = ctx._fe ?? pos;
3453
3637
  if (at > best) {
@@ -3474,11 +3658,58 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
3474
3658
  )
3475
3659
  };
3476
3660
  }
3661
+ function exclusiveChoiceNode(arms, classes, choiceFx) {
3662
+ const ascii = (classes.length <= 128 ? new Int8Array(128) : new Int32Array(128)).fill(-1);
3663
+ const hi = [];
3664
+ for (let i = 0; i < classes.length; i++) {
3665
+ const cls = classes[i];
3666
+ for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) ascii[c] = i;
3667
+ for (let r = 0; r < cls.hi.length; r += 2) hi.push(cls.hi[r], cls.hi[r + 1], i);
3668
+ }
3669
+ const select = (code) => {
3670
+ if (code < 0) return -1;
3671
+ if (code < 128) return ascii[code];
3672
+ for (let r = 0; r < hi.length; r += 3) if (code >= hi[r] && code <= hi[r + 1]) return hi[r + 2];
3673
+ return -1;
3674
+ };
3675
+ let matchArm = () => -1;
3676
+ let selectRun = () => -1;
3677
+ for (let i = arms.length - 1; i >= 0; i--) {
3678
+ const armMatch = arms[i].match, armRun = arms[i].run, nextMatch = matchArm, nextRun = selectRun;
3679
+ matchArm = (selected, input, pos) => selected === i ? armMatch(input, pos) : nextMatch(selected, input, pos);
3680
+ selectRun = (selected, input, pos, ctx) => selected === i ? armRun(input, pos, ctx) : nextRun(selected, input, pos, ctx);
3681
+ }
3682
+ const runArm = (input, pos, ctx) => {
3683
+ const arm = select(lead(input, pos));
3684
+ if (arm >= 0) {
3685
+ ctx._fc = false;
3686
+ const end = selectRun(arm, input, pos, ctx);
3687
+ if (end >= 0) return end;
3688
+ if (committed(ctx)) return -1;
3689
+ const failed = ctx._fx;
3690
+ if (failed !== void 0 && failed.length > 0) {
3691
+ ctx._fe = pos;
3692
+ return -1;
3693
+ }
3694
+ }
3695
+ ctx._fe = pos;
3696
+ ctx._fx = choiceFx;
3697
+ return -1;
3698
+ };
3699
+ return {
3700
+ match: (input, pos) => {
3701
+ const arm = select(lead(input, pos));
3702
+ return arm < 0 ? -1 : matchArm(arm, input, pos);
3703
+ },
3704
+ run: runArm
3705
+ };
3706
+ }
3477
3707
  function notNode(body, failure) {
3708
+ const bodyMatch = body.match;
3478
3709
  return {
3479
- match: (input, pos) => body.match(input, pos) < 0 ? pos : -1,
3710
+ match: (input, pos) => bodyMatch(input, pos) < 0 ? pos : -1,
3480
3711
  run: (input, pos, ctx) => {
3481
- if (body.match(input, pos) < 0) return pos;
3712
+ if (bodyMatch(input, pos) < 0) return pos;
3482
3713
  ctx._fe = pos;
3483
3714
  ctx._fx = failure;
3484
3715
  return -1;
@@ -3486,18 +3717,57 @@ function notNode(body, failure) {
3486
3717
  };
3487
3718
  }
3488
3719
  function optionalNode(body) {
3720
+ const bodyMatch = body.match, bodyRun = body.run;
3489
3721
  return {
3490
3722
  match: (input, pos) => {
3491
- const end = body.match(input, pos);
3723
+ const end = bodyMatch(input, pos);
3492
3724
  return end < 0 ? pos : end;
3493
3725
  },
3494
3726
  run: (input, pos, ctx) => {
3495
3727
  ctx._fc = false;
3496
- const end = body.run(input, pos, ctx);
3728
+ const end = bodyRun(input, pos, ctx);
3497
3729
  return end < 0 && !committed(ctx) ? pos : end;
3498
3730
  }
3499
3731
  };
3500
3732
  }
3733
+ function repeatNode(item, min, max) {
3734
+ const itemMatch = item.match, itemRun = item.run;
3735
+ return {
3736
+ match: (input, pos) => {
3737
+ let cur = pos;
3738
+ let count = 0;
3739
+ for (; ; ) {
3740
+ if (max >= 0 && count >= max) break;
3741
+ const optional = count >= min && (count > 0 || min === 0);
3742
+ if (optional && cur >= input.length) break;
3743
+ const end = itemMatch(input, cur);
3744
+ if (end < 0 || optional && end === cur) break;
3745
+ cur = end;
3746
+ count++;
3747
+ }
3748
+ return count < min ? -1 : cur;
3749
+ },
3750
+ run: (input, pos, ctx) => {
3751
+ let cur = pos;
3752
+ let count = 0;
3753
+ for (; ; ) {
3754
+ if (max >= 0 && count >= max) break;
3755
+ const optional = count >= min && (count > 0 || min === 0);
3756
+ if (optional && cur >= input.length) break;
3757
+ ctx._fc = false;
3758
+ const end = itemRun(input, cur, ctx);
3759
+ if (end < 0) {
3760
+ if (committed(ctx)) return -1;
3761
+ break;
3762
+ }
3763
+ if (optional && end === cur) break;
3764
+ cur = end;
3765
+ count++;
3766
+ }
3767
+ return count < min ? -1 : cur;
3768
+ }
3769
+ };
3770
+ }
3501
3771
  function fixedTreeRunner(words, matchers, classes, expected) {
3502
3772
  const stack = [];
3503
3773
  const pop = () => {
@@ -3525,9 +3795,14 @@ function fixedTreeRunner(words, matchers, classes, expected) {
3525
3795
  else stack.push(sequence5(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4]));
3526
3796
  continue;
3527
3797
  }
3528
- if (op >= LEX_NODE_CHOICE2 && op <= LEX_NODE_CHOICE8) {
3529
- const count = op === LEX_NODE_CHOICE2 ? 2 : op === LEX_NODE_CHOICE4 ? 4 : 8;
3798
+ if (op === LEX_NODE_CHOICE) {
3799
+ const count = words[at++];
3800
+ const exclusive = words[at++];
3801
+ if (exclusive !== 0 && exclusive !== 1) throw new TypeError("table lexical tree choice has an invalid dispatch mode");
3530
3802
  const choiceFx = expected[words[at++]];
3803
+ if (!Number.isInteger(count) || count < 2 || count > stack.length) {
3804
+ throw new TypeError("table lexical tree choice has an invalid arm count");
3805
+ }
3531
3806
  if (choiceFx === void 0) throw new TypeError("table lexical tree choice has an invalid expected set");
3532
3807
  const armClasses = [];
3533
3808
  const armFx = [];
@@ -3540,7 +3815,7 @@ function fixedTreeRunner(words, matchers, classes, expected) {
3540
3815
  armFx.push(fx);
3541
3816
  }
3542
3817
  const arms = Array.from({ length: count }, pop).reverse();
3543
- stack.push(choiceNode(arms, armClasses, armFx, choiceFx));
3818
+ stack.push(exclusive === 1 ? exclusiveChoiceNode(arms, armClasses, choiceFx) : choiceNode(arms, armClasses, armFx, choiceFx));
3544
3819
  continue;
3545
3820
  }
3546
3821
  if (op === LEX_NODE_NOT) {
@@ -3553,6 +3828,14 @@ function fixedTreeRunner(words, matchers, classes, expected) {
3553
3828
  stack.push(optionalNode(pop()));
3554
3829
  continue;
3555
3830
  }
3831
+ if (op === LEX_NODE_REPEAT) {
3832
+ const min = words[at++], max = words[at++];
3833
+ if (!Number.isInteger(min) || min < 0 || !Number.isInteger(max) || max >= 0 && max < min) {
3834
+ throw new TypeError("table lexical tree repeat has invalid bounds");
3835
+ }
3836
+ stack.push(repeatNode(pop(), min, max));
3837
+ continue;
3838
+ }
3556
3839
  throw new TypeError("table lexical tree has an unknown fixed body");
3557
3840
  }
3558
3841
  if (stack.length !== 1) throw new TypeError("table lexical tree does not resolve to one root body");
@@ -3707,6 +3990,12 @@ function scanRefs(s) {
3707
3990
  refs.push(...s.skip);
3708
3991
  return refs;
3709
3992
  }
3993
+ function assemblyExtraIps(prog) {
3994
+ const ips = [];
3995
+ for (const s of prog.scans ?? []) for (const r of scanRefs(s)) ips.push(r[0]);
3996
+ for (const set of prog.scanSkip ?? []) for (const r of set) ips.push(r[0]);
3997
+ return ips;
3998
+ }
3710
3999
  function expandCompact(p) {
3711
4000
  if ("code" in p) return p;
3712
4001
  return ownTableProgram({
@@ -3837,6 +4126,11 @@ function classHas2(cls, code) {
3837
4126
  for (let i = 0; i < hi.length; i += 2) if (code >= hi[i] && code <= hi[i + 1]) return true;
3838
4127
  return false;
3839
4128
  }
4129
+ function dispatchIsExclusive(arms, cc) {
4130
+ const resolved = [];
4131
+ for (const ci of arms) if (ci >= 0) resolved[ci] = resolveClass(cc[ci]);
4132
+ return resolveDispatch(arms, resolved).exclusive;
4133
+ }
3840
4134
  function resolveDispatch(arms, cc) {
3841
4135
  const ascii = new Uint8Array(128);
3842
4136
  const hi = [];
@@ -4217,7 +4511,7 @@ function sequence(...parsers) {
4217
4511
  if (tolerant) {
4218
4512
  followSentinels ??= parsers.map((_, i) => firstSetSentinel(
4219
4513
  parsers.slice(i + 1).reduce(
4220
- (set, parser) => union(set, firstSetOf(parser)),
4514
+ (set, parser2) => union(set, firstSetOf(parser2)),
4221
4515
  { kind: "empty" }
4222
4516
  )
4223
4517
  ));
@@ -4353,13 +4647,13 @@ function ref() {
4353
4647
  return scalar(input, pos, ctx);
4354
4648
  },
4355
4649
  parse(input, pos, ctx) {
4356
- const parser = resolved;
4357
- if (!parser) throw new Error("ref<T>() used before .define() was called");
4650
+ const parser2 = resolved;
4651
+ if (!parser2) throw new Error("ref<T>() used before .define() was called");
4358
4652
  const gt = meta.grammarTrivia;
4359
4653
  if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
4360
- return withRuleTrivia(gt, ctx, () => parser.parse(input, pos, ctx));
4654
+ return withRuleTrivia(gt, ctx, () => parser2.parse(input, pos, ctx));
4361
4655
  }
4362
- return parser.parse(input, pos, ctx);
4656
+ return parser2.parse(input, pos, ctx);
4363
4657
  },
4364
4658
  define(p) {
4365
4659
  if (resolved) throw new Error("ref<T>() already defined");
@@ -4618,7 +4912,7 @@ function confirmedArityForDef(def) {
4618
4912
  severity: "warn",
4619
4913
  where: `node("${def.type ?? "<inferred>"}")`,
4620
4914
  subject,
4621
- fellBackTo: `could not confirm its declared arity \u2014 ${unconfirmableReason(def, src)} \u2014 so this node captures children, fields and raw children, logs trivia, and clones \`_ctx.state\` on every match`,
4915
+ fellBackTo: `could not confirm its declared arity \u2014 ${unconfirmableReason(def, src)} \u2014 so this node captures children, fields and raw children, logs trivia, and hands it \`_ctx.state\` on every match`,
4622
4916
  otherwise: "only the tiers the reducer actually declares would be captured (arity >= 1 children, >= 2 fields, >= 4 raw, >= 5 trivia, >= 6 state). Declare it with `node(..., { buildArity: n })` if it cannot be derived"
4623
4917
  });
4624
4918
  return null;
@@ -4644,6 +4938,12 @@ function buildReadsState(def) {
4644
4938
  }
4645
4939
 
4646
4940
  // src/combinators/token.ts
4941
+ function semanticLeafValue(_ctx, _input, _start, _end, value) {
4942
+ return value;
4943
+ }
4944
+ function sourceLeafValue(ctx, input, start, end, value) {
4945
+ return cstOutputHost(ctx.build) ? input.slice(start, end) : value;
4946
+ }
4647
4947
  function token(root) {
4648
4948
  const meta = {
4649
4949
  firstSet: root._meta.firstSet,
@@ -4696,6 +4996,64 @@ function token(root) {
4696
4996
  }
4697
4997
  };
4698
4998
  }
4999
+ function makeLeaf(root, fn, sourceCstValue) {
5000
+ const cstValue = sourceCstValue ? sourceLeafValue : semanticLeafValue;
5001
+ const meta = {
5002
+ firstSet: root._meta.firstSet,
5003
+ canMatchNewline: root._meta.canMatchNewline,
5004
+ isTrivia: false
5005
+ };
5006
+ return {
5007
+ _tag: "leaf",
5008
+ _meta: meta,
5009
+ _def: {
5010
+ tag: "leaf",
5011
+ parser: root,
5012
+ fn,
5013
+ ...sourceCstValue ? { cstValue: "source" } : {}
5014
+ },
5015
+ parse(input, pos, ctx) {
5016
+ const savedBuf = ctx._cstBuf;
5017
+ const savedChildren = ctx._cstChildren;
5018
+ const savedLeaves = ctx._cstLeaves;
5019
+ const savedRaw = ctx._cstRawChildren;
5020
+ const savedTriviaLog = ctx._cstTriviaLog;
5021
+ const savedOuterTriviaLog = ctx._triviaLog;
5022
+ const wasCapturing = cstCaptureActive(ctx);
5023
+ ctx._cstBuf = void 0;
5024
+ ctx._cstChildren = void 0;
5025
+ ctx._cstLeaves = void 0;
5026
+ ctx._cstRawChildren = void 0;
5027
+ ctx._cstTriviaLog = void 0;
5028
+ ctx._triviaLog = void 0;
5029
+ let result;
5030
+ try {
5031
+ result = root.parse(input, pos, ctx);
5032
+ } finally {
5033
+ ctx._cstBuf = savedBuf;
5034
+ ctx._cstChildren = savedChildren;
5035
+ ctx._cstLeaves = savedLeaves;
5036
+ ctx._cstRawChildren = savedRaw;
5037
+ ctx._cstTriviaLog = savedTriviaLog;
5038
+ ctx._triviaLog = savedOuterTriviaLog;
5039
+ }
5040
+ if (!result.ok) return result;
5041
+ const value = fn(result.value, result.span);
5042
+ if (wasCapturing) pushCstLeaf(ctx, {
5043
+ _tag: "leaf",
5044
+ value: cstValue(ctx, input, pos, result.span.end, value),
5045
+ span: result.span
5046
+ });
5047
+ return { ok: true, value, span: result.span };
5048
+ }
5049
+ };
5050
+ }
5051
+ function leaf(root, fn) {
5052
+ return makeLeaf(root, fn, false);
5053
+ }
5054
+ function sourceLeaf(root, fn) {
5055
+ return makeLeaf(root, fn, true);
5056
+ }
4699
5057
 
4700
5058
  // src/combinators/scanTo.ts
4701
5059
  function resolveScanSkip(explicitSkip, raw, ctx) {
@@ -4735,8 +5093,8 @@ function scanTo(sentinel, { skip, raw = false, orEOF = false, recoverAt, stopAt
4735
5093
  probeCtx._errors = ctx._errors;
4736
5094
  const emit = (end) => {
4737
5095
  if (end > pos && cstCaptureActive(ctx)) {
4738
- const leaf = { _tag: "leaf", value: input.slice(pos, end), span: { start: pos, end } };
4739
- pushCstLeaf(ctx, leaf);
5096
+ const leaf2 = { _tag: "leaf", value: input.slice(pos, end), span: { start: pos, end } };
5097
+ pushCstLeaf(ctx, leaf2);
4740
5098
  }
4741
5099
  };
4742
5100
  if (recoverAt === void 0 && stopAt === void 0) {
@@ -5012,11 +5370,75 @@ function buildFieldMap(captures) {
5012
5370
  return out;
5013
5371
  }
5014
5372
 
5373
+ // src/table/trivia-gap.ts
5374
+ function skipDeferredTrivia(input, cur, ctx) {
5375
+ const triviaP = ctx.trivia;
5376
+ const plain = ctx.trackLines !== true && ctx.captureTrivia !== true;
5377
+ const gap = ctx._gap;
5378
+ if (plain && gap !== void 0 && cur === gap.at && input === gap.input && triviaP === gap.of && ctx._rootTriviaCapture === gap.root && ctx.state === gap.state && ctx._rootTriviaKindIndex === gap.rootKinds && ctx._triviaLog === gap.log) return gap.end;
5379
+ const end = clearRunEnd(input, cur, ctx, triviaP, plain);
5380
+ if (end >= 0) {
5381
+ remember(cur, end, ctx, input, triviaP);
5382
+ return end;
5383
+ }
5384
+ const scan = scanTriviaCompact(input, cur, ctx);
5385
+ if (typeof scan !== "number") return commitTriviaScan(scan);
5386
+ if (plain) remember(cur, scan, ctx, input, triviaP);
5387
+ return scan;
5388
+ }
5389
+ function clearRunEnd(input, cur, ctx, triviaP, plain) {
5390
+ const rootKinds = ctx._rootTriviaKindIndex;
5391
+ const spec = triviaP?._meta.labeledTriviaSpec;
5392
+ if (!plain || triviaP === void 0 || spec == null || rootKinds === void 0 || ctx._triviaLog !== void 0) return -1;
5393
+ if (spec.rootKinds !== rootKinds) prime(spec, triviaP, rootKinds);
5394
+ const fast = spec.rootScan;
5395
+ if (fast === null) return -1;
5396
+ const end = fast(input, cur);
5397
+ return ctx._rootTriviaCapture === false || clearOf(spec.rootLeaders, input, cur, end) ? end : -1;
5398
+ }
5399
+ function remember(cur, end, ctx, input, triviaP) {
5400
+ const gap = ctx._gap;
5401
+ if (gap === void 0) {
5402
+ ctx._gap = { at: cur, end, input, of: triviaP, root: ctx._rootTriviaCapture, rootKinds: ctx._rootTriviaKindIndex, log: ctx._triviaLog, state: ctx.state };
5403
+ return;
5404
+ }
5405
+ gap.at = cur;
5406
+ gap.end = end;
5407
+ gap.input = input;
5408
+ gap.of = triviaP;
5409
+ gap.root = ctx._rootTriviaCapture;
5410
+ gap.rootKinds = ctx._rootTriviaKindIndex;
5411
+ gap.log = ctx._triviaLog;
5412
+ gap.state = ctx.state;
5413
+ }
5414
+ function prime(spec, triviaP, rootKinds) {
5415
+ const ranges = [];
5416
+ let bounded = true;
5417
+ for (const arm of spec.arms) {
5418
+ if (rootKinds[arm.label] === void 0) continue;
5419
+ const fs = arm.parser._meta.firstSet;
5420
+ if (fs.kind === "any") bounded = false;
5421
+ else if (fs.kind === "ranges") ranges.push(...fs.ranges);
5422
+ }
5423
+ const classified = triviaP._meta.triviaScanner;
5424
+ spec.rootKinds = rootKinds;
5425
+ spec.rootLeaders = ranges;
5426
+ spec.rootScan = !bounded ? null : classified === void 0 ? fastTriviaScanner(triviaP) : classified;
5427
+ }
5428
+ function clearOf(ranges, input, from, to) {
5429
+ for (let i = from; i < to; i++) {
5430
+ const c = input.charCodeAt(i);
5431
+ if (c >= 55296 && c <= 57343) return false;
5432
+ for (const r of ranges) if (c >= r.lo && c <= r.hi) return false;
5433
+ }
5434
+ return true;
5435
+ }
5436
+
5015
5437
  // src/combinators/dispatch.ts
5016
- function parserUsesRouted(parser, seen = /* @__PURE__ */ new Set()) {
5017
- if (seen.has(parser)) return false;
5018
- seen.add(parser);
5019
- const def = parser._def;
5438
+ function parserUsesRouted(parser2, seen = /* @__PURE__ */ new Set()) {
5439
+ if (seen.has(parser2)) return false;
5440
+ seen.add(parser2);
5441
+ const def = parser2._def;
5020
5442
  switch (def.tag) {
5021
5443
  case "routed":
5022
5444
  return true;
@@ -5066,10 +5488,16 @@ function branchUsesRouted(branch) {
5066
5488
  return branch.usesRouted === true || parserUsesRouted(branch.parser);
5067
5489
  }
5068
5490
  function asciiFoldKey(key) {
5069
- let out = "";
5070
- for (let i = 0; i < key.length; i++) {
5491
+ let i = 0;
5492
+ for (; i < key.length; i++) {
5493
+ const c = key.charCodeAt(i);
5494
+ if (c >= 65 && c <= 90) break;
5495
+ }
5496
+ if (i === key.length) return key;
5497
+ let out = key.slice(0, i);
5498
+ for (; i < key.length; i++) {
5071
5499
  const c = key.charCodeAt(i);
5072
- out += String.fromCharCode(c >= 65 && c <= 90 ? c + 32 : c);
5500
+ out += c >= 65 && c <= 90 ? String.fromCharCode(c + 32) : key[i];
5073
5501
  }
5074
5502
  return out;
5075
5503
  }
@@ -5131,6 +5559,7 @@ var OP_SCOPE_PLAIN = 41;
5131
5559
  var OP_LEX_BODY = 42;
5132
5560
  var OP_LEX_PROGRAM = 43;
5133
5561
  var OP_SOURCE_LEAF = 44;
5562
+ var OP_RGATE = 45;
5134
5563
  var OP_DISPATCH = 25;
5135
5564
  var OP_ROUTED = 26;
5136
5565
  var OP_NAMES = {
@@ -5150,6 +5579,7 @@ var OP_NAMES = {
5150
5579
  [OP_PEEK]: "PEEK",
5151
5580
  [OP_LEAF]: "LEAF",
5152
5581
  [OP_SOURCE_LEAF]: "SOURCE_LEAF",
5582
+ [OP_RGATE]: "RGATE",
5153
5583
  [OP_EMPTY]: "EMPTY",
5154
5584
  [OP_LIT_TRACK]: "LIT_TRACK",
5155
5585
  [OP_RX_TRACK]: "RX_TRACK",
@@ -6249,6 +6679,7 @@ function childSlots(code, ip, out) {
6249
6679
  case OP_LEAF:
6250
6680
  case OP_SOURCE_LEAF:
6251
6681
  case OP_ARMGATE:
6682
+ case OP_RGATE:
6252
6683
  out.push(code[ip + 2]);
6253
6684
  return true;
6254
6685
  // `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
@@ -6332,6 +6763,42 @@ function reachableSites(code, roots) {
6332
6763
  }
6333
6764
  return seen;
6334
6765
  }
6766
+ function passCollapse(code, ip, hostCst) {
6767
+ const flags = code[ip + 3];
6768
+ if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return false;
6769
+ if (flags !== 32 && flags !== 34) return false;
6770
+ let at = code[ip + 2];
6771
+ for (let n = 0; n < 8; n++) {
6772
+ const op = code[at];
6773
+ if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[at + 3] === 0) at = code[at + 2];
6774
+ else if (op === OP_RULE) at = code[at + 1];
6775
+ else break;
6776
+ }
6777
+ return code[at] === OP_NODE;
6778
+ }
6779
+ function gatedPassCollapse(code, ip, hostCst) {
6780
+ const flags = code[ip + 3];
6781
+ if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return void 0;
6782
+ if (flags !== 32 && flags !== 34) return void 0;
6783
+ const seq = code[ip + 2];
6784
+ if (code[seq] !== OP_SEQ && code[seq] !== OP_SEQV) return void 0;
6785
+ const n = code[seq + 1];
6786
+ if (n < 2) return void 0;
6787
+ const leads = [];
6788
+ const lits = [];
6789
+ for (let i = 0; i < n - 1; i++) {
6790
+ const t = code[seq + 2 + i];
6791
+ if (code[t] !== OP_OPT && code[t] !== OP_NOT) return void 0;
6792
+ const g = code[t + 1];
6793
+ if (code[g] === OP_GATE) leads.push(g);
6794
+ else if (code[g] === OP_LIT) lits.push(code[g + 1]);
6795
+ else return void 0;
6796
+ }
6797
+ const last = code[seq + 2 + n - 1];
6798
+ let at = last;
6799
+ for (let k = 0; k < 8 && (code[at] === OP_GATE || code[at] === OP_RULE); k++) at = code[at] === OP_RULE ? code[at + 1] : code[at + 2];
6800
+ return code[at] === OP_NODE ? { leads, lits, last } : void 0;
6801
+ }
6335
6802
  function transfer(code, ip, at, hostCst) {
6336
6803
  const op = code[ip];
6337
6804
  if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
@@ -6343,14 +6810,18 @@ function transfer(code, ip, at, hostCst) {
6343
6810
  }
6344
6811
  if (op === OP_NODE || op === OP_NODE_TRACK) {
6345
6812
  const flags = code[ip + 3];
6813
+ if (passCollapse(code, ip, hostCst)) return at;
6814
+ const gated = gatedPassCollapse(code, ip, hostCst) !== void 0;
6346
6815
  const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && ((flags & ~128) === 2 || flags === 18 || flags === 34);
6347
6816
  if (directChildren) {
6348
- return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
6817
+ const framed2 = { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
6818
+ return gated ? meet(at, framed2) : framed2;
6349
6819
  }
6350
6820
  const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
6351
6821
  const raw = !hostCst && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags & 2) !== 0 ? RAW_OMIT : RAW_CAPTURE;
6352
6822
  if (at.buf && raw === at.raw && cap === at.cap) return at;
6353
- return { tri: at.tri, buf: true, raw, cap };
6823
+ const framed = { tri: at.tri, buf: true, raw, cap };
6824
+ return gated ? meet(at, framed) : framed;
6354
6825
  }
6355
6826
  if (op === OP_TOKEN) {
6356
6827
  if (at.tri === TRI_NONE && !at.buf) return at;
@@ -6388,6 +6859,40 @@ function computeSiteLabels(code, roots, hostCst) {
6388
6859
  }
6389
6860
  return { at: (ip) => labels.get(ip) ?? TOP };
6390
6861
  }
6862
+ function scopeIsIdentity(code, ip, at) {
6863
+ const op = code[ip];
6864
+ if (op !== OP_SCOPE_PLAIN && !(op === OP_SCOPE && code[ip + 3] === 0)) return false;
6865
+ const ki = code[ip + 1];
6866
+ return at.tri === (ki < 0 ? TRI_NONE : ki);
6867
+ }
6868
+ function scanHandoffNeeded(code, ip, labels) {
6869
+ const seen = /* @__PURE__ */ new Set();
6870
+ const stack = [ip];
6871
+ const kids = [];
6872
+ while (stack.length > 0) {
6873
+ const at = stack.pop();
6874
+ if (seen.has(at)) continue;
6875
+ seen.add(at);
6876
+ const l = labels.at(at);
6877
+ if (l.tri === TRI_UNKNOWN) return true;
6878
+ const op = code[at];
6879
+ if (op === OP_SCAN) return true;
6880
+ if (op === OP_TOKEN || op === OP_SCOPE_CAP) continue;
6881
+ if ((op === OP_SCOPE_PLAIN || op === OP_SCOPE) && !(code[at + 1] >= 0 && l.tri === code[at + 1] && (op === OP_SCOPE_PLAIN || code[at + 3] === 0))) continue;
6882
+ kids.length = 0;
6883
+ if (!childSlots(code, at, kids)) return true;
6884
+ for (const c of kids) stack.push(c);
6885
+ }
6886
+ return false;
6887
+ }
6888
+ function triviaLeadRanges(tri, trivia2) {
6889
+ if (tri === TRI_NONE) return [];
6890
+ if (tri < 0) return void 0;
6891
+ const fs = trivia2[tri]?._meta.firstSet;
6892
+ if (fs === void 0) return void 0;
6893
+ if (fs.kind === "empty") return [];
6894
+ return fs.kind === "ranges" && fs.ranges !== void 0 ? fs.ranges : void 0;
6895
+ }
6391
6896
 
6392
6897
  // src/table/scalar-terminal.ts
6393
6898
  function makeScalarRecognizer(op, spec) {
@@ -6425,6 +6930,12 @@ function scalarTerminalNotChild(code, ip) {
6425
6930
  const op = code[child];
6426
6931
  return op === OP_RX || op === OP_LIT ? child : -1;
6427
6932
  }
6933
+ function scalarTerminalPeekChild(code, ip) {
6934
+ if (code[ip] !== OP_PEEK) return -1;
6935
+ const child = code[ip + 1];
6936
+ const op = code[child];
6937
+ return op === OP_RX || op === OP_LIT ? child : -1;
6938
+ }
6428
6939
  function leadingScalarTerminal(code, ip, minDepth = 2, throughAttempt = true, throughPeek = false) {
6429
6940
  const seen = /* @__PURE__ */ new Set();
6430
6941
  let at = ip;
@@ -6602,6 +7113,59 @@ function leadingTriviaFieldAt(code, k, ip) {
6602
7113
  return code[ip] === OP_FIELD && (fieldSpec(k[code[ip + 1]]).bits & FIELD_LEADING_TRIVIA) !== 0;
6603
7114
  }
6604
7115
 
7116
+ // src/table/hold-gap.ts
7117
+ var WRAPPERS = /* @__PURE__ */ new Set([
7118
+ OP_NODE,
7119
+ OP_XFORM,
7120
+ OP_LEAF,
7121
+ OP_SOURCE_LEAF,
7122
+ OP_TOKEN,
7123
+ OP_SCOPE,
7124
+ OP_SCOPE_CAP,
7125
+ OP_SCOPE_PLAIN,
7126
+ OP_FIELD,
7127
+ OP_LABEL,
7128
+ OP_EXPECT,
7129
+ OP_WITHCTX,
7130
+ OP_RULE,
7131
+ OP_ATTEMPT,
7132
+ OP_COV
7133
+ ]);
7134
+ function rowNullable(code, k, ip, memo) {
7135
+ const hit = memo.get(ip);
7136
+ if (hit !== void 0) return hit;
7137
+ memo.set(ip, true);
7138
+ const op = code[ip];
7139
+ const kids = [];
7140
+ let out = true;
7141
+ if (op === OP_GATE) out = false;
7142
+ else if (op === OP_LIT || op === OP_LIT_CI) out = k[code[ip + 1]].length === 0;
7143
+ else if (op === OP_RX) {
7144
+ const re = k[code[ip + 1]];
7145
+ out = !(re instanceof RegExp) || regexCanMatchEmpty(re.source);
7146
+ } else if (op === OP_SEQ || op === OP_SEQV || op === OP_SEQX) {
7147
+ childSlots(code, ip, kids);
7148
+ out = kids.every((c) => rowNullable(code, k, c, memo));
7149
+ } else if (op === OP_CHOICE) {
7150
+ childSlots(code, ip, kids);
7151
+ out = kids.length === 0 || kids.some((c) => rowNullable(code, k, c, memo));
7152
+ } else if (op === OP_REP || op === OP_REPV) {
7153
+ out = code[ip + 2] === 0 || rowNullable(code, k, code[ip + 1], memo);
7154
+ } else if (WRAPPERS.has(op)) {
7155
+ if (childSlots(code, ip, kids) && kids.length === 1) out = rowNullable(code, k, kids[0], memo);
7156
+ }
7157
+ memo.set(ip, out);
7158
+ return out;
7159
+ }
7160
+ function holdsGap(code, k, base, n, i, memo) {
7161
+ if (i < 1 || i + 1 >= n) return false;
7162
+ const term = code[base + i];
7163
+ if (code[term] !== OP_NOT && code[term] !== OP_PEEK) return false;
7164
+ const next = code[base + i + 1];
7165
+ if (code[next] === OP_ADJ || leadingTriviaFieldAt(code, k, next)) return false;
7166
+ return !rowNullable(code, k, next, memo);
7167
+ }
7168
+
6605
7169
  // src/table/emit-assembly.ts
6606
7170
  var Unemittable = class extends Error {
6607
7171
  construct;
@@ -6679,7 +7243,13 @@ var EMITTED_PARAMS = [
6679
7243
  // Appended for trivia-attributing fields (`field(…, { leadingTrivia })`);
6680
7244
  // old factories ignore them.
6681
7245
  "LEAD",
6682
- "triviaFieldCapture"
7246
+ "triviaFieldCapture",
7247
+ // Appended for the deferred-commit trivia skip (`trivia-gap.ts`); old
7248
+ // factories ignore it.
7249
+ "skipDeferredTrivia",
7250
+ // Appended for the pass-through collapse (`run-support.ts`); old factories
7251
+ // ignore it.
7252
+ "collapseEmpty"
6683
7253
  ];
6684
7254
  var RUNTIME_PRELUDE = `
6685
7255
  let _pfScan=null
@@ -6700,7 +7270,7 @@ function _skipTrivia(input,cur,ctx){
6700
7270
  const s=_pfScan
6701
7271
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
6702
7272
  if(s!==null)return skipTriviaScanned(s,input,cur,ctx)
6703
- if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
7273
+ if(needsDeferredTriviaCommit(ctx))return skipDeferredTrivia(input,cur,ctx)
6704
7274
  return advanceTrivia(input,cur,ctx)
6705
7275
  }
6706
7276
  function _pushLeaf(ctx,value,s,e){pushCstLeaf(ctx,{_tag:'leaf',value,span:{start:s,end:e}})}
@@ -6876,6 +7446,24 @@ ${fast}
6876
7446
  ${scanned}
6877
7447
  }`;
6878
7448
  }
7449
+ function emitHoldTerm(callee, dst, t, l, skip) {
7450
+ const fast = `const ${t}v=${callee}(input,cur,ctx)
7451
+ if(${t}v===FAIL)return FAIL
7452
+ ${dst}=${t}v
7453
+ cur=EC.e`;
7454
+ if (l.tri === TRI_NONE) return fast;
7455
+ const held = `const ${t}s=${skip}(input,cur,ctx)
7456
+ const ${t}v=${callee}(input,${t}s,ctx)
7457
+ if(${t}v===FAIL)return FAIL
7458
+ ${dst}=${t}v
7459
+ cur=${t}s`;
7460
+ if (l.tri !== TRI_UNKNOWN) return held;
7461
+ return `if(ctx.trivia===undefined){
7462
+ ${fast}
7463
+ }else{
7464
+ ${held}
7465
+ }`;
7466
+ }
6879
7467
  function leadSkip(hasTrivia, leadTrivia, skip) {
6880
7468
  if (hasTrivia === "false") return "{}";
6881
7469
  const call = `itemStart=${skip}(input,itemStart,ctx)`;
@@ -6907,7 +7495,7 @@ function rebuildPools(cc, fx, disp, plan) {
6907
7495
  })
6908
7496
  };
6909
7497
  }
6910
- function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
7498
+ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, select) {
6911
7499
  const { code, k, fx, disp, dsp, triviaLabelled } = t;
6912
7500
  const swapLegal = !cfg.trackLines;
6913
7501
  const hostCst = cfg.hostCst;
@@ -6917,6 +7505,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
6917
7505
  const reachable = [...reachableSites(code, roots)];
6918
7506
  const labels = computeSiteLabels(code, roots, hostCst);
6919
7507
  const scalarSpecs = /* @__PURE__ */ new Set();
7508
+ const nullable2 = /* @__PURE__ */ new Map();
6920
7509
  const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
6921
7510
  const largeChoiceLiteralFamilies = /* @__PURE__ */ new Map();
6922
7511
  const largeChoiceScalarSequences = /* @__PURE__ */ new Map();
@@ -7006,6 +7595,8 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
7006
7595
  };
7007
7596
  const bodies = [];
7008
7597
  const byIp = /* @__PURE__ */ new Map();
7598
+ const externals = [];
7599
+ const siteBytes = /* @__PURE__ */ new Map();
7009
7600
  const reached = /* @__PURE__ */ new Set();
7010
7601
  const prelude = [];
7011
7602
  const skipDefs = [];
@@ -7141,6 +7732,18 @@ return 1
7141
7732
  tokenDecisionRefs.set(dispatchIp, made);
7142
7733
  return made;
7143
7734
  }
7735
+ function gateMissTest(gip) {
7736
+ const resolved = t.cc[code[gip + 1]];
7737
+ const ci = classes.push([resolved]) - 1;
7738
+ classPlan.push([code[gip + 1]]);
7739
+ const cls = hoist("cl", `CLS[${ci}][0]`);
7740
+ return isAsciiOnlyClass(resolved) ? `${cls}.ascii[input.charCodeAt(pos)]!==1` : `!classHas(${cls},lead(input,pos))`;
7741
+ }
7742
+ function lookaheadMiss(child, miss) {
7743
+ if (code[child] !== OP_GATE || cfg.tolerant || cfg.probe) return "";
7744
+ return `if(${gateMissTest(child)}){${miss}}
7745
+ `;
7746
+ }
7144
7747
  function skipFor(l) {
7145
7748
  if (l.tri < 0) return "_skipTrivia";
7146
7749
  const ki = l.tri;
@@ -7151,8 +7754,8 @@ return 1
7151
7754
  const nm = `_sk${skipPool.size}`;
7152
7755
  skipPool.set(key, nm);
7153
7756
  if (!hasScan) {
7154
- skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return commitTriviaScan(scanTriviaCompact(input,cur,ctx))}` : `function ${nm}(input,cur,ctx){
7155
- if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
7757
+ skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return skipDeferredTrivia(input,cur,ctx)}` : `function ${nm}(input,cur,ctx){
7758
+ if(needsDeferredTriviaCommit(ctx))return skipDeferredTrivia(input,cur,ctx)
7156
7759
  return advanceTrivia(input,cur,ctx)}`);
7157
7760
  return nm;
7158
7761
  }
@@ -7197,9 +7800,17 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
7197
7800
  const target = resolveAlias(ip);
7198
7801
  const done = byIp.get(target);
7199
7802
  if (done !== void 0) return done;
7803
+ if (select !== void 0 && !select.has(target)) {
7804
+ const ext = `_px${target}`;
7805
+ byIp.set(target, ext);
7806
+ externals.push(target);
7807
+ return ext;
7808
+ }
7200
7809
  const fname = `_pf${target}`;
7201
7810
  byIp.set(target, fname);
7202
- bodies.push(lower(target, fname));
7811
+ const body = lower(target, fname);
7812
+ siteBytes.set(target, body.length);
7813
+ bodies.push(body);
7203
7814
  return fname;
7204
7815
  }
7205
7816
  function resolveAlias(ip) {
@@ -7219,9 +7830,7 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
7219
7830
  const op = code[ip];
7220
7831
  if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
7221
7832
  if (op === OP_RULE) return code[ip + 1];
7222
- if ((op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[ip + 3] === 0) && code[ip + 1] >= 0 && labels.at(ip).tri === code[ip + 1]) {
7223
- return code[ip + 2];
7224
- }
7833
+ if (scopeIsIdentity(code, ip, labels.at(ip))) return code[ip + 2];
7225
7834
  return void 0;
7226
7835
  }
7227
7836
  function lower(ip, fname) {
@@ -7339,14 +7948,44 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
7339
7948
  return `${head}EC.e=pos;return ''}`;
7340
7949
  case OP_GATE: {
7341
7950
  const child = link(code[ip + 2]);
7951
+ const xf = fxRef(code[ip + 3]);
7952
+ return `${head}
7953
+ if(${gateMissTest(ip)}){ctx._fe=pos;ctx._fx=${xf};return FAIL}
7954
+ return ${child}(input,pos,ctx)
7955
+ }`;
7956
+ }
7957
+ case OP_RGATE: {
7958
+ const child = link(code[ip + 2]);
7959
+ if (cfg.tolerant || cfg.probe) return `${head}
7960
+ return ${child}(input,pos,ctx)
7961
+ }`;
7342
7962
  const resolved = t.cc[code[ip + 1]];
7343
7963
  const ci = classes.push([resolved]) - 1;
7344
7964
  classPlan.push([code[ip + 1]]);
7345
7965
  const cls = hoist("cl", `CLS[${ci}][0]`);
7346
7966
  const xf = fxRef(code[ip + 3]);
7347
7967
  return `${head}
7348
- if(${staticBuild && isAsciiOnlyClass(resolved) ? `${cls}.ascii[input.charCodeAt(pos)]!==1` : `!classHas(${cls},lead(input,pos))`}){ctx._fe=pos;ctx._fx=${xf};return FAIL}
7968
+ const it=ctx._routed
7969
+ if(it!==undefined&&it.span.start===pos&&!classHas(${cls},lead(input,it.span.end))){ctx._fe=it.span.end;ctx._fx=${xf};return FAIL}
7349
7970
  return ${child}(input,pos,ctx)
7971
+ }`;
7972
+ }
7973
+ case OP_ARMGATE: {
7974
+ const pred = fnRef(code[ip + 1]);
7975
+ const child = link(code[ip + 2]);
7976
+ const xf = fxRef(code[ip + 3]);
7977
+ return `${head}
7978
+ if(!${pred}(ctx.state)){ctx._fc=false;ctx._fe=-1;ctx._fx=${xf};return FAIL}
7979
+ return ${child}(input,pos,ctx)
7980
+ }`;
7981
+ }
7982
+ case OP_WITHCTX: {
7983
+ const ki = code[ip + 1];
7984
+ const child = link(code[ip + 2]);
7985
+ return `${head}
7986
+ const saved=ctx.state
7987
+ ctx.state=${ki < 0 ? `${fnRef(~ki)}(saved)` : kRef(ki)}
7988
+ try{return ${child}(input,pos,ctx)}finally{ctx.state=saved}
7350
7989
  }`;
7351
7990
  }
7352
7991
  case OP_XFORM: {
@@ -7602,24 +8241,34 @@ return FAIL
7602
8241
  const xf = fxRef(code[ip + 2]);
7603
8242
  const p = tmp();
7604
8243
  return `${head}
7605
- ${emitMark(p, L.buf, L.raw, sinks)}
7606
- const v=${child}(input,pos,ctx)
8244
+ ${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${emitMark(p, L.buf, L.raw, sinks)}
8245
+ ${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
7607
8246
  ${emitRollback(p, L.buf, L.raw, sinks)}
7608
- if(v===FAIL){EC.e=pos;return null}
8247
+ ${cfg.probe ? "if(ctx._probe!==undefined)ctx._probe.best=pb??null\n" : ""}if(v===FAIL){EC.e=pos;return null}
7609
8248
  ctx._fe=pos
7610
8249
  ctx._fx=${xf}
7611
8250
  return FAIL
7612
8251
  }`;
7613
8252
  }
7614
8253
  case OP_PEEK: {
8254
+ const scalarChild = scalarTerminalPeekChild(code, ip);
8255
+ if (scalarChild >= 0) {
8256
+ const recognize = recognizerRef(code[scalarChild + 1]);
8257
+ const xf2 = fxRef(code[ip + 2]);
8258
+ return `${head}
8259
+ if(${recognize}(input,pos)<0){ctx._fe=pos;ctx._fx=${xf2};return FAIL}
8260
+ EC.e=pos
8261
+ return null
8262
+ }`;
8263
+ }
7615
8264
  const child = link(code[ip + 1]);
7616
8265
  const xf = fxRef(code[ip + 2]);
7617
8266
  const p = tmp();
7618
8267
  return `${head}
7619
- ${emitMark(p, L.buf, L.raw, sinks)}
7620
- const v=${child}(input,pos,ctx)
8268
+ ${lookaheadMiss(code[ip + 1], `ctx._fe=pos;ctx._fx=${xf};return FAIL`)}${emitMark(p, L.buf, L.raw, sinks)}
8269
+ ${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
7621
8270
  ${emitRollback(p, L.buf, L.raw, sinks)}
7622
- if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
8271
+ ${cfg.probe ? "if(ctx._probe!==undefined)ctx._probe.best=pb??null\n" : ""}if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
7623
8272
  EC.e=pos
7624
8273
  return null
7625
8274
  }`;
@@ -7629,7 +8278,7 @@ return null
7629
8278
  const clean = !REC && failureRollbackClean(prog, ip);
7630
8279
  const p = tmp();
7631
8280
  return `${head}
7632
- ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
8281
+ ${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
7633
8282
  ctx._fc=false
7634
8283
  const v=${child}(input,pos,ctx)
7635
8284
  if(v===FAIL){
@@ -7690,7 +8339,7 @@ return v
7690
8339
  );
7691
8340
  } else {
7692
8341
  const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
7693
- parts.push(emitTerm(callee, vn, tmp(), L, skipFor(L)));
8342
+ parts.push(holdsGap(code, k, base, n, i, nullable2) ? emitHoldTerm(callee, vn, tmp(), L, skipFor(L)) : emitTerm(callee, vn, tmp(), L, skipFor(L)));
7694
8343
  }
7695
8344
  names.push(vn);
7696
8345
  }
@@ -7710,7 +8359,7 @@ return v
7710
8359
  const asc = hoist("as", `DISP[${di}].ascii`);
7711
8360
  const hiArr = table.hi;
7712
8361
  const armSwitch = arms.map((a, i) => `case ${i}:v=${a}(input,pos,ctx);break`).join("\n");
7713
- const directAscii = staticBuild && table.hi.length === 0;
8362
+ const directAscii = table.hi.length === 0;
7714
8363
  return `${head}
7715
8364
  const c=${directAscii ? "input.charCodeAt(pos)" : "lead(input,pos)"}
7716
8365
  let arm=-1
@@ -7737,7 +8386,7 @@ return FAIL
7737
8386
  const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
7738
8387
  const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
7739
8388
  const maskable = n <= 32;
7740
- const directAsciiMask = staticBuild && maskable && gates.every(isAsciiOnlyClass);
8389
+ const directAsciiMask = maskable && gates.every(isAsciiOnlyClass);
7741
8390
  const gateRefs = directAsciiMask ? [] : Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
7742
8391
  const tokenCandidate = tokenChoiceCandidates.get(ip);
7743
8392
  const pretests = Array.from({ length: n }, (_, i) => {
@@ -7779,7 +8428,7 @@ return FAIL
7779
8428
  if (choiceCannotCommit(prog, ip) && !startFailureExact) {
7780
8429
  const deepAt = Array.from({ length: n }, () => tmp());
7781
8430
  const deepFx = Array.from({ length: n }, () => tmp());
7782
- const remember = (i, at, expectedSet) => `${deepAt[i]}=${at};${deepFx[i]}=${expectedSet}`;
8431
+ const remember2 = (i, at, expectedSet) => `${deepAt[i]}=${at};${deepFx[i]}=${expectedSet}`;
7783
8432
  const lazyArms = (ascii) => arms.map((arm, i) => {
7784
8433
  const pretest = pretests[i];
7785
8434
  const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
@@ -7791,13 +8440,13 @@ return FAIL
7791
8440
  if(${decision}===0){
7792
8441
  ctx._fc=false
7793
8442
  {const at=_pfTokEnd
7794
- ${remember(i, "at", pretest.token.expected)}}
8443
+ ${remember2(i, "at", pretest.token.expected)}}
7795
8444
  }`;
7796
8445
  const sequenceMiss = pretest?.sequence === void 0 ? "" : `
7797
8446
  else if(${ascii ? `(bits&${1 << i})!==0&&` : ""}${decision}<0){
7798
8447
  ctx._fc=false
7799
8448
  {const at=_pfSeqEnd
7800
- ${remember(i, "at", pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("") + pretest.sequence.expected.at(-1))}}
8449
+ ${remember2(i, "at", pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("") + pretest.sequence.expected.at(-1))}}
7801
8450
  }`;
7802
8451
  return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
7803
8452
  `}if(${gate}){
@@ -7805,7 +8454,7 @@ ctx._fc=false
7805
8454
  {const v=${arm}(input,pos,ctx)
7806
8455
  if(v!==FAIL)return v}
7807
8456
  {const at=ctx._fe??pos
7808
- ${remember(i, "at", "ctx._fx")}}
8457
+ ${remember2(i, "at", "ctx._fx")}}
7809
8458
  ${rollbackFor(i)}
7810
8459
  }${routeMiss}${sequenceMiss}`;
7811
8460
  }).join("\n");
@@ -7918,7 +8567,7 @@ const bits=${maskName}[${directAsciiMask ? "c" : "c<0?128:c"}]
7918
8567
  if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
7919
8568
  ${startFailureExact ? "" : "let prev=0"}
7920
8569
  ${maskArms}
7921
- ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${n},prev,acc)`}
8570
+ ${startFailureExact ? "" : `if(best===pos&&prev!==0)acc=${catchName}(${n},prev,acc)`}
7922
8571
  ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
7923
8572
  return FAIL
7924
8573
  }
@@ -8017,7 +8666,7 @@ return [key,v]
8017
8666
  const ci = classes.push([resolved]) - 1;
8018
8667
  classPlan.push([itemClassIndex]);
8019
8668
  itemCls = hoist("ri", `CLS[${ci}][0]`);
8020
- itemAscii = staticBuild && isAsciiOnlyClass(resolved);
8669
+ itemAscii = isAsciiOnlyClass(resolved);
8021
8670
  }
8022
8671
  }
8023
8672
  const itemMiss = (at) => itemAscii ? `${itemCls}.ascii[input.charCodeAt(${at})]!==1` : `!classHas(${itemCls},lead(input,${at}))`;
@@ -8173,6 +8822,26 @@ return nd
8173
8822
  const trailingTrivia = (flags & 128) !== 0;
8174
8823
  const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
8175
8824
  const leanFlags = flags & ~128;
8825
+ if (build !== void 0 && passCollapse(code, ip, hostCst)) {
8826
+ return `${head}
8827
+ const v=${child}(input,pos,ctx)
8828
+ if(v!==undefined)return v
8829
+ return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
8830
+ }`;
8831
+ }
8832
+ const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
8833
+ const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(labels.at(code[ip + 2]).tri, t.trivia);
8834
+ const gp = gated !== void 0 && triviaLead !== void 0 && triviaLead.length <= 16 ? `const gc=lead(input,pos)
8835
+ if(!(${[
8836
+ ...gated.leads.map((g) => `!(${gateMissTest(g)})`),
8837
+ ...gated.lits.map((i) => `gc===${k[i].codePointAt(0)}`),
8838
+ ...triviaLead.map((r) => r.lo === r.hi ? `gc===${r.lo}` : `(gc>=${r.lo}&&gc<=${r.hi})`)
8839
+ ].join("||") || "false"})){
8840
+ const gv=${link(gated.last)}(input,pos,ctx)
8841
+ if(gv!==undefined)return gv
8842
+ return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
8843
+ }
8844
+ ` : "";
8176
8845
  if (!hostCst && !tracked && build !== void 0 && proj < 0 && (leanFlags === 2 || (flags === 18 || flags === 34))) {
8177
8846
  const fields = flags === 18;
8178
8847
  const collapseChildren = flags === 34;
@@ -8207,7 +8876,7 @@ sCh.push(nd)
8207
8876
  if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
8208
8877
  }`;
8209
8878
  return `${head}
8210
- const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
8879
+ ${gp}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
8211
8880
  const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
8212
8881
  const flat=[]
8213
8882
  ctx._cstBuf=undefined
@@ -8243,7 +8912,7 @@ return nd
8243
8912
  const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
8244
8913
  const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
8245
8914
  const ty = q(type);
8246
- const stArg = readsState ? "st" : "(ctx.state!==undefined?Object.assign({},ctx.state):undefined)";
8915
+ const stArg = "ctx.state";
8247
8916
  const hostCall = `_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,${stArg},${tags})`;
8248
8917
  let value;
8249
8918
  if (proj >= 0) {
@@ -8282,7 +8951,7 @@ const hostKids=kids
8282
8951
  const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
8283
8952
  const tlog=buf.tl??EMPTY_TLOG`;
8284
8953
  return `${head}
8285
- const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
8954
+ ${!hostCst && !tracked ? gp : ""}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
8286
8955
  const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf
8287
8956
  ${openCapture}
8288
8957
  ctx.captureTrivia=${captureWide}
@@ -8304,7 +8973,7 @@ ctx.captureTrivia=sCap
8304
8973
  if(v===FAIL)return FAIL
8305
8974
  const end=EC.e
8306
8975
  const span=${tracked ? "spanLines(ctx,pos,end)" : "{start:pos,end}"}
8307
- const st=${readsState ? "(ctx.state!==undefined?Object.assign({},ctx.state):undefined)" : "undefined"}
8976
+ const st=${readsState ? "ctx.state" : "undefined"}
8308
8977
  let nd
8309
8978
  ${unwrap ? "if(kids.length===1)nd=unwrapChild(kids[0])\nelse " : ""}${collapse ? "if(kids.length===1)nd=kids[0]\nelse " : ""}${collapsible ? `if(_pfHost!==undefined&&_pfHost._parsemanCstCollapse!==undefined&&kids.length===1&&rawKids.length===1&&_pfHost._parsemanCstCollapse(${ty},kids[0],kids,rawKids))nd=kids[0]
8310
8979
  else ` : ""}{${value}}
@@ -8317,21 +8986,57 @@ return nd
8317
8986
  throw new Unemittable(`OP_${OP_NAMES[op] ?? String(op)}`);
8318
8987
  }
8319
8988
  }
8989
+ const served = (ip) => select === void 0 || select.has(resolveAlias(ip));
8320
8990
  const ruleEntries = [];
8321
8991
  for (const [rname, entryIp] of Object.entries(prog.rules)) {
8992
+ if (!served(entryIp)) continue;
8322
8993
  const target = link(entryIp);
8323
8994
  const rn = `_r_${rname.replace(/[^A-Za-z0-9_$]/g, "_")}`;
8324
8995
  bodies.push(`const ${rn}=${target}`);
8325
8996
  ruleEntries.push(`${q(rname)}:${rn}`);
8326
8997
  }
8327
8998
  const extra = [];
8328
- for (const ip of extraIps) extra.push(`${ip}:${link(ip)}`);
8999
+ const exported = /* @__PURE__ */ new Set();
9000
+ for (const ip of extraIps) {
9001
+ if (!served(ip)) continue;
9002
+ exported.add(ip);
9003
+ extra.push(`${ip}:${link(ip)}`);
9004
+ }
9005
+ if (select !== void 0) {
9006
+ const kids = [];
9007
+ for (const ip of reachable) {
9008
+ if (select.has(resolveAlias(ip))) continue;
9009
+ kids.length = 0;
9010
+ childSlots(code, ip, kids);
9011
+ for (const kid of kids) {
9012
+ const target = resolveAlias(kid);
9013
+ if (!select.has(target) || exported.has(target)) continue;
9014
+ exported.add(target);
9015
+ extra.push(`${target}:${link(target)}`);
9016
+ }
9017
+ }
9018
+ }
9019
+ const hybrid = select === void 0 ? "" : `,
9020
+ ext:[${externals.join(",")}],
9021
+ bind:function(xs,ps){_xScan=xs
9022
+ ${externals.map((ip, i) => `_xp${ip}=ps[${i}]`).join("\n")}},
9023
+ scan:function(s){const o=_pfScan;_pfScan=s;return o}`;
9024
+ const scannerFor = (ip) => {
9025
+ const ki = labels.at(ip).tri;
9026
+ if (ki === TRI_UNKNOWN) return "_pfScan";
9027
+ if (ki === TRI_NONE) return "null";
9028
+ return swapLegal && !triviaLabelled[ki] && t.triviaScan[ki] != null ? hoist("ts", `TRIVIASCAN[${ki}]`) : "null";
9029
+ };
9030
+ const externalDefs = select === void 0 ? "" : `let _xScan
9031
+ ${externals.map((ip) => `let _xp${ip}
9032
+ function _px${ip}(input,pos,ctx){const o=_xScan(${scannerFor(ip)});const v=_xp${ip}(input,pos,ctx);_xScan(o);return v}`).join("\n")}
9033
+ `;
8329
9034
  const source = `${RUNTIME_PRELUDE}${needsNoRawPrelude ? NO_RAW_RUNTIME_PRELUDE : ""}
8330
9035
  ${prelude.join("\n")}
8331
9036
  ${skipDefs.join("\n")}
8332
9037
  ${choiceDefs.join("\n")}
8333
9038
  ${bodies.join("\n")}
8334
- function _begin(ctx){
9039
+ ${externalDefs}function _begin(ctx){
8335
9040
  const host=ctx.build
8336
9041
  if(_pfDepth>0)_pfFrames.push([_pfScan,_pfHost,EC.e])
8337
9042
  _pfDepth++
@@ -8358,7 +9063,7 @@ pieces:{${ruleEntries.join(",")}},
8358
9063
  byIp:{${extra.join(",")}},
8359
9064
  end:function(){return EC.e},
8360
9065
  begin:_begin,
8361
- finish:_finish
9066
+ finish:_finish${hybrid}
8362
9067
  }`;
8363
9068
  return {
8364
9069
  source,
@@ -8366,41 +9071,125 @@ finish:_finish
8366
9071
  masks,
8367
9072
  classes,
8368
9073
  armExpected,
9074
+ siteBytes,
8369
9075
  plan: { classes: classPlan, armExpected: armExpectedPlan, masks: maskPlan }
8370
9076
  };
8371
9077
  }
8372
9078
 
8373
- // src/table/run-support.ts
8374
- function lineCol(ctx, offset) {
8375
- const starts = ctx._lineStarts ?? [0];
8376
- let lo = 0, hi = starts.length - 1;
8377
- while (lo < hi) {
8378
- const mid = lo + hi + 1 >> 1;
8379
- if (starts[mid] <= offset) lo = mid;
8380
- else hi = mid - 1;
9079
+ // src/table/fail-clean.ts
9080
+ function passChild(code, ip) {
9081
+ switch (code[ip]) {
9082
+ case OP_RULE:
9083
+ case OP_LABEL:
9084
+ case OP_COV:
9085
+ case OP_TOKEN:
9086
+ return code[ip + 1];
9087
+ case OP_GATE:
9088
+ case OP_NODE:
9089
+ case OP_NODE_TRACK:
9090
+ case OP_XFORM:
9091
+ case OP_FIELD:
9092
+ case OP_SCOPE:
9093
+ case OP_SCOPE_CAP:
9094
+ case OP_SCOPE_PLAIN:
9095
+ case OP_WITHCTX:
9096
+ case OP_LEAF:
9097
+ case OP_SOURCE_LEAF:
9098
+ return code[ip + 2];
9099
+ default:
9100
+ return -1;
8381
9101
  }
8382
- return [lo + 1, offset - starts[lo] + 1];
8383
- }
8384
- function spanLines(ctx, start, end) {
8385
- const s = lineCol(ctx, start), e = lineCol(ctx, end);
8386
- return { start, end, startLine: s[0], startColumn: s[1], endLine: e[0], endColumn: e[1] };
8387
9102
  }
8388
- function rawEntry(v, input, s, e) {
8389
- if (typeof v === "object" && v !== null) {
8390
- const tg = v._tag;
8391
- if (tg === "node" || tg === "leaf" || tg === "parseError") return v;
8392
- }
8393
- return {
8394
- _tag: "leaf",
8395
- value: typeof v === "string" ? v : typeof v === "object" && v !== null ? input.slice(s, e) : "",
8396
- span: { start: s, end: e }
9103
+ function seqCount(code, ip) {
9104
+ const op = code[ip];
9105
+ return op === OP_SEQ || op === OP_SEQV ? ip + 1 : op === OP_SEQX ? ip + 2 : -1;
9106
+ }
9107
+ function failCleanAnalysis(code) {
9108
+ const cleanAt = new Uint8Array(code.length);
9109
+ const neverAt = new Uint8Array(code.length);
9110
+ const neverFails = (ip) => {
9111
+ const hit = neverAt[ip];
9112
+ if (hit !== 0) return hit === 1;
9113
+ neverAt[ip] = 3;
9114
+ let out = false;
9115
+ const op = code[ip];
9116
+ if (op === OP_OPT || op === OP_EMPTY || op === OP_EXPECT) out = true;
9117
+ else if (op === OP_REP || op === OP_REPV) out = code[ip + 2] === 0;
9118
+ else {
9119
+ const at = seqCount(code, ip);
9120
+ if (at >= 0) {
9121
+ out = true;
9122
+ for (let i = 1, n = code[at]; out && i <= n; i++) out = neverFails(code[at + i]);
9123
+ } else if (op !== OP_GATE) {
9124
+ const c = passChild(code, ip);
9125
+ out = c >= 0 && neverFails(c);
9126
+ }
9127
+ }
9128
+ neverAt[ip] = out ? 1 : 2;
9129
+ return out;
8397
9130
  };
8398
- }
8399
- function lead(input, pos) {
8400
- if (pos >= input.length) return -1;
8401
- const c = input.charCodeAt(pos);
8402
- if (c < 55296 || c > 56319) return c;
8403
- return input.codePointAt(pos) ?? c;
9131
+ const clean = (ip) => {
9132
+ const hit = cleanAt[ip];
9133
+ if (hit !== 0) return hit === 1;
9134
+ cleanAt[ip] = 3;
9135
+ let out = false;
9136
+ switch (code[ip]) {
9137
+ // A terminal pushes its leaf only on a match; NOT/PEEK/ATTEMPT restore
9138
+ // their own mark; OPT, EMPTY and EXPECT do not fail uncommitted.
9139
+ case OP_LIT:
9140
+ case OP_RX:
9141
+ case OP_LIT_TRACK:
9142
+ case OP_RX_TRACK:
9143
+ case OP_LIT_CI:
9144
+ case OP_LIT_CI_TRACK:
9145
+ case OP_GUARD:
9146
+ case OP_NOT:
9147
+ case OP_PEEK:
9148
+ case OP_ATTEMPT:
9149
+ case OP_EMPTY:
9150
+ case OP_OPT:
9151
+ case OP_EXPECT:
9152
+ out = true;
9153
+ break;
9154
+ // Min 0 does not fail uncommitted; min 1 fails only with no item kept, and
9155
+ // restores the failed item itself.
9156
+ case OP_REP:
9157
+ case OP_REPV:
9158
+ out = code[ip + 2] <= 1;
9159
+ break;
9160
+ // Only the first term may fail: a later one fails after the terms before it
9161
+ // wrote, and after the trivia scanned in front of it.
9162
+ case OP_SEQ:
9163
+ case OP_SEQV:
9164
+ case OP_SEQX: {
9165
+ const at = seqCount(code, ip);
9166
+ const n = code[at];
9167
+ out = n > 0 && clean(code[at + 1]);
9168
+ for (let i = 2; out && i <= n; i++) out = neverFails(code[at + i]);
9169
+ break;
9170
+ }
9171
+ case OP_CHOICE: {
9172
+ out = true;
9173
+ for (let i = 0, n = code[ip + 2]; out && i < n; i++) out = clean(code[ip + 4 + i]);
9174
+ break;
9175
+ }
9176
+ case OP_ROUTED:
9177
+ out = code[ip + 1] < 0 || clean(code[ip + 1]);
9178
+ break;
9179
+ // An arm's failure and the fallback's are committed; only the selector's is
9180
+ // not, and without a fallback an unknown key fails after the selector wrote.
9181
+ case OP_DISPATCH:
9182
+ out = code[ip + 3] >= 0 && clean(code[ip + 1]);
9183
+ break;
9184
+ default: {
9185
+ const c = passChild(code, ip);
9186
+ out = c >= 0 && clean(c);
9187
+ }
9188
+ }
9189
+ cleanAt[ip] = out ? 1 : 2;
9190
+ return out;
9191
+ };
9192
+ return clean;
8404
9193
  }
8405
9194
 
8406
9195
  // src/cst/host-mode.ts
@@ -8572,6 +9361,7 @@ function assemble(t, prog, cfg) {
8572
9361
  const swapLegal = !cfg.trackLines;
8573
9362
  const hostCst = cfg.hostCst;
8574
9363
  const REC = prog.rec === 1 && cfg.tolerant;
9364
+ const PROBE = cfg.probe;
8575
9365
  const sentinels = /* @__PURE__ */ new Map();
8576
9366
  function sentinelFor(cls) {
8577
9367
  if (cls < 0) return void 0;
@@ -8586,6 +9376,9 @@ function assemble(t, prog, cfg) {
8586
9376
  const EC = newEndCell();
8587
9377
  const scalarRecognizers = [];
8588
9378
  const rawScalarSpecs = /* @__PURE__ */ new Set();
9379
+ function lookaheadClass(child) {
9380
+ return code[child] === OP_GATE && !cfg.tolerant && !cfg.probe ? cc[code[child + 1]] : null;
9381
+ }
8589
9382
  function scalarFor(child) {
8590
9383
  const spec = code[child + 1];
8591
9384
  let recognize = scalarRecognizers[spec];
@@ -8595,17 +9388,27 @@ function assemble(t, prog, cfg) {
8595
9388
  }
8596
9389
  return recognize;
8597
9390
  }
8598
- const labelExtraIps = [];
8599
- for (const s of prog.scans ?? []) for (const r of scanRefs(s)) labelExtraIps.push(r[0]);
8600
- for (const set of prog.scanSkip ?? []) for (const r of set) labelExtraIps.push(r[0]);
9391
+ const labelExtraIps = assemblyExtraIps(prog);
8601
9392
  const closureLabels = computeSiteLabels(
8602
9393
  code,
8603
9394
  [...Object.values(prog.rules), ...labelExtraIps],
8604
9395
  hostCst
8605
9396
  );
8606
9397
  let SCAN = null;
9398
+ let HYBRID;
9399
+ function hybridPiece(piece) {
9400
+ const setScan = HYBRID.scan;
9401
+ return (input, pos, ctx) => {
9402
+ const saved = setScan(SCAN);
9403
+ const value = piece(input, pos, ctx);
9404
+ setScan(saved);
9405
+ return value;
9406
+ };
9407
+ }
8607
9408
  const memo = /* @__PURE__ */ new Map();
8608
9409
  const reached = /* @__PURE__ */ new Set();
9410
+ const NULLABLE = /* @__PURE__ */ new Map();
9411
+ const CLEAN = REC ? () => false : failCleanAnalysis(code);
8609
9412
  function pushLeaf(ctx, value, s, e) {
8610
9413
  const lf = { _tag: "leaf", value, span: { start: s, end: e } };
8611
9414
  pushCstLeaf(ctx, lf);
@@ -8804,6 +9607,22 @@ function assemble(t, prog, cfg) {
8804
9607
  return node;
8805
9608
  };
8806
9609
  }
9610
+ function passCollapseNode(child, build, readsRaw) {
9611
+ return (input, pos, ctx) => {
9612
+ const v = child(input, pos, ctx);
9613
+ if (v !== void 0) return v;
9614
+ return collapseEmpty(ctx, build, input, pos, EC.e, readsRaw);
9615
+ };
9616
+ }
9617
+ function gatedPassCollapseNode(blockers, last, classic, build, readsRaw) {
9618
+ return (input, pos, ctx) => {
9619
+ const c = lead(input, pos);
9620
+ for (let i = 0; i < blockers.length; i++) if (classHas2(blockers[i], c)) return classic(input, pos, ctx);
9621
+ const v = last(input, pos, ctx);
9622
+ if (v !== void 0) return v;
9623
+ return collapseEmpty(ctx, build, input, pos, EC.e, readsRaw);
9624
+ };
9625
+ }
8807
9626
  function plainProjectNode(child, projection, type) {
8808
9627
  return (input, pos, ctx) => {
8809
9628
  const sCh = ctx._cstChildren;
@@ -8895,9 +9714,7 @@ function assemble(t, prog, cfg) {
8895
9714
  return s(input, cur);
8896
9715
  }
8897
9716
  if (s !== null) return skipTriviaScanned(s, input, cur, ctx);
8898
- if (needsDeferredTriviaCommit(ctx)) {
8899
- return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
8900
- }
9717
+ if (needsDeferredTriviaCommit(ctx)) return skipDeferredTrivia(input, cur, ctx);
8901
9718
  return advanceTrivia(input, cur, ctx);
8902
9719
  }
8903
9720
  let TERMV;
@@ -9067,7 +9884,7 @@ function assemble(t, prog, cfg) {
9067
9884
  if (next !== void 0) {
9068
9885
  return next(input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best);
9069
9886
  }
9070
- if (best === pos) acc = through(total, prev, acc);
9887
+ if (best === pos && prev !== 0) acc = through(total, prev, acc);
9071
9888
  ctx._fe = pos;
9072
9889
  ctx._fx = acc ?? choiceFx;
9073
9890
  return FAIL;
@@ -9150,7 +9967,7 @@ function assemble(t, prog, cfg) {
9150
9967
  if (next !== void 0) {
9151
9968
  return next(input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best);
9152
9969
  }
9153
- if (best === pos) acc = through(total, prev, acc);
9970
+ if (best === pos && prev !== 0) acc = through(total, prev, acc);
9154
9971
  ctx._fe = pos;
9155
9972
  ctx._fx = acc ?? choiceFx;
9156
9973
  return FAIL;
@@ -9176,21 +9993,27 @@ function assemble(t, prog, cfg) {
9176
9993
  }
9177
9994
  function dispatchBranch(child, usesRouted) {
9178
9995
  if (!usesRouted) {
9179
- return (input, _pos, selEnd, key, _selectorMark, ctx) => {
9180
- const mark = saveTriviaMark(ctx);
9996
+ return (input, _pos, selEnd, key, ctx) => {
9997
+ const need = markCst(ctx);
9998
+ const mRaw = MRAW;
9999
+ const mTl = MTL;
10000
+ const mLv = MLV;
10001
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
10002
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
10003
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
10004
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
9181
10005
  const v = child(input, selEnd, ctx);
9182
10006
  if (v === FAIL) {
9183
- rollbackTrivia(ctx, mark);
10007
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9184
10008
  ctx._fc = true;
9185
10009
  return FAIL;
9186
10010
  }
9187
10011
  return [key, v];
9188
10012
  };
9189
10013
  }
9190
- return (input, pos, selEnd, key, selectorMark, ctx) => {
10014
+ return (input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot) => {
9191
10015
  const savedRouted = ctx._routed;
9192
- rollbackTrivia(ctx, selectorMark);
9193
- const mark = saveTriviaMark(ctx);
10016
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9194
10017
  ctx._routed = { value: key, span: { start: pos, end: selEnd } };
9195
10018
  let v;
9196
10019
  try {
@@ -9199,7 +10022,7 @@ function assemble(t, prog, cfg) {
9199
10022
  ctx._routed = savedRouted;
9200
10023
  }
9201
10024
  if (v === FAIL) {
9202
- rollbackTrivia(ctx, mark);
10025
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9203
10026
  ctx._fc = true;
9204
10027
  return FAIL;
9205
10028
  }
@@ -9207,12 +10030,12 @@ function assemble(t, prog, cfg) {
9207
10030
  };
9208
10031
  }
9209
10032
  function dispatchArmBlock(start, a0, a1, a2, a3, next) {
9210
- return (arm, input, pos, selEnd, key, selectorMark, ctx) => {
9211
- if (arm === start) return a0(input, pos, selEnd, key, selectorMark, ctx);
9212
- if (arm === start + 1) return a1(input, pos, selEnd, key, selectorMark, ctx);
9213
- if (arm === start + 2) return a2(input, pos, selEnd, key, selectorMark, ctx);
9214
- if (arm === start + 3) return a3(input, pos, selEnd, key, selectorMark, ctx);
9215
- return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key, selectorMark, ctx);
10033
+ return (arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot) => {
10034
+ if (arm === start) return a0(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10035
+ if (arm === start + 1) return a1(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10036
+ if (arm === start + 2) return a2(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10037
+ if (arm === start + 3) return a3(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10038
+ return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9216
10039
  };
9217
10040
  }
9218
10041
  function trackLinesInto(ctx, input, end) {
@@ -9229,20 +10052,68 @@ function assemble(t, prog, cfg) {
9229
10052
  if (done !== void 0) return done;
9230
10053
  const flight = inFlight.get(ip);
9231
10054
  if (flight !== void 0) return flight.fwd;
10055
+ const selected = HYBRID?.byIp[ip];
10056
+ if (selected !== void 0) {
10057
+ const piece2 = scanHandoffNeeded(code, ip, closureLabels) ? hybridPiece(selected) : selected;
10058
+ memo.set(ip, piece2);
10059
+ reached.add(ip);
10060
+ return piece2;
10061
+ }
9232
10062
  let target;
9233
10063
  const fwd = (input, pos, ctx) => target(input, pos, ctx);
9234
10064
  const holder = { fwd, set: (p) => {
9235
10065
  target = p;
9236
10066
  } };
9237
10067
  inFlight.set(ip, holder);
9238
- const op = code[ip];
9239
- const piece = (op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[ip + 3] === 0) && code[ip + 1] >= 0 && closureLabels.at(ip).tri === code[ip + 1] ? link(code[ip + 2]) : lower(ip);
10068
+ const piece = scopeIsIdentity(code, ip, closureLabels.at(ip)) ? link(code[ip + 2]) : countedPiece(lookaheadLedNode(ip) ?? lower(ip), ip);
9240
10069
  inFlight.delete(ip);
9241
10070
  holder.set(piece);
9242
10071
  memo.set(ip, piece);
9243
10072
  reached.add(ip);
9244
10073
  return piece;
9245
10074
  }
10075
+ let FIRST_DECIDED;
10076
+ let NODE_BODY;
10077
+ const DECIDED = (_input, pos) => {
10078
+ EC.e = pos;
10079
+ return null;
10080
+ };
10081
+ function lookaheadLedNode(ip) {
10082
+ const op = code[ip];
10083
+ if (op !== OP_NODE && op !== OP_NODE_TRACK || hostCst || REC || cfg.probe || cfg.coverage || cfg.trackLines) return void 0;
10084
+ if (passCollapse(code, ip, hostCst) || gatedPassCollapse(code, ip, hostCst) !== void 0) return void 0;
10085
+ const body = code[ip + 2];
10086
+ const bop = code[body];
10087
+ if (bop !== OP_SEQ && bop !== OP_SEQV && bop !== OP_SEQX) return void 0;
10088
+ const base = bop === OP_SEQX ? body + 3 : body + 2;
10089
+ if (code[bop === OP_SEQX ? body + 2 : body + 1] < 2) return void 0;
10090
+ const first = code[base];
10091
+ const negative = code[first] === OP_NOT;
10092
+ const terminal = negative ? scalarTerminalNotChild(code, first) : code[first] === OP_PEEK ? scalarTerminalPeekChild(code, first) : -1;
10093
+ if (terminal < 0) return void 0;
10094
+ const recognize = scalarFor(terminal);
10095
+ const xf = fx[code[first + 2]];
10096
+ FIRST_DECIDED = DECIDED;
10097
+ NODE_BODY = lower(body);
10098
+ const node = lower(ip);
10099
+ NODE_BODY = void 0;
10100
+ return negative ? (input, pos, ctx) => {
10101
+ if (recognize(input, pos) >= 0) {
10102
+ ctx._fe = pos;
10103
+ ctx._fx = xf;
10104
+ EC.e = pos;
10105
+ return FAIL;
10106
+ }
10107
+ return node(input, pos, ctx);
10108
+ } : (input, pos, ctx) => {
10109
+ if (recognize(input, pos) < 0) {
10110
+ ctx._fe = pos;
10111
+ ctx._fx = xf;
10112
+ return FAIL;
10113
+ }
10114
+ return node(input, pos, ctx);
10115
+ };
10116
+ }
9246
10117
  function lower(ip) {
9247
10118
  const op = code[ip];
9248
10119
  switch (op) {
@@ -9773,7 +10644,12 @@ function assemble(t, prog, cfg) {
9773
10644
  }
9774
10645
  const child = link(code[ip + 1]);
9775
10646
  const xf = fx[code[ip + 2]];
10647
+ const gate = lookaheadClass(code[ip + 1]);
9776
10648
  return (input, pos, ctx) => {
10649
+ if (gate !== null && !classHas2(gate, lead(input, pos))) {
10650
+ EC.e = pos;
10651
+ return null;
10652
+ }
9777
10653
  const need = markCst(ctx);
9778
10654
  const mRaw = MRAW;
9779
10655
  const mTl = MTL;
@@ -9782,8 +10658,10 @@ function assemble(t, prog, cfg) {
9782
10658
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
9783
10659
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
9784
10660
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
10661
+ const probeBest = PROBE ? ctx._probe?.best : void 0;
9785
10662
  const v = child(input, pos, ctx);
9786
10663
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10664
+ if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
9787
10665
  if (v === FAIL) {
9788
10666
  EC.e = pos;
9789
10667
  return null;
@@ -9794,9 +10672,29 @@ function assemble(t, prog, cfg) {
9794
10672
  };
9795
10673
  }
9796
10674
  case OP_PEEK: {
10675
+ const scalarChild = scalarTerminalPeekChild(code, ip);
10676
+ if (scalarChild >= 0) {
10677
+ const recognize = scalarFor(scalarChild);
10678
+ const xf2 = fx[code[ip + 2]];
10679
+ return (input, pos, ctx) => {
10680
+ if (recognize(input, pos) < 0) {
10681
+ ctx._fe = pos;
10682
+ ctx._fx = xf2;
10683
+ return FAIL;
10684
+ }
10685
+ EC.e = pos;
10686
+ return null;
10687
+ };
10688
+ }
9797
10689
  const child = link(code[ip + 1]);
9798
10690
  const xf = fx[code[ip + 2]];
10691
+ const gate = lookaheadClass(code[ip + 1]);
9799
10692
  return (input, pos, ctx) => {
10693
+ if (gate !== null && !classHas2(gate, lead(input, pos))) {
10694
+ ctx._fe = pos;
10695
+ ctx._fx = xf;
10696
+ return FAIL;
10697
+ }
9800
10698
  const need = markCst(ctx);
9801
10699
  const mRaw = MRAW;
9802
10700
  const mTl = MTL;
@@ -9805,8 +10703,10 @@ function assemble(t, prog, cfg) {
9805
10703
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
9806
10704
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
9807
10705
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
10706
+ const probeBest = PROBE ? ctx._probe?.best : void 0;
9808
10707
  const v = child(input, pos, ctx);
9809
10708
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10709
+ if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
9810
10710
  if (v === FAIL) {
9811
10711
  ctx._fe = pos;
9812
10712
  ctx._fx = xf;
@@ -9818,8 +10718,14 @@ function assemble(t, prog, cfg) {
9818
10718
  }
9819
10719
  case OP_OPT: {
9820
10720
  const child = link(code[ip + 1]);
10721
+ const gate = lookaheadClass(code[ip + 1]);
10722
+ const childClean = CLEAN(code[ip + 1]);
9821
10723
  return (input, pos, ctx) => {
9822
- const need = markCst(ctx);
10724
+ if (gate !== null && !classHas2(gate, lead(input, pos))) {
10725
+ EC.e = pos;
10726
+ return null;
10727
+ }
10728
+ const need = !childClean && markCst(ctx);
9823
10729
  const mRaw = MRAW;
9824
10730
  const mTl = MTL;
9825
10731
  const mLv = MLV;
@@ -10017,6 +10923,9 @@ function assemble(t, prog, cfg) {
10017
10923
  const projection = reducer < 0 ? ~reducer : -1;
10018
10924
  const fn = fused && projection < 0 ? fns[reducer] : void 0;
10019
10925
  const step = closureLabels.at(ip).buf ? nextTermBuffered : nextTerm;
10926
+ const decided = FIRST_DECIDED;
10927
+ FIRST_DECIDED = void 0;
10928
+ const linkFirst = () => decided ?? link(code[base]);
10020
10929
  const runnerBlock = (count, r0, r1, r2, r3, next) => {
10021
10930
  if (count === 1) return (input, cur, ctx, values, inherited) => {
10022
10931
  cur = r0(input, cur, ctx, inherited);
@@ -10062,7 +10971,7 @@ function assemble(t, prog, cfg) {
10062
10971
  };
10063
10972
  };
10064
10973
  if (REC) {
10065
- const first2 = link(code[base]);
10974
+ const first2 = linkFirst();
10066
10975
  const firstSync = sentinelFor(code[base + n]);
10067
10976
  const runnerAt = (i) => {
10068
10977
  const sync = sentinelFor(code[base + n + i]);
@@ -10098,13 +11007,13 @@ function assemble(t, prog, cfg) {
10098
11007
  const bindRunners = (start) => {
10099
11008
  const count = Math.min(4, n - start);
10100
11009
  const at = (offset) => runnerAt(start + offset);
10101
- const never = () => -1;
11010
+ const never2 = () => -1;
10102
11011
  return runnerBlock(
10103
11012
  count,
10104
11013
  at(0),
10105
- count > 1 ? at(1) : never,
10106
- count > 2 ? at(2) : never,
10107
- count > 3 ? at(3) : never,
11014
+ count > 1 ? at(1) : never2,
11015
+ count > 2 ? at(2) : never2,
11016
+ count > 3 ? at(3) : never2,
10108
11017
  start + count < n ? bindRunners(start + count) : void 0
10109
11018
  );
10110
11019
  };
@@ -10154,15 +11063,31 @@ function assemble(t, prog, cfg) {
10154
11063
  let hasAdj = false;
10155
11064
  for (let i = 1; i < n; i++) {
10156
11065
  const kidIp = code[base + i];
10157
- if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp)) {
11066
+ if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp) || holdsGap(code, k, base, n, i, NULLABLE)) {
10158
11067
  hasAdj = true;
10159
11068
  break;
10160
11069
  }
10161
11070
  }
10162
11071
  if (hasAdj) {
10163
- const first2 = link(code[base]);
11072
+ const first2 = linkFirst();
10164
11073
  const runnerAt = (i) => {
10165
11074
  const kidIp = code[base + i];
11075
+ if (holdsGap(code, k, base, n, i, NULLABLE)) {
11076
+ const kid = link(kidIp);
11077
+ return (input, cur, ctx) => {
11078
+ if (ctx.trivia === void 0) {
11079
+ const v2 = kid(input, cur, ctx);
11080
+ if (v2 === FAIL) return -1;
11081
+ TERMV = v2;
11082
+ return EC.e;
11083
+ }
11084
+ const scanEnd = skipTrivia(input, cur, ctx);
11085
+ const v = kid(input, scanEnd, ctx);
11086
+ if (v === FAIL) return -1;
11087
+ TERMV = v;
11088
+ return scanEnd;
11089
+ };
11090
+ }
10166
11091
  if (code[kidIp] !== OP_ADJ) {
10167
11092
  const kid = link(kidIp);
10168
11093
  if (leadingTriviaFieldAt(code, k, kidIp)) {
@@ -10187,13 +11112,13 @@ function assemble(t, prog, cfg) {
10187
11112
  const bindRunners = (start) => {
10188
11113
  const count = Math.min(4, n - start);
10189
11114
  const at = (offset) => runnerAt(start + offset);
10190
- const never = () => -1;
11115
+ const never2 = () => -1;
10191
11116
  return runnerBlock(
10192
11117
  count,
10193
11118
  at(0),
10194
- count > 1 ? at(1) : never,
10195
- count > 2 ? at(2) : never,
10196
- count > 3 ? at(3) : never,
11119
+ count > 1 ? at(1) : never2,
11120
+ count > 2 ? at(2) : never2,
11121
+ count > 3 ? at(3) : never2,
10197
11122
  start + count < n ? bindRunners(start + count) : void 0
10198
11123
  );
10199
11124
  };
@@ -10230,7 +11155,7 @@ function assemble(t, prog, cfg) {
10230
11155
  };
10231
11156
  }
10232
11157
  if (n === 1) {
10233
- const k0 = link(code[base]);
11158
+ const k0 = linkFirst();
10234
11159
  if (fused) {
10235
11160
  return (input, pos, ctx) => {
10236
11161
  const v = k0(input, pos, ctx);
@@ -10252,7 +11177,7 @@ function assemble(t, prog, cfg) {
10252
11177
  };
10253
11178
  }
10254
11179
  if (n === 2) {
10255
- const k0 = link(code[base]), k1 = link(code[base + 1]);
11180
+ const k0 = linkFirst(), k1 = link(code[base + 1]);
10256
11181
  if (fused) {
10257
11182
  return (input, pos, ctx) => {
10258
11183
  const v0 = k0(input, pos, ctx);
@@ -10283,7 +11208,7 @@ function assemble(t, prog, cfg) {
10283
11208
  };
10284
11209
  }
10285
11210
  if (n === 3) {
10286
- const k0 = link(code[base]), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
11211
+ const k0 = linkFirst(), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
10287
11212
  if (fused) {
10288
11213
  return (input, pos, ctx) => {
10289
11214
  const v0 = k0(input, pos, ctx);
@@ -10377,7 +11302,7 @@ function assemble(t, prog, cfg) {
10377
11302
  start + count < n ? bind(start + count) : void 0
10378
11303
  );
10379
11304
  };
10380
- const first = link(code[base]);
11305
+ const first = linkFirst();
10381
11306
  const tail = bind(1);
10382
11307
  const runDirectTerms = (input, pos, ctx, values) => {
10383
11308
  const v0 = first(input, pos, ctx);
@@ -10416,6 +11341,8 @@ function assemble(t, prog, cfg) {
10416
11341
  const n = code[ip + 2];
10417
11342
  const choiceFx = fx[code[ip + 3]];
10418
11343
  const base = ip + 4;
11344
+ for (let i = 0; i < n; i++) link(code[base + i]);
11345
+ const armsClean = CLEAN(ip);
10419
11346
  if (table.exclusive) {
10420
11347
  const ascii = table.ascii;
10421
11348
  const hi = table.hi;
@@ -10555,7 +11482,7 @@ function assemble(t, prog, cfg) {
10555
11482
  if (n === 3) addGate(g2, 4);
10556
11483
  return (input, pos, ctx) => {
10557
11484
  const c = lead(input, pos);
10558
- const need = markCst(ctx);
11485
+ const need = !armsClean && markCst(ctx);
10559
11486
  const mRaw = MRAW;
10560
11487
  const mTl = MTL;
10561
11488
  const mLv = MLV;
@@ -10625,6 +11552,11 @@ function assemble(t, prog, cfg) {
10625
11552
  }
10626
11553
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10627
11554
  }
11555
+ if (prev === 0) {
11556
+ ctx._fe = pos;
11557
+ ctx._fx = choiceFx;
11558
+ return FAIL;
11559
+ }
10628
11560
  if (best === pos && prev < 1) acc = accSet(e0, acc);
10629
11561
  if (best === pos && prev < 2) acc = accSet(e1, acc);
10630
11562
  if (best === pos && n === 3 && prev < 3) acc = accSet(e2, acc);
@@ -10767,7 +11699,7 @@ function assemble(t, prog, cfg) {
10767
11699
  if (pn !== 0) {
10768
11700
  return (input, pos, ctx) => {
10769
11701
  const c = lead(input, pos);
10770
- const need = markCst(ctx);
11702
+ const need = !armsClean && markCst(ctx);
10771
11703
  const mRaw = MRAW;
10772
11704
  const mTl = MTL;
10773
11705
  const mLv = MLV;
@@ -10824,7 +11756,7 @@ function assemble(t, prog, cfg) {
10824
11756
  }
10825
11757
  return (input, pos, ctx) => {
10826
11758
  const c = lead(input, pos);
10827
- const need = markCst(ctx);
11759
+ const need = !armsClean && markCst(ctx);
10828
11760
  const mRaw = MRAW;
10829
11761
  const mTl = MTL;
10830
11762
  const mLv = MLV;
@@ -10872,7 +11804,7 @@ function assemble(t, prog, cfg) {
10872
11804
  }
10873
11805
  return (input, pos, ctx) => {
10874
11806
  const c = lead(input, pos);
10875
- const need = markCst(ctx);
11807
+ const need = !armsClean && markCst(ctx);
10876
11808
  const mRaw = MRAW;
10877
11809
  const mTl = MTL;
10878
11810
  const mLv = MLV;
@@ -10926,6 +11858,21 @@ function assemble(t, prog, cfg) {
10926
11858
  return lit(input, pos, ctx);
10927
11859
  };
10928
11860
  }
11861
+ case OP_RGATE: {
11862
+ const cls = cc[code[ip + 1]];
11863
+ const xf = fx[code[ip + 3]];
11864
+ const child = link(code[ip + 2]);
11865
+ if (cfg.tolerant || cfg.probe) return child;
11866
+ return (input, pos, ctx) => {
11867
+ const item = ctx._routed;
11868
+ if (item !== void 0 && item.span.start === pos && !classHas2(cls, lead(input, item.span.end))) {
11869
+ ctx._fe = item.span.end;
11870
+ ctx._fx = xf;
11871
+ return FAIL;
11872
+ }
11873
+ return child(input, pos, ctx);
11874
+ };
11875
+ }
10929
11876
  case OP_ARMGATE: {
10930
11877
  const pred = fns[code[ip + 1]];
10931
11878
  const child = link(code[ip + 2]);
@@ -10933,7 +11880,7 @@ function assemble(t, prog, cfg) {
10933
11880
  return (input, pos, ctx) => {
10934
11881
  if (!pred(ctx.state)) {
10935
11882
  ctx._fc = false;
10936
- ctx._fe = pos;
11883
+ ctx._fe = -1;
10937
11884
  ctx._fx = xf;
10938
11885
  return FAIL;
10939
11886
  }
@@ -10994,6 +11941,7 @@ function assemble(t, prog, cfg) {
10994
11941
  const itemClass = !REC && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
10995
11942
  const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
10996
11943
  const skipBeforeFirst = sepIp < 0 && min === 0;
11944
+ const itemClean = sepIp < 0 && CLEAN(code[ip + 1]) && !rowNullable(code, k, code[ip + 1], NULLABLE);
10997
11945
  if (REC) {
10998
11946
  const itemFx2 = fx[code[ip + 6]];
10999
11947
  const sepSent = sentinelFor(code[ip + 7]);
@@ -11090,6 +12038,8 @@ function assemble(t, prog, cfg) {
11090
12038
  const out = collect ? [] : void 0;
11091
12039
  const hasTrivia = ctx.trivia !== void 0;
11092
12040
  const needMark = rollbackNeeded(ctx);
12041
+ const markLater = needMark && (!itemClean || hasTrivia);
12042
+ const markFirst = needMark && (!itemClean || hasTrivia && skipBeforeFirst);
11093
12043
  const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
11094
12044
  let cur = pos;
11095
12045
  let count = 0;
@@ -11097,14 +12047,15 @@ function assemble(t, prog, cfg) {
11097
12047
  if (max >= 0 && count >= max) break;
11098
12048
  if (sep !== void 0 && count > 0 && count >= min && cur >= input.length) break;
11099
12049
  if (count >= min && sep === void 0 && !hasTrivia && gateItems && !itemMayStart(input, cur)) break;
11100
- if (needMark) markCst(ctx);
11101
- const mRaw = needMark ? MRAW : 0;
11102
- const mTl = needMark ? MTL : 0;
11103
- const mLv = needMark ? MLV : 0;
11104
- const mFl = needMark ? ctx._fields?.length ?? 0 : 0;
11105
- const mEr = needMark ? ctx._errors?.length ?? 0 : 0;
11106
- const mLog = needMark ? ctx._triviaLog?.length ?? 0 : 0;
11107
- const mRoot = needMark ? ctx._rootTriviaLog?.length ?? 0 : 0;
12050
+ const markIt = count > 0 ? markLater : markFirst;
12051
+ if (markIt) markCst(ctx);
12052
+ const mRaw = markIt ? MRAW : 0;
12053
+ const mTl = markIt ? MTL : 0;
12054
+ const mLv = markIt ? MLV : 0;
12055
+ const mFl = markIt ? ctx._fields?.length ?? 0 : 0;
12056
+ const mEr = markIt ? ctx._errors?.length ?? 0 : 0;
12057
+ const mLog = markIt ? ctx._triviaLog?.length ?? 0 : 0;
12058
+ const mRoot = markIt ? ctx._rootTriviaLog?.length ?? 0 : 0;
11108
12059
  let itemStart = cur;
11109
12060
  let sepEnd = -1;
11110
12061
  const viaRepItem = sep === void 0 && count >= min && (count > 0 || skipBeforeFirst);
@@ -11116,7 +12067,7 @@ function assemble(t, prog, cfg) {
11116
12067
  if (sepLeads) LEAD.at = cur;
11117
12068
  const sv = sep(input, sp, ctx);
11118
12069
  if (sv === FAIL) {
11119
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12070
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11120
12071
  if (committed3(ctx)) return FAIL;
11121
12072
  break;
11122
12073
  }
@@ -11127,25 +12078,25 @@ function assemble(t, prog, cfg) {
11127
12078
  itemStart = skipTrivia(input, itemStart, ctx);
11128
12079
  }
11129
12080
  if (itemStart >= input.length && viaRepItem) {
11130
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12081
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11131
12082
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
11132
12083
  break;
11133
12084
  }
11134
12085
  if (count >= min && gateItems && !itemMayStart(input, itemStart)) {
11135
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12086
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11136
12087
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
11137
12088
  break;
11138
12089
  }
11139
12090
  ctx._fc = false;
11140
12091
  const v = child(input, itemStart, ctx);
11141
12092
  if (v === FAIL) {
11142
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12093
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11143
12094
  if (committed3(ctx)) return FAIL;
11144
12095
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
11145
12096
  break;
11146
12097
  }
11147
12098
  if (EC.e === itemStart && viaRepItem) {
11148
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12099
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11149
12100
  break;
11150
12101
  }
11151
12102
  if (out !== void 0) out.push(v);
@@ -11219,7 +12170,14 @@ function assemble(t, prog, cfg) {
11219
12170
  const runArm = n === 0 ? void 0 : bindArms(0);
11220
12171
  const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted);
11221
12172
  return (input, pos, ctx) => {
11222
- const selectorMark = saveTriviaMark(ctx);
12173
+ const need = markCst(ctx);
12174
+ const mRaw = MRAW;
12175
+ const mTl = MTL;
12176
+ const mLv = MLV;
12177
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
12178
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
12179
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
12180
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
11223
12181
  const selVal = selector(input, pos, ctx);
11224
12182
  if (selVal === FAIL) return FAIL;
11225
12183
  const selEnd = EC.e;
@@ -11231,9 +12189,9 @@ function assemble(t, prog, cfg) {
11231
12189
  ctx._fx = expected;
11232
12190
  return FAIL;
11233
12191
  }
11234
- return runOther(input, pos, selEnd, key, selectorMark, ctx);
12192
+ return runOther(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11235
12193
  }
11236
- return runArm(arm, input, pos, selEnd, key, selectorMark, ctx);
12194
+ return runArm(arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11237
12195
  };
11238
12196
  }
11239
12197
  /* ── node ────────────────────────────────────────────────────────────── */
@@ -11256,9 +12214,9 @@ function assemble(t, prog, cfg) {
11256
12214
  return FAIL;
11257
12215
  }
11258
12216
  const value = regexValue ? input.slice(pos, end) : spec;
11259
- const leaf = { _tag: "leaf", value, span: { start: pos, end } };
11260
- const kids = [leaf];
11261
- const rawKids = [leaf];
12217
+ const leaf2 = { _tag: "leaf", value, span: { start: pos, end } };
12218
+ const kids = [leaf2];
12219
+ const rawKids = [leaf2];
11262
12220
  const span = { start: pos, end };
11263
12221
  EC.e = end;
11264
12222
  const nd = build2(kids, void 0, span, rawKids, EMPTY_TL, void 0);
@@ -11269,7 +12227,8 @@ function assemble(t, prog, cfg) {
11269
12227
  return nd;
11270
12228
  };
11271
12229
  }
11272
- const child = link(code[ip + 2]);
12230
+ const child = NODE_BODY ?? link(code[ip + 2]);
12231
+ NODE_BODY = void 0;
11273
12232
  const proj = code[ip + 4];
11274
12233
  const buildIdx = code[ip + 1];
11275
12234
  const type = k[code[ip + 5]];
@@ -11293,6 +12252,30 @@ function assemble(t, prog, cfg) {
11293
12252
  if (build !== void 0 && proj < 0 && flags === 18) {
11294
12253
  return childrenOnlyFieldsBuildNode(child, build);
11295
12254
  }
12255
+ if (build !== void 0 && passCollapse(code, ip, hostCst)) {
12256
+ return passCollapseNode(child, build, flags === 32);
12257
+ }
12258
+ const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
12259
+ const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(closureLabels.at(code[ip + 2]).tri, trivia2);
12260
+ if (build !== void 0 && gated !== void 0 && triviaLead !== void 0) {
12261
+ const classic = flags === 32 ? collapseBuildNode(child, build) : childrenOnlyCollapseBuildNode(child, build);
12262
+ return gatedPassCollapseNode(
12263
+ [
12264
+ ...gated.leads.map((g) => cc[code[g + 1]]),
12265
+ resolveClass(encodeClassSpec([
12266
+ ...triviaLead,
12267
+ ...gated.lits.map((i) => {
12268
+ const c = k[i].codePointAt(0);
12269
+ return { lo: c, hi: c };
12270
+ })
12271
+ ]))
12272
+ ],
12273
+ link(gated.last),
12274
+ classic,
12275
+ build,
12276
+ flags === 32
12277
+ );
12278
+ }
11296
12279
  if (build !== void 0 && proj < 0 && flags === 32) {
11297
12280
  return collapseBuildNode(child, build);
11298
12281
  }
@@ -11339,7 +12322,7 @@ function assemble(t, prog, cfg) {
11339
12322
  if (v === FAIL) return FAIL;
11340
12323
  const end = EC.e;
11341
12324
  const span = tracked ? spanLines(ctx, pos, end) : { start: pos, end };
11342
- const st = readsState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
12325
+ const st = readsState ? ctx.state : void 0;
11343
12326
  let nd;
11344
12327
  if (unwrap && kids.length === 1) {
11345
12328
  nd = unwrapChild(kids[0]);
@@ -11352,10 +12335,10 @@ function assemble(t, prog, cfg) {
11352
12335
  ) {
11353
12336
  nd = kids[0];
11354
12337
  } else if (proj >= 0) {
11355
- nd = hostCst && host !== void 0 ? host(type, kids, fieldMap, span, rawKids, tlog, readsState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0, tags) : projectChild(kids, proj, type);
12338
+ nd = hostCst && host !== void 0 ? host(type, kids, fieldMap, span, rawKids, tlog, ctx.state, tags) : projectChild(kids, proj, type);
11356
12339
  } else if (build !== void 0) {
11357
12340
  if (hostCst && host !== void 0) {
11358
- nd = host(type, kids, fieldMap, span, rawKids, tlog, readsState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0, tags);
12341
+ nd = host(type, kids, fieldMap, span, rawKids, tlog, ctx.state, tags);
11359
12342
  } else {
11360
12343
  nd = build(kids, fieldMap, span, rawKids, captureWide ? tlog : EMPTY_TL, st);
11361
12344
  }
@@ -11406,9 +12389,7 @@ function assemble(t, prog, cfg) {
11406
12389
  let emitRefusal;
11407
12390
  let emitReached;
11408
12391
  {
11409
- const extraIps = [];
11410
- for (const s of prog.scans ?? []) for (const r of scanRefs(s)) extraIps.push(r[0]);
11411
- for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
12392
+ const extraIps = assemblyExtraIps(prog);
11412
12393
  const roots = [...Object.values(prog.rules), ...extraIps];
11413
12394
  for (const ip of reachableSites(code, roots)) {
11414
12395
  if (code[ip] === OP_DISPATCH) {
@@ -11443,6 +12424,8 @@ function assemble(t, prog, cfg) {
11443
12424
  }
11444
12425
  const notChild = scalarTerminalNotChild(code, ip);
11445
12426
  if (notChild >= 0) scalarFor(notChild);
12427
+ const peekChild = scalarTerminalPeekChild(code, ip);
12428
+ if (peekChild >= 0) scalarFor(peekChild);
11446
12429
  }
11447
12430
  const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
11448
12431
  if (pre !== void 0) {
@@ -11501,9 +12484,12 @@ function assemble(t, prog, cfg) {
11501
12484
  adjacencyHolds,
11502
12485
  t.lexPrograms,
11503
12486
  LEAD,
11504
- triviaFieldCapture
12487
+ triviaFieldCapture,
12488
+ skipDeferredTrivia,
12489
+ collapseEmpty
11505
12490
  );
11506
12491
  emitReached = new Set(pre.reached);
12492
+ if (emitted.ext !== void 0) HYBRID = emitted;
11507
12493
  }
11508
12494
  try {
11509
12495
  if (emitted !== void 0) throw new ServedByBuild();
@@ -11585,7 +12571,9 @@ function assemble(t, prog, cfg) {
11585
12571
  adjacencyHolds,
11586
12572
  t.lexPrograms,
11587
12573
  LEAD,
11588
- triviaFieldCapture
12574
+ triviaFieldCapture,
12575
+ skipDeferredTrivia,
12576
+ collapseEmpty
11589
12577
  );
11590
12578
  emitReached = em.reached;
11591
12579
  } catch (e) {
@@ -11596,7 +12584,7 @@ function assemble(t, prog, cfg) {
11596
12584
  }
11597
12585
  function pieceAt(ip) {
11598
12586
  const em = emitted;
11599
- if (em !== void 0) {
12587
+ if (em !== void 0 && HYBRID === void 0) {
11600
12588
  const p = em.byIp[ip];
11601
12589
  if (p === void 0) throw new Error(`table emitter: no emitted body for site ${ip}`);
11602
12590
  return p;
@@ -11626,6 +12614,37 @@ function assemble(t, prog, cfg) {
11626
12614
  }
11627
12615
  const scans = scansArr;
11628
12616
  const scanSkip = (prog.scanSkip ?? []).map((set) => set.map((r) => subtreeComb(r)));
12617
+ if (HYBRID !== void 0) {
12618
+ const em = HYBRID;
12619
+ em.bind(
12620
+ (s) => {
12621
+ const saved = SCAN;
12622
+ SCAN = s;
12623
+ return saved;
12624
+ },
12625
+ em.ext.map((ip) => link(ip))
12626
+ );
12627
+ const pieces2 = {};
12628
+ for (const [name, entryIp] of Object.entries(prog.rules)) {
12629
+ pieces2[name] = em.pieces[name] ?? link(entryIp);
12630
+ }
12631
+ for (const ip of emitReached) reached.add(ip);
12632
+ return {
12633
+ pieces: pieces2,
12634
+ end: () => EC.e,
12635
+ begin: (ctx) => {
12636
+ begin(ctx);
12637
+ em.begin(ctx);
12638
+ },
12639
+ finish: () => {
12640
+ em.finish();
12641
+ finish();
12642
+ },
12643
+ scanSkip,
12644
+ reached,
12645
+ emitRefusal: void 0
12646
+ };
12647
+ }
11629
12648
  if (emitted !== void 0) {
11630
12649
  const em = emitted;
11631
12650
  return {
@@ -11661,6 +12680,15 @@ function assemble(t, prog, cfg) {
11661
12680
  }
11662
12681
  return { pieces, end: () => EC.e, begin, finish, scanSkip, reached, emitRefusal };
11663
12682
  }
12683
+ var SITE_COUNTS;
12684
+ function countedPiece(piece, ip) {
12685
+ const counts = SITE_COUNTS;
12686
+ if (counts === void 0) return piece;
12687
+ return (input, pos, ctx) => {
12688
+ counts[ip]++;
12689
+ return piece(input, pos, ctx);
12690
+ };
12691
+ }
11664
12692
  var AssemblyCache = class {
11665
12693
  t;
11666
12694
  prog;
@@ -11803,6 +12831,172 @@ function tableRules(source, metadataOrEntry = {}) {
11803
12831
  return map[entry];
11804
12832
  }
11805
12833
 
12834
+ // src/combinators/grammar.ts
12835
+ function annotateResultLines(result, index) {
12836
+ const annotated = { ...result, span: annotateSpan(result.span, index) };
12837
+ const errors = annotated.errors;
12838
+ if (errors) {
12839
+ ;
12840
+ annotated.errors = errors.map((error) => ({
12841
+ ...error,
12842
+ span: annotateSpan(error.span, index)
12843
+ }));
12844
+ }
12845
+ return annotated;
12846
+ }
12847
+ function createParseLineContext(input, pos) {
12848
+ const lineIndex = createLineIndex();
12849
+ if (pos > 0) recordLineRange(lineIndex, input, 0, pos);
12850
+ return { lineIndex, lineScannedTo: pos };
12851
+ }
12852
+ var TRACK_LINES_ON = () => true;
12853
+ var TRACK_LINES_OFF = () => false;
12854
+ var TRACK_LINES_INHERIT = (ctx) => ctx?.trackLines === true;
12855
+ function parser(opts, root) {
12856
+ const clearTrivia = opts.trivia === null;
12857
+ const opaqueRootCapture = opts.rootCapture === "opaque";
12858
+ if (opaqueRootCapture && opts.trivia === void 0) {
12859
+ throw new TypeError("parser({ rootCapture: 'opaque' }) requires an explicit trivia scope.");
12860
+ }
12861
+ const scopeTrivia = clearTrivia ? void 0 : opts.trivia ?? void 0;
12862
+ const scopeLabels = scopeTrivia?._meta?.triviaKindLabels;
12863
+ const refuseUnclassified = scopeTrivia !== void 0 && !scopeTrivia._meta?.rootTriviaClassified && !opaqueRootCapture;
12864
+ const forceCaptureTrivia = opts.captureTrivia === true;
12865
+ const trackLinesPolicy = opts.trackLines === true ? "on" : opts.trackLines === false ? "off" : "inherit";
12866
+ const trackLinesOf = trackLinesPolicy === "on" ? TRACK_LINES_ON : trackLinesPolicy === "off" ? TRACK_LINES_OFF : TRACK_LINES_INHERIT;
12867
+ const captureKinds = clearTrivia ? void 0 : opts.captureTriviaKinds;
12868
+ const ownCaptureMask = captureKinds === void 0 ? void 0 : scopeLabels !== void 0 ? triviaKindMask(scopeLabels, captureKinds) : void 0;
12869
+ const inheritCaptureMask = captureKinds !== void 0 && scopeLabels === void 0;
12870
+ const rootScalar = scalarOf(root);
12871
+ const scalarEligible = opts.trackLines !== true && opts.recover !== true && !opaqueRootCapture && !forceCaptureTrivia && captureKinds === void 0;
12872
+ const parseScalar = scalarEligible ? (input, pos, ctx) => {
12873
+ const savedTrivia = ctx.trivia;
12874
+ const savedLabels = ctx.triviaKindLabels;
12875
+ if (clearTrivia) {
12876
+ ctx.trivia = void 0;
12877
+ ctx.triviaKindLabels = void 0;
12878
+ } else if (scopeTrivia !== void 0) {
12879
+ ctx.trivia = scopeTrivia;
12880
+ ctx.triviaKindLabels = scopeLabels;
12881
+ }
12882
+ const end = rootScalar(input, pos, ctx);
12883
+ ctx.trivia = savedTrivia;
12884
+ ctx.triviaKindLabels = savedLabels;
12885
+ return end;
12886
+ } : void 0;
12887
+ let publicScalar;
12888
+ const grammar = {
12889
+ _tag: "grammar",
12890
+ _meta: {
12891
+ ...root._meta,
12892
+ // Trivia classification describes this grammar's own active trivia
12893
+ // scope. A directly nested grammar may have classified trivia of its
12894
+ // own, but that must not advertise classification for this wrapper.
12895
+ triviaKindLabels: void 0,
12896
+ rootTriviaClassified: void 0,
12897
+ ...opts.trivia?._meta?.triviaKindLabels ? { triviaKindLabels: opts.trivia._meta.triviaKindLabels } : {},
12898
+ ...opts.trivia?._meta?.rootTriviaClassified ? { rootTriviaClassified: true } : {}
12899
+ },
12900
+ _def: {
12901
+ tag: "grammar",
12902
+ parser: root,
12903
+ triviaParser: scopeTrivia,
12904
+ clearTrivia,
12905
+ ...opaqueRootCapture ? { rootCapture: "opaque" } : {},
12906
+ ...opts.captureTrivia ? { captureTrivia: true } : {},
12907
+ trackLines: opts.trackLines ?? false,
12908
+ constructionTrackLines: trackLinesPolicy,
12909
+ ...captureKinds === void 0 ? {} : { constructionCaptureTriviaKinds: captureKinds }
12910
+ },
12911
+ _parseScalar: parseScalar,
12912
+ parse(input, pos, _ctx) {
12913
+ if (pos === void 0 && _ctx === void 0) {
12914
+ publicScalar ??= scalarRootOf(grammar) ?? null;
12915
+ if (publicScalar) {
12916
+ const ctx2 = createParseContext();
12917
+ const end = publicScalar(input, 0, ctx2);
12918
+ if (end < 0) {
12919
+ const at = ~end;
12920
+ return { ok: false, expected: ctx2._fx ?? [], span: { start: at, end: at } };
12921
+ }
12922
+ return { ok: true, value: ctx2._sv, span: { start: 0, end } };
12923
+ }
12924
+ }
12925
+ if (refuseUnclassified) refuseUnclassifiedRootScope(_ctx?._rootTriviaStrictScopes);
12926
+ const trackLines = trackLinesOf(_ctx);
12927
+ const lineContext = trackLines && _ctx?._lineIndex === void 0 && _ctx?._lineStarts === void 0 ? createParseLineContext(input, pos ?? 0) : void 0;
12928
+ const lineIndex = trackLines ? _ctx?._lineIndex ?? (_ctx?._lineStarts ? { lineStarts: _ctx._lineStarts } : lineContext.lineIndex) : void 0;
12929
+ const ctx = _ctx === void 0 ? createParseContext() : { ..._ctx };
12930
+ ctx.trackLines = trackLines;
12931
+ if (lineIndex) ctx._lineIndex = lineIndex;
12932
+ if (lineContext) ctx._lineScannedTo = lineContext.lineScannedTo;
12933
+ if (clearTrivia) {
12934
+ ctx.trivia = void 0;
12935
+ ctx.triviaKindLabels = void 0;
12936
+ } else if (scopeTrivia !== void 0) {
12937
+ ctx.trivia = scopeTrivia;
12938
+ if (scopeLabels) ctx.triviaKindLabels = scopeLabels;
12939
+ }
12940
+ if (forceCaptureTrivia || _ctx?.captureTrivia) ctx.captureTrivia = true;
12941
+ if (ownCaptureMask !== void 0) ctx._triviaCaptureMask = ownCaptureMask;
12942
+ else if (inheritCaptureMask) ctx._triviaCaptureMask = triviaKindMask(_ctx?.triviaKindLabels, captureKinds);
12943
+ if (opaqueRootCapture) ctx._rootTriviaCapture = false;
12944
+ const result = root.parse(input, pos ?? 0, ctx);
12945
+ if (trackLines && _ctx && ctx._lineScannedTo !== void 0) {
12946
+ _ctx._lineScannedTo = Math.max(_ctx._lineScannedTo ?? 0, ctx._lineScannedTo);
12947
+ }
12948
+ return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
12949
+ }
12950
+ };
12951
+ return grammar;
12952
+ }
12953
+ function noTrivia(root) {
12954
+ return parser({ trivia: null }, root);
12955
+ }
12956
+
12957
+ // src/combinators/attempt.ts
12958
+ function containOption(options) {
12959
+ if (options === void 0) return false;
12960
+ for (const key of Object.keys(options)) {
12961
+ if (key !== "contain") throw new TypeError(`attempt(): unknown option ${JSON.stringify(key)}`);
12962
+ }
12963
+ if (options.contain !== void 0 && typeof options.contain !== "boolean") {
12964
+ throw new TypeError("attempt(): `contain` must be a boolean");
12965
+ }
12966
+ return options.contain === true;
12967
+ }
12968
+ function attempt(parser2, options) {
12969
+ const contain = containOption(options);
12970
+ const guardable = parser2._meta.firstSet.kind !== "any" && !matchesEmpty(parser2);
12971
+ let failExpected;
12972
+ return {
12973
+ _tag: "attempt",
12974
+ _meta: parser2._meta,
12975
+ _def: contain ? { tag: "attempt", parser: parser2, contain: true } : { tag: "attempt", parser: parser2 },
12976
+ parse(input, pos, ctx) {
12977
+ if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(parser2, input, pos)) {
12978
+ if (failExpected === void 0) {
12979
+ const e = deriveExpected(parser2);
12980
+ failExpected = e.length > 0 ? e : [parser2._tag];
12981
+ }
12982
+ return { ok: false, expected: failExpected, span: { start: pos, end: pos } };
12983
+ }
12984
+ const mark = saveCstMark(ctx);
12985
+ const log = ctx._triviaLog?.length;
12986
+ const rootLog = ctx._rootTriviaLog?.length;
12987
+ const split = ctx._columnsSplit;
12988
+ const result = parser2.parse(input, pos, ctx);
12989
+ if (result.ok) return result;
12990
+ rollbackCstCapture(ctx, mark);
12991
+ ctx._columnsSplit = split;
12992
+ if (log !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== log) ctx._triviaLog.length = log;
12993
+ if (rootLog !== void 0 && ctx._rootTriviaLog && ctx._rootTriviaLog.length !== rootLog) ctx._rootTriviaLog.length = rootLog;
12994
+ if (result.committed && !contain) return result;
12995
+ return { ok: false, expected: result.expected, span: { start: pos, end: pos } };
12996
+ }
12997
+ };
12998
+ }
12999
+
11806
13000
  // src/analysis/gating.ts
11807
13001
  function childrenOf(d) {
11808
13002
  switch (d.tag) {
@@ -12270,6 +13464,111 @@ function reachesMarked(root, successors, memo) {
12270
13464
  return found[visit(root)];
12271
13465
  }
12272
13466
 
13467
+ // src/table/factor-choice.ts
13468
+ var DERIVED = /* @__PURE__ */ new Set(["_tag", "_meta", "_def", "_parseScalar", "_stickyRegex", "parse"]);
13469
+ function isCombinator(v) {
13470
+ return typeof v === "object" && v !== null && "_def" in v && "_meta" in v;
13471
+ }
13472
+ function sameComb(a, b, depth) {
13473
+ if (a === b) return true;
13474
+ if (depth > 32 || a._tag !== b._tag) return false;
13475
+ for (const k of Object.keys(a)) if (!DERIVED.has(k)) return false;
13476
+ for (const k of Object.keys(b)) if (!DERIVED.has(k)) return false;
13477
+ return sameFields(a._def, b._def, depth, void 0);
13478
+ }
13479
+ function sameValue(u, v, depth) {
13480
+ if (u === v) return true;
13481
+ if (isCombinator(u) && isCombinator(v)) return sameComb(u, v, depth + 1);
13482
+ if (Array.isArray(u) && Array.isArray(v)) return u.length === v.length && u.every((x, i) => sameValue(x, v[i], depth));
13483
+ if (typeof u === "object" && u !== null && typeof v === "object" && v !== null && Object.getPrototypeOf(u) === Object.prototype && Object.getPrototypeOf(v) === Object.prototype) {
13484
+ return sameFields(u, v, depth, void 0);
13485
+ }
13486
+ return false;
13487
+ }
13488
+ function sameFields(x, y, depth, skip) {
13489
+ const kx = Object.keys(x).filter((k) => k !== skip && x[k] !== void 0);
13490
+ const ky = Object.keys(y).filter((k) => k !== skip && y[k] !== void 0);
13491
+ if (kx.length !== ky.length) return false;
13492
+ for (const k of kx) {
13493
+ if (!(k in y)) return false;
13494
+ const u = x[k];
13495
+ const v = y[k];
13496
+ if (k === "fn" && typeof u === "function" && typeof v === "function" && u !== v) {
13497
+ if (typeof x.fnSrc !== "string" || x.fnSrc === "" || x.fnSrc !== y.fnSrc) return false;
13498
+ continue;
13499
+ }
13500
+ if (!sameValue(u, v, depth)) return false;
13501
+ }
13502
+ return true;
13503
+ }
13504
+ function rewrap(w, body) {
13505
+ const d = w._def;
13506
+ let out;
13507
+ if (d.tag === "leaf") {
13508
+ out = d.cstValue === "source" ? sourceLeaf(body, d.fn) : leaf(body, d.fn);
13509
+ if (d.fnSrc !== void 0) out._def.fnSrc = d.fnSrc;
13510
+ } else if (d.tag === "grammar") {
13511
+ out = d.clearTrivia === true ? noTrivia(body) : parser({ trivia: d.triviaParser ?? null }, body);
13512
+ } else return void 0;
13513
+ return sameFields(d, out._def, 0, "parser") ? out : void 0;
13514
+ }
13515
+ function unusedOf(seq) {
13516
+ return seq._def.tag === "sequence" && seq._def.valueUnused === true;
13517
+ }
13518
+ function never(c) {
13519
+ const t = c._def.tag;
13520
+ return t === "optional" || t === "many";
13521
+ }
13522
+ function factorSharedEnds(d) {
13523
+ const arms = d.parsers;
13524
+ if (arms.length < 2) return void 0;
13525
+ if (d.strategy.tag !== "firstMatch" && d.strategy.tag !== "sharedPrefix") return void 0;
13526
+ if (d.gates.some((g) => g !== null) || d.autoNot.some((a) => a !== null)) return void 0;
13527
+ const shapes = [];
13528
+ for (const arm of arms) {
13529
+ const wrappers = [];
13530
+ let c = arm;
13531
+ while ((c._def.tag === "leaf" || c._def.tag === "grammar") && wrappers.length < 4) {
13532
+ wrappers.push(c);
13533
+ c = c._def.parser;
13534
+ }
13535
+ if (c._def.tag !== "sequence" || c._def.parsers.length < 2) return void 0;
13536
+ shapes.push({ wrappers, terms: c._def.parsers, seq: c });
13537
+ }
13538
+ const first = shapes[0];
13539
+ const n = first.terms.length;
13540
+ for (const s of shapes) {
13541
+ if (s.wrappers.length !== first.wrappers.length || s.terms.length !== n) return void 0;
13542
+ if (unusedOf(s.seq) !== unusedOf(first.seq)) return void 0;
13543
+ for (let j = 0; j < s.wrappers.length; j++) {
13544
+ const a = first.wrappers[j]._def;
13545
+ const b = s.wrappers[j]._def;
13546
+ if (a.tag !== b.tag || !sameFields(a, b, 0, "parser")) return void 0;
13547
+ }
13548
+ }
13549
+ let at = -1;
13550
+ for (let i = 0; i < n; i++) {
13551
+ if (shapes.every((s) => sameComb(s.terms[i], first.terms[i], 0))) continue;
13552
+ if (at >= 0) return void 0;
13553
+ at = i;
13554
+ }
13555
+ if (at < 0) return void 0;
13556
+ for (let i = at + 1; i < n; i++) if (!never(first.terms[i])) return void 0;
13557
+ if (arms.some((a) => mayCommitFailure(a))) return void 0;
13558
+ const middle = choice(...shapes.map((s) => s.terms[at]));
13559
+ if (middle._def.tag === "choice" && middle._def.autoNot.some((a) => a !== null)) return void 0;
13560
+ const st = middle._def.tag === "choice" ? middle._def.strategy : void 0;
13561
+ if (st === void 0 || st.tag !== "firstMatch" && st.tag !== "sharedPrefix" && !(st.tag === "literalsLongestFirst" && st.sortedIndices.every((x, i) => x === i))) return void 0;
13562
+ let out = sequence(
13563
+ ...[...first.terms.slice(0, at), middle, ...first.terms.slice(at + 1)]
13564
+ );
13565
+ if (unusedOf(first.seq)) {
13566
+ out._def.valueUnused = true;
13567
+ }
13568
+ for (let j = first.wrappers.length - 1; j >= 0 && out !== void 0; j--) out = rewrap(first.wrappers[j], out);
13569
+ return out === void 0 ? void 0 : attempt(out);
13570
+ }
13571
+
12273
13572
  // src/compiler/direct-projection.ts
12274
13573
  function directArrayProjection(fn, fnSrc, arity) {
12275
13574
  let source = fnSrc;
@@ -12330,8 +13629,11 @@ function selectOptionalSuffixLexBody(ir) {
12330
13629
  const token2 = { strategy: "token", estimatedOps: 2, body };
12331
13630
  return token2.estimatedOps < character.estimatedOps ? token2 : character;
12332
13631
  }
12333
- function directTokenBodyParser(parser, resolve) {
12334
- const outer = parser._def;
13632
+ function reinstallsRuleTrivia(reference, target) {
13633
+ return (reference._meta.grammarTrivia ?? target._meta.grammarTrivia) !== void 0 && hasOwnTriviaBoundary(target);
13634
+ }
13635
+ function directTokenBodyParser(parser2, resolve, scope) {
13636
+ const outer = parser2._def;
12335
13637
  if (outer.tag !== "token") return void 0;
12336
13638
  let body = outer.parser;
12337
13639
  const seen = /* @__PURE__ */ new Set();
@@ -12340,12 +13642,13 @@ function directTokenBodyParser(parser, resolve) {
12340
13642
  const wrapper = body._def;
12341
13643
  if (wrapper.tag === "grammar") {
12342
13644
  if (wrapper.clearTrivia !== true || wrapper.triviaParser !== void 0 || wrapper.captureTrivia === true || wrapper.rootCapture === "opaque" || wrapper.constructionTrackLines !== "inherit" || wrapper.constructionCaptureTriviaKinds !== void 0) return void 0;
13645
+ if (scope !== void 0) scope.cleared = true;
12343
13646
  body = wrapper.parser;
12344
13647
  continue;
12345
13648
  }
12346
13649
  if (wrapper.tag === "lazy") {
12347
13650
  const target = resolvedLazyTarget(body, resolve);
12348
- if (target === void 0) return void 0;
13651
+ if (target === void 0 || reinstallsRuleTrivia(body, target)) return void 0;
12349
13652
  body = target;
12350
13653
  continue;
12351
13654
  }
@@ -12353,8 +13656,8 @@ function directTokenBodyParser(parser, resolve) {
12353
13656
  }
12354
13657
  return void 0;
12355
13658
  }
12356
- function directOptionalSuffixTokenBody(parser, resolve) {
12357
- const inner = directTokenBodyParser(parser, resolve);
13659
+ function directOptionalSuffixTokenBody(parser2, resolve) {
13660
+ const inner = directTokenBodyParser(parser2, resolve);
12358
13661
  if (inner === void 0) return void 0;
12359
13662
  const sequence6 = inner._def;
12360
13663
  if (sequence6.tag !== "sequence" || sequence6.parsers.length !== 2) return void 0;
@@ -12390,10 +13693,10 @@ function directOptionalSuffixTokenBody(parser, resolve) {
12390
13693
  expected: directTerminalFailureExpected(base)
12391
13694
  } : void 0;
12392
13695
  }
12393
- function directTerminalTokenBody(parser, resolve) {
12394
- const outer = parser._def;
13696
+ function directTerminalTokenBody(parser2, resolve) {
13697
+ const outer = parser2._def;
12395
13698
  if (outer.tag !== "token") return void 0;
12396
- const body = directTokenBodyParser(parser, resolve);
13699
+ const body = directTokenBodyParser(parser2, resolve);
12397
13700
  if (body === void 0) return void 0;
12398
13701
  const def = body._def;
12399
13702
  if (def.tag === "regex") return {
@@ -12413,28 +13716,28 @@ function directTerminalTokenBody(parser, resolve) {
12413
13716
  expected: directTerminalFailureExpected(def)
12414
13717
  };
12415
13718
  }
12416
- function directTerminalParser(parser, resolve) {
13719
+ function directTerminalParser(parser2, resolve) {
12417
13720
  const seen = /* @__PURE__ */ new Set();
12418
- while (!seen.has(parser)) {
12419
- seen.add(parser);
12420
- const def = parser._def;
13721
+ while (!seen.has(parser2)) {
13722
+ seen.add(parser2);
13723
+ const def = parser2._def;
12421
13724
  if (def.tag === "lazy") {
12422
- const target = resolvedLazyTarget(parser, resolve);
13725
+ const target = resolvedLazyTarget(parser2, resolve);
12423
13726
  if (target === void 0) return void 0;
12424
- parser = target;
13727
+ parser2 = target;
12425
13728
  continue;
12426
13729
  }
12427
13730
  if (def.tag === "token") {
12428
- parser = def.parser;
13731
+ parser2 = def.parser;
12429
13732
  continue;
12430
13733
  }
12431
13734
  if (def.tag === "grammar") return void 0;
12432
- return parser;
13735
+ return parser2;
12433
13736
  }
12434
13737
  return void 0;
12435
13738
  }
12436
- function directTerminalLexBody(parser, resolve) {
12437
- const terminal = directTerminalParser(parser, resolve);
13739
+ function directTerminalLexBody(parser2, resolve) {
13740
+ const terminal = directTerminalParser(parser2, resolve);
12438
13741
  if (terminal === void 0) return void 0;
12439
13742
  const def = terminal._def;
12440
13743
  if (def.tag === "literal") {
@@ -12465,8 +13768,8 @@ function directTerminalLexBody(parser, resolve) {
12465
13768
  expected: directTerminalFailureExpected(def)
12466
13769
  };
12467
13770
  }
12468
- function directOrdered4TokenBody(parser, resolve) {
12469
- const body = directTokenBodyParser(parser, resolve);
13771
+ function directOrdered4TokenBody(parser2, resolve) {
13772
+ const body = directTokenBodyParser(parser2, resolve);
12470
13773
  return body === void 0 ? void 0 : directOrdered4Body(body, resolve);
12471
13774
  }
12472
13775
  function directOrdered4Body(body, resolve) {
@@ -12494,8 +13797,8 @@ function directOrdered4Body(body, resolve) {
12494
13797
  arms
12495
13798
  };
12496
13799
  }
12497
- function directNot2TokenBody(parser, resolve) {
12498
- const body = directTokenBodyParser(parser, resolve);
13800
+ function directNot2TokenBody(parser2, resolve) {
13801
+ const body = directTokenBodyParser(parser2, resolve);
12499
13802
  const sequence6 = body?._def;
12500
13803
  if (sequence6?.tag !== "sequence" || sequence6.parsers.length !== 3) return void 0;
12501
13804
  const [guard0Parser, guard1Parser, terminalParser] = sequence6.parsers;
@@ -12517,15 +13820,15 @@ function directNot2TokenBody(parser, resolve) {
12517
13820
  terminal
12518
13821
  };
12519
13822
  }
12520
- function directFixedLexNode(parser, resolve, active, pureOnly = false) {
12521
- let current = parser;
13823
+ function directFixedLexNode(parser2, resolve, active, pureOnly = false, cleared = false) {
13824
+ let current = parser2;
12522
13825
  const wrappers = /* @__PURE__ */ new Set();
12523
13826
  while (!wrappers.has(current)) {
12524
13827
  wrappers.add(current);
12525
13828
  const def = current._def;
12526
13829
  if (def.tag === "lazy") {
12527
13830
  const target = resolvedLazyTarget(current, resolve);
12528
- if (target === void 0) return void 0;
13831
+ if (target === void 0 || reinstallsRuleTrivia(current, target)) return void 0;
12529
13832
  current = target;
12530
13833
  continue;
12531
13834
  }
@@ -12535,7 +13838,7 @@ function directFixedLexNode(parser, resolve, active, pureOnly = false) {
12535
13838
  }
12536
13839
  break;
12537
13840
  }
12538
- if (wrappers.has(current) && current !== parser && current._def.tag === "lazy") return void 0;
13841
+ if (wrappers.has(current) && current !== parser2 && current._def.tag === "lazy") return void 0;
12539
13842
  if (active.has(current)) return void 0;
12540
13843
  active.add(current);
12541
13844
  try {
@@ -12543,30 +13846,33 @@ function directFixedLexNode(parser, resolve, active, pureOnly = false) {
12543
13846
  if (terminal !== void 0) return { kind: "terminal", terminal };
12544
13847
  const def = current._def;
12545
13848
  if (def.tag === "grammar") {
13849
+ if (def.triviaParser === void 0 && def.captureTrivia !== true && def.rootCapture !== "opaque" && def.constructionCaptureTriviaKinds === void 0) {
13850
+ return directFixedLexNode(def.parser, resolve, active, pureOnly, cleared || def.clearTrivia === true);
13851
+ }
12546
13852
  if (!pureOnly || def.parser._def.tag !== "token" && (def.clearTrivia !== true || def.triviaParser !== void 0 || def.captureTrivia === true || def.rootCapture === "opaque")) return void 0;
12547
- return directFixedLexNode(def.parser, resolve, active, true);
13853
+ return directFixedLexNode(def.parser, resolve, active, true, cleared);
12548
13854
  }
12549
13855
  if (def.tag === "sequence") {
12550
13856
  if (def.parsers.length < 2 || def.parsers.length > 5) return void 0;
12551
- const parts = def.parsers.map((part) => directFixedLexNode(part, resolve, active, pureOnly));
13857
+ const parts = def.parsers.map((part) => directFixedLexNode(part, resolve, active, pureOnly, cleared));
12552
13858
  if (parts.some((part) => part === void 0)) return void 0;
12553
13859
  return { kind: "sequence", parts };
12554
13860
  }
12555
13861
  if (def.tag === "choice") {
12556
- if (def.parsers.length !== 2 && def.parsers.length !== 4 && def.parsers.length !== 8 || def.strategy.tag !== "firstMatch" || def.gates.some((gate) => gate !== null) || def.autoNot.some((check) => check !== null)) return void 0;
12557
- const arms = def.parsers.map((arm) => directFixedLexNode(arm, resolve, active, pureOnly));
13862
+ if (def.parsers.length < 2 || def.strategy.tag !== "firstMatch" || def.gates.some((gate) => gate !== null) || def.autoNot.some((check) => check !== null)) return void 0;
13863
+ const arms = def.parsers.map((arm) => directFixedLexNode(arm, resolve, active, pureOnly, cleared));
12558
13864
  if (arms.some((arm) => arm === void 0)) return void 0;
12559
- const final = classifyFinalChoice(def.parsers, resolve);
12560
13865
  return {
12561
13866
  kind: "choice",
12562
13867
  arms,
12563
- firstSets: final.firstSets,
13868
+ parsers: def.parsers,
13869
+ cleared,
12564
13870
  armExpected: def.parsers.map(deriveExpected),
12565
13871
  expected: def.parsers.flatMap(deriveExpected)
12566
13872
  };
12567
13873
  }
12568
13874
  if (def.tag === "not") {
12569
- const body = directFixedLexNode(def.parser, resolve, active, true);
13875
+ const body = directFixedLexNode(def.parser, resolve, active, true, cleared);
12570
13876
  return body === void 0 ? void 0 : {
12571
13877
  kind: "not",
12572
13878
  body,
@@ -12574,23 +13880,33 @@ function directFixedLexNode(parser, resolve, active, pureOnly = false) {
12574
13880
  };
12575
13881
  }
12576
13882
  if (def.tag === "optional") {
12577
- const body = directFixedLexNode(def.parser, resolve, active, pureOnly);
13883
+ const body = directFixedLexNode(def.parser, resolve, active, pureOnly, cleared);
12578
13884
  return body === void 0 ? void 0 : { kind: "optional", body };
12579
13885
  }
13886
+ if (def.tag === "many" || def.tag === "oneOrMore") {
13887
+ const body = directFixedLexNode(def.parser, resolve, active, pureOnly, cleared);
13888
+ return body === void 0 ? void 0 : {
13889
+ kind: "repeat",
13890
+ body,
13891
+ min: def.tag === "many" ? 0 : def.min,
13892
+ max: def.max ?? -1
13893
+ };
13894
+ }
12580
13895
  return void 0;
12581
13896
  } finally {
12582
13897
  active.delete(current);
12583
13898
  }
12584
13899
  }
12585
- function directFixedTokenBody(parser, resolve) {
12586
- const body = directTokenBodyParser(parser, resolve);
13900
+ function directFixedTokenBody(parser2, resolve) {
13901
+ const scope = { cleared: false };
13902
+ const body = directTokenBodyParser(parser2, resolve, scope);
12587
13903
  if (body === void 0) return void 0;
12588
- const root = directFixedLexNode(body, resolve, /* @__PURE__ */ new Set());
13904
+ const root = directFixedLexNode(body, resolve, /* @__PURE__ */ new Set(), false, scope.cleared);
12589
13905
  return root === void 0 ? void 0 : { kind: "fixed-tree", root };
12590
13906
  }
12591
- function directBalancedTokenBody(parser, resolve) {
12592
- if (directTokenBodyParser(parser, resolve) === void 0) return void 0;
12593
- const spec = balancedSpecOf(parser);
13907
+ function directBalancedTokenBody(parser2, resolve) {
13908
+ if (directTokenBodyParser(parser2, resolve) === void 0) return void 0;
13909
+ const spec = balancedSpecOf(parser2);
12594
13910
  return spec === void 0 ? void 0 : {
12595
13911
  kind: "balanced-scan",
12596
13912
  open: spec.open,
@@ -12600,8 +13916,8 @@ function directBalancedTokenBody(parser, resolve) {
12600
13916
  ownSkip: spec.ownSkip
12601
13917
  };
12602
13918
  }
12603
- function directExecutableTokenBody(parser, resolve) {
12604
- return directOptionalSuffixTokenBody(parser, resolve) ?? directTerminalTokenBody(parser, resolve) ?? directOrdered4TokenBody(parser, resolve) ?? directNot2TokenBody(parser, resolve) ?? directBalancedTokenBody(parser, resolve) ?? directFixedTokenBody(parser, resolve);
13919
+ function directExecutableTokenBody(parser2, resolve) {
13920
+ return directOptionalSuffixTokenBody(parser2, resolve) ?? directTerminalTokenBody(parser2, resolve) ?? directOrdered4TokenBody(parser2, resolve) ?? directNot2TokenBody(parser2, resolve) ?? directBalancedTokenBody(parser2, resolve) ?? directFixedTokenBody(parser2, resolve);
12605
13921
  }
12606
13922
  function winnerWrapsReference(winner, reference) {
12607
13923
  let current = winner;
@@ -12615,13 +13931,13 @@ function winnerWrapsReference(winner, reference) {
12615
13931
  }
12616
13932
  return false;
12617
13933
  }
12618
- function resolvedLazyTarget(parser, resolve) {
12619
- const def = parser._def;
13934
+ function resolvedLazyTarget(parser2, resolve) {
13935
+ const def = parser2._def;
12620
13936
  if (def.tag !== "lazy") return void 0;
12621
- const name = parser._ruleName;
13937
+ const name = parser2._ruleName;
12622
13938
  if (name !== void 0 && resolve !== void 0) {
12623
13939
  const winner = resolve(name);
12624
- if (winner !== void 0 && !winnerWrapsReference(winner, parser)) return winner;
13940
+ if (winner !== void 0 && !winnerWrapsReference(winner, parser2)) return winner;
12625
13941
  }
12626
13942
  try {
12627
13943
  return def.thunk();
@@ -12629,8 +13945,8 @@ function resolvedLazyTarget(parser, resolve) {
12629
13945
  return void 0;
12630
13946
  }
12631
13947
  }
12632
- function balancedSpecOf(parser) {
12633
- let current = parser;
13948
+ function balancedSpecOf(parser2) {
13949
+ let current = parser2;
12634
13950
  let spec = current._balancedSpec;
12635
13951
  const seen = /* @__PURE__ */ new Set();
12636
13952
  while (spec === void 0 && current._def.tag === "token" && !seen.has(current)) {
@@ -12832,13 +14148,16 @@ var Encoder = class {
12832
14148
  }
12833
14149
  case "choice": {
12834
14150
  for (const arm of node.arms) if (!emitNode(arm)) return false;
12835
- const op = node.arms.length === 2 ? LEX_NODE_CHOICE2 : node.arms.length === 4 ? LEX_NODE_CHOICE4 : node.arms.length === 8 ? LEX_NODE_CHOICE8 : -1;
12836
- if (op < 0) return false;
12837
- words.push(op, this.expected(node.expected));
14151
+ const final = classifyFinalChoice(
14152
+ node.parsers,
14153
+ this.refResolver(),
14154
+ node.cleared ? void 0 : this.activeTrivia
14155
+ );
14156
+ const classes = final.firstSets.map((first, i) => final.nullable[i] ? -1 : this.charClass(first));
14157
+ const exclusive = final.exclusive && classes.every((cls) => cls >= 0);
14158
+ words.push(LEX_NODE_CHOICE, node.arms.length, exclusive ? 1 : 0, this.expected(node.expected));
12838
14159
  for (let i = 0; i < node.arms.length; i++) {
12839
- const first = node.firstSets[i];
12840
- words.push(first.kind === "ranges" ? this.charClass(first) : -1);
12841
- words.push(this.expected(node.armExpected[i]));
14160
+ words.push(classes[i], this.expected(node.armExpected[i]));
12842
14161
  }
12843
14162
  return true;
12844
14163
  }
@@ -12850,6 +14169,10 @@ var Encoder = class {
12850
14169
  if (!emitNode(node.body)) return false;
12851
14170
  words.push(LEX_NODE_OPTIONAL);
12852
14171
  return true;
14172
+ case "repeat":
14173
+ if (!emitNode(node.body)) return false;
14174
+ words.push(LEX_NODE_REPEAT, node.min, node.max);
14175
+ return true;
12853
14176
  }
12854
14177
  };
12855
14178
  if (!emitNode(body.root)) return void 0;
@@ -13177,6 +14500,33 @@ var Encoder = class {
13177
14500
  return childrenOf(def);
13178
14501
  }
13179
14502
  }
14503
+ /**
14504
+ * THE FIRST-CHARACTER GATE OF AN `optional`, `not` OR `peek` CHILD.
14505
+ *
14506
+ * A non-nullable child cannot match at a character outside its first set, so
14507
+ * the wrapper's outcome there is already decided: `optional` yields `null`,
14508
+ * `not` succeeds, `peek` fails with its own set. The interpreter's `optional`
14509
+ * makes that test itself (`repeat.ts` `startsFirstSet`); the table entered the
14510
+ * child — a rollback mark, the call, the child's own failure — to learn it.
14511
+ *
14512
+ * The gate is an `OP_GATE` row around the child, so every engine runs it
14513
+ * unchanged, a probe or tolerant parse forwards through it as for a node's
14514
+ * gate, and the wrapper's row keeps its layout. The engines test the class
14515
+ * before taking the wrapper's mark. The first set is resolved through
14516
+ * `winners`, the analysis a choice arm's gate uses, so a composed rule's set
14517
+ * is the merged one. A scalar `not` child stays bare: `scalarTerminalNotChild`
14518
+ * already reduces it to one recognizer call.
14519
+ */
14520
+ lookaheadGate(p, child) {
14521
+ const op = this.code[child];
14522
+ if (op === OP_GATE || op === OP_LIT || op === OP_LIT_CI || op === OP_LIT_TRACK || op === OP_LIT_CI_TRACK || op === OP_RX || op === OP_RX_TRACK) return child;
14523
+ const rr = this.refResolver();
14524
+ if (matchesEmpty(p, /* @__PURE__ */ new Set(), rr)) return child;
14525
+ const cls = this.charClass(firstSetOf(p, /* @__PURE__ */ new Set(), rr, this.activeTrivia));
14526
+ if (cls < 0) return child;
14527
+ const e = deriveExpected(p);
14528
+ return this.emit(OP_GATE, cls, child, this.expected(e.length > 0 ? e : [p._tag]));
14529
+ }
13180
14530
  /** A first set becomes a char class string, or −1 for `any`. */
13181
14531
  charClass(fs) {
13182
14532
  if (fs.kind !== "ranges" || fs.ranges.length === 0) return -1;
@@ -13188,12 +14538,19 @@ var Encoder = class {
13188
14538
  this.ccIndex.set(spec, i);
13189
14539
  return i;
13190
14540
  }
13191
- /** Bind a guard only when its class is already part of the program. Repeat
13192
- * gating must not grow the compact artifact merely to avoid a failed call. */
13193
- existingCharClass(fs) {
13194
- if (fs.kind !== "ranges" || fs.ranges.length === 0) return -1;
13195
- const hit = this.ccIndex.get(encodeClassSpec(fs.ranges));
13196
- return hit !== void 0 && hit < 100 ? hit : -1;
14541
+ /**
14542
+ * The first set a node's or an attempt's fail-fast gate tests. A bare
14543
+ * cross-rule ref resolves through `winners` (a compose OVERRIDE may widen
14544
+ * it). Any other body keeps its construction-time `_meta.firstSet`, except
14545
+ * where that is `any`: under `compose()` a body that reaches a rule of
14546
+ * another piece is built before that rule exists, so its cached set is
14547
+ * `any` and the node got NO gate (jess's `CompoundSelector` was entered at
14548
+ * `{`, `Call` at `}`). The resolved set is the one a choice arm's gate uses,
14549
+ * over the final merged map.
14550
+ */
14551
+ gateFirstSet(p) {
14552
+ const cached = p._meta.firstSet;
14553
+ return p._def.tag === "lazy" || cached.kind === "any" ? firstSetOf(p, /* @__PURE__ */ new Set(), this.refResolver(), this.activeTrivia) : cached;
13197
14554
  }
13198
14555
  /**
13199
14556
  * Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
@@ -13321,6 +14678,50 @@ var Encoder = class {
13321
14678
  if (!hasOwnTriviaBoundary(target)) return ip;
13322
14679
  return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), ip);
13323
14680
  }
14681
+ /**
14682
+ * The `OP_RGATE` operands of a choice arm that opens with `routed()`, or
14683
+ * `undefined`. Through `node()`/scope wrappers and first sequence terms, the
14684
+ * arm's next term after the routed token is found; the gate is that term's
14685
+ * first characters, with the trivia in force at the boundary before it, so
14686
+ * the arm is entered only where it can get past the token. The term must be
14687
+ * unable to match empty or to commit, so a miss is exactly that term failing
14688
+ * at the token's end with its own set.
14689
+ */
14690
+ routedArmGate(arm) {
14691
+ const walk = (p, trivia2, depth) => {
14692
+ if (depth > 16) return void 0;
14693
+ const d = p._def;
14694
+ switch (d.tag) {
14695
+ case "routed":
14696
+ return "end";
14697
+ case "node":
14698
+ return walk(d.parser, trivia2, depth + 1);
14699
+ case "grammar":
14700
+ return walk(d.parser, d.clearTrivia === true ? void 0 : d.triviaParser ?? trivia2, depth + 1);
14701
+ case "sequence": {
14702
+ const head = d.parsers[0];
14703
+ if (head === void 0) return void 0;
14704
+ const r = walk(head, trivia2, depth + 1);
14705
+ if (r !== "end") return r;
14706
+ const next2 = d.parsers[1];
14707
+ return next2 === void 0 ? "end" : { next: next2, boundary: trivia2 };
14708
+ }
14709
+ default:
14710
+ return void 0;
14711
+ }
14712
+ };
14713
+ const follow = walk(arm, this.activeTrivia, 0);
14714
+ if (follow === void 0 || follow === "end") return void 0;
14715
+ const rr = this.refResolver();
14716
+ const { next, boundary } = follow;
14717
+ if (matchesEmpty(next, /* @__PURE__ */ new Set(), rr) || mayCommitFailure(next, rr, this.commitFailureMemo)) return void 0;
14718
+ const nextTag = next._def.tag;
14719
+ if (nextTag !== "literal" && nextTag !== "regex" && nextTag !== "keywords" && nextTag !== "label") return void 0;
14720
+ const first = firstSetOf(next, /* @__PURE__ */ new Set(), rr, boundary);
14721
+ const cls = this.charClass(boundary === void 0 ? first : union(first, firstSetOf(boundary, /* @__PURE__ */ new Set(), rr)));
14722
+ if (cls < 0) return void 0;
14723
+ return { cls, fx: this.expected(deriveExpected(next)) };
14724
+ }
13324
14725
  node(p) {
13325
14726
  const lazyRef = p._def.tag === "lazy";
13326
14727
  const scopeKey = lazyRef ? this.activeTrivia : void 0;
@@ -13445,6 +14846,10 @@ var Encoder = class {
13445
14846
  return head;
13446
14847
  }
13447
14848
  case "choice": {
14849
+ if (this.plan === void 0) {
14850
+ const factored = factorSharedEnds(d);
14851
+ if (factored !== void 0) return this.node(factored).ip;
14852
+ }
13448
14853
  if (d.strategy.tag === "greedyClassify") {
13449
14854
  const superIndex = d.strategy.superIndex;
13450
14855
  const sup = this.node(d.parsers[superIndex]).ip;
@@ -13468,9 +14873,12 @@ var Encoder = class {
13468
14873
  const kids = arms.map((c, k) => {
13469
14874
  const src = order[k];
13470
14875
  const checks = d.autoNot[src];
13471
- const inner = this.node(c).ip;
13472
- const ip = checks === null || checks === void 0 || checks.length === 0 ? inner : this.reject(inner, checks);
13473
14876
  const gate = d.gates[src];
14877
+ const plain = (checks === null || checks === void 0 || checks.length === 0) && (gate === null || gate === void 0);
14878
+ const routedGate = plain ? this.routedArmGate(c) : void 0;
14879
+ const body = this.node(c).ip;
14880
+ const inner = routedGate === void 0 ? body : this.emit(OP_RGATE, routedGate.cls, body, routedGate.fx);
14881
+ const ip = checks === null || checks === void 0 || checks.length === 0 ? inner : this.reject(inner, checks);
13474
14882
  const gated = gate === null || gate === void 0 ? ip : this.emit(OP_ARMGATE, this.fn(gate, d.gateSrcs?.[src] ?? null), ip, this.expected(deriveExpected(c)));
13475
14883
  return this.covWrap(gated, armCovIds?.[src], 1);
13476
14884
  });
@@ -13498,6 +14906,12 @@ var Encoder = class {
13498
14906
  if (transactionalFirst[i] !== void 0) classes[i] = -1;
13499
14907
  }
13500
14908
  }
14909
+ if (d.gates.some((g) => g !== null && g !== void 0) && !dispatchIsExclusive(classes, this.cc)) {
14910
+ for (let k = 0; k < classes.length; k++) {
14911
+ const gate = d.gates[order[k]];
14912
+ if (gate !== null && gate !== void 0) classes[k] = -1;
14913
+ }
14914
+ }
13501
14915
  const dispIdx = this.disp.length;
13502
14916
  this.disp.push(classes);
13503
14917
  let rollbackMask = kids.length > 31 ? -1 : 0;
@@ -13527,7 +14941,7 @@ var Encoder = class {
13527
14941
  case "oneOrMore": {
13528
14942
  const child = this.node(d.parser).ip;
13529
14943
  const rr = this.refResolver();
13530
- const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.existingCharClass(firstSetOf(d.parser, /* @__PURE__ */ new Set(), rr, this.activeTrivia));
14944
+ const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.charClass(firstSetOf(d.parser, /* @__PURE__ */ new Set(), rr, this.activeTrivia));
13531
14945
  const op = d.valueUnused ? OP_REPV : OP_REP;
13532
14946
  const min = d.tag === "many" ? 0 : d.min;
13533
14947
  return this.rec ? this.emit(op, child, min, d.max ?? -1, -1, 0, this.expected(deriveExpected(d.parser)), itemClass) : this.emit(op, child, min, d.max ?? -1, -1, 0);
@@ -13551,7 +14965,7 @@ var Encoder = class {
13551
14965
  return d.min >= 2 ? this.emit(OP_REP, child, d.min, d.max ?? -1, sep, flags, this.expected(deriveExpected(d.parser))) : this.emit(OP_REP, child, d.min, d.max ?? -1, sep, flags);
13552
14966
  }
13553
14967
  case "optional": {
13554
- const head = this.emit(OP_OPT, this.node(d.parser).ip);
14968
+ const head = this.emit(OP_OPT, this.lookaheadGate(d.parser, this.node(d.parser).ip));
13555
14969
  if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(head);
13556
14970
  return head;
13557
14971
  }
@@ -13599,8 +15013,8 @@ var Encoder = class {
13599
15013
  // every CST node, so this is load-bearing, not reflection trivia.
13600
15014
  d.tags === void 0 ? -1 : this.constant(d.tags)
13601
15015
  );
13602
- if (matchesEmpty(d.parser)) return body;
13603
- const fs = d.parser._def.tag === "lazy" ? firstSetOf(d.parser, /* @__PURE__ */ new Set(), this.refResolver(), this.activeTrivia) : d.parser._meta.firstSet;
15016
+ if (matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return body;
15017
+ const fs = this.gateFirstSet(d.parser);
13604
15018
  if (fs.kind === "any") return body;
13605
15019
  const cls = this.charClass(fs);
13606
15020
  if (cls < 0) return body;
@@ -13692,7 +15106,7 @@ var Encoder = class {
13692
15106
  // other engine reported `['not(literal)']`. It hid because `expected` is a
13693
15107
  // TOP-LEVEL field on `RunResult` and is NOT part of the identity digest.
13694
15108
  case "not":
13695
- return this.emit(OP_NOT, this.node(d.parser).ip, this.expected(assertionFailureExpected(false, d.parser._tag)));
15109
+ return this.emit(OP_NOT, this.lookaheadGate(d.parser, this.node(d.parser).ip), this.expected(assertionFailureExpected(false, d.parser._tag)));
13696
15110
  case "guard":
13697
15111
  return this.emit(OP_GUARD, this.fn(d.predicate, d.predSrc ?? null), this.expected(["gate"]));
13698
15112
  case "adjacency":
@@ -13713,14 +15127,14 @@ var Encoder = class {
13713
15127
  return this.emit(OP_WITHCTX, this.constant(d.extra), this.node(d.parser).ip);
13714
15128
  }
13715
15129
  case "peek":
13716
- return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected(assertionFailureExpected(true, d.parser._tag)));
15130
+ return this.emit(OP_PEEK, this.lookaheadGate(d.parser, this.node(d.parser).ip), this.expected(assertionFailureExpected(true, d.parser._tag)));
13717
15131
  // A TRANSACTION IS A ROW. See `OP_ATTEMPT` for why the transparent
13718
15132
  // lowering was correct only for a choice arm.
13719
15133
  case "attempt": {
13720
15134
  const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip, d.contain === true ? 1 : 0);
13721
15135
  if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
13722
- const fs = d.parser._def.tag === "lazy" ? firstSetOf(d.parser, /* @__PURE__ */ new Set(), this.refResolver(), this.activeTrivia) : d.parser._meta.firstSet;
13723
- if (fs.kind === "any" || matchesEmpty(d.parser)) return inner;
15136
+ const fs = this.gateFirstSet(d.parser);
15137
+ if (fs.kind === "any" || matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return inner;
13724
15138
  const cls = this.charClass(fs);
13725
15139
  if (cls < 0) return inner;
13726
15140
  const e = deriveExpected(d.parser);
@@ -13788,6 +15202,7 @@ var Encoder = class {
13788
15202
  const slots = (ip) => {
13789
15203
  switch (this.code[ip]) {
13790
15204
  case OP_GATE:
15205
+ case OP_RGATE:
13791
15206
  return [ip + 2];
13792
15207
  case OP_RULE:
13793
15208
  case OP_OPT:
@@ -13958,7 +15373,7 @@ function emitClassPool(classes) {
13958
15373
  if (classes.length < 2) return array;
13959
15374
  const delimiter = "|/~?^`".split("").find((ch2) => classes.every((spec) => !spec.includes(ch2)));
13960
15375
  if (delimiter === void 0) return array;
13961
- const split = `${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
15376
+ const split = `/* @__PURE__ */ ${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
13962
15377
  return split.length < array.length ? split : array;
13963
15378
  }
13964
15379
  function emitConst(v) {
@@ -14020,9 +15435,7 @@ function defaultAssemblyCfgs(prog) {
14020
15435
  function emitAssemblies(prog, cfgs) {
14021
15436
  if (cfgs.length === 0) return ["a:[],"];
14022
15437
  const t = resolveTable(prog);
14023
- const extraIps = [];
14024
- for (const s of prog.scans ?? []) for (const r of scanRefs(s)) extraIps.push(r[0]);
14025
- for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
15438
+ const extraIps = assemblyExtraIps(prog);
14026
15439
  const out = [];
14027
15440
  const seen = /* @__PURE__ */ new Set();
14028
15441
  for (const cfg of cfgs) {
@@ -14031,7 +15444,7 @@ function emitAssemblies(prog, cfgs) {
14031
15444
  seen.add(key);
14032
15445
  let em;
14033
15446
  try {
14034
- em = emitAssemblySource(t, prog, cfg, extraIps, true);
15447
+ em = emitAssemblySource(t, prog, cfg, extraIps, true, cfg.select);
14035
15448
  } catch (e) {
14036
15449
  if (e instanceof Unemittable) continue;
14037
15450
  throw e;
@@ -14243,12 +15656,12 @@ function buildGrammarPlan(entry, winners) {
14243
15656
  }
14244
15657
  }
14245
15658
  }
14246
- const selfWinnerBody = (parser) => {
14247
- if (parser._def.tag !== "lazy" || winners === void 0) return void 0;
14248
- const name = winnerNames.get(parser);
14249
- if (name === void 0 || winners[name] !== parser) return void 0;
15659
+ const selfWinnerBody = (parser2) => {
15660
+ if (parser2._def.tag !== "lazy" || winners === void 0) return void 0;
15661
+ const name = winnerNames.get(parser2);
15662
+ if (name === void 0 || winners[name] !== parser2) return void 0;
14250
15663
  try {
14251
- return parser._def.thunk();
15664
+ return parser2._def.thunk();
14252
15665
  } catch {
14253
15666
  return void 0;
14254
15667
  }
@@ -14260,39 +15673,39 @@ function buildGrammarPlan(entry, winners) {
14260
15673
  if (body !== void 0) slotsPerBody.set(body, (slotsPerBody.get(body) ?? 0) + 1);
14261
15674
  }
14262
15675
  }
14263
- const sharedBody = (parser) => (slotsPerBody.get(parser) ?? 0) > 1;
14264
- const ownRule = (parser, rule) => {
15676
+ const sharedBody = (parser2) => (slotsPerBody.get(parser2) ?? 0) > 1;
15677
+ const ownRule = (parser2, rule) => {
14265
15678
  const id = `rule:${rule}`;
14266
15679
  definitions.set(id, { id, kind: "rule" });
14267
- rules.set(parser, id);
15680
+ rules.set(parser2, id);
14268
15681
  };
14269
15682
  const seen = /* @__PURE__ */ new Set();
14270
- const visit = (parser, path) => {
14271
- if (seen.has(parser)) return;
14272
- seen.add(parser);
14273
- const rule = winnerNames.get(parser) ?? parser._ruleName;
14274
- const body = selfWinnerBody(parser);
14275
- if (rule && body === void 0 && !sharedBody(parser) && (winnerNames.has(parser) || parser._def.tag !== "lazy")) {
14276
- ownRule(parser, rule);
14277
- }
14278
- if (rule && body !== void 0 && sharedBody(body)) ownRule(parser, rule);
14279
- if (parser._def.tag === "choice") {
14280
- const ids = parser._def.parsers.map((_, index) => `choice:${path}/arm:${index}`);
14281
- choices.set(parser, ids);
15683
+ const visit = (parser2, path) => {
15684
+ if (seen.has(parser2)) return;
15685
+ seen.add(parser2);
15686
+ const rule = winnerNames.get(parser2) ?? parser2._ruleName;
15687
+ const body = selfWinnerBody(parser2);
15688
+ if (rule && body === void 0 && !sharedBody(parser2) && (winnerNames.has(parser2) || parser2._def.tag !== "lazy")) {
15689
+ ownRule(parser2, rule);
15690
+ }
15691
+ if (rule && body !== void 0 && sharedBody(body)) ownRule(parser2, rule);
15692
+ if (parser2._def.tag === "choice") {
15693
+ const ids = parser2._def.parsers.map((_, index) => `choice:${path}/arm:${index}`);
15694
+ choices.set(parser2, ids);
14282
15695
  ids.forEach((id) => definitions.set(id, { id, kind: "choice-arm" }));
14283
15696
  }
14284
- if (parser._def.tag === "dispatch") {
14285
- const ids = dispatchArmIds(parser._def, path);
14286
- dispatches.set(parser, ids);
15697
+ if (parser2._def.tag === "dispatch") {
15698
+ const ids = dispatchArmIds(parser2._def, path);
15699
+ dispatches.set(parser2, ids);
14287
15700
  ids.forEach((id) => definitions.set(id, { id, kind: "dispatch-arm" }));
14288
15701
  }
14289
- if (parser._def.tag === "attempt") attempts.set(parser, `attempt:${path}`);
14290
- if (parser._def.tag === "label") {
15702
+ if (parser2._def.tag === "attempt") attempts.set(parser2, `attempt:${path}`);
15703
+ if (parser2._def.tag === "label") {
14291
15704
  const id = `label:${path}`;
14292
- labels.set(parser, [id]);
15705
+ labels.set(parser2, [id]);
14293
15706
  definitions.set(id, { id, kind: "label" });
14294
15707
  }
14295
- children(parser._def, winners).forEach((child, index) => visit(child, `${path}/${parser._def.tag}:${index}`));
15708
+ children(parser2._def, winners).forEach((child, index) => visit(child, `${path}/${parser2._def.tag}:${index}`));
14296
15709
  };
14297
15710
  const roots = Array.isArray(entry) ? entry : [entry];
14298
15711
  for (const root of roots) {
@@ -15686,10 +17099,10 @@ function addNode(out, def) {
15686
17099
  if (!existing.includes(tag)) existing.push(tag);
15687
17100
  }
15688
17101
  }
15689
- function collectFromCombinator(parser, out, seen, followLazy = true) {
15690
- if (seen.has(parser)) return;
15691
- seen.add(parser);
15692
- const def = parser._def;
17102
+ function collectFromCombinator(parser2, out, seen, followLazy = true) {
17103
+ if (seen.has(parser2)) return;
17104
+ seen.add(parser2);
17105
+ const def = parser2._def;
15693
17106
  if (def.tag === "lazy") {
15694
17107
  if (followLazy) {
15695
17108
  try {
@@ -15720,8 +17133,46 @@ function collectGrammarReflection(ruleMap, opts) {
15720
17133
  return { nodes: [...byType].map(([type, tags]) => ({ type, tags })) };
15721
17134
  }
15722
17135
 
17136
+ // src/table/select-hot.ts
17137
+ var LOOP = 8;
17138
+ var ROUNDS = 60;
17139
+ var CAP = 1e12;
17140
+ function selectHotSites(code, entries, siteBytes, budget, profile) {
17141
+ const selected = /* @__PURE__ */ new Set();
17142
+ if (budget <= 0) return selected;
17143
+ const weight = profile === void 0 ? staticWeights(code, entries) : void 0;
17144
+ const w = (ip) => (weight !== void 0 ? weight.get(ip) : profile[ip]) ?? 0;
17145
+ const ranked = [...siteBytes.keys()].sort((a, b) => w(b) / siteBytes.get(b) - w(a) / siteBytes.get(a) || a - b);
17146
+ let spent = 0;
17147
+ for (const ip of ranked) {
17148
+ if (w(ip) === 0) break;
17149
+ const bytes = siteBytes.get(ip);
17150
+ if (spent + bytes > budget) continue;
17151
+ spent += bytes;
17152
+ selected.add(ip);
17153
+ }
17154
+ return selected;
17155
+ }
17156
+ function staticWeights(code, entries) {
17157
+ let weight = /* @__PURE__ */ new Map();
17158
+ const kids = [];
17159
+ for (let round = 0; round < ROUNDS; round++) {
17160
+ const next = /* @__PURE__ */ new Map();
17161
+ for (const ip of entries) next.set(ip, 1);
17162
+ for (const [ip, w] of weight) {
17163
+ kids.length = 0;
17164
+ childSlots(code, ip, kids);
17165
+ const op = code[ip];
17166
+ const scale = op === OP_REP || op === OP_REPV ? LOOP : op === OP_CHOICE || op === OP_DISPATCH ? 1 / Math.max(1, kids.length) : 1;
17167
+ for (const kid of kids) next.set(kid, Math.min(CAP, (next.get(kid) ?? 0) + w * scale));
17168
+ }
17169
+ weight = next;
17170
+ }
17171
+ return weight;
17172
+ }
17173
+
15723
17174
  // src/table/compile-rule-map.ts
15724
- var DEFAULT_PRECOMPILE_MIN_WORDS = 1024;
17175
+ var SUPERCOMPILE_GROWTH = 1.05;
15725
17176
  function resolveHostMode(ruleMap, explicit) {
15726
17177
  return explicit ?? ruleMap.map(([, r]) => r._meta.grammarHostMode).find(Boolean) ?? "ast";
15727
17178
  }
@@ -15818,14 +17269,45 @@ function compileRuleMap(ruleMap, opts = {}) {
15818
17269
  entry: null,
15819
17270
  runtimeRef: opts.runtimeRef ?? "tableRules",
15820
17271
  fnSources: sources,
15821
- ...options.precompileDefault === true && hostMode === "ast" && prog.lines !== 1 && prog.code.length >= DEFAULT_PRECOMPILE_MIN_WORDS ? { assemblies: defaultAssemblyCfgs(artifact).slice(0, 1) } : {},
17272
+ ...options.select !== void 0 && options.select.size > 0 ? { assemblies: [{ ...defaultAssemblyCfgs(artifact)[0], select: options.select }] } : {},
15822
17273
  ...metadataSource === void 0 ? {} : { metadataSource }
15823
17274
  });
15824
17275
  const replacement = replacementWithMetadata();
17276
+ const selectAssembly = (budget, profile) => {
17277
+ const none = { sites: /* @__PURE__ */ new Set(), bytes: 0 };
17278
+ if (hostMode !== "ast" || prog.lines === 1) return none;
17279
+ const table = resolveTable(artifact);
17280
+ const cfg = defaultAssemblyCfgs(artifact)[0];
17281
+ const roots = assemblyExtraIps(artifact);
17282
+ let siteBytes, fixed;
17283
+ try {
17284
+ siteBytes = emitAssemblySource(table, artifact, cfg, roots, true).siteBytes;
17285
+ fixed = emitAssemblySource(table, artifact, cfg, roots, true, /* @__PURE__ */ new Set()).source.length;
17286
+ } catch (e) {
17287
+ if (e instanceof Unemittable) return { ...none, refusal: e.construct };
17288
+ throw e;
17289
+ }
17290
+ const ceiling = budget / SUPERCOMPILE_GROWTH;
17291
+ if (ceiling <= fixed) return none;
17292
+ let target = ceiling;
17293
+ for (; ; ) {
17294
+ const sites = selectHotSites(artifact.code, Object.values(artifact.rules), siteBytes, target - fixed, profile);
17295
+ if (sites.size === 0) {
17296
+ return {
17297
+ ...none,
17298
+ refusal: `a site within its ${Math.floor(ceiling)} B selection ceiling (the prelude alone is ${fixed} B)`
17299
+ };
17300
+ }
17301
+ const bytes = emitAssemblySource(table, artifact, cfg, roots, true, sites).source.length;
17302
+ if (bytes <= ceiling) return { sites, bytes: Math.ceil(bytes * SUPERCOMPILE_GROWTH) };
17303
+ target *= Math.min(ceiling / bytes, 0.99);
17304
+ }
17305
+ };
15825
17306
  return {
15826
17307
  keys: ruleMap.map(([key]) => key),
15827
17308
  replacement,
15828
17309
  replacementWithMetadata,
17310
+ selectAssembly,
15829
17311
  hostMode,
15830
17312
  // WHAT THE FLAG MEANS is "a DIRECT BUILDER's positioned-CST branch was
15831
17313
  // dropped", which is what the driver's `'ast' artifact + CST host` check keys
@@ -15907,16 +17389,16 @@ function ownSource(fn) {
15907
17389
  return typeof name === "string" && name.length > 0 && globalThis[name] === fn ? name : null;
15908
17390
  }
15909
17391
  function compile(target, second, third) {
15910
- if (!isCombinator(target)) return compileMap(target, second);
17392
+ if (!isCombinator2(target)) return compileMap(target, second);
15911
17393
  return compileRoot(target, second, third);
15912
17394
  }
15913
- function isCombinator(x) {
17395
+ function isCombinator2(x) {
15914
17396
  return typeof x === "object" && x !== null && typeof x.parse === "function" && "_def" in x;
15915
17397
  }
15916
17398
  function compileMap(grammar, opts = {}) {
15917
17399
  const entries = [];
15918
17400
  for (const [key, value] of Object.entries(grammar)) {
15919
- if (!isCombinator(value)) throw new TypeError(`compile: grammar entry "${key}" is not a parser`);
17401
+ if (!isCombinator2(value)) throw new TypeError(`compile: grammar entry "${key}" is not a parser`);
15920
17402
  if (value._def.tag === "lazy") {
15921
17403
  try {
15922
17404
  value._def.thunk();