parseman 0.60.6 → 0.61.1

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 (60) hide show
  1. package/dist/analysis/backtrack.d.ts +50 -0
  2. package/dist/analysis/backtrack.d.ts.map +1 -0
  3. package/dist/analysis/diagnostics.d.ts +3 -0
  4. package/dist/analysis/diagnostics.d.ts.map +1 -1
  5. package/dist/analysis/diagnostics.js +1162 -158
  6. package/dist/analysis/diagnostics.js.map +3 -3
  7. package/dist/analysis/rebuild.d.ts +17 -1
  8. package/dist/analysis/rebuild.d.ts.map +1 -1
  9. package/dist/cli/index.js +353 -69
  10. package/dist/cli/index.js.map +3 -3
  11. package/dist/combinators/choice.d.ts.map +1 -1
  12. package/dist/combinators/dispatch.d.ts +2 -0
  13. package/dist/combinators/dispatch.d.ts.map +1 -1
  14. package/dist/combinators/expect.d.ts.map +1 -1
  15. package/dist/combinators/link-scope.d.ts +7 -0
  16. package/dist/combinators/link-scope.d.ts.map +1 -0
  17. package/dist/combinators/node.d.ts.map +1 -1
  18. package/dist/combinators/parser.d.ts.map +1 -1
  19. package/dist/compiler/token-capability.js +1 -0
  20. package/dist/compiler/token-capability.js.map +1 -1
  21. package/dist/compiler/value-usage.d.ts.map +1 -1
  22. package/dist/coverage.d.ts.map +1 -1
  23. package/dist/functional/run.d.ts.map +1 -1
  24. package/dist/index.js +121 -90
  25. package/dist/index.js.map +3 -3
  26. package/dist/language-service/index.js +1 -1
  27. package/dist/language-service/index.js.map +1 -1
  28. package/dist/plugin/index.js +274 -243
  29. package/dist/plugin/index.js.map +3 -3
  30. package/dist/run/index.js +1 -1
  31. package/dist/run/index.js.map +1 -1
  32. package/dist/spec/index.js.map +1 -1
  33. package/dist/table/backtrack-probe.d.ts +41 -0
  34. package/dist/table/backtrack-probe.d.ts.map +1 -0
  35. package/dist/table/child-slots.d.ts +10 -0
  36. package/dist/table/child-slots.d.ts.map +1 -1
  37. package/dist/table/emit.d.ts.map +1 -1
  38. package/dist/table/index.js +31 -20
  39. package/dist/table/index.js.map +3 -3
  40. package/dist/table/program.d.ts +3 -1
  41. package/dist/table/program.d.ts.map +1 -1
  42. package/dist/version.d.ts +1 -1
  43. package/package.json +5 -1
  44. package/src/analysis/backtrack.ts +249 -0
  45. package/src/analysis/diagnostics.ts +4 -0
  46. package/src/analysis/rebuild.ts +63 -11
  47. package/src/combinators/choice.ts +3 -1
  48. package/src/combinators/dispatch.ts +9 -0
  49. package/src/combinators/expect.ts +1 -0
  50. package/src/combinators/link-scope.ts +19 -0
  51. package/src/combinators/node.ts +11 -2
  52. package/src/combinators/parser.ts +37 -31
  53. package/src/compiler/value-usage.ts +16 -29
  54. package/src/coverage.ts +2 -14
  55. package/src/functional/run.ts +3 -1
  56. package/src/table/backtrack-probe.ts +326 -0
  57. package/src/table/child-slots.ts +30 -14
  58. package/src/table/emit.ts +5 -1
  59. package/src/table/program.ts +8 -2
  60. package/src/version.ts +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/functional/run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAQ,MAAM,aAAa,CAAA;AAG1F,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAMrF;;;;;;;;;;;;GAYG;AAEH,+EAA+E;AAC/E,MAAM,MAAM,QAAQ,GAChB,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,KAAK,WAAW,CAAC,OAAO,CAAC,CAAC,GACzE,UAAU,CAAC,OAAO,CAAC,CAAA;AAEvB,MAAM,MAAM,UAAU,GAAG;IACvB;;;;eAIW;IACX,eAAe,CAAC,EAAE;QAChB,gBAAgB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;QACvC,aAAa,CAAC,EAAE;YAAE,KAAK,CAAC,KAAK,EAAE;gBAAE,EAAE,EAAE,MAAM,CAAC;gBAAC,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,CAAC;gBAAC,MAAM,EAAE,MAAM,CAAC;gBAAC,GAAG,CAAC,EAAE,MAAM,CAAA;aAAE,GAAG,IAAI,CAAA;SAAE,CAAA;KACjL,CAAA;IACD;qFACiF;IACjF,KAAK,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,CAAA;IAC7B,uDAAuD;IACvD,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,EAAE,QAAQ,CAAA;IACjB;;;;;;;OAOG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B;;;;OAIG;IACH,UAAU,CAAC,EAAE;QACX,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;KACnC,CAAA;IACD;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,mFAAmF;IACnF,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IAChC,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC,sEAAsE;IACtE,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAA;CAChC,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,EAAE,EAAE,OAAO,CAAA;IACX,0DAA0D;IAC1D,KAAK,EAAE,OAAO,CAAA;IACd,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;IACpC,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,gGAAgG;IAChG,MAAM,EAAE,UAAU,EAAE,CAAA;IACpB;;;;OAIG;IACH,UAAU,CAAC,EAAE,iBAAiB,CAAA;IAC9B;;;;qEAIiE;IACjE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B,CAAA;AAgbD,wBAAgB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,GAAG,SAAS,CAEvF"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/functional/run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAQ,MAAM,aAAa,CAAA;AAG1F,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAMrF;;;;;;;;;;;;GAYG;AAEH,+EAA+E;AAC/E,MAAM,MAAM,QAAQ,GAChB,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,KAAK,WAAW,CAAC,OAAO,CAAC,CAAC,GACzE,UAAU,CAAC,OAAO,CAAC,CAAA;AAEvB,MAAM,MAAM,UAAU,GAAG;IACvB;;;;eAIW;IACX,eAAe,CAAC,EAAE;QAChB,gBAAgB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;QACvC,aAAa,CAAC,EAAE;YAAE,KAAK,CAAC,KAAK,EAAE;gBAAE,EAAE,EAAE,MAAM,CAAC;gBAAC,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,CAAC;gBAAC,MAAM,EAAE,MAAM,CAAC;gBAAC,GAAG,CAAC,EAAE,MAAM,CAAA;aAAE,GAAG,IAAI,CAAA;SAAE,CAAA;KACjL,CAAA;IACD;qFACiF;IACjF,KAAK,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,CAAA;IAC7B,uDAAuD;IACvD,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,EAAE,QAAQ,CAAA;IACjB;;;;;;;OAOG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B;;;;OAIG;IACH,UAAU,CAAC,EAAE;QACX,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;KACnC,CAAA;IACD;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,mFAAmF;IACnF,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IAChC,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC,sEAAsE;IACtE,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAA;CAChC,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,EAAE,EAAE,OAAO,CAAA;IACX,0DAA0D;IAC1D,KAAK,EAAE,OAAO,CAAA;IACd,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;IACpC,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,gGAAgG;IAChG,MAAM,EAAE,UAAU,EAAE,CAAA;IACpB;;;;OAIG;IACH,UAAU,CAAC,EAAE,iBAAiB,CAAA;IAC9B;;;;qEAIiE;IACjE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B,CAAA;AAkbD,wBAAgB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,GAAG,SAAS,CAEvF"}
package/dist/index.js CHANGED
@@ -3203,6 +3203,7 @@ function derive(c, seen) {
3203
3203
  case "optional":
3204
3204
  case "many":
3205
3205
  case "oneOrMore":
3206
+ case "sepBy":
3206
3207
  case "transform":
3207
3208
  case "not":
3208
3209
  case "peek":
@@ -3353,7 +3354,7 @@ function choice(...args) {
3353
3354
  const result = parsers[idx].parse(input, pos, ctx);
3354
3355
  if (result.ok) return result;
3355
3356
  expected.push(...result.expected);
3356
- if (result.committed) return { ok: false, expected, span: { start: pos, end: pos }, committed: true };
3357
+ if (result.committed) return { ok: false, expected, span: result.span, committed: true };
3357
3358
  return { ok: false, expected, span: { start: pos, end: pos } };
3358
3359
  }
3359
3360
  if (ctx._probe !== void 0 || ctx._tolerant) for (const p of parsers) p.parse(input, pos, ctx);
@@ -3694,6 +3695,16 @@ function matches(pattern) {
3694
3695
  }
3695
3696
  return { kind: "matches", value: pattern.source, flags: pattern.flags };
3696
3697
  }
3698
+ function dispatchMatcher(entry) {
3699
+ switch (entry.kind) {
3700
+ case "startsWith":
3701
+ return startsWith(entry.value);
3702
+ case "endsWith":
3703
+ return endsWith(entry.value);
3704
+ case "matches":
3705
+ return matches(new RegExp(entry.value, entry.flags));
3706
+ }
3707
+ }
3697
3708
  function when(key, parser2, opts = {}) {
3698
3709
  const usesRouted = parserUsesRouted(parser2);
3699
3710
  if (isStringMatcher(key)) {
@@ -4348,15 +4359,20 @@ function markUnusedValues(root) {
4348
4359
  case "many":
4349
4360
  case "oneOrMore":
4350
4361
  mark(def, consumed);
4351
- visit(def.parser, consumed);
4352
- return;
4353
4362
  case "optional":
4363
+ // `optional` returns `inner | null` — no aggregate array/tuple to elide, so
4364
+ // it carries no valueUnused flag. Still descend so an inner many/sequence
4365
+ // under a node() is analyzed (it benefits even when its optional wrapper
4366
+ // doesn't).
4367
+ case "label":
4368
+ case "trivia":
4369
+ case "attempt":
4370
+ case "withCtx":
4371
+ case "expect":
4354
4372
  visit(def.parser, consumed);
4355
4373
  return;
4356
4374
  case "sequence":
4357
4375
  mark(def, consumed);
4358
- for (const p of def.parsers) visit(p, consumed);
4359
- return;
4360
4376
  case "choice":
4361
4377
  for (const p of def.parsers) visit(p, consumed);
4362
4378
  return;
@@ -4367,22 +4383,24 @@ function markUnusedValues(root) {
4367
4383
  if (def.otherwise) visit(def.otherwise, consumed);
4368
4384
  return;
4369
4385
  case "node":
4386
+ // builds from captured children, NOT the inner parser value.
4387
+ case "not":
4388
+ case "peek":
4389
+ // lookahead — value never observed
4390
+ case "token":
4370
4391
  visit(def.parser, false);
4371
4392
  return;
4372
4393
  case "transform":
4373
- visit(def.parser, true);
4374
- return;
4394
+ // the map fn reads the value → always consumed.
4375
4395
  case "field":
4396
+ // the field capture records the parsed value → always consumed.
4397
+ case "leaf":
4376
4398
  visit(def.parser, true);
4377
4399
  return;
4378
4400
  case "sepBy":
4379
4401
  visit(def.parser, true);
4380
4402
  visit(def.separator, false);
4381
4403
  return;
4382
- case "not":
4383
- case "peek":
4384
- visit(def.parser, false);
4385
- return;
4386
4404
  case "grammar":
4387
4405
  visit(def.parser, consumed);
4388
4406
  if (def.triviaParser) visit(def.triviaParser, false);
@@ -4391,19 +4409,6 @@ function markUnusedValues(root) {
4391
4409
  visit(def.parser, consumed);
4392
4410
  visit(def.sentinel, false);
4393
4411
  return;
4394
- case "token":
4395
- visit(def.parser, false);
4396
- return;
4397
- case "label":
4398
- case "trivia":
4399
- case "attempt":
4400
- case "withCtx":
4401
- case "expect":
4402
- visit(def.parser, consumed);
4403
- return;
4404
- case "leaf":
4405
- visit(def.parser, true);
4406
- return;
4407
4412
  case "lazy":
4408
4413
  return;
4409
4414
  default:
@@ -4433,6 +4438,21 @@ function markUnusedValues(root) {
4433
4438
  visit(resolveRoot2(root), true);
4434
4439
  }
4435
4440
 
4441
+ // src/combinators/link-scope.ts
4442
+ var scope;
4443
+ function afterLink(settle) {
4444
+ scope?.push(settle);
4445
+ }
4446
+ function collectAfterLink(pending, build) {
4447
+ const outer = scope;
4448
+ scope = outer ?? pending;
4449
+ try {
4450
+ return build();
4451
+ } finally {
4452
+ scope = outer;
4453
+ }
4454
+ }
4455
+
4436
4456
  // src/cst/root-trivia-scope.ts
4437
4457
  var ROOT_TRIVIA_SCOPE_REFUSAL = "parser(): selected root trivia requires classifiedTrivia() for every local trivia scope, or rootCapture: 'opaque'.";
4438
4458
  function refuseUnclassifiedRootScope(strict) {
@@ -4779,6 +4799,7 @@ function linkRules(recipes, link) {
4779
4799
  }
4780
4800
  });
4781
4801
  const winners = /* @__PURE__ */ new Map();
4802
+ const afterLink2 = [];
4782
4803
  const priorHoles = /* @__PURE__ */ new Map();
4783
4804
  const prior = new Proxy({}, {
4784
4805
  get(_target, key) {
@@ -4791,38 +4812,42 @@ function linkRules(recipes, link) {
4791
4812
  return hole;
4792
4813
  }
4793
4814
  });
4794
- for (const recipe of recipes) {
4795
- const definitions = recipe.factory(proxy, prior);
4796
- for (const key of Object.keys(definitions)) {
4797
- winners.set(key, { parser: definitions[key], options: recipe.options });
4798
- }
4799
- }
4800
- const keys = [...winners.keys()];
4801
4815
  const copies = /* @__PURE__ */ new Map();
4802
- for (const [key, { parser: defined }] of winners) {
4803
- const placeholder = cache[key];
4804
- const parser2 = ownRule(defined, copies);
4805
- if (placeholder === parser2) {
4806
- throw new Error(`rules(): rule "${key}" cannot be a direct alias to itself`);
4807
- }
4808
- if (isDefinableRef(placeholder)) {
4809
- if (!isNamedRuleRefForAnotherRule(parser2, key)) tagRule(parser2, key);
4810
- placeholder.define(parser2);
4811
- placeholder._meta.firstSet = parser2._meta.firstSet;
4812
- placeholder._meta.canMatchNewline = parser2._meta.canMatchNewline;
4813
- } else if (isNamedRuleRefForAnotherRule(parser2, key) || link !== void 0) {
4814
- if (!isNamedRuleRefForAnotherRule(parser2, key)) tagRule(parser2, key);
4815
- const alias = ref();
4816
- tagRule(alias, key);
4817
- alias.define(parser2);
4818
- alias._meta.firstSet = parser2._meta.firstSet;
4819
- alias._meta.canMatchNewline = parser2._meta.canMatchNewline;
4820
- cache[key] = alias;
4821
- } else {
4822
- tagRule(parser2, key);
4823
- cache[key] = parser2;
4816
+ try {
4817
+ for (const recipe of recipes) {
4818
+ const definitions = collectAfterLink(afterLink2, () => recipe.factory(proxy, prior));
4819
+ for (const key of Object.keys(definitions)) {
4820
+ winners.set(key, { parser: definitions[key], options: recipe.options });
4821
+ }
4822
+ }
4823
+ for (const [key, { parser: defined }] of winners) {
4824
+ const placeholder = cache[key];
4825
+ const parser2 = ownRule(defined, copies);
4826
+ if (placeholder === parser2) {
4827
+ throw new Error(`rules(): rule "${key}" cannot be a direct alias to itself`);
4828
+ }
4829
+ if (isDefinableRef(placeholder)) {
4830
+ if (!isNamedRuleRefForAnotherRule(parser2, key)) tagRule(parser2, key);
4831
+ placeholder.define(parser2);
4832
+ placeholder._meta.firstSet = parser2._meta.firstSet;
4833
+ placeholder._meta.canMatchNewline = parser2._meta.canMatchNewline;
4834
+ } else if (isNamedRuleRefForAnotherRule(parser2, key) || link !== void 0) {
4835
+ if (!isNamedRuleRefForAnotherRule(parser2, key)) tagRule(parser2, key);
4836
+ const alias = ref();
4837
+ tagRule(alias, key);
4838
+ alias.define(parser2);
4839
+ alias._meta.firstSet = parser2._meta.firstSet;
4840
+ alias._meta.canMatchNewline = parser2._meta.canMatchNewline;
4841
+ cache[key] = alias;
4842
+ } else {
4843
+ tagRule(parser2, key);
4844
+ cache[key] = parser2;
4845
+ }
4824
4846
  }
4847
+ } finally {
4848
+ for (const settle of afterLink2) settle();
4825
4849
  }
4850
+ const keys = [...winners.keys()];
4826
4851
  for (const key of keys) {
4827
4852
  const options = winners.get(key).options;
4828
4853
  let rule = cache[key];
@@ -5307,8 +5332,14 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
5307
5332
  const def = unwrap || collapse || project !== void 0 || captureTrivia || trailingTrivia || buildArity !== void 0 || tags !== void 0 && tags.length > 0 ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {}, ...project !== void 0 ? { project } : {}, ...captureTrivia ? { captureTrivia: true } : {}, ...trailingTrivia ? { trailingTrivia: true } : {}, ...buildArity !== void 0 ? { buildArity } : {}, ...tags !== void 0 && tags.length > 0 ? { tags } : {} } : baseDef;
5308
5333
  const capturesTrivia = captureTrivia || (build ? buildReadsTrivia(def) : project === void 0);
5309
5334
  const readsState = build ? buildReadsState(def) : project === void 0;
5310
- const hasOwnFields = parserHasOwnFields(combinator);
5311
- const capturesFields = hasOwnFields && (build ? buildReadsFields(def) : project === void 0);
5335
+ let hasOwnFields = parserHasOwnFields(combinator);
5336
+ let capturesFields = hasOwnFields && (build ? buildReadsFields(def) : project === void 0);
5337
+ if (!hasOwnFields) {
5338
+ afterLink(() => {
5339
+ hasOwnFields = parserHasOwnFields(combinator);
5340
+ capturesFields = hasOwnFields && (build ? buildReadsFields(def) : project === void 0);
5341
+ });
5342
+ }
5312
5343
  const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
5313
5344
  let failExpected;
5314
5345
  return {
@@ -5621,6 +5652,9 @@ function sourceLeaf(root, fn) {
5621
5652
  return makeLeaf(root, fn, true);
5622
5653
  }
5623
5654
 
5655
+ // src/version.ts
5656
+ var PARSEMAN_VERSION = "0.61.1";
5657
+
5624
5658
  // src/table/lex-body.ts
5625
5659
  function buildLexBodyRecognizer(spec, constants) {
5626
5660
  const raw = constants[spec[0]];
@@ -6236,11 +6270,12 @@ function assemblyExtraIps(prog) {
6236
6270
  }
6237
6271
  function expandCompact(p) {
6238
6272
  if ("code" in p) return p;
6273
+ if (p.es === void 0) throw new Error(`parseman: this parser was printed by an earlier parseman; reprint it with parseman ${PARSEMAN_VERSION}`);
6239
6274
  return ownTableProgram({
6240
6275
  code: p.c,
6241
6276
  k: p.k,
6242
6277
  cc: p.x,
6243
- fx: p.e,
6278
+ fx: p.e.map((set) => set.map((i) => p.es[i])),
6244
6279
  disp: p.d,
6245
6280
  rules: p.r,
6246
6281
  fns: p.f,
@@ -7649,7 +7684,7 @@ function selectOptionalSuffixLexBody(ir) {
7649
7684
  function reinstallsRuleTrivia(reference, target) {
7650
7685
  return (reference._meta.grammarTrivia ?? target._meta.grammarTrivia) !== void 0 && hasOwnTriviaBoundary(target);
7651
7686
  }
7652
- function directTokenBodyParser(parser2, resolve, scope) {
7687
+ function directTokenBodyParser(parser2, resolve, scope2) {
7653
7688
  const outer = parser2._def;
7654
7689
  if (outer.tag !== "token") return void 0;
7655
7690
  let body = outer.parser;
@@ -7659,7 +7694,7 @@ function directTokenBodyParser(parser2, resolve, scope) {
7659
7694
  const wrapper = body._def;
7660
7695
  if (wrapper.tag === "grammar") {
7661
7696
  if (wrapper.clearTrivia !== true || wrapper.triviaParser !== void 0 || wrapper.captureTrivia === true || wrapper.rootCapture === "opaque" || wrapper.constructionTrackLines !== "inherit" || wrapper.constructionCaptureTriviaKinds !== void 0) return void 0;
7662
- if (scope !== void 0) scope.cleared = true;
7697
+ if (scope2 !== void 0) scope2.cleared = true;
7663
7698
  body = wrapper.parser;
7664
7699
  continue;
7665
7700
  }
@@ -7916,10 +7951,10 @@ function directFixedLexNode(parser2, resolve, active, pureOnly = false, cleared
7916
7951
  }
7917
7952
  }
7918
7953
  function directFixedTokenBody(parser2, resolve) {
7919
- const scope = { cleared: false };
7920
- const body = directTokenBodyParser(parser2, resolve, scope);
7954
+ const scope2 = { cleared: false };
7955
+ const body = directTokenBodyParser(parser2, resolve, scope2);
7921
7956
  if (body === void 0) return void 0;
7922
- const root = directFixedLexNode(body, resolve, /* @__PURE__ */ new Set(), false, scope.cleared);
7957
+ const root = directFixedLexNode(body, resolve, /* @__PURE__ */ new Set(), false, scope2.cleared);
7923
7958
  return root === void 0 ? void 0 : { kind: "fixed-tree", root };
7924
7959
  }
7925
7960
  function directBalancedTokenBody(parser2, resolve) {
@@ -10776,6 +10811,12 @@ function emitShapeMatch(shape, start, mint, ind, firstChar) {
10776
10811
 
10777
10812
  // src/table/child-slots.ts
10778
10813
  function childSlots(code, ip, out) {
10814
+ const from = out.length;
10815
+ if (!childSlotOffsets(code, ip, out)) return false;
10816
+ for (let i = from; i < out.length; i++) out[i] = code[out[i]];
10817
+ return true;
10818
+ }
10819
+ function childSlotOffsets(code, ip, out) {
10779
10820
  switch (code[ip]) {
10780
10821
  // ZERO-WIDTH / TERMINAL ROWS — no successor. `OP_GUARD` and `OP_ADJ` are both
10781
10822
  // childless tests. `OP_LIVE` holds a hand-written combinator in `prog.fns`; its
@@ -10808,7 +10849,7 @@ function childSlots(code, ip, out) {
10808
10849
  case OP_COV:
10809
10850
  case OP_REJECT:
10810
10851
  case OP_GAPGATE:
10811
- out.push(code[ip + 1]);
10852
+ out.push(ip + 1);
10812
10853
  return true;
10813
10854
  // Single child at `ip + 2`.
10814
10855
  case OP_GATE:
@@ -10825,55 +10866,55 @@ function childSlots(code, ip, out) {
10825
10866
  case OP_ARMGATE:
10826
10867
  case OP_RGATE:
10827
10868
  case OP_RGATE2:
10828
- out.push(code[ip + 2]);
10869
+ out.push(ip + 2);
10829
10870
  return true;
10830
10871
  // `STRICT strict tolerant` — both encodings are reachable; an assembly keeps one.
10831
10872
  case OP_STRICT:
10832
- out.push(code[ip + 1], code[ip + 2]);
10873
+ out.push(ip + 1, ip + 2);
10833
10874
  return true;
10834
10875
  // `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
10835
10876
  // data the enclosing `dispatch()` already consumed, so the only edge is the
10836
10877
  // fallback.
10837
10878
  case OP_ROUTED:
10838
- if (code[ip + 1] >= 0) out.push(code[ip + 1]);
10879
+ if (code[ip + 1] >= 0) out.push(ip + 1);
10839
10880
  return true;
10840
10881
  // `DISPATCH sel d other otherRouted n a1 … an` — the SELECTOR is a child on
10841
10882
  // exactly the same footing as the arms: it runs inside whatever node and scope
10842
10883
  // this site sits in.
10843
10884
  case OP_DISPATCH: {
10844
- out.push(code[ip + 1]);
10845
- if (code[ip + 3] >= 0) out.push(code[ip + 3]);
10885
+ out.push(ip + 1);
10886
+ if (code[ip + 3] >= 0) out.push(ip + 3);
10846
10887
  const n = code[ip + 5];
10847
- for (let i = 0; i < n; i++) out.push(code[ip + 6 + i]);
10888
+ for (let i = 0; i < n; i++) out.push(ip + 6 + i);
10848
10889
  return true;
10849
10890
  }
10850
10891
  case OP_SEQ:
10851
10892
  case OP_SEQV: {
10852
10893
  const n = code[ip + 1];
10853
- for (let i = 0; i < n; i++) out.push(code[ip + 2 + i]);
10894
+ for (let i = 0; i < n; i++) out.push(ip + 2 + i);
10854
10895
  return true;
10855
10896
  }
10856
10897
  case OP_SEQX: {
10857
10898
  const n = code[ip + 2];
10858
- for (let i = 0; i < n; i++) out.push(code[ip + 3 + i]);
10899
+ for (let i = 0; i < n; i++) out.push(ip + 3 + i);
10859
10900
  return true;
10860
10901
  }
10861
10902
  case OP_CHOICE: {
10862
10903
  const n = code[ip + 2];
10863
- for (let i = 0; i < n; i++) out.push(code[ip + 4 + i]);
10904
+ for (let i = 0; i < n; i++) out.push(ip + 4 + i);
10864
10905
  return true;
10865
10906
  }
10866
10907
  // Arms are stride-2 from `ip + 4` — the gate word sits beside each arm offset.
10867
10908
  case OP_GREEDY: {
10868
- out.push(code[ip + 1]);
10909
+ out.push(ip + 1);
10869
10910
  const n = code[ip + 2];
10870
- for (let i = 0; i < n; i++) out.push(code[ip + 4 + 2 * i]);
10911
+ for (let i = 0; i < n; i++) out.push(ip + 4 + 2 * i);
10871
10912
  return true;
10872
10913
  }
10873
10914
  case OP_REP:
10874
10915
  case OP_REPV:
10875
- out.push(code[ip + 1]);
10876
- if (code[ip + 4] >= 0) out.push(code[ip + 4]);
10916
+ out.push(ip + 1);
10917
+ if (code[ip + 4] >= 0) out.push(ip + 4);
10877
10918
  return true;
10878
10919
  default:
10879
10920
  return false;
@@ -13918,9 +13959,6 @@ function clearOf(ranges, input, from, to) {
13918
13959
  return true;
13919
13960
  }
13920
13961
 
13921
- // src/version.ts
13922
- var PARSEMAN_VERSION = "0.60.6";
13923
-
13924
13962
  // src/table/assemble.ts
13925
13963
  import { PlainBuf as PlainBuf2, PlainField, PlainLeaf as PlainLeaf9, PlainNode as PlainNode2, PlainSpan as PlainSpan10 } from "./cst/plain.js";
13926
13964
 
@@ -17928,12 +17966,15 @@ function assertPrintable(prog, who) {
17928
17966
  }
17929
17967
  }
17930
17968
  function programFields(prog, fns, opts = {}) {
17969
+ const tokens = [...new Set(prog.fx.flat())];
17970
+ const tokenAt = new Map(tokens.map((token2, i) => [token2, i]));
17931
17971
  return [
17932
17972
  ...emitAssemblies(prog, opts.assemblies ?? []),
17933
17973
  `c:[${prog.code.join(",")}],`,
17934
17974
  `k:[${prog.k.map(emitConst).join(",")}],`,
17935
17975
  `x:${emitClassPool(prog.cc)},`,
17936
- `e:[${prog.fx.map((f) => `[${f.map(jsString).join(",")}]`).join(",")}],`,
17976
+ `e:[${prog.fx.map((f) => `[${f.map((token2) => tokenAt.get(token2)).join(",")}]`).join(",")}],`,
17977
+ `es:[${tokens.map(jsString).join(",")}],`,
17937
17978
  `d:[${prog.disp.map((a) => `[${a.join(",")}]`).join(",")}],`,
17938
17979
  `r:${JSON.stringify(prog.rules)},`,
17939
17980
  ...prog.lines === 1 ? ["l:1,"] : [],
@@ -21056,7 +21097,7 @@ function runOnce(entry, input, options) {
21056
21097
  const r = invoke(entry, input, 0, ctx);
21057
21098
  const value = r.ok ? r.value : void 0;
21058
21099
  let span = r.span ?? { start: 0, end: 0 };
21059
- const expected = r.ok ? [] : r.expected ?? [];
21100
+ const expected = r.ok ? [] : [...new Set(r.expected ?? [])];
21060
21101
  let unconsumedFrom = null;
21061
21102
  if (r.ok) {
21062
21103
  let pos = span.end;
@@ -22510,16 +22551,6 @@ function run2(entry, input, options = {}) {
22510
22551
  }
22511
22552
 
22512
22553
  // src/coverage.ts
22513
- function dispatchMatcher(entry) {
22514
- switch (entry.kind) {
22515
- case "startsWith":
22516
- return startsWith(entry.value);
22517
- case "endsWith":
22518
- return endsWith(entry.value);
22519
- case "matches":
22520
- return matches(new RegExp(entry.value, entry.flags));
22521
- }
22522
- }
22523
22554
  function compiledGrammarCoverageDefinitions(grammar) {
22524
22555
  const definitions = grammar[GRAMMAR_COVERAGE_DEFINITIONS];
22525
22556
  if (!Array.isArray(definitions) || definitions.length === 0 || !definitions.every((definition) => typeof definition === "object" && definition !== null && typeof definition.id === "string" && (definition.kind === "rule" || definition.kind === "choice-arm" || definition.kind === "dispatch-arm" || definition.kind === "label"))) {