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
@@ -1485,65 +1485,17 @@ function plainRegexSource(p) {
1485
1485
  const d = p._def;
1486
1486
  return d.tag === "regex" && d.flags === "" ? d.source : null;
1487
1487
  }
1488
- var visitSpec0;
1489
- var visitSpec1;
1490
- var visitSpec2;
1491
- var visitSpec3;
1492
- var visitValue0;
1493
- var visitValue1;
1494
- var visitValue2;
1495
- var visitValue3;
1496
1488
  function commonLabeledTriviaVisitor(spec) {
1497
- if (spec === visitSpec0) return visitValue0;
1498
- if (spec === visitSpec1) return visitValue1;
1499
- if (spec === visitSpec2) return visitValue2;
1500
- if (spec === visitSpec3) return visitValue3;
1501
- const sources = spec.minRepeats <= 1 ? spec.arms.map((arm) => plainRegexSource(arm.parser)) : [];
1502
- const visitor = commonCssTriviaVisitor(sources);
1503
- visitSpec3 = visitSpec2;
1504
- visitValue3 = visitValue2;
1505
- visitSpec2 = visitSpec1;
1506
- visitValue2 = visitValue1;
1507
- visitSpec1 = visitSpec0;
1508
- visitValue1 = visitValue0;
1509
- visitSpec0 = spec;
1510
- visitValue0 = visitor;
1511
- return visitor;
1512
- }
1513
- var armSpec0;
1514
- var armSpec1;
1515
- var armSpec2;
1516
- var armSpec3;
1517
- var armValue0;
1518
- var armValue1;
1519
- var armValue2;
1520
- var armValue3;
1489
+ return commonCssTriviaVisitor(spec.minRepeats <= 1 ? spec.arms.map((arm) => plainRegexSource(arm.parser)) : []);
1490
+ }
1521
1491
  function charArmsFor(spec) {
1522
- if (spec === armSpec0) return armValue0;
1523
- if (spec === armSpec1) return armValue1;
1524
- if (spec === armSpec2) return armValue2;
1525
- if (spec === armSpec3) return armValue3;
1526
- let arms = [];
1527
- if (spec.minRepeats > 1) {
1528
- arms = null;
1529
- } else {
1530
- for (const arm of spec.arms) {
1531
- const c = classifyParser(arm.parser);
1532
- if (!c) {
1533
- arms = null;
1534
- break;
1535
- }
1536
- arms.push(c);
1537
- }
1492
+ if (spec.minRepeats > 1) return null;
1493
+ const arms = [];
1494
+ for (const arm of spec.arms) {
1495
+ const c = classifyParser(arm.parser);
1496
+ if (!c) return null;
1497
+ arms.push(c);
1538
1498
  }
1539
- armSpec3 = armSpec2;
1540
- armValue3 = armValue2;
1541
- armSpec2 = armSpec1;
1542
- armValue2 = armValue1;
1543
- armSpec1 = armSpec0;
1544
- armValue1 = armValue0;
1545
- armSpec0 = spec;
1546
- armValue0 = arms;
1547
1499
  return arms;
1548
1500
  }
1549
1501
  function charTriviaEnd(input, cur, arms) {
@@ -1659,12 +1611,16 @@ function analyzeLabeledTrivia(trivia2) {
1659
1611
  }
1660
1612
  arms.push({ label: peeled.label, kindIndex: 0, parser: peeled.parser });
1661
1613
  }
1662
- const spec = {
1614
+ return cacheLabeledTrivia(trivia2, labeledTriviaSpec(arms, minRepeats));
1615
+ }
1616
+ function labeledTriviaSpec(arms, minRepeats) {
1617
+ return {
1663
1618
  labels: arms.map((a) => a.label),
1664
1619
  arms,
1665
- minRepeats
1620
+ minRepeats,
1621
+ visitor: commonLabeledTriviaVisitor({ arms, minRepeats }),
1622
+ charArms: charArmsFor({ arms, minRepeats })
1666
1623
  };
1667
- return cacheLabeledTrivia(trivia2, spec);
1668
1624
  }
1669
1625
  function matchArmAt(input, pos, arm, state) {
1670
1626
  if (!startsFirstSet(arm, input, pos)) return null;
@@ -1694,7 +1650,7 @@ function scanLabeledTriviaChunks(input, cur, spec, state) {
1694
1650
  return { end: pos, chunks };
1695
1651
  }
1696
1652
  function scanLabeledTriviaEnd(input, cur, spec, state) {
1697
- const chars = charArmsFor(spec);
1653
+ const chars = spec.charArms;
1698
1654
  if (chars !== null) return charTriviaEnd(input, cur, chars);
1699
1655
  let pos = cur;
1700
1656
  let count = 0;
@@ -1712,9 +1668,9 @@ function scanLabeledTriviaEnd(input, cur, spec, state) {
1712
1668
  }
1713
1669
  function visitLabeledTrivia(input, cur, spec, state, visit) {
1714
1670
  if (spec.minRepeats > 1) return void 0;
1715
- const common = commonLabeledTriviaVisitor(spec);
1671
+ const common = spec.visitor;
1716
1672
  if (common !== null) return common(input, cur, visit);
1717
- const chars = charArmsFor(spec);
1673
+ const chars = spec.charArms;
1718
1674
  if (chars !== null) return charTriviaVisit(input, cur, chars, visit);
1719
1675
  let pos = cur;
1720
1676
  let count = 0;
@@ -1781,7 +1737,7 @@ function resolveAdjacencyKindMask(trivia2, kinds) {
1781
1737
  return mask;
1782
1738
  }
1783
1739
  function triviaKindMaskAt(input, pos, spec, state) {
1784
- const chars = charArmsFor(spec);
1740
+ const chars = spec.charArms;
1785
1741
  if (chars !== null) return charTriviaKindMask(input, pos, chars);
1786
1742
  let cur = pos;
1787
1743
  let mask = 0;
@@ -2494,6 +2450,23 @@ function scalarOf(combinator) {
2494
2450
  return combinator._parseScalar;
2495
2451
  }
2496
2452
 
2453
+ // src/combinators/field-trivia.ts
2454
+ var LEAD = { at: -1 };
2455
+ var FIELD_LEADING_TRIVIA = 1;
2456
+ var FIELD_TRAILING_TRIVIA = 2;
2457
+ function triviaFieldCapture(name, value, input, start, end, leadFrom, trailEnd) {
2458
+ return {
2459
+ name,
2460
+ value,
2461
+ span: { start, end },
2462
+ leading: leadFrom >= 0 && leadFrom < start ? input.slice(leadFrom, start) : "",
2463
+ trailing: trailEnd > end ? input.slice(end, trailEnd) : ""
2464
+ };
2465
+ }
2466
+ function leadsTrivia(p) {
2467
+ return p._def.tag === "field" && p._def.leadingTrivia === true;
2468
+ }
2469
+
2497
2470
  // src/combinators/sequence.ts
2498
2471
  function sequence(...parsers) {
2499
2472
  let adjacency = null;
@@ -2509,6 +2482,10 @@ function sequence(...parsers) {
2509
2482
  (adjacency ??= Array.from({ length: parsers.length }, () => null))[i] = a;
2510
2483
  }
2511
2484
  const hasAdjacency = adjacency !== null;
2485
+ let leading = null;
2486
+ for (let i = 1; i < parsers.length; i++) {
2487
+ if (leadsTrivia(parsers[i])) (leading ??= Array.from({ length: parsers.length }, () => false))[i] = true;
2488
+ }
2512
2489
  const strictArity = !hasAdjacency && (parsers.length === 2 && !matchesEmpty(parsers[1]) || parsers.length === 3 && parsers.every((p) => !matchesEmpty(p))) ? parsers.length : 0;
2513
2490
  const meta = {
2514
2491
  // Union through the nullable prefix — a leading optional()/many() lets a later
@@ -2556,7 +2533,7 @@ function sequence(...parsers) {
2556
2533
  _tag: "sequence",
2557
2534
  _meta: meta,
2558
2535
  _def: def,
2559
- _parseScalar: hasAdjacency ? void 0 : parseScalar,
2536
+ _parseScalar: hasAdjacency || leading !== null ? void 0 : parseScalar,
2560
2537
  parse(input, pos, ctx) {
2561
2538
  const tolerant = ctx._tolerant === true;
2562
2539
  if (tolerant) {
@@ -2590,6 +2567,7 @@ function sequence(...parsers) {
2590
2567
  const scanTlog = deferredTrivia ? cstTlLen(ctx) : 0;
2591
2568
  const scanLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
2592
2569
  const scanRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
2570
+ if (leading?.[i] === true) LEAD.at = cur;
2593
2571
  const result = parsers[i].parse(input, termPos, ctx);
2594
2572
  if (!result.ok) return result;
2595
2573
  if (values !== void 0) values.push(result.value);
@@ -4070,7 +4048,7 @@ function buildFieldMap(captures) {
4070
4048
  if (!captures?.length) return void 0;
4071
4049
  const out = {};
4072
4050
  for (const cap of captures) {
4073
- const entry = { value: cap.value, span: cap.span };
4051
+ const entry = cap.leading === void 0 ? { value: cap.value, span: cap.span } : { value: cap.value, span: cap.span, leading: cap.leading, trailing: cap.trailing };
4074
4052
  const current = out[cap.name];
4075
4053
  if (current === void 0) out[cap.name] = entry;
4076
4054
  else if (Array.isArray(current)) current.push(entry);
@@ -6396,6 +6374,26 @@ function leadingLiteralFamily(code, constants, ip, minDepth = 2, limit = 4) {
6396
6374
  };
6397
6375
  return walk(ip, 0);
6398
6376
  }
6377
+ function largeChoiceLiteralPretest(code, constants, armIp) {
6378
+ const child = leadingScalarTerminal(code, armIp, 2, true, true);
6379
+ if (child >= 0) {
6380
+ const spec = constants[code[child + 1]];
6381
+ if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) return [child];
6382
+ }
6383
+ const family = leadingLiteralFamily(code, constants, armIp);
6384
+ return family !== void 0 && family.length >= 2 && family.every((terminal) => {
6385
+ const value = constants[code[terminal + 1]];
6386
+ return typeof value === "string" && value.length >= 2;
6387
+ }) ? family : void 0;
6388
+ }
6389
+
6390
+ // src/table/field-spec.ts
6391
+ function fieldSpec(slot) {
6392
+ return Array.isArray(slot) ? { name: slot[0], bits: slot[1] } : { name: slot, bits: 0 };
6393
+ }
6394
+ function leadingTriviaFieldAt(code, k, ip) {
6395
+ return code[ip] === OP_FIELD && (fieldSpec(k[code[ip + 1]]).bits & FIELD_LEADING_TRIVIA) !== 0;
6396
+ }
6399
6397
 
6400
6398
  // src/table/emit-assembly.ts
6401
6399
  var Unemittable = class extends Error {
@@ -6470,7 +6468,11 @@ var EMITTED_PARAMS = [
6470
6468
  // Appended for old precompiled-factory ABI: old factories ignore it.
6471
6469
  "adjacencyHolds",
6472
6470
  // Appended for selected composite lexical programs; old factories ignore it.
6473
- "LEXPROG"
6471
+ "LEXPROG",
6472
+ // Appended for trivia-attributing fields (`field(…, { leadingTrivia })`);
6473
+ // old factories ignore them.
6474
+ "LEAD",
6475
+ "triviaFieldCapture"
6474
6476
  ];
6475
6477
  var RUNTIME_PRELUDE = `
6476
6478
  let _pfScan=null
@@ -6730,20 +6732,12 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
6730
6732
  if (child >= 0) scalarSpecs.add(code[child + 1]);
6731
6733
  continue;
6732
6734
  }
6733
- if (child >= 0) {
6734
- const spec = k[code[child + 1]];
6735
- if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
6736
- largeChoiceScalarSpecs.add(code[child + 1]);
6737
- continue;
6738
- }
6739
- }
6740
- const family = leadingLiteralFamily(code, k, armIp);
6741
- if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
6742
- const value = k[code[terminal + 1]];
6743
- return typeof value === "string" && value.length >= 2;
6744
- })) {
6745
- largeChoiceLiteralFamilies.set(armIp, family);
6735
+ const literals = largeChoiceLiteralPretest(code, k, armIp);
6736
+ if (literals !== void 0 && literals.length === 1 && literals[0] === child) {
6737
+ largeChoiceScalarSpecs.add(code[child + 1]);
6738
+ continue;
6746
6739
  }
6740
+ if (literals !== void 0) largeChoiceLiteralFamilies.set(armIp, literals);
6747
6741
  const sequence6 = leadingScalarSequence(code, armIp);
6748
6742
  if (sequence6 !== void 0 && (sequence6.trivia < 0 || swapLegal && t.triviaScan[sequence6.trivia] != null)) {
6749
6743
  largeChoiceScalarSequences.set(armIp, sequence6);
@@ -7167,14 +7161,31 @@ return v
7167
7161
  }`;
7168
7162
  }
7169
7163
  case OP_FIELD: {
7170
- const name = q(k[code[ip + 1]]);
7164
+ const spec = fieldSpec(k[code[ip + 1]]);
7165
+ const name = q(spec.name);
7171
7166
  const child = link(code[ip + 2]);
7172
- return `${head}
7167
+ if (spec.bits === 0) {
7168
+ return `${head}
7173
7169
  const v=${child}(input,pos,ctx)
7174
7170
  if(v===FAIL)return FAIL
7175
7171
  const f=ctx._fields
7176
7172
  if(f!==undefined)f.push({name:${name},value:v,span:{start:pos,end:EC.e}})
7177
7173
  return v
7174
+ }`;
7175
+ }
7176
+ const leading = (spec.bits & FIELD_LEADING_TRIVIA) !== 0;
7177
+ const trailing = (spec.bits & FIELD_TRAILING_TRIVIA) !== 0;
7178
+ return `${head}
7179
+ const lf=${leading ? "LEAD.at" : "-1"}
7180
+ LEAD.at=-1
7181
+ const v=${child}(input,pos,ctx)
7182
+ if(v===FAIL)return FAIL
7183
+ const e=EC.e
7184
+ const te=${trailing ? "ctx.trivia!==undefined?consumeTrivia(input,e,ctx):e" : "e"}
7185
+ const f=ctx._fields
7186
+ if(f!==undefined)f.push(triviaFieldCapture(${name},v,input,pos,e,lf,te))
7187
+ EC.e=te
7188
+ return v
7178
7189
  }`;
7179
7190
  }
7180
7191
  case OP_EXPECT: {
@@ -7470,7 +7481,10 @@ return v
7470
7481
  `if(!adjacencyHolds(input,cur,ctx,${negated ? "true" : "false"},${kinds})){ctx._fe=cur;ctx._fx=${expected};return FAIL}`,
7471
7482
  `${vn}=null`
7472
7483
  );
7473
- } else parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
7484
+ } else {
7485
+ const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
7486
+ parts.push(emitTerm(callee, vn, tmp(), L, skipFor(L)));
7487
+ }
7474
7488
  names.push(vn);
7475
7489
  }
7476
7490
  parts.push("EC.e=cur");
@@ -7870,7 +7884,7 @@ let sp=cur
7870
7884
  ${hasTrivia === "false" ? "" : hasTrivia === "true" ? `sp=${skip}(input,sp,ctx)
7871
7885
  ` : `if(hasTrivia)sp=${skip}(input,sp,ctx)
7872
7886
  `}ctx._fc=false
7873
- const sv=${sep}(input,sp,ctx)
7887
+ ${sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp) ? "LEAD.at=cur\n" : ""}const sv=${sep}(input,sp,ctx)
7874
7888
  if(sv===FAIL){
7875
7889
  ${rb}
7876
7890
  if(ctx._fc===true)return FAIL
@@ -8743,6 +8757,12 @@ function assemble(t, prog, cfg) {
8743
8757
  rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
8744
8758
  return cur;
8745
8759
  }
8760
+ function leadingFieldTerm(step, child, input, cur, ctx) {
8761
+ return step((i, p, c) => {
8762
+ LEAD.at = cur;
8763
+ return child(i, p, c);
8764
+ }, input, cur, ctx);
8765
+ }
8746
8766
  function committed3(c) {
8747
8767
  return c._fc === true;
8748
8768
  }
@@ -9380,12 +9400,27 @@ function assemble(t, prog, cfg) {
9380
9400
  };
9381
9401
  }
9382
9402
  case OP_FIELD: {
9383
- const name = k[code[ip + 1]];
9403
+ const { name, bits } = fieldSpec(k[code[ip + 1]]);
9384
9404
  const child = link(code[ip + 2]);
9405
+ if (bits === 0) {
9406
+ return (input, pos, ctx) => {
9407
+ const v = child(input, pos, ctx);
9408
+ if (v === FAIL) return FAIL;
9409
+ ctx._fields?.push({ name, value: v, span: { start: pos, end: EC.e } });
9410
+ return v;
9411
+ };
9412
+ }
9413
+ const leading = (bits & FIELD_LEADING_TRIVIA) !== 0;
9414
+ const trailing = (bits & FIELD_TRAILING_TRIVIA) !== 0;
9385
9415
  return (input, pos, ctx) => {
9416
+ const leadFrom = leading ? LEAD.at : -1;
9417
+ LEAD.at = -1;
9386
9418
  const v = child(input, pos, ctx);
9387
9419
  if (v === FAIL) return FAIL;
9388
- ctx._fields?.push({ name, value: v, span: { start: pos, end: EC.e } });
9420
+ const end = EC.e;
9421
+ const trailEnd = trailing && ctx.trivia !== void 0 ? consumeTrivia(input, end, ctx) : end;
9422
+ ctx._fields?.push(triviaFieldCapture(name, v, input, pos, end, leadFrom, trailEnd));
9423
+ EC.e = trailEnd;
9389
9424
  return v;
9390
9425
  };
9391
9426
  }
@@ -9414,8 +9449,21 @@ function assemble(t, prog, cfg) {
9414
9449
  };
9415
9450
  }
9416
9451
  case OP_WITHCTX: {
9417
- const extra = k[code[ip + 1]];
9452
+ const ki = code[ip + 1];
9418
9453
  const child = link(code[ip + 2]);
9454
+ if (ki < 0) {
9455
+ const derive2 = fns[~ki];
9456
+ return (input, pos, ctx) => {
9457
+ const saved = ctx.state;
9458
+ ctx.state = derive2(saved);
9459
+ try {
9460
+ return child(input, pos, ctx);
9461
+ } finally {
9462
+ ctx.state = saved;
9463
+ }
9464
+ };
9465
+ }
9466
+ const extra = k[ki];
9419
9467
  return (input, pos, ctx) => {
9420
9468
  const saved = ctx.state;
9421
9469
  ctx.state = extra;
@@ -9819,6 +9867,12 @@ function assemble(t, prog, cfg) {
9819
9867
  const kidIp = code[base + i];
9820
9868
  if (code[kidIp] !== OP_ADJ) {
9821
9869
  const kid = link(kidIp);
9870
+ if (leadingTriviaFieldAt(code, k, kidIp)) {
9871
+ return (input, cur, ctx, inherited) => {
9872
+ ctx._sync = sync ?? inherited;
9873
+ return leadingFieldTerm(step, kid, input, cur, ctx);
9874
+ };
9875
+ }
9822
9876
  return (input, cur, ctx, inherited) => {
9823
9877
  ctx._sync = sync ?? inherited;
9824
9878
  return step(kid, input, cur, ctx);
@@ -9896,9 +9950,12 @@ function assemble(t, prog, cfg) {
9896
9950
  };
9897
9951
  }
9898
9952
  let hasAdj = false;
9899
- for (let i = 1; i < n; i++) if (code[code[base + i]] === OP_ADJ) {
9900
- hasAdj = true;
9901
- break;
9953
+ for (let i = 1; i < n; i++) {
9954
+ const kidIp = code[base + i];
9955
+ if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp)) {
9956
+ hasAdj = true;
9957
+ break;
9958
+ }
9902
9959
  }
9903
9960
  if (hasAdj) {
9904
9961
  const first2 = link(code[base]);
@@ -9906,6 +9963,9 @@ function assemble(t, prog, cfg) {
9906
9963
  const kidIp = code[base + i];
9907
9964
  if (code[kidIp] !== OP_ADJ) {
9908
9965
  const kid = link(kidIp);
9966
+ if (leadingTriviaFieldAt(code, k, kidIp)) {
9967
+ return (input, cur, ctx) => leadingFieldTerm(step, kid, input, cur, ctx);
9968
+ }
9909
9969
  return (input, cur, ctx) => step(kid, input, cur, ctx);
9910
9970
  }
9911
9971
  const negated = code[kidIp + 1] === 1;
@@ -10268,7 +10328,7 @@ function assemble(t, prog, cfg) {
10268
10328
  if (n === 2 || n === 3) {
10269
10329
  const a0 = link(code[base]), a1 = link(code[base + 1]);
10270
10330
  const a2 = n === 3 ? link(code[base + 2]) : void 0;
10271
- const predecide = !hostCst && !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
10331
+ const predecide = !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
10272
10332
  const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
10273
10333
  const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
10274
10334
  const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
@@ -10491,6 +10551,75 @@ function assemble(t, prog, cfg) {
10491
10551
  );
10492
10552
  };
10493
10553
  const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
10554
+ const pBit = [];
10555
+ const pRec = [];
10556
+ if (!REC && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
10557
+ for (let i = 0; i < n; i++) {
10558
+ for (const terminal of largeChoiceLiteralPretest(code, k, code[base + i]) ?? []) {
10559
+ pBit.push(1 << i);
10560
+ pRec.push(scalarFor(terminal));
10561
+ }
10562
+ }
10563
+ }
10564
+ const pn = pBit.length;
10565
+ if (pn !== 0) {
10566
+ return (input, pos, ctx) => {
10567
+ const c = lead(input, pos);
10568
+ const need = markCst(ctx);
10569
+ const mRaw = MRAW;
10570
+ const mTl = MTL;
10571
+ const mLv = MLV;
10572
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
10573
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
10574
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
10575
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
10576
+ if (c < 128) {
10577
+ const bits = mask[c < 0 ? 128 : c];
10578
+ let tested = 0;
10579
+ let hit = 0;
10580
+ for (let i = 0; i < pn; i++) {
10581
+ const b = pBit[i];
10582
+ if ((bits & b) === 0 || (hit & b) !== 0) continue;
10583
+ tested |= b;
10584
+ if (pRec[i](input, pos) >= 0) hit |= b;
10585
+ }
10586
+ return masked(
10587
+ input,
10588
+ pos,
10589
+ ctx,
10590
+ bits & (~tested | hit),
10591
+ need,
10592
+ mRaw,
10593
+ mTl,
10594
+ mLv,
10595
+ mFl,
10596
+ mEr,
10597
+ mLog,
10598
+ mRoot,
10599
+ void 0,
10600
+ 0,
10601
+ pos
10602
+ );
10603
+ }
10604
+ return general(
10605
+ input,
10606
+ pos,
10607
+ ctx,
10608
+ c,
10609
+ need,
10610
+ mRaw,
10611
+ mTl,
10612
+ mLv,
10613
+ mFl,
10614
+ mEr,
10615
+ mLog,
10616
+ mRoot,
10617
+ void 0,
10618
+ 0,
10619
+ pos
10620
+ );
10621
+ };
10622
+ }
10494
10623
  return (input, pos, ctx) => {
10495
10624
  const c = lead(input, pos);
10496
10625
  const need = markCst(ctx);
@@ -10652,6 +10781,7 @@ function assemble(t, prog, cfg) {
10652
10781
  const max = code[ip + 3];
10653
10782
  const sepIp = code[ip + 4];
10654
10783
  const sep = sepIp >= 0 ? link(sepIp) : void 0;
10784
+ const sepLeads = sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp);
10655
10785
  const flags = code[ip + 5];
10656
10786
  const keepSeparators = (flags & 2) !== 0;
10657
10787
  const trailingAllowed = (flags & 1) !== 0;
@@ -10691,6 +10821,7 @@ function assemble(t, prog, cfg) {
10691
10821
  let sp = cur;
10692
10822
  if (hasTrivia) sp = skipTrivia(input, sp, ctx);
10693
10823
  ctx._fc = false;
10824
+ if (sepLeads) LEAD.at = cur;
10694
10825
  const sv = sep(input, sp, ctx);
10695
10826
  if (sv === FAIL) {
10696
10827
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
@@ -10780,6 +10911,7 @@ function assemble(t, prog, cfg) {
10780
10911
  let sp = cur;
10781
10912
  if (hasTrivia) sp = skipTrivia(input, sp, ctx);
10782
10913
  ctx._fc = false;
10914
+ if (sepLeads) LEAD.at = cur;
10783
10915
  const sv = sep(input, sp, ctx);
10784
10916
  if (sv === FAIL) {
10785
10917
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
@@ -11102,20 +11234,9 @@ function assemble(t, prog, cfg) {
11102
11234
  if (child >= 0) scalarFor(child);
11103
11235
  continue;
11104
11236
  }
11105
- if (child >= 0) {
11106
- const spec = k[code[child + 1]];
11107
- if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
11108
- scalarFor(child);
11109
- continue;
11110
- }
11111
- }
11112
- const family = leadingLiteralFamily(code, k, armIp);
11113
- if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
11114
- const value = k[code[terminal + 1]];
11115
- return typeof value === "string" && value.length >= 2;
11116
- })) {
11117
- for (const terminal of family) scalarFor(terminal);
11118
- }
11237
+ const literals = largeChoiceLiteralPretest(code, k, armIp);
11238
+ if (literals !== void 0) for (const terminal of literals) scalarFor(terminal);
11239
+ if (literals !== void 0 && literals.length === 1 && literals[0] === child) continue;
11119
11240
  const sequence6 = leadingScalarSequence(code, armIp);
11120
11241
  if (sequence6 !== void 0 && (sequence6.trivia < 0 || triviaScan[sequence6.trivia] != null)) {
11121
11242
  for (const terminal of sequence6.terminals) scalarFor(terminal);
@@ -11181,7 +11302,9 @@ function assemble(t, prog, cfg) {
11181
11302
  scanTriviaCompact,
11182
11303
  t.lex,
11183
11304
  adjacencyHolds,
11184
- t.lexPrograms
11305
+ t.lexPrograms,
11306
+ LEAD,
11307
+ triviaFieldCapture
11185
11308
  );
11186
11309
  emitReached = new Set(pre.reached);
11187
11310
  }
@@ -11263,7 +11386,9 @@ function assemble(t, prog, cfg) {
11263
11386
  scanTriviaCompact,
11264
11387
  t.lex,
11265
11388
  adjacencyHolds,
11266
- t.lexPrograms
11389
+ t.lexPrograms,
11390
+ LEAD,
11391
+ triviaFieldCapture
11267
11392
  );
11268
11393
  emitReached = em.reached;
11269
11394
  } catch (e) {
@@ -11439,7 +11564,9 @@ var AssemblyCache = class {
11439
11564
  return made;
11440
11565
  }
11441
11566
  };
11442
- function tableRules(source, artifactMetadata = {}) {
11567
+ function tableRules(source, metadataOrEntry = {}) {
11568
+ const entry = typeof metadataOrEntry === "string" ? metadataOrEntry : void 0;
11569
+ const artifactMetadata = typeof metadataOrEntry === "string" ? {} : metadataOrEntry;
11443
11570
  const prog = expandCompact(source);
11444
11571
  const resolved = resolveTable(prog);
11445
11572
  const cache = new AssemblyCache(prog, resolved);
@@ -11447,7 +11574,7 @@ function tableRules(source, artifactMetadata = {}) {
11447
11574
  const skipOf = prog.scanSkipOf;
11448
11575
  let last;
11449
11576
  let selected;
11450
- return stampRuleMap(prog, {
11577
+ const map = stampRuleMap(prog, {
11451
11578
  runRule: (ri, input, pos, ctx) => {
11452
11579
  const a = selected ?? cache.forCtx(ctx);
11453
11580
  selected = void 0;
@@ -11468,6 +11595,9 @@ function tableRules(source, artifactMetadata = {}) {
11468
11595
  return a.scanSkip[skipOf?.[ri] ?? -1];
11469
11596
  }
11470
11597
  }, artifactMetadata, resolved);
11598
+ if (entry === void 0) return map;
11599
+ if (!Object.hasOwn(map, entry)) throw new Error(`tableRules: the program has no rule ${JSON.stringify(entry)}`);
11600
+ return map[entry];
11471
11601
  }
11472
11602
 
11473
11603
  // src/analysis/gating.ts
@@ -12644,6 +12774,16 @@ var Encoder = class {
12644
12774
  this.kIndex.set(key, i);
12645
12775
  return i;
12646
12776
  }
12777
+ fieldSpecIndex = /* @__PURE__ */ new Map();
12778
+ fieldSpecSlot(name, bits) {
12779
+ const key = JSON.stringify([name, bits]);
12780
+ const hit = this.fieldSpecIndex.get(key);
12781
+ if (hit !== void 0) return hit;
12782
+ const i = this.k.length;
12783
+ this.k.push([name, bits]);
12784
+ this.fieldSpecIndex.set(key, i);
12785
+ return i;
12786
+ }
12647
12787
  /**
12648
12788
  * A `notAdjacent({ kinds })` filter, pooled by its CONTENTS.
12649
12789
  *
@@ -13264,8 +13404,10 @@ var Encoder = class {
13264
13404
  for (let i = 0; i < arms.length; i++) this.code[head + 6 + i] = arms[i];
13265
13405
  return head;
13266
13406
  }
13267
- case "field":
13268
- return this.emit(OP_FIELD, this.constant(d.name), this.node(d.parser).ip);
13407
+ case "field": {
13408
+ const bits = (d.leadingTrivia === true ? FIELD_LEADING_TRIVIA : 0) | (d.trailingTrivia === true ? FIELD_TRAILING_TRIVIA : 0);
13409
+ return this.emit(OP_FIELD, bits === 0 ? this.constant(d.name) : this.fieldSpecSlot(d.name, bits), this.node(d.parser).ip);
13410
+ }
13269
13411
  case "lazy": {
13270
13412
  const refName = p._ruleName;
13271
13413
  const winner = refName === void 0 ? void 0 : this.winners?.[refName];
@@ -13297,6 +13439,9 @@ var Encoder = class {
13297
13439
  this.expected([adjacencyExpected(d)])
13298
13440
  );
13299
13441
  case "withCtx": {
13442
+ if (typeof d.extra === "function") {
13443
+ return this.emit(OP_WITHCTX, ~this.fn(d.extra, d.extraSrc ?? null), this.node(d.parser).ip);
13444
+ }
13300
13445
  if (!emittableConst(d.extra)) {
13301
13446
  this.runtimeOnly.add("withCtx(extra) \u2014 the state object is not serialisable");
13302
13447
  }
@@ -13703,11 +13848,15 @@ function emitTableExpression(prog, opts = {}) {
13703
13848
  const entry = opts.entry === void 0 ? "grammar" : opts.entry;
13704
13849
  const ref2 = opts.runtimeRef ?? "tableRules";
13705
13850
  const fns = opts.fnSources ?? prog.fns.map(() => "() => {}");
13706
- const close = `}${opts.metadataSource === void 0 ? "" : `,${opts.metadataSource}`})`;
13851
+ const meta = opts.metadataSource;
13852
+ if (entry !== null && meta !== void 0) {
13853
+ throw new Error("emitTableExpression: metadataSource is for the rule-map form (entry: null); a single entry carries none");
13854
+ }
13855
+ const tail = entry !== null ? `,${jsString(entry)}` : meta === void 0 ? "" : `,${meta}`;
13707
13856
  return [
13708
13857
  `/* @__PURE__ */ ${ref2}({`,
13709
13858
  ...programFields(prog, fns, opts),
13710
- entry === null ? close : `${close}[${jsString(entry)}]`
13859
+ `}${tail})`
13711
13860
  ].join("\n");
13712
13861
  }
13713
13862
  function emitFoldedModule(folded, opts = {}) {
@@ -13911,7 +14060,7 @@ function payloadKey(p, d) {
13911
14060
  case "label":
13912
14061
  return `label\0${d.label}`;
13913
14062
  case "field":
13914
- return `field\0${d.name}`;
14063
+ return `field\0${d.name}\0${d.leadingTrivia === true}\0${d.trailingTrivia === true}`;
13915
14064
  case "node":
13916
14065
  return `node\0${d.type ?? ""}\0${d.unwrap === true}\0${d.collapse === true}\0${fnKey(d.buildSrc, d.build)}`;
13917
14066
  case "transform":