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.
@@ -107,8 +107,33 @@ export declare function hasNodeDef(p: Combinator<unknown>, seen?: Set<Combinator
107
107
  * sites and neither of which `hasNodeDef` above walks.
108
108
  */
109
109
  export declare function hasDirectBuildDef(p: Combinator<unknown>, seen?: Set<Combinator<unknown>>): boolean;
110
- /** True when `p` can report a committed failure through emitFallible's failure channel. */
111
- export declare function mayCommitFailure(p: Combinator<unknown>, seen?: Set<Combinator<unknown>>, resolve?: RefResolver): boolean;
110
+ /**
111
+ * True when `p` can report a committed failure through emitFallible's failure
112
+ * channel: a `dispatch`, or a shape this analysis cannot see into, is reachable
113
+ * along `commitFailureSuccessors`' edges.
114
+ *
115
+ * `memo` carries exact answers between calls over one graph and one `resolve`;
116
+ * a caller asking at many sites passes the same map to every call, so the graph
117
+ * is walked once rather than once per site.
118
+ */
119
+ export declare function mayCommitFailure(p: Combinator<unknown>, resolve?: RefResolver, memo?: Map<Combinator<unknown>, boolean>): boolean;
120
+ /**
121
+ * Whether a MARKED node — one `successors` answers `true` for — is reachable
122
+ * from `root`.
123
+ *
124
+ * Reachability over a cyclic graph, decided with Tarjan's strongly connected
125
+ * components so that every node the walk enters leaves with its exact answer in
126
+ * `memo`: the members of one component reach each other, so they share one
127
+ * answer, settled when the walk returns to the component's first node. A DFS
128
+ * that instead cuts a cycle at its own ancestor path learns nothing it can keep
129
+ * about a node whose walk hit the cut; one that keeps a visited set per call
130
+ * keeps nothing past the call. Shared across calls, `memo` makes every node
131
+ * entered once however many roots are asked about.
132
+ *
133
+ * `memo` must only ever be used with one `successors`: its entries are answers
134
+ * about that graph.
135
+ */
136
+ export declare function reachesMarked<T>(root: T, successors: (node: T) => readonly T[] | true, memo: Map<T, boolean>): boolean;
112
137
  /**
113
138
  * `hasDirectBuilders` / `isRecognitionOnly` for a rule map WITHOUT lowering it.
114
139
  *
@@ -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,CAwGvI;AAED,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAkDxG;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAgCtG;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAqC7G;AAED,2FAA2F;AAC3F,wBAAgB,gBAAgB,CAC9B,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EACtB,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,EAC1C,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CA+CT;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,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,EAAE,YAAY,UAAO,GAAG,OAAO,CAwGvI;AAED,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAkDxG;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAgCtG;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAqC7G;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;AAsDD;;;;;;;;;;;;;;;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"}
@@ -3255,19 +3255,22 @@ function hasDirectBuildDef(p, seen = /* @__PURE__ */ new Set()) {
3255
3255
  return false;
3256
3256
  }
3257
3257
  }
3258
- function mayCommitFailure(p, seen = /* @__PURE__ */ new Set(), resolve) {
3259
- if (seen.has(p)) return false;
3260
- seen.add(p);
3258
+ function mayCommitFailure(p, resolve, memo = /* @__PURE__ */ new Map()) {
3259
+ return reachesMarked(p, (node2) => commitFailureSuccessors(node2, resolve), memo);
3260
+ }
3261
+ var NO_EDGES = [];
3262
+ function commitFailureSuccessors(p, resolve) {
3261
3263
  const d = p._def;
3262
3264
  switch (d.tag) {
3263
3265
  case "dispatch":
3266
+ case "unknown":
3264
3267
  return true;
3265
3268
  case "choice":
3266
3269
  case "sequence":
3267
- return d.parsers.some((x) => mayCommitFailure(x, seen, resolve));
3270
+ return d.parsers;
3268
3271
  // A contained transaction reports every failure uncommitted.
3269
3272
  case "attempt":
3270
- return d.contain !== true && mayCommitFailure(d.parser, seen, resolve);
3273
+ return d.contain === true ? NO_EDGES : [d.parser];
3271
3274
  case "many":
3272
3275
  case "oneOrMore":
3273
3276
  case "optional":
@@ -3276,31 +3279,77 @@ function mayCommitFailure(p, seen = /* @__PURE__ */ new Set(), resolve) {
3276
3279
  case "field":
3277
3280
  case "grammar":
3278
3281
  case "node":
3279
- return mayCommitFailure(d.parser, seen, resolve);
3280
- case "sepBy":
3281
- return mayCommitFailure(d.parser, seen, resolve) || mayCommitFailure(d.separator, seen, resolve);
3282
3282
  case "token":
3283
3283
  case "leaf":
3284
- return mayCommitFailure(d.parser, seen, resolve);
3285
3284
  case "withCtx":
3286
- return mayCommitFailure(d.parser, seen, resolve);
3285
+ return [d.parser];
3286
+ case "sepBy":
3287
+ return [d.parser, d.separator];
3287
3288
  case "scanTo":
3288
- return mayCommitFailure(d.sentinel, seen, resolve) || d.skip.some((x) => mayCommitFailure(x, seen, resolve)) || d.recoverAt !== void 0 && mayCommitFailure(d.recoverAt, seen, resolve) || d.stopAt !== void 0 && mayCommitFailure(d.stopAt, seen, resolve);
3289
+ return [
3290
+ d.sentinel,
3291
+ ...d.skip,
3292
+ ...d.recoverAt === void 0 ? NO_EDGES : [d.recoverAt],
3293
+ ...d.stopAt === void 0 ? NO_EDGES : [d.stopAt]
3294
+ ];
3289
3295
  case "lazy": {
3290
3296
  try {
3291
- return mayCommitFailure(d.thunk(), seen, resolve);
3297
+ return [d.thunk()];
3292
3298
  } catch {
3293
3299
  const name = p._ruleName;
3294
3300
  const target = name === void 0 ? void 0 : resolve?.(name);
3295
- return target === void 0 ? true : mayCommitFailure(target, seen, resolve);
3301
+ return target === void 0 ? true : [target];
3296
3302
  }
3297
3303
  }
3298
- case "unknown":
3299
- return true;
3300
3304
  default:
3301
- return false;
3305
+ return NO_EDGES;
3302
3306
  }
3303
3307
  }
3308
+ function reachesMarked(root, successors, memo) {
3309
+ const known = memo.get(root);
3310
+ if (known !== void 0) return known;
3311
+ const order = /* @__PURE__ */ new Map();
3312
+ const low = [];
3313
+ const found = [];
3314
+ const stack = [];
3315
+ const visit = (node2) => {
3316
+ const at = low.length;
3317
+ order.set(node2, at);
3318
+ low.push(at);
3319
+ found.push(false);
3320
+ stack.push(node2);
3321
+ const next = successors(node2);
3322
+ if (next === true) found[at] = true;
3323
+ else {
3324
+ for (const child of next) {
3325
+ if (found[at]) break;
3326
+ const hit = memo.get(child);
3327
+ if (hit !== void 0) {
3328
+ if (hit) found[at] = true;
3329
+ continue;
3330
+ }
3331
+ const seen = order.get(child);
3332
+ if (seen !== void 0) {
3333
+ if (seen < low[at]) low[at] = seen;
3334
+ continue;
3335
+ }
3336
+ const k = visit(child);
3337
+ if (low[k] < low[at]) low[at] = low[k];
3338
+ if (found[k]) found[at] = true;
3339
+ }
3340
+ }
3341
+ if (low[at] === at) {
3342
+ const answer = found[at];
3343
+ let member;
3344
+ do {
3345
+ member = stack.pop();
3346
+ memo.set(member, answer);
3347
+ } while (member !== node2);
3348
+ }
3349
+ return at;
3350
+ };
3351
+ return found[visit(root)];
3352
+ }
3304
3353
 
3305
3354
  // src/recovery/scan.ts
3306
3355
  function probeAt(sentinel, input, pos, ctx) {
@@ -3597,14 +3646,8 @@ function choice(...args) {
3597
3646
  if (result.committed) return { ok: false, expected, span: { start: pos, end: pos }, committed: true };
3598
3647
  return { ok: false, expected, span: { start: pos, end: pos } };
3599
3648
  }
3600
- return {
3601
- ok: false,
3602
- expected: parsers.flatMap((p) => {
3603
- const r = p.parse(input, pos, ctx);
3604
- return r.ok ? [] : r.expected;
3605
- }),
3606
- span: { start: pos, end: pos }
3607
- };
3649
+ if (ctx._probe !== void 0 || ctx._tolerant) for (const p of parsers) p.parse(input, pos, ctx);
3650
+ return { ok: false, expected: [...scalarExpected], span: { start: pos, end: pos } };
3608
3651
  }
3609
3652
  if (strategy?.tag === "greedyClassify") {
3610
3653
  const superResult = parsers[strategy.superIndex].parse(input, pos, ctx);
@@ -6232,6 +6275,13 @@ var Encoder = class {
6232
6275
  * attempt sites reach it.
6233
6276
  */
6234
6277
  sideWriterMemo = /* @__PURE__ */ new Map();
6278
+ /**
6279
+ * `mayCommitFailure`'s answers, shared by every choice site for the lifetime
6280
+ * of this `Encoder` — exact for the graph and the `winners` resolver it is
6281
+ * encoding, so the rule graph is walked once per encode rather than once per
6282
+ * choice site.
6283
+ */
6284
+ commitFailureMemo = /* @__PURE__ */ new Map();
6235
6285
  labels = void 0;
6236
6286
  /** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
6237
6287
  activeTrivia = void 0;
@@ -6672,62 +6722,11 @@ var Encoder = class {
6672
6722
  }
6673
6723
  /**
6674
6724
  * Whether a field, recovered error, interpreted scanner or unresolvable shape
6675
- * is reachable from `root` — the writer census of `failureNeedsRollback`.
6676
- *
6677
- * Reachability over a cyclic graph, decided with Tarjan's strongly connected
6678
- * components so that every node the walk enters leaves with its exact answer
6679
- * memoized: the members of one component reach each other, so they share one
6680
- * answer, settled when the walk returns to the component's first node. A DFS
6681
- * that instead cuts a cycle at its own ancestor path learns nothing it can
6682
- * keep about a node whose walk hit the cut, and re-walks that node along
6683
- * every path that reaches it — exponential over recursive value rules (linking
6684
- * jess's SCSS grammar cost ~290G instructions). This walk enters each node
6685
- * once per `Encoder`.
6725
+ * is reachable from `root` — the writer census of `failureNeedsRollback`,
6726
+ * entering each combinator once per `Encoder` (see `reachesMarked`).
6686
6727
  */
6687
6728
  reachesSideWriter(root) {
6688
- const memo = this.sideWriterMemo;
6689
- const known = memo.get(root);
6690
- if (known !== void 0) return known;
6691
- const order = /* @__PURE__ */ new Map();
6692
- const low = [];
6693
- const found = [];
6694
- const stack = [];
6695
- const visit = (node2) => {
6696
- const at = low.length;
6697
- order.set(node2, at);
6698
- low.push(at);
6699
- found.push(false);
6700
- stack.push(node2);
6701
- const next = this.sideWriterSuccessors(node2);
6702
- if (next === true) found[at] = true;
6703
- else {
6704
- for (const child of next) {
6705
- const hit = memo.get(child);
6706
- if (hit !== void 0) {
6707
- if (hit) found[at] = true;
6708
- continue;
6709
- }
6710
- const seen = order.get(child);
6711
- if (seen !== void 0) {
6712
- if (seen < low[at]) low[at] = seen;
6713
- continue;
6714
- }
6715
- const k = visit(child);
6716
- if (low[k] < low[at]) low[at] = low[k];
6717
- if (found[k]) found[at] = true;
6718
- }
6719
- }
6720
- if (low[at] === at) {
6721
- const answer = found[at];
6722
- let member;
6723
- do {
6724
- member = stack.pop();
6725
- memo.set(member, answer);
6726
- } while (member !== node2);
6727
- }
6728
- return at;
6729
- };
6730
- return found[visit(root)];
6729
+ return reachesMarked(root, (node2) => this.sideWriterSuccessors(node2), this.sideWriterMemo);
6731
6730
  }
6732
6731
  /** The census's edges out of `node`, or `true` when `node` is itself a writer. */
6733
6732
  sideWriterSuccessors(node2) {
@@ -7082,7 +7081,7 @@ var Encoder = class {
7082
7081
  this.code[head + 4 + kids.length + i] = this.expected(deriveExpected(arms[i]));
7083
7082
  }
7084
7083
  this.choiceRollbackMasks.set(head, rollbackMask);
7085
- if (arms.every((arm) => !mayCommitFailure(arm, /* @__PURE__ */ new Set(), rr))) {
7084
+ if (arms.every((arm) => !mayCommitFailure(arm, rr, this.commitFailureMemo))) {
7086
7085
  this.nonCommittingChoiceSites.add(head);
7087
7086
  }
7088
7087
  return head;