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.
@@ -79,7 +79,7 @@ export declare function alwaysConsumes(p: Combinator<unknown>, seen?: Set<Combin
79
79
  * internally. optional/many never "fail" with partial output. Delegating
80
80
  * wrappers (transform/label/grammar/withCtx/expect) pass through to inner.
81
81
  */
82
- export declare function mayLeavePartialCapture(p: Combinator<unknown>, seen?: Set<Combinator<unknown>>, triviaActive?: boolean): boolean;
82
+ export declare function mayLeavePartialCapture(p: Combinator<unknown>, seen?: Set<Combinator<unknown>>, triviaActive?: boolean, throughNodes?: boolean | ((choice: Combinator<unknown>) => boolean)): boolean;
83
83
  /** True when `p` can push a leaf/node into the capture buffers on success. */
84
84
  export declare function capturesLeaf(p: Combinator<unknown>, seen?: Set<Combinator<unknown>>): boolean;
85
85
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"commitment.d.ts","sourceRoot":"","sources":["../../src/analysis/commitment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,aAAa,CAAA;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAI9D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAqCnG;AAkCD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAiC1G;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,EAAE,YAAY,UAAO,GAAG,OAAO,CA4GvI;AAED,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAsDxG;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAiCtG;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAsC7G;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EACtB,OAAO,CAAC,EAAE,WAAW,EACrB,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,OAAO,CAAa,GAClD,OAAO,CAET;AAyDD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAC7B,IAAI,EAAE,CAAC,EACP,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,SAAS,CAAC,EAAE,GAAG,IAAI,EAC5C,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,GACpB,OAAO,CAkDT;AAwCD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,GAC7D;IAAE,iBAAiB,EAAE,OAAO,CAAC;IAAC,iBAAiB,EAAE,OAAO,CAAA;CAAE,CAwB5D"}
1
+ {"version":3,"file":"commitment.d.ts","sourceRoot":"","sources":["../../src/analysis/commitment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,aAAa,CAAA;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAI9D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAqCnG;AAkCD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAiC1G;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CACpC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,EAAE,YAAY,UAAO,EACvF,YAAY,GAAE,OAAO,GAAG,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,KAAK,OAAO,CAAS,GACzE,OAAO,CAuHT;AAED,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAsDxG;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAiCtG;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAsC7G;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EACtB,OAAO,CAAC,EAAE,WAAW,EACrB,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,OAAO,CAAa,GAClD,OAAO,CAET;AAyDD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAC7B,IAAI,EAAE,CAAC,EACP,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,SAAS,CAAC,EAAE,GAAG,IAAI,EAC5C,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,GACpB,OAAO,CAkDT;AAwCD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,GAC7D;IAAE,iBAAiB,EAAE,OAAO,CAAC;IAAC,iBAAiB,EAAE,OAAO,CAAA;CAAE,CAwB5D"}
@@ -4718,7 +4718,9 @@ function ownTableProgram(prog, resolved, caches = {}) {
4718
4718
  resolved,
4719
4719
  choiceRollbackMasks: caches.choiceRollbackMasks ?? runtime?.choiceRollbackMasks,
4720
4720
  nonCommittingChoiceSites: caches.nonCommittingChoiceSites ?? runtime?.nonCommittingChoiceSites,
4721
- failureRollbackCleanSites: caches.failureRollbackCleanSites ?? runtime?.failureRollbackCleanSites
4721
+ failureRollbackCleanSites: caches.failureRollbackCleanSites ?? runtime?.failureRollbackCleanSites,
4722
+ choiceLogRollbackMasks: caches.choiceLogRollbackMasks ?? runtime?.choiceLogRollbackMasks,
4723
+ failureLogRollbackSites: caches.failureLogRollbackSites ?? runtime?.failureLogRollbackSites
4722
4724
  }
4723
4725
  };
4724
4726
  }
@@ -4731,6 +4733,12 @@ function choiceCannotCommit(prog, ip) {
4731
4733
  function failureRollbackClean(prog, ip) {
4732
4734
  return prog[TABLE_RUNTIME]?.failureRollbackCleanSites?.has(ip) === true;
4733
4735
  }
4736
+ function choiceLogRollbackMask(prog, ip) {
4737
+ return prog[TABLE_RUNTIME]?.choiceLogRollbackMasks?.get(ip) ?? 0;
4738
+ }
4739
+ function failureLogRollback(prog, ip) {
4740
+ return prog[TABLE_RUNTIME]?.failureLogRollbackSites?.has(ip) === true;
4741
+ }
4734
4742
  var WIDE_CLASS_PREFIX_LO = 65535;
4735
4743
  var WIDE_CLASS_PREFIX_HI = 0;
4736
4744
  function validateClassRange(lo, hi) {
@@ -5935,7 +5943,7 @@ function mayFail(p, seen = /* @__PURE__ */ new Set()) {
5935
5943
  return true;
5936
5944
  }
5937
5945
  }
5938
- function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set(), triviaActive = true) {
5946
+ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set(), triviaActive = true, throughNodes = false) {
5939
5947
  if (seen.has(p)) return false;
5940
5948
  seen.add(p);
5941
5949
  const d = p._def;
@@ -5960,17 +5968,26 @@ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set(), triviaActiv
5960
5968
  return false;
5961
5969
  // A run's prefixes are probed detached; only its body can capture.
5962
5970
  case "lines":
5963
- return mayLeavePartialCapture(d.body, seen, triviaActive);
5964
- // node() captures into its own private buffers and rolls them back on
5965
- // failure (emitNode restores _ctx.* and never pushes on the !ok path).
5971
+ return mayLeavePartialCapture(d.body, seen, triviaActive, throughNodes);
5972
+ // node() captures its children into a frame of its own and drops it on
5973
+ // failure. The trivia logs (`_triviaLog`, `_rootTriviaLog`) are not part of
5974
+ // that frame: trivia its body scanned before failing stays recorded. With
5975
+ // `throughNodes` (a program that installs trivia somewhere) a node leaves
5976
+ // what its body leaves; without, it leaves nothing.
5966
5977
  case "node":
5967
- return false;
5968
- // choice/firstMatch already roll back each failed arm; on overall failure
5969
- // nothing committed remains.
5978
+ return throughNodes && mayLeavePartialCapture(d.parser, seen, triviaActive, throughNodes);
5979
+ // choice/firstMatch already roll back each failed arm's captures; on overall
5980
+ // failure nothing committed remains. The trivia logs are the exception: a
5981
+ // choice the table lowers as an exclusive dispatch runs its one selected arm
5982
+ // with no mark of its own (`emit-assembly.ts`, `table.exclusive`), so the
5983
+ // rows that arm's trivia scans recorded stay when it fails. With
5984
+ // `throughNodes` a choice leaves what one of its arms leaves, unless
5985
+ // `throughNodes` is the encoder's answer that this choice marks and restores
5986
+ // each arm it enters.
5970
5987
  case "choice":
5971
- return false;
5988
+ return throughNodes !== false && !(typeof throughNodes === "function" && throughNodes(p)) && d.parsers.some((arm) => mayLeavePartialCapture(arm, new Set(seen), triviaActive, throughNodes));
5972
5989
  case "dispatch":
5973
- 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);
5990
+ 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);
5974
5991
  case "attempt":
5975
5992
  return false;
5976
5993
  // optional never fails; many/oneOrMore only "fail" with zero captured items.
@@ -6012,7 +6029,7 @@ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set(), triviaActiv
6012
6029
  const part = parts[i];
6013
6030
  if (i > 0 && triviaActive) captured = true;
6014
6031
  if (captured && mayFail(part)) return true;
6015
- if (mayLeavePartialCapture(part, seen, triviaActive)) return true;
6032
+ if (mayLeavePartialCapture(part, seen, triviaActive, throughNodes)) return true;
6016
6033
  if (capturesLeaf(part) || hasNodeDef(part)) captured = true;
6017
6034
  }
6018
6035
  return false;
@@ -6024,12 +6041,12 @@ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set(), triviaActiv
6024
6041
  case "expect":
6025
6042
  case "withCtx":
6026
6043
  case "grammar":
6027
- return mayLeavePartialCapture(d.parser, seen, triviaActive);
6044
+ return mayLeavePartialCapture(d.parser, seen, triviaActive, throughNodes);
6028
6045
  case "recover":
6029
- return mayLeavePartialCapture(d.parser, seen, triviaActive);
6046
+ return mayLeavePartialCapture(d.parser, seen, triviaActive, throughNodes);
6030
6047
  case "lazy": {
6031
6048
  try {
6032
- return mayLeavePartialCapture(d.thunk(), seen, triviaActive);
6049
+ return mayLeavePartialCapture(d.thunk(), seen, triviaActive, throughNodes);
6033
6050
  } catch {
6034
6051
  return true;
6035
6052
  }
@@ -7238,6 +7255,32 @@ var Encoder = class {
7238
7255
  choiceRollbackMasks = /* @__PURE__ */ new Map();
7239
7256
  nonCommittingChoiceSites = /* @__PURE__ */ new Set();
7240
7257
  failureRollbackCleanSites = /* @__PURE__ */ new Set();
7258
+ /**
7259
+ * THE TRIVIA LOGS A FAILED NODE LEAVES. A node drops its own capture frame when
7260
+ * it fails, but the trivia its body recorded into `_triviaLog`/`_rootTriviaLog`
7261
+ * is not part of that frame. So a child the census above counts as clean can
7262
+ * still leave trivia rows when it reaches a node whose body can fail after a
7263
+ * trivia scan (`mayLeavePartialCapture`'s `throughNodes`). These are the arms
7264
+ * and sites that need only the two logs restored. A program with no trivia of
7265
+ * its own records rows only under trivia its caller supplies, so its emitted
7266
+ * assembly takes these marks only for such a parse (`RunCfg.inheritedTrivia`).
7267
+ */
7268
+ choiceLogRollbackMasks = /* @__PURE__ */ new Map();
7269
+ failureLogRollbackSites = /* @__PURE__ */ new Set();
7270
+ /**
7271
+ * HOW EACH CHOICE WAS LOWERED, for the census above. A choice on the ordered
7272
+ * path whose arms cannot commit a failure restores the logs after every arm
7273
+ * it enters (its full mark, or its own two-log mark), so it leaves no rows.
7274
+ * An exclusive dispatch runs its one arm with no mark, and an ordered choice
7275
+ * returns a committed arm's failure before restoring, so either leaves what an
7276
+ * arm leaves. A choice in neither set, or in both, is taken to leave rows. Both
7277
+ * sets are complete only once every rule is encoded, so the trivia-log census
7278
+ * runs then (`logCensus`).
7279
+ */
7280
+ restoringChoices = /* @__PURE__ */ new Set();
7281
+ leakingChoices = /* @__PURE__ */ new Set();
7282
+ logCensus = [];
7283
+ restoresArms = (choice2) => this.restoringChoices.has(choice2) && !this.leakingChoices.has(choice2);
7241
7284
  /**
7242
7285
  * `reachesSideWriter`'s answers, shared by every `failureNeedsRollback` call
7243
7286
  * for the lifetime of this `Encoder`. Every entry is exact — it depends only on
@@ -7812,11 +7855,19 @@ var Encoder = class {
7812
7855
  * not run repeat recovery, but these rows can still publish through a caller's
7813
7856
  * context.
7814
7857
  */
7815
- failureNeedsRollback(p, autoNot) {
7858
+ failureNeedsRollback(p, autoNot, throughNodes) {
7816
7859
  const refName = p._ruleName;
7817
7860
  const winner = refName === void 0 ? void 0 : this.winners?.[refName];
7818
7861
  const root = winner !== void 0 && !winnerWrapsReference2(winner, p) ? winner : p;
7819
- return mayLeavePartialCapture(root, /* @__PURE__ */ new Set(), true) || this.reachesSideWriter(root) || (autoNot?.length ?? 0) > 0 && capturesLeaf(root);
7862
+ return mayLeavePartialCapture(root, /* @__PURE__ */ new Set(), true, throughNodes) || this.reachesSideWriter(root) || (autoNot?.length ?? 0) > 0 && capturesLeaf(root);
7863
+ }
7864
+ /** The rollback census of an `optional()` or `attempt()` row at `ip` over `child`. */
7865
+ censusTransaction(child, ip) {
7866
+ if (this.failureNeedsRollback(child, void 0, false)) return;
7867
+ this.failureRollbackCleanSites.add(ip);
7868
+ this.logCensus.push(() => {
7869
+ if (this.failureNeedsRollback(child, void 0, this.restoresArms)) this.failureLogRollbackSites.add(ip);
7870
+ });
7820
7871
  }
7821
7872
  /**
7822
7873
  * Whether a field, recovered error, interpreted scanner or unresolvable shape
@@ -8438,13 +8489,11 @@ var Encoder = class {
8438
8489
  }
8439
8490
  const dispIdx = this.disp.length;
8440
8491
  this.disp.push(classes);
8492
+ const exclusive = dispatchIsExclusive(classes, this.cc);
8441
8493
  let rollbackMask = kids.length > 31 ? -1 : 0;
8442
8494
  if (rollbackMask === 0) {
8443
8495
  for (let i = 0; i < arms.length; i++) {
8444
- const src = order[i];
8445
- if (this.failureNeedsRollback(arms[i], d.autoNot[src])) {
8446
- rollbackMask |= 1 << i;
8447
- }
8496
+ if (this.failureNeedsRollback(arms[i], d.autoNot[order[i]], false)) rollbackMask |= 1 << i;
8448
8497
  }
8449
8498
  }
8450
8499
  const head = this.emitHead(OP_CHOICE, 3 + 2 * kids.length);
@@ -8456,9 +8505,19 @@ var Encoder = class {
8456
8505
  this.code[head + 4 + kids.length + i] = this.expected(deriveExpected(arms[i]));
8457
8506
  }
8458
8507
  this.choiceRollbackMasks.set(head, rollbackMask);
8459
- if (arms.every((arm) => !mayCommitFailure(arm, rr, this.commitFailureMemo))) {
8460
- this.nonCommittingChoiceSites.add(head);
8508
+ if (rollbackMask !== -1) {
8509
+ const full = rollbackMask;
8510
+ this.logCensus.push(() => {
8511
+ let logMask = 0;
8512
+ for (let i = 0; i < arms.length; i++) {
8513
+ if ((full & 1 << i) === 0 && this.failureNeedsRollback(arms[i], d.autoNot[order[i]], this.restoresArms)) logMask |= 1 << i;
8514
+ }
8515
+ if (logMask !== 0) this.choiceLogRollbackMasks.set(head, logMask);
8516
+ });
8461
8517
  }
8518
+ const nonCommitting = arms.every((arm) => !mayCommitFailure(arm, rr, this.commitFailureMemo));
8519
+ if (nonCommitting) this.nonCommittingChoiceSites.add(head);
8520
+ (!exclusive && nonCommitting ? this.restoringChoices : this.leakingChoices).add(p);
8462
8521
  return head;
8463
8522
  }
8464
8523
  case "many":
@@ -8494,7 +8553,7 @@ var Encoder = class {
8494
8553
  }
8495
8554
  case "optional": {
8496
8555
  const head = this.emit(OP_OPT, this.lookaheadGate(d.parser, this.node(d.parser).ip));
8497
- if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(head);
8556
+ this.censusTransaction(d.parser, head);
8498
8557
  return head;
8499
8558
  }
8500
8559
  case "transform": {
@@ -8665,7 +8724,7 @@ var Encoder = class {
8665
8724
  // lowering was correct only for a choice arm.
8666
8725
  case "attempt": {
8667
8726
  const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip, d.contain === true ? 1 : 0);
8668
- if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
8727
+ this.censusTransaction(d.parser, inner);
8669
8728
  const fs = this.gateFirstSet(d.parser, d.guarded === true, false);
8670
8729
  if (fs.kind === "any" || matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return inner;
8671
8730
  const cls = this.charClass(fs);
@@ -8829,6 +8888,7 @@ var Encoder = class {
8829
8888
  finish() {
8830
8889
  if (this.code.length === 0) this.emit(OP_EMPTY);
8831
8890
  this.collapseIndirection();
8891
+ for (const census of this.logCensus) census();
8832
8892
  return ownTableProgram({
8833
8893
  code: this.code,
8834
8894
  k: this.k,
@@ -8853,6 +8913,8 @@ var Encoder = class {
8853
8913
  }, void 0, {
8854
8914
  choiceRollbackMasks: this.choiceRollbackMasks,
8855
8915
  failureRollbackCleanSites: this.failureRollbackCleanSites,
8916
+ choiceLogRollbackMasks: this.choiceLogRollbackMasks,
8917
+ failureLogRollbackSites: this.failureLogRollbackSites,
8856
8918
  nonCommittingChoiceSites: this.nonCommittingChoiceSites
8857
8919
  });
8858
8920
  }
@@ -10739,6 +10801,13 @@ if(ctx._errors!==undefined&&ctx._errors.length!==${t2}er)ctx._errors.length=${t2
10739
10801
  if (!s.fd && !s.er) return `if(${t2}n)rollbackTriviaAt(ctx,${t2}raw,${t2}tl,${t2}lv,undefined,undefined,${t2}lg,${t2}rt)`;
10740
10802
  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)}`;
10741
10803
  }
10804
+ function emitLogMark(t2) {
10805
+ return `const ${t2}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0,${t2}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0`;
10806
+ }
10807
+ function emitLogRollback(t2) {
10808
+ return `{const g=ctx._triviaLog;if(g!==undefined)while(g.length>${t2}lg)g.pop()}
10809
+ {const r=ctx._rootTriviaLog;if(r!==undefined)while(r.length>${t2}rt)r.pop()}`;
10810
+ }
10742
10811
  function emitTerm(callee, dst, t2, l, skip, miss) {
10743
10812
  const fast = `const ${t2}v=${callee}(input,cur,ctx)
10744
10813
  if(${t2}v===FAIL)return FAIL
@@ -10822,6 +10891,7 @@ function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false, s
10822
10891
  const { code, k, fx, disp, dsp, triviaLabelled } = t2;
10823
10892
  const swapLegal = !cfg.trackLines;
10824
10893
  const hostCst = cfg.hostCst;
10894
+ const LOGS = (prog.triviaSpecs?.length ?? 0) > 0 || cfg.inheritedTrivia === true;
10825
10895
  const REC = prog.rec === 1 && cfg.tolerant;
10826
10896
  if (cfg.coverage) throw new Unemittable("a coverage assembly");
10827
10897
  const roots = [...Object.values(prog.rules), ...extraIps];
@@ -11590,12 +11660,13 @@ return v
11590
11660
  case OP_ATTEMPT: {
11591
11661
  const child = link(code[ip + 1]);
11592
11662
  const clean = !REC && failureRollbackClean(prog, ip);
11663
+ const logs = clean && LOGS && failureLogRollback(prog, ip);
11593
11664
  const p = tmp();
11594
11665
  return `${head}
11595
- ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
11666
+ ${clean ? logs ? emitLogMark(p) : "" : emitMark(p, L.buf, L.raw, sinks)}
11596
11667
  const v=${child}(input,pos,ctx)
11597
11668
  if(v!==FAIL)return v
11598
- ${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
11669
+ ${clean ? logs ? emitLogRollback(p) : "" : emitRollback(p, L.buf, L.raw, sinks)}
11599
11670
  ${code[ip + 2] === 1 ? "ctx._fc=false" : "if(ctx._fc===true)return FAIL"}
11600
11671
  ctx._fe=pos
11601
11672
  return FAIL
@@ -11621,6 +11692,7 @@ return FAIL
11621
11692
  ${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${emitMark(p, L.buf, L.raw, sinks)}
11622
11693
  ${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
11623
11694
  ${emitRollback(p, L.buf, L.raw, sinks)}
11695
+ ctx._fc=false
11624
11696
  ${cfg.probe ? "if(ctx._probe!==undefined)ctx._probe.best=pb??null\n" : ""}if(v===FAIL){EC.e=pos;return null}
11625
11697
  ctx._fe=pos
11626
11698
  ctx._fx=${xf}
@@ -11645,6 +11717,7 @@ return null
11645
11717
  ${lookaheadMiss(code[ip + 1], `ctx._fe=pos;ctx._fx=${xf};return FAIL`)}${emitMark(p, L.buf, L.raw, sinks)}
11646
11718
  ${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
11647
11719
  ${emitRollback(p, L.buf, L.raw, sinks)}
11720
+ ctx._fc=false
11648
11721
  ${cfg.probe ? "if(ctx._probe!==undefined)ctx._probe.best=pb??null\n" : ""}if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
11649
11722
  EC.e=pos
11650
11723
  return null
@@ -11653,14 +11726,15 @@ return null
11653
11726
  case OP_OPT: {
11654
11727
  const child = link(code[ip + 1]);
11655
11728
  const clean = !REC && failureRollbackClean(prog, ip);
11729
+ const logs = clean && LOGS && failureLogRollback(prog, ip);
11656
11730
  const p = tmp();
11657
11731
  return `${head}
11658
- ${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
11732
+ ${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${clean ? logs ? emitLogMark(p) : "" : emitMark(p, L.buf, L.raw, sinks)}
11659
11733
  ctx._fc=false
11660
11734
  const v=${child}(input,pos,ctx)
11661
11735
  if(v===FAIL){
11662
11736
  if(ctx._fc===true)return FAIL
11663
- ${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
11737
+ ${clean ? logs ? emitLogRollback(p) : "" : emitRollback(p, L.buf, L.raw, sinks)}
11664
11738
  EC.e=pos
11665
11739
  return null
11666
11740
  }
@@ -11810,6 +11884,10 @@ return FAIL
11810
11884
  const encodedRollbackMask = choiceRollbackMask(prog, ip) ?? -1;
11811
11885
  const rollbackMask = REC ? -1 : encodedRollbackMask;
11812
11886
  const hasRollback = rollbackMask !== 0;
11887
+ const logMask = rollbackMask === -1 || !LOGS ? 0 : choiceLogRollbackMask(prog, ip);
11888
+ const choiceMark = hasRollback ? emitMark(p, L.buf, L.raw, sinks) : "";
11889
+ const armMark = (i) => !hasRollback && (logMask & 1 << i) !== 0 ? `${emitLogMark(p)}
11890
+ ` : "";
11813
11891
  const startFailureExact = arms.every((_arm, i) => {
11814
11892
  const terminal = leadingScalarTerminal(code, code[base + i], 0, false);
11815
11893
  if (terminal < 0) return false;
@@ -11821,7 +11899,7 @@ return FAIL
11821
11899
  if (op2 === OP_LIT) return typeof spec === "string" && spec.length > 0;
11822
11900
  return op2 === OP_RX && spec instanceof RegExp && !regexCanMatchEmpty(spec.source);
11823
11901
  });
11824
- const rollbackFor = (i) => rollbackMask === -1 || (rollbackMask & 1 << i) !== 0 ? emitRollback(p, L.buf, L.raw, sinks) : "";
11902
+ 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);
11825
11903
  if (choiceCannotCommit(prog, ip) && !startFailureExact) {
11826
11904
  const deepAt = Array.from({ length: n }, () => tmp());
11827
11905
  const deepFx = Array.from({ length: n }, () => tmp());
@@ -11847,7 +11925,7 @@ ${remember2(i, "at", pretest.sequence.expected.map((value, at) => `${decision}==
11847
11925
  }`;
11848
11926
  return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
11849
11927
  `}if(${gate}){
11850
- ctx._fc=false
11928
+ ${armMark(i)}ctx._fc=false
11851
11929
  {const v=${arm}(input,pos,ctx)
11852
11930
  if(v!==FAIL)return v}
11853
11931
  {const at=ctx._fe??pos
@@ -11866,7 +11944,7 @@ ctx._fe=pos;ctx._fx=acc??${choiceFx}
11866
11944
  return FAIL`;
11867
11945
  return `${head}
11868
11946
  const c=${directAsciiMask ? "input.charCodeAt(pos)" : "lead(input,pos)"}
11869
- ${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
11947
+ ${choiceMark}
11870
11948
  ${deepAt.map((at, i) => `let ${at},${deepFx[i]}`).join("\n")}
11871
11949
  ${maskable ? `if(c<128){
11872
11950
  const bits=${maskName}[${directAsciiMask ? "c" : "c<0?128:c"}]
@@ -11913,7 +11991,7 @@ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.sequenc
11913
11991
  }`;
11914
11992
  return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
11915
11993
  `}if((bits&${1 << i})!==0${condition}){
11916
- ctx._fc=false
11994
+ ${armMark(i)}ctx._fc=false
11917
11995
  {const v=${arm}(input,pos,ctx)
11918
11996
  if(v!==FAIL)return v}
11919
11997
  ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
@@ -11944,7 +12022,7 @@ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.token.e
11944
12022
  }${startFailureExact ? "" : `else if(best===pos)acc=_accSet(${expected[i]},acc)`}`;
11945
12023
  return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
11946
12024
  `}if((${gateRefs[i]}===null||classHas(${gateRefs[i]},c))${condition}){
11947
- ctx._fc=false
12025
+ ${armMark(i)}ctx._fc=false
11948
12026
  {const v=${arm}(input,pos,ctx)
11949
12027
  if(v!==FAIL)return v}
11950
12028
  {const at=ctx._fe??pos
@@ -11956,7 +12034,7 @@ ${rollbackFor(i)}
11956
12034
  }).join("\n");
11957
12035
  return `${head}
11958
12036
  const c=${directAsciiMask ? "input.charCodeAt(pos)" : "lead(input,pos)"}
11959
- ${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
12037
+ ${choiceMark}
11960
12038
  let acc
11961
12039
  let best=pos
11962
12040
  ${maskable ? `if(c<128){
@@ -13192,7 +13270,7 @@ function clearOf(ranges, input, from, to) {
13192
13270
  }
13193
13271
 
13194
13272
  // src/version.ts
13195
- var PARSEMAN_VERSION = "0.60.2";
13273
+ var PARSEMAN_VERSION = "0.60.3";
13196
13274
 
13197
13275
  // src/table/assemble.ts
13198
13276
  import { PlainBuf as PlainBuf2, PlainField, PlainLeaf as PlainLeaf9, PlainNode as PlainNode2, PlainSpan as PlainSpan10 } from "../cst/plain.js";
@@ -13451,11 +13529,11 @@ function linkMatcher(m) {
13451
13529
  }
13452
13530
  var NO_COVERAGE = (_id) => {
13453
13531
  };
13454
- function cfgKeyOf(hostCst, trackLines, tolerant, coverage, probe, hostReadsChildren = true) {
13455
- return (hostCst ? 1 : 0) | (trackLines ? 2 : 0) | (tolerant ? 4 : 0) | (coverage ? 8 : 0) | (probe ? 16 : 0) | (hostReadsChildren ? 0 : 32);
13532
+ function cfgKeyOf(hostCst, trackLines, tolerant, coverage, probe, hostReadsChildren = true, inheritedTrivia = false) {
13533
+ return (hostCst ? 1 : 0) | (trackLines ? 2 : 0) | (tolerant ? 4 : 0) | (coverage ? 8 : 0) | (probe ? 16 : 0) | (hostReadsChildren ? 0 : 32) | (inheritedTrivia ? 64 : 0);
13456
13534
  }
13457
13535
  function cfgKey(c) {
13458
- return cfgKeyOf(c.hostCst, c.trackLines, c.tolerant, c.coverage, c.probe, c.hostReadsChildren);
13536
+ return cfgKeyOf(c.hostCst, c.trackLines, c.tolerant, c.coverage, c.probe, c.hostReadsChildren, c.inheritedTrivia);
13459
13537
  }
13460
13538
  function assertFactoryArity(pre) {
13461
13539
  if (pre.arity === EMITTED_PARAMS.length) return;
@@ -14830,6 +14908,7 @@ function assemble(t2, prog, cfg) {
14830
14908
  const probeBest = PROBE ? ctx._probe?.best : void 0;
14831
14909
  const v = child(input, pos, ctx);
14832
14910
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14911
+ ctx._fc = false;
14833
14912
  if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
14834
14913
  if (v === FAIL) {
14835
14914
  EC.e = pos;
@@ -14875,6 +14954,7 @@ function assemble(t2, prog, cfg) {
14875
14954
  const probeBest = PROBE ? ctx._probe?.best : void 0;
14876
14955
  const v = child(input, pos, ctx);
14877
14956
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
14957
+ ctx._fc = false;
14878
14958
  if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
14879
14959
  if (v === FAIL) {
14880
14960
  ctx._fe = pos;
@@ -16733,7 +16813,7 @@ function assemble(t2, prog, cfg) {
16733
16813
  if (emitted !== void 0) throw new ServedByBuild();
16734
16814
  if (prog.asm !== void 0) {
16735
16815
  throw new Unemittable(
16736
- `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`
16816
+ `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`
16737
16817
  );
16738
16818
  }
16739
16819
  if (!EMIT_ENABLED) throw new Unemittable("PM_TABLE_EMIT=0 (measurement toggle)");
@@ -16932,7 +17012,9 @@ function countedPiece(piece, ip) {
16932
17012
  var AssemblyCache = class {
16933
17013
  t;
16934
17014
  prog;
16935
- byCfg = Array.from({ length: 64 });
17015
+ byCfg = Array.from({ length: 128 });
17016
+ /** Whether this program installs no trivia of its own (`RunCfg.inheritedTrivia`). */
17017
+ noOwnTrivia;
16936
17018
  /**
16937
17019
  * Monomorphic predicate inline cache. An assembly depends on the predicate
16938
17020
  * FUNCTION and the scalar cfg key, not on the host object that carries it, so
@@ -16945,6 +17027,7 @@ var AssemblyCache = class {
16945
17027
  constructor(prog, resolved = resolveTable(prog)) {
16946
17028
  this.prog = prog;
16947
17029
  this.t = resolved;
17030
+ this.noOwnTrivia = prog.triviaSpecs === void 0 || prog.triviaSpecs.length === 0;
16948
17031
  }
16949
17032
  for(cfg) {
16950
17033
  const key = cfgKey(cfg);
@@ -17008,13 +17091,14 @@ var AssemblyCache = class {
17008
17091
  const tolerant = ctx._tolerant === true;
17009
17092
  const coverage = ctx._grammarCoverage !== void 0;
17010
17093
  const probe = ctx._probe !== void 0;
17011
- const key = cfgKeyOf(hostCst, trackLines, tolerant, coverage, probe, hostReadsChildren);
17094
+ const inheritedTrivia = this.noOwnTrivia && ctx.trivia !== void 0;
17095
+ const key = cfgKeyOf(hostCst, trackLines, tolerant, coverage, probe, hostReadsChildren, inheritedTrivia);
17012
17096
  let cache = this.byCfg;
17013
17097
  if (hostCaptureTrivia !== void 0) {
17014
17098
  if (this.hostPredicate === hostCaptureTrivia) {
17015
17099
  cache = this.hostAssemblies;
17016
17100
  } else {
17017
- cache = Array.from({ length: 64 });
17101
+ cache = Array.from({ length: 128 });
17018
17102
  this.hostPredicate = hostCaptureTrivia;
17019
17103
  this.hostAssemblies = cache;
17020
17104
  }
@@ -17028,7 +17112,8 @@ var AssemblyCache = class {
17028
17112
  trackLines,
17029
17113
  tolerant,
17030
17114
  coverage,
17031
- probe
17115
+ probe,
17116
+ inheritedTrivia
17032
17117
  });
17033
17118
  cache[key] = made;
17034
17119
  return made;