parseman 0.60.5 → 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 (59) hide show
  1. package/dist/analysis/diagnostics.js +77 -40
  2. package/dist/analysis/diagnostics.js.map +3 -3
  3. package/dist/cli/index.js +77 -40
  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/combinators/trivia-boundary.d.ts +5 -3
  12. package/dist/combinators/trivia-boundary.d.ts.map +1 -1
  13. package/dist/compiler/token-capability.js +7 -0
  14. package/dist/compiler/token-capability.js.map +1 -1
  15. package/dist/compiler/value-usage.d.ts.map +1 -1
  16. package/dist/functional/run.d.ts.map +1 -1
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +121 -70
  20. package/dist/index.js.map +3 -3
  21. package/dist/language-service/index.js +1 -1
  22. package/dist/language-service/index.js.map +1 -1
  23. package/dist/plugin/index.js +284 -233
  24. package/dist/plugin/index.js.map +3 -3
  25. package/dist/run/index.js +1 -1
  26. package/dist/run/index.js.map +1 -1
  27. package/dist/spec/index.js.map +1 -1
  28. package/dist/table/assemble.d.ts.map +1 -1
  29. package/dist/table/emit-assembly.d.ts.map +1 -1
  30. package/dist/table/emit.d.ts.map +1 -1
  31. package/dist/table/encode.d.ts.map +1 -1
  32. package/dist/table/exec.d.ts.map +1 -1
  33. package/dist/table/index.js +41 -10
  34. package/dist/table/index.js.map +3 -3
  35. package/dist/table/ops.d.ts +6 -0
  36. package/dist/table/ops.d.ts.map +1 -1
  37. package/dist/table/program.d.ts +3 -1
  38. package/dist/table/program.d.ts.map +1 -1
  39. package/dist/version.d.ts +1 -1
  40. package/package.json +1 -1
  41. package/src/combinators/choice.ts +3 -1
  42. package/src/combinators/expect.ts +1 -0
  43. package/src/combinators/grammar.ts +1 -1
  44. package/src/combinators/link-scope.ts +19 -0
  45. package/src/combinators/node.ts +11 -2
  46. package/src/combinators/parser.ts +37 -31
  47. package/src/combinators/trivia-boundary.ts +11 -3
  48. package/src/compiler/value-usage.ts +16 -29
  49. package/src/functional/run.ts +3 -1
  50. package/src/index.ts +1 -1
  51. package/src/table/assemble.ts +11 -1
  52. package/src/table/emit-assembly.ts +10 -1
  53. package/src/table/emit.ts +5 -1
  54. package/src/table/encode.ts +16 -9
  55. package/src/table/exec.ts +11 -9
  56. package/src/table/ops.ts +6 -0
  57. package/src/table/program.ts +8 -2
  58. package/src/table/site-labels.ts +3 -3
  59. package/src/version.ts +1 -1
package/dist/cli/index.js CHANGED
@@ -48,6 +48,12 @@ function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
48
48
  case "oneOrMore":
49
49
  case "sepBy":
50
50
  return true;
51
+ // A scope that names or clears trivia keeps an outer install out of its body.
52
+ // Any other inherits, so it falls through at no cost in depth: line tracking
53
+ // wraps every rule in one, and must not change what this walk sees.
54
+ case "grammar":
55
+ if (d.triviaParser || d.clearTrivia) return false;
56
+ depth++;
51
57
  // Transparent wrappers — they add no position, so ask what they wrap.
52
58
  case "node":
53
59
  case "transform":
@@ -2712,6 +2718,7 @@ function derive(c, seen) {
2712
2718
  case "optional":
2713
2719
  case "many":
2714
2720
  case "oneOrMore":
2721
+ case "sepBy":
2715
2722
  case "transform":
2716
2723
  case "not":
2717
2724
  case "peek":
@@ -2893,7 +2900,7 @@ function selectOptionalSuffixLexBody(ir) {
2893
2900
  function reinstallsRuleTrivia(reference, target) {
2894
2901
  return (reference._meta.grammarTrivia ?? target._meta.grammarTrivia) !== void 0 && hasOwnTriviaBoundary(target);
2895
2902
  }
2896
- function directTokenBodyParser(parser2, resolve2, scope) {
2903
+ function directTokenBodyParser(parser2, resolve2, scope2) {
2897
2904
  const outer = parser2._def;
2898
2905
  if (outer.tag !== "token") return void 0;
2899
2906
  let body = outer.parser;
@@ -2903,7 +2910,7 @@ function directTokenBodyParser(parser2, resolve2, scope) {
2903
2910
  const wrapper = body._def;
2904
2911
  if (wrapper.tag === "grammar") {
2905
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;
2906
- if (scope !== void 0) scope.cleared = true;
2913
+ if (scope2 !== void 0) scope2.cleared = true;
2907
2914
  body = wrapper.parser;
2908
2915
  continue;
2909
2916
  }
@@ -3160,10 +3167,10 @@ function directFixedLexNode(parser2, resolve2, active, pureOnly = false, cleared
3160
3167
  }
3161
3168
  }
3162
3169
  function directFixedTokenBody(parser2, resolve2) {
3163
- const scope = { cleared: false };
3164
- const body = directTokenBodyParser(parser2, resolve2, scope);
3170
+ const scope2 = { cleared: false };
3171
+ const body = directTokenBodyParser(parser2, resolve2, scope2);
3165
3172
  if (body === void 0) return void 0;
3166
- const root = directFixedLexNode(body, resolve2, /* @__PURE__ */ new Set(), false, scope.cleared);
3173
+ const root = directFixedLexNode(body, resolve2, /* @__PURE__ */ new Set(), false, scope2.cleared);
3167
3174
  return root === void 0 ? void 0 : { kind: "fixed-tree", root };
3168
3175
  }
3169
3176
  function directBalancedTokenBody(parser2, resolve2) {
@@ -4251,15 +4258,20 @@ function markUnusedValues(root) {
4251
4258
  case "many":
4252
4259
  case "oneOrMore":
4253
4260
  mark(def, consumed);
4254
- visit(def.parser, consumed);
4255
- return;
4256
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":
4257
4271
  visit(def.parser, consumed);
4258
4272
  return;
4259
4273
  case "sequence":
4260
4274
  mark(def, consumed);
4261
- for (const p of def.parsers) visit(p, consumed);
4262
- return;
4263
4275
  case "choice":
4264
4276
  for (const p of def.parsers) visit(p, consumed);
4265
4277
  return;
@@ -4270,22 +4282,24 @@ function markUnusedValues(root) {
4270
4282
  if (def.otherwise) visit(def.otherwise, consumed);
4271
4283
  return;
4272
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":
4273
4290
  visit(def.parser, false);
4274
4291
  return;
4275
4292
  case "transform":
4276
- visit(def.parser, true);
4277
- return;
4293
+ // the map fn reads the value → always consumed.
4278
4294
  case "field":
4295
+ // the field capture records the parsed value → always consumed.
4296
+ case "leaf":
4279
4297
  visit(def.parser, true);
4280
4298
  return;
4281
4299
  case "sepBy":
4282
4300
  visit(def.parser, true);
4283
4301
  visit(def.separator, false);
4284
4302
  return;
4285
- case "not":
4286
- case "peek":
4287
- visit(def.parser, false);
4288
- return;
4289
4303
  case "grammar":
4290
4304
  visit(def.parser, consumed);
4291
4305
  if (def.triviaParser) visit(def.triviaParser, false);
@@ -4294,19 +4308,6 @@ function markUnusedValues(root) {
4294
4308
  visit(def.parser, consumed);
4295
4309
  visit(def.sentinel, false);
4296
4310
  return;
4297
- case "token":
4298
- visit(def.parser, false);
4299
- return;
4300
- case "label":
4301
- case "trivia":
4302
- case "attempt":
4303
- case "withCtx":
4304
- case "expect":
4305
- visit(def.parser, consumed);
4306
- return;
4307
- case "leaf":
4308
- visit(def.parser, true);
4309
- return;
4310
4311
  case "lazy":
4311
4312
  return;
4312
4313
  default:
@@ -4336,6 +4337,12 @@ function markUnusedValues(root) {
4336
4337
  visit(resolveRoot(root), true);
4337
4338
  }
4338
4339
 
4340
+ // src/combinators/link-scope.ts
4341
+ var scope;
4342
+ function afterLink(settle) {
4343
+ scope?.push(settle);
4344
+ }
4345
+
4339
4346
  // src/cst/root-trivia-scope.ts
4340
4347
  var ROOT_TRIVIA_SCOPE_REFUSAL = "parser(): selected root trivia requires classifiedTrivia() for every local trivia scope, or rootCapture: 'opaque'.";
4341
4348
  function refuseUnclassifiedRootScope(strict) {
@@ -4446,7 +4453,7 @@ function parser(opts, root) {
4446
4453
  ctx.triviaKindLabels = void 0;
4447
4454
  } else if (scopeTrivia !== void 0) {
4448
4455
  ctx.trivia = scopeTrivia;
4449
- if (scopeLabels) ctx.triviaKindLabels = scopeLabels;
4456
+ ctx.triviaKindLabels = scopeLabels;
4450
4457
  }
4451
4458
  if (forceCaptureTrivia || _ctx?.captureTrivia) ctx.captureTrivia = true;
4452
4459
  if (ownCaptureMask !== void 0) ctx._triviaCaptureMask = ownCaptureMask;
@@ -4592,7 +4599,7 @@ function choice(...args) {
4592
4599
  const result = parsers[idx].parse(input, pos, ctx);
4593
4600
  if (result.ok) return result;
4594
4601
  expected.push(...result.expected);
4595
- 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 };
4596
4603
  return { ok: false, expected, span: { start: pos, end: pos } };
4597
4604
  }
4598
4605
  if (ctx._probe !== void 0 || ctx._tolerant) for (const p of parsers) p.parse(input, pos, ctx);
@@ -5492,6 +5499,9 @@ function regex(pattern, flags = "") {
5492
5499
  };
5493
5500
  }
5494
5501
 
5502
+ // src/version.ts
5503
+ var PARSEMAN_VERSION = "0.61.0";
5504
+
5495
5505
  // src/table/lex-body.ts
5496
5506
  function buildLexBodyRecognizer(spec, constants) {
5497
5507
  const raw = constants[spec[0]];
@@ -6107,11 +6117,12 @@ function assemblyExtraIps(prog) {
6107
6117
  }
6108
6118
  function expandCompact(p) {
6109
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}`);
6110
6121
  return ownTableProgram({
6111
6122
  code: p.c,
6112
6123
  k: p.k,
6113
6124
  cc: p.x,
6114
- fx: p.e,
6125
+ fx: p.e.map((set) => set.map((i) => p.es[i])),
6115
6126
  disp: p.d,
6116
6127
  rules: p.r,
6117
6128
  fns: p.f,
@@ -7177,6 +7188,7 @@ var OP_LIT_CI = 27;
7177
7188
  var OP_LIT_CI_TRACK = 28;
7178
7189
  var OP_TOKEN = 29;
7179
7190
  var OP_SCOPE_CAP = 30;
7191
+ var SCOPE_INHERIT = -2;
7180
7192
  var OP_WITHCTX = 31;
7181
7193
  var OP_GUARD = 32;
7182
7194
  var OP_ADJ = 33;
@@ -7311,8 +7323,14 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
7311
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;
7312
7324
  const capturesTrivia = captureTrivia || (build ? buildReadsTrivia(def) : project === void 0);
7313
7325
  const readsState = build ? buildReadsState(def) : project === void 0;
7314
- const hasOwnFields = parserHasOwnFields(combinator);
7315
- 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
+ }
7316
7334
  const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
7317
7335
  let failExpected;
7318
7336
  return {
@@ -8976,7 +8994,7 @@ var Encoder = class {
8976
8994
  this.triviaKnown = savedKnown;
8977
8995
  if (d.clearTrivia === true) return this.emit(op, -1, bodyIp, flags);
8978
8996
  if (d.triviaParser === void 0) {
8979
- return cap || flags !== 0 ? this.emit(op, -1, bodyIp, flags) : bodyIp;
8997
+ return cap ? this.emit(op, SCOPE_INHERIT, bodyIp, flags) : bodyIp;
8980
8998
  }
8981
8999
  return this.emit(op, this.triviaSlot(d.triviaParser), bodyIp, flags);
8982
9000
  }
@@ -10368,7 +10386,7 @@ function transfer(code, ip, at, hostCst) {
10368
10386
  const op = code[ip];
10369
10387
  if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
10370
10388
  const ki = code[ip + 1];
10371
- const tri = ki < 0 ? TRI_NONE : ki;
10389
+ const tri = ki === SCOPE_INHERIT ? at.tri : ki < 0 ? TRI_NONE : ki;
10372
10390
  const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
10373
10391
  if (tri === at.tri && cap === at.cap) return at;
10374
10392
  return { tri, buf: at.buf, raw: at.raw, cap };
@@ -10442,7 +10460,7 @@ function scanHandoffNeeded(code, ip, labels) {
10442
10460
  if (l.tri === TRI_UNKNOWN) return true;
10443
10461
  const op = code[at];
10444
10462
  if (op === OP_SCAN) return true;
10445
- if (op === OP_TOKEN || op === OP_SCOPE_CAP) continue;
10463
+ if (op === OP_TOKEN || op === OP_SCOPE_CAP && code[at + 1] !== SCOPE_INHERIT) continue;
10446
10464
  if ((op === OP_SCOPE_PLAIN || op === OP_SCOPE) && !(code[at + 1] >= 0 && l.tri === code[at + 1] && (op === OP_SCOPE_PLAIN || code[at + 3] === 0))) continue;
10447
10465
  kids.length = 0;
10448
10466
  if (!childSlots(code, at, kids)) return true;
@@ -11737,6 +11755,15 @@ return r.value
11737
11755
  const cap = op === OP_SCOPE_CAP;
11738
11756
  const flags = op === OP_SCOPE_PLAIN ? 0 : code[ip + 3];
11739
11757
  const child = link(code[ip + 2]);
11758
+ if (ki === SCOPE_INHERIT) {
11759
+ return `${head}
11760
+ const sC=ctx.captureTrivia
11761
+ ctx.captureTrivia=true
11762
+ const v=${child}(input,pos,ctx)
11763
+ ctx.captureTrivia=sC
11764
+ return v
11765
+ }`;
11766
+ }
11740
11767
  const scanFor = swapLegal && ki >= 0 && !triviaLabelled[ki] ? hoist("ts", `TRIVIASCAN[${ki}]`) : "null";
11741
11768
  const tri = ki < 0 ? "undefined" : hoist("tv", `TRIVIA[${ki}]`);
11742
11769
  const lab = ki < 0 ? "undefined" : hoist("tl", `TRIVIA[${ki}]._meta.triviaKindLabels`);
@@ -13414,9 +13441,6 @@ function clearOf(ranges, input, from, to) {
13414
13441
  return true;
13415
13442
  }
13416
13443
 
13417
- // src/version.ts
13418
- var PARSEMAN_VERSION = "0.60.5";
13419
-
13420
13444
  // src/table/assemble.ts
13421
13445
  import { PlainBuf as PlainBuf2, PlainField, PlainLeaf as PlainLeaf9, PlainNode as PlainNode2, PlainSpan as PlainSpan10 } from "../cst/plain.js";
13422
13446
 
@@ -14928,6 +14952,16 @@ function assemble(t2, prog, cfg) {
14928
14952
  case OP_SCOPE_CAP:
14929
14953
  case OP_SCOPE_PLAIN: {
14930
14954
  const ki = code[ip + 1];
14955
+ if (ki === SCOPE_INHERIT) {
14956
+ const body = link(code[ip + 2]);
14957
+ return (input, pos, ctx) => {
14958
+ const savedCap = ctx.captureTrivia;
14959
+ ctx.captureTrivia = true;
14960
+ const v = body(input, pos, ctx);
14961
+ ctx.captureTrivia = savedCap;
14962
+ return v;
14963
+ };
14964
+ }
14931
14965
  const scopeTrivia = ki < 0 ? void 0 : trivia2[ki];
14932
14966
  const scopeLabels = scopeTrivia?._meta.triviaKindLabels;
14933
14967
  const scanFor = swapLegal && ki >= 0 && !triviaLabelled[ki] ? triviaScan[ki] : null;
@@ -17386,12 +17420,15 @@ function assertPrintable(prog, who) {
17386
17420
  }
17387
17421
  }
17388
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]));
17389
17425
  return [
17390
17426
  ...emitAssemblies(prog, opts.assemblies ?? []),
17391
17427
  `c:[${prog.code.join(",")}],`,
17392
17428
  `k:[${prog.k.map(emitConst).join(",")}],`,
17393
17429
  `x:${emitClassPool(prog.cc)},`,
17394
- `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(",")}],`,
17395
17432
  `d:[${prog.disp.map((a) => `[${a.join(",")}]`).join(",")}],`,
17396
17433
  `r:${JSON.stringify(prog.rules)},`,
17397
17434
  ...prog.lines === 1 ? ["l:1,"] : [],