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
@@ -40,6 +40,12 @@ function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
40
40
  case "oneOrMore":
41
41
  case "sepBy":
42
42
  return true;
43
+ // A scope that names or clears trivia keeps an outer install out of its body.
44
+ // Any other inherits, so it falls through at no cost in depth: line tracking
45
+ // wraps every rule in one, and must not change what this walk sees.
46
+ case "grammar":
47
+ if (d.triviaParser || d.clearTrivia) return false;
48
+ depth++;
43
49
  // Transparent wrappers — they add no position, so ask what they wrap.
44
50
  case "node":
45
51
  case "transform":
@@ -2252,15 +2258,20 @@ function markUnusedValues(root) {
2252
2258
  case "many":
2253
2259
  case "oneOrMore":
2254
2260
  mark(def, consumed);
2255
- visit(def.parser, consumed);
2256
- return;
2257
2261
  case "optional":
2262
+ // `optional` returns `inner | null` — no aggregate array/tuple to elide, so
2263
+ // it carries no valueUnused flag. Still descend so an inner many/sequence
2264
+ // under a node() is analyzed (it benefits even when its optional wrapper
2265
+ // doesn't).
2266
+ case "label":
2267
+ case "trivia":
2268
+ case "attempt":
2269
+ case "withCtx":
2270
+ case "expect":
2258
2271
  visit(def.parser, consumed);
2259
2272
  return;
2260
2273
  case "sequence":
2261
2274
  mark(def, consumed);
2262
- for (const p of def.parsers) visit(p, consumed);
2263
- return;
2264
2275
  case "choice":
2265
2276
  for (const p of def.parsers) visit(p, consumed);
2266
2277
  return;
@@ -2271,22 +2282,24 @@ function markUnusedValues(root) {
2271
2282
  if (def.otherwise) visit(def.otherwise, consumed);
2272
2283
  return;
2273
2284
  case "node":
2285
+ // builds from captured children, NOT the inner parser value.
2286
+ case "not":
2287
+ case "peek":
2288
+ // lookahead — value never observed
2289
+ case "token":
2274
2290
  visit(def.parser, false);
2275
2291
  return;
2276
2292
  case "transform":
2277
- visit(def.parser, true);
2278
- return;
2293
+ // the map fn reads the value → always consumed.
2279
2294
  case "field":
2295
+ // the field capture records the parsed value → always consumed.
2296
+ case "leaf":
2280
2297
  visit(def.parser, true);
2281
2298
  return;
2282
2299
  case "sepBy":
2283
2300
  visit(def.parser, true);
2284
2301
  visit(def.separator, false);
2285
2302
  return;
2286
- case "not":
2287
- case "peek":
2288
- visit(def.parser, false);
2289
- return;
2290
2303
  case "grammar":
2291
2304
  visit(def.parser, consumed);
2292
2305
  if (def.triviaParser) visit(def.triviaParser, false);
@@ -2295,19 +2308,6 @@ function markUnusedValues(root) {
2295
2308
  visit(def.parser, consumed);
2296
2309
  visit(def.sentinel, false);
2297
2310
  return;
2298
- case "token":
2299
- visit(def.parser, false);
2300
- return;
2301
- case "label":
2302
- case "trivia":
2303
- case "attempt":
2304
- case "withCtx":
2305
- case "expect":
2306
- visit(def.parser, consumed);
2307
- return;
2308
- case "leaf":
2309
- visit(def.parser, true);
2310
- return;
2311
2311
  case "lazy":
2312
2312
  return;
2313
2313
  default:
@@ -2469,7 +2469,7 @@ function parser(opts, root) {
2469
2469
  ctx.triviaKindLabels = void 0;
2470
2470
  } else if (scopeTrivia !== void 0) {
2471
2471
  ctx.trivia = scopeTrivia;
2472
- if (scopeLabels) ctx.triviaKindLabels = scopeLabels;
2472
+ ctx.triviaKindLabels = scopeLabels;
2473
2473
  }
2474
2474
  if (forceCaptureTrivia || _ctx?.captureTrivia) ctx.captureTrivia = true;
2475
2475
  if (ownCaptureMask !== void 0) ctx._triviaCaptureMask = ownCaptureMask;
@@ -2670,6 +2670,7 @@ function derive(c, seen) {
2670
2670
  case "optional":
2671
2671
  case "many":
2672
2672
  case "oneOrMore":
2673
+ case "sepBy":
2673
2674
  case "transform":
2674
2675
  case "not":
2675
2676
  case "peek":
@@ -2817,7 +2818,7 @@ function choice(...args) {
2817
2818
  const result = parsers[idx].parse(input, pos, ctx);
2818
2819
  if (result.ok) return result;
2819
2820
  expected.push(...result.expected);
2820
- if (result.committed) return { ok: false, expected, span: { start: pos, end: pos }, committed: true };
2821
+ if (result.committed) return { ok: false, expected, span: result.span, committed: true };
2821
2822
  return { ok: false, expected, span: { start: pos, end: pos } };
2822
2823
  }
2823
2824
  if (ctx._probe !== void 0 || ctx._tolerant) for (const p of parsers) p.parse(input, pos, ctx);
@@ -4061,6 +4062,9 @@ function regex(pattern, flags = "") {
4061
4062
  };
4062
4063
  }
4063
4064
 
4065
+ // src/version.ts
4066
+ var PARSEMAN_VERSION = "0.61.0";
4067
+
4064
4068
  // src/table/lex-body.ts
4065
4069
  function buildLexBodyRecognizer(spec, constants) {
4066
4070
  const raw = constants[spec[0]];
@@ -4676,11 +4680,12 @@ function assemblyExtraIps(prog) {
4676
4680
  }
4677
4681
  function expandCompact(p) {
4678
4682
  if ("code" in p) return p;
4683
+ if (p.es === void 0) throw new Error(`parseman: this parser was printed by an earlier parseman; reprint it with parseman ${PARSEMAN_VERSION}`);
4679
4684
  return ownTableProgram({
4680
4685
  code: p.c,
4681
4686
  k: p.k,
4682
4687
  cc: p.x,
4683
- fx: p.e,
4688
+ fx: p.e.map((set) => set.map((i) => p.es[i])),
4684
4689
  disp: p.d,
4685
4690
  rules: p.r,
4686
4691
  fns: p.f,
@@ -6615,6 +6620,7 @@ var OP_LIT_CI = 27;
6615
6620
  var OP_LIT_CI_TRACK = 28;
6616
6621
  var OP_TOKEN = 29;
6617
6622
  var OP_SCOPE_CAP = 30;
6623
+ var SCOPE_INHERIT = -2;
6618
6624
  var OP_WITHCTX = 31;
6619
6625
  var OP_GUARD = 32;
6620
6626
  var OP_ADJ = 33;
@@ -6686,6 +6692,12 @@ var OP_NAMES = {
6686
6692
  [OP_STRICT]: "STRICT"
6687
6693
  };
6688
6694
 
6695
+ // src/combinators/link-scope.ts
6696
+ var scope;
6697
+ function afterLink(settle) {
6698
+ scope?.push(settle);
6699
+ }
6700
+
6689
6701
  // src/combinators/node.ts
6690
6702
  import { PlainNode, PlainSpan as PlainSpan7 } from "../cst/plain.js";
6691
6703
  function unwrapChild(child) {
@@ -6749,8 +6761,14 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
6749
6761
  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;
6750
6762
  const capturesTrivia = captureTrivia || (build ? buildReadsTrivia(def) : project === void 0);
6751
6763
  const readsState = build ? buildReadsState(def) : project === void 0;
6752
- const hasOwnFields = parserHasOwnFields(combinator);
6753
- const capturesFields = hasOwnFields && (build ? buildReadsFields(def) : project === void 0);
6764
+ let hasOwnFields = parserHasOwnFields(combinator);
6765
+ let capturesFields = hasOwnFields && (build ? buildReadsFields(def) : project === void 0);
6766
+ if (!hasOwnFields) {
6767
+ afterLink(() => {
6768
+ hasOwnFields = parserHasOwnFields(combinator);
6769
+ capturesFields = hasOwnFields && (build ? buildReadsFields(def) : project === void 0);
6770
+ });
6771
+ }
6754
6772
  const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
6755
6773
  let failExpected;
6756
6774
  return {
@@ -6856,7 +6874,7 @@ function selectOptionalSuffixLexBody(ir) {
6856
6874
  function reinstallsRuleTrivia(reference, target) {
6857
6875
  return (reference._meta.grammarTrivia ?? target._meta.grammarTrivia) !== void 0 && hasOwnTriviaBoundary(target);
6858
6876
  }
6859
- function directTokenBodyParser(parser2, resolve, scope) {
6877
+ function directTokenBodyParser(parser2, resolve, scope2) {
6860
6878
  const outer = parser2._def;
6861
6879
  if (outer.tag !== "token") return void 0;
6862
6880
  let body = outer.parser;
@@ -6866,7 +6884,7 @@ function directTokenBodyParser(parser2, resolve, scope) {
6866
6884
  const wrapper = body._def;
6867
6885
  if (wrapper.tag === "grammar") {
6868
6886
  if (wrapper.clearTrivia !== true || wrapper.triviaParser !== void 0 || wrapper.captureTrivia === true || wrapper.rootCapture === "opaque" || wrapper.constructionTrackLines !== "inherit" || wrapper.constructionCaptureTriviaKinds !== void 0) return void 0;
6869
- if (scope !== void 0) scope.cleared = true;
6887
+ if (scope2 !== void 0) scope2.cleared = true;
6870
6888
  body = wrapper.parser;
6871
6889
  continue;
6872
6890
  }
@@ -7123,10 +7141,10 @@ function directFixedLexNode(parser2, resolve, active, pureOnly = false, cleared
7123
7141
  }
7124
7142
  }
7125
7143
  function directFixedTokenBody(parser2, resolve) {
7126
- const scope = { cleared: false };
7127
- const body = directTokenBodyParser(parser2, resolve, scope);
7144
+ const scope2 = { cleared: false };
7145
+ const body = directTokenBodyParser(parser2, resolve, scope2);
7128
7146
  if (body === void 0) return void 0;
7129
- const root = directFixedLexNode(body, resolve, /* @__PURE__ */ new Set(), false, scope.cleared);
7147
+ const root = directFixedLexNode(body, resolve, /* @__PURE__ */ new Set(), false, scope2.cleared);
7130
7148
  return root === void 0 ? void 0 : { kind: "fixed-tree", root };
7131
7149
  }
7132
7150
  function directBalancedTokenBody(parser2, resolve) {
@@ -8764,7 +8782,7 @@ var Encoder = class {
8764
8782
  this.triviaKnown = savedKnown;
8765
8783
  if (d.clearTrivia === true) return this.emit(op, -1, bodyIp, flags);
8766
8784
  if (d.triviaParser === void 0) {
8767
- return cap || flags !== 0 ? this.emit(op, -1, bodyIp, flags) : bodyIp;
8785
+ return cap ? this.emit(op, SCOPE_INHERIT, bodyIp, flags) : bodyIp;
8768
8786
  }
8769
8787
  return this.emit(op, this.triviaSlot(d.triviaParser), bodyIp, flags);
8770
8788
  }
@@ -10156,7 +10174,7 @@ function transfer(code, ip, at, hostCst) {
10156
10174
  const op = code[ip];
10157
10175
  if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
10158
10176
  const ki = code[ip + 1];
10159
- const tri = ki < 0 ? TRI_NONE : ki;
10177
+ const tri = ki === SCOPE_INHERIT ? at.tri : ki < 0 ? TRI_NONE : ki;
10160
10178
  const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
10161
10179
  if (tri === at.tri && cap === at.cap) return at;
10162
10180
  return { tri, buf: at.buf, raw: at.raw, cap };
@@ -10230,7 +10248,7 @@ function scanHandoffNeeded(code, ip, labels) {
10230
10248
  if (l.tri === TRI_UNKNOWN) return true;
10231
10249
  const op = code[at];
10232
10250
  if (op === OP_SCAN) return true;
10233
- if (op === OP_TOKEN || op === OP_SCOPE_CAP) continue;
10251
+ if (op === OP_TOKEN || op === OP_SCOPE_CAP && code[at + 1] !== SCOPE_INHERIT) continue;
10234
10252
  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;
10235
10253
  kids.length = 0;
10236
10254
  if (!childSlots(code, at, kids)) return true;
@@ -11525,6 +11543,15 @@ return r.value
11525
11543
  const cap = op === OP_SCOPE_CAP;
11526
11544
  const flags = op === OP_SCOPE_PLAIN ? 0 : code[ip + 3];
11527
11545
  const child = link(code[ip + 2]);
11546
+ if (ki === SCOPE_INHERIT) {
11547
+ return `${head}
11548
+ const sC=ctx.captureTrivia
11549
+ ctx.captureTrivia=true
11550
+ const v=${child}(input,pos,ctx)
11551
+ ctx.captureTrivia=sC
11552
+ return v
11553
+ }`;
11554
+ }
11528
11555
  const scanFor = swapLegal && ki >= 0 && !triviaLabelled[ki] ? hoist("ts", `TRIVIASCAN[${ki}]`) : "null";
11529
11556
  const tri = ki < 0 ? "undefined" : hoist("tv", `TRIVIA[${ki}]`);
11530
11557
  const lab = ki < 0 ? "undefined" : hoist("tl", `TRIVIA[${ki}]._meta.triviaKindLabels`);
@@ -13269,9 +13296,6 @@ function clearOf(ranges, input, from, to) {
13269
13296
  return true;
13270
13297
  }
13271
13298
 
13272
- // src/version.ts
13273
- var PARSEMAN_VERSION = "0.60.5";
13274
-
13275
13299
  // src/table/assemble.ts
13276
13300
  import { PlainBuf as PlainBuf2, PlainField, PlainLeaf as PlainLeaf9, PlainNode as PlainNode2, PlainSpan as PlainSpan10 } from "../cst/plain.js";
13277
13301
 
@@ -14787,6 +14811,16 @@ function assemble(t2, prog, cfg) {
14787
14811
  case OP_SCOPE_CAP:
14788
14812
  case OP_SCOPE_PLAIN: {
14789
14813
  const ki = code[ip + 1];
14814
+ if (ki === SCOPE_INHERIT) {
14815
+ const body = link(code[ip + 2]);
14816
+ return (input, pos, ctx) => {
14817
+ const savedCap = ctx.captureTrivia;
14818
+ ctx.captureTrivia = true;
14819
+ const v = body(input, pos, ctx);
14820
+ ctx.captureTrivia = savedCap;
14821
+ return v;
14822
+ };
14823
+ }
14790
14824
  const scopeTrivia = ki < 0 ? void 0 : trivia2[ki];
14791
14825
  const scopeLabels = scopeTrivia?._meta.triviaKindLabels;
14792
14826
  const scanFor = swapLegal && ki >= 0 && !triviaLabelled[ki] ? triviaScan[ki] : null;
@@ -17245,12 +17279,15 @@ function assertPrintable(prog, who) {
17245
17279
  }
17246
17280
  }
17247
17281
  function programFields(prog, fns, opts = {}) {
17282
+ const tokens = [...new Set(prog.fx.flat())];
17283
+ const tokenAt = new Map(tokens.map((token2, i) => [token2, i]));
17248
17284
  return [
17249
17285
  ...emitAssemblies(prog, opts.assemblies ?? []),
17250
17286
  `c:[${prog.code.join(",")}],`,
17251
17287
  `k:[${prog.k.map(emitConst).join(",")}],`,
17252
17288
  `x:${emitClassPool(prog.cc)},`,
17253
- `e:[${prog.fx.map((f) => `[${f.map(jsString).join(",")}]`).join(",")}],`,
17289
+ `e:[${prog.fx.map((f) => `[${f.map((token2) => tokenAt.get(token2)).join(",")}]`).join(",")}],`,
17290
+ `es:[${tokens.map(jsString).join(",")}],`,
17254
17291
  `d:[${prog.disp.map((a) => `[${a.join(",")}]`).join(",")}],`,
17255
17292
  `r:${JSON.stringify(prog.rules)},`,
17256
17293
  ...prog.lines === 1 ? ["l:1,"] : [],