parseman 0.50.7 → 0.51.0

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 (56) hide show
  1. package/dist/analysis/choice-cost.d.ts.map +1 -1
  2. package/dist/analysis/commitment.d.ts.map +1 -1
  3. package/dist/analysis/diagnostics.js +165 -21
  4. package/dist/analysis/diagnostics.js.map +2 -2
  5. package/dist/analysis/duplication.d.ts.map +1 -1
  6. package/dist/analysis/gating.d.ts.map +1 -1
  7. package/dist/cli/index.js +171 -22
  8. package/dist/cli/index.js.map +2 -2
  9. package/dist/combinators/dispatch.d.ts.map +1 -1
  10. package/dist/combinators/scanTo.d.ts +23 -1
  11. package/dist/combinators/scanTo.d.ts.map +1 -1
  12. package/dist/compiler/fields.d.ts.map +1 -1
  13. package/dist/compiler/grammar-coverage-ids.d.ts.map +1 -1
  14. package/dist/compiler/ir-serialize.d.ts.map +1 -1
  15. package/dist/compiler/token-capability.js +2 -2
  16. package/dist/compiler/token-capability.js.map +1 -1
  17. package/dist/coverage.d.ts.map +1 -1
  18. package/dist/cst/reflection.d.ts.map +1 -1
  19. package/dist/index.js +192 -28
  20. package/dist/index.js.map +2 -2
  21. package/dist/plugin/index.js +179 -25
  22. package/dist/plugin/index.js.map +2 -2
  23. package/dist/spec/index.js +127 -12
  24. package/dist/spec/index.js.map +2 -2
  25. package/dist/table/assemble.d.ts.map +1 -1
  26. package/dist/table/emit.d.ts.map +1 -1
  27. package/dist/table/encode.d.ts.map +1 -1
  28. package/dist/table/exec.d.ts.map +1 -1
  29. package/dist/table/index.js +171 -22
  30. package/dist/table/index.js.map +2 -2
  31. package/dist/table/program.d.ts +2 -0
  32. package/dist/table/program.d.ts.map +1 -1
  33. package/dist/types.d.ts +2 -0
  34. package/dist/types.d.ts.map +1 -1
  35. package/dist/version.d.ts +1 -1
  36. package/package.json +1 -1
  37. package/src/analysis/choice-cost.ts +6 -1
  38. package/src/analysis/commitment.ts +10 -2
  39. package/src/analysis/duplication.ts +7 -2
  40. package/src/analysis/gating.ts +6 -1
  41. package/src/analysis/rebuild.ts +1 -1
  42. package/src/combinators/dispatch.ts +4 -1
  43. package/src/combinators/scanTo.ts +163 -9
  44. package/src/compiler/fields.ts +8 -2
  45. package/src/compiler/grammar-coverage-ids.ts +6 -1
  46. package/src/compiler/ir-serialize.ts +7 -2
  47. package/src/compiler/token-alphabet.ts +1 -1
  48. package/src/coverage.ts +7 -1
  49. package/src/cst/reflection.ts +6 -1
  50. package/src/table/assemble.ts +11 -1
  51. package/src/table/emit.ts +4 -0
  52. package/src/table/encode.ts +6 -0
  53. package/src/table/exec.ts +7 -1
  54. package/src/table/program.ts +2 -0
  55. package/src/types.ts +1 -1
  56. package/src/version.ts +1 -1
package/dist/index.js CHANGED
@@ -3314,7 +3314,7 @@ function parserUsesRouted(parser2, seen = /* @__PURE__ */ new Set()) {
3314
3314
  case "grammar":
3315
3315
  return parserUsesRouted(def.parser, seen) || (def.triviaParser ? parserUsesRouted(def.triviaParser, seen) : false);
3316
3316
  case "scanTo":
3317
- return parserUsesRouted(def.sentinel, seen) || def.skip.some((entry) => parserUsesRouted(entry, seen));
3317
+ return parserUsesRouted(def.sentinel, seen) || def.skip.some((entry) => parserUsesRouted(entry, seen)) || def.recoverAt !== void 0 && parserUsesRouted(def.recoverAt, seen) || def.stopAt !== void 0 && parserUsesRouted(def.stopAt, seen);
3318
3318
  case "recover":
3319
3319
  return parserUsesRouted(def.parser, seen) || parserUsesRouted(def.sentinel, seen);
3320
3320
  case "lazy":
@@ -4342,7 +4342,12 @@ function childrenOf(def) {
4342
4342
  case "sepBy":
4343
4343
  return [def.parser, def.separator];
4344
4344
  case "scanTo":
4345
- return [def.sentinel, ...def.skip];
4345
+ return [
4346
+ def.sentinel,
4347
+ ...def.skip,
4348
+ ...def.recoverAt === void 0 ? [] : [def.recoverAt],
4349
+ ...def.stopAt === void 0 ? [] : [def.stopAt]
4350
+ ];
4346
4351
  case "routed":
4347
4352
  return def.fallback ? [def.fallback] : [];
4348
4353
  case "literal":
@@ -4863,7 +4868,7 @@ function parserHasOwnFields(p, seen = /* @__PURE__ */ new Set()) {
4863
4868
  case "grammar":
4864
4869
  return parserHasOwnFields(d.parser, seen) || (d.triviaParser ? parserHasOwnFields(d.triviaParser, seen) : false);
4865
4870
  case "scanTo":
4866
- return parserHasOwnFields(d.sentinel, seen) || d.skip.some((x) => parserHasOwnFields(x, seen));
4871
+ return parserHasOwnFields(d.sentinel, seen) || d.skip.some((x) => parserHasOwnFields(x, seen)) || d.recoverAt !== void 0 && parserHasOwnFields(d.recoverAt, seen) || d.stopAt !== void 0 && parserHasOwnFields(d.stopAt, seen);
4867
4872
  case "recover":
4868
4873
  return parserHasOwnFields(d.parser, seen) || parserHasOwnFields(d.sentinel, seen);
4869
4874
  case "routed":
@@ -5246,7 +5251,12 @@ function childrenOf2(d) {
5246
5251
  case "recover":
5247
5252
  return [d.parser, d.sentinel];
5248
5253
  case "scanTo":
5249
- return [d.sentinel, ...d.skip];
5254
+ return [
5255
+ d.sentinel,
5256
+ ...d.skip,
5257
+ ...d.recoverAt === void 0 ? [] : [d.recoverAt],
5258
+ ...d.stopAt === void 0 ? [] : [d.stopAt]
5259
+ ];
5250
5260
  case "grammar":
5251
5261
  return d.triviaParser ? [d.parser, d.triviaParser] : [d.parser];
5252
5262
  case "routed":
@@ -5893,7 +5903,7 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
5893
5903
  case "sepBy":
5894
5904
  return hasNodeDef(d.parser, seen) || hasNodeDef(d.separator, seen);
5895
5905
  case "scanTo":
5896
- return hasNodeDef(d.sentinel, seen) || d.skip.some((x) => hasNodeDef(x, seen));
5906
+ return hasNodeDef(d.sentinel, seen) || d.skip.some((x) => hasNodeDef(x, seen)) || d.recoverAt !== void 0 && hasNodeDef(d.recoverAt, seen) || d.stopAt !== void 0 && hasNodeDef(d.stopAt, seen);
5897
5907
  case "recover":
5898
5908
  return hasNodeDef(d.parser, seen) || hasNodeDef(d.sentinel, seen);
5899
5909
  case "expect":
@@ -5942,7 +5952,7 @@ function hasDirectBuildDef(p, seen = /* @__PURE__ */ new Set()) {
5942
5952
  case "sepBy":
5943
5953
  return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.separator, seen);
5944
5954
  case "scanTo":
5945
- return hasDirectBuildDef(d.sentinel, seen) || d.skip.some((x) => hasDirectBuildDef(x, seen));
5955
+ return hasDirectBuildDef(d.sentinel, seen) || d.skip.some((x) => hasDirectBuildDef(x, seen)) || d.recoverAt !== void 0 && hasDirectBuildDef(d.recoverAt, seen) || d.stopAt !== void 0 && hasDirectBuildDef(d.stopAt, seen);
5946
5956
  case "recover":
5947
5957
  return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.sentinel, seen);
5948
5958
  case "routed":
@@ -5979,7 +5989,7 @@ function mayCommitFailure(p, seen = /* @__PURE__ */ new Set(), resolve) {
5979
5989
  case "withCtx":
5980
5990
  return mayCommitFailure(d.parser, seen, resolve);
5981
5991
  case "scanTo":
5982
- return mayCommitFailure(d.sentinel, seen, resolve) || d.skip.some((x) => mayCommitFailure(x, seen, resolve));
5992
+ 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);
5983
5993
  case "lazy": {
5984
5994
  try {
5985
5995
  return mayCommitFailure(d.thunk(), seen, resolve);
@@ -7885,6 +7895,8 @@ var Encoder = class {
7885
7895
  flags: (d.raw ? 1 : 0) | (d.orEOF ? 2 : 0),
7886
7896
  skip: d.skip.map((c) => this.subtree(c)),
7887
7897
  sentinel: this.subtree(d.sentinel),
7898
+ ...d.recoverAt === void 0 ? {} : { recoverAt: this.subtree(d.recoverAt) },
7899
+ ...d.stopAt === void 0 ? {} : { stopAt: this.subtree(d.stopAt) },
7888
7900
  sent: sentDef.tag === "literal" ? sentDef.value : null
7889
7901
  }));
7890
7902
  }
@@ -8318,6 +8330,8 @@ var Encoder = class {
8318
8330
  const refs = [];
8319
8331
  for (const s of this.scans) {
8320
8332
  if (s.sentinel !== void 0) refs.push(s.sentinel);
8333
+ if (s.recoverAt !== void 0) refs.push(s.recoverAt);
8334
+ if (s.stopAt !== void 0) refs.push(s.stopAt);
8321
8335
  refs.push(...s.skip);
8322
8336
  }
8323
8337
  for (const set of this.scanSkipSets) refs.push(...set);
@@ -8337,7 +8351,9 @@ var Encoder = class {
8337
8351
  this.scans = this.scans.map((s) => ({
8338
8352
  ...s,
8339
8353
  skip: s.skip.map(res),
8340
- ...s.sentinel === void 0 ? {} : { sentinel: res(s.sentinel) }
8354
+ ...s.sentinel === void 0 ? {} : { sentinel: res(s.sentinel) },
8355
+ ...s.recoverAt === void 0 ? {} : { recoverAt: res(s.recoverAt) },
8356
+ ...s.stopAt === void 0 ? {} : { stopAt: res(s.stopAt) }
8341
8357
  }));
8342
8358
  this.scanSkipSets = this.scanSkipSets.map((set) => set.map(res));
8343
8359
  }
@@ -11584,7 +11600,7 @@ function resolveScanSkip(explicitSkip, raw, ctx) {
11584
11600
  out.push(...explicitSkip);
11585
11601
  return out;
11586
11602
  }
11587
- function scanTo(sentinel, { skip, raw = false, orEOF = false } = {}) {
11603
+ function scanTo(sentinel, { skip, raw = false, orEOF = false, recoverAt, stopAt } = {}) {
11588
11604
  const meta = {
11589
11605
  firstSet: any(),
11590
11606
  canMatchNewline: true,
@@ -11594,7 +11610,15 @@ function scanTo(sentinel, { skip, raw = false, orEOF = false } = {}) {
11594
11610
  return {
11595
11611
  _tag: "scanTo",
11596
11612
  _meta: meta,
11597
- _def: { tag: "scanTo", sentinel, skip: explicitSkip, raw, orEOF },
11613
+ _def: {
11614
+ tag: "scanTo",
11615
+ sentinel,
11616
+ skip: explicitSkip,
11617
+ raw,
11618
+ orEOF,
11619
+ ...recoverAt === void 0 ? {} : { recoverAt },
11620
+ ...stopAt === void 0 ? {} : { stopAt }
11621
+ },
11598
11622
  parse(input, pos, ctx) {
11599
11623
  let cur = pos;
11600
11624
  const skip2 = resolveScanSkip(explicitSkip, raw, ctx);
@@ -11606,28 +11630,130 @@ function scanTo(sentinel, { skip, raw = false, orEOF = false } = {}) {
11606
11630
  pushCstLeaf(ctx, leaf2);
11607
11631
  }
11608
11632
  };
11609
- while (cur < input.length) {
11610
- const s = sentinel.parse(input, cur, probeCtx);
11611
- if (s.ok) {
11633
+ if (recoverAt === void 0 && stopAt === void 0) {
11634
+ while (cur < input.length) {
11635
+ const s = sentinel.parse(input, cur, probeCtx);
11636
+ if (s.ok) {
11637
+ if (ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, cur);
11638
+ emit(cur);
11639
+ return { ok: true, value: input.slice(pos, cur), span: { start: pos, end: cur } };
11640
+ }
11641
+ let advanced = false;
11642
+ for (const skipper of skip2) {
11643
+ const r = skipper.parse(input, cur, probeCtx);
11644
+ if (r.ok && r.span.end > cur) {
11645
+ cur = r.span.end;
11646
+ advanced = true;
11647
+ break;
11648
+ }
11649
+ }
11650
+ if (!advanced) cur++;
11651
+ }
11652
+ if (orEOF) {
11612
11653
  if (ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, cur);
11613
11654
  emit(cur);
11614
11655
  return { ok: true, value: input.slice(pos, cur), span: { start: pos, end: cur } };
11615
11656
  }
11657
+ const sentDef2 = sentinel._def;
11658
+ const expected2 = sentDef2.tag === "literal" ? [JSON.stringify(sentDef2.value)] : ["sentinel"];
11659
+ return { ok: false, expected: expected2, span: { start: pos, end: cur } };
11660
+ }
11661
+ let recovery = -1;
11662
+ let firstSentinel = -1;
11663
+ let sentinelCount = 0;
11664
+ let recoveryErrorCount = -1;
11665
+ let sentinelErrorCount = -1;
11666
+ const succeed = (end) => {
11667
+ if (ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, end);
11668
+ emit(end);
11669
+ return { ok: true, value: input.slice(pos, end), span: { start: pos, end } };
11670
+ };
11671
+ const recoveredEnd = () => {
11672
+ const acceptSentinel = firstSentinel >= 0 && (sentinelCount & 1) === 1;
11673
+ const errors = ctx._errors;
11674
+ if (errors !== void 0) {
11675
+ const keep = acceptSentinel ? sentinelErrorCount : recoveryErrorCount;
11676
+ if (keep >= 0 && errors.length > keep) errors.length = keep;
11677
+ }
11678
+ return acceptSentinel ? firstSentinel : recovery;
11679
+ };
11680
+ while (cur < input.length) {
11681
+ const sentinelProbeErrorCount = ctx._errors?.length ?? -1;
11682
+ const s = sentinel.parse(input, cur, probeCtx);
11683
+ const sentinelProbeErrors = ctx._errors;
11684
+ if (sentinelProbeErrors !== void 0 && sentinelProbeErrorCount >= 0 && sentinelProbeErrors.length > sentinelProbeErrorCount) {
11685
+ sentinelProbeErrors.length = sentinelProbeErrorCount;
11686
+ }
11687
+ if (s.ok) {
11688
+ if (recovery < 0) return succeed(cur);
11689
+ if (s.span.end <= cur) {
11690
+ throw new TypeError("scanTo recovery requires a sentinel that consumes input");
11691
+ }
11692
+ if (firstSentinel < 0) {
11693
+ firstSentinel = cur;
11694
+ sentinelErrorCount = sentinelProbeErrorCount;
11695
+ }
11696
+ sentinelCount++;
11697
+ cur = s.span.end;
11698
+ continue;
11699
+ }
11700
+ if (stopAt !== void 0) {
11701
+ const errorCount = ctx._errors?.length ?? -1;
11702
+ const stop = stopAt.parse(input, cur, probeCtx);
11703
+ const errors = ctx._errors;
11704
+ if (errors !== void 0 && errorCount >= 0 && errors.length > errorCount) {
11705
+ errors.length = errorCount;
11706
+ }
11707
+ if (stop.ok) {
11708
+ if (recovery < 0) {
11709
+ recovery = cur;
11710
+ recoveryErrorCount = errorCount;
11711
+ }
11712
+ return succeed(recoveredEnd());
11713
+ }
11714
+ }
11616
11715
  let advanced = false;
11617
11716
  for (const skipper of skip2) {
11717
+ const errorCount = ctx._errors?.length ?? -1;
11618
11718
  const r = skipper.parse(input, cur, probeCtx);
11619
11719
  if (r.ok && r.span.end > cur) {
11620
11720
  cur = r.span.end;
11621
11721
  advanced = true;
11622
11722
  break;
11623
11723
  }
11724
+ const errors = ctx._errors;
11725
+ if (errors !== void 0 && errorCount >= 0 && errors.length > errorCount) {
11726
+ errors.length = errorCount;
11727
+ }
11624
11728
  }
11625
- if (!advanced) cur++;
11729
+ if (advanced) continue;
11730
+ if (recoverAt !== void 0) {
11731
+ const errorCount = ctx._errors?.length ?? -1;
11732
+ const recover = recoverAt.parse(input, cur, probeCtx);
11733
+ const errors = ctx._errors;
11734
+ if (errors !== void 0 && errorCount >= 0 && errors.length > errorCount) {
11735
+ errors.length = errorCount;
11736
+ }
11737
+ if (recover.ok) {
11738
+ if (recover.span.end <= cur) {
11739
+ throw new TypeError("scanTo recoverAt must consume input");
11740
+ }
11741
+ if (recovery < 0) {
11742
+ recovery = cur;
11743
+ recoveryErrorCount = errorCount;
11744
+ }
11745
+ if (firstSentinel >= 0 && (sentinelCount & 1) === 1) {
11746
+ return succeed(recoveredEnd());
11747
+ }
11748
+ cur = recover.span.end;
11749
+ continue;
11750
+ }
11751
+ }
11752
+ cur++;
11626
11753
  }
11754
+ if (recovery >= 0) return succeed(recoveredEnd());
11627
11755
  if (orEOF) {
11628
- if (ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, cur);
11629
- emit(cur);
11630
- return { ok: true, value: input.slice(pos, cur), span: { start: pos, end: cur } };
11756
+ return succeed(cur);
11631
11757
  }
11632
11758
  const sentDef = sentinel._def;
11633
11759
  const expected = sentDef.tag === "literal" ? [JSON.stringify(sentDef.value)] : ["sentinel"];
@@ -11928,6 +12054,8 @@ function assemble(t, prog, cfg) {
11928
12054
  for (const s of prog.scans ?? []) {
11929
12055
  for (const r of s.skip) labelExtraIps.push(r[0]);
11930
12056
  if (s.sentinel !== void 0) labelExtraIps.push(s.sentinel[0]);
12057
+ if (s.recoverAt !== void 0) labelExtraIps.push(s.recoverAt[0]);
12058
+ if (s.stopAt !== void 0) labelExtraIps.push(s.stopAt[0]);
11931
12059
  }
11932
12060
  for (const set of prog.scanSkip ?? []) for (const r of set) labelExtraIps.push(r[0]);
11933
12061
  const closureLabels = computeSiteLabels(
@@ -14613,6 +14741,8 @@ function assemble(t, prog, cfg) {
14613
14741
  for (const s of prog.scans ?? []) {
14614
14742
  for (const r of s.skip) extraIps.push(r[0]);
14615
14743
  if (s.sentinel !== void 0) extraIps.push(s.sentinel[0]);
14744
+ if (s.recoverAt !== void 0) extraIps.push(s.recoverAt[0]);
14745
+ if (s.stopAt !== void 0) extraIps.push(s.stopAt[0]);
14616
14746
  }
14617
14747
  for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
14618
14748
  const roots = [...Object.values(prog.rules), ...extraIps];
@@ -14824,7 +14954,13 @@ function assemble(t, prog, cfg) {
14824
14954
  continue;
14825
14955
  }
14826
14956
  const sentDef = typeof s.sent === "string" ? { tag: "literal", value: s.sent, caseInsensitive: false } : void 0;
14827
- scansArr.push(scanTo(subtreeComb(s.sentinel, sentDef), { skip, raw, orEOF: (s.flags & 2) !== 0 }));
14957
+ scansArr.push(scanTo(subtreeComb(s.sentinel, sentDef), {
14958
+ skip,
14959
+ raw,
14960
+ orEOF: (s.flags & 2) !== 0,
14961
+ ...s.recoverAt === void 0 ? {} : { recoverAt: subtreeComb(s.recoverAt) },
14962
+ ...s.stopAt === void 0 ? {} : { stopAt: subtreeComb(s.stopAt) }
14963
+ }));
14828
14964
  }
14829
14965
  const scans = scansArr;
14830
14966
  const scanSkip = (prog.scanSkip ?? []).map((set) => set.map((r) => subtreeComb(r)));
@@ -15041,6 +15177,8 @@ function emitRef(r) {
15041
15177
  function emitScanSpec(s) {
15042
15178
  const parts = [`kind:${s.kind}`, `flags:${s.flags}`, `skip:[${s.skip.map(emitRef).join(",")}]`];
15043
15179
  if (s.sentinel !== void 0) parts.push(`sentinel:${emitRef(s.sentinel)}`);
15180
+ if (s.recoverAt !== void 0) parts.push(`recoverAt:${emitRef(s.recoverAt)}`);
15181
+ if (s.stopAt !== void 0) parts.push(`stopAt:${emitRef(s.stopAt)}`);
15044
15182
  if (s.sent !== void 0) parts.push(`sent:${s.sent === null ? "null" : jsString(s.sent)}`);
15045
15183
  if (s.open !== void 0) parts.push(`open:${jsString(s.open)}`);
15046
15184
  if (s.close !== void 0) parts.push(`close:${jsString(s.close)}`);
@@ -15067,6 +15205,8 @@ function emitAssemblies(prog, cfgs) {
15067
15205
  for (const s of prog.scans ?? []) {
15068
15206
  for (const r of s.skip) extraIps.push(r[0]);
15069
15207
  if (s.sentinel !== void 0) extraIps.push(s.sentinel[0]);
15208
+ if (s.recoverAt !== void 0) extraIps.push(s.recoverAt[0]);
15209
+ if (s.stopAt !== void 0) extraIps.push(s.stopAt[0]);
15070
15210
  }
15071
15211
  for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
15072
15212
  const out = [];
@@ -15209,7 +15349,12 @@ function children(def, winners) {
15209
15349
  case "sepBy":
15210
15350
  return [def.parser, def.separator];
15211
15351
  case "scanTo":
15212
- return [def.sentinel, ...def.skip];
15352
+ return [
15353
+ def.sentinel,
15354
+ ...def.skip,
15355
+ ...def.recoverAt === void 0 ? [] : [def.recoverAt],
15356
+ ...def.stopAt === void 0 ? [] : [def.stopAt]
15357
+ ];
15213
15358
  case "lazy": {
15214
15359
  let resolved;
15215
15360
  try {
@@ -15322,7 +15467,7 @@ function payloadKey(p, d) {
15322
15467
  case "expect":
15323
15468
  return `expect\0${d.label ?? ""}\0${d.expected.join("")}`;
15324
15469
  case "scanTo":
15325
- return `scanTo\0${d.raw}\0${d.orEOF}`;
15470
+ return `scanTo\0${d.raw}\0${d.orEOF}\0${d.recoverAt !== void 0}\0${d.stopAt !== void 0}`;
15326
15471
  case "guard":
15327
15472
  return `guard\0${fnKey(d.predSrc, d.predicate)}`;
15328
15473
  case "adjacency":
@@ -15437,8 +15582,12 @@ function segment(d, index) {
15437
15582
  return index === 0 ? "sepBy.item" : "sepBy.sep";
15438
15583
  case "recover":
15439
15584
  return index === 0 ? "recover.body" : "recover.sentinel";
15440
- case "scanTo":
15441
- return index === 0 ? "scanTo.sentinel" : `scanTo.skip[${index - 1}]`;
15585
+ case "scanTo": {
15586
+ if (index === 0) return "scanTo.sentinel";
15587
+ if (index <= d.skip.length) return `scanTo.skip[${index - 1}]`;
15588
+ if (d.recoverAt !== void 0 && index === d.skip.length + 1) return "scanTo.recoverAt";
15589
+ return "scanTo.stopAt";
15590
+ }
15442
15591
  default:
15443
15592
  return d.tag;
15444
15593
  }
@@ -16714,7 +16863,12 @@ function childrenOf3(def) {
16714
16863
  case "sepBy":
16715
16864
  return [def.parser, def.separator];
16716
16865
  case "scanTo":
16717
- return [def.sentinel, ...def.skip];
16866
+ return [
16867
+ def.sentinel,
16868
+ ...def.skip,
16869
+ ...def.recoverAt === void 0 ? [] : [def.recoverAt],
16870
+ ...def.stopAt === void 0 ? [] : [def.stopAt]
16871
+ ];
16718
16872
  case "routed":
16719
16873
  return def.fallback ? [def.fallback] : [];
16720
16874
  case "lazy":
@@ -17208,7 +17362,7 @@ ${outerDecls.map((d) => " " + d).join("\n")}
17208
17362
  case "expect":
17209
17363
  return `expect(${kid(def.parser)}${def.label !== void 0 ? `, ${JSON.stringify(def.label)}` : ""})`;
17210
17364
  case "scanTo":
17211
- return `scanTo(${kid(def.sentinel)}, { skip: [${def.skip.map(kid).join(", ")}]${def.raw ? ", raw: true" : ""}, orEOF: ${def.orEOF} })`;
17365
+ return `scanTo(${kid(def.sentinel)}, { skip: [${def.skip.map(kid).join(", ")}]${def.raw ? ", raw: true" : ""}, orEOF: ${def.orEOF}${def.recoverAt === void 0 ? "" : `, recoverAt: ${kid(def.recoverAt)}`}${def.stopAt === void 0 ? "" : `, stopAt: ${kid(def.stopAt)}`} })`;
17212
17366
  case "transform": {
17213
17367
  if (def.fnSrc === void 0) throw new Unserializable("transform without fnSrc");
17214
17368
  return `_tf(${kid(def.parser)}, ${JSON.stringify(def.fnSrc)}${def.recognitionOnly ? ", true" : ""})`;
@@ -17388,7 +17542,7 @@ function compileRuleMap(ruleMap, opts = {}) {
17388
17542
  }
17389
17543
 
17390
17544
  // src/version.ts
17391
- var PARSEMAN_VERSION = "0.50.7";
17545
+ var PARSEMAN_VERSION = "0.51.0";
17392
17546
 
17393
17547
  // src/compiler/compile-linkable-table.ts
17394
17548
  function isLocal(rule) {
@@ -18454,8 +18608,12 @@ function slotLabel(d, index) {
18454
18608
  return index === 0 ? "sepBy.item" : "sepBy.sep";
18455
18609
  case "recover":
18456
18610
  return index === 0 ? "recover.parser" : "recover.sentinel";
18457
- case "scanTo":
18458
- return index === 0 ? "scanTo.sentinel" : `scanTo.skip[${index - 1}]`;
18611
+ case "scanTo": {
18612
+ if (index === 0) return "scanTo.sentinel";
18613
+ if (index <= d.skip.length) return `scanTo.skip[${index - 1}]`;
18614
+ if (d.recoverAt !== void 0 && index === d.skip.length + 1) return "scanTo.recoverAt";
18615
+ return "scanTo.stopAt";
18616
+ }
18459
18617
  case "grammar":
18460
18618
  return index === 0 ? "grammar" : "grammar.trivia";
18461
18619
  case "node":
@@ -20121,7 +20279,13 @@ function coverageEntry(entry, collector, maps, trace) {
20121
20279
  case "expect":
20122
20280
  return expect(build(def.parser), def.label);
20123
20281
  case "scanTo":
20124
- return scanTo(build(def.sentinel), { skip: def.skip.map(build), orEOF: def.orEOF });
20282
+ return scanTo(build(def.sentinel), {
20283
+ skip: def.skip.map(build),
20284
+ raw: def.raw,
20285
+ orEOF: def.orEOF,
20286
+ ...def.recoverAt === void 0 ? {} : { recoverAt: build(def.recoverAt) },
20287
+ ...def.stopAt === void 0 ? {} : { stopAt: build(def.stopAt) }
20288
+ });
20125
20289
  // Zero-width assertion with no coverage-bearing child; reuse it verbatim so
20126
20290
  // the rebuilt sequence still recognises the boundary marker.
20127
20291
  case "adjacency":