parseman 0.56.0 → 0.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/dist/analysis/diagnostics.js +2232 -1088
  2. package/dist/analysis/diagnostics.js.map +3 -3
  3. package/dist/cli/index.js +2247 -1103
  4. package/dist/cli/index.js.map +3 -3
  5. package/dist/combinators/dispatch.d.ts.map +1 -1
  6. package/dist/combinators/node.d.ts +1 -1
  7. package/dist/compiler/build-arity.d.ts +1 -1
  8. package/dist/compiler/build-arity.d.ts.map +1 -1
  9. package/dist/compiler/token-alphabet.d.ts +11 -1
  10. package/dist/compiler/token-alphabet.d.ts.map +1 -1
  11. package/dist/compiler/token-capability.js +69 -16
  12. package/dist/compiler/token-capability.js.map +2 -2
  13. package/dist/cst/capture-buffer.d.ts +6 -0
  14. package/dist/cst/capture-buffer.d.ts.map +1 -1
  15. package/dist/cst/trivia-kinds.d.ts +9 -1
  16. package/dist/cst/trivia-kinds.d.ts.map +1 -1
  17. package/dist/index.js +1446 -236
  18. package/dist/index.js.map +3 -3
  19. package/dist/language-service/index.js +1 -0
  20. package/dist/language-service/index.js.map +1 -1
  21. package/dist/parse-context.d.ts.map +1 -1
  22. package/dist/plugin/entry-supercompiler.d.ts +1 -1
  23. package/dist/plugin/entry-supercompiler.d.ts.map +1 -1
  24. package/dist/plugin/index.d.ts +51 -1
  25. package/dist/plugin/index.d.ts.map +1 -1
  26. package/dist/plugin/index.js +2126 -380
  27. package/dist/plugin/index.js.map +3 -3
  28. package/dist/plugin/ir-eval.d.ts +2 -0
  29. package/dist/plugin/ir-eval.d.ts.map +1 -1
  30. package/dist/regex/classes.d.ts.map +1 -1
  31. package/dist/run/index.js +1 -0
  32. package/dist/run/index.js.map +1 -1
  33. package/dist/table/assemble.d.ts +9 -0
  34. package/dist/table/assemble.d.ts.map +1 -1
  35. package/dist/table/child-slots.d.ts +4 -6
  36. package/dist/table/child-slots.d.ts.map +1 -1
  37. package/dist/table/compile-rule-map.d.ts +14 -2
  38. package/dist/table/compile-rule-map.d.ts.map +1 -1
  39. package/dist/table/emit-assembly.d.ts +17 -2
  40. package/dist/table/emit-assembly.d.ts.map +1 -1
  41. package/dist/table/emit.d.ts +5 -1
  42. package/dist/table/emit.d.ts.map +1 -1
  43. package/dist/table/encode.d.ts.map +1 -1
  44. package/dist/table/exec-baseline.d.ts.map +1 -1
  45. package/dist/table/exec.d.ts.map +1 -1
  46. package/dist/table/factor-choice.d.ts +42 -0
  47. package/dist/table/factor-choice.d.ts.map +1 -0
  48. package/dist/table/fail-clean.d.ts +3 -0
  49. package/dist/table/fail-clean.d.ts.map +1 -0
  50. package/dist/table/hold-gap.d.ts +8 -0
  51. package/dist/table/hold-gap.d.ts.map +1 -0
  52. package/dist/table/index.js +1798 -316
  53. package/dist/table/index.js.map +3 -3
  54. package/dist/table/lex-program.d.ts +7 -3
  55. package/dist/table/lex-program.d.ts.map +1 -1
  56. package/dist/table/ops.d.ts +17 -6
  57. package/dist/table/ops.d.ts.map +1 -1
  58. package/dist/table/program.d.ts +13 -0
  59. package/dist/table/program.d.ts.map +1 -1
  60. package/dist/table/run-support.d.ts +19 -0
  61. package/dist/table/run-support.d.ts.map +1 -1
  62. package/dist/table/scalar-terminal.d.ts +2 -0
  63. package/dist/table/scalar-terminal.d.ts.map +1 -1
  64. package/dist/table/select-hot.d.ts +6 -0
  65. package/dist/table/select-hot.d.ts.map +1 -0
  66. package/dist/table/site-labels.d.ts +66 -0
  67. package/dist/table/site-labels.d.ts.map +1 -1
  68. package/dist/table/trivia-gap.d.ts +31 -0
  69. package/dist/table/trivia-gap.d.ts.map +1 -0
  70. package/dist/types.d.ts +17 -0
  71. package/dist/types.d.ts.map +1 -1
  72. package/dist/version.d.ts +1 -1
  73. package/package.json +4 -1
  74. package/src/combinators/dispatch.ts +12 -3
  75. package/src/combinators/node.ts +6 -13
  76. package/src/combinators/trivia-skip.ts +44 -1
  77. package/src/compiler/build-arity.ts +3 -3
  78. package/src/compiler/token-alphabet.ts +57 -17
  79. package/src/cst/capture-buffer.ts +25 -0
  80. package/src/cst/trivia-kinds.ts +12 -1
  81. package/src/parse-context.ts +1 -0
  82. package/src/plugin/entry-supercompiler.ts +8 -9
  83. package/src/plugin/index.ts +362 -42
  84. package/src/plugin/ir-eval.ts +7 -1
  85. package/src/regex/classes.ts +3 -0
  86. package/src/table/assemble.ts +371 -83
  87. package/src/table/child-slots.ts +6 -8
  88. package/src/table/compile-rule-map.ts +64 -15
  89. package/src/table/emit-assembly.ts +244 -42
  90. package/src/table/emit.ts +11 -8
  91. package/src/table/encode.ts +149 -35
  92. package/src/table/exec-baseline.ts +1 -3
  93. package/src/table/exec.ts +34 -14
  94. package/src/table/factor-choice.ts +173 -0
  95. package/src/table/fail-clean.ts +130 -0
  96. package/src/table/hold-gap.ts +68 -0
  97. package/src/table/lex-program.ts +197 -43
  98. package/src/table/ops.ts +18 -7
  99. package/src/table/program.ts +24 -0
  100. package/src/table/run-support.ts +35 -0
  101. package/src/table/scalar-terminal.ts +8 -0
  102. package/src/table/select-hot.ts +70 -0
  103. package/src/table/site-labels.ts +135 -4
  104. package/src/table/trivia-gap.ts +109 -0
  105. package/src/types.ts +18 -0
  106. package/src/version.ts +1 -1
@@ -366,12 +366,12 @@ function scalarRootOf(combinator) {
366
366
  }
367
367
 
368
368
  // src/combinators/ref.ts
369
- function withRuleTrivia(trivia2, ctx, run) {
369
+ function withRuleTrivia(trivia2, ctx, run2) {
370
370
  const savedLabels = ctx.triviaKindLabels;
371
371
  ctx.trivia = trivia2;
372
372
  ctx.triviaKindLabels = trivia2._meta.triviaKindLabels;
373
373
  try {
374
- return run();
374
+ return run2();
375
375
  } finally {
376
376
  ctx.trivia = void 0;
377
377
  ctx.triviaKindLabels = savedLabels;
@@ -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) {
@@ -816,6 +841,7 @@ function createParseContext() {
816
841
  _rootTriviaKindIndex: void 0,
817
842
  _rootTriviaStrictScopes: void 0,
818
843
  _rootTriviaCapture: void 0,
844
+ _gap: void 0,
819
845
  _cstTriviaLog: void 0,
820
846
  _fields: void 0,
821
847
  _cstBuf: void 0,
@@ -869,6 +895,7 @@ function literalCodePoints(frag) {
869
895
  if (ch2 === "\\") {
870
896
  const e = frag[i + 1];
871
897
  if (e === void 0) return null;
898
+ if (!(e in CLASS_ESCAPES) && /\w/.test(e)) return null;
872
899
  out.push(e in CLASS_ESCAPES ? CLASS_ESCAPES[e] : e.codePointAt(0));
873
900
  i += 2;
874
901
  continue;
@@ -1415,7 +1442,10 @@ function labeledTriviaSpec(arms, minRepeats) {
1415
1442
  arms,
1416
1443
  minRepeats,
1417
1444
  visitor: commonLabeledTriviaVisitor({ arms, minRepeats }),
1418
- charArms: charArmsFor({ arms, minRepeats })
1445
+ charArms: charArmsFor({ arms, minRepeats }),
1446
+ rootKinds: void 0,
1447
+ rootLeaders: [],
1448
+ rootScan: null
1419
1449
  };
1420
1450
  }
1421
1451
  function matchArmAt(input, pos, arm, state) {
@@ -2831,8 +2861,50 @@ function loopScanner(arms) {
2831
2861
  function regexTriviaScanner(parser2) {
2832
2862
  const d = parser2._def.tag === "label" ? parser2._def.parser._def : parser2._def;
2833
2863
  if (d.tag !== "regex" || d.flags) return null;
2834
- const source = d.source;
2835
- return classRunSource(source) ?? altStarSource(source) ?? prefixRunSource(source) ?? delimitedSource(source);
2864
+ return sourceScanner(d.source);
2865
+ }
2866
+ function sourceScanner(source) {
2867
+ return classRunSource(source) ?? altStarSource(source) ?? prefixRunSource(source) ?? delimitedSource(source) ?? sharedPrefixAltSource(source);
2868
+ }
2869
+ function sharedPrefixAltSource(source) {
2870
+ const m = /^((?:\\.|[^\\[\]()*+?|^$.{}])+)\(\?:(.*)\)$/.exec(source);
2871
+ if (!m) return null;
2872
+ const alts = [];
2873
+ const body = m[2];
2874
+ let depth = 0;
2875
+ let start = 0;
2876
+ for (let i = 0; i < body.length; i++) {
2877
+ const c = body[i];
2878
+ if (c === "\\") {
2879
+ i++;
2880
+ continue;
2881
+ }
2882
+ if (c === "[") {
2883
+ while (i < body.length && body[i] !== "]") i += body[i] === "\\" ? 2 : 1;
2884
+ continue;
2885
+ }
2886
+ if (c === "(") depth++;
2887
+ else if (c === ")" && --depth < 0) return null;
2888
+ else if (c === "|" && depth === 0) {
2889
+ alts.push(body.slice(start, i));
2890
+ start = i + 1;
2891
+ }
2892
+ }
2893
+ if (depth !== 0 || alts.length === 0) return null;
2894
+ alts.push(body.slice(start));
2895
+ const scanners = [];
2896
+ for (const alt of alts) {
2897
+ const scanner = sourceScanner(m[1] + alt);
2898
+ if (scanner === null) return null;
2899
+ scanners.push(scanner);
2900
+ }
2901
+ return (input, cur) => {
2902
+ for (const scanner of scanners) {
2903
+ const end = scanner(input, cur);
2904
+ if (end > cur) return end;
2905
+ }
2906
+ return cur;
2907
+ };
2836
2908
  }
2837
2909
  function bmpString(cps) {
2838
2910
  if (!cps) return null;
@@ -3185,6 +3257,7 @@ function matchesAt(sentinel, input, pos, ctx) {
3185
3257
  function captureError(ctx, error) {
3186
3258
  if (cstCaptureActive(ctx)) pushCstChild(ctx, error, error);
3187
3259
  }
3260
+ var REC = { scan: recoverScan, at: matchesAt, or: orSentinel, sentinel: firstSetSentinel, capture: captureError };
3188
3261
 
3189
3262
  // src/combinators/adjacency.ts
3190
3263
  function adjacencyOf(p) {
@@ -3891,10 +3964,16 @@ function branchUsesRouted(branch) {
3891
3964
  return branch.usesRouted === true || parserUsesRouted(branch.parser);
3892
3965
  }
3893
3966
  function asciiFoldKey(key) {
3894
- let out = "";
3895
- for (let i = 0; i < key.length; i++) {
3967
+ let i = 0;
3968
+ for (; i < key.length; i++) {
3969
+ const c = key.charCodeAt(i);
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++) {
3896
3975
  const c = key.charCodeAt(i);
3897
- out += String.fromCharCode(c >= 65 && c <= 90 ? c + 32 : c);
3976
+ out += c >= 65 && c <= 90 ? String.fromCharCode(c + 32) : key[i];
3898
3977
  }
3899
3978
  return out;
3900
3979
  }
@@ -4821,7 +4900,7 @@ function confirmedArityForDef(def) {
4821
4900
  severity: "warn",
4822
4901
  where: `node("${def.type ?? "<inferred>"}")`,
4823
4902
  subject,
4824
- fellBackTo: `could not confirm its declared arity \u2014 ${unconfirmableReason(def, src)} \u2014 so this node captures children, fields and raw children, logs trivia, and clones \`_ctx.state\` on every match`,
4903
+ fellBackTo: `could not confirm its declared arity \u2014 ${unconfirmableReason(def, src)} \u2014 so this node captures children, fields and raw children, logs trivia, and hands it \`_ctx.state\` on every match`,
4825
4904
  otherwise: "only the tiers the reducer actually declares would be captured (arity >= 1 children, >= 2 fields, >= 4 raw, >= 5 trivia, >= 6 state). Declare it with `node(..., { buildArity: n })` if it cannot be derived"
4826
4905
  });
4827
4906
  return null;
@@ -4978,7 +5057,7 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
4978
5057
  }
4979
5058
  const def = unwrap || collapse || project !== void 0 || captureTrivia || trailingTrivia || buildArity !== void 0 || tags !== void 0 && tags.length > 0 ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {}, ...project !== void 0 ? { project } : {}, ...captureTrivia ? { captureTrivia: true } : {}, ...trailingTrivia ? { trailingTrivia: true } : {}, ...buildArity !== void 0 ? { buildArity } : {}, ...tags !== void 0 && tags.length > 0 ? { tags } : {} } : baseDef;
4980
5059
  const capturesTrivia = captureTrivia || (build ? buildReadsTrivia(def) : project === void 0);
4981
- const clonesState = build ? buildReadsState(def) : project === void 0;
5060
+ const readsState = build ? buildReadsState(def) : project === void 0;
4982
5061
  const hasOwnFields = parserHasOwnFields(combinator);
4983
5062
  const capturesFields = hasOwnFields && (build ? buildReadsFields(def) : project === void 0);
4984
5063
  const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
@@ -5019,12 +5098,11 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
5019
5098
  ctx._triviaCaptureMask = savedMask;
5020
5099
  const { children: children3, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
5021
5100
  if (!r.ok) return r;
5022
- const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
5101
+ const st = readsState ? ctx.state : void 0;
5023
5102
  const nodeType = def.type ?? missingInferredType();
5024
5103
  const cstOutput = cstOutputHost(ctx.build);
5025
5104
  const span = ctx.trackLines ? annotateSpanFromLineContext(r.span, ctx) : r.span;
5026
- const hostState = clonesState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
5027
- const built = unwrap && children3.length === 1 ? unwrapChild(children3[0]) : collapse && children3.length === 1 ? children3[0] : (cstOutput || !build && project === void 0) && ctx.build?._parsemanCstCollapse && children3.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children3[0], children3, rawChildren) ? children3[0] : project !== void 0 ? cstOutput && ctx.build ? ctx.build(nodeType, children3, fields, span, rawChildren, triviaLog, hostState, tags) : projectChild(children3, project, nodeType) : build ? cstOutput && ctx.build ? ctx.build(nodeType, children3, fields, span, rawChildren, triviaLog, hostState, tags) : build(children3, fields, span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children3, fields, span, rawChildren, triviaLog, st, tags) : { _tag: "node", type: nodeType, span: ctx.trackLines ? { ...span } : { start: r.span.start, end: r.span.end }, state: st ?? null, children: children3 };
5105
+ const built = unwrap && children3.length === 1 ? unwrapChild(children3[0]) : collapse && children3.length === 1 ? children3[0] : (cstOutput || !build && project === void 0) && ctx.build?._parsemanCstCollapse && children3.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children3[0], children3, rawChildren) ? children3[0] : project !== void 0 ? cstOutput && ctx.build ? ctx.build(nodeType, children3, fields, span, rawChildren, triviaLog, ctx.state, tags) : projectChild(children3, project, nodeType) : build ? cstOutput && ctx.build ? ctx.build(nodeType, children3, fields, span, rawChildren, triviaLog, ctx.state, tags) : build(children3, fields, span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children3, fields, span, rawChildren, triviaLog, st, tags) : { _tag: "node", type: nodeType, span: ctx.trackLines ? { ...span } : { start: r.span.start, end: r.span.end }, state: st ?? null, children: children3 };
5028
5106
  const rawEntry2 = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : typeof built === "object" && built !== null ? input.slice(r.span.start, r.span.end) : "", span };
5029
5107
  if (saved.buf !== void 0 || saved.ch !== void 0) {
5030
5108
  pushCstChild(ctx, built, rawEntry2);
@@ -5317,17 +5395,59 @@ function buildLexBodyRecognizer(spec, constants) {
5317
5395
  };
5318
5396
  }
5319
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
+
5320
5441
  // src/table/lex-program.ts
5321
5442
  var LEX_NODE_TERMINAL = 0;
5322
5443
  var LEX_NODE_SEQUENCE2 = 1;
5323
5444
  var LEX_NODE_SEQUENCE3 = 2;
5324
5445
  var LEX_NODE_SEQUENCE4 = 3;
5325
5446
  var LEX_NODE_SEQUENCE5 = 4;
5326
- var LEX_NODE_CHOICE2 = 5;
5327
- var LEX_NODE_CHOICE4 = 6;
5328
- var LEX_NODE_CHOICE8 = 7;
5447
+ var LEX_NODE_CHOICE = 5;
5329
5448
  var LEX_NODE_NOT = 8;
5330
5449
  var LEX_NODE_OPTIONAL = 9;
5450
+ var LEX_NODE_REPEAT = 10;
5331
5451
  function lexProgramDigest(words) {
5332
5452
  let hash = 2166136261;
5333
5453
  for (const word2 of words) {
@@ -5356,85 +5476,114 @@ function trackLexLines(ctx, input, end) {
5356
5476
  ctx._lineScannedTo = end;
5357
5477
  }
5358
5478
  function terminalNode(matcher, failure, tracksLines) {
5359
- const match = (input, pos) => {
5360
- const result = matcher(input, pos);
5361
- return result < 0 ? -1 : result / 2;
5362
- };
5363
5479
  return {
5364
- match,
5480
+ match: (input, pos) => {
5481
+ const result = matcher(input, pos);
5482
+ return result < 0 ? -1 : result / 2;
5483
+ },
5365
5484
  run: (input, pos, ctx) => {
5366
- const end = match(input, pos);
5367
- if (end < 0) {
5485
+ const result = matcher(input, pos);
5486
+ if (result < 0) {
5368
5487
  ctx._fe = pos;
5369
5488
  ctx._fx = failure;
5370
5489
  if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
5371
5490
  return -1;
5372
5491
  }
5492
+ const end = result / 2;
5373
5493
  if (tracksLines) trackLexLines(ctx, input, end);
5374
5494
  return end;
5375
5495
  }
5376
5496
  };
5377
5497
  }
5378
5498
  function sequence2(a, b) {
5499
+ const am = a.match, bm = b.match, ar = a.run, br = b.run;
5379
5500
  return {
5380
5501
  match: (input, pos) => {
5381
- const e0 = a.match(input, pos);
5382
- return e0 < 0 ? -1 : b.match(input, e0);
5502
+ const e0 = am(input, pos);
5503
+ return e0 < 0 ? -1 : bm(input, e0);
5383
5504
  },
5384
5505
  run: (input, pos, ctx) => {
5385
- const e0 = a.run(input, pos, ctx);
5506
+ const e0 = ar(input, pos, ctx);
5386
5507
  if (e0 < 0) return -1;
5387
5508
  ctx._fc = false;
5388
- return b.run(input, e0, ctx);
5509
+ return br(input, e0, ctx);
5389
5510
  }
5390
5511
  };
5391
5512
  }
5392
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;
5393
5515
  return {
5394
5516
  match: (input, pos) => {
5395
- const e0 = a.match(input, pos);
5517
+ const e0 = am(input, pos);
5396
5518
  if (e0 < 0) return -1;
5397
- const e1 = b.match(input, e0);
5398
- return e1 < 0 ? -1 : c.match(input, e1);
5519
+ const e1 = bm(input, e0);
5520
+ return e1 < 0 ? -1 : cm(input, e1);
5399
5521
  },
5400
5522
  run: (input, pos, ctx) => {
5401
- const e0 = a.run(input, pos, ctx);
5523
+ const e0 = ar(input, pos, ctx);
5402
5524
  if (e0 < 0) return -1;
5403
5525
  ctx._fc = false;
5404
- const e1 = b.run(input, e0, ctx);
5526
+ const e1 = br(input, e0, ctx);
5405
5527
  if (e1 < 0) return -1;
5406
5528
  ctx._fc = false;
5407
- return c.run(input, e1, ctx);
5529
+ return cr(input, e1, ctx);
5408
5530
  }
5409
5531
  };
5410
5532
  }
5411
5533
  function sequence4(a, b, c, d) {
5412
- 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;
5413
5536
  return {
5414
5537
  match: (input, pos) => {
5415
- const end = abc.match(input, pos);
5416
- 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);
5417
5544
  },
5418
5545
  run: (input, pos, ctx) => {
5419
- const end = abc.run(input, pos, ctx);
5420
- if (end < 0) return -1;
5546
+ const e0 = ar(input, pos, ctx);
5547
+ if (e0 < 0) return -1;
5421
5548
  ctx._fc = false;
5422
- 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);
5423
5556
  }
5424
5557
  };
5425
5558
  }
5426
5559
  function sequence5(a, b, c, d, e) {
5427
- 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;
5428
5562
  return {
5429
5563
  match: (input, pos) => {
5430
- const end = abcd.match(input, pos);
5431
- 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);
5432
5572
  },
5433
5573
  run: (input, pos, ctx) => {
5434
- const end = abcd.run(input, pos, ctx);
5435
- 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;
5436
5579
  ctx._fc = false;
5437
- 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);
5438
5587
  }
5439
5588
  };
5440
5589
  }
@@ -5447,9 +5596,9 @@ function appendExpected(acc, values) {
5447
5596
  function choiceNode(arms, classes, armExpected, choiceExpected) {
5448
5597
  let matchTail = () => -1;
5449
5598
  for (let i = arms.length - 1; i >= 0; i--) {
5450
- const arm = arms[i], next = matchTail;
5599
+ const armMatch = arms[i].match, next = matchTail;
5451
5600
  matchTail = (input, pos) => {
5452
- const end = arm.match(input, pos);
5601
+ const end = armMatch(input, pos);
5453
5602
  return end < 0 ? next(input, pos) : end;
5454
5603
  };
5455
5604
  }
@@ -5459,7 +5608,7 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
5459
5608
  return -1;
5460
5609
  };
5461
5610
  for (let i = arms.length - 1; i >= 0; i--) {
5462
- 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;
5463
5612
  tail = (input, pos, ctx, lead2, acc, best) => {
5464
5613
  if (cls !== void 0 && !classHas(cls, lead2)) {
5465
5614
  return next(
@@ -5472,7 +5621,7 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
5472
5621
  );
5473
5622
  }
5474
5623
  ctx._fc = false;
5475
- const end = arm.run(input, pos, ctx);
5624
+ const end = armRun(input, pos, ctx);
5476
5625
  if (end >= 0) return end;
5477
5626
  const at = ctx._fe ?? pos;
5478
5627
  if (at > best) {
@@ -5499,11 +5648,58 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
5499
5648
  )
5500
5649
  };
5501
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
+ }
5502
5697
  function notNode(body, failure) {
5698
+ const bodyMatch = body.match;
5503
5699
  return {
5504
- match: (input, pos) => body.match(input, pos) < 0 ? pos : -1,
5700
+ match: (input, pos) => bodyMatch(input, pos) < 0 ? pos : -1,
5505
5701
  run: (input, pos, ctx) => {
5506
- if (body.match(input, pos) < 0) return pos;
5702
+ if (bodyMatch(input, pos) < 0) return pos;
5507
5703
  ctx._fe = pos;
5508
5704
  ctx._fx = failure;
5509
5705
  return -1;
@@ -5511,18 +5707,57 @@ function notNode(body, failure) {
5511
5707
  };
5512
5708
  }
5513
5709
  function optionalNode(body) {
5710
+ const bodyMatch = body.match, bodyRun = body.run;
5514
5711
  return {
5515
5712
  match: (input, pos) => {
5516
- const end = body.match(input, pos);
5713
+ const end = bodyMatch(input, pos);
5517
5714
  return end < 0 ? pos : end;
5518
5715
  },
5519
5716
  run: (input, pos, ctx) => {
5520
5717
  ctx._fc = false;
5521
- const end = body.run(input, pos, ctx);
5718
+ const end = bodyRun(input, pos, ctx);
5522
5719
  return end < 0 && !committed(ctx) ? pos : end;
5523
5720
  }
5524
5721
  };
5525
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
+ }
5526
5761
  function fixedTreeRunner(words, matchers, classes, expected) {
5527
5762
  const stack = [];
5528
5763
  const pop = () => {
@@ -5550,9 +5785,14 @@ function fixedTreeRunner(words, matchers, classes, expected) {
5550
5785
  else stack.push(sequence5(nodes2[0], nodes2[1], nodes2[2], nodes2[3], nodes2[4]));
5551
5786
  continue;
5552
5787
  }
5553
- if (op >= LEX_NODE_CHOICE2 && op <= LEX_NODE_CHOICE8) {
5554
- 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");
5555
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
+ }
5556
5796
  if (choiceFx === void 0) throw new TypeError("table lexical tree choice has an invalid expected set");
5557
5797
  const armClasses = [];
5558
5798
  const armFx = [];
@@ -5565,7 +5805,7 @@ function fixedTreeRunner(words, matchers, classes, expected) {
5565
5805
  armFx.push(fx);
5566
5806
  }
5567
5807
  const arms = Array.from({ length: count }, pop).reverse();
5568
- stack.push(choiceNode(arms, armClasses, armFx, choiceFx));
5808
+ stack.push(exclusive === 1 ? exclusiveChoiceNode(arms, armClasses, choiceFx) : choiceNode(arms, armClasses, armFx, choiceFx));
5569
5809
  continue;
5570
5810
  }
5571
5811
  if (op === LEX_NODE_NOT) {
@@ -5578,6 +5818,14 @@ function fixedTreeRunner(words, matchers, classes, expected) {
5578
5818
  stack.push(optionalNode(pop()));
5579
5819
  continue;
5580
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
+ }
5581
5829
  throw new TypeError("table lexical tree has an unknown fixed body");
5582
5830
  }
5583
5831
  if (stack.length !== 1) throw new TypeError("table lexical tree does not resolve to one root body");
@@ -5594,7 +5842,7 @@ function buildLexProgramRunner(spec, matchers, classes, expected) {
5594
5842
  if (!Number.isInteger(spec[2]) || spec[2] < 0) {
5595
5843
  throw new TypeError("table balanced lexical program has an invalid scan reference");
5596
5844
  }
5597
- const run = (_input, _pos, ctx, scan) => {
5845
+ const run2 = (_input, _pos, ctx, scan) => {
5598
5846
  if (scan === void 0) throw new TypeError("table balanced lexical program lost its scan body");
5599
5847
  const result = scan.parse(_input, _pos, ctx);
5600
5848
  if (!result.ok) {
@@ -5604,7 +5852,7 @@ function buildLexProgramRunner(spec, matchers, classes, expected) {
5604
5852
  }
5605
5853
  return result.span.end;
5606
5854
  };
5607
- return Object.assign(run, { scan: spec[2] });
5855
+ return Object.assign(run2, { scan: spec[2] });
5608
5856
  }
5609
5857
  if (spec[0] === 2) return fixedTreeRunner(spec.slice(2), matchers, classes, expected);
5610
5858
  if (spec[0] === 1) {
@@ -5732,6 +5980,12 @@ function scanRefs(s) {
5732
5980
  refs.push(...s.skip);
5733
5981
  return refs;
5734
5982
  }
5983
+ function assemblyExtraIps(prog) {
5984
+ const ips = [];
5985
+ for (const s of prog.scans ?? []) for (const r of scanRefs(s)) ips.push(r[0]);
5986
+ for (const set of prog.scanSkip ?? []) for (const r of set) ips.push(r[0]);
5987
+ return ips;
5988
+ }
5735
5989
  function expandCompact(p) {
5736
5990
  if ("code" in p) return p;
5737
5991
  return ownTableProgram({
@@ -5862,6 +6116,11 @@ function classHas2(cls, code) {
5862
6116
  for (let i = 0; i < hi.length; i += 2) if (code >= hi[i] && code <= hi[i + 1]) return true;
5863
6117
  return false;
5864
6118
  }
6119
+ function dispatchIsExclusive(arms, cc) {
6120
+ const resolved = [];
6121
+ for (const ci of arms) if (ci >= 0) resolved[ci] = resolveClass(cc[ci]);
6122
+ return resolveDispatch(arms, resolved).exclusive;
6123
+ }
5865
6124
  function resolveDispatch(arms, cc) {
5866
6125
  const ascii = new Uint8Array(128);
5867
6126
  const hi = [];
@@ -6453,6 +6712,111 @@ function classifyRuleMap(ruleMap) {
6453
6712
  };
6454
6713
  }
6455
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
+
6456
6820
  // src/table/ops.ts
6457
6821
  var OP_LIT = 1;
6458
6822
  var OP_RX = 2;
@@ -6496,6 +6860,7 @@ var OP_SCOPE_PLAIN = 41;
6496
6860
  var OP_LEX_BODY = 42;
6497
6861
  var OP_LEX_PROGRAM = 43;
6498
6862
  var OP_SOURCE_LEAF = 44;
6863
+ var OP_RGATE = 45;
6499
6864
  var OP_DISPATCH = 25;
6500
6865
  var OP_ROUTED = 26;
6501
6866
  var OP_NAMES = {
@@ -6515,6 +6880,7 @@ var OP_NAMES = {
6515
6880
  [OP_PEEK]: "PEEK",
6516
6881
  [OP_LEAF]: "LEAF",
6517
6882
  [OP_SOURCE_LEAF]: "SOURCE_LEAF",
6883
+ [OP_RGATE]: "RGATE",
6518
6884
  [OP_EMPTY]: "EMPTY",
6519
6885
  [OP_LIT_TRACK]: "LIT_TRACK",
6520
6886
  [OP_RX_TRACK]: "RX_TRACK",
@@ -6595,7 +6961,10 @@ function selectOptionalSuffixLexBody(ir) {
6595
6961
  const token2 = { strategy: "token", estimatedOps: 2, body };
6596
6962
  return token2.estimatedOps < character.estimatedOps ? token2 : character;
6597
6963
  }
6598
- 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) {
6599
6968
  const outer = parser2._def;
6600
6969
  if (outer.tag !== "token") return void 0;
6601
6970
  let body = outer.parser;
@@ -6605,12 +6974,13 @@ function directTokenBodyParser(parser2, resolve3) {
6605
6974
  const wrapper = body._def;
6606
6975
  if (wrapper.tag === "grammar") {
6607
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;
6608
6978
  body = wrapper.parser;
6609
6979
  continue;
6610
6980
  }
6611
6981
  if (wrapper.tag === "lazy") {
6612
6982
  const target = resolvedLazyTarget(body, resolve3);
6613
- if (target === void 0) return void 0;
6983
+ if (target === void 0 || reinstallsRuleTrivia(body, target)) return void 0;
6614
6984
  body = target;
6615
6985
  continue;
6616
6986
  }
@@ -6782,7 +7152,7 @@ function directNot2TokenBody(parser2, resolve3) {
6782
7152
  terminal
6783
7153
  };
6784
7154
  }
6785
- function directFixedLexNode(parser2, resolve3, active, pureOnly = false) {
7155
+ function directFixedLexNode(parser2, resolve3, active, pureOnly = false, cleared = false) {
6786
7156
  let current = parser2;
6787
7157
  const wrappers = /* @__PURE__ */ new Set();
6788
7158
  while (!wrappers.has(current)) {
@@ -6790,7 +7160,7 @@ function directFixedLexNode(parser2, resolve3, active, pureOnly = false) {
6790
7160
  const def = current._def;
6791
7161
  if (def.tag === "lazy") {
6792
7162
  const target = resolvedLazyTarget(current, resolve3);
6793
- if (target === void 0) return void 0;
7163
+ if (target === void 0 || reinstallsRuleTrivia(current, target)) return void 0;
6794
7164
  current = target;
6795
7165
  continue;
6796
7166
  }
@@ -6808,30 +7178,33 @@ function directFixedLexNode(parser2, resolve3, active, pureOnly = false) {
6808
7178
  if (terminal !== void 0) return { kind: "terminal", terminal };
6809
7179
  const def = current._def;
6810
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
+ }
6811
7184
  if (!pureOnly || def.parser._def.tag !== "token" && (def.clearTrivia !== true || def.triviaParser !== void 0 || def.captureTrivia === true || def.rootCapture === "opaque")) return void 0;
6812
- return directFixedLexNode(def.parser, resolve3, active, true);
7185
+ return directFixedLexNode(def.parser, resolve3, active, true, cleared);
6813
7186
  }
6814
7187
  if (def.tag === "sequence") {
6815
7188
  if (def.parsers.length < 2 || def.parsers.length > 5) return void 0;
6816
- const parts = def.parsers.map((part) => directFixedLexNode(part, resolve3, active, pureOnly));
7189
+ const parts = def.parsers.map((part) => directFixedLexNode(part, resolve3, active, pureOnly, cleared));
6817
7190
  if (parts.some((part) => part === void 0)) return void 0;
6818
7191
  return { kind: "sequence", parts };
6819
7192
  }
6820
7193
  if (def.tag === "choice") {
6821
- 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;
6822
- 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));
6823
7196
  if (arms.some((arm) => arm === void 0)) return void 0;
6824
- const final = classifyFinalChoice(def.parsers, resolve3);
6825
7197
  return {
6826
7198
  kind: "choice",
6827
7199
  arms,
6828
- firstSets: final.firstSets,
7200
+ parsers: def.parsers,
7201
+ cleared,
6829
7202
  armExpected: def.parsers.map(deriveExpected),
6830
7203
  expected: def.parsers.flatMap(deriveExpected)
6831
7204
  };
6832
7205
  }
6833
7206
  if (def.tag === "not") {
6834
- const body = directFixedLexNode(def.parser, resolve3, active, true);
7207
+ const body = directFixedLexNode(def.parser, resolve3, active, true, cleared);
6835
7208
  return body === void 0 ? void 0 : {
6836
7209
  kind: "not",
6837
7210
  body,
@@ -6839,18 +7212,28 @@ function directFixedLexNode(parser2, resolve3, active, pureOnly = false) {
6839
7212
  };
6840
7213
  }
6841
7214
  if (def.tag === "optional") {
6842
- const body = directFixedLexNode(def.parser, resolve3, active, pureOnly);
7215
+ const body = directFixedLexNode(def.parser, resolve3, active, pureOnly, cleared);
6843
7216
  return body === void 0 ? void 0 : { kind: "optional", body };
6844
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
+ }
6845
7227
  return void 0;
6846
7228
  } finally {
6847
7229
  active.delete(current);
6848
7230
  }
6849
7231
  }
6850
7232
  function directFixedTokenBody(parser2, resolve3) {
6851
- const body = directTokenBodyParser(parser2, resolve3);
7233
+ const scope = { cleared: false };
7234
+ const body = directTokenBodyParser(parser2, resolve3, scope);
6852
7235
  if (body === void 0) return void 0;
6853
- const root = directFixedLexNode(body, resolve3, /* @__PURE__ */ new Set());
7236
+ const root = directFixedLexNode(body, resolve3, /* @__PURE__ */ new Set(), false, scope.cleared);
6854
7237
  return root === void 0 ? void 0 : { kind: "fixed-tree", root };
6855
7238
  }
6856
7239
  function directBalancedTokenBody(parser2, resolve3) {
@@ -7097,13 +7480,16 @@ var Encoder = class {
7097
7480
  }
7098
7481
  case "choice": {
7099
7482
  for (const arm of node2.arms) if (!emitNode(arm)) return false;
7100
- const op = node2.arms.length === 2 ? LEX_NODE_CHOICE2 : node2.arms.length === 4 ? LEX_NODE_CHOICE4 : node2.arms.length === 8 ? LEX_NODE_CHOICE8 : -1;
7101
- if (op < 0) return false;
7102
- 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));
7103
7491
  for (let i = 0; i < node2.arms.length; i++) {
7104
- const first = node2.firstSets[i];
7105
- words.push(first.kind === "ranges" ? this.charClass(first) : -1);
7106
- words.push(this.expected(node2.armExpected[i]));
7492
+ words.push(classes[i], this.expected(node2.armExpected[i]));
7107
7493
  }
7108
7494
  return true;
7109
7495
  }
@@ -7115,6 +7501,10 @@ var Encoder = class {
7115
7501
  if (!emitNode(node2.body)) return false;
7116
7502
  words.push(LEX_NODE_OPTIONAL);
7117
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;
7118
7508
  }
7119
7509
  };
7120
7510
  if (!emitNode(body.root)) return void 0;
@@ -7442,6 +7832,33 @@ var Encoder = class {
7442
7832
  return childrenOf2(def);
7443
7833
  }
7444
7834
  }
7835
+ /**
7836
+ * THE FIRST-CHARACTER GATE OF AN `optional`, `not` OR `peek` CHILD.
7837
+ *
7838
+ * A non-nullable child cannot match at a character outside its first set, so
7839
+ * the wrapper's outcome there is already decided: `optional` yields `null`,
7840
+ * `not` succeeds, `peek` fails with its own set. The interpreter's `optional`
7841
+ * makes that test itself (`repeat.ts` `startsFirstSet`); the table entered the
7842
+ * child — a rollback mark, the call, the child's own failure — to learn it.
7843
+ *
7844
+ * The gate is an `OP_GATE` row around the child, so every engine runs it
7845
+ * unchanged, a probe or tolerant parse forwards through it as for a node's
7846
+ * gate, and the wrapper's row keeps its layout. The engines test the class
7847
+ * before taking the wrapper's mark. The first set is resolved through
7848
+ * `winners`, the analysis a choice arm's gate uses, so a composed rule's set
7849
+ * is the merged one. A scalar `not` child stays bare: `scalarTerminalNotChild`
7850
+ * already reduces it to one recognizer call.
7851
+ */
7852
+ lookaheadGate(p, child) {
7853
+ const op = this.code[child];
7854
+ if (op === OP_GATE || op === OP_LIT || op === OP_LIT_CI || op === OP_LIT_TRACK || op === OP_LIT_CI_TRACK || op === OP_RX || op === OP_RX_TRACK) return child;
7855
+ const rr = this.refResolver();
7856
+ if (matchesEmpty(p, /* @__PURE__ */ new Set(), rr)) return child;
7857
+ const cls = this.charClass(firstSetOf(p, /* @__PURE__ */ new Set(), rr, this.activeTrivia));
7858
+ if (cls < 0) return child;
7859
+ const e = deriveExpected(p);
7860
+ return this.emit(OP_GATE, cls, child, this.expected(e.length > 0 ? e : [p._tag]));
7861
+ }
7445
7862
  /** A first set becomes a char class string, or −1 for `any`. */
7446
7863
  charClass(fs3) {
7447
7864
  if (fs3.kind !== "ranges" || fs3.ranges.length === 0) return -1;
@@ -7453,12 +7870,19 @@ var Encoder = class {
7453
7870
  this.ccIndex.set(spec, i);
7454
7871
  return i;
7455
7872
  }
7456
- /** Bind a guard only when its class is already part of the program. Repeat
7457
- * gating must not grow the compact artifact merely to avoid a failed call. */
7458
- existingCharClass(fs3) {
7459
- if (fs3.kind !== "ranges" || fs3.ranges.length === 0) return -1;
7460
- const hit = this.ccIndex.get(encodeClassSpec(fs3.ranges));
7461
- return hit !== void 0 && hit < 100 ? hit : -1;
7873
+ /**
7874
+ * The first set a node's or an attempt's fail-fast gate tests. A bare
7875
+ * cross-rule ref resolves through `winners` (a compose OVERRIDE may widen
7876
+ * it). Any other body keeps its construction-time `_meta.firstSet`, except
7877
+ * where that is `any`: under `compose()` a body that reaches a rule of
7878
+ * another piece is built before that rule exists, so its cached set is
7879
+ * `any` and the node got NO gate (jess's `CompoundSelector` was entered at
7880
+ * `{`, `Call` at `}`). The resolved set is the one a choice arm's gate uses,
7881
+ * over the final merged map.
7882
+ */
7883
+ gateFirstSet(p) {
7884
+ const cached = p._meta.firstSet;
7885
+ return p._def.tag === "lazy" || cached.kind === "any" ? firstSetOf(p, /* @__PURE__ */ new Set(), this.refResolver(), this.activeTrivia) : cached;
7462
7886
  }
7463
7887
  /**
7464
7888
  * Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
@@ -7586,6 +8010,50 @@ var Encoder = class {
7586
8010
  if (!hasOwnTriviaBoundary(target)) return ip;
7587
8011
  return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), ip);
7588
8012
  }
8013
+ /**
8014
+ * The `OP_RGATE` operands of a choice arm that opens with `routed()`, or
8015
+ * `undefined`. Through `node()`/scope wrappers and first sequence terms, the
8016
+ * arm's next term after the routed token is found; the gate is that term's
8017
+ * first characters, with the trivia in force at the boundary before it, so
8018
+ * the arm is entered only where it can get past the token. The term must be
8019
+ * unable to match empty or to commit, so a miss is exactly that term failing
8020
+ * at the token's end with its own set.
8021
+ */
8022
+ routedArmGate(arm) {
8023
+ const walk = (p, trivia2, depth) => {
8024
+ if (depth > 16) return void 0;
8025
+ const d = p._def;
8026
+ switch (d.tag) {
8027
+ case "routed":
8028
+ return "end";
8029
+ case "node":
8030
+ return walk(d.parser, trivia2, depth + 1);
8031
+ case "grammar":
8032
+ return walk(d.parser, d.clearTrivia === true ? void 0 : d.triviaParser ?? trivia2, depth + 1);
8033
+ case "sequence": {
8034
+ const head = d.parsers[0];
8035
+ if (head === void 0) return void 0;
8036
+ const r = walk(head, trivia2, depth + 1);
8037
+ if (r !== "end") return r;
8038
+ const next2 = d.parsers[1];
8039
+ return next2 === void 0 ? "end" : { next: next2, boundary: trivia2 };
8040
+ }
8041
+ default:
8042
+ return void 0;
8043
+ }
8044
+ };
8045
+ const follow = walk(arm, this.activeTrivia, 0);
8046
+ if (follow === void 0 || follow === "end") return void 0;
8047
+ const rr = this.refResolver();
8048
+ const { next, boundary } = follow;
8049
+ if (matchesEmpty(next, /* @__PURE__ */ new Set(), rr) || mayCommitFailure(next, rr, this.commitFailureMemo)) return void 0;
8050
+ const nextTag = next._def.tag;
8051
+ if (nextTag !== "literal" && nextTag !== "regex" && nextTag !== "keywords" && nextTag !== "label") return void 0;
8052
+ const first = firstSetOf(next, /* @__PURE__ */ new Set(), rr, boundary);
8053
+ const cls = this.charClass(boundary === void 0 ? first : union(first, firstSetOf(boundary, /* @__PURE__ */ new Set(), rr)));
8054
+ if (cls < 0) return void 0;
8055
+ return { cls, fx: this.expected(deriveExpected(next)) };
8056
+ }
7589
8057
  node(p) {
7590
8058
  const lazyRef = p._def.tag === "lazy";
7591
8059
  const scopeKey = lazyRef ? this.activeTrivia : void 0;
@@ -7710,6 +8178,10 @@ var Encoder = class {
7710
8178
  return head;
7711
8179
  }
7712
8180
  case "choice": {
8181
+ if (this.plan === void 0) {
8182
+ const factored = factorSharedEnds(d);
8183
+ if (factored !== void 0) return this.node(factored).ip;
8184
+ }
7713
8185
  if (d.strategy.tag === "greedyClassify") {
7714
8186
  const superIndex = d.strategy.superIndex;
7715
8187
  const sup = this.node(d.parsers[superIndex]).ip;
@@ -7733,9 +8205,12 @@ var Encoder = class {
7733
8205
  const kids = arms.map((c, k) => {
7734
8206
  const src = order[k];
7735
8207
  const checks = d.autoNot[src];
7736
- const inner = this.node(c).ip;
7737
- const ip = checks === null || checks === void 0 || checks.length === 0 ? inner : this.reject(inner, checks);
7738
8208
  const gate2 = d.gates[src];
8209
+ const plain = (checks === null || checks === void 0 || checks.length === 0) && (gate2 === null || gate2 === void 0);
8210
+ const routedGate = plain ? this.routedArmGate(c) : void 0;
8211
+ const body = this.node(c).ip;
8212
+ const inner = routedGate === void 0 ? body : this.emit(OP_RGATE, routedGate.cls, body, routedGate.fx);
8213
+ const ip = checks === null || checks === void 0 || checks.length === 0 ? inner : this.reject(inner, checks);
7739
8214
  const gated = gate2 === null || gate2 === void 0 ? ip : this.emit(OP_ARMGATE, this.fn(gate2, d.gateSrcs?.[src] ?? null), ip, this.expected(deriveExpected(c)));
7740
8215
  return this.covWrap(gated, armCovIds?.[src], 1);
7741
8216
  });
@@ -7763,6 +8238,12 @@ var Encoder = class {
7763
8238
  if (transactionalFirst[i] !== void 0) classes[i] = -1;
7764
8239
  }
7765
8240
  }
8241
+ if (d.gates.some((g) => g !== null && g !== void 0) && !dispatchIsExclusive(classes, this.cc)) {
8242
+ for (let k = 0; k < classes.length; k++) {
8243
+ const gate2 = d.gates[order[k]];
8244
+ if (gate2 !== null && gate2 !== void 0) classes[k] = -1;
8245
+ }
8246
+ }
7766
8247
  const dispIdx = this.disp.length;
7767
8248
  this.disp.push(classes);
7768
8249
  let rollbackMask = kids.length > 31 ? -1 : 0;
@@ -7792,7 +8273,7 @@ var Encoder = class {
7792
8273
  case "oneOrMore": {
7793
8274
  const child = this.node(d.parser).ip;
7794
8275
  const rr = this.refResolver();
7795
- const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.existingCharClass(firstSetOf(d.parser, /* @__PURE__ */ new Set(), rr, this.activeTrivia));
8276
+ const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.charClass(firstSetOf(d.parser, /* @__PURE__ */ new Set(), rr, this.activeTrivia));
7796
8277
  const op = d.valueUnused ? OP_REPV : OP_REP;
7797
8278
  const min = d.tag === "many" ? 0 : d.min;
7798
8279
  return this.rec ? this.emit(op, child, min, d.max ?? -1, -1, 0, this.expected(deriveExpected(d.parser)), itemClass) : this.emit(op, child, min, d.max ?? -1, -1, 0);
@@ -7816,7 +8297,7 @@ var Encoder = class {
7816
8297
  return d.min >= 2 ? this.emit(OP_REP, child, d.min, d.max ?? -1, sep2, flags, this.expected(deriveExpected(d.parser))) : this.emit(OP_REP, child, d.min, d.max ?? -1, sep2, flags);
7817
8298
  }
7818
8299
  case "optional": {
7819
- const head = this.emit(OP_OPT, this.node(d.parser).ip);
8300
+ const head = this.emit(OP_OPT, this.lookaheadGate(d.parser, this.node(d.parser).ip));
7820
8301
  if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(head);
7821
8302
  return head;
7822
8303
  }
@@ -7864,8 +8345,8 @@ var Encoder = class {
7864
8345
  // every CST node, so this is load-bearing, not reflection trivia.
7865
8346
  d.tags === void 0 ? -1 : this.constant(d.tags)
7866
8347
  );
7867
- if (matchesEmpty(d.parser)) return body;
7868
- const fs3 = d.parser._def.tag === "lazy" ? firstSetOf(d.parser, /* @__PURE__ */ new Set(), this.refResolver(), this.activeTrivia) : d.parser._meta.firstSet;
8348
+ if (matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return body;
8349
+ const fs3 = this.gateFirstSet(d.parser);
7869
8350
  if (fs3.kind === "any") return body;
7870
8351
  const cls = this.charClass(fs3);
7871
8352
  if (cls < 0) return body;
@@ -7957,7 +8438,7 @@ var Encoder = class {
7957
8438
  // other engine reported `['not(literal)']`. It hid because `expected` is a
7958
8439
  // TOP-LEVEL field on `RunResult` and is NOT part of the identity digest.
7959
8440
  case "not":
7960
- return this.emit(OP_NOT, this.node(d.parser).ip, this.expected(assertionFailureExpected(false, d.parser._tag)));
8441
+ return this.emit(OP_NOT, this.lookaheadGate(d.parser, this.node(d.parser).ip), this.expected(assertionFailureExpected(false, d.parser._tag)));
7961
8442
  case "guard":
7962
8443
  return this.emit(OP_GUARD, this.fn(d.predicate, d.predSrc ?? null), this.expected(["gate"]));
7963
8444
  case "adjacency":
@@ -7978,14 +8459,14 @@ var Encoder = class {
7978
8459
  return this.emit(OP_WITHCTX, this.constant(d.extra), this.node(d.parser).ip);
7979
8460
  }
7980
8461
  case "peek":
7981
- return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected(assertionFailureExpected(true, d.parser._tag)));
8462
+ return this.emit(OP_PEEK, this.lookaheadGate(d.parser, this.node(d.parser).ip), this.expected(assertionFailureExpected(true, d.parser._tag)));
7982
8463
  // A TRANSACTION IS A ROW. See `OP_ATTEMPT` for why the transparent
7983
8464
  // lowering was correct only for a choice arm.
7984
8465
  case "attempt": {
7985
8466
  const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip, d.contain === true ? 1 : 0);
7986
8467
  if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
7987
- const fs3 = d.parser._def.tag === "lazy" ? firstSetOf(d.parser, /* @__PURE__ */ new Set(), this.refResolver(), this.activeTrivia) : d.parser._meta.firstSet;
7988
- if (fs3.kind === "any" || matchesEmpty(d.parser)) return inner;
8468
+ const fs3 = this.gateFirstSet(d.parser);
8469
+ if (fs3.kind === "any" || matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return inner;
7989
8470
  const cls = this.charClass(fs3);
7990
8471
  if (cls < 0) return inner;
7991
8472
  const e = deriveExpected(d.parser);
@@ -8053,6 +8534,7 @@ var Encoder = class {
8053
8534
  const slots = (ip) => {
8054
8535
  switch (this.code[ip]) {
8055
8536
  case OP_GATE:
8537
+ case OP_RGATE:
8056
8538
  return [ip + 2];
8057
8539
  case OP_RULE:
8058
8540
  case OP_OPT:
@@ -9280,6 +9762,7 @@ function childSlots(code, ip, out) {
9280
9762
  case OP_LEAF:
9281
9763
  case OP_SOURCE_LEAF:
9282
9764
  case OP_ARMGATE:
9765
+ case OP_RGATE:
9283
9766
  out.push(code[ip + 2]);
9284
9767
  return true;
9285
9768
  // `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
@@ -9363,6 +9846,42 @@ function reachableSites(code, roots) {
9363
9846
  }
9364
9847
  return seen;
9365
9848
  }
9849
+ function passCollapse(code, ip, hostCst) {
9850
+ const flags = code[ip + 3];
9851
+ if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return false;
9852
+ if (flags !== 32 && flags !== 34) return false;
9853
+ let at = code[ip + 2];
9854
+ for (let n = 0; n < 8; n++) {
9855
+ const op = code[at];
9856
+ if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[at + 3] === 0) at = code[at + 2];
9857
+ else if (op === OP_RULE) at = code[at + 1];
9858
+ else break;
9859
+ }
9860
+ return code[at] === OP_NODE;
9861
+ }
9862
+ function gatedPassCollapse(code, ip, hostCst) {
9863
+ const flags = code[ip + 3];
9864
+ if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return void 0;
9865
+ if (flags !== 32 && flags !== 34) return void 0;
9866
+ const seq = code[ip + 2];
9867
+ if (code[seq] !== OP_SEQ && code[seq] !== OP_SEQV) return void 0;
9868
+ const n = code[seq + 1];
9869
+ if (n < 2) return void 0;
9870
+ const leads = [];
9871
+ const lits = [];
9872
+ for (let i = 0; i < n - 1; i++) {
9873
+ const t = code[seq + 2 + i];
9874
+ if (code[t] !== OP_OPT && code[t] !== OP_NOT) return void 0;
9875
+ const g = code[t + 1];
9876
+ if (code[g] === OP_GATE) leads.push(g);
9877
+ else if (code[g] === OP_LIT) lits.push(code[g + 1]);
9878
+ else return void 0;
9879
+ }
9880
+ const last = code[seq + 2 + n - 1];
9881
+ let at = last;
9882
+ for (let k = 0; k < 8 && (code[at] === OP_GATE || code[at] === OP_RULE); k++) at = code[at] === OP_RULE ? code[at + 1] : code[at + 2];
9883
+ return code[at] === OP_NODE ? { leads, lits, last } : void 0;
9884
+ }
9366
9885
  function transfer(code, ip, at, hostCst) {
9367
9886
  const op = code[ip];
9368
9887
  if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
@@ -9374,14 +9893,18 @@ function transfer(code, ip, at, hostCst) {
9374
9893
  }
9375
9894
  if (op === OP_NODE || op === OP_NODE_TRACK) {
9376
9895
  const flags = code[ip + 3];
9896
+ if (passCollapse(code, ip, hostCst)) return at;
9897
+ const gated = gatedPassCollapse(code, ip, hostCst) !== void 0;
9377
9898
  const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && ((flags & ~128) === 2 || flags === 18 || flags === 34);
9378
9899
  if (directChildren) {
9379
- return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
9900
+ const framed2 = { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
9901
+ return gated ? meet(at, framed2) : framed2;
9380
9902
  }
9381
9903
  const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
9382
9904
  const raw = !hostCst && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags & 2) !== 0 ? RAW_OMIT : RAW_CAPTURE;
9383
9905
  if (at.buf && raw === at.raw && cap === at.cap) return at;
9384
- return { tri: at.tri, buf: true, raw, cap };
9906
+ const framed = { tri: at.tri, buf: true, raw, cap };
9907
+ return gated ? meet(at, framed) : framed;
9385
9908
  }
9386
9909
  if (op === OP_TOKEN) {
9387
9910
  if (at.tri === TRI_NONE && !at.buf) return at;
@@ -9419,6 +9942,40 @@ function computeSiteLabels(code, roots, hostCst) {
9419
9942
  }
9420
9943
  return { at: (ip) => labels.get(ip) ?? TOP };
9421
9944
  }
9945
+ function scopeIsIdentity(code, ip, at) {
9946
+ const op = code[ip];
9947
+ if (op !== OP_SCOPE_PLAIN && !(op === OP_SCOPE && code[ip + 3] === 0)) return false;
9948
+ const ki = code[ip + 1];
9949
+ return at.tri === (ki < 0 ? TRI_NONE : ki);
9950
+ }
9951
+ function scanHandoffNeeded(code, ip, labels) {
9952
+ const seen = /* @__PURE__ */ new Set();
9953
+ const stack = [ip];
9954
+ const kids = [];
9955
+ while (stack.length > 0) {
9956
+ const at = stack.pop();
9957
+ if (seen.has(at)) continue;
9958
+ seen.add(at);
9959
+ const l = labels.at(at);
9960
+ if (l.tri === TRI_UNKNOWN) return true;
9961
+ const op = code[at];
9962
+ if (op === OP_SCAN) return true;
9963
+ if (op === OP_TOKEN || op === OP_SCOPE_CAP) continue;
9964
+ if ((op === OP_SCOPE_PLAIN || op === OP_SCOPE) && !(code[at + 1] >= 0 && l.tri === code[at + 1] && (op === OP_SCOPE_PLAIN || code[at + 3] === 0))) continue;
9965
+ kids.length = 0;
9966
+ if (!childSlots(code, at, kids)) return true;
9967
+ for (const c of kids) stack.push(c);
9968
+ }
9969
+ return false;
9970
+ }
9971
+ function triviaLeadRanges(tri, trivia2) {
9972
+ if (tri === TRI_NONE) return [];
9973
+ if (tri < 0) return void 0;
9974
+ const fs3 = trivia2[tri]?._meta.firstSet;
9975
+ if (fs3 === void 0) return void 0;
9976
+ if (fs3.kind === "empty") return [];
9977
+ return fs3.kind === "ranges" && fs3.ranges !== void 0 ? fs3.ranges : void 0;
9978
+ }
9422
9979
 
9423
9980
  // src/table/scalar-terminal.ts
9424
9981
  function makeScalarRecognizer(op, spec) {
@@ -9456,6 +10013,12 @@ function scalarTerminalNotChild(code, ip) {
9456
10013
  const op = code[child];
9457
10014
  return op === OP_RX || op === OP_LIT ? child : -1;
9458
10015
  }
10016
+ function scalarTerminalPeekChild(code, ip) {
10017
+ if (code[ip] !== OP_PEEK) return -1;
10018
+ const child = code[ip + 1];
10019
+ const op = code[child];
10020
+ return op === OP_RX || op === OP_LIT ? child : -1;
10021
+ }
9459
10022
  function leadingScalarTerminal(code, ip, minDepth = 2, throughAttempt = true, throughPeek = false) {
9460
10023
  const seen = /* @__PURE__ */ new Set();
9461
10024
  let at = ip;
@@ -9633,6 +10196,59 @@ function leadingTriviaFieldAt(code, k, ip) {
9633
10196
  return code[ip] === OP_FIELD && (fieldSpec(k[code[ip + 1]]).bits & FIELD_LEADING_TRIVIA) !== 0;
9634
10197
  }
9635
10198
 
10199
+ // src/table/hold-gap.ts
10200
+ var WRAPPERS = /* @__PURE__ */ new Set([
10201
+ OP_NODE,
10202
+ OP_XFORM,
10203
+ OP_LEAF,
10204
+ OP_SOURCE_LEAF,
10205
+ OP_TOKEN,
10206
+ OP_SCOPE,
10207
+ OP_SCOPE_CAP,
10208
+ OP_SCOPE_PLAIN,
10209
+ OP_FIELD,
10210
+ OP_LABEL,
10211
+ OP_EXPECT,
10212
+ OP_WITHCTX,
10213
+ OP_RULE,
10214
+ OP_ATTEMPT,
10215
+ OP_COV
10216
+ ]);
10217
+ function rowNullable(code, k, ip, memo) {
10218
+ const hit = memo.get(ip);
10219
+ if (hit !== void 0) return hit;
10220
+ memo.set(ip, true);
10221
+ const op = code[ip];
10222
+ const kids = [];
10223
+ let out = true;
10224
+ if (op === OP_GATE) out = false;
10225
+ else if (op === OP_LIT || op === OP_LIT_CI) out = k[code[ip + 1]].length === 0;
10226
+ else if (op === OP_RX) {
10227
+ const re = k[code[ip + 1]];
10228
+ out = !(re instanceof RegExp) || regexCanMatchEmpty(re.source);
10229
+ } else if (op === OP_SEQ || op === OP_SEQV || op === OP_SEQX) {
10230
+ childSlots(code, ip, kids);
10231
+ out = kids.every((c) => rowNullable(code, k, c, memo));
10232
+ } else if (op === OP_CHOICE) {
10233
+ childSlots(code, ip, kids);
10234
+ out = kids.length === 0 || kids.some((c) => rowNullable(code, k, c, memo));
10235
+ } else if (op === OP_REP || op === OP_REPV) {
10236
+ out = code[ip + 2] === 0 || rowNullable(code, k, code[ip + 1], memo);
10237
+ } else if (WRAPPERS.has(op)) {
10238
+ if (childSlots(code, ip, kids) && kids.length === 1) out = rowNullable(code, k, kids[0], memo);
10239
+ }
10240
+ memo.set(ip, out);
10241
+ return out;
10242
+ }
10243
+ function holdsGap(code, k, base, n, i, memo) {
10244
+ if (i < 1 || i + 1 >= n) return false;
10245
+ const term = code[base + i];
10246
+ if (code[term] !== OP_NOT && code[term] !== OP_PEEK) return false;
10247
+ const next = code[base + i + 1];
10248
+ if (code[next] === OP_ADJ || leadingTriviaFieldAt(code, k, next)) return false;
10249
+ return !rowNullable(code, k, next, memo);
10250
+ }
10251
+
9636
10252
  // src/table/emit-assembly.ts
9637
10253
  var Unemittable = class extends Error {
9638
10254
  construct;
@@ -9710,7 +10326,13 @@ var EMITTED_PARAMS = [
9710
10326
  // Appended for trivia-attributing fields (`field(…, { leadingTrivia })`);
9711
10327
  // old factories ignore them.
9712
10328
  "LEAD",
9713
- "triviaFieldCapture"
10329
+ "triviaFieldCapture",
10330
+ // Appended for the deferred-commit trivia skip (`trivia-gap.ts`); old
10331
+ // factories ignore it.
10332
+ "skipDeferredTrivia",
10333
+ // Appended for the pass-through collapse (`run-support.ts`); old factories
10334
+ // ignore it.
10335
+ "collapseEmpty"
9714
10336
  ];
9715
10337
  var RUNTIME_PRELUDE = `
9716
10338
  let _pfScan=null
@@ -9731,7 +10353,7 @@ function _skipTrivia(input,cur,ctx){
9731
10353
  const s=_pfScan
9732
10354
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
9733
10355
  if(s!==null)return skipTriviaScanned(s,input,cur,ctx)
9734
- if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
10356
+ if(needsDeferredTriviaCommit(ctx))return skipDeferredTrivia(input,cur,ctx)
9735
10357
  return advanceTrivia(input,cur,ctx)
9736
10358
  }
9737
10359
  function _pushLeaf(ctx,value,s,e){pushCstLeaf(ctx,{_tag:'leaf',value,span:{start:s,end:e}})}
@@ -9907,6 +10529,24 @@ ${fast}
9907
10529
  ${scanned}
9908
10530
  }`;
9909
10531
  }
10532
+ function emitHoldTerm(callee, dst, t, l, skip) {
10533
+ const fast = `const ${t}v=${callee}(input,cur,ctx)
10534
+ if(${t}v===FAIL)return FAIL
10535
+ ${dst}=${t}v
10536
+ cur=EC.e`;
10537
+ if (l.tri === TRI_NONE) return fast;
10538
+ const held = `const ${t}s=${skip}(input,cur,ctx)
10539
+ const ${t}v=${callee}(input,${t}s,ctx)
10540
+ if(${t}v===FAIL)return FAIL
10541
+ ${dst}=${t}v
10542
+ cur=${t}s`;
10543
+ if (l.tri !== TRI_UNKNOWN) return held;
10544
+ return `if(ctx.trivia===undefined){
10545
+ ${fast}
10546
+ }else{
10547
+ ${held}
10548
+ }`;
10549
+ }
9910
10550
  function leadSkip(hasTrivia, leadTrivia, skip) {
9911
10551
  if (hasTrivia === "false") return "{}";
9912
10552
  const call = `itemStart=${skip}(input,itemStart,ctx)`;
@@ -9938,16 +10578,17 @@ function rebuildPools(cc, fx, disp, plan) {
9938
10578
  })
9939
10579
  };
9940
10580
  }
9941
- function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
10581
+ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, select) {
9942
10582
  const { code, k, fx, disp, dsp, triviaLabelled } = t;
9943
10583
  const swapLegal = !cfg.trackLines;
9944
10584
  const hostCst = cfg.hostCst;
9945
- const REC = prog.rec === 1 && cfg.tolerant;
10585
+ const REC2 = prog.rec === 1 && cfg.tolerant;
9946
10586
  if (cfg.coverage) throw new Unemittable("a coverage assembly");
9947
10587
  const roots = [...Object.values(prog.rules), ...extraIps];
9948
10588
  const reachable = [...reachableSites(code, roots)];
9949
10589
  const labels = computeSiteLabels(code, roots, hostCst);
9950
10590
  const scalarSpecs = /* @__PURE__ */ new Set();
10591
+ const nullable2 = /* @__PURE__ */ new Map();
9951
10592
  const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
9952
10593
  const largeChoiceLiteralFamilies = /* @__PURE__ */ new Map();
9953
10594
  const largeChoiceScalarSequences = /* @__PURE__ */ new Map();
@@ -10013,7 +10654,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
10013
10654
  const op = code[ip];
10014
10655
  sinkBits.set(
10015
10656
  ip,
10016
- op === OP_SCAN ? 3 : (op === OP_FIELD ? 1 : 0) | (op === OP_EXPECT || REC && (op === OP_REP || op === OP_REPV) ? 2 : 0)
10657
+ op === OP_SCAN ? 3 : (op === OP_FIELD ? 1 : 0) | (op === OP_EXPECT || REC2 && (op === OP_REP || op === OP_REPV) ? 2 : 0)
10017
10658
  );
10018
10659
  }
10019
10660
  const sinkKids = [];
@@ -10037,6 +10678,8 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
10037
10678
  };
10038
10679
  const bodies = [];
10039
10680
  const byIp = /* @__PURE__ */ new Map();
10681
+ const externals = [];
10682
+ const siteBytes = /* @__PURE__ */ new Map();
10040
10683
  const reached = /* @__PURE__ */ new Set();
10041
10684
  const prelude = [];
10042
10685
  const skipDefs = [];
@@ -10172,6 +10815,18 @@ return 1
10172
10815
  tokenDecisionRefs.set(dispatchIp, made);
10173
10816
  return made;
10174
10817
  }
10818
+ function gateMissTest(gip) {
10819
+ const resolved = t.cc[code[gip + 1]];
10820
+ const ci = classes.push([resolved]) - 1;
10821
+ classPlan.push([code[gip + 1]]);
10822
+ const cls = hoist("cl", `CLS[${ci}][0]`);
10823
+ return isAsciiOnlyClass(resolved) ? `${cls}.ascii[input.charCodeAt(pos)]!==1` : `!classHas(${cls},lead(input,pos))`;
10824
+ }
10825
+ function lookaheadMiss(child, miss) {
10826
+ if (code[child] !== OP_GATE || cfg.tolerant || cfg.probe) return "";
10827
+ return `if(${gateMissTest(child)}){${miss}}
10828
+ `;
10829
+ }
10175
10830
  function skipFor(l) {
10176
10831
  if (l.tri < 0) return "_skipTrivia";
10177
10832
  const ki = l.tri;
@@ -10182,8 +10837,8 @@ return 1
10182
10837
  const nm = `_sk${skipPool.size}`;
10183
10838
  skipPool.set(key, nm);
10184
10839
  if (!hasScan) {
10185
- skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return commitTriviaScan(scanTriviaCompact(input,cur,ctx))}` : `function ${nm}(input,cur,ctx){
10186
- if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
10840
+ skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return skipDeferredTrivia(input,cur,ctx)}` : `function ${nm}(input,cur,ctx){
10841
+ if(needsDeferredTriviaCommit(ctx))return skipDeferredTrivia(input,cur,ctx)
10187
10842
  return advanceTrivia(input,cur,ctx)}`);
10188
10843
  return nm;
10189
10844
  }
@@ -10228,9 +10883,17 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
10228
10883
  const target = resolveAlias(ip);
10229
10884
  const done = byIp.get(target);
10230
10885
  if (done !== void 0) return done;
10886
+ if (select !== void 0 && !select.has(target)) {
10887
+ const ext = `_px${target}`;
10888
+ byIp.set(target, ext);
10889
+ externals.push(target);
10890
+ return ext;
10891
+ }
10231
10892
  const fname = `_pf${target}`;
10232
10893
  byIp.set(target, fname);
10233
- bodies.push(lower(target, fname));
10894
+ const body = lower(target, fname);
10895
+ siteBytes.set(target, body.length);
10896
+ bodies.push(body);
10234
10897
  return fname;
10235
10898
  }
10236
10899
  function resolveAlias(ip) {
@@ -10250,9 +10913,7 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
10250
10913
  const op = code[ip];
10251
10914
  if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
10252
10915
  if (op === OP_RULE) return code[ip + 1];
10253
- if ((op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[ip + 3] === 0) && code[ip + 1] >= 0 && labels.at(ip).tri === code[ip + 1]) {
10254
- return code[ip + 2];
10255
- }
10916
+ if (scopeIsIdentity(code, ip, labels.at(ip))) return code[ip + 2];
10256
10917
  return void 0;
10257
10918
  }
10258
10919
  function lower(ip, fname) {
@@ -10370,28 +11031,58 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
10370
11031
  return `${head}EC.e=pos;return ''}`;
10371
11032
  case OP_GATE: {
10372
11033
  const child = link(code[ip + 2]);
11034
+ const xf = fxRef(code[ip + 3]);
11035
+ return `${head}
11036
+ if(${gateMissTest(ip)}){ctx._fe=pos;ctx._fx=${xf};return FAIL}
11037
+ return ${child}(input,pos,ctx)
11038
+ }`;
11039
+ }
11040
+ case OP_RGATE: {
11041
+ const child = link(code[ip + 2]);
11042
+ if (cfg.tolerant || cfg.probe) return `${head}
11043
+ return ${child}(input,pos,ctx)
11044
+ }`;
10373
11045
  const resolved = t.cc[code[ip + 1]];
10374
11046
  const ci = classes.push([resolved]) - 1;
10375
11047
  classPlan.push([code[ip + 1]]);
10376
11048
  const cls = hoist("cl", `CLS[${ci}][0]`);
10377
11049
  const xf = fxRef(code[ip + 3]);
10378
11050
  return `${head}
10379
- if(${staticBuild && isAsciiOnlyClass(resolved) ? `${cls}.ascii[input.charCodeAt(pos)]!==1` : `!classHas(${cls},lead(input,pos))`}){ctx._fe=pos;ctx._fx=${xf};return FAIL}
11051
+ const it=ctx._routed
11052
+ if(it!==undefined&&it.span.start===pos&&!classHas(${cls},lead(input,it.span.end))){ctx._fe=it.span.end;ctx._fx=${xf};return FAIL}
10380
11053
  return ${child}(input,pos,ctx)
10381
11054
  }`;
10382
11055
  }
10383
- case OP_XFORM: {
10384
- const fn = fnRef(code[ip + 1]);
11056
+ case OP_ARMGATE: {
11057
+ const pred = fnRef(code[ip + 1]);
10385
11058
  const child = link(code[ip + 2]);
11059
+ const xf = fxRef(code[ip + 3]);
10386
11060
  return `${head}
10387
- const v=${child}(input,pos,ctx)
10388
- if(v===FAIL)return FAIL
10389
- return ${fn}(v,{start:pos,end:EC.e})
11061
+ if(!${pred}(ctx.state)){ctx._fc=false;ctx._fe=-1;ctx._fx=${xf};return FAIL}
11062
+ return ${child}(input,pos,ctx)
10390
11063
  }`;
10391
11064
  }
10392
- case OP_LABEL: {
10393
- const child = link(code[ip + 1]);
10394
- const xf = fxRef(code[ip + 2]);
11065
+ case OP_WITHCTX: {
11066
+ const ki = code[ip + 1];
11067
+ const child = link(code[ip + 2]);
11068
+ return `${head}
11069
+ const saved=ctx.state
11070
+ ctx.state=${ki < 0 ? `${fnRef(~ki)}(saved)` : kRef(ki)}
11071
+ try{return ${child}(input,pos,ctx)}finally{ctx.state=saved}
11072
+ }`;
11073
+ }
11074
+ case OP_XFORM: {
11075
+ const fn = fnRef(code[ip + 1]);
11076
+ const child = link(code[ip + 2]);
11077
+ return `${head}
11078
+ const v=${child}(input,pos,ctx)
11079
+ if(v===FAIL)return FAIL
11080
+ return ${fn}(v,{start:pos,end:EC.e})
11081
+ }`;
11082
+ }
11083
+ case OP_LABEL: {
11084
+ const child = link(code[ip + 1]);
11085
+ const xf = fxRef(code[ip + 2]);
10395
11086
  return `${head}
10396
11087
  const v=${child}(input,pos,ctx)
10397
11088
  if(v===FAIL)ctx._fx=${xf}
@@ -10435,7 +11126,7 @@ if(v!==FAIL)return v
10435
11126
  const err={_tag:'parseError',span:${prog.lines === 1 ? "spanLines(ctx,pos,pos)" : "{start:pos,end:pos}"},expected:${xf}}
10436
11127
  const es=ctx._errors
10437
11128
  if(es!==undefined)es.push(err)
10438
- ${REC ? "if(ctx._tolerant===true)captureError(ctx,err)\n" : ""}ctx._fc=false
11129
+ ${REC2 ? "if(ctx._tolerant===true)captureError(ctx,err)\n" : ""}ctx._fc=false
10439
11130
  EC.e=pos
10440
11131
  return err
10441
11132
  }`;
@@ -10556,7 +11247,7 @@ return v
10556
11247
  }
10557
11248
  case OP_LEX_PROGRAM: {
10558
11249
  const programId = code[ip + 1];
10559
- const run = hoist("lexProgram", `LEXPROG[${programId}]`);
11250
+ const run2 = hoist("lexProgram", `LEXPROG[${programId}]`);
10560
11251
  const scanId = t.lexPrograms[programId].scan;
10561
11252
  if (scanId !== void 0) return `${head}
10562
11253
  const sTri=ctx.trivia,sKinds=ctx.triviaKindLabels,sScan=_pfScan
@@ -10574,7 +11265,7 @@ ctx._cstTriviaLog=undefined
10574
11265
  ctx._triviaLog=undefined
10575
11266
  ctx._rootTriviaLog=undefined
10576
11267
  let e
10577
- try{e=${run}(input,pos,ctx,SCANS[${scanId}])}finally{
11268
+ try{e=${run2}(input,pos,ctx,SCANS[${scanId}])}finally{
10578
11269
  _pfScan=sScan
10579
11270
  ctx.trivia=sTri
10580
11271
  ctx.triviaKindLabels=sKinds
@@ -10593,7 +11284,7 @@ EC.e=e
10593
11284
  return v
10594
11285
  }`;
10595
11286
  return `${head}
10596
- const e=${run}(input,pos,ctx)
11287
+ const e=${run2}(input,pos,ctx)
10597
11288
  if(e<0)return FAIL
10598
11289
  const v=input.slice(pos,e)
10599
11290
  if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
@@ -10604,7 +11295,7 @@ return v
10604
11295
  /* ── transaction ─────────────────────────────────────────────────────── */
10605
11296
  case OP_ATTEMPT: {
10606
11297
  const child = link(code[ip + 1]);
10607
- const clean = !REC && failureRollbackClean(prog, ip);
11298
+ const clean = !REC2 && failureRollbackClean(prog, ip);
10608
11299
  const p = tmp();
10609
11300
  return `${head}
10610
11301
  ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
@@ -10633,34 +11324,44 @@ return FAIL
10633
11324
  const xf = fxRef(code[ip + 2]);
10634
11325
  const p = tmp();
10635
11326
  return `${head}
10636
- ${emitMark(p, L.buf, L.raw, sinks)}
10637
- const v=${child}(input,pos,ctx)
11327
+ ${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${emitMark(p, L.buf, L.raw, sinks)}
11328
+ ${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
10638
11329
  ${emitRollback(p, L.buf, L.raw, sinks)}
10639
- if(v===FAIL){EC.e=pos;return null}
11330
+ ${cfg.probe ? "if(ctx._probe!==undefined)ctx._probe.best=pb??null\n" : ""}if(v===FAIL){EC.e=pos;return null}
10640
11331
  ctx._fe=pos
10641
11332
  ctx._fx=${xf}
10642
11333
  return FAIL
10643
11334
  }`;
10644
11335
  }
10645
11336
  case OP_PEEK: {
11337
+ const scalarChild = scalarTerminalPeekChild(code, ip);
11338
+ if (scalarChild >= 0) {
11339
+ const recognize = recognizerRef(code[scalarChild + 1]);
11340
+ const xf2 = fxRef(code[ip + 2]);
11341
+ return `${head}
11342
+ if(${recognize}(input,pos)<0){ctx._fe=pos;ctx._fx=${xf2};return FAIL}
11343
+ EC.e=pos
11344
+ return null
11345
+ }`;
11346
+ }
10646
11347
  const child = link(code[ip + 1]);
10647
11348
  const xf = fxRef(code[ip + 2]);
10648
11349
  const p = tmp();
10649
11350
  return `${head}
10650
- ${emitMark(p, L.buf, L.raw, sinks)}
10651
- const v=${child}(input,pos,ctx)
11351
+ ${lookaheadMiss(code[ip + 1], `ctx._fe=pos;ctx._fx=${xf};return FAIL`)}${emitMark(p, L.buf, L.raw, sinks)}
11352
+ ${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
10652
11353
  ${emitRollback(p, L.buf, L.raw, sinks)}
10653
- if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
11354
+ ${cfg.probe ? "if(ctx._probe!==undefined)ctx._probe.best=pb??null\n" : ""}if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
10654
11355
  EC.e=pos
10655
11356
  return null
10656
11357
  }`;
10657
11358
  }
10658
11359
  case OP_OPT: {
10659
11360
  const child = link(code[ip + 1]);
10660
- const clean = !REC && failureRollbackClean(prog, ip);
11361
+ const clean = !REC2 && failureRollbackClean(prog, ip);
10661
11362
  const p = tmp();
10662
11363
  return `${head}
10663
- ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
11364
+ ${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
10664
11365
  ctx._fc=false
10665
11366
  const v=${child}(input,pos,ctx)
10666
11367
  if(v===FAIL){
@@ -10687,15 +11388,15 @@ return v
10687
11388
  const childIp = code[base + i];
10688
11389
  kids.push(code[childIp] === OP_ADJ ? "" : link(childIp));
10689
11390
  }
10690
- const sy = REC ? `${tmp()}sy` : "";
11391
+ const sy = REC2 ? `${tmp()}sy` : "";
10691
11392
  const pub = (i) => {
10692
11393
  const s = sentRef(code[base + n + i]);
10693
11394
  return s === "undefined" ? `ctx._sync=${sy}` : `ctx._sync=${s}??${sy}`;
10694
11395
  };
10695
11396
  const parts = [head];
10696
- if (REC) parts.push(`const ${sy}=ctx._sync`, "try{", pub(0));
11397
+ if (REC2) parts.push(`const ${sy}=ctx._sync`, "try{", pub(0));
10697
11398
  parts.push(`const v0=${kids[0]}(input,pos,ctx)`, "if(v0===FAIL)return FAIL");
10698
- const close = () => REC ? `${parts.join("\n")}
11399
+ const close = () => REC2 ? `${parts.join("\n")}
10699
11400
  }finally{ctx._sync=${sy}}
10700
11401
  }` : `${parts.join("\n")}
10701
11402
  }`;
@@ -10708,7 +11409,7 @@ return v
10708
11409
  for (let i = 1; i < n; i++) {
10709
11410
  const vn = `v${i}`;
10710
11411
  parts.push(`let ${vn}`);
10711
- if (REC) parts.push(pub(i));
11412
+ if (REC2) parts.push(pub(i));
10712
11413
  const childIp = code[base + i];
10713
11414
  if (code[childIp] === OP_ADJ) {
10714
11415
  const negated = code[childIp + 1] === 1;
@@ -10721,7 +11422,7 @@ return v
10721
11422
  );
10722
11423
  } else {
10723
11424
  const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
10724
- parts.push(emitTerm(callee, vn, tmp(), L, skipFor(L)));
11425
+ parts.push(holdsGap(code, k, base, n, i, nullable2) ? emitHoldTerm(callee, vn, tmp(), L, skipFor(L)) : emitTerm(callee, vn, tmp(), L, skipFor(L)));
10725
11426
  }
10726
11427
  names.push(vn);
10727
11428
  }
@@ -10741,7 +11442,7 @@ return v
10741
11442
  const asc = hoist("as", `DISP[${di}].ascii`);
10742
11443
  const hiArr = table.hi;
10743
11444
  const armSwitch = arms.map((a, i) => `case ${i}:v=${a}(input,pos,ctx);break`).join("\n");
10744
- const directAscii = staticBuild && table.hi.length === 0;
11445
+ const directAscii = table.hi.length === 0;
10745
11446
  return `${head}
10746
11447
  const c=${directAscii ? "input.charCodeAt(pos)" : "lead(input,pos)"}
10747
11448
  let arm=-1
@@ -10768,7 +11469,7 @@ return FAIL
10768
11469
  const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
10769
11470
  const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
10770
11471
  const maskable = n <= 32;
10771
- const directAsciiMask = staticBuild && maskable && gates.every(isAsciiOnlyClass);
11472
+ const directAsciiMask = maskable && gates.every(isAsciiOnlyClass);
10772
11473
  const gateRefs = directAsciiMask ? [] : Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
10773
11474
  const tokenCandidate = tokenChoiceCandidates.get(ip);
10774
11475
  const pretests = Array.from({ length: n }, (_, i) => {
@@ -10793,7 +11494,7 @@ return FAIL
10793
11494
  if (maskable) maskPlan.push(~di);
10794
11495
  const p = tmp();
10795
11496
  const encodedRollbackMask = choiceRollbackMask(prog, ip) ?? -1;
10796
- const rollbackMask = REC ? -1 : encodedRollbackMask;
11497
+ const rollbackMask = REC2 ? -1 : encodedRollbackMask;
10797
11498
  const hasRollback = rollbackMask !== 0;
10798
11499
  const startFailureExact = arms.every((_arm, i) => {
10799
11500
  const terminal = leadingScalarTerminal(code, code[base + i], 0, false);
@@ -10810,7 +11511,7 @@ return FAIL
10810
11511
  if (choiceCannotCommit(prog, ip) && !startFailureExact) {
10811
11512
  const deepAt = Array.from({ length: n }, () => tmp());
10812
11513
  const deepFx = Array.from({ length: n }, () => tmp());
10813
- const remember = (i, at, expectedSet) => `${deepAt[i]}=${at};${deepFx[i]}=${expectedSet}`;
11514
+ const remember2 = (i, at, expectedSet) => `${deepAt[i]}=${at};${deepFx[i]}=${expectedSet}`;
10814
11515
  const lazyArms = (ascii) => arms.map((arm, i) => {
10815
11516
  const pretest = pretests[i];
10816
11517
  const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
@@ -10822,13 +11523,13 @@ return FAIL
10822
11523
  if(${decision}===0){
10823
11524
  ctx._fc=false
10824
11525
  {const at=_pfTokEnd
10825
- ${remember(i, "at", pretest.token.expected)}}
11526
+ ${remember2(i, "at", pretest.token.expected)}}
10826
11527
  }`;
10827
11528
  const sequenceMiss = pretest?.sequence === void 0 ? "" : `
10828
11529
  else if(${ascii ? `(bits&${1 << i})!==0&&` : ""}${decision}<0){
10829
11530
  ctx._fc=false
10830
11531
  {const at=_pfSeqEnd
10831
- ${remember(i, "at", pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("") + pretest.sequence.expected.at(-1))}}
11532
+ ${remember2(i, "at", pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("") + pretest.sequence.expected.at(-1))}}
10832
11533
  }`;
10833
11534
  return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
10834
11535
  `}if(${gate2}){
@@ -10836,7 +11537,7 @@ ctx._fc=false
10836
11537
  {const v=${arm}(input,pos,ctx)
10837
11538
  if(v!==FAIL)return v}
10838
11539
  {const at=ctx._fe??pos
10839
- ${remember(i, "at", "ctx._fx")}}
11540
+ ${remember2(i, "at", "ctx._fx")}}
10840
11541
  ${rollbackFor(i)}
10841
11542
  }${routeMiss}${sequenceMiss}`;
10842
11543
  }).join("\n");
@@ -10949,7 +11650,7 @@ const bits=${maskName}[${directAsciiMask ? "c" : "c<0?128:c"}]
10949
11650
  if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
10950
11651
  ${startFailureExact ? "" : "let prev=0"}
10951
11652
  ${maskArms}
10952
- ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${n},prev,acc)`}
11653
+ ${startFailureExact ? "" : `if(best===pos&&prev!==0)acc=${catchName}(${n},prev,acc)`}
10953
11654
  ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
10954
11655
  return FAIL
10955
11656
  }
@@ -11041,14 +11742,14 @@ return [key,v]
11041
11742
  const collect = op === OP_REP;
11042
11743
  let itemCls;
11043
11744
  let itemAscii = false;
11044
- if (!REC) {
11745
+ if (!REC2) {
11045
11746
  const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
11046
11747
  if (itemClassIndex >= 0) {
11047
11748
  const resolved = t.cc[itemClassIndex];
11048
11749
  const ci = classes.push([resolved]) - 1;
11049
11750
  classPlan.push([itemClassIndex]);
11050
11751
  itemCls = hoist("ri", `CLS[${ci}][0]`);
11051
- itemAscii = staticBuild && isAsciiOnlyClass(resolved);
11752
+ itemAscii = isAsciiOnlyClass(resolved);
11052
11753
  }
11053
11754
  }
11054
11755
  const itemMiss = (at) => itemAscii ? `${itemCls}.ascii[input.charCodeAt(${at})]!==1` : `!classHas(${itemCls},lead(input,${at}))`;
@@ -11089,11 +11790,11 @@ ${p}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
11089
11790
  ${p}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${markSinks}
11090
11791
  }`;
11091
11792
  const my = `${p}my`;
11092
- const recFx = REC ? fxRef(code[ip + 6]) : "";
11093
- const sepSent = REC ? sentRef(code[ip + 7]) : "undefined";
11793
+ const recFx = REC2 ? fxRef(code[ip + 6]) : "";
11794
+ const sepSent = REC2 ? sentRef(code[ip + 7]) : "undefined";
11094
11795
  const recSent = sep2 === void 0 ? my : sepSent === "undefined" ? `orSentinel(${my},undefined)` : `orSentinel(${sepSent}??${my},${sepSent}===undefined?undefined:${my})`;
11095
11796
  const recGate = sep2 !== void 0 || min === 0 ? "" : `count>=${min}&&`;
11096
- const recBranch = !REC ? "" : `if(ctx._tolerant===true&&${my}!==undefined&&${recGate}!matchesAt(${my},input,itemStart,ctx)){
11797
+ const recBranch = !REC2 ? "" : `if(ctx._tolerant===true&&${my}!==undefined&&${recGate}!matchesAt(${my},input,itemStart,ctx)){
11097
11798
  ${sep2 === void 0 ? `${rb}
11098
11799
  ` : ""}const rr=recoverScan(input,itemStart,ctx,${recSent},${recFx})
11099
11800
  ${collect ? "out.push(rr.error)\n" : ""}captureError(ctx,rr.error)
@@ -11104,7 +11805,7 @@ continue
11104
11805
  `;
11105
11806
  return `${head}
11106
11807
  const out=${collect ? "[]" : "undefined"}
11107
- ${knownTrivia === void 0 ? "const hasTrivia=ctx.trivia!==undefined\n" : ""}${L.buf ? "" : "const needMark=_rollbackNeeded(ctx)\n"}${REC ? `const ${my}=ctx._sync
11808
+ ${knownTrivia === void 0 ? "const hasTrivia=ctx.trivia!==undefined\n" : ""}${L.buf ? "" : "const needMark=_rollbackNeeded(ctx)\n"}${REC2 ? `const ${my}=ctx._sync
11108
11809
  ` : ""}${itemCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
11109
11810
  `}let cur=pos
11110
11811
  let count=0
@@ -11143,7 +11844,7 @@ ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
11143
11844
  `}ctx._fc=false
11144
11845
  const v=${child}(input,itemStart,ctx)
11145
11846
  if(v===FAIL){
11146
- ${REC ? `if(ctx._fc===true){
11847
+ ${REC2 ? `if(ctx._fc===true){
11147
11848
  ${rb}
11148
11849
  return FAIL
11149
11850
  }
@@ -11204,6 +11905,26 @@ return nd
11204
11905
  const trailingTrivia = (flags & 128) !== 0;
11205
11906
  const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
11206
11907
  const leanFlags = flags & ~128;
11908
+ if (build !== void 0 && passCollapse(code, ip, hostCst)) {
11909
+ return `${head}
11910
+ const v=${child}(input,pos,ctx)
11911
+ if(v!==undefined)return v
11912
+ return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
11913
+ }`;
11914
+ }
11915
+ const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
11916
+ const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(labels.at(code[ip + 2]).tri, t.trivia);
11917
+ const gp = gated !== void 0 && triviaLead !== void 0 && triviaLead.length <= 16 ? `const gc=lead(input,pos)
11918
+ if(!(${[
11919
+ ...gated.leads.map((g) => `!(${gateMissTest(g)})`),
11920
+ ...gated.lits.map((i) => `gc===${k[i].codePointAt(0)}`),
11921
+ ...triviaLead.map((r) => r.lo === r.hi ? `gc===${r.lo}` : `(gc>=${r.lo}&&gc<=${r.hi})`)
11922
+ ].join("||") || "false"})){
11923
+ const gv=${link(gated.last)}(input,pos,ctx)
11924
+ if(gv!==undefined)return gv
11925
+ return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
11926
+ }
11927
+ ` : "";
11207
11928
  if (!hostCst && !tracked && build !== void 0 && proj < 0 && (leanFlags === 2 || (flags === 18 || flags === 34))) {
11208
11929
  const fields = flags === 18;
11209
11930
  const collapseChildren = flags === 34;
@@ -11238,7 +11959,7 @@ sCh.push(nd)
11238
11959
  if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
11239
11960
  }`;
11240
11961
  return `${head}
11241
- const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
11962
+ ${gp}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
11242
11963
  const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
11243
11964
  const flat=[]
11244
11965
  ctx._cstBuf=undefined
@@ -11274,7 +11995,7 @@ return nd
11274
11995
  const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
11275
11996
  const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
11276
11997
  const ty = q(type);
11277
- const stArg = readsState ? "st" : "(ctx.state!==undefined?Object.assign({},ctx.state):undefined)";
11998
+ const stArg = "ctx.state";
11278
11999
  const hostCall = `_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,${stArg},${tags})`;
11279
12000
  let value;
11280
12001
  if (proj >= 0) {
@@ -11313,7 +12034,7 @@ const hostKids=kids
11313
12034
  const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
11314
12035
  const tlog=buf.tl??EMPTY_TLOG`;
11315
12036
  return `${head}
11316
- const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
12037
+ ${!hostCst && !tracked ? gp : ""}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
11317
12038
  const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf
11318
12039
  ${openCapture}
11319
12040
  ctx.captureTrivia=${captureWide}
@@ -11335,7 +12056,7 @@ ctx.captureTrivia=sCap
11335
12056
  if(v===FAIL)return FAIL
11336
12057
  const end=EC.e
11337
12058
  const span=${tracked ? "spanLines(ctx,pos,end)" : "{start:pos,end}"}
11338
- const st=${readsState ? "(ctx.state!==undefined?Object.assign({},ctx.state):undefined)" : "undefined"}
12059
+ const st=${readsState ? "ctx.state" : "undefined"}
11339
12060
  let nd
11340
12061
  ${unwrap ? "if(kids.length===1)nd=unwrapChild(kids[0])\nelse " : ""}${collapse ? "if(kids.length===1)nd=kids[0]\nelse " : ""}${collapsible ? `if(_pfHost!==undefined&&_pfHost._parsemanCstCollapse!==undefined&&kids.length===1&&rawKids.length===1&&_pfHost._parsemanCstCollapse(${ty},kids[0],kids,rawKids))nd=kids[0]
11341
12062
  else ` : ""}{${value}}
@@ -11348,21 +12069,57 @@ return nd
11348
12069
  throw new Unemittable(`OP_${OP_NAMES[op] ?? String(op)}`);
11349
12070
  }
11350
12071
  }
12072
+ const served = (ip) => select === void 0 || select.has(resolveAlias(ip));
11351
12073
  const ruleEntries = [];
11352
12074
  for (const [rname, entryIp] of Object.entries(prog.rules)) {
12075
+ if (!served(entryIp)) continue;
11353
12076
  const target = link(entryIp);
11354
12077
  const rn = `_r_${rname.replace(/[^A-Za-z0-9_$]/g, "_")}`;
11355
12078
  bodies.push(`const ${rn}=${target}`);
11356
12079
  ruleEntries.push(`${q(rname)}:${rn}`);
11357
12080
  }
11358
12081
  const extra = [];
11359
- for (const ip of extraIps) extra.push(`${ip}:${link(ip)}`);
12082
+ const exported = /* @__PURE__ */ new Set();
12083
+ for (const ip of extraIps) {
12084
+ if (!served(ip)) continue;
12085
+ exported.add(ip);
12086
+ extra.push(`${ip}:${link(ip)}`);
12087
+ }
12088
+ if (select !== void 0) {
12089
+ const kids = [];
12090
+ for (const ip of reachable) {
12091
+ if (select.has(resolveAlias(ip))) continue;
12092
+ kids.length = 0;
12093
+ childSlots(code, ip, kids);
12094
+ for (const kid of kids) {
12095
+ const target = resolveAlias(kid);
12096
+ if (!select.has(target) || exported.has(target)) continue;
12097
+ exported.add(target);
12098
+ extra.push(`${target}:${link(target)}`);
12099
+ }
12100
+ }
12101
+ }
12102
+ const hybrid = select === void 0 ? "" : `,
12103
+ ext:[${externals.join(",")}],
12104
+ bind:function(xs,ps){_xScan=xs
12105
+ ${externals.map((ip, i) => `_xp${ip}=ps[${i}]`).join("\n")}},
12106
+ scan:function(s){const o=_pfScan;_pfScan=s;return o}`;
12107
+ const scannerFor = (ip) => {
12108
+ const ki = labels.at(ip).tri;
12109
+ if (ki === TRI_UNKNOWN) return "_pfScan";
12110
+ if (ki === TRI_NONE) return "null";
12111
+ return swapLegal && !triviaLabelled[ki] && t.triviaScan[ki] != null ? hoist("ts", `TRIVIASCAN[${ki}]`) : "null";
12112
+ };
12113
+ const externalDefs = select === void 0 ? "" : `let _xScan
12114
+ ${externals.map((ip) => `let _xp${ip}
12115
+ function _px${ip}(input,pos,ctx){const o=_xScan(${scannerFor(ip)});const v=_xp${ip}(input,pos,ctx);_xScan(o);return v}`).join("\n")}
12116
+ `;
11360
12117
  const source = `${RUNTIME_PRELUDE}${needsNoRawPrelude ? NO_RAW_RUNTIME_PRELUDE : ""}
11361
12118
  ${prelude.join("\n")}
11362
12119
  ${skipDefs.join("\n")}
11363
12120
  ${choiceDefs.join("\n")}
11364
12121
  ${bodies.join("\n")}
11365
- function _begin(ctx){
12122
+ ${externalDefs}function _begin(ctx){
11366
12123
  const host=ctx.build
11367
12124
  if(_pfDepth>0)_pfFrames.push([_pfScan,_pfHost,EC.e])
11368
12125
  _pfDepth++
@@ -11389,7 +12146,7 @@ pieces:{${ruleEntries.join(",")}},
11389
12146
  byIp:{${extra.join(",")}},
11390
12147
  end:function(){return EC.e},
11391
12148
  begin:_begin,
11392
- finish:_finish
12149
+ finish:_finish${hybrid}
11393
12150
  }`;
11394
12151
  return {
11395
12152
  source,
@@ -11397,6 +12154,7 @@ finish:_finish
11397
12154
  masks,
11398
12155
  classes,
11399
12156
  armExpected,
12157
+ siteBytes,
11400
12158
  plan: { classes: classPlan, armExpected: armExpectedPlan, masks: maskPlan }
11401
12159
  };
11402
12160
  }
@@ -11495,20 +12253,20 @@ function lines(prefix, body, options = {}) {
11495
12253
  const c = ctx;
11496
12254
  const probe = createDetachedParseContext(false, ctx.state);
11497
12255
  probe.lineView = c.lineView;
11498
- const run = [];
12256
+ const run2 = [];
11499
12257
  const parts = [];
11500
12258
  let offset = 0;
11501
12259
  for (let start = pos; start < input.length || start === pos; ) {
11502
12260
  let end2 = input.indexOf("\n", start);
11503
12261
  if (end2 < 0) end2 = input.length;
11504
12262
  probe._columnsSplit = void 0;
11505
- const head = (run.length === 0 ? opening : prefix).parse(input, start, probe);
12263
+ const head = (run2.length === 0 ? opening : prefix).parse(input, start, probe);
11506
12264
  let content;
11507
12265
  let joined;
11508
12266
  if (head.ok && head.span.end <= end2) {
11509
12267
  content = head.span.end;
11510
12268
  joined = "prefix";
11511
- } else if (run.length === 0) {
12269
+ } else if (run2.length === 0) {
11512
12270
  return { ok: false, expected: head.ok ? ["line prefix"] : head.expected, span: { start, end: start } };
11513
12271
  } else if (lazy !== void 0 && lazy.parse(input, start, probe).ok) {
11514
12272
  content = start;
@@ -11517,7 +12275,7 @@ function lines(prefix, body, options = {}) {
11517
12275
  const mark = probe._columnsSplit;
11518
12276
  const here = columnAt(input, content, c);
11519
12277
  const split = joined === "prefix" && mark !== void 0 && mark.at === content ? mark.split : here.split;
11520
- run.push({ offset, source: content, end: end2, column: here.column + (split - here.split), split, lazy: joined === "lazy" });
12278
+ run2.push({ offset, source: content, end: end2, column: here.column + (split - here.split), split, lazy: joined === "lazy" });
11521
12279
  const text = input.slice(content, end2);
11522
12280
  const newline = end2 < input.length;
11523
12281
  parts.push(newline ? `${text}
@@ -11526,11 +12284,11 @@ function lines(prefix, body, options = {}) {
11526
12284
  start = end2 + 1;
11527
12285
  if (!newline) break;
11528
12286
  }
11529
- const view = { lines: run, parent: c.lineView };
12287
+ const view = { lines: run2, parent: c.lineView };
11530
12288
  const saved = c.lineView, starts = c._lineStarts, lineIndex = c._lineIndex, scanned = c._lineScannedTo, probing = c._probe;
11531
12289
  const errors = c._errors?.length ?? 0;
11532
12290
  let cursor = -1;
11533
- if (probing !== void 0) for (const line2 of run) {
12291
+ if (probing !== void 0) for (const line2 of run2) {
11534
12292
  if (probing.offset >= line2.source && probing.offset <= line2.end) {
11535
12293
  cursor = line2.offset + probing.offset - line2.source;
11536
12294
  break;
@@ -11563,8 +12321,8 @@ function lines(prefix, body, options = {}) {
11563
12321
  }
11564
12322
  const stop = result.span.end;
11565
12323
  const index = lineIndexAt(view, stop);
11566
- const line = run[index];
11567
- const end = stop === line.offset && index > 0 ? run[index - 1].end + 1 : stop - line.offset > line.end - line.source ? line.end + 1 : line.source + (stop - line.offset);
12324
+ const line = run2[index];
12325
+ const end = stop === line.offset && index > 0 ? run2[index - 1].end + 1 : stop - line.offset > line.end - line.source ? line.end + 1 : line.source + (stop - line.offset);
11568
12326
  recordLineRangeFromContext(c, input, pos, end);
11569
12327
  return { ok: true, value: result.value, span: { start: pos, end } };
11570
12328
  }
@@ -11827,42 +12585,202 @@ function escapeClassChar(ch2) {
11827
12585
  return ch2.replace(/[\\\]^-]/g, "\\$&");
11828
12586
  }
11829
12587
 
11830
- // src/table/run-support.ts
11831
- function lineCol(ctx, offset) {
11832
- const starts = ctx._lineStarts ?? [0];
11833
- let lo = 0, hi = starts.length - 1;
11834
- while (lo < hi) {
11835
- const mid = lo + hi + 1 >> 1;
11836
- if (starts[mid] <= offset) lo = mid;
11837
- else hi = mid - 1;
12588
+ // src/table/trivia-gap.ts
12589
+ function skipDeferredTrivia(input, cur, ctx) {
12590
+ const triviaP = ctx.trivia;
12591
+ const plain = ctx.trackLines !== true && ctx.captureTrivia !== true;
12592
+ const gap = ctx._gap;
12593
+ if (plain && gap !== void 0 && cur === gap.at && input === gap.input && triviaP === gap.of && ctx._rootTriviaCapture === gap.root && ctx.state === gap.state && ctx._rootTriviaKindIndex === gap.rootKinds && ctx._triviaLog === gap.log) return gap.end;
12594
+ const end = clearRunEnd(input, cur, ctx, triviaP, plain);
12595
+ if (end >= 0) {
12596
+ remember(cur, end, ctx, input, triviaP);
12597
+ return end;
11838
12598
  }
11839
- return [lo + 1, offset - starts[lo] + 1];
12599
+ const scan = scanTriviaCompact(input, cur, ctx);
12600
+ if (typeof scan !== "number") return commitTriviaScan(scan);
12601
+ if (plain) remember(cur, scan, ctx, input, triviaP);
12602
+ return scan;
11840
12603
  }
11841
- function spanLines(ctx, start, end) {
11842
- const s = lineCol(ctx, start), e = lineCol(ctx, end);
11843
- return { start, end, startLine: s[0], startColumn: s[1], endLine: e[0], endColumn: e[1] };
12604
+ function clearRunEnd(input, cur, ctx, triviaP, plain) {
12605
+ const rootKinds = ctx._rootTriviaKindIndex;
12606
+ const spec = triviaP?._meta.labeledTriviaSpec;
12607
+ if (!plain || triviaP === void 0 || spec == null || rootKinds === void 0 || ctx._triviaLog !== void 0) return -1;
12608
+ if (spec.rootKinds !== rootKinds) prime(spec, triviaP, rootKinds);
12609
+ const fast = spec.rootScan;
12610
+ if (fast === null) return -1;
12611
+ const end = fast(input, cur);
12612
+ return ctx._rootTriviaCapture === false || clearOf(spec.rootLeaders, input, cur, end) ? end : -1;
12613
+ }
12614
+ function remember(cur, end, ctx, input, triviaP) {
12615
+ const gap = ctx._gap;
12616
+ if (gap === void 0) {
12617
+ ctx._gap = { at: cur, end, input, of: triviaP, root: ctx._rootTriviaCapture, rootKinds: ctx._rootTriviaKindIndex, log: ctx._triviaLog, state: ctx.state };
12618
+ return;
12619
+ }
12620
+ gap.at = cur;
12621
+ gap.end = end;
12622
+ gap.input = input;
12623
+ gap.of = triviaP;
12624
+ gap.root = ctx._rootTriviaCapture;
12625
+ gap.rootKinds = ctx._rootTriviaKindIndex;
12626
+ gap.log = ctx._triviaLog;
12627
+ gap.state = ctx.state;
11844
12628
  }
11845
- function rawEntry(v, input, s, e) {
11846
- if (typeof v === "object" && v !== null) {
11847
- const tg = v._tag;
11848
- if (tg === "node" || tg === "leaf" || tg === "parseError") return v;
12629
+ function prime(spec, triviaP, rootKinds) {
12630
+ const ranges = [];
12631
+ let bounded = true;
12632
+ for (const arm of spec.arms) {
12633
+ if (rootKinds[arm.label] === void 0) continue;
12634
+ const fs3 = arm.parser._meta.firstSet;
12635
+ if (fs3.kind === "any") bounded = false;
12636
+ else if (fs3.kind === "ranges") ranges.push(...fs3.ranges);
12637
+ }
12638
+ const classified = triviaP._meta.triviaScanner;
12639
+ spec.rootKinds = rootKinds;
12640
+ spec.rootLeaders = ranges;
12641
+ spec.rootScan = !bounded ? null : classified === void 0 ? fastTriviaScanner(triviaP) : classified;
12642
+ }
12643
+ function clearOf(ranges, input, from, to) {
12644
+ for (let i = from; i < to; i++) {
12645
+ const c = input.charCodeAt(i);
12646
+ if (c >= 55296 && c <= 57343) return false;
12647
+ for (const r of ranges) if (c >= r.lo && c <= r.hi) return false;
11849
12648
  }
11850
- return {
11851
- _tag: "leaf",
11852
- value: typeof v === "string" ? v : typeof v === "object" && v !== null ? input.slice(s, e) : "",
11853
- span: { start: s, end: e }
11854
- };
12649
+ return true;
11855
12650
  }
11856
- function lead(input, pos) {
11857
- if (pos >= input.length) return -1;
11858
- const c = input.charCodeAt(pos);
11859
- if (c < 55296 || c > 56319) return c;
11860
- return input.codePointAt(pos) ?? c;
12651
+
12652
+ // src/table/fail-clean.ts
12653
+ function passChild(code, ip) {
12654
+ switch (code[ip]) {
12655
+ case OP_RULE:
12656
+ case OP_LABEL:
12657
+ case OP_COV:
12658
+ case OP_TOKEN:
12659
+ return code[ip + 1];
12660
+ case OP_GATE:
12661
+ case OP_NODE:
12662
+ case OP_NODE_TRACK:
12663
+ case OP_XFORM:
12664
+ case OP_FIELD:
12665
+ case OP_SCOPE:
12666
+ case OP_SCOPE_CAP:
12667
+ case OP_SCOPE_PLAIN:
12668
+ case OP_WITHCTX:
12669
+ case OP_LEAF:
12670
+ case OP_SOURCE_LEAF:
12671
+ return code[ip + 2];
12672
+ default:
12673
+ return -1;
12674
+ }
12675
+ }
12676
+ function seqCount(code, ip) {
12677
+ const op = code[ip];
12678
+ return op === OP_SEQ || op === OP_SEQV ? ip + 1 : op === OP_SEQX ? ip + 2 : -1;
12679
+ }
12680
+ function failCleanAnalysis(code) {
12681
+ const cleanAt = new Uint8Array(code.length);
12682
+ const neverAt = new Uint8Array(code.length);
12683
+ const neverFails = (ip) => {
12684
+ const hit = neverAt[ip];
12685
+ if (hit !== 0) return hit === 1;
12686
+ neverAt[ip] = 3;
12687
+ let out = false;
12688
+ const op = code[ip];
12689
+ if (op === OP_OPT || op === OP_EMPTY || op === OP_EXPECT) out = true;
12690
+ else if (op === OP_REP || op === OP_REPV) out = code[ip + 2] === 0;
12691
+ else {
12692
+ const at = seqCount(code, ip);
12693
+ if (at >= 0) {
12694
+ out = true;
12695
+ for (let i = 1, n = code[at]; out && i <= n; i++) out = neverFails(code[at + i]);
12696
+ } else if (op !== OP_GATE) {
12697
+ const c = passChild(code, ip);
12698
+ out = c >= 0 && neverFails(c);
12699
+ }
12700
+ }
12701
+ neverAt[ip] = out ? 1 : 2;
12702
+ return out;
12703
+ };
12704
+ const clean = (ip) => {
12705
+ const hit = cleanAt[ip];
12706
+ if (hit !== 0) return hit === 1;
12707
+ cleanAt[ip] = 3;
12708
+ let out = false;
12709
+ switch (code[ip]) {
12710
+ // A terminal pushes its leaf only on a match; NOT/PEEK/ATTEMPT restore
12711
+ // their own mark; OPT, EMPTY and EXPECT do not fail uncommitted.
12712
+ case OP_LIT:
12713
+ case OP_RX:
12714
+ case OP_LIT_TRACK:
12715
+ case OP_RX_TRACK:
12716
+ case OP_LIT_CI:
12717
+ case OP_LIT_CI_TRACK:
12718
+ case OP_GUARD:
12719
+ case OP_NOT:
12720
+ case OP_PEEK:
12721
+ case OP_ATTEMPT:
12722
+ case OP_EMPTY:
12723
+ case OP_OPT:
12724
+ case OP_EXPECT:
12725
+ out = true;
12726
+ break;
12727
+ // Min 0 does not fail uncommitted; min 1 fails only with no item kept, and
12728
+ // restores the failed item itself.
12729
+ case OP_REP:
12730
+ case OP_REPV:
12731
+ out = code[ip + 2] <= 1;
12732
+ break;
12733
+ // Only the first term may fail: a later one fails after the terms before it
12734
+ // wrote, and after the trivia scanned in front of it.
12735
+ case OP_SEQ:
12736
+ case OP_SEQV:
12737
+ case OP_SEQX: {
12738
+ const at = seqCount(code, ip);
12739
+ const n = code[at];
12740
+ out = n > 0 && clean(code[at + 1]);
12741
+ for (let i = 2; out && i <= n; i++) out = neverFails(code[at + i]);
12742
+ break;
12743
+ }
12744
+ case OP_CHOICE: {
12745
+ out = true;
12746
+ for (let i = 0, n = code[ip + 2]; out && i < n; i++) out = clean(code[ip + 4 + i]);
12747
+ break;
12748
+ }
12749
+ case OP_ROUTED:
12750
+ out = code[ip + 1] < 0 || clean(code[ip + 1]);
12751
+ break;
12752
+ // An arm's failure and the fallback's are committed; only the selector's is
12753
+ // not, and without a fallback an unknown key fails after the selector wrote.
12754
+ case OP_DISPATCH:
12755
+ out = code[ip + 3] >= 0 && clean(code[ip + 1]);
12756
+ break;
12757
+ default: {
12758
+ const c = passChild(code, ip);
12759
+ out = c >= 0 && clean(c);
12760
+ }
12761
+ }
12762
+ cleanAt[ip] = out ? 1 : 2;
12763
+ return out;
12764
+ };
12765
+ return clean;
11861
12766
  }
11862
12767
 
11863
12768
  // src/cst/host-mode.ts
11864
12769
  var FUSED_HOST_MODE = /* @__PURE__ */ Symbol.for("parseman.fusedHostMode");
11865
12770
  var FUSED_HOST_ELIDED = /* @__PURE__ */ Symbol.for("parseman.fusedHostElided");
12771
+ function assertHostModeCompatible(mode, build, hostBranchElided = true) {
12772
+ const isCstHost = build?._parsemanCstOutput === true;
12773
+ if (mode === "ast" && isCstHost && hostBranchElided) {
12774
+ throw new Error(
12775
+ "parseman: this parser was compiled for host mode \"ast\" (the default), so its nodes build through their own `build` callbacks and no positioned-CST branch was emitted. It cannot be driven with a positioned-CST host (cstBuildHost / a language-service host). Compile a second artifact from the SAME grammar with `compile(grammar, { hostMode: 'cst' })` \u2014 or, under the macro, a second `rules({ hostMode: 'cst' }, factory)` call site \u2014 and drive that one instead."
12776
+ );
12777
+ }
12778
+ if (mode === "cst" && !isCstHost) {
12779
+ throw new Error(
12780
+ 'parseman: this parser was compiled for host mode "cst", so every node builds through a positioned-CST `ctx.build` host. Pass one (e.g. `{ build: cstBuildHost }`), or use an artifact compiled with the default `hostMode: "ast"` to get the grammar\'s own AST.'
12781
+ );
12782
+ }
12783
+ }
11866
12784
 
11867
12785
  // src/grammar-metadata.ts
11868
12786
  var GRAMMAR_COVERAGE_DEFINITIONS = /* @__PURE__ */ Symbol.for("parseman.grammarCoverageDefinitions");
@@ -12008,7 +12926,8 @@ function assemble(t, prog, cfg) {
12008
12926
  const triviaScan = t.triviaScan;
12009
12927
  const swapLegal = !cfg.trackLines;
12010
12928
  const hostCst = cfg.hostCst;
12011
- const REC = prog.rec === 1 && cfg.tolerant;
12929
+ const REC2 = prog.rec === 1 && cfg.tolerant;
12930
+ const PROBE = cfg.probe;
12012
12931
  const sentinels = /* @__PURE__ */ new Map();
12013
12932
  function sentinelFor(cls) {
12014
12933
  if (cls < 0) return void 0;
@@ -12023,6 +12942,9 @@ function assemble(t, prog, cfg) {
12023
12942
  const EC = newEndCell();
12024
12943
  const scalarRecognizers = [];
12025
12944
  const rawScalarSpecs = /* @__PURE__ */ new Set();
12945
+ function lookaheadClass(child) {
12946
+ return code[child] === OP_GATE && !cfg.tolerant && !cfg.probe ? cc[code[child + 1]] : null;
12947
+ }
12026
12948
  function scalarFor(child) {
12027
12949
  const spec = code[child + 1];
12028
12950
  let recognize = scalarRecognizers[spec];
@@ -12032,17 +12954,27 @@ function assemble(t, prog, cfg) {
12032
12954
  }
12033
12955
  return recognize;
12034
12956
  }
12035
- const labelExtraIps = [];
12036
- for (const s of prog.scans ?? []) for (const r of scanRefs(s)) labelExtraIps.push(r[0]);
12037
- for (const set of prog.scanSkip ?? []) for (const r of set) labelExtraIps.push(r[0]);
12957
+ const labelExtraIps = assemblyExtraIps(prog);
12038
12958
  const closureLabels = computeSiteLabels(
12039
12959
  code,
12040
12960
  [...Object.values(prog.rules), ...labelExtraIps],
12041
12961
  hostCst
12042
12962
  );
12043
12963
  let SCAN = null;
12964
+ let HYBRID;
12965
+ function hybridPiece(piece) {
12966
+ const setScan = HYBRID.scan;
12967
+ return (input, pos, ctx) => {
12968
+ const saved = setScan(SCAN);
12969
+ const value = piece(input, pos, ctx);
12970
+ setScan(saved);
12971
+ return value;
12972
+ };
12973
+ }
12044
12974
  const memo = /* @__PURE__ */ new Map();
12045
12975
  const reached = /* @__PURE__ */ new Set();
12976
+ const NULLABLE = /* @__PURE__ */ new Map();
12977
+ const CLEAN = REC2 ? () => false : failCleanAnalysis(code);
12046
12978
  function pushLeaf(ctx, value, s, e) {
12047
12979
  const lf = { _tag: "leaf", value, span: { start: s, end: e } };
12048
12980
  pushCstLeaf(ctx, lf);
@@ -12241,6 +13173,22 @@ function assemble(t, prog, cfg) {
12241
13173
  return node2;
12242
13174
  };
12243
13175
  }
13176
+ function passCollapseNode(child, build, readsRaw) {
13177
+ return (input, pos, ctx) => {
13178
+ const v = child(input, pos, ctx);
13179
+ if (v !== void 0) return v;
13180
+ return collapseEmpty(ctx, build, input, pos, EC.e, readsRaw);
13181
+ };
13182
+ }
13183
+ function gatedPassCollapseNode(blockers, last, classic, build, readsRaw) {
13184
+ return (input, pos, ctx) => {
13185
+ const c = lead(input, pos);
13186
+ for (let i = 0; i < blockers.length; i++) if (classHas2(blockers[i], c)) return classic(input, pos, ctx);
13187
+ const v = last(input, pos, ctx);
13188
+ if (v !== void 0) return v;
13189
+ return collapseEmpty(ctx, build, input, pos, EC.e, readsRaw);
13190
+ };
13191
+ }
12244
13192
  function plainProjectNode(child, projection, type) {
12245
13193
  return (input, pos, ctx) => {
12246
13194
  const sCh = ctx._cstChildren;
@@ -12332,9 +13280,7 @@ function assemble(t, prog, cfg) {
12332
13280
  return s(input, cur);
12333
13281
  }
12334
13282
  if (s !== null) return skipTriviaScanned(s, input, cur, ctx);
12335
- if (needsDeferredTriviaCommit(ctx)) {
12336
- return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
12337
- }
13283
+ if (needsDeferredTriviaCommit(ctx)) return skipDeferredTrivia(input, cur, ctx);
12338
13284
  return advanceTrivia(input, cur, ctx);
12339
13285
  }
12340
13286
  let TERMV;
@@ -12504,7 +13450,7 @@ function assemble(t, prog, cfg) {
12504
13450
  if (next !== void 0) {
12505
13451
  return next(input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best);
12506
13452
  }
12507
- if (best === pos) acc = through(total, prev, acc);
13453
+ if (best === pos && prev !== 0) acc = through(total, prev, acc);
12508
13454
  ctx._fe = pos;
12509
13455
  ctx._fx = acc ?? choiceFx;
12510
13456
  return FAIL;
@@ -12587,7 +13533,7 @@ function assemble(t, prog, cfg) {
12587
13533
  if (next !== void 0) {
12588
13534
  return next(input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best);
12589
13535
  }
12590
- if (best === pos) acc = through(total, prev, acc);
13536
+ if (best === pos && prev !== 0) acc = through(total, prev, acc);
12591
13537
  ctx._fe = pos;
12592
13538
  ctx._fx = acc ?? choiceFx;
12593
13539
  return FAIL;
@@ -12613,21 +13559,27 @@ function assemble(t, prog, cfg) {
12613
13559
  }
12614
13560
  function dispatchBranch(child, usesRouted) {
12615
13561
  if (!usesRouted) {
12616
- return (input, _pos, selEnd, key, _selectorMark, ctx) => {
12617
- const mark = saveTriviaMark(ctx);
13562
+ return (input, _pos, selEnd, key, ctx) => {
13563
+ const need = markCst(ctx);
13564
+ const mRaw = MRAW;
13565
+ const mTl = MTL;
13566
+ const mLv = MLV;
13567
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
13568
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
13569
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
13570
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
12618
13571
  const v = child(input, selEnd, ctx);
12619
13572
  if (v === FAIL) {
12620
- rollbackTrivia(ctx, mark);
13573
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12621
13574
  ctx._fc = true;
12622
13575
  return FAIL;
12623
13576
  }
12624
13577
  return [key, v];
12625
13578
  };
12626
13579
  }
12627
- return (input, pos, selEnd, key, selectorMark, ctx) => {
13580
+ return (input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot) => {
12628
13581
  const savedRouted = ctx._routed;
12629
- rollbackTrivia(ctx, selectorMark);
12630
- const mark = saveTriviaMark(ctx);
13582
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12631
13583
  ctx._routed = { value: key, span: { start: pos, end: selEnd } };
12632
13584
  let v;
12633
13585
  try {
@@ -12636,7 +13588,7 @@ function assemble(t, prog, cfg) {
12636
13588
  ctx._routed = savedRouted;
12637
13589
  }
12638
13590
  if (v === FAIL) {
12639
- rollbackTrivia(ctx, mark);
13591
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12640
13592
  ctx._fc = true;
12641
13593
  return FAIL;
12642
13594
  }
@@ -12644,12 +13596,12 @@ function assemble(t, prog, cfg) {
12644
13596
  };
12645
13597
  }
12646
13598
  function dispatchArmBlock(start, a0, a1, a2, a3, next) {
12647
- return (arm, input, pos, selEnd, key, selectorMark, ctx) => {
12648
- if (arm === start) return a0(input, pos, selEnd, key, selectorMark, ctx);
12649
- if (arm === start + 1) return a1(input, pos, selEnd, key, selectorMark, ctx);
12650
- if (arm === start + 2) return a2(input, pos, selEnd, key, selectorMark, ctx);
12651
- if (arm === start + 3) return a3(input, pos, selEnd, key, selectorMark, ctx);
12652
- return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key, selectorMark, ctx);
13599
+ return (arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot) => {
13600
+ if (arm === start) return a0(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
13601
+ if (arm === start + 1) return a1(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
13602
+ if (arm === start + 2) return a2(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
13603
+ if (arm === start + 3) return a3(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
13604
+ return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12653
13605
  };
12654
13606
  }
12655
13607
  function trackLinesInto(ctx, input, end) {
@@ -12666,20 +13618,68 @@ function assemble(t, prog, cfg) {
12666
13618
  if (done !== void 0) return done;
12667
13619
  const flight = inFlight.get(ip);
12668
13620
  if (flight !== void 0) return flight.fwd;
13621
+ const selected = HYBRID?.byIp[ip];
13622
+ if (selected !== void 0) {
13623
+ const piece2 = scanHandoffNeeded(code, ip, closureLabels) ? hybridPiece(selected) : selected;
13624
+ memo.set(ip, piece2);
13625
+ reached.add(ip);
13626
+ return piece2;
13627
+ }
12669
13628
  let target;
12670
13629
  const fwd = (input, pos, ctx) => target(input, pos, ctx);
12671
13630
  const holder = { fwd, set: (p) => {
12672
13631
  target = p;
12673
13632
  } };
12674
13633
  inFlight.set(ip, holder);
12675
- const op = code[ip];
12676
- const piece = (op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[ip + 3] === 0) && code[ip + 1] >= 0 && closureLabels.at(ip).tri === code[ip + 1] ? link(code[ip + 2]) : lower(ip);
13634
+ const piece = scopeIsIdentity(code, ip, closureLabels.at(ip)) ? link(code[ip + 2]) : countedPiece(lookaheadLedNode(ip) ?? lower(ip), ip);
12677
13635
  inFlight.delete(ip);
12678
13636
  holder.set(piece);
12679
13637
  memo.set(ip, piece);
12680
13638
  reached.add(ip);
12681
13639
  return piece;
12682
13640
  }
13641
+ let FIRST_DECIDED;
13642
+ let NODE_BODY;
13643
+ const DECIDED = (_input, pos) => {
13644
+ EC.e = pos;
13645
+ return null;
13646
+ };
13647
+ function lookaheadLedNode(ip) {
13648
+ const op = code[ip];
13649
+ if (op !== OP_NODE && op !== OP_NODE_TRACK || hostCst || REC2 || cfg.probe || cfg.coverage || cfg.trackLines) return void 0;
13650
+ if (passCollapse(code, ip, hostCst) || gatedPassCollapse(code, ip, hostCst) !== void 0) return void 0;
13651
+ const body = code[ip + 2];
13652
+ const bop = code[body];
13653
+ if (bop !== OP_SEQ && bop !== OP_SEQV && bop !== OP_SEQX) return void 0;
13654
+ const base = bop === OP_SEQX ? body + 3 : body + 2;
13655
+ if (code[bop === OP_SEQX ? body + 2 : body + 1] < 2) return void 0;
13656
+ const first = code[base];
13657
+ const negative = code[first] === OP_NOT;
13658
+ const terminal = negative ? scalarTerminalNotChild(code, first) : code[first] === OP_PEEK ? scalarTerminalPeekChild(code, first) : -1;
13659
+ if (terminal < 0) return void 0;
13660
+ const recognize = scalarFor(terminal);
13661
+ const xf = fx[code[first + 2]];
13662
+ FIRST_DECIDED = DECIDED;
13663
+ NODE_BODY = lower(body);
13664
+ const node2 = lower(ip);
13665
+ NODE_BODY = void 0;
13666
+ return negative ? (input, pos, ctx) => {
13667
+ if (recognize(input, pos) >= 0) {
13668
+ ctx._fe = pos;
13669
+ ctx._fx = xf;
13670
+ EC.e = pos;
13671
+ return FAIL;
13672
+ }
13673
+ return node2(input, pos, ctx);
13674
+ } : (input, pos, ctx) => {
13675
+ if (recognize(input, pos) < 0) {
13676
+ ctx._fe = pos;
13677
+ ctx._fx = xf;
13678
+ return FAIL;
13679
+ }
13680
+ return node2(input, pos, ctx);
13681
+ };
13682
+ }
12683
13683
  function lower(ip) {
12684
13684
  const op = code[ip];
12685
13685
  switch (op) {
@@ -13014,7 +14014,7 @@ function assemble(t, prog, cfg) {
13014
14014
  const child = link(code[ip + 1]);
13015
14015
  const xf = fx[code[ip + 2]];
13016
14016
  const expectSpan = (ctx, pos) => prog.lines === 1 ? spanLines(ctx, pos, pos) : { start: pos, end: pos };
13017
- if (REC) {
14017
+ if (REC2) {
13018
14018
  return (input, pos, ctx) => {
13019
14019
  const v = child(input, pos, ctx);
13020
14020
  if (v !== FAIL) return v;
@@ -13210,7 +14210,12 @@ function assemble(t, prog, cfg) {
13210
14210
  }
13211
14211
  const child = link(code[ip + 1]);
13212
14212
  const xf = fx[code[ip + 2]];
14213
+ const gate2 = lookaheadClass(code[ip + 1]);
13213
14214
  return (input, pos, ctx) => {
14215
+ if (gate2 !== null && !classHas2(gate2, lead(input, pos))) {
14216
+ EC.e = pos;
14217
+ return null;
14218
+ }
13214
14219
  const need = markCst(ctx);
13215
14220
  const mRaw = MRAW;
13216
14221
  const mTl = MTL;
@@ -13219,8 +14224,10 @@ function assemble(t, prog, cfg) {
13219
14224
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
13220
14225
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
13221
14226
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
14227
+ const probeBest = PROBE ? ctx._probe?.best : void 0;
13222
14228
  const v = child(input, pos, ctx);
13223
14229
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14230
+ if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
13224
14231
  if (v === FAIL) {
13225
14232
  EC.e = pos;
13226
14233
  return null;
@@ -13231,9 +14238,29 @@ function assemble(t, prog, cfg) {
13231
14238
  };
13232
14239
  }
13233
14240
  case OP_PEEK: {
14241
+ const scalarChild = scalarTerminalPeekChild(code, ip);
14242
+ if (scalarChild >= 0) {
14243
+ const recognize = scalarFor(scalarChild);
14244
+ const xf2 = fx[code[ip + 2]];
14245
+ return (input, pos, ctx) => {
14246
+ if (recognize(input, pos) < 0) {
14247
+ ctx._fe = pos;
14248
+ ctx._fx = xf2;
14249
+ return FAIL;
14250
+ }
14251
+ EC.e = pos;
14252
+ return null;
14253
+ };
14254
+ }
13234
14255
  const child = link(code[ip + 1]);
13235
14256
  const xf = fx[code[ip + 2]];
14257
+ const gate2 = lookaheadClass(code[ip + 1]);
13236
14258
  return (input, pos, ctx) => {
14259
+ if (gate2 !== null && !classHas2(gate2, lead(input, pos))) {
14260
+ ctx._fe = pos;
14261
+ ctx._fx = xf;
14262
+ return FAIL;
14263
+ }
13237
14264
  const need = markCst(ctx);
13238
14265
  const mRaw = MRAW;
13239
14266
  const mTl = MTL;
@@ -13242,8 +14269,10 @@ function assemble(t, prog, cfg) {
13242
14269
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
13243
14270
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
13244
14271
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
14272
+ const probeBest = PROBE ? ctx._probe?.best : void 0;
13245
14273
  const v = child(input, pos, ctx);
13246
14274
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14275
+ if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
13247
14276
  if (v === FAIL) {
13248
14277
  ctx._fe = pos;
13249
14278
  ctx._fx = xf;
@@ -13255,8 +14284,14 @@ function assemble(t, prog, cfg) {
13255
14284
  }
13256
14285
  case OP_OPT: {
13257
14286
  const child = link(code[ip + 1]);
14287
+ const gate2 = lookaheadClass(code[ip + 1]);
14288
+ const childClean = CLEAN(code[ip + 1]);
13258
14289
  return (input, pos, ctx) => {
13259
- const need = markCst(ctx);
14290
+ if (gate2 !== null && !classHas2(gate2, lead(input, pos))) {
14291
+ EC.e = pos;
14292
+ return null;
14293
+ }
14294
+ const need = !childClean && markCst(ctx);
13260
14295
  const mRaw = MRAW;
13261
14296
  const mTl = MTL;
13262
14297
  const mLv = MLV;
@@ -13353,8 +14388,8 @@ function assemble(t, prog, cfg) {
13353
14388
  };
13354
14389
  }
13355
14390
  case OP_LEX_PROGRAM: {
13356
- const run = t.lexPrograms[code[ip + 1]];
13357
- const scanId = run.scan;
14391
+ const run2 = t.lexPrograms[code[ip + 1]];
14392
+ const scanId = run2.scan;
13358
14393
  if (scanId !== void 0) {
13359
14394
  return (input, pos, ctx) => {
13360
14395
  const sTrivia = ctx.trivia, sKinds = ctx.triviaKindLabels;
@@ -13375,7 +14410,7 @@ function assemble(t, prog, cfg) {
13375
14410
  ctx._rootTriviaLog = void 0;
13376
14411
  let end;
13377
14412
  try {
13378
- end = run(input, pos, ctx, scans[scanId]);
14413
+ end = run2(input, pos, ctx, scans[scanId]);
13379
14414
  } finally {
13380
14415
  SCAN = sScan;
13381
14416
  ctx.trivia = sTrivia;
@@ -13396,7 +14431,7 @@ function assemble(t, prog, cfg) {
13396
14431
  };
13397
14432
  }
13398
14433
  return (input, pos, ctx) => {
13399
- const end = run(input, pos, ctx);
14434
+ const end = run2(input, pos, ctx);
13400
14435
  if (end < 0) return FAIL;
13401
14436
  const value = input.slice(pos, end);
13402
14437
  if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
@@ -13454,6 +14489,9 @@ function assemble(t, prog, cfg) {
13454
14489
  const projection = reducer < 0 ? ~reducer : -1;
13455
14490
  const fn = fused && projection < 0 ? fns[reducer] : void 0;
13456
14491
  const step = closureLabels.at(ip).buf ? nextTermBuffered : nextTerm;
14492
+ const decided = FIRST_DECIDED;
14493
+ FIRST_DECIDED = void 0;
14494
+ const linkFirst = () => decided ?? link(code[base]);
13457
14495
  const runnerBlock = (count, r0, r1, r2, r3, next) => {
13458
14496
  if (count === 1) return (input, cur, ctx, values, inherited) => {
13459
14497
  cur = r0(input, cur, ctx, inherited);
@@ -13498,8 +14536,8 @@ function assemble(t, prog, cfg) {
13498
14536
  return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
13499
14537
  };
13500
14538
  };
13501
- if (REC) {
13502
- const first2 = link(code[base]);
14539
+ if (REC2) {
14540
+ const first2 = linkFirst();
13503
14541
  const firstSync = sentinelFor(code[base + n]);
13504
14542
  const runnerAt = (i) => {
13505
14543
  const sync = sentinelFor(code[base + n + i]);
@@ -13535,13 +14573,13 @@ function assemble(t, prog, cfg) {
13535
14573
  const bindRunners = (start) => {
13536
14574
  const count = Math.min(4, n - start);
13537
14575
  const at = (offset) => runnerAt(start + offset);
13538
- const never = () => -1;
14576
+ const never2 = () => -1;
13539
14577
  return runnerBlock(
13540
14578
  count,
13541
14579
  at(0),
13542
- count > 1 ? at(1) : never,
13543
- count > 2 ? at(2) : never,
13544
- count > 3 ? at(3) : never,
14580
+ count > 1 ? at(1) : never2,
14581
+ count > 2 ? at(2) : never2,
14582
+ count > 3 ? at(3) : never2,
13545
14583
  start + count < n ? bindRunners(start + count) : void 0
13546
14584
  );
13547
14585
  };
@@ -13591,15 +14629,31 @@ function assemble(t, prog, cfg) {
13591
14629
  let hasAdj = false;
13592
14630
  for (let i = 1; i < n; i++) {
13593
14631
  const kidIp = code[base + i];
13594
- if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp)) {
14632
+ if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp) || holdsGap(code, k, base, n, i, NULLABLE)) {
13595
14633
  hasAdj = true;
13596
14634
  break;
13597
14635
  }
13598
14636
  }
13599
14637
  if (hasAdj) {
13600
- const first2 = link(code[base]);
14638
+ const first2 = linkFirst();
13601
14639
  const runnerAt = (i) => {
13602
14640
  const kidIp = code[base + i];
14641
+ if (holdsGap(code, k, base, n, i, NULLABLE)) {
14642
+ const kid = link(kidIp);
14643
+ return (input, cur, ctx) => {
14644
+ if (ctx.trivia === void 0) {
14645
+ const v2 = kid(input, cur, ctx);
14646
+ if (v2 === FAIL) return -1;
14647
+ TERMV = v2;
14648
+ return EC.e;
14649
+ }
14650
+ const scanEnd = skipTrivia(input, cur, ctx);
14651
+ const v = kid(input, scanEnd, ctx);
14652
+ if (v === FAIL) return -1;
14653
+ TERMV = v;
14654
+ return scanEnd;
14655
+ };
14656
+ }
13603
14657
  if (code[kidIp] !== OP_ADJ) {
13604
14658
  const kid = link(kidIp);
13605
14659
  if (leadingTriviaFieldAt(code, k, kidIp)) {
@@ -13624,13 +14678,13 @@ function assemble(t, prog, cfg) {
13624
14678
  const bindRunners = (start) => {
13625
14679
  const count = Math.min(4, n - start);
13626
14680
  const at = (offset) => runnerAt(start + offset);
13627
- const never = () => -1;
14681
+ const never2 = () => -1;
13628
14682
  return runnerBlock(
13629
14683
  count,
13630
14684
  at(0),
13631
- count > 1 ? at(1) : never,
13632
- count > 2 ? at(2) : never,
13633
- count > 3 ? at(3) : never,
14685
+ count > 1 ? at(1) : never2,
14686
+ count > 2 ? at(2) : never2,
14687
+ count > 3 ? at(3) : never2,
13634
14688
  start + count < n ? bindRunners(start + count) : void 0
13635
14689
  );
13636
14690
  };
@@ -13667,7 +14721,7 @@ function assemble(t, prog, cfg) {
13667
14721
  };
13668
14722
  }
13669
14723
  if (n === 1) {
13670
- const k0 = link(code[base]);
14724
+ const k0 = linkFirst();
13671
14725
  if (fused) {
13672
14726
  return (input, pos, ctx) => {
13673
14727
  const v = k0(input, pos, ctx);
@@ -13689,7 +14743,7 @@ function assemble(t, prog, cfg) {
13689
14743
  };
13690
14744
  }
13691
14745
  if (n === 2) {
13692
- const k0 = link(code[base]), k1 = link(code[base + 1]);
14746
+ const k0 = linkFirst(), k1 = link(code[base + 1]);
13693
14747
  if (fused) {
13694
14748
  return (input, pos, ctx) => {
13695
14749
  const v0 = k0(input, pos, ctx);
@@ -13720,7 +14774,7 @@ function assemble(t, prog, cfg) {
13720
14774
  };
13721
14775
  }
13722
14776
  if (n === 3) {
13723
- const k0 = link(code[base]), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
14777
+ const k0 = linkFirst(), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
13724
14778
  if (fused) {
13725
14779
  return (input, pos, ctx) => {
13726
14780
  const v0 = k0(input, pos, ctx);
@@ -13814,7 +14868,7 @@ function assemble(t, prog, cfg) {
13814
14868
  start + count < n ? bind(start + count) : void 0
13815
14869
  );
13816
14870
  };
13817
- const first = link(code[base]);
14871
+ const first = linkFirst();
13818
14872
  const tail = bind(1);
13819
14873
  const runDirectTerms = (input, pos, ctx, values) => {
13820
14874
  const v0 = first(input, pos, ctx);
@@ -13853,6 +14907,8 @@ function assemble(t, prog, cfg) {
13853
14907
  const n = code[ip + 2];
13854
14908
  const choiceFx = fx[code[ip + 3]];
13855
14909
  const base = ip + 4;
14910
+ for (let i = 0; i < n; i++) link(code[base + i]);
14911
+ const armsClean = CLEAN(ip);
13856
14912
  if (table.exclusive) {
13857
14913
  const ascii = table.ascii;
13858
14914
  const hi = table.hi;
@@ -13967,7 +15023,7 @@ function assemble(t, prog, cfg) {
13967
15023
  if (n === 2 || n === 3) {
13968
15024
  const a0 = link(code[base]), a1 = link(code[base + 1]);
13969
15025
  const a2 = n === 3 ? link(code[base + 2]) : void 0;
13970
- const predecide = !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
15026
+ const predecide = !REC2 && !cfg.probe && !cfg.coverage && !cfg.trackLines;
13971
15027
  const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
13972
15028
  const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
13973
15029
  const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
@@ -13992,7 +15048,7 @@ function assemble(t, prog, cfg) {
13992
15048
  if (n === 3) addGate(g2, 4);
13993
15049
  return (input, pos, ctx) => {
13994
15050
  const c = lead(input, pos);
13995
- const need = markCst(ctx);
15051
+ const need = !armsClean && markCst(ctx);
13996
15052
  const mRaw = MRAW;
13997
15053
  const mTl = MTL;
13998
15054
  const mLv = MLV;
@@ -14062,6 +15118,11 @@ function assemble(t, prog, cfg) {
14062
15118
  }
14063
15119
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14064
15120
  }
15121
+ if (prev === 0) {
15122
+ ctx._fe = pos;
15123
+ ctx._fx = choiceFx;
15124
+ return FAIL;
15125
+ }
14065
15126
  if (best === pos && prev < 1) acc = accSet(e0, acc);
14066
15127
  if (best === pos && prev < 2) acc = accSet(e1, acc);
14067
15128
  if (best === pos && n === 3 && prev < 3) acc = accSet(e2, acc);
@@ -14192,7 +15253,7 @@ function assemble(t, prog, cfg) {
14192
15253
  const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
14193
15254
  const pBit = [];
14194
15255
  const pRec = [];
14195
- if (!REC && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
15256
+ if (!REC2 && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
14196
15257
  for (let i = 0; i < n; i++) {
14197
15258
  for (const terminal of largeChoiceLiteralPretest(code, k, code[base + i]) ?? []) {
14198
15259
  pBit.push(1 << i);
@@ -14204,7 +15265,7 @@ function assemble(t, prog, cfg) {
14204
15265
  if (pn !== 0) {
14205
15266
  return (input, pos, ctx) => {
14206
15267
  const c = lead(input, pos);
14207
- const need = markCst(ctx);
15268
+ const need = !armsClean && markCst(ctx);
14208
15269
  const mRaw = MRAW;
14209
15270
  const mTl = MTL;
14210
15271
  const mLv = MLV;
@@ -14261,7 +15322,7 @@ function assemble(t, prog, cfg) {
14261
15322
  }
14262
15323
  return (input, pos, ctx) => {
14263
15324
  const c = lead(input, pos);
14264
- const need = markCst(ctx);
15325
+ const need = !armsClean && markCst(ctx);
14265
15326
  const mRaw = MRAW;
14266
15327
  const mTl = MTL;
14267
15328
  const mLv = MLV;
@@ -14309,7 +15370,7 @@ function assemble(t, prog, cfg) {
14309
15370
  }
14310
15371
  return (input, pos, ctx) => {
14311
15372
  const c = lead(input, pos);
14312
- const need = markCst(ctx);
15373
+ const need = !armsClean && markCst(ctx);
14313
15374
  const mRaw = MRAW;
14314
15375
  const mTl = MTL;
14315
15376
  const mLv = MLV;
@@ -14363,6 +15424,21 @@ function assemble(t, prog, cfg) {
14363
15424
  return lit(input, pos, ctx);
14364
15425
  };
14365
15426
  }
15427
+ case OP_RGATE: {
15428
+ const cls = cc[code[ip + 1]];
15429
+ const xf = fx[code[ip + 3]];
15430
+ const child = link(code[ip + 2]);
15431
+ if (cfg.tolerant || cfg.probe) return child;
15432
+ return (input, pos, ctx) => {
15433
+ const item = ctx._routed;
15434
+ if (item !== void 0 && item.span.start === pos && !classHas2(cls, lead(input, item.span.end))) {
15435
+ ctx._fe = item.span.end;
15436
+ ctx._fx = xf;
15437
+ return FAIL;
15438
+ }
15439
+ return child(input, pos, ctx);
15440
+ };
15441
+ }
14366
15442
  case OP_ARMGATE: {
14367
15443
  const pred = fns[code[ip + 1]];
14368
15444
  const child = link(code[ip + 2]);
@@ -14370,7 +15446,7 @@ function assemble(t, prog, cfg) {
14370
15446
  return (input, pos, ctx) => {
14371
15447
  if (!pred(ctx.state)) {
14372
15448
  ctx._fc = false;
14373
- ctx._fe = pos;
15449
+ ctx._fe = -1;
14374
15450
  ctx._fx = xf;
14375
15451
  return FAIL;
14376
15452
  }
@@ -14428,10 +15504,11 @@ function assemble(t, prog, cfg) {
14428
15504
  const itemFx = reportItem ? fx[code[ip + 6]] : EMPTY_FX2;
14429
15505
  const collect = op === OP_REP;
14430
15506
  const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
14431
- const itemClass = !REC && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
15507
+ const itemClass = !REC2 && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
14432
15508
  const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
14433
15509
  const skipBeforeFirst = sepIp < 0 && min === 0;
14434
- if (REC) {
15510
+ const itemClean = sepIp < 0 && CLEAN(code[ip + 1]) && !rowNullable(code, k, code[ip + 1], NULLABLE);
15511
+ if (REC2) {
14435
15512
  const itemFx2 = fx[code[ip + 6]];
14436
15513
  const sepSent = sentinelFor(code[ip + 7]);
14437
15514
  return (input, pos, ctx) => {
@@ -14527,6 +15604,8 @@ function assemble(t, prog, cfg) {
14527
15604
  const out = collect ? [] : void 0;
14528
15605
  const hasTrivia = ctx.trivia !== void 0;
14529
15606
  const needMark = rollbackNeeded(ctx);
15607
+ const markLater = needMark && (!itemClean || hasTrivia);
15608
+ const markFirst = needMark && (!itemClean || hasTrivia && skipBeforeFirst);
14530
15609
  const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
14531
15610
  let cur = pos;
14532
15611
  let count = 0;
@@ -14534,14 +15613,15 @@ function assemble(t, prog, cfg) {
14534
15613
  if (max >= 0 && count >= max) break;
14535
15614
  if (sep2 !== void 0 && count > 0 && count >= min && cur >= input.length) break;
14536
15615
  if (count >= min && sep2 === void 0 && !hasTrivia && gateItems && !itemMayStart(input, cur)) break;
14537
- if (needMark) markCst(ctx);
14538
- const mRaw = needMark ? MRAW : 0;
14539
- const mTl = needMark ? MTL : 0;
14540
- const mLv = needMark ? MLV : 0;
14541
- const mFl = needMark ? ctx._fields?.length ?? 0 : 0;
14542
- const mEr = needMark ? ctx._errors?.length ?? 0 : 0;
14543
- const mLog = needMark ? ctx._triviaLog?.length ?? 0 : 0;
14544
- const mRoot = needMark ? ctx._rootTriviaLog?.length ?? 0 : 0;
15616
+ const markIt = count > 0 ? markLater : markFirst;
15617
+ if (markIt) markCst(ctx);
15618
+ const mRaw = markIt ? MRAW : 0;
15619
+ const mTl = markIt ? MTL : 0;
15620
+ const mLv = markIt ? MLV : 0;
15621
+ const mFl = markIt ? ctx._fields?.length ?? 0 : 0;
15622
+ const mEr = markIt ? ctx._errors?.length ?? 0 : 0;
15623
+ const mLog = markIt ? ctx._triviaLog?.length ?? 0 : 0;
15624
+ const mRoot = markIt ? ctx._rootTriviaLog?.length ?? 0 : 0;
14545
15625
  let itemStart = cur;
14546
15626
  let sepEnd = -1;
14547
15627
  const viaRepItem = sep2 === void 0 && count >= min && (count > 0 || skipBeforeFirst);
@@ -14553,7 +15633,7 @@ function assemble(t, prog, cfg) {
14553
15633
  if (sepLeads) LEAD.at = cur;
14554
15634
  const sv = sep2(input, sp, ctx);
14555
15635
  if (sv === FAIL) {
14556
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
15636
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14557
15637
  if (committed3(ctx)) return FAIL;
14558
15638
  break;
14559
15639
  }
@@ -14564,25 +15644,25 @@ function assemble(t, prog, cfg) {
14564
15644
  itemStart = skipTrivia(input, itemStart, ctx);
14565
15645
  }
14566
15646
  if (itemStart >= input.length && viaRepItem) {
14567
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
15647
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14568
15648
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
14569
15649
  break;
14570
15650
  }
14571
15651
  if (count >= min && gateItems && !itemMayStart(input, itemStart)) {
14572
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
15652
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14573
15653
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
14574
15654
  break;
14575
15655
  }
14576
15656
  ctx._fc = false;
14577
15657
  const v = child(input, itemStart, ctx);
14578
15658
  if (v === FAIL) {
14579
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
15659
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14580
15660
  if (committed3(ctx)) return FAIL;
14581
15661
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
14582
15662
  break;
14583
15663
  }
14584
15664
  if (EC.e === itemStart && viaRepItem) {
14585
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
15665
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14586
15666
  break;
14587
15667
  }
14588
15668
  if (out !== void 0) out.push(v);
@@ -14656,7 +15736,14 @@ function assemble(t, prog, cfg) {
14656
15736
  const runArm = n === 0 ? void 0 : bindArms(0);
14657
15737
  const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted);
14658
15738
  return (input, pos, ctx) => {
14659
- const selectorMark = saveTriviaMark(ctx);
15739
+ const need = markCst(ctx);
15740
+ const mRaw = MRAW;
15741
+ const mTl = MTL;
15742
+ const mLv = MLV;
15743
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
15744
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
15745
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
15746
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
14660
15747
  const selVal = selector(input, pos, ctx);
14661
15748
  if (selVal === FAIL) return FAIL;
14662
15749
  const selEnd = EC.e;
@@ -14668,9 +15755,9 @@ function assemble(t, prog, cfg) {
14668
15755
  ctx._fx = expected;
14669
15756
  return FAIL;
14670
15757
  }
14671
- return runOther(input, pos, selEnd, key, selectorMark, ctx);
15758
+ return runOther(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14672
15759
  }
14673
- return runArm(arm, input, pos, selEnd, key, selectorMark, ctx);
15760
+ return runArm(arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14674
15761
  };
14675
15762
  }
14676
15763
  /* ── node ────────────────────────────────────────────────────────────── */
@@ -14706,7 +15793,8 @@ function assemble(t, prog, cfg) {
14706
15793
  return nd;
14707
15794
  };
14708
15795
  }
14709
- const child = link(code[ip + 2]);
15796
+ const child = NODE_BODY ?? link(code[ip + 2]);
15797
+ NODE_BODY = void 0;
14710
15798
  const proj = code[ip + 4];
14711
15799
  const buildIdx = code[ip + 1];
14712
15800
  const type = k[code[ip + 5]];
@@ -14730,6 +15818,30 @@ function assemble(t, prog, cfg) {
14730
15818
  if (build !== void 0 && proj < 0 && flags === 18) {
14731
15819
  return childrenOnlyFieldsBuildNode(child, build);
14732
15820
  }
15821
+ if (build !== void 0 && passCollapse(code, ip, hostCst)) {
15822
+ return passCollapseNode(child, build, flags === 32);
15823
+ }
15824
+ const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
15825
+ const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(closureLabels.at(code[ip + 2]).tri, trivia2);
15826
+ if (build !== void 0 && gated !== void 0 && triviaLead !== void 0) {
15827
+ const classic = flags === 32 ? collapseBuildNode(child, build) : childrenOnlyCollapseBuildNode(child, build);
15828
+ return gatedPassCollapseNode(
15829
+ [
15830
+ ...gated.leads.map((g) => cc[code[g + 1]]),
15831
+ resolveClass(encodeClassSpec([
15832
+ ...triviaLead,
15833
+ ...gated.lits.map((i) => {
15834
+ const c = k[i].codePointAt(0);
15835
+ return { lo: c, hi: c };
15836
+ })
15837
+ ]))
15838
+ ],
15839
+ link(gated.last),
15840
+ classic,
15841
+ build,
15842
+ flags === 32
15843
+ );
15844
+ }
14733
15845
  if (build !== void 0 && proj < 0 && flags === 32) {
14734
15846
  return collapseBuildNode(child, build);
14735
15847
  }
@@ -14776,7 +15888,7 @@ function assemble(t, prog, cfg) {
14776
15888
  if (v === FAIL) return FAIL;
14777
15889
  const end = EC.e;
14778
15890
  const span = tracked ? spanLines(ctx, pos, end) : { start: pos, end };
14779
- const st = readsState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
15891
+ const st = readsState ? ctx.state : void 0;
14780
15892
  let nd;
14781
15893
  if (unwrap && kids.length === 1) {
14782
15894
  nd = unwrapChild(kids[0]);
@@ -14789,10 +15901,10 @@ function assemble(t, prog, cfg) {
14789
15901
  ) {
14790
15902
  nd = kids[0];
14791
15903
  } else if (proj >= 0) {
14792
- nd = hostCst && host !== void 0 ? host(type, kids, fieldMap, span, rawKids, tlog, readsState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0, tags) : projectChild(kids, proj, type);
15904
+ nd = hostCst && host !== void 0 ? host(type, kids, fieldMap, span, rawKids, tlog, ctx.state, tags) : projectChild(kids, proj, type);
14793
15905
  } else if (build !== void 0) {
14794
15906
  if (hostCst && host !== void 0) {
14795
- nd = host(type, kids, fieldMap, span, rawKids, tlog, readsState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0, tags);
15907
+ nd = host(type, kids, fieldMap, span, rawKids, tlog, ctx.state, tags);
14796
15908
  } else {
14797
15909
  nd = build(kids, fieldMap, span, rawKids, captureWide ? tlog : EMPTY_TL2, st);
14798
15910
  }
@@ -14843,9 +15955,7 @@ function assemble(t, prog, cfg) {
14843
15955
  let emitRefusal;
14844
15956
  let emitReached;
14845
15957
  {
14846
- const extraIps = [];
14847
- for (const s of prog.scans ?? []) for (const r of scanRefs(s)) extraIps.push(r[0]);
14848
- for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
15958
+ const extraIps = assemblyExtraIps(prog);
14849
15959
  const roots = [...Object.values(prog.rules), ...extraIps];
14850
15960
  for (const ip of reachableSites(code, roots)) {
14851
15961
  if (code[ip] === OP_DISPATCH) {
@@ -14880,6 +15990,8 @@ function assemble(t, prog, cfg) {
14880
15990
  }
14881
15991
  const notChild = scalarTerminalNotChild(code, ip);
14882
15992
  if (notChild >= 0) scalarFor(notChild);
15993
+ const peekChild = scalarTerminalPeekChild(code, ip);
15994
+ if (peekChild >= 0) scalarFor(peekChild);
14883
15995
  }
14884
15996
  const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
14885
15997
  if (pre !== void 0) {
@@ -14926,7 +16038,7 @@ function assemble(t, prog, cfg) {
14926
16038
  lead,
14927
16039
  asciiFoldKey,
14928
16040
  ROUTED_FX,
14929
- REC ? prog.cc.map((_, i) => sentinelFor(i)) : EMPTY_SENTS,
16041
+ REC2 ? prog.cc.map((_, i) => sentinelFor(i)) : EMPTY_SENTS,
14930
16042
  matchesAt,
14931
16043
  recoverScan,
14932
16044
  orSentinel,
@@ -14938,9 +16050,12 @@ function assemble(t, prog, cfg) {
14938
16050
  adjacencyHolds,
14939
16051
  t.lexPrograms,
14940
16052
  LEAD,
14941
- triviaFieldCapture
16053
+ triviaFieldCapture,
16054
+ skipDeferredTrivia,
16055
+ collapseEmpty
14942
16056
  );
14943
16057
  emitReached = new Set(pre.reached);
16058
+ if (emitted.ext !== void 0) HYBRID = emitted;
14944
16059
  }
14945
16060
  try {
14946
16061
  if (emitted !== void 0) throw new ServedByBuild();
@@ -15010,7 +16125,7 @@ function assemble(t, prog, cfg) {
15010
16125
  // — a strict one emits no reader — and through the SAME `sentinelFor` memo
15011
16126
  // the closure pieces use, so both engines resync to the same combinator
15012
16127
  // object rather than to two separately constructed ones.
15013
- REC ? prog.cc.map((_, i) => sentinelFor(i)) : EMPTY_SENTS,
16128
+ REC2 ? prog.cc.map((_, i) => sentinelFor(i)) : EMPTY_SENTS,
15014
16129
  matchesAt,
15015
16130
  recoverScan,
15016
16131
  orSentinel,
@@ -15022,7 +16137,9 @@ function assemble(t, prog, cfg) {
15022
16137
  adjacencyHolds,
15023
16138
  t.lexPrograms,
15024
16139
  LEAD,
15025
- triviaFieldCapture
16140
+ triviaFieldCapture,
16141
+ skipDeferredTrivia,
16142
+ collapseEmpty
15026
16143
  );
15027
16144
  emitReached = em.reached;
15028
16145
  } catch (e) {
@@ -15033,7 +16150,7 @@ function assemble(t, prog, cfg) {
15033
16150
  }
15034
16151
  function pieceAt(ip) {
15035
16152
  const em = emitted;
15036
- if (em !== void 0) {
16153
+ if (em !== void 0 && HYBRID === void 0) {
15037
16154
  const p = em.byIp[ip];
15038
16155
  if (p === void 0) throw new Error(`table emitter: no emitted body for site ${ip}`);
15039
16156
  return p;
@@ -15063,6 +16180,37 @@ function assemble(t, prog, cfg) {
15063
16180
  }
15064
16181
  const scans = scansArr;
15065
16182
  const scanSkip = (prog.scanSkip ?? []).map((set) => set.map((r) => subtreeComb(r)));
16183
+ if (HYBRID !== void 0) {
16184
+ const em = HYBRID;
16185
+ em.bind(
16186
+ (s) => {
16187
+ const saved = SCAN;
16188
+ SCAN = s;
16189
+ return saved;
16190
+ },
16191
+ em.ext.map((ip) => link(ip))
16192
+ );
16193
+ const pieces2 = {};
16194
+ for (const [name, entryIp] of Object.entries(prog.rules)) {
16195
+ pieces2[name] = em.pieces[name] ?? link(entryIp);
16196
+ }
16197
+ for (const ip of emitReached) reached.add(ip);
16198
+ return {
16199
+ pieces: pieces2,
16200
+ end: () => EC.e,
16201
+ begin: (ctx) => {
16202
+ begin(ctx);
16203
+ em.begin(ctx);
16204
+ },
16205
+ finish: () => {
16206
+ em.finish();
16207
+ finish();
16208
+ },
16209
+ scanSkip,
16210
+ reached,
16211
+ emitRefusal: void 0
16212
+ };
16213
+ }
15066
16214
  if (emitted !== void 0) {
15067
16215
  const em = emitted;
15068
16216
  return {
@@ -15098,6 +16246,26 @@ function assemble(t, prog, cfg) {
15098
16246
  }
15099
16247
  return { pieces, end: () => EC.e, begin, finish, scanSkip, reached, emitRefusal };
15100
16248
  }
16249
+ var SITE_COUNTS;
16250
+ function countedPiece(piece, ip) {
16251
+ const counts = SITE_COUNTS;
16252
+ if (counts === void 0) return piece;
16253
+ return (input, pos, ctx) => {
16254
+ counts[ip]++;
16255
+ return piece(input, pos, ctx);
16256
+ };
16257
+ }
16258
+ function countSiteVisits(prog, parse2, fns = prog.fns) {
16259
+ const counts = new Int32Array(prog.code.length);
16260
+ const profiled = ownTableProgram({ ...prog, fns, asm: [] });
16261
+ SITE_COUNTS = counts;
16262
+ try {
16263
+ parse2(tableRules(profiled));
16264
+ } finally {
16265
+ SITE_COUNTS = void 0;
16266
+ }
16267
+ return counts;
16268
+ }
15101
16269
  var AssemblyCache = class {
15102
16270
  t;
15103
16271
  prog;
@@ -15249,7 +16417,7 @@ function emitClassPool(classes) {
15249
16417
  if (classes.length < 2) return array;
15250
16418
  const delimiter = "|/~?^`".split("").find((ch2) => classes.every((spec) => !spec.includes(ch2)));
15251
16419
  if (delimiter === void 0) return array;
15252
- const split = `${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
16420
+ const split = `/* @__PURE__ */ ${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
15253
16421
  return split.length < array.length ? split : array;
15254
16422
  }
15255
16423
  function emitConst(v) {
@@ -15311,9 +16479,7 @@ function defaultAssemblyCfgs(prog) {
15311
16479
  function emitAssemblies(prog, cfgs) {
15312
16480
  if (cfgs.length === 0) return ["a:[],"];
15313
16481
  const t = resolveTable(prog);
15314
- const extraIps = [];
15315
- for (const s of prog.scans ?? []) for (const r of scanRefs(s)) extraIps.push(r[0]);
15316
- for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
16482
+ const extraIps = assemblyExtraIps(prog);
15317
16483
  const out = [];
15318
16484
  const seen = /* @__PURE__ */ new Set();
15319
16485
  for (const cfg of cfgs) {
@@ -15322,7 +16488,7 @@ function emitAssemblies(prog, cfgs) {
15322
16488
  seen.add(key);
15323
16489
  let em;
15324
16490
  try {
15325
- em = emitAssemblySource(t, prog, cfg, extraIps, true);
16491
+ em = emitAssemblySource(t, prog, cfg, extraIps, true, cfg.select);
15326
16492
  } catch (e) {
15327
16493
  if (e instanceof Unemittable) continue;
15328
16494
  throw e;
@@ -16117,36 +17283,36 @@ function findRegexFragments(visited) {
16117
17283
  if (branches.length >= 2) runs.add(branches.join("|"));
16118
17284
  for (let i = 0; i < branches.length; i++) {
16119
17285
  for (let n = 2; n <= Math.min(MAX_RUN, branches.length - i); n++) {
16120
- const run = branches.slice(i, i + n).join("|");
16121
- if (run.length < 4) continue;
16122
- runs.add(run);
17286
+ const run2 = branches.slice(i, i + n).join("|");
17287
+ if (run2.length < 4) continue;
17288
+ runs.add(run2);
16123
17289
  }
16124
17290
  }
16125
17291
  }
16126
- for (const run of runs) {
16127
- let e = byRun.get(run);
17292
+ for (const run2 of runs) {
17293
+ let e = byRun.get(run2);
16128
17294
  if (e === void 0) {
16129
- e = { occ: [], nodes: /* @__PURE__ */ new Set(), branches: run.split("|").length };
16130
- byRun.set(run, e);
17295
+ e = { occ: [], nodes: /* @__PURE__ */ new Set(), branches: run2.split("|").length };
17296
+ byRun.set(run2, e);
16131
17297
  }
16132
17298
  if (e.nodes.has(v.p)) continue;
16133
17299
  e.nodes.add(v.p);
16134
17300
  e.occ.push({ site: v.site, source: d.source });
16135
17301
  }
16136
17302
  }
16137
- const candidates = [...byRun.entries()].filter(([, e]) => e.occ.length >= 2).map(([run, e]) => ({ run, e, savings: (e.occ.length - 1) * run.length })).sort((a, b) => b.e.occ.length - a.e.occ.length || b.savings - a.savings || b.run.length - a.run.length);
17303
+ const candidates = [...byRun.entries()].filter(([, e]) => e.occ.length >= 2).map(([run2, e]) => ({ run: run2, e, savings: (e.occ.length - 1) * run2.length })).sort((a, b) => b.e.occ.length - a.e.occ.length || b.savings - a.savings || b.run.length - a.run.length);
16138
17304
  const kept = [];
16139
17305
  for (const c of candidates) {
16140
17306
  if (kept.some((k) => k.e.occ.length >= c.e.occ.length && `|${k.run}|`.includes(`|${c.run}|`))) continue;
16141
17307
  kept.push(c);
16142
17308
  }
16143
- return kept.map(({ run, e }) => ({
17309
+ return kept.map(({ run: run2, e }) => ({
16144
17310
  kind: "regex-fragment",
16145
- id: `regex-fragment:${run}`,
16146
- fragment: run,
17311
+ id: `regex-fragment:${run2}`,
17312
+ fragment: run2,
16147
17313
  branches: e.branches,
16148
17314
  count: e.occ.length,
16149
- savings: (e.occ.length - 1) * run.length,
17315
+ savings: (e.occ.length - 1) * run2.length,
16150
17316
  sources: e.occ.map((o) => `/${o.source}/`),
16151
17317
  sites: e.occ.map((o) => o.site),
16152
17318
  suggestion: `this ${e.branches}-branch alternation is re-spelled in ${e.occ.length} DISTINCT regex() terminals. Hoist it to one shared source string and interpolate it (\`new RegExp(\\\`\u2026\\\${OP}\u2026\\\`)\`) or lift the shared part into its own terminal \u2014 an edit to the operator set currently has to land in ${e.occ.length} places, and the analysis cannot tell you when one of them drifts.`
@@ -16879,8 +18045,46 @@ function runDuplicationDiagnosticRules(ruleMap, opt) {
16879
18045
  return reportDuplication(opt, (o) => analyzeDuplicationRules(ruleMap, o));
16880
18046
  }
16881
18047
 
18048
+ // src/table/select-hot.ts
18049
+ var LOOP = 8;
18050
+ var ROUNDS = 60;
18051
+ var CAP = 1e12;
18052
+ function selectHotSites(code, entries, siteBytes, budget, profile) {
18053
+ const selected = /* @__PURE__ */ new Set();
18054
+ if (budget <= 0) return selected;
18055
+ const weight = profile === void 0 ? staticWeights(code, entries) : void 0;
18056
+ const w = (ip) => (weight !== void 0 ? weight.get(ip) : profile[ip]) ?? 0;
18057
+ const ranked = [...siteBytes.keys()].sort((a, b) => w(b) / siteBytes.get(b) - w(a) / siteBytes.get(a) || a - b);
18058
+ let spent = 0;
18059
+ for (const ip of ranked) {
18060
+ if (w(ip) === 0) break;
18061
+ const bytes = siteBytes.get(ip);
18062
+ if (spent + bytes > budget) continue;
18063
+ spent += bytes;
18064
+ selected.add(ip);
18065
+ }
18066
+ return selected;
18067
+ }
18068
+ function staticWeights(code, entries) {
18069
+ let weight = /* @__PURE__ */ new Map();
18070
+ const kids = [];
18071
+ for (let round = 0; round < ROUNDS; round++) {
18072
+ const next = /* @__PURE__ */ new Map();
18073
+ for (const ip of entries) next.set(ip, 1);
18074
+ for (const [ip, w] of weight) {
18075
+ kids.length = 0;
18076
+ childSlots(code, ip, kids);
18077
+ const op = code[ip];
18078
+ const scale = op === OP_REP || op === OP_REPV ? LOOP : op === OP_CHOICE || op === OP_DISPATCH ? 1 / Math.max(1, kids.length) : 1;
18079
+ for (const kid of kids) next.set(kid, Math.min(CAP, (next.get(kid) ?? 0) + w * scale));
18080
+ }
18081
+ weight = next;
18082
+ }
18083
+ return weight;
18084
+ }
18085
+
16882
18086
  // src/table/compile-rule-map.ts
16883
- var DEFAULT_PRECOMPILE_MIN_WORDS = 1024;
18087
+ var SUPERCOMPILE_GROWTH = 1.05;
16884
18088
  function resolveHostMode(ruleMap, explicit) {
16885
18089
  return explicit ?? ruleMap.map(([, r]) => r._meta.grammarHostMode).find(Boolean) ?? "ast";
16886
18090
  }
@@ -16977,14 +18181,45 @@ function compileRuleMap(ruleMap, opts = {}) {
16977
18181
  entry: null,
16978
18182
  runtimeRef: opts.runtimeRef ?? "tableRules",
16979
18183
  fnSources: sources,
16980
- ...options.precompileDefault === true && hostMode === "ast" && prog.lines !== 1 && prog.code.length >= DEFAULT_PRECOMPILE_MIN_WORDS ? { assemblies: defaultAssemblyCfgs(artifact).slice(0, 1) } : {},
18184
+ ...options.select !== void 0 && options.select.size > 0 ? { assemblies: [{ ...defaultAssemblyCfgs(artifact)[0], select: options.select }] } : {},
16981
18185
  ...metadataSource === void 0 ? {} : { metadataSource }
16982
18186
  });
16983
18187
  const replacement = replacementWithMetadata();
18188
+ const selectAssembly = (budget, profile) => {
18189
+ const none = { sites: /* @__PURE__ */ new Set(), bytes: 0 };
18190
+ if (hostMode !== "ast" || prog.lines === 1) return none;
18191
+ const table = resolveTable(artifact);
18192
+ const cfg = defaultAssemblyCfgs(artifact)[0];
18193
+ const roots = assemblyExtraIps(artifact);
18194
+ let siteBytes, fixed;
18195
+ try {
18196
+ siteBytes = emitAssemblySource(table, artifact, cfg, roots, true).siteBytes;
18197
+ fixed = emitAssemblySource(table, artifact, cfg, roots, true, /* @__PURE__ */ new Set()).source.length;
18198
+ } catch (e) {
18199
+ if (e instanceof Unemittable) return { ...none, refusal: e.construct };
18200
+ throw e;
18201
+ }
18202
+ const ceiling = budget / SUPERCOMPILE_GROWTH;
18203
+ if (ceiling <= fixed) return none;
18204
+ let target = ceiling;
18205
+ for (; ; ) {
18206
+ const sites = selectHotSites(artifact.code, Object.values(artifact.rules), siteBytes, target - fixed, profile);
18207
+ if (sites.size === 0) {
18208
+ return {
18209
+ ...none,
18210
+ refusal: `a site within its ${Math.floor(ceiling)} B selection ceiling (the prelude alone is ${fixed} B)`
18211
+ };
18212
+ }
18213
+ const bytes = emitAssemblySource(table, artifact, cfg, roots, true, sites).source.length;
18214
+ if (bytes <= ceiling) return { sites, bytes: Math.ceil(bytes * SUPERCOMPILE_GROWTH) };
18215
+ target *= Math.min(ceiling / bytes, 0.99);
18216
+ }
18217
+ };
16984
18218
  return {
16985
18219
  keys: ruleMap.map(([key]) => key),
16986
18220
  replacement,
16987
18221
  replacementWithMetadata,
18222
+ selectAssembly,
16988
18223
  hostMode,
16989
18224
  // WHAT THE FLAG MEANS is "a DIRECT BUILDER's positioned-CST branch was
16990
18225
  // dropped", which is what the driver's `'ast' artifact + CST host` check keys
@@ -17066,16 +18301,16 @@ function ownSource(fn) {
17066
18301
  return typeof name === "string" && name.length > 0 && globalThis[name] === fn ? name : null;
17067
18302
  }
17068
18303
  function compile(target, second, third) {
17069
- if (!isCombinator(target)) return compileMap(target, second);
18304
+ if (!isCombinator2(target)) return compileMap(target, second);
17070
18305
  return compileRoot(target, second, third);
17071
18306
  }
17072
- function isCombinator(x) {
18307
+ function isCombinator2(x) {
17073
18308
  return typeof x === "object" && x !== null && typeof x.parse === "function" && "_def" in x;
17074
18309
  }
17075
18310
  function compileMap(grammar, opts = {}) {
17076
18311
  const entries = [];
17077
18312
  for (const [key, value] of Object.entries(grammar)) {
17078
- if (!isCombinator(value)) throw new TypeError(`compile: grammar entry "${key}" is not a parser`);
18313
+ if (!isCombinator2(value)) throw new TypeError(`compile: grammar entry "${key}" is not a parser`);
17079
18314
  if (value._def.tag === "lazy") {
17080
18315
  try {
17081
18316
  value._def.thunk();
@@ -17139,7 +18374,7 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
17139
18374
  const emitOpts = { fnSources: sources };
17140
18375
  const source = printable ? emitTableModule(artifact, { name: "grammar", ...emitOpts }) : "";
17141
18376
  const inlineExpression = printable ? emitTableExpression(artifact, { entry: ENTRY, runtimeRef: opts.runtimeRef ?? "tableRules", ...emitOpts }) : null;
17142
- const runOnce = (input, pos, ctx) => entry(input, pos, ctx);
18377
+ const runOnce2 = (input, pos, ctx) => entry(input, pos, ctx);
17143
18378
  return {
17144
18379
  source,
17145
18380
  inlineExpression,
@@ -17153,10 +18388,10 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
17153
18388
  // parser runs where a combinator does. A caller probing many positions
17154
18389
  // passes one context and pays for none per call.
17155
18390
  parse(input, pos = 0, ctx) {
17156
- return runOnce(input, pos, ctx ?? createParseContext());
18391
+ return runOnce2(input, pos, ctx ?? createParseContext());
17157
18392
  },
17158
18393
  parseWithContext(input, parseCtx, pos = 0) {
17159
- return runOnce(input, pos, parseCtx);
18394
+ return runOnce2(input, pos, parseCtx);
17160
18395
  },
17161
18396
  /**
17162
18397
  * NO LONGER REFUSES. It used to throw unless the caller passed
@@ -17172,7 +18407,7 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
17172
18407
  const errors = [];
17173
18408
  ctx._errors = errors;
17174
18409
  ctx._tolerant = true;
17175
- const r = runOnce(input, pos, ctx);
18410
+ const r = runOnce2(input, pos, ctx);
17176
18411
  return { ...r, errors };
17177
18412
  }
17178
18413
  };
@@ -17620,7 +18855,7 @@ function fieldOptionsSrc(def) {
17620
18855
  }
17621
18856
 
17622
18857
  // src/version.ts
17623
- var PARSEMAN_VERSION = "0.56.0";
18858
+ var PARSEMAN_VERSION = "0.58.0";
17624
18859
 
17625
18860
  // src/compiler/compile-linkable-table.ts
17626
18861
  function isLocal(rule) {
@@ -17713,6 +18948,337 @@ function cstBuildHost(typeOrOptions, children3, _fields, span, rawChildren, triv
17713
18948
  cstBuildHost._parsemanCstOutput = true;
17714
18949
  var COMPOSED_PIECES = /* @__PURE__ */ Symbol.for("parseman.composedPieces");
17715
18950
 
18951
+ // src/cst/trivia-entries.ts
18952
+ var EMPTY_INDICES = Object.freeze([]);
18953
+ var EMPTY_GAPS = Object.freeze([]);
18954
+ var SELECTED_ROOT_STRIDE = 5;
18955
+ function buildRootTriviaIndex(log, labels) {
18956
+ const length = Math.floor(log.length / SELECTED_ROOT_STRIDE);
18957
+ const markerOffset = (i) => i * SELECTED_ROOT_STRIDE;
18958
+ const ownedRangeStart = (i) => log[markerOffset(i)];
18959
+ const ownedRangeEnd = (i) => log[markerOffset(i) + 1];
18960
+ const markerStart = (i) => log[markerOffset(i) + 2];
18961
+ const markerEnd = (i) => log[markerOffset(i) + 3];
18962
+ const markerKind = (i) => log[markerOffset(i) + 4];
18963
+ const entries = {
18964
+ length,
18965
+ labels,
18966
+ stride: SELECTED_ROOT_STRIDE,
18967
+ start: markerStart,
18968
+ end: markerEnd,
18969
+ insertIndex: () => void 0,
18970
+ kindIndex: markerKind,
18971
+ kind(i) {
18972
+ return labels[markerKind(i)];
18973
+ },
18974
+ text(i, input) {
18975
+ return input.slice(markerStart(i), markerEnd(i));
18976
+ }
18977
+ };
18978
+ const lowerBound = (offset, by) => {
18979
+ let lo = 0;
18980
+ let hi = length;
18981
+ while (lo < hi) {
18982
+ const mid = lo + hi >>> 1;
18983
+ if (by(mid) < offset) lo = mid + 1;
18984
+ else hi = mid;
18985
+ }
18986
+ return lo;
18987
+ };
18988
+ const gapRowsAt = (offset, direction) => {
18989
+ const edge = direction === "before" ? ownedRangeEnd : ownedRangeStart;
18990
+ let first = lowerBound(offset, edge);
18991
+ if (first === length || edge(first) !== offset) return void 0;
18992
+ const start = ownedRangeStart(first);
18993
+ const end = ownedRangeEnd(first);
18994
+ while (first > 0 && ownedRangeStart(first - 1) === start && ownedRangeEnd(first - 1) === end) first--;
18995
+ let last = first + 1;
18996
+ while (last < length && ownedRangeStart(last) === start && ownedRangeEnd(last) === end) last++;
18997
+ return [first, last];
18998
+ };
18999
+ const indices = (first, last) => {
19000
+ const out = [];
19001
+ for (let i = first; i < last; i++) out.push(i);
19002
+ return out;
19003
+ };
19004
+ const makeGap = (first, last) => {
19005
+ const start = ownedRangeStart(first);
19006
+ const end = ownedRangeEnd(first);
19007
+ let entryIndices;
19008
+ return {
19009
+ start,
19010
+ end,
19011
+ get entryIndices() {
19012
+ return entryIndices ??= indices(first, last);
19013
+ },
19014
+ hasKind(kind) {
19015
+ for (let i = first; i < last; i++) {
19016
+ if (labels[markerKind(i)] === kind) return true;
19017
+ }
19018
+ return false;
19019
+ },
19020
+ text(input) {
19021
+ return input.slice(start, end);
19022
+ }
19023
+ };
19024
+ };
19025
+ let maps;
19026
+ const getMaps = () => {
19027
+ if (maps !== void 0) return maps;
19028
+ const before = /* @__PURE__ */ new Map();
19029
+ const after = /* @__PURE__ */ new Map();
19030
+ const beforeGaps = /* @__PURE__ */ new Map();
19031
+ const afterGaps = /* @__PURE__ */ new Map();
19032
+ const gaps = [];
19033
+ for (let first = 0; first < length; ) {
19034
+ let last = first + 1;
19035
+ while (last < length && ownedRangeStart(last) === ownedRangeStart(first) && ownedRangeEnd(last) === ownedRangeEnd(first)) last++;
19036
+ const gap = makeGap(first, last);
19037
+ gaps.push(gap);
19038
+ afterGaps.set(gap.start, gap);
19039
+ beforeGaps.set(gap.end, gap);
19040
+ after.set(gap.start, [...gap.entryIndices]);
19041
+ before.set(gap.end, [...gap.entryIndices]);
19042
+ first = last;
19043
+ }
19044
+ maps = { before, after, beforeGaps, afterGaps, gaps };
19045
+ return maps;
19046
+ };
19047
+ return {
19048
+ entries,
19049
+ labels,
19050
+ get before() {
19051
+ return getMaps().before;
19052
+ },
19053
+ get after() {
19054
+ return getMaps().after;
19055
+ },
19056
+ entryIndicesBefore(offset) {
19057
+ const rows = gapRowsAt(offset, "before");
19058
+ return rows ? indices(rows[0], rows[1]) : EMPTY_INDICES;
19059
+ },
19060
+ entryIndicesAfter(offset) {
19061
+ const rows = gapRowsAt(offset, "after");
19062
+ return rows ? indices(rows[0], rows[1]) : EMPTY_INDICES;
19063
+ },
19064
+ gapBefore(offset) {
19065
+ const rows = gapRowsAt(offset, "before");
19066
+ return rows ? makeGap(rows[0], rows[1]) : void 0;
19067
+ },
19068
+ gapAfter(offset) {
19069
+ const rows = gapRowsAt(offset, "after");
19070
+ return rows ? makeGap(rows[0], rows[1]) : void 0;
19071
+ },
19072
+ gaps() {
19073
+ return getMaps().gaps;
19074
+ },
19075
+ gapsWithKind(kind) {
19076
+ const kinds = typeof kind === "string" ? [kind] : kind;
19077
+ const matches2 = [];
19078
+ for (let first = 0; first < length; ) {
19079
+ let last = first + 1;
19080
+ while (last < length && ownedRangeStart(last) === ownedRangeStart(first) && ownedRangeEnd(last) === ownedRangeEnd(first)) last++;
19081
+ let matched = false;
19082
+ for (let i = first; i < last && !matched; i++) {
19083
+ const label2 = labels[markerKind(i)];
19084
+ for (const kind2 of kinds) {
19085
+ if (label2 === kind2) {
19086
+ matched = true;
19087
+ break;
19088
+ }
19089
+ }
19090
+ }
19091
+ if (matched) matches2.push(makeGap(first, last));
19092
+ first = last;
19093
+ }
19094
+ return matches2.length === 0 ? EMPTY_GAPS : matches2;
19095
+ }
19096
+ };
19097
+ }
19098
+
19099
+ // src/functional/run.ts
19100
+ var SELECT_EXAMPLE = "run(entry, input, { rootTrivia: { select: ['blockComment', 'lineComment'] } })";
19101
+ var REMOVED_RUN_RESULT_FIELDS = [
19102
+ [
19103
+ "triviaMap",
19104
+ `It was a dense root-trivia index built on every parse; root trivia is now an OPT-IN sparse capture, because most grammars paid for an index they never read. Migration: name the trivia labels your grammar defines \u2014 ${SELECT_EXAMPLE} \u2014 and read \`RunResult.rootTrivia\`, whose \`.index\` carries the labels and gap lookups \`triviaMap\` exposed.`
19105
+ ],
19106
+ [
19107
+ "triviaLog",
19108
+ `It was the flat \`start, end[, kindIndex]\` log every other trivia view was derived from, and it is no longer allocated at all \u2014 not empty, absent. Migration: request the labels you need \u2014 ${SELECT_EXAMPLE} \u2014 and read \`RunResult.rootTrivia.rows\`. Do NOT reuse a stride-2/3 reader: rows are a different width and a different unit (one row per SELECTED marker, not one per trivia chunk), so an old loop reads confidently wrong offsets rather than failing.`
19109
+ ],
19110
+ [
19111
+ "triviaKindLabels",
19112
+ `It was already optional, so nothing ever flagged its disappearance \u2014 and \`triviaKindMask(undefined, \u2026)\` means "capture everything", so reading it now silently WIDENS capture instead of erroring. Migration: request labels \u2014 ${SELECT_EXAMPLE} \u2014 then the set you asked for is \`RunResult.rootTrivia.select\` and the resolved table is \`RunResult.rootTrivia.index.labels\`.`
19113
+ ]
19114
+ ];
19115
+ var RunResultRecord = class {
19116
+ constructor(ok, value, span, expected, errors, unconsumedFrom) {
19117
+ this.ok = ok;
19118
+ this.value = value;
19119
+ this.span = span;
19120
+ this.expected = expected;
19121
+ this.errors = errors;
19122
+ this.unconsumedFrom = unconsumedFrom;
19123
+ }
19124
+ };
19125
+ var RunResultWithRootTrivia = class {
19126
+ constructor(ok, value, span, expected, errors, rootTrivia, unconsumedFrom) {
19127
+ this.ok = ok;
19128
+ this.value = value;
19129
+ this.span = span;
19130
+ this.expected = expected;
19131
+ this.errors = errors;
19132
+ this.rootTrivia = rootTrivia;
19133
+ this.unconsumedFrom = unconsumedFrom;
19134
+ }
19135
+ };
19136
+ for (const proto of [RunResultRecord.prototype, RunResultWithRootTrivia.prototype]) {
19137
+ for (const [name, detail] of REMOVED_RUN_RESULT_FIELDS) {
19138
+ Object.defineProperty(proto, name, {
19139
+ configurable: true,
19140
+ enumerable: false,
19141
+ get() {
19142
+ throw new TypeError(
19143
+ `RunResult.${name} was REMOVED in parseman 0.44.0 and has no default replacement. ${detail}`
19144
+ );
19145
+ }
19146
+ });
19147
+ }
19148
+ }
19149
+ var invoke = (r, input, pos, ctx) => typeof r === "function" ? r(input, pos, ctx) : r.parse(input, pos, ctx);
19150
+ function ambientTriviaFromRunnable(r) {
19151
+ if (!r) return void 0;
19152
+ if (typeof r === "function") return r._meta?.grammarTrivia;
19153
+ if (r._meta.isTrivia) return void 0;
19154
+ return r._meta.grammarTrivia ?? (r._def.tag === "grammar" ? r._def.triviaParser : void 0);
19155
+ }
19156
+ function triviaKindLabelsFromRunnable(r) {
19157
+ if (!r) return void 0;
19158
+ if (typeof r === "function") return r._meta?.triviaKindLabels;
19159
+ const grammarTrivia = r._meta.grammarTrivia;
19160
+ return grammarTrivia?._meta.triviaKindLabels ?? r._meta.triviaKindLabels ?? (r._def.tag === "grammar" ? r._def.triviaParser?._meta.triviaKindLabels : void 0);
19161
+ }
19162
+ function rootTriviaClassifiedFromRunnable(r) {
19163
+ if (!r) return false;
19164
+ if (typeof r === "function") return r._meta?.rootTriviaClassified === true;
19165
+ const grammarTrivia = r._meta.grammarTrivia;
19166
+ return grammarTrivia?._meta.rootTriviaClassified === true || r._meta.rootTriviaClassified === true;
19167
+ }
19168
+ function makeSelectedRootLabelIndex(labels) {
19169
+ const index = /* @__PURE__ */ Object.create(null);
19170
+ for (let i = 0; i < labels.length; i++) {
19171
+ if (index[labels[i]] === void 0) index[labels[i]] = i;
19172
+ }
19173
+ return index;
19174
+ }
19175
+ function growSpanEnd(span, input, end) {
19176
+ if (span.endLine === void 0 || span.endColumn === void 0) {
19177
+ return { start: span.start, end };
19178
+ }
19179
+ let line = span.endLine;
19180
+ let column = span.endColumn;
19181
+ for (let i = span.end; i < end; i++) {
19182
+ if (input.charCodeAt(i) === 10) {
19183
+ line++;
19184
+ column = 1;
19185
+ } else {
19186
+ column++;
19187
+ }
19188
+ }
19189
+ return { ...span, end, endLine: line, endColumn: column };
19190
+ }
19191
+ function runOnce(entry, input, options) {
19192
+ if (typeof entry !== "function" && typeof entry?.parse !== "function") {
19193
+ throw new TypeError(
19194
+ `run(): start production is ${entry === null ? "null" : typeof entry}, not a rule \u2014 the requested grammar rule does not exist (check the rule name).`
19195
+ );
19196
+ }
19197
+ const rootTriviaSelection = options.rootTrivia?.select;
19198
+ const captureRootTrivia = rootTriviaSelection !== void 0 && rootTriviaSelection.length > 0;
19199
+ const selectedRootLog = captureRootTrivia ? [] : void 0;
19200
+ const selectedRootLabelIndex = captureRootTrivia ? makeSelectedRootLabelIndex(rootTriviaSelection) : void 0;
19201
+ const errors = [];
19202
+ const grammarTrivia = typeof entry !== "function" ? entry._meta.grammarTrivia : void 0;
19203
+ const grammarScanSkip = typeof entry !== "function" ? entry._meta.grammarScanSkip : void 0;
19204
+ const triviaKindLabels = triviaKindLabelsFromRunnable(entry) ?? triviaKindLabelsFromRunnable(options.trivia);
19205
+ if (captureRootTrivia && triviaKindLabels === void 0) {
19206
+ throw new TypeError("run(): rootTrivia.select requires labeled grammar trivia.");
19207
+ }
19208
+ if (captureRootTrivia) {
19209
+ for (const label2 of rootTriviaSelection) {
19210
+ if (!triviaKindLabels.includes(label2)) {
19211
+ throw new TypeError(`run(): rootTrivia.select contains unknown trivia label ${JSON.stringify(label2)}.`);
19212
+ }
19213
+ }
19214
+ }
19215
+ if (captureRootTrivia && !rootTriviaClassifiedFromRunnable(entry) && !rootTriviaClassifiedFromRunnable(options.trivia)) {
19216
+ throw new TypeError(
19217
+ "run(): rootTrivia.select requires classifiedTrivia() at the root."
19218
+ );
19219
+ }
19220
+ const stamped = entry;
19221
+ assertHostModeCompatible(
19222
+ typeof entry === "function" ? stamped[FUSED_HOST_MODE] ?? "ast" : entry._meta.grammarHostMode ?? "ast",
19223
+ options.build,
19224
+ typeof entry === "function" && stamped[FUSED_HOST_ELIDED] === true
19225
+ );
19226
+ const ctx = createParseContext();
19227
+ if (captureRootTrivia) {
19228
+ ctx._rootTriviaLog = selectedRootLog;
19229
+ ctx._rootTriviaKindIndex = selectedRootLabelIndex;
19230
+ ctx._rootTriviaStrictScopes = true;
19231
+ }
19232
+ ctx._errors = errors;
19233
+ ctx.build = options.build;
19234
+ ctx.state = options.state;
19235
+ if (grammarTrivia !== void 0) ctx.trivia = grammarTrivia;
19236
+ if (triviaKindLabels) ctx.triviaKindLabels = triviaKindLabels;
19237
+ if (grammarScanSkip !== void 0) ctx.scanSkip = grammarScanSkip;
19238
+ if (options.triviaCaptureMask !== void 0) ctx._triviaCaptureMask = options.triviaCaptureMask;
19239
+ if (options.tolerant) {
19240
+ ctx._tolerant = true;
19241
+ ctx._rec = REC;
19242
+ }
19243
+ if (options.instrumentation !== void 0) {
19244
+ ctx._grammarCoverage = options.instrumentation._grammarCoverage;
19245
+ ctx._grammarTrace = options.instrumentation._grammarTrace;
19246
+ }
19247
+ const r = invoke(entry, input, 0, ctx);
19248
+ const value = r.ok ? r.value : void 0;
19249
+ let span = r.span ?? { start: 0, end: 0 };
19250
+ const expected = r.ok ? [] : r.expected ?? [];
19251
+ let unconsumedFrom = null;
19252
+ if (r.ok) {
19253
+ let pos = span.end;
19254
+ const tail = options.trivia ?? ambientTriviaFromRunnable(entry);
19255
+ if (tail !== void 0 && pos < input.length) {
19256
+ const t = invoke(tail, input, pos, createParseContext());
19257
+ if (t.ok && t.span.end > pos) {
19258
+ span = growSpanEnd(span, input, t.span.end);
19259
+ pos = t.span.end;
19260
+ }
19261
+ }
19262
+ unconsumedFrom = pos < input.length ? pos : null;
19263
+ }
19264
+ return selectedRootLog !== void 0 && selectedRootLog.length > 0 ? new RunResultWithRootTrivia(
19265
+ r.ok,
19266
+ value,
19267
+ span,
19268
+ expected,
19269
+ errors,
19270
+ {
19271
+ rows: selectedRootLog,
19272
+ select: rootTriviaSelection,
19273
+ index: buildRootTriviaIndex(selectedRootLog, rootTriviaSelection)
19274
+ },
19275
+ unconsumedFrom
19276
+ ) : new RunResultRecord(r.ok, value, span, expected, errors, unconsumedFrom);
19277
+ }
19278
+ function run(entry, input, options = {}) {
19279
+ return runOnce(entry, input, options);
19280
+ }
19281
+
17716
19282
  // src/combinators/gate.ts
17717
19283
  function gate(predicate) {
17718
19284
  const meta = {
@@ -18212,7 +19778,7 @@ function dispatchArmValue(node2, scope, code, mfs) {
18212
19778
  if (!keyArg || !parserArg || extraArg !== void 0 || keyArg.type === "SpreadElement" || parserArg.type === "SpreadElement") return null;
18213
19779
  const key = anyValue(keyArg, scope, code, mfs);
18214
19780
  const parserValue = anyValue(parserArg, scope, code, mfs);
18215
- if (!isCombinator2(parserValue)) return null;
19781
+ if (!isCombinator3(parserValue)) return null;
18216
19782
  const opts = { caseInsensitive: factory.caseInsensitive };
18217
19783
  if (typeof key === "string") return when(key, parserValue, opts);
18218
19784
  if (Array.isArray(key) && key.every((item) => typeof item === "string")) return when(key, parserValue, opts);
@@ -18223,7 +19789,7 @@ function dispatchArmValue(node2, scope, code, mfs) {
18223
19789
  const [parserArg] = node2.arguments;
18224
19790
  if (!parserArg || parserArg.type === "SpreadElement") return null;
18225
19791
  const parserValue = anyValue(parserArg, scope, code, mfs);
18226
- if (!isCombinator2(parserValue)) return null;
19792
+ if (!isCombinator3(parserValue)) return null;
18227
19793
  return otherwise(parserValue);
18228
19794
  }
18229
19795
  if (callee.name === "when") {
@@ -18233,24 +19799,24 @@ function dispatchArmValue(node2, scope, code, mfs) {
18233
19799
  const parserValue = anyValue(parserArg, scope, code, mfs);
18234
19800
  const opts = dispatchWhenOptions(optsArg === void 0 ? void 0 : anyValue(optsArg, scope, code, mfs));
18235
19801
  if (opts === null) return null;
18236
- if (!isCombinator2(parserValue)) return null;
19802
+ if (!isCombinator3(parserValue)) return null;
18237
19803
  if (typeof key === "string") return when(key, parserValue, opts);
18238
19804
  if (Array.isArray(key) && key.every((item) => typeof item === "string")) return when(key, parserValue, opts);
18239
19805
  if (isDispatchMatcher(key)) return when(key, parserValue, opts);
18240
19806
  }
18241
19807
  return null;
18242
19808
  }
18243
- function isCombinator2(v) {
19809
+ function isCombinator3(v) {
18244
19810
  return !!v && typeof v === "object" && "_def" in v;
18245
19811
  }
18246
19812
  function isDispatchArm(v) {
18247
19813
  if (!v || typeof v !== "object") return false;
18248
19814
  const rec = v;
18249
- if (rec.kind === "otherwise") return isCombinator2(rec.parser);
19815
+ if (rec.kind === "otherwise") return isCombinator3(rec.parser);
18250
19816
  if (rec.kind === "whenMatcher") {
18251
- return isDispatchMatcher(rec.matcher) && typeof rec.caseInsensitive === "boolean" && isCombinator2(rec.parser);
19817
+ return isDispatchMatcher(rec.matcher) && typeof rec.caseInsensitive === "boolean" && isCombinator3(rec.parser);
18252
19818
  }
18253
- return rec.kind === "when" && Array.isArray(rec.keys) && rec.keys.every((key) => typeof key === "string") && typeof rec.caseInsensitive === "boolean" && isCombinator2(rec.parser);
19819
+ return rec.kind === "when" && Array.isArray(rec.keys) && rec.keys.every((key) => typeof key === "string") && typeof rec.caseInsensitive === "boolean" && isCombinator3(rec.parser);
18254
19820
  }
18255
19821
  function isDispatchMatcher(v) {
18256
19822
  if (!v || typeof v !== "object") return false;
@@ -18265,7 +19831,7 @@ function scopeGet(scope, name, mfs) {
18265
19831
  if (mfs && entry.mfSrcs.length > 0) mfs.push(...entry.mfSrcs);
18266
19832
  return entry.combi;
18267
19833
  }
18268
- if (isCombinator2(entry)) return entry;
19834
+ if (isCombinator3(entry)) return entry;
18269
19835
  return null;
18270
19836
  }
18271
19837
  function unwrapStaticExpr(expr) {
@@ -18317,7 +19883,7 @@ function scopedStaticValue(expr, scope) {
18317
19883
  return { found: true, value };
18318
19884
  }
18319
19885
  function staticNodeOptionsFromValue(value) {
18320
- if (value === null || typeof value !== "object" || Array.isArray(value) || isCombinator2(value)) return STATIC_NODE_OPTIONS_NOT_OPTIONS;
19886
+ if (value === null || typeof value !== "object" || Array.isArray(value) || isCombinator3(value)) return STATIC_NODE_OPTIONS_NOT_OPTIONS;
18321
19887
  const opts = {};
18322
19888
  const rec = value;
18323
19889
  for (const name of Object.keys(rec)) {
@@ -18411,7 +19977,7 @@ function exprToCombi(node2, scope, code, mfs) {
18411
19977
  const [parserArg, fnArg] = node2.arguments;
18412
19978
  if (!parserArg || !fnArg || parserArg.type === "SpreadElement" || fnArg.type === "SpreadElement") return null;
18413
19979
  const inner = anyValue(parserArg, scope, code, mfs);
18414
- if (!isCombinator2(inner)) return null;
19980
+ if (!isCombinator3(inner)) return null;
18415
19981
  const fnSrc = stripTsFromSource(fnArg, code);
18416
19982
  mfs.push(fnSrc);
18417
19983
  try {
@@ -18426,7 +19992,7 @@ function exprToCombi(node2, scope, code, mfs) {
18426
19992
  const [parserArg, fnArg] = node2.arguments;
18427
19993
  if (!parserArg || !fnArg || parserArg.type === "SpreadElement" || fnArg.type === "SpreadElement") return null;
18428
19994
  const inner = anyValue(parserArg, scope, code, mfs);
18429
- if (!isCombinator2(inner)) return null;
19995
+ if (!isCombinator3(inner)) return null;
18430
19996
  const fnSrc = stripTsFromSource(fnArg, code);
18431
19997
  mfs.push(fnSrc);
18432
19998
  try {
@@ -18447,7 +20013,7 @@ function exprToCombi(node2, scope, code, mfs) {
18447
20013
  const optsArg = explicitType !== void 0 ? fourthArg : thirdArg;
18448
20014
  if (!parserArg || parserArg.type === "SpreadElement") return null;
18449
20015
  const inner = anyValue(parserArg, scope, code, mfs);
18450
- if (!isCombinator2(inner)) return null;
20016
+ if (!isCombinator3(inner)) return null;
18451
20017
  const be = buildArg;
18452
20018
  const buildExpr = be === void 0 || be.type === "SpreadElement" ? void 0 : unwrapStaticExpr(be);
18453
20019
  const buildArgOptions = be !== void 0 && be.type !== "SpreadElement" ? staticNodeOptions(buildArg, scope) : STATIC_NODE_OPTIONS_NOT_OPTIONS;
@@ -18521,7 +20087,7 @@ function exprToCombi(node2, scope, code, mfs) {
18521
20087
  const opts = anyValue(optsArg, scope, code, []);
18522
20088
  if (!opts || typeof opts !== "object") return null;
18523
20089
  const root = anyValue(rootArg, scope, code, mfs);
18524
- if (!isCombinator2(root)) return null;
20090
+ if (!isCombinator3(root)) return null;
18525
20091
  try {
18526
20092
  return parser(opts, root);
18527
20093
  } catch {
@@ -18533,10 +20099,10 @@ function exprToCombi(node2, scope, code, mfs) {
18533
20099
  if (!itemArg || !sepArg || itemArg.type === "SpreadElement" || sepArg.type === "SpreadElement") return null;
18534
20100
  const itemMfs = [];
18535
20101
  const itemCombi = anyValue(itemArg, scope, code, itemMfs);
18536
- if (!isCombinator2(itemCombi)) return null;
20102
+ if (!isCombinator3(itemCombi)) return null;
18537
20103
  const sepMfs = [];
18538
20104
  const sepCombi = anyValue(sepArg, scope, code, sepMfs);
18539
- if (!isCombinator2(sepCombi)) return null;
20105
+ if (!isCombinator3(sepCombi)) return null;
18540
20106
  let opts;
18541
20107
  if (optsArg) {
18542
20108
  if (optsArg.type === "SpreadElement") return null;
@@ -18556,7 +20122,7 @@ function exprToCombi(node2, scope, code, mfs) {
18556
20122
  if (!itemArg || itemArg.type === "SpreadElement") return null;
18557
20123
  const itemMfs = [];
18558
20124
  const itemCombi = anyValue(itemArg, scope, code, itemMfs);
18559
- if (!isCombinator2(itemCombi)) return null;
20125
+ if (!isCombinator3(itemCombi)) return null;
18560
20126
  let opts;
18561
20127
  if (optsArg) {
18562
20128
  if (optsArg.type === "SpreadElement") return null;
@@ -18578,7 +20144,7 @@ function exprToCombi(node2, scope, code, mfs) {
18578
20144
  const [innerArg] = node2.arguments;
18579
20145
  if (!innerArg || innerArg.type === "SpreadElement") return null;
18580
20146
  const inner = anyValue(innerArg, scope, code, mfs);
18581
- if (!isCombinator2(inner)) return null;
20147
+ if (!isCombinator3(inner)) return null;
18582
20148
  try {
18583
20149
  return not(inner);
18584
20150
  } catch {
@@ -18589,7 +20155,7 @@ function exprToCombi(node2, scope, code, mfs) {
18589
20155
  const [innerArg] = node2.arguments;
18590
20156
  if (!innerArg || innerArg.type === "SpreadElement") return null;
18591
20157
  const inner = anyValue(innerArg, scope, code, mfs);
18592
- if (!isCombinator2(inner)) return null;
20158
+ if (!isCombinator3(inner)) return null;
18593
20159
  try {
18594
20160
  return peek(inner);
18595
20161
  } catch {
@@ -18614,7 +20180,7 @@ function exprToCombi(node2, scope, code, mfs) {
18614
20180
  const [sentinelArg, optsArg] = node2.arguments;
18615
20181
  if (!sentinelArg || sentinelArg.type === "SpreadElement") return null;
18616
20182
  const sentinel = anyValue(sentinelArg, scope, code, []);
18617
- if (!isCombinator2(sentinel)) return null;
20183
+ if (!isCombinator3(sentinel)) return null;
18618
20184
  const opts = scanOptions(optsArg, scope, code);
18619
20185
  if (opts === UNKNOWN_OPTIONS) return null;
18620
20186
  try {
@@ -18645,7 +20211,7 @@ function exprToCombi(node2, scope, code, mfs) {
18645
20211
  const extraSrc = stripTsFromSource(extraArg, code);
18646
20212
  mfs.push(extraSrc);
18647
20213
  const inner = anyValue(innerArg, scope, code, mfs);
18648
- if (!isCombinator2(inner)) return null;
20214
+ if (!isCombinator3(inner)) return null;
18649
20215
  try {
18650
20216
  const extraType = unwrapStaticExpr(extraArg).type;
18651
20217
  const derives = extraType === "ArrowFunctionExpression" || extraType === "FunctionExpression";
@@ -18663,7 +20229,7 @@ function exprToCombi(node2, scope, code, mfs) {
18663
20229
  const [selectorArg, ...armArgs] = node2.arguments;
18664
20230
  if (!selectorArg || selectorArg.type === "SpreadElement") return null;
18665
20231
  const selector = anyValue(selectorArg, scope, code, mfs);
18666
- if (!isCombinator2(selector)) return null;
20232
+ if (!isCombinator3(selector)) return null;
18667
20233
  const arms = [];
18668
20234
  for (const arg of armArgs) {
18669
20235
  if (arg.type === "SpreadElement") return null;
@@ -18690,12 +20256,12 @@ function exprToCombi(node2, scope, code, mfs) {
18690
20256
  const gateSrc = stripTsFromSource(parts.gate, code);
18691
20257
  mfs.push(gateSrc);
18692
20258
  const combi = anyValue(parts.combinator, scope, code, mfs);
18693
- if (!isCombinator2(combi)) return null;
20259
+ if (!isCombinator3(combi)) return null;
18694
20260
  arms.push({ gate: () => true, combinator: combi });
18695
20261
  gateSrcs.push(gateSrc);
18696
20262
  } else {
18697
20263
  const combi = anyValue(argNode, scope, code, mfs);
18698
- if (!isCombinator2(combi)) return null;
20264
+ if (!isCombinator3(combi)) return null;
18699
20265
  arms.push(combi);
18700
20266
  gateSrcs.push(null);
18701
20267
  }
@@ -18843,7 +20409,7 @@ function evaluateExpr(node2, scope, code, mapFnSources) {
18843
20409
  function evaluateCombinatorArray(node2, scope, code) {
18844
20410
  const val = anyValue(node2, scope, code, []);
18845
20411
  if (!Array.isArray(val) || val.length === 0) return null;
18846
- if (!val.every(isCombinator2)) return null;
20412
+ if (!val.every(isCombinator3)) return null;
18847
20413
  return val;
18848
20414
  }
18849
20415
  function collectRuleKeys(retObj) {
@@ -18921,7 +20487,7 @@ function evalBodyStatements(statements, scope, code, out) {
18921
20487
  return false;
18922
20488
  }
18923
20489
  const thisDeclMfSrcs = bodyMfs.slice(before);
18924
- if (isCombinator2(val)) scope.set(name, { combi: val, mfSrcs: thisDeclMfSrcs });
20490
+ if (isCombinator3(val)) scope.set(name, { combi: val, mfSrcs: thisDeclMfSrcs });
18925
20491
  else if (isDispatchArm(val)) scope.set(name, { value: val, mfSrcs: thisDeclMfSrcs });
18926
20492
  else scope.set(name, val);
18927
20493
  }
@@ -18976,7 +20542,7 @@ function evaluateParserFactory(factoryNode, scope, code, mapFnSources, out, opti
18976
20542
  const definitions = {};
18977
20543
  for (const [key, e] of finalByKey) {
18978
20544
  const val = anyValue(e.value, e.scope, e.code, mapFnSources);
18979
- if (!isCombinator2(val)) throw ABORT;
20545
+ if (!isCombinator3(val)) throw ABORT;
18980
20546
  definitions[key] = val;
18981
20547
  }
18982
20548
  return definitions;
@@ -18991,7 +20557,7 @@ function evaluateParserFactory(factoryNode, scope, code, mapFnSources, out, opti
18991
20557
  return map;
18992
20558
  }
18993
20559
  function isDefinableRef2(v) {
18994
- return isCombinator2(v) && typeof v.define === "function" && v._def.tag === "lazy";
20560
+ return isCombinator3(v) && typeof v.define === "function" && v._def.tag === "lazy";
18995
20561
  }
18996
20562
  function evaluateRefDeclaration(init, name, scope) {
18997
20563
  if (init.type !== "CallExpression") return null;
@@ -19011,12 +20577,12 @@ function applyDefineStatement(callExpr, scope, code) {
19011
20577
  if (mem.property.type !== "Identifier" || mem.property.name !== "define") return false;
19012
20578
  if (mem.object.type !== "Identifier" || !mem.object.name) return false;
19013
20579
  const target = scope.get(mem.object.name);
19014
- const refCombi = isScopeEntry(target) ? target.combi : isCombinator2(target) ? target : null;
20580
+ const refCombi = isScopeEntry(target) ? target.combi : isCombinator3(target) ? target : null;
19015
20581
  if (!refCombi || !isDefinableRef2(refCombi)) return false;
19016
20582
  const args = callExpr.arguments;
19017
20583
  if (args.length !== 1 || args[0].type === "SpreadElement") return false;
19018
20584
  const inner = anyValue(args[0], scope, code, []);
19019
- if (!isCombinator2(inner)) return false;
20585
+ if (!isCombinator3(inner)) return false;
19020
20586
  try {
19021
20587
  refCombi.define(inner);
19022
20588
  } catch {
@@ -19788,19 +21354,14 @@ function fallback(emitted, reason, before) {
19788
21354
  }
19789
21355
  };
19790
21356
  }
19791
- function supercompileRuleMapReplacement(prog, replacement) {
21357
+ function supercompileRuleMapReplacement(prog, replacement, select) {
19792
21358
  const cfg = defaultAssemblyCfgs(prog)[0];
19793
21359
  if (cfg === void 0) return replacement;
19794
- const extraIps = [];
19795
- for (const scan of prog.scans ?? []) {
19796
- for (const ref2 of scan.skip) extraIps.push(ref2[0]);
19797
- if (scan.sentinel !== void 0) extraIps.push(scan.sentinel[0]);
19798
- }
19799
- for (const set of prog.scanSkip ?? []) for (const ref2 of set) extraIps.push(ref2[0]);
21360
+ const extraIps = assemblyExtraIps(prog);
19800
21361
  let canonical2;
19801
21362
  let candidate;
19802
21363
  try {
19803
- canonical2 = emitAssemblySource(resolveTable(prog), prog, cfg, extraIps, true);
21364
+ canonical2 = emitAssemblySource(resolveTable(prog), prog, cfg, extraIps, true, select);
19804
21365
  candidate = supercompileEmittedAssembly(prog, cfg, extraIps, canonical2);
19805
21366
  } catch {
19806
21367
  return replacement;
@@ -20103,6 +21664,7 @@ ${nested}
20103
21664
  }
20104
21665
 
20105
21666
  // src/plugin/ir-eval.ts
21667
+ var INERT_BUILDER = /* @__PURE__ */ Symbol("parseman.inertBuilder");
20106
21668
  function evalRulesIR(ir) {
20107
21669
  return evalIR(ir, rules);
20108
21670
  }
@@ -20142,9 +21704,11 @@ function evalIR(ir, rulesImpl) {
20142
21704
  if (staticError !== void 0 && staticError.length > 0) {
20143
21705
  throw new Error(`IR direct node builder for ${type} must be macro-static and self-contained; unsupported binding(s): ${staticError.join(", ")}`);
20144
21706
  }
20145
- const n = node(type, child, (() => {
21707
+ const inert = (() => {
20146
21708
  throw new Error("IR node build requires static re-lowering");
20147
- }), opts);
21709
+ });
21710
+ inert[INERT_BUILDER] = type;
21711
+ const n = node(type, child, inert, opts);
20148
21712
  n._def.buildSrc = src;
20149
21713
  if (staticError !== void 0) n._def.buildStaticError = staticError;
20150
21714
  if (sigSrc !== void 0) n._def.buildSigSrc = sigSrc;
@@ -20287,7 +21851,41 @@ function evalIR(ir, rulesImpl) {
20287
21851
  // src/plugin/index.ts
20288
21852
  import { createHash } from "node:crypto";
20289
21853
  var TABLE_RUNTIME_SPECIFIER = "parseman/table";
21854
+ var CARRIED_SIDECAR_SUFFIX = ".parseman.json";
21855
+ var _sidecarCache = /* @__PURE__ */ new Map();
21856
+ function readCarriedSidecar(artifact) {
21857
+ const file = artifact + CARRIED_SIDECAR_SUFFIX;
21858
+ let mtimeMs;
21859
+ try {
21860
+ mtimeMs = fs2.statSync(file).mtimeMs;
21861
+ } catch {
21862
+ return null;
21863
+ }
21864
+ const hit = _sidecarCache.get(file);
21865
+ if (hit && hit.mtimeMs === mtimeMs) return hit.sidecar;
21866
+ let sidecar = null;
21867
+ try {
21868
+ const parsed = JSON.parse(fs2.readFileSync(file, "utf8"));
21869
+ const exports = typeof parsed === "object" && parsed !== null ? parsed.exports : void 0;
21870
+ if (typeof exports === "object" && exports !== null) sidecar = parsed;
21871
+ } catch {
21872
+ }
21873
+ _sidecarCache.set(file, { mtimeMs, sidecar });
21874
+ return sidecar;
21875
+ }
21876
+ var corpusCache = /* @__PURE__ */ new Map();
21877
+ function corpusTexts(profile) {
21878
+ return profile.files.map((file) => {
21879
+ const mtimeMs = fs2.statSync(file).mtimeMs;
21880
+ const hit = corpusCache.get(file);
21881
+ if (hit !== void 0 && hit.mtimeMs === mtimeMs) return hit.text;
21882
+ const text = fs2.readFileSync(file, "utf8");
21883
+ corpusCache.set(file, { mtimeMs, text });
21884
+ return text;
21885
+ });
21886
+ }
20290
21887
  var PARSEMAN_MODULE = "parseman";
21888
+ var DEFAULT_ASSEMBLY_BUDGET = 0.25;
20291
21889
  function reasonSuffix(runtimeOnly) {
20292
21890
  return runtimeOnly === void 0 || runtimeOnly.length === 0 ? "" : ` \u2014 ${runtimeOnly.join("; ")}`;
20293
21891
  }
@@ -20393,30 +21991,101 @@ function parseModuleCached(filePath) {
20393
21991
  _moduleParseCache.set(filePath, { mtimeMs, parsed });
20394
21992
  return parsed;
20395
21993
  }
20396
- var plugin_default = createUnplugin((opts = {}) => ({
20397
- name: "parseman",
20398
- // Run BEFORE the bundler's TS/JS transform — otherwise esbuild (Vite) strips
20399
- // the `with { type: 'macro' }` import attribute before we ever see it, and the
20400
- // macro silently never fires.
20401
- enforce: "pre",
20402
- transformInclude(id) {
20403
- return /\.[jt]sx?$/.test(id) && !id.includes("node_modules");
20404
- },
20405
- transform(code, id) {
20406
- if (!code.includes("parseman")) return null;
20407
- if (!code.includes("macro")) return null;
20408
- const moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE, ...opts.moduleAliases ?? []]);
20409
- const result = transformMacro(code, id, moduleAliases, opts.warnUnloweredRegex === true, opts.recovery === true, opts.grammarCoverage === true);
20410
- if (result?.warnings.length) {
20411
- for (const w of result.warnings) {
20412
- if (typeof this?.warn === "function") this.warn(`[parseman] ${w}`);
20413
- else console.warn(`[parseman] ${w}`);
20414
- }
20415
- }
20416
- if (!result) return null;
20417
- return { code: result.code, map: result.map };
20418
- }
20419
- }));
21994
+ function reexportSource(body, exported) {
21995
+ for (const st of body) {
21996
+ if (st.type !== "ExportNamedDeclaration") continue;
21997
+ for (const sp of st.specifiers ?? []) {
21998
+ const exp = sp.exported;
21999
+ if ((exp?.name ?? exp?.value) !== exported) continue;
22000
+ const local = sp.local;
22001
+ const name = local?.name ?? local?.value;
22002
+ if (name === void 0) return null;
22003
+ const from = st.source?.value;
22004
+ return from !== void 0 ? { source: from, imported: name } : extractImportBindings(body).get(name) ?? null;
22005
+ }
22006
+ }
22007
+ return null;
22008
+ }
22009
+ async function followCarried(sinks, moduleId, name) {
22010
+ for (let hop = 0; hop < 64; hop++) {
22011
+ const own = sinks.get(moduleId)?.get(name);
22012
+ if (own !== void 0) return own;
22013
+ const code = this.getModuleInfo(moduleId)?.code;
22014
+ if (!code) return void 0;
22015
+ const parsed = parseSync5(moduleId, code);
22016
+ if (parsed.errors.length > 0) return void 0;
22017
+ const next = reexportSource(parsed.program.body, name);
22018
+ if (next === null) return void 0;
22019
+ const resolved = await this.resolve(next.source, moduleId);
22020
+ if (resolved === null || resolved.external) return void 0;
22021
+ moduleId = resolved.id;
22022
+ name = next.imported;
22023
+ }
22024
+ return void 0;
22025
+ }
22026
+ async function emitCarriedSidecars(sinks, bundle) {
22027
+ const recorders = /* @__PURE__ */ new Map();
22028
+ for (const [moduleId, sink] of sinks) for (const name of sink.keys()) (recorders.get(name) ?? recorders.set(name, []).get(name)).push(moduleId);
22029
+ for (const chunk of Object.values(bundle)) {
22030
+ if (chunk.type !== "chunk") continue;
22031
+ const exports = {};
22032
+ for (const name of chunk.exports ?? []) {
22033
+ const followed = chunk.facadeModuleId ? await followCarried.call(this, sinks, chunk.facadeModuleId, name) : void 0;
22034
+ if (followed !== void 0) {
22035
+ exports[name] = followed;
22036
+ continue;
22037
+ }
22038
+ const ids = recorders.get(name);
22039
+ if (ids === void 0) continue;
22040
+ const own = ids.filter((m) => chunk.moduleIds?.includes(m));
22041
+ const moduleId = own.length === 1 ? own[0] : own.length === 0 && ids.length === 1 ? ids[0] : void 0;
22042
+ if (moduleId !== void 0) exports[name] = sinks.get(moduleId).get(name);
22043
+ }
22044
+ if (Object.keys(exports).length === 0) continue;
22045
+ const sidecar = { parseman: PARSEMAN_VERSION, exports };
22046
+ this.emitFile({ type: "asset", fileName: chunk.fileName + CARRIED_SIDECAR_SUFFIX, source: JSON.stringify(sidecar) });
22047
+ }
22048
+ }
22049
+ var SIDECAR_FRAMEWORKS = /* @__PURE__ */ new Set(["rollup", "rolldown", "vite"]);
22050
+ var plugin_default = createUnplugin((opts = {}, meta) => {
22051
+ const sinks = SIDECAR_FRAMEWORKS.has(meta.framework) ? /* @__PURE__ */ new Map() : void 0;
22052
+ const generateBundle = sinks === void 0 ? void 0 : {
22053
+ generateBundle(_options, bundle) {
22054
+ return emitCarriedSidecars.call(this, sinks, bundle);
22055
+ }
22056
+ };
22057
+ return {
22058
+ name: "parseman",
22059
+ ...generateBundle === void 0 ? {} : { rollup: generateBundle, rolldown: generateBundle, vite: generateBundle },
22060
+ // Run BEFORE the bundler's TS/JS transform — otherwise esbuild (Vite) strips
22061
+ // the `with { type: 'macro' }` import attribute before we ever see it, and the
22062
+ // macro silently never fires.
22063
+ enforce: "pre",
22064
+ transformInclude(id) {
22065
+ return /\.[jt]sx?$/.test(id) && !id.includes("node_modules");
22066
+ },
22067
+ transform(code, id) {
22068
+ if (!code.includes("parseman")) return null;
22069
+ if (!code.includes("macro")) return null;
22070
+ for (const file of opts.assemblyProfile?.files ?? []) this?.addWatchFile?.(file);
22071
+ const moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE, ...opts.moduleAliases ?? []]);
22072
+ const sink = sinks && /* @__PURE__ */ new Map();
22073
+ const result = transformMacro(code, id, moduleAliases, opts.warnUnloweredRegex === true, opts.recovery === true, opts.grammarCoverage === true, opts.assemblyProfile, opts.assemblyBudget, sink);
22074
+ if (sinks && sink) {
22075
+ if (sink.size > 0) sinks.set(id, sink);
22076
+ else sinks.delete(id);
22077
+ }
22078
+ if (result?.warnings.length) {
22079
+ for (const w of result.warnings) {
22080
+ if (typeof this?.warn === "function") this.warn(`[parseman] ${w}`);
22081
+ else console.warn(`[parseman] ${w}`);
22082
+ }
22083
+ }
22084
+ if (!result) return null;
22085
+ return { code: result.code, map: result.map };
22086
+ }
22087
+ };
22088
+ });
20420
22089
  function exportLocalName(body, exported) {
20421
22090
  for (const st of body) {
20422
22091
  if (st.type !== "ExportNamedDeclaration") continue;
@@ -20562,17 +22231,17 @@ function lowerPrivateSourceModule(file, moduleAliases, warnUnloweredRegex, recov
20562
22231
  _sourceLowering.delete(file);
20563
22232
  }
20564
22233
  }
20565
- function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE]), warnUnloweredRegex = false, recovery = false, grammarCoverage = false) {
22234
+ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE]), warnUnloweredRegex = false, recovery = false, grammarCoverage = false, assemblyProfile, assemblyBudget = DEFAULT_ASSEMBLY_BUDGET, carriedSink) {
20566
22235
  const depth = degradationCaptureDepth();
20567
22236
  try {
20568
- return transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recovery, grammarCoverage);
22237
+ return transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recovery, grammarCoverage, assemblyProfile, assemblyBudget, carriedSink);
20569
22238
  } finally {
20570
22239
  setReducerResolver(null);
20571
22240
  setBuilderImportResolver(null);
20572
22241
  for (const d of unwindDegradationCapture(depth)) console.warn(formatDegradation(d));
20573
22242
  }
20574
22243
  }
20575
- function transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recovery, grammarCoverage) {
22244
+ function transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recovery, grammarCoverage, assemblyProfile, assemblyBudgetShare, carriedSink) {
20576
22245
  let result;
20577
22246
  try {
20578
22247
  result = parseSync5(id, code);
@@ -21175,17 +22844,36 @@ ${names.map((n) => ` - ${n}`).join("\n")}` : " (it is not a static combinator/v
21175
22844
  const importedPiecesCache = /* @__PURE__ */ new Map();
21176
22845
  const resolveModulePieces = (module, exportName, seen, unresolved, local = false) => {
21177
22846
  const { file } = module;
22847
+ const fail = (why) => {
22848
+ unresolved.why ??= `${exportName} in ${file}: ${why}`;
22849
+ return null;
22850
+ };
22851
+ const sidecarItems = module.source || local ? void 0 : readCarriedSidecar(file)?.exports[exportName];
22852
+ if (sidecarItems !== void 0) {
22853
+ const list = [];
22854
+ for (const item of sidecarItems) {
22855
+ if ("ir" in item) {
22856
+ list.push(item);
22857
+ continue;
22858
+ }
22859
+ const sub = resolveGrammarModule(file, item.from);
22860
+ if (sub === null) return fail(`its carried pieces name \`${item.name}\` from '${item.from}', a module that could not be found`);
22861
+ if (seen.has(sub.file)) continue;
22862
+ const pieces = resolveModulePieces(sub, item.name, new Set(seen).add(sub.file), unresolved);
22863
+ if (pieces === null) return fail(`its carried pieces name \`${item.name}\` from '${item.from}', which could not be resolved`);
22864
+ list.push(...pieces);
22865
+ }
22866
+ return list;
22867
+ }
21178
22868
  const mod = module.source ? lowerPrivateSourceModule(file, moduleAliases, warnUnloweredRegex, recovery) : parseModuleCached(file);
21179
22869
  if (!mod) return null;
21180
22870
  const localFor = local ? exportName : exportLocalName(mod.body, exportName);
21181
22871
  const initNode = localFor ? topLevelInit(mod.body, localFor) : null;
21182
22872
  const literalRange = initNode ? findCarriedPiecesLiteral(initNode) : null;
21183
- if (!literalRange) return null;
22873
+ if (!literalRange) {
22874
+ return initNode !== null && !module.source && mod.src.slice(initNode.start, initNode.end).includes("tableRules(") ? fail(`is a compiled grammar with no carried pieces \u2014 no inline literal, and no entry in ${path2.basename(file)}${CARRIED_SIDECAR_SUFFIX}. Rebuild it with this parseman, and keep that file beside the artifact`) : null;
22875
+ }
21184
22876
  const literal2 = mod.src.slice(literalRange.start, literalRange.end);
21185
- const fail = (why) => {
21186
- unresolved.why ??= `${exportName} in ${file}: ${why}`;
21187
- return null;
21188
- };
21189
22877
  const imports = extractImportBindings(mod.body);
21190
22878
  const stubNames = [];
21191
22879
  const stubVals = [];
@@ -21234,6 +22922,27 @@ ${names.map((n) => ` - ${n}`).join("\n")}` : " (it is not a static combinator/v
21234
22922
  importedPiecesCache.set(localName, result2);
21235
22923
  return result2;
21236
22924
  };
22925
+ const sinkCarried = (name, list) => {
22926
+ if (carriedSink === void 0) return false;
22927
+ const out = [];
22928
+ for (const it of list) {
22929
+ if (!isSpread(it)) {
22930
+ out.push(it);
22931
+ continue;
22932
+ }
22933
+ const b = importBindings.get(it.__spreadLocal);
22934
+ if (b === void 0) return false;
22935
+ if (!b.source.startsWith(".") && !path2.isAbsolute(b.source)) {
22936
+ out.push({ from: b.source, name: b.imported });
22937
+ continue;
22938
+ }
22939
+ const pieces = importedPieces(it.__spreadLocal);
22940
+ if (pieces === null) return false;
22941
+ out.push(...pieces);
22942
+ }
22943
+ carriedSink.set(name, out);
22944
+ return true;
22945
+ };
21237
22946
  const carriedRuleMaps = (items) => {
21238
22947
  const pieces = [];
21239
22948
  let trackLines = false;
@@ -21398,9 +23107,10 @@ ${names.map((n) => ` - ${n}`).join("\n")}` : " (it is not a static combinator/v
21398
23107
  carried,
21399
23108
  reflection: compiled.reflection
21400
23109
  });
23110
+ const select = selectAssembly(init.start, "compose()", compiled, !declaresLeaf());
21401
23111
  return {
21402
- replacement: compiled.replacementWithMetadata(reflectionMetadata),
21403
- exportedReplacement: compiled.replacementWithMetadata(exportedMetadata),
23112
+ replacement: assembledReplacement(compiled, reflectionMetadata, select),
23113
+ exportedReplacement: assembledReplacement(compiled, exportedMetadata, select),
21404
23114
  carried,
21405
23115
  ...composing ? { trivia: composing } : {},
21406
23116
  ...importedFactories.length ? { importedFactories } : {},
@@ -21416,6 +23126,42 @@ ${names.map((n) => ` - ${n}`).join("\n")}` : " (it is not a static combinator/v
21416
23126
  warn(init.start, "compose(): a carried piece has no re-lowerable IR; leaving the runtime compose() in place");
21417
23127
  return null;
21418
23128
  };
23129
+ let assemblyBudget = Math.floor(code.length * assemblyBudgetShare);
23130
+ let leafDeclared;
23131
+ const declaresLeaf = () => leafDeclared ??= body.some((stmt) => {
23132
+ const vd = unwrapVd(stmt);
23133
+ return vd !== null && vd.declarations.some((d) => d.init != null && isComposeLeafCall(d.init));
23134
+ });
23135
+ const selectAssembly = (pos, label2, compiled, terminal) => {
23136
+ if (!terminal || grammarCoverage) return /* @__PURE__ */ new Set();
23137
+ const { sites, bytes, refusal } = compiled.selectAssembly(assemblyBudget, profileOf(compiled));
23138
+ if (refusal !== void 0) {
23139
+ warnings.push(`${id}:${lineOf(pos)} \u2014 ${label2}: its precompiled assembly cannot emit ${refusal}; the artifact runs on the closure engine`);
23140
+ }
23141
+ assemblyBudget -= bytes;
23142
+ return sites;
23143
+ };
23144
+ const profileOf = (compiled) => {
23145
+ if (assemblyProfile === void 0 || compiled.hostMode !== "ast" || compiled.prog.lines === 1 || !(assemblyProfile.entry in compiled.prog.rules)) return void 0;
23146
+ let parsed = 0;
23147
+ const fns = compiled.prog.fns.map((fn) => {
23148
+ const type = fn?.[INERT_BUILDER];
23149
+ return type === void 0 ? fn : (children3, _fields, span) => ({ type, span, children: children3 });
23150
+ });
23151
+ const counts = countSiteVisits(compiled.prog, (rules2) => {
23152
+ const entry = rules2[assemblyProfile.entry];
23153
+ for (const text of corpusTexts(assemblyProfile)) {
23154
+ try {
23155
+ if (run(entry, text).ok) parsed++;
23156
+ } catch {
23157
+ }
23158
+ }
23159
+ }, fns);
23160
+ if (parsed > 0) return counts;
23161
+ warnings.push(`${id} \u2014 assemblyProfile: no corpus file parsed from rule "${assemblyProfile.entry}"; using the static ranking`);
23162
+ return void 0;
23163
+ };
23164
+ const assembledReplacement = (compiled, metadata, select) => select.size === 0 ? compiled.replacementWithMetadata(metadata) : supercompileRuleMapReplacement(compiled.prog, compiled.replacementWithMetadata(metadata, { select }), select);
21419
23165
  const compileComposeLeafCall = (init) => {
21420
23166
  const args = init.arguments;
21421
23167
  const arr = args[0];
@@ -21494,12 +23240,10 @@ ${names.map((n) => ` - ${n}`).join("\n")}` : " (it is not a static combinator/v
21494
23240
  if (compiled !== null) {
21495
23241
  usedTableRuntime = true;
21496
23242
  return {
21497
- replacement: supercompileRuleMapReplacement(
21498
- compiled.prog,
21499
- compiled.replacementWithMetadata(
21500
- staticTableMetadataSource({ reflection: compiled.reflection, leaf: true }),
21501
- { precompileDefault: true }
21502
- )
23243
+ replacement: assembledReplacement(
23244
+ compiled,
23245
+ staticTableMetadataSource({ reflection: compiled.reflection, leaf: true }),
23246
+ selectAssembly(init.start, "composeLeaf()", compiled, true)
21503
23247
  ),
21504
23248
  ...importedFactories.length ? { importedFactories } : {}
21505
23249
  };
@@ -21618,6 +23362,7 @@ ${names.map((n) => ` - ${n}`).join("\n")}` : " (it is not a static combinator/v
21618
23362
  const ir = serializeRuleMap([...compiledRules.ruleMap], compiledRules.scanSkip);
21619
23363
  if (ir) carriedMetadata = [{ ns, ir, ...compiledRules.trackLines ? { trackLines: true } : {} }];
21620
23364
  else warn(init.start, `${varName}: exported grammar could not be serialized to IR, so it carries no composable pieces \u2014 a downstream compose() of this grammar will fall back to runtime. Re-run with PARSEMAN_IR_DEBUG=1 to print the combinator that blocked serialization.`);
23365
+ if (carriedMetadata !== void 0 && sinkCarried(varName, carriedMetadata)) carriedMetadata = void 0;
21621
23366
  }
21622
23367
  const replacement = compiledRules.replacement !== null ? compiledRules.replacementWithMetadata(staticTableMetadataSource({
21623
23368
  ...carriedMetadata === void 0 ? {} : { carried: carriedMetadata },
@@ -21642,7 +23387,7 @@ ${names.map((n) => ` - ${n}`).join("\n")}` : " (it is not a static combinator/v
21642
23387
  continue;
21643
23388
  }
21644
23389
  localComposedCarried.set(varName, fused.carried);
21645
- const replacement = exportPrefix ? fused.exportedReplacement : fused.replacement;
23390
+ const replacement = exportPrefix && !sinkCarried(varName, fused.carried) ? fused.exportedReplacement : fused.replacement;
21646
23391
  replacements.push({ start: init.start, end: init.end, replacement });
21647
23392
  markUsedImportedFactories(fused.importedFactories);
21648
23393
  continue;
@@ -21932,6 +23677,7 @@ ${lines2.join("\n")}`);
21932
23677
  };
21933
23678
  }
21934
23679
  export {
23680
+ CARRIED_SIDECAR_SUFFIX,
21935
23681
  plugin_default as default,
21936
23682
  transformMacro
21937
23683
  };