parseman 0.53.0 → 0.55.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 (69) hide show
  1. package/dist/analysis/diagnostics.js +295 -119
  2. package/dist/analysis/diagnostics.js.map +3 -3
  3. package/dist/cli/index.js +295 -119
  4. package/dist/cli/index.js.map +3 -3
  5. package/dist/combinators/field-trivia.d.ts +40 -0
  6. package/dist/combinators/field-trivia.d.ts.map +1 -0
  7. package/dist/combinators/map.d.ts +19 -2
  8. package/dist/combinators/map.d.ts.map +1 -1
  9. package/dist/combinators/repeat.d.ts.map +1 -1
  10. package/dist/combinators/sequence.d.ts.map +1 -1
  11. package/dist/combinators/withCtx.d.ts +22 -7
  12. package/dist/combinators/withCtx.d.ts.map +1 -1
  13. package/dist/compiler/fields.d.ts +2 -0
  14. package/dist/compiler/fields.d.ts.map +1 -1
  15. package/dist/cst/trivia-charscan.d.ts +11 -3
  16. package/dist/cst/trivia-charscan.d.ts.map +1 -1
  17. package/dist/cst/trivia-kinds.d.ts +11 -0
  18. package/dist/cst/trivia-kinds.d.ts.map +1 -1
  19. package/dist/index.d.ts +1 -0
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +319 -130
  22. package/dist/index.js.map +3 -3
  23. package/dist/plugin/evaluator.d.ts.map +1 -1
  24. package/dist/plugin/index.js +324 -132
  25. package/dist/plugin/index.js.map +3 -3
  26. package/dist/table/assemble.d.ts +9 -0
  27. package/dist/table/assemble.d.ts.map +1 -1
  28. package/dist/table/emit-assembly.d.ts +1 -1
  29. package/dist/table/emit-assembly.d.ts.map +1 -1
  30. package/dist/table/emit.d.ts +6 -2
  31. package/dist/table/emit.d.ts.map +1 -1
  32. package/dist/table/encode.d.ts.map +1 -1
  33. package/dist/table/exec.d.ts.map +1 -1
  34. package/dist/table/field-spec.d.ts +13 -0
  35. package/dist/table/field-spec.d.ts.map +1 -0
  36. package/dist/table/index.js +262 -113
  37. package/dist/table/index.js.map +3 -3
  38. package/dist/table/ops.d.ts +3 -1
  39. package/dist/table/ops.d.ts.map +1 -1
  40. package/dist/table/scalar-terminal.d.ts +11 -0
  41. package/dist/table/scalar-terminal.d.ts.map +1 -1
  42. package/dist/types.d.ts +14 -0
  43. package/dist/types.d.ts.map +1 -1
  44. package/dist/version.d.ts +1 -1
  45. package/package.json +1 -1
  46. package/src/analysis/duplication.ts +1 -1
  47. package/src/analysis/rebuild.ts +1 -1
  48. package/src/combinators/field-trivia.ts +44 -0
  49. package/src/combinators/map.ts +48 -6
  50. package/src/combinators/repeat.ts +6 -1
  51. package/src/combinators/sequence.ts +9 -1
  52. package/src/combinators/withCtx.ts +61 -28
  53. package/src/compiler/fields.ts +5 -2
  54. package/src/compiler/ir-serialize.ts +7 -1
  55. package/src/coverage.ts +1 -1
  56. package/src/cst/trivia-charscan.ts +17 -56
  57. package/src/cst/trivia-kinds.ts +24 -8
  58. package/src/index.ts +1 -0
  59. package/src/plugin/evaluator.ts +13 -3
  60. package/src/table/assemble.ts +137 -23
  61. package/src/table/emit-assembly.ts +38 -18
  62. package/src/table/emit.ts +15 -4
  63. package/src/table/encode.ts +23 -2
  64. package/src/table/exec.ts +17 -2
  65. package/src/table/field-spec.ts +17 -0
  66. package/src/table/ops.ts +3 -1
  67. package/src/table/scalar-terminal.ts +25 -0
  68. package/src/types.ts +14 -2
  69. package/src/version.ts +1 -1
package/dist/index.js CHANGED
@@ -1659,65 +1659,17 @@ function plainRegexSource(p) {
1659
1659
  const d = p._def;
1660
1660
  return d.tag === "regex" && d.flags === "" ? d.source : null;
1661
1661
  }
1662
- var visitSpec0;
1663
- var visitSpec1;
1664
- var visitSpec2;
1665
- var visitSpec3;
1666
- var visitValue0;
1667
- var visitValue1;
1668
- var visitValue2;
1669
- var visitValue3;
1670
1662
  function commonLabeledTriviaVisitor(spec) {
1671
- if (spec === visitSpec0) return visitValue0;
1672
- if (spec === visitSpec1) return visitValue1;
1673
- if (spec === visitSpec2) return visitValue2;
1674
- if (spec === visitSpec3) return visitValue3;
1675
- const sources = spec.minRepeats <= 1 ? spec.arms.map((arm) => plainRegexSource(arm.parser)) : [];
1676
- const visitor = commonCssTriviaVisitor(sources);
1677
- visitSpec3 = visitSpec2;
1678
- visitValue3 = visitValue2;
1679
- visitSpec2 = visitSpec1;
1680
- visitValue2 = visitValue1;
1681
- visitSpec1 = visitSpec0;
1682
- visitValue1 = visitValue0;
1683
- visitSpec0 = spec;
1684
- visitValue0 = visitor;
1685
- return visitor;
1686
- }
1687
- var armSpec0;
1688
- var armSpec1;
1689
- var armSpec2;
1690
- var armSpec3;
1691
- var armValue0;
1692
- var armValue1;
1693
- var armValue2;
1694
- var armValue3;
1663
+ return commonCssTriviaVisitor(spec.minRepeats <= 1 ? spec.arms.map((arm) => plainRegexSource(arm.parser)) : []);
1664
+ }
1695
1665
  function charArmsFor(spec) {
1696
- if (spec === armSpec0) return armValue0;
1697
- if (spec === armSpec1) return armValue1;
1698
- if (spec === armSpec2) return armValue2;
1699
- if (spec === armSpec3) return armValue3;
1700
- let arms = [];
1701
- if (spec.minRepeats > 1) {
1702
- arms = null;
1703
- } else {
1704
- for (const arm of spec.arms) {
1705
- const c = classifyParser(arm.parser);
1706
- if (!c) {
1707
- arms = null;
1708
- break;
1709
- }
1710
- arms.push(c);
1711
- }
1666
+ if (spec.minRepeats > 1) return null;
1667
+ const arms = [];
1668
+ for (const arm of spec.arms) {
1669
+ const c = classifyParser(arm.parser);
1670
+ if (!c) return null;
1671
+ arms.push(c);
1712
1672
  }
1713
- armSpec3 = armSpec2;
1714
- armValue3 = armValue2;
1715
- armSpec2 = armSpec1;
1716
- armValue2 = armValue1;
1717
- armSpec1 = armSpec0;
1718
- armValue1 = armValue0;
1719
- armSpec0 = spec;
1720
- armValue0 = arms;
1721
1673
  return arms;
1722
1674
  }
1723
1675
  function charTriviaEnd(input, cur, arms) {
@@ -1833,12 +1785,16 @@ function analyzeLabeledTrivia(trivia2) {
1833
1785
  }
1834
1786
  arms.push({ label: peeled.label, kindIndex: 0, parser: peeled.parser });
1835
1787
  }
1836
- const spec = {
1788
+ return cacheLabeledTrivia(trivia2, labeledTriviaSpec(arms, minRepeats));
1789
+ }
1790
+ function labeledTriviaSpec(arms, minRepeats) {
1791
+ return {
1837
1792
  labels: arms.map((a) => a.label),
1838
1793
  arms,
1839
- minRepeats
1794
+ minRepeats,
1795
+ visitor: commonLabeledTriviaVisitor({ arms, minRepeats }),
1796
+ charArms: charArmsFor({ arms, minRepeats })
1840
1797
  };
1841
- return cacheLabeledTrivia(trivia2, spec);
1842
1798
  }
1843
1799
  function matchArmAt(input, pos, arm, state) {
1844
1800
  if (!startsFirstSet(arm, input, pos)) return null;
@@ -1868,7 +1824,7 @@ function scanLabeledTriviaChunks(input, cur, spec, state) {
1868
1824
  return { end: pos, chunks };
1869
1825
  }
1870
1826
  function scanLabeledTriviaEnd(input, cur, spec, state) {
1871
- const chars = charArmsFor(spec);
1827
+ const chars = spec.charArms;
1872
1828
  if (chars !== null) return charTriviaEnd(input, cur, chars);
1873
1829
  let pos = cur;
1874
1830
  let count = 0;
@@ -1886,9 +1842,9 @@ function scanLabeledTriviaEnd(input, cur, spec, state) {
1886
1842
  }
1887
1843
  function visitLabeledTrivia(input, cur, spec, state, visit) {
1888
1844
  if (spec.minRepeats > 1) return void 0;
1889
- const common = commonLabeledTriviaVisitor(spec);
1845
+ const common = spec.visitor;
1890
1846
  if (common !== null) return common(input, cur, visit);
1891
- const chars = charArmsFor(spec);
1847
+ const chars = spec.charArms;
1892
1848
  if (chars !== null) return charTriviaVisit(input, cur, chars, visit);
1893
1849
  let pos = cur;
1894
1850
  let count = 0;
@@ -1955,7 +1911,7 @@ function resolveAdjacencyKindMask(trivia2, kinds) {
1955
1911
  return mask;
1956
1912
  }
1957
1913
  function triviaKindMaskAt(input, pos, spec, state) {
1958
- const chars = charArmsFor(spec);
1914
+ const chars = spec.charArms;
1959
1915
  if (chars !== null) return charTriviaKindMask(input, pos, chars);
1960
1916
  let cur = pos;
1961
1917
  let mask = 0;
@@ -2739,6 +2695,23 @@ function scalarRootOf(combinator) {
2739
2695
  return scalar !== void 0 && def.tag === "grammar" && scalarTree(def.parser, /* @__PURE__ */ new Set()) ? scalar : void 0;
2740
2696
  }
2741
2697
 
2698
+ // src/combinators/field-trivia.ts
2699
+ var LEAD = { at: -1 };
2700
+ var FIELD_LEADING_TRIVIA = 1;
2701
+ var FIELD_TRAILING_TRIVIA = 2;
2702
+ function triviaFieldCapture(name, value, input, start, end, leadFrom, trailEnd) {
2703
+ return {
2704
+ name,
2705
+ value,
2706
+ span: { start, end },
2707
+ leading: leadFrom >= 0 && leadFrom < start ? input.slice(leadFrom, start) : "",
2708
+ trailing: trailEnd > end ? input.slice(end, trailEnd) : ""
2709
+ };
2710
+ }
2711
+ function leadsTrivia(p) {
2712
+ return p._def.tag === "field" && p._def.leadingTrivia === true;
2713
+ }
2714
+
2742
2715
  // src/combinators/sequence.ts
2743
2716
  function sequence(...parsers) {
2744
2717
  let adjacency = null;
@@ -2754,6 +2727,10 @@ function sequence(...parsers) {
2754
2727
  (adjacency ??= Array.from({ length: parsers.length }, () => null))[i] = a;
2755
2728
  }
2756
2729
  const hasAdjacency = adjacency !== null;
2730
+ let leading = null;
2731
+ for (let i = 1; i < parsers.length; i++) {
2732
+ if (leadsTrivia(parsers[i])) (leading ??= Array.from({ length: parsers.length }, () => false))[i] = true;
2733
+ }
2757
2734
  const strictArity = !hasAdjacency && (parsers.length === 2 && !matchesEmpty(parsers[1]) || parsers.length === 3 && parsers.every((p) => !matchesEmpty(p))) ? parsers.length : 0;
2758
2735
  const meta = {
2759
2736
  // Union through the nullable prefix — a leading optional()/many() lets a later
@@ -2801,7 +2778,7 @@ function sequence(...parsers) {
2801
2778
  _tag: "sequence",
2802
2779
  _meta: meta,
2803
2780
  _def: def,
2804
- _parseScalar: hasAdjacency ? void 0 : parseScalar,
2781
+ _parseScalar: hasAdjacency || leading !== null ? void 0 : parseScalar,
2805
2782
  parse(input, pos, ctx) {
2806
2783
  const tolerant = ctx._tolerant === true;
2807
2784
  if (tolerant) {
@@ -2835,6 +2812,7 @@ function sequence(...parsers) {
2835
2812
  const scanTlog = deferredTrivia ? cstTlLen(ctx) : 0;
2836
2813
  const scanLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
2837
2814
  const scanRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
2815
+ if (leading?.[i] === true) LEAD.at = cur;
2838
2816
  const result = parsers[i].parse(input, termPos, ctx);
2839
2817
  if (!result.ok) return result;
2840
2818
  if (values !== void 0) values.push(result.value);
@@ -3816,6 +3794,7 @@ function unwrapSeparator(separator) {
3816
3794
  }
3817
3795
  function sepBy(combinator, separatorArg, opts = {}) {
3818
3796
  const { sep: separator, keep: keepSeparators } = unwrapSeparator(separatorArg);
3797
+ const separatorLeads = leadsTrivia(separator);
3819
3798
  const { min, max } = resolveBounds("sepBy()", opts);
3820
3799
  const trailing = opts.trailing ?? "forbid";
3821
3800
  const meta = {
@@ -3880,7 +3859,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
3880
3859
  // this option surface already; parity is held by test/parity, not by hope.
3881
3860
  ...keepSeparators ? { keepSeparators: true } : {}
3882
3861
  },
3883
- _parseScalar: keepSeparators ? void 0 : parseScalar,
3862
+ _parseScalar: keepSeparators || separatorLeads ? void 0 : parseScalar,
3884
3863
  parse(input, pos, ctx) {
3885
3864
  const first = combinator.parse(input, pos, ctx);
3886
3865
  const values = [];
@@ -3912,6 +3891,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
3912
3891
  sepPos = advanceTrivia(input, cur, ctx);
3913
3892
  }
3914
3893
  }
3894
+ if (separatorLeads) LEAD.at = cur;
3915
3895
  const sep = separator.parse(input, sepPos, ctx);
3916
3896
  if (!sep.ok) {
3917
3897
  rollbackTrivia(ctx, loopMark);
@@ -4928,7 +4908,7 @@ function buildFieldMap(captures) {
4928
4908
  if (!captures?.length) return void 0;
4929
4909
  const out = {};
4930
4910
  for (const cap of captures) {
4931
- const entry = { value: cap.value, span: cap.span };
4911
+ const entry = cap.leading === void 0 ? { value: cap.value, span: cap.span } : { value: cap.value, span: cap.span, leading: cap.leading, trailing: cap.trailing };
4932
4912
  const current = out[cap.name];
4933
4913
  if (current === void 0) out[cap.name] = entry;
4934
4914
  else if (Array.isArray(current)) current.push(entry);
@@ -5160,16 +5140,41 @@ function label(name, combinator) {
5160
5140
  }
5161
5141
  };
5162
5142
  }
5163
- function field(name, combinator) {
5143
+ function field(name, combinator, opts) {
5144
+ const leadingTrivia = opts?.leadingTrivia === true;
5145
+ const trailingTrivia = opts?.trailingTrivia === true;
5146
+ if (!leadingTrivia && !trailingTrivia) {
5147
+ return {
5148
+ _tag: combinator._tag,
5149
+ _meta: combinator._meta,
5150
+ _def: { tag: "field", name, parser: combinator },
5151
+ parse(input, pos, ctx) {
5152
+ const result = combinator.parse(input, pos, ctx);
5153
+ if (!result.ok) return result;
5154
+ ctx._fields?.push({ name, value: result.value, span: result.span });
5155
+ return result;
5156
+ }
5157
+ };
5158
+ }
5164
5159
  return {
5165
5160
  _tag: combinator._tag,
5166
5161
  _meta: combinator._meta,
5167
- _def: { tag: "field", name, parser: combinator },
5162
+ _def: {
5163
+ tag: "field",
5164
+ name,
5165
+ parser: combinator,
5166
+ ...leadingTrivia ? { leadingTrivia: true } : {},
5167
+ ...trailingTrivia ? { trailingTrivia: true } : {}
5168
+ },
5168
5169
  parse(input, pos, ctx) {
5170
+ const leadFrom = LEAD.at;
5171
+ LEAD.at = -1;
5169
5172
  const result = combinator.parse(input, pos, ctx);
5170
5173
  if (!result.ok) return result;
5171
- ctx._fields?.push({ name, value: result.value, span: result.span });
5172
- return result;
5174
+ const end = result.span.end;
5175
+ const trailEnd = trailingTrivia && ctx.trivia ? consumeTrivia(input, end, ctx) : end;
5176
+ ctx._fields?.push(triviaFieldCapture(name, result.value, input, result.span.start, end, leadingTrivia ? leadFrom : -1, trailEnd));
5177
+ return trailEnd === end ? result : { ok: true, value: result.value, span: { start: result.span.start, end: trailEnd } };
5173
5178
  }
5174
5179
  };
5175
5180
  }
@@ -7607,6 +7612,16 @@ var Encoder = class {
7607
7612
  this.kIndex.set(key, i);
7608
7613
  return i;
7609
7614
  }
7615
+ fieldSpecIndex = /* @__PURE__ */ new Map();
7616
+ fieldSpecSlot(name, bits) {
7617
+ const key = JSON.stringify([name, bits]);
7618
+ const hit = this.fieldSpecIndex.get(key);
7619
+ if (hit !== void 0) return hit;
7620
+ const i = this.k.length;
7621
+ this.k.push([name, bits]);
7622
+ this.fieldSpecIndex.set(key, i);
7623
+ return i;
7624
+ }
7610
7625
  /**
7611
7626
  * A `notAdjacent({ kinds })` filter, pooled by its CONTENTS.
7612
7627
  *
@@ -8227,8 +8242,10 @@ var Encoder = class {
8227
8242
  for (let i = 0; i < arms.length; i++) this.code[head + 6 + i] = arms[i];
8228
8243
  return head;
8229
8244
  }
8230
- case "field":
8231
- return this.emit(OP_FIELD, this.constant(d.name), this.node(d.parser).ip);
8245
+ case "field": {
8246
+ const bits = (d.leadingTrivia === true ? FIELD_LEADING_TRIVIA : 0) | (d.trailingTrivia === true ? FIELD_TRAILING_TRIVIA : 0);
8247
+ return this.emit(OP_FIELD, bits === 0 ? this.constant(d.name) : this.fieldSpecSlot(d.name, bits), this.node(d.parser).ip);
8248
+ }
8232
8249
  case "lazy": {
8233
8250
  const refName = p._ruleName;
8234
8251
  const winner = refName === void 0 ? void 0 : this.winners?.[refName];
@@ -8260,6 +8277,9 @@ var Encoder = class {
8260
8277
  this.expected([adjacencyExpected(d)])
8261
8278
  );
8262
8279
  case "withCtx": {
8280
+ if (typeof d.extra === "function") {
8281
+ return this.emit(OP_WITHCTX, ~this.fn(d.extra, d.extraSrc ?? null), this.node(d.parser).ip);
8282
+ }
8263
8283
  if (!emittableConst(d.extra)) {
8264
8284
  this.runtimeOnly.add("withCtx(extra) \u2014 the state object is not serialisable");
8265
8285
  }
@@ -9904,6 +9924,26 @@ function leadingLiteralFamily(code, constants, ip, minDepth = 2, limit = 4) {
9904
9924
  };
9905
9925
  return walk(ip, 0);
9906
9926
  }
9927
+ function largeChoiceLiteralPretest(code, constants, armIp) {
9928
+ const child = leadingScalarTerminal(code, armIp, 2, true, true);
9929
+ if (child >= 0) {
9930
+ const spec = constants[code[child + 1]];
9931
+ if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) return [child];
9932
+ }
9933
+ const family = leadingLiteralFamily(code, constants, armIp);
9934
+ return family !== void 0 && family.length >= 2 && family.every((terminal) => {
9935
+ const value = constants[code[terminal + 1]];
9936
+ return typeof value === "string" && value.length >= 2;
9937
+ }) ? family : void 0;
9938
+ }
9939
+
9940
+ // src/table/field-spec.ts
9941
+ function fieldSpec(slot) {
9942
+ return Array.isArray(slot) ? { name: slot[0], bits: slot[1] } : { name: slot, bits: 0 };
9943
+ }
9944
+ function leadingTriviaFieldAt(code, k, ip) {
9945
+ return code[ip] === OP_FIELD && (fieldSpec(k[code[ip + 1]]).bits & FIELD_LEADING_TRIVIA) !== 0;
9946
+ }
9907
9947
 
9908
9948
  // src/table/emit-assembly.ts
9909
9949
  var Unemittable = class extends Error {
@@ -9978,7 +10018,11 @@ var EMITTED_PARAMS = [
9978
10018
  // Appended for old precompiled-factory ABI: old factories ignore it.
9979
10019
  "adjacencyHolds",
9980
10020
  // Appended for selected composite lexical programs; old factories ignore it.
9981
- "LEXPROG"
10021
+ "LEXPROG",
10022
+ // Appended for trivia-attributing fields (`field(…, { leadingTrivia })`);
10023
+ // old factories ignore them.
10024
+ "LEAD",
10025
+ "triviaFieldCapture"
9982
10026
  ];
9983
10027
  var RUNTIME_PRELUDE = `
9984
10028
  let _pfScan=null
@@ -10238,20 +10282,12 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
10238
10282
  if (child >= 0) scalarSpecs.add(code[child + 1]);
10239
10283
  continue;
10240
10284
  }
10241
- if (child >= 0) {
10242
- const spec = k[code[child + 1]];
10243
- if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
10244
- largeChoiceScalarSpecs.add(code[child + 1]);
10245
- continue;
10246
- }
10247
- }
10248
- const family = leadingLiteralFamily(code, k, armIp);
10249
- if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
10250
- const value = k[code[terminal + 1]];
10251
- return typeof value === "string" && value.length >= 2;
10252
- })) {
10253
- largeChoiceLiteralFamilies.set(armIp, family);
10285
+ const literals = largeChoiceLiteralPretest(code, k, armIp);
10286
+ if (literals !== void 0 && literals.length === 1 && literals[0] === child) {
10287
+ largeChoiceScalarSpecs.add(code[child + 1]);
10288
+ continue;
10254
10289
  }
10290
+ if (literals !== void 0) largeChoiceLiteralFamilies.set(armIp, literals);
10255
10291
  const sequence6 = leadingScalarSequence(code, armIp);
10256
10292
  if (sequence6 !== void 0 && (sequence6.trivia < 0 || swapLegal && t.triviaScan[sequence6.trivia] != null)) {
10257
10293
  largeChoiceScalarSequences.set(armIp, sequence6);
@@ -10675,14 +10711,31 @@ return v
10675
10711
  }`;
10676
10712
  }
10677
10713
  case OP_FIELD: {
10678
- const name = q(k[code[ip + 1]]);
10714
+ const spec = fieldSpec(k[code[ip + 1]]);
10715
+ const name = q(spec.name);
10679
10716
  const child = link(code[ip + 2]);
10680
- return `${head}
10717
+ if (spec.bits === 0) {
10718
+ return `${head}
10681
10719
  const v=${child}(input,pos,ctx)
10682
10720
  if(v===FAIL)return FAIL
10683
10721
  const f=ctx._fields
10684
10722
  if(f!==undefined)f.push({name:${name},value:v,span:{start:pos,end:EC.e}})
10685
10723
  return v
10724
+ }`;
10725
+ }
10726
+ const leading = (spec.bits & FIELD_LEADING_TRIVIA) !== 0;
10727
+ const trailing = (spec.bits & FIELD_TRAILING_TRIVIA) !== 0;
10728
+ return `${head}
10729
+ const lf=${leading ? "LEAD.at" : "-1"}
10730
+ LEAD.at=-1
10731
+ const v=${child}(input,pos,ctx)
10732
+ if(v===FAIL)return FAIL
10733
+ const e=EC.e
10734
+ const te=${trailing ? "ctx.trivia!==undefined?consumeTrivia(input,e,ctx):e" : "e"}
10735
+ const f=ctx._fields
10736
+ if(f!==undefined)f.push(triviaFieldCapture(${name},v,input,pos,e,lf,te))
10737
+ EC.e=te
10738
+ return v
10686
10739
  }`;
10687
10740
  }
10688
10741
  case OP_EXPECT: {
@@ -10978,7 +11031,10 @@ return v
10978
11031
  `if(!adjacencyHolds(input,cur,ctx,${negated ? "true" : "false"},${kinds})){ctx._fe=cur;ctx._fx=${expected};return FAIL}`,
10979
11032
  `${vn}=null`
10980
11033
  );
10981
- } else parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
11034
+ } else {
11035
+ const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
11036
+ parts.push(emitTerm(callee, vn, tmp(), L, skipFor(L)));
11037
+ }
10982
11038
  names.push(vn);
10983
11039
  }
10984
11040
  parts.push("EC.e=cur");
@@ -11378,7 +11434,7 @@ let sp=cur
11378
11434
  ${hasTrivia === "false" ? "" : hasTrivia === "true" ? `sp=${skip}(input,sp,ctx)
11379
11435
  ` : `if(hasTrivia)sp=${skip}(input,sp,ctx)
11380
11436
  `}ctx._fc=false
11381
- const sv=${sep}(input,sp,ctx)
11437
+ ${sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp) ? "LEAD.at=cur\n" : ""}const sv=${sep}(input,sp,ctx)
11382
11438
  if(sv===FAIL){
11383
11439
  ${rb}
11384
11440
  if(ctx._fc===true)return FAIL
@@ -12488,6 +12544,12 @@ function assemble(t, prog, cfg) {
12488
12544
  rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
12489
12545
  return cur;
12490
12546
  }
12547
+ function leadingFieldTerm(step, child, input, cur, ctx) {
12548
+ return step((i, p, c) => {
12549
+ LEAD.at = cur;
12550
+ return child(i, p, c);
12551
+ }, input, cur, ctx);
12552
+ }
12491
12553
  function committed3(c) {
12492
12554
  return c._fc === true;
12493
12555
  }
@@ -13125,12 +13187,27 @@ function assemble(t, prog, cfg) {
13125
13187
  };
13126
13188
  }
13127
13189
  case OP_FIELD: {
13128
- const name = k[code[ip + 1]];
13190
+ const { name, bits } = fieldSpec(k[code[ip + 1]]);
13129
13191
  const child = link(code[ip + 2]);
13192
+ if (bits === 0) {
13193
+ return (input, pos, ctx) => {
13194
+ const v = child(input, pos, ctx);
13195
+ if (v === FAIL) return FAIL;
13196
+ ctx._fields?.push({ name, value: v, span: { start: pos, end: EC.e } });
13197
+ return v;
13198
+ };
13199
+ }
13200
+ const leading = (bits & FIELD_LEADING_TRIVIA) !== 0;
13201
+ const trailing = (bits & FIELD_TRAILING_TRIVIA) !== 0;
13130
13202
  return (input, pos, ctx) => {
13203
+ const leadFrom = leading ? LEAD.at : -1;
13204
+ LEAD.at = -1;
13131
13205
  const v = child(input, pos, ctx);
13132
13206
  if (v === FAIL) return FAIL;
13133
- ctx._fields?.push({ name, value: v, span: { start: pos, end: EC.e } });
13207
+ const end = EC.e;
13208
+ const trailEnd = trailing && ctx.trivia !== void 0 ? consumeTrivia(input, end, ctx) : end;
13209
+ ctx._fields?.push(triviaFieldCapture(name, v, input, pos, end, leadFrom, trailEnd));
13210
+ EC.e = trailEnd;
13134
13211
  return v;
13135
13212
  };
13136
13213
  }
@@ -13159,8 +13236,21 @@ function assemble(t, prog, cfg) {
13159
13236
  };
13160
13237
  }
13161
13238
  case OP_WITHCTX: {
13162
- const extra = k[code[ip + 1]];
13239
+ const ki = code[ip + 1];
13163
13240
  const child = link(code[ip + 2]);
13241
+ if (ki < 0) {
13242
+ const derive2 = fns[~ki];
13243
+ return (input, pos, ctx) => {
13244
+ const saved = ctx.state;
13245
+ ctx.state = derive2(saved);
13246
+ try {
13247
+ return child(input, pos, ctx);
13248
+ } finally {
13249
+ ctx.state = saved;
13250
+ }
13251
+ };
13252
+ }
13253
+ const extra = k[ki];
13164
13254
  return (input, pos, ctx) => {
13165
13255
  const saved = ctx.state;
13166
13256
  ctx.state = extra;
@@ -13564,6 +13654,12 @@ function assemble(t, prog, cfg) {
13564
13654
  const kidIp = code[base + i];
13565
13655
  if (code[kidIp] !== OP_ADJ) {
13566
13656
  const kid = link(kidIp);
13657
+ if (leadingTriviaFieldAt(code, k, kidIp)) {
13658
+ return (input, cur, ctx, inherited) => {
13659
+ ctx._sync = sync ?? inherited;
13660
+ return leadingFieldTerm(step, kid, input, cur, ctx);
13661
+ };
13662
+ }
13567
13663
  return (input, cur, ctx, inherited) => {
13568
13664
  ctx._sync = sync ?? inherited;
13569
13665
  return step(kid, input, cur, ctx);
@@ -13641,9 +13737,12 @@ function assemble(t, prog, cfg) {
13641
13737
  };
13642
13738
  }
13643
13739
  let hasAdj = false;
13644
- for (let i = 1; i < n; i++) if (code[code[base + i]] === OP_ADJ) {
13645
- hasAdj = true;
13646
- break;
13740
+ for (let i = 1; i < n; i++) {
13741
+ const kidIp = code[base + i];
13742
+ if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp)) {
13743
+ hasAdj = true;
13744
+ break;
13745
+ }
13647
13746
  }
13648
13747
  if (hasAdj) {
13649
13748
  const first2 = link(code[base]);
@@ -13651,6 +13750,9 @@ function assemble(t, prog, cfg) {
13651
13750
  const kidIp = code[base + i];
13652
13751
  if (code[kidIp] !== OP_ADJ) {
13653
13752
  const kid = link(kidIp);
13753
+ if (leadingTriviaFieldAt(code, k, kidIp)) {
13754
+ return (input, cur, ctx) => leadingFieldTerm(step, kid, input, cur, ctx);
13755
+ }
13654
13756
  return (input, cur, ctx) => step(kid, input, cur, ctx);
13655
13757
  }
13656
13758
  const negated = code[kidIp + 1] === 1;
@@ -14013,7 +14115,7 @@ function assemble(t, prog, cfg) {
14013
14115
  if (n === 2 || n === 3) {
14014
14116
  const a0 = link(code[base]), a1 = link(code[base + 1]);
14015
14117
  const a2 = n === 3 ? link(code[base + 2]) : void 0;
14016
- const predecide = !hostCst && !REC2 && !cfg.probe && !cfg.coverage && !cfg.trackLines;
14118
+ const predecide = !REC2 && !cfg.probe && !cfg.coverage && !cfg.trackLines;
14017
14119
  const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
14018
14120
  const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
14019
14121
  const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
@@ -14236,6 +14338,75 @@ function assemble(t, prog, cfg) {
14236
14338
  );
14237
14339
  };
14238
14340
  const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
14341
+ const pBit = [];
14342
+ const pRec = [];
14343
+ if (!REC2 && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
14344
+ for (let i = 0; i < n; i++) {
14345
+ for (const terminal of largeChoiceLiteralPretest(code, k, code[base + i]) ?? []) {
14346
+ pBit.push(1 << i);
14347
+ pRec.push(scalarFor(terminal));
14348
+ }
14349
+ }
14350
+ }
14351
+ const pn = pBit.length;
14352
+ if (pn !== 0) {
14353
+ return (input, pos, ctx) => {
14354
+ const c = lead(input, pos);
14355
+ const need = markCst(ctx);
14356
+ const mRaw = MRAW;
14357
+ const mTl = MTL;
14358
+ const mLv = MLV;
14359
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
14360
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
14361
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
14362
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
14363
+ if (c < 128) {
14364
+ const bits = mask[c < 0 ? 128 : c];
14365
+ let tested = 0;
14366
+ let hit = 0;
14367
+ for (let i = 0; i < pn; i++) {
14368
+ const b = pBit[i];
14369
+ if ((bits & b) === 0 || (hit & b) !== 0) continue;
14370
+ tested |= b;
14371
+ if (pRec[i](input, pos) >= 0) hit |= b;
14372
+ }
14373
+ return masked(
14374
+ input,
14375
+ pos,
14376
+ ctx,
14377
+ bits & (~tested | hit),
14378
+ need,
14379
+ mRaw,
14380
+ mTl,
14381
+ mLv,
14382
+ mFl,
14383
+ mEr,
14384
+ mLog,
14385
+ mRoot,
14386
+ void 0,
14387
+ 0,
14388
+ pos
14389
+ );
14390
+ }
14391
+ return general(
14392
+ input,
14393
+ pos,
14394
+ ctx,
14395
+ c,
14396
+ need,
14397
+ mRaw,
14398
+ mTl,
14399
+ mLv,
14400
+ mFl,
14401
+ mEr,
14402
+ mLog,
14403
+ mRoot,
14404
+ void 0,
14405
+ 0,
14406
+ pos
14407
+ );
14408
+ };
14409
+ }
14239
14410
  return (input, pos, ctx) => {
14240
14411
  const c = lead(input, pos);
14241
14412
  const need = markCst(ctx);
@@ -14397,6 +14568,7 @@ function assemble(t, prog, cfg) {
14397
14568
  const max = code[ip + 3];
14398
14569
  const sepIp = code[ip + 4];
14399
14570
  const sep = sepIp >= 0 ? link(sepIp) : void 0;
14571
+ const sepLeads = sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp);
14400
14572
  const flags = code[ip + 5];
14401
14573
  const keepSeparators = (flags & 2) !== 0;
14402
14574
  const trailingAllowed = (flags & 1) !== 0;
@@ -14436,6 +14608,7 @@ function assemble(t, prog, cfg) {
14436
14608
  let sp = cur;
14437
14609
  if (hasTrivia) sp = skipTrivia(input, sp, ctx);
14438
14610
  ctx._fc = false;
14611
+ if (sepLeads) LEAD.at = cur;
14439
14612
  const sv = sep(input, sp, ctx);
14440
14613
  if (sv === FAIL) {
14441
14614
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
@@ -14525,6 +14698,7 @@ function assemble(t, prog, cfg) {
14525
14698
  let sp = cur;
14526
14699
  if (hasTrivia) sp = skipTrivia(input, sp, ctx);
14527
14700
  ctx._fc = false;
14701
+ if (sepLeads) LEAD.at = cur;
14528
14702
  const sv = sep(input, sp, ctx);
14529
14703
  if (sv === FAIL) {
14530
14704
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
@@ -14847,20 +15021,9 @@ function assemble(t, prog, cfg) {
14847
15021
  if (child >= 0) scalarFor(child);
14848
15022
  continue;
14849
15023
  }
14850
- if (child >= 0) {
14851
- const spec = k[code[child + 1]];
14852
- if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
14853
- scalarFor(child);
14854
- continue;
14855
- }
14856
- }
14857
- const family = leadingLiteralFamily(code, k, armIp);
14858
- if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
14859
- const value = k[code[terminal + 1]];
14860
- return typeof value === "string" && value.length >= 2;
14861
- })) {
14862
- for (const terminal of family) scalarFor(terminal);
14863
- }
15024
+ const literals = largeChoiceLiteralPretest(code, k, armIp);
15025
+ if (literals !== void 0) for (const terminal of literals) scalarFor(terminal);
15026
+ if (literals !== void 0 && literals.length === 1 && literals[0] === child) continue;
14864
15027
  const sequence6 = leadingScalarSequence(code, armIp);
14865
15028
  if (sequence6 !== void 0 && (sequence6.trivia < 0 || triviaScan[sequence6.trivia] != null)) {
14866
15029
  for (const terminal of sequence6.terminals) scalarFor(terminal);
@@ -14926,7 +15089,9 @@ function assemble(t, prog, cfg) {
14926
15089
  scanTriviaCompact,
14927
15090
  t.lex,
14928
15091
  adjacencyHolds,
14929
- t.lexPrograms
15092
+ t.lexPrograms,
15093
+ LEAD,
15094
+ triviaFieldCapture
14930
15095
  );
14931
15096
  emitReached = new Set(pre.reached);
14932
15097
  }
@@ -15008,7 +15173,9 @@ function assemble(t, prog, cfg) {
15008
15173
  scanTriviaCompact,
15009
15174
  t.lex,
15010
15175
  adjacencyHolds,
15011
- t.lexPrograms
15176
+ t.lexPrograms,
15177
+ LEAD,
15178
+ triviaFieldCapture
15012
15179
  );
15013
15180
  emitReached = em.reached;
15014
15181
  } catch (e) {
@@ -15184,7 +15351,9 @@ var AssemblyCache = class {
15184
15351
  return made;
15185
15352
  }
15186
15353
  };
15187
- function tableRules(source, artifactMetadata = {}) {
15354
+ function tableRules(source, metadataOrEntry = {}) {
15355
+ const entry = typeof metadataOrEntry === "string" ? metadataOrEntry : void 0;
15356
+ const artifactMetadata = typeof metadataOrEntry === "string" ? {} : metadataOrEntry;
15188
15357
  const prog = expandCompact(source);
15189
15358
  const resolved = resolveTable(prog);
15190
15359
  const cache = new AssemblyCache(prog, resolved);
@@ -15192,7 +15361,7 @@ function tableRules(source, artifactMetadata = {}) {
15192
15361
  const skipOf = prog.scanSkipOf;
15193
15362
  let last;
15194
15363
  let selected;
15195
- return stampRuleMap(prog, {
15364
+ const map = stampRuleMap(prog, {
15196
15365
  runRule: (ri, input, pos, ctx) => {
15197
15366
  const a = selected ?? cache.forCtx(ctx);
15198
15367
  selected = void 0;
@@ -15213,6 +15382,9 @@ function tableRules(source, artifactMetadata = {}) {
15213
15382
  return a.scanSkip[skipOf?.[ri] ?? -1];
15214
15383
  }
15215
15384
  }, artifactMetadata, resolved);
15385
+ if (entry === void 0) return map;
15386
+ if (!Object.hasOwn(map, entry)) throw new Error(`tableRules: the program has no rule ${JSON.stringify(entry)}`);
15387
+ return map[entry];
15216
15388
  }
15217
15389
 
15218
15390
  // src/table/emit.ts
@@ -15378,11 +15550,15 @@ function emitTableExpression(prog, opts = {}) {
15378
15550
  const entry = opts.entry === void 0 ? "grammar" : opts.entry;
15379
15551
  const ref2 = opts.runtimeRef ?? "tableRules";
15380
15552
  const fns = opts.fnSources ?? prog.fns.map(() => "() => {}");
15381
- const close = `}${opts.metadataSource === void 0 ? "" : `,${opts.metadataSource}`})`;
15553
+ const meta = opts.metadataSource;
15554
+ if (entry !== null && meta !== void 0) {
15555
+ throw new Error("emitTableExpression: metadataSource is for the rule-map form (entry: null); a single entry carries none");
15556
+ }
15557
+ const tail = entry !== null ? `,${jsString(entry)}` : meta === void 0 ? "" : `,${meta}`;
15382
15558
  return [
15383
15559
  `/* @__PURE__ */ ${ref2}({`,
15384
15560
  ...programFields(prog, fns, opts),
15385
- entry === null ? close : `${close}[${jsString(entry)}]`
15561
+ `}${tail})`
15386
15562
  ].join("\n");
15387
15563
  }
15388
15564
 
@@ -15560,7 +15736,7 @@ function payloadKey(p, d) {
15560
15736
  case "label":
15561
15737
  return `label\0${d.label}`;
15562
15738
  case "field":
15563
- return `field\0${d.name}`;
15739
+ return `field\0${d.name}\0${d.leadingTrivia === true}\0${d.trailingTrivia === true}`;
15564
15740
  case "node":
15565
15741
  return `node\0${d.type ?? ""}\0${d.unwrap === true}\0${d.collapse === true}\0${fnKey(d.buildSrc, d.build)}`;
15566
15742
  case "transform":
@@ -17496,7 +17672,7 @@ ${outerDecls.map((d) => " " + d).join("\n")}
17496
17672
  case "label":
17497
17673
  return `label(${JSON.stringify(def.label)}, ${kid(def.parser)})`;
17498
17674
  case "field":
17499
- return `field(${JSON.stringify(def.name)}, ${kid(def.parser)})`;
17675
+ return `field(${JSON.stringify(def.name)}, ${kid(def.parser)}${fieldOptionsSrc(def)})`;
17500
17676
  case "expect":
17501
17677
  return `expect(${kid(def.parser)}${def.label !== void 0 ? `, ${JSON.stringify(def.label)}` : ""})`;
17502
17678
  case "scanTo":
@@ -17559,9 +17735,13 @@ ${outerDecls.map((d) => " " + d).join("\n")}
17559
17735
  }
17560
17736
  }
17561
17737
  };
17738
+ function fieldOptionsSrc(def) {
17739
+ if (def.leadingTrivia !== true && def.trailingTrivia !== true) return "";
17740
+ return `, { ${[def.leadingTrivia === true ? "leadingTrivia: true" : "", def.trailingTrivia === true ? "trailingTrivia: true" : ""].filter(Boolean).join(", ")} }`;
17741
+ }
17562
17742
 
17563
17743
  // src/version.ts
17564
- var PARSEMAN_VERSION = "0.53.0";
17744
+ var PARSEMAN_VERSION = "0.55.0";
17565
17745
 
17566
17746
  // src/compiler/compile-linkable-table.ts
17567
17747
  function isLocal(rule) {
@@ -19149,19 +19329,28 @@ function withCtx(extra, combinator) {
19149
19329
  canMatchNewline: combinator._meta.canMatchNewline,
19150
19330
  isTrivia: false
19151
19331
  };
19332
+ const parse2 = typeof extra === "function" ? (input, pos, ctx) => {
19333
+ const saved = ctx.state;
19334
+ ctx.state = extra(saved);
19335
+ try {
19336
+ return combinator.parse(input, pos, ctx);
19337
+ } finally {
19338
+ ctx.state = saved;
19339
+ }
19340
+ } : (input, pos, ctx) => {
19341
+ const saved = ctx.state;
19342
+ ctx.state = extra;
19343
+ try {
19344
+ return combinator.parse(input, pos, ctx);
19345
+ } finally {
19346
+ ctx.state = saved;
19347
+ }
19348
+ };
19152
19349
  return {
19153
19350
  _tag: "withCtx",
19154
19351
  _meta: meta,
19155
19352
  _def: { tag: "withCtx", extra, parser: combinator },
19156
- parse(input, pos, ctx) {
19157
- const saved = ctx.state;
19158
- ctx.state = extra;
19159
- try {
19160
- return combinator.parse(input, pos, ctx);
19161
- } finally {
19162
- ctx.state = saved;
19163
- }
19164
- }
19353
+ parse: parse2
19165
19354
  };
19166
19355
  }
19167
19356
 
@@ -20039,7 +20228,7 @@ function coverageEntry(entry, collector, maps, trace) {
20039
20228
  case "leaf":
20040
20229
  return def.cstValue === "source" ? sourceLeaf(build(def.parser), def.fn) : leaf(build(def.parser), def.fn);
20041
20230
  case "field":
20042
- return field(def.name, build(def.parser));
20231
+ return field(def.name, build(def.parser), { leadingTrivia: def.leadingTrivia === true, trailingTrivia: def.trailingTrivia === true });
20043
20232
  case "grammar":
20044
20233
  return parser({
20045
20234
  ...def.triviaParser === void 0 ? def.clearTrivia ? { trivia: null } : {} : { trivia: build(def.triviaParser) },