parseman 0.60.4 → 0.60.6

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 (54) hide show
  1. package/dist/analysis/commitment.d.ts.map +1 -1
  2. package/dist/analysis/diagnostics.js +31 -5
  3. package/dist/analysis/diagnostics.js.map +1 -1
  4. package/dist/cli/index.js +639 -613
  5. package/dist/cli/index.js.map +3 -3
  6. package/dist/combinators/parser.d.ts +34 -3
  7. package/dist/combinators/parser.d.ts.map +1 -1
  8. package/dist/combinators/trivia-boundary.d.ts +5 -3
  9. package/dist/combinators/trivia-boundary.d.ts.map +1 -1
  10. package/dist/compiler/compile-linkable-table.d.ts.map +1 -1
  11. package/dist/compiler/linker.d.ts +11 -3
  12. package/dist/compiler/linker.d.ts.map +1 -1
  13. package/dist/compiler/token-capability.js +6 -0
  14. package/dist/compiler/token-capability.js.map +1 -1
  15. package/dist/index.d.ts +2 -1
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +93 -25
  18. package/dist/index.js.map +1 -1
  19. package/dist/plugin/evaluator.d.ts +3 -1
  20. package/dist/plugin/evaluator.d.ts.map +1 -1
  21. package/dist/plugin/index.d.ts.map +1 -1
  22. package/dist/plugin/index.js +116 -75
  23. package/dist/plugin/index.js.map +1 -1
  24. package/dist/spec/index.js +3 -1
  25. package/dist/spec/index.js.map +1 -1
  26. package/dist/spec/model.d.ts.map +1 -1
  27. package/dist/table/assemble.d.ts.map +1 -1
  28. package/dist/table/emit-assembly.d.ts.map +1 -1
  29. package/dist/table/encode.d.ts.map +1 -1
  30. package/dist/table/exec.d.ts.map +1 -1
  31. package/dist/table/index.js +31 -5
  32. package/dist/table/index.js.map +1 -1
  33. package/dist/table/ops.d.ts +6 -0
  34. package/dist/table/ops.d.ts.map +1 -1
  35. package/dist/version.d.ts +1 -1
  36. package/package.json +1 -1
  37. package/src/analysis/commitment.ts +3 -1
  38. package/src/combinators/grammar.ts +1 -1
  39. package/src/combinators/parser.ts +82 -9
  40. package/src/combinators/trivia-boundary.ts +11 -3
  41. package/src/compiler/compile-linkable-table.ts +4 -1
  42. package/src/compiler/ir-serialize.ts +10 -4
  43. package/src/compiler/linker.ts +22 -12
  44. package/src/index.ts +2 -1
  45. package/src/plugin/evaluator.ts +16 -5
  46. package/src/plugin/index.ts +27 -104
  47. package/src/spec/model.ts +3 -1
  48. package/src/table/assemble.ts +11 -1
  49. package/src/table/emit-assembly.ts +10 -1
  50. package/src/table/encode.ts +16 -9
  51. package/src/table/exec.ts +11 -9
  52. package/src/table/ops.ts +6 -0
  53. package/src/table/site-labels.ts +3 -3
  54. package/src/version.ts +1 -1
package/dist/index.js CHANGED
@@ -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":
@@ -4537,7 +4543,7 @@ function parser(opts, root) {
4537
4543
  ctx.triviaKindLabels = void 0;
4538
4544
  } else if (scopeTrivia !== void 0) {
4539
4545
  ctx.trivia = scopeTrivia;
4540
- if (scopeLabels) ctx.triviaKindLabels = scopeLabels;
4546
+ ctx.triviaKindLabels = scopeLabels;
4541
4547
  }
4542
4548
  if (forceCaptureTrivia || _ctx?.captureTrivia) ctx.captureTrivia = true;
4543
4549
  if (ownCaptureMask !== void 0) ctx._triviaCaptureMask = ownCaptureMask;
@@ -4713,11 +4719,16 @@ function tagRule(r, key) {
4713
4719
  function isDefinableRef(v) {
4714
4720
  return !!v && typeof v === "object" && "_def" in v && v._def.tag === "lazy" && typeof v.define === "function";
4715
4721
  }
4722
+ function priorNameOf(r) {
4723
+ return r._priorOf;
4724
+ }
4716
4725
  function ruleNameOf(r) {
4717
4726
  return r._ruleName;
4718
4727
  }
4719
4728
  function isNamedRuleRefForAnotherRule(r, key) {
4720
- const name = r._def.tag === "lazy" ? ruleNameOf(r) : void 0;
4729
+ if (r._def.tag !== "lazy") return false;
4730
+ if (priorNameOf(r) !== void 0) return true;
4731
+ const name = ruleNameOf(r);
4721
4732
  return name !== void 0 && name !== key;
4722
4733
  }
4723
4734
  var claimedRules = /* @__PURE__ */ new WeakSet();
@@ -4730,6 +4741,20 @@ function ownRule(p, copies) {
4730
4741
  }
4731
4742
  return own;
4732
4743
  }
4744
+ var priorUnfilled = (key) => new Error(`compose: prior.${key} is read, but no grammar composed before it defines "${key}"`);
4745
+ function priorHole(key) {
4746
+ const unfilled = priorUnfilled(key);
4747
+ const fail = () => {
4748
+ throw unfilled;
4749
+ };
4750
+ return {
4751
+ _tag: "lazy",
4752
+ _meta: { firstSet: any(), canMatchNewline: true, isTrivia: false },
4753
+ _def: { tag: "lazy", thunk: fail },
4754
+ parse: fail,
4755
+ _priorOf: key
4756
+ };
4757
+ }
4733
4758
  function rules(a, b) {
4734
4759
  const factory = typeof a === "function" ? a : b;
4735
4760
  const options = typeof a === "function" ? b : a;
@@ -4754,8 +4779,20 @@ function linkRules(recipes, link) {
4754
4779
  }
4755
4780
  });
4756
4781
  const winners = /* @__PURE__ */ new Map();
4782
+ const priorHoles = /* @__PURE__ */ new Map();
4783
+ const prior = new Proxy({}, {
4784
+ get(_target, key) {
4785
+ if (typeof key !== "string") return void 0;
4786
+ const earlier = winners.get(key)?.parser;
4787
+ if (earlier !== void 0) return earlier._def.tag === "node" ? earlier._def.parser : earlier;
4788
+ if (link !== void 0) throw priorUnfilled(key);
4789
+ let hole = priorHoles.get(key);
4790
+ if (hole === void 0) priorHoles.set(key, hole = priorHole(key));
4791
+ return hole;
4792
+ }
4793
+ });
4757
4794
  for (const recipe of recipes) {
4758
- const definitions = recipe.factory(proxy);
4795
+ const definitions = recipe.factory(proxy, prior);
4759
4796
  for (const key of Object.keys(definitions)) {
4760
4797
  winners.set(key, { parser: definitions[key], options: recipe.options });
4761
4798
  }
@@ -7304,7 +7341,8 @@ function classifyRuleMap(ruleMap) {
7304
7341
  resolved = void 0;
7305
7342
  }
7306
7343
  if (resolved === void 0) {
7307
- if (p._ruleName) externalRefs.add(p);
7344
+ const hole = p;
7345
+ if (hole._ruleName !== void 0 || hole._priorOf !== void 0) externalRefs.add(p);
7308
7346
  return;
7309
7347
  }
7310
7348
  scanExternal(resolved);
@@ -7486,6 +7524,7 @@ var OP_LIT_CI = 27;
7486
7524
  var OP_LIT_CI_TRACK = 28;
7487
7525
  var OP_TOKEN = 29;
7488
7526
  var OP_SCOPE_CAP = 30;
7527
+ var SCOPE_INHERIT = -2;
7489
7528
  var OP_WITHCTX = 31;
7490
7529
  var OP_GUARD = 32;
7491
7530
  var OP_ADJ = 33;
@@ -9518,7 +9557,7 @@ var Encoder = class {
9518
9557
  this.triviaKnown = savedKnown;
9519
9558
  if (d.clearTrivia === true) return this.emit(op, -1, bodyIp, flags);
9520
9559
  if (d.triviaParser === void 0) {
9521
- return cap || flags !== 0 ? this.emit(op, -1, bodyIp, flags) : bodyIp;
9560
+ return cap ? this.emit(op, SCOPE_INHERIT, bodyIp, flags) : bodyIp;
9522
9561
  }
9523
9562
  return this.emit(op, this.triviaSlot(d.triviaParser), bodyIp, flags);
9524
9563
  }
@@ -10913,7 +10952,7 @@ function transfer(code, ip, at, hostCst) {
10913
10952
  const op = code[ip];
10914
10953
  if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
10915
10954
  const ki = code[ip + 1];
10916
- const tri = ki < 0 ? TRI_NONE : ki;
10955
+ const tri = ki === SCOPE_INHERIT ? at.tri : ki < 0 ? TRI_NONE : ki;
10917
10956
  const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
10918
10957
  if (tri === at.tri && cap === at.cap) return at;
10919
10958
  return { tri, buf: at.buf, raw: at.raw, cap };
@@ -10987,7 +11026,7 @@ function scanHandoffNeeded(code, ip, labels) {
10987
11026
  if (l.tri === TRI_UNKNOWN) return true;
10988
11027
  const op = code[at];
10989
11028
  if (op === OP_SCAN) return true;
10990
- if (op === OP_TOKEN || op === OP_SCOPE_CAP) continue;
11029
+ if (op === OP_TOKEN || op === OP_SCOPE_CAP && code[at + 1] !== SCOPE_INHERIT) continue;
10991
11030
  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;
10992
11031
  kids.length = 0;
10993
11032
  if (!childSlots(code, at, kids)) return true;
@@ -12282,6 +12321,15 @@ return r.value
12282
12321
  const cap = op === OP_SCOPE_CAP;
12283
12322
  const flags = op === OP_SCOPE_PLAIN ? 0 : code[ip + 3];
12284
12323
  const child = link(code[ip + 2]);
12324
+ if (ki === SCOPE_INHERIT) {
12325
+ return `${head}
12326
+ const sC=ctx.captureTrivia
12327
+ ctx.captureTrivia=true
12328
+ const v=${child}(input,pos,ctx)
12329
+ ctx.captureTrivia=sC
12330
+ return v
12331
+ }`;
12332
+ }
12285
12333
  const scanFor = swapLegal && ki >= 0 && !triviaLabelled[ki] ? hoist("ts", `TRIVIASCAN[${ki}]`) : "null";
12286
12334
  const tri = ki < 0 ? "undefined" : hoist("tv", `TRIVIA[${ki}]`);
12287
12335
  const lab = ki < 0 ? "undefined" : hoist("tl", `TRIVIA[${ki}]._meta.triviaKindLabels`);
@@ -13871,7 +13919,7 @@ function clearOf(ranges, input, from, to) {
13871
13919
  }
13872
13920
 
13873
13921
  // src/version.ts
13874
- var PARSEMAN_VERSION = "0.60.4";
13922
+ var PARSEMAN_VERSION = "0.60.6";
13875
13923
 
13876
13924
  // src/table/assemble.ts
13877
13925
  import { PlainBuf as PlainBuf2, PlainField, PlainLeaf as PlainLeaf9, PlainNode as PlainNode2, PlainSpan as PlainSpan10 } from "./cst/plain.js";
@@ -15401,6 +15449,16 @@ function assemble(t, prog, cfg) {
15401
15449
  case OP_SCOPE_CAP:
15402
15450
  case OP_SCOPE_PLAIN: {
15403
15451
  const ki = code[ip + 1];
15452
+ if (ki === SCOPE_INHERIT) {
15453
+ const body = link(code[ip + 2]);
15454
+ return (input, pos, ctx) => {
15455
+ const savedCap = ctx.captureTrivia;
15456
+ ctx.captureTrivia = true;
15457
+ const v = body(input, pos, ctx);
15458
+ ctx.captureTrivia = savedCap;
15459
+ return v;
15460
+ };
15461
+ }
15404
15462
  const scopeTrivia = ki < 0 ? void 0 : trivia2[ki];
15405
15463
  const scopeLabels = scopeTrivia?._meta.triviaKindLabels;
15406
15464
  const scanFor = swapLegal && ki >= 0 && !triviaLabelled[ki] ? triviaScan[ki] : null;
@@ -18024,7 +18082,7 @@ function buildGrammarPlan(entry, winners) {
18024
18082
  const dispatches = /* @__PURE__ */ new Map();
18025
18083
  const attempts = /* @__PURE__ */ new Map();
18026
18084
  const labels = /* @__PURE__ */ new Map();
18027
- const rules2 = /* @__PURE__ */ new Map();
18085
+ const rules3 = /* @__PURE__ */ new Map();
18028
18086
  const winnerNames = /* @__PURE__ */ new Map();
18029
18087
  if (winners) {
18030
18088
  for (const [name, winner] of Object.entries(winners)) {
@@ -18058,7 +18116,7 @@ function buildGrammarPlan(entry, winners) {
18058
18116
  const ownRule2 = (parser2, rule) => {
18059
18117
  const id = `rule:${rule}`;
18060
18118
  definitions.set(id, { id, kind: "rule" });
18061
- rules2.set(parser2, id);
18119
+ rules3.set(parser2, id);
18062
18120
  };
18063
18121
  const seen = /* @__PURE__ */ new Set();
18064
18122
  const visit = (parser2, path) => {
@@ -18098,7 +18156,7 @@ function buildGrammarPlan(entry, winners) {
18098
18156
  }
18099
18157
  visit(body ?? root, name);
18100
18158
  }
18101
- return { definitions: [...definitions.values()].sort((a, b) => a.id.localeCompare(b.id)), choices, dispatches, attempts, labels, rules: rules2 };
18159
+ return { definitions: [...definitions.values()].sort((a, b) => a.id.localeCompare(b.id)), choices, dispatches, attempts, labels, rules: rules3 };
18102
18160
  }
18103
18161
 
18104
18162
  // src/analysis/duplication.ts
@@ -19891,6 +19949,8 @@ var Serializer = class {
19891
19949
  localRuleNames = /* @__PURE__ */ new Map();
19892
19950
  ruleMap;
19893
19951
  scanSkip;
19952
+ /** Whether any rule reads a `prior.X` hole, so the factory takes `(g, prior)`. */
19953
+ usesPrior = false;
19894
19954
  accessed;
19895
19955
  referenced = /* @__PURE__ */ new Set();
19896
19956
  constructor(ruleMap, scanSkip = [], accessed = []) {
@@ -19911,7 +19971,7 @@ var Serializer = class {
19911
19971
  if (seen.has(c)) return;
19912
19972
  seen.add(c);
19913
19973
  if (c._def.tag === "lazy") {
19914
- if (ruleNameOf4(c) !== void 0) throw new Unserializable("scanSkip unit references a grammar rule");
19974
+ if (ruleNameOf4(c) !== void 0 || priorNameOf(c) !== void 0) throw new Unserializable("scanSkip unit references a grammar rule");
19915
19975
  const target = lazyTarget(c);
19916
19976
  if (target) this.assertNoRuleRef(target, seen);
19917
19977
  return;
@@ -19975,9 +20035,10 @@ var Serializer = class {
19975
20035
  for (const name of this.accessed) {
19976
20036
  if (!this.referenced.has(name)) innerDecls.push(`void g[${JSON.stringify(name)}]`);
19977
20037
  }
19978
- const factory = innerDecls.length === 0 ? `(g) => ({
20038
+ const params = this.usesPrior ? "(g, prior)" : "(g)";
20039
+ const factory = innerDecls.length === 0 ? `${params} => ({
19979
20040
  ${body}
19980
- })` : `(g) => {
20041
+ })` : `${params} => {
19981
20042
  ${innerDecls.map((d) => " " + d).join("\n")}
19982
20043
  return ({
19983
20044
  ${body}
@@ -19994,6 +20055,10 @@ ${outerDecls.map((d) => " " + d).join("\n")}
19994
20055
  analyze(c, active) {
19995
20056
  const def = c._def;
19996
20057
  if (def.tag === "lazy") {
20058
+ if (priorNameOf(c) !== void 0) {
20059
+ this.usesPrior = true;
20060
+ return;
20061
+ }
19997
20062
  if (ruleNameOf4(c) !== void 0) return;
19998
20063
  const target = lazyTarget(c);
19999
20064
  if (!target) throw new Unserializable("unresolved unnamed ref");
@@ -20072,6 +20137,8 @@ ${outerDecls.map((d) => " " + d).join("\n")}
20072
20137
  }
20073
20138
  switch (def.tag) {
20074
20139
  case "lazy": {
20140
+ const prior = priorNameOf(c);
20141
+ if (prior !== void 0) return `prior[${JSON.stringify(prior)}]`;
20075
20142
  const name = this.localRuleNames.get(c) ?? ruleNameOf4(c);
20076
20143
  if (name !== void 0) {
20077
20144
  this.referenced.add(name);
@@ -20252,7 +20319,8 @@ function externalNames(ruleMap) {
20252
20319
  resolved = void 0;
20253
20320
  }
20254
20321
  if (resolved === void 0) {
20255
- const name = p._ruleName;
20322
+ const prior = priorNameOf(p);
20323
+ const name = prior === void 0 ? p._ruleName : `prior.${prior}`;
20256
20324
  if (name !== void 0 && !out.includes(name)) out.push(name);
20257
20325
  return;
20258
20326
  }
@@ -20345,9 +20413,9 @@ function carriedRuleMapsDetailed(carried) {
20345
20413
  const maps = [];
20346
20414
  const opaque = [];
20347
20415
  for (const p of carried) {
20348
- const rules2 = ruleMapOfCarried(p);
20349
- if (rules2 !== void 0) {
20350
- maps.push(rules2);
20416
+ const rules3 = ruleMapOfCarried(p);
20417
+ if (rules3 !== void 0) {
20418
+ maps.push(rules3);
20351
20419
  continue;
20352
20420
  }
20353
20421
  opaque.push({ ns: p.ns, ruleNames: isIRPiece(p) ? [] : [...p.keys] });
@@ -20358,7 +20426,7 @@ function recoverComposedRules(grammar) {
20358
20426
  const carried = composedPiecesOf(grammar);
20359
20427
  if (carried === void 0) return void 0;
20360
20428
  const { maps, opaque } = carriedRuleMapsDetailed(carried);
20361
- const rules2 = /* @__PURE__ */ new Map();
20429
+ const rules3 = /* @__PURE__ */ new Map();
20362
20430
  for (const map of maps) for (const [name, rule] of map) {
20363
20431
  if (rule._def.tag === "lazy") {
20364
20432
  try {
@@ -20367,9 +20435,9 @@ function recoverComposedRules(grammar) {
20367
20435
  continue;
20368
20436
  }
20369
20437
  }
20370
- rules2.set(name, rule);
20438
+ rules3.set(name, rule);
20371
20439
  }
20372
- return { rules: rules2, opaque };
20440
+ return { rules: rules3, opaque };
20373
20441
  }
20374
20442
  function composedCoverageRules(grammar) {
20375
20443
  const link = grammar[LINKED];
@@ -21282,12 +21350,12 @@ function inSet(code, fs) {
21282
21350
  var TERMINAL_TAGS = /* @__PURE__ */ new Set(["literal", "regex", "keywords", "scanTo"]);
21283
21351
  var INSTRUMENTABLE = /* @__PURE__ */ new Set(["firstMatch", "sharedPrefix"]);
21284
21352
  function profileWastedWork(opts) {
21285
- const { rules: rules2, corpus } = opts;
21286
- const { walked, unresolvedRoots } = walkRules(rules2);
21287
- const entryParser = typeof opts.entry === "string" ? rules2.find(([n]) => n === opts.entry)?.[1] : opts.entry;
21353
+ const { rules: rules3, corpus } = opts;
21354
+ const { walked, unresolvedRoots } = walkRules(rules3);
21355
+ const entryParser = typeof opts.entry === "string" ? rules3.find(([n]) => n === opts.entry)?.[1] : opts.entry;
21288
21356
  if (entryParser === void 0) {
21289
21357
  throw new TypeError(
21290
- `choice-cost: entry rule '${String(opts.entry)}' is not in the rule map (have: ${rules2.map(([n]) => n).slice(0, 12).join(", ")}${rules2.length > 12 ? ", \u2026" : ""}).`
21358
+ `choice-cost: entry rule '${String(opts.entry)}' is not in the rule map (have: ${rules3.map(([n]) => n).slice(0, 12).join(", ")}${rules3.length > 12 ? ", \u2026" : ""}).`
21291
21359
  );
21292
21360
  }
21293
21361
  if (corpus.length === 0) {