parseman 0.56.0 → 0.57.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 (75) hide show
  1. package/dist/analysis/diagnostics.js +379 -72
  2. package/dist/analysis/diagnostics.js.map +3 -3
  3. package/dist/cli/index.js +379 -72
  4. package/dist/cli/index.js.map +3 -3
  5. package/dist/combinators/node.d.ts +1 -1
  6. package/dist/compiler/build-arity.d.ts +1 -1
  7. package/dist/compiler/build-arity.d.ts.map +1 -1
  8. package/dist/cst/trivia-kinds.d.ts +9 -1
  9. package/dist/cst/trivia-kinds.d.ts.map +1 -1
  10. package/dist/index.js +446 -75
  11. package/dist/index.js.map +3 -3
  12. package/dist/language-service/index.js +1 -0
  13. package/dist/language-service/index.js.map +1 -1
  14. package/dist/parse-context.d.ts.map +1 -1
  15. package/dist/plugin/entry-supercompiler.d.ts +1 -1
  16. package/dist/plugin/entry-supercompiler.d.ts.map +1 -1
  17. package/dist/plugin/index.d.ts +27 -1
  18. package/dist/plugin/index.d.ts.map +1 -1
  19. package/dist/plugin/index.js +930 -157
  20. package/dist/plugin/index.js.map +3 -3
  21. package/dist/plugin/ir-eval.d.ts +2 -0
  22. package/dist/plugin/ir-eval.d.ts.map +1 -1
  23. package/dist/regex/classes.d.ts.map +1 -1
  24. package/dist/run/index.js +1 -0
  25. package/dist/run/index.js.map +1 -1
  26. package/dist/table/assemble.d.ts +9 -0
  27. package/dist/table/assemble.d.ts.map +1 -1
  28. package/dist/table/child-slots.d.ts +4 -6
  29. package/dist/table/child-slots.d.ts.map +1 -1
  30. package/dist/table/compile-rule-map.d.ts +14 -2
  31. package/dist/table/compile-rule-map.d.ts.map +1 -1
  32. package/dist/table/emit-assembly.d.ts +17 -2
  33. package/dist/table/emit-assembly.d.ts.map +1 -1
  34. package/dist/table/emit.d.ts +5 -1
  35. package/dist/table/emit.d.ts.map +1 -1
  36. package/dist/table/encode.d.ts.map +1 -1
  37. package/dist/table/exec-baseline.d.ts.map +1 -1
  38. package/dist/table/exec.d.ts.map +1 -1
  39. package/dist/table/index.js +442 -70
  40. package/dist/table/index.js.map +3 -3
  41. package/dist/table/ops.d.ts +9 -6
  42. package/dist/table/ops.d.ts.map +1 -1
  43. package/dist/table/program.d.ts +13 -0
  44. package/dist/table/program.d.ts.map +1 -1
  45. package/dist/table/select-hot.d.ts +6 -0
  46. package/dist/table/select-hot.d.ts.map +1 -0
  47. package/dist/table/trivia-gap.d.ts +31 -0
  48. package/dist/table/trivia-gap.d.ts.map +1 -0
  49. package/dist/types.d.ts +17 -0
  50. package/dist/types.d.ts.map +1 -1
  51. package/dist/version.d.ts +1 -1
  52. package/package.json +4 -1
  53. package/src/combinators/node.ts +6 -13
  54. package/src/combinators/trivia-skip.ts +44 -1
  55. package/src/compiler/build-arity.ts +3 -3
  56. package/src/cst/trivia-kinds.ts +12 -1
  57. package/src/parse-context.ts +1 -0
  58. package/src/plugin/entry-supercompiler.ts +8 -9
  59. package/src/plugin/index.ts +138 -13
  60. package/src/plugin/ir-eval.ts +7 -1
  61. package/src/regex/classes.ts +3 -0
  62. package/src/table/assemble.ts +122 -24
  63. package/src/table/child-slots.ts +4 -6
  64. package/src/table/compile-rule-map.ts +55 -15
  65. package/src/table/emit-assembly.ts +139 -26
  66. package/src/table/emit.ts +8 -7
  67. package/src/table/encode.ts +69 -21
  68. package/src/table/exec-baseline.ts +1 -3
  69. package/src/table/exec.ts +7 -6
  70. package/src/table/ops.ts +9 -6
  71. package/src/table/program.ts +24 -0
  72. package/src/table/select-hot.ts +70 -0
  73. package/src/table/trivia-gap.ts +109 -0
  74. package/src/types.ts +18 -0
  75. package/src/version.ts +1 -1
package/dist/cli/index.js CHANGED
@@ -977,6 +977,7 @@ function literalCodePoints(frag) {
977
977
  if (ch2 === "\\") {
978
978
  const e = frag[i + 1];
979
979
  if (e === void 0) return null;
980
+ if (!(e in CLASS_ESCAPES) && /\w/.test(e)) return null;
980
981
  out.push(e in CLASS_ESCAPES ? CLASS_ESCAPES[e] : e.codePointAt(0));
981
982
  i += 2;
982
983
  continue;
@@ -1089,6 +1090,7 @@ function createParseContext() {
1089
1090
  _rootTriviaKindIndex: void 0,
1090
1091
  _rootTriviaStrictScopes: void 0,
1091
1092
  _rootTriviaCapture: void 0,
1093
+ _gap: void 0,
1092
1094
  _cstTriviaLog: void 0,
1093
1095
  _fields: void 0,
1094
1096
  _cstBuf: void 0,
@@ -1571,7 +1573,10 @@ function labeledTriviaSpec(arms, minRepeats) {
1571
1573
  arms,
1572
1574
  minRepeats,
1573
1575
  visitor: commonLabeledTriviaVisitor({ arms, minRepeats }),
1574
- charArms: charArmsFor({ arms, minRepeats })
1576
+ charArms: charArmsFor({ arms, minRepeats }),
1577
+ rootKinds: void 0,
1578
+ rootLeaders: [],
1579
+ rootScan: null
1575
1580
  };
1576
1581
  }
1577
1582
  function matchArmAt(input, pos, arm, state) {
@@ -2031,8 +2036,50 @@ function loopScanner(arms) {
2031
2036
  function regexTriviaScanner(parser2) {
2032
2037
  const d = parser2._def.tag === "label" ? parser2._def.parser._def : parser2._def;
2033
2038
  if (d.tag !== "regex" || d.flags) return null;
2034
- const source = d.source;
2035
- return classRunSource(source) ?? altStarSource(source) ?? prefixRunSource(source) ?? delimitedSource(source);
2039
+ return sourceScanner(d.source);
2040
+ }
2041
+ function sourceScanner(source) {
2042
+ return classRunSource(source) ?? altStarSource(source) ?? prefixRunSource(source) ?? delimitedSource(source) ?? sharedPrefixAltSource(source);
2043
+ }
2044
+ function sharedPrefixAltSource(source) {
2045
+ const m = /^((?:\\.|[^\\[\]()*+?|^$.{}])+)\(\?:(.*)\)$/.exec(source);
2046
+ if (!m) return null;
2047
+ const alts = [];
2048
+ const body = m[2];
2049
+ let depth = 0;
2050
+ let start = 0;
2051
+ for (let i = 0; i < body.length; i++) {
2052
+ const c = body[i];
2053
+ if (c === "\\") {
2054
+ i++;
2055
+ continue;
2056
+ }
2057
+ if (c === "[") {
2058
+ while (i < body.length && body[i] !== "]") i += body[i] === "\\" ? 2 : 1;
2059
+ continue;
2060
+ }
2061
+ if (c === "(") depth++;
2062
+ else if (c === ")" && --depth < 0) return null;
2063
+ else if (c === "|" && depth === 0) {
2064
+ alts.push(body.slice(start, i));
2065
+ start = i + 1;
2066
+ }
2067
+ }
2068
+ if (depth !== 0 || alts.length === 0) return null;
2069
+ alts.push(body.slice(start));
2070
+ const scanners = [];
2071
+ for (const alt of alts) {
2072
+ const scanner = sourceScanner(m[1] + alt);
2073
+ if (scanner === null) return null;
2074
+ scanners.push(scanner);
2075
+ }
2076
+ return (input, cur) => {
2077
+ for (const scanner of scanners) {
2078
+ const end = scanner(input, cur);
2079
+ if (end > cur) return end;
2080
+ }
2081
+ return cur;
2082
+ };
2036
2083
  }
2037
2084
  function bmpString(cps) {
2038
2085
  if (!cps) return null;
@@ -5278,6 +5325,12 @@ function scanRefs(s) {
5278
5325
  refs.push(...s.skip);
5279
5326
  return refs;
5280
5327
  }
5328
+ function assemblyExtraIps(prog) {
5329
+ const ips = [];
5330
+ for (const s of prog.scans ?? []) for (const r of scanRefs(s)) ips.push(r[0]);
5331
+ for (const set of prog.scanSkip ?? []) for (const r of set) ips.push(r[0]);
5332
+ return ips;
5333
+ }
5281
5334
  function expandCompact(p) {
5282
5335
  if ("code" in p) return p;
5283
5336
  return ownTableProgram({
@@ -5408,6 +5461,11 @@ function classHas2(cls, code) {
5408
5461
  for (let i = 0; i < hi.length; i += 2) if (code >= hi[i] && code <= hi[i + 1]) return true;
5409
5462
  return false;
5410
5463
  }
5464
+ function dispatchIsExclusive(arms, cc) {
5465
+ const resolved = [];
5466
+ for (const ci of arms) if (ci >= 0) resolved[ci] = resolveClass(cc[ci]);
5467
+ return resolveDispatch(arms, resolved).exclusive;
5468
+ }
5411
5469
  function resolveDispatch(arms, cc) {
5412
5470
  const ascii = new Uint8Array(128);
5413
5471
  const hi = [];
@@ -5721,7 +5779,7 @@ function confirmedArityForDef(def) {
5721
5779
  severity: "warn",
5722
5780
  where: `node("${def.type ?? "<inferred>"}")`,
5723
5781
  subject,
5724
- 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`,
5782
+ 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`,
5725
5783
  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"
5726
5784
  });
5727
5785
  return null;
@@ -6035,7 +6093,7 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
6035
6093
  }
6036
6094
  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;
6037
6095
  const capturesTrivia = captureTrivia || (build ? buildReadsTrivia(def) : project === void 0);
6038
- const clonesState = build ? buildReadsState(def) : project === void 0;
6096
+ const readsState = build ? buildReadsState(def) : project === void 0;
6039
6097
  const hasOwnFields = parserHasOwnFields(combinator);
6040
6098
  const capturesFields = hasOwnFields && (build ? buildReadsFields(def) : project === void 0);
6041
6099
  const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
@@ -6076,12 +6134,11 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
6076
6134
  ctx._triviaCaptureMask = savedMask;
6077
6135
  const { children: children2, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
6078
6136
  if (!r.ok) return r;
6079
- const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
6137
+ const st = readsState ? ctx.state : void 0;
6080
6138
  const nodeType = def.type ?? missingInferredType();
6081
6139
  const cstOutput = cstOutputHost(ctx.build);
6082
6140
  const span = ctx.trackLines ? annotateSpanFromLineContext(r.span, ctx) : r.span;
6083
- const hostState = clonesState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
6084
- const built = unwrap && children2.length === 1 ? unwrapChild(children2[0]) : collapse && children2.length === 1 ? children2[0] : (cstOutput || !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 ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, hostState, tags) : projectChild(children2, project, nodeType) : build ? cstOutput && 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 };
6141
+ const built = unwrap && children2.length === 1 ? unwrapChild(children2[0]) : collapse && children2.length === 1 ? children2[0] : (cstOutput || !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 ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, ctx.state, tags) : projectChild(children2, project, nodeType) : build ? cstOutput && 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 };
6085
6142
  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 };
6086
6143
  if (saved.buf !== void 0 || saved.ch !== void 0) {
6087
6144
  pushCstChild(ctx, built, rawEntry2);
@@ -6692,6 +6749,33 @@ var Encoder = class {
6692
6749
  return childrenOf(def);
6693
6750
  }
6694
6751
  }
6752
+ /**
6753
+ * THE FIRST-CHARACTER GATE OF AN `optional`, `not` OR `peek` CHILD.
6754
+ *
6755
+ * A non-nullable child cannot match at a character outside its first set, so
6756
+ * the wrapper's outcome there is already decided: `optional` yields `null`,
6757
+ * `not` succeeds, `peek` fails with its own set. The interpreter's `optional`
6758
+ * makes that test itself (`repeat.ts` `startsFirstSet`); the table entered the
6759
+ * child — a rollback mark, the call, the child's own failure — to learn it.
6760
+ *
6761
+ * The gate is an `OP_GATE` row around the child, so every engine runs it
6762
+ * unchanged, a probe or tolerant parse forwards through it as for a node's
6763
+ * gate, and the wrapper's row keeps its layout. The engines test the class
6764
+ * before taking the wrapper's mark. The first set is resolved through
6765
+ * `winners`, the analysis a choice arm's gate uses, so a composed rule's set
6766
+ * is the merged one. A scalar `not` child stays bare: `scalarTerminalNotChild`
6767
+ * already reduces it to one recognizer call.
6768
+ */
6769
+ lookaheadGate(p, child) {
6770
+ const op = this.code[child];
6771
+ 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;
6772
+ const rr = this.refResolver();
6773
+ if (matchesEmpty(p, /* @__PURE__ */ new Set(), rr)) return child;
6774
+ const cls = this.charClass(firstSetOf(p, /* @__PURE__ */ new Set(), rr, this.activeTrivia));
6775
+ if (cls < 0) return child;
6776
+ const e = deriveExpected(p);
6777
+ return this.emit(OP_GATE, cls, child, this.expected(e.length > 0 ? e : [p._tag]));
6778
+ }
6695
6779
  /** A first set becomes a char class string, or −1 for `any`. */
6696
6780
  charClass(fs) {
6697
6781
  if (fs.kind !== "ranges" || fs.ranges.length === 0) return -1;
@@ -6703,12 +6787,19 @@ var Encoder = class {
6703
6787
  this.ccIndex.set(spec, i);
6704
6788
  return i;
6705
6789
  }
6706
- /** Bind a guard only when its class is already part of the program. Repeat
6707
- * gating must not grow the compact artifact merely to avoid a failed call. */
6708
- existingCharClass(fs) {
6709
- if (fs.kind !== "ranges" || fs.ranges.length === 0) return -1;
6710
- const hit = this.ccIndex.get(encodeClassSpec(fs.ranges));
6711
- return hit !== void 0 && hit < 100 ? hit : -1;
6790
+ /**
6791
+ * The first set a node's or an attempt's fail-fast gate tests. A bare
6792
+ * cross-rule ref resolves through `winners` (a compose OVERRIDE may widen
6793
+ * it). Any other body keeps its construction-time `_meta.firstSet`, except
6794
+ * where that is `any`: under `compose()` a body that reaches a rule of
6795
+ * another piece is built before that rule exists, so its cached set is
6796
+ * `any` and the node got NO gate (jess's `CompoundSelector` was entered at
6797
+ * `{`, `Call` at `}`). The resolved set is the one a choice arm's gate uses,
6798
+ * over the final merged map.
6799
+ */
6800
+ gateFirstSet(p) {
6801
+ const cached = p._meta.firstSet;
6802
+ return p._def.tag === "lazy" || cached.kind === "any" ? firstSetOf(p, /* @__PURE__ */ new Set(), this.refResolver(), this.activeTrivia) : cached;
6712
6803
  }
6713
6804
  /**
6714
6805
  * Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
@@ -7013,6 +7104,12 @@ var Encoder = class {
7013
7104
  if (transactionalFirst[i] !== void 0) classes[i] = -1;
7014
7105
  }
7015
7106
  }
7107
+ if (d.gates.some((g) => g !== null && g !== void 0) && !dispatchIsExclusive(classes, this.cc)) {
7108
+ for (let k = 0; k < classes.length; k++) {
7109
+ const gate = d.gates[order[k]];
7110
+ if (gate !== null && gate !== void 0) classes[k] = -1;
7111
+ }
7112
+ }
7016
7113
  const dispIdx = this.disp.length;
7017
7114
  this.disp.push(classes);
7018
7115
  let rollbackMask = kids.length > 31 ? -1 : 0;
@@ -7042,7 +7139,7 @@ var Encoder = class {
7042
7139
  case "oneOrMore": {
7043
7140
  const child = this.node(d.parser).ip;
7044
7141
  const rr = this.refResolver();
7045
- const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.existingCharClass(firstSetOf(d.parser, /* @__PURE__ */ new Set(), rr, this.activeTrivia));
7142
+ const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.charClass(firstSetOf(d.parser, /* @__PURE__ */ new Set(), rr, this.activeTrivia));
7046
7143
  const op = d.valueUnused ? OP_REPV : OP_REP;
7047
7144
  const min = d.tag === "many" ? 0 : d.min;
7048
7145
  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);
@@ -7066,7 +7163,7 @@ var Encoder = class {
7066
7163
  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);
7067
7164
  }
7068
7165
  case "optional": {
7069
- const head = this.emit(OP_OPT, this.node(d.parser).ip);
7166
+ const head = this.emit(OP_OPT, this.lookaheadGate(d.parser, this.node(d.parser).ip));
7070
7167
  if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(head);
7071
7168
  return head;
7072
7169
  }
@@ -7114,8 +7211,8 @@ var Encoder = class {
7114
7211
  // every CST node, so this is load-bearing, not reflection trivia.
7115
7212
  d.tags === void 0 ? -1 : this.constant(d.tags)
7116
7213
  );
7117
- if (matchesEmpty(d.parser)) return body;
7118
- const fs = d.parser._def.tag === "lazy" ? firstSetOf(d.parser, /* @__PURE__ */ new Set(), this.refResolver(), this.activeTrivia) : d.parser._meta.firstSet;
7214
+ if (matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return body;
7215
+ const fs = this.gateFirstSet(d.parser);
7119
7216
  if (fs.kind === "any") return body;
7120
7217
  const cls = this.charClass(fs);
7121
7218
  if (cls < 0) return body;
@@ -7207,7 +7304,7 @@ var Encoder = class {
7207
7304
  // other engine reported `['not(literal)']`. It hid because `expected` is a
7208
7305
  // TOP-LEVEL field on `RunResult` and is NOT part of the identity digest.
7209
7306
  case "not":
7210
- return this.emit(OP_NOT, this.node(d.parser).ip, this.expected(assertionFailureExpected(false, d.parser._tag)));
7307
+ return this.emit(OP_NOT, this.lookaheadGate(d.parser, this.node(d.parser).ip), this.expected(assertionFailureExpected(false, d.parser._tag)));
7211
7308
  case "guard":
7212
7309
  return this.emit(OP_GUARD, this.fn(d.predicate, d.predSrc ?? null), this.expected(["gate"]));
7213
7310
  case "adjacency":
@@ -7228,14 +7325,14 @@ var Encoder = class {
7228
7325
  return this.emit(OP_WITHCTX, this.constant(d.extra), this.node(d.parser).ip);
7229
7326
  }
7230
7327
  case "peek":
7231
- return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected(assertionFailureExpected(true, d.parser._tag)));
7328
+ return this.emit(OP_PEEK, this.lookaheadGate(d.parser, this.node(d.parser).ip), this.expected(assertionFailureExpected(true, d.parser._tag)));
7232
7329
  // A TRANSACTION IS A ROW. See `OP_ATTEMPT` for why the transparent
7233
7330
  // lowering was correct only for a choice arm.
7234
7331
  case "attempt": {
7235
7332
  const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip, d.contain === true ? 1 : 0);
7236
7333
  if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
7237
- const fs = d.parser._def.tag === "lazy" ? firstSetOf(d.parser, /* @__PURE__ */ new Set(), this.refResolver(), this.activeTrivia) : d.parser._meta.firstSet;
7238
- if (fs.kind === "any" || matchesEmpty(d.parser)) return inner;
7334
+ const fs = this.gateFirstSet(d.parser);
7335
+ if (fs.kind === "any" || matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return inner;
7239
7336
  const cls = this.charClass(fs);
7240
7337
  if (cls < 0) return inner;
7241
7338
  const e = deriveExpected(d.parser);
@@ -8960,7 +9057,10 @@ var EMITTED_PARAMS = [
8960
9057
  // Appended for trivia-attributing fields (`field(…, { leadingTrivia })`);
8961
9058
  // old factories ignore them.
8962
9059
  "LEAD",
8963
- "triviaFieldCapture"
9060
+ "triviaFieldCapture",
9061
+ // Appended for the deferred-commit trivia skip (`trivia-gap.ts`); old
9062
+ // factories ignore it.
9063
+ "skipDeferredTrivia"
8964
9064
  ];
8965
9065
  var RUNTIME_PRELUDE = `
8966
9066
  let _pfScan=null
@@ -8981,7 +9081,7 @@ function _skipTrivia(input,cur,ctx){
8981
9081
  const s=_pfScan
8982
9082
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
8983
9083
  if(s!==null)return skipTriviaScanned(s,input,cur,ctx)
8984
- if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
9084
+ if(needsDeferredTriviaCommit(ctx))return skipDeferredTrivia(input,cur,ctx)
8985
9085
  return advanceTrivia(input,cur,ctx)
8986
9086
  }
8987
9087
  function _pushLeaf(ctx,value,s,e){pushCstLeaf(ctx,{_tag:'leaf',value,span:{start:s,end:e}})}
@@ -9188,7 +9288,7 @@ function rebuildPools(cc, fx, disp, plan) {
9188
9288
  })
9189
9289
  };
9190
9290
  }
9191
- function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false) {
9291
+ function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false, select) {
9192
9292
  const { code, k, fx, disp, dsp, triviaLabelled } = t2;
9193
9293
  const swapLegal = !cfg.trackLines;
9194
9294
  const hostCst = cfg.hostCst;
@@ -9287,6 +9387,8 @@ function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false) {
9287
9387
  };
9288
9388
  const bodies = [];
9289
9389
  const byIp = /* @__PURE__ */ new Map();
9390
+ const externals = [];
9391
+ const siteBytes = /* @__PURE__ */ new Map();
9290
9392
  const reached = /* @__PURE__ */ new Set();
9291
9393
  const prelude = [];
9292
9394
  const skipDefs = [];
@@ -9422,6 +9524,18 @@ return 1
9422
9524
  tokenDecisionRefs.set(dispatchIp, made);
9423
9525
  return made;
9424
9526
  }
9527
+ function gateMissTest(gip) {
9528
+ const resolved = t2.cc[code[gip + 1]];
9529
+ const ci = classes.push([resolved]) - 1;
9530
+ classPlan.push([code[gip + 1]]);
9531
+ const cls = hoist("cl", `CLS[${ci}][0]`);
9532
+ return isAsciiOnlyClass(resolved) ? `${cls}.ascii[input.charCodeAt(pos)]!==1` : `!classHas(${cls},lead(input,pos))`;
9533
+ }
9534
+ function lookaheadMiss(child, miss) {
9535
+ if (code[child] !== OP_GATE || cfg.tolerant || cfg.probe) return "";
9536
+ return `if(${gateMissTest(child)}){${miss}}
9537
+ `;
9538
+ }
9425
9539
  function skipFor(l) {
9426
9540
  if (l.tri < 0) return "_skipTrivia";
9427
9541
  const ki = l.tri;
@@ -9432,8 +9546,8 @@ return 1
9432
9546
  const nm = `_sk${skipPool.size}`;
9433
9547
  skipPool.set(key, nm);
9434
9548
  if (!hasScan) {
9435
- skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return commitTriviaScan(scanTriviaCompact(input,cur,ctx))}` : `function ${nm}(input,cur,ctx){
9436
- if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
9549
+ skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return skipDeferredTrivia(input,cur,ctx)}` : `function ${nm}(input,cur,ctx){
9550
+ if(needsDeferredTriviaCommit(ctx))return skipDeferredTrivia(input,cur,ctx)
9437
9551
  return advanceTrivia(input,cur,ctx)}`);
9438
9552
  return nm;
9439
9553
  }
@@ -9478,9 +9592,17 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
9478
9592
  const target = resolveAlias(ip);
9479
9593
  const done = byIp.get(target);
9480
9594
  if (done !== void 0) return done;
9595
+ if (select !== void 0 && !select.has(target)) {
9596
+ const ext = `_px${target}`;
9597
+ byIp.set(target, ext);
9598
+ externals.push(target);
9599
+ return ext;
9600
+ }
9481
9601
  const fname = `_pf${target}`;
9482
9602
  byIp.set(target, fname);
9483
- bodies.push(lower(target, fname));
9603
+ const body = lower(target, fname);
9604
+ siteBytes.set(target, body.length);
9605
+ bodies.push(body);
9484
9606
  return fname;
9485
9607
  }
9486
9608
  function resolveAlias(ip) {
@@ -9620,14 +9742,28 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
9620
9742
  return `${head}EC.e=pos;return ''}`;
9621
9743
  case OP_GATE: {
9622
9744
  const child = link(code[ip + 2]);
9623
- const resolved = t2.cc[code[ip + 1]];
9624
- const ci = classes.push([resolved]) - 1;
9625
- classPlan.push([code[ip + 1]]);
9626
- const cls = hoist("cl", `CLS[${ci}][0]`);
9627
9745
  const xf = fxRef(code[ip + 3]);
9628
9746
  return `${head}
9629
- if(${staticBuild && isAsciiOnlyClass(resolved) ? `${cls}.ascii[input.charCodeAt(pos)]!==1` : `!classHas(${cls},lead(input,pos))`}){ctx._fe=pos;ctx._fx=${xf};return FAIL}
9747
+ if(${gateMissTest(ip)}){ctx._fe=pos;ctx._fx=${xf};return FAIL}
9630
9748
  return ${child}(input,pos,ctx)
9749
+ }`;
9750
+ }
9751
+ case OP_ARMGATE: {
9752
+ const pred = fnRef(code[ip + 1]);
9753
+ const child = link(code[ip + 2]);
9754
+ const xf = fxRef(code[ip + 3]);
9755
+ return `${head}
9756
+ if(!${pred}(ctx.state)){ctx._fc=false;ctx._fe=-1;ctx._fx=${xf};return FAIL}
9757
+ return ${child}(input,pos,ctx)
9758
+ }`;
9759
+ }
9760
+ case OP_WITHCTX: {
9761
+ const ki = code[ip + 1];
9762
+ const child = link(code[ip + 2]);
9763
+ return `${head}
9764
+ const saved=ctx.state
9765
+ ctx.state=${ki < 0 ? `${fnRef(~ki)}(saved)` : kRef(ki)}
9766
+ try{return ${child}(input,pos,ctx)}finally{ctx.state=saved}
9631
9767
  }`;
9632
9768
  }
9633
9769
  case OP_XFORM: {
@@ -9883,7 +10019,7 @@ return FAIL
9883
10019
  const xf = fxRef(code[ip + 2]);
9884
10020
  const p = tmp();
9885
10021
  return `${head}
9886
- ${emitMark(p, L.buf, L.raw, sinks)}
10022
+ ${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${emitMark(p, L.buf, L.raw, sinks)}
9887
10023
  const v=${child}(input,pos,ctx)
9888
10024
  ${emitRollback(p, L.buf, L.raw, sinks)}
9889
10025
  if(v===FAIL){EC.e=pos;return null}
@@ -9897,7 +10033,7 @@ return FAIL
9897
10033
  const xf = fxRef(code[ip + 2]);
9898
10034
  const p = tmp();
9899
10035
  return `${head}
9900
- ${emitMark(p, L.buf, L.raw, sinks)}
10036
+ ${lookaheadMiss(code[ip + 1], `ctx._fe=pos;ctx._fx=${xf};return FAIL`)}${emitMark(p, L.buf, L.raw, sinks)}
9901
10037
  const v=${child}(input,pos,ctx)
9902
10038
  ${emitRollback(p, L.buf, L.raw, sinks)}
9903
10039
  if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
@@ -9910,7 +10046,7 @@ return null
9910
10046
  const clean = !REC && failureRollbackClean(prog, ip);
9911
10047
  const p = tmp();
9912
10048
  return `${head}
9913
- ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
10049
+ ${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
9914
10050
  ctx._fc=false
9915
10051
  const v=${child}(input,pos,ctx)
9916
10052
  if(v===FAIL){
@@ -9991,7 +10127,7 @@ return v
9991
10127
  const asc = hoist("as", `DISP[${di}].ascii`);
9992
10128
  const hiArr = table.hi;
9993
10129
  const armSwitch = arms.map((a, i) => `case ${i}:v=${a}(input,pos,ctx);break`).join("\n");
9994
- const directAscii = staticBuild && table.hi.length === 0;
10130
+ const directAscii = table.hi.length === 0;
9995
10131
  return `${head}
9996
10132
  const c=${directAscii ? "input.charCodeAt(pos)" : "lead(input,pos)"}
9997
10133
  let arm=-1
@@ -10018,7 +10154,7 @@ return FAIL
10018
10154
  const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
10019
10155
  const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
10020
10156
  const maskable = n <= 32;
10021
- const directAsciiMask = staticBuild && maskable && gates.every(isAsciiOnlyClass);
10157
+ const directAsciiMask = maskable && gates.every(isAsciiOnlyClass);
10022
10158
  const gateRefs = directAsciiMask ? [] : Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
10023
10159
  const tokenCandidate = tokenChoiceCandidates.get(ip);
10024
10160
  const pretests = Array.from({ length: n }, (_, i) => {
@@ -10060,7 +10196,7 @@ return FAIL
10060
10196
  if (choiceCannotCommit(prog, ip) && !startFailureExact) {
10061
10197
  const deepAt = Array.from({ length: n }, () => tmp());
10062
10198
  const deepFx = Array.from({ length: n }, () => tmp());
10063
- const remember = (i, at, expectedSet) => `${deepAt[i]}=${at};${deepFx[i]}=${expectedSet}`;
10199
+ const remember2 = (i, at, expectedSet) => `${deepAt[i]}=${at};${deepFx[i]}=${expectedSet}`;
10064
10200
  const lazyArms = (ascii) => arms.map((arm, i) => {
10065
10201
  const pretest = pretests[i];
10066
10202
  const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
@@ -10072,13 +10208,13 @@ return FAIL
10072
10208
  if(${decision}===0){
10073
10209
  ctx._fc=false
10074
10210
  {const at=_pfTokEnd
10075
- ${remember(i, "at", pretest.token.expected)}}
10211
+ ${remember2(i, "at", pretest.token.expected)}}
10076
10212
  }`;
10077
10213
  const sequenceMiss = pretest?.sequence === void 0 ? "" : `
10078
10214
  else if(${ascii ? `(bits&${1 << i})!==0&&` : ""}${decision}<0){
10079
10215
  ctx._fc=false
10080
10216
  {const at=_pfSeqEnd
10081
- ${remember(i, "at", pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("") + pretest.sequence.expected.at(-1))}}
10217
+ ${remember2(i, "at", pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("") + pretest.sequence.expected.at(-1))}}
10082
10218
  }`;
10083
10219
  return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
10084
10220
  `}if(${gate}){
@@ -10086,7 +10222,7 @@ ctx._fc=false
10086
10222
  {const v=${arm}(input,pos,ctx)
10087
10223
  if(v!==FAIL)return v}
10088
10224
  {const at=ctx._fe??pos
10089
- ${remember(i, "at", "ctx._fx")}}
10225
+ ${remember2(i, "at", "ctx._fx")}}
10090
10226
  ${rollbackFor(i)}
10091
10227
  }${routeMiss}${sequenceMiss}`;
10092
10228
  }).join("\n");
@@ -10199,7 +10335,7 @@ const bits=${maskName}[${directAsciiMask ? "c" : "c<0?128:c"}]
10199
10335
  if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
10200
10336
  ${startFailureExact ? "" : "let prev=0"}
10201
10337
  ${maskArms}
10202
- ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${n},prev,acc)`}
10338
+ ${startFailureExact ? "" : `if(best===pos&&prev!==0)acc=${catchName}(${n},prev,acc)`}
10203
10339
  ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
10204
10340
  return FAIL
10205
10341
  }
@@ -10298,7 +10434,7 @@ return [key,v]
10298
10434
  const ci = classes.push([resolved]) - 1;
10299
10435
  classPlan.push([itemClassIndex]);
10300
10436
  itemCls = hoist("ri", `CLS[${ci}][0]`);
10301
- itemAscii = staticBuild && isAsciiOnlyClass(resolved);
10437
+ itemAscii = isAsciiOnlyClass(resolved);
10302
10438
  }
10303
10439
  }
10304
10440
  const itemMiss = (at) => itemAscii ? `${itemCls}.ascii[input.charCodeAt(${at})]!==1` : `!classHas(${itemCls},lead(input,${at}))`;
@@ -10524,7 +10660,7 @@ return nd
10524
10660
  const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
10525
10661
  const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
10526
10662
  const ty = q(type);
10527
- const stArg = readsState ? "st" : "(ctx.state!==undefined?Object.assign({},ctx.state):undefined)";
10663
+ const stArg = "ctx.state";
10528
10664
  const hostCall = `_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,${stArg},${tags})`;
10529
10665
  let value;
10530
10666
  if (proj >= 0) {
@@ -10585,7 +10721,7 @@ ctx.captureTrivia=sCap
10585
10721
  if(v===FAIL)return FAIL
10586
10722
  const end=EC.e
10587
10723
  const span=${tracked ? "spanLines(ctx,pos,end)" : "{start:pos,end}"}
10588
- const st=${readsState ? "(ctx.state!==undefined?Object.assign({},ctx.state):undefined)" : "undefined"}
10724
+ const st=${readsState ? "ctx.state" : "undefined"}
10589
10725
  let nd
10590
10726
  ${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]
10591
10727
  else ` : ""}{${value}}
@@ -10598,21 +10734,51 @@ return nd
10598
10734
  throw new Unemittable(`OP_${OP_NAMES[op] ?? String(op)}`);
10599
10735
  }
10600
10736
  }
10737
+ const served = (ip) => select === void 0 || select.has(resolveAlias(ip));
10601
10738
  const ruleEntries = [];
10602
10739
  for (const [rname, entryIp] of Object.entries(prog.rules)) {
10740
+ if (!served(entryIp)) continue;
10603
10741
  const target = link(entryIp);
10604
10742
  const rn = `_r_${rname.replace(/[^A-Za-z0-9_$]/g, "_")}`;
10605
10743
  bodies.push(`const ${rn}=${target}`);
10606
10744
  ruleEntries.push(`${q(rname)}:${rn}`);
10607
10745
  }
10608
10746
  const extra = [];
10609
- for (const ip of extraIps) extra.push(`${ip}:${link(ip)}`);
10747
+ const exported = /* @__PURE__ */ new Set();
10748
+ for (const ip of extraIps) {
10749
+ if (!served(ip)) continue;
10750
+ exported.add(ip);
10751
+ extra.push(`${ip}:${link(ip)}`);
10752
+ }
10753
+ if (select !== void 0) {
10754
+ const kids = [];
10755
+ for (const ip of reachable) {
10756
+ if (select.has(resolveAlias(ip))) continue;
10757
+ kids.length = 0;
10758
+ childSlots(code, ip, kids);
10759
+ for (const kid of kids) {
10760
+ const target = resolveAlias(kid);
10761
+ if (!select.has(target) || exported.has(target)) continue;
10762
+ exported.add(target);
10763
+ extra.push(`${target}:${link(target)}`);
10764
+ }
10765
+ }
10766
+ }
10767
+ const hybrid = select === void 0 ? "" : `,
10768
+ ext:[${externals.join(",")}],
10769
+ bind:function(xs,ps){_xScan=xs
10770
+ ${externals.map((ip, i) => `_xp${ip}=ps[${i}]`).join("\n")}},
10771
+ scan:function(s){const o=_pfScan;_pfScan=s;return o}`;
10772
+ const externalDefs = select === void 0 ? "" : `let _xScan
10773
+ ${externals.map((ip) => `let _xp${ip}
10774
+ function _px${ip}(input,pos,ctx){const o=_xScan(_pfScan);const v=_xp${ip}(input,pos,ctx);_xScan(o);return v}`).join("\n")}
10775
+ `;
10610
10776
  const source = `${RUNTIME_PRELUDE}${needsNoRawPrelude ? NO_RAW_RUNTIME_PRELUDE : ""}
10611
10777
  ${prelude.join("\n")}
10612
10778
  ${skipDefs.join("\n")}
10613
10779
  ${choiceDefs.join("\n")}
10614
10780
  ${bodies.join("\n")}
10615
- function _begin(ctx){
10781
+ ${externalDefs}function _begin(ctx){
10616
10782
  const host=ctx.build
10617
10783
  if(_pfDepth>0)_pfFrames.push([_pfScan,_pfHost,EC.e])
10618
10784
  _pfDepth++
@@ -10639,7 +10805,7 @@ pieces:{${ruleEntries.join(",")}},
10639
10805
  byIp:{${extra.join(",")}},
10640
10806
  end:function(){return EC.e},
10641
10807
  begin:_begin,
10642
- finish:_finish
10808
+ finish:_finish${hybrid}
10643
10809
  }`;
10644
10810
  return {
10645
10811
  source,
@@ -10647,6 +10813,7 @@ finish:_finish
10647
10813
  masks,
10648
10814
  classes,
10649
10815
  armExpected,
10816
+ siteBytes,
10650
10817
  plan: { classes: classPlan, armExpected: armExpectedPlan, masks: maskPlan }
10651
10818
  };
10652
10819
  }
@@ -11480,6 +11647,70 @@ function escapeClassChar(ch2) {
11480
11647
  return ch2.replace(/[\\\]^-]/g, "\\$&");
11481
11648
  }
11482
11649
 
11650
+ // src/table/trivia-gap.ts
11651
+ function skipDeferredTrivia(input, cur, ctx) {
11652
+ const triviaP = ctx.trivia;
11653
+ const plain2 = ctx.trackLines !== true && ctx.captureTrivia !== true;
11654
+ const gap = ctx._gap;
11655
+ if (plain2 && 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;
11656
+ const end = clearRunEnd(input, cur, ctx, triviaP, plain2);
11657
+ if (end >= 0) {
11658
+ remember(cur, end, ctx, input, triviaP);
11659
+ return end;
11660
+ }
11661
+ const scan = scanTriviaCompact(input, cur, ctx);
11662
+ if (typeof scan !== "number") return commitTriviaScan(scan);
11663
+ if (plain2) remember(cur, scan, ctx, input, triviaP);
11664
+ return scan;
11665
+ }
11666
+ function clearRunEnd(input, cur, ctx, triviaP, plain2) {
11667
+ const rootKinds = ctx._rootTriviaKindIndex;
11668
+ const spec = triviaP?._meta.labeledTriviaSpec;
11669
+ if (!plain2 || triviaP === void 0 || spec == null || rootKinds === void 0 || ctx._triviaLog !== void 0) return -1;
11670
+ if (spec.rootKinds !== rootKinds) prime(spec, triviaP, rootKinds);
11671
+ const fast = spec.rootScan;
11672
+ if (fast === null) return -1;
11673
+ const end = fast(input, cur);
11674
+ return ctx._rootTriviaCapture === false || clearOf(spec.rootLeaders, input, cur, end) ? end : -1;
11675
+ }
11676
+ function remember(cur, end, ctx, input, triviaP) {
11677
+ const gap = ctx._gap;
11678
+ if (gap === void 0) {
11679
+ ctx._gap = { at: cur, end, input, of: triviaP, root: ctx._rootTriviaCapture, rootKinds: ctx._rootTriviaKindIndex, log: ctx._triviaLog, state: ctx.state };
11680
+ return;
11681
+ }
11682
+ gap.at = cur;
11683
+ gap.end = end;
11684
+ gap.input = input;
11685
+ gap.of = triviaP;
11686
+ gap.root = ctx._rootTriviaCapture;
11687
+ gap.rootKinds = ctx._rootTriviaKindIndex;
11688
+ gap.log = ctx._triviaLog;
11689
+ gap.state = ctx.state;
11690
+ }
11691
+ function prime(spec, triviaP, rootKinds) {
11692
+ const ranges = [];
11693
+ let bounded = true;
11694
+ for (const arm of spec.arms) {
11695
+ if (rootKinds[arm.label] === void 0) continue;
11696
+ const fs = arm.parser._meta.firstSet;
11697
+ if (fs.kind === "any") bounded = false;
11698
+ else if (fs.kind === "ranges") ranges.push(...fs.ranges);
11699
+ }
11700
+ const classified = triviaP._meta.triviaScanner;
11701
+ spec.rootKinds = rootKinds;
11702
+ spec.rootLeaders = ranges;
11703
+ spec.rootScan = !bounded ? null : classified === void 0 ? fastTriviaScanner(triviaP) : classified;
11704
+ }
11705
+ function clearOf(ranges, input, from, to) {
11706
+ for (let i = from; i < to; i++) {
11707
+ const c = input.charCodeAt(i);
11708
+ if (c >= 55296 && c <= 57343) return false;
11709
+ for (const r of ranges) if (c >= r.lo && c <= r.hi) return false;
11710
+ }
11711
+ return true;
11712
+ }
11713
+
11483
11714
  // src/table/run-support.ts
11484
11715
  function lineCol(ctx, offset) {
11485
11716
  const starts = ctx._lineStarts ?? [0];
@@ -11678,6 +11909,9 @@ function assemble(t2, prog, cfg) {
11678
11909
  const EC = newEndCell();
11679
11910
  const scalarRecognizers = [];
11680
11911
  const rawScalarSpecs = /* @__PURE__ */ new Set();
11912
+ function lookaheadClass(child) {
11913
+ return code[child] === OP_GATE && !cfg.tolerant && !cfg.probe ? cc[code[child + 1]] : null;
11914
+ }
11681
11915
  function scalarFor(child) {
11682
11916
  const spec = code[child + 1];
11683
11917
  let recognize = scalarRecognizers[spec];
@@ -11687,15 +11921,23 @@ function assemble(t2, prog, cfg) {
11687
11921
  }
11688
11922
  return recognize;
11689
11923
  }
11690
- const labelExtraIps = [];
11691
- for (const s of prog.scans ?? []) for (const r of scanRefs(s)) labelExtraIps.push(r[0]);
11692
- for (const set of prog.scanSkip ?? []) for (const r of set) labelExtraIps.push(r[0]);
11924
+ const labelExtraIps = assemblyExtraIps(prog);
11693
11925
  const closureLabels = computeSiteLabels(
11694
11926
  code,
11695
11927
  [...Object.values(prog.rules), ...labelExtraIps],
11696
11928
  hostCst
11697
11929
  );
11698
11930
  let SCAN = null;
11931
+ let HYBRID;
11932
+ function hybridPiece(piece) {
11933
+ const setScan = HYBRID.scan;
11934
+ return (input, pos, ctx) => {
11935
+ const saved = setScan(SCAN);
11936
+ const value = piece(input, pos, ctx);
11937
+ setScan(saved);
11938
+ return value;
11939
+ };
11940
+ }
11699
11941
  const memo = /* @__PURE__ */ new Map();
11700
11942
  const reached = /* @__PURE__ */ new Set();
11701
11943
  function pushLeaf(ctx, value, s, e) {
@@ -11987,9 +12229,7 @@ function assemble(t2, prog, cfg) {
11987
12229
  return s(input, cur);
11988
12230
  }
11989
12231
  if (s !== null) return skipTriviaScanned(s, input, cur, ctx);
11990
- if (needsDeferredTriviaCommit(ctx)) {
11991
- return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
11992
- }
12232
+ if (needsDeferredTriviaCommit(ctx)) return skipDeferredTrivia(input, cur, ctx);
11993
12233
  return advanceTrivia(input, cur, ctx);
11994
12234
  }
11995
12235
  let TERMV;
@@ -12159,7 +12399,7 @@ function assemble(t2, prog, cfg) {
12159
12399
  if (next !== void 0) {
12160
12400
  return next(input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best);
12161
12401
  }
12162
- if (best === pos) acc = through(total, prev, acc);
12402
+ if (best === pos && prev !== 0) acc = through(total, prev, acc);
12163
12403
  ctx._fe = pos;
12164
12404
  ctx._fx = acc ?? choiceFx;
12165
12405
  return FAIL;
@@ -12242,7 +12482,7 @@ function assemble(t2, prog, cfg) {
12242
12482
  if (next !== void 0) {
12243
12483
  return next(input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best);
12244
12484
  }
12245
- if (best === pos) acc = through(total, prev, acc);
12485
+ if (best === pos && prev !== 0) acc = through(total, prev, acc);
12246
12486
  ctx._fe = pos;
12247
12487
  ctx._fx = acc ?? choiceFx;
12248
12488
  return FAIL;
@@ -12321,6 +12561,13 @@ function assemble(t2, prog, cfg) {
12321
12561
  if (done !== void 0) return done;
12322
12562
  const flight = inFlight.get(ip);
12323
12563
  if (flight !== void 0) return flight.fwd;
12564
+ const selected = HYBRID?.byIp[ip];
12565
+ if (selected !== void 0) {
12566
+ const piece2 = hybridPiece(selected);
12567
+ memo.set(ip, piece2);
12568
+ reached.add(ip);
12569
+ return piece2;
12570
+ }
12324
12571
  let target;
12325
12572
  const fwd = (input, pos, ctx) => target(input, pos, ctx);
12326
12573
  const holder = { fwd, set: (p) => {
@@ -12328,7 +12575,7 @@ function assemble(t2, prog, cfg) {
12328
12575
  } };
12329
12576
  inFlight.set(ip, holder);
12330
12577
  const op = code[ip];
12331
- 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);
12578
+ const piece = (op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[ip + 3] === 0) && code[ip + 1] >= 0 && closureLabels.at(ip).tri === code[ip + 1] ? link(code[ip + 2]) : countedPiece(lower(ip), ip);
12332
12579
  inFlight.delete(ip);
12333
12580
  holder.set(piece);
12334
12581
  memo.set(ip, piece);
@@ -12865,7 +13112,12 @@ function assemble(t2, prog, cfg) {
12865
13112
  }
12866
13113
  const child = link(code[ip + 1]);
12867
13114
  const xf = fx[code[ip + 2]];
13115
+ const gate = lookaheadClass(code[ip + 1]);
12868
13116
  return (input, pos, ctx) => {
13117
+ if (gate !== null && !classHas2(gate, lead(input, pos))) {
13118
+ EC.e = pos;
13119
+ return null;
13120
+ }
12869
13121
  const need = markCst(ctx);
12870
13122
  const mRaw = MRAW;
12871
13123
  const mTl = MTL;
@@ -12888,7 +13140,13 @@ function assemble(t2, prog, cfg) {
12888
13140
  case OP_PEEK: {
12889
13141
  const child = link(code[ip + 1]);
12890
13142
  const xf = fx[code[ip + 2]];
13143
+ const gate = lookaheadClass(code[ip + 1]);
12891
13144
  return (input, pos, ctx) => {
13145
+ if (gate !== null && !classHas2(gate, lead(input, pos))) {
13146
+ ctx._fe = pos;
13147
+ ctx._fx = xf;
13148
+ return FAIL;
13149
+ }
12892
13150
  const need = markCst(ctx);
12893
13151
  const mRaw = MRAW;
12894
13152
  const mTl = MTL;
@@ -12910,7 +13168,12 @@ function assemble(t2, prog, cfg) {
12910
13168
  }
12911
13169
  case OP_OPT: {
12912
13170
  const child = link(code[ip + 1]);
13171
+ const gate = lookaheadClass(code[ip + 1]);
12913
13172
  return (input, pos, ctx) => {
13173
+ if (gate !== null && !classHas2(gate, lead(input, pos))) {
13174
+ EC.e = pos;
13175
+ return null;
13176
+ }
12914
13177
  const need = markCst(ctx);
12915
13178
  const mRaw = MRAW;
12916
13179
  const mTl = MTL;
@@ -13717,6 +13980,11 @@ function assemble(t2, prog, cfg) {
13717
13980
  }
13718
13981
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
13719
13982
  }
13983
+ if (prev === 0) {
13984
+ ctx._fe = pos;
13985
+ ctx._fx = choiceFx;
13986
+ return FAIL;
13987
+ }
13720
13988
  if (best === pos && prev < 1) acc = accSet(e0, acc);
13721
13989
  if (best === pos && prev < 2) acc = accSet(e1, acc);
13722
13990
  if (best === pos && n === 3 && prev < 3) acc = accSet(e2, acc);
@@ -14025,7 +14293,7 @@ function assemble(t2, prog, cfg) {
14025
14293
  return (input, pos, ctx) => {
14026
14294
  if (!pred(ctx.state)) {
14027
14295
  ctx._fc = false;
14028
- ctx._fe = pos;
14296
+ ctx._fe = -1;
14029
14297
  ctx._fx = xf;
14030
14298
  return FAIL;
14031
14299
  }
@@ -14431,7 +14699,7 @@ function assemble(t2, prog, cfg) {
14431
14699
  if (v === FAIL) return FAIL;
14432
14700
  const end = EC.e;
14433
14701
  const span = tracked ? spanLines(ctx, pos, end) : { start: pos, end };
14434
- const st = readsState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
14702
+ const st = readsState ? ctx.state : void 0;
14435
14703
  let nd;
14436
14704
  if (unwrap && kids.length === 1) {
14437
14705
  nd = unwrapChild(kids[0]);
@@ -14444,10 +14712,10 @@ function assemble(t2, prog, cfg) {
14444
14712
  ) {
14445
14713
  nd = kids[0];
14446
14714
  } else if (proj >= 0) {
14447
- 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);
14715
+ nd = hostCst && host !== void 0 ? host(type, kids, fieldMap, span, rawKids, tlog, ctx.state, tags) : projectChild(kids, proj, type);
14448
14716
  } else if (build !== void 0) {
14449
14717
  if (hostCst && host !== void 0) {
14450
- nd = host(type, kids, fieldMap, span, rawKids, tlog, readsState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0, tags);
14718
+ nd = host(type, kids, fieldMap, span, rawKids, tlog, ctx.state, tags);
14451
14719
  } else {
14452
14720
  nd = build(kids, fieldMap, span, rawKids, captureWide ? tlog : EMPTY_TL2, st);
14453
14721
  }
@@ -14498,9 +14766,7 @@ function assemble(t2, prog, cfg) {
14498
14766
  let emitRefusal;
14499
14767
  let emitReached;
14500
14768
  {
14501
- const extraIps = [];
14502
- for (const s of prog.scans ?? []) for (const r of scanRefs(s)) extraIps.push(r[0]);
14503
- for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
14769
+ const extraIps = assemblyExtraIps(prog);
14504
14770
  const roots = [...Object.values(prog.rules), ...extraIps];
14505
14771
  for (const ip of reachableSites(code, roots)) {
14506
14772
  if (code[ip] === OP_DISPATCH) {
@@ -14593,9 +14859,11 @@ function assemble(t2, prog, cfg) {
14593
14859
  adjacencyHolds,
14594
14860
  t2.lexPrograms,
14595
14861
  LEAD,
14596
- triviaFieldCapture
14862
+ triviaFieldCapture,
14863
+ skipDeferredTrivia
14597
14864
  );
14598
14865
  emitReached = new Set(pre.reached);
14866
+ if (emitted.ext !== void 0) HYBRID = emitted;
14599
14867
  }
14600
14868
  try {
14601
14869
  if (emitted !== void 0) throw new ServedByBuild();
@@ -14677,7 +14945,8 @@ function assemble(t2, prog, cfg) {
14677
14945
  adjacencyHolds,
14678
14946
  t2.lexPrograms,
14679
14947
  LEAD,
14680
- triviaFieldCapture
14948
+ triviaFieldCapture,
14949
+ skipDeferredTrivia
14681
14950
  );
14682
14951
  emitReached = em.reached;
14683
14952
  } catch (e) {
@@ -14688,7 +14957,7 @@ function assemble(t2, prog, cfg) {
14688
14957
  }
14689
14958
  function pieceAt(ip) {
14690
14959
  const em = emitted;
14691
- if (em !== void 0) {
14960
+ if (em !== void 0 && HYBRID === void 0) {
14692
14961
  const p = em.byIp[ip];
14693
14962
  if (p === void 0) throw new Error(`table emitter: no emitted body for site ${ip}`);
14694
14963
  return p;
@@ -14718,6 +14987,37 @@ function assemble(t2, prog, cfg) {
14718
14987
  }
14719
14988
  const scans = scansArr;
14720
14989
  const scanSkip = (prog.scanSkip ?? []).map((set) => set.map((r) => subtreeComb(r)));
14990
+ if (HYBRID !== void 0) {
14991
+ const em = HYBRID;
14992
+ em.bind(
14993
+ (s) => {
14994
+ const saved = SCAN;
14995
+ SCAN = s;
14996
+ return saved;
14997
+ },
14998
+ em.ext.map((ip) => link(ip))
14999
+ );
15000
+ const pieces2 = {};
15001
+ for (const [name, entryIp] of Object.entries(prog.rules)) {
15002
+ pieces2[name] = em.pieces[name] ?? link(entryIp);
15003
+ }
15004
+ for (const ip of emitReached) reached.add(ip);
15005
+ return {
15006
+ pieces: pieces2,
15007
+ end: () => EC.e,
15008
+ begin: (ctx) => {
15009
+ begin(ctx);
15010
+ em.begin(ctx);
15011
+ },
15012
+ finish: () => {
15013
+ em.finish();
15014
+ finish();
15015
+ },
15016
+ scanSkip,
15017
+ reached,
15018
+ emitRefusal: void 0
15019
+ };
15020
+ }
14721
15021
  if (emitted !== void 0) {
14722
15022
  const em = emitted;
14723
15023
  return {
@@ -14753,6 +15053,15 @@ function assemble(t2, prog, cfg) {
14753
15053
  }
14754
15054
  return { pieces, end: () => EC.e, begin, finish, scanSkip, reached, emitRefusal };
14755
15055
  }
15056
+ var SITE_COUNTS;
15057
+ function countedPiece(piece, ip) {
15058
+ const counts = SITE_COUNTS;
15059
+ if (counts === void 0) return piece;
15060
+ return (input, pos, ctx) => {
15061
+ counts[ip]++;
15062
+ return piece(input, pos, ctx);
15063
+ };
15064
+ }
14756
15065
  var AssemblyCache = class {
14757
15066
  t;
14758
15067
  prog;
@@ -14955,9 +15264,7 @@ function emitDispatchSpec(d) {
14955
15264
  function emitAssemblies(prog, cfgs) {
14956
15265
  if (cfgs.length === 0) return ["a:[],"];
14957
15266
  const t2 = resolveTable(prog);
14958
- const extraIps = [];
14959
- for (const s of prog.scans ?? []) for (const r of scanRefs(s)) extraIps.push(r[0]);
14960
- for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
15267
+ const extraIps = assemblyExtraIps(prog);
14961
15268
  const out = [];
14962
15269
  const seen = /* @__PURE__ */ new Set();
14963
15270
  for (const cfg of cfgs) {
@@ -14966,7 +15273,7 @@ function emitAssemblies(prog, cfgs) {
14966
15273
  seen.add(key);
14967
15274
  let em;
14968
15275
  try {
14969
- em = emitAssemblySource(t2, prog, cfg, extraIps, true);
15276
+ em = emitAssemblySource(t2, prog, cfg, extraIps, true, cfg.select);
14970
15277
  } catch (e) {
14971
15278
  if (e instanceof Unemittable) continue;
14972
15279
  throw e;