parseman 0.49.0 → 0.50.1

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 (77) hide show
  1. package/dist/analysis/commitment.d.ts +2 -1
  2. package/dist/analysis/commitment.d.ts.map +1 -1
  3. package/dist/analysis/diagnostics.js +1824 -737
  4. package/dist/analysis/diagnostics.js.map +3 -3
  5. package/dist/analysis/rebuild.d.ts.map +1 -1
  6. package/dist/cli/index.js +1252 -164
  7. package/dist/cli/index.js.map +3 -3
  8. package/dist/combinators/trivia-skip.d.ts +1 -1
  9. package/dist/combinators/trivia-skip.d.ts.map +1 -1
  10. package/dist/compiler/build-arity.d.ts +16 -0
  11. package/dist/compiler/build-arity.d.ts.map +1 -1
  12. package/dist/compiler/degradation.d.ts +0 -2
  13. package/dist/compiler/degradation.d.ts.map +1 -1
  14. package/dist/compiler/ir-serialize.d.ts.map +1 -1
  15. package/dist/compiler/token-alphabet.d.ts +11 -0
  16. package/dist/compiler/token-alphabet.d.ts.map +1 -1
  17. package/dist/compiler/token-capability.js +185 -20
  18. package/dist/compiler/token-capability.js.map +1 -1
  19. package/dist/cst/capture-buffer.d.ts +5 -1
  20. package/dist/cst/capture-buffer.d.ts.map +1 -1
  21. package/dist/index.js +1365 -279
  22. package/dist/index.js.map +3 -3
  23. package/dist/language-service/index.js +2 -1
  24. package/dist/language-service/index.js.map +1 -1
  25. package/dist/plugin/entry-supercompiler.d.ts +48 -0
  26. package/dist/plugin/entry-supercompiler.d.ts.map +1 -0
  27. package/dist/plugin/evaluator.d.ts.map +1 -1
  28. package/dist/plugin/index.d.ts.map +1 -1
  29. package/dist/plugin/index.js +1957 -385
  30. package/dist/plugin/index.js.map +3 -3
  31. package/dist/run/index.js +2 -1
  32. package/dist/run/index.js.map +1 -1
  33. package/dist/spec/index.js +28 -7
  34. package/dist/spec/index.js.map +1 -1
  35. package/dist/table/assemble.d.ts.map +1 -1
  36. package/dist/table/compile-rule-map.d.ts +6 -5
  37. package/dist/table/compile-rule-map.d.ts.map +1 -1
  38. package/dist/table/emit-assembly.d.ts +6 -1
  39. package/dist/table/emit-assembly.d.ts.map +1 -1
  40. package/dist/table/encode.d.ts.map +1 -1
  41. package/dist/table/index.js +1315 -231
  42. package/dist/table/index.js.map +3 -3
  43. package/dist/table/ops.d.ts +3 -2
  44. package/dist/table/ops.d.ts.map +1 -1
  45. package/dist/table/program.d.ts +15 -1
  46. package/dist/table/program.d.ts.map +1 -1
  47. package/dist/table/scalar-terminal.d.ts +30 -0
  48. package/dist/table/scalar-terminal.d.ts.map +1 -1
  49. package/dist/table/site-labels.d.ts +8 -0
  50. package/dist/table/site-labels.d.ts.map +1 -1
  51. package/dist/types.d.ts +2 -1
  52. package/dist/types.d.ts.map +1 -1
  53. package/dist/version.d.ts +1 -1
  54. package/package.json +1 -1
  55. package/src/analysis/commitment.ts +19 -8
  56. package/src/analysis/rebuild.ts +1 -0
  57. package/src/combinators/trivia-skip.ts +2 -2
  58. package/src/compiler/build-arity.ts +50 -0
  59. package/src/compiler/degradation.ts +0 -6
  60. package/src/compiler/ir-serialize.ts +6 -4
  61. package/src/compiler/token-alphabet.ts +322 -28
  62. package/src/cst/capture-buffer.ts +34 -11
  63. package/src/plugin/entry-supercompiler.ts +567 -0
  64. package/src/plugin/evaluator.ts +10 -0
  65. package/src/plugin/index.ts +7 -3
  66. package/src/table/assemble.ts +125 -42
  67. package/src/table/compile-rule-map.ts +8 -7
  68. package/src/table/compile.ts +7 -8
  69. package/src/table/emit-assembly.ts +646 -126
  70. package/src/table/emit.ts +1 -1
  71. package/src/table/encode.ts +152 -7
  72. package/src/table/ops.ts +3 -2
  73. package/src/table/program.ts +44 -3
  74. package/src/table/scalar-terminal.ts +213 -1
  75. package/src/table/site-labels.ts +22 -9
  76. package/src/types.ts +1 -1
  77. package/src/version.ts +1 -1
@@ -405,7 +405,7 @@ function beginCstNodeCapture(ctx) {
405
405
  function finishCstBuf(buf) {
406
406
  if (!buf) return { children: EMPTY, rawChildren: EMPTY, triviaLog: EMPTY_TL };
407
407
  const children2 = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY);
408
- const rawChildren = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY);
408
+ const rawChildren = buf.noRaw === true ? EMPTY : buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY);
409
409
  const triviaLog = buf.tl ?? EMPTY_TL;
410
410
  return { children: children2, rawChildren, triviaLog };
411
411
  }
@@ -437,7 +437,8 @@ function pushCstChild(ctx, built, rawEntry2) {
437
437
  b.single = void 0;
438
438
  } else b.single = built;
439
439
  }
440
- if (b.raw) b.raw.push(rawEntry2);
440
+ if (b.noRaw === true) b.rawLen = (b.rawLen ?? 0) + 1;
441
+ else if (b.raw) b.raw.push(rawEntry2);
441
442
  else if (b.rawSingle !== void 0) {
442
443
  b.raw = [b.rawSingle, rawEntry2];
443
444
  b.rawSingle = void 0;
@@ -451,6 +452,7 @@ function pushCstChild(ctx, built, rawEntry2) {
451
452
  function cstRawLen(ctx) {
452
453
  const b = ctx._cstBuf;
453
454
  if (b) {
455
+ if (b.noRaw === true) return b.rawLen ?? 0;
454
456
  if (b.raw) return b.raw.length;
455
457
  return b.rawSingle !== void 0 ? 1 : 0;
456
458
  }
@@ -510,19 +512,37 @@ function rollbackCstCaptureAt(ctx, raw, tlog, leaves, fields, errors) {
510
512
  if (ctx._errors && errors !== void 0 && ctx._errors.length !== errors) ctx._errors.length = errors;
511
513
  const b = ctx._cstBuf;
512
514
  if (b) {
513
- rollbackBufList(b, "raw", "rawSingle", raw);
514
- rollbackBufList(b, "ch", "single", leaves);
515
+ if (b.noRaw === true) {
516
+ if (b.rawLen !== raw) b.rawLen = raw;
517
+ } else {
518
+ const rawList = b.raw;
519
+ if (rawList) {
520
+ if (raw === 0) b.raw = void 0;
521
+ else if (raw === 1) {
522
+ b.rawSingle = rawList[0];
523
+ b.raw = void 0;
524
+ } else if (rawList.length !== raw) rawList.length = raw;
525
+ } else if (raw === 0) b.rawSingle = void 0;
526
+ }
527
+ const childList = b.ch;
528
+ if (childList) {
529
+ if (leaves === 0) b.ch = void 0;
530
+ else if (leaves === 1) {
531
+ b.single = childList[0];
532
+ b.ch = void 0;
533
+ } else if (childList.length !== leaves) childList.length = leaves;
534
+ } else if (leaves === 0) b.single = void 0;
515
535
  if (b.tl) {
516
536
  if (tlog === 0) b.tl = void 0;
517
537
  else if (b.tl.length !== tlog) b.tl.length = tlog;
518
538
  }
519
- if (ctx._fields && ctx._fields.length !== fields) ctx._fields.length = fields;
539
+ if (ctx._fields && fields !== void 0 && ctx._fields.length !== fields) ctx._fields.length = fields;
520
540
  return;
521
541
  }
522
542
  if (ctx._cstRawChildren && ctx._cstRawChildren.length !== raw) ctx._cstRawChildren.length = raw;
523
543
  if (ctx._cstTriviaLog && ctx._cstTriviaLog.length !== tlog) ctx._cstTriviaLog.length = tlog;
524
544
  if (ctx._cstLeaves && ctx._cstLeaves.length !== leaves) ctx._cstLeaves.length = leaves;
525
- if (ctx._fields && ctx._fields.length !== fields) ctx._fields.length = fields;
545
+ if (ctx._fields && fields !== void 0 && ctx._fields.length !== fields) ctx._fields.length = fields;
526
546
  }
527
547
  function pushCstTriviaEntry(ctx, start, end, kindIndex) {
528
548
  const insertIdx = cstRawLen(ctx);
@@ -2620,222 +2640,780 @@ function analyzeChoice(p, d, rule2, resolve) {
2620
2640
  };
2621
2641
  }
2622
2642
 
2623
- // src/recovery/scan.ts
2624
- function probeAt(sentinel, input, pos, ctx) {
2625
- const s = {
2626
- _probe: ctx._probe,
2627
- _errors: ctx._errors,
2628
- _cstLeaves: ctx._cstLeaves,
2629
- _cstChildren: ctx._cstChildren,
2630
- _cstRawChildren: ctx._cstRawChildren,
2631
- _cstTriviaLog: ctx._cstTriviaLog,
2632
- _triviaLog: ctx._triviaLog,
2633
- _rootTriviaLog: ctx._rootTriviaLog,
2634
- _fields: ctx._fields,
2635
- _cstBuf: ctx._cstBuf,
2636
- _tolerant: ctx._tolerant,
2637
- _sync: ctx._sync
2638
- };
2639
- ctx._probe = void 0;
2640
- ctx._errors = void 0;
2641
- ctx._cstLeaves = void 0;
2642
- ctx._cstChildren = void 0;
2643
- ctx._cstRawChildren = void 0;
2644
- ctx._cstTriviaLog = void 0;
2645
- ctx._triviaLog = void 0;
2646
- ctx._rootTriviaLog = void 0;
2647
- ctx._fields = void 0;
2648
- ctx._cstBuf = void 0;
2649
- ctx._tolerant = void 0;
2650
- ctx._sync = void 0;
2651
- try {
2652
- return sentinel.parse(input, pos, ctx).ok;
2653
- } finally {
2654
- ctx._probe = s._probe;
2655
- ctx._errors = s._errors;
2656
- ctx._cstLeaves = s._cstLeaves;
2657
- ctx._cstChildren = s._cstChildren;
2658
- ctx._cstRawChildren = s._cstRawChildren;
2659
- ctx._cstTriviaLog = s._cstTriviaLog;
2660
- ctx._triviaLog = s._triviaLog;
2661
- ctx._rootTriviaLog = s._rootTriviaLog;
2662
- ctx._fields = s._fields;
2663
- ctx._cstBuf = s._cstBuf;
2664
- ctx._tolerant = s._tolerant;
2665
- ctx._sync = s._sync;
2666
- }
2667
- }
2668
- function orSentinel(a, b) {
2669
- if (b === void 0) return a;
2670
- return {
2671
- _tag: "orSentinel",
2672
- _meta: { firstSet: { kind: "any" }, canMatchNewline: false, isTrivia: false },
2673
- _def: { tag: "unknown" },
2674
- parse(input, pos, ctx) {
2675
- const ra = a.parse(input, pos, ctx);
2676
- if (ra.ok) return ra;
2677
- return b.parse(input, pos, ctx);
2678
- }
2679
- };
2680
- }
2681
- function firstSetSentinel(fs) {
2682
- if (fs.kind !== "ranges" || fs.ranges.length === 0) return null;
2683
- const ranges = fs.ranges;
2684
- return {
2685
- _tag: "firstSetSentinel",
2686
- _meta: { firstSet: fs, canMatchNewline: false, isTrivia: false },
2687
- _def: { tag: "unknown" },
2688
- parse(input, pos) {
2689
- const code = pos < input.length ? input.codePointAt(pos) : void 0;
2690
- if (code !== void 0) {
2691
- for (const r of ranges) {
2692
- if (code >= r.lo && code <= r.hi) return { ok: true, value: null, span: { start: pos, end: pos } };
2693
- }
2694
- }
2695
- return { ok: false, expected: [], span: { start: pos, end: pos } };
2696
- }
2697
- };
2698
- }
2699
- function recoverScan(input, from, ctx, sync, expected) {
2700
- let scanPos = from;
2701
- while (scanPos < input.length && !probeAt(sync, input, scanPos, ctx)) scanPos++;
2702
- const span = { start: from, end: scanPos };
2703
- if (ctx.trackLines) recordLineRangeFromContext(ctx, input, from, scanPos);
2704
- const error = { _tag: "parseError", span: ctx.trackLines ? annotateSpanFromLineContext(span, ctx) : span, expected };
2705
- ctx._errors?.push(error);
2706
- return { error, end: scanPos };
2707
- }
2708
- function matchesAt(sentinel, input, pos, ctx) {
2709
- return probeAt(sentinel, input, pos, ctx);
2643
+ // src/regex/first-set.ts
2644
+ var ANY = { t: "any" };
2645
+ var EMPTY2 = { t: "empty" };
2646
+ function charNode(set, nl) {
2647
+ return { t: "char", set, nl };
2710
2648
  }
2711
- function captureError(ctx, error) {
2712
- if (cstCaptureActive(ctx)) pushCstChild(ctx, error, error);
2649
+ function rangesToSet(ranges) {
2650
+ let fs = empty();
2651
+ for (const [lo, hi] of ranges) fs = union(fs, fromRange(lo, hi));
2652
+ return fs;
2713
2653
  }
2714
-
2715
- // src/combinators/expect.ts
2716
- function deriveExpected(c) {
2717
- return [...new Set(derive(c, /* @__PURE__ */ new Set()))];
2654
+ function rangesHaveNewline(ranges) {
2655
+ return ranges.some(([lo, hi]) => lo <= 10 && 10 <= hi);
2718
2656
  }
2719
- function derive(c, seen) {
2720
- const deriveExpected2 = (p) => derive(p, seen);
2721
- const def = c._def;
2722
- switch (def.tag) {
2723
- case "literal":
2724
- return [JSON.stringify(def.value)];
2725
- case "regex":
2726
- return [`/${def.source}/`];
2727
- case "keywords":
2728
- return def.words.map((w) => JSON.stringify(w));
2729
- case "label":
2730
- return [def.label];
2731
- case "choice":
2732
- return def.parsers.flatMap(deriveExpected2);
2733
- case "dispatch":
2734
- return deriveExpected2(def.selector);
2735
- // Union through the NULLABLE prefix, mirroring `sequenceFirstSet`. A leading
2736
- // `optional(…)`/`many(…)` can match nothing, so the term after it is equally
2737
- // able to fail first — deriving from term 0 alone named a token the parse
2738
- // never actually required. A leading `not(…)` is zero-width and contributes
2739
- // nothing (its own expectation is about what must NOT be here), but it is
2740
- // nullable, so keep scanning past it. Stop at the first term that must match.
2741
- case "sequence": {
2742
- const out = [];
2743
- for (const term of def.parsers) {
2744
- if (!isZeroWidthAssertion(term)) out.push(...deriveExpected2(term));
2745
- if (!matchesEmpty(term)) break;
2746
- }
2747
- return out;
2748
- }
2749
- case "attempt":
2750
- return deriveExpected2(def.parser);
2751
- // Delegating wrappers whose first-token failure is their inner parser's — must
2752
- // pass through so a start-failure (and the first-set-miss fast-path in attempt/
2753
- // node, which reads this) names the real expected token, not the wrapper tag.
2754
- case "field":
2755
- case "withCtx":
2756
- case "recover":
2757
- return deriveExpected2(def.parser);
2758
- case "expect":
2759
- return def.expected;
2760
- case "node":
2761
- case "grammar":
2762
- case "trivia":
2763
- case "token":
2764
- case "leaf":
2765
- case "optional":
2766
- case "many":
2767
- case "oneOrMore":
2768
- case "transform":
2769
- case "not":
2770
- case "peek":
2771
- return deriveExpected2(def.parser);
2772
- // A bare routed() can only fail as "there is no routed token here". With a
2773
- // fallback, THAT is the branch that can fail, so its expectations are the useful
2774
- // ones — the routed path either succeeds or is not taken.
2775
- case "routed":
2776
- return def.fallback === void 0 ? ["routed()"] : deriveExpected2(def.fallback);
2777
- // A bare adjacency assertion names the JOIN it requires. Inside a sequence it is
2778
- // skipped entirely (isZeroWidthAssertion, above), which is the normal path.
2779
- case "adjacency":
2780
- return [def.polarity];
2781
- case "lazy": {
2782
- const name = c._ruleName;
2783
- if (seen.has(c)) return name ? [name] : [];
2784
- seen.add(c);
2785
- try {
2786
- return deriveExpected2(def.thunk());
2787
- } catch {
2788
- return name ? [name] : [];
2789
- } finally {
2790
- seen.delete(c);
2791
- }
2657
+ var BAIL = /* @__PURE__ */ Symbol("regex-bail");
2658
+ function parseRegex(src) {
2659
+ let i = 0;
2660
+ const parseAlt = () => {
2661
+ const arms = [parseSeq()];
2662
+ while (src[i] === "|") {
2663
+ i++;
2664
+ arms.push(parseSeq());
2792
2665
  }
2793
- default:
2794
- return [];
2795
- }
2796
- }
2797
- function expect(combinator, label2) {
2798
- const expected = label2 !== void 0 ? [label2] : deriveExpected(combinator);
2799
- const meta = {
2800
- firstSet: combinator._meta.firstSet,
2801
- canMatchNewline: combinator._meta.canMatchNewline,
2802
- isTrivia: false
2666
+ return arms.length === 1 ? arms[0] : { t: "alt", arms };
2803
2667
  };
2804
- return {
2805
- _tag: "expect",
2806
- _meta: meta,
2807
- _def: { tag: "expect", parser: combinator, label: label2, expected },
2808
- parse(input, pos, ctx) {
2809
- const result = combinator.parse(input, pos, ctx);
2810
- if (result.ok) return result;
2811
- const span = { start: pos, end: pos };
2812
- const error = { _tag: "parseError", span: ctx.trackLines ? annotateSpanFromLineContext(span, ctx) : span, expected };
2813
- ctx._errors?.push(error);
2814
- if (ctx._tolerant) captureError(ctx, error);
2815
- return { ok: true, value: error, span: { start: pos, end: pos } };
2668
+ const parseSeq = () => {
2669
+ const parts = [];
2670
+ while (i < src.length) {
2671
+ const ch2 = src[i];
2672
+ if (ch2 === "|" || ch2 === ")") break;
2673
+ parts.push(parseQuantified());
2816
2674
  }
2675
+ if (parts.length === 0) return EMPTY2;
2676
+ return parts.length === 1 ? parts[0] : { t: "seq", parts };
2817
2677
  };
2818
- }
2819
-
2820
- // src/combinators/choice.ts
2821
- function choice(...args) {
2822
- const parsers = args.map((a) => "gate" in a ? a.combinator : a);
2823
- const gates = args.map((a) => "gate" in a ? a.gate : null);
2824
- const hasGates = gates.some((g) => g !== null);
2825
- const disjoint = areDisjoint(parsers.map((p) => p._meta.firstSet)) && parsers.every((p) => !matchesEmpty(p));
2826
- let combined = { kind: "empty" };
2827
- for (const p of parsers) combined = union(combined, p._meta.firstSet);
2828
- const meta = {
2829
- firstSet: combined,
2830
- canMatchNewline: parsers.some((p) => p._meta.canMatchNewline),
2831
- isTrivia: false,
2832
- disjoint
2678
+ const parseQuantified = () => {
2679
+ const atom = parseAtom();
2680
+ const ch2 = src[i];
2681
+ let min = null;
2682
+ if (ch2 === "*") {
2683
+ min = 0;
2684
+ i++;
2685
+ } else if (ch2 === "+") {
2686
+ min = 1;
2687
+ i++;
2688
+ } else if (ch2 === "?") {
2689
+ min = 0;
2690
+ i++;
2691
+ } else if (ch2 === "{") {
2692
+ min = parseBraceQuantifier();
2693
+ }
2694
+ if (min === null) return atom;
2695
+ if (src[i] === "?") i++;
2696
+ return { t: "rep", node: atom, min };
2833
2697
  };
2834
- const strategy = disjoint || hasGates ? null : detectStrategy(parsers);
2835
- const autoNot = !disjoint && !hasGates && (strategy?.tag === "firstMatch" || strategy?.tag === "sharedPrefix") ? computeAutoNot(parsers) : parsers.map(() => null);
2836
- let greedyLitMap = null;
2837
- let sortedParsers = null;
2838
- const asciiDispatch = disjoint ? buildAsciiDispatch(parsers) : null;
2698
+ const parseBraceQuantifier = () => {
2699
+ const close = src.indexOf("}", i);
2700
+ if (close === -1) return null;
2701
+ const m = /^(\d+)(?:,(\d*))?$/.exec(src.slice(i + 1, close));
2702
+ if (!m) return null;
2703
+ i = close + 1;
2704
+ return Number.parseInt(m[1], 10);
2705
+ };
2706
+ const parseAtom = () => {
2707
+ const ch2 = src[i];
2708
+ switch (ch2) {
2709
+ case "(":
2710
+ return parseGroup();
2711
+ case "[":
2712
+ return parseClass();
2713
+ case ".":
2714
+ i++;
2715
+ return charNode(any(), false);
2716
+ // `.` matches any char except line terminators
2717
+ case "\\":
2718
+ return parseEscape();
2719
+ case "^":
2720
+ case "$":
2721
+ i++;
2722
+ return EMPTY2;
2723
+ // anchors are zero-width
2724
+ case "{":
2725
+ i++;
2726
+ return charNode(fromRange(123, 123), false);
2727
+ // a `{` with nothing to quantify is a literal brace
2728
+ default:
2729
+ i += ch2.length;
2730
+ return charNode(fromRange(ch2.codePointAt(0), ch2.codePointAt(0)), ch2 === "\n");
2731
+ }
2732
+ };
2733
+ const parseGroup = () => {
2734
+ i++;
2735
+ let lookaround = false;
2736
+ if (src[i] === "?") {
2737
+ const c1 = src[i + 1];
2738
+ if (c1 === ":") i += 2;
2739
+ else if (c1 === "=" || c1 === "!") {
2740
+ i += 2;
2741
+ lookaround = true;
2742
+ } else if (c1 === "<") {
2743
+ const c2 = src[i + 2];
2744
+ if (c2 === "=" || c2 === "!") {
2745
+ i += 3;
2746
+ lookaround = true;
2747
+ } else {
2748
+ const gt = src.indexOf(">", i);
2749
+ if (gt === -1) throw BAIL;
2750
+ i = gt + 1;
2751
+ }
2752
+ } else throw BAIL;
2753
+ }
2754
+ const inner = parseAlt();
2755
+ if (src[i] !== ")") throw BAIL;
2756
+ i++;
2757
+ return lookaround ? EMPTY2 : inner;
2758
+ };
2759
+ const parseClass = () => {
2760
+ let k = i + 1;
2761
+ const negated = src[k] === "^";
2762
+ if (negated) k++;
2763
+ let body = "";
2764
+ while (k < src.length && src[k] !== "]") {
2765
+ if (src[k] === "\\") {
2766
+ body += src[k] + (src[k + 1] ?? "");
2767
+ k += 2;
2768
+ } else {
2769
+ body += src[k];
2770
+ k++;
2771
+ }
2772
+ }
2773
+ if (src[k] !== "]") throw BAIL;
2774
+ i = k + 1;
2775
+ const ranges = parseClassRanges(body);
2776
+ if (negated) return charNode(any(), !ranges || !rangesHaveNewline(ranges));
2777
+ if (!ranges) return charNode(any(), true);
2778
+ return charNode(rangesToSet(ranges), rangesHaveNewline(ranges));
2779
+ };
2780
+ const parseEscape = () => {
2781
+ const e = src[i + 1];
2782
+ if (e === void 0) throw BAIL;
2783
+ if (e === "u" && /^[0-9a-fA-F]{4}$/.test(src.slice(i + 2, i + 6))) {
2784
+ const cp = Number.parseInt(src.slice(i + 2, i + 6), 16);
2785
+ i += 6;
2786
+ return charNode(fromRange(cp, cp), cp === 10);
2787
+ }
2788
+ if (e === "x" && /^[0-9a-fA-F]{2}$/.test(src.slice(i + 2, i + 4))) {
2789
+ const cp = Number.parseInt(src.slice(i + 2, i + 4), 16);
2790
+ i += 4;
2791
+ return charNode(fromRange(cp, cp), cp === 10);
2792
+ }
2793
+ i += 2;
2794
+ switch (e) {
2795
+ case "d":
2796
+ return charNode(rangesToSet(shorthandRanges("d")), false);
2797
+ case "w":
2798
+ return charNode(rangesToSet(shorthandRanges("w")), false);
2799
+ case "s":
2800
+ return charNode(rangesToSet(shorthandRanges("s")), true);
2801
+ case "D":
2802
+ case "W":
2803
+ case "S":
2804
+ return charNode(any(), true);
2805
+ // negated shorthand → widen
2806
+ case "b":
2807
+ case "B":
2808
+ return EMPTY2;
2809
+ // word boundary: zero-width
2810
+ case "n":
2811
+ return charNode(fromRange(10, 10), true);
2812
+ case "r":
2813
+ return charNode(fromRange(13, 13), false);
2814
+ case "t":
2815
+ return charNode(fromRange(9, 9), false);
2816
+ case "f":
2817
+ return charNode(fromRange(12, 12), false);
2818
+ case "v":
2819
+ return charNode(fromRange(11, 11), false);
2820
+ case "0":
2821
+ return charNode(fromRange(0, 0), false);
2822
+ default:
2823
+ if (e >= "1" && e <= "9") return ANY;
2824
+ return charNode(fromRange(e.codePointAt(0), e.codePointAt(0)), e === "\n");
2825
+ }
2826
+ };
2827
+ const node2 = parseAlt();
2828
+ if (i < src.length) throw BAIL;
2829
+ return node2;
2830
+ }
2831
+ function nullable(n) {
2832
+ switch (n.t) {
2833
+ case "char":
2834
+ return false;
2835
+ case "any":
2836
+ return true;
2837
+ case "empty":
2838
+ return true;
2839
+ case "seq":
2840
+ return n.parts.every(nullable);
2841
+ case "alt":
2842
+ return n.arms.some(nullable);
2843
+ case "rep":
2844
+ return n.min === 0 || nullable(n.node);
2845
+ }
2846
+ }
2847
+ function firstSet(n) {
2848
+ switch (n.t) {
2849
+ case "char":
2850
+ return n.set;
2851
+ case "any":
2852
+ return any();
2853
+ case "empty":
2854
+ return empty();
2855
+ case "rep":
2856
+ return firstSet(n.node);
2857
+ case "alt": {
2858
+ let fs = empty();
2859
+ for (const arm of n.arms) fs = union(fs, firstSet(arm));
2860
+ return fs;
2861
+ }
2862
+ case "seq": {
2863
+ let fs = empty();
2864
+ for (const part of n.parts) {
2865
+ fs = union(fs, firstSet(part));
2866
+ if (!nullable(part)) break;
2867
+ }
2868
+ return fs;
2869
+ }
2870
+ }
2871
+ }
2872
+ function canConsumeNewline(n) {
2873
+ switch (n.t) {
2874
+ case "char":
2875
+ return n.nl;
2876
+ case "any":
2877
+ return true;
2878
+ case "empty":
2879
+ return false;
2880
+ case "rep":
2881
+ return canConsumeNewline(n.node);
2882
+ case "alt":
2883
+ return n.arms.some(canConsumeNewline);
2884
+ case "seq":
2885
+ return n.parts.some(canConsumeNewline);
2886
+ }
2887
+ }
2888
+ function regexCanMatchEmpty(source) {
2889
+ try {
2890
+ return nullable(parseRegex(source));
2891
+ } catch {
2892
+ return true;
2893
+ }
2894
+ }
2895
+ function firstSetFromRegex(source) {
2896
+ let ast;
2897
+ try {
2898
+ ast = parseRegex(source);
2899
+ } catch {
2900
+ return { firstSet: any(), canMatchNewline: true };
2901
+ }
2902
+ if (nullable(ast)) return { firstSet: any(), canMatchNewline: canConsumeNewline(ast) };
2903
+ return { firstSet: firstSet(ast), canMatchNewline: canConsumeNewline(ast) };
2904
+ }
2905
+
2906
+ // src/analysis/commitment.ts
2907
+ function mayFail(p, seen = /* @__PURE__ */ new Set()) {
2908
+ if (seen.has(p)) return true;
2909
+ seen.add(p);
2910
+ const d = p._def;
2911
+ switch (d.tag) {
2912
+ case "literal":
2913
+ return d.value.length > 0;
2914
+ case "trivia":
2915
+ return false;
2916
+ // `optional`/`many`/a min-0 `sepBy` swallow an ORDINARY failure — zero
2917
+ // repetitions is a match. They do NOT swallow a COMMITTED one: a dispatch
2918
+ // that has selected an arm and then failed inside it breaks out past every
2919
+ // enclosing repeat, straight to the fallible boundary. So these are total
2920
+ // exactly when their body cannot commit. (Measured: treating them as
2921
+ // unconditionally total left an extra zero-width leaf in
2922
+ // `BareInterpolatedSelector` on benchmark.less — a rollback the legacy
2923
+ // build fired and this one had deleted.)
2924
+ case "optional":
2925
+ case "many":
2926
+ return mayCommitFailure(d.parser);
2927
+ case "sepBy":
2928
+ return d.min >= 1 ? mayFail(d.parser, seen) : mayCommitFailure(d.parser) || mayCommitFailure(d.separator);
2929
+ case "oneOrMore":
2930
+ return mayFail(d.parser, seen);
2931
+ case "sequence":
2932
+ return d.parsers.some((x) => mayFail(x, seen));
2933
+ // Delegating wrappers: as fallible as what they wrap.
2934
+ case "node":
2935
+ case "transform":
2936
+ case "label":
2937
+ case "field":
2938
+ case "expect":
2939
+ case "withCtx":
2940
+ case "grammar":
2941
+ case "token":
2942
+ case "leaf":
2943
+ return mayFail(d.parser, seen);
2944
+ case "lazy": {
2945
+ try {
2946
+ return mayFail(d.thunk(), seen);
2947
+ } catch {
2948
+ return true;
2949
+ }
2950
+ }
2951
+ // An adjacency assertion is a TEST — failing is its whole job.
2952
+ case "adjacency":
2953
+ return true;
2954
+ default:
2955
+ return true;
2956
+ }
2957
+ }
2958
+ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set(), triviaActive = true) {
2959
+ if (seen.has(p)) return false;
2960
+ seen.add(p);
2961
+ const d = p._def;
2962
+ switch (d.tag) {
2963
+ // Atomic / non-capturing-then-failing: a failure happens before any push.
2964
+ case "literal":
2965
+ case "regex":
2966
+ case "keywords":
2967
+ case "guard":
2968
+ // Adjacency probes with `_cap = 0` / no `commit()`: it cannot push anything.
2969
+ case "adjacency":
2970
+ case "not":
2971
+ // peek(): emitted under a non-capturing probe ctx and zero-width on both
2972
+ // outcomes, so it can never leave a partial capture behind.
2973
+ case "peek":
2974
+ case "trivia":
2975
+ case "token":
2976
+ case "leaf":
2977
+ case "scanTo":
2978
+ case "unknown":
2979
+ return false;
2980
+ // node() captures into its own private buffers and rolls them back on
2981
+ // failure (emitNode restores _ctx.* and never pushes on the !ok path).
2982
+ case "node":
2983
+ return false;
2984
+ // choice/firstMatch already roll back each failed arm; on overall failure
2985
+ // nothing committed remains.
2986
+ case "choice":
2987
+ return false;
2988
+ case "dispatch":
2989
+ return capturesLeaf(d.selector, new Set(seen)) || d.cases.some((x) => mayLeavePartialCapture(x.parser, new Set(seen), triviaActive) || capturesLeaf(x.parser, new Set(seen))) || (d.matchers ? d.matchers.some((x) => mayLeavePartialCapture(x.parser, new Set(seen), triviaActive) || capturesLeaf(x.parser, new Set(seen))) : false) || (d.otherwise ? mayLeavePartialCapture(d.otherwise, new Set(seen), triviaActive) || capturesLeaf(d.otherwise, new Set(seen)) : false);
2990
+ case "attempt":
2991
+ return false;
2992
+ // optional never fails; many/oneOrMore only "fail" with zero captured items.
2993
+ case "optional":
2994
+ case "many":
2995
+ case "oneOrMore":
2996
+ return false;
2997
+ // sepBy emits its own per-iteration rollback in emitSepBy.
2998
+ case "sepBy":
2999
+ return false;
3000
+ // A sequence is the real case: an earlier capturing term followed by a term
3001
+ // that can fail leaves the earlier captures buffered.
3002
+ //
3003
+ // BOTH halves of that sentence are load-bearing, and the second half is what
3004
+ // this walk exists to exploit. "Some earlier term captures" alone was the old
3005
+ // test, and it is true of very nearly every sequence in a real grammar — a
3006
+ // sequence almost always opens with a literal or a node. The rollback is only
3007
+ // reachable if something AFTER the capture can still fail; once the remainder
3008
+ // is total (`optional`/`many`/trivia/a min-0 `sepBy`), the sequence has no
3009
+ // failure path left to roll back from, and the save+restore is dead code.
3010
+ //
3011
+ // `captured` tracks whether anything is in the buffers yet as the scan moves
3012
+ // left to right. Two things put it there:
3013
+ // - a term that captures (`capturesLeaf`/`hasNodeDef`), and
3014
+ // - the inter-term TRIVIA scan, which under `capturing` pushes into
3015
+ // `_cstRawChildren`/`_cstTriviaLog` BEFORE the term at each boundary
3016
+ // i >= 1. `emitSeqValues` only rewinds that push on the term's SUCCESS
3017
+ // path (the "matched empty, so leave the whitespace out of the span"
3018
+ // branch); a term that FAILS breaks straight out with the trivia still
3019
+ // buffered, so from boundary 1 onward the buffers are dirty regardless of
3020
+ // what the earlier terms did.
3021
+ // Each term is also asked about itself: a nested sequence can leave its own
3022
+ // partial capture behind, and its terms are emitted inline into this same
3023
+ // block with no boundary of their own to roll them back.
3024
+ case "sequence": {
3025
+ const parts = d.parsers;
3026
+ let captured = false;
3027
+ for (let i = 0; i < parts.length; i++) {
3028
+ const part = parts[i];
3029
+ if (i > 0 && triviaActive) captured = true;
3030
+ if (captured && mayFail(part)) return true;
3031
+ if (mayLeavePartialCapture(part, seen, triviaActive)) return true;
3032
+ if (capturesLeaf(part) || hasNodeDef(part)) captured = true;
3033
+ }
3034
+ return false;
3035
+ }
3036
+ // Delegating wrappers: defer to the wrapped parser.
3037
+ case "transform":
3038
+ case "label":
3039
+ case "field":
3040
+ case "expect":
3041
+ case "withCtx":
3042
+ case "grammar":
3043
+ return mayLeavePartialCapture(d.parser, seen, triviaActive);
3044
+ case "recover":
3045
+ return mayLeavePartialCapture(d.parser, seen, triviaActive);
3046
+ case "lazy": {
3047
+ try {
3048
+ return mayLeavePartialCapture(d.thunk(), seen, triviaActive);
3049
+ } catch {
3050
+ return true;
3051
+ }
3052
+ }
3053
+ // Unknown shapes: be safe and keep the rollback.
3054
+ default:
3055
+ return true;
3056
+ }
3057
+ }
3058
+ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
3059
+ if (seen.has(p)) return false;
3060
+ seen.add(p);
3061
+ const d = p._def;
3062
+ switch (d.tag) {
3063
+ case "literal":
3064
+ case "regex":
3065
+ case "keywords":
3066
+ case "node":
3067
+ case "token":
3068
+ case "routed":
3069
+ case "leaf":
3070
+ return true;
3071
+ case "not":
3072
+ case "peek":
3073
+ case "guard":
3074
+ case "adjacency":
3075
+ case "trivia":
3076
+ case "unknown":
3077
+ return false;
3078
+ case "sequence":
3079
+ case "choice":
3080
+ return d.parsers.some((x) => capturesLeaf(x, seen));
3081
+ case "dispatch":
3082
+ return capturesLeaf(d.selector, seen) || d.cases.some((x) => capturesLeaf(x.parser, seen)) || (d.matchers ? d.matchers.some((entry) => capturesLeaf(entry.parser, seen)) : false) || (d.otherwise ? capturesLeaf(d.otherwise, seen) : false);
3083
+ case "sepBy":
3084
+ return capturesLeaf(d.parser, seen) || capturesLeaf(d.separator, seen);
3085
+ case "many":
3086
+ case "oneOrMore":
3087
+ case "optional":
3088
+ case "attempt":
3089
+ case "transform":
3090
+ case "label":
3091
+ case "field":
3092
+ case "expect":
3093
+ case "withCtx":
3094
+ case "grammar":
3095
+ case "recover":
3096
+ return capturesLeaf(d.parser, seen);
3097
+ case "scanTo":
3098
+ return true;
3099
+ case "lazy": {
3100
+ try {
3101
+ return capturesLeaf(d.thunk(), seen);
3102
+ } catch {
3103
+ return true;
3104
+ }
3105
+ }
3106
+ default:
3107
+ return true;
3108
+ }
3109
+ }
3110
+ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
3111
+ if (seen.has(p)) return false;
3112
+ seen.add(p);
3113
+ const d = p._def;
3114
+ switch (d.tag) {
3115
+ case "node":
3116
+ return true;
3117
+ case "lazy": {
3118
+ try {
3119
+ return hasNodeDef(d.thunk(), seen);
3120
+ } catch {
3121
+ return false;
3122
+ }
3123
+ }
3124
+ case "grammar":
3125
+ case "trivia":
3126
+ case "token":
3127
+ case "leaf":
3128
+ case "label":
3129
+ case "field":
3130
+ case "optional":
3131
+ case "many":
3132
+ case "oneOrMore":
3133
+ case "not":
3134
+ case "peek":
3135
+ case "transform":
3136
+ return hasNodeDef(d.parser, seen);
3137
+ case "sequence":
3138
+ case "choice":
3139
+ return d.parsers.some((x) => hasNodeDef(x, seen));
3140
+ case "dispatch":
3141
+ return hasNodeDef(d.selector, seen) || d.cases.some((x) => hasNodeDef(x.parser, seen)) || (d.matchers ? d.matchers.some((entry) => hasNodeDef(entry.parser, seen)) : false) || (d.otherwise ? hasNodeDef(d.otherwise, seen) : false);
3142
+ case "sepBy":
3143
+ return hasNodeDef(d.parser, seen) || hasNodeDef(d.separator, seen);
3144
+ case "scanTo":
3145
+ return hasNodeDef(d.sentinel, seen) || d.skip.some((x) => hasNodeDef(x, seen));
3146
+ case "recover":
3147
+ return hasNodeDef(d.parser, seen) || hasNodeDef(d.sentinel, seen);
3148
+ case "expect":
3149
+ return hasNodeDef(d.parser, seen);
3150
+ case "withCtx":
3151
+ return hasNodeDef(d.parser, seen);
3152
+ default:
3153
+ return false;
3154
+ }
3155
+ }
3156
+ function mayCommitFailure(p, seen = /* @__PURE__ */ new Set(), resolve) {
3157
+ if (seen.has(p)) return false;
3158
+ seen.add(p);
3159
+ const d = p._def;
3160
+ switch (d.tag) {
3161
+ case "dispatch":
3162
+ return true;
3163
+ case "choice":
3164
+ case "sequence":
3165
+ return d.parsers.some((x) => mayCommitFailure(x, seen, resolve));
3166
+ case "many":
3167
+ case "oneOrMore":
3168
+ case "optional":
3169
+ case "attempt":
3170
+ case "transform":
3171
+ case "label":
3172
+ case "field":
3173
+ case "grammar":
3174
+ case "node":
3175
+ return mayCommitFailure(d.parser, seen, resolve);
3176
+ case "sepBy":
3177
+ return mayCommitFailure(d.parser, seen, resolve) || mayCommitFailure(d.separator, seen, resolve);
3178
+ case "token":
3179
+ case "leaf":
3180
+ return mayCommitFailure(d.parser, seen, resolve);
3181
+ case "withCtx":
3182
+ return mayCommitFailure(d.parser, seen, resolve);
3183
+ case "scanTo":
3184
+ return mayCommitFailure(d.sentinel, seen, resolve) || d.skip.some((x) => mayCommitFailure(x, seen, resolve));
3185
+ case "lazy": {
3186
+ try {
3187
+ return mayCommitFailure(d.thunk(), seen, resolve);
3188
+ } catch {
3189
+ const name = p._ruleName;
3190
+ const target = name === void 0 ? void 0 : resolve?.(name);
3191
+ return target === void 0 ? true : mayCommitFailure(target, seen, resolve);
3192
+ }
3193
+ }
3194
+ case "unknown":
3195
+ return true;
3196
+ default:
3197
+ return false;
3198
+ }
3199
+ }
3200
+
3201
+ // src/recovery/scan.ts
3202
+ function probeAt(sentinel, input, pos, ctx) {
3203
+ const s = {
3204
+ _probe: ctx._probe,
3205
+ _errors: ctx._errors,
3206
+ _cstLeaves: ctx._cstLeaves,
3207
+ _cstChildren: ctx._cstChildren,
3208
+ _cstRawChildren: ctx._cstRawChildren,
3209
+ _cstTriviaLog: ctx._cstTriviaLog,
3210
+ _triviaLog: ctx._triviaLog,
3211
+ _rootTriviaLog: ctx._rootTriviaLog,
3212
+ _fields: ctx._fields,
3213
+ _cstBuf: ctx._cstBuf,
3214
+ _tolerant: ctx._tolerant,
3215
+ _sync: ctx._sync
3216
+ };
3217
+ ctx._probe = void 0;
3218
+ ctx._errors = void 0;
3219
+ ctx._cstLeaves = void 0;
3220
+ ctx._cstChildren = void 0;
3221
+ ctx._cstRawChildren = void 0;
3222
+ ctx._cstTriviaLog = void 0;
3223
+ ctx._triviaLog = void 0;
3224
+ ctx._rootTriviaLog = void 0;
3225
+ ctx._fields = void 0;
3226
+ ctx._cstBuf = void 0;
3227
+ ctx._tolerant = void 0;
3228
+ ctx._sync = void 0;
3229
+ try {
3230
+ return sentinel.parse(input, pos, ctx).ok;
3231
+ } finally {
3232
+ ctx._probe = s._probe;
3233
+ ctx._errors = s._errors;
3234
+ ctx._cstLeaves = s._cstLeaves;
3235
+ ctx._cstChildren = s._cstChildren;
3236
+ ctx._cstRawChildren = s._cstRawChildren;
3237
+ ctx._cstTriviaLog = s._cstTriviaLog;
3238
+ ctx._triviaLog = s._triviaLog;
3239
+ ctx._rootTriviaLog = s._rootTriviaLog;
3240
+ ctx._fields = s._fields;
3241
+ ctx._cstBuf = s._cstBuf;
3242
+ ctx._tolerant = s._tolerant;
3243
+ ctx._sync = s._sync;
3244
+ }
3245
+ }
3246
+ function orSentinel(a, b) {
3247
+ if (b === void 0) return a;
3248
+ return {
3249
+ _tag: "orSentinel",
3250
+ _meta: { firstSet: { kind: "any" }, canMatchNewline: false, isTrivia: false },
3251
+ _def: { tag: "unknown" },
3252
+ parse(input, pos, ctx) {
3253
+ const ra = a.parse(input, pos, ctx);
3254
+ if (ra.ok) return ra;
3255
+ return b.parse(input, pos, ctx);
3256
+ }
3257
+ };
3258
+ }
3259
+ function firstSetSentinel(fs) {
3260
+ if (fs.kind !== "ranges" || fs.ranges.length === 0) return null;
3261
+ const ranges = fs.ranges;
3262
+ return {
3263
+ _tag: "firstSetSentinel",
3264
+ _meta: { firstSet: fs, canMatchNewline: false, isTrivia: false },
3265
+ _def: { tag: "unknown" },
3266
+ parse(input, pos) {
3267
+ const code = pos < input.length ? input.codePointAt(pos) : void 0;
3268
+ if (code !== void 0) {
3269
+ for (const r of ranges) {
3270
+ if (code >= r.lo && code <= r.hi) return { ok: true, value: null, span: { start: pos, end: pos } };
3271
+ }
3272
+ }
3273
+ return { ok: false, expected: [], span: { start: pos, end: pos } };
3274
+ }
3275
+ };
3276
+ }
3277
+ function recoverScan(input, from, ctx, sync, expected) {
3278
+ let scanPos = from;
3279
+ while (scanPos < input.length && !probeAt(sync, input, scanPos, ctx)) scanPos++;
3280
+ const span = { start: from, end: scanPos };
3281
+ if (ctx.trackLines) recordLineRangeFromContext(ctx, input, from, scanPos);
3282
+ const error = { _tag: "parseError", span: ctx.trackLines ? annotateSpanFromLineContext(span, ctx) : span, expected };
3283
+ ctx._errors?.push(error);
3284
+ return { error, end: scanPos };
3285
+ }
3286
+ function matchesAt(sentinel, input, pos, ctx) {
3287
+ return probeAt(sentinel, input, pos, ctx);
3288
+ }
3289
+ function captureError(ctx, error) {
3290
+ if (cstCaptureActive(ctx)) pushCstChild(ctx, error, error);
3291
+ }
3292
+
3293
+ // src/combinators/expect.ts
3294
+ function deriveExpected(c) {
3295
+ return [...new Set(derive(c, /* @__PURE__ */ new Set()))];
3296
+ }
3297
+ function derive(c, seen) {
3298
+ const deriveExpected2 = (p) => derive(p, seen);
3299
+ const def = c._def;
3300
+ switch (def.tag) {
3301
+ case "literal":
3302
+ return [JSON.stringify(def.value)];
3303
+ case "regex":
3304
+ return [`/${def.source}/`];
3305
+ case "keywords":
3306
+ return def.words.map((w) => JSON.stringify(w));
3307
+ case "label":
3308
+ return [def.label];
3309
+ case "choice":
3310
+ return def.parsers.flatMap(deriveExpected2);
3311
+ case "dispatch":
3312
+ return deriveExpected2(def.selector);
3313
+ // Union through the NULLABLE prefix, mirroring `sequenceFirstSet`. A leading
3314
+ // `optional(…)`/`many(…)` can match nothing, so the term after it is equally
3315
+ // able to fail first — deriving from term 0 alone named a token the parse
3316
+ // never actually required. A leading `not(…)` is zero-width and contributes
3317
+ // nothing (its own expectation is about what must NOT be here), but it is
3318
+ // nullable, so keep scanning past it. Stop at the first term that must match.
3319
+ case "sequence": {
3320
+ const out = [];
3321
+ for (const term of def.parsers) {
3322
+ if (!isZeroWidthAssertion(term)) out.push(...deriveExpected2(term));
3323
+ if (!matchesEmpty(term)) break;
3324
+ }
3325
+ return out;
3326
+ }
3327
+ case "attempt":
3328
+ return deriveExpected2(def.parser);
3329
+ // Delegating wrappers whose first-token failure is their inner parser's — must
3330
+ // pass through so a start-failure (and the first-set-miss fast-path in attempt/
3331
+ // node, which reads this) names the real expected token, not the wrapper tag.
3332
+ case "field":
3333
+ case "withCtx":
3334
+ case "recover":
3335
+ return deriveExpected2(def.parser);
3336
+ case "expect":
3337
+ return def.expected;
3338
+ case "node":
3339
+ case "grammar":
3340
+ case "trivia":
3341
+ case "token":
3342
+ case "leaf":
3343
+ case "optional":
3344
+ case "many":
3345
+ case "oneOrMore":
3346
+ case "transform":
3347
+ case "not":
3348
+ case "peek":
3349
+ return deriveExpected2(def.parser);
3350
+ // A bare routed() can only fail as "there is no routed token here". With a
3351
+ // fallback, THAT is the branch that can fail, so its expectations are the useful
3352
+ // ones — the routed path either succeeds or is not taken.
3353
+ case "routed":
3354
+ return def.fallback === void 0 ? ["routed()"] : deriveExpected2(def.fallback);
3355
+ // A bare adjacency assertion names the JOIN it requires. Inside a sequence it is
3356
+ // skipped entirely (isZeroWidthAssertion, above), which is the normal path.
3357
+ case "adjacency":
3358
+ return [def.polarity];
3359
+ case "lazy": {
3360
+ const name = c._ruleName;
3361
+ if (seen.has(c)) return name ? [name] : [];
3362
+ seen.add(c);
3363
+ try {
3364
+ return deriveExpected2(def.thunk());
3365
+ } catch {
3366
+ return name ? [name] : [];
3367
+ } finally {
3368
+ seen.delete(c);
3369
+ }
3370
+ }
3371
+ default:
3372
+ return [];
3373
+ }
3374
+ }
3375
+ function expect(combinator, label2) {
3376
+ const expected = label2 !== void 0 ? [label2] : deriveExpected(combinator);
3377
+ const meta = {
3378
+ firstSet: combinator._meta.firstSet,
3379
+ canMatchNewline: combinator._meta.canMatchNewline,
3380
+ isTrivia: false
3381
+ };
3382
+ return {
3383
+ _tag: "expect",
3384
+ _meta: meta,
3385
+ _def: { tag: "expect", parser: combinator, label: label2, expected },
3386
+ parse(input, pos, ctx) {
3387
+ const result = combinator.parse(input, pos, ctx);
3388
+ if (result.ok) return result;
3389
+ const span = { start: pos, end: pos };
3390
+ const error = { _tag: "parseError", span: ctx.trackLines ? annotateSpanFromLineContext(span, ctx) : span, expected };
3391
+ ctx._errors?.push(error);
3392
+ if (ctx._tolerant) captureError(ctx, error);
3393
+ return { ok: true, value: error, span: { start: pos, end: pos } };
3394
+ }
3395
+ };
3396
+ }
3397
+
3398
+ // src/combinators/choice.ts
3399
+ function choice(...args) {
3400
+ const parsers = args.map((a) => "gate" in a ? a.combinator : a);
3401
+ const gates = args.map((a) => "gate" in a ? a.gate : null);
3402
+ const hasGates = gates.some((g) => g !== null);
3403
+ const disjoint = areDisjoint(parsers.map((p) => p._meta.firstSet)) && parsers.every((p) => !matchesEmpty(p));
3404
+ let combined = { kind: "empty" };
3405
+ for (const p of parsers) combined = union(combined, p._meta.firstSet);
3406
+ const meta = {
3407
+ firstSet: combined,
3408
+ canMatchNewline: parsers.some((p) => p._meta.canMatchNewline),
3409
+ isTrivia: false,
3410
+ disjoint
3411
+ };
3412
+ const strategy = disjoint || hasGates ? null : detectStrategy(parsers);
3413
+ const autoNot = !disjoint && !hasGates && (strategy?.tag === "firstMatch" || strategy?.tag === "sharedPrefix") ? computeAutoNot(parsers) : parsers.map(() => null);
3414
+ let greedyLitMap = null;
3415
+ let sortedParsers = null;
3416
+ const asciiDispatch = disjoint ? buildAsciiDispatch(parsers) : null;
2839
3417
  if (strategy?.tag === "greedyClassify") {
2840
3418
  greedyLitMap = /* @__PURE__ */ new Map();
2841
3419
  for (let i = 0; i < parsers.length; i++) {
@@ -3363,6 +3941,7 @@ function confirmedArityForDef(def) {
3363
3941
  }
3364
3942
  function buildReadsRaw(def) {
3365
3943
  if (!def.build) return true;
3944
+ if (def.buildRawUnused === true) return false;
3366
3945
  const arity = confirmedArityForDef(def);
3367
3946
  if (arity === null) return true;
3368
3947
  return arity >= 4;
@@ -4420,381 +4999,125 @@ function sepBy(combinator, separatorArg, opts = {}) {
4420
4999
  let sepPos = cur;
4421
5000
  if (ctx.trivia) {
4422
5001
  if (needsDeferredTriviaCommit(ctx)) {
4423
- sepPos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
4424
- } else {
4425
- sepPos = advanceTrivia(input, cur, ctx);
4426
- }
4427
- }
4428
- const sep = separator.parse(input, sepPos, ctx);
4429
- if (!sep.ok) {
4430
- rollbackTrivia(ctx, loopMark);
4431
- if (sep.committed) return sep;
4432
- break;
4433
- }
4434
- if (!keepSeparators) demoteCapturedToRaw(ctx, loopMark.leaves);
4435
- const sepMark = trailing === "forbid" ? void 0 : saveTriviaMark(ctx);
4436
- let nextPos = sep.span.end;
4437
- if (ctx.trivia) {
4438
- if (needsDeferredTriviaCommit(ctx)) {
4439
- nextPos = commitTriviaScan(scanTriviaCompact(input, sep.span.end, ctx));
4440
- } else {
4441
- nextPos = advanceTrivia(input, sep.span.end, ctx);
4442
- }
4443
- }
4444
- const next = combinator.parse(input, nextPos, ctx);
4445
- if (!next.ok) {
4446
- if (next.committed) return next;
4447
- const term = ctx._tolerant ? ctx._sync : void 0;
4448
- if (term !== void 0 && !matchesAt(term, input, nextPos, ctx)) {
4449
- expected ??= deriveExpected(combinator);
4450
- const rec = recoverScan(input, nextPos, ctx, orSentinel(separator, term), expected);
4451
- values.push(rec.error);
4452
- captureError(ctx, rec.error);
4453
- cur = rec.end;
4454
- continue;
4455
- }
4456
- if (sepMark !== void 0) {
4457
- rollbackTrivia(ctx, sepMark);
4458
- cur = sep.span.end;
4459
- break;
4460
- }
4461
- rollbackTrivia(ctx, loopMark);
4462
- break;
4463
- }
4464
- values.push(next.value);
4465
- cur = next.span.end;
4466
- }
4467
- if (values.length < min) return failAt2(cur);
4468
- return { ok: true, value: values, span: { start: pos, end: cur } };
4469
- }
4470
- };
4471
- }
4472
-
4473
- // src/combinators/map.ts
4474
- function transform(combinator, fn) {
4475
- return {
4476
- _tag: "transform",
4477
- _meta: combinator._meta,
4478
- _def: { tag: "transform", parser: combinator, fn },
4479
- parse(input, pos, ctx) {
4480
- const result = combinator.parse(input, pos, ctx);
4481
- if (!result.ok) return result;
4482
- return { ok: true, value: fn(result.value, result.span), span: result.span };
4483
- }
4484
- };
4485
- }
4486
- function trivia(combinator) {
4487
- const kindLabels = analyzeLabeledTrivia(combinator)?.labels;
4488
- return {
4489
- _tag: combinator._tag,
4490
- _meta: {
4491
- ...combinator._meta,
4492
- isTrivia: true,
4493
- ...kindLabels ? { triviaKindLabels: kindLabels } : {}
4494
- },
4495
- _def: { tag: "trivia", parser: combinator },
4496
- parse: combinator.parse.bind(combinator)
4497
- };
4498
- }
4499
- function classifiedTrivia(arms) {
4500
- const entries = Object.entries(arms);
4501
- if (entries.length === 0) {
4502
- throw new TypeError("classifiedTrivia() requires at least one named trivia arm.");
4503
- }
4504
- for (let i = 0; i < entries.length; i++) {
4505
- const [name, arm] = entries[i];
4506
- const first = arm._meta.firstSet;
4507
- if (matchesEmpty(arm) || first.kind !== "ranges" || first.ranges.length === 0) {
4508
- throw new TypeError(
4509
- `classifiedTrivia(): ${JSON.stringify(name)} must be non-nullable with a concrete finite first set.`
4510
- );
4511
- }
4512
- }
4513
- const labeledArms = entries.map(([name, arm]) => label(name, arm));
4514
- const result = trivia(oneOrMore(choice(...labeledArms)));
4515
- result._meta.rootTriviaClassified = true;
4516
- return result;
4517
- }
4518
- function label(name, combinator) {
4519
- return {
4520
- _tag: combinator._tag,
4521
- _meta: combinator._meta,
4522
- _def: { tag: "label", label: name, parser: combinator },
4523
- parse(input, pos, ctx) {
4524
- const result = combinator.parse(input, pos, ctx);
4525
- if (!result.ok) return { ok: false, expected: [name], span: result.span };
4526
- return result;
4527
- }
4528
- };
4529
- }
4530
- function field(name, combinator) {
4531
- return {
4532
- _tag: combinator._tag,
4533
- _meta: combinator._meta,
4534
- _def: { tag: "field", name, parser: combinator },
4535
- parse(input, pos, ctx) {
4536
- const result = combinator.parse(input, pos, ctx);
4537
- if (!result.ok) return result;
4538
- ctx._fields?.push({ name, value: result.value, span: result.span });
4539
- return result;
4540
- }
4541
- };
4542
- }
4543
-
4544
- // src/regex/first-set.ts
4545
- var ANY = { t: "any" };
4546
- var EMPTY2 = { t: "empty" };
4547
- function charNode(set, nl) {
4548
- return { t: "char", set, nl };
4549
- }
4550
- function rangesToSet(ranges) {
4551
- let fs = empty();
4552
- for (const [lo, hi] of ranges) fs = union(fs, fromRange(lo, hi));
4553
- return fs;
4554
- }
4555
- function rangesHaveNewline(ranges) {
4556
- return ranges.some(([lo, hi]) => lo <= 10 && 10 <= hi);
4557
- }
4558
- var BAIL = /* @__PURE__ */ Symbol("regex-bail");
4559
- function parseRegex(src) {
4560
- let i = 0;
4561
- const parseAlt = () => {
4562
- const arms = [parseSeq()];
4563
- while (src[i] === "|") {
4564
- i++;
4565
- arms.push(parseSeq());
4566
- }
4567
- return arms.length === 1 ? arms[0] : { t: "alt", arms };
4568
- };
4569
- const parseSeq = () => {
4570
- const parts = [];
4571
- while (i < src.length) {
4572
- const ch2 = src[i];
4573
- if (ch2 === "|" || ch2 === ")") break;
4574
- parts.push(parseQuantified());
4575
- }
4576
- if (parts.length === 0) return EMPTY2;
4577
- return parts.length === 1 ? parts[0] : { t: "seq", parts };
4578
- };
4579
- const parseQuantified = () => {
4580
- const atom = parseAtom();
4581
- const ch2 = src[i];
4582
- let min = null;
4583
- if (ch2 === "*") {
4584
- min = 0;
4585
- i++;
4586
- } else if (ch2 === "+") {
4587
- min = 1;
4588
- i++;
4589
- } else if (ch2 === "?") {
4590
- min = 0;
4591
- i++;
4592
- } else if (ch2 === "{") {
4593
- min = parseBraceQuantifier();
4594
- }
4595
- if (min === null) return atom;
4596
- if (src[i] === "?") i++;
4597
- return { t: "rep", node: atom, min };
4598
- };
4599
- const parseBraceQuantifier = () => {
4600
- const close = src.indexOf("}", i);
4601
- if (close === -1) return null;
4602
- const m = /^(\d+)(?:,(\d*))?$/.exec(src.slice(i + 1, close));
4603
- if (!m) return null;
4604
- i = close + 1;
4605
- return Number.parseInt(m[1], 10);
4606
- };
4607
- const parseAtom = () => {
4608
- const ch2 = src[i];
4609
- switch (ch2) {
4610
- case "(":
4611
- return parseGroup();
4612
- case "[":
4613
- return parseClass();
4614
- case ".":
4615
- i++;
4616
- return charNode(any(), false);
4617
- // `.` matches any char except line terminators
4618
- case "\\":
4619
- return parseEscape();
4620
- case "^":
4621
- case "$":
4622
- i++;
4623
- return EMPTY2;
4624
- // anchors are zero-width
4625
- case "{":
4626
- i++;
4627
- return charNode(fromRange(123, 123), false);
4628
- // a `{` with nothing to quantify is a literal brace
4629
- default:
4630
- i += ch2.length;
4631
- return charNode(fromRange(ch2.codePointAt(0), ch2.codePointAt(0)), ch2 === "\n");
4632
- }
4633
- };
4634
- const parseGroup = () => {
4635
- i++;
4636
- let lookaround = false;
4637
- if (src[i] === "?") {
4638
- const c1 = src[i + 1];
4639
- if (c1 === ":") i += 2;
4640
- else if (c1 === "=" || c1 === "!") {
4641
- i += 2;
4642
- lookaround = true;
4643
- } else if (c1 === "<") {
4644
- const c2 = src[i + 2];
4645
- if (c2 === "=" || c2 === "!") {
4646
- i += 3;
4647
- lookaround = true;
4648
- } else {
4649
- const gt = src.indexOf(">", i);
4650
- if (gt === -1) throw BAIL;
4651
- i = gt + 1;
5002
+ sepPos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
5003
+ } else {
5004
+ sepPos = advanceTrivia(input, cur, ctx);
5005
+ }
4652
5006
  }
4653
- } else throw BAIL;
4654
- }
4655
- const inner = parseAlt();
4656
- if (src[i] !== ")") throw BAIL;
4657
- i++;
4658
- return lookaround ? EMPTY2 : inner;
4659
- };
4660
- const parseClass = () => {
4661
- let k = i + 1;
4662
- const negated = src[k] === "^";
4663
- if (negated) k++;
4664
- let body = "";
4665
- while (k < src.length && src[k] !== "]") {
4666
- if (src[k] === "\\") {
4667
- body += src[k] + (src[k + 1] ?? "");
4668
- k += 2;
4669
- } else {
4670
- body += src[k];
4671
- k++;
5007
+ const sep = separator.parse(input, sepPos, ctx);
5008
+ if (!sep.ok) {
5009
+ rollbackTrivia(ctx, loopMark);
5010
+ if (sep.committed) return sep;
5011
+ break;
5012
+ }
5013
+ if (!keepSeparators) demoteCapturedToRaw(ctx, loopMark.leaves);
5014
+ const sepMark = trailing === "forbid" ? void 0 : saveTriviaMark(ctx);
5015
+ let nextPos = sep.span.end;
5016
+ if (ctx.trivia) {
5017
+ if (needsDeferredTriviaCommit(ctx)) {
5018
+ nextPos = commitTriviaScan(scanTriviaCompact(input, sep.span.end, ctx));
5019
+ } else {
5020
+ nextPos = advanceTrivia(input, sep.span.end, ctx);
5021
+ }
5022
+ }
5023
+ const next = combinator.parse(input, nextPos, ctx);
5024
+ if (!next.ok) {
5025
+ if (next.committed) return next;
5026
+ const term = ctx._tolerant ? ctx._sync : void 0;
5027
+ if (term !== void 0 && !matchesAt(term, input, nextPos, ctx)) {
5028
+ expected ??= deriveExpected(combinator);
5029
+ const rec = recoverScan(input, nextPos, ctx, orSentinel(separator, term), expected);
5030
+ values.push(rec.error);
5031
+ captureError(ctx, rec.error);
5032
+ cur = rec.end;
5033
+ continue;
5034
+ }
5035
+ if (sepMark !== void 0) {
5036
+ rollbackTrivia(ctx, sepMark);
5037
+ cur = sep.span.end;
5038
+ break;
5039
+ }
5040
+ rollbackTrivia(ctx, loopMark);
5041
+ break;
5042
+ }
5043
+ values.push(next.value);
5044
+ cur = next.span.end;
4672
5045
  }
5046
+ if (values.length < min) return failAt2(cur);
5047
+ return { ok: true, value: values, span: { start: pos, end: cur } };
4673
5048
  }
4674
- if (src[k] !== "]") throw BAIL;
4675
- i = k + 1;
4676
- const ranges = parseClassRanges(body);
4677
- if (negated) return charNode(any(), !ranges || !rangesHaveNewline(ranges));
4678
- if (!ranges) return charNode(any(), true);
4679
- return charNode(rangesToSet(ranges), rangesHaveNewline(ranges));
4680
5049
  };
4681
- const parseEscape = () => {
4682
- const e = src[i + 1];
4683
- if (e === void 0) throw BAIL;
4684
- if (e === "u" && /^[0-9a-fA-F]{4}$/.test(src.slice(i + 2, i + 6))) {
4685
- const cp = Number.parseInt(src.slice(i + 2, i + 6), 16);
4686
- i += 6;
4687
- return charNode(fromRange(cp, cp), cp === 10);
4688
- }
4689
- if (e === "x" && /^[0-9a-fA-F]{2}$/.test(src.slice(i + 2, i + 4))) {
4690
- const cp = Number.parseInt(src.slice(i + 2, i + 4), 16);
4691
- i += 4;
4692
- return charNode(fromRange(cp, cp), cp === 10);
4693
- }
4694
- i += 2;
4695
- switch (e) {
4696
- case "d":
4697
- return charNode(rangesToSet(shorthandRanges("d")), false);
4698
- case "w":
4699
- return charNode(rangesToSet(shorthandRanges("w")), false);
4700
- case "s":
4701
- return charNode(rangesToSet(shorthandRanges("s")), true);
4702
- case "D":
4703
- case "W":
4704
- case "S":
4705
- return charNode(any(), true);
4706
- // negated shorthand → widen
4707
- case "b":
4708
- case "B":
4709
- return EMPTY2;
4710
- // word boundary: zero-width
4711
- case "n":
4712
- return charNode(fromRange(10, 10), true);
4713
- case "r":
4714
- return charNode(fromRange(13, 13), false);
4715
- case "t":
4716
- return charNode(fromRange(9, 9), false);
4717
- case "f":
4718
- return charNode(fromRange(12, 12), false);
4719
- case "v":
4720
- return charNode(fromRange(11, 11), false);
4721
- case "0":
4722
- return charNode(fromRange(0, 0), false);
4723
- default:
4724
- if (e >= "1" && e <= "9") return ANY;
4725
- return charNode(fromRange(e.codePointAt(0), e.codePointAt(0)), e === "\n");
5050
+ }
5051
+
5052
+ // src/combinators/map.ts
5053
+ function transform(combinator, fn) {
5054
+ return {
5055
+ _tag: "transform",
5056
+ _meta: combinator._meta,
5057
+ _def: { tag: "transform", parser: combinator, fn },
5058
+ parse(input, pos, ctx) {
5059
+ const result = combinator.parse(input, pos, ctx);
5060
+ if (!result.ok) return result;
5061
+ return { ok: true, value: fn(result.value, result.span), span: result.span };
4726
5062
  }
4727
5063
  };
4728
- const node2 = parseAlt();
4729
- if (i < src.length) throw BAIL;
4730
- return node2;
4731
5064
  }
4732
- function nullable(n) {
4733
- switch (n.t) {
4734
- case "char":
4735
- return false;
4736
- case "any":
4737
- return true;
4738
- case "empty":
4739
- return true;
4740
- case "seq":
4741
- return n.parts.every(nullable);
4742
- case "alt":
4743
- return n.arms.some(nullable);
4744
- case "rep":
4745
- return n.min === 0 || nullable(n.node);
4746
- }
5065
+ function trivia(combinator) {
5066
+ const kindLabels = analyzeLabeledTrivia(combinator)?.labels;
5067
+ return {
5068
+ _tag: combinator._tag,
5069
+ _meta: {
5070
+ ...combinator._meta,
5071
+ isTrivia: true,
5072
+ ...kindLabels ? { triviaKindLabels: kindLabels } : {}
5073
+ },
5074
+ _def: { tag: "trivia", parser: combinator },
5075
+ parse: combinator.parse.bind(combinator)
5076
+ };
4747
5077
  }
4748
- function firstSet(n) {
4749
- switch (n.t) {
4750
- case "char":
4751
- return n.set;
4752
- case "any":
4753
- return any();
4754
- case "empty":
4755
- return empty();
4756
- case "rep":
4757
- return firstSet(n.node);
4758
- case "alt": {
4759
- let fs = empty();
4760
- for (const arm of n.arms) fs = union(fs, firstSet(arm));
4761
- return fs;
4762
- }
4763
- case "seq": {
4764
- let fs = empty();
4765
- for (const part of n.parts) {
4766
- fs = union(fs, firstSet(part));
4767
- if (!nullable(part)) break;
4768
- }
4769
- return fs;
5078
+ function classifiedTrivia(arms) {
5079
+ const entries = Object.entries(arms);
5080
+ if (entries.length === 0) {
5081
+ throw new TypeError("classifiedTrivia() requires at least one named trivia arm.");
5082
+ }
5083
+ for (let i = 0; i < entries.length; i++) {
5084
+ const [name, arm] = entries[i];
5085
+ const first = arm._meta.firstSet;
5086
+ if (matchesEmpty(arm) || first.kind !== "ranges" || first.ranges.length === 0) {
5087
+ throw new TypeError(
5088
+ `classifiedTrivia(): ${JSON.stringify(name)} must be non-nullable with a concrete finite first set.`
5089
+ );
4770
5090
  }
4771
5091
  }
5092
+ const labeledArms = entries.map(([name, arm]) => label(name, arm));
5093
+ const result = trivia(oneOrMore(choice(...labeledArms)));
5094
+ result._meta.rootTriviaClassified = true;
5095
+ return result;
4772
5096
  }
4773
- function canConsumeNewline(n) {
4774
- switch (n.t) {
4775
- case "char":
4776
- return n.nl;
4777
- case "any":
4778
- return true;
4779
- case "empty":
4780
- return false;
4781
- case "rep":
4782
- return canConsumeNewline(n.node);
4783
- case "alt":
4784
- return n.arms.some(canConsumeNewline);
4785
- case "seq":
4786
- return n.parts.some(canConsumeNewline);
4787
- }
5097
+ function label(name, combinator) {
5098
+ return {
5099
+ _tag: combinator._tag,
5100
+ _meta: combinator._meta,
5101
+ _def: { tag: "label", label: name, parser: combinator },
5102
+ parse(input, pos, ctx) {
5103
+ const result = combinator.parse(input, pos, ctx);
5104
+ if (!result.ok) return { ok: false, expected: [name], span: result.span };
5105
+ return result;
5106
+ }
5107
+ };
4788
5108
  }
4789
- function firstSetFromRegex(source) {
4790
- let ast;
4791
- try {
4792
- ast = parseRegex(source);
4793
- } catch {
4794
- return { firstSet: any(), canMatchNewline: true };
4795
- }
4796
- if (nullable(ast)) return { firstSet: any(), canMatchNewline: canConsumeNewline(ast) };
4797
- return { firstSet: firstSet(ast), canMatchNewline: canConsumeNewline(ast) };
5109
+ function field(name, combinator) {
5110
+ return {
5111
+ _tag: combinator._tag,
5112
+ _meta: combinator._meta,
5113
+ _def: { tag: "field", name, parser: combinator },
5114
+ parse(input, pos, ctx) {
5115
+ const result = combinator.parse(input, pos, ctx);
5116
+ if (!result.ok) return result;
5117
+ ctx._fields?.push({ name, value: result.value, span: result.span });
5118
+ return result;
5119
+ }
5120
+ };
4798
5121
  }
4799
5122
 
4800
5123
  // src/combinators/regex.ts
@@ -4983,8 +5306,26 @@ function validateDispatchSpec(spec, arity, fallbackRouted) {
4983
5306
  }
4984
5307
  }
4985
5308
  var TABLE_RUNTIME = /* @__PURE__ */ Symbol("parseman.tableRuntime");
4986
- function ownTableProgram(prog, resolved) {
4987
- return { ...prog, [TABLE_RUNTIME]: { resolved } };
5309
+ function ownTableProgram(prog, resolved, caches = {}) {
5310
+ const runtime = prog[TABLE_RUNTIME];
5311
+ return {
5312
+ ...prog,
5313
+ [TABLE_RUNTIME]: {
5314
+ resolved,
5315
+ choiceRollbackMasks: caches.choiceRollbackMasks ?? runtime?.choiceRollbackMasks,
5316
+ nonCommittingChoiceSites: caches.nonCommittingChoiceSites ?? runtime?.nonCommittingChoiceSites,
5317
+ failureRollbackCleanSites: caches.failureRollbackCleanSites ?? runtime?.failureRollbackCleanSites
5318
+ }
5319
+ };
5320
+ }
5321
+ function choiceRollbackMask(prog, ip) {
5322
+ return prog[TABLE_RUNTIME]?.choiceRollbackMasks?.get(ip);
5323
+ }
5324
+ function choiceCannotCommit(prog, ip) {
5325
+ return prog[TABLE_RUNTIME]?.nonCommittingChoiceSites?.has(ip) === true;
5326
+ }
5327
+ function failureRollbackClean(prog, ip) {
5328
+ return prog[TABLE_RUNTIME]?.failureRollbackCleanSites?.has(ip) === true;
4988
5329
  }
4989
5330
  var WIDE_CLASS_PREFIX_LO = 65535;
4990
5331
  var WIDE_CLASS_PREFIX_HI = 0;
@@ -5159,7 +5500,6 @@ function directArrayProjection(fn, fnSrc, arity) {
5159
5500
 
5160
5501
  // src/table/encode.ts
5161
5502
  import {
5162
- assertLexicalCapabilityClosure,
5163
5503
  collectLexicalCapabilities,
5164
5504
  winnerWrapsReference as winnerWrapsReference2
5165
5505
  } from "../compiler/token-capability.js";
@@ -5541,6 +5881,25 @@ var Encoder = class {
5541
5881
  lexIndex = /* @__PURE__ */ new Map();
5542
5882
  lexPrograms = [];
5543
5883
  lexProgramIndex = /* @__PURE__ */ new Map();
5884
+ choiceRollbackMasks = /* @__PURE__ */ new Map();
5885
+ nonCommittingChoiceSites = /* @__PURE__ */ new Set();
5886
+ failureRollbackCleanSites = /* @__PURE__ */ new Set();
5887
+ /**
5888
+ * `hasSideWriter` memo for `failureNeedsRollback`, shared across every call
5889
+ * for the lifetime of this `Encoder`. A cached entry is written only when
5890
+ * `complete` is true, which means the answer is a path-independent fact
5891
+ * about that combinator node — it does not depend on which root's traversal
5892
+ * asked, only on the node's own reachable subgraph. Scoping the memo per call
5893
+ * (as a local inside `failureNeedsRollback`) was correct but discarded that
5894
+ * fact after every arm, so a grammar with many ordered-choice arms / optional
5895
+ * / attempt sites re-walked the SAME shared rule graph from scratch for each
5896
+ * site — O(sites × graph size) instead of O(graph size). Measured on the
5897
+ * scss-parser grammar (composed CSS-base superset, the deepest/largest of the
5898
+ * four grammars): 47-50s for one `compileRuleMap` with the per-call memo,
5899
+ * versus the whole macro transform completing in under a second once this
5900
+ * memo is hoisted here.
5901
+ */
5902
+ sideWriterMemo = /* @__PURE__ */ new Map();
5544
5903
  labels = void 0;
5545
5904
  /** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
5546
5905
  activeTrivia = void 0;
@@ -5947,9 +6306,75 @@ var Encoder = class {
5947
6306
  * nothing consults the resolver and nothing changes, which is why the runtime
5948
6307
  * leg's counts are byte-for-byte what they were.
5949
6308
  */
5950
- refResolver() {
5951
- const w = this.winners;
5952
- return w === void 0 ? void 0 : (name) => w[name];
6309
+ refResolver() {
6310
+ const w = this.winners;
6311
+ return w === void 0 ? void 0 : (name) => w[name];
6312
+ }
6313
+ /**
6314
+ * Whether a failed ordered-choice arm can leave state that the enclosing
6315
+ * choice must restore before trying its successor.
6316
+ *
6317
+ * `mayLeavePartialCapture` is the existing sound CST/trivia proof. The extra
6318
+ * writer census covers the side sinks that proof deliberately does not model:
6319
+ * fields, recovered errors, and interpreted scanners. Strict assemblies do
6320
+ * not run repeat recovery, but these rows can still publish through a caller's
6321
+ * context. Cycles are safe to stop: revisiting the same combinator cannot
6322
+ * discover a writer the first traversal did not already reach.
6323
+ */
6324
+ failureNeedsRollback(p, autoNot) {
6325
+ const refName = p._ruleName;
6326
+ const winner = refName === void 0 ? void 0 : this.winners?.[refName];
6327
+ const root = winner !== void 0 && !winnerWrapsReference2(winner, p) ? winner : p;
6328
+ const sideWriterMemo = this.sideWriterMemo;
6329
+ const seen = /* @__PURE__ */ new Set();
6330
+ const hasSideWriter = (current) => {
6331
+ const cached = sideWriterMemo.get(current);
6332
+ if (cached !== void 0) return { found: cached, complete: true };
6333
+ if (seen.has(current)) return { found: false, complete: false };
6334
+ seen.add(current);
6335
+ const def = current._def;
6336
+ let result;
6337
+ switch (def.tag) {
6338
+ case "field":
6339
+ case "expect":
6340
+ case "recover":
6341
+ case "scanTo":
6342
+ case "unknown":
6343
+ result = { found: true, complete: true };
6344
+ break;
6345
+ case "lazy": {
6346
+ const name = current._ruleName;
6347
+ const resolvedWinner = name === void 0 ? void 0 : this.winners?.[name];
6348
+ if (resolvedWinner !== void 0 && !winnerWrapsReference2(resolvedWinner, current)) {
6349
+ result = hasSideWriter(resolvedWinner);
6350
+ break;
6351
+ }
6352
+ try {
6353
+ result = hasSideWriter(def.thunk());
6354
+ } catch {
6355
+ result = { found: true, complete: true };
6356
+ }
6357
+ break;
6358
+ }
6359
+ default: {
6360
+ let complete = true;
6361
+ result = { found: false, complete: true };
6362
+ for (const child of childrenOf(def)) {
6363
+ const childResult = hasSideWriter(child);
6364
+ if (childResult.found) {
6365
+ result = { found: true, complete: true };
6366
+ break;
6367
+ }
6368
+ complete &&= childResult.complete;
6369
+ }
6370
+ if (!result.found) result = { found: false, complete };
6371
+ }
6372
+ }
6373
+ seen.delete(current);
6374
+ if (result.found || result.complete) sideWriterMemo.set(current, result.found);
6375
+ return result;
6376
+ };
6377
+ return mayLeavePartialCapture(root, /* @__PURE__ */ new Set(), true) || hasSideWriter(root).found || (autoNot?.length ?? 0) > 0 && capturesLeaf(root);
5953
6378
  }
5954
6379
  /** A first set becomes a char class string, or −1 for `any`. */
5955
6380
  charClass(fs) {
@@ -6236,9 +6661,39 @@ var Encoder = class {
6236
6661
  });
6237
6662
  const rr = this.refResolver();
6238
6663
  const finalChoice = classifyFinalChoice(arms, rr);
6239
- const classes = arms.map((_, i) => finalChoice.nullable[i] ? -1 : this.charClass(finalChoice.firstSets[i]));
6664
+ const transactionalFirst = arms.map((arm, i) => {
6665
+ if (!finalChoice.nullable[i]) return void 0;
6666
+ const def = arm._def;
6667
+ if (def.tag !== "attempt" || matchesEmpty(def.parser, /* @__PURE__ */ new Set(), rr)) return void 0;
6668
+ return firstSetOf(def.parser, /* @__PURE__ */ new Set(), rr);
6669
+ });
6670
+ const gateFirst = finalChoice.firstSets.map((first, i) => transactionalFirst[i] ?? first);
6671
+ const classes = gateFirst.map((first, i) => finalChoice.nullable[i] && transactionalFirst[i] === void 0 ? -1 : this.charClass(first));
6672
+ if (transactionalFirst.some((first) => first !== void 0) && classes.every((cls) => cls >= 0)) {
6673
+ let overlap = false;
6674
+ for (let i = 0; i < gateFirst.length && !overlap; i++) {
6675
+ for (let j = i + 1; j < gateFirst.length; j++) {
6676
+ if (intersects(gateFirst[i], gateFirst[j])) {
6677
+ overlap = true;
6678
+ break;
6679
+ }
6680
+ }
6681
+ }
6682
+ if (!overlap) for (let i = 0; i < classes.length; i++) {
6683
+ if (transactionalFirst[i] !== void 0) classes[i] = -1;
6684
+ }
6685
+ }
6240
6686
  const dispIdx = this.disp.length;
6241
6687
  this.disp.push(classes);
6688
+ let rollbackMask = kids.length > 31 ? -1 : 0;
6689
+ if (rollbackMask === 0) {
6690
+ for (let i = 0; i < arms.length; i++) {
6691
+ const src = order[i];
6692
+ if (this.failureNeedsRollback(arms[i], d.autoNot[src])) {
6693
+ rollbackMask |= 1 << i;
6694
+ }
6695
+ }
6696
+ }
6242
6697
  const head = this.emitHead(OP_CHOICE, 3 + 2 * kids.length);
6243
6698
  this.code[head + 1] = dispIdx;
6244
6699
  this.code[head + 2] = kids.length;
@@ -6247,6 +6702,10 @@ var Encoder = class {
6247
6702
  this.code[head + 4 + i] = kids[i];
6248
6703
  this.code[head + 4 + kids.length + i] = this.expected(deriveExpected(arms[i]));
6249
6704
  }
6705
+ this.choiceRollbackMasks.set(head, rollbackMask);
6706
+ if (arms.every((arm) => !mayCommitFailure(arm, /* @__PURE__ */ new Set(), rr))) {
6707
+ this.nonCommittingChoiceSites.add(head);
6708
+ }
6250
6709
  return head;
6251
6710
  }
6252
6711
  case "many":
@@ -6276,8 +6735,11 @@ var Encoder = class {
6276
6735
  }
6277
6736
  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);
6278
6737
  }
6279
- case "optional":
6280
- return this.emit(OP_OPT, this.node(d.parser).ip);
6738
+ case "optional": {
6739
+ const head = this.emit(OP_OPT, this.node(d.parser).ip);
6740
+ if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(head);
6741
+ return head;
6742
+ }
6281
6743
  case "transform": {
6282
6744
  const inner = d.parser._def;
6283
6745
  if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
@@ -6436,6 +6898,7 @@ var Encoder = class {
6436
6898
  // lowering was correct only for a choice arm.
6437
6899
  case "attempt": {
6438
6900
  const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip);
6901
+ if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
6439
6902
  const fs = d.parser._meta.firstSet;
6440
6903
  if (fs.kind === "any" || matchesEmpty(d.parser)) return inner;
6441
6904
  const cls = this.charClass(fs);
@@ -6604,6 +7067,10 @@ var Encoder = class {
6604
7067
  ...this.rec ? { rec: 1 } : {},
6605
7068
  ...this.cov === void 0 ? {} : { cov: this.cov },
6606
7069
  lines: this.track ? 1 : 0
7070
+ }, void 0, {
7071
+ choiceRollbackMasks: this.choiceRollbackMasks,
7072
+ failureRollbackCleanSites: this.failureRollbackCleanSites,
7073
+ nonCommittingChoiceSites: this.nonCommittingChoiceSites
6607
7074
  });
6608
7075
  }
6609
7076
  };
@@ -6648,7 +7115,6 @@ function encodeTableProgram(ruleMap, settings = {}) {
6648
7115
  const lexicalRoots = [...names].sort().map((name) => ruleMap[name]);
6649
7116
  const resolveLexical = (name) => ruleMap[name];
6650
7117
  const capabilities = collectLexicalCapabilities(lexicalRoots, resolveLexical);
6651
- assertLexicalCapabilityClosure(lexicalRoots, capabilities, resolveLexical);
6652
7118
  const enc = new Encoder(resolvedSettings, capabilities.capabilityComplete);
6653
7119
  enc.winners = ruleMap;
6654
7120
  for (const name of names) enc.encodeRule(name, ruleMap[name]);
@@ -7781,13 +8247,17 @@ var TRI_NONE = -1;
7781
8247
  var CAP_UNKNOWN = 0;
7782
8248
  var CAP_OFF = 1;
7783
8249
  var CAP_ON = 2;
7784
- var TOP = { tri: TRI_UNKNOWN, buf: false, cap: CAP_UNKNOWN };
8250
+ var RAW_UNKNOWN = 0;
8251
+ var RAW_CAPTURE = 1;
8252
+ var RAW_OMIT = 2;
8253
+ var TOP = { tri: TRI_UNKNOWN, buf: false, raw: RAW_UNKNOWN, cap: CAP_UNKNOWN };
7785
8254
  function meet(a, b) {
7786
8255
  const tri = a.tri === b.tri ? a.tri : TRI_UNKNOWN;
7787
8256
  const buf = a.buf && b.buf;
8257
+ const raw = a.raw === b.raw ? a.raw : RAW_UNKNOWN;
7788
8258
  const cap = a.cap === b.cap ? a.cap : CAP_UNKNOWN;
7789
- if (tri === a.tri && buf === a.buf && cap === a.cap) return a;
7790
- return { tri, buf, cap };
8259
+ if (tri === a.tri && buf === a.buf && raw === a.raw && cap === a.cap) return a;
8260
+ return { tri, buf, raw, cap };
7791
8261
  }
7792
8262
  function reachableSites(code, roots) {
7793
8263
  const seen = /* @__PURE__ */ new Set();
@@ -7810,25 +8280,26 @@ function transfer(code, ip, at, hostCst) {
7810
8280
  const tri = ki < 0 ? TRI_NONE : ki;
7811
8281
  const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
7812
8282
  if (tri === at.tri && cap === at.cap) return at;
7813
- return { tri, buf: at.buf, cap };
8283
+ return { tri, buf: at.buf, raw: at.raw, cap };
7814
8284
  }
7815
8285
  if (op === OP_NODE || op === OP_NODE_TRACK) {
7816
8286
  const flags = code[ip + 3];
7817
8287
  const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags === 2 || flags === 18 || flags === 34);
7818
8288
  if (directChildren) {
7819
- return { tri: at.tri, buf: false, cap: CAP_OFF };
8289
+ return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
7820
8290
  }
7821
8291
  const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
7822
- if (at.buf && cap === at.cap) return at;
7823
- return { tri: at.tri, buf: true, cap };
8292
+ const raw = !hostCst && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags & 2) !== 0 ? RAW_OMIT : RAW_CAPTURE;
8293
+ if (at.buf && raw === at.raw && cap === at.cap) return at;
8294
+ return { tri: at.tri, buf: true, raw, cap };
7824
8295
  }
7825
8296
  if (op === OP_TOKEN) {
7826
8297
  if (at.tri === TRI_NONE && !at.buf) return at;
7827
- return { tri: TRI_NONE, buf: false, cap: at.cap };
8298
+ return { tri: TRI_NONE, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
7828
8299
  }
7829
8300
  if (op === OP_LEAF) {
7830
8301
  if (!at.buf) return at;
7831
- return { tri: at.tri, buf: false, cap: at.cap };
8302
+ return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
7832
8303
  }
7833
8304
  return at;
7834
8305
  }
@@ -7895,6 +8366,162 @@ function scalarTerminalNotChild(code, ip) {
7895
8366
  const op = code[child];
7896
8367
  return op === OP_RX || op === OP_LIT ? child : -1;
7897
8368
  }
8369
+ function leadingScalarTerminal(code, ip, minDepth = 2, throughAttempt = true, throughPeek = false) {
8370
+ const seen = /* @__PURE__ */ new Set();
8371
+ let at = ip;
8372
+ let depth = 0;
8373
+ while (!seen.has(at)) {
8374
+ seen.add(at);
8375
+ const op = code[at];
8376
+ if (op === OP_LIT || op === OP_RX) return depth >= minDepth ? at : -1;
8377
+ if (op === OP_RULE || op === OP_LABEL || op === OP_TOKEN || throughAttempt && op === OP_ATTEMPT) {
8378
+ at = code[at + 1];
8379
+ depth++;
8380
+ continue;
8381
+ }
8382
+ if (throughPeek && op === OP_PEEK) {
8383
+ at = code[at + 1];
8384
+ depth++;
8385
+ continue;
8386
+ }
8387
+ if (op === OP_GATE || op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
8388
+ at = code[at + 2];
8389
+ depth++;
8390
+ continue;
8391
+ }
8392
+ if (op === OP_SEQ || op === OP_SEQV) {
8393
+ if (code[at + 1] < 1) return -1;
8394
+ at = code[at + 2];
8395
+ depth++;
8396
+ continue;
8397
+ }
8398
+ if (op === OP_SEQX) {
8399
+ if (code[at + 2] < 1) return -1;
8400
+ at = code[at + 3];
8401
+ depth++;
8402
+ continue;
8403
+ }
8404
+ return -1;
8405
+ }
8406
+ return -1;
8407
+ }
8408
+ function leadingScalarSequence(code, ip) {
8409
+ const wholeScalar = (start) => {
8410
+ const seen2 = /* @__PURE__ */ new Set();
8411
+ let at2 = start;
8412
+ while (!seen2.has(at2)) {
8413
+ seen2.add(at2);
8414
+ const op = code[at2];
8415
+ if (op === OP_LIT || op === OP_RX) return at2;
8416
+ if (op === OP_RULE || op === OP_TOKEN || op === OP_ATTEMPT) {
8417
+ at2 = code[at2 + 1];
8418
+ continue;
8419
+ }
8420
+ if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
8421
+ at2 = code[at2 + 2];
8422
+ continue;
8423
+ }
8424
+ if (op === OP_SEQ || op === OP_SEQV) {
8425
+ if (code[at2 + 1] !== 1) return -1;
8426
+ at2 = code[at2 + 2];
8427
+ continue;
8428
+ }
8429
+ if (op === OP_SEQX) {
8430
+ if (code[at2 + 2] !== 1) return -1;
8431
+ at2 = code[at2 + 3];
8432
+ continue;
8433
+ }
8434
+ return -1;
8435
+ }
8436
+ return -1;
8437
+ };
8438
+ const seen = /* @__PURE__ */ new Set();
8439
+ let at = ip;
8440
+ let ambientTrivia;
8441
+ while (!seen.has(at)) {
8442
+ seen.add(at);
8443
+ const op = code[at];
8444
+ if (op === OP_RULE) {
8445
+ at = code[at + 1];
8446
+ continue;
8447
+ }
8448
+ if (op === OP_SCOPE_PLAIN) {
8449
+ ambientTrivia = code[at + 1];
8450
+ at = code[at + 2];
8451
+ continue;
8452
+ }
8453
+ if (op === OP_GATE || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
8454
+ at = code[at + 2];
8455
+ continue;
8456
+ }
8457
+ const n = op === OP_SEQ || op === OP_SEQV ? code[at + 1] : op === OP_SEQX ? code[at + 2] : 0;
8458
+ if (n < 3 || ambientTrivia === void 0) return void 0;
8459
+ const base = op === OP_SEQX ? at + 3 : at + 2;
8460
+ const terminals = [
8461
+ wholeScalar(code[base]),
8462
+ wholeScalar(code[base + 1]),
8463
+ wholeScalar(code[base + 2])
8464
+ ];
8465
+ return terminals.every((terminal) => terminal >= 0) ? { terminals, trivia: ambientTrivia } : void 0;
8466
+ }
8467
+ return void 0;
8468
+ }
8469
+ function leadingLiteralFamily(code, constants, ip, minDepth = 2, limit = 4) {
8470
+ const active = /* @__PURE__ */ new Set();
8471
+ const walk = (at, depth) => {
8472
+ if (active.has(at)) return void 0;
8473
+ active.add(at);
8474
+ try {
8475
+ const op = code[at];
8476
+ if (op === OP_LIT) {
8477
+ const value = constants[code[at + 1]];
8478
+ return depth >= minDepth && typeof value === "string" && value.length > 0 ? [at] : void 0;
8479
+ }
8480
+ if (op === OP_RULE || op === OP_LABEL || op === OP_TOKEN || op === OP_ATTEMPT || op === OP_PEEK) {
8481
+ return walk(code[at + 1], depth + 1);
8482
+ }
8483
+ if (op === OP_GATE || op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
8484
+ return walk(code[at + 2], depth + 1);
8485
+ }
8486
+ if (op === OP_SEQ || op === OP_SEQV) {
8487
+ return code[at + 1] < 1 ? void 0 : walk(code[at + 2], depth + 1);
8488
+ }
8489
+ if (op === OP_SEQX) {
8490
+ return code[at + 2] < 1 ? void 0 : walk(code[at + 3], depth + 1);
8491
+ }
8492
+ if (op !== OP_CHOICE) return void 0;
8493
+ const n = code[at + 2];
8494
+ if (n < 1) return void 0;
8495
+ const out = [];
8496
+ for (let i = 0; i < n; i++) {
8497
+ const branch = walk(code[at + 4 + i], depth + 1);
8498
+ if (branch === void 0) return void 0;
8499
+ for (const terminal of branch) {
8500
+ const value = constants[code[terminal + 1]];
8501
+ let covered = false;
8502
+ for (let j = 0; j < out.length; j++) {
8503
+ const prior = constants[code[out[j] + 1]];
8504
+ if (value.startsWith(prior)) {
8505
+ covered = true;
8506
+ break;
8507
+ }
8508
+ }
8509
+ if (covered) continue;
8510
+ for (let j = out.length - 1; j >= 0; j--) {
8511
+ const prior = constants[code[out[j] + 1]];
8512
+ if (prior.startsWith(value)) out.splice(j, 1);
8513
+ }
8514
+ out.push(terminal);
8515
+ if (out.length > limit) return void 0;
8516
+ }
8517
+ }
8518
+ return out;
8519
+ } finally {
8520
+ active.delete(at);
8521
+ }
8522
+ };
8523
+ return walk(ip, 0);
8524
+ }
7898
8525
 
7899
8526
  // src/table/emit-assembly.ts
7900
8527
  var Unemittable = class extends Error {
@@ -7976,6 +8603,16 @@ let _pfScan=null
7976
8603
  let _pfHost
7977
8604
  let _pfDepth=0
7978
8605
  const _pfFrames=[]
8606
+ let _pfTokInput
8607
+ let _pfTokPos=-1
8608
+ let _pfTokBody=-1
8609
+ let _pfTokPacked=-1
8610
+ let _pfTokValue
8611
+ let _pfTokDispatch=-1
8612
+ let _pfTokArm=-1
8613
+ let _pfTokEnd=-1
8614
+ let _pfSeqEnd=-1
8615
+ function _asciiFoldCode(c){return c>=65&&c<=90?c+32:c}
7979
8616
  function _skipTrivia(input,cur,ctx){
7980
8617
  const s=_pfScan
7981
8618
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
@@ -8041,6 +8678,40 @@ if(ctx._triviaLog!==undefined&&ctx._triviaLog.length!==lg)ctx._triviaLog.length=
8041
8678
  if(ctx._rootTriviaLog!==undefined&&ctx._rootTriviaLog.length!==rt)ctx._rootTriviaLog.length=rt
8042
8679
  }
8043
8680
  `;
8681
+ var NO_RAW_RUNTIME_PRELUDE = `
8682
+ function _pushLeafNoRawBuf(ctx,value,s,e){
8683
+ const l={_tag:'leaf',value,span:{start:s,end:e}}
8684
+ const b=ctx._cstBuf
8685
+ if(b.ch!==undefined)b.ch.push(l)
8686
+ else if(b.single!==undefined){b.ch=[b.single,l];b.single=undefined}
8687
+ else b.single=l
8688
+ b.rawLen++
8689
+ }
8690
+ function _pushNodeNoRawBuf(ctx,value){
8691
+ const b=ctx._cstBuf
8692
+ if(b.ch!==undefined)b.ch.push(value)
8693
+ else if(b.single!==undefined){b.ch=[b.single,value];b.single=undefined}
8694
+ else b.single=value
8695
+ b.rawLen++
8696
+ }
8697
+ function _rbNoRawBuf(ctx,raw,tl,lv,lg,rt){
8698
+ const b=ctx._cstBuf
8699
+ if(b.rawLen!==raw)b.rawLen=raw
8700
+ const ch=b.ch
8701
+ if(ch!==undefined){
8702
+ if(lv===0)b.ch=undefined
8703
+ else if(lv===1){b.single=ch[0];b.ch=undefined}
8704
+ else if(ch.length!==lv)ch.length=lv
8705
+ }else if(lv===0)b.single=undefined
8706
+ const bt=b.tl
8707
+ if(bt!==undefined){
8708
+ if(tl===0)b.tl=undefined
8709
+ else if(bt.length!==tl)bt.length=tl
8710
+ }
8711
+ if(ctx._triviaLog!==undefined&&ctx._triviaLog.length!==lg)ctx._triviaLog.length=lg
8712
+ if(ctx._rootTriviaLog!==undefined&&ctx._rootTriviaLog.length!==rt)ctx._rootTriviaLog.length=rt
8713
+ }
8714
+ `;
8044
8715
  function q(s) {
8045
8716
  return JSON.stringify(s);
8046
8717
  }
@@ -8053,11 +8724,12 @@ function sinkReads(t2, s) {
8053
8724
  ${t2}fd=ctx._fields!==undefined?ctx._fields.length:0` : ""}${s.er ? `
8054
8725
  ${t2}er=ctx._errors!==undefined?ctx._errors.length:0` : ""}`;
8055
8726
  }
8056
- function emitMark(t2, buf, s = NO_SINKS, decl = true) {
8727
+ function emitMark(t2, buf, rawMode, s = NO_SINKS, decl = true) {
8057
8728
  if (buf) {
8729
+ const raw = rawMode === RAW_OMIT ? `${t2}raw=b.rawLen` : rawMode === RAW_CAPTURE ? `const r=b.raw;${t2}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0` : `const r=b.raw;${t2}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)`;
8058
8730
  return `${decl ? `let ${t2}raw=0,${t2}tl=0,${t2}lv=0,${t2}lg=0,${t2}rt=0${sinkSlots(t2, s)}
8059
8731
  ` : ""}{const b=ctx._cstBuf
8060
- const r=b.raw;${t2}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
8732
+ ${raw}
8061
8733
  const h=b.ch;${t2}lv=h!==undefined?h.length:b.single!==undefined?1:0
8062
8734
  const l=b.tl;${t2}tl=l!==undefined?l.length:0
8063
8735
  ${t2}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
@@ -8067,7 +8739,7 @@ ${t2}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${sinkReads(t2
8067
8739
  ` : `${t2}n=false
8068
8740
  `}{const b=ctx._cstBuf
8069
8741
  if(b!==undefined){
8070
- const r=b.raw;${t2}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
8742
+ const r=b.raw;${t2}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)
8071
8743
  const h=b.ch;${t2}lv=h!==undefined?h.length:b.single!==undefined?1:0
8072
8744
  const l=b.tl;${t2}tl=l!==undefined?l.length:0
8073
8745
  ${t2}n=true
@@ -8082,14 +8754,16 @@ ${t2}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
8082
8754
  ${t2}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${sinkReads(t2, s)}
8083
8755
  }}`;
8084
8756
  }
8085
- function emitRollback(t2, buf, s = NO_SINKS) {
8757
+ function emitRollback(t2, buf, rawMode, s = NO_SINKS) {
8086
8758
  const fd = s.fd ? `
8087
8759
  if(ctx._fields!==undefined&&ctx._fields.length!==${t2}fd)ctx._fields.length=${t2}fd` : "";
8088
8760
  const er = s.er ? `
8089
8761
  if(ctx._errors!==undefined&&ctx._errors.length!==${t2}er)ctx._errors.length=${t2}er` : "";
8090
- if (buf) return `_rbBuf(ctx,${t2}raw,${t2}tl,${t2}lv,${t2}lg,${t2}rt)${fd}${er}`;
8091
- if (!s.fd && !s.er) return `if(${t2}n)rollbackTriviaAt(ctx,${t2}raw,${t2}tl,${t2}lv,0,undefined,${t2}lg,${t2}rt)`;
8092
- return `if(${t2}n){rollbackTriviaAt(ctx,${t2}raw,${t2}tl,${t2}lv,${s.fd ? `${t2}fd` : "0"},${s.er ? `${t2}er` : "undefined"},${t2}lg,${t2}rt)}`;
8762
+ if (buf && rawMode === RAW_OMIT) return `_rbNoRawBuf(ctx,${t2}raw,${t2}tl,${t2}lv,${t2}lg,${t2}rt)${fd}${er}`;
8763
+ if (buf && rawMode === RAW_CAPTURE) return `_rbBuf(ctx,${t2}raw,${t2}tl,${t2}lv,${t2}lg,${t2}rt)${fd}${er}`;
8764
+ if (buf) return `rollbackTriviaAt(ctx,${t2}raw,${t2}tl,${t2}lv,${s.fd ? `${t2}fd` : "undefined"},${s.er ? `${t2}er` : "undefined"},${t2}lg,${t2}rt)`;
8765
+ if (!s.fd && !s.er) return `if(${t2}n)rollbackTriviaAt(ctx,${t2}raw,${t2}tl,${t2}lv,undefined,undefined,${t2}lg,${t2}rt)`;
8766
+ return `if(${t2}n){rollbackTriviaAt(ctx,${t2}raw,${t2}tl,${t2}lv,${s.fd ? `${t2}fd` : "undefined"},${s.er ? `${t2}er` : "undefined"},${t2}lg,${t2}rt)}`;
8093
8767
  }
8094
8768
  function emitTerm(callee, dst, t2, l, skip) {
8095
8769
  const fast = `const ${t2}v=${callee}(input,cur,ctx)
@@ -8147,37 +8821,111 @@ function rebuildPools(cc, fx, disp, plan) {
8147
8821
  })
8148
8822
  };
8149
8823
  }
8150
- function emitAssemblySource(t2, prog, cfg, extraIps = []) {
8151
- const { code, k, disp, dsp, triviaLabelled } = t2;
8824
+ function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false) {
8825
+ const { code, k, fx, disp, dsp, triviaLabelled } = t2;
8152
8826
  const swapLegal = !cfg.trackLines;
8153
8827
  const hostCst = cfg.hostCst;
8154
8828
  const REC = prog.rec === 1 && cfg.tolerant;
8155
8829
  if (cfg.coverage) throw new Unemittable("a coverage assembly");
8156
8830
  const roots = [...Object.values(prog.rules), ...extraIps];
8831
+ const reachable = [...reachableSites(code, roots)];
8157
8832
  const labels = computeSiteLabels(code, roots, hostCst);
8158
8833
  const scalarSpecs = /* @__PURE__ */ new Set();
8834
+ const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
8835
+ const largeChoiceLiteralFamilies = /* @__PURE__ */ new Map();
8836
+ const largeChoiceScalarSequences = /* @__PURE__ */ new Map();
8837
+ const tokenChoiceCandidates = /* @__PURE__ */ new Map();
8838
+ const tokenChoiceDispatches = /* @__PURE__ */ new Set();
8839
+ const tokenChoiceBodies = /* @__PURE__ */ new Set();
8159
8840
  if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
8160
- for (const ip of reachableSites(code, roots)) {
8161
- if (code[ip] !== OP_NODE) continue;
8162
- const child = scalarTerminalNodeChild(code, ip);
8163
- if (child >= 0) scalarSpecs.add(code[child + 1]);
8841
+ for (const ip of reachable) {
8842
+ if (code[ip] === OP_NODE) {
8843
+ const child = scalarTerminalNodeChild(code, ip);
8844
+ if (child >= 0) scalarSpecs.add(code[child + 1]);
8845
+ continue;
8846
+ }
8847
+ if (code[ip] !== OP_CHOICE || disp[code[ip + 1]].exclusive) continue;
8848
+ const n = code[ip + 2];
8849
+ for (let i = 0; i < n; i++) {
8850
+ const armIp = code[ip + 4 + i];
8851
+ const child = leadingScalarTerminal(code, armIp, 2, true, true);
8852
+ if (n === 2 || n === 3) {
8853
+ if (child >= 0) scalarSpecs.add(code[child + 1]);
8854
+ continue;
8855
+ }
8856
+ if (child >= 0) {
8857
+ const spec = k[code[child + 1]];
8858
+ if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
8859
+ largeChoiceScalarSpecs.add(code[child + 1]);
8860
+ continue;
8861
+ }
8862
+ }
8863
+ const family = leadingLiteralFamily(code, k, armIp);
8864
+ if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
8865
+ const value = k[code[terminal + 1]];
8866
+ return typeof value === "string" && value.length >= 2;
8867
+ })) {
8868
+ largeChoiceLiteralFamilies.set(armIp, family);
8869
+ }
8870
+ const sequence6 = leadingScalarSequence(code, armIp);
8871
+ if (sequence6 !== void 0 && (sequence6.trivia < 0 || swapLegal && t2.triviaScan[sequence6.trivia] != null)) {
8872
+ largeChoiceScalarSequences.set(armIp, sequence6);
8873
+ }
8874
+ }
8875
+ let candidate;
8876
+ let ambiguous = false;
8877
+ for (let i = 0; i < n; i++) {
8878
+ const armIp = code[ip + 4 + i];
8879
+ if (code[armIp] !== OP_XFORM) continue;
8880
+ const dispatchIp = code[armIp + 2];
8881
+ if (code[dispatchIp] !== OP_DISPATCH) continue;
8882
+ const selectorIp = code[dispatchIp + 1];
8883
+ if (code[selectorIp] !== OP_LEX_BODY) continue;
8884
+ if (candidate !== void 0) {
8885
+ ambiguous = true;
8886
+ break;
8887
+ }
8888
+ candidate = { arm: i, dispatchIp };
8889
+ }
8890
+ if (!ambiguous && candidate !== void 0) {
8891
+ tokenChoiceCandidates.set(ip, candidate);
8892
+ tokenChoiceDispatches.add(candidate.dispatchIp);
8893
+ tokenChoiceBodies.add(code[code[candidate.dispatchIp + 1] + 1]);
8894
+ }
8164
8895
  }
8165
8896
  }
8166
- const sinks = (() => {
8167
- let fd = false;
8168
- let er = REC;
8169
- for (const ip of reachableSites(code, roots)) {
8170
- const op = code[ip];
8171
- if (op === OP_SCAN) {
8172
- fd = true;
8173
- er = true;
8174
- break;
8897
+ const needsNoRawPrelude = !hostCst && reachable.some((ip) => {
8898
+ const op = code[ip];
8899
+ return (op === OP_NODE || op === OP_NODE_TRACK) && code[ip + 1] >= 0 && code[ip + 4] < 0 && (code[ip + 3] & 2) !== 0;
8900
+ });
8901
+ const sinkSites = reachable;
8902
+ const sinkBits = /* @__PURE__ */ new Map();
8903
+ for (const ip of sinkSites) {
8904
+ const op = code[ip];
8905
+ sinkBits.set(
8906
+ ip,
8907
+ op === OP_SCAN ? 3 : (op === OP_FIELD ? 1 : 0) | (op === OP_EXPECT || REC && (op === OP_REP || op === OP_REPV) ? 2 : 0)
8908
+ );
8909
+ }
8910
+ const sinkKids = [];
8911
+ let sinkChanged = true;
8912
+ while (sinkChanged) {
8913
+ sinkChanged = false;
8914
+ for (const ip of sinkSites) {
8915
+ let bits = sinkBits.get(ip) ?? 0;
8916
+ sinkKids.length = 0;
8917
+ childSlots(code, ip, sinkKids);
8918
+ for (let i = 0; i < sinkKids.length; i++) bits |= sinkBits.get(sinkKids[i]) ?? 0;
8919
+ if (bits !== sinkBits.get(ip)) {
8920
+ sinkBits.set(ip, bits);
8921
+ sinkChanged = true;
8175
8922
  }
8176
- if (op === OP_FIELD) fd = true;
8177
- else if (op === OP_EXPECT) er = true;
8178
8923
  }
8179
- return { fd, er };
8180
- })();
8924
+ }
8925
+ const sinksAt = (ip) => {
8926
+ const bits = sinkBits.get(ip) ?? 0;
8927
+ return bits === 0 ? NO_SINKS : { fd: (bits & 1) !== 0, er: (bits & 2) !== 0 };
8928
+ };
8181
8929
  const bodies = [];
8182
8930
  const byIp = /* @__PURE__ */ new Map();
8183
8931
  const reached = /* @__PURE__ */ new Set();
@@ -8204,9 +8952,117 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
8204
8952
  const fxRef = (i) => hoist("fx", `FX[${i}]`);
8205
8953
  const fnRef = (i) => hoist("fn", `FNS[${i}]`);
8206
8954
  const recognizerRef = (i) => hoist("rec", `RECOG[${i}]`);
8955
+ const scalarSequenceRefs = /* @__PURE__ */ new Map();
8956
+ const scalarSequenceRef = (sequence6) => {
8957
+ const key = `${sequence6.trivia}:${sequence6.terminals.map((terminal) => code[terminal + 1]).join(",")}`;
8958
+ const prior = scalarSequenceRefs.get(key);
8959
+ if (prior !== void 0) return prior;
8960
+ const recognizers = sequence6.terminals.map((terminal) => recognizerRef(code[terminal + 1]));
8961
+ const expected = sequence6.terminals.map((terminal) => fxRef(code[terminal + 2]));
8962
+ const scan = sequence6.trivia < 0 ? void 0 : hoist("ts", `TRIVIASCAN[${sequence6.trivia}]`);
8963
+ const name = `_sd${scalarSequenceRefs.size}_`;
8964
+ const steps = recognizers.map((recognize, i) => `${i === 0 ? "let " : ""}at=${i === 0 ? "pos" : scan === void 0 ? "cur" : `${scan}(input,cur)`}
8965
+ ${i === 0 ? "let " : ""}cur=${recognize}(input,at)
8966
+ if(cur<0){_pfSeqEnd=at;return ${~i}}`).join("\n");
8967
+ choiceDefs.push(`function ${name}(input,pos){
8968
+ ${steps}
8969
+ return cur
8970
+ }`);
8971
+ const made = { name, expected };
8972
+ scalarSequenceRefs.set(key, made);
8973
+ return made;
8974
+ };
8207
8975
  const sentRef = (cls) => cls < 0 ? "undefined" : hoist("sent", `SENTS[${cls}]`);
8208
8976
  let uid = 0;
8209
8977
  const tmp = () => `_t${uid++}_`;
8978
+ const dispatchClaim = (m) => {
8979
+ switch (m[0]) {
8980
+ case 0:
8981
+ return `key.startsWith(${q(m[1])})`;
8982
+ case 1:
8983
+ return `key.endsWith(${q(m[1])})`;
8984
+ case 3:
8985
+ return `asciiFoldKey(key).startsWith(${q(m[1])})`;
8986
+ case 4:
8987
+ return `asciiFoldKey(key).endsWith(${q(m[1])})`;
8988
+ default: {
8989
+ if (!m[2].includes("g") && !m[2].includes("y")) {
8990
+ try {
8991
+ new RegExp(m[1], m[2]);
8992
+ return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
8993
+ } catch {
8994
+ }
8995
+ }
8996
+ return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
8997
+ }
8998
+ }
8999
+ };
9000
+ const tokenDecisionRefs = /* @__PURE__ */ new Map();
9001
+ function tokenDecisionFor(dispatchIp) {
9002
+ const prior = tokenDecisionRefs.get(dispatchIp);
9003
+ if (prior !== void 0) return prior;
9004
+ const selectorIp = code[dispatchIp + 1];
9005
+ const body = code[selectorIp + 1];
9006
+ const lineFlags = code[selectorIp + 4];
9007
+ const hasSuffix = (lineFlags & 4) !== 0;
9008
+ const di = code[dispatchIp + 2];
9009
+ const spec = dsp[di];
9010
+ const n = code[dispatchIp + 5];
9011
+ validateDispatchSpec(spec, n, code[dispatchIp + 4]);
9012
+ const recognize = hoist("lex", `LEX[${body}]`);
9013
+ const bk = hoist("bk", `DSP[${di}].byKey`);
9014
+ const expected = hoist("dx", `DSP[${di}].expected`);
9015
+ const fold = spec.byFold.size > 0 ? `if(arm===undefined)arm=${hoist("bf", `DSP[${di}].byFold`)}.get(asciiFoldKey(key))
9016
+ ` : "";
9017
+ const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
9018
+ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${dispatchClaim(m)})arm=${m[3]}`).join("\n")}
9019
+ }
9020
+ `;
9021
+ const foldedEntries = [...spec.byFold.entries()];
9022
+ const fixedFunctionChoice = spec.byKey.size === 0 && foldedEntries.length === 1 && spec.match.length === 1 && spec.match[0][0] === 2 && spec.match[0][1] === "^(?!(?:url|calc)\\($).+\\($" && spec.match[0][2] === "i" && code[dispatchIp + 3] < 0;
9023
+ const foldedRangeEquals = (value) => {
9024
+ const folded = value.replace(/[A-Z]/g, (c) => c.toLowerCase());
9025
+ return `e-pos===${folded.length}&&${[...folded].map((c, i) => {
9026
+ const cc = c.charCodeAt(0);
9027
+ return `_asciiFoldCode(input.charCodeAt(pos+${i}))===${cc}`;
9028
+ }).join("&&")}`;
9029
+ };
9030
+ const classify = fixedFunctionChoice ? (() => {
9031
+ const [exact, exactArm] = foldedEntries[0];
9032
+ const genericArm = spec.match[0][3];
9033
+ return `let arm
9034
+ if(${foldedRangeEquals(exact)})arm=${exactArm}
9035
+ else if(sm&&e>pos+1){
9036
+ let clean=true
9037
+ for(let i=pos;i<e;i++){const c=input.charCodeAt(i);if(c===10||c===13||c===0x2028||c===0x2029){clean=false;break}}
9038
+ if(clean&&!(${foldedRangeEquals("url(")})&&!(${foldedRangeEquals("calc(")}))arm=${genericArm}
9039
+ }`;
9040
+ })() : `const key=input.slice(pos,e)
9041
+ let arm=${bk}.get(key)
9042
+ ${fold}${chain}`;
9043
+ const name = `_td${tokenDecisionRefs.size}_`;
9044
+ choiceDefs.push(`function ${name}(input,pos){
9045
+ const r=${recognize}(input,pos)
9046
+ if(r<0)return -1
9047
+ const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
9048
+ ${classify}
9049
+ if(arm===undefined){
9050
+ ${code[dispatchIp + 3] < 0 ? "_pfTokEnd=e;return 0" : `arm=${n}`}
9051
+ }
9052
+ ${fixedFunctionChoice ? "const key=input.slice(pos,e)" : ""}
9053
+ _pfTokInput=input
9054
+ _pfTokPos=pos
9055
+ _pfTokBody=${body}
9056
+ _pfTokPacked=r
9057
+ _pfTokValue=key
9058
+ _pfTokDispatch=${dispatchIp}
9059
+ _pfTokArm=arm
9060
+ return 1
9061
+ }`);
9062
+ const made = { name, expected };
9063
+ tokenDecisionRefs.set(dispatchIp, made);
9064
+ return made;
9065
+ }
8210
9066
  function skipFor(l) {
8211
9067
  if (l.tri < 0) return "_skipTrivia";
8212
9068
  const ki = l.tri;
@@ -8294,7 +9150,8 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
8294
9150
  const op = code[ip];
8295
9151
  const head = `function ${fname}(input,pos,ctx){`;
8296
9152
  const L = labels.at(ip);
8297
- const pushLeaf = L.buf && !cfg.trackLines ? "_pushLeafBuf" : "_pushLeaf";
9153
+ const sinks = sinksAt(ip);
9154
+ const pushLeaf = L.buf && !cfg.trackLines ? L.raw === RAW_OMIT ? "_pushLeafNoRawBuf" : L.raw === RAW_CAPTURE ? "_pushLeafBuf" : "_pushLeaf" : "_pushLeaf";
8298
9155
  const captureLeaf = (value) => {
8299
9156
  const call = `${pushLeaf}(ctx,${value},pos,e)`;
8300
9157
  return L.buf ? call : `if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)${call}`;
@@ -8545,20 +9402,24 @@ return out
8545
9402
  }`;
8546
9403
  }
8547
9404
  case OP_LEX_BODY: {
8548
- const recognize = hoist("lex", `LEX[${code[ip + 1]}]`);
9405
+ const body = code[ip + 1];
9406
+ const recognize = hoist("lex", `LEX[${body}]`);
8549
9407
  const expected = fxRef(code[ip + 2]);
8550
9408
  const suffixExpected = fxRef(code[ip + 3]);
8551
9409
  const lineFlags = code[ip + 4];
8552
9410
  const hasSuffix = (lineFlags & 4) !== 0;
9411
+ const pending = tokenChoiceBodies.has(body);
8553
9412
  return `${head}
8554
- const r=${recognize}(input,pos)
9413
+ ${pending ? `const tp=_pfTokBody===${body}&&_pfTokInput===input&&_pfTokPos===pos
9414
+ const r=tp?_pfTokPacked:${recognize}(input,pos)` : `const r=${recognize}(input,pos)`}
8555
9415
  if(r<0){ctx._fe=pos;ctx._fx=${expected};if(ctx._probe!==undefined)failAt(ctx,${expected},pos);return FAIL}
8556
9416
  const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
8557
9417
  ${(lineFlags & 1) !== 0 ? "_trackLines(ctx,input,sm?e-1:e)" : ""}
8558
9418
  ${hasSuffix ? "ctx._fc=false" : ""}
8559
9419
  ${hasSuffix && (lineFlags & 2) !== 0 ? "if(sm)_trackLines(ctx,input,e)" : ""}
8560
9420
  ${hasSuffix ? `if(!sm){ctx._fe=e;ctx._fx=${suffixExpected};if(ctx._probe!==undefined)failAt(ctx,${suffixExpected},e)}` : ""}
8561
- const v=input.slice(pos,e)
9421
+ const v=${pending ? "tp?_pfTokValue:" : ""}input.slice(pos,e)
9422
+ ${pending ? "if(tp){_pfTokBody=-1;_pfTokValue=undefined}" : ""}
8562
9423
  if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
8563
9424
  EC.e=e
8564
9425
  return v
@@ -8614,12 +9475,13 @@ return v
8614
9475
  /* ── transaction ─────────────────────────────────────────────────────── */
8615
9476
  case OP_ATTEMPT: {
8616
9477
  const child = link(code[ip + 1]);
9478
+ const clean = !REC && failureRollbackClean(prog, ip);
8617
9479
  const p = tmp();
8618
9480
  return `${head}
8619
- ${emitMark(p, L.buf, sinks)}
9481
+ ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
8620
9482
  const v=${child}(input,pos,ctx)
8621
9483
  if(v!==FAIL)return v
8622
- ${emitRollback(p, L.buf, sinks)}
9484
+ ${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
8623
9485
  if(ctx._fc===true)return FAIL
8624
9486
  ctx._fe=pos
8625
9487
  return FAIL
@@ -8642,9 +9504,9 @@ return FAIL
8642
9504
  const xf = fxRef(code[ip + 2]);
8643
9505
  const p = tmp();
8644
9506
  return `${head}
8645
- ${emitMark(p, L.buf, sinks)}
9507
+ ${emitMark(p, L.buf, L.raw, sinks)}
8646
9508
  const v=${child}(input,pos,ctx)
8647
- ${emitRollback(p, L.buf, sinks)}
9509
+ ${emitRollback(p, L.buf, L.raw, sinks)}
8648
9510
  if(v===FAIL){EC.e=pos;return null}
8649
9511
  ctx._fe=pos
8650
9512
  ctx._fx=${xf}
@@ -8656,9 +9518,9 @@ return FAIL
8656
9518
  const xf = fxRef(code[ip + 2]);
8657
9519
  const p = tmp();
8658
9520
  return `${head}
8659
- ${emitMark(p, L.buf, sinks)}
9521
+ ${emitMark(p, L.buf, L.raw, sinks)}
8660
9522
  const v=${child}(input,pos,ctx)
8661
- ${emitRollback(p, L.buf, sinks)}
9523
+ ${emitRollback(p, L.buf, L.raw, sinks)}
8662
9524
  if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
8663
9525
  EC.e=pos
8664
9526
  return null
@@ -8666,14 +9528,15 @@ return null
8666
9528
  }
8667
9529
  case OP_OPT: {
8668
9530
  const child = link(code[ip + 1]);
9531
+ const clean = !REC && failureRollbackClean(prog, ip);
8669
9532
  const p = tmp();
8670
9533
  return `${head}
8671
- ${emitMark(p, L.buf, sinks)}
9534
+ ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
8672
9535
  ctx._fc=false
8673
9536
  const v=${child}(input,pos,ctx)
8674
9537
  if(v===FAIL){
8675
9538
  if(ctx._fc===true)return FAIL
8676
- ${emitRollback(p, L.buf, sinks)}
9539
+ ${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
8677
9540
  EC.e=pos
8678
9541
  return null
8679
9542
  }
@@ -8772,57 +9635,193 @@ return FAIL
8772
9635
  const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
8773
9636
  const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
8774
9637
  const gateRefs = Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
9638
+ const tokenCandidate = tokenChoiceCandidates.get(ip);
9639
+ const pretests = Array.from({ length: n }, (_, i) => {
9640
+ if (tokenCandidate?.arm === i) {
9641
+ return { token: tokenDecisionFor(tokenCandidate.dispatchIp) };
9642
+ }
9643
+ const terminal = leadingScalarTerminal(code, code[base + i], 2, true, true);
9644
+ if (terminal >= 0) {
9645
+ const spec = code[terminal + 1];
9646
+ if ((n === 2 || n === 3 ? scalarSpecs : largeChoiceScalarSpecs).has(spec)) {
9647
+ return { scalar: [recognizerRef(spec)] };
9648
+ }
9649
+ }
9650
+ const family = largeChoiceLiteralFamilies.get(code[base + i]);
9651
+ if (family !== void 0) {
9652
+ return { scalar: family.map((member) => recognizerRef(code[member + 1])) };
9653
+ }
9654
+ const sequence6 = largeChoiceScalarSequences.get(code[base + i]);
9655
+ return sequence6 === void 0 ? void 0 : { sequence: scalarSequenceRef(sequence6) };
9656
+ });
8775
9657
  const maskable = n <= 32;
8776
9658
  const maskName = maskable ? hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`) : "";
8777
9659
  if (maskable) maskPlan.push(~di);
8778
9660
  const p = tmp();
8779
- const catchName = maskable ? `_cx${uid++}_` : "";
8780
- if (maskable) {
9661
+ const encodedRollbackMask = choiceRollbackMask(prog, ip) ?? -1;
9662
+ const rollbackMask = REC ? -1 : encodedRollbackMask;
9663
+ const hasRollback = rollbackMask !== 0;
9664
+ const startFailureExact = arms.every((_arm, i) => {
9665
+ const terminal = leadingScalarTerminal(code, code[base + i], 0, false);
9666
+ if (terminal < 0) return false;
9667
+ const op2 = code[terminal];
9668
+ const spec = k[code[terminal + 1]];
9669
+ const terminalFx = fx[code[terminal + 2]];
9670
+ const armFx = fx[code[base + n + i]];
9671
+ if (terminalFx.length !== armFx.length || terminalFx.some((expected2, at) => expected2 !== armFx[at])) return false;
9672
+ if (op2 === OP_LIT) return typeof spec === "string" && spec.length > 0;
9673
+ return op2 === OP_RX && spec instanceof RegExp && !regexCanMatchEmpty(spec.source);
9674
+ });
9675
+ const rollbackFor = (i) => rollbackMask === -1 || (rollbackMask & 1 << i) !== 0 ? emitRollback(p, L.buf, L.raw, sinks) : "";
9676
+ if (choiceCannotCommit(prog, ip) && !startFailureExact) {
9677
+ const deepAt = Array.from({ length: n }, () => tmp());
9678
+ const deepFx = Array.from({ length: n }, () => tmp());
9679
+ const remember = (i, at, expectedSet) => `${deepAt[i]}=${at};${deepFx[i]}=${expectedSet}`;
9680
+ const lazyArms = (ascii) => arms.map((arm, i) => {
9681
+ const pretest = pretests[i];
9682
+ const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
9683
+ const scalarCondition = pretest?.scalar === void 0 ? "" : pretest.scalar.length === 1 ? `&&${pretest.scalar[0]}(input,pos)>=0` : `&&(${pretest.scalar.map((recognize) => `${recognize}(input,pos)>=0`).join("||")})`;
9684
+ const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
9685
+ const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
9686
+ const gate = ascii ? `(bits&${1 << i})!==0${condition}` : `(${gateRefs[i]}===null||classHas(${gateRefs[i]},c))${condition}`;
9687
+ const routeMiss = pretest?.token === void 0 ? "" : `
9688
+ if(${decision}===0){
9689
+ ctx._fc=false
9690
+ {const at=_pfTokEnd
9691
+ ${remember(i, "at", pretest.token.expected)}}
9692
+ }`;
9693
+ const sequenceMiss = pretest?.sequence === void 0 ? "" : `
9694
+ else if(${ascii ? `(bits&${1 << i})!==0&&` : ""}${decision}<0){
9695
+ ctx._fc=false
9696
+ {const at=_pfSeqEnd
9697
+ ${remember(i, "at", pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("") + pretest.sequence.expected.at(-1))}}
9698
+ }`;
9699
+ return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
9700
+ `}if(${gate}){
9701
+ ctx._fc=false
9702
+ {const v=${arm}(input,pos,ctx)
9703
+ if(v!==FAIL)return v}
9704
+ {const at=ctx._fe??pos
9705
+ ${remember(i, "at", "ctx._fx")}}
9706
+ ${rollbackFor(i)}
9707
+ }${routeMiss}${sequenceMiss}`;
9708
+ }).join("\n");
9709
+ const merge = deepAt.map((at, i) => `{const at=${at}??pos
9710
+ const ex=${at}===undefined?${expected[i]}:${deepFx[i]}
9711
+ if(at>best){best=at;acc=_accSet(ex,undefined)}
9712
+ else if(at===best)acc=_accSet(ex,acc)
9713
+ }`).join("\n");
9714
+ const finish = `let best=pos,acc
9715
+ ${merge}
9716
+ ctx._fe=pos;ctx._fx=acc??${choiceFx}
9717
+ return FAIL`;
9718
+ return `${head}
9719
+ const c=lead(input,pos)
9720
+ ${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
9721
+ ${deepAt.map((at, i) => `let ${at},${deepFx[i]}`).join("\n")}
9722
+ ${maskable ? `if(c<128){
9723
+ const bits=${maskName}[c<0?128:c]
9724
+ if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
9725
+ ${lazyArms(true)}
9726
+ }else{
9727
+ ${lazyArms(false)}
9728
+ }
9729
+ ` : lazyArms(false)}
9730
+ ${finish}
9731
+ }`;
9732
+ }
9733
+ const needsCatch = maskable || startFailureExact;
9734
+ const catchName = needsCatch ? `_cx${uid++}_` : "";
9735
+ if (needsCatch) {
8781
9736
  const catchCases = expected.map((e, i) => `case ${i}:if(target<=${i})return acc;acc=_accSet(${e},acc)`).join("\n");
8782
9737
  choiceDefs.push(`function ${catchName}(target,prev,acc){switch(prev){
8783
9738
  ${catchCases}
8784
9739
  }return acc}`);
8785
9740
  }
8786
9741
  const maskArms = maskable ? arms.map((arm, i) => {
8787
- return `if((bits&${1 << i})!==0){
9742
+ const pretest = pretests[i];
9743
+ const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
9744
+ const scalarCondition = pretest?.scalar === void 0 ? "" : pretest.scalar.length === 1 ? `&&${pretest.scalar[0]}(input,pos)>=0` : `&&(${pretest.scalar.map((recognize) => `${recognize}(input,pos)>=0`).join("||")})`;
9745
+ const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
9746
+ const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
9747
+ const routeMiss = pretest?.token === void 0 ? "" : `
9748
+ if(${decision}===0){
9749
+ ctx._fc=false
9750
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
9751
+ prev=${i + 1}`}
9752
+ {const at=_pfTokEnd
9753
+ if(at>best){best=at;acc=undefined}
9754
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.token.expected},acc)}
9755
+ }`;
9756
+ const sequenceMiss = pretest?.sequence === void 0 ? "" : `
9757
+ else if((bits&${1 << i})!==0&&${decision}<0){
9758
+ ctx._fc=false
9759
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
9760
+ prev=${i + 1}`}
9761
+ {const at=_pfSeqEnd
9762
+ if(at>best){best=at;acc=undefined}
9763
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("")}${pretest.sequence.expected.at(-1)},acc)}
9764
+ }`;
9765
+ return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
9766
+ `}if((bits&${1 << i})!==0${condition}){
8788
9767
  ctx._fc=false
8789
9768
  {const v=${arm}(input,pos,ctx)
8790
9769
  if(v!==FAIL)return v}
8791
- if(best===pos)acc=${catchName}(${i},prev,acc)
8792
- prev=${i + 1}
9770
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
9771
+ prev=${i + 1}`}
8793
9772
  {const at=ctx._fe??pos
8794
9773
  if(at>best){best=at;acc=undefined}
8795
- if(at===best)acc=_accSet(ctx._fx,acc)}
8796
- if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
8797
- ${emitRollback(p, L.buf, sinks)}
8798
- }`;
9774
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(ctx._fx,acc)}
9775
+ if(ctx._fc===true){${startFailureExact ? `if(best===pos){acc=${catchName}(${i},0,undefined);acc=_accSet(ctx._fx,acc)}` : ""}if(acc!==undefined)ctx._fx=acc;return FAIL}
9776
+ ${rollbackFor(i)}
9777
+ }${routeMiss}${sequenceMiss}`;
8799
9778
  }).join("\n") : "";
8800
- const generalArms = arms.map((arm, i) => `if(${gateRefs[i]}===null||classHas(${gateRefs[i]},c)){
9779
+ const generalArms = arms.map((arm, i) => {
9780
+ const pretest = pretests[i];
9781
+ const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
9782
+ const scalarCondition = pretest?.scalar === void 0 ? "" : pretest.scalar.length === 1 ? `&&${pretest.scalar[0]}(input,pos)>=0` : `&&(${pretest.scalar.map((recognize) => `${recognize}(input,pos)>=0`).join("||")})`;
9783
+ const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
9784
+ const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
9785
+ const miss = pretest?.sequence !== void 0 ? `else if(${decision}<0){
9786
+ ctx._fc=false
9787
+ const at=_pfSeqEnd
9788
+ if(at>best){best=at;acc=undefined}
9789
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("")}${pretest.sequence.expected.at(-1)},acc)
9790
+ }${startFailureExact ? "" : `else if(best===pos)acc=_accSet(${expected[i]},acc)`}` : pretest?.token === void 0 ? startFailureExact ? "" : `else if(best===pos)acc=_accSet(${expected[i]},acc)` : `else if(${decision}===0){
9791
+ ctx._fc=false
9792
+ const at=_pfTokEnd
9793
+ if(at>best){best=at;acc=undefined}
9794
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.token.expected},acc)
9795
+ }${startFailureExact ? "" : `else if(best===pos)acc=_accSet(${expected[i]},acc)`}`;
9796
+ return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
9797
+ `}if((${gateRefs[i]}===null||classHas(${gateRefs[i]},c))${condition}){
8801
9798
  ctx._fc=false
8802
9799
  {const v=${arm}(input,pos,ctx)
8803
9800
  if(v!==FAIL)return v}
8804
9801
  {const at=ctx._fe??pos
8805
9802
  if(at>best){best=at;acc=undefined}
8806
- if(at===best)acc=_accSet(ctx._fx,acc)}
8807
- if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
8808
- ${emitRollback(p, L.buf, sinks)}
8809
- }else if(best===pos)acc=_accSet(${expected[i]},acc)`).join("\n");
9803
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(ctx._fx,acc)}
9804
+ if(ctx._fc===true){${startFailureExact ? `if(best===pos){acc=${catchName}(${i},0,undefined);acc=_accSet(ctx._fx,acc)}` : ""}if(acc!==undefined)ctx._fx=acc;return FAIL}
9805
+ ${rollbackFor(i)}
9806
+ }${miss}`;
9807
+ }).join("\n");
8810
9808
  return `${head}
8811
9809
  const c=lead(input,pos)
8812
- ${emitMark(p, L.buf, sinks)}
9810
+ ${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
8813
9811
  let acc
8814
9812
  let best=pos
8815
9813
  ${maskable ? `if(c<128){
8816
9814
  const bits=${maskName}[c<0?128:c]
8817
- let prev=0
9815
+ if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
9816
+ ${startFailureExact ? "" : "let prev=0"}
8818
9817
  ${maskArms}
8819
- if(best===pos)acc=${catchName}(${n},prev,acc)
8820
- ctx._fe=pos;ctx._fx=acc??${choiceFx}
9818
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${n},prev,acc)`}
9819
+ ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
8821
9820
  return FAIL
8822
9821
  }
8823
9822
  ` : ""}
8824
9823
  ${generalArms}
8825
- ctx._fe=pos;ctx._fx=acc??${choiceFx}
9824
+ ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
8826
9825
  return FAIL
8827
9826
  }`;
8828
9827
  }
@@ -8841,30 +9840,8 @@ return FAIL
8841
9840
  for (let i = 0; i < n; i++) arms.push(link(code[armBase + i]));
8842
9841
  const bk = hoist("bk", `DSP[${di}].byKey`);
8843
9842
  const dx = hoist("dx", `DSP[${di}].expected`);
8844
- const claims = (m) => {
8845
- switch (m[0]) {
8846
- case 0:
8847
- return `key.startsWith(${q(m[1])})`;
8848
- case 1:
8849
- return `key.endsWith(${q(m[1])})`;
8850
- case 3:
8851
- return `asciiFoldKey(key).startsWith(${q(m[1])})`;
8852
- case 4:
8853
- return `asciiFoldKey(key).endsWith(${q(m[1])})`;
8854
- default: {
8855
- if (!m[2].includes("g") && !m[2].includes("y")) {
8856
- try {
8857
- new RegExp(m[1], m[2]);
8858
- return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
8859
- } catch {
8860
- }
8861
- }
8862
- return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
8863
- }
8864
- }
8865
- };
8866
9843
  const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
8867
- ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${claims(m)})arm=${m[3]}`).join("\n")}
9844
+ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${dispatchClaim(m)})arm=${m[3]}`).join("\n")}
8868
9845
  }
8869
9846
  `;
8870
9847
  const fold = spec.byFold.size > 0 ? `if(arm===undefined)arm=${hoist("bf", `DSP[${di}].byFold`)}.get(asciiFoldKey(key))
@@ -8872,33 +9849,43 @@ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${claims(m)})arm=${m[3]}
8872
9849
  const m1 = tmp();
8873
9850
  const m2 = tmp();
8874
9851
  const routedCall = (target) => `{const savedRouted=ctx._routed
8875
- ${emitRollback(m1, L.buf, sinks)}
8876
- ${emitMark(m2, L.buf, sinks, false)}
9852
+ ${emitRollback(m1, L.buf, L.raw, sinks)}
9853
+ ${emitMark(m2, L.buf, L.raw, sinks, false)}
8877
9854
  ctx._routed={value:key,span:{start:pos,end:selEnd}}
8878
9855
  try{v=${target}(input,pos,ctx)}finally{ctx._routed=savedRouted}
8879
9856
  break}`;
8880
9857
  const plainCall = (target) => `v=${target}(input,selEnd,ctx);break`;
8881
9858
  const armCases = arms.map((target, i) => `case ${i}:${spec.routed[i] === 1 ? routedCall(target) : plainCall(target)}`).join("\n");
8882
9859
  const fallbackCase = other === void 0 ? "" : `default:${otherRouted ? routedCall(other) : plainCall(other)}`;
9860
+ const armSelection = tokenChoiceDispatches.has(ip) ? `const tp=_pfTokDispatch===${ip}&&_pfTokInput===input&&_pfTokPos===pos
9861
+ let arm
9862
+ if(tp){
9863
+ arm=_pfTokArm
9864
+ _pfTokDispatch=-1
9865
+ _pfTokInput=undefined
9866
+ if(arm===${n})arm=undefined
9867
+ }else{
9868
+ arm=${bk}.get(key)
9869
+ ${fold}${chain}}` : `let arm=${bk}.get(key)
9870
+ ${fold}${chain}`;
8883
9871
  return `${head}
8884
- ${emitMark(m1, L.buf, sinks)}
9872
+ ${emitMark(m1, L.buf, L.raw, sinks)}
8885
9873
  const sv=${selector}(input,pos,ctx)
8886
9874
  if(sv===FAIL)return FAIL
8887
9875
  const selEnd=EC.e
8888
9876
  const key=sv
8889
- let arm=${bk}.get(key)
8890
- ${fold}${chain}
9877
+ ${armSelection}
8891
9878
  if(arm===undefined){
8892
9879
  ${other === void 0 ? `ctx._fe=selEnd;ctx._fx=${dx};return FAIL` : ""}
8893
9880
  }
8894
- ${emitMark(m2, L.buf, sinks)}
9881
+ ${emitMark(m2, L.buf, L.raw, sinks)}
8895
9882
  let v
8896
9883
  switch(arm){
8897
9884
  ${armCases}
8898
9885
  ${fallbackCase}
8899
9886
  }
8900
9887
  if(v===FAIL){
8901
- ${emitRollback(m2, L.buf, sinks)}
9888
+ ${emitRollback(m2, L.buf, L.raw, sinks)}
8902
9889
  ctx._fc=true
8903
9890
  return FAIL
8904
9891
  }
@@ -8934,23 +9921,25 @@ return [key,v]
8934
9921
  const skip = skipFor(L);
8935
9922
  const knownTrivia = L.tri === TRI_NONE ? false : L.tri !== TRI_UNKNOWN ? true : void 0;
8936
9923
  const hasTrivia = knownTrivia === void 0 ? "hasTrivia" : String(knownTrivia);
8937
- const pfd = sinks.fd ? `${p}fd` : "0";
9924
+ const pfd = sinks.fd ? `${p}fd` : "undefined";
8938
9925
  const per = sinks.er ? `${p}er` : "undefined";
8939
- const rb = L.buf ? `_rbBuf(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
9926
+ const rbHelper = L.raw === RAW_OMIT ? "_rbNoRawBuf" : "_rbBuf";
9927
+ const rb = L.buf && L.raw !== 0 ? `${rbHelper}(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
8940
9928
  if(ctx._fields!==undefined&&ctx._fields.length!==${p}fd)ctx._fields.length=${p}fd` : ""}${sinks.er ? `
8941
- if(ctx._errors!==undefined&&ctx._errors.length!==${p}er)ctx._errors.length=${p}er` : ""}` : `if(needMark)rollbackTriviaAt(ctx,${p}raw,${p}tl,${p}lv,${pfd},${per},${p}lg,${p}rt)`;
9929
+ if(ctx._errors!==undefined&&ctx._errors.length!==${p}er)ctx._errors.length=${p}er` : ""}` : L.buf ? `rollbackTriviaAt(ctx,${p}raw,${p}tl,${p}lv,${pfd},${per},${p}lg,${p}rt)` : `if(needMark)rollbackTriviaAt(ctx,${p}raw,${p}tl,${p}lv,${pfd},${per},${p}lg,${p}rt)`;
8942
9930
  const markSinks = `${sinks.fd ? `
8943
9931
  ${p}fd=ctx._fields!==undefined?ctx._fields.length:0` : ""}${sinks.er ? `
8944
9932
  ${p}er=ctx._errors!==undefined?ctx._errors.length:0` : ""}`;
9933
+ const markRaw = L.raw === RAW_OMIT ? `${p}raw=b.rawLen` : L.raw === RAW_CAPTURE ? `const r=b.raw;${p}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0` : `const r=b.raw;${p}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)`;
8945
9934
  const markBody = L.buf ? `const b=ctx._cstBuf
8946
- const r=b.raw;${p}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
9935
+ ${markRaw}
8947
9936
  const h=b.ch;${p}lv=h!==undefined?h.length:b.single!==undefined?1:0
8948
9937
  const l=b.tl;${p}tl=l!==undefined?l.length:0
8949
9938
  ${p}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
8950
9939
  ${p}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${markSinks}` : `if(needMark){
8951
9940
  const b=ctx._cstBuf
8952
9941
  if(b!==undefined){
8953
- const r=b.raw;${p}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
9942
+ const r=b.raw;${p}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)
8954
9943
  const h=b.ch;${p}lv=h!==undefined?h.length:b.single!==undefined?1:0
8955
9944
  const l=b.tl;${p}tl=l!==undefined?l.length:0
8956
9945
  }else{
@@ -9057,7 +10046,7 @@ const leaf={_tag:'leaf',value,span:{start:pos,end}}
9057
10046
  const kids=[leaf],rawKids=[leaf],span={start:pos,end}
9058
10047
  EC.e=end
9059
10048
  const nd=${build2}(kids,undefined,span,rawKids,EMPTY_TL,undefined)
9060
- ${L.buf ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : "if(ctx._cstBuf!==undefined||ctx._cstChildren!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
10049
+ ${L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : staticBuild ? "if(ctx._cstBuf!==undefined||ctx._cstChildren!==undefined)pushCstChild(ctx,nd,ctx._cstBuf!==undefined&&ctx._cstBuf.noRaw===true?undefined:ctx._cstBuf!==undefined||ctx._cstRawChildren!==undefined?rawEntry(nd,input,pos,end):undefined)" : "if(ctx._cstBuf!==undefined||ctx._cstChildren!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
9061
10050
  EC.e=end
9062
10051
  return nd
9063
10052
  }`;
@@ -9079,7 +10068,22 @@ return nd
9079
10068
  if (!hostCst && !tracked && build !== void 0 && proj < 0 && (flags === 2 || flags === 18 || flags === 34)) {
9080
10069
  const fields = flags === 18;
9081
10070
  const collapseChildren = flags === 34;
9082
- const publish = `if(sBuf!==undefined){
10071
+ const publish = L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? `if(sBuf!==undefined){
10072
+ if(sBuf.rawOnly!==true){
10073
+ if(sBuf.ch!==undefined)sBuf.ch.push(nd)
10074
+ else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
10075
+ else sBuf.single=nd
10076
+ }
10077
+ const rawNd=rawEntry(nd,input,pos,end)
10078
+ if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
10079
+ else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
10080
+ else sBuf.rawSingle=rawNd
10081
+ }else if(sCh!==undefined){
10082
+ sCh.push(nd)
10083
+ if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
10084
+ }` : `if(sBuf!==undefined){
10085
+ if(sBuf.noRaw===true)_pushNodeNoRawBuf(ctx,nd)
10086
+ else{
9083
10087
  if(sBuf.rawOnly!==true){
9084
10088
  if(sBuf.ch!==undefined)sBuf.ch.push(nd)
9085
10089
  else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
@@ -9089,6 +10093,7 @@ const rawNd=rawEntry(nd,input,pos,end)
9089
10093
  if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
9090
10094
  else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
9091
10095
  else sBuf.rawSingle=rawNd
10096
+ }
9092
10097
  }else if(sCh!==undefined){
9093
10098
  sCh.push(nd)
9094
10099
  if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
@@ -9127,6 +10132,7 @@ return nd
9127
10132
  const wantFields = hasFields || hostCst;
9128
10133
  const captureWide = readsTrivia || hostCst ? !structural || grammarCapture || hostCapturesThisType !== false : hostCapturesThisType === true;
9129
10134
  const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
10135
+ const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
9130
10136
  const ty = q(type);
9131
10137
  const stArg = readsState ? "st" : "(ctx.state!==undefined?Object.assign({},ctx.state):undefined)";
9132
10138
  const hostCall = `_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,${stArg},${tags})`;
@@ -9140,7 +10146,12 @@ return nd
9140
10146
  value = `nd=_pfHost!==undefined?_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,st,${tags}):{_tag:'node',type:${ty},span,state:st??null,children:kids}`;
9141
10147
  }
9142
10148
  const collapsible = keepChildren && (hostCst || build === void 0 && proj < 0);
9143
- const openCapture = keepChildren ? `const buf={}
10149
+ const openCapture = omitsRaw ? `const buf={noRaw:true,rawLen:0}
10150
+ ctx._cstBuf=buf
10151
+ ctx._cstChildren=undefined
10152
+ ctx._cstLeaves=undefined
10153
+ ctx._cstRawChildren=undefined
10154
+ ctx._cstTriviaLog=undefined` : keepChildren ? `const buf={}
9144
10155
  ctx._cstBuf=buf
9145
10156
  ctx._cstChildren=undefined
9146
10157
  ctx._cstLeaves=undefined
@@ -9151,7 +10162,10 @@ ctx._cstChildren=undefined
9151
10162
  ctx._cstLeaves=undefined
9152
10163
  ctx._cstRawChildren=undefined
9153
10164
  ctx._cstTriviaLog=undefined`;
9154
- const finishCapture = keepChildren ? `const kids=buf.ch??(buf.single!==undefined?[buf.single]:EMPTY_CH)
10165
+ const finishCapture = omitsRaw ? `const kids=buf.ch??(buf.single!==undefined?[buf.single]:EMPTY_CH)
10166
+ const hostKids=kids
10167
+ const rawKids=EMPTY_CH
10168
+ const tlog=buf.tl??EMPTY_TLOG` : keepChildren ? `const kids=buf.ch??(buf.single!==undefined?[buf.single]:EMPTY_CH)
9155
10169
  const hostKids=kids
9156
10170
  const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
9157
10171
  const tlog=buf.tl??EMPTY_TLOG` : `const kids=EMPTY_CH
@@ -9185,7 +10199,7 @@ const st=${readsState ? "(ctx.state!==undefined?Object.assign({},ctx.state):unde
9185
10199
  let nd
9186
10200
  ${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]
9187
10201
  else ` : ""}{${value}}
9188
- ${L.buf ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : "if(sBuf!==undefined||sCh!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
10202
+ ${L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : staticBuild ? "if(sBuf!==undefined||sCh!==undefined)pushCstChild(ctx,nd,sBuf!==undefined?(sBuf.noRaw===true?undefined:rawEntry(nd,input,pos,end)):sRaw!==undefined?rawEntry(nd,input,pos,end):undefined)" : "if(sBuf!==undefined||sCh!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
9189
10203
  EC.e=end
9190
10204
  return nd
9191
10205
  }`;
@@ -9203,7 +10217,7 @@ return nd
9203
10217
  }
9204
10218
  const extra = [];
9205
10219
  for (const ip of extraIps) extra.push(`${ip}:${link(ip)}`);
9206
- const source = `${RUNTIME_PRELUDE}
10220
+ const source = `${RUNTIME_PRELUDE}${needsNoRawPrelude ? NO_RAW_RUNTIME_PRELUDE : ""}
9207
10221
  ${prelude.join("\n")}
9208
10222
  ${skipDefs.join("\n")}
9209
10223
  ${choiceDefs.join("\n")}
@@ -9218,7 +10232,13 @@ _pfHost=host
9218
10232
  function _finish(){
9219
10233
  if(_pfDepth<=0)throw new Error('parseman emitted table assembly frame underflow')
9220
10234
  _pfDepth--
9221
- if(_pfDepth===0)return
10235
+ if(_pfDepth===0){
10236
+ _pfTokInput=undefined
10237
+ _pfTokBody=-1
10238
+ _pfTokValue=undefined
10239
+ _pfTokDispatch=-1
10240
+ return
10241
+ }
9222
10242
  const prior=_pfFrames.pop()
9223
10243
  _pfScan=prior[0]
9224
10244
  _pfHost=prior[1]
@@ -9985,6 +11005,17 @@ function assemble(t2, prog, cfg) {
9985
11005
  }
9986
11006
  return recognize;
9987
11007
  }
11008
+ const labelExtraIps = [];
11009
+ for (const s of prog.scans ?? []) {
11010
+ for (const r of s.skip) labelExtraIps.push(r[0]);
11011
+ if (s.sentinel !== void 0) labelExtraIps.push(s.sentinel[0]);
11012
+ }
11013
+ for (const set of prog.scanSkip ?? []) for (const r of set) labelExtraIps.push(r[0]);
11014
+ const closureLabels = computeSiteLabels(
11015
+ code,
11016
+ [...Object.values(prog.rules), ...labelExtraIps],
11017
+ hostCst
11018
+ );
9988
11019
  let SCAN = null;
9989
11020
  const memo = /* @__PURE__ */ new Map();
9990
11021
  const reached = /* @__PURE__ */ new Set();
@@ -10230,7 +11261,7 @@ function assemble(t2, prog, cfg) {
10230
11261
  const b = ctx._cstBuf;
10231
11262
  if (b !== void 0) {
10232
11263
  const raw = b.raw;
10233
- MRAW = raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
11264
+ MRAW = b.noRaw === true ? b.rawLen ?? 0 : raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
10234
11265
  const ch2 = b.ch;
10235
11266
  MLV = ch2 !== void 0 ? ch2.length : b.single !== void 0 ? 1 : 0;
10236
11267
  const tl = b.tl;
@@ -10314,6 +11345,31 @@ function assemble(t2, prog, cfg) {
10314
11345
  if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
10315
11346
  return cur;
10316
11347
  }
11348
+ function nextTermBuffered(child, input, cur, ctx) {
11349
+ if (ctx.trivia === void 0) {
11350
+ const v2 = child(input, cur, ctx);
11351
+ if (v2 === FAIL) return -1;
11352
+ TERMV = v2;
11353
+ return EC.e;
11354
+ }
11355
+ const before = ctx._cstBuf;
11356
+ const beforeTl = before.tl;
11357
+ const mTl = beforeTl === void 0 ? 0 : beforeTl.length;
11358
+ const mLog = ctx._triviaLog?.length ?? 0;
11359
+ const mRoot = ctx._rootTriviaLog?.length ?? 0;
11360
+ const scanEnd = skipTrivia(input, cur, ctx);
11361
+ const scanned = ctx._cstBuf;
11362
+ const scannedTl = scanned.tl;
11363
+ const scanTl = scannedTl === void 0 ? 0 : scannedTl.length;
11364
+ const scanLog = ctx._triviaLog?.length ?? 0;
11365
+ const scanRoot = ctx._rootTriviaLog?.length ?? 0;
11366
+ const v = child(input, scanEnd, ctx);
11367
+ if (v === FAIL) return -1;
11368
+ TERMV = v;
11369
+ if (EC.e > scanEnd) return EC.e;
11370
+ rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
11371
+ return cur;
11372
+ }
10317
11373
  function committed3(c) {
10318
11374
  return c._fc === true;
10319
11375
  }
@@ -10584,7 +11640,8 @@ function assemble(t2, prog, cfg) {
10584
11640
  target = p;
10585
11641
  } };
10586
11642
  inFlight.set(ip, holder);
10587
- const piece = lower(ip);
11643
+ const op = code[ip];
11644
+ 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);
10588
11645
  inFlight.delete(ip);
10589
11646
  holder.set(piece);
10590
11647
  memo.set(ip, piece);
@@ -11327,6 +12384,7 @@ function assemble(t2, prog, cfg) {
11327
12384
  const reducer = fused ? code[ip + 1] : -1;
11328
12385
  const projection = reducer < 0 ? ~reducer : -1;
11329
12386
  const fn = fused && projection < 0 ? fns[reducer] : void 0;
12387
+ const step = closureLabels.at(ip).buf ? nextTermBuffered : nextTerm;
11330
12388
  const runnerBlock = (count, r0, r1, r2, r3, next) => {
11331
12389
  if (count === 1) return (input, cur, ctx, values, inherited) => {
11332
12390
  cur = r0(input, cur, ctx, inherited);
@@ -11381,7 +12439,7 @@ function assemble(t2, prog, cfg) {
11381
12439
  const kid = link(kidIp);
11382
12440
  return (input, cur, ctx, inherited) => {
11383
12441
  ctx._sync = sync ?? inherited;
11384
- return nextTerm(kid, input, cur, ctx);
12442
+ return step(kid, input, cur, ctx);
11385
12443
  };
11386
12444
  }
11387
12445
  const negated = code[kidIp + 1] === 1;
@@ -11466,7 +12524,7 @@ function assemble(t2, prog, cfg) {
11466
12524
  const kidIp = code[base + i];
11467
12525
  if (code[kidIp] !== OP_ADJ) {
11468
12526
  const kid = link(kidIp);
11469
- return (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
12527
+ return (input, cur, ctx) => step(kid, input, cur, ctx);
11470
12528
  }
11471
12529
  const negated = code[kidIp + 1] === 1;
11472
12530
  const ki = code[kidIp + 2];
@@ -11555,7 +12613,7 @@ function assemble(t2, prog, cfg) {
11555
12613
  return (input, pos, ctx) => {
11556
12614
  const v0 = k0(input, pos, ctx);
11557
12615
  if (v0 === FAIL) return FAIL;
11558
- const cur = nextTerm(k1, input, EC.e, ctx);
12616
+ const cur = step(k1, input, EC.e, ctx);
11559
12617
  if (cur < 0) return FAIL;
11560
12618
  EC.e = cur;
11561
12619
  return projection === 0 ? v0 : projection === 1 ? TERMV : fn([v0, TERMV], { start: pos, end: cur });
@@ -11565,7 +12623,7 @@ function assemble(t2, prog, cfg) {
11565
12623
  return (input, pos, ctx) => {
11566
12624
  const v0 = k0(input, pos, ctx);
11567
12625
  if (v0 === FAIL) return FAIL;
11568
- const cur = nextTerm(k1, input, EC.e, ctx);
12626
+ const cur = step(k1, input, EC.e, ctx);
11569
12627
  if (cur < 0) return FAIL;
11570
12628
  EC.e = cur;
11571
12629
  return [v0, TERMV];
@@ -11574,7 +12632,7 @@ function assemble(t2, prog, cfg) {
11574
12632
  return (input, pos, ctx) => {
11575
12633
  const v0 = k0(input, pos, ctx);
11576
12634
  if (v0 === FAIL) return FAIL;
11577
- const cur = nextTerm(k1, input, EC.e, ctx);
12635
+ const cur = step(k1, input, EC.e, ctx);
11578
12636
  if (cur < 0) return FAIL;
11579
12637
  EC.e = cur;
11580
12638
  return void 0;
@@ -11586,10 +12644,10 @@ function assemble(t2, prog, cfg) {
11586
12644
  return (input, pos, ctx) => {
11587
12645
  const v0 = k0(input, pos, ctx);
11588
12646
  if (v0 === FAIL) return FAIL;
11589
- let cur = nextTerm(k1, input, EC.e, ctx);
12647
+ let cur = step(k1, input, EC.e, ctx);
11590
12648
  if (cur < 0) return FAIL;
11591
12649
  const v1 = TERMV;
11592
- cur = nextTerm(k2, input, cur, ctx);
12650
+ cur = step(k2, input, cur, ctx);
11593
12651
  if (cur < 0) return FAIL;
11594
12652
  EC.e = cur;
11595
12653
  return projection === 0 ? v0 : projection === 1 ? v1 : projection === 2 ? TERMV : fn([v0, v1, TERMV], { start: pos, end: cur });
@@ -11599,10 +12657,10 @@ function assemble(t2, prog, cfg) {
11599
12657
  return (input, pos, ctx) => {
11600
12658
  const v0 = k0(input, pos, ctx);
11601
12659
  if (v0 === FAIL) return FAIL;
11602
- let cur = nextTerm(k1, input, EC.e, ctx);
12660
+ let cur = step(k1, input, EC.e, ctx);
11603
12661
  if (cur < 0) return FAIL;
11604
12662
  const v1 = TERMV;
11605
- cur = nextTerm(k2, input, cur, ctx);
12663
+ cur = step(k2, input, cur, ctx);
11606
12664
  if (cur < 0) return FAIL;
11607
12665
  EC.e = cur;
11608
12666
  return [v0, v1, TERMV];
@@ -11611,9 +12669,9 @@ function assemble(t2, prog, cfg) {
11611
12669
  return (input, pos, ctx) => {
11612
12670
  const v0 = k0(input, pos, ctx);
11613
12671
  if (v0 === FAIL) return FAIL;
11614
- let cur = nextTerm(k1, input, EC.e, ctx);
12672
+ let cur = step(k1, input, EC.e, ctx);
11615
12673
  if (cur < 0) return FAIL;
11616
- cur = nextTerm(k2, input, cur, ctx);
12674
+ cur = step(k2, input, cur, ctx);
11617
12675
  if (cur < 0) return FAIL;
11618
12676
  EC.e = cur;
11619
12677
  return void 0;
@@ -11621,43 +12679,43 @@ function assemble(t2, prog, cfg) {
11621
12679
  }
11622
12680
  const block = (count, k0, k1, k2, k3, next) => {
11623
12681
  if (count === 1) return (input, cur, ctx, values) => {
11624
- cur = nextTerm(k0, input, cur, ctx);
12682
+ cur = step(k0, input, cur, ctx);
11625
12683
  if (cur < 0) return -1;
11626
12684
  if (values !== void 0) values.push(TERMV);
11627
12685
  return next === void 0 ? cur : next(input, cur, ctx, values);
11628
12686
  };
11629
12687
  if (count === 2) return (input, cur, ctx, values) => {
11630
- cur = nextTerm(k0, input, cur, ctx);
12688
+ cur = step(k0, input, cur, ctx);
11631
12689
  if (cur < 0) return -1;
11632
12690
  if (values !== void 0) values.push(TERMV);
11633
- cur = nextTerm(k1, input, cur, ctx);
12691
+ cur = step(k1, input, cur, ctx);
11634
12692
  if (cur < 0) return -1;
11635
12693
  if (values !== void 0) values.push(TERMV);
11636
12694
  return next === void 0 ? cur : next(input, cur, ctx, values);
11637
12695
  };
11638
12696
  if (count === 3) return (input, cur, ctx, values) => {
11639
- cur = nextTerm(k0, input, cur, ctx);
12697
+ cur = step(k0, input, cur, ctx);
11640
12698
  if (cur < 0) return -1;
11641
12699
  if (values !== void 0) values.push(TERMV);
11642
- cur = nextTerm(k1, input, cur, ctx);
12700
+ cur = step(k1, input, cur, ctx);
11643
12701
  if (cur < 0) return -1;
11644
12702
  if (values !== void 0) values.push(TERMV);
11645
- cur = nextTerm(k2, input, cur, ctx);
12703
+ cur = step(k2, input, cur, ctx);
11646
12704
  if (cur < 0) return -1;
11647
12705
  if (values !== void 0) values.push(TERMV);
11648
12706
  return next === void 0 ? cur : next(input, cur, ctx, values);
11649
12707
  };
11650
12708
  return (input, cur, ctx, values) => {
11651
- cur = nextTerm(k0, input, cur, ctx);
12709
+ cur = step(k0, input, cur, ctx);
11652
12710
  if (cur < 0) return -1;
11653
12711
  if (values !== void 0) values.push(TERMV);
11654
- cur = nextTerm(k1, input, cur, ctx);
12712
+ cur = step(k1, input, cur, ctx);
11655
12713
  if (cur < 0) return -1;
11656
12714
  if (values !== void 0) values.push(TERMV);
11657
- cur = nextTerm(k2, input, cur, ctx);
12715
+ cur = step(k2, input, cur, ctx);
11658
12716
  if (cur < 0) return -1;
11659
12717
  if (values !== void 0) values.push(TERMV);
11660
- cur = nextTerm(k3, input, cur, ctx);
12718
+ cur = step(k3, input, cur, ctx);
11661
12719
  if (cur < 0) return -1;
11662
12720
  if (values !== void 0) values.push(TERMV);
11663
12721
  return next === void 0 ? cur : next(input, cur, ctx, values);
@@ -11828,6 +12886,13 @@ function assemble(t2, prog, cfg) {
11828
12886
  if (n === 2 || n === 3) {
11829
12887
  const a0 = link(code[base]), a1 = link(code[base + 1]);
11830
12888
  const a2 = n === 3 ? link(code[base + 2]) : void 0;
12889
+ const predecide = !hostCst && !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
12890
+ const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
12891
+ const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
12892
+ const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
12893
+ const p0 = p0ip < 0 ? void 0 : scalarFor(p0ip);
12894
+ const p1 = p1ip < 0 ? void 0 : scalarFor(p1ip);
12895
+ const p2 = p2ip < 0 ? void 0 : scalarFor(p2ip);
11831
12896
  const e0 = fx[code[base + n]];
11832
12897
  const e1 = fx[code[base + n + 1]];
11833
12898
  const e2 = n === 3 ? fx[code[base + n + 2]] : void 0;
@@ -11857,7 +12922,10 @@ function assemble(t2, prog, cfg) {
11857
12922
  let acc;
11858
12923
  let best = pos;
11859
12924
  if (c < 128) {
11860
- const bits = mask[c < 0 ? 128 : c];
12925
+ let bits = mask[c < 0 ? 128 : c];
12926
+ if ((bits & 1) !== 0 && p0 !== void 0 && p0(input, pos) < 0) bits &= ~1;
12927
+ if ((bits & 2) !== 0 && p1 !== void 0 && p1(input, pos) < 0) bits &= ~2;
12928
+ if ((bits & 4) !== 0 && p2 !== void 0 && p2(input, pos) < 0) bits &= ~4;
11861
12929
  let prev = 0;
11862
12930
  if ((bits & 1) !== 0) {
11863
12931
  ctx._fc = false;
@@ -11920,7 +12988,7 @@ function assemble(t2, prog, cfg) {
11920
12988
  ctx._fx = acc ?? choiceFx;
11921
12989
  return FAIL;
11922
12990
  }
11923
- if (g0 === null || classHas2(g0, c)) {
12991
+ if ((g0 === null || classHas2(g0, c)) && (p0 === void 0 || p0(input, pos) >= 0)) {
11924
12992
  ctx._fc = false;
11925
12993
  const v = a0(input, pos, ctx);
11926
12994
  if (v !== FAIL) return v;
@@ -11936,7 +13004,7 @@ function assemble(t2, prog, cfg) {
11936
13004
  }
11937
13005
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11938
13006
  } else if (best === pos) acc = accSet(e0, acc);
11939
- if (g1 === null || classHas2(g1, c)) {
13007
+ if ((g1 === null || classHas2(g1, c)) && (p1 === void 0 || p1(input, pos) >= 0)) {
11940
13008
  ctx._fc = false;
11941
13009
  const v = a1(input, pos, ctx);
11942
13010
  if (v !== FAIL) return v;
@@ -11953,7 +13021,7 @@ function assemble(t2, prog, cfg) {
11953
13021
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11954
13022
  } else if (best === pos) acc = accSet(e1, acc);
11955
13023
  if (n === 3) {
11956
- if (g2 === null || classHas2(g2, c)) {
13024
+ if ((g2 === null || classHas2(g2, c)) && (p2 === void 0 || p2(input, pos) >= 0)) {
11957
13025
  ctx._fc = false;
11958
13026
  const v = a2(input, pos, ctx);
11959
13027
  if (v !== FAIL) return v;
@@ -12526,20 +13594,14 @@ function assemble(t2, prog, cfg) {
12526
13594
  const captureWide = readsTrivia || hostCst ? !structural || grammarCapture || hostCapturesThisType !== false : hostCapturesThisType === true;
12527
13595
  const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
12528
13596
  const rawOnly = !keepChildren;
13597
+ const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
12529
13598
  return (input, pos, ctx) => {
12530
13599
  const host = HOST;
12531
13600
  const sCh = ctx._cstChildren;
12532
- const sLv = ctx._cstLeaves;
12533
- const sRaw = ctx._cstRawChildren;
12534
- const sTl = ctx._cstTriviaLog;
12535
13601
  const sCap = ctx.captureTrivia;
12536
13602
  const sBuf = ctx._cstBuf;
12537
- const buf = rawOnly ? { rawOnly: true } : {};
13603
+ const buf = rawOnly ? { rawOnly: true } : omitsRaw ? { noRaw: true, rawLen: 0 } : {};
12538
13604
  ctx._cstBuf = buf;
12539
- ctx._cstChildren = void 0;
12540
- ctx._cstLeaves = void 0;
12541
- ctx._cstRawChildren = void 0;
12542
- ctx._cstTriviaLog = void 0;
12543
13605
  ctx.captureTrivia = captureWide;
12544
13606
  const savedFields = ctx._fields;
12545
13607
  ctx._fields = wantFields ? [] : void 0;
@@ -12554,13 +13616,9 @@ function assemble(t2, prog, cfg) {
12554
13616
  if (structural) ctx._triviaCaptureMask = savedMask;
12555
13617
  const kids = rawOnly ? EMPTY_CH : buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
12556
13618
  const hostKids = kids;
12557
- const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
13619
+ const rawKids = omitsRaw ? EMPTY_CH : buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
12558
13620
  const tlog = buf.tl ?? EMPTY_TLOG;
12559
13621
  ctx._cstBuf = sBuf;
12560
- ctx._cstChildren = sCh;
12561
- ctx._cstLeaves = sLv;
12562
- ctx._cstRawChildren = sRaw;
12563
- ctx._cstTriviaLog = sTl;
12564
13622
  ctx.captureTrivia = sCap;
12565
13623
  if (v === FAIL) return FAIL;
12566
13624
  const end = EC.e;
@@ -12651,6 +13709,34 @@ function assemble(t2, prog, cfg) {
12651
13709
  rawScalarSpecs.add(code[child + 1]);
12652
13710
  scalarFor(child);
12653
13711
  }
13712
+ } else if (code[ip] === OP_CHOICE && !disp[code[ip + 1]].exclusive) {
13713
+ const n = code[ip + 2];
13714
+ for (let i = 0; i < n; i++) {
13715
+ const armIp = code[ip + 4 + i];
13716
+ const child = leadingScalarTerminal(code, armIp, 2, true, true);
13717
+ if (n === 2 || n === 3) {
13718
+ if (child >= 0) scalarFor(child);
13719
+ continue;
13720
+ }
13721
+ if (child >= 0) {
13722
+ const spec = k[code[child + 1]];
13723
+ if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
13724
+ scalarFor(child);
13725
+ continue;
13726
+ }
13727
+ }
13728
+ const family = leadingLiteralFamily(code, k, armIp);
13729
+ if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
13730
+ const value = k[code[terminal + 1]];
13731
+ return typeof value === "string" && value.length >= 2;
13732
+ })) {
13733
+ for (const terminal of family) scalarFor(terminal);
13734
+ }
13735
+ const sequence6 = leadingScalarSequence(code, armIp);
13736
+ if (sequence6 !== void 0 && (sequence6.trivia < 0 || triviaScan[sequence6.trivia] != null)) {
13737
+ for (const terminal of sequence6.terminals) scalarFor(terminal);
13738
+ }
13739
+ }
12654
13740
  }
12655
13741
  }
12656
13742
  const notChild = scalarTerminalNotChild(code, ip);
@@ -13061,7 +14147,7 @@ function emitAssemblies(prog, cfgs) {
13061
14147
  seen.add(key);
13062
14148
  let em;
13063
14149
  try {
13064
- em = emitAssemblySource(t2, prog, cfg, extraIps);
14150
+ em = emitAssemblySource(t2, prog, cfg, extraIps, true);
13065
14151
  } catch (e) {
13066
14152
  if (e instanceof Unemittable) continue;
13067
14153
  throw e;
@@ -14594,7 +15680,7 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
14594
15680
  };
14595
15681
  const { prog, fnSrcs } = encodeTableProgram({ [ENTRY]: combinator }, settings);
14596
15682
  const artifact = closureArtifact(prog);
14597
- const entry = tableRules(artifact)[ENTRY];
15683
+ const entry = tableRules(prog)[ENTRY];
14598
15684
  const offered = opts.fnSources ?? mapFnSources;
14599
15685
  const supplied = offered !== void 0 && offered.length === fnSrcs.length ? offered : void 0;
14600
15686
  const sources = fnSrcs.map((s, i) => s ?? supplied?.[i] ?? ownSource(prog.fns[i]));
@@ -15116,6 +16202,7 @@ function rebuildCombinator(root, replacements) {
15116
16202
  return p;
15117
16203
  }
15118
16204
  out = d.type === void 0 ? d.build === void 0 ? node(one(d.parser), opts) : node(one(d.parser), d.build) : node(d.type, one(d.parser), d.build, opts);
16205
+ if (d.buildRawUnused === true && out._def.tag === "node") out._def.buildRawUnused = true;
15119
16206
  break;
15120
16207
  }
15121
16208
  case "grammar": {