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/index.js CHANGED
@@ -726,6 +726,7 @@ function literalCodePoints(frag) {
726
726
  if (ch2 === "\\") {
727
727
  const e = frag[i + 1];
728
728
  if (e === void 0) return null;
729
+ if (!(e in CLASS_ESCAPES) && /\w/.test(e)) return null;
729
730
  out.push(e in CLASS_ESCAPES ? CLASS_ESCAPES[e] : e.codePointAt(0));
730
731
  i += 2;
731
732
  continue;
@@ -1323,6 +1324,7 @@ function createParseContext() {
1323
1324
  _rootTriviaKindIndex: void 0,
1324
1325
  _rootTriviaStrictScopes: void 0,
1325
1326
  _rootTriviaCapture: void 0,
1327
+ _gap: void 0,
1326
1328
  _cstTriviaLog: void 0,
1327
1329
  _fields: void 0,
1328
1330
  _cstBuf: void 0,
@@ -1805,7 +1807,10 @@ function labeledTriviaSpec(arms, minRepeats) {
1805
1807
  arms,
1806
1808
  minRepeats,
1807
1809
  visitor: commonLabeledTriviaVisitor({ arms, minRepeats }),
1808
- charArms: charArmsFor({ arms, minRepeats })
1810
+ charArms: charArmsFor({ arms, minRepeats }),
1811
+ rootKinds: void 0,
1812
+ rootLeaders: [],
1813
+ rootScan: null
1809
1814
  };
1810
1815
  }
1811
1816
  function matchArmAt(input, pos, arm, state) {
@@ -2265,8 +2270,50 @@ function loopScanner(arms) {
2265
2270
  function regexTriviaScanner(parser2) {
2266
2271
  const d = parser2._def.tag === "label" ? parser2._def.parser._def : parser2._def;
2267
2272
  if (d.tag !== "regex" || d.flags) return null;
2268
- const source = d.source;
2269
- return classRunSource(source) ?? altStarSource(source) ?? prefixRunSource(source) ?? delimitedSource(source);
2273
+ return sourceScanner(d.source);
2274
+ }
2275
+ function sourceScanner(source) {
2276
+ return classRunSource(source) ?? altStarSource(source) ?? prefixRunSource(source) ?? delimitedSource(source) ?? sharedPrefixAltSource(source);
2277
+ }
2278
+ function sharedPrefixAltSource(source) {
2279
+ const m = /^((?:\\.|[^\\[\]()*+?|^$.{}])+)\(\?:(.*)\)$/.exec(source);
2280
+ if (!m) return null;
2281
+ const alts = [];
2282
+ const body = m[2];
2283
+ let depth = 0;
2284
+ let start = 0;
2285
+ for (let i = 0; i < body.length; i++) {
2286
+ const c = body[i];
2287
+ if (c === "\\") {
2288
+ i++;
2289
+ continue;
2290
+ }
2291
+ if (c === "[") {
2292
+ while (i < body.length && body[i] !== "]") i += body[i] === "\\" ? 2 : 1;
2293
+ continue;
2294
+ }
2295
+ if (c === "(") depth++;
2296
+ else if (c === ")" && --depth < 0) return null;
2297
+ else if (c === "|" && depth === 0) {
2298
+ alts.push(body.slice(start, i));
2299
+ start = i + 1;
2300
+ }
2301
+ }
2302
+ if (depth !== 0 || alts.length === 0) return null;
2303
+ alts.push(body.slice(start));
2304
+ const scanners = [];
2305
+ for (const alt of alts) {
2306
+ const scanner = sourceScanner(m[1] + alt);
2307
+ if (scanner === null) return null;
2308
+ scanners.push(scanner);
2309
+ }
2310
+ return (input, cur) => {
2311
+ for (const scanner of scanners) {
2312
+ const end = scanner(input, cur);
2313
+ if (end > cur) return end;
2314
+ }
2315
+ return cur;
2316
+ };
2270
2317
  }
2271
2318
  function bmpString(cps) {
2272
2319
  if (!cps) return null;
@@ -4846,7 +4893,7 @@ function confirmedArityForDef(def) {
4846
4893
  severity: "warn",
4847
4894
  where: `node("${def.type ?? "<inferred>"}")`,
4848
4895
  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`,
4896
+ 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
4897
  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
4898
  });
4852
4899
  return null;
@@ -5003,7 +5050,7 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
5003
5050
  }
5004
5051
  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
5052
  const capturesTrivia = captureTrivia || (build ? buildReadsTrivia(def) : project === void 0);
5006
- const clonesState = build ? buildReadsState(def) : project === void 0;
5053
+ const readsState = build ? buildReadsState(def) : project === void 0;
5007
5054
  const hasOwnFields = parserHasOwnFields(combinator);
5008
5055
  const capturesFields = hasOwnFields && (build ? buildReadsFields(def) : project === void 0);
5009
5056
  const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
@@ -5044,12 +5091,11 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
5044
5091
  ctx._triviaCaptureMask = savedMask;
5045
5092
  const { children: children2, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
5046
5093
  if (!r.ok) return r;
5047
- const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
5094
+ const st = readsState ? ctx.state : void 0;
5048
5095
  const nodeType = def.type ?? missingInferredType();
5049
5096
  const cstOutput2 = cstOutputHost(ctx.build);
5050
5097
  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 };
5098
+ 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
5099
  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
5100
  if (saved.buf !== void 0 || saved.ch !== void 0) {
5055
5101
  pushCstChild(ctx, built, rawEntry2);
@@ -5757,6 +5803,12 @@ function scanRefs(s) {
5757
5803
  refs.push(...s.skip);
5758
5804
  return refs;
5759
5805
  }
5806
+ function assemblyExtraIps(prog) {
5807
+ const ips = [];
5808
+ for (const s of prog.scans ?? []) for (const r of scanRefs(s)) ips.push(r[0]);
5809
+ for (const set of prog.scanSkip ?? []) for (const r of set) ips.push(r[0]);
5810
+ return ips;
5811
+ }
5760
5812
  function expandCompact(p) {
5761
5813
  if ("code" in p) return p;
5762
5814
  return ownTableProgram({
@@ -5887,6 +5939,11 @@ function classHas2(cls, code) {
5887
5939
  for (let i = 0; i < hi.length; i += 2) if (code >= hi[i] && code <= hi[i + 1]) return true;
5888
5940
  return false;
5889
5941
  }
5942
+ function dispatchIsExclusive(arms, cc) {
5943
+ const resolved = [];
5944
+ for (const ci of arms) if (ci >= 0) resolved[ci] = resolveClass(cc[ci]);
5945
+ return resolveDispatch(arms, resolved).exclusive;
5946
+ }
5890
5947
  function resolveDispatch(arms, cc) {
5891
5948
  const ascii = new Uint8Array(128);
5892
5949
  const hi = [];
@@ -7846,6 +7903,33 @@ var Encoder = class {
7846
7903
  return childrenOf2(def);
7847
7904
  }
7848
7905
  }
7906
+ /**
7907
+ * THE FIRST-CHARACTER GATE OF AN `optional`, `not` OR `peek` CHILD.
7908
+ *
7909
+ * A non-nullable child cannot match at a character outside its first set, so
7910
+ * the wrapper's outcome there is already decided: `optional` yields `null`,
7911
+ * `not` succeeds, `peek` fails with its own set. The interpreter's `optional`
7912
+ * makes that test itself (`repeat.ts` `startsFirstSet`); the table entered the
7913
+ * child — a rollback mark, the call, the child's own failure — to learn it.
7914
+ *
7915
+ * The gate is an `OP_GATE` row around the child, so every engine runs it
7916
+ * unchanged, a probe or tolerant parse forwards through it as for a node's
7917
+ * gate, and the wrapper's row keeps its layout. The engines test the class
7918
+ * before taking the wrapper's mark. The first set is resolved through
7919
+ * `winners`, the analysis a choice arm's gate uses, so a composed rule's set
7920
+ * is the merged one. A scalar `not` child stays bare: `scalarTerminalNotChild`
7921
+ * already reduces it to one recognizer call.
7922
+ */
7923
+ lookaheadGate(p, child) {
7924
+ const op = this.code[child];
7925
+ 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;
7926
+ const rr = this.refResolver();
7927
+ if (matchesEmpty(p, /* @__PURE__ */ new Set(), rr)) return child;
7928
+ const cls = this.charClass(firstSetOf(p, /* @__PURE__ */ new Set(), rr, this.activeTrivia));
7929
+ if (cls < 0) return child;
7930
+ const e = deriveExpected(p);
7931
+ return this.emit(OP_GATE, cls, child, this.expected(e.length > 0 ? e : [p._tag]));
7932
+ }
7849
7933
  /** A first set becomes a char class string, or −1 for `any`. */
7850
7934
  charClass(fs) {
7851
7935
  if (fs.kind !== "ranges" || fs.ranges.length === 0) return -1;
@@ -7857,12 +7941,19 @@ var Encoder = class {
7857
7941
  this.ccIndex.set(spec, i);
7858
7942
  return i;
7859
7943
  }
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;
7944
+ /**
7945
+ * The first set a node's or an attempt's fail-fast gate tests. A bare
7946
+ * cross-rule ref resolves through `winners` (a compose OVERRIDE may widen
7947
+ * it). Any other body keeps its construction-time `_meta.firstSet`, except
7948
+ * where that is `any`: under `compose()` a body that reaches a rule of
7949
+ * another piece is built before that rule exists, so its cached set is
7950
+ * `any` and the node got NO gate (jess's `CompoundSelector` was entered at
7951
+ * `{`, `Call` at `}`). The resolved set is the one a choice arm's gate uses,
7952
+ * over the final merged map.
7953
+ */
7954
+ gateFirstSet(p) {
7955
+ const cached = p._meta.firstSet;
7956
+ return p._def.tag === "lazy" || cached.kind === "any" ? firstSetOf(p, /* @__PURE__ */ new Set(), this.refResolver(), this.activeTrivia) : cached;
7866
7957
  }
7867
7958
  /**
7868
7959
  * Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
@@ -8167,6 +8258,12 @@ var Encoder = class {
8167
8258
  if (transactionalFirst[i] !== void 0) classes[i] = -1;
8168
8259
  }
8169
8260
  }
8261
+ if (d.gates.some((g) => g !== null && g !== void 0) && !dispatchIsExclusive(classes, this.cc)) {
8262
+ for (let k = 0; k < classes.length; k++) {
8263
+ const gate2 = d.gates[order[k]];
8264
+ if (gate2 !== null && gate2 !== void 0) classes[k] = -1;
8265
+ }
8266
+ }
8170
8267
  const dispIdx = this.disp.length;
8171
8268
  this.disp.push(classes);
8172
8269
  let rollbackMask = kids.length > 31 ? -1 : 0;
@@ -8196,7 +8293,7 @@ var Encoder = class {
8196
8293
  case "oneOrMore": {
8197
8294
  const child = this.node(d.parser).ip;
8198
8295
  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));
8296
+ const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.charClass(firstSetOf(d.parser, /* @__PURE__ */ new Set(), rr, this.activeTrivia));
8200
8297
  const op = d.valueUnused ? OP_REPV : OP_REP;
8201
8298
  const min = d.tag === "many" ? 0 : d.min;
8202
8299
  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 +8317,7 @@ var Encoder = class {
8220
8317
  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
8318
  }
8222
8319
  case "optional": {
8223
- const head = this.emit(OP_OPT, this.node(d.parser).ip);
8320
+ const head = this.emit(OP_OPT, this.lookaheadGate(d.parser, this.node(d.parser).ip));
8224
8321
  if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(head);
8225
8322
  return head;
8226
8323
  }
@@ -8268,8 +8365,8 @@ var Encoder = class {
8268
8365
  // every CST node, so this is load-bearing, not reflection trivia.
8269
8366
  d.tags === void 0 ? -1 : this.constant(d.tags)
8270
8367
  );
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;
8368
+ if (matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return body;
8369
+ const fs = this.gateFirstSet(d.parser);
8273
8370
  if (fs.kind === "any") return body;
8274
8371
  const cls = this.charClass(fs);
8275
8372
  if (cls < 0) return body;
@@ -8361,7 +8458,7 @@ var Encoder = class {
8361
8458
  // other engine reported `['not(literal)']`. It hid because `expected` is a
8362
8459
  // TOP-LEVEL field on `RunResult` and is NOT part of the identity digest.
8363
8460
  case "not":
8364
- return this.emit(OP_NOT, this.node(d.parser).ip, this.expected(assertionFailureExpected(false, d.parser._tag)));
8461
+ return this.emit(OP_NOT, this.lookaheadGate(d.parser, this.node(d.parser).ip), this.expected(assertionFailureExpected(false, d.parser._tag)));
8365
8462
  case "guard":
8366
8463
  return this.emit(OP_GUARD, this.fn(d.predicate, d.predSrc ?? null), this.expected(["gate"]));
8367
8464
  case "adjacency":
@@ -8382,14 +8479,14 @@ var Encoder = class {
8382
8479
  return this.emit(OP_WITHCTX, this.constant(d.extra), this.node(d.parser).ip);
8383
8480
  }
8384
8481
  case "peek":
8385
- return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected(assertionFailureExpected(true, d.parser._tag)));
8482
+ return this.emit(OP_PEEK, this.lookaheadGate(d.parser, this.node(d.parser).ip), this.expected(assertionFailureExpected(true, d.parser._tag)));
8386
8483
  // A TRANSACTION IS A ROW. See `OP_ATTEMPT` for why the transparent
8387
8484
  // lowering was correct only for a choice arm.
8388
8485
  case "attempt": {
8389
8486
  const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip, d.contain === true ? 1 : 0);
8390
8487
  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;
8488
+ const fs = this.gateFirstSet(d.parser);
8489
+ if (fs.kind === "any" || matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return inner;
8393
8490
  const cls = this.charClass(fs);
8394
8491
  if (cls < 0) return inner;
8395
8492
  const e = deriveExpected(d.parser);
@@ -10117,7 +10214,10 @@ var EMITTED_PARAMS = [
10117
10214
  // Appended for trivia-attributing fields (`field(…, { leadingTrivia })`);
10118
10215
  // old factories ignore them.
10119
10216
  "LEAD",
10120
- "triviaFieldCapture"
10217
+ "triviaFieldCapture",
10218
+ // Appended for the deferred-commit trivia skip (`trivia-gap.ts`); old
10219
+ // factories ignore it.
10220
+ "skipDeferredTrivia"
10121
10221
  ];
10122
10222
  var RUNTIME_PRELUDE = `
10123
10223
  let _pfScan=null
@@ -10138,7 +10238,7 @@ function _skipTrivia(input,cur,ctx){
10138
10238
  const s=_pfScan
10139
10239
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
10140
10240
  if(s!==null)return skipTriviaScanned(s,input,cur,ctx)
10141
- if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
10241
+ if(needsDeferredTriviaCommit(ctx))return skipDeferredTrivia(input,cur,ctx)
10142
10242
  return advanceTrivia(input,cur,ctx)
10143
10243
  }
10144
10244
  function _pushLeaf(ctx,value,s,e){pushCstLeaf(ctx,{_tag:'leaf',value,span:{start:s,end:e}})}
@@ -10345,7 +10445,7 @@ function rebuildPools(cc, fx, disp, plan) {
10345
10445
  })
10346
10446
  };
10347
10447
  }
10348
- function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
10448
+ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, select) {
10349
10449
  const { code, k, fx, disp, dsp, triviaLabelled } = t;
10350
10450
  const swapLegal = !cfg.trackLines;
10351
10451
  const hostCst = cfg.hostCst;
@@ -10444,6 +10544,8 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
10444
10544
  };
10445
10545
  const bodies = [];
10446
10546
  const byIp = /* @__PURE__ */ new Map();
10547
+ const externals = [];
10548
+ const siteBytes = /* @__PURE__ */ new Map();
10447
10549
  const reached = /* @__PURE__ */ new Set();
10448
10550
  const prelude = [];
10449
10551
  const skipDefs = [];
@@ -10579,6 +10681,18 @@ return 1
10579
10681
  tokenDecisionRefs.set(dispatchIp, made);
10580
10682
  return made;
10581
10683
  }
10684
+ function gateMissTest(gip) {
10685
+ const resolved = t.cc[code[gip + 1]];
10686
+ const ci = classes.push([resolved]) - 1;
10687
+ classPlan.push([code[gip + 1]]);
10688
+ const cls = hoist("cl", `CLS[${ci}][0]`);
10689
+ return isAsciiOnlyClass(resolved) ? `${cls}.ascii[input.charCodeAt(pos)]!==1` : `!classHas(${cls},lead(input,pos))`;
10690
+ }
10691
+ function lookaheadMiss(child, miss) {
10692
+ if (code[child] !== OP_GATE || cfg.tolerant || cfg.probe) return "";
10693
+ return `if(${gateMissTest(child)}){${miss}}
10694
+ `;
10695
+ }
10582
10696
  function skipFor(l) {
10583
10697
  if (l.tri < 0) return "_skipTrivia";
10584
10698
  const ki = l.tri;
@@ -10589,8 +10703,8 @@ return 1
10589
10703
  const nm = `_sk${skipPool.size}`;
10590
10704
  skipPool.set(key, nm);
10591
10705
  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))
10706
+ skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return skipDeferredTrivia(input,cur,ctx)}` : `function ${nm}(input,cur,ctx){
10707
+ if(needsDeferredTriviaCommit(ctx))return skipDeferredTrivia(input,cur,ctx)
10594
10708
  return advanceTrivia(input,cur,ctx)}`);
10595
10709
  return nm;
10596
10710
  }
@@ -10635,9 +10749,17 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
10635
10749
  const target = resolveAlias(ip);
10636
10750
  const done = byIp.get(target);
10637
10751
  if (done !== void 0) return done;
10752
+ if (select !== void 0 && !select.has(target)) {
10753
+ const ext = `_px${target}`;
10754
+ byIp.set(target, ext);
10755
+ externals.push(target);
10756
+ return ext;
10757
+ }
10638
10758
  const fname = `_pf${target}`;
10639
10759
  byIp.set(target, fname);
10640
- bodies.push(lower(target, fname));
10760
+ const body = lower(target, fname);
10761
+ siteBytes.set(target, body.length);
10762
+ bodies.push(body);
10641
10763
  return fname;
10642
10764
  }
10643
10765
  function resolveAlias(ip) {
@@ -10777,14 +10899,28 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
10777
10899
  return `${head}EC.e=pos;return ''}`;
10778
10900
  case OP_GATE: {
10779
10901
  const child = link(code[ip + 2]);
10780
- const resolved = t.cc[code[ip + 1]];
10781
- const ci = classes.push([resolved]) - 1;
10782
- classPlan.push([code[ip + 1]]);
10783
- const cls = hoist("cl", `CLS[${ci}][0]`);
10784
10902
  const xf = fxRef(code[ip + 3]);
10785
10903
  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}
10904
+ if(${gateMissTest(ip)}){ctx._fe=pos;ctx._fx=${xf};return FAIL}
10787
10905
  return ${child}(input,pos,ctx)
10906
+ }`;
10907
+ }
10908
+ case OP_ARMGATE: {
10909
+ const pred = fnRef(code[ip + 1]);
10910
+ const child = link(code[ip + 2]);
10911
+ const xf = fxRef(code[ip + 3]);
10912
+ return `${head}
10913
+ if(!${pred}(ctx.state)){ctx._fc=false;ctx._fe=-1;ctx._fx=${xf};return FAIL}
10914
+ return ${child}(input,pos,ctx)
10915
+ }`;
10916
+ }
10917
+ case OP_WITHCTX: {
10918
+ const ki = code[ip + 1];
10919
+ const child = link(code[ip + 2]);
10920
+ return `${head}
10921
+ const saved=ctx.state
10922
+ ctx.state=${ki < 0 ? `${fnRef(~ki)}(saved)` : kRef(ki)}
10923
+ try{return ${child}(input,pos,ctx)}finally{ctx.state=saved}
10788
10924
  }`;
10789
10925
  }
10790
10926
  case OP_XFORM: {
@@ -11040,7 +11176,7 @@ return FAIL
11040
11176
  const xf = fxRef(code[ip + 2]);
11041
11177
  const p = tmp();
11042
11178
  return `${head}
11043
- ${emitMark(p, L.buf, L.raw, sinks)}
11179
+ ${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${emitMark(p, L.buf, L.raw, sinks)}
11044
11180
  const v=${child}(input,pos,ctx)
11045
11181
  ${emitRollback(p, L.buf, L.raw, sinks)}
11046
11182
  if(v===FAIL){EC.e=pos;return null}
@@ -11054,7 +11190,7 @@ return FAIL
11054
11190
  const xf = fxRef(code[ip + 2]);
11055
11191
  const p = tmp();
11056
11192
  return `${head}
11057
- ${emitMark(p, L.buf, L.raw, sinks)}
11193
+ ${lookaheadMiss(code[ip + 1], `ctx._fe=pos;ctx._fx=${xf};return FAIL`)}${emitMark(p, L.buf, L.raw, sinks)}
11058
11194
  const v=${child}(input,pos,ctx)
11059
11195
  ${emitRollback(p, L.buf, L.raw, sinks)}
11060
11196
  if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
@@ -11067,7 +11203,7 @@ return null
11067
11203
  const clean = !REC2 && failureRollbackClean(prog, ip);
11068
11204
  const p = tmp();
11069
11205
  return `${head}
11070
- ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
11206
+ ${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
11071
11207
  ctx._fc=false
11072
11208
  const v=${child}(input,pos,ctx)
11073
11209
  if(v===FAIL){
@@ -11148,7 +11284,7 @@ return v
11148
11284
  const asc = hoist("as", `DISP[${di}].ascii`);
11149
11285
  const hiArr = table.hi;
11150
11286
  const armSwitch = arms.map((a, i) => `case ${i}:v=${a}(input,pos,ctx);break`).join("\n");
11151
- const directAscii = staticBuild && table.hi.length === 0;
11287
+ const directAscii = table.hi.length === 0;
11152
11288
  return `${head}
11153
11289
  const c=${directAscii ? "input.charCodeAt(pos)" : "lead(input,pos)"}
11154
11290
  let arm=-1
@@ -11175,7 +11311,7 @@ return FAIL
11175
11311
  const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
11176
11312
  const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
11177
11313
  const maskable = n <= 32;
11178
- const directAsciiMask = staticBuild && maskable && gates.every(isAsciiOnlyClass);
11314
+ const directAsciiMask = maskable && gates.every(isAsciiOnlyClass);
11179
11315
  const gateRefs = directAsciiMask ? [] : Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
11180
11316
  const tokenCandidate = tokenChoiceCandidates.get(ip);
11181
11317
  const pretests = Array.from({ length: n }, (_, i) => {
@@ -11217,7 +11353,7 @@ return FAIL
11217
11353
  if (choiceCannotCommit(prog, ip) && !startFailureExact) {
11218
11354
  const deepAt = Array.from({ length: n }, () => tmp());
11219
11355
  const deepFx = Array.from({ length: n }, () => tmp());
11220
- const remember = (i, at, expectedSet) => `${deepAt[i]}=${at};${deepFx[i]}=${expectedSet}`;
11356
+ const remember2 = (i, at, expectedSet) => `${deepAt[i]}=${at};${deepFx[i]}=${expectedSet}`;
11221
11357
  const lazyArms = (ascii) => arms.map((arm, i) => {
11222
11358
  const pretest = pretests[i];
11223
11359
  const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
@@ -11229,13 +11365,13 @@ return FAIL
11229
11365
  if(${decision}===0){
11230
11366
  ctx._fc=false
11231
11367
  {const at=_pfTokEnd
11232
- ${remember(i, "at", pretest.token.expected)}}
11368
+ ${remember2(i, "at", pretest.token.expected)}}
11233
11369
  }`;
11234
11370
  const sequenceMiss = pretest?.sequence === void 0 ? "" : `
11235
11371
  else if(${ascii ? `(bits&${1 << i})!==0&&` : ""}${decision}<0){
11236
11372
  ctx._fc=false
11237
11373
  {const at=_pfSeqEnd
11238
- ${remember(i, "at", pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("") + pretest.sequence.expected.at(-1))}}
11374
+ ${remember2(i, "at", pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("") + pretest.sequence.expected.at(-1))}}
11239
11375
  }`;
11240
11376
  return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
11241
11377
  `}if(${gate2}){
@@ -11243,7 +11379,7 @@ ctx._fc=false
11243
11379
  {const v=${arm}(input,pos,ctx)
11244
11380
  if(v!==FAIL)return v}
11245
11381
  {const at=ctx._fe??pos
11246
- ${remember(i, "at", "ctx._fx")}}
11382
+ ${remember2(i, "at", "ctx._fx")}}
11247
11383
  ${rollbackFor(i)}
11248
11384
  }${routeMiss}${sequenceMiss}`;
11249
11385
  }).join("\n");
@@ -11356,7 +11492,7 @@ const bits=${maskName}[${directAsciiMask ? "c" : "c<0?128:c"}]
11356
11492
  if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
11357
11493
  ${startFailureExact ? "" : "let prev=0"}
11358
11494
  ${maskArms}
11359
- ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${n},prev,acc)`}
11495
+ ${startFailureExact ? "" : `if(best===pos&&prev!==0)acc=${catchName}(${n},prev,acc)`}
11360
11496
  ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
11361
11497
  return FAIL
11362
11498
  }
@@ -11455,7 +11591,7 @@ return [key,v]
11455
11591
  const ci = classes.push([resolved]) - 1;
11456
11592
  classPlan.push([itemClassIndex]);
11457
11593
  itemCls = hoist("ri", `CLS[${ci}][0]`);
11458
- itemAscii = staticBuild && isAsciiOnlyClass(resolved);
11594
+ itemAscii = isAsciiOnlyClass(resolved);
11459
11595
  }
11460
11596
  }
11461
11597
  const itemMiss = (at) => itemAscii ? `${itemCls}.ascii[input.charCodeAt(${at})]!==1` : `!classHas(${itemCls},lead(input,${at}))`;
@@ -11681,7 +11817,7 @@ return nd
11681
11817
  const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
11682
11818
  const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
11683
11819
  const ty = q(type);
11684
- const stArg = readsState ? "st" : "(ctx.state!==undefined?Object.assign({},ctx.state):undefined)";
11820
+ const stArg = "ctx.state";
11685
11821
  const hostCall = `_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,${stArg},${tags})`;
11686
11822
  let value;
11687
11823
  if (proj >= 0) {
@@ -11742,7 +11878,7 @@ ctx.captureTrivia=sCap
11742
11878
  if(v===FAIL)return FAIL
11743
11879
  const end=EC.e
11744
11880
  const span=${tracked ? "spanLines(ctx,pos,end)" : "{start:pos,end}"}
11745
- const st=${readsState ? "(ctx.state!==undefined?Object.assign({},ctx.state):undefined)" : "undefined"}
11881
+ const st=${readsState ? "ctx.state" : "undefined"}
11746
11882
  let nd
11747
11883
  ${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
11884
  else ` : ""}{${value}}
@@ -11755,21 +11891,51 @@ return nd
11755
11891
  throw new Unemittable(`OP_${OP_NAMES[op] ?? String(op)}`);
11756
11892
  }
11757
11893
  }
11894
+ const served = (ip) => select === void 0 || select.has(resolveAlias(ip));
11758
11895
  const ruleEntries = [];
11759
11896
  for (const [rname, entryIp] of Object.entries(prog.rules)) {
11897
+ if (!served(entryIp)) continue;
11760
11898
  const target = link(entryIp);
11761
11899
  const rn = `_r_${rname.replace(/[^A-Za-z0-9_$]/g, "_")}`;
11762
11900
  bodies.push(`const ${rn}=${target}`);
11763
11901
  ruleEntries.push(`${q(rname)}:${rn}`);
11764
11902
  }
11765
11903
  const extra = [];
11766
- for (const ip of extraIps) extra.push(`${ip}:${link(ip)}`);
11904
+ const exported = /* @__PURE__ */ new Set();
11905
+ for (const ip of extraIps) {
11906
+ if (!served(ip)) continue;
11907
+ exported.add(ip);
11908
+ extra.push(`${ip}:${link(ip)}`);
11909
+ }
11910
+ if (select !== void 0) {
11911
+ const kids = [];
11912
+ for (const ip of reachable) {
11913
+ if (select.has(resolveAlias(ip))) continue;
11914
+ kids.length = 0;
11915
+ childSlots(code, ip, kids);
11916
+ for (const kid of kids) {
11917
+ const target = resolveAlias(kid);
11918
+ if (!select.has(target) || exported.has(target)) continue;
11919
+ exported.add(target);
11920
+ extra.push(`${target}:${link(target)}`);
11921
+ }
11922
+ }
11923
+ }
11924
+ const hybrid = select === void 0 ? "" : `,
11925
+ ext:[${externals.join(",")}],
11926
+ bind:function(xs,ps){_xScan=xs
11927
+ ${externals.map((ip, i) => `_xp${ip}=ps[${i}]`).join("\n")}},
11928
+ scan:function(s){const o=_pfScan;_pfScan=s;return o}`;
11929
+ const externalDefs = select === void 0 ? "" : `let _xScan
11930
+ ${externals.map((ip) => `let _xp${ip}
11931
+ function _px${ip}(input,pos,ctx){const o=_xScan(_pfScan);const v=_xp${ip}(input,pos,ctx);_xScan(o);return v}`).join("\n")}
11932
+ `;
11767
11933
  const source = `${RUNTIME_PRELUDE}${needsNoRawPrelude ? NO_RAW_RUNTIME_PRELUDE : ""}
11768
11934
  ${prelude.join("\n")}
11769
11935
  ${skipDefs.join("\n")}
11770
11936
  ${choiceDefs.join("\n")}
11771
11937
  ${bodies.join("\n")}
11772
- function _begin(ctx){
11938
+ ${externalDefs}function _begin(ctx){
11773
11939
  const host=ctx.build
11774
11940
  if(_pfDepth>0)_pfFrames.push([_pfScan,_pfHost,EC.e])
11775
11941
  _pfDepth++
@@ -11796,7 +11962,7 @@ pieces:{${ruleEntries.join(",")}},
11796
11962
  byIp:{${extra.join(",")}},
11797
11963
  end:function(){return EC.e},
11798
11964
  begin:_begin,
11799
- finish:_finish
11965
+ finish:_finish${hybrid}
11800
11966
  }`;
11801
11967
  return {
11802
11968
  source,
@@ -11804,6 +11970,7 @@ finish:_finish
11804
11970
  masks,
11805
11971
  classes,
11806
11972
  armExpected,
11973
+ siteBytes,
11807
11974
  plan: { classes: classPlan, armExpected: armExpectedPlan, masks: maskPlan }
11808
11975
  };
11809
11976
  }
@@ -12234,6 +12401,70 @@ function escapeClassChar(ch2) {
12234
12401
  return ch2.replace(/[\\\]^-]/g, "\\$&");
12235
12402
  }
12236
12403
 
12404
+ // src/table/trivia-gap.ts
12405
+ function skipDeferredTrivia(input, cur, ctx) {
12406
+ const triviaP = ctx.trivia;
12407
+ const plain = ctx.trackLines !== true && ctx.captureTrivia !== true;
12408
+ const gap = ctx._gap;
12409
+ 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;
12410
+ const end = clearRunEnd(input, cur, ctx, triviaP, plain);
12411
+ if (end >= 0) {
12412
+ remember(cur, end, ctx, input, triviaP);
12413
+ return end;
12414
+ }
12415
+ const scan = scanTriviaCompact(input, cur, ctx);
12416
+ if (typeof scan !== "number") return commitTriviaScan(scan);
12417
+ if (plain) remember(cur, scan, ctx, input, triviaP);
12418
+ return scan;
12419
+ }
12420
+ function clearRunEnd(input, cur, ctx, triviaP, plain) {
12421
+ const rootKinds = ctx._rootTriviaKindIndex;
12422
+ const spec = triviaP?._meta.labeledTriviaSpec;
12423
+ if (!plain || triviaP === void 0 || spec == null || rootKinds === void 0 || ctx._triviaLog !== void 0) return -1;
12424
+ if (spec.rootKinds !== rootKinds) prime(spec, triviaP, rootKinds);
12425
+ const fast = spec.rootScan;
12426
+ if (fast === null) return -1;
12427
+ const end = fast(input, cur);
12428
+ return ctx._rootTriviaCapture === false || clearOf(spec.rootLeaders, input, cur, end) ? end : -1;
12429
+ }
12430
+ function remember(cur, end, ctx, input, triviaP) {
12431
+ const gap = ctx._gap;
12432
+ if (gap === void 0) {
12433
+ ctx._gap = { at: cur, end, input, of: triviaP, root: ctx._rootTriviaCapture, rootKinds: ctx._rootTriviaKindIndex, log: ctx._triviaLog, state: ctx.state };
12434
+ return;
12435
+ }
12436
+ gap.at = cur;
12437
+ gap.end = end;
12438
+ gap.input = input;
12439
+ gap.of = triviaP;
12440
+ gap.root = ctx._rootTriviaCapture;
12441
+ gap.rootKinds = ctx._rootTriviaKindIndex;
12442
+ gap.log = ctx._triviaLog;
12443
+ gap.state = ctx.state;
12444
+ }
12445
+ function prime(spec, triviaP, rootKinds) {
12446
+ const ranges = [];
12447
+ let bounded = true;
12448
+ for (const arm of spec.arms) {
12449
+ if (rootKinds[arm.label] === void 0) continue;
12450
+ const fs = arm.parser._meta.firstSet;
12451
+ if (fs.kind === "any") bounded = false;
12452
+ else if (fs.kind === "ranges") ranges.push(...fs.ranges);
12453
+ }
12454
+ const classified = triviaP._meta.triviaScanner;
12455
+ spec.rootKinds = rootKinds;
12456
+ spec.rootLeaders = ranges;
12457
+ spec.rootScan = !bounded ? null : classified === void 0 ? fastTriviaScanner(triviaP) : classified;
12458
+ }
12459
+ function clearOf(ranges, input, from, to) {
12460
+ for (let i = from; i < to; i++) {
12461
+ const c = input.charCodeAt(i);
12462
+ if (c >= 55296 && c <= 57343) return false;
12463
+ for (const r of ranges) if (c >= r.lo && c <= r.hi) return false;
12464
+ }
12465
+ return true;
12466
+ }
12467
+
12237
12468
  // src/table/run-support.ts
12238
12469
  function lineCol(ctx, offset) {
12239
12470
  const starts = ctx._lineStarts ?? [0];
@@ -12443,6 +12674,9 @@ function assemble(t, prog, cfg) {
12443
12674
  const EC = newEndCell();
12444
12675
  const scalarRecognizers = [];
12445
12676
  const rawScalarSpecs = /* @__PURE__ */ new Set();
12677
+ function lookaheadClass(child) {
12678
+ return code[child] === OP_GATE && !cfg.tolerant && !cfg.probe ? cc[code[child + 1]] : null;
12679
+ }
12446
12680
  function scalarFor(child) {
12447
12681
  const spec = code[child + 1];
12448
12682
  let recognize = scalarRecognizers[spec];
@@ -12452,15 +12686,23 @@ function assemble(t, prog, cfg) {
12452
12686
  }
12453
12687
  return recognize;
12454
12688
  }
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]);
12689
+ const labelExtraIps = assemblyExtraIps(prog);
12458
12690
  const closureLabels = computeSiteLabels(
12459
12691
  code,
12460
12692
  [...Object.values(prog.rules), ...labelExtraIps],
12461
12693
  hostCst
12462
12694
  );
12463
12695
  let SCAN = null;
12696
+ let HYBRID;
12697
+ function hybridPiece(piece) {
12698
+ const setScan = HYBRID.scan;
12699
+ return (input, pos, ctx) => {
12700
+ const saved = setScan(SCAN);
12701
+ const value = piece(input, pos, ctx);
12702
+ setScan(saved);
12703
+ return value;
12704
+ };
12705
+ }
12464
12706
  const memo = /* @__PURE__ */ new Map();
12465
12707
  const reached = /* @__PURE__ */ new Set();
12466
12708
  function pushLeaf(ctx, value, s, e) {
@@ -12752,9 +12994,7 @@ function assemble(t, prog, cfg) {
12752
12994
  return s(input, cur);
12753
12995
  }
12754
12996
  if (s !== null) return skipTriviaScanned(s, input, cur, ctx);
12755
- if (needsDeferredTriviaCommit(ctx)) {
12756
- return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
12757
- }
12997
+ if (needsDeferredTriviaCommit(ctx)) return skipDeferredTrivia(input, cur, ctx);
12758
12998
  return advanceTrivia(input, cur, ctx);
12759
12999
  }
12760
13000
  let TERMV;
@@ -12924,7 +13164,7 @@ function assemble(t, prog, cfg) {
12924
13164
  if (next !== void 0) {
12925
13165
  return next(input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best);
12926
13166
  }
12927
- if (best === pos) acc = through(total, prev, acc);
13167
+ if (best === pos && prev !== 0) acc = through(total, prev, acc);
12928
13168
  ctx._fe = pos;
12929
13169
  ctx._fx = acc ?? choiceFx;
12930
13170
  return FAIL;
@@ -13007,7 +13247,7 @@ function assemble(t, prog, cfg) {
13007
13247
  if (next !== void 0) {
13008
13248
  return next(input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best);
13009
13249
  }
13010
- if (best === pos) acc = through(total, prev, acc);
13250
+ if (best === pos && prev !== 0) acc = through(total, prev, acc);
13011
13251
  ctx._fe = pos;
13012
13252
  ctx._fx = acc ?? choiceFx;
13013
13253
  return FAIL;
@@ -13086,6 +13326,13 @@ function assemble(t, prog, cfg) {
13086
13326
  if (done !== void 0) return done;
13087
13327
  const flight = inFlight.get(ip);
13088
13328
  if (flight !== void 0) return flight.fwd;
13329
+ const selected = HYBRID?.byIp[ip];
13330
+ if (selected !== void 0) {
13331
+ const piece2 = hybridPiece(selected);
13332
+ memo.set(ip, piece2);
13333
+ reached.add(ip);
13334
+ return piece2;
13335
+ }
13089
13336
  let target;
13090
13337
  const fwd = (input, pos, ctx) => target(input, pos, ctx);
13091
13338
  const holder = { fwd, set: (p) => {
@@ -13093,7 +13340,7 @@ function assemble(t, prog, cfg) {
13093
13340
  } };
13094
13341
  inFlight.set(ip, holder);
13095
13342
  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);
13343
+ 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);
13097
13344
  inFlight.delete(ip);
13098
13345
  holder.set(piece);
13099
13346
  memo.set(ip, piece);
@@ -13630,7 +13877,12 @@ function assemble(t, prog, cfg) {
13630
13877
  }
13631
13878
  const child = link(code[ip + 1]);
13632
13879
  const xf = fx[code[ip + 2]];
13880
+ const gate2 = lookaheadClass(code[ip + 1]);
13633
13881
  return (input, pos, ctx) => {
13882
+ if (gate2 !== null && !classHas2(gate2, lead(input, pos))) {
13883
+ EC.e = pos;
13884
+ return null;
13885
+ }
13634
13886
  const need = markCst(ctx);
13635
13887
  const mRaw = MRAW;
13636
13888
  const mTl = MTL;
@@ -13653,7 +13905,13 @@ function assemble(t, prog, cfg) {
13653
13905
  case OP_PEEK: {
13654
13906
  const child = link(code[ip + 1]);
13655
13907
  const xf = fx[code[ip + 2]];
13908
+ const gate2 = lookaheadClass(code[ip + 1]);
13656
13909
  return (input, pos, ctx) => {
13910
+ if (gate2 !== null && !classHas2(gate2, lead(input, pos))) {
13911
+ ctx._fe = pos;
13912
+ ctx._fx = xf;
13913
+ return FAIL;
13914
+ }
13657
13915
  const need = markCst(ctx);
13658
13916
  const mRaw = MRAW;
13659
13917
  const mTl = MTL;
@@ -13675,7 +13933,12 @@ function assemble(t, prog, cfg) {
13675
13933
  }
13676
13934
  case OP_OPT: {
13677
13935
  const child = link(code[ip + 1]);
13936
+ const gate2 = lookaheadClass(code[ip + 1]);
13678
13937
  return (input, pos, ctx) => {
13938
+ if (gate2 !== null && !classHas2(gate2, lead(input, pos))) {
13939
+ EC.e = pos;
13940
+ return null;
13941
+ }
13679
13942
  const need = markCst(ctx);
13680
13943
  const mRaw = MRAW;
13681
13944
  const mTl = MTL;
@@ -14482,6 +14745,11 @@ function assemble(t, prog, cfg) {
14482
14745
  }
14483
14746
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14484
14747
  }
14748
+ if (prev === 0) {
14749
+ ctx._fe = pos;
14750
+ ctx._fx = choiceFx;
14751
+ return FAIL;
14752
+ }
14485
14753
  if (best === pos && prev < 1) acc = accSet(e0, acc);
14486
14754
  if (best === pos && prev < 2) acc = accSet(e1, acc);
14487
14755
  if (best === pos && n === 3 && prev < 3) acc = accSet(e2, acc);
@@ -14790,7 +15058,7 @@ function assemble(t, prog, cfg) {
14790
15058
  return (input, pos, ctx) => {
14791
15059
  if (!pred(ctx.state)) {
14792
15060
  ctx._fc = false;
14793
- ctx._fe = pos;
15061
+ ctx._fe = -1;
14794
15062
  ctx._fx = xf;
14795
15063
  return FAIL;
14796
15064
  }
@@ -15196,7 +15464,7 @@ function assemble(t, prog, cfg) {
15196
15464
  if (v === FAIL) return FAIL;
15197
15465
  const end = EC.e;
15198
15466
  const span = tracked ? spanLines(ctx, pos, end) : { start: pos, end };
15199
- const st = readsState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
15467
+ const st = readsState ? ctx.state : void 0;
15200
15468
  let nd;
15201
15469
  if (unwrap && kids.length === 1) {
15202
15470
  nd = unwrapChild(kids[0]);
@@ -15209,10 +15477,10 @@ function assemble(t, prog, cfg) {
15209
15477
  ) {
15210
15478
  nd = kids[0];
15211
15479
  } 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);
15480
+ nd = hostCst && host !== void 0 ? host(type, kids, fieldMap, span, rawKids, tlog, ctx.state, tags) : projectChild(kids, proj, type);
15213
15481
  } else if (build !== void 0) {
15214
15482
  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);
15483
+ nd = host(type, kids, fieldMap, span, rawKids, tlog, ctx.state, tags);
15216
15484
  } else {
15217
15485
  nd = build(kids, fieldMap, span, rawKids, captureWide ? tlog : EMPTY_TL2, st);
15218
15486
  }
@@ -15263,9 +15531,7 @@ function assemble(t, prog, cfg) {
15263
15531
  let emitRefusal;
15264
15532
  let emitReached;
15265
15533
  {
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]);
15534
+ const extraIps = assemblyExtraIps(prog);
15269
15535
  const roots = [...Object.values(prog.rules), ...extraIps];
15270
15536
  for (const ip of reachableSites(code, roots)) {
15271
15537
  if (code[ip] === OP_DISPATCH) {
@@ -15358,9 +15624,11 @@ function assemble(t, prog, cfg) {
15358
15624
  adjacencyHolds,
15359
15625
  t.lexPrograms,
15360
15626
  LEAD,
15361
- triviaFieldCapture
15627
+ triviaFieldCapture,
15628
+ skipDeferredTrivia
15362
15629
  );
15363
15630
  emitReached = new Set(pre.reached);
15631
+ if (emitted.ext !== void 0) HYBRID = emitted;
15364
15632
  }
15365
15633
  try {
15366
15634
  if (emitted !== void 0) throw new ServedByBuild();
@@ -15442,7 +15710,8 @@ function assemble(t, prog, cfg) {
15442
15710
  adjacencyHolds,
15443
15711
  t.lexPrograms,
15444
15712
  LEAD,
15445
- triviaFieldCapture
15713
+ triviaFieldCapture,
15714
+ skipDeferredTrivia
15446
15715
  );
15447
15716
  emitReached = em.reached;
15448
15717
  } catch (e) {
@@ -15453,7 +15722,7 @@ function assemble(t, prog, cfg) {
15453
15722
  }
15454
15723
  function pieceAt(ip) {
15455
15724
  const em = emitted;
15456
- if (em !== void 0) {
15725
+ if (em !== void 0 && HYBRID === void 0) {
15457
15726
  const p = em.byIp[ip];
15458
15727
  if (p === void 0) throw new Error(`table emitter: no emitted body for site ${ip}`);
15459
15728
  return p;
@@ -15483,6 +15752,37 @@ function assemble(t, prog, cfg) {
15483
15752
  }
15484
15753
  const scans = scansArr;
15485
15754
  const scanSkip = (prog.scanSkip ?? []).map((set) => set.map((r) => subtreeComb(r)));
15755
+ if (HYBRID !== void 0) {
15756
+ const em = HYBRID;
15757
+ em.bind(
15758
+ (s) => {
15759
+ const saved = SCAN;
15760
+ SCAN = s;
15761
+ return saved;
15762
+ },
15763
+ em.ext.map((ip) => link(ip))
15764
+ );
15765
+ const pieces2 = {};
15766
+ for (const [name, entryIp] of Object.entries(prog.rules)) {
15767
+ pieces2[name] = em.pieces[name] ?? link(entryIp);
15768
+ }
15769
+ for (const ip of emitReached) reached.add(ip);
15770
+ return {
15771
+ pieces: pieces2,
15772
+ end: () => EC.e,
15773
+ begin: (ctx) => {
15774
+ begin(ctx);
15775
+ em.begin(ctx);
15776
+ },
15777
+ finish: () => {
15778
+ em.finish();
15779
+ finish();
15780
+ },
15781
+ scanSkip,
15782
+ reached,
15783
+ emitRefusal: void 0
15784
+ };
15785
+ }
15486
15786
  if (emitted !== void 0) {
15487
15787
  const em = emitted;
15488
15788
  return {
@@ -15518,6 +15818,15 @@ function assemble(t, prog, cfg) {
15518
15818
  }
15519
15819
  return { pieces, end: () => EC.e, begin, finish, scanSkip, reached, emitRefusal };
15520
15820
  }
15821
+ var SITE_COUNTS;
15822
+ function countedPiece(piece, ip) {
15823
+ const counts = SITE_COUNTS;
15824
+ if (counts === void 0) return piece;
15825
+ return (input, pos, ctx) => {
15826
+ counts[ip]++;
15827
+ return piece(input, pos, ctx);
15828
+ };
15829
+ }
15521
15830
  var AssemblyCache = class {
15522
15831
  t;
15523
15832
  prog;
@@ -15731,9 +16040,7 @@ function defaultAssemblyCfgs(prog) {
15731
16040
  function emitAssemblies(prog, cfgs) {
15732
16041
  if (cfgs.length === 0) return ["a:[],"];
15733
16042
  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]);
16043
+ const extraIps = assemblyExtraIps(prog);
15737
16044
  const out = [];
15738
16045
  const seen = /* @__PURE__ */ new Set();
15739
16046
  for (const cfg of cfgs) {
@@ -15742,7 +16049,7 @@ function emitAssemblies(prog, cfgs) {
15742
16049
  seen.add(key);
15743
16050
  let em;
15744
16051
  try {
15745
- em = emitAssemblySource(t, prog, cfg, extraIps, true);
16052
+ em = emitAssemblySource(t, prog, cfg, extraIps, true, cfg.select);
15746
16053
  } catch (e) {
15747
16054
  if (e instanceof Unemittable) continue;
15748
16055
  throw e;
@@ -17299,8 +17606,46 @@ function runDuplicationDiagnosticRules(ruleMap, opt) {
17299
17606
  return reportDuplication(opt, (o) => analyzeDuplicationRules(ruleMap, o));
17300
17607
  }
17301
17608
 
17609
+ // src/table/select-hot.ts
17610
+ var LOOP = 8;
17611
+ var ROUNDS = 60;
17612
+ var CAP = 1e12;
17613
+ function selectHotSites(code, entries, siteBytes, budget, profile) {
17614
+ const selected = /* @__PURE__ */ new Set();
17615
+ if (budget <= 0) return selected;
17616
+ const weight = profile === void 0 ? staticWeights(code, entries) : void 0;
17617
+ const w = (ip) => (weight !== void 0 ? weight.get(ip) : profile[ip]) ?? 0;
17618
+ const ranked = [...siteBytes.keys()].sort((a, b) => w(b) / siteBytes.get(b) - w(a) / siteBytes.get(a) || a - b);
17619
+ let spent = 0;
17620
+ for (const ip of ranked) {
17621
+ if (w(ip) === 0) break;
17622
+ const bytes2 = siteBytes.get(ip);
17623
+ if (spent + bytes2 > budget) continue;
17624
+ spent += bytes2;
17625
+ selected.add(ip);
17626
+ }
17627
+ return selected;
17628
+ }
17629
+ function staticWeights(code, entries) {
17630
+ let weight = /* @__PURE__ */ new Map();
17631
+ const kids = [];
17632
+ for (let round = 0; round < ROUNDS; round++) {
17633
+ const next = /* @__PURE__ */ new Map();
17634
+ for (const ip of entries) next.set(ip, 1);
17635
+ for (const [ip, w] of weight) {
17636
+ kids.length = 0;
17637
+ childSlots(code, ip, kids);
17638
+ const op = code[ip];
17639
+ const scale = op === OP_REP || op === OP_REPV ? LOOP : op === OP_CHOICE || op === OP_DISPATCH ? 1 / Math.max(1, kids.length) : 1;
17640
+ for (const kid of kids) next.set(kid, Math.min(CAP, (next.get(kid) ?? 0) + w * scale));
17641
+ }
17642
+ weight = next;
17643
+ }
17644
+ return weight;
17645
+ }
17646
+
17302
17647
  // src/table/compile-rule-map.ts
17303
- var DEFAULT_PRECOMPILE_MIN_WORDS = 1024;
17648
+ var SUPERCOMPILE_GROWTH = 1.05;
17304
17649
  function resolveHostMode(ruleMap, explicit) {
17305
17650
  return explicit ?? ruleMap.map(([, r]) => r._meta.grammarHostMode).find(Boolean) ?? "ast";
17306
17651
  }
@@ -17397,14 +17742,40 @@ function compileRuleMap(ruleMap, opts = {}) {
17397
17742
  entry: null,
17398
17743
  runtimeRef: opts.runtimeRef ?? "tableRules",
17399
17744
  fnSources: sources,
17400
- ...options.precompileDefault === true && hostMode === "ast" && prog.lines !== 1 && prog.code.length >= DEFAULT_PRECOMPILE_MIN_WORDS ? { assemblies: defaultAssemblyCfgs(artifact).slice(0, 1) } : {},
17745
+ ...options.select !== void 0 && options.select.size > 0 ? { assemblies: [{ ...defaultAssemblyCfgs(artifact)[0], select: options.select }] } : {},
17401
17746
  ...metadataSource === void 0 ? {} : { metadataSource }
17402
17747
  });
17403
17748
  const replacement = replacementWithMetadata();
17749
+ const selectAssembly = (budget, profile) => {
17750
+ const none = { sites: /* @__PURE__ */ new Set(), bytes: 0 };
17751
+ if (hostMode !== "ast" || prog.lines === 1) return none;
17752
+ const table = resolveTable(artifact);
17753
+ const cfg = defaultAssemblyCfgs(artifact)[0];
17754
+ const roots = assemblyExtraIps(artifact);
17755
+ let siteBytes, fixed;
17756
+ try {
17757
+ siteBytes = emitAssemblySource(table, artifact, cfg, roots, true).siteBytes;
17758
+ fixed = emitAssemblySource(table, artifact, cfg, roots, true, /* @__PURE__ */ new Set()).source.length;
17759
+ } catch (e) {
17760
+ if (e instanceof Unemittable) return { ...none, refusal: e.construct };
17761
+ throw e;
17762
+ }
17763
+ const ceiling = budget / SUPERCOMPILE_GROWTH;
17764
+ let target = ceiling;
17765
+ for (let attempt2 = 0; attempt2 < 16; attempt2++) {
17766
+ const sites = selectHotSites(artifact.code, Object.values(artifact.rules), siteBytes, target - fixed, profile);
17767
+ if (sites.size === 0) return none;
17768
+ const bytes2 = emitAssemblySource(table, artifact, cfg, roots, true, sites).source.length;
17769
+ if (bytes2 <= ceiling) return { sites, bytes: Math.ceil(bytes2 * SUPERCOMPILE_GROWTH) };
17770
+ target *= Math.min(ceiling / bytes2, 0.99);
17771
+ }
17772
+ return none;
17773
+ };
17404
17774
  return {
17405
17775
  keys: ruleMap.map(([key]) => key),
17406
17776
  replacement,
17407
17777
  replacementWithMetadata,
17778
+ selectAssembly,
17408
17779
  hostMode,
17409
17780
  // WHAT THE FLAG MEANS is "a DIRECT BUILDER's positioned-CST branch was
17410
17781
  // dropped", which is what the driver's `'ast' artifact + CST host` check keys
@@ -18037,7 +18408,7 @@ function fieldOptionsSrc(def) {
18037
18408
  }
18038
18409
 
18039
18410
  // src/version.ts
18040
- var PARSEMAN_VERSION = "0.56.0";
18411
+ var PARSEMAN_VERSION = "0.57.0";
18041
18412
 
18042
18413
  // src/compiler/compile-linkable-table.ts
18043
18414
  function isLocal(rule) {