parseman 0.60.2 → 0.60.3

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.
package/dist/cli/index.js CHANGED
@@ -3780,7 +3780,7 @@ function mayFail(p, seen = /* @__PURE__ */ new Set()) {
3780
3780
  return true;
3781
3781
  }
3782
3782
  }
3783
- function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set(), triviaActive = true) {
3783
+ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set(), triviaActive = true, throughNodes = false) {
3784
3784
  if (seen.has(p)) return false;
3785
3785
  seen.add(p);
3786
3786
  const d = p._def;
@@ -3805,17 +3805,26 @@ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set(), triviaActiv
3805
3805
  return false;
3806
3806
  // A run's prefixes are probed detached; only its body can capture.
3807
3807
  case "lines":
3808
- return mayLeavePartialCapture(d.body, seen, triviaActive);
3809
- // node() captures into its own private buffers and rolls them back on
3810
- // failure (emitNode restores _ctx.* and never pushes on the !ok path).
3808
+ return mayLeavePartialCapture(d.body, seen, triviaActive, throughNodes);
3809
+ // node() captures its children into a frame of its own and drops it on
3810
+ // failure. The trivia logs (`_triviaLog`, `_rootTriviaLog`) are not part of
3811
+ // that frame: trivia its body scanned before failing stays recorded. With
3812
+ // `throughNodes` (a program that installs trivia somewhere) a node leaves
3813
+ // what its body leaves; without, it leaves nothing.
3811
3814
  case "node":
3812
- return false;
3813
- // choice/firstMatch already roll back each failed arm; on overall failure
3814
- // nothing committed remains.
3815
+ return throughNodes && mayLeavePartialCapture(d.parser, seen, triviaActive, throughNodes);
3816
+ // choice/firstMatch already roll back each failed arm's captures; on overall
3817
+ // failure nothing committed remains. The trivia logs are the exception: a
3818
+ // choice the table lowers as an exclusive dispatch runs its one selected arm
3819
+ // with no mark of its own (`emit-assembly.ts`, `table.exclusive`), so the
3820
+ // rows that arm's trivia scans recorded stay when it fails. With
3821
+ // `throughNodes` a choice leaves what one of its arms leaves, unless
3822
+ // `throughNodes` is the encoder's answer that this choice marks and restores
3823
+ // each arm it enters.
3815
3824
  case "choice":
3816
- return false;
3825
+ return throughNodes !== false && !(typeof throughNodes === "function" && throughNodes(p)) && d.parsers.some((arm) => mayLeavePartialCapture(arm, new Set(seen), triviaActive, throughNodes));
3817
3826
  case "dispatch":
3818
- return capturesLeaf(d.selector, new Set(seen)) || d.cases.some((x) => mayLeavePartialCapture(x.parser, new Set(seen), triviaActive) || capturesLeaf(x.parser, new Set(seen))) || (d.matchers ? d.matchers.some((x) => mayLeavePartialCapture(x.parser, new Set(seen), triviaActive) || capturesLeaf(x.parser, new Set(seen))) : false) || (d.otherwise ? mayLeavePartialCapture(d.otherwise, new Set(seen), triviaActive) || capturesLeaf(d.otherwise, new Set(seen)) : false);
3827
+ return capturesLeaf(d.selector, new Set(seen)) || d.cases.some((x) => mayLeavePartialCapture(x.parser, new Set(seen), triviaActive, throughNodes) || capturesLeaf(x.parser, new Set(seen))) || (d.matchers ? d.matchers.some((x) => mayLeavePartialCapture(x.parser, new Set(seen), triviaActive, throughNodes) || capturesLeaf(x.parser, new Set(seen))) : false) || (d.otherwise ? mayLeavePartialCapture(d.otherwise, new Set(seen), triviaActive, throughNodes) || capturesLeaf(d.otherwise, new Set(seen)) : false);
3819
3828
  case "attempt":
3820
3829
  return false;
3821
3830
  // optional never fails; many/oneOrMore only "fail" with zero captured items.
@@ -3857,7 +3866,7 @@ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set(), triviaActiv
3857
3866
  const part = parts[i];
3858
3867
  if (i > 0 && triviaActive) captured = true;
3859
3868
  if (captured && mayFail(part)) return true;
3860
- if (mayLeavePartialCapture(part, seen, triviaActive)) return true;
3869
+ if (mayLeavePartialCapture(part, seen, triviaActive, throughNodes)) return true;
3861
3870
  if (capturesLeaf(part) || hasNodeDef(part)) captured = true;
3862
3871
  }
3863
3872
  return false;
@@ -3869,12 +3878,12 @@ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set(), triviaActiv
3869
3878
  case "expect":
3870
3879
  case "withCtx":
3871
3880
  case "grammar":
3872
- return mayLeavePartialCapture(d.parser, seen, triviaActive);
3881
+ return mayLeavePartialCapture(d.parser, seen, triviaActive, throughNodes);
3873
3882
  case "recover":
3874
- return mayLeavePartialCapture(d.parser, seen, triviaActive);
3883
+ return mayLeavePartialCapture(d.parser, seen, triviaActive, throughNodes);
3875
3884
  case "lazy": {
3876
3885
  try {
3877
- return mayLeavePartialCapture(d.thunk(), seen, triviaActive);
3886
+ return mayLeavePartialCapture(d.thunk(), seen, triviaActive, throughNodes);
3878
3887
  } catch {
3879
3888
  return true;
3880
3889
  }
@@ -5810,7 +5819,9 @@ function ownTableProgram(prog, resolved, caches = {}) {
5810
5819
  resolved,
5811
5820
  choiceRollbackMasks: caches.choiceRollbackMasks ?? runtime?.choiceRollbackMasks,
5812
5821
  nonCommittingChoiceSites: caches.nonCommittingChoiceSites ?? runtime?.nonCommittingChoiceSites,
5813
- failureRollbackCleanSites: caches.failureRollbackCleanSites ?? runtime?.failureRollbackCleanSites
5822
+ failureRollbackCleanSites: caches.failureRollbackCleanSites ?? runtime?.failureRollbackCleanSites,
5823
+ choiceLogRollbackMasks: caches.choiceLogRollbackMasks ?? runtime?.choiceLogRollbackMasks,
5824
+ failureLogRollbackSites: caches.failureLogRollbackSites ?? runtime?.failureLogRollbackSites
5814
5825
  }
5815
5826
  };
5816
5827
  }
@@ -5823,6 +5834,12 @@ function choiceCannotCommit(prog, ip) {
5823
5834
  function failureRollbackClean(prog, ip) {
5824
5835
  return prog[TABLE_RUNTIME]?.failureRollbackCleanSites?.has(ip) === true;
5825
5836
  }
5837
+ function choiceLogRollbackMask(prog, ip) {
5838
+ return prog[TABLE_RUNTIME]?.choiceLogRollbackMasks?.get(ip) ?? 0;
5839
+ }
5840
+ function failureLogRollback(prog, ip) {
5841
+ return prog[TABLE_RUNTIME]?.failureLogRollbackSites?.has(ip) === true;
5842
+ }
5826
5843
  var WIDE_CLASS_PREFIX_LO = 65535;
5827
5844
  var WIDE_CLASS_PREFIX_HI = 0;
5828
5845
  function validateClassRange(lo, hi) {
@@ -7383,6 +7400,32 @@ var Encoder = class {
7383
7400
  choiceRollbackMasks = /* @__PURE__ */ new Map();
7384
7401
  nonCommittingChoiceSites = /* @__PURE__ */ new Set();
7385
7402
  failureRollbackCleanSites = /* @__PURE__ */ new Set();
7403
+ /**
7404
+ * THE TRIVIA LOGS A FAILED NODE LEAVES. A node drops its own capture frame when
7405
+ * it fails, but the trivia its body recorded into `_triviaLog`/`_rootTriviaLog`
7406
+ * is not part of that frame. So a child the census above counts as clean can
7407
+ * still leave trivia rows when it reaches a node whose body can fail after a
7408
+ * trivia scan (`mayLeavePartialCapture`'s `throughNodes`). These are the arms
7409
+ * and sites that need only the two logs restored. A program with no trivia of
7410
+ * its own records rows only under trivia its caller supplies, so its emitted
7411
+ * assembly takes these marks only for such a parse (`RunCfg.inheritedTrivia`).
7412
+ */
7413
+ choiceLogRollbackMasks = /* @__PURE__ */ new Map();
7414
+ failureLogRollbackSites = /* @__PURE__ */ new Set();
7415
+ /**
7416
+ * HOW EACH CHOICE WAS LOWERED, for the census above. A choice on the ordered
7417
+ * path whose arms cannot commit a failure restores the logs after every arm
7418
+ * it enters (its full mark, or its own two-log mark), so it leaves no rows.
7419
+ * An exclusive dispatch runs its one arm with no mark, and an ordered choice
7420
+ * returns a committed arm's failure before restoring, so either leaves what an
7421
+ * arm leaves. A choice in neither set, or in both, is taken to leave rows. Both
7422
+ * sets are complete only once every rule is encoded, so the trivia-log census
7423
+ * runs then (`logCensus`).
7424
+ */
7425
+ restoringChoices = /* @__PURE__ */ new Set();
7426
+ leakingChoices = /* @__PURE__ */ new Set();
7427
+ logCensus = [];
7428
+ restoresArms = (choice2) => this.restoringChoices.has(choice2) && !this.leakingChoices.has(choice2);
7386
7429
  /**
7387
7430
  * `reachesSideWriter`'s answers, shared by every `failureNeedsRollback` call
7388
7431
  * for the lifetime of this `Encoder`. Every entry is exact — it depends only on
@@ -7957,11 +8000,19 @@ var Encoder = class {
7957
8000
  * not run repeat recovery, but these rows can still publish through a caller's
7958
8001
  * context.
7959
8002
  */
7960
- failureNeedsRollback(p, autoNot) {
8003
+ failureNeedsRollback(p, autoNot, throughNodes) {
7961
8004
  const refName = p._ruleName;
7962
8005
  const winner = refName === void 0 ? void 0 : this.winners?.[refName];
7963
8006
  const root = winner !== void 0 && !winnerWrapsReference2(winner, p) ? winner : p;
7964
- return mayLeavePartialCapture(root, /* @__PURE__ */ new Set(), true) || this.reachesSideWriter(root) || (autoNot?.length ?? 0) > 0 && capturesLeaf(root);
8007
+ return mayLeavePartialCapture(root, /* @__PURE__ */ new Set(), true, throughNodes) || this.reachesSideWriter(root) || (autoNot?.length ?? 0) > 0 && capturesLeaf(root);
8008
+ }
8009
+ /** The rollback census of an `optional()` or `attempt()` row at `ip` over `child`. */
8010
+ censusTransaction(child, ip) {
8011
+ if (this.failureNeedsRollback(child, void 0, false)) return;
8012
+ this.failureRollbackCleanSites.add(ip);
8013
+ this.logCensus.push(() => {
8014
+ if (this.failureNeedsRollback(child, void 0, this.restoresArms)) this.failureLogRollbackSites.add(ip);
8015
+ });
7965
8016
  }
7966
8017
  /**
7967
8018
  * Whether a field, recovered error, interpreted scanner or unresolvable shape
@@ -8583,13 +8634,11 @@ var Encoder = class {
8583
8634
  }
8584
8635
  const dispIdx = this.disp.length;
8585
8636
  this.disp.push(classes);
8637
+ const exclusive = dispatchIsExclusive(classes, this.cc);
8586
8638
  let rollbackMask = kids.length > 31 ? -1 : 0;
8587
8639
  if (rollbackMask === 0) {
8588
8640
  for (let i = 0; i < arms.length; i++) {
8589
- const src = order[i];
8590
- if (this.failureNeedsRollback(arms[i], d.autoNot[src])) {
8591
- rollbackMask |= 1 << i;
8592
- }
8641
+ if (this.failureNeedsRollback(arms[i], d.autoNot[order[i]], false)) rollbackMask |= 1 << i;
8593
8642
  }
8594
8643
  }
8595
8644
  const head = this.emitHead(OP_CHOICE, 3 + 2 * kids.length);
@@ -8601,9 +8650,19 @@ var Encoder = class {
8601
8650
  this.code[head + 4 + kids.length + i] = this.expected(deriveExpected(arms[i]));
8602
8651
  }
8603
8652
  this.choiceRollbackMasks.set(head, rollbackMask);
8604
- if (arms.every((arm) => !mayCommitFailure(arm, rr, this.commitFailureMemo))) {
8605
- this.nonCommittingChoiceSites.add(head);
8653
+ if (rollbackMask !== -1) {
8654
+ const full = rollbackMask;
8655
+ this.logCensus.push(() => {
8656
+ let logMask = 0;
8657
+ for (let i = 0; i < arms.length; i++) {
8658
+ if ((full & 1 << i) === 0 && this.failureNeedsRollback(arms[i], d.autoNot[order[i]], this.restoresArms)) logMask |= 1 << i;
8659
+ }
8660
+ if (logMask !== 0) this.choiceLogRollbackMasks.set(head, logMask);
8661
+ });
8606
8662
  }
8663
+ const nonCommitting = arms.every((arm) => !mayCommitFailure(arm, rr, this.commitFailureMemo));
8664
+ if (nonCommitting) this.nonCommittingChoiceSites.add(head);
8665
+ (!exclusive && nonCommitting ? this.restoringChoices : this.leakingChoices).add(p);
8607
8666
  return head;
8608
8667
  }
8609
8668
  case "many":
@@ -8639,7 +8698,7 @@ var Encoder = class {
8639
8698
  }
8640
8699
  case "optional": {
8641
8700
  const head = this.emit(OP_OPT, this.lookaheadGate(d.parser, this.node(d.parser).ip));
8642
- if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(head);
8701
+ this.censusTransaction(d.parser, head);
8643
8702
  return head;
8644
8703
  }
8645
8704
  case "transform": {
@@ -8810,7 +8869,7 @@ var Encoder = class {
8810
8869
  // lowering was correct only for a choice arm.
8811
8870
  case "attempt": {
8812
8871
  const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip, d.contain === true ? 1 : 0);
8813
- if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
8872
+ this.censusTransaction(d.parser, inner);
8814
8873
  const fs = this.gateFirstSet(d.parser, d.guarded === true, false);
8815
8874
  if (fs.kind === "any" || matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return inner;
8816
8875
  const cls = this.charClass(fs);
@@ -8974,6 +9033,7 @@ var Encoder = class {
8974
9033
  finish() {
8975
9034
  if (this.code.length === 0) this.emit(OP_EMPTY);
8976
9035
  this.collapseIndirection();
9036
+ for (const census of this.logCensus) census();
8977
9037
  return ownTableProgram({
8978
9038
  code: this.code,
8979
9039
  k: this.k,
@@ -8998,6 +9058,8 @@ var Encoder = class {
8998
9058
  }, void 0, {
8999
9059
  choiceRollbackMasks: this.choiceRollbackMasks,
9000
9060
  failureRollbackCleanSites: this.failureRollbackCleanSites,
9061
+ choiceLogRollbackMasks: this.choiceLogRollbackMasks,
9062
+ failureLogRollbackSites: this.failureLogRollbackSites,
9001
9063
  nonCommittingChoiceSites: this.nonCommittingChoiceSites
9002
9064
  });
9003
9065
  }
@@ -10884,6 +10946,13 @@ if(ctx._errors!==undefined&&ctx._errors.length!==${t2}er)ctx._errors.length=${t2
10884
10946
  if (!s.fd && !s.er) return `if(${t2}n)rollbackTriviaAt(ctx,${t2}raw,${t2}tl,${t2}lv,undefined,undefined,${t2}lg,${t2}rt)`;
10885
10947
  return `if(${t2}n){rollbackTriviaAt(ctx,${t2}raw,${t2}tl,${t2}lv,${s.fd ? `${t2}fd` : "undefined"},${s.er ? `${t2}er` : "undefined"},${t2}lg,${t2}rt)}`;
10886
10948
  }
10949
+ function emitLogMark(t2) {
10950
+ return `const ${t2}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0,${t2}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0`;
10951
+ }
10952
+ function emitLogRollback(t2) {
10953
+ return `{const g=ctx._triviaLog;if(g!==undefined)while(g.length>${t2}lg)g.pop()}
10954
+ {const r=ctx._rootTriviaLog;if(r!==undefined)while(r.length>${t2}rt)r.pop()}`;
10955
+ }
10887
10956
  function emitTerm(callee, dst, t2, l, skip, miss) {
10888
10957
  const fast = `const ${t2}v=${callee}(input,cur,ctx)
10889
10958
  if(${t2}v===FAIL)return FAIL
@@ -10967,6 +11036,7 @@ function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false, s
10967
11036
  const { code, k, fx, disp, dsp, triviaLabelled } = t2;
10968
11037
  const swapLegal = !cfg.trackLines;
10969
11038
  const hostCst = cfg.hostCst;
11039
+ const LOGS = (prog.triviaSpecs?.length ?? 0) > 0 || cfg.inheritedTrivia === true;
10970
11040
  const REC = prog.rec === 1 && cfg.tolerant;
10971
11041
  if (cfg.coverage) throw new Unemittable("a coverage assembly");
10972
11042
  const roots = [...Object.values(prog.rules), ...extraIps];
@@ -11735,12 +11805,13 @@ return v
11735
11805
  case OP_ATTEMPT: {
11736
11806
  const child = link(code[ip + 1]);
11737
11807
  const clean = !REC && failureRollbackClean(prog, ip);
11808
+ const logs = clean && LOGS && failureLogRollback(prog, ip);
11738
11809
  const p = tmp();
11739
11810
  return `${head}
11740
- ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
11811
+ ${clean ? logs ? emitLogMark(p) : "" : emitMark(p, L.buf, L.raw, sinks)}
11741
11812
  const v=${child}(input,pos,ctx)
11742
11813
  if(v!==FAIL)return v
11743
- ${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
11814
+ ${clean ? logs ? emitLogRollback(p) : "" : emitRollback(p, L.buf, L.raw, sinks)}
11744
11815
  ${code[ip + 2] === 1 ? "ctx._fc=false" : "if(ctx._fc===true)return FAIL"}
11745
11816
  ctx._fe=pos
11746
11817
  return FAIL
@@ -11766,6 +11837,7 @@ return FAIL
11766
11837
  ${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${emitMark(p, L.buf, L.raw, sinks)}
11767
11838
  ${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
11768
11839
  ${emitRollback(p, L.buf, L.raw, sinks)}
11840
+ ctx._fc=false
11769
11841
  ${cfg.probe ? "if(ctx._probe!==undefined)ctx._probe.best=pb??null\n" : ""}if(v===FAIL){EC.e=pos;return null}
11770
11842
  ctx._fe=pos
11771
11843
  ctx._fx=${xf}
@@ -11790,6 +11862,7 @@ return null
11790
11862
  ${lookaheadMiss(code[ip + 1], `ctx._fe=pos;ctx._fx=${xf};return FAIL`)}${emitMark(p, L.buf, L.raw, sinks)}
11791
11863
  ${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
11792
11864
  ${emitRollback(p, L.buf, L.raw, sinks)}
11865
+ ctx._fc=false
11793
11866
  ${cfg.probe ? "if(ctx._probe!==undefined)ctx._probe.best=pb??null\n" : ""}if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
11794
11867
  EC.e=pos
11795
11868
  return null
@@ -11798,14 +11871,15 @@ return null
11798
11871
  case OP_OPT: {
11799
11872
  const child = link(code[ip + 1]);
11800
11873
  const clean = !REC && failureRollbackClean(prog, ip);
11874
+ const logs = clean && LOGS && failureLogRollback(prog, ip);
11801
11875
  const p = tmp();
11802
11876
  return `${head}
11803
- ${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
11877
+ ${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${clean ? logs ? emitLogMark(p) : "" : emitMark(p, L.buf, L.raw, sinks)}
11804
11878
  ctx._fc=false
11805
11879
  const v=${child}(input,pos,ctx)
11806
11880
  if(v===FAIL){
11807
11881
  if(ctx._fc===true)return FAIL
11808
- ${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
11882
+ ${clean ? logs ? emitLogRollback(p) : "" : emitRollback(p, L.buf, L.raw, sinks)}
11809
11883
  EC.e=pos
11810
11884
  return null
11811
11885
  }
@@ -11955,6 +12029,10 @@ return FAIL
11955
12029
  const encodedRollbackMask = choiceRollbackMask(prog, ip) ?? -1;
11956
12030
  const rollbackMask = REC ? -1 : encodedRollbackMask;
11957
12031
  const hasRollback = rollbackMask !== 0;
12032
+ const logMask = rollbackMask === -1 || !LOGS ? 0 : choiceLogRollbackMask(prog, ip);
12033
+ const choiceMark = hasRollback ? emitMark(p, L.buf, L.raw, sinks) : "";
12034
+ const armMark = (i) => !hasRollback && (logMask & 1 << i) !== 0 ? `${emitLogMark(p)}
12035
+ ` : "";
11958
12036
  const startFailureExact = arms.every((_arm, i) => {
11959
12037
  const terminal = leadingScalarTerminal(code, code[base + i], 0, false);
11960
12038
  if (terminal < 0) return false;
@@ -11966,7 +12044,7 @@ return FAIL
11966
12044
  if (op2 === OP_LIT) return typeof spec === "string" && spec.length > 0;
11967
12045
  return op2 === OP_RX && spec instanceof RegExp && !regexCanMatchEmpty(spec.source);
11968
12046
  });
11969
- const rollbackFor = (i) => rollbackMask === -1 || (rollbackMask & 1 << i) !== 0 ? emitRollback(p, L.buf, L.raw, sinks) : "";
12047
+ const rollbackFor = (i) => rollbackMask === -1 || (rollbackMask & 1 << i) !== 0 ? emitRollback(p, L.buf, L.raw, sinks) : (logMask & 1 << i) === 0 ? "" : hasRollback ? emitRollback(p, L.buf, L.raw, sinks) : emitLogRollback(p);
11970
12048
  if (choiceCannotCommit(prog, ip) && !startFailureExact) {
11971
12049
  const deepAt = Array.from({ length: n }, () => tmp());
11972
12050
  const deepFx = Array.from({ length: n }, () => tmp());
@@ -11992,7 +12070,7 @@ ${remember2(i, "at", pretest.sequence.expected.map((value, at) => `${decision}==
11992
12070
  }`;
11993
12071
  return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
11994
12072
  `}if(${gate}){
11995
- ctx._fc=false
12073
+ ${armMark(i)}ctx._fc=false
11996
12074
  {const v=${arm}(input,pos,ctx)
11997
12075
  if(v!==FAIL)return v}
11998
12076
  {const at=ctx._fe??pos
@@ -12011,7 +12089,7 @@ ctx._fe=pos;ctx._fx=acc??${choiceFx}
12011
12089
  return FAIL`;
12012
12090
  return `${head}
12013
12091
  const c=${directAsciiMask ? "input.charCodeAt(pos)" : "lead(input,pos)"}
12014
- ${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
12092
+ ${choiceMark}
12015
12093
  ${deepAt.map((at, i) => `let ${at},${deepFx[i]}`).join("\n")}
12016
12094
  ${maskable ? `if(c<128){
12017
12095
  const bits=${maskName}[${directAsciiMask ? "c" : "c<0?128:c"}]
@@ -12058,7 +12136,7 @@ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.sequenc
12058
12136
  }`;
12059
12137
  return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
12060
12138
  `}if((bits&${1 << i})!==0${condition}){
12061
- ctx._fc=false
12139
+ ${armMark(i)}ctx._fc=false
12062
12140
  {const v=${arm}(input,pos,ctx)
12063
12141
  if(v!==FAIL)return v}
12064
12142
  ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
@@ -12089,7 +12167,7 @@ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.token.e
12089
12167
  }${startFailureExact ? "" : `else if(best===pos)acc=_accSet(${expected[i]},acc)`}`;
12090
12168
  return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
12091
12169
  `}if((${gateRefs[i]}===null||classHas(${gateRefs[i]},c))${condition}){
12092
- ctx._fc=false
12170
+ ${armMark(i)}ctx._fc=false
12093
12171
  {const v=${arm}(input,pos,ctx)
12094
12172
  if(v!==FAIL)return v}
12095
12173
  {const at=ctx._fe??pos
@@ -12101,7 +12179,7 @@ ${rollbackFor(i)}
12101
12179
  }).join("\n");
12102
12180
  return `${head}
12103
12181
  const c=${directAsciiMask ? "input.charCodeAt(pos)" : "lead(input,pos)"}
12104
- ${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
12182
+ ${choiceMark}
12105
12183
  let acc
12106
12184
  let best=pos
12107
12185
  ${maskable ? `if(c<128){
@@ -13337,7 +13415,7 @@ function clearOf(ranges, input, from, to) {
13337
13415
  }
13338
13416
 
13339
13417
  // src/version.ts
13340
- var PARSEMAN_VERSION = "0.60.2";
13418
+ var PARSEMAN_VERSION = "0.60.3";
13341
13419
 
13342
13420
  // src/table/assemble.ts
13343
13421
  import { PlainBuf as PlainBuf2, PlainField, PlainLeaf as PlainLeaf9, PlainNode as PlainNode2, PlainSpan as PlainSpan10 } from "../cst/plain.js";
@@ -13592,11 +13670,11 @@ function linkMatcher(m) {
13592
13670
  }
13593
13671
  var NO_COVERAGE = (_id) => {
13594
13672
  };
13595
- function cfgKeyOf(hostCst, trackLines, tolerant, coverage, probe, hostReadsChildren = true) {
13596
- return (hostCst ? 1 : 0) | (trackLines ? 2 : 0) | (tolerant ? 4 : 0) | (coverage ? 8 : 0) | (probe ? 16 : 0) | (hostReadsChildren ? 0 : 32);
13673
+ function cfgKeyOf(hostCst, trackLines, tolerant, coverage, probe, hostReadsChildren = true, inheritedTrivia = false) {
13674
+ return (hostCst ? 1 : 0) | (trackLines ? 2 : 0) | (tolerant ? 4 : 0) | (coverage ? 8 : 0) | (probe ? 16 : 0) | (hostReadsChildren ? 0 : 32) | (inheritedTrivia ? 64 : 0);
13597
13675
  }
13598
13676
  function cfgKey(c) {
13599
- return cfgKeyOf(c.hostCst, c.trackLines, c.tolerant, c.coverage, c.probe, c.hostReadsChildren);
13677
+ return cfgKeyOf(c.hostCst, c.trackLines, c.tolerant, c.coverage, c.probe, c.hostReadsChildren, c.inheritedTrivia);
13600
13678
  }
13601
13679
  function assertFactoryArity(pre) {
13602
13680
  if (pre.arity === EMITTED_PARAMS.length) return;
@@ -14971,6 +15049,7 @@ function assemble(t2, prog, cfg) {
14971
15049
  const probeBest = PROBE ? ctx._probe?.best : void 0;
14972
15050
  const v = child(input, pos, ctx);
14973
15051
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
15052
+ ctx._fc = false;
14974
15053
  if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
14975
15054
  if (v === FAIL) {
14976
15055
  EC.e = pos;
@@ -15016,6 +15095,7 @@ function assemble(t2, prog, cfg) {
15016
15095
  const probeBest = PROBE ? ctx._probe?.best : void 0;
15017
15096
  const v = child(input, pos, ctx);
15018
15097
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
15098
+ ctx._fc = false;
15019
15099
  if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
15020
15100
  if (v === FAIL) {
15021
15101
  ctx._fe = pos;
@@ -16874,7 +16954,7 @@ function assemble(t2, prog, cfg) {
16874
16954
  if (emitted !== void 0) throw new ServedByBuild();
16875
16955
  if (prog.asm !== void 0) {
16876
16956
  throw new Unemittable(
16877
- `option set ${cfgKey(cfg)} (hostCst=${cfg.hostCst} trackLines=${cfg.trackLines} tolerant=${cfg.tolerant} coverage=${cfg.coverage} probe=${cfg.probe}), which this build did not pre-compile. The Function constructor is NOT used for an artifact that carries assemblies \u2014 see \`EmitOptions.assemblies\` to add this option set to the build`
16957
+ `option set ${cfgKey(cfg)} (hostCst=${cfg.hostCst} trackLines=${cfg.trackLines} tolerant=${cfg.tolerant} coverage=${cfg.coverage} probe=${cfg.probe} inheritedTrivia=${cfg.inheritedTrivia === true}), which this build did not pre-compile. The Function constructor is NOT used for an artifact that carries assemblies \u2014 see \`EmitOptions.assemblies\` to add this option set to the build`
16878
16958
  );
16879
16959
  }
16880
16960
  if (!EMIT_ENABLED) throw new Unemittable("PM_TABLE_EMIT=0 (measurement toggle)");
@@ -17073,7 +17153,9 @@ function countedPiece(piece, ip) {
17073
17153
  var AssemblyCache = class {
17074
17154
  t;
17075
17155
  prog;
17076
- byCfg = Array.from({ length: 64 });
17156
+ byCfg = Array.from({ length: 128 });
17157
+ /** Whether this program installs no trivia of its own (`RunCfg.inheritedTrivia`). */
17158
+ noOwnTrivia;
17077
17159
  /**
17078
17160
  * Monomorphic predicate inline cache. An assembly depends on the predicate
17079
17161
  * FUNCTION and the scalar cfg key, not on the host object that carries it, so
@@ -17086,6 +17168,7 @@ var AssemblyCache = class {
17086
17168
  constructor(prog, resolved = resolveTable(prog)) {
17087
17169
  this.prog = prog;
17088
17170
  this.t = resolved;
17171
+ this.noOwnTrivia = prog.triviaSpecs === void 0 || prog.triviaSpecs.length === 0;
17089
17172
  }
17090
17173
  for(cfg) {
17091
17174
  const key = cfgKey(cfg);
@@ -17149,13 +17232,14 @@ var AssemblyCache = class {
17149
17232
  const tolerant = ctx._tolerant === true;
17150
17233
  const coverage = ctx._grammarCoverage !== void 0;
17151
17234
  const probe = ctx._probe !== void 0;
17152
- const key = cfgKeyOf(hostCst, trackLines, tolerant, coverage, probe, hostReadsChildren);
17235
+ const inheritedTrivia = this.noOwnTrivia && ctx.trivia !== void 0;
17236
+ const key = cfgKeyOf(hostCst, trackLines, tolerant, coverage, probe, hostReadsChildren, inheritedTrivia);
17153
17237
  let cache = this.byCfg;
17154
17238
  if (hostCaptureTrivia !== void 0) {
17155
17239
  if (this.hostPredicate === hostCaptureTrivia) {
17156
17240
  cache = this.hostAssemblies;
17157
17241
  } else {
17158
- cache = Array.from({ length: 64 });
17242
+ cache = Array.from({ length: 128 });
17159
17243
  this.hostPredicate = hostCaptureTrivia;
17160
17244
  this.hostAssemblies = cache;
17161
17245
  }
@@ -17169,7 +17253,8 @@ var AssemblyCache = class {
17169
17253
  trackLines,
17170
17254
  tolerant,
17171
17255
  coverage,
17172
- probe
17256
+ probe,
17257
+ inheritedTrivia
17173
17258
  });
17174
17259
  cache[key] = made;
17175
17260
  return made;