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
package/dist/index.js CHANGED
@@ -465,6 +465,31 @@ function pushCstChild(ctx, built, rawEntry2) {
465
465
  else if (ctx._cstLeaves) ctx._cstLeaves.push(built);
466
466
  if (ctx._cstRawChildren) ctx._cstRawChildren.push(rawEntry2);
467
467
  }
468
+ function popCstChild(ctx) {
469
+ const b = ctx._cstBuf;
470
+ if (b) {
471
+ const ch2 = b.ch;
472
+ if (b.rawOnly !== true && ch2) {
473
+ ch2.pop();
474
+ if (ch2.length === 1) {
475
+ b.single = ch2[0];
476
+ b.ch = void 0;
477
+ }
478
+ }
479
+ if (b.noRaw === true) b.rawLen = (b.rawLen ?? 1) - 1;
480
+ else if (b.raw) {
481
+ b.raw.pop();
482
+ if (b.raw.length === 1) {
483
+ b.rawSingle = b.raw[0];
484
+ b.raw = void 0;
485
+ }
486
+ } else b.rawSingle = void 0;
487
+ return;
488
+ }
489
+ if (ctx._cstChildren) ctx._cstChildren.pop();
490
+ else if (ctx._cstLeaves) ctx._cstLeaves.pop();
491
+ if (ctx._cstRawChildren) ctx._cstRawChildren.pop();
492
+ }
468
493
  function cstRawLen(ctx) {
469
494
  const b = ctx._cstBuf;
470
495
  if (b) {
@@ -726,6 +751,7 @@ function literalCodePoints(frag) {
726
751
  if (ch2 === "\\") {
727
752
  const e = frag[i + 1];
728
753
  if (e === void 0) return null;
754
+ if (!(e in CLASS_ESCAPES) && /\w/.test(e)) return null;
729
755
  out.push(e in CLASS_ESCAPES ? CLASS_ESCAPES[e] : e.codePointAt(0));
730
756
  i += 2;
731
757
  continue;
@@ -1323,6 +1349,7 @@ function createParseContext() {
1323
1349
  _rootTriviaKindIndex: void 0,
1324
1350
  _rootTriviaStrictScopes: void 0,
1325
1351
  _rootTriviaCapture: void 0,
1352
+ _gap: void 0,
1326
1353
  _cstTriviaLog: void 0,
1327
1354
  _fields: void 0,
1328
1355
  _cstBuf: void 0,
@@ -1805,7 +1832,10 @@ function labeledTriviaSpec(arms, minRepeats) {
1805
1832
  arms,
1806
1833
  minRepeats,
1807
1834
  visitor: commonLabeledTriviaVisitor({ arms, minRepeats }),
1808
- charArms: charArmsFor({ arms, minRepeats })
1835
+ charArms: charArmsFor({ arms, minRepeats }),
1836
+ rootKinds: void 0,
1837
+ rootLeaders: [],
1838
+ rootScan: null
1809
1839
  };
1810
1840
  }
1811
1841
  function matchArmAt(input, pos, arm, state) {
@@ -2265,8 +2295,50 @@ function loopScanner(arms) {
2265
2295
  function regexTriviaScanner(parser2) {
2266
2296
  const d = parser2._def.tag === "label" ? parser2._def.parser._def : parser2._def;
2267
2297
  if (d.tag !== "regex" || d.flags) return null;
2268
- const source = d.source;
2269
- return classRunSource(source) ?? altStarSource(source) ?? prefixRunSource(source) ?? delimitedSource(source);
2298
+ return sourceScanner(d.source);
2299
+ }
2300
+ function sourceScanner(source) {
2301
+ return classRunSource(source) ?? altStarSource(source) ?? prefixRunSource(source) ?? delimitedSource(source) ?? sharedPrefixAltSource(source);
2302
+ }
2303
+ function sharedPrefixAltSource(source) {
2304
+ const m = /^((?:\\.|[^\\[\]()*+?|^$.{}])+)\(\?:(.*)\)$/.exec(source);
2305
+ if (!m) return null;
2306
+ const alts = [];
2307
+ const body = m[2];
2308
+ let depth = 0;
2309
+ let start = 0;
2310
+ for (let i = 0; i < body.length; i++) {
2311
+ const c = body[i];
2312
+ if (c === "\\") {
2313
+ i++;
2314
+ continue;
2315
+ }
2316
+ if (c === "[") {
2317
+ while (i < body.length && body[i] !== "]") i += body[i] === "\\" ? 2 : 1;
2318
+ continue;
2319
+ }
2320
+ if (c === "(") depth++;
2321
+ else if (c === ")" && --depth < 0) return null;
2322
+ else if (c === "|" && depth === 0) {
2323
+ alts.push(body.slice(start, i));
2324
+ start = i + 1;
2325
+ }
2326
+ }
2327
+ if (depth !== 0 || alts.length === 0) return null;
2328
+ alts.push(body.slice(start));
2329
+ const scanners = [];
2330
+ for (const alt of alts) {
2331
+ const scanner = sourceScanner(m[1] + alt);
2332
+ if (scanner === null) return null;
2333
+ scanners.push(scanner);
2334
+ }
2335
+ return (input, cur) => {
2336
+ for (const scanner of scanners) {
2337
+ const end = scanner(input, cur);
2338
+ if (end > cur) return end;
2339
+ }
2340
+ return cur;
2341
+ };
2270
2342
  }
2271
2343
  function bmpString(cps) {
2272
2344
  if (!cps) return null;
@@ -3351,10 +3423,16 @@ function branchUsesRouted(branch) {
3351
3423
  return branch.usesRouted === true || parserUsesRouted(branch.parser);
3352
3424
  }
3353
3425
  function asciiFoldKey(key) {
3354
- let out = "";
3355
- for (let i = 0; i < key.length; i++) {
3426
+ let i = 0;
3427
+ for (; i < key.length; i++) {
3356
3428
  const c = key.charCodeAt(i);
3357
- out += String.fromCharCode(c >= 65 && c <= 90 ? c + 32 : c);
3429
+ if (c >= 65 && c <= 90) break;
3430
+ }
3431
+ if (i === key.length) return key;
3432
+ let out = key.slice(0, i);
3433
+ for (; i < key.length; i++) {
3434
+ const c = key.charCodeAt(i);
3435
+ out += c >= 65 && c <= 90 ? String.fromCharCode(c + 32) : key[i];
3358
3436
  }
3359
3437
  return out;
3360
3438
  }
@@ -4846,7 +4924,7 @@ function confirmedArityForDef(def) {
4846
4924
  severity: "warn",
4847
4925
  where: `node("${def.type ?? "<inferred>"}")`,
4848
4926
  subject,
4849
- 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`,
4927
+ 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`,
4850
4928
  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"
4851
4929
  });
4852
4930
  return null;
@@ -5003,7 +5081,7 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
5003
5081
  }
5004
5082
  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;
5005
5083
  const capturesTrivia = captureTrivia || (build ? buildReadsTrivia(def) : project === void 0);
5006
- const clonesState = build ? buildReadsState(def) : project === void 0;
5084
+ const readsState = build ? buildReadsState(def) : project === void 0;
5007
5085
  const hasOwnFields = parserHasOwnFields(combinator);
5008
5086
  const capturesFields = hasOwnFields && (build ? buildReadsFields(def) : project === void 0);
5009
5087
  const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
@@ -5044,12 +5122,11 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
5044
5122
  ctx._triviaCaptureMask = savedMask;
5045
5123
  const { children: children2, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
5046
5124
  if (!r.ok) return r;
5047
- const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
5125
+ const st = readsState ? ctx.state : void 0;
5048
5126
  const nodeType = def.type ?? missingInferredType();
5049
5127
  const cstOutput2 = cstOutputHost(ctx.build);
5050
5128
  const span = ctx.trackLines ? annotateSpanFromLineContext(r.span, ctx) : r.span;
5051
- const hostState = clonesState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
5052
- const built = unwrap && children2.length === 1 ? unwrapChild(children2[0]) : collapse && children2.length === 1 ? children2[0] : (cstOutput2 || !build && project === void 0) && ctx.build?._parsemanCstCollapse && children2.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children2[0], children2, rawChildren) ? children2[0] : project !== void 0 ? cstOutput2 && ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, hostState, tags) : projectChild(children2, project, nodeType) : build ? cstOutput2 && ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, hostState, tags) : build(children2, fields, span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children2, 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: children2 };
5129
+ const built = unwrap && children2.length === 1 ? unwrapChild(children2[0]) : collapse && children2.length === 1 ? children2[0] : (cstOutput2 || !build && project === void 0) && ctx.build?._parsemanCstCollapse && children2.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children2[0], children2, rawChildren) ? children2[0] : project !== void 0 ? cstOutput2 && ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, ctx.state, tags) : projectChild(children2, project, nodeType) : build ? cstOutput2 && ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, ctx.state, tags) : build(children2, fields, span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children2, 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: children2 };
5053
5130
  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 };
5054
5131
  if (saved.buf !== void 0 || saved.ch !== void 0) {
5055
5132
  pushCstChild(ctx, built, rawEntry2);
@@ -5342,17 +5419,59 @@ function buildLexBodyRecognizer(spec, constants) {
5342
5419
  };
5343
5420
  }
5344
5421
 
5422
+ // src/table/run-support.ts
5423
+ function lineCol(ctx, offset) {
5424
+ const starts = ctx._lineStarts ?? [0];
5425
+ let lo = 0, hi = starts.length - 1;
5426
+ while (lo < hi) {
5427
+ const mid = lo + hi + 1 >> 1;
5428
+ if (starts[mid] <= offset) lo = mid;
5429
+ else hi = mid - 1;
5430
+ }
5431
+ return [lo + 1, offset - starts[lo] + 1];
5432
+ }
5433
+ function spanLines(ctx, start, end) {
5434
+ const s = lineCol(ctx, start), e = lineCol(ctx, end);
5435
+ return { start, end, startLine: s[0], startColumn: s[1], endLine: e[0], endColumn: e[1] };
5436
+ }
5437
+ function rawEntry(v, input, s, e) {
5438
+ if (typeof v === "object" && v !== null) {
5439
+ const tg = v._tag;
5440
+ if (tg === "node" || tg === "leaf" || tg === "parseError") return v;
5441
+ }
5442
+ return {
5443
+ _tag: "leaf",
5444
+ value: typeof v === "string" ? v : typeof v === "object" && v !== null ? input.slice(s, e) : "",
5445
+ span: { start: s, end: e }
5446
+ };
5447
+ }
5448
+ function lead(input, pos) {
5449
+ if (pos >= input.length) return -1;
5450
+ const c = input.charCodeAt(pos);
5451
+ if (c < 55296 || c > 56319) return c;
5452
+ return input.codePointAt(pos) ?? c;
5453
+ }
5454
+ var EMPTY_KIDS = Object.freeze([]);
5455
+ var EMPTY_TRIVIA = Object.freeze([]);
5456
+ function collapseEmpty(ctx, build, input, pos, end, readsRaw) {
5457
+ const collected = ctx._cstBuf !== void 0 || ctx._cstChildren !== void 0;
5458
+ if (collected) popCstChild(ctx);
5459
+ const raw = readsRaw ? [rawEntry(void 0, input, pos, end)] : EMPTY_KIDS;
5460
+ const nd = build(EMPTY_KIDS, void 0, { start: pos, end }, raw, EMPTY_TRIVIA, void 0);
5461
+ if (collected) pushCstChild(ctx, nd, ctx._cstBuf?.noRaw === true ? void 0 : rawEntry(nd, input, pos, end));
5462
+ return nd;
5463
+ }
5464
+
5345
5465
  // src/table/lex-program.ts
5346
5466
  var LEX_NODE_TERMINAL = 0;
5347
5467
  var LEX_NODE_SEQUENCE2 = 1;
5348
5468
  var LEX_NODE_SEQUENCE3 = 2;
5349
5469
  var LEX_NODE_SEQUENCE4 = 3;
5350
5470
  var LEX_NODE_SEQUENCE5 = 4;
5351
- var LEX_NODE_CHOICE2 = 5;
5352
- var LEX_NODE_CHOICE4 = 6;
5353
- var LEX_NODE_CHOICE8 = 7;
5471
+ var LEX_NODE_CHOICE = 5;
5354
5472
  var LEX_NODE_NOT = 8;
5355
5473
  var LEX_NODE_OPTIONAL = 9;
5474
+ var LEX_NODE_REPEAT = 10;
5356
5475
  function lexProgramDigest(words) {
5357
5476
  let hash = 2166136261;
5358
5477
  for (const word2 of words) {
@@ -5381,85 +5500,114 @@ function trackLexLines(ctx, input, end) {
5381
5500
  ctx._lineScannedTo = end;
5382
5501
  }
5383
5502
  function terminalNode(matcher, failure, tracksLines) {
5384
- const match = (input, pos) => {
5385
- const result = matcher(input, pos);
5386
- return result < 0 ? -1 : result / 2;
5387
- };
5388
5503
  return {
5389
- match,
5504
+ match: (input, pos) => {
5505
+ const result = matcher(input, pos);
5506
+ return result < 0 ? -1 : result / 2;
5507
+ },
5390
5508
  run: (input, pos, ctx) => {
5391
- const end = match(input, pos);
5392
- if (end < 0) {
5509
+ const result = matcher(input, pos);
5510
+ if (result < 0) {
5393
5511
  ctx._fe = pos;
5394
5512
  ctx._fx = failure;
5395
5513
  if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
5396
5514
  return -1;
5397
5515
  }
5516
+ const end = result / 2;
5398
5517
  if (tracksLines) trackLexLines(ctx, input, end);
5399
5518
  return end;
5400
5519
  }
5401
5520
  };
5402
5521
  }
5403
5522
  function sequence2(a, b) {
5523
+ const am = a.match, bm = b.match, ar = a.run, br = b.run;
5404
5524
  return {
5405
5525
  match: (input, pos) => {
5406
- const e0 = a.match(input, pos);
5407
- return e0 < 0 ? -1 : b.match(input, e0);
5526
+ const e0 = am(input, pos);
5527
+ return e0 < 0 ? -1 : bm(input, e0);
5408
5528
  },
5409
5529
  run: (input, pos, ctx) => {
5410
- const e0 = a.run(input, pos, ctx);
5530
+ const e0 = ar(input, pos, ctx);
5411
5531
  if (e0 < 0) return -1;
5412
5532
  ctx._fc = false;
5413
- return b.run(input, e0, ctx);
5533
+ return br(input, e0, ctx);
5414
5534
  }
5415
5535
  };
5416
5536
  }
5417
5537
  function sequence3(a, b, c) {
5538
+ const am = a.match, bm = b.match, cm = c.match, ar = a.run, br = b.run, cr = c.run;
5418
5539
  return {
5419
5540
  match: (input, pos) => {
5420
- const e0 = a.match(input, pos);
5541
+ const e0 = am(input, pos);
5421
5542
  if (e0 < 0) return -1;
5422
- const e1 = b.match(input, e0);
5423
- return e1 < 0 ? -1 : c.match(input, e1);
5543
+ const e1 = bm(input, e0);
5544
+ return e1 < 0 ? -1 : cm(input, e1);
5424
5545
  },
5425
5546
  run: (input, pos, ctx) => {
5426
- const e0 = a.run(input, pos, ctx);
5547
+ const e0 = ar(input, pos, ctx);
5427
5548
  if (e0 < 0) return -1;
5428
5549
  ctx._fc = false;
5429
- const e1 = b.run(input, e0, ctx);
5550
+ const e1 = br(input, e0, ctx);
5430
5551
  if (e1 < 0) return -1;
5431
5552
  ctx._fc = false;
5432
- return c.run(input, e1, ctx);
5553
+ return cr(input, e1, ctx);
5433
5554
  }
5434
5555
  };
5435
5556
  }
5436
5557
  function sequence4(a, b, c, d) {
5437
- const abc = sequence3(a, b, c);
5558
+ const am = a.match, bm = b.match, cm = c.match, dm = d.match;
5559
+ const ar = a.run, br = b.run, cr = c.run, dr = d.run;
5438
5560
  return {
5439
5561
  match: (input, pos) => {
5440
- const end = abc.match(input, pos);
5441
- return end < 0 ? -1 : d.match(input, end);
5562
+ const e0 = am(input, pos);
5563
+ if (e0 < 0) return -1;
5564
+ const e1 = bm(input, e0);
5565
+ if (e1 < 0) return -1;
5566
+ const e2 = cm(input, e1);
5567
+ return e2 < 0 ? -1 : dm(input, e2);
5442
5568
  },
5443
5569
  run: (input, pos, ctx) => {
5444
- const end = abc.run(input, pos, ctx);
5445
- if (end < 0) return -1;
5570
+ const e0 = ar(input, pos, ctx);
5571
+ if (e0 < 0) return -1;
5572
+ ctx._fc = false;
5573
+ const e1 = br(input, e0, ctx);
5574
+ if (e1 < 0) return -1;
5575
+ ctx._fc = false;
5576
+ const e2 = cr(input, e1, ctx);
5577
+ if (e2 < 0) return -1;
5446
5578
  ctx._fc = false;
5447
- return d.run(input, end, ctx);
5579
+ return dr(input, e2, ctx);
5448
5580
  }
5449
5581
  };
5450
5582
  }
5451
5583
  function sequence5(a, b, c, d, e) {
5452
- const abcd = sequence4(a, b, c, d);
5584
+ const am = a.match, bm = b.match, cm = c.match, dm = d.match, em = e.match;
5585
+ const ar = a.run, br = b.run, cr = c.run, dr = d.run, er = e.run;
5453
5586
  return {
5454
5587
  match: (input, pos) => {
5455
- const end = abcd.match(input, pos);
5456
- return end < 0 ? -1 : e.match(input, end);
5588
+ const e0 = am(input, pos);
5589
+ if (e0 < 0) return -1;
5590
+ const e1 = bm(input, e0);
5591
+ if (e1 < 0) return -1;
5592
+ const e2 = cm(input, e1);
5593
+ if (e2 < 0) return -1;
5594
+ const e3 = dm(input, e2);
5595
+ return e3 < 0 ? -1 : em(input, e3);
5457
5596
  },
5458
5597
  run: (input, pos, ctx) => {
5459
- const end = abcd.run(input, pos, ctx);
5460
- if (end < 0) return -1;
5598
+ const e0 = ar(input, pos, ctx);
5599
+ if (e0 < 0) return -1;
5600
+ ctx._fc = false;
5601
+ const e1 = br(input, e0, ctx);
5602
+ if (e1 < 0) return -1;
5603
+ ctx._fc = false;
5604
+ const e2 = cr(input, e1, ctx);
5605
+ if (e2 < 0) return -1;
5461
5606
  ctx._fc = false;
5462
- return e.run(input, end, ctx);
5607
+ const e3 = dr(input, e2, ctx);
5608
+ if (e3 < 0) return -1;
5609
+ ctx._fc = false;
5610
+ return er(input, e3, ctx);
5463
5611
  }
5464
5612
  };
5465
5613
  }
@@ -5472,9 +5620,9 @@ function appendExpected(acc, values) {
5472
5620
  function choiceNode(arms, classes, armExpected, choiceExpected) {
5473
5621
  let matchTail = () => -1;
5474
5622
  for (let i = arms.length - 1; i >= 0; i--) {
5475
- const arm = arms[i], next = matchTail;
5623
+ const armMatch = arms[i].match, next = matchTail;
5476
5624
  matchTail = (input, pos) => {
5477
- const end = arm.match(input, pos);
5625
+ const end = armMatch(input, pos);
5478
5626
  return end < 0 ? next(input, pos) : end;
5479
5627
  };
5480
5628
  }
@@ -5484,7 +5632,7 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
5484
5632
  return -1;
5485
5633
  };
5486
5634
  for (let i = arms.length - 1; i >= 0; i--) {
5487
- const arm = arms[i], cls = classes[i], staticExpected = armExpected[i], next = tail;
5635
+ const armRun = arms[i].run, cls = classes[i], staticExpected = armExpected[i], next = tail;
5488
5636
  tail = (input, pos, ctx, lead2, acc, best) => {
5489
5637
  if (cls !== void 0 && !classHas(cls, lead2)) {
5490
5638
  return next(
@@ -5497,7 +5645,7 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
5497
5645
  );
5498
5646
  }
5499
5647
  ctx._fc = false;
5500
- const end = arm.run(input, pos, ctx);
5648
+ const end = armRun(input, pos, ctx);
5501
5649
  if (end >= 0) return end;
5502
5650
  const at = ctx._fe ?? pos;
5503
5651
  if (at > best) {
@@ -5524,11 +5672,58 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
5524
5672
  )
5525
5673
  };
5526
5674
  }
5675
+ function exclusiveChoiceNode(arms, classes, choiceFx) {
5676
+ const ascii = (classes.length <= 128 ? new Int8Array(128) : new Int32Array(128)).fill(-1);
5677
+ const hi = [];
5678
+ for (let i = 0; i < classes.length; i++) {
5679
+ const cls = classes[i];
5680
+ for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) ascii[c] = i;
5681
+ for (let r = 0; r < cls.hi.length; r += 2) hi.push(cls.hi[r], cls.hi[r + 1], i);
5682
+ }
5683
+ const select = (code) => {
5684
+ if (code < 0) return -1;
5685
+ if (code < 128) return ascii[code];
5686
+ for (let r = 0; r < hi.length; r += 3) if (code >= hi[r] && code <= hi[r + 1]) return hi[r + 2];
5687
+ return -1;
5688
+ };
5689
+ let matchArm = () => -1;
5690
+ let selectRun = () => -1;
5691
+ for (let i = arms.length - 1; i >= 0; i--) {
5692
+ const armMatch = arms[i].match, armRun = arms[i].run, nextMatch = matchArm, nextRun = selectRun;
5693
+ matchArm = (selected, input, pos) => selected === i ? armMatch(input, pos) : nextMatch(selected, input, pos);
5694
+ selectRun = (selected, input, pos, ctx) => selected === i ? armRun(input, pos, ctx) : nextRun(selected, input, pos, ctx);
5695
+ }
5696
+ const runArm = (input, pos, ctx) => {
5697
+ const arm = select(lead(input, pos));
5698
+ if (arm >= 0) {
5699
+ ctx._fc = false;
5700
+ const end = selectRun(arm, input, pos, ctx);
5701
+ if (end >= 0) return end;
5702
+ if (committed(ctx)) return -1;
5703
+ const failed = ctx._fx;
5704
+ if (failed !== void 0 && failed.length > 0) {
5705
+ ctx._fe = pos;
5706
+ return -1;
5707
+ }
5708
+ }
5709
+ ctx._fe = pos;
5710
+ ctx._fx = choiceFx;
5711
+ return -1;
5712
+ };
5713
+ return {
5714
+ match: (input, pos) => {
5715
+ const arm = select(lead(input, pos));
5716
+ return arm < 0 ? -1 : matchArm(arm, input, pos);
5717
+ },
5718
+ run: runArm
5719
+ };
5720
+ }
5527
5721
  function notNode(body, failure) {
5722
+ const bodyMatch = body.match;
5528
5723
  return {
5529
- match: (input, pos) => body.match(input, pos) < 0 ? pos : -1,
5724
+ match: (input, pos) => bodyMatch(input, pos) < 0 ? pos : -1,
5530
5725
  run: (input, pos, ctx) => {
5531
- if (body.match(input, pos) < 0) return pos;
5726
+ if (bodyMatch(input, pos) < 0) return pos;
5532
5727
  ctx._fe = pos;
5533
5728
  ctx._fx = failure;
5534
5729
  return -1;
@@ -5536,18 +5731,57 @@ function notNode(body, failure) {
5536
5731
  };
5537
5732
  }
5538
5733
  function optionalNode(body) {
5734
+ const bodyMatch = body.match, bodyRun = body.run;
5539
5735
  return {
5540
5736
  match: (input, pos) => {
5541
- const end = body.match(input, pos);
5737
+ const end = bodyMatch(input, pos);
5542
5738
  return end < 0 ? pos : end;
5543
5739
  },
5544
5740
  run: (input, pos, ctx) => {
5545
5741
  ctx._fc = false;
5546
- const end = body.run(input, pos, ctx);
5742
+ const end = bodyRun(input, pos, ctx);
5547
5743
  return end < 0 && !committed(ctx) ? pos : end;
5548
5744
  }
5549
5745
  };
5550
5746
  }
5747
+ function repeatNode(item, min, max) {
5748
+ const itemMatch = item.match, itemRun = item.run;
5749
+ return {
5750
+ match: (input, pos) => {
5751
+ let cur = pos;
5752
+ let count = 0;
5753
+ for (; ; ) {
5754
+ if (max >= 0 && count >= max) break;
5755
+ const optional2 = count >= min && (count > 0 || min === 0);
5756
+ if (optional2 && cur >= input.length) break;
5757
+ const end = itemMatch(input, cur);
5758
+ if (end < 0 || optional2 && end === cur) break;
5759
+ cur = end;
5760
+ count++;
5761
+ }
5762
+ return count < min ? -1 : cur;
5763
+ },
5764
+ run: (input, pos, ctx) => {
5765
+ let cur = pos;
5766
+ let count = 0;
5767
+ for (; ; ) {
5768
+ if (max >= 0 && count >= max) break;
5769
+ const optional2 = count >= min && (count > 0 || min === 0);
5770
+ if (optional2 && cur >= input.length) break;
5771
+ ctx._fc = false;
5772
+ const end = itemRun(input, cur, ctx);
5773
+ if (end < 0) {
5774
+ if (committed(ctx)) return -1;
5775
+ break;
5776
+ }
5777
+ if (optional2 && end === cur) break;
5778
+ cur = end;
5779
+ count++;
5780
+ }
5781
+ return count < min ? -1 : cur;
5782
+ }
5783
+ };
5784
+ }
5551
5785
  function fixedTreeRunner(words, matchers, classes, expected) {
5552
5786
  const stack = [];
5553
5787
  const pop = () => {
@@ -5575,9 +5809,14 @@ function fixedTreeRunner(words, matchers, classes, expected) {
5575
5809
  else stack.push(sequence5(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4]));
5576
5810
  continue;
5577
5811
  }
5578
- if (op >= LEX_NODE_CHOICE2 && op <= LEX_NODE_CHOICE8) {
5579
- const count = op === LEX_NODE_CHOICE2 ? 2 : op === LEX_NODE_CHOICE4 ? 4 : 8;
5812
+ if (op === LEX_NODE_CHOICE) {
5813
+ const count = words[at++];
5814
+ const exclusive = words[at++];
5815
+ if (exclusive !== 0 && exclusive !== 1) throw new TypeError("table lexical tree choice has an invalid dispatch mode");
5580
5816
  const choiceFx = expected[words[at++]];
5817
+ if (!Number.isInteger(count) || count < 2 || count > stack.length) {
5818
+ throw new TypeError("table lexical tree choice has an invalid arm count");
5819
+ }
5581
5820
  if (choiceFx === void 0) throw new TypeError("table lexical tree choice has an invalid expected set");
5582
5821
  const armClasses = [];
5583
5822
  const armFx = [];
@@ -5590,7 +5829,7 @@ function fixedTreeRunner(words, matchers, classes, expected) {
5590
5829
  armFx.push(fx);
5591
5830
  }
5592
5831
  const arms = Array.from({ length: count }, pop).reverse();
5593
- stack.push(choiceNode(arms, armClasses, armFx, choiceFx));
5832
+ stack.push(exclusive === 1 ? exclusiveChoiceNode(arms, armClasses, choiceFx) : choiceNode(arms, armClasses, armFx, choiceFx));
5594
5833
  continue;
5595
5834
  }
5596
5835
  if (op === LEX_NODE_NOT) {
@@ -5603,6 +5842,14 @@ function fixedTreeRunner(words, matchers, classes, expected) {
5603
5842
  stack.push(optionalNode(pop()));
5604
5843
  continue;
5605
5844
  }
5845
+ if (op === LEX_NODE_REPEAT) {
5846
+ const min = words[at++], max = words[at++];
5847
+ if (!Number.isInteger(min) || min < 0 || !Number.isInteger(max) || max >= 0 && max < min) {
5848
+ throw new TypeError("table lexical tree repeat has invalid bounds");
5849
+ }
5850
+ stack.push(repeatNode(pop(), min, max));
5851
+ continue;
5852
+ }
5606
5853
  throw new TypeError("table lexical tree has an unknown fixed body");
5607
5854
  }
5608
5855
  if (stack.length !== 1) throw new TypeError("table lexical tree does not resolve to one root body");
@@ -5757,6 +6004,12 @@ function scanRefs(s) {
5757
6004
  refs.push(...s.skip);
5758
6005
  return refs;
5759
6006
  }
6007
+ function assemblyExtraIps(prog) {
6008
+ const ips = [];
6009
+ for (const s of prog.scans ?? []) for (const r of scanRefs(s)) ips.push(r[0]);
6010
+ for (const set of prog.scanSkip ?? []) for (const r of set) ips.push(r[0]);
6011
+ return ips;
6012
+ }
5760
6013
  function expandCompact(p) {
5761
6014
  if ("code" in p) return p;
5762
6015
  return ownTableProgram({
@@ -5887,6 +6140,11 @@ function classHas2(cls, code) {
5887
6140
  for (let i = 0; i < hi.length; i += 2) if (code >= hi[i] && code <= hi[i + 1]) return true;
5888
6141
  return false;
5889
6142
  }
6143
+ function dispatchIsExclusive(arms, cc) {
6144
+ const resolved = [];
6145
+ for (const ci of arms) if (ci >= 0) resolved[ci] = resolveClass(cc[ci]);
6146
+ return resolveDispatch(arms, resolved).exclusive;
6147
+ }
5890
6148
  function resolveDispatch(arms, cc) {
5891
6149
  const ascii = new Uint8Array(128);
5892
6150
  const hi = [];
@@ -6857,6 +7115,111 @@ function classifyRuleMap(ruleMap) {
6857
7115
  };
6858
7116
  }
6859
7117
 
7118
+ // src/table/factor-choice.ts
7119
+ var DERIVED = /* @__PURE__ */ new Set(["_tag", "_meta", "_def", "_parseScalar", "_stickyRegex", "parse"]);
7120
+ function isCombinator(v) {
7121
+ return typeof v === "object" && v !== null && "_def" in v && "_meta" in v;
7122
+ }
7123
+ function sameComb(a, b, depth) {
7124
+ if (a === b) return true;
7125
+ if (depth > 32 || a._tag !== b._tag) return false;
7126
+ for (const k of Object.keys(a)) if (!DERIVED.has(k)) return false;
7127
+ for (const k of Object.keys(b)) if (!DERIVED.has(k)) return false;
7128
+ return sameFields(a._def, b._def, depth, void 0);
7129
+ }
7130
+ function sameValue(u, v, depth) {
7131
+ if (u === v) return true;
7132
+ if (isCombinator(u) && isCombinator(v)) return sameComb(u, v, depth + 1);
7133
+ if (Array.isArray(u) && Array.isArray(v)) return u.length === v.length && u.every((x, i) => sameValue(x, v[i], depth));
7134
+ if (typeof u === "object" && u !== null && typeof v === "object" && v !== null && Object.getPrototypeOf(u) === Object.prototype && Object.getPrototypeOf(v) === Object.prototype) {
7135
+ return sameFields(u, v, depth, void 0);
7136
+ }
7137
+ return false;
7138
+ }
7139
+ function sameFields(x, y, depth, skip) {
7140
+ const kx = Object.keys(x).filter((k) => k !== skip && x[k] !== void 0);
7141
+ const ky = Object.keys(y).filter((k) => k !== skip && y[k] !== void 0);
7142
+ if (kx.length !== ky.length) return false;
7143
+ for (const k of kx) {
7144
+ if (!(k in y)) return false;
7145
+ const u = x[k];
7146
+ const v = y[k];
7147
+ if (k === "fn" && typeof u === "function" && typeof v === "function" && u !== v) {
7148
+ if (typeof x.fnSrc !== "string" || x.fnSrc === "" || x.fnSrc !== y.fnSrc) return false;
7149
+ continue;
7150
+ }
7151
+ if (!sameValue(u, v, depth)) return false;
7152
+ }
7153
+ return true;
7154
+ }
7155
+ function rewrap(w, body) {
7156
+ const d = w._def;
7157
+ let out;
7158
+ if (d.tag === "leaf") {
7159
+ out = d.cstValue === "source" ? sourceLeaf(body, d.fn) : leaf(body, d.fn);
7160
+ if (d.fnSrc !== void 0) out._def.fnSrc = d.fnSrc;
7161
+ } else if (d.tag === "grammar") {
7162
+ out = d.clearTrivia === true ? noTrivia(body) : parser({ trivia: d.triviaParser ?? null }, body);
7163
+ } else return void 0;
7164
+ return sameFields(d, out._def, 0, "parser") ? out : void 0;
7165
+ }
7166
+ function unusedOf(seq) {
7167
+ return seq._def.tag === "sequence" && seq._def.valueUnused === true;
7168
+ }
7169
+ function never(c) {
7170
+ const t = c._def.tag;
7171
+ return t === "optional" || t === "many";
7172
+ }
7173
+ function factorSharedEnds(d) {
7174
+ const arms = d.parsers;
7175
+ if (arms.length < 2) return void 0;
7176
+ if (d.strategy.tag !== "firstMatch" && d.strategy.tag !== "sharedPrefix") return void 0;
7177
+ if (d.gates.some((g) => g !== null) || d.autoNot.some((a) => a !== null)) return void 0;
7178
+ const shapes = [];
7179
+ for (const arm of arms) {
7180
+ const wrappers = [];
7181
+ let c = arm;
7182
+ while ((c._def.tag === "leaf" || c._def.tag === "grammar") && wrappers.length < 4) {
7183
+ wrappers.push(c);
7184
+ c = c._def.parser;
7185
+ }
7186
+ if (c._def.tag !== "sequence" || c._def.parsers.length < 2) return void 0;
7187
+ shapes.push({ wrappers, terms: c._def.parsers, seq: c });
7188
+ }
7189
+ const first = shapes[0];
7190
+ const n = first.terms.length;
7191
+ for (const s of shapes) {
7192
+ if (s.wrappers.length !== first.wrappers.length || s.terms.length !== n) return void 0;
7193
+ if (unusedOf(s.seq) !== unusedOf(first.seq)) return void 0;
7194
+ for (let j = 0; j < s.wrappers.length; j++) {
7195
+ const a = first.wrappers[j]._def;
7196
+ const b = s.wrappers[j]._def;
7197
+ if (a.tag !== b.tag || !sameFields(a, b, 0, "parser")) return void 0;
7198
+ }
7199
+ }
7200
+ let at = -1;
7201
+ for (let i = 0; i < n; i++) {
7202
+ if (shapes.every((s) => sameComb(s.terms[i], first.terms[i], 0))) continue;
7203
+ if (at >= 0) return void 0;
7204
+ at = i;
7205
+ }
7206
+ if (at < 0) return void 0;
7207
+ for (let i = at + 1; i < n; i++) if (!never(first.terms[i])) return void 0;
7208
+ if (arms.some((a) => mayCommitFailure(a))) return void 0;
7209
+ const middle = choice(...shapes.map((s) => s.terms[at]));
7210
+ if (middle._def.tag === "choice" && middle._def.autoNot.some((a) => a !== null)) return void 0;
7211
+ const st = middle._def.tag === "choice" ? middle._def.strategy : void 0;
7212
+ if (st === void 0 || st.tag !== "firstMatch" && st.tag !== "sharedPrefix" && !(st.tag === "literalsLongestFirst" && st.sortedIndices.every((x, i) => x === i))) return void 0;
7213
+ let out = sequence(
7214
+ ...[...first.terms.slice(0, at), middle, ...first.terms.slice(at + 1)]
7215
+ );
7216
+ if (unusedOf(first.seq)) {
7217
+ out._def.valueUnused = true;
7218
+ }
7219
+ for (let j = first.wrappers.length - 1; j >= 0 && out !== void 0; j--) out = rewrap(first.wrappers[j], out);
7220
+ return out === void 0 ? void 0 : attempt(out);
7221
+ }
7222
+
6860
7223
  // src/table/ops.ts
6861
7224
  var OP_LIT = 1;
6862
7225
  var OP_RX = 2;
@@ -6900,6 +7263,7 @@ var OP_SCOPE_PLAIN = 41;
6900
7263
  var OP_LEX_BODY = 42;
6901
7264
  var OP_LEX_PROGRAM = 43;
6902
7265
  var OP_SOURCE_LEAF = 44;
7266
+ var OP_RGATE = 45;
6903
7267
  var OP_DISPATCH = 25;
6904
7268
  var OP_ROUTED = 26;
6905
7269
  var OP_NAMES = {
@@ -6919,6 +7283,7 @@ var OP_NAMES = {
6919
7283
  [OP_PEEK]: "PEEK",
6920
7284
  [OP_LEAF]: "LEAF",
6921
7285
  [OP_SOURCE_LEAF]: "SOURCE_LEAF",
7286
+ [OP_RGATE]: "RGATE",
6922
7287
  [OP_EMPTY]: "EMPTY",
6923
7288
  [OP_LIT_TRACK]: "LIT_TRACK",
6924
7289
  [OP_RX_TRACK]: "RX_TRACK",
@@ -6999,7 +7364,10 @@ function selectOptionalSuffixLexBody(ir) {
6999
7364
  const token2 = { strategy: "token", estimatedOps: 2, body };
7000
7365
  return token2.estimatedOps < character.estimatedOps ? token2 : character;
7001
7366
  }
7002
- function directTokenBodyParser(parser2, resolve) {
7367
+ function reinstallsRuleTrivia(reference, target) {
7368
+ return (reference._meta.grammarTrivia ?? target._meta.grammarTrivia) !== void 0 && hasOwnTriviaBoundary(target);
7369
+ }
7370
+ function directTokenBodyParser(parser2, resolve, scope) {
7003
7371
  const outer = parser2._def;
7004
7372
  if (outer.tag !== "token") return void 0;
7005
7373
  let body = outer.parser;
@@ -7009,12 +7377,13 @@ function directTokenBodyParser(parser2, resolve) {
7009
7377
  const wrapper = body._def;
7010
7378
  if (wrapper.tag === "grammar") {
7011
7379
  if (wrapper.clearTrivia !== true || wrapper.triviaParser !== void 0 || wrapper.captureTrivia === true || wrapper.rootCapture === "opaque" || wrapper.constructionTrackLines !== "inherit" || wrapper.constructionCaptureTriviaKinds !== void 0) return void 0;
7380
+ if (scope !== void 0) scope.cleared = true;
7012
7381
  body = wrapper.parser;
7013
7382
  continue;
7014
7383
  }
7015
7384
  if (wrapper.tag === "lazy") {
7016
7385
  const target = resolvedLazyTarget(body, resolve);
7017
- if (target === void 0) return void 0;
7386
+ if (target === void 0 || reinstallsRuleTrivia(body, target)) return void 0;
7018
7387
  body = target;
7019
7388
  continue;
7020
7389
  }
@@ -7186,7 +7555,7 @@ function directNot2TokenBody(parser2, resolve) {
7186
7555
  terminal
7187
7556
  };
7188
7557
  }
7189
- function directFixedLexNode(parser2, resolve, active, pureOnly = false) {
7558
+ function directFixedLexNode(parser2, resolve, active, pureOnly = false, cleared = false) {
7190
7559
  let current = parser2;
7191
7560
  const wrappers = /* @__PURE__ */ new Set();
7192
7561
  while (!wrappers.has(current)) {
@@ -7194,7 +7563,7 @@ function directFixedLexNode(parser2, resolve, active, pureOnly = false) {
7194
7563
  const def = current._def;
7195
7564
  if (def.tag === "lazy") {
7196
7565
  const target = resolvedLazyTarget(current, resolve);
7197
- if (target === void 0) return void 0;
7566
+ if (target === void 0 || reinstallsRuleTrivia(current, target)) return void 0;
7198
7567
  current = target;
7199
7568
  continue;
7200
7569
  }
@@ -7212,30 +7581,33 @@ function directFixedLexNode(parser2, resolve, active, pureOnly = false) {
7212
7581
  if (terminal !== void 0) return { kind: "terminal", terminal };
7213
7582
  const def = current._def;
7214
7583
  if (def.tag === "grammar") {
7584
+ if (def.triviaParser === void 0 && def.captureTrivia !== true && def.rootCapture !== "opaque" && def.constructionCaptureTriviaKinds === void 0) {
7585
+ return directFixedLexNode(def.parser, resolve, active, pureOnly, cleared || def.clearTrivia === true);
7586
+ }
7215
7587
  if (!pureOnly || def.parser._def.tag !== "token" && (def.clearTrivia !== true || def.triviaParser !== void 0 || def.captureTrivia === true || def.rootCapture === "opaque")) return void 0;
7216
- return directFixedLexNode(def.parser, resolve, active, true);
7588
+ return directFixedLexNode(def.parser, resolve, active, true, cleared);
7217
7589
  }
7218
7590
  if (def.tag === "sequence") {
7219
7591
  if (def.parsers.length < 2 || def.parsers.length > 5) return void 0;
7220
- const parts = def.parsers.map((part) => directFixedLexNode(part, resolve, active, pureOnly));
7592
+ const parts = def.parsers.map((part) => directFixedLexNode(part, resolve, active, pureOnly, cleared));
7221
7593
  if (parts.some((part) => part === void 0)) return void 0;
7222
7594
  return { kind: "sequence", parts };
7223
7595
  }
7224
7596
  if (def.tag === "choice") {
7225
- 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;
7226
- const arms = def.parsers.map((arm) => directFixedLexNode(arm, resolve, active, pureOnly));
7597
+ if (def.parsers.length < 2 || def.strategy.tag !== "firstMatch" || def.gates.some((gate2) => gate2 !== null) || def.autoNot.some((check) => check !== null)) return void 0;
7598
+ const arms = def.parsers.map((arm) => directFixedLexNode(arm, resolve, active, pureOnly, cleared));
7227
7599
  if (arms.some((arm) => arm === void 0)) return void 0;
7228
- const final = classifyFinalChoice(def.parsers, resolve);
7229
7600
  return {
7230
7601
  kind: "choice",
7231
7602
  arms,
7232
- firstSets: final.firstSets,
7603
+ parsers: def.parsers,
7604
+ cleared,
7233
7605
  armExpected: def.parsers.map(deriveExpected),
7234
7606
  expected: def.parsers.flatMap(deriveExpected)
7235
7607
  };
7236
7608
  }
7237
7609
  if (def.tag === "not") {
7238
- const body = directFixedLexNode(def.parser, resolve, active, true);
7610
+ const body = directFixedLexNode(def.parser, resolve, active, true, cleared);
7239
7611
  return body === void 0 ? void 0 : {
7240
7612
  kind: "not",
7241
7613
  body,
@@ -7243,18 +7615,28 @@ function directFixedLexNode(parser2, resolve, active, pureOnly = false) {
7243
7615
  };
7244
7616
  }
7245
7617
  if (def.tag === "optional") {
7246
- const body = directFixedLexNode(def.parser, resolve, active, pureOnly);
7618
+ const body = directFixedLexNode(def.parser, resolve, active, pureOnly, cleared);
7247
7619
  return body === void 0 ? void 0 : { kind: "optional", body };
7248
7620
  }
7621
+ if (def.tag === "many" || def.tag === "oneOrMore") {
7622
+ const body = directFixedLexNode(def.parser, resolve, active, pureOnly, cleared);
7623
+ return body === void 0 ? void 0 : {
7624
+ kind: "repeat",
7625
+ body,
7626
+ min: def.tag === "many" ? 0 : def.min,
7627
+ max: def.max ?? -1
7628
+ };
7629
+ }
7249
7630
  return void 0;
7250
7631
  } finally {
7251
7632
  active.delete(current);
7252
7633
  }
7253
7634
  }
7254
7635
  function directFixedTokenBody(parser2, resolve) {
7255
- const body = directTokenBodyParser(parser2, resolve);
7636
+ const scope = { cleared: false };
7637
+ const body = directTokenBodyParser(parser2, resolve, scope);
7256
7638
  if (body === void 0) return void 0;
7257
- const root = directFixedLexNode(body, resolve, /* @__PURE__ */ new Set());
7639
+ const root = directFixedLexNode(body, resolve, /* @__PURE__ */ new Set(), false, scope.cleared);
7258
7640
  return root === void 0 ? void 0 : { kind: "fixed-tree", root };
7259
7641
  }
7260
7642
  function directBalancedTokenBody(parser2, resolve) {
@@ -7501,13 +7883,16 @@ var Encoder = class {
7501
7883
  }
7502
7884
  case "choice": {
7503
7885
  for (const arm of node2.arms) if (!emitNode(arm)) return false;
7504
- const op = node2.arms.length === 2 ? LEX_NODE_CHOICE2 : node2.arms.length === 4 ? LEX_NODE_CHOICE4 : node2.arms.length === 8 ? LEX_NODE_CHOICE8 : -1;
7505
- if (op < 0) return false;
7506
- words.push(op, this.expected(node2.expected));
7886
+ const final = classifyFinalChoice(
7887
+ node2.parsers,
7888
+ this.refResolver(),
7889
+ node2.cleared ? void 0 : this.activeTrivia
7890
+ );
7891
+ const classes = final.firstSets.map((first, i) => final.nullable[i] ? -1 : this.charClass(first));
7892
+ const exclusive = final.exclusive && classes.every((cls) => cls >= 0);
7893
+ words.push(LEX_NODE_CHOICE, node2.arms.length, exclusive ? 1 : 0, this.expected(node2.expected));
7507
7894
  for (let i = 0; i < node2.arms.length; i++) {
7508
- const first = node2.firstSets[i];
7509
- words.push(first.kind === "ranges" ? this.charClass(first) : -1);
7510
- words.push(this.expected(node2.armExpected[i]));
7895
+ words.push(classes[i], this.expected(node2.armExpected[i]));
7511
7896
  }
7512
7897
  return true;
7513
7898
  }
@@ -7519,6 +7904,10 @@ var Encoder = class {
7519
7904
  if (!emitNode(node2.body)) return false;
7520
7905
  words.push(LEX_NODE_OPTIONAL);
7521
7906
  return true;
7907
+ case "repeat":
7908
+ if (!emitNode(node2.body)) return false;
7909
+ words.push(LEX_NODE_REPEAT, node2.min, node2.max);
7910
+ return true;
7522
7911
  }
7523
7912
  };
7524
7913
  if (!emitNode(body.root)) return void 0;
@@ -7846,6 +8235,33 @@ var Encoder = class {
7846
8235
  return childrenOf2(def);
7847
8236
  }
7848
8237
  }
8238
+ /**
8239
+ * THE FIRST-CHARACTER GATE OF AN `optional`, `not` OR `peek` CHILD.
8240
+ *
8241
+ * A non-nullable child cannot match at a character outside its first set, so
8242
+ * the wrapper's outcome there is already decided: `optional` yields `null`,
8243
+ * `not` succeeds, `peek` fails with its own set. The interpreter's `optional`
8244
+ * makes that test itself (`repeat.ts` `startsFirstSet`); the table entered the
8245
+ * child — a rollback mark, the call, the child's own failure — to learn it.
8246
+ *
8247
+ * The gate is an `OP_GATE` row around the child, so every engine runs it
8248
+ * unchanged, a probe or tolerant parse forwards through it as for a node's
8249
+ * gate, and the wrapper's row keeps its layout. The engines test the class
8250
+ * before taking the wrapper's mark. The first set is resolved through
8251
+ * `winners`, the analysis a choice arm's gate uses, so a composed rule's set
8252
+ * is the merged one. A scalar `not` child stays bare: `scalarTerminalNotChild`
8253
+ * already reduces it to one recognizer call.
8254
+ */
8255
+ lookaheadGate(p, child) {
8256
+ const op = this.code[child];
8257
+ 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;
8258
+ const rr = this.refResolver();
8259
+ if (matchesEmpty(p, /* @__PURE__ */ new Set(), rr)) return child;
8260
+ const cls = this.charClass(firstSetOf(p, /* @__PURE__ */ new Set(), rr, this.activeTrivia));
8261
+ if (cls < 0) return child;
8262
+ const e = deriveExpected(p);
8263
+ return this.emit(OP_GATE, cls, child, this.expected(e.length > 0 ? e : [p._tag]));
8264
+ }
7849
8265
  /** A first set becomes a char class string, or −1 for `any`. */
7850
8266
  charClass(fs) {
7851
8267
  if (fs.kind !== "ranges" || fs.ranges.length === 0) return -1;
@@ -7857,12 +8273,19 @@ var Encoder = class {
7857
8273
  this.ccIndex.set(spec, i);
7858
8274
  return i;
7859
8275
  }
7860
- /** Bind a guard only when its class is already part of the program. Repeat
7861
- * gating must not grow the compact artifact merely to avoid a failed call. */
7862
- existingCharClass(fs) {
7863
- if (fs.kind !== "ranges" || fs.ranges.length === 0) return -1;
7864
- const hit = this.ccIndex.get(encodeClassSpec(fs.ranges));
7865
- return hit !== void 0 && hit < 100 ? hit : -1;
8276
+ /**
8277
+ * The first set a node's or an attempt's fail-fast gate tests. A bare
8278
+ * cross-rule ref resolves through `winners` (a compose OVERRIDE may widen
8279
+ * it). Any other body keeps its construction-time `_meta.firstSet`, except
8280
+ * where that is `any`: under `compose()` a body that reaches a rule of
8281
+ * another piece is built before that rule exists, so its cached set is
8282
+ * `any` and the node got NO gate (jess's `CompoundSelector` was entered at
8283
+ * `{`, `Call` at `}`). The resolved set is the one a choice arm's gate uses,
8284
+ * over the final merged map.
8285
+ */
8286
+ gateFirstSet(p) {
8287
+ const cached = p._meta.firstSet;
8288
+ return p._def.tag === "lazy" || cached.kind === "any" ? firstSetOf(p, /* @__PURE__ */ new Set(), this.refResolver(), this.activeTrivia) : cached;
7866
8289
  }
7867
8290
  /**
7868
8291
  * Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
@@ -7990,6 +8413,50 @@ var Encoder = class {
7990
8413
  if (!hasOwnTriviaBoundary(target)) return ip;
7991
8414
  return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), ip);
7992
8415
  }
8416
+ /**
8417
+ * The `OP_RGATE` operands of a choice arm that opens with `routed()`, or
8418
+ * `undefined`. Through `node()`/scope wrappers and first sequence terms, the
8419
+ * arm's next term after the routed token is found; the gate is that term's
8420
+ * first characters, with the trivia in force at the boundary before it, so
8421
+ * the arm is entered only where it can get past the token. The term must be
8422
+ * unable to match empty or to commit, so a miss is exactly that term failing
8423
+ * at the token's end with its own set.
8424
+ */
8425
+ routedArmGate(arm) {
8426
+ const walk = (p, trivia2, depth) => {
8427
+ if (depth > 16) return void 0;
8428
+ const d = p._def;
8429
+ switch (d.tag) {
8430
+ case "routed":
8431
+ return "end";
8432
+ case "node":
8433
+ return walk(d.parser, trivia2, depth + 1);
8434
+ case "grammar":
8435
+ return walk(d.parser, d.clearTrivia === true ? void 0 : d.triviaParser ?? trivia2, depth + 1);
8436
+ case "sequence": {
8437
+ const head = d.parsers[0];
8438
+ if (head === void 0) return void 0;
8439
+ const r = walk(head, trivia2, depth + 1);
8440
+ if (r !== "end") return r;
8441
+ const next2 = d.parsers[1];
8442
+ return next2 === void 0 ? "end" : { next: next2, boundary: trivia2 };
8443
+ }
8444
+ default:
8445
+ return void 0;
8446
+ }
8447
+ };
8448
+ const follow = walk(arm, this.activeTrivia, 0);
8449
+ if (follow === void 0 || follow === "end") return void 0;
8450
+ const rr = this.refResolver();
8451
+ const { next, boundary } = follow;
8452
+ if (matchesEmpty(next, /* @__PURE__ */ new Set(), rr) || mayCommitFailure(next, rr, this.commitFailureMemo)) return void 0;
8453
+ const nextTag = next._def.tag;
8454
+ if (nextTag !== "literal" && nextTag !== "regex" && nextTag !== "keywords" && nextTag !== "label") return void 0;
8455
+ const first = firstSetOf(next, /* @__PURE__ */ new Set(), rr, boundary);
8456
+ const cls = this.charClass(boundary === void 0 ? first : union(first, firstSetOf(boundary, /* @__PURE__ */ new Set(), rr)));
8457
+ if (cls < 0) return void 0;
8458
+ return { cls, fx: this.expected(deriveExpected(next)) };
8459
+ }
7993
8460
  node(p) {
7994
8461
  const lazyRef = p._def.tag === "lazy";
7995
8462
  const scopeKey = lazyRef ? this.activeTrivia : void 0;
@@ -8114,6 +8581,10 @@ var Encoder = class {
8114
8581
  return head;
8115
8582
  }
8116
8583
  case "choice": {
8584
+ if (this.plan === void 0) {
8585
+ const factored = factorSharedEnds(d);
8586
+ if (factored !== void 0) return this.node(factored).ip;
8587
+ }
8117
8588
  if (d.strategy.tag === "greedyClassify") {
8118
8589
  const superIndex = d.strategy.superIndex;
8119
8590
  const sup = this.node(d.parsers[superIndex]).ip;
@@ -8137,9 +8608,12 @@ var Encoder = class {
8137
8608
  const kids = arms.map((c, k) => {
8138
8609
  const src = order[k];
8139
8610
  const checks = d.autoNot[src];
8140
- const inner = this.node(c).ip;
8141
- const ip = checks === null || checks === void 0 || checks.length === 0 ? inner : this.reject(inner, checks);
8142
8611
  const gate2 = d.gates[src];
8612
+ const plain = (checks === null || checks === void 0 || checks.length === 0) && (gate2 === null || gate2 === void 0);
8613
+ const routedGate = plain ? this.routedArmGate(c) : void 0;
8614
+ const body = this.node(c).ip;
8615
+ const inner = routedGate === void 0 ? body : this.emit(OP_RGATE, routedGate.cls, body, routedGate.fx);
8616
+ const ip = checks === null || checks === void 0 || checks.length === 0 ? inner : this.reject(inner, checks);
8143
8617
  const gated = gate2 === null || gate2 === void 0 ? ip : this.emit(OP_ARMGATE, this.fn(gate2, d.gateSrcs?.[src] ?? null), ip, this.expected(deriveExpected(c)));
8144
8618
  return this.covWrap(gated, armCovIds?.[src], 1);
8145
8619
  });
@@ -8167,6 +8641,12 @@ var Encoder = class {
8167
8641
  if (transactionalFirst[i] !== void 0) classes[i] = -1;
8168
8642
  }
8169
8643
  }
8644
+ if (d.gates.some((g) => g !== null && g !== void 0) && !dispatchIsExclusive(classes, this.cc)) {
8645
+ for (let k = 0; k < classes.length; k++) {
8646
+ const gate2 = d.gates[order[k]];
8647
+ if (gate2 !== null && gate2 !== void 0) classes[k] = -1;
8648
+ }
8649
+ }
8170
8650
  const dispIdx = this.disp.length;
8171
8651
  this.disp.push(classes);
8172
8652
  let rollbackMask = kids.length > 31 ? -1 : 0;
@@ -8196,7 +8676,7 @@ var Encoder = class {
8196
8676
  case "oneOrMore": {
8197
8677
  const child = this.node(d.parser).ip;
8198
8678
  const rr = this.refResolver();
8199
- const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.existingCharClass(firstSetOf(d.parser, /* @__PURE__ */ new Set(), rr, this.activeTrivia));
8679
+ const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.charClass(firstSetOf(d.parser, /* @__PURE__ */ new Set(), rr, this.activeTrivia));
8200
8680
  const op = d.valueUnused ? OP_REPV : OP_REP;
8201
8681
  const min = d.tag === "many" ? 0 : d.min;
8202
8682
  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);
@@ -8220,7 +8700,7 @@ var Encoder = class {
8220
8700
  return d.min >= 2 ? this.emit(OP_REP, child, d.min, d.max ?? -1, sep, flags, this.expected(deriveExpected(d.parser))) : this.emit(OP_REP, child, d.min, d.max ?? -1, sep, flags);
8221
8701
  }
8222
8702
  case "optional": {
8223
- const head = this.emit(OP_OPT, this.node(d.parser).ip);
8703
+ const head = this.emit(OP_OPT, this.lookaheadGate(d.parser, this.node(d.parser).ip));
8224
8704
  if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(head);
8225
8705
  return head;
8226
8706
  }
@@ -8268,8 +8748,8 @@ var Encoder = class {
8268
8748
  // every CST node, so this is load-bearing, not reflection trivia.
8269
8749
  d.tags === void 0 ? -1 : this.constant(d.tags)
8270
8750
  );
8271
- if (matchesEmpty(d.parser)) return body;
8272
- const fs = d.parser._def.tag === "lazy" ? firstSetOf(d.parser, /* @__PURE__ */ new Set(), this.refResolver(), this.activeTrivia) : d.parser._meta.firstSet;
8751
+ if (matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return body;
8752
+ const fs = this.gateFirstSet(d.parser);
8273
8753
  if (fs.kind === "any") return body;
8274
8754
  const cls = this.charClass(fs);
8275
8755
  if (cls < 0) return body;
@@ -8361,7 +8841,7 @@ var Encoder = class {
8361
8841
  // other engine reported `['not(literal)']`. It hid because `expected` is a
8362
8842
  // TOP-LEVEL field on `RunResult` and is NOT part of the identity digest.
8363
8843
  case "not":
8364
- return this.emit(OP_NOT, this.node(d.parser).ip, this.expected(assertionFailureExpected(false, d.parser._tag)));
8844
+ return this.emit(OP_NOT, this.lookaheadGate(d.parser, this.node(d.parser).ip), this.expected(assertionFailureExpected(false, d.parser._tag)));
8365
8845
  case "guard":
8366
8846
  return this.emit(OP_GUARD, this.fn(d.predicate, d.predSrc ?? null), this.expected(["gate"]));
8367
8847
  case "adjacency":
@@ -8382,14 +8862,14 @@ var Encoder = class {
8382
8862
  return this.emit(OP_WITHCTX, this.constant(d.extra), this.node(d.parser).ip);
8383
8863
  }
8384
8864
  case "peek":
8385
- return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected(assertionFailureExpected(true, d.parser._tag)));
8865
+ return this.emit(OP_PEEK, this.lookaheadGate(d.parser, this.node(d.parser).ip), this.expected(assertionFailureExpected(true, d.parser._tag)));
8386
8866
  // A TRANSACTION IS A ROW. See `OP_ATTEMPT` for why the transparent
8387
8867
  // lowering was correct only for a choice arm.
8388
8868
  case "attempt": {
8389
8869
  const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip, d.contain === true ? 1 : 0);
8390
8870
  if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
8391
- const fs = d.parser._def.tag === "lazy" ? firstSetOf(d.parser, /* @__PURE__ */ new Set(), this.refResolver(), this.activeTrivia) : d.parser._meta.firstSet;
8392
- if (fs.kind === "any" || matchesEmpty(d.parser)) return inner;
8871
+ const fs = this.gateFirstSet(d.parser);
8872
+ if (fs.kind === "any" || matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return inner;
8393
8873
  const cls = this.charClass(fs);
8394
8874
  if (cls < 0) return inner;
8395
8875
  const e = deriveExpected(d.parser);
@@ -8457,6 +8937,7 @@ var Encoder = class {
8457
8937
  const slots = (ip) => {
8458
8938
  switch (this.code[ip]) {
8459
8939
  case OP_GATE:
8940
+ case OP_RGATE:
8460
8941
  return [ip + 2];
8461
8942
  case OP_RULE:
8462
8943
  case OP_OPT:
@@ -9687,6 +10168,7 @@ function childSlots(code, ip, out) {
9687
10168
  case OP_LEAF:
9688
10169
  case OP_SOURCE_LEAF:
9689
10170
  case OP_ARMGATE:
10171
+ case OP_RGATE:
9690
10172
  out.push(code[ip + 2]);
9691
10173
  return true;
9692
10174
  // `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
@@ -9770,6 +10252,42 @@ function reachableSites(code, roots) {
9770
10252
  }
9771
10253
  return seen;
9772
10254
  }
10255
+ function passCollapse(code, ip, hostCst) {
10256
+ const flags = code[ip + 3];
10257
+ if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return false;
10258
+ if (flags !== 32 && flags !== 34) return false;
10259
+ let at = code[ip + 2];
10260
+ for (let n = 0; n < 8; n++) {
10261
+ const op = code[at];
10262
+ if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[at + 3] === 0) at = code[at + 2];
10263
+ else if (op === OP_RULE) at = code[at + 1];
10264
+ else break;
10265
+ }
10266
+ return code[at] === OP_NODE;
10267
+ }
10268
+ function gatedPassCollapse(code, ip, hostCst) {
10269
+ const flags = code[ip + 3];
10270
+ if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return void 0;
10271
+ if (flags !== 32 && flags !== 34) return void 0;
10272
+ const seq = code[ip + 2];
10273
+ if (code[seq] !== OP_SEQ && code[seq] !== OP_SEQV) return void 0;
10274
+ const n = code[seq + 1];
10275
+ if (n < 2) return void 0;
10276
+ const leads = [];
10277
+ const lits = [];
10278
+ for (let i = 0; i < n - 1; i++) {
10279
+ const t = code[seq + 2 + i];
10280
+ if (code[t] !== OP_OPT && code[t] !== OP_NOT) return void 0;
10281
+ const g = code[t + 1];
10282
+ if (code[g] === OP_GATE) leads.push(g);
10283
+ else if (code[g] === OP_LIT) lits.push(code[g + 1]);
10284
+ else return void 0;
10285
+ }
10286
+ const last = code[seq + 2 + n - 1];
10287
+ let at = last;
10288
+ 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];
10289
+ return code[at] === OP_NODE ? { leads, lits, last } : void 0;
10290
+ }
9773
10291
  function transfer(code, ip, at, hostCst) {
9774
10292
  const op = code[ip];
9775
10293
  if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
@@ -9781,14 +10299,18 @@ function transfer(code, ip, at, hostCst) {
9781
10299
  }
9782
10300
  if (op === OP_NODE || op === OP_NODE_TRACK) {
9783
10301
  const flags = code[ip + 3];
10302
+ if (passCollapse(code, ip, hostCst)) return at;
10303
+ const gated = gatedPassCollapse(code, ip, hostCst) !== void 0;
9784
10304
  const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && ((flags & ~128) === 2 || flags === 18 || flags === 34);
9785
10305
  if (directChildren) {
9786
- return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
10306
+ const framed2 = { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
10307
+ return gated ? meet(at, framed2) : framed2;
9787
10308
  }
9788
10309
  const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
9789
10310
  const raw = !hostCst && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags & 2) !== 0 ? RAW_OMIT : RAW_CAPTURE;
9790
10311
  if (at.buf && raw === at.raw && cap === at.cap) return at;
9791
- return { tri: at.tri, buf: true, raw, cap };
10312
+ const framed = { tri: at.tri, buf: true, raw, cap };
10313
+ return gated ? meet(at, framed) : framed;
9792
10314
  }
9793
10315
  if (op === OP_TOKEN) {
9794
10316
  if (at.tri === TRI_NONE && !at.buf) return at;
@@ -9826,6 +10348,40 @@ function computeSiteLabels(code, roots, hostCst) {
9826
10348
  }
9827
10349
  return { at: (ip) => labels.get(ip) ?? TOP };
9828
10350
  }
10351
+ function scopeIsIdentity(code, ip, at) {
10352
+ const op = code[ip];
10353
+ if (op !== OP_SCOPE_PLAIN && !(op === OP_SCOPE && code[ip + 3] === 0)) return false;
10354
+ const ki = code[ip + 1];
10355
+ return at.tri === (ki < 0 ? TRI_NONE : ki);
10356
+ }
10357
+ function scanHandoffNeeded(code, ip, labels) {
10358
+ const seen = /* @__PURE__ */ new Set();
10359
+ const stack = [ip];
10360
+ const kids = [];
10361
+ while (stack.length > 0) {
10362
+ const at = stack.pop();
10363
+ if (seen.has(at)) continue;
10364
+ seen.add(at);
10365
+ const l = labels.at(at);
10366
+ if (l.tri === TRI_UNKNOWN) return true;
10367
+ const op = code[at];
10368
+ if (op === OP_SCAN) return true;
10369
+ if (op === OP_TOKEN || op === OP_SCOPE_CAP) continue;
10370
+ 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;
10371
+ kids.length = 0;
10372
+ if (!childSlots(code, at, kids)) return true;
10373
+ for (const c of kids) stack.push(c);
10374
+ }
10375
+ return false;
10376
+ }
10377
+ function triviaLeadRanges(tri, trivia2) {
10378
+ if (tri === TRI_NONE) return [];
10379
+ if (tri < 0) return void 0;
10380
+ const fs = trivia2[tri]?._meta.firstSet;
10381
+ if (fs === void 0) return void 0;
10382
+ if (fs.kind === "empty") return [];
10383
+ return fs.kind === "ranges" && fs.ranges !== void 0 ? fs.ranges : void 0;
10384
+ }
9829
10385
 
9830
10386
  // src/table/scalar-terminal.ts
9831
10387
  function makeScalarRecognizer(op, spec) {
@@ -9863,6 +10419,12 @@ function scalarTerminalNotChild(code, ip) {
9863
10419
  const op = code[child];
9864
10420
  return op === OP_RX || op === OP_LIT ? child : -1;
9865
10421
  }
10422
+ function scalarTerminalPeekChild(code, ip) {
10423
+ if (code[ip] !== OP_PEEK) return -1;
10424
+ const child = code[ip + 1];
10425
+ const op = code[child];
10426
+ return op === OP_RX || op === OP_LIT ? child : -1;
10427
+ }
9866
10428
  function leadingScalarTerminal(code, ip, minDepth = 2, throughAttempt = true, throughPeek = false) {
9867
10429
  const seen = /* @__PURE__ */ new Set();
9868
10430
  let at = ip;
@@ -10040,6 +10602,59 @@ function leadingTriviaFieldAt(code, k, ip) {
10040
10602
  return code[ip] === OP_FIELD && (fieldSpec(k[code[ip + 1]]).bits & FIELD_LEADING_TRIVIA) !== 0;
10041
10603
  }
10042
10604
 
10605
+ // src/table/hold-gap.ts
10606
+ var WRAPPERS = /* @__PURE__ */ new Set([
10607
+ OP_NODE,
10608
+ OP_XFORM,
10609
+ OP_LEAF,
10610
+ OP_SOURCE_LEAF,
10611
+ OP_TOKEN,
10612
+ OP_SCOPE,
10613
+ OP_SCOPE_CAP,
10614
+ OP_SCOPE_PLAIN,
10615
+ OP_FIELD,
10616
+ OP_LABEL,
10617
+ OP_EXPECT,
10618
+ OP_WITHCTX,
10619
+ OP_RULE,
10620
+ OP_ATTEMPT,
10621
+ OP_COV
10622
+ ]);
10623
+ function rowNullable(code, k, ip, memo) {
10624
+ const hit = memo.get(ip);
10625
+ if (hit !== void 0) return hit;
10626
+ memo.set(ip, true);
10627
+ const op = code[ip];
10628
+ const kids = [];
10629
+ let out = true;
10630
+ if (op === OP_GATE) out = false;
10631
+ else if (op === OP_LIT || op === OP_LIT_CI) out = k[code[ip + 1]].length === 0;
10632
+ else if (op === OP_RX) {
10633
+ const re = k[code[ip + 1]];
10634
+ out = !(re instanceof RegExp) || regexCanMatchEmpty(re.source);
10635
+ } else if (op === OP_SEQ || op === OP_SEQV || op === OP_SEQX) {
10636
+ childSlots(code, ip, kids);
10637
+ out = kids.every((c) => rowNullable(code, k, c, memo));
10638
+ } else if (op === OP_CHOICE) {
10639
+ childSlots(code, ip, kids);
10640
+ out = kids.length === 0 || kids.some((c) => rowNullable(code, k, c, memo));
10641
+ } else if (op === OP_REP || op === OP_REPV) {
10642
+ out = code[ip + 2] === 0 || rowNullable(code, k, code[ip + 1], memo);
10643
+ } else if (WRAPPERS.has(op)) {
10644
+ if (childSlots(code, ip, kids) && kids.length === 1) out = rowNullable(code, k, kids[0], memo);
10645
+ }
10646
+ memo.set(ip, out);
10647
+ return out;
10648
+ }
10649
+ function holdsGap(code, k, base, n, i, memo) {
10650
+ if (i < 1 || i + 1 >= n) return false;
10651
+ const term = code[base + i];
10652
+ if (code[term] !== OP_NOT && code[term] !== OP_PEEK) return false;
10653
+ const next = code[base + i + 1];
10654
+ if (code[next] === OP_ADJ || leadingTriviaFieldAt(code, k, next)) return false;
10655
+ return !rowNullable(code, k, next, memo);
10656
+ }
10657
+
10043
10658
  // src/table/emit-assembly.ts
10044
10659
  var Unemittable = class extends Error {
10045
10660
  construct;
@@ -10117,7 +10732,13 @@ var EMITTED_PARAMS = [
10117
10732
  // Appended for trivia-attributing fields (`field(…, { leadingTrivia })`);
10118
10733
  // old factories ignore them.
10119
10734
  "LEAD",
10120
- "triviaFieldCapture"
10735
+ "triviaFieldCapture",
10736
+ // Appended for the deferred-commit trivia skip (`trivia-gap.ts`); old
10737
+ // factories ignore it.
10738
+ "skipDeferredTrivia",
10739
+ // Appended for the pass-through collapse (`run-support.ts`); old factories
10740
+ // ignore it.
10741
+ "collapseEmpty"
10121
10742
  ];
10122
10743
  var RUNTIME_PRELUDE = `
10123
10744
  let _pfScan=null
@@ -10138,7 +10759,7 @@ function _skipTrivia(input,cur,ctx){
10138
10759
  const s=_pfScan
10139
10760
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
10140
10761
  if(s!==null)return skipTriviaScanned(s,input,cur,ctx)
10141
- if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
10762
+ if(needsDeferredTriviaCommit(ctx))return skipDeferredTrivia(input,cur,ctx)
10142
10763
  return advanceTrivia(input,cur,ctx)
10143
10764
  }
10144
10765
  function _pushLeaf(ctx,value,s,e){pushCstLeaf(ctx,{_tag:'leaf',value,span:{start:s,end:e}})}
@@ -10314,6 +10935,24 @@ ${fast}
10314
10935
  ${scanned}
10315
10936
  }`;
10316
10937
  }
10938
+ function emitHoldTerm(callee, dst, t, l, skip) {
10939
+ const fast = `const ${t}v=${callee}(input,cur,ctx)
10940
+ if(${t}v===FAIL)return FAIL
10941
+ ${dst}=${t}v
10942
+ cur=EC.e`;
10943
+ if (l.tri === TRI_NONE) return fast;
10944
+ const held = `const ${t}s=${skip}(input,cur,ctx)
10945
+ const ${t}v=${callee}(input,${t}s,ctx)
10946
+ if(${t}v===FAIL)return FAIL
10947
+ ${dst}=${t}v
10948
+ cur=${t}s`;
10949
+ if (l.tri !== TRI_UNKNOWN) return held;
10950
+ return `if(ctx.trivia===undefined){
10951
+ ${fast}
10952
+ }else{
10953
+ ${held}
10954
+ }`;
10955
+ }
10317
10956
  function leadSkip(hasTrivia, leadTrivia, skip) {
10318
10957
  if (hasTrivia === "false") return "{}";
10319
10958
  const call = `itemStart=${skip}(input,itemStart,ctx)`;
@@ -10345,7 +10984,7 @@ function rebuildPools(cc, fx, disp, plan) {
10345
10984
  })
10346
10985
  };
10347
10986
  }
10348
- function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
10987
+ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, select) {
10349
10988
  const { code, k, fx, disp, dsp, triviaLabelled } = t;
10350
10989
  const swapLegal = !cfg.trackLines;
10351
10990
  const hostCst = cfg.hostCst;
@@ -10355,6 +10994,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
10355
10994
  const reachable = [...reachableSites(code, roots)];
10356
10995
  const labels = computeSiteLabels(code, roots, hostCst);
10357
10996
  const scalarSpecs = /* @__PURE__ */ new Set();
10997
+ const nullable2 = /* @__PURE__ */ new Map();
10358
10998
  const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
10359
10999
  const largeChoiceLiteralFamilies = /* @__PURE__ */ new Map();
10360
11000
  const largeChoiceScalarSequences = /* @__PURE__ */ new Map();
@@ -10444,6 +11084,8 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
10444
11084
  };
10445
11085
  const bodies = [];
10446
11086
  const byIp = /* @__PURE__ */ new Map();
11087
+ const externals = [];
11088
+ const siteBytes = /* @__PURE__ */ new Map();
10447
11089
  const reached = /* @__PURE__ */ new Set();
10448
11090
  const prelude = [];
10449
11091
  const skipDefs = [];
@@ -10579,6 +11221,18 @@ return 1
10579
11221
  tokenDecisionRefs.set(dispatchIp, made);
10580
11222
  return made;
10581
11223
  }
11224
+ function gateMissTest(gip) {
11225
+ const resolved = t.cc[code[gip + 1]];
11226
+ const ci = classes.push([resolved]) - 1;
11227
+ classPlan.push([code[gip + 1]]);
11228
+ const cls = hoist("cl", `CLS[${ci}][0]`);
11229
+ return isAsciiOnlyClass(resolved) ? `${cls}.ascii[input.charCodeAt(pos)]!==1` : `!classHas(${cls},lead(input,pos))`;
11230
+ }
11231
+ function lookaheadMiss(child, miss) {
11232
+ if (code[child] !== OP_GATE || cfg.tolerant || cfg.probe) return "";
11233
+ return `if(${gateMissTest(child)}){${miss}}
11234
+ `;
11235
+ }
10582
11236
  function skipFor(l) {
10583
11237
  if (l.tri < 0) return "_skipTrivia";
10584
11238
  const ki = l.tri;
@@ -10589,8 +11243,8 @@ return 1
10589
11243
  const nm = `_sk${skipPool.size}`;
10590
11244
  skipPool.set(key, nm);
10591
11245
  if (!hasScan) {
10592
- skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return commitTriviaScan(scanTriviaCompact(input,cur,ctx))}` : `function ${nm}(input,cur,ctx){
10593
- if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
11246
+ skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return skipDeferredTrivia(input,cur,ctx)}` : `function ${nm}(input,cur,ctx){
11247
+ if(needsDeferredTriviaCommit(ctx))return skipDeferredTrivia(input,cur,ctx)
10594
11248
  return advanceTrivia(input,cur,ctx)}`);
10595
11249
  return nm;
10596
11250
  }
@@ -10635,9 +11289,17 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
10635
11289
  const target = resolveAlias(ip);
10636
11290
  const done = byIp.get(target);
10637
11291
  if (done !== void 0) return done;
11292
+ if (select !== void 0 && !select.has(target)) {
11293
+ const ext = `_px${target}`;
11294
+ byIp.set(target, ext);
11295
+ externals.push(target);
11296
+ return ext;
11297
+ }
10638
11298
  const fname = `_pf${target}`;
10639
11299
  byIp.set(target, fname);
10640
- bodies.push(lower(target, fname));
11300
+ const body = lower(target, fname);
11301
+ siteBytes.set(target, body.length);
11302
+ bodies.push(body);
10641
11303
  return fname;
10642
11304
  }
10643
11305
  function resolveAlias(ip) {
@@ -10657,9 +11319,7 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
10657
11319
  const op = code[ip];
10658
11320
  if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
10659
11321
  if (op === OP_RULE) return code[ip + 1];
10660
- if ((op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[ip + 3] === 0) && code[ip + 1] >= 0 && labels.at(ip).tri === code[ip + 1]) {
10661
- return code[ip + 2];
10662
- }
11322
+ if (scopeIsIdentity(code, ip, labels.at(ip))) return code[ip + 2];
10663
11323
  return void 0;
10664
11324
  }
10665
11325
  function lower(ip, fname) {
@@ -10777,14 +11437,44 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
10777
11437
  return `${head}EC.e=pos;return ''}`;
10778
11438
  case OP_GATE: {
10779
11439
  const child = link(code[ip + 2]);
11440
+ const xf = fxRef(code[ip + 3]);
11441
+ return `${head}
11442
+ if(${gateMissTest(ip)}){ctx._fe=pos;ctx._fx=${xf};return FAIL}
11443
+ return ${child}(input,pos,ctx)
11444
+ }`;
11445
+ }
11446
+ case OP_RGATE: {
11447
+ const child = link(code[ip + 2]);
11448
+ if (cfg.tolerant || cfg.probe) return `${head}
11449
+ return ${child}(input,pos,ctx)
11450
+ }`;
10780
11451
  const resolved = t.cc[code[ip + 1]];
10781
11452
  const ci = classes.push([resolved]) - 1;
10782
11453
  classPlan.push([code[ip + 1]]);
10783
11454
  const cls = hoist("cl", `CLS[${ci}][0]`);
10784
11455
  const xf = fxRef(code[ip + 3]);
10785
11456
  return `${head}
10786
- if(${staticBuild && isAsciiOnlyClass(resolved) ? `${cls}.ascii[input.charCodeAt(pos)]!==1` : `!classHas(${cls},lead(input,pos))`}){ctx._fe=pos;ctx._fx=${xf};return FAIL}
11457
+ const it=ctx._routed
11458
+ if(it!==undefined&&it.span.start===pos&&!classHas(${cls},lead(input,it.span.end))){ctx._fe=it.span.end;ctx._fx=${xf};return FAIL}
11459
+ return ${child}(input,pos,ctx)
11460
+ }`;
11461
+ }
11462
+ case OP_ARMGATE: {
11463
+ const pred = fnRef(code[ip + 1]);
11464
+ const child = link(code[ip + 2]);
11465
+ const xf = fxRef(code[ip + 3]);
11466
+ return `${head}
11467
+ if(!${pred}(ctx.state)){ctx._fc=false;ctx._fe=-1;ctx._fx=${xf};return FAIL}
10787
11468
  return ${child}(input,pos,ctx)
11469
+ }`;
11470
+ }
11471
+ case OP_WITHCTX: {
11472
+ const ki = code[ip + 1];
11473
+ const child = link(code[ip + 2]);
11474
+ return `${head}
11475
+ const saved=ctx.state
11476
+ ctx.state=${ki < 0 ? `${fnRef(~ki)}(saved)` : kRef(ki)}
11477
+ try{return ${child}(input,pos,ctx)}finally{ctx.state=saved}
10788
11478
  }`;
10789
11479
  }
10790
11480
  case OP_XFORM: {
@@ -11040,24 +11730,34 @@ return FAIL
11040
11730
  const xf = fxRef(code[ip + 2]);
11041
11731
  const p = tmp();
11042
11732
  return `${head}
11043
- ${emitMark(p, L.buf, L.raw, sinks)}
11044
- const v=${child}(input,pos,ctx)
11733
+ ${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${emitMark(p, L.buf, L.raw, sinks)}
11734
+ ${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
11045
11735
  ${emitRollback(p, L.buf, L.raw, sinks)}
11046
- if(v===FAIL){EC.e=pos;return null}
11736
+ ${cfg.probe ? "if(ctx._probe!==undefined)ctx._probe.best=pb??null\n" : ""}if(v===FAIL){EC.e=pos;return null}
11047
11737
  ctx._fe=pos
11048
11738
  ctx._fx=${xf}
11049
11739
  return FAIL
11050
11740
  }`;
11051
11741
  }
11052
11742
  case OP_PEEK: {
11743
+ const scalarChild = scalarTerminalPeekChild(code, ip);
11744
+ if (scalarChild >= 0) {
11745
+ const recognize = recognizerRef(code[scalarChild + 1]);
11746
+ const xf2 = fxRef(code[ip + 2]);
11747
+ return `${head}
11748
+ if(${recognize}(input,pos)<0){ctx._fe=pos;ctx._fx=${xf2};return FAIL}
11749
+ EC.e=pos
11750
+ return null
11751
+ }`;
11752
+ }
11053
11753
  const child = link(code[ip + 1]);
11054
11754
  const xf = fxRef(code[ip + 2]);
11055
11755
  const p = tmp();
11056
11756
  return `${head}
11057
- ${emitMark(p, L.buf, L.raw, sinks)}
11058
- const v=${child}(input,pos,ctx)
11757
+ ${lookaheadMiss(code[ip + 1], `ctx._fe=pos;ctx._fx=${xf};return FAIL`)}${emitMark(p, L.buf, L.raw, sinks)}
11758
+ ${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
11059
11759
  ${emitRollback(p, L.buf, L.raw, sinks)}
11060
- if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
11760
+ ${cfg.probe ? "if(ctx._probe!==undefined)ctx._probe.best=pb??null\n" : ""}if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
11061
11761
  EC.e=pos
11062
11762
  return null
11063
11763
  }`;
@@ -11067,7 +11767,7 @@ return null
11067
11767
  const clean = !REC2 && failureRollbackClean(prog, ip);
11068
11768
  const p = tmp();
11069
11769
  return `${head}
11070
- ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
11770
+ ${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
11071
11771
  ctx._fc=false
11072
11772
  const v=${child}(input,pos,ctx)
11073
11773
  if(v===FAIL){
@@ -11128,7 +11828,7 @@ return v
11128
11828
  );
11129
11829
  } else {
11130
11830
  const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
11131
- parts.push(emitTerm(callee, vn, tmp(), L, skipFor(L)));
11831
+ parts.push(holdsGap(code, k, base, n, i, nullable2) ? emitHoldTerm(callee, vn, tmp(), L, skipFor(L)) : emitTerm(callee, vn, tmp(), L, skipFor(L)));
11132
11832
  }
11133
11833
  names.push(vn);
11134
11834
  }
@@ -11148,7 +11848,7 @@ return v
11148
11848
  const asc = hoist("as", `DISP[${di}].ascii`);
11149
11849
  const hiArr = table.hi;
11150
11850
  const armSwitch = arms.map((a, i) => `case ${i}:v=${a}(input,pos,ctx);break`).join("\n");
11151
- const directAscii = staticBuild && table.hi.length === 0;
11851
+ const directAscii = table.hi.length === 0;
11152
11852
  return `${head}
11153
11853
  const c=${directAscii ? "input.charCodeAt(pos)" : "lead(input,pos)"}
11154
11854
  let arm=-1
@@ -11175,7 +11875,7 @@ return FAIL
11175
11875
  const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
11176
11876
  const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
11177
11877
  const maskable = n <= 32;
11178
- const directAsciiMask = staticBuild && maskable && gates.every(isAsciiOnlyClass);
11878
+ const directAsciiMask = maskable && gates.every(isAsciiOnlyClass);
11179
11879
  const gateRefs = directAsciiMask ? [] : Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
11180
11880
  const tokenCandidate = tokenChoiceCandidates.get(ip);
11181
11881
  const pretests = Array.from({ length: n }, (_, i) => {
@@ -11217,7 +11917,7 @@ return FAIL
11217
11917
  if (choiceCannotCommit(prog, ip) && !startFailureExact) {
11218
11918
  const deepAt = Array.from({ length: n }, () => tmp());
11219
11919
  const deepFx = Array.from({ length: n }, () => tmp());
11220
- const remember = (i, at, expectedSet) => `${deepAt[i]}=${at};${deepFx[i]}=${expectedSet}`;
11920
+ const remember2 = (i, at, expectedSet) => `${deepAt[i]}=${at};${deepFx[i]}=${expectedSet}`;
11221
11921
  const lazyArms = (ascii) => arms.map((arm, i) => {
11222
11922
  const pretest = pretests[i];
11223
11923
  const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
@@ -11229,13 +11929,13 @@ return FAIL
11229
11929
  if(${decision}===0){
11230
11930
  ctx._fc=false
11231
11931
  {const at=_pfTokEnd
11232
- ${remember(i, "at", pretest.token.expected)}}
11932
+ ${remember2(i, "at", pretest.token.expected)}}
11233
11933
  }`;
11234
11934
  const sequenceMiss = pretest?.sequence === void 0 ? "" : `
11235
11935
  else if(${ascii ? `(bits&${1 << i})!==0&&` : ""}${decision}<0){
11236
11936
  ctx._fc=false
11237
11937
  {const at=_pfSeqEnd
11238
- ${remember(i, "at", pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("") + pretest.sequence.expected.at(-1))}}
11938
+ ${remember2(i, "at", pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("") + pretest.sequence.expected.at(-1))}}
11239
11939
  }`;
11240
11940
  return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
11241
11941
  `}if(${gate2}){
@@ -11243,7 +11943,7 @@ ctx._fc=false
11243
11943
  {const v=${arm}(input,pos,ctx)
11244
11944
  if(v!==FAIL)return v}
11245
11945
  {const at=ctx._fe??pos
11246
- ${remember(i, "at", "ctx._fx")}}
11946
+ ${remember2(i, "at", "ctx._fx")}}
11247
11947
  ${rollbackFor(i)}
11248
11948
  }${routeMiss}${sequenceMiss}`;
11249
11949
  }).join("\n");
@@ -11356,7 +12056,7 @@ const bits=${maskName}[${directAsciiMask ? "c" : "c<0?128:c"}]
11356
12056
  if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
11357
12057
  ${startFailureExact ? "" : "let prev=0"}
11358
12058
  ${maskArms}
11359
- ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${n},prev,acc)`}
12059
+ ${startFailureExact ? "" : `if(best===pos&&prev!==0)acc=${catchName}(${n},prev,acc)`}
11360
12060
  ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
11361
12061
  return FAIL
11362
12062
  }
@@ -11455,7 +12155,7 @@ return [key,v]
11455
12155
  const ci = classes.push([resolved]) - 1;
11456
12156
  classPlan.push([itemClassIndex]);
11457
12157
  itemCls = hoist("ri", `CLS[${ci}][0]`);
11458
- itemAscii = staticBuild && isAsciiOnlyClass(resolved);
12158
+ itemAscii = isAsciiOnlyClass(resolved);
11459
12159
  }
11460
12160
  }
11461
12161
  const itemMiss = (at) => itemAscii ? `${itemCls}.ascii[input.charCodeAt(${at})]!==1` : `!classHas(${itemCls},lead(input,${at}))`;
@@ -11611,6 +12311,26 @@ return nd
11611
12311
  const trailingTrivia = (flags & 128) !== 0;
11612
12312
  const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
11613
12313
  const leanFlags = flags & ~128;
12314
+ if (build !== void 0 && passCollapse(code, ip, hostCst)) {
12315
+ return `${head}
12316
+ const v=${child}(input,pos,ctx)
12317
+ if(v!==undefined)return v
12318
+ return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
12319
+ }`;
12320
+ }
12321
+ const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
12322
+ const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(labels.at(code[ip + 2]).tri, t.trivia);
12323
+ const gp = gated !== void 0 && triviaLead !== void 0 && triviaLead.length <= 16 ? `const gc=lead(input,pos)
12324
+ if(!(${[
12325
+ ...gated.leads.map((g) => `!(${gateMissTest(g)})`),
12326
+ ...gated.lits.map((i) => `gc===${k[i].codePointAt(0)}`),
12327
+ ...triviaLead.map((r) => r.lo === r.hi ? `gc===${r.lo}` : `(gc>=${r.lo}&&gc<=${r.hi})`)
12328
+ ].join("||") || "false"})){
12329
+ const gv=${link(gated.last)}(input,pos,ctx)
12330
+ if(gv!==undefined)return gv
12331
+ return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
12332
+ }
12333
+ ` : "";
11614
12334
  if (!hostCst && !tracked && build !== void 0 && proj < 0 && (leanFlags === 2 || (flags === 18 || flags === 34))) {
11615
12335
  const fields = flags === 18;
11616
12336
  const collapseChildren = flags === 34;
@@ -11645,7 +12365,7 @@ sCh.push(nd)
11645
12365
  if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
11646
12366
  }`;
11647
12367
  return `${head}
11648
- const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
12368
+ ${gp}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
11649
12369
  const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
11650
12370
  const flat=[]
11651
12371
  ctx._cstBuf=undefined
@@ -11681,7 +12401,7 @@ return nd
11681
12401
  const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
11682
12402
  const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
11683
12403
  const ty = q(type);
11684
- const stArg = readsState ? "st" : "(ctx.state!==undefined?Object.assign({},ctx.state):undefined)";
12404
+ const stArg = "ctx.state";
11685
12405
  const hostCall = `_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,${stArg},${tags})`;
11686
12406
  let value;
11687
12407
  if (proj >= 0) {
@@ -11720,7 +12440,7 @@ const hostKids=kids
11720
12440
  const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
11721
12441
  const tlog=buf.tl??EMPTY_TLOG`;
11722
12442
  return `${head}
11723
- const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
12443
+ ${!hostCst && !tracked ? gp : ""}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
11724
12444
  const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf
11725
12445
  ${openCapture}
11726
12446
  ctx.captureTrivia=${captureWide}
@@ -11742,7 +12462,7 @@ ctx.captureTrivia=sCap
11742
12462
  if(v===FAIL)return FAIL
11743
12463
  const end=EC.e
11744
12464
  const span=${tracked ? "spanLines(ctx,pos,end)" : "{start:pos,end}"}
11745
- const st=${readsState ? "(ctx.state!==undefined?Object.assign({},ctx.state):undefined)" : "undefined"}
12465
+ const st=${readsState ? "ctx.state" : "undefined"}
11746
12466
  let nd
11747
12467
  ${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]
11748
12468
  else ` : ""}{${value}}
@@ -11755,21 +12475,57 @@ return nd
11755
12475
  throw new Unemittable(`OP_${OP_NAMES[op] ?? String(op)}`);
11756
12476
  }
11757
12477
  }
12478
+ const served = (ip) => select === void 0 || select.has(resolveAlias(ip));
11758
12479
  const ruleEntries = [];
11759
12480
  for (const [rname, entryIp] of Object.entries(prog.rules)) {
12481
+ if (!served(entryIp)) continue;
11760
12482
  const target = link(entryIp);
11761
12483
  const rn = `_r_${rname.replace(/[^A-Za-z0-9_$]/g, "_")}`;
11762
12484
  bodies.push(`const ${rn}=${target}`);
11763
12485
  ruleEntries.push(`${q(rname)}:${rn}`);
11764
12486
  }
11765
12487
  const extra = [];
11766
- for (const ip of extraIps) extra.push(`${ip}:${link(ip)}`);
12488
+ const exported = /* @__PURE__ */ new Set();
12489
+ for (const ip of extraIps) {
12490
+ if (!served(ip)) continue;
12491
+ exported.add(ip);
12492
+ extra.push(`${ip}:${link(ip)}`);
12493
+ }
12494
+ if (select !== void 0) {
12495
+ const kids = [];
12496
+ for (const ip of reachable) {
12497
+ if (select.has(resolveAlias(ip))) continue;
12498
+ kids.length = 0;
12499
+ childSlots(code, ip, kids);
12500
+ for (const kid of kids) {
12501
+ const target = resolveAlias(kid);
12502
+ if (!select.has(target) || exported.has(target)) continue;
12503
+ exported.add(target);
12504
+ extra.push(`${target}:${link(target)}`);
12505
+ }
12506
+ }
12507
+ }
12508
+ const hybrid = select === void 0 ? "" : `,
12509
+ ext:[${externals.join(",")}],
12510
+ bind:function(xs,ps){_xScan=xs
12511
+ ${externals.map((ip, i) => `_xp${ip}=ps[${i}]`).join("\n")}},
12512
+ scan:function(s){const o=_pfScan;_pfScan=s;return o}`;
12513
+ const scannerFor = (ip) => {
12514
+ const ki = labels.at(ip).tri;
12515
+ if (ki === TRI_UNKNOWN) return "_pfScan";
12516
+ if (ki === TRI_NONE) return "null";
12517
+ return swapLegal && !triviaLabelled[ki] && t.triviaScan[ki] != null ? hoist("ts", `TRIVIASCAN[${ki}]`) : "null";
12518
+ };
12519
+ const externalDefs = select === void 0 ? "" : `let _xScan
12520
+ ${externals.map((ip) => `let _xp${ip}
12521
+ function _px${ip}(input,pos,ctx){const o=_xScan(${scannerFor(ip)});const v=_xp${ip}(input,pos,ctx);_xScan(o);return v}`).join("\n")}
12522
+ `;
11767
12523
  const source = `${RUNTIME_PRELUDE}${needsNoRawPrelude ? NO_RAW_RUNTIME_PRELUDE : ""}
11768
12524
  ${prelude.join("\n")}
11769
12525
  ${skipDefs.join("\n")}
11770
12526
  ${choiceDefs.join("\n")}
11771
12527
  ${bodies.join("\n")}
11772
- function _begin(ctx){
12528
+ ${externalDefs}function _begin(ctx){
11773
12529
  const host=ctx.build
11774
12530
  if(_pfDepth>0)_pfFrames.push([_pfScan,_pfHost,EC.e])
11775
12531
  _pfDepth++
@@ -11796,7 +12552,7 @@ pieces:{${ruleEntries.join(",")}},
11796
12552
  byIp:{${extra.join(",")}},
11797
12553
  end:function(){return EC.e},
11798
12554
  begin:_begin,
11799
- finish:_finish
12555
+ finish:_finish${hybrid}
11800
12556
  }`;
11801
12557
  return {
11802
12558
  source,
@@ -11804,6 +12560,7 @@ finish:_finish
11804
12560
  masks,
11805
12561
  classes,
11806
12562
  armExpected,
12563
+ siteBytes,
11807
12564
  plan: { classes: classPlan, armExpected: armExpectedPlan, masks: maskPlan }
11808
12565
  };
11809
12566
  }
@@ -12234,37 +12991,184 @@ function escapeClassChar(ch2) {
12234
12991
  return ch2.replace(/[\\\]^-]/g, "\\$&");
12235
12992
  }
12236
12993
 
12237
- // src/table/run-support.ts
12238
- function lineCol(ctx, offset) {
12239
- const starts = ctx._lineStarts ?? [0];
12240
- let lo = 0, hi = starts.length - 1;
12241
- while (lo < hi) {
12242
- const mid = lo + hi + 1 >> 1;
12243
- if (starts[mid] <= offset) lo = mid;
12244
- else hi = mid - 1;
12994
+ // src/table/trivia-gap.ts
12995
+ function skipDeferredTrivia(input, cur, ctx) {
12996
+ const triviaP = ctx.trivia;
12997
+ const plain = ctx.trackLines !== true && ctx.captureTrivia !== true;
12998
+ const gap = ctx._gap;
12999
+ 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;
13000
+ const end = clearRunEnd(input, cur, ctx, triviaP, plain);
13001
+ if (end >= 0) {
13002
+ remember(cur, end, ctx, input, triviaP);
13003
+ return end;
12245
13004
  }
12246
- return [lo + 1, offset - starts[lo] + 1];
13005
+ const scan = scanTriviaCompact(input, cur, ctx);
13006
+ if (typeof scan !== "number") return commitTriviaScan(scan);
13007
+ if (plain) remember(cur, scan, ctx, input, triviaP);
13008
+ return scan;
12247
13009
  }
12248
- function spanLines(ctx, start, end) {
12249
- const s = lineCol(ctx, start), e = lineCol(ctx, end);
12250
- return { start, end, startLine: s[0], startColumn: s[1], endLine: e[0], endColumn: e[1] };
13010
+ function clearRunEnd(input, cur, ctx, triviaP, plain) {
13011
+ const rootKinds = ctx._rootTriviaKindIndex;
13012
+ const spec = triviaP?._meta.labeledTriviaSpec;
13013
+ if (!plain || triviaP === void 0 || spec == null || rootKinds === void 0 || ctx._triviaLog !== void 0) return -1;
13014
+ if (spec.rootKinds !== rootKinds) prime(spec, triviaP, rootKinds);
13015
+ const fast = spec.rootScan;
13016
+ if (fast === null) return -1;
13017
+ const end = fast(input, cur);
13018
+ return ctx._rootTriviaCapture === false || clearOf(spec.rootLeaders, input, cur, end) ? end : -1;
13019
+ }
13020
+ function remember(cur, end, ctx, input, triviaP) {
13021
+ const gap = ctx._gap;
13022
+ if (gap === void 0) {
13023
+ ctx._gap = { at: cur, end, input, of: triviaP, root: ctx._rootTriviaCapture, rootKinds: ctx._rootTriviaKindIndex, log: ctx._triviaLog, state: ctx.state };
13024
+ return;
13025
+ }
13026
+ gap.at = cur;
13027
+ gap.end = end;
13028
+ gap.input = input;
13029
+ gap.of = triviaP;
13030
+ gap.root = ctx._rootTriviaCapture;
13031
+ gap.rootKinds = ctx._rootTriviaKindIndex;
13032
+ gap.log = ctx._triviaLog;
13033
+ gap.state = ctx.state;
12251
13034
  }
12252
- function rawEntry(v, input, s, e) {
12253
- if (typeof v === "object" && v !== null) {
12254
- const tg = v._tag;
12255
- if (tg === "node" || tg === "leaf" || tg === "parseError") return v;
13035
+ function prime(spec, triviaP, rootKinds) {
13036
+ const ranges = [];
13037
+ let bounded = true;
13038
+ for (const arm of spec.arms) {
13039
+ if (rootKinds[arm.label] === void 0) continue;
13040
+ const fs = arm.parser._meta.firstSet;
13041
+ if (fs.kind === "any") bounded = false;
13042
+ else if (fs.kind === "ranges") ranges.push(...fs.ranges);
13043
+ }
13044
+ const classified = triviaP._meta.triviaScanner;
13045
+ spec.rootKinds = rootKinds;
13046
+ spec.rootLeaders = ranges;
13047
+ spec.rootScan = !bounded ? null : classified === void 0 ? fastTriviaScanner(triviaP) : classified;
13048
+ }
13049
+ function clearOf(ranges, input, from, to) {
13050
+ for (let i = from; i < to; i++) {
13051
+ const c = input.charCodeAt(i);
13052
+ if (c >= 55296 && c <= 57343) return false;
13053
+ for (const r of ranges) if (c >= r.lo && c <= r.hi) return false;
12256
13054
  }
12257
- return {
12258
- _tag: "leaf",
12259
- value: typeof v === "string" ? v : typeof v === "object" && v !== null ? input.slice(s, e) : "",
12260
- span: { start: s, end: e }
12261
- };
13055
+ return true;
12262
13056
  }
12263
- function lead(input, pos) {
12264
- if (pos >= input.length) return -1;
12265
- const c = input.charCodeAt(pos);
12266
- if (c < 55296 || c > 56319) return c;
12267
- return input.codePointAt(pos) ?? c;
13057
+
13058
+ // src/table/fail-clean.ts
13059
+ function passChild(code, ip) {
13060
+ switch (code[ip]) {
13061
+ case OP_RULE:
13062
+ case OP_LABEL:
13063
+ case OP_COV:
13064
+ case OP_TOKEN:
13065
+ return code[ip + 1];
13066
+ case OP_GATE:
13067
+ case OP_NODE:
13068
+ case OP_NODE_TRACK:
13069
+ case OP_XFORM:
13070
+ case OP_FIELD:
13071
+ case OP_SCOPE:
13072
+ case OP_SCOPE_CAP:
13073
+ case OP_SCOPE_PLAIN:
13074
+ case OP_WITHCTX:
13075
+ case OP_LEAF:
13076
+ case OP_SOURCE_LEAF:
13077
+ return code[ip + 2];
13078
+ default:
13079
+ return -1;
13080
+ }
13081
+ }
13082
+ function seqCount(code, ip) {
13083
+ const op = code[ip];
13084
+ return op === OP_SEQ || op === OP_SEQV ? ip + 1 : op === OP_SEQX ? ip + 2 : -1;
13085
+ }
13086
+ function failCleanAnalysis(code) {
13087
+ const cleanAt = new Uint8Array(code.length);
13088
+ const neverAt = new Uint8Array(code.length);
13089
+ const neverFails = (ip) => {
13090
+ const hit = neverAt[ip];
13091
+ if (hit !== 0) return hit === 1;
13092
+ neverAt[ip] = 3;
13093
+ let out = false;
13094
+ const op = code[ip];
13095
+ if (op === OP_OPT || op === OP_EMPTY || op === OP_EXPECT) out = true;
13096
+ else if (op === OP_REP || op === OP_REPV) out = code[ip + 2] === 0;
13097
+ else {
13098
+ const at = seqCount(code, ip);
13099
+ if (at >= 0) {
13100
+ out = true;
13101
+ for (let i = 1, n = code[at]; out && i <= n; i++) out = neverFails(code[at + i]);
13102
+ } else if (op !== OP_GATE) {
13103
+ const c = passChild(code, ip);
13104
+ out = c >= 0 && neverFails(c);
13105
+ }
13106
+ }
13107
+ neverAt[ip] = out ? 1 : 2;
13108
+ return out;
13109
+ };
13110
+ const clean = (ip) => {
13111
+ const hit = cleanAt[ip];
13112
+ if (hit !== 0) return hit === 1;
13113
+ cleanAt[ip] = 3;
13114
+ let out = false;
13115
+ switch (code[ip]) {
13116
+ // A terminal pushes its leaf only on a match; NOT/PEEK/ATTEMPT restore
13117
+ // their own mark; OPT, EMPTY and EXPECT do not fail uncommitted.
13118
+ case OP_LIT:
13119
+ case OP_RX:
13120
+ case OP_LIT_TRACK:
13121
+ case OP_RX_TRACK:
13122
+ case OP_LIT_CI:
13123
+ case OP_LIT_CI_TRACK:
13124
+ case OP_GUARD:
13125
+ case OP_NOT:
13126
+ case OP_PEEK:
13127
+ case OP_ATTEMPT:
13128
+ case OP_EMPTY:
13129
+ case OP_OPT:
13130
+ case OP_EXPECT:
13131
+ out = true;
13132
+ break;
13133
+ // Min 0 does not fail uncommitted; min 1 fails only with no item kept, and
13134
+ // restores the failed item itself.
13135
+ case OP_REP:
13136
+ case OP_REPV:
13137
+ out = code[ip + 2] <= 1;
13138
+ break;
13139
+ // Only the first term may fail: a later one fails after the terms before it
13140
+ // wrote, and after the trivia scanned in front of it.
13141
+ case OP_SEQ:
13142
+ case OP_SEQV:
13143
+ case OP_SEQX: {
13144
+ const at = seqCount(code, ip);
13145
+ const n = code[at];
13146
+ out = n > 0 && clean(code[at + 1]);
13147
+ for (let i = 2; out && i <= n; i++) out = neverFails(code[at + i]);
13148
+ break;
13149
+ }
13150
+ case OP_CHOICE: {
13151
+ out = true;
13152
+ for (let i = 0, n = code[ip + 2]; out && i < n; i++) out = clean(code[ip + 4 + i]);
13153
+ break;
13154
+ }
13155
+ case OP_ROUTED:
13156
+ out = code[ip + 1] < 0 || clean(code[ip + 1]);
13157
+ break;
13158
+ // An arm's failure and the fallback's are committed; only the selector's is
13159
+ // not, and without a fallback an unknown key fails after the selector wrote.
13160
+ case OP_DISPATCH:
13161
+ out = code[ip + 3] >= 0 && clean(code[ip + 1]);
13162
+ break;
13163
+ default: {
13164
+ const c = passChild(code, ip);
13165
+ out = c >= 0 && clean(c);
13166
+ }
13167
+ }
13168
+ cleanAt[ip] = out ? 1 : 2;
13169
+ return out;
13170
+ };
13171
+ return clean;
12268
13172
  }
12269
13173
 
12270
13174
  // src/cst/host-mode.ts
@@ -12429,6 +13333,7 @@ function assemble(t, prog, cfg) {
12429
13333
  const swapLegal = !cfg.trackLines;
12430
13334
  const hostCst = cfg.hostCst;
12431
13335
  const REC2 = prog.rec === 1 && cfg.tolerant;
13336
+ const PROBE = cfg.probe;
12432
13337
  const sentinels = /* @__PURE__ */ new Map();
12433
13338
  function sentinelFor(cls) {
12434
13339
  if (cls < 0) return void 0;
@@ -12443,6 +13348,9 @@ function assemble(t, prog, cfg) {
12443
13348
  const EC = newEndCell();
12444
13349
  const scalarRecognizers = [];
12445
13350
  const rawScalarSpecs = /* @__PURE__ */ new Set();
13351
+ function lookaheadClass(child) {
13352
+ return code[child] === OP_GATE && !cfg.tolerant && !cfg.probe ? cc[code[child + 1]] : null;
13353
+ }
12446
13354
  function scalarFor(child) {
12447
13355
  const spec = code[child + 1];
12448
13356
  let recognize = scalarRecognizers[spec];
@@ -12452,17 +13360,27 @@ function assemble(t, prog, cfg) {
12452
13360
  }
12453
13361
  return recognize;
12454
13362
  }
12455
- const labelExtraIps = [];
12456
- for (const s of prog.scans ?? []) for (const r of scanRefs(s)) labelExtraIps.push(r[0]);
12457
- for (const set of prog.scanSkip ?? []) for (const r of set) labelExtraIps.push(r[0]);
13363
+ const labelExtraIps = assemblyExtraIps(prog);
12458
13364
  const closureLabels = computeSiteLabels(
12459
13365
  code,
12460
13366
  [...Object.values(prog.rules), ...labelExtraIps],
12461
13367
  hostCst
12462
13368
  );
12463
13369
  let SCAN = null;
13370
+ let HYBRID;
13371
+ function hybridPiece(piece) {
13372
+ const setScan = HYBRID.scan;
13373
+ return (input, pos, ctx) => {
13374
+ const saved = setScan(SCAN);
13375
+ const value = piece(input, pos, ctx);
13376
+ setScan(saved);
13377
+ return value;
13378
+ };
13379
+ }
12464
13380
  const memo = /* @__PURE__ */ new Map();
12465
13381
  const reached = /* @__PURE__ */ new Set();
13382
+ const NULLABLE = /* @__PURE__ */ new Map();
13383
+ const CLEAN = REC2 ? () => false : failCleanAnalysis(code);
12466
13384
  function pushLeaf(ctx, value, s, e) {
12467
13385
  const lf = { _tag: "leaf", value, span: { start: s, end: e } };
12468
13386
  pushCstLeaf(ctx, lf);
@@ -12661,6 +13579,22 @@ function assemble(t, prog, cfg) {
12661
13579
  return node2;
12662
13580
  };
12663
13581
  }
13582
+ function passCollapseNode(child, build, readsRaw) {
13583
+ return (input, pos, ctx) => {
13584
+ const v = child(input, pos, ctx);
13585
+ if (v !== void 0) return v;
13586
+ return collapseEmpty(ctx, build, input, pos, EC.e, readsRaw);
13587
+ };
13588
+ }
13589
+ function gatedPassCollapseNode(blockers, last, classic, build, readsRaw) {
13590
+ return (input, pos, ctx) => {
13591
+ const c = lead(input, pos);
13592
+ for (let i = 0; i < blockers.length; i++) if (classHas2(blockers[i], c)) return classic(input, pos, ctx);
13593
+ const v = last(input, pos, ctx);
13594
+ if (v !== void 0) return v;
13595
+ return collapseEmpty(ctx, build, input, pos, EC.e, readsRaw);
13596
+ };
13597
+ }
12664
13598
  function plainProjectNode(child, projection, type) {
12665
13599
  return (input, pos, ctx) => {
12666
13600
  const sCh = ctx._cstChildren;
@@ -12752,9 +13686,7 @@ function assemble(t, prog, cfg) {
12752
13686
  return s(input, cur);
12753
13687
  }
12754
13688
  if (s !== null) return skipTriviaScanned(s, input, cur, ctx);
12755
- if (needsDeferredTriviaCommit(ctx)) {
12756
- return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
12757
- }
13689
+ if (needsDeferredTriviaCommit(ctx)) return skipDeferredTrivia(input, cur, ctx);
12758
13690
  return advanceTrivia(input, cur, ctx);
12759
13691
  }
12760
13692
  let TERMV;
@@ -12924,7 +13856,7 @@ function assemble(t, prog, cfg) {
12924
13856
  if (next !== void 0) {
12925
13857
  return next(input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best);
12926
13858
  }
12927
- if (best === pos) acc = through(total, prev, acc);
13859
+ if (best === pos && prev !== 0) acc = through(total, prev, acc);
12928
13860
  ctx._fe = pos;
12929
13861
  ctx._fx = acc ?? choiceFx;
12930
13862
  return FAIL;
@@ -13007,7 +13939,7 @@ function assemble(t, prog, cfg) {
13007
13939
  if (next !== void 0) {
13008
13940
  return next(input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best);
13009
13941
  }
13010
- if (best === pos) acc = through(total, prev, acc);
13942
+ if (best === pos && prev !== 0) acc = through(total, prev, acc);
13011
13943
  ctx._fe = pos;
13012
13944
  ctx._fx = acc ?? choiceFx;
13013
13945
  return FAIL;
@@ -13033,21 +13965,27 @@ function assemble(t, prog, cfg) {
13033
13965
  }
13034
13966
  function dispatchBranch(child, usesRouted) {
13035
13967
  if (!usesRouted) {
13036
- return (input, _pos, selEnd, key, _selectorMark, ctx) => {
13037
- const mark = saveTriviaMark(ctx);
13968
+ return (input, _pos, selEnd, key, ctx) => {
13969
+ const need = markCst(ctx);
13970
+ const mRaw = MRAW;
13971
+ const mTl = MTL;
13972
+ const mLv = MLV;
13973
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
13974
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
13975
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
13976
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
13038
13977
  const v = child(input, selEnd, ctx);
13039
13978
  if (v === FAIL) {
13040
- rollbackTrivia(ctx, mark);
13979
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
13041
13980
  ctx._fc = true;
13042
13981
  return FAIL;
13043
13982
  }
13044
13983
  return [key, v];
13045
13984
  };
13046
13985
  }
13047
- return (input, pos, selEnd, key, selectorMark, ctx) => {
13986
+ return (input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot) => {
13048
13987
  const savedRouted = ctx._routed;
13049
- rollbackTrivia(ctx, selectorMark);
13050
- const mark = saveTriviaMark(ctx);
13988
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
13051
13989
  ctx._routed = { value: key, span: { start: pos, end: selEnd } };
13052
13990
  let v;
13053
13991
  try {
@@ -13056,7 +13994,7 @@ function assemble(t, prog, cfg) {
13056
13994
  ctx._routed = savedRouted;
13057
13995
  }
13058
13996
  if (v === FAIL) {
13059
- rollbackTrivia(ctx, mark);
13997
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
13060
13998
  ctx._fc = true;
13061
13999
  return FAIL;
13062
14000
  }
@@ -13064,12 +14002,12 @@ function assemble(t, prog, cfg) {
13064
14002
  };
13065
14003
  }
13066
14004
  function dispatchArmBlock(start, a0, a1, a2, a3, next) {
13067
- return (arm, input, pos, selEnd, key, selectorMark, ctx) => {
13068
- if (arm === start) return a0(input, pos, selEnd, key, selectorMark, ctx);
13069
- if (arm === start + 1) return a1(input, pos, selEnd, key, selectorMark, ctx);
13070
- if (arm === start + 2) return a2(input, pos, selEnd, key, selectorMark, ctx);
13071
- if (arm === start + 3) return a3(input, pos, selEnd, key, selectorMark, ctx);
13072
- return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key, selectorMark, ctx);
14005
+ return (arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot) => {
14006
+ if (arm === start) return a0(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14007
+ if (arm === start + 1) return a1(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14008
+ if (arm === start + 2) return a2(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14009
+ if (arm === start + 3) return a3(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14010
+ return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
13073
14011
  };
13074
14012
  }
13075
14013
  function trackLinesInto(ctx, input, end) {
@@ -13086,20 +14024,68 @@ function assemble(t, prog, cfg) {
13086
14024
  if (done !== void 0) return done;
13087
14025
  const flight = inFlight.get(ip);
13088
14026
  if (flight !== void 0) return flight.fwd;
14027
+ const selected = HYBRID?.byIp[ip];
14028
+ if (selected !== void 0) {
14029
+ const piece2 = scanHandoffNeeded(code, ip, closureLabels) ? hybridPiece(selected) : selected;
14030
+ memo.set(ip, piece2);
14031
+ reached.add(ip);
14032
+ return piece2;
14033
+ }
13089
14034
  let target;
13090
14035
  const fwd = (input, pos, ctx) => target(input, pos, ctx);
13091
14036
  const holder = { fwd, set: (p) => {
13092
14037
  target = p;
13093
14038
  } };
13094
14039
  inFlight.set(ip, holder);
13095
- const op = code[ip];
13096
- 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);
14040
+ const piece = scopeIsIdentity(code, ip, closureLabels.at(ip)) ? link(code[ip + 2]) : countedPiece(lookaheadLedNode(ip) ?? lower(ip), ip);
13097
14041
  inFlight.delete(ip);
13098
14042
  holder.set(piece);
13099
14043
  memo.set(ip, piece);
13100
14044
  reached.add(ip);
13101
14045
  return piece;
13102
14046
  }
14047
+ let FIRST_DECIDED;
14048
+ let NODE_BODY;
14049
+ const DECIDED = (_input, pos) => {
14050
+ EC.e = pos;
14051
+ return null;
14052
+ };
14053
+ function lookaheadLedNode(ip) {
14054
+ const op = code[ip];
14055
+ if (op !== OP_NODE && op !== OP_NODE_TRACK || hostCst || REC2 || cfg.probe || cfg.coverage || cfg.trackLines) return void 0;
14056
+ if (passCollapse(code, ip, hostCst) || gatedPassCollapse(code, ip, hostCst) !== void 0) return void 0;
14057
+ const body = code[ip + 2];
14058
+ const bop = code[body];
14059
+ if (bop !== OP_SEQ && bop !== OP_SEQV && bop !== OP_SEQX) return void 0;
14060
+ const base = bop === OP_SEQX ? body + 3 : body + 2;
14061
+ if (code[bop === OP_SEQX ? body + 2 : body + 1] < 2) return void 0;
14062
+ const first = code[base];
14063
+ const negative = code[first] === OP_NOT;
14064
+ const terminal = negative ? scalarTerminalNotChild(code, first) : code[first] === OP_PEEK ? scalarTerminalPeekChild(code, first) : -1;
14065
+ if (terminal < 0) return void 0;
14066
+ const recognize = scalarFor(terminal);
14067
+ const xf = fx[code[first + 2]];
14068
+ FIRST_DECIDED = DECIDED;
14069
+ NODE_BODY = lower(body);
14070
+ const node2 = lower(ip);
14071
+ NODE_BODY = void 0;
14072
+ return negative ? (input, pos, ctx) => {
14073
+ if (recognize(input, pos) >= 0) {
14074
+ ctx._fe = pos;
14075
+ ctx._fx = xf;
14076
+ EC.e = pos;
14077
+ return FAIL;
14078
+ }
14079
+ return node2(input, pos, ctx);
14080
+ } : (input, pos, ctx) => {
14081
+ if (recognize(input, pos) < 0) {
14082
+ ctx._fe = pos;
14083
+ ctx._fx = xf;
14084
+ return FAIL;
14085
+ }
14086
+ return node2(input, pos, ctx);
14087
+ };
14088
+ }
13103
14089
  function lower(ip) {
13104
14090
  const op = code[ip];
13105
14091
  switch (op) {
@@ -13630,7 +14616,12 @@ function assemble(t, prog, cfg) {
13630
14616
  }
13631
14617
  const child = link(code[ip + 1]);
13632
14618
  const xf = fx[code[ip + 2]];
14619
+ const gate2 = lookaheadClass(code[ip + 1]);
13633
14620
  return (input, pos, ctx) => {
14621
+ if (gate2 !== null && !classHas2(gate2, lead(input, pos))) {
14622
+ EC.e = pos;
14623
+ return null;
14624
+ }
13634
14625
  const need = markCst(ctx);
13635
14626
  const mRaw = MRAW;
13636
14627
  const mTl = MTL;
@@ -13639,8 +14630,10 @@ function assemble(t, prog, cfg) {
13639
14630
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
13640
14631
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
13641
14632
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
14633
+ const probeBest = PROBE ? ctx._probe?.best : void 0;
13642
14634
  const v = child(input, pos, ctx);
13643
14635
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14636
+ if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
13644
14637
  if (v === FAIL) {
13645
14638
  EC.e = pos;
13646
14639
  return null;
@@ -13651,9 +14644,29 @@ function assemble(t, prog, cfg) {
13651
14644
  };
13652
14645
  }
13653
14646
  case OP_PEEK: {
14647
+ const scalarChild = scalarTerminalPeekChild(code, ip);
14648
+ if (scalarChild >= 0) {
14649
+ const recognize = scalarFor(scalarChild);
14650
+ const xf2 = fx[code[ip + 2]];
14651
+ return (input, pos, ctx) => {
14652
+ if (recognize(input, pos) < 0) {
14653
+ ctx._fe = pos;
14654
+ ctx._fx = xf2;
14655
+ return FAIL;
14656
+ }
14657
+ EC.e = pos;
14658
+ return null;
14659
+ };
14660
+ }
13654
14661
  const child = link(code[ip + 1]);
13655
14662
  const xf = fx[code[ip + 2]];
14663
+ const gate2 = lookaheadClass(code[ip + 1]);
13656
14664
  return (input, pos, ctx) => {
14665
+ if (gate2 !== null && !classHas2(gate2, lead(input, pos))) {
14666
+ ctx._fe = pos;
14667
+ ctx._fx = xf;
14668
+ return FAIL;
14669
+ }
13657
14670
  const need = markCst(ctx);
13658
14671
  const mRaw = MRAW;
13659
14672
  const mTl = MTL;
@@ -13662,8 +14675,10 @@ function assemble(t, prog, cfg) {
13662
14675
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
13663
14676
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
13664
14677
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
14678
+ const probeBest = PROBE ? ctx._probe?.best : void 0;
13665
14679
  const v = child(input, pos, ctx);
13666
14680
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14681
+ if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
13667
14682
  if (v === FAIL) {
13668
14683
  ctx._fe = pos;
13669
14684
  ctx._fx = xf;
@@ -13675,8 +14690,14 @@ function assemble(t, prog, cfg) {
13675
14690
  }
13676
14691
  case OP_OPT: {
13677
14692
  const child = link(code[ip + 1]);
14693
+ const gate2 = lookaheadClass(code[ip + 1]);
14694
+ const childClean = CLEAN(code[ip + 1]);
13678
14695
  return (input, pos, ctx) => {
13679
- const need = markCst(ctx);
14696
+ if (gate2 !== null && !classHas2(gate2, lead(input, pos))) {
14697
+ EC.e = pos;
14698
+ return null;
14699
+ }
14700
+ const need = !childClean && markCst(ctx);
13680
14701
  const mRaw = MRAW;
13681
14702
  const mTl = MTL;
13682
14703
  const mLv = MLV;
@@ -13874,6 +14895,9 @@ function assemble(t, prog, cfg) {
13874
14895
  const projection = reducer < 0 ? ~reducer : -1;
13875
14896
  const fn = fused && projection < 0 ? fns[reducer] : void 0;
13876
14897
  const step = closureLabels.at(ip).buf ? nextTermBuffered : nextTerm;
14898
+ const decided = FIRST_DECIDED;
14899
+ FIRST_DECIDED = void 0;
14900
+ const linkFirst = () => decided ?? link(code[base]);
13877
14901
  const runnerBlock = (count, r0, r1, r2, r3, next) => {
13878
14902
  if (count === 1) return (input, cur, ctx, values, inherited) => {
13879
14903
  cur = r0(input, cur, ctx, inherited);
@@ -13919,7 +14943,7 @@ function assemble(t, prog, cfg) {
13919
14943
  };
13920
14944
  };
13921
14945
  if (REC2) {
13922
- const first2 = link(code[base]);
14946
+ const first2 = linkFirst();
13923
14947
  const firstSync = sentinelFor(code[base + n]);
13924
14948
  const runnerAt = (i) => {
13925
14949
  const sync = sentinelFor(code[base + n + i]);
@@ -13955,13 +14979,13 @@ function assemble(t, prog, cfg) {
13955
14979
  const bindRunners = (start) => {
13956
14980
  const count = Math.min(4, n - start);
13957
14981
  const at = (offset) => runnerAt(start + offset);
13958
- const never = () => -1;
14982
+ const never2 = () => -1;
13959
14983
  return runnerBlock(
13960
14984
  count,
13961
14985
  at(0),
13962
- count > 1 ? at(1) : never,
13963
- count > 2 ? at(2) : never,
13964
- count > 3 ? at(3) : never,
14986
+ count > 1 ? at(1) : never2,
14987
+ count > 2 ? at(2) : never2,
14988
+ count > 3 ? at(3) : never2,
13965
14989
  start + count < n ? bindRunners(start + count) : void 0
13966
14990
  );
13967
14991
  };
@@ -14011,15 +15035,31 @@ function assemble(t, prog, cfg) {
14011
15035
  let hasAdj = false;
14012
15036
  for (let i = 1; i < n; i++) {
14013
15037
  const kidIp = code[base + i];
14014
- if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp)) {
15038
+ if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp) || holdsGap(code, k, base, n, i, NULLABLE)) {
14015
15039
  hasAdj = true;
14016
15040
  break;
14017
15041
  }
14018
15042
  }
14019
15043
  if (hasAdj) {
14020
- const first2 = link(code[base]);
15044
+ const first2 = linkFirst();
14021
15045
  const runnerAt = (i) => {
14022
15046
  const kidIp = code[base + i];
15047
+ if (holdsGap(code, k, base, n, i, NULLABLE)) {
15048
+ const kid = link(kidIp);
15049
+ return (input, cur, ctx) => {
15050
+ if (ctx.trivia === void 0) {
15051
+ const v2 = kid(input, cur, ctx);
15052
+ if (v2 === FAIL) return -1;
15053
+ TERMV = v2;
15054
+ return EC.e;
15055
+ }
15056
+ const scanEnd = skipTrivia(input, cur, ctx);
15057
+ const v = kid(input, scanEnd, ctx);
15058
+ if (v === FAIL) return -1;
15059
+ TERMV = v;
15060
+ return scanEnd;
15061
+ };
15062
+ }
14023
15063
  if (code[kidIp] !== OP_ADJ) {
14024
15064
  const kid = link(kidIp);
14025
15065
  if (leadingTriviaFieldAt(code, k, kidIp)) {
@@ -14044,13 +15084,13 @@ function assemble(t, prog, cfg) {
14044
15084
  const bindRunners = (start) => {
14045
15085
  const count = Math.min(4, n - start);
14046
15086
  const at = (offset) => runnerAt(start + offset);
14047
- const never = () => -1;
15087
+ const never2 = () => -1;
14048
15088
  return runnerBlock(
14049
15089
  count,
14050
15090
  at(0),
14051
- count > 1 ? at(1) : never,
14052
- count > 2 ? at(2) : never,
14053
- count > 3 ? at(3) : never,
15091
+ count > 1 ? at(1) : never2,
15092
+ count > 2 ? at(2) : never2,
15093
+ count > 3 ? at(3) : never2,
14054
15094
  start + count < n ? bindRunners(start + count) : void 0
14055
15095
  );
14056
15096
  };
@@ -14087,7 +15127,7 @@ function assemble(t, prog, cfg) {
14087
15127
  };
14088
15128
  }
14089
15129
  if (n === 1) {
14090
- const k0 = link(code[base]);
15130
+ const k0 = linkFirst();
14091
15131
  if (fused) {
14092
15132
  return (input, pos, ctx) => {
14093
15133
  const v = k0(input, pos, ctx);
@@ -14109,7 +15149,7 @@ function assemble(t, prog, cfg) {
14109
15149
  };
14110
15150
  }
14111
15151
  if (n === 2) {
14112
- const k0 = link(code[base]), k1 = link(code[base + 1]);
15152
+ const k0 = linkFirst(), k1 = link(code[base + 1]);
14113
15153
  if (fused) {
14114
15154
  return (input, pos, ctx) => {
14115
15155
  const v0 = k0(input, pos, ctx);
@@ -14140,7 +15180,7 @@ function assemble(t, prog, cfg) {
14140
15180
  };
14141
15181
  }
14142
15182
  if (n === 3) {
14143
- const k0 = link(code[base]), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
15183
+ const k0 = linkFirst(), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
14144
15184
  if (fused) {
14145
15185
  return (input, pos, ctx) => {
14146
15186
  const v0 = k0(input, pos, ctx);
@@ -14234,7 +15274,7 @@ function assemble(t, prog, cfg) {
14234
15274
  start + count < n ? bind(start + count) : void 0
14235
15275
  );
14236
15276
  };
14237
- const first = link(code[base]);
15277
+ const first = linkFirst();
14238
15278
  const tail = bind(1);
14239
15279
  const runDirectTerms = (input, pos, ctx, values) => {
14240
15280
  const v0 = first(input, pos, ctx);
@@ -14273,6 +15313,8 @@ function assemble(t, prog, cfg) {
14273
15313
  const n = code[ip + 2];
14274
15314
  const choiceFx = fx[code[ip + 3]];
14275
15315
  const base = ip + 4;
15316
+ for (let i = 0; i < n; i++) link(code[base + i]);
15317
+ const armsClean = CLEAN(ip);
14276
15318
  if (table.exclusive) {
14277
15319
  const ascii = table.ascii;
14278
15320
  const hi = table.hi;
@@ -14412,7 +15454,7 @@ function assemble(t, prog, cfg) {
14412
15454
  if (n === 3) addGate(g2, 4);
14413
15455
  return (input, pos, ctx) => {
14414
15456
  const c = lead(input, pos);
14415
- const need = markCst(ctx);
15457
+ const need = !armsClean && markCst(ctx);
14416
15458
  const mRaw = MRAW;
14417
15459
  const mTl = MTL;
14418
15460
  const mLv = MLV;
@@ -14482,6 +15524,11 @@ function assemble(t, prog, cfg) {
14482
15524
  }
14483
15525
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14484
15526
  }
15527
+ if (prev === 0) {
15528
+ ctx._fe = pos;
15529
+ ctx._fx = choiceFx;
15530
+ return FAIL;
15531
+ }
14485
15532
  if (best === pos && prev < 1) acc = accSet(e0, acc);
14486
15533
  if (best === pos && prev < 2) acc = accSet(e1, acc);
14487
15534
  if (best === pos && n === 3 && prev < 3) acc = accSet(e2, acc);
@@ -14624,7 +15671,7 @@ function assemble(t, prog, cfg) {
14624
15671
  if (pn !== 0) {
14625
15672
  return (input, pos, ctx) => {
14626
15673
  const c = lead(input, pos);
14627
- const need = markCst(ctx);
15674
+ const need = !armsClean && markCst(ctx);
14628
15675
  const mRaw = MRAW;
14629
15676
  const mTl = MTL;
14630
15677
  const mLv = MLV;
@@ -14681,7 +15728,7 @@ function assemble(t, prog, cfg) {
14681
15728
  }
14682
15729
  return (input, pos, ctx) => {
14683
15730
  const c = lead(input, pos);
14684
- const need = markCst(ctx);
15731
+ const need = !armsClean && markCst(ctx);
14685
15732
  const mRaw = MRAW;
14686
15733
  const mTl = MTL;
14687
15734
  const mLv = MLV;
@@ -14729,7 +15776,7 @@ function assemble(t, prog, cfg) {
14729
15776
  }
14730
15777
  return (input, pos, ctx) => {
14731
15778
  const c = lead(input, pos);
14732
- const need = markCst(ctx);
15779
+ const need = !armsClean && markCst(ctx);
14733
15780
  const mRaw = MRAW;
14734
15781
  const mTl = MTL;
14735
15782
  const mLv = MLV;
@@ -14783,6 +15830,21 @@ function assemble(t, prog, cfg) {
14783
15830
  return lit(input, pos, ctx);
14784
15831
  };
14785
15832
  }
15833
+ case OP_RGATE: {
15834
+ const cls = cc[code[ip + 1]];
15835
+ const xf = fx[code[ip + 3]];
15836
+ const child = link(code[ip + 2]);
15837
+ if (cfg.tolerant || cfg.probe) return child;
15838
+ return (input, pos, ctx) => {
15839
+ const item = ctx._routed;
15840
+ if (item !== void 0 && item.span.start === pos && !classHas2(cls, lead(input, item.span.end))) {
15841
+ ctx._fe = item.span.end;
15842
+ ctx._fx = xf;
15843
+ return FAIL;
15844
+ }
15845
+ return child(input, pos, ctx);
15846
+ };
15847
+ }
14786
15848
  case OP_ARMGATE: {
14787
15849
  const pred = fns[code[ip + 1]];
14788
15850
  const child = link(code[ip + 2]);
@@ -14790,7 +15852,7 @@ function assemble(t, prog, cfg) {
14790
15852
  return (input, pos, ctx) => {
14791
15853
  if (!pred(ctx.state)) {
14792
15854
  ctx._fc = false;
14793
- ctx._fe = pos;
15855
+ ctx._fe = -1;
14794
15856
  ctx._fx = xf;
14795
15857
  return FAIL;
14796
15858
  }
@@ -14851,6 +15913,7 @@ function assemble(t, prog, cfg) {
14851
15913
  const itemClass = !REC2 && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
14852
15914
  const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
14853
15915
  const skipBeforeFirst = sepIp < 0 && min === 0;
15916
+ const itemClean = sepIp < 0 && CLEAN(code[ip + 1]) && !rowNullable(code, k, code[ip + 1], NULLABLE);
14854
15917
  if (REC2) {
14855
15918
  const itemFx2 = fx[code[ip + 6]];
14856
15919
  const sepSent = sentinelFor(code[ip + 7]);
@@ -14947,6 +16010,8 @@ function assemble(t, prog, cfg) {
14947
16010
  const out = collect ? [] : void 0;
14948
16011
  const hasTrivia = ctx.trivia !== void 0;
14949
16012
  const needMark = rollbackNeeded(ctx);
16013
+ const markLater = needMark && (!itemClean || hasTrivia);
16014
+ const markFirst = needMark && (!itemClean || hasTrivia && skipBeforeFirst);
14950
16015
  const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
14951
16016
  let cur = pos;
14952
16017
  let count = 0;
@@ -14954,14 +16019,15 @@ function assemble(t, prog, cfg) {
14954
16019
  if (max >= 0 && count >= max) break;
14955
16020
  if (sep !== void 0 && count > 0 && count >= min && cur >= input.length) break;
14956
16021
  if (count >= min && sep === void 0 && !hasTrivia && gateItems && !itemMayStart(input, cur)) break;
14957
- if (needMark) markCst(ctx);
14958
- const mRaw = needMark ? MRAW : 0;
14959
- const mTl = needMark ? MTL : 0;
14960
- const mLv = needMark ? MLV : 0;
14961
- const mFl = needMark ? ctx._fields?.length ?? 0 : 0;
14962
- const mEr = needMark ? ctx._errors?.length ?? 0 : 0;
14963
- const mLog = needMark ? ctx._triviaLog?.length ?? 0 : 0;
14964
- const mRoot = needMark ? ctx._rootTriviaLog?.length ?? 0 : 0;
16022
+ const markIt = count > 0 ? markLater : markFirst;
16023
+ if (markIt) markCst(ctx);
16024
+ const mRaw = markIt ? MRAW : 0;
16025
+ const mTl = markIt ? MTL : 0;
16026
+ const mLv = markIt ? MLV : 0;
16027
+ const mFl = markIt ? ctx._fields?.length ?? 0 : 0;
16028
+ const mEr = markIt ? ctx._errors?.length ?? 0 : 0;
16029
+ const mLog = markIt ? ctx._triviaLog?.length ?? 0 : 0;
16030
+ const mRoot = markIt ? ctx._rootTriviaLog?.length ?? 0 : 0;
14965
16031
  let itemStart = cur;
14966
16032
  let sepEnd = -1;
14967
16033
  const viaRepItem = sep === void 0 && count >= min && (count > 0 || skipBeforeFirst);
@@ -14973,7 +16039,7 @@ function assemble(t, prog, cfg) {
14973
16039
  if (sepLeads) LEAD.at = cur;
14974
16040
  const sv = sep(input, sp, ctx);
14975
16041
  if (sv === FAIL) {
14976
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
16042
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14977
16043
  if (committed3(ctx)) return FAIL;
14978
16044
  break;
14979
16045
  }
@@ -14984,25 +16050,25 @@ function assemble(t, prog, cfg) {
14984
16050
  itemStart = skipTrivia(input, itemStart, ctx);
14985
16051
  }
14986
16052
  if (itemStart >= input.length && viaRepItem) {
14987
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
16053
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14988
16054
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
14989
16055
  break;
14990
16056
  }
14991
16057
  if (count >= min && gateItems && !itemMayStart(input, itemStart)) {
14992
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
16058
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14993
16059
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
14994
16060
  break;
14995
16061
  }
14996
16062
  ctx._fc = false;
14997
16063
  const v = child(input, itemStart, ctx);
14998
16064
  if (v === FAIL) {
14999
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
16065
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
15000
16066
  if (committed3(ctx)) return FAIL;
15001
16067
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
15002
16068
  break;
15003
16069
  }
15004
16070
  if (EC.e === itemStart && viaRepItem) {
15005
- if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
16071
+ if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
15006
16072
  break;
15007
16073
  }
15008
16074
  if (out !== void 0) out.push(v);
@@ -15076,7 +16142,14 @@ function assemble(t, prog, cfg) {
15076
16142
  const runArm = n === 0 ? void 0 : bindArms(0);
15077
16143
  const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted);
15078
16144
  return (input, pos, ctx) => {
15079
- const selectorMark = saveTriviaMark(ctx);
16145
+ const need = markCst(ctx);
16146
+ const mRaw = MRAW;
16147
+ const mTl = MTL;
16148
+ const mLv = MLV;
16149
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
16150
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
16151
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
16152
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
15080
16153
  const selVal = selector(input, pos, ctx);
15081
16154
  if (selVal === FAIL) return FAIL;
15082
16155
  const selEnd = EC.e;
@@ -15088,9 +16161,9 @@ function assemble(t, prog, cfg) {
15088
16161
  ctx._fx = expected;
15089
16162
  return FAIL;
15090
16163
  }
15091
- return runOther(input, pos, selEnd, key, selectorMark, ctx);
16164
+ return runOther(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
15092
16165
  }
15093
- return runArm(arm, input, pos, selEnd, key, selectorMark, ctx);
16166
+ return runArm(arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
15094
16167
  };
15095
16168
  }
15096
16169
  /* ── node ────────────────────────────────────────────────────────────── */
@@ -15126,7 +16199,8 @@ function assemble(t, prog, cfg) {
15126
16199
  return nd;
15127
16200
  };
15128
16201
  }
15129
- const child = link(code[ip + 2]);
16202
+ const child = NODE_BODY ?? link(code[ip + 2]);
16203
+ NODE_BODY = void 0;
15130
16204
  const proj = code[ip + 4];
15131
16205
  const buildIdx = code[ip + 1];
15132
16206
  const type = k[code[ip + 5]];
@@ -15150,6 +16224,30 @@ function assemble(t, prog, cfg) {
15150
16224
  if (build !== void 0 && proj < 0 && flags === 18) {
15151
16225
  return childrenOnlyFieldsBuildNode(child, build);
15152
16226
  }
16227
+ if (build !== void 0 && passCollapse(code, ip, hostCst)) {
16228
+ return passCollapseNode(child, build, flags === 32);
16229
+ }
16230
+ const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
16231
+ const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(closureLabels.at(code[ip + 2]).tri, trivia2);
16232
+ if (build !== void 0 && gated !== void 0 && triviaLead !== void 0) {
16233
+ const classic = flags === 32 ? collapseBuildNode(child, build) : childrenOnlyCollapseBuildNode(child, build);
16234
+ return gatedPassCollapseNode(
16235
+ [
16236
+ ...gated.leads.map((g) => cc[code[g + 1]]),
16237
+ resolveClass(encodeClassSpec([
16238
+ ...triviaLead,
16239
+ ...gated.lits.map((i) => {
16240
+ const c = k[i].codePointAt(0);
16241
+ return { lo: c, hi: c };
16242
+ })
16243
+ ]))
16244
+ ],
16245
+ link(gated.last),
16246
+ classic,
16247
+ build,
16248
+ flags === 32
16249
+ );
16250
+ }
15153
16251
  if (build !== void 0 && proj < 0 && flags === 32) {
15154
16252
  return collapseBuildNode(child, build);
15155
16253
  }
@@ -15196,7 +16294,7 @@ function assemble(t, prog, cfg) {
15196
16294
  if (v === FAIL) return FAIL;
15197
16295
  const end = EC.e;
15198
16296
  const span = tracked ? spanLines(ctx, pos, end) : { start: pos, end };
15199
- const st = readsState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
16297
+ const st = readsState ? ctx.state : void 0;
15200
16298
  let nd;
15201
16299
  if (unwrap && kids.length === 1) {
15202
16300
  nd = unwrapChild(kids[0]);
@@ -15209,10 +16307,10 @@ function assemble(t, prog, cfg) {
15209
16307
  ) {
15210
16308
  nd = kids[0];
15211
16309
  } else if (proj >= 0) {
15212
- 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);
16310
+ nd = hostCst && host !== void 0 ? host(type, kids, fieldMap, span, rawKids, tlog, ctx.state, tags) : projectChild(kids, proj, type);
15213
16311
  } else if (build !== void 0) {
15214
16312
  if (hostCst && host !== void 0) {
15215
- nd = host(type, kids, fieldMap, span, rawKids, tlog, readsState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0, tags);
16313
+ nd = host(type, kids, fieldMap, span, rawKids, tlog, ctx.state, tags);
15216
16314
  } else {
15217
16315
  nd = build(kids, fieldMap, span, rawKids, captureWide ? tlog : EMPTY_TL2, st);
15218
16316
  }
@@ -15263,9 +16361,7 @@ function assemble(t, prog, cfg) {
15263
16361
  let emitRefusal;
15264
16362
  let emitReached;
15265
16363
  {
15266
- const extraIps = [];
15267
- for (const s of prog.scans ?? []) for (const r of scanRefs(s)) extraIps.push(r[0]);
15268
- for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
16364
+ const extraIps = assemblyExtraIps(prog);
15269
16365
  const roots = [...Object.values(prog.rules), ...extraIps];
15270
16366
  for (const ip of reachableSites(code, roots)) {
15271
16367
  if (code[ip] === OP_DISPATCH) {
@@ -15300,6 +16396,8 @@ function assemble(t, prog, cfg) {
15300
16396
  }
15301
16397
  const notChild = scalarTerminalNotChild(code, ip);
15302
16398
  if (notChild >= 0) scalarFor(notChild);
16399
+ const peekChild = scalarTerminalPeekChild(code, ip);
16400
+ if (peekChild >= 0) scalarFor(peekChild);
15303
16401
  }
15304
16402
  const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
15305
16403
  if (pre !== void 0) {
@@ -15358,9 +16456,12 @@ function assemble(t, prog, cfg) {
15358
16456
  adjacencyHolds,
15359
16457
  t.lexPrograms,
15360
16458
  LEAD,
15361
- triviaFieldCapture
16459
+ triviaFieldCapture,
16460
+ skipDeferredTrivia,
16461
+ collapseEmpty
15362
16462
  );
15363
16463
  emitReached = new Set(pre.reached);
16464
+ if (emitted.ext !== void 0) HYBRID = emitted;
15364
16465
  }
15365
16466
  try {
15366
16467
  if (emitted !== void 0) throw new ServedByBuild();
@@ -15442,7 +16543,9 @@ function assemble(t, prog, cfg) {
15442
16543
  adjacencyHolds,
15443
16544
  t.lexPrograms,
15444
16545
  LEAD,
15445
- triviaFieldCapture
16546
+ triviaFieldCapture,
16547
+ skipDeferredTrivia,
16548
+ collapseEmpty
15446
16549
  );
15447
16550
  emitReached = em.reached;
15448
16551
  } catch (e) {
@@ -15453,7 +16556,7 @@ function assemble(t, prog, cfg) {
15453
16556
  }
15454
16557
  function pieceAt(ip) {
15455
16558
  const em = emitted;
15456
- if (em !== void 0) {
16559
+ if (em !== void 0 && HYBRID === void 0) {
15457
16560
  const p = em.byIp[ip];
15458
16561
  if (p === void 0) throw new Error(`table emitter: no emitted body for site ${ip}`);
15459
16562
  return p;
@@ -15483,6 +16586,37 @@ function assemble(t, prog, cfg) {
15483
16586
  }
15484
16587
  const scans = scansArr;
15485
16588
  const scanSkip = (prog.scanSkip ?? []).map((set) => set.map((r) => subtreeComb(r)));
16589
+ if (HYBRID !== void 0) {
16590
+ const em = HYBRID;
16591
+ em.bind(
16592
+ (s) => {
16593
+ const saved = SCAN;
16594
+ SCAN = s;
16595
+ return saved;
16596
+ },
16597
+ em.ext.map((ip) => link(ip))
16598
+ );
16599
+ const pieces2 = {};
16600
+ for (const [name, entryIp] of Object.entries(prog.rules)) {
16601
+ pieces2[name] = em.pieces[name] ?? link(entryIp);
16602
+ }
16603
+ for (const ip of emitReached) reached.add(ip);
16604
+ return {
16605
+ pieces: pieces2,
16606
+ end: () => EC.e,
16607
+ begin: (ctx) => {
16608
+ begin(ctx);
16609
+ em.begin(ctx);
16610
+ },
16611
+ finish: () => {
16612
+ em.finish();
16613
+ finish();
16614
+ },
16615
+ scanSkip,
16616
+ reached,
16617
+ emitRefusal: void 0
16618
+ };
16619
+ }
15486
16620
  if (emitted !== void 0) {
15487
16621
  const em = emitted;
15488
16622
  return {
@@ -15518,6 +16652,15 @@ function assemble(t, prog, cfg) {
15518
16652
  }
15519
16653
  return { pieces, end: () => EC.e, begin, finish, scanSkip, reached, emitRefusal };
15520
16654
  }
16655
+ var SITE_COUNTS;
16656
+ function countedPiece(piece, ip) {
16657
+ const counts = SITE_COUNTS;
16658
+ if (counts === void 0) return piece;
16659
+ return (input, pos, ctx) => {
16660
+ counts[ip]++;
16661
+ return piece(input, pos, ctx);
16662
+ };
16663
+ }
15521
16664
  var AssemblyCache = class {
15522
16665
  t;
15523
16666
  prog;
@@ -15669,7 +16812,7 @@ function emitClassPool(classes) {
15669
16812
  if (classes.length < 2) return array;
15670
16813
  const delimiter = "|/~?^`".split("").find((ch2) => classes.every((spec) => !spec.includes(ch2)));
15671
16814
  if (delimiter === void 0) return array;
15672
- const split = `${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
16815
+ const split = `/* @__PURE__ */ ${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
15673
16816
  return split.length < array.length ? split : array;
15674
16817
  }
15675
16818
  function emitConst(v) {
@@ -15731,9 +16874,7 @@ function defaultAssemblyCfgs(prog) {
15731
16874
  function emitAssemblies(prog, cfgs) {
15732
16875
  if (cfgs.length === 0) return ["a:[],"];
15733
16876
  const t = resolveTable(prog);
15734
- const extraIps = [];
15735
- for (const s of prog.scans ?? []) for (const r of scanRefs(s)) extraIps.push(r[0]);
15736
- for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
16877
+ const extraIps = assemblyExtraIps(prog);
15737
16878
  const out = [];
15738
16879
  const seen = /* @__PURE__ */ new Set();
15739
16880
  for (const cfg of cfgs) {
@@ -15742,7 +16883,7 @@ function emitAssemblies(prog, cfgs) {
15742
16883
  seen.add(key);
15743
16884
  let em;
15744
16885
  try {
15745
- em = emitAssemblySource(t, prog, cfg, extraIps, true);
16886
+ em = emitAssemblySource(t, prog, cfg, extraIps, true, cfg.select);
15746
16887
  } catch (e) {
15747
16888
  if (e instanceof Unemittable) continue;
15748
16889
  throw e;
@@ -17299,8 +18440,46 @@ function runDuplicationDiagnosticRules(ruleMap, opt) {
17299
18440
  return reportDuplication(opt, (o) => analyzeDuplicationRules(ruleMap, o));
17300
18441
  }
17301
18442
 
18443
+ // src/table/select-hot.ts
18444
+ var LOOP = 8;
18445
+ var ROUNDS = 60;
18446
+ var CAP = 1e12;
18447
+ function selectHotSites(code, entries, siteBytes, budget, profile) {
18448
+ const selected = /* @__PURE__ */ new Set();
18449
+ if (budget <= 0) return selected;
18450
+ const weight = profile === void 0 ? staticWeights(code, entries) : void 0;
18451
+ const w = (ip) => (weight !== void 0 ? weight.get(ip) : profile[ip]) ?? 0;
18452
+ const ranked = [...siteBytes.keys()].sort((a, b) => w(b) / siteBytes.get(b) - w(a) / siteBytes.get(a) || a - b);
18453
+ let spent = 0;
18454
+ for (const ip of ranked) {
18455
+ if (w(ip) === 0) break;
18456
+ const bytes2 = siteBytes.get(ip);
18457
+ if (spent + bytes2 > budget) continue;
18458
+ spent += bytes2;
18459
+ selected.add(ip);
18460
+ }
18461
+ return selected;
18462
+ }
18463
+ function staticWeights(code, entries) {
18464
+ let weight = /* @__PURE__ */ new Map();
18465
+ const kids = [];
18466
+ for (let round = 0; round < ROUNDS; round++) {
18467
+ const next = /* @__PURE__ */ new Map();
18468
+ for (const ip of entries) next.set(ip, 1);
18469
+ for (const [ip, w] of weight) {
18470
+ kids.length = 0;
18471
+ childSlots(code, ip, kids);
18472
+ const op = code[ip];
18473
+ const scale = op === OP_REP || op === OP_REPV ? LOOP : op === OP_CHOICE || op === OP_DISPATCH ? 1 / Math.max(1, kids.length) : 1;
18474
+ for (const kid of kids) next.set(kid, Math.min(CAP, (next.get(kid) ?? 0) + w * scale));
18475
+ }
18476
+ weight = next;
18477
+ }
18478
+ return weight;
18479
+ }
18480
+
17302
18481
  // src/table/compile-rule-map.ts
17303
- var DEFAULT_PRECOMPILE_MIN_WORDS = 1024;
18482
+ var SUPERCOMPILE_GROWTH = 1.05;
17304
18483
  function resolveHostMode(ruleMap, explicit) {
17305
18484
  return explicit ?? ruleMap.map(([, r]) => r._meta.grammarHostMode).find(Boolean) ?? "ast";
17306
18485
  }
@@ -17397,14 +18576,45 @@ function compileRuleMap(ruleMap, opts = {}) {
17397
18576
  entry: null,
17398
18577
  runtimeRef: opts.runtimeRef ?? "tableRules",
17399
18578
  fnSources: sources,
17400
- ...options.precompileDefault === true && hostMode === "ast" && prog.lines !== 1 && prog.code.length >= DEFAULT_PRECOMPILE_MIN_WORDS ? { assemblies: defaultAssemblyCfgs(artifact).slice(0, 1) } : {},
18579
+ ...options.select !== void 0 && options.select.size > 0 ? { assemblies: [{ ...defaultAssemblyCfgs(artifact)[0], select: options.select }] } : {},
17401
18580
  ...metadataSource === void 0 ? {} : { metadataSource }
17402
18581
  });
17403
18582
  const replacement = replacementWithMetadata();
18583
+ const selectAssembly = (budget, profile) => {
18584
+ const none = { sites: /* @__PURE__ */ new Set(), bytes: 0 };
18585
+ if (hostMode !== "ast" || prog.lines === 1) return none;
18586
+ const table = resolveTable(artifact);
18587
+ const cfg = defaultAssemblyCfgs(artifact)[0];
18588
+ const roots = assemblyExtraIps(artifact);
18589
+ let siteBytes, fixed;
18590
+ try {
18591
+ siteBytes = emitAssemblySource(table, artifact, cfg, roots, true).siteBytes;
18592
+ fixed = emitAssemblySource(table, artifact, cfg, roots, true, /* @__PURE__ */ new Set()).source.length;
18593
+ } catch (e) {
18594
+ if (e instanceof Unemittable) return { ...none, refusal: e.construct };
18595
+ throw e;
18596
+ }
18597
+ const ceiling = budget / SUPERCOMPILE_GROWTH;
18598
+ if (ceiling <= fixed) return none;
18599
+ let target = ceiling;
18600
+ for (; ; ) {
18601
+ const sites = selectHotSites(artifact.code, Object.values(artifact.rules), siteBytes, target - fixed, profile);
18602
+ if (sites.size === 0) {
18603
+ return {
18604
+ ...none,
18605
+ refusal: `a site within its ${Math.floor(ceiling)} B selection ceiling (the prelude alone is ${fixed} B)`
18606
+ };
18607
+ }
18608
+ const bytes2 = emitAssemblySource(table, artifact, cfg, roots, true, sites).source.length;
18609
+ if (bytes2 <= ceiling) return { sites, bytes: Math.ceil(bytes2 * SUPERCOMPILE_GROWTH) };
18610
+ target *= Math.min(ceiling / bytes2, 0.99);
18611
+ }
18612
+ };
17404
18613
  return {
17405
18614
  keys: ruleMap.map(([key]) => key),
17406
18615
  replacement,
17407
18616
  replacementWithMetadata,
18617
+ selectAssembly,
17408
18618
  hostMode,
17409
18619
  // WHAT THE FLAG MEANS is "a DIRECT BUILDER's positioned-CST branch was
17410
18620
  // dropped", which is what the driver's `'ast' artifact + CST host` check keys
@@ -17486,16 +18696,16 @@ function ownSource(fn) {
17486
18696
  return typeof name === "string" && name.length > 0 && globalThis[name] === fn ? name : null;
17487
18697
  }
17488
18698
  function compile(target, second, third) {
17489
- if (!isCombinator(target)) return compileMap(target, second);
18699
+ if (!isCombinator2(target)) return compileMap(target, second);
17490
18700
  return compileRoot(target, second, third);
17491
18701
  }
17492
- function isCombinator(x) {
18702
+ function isCombinator2(x) {
17493
18703
  return typeof x === "object" && x !== null && typeof x.parse === "function" && "_def" in x;
17494
18704
  }
17495
18705
  function compileMap(grammar, opts = {}) {
17496
18706
  const entries = [];
17497
18707
  for (const [key, value] of Object.entries(grammar)) {
17498
- if (!isCombinator(value)) throw new TypeError(`compile: grammar entry "${key}" is not a parser`);
18708
+ if (!isCombinator2(value)) throw new TypeError(`compile: grammar entry "${key}" is not a parser`);
17499
18709
  if (value._def.tag === "lazy") {
17500
18710
  try {
17501
18711
  value._def.thunk();
@@ -18037,7 +19247,7 @@ function fieldOptionsSrc(def) {
18037
19247
  }
18038
19248
 
18039
19249
  // src/version.ts
18040
- var PARSEMAN_VERSION = "0.56.0";
19250
+ var PARSEMAN_VERSION = "0.58.0";
18041
19251
 
18042
19252
  // src/compiler/compile-linkable-table.ts
18043
19253
  function isLocal(rule) {
@@ -18306,7 +19516,7 @@ function analyzeGrammarGating(grammar, opts) {
18306
19516
  }
18307
19517
 
18308
19518
  // src/analysis/diagnose.ts
18309
- var isCombinator2 = (g) => typeof g === "object" && g !== null && "_def" in g;
19519
+ var isCombinator3 = (g) => typeof g === "object" && g !== null && "_def" in g;
18310
19520
  var isRuleEntries = (g) => Array.isArray(g);
18311
19521
  function diagnoseGrammar(grammar, opts) {
18312
19522
  const depth = degradationCaptureDepth();
@@ -18350,7 +19560,7 @@ function formatGrammarDiagnosis(d) {
18350
19560
  return lines2;
18351
19561
  }
18352
19562
  function runAnalysis(grammar, opts) {
18353
- if (isCombinator2(grammar)) return analyzeGating(grammar, opts);
19563
+ if (isCombinator3(grammar)) return analyzeGating(grammar, opts);
18354
19564
  if (isRuleEntries(grammar)) return analyzeGatingRules(grammar, opts);
18355
19565
  return analyzeGrammarGating(grammar, opts);
18356
19566
  }
@@ -20657,13 +21867,13 @@ function buildTriviaIndex(root, input = "", opts) {
20657
21867
  }
20658
21868
 
20659
21869
  // src/cst/walk.ts
20660
- function isCombinator3(value) {
21870
+ function isCombinator4(value) {
20661
21871
  return !!value && typeof value === "object" && "_def" in value && "_meta" in value && typeof value.parse === "function";
20662
21872
  }
20663
21873
  function reflectionFor(grammar) {
20664
21874
  const stamped = grammarReflectionOf(grammar);
20665
21875
  if (stamped) return stamped;
20666
- const entries = Object.entries(grammar).filter((entry) => isCombinator3(entry[1]));
21876
+ const entries = Object.entries(grammar).filter((entry) => isCombinator4(entry[1]));
20667
21877
  return collectGrammarReflection(entries);
20668
21878
  }
20669
21879
  function createVisitor(grammar, spec) {