parseman 0.57.0 → 0.58.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 (69) hide show
  1. package/dist/analysis/diagnostics.js +1800 -962
  2. package/dist/analysis/diagnostics.js.map +3 -3
  3. package/dist/cli/index.js +1929 -1091
  4. package/dist/cli/index.js.map +3 -3
  5. package/dist/combinators/dispatch.d.ts.map +1 -1
  6. package/dist/compiler/token-alphabet.d.ts +11 -1
  7. package/dist/compiler/token-alphabet.d.ts.map +1 -1
  8. package/dist/compiler/token-capability.js +69 -16
  9. package/dist/compiler/token-capability.js.map +2 -2
  10. package/dist/cst/capture-buffer.d.ts +6 -0
  11. package/dist/cst/capture-buffer.d.ts.map +1 -1
  12. package/dist/index.js +1017 -177
  13. package/dist/index.js.map +3 -3
  14. package/dist/plugin/index.d.ts +25 -1
  15. package/dist/plugin/index.d.ts.map +1 -1
  16. package/dist/plugin/index.js +1210 -236
  17. package/dist/plugin/index.js.map +3 -3
  18. package/dist/run/index.d.ts +2 -0
  19. package/dist/run/index.d.ts.map +1 -1
  20. package/dist/run/index.js +9 -0
  21. package/dist/run/index.js.map +1 -1
  22. package/dist/table/assemble.d.ts.map +1 -1
  23. package/dist/table/compile-rule-map.d.ts.map +1 -1
  24. package/dist/table/emit-assembly.d.ts +1 -1
  25. package/dist/table/emit-assembly.d.ts.map +1 -1
  26. package/dist/table/emit.d.ts.map +1 -1
  27. package/dist/table/encode.d.ts.map +1 -1
  28. package/dist/table/exec.d.ts.map +1 -1
  29. package/dist/table/factor-choice.d.ts +42 -0
  30. package/dist/table/factor-choice.d.ts.map +1 -0
  31. package/dist/table/fail-clean.d.ts +3 -0
  32. package/dist/table/fail-clean.d.ts.map +1 -0
  33. package/dist/table/hold-gap.d.ts +8 -0
  34. package/dist/table/hold-gap.d.ts.map +1 -0
  35. package/dist/table/index.js +1370 -259
  36. package/dist/table/index.js.map +3 -3
  37. package/dist/table/lex-program.d.ts +7 -3
  38. package/dist/table/lex-program.d.ts.map +1 -1
  39. package/dist/table/ops.d.ts +8 -0
  40. package/dist/table/ops.d.ts.map +1 -1
  41. package/dist/table/run-support.d.ts +19 -0
  42. package/dist/table/run-support.d.ts.map +1 -1
  43. package/dist/table/scalar-terminal.d.ts +2 -0
  44. package/dist/table/scalar-terminal.d.ts.map +1 -1
  45. package/dist/table/site-labels.d.ts +66 -0
  46. package/dist/table/site-labels.d.ts.map +1 -1
  47. package/dist/version.d.ts +1 -1
  48. package/package.json +1 -1
  49. package/src/combinators/dispatch.ts +12 -3
  50. package/src/compiler/token-alphabet.ts +57 -17
  51. package/src/cst/capture-buffer.ts +25 -0
  52. package/src/plugin/index.ts +230 -35
  53. package/src/run/index.ts +5 -0
  54. package/src/table/assemble.ts +252 -62
  55. package/src/table/child-slots.ts +2 -2
  56. package/src/table/compile-rule-map.ts +14 -5
  57. package/src/table/emit-assembly.ts +112 -23
  58. package/src/table/emit.ts +3 -1
  59. package/src/table/encode.ts +83 -14
  60. package/src/table/exec.ts +27 -8
  61. package/src/table/factor-choice.ts +173 -0
  62. package/src/table/fail-clean.ts +130 -0
  63. package/src/table/hold-gap.ts +68 -0
  64. package/src/table/lex-program.ts +197 -43
  65. package/src/table/ops.ts +9 -1
  66. package/src/table/run-support.ts +35 -0
  67. package/src/table/scalar-terminal.ts +8 -0
  68. package/src/table/site-labels.ts +135 -4
  69. package/src/version.ts +1 -1
@@ -349,6 +349,9 @@ function createDetachedParseContext(trackLines, state) {
349
349
  }
350
350
 
351
351
  // src/line-index.ts
352
+ function createLineIndex() {
353
+ return { lineStarts: [0] };
354
+ }
352
355
  function recordLineRange(index, input, start, end) {
353
356
  const lineStarts = index.lineStarts;
354
357
  for (let i = start; i < end; i++) {
@@ -364,6 +367,18 @@ function recordLineRangeFromContext(ctx, input, _startHint, end) {
364
367
  recordLineRange(index, input, from, end);
365
368
  ctx._lineScannedTo = end;
366
369
  }
370
+ function normalizeLineIndex(index) {
371
+ const starts = index.lineStarts;
372
+ starts.sort((a, b) => a - b);
373
+ let write = 0;
374
+ for (let read = 0; read < starts.length; read++) {
375
+ const value = starts[read];
376
+ if (write === 0 || starts[write - 1] !== value) starts[write++] = value;
377
+ }
378
+ starts.length = write;
379
+ if (starts.length === 0 || starts[0] !== 0) starts.unshift(0);
380
+ return index;
381
+ }
367
382
  function offsetToLineCol(index, offset) {
368
383
  const { lineStarts } = index;
369
384
  let lo = 0;
@@ -593,12 +608,12 @@ function rebuildLineScan(s, subtree) {
593
608
  function cstCaptureActive(ctx) {
594
609
  return ctx._cstBuf !== void 0 || ctx._cstLeaves !== void 0;
595
610
  }
596
- function pushCstLeaf(ctx, leaf) {
611
+ function pushCstLeaf(ctx, leaf2) {
597
612
  if (!ctx.trackLines) {
598
- pushCstChild(ctx, leaf, leaf);
613
+ pushCstChild(ctx, leaf2, leaf2);
599
614
  return;
600
615
  }
601
- const annotated = leaf && typeof leaf === "object" && leaf.span ? { ...leaf, span: annotateSpanFromLineContext(leaf.span, ctx) } : leaf;
616
+ const annotated = leaf2 && typeof leaf2 === "object" && leaf2.span ? { ...leaf2, span: annotateSpanFromLineContext(leaf2.span, ctx) } : leaf2;
602
617
  pushCstChild(ctx, annotated, annotated);
603
618
  }
604
619
  function pushCstChild(ctx, built, rawEntry2) {
@@ -623,6 +638,31 @@ function pushCstChild(ctx, built, rawEntry2) {
623
638
  else if (ctx._cstLeaves) ctx._cstLeaves.push(built);
624
639
  if (ctx._cstRawChildren) ctx._cstRawChildren.push(rawEntry2);
625
640
  }
641
+ function popCstChild(ctx) {
642
+ const b = ctx._cstBuf;
643
+ if (b) {
644
+ const ch2 = b.ch;
645
+ if (b.rawOnly !== true && ch2) {
646
+ ch2.pop();
647
+ if (ch2.length === 1) {
648
+ b.single = ch2[0];
649
+ b.ch = void 0;
650
+ }
651
+ }
652
+ if (b.noRaw === true) b.rawLen = (b.rawLen ?? 1) - 1;
653
+ else if (b.raw) {
654
+ b.raw.pop();
655
+ if (b.raw.length === 1) {
656
+ b.rawSingle = b.raw[0];
657
+ b.raw = void 0;
658
+ }
659
+ } else b.rawSingle = void 0;
660
+ return;
661
+ }
662
+ if (ctx._cstChildren) ctx._cstChildren.pop();
663
+ else if (ctx._cstLeaves) ctx._cstLeaves.pop();
664
+ if (ctx._cstRawChildren) ctx._cstRawChildren.pop();
665
+ }
626
666
  function cstRawLen(ctx) {
627
667
  const b = ctx._cstBuf;
628
668
  if (b) {
@@ -1468,6 +1508,15 @@ function triviaKindMaskAt(input, pos, spec, state) {
1468
1508
  }
1469
1509
  return mask;
1470
1510
  }
1511
+ function triviaKindMask(labels, keep) {
1512
+ if (!labels) return void 0;
1513
+ let mask = 0;
1514
+ for (const name of keep) {
1515
+ const idx = labels.indexOf(name);
1516
+ if (idx >= 0) mask |= 1 << idx;
1517
+ }
1518
+ return mask;
1519
+ }
1471
1520
 
1472
1521
  // src/recovery/scan.ts
1473
1522
  function probeAt(sentinel, input, pos, ctx) {
@@ -1969,8 +2018,8 @@ function buildFastTriviaScanner(trivia2) {
1969
2018
  if (arms.some((s) => s === null)) return null;
1970
2019
  return loopScanner(arms);
1971
2020
  }
1972
- function triviaRegexSource(parser) {
1973
- const d = parser._def.tag === "label" ? parser._def.parser._def : parser._def;
2021
+ function triviaRegexSource(parser2) {
2022
+ const d = parser2._def.tag === "label" ? parser2._def.parser._def : parser2._def;
1974
2023
  return d.tag === "regex" && d.flags === "" ? d.source : null;
1975
2024
  }
1976
2025
  function loopScanner(arms) {
@@ -1989,8 +2038,8 @@ function loopScanner(arms) {
1989
2038
  return pos;
1990
2039
  };
1991
2040
  }
1992
- function regexTriviaScanner(parser) {
1993
- const d = parser._def.tag === "label" ? parser._def.parser._def : parser._def;
2041
+ function regexTriviaScanner(parser2) {
2042
+ const d = parser2._def.tag === "label" ? parser2._def.parser._def : parser2._def;
1994
2043
  if (d.tag !== "regex" || d.flags) return null;
1995
2044
  return sourceScanner(d.source);
1996
2045
  }
@@ -2298,9 +2347,26 @@ function altStarSource(source) {
2298
2347
  }
2299
2348
 
2300
2349
  // src/combinators/scalar.ts
2350
+ var SCALAR_TAG = /^(?:literal|regex|keywords|sequence|choice|many|oneOrMore|optional|transform|trivia|grammar|sepBy|lazy)$/;
2301
2351
  function scalarOf(combinator) {
2302
2352
  return combinator._parseScalar;
2303
2353
  }
2354
+ function scalarTree(parser2, seen) {
2355
+ if (seen.has(parser2)) return true;
2356
+ if (parser2._parseScalar === void 0) return false;
2357
+ seen.add(parser2);
2358
+ const def = parser2._def;
2359
+ if (!SCALAR_TAG.test(def.tag)) return false;
2360
+ if ("parsers" in def && !def.parsers.every((child) => scalarTree(child, seen))) return false;
2361
+ if ("parser" in def && !scalarTree(def.parser, seen)) return false;
2362
+ if ("separator" in def && !scalarTree(def.separator, seen)) return false;
2363
+ return def.tag !== "lazy" || scalarTree(def.thunk(), seen);
2364
+ }
2365
+ function scalarRootOf(combinator) {
2366
+ const scalar = combinator._parseScalar;
2367
+ const def = combinator._def;
2368
+ return scalar !== void 0 && def.tag === "grammar" && scalarTree(def.parser, /* @__PURE__ */ new Set()) ? scalar : void 0;
2369
+ }
2304
2370
 
2305
2371
  // src/combinators/choice.ts
2306
2372
  function choice(...args) {
@@ -2448,7 +2514,7 @@ function choice(...args) {
2448
2514
  return result;
2449
2515
  }
2450
2516
  if (expected.length === 0) {
2451
- for (const parser of parsers) expected.push(...deriveExpected(parser));
2517
+ for (const parser2 of parsers) expected.push(...deriveExpected(parser2));
2452
2518
  }
2453
2519
  return { ok: false, expected, span: { start: pos, end: pos } };
2454
2520
  }
@@ -3339,17 +3405,59 @@ function buildLexBodyRecognizer(spec, constants) {
3339
3405
  };
3340
3406
  }
3341
3407
 
3408
+ // src/table/run-support.ts
3409
+ function lineCol(ctx, offset) {
3410
+ const starts = ctx._lineStarts ?? [0];
3411
+ let lo = 0, hi = starts.length - 1;
3412
+ while (lo < hi) {
3413
+ const mid = lo + hi + 1 >> 1;
3414
+ if (starts[mid] <= offset) lo = mid;
3415
+ else hi = mid - 1;
3416
+ }
3417
+ return [lo + 1, offset - starts[lo] + 1];
3418
+ }
3419
+ function spanLines(ctx, start, end) {
3420
+ const s = lineCol(ctx, start), e = lineCol(ctx, end);
3421
+ return { start, end, startLine: s[0], startColumn: s[1], endLine: e[0], endColumn: e[1] };
3422
+ }
3423
+ function rawEntry(v, input, s, e) {
3424
+ if (typeof v === "object" && v !== null) {
3425
+ const tg = v._tag;
3426
+ if (tg === "node" || tg === "leaf" || tg === "parseError") return v;
3427
+ }
3428
+ return {
3429
+ _tag: "leaf",
3430
+ value: typeof v === "string" ? v : typeof v === "object" && v !== null ? input.slice(s, e) : "",
3431
+ span: { start: s, end: e }
3432
+ };
3433
+ }
3434
+ function lead(input, pos) {
3435
+ if (pos >= input.length) return -1;
3436
+ const c = input.charCodeAt(pos);
3437
+ if (c < 55296 || c > 56319) return c;
3438
+ return input.codePointAt(pos) ?? c;
3439
+ }
3440
+ var EMPTY_KIDS = Object.freeze([]);
3441
+ var EMPTY_TRIVIA = Object.freeze([]);
3442
+ function collapseEmpty(ctx, build, input, pos, end, readsRaw) {
3443
+ const collected = ctx._cstBuf !== void 0 || ctx._cstChildren !== void 0;
3444
+ if (collected) popCstChild(ctx);
3445
+ const raw = readsRaw ? [rawEntry(void 0, input, pos, end)] : EMPTY_KIDS;
3446
+ const nd = build(EMPTY_KIDS, void 0, { start: pos, end }, raw, EMPTY_TRIVIA, void 0);
3447
+ if (collected) pushCstChild(ctx, nd, ctx._cstBuf?.noRaw === true ? void 0 : rawEntry(nd, input, pos, end));
3448
+ return nd;
3449
+ }
3450
+
3342
3451
  // src/table/lex-program.ts
3343
3452
  var LEX_NODE_TERMINAL = 0;
3344
3453
  var LEX_NODE_SEQUENCE2 = 1;
3345
3454
  var LEX_NODE_SEQUENCE3 = 2;
3346
3455
  var LEX_NODE_SEQUENCE4 = 3;
3347
3456
  var LEX_NODE_SEQUENCE5 = 4;
3348
- var LEX_NODE_CHOICE2 = 5;
3349
- var LEX_NODE_CHOICE4 = 6;
3350
- var LEX_NODE_CHOICE8 = 7;
3457
+ var LEX_NODE_CHOICE = 5;
3351
3458
  var LEX_NODE_NOT = 8;
3352
3459
  var LEX_NODE_OPTIONAL = 9;
3460
+ var LEX_NODE_REPEAT = 10;
3353
3461
  function lexProgramDigest(words) {
3354
3462
  let hash = 2166136261;
3355
3463
  for (const word of words) {
@@ -3378,85 +3486,114 @@ function trackLexLines(ctx, input, end) {
3378
3486
  ctx._lineScannedTo = end;
3379
3487
  }
3380
3488
  function terminalNode(matcher, failure, tracksLines) {
3381
- const match = (input, pos) => {
3382
- const result = matcher(input, pos);
3383
- return result < 0 ? -1 : result / 2;
3384
- };
3385
3489
  return {
3386
- match,
3490
+ match: (input, pos) => {
3491
+ const result = matcher(input, pos);
3492
+ return result < 0 ? -1 : result / 2;
3493
+ },
3387
3494
  run: (input, pos, ctx) => {
3388
- const end = match(input, pos);
3389
- if (end < 0) {
3495
+ const result = matcher(input, pos);
3496
+ if (result < 0) {
3390
3497
  ctx._fe = pos;
3391
3498
  ctx._fx = failure;
3392
3499
  if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
3393
3500
  return -1;
3394
3501
  }
3502
+ const end = result / 2;
3395
3503
  if (tracksLines) trackLexLines(ctx, input, end);
3396
3504
  return end;
3397
3505
  }
3398
3506
  };
3399
3507
  }
3400
3508
  function sequence2(a, b) {
3509
+ const am = a.match, bm = b.match, ar = a.run, br = b.run;
3401
3510
  return {
3402
3511
  match: (input, pos) => {
3403
- const e0 = a.match(input, pos);
3404
- return e0 < 0 ? -1 : b.match(input, e0);
3512
+ const e0 = am(input, pos);
3513
+ return e0 < 0 ? -1 : bm(input, e0);
3405
3514
  },
3406
3515
  run: (input, pos, ctx) => {
3407
- const e0 = a.run(input, pos, ctx);
3516
+ const e0 = ar(input, pos, ctx);
3408
3517
  if (e0 < 0) return -1;
3409
3518
  ctx._fc = false;
3410
- return b.run(input, e0, ctx);
3519
+ return br(input, e0, ctx);
3411
3520
  }
3412
3521
  };
3413
3522
  }
3414
3523
  function sequence3(a, b, c) {
3524
+ const am = a.match, bm = b.match, cm = c.match, ar = a.run, br = b.run, cr = c.run;
3415
3525
  return {
3416
3526
  match: (input, pos) => {
3417
- const e0 = a.match(input, pos);
3527
+ const e0 = am(input, pos);
3418
3528
  if (e0 < 0) return -1;
3419
- const e1 = b.match(input, e0);
3420
- return e1 < 0 ? -1 : c.match(input, e1);
3529
+ const e1 = bm(input, e0);
3530
+ return e1 < 0 ? -1 : cm(input, e1);
3421
3531
  },
3422
3532
  run: (input, pos, ctx) => {
3423
- const e0 = a.run(input, pos, ctx);
3533
+ const e0 = ar(input, pos, ctx);
3424
3534
  if (e0 < 0) return -1;
3425
3535
  ctx._fc = false;
3426
- const e1 = b.run(input, e0, ctx);
3536
+ const e1 = br(input, e0, ctx);
3427
3537
  if (e1 < 0) return -1;
3428
3538
  ctx._fc = false;
3429
- return c.run(input, e1, ctx);
3539
+ return cr(input, e1, ctx);
3430
3540
  }
3431
3541
  };
3432
3542
  }
3433
3543
  function sequence4(a, b, c, d) {
3434
- const abc = sequence3(a, b, c);
3544
+ const am = a.match, bm = b.match, cm = c.match, dm = d.match;
3545
+ const ar = a.run, br = b.run, cr = c.run, dr = d.run;
3435
3546
  return {
3436
3547
  match: (input, pos) => {
3437
- const end = abc.match(input, pos);
3438
- return end < 0 ? -1 : d.match(input, end);
3548
+ const e0 = am(input, pos);
3549
+ if (e0 < 0) return -1;
3550
+ const e1 = bm(input, e0);
3551
+ if (e1 < 0) return -1;
3552
+ const e2 = cm(input, e1);
3553
+ return e2 < 0 ? -1 : dm(input, e2);
3439
3554
  },
3440
3555
  run: (input, pos, ctx) => {
3441
- const end = abc.run(input, pos, ctx);
3442
- if (end < 0) return -1;
3556
+ const e0 = ar(input, pos, ctx);
3557
+ if (e0 < 0) return -1;
3558
+ ctx._fc = false;
3559
+ const e1 = br(input, e0, ctx);
3560
+ if (e1 < 0) return -1;
3561
+ ctx._fc = false;
3562
+ const e2 = cr(input, e1, ctx);
3563
+ if (e2 < 0) return -1;
3443
3564
  ctx._fc = false;
3444
- return d.run(input, end, ctx);
3565
+ return dr(input, e2, ctx);
3445
3566
  }
3446
3567
  };
3447
3568
  }
3448
3569
  function sequence5(a, b, c, d, e) {
3449
- const abcd = sequence4(a, b, c, d);
3570
+ const am = a.match, bm = b.match, cm = c.match, dm = d.match, em = e.match;
3571
+ const ar = a.run, br = b.run, cr = c.run, dr = d.run, er = e.run;
3450
3572
  return {
3451
3573
  match: (input, pos) => {
3452
- const end = abcd.match(input, pos);
3453
- return end < 0 ? -1 : e.match(input, end);
3574
+ const e0 = am(input, pos);
3575
+ if (e0 < 0) return -1;
3576
+ const e1 = bm(input, e0);
3577
+ if (e1 < 0) return -1;
3578
+ const e2 = cm(input, e1);
3579
+ if (e2 < 0) return -1;
3580
+ const e3 = dm(input, e2);
3581
+ return e3 < 0 ? -1 : em(input, e3);
3454
3582
  },
3455
3583
  run: (input, pos, ctx) => {
3456
- const end = abcd.run(input, pos, ctx);
3457
- if (end < 0) return -1;
3584
+ const e0 = ar(input, pos, ctx);
3585
+ if (e0 < 0) return -1;
3586
+ ctx._fc = false;
3587
+ const e1 = br(input, e0, ctx);
3588
+ if (e1 < 0) return -1;
3589
+ ctx._fc = false;
3590
+ const e2 = cr(input, e1, ctx);
3591
+ if (e2 < 0) return -1;
3592
+ ctx._fc = false;
3593
+ const e3 = dr(input, e2, ctx);
3594
+ if (e3 < 0) return -1;
3458
3595
  ctx._fc = false;
3459
- return e.run(input, end, ctx);
3596
+ return er(input, e3, ctx);
3460
3597
  }
3461
3598
  };
3462
3599
  }
@@ -3469,9 +3606,9 @@ function appendExpected(acc, values) {
3469
3606
  function choiceNode(arms, classes, armExpected, choiceExpected) {
3470
3607
  let matchTail = () => -1;
3471
3608
  for (let i = arms.length - 1; i >= 0; i--) {
3472
- const arm = arms[i], next = matchTail;
3609
+ const armMatch = arms[i].match, next = matchTail;
3473
3610
  matchTail = (input, pos) => {
3474
- const end = arm.match(input, pos);
3611
+ const end = armMatch(input, pos);
3475
3612
  return end < 0 ? next(input, pos) : end;
3476
3613
  };
3477
3614
  }
@@ -3481,7 +3618,7 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
3481
3618
  return -1;
3482
3619
  };
3483
3620
  for (let i = arms.length - 1; i >= 0; i--) {
3484
- const arm = arms[i], cls = classes[i], staticExpected = armExpected[i], next = tail;
3621
+ const armRun = arms[i].run, cls = classes[i], staticExpected = armExpected[i], next = tail;
3485
3622
  tail = (input, pos, ctx, lead2, acc, best) => {
3486
3623
  if (cls !== void 0 && !classHas(cls, lead2)) {
3487
3624
  return next(
@@ -3494,7 +3631,7 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
3494
3631
  );
3495
3632
  }
3496
3633
  ctx._fc = false;
3497
- const end = arm.run(input, pos, ctx);
3634
+ const end = armRun(input, pos, ctx);
3498
3635
  if (end >= 0) return end;
3499
3636
  const at = ctx._fe ?? pos;
3500
3637
  if (at > best) {
@@ -3521,11 +3658,58 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
3521
3658
  )
3522
3659
  };
3523
3660
  }
3661
+ function exclusiveChoiceNode(arms, classes, choiceFx) {
3662
+ const ascii = (classes.length <= 128 ? new Int8Array(128) : new Int32Array(128)).fill(-1);
3663
+ const hi = [];
3664
+ for (let i = 0; i < classes.length; i++) {
3665
+ const cls = classes[i];
3666
+ for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) ascii[c] = i;
3667
+ for (let r = 0; r < cls.hi.length; r += 2) hi.push(cls.hi[r], cls.hi[r + 1], i);
3668
+ }
3669
+ const select = (code) => {
3670
+ if (code < 0) return -1;
3671
+ if (code < 128) return ascii[code];
3672
+ for (let r = 0; r < hi.length; r += 3) if (code >= hi[r] && code <= hi[r + 1]) return hi[r + 2];
3673
+ return -1;
3674
+ };
3675
+ let matchArm = () => -1;
3676
+ let selectRun = () => -1;
3677
+ for (let i = arms.length - 1; i >= 0; i--) {
3678
+ const armMatch = arms[i].match, armRun = arms[i].run, nextMatch = matchArm, nextRun = selectRun;
3679
+ matchArm = (selected, input, pos) => selected === i ? armMatch(input, pos) : nextMatch(selected, input, pos);
3680
+ selectRun = (selected, input, pos, ctx) => selected === i ? armRun(input, pos, ctx) : nextRun(selected, input, pos, ctx);
3681
+ }
3682
+ const runArm = (input, pos, ctx) => {
3683
+ const arm = select(lead(input, pos));
3684
+ if (arm >= 0) {
3685
+ ctx._fc = false;
3686
+ const end = selectRun(arm, input, pos, ctx);
3687
+ if (end >= 0) return end;
3688
+ if (committed(ctx)) return -1;
3689
+ const failed = ctx._fx;
3690
+ if (failed !== void 0 && failed.length > 0) {
3691
+ ctx._fe = pos;
3692
+ return -1;
3693
+ }
3694
+ }
3695
+ ctx._fe = pos;
3696
+ ctx._fx = choiceFx;
3697
+ return -1;
3698
+ };
3699
+ return {
3700
+ match: (input, pos) => {
3701
+ const arm = select(lead(input, pos));
3702
+ return arm < 0 ? -1 : matchArm(arm, input, pos);
3703
+ },
3704
+ run: runArm
3705
+ };
3706
+ }
3524
3707
  function notNode(body, failure) {
3708
+ const bodyMatch = body.match;
3525
3709
  return {
3526
- match: (input, pos) => body.match(input, pos) < 0 ? pos : -1,
3710
+ match: (input, pos) => bodyMatch(input, pos) < 0 ? pos : -1,
3527
3711
  run: (input, pos, ctx) => {
3528
- if (body.match(input, pos) < 0) return pos;
3712
+ if (bodyMatch(input, pos) < 0) return pos;
3529
3713
  ctx._fe = pos;
3530
3714
  ctx._fx = failure;
3531
3715
  return -1;
@@ -3533,18 +3717,57 @@ function notNode(body, failure) {
3533
3717
  };
3534
3718
  }
3535
3719
  function optionalNode(body) {
3720
+ const bodyMatch = body.match, bodyRun = body.run;
3536
3721
  return {
3537
3722
  match: (input, pos) => {
3538
- const end = body.match(input, pos);
3723
+ const end = bodyMatch(input, pos);
3539
3724
  return end < 0 ? pos : end;
3540
3725
  },
3541
3726
  run: (input, pos, ctx) => {
3542
3727
  ctx._fc = false;
3543
- const end = body.run(input, pos, ctx);
3728
+ const end = bodyRun(input, pos, ctx);
3544
3729
  return end < 0 && !committed(ctx) ? pos : end;
3545
3730
  }
3546
3731
  };
3547
3732
  }
3733
+ function repeatNode(item, min, max) {
3734
+ const itemMatch = item.match, itemRun = item.run;
3735
+ return {
3736
+ match: (input, pos) => {
3737
+ let cur = pos;
3738
+ let count = 0;
3739
+ for (; ; ) {
3740
+ if (max >= 0 && count >= max) break;
3741
+ const optional = count >= min && (count > 0 || min === 0);
3742
+ if (optional && cur >= input.length) break;
3743
+ const end = itemMatch(input, cur);
3744
+ if (end < 0 || optional && end === cur) break;
3745
+ cur = end;
3746
+ count++;
3747
+ }
3748
+ return count < min ? -1 : cur;
3749
+ },
3750
+ run: (input, pos, ctx) => {
3751
+ let cur = pos;
3752
+ let count = 0;
3753
+ for (; ; ) {
3754
+ if (max >= 0 && count >= max) break;
3755
+ const optional = count >= min && (count > 0 || min === 0);
3756
+ if (optional && cur >= input.length) break;
3757
+ ctx._fc = false;
3758
+ const end = itemRun(input, cur, ctx);
3759
+ if (end < 0) {
3760
+ if (committed(ctx)) return -1;
3761
+ break;
3762
+ }
3763
+ if (optional && end === cur) break;
3764
+ cur = end;
3765
+ count++;
3766
+ }
3767
+ return count < min ? -1 : cur;
3768
+ }
3769
+ };
3770
+ }
3548
3771
  function fixedTreeRunner(words, matchers, classes, expected) {
3549
3772
  const stack = [];
3550
3773
  const pop = () => {
@@ -3572,9 +3795,14 @@ function fixedTreeRunner(words, matchers, classes, expected) {
3572
3795
  else stack.push(sequence5(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4]));
3573
3796
  continue;
3574
3797
  }
3575
- if (op >= LEX_NODE_CHOICE2 && op <= LEX_NODE_CHOICE8) {
3576
- const count = op === LEX_NODE_CHOICE2 ? 2 : op === LEX_NODE_CHOICE4 ? 4 : 8;
3798
+ if (op === LEX_NODE_CHOICE) {
3799
+ const count = words[at++];
3800
+ const exclusive = words[at++];
3801
+ if (exclusive !== 0 && exclusive !== 1) throw new TypeError("table lexical tree choice has an invalid dispatch mode");
3577
3802
  const choiceFx = expected[words[at++]];
3803
+ if (!Number.isInteger(count) || count < 2 || count > stack.length) {
3804
+ throw new TypeError("table lexical tree choice has an invalid arm count");
3805
+ }
3578
3806
  if (choiceFx === void 0) throw new TypeError("table lexical tree choice has an invalid expected set");
3579
3807
  const armClasses = [];
3580
3808
  const armFx = [];
@@ -3587,7 +3815,7 @@ function fixedTreeRunner(words, matchers, classes, expected) {
3587
3815
  armFx.push(fx);
3588
3816
  }
3589
3817
  const arms = Array.from({ length: count }, pop).reverse();
3590
- stack.push(choiceNode(arms, armClasses, armFx, choiceFx));
3818
+ stack.push(exclusive === 1 ? exclusiveChoiceNode(arms, armClasses, choiceFx) : choiceNode(arms, armClasses, armFx, choiceFx));
3591
3819
  continue;
3592
3820
  }
3593
3821
  if (op === LEX_NODE_NOT) {
@@ -3600,6 +3828,14 @@ function fixedTreeRunner(words, matchers, classes, expected) {
3600
3828
  stack.push(optionalNode(pop()));
3601
3829
  continue;
3602
3830
  }
3831
+ if (op === LEX_NODE_REPEAT) {
3832
+ const min = words[at++], max = words[at++];
3833
+ if (!Number.isInteger(min) || min < 0 || !Number.isInteger(max) || max >= 0 && max < min) {
3834
+ throw new TypeError("table lexical tree repeat has invalid bounds");
3835
+ }
3836
+ stack.push(repeatNode(pop(), min, max));
3837
+ continue;
3838
+ }
3603
3839
  throw new TypeError("table lexical tree has an unknown fixed body");
3604
3840
  }
3605
3841
  if (stack.length !== 1) throw new TypeError("table lexical tree does not resolve to one root body");
@@ -4275,7 +4511,7 @@ function sequence(...parsers) {
4275
4511
  if (tolerant) {
4276
4512
  followSentinels ??= parsers.map((_, i) => firstSetSentinel(
4277
4513
  parsers.slice(i + 1).reduce(
4278
- (set, parser) => union(set, firstSetOf(parser)),
4514
+ (set, parser2) => union(set, firstSetOf(parser2)),
4279
4515
  { kind: "empty" }
4280
4516
  )
4281
4517
  ));
@@ -4411,13 +4647,13 @@ function ref() {
4411
4647
  return scalar(input, pos, ctx);
4412
4648
  },
4413
4649
  parse(input, pos, ctx) {
4414
- const parser = resolved;
4415
- if (!parser) throw new Error("ref<T>() used before .define() was called");
4650
+ const parser2 = resolved;
4651
+ if (!parser2) throw new Error("ref<T>() used before .define() was called");
4416
4652
  const gt = meta.grammarTrivia;
4417
4653
  if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
4418
- return withRuleTrivia(gt, ctx, () => parser.parse(input, pos, ctx));
4654
+ return withRuleTrivia(gt, ctx, () => parser2.parse(input, pos, ctx));
4419
4655
  }
4420
- return parser.parse(input, pos, ctx);
4656
+ return parser2.parse(input, pos, ctx);
4421
4657
  },
4422
4658
  define(p) {
4423
4659
  if (resolved) throw new Error("ref<T>() already defined");
@@ -4702,6 +4938,12 @@ function buildReadsState(def) {
4702
4938
  }
4703
4939
 
4704
4940
  // src/combinators/token.ts
4941
+ function semanticLeafValue(_ctx, _input, _start, _end, value) {
4942
+ return value;
4943
+ }
4944
+ function sourceLeafValue(ctx, input, start, end, value) {
4945
+ return cstOutputHost(ctx.build) ? input.slice(start, end) : value;
4946
+ }
4705
4947
  function token(root) {
4706
4948
  const meta = {
4707
4949
  firstSet: root._meta.firstSet,
@@ -4754,6 +4996,64 @@ function token(root) {
4754
4996
  }
4755
4997
  };
4756
4998
  }
4999
+ function makeLeaf(root, fn, sourceCstValue) {
5000
+ const cstValue = sourceCstValue ? sourceLeafValue : semanticLeafValue;
5001
+ const meta = {
5002
+ firstSet: root._meta.firstSet,
5003
+ canMatchNewline: root._meta.canMatchNewline,
5004
+ isTrivia: false
5005
+ };
5006
+ return {
5007
+ _tag: "leaf",
5008
+ _meta: meta,
5009
+ _def: {
5010
+ tag: "leaf",
5011
+ parser: root,
5012
+ fn,
5013
+ ...sourceCstValue ? { cstValue: "source" } : {}
5014
+ },
5015
+ parse(input, pos, ctx) {
5016
+ const savedBuf = ctx._cstBuf;
5017
+ const savedChildren = ctx._cstChildren;
5018
+ const savedLeaves = ctx._cstLeaves;
5019
+ const savedRaw = ctx._cstRawChildren;
5020
+ const savedTriviaLog = ctx._cstTriviaLog;
5021
+ const savedOuterTriviaLog = ctx._triviaLog;
5022
+ const wasCapturing = cstCaptureActive(ctx);
5023
+ ctx._cstBuf = void 0;
5024
+ ctx._cstChildren = void 0;
5025
+ ctx._cstLeaves = void 0;
5026
+ ctx._cstRawChildren = void 0;
5027
+ ctx._cstTriviaLog = void 0;
5028
+ ctx._triviaLog = void 0;
5029
+ let result;
5030
+ try {
5031
+ result = root.parse(input, pos, ctx);
5032
+ } finally {
5033
+ ctx._cstBuf = savedBuf;
5034
+ ctx._cstChildren = savedChildren;
5035
+ ctx._cstLeaves = savedLeaves;
5036
+ ctx._cstRawChildren = savedRaw;
5037
+ ctx._cstTriviaLog = savedTriviaLog;
5038
+ ctx._triviaLog = savedOuterTriviaLog;
5039
+ }
5040
+ if (!result.ok) return result;
5041
+ const value = fn(result.value, result.span);
5042
+ if (wasCapturing) pushCstLeaf(ctx, {
5043
+ _tag: "leaf",
5044
+ value: cstValue(ctx, input, pos, result.span.end, value),
5045
+ span: result.span
5046
+ });
5047
+ return { ok: true, value, span: result.span };
5048
+ }
5049
+ };
5050
+ }
5051
+ function leaf(root, fn) {
5052
+ return makeLeaf(root, fn, false);
5053
+ }
5054
+ function sourceLeaf(root, fn) {
5055
+ return makeLeaf(root, fn, true);
5056
+ }
4757
5057
 
4758
5058
  // src/combinators/scanTo.ts
4759
5059
  function resolveScanSkip(explicitSkip, raw, ctx) {
@@ -4793,8 +5093,8 @@ function scanTo(sentinel, { skip, raw = false, orEOF = false, recoverAt, stopAt
4793
5093
  probeCtx._errors = ctx._errors;
4794
5094
  const emit = (end) => {
4795
5095
  if (end > pos && cstCaptureActive(ctx)) {
4796
- const leaf = { _tag: "leaf", value: input.slice(pos, end), span: { start: pos, end } };
4797
- pushCstLeaf(ctx, leaf);
5096
+ const leaf2 = { _tag: "leaf", value: input.slice(pos, end), span: { start: pos, end } };
5097
+ pushCstLeaf(ctx, leaf2);
4798
5098
  }
4799
5099
  };
4800
5100
  if (recoverAt === void 0 && stopAt === void 0) {
@@ -5135,10 +5435,10 @@ function clearOf(ranges, input, from, to) {
5135
5435
  }
5136
5436
 
5137
5437
  // src/combinators/dispatch.ts
5138
- function parserUsesRouted(parser, seen = /* @__PURE__ */ new Set()) {
5139
- if (seen.has(parser)) return false;
5140
- seen.add(parser);
5141
- const def = parser._def;
5438
+ function parserUsesRouted(parser2, seen = /* @__PURE__ */ new Set()) {
5439
+ if (seen.has(parser2)) return false;
5440
+ seen.add(parser2);
5441
+ const def = parser2._def;
5142
5442
  switch (def.tag) {
5143
5443
  case "routed":
5144
5444
  return true;
@@ -5188,10 +5488,16 @@ function branchUsesRouted(branch) {
5188
5488
  return branch.usesRouted === true || parserUsesRouted(branch.parser);
5189
5489
  }
5190
5490
  function asciiFoldKey(key) {
5191
- let out = "";
5192
- for (let i = 0; i < key.length; i++) {
5491
+ let i = 0;
5492
+ for (; i < key.length; i++) {
5493
+ const c = key.charCodeAt(i);
5494
+ if (c >= 65 && c <= 90) break;
5495
+ }
5496
+ if (i === key.length) return key;
5497
+ let out = key.slice(0, i);
5498
+ for (; i < key.length; i++) {
5193
5499
  const c = key.charCodeAt(i);
5194
- out += String.fromCharCode(c >= 65 && c <= 90 ? c + 32 : c);
5500
+ out += c >= 65 && c <= 90 ? String.fromCharCode(c + 32) : key[i];
5195
5501
  }
5196
5502
  return out;
5197
5503
  }
@@ -5253,6 +5559,7 @@ var OP_SCOPE_PLAIN = 41;
5253
5559
  var OP_LEX_BODY = 42;
5254
5560
  var OP_LEX_PROGRAM = 43;
5255
5561
  var OP_SOURCE_LEAF = 44;
5562
+ var OP_RGATE = 45;
5256
5563
  var OP_DISPATCH = 25;
5257
5564
  var OP_ROUTED = 26;
5258
5565
  var OP_NAMES = {
@@ -5272,6 +5579,7 @@ var OP_NAMES = {
5272
5579
  [OP_PEEK]: "PEEK",
5273
5580
  [OP_LEAF]: "LEAF",
5274
5581
  [OP_SOURCE_LEAF]: "SOURCE_LEAF",
5582
+ [OP_RGATE]: "RGATE",
5275
5583
  [OP_EMPTY]: "EMPTY",
5276
5584
  [OP_LIT_TRACK]: "LIT_TRACK",
5277
5585
  [OP_RX_TRACK]: "RX_TRACK",
@@ -6371,6 +6679,7 @@ function childSlots(code, ip, out) {
6371
6679
  case OP_LEAF:
6372
6680
  case OP_SOURCE_LEAF:
6373
6681
  case OP_ARMGATE:
6682
+ case OP_RGATE:
6374
6683
  out.push(code[ip + 2]);
6375
6684
  return true;
6376
6685
  // `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
@@ -6454,6 +6763,42 @@ function reachableSites(code, roots) {
6454
6763
  }
6455
6764
  return seen;
6456
6765
  }
6766
+ function passCollapse(code, ip, hostCst) {
6767
+ const flags = code[ip + 3];
6768
+ if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return false;
6769
+ if (flags !== 32 && flags !== 34) return false;
6770
+ let at = code[ip + 2];
6771
+ for (let n = 0; n < 8; n++) {
6772
+ const op = code[at];
6773
+ if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[at + 3] === 0) at = code[at + 2];
6774
+ else if (op === OP_RULE) at = code[at + 1];
6775
+ else break;
6776
+ }
6777
+ return code[at] === OP_NODE;
6778
+ }
6779
+ function gatedPassCollapse(code, ip, hostCst) {
6780
+ const flags = code[ip + 3];
6781
+ if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return void 0;
6782
+ if (flags !== 32 && flags !== 34) return void 0;
6783
+ const seq = code[ip + 2];
6784
+ if (code[seq] !== OP_SEQ && code[seq] !== OP_SEQV) return void 0;
6785
+ const n = code[seq + 1];
6786
+ if (n < 2) return void 0;
6787
+ const leads = [];
6788
+ const lits = [];
6789
+ for (let i = 0; i < n - 1; i++) {
6790
+ const t = code[seq + 2 + i];
6791
+ if (code[t] !== OP_OPT && code[t] !== OP_NOT) return void 0;
6792
+ const g = code[t + 1];
6793
+ if (code[g] === OP_GATE) leads.push(g);
6794
+ else if (code[g] === OP_LIT) lits.push(code[g + 1]);
6795
+ else return void 0;
6796
+ }
6797
+ const last = code[seq + 2 + n - 1];
6798
+ let at = last;
6799
+ for (let k = 0; k < 8 && (code[at] === OP_GATE || code[at] === OP_RULE); k++) at = code[at] === OP_RULE ? code[at + 1] : code[at + 2];
6800
+ return code[at] === OP_NODE ? { leads, lits, last } : void 0;
6801
+ }
6457
6802
  function transfer(code, ip, at, hostCst) {
6458
6803
  const op = code[ip];
6459
6804
  if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
@@ -6465,14 +6810,18 @@ function transfer(code, ip, at, hostCst) {
6465
6810
  }
6466
6811
  if (op === OP_NODE || op === OP_NODE_TRACK) {
6467
6812
  const flags = code[ip + 3];
6813
+ if (passCollapse(code, ip, hostCst)) return at;
6814
+ const gated = gatedPassCollapse(code, ip, hostCst) !== void 0;
6468
6815
  const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && ((flags & ~128) === 2 || flags === 18 || flags === 34);
6469
6816
  if (directChildren) {
6470
- return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
6817
+ const framed2 = { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
6818
+ return gated ? meet(at, framed2) : framed2;
6471
6819
  }
6472
6820
  const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
6473
6821
  const raw = !hostCst && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags & 2) !== 0 ? RAW_OMIT : RAW_CAPTURE;
6474
6822
  if (at.buf && raw === at.raw && cap === at.cap) return at;
6475
- return { tri: at.tri, buf: true, raw, cap };
6823
+ const framed = { tri: at.tri, buf: true, raw, cap };
6824
+ return gated ? meet(at, framed) : framed;
6476
6825
  }
6477
6826
  if (op === OP_TOKEN) {
6478
6827
  if (at.tri === TRI_NONE && !at.buf) return at;
@@ -6510,6 +6859,40 @@ function computeSiteLabels(code, roots, hostCst) {
6510
6859
  }
6511
6860
  return { at: (ip) => labels.get(ip) ?? TOP };
6512
6861
  }
6862
+ function scopeIsIdentity(code, ip, at) {
6863
+ const op = code[ip];
6864
+ if (op !== OP_SCOPE_PLAIN && !(op === OP_SCOPE && code[ip + 3] === 0)) return false;
6865
+ const ki = code[ip + 1];
6866
+ return at.tri === (ki < 0 ? TRI_NONE : ki);
6867
+ }
6868
+ function scanHandoffNeeded(code, ip, labels) {
6869
+ const seen = /* @__PURE__ */ new Set();
6870
+ const stack = [ip];
6871
+ const kids = [];
6872
+ while (stack.length > 0) {
6873
+ const at = stack.pop();
6874
+ if (seen.has(at)) continue;
6875
+ seen.add(at);
6876
+ const l = labels.at(at);
6877
+ if (l.tri === TRI_UNKNOWN) return true;
6878
+ const op = code[at];
6879
+ if (op === OP_SCAN) return true;
6880
+ if (op === OP_TOKEN || op === OP_SCOPE_CAP) continue;
6881
+ if ((op === OP_SCOPE_PLAIN || op === OP_SCOPE) && !(code[at + 1] >= 0 && l.tri === code[at + 1] && (op === OP_SCOPE_PLAIN || code[at + 3] === 0))) continue;
6882
+ kids.length = 0;
6883
+ if (!childSlots(code, at, kids)) return true;
6884
+ for (const c of kids) stack.push(c);
6885
+ }
6886
+ return false;
6887
+ }
6888
+ function triviaLeadRanges(tri, trivia2) {
6889
+ if (tri === TRI_NONE) return [];
6890
+ if (tri < 0) return void 0;
6891
+ const fs = trivia2[tri]?._meta.firstSet;
6892
+ if (fs === void 0) return void 0;
6893
+ if (fs.kind === "empty") return [];
6894
+ return fs.kind === "ranges" && fs.ranges !== void 0 ? fs.ranges : void 0;
6895
+ }
6513
6896
 
6514
6897
  // src/table/scalar-terminal.ts
6515
6898
  function makeScalarRecognizer(op, spec) {
@@ -6547,6 +6930,12 @@ function scalarTerminalNotChild(code, ip) {
6547
6930
  const op = code[child];
6548
6931
  return op === OP_RX || op === OP_LIT ? child : -1;
6549
6932
  }
6933
+ function scalarTerminalPeekChild(code, ip) {
6934
+ if (code[ip] !== OP_PEEK) return -1;
6935
+ const child = code[ip + 1];
6936
+ const op = code[child];
6937
+ return op === OP_RX || op === OP_LIT ? child : -1;
6938
+ }
6550
6939
  function leadingScalarTerminal(code, ip, minDepth = 2, throughAttempt = true, throughPeek = false) {
6551
6940
  const seen = /* @__PURE__ */ new Set();
6552
6941
  let at = ip;
@@ -6724,6 +7113,59 @@ function leadingTriviaFieldAt(code, k, ip) {
6724
7113
  return code[ip] === OP_FIELD && (fieldSpec(k[code[ip + 1]]).bits & FIELD_LEADING_TRIVIA) !== 0;
6725
7114
  }
6726
7115
 
7116
+ // src/table/hold-gap.ts
7117
+ var WRAPPERS = /* @__PURE__ */ new Set([
7118
+ OP_NODE,
7119
+ OP_XFORM,
7120
+ OP_LEAF,
7121
+ OP_SOURCE_LEAF,
7122
+ OP_TOKEN,
7123
+ OP_SCOPE,
7124
+ OP_SCOPE_CAP,
7125
+ OP_SCOPE_PLAIN,
7126
+ OP_FIELD,
7127
+ OP_LABEL,
7128
+ OP_EXPECT,
7129
+ OP_WITHCTX,
7130
+ OP_RULE,
7131
+ OP_ATTEMPT,
7132
+ OP_COV
7133
+ ]);
7134
+ function rowNullable(code, k, ip, memo) {
7135
+ const hit = memo.get(ip);
7136
+ if (hit !== void 0) return hit;
7137
+ memo.set(ip, true);
7138
+ const op = code[ip];
7139
+ const kids = [];
7140
+ let out = true;
7141
+ if (op === OP_GATE) out = false;
7142
+ else if (op === OP_LIT || op === OP_LIT_CI) out = k[code[ip + 1]].length === 0;
7143
+ else if (op === OP_RX) {
7144
+ const re = k[code[ip + 1]];
7145
+ out = !(re instanceof RegExp) || regexCanMatchEmpty(re.source);
7146
+ } else if (op === OP_SEQ || op === OP_SEQV || op === OP_SEQX) {
7147
+ childSlots(code, ip, kids);
7148
+ out = kids.every((c) => rowNullable(code, k, c, memo));
7149
+ } else if (op === OP_CHOICE) {
7150
+ childSlots(code, ip, kids);
7151
+ out = kids.length === 0 || kids.some((c) => rowNullable(code, k, c, memo));
7152
+ } else if (op === OP_REP || op === OP_REPV) {
7153
+ out = code[ip + 2] === 0 || rowNullable(code, k, code[ip + 1], memo);
7154
+ } else if (WRAPPERS.has(op)) {
7155
+ if (childSlots(code, ip, kids) && kids.length === 1) out = rowNullable(code, k, kids[0], memo);
7156
+ }
7157
+ memo.set(ip, out);
7158
+ return out;
7159
+ }
7160
+ function holdsGap(code, k, base, n, i, memo) {
7161
+ if (i < 1 || i + 1 >= n) return false;
7162
+ const term = code[base + i];
7163
+ if (code[term] !== OP_NOT && code[term] !== OP_PEEK) return false;
7164
+ const next = code[base + i + 1];
7165
+ if (code[next] === OP_ADJ || leadingTriviaFieldAt(code, k, next)) return false;
7166
+ return !rowNullable(code, k, next, memo);
7167
+ }
7168
+
6727
7169
  // src/table/emit-assembly.ts
6728
7170
  var Unemittable = class extends Error {
6729
7171
  construct;
@@ -6804,7 +7246,10 @@ var EMITTED_PARAMS = [
6804
7246
  "triviaFieldCapture",
6805
7247
  // Appended for the deferred-commit trivia skip (`trivia-gap.ts`); old
6806
7248
  // factories ignore it.
6807
- "skipDeferredTrivia"
7249
+ "skipDeferredTrivia",
7250
+ // Appended for the pass-through collapse (`run-support.ts`); old factories
7251
+ // ignore it.
7252
+ "collapseEmpty"
6808
7253
  ];
6809
7254
  var RUNTIME_PRELUDE = `
6810
7255
  let _pfScan=null
@@ -7001,6 +7446,24 @@ ${fast}
7001
7446
  ${scanned}
7002
7447
  }`;
7003
7448
  }
7449
+ function emitHoldTerm(callee, dst, t, l, skip) {
7450
+ const fast = `const ${t}v=${callee}(input,cur,ctx)
7451
+ if(${t}v===FAIL)return FAIL
7452
+ ${dst}=${t}v
7453
+ cur=EC.e`;
7454
+ if (l.tri === TRI_NONE) return fast;
7455
+ const held = `const ${t}s=${skip}(input,cur,ctx)
7456
+ const ${t}v=${callee}(input,${t}s,ctx)
7457
+ if(${t}v===FAIL)return FAIL
7458
+ ${dst}=${t}v
7459
+ cur=${t}s`;
7460
+ if (l.tri !== TRI_UNKNOWN) return held;
7461
+ return `if(ctx.trivia===undefined){
7462
+ ${fast}
7463
+ }else{
7464
+ ${held}
7465
+ }`;
7466
+ }
7004
7467
  function leadSkip(hasTrivia, leadTrivia, skip) {
7005
7468
  if (hasTrivia === "false") return "{}";
7006
7469
  const call = `itemStart=${skip}(input,itemStart,ctx)`;
@@ -7042,6 +7505,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, se
7042
7505
  const reachable = [...reachableSites(code, roots)];
7043
7506
  const labels = computeSiteLabels(code, roots, hostCst);
7044
7507
  const scalarSpecs = /* @__PURE__ */ new Set();
7508
+ const nullable2 = /* @__PURE__ */ new Map();
7045
7509
  const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
7046
7510
  const largeChoiceLiteralFamilies = /* @__PURE__ */ new Map();
7047
7511
  const largeChoiceScalarSequences = /* @__PURE__ */ new Map();
@@ -7366,9 +7830,7 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
7366
7830
  const op = code[ip];
7367
7831
  if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
7368
7832
  if (op === OP_RULE) return code[ip + 1];
7369
- if ((op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[ip + 3] === 0) && code[ip + 1] >= 0 && labels.at(ip).tri === code[ip + 1]) {
7370
- return code[ip + 2];
7371
- }
7833
+ if (scopeIsIdentity(code, ip, labels.at(ip))) return code[ip + 2];
7372
7834
  return void 0;
7373
7835
  }
7374
7836
  function lower(ip, fname) {
@@ -7490,6 +7952,22 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
7490
7952
  return `${head}
7491
7953
  if(${gateMissTest(ip)}){ctx._fe=pos;ctx._fx=${xf};return FAIL}
7492
7954
  return ${child}(input,pos,ctx)
7955
+ }`;
7956
+ }
7957
+ case OP_RGATE: {
7958
+ const child = link(code[ip + 2]);
7959
+ if (cfg.tolerant || cfg.probe) return `${head}
7960
+ return ${child}(input,pos,ctx)
7961
+ }`;
7962
+ const resolved = t.cc[code[ip + 1]];
7963
+ const ci = classes.push([resolved]) - 1;
7964
+ classPlan.push([code[ip + 1]]);
7965
+ const cls = hoist("cl", `CLS[${ci}][0]`);
7966
+ const xf = fxRef(code[ip + 3]);
7967
+ return `${head}
7968
+ const it=ctx._routed
7969
+ if(it!==undefined&&it.span.start===pos&&!classHas(${cls},lead(input,it.span.end))){ctx._fe=it.span.end;ctx._fx=${xf};return FAIL}
7970
+ return ${child}(input,pos,ctx)
7493
7971
  }`;
7494
7972
  }
7495
7973
  case OP_ARMGATE: {
@@ -7764,23 +8242,33 @@ return FAIL
7764
8242
  const p = tmp();
7765
8243
  return `${head}
7766
8244
  ${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${emitMark(p, L.buf, L.raw, sinks)}
7767
- const v=${child}(input,pos,ctx)
8245
+ ${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
7768
8246
  ${emitRollback(p, L.buf, L.raw, sinks)}
7769
- if(v===FAIL){EC.e=pos;return null}
8247
+ ${cfg.probe ? "if(ctx._probe!==undefined)ctx._probe.best=pb??null\n" : ""}if(v===FAIL){EC.e=pos;return null}
7770
8248
  ctx._fe=pos
7771
8249
  ctx._fx=${xf}
7772
8250
  return FAIL
7773
8251
  }`;
7774
8252
  }
7775
8253
  case OP_PEEK: {
8254
+ const scalarChild = scalarTerminalPeekChild(code, ip);
8255
+ if (scalarChild >= 0) {
8256
+ const recognize = recognizerRef(code[scalarChild + 1]);
8257
+ const xf2 = fxRef(code[ip + 2]);
8258
+ return `${head}
8259
+ if(${recognize}(input,pos)<0){ctx._fe=pos;ctx._fx=${xf2};return FAIL}
8260
+ EC.e=pos
8261
+ return null
8262
+ }`;
8263
+ }
7776
8264
  const child = link(code[ip + 1]);
7777
8265
  const xf = fxRef(code[ip + 2]);
7778
8266
  const p = tmp();
7779
8267
  return `${head}
7780
8268
  ${lookaheadMiss(code[ip + 1], `ctx._fe=pos;ctx._fx=${xf};return FAIL`)}${emitMark(p, L.buf, L.raw, sinks)}
7781
- const v=${child}(input,pos,ctx)
8269
+ ${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
7782
8270
  ${emitRollback(p, L.buf, L.raw, sinks)}
7783
- if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
8271
+ ${cfg.probe ? "if(ctx._probe!==undefined)ctx._probe.best=pb??null\n" : ""}if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
7784
8272
  EC.e=pos
7785
8273
  return null
7786
8274
  }`;
@@ -7851,7 +8339,7 @@ return v
7851
8339
  );
7852
8340
  } else {
7853
8341
  const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
7854
- parts.push(emitTerm(callee, vn, tmp(), L, skipFor(L)));
8342
+ parts.push(holdsGap(code, k, base, n, i, nullable2) ? emitHoldTerm(callee, vn, tmp(), L, skipFor(L)) : emitTerm(callee, vn, tmp(), L, skipFor(L)));
7855
8343
  }
7856
8344
  names.push(vn);
7857
8345
  }
@@ -8334,6 +8822,26 @@ return nd
8334
8822
  const trailingTrivia = (flags & 128) !== 0;
8335
8823
  const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
8336
8824
  const leanFlags = flags & ~128;
8825
+ if (build !== void 0 && passCollapse(code, ip, hostCst)) {
8826
+ return `${head}
8827
+ const v=${child}(input,pos,ctx)
8828
+ if(v!==undefined)return v
8829
+ return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
8830
+ }`;
8831
+ }
8832
+ const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
8833
+ const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(labels.at(code[ip + 2]).tri, t.trivia);
8834
+ const gp = gated !== void 0 && triviaLead !== void 0 && triviaLead.length <= 16 ? `const gc=lead(input,pos)
8835
+ if(!(${[
8836
+ ...gated.leads.map((g) => `!(${gateMissTest(g)})`),
8837
+ ...gated.lits.map((i) => `gc===${k[i].codePointAt(0)}`),
8838
+ ...triviaLead.map((r) => r.lo === r.hi ? `gc===${r.lo}` : `(gc>=${r.lo}&&gc<=${r.hi})`)
8839
+ ].join("||") || "false"})){
8840
+ const gv=${link(gated.last)}(input,pos,ctx)
8841
+ if(gv!==undefined)return gv
8842
+ return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
8843
+ }
8844
+ ` : "";
8337
8845
  if (!hostCst && !tracked && build !== void 0 && proj < 0 && (leanFlags === 2 || (flags === 18 || flags === 34))) {
8338
8846
  const fields = flags === 18;
8339
8847
  const collapseChildren = flags === 34;
@@ -8368,7 +8876,7 @@ sCh.push(nd)
8368
8876
  if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
8369
8877
  }`;
8370
8878
  return `${head}
8371
- const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
8879
+ ${gp}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
8372
8880
  const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
8373
8881
  const flat=[]
8374
8882
  ctx._cstBuf=undefined
@@ -8443,7 +8951,7 @@ const hostKids=kids
8443
8951
  const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
8444
8952
  const tlog=buf.tl??EMPTY_TLOG`;
8445
8953
  return `${head}
8446
- const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
8954
+ ${!hostCst && !tracked ? gp : ""}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
8447
8955
  const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf
8448
8956
  ${openCapture}
8449
8957
  ctx.captureTrivia=${captureWide}
@@ -8513,9 +9021,15 @@ ext:[${externals.join(",")}],
8513
9021
  bind:function(xs,ps){_xScan=xs
8514
9022
  ${externals.map((ip, i) => `_xp${ip}=ps[${i}]`).join("\n")}},
8515
9023
  scan:function(s){const o=_pfScan;_pfScan=s;return o}`;
9024
+ const scannerFor = (ip) => {
9025
+ const ki = labels.at(ip).tri;
9026
+ if (ki === TRI_UNKNOWN) return "_pfScan";
9027
+ if (ki === TRI_NONE) return "null";
9028
+ return swapLegal && !triviaLabelled[ki] && t.triviaScan[ki] != null ? hoist("ts", `TRIVIASCAN[${ki}]`) : "null";
9029
+ };
8516
9030
  const externalDefs = select === void 0 ? "" : `let _xScan
8517
9031
  ${externals.map((ip) => `let _xp${ip}
8518
- function _px${ip}(input,pos,ctx){const o=_xScan(_pfScan);const v=_xp${ip}(input,pos,ctx);_xScan(o);return v}`).join("\n")}
9032
+ function _px${ip}(input,pos,ctx){const o=_xScan(${scannerFor(ip)});const v=_xp${ip}(input,pos,ctx);_xScan(o);return v}`).join("\n")}
8519
9033
  `;
8520
9034
  const source = `${RUNTIME_PRELUDE}${needsNoRawPrelude ? NO_RAW_RUNTIME_PRELUDE : ""}
8521
9035
  ${prelude.join("\n")}
@@ -8562,37 +9076,120 @@ finish:_finish${hybrid}
8562
9076
  };
8563
9077
  }
8564
9078
 
8565
- // src/table/run-support.ts
8566
- function lineCol(ctx, offset) {
8567
- const starts = ctx._lineStarts ?? [0];
8568
- let lo = 0, hi = starts.length - 1;
8569
- while (lo < hi) {
8570
- const mid = lo + hi + 1 >> 1;
8571
- if (starts[mid] <= offset) lo = mid;
8572
- else hi = mid - 1;
9079
+ // src/table/fail-clean.ts
9080
+ function passChild(code, ip) {
9081
+ switch (code[ip]) {
9082
+ case OP_RULE:
9083
+ case OP_LABEL:
9084
+ case OP_COV:
9085
+ case OP_TOKEN:
9086
+ return code[ip + 1];
9087
+ case OP_GATE:
9088
+ case OP_NODE:
9089
+ case OP_NODE_TRACK:
9090
+ case OP_XFORM:
9091
+ case OP_FIELD:
9092
+ case OP_SCOPE:
9093
+ case OP_SCOPE_CAP:
9094
+ case OP_SCOPE_PLAIN:
9095
+ case OP_WITHCTX:
9096
+ case OP_LEAF:
9097
+ case OP_SOURCE_LEAF:
9098
+ return code[ip + 2];
9099
+ default:
9100
+ return -1;
8573
9101
  }
8574
- return [lo + 1, offset - starts[lo] + 1];
8575
9102
  }
8576
- function spanLines(ctx, start, end) {
8577
- const s = lineCol(ctx, start), e = lineCol(ctx, end);
8578
- return { start, end, startLine: s[0], startColumn: s[1], endLine: e[0], endColumn: e[1] };
8579
- }
8580
- function rawEntry(v, input, s, e) {
8581
- if (typeof v === "object" && v !== null) {
8582
- const tg = v._tag;
8583
- if (tg === "node" || tg === "leaf" || tg === "parseError") return v;
8584
- }
8585
- return {
8586
- _tag: "leaf",
8587
- value: typeof v === "string" ? v : typeof v === "object" && v !== null ? input.slice(s, e) : "",
8588
- span: { start: s, end: e }
9103
+ function seqCount(code, ip) {
9104
+ const op = code[ip];
9105
+ return op === OP_SEQ || op === OP_SEQV ? ip + 1 : op === OP_SEQX ? ip + 2 : -1;
9106
+ }
9107
+ function failCleanAnalysis(code) {
9108
+ const cleanAt = new Uint8Array(code.length);
9109
+ const neverAt = new Uint8Array(code.length);
9110
+ const neverFails = (ip) => {
9111
+ const hit = neverAt[ip];
9112
+ if (hit !== 0) return hit === 1;
9113
+ neverAt[ip] = 3;
9114
+ let out = false;
9115
+ const op = code[ip];
9116
+ if (op === OP_OPT || op === OP_EMPTY || op === OP_EXPECT) out = true;
9117
+ else if (op === OP_REP || op === OP_REPV) out = code[ip + 2] === 0;
9118
+ else {
9119
+ const at = seqCount(code, ip);
9120
+ if (at >= 0) {
9121
+ out = true;
9122
+ for (let i = 1, n = code[at]; out && i <= n; i++) out = neverFails(code[at + i]);
9123
+ } else if (op !== OP_GATE) {
9124
+ const c = passChild(code, ip);
9125
+ out = c >= 0 && neverFails(c);
9126
+ }
9127
+ }
9128
+ neverAt[ip] = out ? 1 : 2;
9129
+ return out;
8589
9130
  };
8590
- }
8591
- function lead(input, pos) {
8592
- if (pos >= input.length) return -1;
8593
- const c = input.charCodeAt(pos);
8594
- if (c < 55296 || c > 56319) return c;
8595
- return input.codePointAt(pos) ?? c;
9131
+ const clean = (ip) => {
9132
+ const hit = cleanAt[ip];
9133
+ if (hit !== 0) return hit === 1;
9134
+ cleanAt[ip] = 3;
9135
+ let out = false;
9136
+ switch (code[ip]) {
9137
+ // A terminal pushes its leaf only on a match; NOT/PEEK/ATTEMPT restore
9138
+ // their own mark; OPT, EMPTY and EXPECT do not fail uncommitted.
9139
+ case OP_LIT:
9140
+ case OP_RX:
9141
+ case OP_LIT_TRACK:
9142
+ case OP_RX_TRACK:
9143
+ case OP_LIT_CI:
9144
+ case OP_LIT_CI_TRACK:
9145
+ case OP_GUARD:
9146
+ case OP_NOT:
9147
+ case OP_PEEK:
9148
+ case OP_ATTEMPT:
9149
+ case OP_EMPTY:
9150
+ case OP_OPT:
9151
+ case OP_EXPECT:
9152
+ out = true;
9153
+ break;
9154
+ // Min 0 does not fail uncommitted; min 1 fails only with no item kept, and
9155
+ // restores the failed item itself.
9156
+ case OP_REP:
9157
+ case OP_REPV:
9158
+ out = code[ip + 2] <= 1;
9159
+ break;
9160
+ // Only the first term may fail: a later one fails after the terms before it
9161
+ // wrote, and after the trivia scanned in front of it.
9162
+ case OP_SEQ:
9163
+ case OP_SEQV:
9164
+ case OP_SEQX: {
9165
+ const at = seqCount(code, ip);
9166
+ const n = code[at];
9167
+ out = n > 0 && clean(code[at + 1]);
9168
+ for (let i = 2; out && i <= n; i++) out = neverFails(code[at + i]);
9169
+ break;
9170
+ }
9171
+ case OP_CHOICE: {
9172
+ out = true;
9173
+ for (let i = 0, n = code[ip + 2]; out && i < n; i++) out = clean(code[ip + 4 + i]);
9174
+ break;
9175
+ }
9176
+ case OP_ROUTED:
9177
+ out = code[ip + 1] < 0 || clean(code[ip + 1]);
9178
+ break;
9179
+ // An arm's failure and the fallback's are committed; only the selector's is
9180
+ // not, and without a fallback an unknown key fails after the selector wrote.
9181
+ case OP_DISPATCH:
9182
+ out = code[ip + 3] >= 0 && clean(code[ip + 1]);
9183
+ break;
9184
+ default: {
9185
+ const c = passChild(code, ip);
9186
+ out = c >= 0 && clean(c);
9187
+ }
9188
+ }
9189
+ cleanAt[ip] = out ? 1 : 2;
9190
+ return out;
9191
+ };
9192
+ return clean;
8596
9193
  }
8597
9194
 
8598
9195
  // src/cst/host-mode.ts
@@ -8764,6 +9361,7 @@ function assemble(t, prog, cfg) {
8764
9361
  const swapLegal = !cfg.trackLines;
8765
9362
  const hostCst = cfg.hostCst;
8766
9363
  const REC = prog.rec === 1 && cfg.tolerant;
9364
+ const PROBE = cfg.probe;
8767
9365
  const sentinels = /* @__PURE__ */ new Map();
8768
9366
  function sentinelFor(cls) {
8769
9367
  if (cls < 0) return void 0;
@@ -8809,6 +9407,8 @@ function assemble(t, prog, cfg) {
8809
9407
  }
8810
9408
  const memo = /* @__PURE__ */ new Map();
8811
9409
  const reached = /* @__PURE__ */ new Set();
9410
+ const NULLABLE = /* @__PURE__ */ new Map();
9411
+ const CLEAN = REC ? () => false : failCleanAnalysis(code);
8812
9412
  function pushLeaf(ctx, value, s, e) {
8813
9413
  const lf = { _tag: "leaf", value, span: { start: s, end: e } };
8814
9414
  pushCstLeaf(ctx, lf);
@@ -9007,6 +9607,22 @@ function assemble(t, prog, cfg) {
9007
9607
  return node;
9008
9608
  };
9009
9609
  }
9610
+ function passCollapseNode(child, build, readsRaw) {
9611
+ return (input, pos, ctx) => {
9612
+ const v = child(input, pos, ctx);
9613
+ if (v !== void 0) return v;
9614
+ return collapseEmpty(ctx, build, input, pos, EC.e, readsRaw);
9615
+ };
9616
+ }
9617
+ function gatedPassCollapseNode(blockers, last, classic, build, readsRaw) {
9618
+ return (input, pos, ctx) => {
9619
+ const c = lead(input, pos);
9620
+ for (let i = 0; i < blockers.length; i++) if (classHas2(blockers[i], c)) return classic(input, pos, ctx);
9621
+ const v = last(input, pos, ctx);
9622
+ if (v !== void 0) return v;
9623
+ return collapseEmpty(ctx, build, input, pos, EC.e, readsRaw);
9624
+ };
9625
+ }
9010
9626
  function plainProjectNode(child, projection, type) {
9011
9627
  return (input, pos, ctx) => {
9012
9628
  const sCh = ctx._cstChildren;
@@ -9377,21 +9993,27 @@ function assemble(t, prog, cfg) {
9377
9993
  }
9378
9994
  function dispatchBranch(child, usesRouted) {
9379
9995
  if (!usesRouted) {
9380
- return (input, _pos, selEnd, key, _selectorMark, ctx) => {
9381
- const mark = saveTriviaMark(ctx);
9996
+ return (input, _pos, selEnd, key, ctx) => {
9997
+ const need = markCst(ctx);
9998
+ const mRaw = MRAW;
9999
+ const mTl = MTL;
10000
+ const mLv = MLV;
10001
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
10002
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
10003
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
10004
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
9382
10005
  const v = child(input, selEnd, ctx);
9383
10006
  if (v === FAIL) {
9384
- rollbackTrivia(ctx, mark);
10007
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9385
10008
  ctx._fc = true;
9386
10009
  return FAIL;
9387
10010
  }
9388
10011
  return [key, v];
9389
10012
  };
9390
10013
  }
9391
- return (input, pos, selEnd, key, selectorMark, ctx) => {
10014
+ return (input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot) => {
9392
10015
  const savedRouted = ctx._routed;
9393
- rollbackTrivia(ctx, selectorMark);
9394
- const mark = saveTriviaMark(ctx);
10016
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9395
10017
  ctx._routed = { value: key, span: { start: pos, end: selEnd } };
9396
10018
  let v;
9397
10019
  try {
@@ -9400,7 +10022,7 @@ function assemble(t, prog, cfg) {
9400
10022
  ctx._routed = savedRouted;
9401
10023
  }
9402
10024
  if (v === FAIL) {
9403
- rollbackTrivia(ctx, mark);
10025
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9404
10026
  ctx._fc = true;
9405
10027
  return FAIL;
9406
10028
  }
@@ -9408,12 +10030,12 @@ function assemble(t, prog, cfg) {
9408
10030
  };
9409
10031
  }
9410
10032
  function dispatchArmBlock(start, a0, a1, a2, a3, next) {
9411
- return (arm, input, pos, selEnd, key, selectorMark, ctx) => {
9412
- if (arm === start) return a0(input, pos, selEnd, key, selectorMark, ctx);
9413
- if (arm === start + 1) return a1(input, pos, selEnd, key, selectorMark, ctx);
9414
- if (arm === start + 2) return a2(input, pos, selEnd, key, selectorMark, ctx);
9415
- if (arm === start + 3) return a3(input, pos, selEnd, key, selectorMark, ctx);
9416
- return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key, selectorMark, ctx);
10033
+ return (arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot) => {
10034
+ if (arm === start) return a0(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10035
+ if (arm === start + 1) return a1(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10036
+ if (arm === start + 2) return a2(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10037
+ if (arm === start + 3) return a3(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10038
+ return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9417
10039
  };
9418
10040
  }
9419
10041
  function trackLinesInto(ctx, input, end) {
@@ -9432,7 +10054,7 @@ function assemble(t, prog, cfg) {
9432
10054
  if (flight !== void 0) return flight.fwd;
9433
10055
  const selected = HYBRID?.byIp[ip];
9434
10056
  if (selected !== void 0) {
9435
- const piece2 = hybridPiece(selected);
10057
+ const piece2 = scanHandoffNeeded(code, ip, closureLabels) ? hybridPiece(selected) : selected;
9436
10058
  memo.set(ip, piece2);
9437
10059
  reached.add(ip);
9438
10060
  return piece2;
@@ -9443,14 +10065,55 @@ function assemble(t, prog, cfg) {
9443
10065
  target = p;
9444
10066
  } };
9445
10067
  inFlight.set(ip, holder);
9446
- const op = code[ip];
9447
- 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]) : countedPiece(lower(ip), ip);
10068
+ const piece = scopeIsIdentity(code, ip, closureLabels.at(ip)) ? link(code[ip + 2]) : countedPiece(lookaheadLedNode(ip) ?? lower(ip), ip);
9448
10069
  inFlight.delete(ip);
9449
10070
  holder.set(piece);
9450
10071
  memo.set(ip, piece);
9451
10072
  reached.add(ip);
9452
10073
  return piece;
9453
10074
  }
10075
+ let FIRST_DECIDED;
10076
+ let NODE_BODY;
10077
+ const DECIDED = (_input, pos) => {
10078
+ EC.e = pos;
10079
+ return null;
10080
+ };
10081
+ function lookaheadLedNode(ip) {
10082
+ const op = code[ip];
10083
+ if (op !== OP_NODE && op !== OP_NODE_TRACK || hostCst || REC || cfg.probe || cfg.coverage || cfg.trackLines) return void 0;
10084
+ if (passCollapse(code, ip, hostCst) || gatedPassCollapse(code, ip, hostCst) !== void 0) return void 0;
10085
+ const body = code[ip + 2];
10086
+ const bop = code[body];
10087
+ if (bop !== OP_SEQ && bop !== OP_SEQV && bop !== OP_SEQX) return void 0;
10088
+ const base = bop === OP_SEQX ? body + 3 : body + 2;
10089
+ if (code[bop === OP_SEQX ? body + 2 : body + 1] < 2) return void 0;
10090
+ const first = code[base];
10091
+ const negative = code[first] === OP_NOT;
10092
+ const terminal = negative ? scalarTerminalNotChild(code, first) : code[first] === OP_PEEK ? scalarTerminalPeekChild(code, first) : -1;
10093
+ if (terminal < 0) return void 0;
10094
+ const recognize = scalarFor(terminal);
10095
+ const xf = fx[code[first + 2]];
10096
+ FIRST_DECIDED = DECIDED;
10097
+ NODE_BODY = lower(body);
10098
+ const node = lower(ip);
10099
+ NODE_BODY = void 0;
10100
+ return negative ? (input, pos, ctx) => {
10101
+ if (recognize(input, pos) >= 0) {
10102
+ ctx._fe = pos;
10103
+ ctx._fx = xf;
10104
+ EC.e = pos;
10105
+ return FAIL;
10106
+ }
10107
+ return node(input, pos, ctx);
10108
+ } : (input, pos, ctx) => {
10109
+ if (recognize(input, pos) < 0) {
10110
+ ctx._fe = pos;
10111
+ ctx._fx = xf;
10112
+ return FAIL;
10113
+ }
10114
+ return node(input, pos, ctx);
10115
+ };
10116
+ }
9454
10117
  function lower(ip) {
9455
10118
  const op = code[ip];
9456
10119
  switch (op) {
@@ -9995,8 +10658,10 @@ function assemble(t, prog, cfg) {
9995
10658
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
9996
10659
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
9997
10660
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
10661
+ const probeBest = PROBE ? ctx._probe?.best : void 0;
9998
10662
  const v = child(input, pos, ctx);
9999
10663
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10664
+ if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
10000
10665
  if (v === FAIL) {
10001
10666
  EC.e = pos;
10002
10667
  return null;
@@ -10007,6 +10672,20 @@ function assemble(t, prog, cfg) {
10007
10672
  };
10008
10673
  }
10009
10674
  case OP_PEEK: {
10675
+ const scalarChild = scalarTerminalPeekChild(code, ip);
10676
+ if (scalarChild >= 0) {
10677
+ const recognize = scalarFor(scalarChild);
10678
+ const xf2 = fx[code[ip + 2]];
10679
+ return (input, pos, ctx) => {
10680
+ if (recognize(input, pos) < 0) {
10681
+ ctx._fe = pos;
10682
+ ctx._fx = xf2;
10683
+ return FAIL;
10684
+ }
10685
+ EC.e = pos;
10686
+ return null;
10687
+ };
10688
+ }
10010
10689
  const child = link(code[ip + 1]);
10011
10690
  const xf = fx[code[ip + 2]];
10012
10691
  const gate = lookaheadClass(code[ip + 1]);
@@ -10024,8 +10703,10 @@ function assemble(t, prog, cfg) {
10024
10703
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
10025
10704
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
10026
10705
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
10706
+ const probeBest = PROBE ? ctx._probe?.best : void 0;
10027
10707
  const v = child(input, pos, ctx);
10028
10708
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10709
+ if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
10029
10710
  if (v === FAIL) {
10030
10711
  ctx._fe = pos;
10031
10712
  ctx._fx = xf;
@@ -10038,12 +10719,13 @@ function assemble(t, prog, cfg) {
10038
10719
  case OP_OPT: {
10039
10720
  const child = link(code[ip + 1]);
10040
10721
  const gate = lookaheadClass(code[ip + 1]);
10722
+ const childClean = CLEAN(code[ip + 1]);
10041
10723
  return (input, pos, ctx) => {
10042
10724
  if (gate !== null && !classHas2(gate, lead(input, pos))) {
10043
10725
  EC.e = pos;
10044
10726
  return null;
10045
10727
  }
10046
- const need = markCst(ctx);
10728
+ const need = !childClean && markCst(ctx);
10047
10729
  const mRaw = MRAW;
10048
10730
  const mTl = MTL;
10049
10731
  const mLv = MLV;
@@ -10241,6 +10923,9 @@ function assemble(t, prog, cfg) {
10241
10923
  const projection = reducer < 0 ? ~reducer : -1;
10242
10924
  const fn = fused && projection < 0 ? fns[reducer] : void 0;
10243
10925
  const step = closureLabels.at(ip).buf ? nextTermBuffered : nextTerm;
10926
+ const decided = FIRST_DECIDED;
10927
+ FIRST_DECIDED = void 0;
10928
+ const linkFirst = () => decided ?? link(code[base]);
10244
10929
  const runnerBlock = (count, r0, r1, r2, r3, next) => {
10245
10930
  if (count === 1) return (input, cur, ctx, values, inherited) => {
10246
10931
  cur = r0(input, cur, ctx, inherited);
@@ -10286,7 +10971,7 @@ function assemble(t, prog, cfg) {
10286
10971
  };
10287
10972
  };
10288
10973
  if (REC) {
10289
- const first2 = link(code[base]);
10974
+ const first2 = linkFirst();
10290
10975
  const firstSync = sentinelFor(code[base + n]);
10291
10976
  const runnerAt = (i) => {
10292
10977
  const sync = sentinelFor(code[base + n + i]);
@@ -10322,13 +11007,13 @@ function assemble(t, prog, cfg) {
10322
11007
  const bindRunners = (start) => {
10323
11008
  const count = Math.min(4, n - start);
10324
11009
  const at = (offset) => runnerAt(start + offset);
10325
- const never = () => -1;
11010
+ const never2 = () => -1;
10326
11011
  return runnerBlock(
10327
11012
  count,
10328
11013
  at(0),
10329
- count > 1 ? at(1) : never,
10330
- count > 2 ? at(2) : never,
10331
- count > 3 ? at(3) : never,
11014
+ count > 1 ? at(1) : never2,
11015
+ count > 2 ? at(2) : never2,
11016
+ count > 3 ? at(3) : never2,
10332
11017
  start + count < n ? bindRunners(start + count) : void 0
10333
11018
  );
10334
11019
  };
@@ -10378,15 +11063,31 @@ function assemble(t, prog, cfg) {
10378
11063
  let hasAdj = false;
10379
11064
  for (let i = 1; i < n; i++) {
10380
11065
  const kidIp = code[base + i];
10381
- if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp)) {
11066
+ if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp) || holdsGap(code, k, base, n, i, NULLABLE)) {
10382
11067
  hasAdj = true;
10383
11068
  break;
10384
11069
  }
10385
11070
  }
10386
11071
  if (hasAdj) {
10387
- const first2 = link(code[base]);
11072
+ const first2 = linkFirst();
10388
11073
  const runnerAt = (i) => {
10389
11074
  const kidIp = code[base + i];
11075
+ if (holdsGap(code, k, base, n, i, NULLABLE)) {
11076
+ const kid = link(kidIp);
11077
+ return (input, cur, ctx) => {
11078
+ if (ctx.trivia === void 0) {
11079
+ const v2 = kid(input, cur, ctx);
11080
+ if (v2 === FAIL) return -1;
11081
+ TERMV = v2;
11082
+ return EC.e;
11083
+ }
11084
+ const scanEnd = skipTrivia(input, cur, ctx);
11085
+ const v = kid(input, scanEnd, ctx);
11086
+ if (v === FAIL) return -1;
11087
+ TERMV = v;
11088
+ return scanEnd;
11089
+ };
11090
+ }
10390
11091
  if (code[kidIp] !== OP_ADJ) {
10391
11092
  const kid = link(kidIp);
10392
11093
  if (leadingTriviaFieldAt(code, k, kidIp)) {
@@ -10411,13 +11112,13 @@ function assemble(t, prog, cfg) {
10411
11112
  const bindRunners = (start) => {
10412
11113
  const count = Math.min(4, n - start);
10413
11114
  const at = (offset) => runnerAt(start + offset);
10414
- const never = () => -1;
11115
+ const never2 = () => -1;
10415
11116
  return runnerBlock(
10416
11117
  count,
10417
11118
  at(0),
10418
- count > 1 ? at(1) : never,
10419
- count > 2 ? at(2) : never,
10420
- count > 3 ? at(3) : never,
11119
+ count > 1 ? at(1) : never2,
11120
+ count > 2 ? at(2) : never2,
11121
+ count > 3 ? at(3) : never2,
10421
11122
  start + count < n ? bindRunners(start + count) : void 0
10422
11123
  );
10423
11124
  };
@@ -10454,7 +11155,7 @@ function assemble(t, prog, cfg) {
10454
11155
  };
10455
11156
  }
10456
11157
  if (n === 1) {
10457
- const k0 = link(code[base]);
11158
+ const k0 = linkFirst();
10458
11159
  if (fused) {
10459
11160
  return (input, pos, ctx) => {
10460
11161
  const v = k0(input, pos, ctx);
@@ -10476,7 +11177,7 @@ function assemble(t, prog, cfg) {
10476
11177
  };
10477
11178
  }
10478
11179
  if (n === 2) {
10479
- const k0 = link(code[base]), k1 = link(code[base + 1]);
11180
+ const k0 = linkFirst(), k1 = link(code[base + 1]);
10480
11181
  if (fused) {
10481
11182
  return (input, pos, ctx) => {
10482
11183
  const v0 = k0(input, pos, ctx);
@@ -10507,7 +11208,7 @@ function assemble(t, prog, cfg) {
10507
11208
  };
10508
11209
  }
10509
11210
  if (n === 3) {
10510
- const k0 = link(code[base]), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
11211
+ const k0 = linkFirst(), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
10511
11212
  if (fused) {
10512
11213
  return (input, pos, ctx) => {
10513
11214
  const v0 = k0(input, pos, ctx);
@@ -10601,7 +11302,7 @@ function assemble(t, prog, cfg) {
10601
11302
  start + count < n ? bind(start + count) : void 0
10602
11303
  );
10603
11304
  };
10604
- const first = link(code[base]);
11305
+ const first = linkFirst();
10605
11306
  const tail = bind(1);
10606
11307
  const runDirectTerms = (input, pos, ctx, values) => {
10607
11308
  const v0 = first(input, pos, ctx);
@@ -10640,6 +11341,8 @@ function assemble(t, prog, cfg) {
10640
11341
  const n = code[ip + 2];
10641
11342
  const choiceFx = fx[code[ip + 3]];
10642
11343
  const base = ip + 4;
11344
+ for (let i = 0; i < n; i++) link(code[base + i]);
11345
+ const armsClean = CLEAN(ip);
10643
11346
  if (table.exclusive) {
10644
11347
  const ascii = table.ascii;
10645
11348
  const hi = table.hi;
@@ -10779,7 +11482,7 @@ function assemble(t, prog, cfg) {
10779
11482
  if (n === 3) addGate(g2, 4);
10780
11483
  return (input, pos, ctx) => {
10781
11484
  const c = lead(input, pos);
10782
- const need = markCst(ctx);
11485
+ const need = !armsClean && markCst(ctx);
10783
11486
  const mRaw = MRAW;
10784
11487
  const mTl = MTL;
10785
11488
  const mLv = MLV;
@@ -10996,7 +11699,7 @@ function assemble(t, prog, cfg) {
10996
11699
  if (pn !== 0) {
10997
11700
  return (input, pos, ctx) => {
10998
11701
  const c = lead(input, pos);
10999
- const need = markCst(ctx);
11702
+ const need = !armsClean && markCst(ctx);
11000
11703
  const mRaw = MRAW;
11001
11704
  const mTl = MTL;
11002
11705
  const mLv = MLV;
@@ -11053,7 +11756,7 @@ function assemble(t, prog, cfg) {
11053
11756
  }
11054
11757
  return (input, pos, ctx) => {
11055
11758
  const c = lead(input, pos);
11056
- const need = markCst(ctx);
11759
+ const need = !armsClean && markCst(ctx);
11057
11760
  const mRaw = MRAW;
11058
11761
  const mTl = MTL;
11059
11762
  const mLv = MLV;
@@ -11101,7 +11804,7 @@ function assemble(t, prog, cfg) {
11101
11804
  }
11102
11805
  return (input, pos, ctx) => {
11103
11806
  const c = lead(input, pos);
11104
- const need = markCst(ctx);
11807
+ const need = !armsClean && markCst(ctx);
11105
11808
  const mRaw = MRAW;
11106
11809
  const mTl = MTL;
11107
11810
  const mLv = MLV;
@@ -11155,6 +11858,21 @@ function assemble(t, prog, cfg) {
11155
11858
  return lit(input, pos, ctx);
11156
11859
  };
11157
11860
  }
11861
+ case OP_RGATE: {
11862
+ const cls = cc[code[ip + 1]];
11863
+ const xf = fx[code[ip + 3]];
11864
+ const child = link(code[ip + 2]);
11865
+ if (cfg.tolerant || cfg.probe) return child;
11866
+ return (input, pos, ctx) => {
11867
+ const item = ctx._routed;
11868
+ if (item !== void 0 && item.span.start === pos && !classHas2(cls, lead(input, item.span.end))) {
11869
+ ctx._fe = item.span.end;
11870
+ ctx._fx = xf;
11871
+ return FAIL;
11872
+ }
11873
+ return child(input, pos, ctx);
11874
+ };
11875
+ }
11158
11876
  case OP_ARMGATE: {
11159
11877
  const pred = fns[code[ip + 1]];
11160
11878
  const child = link(code[ip + 2]);
@@ -11223,6 +11941,7 @@ function assemble(t, prog, cfg) {
11223
11941
  const itemClass = !REC && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
11224
11942
  const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
11225
11943
  const skipBeforeFirst = sepIp < 0 && min === 0;
11944
+ const itemClean = sepIp < 0 && CLEAN(code[ip + 1]) && !rowNullable(code, k, code[ip + 1], NULLABLE);
11226
11945
  if (REC) {
11227
11946
  const itemFx2 = fx[code[ip + 6]];
11228
11947
  const sepSent = sentinelFor(code[ip + 7]);
@@ -11319,6 +12038,8 @@ function assemble(t, prog, cfg) {
11319
12038
  const out = collect ? [] : void 0;
11320
12039
  const hasTrivia = ctx.trivia !== void 0;
11321
12040
  const needMark = rollbackNeeded(ctx);
12041
+ const markLater = needMark && (!itemClean || hasTrivia);
12042
+ const markFirst = needMark && (!itemClean || hasTrivia && skipBeforeFirst);
11322
12043
  const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
11323
12044
  let cur = pos;
11324
12045
  let count = 0;
@@ -11326,14 +12047,15 @@ function assemble(t, prog, cfg) {
11326
12047
  if (max >= 0 && count >= max) break;
11327
12048
  if (sep !== void 0 && count > 0 && count >= min && cur >= input.length) break;
11328
12049
  if (count >= min && sep === void 0 && !hasTrivia && gateItems && !itemMayStart(input, cur)) break;
11329
- if (needMark) markCst(ctx);
11330
- const mRaw = needMark ? MRAW : 0;
11331
- const mTl = needMark ? MTL : 0;
11332
- const mLv = needMark ? MLV : 0;
11333
- const mFl = needMark ? ctx._fields?.length ?? 0 : 0;
11334
- const mEr = needMark ? ctx._errors?.length ?? 0 : 0;
11335
- const mLog = needMark ? ctx._triviaLog?.length ?? 0 : 0;
11336
- const mRoot = needMark ? ctx._rootTriviaLog?.length ?? 0 : 0;
12050
+ const markIt = count > 0 ? markLater : markFirst;
12051
+ if (markIt) markCst(ctx);
12052
+ const mRaw = markIt ? MRAW : 0;
12053
+ const mTl = markIt ? MTL : 0;
12054
+ const mLv = markIt ? MLV : 0;
12055
+ const mFl = markIt ? ctx._fields?.length ?? 0 : 0;
12056
+ const mEr = markIt ? ctx._errors?.length ?? 0 : 0;
12057
+ const mLog = markIt ? ctx._triviaLog?.length ?? 0 : 0;
12058
+ const mRoot = markIt ? ctx._rootTriviaLog?.length ?? 0 : 0;
11337
12059
  let itemStart = cur;
11338
12060
  let sepEnd = -1;
11339
12061
  const viaRepItem = sep === void 0 && count >= min && (count > 0 || skipBeforeFirst);
@@ -11345,7 +12067,7 @@ function assemble(t, prog, cfg) {
11345
12067
  if (sepLeads) LEAD.at = cur;
11346
12068
  const sv = sep(input, sp, ctx);
11347
12069
  if (sv === FAIL) {
11348
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12070
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11349
12071
  if (committed3(ctx)) return FAIL;
11350
12072
  break;
11351
12073
  }
@@ -11356,25 +12078,25 @@ function assemble(t, prog, cfg) {
11356
12078
  itemStart = skipTrivia(input, itemStart, ctx);
11357
12079
  }
11358
12080
  if (itemStart >= input.length && viaRepItem) {
11359
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12081
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11360
12082
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
11361
12083
  break;
11362
12084
  }
11363
12085
  if (count >= min && gateItems && !itemMayStart(input, itemStart)) {
11364
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12086
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11365
12087
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
11366
12088
  break;
11367
12089
  }
11368
12090
  ctx._fc = false;
11369
12091
  const v = child(input, itemStart, ctx);
11370
12092
  if (v === FAIL) {
11371
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12093
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11372
12094
  if (committed3(ctx)) return FAIL;
11373
12095
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
11374
12096
  break;
11375
12097
  }
11376
12098
  if (EC.e === itemStart && viaRepItem) {
11377
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12099
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11378
12100
  break;
11379
12101
  }
11380
12102
  if (out !== void 0) out.push(v);
@@ -11448,7 +12170,14 @@ function assemble(t, prog, cfg) {
11448
12170
  const runArm = n === 0 ? void 0 : bindArms(0);
11449
12171
  const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted);
11450
12172
  return (input, pos, ctx) => {
11451
- const selectorMark = saveTriviaMark(ctx);
12173
+ const need = markCst(ctx);
12174
+ const mRaw = MRAW;
12175
+ const mTl = MTL;
12176
+ const mLv = MLV;
12177
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
12178
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
12179
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
12180
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
11452
12181
  const selVal = selector(input, pos, ctx);
11453
12182
  if (selVal === FAIL) return FAIL;
11454
12183
  const selEnd = EC.e;
@@ -11460,9 +12189,9 @@ function assemble(t, prog, cfg) {
11460
12189
  ctx._fx = expected;
11461
12190
  return FAIL;
11462
12191
  }
11463
- return runOther(input, pos, selEnd, key, selectorMark, ctx);
12192
+ return runOther(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11464
12193
  }
11465
- return runArm(arm, input, pos, selEnd, key, selectorMark, ctx);
12194
+ return runArm(arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11466
12195
  };
11467
12196
  }
11468
12197
  /* ── node ────────────────────────────────────────────────────────────── */
@@ -11485,9 +12214,9 @@ function assemble(t, prog, cfg) {
11485
12214
  return FAIL;
11486
12215
  }
11487
12216
  const value = regexValue ? input.slice(pos, end) : spec;
11488
- const leaf = { _tag: "leaf", value, span: { start: pos, end } };
11489
- const kids = [leaf];
11490
- const rawKids = [leaf];
12217
+ const leaf2 = { _tag: "leaf", value, span: { start: pos, end } };
12218
+ const kids = [leaf2];
12219
+ const rawKids = [leaf2];
11491
12220
  const span = { start: pos, end };
11492
12221
  EC.e = end;
11493
12222
  const nd = build2(kids, void 0, span, rawKids, EMPTY_TL, void 0);
@@ -11498,7 +12227,8 @@ function assemble(t, prog, cfg) {
11498
12227
  return nd;
11499
12228
  };
11500
12229
  }
11501
- const child = link(code[ip + 2]);
12230
+ const child = NODE_BODY ?? link(code[ip + 2]);
12231
+ NODE_BODY = void 0;
11502
12232
  const proj = code[ip + 4];
11503
12233
  const buildIdx = code[ip + 1];
11504
12234
  const type = k[code[ip + 5]];
@@ -11522,6 +12252,30 @@ function assemble(t, prog, cfg) {
11522
12252
  if (build !== void 0 && proj < 0 && flags === 18) {
11523
12253
  return childrenOnlyFieldsBuildNode(child, build);
11524
12254
  }
12255
+ if (build !== void 0 && passCollapse(code, ip, hostCst)) {
12256
+ return passCollapseNode(child, build, flags === 32);
12257
+ }
12258
+ const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
12259
+ const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(closureLabels.at(code[ip + 2]).tri, trivia2);
12260
+ if (build !== void 0 && gated !== void 0 && triviaLead !== void 0) {
12261
+ const classic = flags === 32 ? collapseBuildNode(child, build) : childrenOnlyCollapseBuildNode(child, build);
12262
+ return gatedPassCollapseNode(
12263
+ [
12264
+ ...gated.leads.map((g) => cc[code[g + 1]]),
12265
+ resolveClass(encodeClassSpec([
12266
+ ...triviaLead,
12267
+ ...gated.lits.map((i) => {
12268
+ const c = k[i].codePointAt(0);
12269
+ return { lo: c, hi: c };
12270
+ })
12271
+ ]))
12272
+ ],
12273
+ link(gated.last),
12274
+ classic,
12275
+ build,
12276
+ flags === 32
12277
+ );
12278
+ }
11525
12279
  if (build !== void 0 && proj < 0 && flags === 32) {
11526
12280
  return collapseBuildNode(child, build);
11527
12281
  }
@@ -11670,6 +12424,8 @@ function assemble(t, prog, cfg) {
11670
12424
  }
11671
12425
  const notChild = scalarTerminalNotChild(code, ip);
11672
12426
  if (notChild >= 0) scalarFor(notChild);
12427
+ const peekChild = scalarTerminalPeekChild(code, ip);
12428
+ if (peekChild >= 0) scalarFor(peekChild);
11673
12429
  }
11674
12430
  const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
11675
12431
  if (pre !== void 0) {
@@ -11729,7 +12485,8 @@ function assemble(t, prog, cfg) {
11729
12485
  t.lexPrograms,
11730
12486
  LEAD,
11731
12487
  triviaFieldCapture,
11732
- skipDeferredTrivia
12488
+ skipDeferredTrivia,
12489
+ collapseEmpty
11733
12490
  );
11734
12491
  emitReached = new Set(pre.reached);
11735
12492
  if (emitted.ext !== void 0) HYBRID = emitted;
@@ -11815,7 +12572,8 @@ function assemble(t, prog, cfg) {
11815
12572
  t.lexPrograms,
11816
12573
  LEAD,
11817
12574
  triviaFieldCapture,
11818
- skipDeferredTrivia
12575
+ skipDeferredTrivia,
12576
+ collapseEmpty
11819
12577
  );
11820
12578
  emitReached = em.reached;
11821
12579
  } catch (e) {
@@ -12073,6 +12831,172 @@ function tableRules(source, metadataOrEntry = {}) {
12073
12831
  return map[entry];
12074
12832
  }
12075
12833
 
12834
+ // src/combinators/grammar.ts
12835
+ function annotateResultLines(result, index) {
12836
+ const annotated = { ...result, span: annotateSpan(result.span, index) };
12837
+ const errors = annotated.errors;
12838
+ if (errors) {
12839
+ ;
12840
+ annotated.errors = errors.map((error) => ({
12841
+ ...error,
12842
+ span: annotateSpan(error.span, index)
12843
+ }));
12844
+ }
12845
+ return annotated;
12846
+ }
12847
+ function createParseLineContext(input, pos) {
12848
+ const lineIndex = createLineIndex();
12849
+ if (pos > 0) recordLineRange(lineIndex, input, 0, pos);
12850
+ return { lineIndex, lineScannedTo: pos };
12851
+ }
12852
+ var TRACK_LINES_ON = () => true;
12853
+ var TRACK_LINES_OFF = () => false;
12854
+ var TRACK_LINES_INHERIT = (ctx) => ctx?.trackLines === true;
12855
+ function parser(opts, root) {
12856
+ const clearTrivia = opts.trivia === null;
12857
+ const opaqueRootCapture = opts.rootCapture === "opaque";
12858
+ if (opaqueRootCapture && opts.trivia === void 0) {
12859
+ throw new TypeError("parser({ rootCapture: 'opaque' }) requires an explicit trivia scope.");
12860
+ }
12861
+ const scopeTrivia = clearTrivia ? void 0 : opts.trivia ?? void 0;
12862
+ const scopeLabels = scopeTrivia?._meta?.triviaKindLabels;
12863
+ const refuseUnclassified = scopeTrivia !== void 0 && !scopeTrivia._meta?.rootTriviaClassified && !opaqueRootCapture;
12864
+ const forceCaptureTrivia = opts.captureTrivia === true;
12865
+ const trackLinesPolicy = opts.trackLines === true ? "on" : opts.trackLines === false ? "off" : "inherit";
12866
+ const trackLinesOf = trackLinesPolicy === "on" ? TRACK_LINES_ON : trackLinesPolicy === "off" ? TRACK_LINES_OFF : TRACK_LINES_INHERIT;
12867
+ const captureKinds = clearTrivia ? void 0 : opts.captureTriviaKinds;
12868
+ const ownCaptureMask = captureKinds === void 0 ? void 0 : scopeLabels !== void 0 ? triviaKindMask(scopeLabels, captureKinds) : void 0;
12869
+ const inheritCaptureMask = captureKinds !== void 0 && scopeLabels === void 0;
12870
+ const rootScalar = scalarOf(root);
12871
+ const scalarEligible = opts.trackLines !== true && opts.recover !== true && !opaqueRootCapture && !forceCaptureTrivia && captureKinds === void 0;
12872
+ const parseScalar = scalarEligible ? (input, pos, ctx) => {
12873
+ const savedTrivia = ctx.trivia;
12874
+ const savedLabels = ctx.triviaKindLabels;
12875
+ if (clearTrivia) {
12876
+ ctx.trivia = void 0;
12877
+ ctx.triviaKindLabels = void 0;
12878
+ } else if (scopeTrivia !== void 0) {
12879
+ ctx.trivia = scopeTrivia;
12880
+ ctx.triviaKindLabels = scopeLabels;
12881
+ }
12882
+ const end = rootScalar(input, pos, ctx);
12883
+ ctx.trivia = savedTrivia;
12884
+ ctx.triviaKindLabels = savedLabels;
12885
+ return end;
12886
+ } : void 0;
12887
+ let publicScalar;
12888
+ const grammar = {
12889
+ _tag: "grammar",
12890
+ _meta: {
12891
+ ...root._meta,
12892
+ // Trivia classification describes this grammar's own active trivia
12893
+ // scope. A directly nested grammar may have classified trivia of its
12894
+ // own, but that must not advertise classification for this wrapper.
12895
+ triviaKindLabels: void 0,
12896
+ rootTriviaClassified: void 0,
12897
+ ...opts.trivia?._meta?.triviaKindLabels ? { triviaKindLabels: opts.trivia._meta.triviaKindLabels } : {},
12898
+ ...opts.trivia?._meta?.rootTriviaClassified ? { rootTriviaClassified: true } : {}
12899
+ },
12900
+ _def: {
12901
+ tag: "grammar",
12902
+ parser: root,
12903
+ triviaParser: scopeTrivia,
12904
+ clearTrivia,
12905
+ ...opaqueRootCapture ? { rootCapture: "opaque" } : {},
12906
+ ...opts.captureTrivia ? { captureTrivia: true } : {},
12907
+ trackLines: opts.trackLines ?? false,
12908
+ constructionTrackLines: trackLinesPolicy,
12909
+ ...captureKinds === void 0 ? {} : { constructionCaptureTriviaKinds: captureKinds }
12910
+ },
12911
+ _parseScalar: parseScalar,
12912
+ parse(input, pos, _ctx) {
12913
+ if (pos === void 0 && _ctx === void 0) {
12914
+ publicScalar ??= scalarRootOf(grammar) ?? null;
12915
+ if (publicScalar) {
12916
+ const ctx2 = createParseContext();
12917
+ const end = publicScalar(input, 0, ctx2);
12918
+ if (end < 0) {
12919
+ const at = ~end;
12920
+ return { ok: false, expected: ctx2._fx ?? [], span: { start: at, end: at } };
12921
+ }
12922
+ return { ok: true, value: ctx2._sv, span: { start: 0, end } };
12923
+ }
12924
+ }
12925
+ if (refuseUnclassified) refuseUnclassifiedRootScope(_ctx?._rootTriviaStrictScopes);
12926
+ const trackLines = trackLinesOf(_ctx);
12927
+ const lineContext = trackLines && _ctx?._lineIndex === void 0 && _ctx?._lineStarts === void 0 ? createParseLineContext(input, pos ?? 0) : void 0;
12928
+ const lineIndex = trackLines ? _ctx?._lineIndex ?? (_ctx?._lineStarts ? { lineStarts: _ctx._lineStarts } : lineContext.lineIndex) : void 0;
12929
+ const ctx = _ctx === void 0 ? createParseContext() : { ..._ctx };
12930
+ ctx.trackLines = trackLines;
12931
+ if (lineIndex) ctx._lineIndex = lineIndex;
12932
+ if (lineContext) ctx._lineScannedTo = lineContext.lineScannedTo;
12933
+ if (clearTrivia) {
12934
+ ctx.trivia = void 0;
12935
+ ctx.triviaKindLabels = void 0;
12936
+ } else if (scopeTrivia !== void 0) {
12937
+ ctx.trivia = scopeTrivia;
12938
+ if (scopeLabels) ctx.triviaKindLabels = scopeLabels;
12939
+ }
12940
+ if (forceCaptureTrivia || _ctx?.captureTrivia) ctx.captureTrivia = true;
12941
+ if (ownCaptureMask !== void 0) ctx._triviaCaptureMask = ownCaptureMask;
12942
+ else if (inheritCaptureMask) ctx._triviaCaptureMask = triviaKindMask(_ctx?.triviaKindLabels, captureKinds);
12943
+ if (opaqueRootCapture) ctx._rootTriviaCapture = false;
12944
+ const result = root.parse(input, pos ?? 0, ctx);
12945
+ if (trackLines && _ctx && ctx._lineScannedTo !== void 0) {
12946
+ _ctx._lineScannedTo = Math.max(_ctx._lineScannedTo ?? 0, ctx._lineScannedTo);
12947
+ }
12948
+ return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
12949
+ }
12950
+ };
12951
+ return grammar;
12952
+ }
12953
+ function noTrivia(root) {
12954
+ return parser({ trivia: null }, root);
12955
+ }
12956
+
12957
+ // src/combinators/attempt.ts
12958
+ function containOption(options) {
12959
+ if (options === void 0) return false;
12960
+ for (const key of Object.keys(options)) {
12961
+ if (key !== "contain") throw new TypeError(`attempt(): unknown option ${JSON.stringify(key)}`);
12962
+ }
12963
+ if (options.contain !== void 0 && typeof options.contain !== "boolean") {
12964
+ throw new TypeError("attempt(): `contain` must be a boolean");
12965
+ }
12966
+ return options.contain === true;
12967
+ }
12968
+ function attempt(parser2, options) {
12969
+ const contain = containOption(options);
12970
+ const guardable = parser2._meta.firstSet.kind !== "any" && !matchesEmpty(parser2);
12971
+ let failExpected;
12972
+ return {
12973
+ _tag: "attempt",
12974
+ _meta: parser2._meta,
12975
+ _def: contain ? { tag: "attempt", parser: parser2, contain: true } : { tag: "attempt", parser: parser2 },
12976
+ parse(input, pos, ctx) {
12977
+ if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(parser2, input, pos)) {
12978
+ if (failExpected === void 0) {
12979
+ const e = deriveExpected(parser2);
12980
+ failExpected = e.length > 0 ? e : [parser2._tag];
12981
+ }
12982
+ return { ok: false, expected: failExpected, span: { start: pos, end: pos } };
12983
+ }
12984
+ const mark = saveCstMark(ctx);
12985
+ const log = ctx._triviaLog?.length;
12986
+ const rootLog = ctx._rootTriviaLog?.length;
12987
+ const split = ctx._columnsSplit;
12988
+ const result = parser2.parse(input, pos, ctx);
12989
+ if (result.ok) return result;
12990
+ rollbackCstCapture(ctx, mark);
12991
+ ctx._columnsSplit = split;
12992
+ if (log !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== log) ctx._triviaLog.length = log;
12993
+ if (rootLog !== void 0 && ctx._rootTriviaLog && ctx._rootTriviaLog.length !== rootLog) ctx._rootTriviaLog.length = rootLog;
12994
+ if (result.committed && !contain) return result;
12995
+ return { ok: false, expected: result.expected, span: { start: pos, end: pos } };
12996
+ }
12997
+ };
12998
+ }
12999
+
12076
13000
  // src/analysis/gating.ts
12077
13001
  function childrenOf(d) {
12078
13002
  switch (d.tag) {
@@ -12540,6 +13464,111 @@ function reachesMarked(root, successors, memo) {
12540
13464
  return found[visit(root)];
12541
13465
  }
12542
13466
 
13467
+ // src/table/factor-choice.ts
13468
+ var DERIVED = /* @__PURE__ */ new Set(["_tag", "_meta", "_def", "_parseScalar", "_stickyRegex", "parse"]);
13469
+ function isCombinator(v) {
13470
+ return typeof v === "object" && v !== null && "_def" in v && "_meta" in v;
13471
+ }
13472
+ function sameComb(a, b, depth) {
13473
+ if (a === b) return true;
13474
+ if (depth > 32 || a._tag !== b._tag) return false;
13475
+ for (const k of Object.keys(a)) if (!DERIVED.has(k)) return false;
13476
+ for (const k of Object.keys(b)) if (!DERIVED.has(k)) return false;
13477
+ return sameFields(a._def, b._def, depth, void 0);
13478
+ }
13479
+ function sameValue(u, v, depth) {
13480
+ if (u === v) return true;
13481
+ if (isCombinator(u) && isCombinator(v)) return sameComb(u, v, depth + 1);
13482
+ if (Array.isArray(u) && Array.isArray(v)) return u.length === v.length && u.every((x, i) => sameValue(x, v[i], depth));
13483
+ if (typeof u === "object" && u !== null && typeof v === "object" && v !== null && Object.getPrototypeOf(u) === Object.prototype && Object.getPrototypeOf(v) === Object.prototype) {
13484
+ return sameFields(u, v, depth, void 0);
13485
+ }
13486
+ return false;
13487
+ }
13488
+ function sameFields(x, y, depth, skip) {
13489
+ const kx = Object.keys(x).filter((k) => k !== skip && x[k] !== void 0);
13490
+ const ky = Object.keys(y).filter((k) => k !== skip && y[k] !== void 0);
13491
+ if (kx.length !== ky.length) return false;
13492
+ for (const k of kx) {
13493
+ if (!(k in y)) return false;
13494
+ const u = x[k];
13495
+ const v = y[k];
13496
+ if (k === "fn" && typeof u === "function" && typeof v === "function" && u !== v) {
13497
+ if (typeof x.fnSrc !== "string" || x.fnSrc === "" || x.fnSrc !== y.fnSrc) return false;
13498
+ continue;
13499
+ }
13500
+ if (!sameValue(u, v, depth)) return false;
13501
+ }
13502
+ return true;
13503
+ }
13504
+ function rewrap(w, body) {
13505
+ const d = w._def;
13506
+ let out;
13507
+ if (d.tag === "leaf") {
13508
+ out = d.cstValue === "source" ? sourceLeaf(body, d.fn) : leaf(body, d.fn);
13509
+ if (d.fnSrc !== void 0) out._def.fnSrc = d.fnSrc;
13510
+ } else if (d.tag === "grammar") {
13511
+ out = d.clearTrivia === true ? noTrivia(body) : parser({ trivia: d.triviaParser ?? null }, body);
13512
+ } else return void 0;
13513
+ return sameFields(d, out._def, 0, "parser") ? out : void 0;
13514
+ }
13515
+ function unusedOf(seq) {
13516
+ return seq._def.tag === "sequence" && seq._def.valueUnused === true;
13517
+ }
13518
+ function never(c) {
13519
+ const t = c._def.tag;
13520
+ return t === "optional" || t === "many";
13521
+ }
13522
+ function factorSharedEnds(d) {
13523
+ const arms = d.parsers;
13524
+ if (arms.length < 2) return void 0;
13525
+ if (d.strategy.tag !== "firstMatch" && d.strategy.tag !== "sharedPrefix") return void 0;
13526
+ if (d.gates.some((g) => g !== null) || d.autoNot.some((a) => a !== null)) return void 0;
13527
+ const shapes = [];
13528
+ for (const arm of arms) {
13529
+ const wrappers = [];
13530
+ let c = arm;
13531
+ while ((c._def.tag === "leaf" || c._def.tag === "grammar") && wrappers.length < 4) {
13532
+ wrappers.push(c);
13533
+ c = c._def.parser;
13534
+ }
13535
+ if (c._def.tag !== "sequence" || c._def.parsers.length < 2) return void 0;
13536
+ shapes.push({ wrappers, terms: c._def.parsers, seq: c });
13537
+ }
13538
+ const first = shapes[0];
13539
+ const n = first.terms.length;
13540
+ for (const s of shapes) {
13541
+ if (s.wrappers.length !== first.wrappers.length || s.terms.length !== n) return void 0;
13542
+ if (unusedOf(s.seq) !== unusedOf(first.seq)) return void 0;
13543
+ for (let j = 0; j < s.wrappers.length; j++) {
13544
+ const a = first.wrappers[j]._def;
13545
+ const b = s.wrappers[j]._def;
13546
+ if (a.tag !== b.tag || !sameFields(a, b, 0, "parser")) return void 0;
13547
+ }
13548
+ }
13549
+ let at = -1;
13550
+ for (let i = 0; i < n; i++) {
13551
+ if (shapes.every((s) => sameComb(s.terms[i], first.terms[i], 0))) continue;
13552
+ if (at >= 0) return void 0;
13553
+ at = i;
13554
+ }
13555
+ if (at < 0) return void 0;
13556
+ for (let i = at + 1; i < n; i++) if (!never(first.terms[i])) return void 0;
13557
+ if (arms.some((a) => mayCommitFailure(a))) return void 0;
13558
+ const middle = choice(...shapes.map((s) => s.terms[at]));
13559
+ if (middle._def.tag === "choice" && middle._def.autoNot.some((a) => a !== null)) return void 0;
13560
+ const st = middle._def.tag === "choice" ? middle._def.strategy : void 0;
13561
+ if (st === void 0 || st.tag !== "firstMatch" && st.tag !== "sharedPrefix" && !(st.tag === "literalsLongestFirst" && st.sortedIndices.every((x, i) => x === i))) return void 0;
13562
+ let out = sequence(
13563
+ ...[...first.terms.slice(0, at), middle, ...first.terms.slice(at + 1)]
13564
+ );
13565
+ if (unusedOf(first.seq)) {
13566
+ out._def.valueUnused = true;
13567
+ }
13568
+ for (let j = first.wrappers.length - 1; j >= 0 && out !== void 0; j--) out = rewrap(first.wrappers[j], out);
13569
+ return out === void 0 ? void 0 : attempt(out);
13570
+ }
13571
+
12543
13572
  // src/compiler/direct-projection.ts
12544
13573
  function directArrayProjection(fn, fnSrc, arity) {
12545
13574
  let source = fnSrc;
@@ -12600,8 +13629,11 @@ function selectOptionalSuffixLexBody(ir) {
12600
13629
  const token2 = { strategy: "token", estimatedOps: 2, body };
12601
13630
  return token2.estimatedOps < character.estimatedOps ? token2 : character;
12602
13631
  }
12603
- function directTokenBodyParser(parser, resolve) {
12604
- const outer = parser._def;
13632
+ function reinstallsRuleTrivia(reference, target) {
13633
+ return (reference._meta.grammarTrivia ?? target._meta.grammarTrivia) !== void 0 && hasOwnTriviaBoundary(target);
13634
+ }
13635
+ function directTokenBodyParser(parser2, resolve, scope) {
13636
+ const outer = parser2._def;
12605
13637
  if (outer.tag !== "token") return void 0;
12606
13638
  let body = outer.parser;
12607
13639
  const seen = /* @__PURE__ */ new Set();
@@ -12610,12 +13642,13 @@ function directTokenBodyParser(parser, resolve) {
12610
13642
  const wrapper = body._def;
12611
13643
  if (wrapper.tag === "grammar") {
12612
13644
  if (wrapper.clearTrivia !== true || wrapper.triviaParser !== void 0 || wrapper.captureTrivia === true || wrapper.rootCapture === "opaque" || wrapper.constructionTrackLines !== "inherit" || wrapper.constructionCaptureTriviaKinds !== void 0) return void 0;
13645
+ if (scope !== void 0) scope.cleared = true;
12613
13646
  body = wrapper.parser;
12614
13647
  continue;
12615
13648
  }
12616
13649
  if (wrapper.tag === "lazy") {
12617
13650
  const target = resolvedLazyTarget(body, resolve);
12618
- if (target === void 0) return void 0;
13651
+ if (target === void 0 || reinstallsRuleTrivia(body, target)) return void 0;
12619
13652
  body = target;
12620
13653
  continue;
12621
13654
  }
@@ -12623,8 +13656,8 @@ function directTokenBodyParser(parser, resolve) {
12623
13656
  }
12624
13657
  return void 0;
12625
13658
  }
12626
- function directOptionalSuffixTokenBody(parser, resolve) {
12627
- const inner = directTokenBodyParser(parser, resolve);
13659
+ function directOptionalSuffixTokenBody(parser2, resolve) {
13660
+ const inner = directTokenBodyParser(parser2, resolve);
12628
13661
  if (inner === void 0) return void 0;
12629
13662
  const sequence6 = inner._def;
12630
13663
  if (sequence6.tag !== "sequence" || sequence6.parsers.length !== 2) return void 0;
@@ -12660,10 +13693,10 @@ function directOptionalSuffixTokenBody(parser, resolve) {
12660
13693
  expected: directTerminalFailureExpected(base)
12661
13694
  } : void 0;
12662
13695
  }
12663
- function directTerminalTokenBody(parser, resolve) {
12664
- const outer = parser._def;
13696
+ function directTerminalTokenBody(parser2, resolve) {
13697
+ const outer = parser2._def;
12665
13698
  if (outer.tag !== "token") return void 0;
12666
- const body = directTokenBodyParser(parser, resolve);
13699
+ const body = directTokenBodyParser(parser2, resolve);
12667
13700
  if (body === void 0) return void 0;
12668
13701
  const def = body._def;
12669
13702
  if (def.tag === "regex") return {
@@ -12683,28 +13716,28 @@ function directTerminalTokenBody(parser, resolve) {
12683
13716
  expected: directTerminalFailureExpected(def)
12684
13717
  };
12685
13718
  }
12686
- function directTerminalParser(parser, resolve) {
13719
+ function directTerminalParser(parser2, resolve) {
12687
13720
  const seen = /* @__PURE__ */ new Set();
12688
- while (!seen.has(parser)) {
12689
- seen.add(parser);
12690
- const def = parser._def;
13721
+ while (!seen.has(parser2)) {
13722
+ seen.add(parser2);
13723
+ const def = parser2._def;
12691
13724
  if (def.tag === "lazy") {
12692
- const target = resolvedLazyTarget(parser, resolve);
13725
+ const target = resolvedLazyTarget(parser2, resolve);
12693
13726
  if (target === void 0) return void 0;
12694
- parser = target;
13727
+ parser2 = target;
12695
13728
  continue;
12696
13729
  }
12697
13730
  if (def.tag === "token") {
12698
- parser = def.parser;
13731
+ parser2 = def.parser;
12699
13732
  continue;
12700
13733
  }
12701
13734
  if (def.tag === "grammar") return void 0;
12702
- return parser;
13735
+ return parser2;
12703
13736
  }
12704
13737
  return void 0;
12705
13738
  }
12706
- function directTerminalLexBody(parser, resolve) {
12707
- const terminal = directTerminalParser(parser, resolve);
13739
+ function directTerminalLexBody(parser2, resolve) {
13740
+ const terminal = directTerminalParser(parser2, resolve);
12708
13741
  if (terminal === void 0) return void 0;
12709
13742
  const def = terminal._def;
12710
13743
  if (def.tag === "literal") {
@@ -12735,8 +13768,8 @@ function directTerminalLexBody(parser, resolve) {
12735
13768
  expected: directTerminalFailureExpected(def)
12736
13769
  };
12737
13770
  }
12738
- function directOrdered4TokenBody(parser, resolve) {
12739
- const body = directTokenBodyParser(parser, resolve);
13771
+ function directOrdered4TokenBody(parser2, resolve) {
13772
+ const body = directTokenBodyParser(parser2, resolve);
12740
13773
  return body === void 0 ? void 0 : directOrdered4Body(body, resolve);
12741
13774
  }
12742
13775
  function directOrdered4Body(body, resolve) {
@@ -12764,8 +13797,8 @@ function directOrdered4Body(body, resolve) {
12764
13797
  arms
12765
13798
  };
12766
13799
  }
12767
- function directNot2TokenBody(parser, resolve) {
12768
- const body = directTokenBodyParser(parser, resolve);
13800
+ function directNot2TokenBody(parser2, resolve) {
13801
+ const body = directTokenBodyParser(parser2, resolve);
12769
13802
  const sequence6 = body?._def;
12770
13803
  if (sequence6?.tag !== "sequence" || sequence6.parsers.length !== 3) return void 0;
12771
13804
  const [guard0Parser, guard1Parser, terminalParser] = sequence6.parsers;
@@ -12787,15 +13820,15 @@ function directNot2TokenBody(parser, resolve) {
12787
13820
  terminal
12788
13821
  };
12789
13822
  }
12790
- function directFixedLexNode(parser, resolve, active, pureOnly = false) {
12791
- let current = parser;
13823
+ function directFixedLexNode(parser2, resolve, active, pureOnly = false, cleared = false) {
13824
+ let current = parser2;
12792
13825
  const wrappers = /* @__PURE__ */ new Set();
12793
13826
  while (!wrappers.has(current)) {
12794
13827
  wrappers.add(current);
12795
13828
  const def = current._def;
12796
13829
  if (def.tag === "lazy") {
12797
13830
  const target = resolvedLazyTarget(current, resolve);
12798
- if (target === void 0) return void 0;
13831
+ if (target === void 0 || reinstallsRuleTrivia(current, target)) return void 0;
12799
13832
  current = target;
12800
13833
  continue;
12801
13834
  }
@@ -12805,7 +13838,7 @@ function directFixedLexNode(parser, resolve, active, pureOnly = false) {
12805
13838
  }
12806
13839
  break;
12807
13840
  }
12808
- if (wrappers.has(current) && current !== parser && current._def.tag === "lazy") return void 0;
13841
+ if (wrappers.has(current) && current !== parser2 && current._def.tag === "lazy") return void 0;
12809
13842
  if (active.has(current)) return void 0;
12810
13843
  active.add(current);
12811
13844
  try {
@@ -12813,30 +13846,33 @@ function directFixedLexNode(parser, resolve, active, pureOnly = false) {
12813
13846
  if (terminal !== void 0) return { kind: "terminal", terminal };
12814
13847
  const def = current._def;
12815
13848
  if (def.tag === "grammar") {
13849
+ if (def.triviaParser === void 0 && def.captureTrivia !== true && def.rootCapture !== "opaque" && def.constructionCaptureTriviaKinds === void 0) {
13850
+ return directFixedLexNode(def.parser, resolve, active, pureOnly, cleared || def.clearTrivia === true);
13851
+ }
12816
13852
  if (!pureOnly || def.parser._def.tag !== "token" && (def.clearTrivia !== true || def.triviaParser !== void 0 || def.captureTrivia === true || def.rootCapture === "opaque")) return void 0;
12817
- return directFixedLexNode(def.parser, resolve, active, true);
13853
+ return directFixedLexNode(def.parser, resolve, active, true, cleared);
12818
13854
  }
12819
13855
  if (def.tag === "sequence") {
12820
13856
  if (def.parsers.length < 2 || def.parsers.length > 5) return void 0;
12821
- const parts = def.parsers.map((part) => directFixedLexNode(part, resolve, active, pureOnly));
13857
+ const parts = def.parsers.map((part) => directFixedLexNode(part, resolve, active, pureOnly, cleared));
12822
13858
  if (parts.some((part) => part === void 0)) return void 0;
12823
13859
  return { kind: "sequence", parts };
12824
13860
  }
12825
13861
  if (def.tag === "choice") {
12826
- if (def.parsers.length !== 2 && def.parsers.length !== 4 && def.parsers.length !== 8 || def.strategy.tag !== "firstMatch" || def.gates.some((gate) => gate !== null) || def.autoNot.some((check) => check !== null)) return void 0;
12827
- const arms = def.parsers.map((arm) => directFixedLexNode(arm, resolve, active, pureOnly));
13862
+ if (def.parsers.length < 2 || def.strategy.tag !== "firstMatch" || def.gates.some((gate) => gate !== null) || def.autoNot.some((check) => check !== null)) return void 0;
13863
+ const arms = def.parsers.map((arm) => directFixedLexNode(arm, resolve, active, pureOnly, cleared));
12828
13864
  if (arms.some((arm) => arm === void 0)) return void 0;
12829
- const final = classifyFinalChoice(def.parsers, resolve);
12830
13865
  return {
12831
13866
  kind: "choice",
12832
13867
  arms,
12833
- firstSets: final.firstSets,
13868
+ parsers: def.parsers,
13869
+ cleared,
12834
13870
  armExpected: def.parsers.map(deriveExpected),
12835
13871
  expected: def.parsers.flatMap(deriveExpected)
12836
13872
  };
12837
13873
  }
12838
13874
  if (def.tag === "not") {
12839
- const body = directFixedLexNode(def.parser, resolve, active, true);
13875
+ const body = directFixedLexNode(def.parser, resolve, active, true, cleared);
12840
13876
  return body === void 0 ? void 0 : {
12841
13877
  kind: "not",
12842
13878
  body,
@@ -12844,23 +13880,33 @@ function directFixedLexNode(parser, resolve, active, pureOnly = false) {
12844
13880
  };
12845
13881
  }
12846
13882
  if (def.tag === "optional") {
12847
- const body = directFixedLexNode(def.parser, resolve, active, pureOnly);
13883
+ const body = directFixedLexNode(def.parser, resolve, active, pureOnly, cleared);
12848
13884
  return body === void 0 ? void 0 : { kind: "optional", body };
12849
13885
  }
13886
+ if (def.tag === "many" || def.tag === "oneOrMore") {
13887
+ const body = directFixedLexNode(def.parser, resolve, active, pureOnly, cleared);
13888
+ return body === void 0 ? void 0 : {
13889
+ kind: "repeat",
13890
+ body,
13891
+ min: def.tag === "many" ? 0 : def.min,
13892
+ max: def.max ?? -1
13893
+ };
13894
+ }
12850
13895
  return void 0;
12851
13896
  } finally {
12852
13897
  active.delete(current);
12853
13898
  }
12854
13899
  }
12855
- function directFixedTokenBody(parser, resolve) {
12856
- const body = directTokenBodyParser(parser, resolve);
13900
+ function directFixedTokenBody(parser2, resolve) {
13901
+ const scope = { cleared: false };
13902
+ const body = directTokenBodyParser(parser2, resolve, scope);
12857
13903
  if (body === void 0) return void 0;
12858
- const root = directFixedLexNode(body, resolve, /* @__PURE__ */ new Set());
13904
+ const root = directFixedLexNode(body, resolve, /* @__PURE__ */ new Set(), false, scope.cleared);
12859
13905
  return root === void 0 ? void 0 : { kind: "fixed-tree", root };
12860
13906
  }
12861
- function directBalancedTokenBody(parser, resolve) {
12862
- if (directTokenBodyParser(parser, resolve) === void 0) return void 0;
12863
- const spec = balancedSpecOf(parser);
13907
+ function directBalancedTokenBody(parser2, resolve) {
13908
+ if (directTokenBodyParser(parser2, resolve) === void 0) return void 0;
13909
+ const spec = balancedSpecOf(parser2);
12864
13910
  return spec === void 0 ? void 0 : {
12865
13911
  kind: "balanced-scan",
12866
13912
  open: spec.open,
@@ -12870,8 +13916,8 @@ function directBalancedTokenBody(parser, resolve) {
12870
13916
  ownSkip: spec.ownSkip
12871
13917
  };
12872
13918
  }
12873
- function directExecutableTokenBody(parser, resolve) {
12874
- return directOptionalSuffixTokenBody(parser, resolve) ?? directTerminalTokenBody(parser, resolve) ?? directOrdered4TokenBody(parser, resolve) ?? directNot2TokenBody(parser, resolve) ?? directBalancedTokenBody(parser, resolve) ?? directFixedTokenBody(parser, resolve);
13919
+ function directExecutableTokenBody(parser2, resolve) {
13920
+ return directOptionalSuffixTokenBody(parser2, resolve) ?? directTerminalTokenBody(parser2, resolve) ?? directOrdered4TokenBody(parser2, resolve) ?? directNot2TokenBody(parser2, resolve) ?? directBalancedTokenBody(parser2, resolve) ?? directFixedTokenBody(parser2, resolve);
12875
13921
  }
12876
13922
  function winnerWrapsReference(winner, reference) {
12877
13923
  let current = winner;
@@ -12885,13 +13931,13 @@ function winnerWrapsReference(winner, reference) {
12885
13931
  }
12886
13932
  return false;
12887
13933
  }
12888
- function resolvedLazyTarget(parser, resolve) {
12889
- const def = parser._def;
13934
+ function resolvedLazyTarget(parser2, resolve) {
13935
+ const def = parser2._def;
12890
13936
  if (def.tag !== "lazy") return void 0;
12891
- const name = parser._ruleName;
13937
+ const name = parser2._ruleName;
12892
13938
  if (name !== void 0 && resolve !== void 0) {
12893
13939
  const winner = resolve(name);
12894
- if (winner !== void 0 && !winnerWrapsReference(winner, parser)) return winner;
13940
+ if (winner !== void 0 && !winnerWrapsReference(winner, parser2)) return winner;
12895
13941
  }
12896
13942
  try {
12897
13943
  return def.thunk();
@@ -12899,8 +13945,8 @@ function resolvedLazyTarget(parser, resolve) {
12899
13945
  return void 0;
12900
13946
  }
12901
13947
  }
12902
- function balancedSpecOf(parser) {
12903
- let current = parser;
13948
+ function balancedSpecOf(parser2) {
13949
+ let current = parser2;
12904
13950
  let spec = current._balancedSpec;
12905
13951
  const seen = /* @__PURE__ */ new Set();
12906
13952
  while (spec === void 0 && current._def.tag === "token" && !seen.has(current)) {
@@ -13102,13 +14148,16 @@ var Encoder = class {
13102
14148
  }
13103
14149
  case "choice": {
13104
14150
  for (const arm of node.arms) if (!emitNode(arm)) return false;
13105
- const op = node.arms.length === 2 ? LEX_NODE_CHOICE2 : node.arms.length === 4 ? LEX_NODE_CHOICE4 : node.arms.length === 8 ? LEX_NODE_CHOICE8 : -1;
13106
- if (op < 0) return false;
13107
- words.push(op, this.expected(node.expected));
14151
+ const final = classifyFinalChoice(
14152
+ node.parsers,
14153
+ this.refResolver(),
14154
+ node.cleared ? void 0 : this.activeTrivia
14155
+ );
14156
+ const classes = final.firstSets.map((first, i) => final.nullable[i] ? -1 : this.charClass(first));
14157
+ const exclusive = final.exclusive && classes.every((cls) => cls >= 0);
14158
+ words.push(LEX_NODE_CHOICE, node.arms.length, exclusive ? 1 : 0, this.expected(node.expected));
13108
14159
  for (let i = 0; i < node.arms.length; i++) {
13109
- const first = node.firstSets[i];
13110
- words.push(first.kind === "ranges" ? this.charClass(first) : -1);
13111
- words.push(this.expected(node.armExpected[i]));
14160
+ words.push(classes[i], this.expected(node.armExpected[i]));
13112
14161
  }
13113
14162
  return true;
13114
14163
  }
@@ -13120,6 +14169,10 @@ var Encoder = class {
13120
14169
  if (!emitNode(node.body)) return false;
13121
14170
  words.push(LEX_NODE_OPTIONAL);
13122
14171
  return true;
14172
+ case "repeat":
14173
+ if (!emitNode(node.body)) return false;
14174
+ words.push(LEX_NODE_REPEAT, node.min, node.max);
14175
+ return true;
13123
14176
  }
13124
14177
  };
13125
14178
  if (!emitNode(body.root)) return void 0;
@@ -13625,6 +14678,51 @@ var Encoder = class {
13625
14678
  if (!hasOwnTriviaBoundary(target)) return ip;
13626
14679
  return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), ip);
13627
14680
  }
14681
+ /**
14682
+ * The `OP_RGATE` operands of a choice arm that opens with `routed()`, or
14683
+ * `undefined`. Through `node()`/scope wrappers and first sequence terms, the
14684
+ * arm's next term after the routed token is found; the gate is that term's
14685
+ * first characters, with the trivia in force at the boundary before it, so
14686
+ * the arm is entered only where it can get past the token. The term must be
14687
+ * unable to match empty or to commit, so a miss is exactly that term failing
14688
+ * at the token's end with its own set.
14689
+ */
14690
+ routedArmGate(arm) {
14691
+ const walk = (p, trivia2, depth) => {
14692
+ if (depth > 16) return void 0;
14693
+ const d = p._def;
14694
+ switch (d.tag) {
14695
+ case "routed":
14696
+ return "end";
14697
+ case "node":
14698
+ return walk(d.parser, trivia2, depth + 1);
14699
+ case "grammar":
14700
+ return walk(d.parser, d.clearTrivia === true ? void 0 : d.triviaParser ?? trivia2, depth + 1);
14701
+ case "sequence": {
14702
+ const head = d.parsers[0];
14703
+ if (head === void 0) return void 0;
14704
+ const r = walk(head, trivia2, depth + 1);
14705
+ if (r !== "end") return r;
14706
+ const next2 = d.parsers[1];
14707
+ return next2 === void 0 ? "end" : { next: next2, boundary: trivia2 };
14708
+ }
14709
+ default:
14710
+ return void 0;
14711
+ }
14712
+ };
14713
+ const follow = walk(arm, this.activeTrivia, 0);
14714
+ if (follow === void 0 || follow === "end") return void 0;
14715
+ const rr = this.refResolver();
14716
+ const { next, boundary } = follow;
14717
+ if (matchesEmpty(next, /* @__PURE__ */ new Set(), rr) || mayCommitFailure(next, rr, this.commitFailureMemo)) return void 0;
14718
+ const nextDef = next._def;
14719
+ if (nextDef.tag !== "literal" && nextDef.tag !== "regex" && nextDef.tag !== "keywords" && nextDef.tag !== "label") return void 0;
14720
+ const first = firstSetOf(next, /* @__PURE__ */ new Set(), rr, boundary);
14721
+ const cls = this.charClass(boundary === void 0 ? first : union(first, firstSetOf(boundary, /* @__PURE__ */ new Set(), rr)));
14722
+ if (cls < 0) return void 0;
14723
+ const miss = nextDef.tag === "label" ? deriveExpected(next) : directTerminalFailureExpected(nextDef);
14724
+ return { cls, fx: this.expected(miss) };
14725
+ }
13628
14726
  node(p) {
13629
14727
  const lazyRef = p._def.tag === "lazy";
13630
14728
  const scopeKey = lazyRef ? this.activeTrivia : void 0;
@@ -13749,6 +14847,10 @@ var Encoder = class {
13749
14847
  return head;
13750
14848
  }
13751
14849
  case "choice": {
14850
+ if (this.plan === void 0) {
14851
+ const factored = factorSharedEnds(d);
14852
+ if (factored !== void 0) return this.node(factored).ip;
14853
+ }
13752
14854
  if (d.strategy.tag === "greedyClassify") {
13753
14855
  const superIndex = d.strategy.superIndex;
13754
14856
  const sup = this.node(d.parsers[superIndex]).ip;
@@ -13772,9 +14874,12 @@ var Encoder = class {
13772
14874
  const kids = arms.map((c, k) => {
13773
14875
  const src = order[k];
13774
14876
  const checks = d.autoNot[src];
13775
- const inner = this.node(c).ip;
13776
- const ip = checks === null || checks === void 0 || checks.length === 0 ? inner : this.reject(inner, checks);
13777
14877
  const gate = d.gates[src];
14878
+ const plain = (checks === null || checks === void 0 || checks.length === 0) && (gate === null || gate === void 0);
14879
+ const routedGate = plain ? this.routedArmGate(c) : void 0;
14880
+ const body = this.node(c).ip;
14881
+ const inner = routedGate === void 0 ? body : this.emit(OP_RGATE, routedGate.cls, body, routedGate.fx);
14882
+ const ip = checks === null || checks === void 0 || checks.length === 0 ? inner : this.reject(inner, checks);
13778
14883
  const gated = gate === null || gate === void 0 ? ip : this.emit(OP_ARMGATE, this.fn(gate, d.gateSrcs?.[src] ?? null), ip, this.expected(deriveExpected(c)));
13779
14884
  return this.covWrap(gated, armCovIds?.[src], 1);
13780
14885
  });
@@ -14098,6 +15203,7 @@ var Encoder = class {
14098
15203
  const slots = (ip) => {
14099
15204
  switch (this.code[ip]) {
14100
15205
  case OP_GATE:
15206
+ case OP_RGATE:
14101
15207
  return [ip + 2];
14102
15208
  case OP_RULE:
14103
15209
  case OP_OPT:
@@ -14268,7 +15374,7 @@ function emitClassPool(classes) {
14268
15374
  if (classes.length < 2) return array;
14269
15375
  const delimiter = "|/~?^`".split("").find((ch2) => classes.every((spec) => !spec.includes(ch2)));
14270
15376
  if (delimiter === void 0) return array;
14271
- const split = `${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
15377
+ const split = `/* @__PURE__ */ ${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
14272
15378
  return split.length < array.length ? split : array;
14273
15379
  }
14274
15380
  function emitConst(v) {
@@ -14551,12 +15657,12 @@ function buildGrammarPlan(entry, winners) {
14551
15657
  }
14552
15658
  }
14553
15659
  }
14554
- const selfWinnerBody = (parser) => {
14555
- if (parser._def.tag !== "lazy" || winners === void 0) return void 0;
14556
- const name = winnerNames.get(parser);
14557
- if (name === void 0 || winners[name] !== parser) return void 0;
15660
+ const selfWinnerBody = (parser2) => {
15661
+ if (parser2._def.tag !== "lazy" || winners === void 0) return void 0;
15662
+ const name = winnerNames.get(parser2);
15663
+ if (name === void 0 || winners[name] !== parser2) return void 0;
14558
15664
  try {
14559
- return parser._def.thunk();
15665
+ return parser2._def.thunk();
14560
15666
  } catch {
14561
15667
  return void 0;
14562
15668
  }
@@ -14568,39 +15674,39 @@ function buildGrammarPlan(entry, winners) {
14568
15674
  if (body !== void 0) slotsPerBody.set(body, (slotsPerBody.get(body) ?? 0) + 1);
14569
15675
  }
14570
15676
  }
14571
- const sharedBody = (parser) => (slotsPerBody.get(parser) ?? 0) > 1;
14572
- const ownRule = (parser, rule) => {
15677
+ const sharedBody = (parser2) => (slotsPerBody.get(parser2) ?? 0) > 1;
15678
+ const ownRule = (parser2, rule) => {
14573
15679
  const id = `rule:${rule}`;
14574
15680
  definitions.set(id, { id, kind: "rule" });
14575
- rules.set(parser, id);
15681
+ rules.set(parser2, id);
14576
15682
  };
14577
15683
  const seen = /* @__PURE__ */ new Set();
14578
- const visit = (parser, path) => {
14579
- if (seen.has(parser)) return;
14580
- seen.add(parser);
14581
- const rule = winnerNames.get(parser) ?? parser._ruleName;
14582
- const body = selfWinnerBody(parser);
14583
- if (rule && body === void 0 && !sharedBody(parser) && (winnerNames.has(parser) || parser._def.tag !== "lazy")) {
14584
- ownRule(parser, rule);
14585
- }
14586
- if (rule && body !== void 0 && sharedBody(body)) ownRule(parser, rule);
14587
- if (parser._def.tag === "choice") {
14588
- const ids = parser._def.parsers.map((_, index) => `choice:${path}/arm:${index}`);
14589
- choices.set(parser, ids);
15684
+ const visit = (parser2, path) => {
15685
+ if (seen.has(parser2)) return;
15686
+ seen.add(parser2);
15687
+ const rule = winnerNames.get(parser2) ?? parser2._ruleName;
15688
+ const body = selfWinnerBody(parser2);
15689
+ if (rule && body === void 0 && !sharedBody(parser2) && (winnerNames.has(parser2) || parser2._def.tag !== "lazy")) {
15690
+ ownRule(parser2, rule);
15691
+ }
15692
+ if (rule && body !== void 0 && sharedBody(body)) ownRule(parser2, rule);
15693
+ if (parser2._def.tag === "choice") {
15694
+ const ids = parser2._def.parsers.map((_, index) => `choice:${path}/arm:${index}`);
15695
+ choices.set(parser2, ids);
14590
15696
  ids.forEach((id) => definitions.set(id, { id, kind: "choice-arm" }));
14591
15697
  }
14592
- if (parser._def.tag === "dispatch") {
14593
- const ids = dispatchArmIds(parser._def, path);
14594
- dispatches.set(parser, ids);
15698
+ if (parser2._def.tag === "dispatch") {
15699
+ const ids = dispatchArmIds(parser2._def, path);
15700
+ dispatches.set(parser2, ids);
14595
15701
  ids.forEach((id) => definitions.set(id, { id, kind: "dispatch-arm" }));
14596
15702
  }
14597
- if (parser._def.tag === "attempt") attempts.set(parser, `attempt:${path}`);
14598
- if (parser._def.tag === "label") {
15703
+ if (parser2._def.tag === "attempt") attempts.set(parser2, `attempt:${path}`);
15704
+ if (parser2._def.tag === "label") {
14599
15705
  const id = `label:${path}`;
14600
- labels.set(parser, [id]);
15706
+ labels.set(parser2, [id]);
14601
15707
  definitions.set(id, { id, kind: "label" });
14602
15708
  }
14603
- children(parser._def, winners).forEach((child, index) => visit(child, `${path}/${parser._def.tag}:${index}`));
15709
+ children(parser2._def, winners).forEach((child, index) => visit(child, `${path}/${parser2._def.tag}:${index}`));
14604
15710
  };
14605
15711
  const roots = Array.isArray(entry) ? entry : [entry];
14606
15712
  for (const root of roots) {
@@ -15994,10 +17100,10 @@ function addNode(out, def) {
15994
17100
  if (!existing.includes(tag)) existing.push(tag);
15995
17101
  }
15996
17102
  }
15997
- function collectFromCombinator(parser, out, seen, followLazy = true) {
15998
- if (seen.has(parser)) return;
15999
- seen.add(parser);
16000
- const def = parser._def;
17103
+ function collectFromCombinator(parser2, out, seen, followLazy = true) {
17104
+ if (seen.has(parser2)) return;
17105
+ seen.add(parser2);
17106
+ const def = parser2._def;
16001
17107
  if (def.tag === "lazy") {
16002
17108
  if (followLazy) {
16003
17109
  try {
@@ -16183,15 +17289,20 @@ function compileRuleMap(ruleMap, opts = {}) {
16183
17289
  throw e;
16184
17290
  }
16185
17291
  const ceiling = budget / SUPERCOMPILE_GROWTH;
17292
+ if (ceiling <= fixed) return none;
16186
17293
  let target = ceiling;
16187
- for (let attempt = 0; attempt < 16; attempt++) {
17294
+ for (; ; ) {
16188
17295
  const sites = selectHotSites(artifact.code, Object.values(artifact.rules), siteBytes, target - fixed, profile);
16189
- if (sites.size === 0) return none;
17296
+ if (sites.size === 0) {
17297
+ return {
17298
+ ...none,
17299
+ refusal: `a site within its ${Math.floor(ceiling)} B selection ceiling (the prelude alone is ${fixed} B)`
17300
+ };
17301
+ }
16190
17302
  const bytes = emitAssemblySource(table, artifact, cfg, roots, true, sites).source.length;
16191
17303
  if (bytes <= ceiling) return { sites, bytes: Math.ceil(bytes * SUPERCOMPILE_GROWTH) };
16192
17304
  target *= Math.min(ceiling / bytes, 0.99);
16193
17305
  }
16194
- return none;
16195
17306
  };
16196
17307
  return {
16197
17308
  keys: ruleMap.map(([key]) => key),
@@ -16279,16 +17390,16 @@ function ownSource(fn) {
16279
17390
  return typeof name === "string" && name.length > 0 && globalThis[name] === fn ? name : null;
16280
17391
  }
16281
17392
  function compile(target, second, third) {
16282
- if (!isCombinator(target)) return compileMap(target, second);
17393
+ if (!isCombinator2(target)) return compileMap(target, second);
16283
17394
  return compileRoot(target, second, third);
16284
17395
  }
16285
- function isCombinator(x) {
17396
+ function isCombinator2(x) {
16286
17397
  return typeof x === "object" && x !== null && typeof x.parse === "function" && "_def" in x;
16287
17398
  }
16288
17399
  function compileMap(grammar, opts = {}) {
16289
17400
  const entries = [];
16290
17401
  for (const [key, value] of Object.entries(grammar)) {
16291
- if (!isCombinator(value)) throw new TypeError(`compile: grammar entry "${key}" is not a parser`);
17402
+ if (!isCombinator2(value)) throw new TypeError(`compile: grammar entry "${key}" is not a parser`);
16292
17403
  if (value._def.tag === "lazy") {
16293
17404
  try {
16294
17405
  value._def.thunk();