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/cli/index.js CHANGED
@@ -1418,65 +1418,17 @@ function plainRegexSource(p) {
1418
1418
  const d = p._def;
1419
1419
  return d.tag === "regex" && d.flags === "" ? d.source : null;
1420
1420
  }
1421
- var visitSpec0;
1422
- var visitSpec1;
1423
- var visitSpec2;
1424
- var visitSpec3;
1425
- var visitValue0;
1426
- var visitValue1;
1427
- var visitValue2;
1428
- var visitValue3;
1429
1421
  function commonLabeledTriviaVisitor(spec) {
1430
- if (spec === visitSpec0) return visitValue0;
1431
- if (spec === visitSpec1) return visitValue1;
1432
- if (spec === visitSpec2) return visitValue2;
1433
- if (spec === visitSpec3) return visitValue3;
1434
- const sources = spec.minRepeats <= 1 ? spec.arms.map((arm) => plainRegexSource(arm.parser)) : [];
1435
- const visitor = commonCssTriviaVisitor(sources);
1436
- visitSpec3 = visitSpec2;
1437
- visitValue3 = visitValue2;
1438
- visitSpec2 = visitSpec1;
1439
- visitValue2 = visitValue1;
1440
- visitSpec1 = visitSpec0;
1441
- visitValue1 = visitValue0;
1442
- visitSpec0 = spec;
1443
- visitValue0 = visitor;
1444
- return visitor;
1445
- }
1446
- var armSpec0;
1447
- var armSpec1;
1448
- var armSpec2;
1449
- var armSpec3;
1450
- var armValue0;
1451
- var armValue1;
1452
- var armValue2;
1453
- var armValue3;
1422
+ return commonCssTriviaVisitor(spec.minRepeats <= 1 ? spec.arms.map((arm) => plainRegexSource(arm.parser)) : []);
1423
+ }
1454
1424
  function charArmsFor(spec) {
1455
- if (spec === armSpec0) return armValue0;
1456
- if (spec === armSpec1) return armValue1;
1457
- if (spec === armSpec2) return armValue2;
1458
- if (spec === armSpec3) return armValue3;
1459
- let arms = [];
1460
- if (spec.minRepeats > 1) {
1461
- arms = null;
1462
- } else {
1463
- for (const arm of spec.arms) {
1464
- const c = classifyParser(arm.parser);
1465
- if (!c) {
1466
- arms = null;
1467
- break;
1468
- }
1469
- arms.push(c);
1470
- }
1425
+ if (spec.minRepeats > 1) return null;
1426
+ const arms = [];
1427
+ for (const arm of spec.arms) {
1428
+ const c = classifyParser(arm.parser);
1429
+ if (!c) return null;
1430
+ arms.push(c);
1471
1431
  }
1472
- armSpec3 = armSpec2;
1473
- armValue3 = armValue2;
1474
- armSpec2 = armSpec1;
1475
- armValue2 = armValue1;
1476
- armSpec1 = armSpec0;
1477
- armValue1 = armValue0;
1478
- armSpec0 = spec;
1479
- armValue0 = arms;
1480
1432
  return arms;
1481
1433
  }
1482
1434
  function charTriviaEnd(input, cur, arms) {
@@ -1592,12 +1544,16 @@ function analyzeLabeledTrivia(trivia2) {
1592
1544
  }
1593
1545
  arms.push({ label: peeled.label, kindIndex: 0, parser: peeled.parser });
1594
1546
  }
1595
- const spec = {
1547
+ return cacheLabeledTrivia(trivia2, labeledTriviaSpec(arms, minRepeats));
1548
+ }
1549
+ function labeledTriviaSpec(arms, minRepeats) {
1550
+ return {
1596
1551
  labels: arms.map((a) => a.label),
1597
1552
  arms,
1598
- minRepeats
1553
+ minRepeats,
1554
+ visitor: commonLabeledTriviaVisitor({ arms, minRepeats }),
1555
+ charArms: charArmsFor({ arms, minRepeats })
1599
1556
  };
1600
- return cacheLabeledTrivia(trivia2, spec);
1601
1557
  }
1602
1558
  function matchArmAt(input, pos, arm, state) {
1603
1559
  if (!startsFirstSet(arm, input, pos)) return null;
@@ -1627,7 +1583,7 @@ function scanLabeledTriviaChunks(input, cur, spec, state) {
1627
1583
  return { end: pos, chunks };
1628
1584
  }
1629
1585
  function scanLabeledTriviaEnd(input, cur, spec, state) {
1630
- const chars = charArmsFor(spec);
1586
+ const chars = spec.charArms;
1631
1587
  if (chars !== null) return charTriviaEnd(input, cur, chars);
1632
1588
  let pos = cur;
1633
1589
  let count = 0;
@@ -1645,9 +1601,9 @@ function scanLabeledTriviaEnd(input, cur, spec, state) {
1645
1601
  }
1646
1602
  function visitLabeledTrivia(input, cur, spec, state, visit) {
1647
1603
  if (spec.minRepeats > 1) return void 0;
1648
- const common = commonLabeledTriviaVisitor(spec);
1604
+ const common = spec.visitor;
1649
1605
  if (common !== null) return common(input, cur, visit);
1650
- const chars = charArmsFor(spec);
1606
+ const chars = spec.charArms;
1651
1607
  if (chars !== null) return charTriviaVisit(input, cur, chars, visit);
1652
1608
  let pos = cur;
1653
1609
  let count = 0;
@@ -1714,7 +1670,7 @@ function resolveAdjacencyKindMask(trivia2, kinds) {
1714
1670
  return mask;
1715
1671
  }
1716
1672
  function triviaKindMaskAt(input, pos, spec, state) {
1717
- const chars = charArmsFor(spec);
1673
+ const chars = spec.charArms;
1718
1674
  if (chars !== null) return charTriviaKindMask(input, pos, chars);
1719
1675
  let cur = pos;
1720
1676
  let mask = 0;
@@ -4473,7 +4429,7 @@ function buildFieldMap(captures) {
4473
4429
  if (!captures?.length) return void 0;
4474
4430
  const out = {};
4475
4431
  for (const cap of captures) {
4476
- const entry = { value: cap.value, span: cap.span };
4432
+ const entry = cap.leading === void 0 ? { value: cap.value, span: cap.span } : { value: cap.value, span: cap.span, leading: cap.leading, trailing: cap.trailing };
4477
4433
  const current = out[cap.name];
4478
4434
  if (current === void 0) out[cap.name] = entry;
4479
4435
  else if (Array.isArray(current)) current.push(entry);
@@ -4482,6 +4438,23 @@ function buildFieldMap(captures) {
4482
4438
  return out;
4483
4439
  }
4484
4440
 
4441
+ // src/combinators/field-trivia.ts
4442
+ var LEAD = { at: -1 };
4443
+ var FIELD_LEADING_TRIVIA = 1;
4444
+ var FIELD_TRAILING_TRIVIA = 2;
4445
+ function triviaFieldCapture(name, value, input, start, end, leadFrom, trailEnd) {
4446
+ return {
4447
+ name,
4448
+ value,
4449
+ span: { start, end },
4450
+ leading: leadFrom >= 0 && leadFrom < start ? input.slice(leadFrom, start) : "",
4451
+ trailing: trailEnd > end ? input.slice(end, trailEnd) : ""
4452
+ };
4453
+ }
4454
+ function leadsTrivia(p) {
4455
+ return p._def.tag === "field" && p._def.leadingTrivia === true;
4456
+ }
4457
+
4485
4458
  // src/table/ops.ts
4486
4459
  var OP_LIT = 1;
4487
4460
  var OP_RX = 2;
@@ -5391,6 +5364,7 @@ function unwrapSeparator(separator) {
5391
5364
  }
5392
5365
  function sepBy(combinator, separatorArg, opts = {}) {
5393
5366
  const { sep: separator, keep: keepSeparators } = unwrapSeparator(separatorArg);
5367
+ const separatorLeads = leadsTrivia(separator);
5394
5368
  const { min, max } = resolveBounds("sepBy()", opts);
5395
5369
  const trailing = opts.trailing ?? "forbid";
5396
5370
  const meta = {
@@ -5455,7 +5429,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
5455
5429
  // this option surface already; parity is held by test/parity, not by hope.
5456
5430
  ...keepSeparators ? { keepSeparators: true } : {}
5457
5431
  },
5458
- _parseScalar: keepSeparators ? void 0 : parseScalar,
5432
+ _parseScalar: keepSeparators || separatorLeads ? void 0 : parseScalar,
5459
5433
  parse(input, pos, ctx) {
5460
5434
  const first = combinator.parse(input, pos, ctx);
5461
5435
  const values = [];
@@ -5487,6 +5461,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
5487
5461
  sepPos = advanceTrivia(input, cur, ctx);
5488
5462
  }
5489
5463
  }
5464
+ if (separatorLeads) LEAD.at = cur;
5490
5465
  const sep = separator.parse(input, sepPos, ctx);
5491
5466
  if (!sep.ok) {
5492
5467
  rollbackTrivia(ctx, loopMark);
@@ -5638,16 +5613,41 @@ function label(name, combinator) {
5638
5613
  }
5639
5614
  };
5640
5615
  }
5641
- function field(name, combinator) {
5616
+ function field(name, combinator, opts) {
5617
+ const leadingTrivia = opts?.leadingTrivia === true;
5618
+ const trailingTrivia = opts?.trailingTrivia === true;
5619
+ if (!leadingTrivia && !trailingTrivia) {
5620
+ return {
5621
+ _tag: combinator._tag,
5622
+ _meta: combinator._meta,
5623
+ _def: { tag: "field", name, parser: combinator },
5624
+ parse(input, pos, ctx) {
5625
+ const result = combinator.parse(input, pos, ctx);
5626
+ if (!result.ok) return result;
5627
+ ctx._fields?.push({ name, value: result.value, span: result.span });
5628
+ return result;
5629
+ }
5630
+ };
5631
+ }
5642
5632
  return {
5643
5633
  _tag: combinator._tag,
5644
5634
  _meta: combinator._meta,
5645
- _def: { tag: "field", name, parser: combinator },
5635
+ _def: {
5636
+ tag: "field",
5637
+ name,
5638
+ parser: combinator,
5639
+ ...leadingTrivia ? { leadingTrivia: true } : {},
5640
+ ...trailingTrivia ? { trailingTrivia: true } : {}
5641
+ },
5646
5642
  parse(input, pos, ctx) {
5643
+ const leadFrom = LEAD.at;
5644
+ LEAD.at = -1;
5647
5645
  const result = combinator.parse(input, pos, ctx);
5648
5646
  if (!result.ok) return result;
5649
- ctx._fields?.push({ name, value: result.value, span: result.span });
5650
- return result;
5647
+ const end = result.span.end;
5648
+ const trailEnd = trailingTrivia && ctx.trivia ? consumeTrivia(input, end, ctx) : end;
5649
+ ctx._fields?.push(triviaFieldCapture(name, result.value, input, result.span.start, end, leadingTrivia ? leadFrom : -1, trailEnd));
5650
+ return trailEnd === end ? result : { ok: true, value: result.value, span: { start: result.span.start, end: trailEnd } };
5651
5651
  }
5652
5652
  };
5653
5653
  }
@@ -6460,6 +6460,16 @@ var Encoder = class {
6460
6460
  this.kIndex.set(key, i);
6461
6461
  return i;
6462
6462
  }
6463
+ fieldSpecIndex = /* @__PURE__ */ new Map();
6464
+ fieldSpecSlot(name, bits) {
6465
+ const key = JSON.stringify([name, bits]);
6466
+ const hit = this.fieldSpecIndex.get(key);
6467
+ if (hit !== void 0) return hit;
6468
+ const i = this.k.length;
6469
+ this.k.push([name, bits]);
6470
+ this.fieldSpecIndex.set(key, i);
6471
+ return i;
6472
+ }
6463
6473
  /**
6464
6474
  * A `notAdjacent({ kinds })` filter, pooled by its CONTENTS.
6465
6475
  *
@@ -7080,8 +7090,10 @@ var Encoder = class {
7080
7090
  for (let i = 0; i < arms.length; i++) this.code[head + 6 + i] = arms[i];
7081
7091
  return head;
7082
7092
  }
7083
- case "field":
7084
- return this.emit(OP_FIELD, this.constant(d.name), this.node(d.parser).ip);
7093
+ case "field": {
7094
+ const bits = (d.leadingTrivia === true ? FIELD_LEADING_TRIVIA : 0) | (d.trailingTrivia === true ? FIELD_TRAILING_TRIVIA : 0);
7095
+ return this.emit(OP_FIELD, bits === 0 ? this.constant(d.name) : this.fieldSpecSlot(d.name, bits), this.node(d.parser).ip);
7096
+ }
7085
7097
  case "lazy": {
7086
7098
  const refName = p._ruleName;
7087
7099
  const winner = refName === void 0 ? void 0 : this.winners?.[refName];
@@ -8754,6 +8766,26 @@ function leadingLiteralFamily(code, constants, ip, minDepth = 2, limit = 4) {
8754
8766
  };
8755
8767
  return walk(ip, 0);
8756
8768
  }
8769
+ function largeChoiceLiteralPretest(code, constants, armIp) {
8770
+ const child = leadingScalarTerminal(code, armIp, 2, true, true);
8771
+ if (child >= 0) {
8772
+ const spec = constants[code[child + 1]];
8773
+ if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) return [child];
8774
+ }
8775
+ const family = leadingLiteralFamily(code, constants, armIp);
8776
+ return family !== void 0 && family.length >= 2 && family.every((terminal) => {
8777
+ const value = constants[code[terminal + 1]];
8778
+ return typeof value === "string" && value.length >= 2;
8779
+ }) ? family : void 0;
8780
+ }
8781
+
8782
+ // src/table/field-spec.ts
8783
+ function fieldSpec(slot) {
8784
+ return Array.isArray(slot) ? { name: slot[0], bits: slot[1] } : { name: slot, bits: 0 };
8785
+ }
8786
+ function leadingTriviaFieldAt(code, k, ip) {
8787
+ return code[ip] === OP_FIELD && (fieldSpec(k[code[ip + 1]]).bits & FIELD_LEADING_TRIVIA) !== 0;
8788
+ }
8757
8789
 
8758
8790
  // src/table/emit-assembly.ts
8759
8791
  var Unemittable = class extends Error {
@@ -8828,7 +8860,11 @@ var EMITTED_PARAMS = [
8828
8860
  // Appended for old precompiled-factory ABI: old factories ignore it.
8829
8861
  "adjacencyHolds",
8830
8862
  // Appended for selected composite lexical programs; old factories ignore it.
8831
- "LEXPROG"
8863
+ "LEXPROG",
8864
+ // Appended for trivia-attributing fields (`field(…, { leadingTrivia })`);
8865
+ // old factories ignore them.
8866
+ "LEAD",
8867
+ "triviaFieldCapture"
8832
8868
  ];
8833
8869
  var RUNTIME_PRELUDE = `
8834
8870
  let _pfScan=null
@@ -9088,20 +9124,12 @@ function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false) {
9088
9124
  if (child >= 0) scalarSpecs.add(code[child + 1]);
9089
9125
  continue;
9090
9126
  }
9091
- if (child >= 0) {
9092
- const spec = k[code[child + 1]];
9093
- if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
9094
- largeChoiceScalarSpecs.add(code[child + 1]);
9095
- continue;
9096
- }
9097
- }
9098
- const family = leadingLiteralFamily(code, k, armIp);
9099
- if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
9100
- const value = k[code[terminal + 1]];
9101
- return typeof value === "string" && value.length >= 2;
9102
- })) {
9103
- largeChoiceLiteralFamilies.set(armIp, family);
9127
+ const literals = largeChoiceLiteralPretest(code, k, armIp);
9128
+ if (literals !== void 0 && literals.length === 1 && literals[0] === child) {
9129
+ largeChoiceScalarSpecs.add(code[child + 1]);
9130
+ continue;
9104
9131
  }
9132
+ if (literals !== void 0) largeChoiceLiteralFamilies.set(armIp, literals);
9105
9133
  const sequence6 = leadingScalarSequence(code, armIp);
9106
9134
  if (sequence6 !== void 0 && (sequence6.trivia < 0 || swapLegal && t2.triviaScan[sequence6.trivia] != null)) {
9107
9135
  largeChoiceScalarSequences.set(armIp, sequence6);
@@ -9525,14 +9553,31 @@ return v
9525
9553
  }`;
9526
9554
  }
9527
9555
  case OP_FIELD: {
9528
- const name = q(k[code[ip + 1]]);
9556
+ const spec = fieldSpec(k[code[ip + 1]]);
9557
+ const name = q(spec.name);
9529
9558
  const child = link(code[ip + 2]);
9530
- return `${head}
9559
+ if (spec.bits === 0) {
9560
+ return `${head}
9531
9561
  const v=${child}(input,pos,ctx)
9532
9562
  if(v===FAIL)return FAIL
9533
9563
  const f=ctx._fields
9534
9564
  if(f!==undefined)f.push({name:${name},value:v,span:{start:pos,end:EC.e}})
9535
9565
  return v
9566
+ }`;
9567
+ }
9568
+ const leading = (spec.bits & FIELD_LEADING_TRIVIA) !== 0;
9569
+ const trailing = (spec.bits & FIELD_TRAILING_TRIVIA) !== 0;
9570
+ return `${head}
9571
+ const lf=${leading ? "LEAD.at" : "-1"}
9572
+ LEAD.at=-1
9573
+ const v=${child}(input,pos,ctx)
9574
+ if(v===FAIL)return FAIL
9575
+ const e=EC.e
9576
+ const te=${trailing ? "ctx.trivia!==undefined?consumeTrivia(input,e,ctx):e" : "e"}
9577
+ const f=ctx._fields
9578
+ if(f!==undefined)f.push(triviaFieldCapture(${name},v,input,pos,e,lf,te))
9579
+ EC.e=te
9580
+ return v
9536
9581
  }`;
9537
9582
  }
9538
9583
  case OP_EXPECT: {
@@ -9828,7 +9873,10 @@ return v
9828
9873
  `if(!adjacencyHolds(input,cur,ctx,${negated ? "true" : "false"},${kinds})){ctx._fe=cur;ctx._fx=${expected};return FAIL}`,
9829
9874
  `${vn}=null`
9830
9875
  );
9831
- } else parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
9876
+ } else {
9877
+ const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
9878
+ parts.push(emitTerm(callee, vn, tmp(), L, skipFor(L)));
9879
+ }
9832
9880
  names.push(vn);
9833
9881
  }
9834
9882
  parts.push("EC.e=cur");
@@ -10228,7 +10276,7 @@ let sp=cur
10228
10276
  ${hasTrivia === "false" ? "" : hasTrivia === "true" ? `sp=${skip}(input,sp,ctx)
10229
10277
  ` : `if(hasTrivia)sp=${skip}(input,sp,ctx)
10230
10278
  `}ctx._fc=false
10231
- const sv=${sep}(input,sp,ctx)
10279
+ ${sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp) ? "LEAD.at=cur\n" : ""}const sv=${sep}(input,sp,ctx)
10232
10280
  if(sv===FAIL){
10233
10281
  ${rb}
10234
10282
  if(ctx._fc===true)return FAIL
@@ -10610,6 +10658,10 @@ function sequence(...parsers) {
10610
10658
  (adjacency ??= Array.from({ length: parsers.length }, () => null))[i] = a;
10611
10659
  }
10612
10660
  const hasAdjacency = adjacency !== null;
10661
+ let leading = null;
10662
+ for (let i = 1; i < parsers.length; i++) {
10663
+ if (leadsTrivia(parsers[i])) (leading ??= Array.from({ length: parsers.length }, () => false))[i] = true;
10664
+ }
10613
10665
  const strictArity = !hasAdjacency && (parsers.length === 2 && !matchesEmpty(parsers[1]) || parsers.length === 3 && parsers.every((p) => !matchesEmpty(p))) ? parsers.length : 0;
10614
10666
  const meta = {
10615
10667
  // Union through the nullable prefix — a leading optional()/many() lets a later
@@ -10657,7 +10709,7 @@ function sequence(...parsers) {
10657
10709
  _tag: "sequence",
10658
10710
  _meta: meta,
10659
10711
  _def: def,
10660
- _parseScalar: hasAdjacency ? void 0 : parseScalar,
10712
+ _parseScalar: hasAdjacency || leading !== null ? void 0 : parseScalar,
10661
10713
  parse(input, pos, ctx) {
10662
10714
  const tolerant = ctx._tolerant === true;
10663
10715
  if (tolerant) {
@@ -10691,6 +10743,7 @@ function sequence(...parsers) {
10691
10743
  const scanTlog = deferredTrivia ? cstTlLen(ctx) : 0;
10692
10744
  const scanLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
10693
10745
  const scanRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
10746
+ if (leading?.[i] === true) LEAD.at = cur;
10694
10747
  const result = parsers[i].parse(input, termPos, ctx);
10695
10748
  if (!result.ok) return result;
10696
10749
  if (values !== void 0) values.push(result.value);
@@ -11725,6 +11778,12 @@ function assemble(t2, prog, cfg) {
11725
11778
  rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
11726
11779
  return cur;
11727
11780
  }
11781
+ function leadingFieldTerm(step, child, input, cur, ctx) {
11782
+ return step((i, p, c) => {
11783
+ LEAD.at = cur;
11784
+ return child(i, p, c);
11785
+ }, input, cur, ctx);
11786
+ }
11728
11787
  function committed3(c) {
11729
11788
  return c._fc === true;
11730
11789
  }
@@ -12362,12 +12421,27 @@ function assemble(t2, prog, cfg) {
12362
12421
  };
12363
12422
  }
12364
12423
  case OP_FIELD: {
12365
- const name = k[code[ip + 1]];
12424
+ const { name, bits } = fieldSpec(k[code[ip + 1]]);
12366
12425
  const child = link(code[ip + 2]);
12426
+ if (bits === 0) {
12427
+ return (input, pos, ctx) => {
12428
+ const v = child(input, pos, ctx);
12429
+ if (v === FAIL) return FAIL;
12430
+ ctx._fields?.push({ name, value: v, span: { start: pos, end: EC.e } });
12431
+ return v;
12432
+ };
12433
+ }
12434
+ const leading = (bits & FIELD_LEADING_TRIVIA) !== 0;
12435
+ const trailing = (bits & FIELD_TRAILING_TRIVIA) !== 0;
12367
12436
  return (input, pos, ctx) => {
12437
+ const leadFrom = leading ? LEAD.at : -1;
12438
+ LEAD.at = -1;
12368
12439
  const v = child(input, pos, ctx);
12369
12440
  if (v === FAIL) return FAIL;
12370
- ctx._fields?.push({ name, value: v, span: { start: pos, end: EC.e } });
12441
+ const end = EC.e;
12442
+ const trailEnd = trailing && ctx.trivia !== void 0 ? consumeTrivia(input, end, ctx) : end;
12443
+ ctx._fields?.push(triviaFieldCapture(name, v, input, pos, end, leadFrom, trailEnd));
12444
+ EC.e = trailEnd;
12371
12445
  return v;
12372
12446
  };
12373
12447
  }
@@ -12801,6 +12875,12 @@ function assemble(t2, prog, cfg) {
12801
12875
  const kidIp = code[base + i];
12802
12876
  if (code[kidIp] !== OP_ADJ) {
12803
12877
  const kid = link(kidIp);
12878
+ if (leadingTriviaFieldAt(code, k, kidIp)) {
12879
+ return (input, cur, ctx, inherited) => {
12880
+ ctx._sync = sync ?? inherited;
12881
+ return leadingFieldTerm(step, kid, input, cur, ctx);
12882
+ };
12883
+ }
12804
12884
  return (input, cur, ctx, inherited) => {
12805
12885
  ctx._sync = sync ?? inherited;
12806
12886
  return step(kid, input, cur, ctx);
@@ -12878,9 +12958,12 @@ function assemble(t2, prog, cfg) {
12878
12958
  };
12879
12959
  }
12880
12960
  let hasAdj = false;
12881
- for (let i = 1; i < n; i++) if (code[code[base + i]] === OP_ADJ) {
12882
- hasAdj = true;
12883
- break;
12961
+ for (let i = 1; i < n; i++) {
12962
+ const kidIp = code[base + i];
12963
+ if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp)) {
12964
+ hasAdj = true;
12965
+ break;
12966
+ }
12884
12967
  }
12885
12968
  if (hasAdj) {
12886
12969
  const first2 = link(code[base]);
@@ -12888,6 +12971,9 @@ function assemble(t2, prog, cfg) {
12888
12971
  const kidIp = code[base + i];
12889
12972
  if (code[kidIp] !== OP_ADJ) {
12890
12973
  const kid = link(kidIp);
12974
+ if (leadingTriviaFieldAt(code, k, kidIp)) {
12975
+ return (input, cur, ctx) => leadingFieldTerm(step, kid, input, cur, ctx);
12976
+ }
12891
12977
  return (input, cur, ctx) => step(kid, input, cur, ctx);
12892
12978
  }
12893
12979
  const negated = code[kidIp + 1] === 1;
@@ -13250,7 +13336,7 @@ function assemble(t2, prog, cfg) {
13250
13336
  if (n === 2 || n === 3) {
13251
13337
  const a0 = link(code[base]), a1 = link(code[base + 1]);
13252
13338
  const a2 = n === 3 ? link(code[base + 2]) : void 0;
13253
- const predecide = !hostCst && !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
13339
+ const predecide = !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
13254
13340
  const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
13255
13341
  const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
13256
13342
  const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
@@ -13473,6 +13559,75 @@ function assemble(t2, prog, cfg) {
13473
13559
  );
13474
13560
  };
13475
13561
  const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
13562
+ const pBit = [];
13563
+ const pRec = [];
13564
+ if (!REC && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
13565
+ for (let i = 0; i < n; i++) {
13566
+ for (const terminal of largeChoiceLiteralPretest(code, k, code[base + i]) ?? []) {
13567
+ pBit.push(1 << i);
13568
+ pRec.push(scalarFor(terminal));
13569
+ }
13570
+ }
13571
+ }
13572
+ const pn = pBit.length;
13573
+ if (pn !== 0) {
13574
+ return (input, pos, ctx) => {
13575
+ const c = lead(input, pos);
13576
+ const need = markCst(ctx);
13577
+ const mRaw = MRAW;
13578
+ const mTl = MTL;
13579
+ const mLv = MLV;
13580
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
13581
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
13582
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
13583
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
13584
+ if (c < 128) {
13585
+ const bits = mask[c < 0 ? 128 : c];
13586
+ let tested = 0;
13587
+ let hit = 0;
13588
+ for (let i = 0; i < pn; i++) {
13589
+ const b = pBit[i];
13590
+ if ((bits & b) === 0 || (hit & b) !== 0) continue;
13591
+ tested |= b;
13592
+ if (pRec[i](input, pos) >= 0) hit |= b;
13593
+ }
13594
+ return masked(
13595
+ input,
13596
+ pos,
13597
+ ctx,
13598
+ bits & (~tested | hit),
13599
+ need,
13600
+ mRaw,
13601
+ mTl,
13602
+ mLv,
13603
+ mFl,
13604
+ mEr,
13605
+ mLog,
13606
+ mRoot,
13607
+ void 0,
13608
+ 0,
13609
+ pos
13610
+ );
13611
+ }
13612
+ return general(
13613
+ input,
13614
+ pos,
13615
+ ctx,
13616
+ c,
13617
+ need,
13618
+ mRaw,
13619
+ mTl,
13620
+ mLv,
13621
+ mFl,
13622
+ mEr,
13623
+ mLog,
13624
+ mRoot,
13625
+ void 0,
13626
+ 0,
13627
+ pos
13628
+ );
13629
+ };
13630
+ }
13476
13631
  return (input, pos, ctx) => {
13477
13632
  const c = lead(input, pos);
13478
13633
  const need = markCst(ctx);
@@ -13634,6 +13789,7 @@ function assemble(t2, prog, cfg) {
13634
13789
  const max = code[ip + 3];
13635
13790
  const sepIp = code[ip + 4];
13636
13791
  const sep = sepIp >= 0 ? link(sepIp) : void 0;
13792
+ const sepLeads = sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp);
13637
13793
  const flags = code[ip + 5];
13638
13794
  const keepSeparators = (flags & 2) !== 0;
13639
13795
  const trailingAllowed = (flags & 1) !== 0;
@@ -13673,6 +13829,7 @@ function assemble(t2, prog, cfg) {
13673
13829
  let sp = cur;
13674
13830
  if (hasTrivia) sp = skipTrivia(input, sp, ctx);
13675
13831
  ctx._fc = false;
13832
+ if (sepLeads) LEAD.at = cur;
13676
13833
  const sv = sep(input, sp, ctx);
13677
13834
  if (sv === FAIL) {
13678
13835
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
@@ -13762,6 +13919,7 @@ function assemble(t2, prog, cfg) {
13762
13919
  let sp = cur;
13763
13920
  if (hasTrivia) sp = skipTrivia(input, sp, ctx);
13764
13921
  ctx._fc = false;
13922
+ if (sepLeads) LEAD.at = cur;
13765
13923
  const sv = sep(input, sp, ctx);
13766
13924
  if (sv === FAIL) {
13767
13925
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
@@ -14084,20 +14242,9 @@ function assemble(t2, prog, cfg) {
14084
14242
  if (child >= 0) scalarFor(child);
14085
14243
  continue;
14086
14244
  }
14087
- if (child >= 0) {
14088
- const spec = k[code[child + 1]];
14089
- if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
14090
- scalarFor(child);
14091
- continue;
14092
- }
14093
- }
14094
- const family = leadingLiteralFamily(code, k, armIp);
14095
- if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
14096
- const value = k[code[terminal + 1]];
14097
- return typeof value === "string" && value.length >= 2;
14098
- })) {
14099
- for (const terminal of family) scalarFor(terminal);
14100
- }
14245
+ const literals = largeChoiceLiteralPretest(code, k, armIp);
14246
+ if (literals !== void 0) for (const terminal of literals) scalarFor(terminal);
14247
+ if (literals !== void 0 && literals.length === 1 && literals[0] === child) continue;
14101
14248
  const sequence6 = leadingScalarSequence(code, armIp);
14102
14249
  if (sequence6 !== void 0 && (sequence6.trivia < 0 || triviaScan[sequence6.trivia] != null)) {
14103
14250
  for (const terminal of sequence6.terminals) scalarFor(terminal);
@@ -14163,7 +14310,9 @@ function assemble(t2, prog, cfg) {
14163
14310
  scanTriviaCompact,
14164
14311
  t2.lex,
14165
14312
  adjacencyHolds,
14166
- t2.lexPrograms
14313
+ t2.lexPrograms,
14314
+ LEAD,
14315
+ triviaFieldCapture
14167
14316
  );
14168
14317
  emitReached = new Set(pre.reached);
14169
14318
  }
@@ -14245,7 +14394,9 @@ function assemble(t2, prog, cfg) {
14245
14394
  scanTriviaCompact,
14246
14395
  t2.lex,
14247
14396
  adjacencyHolds,
14248
- t2.lexPrograms
14397
+ t2.lexPrograms,
14398
+ LEAD,
14399
+ triviaFieldCapture
14249
14400
  );
14250
14401
  emitReached = em.reached;
14251
14402
  } catch (e) {
@@ -14421,7 +14572,9 @@ var AssemblyCache = class {
14421
14572
  return made;
14422
14573
  }
14423
14574
  };
14424
- function tableRules(source, artifactMetadata = {}) {
14575
+ function tableRules(source, metadataOrEntry = {}) {
14576
+ const entry = typeof metadataOrEntry === "string" ? metadataOrEntry : void 0;
14577
+ const artifactMetadata = typeof metadataOrEntry === "string" ? {} : metadataOrEntry;
14425
14578
  const prog = expandCompact(source);
14426
14579
  const resolved = resolveTable(prog);
14427
14580
  const cache = new AssemblyCache(prog, resolved);
@@ -14429,7 +14582,7 @@ function tableRules(source, artifactMetadata = {}) {
14429
14582
  const skipOf = prog.scanSkipOf;
14430
14583
  let last;
14431
14584
  let selected;
14432
- return stampRuleMap(prog, {
14585
+ const map = stampRuleMap(prog, {
14433
14586
  runRule: (ri, input, pos, ctx) => {
14434
14587
  const a = selected ?? cache.forCtx(ctx);
14435
14588
  selected = void 0;
@@ -14450,6 +14603,9 @@ function tableRules(source, artifactMetadata = {}) {
14450
14603
  return a.scanSkip[skipOf?.[ri] ?? -1];
14451
14604
  }
14452
14605
  }, artifactMetadata, resolved);
14606
+ if (entry === void 0) return map;
14607
+ if (!Object.hasOwn(map, entry)) throw new Error(`tableRules: the program has no rule ${JSON.stringify(entry)}`);
14608
+ return map[entry];
14453
14609
  }
14454
14610
 
14455
14611
  // src/table/emit.ts
@@ -14604,11 +14760,15 @@ function emitTableExpression(prog, opts = {}) {
14604
14760
  const entry = opts.entry === void 0 ? "grammar" : opts.entry;
14605
14761
  const ref2 = opts.runtimeRef ?? "tableRules";
14606
14762
  const fns = opts.fnSources ?? prog.fns.map(() => "() => {}");
14607
- const close = `}${opts.metadataSource === void 0 ? "" : `,${opts.metadataSource}`})`;
14763
+ const meta = opts.metadataSource;
14764
+ if (entry !== null && meta !== void 0) {
14765
+ throw new Error("emitTableExpression: metadataSource is for the rule-map form (entry: null); a single entry carries none");
14766
+ }
14767
+ const tail = entry !== null ? `,${jsString(entry)}` : meta === void 0 ? "" : `,${meta}`;
14608
14768
  return [
14609
14769
  `/* @__PURE__ */ ${ref2}({`,
14610
14770
  ...programFields(prog, fns, opts),
14611
- entry === null ? close : `${close}[${jsString(entry)}]`
14771
+ `}${tail})`
14612
14772
  ].join("\n");
14613
14773
  }
14614
14774
 
@@ -14786,7 +14946,7 @@ function payloadKey(p, d) {
14786
14946
  case "label":
14787
14947
  return `label\0${d.label}`;
14788
14948
  case "field":
14789
- return `field\0${d.name}`;
14949
+ return `field\0${d.name}\0${d.leadingTrivia === true}\0${d.trailingTrivia === true}`;
14790
14950
  case "node":
14791
14951
  return `node\0${d.type ?? ""}\0${d.unwrap === true}\0${d.collapse === true}\0${fnKey(d.buildSrc, d.build)}`;
14792
14952
  case "transform":
@@ -17823,7 +17983,7 @@ function rebuildCombinator(root, replacements) {
17823
17983
  out = label(d.label, one(d.parser));
17824
17984
  break;
17825
17985
  case "field":
17826
- out = field(d.name, one(d.parser));
17986
+ out = field(d.name, one(d.parser), { leadingTrivia: d.leadingTrivia === true, trailingTrivia: d.trailingTrivia === true });
17827
17987
  break;
17828
17988
  case "token":
17829
17989
  out = token(one(d.parser));