parseman 0.55.1 → 0.55.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
@@ -3703,19 +3703,22 @@ function hasDirectBuildDef(p, seen = /* @__PURE__ */ new Set()) {
3703
3703
  return false;
3704
3704
  }
3705
3705
  }
3706
- function mayCommitFailure(p, seen = /* @__PURE__ */ new Set(), resolve2) {
3707
- if (seen.has(p)) return false;
3708
- seen.add(p);
3706
+ function mayCommitFailure(p, resolve2, memo = /* @__PURE__ */ new Map()) {
3707
+ return reachesMarked(p, (node2) => commitFailureSuccessors(node2, resolve2), memo);
3708
+ }
3709
+ var NO_EDGES = [];
3710
+ function commitFailureSuccessors(p, resolve2) {
3709
3711
  const d = p._def;
3710
3712
  switch (d.tag) {
3711
3713
  case "dispatch":
3714
+ case "unknown":
3712
3715
  return true;
3713
3716
  case "choice":
3714
3717
  case "sequence":
3715
- return d.parsers.some((x) => mayCommitFailure(x, seen, resolve2));
3718
+ return d.parsers;
3716
3719
  // A contained transaction reports every failure uncommitted.
3717
3720
  case "attempt":
3718
- return d.contain !== true && mayCommitFailure(d.parser, seen, resolve2);
3721
+ return d.contain === true ? NO_EDGES : [d.parser];
3719
3722
  case "many":
3720
3723
  case "oneOrMore":
3721
3724
  case "optional":
@@ -3724,31 +3727,77 @@ function mayCommitFailure(p, seen = /* @__PURE__ */ new Set(), resolve2) {
3724
3727
  case "field":
3725
3728
  case "grammar":
3726
3729
  case "node":
3727
- return mayCommitFailure(d.parser, seen, resolve2);
3728
- case "sepBy":
3729
- return mayCommitFailure(d.parser, seen, resolve2) || mayCommitFailure(d.separator, seen, resolve2);
3730
3730
  case "token":
3731
3731
  case "leaf":
3732
- return mayCommitFailure(d.parser, seen, resolve2);
3733
3732
  case "withCtx":
3734
- return mayCommitFailure(d.parser, seen, resolve2);
3733
+ return [d.parser];
3734
+ case "sepBy":
3735
+ return [d.parser, d.separator];
3735
3736
  case "scanTo":
3736
- return mayCommitFailure(d.sentinel, seen, resolve2) || d.skip.some((x) => mayCommitFailure(x, seen, resolve2)) || d.recoverAt !== void 0 && mayCommitFailure(d.recoverAt, seen, resolve2) || d.stopAt !== void 0 && mayCommitFailure(d.stopAt, seen, resolve2);
3737
+ return [
3738
+ d.sentinel,
3739
+ ...d.skip,
3740
+ ...d.recoverAt === void 0 ? NO_EDGES : [d.recoverAt],
3741
+ ...d.stopAt === void 0 ? NO_EDGES : [d.stopAt]
3742
+ ];
3737
3743
  case "lazy": {
3738
3744
  try {
3739
- return mayCommitFailure(d.thunk(), seen, resolve2);
3745
+ return [d.thunk()];
3740
3746
  } catch {
3741
3747
  const name = p._ruleName;
3742
3748
  const target = name === void 0 ? void 0 : resolve2?.(name);
3743
- return target === void 0 ? true : mayCommitFailure(target, seen, resolve2);
3749
+ return target === void 0 ? true : [target];
3744
3750
  }
3745
3751
  }
3746
- case "unknown":
3747
- return true;
3748
3752
  default:
3749
- return false;
3753
+ return NO_EDGES;
3750
3754
  }
3751
3755
  }
3756
+ function reachesMarked(root, successors, memo) {
3757
+ const known = memo.get(root);
3758
+ if (known !== void 0) return known;
3759
+ const order = /* @__PURE__ */ new Map();
3760
+ const low = [];
3761
+ const found = [];
3762
+ const stack = [];
3763
+ const visit = (node2) => {
3764
+ const at = low.length;
3765
+ order.set(node2, at);
3766
+ low.push(at);
3767
+ found.push(false);
3768
+ stack.push(node2);
3769
+ const next = successors(node2);
3770
+ if (next === true) found[at] = true;
3771
+ else {
3772
+ for (const child of next) {
3773
+ if (found[at]) break;
3774
+ const hit = memo.get(child);
3775
+ if (hit !== void 0) {
3776
+ if (hit) found[at] = true;
3777
+ continue;
3778
+ }
3779
+ const seen = order.get(child);
3780
+ if (seen !== void 0) {
3781
+ if (seen < low[at]) low[at] = seen;
3782
+ continue;
3783
+ }
3784
+ const k = visit(child);
3785
+ if (low[k] < low[at]) low[at] = low[k];
3786
+ if (found[k]) found[at] = true;
3787
+ }
3788
+ }
3789
+ if (low[at] === at) {
3790
+ const answer = found[at];
3791
+ let member;
3792
+ do {
3793
+ member = stack.pop();
3794
+ memo.set(member, answer);
3795
+ } while (member !== node2);
3796
+ }
3797
+ return at;
3798
+ };
3799
+ return found[visit(root)];
3800
+ }
3752
3801
 
3753
3802
  // src/combinators/scalar.ts
3754
3803
  var SCALAR_TAG = /^(?:literal|regex|keywords|sequence|choice|many|oneOrMore|optional|transform|trivia|grammar|sepBy|lazy)$/;
@@ -3870,14 +3919,8 @@ function choice(...args) {
3870
3919
  if (result.committed) return { ok: false, expected, span: { start: pos, end: pos }, committed: true };
3871
3920
  return { ok: false, expected, span: { start: pos, end: pos } };
3872
3921
  }
3873
- return {
3874
- ok: false,
3875
- expected: parsers.flatMap((p) => {
3876
- const r = p.parse(input, pos, ctx);
3877
- return r.ok ? [] : r.expected;
3878
- }),
3879
- span: { start: pos, end: pos }
3880
- };
3922
+ if (ctx._probe !== void 0 || ctx._tolerant) for (const p of parsers) p.parse(input, pos, ctx);
3923
+ return { ok: false, expected: [...scalarExpected], span: { start: pos, end: pos } };
3881
3924
  }
3882
3925
  if (strategy?.tag === "greedyClassify") {
3883
3926
  const superResult = parsers[strategy.superIndex].parse(input, pos, ctx);
@@ -6114,6 +6157,13 @@ var Encoder = class {
6114
6157
  * attempt sites reach it.
6115
6158
  */
6116
6159
  sideWriterMemo = /* @__PURE__ */ new Map();
6160
+ /**
6161
+ * `mayCommitFailure`'s answers, shared by every choice site for the lifetime
6162
+ * of this `Encoder` — exact for the graph and the `winners` resolver it is
6163
+ * encoding, so the rule graph is walked once per encode rather than once per
6164
+ * choice site.
6165
+ */
6166
+ commitFailureMemo = /* @__PURE__ */ new Map();
6117
6167
  labels = void 0;
6118
6168
  /** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
6119
6169
  activeTrivia = void 0;
@@ -6554,62 +6604,11 @@ var Encoder = class {
6554
6604
  }
6555
6605
  /**
6556
6606
  * Whether a field, recovered error, interpreted scanner or unresolvable shape
6557
- * is reachable from `root` — the writer census of `failureNeedsRollback`.
6558
- *
6559
- * Reachability over a cyclic graph, decided with Tarjan's strongly connected
6560
- * components so that every node the walk enters leaves with its exact answer
6561
- * memoized: the members of one component reach each other, so they share one
6562
- * answer, settled when the walk returns to the component's first node. A DFS
6563
- * that instead cuts a cycle at its own ancestor path learns nothing it can
6564
- * keep about a node whose walk hit the cut, and re-walks that node along
6565
- * every path that reaches it — exponential over recursive value rules (linking
6566
- * jess's SCSS grammar cost ~290G instructions). This walk enters each node
6567
- * once per `Encoder`.
6607
+ * is reachable from `root` — the writer census of `failureNeedsRollback`,
6608
+ * entering each combinator once per `Encoder` (see `reachesMarked`).
6568
6609
  */
6569
6610
  reachesSideWriter(root) {
6570
- const memo = this.sideWriterMemo;
6571
- const known = memo.get(root);
6572
- if (known !== void 0) return known;
6573
- const order = /* @__PURE__ */ new Map();
6574
- const low = [];
6575
- const found = [];
6576
- const stack = [];
6577
- const visit = (node2) => {
6578
- const at = low.length;
6579
- order.set(node2, at);
6580
- low.push(at);
6581
- found.push(false);
6582
- stack.push(node2);
6583
- const next = this.sideWriterSuccessors(node2);
6584
- if (next === true) found[at] = true;
6585
- else {
6586
- for (const child of next) {
6587
- const hit = memo.get(child);
6588
- if (hit !== void 0) {
6589
- if (hit) found[at] = true;
6590
- continue;
6591
- }
6592
- const seen = order.get(child);
6593
- if (seen !== void 0) {
6594
- if (seen < low[at]) low[at] = seen;
6595
- continue;
6596
- }
6597
- const k = visit(child);
6598
- if (low[k] < low[at]) low[at] = low[k];
6599
- if (found[k]) found[at] = true;
6600
- }
6601
- }
6602
- if (low[at] === at) {
6603
- const answer = found[at];
6604
- let member;
6605
- do {
6606
- member = stack.pop();
6607
- memo.set(member, answer);
6608
- } while (member !== node2);
6609
- }
6610
- return at;
6611
- };
6612
- return found[visit(root)];
6611
+ return reachesMarked(root, (node2) => this.sideWriterSuccessors(node2), this.sideWriterMemo);
6613
6612
  }
6614
6613
  /** The census's edges out of `node`, or `true` when `node` is itself a writer. */
6615
6614
  sideWriterSuccessors(node2) {
@@ -6964,7 +6963,7 @@ var Encoder = class {
6964
6963
  this.code[head + 4 + kids.length + i] = this.expected(deriveExpected(arms[i]));
6965
6964
  }
6966
6965
  this.choiceRollbackMasks.set(head, rollbackMask);
6967
- if (arms.every((arm) => !mayCommitFailure(arm, /* @__PURE__ */ new Set(), rr))) {
6966
+ if (arms.every((arm) => !mayCommitFailure(arm, rr, this.commitFailureMemo))) {
6968
6967
  this.nonCommittingChoiceSites.add(head);
6969
6968
  }
6970
6969
  return head;