parseman 0.61.4 → 0.61.5

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 (42) hide show
  1. package/dist/analysis/diagnostics.js +844 -522
  2. package/dist/analysis/diagnostics.js.map +3 -3
  3. package/dist/cli/index.js +846 -522
  4. package/dist/cli/index.js.map +3 -3
  5. package/dist/cst/capture-buffer.d.ts +3 -2
  6. package/dist/cst/capture-buffer.d.ts.map +1 -1
  7. package/dist/index.js +846 -520
  8. package/dist/index.js.map +3 -3
  9. package/dist/plugin/index.js +844 -518
  10. package/dist/plugin/index.js.map +3 -3
  11. package/dist/table/assemble.d.ts.map +1 -1
  12. package/dist/table/child-slots.d.ts.map +1 -1
  13. package/dist/table/emit-assembly.d.ts +1 -1
  14. package/dist/table/emit-assembly.d.ts.map +1 -1
  15. package/dist/table/encode.d.ts.map +1 -1
  16. package/dist/table/exec.d.ts.map +1 -1
  17. package/dist/table/fail-clean.d.ts.map +1 -1
  18. package/dist/table/hold-gap.d.ts.map +1 -1
  19. package/dist/table/index.js +368 -42
  20. package/dist/table/index.js.map +3 -3
  21. package/dist/table/late-frame.d.ts +18 -0
  22. package/dist/table/late-frame.d.ts.map +1 -0
  23. package/dist/table/ops.d.ts +17 -0
  24. package/dist/table/ops.d.ts.map +1 -1
  25. package/dist/table/select-hot.d.ts.map +1 -1
  26. package/dist/table/site-labels.d.ts +5 -1
  27. package/dist/table/site-labels.d.ts.map +1 -1
  28. package/dist/version.d.ts +1 -1
  29. package/package.json +1 -1
  30. package/src/cst/capture-buffer.ts +20 -11
  31. package/src/table/assemble.ts +124 -4
  32. package/src/table/child-slots.ts +9 -1
  33. package/src/table/emit-assembly.ts +101 -14
  34. package/src/table/encode.ts +69 -6
  35. package/src/table/exec.ts +7 -1
  36. package/src/table/fail-clean.ts +8 -1
  37. package/src/table/hold-gap.ts +5 -1
  38. package/src/table/late-frame.ts +54 -0
  39. package/src/table/ops.ts +19 -0
  40. package/src/table/select-hot.ts +7 -1
  41. package/src/table/site-labels.ts +38 -14
  42. package/src/version.ts +1 -1
@@ -742,26 +742,34 @@ function popCstChild(ctx) {
742
742
  const b = ctx._cstBuf;
743
743
  if (b) {
744
744
  const ch2 = b.ch;
745
- if (b.rawOnly !== true && ch2) {
746
- ch2.pop();
747
- if (ch2.length === 1) {
748
- b.single = ch2[0];
749
- b.ch = void 0;
750
- }
745
+ if (b.rawOnly !== true) {
746
+ if (ch2) {
747
+ ch2.pop();
748
+ if (ch2.length === 1) {
749
+ b.single = ch2[0];
750
+ b.ch = void 0;
751
+ }
752
+ } else b.single = void 0;
753
+ }
754
+ if (b.noRaw === true) {
755
+ b.rawLen = (b.rawLen ?? 1) - 1;
756
+ return void 0;
751
757
  }
752
- if (b.noRaw === true) b.rawLen = (b.rawLen ?? 1) - 1;
753
- else if (b.raw) {
754
- b.raw.pop();
758
+ if (b.raw) {
759
+ const entry2 = b.raw.pop();
755
760
  if (b.raw.length === 1) {
756
761
  b.rawSingle = b.raw[0];
757
762
  b.raw = void 0;
758
763
  }
759
- } else b.rawSingle = void 0;
760
- return;
764
+ return entry2;
765
+ }
766
+ const entry = b.rawSingle;
767
+ b.rawSingle = void 0;
768
+ return entry;
761
769
  }
762
770
  if (ctx._cstChildren) ctx._cstChildren.pop();
763
771
  else if (ctx._cstLeaves) ctx._cstLeaves.pop();
764
- if (ctx._cstRawChildren) ctx._cstRawChildren.pop();
772
+ return ctx._cstRawChildren?.pop();
765
773
  }
766
774
  function cstRawLen(ctx) {
767
775
  const b = ctx._cstBuf;
@@ -3628,7 +3636,7 @@ function regex(pattern, flags = "") {
3628
3636
  }
3629
3637
 
3630
3638
  // src/version.ts
3631
- var PARSEMAN_VERSION = "0.61.4";
3639
+ var PARSEMAN_VERSION = "0.61.5";
3632
3640
 
3633
3641
  // src/table/lex-body.ts
3634
3642
  function buildLexBodyRecognizer(spec, constants) {
@@ -5797,6 +5805,8 @@ var OP_RGATE = 45;
5797
5805
  var OP_GAPGATE = 46;
5798
5806
  var OP_RGATE2 = 47;
5799
5807
  var OP_STRICT = 48;
5808
+ var OP_CONT = 49;
5809
+ var OP_SEED = 50;
5800
5810
  var OP_DISPATCH = 25;
5801
5811
  var OP_ROUTED = 26;
5802
5812
  var OP_NAMES = {
@@ -5847,7 +5857,9 @@ var OP_NAMES = {
5847
5857
  [OP_LEX_PROGRAM]: "LEX_PROGRAM",
5848
5858
  [OP_GAPGATE]: "GAPGATE",
5849
5859
  [OP_RGATE2]: "RGATE2",
5850
- [OP_STRICT]: "STRICT"
5860
+ [OP_STRICT]: "STRICT",
5861
+ [OP_CONT]: "CONT",
5862
+ [OP_SEED]: "SEED"
5851
5863
  };
5852
5864
 
5853
5865
  // src/table/scan-shapes.ts
@@ -6920,6 +6932,13 @@ function childSlotOffsets(code, ip, out) {
6920
6932
  case OP_RGATE2:
6921
6933
  out.push(ip + 2);
6922
6934
  return true;
6935
+ // `CONT corner wrapper tail`: `tail` is reached through `wrapper`.
6936
+ case OP_CONT:
6937
+ out.push(ip + 1, ip + 2);
6938
+ return true;
6939
+ case OP_SEED:
6940
+ out.push(ip + 1);
6941
+ return true;
6923
6942
  // `STRICT strict tolerant` — both encodings are reachable; an assembly keeps one.
6924
6943
  case OP_STRICT:
6925
6944
  out.push(ip + 1, ip + 2);
@@ -7016,7 +7035,7 @@ function passCollapse(code, ip, hostCst) {
7016
7035
  else if (op === OP_RULE) at = code[at + 1];
7017
7036
  else break;
7018
7037
  }
7019
- return code[at] === OP_NODE;
7038
+ return code[at] === OP_NODE || code[at] === OP_CONT;
7020
7039
  }
7021
7040
  function gatedPassCollapse(code, ip, hostCst) {
7022
7041
  const flags = code[ip + 3];
@@ -7075,7 +7094,7 @@ function transfer(code, ip, at, hostCst) {
7075
7094
  }
7076
7095
  return at;
7077
7096
  }
7078
- function computeSiteLabels(code, roots, hostCst) {
7097
+ function computeSiteLabels(code, roots, hostCst, late) {
7079
7098
  const labels = /* @__PURE__ */ new Map();
7080
7099
  const work = [];
7081
7100
  const push = (ip, l) => {
@@ -7090,16 +7109,33 @@ function computeSiteLabels(code, roots, hostCst) {
7090
7109
  labels.set(ip, next);
7091
7110
  work.push(ip);
7092
7111
  };
7093
- for (const r of roots) push(r, TOP);
7112
+ const opened = /* @__PURE__ */ new Set();
7094
7113
  const kids = [];
7095
- while (work.length > 0) {
7096
- const ip = work.pop();
7097
- const down = transfer(code, ip, labels.get(ip), hostCst);
7098
- kids.length = 0;
7099
- childSlots(code, ip, kids);
7100
- for (const c of kids) push(c, down);
7114
+ const lateIps = /* @__PURE__ */ new Set();
7115
+ for (const r of roots) push(r, TOP);
7116
+ for (let pass = 0; pass < 2; pass++) {
7117
+ while (work.length > 0) {
7118
+ const ip = work.pop();
7119
+ const down = transfer(code, ip, labels.get(ip), hostCst);
7120
+ kids.length = 0;
7121
+ if (late === void 0 || code[ip] !== OP_SEED || opened.has(ip)) childSlots(code, ip, kids);
7122
+ for (const c of kids) push(c, down);
7123
+ }
7124
+ if (late === void 0 || pass === 1) break;
7125
+ for (const [ip, l] of [...labels]) {
7126
+ if (code[ip] !== OP_CONT) continue;
7127
+ if (late(ip, l.tri)) lateIps.add(ip);
7128
+ else {
7129
+ const seed = seedOf(code, ip);
7130
+ opened.add(seed);
7131
+ work.push(seed);
7132
+ }
7133
+ }
7101
7134
  }
7102
- return { at: (ip) => labels.get(ip) ?? TOP };
7135
+ return { at: (ip) => labels.get(ip) ?? TOP, late: lateIps };
7136
+ }
7137
+ function seedOf(code, cont) {
7138
+ return code[code[code[cont + 2] + 2] + 2];
7103
7139
  }
7104
7140
  function scopeIsIdentity(code, ip, at) {
7105
7141
  const op = code[ip];
@@ -7347,6 +7383,30 @@ function largeChoiceLiteralPretest(code, constants, armIp) {
7347
7383
  }) ? family : void 0;
7348
7384
  }
7349
7385
 
7386
+ // src/table/late-frame.ts
7387
+ function continuationGate(code, ip) {
7388
+ let at = ip;
7389
+ for (let n = 0; n < 8; n++) {
7390
+ const op2 = code[at];
7391
+ if (op2 === OP_RULE) at = code[at + 1];
7392
+ else if (op2 === OP_WITHCTX) at = code[at + 2];
7393
+ else break;
7394
+ }
7395
+ const op = code[at];
7396
+ if (op === OP_OPT) {
7397
+ const c = code[at + 1];
7398
+ return code[c] === OP_GATE ? { cls: code[c + 1], gapRow: -1, follow: -1, other: -1 } : void 0;
7399
+ }
7400
+ if (op !== OP_REP && op !== OP_REPV) return void 0;
7401
+ if (code[at + 2] !== 0 || code[at + 4] >= 0 || code[at + 7] < 0) return void 0;
7402
+ const item = code[at + 1];
7403
+ return code[item] === OP_GAPGATE ? { cls: code[at + 7], gapRow: code[item + 2], follow: code[item + 3], other: code[item + 4] } : { cls: code[at + 7], gapRow: -1, follow: -1, other: -1 };
7404
+ }
7405
+ function canDecide(code, ip, tri, triviaScan) {
7406
+ if (tri !== TRI_NONE && (tri < 0 || triviaScan[tri] == null)) return false;
7407
+ return continuationGate(code, code[ip + 3]) !== void 0;
7408
+ }
7409
+
7350
7410
  // src/table/field-spec.ts
7351
7411
  function fieldSpec(slot) {
7352
7412
  return Array.isArray(slot) ? { name: slot[0], bits: slot[1] } : { name: slot, bits: 0 };
@@ -7394,6 +7454,10 @@ function rowNullable(code, k, ip, memo) {
7394
7454
  out = kids.length === 0 || kids.some((c) => rowNullable(code, k, c, memo));
7395
7455
  } else if (op === OP_REP || op === OP_REPV) {
7396
7456
  out = code[ip + 2] === 0 || rowNullable(code, k, code[ip + 1], memo);
7457
+ } else if (op === OP_SEED) {
7458
+ out = rowNullable(code, k, code[ip + 1], memo);
7459
+ } else if (op === OP_CONT) {
7460
+ out = rowNullable(code, k, code[ip + 1], memo) && rowNullable(code, k, code[ip + 3], memo);
7397
7461
  } else if (WRAPPERS.has(op)) {
7398
7462
  if (childSlots(code, ip, kids) && kids.length === 1) out = rowNullable(code, k, kids[0], memo);
7399
7463
  }
@@ -7507,6 +7571,7 @@ var EMITTED_PARAMS = [
7507
7571
  "skipDeferredTrivia",
7508
7572
  // The pass-through collapse (`run-support.ts`).
7509
7573
  "collapseEmpty",
7574
+ "popCstChild",
7510
7575
  // Constructor-built tree objects (`cst/plain.d.ts`): a `new` call has no
7511
7576
  // allocation site, so V8 cannot pretenure them.
7512
7577
  "_SP",
@@ -7786,7 +7851,12 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, se
7786
7851
  const roots = [...Object.values(prog.rules), ...extraIps];
7787
7852
  const reachable = [...reachableSites(code, roots)];
7788
7853
  const GAP_ROWS = gapNeutral ? /* @__PURE__ */ new Set() : new Set([...gapRows(code, roots)].filter((row) => !gapRegexLowers(k[code[row + 1]])));
7789
- const labels = computeSiteLabels(code, roots, hostCst);
7854
+ const labels = computeSiteLabels(
7855
+ code,
7856
+ roots,
7857
+ hostCst,
7858
+ cfg.tolerant || cfg.probe ? void 0 : (ip, tri) => canDecide(code, ip, tri, t.triviaScan)
7859
+ );
7790
7860
  const scalarSpecs = /* @__PURE__ */ new Set();
7791
7861
  const nullable2 = /* @__PURE__ */ new Map();
7792
7862
  const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
@@ -8033,6 +8103,14 @@ return 1
8033
8103
  if (leads.length === 0) return (c) => `${c}<55296`;
8034
8104
  return (c) => `${c}<55296&&!(${leads.map((r) => r.lo === r.hi ? `${c}===${r.lo}` : `(${c}>=${r.lo}&&${c}<=${r.hi})`).join("||")})`;
8035
8105
  }
8106
+ function skipCapturing(l) {
8107
+ if (l.tri < 0 || !swapLegal || triviaLabelled[l.tri] || t.triviaScan[l.tri] == null) return "true";
8108
+ return capturesHere(l);
8109
+ }
8110
+ function capturesHere(l) {
8111
+ const sink = l.buf ? "true" : "(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)";
8112
+ return l.cap === CAP_OFF ? "false" : l.cap === CAP_ON ? sink : `(ctx.captureTrivia===true&&${sink})`;
8113
+ }
8036
8114
  function skipFor(l) {
8037
8115
  if (l.tri < 0) return "_skipTrivia";
8038
8116
  const ki = l.tri;
@@ -8125,9 +8203,12 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
8125
8203
  if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
8126
8204
  if (op === OP_RULE || op === OP_GAPGATE) return code[ip + 1];
8127
8205
  if (op === OP_STRICT) return code[cfg.tolerant || cfg.probe ? ip + 2 : ip + 1];
8206
+ if (op === OP_CONT && !labels.late.has(ip)) return code[ip + 2];
8207
+ if (op === OP_SEED) return code[ip + 1];
8128
8208
  if (scopeIsIdentity(code, ip, labels.at(ip))) return code[ip + 2];
8129
8209
  return void 0;
8130
8210
  }
8211
+ let LATE;
8131
8212
  function lower(ip, fname) {
8132
8213
  const op = code[ip];
8133
8214
  const head = `function ${fname}(input,pos,ctx){`;
@@ -8260,6 +8341,71 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
8260
8341
  }
8261
8342
  case OP_EMPTY:
8262
8343
  return `${head}EC.e=pos;return ''}`;
8344
+ case OP_CONT: {
8345
+ const tri = L.tri;
8346
+ const g = continuationGate(code, code[ip + 3]);
8347
+ const missAt = (idx, at2) => {
8348
+ const resolved = t.cc[idx];
8349
+ const ci = classes.push([resolved]) - 1;
8350
+ classPlan.push([idx]);
8351
+ const ref2 = hoist("cg", `CLS[${ci}][0]`);
8352
+ return isAsciiOnlyClass(resolved) ? `${ref2}.ascii[input.charCodeAt(${at2})]!==1` : `!classHas(${ref2},lead(input,${at2}))`;
8353
+ };
8354
+ let scanned = "";
8355
+ if (tri >= 0) {
8356
+ const scan = hoist("cs", `TRIVIASCAN[${tri}]`);
8357
+ const miss = triviaMiss(tri);
8358
+ scanned = miss === void 0 ? `const q0=${scan}(input,c1)
8359
+ ` : `const cc=input.charCodeAt(c1)
8360
+ const q0=${miss("cc")}?c1:${scan}(input,c1)
8361
+ `;
8362
+ }
8363
+ const at = tri >= 0 ? "q0" : "c1";
8364
+ let test;
8365
+ if (g.gapRow < 0) test = `if(c0!==undefined&&${missAt(g.cls, at)})return c0
8366
+ `;
8367
+ else {
8368
+ const re = hoist("cr", `K[${code[g.gapRow + 1]}]`);
8369
+ const other = g.other >= 0 ? missAt(g.other, at) : "true";
8370
+ test = `${re}.lastIndex=${at}
8371
+ const gq=${re}.test(input)?${re}.lastIndex:-1
8372
+ if(c0!==undefined&&(gq<0||${missAt(g.follow, "gq")})&&${other})return c0
8373
+ `;
8374
+ }
8375
+ const seq = code[code[ip + 2] + 2];
8376
+ const seqLabel = labels.at(seq);
8377
+ const tail = link(code[ip + 3]);
8378
+ const recorded = tri === TRI_NONE ? "" : `const tl0=ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)
8379
+ const lg0=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
8380
+ const rt0=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
8381
+ const s0=${skipFor(seqLabel)}(input,c1,ctx)
8382
+ const tl1=ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)
8383
+ const lg1=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
8384
+ const rt1=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
8385
+ v=${tail}(input,s0,ctx)
8386
+ if(v!==FAIL&&EC.e<=s0){rollbackScannedTriviaAt(ctx,tl0,tl1,lg0,lg1,rt0,rt1);EC.e=c1}`;
8387
+ const quiet = `v=${tail}(input,${at},ctx)
8388
+ if(v!==FAIL&&EC.e<=${at})EC.e=c1`;
8389
+ const capture = capturesHere(seqLabel);
8390
+ const body = `let v
8391
+ ${tri === TRI_NONE ? `v=${tail}(input,c1,ctx)` : `if(q0===c1)v=${tail}(input,c1,ctx)
8392
+ else ${capture === "true" ? `{
8393
+ ${recorded}
8394
+ }` : `if(ctx._triviaLog===undefined&&ctx._rootTriviaLog===undefined${capture === "false" ? "" : `&&!${capture}`}){
8395
+ ${quiet}
8396
+ }else{
8397
+ ${recorded}
8398
+ }`}`}`;
8399
+ const wrapperIp = code[ip + 2];
8400
+ LATE = {
8401
+ prefix: `const c0=${link(code[ip + 1])}(input,pos,ctx)
8402
+ if(c0===FAIL)return FAIL
8403
+ const c1=EC.e
8404
+ ${scanned}${test}`,
8405
+ body
8406
+ };
8407
+ return lower(wrapperIp, fname);
8408
+ }
8263
8409
  case OP_GATE: {
8264
8410
  const child = link(code[ip + 2]);
8265
8411
  const xf = fxRef(code[ip + 3]);
@@ -9222,7 +9368,9 @@ return out
9222
9368
  case OP_NODE:
9223
9369
  case OP_NODE_TRACK: {
9224
9370
  const flags = code[ip + 3];
9225
- const scalarChild = scalarTerminalNodeChild(code, ip);
9371
+ const late = LATE;
9372
+ LATE = void 0;
9373
+ const scalarChild = late === void 0 ? scalarTerminalNodeChild(code, ip) : -1;
9226
9374
  if (scalarChild >= 0 && scalarSpecs.has(code[scalarChild + 1])) {
9227
9375
  const recognize = recognizerRef(code[scalarChild + 1]);
9228
9376
  const spec = code[scalarChild] === OP_RX ? null : k[code[scalarChild + 1]];
@@ -9242,7 +9390,9 @@ EC.e=end
9242
9390
  return nd
9243
9391
  }`;
9244
9392
  }
9245
- const child = link(code[ip + 2]);
9393
+ const child = late === void 0 ? link(code[ip + 2]) : "";
9394
+ const runBody = late === void 0 ? `const v=${child}(input,pos,ctx)` : late.body;
9395
+ const takeBack = late === void 0 ? "" : "let c0Raw\nif(sBuf===undefined&&sRaw===undefined&&sCh!==undefined)sCh.pop()\nelse if(sBuf!==undefined||sCh!==undefined)c0Raw=popCstChild(ctx)\n";
9246
9396
  const proj = code[ip + 4];
9247
9397
  const buildIdx = code[ip + 1];
9248
9398
  const type = k[code[ip + 5]];
@@ -9257,14 +9407,14 @@ return nd
9257
9407
  const trailingTrivia = (flags & 128) !== 0;
9258
9408
  const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
9259
9409
  const leanFlags = flags & ~128;
9260
- if (build !== void 0 && passCollapse(code, ip, hostCst)) {
9410
+ if (late === void 0 && build !== void 0 && passCollapse(code, ip, hostCst)) {
9261
9411
  return `${head}
9262
9412
  const v=${child}(input,pos,ctx)
9263
9413
  if(v!==undefined)return v
9264
9414
  return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
9265
9415
  }`;
9266
9416
  }
9267
- const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
9417
+ const gated = late === void 0 && build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
9268
9418
  const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(labels.at(code[ip + 2]).tri, t.trivia);
9269
9419
  const gp = gated !== void 0 && triviaLead !== void 0 && triviaLead.length <= 16 ? `const gc=lead(input,pos)
9270
9420
  if(!(${[
@@ -9311,9 +9461,9 @@ sCh.push(nd)
9311
9461
  if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
9312
9462
  }`;
9313
9463
  return `${head}
9314
- ${gp}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
9464
+ ${late?.prefix ?? ""}${gp}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
9315
9465
  const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
9316
- const flat=[]
9466
+ ${takeBack}const flat=${late === void 0 ? "[]" : "[c0]"}
9317
9467
  ctx._cstBuf=undefined
9318
9468
  ctx._cstChildren=flat
9319
9469
  ctx._cstLeaves=flat
@@ -9321,7 +9471,7 @@ ctx._cstRawChildren=undefined
9321
9471
  ctx._cstTriviaLog=undefined
9322
9472
  ctx.captureTrivia=false
9323
9473
  ctx._fields=${fields ? "[]" : "undefined"}
9324
- const v=${child}(input,pos,ctx)
9474
+ ${runBody}
9325
9475
  ${trailingTrivia && L.tri !== TRI_NONE ? `if(v!==FAIL${L.tri === TRI_UNKNOWN ? "&&ctx.trivia!==undefined" : ""})EC.e=consumeTrivia(input,EC.e,ctx)
9326
9476
  ` : ""}const captured=_capturedFlatChildren(flat)
9327
9477
  ${fields ? "const fieldMap=buildFieldMap(ctx._fields)\n" : ""}ctx._fields=sFields
@@ -9385,16 +9535,17 @@ const tlog=buf.tl??EMPTY_TLOG` : `const kids=EMPTY_CH
9385
9535
  const hostKids=kids
9386
9536
  const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
9387
9537
  const tlog=buf.tl??EMPTY_TLOG`;
9538
+ const seedCapture = late === void 0 ? "" : omitsRaw ? "buf.single=c0\nbuf.rawLen=1\n" : "buf.single=c0\nbuf.rawSingle=c0Raw!==undefined?c0Raw:rawEntry(c0,input,pos,c1)\n";
9388
9539
  return `${head}
9389
- ${!hostCst && !tracked ? gp : ""}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
9540
+ ${late?.prefix ?? ""}${!hostCst && !tracked ? gp : ""}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
9390
9541
  const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf
9391
- ${openCapture}
9392
- ctx.captureTrivia=${captureWide}
9542
+ ${takeBack}${openCapture}
9543
+ ${seedCapture}ctx.captureTrivia=${captureWide}
9393
9544
  const savedFields=ctx._fields
9394
9545
  ctx._fields=${wantFields ? "[]" : "undefined"}
9395
9546
  ${structural ? `const savedMask=ctx._triviaCaptureMask
9396
9547
  if(_pfHost!==undefined&&_pfHost._parsemanTriviaKinds!==undefined)ctx._triviaCaptureMask=_pfHost._parsemanTriviaKinds(${ty})
9397
- ` : ""}const v=${child}(input,pos,ctx)
9548
+ ` : ""}${runBody}
9398
9549
  ${trailingTrivia && L.tri !== TRI_NONE ? `if(v!==FAIL${L.tri === TRI_UNKNOWN ? "&&ctx.trivia!==undefined" : ""})EC.e=consumeTrivia(input,EC.e,ctx)
9399
9550
  ` : ""}const fieldMap=${wantFields ? "buildFieldMap(ctx._fields)" : "undefined"}
9400
9551
  ctx._fields=savedFields
@@ -9612,6 +9763,13 @@ function failCleanAnalysis(code) {
9612
9763
  case OP_ROUTED:
9613
9764
  out = code[ip + 1] < 0 || clean(code[ip + 1]);
9614
9765
  break;
9766
+ case OP_SEED:
9767
+ out = clean(code[ip + 1]);
9768
+ break;
9769
+ // The corner may fail; the wrapper fails only through a tail that can.
9770
+ case OP_CONT:
9771
+ out = clean(code[ip + 1]) && neverFails(code[ip + 3]);
9772
+ break;
9615
9773
  // An arm's failure and the fallback's are committed; only the selector's is
9616
9774
  // not, and without a fallback an unknown key fails after the selector wrote.
9617
9775
  case OP_DISPATCH:
@@ -9837,7 +9995,8 @@ function assemble(t, prog, cfg) {
9837
9995
  const closureLabels = computeSiteLabels(
9838
9996
  code,
9839
9997
  [...Object.values(prog.rules), ...labelExtraIps],
9840
- hostCst
9998
+ hostCst,
9999
+ cfg.tolerant || cfg.probe ? void 0 : (ip, tri) => canDecide(code, ip, tri, t.triviaScan)
9841
10000
  );
9842
10001
  let SCAN = null;
9843
10002
  let HYBRID;
@@ -10234,6 +10393,32 @@ function assemble(t, prog, cfg) {
10234
10393
  if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
10235
10394
  return cur;
10236
10395
  }
10396
+ function startsTail(cls, input, at) {
10397
+ const c = input.charCodeAt(at);
10398
+ return c < 128 ? cls.ascii[c] === 1 : classHas2(cls, lead(input, at));
10399
+ }
10400
+ function lateTail(tail, input, end, at, ctx, frame) {
10401
+ if (at === end) return tail(input, end, ctx);
10402
+ if (ctx._triviaLog === void 0 && ctx._rootTriviaLog === void 0 && (frame.cap === CAP_OFF || !((frame.cap === CAP_ON || ctx.captureTrivia === true) && (frame.buf || ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0)))) {
10403
+ const v2 = tail(input, at, ctx);
10404
+ if (v2 !== FAIL && EC.e <= at) EC.e = end;
10405
+ return v2;
10406
+ }
10407
+ const need = rollbackNeeded(ctx);
10408
+ const mTl = need ? cstTlLen(ctx) : 0;
10409
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
10410
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
10411
+ const scanEnd = skipTrivia(input, end, ctx);
10412
+ const scanTl = need ? cstTlLen(ctx) : 0;
10413
+ const scanLog = need ? ctx._triviaLog?.length ?? 0 : 0;
10414
+ const scanRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
10415
+ const v = tail(input, scanEnd, ctx);
10416
+ if (v !== FAIL && EC.e <= scanEnd) {
10417
+ if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
10418
+ EC.e = end;
10419
+ }
10420
+ return v;
10421
+ }
10237
10422
  function nextTermBuffered(child, input, cur, ctx) {
10238
10423
  const t2 = ctx.trivia;
10239
10424
  if (t2 === void 0 || cannotStartTrivia(input, cur, t2)) {
@@ -10849,6 +11034,79 @@ function assemble(t, prog, cfg) {
10849
11034
  EC.e = pos;
10850
11035
  return "";
10851
11036
  };
11037
+ case OP_SEED:
11038
+ return link(code[ip + 1]);
11039
+ case OP_CONT: {
11040
+ const wrapper = code[ip + 2];
11041
+ if (!closureLabels.late.has(ip)) return lower(wrapper);
11042
+ const corner = link(code[ip + 1]);
11043
+ const tail = link(code[ip + 3]);
11044
+ const g = continuationGate(code, code[ip + 3]);
11045
+ const tri = closureLabels.at(ip).tri;
11046
+ const scan = tri === TRI_NONE ? void 0 : t.triviaScan[tri];
11047
+ const leads = tri === TRI_NONE ? null : LEAD_TABLES[tri];
11048
+ const cls = cc[g.cls];
11049
+ const gapRe = g.gapRow < 0 ? void 0 : k[code[g.gapRow + 1]];
11050
+ const follow = g.follow < 0 ? void 0 : cc[g.follow];
11051
+ const other = g.other < 0 ? void 0 : cc[g.other];
11052
+ const mayStartPastGap = (input, at) => {
11053
+ gapRe.lastIndex = at;
11054
+ const q2 = gapRe.test(input) ? gapRe.lastIndex : -1;
11055
+ return q2 >= 0 && classHas2(follow, lead(input, q2)) || other !== void 0 && classHas2(other, lead(input, at));
11056
+ };
11057
+ const frame = closureLabels.at(code[wrapper + 2]);
11058
+ const flags = code[wrapper + 3];
11059
+ const buildIdx = code[wrapper + 1];
11060
+ let held;
11061
+ let heldRaw;
11062
+ let heldEnd = 0;
11063
+ let heldAt = 0;
11064
+ const omitsRaw = !hostCst && buildIdx >= 0 && code[wrapper + 4] < 0 && (flags & 2) !== 0;
11065
+ const body = omitsRaw ? (input, _pos, ctx) => {
11066
+ const b = ctx._cstBuf;
11067
+ if (b !== void 0) {
11068
+ b.single = held;
11069
+ b.rawLen = 1;
11070
+ } else ctx._cstChildren.push(held);
11071
+ held = void 0;
11072
+ heldRaw = void 0;
11073
+ return lateTail(tail, input, heldEnd, heldAt, ctx, frame);
11074
+ } : (input, pos, ctx) => {
11075
+ const b = ctx._cstBuf;
11076
+ if (b !== void 0) {
11077
+ b.single = held;
11078
+ b.rawSingle = heldRaw ?? rawEntry(held, input, pos, heldEnd);
11079
+ } else ctx._cstChildren.push(held);
11080
+ held = void 0;
11081
+ heldRaw = void 0;
11082
+ return lateTail(tail, input, heldEnd, heldAt, ctx, frame);
11083
+ };
11084
+ let open;
11085
+ if (!hostCst && !cfg.trackLines && code[wrapper] === OP_NODE && code[wrapper + 4] < 0 && (flags === 32 || flags === 34)) {
11086
+ const build = fns[buildIdx];
11087
+ open = flags === 34 ? childrenOnlyCollapseBuildNode(body, build) : collapseBuildNode(body, build);
11088
+ } else {
11089
+ NODE_BODY = body;
11090
+ open = lower(wrapper);
11091
+ }
11092
+ return (input, pos, ctx) => {
11093
+ const v = corner(input, pos, ctx);
11094
+ if (v === FAIL) return FAIL;
11095
+ const end = EC.e;
11096
+ let at = end;
11097
+ if (scan !== void 0) {
11098
+ const c = input.charCodeAt(end);
11099
+ if (leads === null || !(c < 128) || leads[c] !== 0) at = scan(input, end);
11100
+ }
11101
+ if (v !== void 0 && !(gapRe === void 0 ? startsTail(cls, input, at) : mayStartPastGap(input, at))) return v;
11102
+ if (ctx._cstBuf === void 0 && ctx._cstRawChildren === void 0 && ctx._cstChildren !== void 0) ctx._cstChildren.pop();
11103
+ else if (ctx._cstBuf !== void 0 || ctx._cstChildren !== void 0) heldRaw = popCstChild(ctx);
11104
+ held = v;
11105
+ heldEnd = end;
11106
+ heldAt = at;
11107
+ return open(input, pos, ctx);
11108
+ };
11109
+ }
10852
11110
  /* ── transparent / structural ────────────────────────────────────────── */
10853
11111
  case OP_GUARD: {
10854
11112
  const pred = fns[code[ip + 1]];
@@ -13065,6 +13323,7 @@ function assemble(t, prog, cfg) {
13065
13323
  triviaFieldCapture,
13066
13324
  skipDeferredTrivia,
13067
13325
  collapseEmpty,
13326
+ popCstChild,
13068
13327
  PlainSpan9,
13069
13328
  PlainLeaf8,
13070
13329
  PlainNode2,
@@ -13154,6 +13413,7 @@ function assemble(t, prog, cfg) {
13154
13413
  triviaFieldCapture,
13155
13414
  skipDeferredTrivia,
13156
13415
  collapseEmpty,
13416
+ popCstChild,
13157
13417
  PlainSpan9,
13158
13418
  PlainLeaf8,
13159
13419
  PlainNode2,
@@ -14634,6 +14894,34 @@ function isGap(p) {
14634
14894
  return true;
14635
14895
  });
14636
14896
  }
14897
+ function publishesOneNode(p, rr, seen = /* @__PURE__ */ new Set()) {
14898
+ if (seen.has(p)) return true;
14899
+ seen.add(p);
14900
+ const d = p._def;
14901
+ switch (d.tag) {
14902
+ case "node":
14903
+ return true;
14904
+ case "lazy": {
14905
+ let target = winnerForRef(p, rr);
14906
+ if (target === void 0) {
14907
+ try {
14908
+ target = d.thunk();
14909
+ } catch {
14910
+ return false;
14911
+ }
14912
+ }
14913
+ return publishesOneNode(target, rr, seen);
14914
+ }
14915
+ case "choice":
14916
+ return d.parsers.every((a) => publishesOneNode(a, rr, seen));
14917
+ case "grammar":
14918
+ case "withCtx":
14919
+ case "label":
14920
+ return publishesOneNode(d.parser, rr, seen);
14921
+ default:
14922
+ return false;
14923
+ }
14924
+ }
14637
14925
  var Encoder = class {
14638
14926
  code = [];
14639
14927
  k = [];
@@ -15987,7 +16275,8 @@ var Encoder = class {
15987
16275
  }
15988
16276
  case "node": {
15989
16277
  if (d.type === void 0) missingInferredType();
15990
- const child = this.node(d.parser).ip;
16278
+ const late = this.opensLate(d);
16279
+ const child = late ? this.lateBody(d.parser._def) : this.node(d.parser).ip;
15991
16280
  const cstOut = this.settings.hostMode === "cst";
15992
16281
  const noBuildCaptures = d.project === void 0;
15993
16282
  const derivedTrivia = d.build !== void 0 ? buildReadsTrivia(d) : noBuildCaptures;
@@ -16008,13 +16297,19 @@ var Encoder = class {
16008
16297
  // every CST node, so this is load-bearing, not reflection trivia.
16009
16298
  d.tags === void 0 ? -1 : this.constant(d.tags)
16010
16299
  );
16011
- if (matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return body;
16300
+ let run = body;
16301
+ if (late) {
16302
+ const corner = this.code[this.code[child + 2] + 1];
16303
+ if (continuationGate(this.code, this.code[child + 3]) === void 0) this.code[child + 2] = corner;
16304
+ else run = this.emit(OP_CONT, corner, body, this.code[child + 3]);
16305
+ }
16306
+ if (matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return run;
16012
16307
  const fs = this.gateFirstSet(d.parser, d.guarded === true, false);
16013
- if (fs.kind === "any") return body;
16308
+ if (fs.kind === "any") return run;
16014
16309
  const cls = this.charClass(fs);
16015
- if (cls < 0) return body;
16310
+ if (cls < 0) return run;
16016
16311
  const e = deriveExpected(d.parser);
16017
- return this.emit(OP_GATE, cls, body, this.expected(e.length > 0 ? e : [d.parser._tag]));
16312
+ return this.emit(OP_GATE, cls, run, this.expected(e.length > 0 ? e : [d.parser._tag]));
16018
16313
  }
16019
16314
  case "token": {
16020
16315
  const saved = this.activeTrivia;
@@ -16196,6 +16491,29 @@ var Encoder = class {
16196
16491
  throw new UnsupportedConstruct(d.tag);
16197
16492
  }
16198
16493
  }
16494
+ /**
16495
+ * `node(sequence(corner, tail), build, { collapse: true })` with a tail that can take
16496
+ * nothing and a corner that is one node: the frame can open after the corner, only if
16497
+ * the tail can start. Any other node keeps its frame from the start, and so does one
16498
+ * with no reducer, whose host can scope the corner's trivia to its type.
16499
+ */
16500
+ opensLate(d) {
16501
+ if (this.plan !== void 0 || d.collapse !== true || d.build === void 0 || d.trailingTrivia === true) return false;
16502
+ const seq = d.parser._def;
16503
+ return seq.tag === "sequence" && seq.parsers.length === 2 && matchesEmpty(seq.parsers[1], /* @__PURE__ */ new Set(), this.refResolver()) && publishesOneNode(seq.parsers[0], this.refResolver());
16504
+ }
16505
+ /** The body of a late frame: the sequence as written, its corner behind `OP_SEED`. */
16506
+ lateBody(seq) {
16507
+ const seed = this.emit(OP_SEED, this.node(seq.parsers[0]).ip);
16508
+ const tailIp = this.node(seq.parsers[1]).ip;
16509
+ const head = this.emitHead(seq.valueUnused ? OP_SEQV : OP_SEQ, 5);
16510
+ this.code[head + 1] = 2;
16511
+ this.code[head + 2] = seed;
16512
+ this.code[head + 3] = tailIp;
16513
+ this.code[head + 4] = this.followClass(seq.parsers, 0);
16514
+ this.code[head + 5] = this.followClass(seq.parsers, 1);
16515
+ return head;
16516
+ }
16199
16517
  /**
16200
16518
  * Peephole: an `OP_RULE` row is pure indirection — a switch dispatch and a
16201
16519
  * call frame to do nothing but jump. Rewrite every child slot that points at
@@ -16261,6 +16579,10 @@ var Encoder = class {
16261
16579
  return this.code[ip + 4] >= 0 ? [ip + 1, ip + 4] : [ip + 1];
16262
16580
  case OP_STRICT:
16263
16581
  return [ip + 1, ip + 2];
16582
+ case OP_CONT:
16583
+ return [ip + 1, ip + 2, ip + 3];
16584
+ case OP_SEED:
16585
+ return [ip + 1];
16264
16586
  default:
16265
16587
  return [];
16266
16588
  }
@@ -18191,6 +18513,10 @@ function staticWeights(code, entries) {
18191
18513
  kids.length = 0;
18192
18514
  childSlots(code, ip, kids);
18193
18515
  const op = code[ip];
18516
+ if (op === OP_CONT && continuationGate(code, code[ip + 3]) !== void 0) {
18517
+ kids.length = 0;
18518
+ kids.push(code[ip + 1], code[ip + 3]);
18519
+ }
18194
18520
  const scale = op === OP_REP || op === OP_REPV ? LOOP : op === OP_CHOICE || op === OP_DISPATCH ? 1 / Math.max(1, kids.length) : 1;
18195
18521
  for (const k of kids) {
18196
18522
  const kid = code[k] === OP_GAPGATE ? code[k + 1] : k;