parseman 0.60.6 → 0.61.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 (40) hide show
  1. package/dist/analysis/diagnostics.js +47 -36
  2. package/dist/analysis/diagnostics.js.map +3 -3
  3. package/dist/cli/index.js +47 -36
  4. package/dist/cli/index.js.map +3 -3
  5. package/dist/combinators/choice.d.ts.map +1 -1
  6. package/dist/combinators/expect.d.ts.map +1 -1
  7. package/dist/combinators/link-scope.d.ts +7 -0
  8. package/dist/combinators/link-scope.d.ts.map +1 -0
  9. package/dist/combinators/node.d.ts.map +1 -1
  10. package/dist/combinators/parser.d.ts.map +1 -1
  11. package/dist/compiler/token-capability.js +1 -0
  12. package/dist/compiler/token-capability.js.map +1 -1
  13. package/dist/compiler/value-usage.d.ts.map +1 -1
  14. package/dist/functional/run.d.ts.map +1 -1
  15. package/dist/index.js +91 -66
  16. package/dist/index.js.map +3 -3
  17. package/dist/language-service/index.js +1 -1
  18. package/dist/language-service/index.js.map +1 -1
  19. package/dist/plugin/index.js +254 -229
  20. package/dist/plugin/index.js.map +3 -3
  21. package/dist/run/index.js +1 -1
  22. package/dist/run/index.js.map +1 -1
  23. package/dist/spec/index.js.map +1 -1
  24. package/dist/table/emit.d.ts.map +1 -1
  25. package/dist/table/index.js +11 -6
  26. package/dist/table/index.js.map +3 -3
  27. package/dist/table/program.d.ts +3 -1
  28. package/dist/table/program.d.ts.map +1 -1
  29. package/dist/version.d.ts +1 -1
  30. package/package.json +1 -1
  31. package/src/combinators/choice.ts +3 -1
  32. package/src/combinators/expect.ts +1 -0
  33. package/src/combinators/link-scope.ts +19 -0
  34. package/src/combinators/node.ts +11 -2
  35. package/src/combinators/parser.ts +37 -31
  36. package/src/compiler/value-usage.ts +16 -29
  37. package/src/functional/run.ts +3 -1
  38. package/src/table/emit.ts +5 -1
  39. package/src/table/program.ts +8 -2
  40. package/src/version.ts +1 -1
package/dist/cli/index.js CHANGED
@@ -2718,6 +2718,7 @@ function derive(c, seen) {
2718
2718
  case "optional":
2719
2719
  case "many":
2720
2720
  case "oneOrMore":
2721
+ case "sepBy":
2721
2722
  case "transform":
2722
2723
  case "not":
2723
2724
  case "peek":
@@ -2899,7 +2900,7 @@ function selectOptionalSuffixLexBody(ir) {
2899
2900
  function reinstallsRuleTrivia(reference, target) {
2900
2901
  return (reference._meta.grammarTrivia ?? target._meta.grammarTrivia) !== void 0 && hasOwnTriviaBoundary(target);
2901
2902
  }
2902
- function directTokenBodyParser(parser2, resolve2, scope) {
2903
+ function directTokenBodyParser(parser2, resolve2, scope2) {
2903
2904
  const outer = parser2._def;
2904
2905
  if (outer.tag !== "token") return void 0;
2905
2906
  let body = outer.parser;
@@ -2909,7 +2910,7 @@ function directTokenBodyParser(parser2, resolve2, scope) {
2909
2910
  const wrapper = body._def;
2910
2911
  if (wrapper.tag === "grammar") {
2911
2912
  if (wrapper.clearTrivia !== true || wrapper.triviaParser !== void 0 || wrapper.captureTrivia === true || wrapper.rootCapture === "opaque" || wrapper.constructionTrackLines !== "inherit" || wrapper.constructionCaptureTriviaKinds !== void 0) return void 0;
2912
- if (scope !== void 0) scope.cleared = true;
2913
+ if (scope2 !== void 0) scope2.cleared = true;
2913
2914
  body = wrapper.parser;
2914
2915
  continue;
2915
2916
  }
@@ -3166,10 +3167,10 @@ function directFixedLexNode(parser2, resolve2, active, pureOnly = false, cleared
3166
3167
  }
3167
3168
  }
3168
3169
  function directFixedTokenBody(parser2, resolve2) {
3169
- const scope = { cleared: false };
3170
- const body = directTokenBodyParser(parser2, resolve2, scope);
3170
+ const scope2 = { cleared: false };
3171
+ const body = directTokenBodyParser(parser2, resolve2, scope2);
3171
3172
  if (body === void 0) return void 0;
3172
- const root = directFixedLexNode(body, resolve2, /* @__PURE__ */ new Set(), false, scope.cleared);
3173
+ const root = directFixedLexNode(body, resolve2, /* @__PURE__ */ new Set(), false, scope2.cleared);
3173
3174
  return root === void 0 ? void 0 : { kind: "fixed-tree", root };
3174
3175
  }
3175
3176
  function directBalancedTokenBody(parser2, resolve2) {
@@ -4257,15 +4258,20 @@ function markUnusedValues(root) {
4257
4258
  case "many":
4258
4259
  case "oneOrMore":
4259
4260
  mark(def, consumed);
4260
- visit(def.parser, consumed);
4261
- return;
4262
4261
  case "optional":
4262
+ // `optional` returns `inner | null` — no aggregate array/tuple to elide, so
4263
+ // it carries no valueUnused flag. Still descend so an inner many/sequence
4264
+ // under a node() is analyzed (it benefits even when its optional wrapper
4265
+ // doesn't).
4266
+ case "label":
4267
+ case "trivia":
4268
+ case "attempt":
4269
+ case "withCtx":
4270
+ case "expect":
4263
4271
  visit(def.parser, consumed);
4264
4272
  return;
4265
4273
  case "sequence":
4266
4274
  mark(def, consumed);
4267
- for (const p of def.parsers) visit(p, consumed);
4268
- return;
4269
4275
  case "choice":
4270
4276
  for (const p of def.parsers) visit(p, consumed);
4271
4277
  return;
@@ -4276,22 +4282,24 @@ function markUnusedValues(root) {
4276
4282
  if (def.otherwise) visit(def.otherwise, consumed);
4277
4283
  return;
4278
4284
  case "node":
4285
+ // builds from captured children, NOT the inner parser value.
4286
+ case "not":
4287
+ case "peek":
4288
+ // lookahead — value never observed
4289
+ case "token":
4279
4290
  visit(def.parser, false);
4280
4291
  return;
4281
4292
  case "transform":
4282
- visit(def.parser, true);
4283
- return;
4293
+ // the map fn reads the value → always consumed.
4284
4294
  case "field":
4295
+ // the field capture records the parsed value → always consumed.
4296
+ case "leaf":
4285
4297
  visit(def.parser, true);
4286
4298
  return;
4287
4299
  case "sepBy":
4288
4300
  visit(def.parser, true);
4289
4301
  visit(def.separator, false);
4290
4302
  return;
4291
- case "not":
4292
- case "peek":
4293
- visit(def.parser, false);
4294
- return;
4295
4303
  case "grammar":
4296
4304
  visit(def.parser, consumed);
4297
4305
  if (def.triviaParser) visit(def.triviaParser, false);
@@ -4300,19 +4308,6 @@ function markUnusedValues(root) {
4300
4308
  visit(def.parser, consumed);
4301
4309
  visit(def.sentinel, false);
4302
4310
  return;
4303
- case "token":
4304
- visit(def.parser, false);
4305
- return;
4306
- case "label":
4307
- case "trivia":
4308
- case "attempt":
4309
- case "withCtx":
4310
- case "expect":
4311
- visit(def.parser, consumed);
4312
- return;
4313
- case "leaf":
4314
- visit(def.parser, true);
4315
- return;
4316
4311
  case "lazy":
4317
4312
  return;
4318
4313
  default:
@@ -4342,6 +4337,12 @@ function markUnusedValues(root) {
4342
4337
  visit(resolveRoot(root), true);
4343
4338
  }
4344
4339
 
4340
+ // src/combinators/link-scope.ts
4341
+ var scope;
4342
+ function afterLink(settle) {
4343
+ scope?.push(settle);
4344
+ }
4345
+
4345
4346
  // src/cst/root-trivia-scope.ts
4346
4347
  var ROOT_TRIVIA_SCOPE_REFUSAL = "parser(): selected root trivia requires classifiedTrivia() for every local trivia scope, or rootCapture: 'opaque'.";
4347
4348
  function refuseUnclassifiedRootScope(strict) {
@@ -4598,7 +4599,7 @@ function choice(...args) {
4598
4599
  const result = parsers[idx].parse(input, pos, ctx);
4599
4600
  if (result.ok) return result;
4600
4601
  expected.push(...result.expected);
4601
- if (result.committed) return { ok: false, expected, span: { start: pos, end: pos }, committed: true };
4602
+ if (result.committed) return { ok: false, expected, span: result.span, committed: true };
4602
4603
  return { ok: false, expected, span: { start: pos, end: pos } };
4603
4604
  }
4604
4605
  if (ctx._probe !== void 0 || ctx._tolerant) for (const p of parsers) p.parse(input, pos, ctx);
@@ -5498,6 +5499,9 @@ function regex(pattern, flags = "") {
5498
5499
  };
5499
5500
  }
5500
5501
 
5502
+ // src/version.ts
5503
+ var PARSEMAN_VERSION = "0.61.0";
5504
+
5501
5505
  // src/table/lex-body.ts
5502
5506
  function buildLexBodyRecognizer(spec, constants) {
5503
5507
  const raw = constants[spec[0]];
@@ -6113,11 +6117,12 @@ function assemblyExtraIps(prog) {
6113
6117
  }
6114
6118
  function expandCompact(p) {
6115
6119
  if ("code" in p) return p;
6120
+ if (p.es === void 0) throw new Error(`parseman: this parser was printed by an earlier parseman; reprint it with parseman ${PARSEMAN_VERSION}`);
6116
6121
  return ownTableProgram({
6117
6122
  code: p.c,
6118
6123
  k: p.k,
6119
6124
  cc: p.x,
6120
- fx: p.e,
6125
+ fx: p.e.map((set) => set.map((i) => p.es[i])),
6121
6126
  disp: p.d,
6122
6127
  rules: p.r,
6123
6128
  fns: p.f,
@@ -7318,8 +7323,14 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
7318
7323
  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;
7319
7324
  const capturesTrivia = captureTrivia || (build ? buildReadsTrivia(def) : project === void 0);
7320
7325
  const readsState = build ? buildReadsState(def) : project === void 0;
7321
- const hasOwnFields = parserHasOwnFields(combinator);
7322
- const capturesFields = hasOwnFields && (build ? buildReadsFields(def) : project === void 0);
7326
+ let hasOwnFields = parserHasOwnFields(combinator);
7327
+ let capturesFields = hasOwnFields && (build ? buildReadsFields(def) : project === void 0);
7328
+ if (!hasOwnFields) {
7329
+ afterLink(() => {
7330
+ hasOwnFields = parserHasOwnFields(combinator);
7331
+ capturesFields = hasOwnFields && (build ? buildReadsFields(def) : project === void 0);
7332
+ });
7333
+ }
7323
7334
  const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
7324
7335
  let failExpected;
7325
7336
  return {
@@ -13430,9 +13441,6 @@ function clearOf(ranges, input, from, to) {
13430
13441
  return true;
13431
13442
  }
13432
13443
 
13433
- // src/version.ts
13434
- var PARSEMAN_VERSION = "0.60.6";
13435
-
13436
13444
  // src/table/assemble.ts
13437
13445
  import { PlainBuf as PlainBuf2, PlainField, PlainLeaf as PlainLeaf9, PlainNode as PlainNode2, PlainSpan as PlainSpan10 } from "../cst/plain.js";
13438
13446
 
@@ -17412,12 +17420,15 @@ function assertPrintable(prog, who) {
17412
17420
  }
17413
17421
  }
17414
17422
  function programFields(prog, fns, opts = {}) {
17423
+ const tokens = [...new Set(prog.fx.flat())];
17424
+ const tokenAt = new Map(tokens.map((token2, i) => [token2, i]));
17415
17425
  return [
17416
17426
  ...emitAssemblies(prog, opts.assemblies ?? []),
17417
17427
  `c:[${prog.code.join(",")}],`,
17418
17428
  `k:[${prog.k.map(emitConst).join(",")}],`,
17419
17429
  `x:${emitClassPool(prog.cc)},`,
17420
- `e:[${prog.fx.map((f) => `[${f.map(jsString).join(",")}]`).join(",")}],`,
17430
+ `e:[${prog.fx.map((f) => `[${f.map((token2) => tokenAt.get(token2)).join(",")}]`).join(",")}],`,
17431
+ `es:[${tokens.map(jsString).join(",")}],`,
17421
17432
  `d:[${prog.disp.map((a) => `[${a.join(",")}]`).join(",")}],`,
17422
17433
  `r:${JSON.stringify(prog.rules)},`,
17423
17434
  ...prog.lines === 1 ? ["l:1,"] : [],