parseman 0.53.0 → 0.54.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 (62) hide show
  1. package/dist/analysis/diagnostics.js +278 -118
  2. package/dist/analysis/diagnostics.js.map +2 -2
  3. package/dist/cli/index.js +278 -118
  4. package/dist/cli/index.js.map +2 -2
  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/compiler/fields.d.ts +2 -0
  12. package/dist/compiler/fields.d.ts.map +1 -1
  13. package/dist/cst/trivia-charscan.d.ts +11 -3
  14. package/dist/cst/trivia-charscan.d.ts.map +1 -1
  15. package/dist/cst/trivia-kinds.d.ts +11 -0
  16. package/dist/cst/trivia-kinds.d.ts.map +1 -1
  17. package/dist/index.d.ts +1 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +284 -120
  20. package/dist/index.js.map +2 -2
  21. package/dist/plugin/index.js +284 -120
  22. package/dist/plugin/index.js.map +2 -2
  23. package/dist/table/assemble.d.ts +9 -0
  24. package/dist/table/assemble.d.ts.map +1 -1
  25. package/dist/table/emit-assembly.d.ts +1 -1
  26. package/dist/table/emit-assembly.d.ts.map +1 -1
  27. package/dist/table/emit.d.ts +6 -2
  28. package/dist/table/emit.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/field-spec.d.ts +13 -0
  32. package/dist/table/field-spec.d.ts.map +1 -0
  33. package/dist/table/index.js +245 -112
  34. package/dist/table/index.js.map +2 -2
  35. package/dist/table/scalar-terminal.d.ts +11 -0
  36. package/dist/table/scalar-terminal.d.ts.map +1 -1
  37. package/dist/types.d.ts +14 -0
  38. package/dist/types.d.ts.map +1 -1
  39. package/dist/version.d.ts +1 -1
  40. package/package.json +1 -1
  41. package/src/analysis/duplication.ts +1 -1
  42. package/src/analysis/rebuild.ts +1 -1
  43. package/src/combinators/field-trivia.ts +44 -0
  44. package/src/combinators/map.ts +48 -6
  45. package/src/combinators/repeat.ts +6 -1
  46. package/src/combinators/sequence.ts +9 -1
  47. package/src/compiler/fields.ts +5 -2
  48. package/src/compiler/ir-serialize.ts +7 -1
  49. package/src/coverage.ts +1 -1
  50. package/src/cst/trivia-charscan.ts +17 -56
  51. package/src/cst/trivia-kinds.ts +24 -8
  52. package/src/index.ts +1 -0
  53. package/src/plugin/evaluator.ts +1 -1
  54. package/src/table/assemble.ts +126 -22
  55. package/src/table/emit-assembly.ts +38 -18
  56. package/src/table/emit.ts +15 -4
  57. package/src/table/encode.ts +18 -2
  58. package/src/table/exec.ts +15 -1
  59. package/src/table/field-spec.ts +17 -0
  60. package/src/table/scalar-terminal.ts +25 -0
  61. package/src/types.ts +12 -2
  62. 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];
@@ -9904,6 +9921,26 @@ function leadingLiteralFamily(code, constants, ip, minDepth = 2, limit = 4) {
9904
9921
  };
9905
9922
  return walk(ip, 0);
9906
9923
  }
9924
+ function largeChoiceLiteralPretest(code, constants, armIp) {
9925
+ const child = leadingScalarTerminal(code, armIp, 2, true, true);
9926
+ if (child >= 0) {
9927
+ const spec = constants[code[child + 1]];
9928
+ if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) return [child];
9929
+ }
9930
+ const family = leadingLiteralFamily(code, constants, armIp);
9931
+ return family !== void 0 && family.length >= 2 && family.every((terminal) => {
9932
+ const value = constants[code[terminal + 1]];
9933
+ return typeof value === "string" && value.length >= 2;
9934
+ }) ? family : void 0;
9935
+ }
9936
+
9937
+ // src/table/field-spec.ts
9938
+ function fieldSpec(slot) {
9939
+ return Array.isArray(slot) ? { name: slot[0], bits: slot[1] } : { name: slot, bits: 0 };
9940
+ }
9941
+ function leadingTriviaFieldAt(code, k, ip) {
9942
+ return code[ip] === OP_FIELD && (fieldSpec(k[code[ip + 1]]).bits & FIELD_LEADING_TRIVIA) !== 0;
9943
+ }
9907
9944
 
9908
9945
  // src/table/emit-assembly.ts
9909
9946
  var Unemittable = class extends Error {
@@ -9978,7 +10015,11 @@ var EMITTED_PARAMS = [
9978
10015
  // Appended for old precompiled-factory ABI: old factories ignore it.
9979
10016
  "adjacencyHolds",
9980
10017
  // Appended for selected composite lexical programs; old factories ignore it.
9981
- "LEXPROG"
10018
+ "LEXPROG",
10019
+ // Appended for trivia-attributing fields (`field(…, { leadingTrivia })`);
10020
+ // old factories ignore them.
10021
+ "LEAD",
10022
+ "triviaFieldCapture"
9982
10023
  ];
9983
10024
  var RUNTIME_PRELUDE = `
9984
10025
  let _pfScan=null
@@ -10238,20 +10279,12 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
10238
10279
  if (child >= 0) scalarSpecs.add(code[child + 1]);
10239
10280
  continue;
10240
10281
  }
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);
10282
+ const literals = largeChoiceLiteralPretest(code, k, armIp);
10283
+ if (literals !== void 0 && literals.length === 1 && literals[0] === child) {
10284
+ largeChoiceScalarSpecs.add(code[child + 1]);
10285
+ continue;
10254
10286
  }
10287
+ if (literals !== void 0) largeChoiceLiteralFamilies.set(armIp, literals);
10255
10288
  const sequence6 = leadingScalarSequence(code, armIp);
10256
10289
  if (sequence6 !== void 0 && (sequence6.trivia < 0 || swapLegal && t.triviaScan[sequence6.trivia] != null)) {
10257
10290
  largeChoiceScalarSequences.set(armIp, sequence6);
@@ -10675,14 +10708,31 @@ return v
10675
10708
  }`;
10676
10709
  }
10677
10710
  case OP_FIELD: {
10678
- const name = q(k[code[ip + 1]]);
10711
+ const spec = fieldSpec(k[code[ip + 1]]);
10712
+ const name = q(spec.name);
10679
10713
  const child = link(code[ip + 2]);
10680
- return `${head}
10714
+ if (spec.bits === 0) {
10715
+ return `${head}
10681
10716
  const v=${child}(input,pos,ctx)
10682
10717
  if(v===FAIL)return FAIL
10683
10718
  const f=ctx._fields
10684
10719
  if(f!==undefined)f.push({name:${name},value:v,span:{start:pos,end:EC.e}})
10685
10720
  return v
10721
+ }`;
10722
+ }
10723
+ const leading = (spec.bits & FIELD_LEADING_TRIVIA) !== 0;
10724
+ const trailing = (spec.bits & FIELD_TRAILING_TRIVIA) !== 0;
10725
+ return `${head}
10726
+ const lf=${leading ? "LEAD.at" : "-1"}
10727
+ LEAD.at=-1
10728
+ const v=${child}(input,pos,ctx)
10729
+ if(v===FAIL)return FAIL
10730
+ const e=EC.e
10731
+ const te=${trailing ? "ctx.trivia!==undefined?consumeTrivia(input,e,ctx):e" : "e"}
10732
+ const f=ctx._fields
10733
+ if(f!==undefined)f.push(triviaFieldCapture(${name},v,input,pos,e,lf,te))
10734
+ EC.e=te
10735
+ return v
10686
10736
  }`;
10687
10737
  }
10688
10738
  case OP_EXPECT: {
@@ -10978,7 +11028,10 @@ return v
10978
11028
  `if(!adjacencyHolds(input,cur,ctx,${negated ? "true" : "false"},${kinds})){ctx._fe=cur;ctx._fx=${expected};return FAIL}`,
10979
11029
  `${vn}=null`
10980
11030
  );
10981
- } else parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
11031
+ } else {
11032
+ const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
11033
+ parts.push(emitTerm(callee, vn, tmp(), L, skipFor(L)));
11034
+ }
10982
11035
  names.push(vn);
10983
11036
  }
10984
11037
  parts.push("EC.e=cur");
@@ -11378,7 +11431,7 @@ let sp=cur
11378
11431
  ${hasTrivia === "false" ? "" : hasTrivia === "true" ? `sp=${skip}(input,sp,ctx)
11379
11432
  ` : `if(hasTrivia)sp=${skip}(input,sp,ctx)
11380
11433
  `}ctx._fc=false
11381
- const sv=${sep}(input,sp,ctx)
11434
+ ${sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp) ? "LEAD.at=cur\n" : ""}const sv=${sep}(input,sp,ctx)
11382
11435
  if(sv===FAIL){
11383
11436
  ${rb}
11384
11437
  if(ctx._fc===true)return FAIL
@@ -12488,6 +12541,12 @@ function assemble(t, prog, cfg) {
12488
12541
  rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
12489
12542
  return cur;
12490
12543
  }
12544
+ function leadingFieldTerm(step, child, input, cur, ctx) {
12545
+ return step((i, p, c) => {
12546
+ LEAD.at = cur;
12547
+ return child(i, p, c);
12548
+ }, input, cur, ctx);
12549
+ }
12491
12550
  function committed3(c) {
12492
12551
  return c._fc === true;
12493
12552
  }
@@ -13125,12 +13184,27 @@ function assemble(t, prog, cfg) {
13125
13184
  };
13126
13185
  }
13127
13186
  case OP_FIELD: {
13128
- const name = k[code[ip + 1]];
13187
+ const { name, bits } = fieldSpec(k[code[ip + 1]]);
13129
13188
  const child = link(code[ip + 2]);
13189
+ if (bits === 0) {
13190
+ return (input, pos, ctx) => {
13191
+ const v = child(input, pos, ctx);
13192
+ if (v === FAIL) return FAIL;
13193
+ ctx._fields?.push({ name, value: v, span: { start: pos, end: EC.e } });
13194
+ return v;
13195
+ };
13196
+ }
13197
+ const leading = (bits & FIELD_LEADING_TRIVIA) !== 0;
13198
+ const trailing = (bits & FIELD_TRAILING_TRIVIA) !== 0;
13130
13199
  return (input, pos, ctx) => {
13200
+ const leadFrom = leading ? LEAD.at : -1;
13201
+ LEAD.at = -1;
13131
13202
  const v = child(input, pos, ctx);
13132
13203
  if (v === FAIL) return FAIL;
13133
- ctx._fields?.push({ name, value: v, span: { start: pos, end: EC.e } });
13204
+ const end = EC.e;
13205
+ const trailEnd = trailing && ctx.trivia !== void 0 ? consumeTrivia(input, end, ctx) : end;
13206
+ ctx._fields?.push(triviaFieldCapture(name, v, input, pos, end, leadFrom, trailEnd));
13207
+ EC.e = trailEnd;
13134
13208
  return v;
13135
13209
  };
13136
13210
  }
@@ -13564,6 +13638,12 @@ function assemble(t, prog, cfg) {
13564
13638
  const kidIp = code[base + i];
13565
13639
  if (code[kidIp] !== OP_ADJ) {
13566
13640
  const kid = link(kidIp);
13641
+ if (leadingTriviaFieldAt(code, k, kidIp)) {
13642
+ return (input, cur, ctx, inherited) => {
13643
+ ctx._sync = sync ?? inherited;
13644
+ return leadingFieldTerm(step, kid, input, cur, ctx);
13645
+ };
13646
+ }
13567
13647
  return (input, cur, ctx, inherited) => {
13568
13648
  ctx._sync = sync ?? inherited;
13569
13649
  return step(kid, input, cur, ctx);
@@ -13641,9 +13721,12 @@ function assemble(t, prog, cfg) {
13641
13721
  };
13642
13722
  }
13643
13723
  let hasAdj = false;
13644
- for (let i = 1; i < n; i++) if (code[code[base + i]] === OP_ADJ) {
13645
- hasAdj = true;
13646
- break;
13724
+ for (let i = 1; i < n; i++) {
13725
+ const kidIp = code[base + i];
13726
+ if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp)) {
13727
+ hasAdj = true;
13728
+ break;
13729
+ }
13647
13730
  }
13648
13731
  if (hasAdj) {
13649
13732
  const first2 = link(code[base]);
@@ -13651,6 +13734,9 @@ function assemble(t, prog, cfg) {
13651
13734
  const kidIp = code[base + i];
13652
13735
  if (code[kidIp] !== OP_ADJ) {
13653
13736
  const kid = link(kidIp);
13737
+ if (leadingTriviaFieldAt(code, k, kidIp)) {
13738
+ return (input, cur, ctx) => leadingFieldTerm(step, kid, input, cur, ctx);
13739
+ }
13654
13740
  return (input, cur, ctx) => step(kid, input, cur, ctx);
13655
13741
  }
13656
13742
  const negated = code[kidIp + 1] === 1;
@@ -14013,7 +14099,7 @@ function assemble(t, prog, cfg) {
14013
14099
  if (n === 2 || n === 3) {
14014
14100
  const a0 = link(code[base]), a1 = link(code[base + 1]);
14015
14101
  const a2 = n === 3 ? link(code[base + 2]) : void 0;
14016
- const predecide = !hostCst && !REC2 && !cfg.probe && !cfg.coverage && !cfg.trackLines;
14102
+ const predecide = !REC2 && !cfg.probe && !cfg.coverage && !cfg.trackLines;
14017
14103
  const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
14018
14104
  const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
14019
14105
  const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
@@ -14236,6 +14322,75 @@ function assemble(t, prog, cfg) {
14236
14322
  );
14237
14323
  };
14238
14324
  const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
14325
+ const pBit = [];
14326
+ const pRec = [];
14327
+ if (!REC2 && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
14328
+ for (let i = 0; i < n; i++) {
14329
+ for (const terminal of largeChoiceLiteralPretest(code, k, code[base + i]) ?? []) {
14330
+ pBit.push(1 << i);
14331
+ pRec.push(scalarFor(terminal));
14332
+ }
14333
+ }
14334
+ }
14335
+ const pn = pBit.length;
14336
+ if (pn !== 0) {
14337
+ return (input, pos, ctx) => {
14338
+ const c = lead(input, pos);
14339
+ const need = markCst(ctx);
14340
+ const mRaw = MRAW;
14341
+ const mTl = MTL;
14342
+ const mLv = MLV;
14343
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
14344
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
14345
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
14346
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
14347
+ if (c < 128) {
14348
+ const bits = mask[c < 0 ? 128 : c];
14349
+ let tested = 0;
14350
+ let hit = 0;
14351
+ for (let i = 0; i < pn; i++) {
14352
+ const b = pBit[i];
14353
+ if ((bits & b) === 0 || (hit & b) !== 0) continue;
14354
+ tested |= b;
14355
+ if (pRec[i](input, pos) >= 0) hit |= b;
14356
+ }
14357
+ return masked(
14358
+ input,
14359
+ pos,
14360
+ ctx,
14361
+ bits & (~tested | hit),
14362
+ need,
14363
+ mRaw,
14364
+ mTl,
14365
+ mLv,
14366
+ mFl,
14367
+ mEr,
14368
+ mLog,
14369
+ mRoot,
14370
+ void 0,
14371
+ 0,
14372
+ pos
14373
+ );
14374
+ }
14375
+ return general(
14376
+ input,
14377
+ pos,
14378
+ ctx,
14379
+ c,
14380
+ need,
14381
+ mRaw,
14382
+ mTl,
14383
+ mLv,
14384
+ mFl,
14385
+ mEr,
14386
+ mLog,
14387
+ mRoot,
14388
+ void 0,
14389
+ 0,
14390
+ pos
14391
+ );
14392
+ };
14393
+ }
14239
14394
  return (input, pos, ctx) => {
14240
14395
  const c = lead(input, pos);
14241
14396
  const need = markCst(ctx);
@@ -14397,6 +14552,7 @@ function assemble(t, prog, cfg) {
14397
14552
  const max = code[ip + 3];
14398
14553
  const sepIp = code[ip + 4];
14399
14554
  const sep = sepIp >= 0 ? link(sepIp) : void 0;
14555
+ const sepLeads = sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp);
14400
14556
  const flags = code[ip + 5];
14401
14557
  const keepSeparators = (flags & 2) !== 0;
14402
14558
  const trailingAllowed = (flags & 1) !== 0;
@@ -14436,6 +14592,7 @@ function assemble(t, prog, cfg) {
14436
14592
  let sp = cur;
14437
14593
  if (hasTrivia) sp = skipTrivia(input, sp, ctx);
14438
14594
  ctx._fc = false;
14595
+ if (sepLeads) LEAD.at = cur;
14439
14596
  const sv = sep(input, sp, ctx);
14440
14597
  if (sv === FAIL) {
14441
14598
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
@@ -14525,6 +14682,7 @@ function assemble(t, prog, cfg) {
14525
14682
  let sp = cur;
14526
14683
  if (hasTrivia) sp = skipTrivia(input, sp, ctx);
14527
14684
  ctx._fc = false;
14685
+ if (sepLeads) LEAD.at = cur;
14528
14686
  const sv = sep(input, sp, ctx);
14529
14687
  if (sv === FAIL) {
14530
14688
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
@@ -14847,20 +15005,9 @@ function assemble(t, prog, cfg) {
14847
15005
  if (child >= 0) scalarFor(child);
14848
15006
  continue;
14849
15007
  }
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
- }
15008
+ const literals = largeChoiceLiteralPretest(code, k, armIp);
15009
+ if (literals !== void 0) for (const terminal of literals) scalarFor(terminal);
15010
+ if (literals !== void 0 && literals.length === 1 && literals[0] === child) continue;
14864
15011
  const sequence6 = leadingScalarSequence(code, armIp);
14865
15012
  if (sequence6 !== void 0 && (sequence6.trivia < 0 || triviaScan[sequence6.trivia] != null)) {
14866
15013
  for (const terminal of sequence6.terminals) scalarFor(terminal);
@@ -14926,7 +15073,9 @@ function assemble(t, prog, cfg) {
14926
15073
  scanTriviaCompact,
14927
15074
  t.lex,
14928
15075
  adjacencyHolds,
14929
- t.lexPrograms
15076
+ t.lexPrograms,
15077
+ LEAD,
15078
+ triviaFieldCapture
14930
15079
  );
14931
15080
  emitReached = new Set(pre.reached);
14932
15081
  }
@@ -15008,7 +15157,9 @@ function assemble(t, prog, cfg) {
15008
15157
  scanTriviaCompact,
15009
15158
  t.lex,
15010
15159
  adjacencyHolds,
15011
- t.lexPrograms
15160
+ t.lexPrograms,
15161
+ LEAD,
15162
+ triviaFieldCapture
15012
15163
  );
15013
15164
  emitReached = em.reached;
15014
15165
  } catch (e) {
@@ -15184,7 +15335,9 @@ var AssemblyCache = class {
15184
15335
  return made;
15185
15336
  }
15186
15337
  };
15187
- function tableRules(source, artifactMetadata = {}) {
15338
+ function tableRules(source, metadataOrEntry = {}) {
15339
+ const entry = typeof metadataOrEntry === "string" ? metadataOrEntry : void 0;
15340
+ const artifactMetadata = typeof metadataOrEntry === "string" ? {} : metadataOrEntry;
15188
15341
  const prog = expandCompact(source);
15189
15342
  const resolved = resolveTable(prog);
15190
15343
  const cache = new AssemblyCache(prog, resolved);
@@ -15192,7 +15345,7 @@ function tableRules(source, artifactMetadata = {}) {
15192
15345
  const skipOf = prog.scanSkipOf;
15193
15346
  let last;
15194
15347
  let selected;
15195
- return stampRuleMap(prog, {
15348
+ const map = stampRuleMap(prog, {
15196
15349
  runRule: (ri, input, pos, ctx) => {
15197
15350
  const a = selected ?? cache.forCtx(ctx);
15198
15351
  selected = void 0;
@@ -15213,6 +15366,9 @@ function tableRules(source, artifactMetadata = {}) {
15213
15366
  return a.scanSkip[skipOf?.[ri] ?? -1];
15214
15367
  }
15215
15368
  }, artifactMetadata, resolved);
15369
+ if (entry === void 0) return map;
15370
+ if (!Object.hasOwn(map, entry)) throw new Error(`tableRules: the program has no rule ${JSON.stringify(entry)}`);
15371
+ return map[entry];
15216
15372
  }
15217
15373
 
15218
15374
  // src/table/emit.ts
@@ -15378,11 +15534,15 @@ function emitTableExpression(prog, opts = {}) {
15378
15534
  const entry = opts.entry === void 0 ? "grammar" : opts.entry;
15379
15535
  const ref2 = opts.runtimeRef ?? "tableRules";
15380
15536
  const fns = opts.fnSources ?? prog.fns.map(() => "() => {}");
15381
- const close = `}${opts.metadataSource === void 0 ? "" : `,${opts.metadataSource}`})`;
15537
+ const meta = opts.metadataSource;
15538
+ if (entry !== null && meta !== void 0) {
15539
+ throw new Error("emitTableExpression: metadataSource is for the rule-map form (entry: null); a single entry carries none");
15540
+ }
15541
+ const tail = entry !== null ? `,${jsString(entry)}` : meta === void 0 ? "" : `,${meta}`;
15382
15542
  return [
15383
15543
  `/* @__PURE__ */ ${ref2}({`,
15384
15544
  ...programFields(prog, fns, opts),
15385
- entry === null ? close : `${close}[${jsString(entry)}]`
15545
+ `}${tail})`
15386
15546
  ].join("\n");
15387
15547
  }
15388
15548
 
@@ -15560,7 +15720,7 @@ function payloadKey(p, d) {
15560
15720
  case "label":
15561
15721
  return `label\0${d.label}`;
15562
15722
  case "field":
15563
- return `field\0${d.name}`;
15723
+ return `field\0${d.name}\0${d.leadingTrivia === true}\0${d.trailingTrivia === true}`;
15564
15724
  case "node":
15565
15725
  return `node\0${d.type ?? ""}\0${d.unwrap === true}\0${d.collapse === true}\0${fnKey(d.buildSrc, d.build)}`;
15566
15726
  case "transform":
@@ -17496,7 +17656,7 @@ ${outerDecls.map((d) => " " + d).join("\n")}
17496
17656
  case "label":
17497
17657
  return `label(${JSON.stringify(def.label)}, ${kid(def.parser)})`;
17498
17658
  case "field":
17499
- return `field(${JSON.stringify(def.name)}, ${kid(def.parser)})`;
17659
+ return `field(${JSON.stringify(def.name)}, ${kid(def.parser)}${fieldOptionsSrc(def)})`;
17500
17660
  case "expect":
17501
17661
  return `expect(${kid(def.parser)}${def.label !== void 0 ? `, ${JSON.stringify(def.label)}` : ""})`;
17502
17662
  case "scanTo":
@@ -17559,9 +17719,13 @@ ${outerDecls.map((d) => " " + d).join("\n")}
17559
17719
  }
17560
17720
  }
17561
17721
  };
17722
+ function fieldOptionsSrc(def) {
17723
+ if (def.leadingTrivia !== true && def.trailingTrivia !== true) return "";
17724
+ return `, { ${[def.leadingTrivia === true ? "leadingTrivia: true" : "", def.trailingTrivia === true ? "trailingTrivia: true" : ""].filter(Boolean).join(", ")} }`;
17725
+ }
17562
17726
 
17563
17727
  // src/version.ts
17564
- var PARSEMAN_VERSION = "0.53.0";
17728
+ var PARSEMAN_VERSION = "0.54.0";
17565
17729
 
17566
17730
  // src/compiler/compile-linkable-table.ts
17567
17731
  function isLocal(rule) {
@@ -20039,7 +20203,7 @@ function coverageEntry(entry, collector, maps, trace) {
20039
20203
  case "leaf":
20040
20204
  return def.cstValue === "source" ? sourceLeaf(build(def.parser), def.fn) : leaf(build(def.parser), def.fn);
20041
20205
  case "field":
20042
- return field(def.name, build(def.parser));
20206
+ return field(def.name, build(def.parser), { leadingTrivia: def.leadingTrivia === true, trailingTrivia: def.trailingTrivia === true });
20043
20207
  case "grammar":
20044
20208
  return parser({
20045
20209
  ...def.triviaParser === void 0 ? def.clearTrivia ? { trivia: null } : {} : { trivia: build(def.triviaParser) },