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/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];
@@ -7113,6 +7125,9 @@ var Encoder = class {
7113
7125
  this.expected([adjacencyExpected(d)])
7114
7126
  );
7115
7127
  case "withCtx": {
7128
+ if (typeof d.extra === "function") {
7129
+ return this.emit(OP_WITHCTX, ~this.fn(d.extra, d.extraSrc ?? null), this.node(d.parser).ip);
7130
+ }
7116
7131
  if (!emittableConst(d.extra)) {
7117
7132
  this.runtimeOnly.add("withCtx(extra) \u2014 the state object is not serialisable");
7118
7133
  }
@@ -8754,6 +8769,26 @@ function leadingLiteralFamily(code, constants, ip, minDepth = 2, limit = 4) {
8754
8769
  };
8755
8770
  return walk(ip, 0);
8756
8771
  }
8772
+ function largeChoiceLiteralPretest(code, constants, armIp) {
8773
+ const child = leadingScalarTerminal(code, armIp, 2, true, true);
8774
+ if (child >= 0) {
8775
+ const spec = constants[code[child + 1]];
8776
+ if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) return [child];
8777
+ }
8778
+ const family = leadingLiteralFamily(code, constants, armIp);
8779
+ return family !== void 0 && family.length >= 2 && family.every((terminal) => {
8780
+ const value = constants[code[terminal + 1]];
8781
+ return typeof value === "string" && value.length >= 2;
8782
+ }) ? family : void 0;
8783
+ }
8784
+
8785
+ // src/table/field-spec.ts
8786
+ function fieldSpec(slot) {
8787
+ return Array.isArray(slot) ? { name: slot[0], bits: slot[1] } : { name: slot, bits: 0 };
8788
+ }
8789
+ function leadingTriviaFieldAt(code, k, ip) {
8790
+ return code[ip] === OP_FIELD && (fieldSpec(k[code[ip + 1]]).bits & FIELD_LEADING_TRIVIA) !== 0;
8791
+ }
8757
8792
 
8758
8793
  // src/table/emit-assembly.ts
8759
8794
  var Unemittable = class extends Error {
@@ -8828,7 +8863,11 @@ var EMITTED_PARAMS = [
8828
8863
  // Appended for old precompiled-factory ABI: old factories ignore it.
8829
8864
  "adjacencyHolds",
8830
8865
  // Appended for selected composite lexical programs; old factories ignore it.
8831
- "LEXPROG"
8866
+ "LEXPROG",
8867
+ // Appended for trivia-attributing fields (`field(…, { leadingTrivia })`);
8868
+ // old factories ignore them.
8869
+ "LEAD",
8870
+ "triviaFieldCapture"
8832
8871
  ];
8833
8872
  var RUNTIME_PRELUDE = `
8834
8873
  let _pfScan=null
@@ -9088,20 +9127,12 @@ function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false) {
9088
9127
  if (child >= 0) scalarSpecs.add(code[child + 1]);
9089
9128
  continue;
9090
9129
  }
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);
9130
+ const literals = largeChoiceLiteralPretest(code, k, armIp);
9131
+ if (literals !== void 0 && literals.length === 1 && literals[0] === child) {
9132
+ largeChoiceScalarSpecs.add(code[child + 1]);
9133
+ continue;
9104
9134
  }
9135
+ if (literals !== void 0) largeChoiceLiteralFamilies.set(armIp, literals);
9105
9136
  const sequence6 = leadingScalarSequence(code, armIp);
9106
9137
  if (sequence6 !== void 0 && (sequence6.trivia < 0 || swapLegal && t2.triviaScan[sequence6.trivia] != null)) {
9107
9138
  largeChoiceScalarSequences.set(armIp, sequence6);
@@ -9525,14 +9556,31 @@ return v
9525
9556
  }`;
9526
9557
  }
9527
9558
  case OP_FIELD: {
9528
- const name = q(k[code[ip + 1]]);
9559
+ const spec = fieldSpec(k[code[ip + 1]]);
9560
+ const name = q(spec.name);
9529
9561
  const child = link(code[ip + 2]);
9530
- return `${head}
9562
+ if (spec.bits === 0) {
9563
+ return `${head}
9531
9564
  const v=${child}(input,pos,ctx)
9532
9565
  if(v===FAIL)return FAIL
9533
9566
  const f=ctx._fields
9534
9567
  if(f!==undefined)f.push({name:${name},value:v,span:{start:pos,end:EC.e}})
9535
9568
  return v
9569
+ }`;
9570
+ }
9571
+ const leading = (spec.bits & FIELD_LEADING_TRIVIA) !== 0;
9572
+ const trailing = (spec.bits & FIELD_TRAILING_TRIVIA) !== 0;
9573
+ return `${head}
9574
+ const lf=${leading ? "LEAD.at" : "-1"}
9575
+ LEAD.at=-1
9576
+ const v=${child}(input,pos,ctx)
9577
+ if(v===FAIL)return FAIL
9578
+ const e=EC.e
9579
+ const te=${trailing ? "ctx.trivia!==undefined?consumeTrivia(input,e,ctx):e" : "e"}
9580
+ const f=ctx._fields
9581
+ if(f!==undefined)f.push(triviaFieldCapture(${name},v,input,pos,e,lf,te))
9582
+ EC.e=te
9583
+ return v
9536
9584
  }`;
9537
9585
  }
9538
9586
  case OP_EXPECT: {
@@ -9828,7 +9876,10 @@ return v
9828
9876
  `if(!adjacencyHolds(input,cur,ctx,${negated ? "true" : "false"},${kinds})){ctx._fe=cur;ctx._fx=${expected};return FAIL}`,
9829
9877
  `${vn}=null`
9830
9878
  );
9831
- } else parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
9879
+ } else {
9880
+ const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
9881
+ parts.push(emitTerm(callee, vn, tmp(), L, skipFor(L)));
9882
+ }
9832
9883
  names.push(vn);
9833
9884
  }
9834
9885
  parts.push("EC.e=cur");
@@ -10228,7 +10279,7 @@ let sp=cur
10228
10279
  ${hasTrivia === "false" ? "" : hasTrivia === "true" ? `sp=${skip}(input,sp,ctx)
10229
10280
  ` : `if(hasTrivia)sp=${skip}(input,sp,ctx)
10230
10281
  `}ctx._fc=false
10231
- const sv=${sep}(input,sp,ctx)
10282
+ ${sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp) ? "LEAD.at=cur\n" : ""}const sv=${sep}(input,sp,ctx)
10232
10283
  if(sv===FAIL){
10233
10284
  ${rb}
10234
10285
  if(ctx._fc===true)return FAIL
@@ -10610,6 +10661,10 @@ function sequence(...parsers) {
10610
10661
  (adjacency ??= Array.from({ length: parsers.length }, () => null))[i] = a;
10611
10662
  }
10612
10663
  const hasAdjacency = adjacency !== null;
10664
+ let leading = null;
10665
+ for (let i = 1; i < parsers.length; i++) {
10666
+ if (leadsTrivia(parsers[i])) (leading ??= Array.from({ length: parsers.length }, () => false))[i] = true;
10667
+ }
10613
10668
  const strictArity = !hasAdjacency && (parsers.length === 2 && !matchesEmpty(parsers[1]) || parsers.length === 3 && parsers.every((p) => !matchesEmpty(p))) ? parsers.length : 0;
10614
10669
  const meta = {
10615
10670
  // Union through the nullable prefix — a leading optional()/many() lets a later
@@ -10657,7 +10712,7 @@ function sequence(...parsers) {
10657
10712
  _tag: "sequence",
10658
10713
  _meta: meta,
10659
10714
  _def: def,
10660
- _parseScalar: hasAdjacency ? void 0 : parseScalar,
10715
+ _parseScalar: hasAdjacency || leading !== null ? void 0 : parseScalar,
10661
10716
  parse(input, pos, ctx) {
10662
10717
  const tolerant = ctx._tolerant === true;
10663
10718
  if (tolerant) {
@@ -10691,6 +10746,7 @@ function sequence(...parsers) {
10691
10746
  const scanTlog = deferredTrivia ? cstTlLen(ctx) : 0;
10692
10747
  const scanLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
10693
10748
  const scanRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
10749
+ if (leading?.[i] === true) LEAD.at = cur;
10694
10750
  const result = parsers[i].parse(input, termPos, ctx);
10695
10751
  if (!result.ok) return result;
10696
10752
  if (values !== void 0) values.push(result.value);
@@ -11725,6 +11781,12 @@ function assemble(t2, prog, cfg) {
11725
11781
  rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
11726
11782
  return cur;
11727
11783
  }
11784
+ function leadingFieldTerm(step, child, input, cur, ctx) {
11785
+ return step((i, p, c) => {
11786
+ LEAD.at = cur;
11787
+ return child(i, p, c);
11788
+ }, input, cur, ctx);
11789
+ }
11728
11790
  function committed3(c) {
11729
11791
  return c._fc === true;
11730
11792
  }
@@ -12362,12 +12424,27 @@ function assemble(t2, prog, cfg) {
12362
12424
  };
12363
12425
  }
12364
12426
  case OP_FIELD: {
12365
- const name = k[code[ip + 1]];
12427
+ const { name, bits } = fieldSpec(k[code[ip + 1]]);
12366
12428
  const child = link(code[ip + 2]);
12429
+ if (bits === 0) {
12430
+ return (input, pos, ctx) => {
12431
+ const v = child(input, pos, ctx);
12432
+ if (v === FAIL) return FAIL;
12433
+ ctx._fields?.push({ name, value: v, span: { start: pos, end: EC.e } });
12434
+ return v;
12435
+ };
12436
+ }
12437
+ const leading = (bits & FIELD_LEADING_TRIVIA) !== 0;
12438
+ const trailing = (bits & FIELD_TRAILING_TRIVIA) !== 0;
12367
12439
  return (input, pos, ctx) => {
12440
+ const leadFrom = leading ? LEAD.at : -1;
12441
+ LEAD.at = -1;
12368
12442
  const v = child(input, pos, ctx);
12369
12443
  if (v === FAIL) return FAIL;
12370
- ctx._fields?.push({ name, value: v, span: { start: pos, end: EC.e } });
12444
+ const end = EC.e;
12445
+ const trailEnd = trailing && ctx.trivia !== void 0 ? consumeTrivia(input, end, ctx) : end;
12446
+ ctx._fields?.push(triviaFieldCapture(name, v, input, pos, end, leadFrom, trailEnd));
12447
+ EC.e = trailEnd;
12371
12448
  return v;
12372
12449
  };
12373
12450
  }
@@ -12396,8 +12473,21 @@ function assemble(t2, prog, cfg) {
12396
12473
  };
12397
12474
  }
12398
12475
  case OP_WITHCTX: {
12399
- const extra = k[code[ip + 1]];
12476
+ const ki = code[ip + 1];
12400
12477
  const child = link(code[ip + 2]);
12478
+ if (ki < 0) {
12479
+ const derive2 = fns[~ki];
12480
+ return (input, pos, ctx) => {
12481
+ const saved = ctx.state;
12482
+ ctx.state = derive2(saved);
12483
+ try {
12484
+ return child(input, pos, ctx);
12485
+ } finally {
12486
+ ctx.state = saved;
12487
+ }
12488
+ };
12489
+ }
12490
+ const extra = k[ki];
12401
12491
  return (input, pos, ctx) => {
12402
12492
  const saved = ctx.state;
12403
12493
  ctx.state = extra;
@@ -12801,6 +12891,12 @@ function assemble(t2, prog, cfg) {
12801
12891
  const kidIp = code[base + i];
12802
12892
  if (code[kidIp] !== OP_ADJ) {
12803
12893
  const kid = link(kidIp);
12894
+ if (leadingTriviaFieldAt(code, k, kidIp)) {
12895
+ return (input, cur, ctx, inherited) => {
12896
+ ctx._sync = sync ?? inherited;
12897
+ return leadingFieldTerm(step, kid, input, cur, ctx);
12898
+ };
12899
+ }
12804
12900
  return (input, cur, ctx, inherited) => {
12805
12901
  ctx._sync = sync ?? inherited;
12806
12902
  return step(kid, input, cur, ctx);
@@ -12878,9 +12974,12 @@ function assemble(t2, prog, cfg) {
12878
12974
  };
12879
12975
  }
12880
12976
  let hasAdj = false;
12881
- for (let i = 1; i < n; i++) if (code[code[base + i]] === OP_ADJ) {
12882
- hasAdj = true;
12883
- break;
12977
+ for (let i = 1; i < n; i++) {
12978
+ const kidIp = code[base + i];
12979
+ if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp)) {
12980
+ hasAdj = true;
12981
+ break;
12982
+ }
12884
12983
  }
12885
12984
  if (hasAdj) {
12886
12985
  const first2 = link(code[base]);
@@ -12888,6 +12987,9 @@ function assemble(t2, prog, cfg) {
12888
12987
  const kidIp = code[base + i];
12889
12988
  if (code[kidIp] !== OP_ADJ) {
12890
12989
  const kid = link(kidIp);
12990
+ if (leadingTriviaFieldAt(code, k, kidIp)) {
12991
+ return (input, cur, ctx) => leadingFieldTerm(step, kid, input, cur, ctx);
12992
+ }
12891
12993
  return (input, cur, ctx) => step(kid, input, cur, ctx);
12892
12994
  }
12893
12995
  const negated = code[kidIp + 1] === 1;
@@ -13250,7 +13352,7 @@ function assemble(t2, prog, cfg) {
13250
13352
  if (n === 2 || n === 3) {
13251
13353
  const a0 = link(code[base]), a1 = link(code[base + 1]);
13252
13354
  const a2 = n === 3 ? link(code[base + 2]) : void 0;
13253
- const predecide = !hostCst && !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
13355
+ const predecide = !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
13254
13356
  const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
13255
13357
  const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
13256
13358
  const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
@@ -13473,6 +13575,75 @@ function assemble(t2, prog, cfg) {
13473
13575
  );
13474
13576
  };
13475
13577
  const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
13578
+ const pBit = [];
13579
+ const pRec = [];
13580
+ if (!REC && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
13581
+ for (let i = 0; i < n; i++) {
13582
+ for (const terminal of largeChoiceLiteralPretest(code, k, code[base + i]) ?? []) {
13583
+ pBit.push(1 << i);
13584
+ pRec.push(scalarFor(terminal));
13585
+ }
13586
+ }
13587
+ }
13588
+ const pn = pBit.length;
13589
+ if (pn !== 0) {
13590
+ return (input, pos, ctx) => {
13591
+ const c = lead(input, pos);
13592
+ const need = markCst(ctx);
13593
+ const mRaw = MRAW;
13594
+ const mTl = MTL;
13595
+ const mLv = MLV;
13596
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
13597
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
13598
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
13599
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
13600
+ if (c < 128) {
13601
+ const bits = mask[c < 0 ? 128 : c];
13602
+ let tested = 0;
13603
+ let hit = 0;
13604
+ for (let i = 0; i < pn; i++) {
13605
+ const b = pBit[i];
13606
+ if ((bits & b) === 0 || (hit & b) !== 0) continue;
13607
+ tested |= b;
13608
+ if (pRec[i](input, pos) >= 0) hit |= b;
13609
+ }
13610
+ return masked(
13611
+ input,
13612
+ pos,
13613
+ ctx,
13614
+ bits & (~tested | hit),
13615
+ need,
13616
+ mRaw,
13617
+ mTl,
13618
+ mLv,
13619
+ mFl,
13620
+ mEr,
13621
+ mLog,
13622
+ mRoot,
13623
+ void 0,
13624
+ 0,
13625
+ pos
13626
+ );
13627
+ }
13628
+ return general(
13629
+ input,
13630
+ pos,
13631
+ ctx,
13632
+ c,
13633
+ need,
13634
+ mRaw,
13635
+ mTl,
13636
+ mLv,
13637
+ mFl,
13638
+ mEr,
13639
+ mLog,
13640
+ mRoot,
13641
+ void 0,
13642
+ 0,
13643
+ pos
13644
+ );
13645
+ };
13646
+ }
13476
13647
  return (input, pos, ctx) => {
13477
13648
  const c = lead(input, pos);
13478
13649
  const need = markCst(ctx);
@@ -13634,6 +13805,7 @@ function assemble(t2, prog, cfg) {
13634
13805
  const max = code[ip + 3];
13635
13806
  const sepIp = code[ip + 4];
13636
13807
  const sep = sepIp >= 0 ? link(sepIp) : void 0;
13808
+ const sepLeads = sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp);
13637
13809
  const flags = code[ip + 5];
13638
13810
  const keepSeparators = (flags & 2) !== 0;
13639
13811
  const trailingAllowed = (flags & 1) !== 0;
@@ -13673,6 +13845,7 @@ function assemble(t2, prog, cfg) {
13673
13845
  let sp = cur;
13674
13846
  if (hasTrivia) sp = skipTrivia(input, sp, ctx);
13675
13847
  ctx._fc = false;
13848
+ if (sepLeads) LEAD.at = cur;
13676
13849
  const sv = sep(input, sp, ctx);
13677
13850
  if (sv === FAIL) {
13678
13851
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
@@ -13762,6 +13935,7 @@ function assemble(t2, prog, cfg) {
13762
13935
  let sp = cur;
13763
13936
  if (hasTrivia) sp = skipTrivia(input, sp, ctx);
13764
13937
  ctx._fc = false;
13938
+ if (sepLeads) LEAD.at = cur;
13765
13939
  const sv = sep(input, sp, ctx);
13766
13940
  if (sv === FAIL) {
13767
13941
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
@@ -14084,20 +14258,9 @@ function assemble(t2, prog, cfg) {
14084
14258
  if (child >= 0) scalarFor(child);
14085
14259
  continue;
14086
14260
  }
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
- }
14261
+ const literals = largeChoiceLiteralPretest(code, k, armIp);
14262
+ if (literals !== void 0) for (const terminal of literals) scalarFor(terminal);
14263
+ if (literals !== void 0 && literals.length === 1 && literals[0] === child) continue;
14101
14264
  const sequence6 = leadingScalarSequence(code, armIp);
14102
14265
  if (sequence6 !== void 0 && (sequence6.trivia < 0 || triviaScan[sequence6.trivia] != null)) {
14103
14266
  for (const terminal of sequence6.terminals) scalarFor(terminal);
@@ -14163,7 +14326,9 @@ function assemble(t2, prog, cfg) {
14163
14326
  scanTriviaCompact,
14164
14327
  t2.lex,
14165
14328
  adjacencyHolds,
14166
- t2.lexPrograms
14329
+ t2.lexPrograms,
14330
+ LEAD,
14331
+ triviaFieldCapture
14167
14332
  );
14168
14333
  emitReached = new Set(pre.reached);
14169
14334
  }
@@ -14245,7 +14410,9 @@ function assemble(t2, prog, cfg) {
14245
14410
  scanTriviaCompact,
14246
14411
  t2.lex,
14247
14412
  adjacencyHolds,
14248
- t2.lexPrograms
14413
+ t2.lexPrograms,
14414
+ LEAD,
14415
+ triviaFieldCapture
14249
14416
  );
14250
14417
  emitReached = em.reached;
14251
14418
  } catch (e) {
@@ -14421,7 +14588,9 @@ var AssemblyCache = class {
14421
14588
  return made;
14422
14589
  }
14423
14590
  };
14424
- function tableRules(source, artifactMetadata = {}) {
14591
+ function tableRules(source, metadataOrEntry = {}) {
14592
+ const entry = typeof metadataOrEntry === "string" ? metadataOrEntry : void 0;
14593
+ const artifactMetadata = typeof metadataOrEntry === "string" ? {} : metadataOrEntry;
14425
14594
  const prog = expandCompact(source);
14426
14595
  const resolved = resolveTable(prog);
14427
14596
  const cache = new AssemblyCache(prog, resolved);
@@ -14429,7 +14598,7 @@ function tableRules(source, artifactMetadata = {}) {
14429
14598
  const skipOf = prog.scanSkipOf;
14430
14599
  let last;
14431
14600
  let selected;
14432
- return stampRuleMap(prog, {
14601
+ const map = stampRuleMap(prog, {
14433
14602
  runRule: (ri, input, pos, ctx) => {
14434
14603
  const a = selected ?? cache.forCtx(ctx);
14435
14604
  selected = void 0;
@@ -14450,6 +14619,9 @@ function tableRules(source, artifactMetadata = {}) {
14450
14619
  return a.scanSkip[skipOf?.[ri] ?? -1];
14451
14620
  }
14452
14621
  }, artifactMetadata, resolved);
14622
+ if (entry === void 0) return map;
14623
+ if (!Object.hasOwn(map, entry)) throw new Error(`tableRules: the program has no rule ${JSON.stringify(entry)}`);
14624
+ return map[entry];
14453
14625
  }
14454
14626
 
14455
14627
  // src/table/emit.ts
@@ -14604,11 +14776,15 @@ function emitTableExpression(prog, opts = {}) {
14604
14776
  const entry = opts.entry === void 0 ? "grammar" : opts.entry;
14605
14777
  const ref2 = opts.runtimeRef ?? "tableRules";
14606
14778
  const fns = opts.fnSources ?? prog.fns.map(() => "() => {}");
14607
- const close = `}${opts.metadataSource === void 0 ? "" : `,${opts.metadataSource}`})`;
14779
+ const meta = opts.metadataSource;
14780
+ if (entry !== null && meta !== void 0) {
14781
+ throw new Error("emitTableExpression: metadataSource is for the rule-map form (entry: null); a single entry carries none");
14782
+ }
14783
+ const tail = entry !== null ? `,${jsString(entry)}` : meta === void 0 ? "" : `,${meta}`;
14608
14784
  return [
14609
14785
  `/* @__PURE__ */ ${ref2}({`,
14610
14786
  ...programFields(prog, fns, opts),
14611
- entry === null ? close : `${close}[${jsString(entry)}]`
14787
+ `}${tail})`
14612
14788
  ].join("\n");
14613
14789
  }
14614
14790
 
@@ -14786,7 +14962,7 @@ function payloadKey(p, d) {
14786
14962
  case "label":
14787
14963
  return `label\0${d.label}`;
14788
14964
  case "field":
14789
- return `field\0${d.name}`;
14965
+ return `field\0${d.name}\0${d.leadingTrivia === true}\0${d.trailingTrivia === true}`;
14790
14966
  case "node":
14791
14967
  return `node\0${d.type ?? ""}\0${d.unwrap === true}\0${d.collapse === true}\0${fnKey(d.buildSrc, d.build)}`;
14792
14968
  case "transform":
@@ -17823,7 +17999,7 @@ function rebuildCombinator(root, replacements) {
17823
17999
  out = label(d.label, one(d.parser));
17824
18000
  break;
17825
18001
  case "field":
17826
- out = field(d.name, one(d.parser));
18002
+ out = field(d.name, one(d.parser), { leadingTrivia: d.leadingTrivia === true, trailingTrivia: d.trailingTrivia === true });
17827
18003
  break;
17828
18004
  case "token":
17829
18005
  out = token(one(d.parser));