parseman 0.57.0 → 0.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/analysis/diagnostics.js +1799 -962
  2. package/dist/analysis/diagnostics.js.map +3 -3
  3. package/dist/cli/index.js +1928 -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 +1016 -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 +1209 -236
  17. package/dist/plugin/index.js.map +3 -3
  18. package/dist/table/assemble.d.ts.map +1 -1
  19. package/dist/table/compile-rule-map.d.ts.map +1 -1
  20. package/dist/table/emit-assembly.d.ts +1 -1
  21. package/dist/table/emit-assembly.d.ts.map +1 -1
  22. package/dist/table/emit.d.ts.map +1 -1
  23. package/dist/table/encode.d.ts.map +1 -1
  24. package/dist/table/exec.d.ts.map +1 -1
  25. package/dist/table/factor-choice.d.ts +42 -0
  26. package/dist/table/factor-choice.d.ts.map +1 -0
  27. package/dist/table/fail-clean.d.ts +3 -0
  28. package/dist/table/fail-clean.d.ts.map +1 -0
  29. package/dist/table/hold-gap.d.ts +8 -0
  30. package/dist/table/hold-gap.d.ts.map +1 -0
  31. package/dist/table/index.js +1369 -259
  32. package/dist/table/index.js.map +3 -3
  33. package/dist/table/lex-program.d.ts +7 -3
  34. package/dist/table/lex-program.d.ts.map +1 -1
  35. package/dist/table/ops.d.ts +8 -0
  36. package/dist/table/ops.d.ts.map +1 -1
  37. package/dist/table/run-support.d.ts +19 -0
  38. package/dist/table/run-support.d.ts.map +1 -1
  39. package/dist/table/scalar-terminal.d.ts +2 -0
  40. package/dist/table/scalar-terminal.d.ts.map +1 -1
  41. package/dist/table/site-labels.d.ts +66 -0
  42. package/dist/table/site-labels.d.ts.map +1 -1
  43. package/dist/version.d.ts +1 -1
  44. package/package.json +1 -1
  45. package/src/combinators/dispatch.ts +12 -3
  46. package/src/compiler/token-alphabet.ts +57 -17
  47. package/src/cst/capture-buffer.ts +25 -0
  48. package/src/plugin/index.ts +230 -35
  49. package/src/table/assemble.ts +252 -62
  50. package/src/table/child-slots.ts +2 -2
  51. package/src/table/compile-rule-map.ts +14 -5
  52. package/src/table/emit-assembly.ts +112 -23
  53. package/src/table/emit.ts +3 -1
  54. package/src/table/encode.ts +80 -14
  55. package/src/table/exec.ts +27 -8
  56. package/src/table/factor-choice.ts +173 -0
  57. package/src/table/fail-clean.ts +130 -0
  58. package/src/table/hold-gap.ts +68 -0
  59. package/src/table/lex-program.ts +197 -43
  60. package/src/table/ops.ts +9 -1
  61. package/src/table/run-support.ts +35 -0
  62. package/src/table/scalar-terminal.ts +8 -0
  63. package/src/table/site-labels.ts +135 -4
  64. package/src/version.ts +1 -1
@@ -663,6 +663,31 @@ function pushCstChild(ctx, built, rawEntry2) {
663
663
  else if (ctx._cstLeaves) ctx._cstLeaves.push(built);
664
664
  if (ctx._cstRawChildren) ctx._cstRawChildren.push(rawEntry2);
665
665
  }
666
+ function popCstChild(ctx) {
667
+ const b = ctx._cstBuf;
668
+ if (b) {
669
+ const ch2 = b.ch;
670
+ if (b.rawOnly !== true && ch2) {
671
+ ch2.pop();
672
+ if (ch2.length === 1) {
673
+ b.single = ch2[0];
674
+ b.ch = void 0;
675
+ }
676
+ }
677
+ if (b.noRaw === true) b.rawLen = (b.rawLen ?? 1) - 1;
678
+ else if (b.raw) {
679
+ b.raw.pop();
680
+ if (b.raw.length === 1) {
681
+ b.rawSingle = b.raw[0];
682
+ b.raw = void 0;
683
+ }
684
+ } else b.rawSingle = void 0;
685
+ return;
686
+ }
687
+ if (ctx._cstChildren) ctx._cstChildren.pop();
688
+ else if (ctx._cstLeaves) ctx._cstLeaves.pop();
689
+ if (ctx._cstRawChildren) ctx._cstRawChildren.pop();
690
+ }
666
691
  function cstRawLen(ctx) {
667
692
  const b = ctx._cstBuf;
668
693
  if (b) {
@@ -3939,10 +3964,16 @@ function branchUsesRouted(branch) {
3939
3964
  return branch.usesRouted === true || parserUsesRouted(branch.parser);
3940
3965
  }
3941
3966
  function asciiFoldKey(key) {
3942
- let out = "";
3943
- for (let i = 0; i < key.length; i++) {
3967
+ let i = 0;
3968
+ for (; i < key.length; i++) {
3944
3969
  const c = key.charCodeAt(i);
3945
- out += String.fromCharCode(c >= 65 && c <= 90 ? c + 32 : c);
3970
+ if (c >= 65 && c <= 90) break;
3971
+ }
3972
+ if (i === key.length) return key;
3973
+ let out = key.slice(0, i);
3974
+ for (; i < key.length; i++) {
3975
+ const c = key.charCodeAt(i);
3976
+ out += c >= 65 && c <= 90 ? String.fromCharCode(c + 32) : key[i];
3946
3977
  }
3947
3978
  return out;
3948
3979
  }
@@ -5364,17 +5395,59 @@ function buildLexBodyRecognizer(spec, constants) {
5364
5395
  };
5365
5396
  }
5366
5397
 
5398
+ // src/table/run-support.ts
5399
+ function lineCol(ctx, offset) {
5400
+ const starts = ctx._lineStarts ?? [0];
5401
+ let lo = 0, hi = starts.length - 1;
5402
+ while (lo < hi) {
5403
+ const mid = lo + hi + 1 >> 1;
5404
+ if (starts[mid] <= offset) lo = mid;
5405
+ else hi = mid - 1;
5406
+ }
5407
+ return [lo + 1, offset - starts[lo] + 1];
5408
+ }
5409
+ function spanLines(ctx, start, end) {
5410
+ const s = lineCol(ctx, start), e = lineCol(ctx, end);
5411
+ return { start, end, startLine: s[0], startColumn: s[1], endLine: e[0], endColumn: e[1] };
5412
+ }
5413
+ function rawEntry(v, input, s, e) {
5414
+ if (typeof v === "object" && v !== null) {
5415
+ const tg = v._tag;
5416
+ if (tg === "node" || tg === "leaf" || tg === "parseError") return v;
5417
+ }
5418
+ return {
5419
+ _tag: "leaf",
5420
+ value: typeof v === "string" ? v : typeof v === "object" && v !== null ? input.slice(s, e) : "",
5421
+ span: { start: s, end: e }
5422
+ };
5423
+ }
5424
+ function lead(input, pos) {
5425
+ if (pos >= input.length) return -1;
5426
+ const c = input.charCodeAt(pos);
5427
+ if (c < 55296 || c > 56319) return c;
5428
+ return input.codePointAt(pos) ?? c;
5429
+ }
5430
+ var EMPTY_KIDS = Object.freeze([]);
5431
+ var EMPTY_TRIVIA = Object.freeze([]);
5432
+ function collapseEmpty(ctx, build, input, pos, end, readsRaw) {
5433
+ const collected = ctx._cstBuf !== void 0 || ctx._cstChildren !== void 0;
5434
+ if (collected) popCstChild(ctx);
5435
+ const raw = readsRaw ? [rawEntry(void 0, input, pos, end)] : EMPTY_KIDS;
5436
+ const nd = build(EMPTY_KIDS, void 0, { start: pos, end }, raw, EMPTY_TRIVIA, void 0);
5437
+ if (collected) pushCstChild(ctx, nd, ctx._cstBuf?.noRaw === true ? void 0 : rawEntry(nd, input, pos, end));
5438
+ return nd;
5439
+ }
5440
+
5367
5441
  // src/table/lex-program.ts
5368
5442
  var LEX_NODE_TERMINAL = 0;
5369
5443
  var LEX_NODE_SEQUENCE2 = 1;
5370
5444
  var LEX_NODE_SEQUENCE3 = 2;
5371
5445
  var LEX_NODE_SEQUENCE4 = 3;
5372
5446
  var LEX_NODE_SEQUENCE5 = 4;
5373
- var LEX_NODE_CHOICE2 = 5;
5374
- var LEX_NODE_CHOICE4 = 6;
5375
- var LEX_NODE_CHOICE8 = 7;
5447
+ var LEX_NODE_CHOICE = 5;
5376
5448
  var LEX_NODE_NOT = 8;
5377
5449
  var LEX_NODE_OPTIONAL = 9;
5450
+ var LEX_NODE_REPEAT = 10;
5378
5451
  function lexProgramDigest(words) {
5379
5452
  let hash = 2166136261;
5380
5453
  for (const word2 of words) {
@@ -5403,85 +5476,114 @@ function trackLexLines(ctx, input, end) {
5403
5476
  ctx._lineScannedTo = end;
5404
5477
  }
5405
5478
  function terminalNode(matcher, failure, tracksLines) {
5406
- const match = (input, pos) => {
5407
- const result = matcher(input, pos);
5408
- return result < 0 ? -1 : result / 2;
5409
- };
5410
5479
  return {
5411
- match,
5480
+ match: (input, pos) => {
5481
+ const result = matcher(input, pos);
5482
+ return result < 0 ? -1 : result / 2;
5483
+ },
5412
5484
  run: (input, pos, ctx) => {
5413
- const end = match(input, pos);
5414
- if (end < 0) {
5485
+ const result = matcher(input, pos);
5486
+ if (result < 0) {
5415
5487
  ctx._fe = pos;
5416
5488
  ctx._fx = failure;
5417
5489
  if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
5418
5490
  return -1;
5419
5491
  }
5492
+ const end = result / 2;
5420
5493
  if (tracksLines) trackLexLines(ctx, input, end);
5421
5494
  return end;
5422
5495
  }
5423
5496
  };
5424
5497
  }
5425
5498
  function sequence2(a, b) {
5499
+ const am = a.match, bm = b.match, ar = a.run, br = b.run;
5426
5500
  return {
5427
5501
  match: (input, pos) => {
5428
- const e0 = a.match(input, pos);
5429
- return e0 < 0 ? -1 : b.match(input, e0);
5502
+ const e0 = am(input, pos);
5503
+ return e0 < 0 ? -1 : bm(input, e0);
5430
5504
  },
5431
5505
  run: (input, pos, ctx) => {
5432
- const e0 = a.run(input, pos, ctx);
5506
+ const e0 = ar(input, pos, ctx);
5433
5507
  if (e0 < 0) return -1;
5434
5508
  ctx._fc = false;
5435
- return b.run(input, e0, ctx);
5509
+ return br(input, e0, ctx);
5436
5510
  }
5437
5511
  };
5438
5512
  }
5439
5513
  function sequence3(a, b, c) {
5514
+ const am = a.match, bm = b.match, cm = c.match, ar = a.run, br = b.run, cr = c.run;
5440
5515
  return {
5441
5516
  match: (input, pos) => {
5442
- const e0 = a.match(input, pos);
5517
+ const e0 = am(input, pos);
5443
5518
  if (e0 < 0) return -1;
5444
- const e1 = b.match(input, e0);
5445
- return e1 < 0 ? -1 : c.match(input, e1);
5519
+ const e1 = bm(input, e0);
5520
+ return e1 < 0 ? -1 : cm(input, e1);
5446
5521
  },
5447
5522
  run: (input, pos, ctx) => {
5448
- const e0 = a.run(input, pos, ctx);
5523
+ const e0 = ar(input, pos, ctx);
5449
5524
  if (e0 < 0) return -1;
5450
5525
  ctx._fc = false;
5451
- const e1 = b.run(input, e0, ctx);
5526
+ const e1 = br(input, e0, ctx);
5452
5527
  if (e1 < 0) return -1;
5453
5528
  ctx._fc = false;
5454
- return c.run(input, e1, ctx);
5529
+ return cr(input, e1, ctx);
5455
5530
  }
5456
5531
  };
5457
5532
  }
5458
5533
  function sequence4(a, b, c, d) {
5459
- const abc = sequence3(a, b, c);
5534
+ const am = a.match, bm = b.match, cm = c.match, dm = d.match;
5535
+ const ar = a.run, br = b.run, cr = c.run, dr = d.run;
5460
5536
  return {
5461
5537
  match: (input, pos) => {
5462
- const end = abc.match(input, pos);
5463
- return end < 0 ? -1 : d.match(input, end);
5538
+ const e0 = am(input, pos);
5539
+ if (e0 < 0) return -1;
5540
+ const e1 = bm(input, e0);
5541
+ if (e1 < 0) return -1;
5542
+ const e2 = cm(input, e1);
5543
+ return e2 < 0 ? -1 : dm(input, e2);
5464
5544
  },
5465
5545
  run: (input, pos, ctx) => {
5466
- const end = abc.run(input, pos, ctx);
5467
- if (end < 0) return -1;
5546
+ const e0 = ar(input, pos, ctx);
5547
+ if (e0 < 0) return -1;
5468
5548
  ctx._fc = false;
5469
- return d.run(input, end, ctx);
5549
+ const e1 = br(input, e0, ctx);
5550
+ if (e1 < 0) return -1;
5551
+ ctx._fc = false;
5552
+ const e2 = cr(input, e1, ctx);
5553
+ if (e2 < 0) return -1;
5554
+ ctx._fc = false;
5555
+ return dr(input, e2, ctx);
5470
5556
  }
5471
5557
  };
5472
5558
  }
5473
5559
  function sequence5(a, b, c, d, e) {
5474
- const abcd = sequence4(a, b, c, d);
5560
+ const am = a.match, bm = b.match, cm = c.match, dm = d.match, em = e.match;
5561
+ const ar = a.run, br = b.run, cr = c.run, dr = d.run, er = e.run;
5475
5562
  return {
5476
5563
  match: (input, pos) => {
5477
- const end = abcd.match(input, pos);
5478
- return end < 0 ? -1 : e.match(input, end);
5564
+ const e0 = am(input, pos);
5565
+ if (e0 < 0) return -1;
5566
+ const e1 = bm(input, e0);
5567
+ if (e1 < 0) return -1;
5568
+ const e2 = cm(input, e1);
5569
+ if (e2 < 0) return -1;
5570
+ const e3 = dm(input, e2);
5571
+ return e3 < 0 ? -1 : em(input, e3);
5479
5572
  },
5480
5573
  run: (input, pos, ctx) => {
5481
- const end = abcd.run(input, pos, ctx);
5482
- if (end < 0) return -1;
5574
+ const e0 = ar(input, pos, ctx);
5575
+ if (e0 < 0) return -1;
5576
+ ctx._fc = false;
5577
+ const e1 = br(input, e0, ctx);
5578
+ if (e1 < 0) return -1;
5483
5579
  ctx._fc = false;
5484
- return e.run(input, end, ctx);
5580
+ const e2 = cr(input, e1, ctx);
5581
+ if (e2 < 0) return -1;
5582
+ ctx._fc = false;
5583
+ const e3 = dr(input, e2, ctx);
5584
+ if (e3 < 0) return -1;
5585
+ ctx._fc = false;
5586
+ return er(input, e3, ctx);
5485
5587
  }
5486
5588
  };
5487
5589
  }
@@ -5494,9 +5596,9 @@ function appendExpected(acc, values) {
5494
5596
  function choiceNode(arms, classes, armExpected, choiceExpected) {
5495
5597
  let matchTail = () => -1;
5496
5598
  for (let i = arms.length - 1; i >= 0; i--) {
5497
- const arm = arms[i], next = matchTail;
5599
+ const armMatch = arms[i].match, next = matchTail;
5498
5600
  matchTail = (input, pos) => {
5499
- const end = arm.match(input, pos);
5601
+ const end = armMatch(input, pos);
5500
5602
  return end < 0 ? next(input, pos) : end;
5501
5603
  };
5502
5604
  }
@@ -5506,7 +5608,7 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
5506
5608
  return -1;
5507
5609
  };
5508
5610
  for (let i = arms.length - 1; i >= 0; i--) {
5509
- const arm = arms[i], cls = classes[i], staticExpected = armExpected[i], next = tail;
5611
+ const armRun = arms[i].run, cls = classes[i], staticExpected = armExpected[i], next = tail;
5510
5612
  tail = (input, pos, ctx, lead2, acc, best) => {
5511
5613
  if (cls !== void 0 && !classHas(cls, lead2)) {
5512
5614
  return next(
@@ -5519,7 +5621,7 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
5519
5621
  );
5520
5622
  }
5521
5623
  ctx._fc = false;
5522
- const end = arm.run(input, pos, ctx);
5624
+ const end = armRun(input, pos, ctx);
5523
5625
  if (end >= 0) return end;
5524
5626
  const at = ctx._fe ?? pos;
5525
5627
  if (at > best) {
@@ -5546,11 +5648,58 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
5546
5648
  )
5547
5649
  };
5548
5650
  }
5651
+ function exclusiveChoiceNode(arms, classes, choiceFx) {
5652
+ const ascii = (classes.length <= 128 ? new Int8Array(128) : new Int32Array(128)).fill(-1);
5653
+ const hi = [];
5654
+ for (let i = 0; i < classes.length; i++) {
5655
+ const cls = classes[i];
5656
+ for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) ascii[c] = i;
5657
+ for (let r = 0; r < cls.hi.length; r += 2) hi.push(cls.hi[r], cls.hi[r + 1], i);
5658
+ }
5659
+ const select = (code) => {
5660
+ if (code < 0) return -1;
5661
+ if (code < 128) return ascii[code];
5662
+ for (let r = 0; r < hi.length; r += 3) if (code >= hi[r] && code <= hi[r + 1]) return hi[r + 2];
5663
+ return -1;
5664
+ };
5665
+ let matchArm = () => -1;
5666
+ let selectRun = () => -1;
5667
+ for (let i = arms.length - 1; i >= 0; i--) {
5668
+ const armMatch = arms[i].match, armRun = arms[i].run, nextMatch = matchArm, nextRun = selectRun;
5669
+ matchArm = (selected, input, pos) => selected === i ? armMatch(input, pos) : nextMatch(selected, input, pos);
5670
+ selectRun = (selected, input, pos, ctx) => selected === i ? armRun(input, pos, ctx) : nextRun(selected, input, pos, ctx);
5671
+ }
5672
+ const runArm = (input, pos, ctx) => {
5673
+ const arm = select(lead(input, pos));
5674
+ if (arm >= 0) {
5675
+ ctx._fc = false;
5676
+ const end = selectRun(arm, input, pos, ctx);
5677
+ if (end >= 0) return end;
5678
+ if (committed(ctx)) return -1;
5679
+ const failed = ctx._fx;
5680
+ if (failed !== void 0 && failed.length > 0) {
5681
+ ctx._fe = pos;
5682
+ return -1;
5683
+ }
5684
+ }
5685
+ ctx._fe = pos;
5686
+ ctx._fx = choiceFx;
5687
+ return -1;
5688
+ };
5689
+ return {
5690
+ match: (input, pos) => {
5691
+ const arm = select(lead(input, pos));
5692
+ return arm < 0 ? -1 : matchArm(arm, input, pos);
5693
+ },
5694
+ run: runArm
5695
+ };
5696
+ }
5549
5697
  function notNode(body, failure) {
5698
+ const bodyMatch = body.match;
5550
5699
  return {
5551
- match: (input, pos) => body.match(input, pos) < 0 ? pos : -1,
5700
+ match: (input, pos) => bodyMatch(input, pos) < 0 ? pos : -1,
5552
5701
  run: (input, pos, ctx) => {
5553
- if (body.match(input, pos) < 0) return pos;
5702
+ if (bodyMatch(input, pos) < 0) return pos;
5554
5703
  ctx._fe = pos;
5555
5704
  ctx._fx = failure;
5556
5705
  return -1;
@@ -5558,18 +5707,57 @@ function notNode(body, failure) {
5558
5707
  };
5559
5708
  }
5560
5709
  function optionalNode(body) {
5710
+ const bodyMatch = body.match, bodyRun = body.run;
5561
5711
  return {
5562
5712
  match: (input, pos) => {
5563
- const end = body.match(input, pos);
5713
+ const end = bodyMatch(input, pos);
5564
5714
  return end < 0 ? pos : end;
5565
5715
  },
5566
5716
  run: (input, pos, ctx) => {
5567
5717
  ctx._fc = false;
5568
- const end = body.run(input, pos, ctx);
5718
+ const end = bodyRun(input, pos, ctx);
5569
5719
  return end < 0 && !committed(ctx) ? pos : end;
5570
5720
  }
5571
5721
  };
5572
5722
  }
5723
+ function repeatNode(item, min, max) {
5724
+ const itemMatch = item.match, itemRun = item.run;
5725
+ return {
5726
+ match: (input, pos) => {
5727
+ let cur = pos;
5728
+ let count = 0;
5729
+ for (; ; ) {
5730
+ if (max >= 0 && count >= max) break;
5731
+ const optional2 = count >= min && (count > 0 || min === 0);
5732
+ if (optional2 && cur >= input.length) break;
5733
+ const end = itemMatch(input, cur);
5734
+ if (end < 0 || optional2 && end === cur) break;
5735
+ cur = end;
5736
+ count++;
5737
+ }
5738
+ return count < min ? -1 : cur;
5739
+ },
5740
+ run: (input, pos, ctx) => {
5741
+ let cur = pos;
5742
+ let count = 0;
5743
+ for (; ; ) {
5744
+ if (max >= 0 && count >= max) break;
5745
+ const optional2 = count >= min && (count > 0 || min === 0);
5746
+ if (optional2 && cur >= input.length) break;
5747
+ ctx._fc = false;
5748
+ const end = itemRun(input, cur, ctx);
5749
+ if (end < 0) {
5750
+ if (committed(ctx)) return -1;
5751
+ break;
5752
+ }
5753
+ if (optional2 && end === cur) break;
5754
+ cur = end;
5755
+ count++;
5756
+ }
5757
+ return count < min ? -1 : cur;
5758
+ }
5759
+ };
5760
+ }
5573
5761
  function fixedTreeRunner(words, matchers, classes, expected) {
5574
5762
  const stack = [];
5575
5763
  const pop = () => {
@@ -5597,9 +5785,14 @@ function fixedTreeRunner(words, matchers, classes, expected) {
5597
5785
  else stack.push(sequence5(nodes2[0], nodes2[1], nodes2[2], nodes2[3], nodes2[4]));
5598
5786
  continue;
5599
5787
  }
5600
- if (op >= LEX_NODE_CHOICE2 && op <= LEX_NODE_CHOICE8) {
5601
- const count = op === LEX_NODE_CHOICE2 ? 2 : op === LEX_NODE_CHOICE4 ? 4 : 8;
5788
+ if (op === LEX_NODE_CHOICE) {
5789
+ const count = words[at++];
5790
+ const exclusive = words[at++];
5791
+ if (exclusive !== 0 && exclusive !== 1) throw new TypeError("table lexical tree choice has an invalid dispatch mode");
5602
5792
  const choiceFx = expected[words[at++]];
5793
+ if (!Number.isInteger(count) || count < 2 || count > stack.length) {
5794
+ throw new TypeError("table lexical tree choice has an invalid arm count");
5795
+ }
5603
5796
  if (choiceFx === void 0) throw new TypeError("table lexical tree choice has an invalid expected set");
5604
5797
  const armClasses = [];
5605
5798
  const armFx = [];
@@ -5612,7 +5805,7 @@ function fixedTreeRunner(words, matchers, classes, expected) {
5612
5805
  armFx.push(fx);
5613
5806
  }
5614
5807
  const arms = Array.from({ length: count }, pop).reverse();
5615
- stack.push(choiceNode(arms, armClasses, armFx, choiceFx));
5808
+ stack.push(exclusive === 1 ? exclusiveChoiceNode(arms, armClasses, choiceFx) : choiceNode(arms, armClasses, armFx, choiceFx));
5616
5809
  continue;
5617
5810
  }
5618
5811
  if (op === LEX_NODE_NOT) {
@@ -5625,6 +5818,14 @@ function fixedTreeRunner(words, matchers, classes, expected) {
5625
5818
  stack.push(optionalNode(pop()));
5626
5819
  continue;
5627
5820
  }
5821
+ if (op === LEX_NODE_REPEAT) {
5822
+ const min = words[at++], max = words[at++];
5823
+ if (!Number.isInteger(min) || min < 0 || !Number.isInteger(max) || max >= 0 && max < min) {
5824
+ throw new TypeError("table lexical tree repeat has invalid bounds");
5825
+ }
5826
+ stack.push(repeatNode(pop(), min, max));
5827
+ continue;
5828
+ }
5628
5829
  throw new TypeError("table lexical tree has an unknown fixed body");
5629
5830
  }
5630
5831
  if (stack.length !== 1) throw new TypeError("table lexical tree does not resolve to one root body");
@@ -6511,6 +6712,111 @@ function classifyRuleMap(ruleMap) {
6511
6712
  };
6512
6713
  }
6513
6714
 
6715
+ // src/table/factor-choice.ts
6716
+ var DERIVED = /* @__PURE__ */ new Set(["_tag", "_meta", "_def", "_parseScalar", "_stickyRegex", "parse"]);
6717
+ function isCombinator(v) {
6718
+ return typeof v === "object" && v !== null && "_def" in v && "_meta" in v;
6719
+ }
6720
+ function sameComb(a, b, depth) {
6721
+ if (a === b) return true;
6722
+ if (depth > 32 || a._tag !== b._tag) return false;
6723
+ for (const k of Object.keys(a)) if (!DERIVED.has(k)) return false;
6724
+ for (const k of Object.keys(b)) if (!DERIVED.has(k)) return false;
6725
+ return sameFields(a._def, b._def, depth, void 0);
6726
+ }
6727
+ function sameValue(u, v, depth) {
6728
+ if (u === v) return true;
6729
+ if (isCombinator(u) && isCombinator(v)) return sameComb(u, v, depth + 1);
6730
+ if (Array.isArray(u) && Array.isArray(v)) return u.length === v.length && u.every((x, i) => sameValue(x, v[i], depth));
6731
+ if (typeof u === "object" && u !== null && typeof v === "object" && v !== null && Object.getPrototypeOf(u) === Object.prototype && Object.getPrototypeOf(v) === Object.prototype) {
6732
+ return sameFields(u, v, depth, void 0);
6733
+ }
6734
+ return false;
6735
+ }
6736
+ function sameFields(x, y, depth, skip) {
6737
+ const kx = Object.keys(x).filter((k) => k !== skip && x[k] !== void 0);
6738
+ const ky = Object.keys(y).filter((k) => k !== skip && y[k] !== void 0);
6739
+ if (kx.length !== ky.length) return false;
6740
+ for (const k of kx) {
6741
+ if (!(k in y)) return false;
6742
+ const u = x[k];
6743
+ const v = y[k];
6744
+ if (k === "fn" && typeof u === "function" && typeof v === "function" && u !== v) {
6745
+ if (typeof x.fnSrc !== "string" || x.fnSrc === "" || x.fnSrc !== y.fnSrc) return false;
6746
+ continue;
6747
+ }
6748
+ if (!sameValue(u, v, depth)) return false;
6749
+ }
6750
+ return true;
6751
+ }
6752
+ function rewrap(w, body) {
6753
+ const d = w._def;
6754
+ let out;
6755
+ if (d.tag === "leaf") {
6756
+ out = d.cstValue === "source" ? sourceLeaf(body, d.fn) : leaf(body, d.fn);
6757
+ if (d.fnSrc !== void 0) out._def.fnSrc = d.fnSrc;
6758
+ } else if (d.tag === "grammar") {
6759
+ out = d.clearTrivia === true ? noTrivia(body) : parser({ trivia: d.triviaParser ?? null }, body);
6760
+ } else return void 0;
6761
+ return sameFields(d, out._def, 0, "parser") ? out : void 0;
6762
+ }
6763
+ function unusedOf(seq) {
6764
+ return seq._def.tag === "sequence" && seq._def.valueUnused === true;
6765
+ }
6766
+ function never(c) {
6767
+ const t = c._def.tag;
6768
+ return t === "optional" || t === "many";
6769
+ }
6770
+ function factorSharedEnds(d) {
6771
+ const arms = d.parsers;
6772
+ if (arms.length < 2) return void 0;
6773
+ if (d.strategy.tag !== "firstMatch" && d.strategy.tag !== "sharedPrefix") return void 0;
6774
+ if (d.gates.some((g) => g !== null) || d.autoNot.some((a) => a !== null)) return void 0;
6775
+ const shapes = [];
6776
+ for (const arm of arms) {
6777
+ const wrappers = [];
6778
+ let c = arm;
6779
+ while ((c._def.tag === "leaf" || c._def.tag === "grammar") && wrappers.length < 4) {
6780
+ wrappers.push(c);
6781
+ c = c._def.parser;
6782
+ }
6783
+ if (c._def.tag !== "sequence" || c._def.parsers.length < 2) return void 0;
6784
+ shapes.push({ wrappers, terms: c._def.parsers, seq: c });
6785
+ }
6786
+ const first = shapes[0];
6787
+ const n = first.terms.length;
6788
+ for (const s of shapes) {
6789
+ if (s.wrappers.length !== first.wrappers.length || s.terms.length !== n) return void 0;
6790
+ if (unusedOf(s.seq) !== unusedOf(first.seq)) return void 0;
6791
+ for (let j = 0; j < s.wrappers.length; j++) {
6792
+ const a = first.wrappers[j]._def;
6793
+ const b = s.wrappers[j]._def;
6794
+ if (a.tag !== b.tag || !sameFields(a, b, 0, "parser")) return void 0;
6795
+ }
6796
+ }
6797
+ let at = -1;
6798
+ for (let i = 0; i < n; i++) {
6799
+ if (shapes.every((s) => sameComb(s.terms[i], first.terms[i], 0))) continue;
6800
+ if (at >= 0) return void 0;
6801
+ at = i;
6802
+ }
6803
+ if (at < 0) return void 0;
6804
+ for (let i = at + 1; i < n; i++) if (!never(first.terms[i])) return void 0;
6805
+ if (arms.some((a) => mayCommitFailure(a))) return void 0;
6806
+ const middle = choice(...shapes.map((s) => s.terms[at]));
6807
+ if (middle._def.tag === "choice" && middle._def.autoNot.some((a) => a !== null)) return void 0;
6808
+ const st = middle._def.tag === "choice" ? middle._def.strategy : void 0;
6809
+ if (st === void 0 || st.tag !== "firstMatch" && st.tag !== "sharedPrefix" && !(st.tag === "literalsLongestFirst" && st.sortedIndices.every((x, i) => x === i))) return void 0;
6810
+ let out = sequence(
6811
+ ...[...first.terms.slice(0, at), middle, ...first.terms.slice(at + 1)]
6812
+ );
6813
+ if (unusedOf(first.seq)) {
6814
+ out._def.valueUnused = true;
6815
+ }
6816
+ for (let j = first.wrappers.length - 1; j >= 0 && out !== void 0; j--) out = rewrap(first.wrappers[j], out);
6817
+ return out === void 0 ? void 0 : attempt(out);
6818
+ }
6819
+
6514
6820
  // src/table/ops.ts
6515
6821
  var OP_LIT = 1;
6516
6822
  var OP_RX = 2;
@@ -6554,6 +6860,7 @@ var OP_SCOPE_PLAIN = 41;
6554
6860
  var OP_LEX_BODY = 42;
6555
6861
  var OP_LEX_PROGRAM = 43;
6556
6862
  var OP_SOURCE_LEAF = 44;
6863
+ var OP_RGATE = 45;
6557
6864
  var OP_DISPATCH = 25;
6558
6865
  var OP_ROUTED = 26;
6559
6866
  var OP_NAMES = {
@@ -6573,6 +6880,7 @@ var OP_NAMES = {
6573
6880
  [OP_PEEK]: "PEEK",
6574
6881
  [OP_LEAF]: "LEAF",
6575
6882
  [OP_SOURCE_LEAF]: "SOURCE_LEAF",
6883
+ [OP_RGATE]: "RGATE",
6576
6884
  [OP_EMPTY]: "EMPTY",
6577
6885
  [OP_LIT_TRACK]: "LIT_TRACK",
6578
6886
  [OP_RX_TRACK]: "RX_TRACK",
@@ -6653,7 +6961,10 @@ function selectOptionalSuffixLexBody(ir) {
6653
6961
  const token2 = { strategy: "token", estimatedOps: 2, body };
6654
6962
  return token2.estimatedOps < character.estimatedOps ? token2 : character;
6655
6963
  }
6656
- function directTokenBodyParser(parser2, resolve3) {
6964
+ function reinstallsRuleTrivia(reference, target) {
6965
+ return (reference._meta.grammarTrivia ?? target._meta.grammarTrivia) !== void 0 && hasOwnTriviaBoundary(target);
6966
+ }
6967
+ function directTokenBodyParser(parser2, resolve3, scope) {
6657
6968
  const outer = parser2._def;
6658
6969
  if (outer.tag !== "token") return void 0;
6659
6970
  let body = outer.parser;
@@ -6663,12 +6974,13 @@ function directTokenBodyParser(parser2, resolve3) {
6663
6974
  const wrapper = body._def;
6664
6975
  if (wrapper.tag === "grammar") {
6665
6976
  if (wrapper.clearTrivia !== true || wrapper.triviaParser !== void 0 || wrapper.captureTrivia === true || wrapper.rootCapture === "opaque" || wrapper.constructionTrackLines !== "inherit" || wrapper.constructionCaptureTriviaKinds !== void 0) return void 0;
6977
+ if (scope !== void 0) scope.cleared = true;
6666
6978
  body = wrapper.parser;
6667
6979
  continue;
6668
6980
  }
6669
6981
  if (wrapper.tag === "lazy") {
6670
6982
  const target = resolvedLazyTarget(body, resolve3);
6671
- if (target === void 0) return void 0;
6983
+ if (target === void 0 || reinstallsRuleTrivia(body, target)) return void 0;
6672
6984
  body = target;
6673
6985
  continue;
6674
6986
  }
@@ -6840,7 +7152,7 @@ function directNot2TokenBody(parser2, resolve3) {
6840
7152
  terminal
6841
7153
  };
6842
7154
  }
6843
- function directFixedLexNode(parser2, resolve3, active, pureOnly = false) {
7155
+ function directFixedLexNode(parser2, resolve3, active, pureOnly = false, cleared = false) {
6844
7156
  let current = parser2;
6845
7157
  const wrappers = /* @__PURE__ */ new Set();
6846
7158
  while (!wrappers.has(current)) {
@@ -6848,7 +7160,7 @@ function directFixedLexNode(parser2, resolve3, active, pureOnly = false) {
6848
7160
  const def = current._def;
6849
7161
  if (def.tag === "lazy") {
6850
7162
  const target = resolvedLazyTarget(current, resolve3);
6851
- if (target === void 0) return void 0;
7163
+ if (target === void 0 || reinstallsRuleTrivia(current, target)) return void 0;
6852
7164
  current = target;
6853
7165
  continue;
6854
7166
  }
@@ -6866,30 +7178,33 @@ function directFixedLexNode(parser2, resolve3, active, pureOnly = false) {
6866
7178
  if (terminal !== void 0) return { kind: "terminal", terminal };
6867
7179
  const def = current._def;
6868
7180
  if (def.tag === "grammar") {
7181
+ if (def.triviaParser === void 0 && def.captureTrivia !== true && def.rootCapture !== "opaque" && def.constructionCaptureTriviaKinds === void 0) {
7182
+ return directFixedLexNode(def.parser, resolve3, active, pureOnly, cleared || def.clearTrivia === true);
7183
+ }
6869
7184
  if (!pureOnly || def.parser._def.tag !== "token" && (def.clearTrivia !== true || def.triviaParser !== void 0 || def.captureTrivia === true || def.rootCapture === "opaque")) return void 0;
6870
- return directFixedLexNode(def.parser, resolve3, active, true);
7185
+ return directFixedLexNode(def.parser, resolve3, active, true, cleared);
6871
7186
  }
6872
7187
  if (def.tag === "sequence") {
6873
7188
  if (def.parsers.length < 2 || def.parsers.length > 5) return void 0;
6874
- const parts = def.parsers.map((part) => directFixedLexNode(part, resolve3, active, pureOnly));
7189
+ const parts = def.parsers.map((part) => directFixedLexNode(part, resolve3, active, pureOnly, cleared));
6875
7190
  if (parts.some((part) => part === void 0)) return void 0;
6876
7191
  return { kind: "sequence", parts };
6877
7192
  }
6878
7193
  if (def.tag === "choice") {
6879
- if (def.parsers.length !== 2 && def.parsers.length !== 4 && def.parsers.length !== 8 || def.strategy.tag !== "firstMatch" || def.gates.some((gate2) => gate2 !== null) || def.autoNot.some((check) => check !== null)) return void 0;
6880
- const arms = def.parsers.map((arm) => directFixedLexNode(arm, resolve3, active, pureOnly));
7194
+ if (def.parsers.length < 2 || def.strategy.tag !== "firstMatch" || def.gates.some((gate2) => gate2 !== null) || def.autoNot.some((check) => check !== null)) return void 0;
7195
+ const arms = def.parsers.map((arm) => directFixedLexNode(arm, resolve3, active, pureOnly, cleared));
6881
7196
  if (arms.some((arm) => arm === void 0)) return void 0;
6882
- const final = classifyFinalChoice(def.parsers, resolve3);
6883
7197
  return {
6884
7198
  kind: "choice",
6885
7199
  arms,
6886
- firstSets: final.firstSets,
7200
+ parsers: def.parsers,
7201
+ cleared,
6887
7202
  armExpected: def.parsers.map(deriveExpected),
6888
7203
  expected: def.parsers.flatMap(deriveExpected)
6889
7204
  };
6890
7205
  }
6891
7206
  if (def.tag === "not") {
6892
- const body = directFixedLexNode(def.parser, resolve3, active, true);
7207
+ const body = directFixedLexNode(def.parser, resolve3, active, true, cleared);
6893
7208
  return body === void 0 ? void 0 : {
6894
7209
  kind: "not",
6895
7210
  body,
@@ -6897,18 +7212,28 @@ function directFixedLexNode(parser2, resolve3, active, pureOnly = false) {
6897
7212
  };
6898
7213
  }
6899
7214
  if (def.tag === "optional") {
6900
- const body = directFixedLexNode(def.parser, resolve3, active, pureOnly);
7215
+ const body = directFixedLexNode(def.parser, resolve3, active, pureOnly, cleared);
6901
7216
  return body === void 0 ? void 0 : { kind: "optional", body };
6902
7217
  }
7218
+ if (def.tag === "many" || def.tag === "oneOrMore") {
7219
+ const body = directFixedLexNode(def.parser, resolve3, active, pureOnly, cleared);
7220
+ return body === void 0 ? void 0 : {
7221
+ kind: "repeat",
7222
+ body,
7223
+ min: def.tag === "many" ? 0 : def.min,
7224
+ max: def.max ?? -1
7225
+ };
7226
+ }
6903
7227
  return void 0;
6904
7228
  } finally {
6905
7229
  active.delete(current);
6906
7230
  }
6907
7231
  }
6908
7232
  function directFixedTokenBody(parser2, resolve3) {
6909
- const body = directTokenBodyParser(parser2, resolve3);
7233
+ const scope = { cleared: false };
7234
+ const body = directTokenBodyParser(parser2, resolve3, scope);
6910
7235
  if (body === void 0) return void 0;
6911
- const root = directFixedLexNode(body, resolve3, /* @__PURE__ */ new Set());
7236
+ const root = directFixedLexNode(body, resolve3, /* @__PURE__ */ new Set(), false, scope.cleared);
6912
7237
  return root === void 0 ? void 0 : { kind: "fixed-tree", root };
6913
7238
  }
6914
7239
  function directBalancedTokenBody(parser2, resolve3) {
@@ -7155,13 +7480,16 @@ var Encoder = class {
7155
7480
  }
7156
7481
  case "choice": {
7157
7482
  for (const arm of node2.arms) if (!emitNode(arm)) return false;
7158
- const op = node2.arms.length === 2 ? LEX_NODE_CHOICE2 : node2.arms.length === 4 ? LEX_NODE_CHOICE4 : node2.arms.length === 8 ? LEX_NODE_CHOICE8 : -1;
7159
- if (op < 0) return false;
7160
- words.push(op, this.expected(node2.expected));
7483
+ const final = classifyFinalChoice(
7484
+ node2.parsers,
7485
+ this.refResolver(),
7486
+ node2.cleared ? void 0 : this.activeTrivia
7487
+ );
7488
+ const classes = final.firstSets.map((first, i) => final.nullable[i] ? -1 : this.charClass(first));
7489
+ const exclusive = final.exclusive && classes.every((cls) => cls >= 0);
7490
+ words.push(LEX_NODE_CHOICE, node2.arms.length, exclusive ? 1 : 0, this.expected(node2.expected));
7161
7491
  for (let i = 0; i < node2.arms.length; i++) {
7162
- const first = node2.firstSets[i];
7163
- words.push(first.kind === "ranges" ? this.charClass(first) : -1);
7164
- words.push(this.expected(node2.armExpected[i]));
7492
+ words.push(classes[i], this.expected(node2.armExpected[i]));
7165
7493
  }
7166
7494
  return true;
7167
7495
  }
@@ -7173,6 +7501,10 @@ var Encoder = class {
7173
7501
  if (!emitNode(node2.body)) return false;
7174
7502
  words.push(LEX_NODE_OPTIONAL);
7175
7503
  return true;
7504
+ case "repeat":
7505
+ if (!emitNode(node2.body)) return false;
7506
+ words.push(LEX_NODE_REPEAT, node2.min, node2.max);
7507
+ return true;
7176
7508
  }
7177
7509
  };
7178
7510
  if (!emitNode(body.root)) return void 0;
@@ -7678,6 +8010,50 @@ var Encoder = class {
7678
8010
  if (!hasOwnTriviaBoundary(target)) return ip;
7679
8011
  return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), ip);
7680
8012
  }
8013
+ /**
8014
+ * The `OP_RGATE` operands of a choice arm that opens with `routed()`, or
8015
+ * `undefined`. Through `node()`/scope wrappers and first sequence terms, the
8016
+ * arm's next term after the routed token is found; the gate is that term's
8017
+ * first characters, with the trivia in force at the boundary before it, so
8018
+ * the arm is entered only where it can get past the token. The term must be
8019
+ * unable to match empty or to commit, so a miss is exactly that term failing
8020
+ * at the token's end with its own set.
8021
+ */
8022
+ routedArmGate(arm) {
8023
+ const walk = (p, trivia2, depth) => {
8024
+ if (depth > 16) return void 0;
8025
+ const d = p._def;
8026
+ switch (d.tag) {
8027
+ case "routed":
8028
+ return "end";
8029
+ case "node":
8030
+ return walk(d.parser, trivia2, depth + 1);
8031
+ case "grammar":
8032
+ return walk(d.parser, d.clearTrivia === true ? void 0 : d.triviaParser ?? trivia2, depth + 1);
8033
+ case "sequence": {
8034
+ const head = d.parsers[0];
8035
+ if (head === void 0) return void 0;
8036
+ const r = walk(head, trivia2, depth + 1);
8037
+ if (r !== "end") return r;
8038
+ const next2 = d.parsers[1];
8039
+ return next2 === void 0 ? "end" : { next: next2, boundary: trivia2 };
8040
+ }
8041
+ default:
8042
+ return void 0;
8043
+ }
8044
+ };
8045
+ const follow = walk(arm, this.activeTrivia, 0);
8046
+ if (follow === void 0 || follow === "end") return void 0;
8047
+ const rr = this.refResolver();
8048
+ const { next, boundary } = follow;
8049
+ if (matchesEmpty(next, /* @__PURE__ */ new Set(), rr) || mayCommitFailure(next, rr, this.commitFailureMemo)) return void 0;
8050
+ const nextTag = next._def.tag;
8051
+ if (nextTag !== "literal" && nextTag !== "regex" && nextTag !== "keywords" && nextTag !== "label") return void 0;
8052
+ const first = firstSetOf(next, /* @__PURE__ */ new Set(), rr, boundary);
8053
+ const cls = this.charClass(boundary === void 0 ? first : union(first, firstSetOf(boundary, /* @__PURE__ */ new Set(), rr)));
8054
+ if (cls < 0) return void 0;
8055
+ return { cls, fx: this.expected(deriveExpected(next)) };
8056
+ }
7681
8057
  node(p) {
7682
8058
  const lazyRef = p._def.tag === "lazy";
7683
8059
  const scopeKey = lazyRef ? this.activeTrivia : void 0;
@@ -7802,6 +8178,10 @@ var Encoder = class {
7802
8178
  return head;
7803
8179
  }
7804
8180
  case "choice": {
8181
+ if (this.plan === void 0) {
8182
+ const factored = factorSharedEnds(d);
8183
+ if (factored !== void 0) return this.node(factored).ip;
8184
+ }
7805
8185
  if (d.strategy.tag === "greedyClassify") {
7806
8186
  const superIndex = d.strategy.superIndex;
7807
8187
  const sup = this.node(d.parsers[superIndex]).ip;
@@ -7825,9 +8205,12 @@ var Encoder = class {
7825
8205
  const kids = arms.map((c, k) => {
7826
8206
  const src = order[k];
7827
8207
  const checks = d.autoNot[src];
7828
- const inner = this.node(c).ip;
7829
- const ip = checks === null || checks === void 0 || checks.length === 0 ? inner : this.reject(inner, checks);
7830
8208
  const gate2 = d.gates[src];
8209
+ const plain = (checks === null || checks === void 0 || checks.length === 0) && (gate2 === null || gate2 === void 0);
8210
+ const routedGate = plain ? this.routedArmGate(c) : void 0;
8211
+ const body = this.node(c).ip;
8212
+ const inner = routedGate === void 0 ? body : this.emit(OP_RGATE, routedGate.cls, body, routedGate.fx);
8213
+ const ip = checks === null || checks === void 0 || checks.length === 0 ? inner : this.reject(inner, checks);
7831
8214
  const gated = gate2 === null || gate2 === void 0 ? ip : this.emit(OP_ARMGATE, this.fn(gate2, d.gateSrcs?.[src] ?? null), ip, this.expected(deriveExpected(c)));
7832
8215
  return this.covWrap(gated, armCovIds?.[src], 1);
7833
8216
  });
@@ -8151,6 +8534,7 @@ var Encoder = class {
8151
8534
  const slots = (ip) => {
8152
8535
  switch (this.code[ip]) {
8153
8536
  case OP_GATE:
8537
+ case OP_RGATE:
8154
8538
  return [ip + 2];
8155
8539
  case OP_RULE:
8156
8540
  case OP_OPT:
@@ -9378,6 +9762,7 @@ function childSlots(code, ip, out) {
9378
9762
  case OP_LEAF:
9379
9763
  case OP_SOURCE_LEAF:
9380
9764
  case OP_ARMGATE:
9765
+ case OP_RGATE:
9381
9766
  out.push(code[ip + 2]);
9382
9767
  return true;
9383
9768
  // `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
@@ -9461,6 +9846,42 @@ function reachableSites(code, roots) {
9461
9846
  }
9462
9847
  return seen;
9463
9848
  }
9849
+ function passCollapse(code, ip, hostCst) {
9850
+ const flags = code[ip + 3];
9851
+ if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return false;
9852
+ if (flags !== 32 && flags !== 34) return false;
9853
+ let at = code[ip + 2];
9854
+ for (let n = 0; n < 8; n++) {
9855
+ const op = code[at];
9856
+ if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[at + 3] === 0) at = code[at + 2];
9857
+ else if (op === OP_RULE) at = code[at + 1];
9858
+ else break;
9859
+ }
9860
+ return code[at] === OP_NODE;
9861
+ }
9862
+ function gatedPassCollapse(code, ip, hostCst) {
9863
+ const flags = code[ip + 3];
9864
+ if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return void 0;
9865
+ if (flags !== 32 && flags !== 34) return void 0;
9866
+ const seq = code[ip + 2];
9867
+ if (code[seq] !== OP_SEQ && code[seq] !== OP_SEQV) return void 0;
9868
+ const n = code[seq + 1];
9869
+ if (n < 2) return void 0;
9870
+ const leads = [];
9871
+ const lits = [];
9872
+ for (let i = 0; i < n - 1; i++) {
9873
+ const t = code[seq + 2 + i];
9874
+ if (code[t] !== OP_OPT && code[t] !== OP_NOT) return void 0;
9875
+ const g = code[t + 1];
9876
+ if (code[g] === OP_GATE) leads.push(g);
9877
+ else if (code[g] === OP_LIT) lits.push(code[g + 1]);
9878
+ else return void 0;
9879
+ }
9880
+ const last = code[seq + 2 + n - 1];
9881
+ let at = last;
9882
+ 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];
9883
+ return code[at] === OP_NODE ? { leads, lits, last } : void 0;
9884
+ }
9464
9885
  function transfer(code, ip, at, hostCst) {
9465
9886
  const op = code[ip];
9466
9887
  if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
@@ -9472,14 +9893,18 @@ function transfer(code, ip, at, hostCst) {
9472
9893
  }
9473
9894
  if (op === OP_NODE || op === OP_NODE_TRACK) {
9474
9895
  const flags = code[ip + 3];
9896
+ if (passCollapse(code, ip, hostCst)) return at;
9897
+ const gated = gatedPassCollapse(code, ip, hostCst) !== void 0;
9475
9898
  const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && ((flags & ~128) === 2 || flags === 18 || flags === 34);
9476
9899
  if (directChildren) {
9477
- return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
9900
+ const framed2 = { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
9901
+ return gated ? meet(at, framed2) : framed2;
9478
9902
  }
9479
9903
  const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
9480
9904
  const raw = !hostCst && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags & 2) !== 0 ? RAW_OMIT : RAW_CAPTURE;
9481
9905
  if (at.buf && raw === at.raw && cap === at.cap) return at;
9482
- return { tri: at.tri, buf: true, raw, cap };
9906
+ const framed = { tri: at.tri, buf: true, raw, cap };
9907
+ return gated ? meet(at, framed) : framed;
9483
9908
  }
9484
9909
  if (op === OP_TOKEN) {
9485
9910
  if (at.tri === TRI_NONE && !at.buf) return at;
@@ -9517,6 +9942,40 @@ function computeSiteLabels(code, roots, hostCst) {
9517
9942
  }
9518
9943
  return { at: (ip) => labels.get(ip) ?? TOP };
9519
9944
  }
9945
+ function scopeIsIdentity(code, ip, at) {
9946
+ const op = code[ip];
9947
+ if (op !== OP_SCOPE_PLAIN && !(op === OP_SCOPE && code[ip + 3] === 0)) return false;
9948
+ const ki = code[ip + 1];
9949
+ return at.tri === (ki < 0 ? TRI_NONE : ki);
9950
+ }
9951
+ function scanHandoffNeeded(code, ip, labels) {
9952
+ const seen = /* @__PURE__ */ new Set();
9953
+ const stack = [ip];
9954
+ const kids = [];
9955
+ while (stack.length > 0) {
9956
+ const at = stack.pop();
9957
+ if (seen.has(at)) continue;
9958
+ seen.add(at);
9959
+ const l = labels.at(at);
9960
+ if (l.tri === TRI_UNKNOWN) return true;
9961
+ const op = code[at];
9962
+ if (op === OP_SCAN) return true;
9963
+ if (op === OP_TOKEN || op === OP_SCOPE_CAP) continue;
9964
+ 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;
9965
+ kids.length = 0;
9966
+ if (!childSlots(code, at, kids)) return true;
9967
+ for (const c of kids) stack.push(c);
9968
+ }
9969
+ return false;
9970
+ }
9971
+ function triviaLeadRanges(tri, trivia2) {
9972
+ if (tri === TRI_NONE) return [];
9973
+ if (tri < 0) return void 0;
9974
+ const fs3 = trivia2[tri]?._meta.firstSet;
9975
+ if (fs3 === void 0) return void 0;
9976
+ if (fs3.kind === "empty") return [];
9977
+ return fs3.kind === "ranges" && fs3.ranges !== void 0 ? fs3.ranges : void 0;
9978
+ }
9520
9979
 
9521
9980
  // src/table/scalar-terminal.ts
9522
9981
  function makeScalarRecognizer(op, spec) {
@@ -9554,6 +10013,12 @@ function scalarTerminalNotChild(code, ip) {
9554
10013
  const op = code[child];
9555
10014
  return op === OP_RX || op === OP_LIT ? child : -1;
9556
10015
  }
10016
+ function scalarTerminalPeekChild(code, ip) {
10017
+ if (code[ip] !== OP_PEEK) return -1;
10018
+ const child = code[ip + 1];
10019
+ const op = code[child];
10020
+ return op === OP_RX || op === OP_LIT ? child : -1;
10021
+ }
9557
10022
  function leadingScalarTerminal(code, ip, minDepth = 2, throughAttempt = true, throughPeek = false) {
9558
10023
  const seen = /* @__PURE__ */ new Set();
9559
10024
  let at = ip;
@@ -9731,6 +10196,59 @@ function leadingTriviaFieldAt(code, k, ip) {
9731
10196
  return code[ip] === OP_FIELD && (fieldSpec(k[code[ip + 1]]).bits & FIELD_LEADING_TRIVIA) !== 0;
9732
10197
  }
9733
10198
 
10199
+ // src/table/hold-gap.ts
10200
+ var WRAPPERS = /* @__PURE__ */ new Set([
10201
+ OP_NODE,
10202
+ OP_XFORM,
10203
+ OP_LEAF,
10204
+ OP_SOURCE_LEAF,
10205
+ OP_TOKEN,
10206
+ OP_SCOPE,
10207
+ OP_SCOPE_CAP,
10208
+ OP_SCOPE_PLAIN,
10209
+ OP_FIELD,
10210
+ OP_LABEL,
10211
+ OP_EXPECT,
10212
+ OP_WITHCTX,
10213
+ OP_RULE,
10214
+ OP_ATTEMPT,
10215
+ OP_COV
10216
+ ]);
10217
+ function rowNullable(code, k, ip, memo) {
10218
+ const hit = memo.get(ip);
10219
+ if (hit !== void 0) return hit;
10220
+ memo.set(ip, true);
10221
+ const op = code[ip];
10222
+ const kids = [];
10223
+ let out = true;
10224
+ if (op === OP_GATE) out = false;
10225
+ else if (op === OP_LIT || op === OP_LIT_CI) out = k[code[ip + 1]].length === 0;
10226
+ else if (op === OP_RX) {
10227
+ const re = k[code[ip + 1]];
10228
+ out = !(re instanceof RegExp) || regexCanMatchEmpty(re.source);
10229
+ } else if (op === OP_SEQ || op === OP_SEQV || op === OP_SEQX) {
10230
+ childSlots(code, ip, kids);
10231
+ out = kids.every((c) => rowNullable(code, k, c, memo));
10232
+ } else if (op === OP_CHOICE) {
10233
+ childSlots(code, ip, kids);
10234
+ out = kids.length === 0 || kids.some((c) => rowNullable(code, k, c, memo));
10235
+ } else if (op === OP_REP || op === OP_REPV) {
10236
+ out = code[ip + 2] === 0 || rowNullable(code, k, code[ip + 1], memo);
10237
+ } else if (WRAPPERS.has(op)) {
10238
+ if (childSlots(code, ip, kids) && kids.length === 1) out = rowNullable(code, k, kids[0], memo);
10239
+ }
10240
+ memo.set(ip, out);
10241
+ return out;
10242
+ }
10243
+ function holdsGap(code, k, base, n, i, memo) {
10244
+ if (i < 1 || i + 1 >= n) return false;
10245
+ const term = code[base + i];
10246
+ if (code[term] !== OP_NOT && code[term] !== OP_PEEK) return false;
10247
+ const next = code[base + i + 1];
10248
+ if (code[next] === OP_ADJ || leadingTriviaFieldAt(code, k, next)) return false;
10249
+ return !rowNullable(code, k, next, memo);
10250
+ }
10251
+
9734
10252
  // src/table/emit-assembly.ts
9735
10253
  var Unemittable = class extends Error {
9736
10254
  construct;
@@ -9811,7 +10329,10 @@ var EMITTED_PARAMS = [
9811
10329
  "triviaFieldCapture",
9812
10330
  // Appended for the deferred-commit trivia skip (`trivia-gap.ts`); old
9813
10331
  // factories ignore it.
9814
- "skipDeferredTrivia"
10332
+ "skipDeferredTrivia",
10333
+ // Appended for the pass-through collapse (`run-support.ts`); old factories
10334
+ // ignore it.
10335
+ "collapseEmpty"
9815
10336
  ];
9816
10337
  var RUNTIME_PRELUDE = `
9817
10338
  let _pfScan=null
@@ -10008,6 +10529,24 @@ ${fast}
10008
10529
  ${scanned}
10009
10530
  }`;
10010
10531
  }
10532
+ function emitHoldTerm(callee, dst, t, l, skip) {
10533
+ const fast = `const ${t}v=${callee}(input,cur,ctx)
10534
+ if(${t}v===FAIL)return FAIL
10535
+ ${dst}=${t}v
10536
+ cur=EC.e`;
10537
+ if (l.tri === TRI_NONE) return fast;
10538
+ const held = `const ${t}s=${skip}(input,cur,ctx)
10539
+ const ${t}v=${callee}(input,${t}s,ctx)
10540
+ if(${t}v===FAIL)return FAIL
10541
+ ${dst}=${t}v
10542
+ cur=${t}s`;
10543
+ if (l.tri !== TRI_UNKNOWN) return held;
10544
+ return `if(ctx.trivia===undefined){
10545
+ ${fast}
10546
+ }else{
10547
+ ${held}
10548
+ }`;
10549
+ }
10011
10550
  function leadSkip(hasTrivia, leadTrivia, skip) {
10012
10551
  if (hasTrivia === "false") return "{}";
10013
10552
  const call = `itemStart=${skip}(input,itemStart,ctx)`;
@@ -10049,6 +10588,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, se
10049
10588
  const reachable = [...reachableSites(code, roots)];
10050
10589
  const labels = computeSiteLabels(code, roots, hostCst);
10051
10590
  const scalarSpecs = /* @__PURE__ */ new Set();
10591
+ const nullable2 = /* @__PURE__ */ new Map();
10052
10592
  const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
10053
10593
  const largeChoiceLiteralFamilies = /* @__PURE__ */ new Map();
10054
10594
  const largeChoiceScalarSequences = /* @__PURE__ */ new Map();
@@ -10373,9 +10913,7 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
10373
10913
  const op = code[ip];
10374
10914
  if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
10375
10915
  if (op === OP_RULE) return code[ip + 1];
10376
- if ((op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[ip + 3] === 0) && code[ip + 1] >= 0 && labels.at(ip).tri === code[ip + 1]) {
10377
- return code[ip + 2];
10378
- }
10916
+ if (scopeIsIdentity(code, ip, labels.at(ip))) return code[ip + 2];
10379
10917
  return void 0;
10380
10918
  }
10381
10919
  function lower(ip, fname) {
@@ -10497,6 +11035,22 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
10497
11035
  return `${head}
10498
11036
  if(${gateMissTest(ip)}){ctx._fe=pos;ctx._fx=${xf};return FAIL}
10499
11037
  return ${child}(input,pos,ctx)
11038
+ }`;
11039
+ }
11040
+ case OP_RGATE: {
11041
+ const child = link(code[ip + 2]);
11042
+ if (cfg.tolerant || cfg.probe) return `${head}
11043
+ return ${child}(input,pos,ctx)
11044
+ }`;
11045
+ const resolved = t.cc[code[ip + 1]];
11046
+ const ci = classes.push([resolved]) - 1;
11047
+ classPlan.push([code[ip + 1]]);
11048
+ const cls = hoist("cl", `CLS[${ci}][0]`);
11049
+ const xf = fxRef(code[ip + 3]);
11050
+ return `${head}
11051
+ const it=ctx._routed
11052
+ if(it!==undefined&&it.span.start===pos&&!classHas(${cls},lead(input,it.span.end))){ctx._fe=it.span.end;ctx._fx=${xf};return FAIL}
11053
+ return ${child}(input,pos,ctx)
10500
11054
  }`;
10501
11055
  }
10502
11056
  case OP_ARMGATE: {
@@ -10771,23 +11325,33 @@ return FAIL
10771
11325
  const p = tmp();
10772
11326
  return `${head}
10773
11327
  ${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${emitMark(p, L.buf, L.raw, sinks)}
10774
- const v=${child}(input,pos,ctx)
11328
+ ${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
10775
11329
  ${emitRollback(p, L.buf, L.raw, sinks)}
10776
- if(v===FAIL){EC.e=pos;return null}
11330
+ ${cfg.probe ? "if(ctx._probe!==undefined)ctx._probe.best=pb??null\n" : ""}if(v===FAIL){EC.e=pos;return null}
10777
11331
  ctx._fe=pos
10778
11332
  ctx._fx=${xf}
10779
11333
  return FAIL
10780
11334
  }`;
10781
11335
  }
10782
11336
  case OP_PEEK: {
11337
+ const scalarChild = scalarTerminalPeekChild(code, ip);
11338
+ if (scalarChild >= 0) {
11339
+ const recognize = recognizerRef(code[scalarChild + 1]);
11340
+ const xf2 = fxRef(code[ip + 2]);
11341
+ return `${head}
11342
+ if(${recognize}(input,pos)<0){ctx._fe=pos;ctx._fx=${xf2};return FAIL}
11343
+ EC.e=pos
11344
+ return null
11345
+ }`;
11346
+ }
10783
11347
  const child = link(code[ip + 1]);
10784
11348
  const xf = fxRef(code[ip + 2]);
10785
11349
  const p = tmp();
10786
11350
  return `${head}
10787
11351
  ${lookaheadMiss(code[ip + 1], `ctx._fe=pos;ctx._fx=${xf};return FAIL`)}${emitMark(p, L.buf, L.raw, sinks)}
10788
- const v=${child}(input,pos,ctx)
11352
+ ${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
10789
11353
  ${emitRollback(p, L.buf, L.raw, sinks)}
10790
- if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
11354
+ ${cfg.probe ? "if(ctx._probe!==undefined)ctx._probe.best=pb??null\n" : ""}if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
10791
11355
  EC.e=pos
10792
11356
  return null
10793
11357
  }`;
@@ -10858,7 +11422,7 @@ return v
10858
11422
  );
10859
11423
  } else {
10860
11424
  const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
10861
- parts.push(emitTerm(callee, vn, tmp(), L, skipFor(L)));
11425
+ parts.push(holdsGap(code, k, base, n, i, nullable2) ? emitHoldTerm(callee, vn, tmp(), L, skipFor(L)) : emitTerm(callee, vn, tmp(), L, skipFor(L)));
10862
11426
  }
10863
11427
  names.push(vn);
10864
11428
  }
@@ -11341,6 +11905,26 @@ return nd
11341
11905
  const trailingTrivia = (flags & 128) !== 0;
11342
11906
  const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
11343
11907
  const leanFlags = flags & ~128;
11908
+ if (build !== void 0 && passCollapse(code, ip, hostCst)) {
11909
+ return `${head}
11910
+ const v=${child}(input,pos,ctx)
11911
+ if(v!==undefined)return v
11912
+ return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
11913
+ }`;
11914
+ }
11915
+ const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
11916
+ const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(labels.at(code[ip + 2]).tri, t.trivia);
11917
+ const gp = gated !== void 0 && triviaLead !== void 0 && triviaLead.length <= 16 ? `const gc=lead(input,pos)
11918
+ if(!(${[
11919
+ ...gated.leads.map((g) => `!(${gateMissTest(g)})`),
11920
+ ...gated.lits.map((i) => `gc===${k[i].codePointAt(0)}`),
11921
+ ...triviaLead.map((r) => r.lo === r.hi ? `gc===${r.lo}` : `(gc>=${r.lo}&&gc<=${r.hi})`)
11922
+ ].join("||") || "false"})){
11923
+ const gv=${link(gated.last)}(input,pos,ctx)
11924
+ if(gv!==undefined)return gv
11925
+ return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
11926
+ }
11927
+ ` : "";
11344
11928
  if (!hostCst && !tracked && build !== void 0 && proj < 0 && (leanFlags === 2 || (flags === 18 || flags === 34))) {
11345
11929
  const fields = flags === 18;
11346
11930
  const collapseChildren = flags === 34;
@@ -11375,7 +11959,7 @@ sCh.push(nd)
11375
11959
  if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
11376
11960
  }`;
11377
11961
  return `${head}
11378
- const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
11962
+ ${gp}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
11379
11963
  const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
11380
11964
  const flat=[]
11381
11965
  ctx._cstBuf=undefined
@@ -11450,7 +12034,7 @@ const hostKids=kids
11450
12034
  const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
11451
12035
  const tlog=buf.tl??EMPTY_TLOG`;
11452
12036
  return `${head}
11453
- const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
12037
+ ${!hostCst && !tracked ? gp : ""}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
11454
12038
  const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf
11455
12039
  ${openCapture}
11456
12040
  ctx.captureTrivia=${captureWide}
@@ -11520,9 +12104,15 @@ ext:[${externals.join(",")}],
11520
12104
  bind:function(xs,ps){_xScan=xs
11521
12105
  ${externals.map((ip, i) => `_xp${ip}=ps[${i}]`).join("\n")}},
11522
12106
  scan:function(s){const o=_pfScan;_pfScan=s;return o}`;
12107
+ const scannerFor = (ip) => {
12108
+ const ki = labels.at(ip).tri;
12109
+ if (ki === TRI_UNKNOWN) return "_pfScan";
12110
+ if (ki === TRI_NONE) return "null";
12111
+ return swapLegal && !triviaLabelled[ki] && t.triviaScan[ki] != null ? hoist("ts", `TRIVIASCAN[${ki}]`) : "null";
12112
+ };
11523
12113
  const externalDefs = select === void 0 ? "" : `let _xScan
11524
12114
  ${externals.map((ip) => `let _xp${ip}
11525
- function _px${ip}(input,pos,ctx){const o=_xScan(_pfScan);const v=_xp${ip}(input,pos,ctx);_xScan(o);return v}`).join("\n")}
12115
+ function _px${ip}(input,pos,ctx){const o=_xScan(${scannerFor(ip)});const v=_xp${ip}(input,pos,ctx);_xScan(o);return v}`).join("\n")}
11526
12116
  `;
11527
12117
  const source = `${RUNTIME_PRELUDE}${needsNoRawPrelude ? NO_RAW_RUNTIME_PRELUDE : ""}
11528
12118
  ${prelude.join("\n")}
@@ -12059,37 +12649,120 @@ function clearOf(ranges, input, from, to) {
12059
12649
  return true;
12060
12650
  }
12061
12651
 
12062
- // src/table/run-support.ts
12063
- function lineCol(ctx, offset) {
12064
- const starts = ctx._lineStarts ?? [0];
12065
- let lo = 0, hi = starts.length - 1;
12066
- while (lo < hi) {
12067
- const mid = lo + hi + 1 >> 1;
12068
- if (starts[mid] <= offset) lo = mid;
12069
- else hi = mid - 1;
12652
+ // src/table/fail-clean.ts
12653
+ function passChild(code, ip) {
12654
+ switch (code[ip]) {
12655
+ case OP_RULE:
12656
+ case OP_LABEL:
12657
+ case OP_COV:
12658
+ case OP_TOKEN:
12659
+ return code[ip + 1];
12660
+ case OP_GATE:
12661
+ case OP_NODE:
12662
+ case OP_NODE_TRACK:
12663
+ case OP_XFORM:
12664
+ case OP_FIELD:
12665
+ case OP_SCOPE:
12666
+ case OP_SCOPE_CAP:
12667
+ case OP_SCOPE_PLAIN:
12668
+ case OP_WITHCTX:
12669
+ case OP_LEAF:
12670
+ case OP_SOURCE_LEAF:
12671
+ return code[ip + 2];
12672
+ default:
12673
+ return -1;
12070
12674
  }
12071
- return [lo + 1, offset - starts[lo] + 1];
12072
- }
12073
- function spanLines(ctx, start, end) {
12074
- const s = lineCol(ctx, start), e = lineCol(ctx, end);
12075
- return { start, end, startLine: s[0], startColumn: s[1], endLine: e[0], endColumn: e[1] };
12076
12675
  }
12077
- function rawEntry(v, input, s, e) {
12078
- if (typeof v === "object" && v !== null) {
12079
- const tg = v._tag;
12080
- if (tg === "node" || tg === "leaf" || tg === "parseError") return v;
12081
- }
12082
- return {
12083
- _tag: "leaf",
12084
- value: typeof v === "string" ? v : typeof v === "object" && v !== null ? input.slice(s, e) : "",
12085
- span: { start: s, end: e }
12676
+ function seqCount(code, ip) {
12677
+ const op = code[ip];
12678
+ return op === OP_SEQ || op === OP_SEQV ? ip + 1 : op === OP_SEQX ? ip + 2 : -1;
12679
+ }
12680
+ function failCleanAnalysis(code) {
12681
+ const cleanAt = new Uint8Array(code.length);
12682
+ const neverAt = new Uint8Array(code.length);
12683
+ const neverFails = (ip) => {
12684
+ const hit = neverAt[ip];
12685
+ if (hit !== 0) return hit === 1;
12686
+ neverAt[ip] = 3;
12687
+ let out = false;
12688
+ const op = code[ip];
12689
+ if (op === OP_OPT || op === OP_EMPTY || op === OP_EXPECT) out = true;
12690
+ else if (op === OP_REP || op === OP_REPV) out = code[ip + 2] === 0;
12691
+ else {
12692
+ const at = seqCount(code, ip);
12693
+ if (at >= 0) {
12694
+ out = true;
12695
+ for (let i = 1, n = code[at]; out && i <= n; i++) out = neverFails(code[at + i]);
12696
+ } else if (op !== OP_GATE) {
12697
+ const c = passChild(code, ip);
12698
+ out = c >= 0 && neverFails(c);
12699
+ }
12700
+ }
12701
+ neverAt[ip] = out ? 1 : 2;
12702
+ return out;
12086
12703
  };
12087
- }
12088
- function lead(input, pos) {
12089
- if (pos >= input.length) return -1;
12090
- const c = input.charCodeAt(pos);
12091
- if (c < 55296 || c > 56319) return c;
12092
- return input.codePointAt(pos) ?? c;
12704
+ const clean = (ip) => {
12705
+ const hit = cleanAt[ip];
12706
+ if (hit !== 0) return hit === 1;
12707
+ cleanAt[ip] = 3;
12708
+ let out = false;
12709
+ switch (code[ip]) {
12710
+ // A terminal pushes its leaf only on a match; NOT/PEEK/ATTEMPT restore
12711
+ // their own mark; OPT, EMPTY and EXPECT do not fail uncommitted.
12712
+ case OP_LIT:
12713
+ case OP_RX:
12714
+ case OP_LIT_TRACK:
12715
+ case OP_RX_TRACK:
12716
+ case OP_LIT_CI:
12717
+ case OP_LIT_CI_TRACK:
12718
+ case OP_GUARD:
12719
+ case OP_NOT:
12720
+ case OP_PEEK:
12721
+ case OP_ATTEMPT:
12722
+ case OP_EMPTY:
12723
+ case OP_OPT:
12724
+ case OP_EXPECT:
12725
+ out = true;
12726
+ break;
12727
+ // Min 0 does not fail uncommitted; min 1 fails only with no item kept, and
12728
+ // restores the failed item itself.
12729
+ case OP_REP:
12730
+ case OP_REPV:
12731
+ out = code[ip + 2] <= 1;
12732
+ break;
12733
+ // Only the first term may fail: a later one fails after the terms before it
12734
+ // wrote, and after the trivia scanned in front of it.
12735
+ case OP_SEQ:
12736
+ case OP_SEQV:
12737
+ case OP_SEQX: {
12738
+ const at = seqCount(code, ip);
12739
+ const n = code[at];
12740
+ out = n > 0 && clean(code[at + 1]);
12741
+ for (let i = 2; out && i <= n; i++) out = neverFails(code[at + i]);
12742
+ break;
12743
+ }
12744
+ case OP_CHOICE: {
12745
+ out = true;
12746
+ for (let i = 0, n = code[ip + 2]; out && i < n; i++) out = clean(code[ip + 4 + i]);
12747
+ break;
12748
+ }
12749
+ case OP_ROUTED:
12750
+ out = code[ip + 1] < 0 || clean(code[ip + 1]);
12751
+ break;
12752
+ // An arm's failure and the fallback's are committed; only the selector's is
12753
+ // not, and without a fallback an unknown key fails after the selector wrote.
12754
+ case OP_DISPATCH:
12755
+ out = code[ip + 3] >= 0 && clean(code[ip + 1]);
12756
+ break;
12757
+ default: {
12758
+ const c = passChild(code, ip);
12759
+ out = c >= 0 && clean(c);
12760
+ }
12761
+ }
12762
+ cleanAt[ip] = out ? 1 : 2;
12763
+ return out;
12764
+ };
12765
+ return clean;
12093
12766
  }
12094
12767
 
12095
12768
  // src/cst/host-mode.ts
@@ -12254,6 +12927,7 @@ function assemble(t, prog, cfg) {
12254
12927
  const swapLegal = !cfg.trackLines;
12255
12928
  const hostCst = cfg.hostCst;
12256
12929
  const REC2 = prog.rec === 1 && cfg.tolerant;
12930
+ const PROBE = cfg.probe;
12257
12931
  const sentinels = /* @__PURE__ */ new Map();
12258
12932
  function sentinelFor(cls) {
12259
12933
  if (cls < 0) return void 0;
@@ -12299,6 +12973,8 @@ function assemble(t, prog, cfg) {
12299
12973
  }
12300
12974
  const memo = /* @__PURE__ */ new Map();
12301
12975
  const reached = /* @__PURE__ */ new Set();
12976
+ const NULLABLE = /* @__PURE__ */ new Map();
12977
+ const CLEAN = REC2 ? () => false : failCleanAnalysis(code);
12302
12978
  function pushLeaf(ctx, value, s, e) {
12303
12979
  const lf = { _tag: "leaf", value, span: { start: s, end: e } };
12304
12980
  pushCstLeaf(ctx, lf);
@@ -12497,6 +13173,22 @@ function assemble(t, prog, cfg) {
12497
13173
  return node2;
12498
13174
  };
12499
13175
  }
13176
+ function passCollapseNode(child, build, readsRaw) {
13177
+ return (input, pos, ctx) => {
13178
+ const v = child(input, pos, ctx);
13179
+ if (v !== void 0) return v;
13180
+ return collapseEmpty(ctx, build, input, pos, EC.e, readsRaw);
13181
+ };
13182
+ }
13183
+ function gatedPassCollapseNode(blockers, last, classic, build, readsRaw) {
13184
+ return (input, pos, ctx) => {
13185
+ const c = lead(input, pos);
13186
+ for (let i = 0; i < blockers.length; i++) if (classHas2(blockers[i], c)) return classic(input, pos, ctx);
13187
+ const v = last(input, pos, ctx);
13188
+ if (v !== void 0) return v;
13189
+ return collapseEmpty(ctx, build, input, pos, EC.e, readsRaw);
13190
+ };
13191
+ }
12500
13192
  function plainProjectNode(child, projection, type) {
12501
13193
  return (input, pos, ctx) => {
12502
13194
  const sCh = ctx._cstChildren;
@@ -12867,21 +13559,27 @@ function assemble(t, prog, cfg) {
12867
13559
  }
12868
13560
  function dispatchBranch(child, usesRouted) {
12869
13561
  if (!usesRouted) {
12870
- return (input, _pos, selEnd, key, _selectorMark, ctx) => {
12871
- const mark = saveTriviaMark(ctx);
13562
+ return (input, _pos, selEnd, key, ctx) => {
13563
+ const need = markCst(ctx);
13564
+ const mRaw = MRAW;
13565
+ const mTl = MTL;
13566
+ const mLv = MLV;
13567
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
13568
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
13569
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
13570
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
12872
13571
  const v = child(input, selEnd, ctx);
12873
13572
  if (v === FAIL) {
12874
- rollbackTrivia(ctx, mark);
13573
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12875
13574
  ctx._fc = true;
12876
13575
  return FAIL;
12877
13576
  }
12878
13577
  return [key, v];
12879
13578
  };
12880
13579
  }
12881
- return (input, pos, selEnd, key, selectorMark, ctx) => {
13580
+ return (input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot) => {
12882
13581
  const savedRouted = ctx._routed;
12883
- rollbackTrivia(ctx, selectorMark);
12884
- const mark = saveTriviaMark(ctx);
13582
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12885
13583
  ctx._routed = { value: key, span: { start: pos, end: selEnd } };
12886
13584
  let v;
12887
13585
  try {
@@ -12890,7 +13588,7 @@ function assemble(t, prog, cfg) {
12890
13588
  ctx._routed = savedRouted;
12891
13589
  }
12892
13590
  if (v === FAIL) {
12893
- rollbackTrivia(ctx, mark);
13591
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12894
13592
  ctx._fc = true;
12895
13593
  return FAIL;
12896
13594
  }
@@ -12898,12 +13596,12 @@ function assemble(t, prog, cfg) {
12898
13596
  };
12899
13597
  }
12900
13598
  function dispatchArmBlock(start, a0, a1, a2, a3, next) {
12901
- return (arm, input, pos, selEnd, key, selectorMark, ctx) => {
12902
- if (arm === start) return a0(input, pos, selEnd, key, selectorMark, ctx);
12903
- if (arm === start + 1) return a1(input, pos, selEnd, key, selectorMark, ctx);
12904
- if (arm === start + 2) return a2(input, pos, selEnd, key, selectorMark, ctx);
12905
- if (arm === start + 3) return a3(input, pos, selEnd, key, selectorMark, ctx);
12906
- return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key, selectorMark, ctx);
13599
+ return (arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot) => {
13600
+ if (arm === start) return a0(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
13601
+ if (arm === start + 1) return a1(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
13602
+ if (arm === start + 2) return a2(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
13603
+ if (arm === start + 3) return a3(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
13604
+ return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12907
13605
  };
12908
13606
  }
12909
13607
  function trackLinesInto(ctx, input, end) {
@@ -12922,7 +13620,7 @@ function assemble(t, prog, cfg) {
12922
13620
  if (flight !== void 0) return flight.fwd;
12923
13621
  const selected = HYBRID?.byIp[ip];
12924
13622
  if (selected !== void 0) {
12925
- const piece2 = hybridPiece(selected);
13623
+ const piece2 = scanHandoffNeeded(code, ip, closureLabels) ? hybridPiece(selected) : selected;
12926
13624
  memo.set(ip, piece2);
12927
13625
  reached.add(ip);
12928
13626
  return piece2;
@@ -12933,14 +13631,55 @@ function assemble(t, prog, cfg) {
12933
13631
  target = p;
12934
13632
  } };
12935
13633
  inFlight.set(ip, holder);
12936
- const op = code[ip];
12937
- 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);
13634
+ const piece = scopeIsIdentity(code, ip, closureLabels.at(ip)) ? link(code[ip + 2]) : countedPiece(lookaheadLedNode(ip) ?? lower(ip), ip);
12938
13635
  inFlight.delete(ip);
12939
13636
  holder.set(piece);
12940
13637
  memo.set(ip, piece);
12941
13638
  reached.add(ip);
12942
13639
  return piece;
12943
13640
  }
13641
+ let FIRST_DECIDED;
13642
+ let NODE_BODY;
13643
+ const DECIDED = (_input, pos) => {
13644
+ EC.e = pos;
13645
+ return null;
13646
+ };
13647
+ function lookaheadLedNode(ip) {
13648
+ const op = code[ip];
13649
+ if (op !== OP_NODE && op !== OP_NODE_TRACK || hostCst || REC2 || cfg.probe || cfg.coverage || cfg.trackLines) return void 0;
13650
+ if (passCollapse(code, ip, hostCst) || gatedPassCollapse(code, ip, hostCst) !== void 0) return void 0;
13651
+ const body = code[ip + 2];
13652
+ const bop = code[body];
13653
+ if (bop !== OP_SEQ && bop !== OP_SEQV && bop !== OP_SEQX) return void 0;
13654
+ const base = bop === OP_SEQX ? body + 3 : body + 2;
13655
+ if (code[bop === OP_SEQX ? body + 2 : body + 1] < 2) return void 0;
13656
+ const first = code[base];
13657
+ const negative = code[first] === OP_NOT;
13658
+ const terminal = negative ? scalarTerminalNotChild(code, first) : code[first] === OP_PEEK ? scalarTerminalPeekChild(code, first) : -1;
13659
+ if (terminal < 0) return void 0;
13660
+ const recognize = scalarFor(terminal);
13661
+ const xf = fx[code[first + 2]];
13662
+ FIRST_DECIDED = DECIDED;
13663
+ NODE_BODY = lower(body);
13664
+ const node2 = lower(ip);
13665
+ NODE_BODY = void 0;
13666
+ return negative ? (input, pos, ctx) => {
13667
+ if (recognize(input, pos) >= 0) {
13668
+ ctx._fe = pos;
13669
+ ctx._fx = xf;
13670
+ EC.e = pos;
13671
+ return FAIL;
13672
+ }
13673
+ return node2(input, pos, ctx);
13674
+ } : (input, pos, ctx) => {
13675
+ if (recognize(input, pos) < 0) {
13676
+ ctx._fe = pos;
13677
+ ctx._fx = xf;
13678
+ return FAIL;
13679
+ }
13680
+ return node2(input, pos, ctx);
13681
+ };
13682
+ }
12944
13683
  function lower(ip) {
12945
13684
  const op = code[ip];
12946
13685
  switch (op) {
@@ -13485,8 +14224,10 @@ function assemble(t, prog, cfg) {
13485
14224
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
13486
14225
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
13487
14226
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
14227
+ const probeBest = PROBE ? ctx._probe?.best : void 0;
13488
14228
  const v = child(input, pos, ctx);
13489
14229
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14230
+ if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
13490
14231
  if (v === FAIL) {
13491
14232
  EC.e = pos;
13492
14233
  return null;
@@ -13497,6 +14238,20 @@ function assemble(t, prog, cfg) {
13497
14238
  };
13498
14239
  }
13499
14240
  case OP_PEEK: {
14241
+ const scalarChild = scalarTerminalPeekChild(code, ip);
14242
+ if (scalarChild >= 0) {
14243
+ const recognize = scalarFor(scalarChild);
14244
+ const xf2 = fx[code[ip + 2]];
14245
+ return (input, pos, ctx) => {
14246
+ if (recognize(input, pos) < 0) {
14247
+ ctx._fe = pos;
14248
+ ctx._fx = xf2;
14249
+ return FAIL;
14250
+ }
14251
+ EC.e = pos;
14252
+ return null;
14253
+ };
14254
+ }
13500
14255
  const child = link(code[ip + 1]);
13501
14256
  const xf = fx[code[ip + 2]];
13502
14257
  const gate2 = lookaheadClass(code[ip + 1]);
@@ -13514,8 +14269,10 @@ function assemble(t, prog, cfg) {
13514
14269
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
13515
14270
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
13516
14271
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
14272
+ const probeBest = PROBE ? ctx._probe?.best : void 0;
13517
14273
  const v = child(input, pos, ctx);
13518
14274
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14275
+ if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
13519
14276
  if (v === FAIL) {
13520
14277
  ctx._fe = pos;
13521
14278
  ctx._fx = xf;
@@ -13528,12 +14285,13 @@ function assemble(t, prog, cfg) {
13528
14285
  case OP_OPT: {
13529
14286
  const child = link(code[ip + 1]);
13530
14287
  const gate2 = lookaheadClass(code[ip + 1]);
14288
+ const childClean = CLEAN(code[ip + 1]);
13531
14289
  return (input, pos, ctx) => {
13532
14290
  if (gate2 !== null && !classHas2(gate2, lead(input, pos))) {
13533
14291
  EC.e = pos;
13534
14292
  return null;
13535
14293
  }
13536
- const need = markCst(ctx);
14294
+ const need = !childClean && markCst(ctx);
13537
14295
  const mRaw = MRAW;
13538
14296
  const mTl = MTL;
13539
14297
  const mLv = MLV;
@@ -13731,6 +14489,9 @@ function assemble(t, prog, cfg) {
13731
14489
  const projection = reducer < 0 ? ~reducer : -1;
13732
14490
  const fn = fused && projection < 0 ? fns[reducer] : void 0;
13733
14491
  const step = closureLabels.at(ip).buf ? nextTermBuffered : nextTerm;
14492
+ const decided = FIRST_DECIDED;
14493
+ FIRST_DECIDED = void 0;
14494
+ const linkFirst = () => decided ?? link(code[base]);
13734
14495
  const runnerBlock = (count, r0, r1, r2, r3, next) => {
13735
14496
  if (count === 1) return (input, cur, ctx, values, inherited) => {
13736
14497
  cur = r0(input, cur, ctx, inherited);
@@ -13776,7 +14537,7 @@ function assemble(t, prog, cfg) {
13776
14537
  };
13777
14538
  };
13778
14539
  if (REC2) {
13779
- const first2 = link(code[base]);
14540
+ const first2 = linkFirst();
13780
14541
  const firstSync = sentinelFor(code[base + n]);
13781
14542
  const runnerAt = (i) => {
13782
14543
  const sync = sentinelFor(code[base + n + i]);
@@ -13812,13 +14573,13 @@ function assemble(t, prog, cfg) {
13812
14573
  const bindRunners = (start) => {
13813
14574
  const count = Math.min(4, n - start);
13814
14575
  const at = (offset) => runnerAt(start + offset);
13815
- const never = () => -1;
14576
+ const never2 = () => -1;
13816
14577
  return runnerBlock(
13817
14578
  count,
13818
14579
  at(0),
13819
- count > 1 ? at(1) : never,
13820
- count > 2 ? at(2) : never,
13821
- count > 3 ? at(3) : never,
14580
+ count > 1 ? at(1) : never2,
14581
+ count > 2 ? at(2) : never2,
14582
+ count > 3 ? at(3) : never2,
13822
14583
  start + count < n ? bindRunners(start + count) : void 0
13823
14584
  );
13824
14585
  };
@@ -13868,15 +14629,31 @@ function assemble(t, prog, cfg) {
13868
14629
  let hasAdj = false;
13869
14630
  for (let i = 1; i < n; i++) {
13870
14631
  const kidIp = code[base + i];
13871
- if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp)) {
14632
+ if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp) || holdsGap(code, k, base, n, i, NULLABLE)) {
13872
14633
  hasAdj = true;
13873
14634
  break;
13874
14635
  }
13875
14636
  }
13876
14637
  if (hasAdj) {
13877
- const first2 = link(code[base]);
14638
+ const first2 = linkFirst();
13878
14639
  const runnerAt = (i) => {
13879
14640
  const kidIp = code[base + i];
14641
+ if (holdsGap(code, k, base, n, i, NULLABLE)) {
14642
+ const kid = link(kidIp);
14643
+ return (input, cur, ctx) => {
14644
+ if (ctx.trivia === void 0) {
14645
+ const v2 = kid(input, cur, ctx);
14646
+ if (v2 === FAIL) return -1;
14647
+ TERMV = v2;
14648
+ return EC.e;
14649
+ }
14650
+ const scanEnd = skipTrivia(input, cur, ctx);
14651
+ const v = kid(input, scanEnd, ctx);
14652
+ if (v === FAIL) return -1;
14653
+ TERMV = v;
14654
+ return scanEnd;
14655
+ };
14656
+ }
13880
14657
  if (code[kidIp] !== OP_ADJ) {
13881
14658
  const kid = link(kidIp);
13882
14659
  if (leadingTriviaFieldAt(code, k, kidIp)) {
@@ -13901,13 +14678,13 @@ function assemble(t, prog, cfg) {
13901
14678
  const bindRunners = (start) => {
13902
14679
  const count = Math.min(4, n - start);
13903
14680
  const at = (offset) => runnerAt(start + offset);
13904
- const never = () => -1;
14681
+ const never2 = () => -1;
13905
14682
  return runnerBlock(
13906
14683
  count,
13907
14684
  at(0),
13908
- count > 1 ? at(1) : never,
13909
- count > 2 ? at(2) : never,
13910
- count > 3 ? at(3) : never,
14685
+ count > 1 ? at(1) : never2,
14686
+ count > 2 ? at(2) : never2,
14687
+ count > 3 ? at(3) : never2,
13911
14688
  start + count < n ? bindRunners(start + count) : void 0
13912
14689
  );
13913
14690
  };
@@ -13944,7 +14721,7 @@ function assemble(t, prog, cfg) {
13944
14721
  };
13945
14722
  }
13946
14723
  if (n === 1) {
13947
- const k0 = link(code[base]);
14724
+ const k0 = linkFirst();
13948
14725
  if (fused) {
13949
14726
  return (input, pos, ctx) => {
13950
14727
  const v = k0(input, pos, ctx);
@@ -13966,7 +14743,7 @@ function assemble(t, prog, cfg) {
13966
14743
  };
13967
14744
  }
13968
14745
  if (n === 2) {
13969
- const k0 = link(code[base]), k1 = link(code[base + 1]);
14746
+ const k0 = linkFirst(), k1 = link(code[base + 1]);
13970
14747
  if (fused) {
13971
14748
  return (input, pos, ctx) => {
13972
14749
  const v0 = k0(input, pos, ctx);
@@ -13997,7 +14774,7 @@ function assemble(t, prog, cfg) {
13997
14774
  };
13998
14775
  }
13999
14776
  if (n === 3) {
14000
- const k0 = link(code[base]), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
14777
+ const k0 = linkFirst(), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
14001
14778
  if (fused) {
14002
14779
  return (input, pos, ctx) => {
14003
14780
  const v0 = k0(input, pos, ctx);
@@ -14091,7 +14868,7 @@ function assemble(t, prog, cfg) {
14091
14868
  start + count < n ? bind(start + count) : void 0
14092
14869
  );
14093
14870
  };
14094
- const first = link(code[base]);
14871
+ const first = linkFirst();
14095
14872
  const tail = bind(1);
14096
14873
  const runDirectTerms = (input, pos, ctx, values) => {
14097
14874
  const v0 = first(input, pos, ctx);
@@ -14130,6 +14907,8 @@ function assemble(t, prog, cfg) {
14130
14907
  const n = code[ip + 2];
14131
14908
  const choiceFx = fx[code[ip + 3]];
14132
14909
  const base = ip + 4;
14910
+ for (let i = 0; i < n; i++) link(code[base + i]);
14911
+ const armsClean = CLEAN(ip);
14133
14912
  if (table.exclusive) {
14134
14913
  const ascii = table.ascii;
14135
14914
  const hi = table.hi;
@@ -14269,7 +15048,7 @@ function assemble(t, prog, cfg) {
14269
15048
  if (n === 3) addGate(g2, 4);
14270
15049
  return (input, pos, ctx) => {
14271
15050
  const c = lead(input, pos);
14272
- const need = markCst(ctx);
15051
+ const need = !armsClean && markCst(ctx);
14273
15052
  const mRaw = MRAW;
14274
15053
  const mTl = MTL;
14275
15054
  const mLv = MLV;
@@ -14486,7 +15265,7 @@ function assemble(t, prog, cfg) {
14486
15265
  if (pn !== 0) {
14487
15266
  return (input, pos, ctx) => {
14488
15267
  const c = lead(input, pos);
14489
- const need = markCst(ctx);
15268
+ const need = !armsClean && markCst(ctx);
14490
15269
  const mRaw = MRAW;
14491
15270
  const mTl = MTL;
14492
15271
  const mLv = MLV;
@@ -14543,7 +15322,7 @@ function assemble(t, prog, cfg) {
14543
15322
  }
14544
15323
  return (input, pos, ctx) => {
14545
15324
  const c = lead(input, pos);
14546
- const need = markCst(ctx);
15325
+ const need = !armsClean && markCst(ctx);
14547
15326
  const mRaw = MRAW;
14548
15327
  const mTl = MTL;
14549
15328
  const mLv = MLV;
@@ -14591,7 +15370,7 @@ function assemble(t, prog, cfg) {
14591
15370
  }
14592
15371
  return (input, pos, ctx) => {
14593
15372
  const c = lead(input, pos);
14594
- const need = markCst(ctx);
15373
+ const need = !armsClean && markCst(ctx);
14595
15374
  const mRaw = MRAW;
14596
15375
  const mTl = MTL;
14597
15376
  const mLv = MLV;
@@ -14645,6 +15424,21 @@ function assemble(t, prog, cfg) {
14645
15424
  return lit(input, pos, ctx);
14646
15425
  };
14647
15426
  }
15427
+ case OP_RGATE: {
15428
+ const cls = cc[code[ip + 1]];
15429
+ const xf = fx[code[ip + 3]];
15430
+ const child = link(code[ip + 2]);
15431
+ if (cfg.tolerant || cfg.probe) return child;
15432
+ return (input, pos, ctx) => {
15433
+ const item = ctx._routed;
15434
+ if (item !== void 0 && item.span.start === pos && !classHas2(cls, lead(input, item.span.end))) {
15435
+ ctx._fe = item.span.end;
15436
+ ctx._fx = xf;
15437
+ return FAIL;
15438
+ }
15439
+ return child(input, pos, ctx);
15440
+ };
15441
+ }
14648
15442
  case OP_ARMGATE: {
14649
15443
  const pred = fns[code[ip + 1]];
14650
15444
  const child = link(code[ip + 2]);
@@ -14713,6 +15507,7 @@ function assemble(t, prog, cfg) {
14713
15507
  const itemClass = !REC2 && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
14714
15508
  const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
14715
15509
  const skipBeforeFirst = sepIp < 0 && min === 0;
15510
+ const itemClean = sepIp < 0 && CLEAN(code[ip + 1]) && !rowNullable(code, k, code[ip + 1], NULLABLE);
14716
15511
  if (REC2) {
14717
15512
  const itemFx2 = fx[code[ip + 6]];
14718
15513
  const sepSent = sentinelFor(code[ip + 7]);
@@ -14809,6 +15604,8 @@ function assemble(t, prog, cfg) {
14809
15604
  const out = collect ? [] : void 0;
14810
15605
  const hasTrivia = ctx.trivia !== void 0;
14811
15606
  const needMark = rollbackNeeded(ctx);
15607
+ const markLater = needMark && (!itemClean || hasTrivia);
15608
+ const markFirst = needMark && (!itemClean || hasTrivia && skipBeforeFirst);
14812
15609
  const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
14813
15610
  let cur = pos;
14814
15611
  let count = 0;
@@ -14816,14 +15613,15 @@ function assemble(t, prog, cfg) {
14816
15613
  if (max >= 0 && count >= max) break;
14817
15614
  if (sep2 !== void 0 && count > 0 && count >= min && cur >= input.length) break;
14818
15615
  if (count >= min && sep2 === void 0 && !hasTrivia && gateItems && !itemMayStart(input, cur)) break;
14819
- if (needMark) markCst(ctx);
14820
- const mRaw = needMark ? MRAW : 0;
14821
- const mTl = needMark ? MTL : 0;
14822
- const mLv = needMark ? MLV : 0;
14823
- const mFl = needMark ? ctx._fields?.length ?? 0 : 0;
14824
- const mEr = needMark ? ctx._errors?.length ?? 0 : 0;
14825
- const mLog = needMark ? ctx._triviaLog?.length ?? 0 : 0;
14826
- const mRoot = needMark ? ctx._rootTriviaLog?.length ?? 0 : 0;
15616
+ const markIt = count > 0 ? markLater : markFirst;
15617
+ if (markIt) markCst(ctx);
15618
+ const mRaw = markIt ? MRAW : 0;
15619
+ const mTl = markIt ? MTL : 0;
15620
+ const mLv = markIt ? MLV : 0;
15621
+ const mFl = markIt ? ctx._fields?.length ?? 0 : 0;
15622
+ const mEr = markIt ? ctx._errors?.length ?? 0 : 0;
15623
+ const mLog = markIt ? ctx._triviaLog?.length ?? 0 : 0;
15624
+ const mRoot = markIt ? ctx._rootTriviaLog?.length ?? 0 : 0;
14827
15625
  let itemStart = cur;
14828
15626
  let sepEnd = -1;
14829
15627
  const viaRepItem = sep2 === void 0 && count >= min && (count > 0 || skipBeforeFirst);
@@ -14835,7 +15633,7 @@ function assemble(t, prog, cfg) {
14835
15633
  if (sepLeads) LEAD.at = cur;
14836
15634
  const sv = sep2(input, sp, ctx);
14837
15635
  if (sv === FAIL) {
14838
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
15636
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14839
15637
  if (committed3(ctx)) return FAIL;
14840
15638
  break;
14841
15639
  }
@@ -14846,25 +15644,25 @@ function assemble(t, prog, cfg) {
14846
15644
  itemStart = skipTrivia(input, itemStart, ctx);
14847
15645
  }
14848
15646
  if (itemStart >= input.length && viaRepItem) {
14849
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
15647
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14850
15648
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
14851
15649
  break;
14852
15650
  }
14853
15651
  if (count >= min && gateItems && !itemMayStart(input, itemStart)) {
14854
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
15652
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14855
15653
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
14856
15654
  break;
14857
15655
  }
14858
15656
  ctx._fc = false;
14859
15657
  const v = child(input, itemStart, ctx);
14860
15658
  if (v === FAIL) {
14861
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
15659
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14862
15660
  if (committed3(ctx)) return FAIL;
14863
15661
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
14864
15662
  break;
14865
15663
  }
14866
15664
  if (EC.e === itemStart && viaRepItem) {
14867
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
15665
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14868
15666
  break;
14869
15667
  }
14870
15668
  if (out !== void 0) out.push(v);
@@ -14938,7 +15736,14 @@ function assemble(t, prog, cfg) {
14938
15736
  const runArm = n === 0 ? void 0 : bindArms(0);
14939
15737
  const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted);
14940
15738
  return (input, pos, ctx) => {
14941
- const selectorMark = saveTriviaMark(ctx);
15739
+ const need = markCst(ctx);
15740
+ const mRaw = MRAW;
15741
+ const mTl = MTL;
15742
+ const mLv = MLV;
15743
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
15744
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
15745
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
15746
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
14942
15747
  const selVal = selector(input, pos, ctx);
14943
15748
  if (selVal === FAIL) return FAIL;
14944
15749
  const selEnd = EC.e;
@@ -14950,9 +15755,9 @@ function assemble(t, prog, cfg) {
14950
15755
  ctx._fx = expected;
14951
15756
  return FAIL;
14952
15757
  }
14953
- return runOther(input, pos, selEnd, key, selectorMark, ctx);
15758
+ return runOther(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14954
15759
  }
14955
- return runArm(arm, input, pos, selEnd, key, selectorMark, ctx);
15760
+ return runArm(arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14956
15761
  };
14957
15762
  }
14958
15763
  /* ── node ────────────────────────────────────────────────────────────── */
@@ -14988,7 +15793,8 @@ function assemble(t, prog, cfg) {
14988
15793
  return nd;
14989
15794
  };
14990
15795
  }
14991
- const child = link(code[ip + 2]);
15796
+ const child = NODE_BODY ?? link(code[ip + 2]);
15797
+ NODE_BODY = void 0;
14992
15798
  const proj = code[ip + 4];
14993
15799
  const buildIdx = code[ip + 1];
14994
15800
  const type = k[code[ip + 5]];
@@ -15012,6 +15818,30 @@ function assemble(t, prog, cfg) {
15012
15818
  if (build !== void 0 && proj < 0 && flags === 18) {
15013
15819
  return childrenOnlyFieldsBuildNode(child, build);
15014
15820
  }
15821
+ if (build !== void 0 && passCollapse(code, ip, hostCst)) {
15822
+ return passCollapseNode(child, build, flags === 32);
15823
+ }
15824
+ const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
15825
+ const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(closureLabels.at(code[ip + 2]).tri, trivia2);
15826
+ if (build !== void 0 && gated !== void 0 && triviaLead !== void 0) {
15827
+ const classic = flags === 32 ? collapseBuildNode(child, build) : childrenOnlyCollapseBuildNode(child, build);
15828
+ return gatedPassCollapseNode(
15829
+ [
15830
+ ...gated.leads.map((g) => cc[code[g + 1]]),
15831
+ resolveClass(encodeClassSpec([
15832
+ ...triviaLead,
15833
+ ...gated.lits.map((i) => {
15834
+ const c = k[i].codePointAt(0);
15835
+ return { lo: c, hi: c };
15836
+ })
15837
+ ]))
15838
+ ],
15839
+ link(gated.last),
15840
+ classic,
15841
+ build,
15842
+ flags === 32
15843
+ );
15844
+ }
15015
15845
  if (build !== void 0 && proj < 0 && flags === 32) {
15016
15846
  return collapseBuildNode(child, build);
15017
15847
  }
@@ -15160,6 +15990,8 @@ function assemble(t, prog, cfg) {
15160
15990
  }
15161
15991
  const notChild = scalarTerminalNotChild(code, ip);
15162
15992
  if (notChild >= 0) scalarFor(notChild);
15993
+ const peekChild = scalarTerminalPeekChild(code, ip);
15994
+ if (peekChild >= 0) scalarFor(peekChild);
15163
15995
  }
15164
15996
  const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
15165
15997
  if (pre !== void 0) {
@@ -15219,7 +16051,8 @@ function assemble(t, prog, cfg) {
15219
16051
  t.lexPrograms,
15220
16052
  LEAD,
15221
16053
  triviaFieldCapture,
15222
- skipDeferredTrivia
16054
+ skipDeferredTrivia,
16055
+ collapseEmpty
15223
16056
  );
15224
16057
  emitReached = new Set(pre.reached);
15225
16058
  if (emitted.ext !== void 0) HYBRID = emitted;
@@ -15305,7 +16138,8 @@ function assemble(t, prog, cfg) {
15305
16138
  t.lexPrograms,
15306
16139
  LEAD,
15307
16140
  triviaFieldCapture,
15308
- skipDeferredTrivia
16141
+ skipDeferredTrivia,
16142
+ collapseEmpty
15309
16143
  );
15310
16144
  emitReached = em.reached;
15311
16145
  } catch (e) {
@@ -15583,7 +16417,7 @@ function emitClassPool(classes) {
15583
16417
  if (classes.length < 2) return array;
15584
16418
  const delimiter = "|/~?^`".split("").find((ch2) => classes.every((spec) => !spec.includes(ch2)));
15585
16419
  if (delimiter === void 0) return array;
15586
- const split = `${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
16420
+ const split = `/* @__PURE__ */ ${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
15587
16421
  return split.length < array.length ? split : array;
15588
16422
  }
15589
16423
  function emitConst(v) {
@@ -17366,15 +18200,20 @@ function compileRuleMap(ruleMap, opts = {}) {
17366
18200
  throw e;
17367
18201
  }
17368
18202
  const ceiling = budget / SUPERCOMPILE_GROWTH;
18203
+ if (ceiling <= fixed) return none;
17369
18204
  let target = ceiling;
17370
- for (let attempt2 = 0; attempt2 < 16; attempt2++) {
18205
+ for (; ; ) {
17371
18206
  const sites = selectHotSites(artifact.code, Object.values(artifact.rules), siteBytes, target - fixed, profile);
17372
- if (sites.size === 0) return none;
18207
+ if (sites.size === 0) {
18208
+ return {
18209
+ ...none,
18210
+ refusal: `a site within its ${Math.floor(ceiling)} B selection ceiling (the prelude alone is ${fixed} B)`
18211
+ };
18212
+ }
17373
18213
  const bytes = emitAssemblySource(table, artifact, cfg, roots, true, sites).source.length;
17374
18214
  if (bytes <= ceiling) return { sites, bytes: Math.ceil(bytes * SUPERCOMPILE_GROWTH) };
17375
18215
  target *= Math.min(ceiling / bytes, 0.99);
17376
18216
  }
17377
- return none;
17378
18217
  };
17379
18218
  return {
17380
18219
  keys: ruleMap.map(([key]) => key),
@@ -17462,16 +18301,16 @@ function ownSource(fn) {
17462
18301
  return typeof name === "string" && name.length > 0 && globalThis[name] === fn ? name : null;
17463
18302
  }
17464
18303
  function compile(target, second, third) {
17465
- if (!isCombinator(target)) return compileMap(target, second);
18304
+ if (!isCombinator2(target)) return compileMap(target, second);
17466
18305
  return compileRoot(target, second, third);
17467
18306
  }
17468
- function isCombinator(x) {
18307
+ function isCombinator2(x) {
17469
18308
  return typeof x === "object" && x !== null && typeof x.parse === "function" && "_def" in x;
17470
18309
  }
17471
18310
  function compileMap(grammar, opts = {}) {
17472
18311
  const entries = [];
17473
18312
  for (const [key, value] of Object.entries(grammar)) {
17474
- if (!isCombinator(value)) throw new TypeError(`compile: grammar entry "${key}" is not a parser`);
18313
+ if (!isCombinator2(value)) throw new TypeError(`compile: grammar entry "${key}" is not a parser`);
17475
18314
  if (value._def.tag === "lazy") {
17476
18315
  try {
17477
18316
  value._def.thunk();
@@ -18016,7 +18855,7 @@ function fieldOptionsSrc(def) {
18016
18855
  }
18017
18856
 
18018
18857
  // src/version.ts
18019
- var PARSEMAN_VERSION = "0.57.0";
18858
+ var PARSEMAN_VERSION = "0.58.0";
18020
18859
 
18021
18860
  // src/compiler/compile-linkable-table.ts
18022
18861
  function isLocal(rule) {
@@ -18939,7 +19778,7 @@ function dispatchArmValue(node2, scope, code, mfs) {
18939
19778
  if (!keyArg || !parserArg || extraArg !== void 0 || keyArg.type === "SpreadElement" || parserArg.type === "SpreadElement") return null;
18940
19779
  const key = anyValue(keyArg, scope, code, mfs);
18941
19780
  const parserValue = anyValue(parserArg, scope, code, mfs);
18942
- if (!isCombinator2(parserValue)) return null;
19781
+ if (!isCombinator3(parserValue)) return null;
18943
19782
  const opts = { caseInsensitive: factory.caseInsensitive };
18944
19783
  if (typeof key === "string") return when(key, parserValue, opts);
18945
19784
  if (Array.isArray(key) && key.every((item) => typeof item === "string")) return when(key, parserValue, opts);
@@ -18950,7 +19789,7 @@ function dispatchArmValue(node2, scope, code, mfs) {
18950
19789
  const [parserArg] = node2.arguments;
18951
19790
  if (!parserArg || parserArg.type === "SpreadElement") return null;
18952
19791
  const parserValue = anyValue(parserArg, scope, code, mfs);
18953
- if (!isCombinator2(parserValue)) return null;
19792
+ if (!isCombinator3(parserValue)) return null;
18954
19793
  return otherwise(parserValue);
18955
19794
  }
18956
19795
  if (callee.name === "when") {
@@ -18960,24 +19799,24 @@ function dispatchArmValue(node2, scope, code, mfs) {
18960
19799
  const parserValue = anyValue(parserArg, scope, code, mfs);
18961
19800
  const opts = dispatchWhenOptions(optsArg === void 0 ? void 0 : anyValue(optsArg, scope, code, mfs));
18962
19801
  if (opts === null) return null;
18963
- if (!isCombinator2(parserValue)) return null;
19802
+ if (!isCombinator3(parserValue)) return null;
18964
19803
  if (typeof key === "string") return when(key, parserValue, opts);
18965
19804
  if (Array.isArray(key) && key.every((item) => typeof item === "string")) return when(key, parserValue, opts);
18966
19805
  if (isDispatchMatcher(key)) return when(key, parserValue, opts);
18967
19806
  }
18968
19807
  return null;
18969
19808
  }
18970
- function isCombinator2(v) {
19809
+ function isCombinator3(v) {
18971
19810
  return !!v && typeof v === "object" && "_def" in v;
18972
19811
  }
18973
19812
  function isDispatchArm(v) {
18974
19813
  if (!v || typeof v !== "object") return false;
18975
19814
  const rec = v;
18976
- if (rec.kind === "otherwise") return isCombinator2(rec.parser);
19815
+ if (rec.kind === "otherwise") return isCombinator3(rec.parser);
18977
19816
  if (rec.kind === "whenMatcher") {
18978
- return isDispatchMatcher(rec.matcher) && typeof rec.caseInsensitive === "boolean" && isCombinator2(rec.parser);
19817
+ return isDispatchMatcher(rec.matcher) && typeof rec.caseInsensitive === "boolean" && isCombinator3(rec.parser);
18979
19818
  }
18980
- return rec.kind === "when" && Array.isArray(rec.keys) && rec.keys.every((key) => typeof key === "string") && typeof rec.caseInsensitive === "boolean" && isCombinator2(rec.parser);
19819
+ return rec.kind === "when" && Array.isArray(rec.keys) && rec.keys.every((key) => typeof key === "string") && typeof rec.caseInsensitive === "boolean" && isCombinator3(rec.parser);
18981
19820
  }
18982
19821
  function isDispatchMatcher(v) {
18983
19822
  if (!v || typeof v !== "object") return false;
@@ -18992,7 +19831,7 @@ function scopeGet(scope, name, mfs) {
18992
19831
  if (mfs && entry.mfSrcs.length > 0) mfs.push(...entry.mfSrcs);
18993
19832
  return entry.combi;
18994
19833
  }
18995
- if (isCombinator2(entry)) return entry;
19834
+ if (isCombinator3(entry)) return entry;
18996
19835
  return null;
18997
19836
  }
18998
19837
  function unwrapStaticExpr(expr) {
@@ -19044,7 +19883,7 @@ function scopedStaticValue(expr, scope) {
19044
19883
  return { found: true, value };
19045
19884
  }
19046
19885
  function staticNodeOptionsFromValue(value) {
19047
- if (value === null || typeof value !== "object" || Array.isArray(value) || isCombinator2(value)) return STATIC_NODE_OPTIONS_NOT_OPTIONS;
19886
+ if (value === null || typeof value !== "object" || Array.isArray(value) || isCombinator3(value)) return STATIC_NODE_OPTIONS_NOT_OPTIONS;
19048
19887
  const opts = {};
19049
19888
  const rec = value;
19050
19889
  for (const name of Object.keys(rec)) {
@@ -19138,7 +19977,7 @@ function exprToCombi(node2, scope, code, mfs) {
19138
19977
  const [parserArg, fnArg] = node2.arguments;
19139
19978
  if (!parserArg || !fnArg || parserArg.type === "SpreadElement" || fnArg.type === "SpreadElement") return null;
19140
19979
  const inner = anyValue(parserArg, scope, code, mfs);
19141
- if (!isCombinator2(inner)) return null;
19980
+ if (!isCombinator3(inner)) return null;
19142
19981
  const fnSrc = stripTsFromSource(fnArg, code);
19143
19982
  mfs.push(fnSrc);
19144
19983
  try {
@@ -19153,7 +19992,7 @@ function exprToCombi(node2, scope, code, mfs) {
19153
19992
  const [parserArg, fnArg] = node2.arguments;
19154
19993
  if (!parserArg || !fnArg || parserArg.type === "SpreadElement" || fnArg.type === "SpreadElement") return null;
19155
19994
  const inner = anyValue(parserArg, scope, code, mfs);
19156
- if (!isCombinator2(inner)) return null;
19995
+ if (!isCombinator3(inner)) return null;
19157
19996
  const fnSrc = stripTsFromSource(fnArg, code);
19158
19997
  mfs.push(fnSrc);
19159
19998
  try {
@@ -19174,7 +20013,7 @@ function exprToCombi(node2, scope, code, mfs) {
19174
20013
  const optsArg = explicitType !== void 0 ? fourthArg : thirdArg;
19175
20014
  if (!parserArg || parserArg.type === "SpreadElement") return null;
19176
20015
  const inner = anyValue(parserArg, scope, code, mfs);
19177
- if (!isCombinator2(inner)) return null;
20016
+ if (!isCombinator3(inner)) return null;
19178
20017
  const be = buildArg;
19179
20018
  const buildExpr = be === void 0 || be.type === "SpreadElement" ? void 0 : unwrapStaticExpr(be);
19180
20019
  const buildArgOptions = be !== void 0 && be.type !== "SpreadElement" ? staticNodeOptions(buildArg, scope) : STATIC_NODE_OPTIONS_NOT_OPTIONS;
@@ -19248,7 +20087,7 @@ function exprToCombi(node2, scope, code, mfs) {
19248
20087
  const opts = anyValue(optsArg, scope, code, []);
19249
20088
  if (!opts || typeof opts !== "object") return null;
19250
20089
  const root = anyValue(rootArg, scope, code, mfs);
19251
- if (!isCombinator2(root)) return null;
20090
+ if (!isCombinator3(root)) return null;
19252
20091
  try {
19253
20092
  return parser(opts, root);
19254
20093
  } catch {
@@ -19260,10 +20099,10 @@ function exprToCombi(node2, scope, code, mfs) {
19260
20099
  if (!itemArg || !sepArg || itemArg.type === "SpreadElement" || sepArg.type === "SpreadElement") return null;
19261
20100
  const itemMfs = [];
19262
20101
  const itemCombi = anyValue(itemArg, scope, code, itemMfs);
19263
- if (!isCombinator2(itemCombi)) return null;
20102
+ if (!isCombinator3(itemCombi)) return null;
19264
20103
  const sepMfs = [];
19265
20104
  const sepCombi = anyValue(sepArg, scope, code, sepMfs);
19266
- if (!isCombinator2(sepCombi)) return null;
20105
+ if (!isCombinator3(sepCombi)) return null;
19267
20106
  let opts;
19268
20107
  if (optsArg) {
19269
20108
  if (optsArg.type === "SpreadElement") return null;
@@ -19283,7 +20122,7 @@ function exprToCombi(node2, scope, code, mfs) {
19283
20122
  if (!itemArg || itemArg.type === "SpreadElement") return null;
19284
20123
  const itemMfs = [];
19285
20124
  const itemCombi = anyValue(itemArg, scope, code, itemMfs);
19286
- if (!isCombinator2(itemCombi)) return null;
20125
+ if (!isCombinator3(itemCombi)) return null;
19287
20126
  let opts;
19288
20127
  if (optsArg) {
19289
20128
  if (optsArg.type === "SpreadElement") return null;
@@ -19305,7 +20144,7 @@ function exprToCombi(node2, scope, code, mfs) {
19305
20144
  const [innerArg] = node2.arguments;
19306
20145
  if (!innerArg || innerArg.type === "SpreadElement") return null;
19307
20146
  const inner = anyValue(innerArg, scope, code, mfs);
19308
- if (!isCombinator2(inner)) return null;
20147
+ if (!isCombinator3(inner)) return null;
19309
20148
  try {
19310
20149
  return not(inner);
19311
20150
  } catch {
@@ -19316,7 +20155,7 @@ function exprToCombi(node2, scope, code, mfs) {
19316
20155
  const [innerArg] = node2.arguments;
19317
20156
  if (!innerArg || innerArg.type === "SpreadElement") return null;
19318
20157
  const inner = anyValue(innerArg, scope, code, mfs);
19319
- if (!isCombinator2(inner)) return null;
20158
+ if (!isCombinator3(inner)) return null;
19320
20159
  try {
19321
20160
  return peek(inner);
19322
20161
  } catch {
@@ -19341,7 +20180,7 @@ function exprToCombi(node2, scope, code, mfs) {
19341
20180
  const [sentinelArg, optsArg] = node2.arguments;
19342
20181
  if (!sentinelArg || sentinelArg.type === "SpreadElement") return null;
19343
20182
  const sentinel = anyValue(sentinelArg, scope, code, []);
19344
- if (!isCombinator2(sentinel)) return null;
20183
+ if (!isCombinator3(sentinel)) return null;
19345
20184
  const opts = scanOptions(optsArg, scope, code);
19346
20185
  if (opts === UNKNOWN_OPTIONS) return null;
19347
20186
  try {
@@ -19372,7 +20211,7 @@ function exprToCombi(node2, scope, code, mfs) {
19372
20211
  const extraSrc = stripTsFromSource(extraArg, code);
19373
20212
  mfs.push(extraSrc);
19374
20213
  const inner = anyValue(innerArg, scope, code, mfs);
19375
- if (!isCombinator2(inner)) return null;
20214
+ if (!isCombinator3(inner)) return null;
19376
20215
  try {
19377
20216
  const extraType = unwrapStaticExpr(extraArg).type;
19378
20217
  const derives = extraType === "ArrowFunctionExpression" || extraType === "FunctionExpression";
@@ -19390,7 +20229,7 @@ function exprToCombi(node2, scope, code, mfs) {
19390
20229
  const [selectorArg, ...armArgs] = node2.arguments;
19391
20230
  if (!selectorArg || selectorArg.type === "SpreadElement") return null;
19392
20231
  const selector = anyValue(selectorArg, scope, code, mfs);
19393
- if (!isCombinator2(selector)) return null;
20232
+ if (!isCombinator3(selector)) return null;
19394
20233
  const arms = [];
19395
20234
  for (const arg of armArgs) {
19396
20235
  if (arg.type === "SpreadElement") return null;
@@ -19417,12 +20256,12 @@ function exprToCombi(node2, scope, code, mfs) {
19417
20256
  const gateSrc = stripTsFromSource(parts.gate, code);
19418
20257
  mfs.push(gateSrc);
19419
20258
  const combi = anyValue(parts.combinator, scope, code, mfs);
19420
- if (!isCombinator2(combi)) return null;
20259
+ if (!isCombinator3(combi)) return null;
19421
20260
  arms.push({ gate: () => true, combinator: combi });
19422
20261
  gateSrcs.push(gateSrc);
19423
20262
  } else {
19424
20263
  const combi = anyValue(argNode, scope, code, mfs);
19425
- if (!isCombinator2(combi)) return null;
20264
+ if (!isCombinator3(combi)) return null;
19426
20265
  arms.push(combi);
19427
20266
  gateSrcs.push(null);
19428
20267
  }
@@ -19570,7 +20409,7 @@ function evaluateExpr(node2, scope, code, mapFnSources) {
19570
20409
  function evaluateCombinatorArray(node2, scope, code) {
19571
20410
  const val = anyValue(node2, scope, code, []);
19572
20411
  if (!Array.isArray(val) || val.length === 0) return null;
19573
- if (!val.every(isCombinator2)) return null;
20412
+ if (!val.every(isCombinator3)) return null;
19574
20413
  return val;
19575
20414
  }
19576
20415
  function collectRuleKeys(retObj) {
@@ -19648,7 +20487,7 @@ function evalBodyStatements(statements, scope, code, out) {
19648
20487
  return false;
19649
20488
  }
19650
20489
  const thisDeclMfSrcs = bodyMfs.slice(before);
19651
- if (isCombinator2(val)) scope.set(name, { combi: val, mfSrcs: thisDeclMfSrcs });
20490
+ if (isCombinator3(val)) scope.set(name, { combi: val, mfSrcs: thisDeclMfSrcs });
19652
20491
  else if (isDispatchArm(val)) scope.set(name, { value: val, mfSrcs: thisDeclMfSrcs });
19653
20492
  else scope.set(name, val);
19654
20493
  }
@@ -19703,7 +20542,7 @@ function evaluateParserFactory(factoryNode, scope, code, mapFnSources, out, opti
19703
20542
  const definitions = {};
19704
20543
  for (const [key, e] of finalByKey) {
19705
20544
  const val = anyValue(e.value, e.scope, e.code, mapFnSources);
19706
- if (!isCombinator2(val)) throw ABORT;
20545
+ if (!isCombinator3(val)) throw ABORT;
19707
20546
  definitions[key] = val;
19708
20547
  }
19709
20548
  return definitions;
@@ -19718,7 +20557,7 @@ function evaluateParserFactory(factoryNode, scope, code, mapFnSources, out, opti
19718
20557
  return map;
19719
20558
  }
19720
20559
  function isDefinableRef2(v) {
19721
- return isCombinator2(v) && typeof v.define === "function" && v._def.tag === "lazy";
20560
+ return isCombinator3(v) && typeof v.define === "function" && v._def.tag === "lazy";
19722
20561
  }
19723
20562
  function evaluateRefDeclaration(init, name, scope) {
19724
20563
  if (init.type !== "CallExpression") return null;
@@ -19738,12 +20577,12 @@ function applyDefineStatement(callExpr, scope, code) {
19738
20577
  if (mem.property.type !== "Identifier" || mem.property.name !== "define") return false;
19739
20578
  if (mem.object.type !== "Identifier" || !mem.object.name) return false;
19740
20579
  const target = scope.get(mem.object.name);
19741
- const refCombi = isScopeEntry(target) ? target.combi : isCombinator2(target) ? target : null;
20580
+ const refCombi = isScopeEntry(target) ? target.combi : isCombinator3(target) ? target : null;
19742
20581
  if (!refCombi || !isDefinableRef2(refCombi)) return false;
19743
20582
  const args = callExpr.arguments;
19744
20583
  if (args.length !== 1 || args[0].type === "SpreadElement") return false;
19745
20584
  const inner = anyValue(args[0], scope, code, []);
19746
- if (!isCombinator2(inner)) return false;
20585
+ if (!isCombinator3(inner)) return false;
19747
20586
  try {
19748
20587
  refCombi.define(inner);
19749
20588
  } catch {
@@ -21012,6 +21851,28 @@ function evalIR(ir, rulesImpl) {
21012
21851
  // src/plugin/index.ts
21013
21852
  import { createHash } from "node:crypto";
21014
21853
  var TABLE_RUNTIME_SPECIFIER = "parseman/table";
21854
+ var CARRIED_SIDECAR_SUFFIX = ".parseman.json";
21855
+ var _sidecarCache = /* @__PURE__ */ new Map();
21856
+ function readCarriedSidecar(artifact) {
21857
+ const file = artifact + CARRIED_SIDECAR_SUFFIX;
21858
+ let mtimeMs;
21859
+ try {
21860
+ mtimeMs = fs2.statSync(file).mtimeMs;
21861
+ } catch {
21862
+ return null;
21863
+ }
21864
+ const hit = _sidecarCache.get(file);
21865
+ if (hit && hit.mtimeMs === mtimeMs) return hit.sidecar;
21866
+ let sidecar = null;
21867
+ try {
21868
+ const parsed = JSON.parse(fs2.readFileSync(file, "utf8"));
21869
+ const exports = typeof parsed === "object" && parsed !== null ? parsed.exports : void 0;
21870
+ if (typeof exports === "object" && exports !== null) sidecar = parsed;
21871
+ } catch {
21872
+ }
21873
+ _sidecarCache.set(file, { mtimeMs, sidecar });
21874
+ return sidecar;
21875
+ }
21015
21876
  var corpusCache = /* @__PURE__ */ new Map();
21016
21877
  function corpusTexts(profile) {
21017
21878
  return profile.files.map((file) => {
@@ -21130,31 +21991,101 @@ function parseModuleCached(filePath) {
21130
21991
  _moduleParseCache.set(filePath, { mtimeMs, parsed });
21131
21992
  return parsed;
21132
21993
  }
21133
- var plugin_default = createUnplugin((opts = {}) => ({
21134
- name: "parseman",
21135
- // Run BEFORE the bundler's TS/JS transform — otherwise esbuild (Vite) strips
21136
- // the `with { type: 'macro' }` import attribute before we ever see it, and the
21137
- // macro silently never fires.
21138
- enforce: "pre",
21139
- transformInclude(id) {
21140
- return /\.[jt]sx?$/.test(id) && !id.includes("node_modules");
21141
- },
21142
- transform(code, id) {
21143
- if (!code.includes("parseman")) return null;
21144
- if (!code.includes("macro")) return null;
21145
- for (const file of opts.assemblyProfile?.files ?? []) this?.addWatchFile?.(file);
21146
- const moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE, ...opts.moduleAliases ?? []]);
21147
- const result = transformMacro(code, id, moduleAliases, opts.warnUnloweredRegex === true, opts.recovery === true, opts.grammarCoverage === true, opts.assemblyProfile, opts.assemblyBudget);
21148
- if (result?.warnings.length) {
21149
- for (const w of result.warnings) {
21150
- if (typeof this?.warn === "function") this.warn(`[parseman] ${w}`);
21151
- else console.warn(`[parseman] ${w}`);
21152
- }
21153
- }
21154
- if (!result) return null;
21155
- return { code: result.code, map: result.map };
21156
- }
21157
- }));
21994
+ function reexportSource(body, exported) {
21995
+ for (const st of body) {
21996
+ if (st.type !== "ExportNamedDeclaration") continue;
21997
+ for (const sp of st.specifiers ?? []) {
21998
+ const exp = sp.exported;
21999
+ if ((exp?.name ?? exp?.value) !== exported) continue;
22000
+ const local = sp.local;
22001
+ const name = local?.name ?? local?.value;
22002
+ if (name === void 0) return null;
22003
+ const from = st.source?.value;
22004
+ return from !== void 0 ? { source: from, imported: name } : extractImportBindings(body).get(name) ?? null;
22005
+ }
22006
+ }
22007
+ return null;
22008
+ }
22009
+ async function followCarried(sinks, moduleId, name) {
22010
+ for (let hop = 0; hop < 64; hop++) {
22011
+ const own = sinks.get(moduleId)?.get(name);
22012
+ if (own !== void 0) return own;
22013
+ const code = this.getModuleInfo(moduleId)?.code;
22014
+ if (!code) return void 0;
22015
+ const parsed = parseSync5(moduleId, code);
22016
+ if (parsed.errors.length > 0) return void 0;
22017
+ const next = reexportSource(parsed.program.body, name);
22018
+ if (next === null) return void 0;
22019
+ const resolved = await this.resolve(next.source, moduleId);
22020
+ if (resolved === null || resolved.external) return void 0;
22021
+ moduleId = resolved.id;
22022
+ name = next.imported;
22023
+ }
22024
+ return void 0;
22025
+ }
22026
+ async function emitCarriedSidecars(sinks, bundle) {
22027
+ const recorders = /* @__PURE__ */ new Map();
22028
+ for (const [moduleId, sink] of sinks) for (const name of sink.keys()) (recorders.get(name) ?? recorders.set(name, []).get(name)).push(moduleId);
22029
+ for (const chunk of Object.values(bundle)) {
22030
+ if (chunk.type !== "chunk") continue;
22031
+ const exports = {};
22032
+ for (const name of chunk.exports ?? []) {
22033
+ const followed = chunk.facadeModuleId ? await followCarried.call(this, sinks, chunk.facadeModuleId, name) : void 0;
22034
+ if (followed !== void 0) {
22035
+ exports[name] = followed;
22036
+ continue;
22037
+ }
22038
+ const ids = recorders.get(name);
22039
+ if (ids === void 0) continue;
22040
+ const own = ids.filter((m) => chunk.moduleIds?.includes(m));
22041
+ const moduleId = own.length === 1 ? own[0] : own.length === 0 && ids.length === 1 ? ids[0] : void 0;
22042
+ if (moduleId !== void 0) exports[name] = sinks.get(moduleId).get(name);
22043
+ }
22044
+ if (Object.keys(exports).length === 0) continue;
22045
+ const sidecar = { parseman: PARSEMAN_VERSION, exports };
22046
+ this.emitFile({ type: "asset", fileName: chunk.fileName + CARRIED_SIDECAR_SUFFIX, source: JSON.stringify(sidecar) });
22047
+ }
22048
+ }
22049
+ var SIDECAR_FRAMEWORKS = /* @__PURE__ */ new Set(["rollup", "rolldown", "vite"]);
22050
+ var plugin_default = createUnplugin((opts = {}, meta) => {
22051
+ const sinks = SIDECAR_FRAMEWORKS.has(meta.framework) ? /* @__PURE__ */ new Map() : void 0;
22052
+ const generateBundle = sinks === void 0 ? void 0 : {
22053
+ generateBundle(_options, bundle) {
22054
+ return emitCarriedSidecars.call(this, sinks, bundle);
22055
+ }
22056
+ };
22057
+ return {
22058
+ name: "parseman",
22059
+ ...generateBundle === void 0 ? {} : { rollup: generateBundle, rolldown: generateBundle, vite: generateBundle },
22060
+ // Run BEFORE the bundler's TS/JS transform — otherwise esbuild (Vite) strips
22061
+ // the `with { type: 'macro' }` import attribute before we ever see it, and the
22062
+ // macro silently never fires.
22063
+ enforce: "pre",
22064
+ transformInclude(id) {
22065
+ return /\.[jt]sx?$/.test(id) && !id.includes("node_modules");
22066
+ },
22067
+ transform(code, id) {
22068
+ if (!code.includes("parseman")) return null;
22069
+ if (!code.includes("macro")) return null;
22070
+ for (const file of opts.assemblyProfile?.files ?? []) this?.addWatchFile?.(file);
22071
+ const moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE, ...opts.moduleAliases ?? []]);
22072
+ const sink = sinks && /* @__PURE__ */ new Map();
22073
+ const result = transformMacro(code, id, moduleAliases, opts.warnUnloweredRegex === true, opts.recovery === true, opts.grammarCoverage === true, opts.assemblyProfile, opts.assemblyBudget, sink);
22074
+ if (sinks && sink) {
22075
+ if (sink.size > 0) sinks.set(id, sink);
22076
+ else sinks.delete(id);
22077
+ }
22078
+ if (result?.warnings.length) {
22079
+ for (const w of result.warnings) {
22080
+ if (typeof this?.warn === "function") this.warn(`[parseman] ${w}`);
22081
+ else console.warn(`[parseman] ${w}`);
22082
+ }
22083
+ }
22084
+ if (!result) return null;
22085
+ return { code: result.code, map: result.map };
22086
+ }
22087
+ };
22088
+ });
21158
22089
  function exportLocalName(body, exported) {
21159
22090
  for (const st of body) {
21160
22091
  if (st.type !== "ExportNamedDeclaration") continue;
@@ -21300,17 +22231,17 @@ function lowerPrivateSourceModule(file, moduleAliases, warnUnloweredRegex, recov
21300
22231
  _sourceLowering.delete(file);
21301
22232
  }
21302
22233
  }
21303
- function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE]), warnUnloweredRegex = false, recovery = false, grammarCoverage = false, assemblyProfile, assemblyBudget = DEFAULT_ASSEMBLY_BUDGET) {
22234
+ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE]), warnUnloweredRegex = false, recovery = false, grammarCoverage = false, assemblyProfile, assemblyBudget = DEFAULT_ASSEMBLY_BUDGET, carriedSink) {
21304
22235
  const depth = degradationCaptureDepth();
21305
22236
  try {
21306
- return transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recovery, grammarCoverage, assemblyProfile, assemblyBudget);
22237
+ return transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recovery, grammarCoverage, assemblyProfile, assemblyBudget, carriedSink);
21307
22238
  } finally {
21308
22239
  setReducerResolver(null);
21309
22240
  setBuilderImportResolver(null);
21310
22241
  for (const d of unwindDegradationCapture(depth)) console.warn(formatDegradation(d));
21311
22242
  }
21312
22243
  }
21313
- function transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recovery, grammarCoverage, assemblyProfile, assemblyBudgetShare) {
22244
+ function transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recovery, grammarCoverage, assemblyProfile, assemblyBudgetShare, carriedSink) {
21314
22245
  let result;
21315
22246
  try {
21316
22247
  result = parseSync5(id, code);
@@ -21913,17 +22844,36 @@ ${names.map((n) => ` - ${n}`).join("\n")}` : " (it is not a static combinator/v
21913
22844
  const importedPiecesCache = /* @__PURE__ */ new Map();
21914
22845
  const resolveModulePieces = (module, exportName, seen, unresolved, local = false) => {
21915
22846
  const { file } = module;
22847
+ const fail = (why) => {
22848
+ unresolved.why ??= `${exportName} in ${file}: ${why}`;
22849
+ return null;
22850
+ };
22851
+ const sidecarItems = module.source || local ? void 0 : readCarriedSidecar(file)?.exports[exportName];
22852
+ if (sidecarItems !== void 0) {
22853
+ const list = [];
22854
+ for (const item of sidecarItems) {
22855
+ if ("ir" in item) {
22856
+ list.push(item);
22857
+ continue;
22858
+ }
22859
+ const sub = resolveGrammarModule(file, item.from);
22860
+ if (sub === null) return fail(`its carried pieces name \`${item.name}\` from '${item.from}', a module that could not be found`);
22861
+ if (seen.has(sub.file)) continue;
22862
+ const pieces = resolveModulePieces(sub, item.name, new Set(seen).add(sub.file), unresolved);
22863
+ if (pieces === null) return fail(`its carried pieces name \`${item.name}\` from '${item.from}', which could not be resolved`);
22864
+ list.push(...pieces);
22865
+ }
22866
+ return list;
22867
+ }
21916
22868
  const mod = module.source ? lowerPrivateSourceModule(file, moduleAliases, warnUnloweredRegex, recovery) : parseModuleCached(file);
21917
22869
  if (!mod) return null;
21918
22870
  const localFor = local ? exportName : exportLocalName(mod.body, exportName);
21919
22871
  const initNode = localFor ? topLevelInit(mod.body, localFor) : null;
21920
22872
  const literalRange = initNode ? findCarriedPiecesLiteral(initNode) : null;
21921
- if (!literalRange) return null;
22873
+ if (!literalRange) {
22874
+ return initNode !== null && !module.source && mod.src.slice(initNode.start, initNode.end).includes("tableRules(") ? fail(`is a compiled grammar with no carried pieces \u2014 no inline literal, and no entry in ${path2.basename(file)}${CARRIED_SIDECAR_SUFFIX}. Rebuild it with this parseman, and keep that file beside the artifact`) : null;
22875
+ }
21922
22876
  const literal2 = mod.src.slice(literalRange.start, literalRange.end);
21923
- const fail = (why) => {
21924
- unresolved.why ??= `${exportName} in ${file}: ${why}`;
21925
- return null;
21926
- };
21927
22877
  const imports = extractImportBindings(mod.body);
21928
22878
  const stubNames = [];
21929
22879
  const stubVals = [];
@@ -21972,6 +22922,27 @@ ${names.map((n) => ` - ${n}`).join("\n")}` : " (it is not a static combinator/v
21972
22922
  importedPiecesCache.set(localName, result2);
21973
22923
  return result2;
21974
22924
  };
22925
+ const sinkCarried = (name, list) => {
22926
+ if (carriedSink === void 0) return false;
22927
+ const out = [];
22928
+ for (const it of list) {
22929
+ if (!isSpread(it)) {
22930
+ out.push(it);
22931
+ continue;
22932
+ }
22933
+ const b = importBindings.get(it.__spreadLocal);
22934
+ if (b === void 0) return false;
22935
+ if (!b.source.startsWith(".") && !path2.isAbsolute(b.source)) {
22936
+ out.push({ from: b.source, name: b.imported });
22937
+ continue;
22938
+ }
22939
+ const pieces = importedPieces(it.__spreadLocal);
22940
+ if (pieces === null) return false;
22941
+ out.push(...pieces);
22942
+ }
22943
+ carriedSink.set(name, out);
22944
+ return true;
22945
+ };
21975
22946
  const carriedRuleMaps = (items) => {
21976
22947
  const pieces = [];
21977
22948
  let trackLines = false;
@@ -22391,6 +23362,7 @@ ${names.map((n) => ` - ${n}`).join("\n")}` : " (it is not a static combinator/v
22391
23362
  const ir = serializeRuleMap([...compiledRules.ruleMap], compiledRules.scanSkip);
22392
23363
  if (ir) carriedMetadata = [{ ns, ir, ...compiledRules.trackLines ? { trackLines: true } : {} }];
22393
23364
  else warn(init.start, `${varName}: exported grammar could not be serialized to IR, so it carries no composable pieces \u2014 a downstream compose() of this grammar will fall back to runtime. Re-run with PARSEMAN_IR_DEBUG=1 to print the combinator that blocked serialization.`);
23365
+ if (carriedMetadata !== void 0 && sinkCarried(varName, carriedMetadata)) carriedMetadata = void 0;
22394
23366
  }
22395
23367
  const replacement = compiledRules.replacement !== null ? compiledRules.replacementWithMetadata(staticTableMetadataSource({
22396
23368
  ...carriedMetadata === void 0 ? {} : { carried: carriedMetadata },
@@ -22415,7 +23387,7 @@ ${names.map((n) => ` - ${n}`).join("\n")}` : " (it is not a static combinator/v
22415
23387
  continue;
22416
23388
  }
22417
23389
  localComposedCarried.set(varName, fused.carried);
22418
- const replacement = exportPrefix ? fused.exportedReplacement : fused.replacement;
23390
+ const replacement = exportPrefix && !sinkCarried(varName, fused.carried) ? fused.exportedReplacement : fused.replacement;
22419
23391
  replacements.push({ start: init.start, end: init.end, replacement });
22420
23392
  markUsedImportedFactories(fused.importedFactories);
22421
23393
  continue;
@@ -22705,6 +23677,7 @@ ${lines2.join("\n")}`);
22705
23677
  };
22706
23678
  }
22707
23679
  export {
23680
+ CARRIED_SIDECAR_SUFFIX,
22708
23681
  plugin_default as default,
22709
23682
  transformMacro
22710
23683
  };