parseman 0.57.0 → 0.58.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/analysis/diagnostics.js +1800 -962
  2. package/dist/analysis/diagnostics.js.map +3 -3
  3. package/dist/cli/index.js +1929 -1091
  4. package/dist/cli/index.js.map +3 -3
  5. package/dist/combinators/dispatch.d.ts.map +1 -1
  6. package/dist/compiler/token-alphabet.d.ts +11 -1
  7. package/dist/compiler/token-alphabet.d.ts.map +1 -1
  8. package/dist/compiler/token-capability.js +69 -16
  9. package/dist/compiler/token-capability.js.map +2 -2
  10. package/dist/cst/capture-buffer.d.ts +6 -0
  11. package/dist/cst/capture-buffer.d.ts.map +1 -1
  12. package/dist/index.js +1017 -177
  13. package/dist/index.js.map +3 -3
  14. package/dist/plugin/index.d.ts +25 -1
  15. package/dist/plugin/index.d.ts.map +1 -1
  16. package/dist/plugin/index.js +1210 -236
  17. package/dist/plugin/index.js.map +3 -3
  18. package/dist/run/index.d.ts +2 -0
  19. package/dist/run/index.d.ts.map +1 -1
  20. package/dist/run/index.js +9 -0
  21. package/dist/run/index.js.map +1 -1
  22. package/dist/table/assemble.d.ts.map +1 -1
  23. package/dist/table/compile-rule-map.d.ts.map +1 -1
  24. package/dist/table/emit-assembly.d.ts +1 -1
  25. package/dist/table/emit-assembly.d.ts.map +1 -1
  26. package/dist/table/emit.d.ts.map +1 -1
  27. package/dist/table/encode.d.ts.map +1 -1
  28. package/dist/table/exec.d.ts.map +1 -1
  29. package/dist/table/factor-choice.d.ts +42 -0
  30. package/dist/table/factor-choice.d.ts.map +1 -0
  31. package/dist/table/fail-clean.d.ts +3 -0
  32. package/dist/table/fail-clean.d.ts.map +1 -0
  33. package/dist/table/hold-gap.d.ts +8 -0
  34. package/dist/table/hold-gap.d.ts.map +1 -0
  35. package/dist/table/index.js +1370 -259
  36. package/dist/table/index.js.map +3 -3
  37. package/dist/table/lex-program.d.ts +7 -3
  38. package/dist/table/lex-program.d.ts.map +1 -1
  39. package/dist/table/ops.d.ts +8 -0
  40. package/dist/table/ops.d.ts.map +1 -1
  41. package/dist/table/run-support.d.ts +19 -0
  42. package/dist/table/run-support.d.ts.map +1 -1
  43. package/dist/table/scalar-terminal.d.ts +2 -0
  44. package/dist/table/scalar-terminal.d.ts.map +1 -1
  45. package/dist/table/site-labels.d.ts +66 -0
  46. package/dist/table/site-labels.d.ts.map +1 -1
  47. package/dist/version.d.ts +1 -1
  48. package/package.json +1 -1
  49. package/src/combinators/dispatch.ts +12 -3
  50. package/src/compiler/token-alphabet.ts +57 -17
  51. package/src/cst/capture-buffer.ts +25 -0
  52. package/src/plugin/index.ts +230 -35
  53. package/src/run/index.ts +5 -0
  54. package/src/table/assemble.ts +252 -62
  55. package/src/table/child-slots.ts +2 -2
  56. package/src/table/compile-rule-map.ts +14 -5
  57. package/src/table/emit-assembly.ts +112 -23
  58. package/src/table/emit.ts +3 -1
  59. package/src/table/encode.ts +83 -14
  60. package/src/table/exec.ts +27 -8
  61. package/src/table/factor-choice.ts +173 -0
  62. package/src/table/fail-clean.ts +130 -0
  63. package/src/table/hold-gap.ts +68 -0
  64. package/src/table/lex-program.ts +197 -43
  65. package/src/table/ops.ts +9 -1
  66. package/src/table/run-support.ts +35 -0
  67. package/src/table/scalar-terminal.ts +8 -0
  68. package/src/table/site-labels.ts +135 -4
  69. package/src/version.ts +1 -1
@@ -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,51 @@ 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 nextDef = next._def;
8051
+ if (nextDef.tag !== "literal" && nextDef.tag !== "regex" && nextDef.tag !== "keywords" && nextDef.tag !== "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
+ const miss = nextDef.tag === "label" ? deriveExpected(next) : directTerminalFailureExpected(nextDef);
8056
+ return { cls, fx: this.expected(miss) };
8057
+ }
7681
8058
  node(p) {
7682
8059
  const lazyRef = p._def.tag === "lazy";
7683
8060
  const scopeKey = lazyRef ? this.activeTrivia : void 0;
@@ -7802,6 +8179,10 @@ var Encoder = class {
7802
8179
  return head;
7803
8180
  }
7804
8181
  case "choice": {
8182
+ if (this.plan === void 0) {
8183
+ const factored = factorSharedEnds(d);
8184
+ if (factored !== void 0) return this.node(factored).ip;
8185
+ }
7805
8186
  if (d.strategy.tag === "greedyClassify") {
7806
8187
  const superIndex = d.strategy.superIndex;
7807
8188
  const sup = this.node(d.parsers[superIndex]).ip;
@@ -7825,9 +8206,12 @@ var Encoder = class {
7825
8206
  const kids = arms.map((c, k) => {
7826
8207
  const src = order[k];
7827
8208
  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
8209
  const gate2 = d.gates[src];
8210
+ const plain = (checks === null || checks === void 0 || checks.length === 0) && (gate2 === null || gate2 === void 0);
8211
+ const routedGate = plain ? this.routedArmGate(c) : void 0;
8212
+ const body = this.node(c).ip;
8213
+ const inner = routedGate === void 0 ? body : this.emit(OP_RGATE, routedGate.cls, body, routedGate.fx);
8214
+ const ip = checks === null || checks === void 0 || checks.length === 0 ? inner : this.reject(inner, checks);
7831
8215
  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
8216
  return this.covWrap(gated, armCovIds?.[src], 1);
7833
8217
  });
@@ -8151,6 +8535,7 @@ var Encoder = class {
8151
8535
  const slots = (ip) => {
8152
8536
  switch (this.code[ip]) {
8153
8537
  case OP_GATE:
8538
+ case OP_RGATE:
8154
8539
  return [ip + 2];
8155
8540
  case OP_RULE:
8156
8541
  case OP_OPT:
@@ -9378,6 +9763,7 @@ function childSlots(code, ip, out) {
9378
9763
  case OP_LEAF:
9379
9764
  case OP_SOURCE_LEAF:
9380
9765
  case OP_ARMGATE:
9766
+ case OP_RGATE:
9381
9767
  out.push(code[ip + 2]);
9382
9768
  return true;
9383
9769
  // `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
@@ -9461,6 +9847,42 @@ function reachableSites(code, roots) {
9461
9847
  }
9462
9848
  return seen;
9463
9849
  }
9850
+ function passCollapse(code, ip, hostCst) {
9851
+ const flags = code[ip + 3];
9852
+ if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return false;
9853
+ if (flags !== 32 && flags !== 34) return false;
9854
+ let at = code[ip + 2];
9855
+ for (let n = 0; n < 8; n++) {
9856
+ const op = code[at];
9857
+ if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[at + 3] === 0) at = code[at + 2];
9858
+ else if (op === OP_RULE) at = code[at + 1];
9859
+ else break;
9860
+ }
9861
+ return code[at] === OP_NODE;
9862
+ }
9863
+ function gatedPassCollapse(code, ip, hostCst) {
9864
+ const flags = code[ip + 3];
9865
+ if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return void 0;
9866
+ if (flags !== 32 && flags !== 34) return void 0;
9867
+ const seq = code[ip + 2];
9868
+ if (code[seq] !== OP_SEQ && code[seq] !== OP_SEQV) return void 0;
9869
+ const n = code[seq + 1];
9870
+ if (n < 2) return void 0;
9871
+ const leads = [];
9872
+ const lits = [];
9873
+ for (let i = 0; i < n - 1; i++) {
9874
+ const t = code[seq + 2 + i];
9875
+ if (code[t] !== OP_OPT && code[t] !== OP_NOT) return void 0;
9876
+ const g = code[t + 1];
9877
+ if (code[g] === OP_GATE) leads.push(g);
9878
+ else if (code[g] === OP_LIT) lits.push(code[g + 1]);
9879
+ else return void 0;
9880
+ }
9881
+ const last = code[seq + 2 + n - 1];
9882
+ let at = last;
9883
+ 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];
9884
+ return code[at] === OP_NODE ? { leads, lits, last } : void 0;
9885
+ }
9464
9886
  function transfer(code, ip, at, hostCst) {
9465
9887
  const op = code[ip];
9466
9888
  if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
@@ -9472,14 +9894,18 @@ function transfer(code, ip, at, hostCst) {
9472
9894
  }
9473
9895
  if (op === OP_NODE || op === OP_NODE_TRACK) {
9474
9896
  const flags = code[ip + 3];
9897
+ if (passCollapse(code, ip, hostCst)) return at;
9898
+ const gated = gatedPassCollapse(code, ip, hostCst) !== void 0;
9475
9899
  const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && ((flags & ~128) === 2 || flags === 18 || flags === 34);
9476
9900
  if (directChildren) {
9477
- return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
9901
+ const framed2 = { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
9902
+ return gated ? meet(at, framed2) : framed2;
9478
9903
  }
9479
9904
  const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
9480
9905
  const raw = !hostCst && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags & 2) !== 0 ? RAW_OMIT : RAW_CAPTURE;
9481
9906
  if (at.buf && raw === at.raw && cap === at.cap) return at;
9482
- return { tri: at.tri, buf: true, raw, cap };
9907
+ const framed = { tri: at.tri, buf: true, raw, cap };
9908
+ return gated ? meet(at, framed) : framed;
9483
9909
  }
9484
9910
  if (op === OP_TOKEN) {
9485
9911
  if (at.tri === TRI_NONE && !at.buf) return at;
@@ -9517,6 +9943,40 @@ function computeSiteLabels(code, roots, hostCst) {
9517
9943
  }
9518
9944
  return { at: (ip) => labels.get(ip) ?? TOP };
9519
9945
  }
9946
+ function scopeIsIdentity(code, ip, at) {
9947
+ const op = code[ip];
9948
+ if (op !== OP_SCOPE_PLAIN && !(op === OP_SCOPE && code[ip + 3] === 0)) return false;
9949
+ const ki = code[ip + 1];
9950
+ return at.tri === (ki < 0 ? TRI_NONE : ki);
9951
+ }
9952
+ function scanHandoffNeeded(code, ip, labels) {
9953
+ const seen = /* @__PURE__ */ new Set();
9954
+ const stack = [ip];
9955
+ const kids = [];
9956
+ while (stack.length > 0) {
9957
+ const at = stack.pop();
9958
+ if (seen.has(at)) continue;
9959
+ seen.add(at);
9960
+ const l = labels.at(at);
9961
+ if (l.tri === TRI_UNKNOWN) return true;
9962
+ const op = code[at];
9963
+ if (op === OP_SCAN) return true;
9964
+ if (op === OP_TOKEN || op === OP_SCOPE_CAP) continue;
9965
+ 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;
9966
+ kids.length = 0;
9967
+ if (!childSlots(code, at, kids)) return true;
9968
+ for (const c of kids) stack.push(c);
9969
+ }
9970
+ return false;
9971
+ }
9972
+ function triviaLeadRanges(tri, trivia2) {
9973
+ if (tri === TRI_NONE) return [];
9974
+ if (tri < 0) return void 0;
9975
+ const fs3 = trivia2[tri]?._meta.firstSet;
9976
+ if (fs3 === void 0) return void 0;
9977
+ if (fs3.kind === "empty") return [];
9978
+ return fs3.kind === "ranges" && fs3.ranges !== void 0 ? fs3.ranges : void 0;
9979
+ }
9520
9980
 
9521
9981
  // src/table/scalar-terminal.ts
9522
9982
  function makeScalarRecognizer(op, spec) {
@@ -9554,6 +10014,12 @@ function scalarTerminalNotChild(code, ip) {
9554
10014
  const op = code[child];
9555
10015
  return op === OP_RX || op === OP_LIT ? child : -1;
9556
10016
  }
10017
+ function scalarTerminalPeekChild(code, ip) {
10018
+ if (code[ip] !== OP_PEEK) return -1;
10019
+ const child = code[ip + 1];
10020
+ const op = code[child];
10021
+ return op === OP_RX || op === OP_LIT ? child : -1;
10022
+ }
9557
10023
  function leadingScalarTerminal(code, ip, minDepth = 2, throughAttempt = true, throughPeek = false) {
9558
10024
  const seen = /* @__PURE__ */ new Set();
9559
10025
  let at = ip;
@@ -9731,6 +10197,59 @@ function leadingTriviaFieldAt(code, k, ip) {
9731
10197
  return code[ip] === OP_FIELD && (fieldSpec(k[code[ip + 1]]).bits & FIELD_LEADING_TRIVIA) !== 0;
9732
10198
  }
9733
10199
 
10200
+ // src/table/hold-gap.ts
10201
+ var WRAPPERS = /* @__PURE__ */ new Set([
10202
+ OP_NODE,
10203
+ OP_XFORM,
10204
+ OP_LEAF,
10205
+ OP_SOURCE_LEAF,
10206
+ OP_TOKEN,
10207
+ OP_SCOPE,
10208
+ OP_SCOPE_CAP,
10209
+ OP_SCOPE_PLAIN,
10210
+ OP_FIELD,
10211
+ OP_LABEL,
10212
+ OP_EXPECT,
10213
+ OP_WITHCTX,
10214
+ OP_RULE,
10215
+ OP_ATTEMPT,
10216
+ OP_COV
10217
+ ]);
10218
+ function rowNullable(code, k, ip, memo) {
10219
+ const hit = memo.get(ip);
10220
+ if (hit !== void 0) return hit;
10221
+ memo.set(ip, true);
10222
+ const op = code[ip];
10223
+ const kids = [];
10224
+ let out = true;
10225
+ if (op === OP_GATE) out = false;
10226
+ else if (op === OP_LIT || op === OP_LIT_CI) out = k[code[ip + 1]].length === 0;
10227
+ else if (op === OP_RX) {
10228
+ const re = k[code[ip + 1]];
10229
+ out = !(re instanceof RegExp) || regexCanMatchEmpty(re.source);
10230
+ } else if (op === OP_SEQ || op === OP_SEQV || op === OP_SEQX) {
10231
+ childSlots(code, ip, kids);
10232
+ out = kids.every((c) => rowNullable(code, k, c, memo));
10233
+ } else if (op === OP_CHOICE) {
10234
+ childSlots(code, ip, kids);
10235
+ out = kids.length === 0 || kids.some((c) => rowNullable(code, k, c, memo));
10236
+ } else if (op === OP_REP || op === OP_REPV) {
10237
+ out = code[ip + 2] === 0 || rowNullable(code, k, code[ip + 1], memo);
10238
+ } else if (WRAPPERS.has(op)) {
10239
+ if (childSlots(code, ip, kids) && kids.length === 1) out = rowNullable(code, k, kids[0], memo);
10240
+ }
10241
+ memo.set(ip, out);
10242
+ return out;
10243
+ }
10244
+ function holdsGap(code, k, base, n, i, memo) {
10245
+ if (i < 1 || i + 1 >= n) return false;
10246
+ const term = code[base + i];
10247
+ if (code[term] !== OP_NOT && code[term] !== OP_PEEK) return false;
10248
+ const next = code[base + i + 1];
10249
+ if (code[next] === OP_ADJ || leadingTriviaFieldAt(code, k, next)) return false;
10250
+ return !rowNullable(code, k, next, memo);
10251
+ }
10252
+
9734
10253
  // src/table/emit-assembly.ts
9735
10254
  var Unemittable = class extends Error {
9736
10255
  construct;
@@ -9811,7 +10330,10 @@ var EMITTED_PARAMS = [
9811
10330
  "triviaFieldCapture",
9812
10331
  // Appended for the deferred-commit trivia skip (`trivia-gap.ts`); old
9813
10332
  // factories ignore it.
9814
- "skipDeferredTrivia"
10333
+ "skipDeferredTrivia",
10334
+ // Appended for the pass-through collapse (`run-support.ts`); old factories
10335
+ // ignore it.
10336
+ "collapseEmpty"
9815
10337
  ];
9816
10338
  var RUNTIME_PRELUDE = `
9817
10339
  let _pfScan=null
@@ -10008,6 +10530,24 @@ ${fast}
10008
10530
  ${scanned}
10009
10531
  }`;
10010
10532
  }
10533
+ function emitHoldTerm(callee, dst, t, l, skip) {
10534
+ const fast = `const ${t}v=${callee}(input,cur,ctx)
10535
+ if(${t}v===FAIL)return FAIL
10536
+ ${dst}=${t}v
10537
+ cur=EC.e`;
10538
+ if (l.tri === TRI_NONE) return fast;
10539
+ const held = `const ${t}s=${skip}(input,cur,ctx)
10540
+ const ${t}v=${callee}(input,${t}s,ctx)
10541
+ if(${t}v===FAIL)return FAIL
10542
+ ${dst}=${t}v
10543
+ cur=${t}s`;
10544
+ if (l.tri !== TRI_UNKNOWN) return held;
10545
+ return `if(ctx.trivia===undefined){
10546
+ ${fast}
10547
+ }else{
10548
+ ${held}
10549
+ }`;
10550
+ }
10011
10551
  function leadSkip(hasTrivia, leadTrivia, skip) {
10012
10552
  if (hasTrivia === "false") return "{}";
10013
10553
  const call = `itemStart=${skip}(input,itemStart,ctx)`;
@@ -10049,6 +10589,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, se
10049
10589
  const reachable = [...reachableSites(code, roots)];
10050
10590
  const labels = computeSiteLabels(code, roots, hostCst);
10051
10591
  const scalarSpecs = /* @__PURE__ */ new Set();
10592
+ const nullable2 = /* @__PURE__ */ new Map();
10052
10593
  const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
10053
10594
  const largeChoiceLiteralFamilies = /* @__PURE__ */ new Map();
10054
10595
  const largeChoiceScalarSequences = /* @__PURE__ */ new Map();
@@ -10373,9 +10914,7 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
10373
10914
  const op = code[ip];
10374
10915
  if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
10375
10916
  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
- }
10917
+ if (scopeIsIdentity(code, ip, labels.at(ip))) return code[ip + 2];
10379
10918
  return void 0;
10380
10919
  }
10381
10920
  function lower(ip, fname) {
@@ -10497,6 +11036,22 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
10497
11036
  return `${head}
10498
11037
  if(${gateMissTest(ip)}){ctx._fe=pos;ctx._fx=${xf};return FAIL}
10499
11038
  return ${child}(input,pos,ctx)
11039
+ }`;
11040
+ }
11041
+ case OP_RGATE: {
11042
+ const child = link(code[ip + 2]);
11043
+ if (cfg.tolerant || cfg.probe) return `${head}
11044
+ return ${child}(input,pos,ctx)
11045
+ }`;
11046
+ const resolved = t.cc[code[ip + 1]];
11047
+ const ci = classes.push([resolved]) - 1;
11048
+ classPlan.push([code[ip + 1]]);
11049
+ const cls = hoist("cl", `CLS[${ci}][0]`);
11050
+ const xf = fxRef(code[ip + 3]);
11051
+ return `${head}
11052
+ const it=ctx._routed
11053
+ if(it!==undefined&&it.span.start===pos&&!classHas(${cls},lead(input,it.span.end))){ctx._fe=it.span.end;ctx._fx=${xf};return FAIL}
11054
+ return ${child}(input,pos,ctx)
10500
11055
  }`;
10501
11056
  }
10502
11057
  case OP_ARMGATE: {
@@ -10771,23 +11326,33 @@ return FAIL
10771
11326
  const p = tmp();
10772
11327
  return `${head}
10773
11328
  ${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${emitMark(p, L.buf, L.raw, sinks)}
10774
- const v=${child}(input,pos,ctx)
11329
+ ${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
10775
11330
  ${emitRollback(p, L.buf, L.raw, sinks)}
10776
- if(v===FAIL){EC.e=pos;return null}
11331
+ ${cfg.probe ? "if(ctx._probe!==undefined)ctx._probe.best=pb??null\n" : ""}if(v===FAIL){EC.e=pos;return null}
10777
11332
  ctx._fe=pos
10778
11333
  ctx._fx=${xf}
10779
11334
  return FAIL
10780
11335
  }`;
10781
11336
  }
10782
11337
  case OP_PEEK: {
11338
+ const scalarChild = scalarTerminalPeekChild(code, ip);
11339
+ if (scalarChild >= 0) {
11340
+ const recognize = recognizerRef(code[scalarChild + 1]);
11341
+ const xf2 = fxRef(code[ip + 2]);
11342
+ return `${head}
11343
+ if(${recognize}(input,pos)<0){ctx._fe=pos;ctx._fx=${xf2};return FAIL}
11344
+ EC.e=pos
11345
+ return null
11346
+ }`;
11347
+ }
10783
11348
  const child = link(code[ip + 1]);
10784
11349
  const xf = fxRef(code[ip + 2]);
10785
11350
  const p = tmp();
10786
11351
  return `${head}
10787
11352
  ${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)
11353
+ ${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
10789
11354
  ${emitRollback(p, L.buf, L.raw, sinks)}
10790
- if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
11355
+ ${cfg.probe ? "if(ctx._probe!==undefined)ctx._probe.best=pb??null\n" : ""}if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
10791
11356
  EC.e=pos
10792
11357
  return null
10793
11358
  }`;
@@ -10858,7 +11423,7 @@ return v
10858
11423
  );
10859
11424
  } else {
10860
11425
  const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
10861
- parts.push(emitTerm(callee, vn, tmp(), L, skipFor(L)));
11426
+ parts.push(holdsGap(code, k, base, n, i, nullable2) ? emitHoldTerm(callee, vn, tmp(), L, skipFor(L)) : emitTerm(callee, vn, tmp(), L, skipFor(L)));
10862
11427
  }
10863
11428
  names.push(vn);
10864
11429
  }
@@ -11341,6 +11906,26 @@ return nd
11341
11906
  const trailingTrivia = (flags & 128) !== 0;
11342
11907
  const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
11343
11908
  const leanFlags = flags & ~128;
11909
+ if (build !== void 0 && passCollapse(code, ip, hostCst)) {
11910
+ return `${head}
11911
+ const v=${child}(input,pos,ctx)
11912
+ if(v!==undefined)return v
11913
+ return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
11914
+ }`;
11915
+ }
11916
+ const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
11917
+ const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(labels.at(code[ip + 2]).tri, t.trivia);
11918
+ const gp = gated !== void 0 && triviaLead !== void 0 && triviaLead.length <= 16 ? `const gc=lead(input,pos)
11919
+ if(!(${[
11920
+ ...gated.leads.map((g) => `!(${gateMissTest(g)})`),
11921
+ ...gated.lits.map((i) => `gc===${k[i].codePointAt(0)}`),
11922
+ ...triviaLead.map((r) => r.lo === r.hi ? `gc===${r.lo}` : `(gc>=${r.lo}&&gc<=${r.hi})`)
11923
+ ].join("||") || "false"})){
11924
+ const gv=${link(gated.last)}(input,pos,ctx)
11925
+ if(gv!==undefined)return gv
11926
+ return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
11927
+ }
11928
+ ` : "";
11344
11929
  if (!hostCst && !tracked && build !== void 0 && proj < 0 && (leanFlags === 2 || (flags === 18 || flags === 34))) {
11345
11930
  const fields = flags === 18;
11346
11931
  const collapseChildren = flags === 34;
@@ -11375,7 +11960,7 @@ sCh.push(nd)
11375
11960
  if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
11376
11961
  }`;
11377
11962
  return `${head}
11378
- const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
11963
+ ${gp}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
11379
11964
  const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
11380
11965
  const flat=[]
11381
11966
  ctx._cstBuf=undefined
@@ -11450,7 +12035,7 @@ const hostKids=kids
11450
12035
  const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
11451
12036
  const tlog=buf.tl??EMPTY_TLOG`;
11452
12037
  return `${head}
11453
- const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
12038
+ ${!hostCst && !tracked ? gp : ""}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
11454
12039
  const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf
11455
12040
  ${openCapture}
11456
12041
  ctx.captureTrivia=${captureWide}
@@ -11520,9 +12105,15 @@ ext:[${externals.join(",")}],
11520
12105
  bind:function(xs,ps){_xScan=xs
11521
12106
  ${externals.map((ip, i) => `_xp${ip}=ps[${i}]`).join("\n")}},
11522
12107
  scan:function(s){const o=_pfScan;_pfScan=s;return o}`;
12108
+ const scannerFor = (ip) => {
12109
+ const ki = labels.at(ip).tri;
12110
+ if (ki === TRI_UNKNOWN) return "_pfScan";
12111
+ if (ki === TRI_NONE) return "null";
12112
+ return swapLegal && !triviaLabelled[ki] && t.triviaScan[ki] != null ? hoist("ts", `TRIVIASCAN[${ki}]`) : "null";
12113
+ };
11523
12114
  const externalDefs = select === void 0 ? "" : `let _xScan
11524
12115
  ${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")}
12116
+ 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
12117
  `;
11527
12118
  const source = `${RUNTIME_PRELUDE}${needsNoRawPrelude ? NO_RAW_RUNTIME_PRELUDE : ""}
11528
12119
  ${prelude.join("\n")}
@@ -12059,37 +12650,120 @@ function clearOf(ranges, input, from, to) {
12059
12650
  return true;
12060
12651
  }
12061
12652
 
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;
12653
+ // src/table/fail-clean.ts
12654
+ function passChild(code, ip) {
12655
+ switch (code[ip]) {
12656
+ case OP_RULE:
12657
+ case OP_LABEL:
12658
+ case OP_COV:
12659
+ case OP_TOKEN:
12660
+ return code[ip + 1];
12661
+ case OP_GATE:
12662
+ case OP_NODE:
12663
+ case OP_NODE_TRACK:
12664
+ case OP_XFORM:
12665
+ case OP_FIELD:
12666
+ case OP_SCOPE:
12667
+ case OP_SCOPE_CAP:
12668
+ case OP_SCOPE_PLAIN:
12669
+ case OP_WITHCTX:
12670
+ case OP_LEAF:
12671
+ case OP_SOURCE_LEAF:
12672
+ return code[ip + 2];
12673
+ default:
12674
+ return -1;
12070
12675
  }
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
12676
  }
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 }
12677
+ function seqCount(code, ip) {
12678
+ const op = code[ip];
12679
+ return op === OP_SEQ || op === OP_SEQV ? ip + 1 : op === OP_SEQX ? ip + 2 : -1;
12680
+ }
12681
+ function failCleanAnalysis(code) {
12682
+ const cleanAt = new Uint8Array(code.length);
12683
+ const neverAt = new Uint8Array(code.length);
12684
+ const neverFails = (ip) => {
12685
+ const hit = neverAt[ip];
12686
+ if (hit !== 0) return hit === 1;
12687
+ neverAt[ip] = 3;
12688
+ let out = false;
12689
+ const op = code[ip];
12690
+ if (op === OP_OPT || op === OP_EMPTY || op === OP_EXPECT) out = true;
12691
+ else if (op === OP_REP || op === OP_REPV) out = code[ip + 2] === 0;
12692
+ else {
12693
+ const at = seqCount(code, ip);
12694
+ if (at >= 0) {
12695
+ out = true;
12696
+ for (let i = 1, n = code[at]; out && i <= n; i++) out = neverFails(code[at + i]);
12697
+ } else if (op !== OP_GATE) {
12698
+ const c = passChild(code, ip);
12699
+ out = c >= 0 && neverFails(c);
12700
+ }
12701
+ }
12702
+ neverAt[ip] = out ? 1 : 2;
12703
+ return out;
12086
12704
  };
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;
12705
+ const clean = (ip) => {
12706
+ const hit = cleanAt[ip];
12707
+ if (hit !== 0) return hit === 1;
12708
+ cleanAt[ip] = 3;
12709
+ let out = false;
12710
+ switch (code[ip]) {
12711
+ // A terminal pushes its leaf only on a match; NOT/PEEK/ATTEMPT restore
12712
+ // their own mark; OPT, EMPTY and EXPECT do not fail uncommitted.
12713
+ case OP_LIT:
12714
+ case OP_RX:
12715
+ case OP_LIT_TRACK:
12716
+ case OP_RX_TRACK:
12717
+ case OP_LIT_CI:
12718
+ case OP_LIT_CI_TRACK:
12719
+ case OP_GUARD:
12720
+ case OP_NOT:
12721
+ case OP_PEEK:
12722
+ case OP_ATTEMPT:
12723
+ case OP_EMPTY:
12724
+ case OP_OPT:
12725
+ case OP_EXPECT:
12726
+ out = true;
12727
+ break;
12728
+ // Min 0 does not fail uncommitted; min 1 fails only with no item kept, and
12729
+ // restores the failed item itself.
12730
+ case OP_REP:
12731
+ case OP_REPV:
12732
+ out = code[ip + 2] <= 1;
12733
+ break;
12734
+ // Only the first term may fail: a later one fails after the terms before it
12735
+ // wrote, and after the trivia scanned in front of it.
12736
+ case OP_SEQ:
12737
+ case OP_SEQV:
12738
+ case OP_SEQX: {
12739
+ const at = seqCount(code, ip);
12740
+ const n = code[at];
12741
+ out = n > 0 && clean(code[at + 1]);
12742
+ for (let i = 2; out && i <= n; i++) out = neverFails(code[at + i]);
12743
+ break;
12744
+ }
12745
+ case OP_CHOICE: {
12746
+ out = true;
12747
+ for (let i = 0, n = code[ip + 2]; out && i < n; i++) out = clean(code[ip + 4 + i]);
12748
+ break;
12749
+ }
12750
+ case OP_ROUTED:
12751
+ out = code[ip + 1] < 0 || clean(code[ip + 1]);
12752
+ break;
12753
+ // An arm's failure and the fallback's are committed; only the selector's is
12754
+ // not, and without a fallback an unknown key fails after the selector wrote.
12755
+ case OP_DISPATCH:
12756
+ out = code[ip + 3] >= 0 && clean(code[ip + 1]);
12757
+ break;
12758
+ default: {
12759
+ const c = passChild(code, ip);
12760
+ out = c >= 0 && clean(c);
12761
+ }
12762
+ }
12763
+ cleanAt[ip] = out ? 1 : 2;
12764
+ return out;
12765
+ };
12766
+ return clean;
12093
12767
  }
12094
12768
 
12095
12769
  // src/cst/host-mode.ts
@@ -12254,6 +12928,7 @@ function assemble(t, prog, cfg) {
12254
12928
  const swapLegal = !cfg.trackLines;
12255
12929
  const hostCst = cfg.hostCst;
12256
12930
  const REC2 = prog.rec === 1 && cfg.tolerant;
12931
+ const PROBE = cfg.probe;
12257
12932
  const sentinels = /* @__PURE__ */ new Map();
12258
12933
  function sentinelFor(cls) {
12259
12934
  if (cls < 0) return void 0;
@@ -12299,6 +12974,8 @@ function assemble(t, prog, cfg) {
12299
12974
  }
12300
12975
  const memo = /* @__PURE__ */ new Map();
12301
12976
  const reached = /* @__PURE__ */ new Set();
12977
+ const NULLABLE = /* @__PURE__ */ new Map();
12978
+ const CLEAN = REC2 ? () => false : failCleanAnalysis(code);
12302
12979
  function pushLeaf(ctx, value, s, e) {
12303
12980
  const lf = { _tag: "leaf", value, span: { start: s, end: e } };
12304
12981
  pushCstLeaf(ctx, lf);
@@ -12497,6 +13174,22 @@ function assemble(t, prog, cfg) {
12497
13174
  return node2;
12498
13175
  };
12499
13176
  }
13177
+ function passCollapseNode(child, build, readsRaw) {
13178
+ return (input, pos, ctx) => {
13179
+ const v = child(input, pos, ctx);
13180
+ if (v !== void 0) return v;
13181
+ return collapseEmpty(ctx, build, input, pos, EC.e, readsRaw);
13182
+ };
13183
+ }
13184
+ function gatedPassCollapseNode(blockers, last, classic, build, readsRaw) {
13185
+ return (input, pos, ctx) => {
13186
+ const c = lead(input, pos);
13187
+ for (let i = 0; i < blockers.length; i++) if (classHas2(blockers[i], c)) return classic(input, pos, ctx);
13188
+ const v = last(input, pos, ctx);
13189
+ if (v !== void 0) return v;
13190
+ return collapseEmpty(ctx, build, input, pos, EC.e, readsRaw);
13191
+ };
13192
+ }
12500
13193
  function plainProjectNode(child, projection, type) {
12501
13194
  return (input, pos, ctx) => {
12502
13195
  const sCh = ctx._cstChildren;
@@ -12867,21 +13560,27 @@ function assemble(t, prog, cfg) {
12867
13560
  }
12868
13561
  function dispatchBranch(child, usesRouted) {
12869
13562
  if (!usesRouted) {
12870
- return (input, _pos, selEnd, key, _selectorMark, ctx) => {
12871
- const mark = saveTriviaMark(ctx);
13563
+ return (input, _pos, selEnd, key, ctx) => {
13564
+ const need = markCst(ctx);
13565
+ const mRaw = MRAW;
13566
+ const mTl = MTL;
13567
+ const mLv = MLV;
13568
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
13569
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
13570
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
13571
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
12872
13572
  const v = child(input, selEnd, ctx);
12873
13573
  if (v === FAIL) {
12874
- rollbackTrivia(ctx, mark);
13574
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12875
13575
  ctx._fc = true;
12876
13576
  return FAIL;
12877
13577
  }
12878
13578
  return [key, v];
12879
13579
  };
12880
13580
  }
12881
- return (input, pos, selEnd, key, selectorMark, ctx) => {
13581
+ return (input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot) => {
12882
13582
  const savedRouted = ctx._routed;
12883
- rollbackTrivia(ctx, selectorMark);
12884
- const mark = saveTriviaMark(ctx);
13583
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12885
13584
  ctx._routed = { value: key, span: { start: pos, end: selEnd } };
12886
13585
  let v;
12887
13586
  try {
@@ -12890,7 +13589,7 @@ function assemble(t, prog, cfg) {
12890
13589
  ctx._routed = savedRouted;
12891
13590
  }
12892
13591
  if (v === FAIL) {
12893
- rollbackTrivia(ctx, mark);
13592
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12894
13593
  ctx._fc = true;
12895
13594
  return FAIL;
12896
13595
  }
@@ -12898,12 +13597,12 @@ function assemble(t, prog, cfg) {
12898
13597
  };
12899
13598
  }
12900
13599
  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);
13600
+ return (arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot) => {
13601
+ if (arm === start) return a0(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
13602
+ if (arm === start + 1) return a1(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
13603
+ if (arm === start + 2) return a2(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
13604
+ if (arm === start + 3) return a3(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
13605
+ return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12907
13606
  };
12908
13607
  }
12909
13608
  function trackLinesInto(ctx, input, end) {
@@ -12922,7 +13621,7 @@ function assemble(t, prog, cfg) {
12922
13621
  if (flight !== void 0) return flight.fwd;
12923
13622
  const selected = HYBRID?.byIp[ip];
12924
13623
  if (selected !== void 0) {
12925
- const piece2 = hybridPiece(selected);
13624
+ const piece2 = scanHandoffNeeded(code, ip, closureLabels) ? hybridPiece(selected) : selected;
12926
13625
  memo.set(ip, piece2);
12927
13626
  reached.add(ip);
12928
13627
  return piece2;
@@ -12933,14 +13632,55 @@ function assemble(t, prog, cfg) {
12933
13632
  target = p;
12934
13633
  } };
12935
13634
  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);
13635
+ const piece = scopeIsIdentity(code, ip, closureLabels.at(ip)) ? link(code[ip + 2]) : countedPiece(lookaheadLedNode(ip) ?? lower(ip), ip);
12938
13636
  inFlight.delete(ip);
12939
13637
  holder.set(piece);
12940
13638
  memo.set(ip, piece);
12941
13639
  reached.add(ip);
12942
13640
  return piece;
12943
13641
  }
13642
+ let FIRST_DECIDED;
13643
+ let NODE_BODY;
13644
+ const DECIDED = (_input, pos) => {
13645
+ EC.e = pos;
13646
+ return null;
13647
+ };
13648
+ function lookaheadLedNode(ip) {
13649
+ const op = code[ip];
13650
+ if (op !== OP_NODE && op !== OP_NODE_TRACK || hostCst || REC2 || cfg.probe || cfg.coverage || cfg.trackLines) return void 0;
13651
+ if (passCollapse(code, ip, hostCst) || gatedPassCollapse(code, ip, hostCst) !== void 0) return void 0;
13652
+ const body = code[ip + 2];
13653
+ const bop = code[body];
13654
+ if (bop !== OP_SEQ && bop !== OP_SEQV && bop !== OP_SEQX) return void 0;
13655
+ const base = bop === OP_SEQX ? body + 3 : body + 2;
13656
+ if (code[bop === OP_SEQX ? body + 2 : body + 1] < 2) return void 0;
13657
+ const first = code[base];
13658
+ const negative = code[first] === OP_NOT;
13659
+ const terminal = negative ? scalarTerminalNotChild(code, first) : code[first] === OP_PEEK ? scalarTerminalPeekChild(code, first) : -1;
13660
+ if (terminal < 0) return void 0;
13661
+ const recognize = scalarFor(terminal);
13662
+ const xf = fx[code[first + 2]];
13663
+ FIRST_DECIDED = DECIDED;
13664
+ NODE_BODY = lower(body);
13665
+ const node2 = lower(ip);
13666
+ NODE_BODY = void 0;
13667
+ return negative ? (input, pos, ctx) => {
13668
+ if (recognize(input, pos) >= 0) {
13669
+ ctx._fe = pos;
13670
+ ctx._fx = xf;
13671
+ EC.e = pos;
13672
+ return FAIL;
13673
+ }
13674
+ return node2(input, pos, ctx);
13675
+ } : (input, pos, ctx) => {
13676
+ if (recognize(input, pos) < 0) {
13677
+ ctx._fe = pos;
13678
+ ctx._fx = xf;
13679
+ return FAIL;
13680
+ }
13681
+ return node2(input, pos, ctx);
13682
+ };
13683
+ }
12944
13684
  function lower(ip) {
12945
13685
  const op = code[ip];
12946
13686
  switch (op) {
@@ -13485,8 +14225,10 @@ function assemble(t, prog, cfg) {
13485
14225
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
13486
14226
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
13487
14227
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
14228
+ const probeBest = PROBE ? ctx._probe?.best : void 0;
13488
14229
  const v = child(input, pos, ctx);
13489
14230
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14231
+ if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
13490
14232
  if (v === FAIL) {
13491
14233
  EC.e = pos;
13492
14234
  return null;
@@ -13497,6 +14239,20 @@ function assemble(t, prog, cfg) {
13497
14239
  };
13498
14240
  }
13499
14241
  case OP_PEEK: {
14242
+ const scalarChild = scalarTerminalPeekChild(code, ip);
14243
+ if (scalarChild >= 0) {
14244
+ const recognize = scalarFor(scalarChild);
14245
+ const xf2 = fx[code[ip + 2]];
14246
+ return (input, pos, ctx) => {
14247
+ if (recognize(input, pos) < 0) {
14248
+ ctx._fe = pos;
14249
+ ctx._fx = xf2;
14250
+ return FAIL;
14251
+ }
14252
+ EC.e = pos;
14253
+ return null;
14254
+ };
14255
+ }
13500
14256
  const child = link(code[ip + 1]);
13501
14257
  const xf = fx[code[ip + 2]];
13502
14258
  const gate2 = lookaheadClass(code[ip + 1]);
@@ -13514,8 +14270,10 @@ function assemble(t, prog, cfg) {
13514
14270
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
13515
14271
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
13516
14272
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
14273
+ const probeBest = PROBE ? ctx._probe?.best : void 0;
13517
14274
  const v = child(input, pos, ctx);
13518
14275
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14276
+ if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
13519
14277
  if (v === FAIL) {
13520
14278
  ctx._fe = pos;
13521
14279
  ctx._fx = xf;
@@ -13528,12 +14286,13 @@ function assemble(t, prog, cfg) {
13528
14286
  case OP_OPT: {
13529
14287
  const child = link(code[ip + 1]);
13530
14288
  const gate2 = lookaheadClass(code[ip + 1]);
14289
+ const childClean = CLEAN(code[ip + 1]);
13531
14290
  return (input, pos, ctx) => {
13532
14291
  if (gate2 !== null && !classHas2(gate2, lead(input, pos))) {
13533
14292
  EC.e = pos;
13534
14293
  return null;
13535
14294
  }
13536
- const need = markCst(ctx);
14295
+ const need = !childClean && markCst(ctx);
13537
14296
  const mRaw = MRAW;
13538
14297
  const mTl = MTL;
13539
14298
  const mLv = MLV;
@@ -13731,6 +14490,9 @@ function assemble(t, prog, cfg) {
13731
14490
  const projection = reducer < 0 ? ~reducer : -1;
13732
14491
  const fn = fused && projection < 0 ? fns[reducer] : void 0;
13733
14492
  const step = closureLabels.at(ip).buf ? nextTermBuffered : nextTerm;
14493
+ const decided = FIRST_DECIDED;
14494
+ FIRST_DECIDED = void 0;
14495
+ const linkFirst = () => decided ?? link(code[base]);
13734
14496
  const runnerBlock = (count, r0, r1, r2, r3, next) => {
13735
14497
  if (count === 1) return (input, cur, ctx, values, inherited) => {
13736
14498
  cur = r0(input, cur, ctx, inherited);
@@ -13776,7 +14538,7 @@ function assemble(t, prog, cfg) {
13776
14538
  };
13777
14539
  };
13778
14540
  if (REC2) {
13779
- const first2 = link(code[base]);
14541
+ const first2 = linkFirst();
13780
14542
  const firstSync = sentinelFor(code[base + n]);
13781
14543
  const runnerAt = (i) => {
13782
14544
  const sync = sentinelFor(code[base + n + i]);
@@ -13812,13 +14574,13 @@ function assemble(t, prog, cfg) {
13812
14574
  const bindRunners = (start) => {
13813
14575
  const count = Math.min(4, n - start);
13814
14576
  const at = (offset) => runnerAt(start + offset);
13815
- const never = () => -1;
14577
+ const never2 = () => -1;
13816
14578
  return runnerBlock(
13817
14579
  count,
13818
14580
  at(0),
13819
- count > 1 ? at(1) : never,
13820
- count > 2 ? at(2) : never,
13821
- count > 3 ? at(3) : never,
14581
+ count > 1 ? at(1) : never2,
14582
+ count > 2 ? at(2) : never2,
14583
+ count > 3 ? at(3) : never2,
13822
14584
  start + count < n ? bindRunners(start + count) : void 0
13823
14585
  );
13824
14586
  };
@@ -13868,15 +14630,31 @@ function assemble(t, prog, cfg) {
13868
14630
  let hasAdj = false;
13869
14631
  for (let i = 1; i < n; i++) {
13870
14632
  const kidIp = code[base + i];
13871
- if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp)) {
14633
+ if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp) || holdsGap(code, k, base, n, i, NULLABLE)) {
13872
14634
  hasAdj = true;
13873
14635
  break;
13874
14636
  }
13875
14637
  }
13876
14638
  if (hasAdj) {
13877
- const first2 = link(code[base]);
14639
+ const first2 = linkFirst();
13878
14640
  const runnerAt = (i) => {
13879
14641
  const kidIp = code[base + i];
14642
+ if (holdsGap(code, k, base, n, i, NULLABLE)) {
14643
+ const kid = link(kidIp);
14644
+ return (input, cur, ctx) => {
14645
+ if (ctx.trivia === void 0) {
14646
+ const v2 = kid(input, cur, ctx);
14647
+ if (v2 === FAIL) return -1;
14648
+ TERMV = v2;
14649
+ return EC.e;
14650
+ }
14651
+ const scanEnd = skipTrivia(input, cur, ctx);
14652
+ const v = kid(input, scanEnd, ctx);
14653
+ if (v === FAIL) return -1;
14654
+ TERMV = v;
14655
+ return scanEnd;
14656
+ };
14657
+ }
13880
14658
  if (code[kidIp] !== OP_ADJ) {
13881
14659
  const kid = link(kidIp);
13882
14660
  if (leadingTriviaFieldAt(code, k, kidIp)) {
@@ -13901,13 +14679,13 @@ function assemble(t, prog, cfg) {
13901
14679
  const bindRunners = (start) => {
13902
14680
  const count = Math.min(4, n - start);
13903
14681
  const at = (offset) => runnerAt(start + offset);
13904
- const never = () => -1;
14682
+ const never2 = () => -1;
13905
14683
  return runnerBlock(
13906
14684
  count,
13907
14685
  at(0),
13908
- count > 1 ? at(1) : never,
13909
- count > 2 ? at(2) : never,
13910
- count > 3 ? at(3) : never,
14686
+ count > 1 ? at(1) : never2,
14687
+ count > 2 ? at(2) : never2,
14688
+ count > 3 ? at(3) : never2,
13911
14689
  start + count < n ? bindRunners(start + count) : void 0
13912
14690
  );
13913
14691
  };
@@ -13944,7 +14722,7 @@ function assemble(t, prog, cfg) {
13944
14722
  };
13945
14723
  }
13946
14724
  if (n === 1) {
13947
- const k0 = link(code[base]);
14725
+ const k0 = linkFirst();
13948
14726
  if (fused) {
13949
14727
  return (input, pos, ctx) => {
13950
14728
  const v = k0(input, pos, ctx);
@@ -13966,7 +14744,7 @@ function assemble(t, prog, cfg) {
13966
14744
  };
13967
14745
  }
13968
14746
  if (n === 2) {
13969
- const k0 = link(code[base]), k1 = link(code[base + 1]);
14747
+ const k0 = linkFirst(), k1 = link(code[base + 1]);
13970
14748
  if (fused) {
13971
14749
  return (input, pos, ctx) => {
13972
14750
  const v0 = k0(input, pos, ctx);
@@ -13997,7 +14775,7 @@ function assemble(t, prog, cfg) {
13997
14775
  };
13998
14776
  }
13999
14777
  if (n === 3) {
14000
- const k0 = link(code[base]), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
14778
+ const k0 = linkFirst(), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
14001
14779
  if (fused) {
14002
14780
  return (input, pos, ctx) => {
14003
14781
  const v0 = k0(input, pos, ctx);
@@ -14091,7 +14869,7 @@ function assemble(t, prog, cfg) {
14091
14869
  start + count < n ? bind(start + count) : void 0
14092
14870
  );
14093
14871
  };
14094
- const first = link(code[base]);
14872
+ const first = linkFirst();
14095
14873
  const tail = bind(1);
14096
14874
  const runDirectTerms = (input, pos, ctx, values) => {
14097
14875
  const v0 = first(input, pos, ctx);
@@ -14130,6 +14908,8 @@ function assemble(t, prog, cfg) {
14130
14908
  const n = code[ip + 2];
14131
14909
  const choiceFx = fx[code[ip + 3]];
14132
14910
  const base = ip + 4;
14911
+ for (let i = 0; i < n; i++) link(code[base + i]);
14912
+ const armsClean = CLEAN(ip);
14133
14913
  if (table.exclusive) {
14134
14914
  const ascii = table.ascii;
14135
14915
  const hi = table.hi;
@@ -14269,7 +15049,7 @@ function assemble(t, prog, cfg) {
14269
15049
  if (n === 3) addGate(g2, 4);
14270
15050
  return (input, pos, ctx) => {
14271
15051
  const c = lead(input, pos);
14272
- const need = markCst(ctx);
15052
+ const need = !armsClean && markCst(ctx);
14273
15053
  const mRaw = MRAW;
14274
15054
  const mTl = MTL;
14275
15055
  const mLv = MLV;
@@ -14486,7 +15266,7 @@ function assemble(t, prog, cfg) {
14486
15266
  if (pn !== 0) {
14487
15267
  return (input, pos, ctx) => {
14488
15268
  const c = lead(input, pos);
14489
- const need = markCst(ctx);
15269
+ const need = !armsClean && markCst(ctx);
14490
15270
  const mRaw = MRAW;
14491
15271
  const mTl = MTL;
14492
15272
  const mLv = MLV;
@@ -14543,7 +15323,7 @@ function assemble(t, prog, cfg) {
14543
15323
  }
14544
15324
  return (input, pos, ctx) => {
14545
15325
  const c = lead(input, pos);
14546
- const need = markCst(ctx);
15326
+ const need = !armsClean && markCst(ctx);
14547
15327
  const mRaw = MRAW;
14548
15328
  const mTl = MTL;
14549
15329
  const mLv = MLV;
@@ -14591,7 +15371,7 @@ function assemble(t, prog, cfg) {
14591
15371
  }
14592
15372
  return (input, pos, ctx) => {
14593
15373
  const c = lead(input, pos);
14594
- const need = markCst(ctx);
15374
+ const need = !armsClean && markCst(ctx);
14595
15375
  const mRaw = MRAW;
14596
15376
  const mTl = MTL;
14597
15377
  const mLv = MLV;
@@ -14645,6 +15425,21 @@ function assemble(t, prog, cfg) {
14645
15425
  return lit(input, pos, ctx);
14646
15426
  };
14647
15427
  }
15428
+ case OP_RGATE: {
15429
+ const cls = cc[code[ip + 1]];
15430
+ const xf = fx[code[ip + 3]];
15431
+ const child = link(code[ip + 2]);
15432
+ if (cfg.tolerant || cfg.probe) return child;
15433
+ return (input, pos, ctx) => {
15434
+ const item = ctx._routed;
15435
+ if (item !== void 0 && item.span.start === pos && !classHas2(cls, lead(input, item.span.end))) {
15436
+ ctx._fe = item.span.end;
15437
+ ctx._fx = xf;
15438
+ return FAIL;
15439
+ }
15440
+ return child(input, pos, ctx);
15441
+ };
15442
+ }
14648
15443
  case OP_ARMGATE: {
14649
15444
  const pred = fns[code[ip + 1]];
14650
15445
  const child = link(code[ip + 2]);
@@ -14713,6 +15508,7 @@ function assemble(t, prog, cfg) {
14713
15508
  const itemClass = !REC2 && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
14714
15509
  const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
14715
15510
  const skipBeforeFirst = sepIp < 0 && min === 0;
15511
+ const itemClean = sepIp < 0 && CLEAN(code[ip + 1]) && !rowNullable(code, k, code[ip + 1], NULLABLE);
14716
15512
  if (REC2) {
14717
15513
  const itemFx2 = fx[code[ip + 6]];
14718
15514
  const sepSent = sentinelFor(code[ip + 7]);
@@ -14809,6 +15605,8 @@ function assemble(t, prog, cfg) {
14809
15605
  const out = collect ? [] : void 0;
14810
15606
  const hasTrivia = ctx.trivia !== void 0;
14811
15607
  const needMark = rollbackNeeded(ctx);
15608
+ const markLater = needMark && (!itemClean || hasTrivia);
15609
+ const markFirst = needMark && (!itemClean || hasTrivia && skipBeforeFirst);
14812
15610
  const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
14813
15611
  let cur = pos;
14814
15612
  let count = 0;
@@ -14816,14 +15614,15 @@ function assemble(t, prog, cfg) {
14816
15614
  if (max >= 0 && count >= max) break;
14817
15615
  if (sep2 !== void 0 && count > 0 && count >= min && cur >= input.length) break;
14818
15616
  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;
15617
+ const markIt = count > 0 ? markLater : markFirst;
15618
+ if (markIt) markCst(ctx);
15619
+ const mRaw = markIt ? MRAW : 0;
15620
+ const mTl = markIt ? MTL : 0;
15621
+ const mLv = markIt ? MLV : 0;
15622
+ const mFl = markIt ? ctx._fields?.length ?? 0 : 0;
15623
+ const mEr = markIt ? ctx._errors?.length ?? 0 : 0;
15624
+ const mLog = markIt ? ctx._triviaLog?.length ?? 0 : 0;
15625
+ const mRoot = markIt ? ctx._rootTriviaLog?.length ?? 0 : 0;
14827
15626
  let itemStart = cur;
14828
15627
  let sepEnd = -1;
14829
15628
  const viaRepItem = sep2 === void 0 && count >= min && (count > 0 || skipBeforeFirst);
@@ -14835,7 +15634,7 @@ function assemble(t, prog, cfg) {
14835
15634
  if (sepLeads) LEAD.at = cur;
14836
15635
  const sv = sep2(input, sp, ctx);
14837
15636
  if (sv === FAIL) {
14838
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
15637
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14839
15638
  if (committed3(ctx)) return FAIL;
14840
15639
  break;
14841
15640
  }
@@ -14846,25 +15645,25 @@ function assemble(t, prog, cfg) {
14846
15645
  itemStart = skipTrivia(input, itemStart, ctx);
14847
15646
  }
14848
15647
  if (itemStart >= input.length && viaRepItem) {
14849
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
15648
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14850
15649
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
14851
15650
  break;
14852
15651
  }
14853
15652
  if (count >= min && gateItems && !itemMayStart(input, itemStart)) {
14854
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
15653
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14855
15654
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
14856
15655
  break;
14857
15656
  }
14858
15657
  ctx._fc = false;
14859
15658
  const v = child(input, itemStart, ctx);
14860
15659
  if (v === FAIL) {
14861
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
15660
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14862
15661
  if (committed3(ctx)) return FAIL;
14863
15662
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
14864
15663
  break;
14865
15664
  }
14866
15665
  if (EC.e === itemStart && viaRepItem) {
14867
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
15666
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14868
15667
  break;
14869
15668
  }
14870
15669
  if (out !== void 0) out.push(v);
@@ -14938,7 +15737,14 @@ function assemble(t, prog, cfg) {
14938
15737
  const runArm = n === 0 ? void 0 : bindArms(0);
14939
15738
  const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted);
14940
15739
  return (input, pos, ctx) => {
14941
- const selectorMark = saveTriviaMark(ctx);
15740
+ const need = markCst(ctx);
15741
+ const mRaw = MRAW;
15742
+ const mTl = MTL;
15743
+ const mLv = MLV;
15744
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
15745
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
15746
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
15747
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
14942
15748
  const selVal = selector(input, pos, ctx);
14943
15749
  if (selVal === FAIL) return FAIL;
14944
15750
  const selEnd = EC.e;
@@ -14950,9 +15756,9 @@ function assemble(t, prog, cfg) {
14950
15756
  ctx._fx = expected;
14951
15757
  return FAIL;
14952
15758
  }
14953
- return runOther(input, pos, selEnd, key, selectorMark, ctx);
15759
+ return runOther(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14954
15760
  }
14955
- return runArm(arm, input, pos, selEnd, key, selectorMark, ctx);
15761
+ return runArm(arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14956
15762
  };
14957
15763
  }
14958
15764
  /* ── node ────────────────────────────────────────────────────────────── */
@@ -14988,7 +15794,8 @@ function assemble(t, prog, cfg) {
14988
15794
  return nd;
14989
15795
  };
14990
15796
  }
14991
- const child = link(code[ip + 2]);
15797
+ const child = NODE_BODY ?? link(code[ip + 2]);
15798
+ NODE_BODY = void 0;
14992
15799
  const proj = code[ip + 4];
14993
15800
  const buildIdx = code[ip + 1];
14994
15801
  const type = k[code[ip + 5]];
@@ -15012,6 +15819,30 @@ function assemble(t, prog, cfg) {
15012
15819
  if (build !== void 0 && proj < 0 && flags === 18) {
15013
15820
  return childrenOnlyFieldsBuildNode(child, build);
15014
15821
  }
15822
+ if (build !== void 0 && passCollapse(code, ip, hostCst)) {
15823
+ return passCollapseNode(child, build, flags === 32);
15824
+ }
15825
+ const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
15826
+ const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(closureLabels.at(code[ip + 2]).tri, trivia2);
15827
+ if (build !== void 0 && gated !== void 0 && triviaLead !== void 0) {
15828
+ const classic = flags === 32 ? collapseBuildNode(child, build) : childrenOnlyCollapseBuildNode(child, build);
15829
+ return gatedPassCollapseNode(
15830
+ [
15831
+ ...gated.leads.map((g) => cc[code[g + 1]]),
15832
+ resolveClass(encodeClassSpec([
15833
+ ...triviaLead,
15834
+ ...gated.lits.map((i) => {
15835
+ const c = k[i].codePointAt(0);
15836
+ return { lo: c, hi: c };
15837
+ })
15838
+ ]))
15839
+ ],
15840
+ link(gated.last),
15841
+ classic,
15842
+ build,
15843
+ flags === 32
15844
+ );
15845
+ }
15015
15846
  if (build !== void 0 && proj < 0 && flags === 32) {
15016
15847
  return collapseBuildNode(child, build);
15017
15848
  }
@@ -15160,6 +15991,8 @@ function assemble(t, prog, cfg) {
15160
15991
  }
15161
15992
  const notChild = scalarTerminalNotChild(code, ip);
15162
15993
  if (notChild >= 0) scalarFor(notChild);
15994
+ const peekChild = scalarTerminalPeekChild(code, ip);
15995
+ if (peekChild >= 0) scalarFor(peekChild);
15163
15996
  }
15164
15997
  const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
15165
15998
  if (pre !== void 0) {
@@ -15219,7 +16052,8 @@ function assemble(t, prog, cfg) {
15219
16052
  t.lexPrograms,
15220
16053
  LEAD,
15221
16054
  triviaFieldCapture,
15222
- skipDeferredTrivia
16055
+ skipDeferredTrivia,
16056
+ collapseEmpty
15223
16057
  );
15224
16058
  emitReached = new Set(pre.reached);
15225
16059
  if (emitted.ext !== void 0) HYBRID = emitted;
@@ -15305,7 +16139,8 @@ function assemble(t, prog, cfg) {
15305
16139
  t.lexPrograms,
15306
16140
  LEAD,
15307
16141
  triviaFieldCapture,
15308
- skipDeferredTrivia
16142
+ skipDeferredTrivia,
16143
+ collapseEmpty
15309
16144
  );
15310
16145
  emitReached = em.reached;
15311
16146
  } catch (e) {
@@ -15583,7 +16418,7 @@ function emitClassPool(classes) {
15583
16418
  if (classes.length < 2) return array;
15584
16419
  const delimiter = "|/~?^`".split("").find((ch2) => classes.every((spec) => !spec.includes(ch2)));
15585
16420
  if (delimiter === void 0) return array;
15586
- const split = `${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
16421
+ const split = `/* @__PURE__ */ ${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
15587
16422
  return split.length < array.length ? split : array;
15588
16423
  }
15589
16424
  function emitConst(v) {
@@ -17366,15 +18201,20 @@ function compileRuleMap(ruleMap, opts = {}) {
17366
18201
  throw e;
17367
18202
  }
17368
18203
  const ceiling = budget / SUPERCOMPILE_GROWTH;
18204
+ if (ceiling <= fixed) return none;
17369
18205
  let target = ceiling;
17370
- for (let attempt2 = 0; attempt2 < 16; attempt2++) {
18206
+ for (; ; ) {
17371
18207
  const sites = selectHotSites(artifact.code, Object.values(artifact.rules), siteBytes, target - fixed, profile);
17372
- if (sites.size === 0) return none;
18208
+ if (sites.size === 0) {
18209
+ return {
18210
+ ...none,
18211
+ refusal: `a site within its ${Math.floor(ceiling)} B selection ceiling (the prelude alone is ${fixed} B)`
18212
+ };
18213
+ }
17373
18214
  const bytes = emitAssemblySource(table, artifact, cfg, roots, true, sites).source.length;
17374
18215
  if (bytes <= ceiling) return { sites, bytes: Math.ceil(bytes * SUPERCOMPILE_GROWTH) };
17375
18216
  target *= Math.min(ceiling / bytes, 0.99);
17376
18217
  }
17377
- return none;
17378
18218
  };
17379
18219
  return {
17380
18220
  keys: ruleMap.map(([key]) => key),
@@ -17462,16 +18302,16 @@ function ownSource(fn) {
17462
18302
  return typeof name === "string" && name.length > 0 && globalThis[name] === fn ? name : null;
17463
18303
  }
17464
18304
  function compile(target, second, third) {
17465
- if (!isCombinator(target)) return compileMap(target, second);
18305
+ if (!isCombinator2(target)) return compileMap(target, second);
17466
18306
  return compileRoot(target, second, third);
17467
18307
  }
17468
- function isCombinator(x) {
18308
+ function isCombinator2(x) {
17469
18309
  return typeof x === "object" && x !== null && typeof x.parse === "function" && "_def" in x;
17470
18310
  }
17471
18311
  function compileMap(grammar, opts = {}) {
17472
18312
  const entries = [];
17473
18313
  for (const [key, value] of Object.entries(grammar)) {
17474
- if (!isCombinator(value)) throw new TypeError(`compile: grammar entry "${key}" is not a parser`);
18314
+ if (!isCombinator2(value)) throw new TypeError(`compile: grammar entry "${key}" is not a parser`);
17475
18315
  if (value._def.tag === "lazy") {
17476
18316
  try {
17477
18317
  value._def.thunk();
@@ -18016,7 +18856,7 @@ function fieldOptionsSrc(def) {
18016
18856
  }
18017
18857
 
18018
18858
  // src/version.ts
18019
- var PARSEMAN_VERSION = "0.57.0";
18859
+ var PARSEMAN_VERSION = "0.58.1";
18020
18860
 
18021
18861
  // src/compiler/compile-linkable-table.ts
18022
18862
  function isLocal(rule) {
@@ -18939,7 +19779,7 @@ function dispatchArmValue(node2, scope, code, mfs) {
18939
19779
  if (!keyArg || !parserArg || extraArg !== void 0 || keyArg.type === "SpreadElement" || parserArg.type === "SpreadElement") return null;
18940
19780
  const key = anyValue(keyArg, scope, code, mfs);
18941
19781
  const parserValue = anyValue(parserArg, scope, code, mfs);
18942
- if (!isCombinator2(parserValue)) return null;
19782
+ if (!isCombinator3(parserValue)) return null;
18943
19783
  const opts = { caseInsensitive: factory.caseInsensitive };
18944
19784
  if (typeof key === "string") return when(key, parserValue, opts);
18945
19785
  if (Array.isArray(key) && key.every((item) => typeof item === "string")) return when(key, parserValue, opts);
@@ -18950,7 +19790,7 @@ function dispatchArmValue(node2, scope, code, mfs) {
18950
19790
  const [parserArg] = node2.arguments;
18951
19791
  if (!parserArg || parserArg.type === "SpreadElement") return null;
18952
19792
  const parserValue = anyValue(parserArg, scope, code, mfs);
18953
- if (!isCombinator2(parserValue)) return null;
19793
+ if (!isCombinator3(parserValue)) return null;
18954
19794
  return otherwise(parserValue);
18955
19795
  }
18956
19796
  if (callee.name === "when") {
@@ -18960,24 +19800,24 @@ function dispatchArmValue(node2, scope, code, mfs) {
18960
19800
  const parserValue = anyValue(parserArg, scope, code, mfs);
18961
19801
  const opts = dispatchWhenOptions(optsArg === void 0 ? void 0 : anyValue(optsArg, scope, code, mfs));
18962
19802
  if (opts === null) return null;
18963
- if (!isCombinator2(parserValue)) return null;
19803
+ if (!isCombinator3(parserValue)) return null;
18964
19804
  if (typeof key === "string") return when(key, parserValue, opts);
18965
19805
  if (Array.isArray(key) && key.every((item) => typeof item === "string")) return when(key, parserValue, opts);
18966
19806
  if (isDispatchMatcher(key)) return when(key, parserValue, opts);
18967
19807
  }
18968
19808
  return null;
18969
19809
  }
18970
- function isCombinator2(v) {
19810
+ function isCombinator3(v) {
18971
19811
  return !!v && typeof v === "object" && "_def" in v;
18972
19812
  }
18973
19813
  function isDispatchArm(v) {
18974
19814
  if (!v || typeof v !== "object") return false;
18975
19815
  const rec = v;
18976
- if (rec.kind === "otherwise") return isCombinator2(rec.parser);
19816
+ if (rec.kind === "otherwise") return isCombinator3(rec.parser);
18977
19817
  if (rec.kind === "whenMatcher") {
18978
- return isDispatchMatcher(rec.matcher) && typeof rec.caseInsensitive === "boolean" && isCombinator2(rec.parser);
19818
+ return isDispatchMatcher(rec.matcher) && typeof rec.caseInsensitive === "boolean" && isCombinator3(rec.parser);
18979
19819
  }
18980
- return rec.kind === "when" && Array.isArray(rec.keys) && rec.keys.every((key) => typeof key === "string") && typeof rec.caseInsensitive === "boolean" && isCombinator2(rec.parser);
19820
+ return rec.kind === "when" && Array.isArray(rec.keys) && rec.keys.every((key) => typeof key === "string") && typeof rec.caseInsensitive === "boolean" && isCombinator3(rec.parser);
18981
19821
  }
18982
19822
  function isDispatchMatcher(v) {
18983
19823
  if (!v || typeof v !== "object") return false;
@@ -18992,7 +19832,7 @@ function scopeGet(scope, name, mfs) {
18992
19832
  if (mfs && entry.mfSrcs.length > 0) mfs.push(...entry.mfSrcs);
18993
19833
  return entry.combi;
18994
19834
  }
18995
- if (isCombinator2(entry)) return entry;
19835
+ if (isCombinator3(entry)) return entry;
18996
19836
  return null;
18997
19837
  }
18998
19838
  function unwrapStaticExpr(expr) {
@@ -19044,7 +19884,7 @@ function scopedStaticValue(expr, scope) {
19044
19884
  return { found: true, value };
19045
19885
  }
19046
19886
  function staticNodeOptionsFromValue(value) {
19047
- if (value === null || typeof value !== "object" || Array.isArray(value) || isCombinator2(value)) return STATIC_NODE_OPTIONS_NOT_OPTIONS;
19887
+ if (value === null || typeof value !== "object" || Array.isArray(value) || isCombinator3(value)) return STATIC_NODE_OPTIONS_NOT_OPTIONS;
19048
19888
  const opts = {};
19049
19889
  const rec = value;
19050
19890
  for (const name of Object.keys(rec)) {
@@ -19138,7 +19978,7 @@ function exprToCombi(node2, scope, code, mfs) {
19138
19978
  const [parserArg, fnArg] = node2.arguments;
19139
19979
  if (!parserArg || !fnArg || parserArg.type === "SpreadElement" || fnArg.type === "SpreadElement") return null;
19140
19980
  const inner = anyValue(parserArg, scope, code, mfs);
19141
- if (!isCombinator2(inner)) return null;
19981
+ if (!isCombinator3(inner)) return null;
19142
19982
  const fnSrc = stripTsFromSource(fnArg, code);
19143
19983
  mfs.push(fnSrc);
19144
19984
  try {
@@ -19153,7 +19993,7 @@ function exprToCombi(node2, scope, code, mfs) {
19153
19993
  const [parserArg, fnArg] = node2.arguments;
19154
19994
  if (!parserArg || !fnArg || parserArg.type === "SpreadElement" || fnArg.type === "SpreadElement") return null;
19155
19995
  const inner = anyValue(parserArg, scope, code, mfs);
19156
- if (!isCombinator2(inner)) return null;
19996
+ if (!isCombinator3(inner)) return null;
19157
19997
  const fnSrc = stripTsFromSource(fnArg, code);
19158
19998
  mfs.push(fnSrc);
19159
19999
  try {
@@ -19174,7 +20014,7 @@ function exprToCombi(node2, scope, code, mfs) {
19174
20014
  const optsArg = explicitType !== void 0 ? fourthArg : thirdArg;
19175
20015
  if (!parserArg || parserArg.type === "SpreadElement") return null;
19176
20016
  const inner = anyValue(parserArg, scope, code, mfs);
19177
- if (!isCombinator2(inner)) return null;
20017
+ if (!isCombinator3(inner)) return null;
19178
20018
  const be = buildArg;
19179
20019
  const buildExpr = be === void 0 || be.type === "SpreadElement" ? void 0 : unwrapStaticExpr(be);
19180
20020
  const buildArgOptions = be !== void 0 && be.type !== "SpreadElement" ? staticNodeOptions(buildArg, scope) : STATIC_NODE_OPTIONS_NOT_OPTIONS;
@@ -19248,7 +20088,7 @@ function exprToCombi(node2, scope, code, mfs) {
19248
20088
  const opts = anyValue(optsArg, scope, code, []);
19249
20089
  if (!opts || typeof opts !== "object") return null;
19250
20090
  const root = anyValue(rootArg, scope, code, mfs);
19251
- if (!isCombinator2(root)) return null;
20091
+ if (!isCombinator3(root)) return null;
19252
20092
  try {
19253
20093
  return parser(opts, root);
19254
20094
  } catch {
@@ -19260,10 +20100,10 @@ function exprToCombi(node2, scope, code, mfs) {
19260
20100
  if (!itemArg || !sepArg || itemArg.type === "SpreadElement" || sepArg.type === "SpreadElement") return null;
19261
20101
  const itemMfs = [];
19262
20102
  const itemCombi = anyValue(itemArg, scope, code, itemMfs);
19263
- if (!isCombinator2(itemCombi)) return null;
20103
+ if (!isCombinator3(itemCombi)) return null;
19264
20104
  const sepMfs = [];
19265
20105
  const sepCombi = anyValue(sepArg, scope, code, sepMfs);
19266
- if (!isCombinator2(sepCombi)) return null;
20106
+ if (!isCombinator3(sepCombi)) return null;
19267
20107
  let opts;
19268
20108
  if (optsArg) {
19269
20109
  if (optsArg.type === "SpreadElement") return null;
@@ -19283,7 +20123,7 @@ function exprToCombi(node2, scope, code, mfs) {
19283
20123
  if (!itemArg || itemArg.type === "SpreadElement") return null;
19284
20124
  const itemMfs = [];
19285
20125
  const itemCombi = anyValue(itemArg, scope, code, itemMfs);
19286
- if (!isCombinator2(itemCombi)) return null;
20126
+ if (!isCombinator3(itemCombi)) return null;
19287
20127
  let opts;
19288
20128
  if (optsArg) {
19289
20129
  if (optsArg.type === "SpreadElement") return null;
@@ -19305,7 +20145,7 @@ function exprToCombi(node2, scope, code, mfs) {
19305
20145
  const [innerArg] = node2.arguments;
19306
20146
  if (!innerArg || innerArg.type === "SpreadElement") return null;
19307
20147
  const inner = anyValue(innerArg, scope, code, mfs);
19308
- if (!isCombinator2(inner)) return null;
20148
+ if (!isCombinator3(inner)) return null;
19309
20149
  try {
19310
20150
  return not(inner);
19311
20151
  } catch {
@@ -19316,7 +20156,7 @@ function exprToCombi(node2, scope, code, mfs) {
19316
20156
  const [innerArg] = node2.arguments;
19317
20157
  if (!innerArg || innerArg.type === "SpreadElement") return null;
19318
20158
  const inner = anyValue(innerArg, scope, code, mfs);
19319
- if (!isCombinator2(inner)) return null;
20159
+ if (!isCombinator3(inner)) return null;
19320
20160
  try {
19321
20161
  return peek(inner);
19322
20162
  } catch {
@@ -19341,7 +20181,7 @@ function exprToCombi(node2, scope, code, mfs) {
19341
20181
  const [sentinelArg, optsArg] = node2.arguments;
19342
20182
  if (!sentinelArg || sentinelArg.type === "SpreadElement") return null;
19343
20183
  const sentinel = anyValue(sentinelArg, scope, code, []);
19344
- if (!isCombinator2(sentinel)) return null;
20184
+ if (!isCombinator3(sentinel)) return null;
19345
20185
  const opts = scanOptions(optsArg, scope, code);
19346
20186
  if (opts === UNKNOWN_OPTIONS) return null;
19347
20187
  try {
@@ -19372,7 +20212,7 @@ function exprToCombi(node2, scope, code, mfs) {
19372
20212
  const extraSrc = stripTsFromSource(extraArg, code);
19373
20213
  mfs.push(extraSrc);
19374
20214
  const inner = anyValue(innerArg, scope, code, mfs);
19375
- if (!isCombinator2(inner)) return null;
20215
+ if (!isCombinator3(inner)) return null;
19376
20216
  try {
19377
20217
  const extraType = unwrapStaticExpr(extraArg).type;
19378
20218
  const derives = extraType === "ArrowFunctionExpression" || extraType === "FunctionExpression";
@@ -19390,7 +20230,7 @@ function exprToCombi(node2, scope, code, mfs) {
19390
20230
  const [selectorArg, ...armArgs] = node2.arguments;
19391
20231
  if (!selectorArg || selectorArg.type === "SpreadElement") return null;
19392
20232
  const selector = anyValue(selectorArg, scope, code, mfs);
19393
- if (!isCombinator2(selector)) return null;
20233
+ if (!isCombinator3(selector)) return null;
19394
20234
  const arms = [];
19395
20235
  for (const arg of armArgs) {
19396
20236
  if (arg.type === "SpreadElement") return null;
@@ -19417,12 +20257,12 @@ function exprToCombi(node2, scope, code, mfs) {
19417
20257
  const gateSrc = stripTsFromSource(parts.gate, code);
19418
20258
  mfs.push(gateSrc);
19419
20259
  const combi = anyValue(parts.combinator, scope, code, mfs);
19420
- if (!isCombinator2(combi)) return null;
20260
+ if (!isCombinator3(combi)) return null;
19421
20261
  arms.push({ gate: () => true, combinator: combi });
19422
20262
  gateSrcs.push(gateSrc);
19423
20263
  } else {
19424
20264
  const combi = anyValue(argNode, scope, code, mfs);
19425
- if (!isCombinator2(combi)) return null;
20265
+ if (!isCombinator3(combi)) return null;
19426
20266
  arms.push(combi);
19427
20267
  gateSrcs.push(null);
19428
20268
  }
@@ -19570,7 +20410,7 @@ function evaluateExpr(node2, scope, code, mapFnSources) {
19570
20410
  function evaluateCombinatorArray(node2, scope, code) {
19571
20411
  const val = anyValue(node2, scope, code, []);
19572
20412
  if (!Array.isArray(val) || val.length === 0) return null;
19573
- if (!val.every(isCombinator2)) return null;
20413
+ if (!val.every(isCombinator3)) return null;
19574
20414
  return val;
19575
20415
  }
19576
20416
  function collectRuleKeys(retObj) {
@@ -19648,7 +20488,7 @@ function evalBodyStatements(statements, scope, code, out) {
19648
20488
  return false;
19649
20489
  }
19650
20490
  const thisDeclMfSrcs = bodyMfs.slice(before);
19651
- if (isCombinator2(val)) scope.set(name, { combi: val, mfSrcs: thisDeclMfSrcs });
20491
+ if (isCombinator3(val)) scope.set(name, { combi: val, mfSrcs: thisDeclMfSrcs });
19652
20492
  else if (isDispatchArm(val)) scope.set(name, { value: val, mfSrcs: thisDeclMfSrcs });
19653
20493
  else scope.set(name, val);
19654
20494
  }
@@ -19703,7 +20543,7 @@ function evaluateParserFactory(factoryNode, scope, code, mapFnSources, out, opti
19703
20543
  const definitions = {};
19704
20544
  for (const [key, e] of finalByKey) {
19705
20545
  const val = anyValue(e.value, e.scope, e.code, mapFnSources);
19706
- if (!isCombinator2(val)) throw ABORT;
20546
+ if (!isCombinator3(val)) throw ABORT;
19707
20547
  definitions[key] = val;
19708
20548
  }
19709
20549
  return definitions;
@@ -19718,7 +20558,7 @@ function evaluateParserFactory(factoryNode, scope, code, mapFnSources, out, opti
19718
20558
  return map;
19719
20559
  }
19720
20560
  function isDefinableRef2(v) {
19721
- return isCombinator2(v) && typeof v.define === "function" && v._def.tag === "lazy";
20561
+ return isCombinator3(v) && typeof v.define === "function" && v._def.tag === "lazy";
19722
20562
  }
19723
20563
  function evaluateRefDeclaration(init, name, scope) {
19724
20564
  if (init.type !== "CallExpression") return null;
@@ -19738,12 +20578,12 @@ function applyDefineStatement(callExpr, scope, code) {
19738
20578
  if (mem.property.type !== "Identifier" || mem.property.name !== "define") return false;
19739
20579
  if (mem.object.type !== "Identifier" || !mem.object.name) return false;
19740
20580
  const target = scope.get(mem.object.name);
19741
- const refCombi = isScopeEntry(target) ? target.combi : isCombinator2(target) ? target : null;
20581
+ const refCombi = isScopeEntry(target) ? target.combi : isCombinator3(target) ? target : null;
19742
20582
  if (!refCombi || !isDefinableRef2(refCombi)) return false;
19743
20583
  const args = callExpr.arguments;
19744
20584
  if (args.length !== 1 || args[0].type === "SpreadElement") return false;
19745
20585
  const inner = anyValue(args[0], scope, code, []);
19746
- if (!isCombinator2(inner)) return false;
20586
+ if (!isCombinator3(inner)) return false;
19747
20587
  try {
19748
20588
  refCombi.define(inner);
19749
20589
  } catch {
@@ -21012,6 +21852,28 @@ function evalIR(ir, rulesImpl) {
21012
21852
  // src/plugin/index.ts
21013
21853
  import { createHash } from "node:crypto";
21014
21854
  var TABLE_RUNTIME_SPECIFIER = "parseman/table";
21855
+ var CARRIED_SIDECAR_SUFFIX = ".parseman.json";
21856
+ var _sidecarCache = /* @__PURE__ */ new Map();
21857
+ function readCarriedSidecar(artifact) {
21858
+ const file = artifact + CARRIED_SIDECAR_SUFFIX;
21859
+ let mtimeMs;
21860
+ try {
21861
+ mtimeMs = fs2.statSync(file).mtimeMs;
21862
+ } catch {
21863
+ return null;
21864
+ }
21865
+ const hit = _sidecarCache.get(file);
21866
+ if (hit && hit.mtimeMs === mtimeMs) return hit.sidecar;
21867
+ let sidecar = null;
21868
+ try {
21869
+ const parsed = JSON.parse(fs2.readFileSync(file, "utf8"));
21870
+ const exports = typeof parsed === "object" && parsed !== null ? parsed.exports : void 0;
21871
+ if (typeof exports === "object" && exports !== null) sidecar = parsed;
21872
+ } catch {
21873
+ }
21874
+ _sidecarCache.set(file, { mtimeMs, sidecar });
21875
+ return sidecar;
21876
+ }
21015
21877
  var corpusCache = /* @__PURE__ */ new Map();
21016
21878
  function corpusTexts(profile) {
21017
21879
  return profile.files.map((file) => {
@@ -21130,31 +21992,101 @@ function parseModuleCached(filePath) {
21130
21992
  _moduleParseCache.set(filePath, { mtimeMs, parsed });
21131
21993
  return parsed;
21132
21994
  }
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
- }));
21995
+ function reexportSource(body, exported) {
21996
+ for (const st of body) {
21997
+ if (st.type !== "ExportNamedDeclaration") continue;
21998
+ for (const sp of st.specifiers ?? []) {
21999
+ const exp = sp.exported;
22000
+ if ((exp?.name ?? exp?.value) !== exported) continue;
22001
+ const local = sp.local;
22002
+ const name = local?.name ?? local?.value;
22003
+ if (name === void 0) return null;
22004
+ const from = st.source?.value;
22005
+ return from !== void 0 ? { source: from, imported: name } : extractImportBindings(body).get(name) ?? null;
22006
+ }
22007
+ }
22008
+ return null;
22009
+ }
22010
+ async function followCarried(sinks, moduleId, name) {
22011
+ for (let hop = 0; hop < 64; hop++) {
22012
+ const own = sinks.get(moduleId)?.get(name);
22013
+ if (own !== void 0) return own;
22014
+ const code = this.getModuleInfo(moduleId)?.code;
22015
+ if (!code) return void 0;
22016
+ const parsed = parseSync5(moduleId, code);
22017
+ if (parsed.errors.length > 0) return void 0;
22018
+ const next = reexportSource(parsed.program.body, name);
22019
+ if (next === null) return void 0;
22020
+ const resolved = await this.resolve(next.source, moduleId);
22021
+ if (resolved === null || resolved.external) return void 0;
22022
+ moduleId = resolved.id;
22023
+ name = next.imported;
22024
+ }
22025
+ return void 0;
22026
+ }
22027
+ async function emitCarriedSidecars(sinks, bundle) {
22028
+ const recorders = /* @__PURE__ */ new Map();
22029
+ for (const [moduleId, sink] of sinks) for (const name of sink.keys()) (recorders.get(name) ?? recorders.set(name, []).get(name)).push(moduleId);
22030
+ for (const chunk of Object.values(bundle)) {
22031
+ if (chunk.type !== "chunk") continue;
22032
+ const exports = {};
22033
+ for (const name of chunk.exports ?? []) {
22034
+ const followed = chunk.facadeModuleId ? await followCarried.call(this, sinks, chunk.facadeModuleId, name) : void 0;
22035
+ if (followed !== void 0) {
22036
+ exports[name] = followed;
22037
+ continue;
22038
+ }
22039
+ const ids = recorders.get(name);
22040
+ if (ids === void 0) continue;
22041
+ const own = ids.filter((m) => chunk.moduleIds?.includes(m));
22042
+ const moduleId = own.length === 1 ? own[0] : own.length === 0 && ids.length === 1 ? ids[0] : void 0;
22043
+ if (moduleId !== void 0) exports[name] = sinks.get(moduleId).get(name);
22044
+ }
22045
+ if (Object.keys(exports).length === 0) continue;
22046
+ const sidecar = { parseman: PARSEMAN_VERSION, exports };
22047
+ this.emitFile({ type: "asset", fileName: chunk.fileName + CARRIED_SIDECAR_SUFFIX, source: JSON.stringify(sidecar) });
22048
+ }
22049
+ }
22050
+ var SIDECAR_FRAMEWORKS = /* @__PURE__ */ new Set(["rollup", "rolldown", "vite"]);
22051
+ var plugin_default = createUnplugin((opts = {}, meta) => {
22052
+ const sinks = SIDECAR_FRAMEWORKS.has(meta.framework) ? /* @__PURE__ */ new Map() : void 0;
22053
+ const generateBundle = sinks === void 0 ? void 0 : {
22054
+ generateBundle(_options, bundle) {
22055
+ return emitCarriedSidecars.call(this, sinks, bundle);
22056
+ }
22057
+ };
22058
+ return {
22059
+ name: "parseman",
22060
+ ...generateBundle === void 0 ? {} : { rollup: generateBundle, rolldown: generateBundle, vite: generateBundle },
22061
+ // Run BEFORE the bundler's TS/JS transform — otherwise esbuild (Vite) strips
22062
+ // the `with { type: 'macro' }` import attribute before we ever see it, and the
22063
+ // macro silently never fires.
22064
+ enforce: "pre",
22065
+ transformInclude(id) {
22066
+ return /\.[jt]sx?$/.test(id) && !id.includes("node_modules");
22067
+ },
22068
+ transform(code, id) {
22069
+ if (!code.includes("parseman")) return null;
22070
+ if (!code.includes("macro")) return null;
22071
+ for (const file of opts.assemblyProfile?.files ?? []) this?.addWatchFile?.(file);
22072
+ const moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE, ...opts.moduleAliases ?? []]);
22073
+ const sink = sinks && /* @__PURE__ */ new Map();
22074
+ const result = transformMacro(code, id, moduleAliases, opts.warnUnloweredRegex === true, opts.recovery === true, opts.grammarCoverage === true, opts.assemblyProfile, opts.assemblyBudget, sink);
22075
+ if (sinks && sink) {
22076
+ if (sink.size > 0) sinks.set(id, sink);
22077
+ else sinks.delete(id);
22078
+ }
22079
+ if (result?.warnings.length) {
22080
+ for (const w of result.warnings) {
22081
+ if (typeof this?.warn === "function") this.warn(`[parseman] ${w}`);
22082
+ else console.warn(`[parseman] ${w}`);
22083
+ }
22084
+ }
22085
+ if (!result) return null;
22086
+ return { code: result.code, map: result.map };
22087
+ }
22088
+ };
22089
+ });
21158
22090
  function exportLocalName(body, exported) {
21159
22091
  for (const st of body) {
21160
22092
  if (st.type !== "ExportNamedDeclaration") continue;
@@ -21300,17 +22232,17 @@ function lowerPrivateSourceModule(file, moduleAliases, warnUnloweredRegex, recov
21300
22232
  _sourceLowering.delete(file);
21301
22233
  }
21302
22234
  }
21303
- function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE]), warnUnloweredRegex = false, recovery = false, grammarCoverage = false, assemblyProfile, assemblyBudget = DEFAULT_ASSEMBLY_BUDGET) {
22235
+ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE]), warnUnloweredRegex = false, recovery = false, grammarCoverage = false, assemblyProfile, assemblyBudget = DEFAULT_ASSEMBLY_BUDGET, carriedSink) {
21304
22236
  const depth = degradationCaptureDepth();
21305
22237
  try {
21306
- return transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recovery, grammarCoverage, assemblyProfile, assemblyBudget);
22238
+ return transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recovery, grammarCoverage, assemblyProfile, assemblyBudget, carriedSink);
21307
22239
  } finally {
21308
22240
  setReducerResolver(null);
21309
22241
  setBuilderImportResolver(null);
21310
22242
  for (const d of unwindDegradationCapture(depth)) console.warn(formatDegradation(d));
21311
22243
  }
21312
22244
  }
21313
- function transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recovery, grammarCoverage, assemblyProfile, assemblyBudgetShare) {
22245
+ function transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recovery, grammarCoverage, assemblyProfile, assemblyBudgetShare, carriedSink) {
21314
22246
  let result;
21315
22247
  try {
21316
22248
  result = parseSync5(id, code);
@@ -21913,17 +22845,36 @@ ${names.map((n) => ` - ${n}`).join("\n")}` : " (it is not a static combinator/v
21913
22845
  const importedPiecesCache = /* @__PURE__ */ new Map();
21914
22846
  const resolveModulePieces = (module, exportName, seen, unresolved, local = false) => {
21915
22847
  const { file } = module;
22848
+ const fail = (why) => {
22849
+ unresolved.why ??= `${exportName} in ${file}: ${why}`;
22850
+ return null;
22851
+ };
22852
+ const sidecarItems = module.source || local ? void 0 : readCarriedSidecar(file)?.exports[exportName];
22853
+ if (sidecarItems !== void 0) {
22854
+ const list = [];
22855
+ for (const item of sidecarItems) {
22856
+ if ("ir" in item) {
22857
+ list.push(item);
22858
+ continue;
22859
+ }
22860
+ const sub = resolveGrammarModule(file, item.from);
22861
+ if (sub === null) return fail(`its carried pieces name \`${item.name}\` from '${item.from}', a module that could not be found`);
22862
+ if (seen.has(sub.file)) continue;
22863
+ const pieces = resolveModulePieces(sub, item.name, new Set(seen).add(sub.file), unresolved);
22864
+ if (pieces === null) return fail(`its carried pieces name \`${item.name}\` from '${item.from}', which could not be resolved`);
22865
+ list.push(...pieces);
22866
+ }
22867
+ return list;
22868
+ }
21916
22869
  const mod = module.source ? lowerPrivateSourceModule(file, moduleAliases, warnUnloweredRegex, recovery) : parseModuleCached(file);
21917
22870
  if (!mod) return null;
21918
22871
  const localFor = local ? exportName : exportLocalName(mod.body, exportName);
21919
22872
  const initNode = localFor ? topLevelInit(mod.body, localFor) : null;
21920
22873
  const literalRange = initNode ? findCarriedPiecesLiteral(initNode) : null;
21921
- if (!literalRange) return null;
22874
+ if (!literalRange) {
22875
+ 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;
22876
+ }
21922
22877
  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
22878
  const imports = extractImportBindings(mod.body);
21928
22879
  const stubNames = [];
21929
22880
  const stubVals = [];
@@ -21972,6 +22923,27 @@ ${names.map((n) => ` - ${n}`).join("\n")}` : " (it is not a static combinator/v
21972
22923
  importedPiecesCache.set(localName, result2);
21973
22924
  return result2;
21974
22925
  };
22926
+ const sinkCarried = (name, list) => {
22927
+ if (carriedSink === void 0) return false;
22928
+ const out = [];
22929
+ for (const it of list) {
22930
+ if (!isSpread(it)) {
22931
+ out.push(it);
22932
+ continue;
22933
+ }
22934
+ const b = importBindings.get(it.__spreadLocal);
22935
+ if (b === void 0) return false;
22936
+ if (!b.source.startsWith(".") && !path2.isAbsolute(b.source)) {
22937
+ out.push({ from: b.source, name: b.imported });
22938
+ continue;
22939
+ }
22940
+ const pieces = importedPieces(it.__spreadLocal);
22941
+ if (pieces === null) return false;
22942
+ out.push(...pieces);
22943
+ }
22944
+ carriedSink.set(name, out);
22945
+ return true;
22946
+ };
21975
22947
  const carriedRuleMaps = (items) => {
21976
22948
  const pieces = [];
21977
22949
  let trackLines = false;
@@ -22391,6 +23363,7 @@ ${names.map((n) => ` - ${n}`).join("\n")}` : " (it is not a static combinator/v
22391
23363
  const ir = serializeRuleMap([...compiledRules.ruleMap], compiledRules.scanSkip);
22392
23364
  if (ir) carriedMetadata = [{ ns, ir, ...compiledRules.trackLines ? { trackLines: true } : {} }];
22393
23365
  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.`);
23366
+ if (carriedMetadata !== void 0 && sinkCarried(varName, carriedMetadata)) carriedMetadata = void 0;
22394
23367
  }
22395
23368
  const replacement = compiledRules.replacement !== null ? compiledRules.replacementWithMetadata(staticTableMetadataSource({
22396
23369
  ...carriedMetadata === void 0 ? {} : { carried: carriedMetadata },
@@ -22415,7 +23388,7 @@ ${names.map((n) => ` - ${n}`).join("\n")}` : " (it is not a static combinator/v
22415
23388
  continue;
22416
23389
  }
22417
23390
  localComposedCarried.set(varName, fused.carried);
22418
- const replacement = exportPrefix ? fused.exportedReplacement : fused.replacement;
23391
+ const replacement = exportPrefix && !sinkCarried(varName, fused.carried) ? fused.exportedReplacement : fused.replacement;
22419
23392
  replacements.push({ start: init.start, end: init.end, replacement });
22420
23393
  markUsedImportedFactories(fused.importedFactories);
22421
23394
  continue;
@@ -22705,6 +23678,7 @@ ${lines2.join("\n")}`);
22705
23678
  };
22706
23679
  }
22707
23680
  export {
23681
+ CARRIED_SIDECAR_SUFFIX,
22708
23682
  plugin_default as default,
22709
23683
  transformMacro
22710
23684
  };