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
@@ -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
  }
@@ -9819,6 +9854,12 @@ function assemble(t, prog, cfg) {
9819
9854
  const kidIp = code[base + i];
9820
9855
  if (code[kidIp] !== OP_ADJ) {
9821
9856
  const kid = link(kidIp);
9857
+ if (leadingTriviaFieldAt(code, k, kidIp)) {
9858
+ return (input, cur, ctx, inherited) => {
9859
+ ctx._sync = sync ?? inherited;
9860
+ return leadingFieldTerm(step, kid, input, cur, ctx);
9861
+ };
9862
+ }
9822
9863
  return (input, cur, ctx, inherited) => {
9823
9864
  ctx._sync = sync ?? inherited;
9824
9865
  return step(kid, input, cur, ctx);
@@ -9896,9 +9937,12 @@ function assemble(t, prog, cfg) {
9896
9937
  };
9897
9938
  }
9898
9939
  let hasAdj = false;
9899
- for (let i = 1; i < n; i++) if (code[code[base + i]] === OP_ADJ) {
9900
- hasAdj = true;
9901
- break;
9940
+ for (let i = 1; i < n; i++) {
9941
+ const kidIp = code[base + i];
9942
+ if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp)) {
9943
+ hasAdj = true;
9944
+ break;
9945
+ }
9902
9946
  }
9903
9947
  if (hasAdj) {
9904
9948
  const first2 = link(code[base]);
@@ -9906,6 +9950,9 @@ function assemble(t, prog, cfg) {
9906
9950
  const kidIp = code[base + i];
9907
9951
  if (code[kidIp] !== OP_ADJ) {
9908
9952
  const kid = link(kidIp);
9953
+ if (leadingTriviaFieldAt(code, k, kidIp)) {
9954
+ return (input, cur, ctx) => leadingFieldTerm(step, kid, input, cur, ctx);
9955
+ }
9909
9956
  return (input, cur, ctx) => step(kid, input, cur, ctx);
9910
9957
  }
9911
9958
  const negated = code[kidIp + 1] === 1;
@@ -10268,7 +10315,7 @@ function assemble(t, prog, cfg) {
10268
10315
  if (n === 2 || n === 3) {
10269
10316
  const a0 = link(code[base]), a1 = link(code[base + 1]);
10270
10317
  const a2 = n === 3 ? link(code[base + 2]) : void 0;
10271
- const predecide = !hostCst && !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
10318
+ const predecide = !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
10272
10319
  const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
10273
10320
  const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
10274
10321
  const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
@@ -10491,6 +10538,75 @@ function assemble(t, prog, cfg) {
10491
10538
  );
10492
10539
  };
10493
10540
  const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
10541
+ const pBit = [];
10542
+ const pRec = [];
10543
+ if (!REC && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
10544
+ for (let i = 0; i < n; i++) {
10545
+ for (const terminal of largeChoiceLiteralPretest(code, k, code[base + i]) ?? []) {
10546
+ pBit.push(1 << i);
10547
+ pRec.push(scalarFor(terminal));
10548
+ }
10549
+ }
10550
+ }
10551
+ const pn = pBit.length;
10552
+ if (pn !== 0) {
10553
+ return (input, pos, ctx) => {
10554
+ const c = lead(input, pos);
10555
+ const need = markCst(ctx);
10556
+ const mRaw = MRAW;
10557
+ const mTl = MTL;
10558
+ const mLv = MLV;
10559
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
10560
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
10561
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
10562
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
10563
+ if (c < 128) {
10564
+ const bits = mask[c < 0 ? 128 : c];
10565
+ let tested = 0;
10566
+ let hit = 0;
10567
+ for (let i = 0; i < pn; i++) {
10568
+ const b = pBit[i];
10569
+ if ((bits & b) === 0 || (hit & b) !== 0) continue;
10570
+ tested |= b;
10571
+ if (pRec[i](input, pos) >= 0) hit |= b;
10572
+ }
10573
+ return masked(
10574
+ input,
10575
+ pos,
10576
+ ctx,
10577
+ bits & (~tested | hit),
10578
+ need,
10579
+ mRaw,
10580
+ mTl,
10581
+ mLv,
10582
+ mFl,
10583
+ mEr,
10584
+ mLog,
10585
+ mRoot,
10586
+ void 0,
10587
+ 0,
10588
+ pos
10589
+ );
10590
+ }
10591
+ return general(
10592
+ input,
10593
+ pos,
10594
+ ctx,
10595
+ c,
10596
+ need,
10597
+ mRaw,
10598
+ mTl,
10599
+ mLv,
10600
+ mFl,
10601
+ mEr,
10602
+ mLog,
10603
+ mRoot,
10604
+ void 0,
10605
+ 0,
10606
+ pos
10607
+ );
10608
+ };
10609
+ }
10494
10610
  return (input, pos, ctx) => {
10495
10611
  const c = lead(input, pos);
10496
10612
  const need = markCst(ctx);
@@ -10652,6 +10768,7 @@ function assemble(t, prog, cfg) {
10652
10768
  const max = code[ip + 3];
10653
10769
  const sepIp = code[ip + 4];
10654
10770
  const sep = sepIp >= 0 ? link(sepIp) : void 0;
10771
+ const sepLeads = sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp);
10655
10772
  const flags = code[ip + 5];
10656
10773
  const keepSeparators = (flags & 2) !== 0;
10657
10774
  const trailingAllowed = (flags & 1) !== 0;
@@ -10691,6 +10808,7 @@ function assemble(t, prog, cfg) {
10691
10808
  let sp = cur;
10692
10809
  if (hasTrivia) sp = skipTrivia(input, sp, ctx);
10693
10810
  ctx._fc = false;
10811
+ if (sepLeads) LEAD.at = cur;
10694
10812
  const sv = sep(input, sp, ctx);
10695
10813
  if (sv === FAIL) {
10696
10814
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
@@ -10780,6 +10898,7 @@ function assemble(t, prog, cfg) {
10780
10898
  let sp = cur;
10781
10899
  if (hasTrivia) sp = skipTrivia(input, sp, ctx);
10782
10900
  ctx._fc = false;
10901
+ if (sepLeads) LEAD.at = cur;
10783
10902
  const sv = sep(input, sp, ctx);
10784
10903
  if (sv === FAIL) {
10785
10904
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
@@ -11102,20 +11221,9 @@ function assemble(t, prog, cfg) {
11102
11221
  if (child >= 0) scalarFor(child);
11103
11222
  continue;
11104
11223
  }
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
- }
11224
+ const literals = largeChoiceLiteralPretest(code, k, armIp);
11225
+ if (literals !== void 0) for (const terminal of literals) scalarFor(terminal);
11226
+ if (literals !== void 0 && literals.length === 1 && literals[0] === child) continue;
11119
11227
  const sequence6 = leadingScalarSequence(code, armIp);
11120
11228
  if (sequence6 !== void 0 && (sequence6.trivia < 0 || triviaScan[sequence6.trivia] != null)) {
11121
11229
  for (const terminal of sequence6.terminals) scalarFor(terminal);
@@ -11181,7 +11289,9 @@ function assemble(t, prog, cfg) {
11181
11289
  scanTriviaCompact,
11182
11290
  t.lex,
11183
11291
  adjacencyHolds,
11184
- t.lexPrograms
11292
+ t.lexPrograms,
11293
+ LEAD,
11294
+ triviaFieldCapture
11185
11295
  );
11186
11296
  emitReached = new Set(pre.reached);
11187
11297
  }
@@ -11263,7 +11373,9 @@ function assemble(t, prog, cfg) {
11263
11373
  scanTriviaCompact,
11264
11374
  t.lex,
11265
11375
  adjacencyHolds,
11266
- t.lexPrograms
11376
+ t.lexPrograms,
11377
+ LEAD,
11378
+ triviaFieldCapture
11267
11379
  );
11268
11380
  emitReached = em.reached;
11269
11381
  } catch (e) {
@@ -11439,7 +11551,9 @@ var AssemblyCache = class {
11439
11551
  return made;
11440
11552
  }
11441
11553
  };
11442
- function tableRules(source, artifactMetadata = {}) {
11554
+ function tableRules(source, metadataOrEntry = {}) {
11555
+ const entry = typeof metadataOrEntry === "string" ? metadataOrEntry : void 0;
11556
+ const artifactMetadata = typeof metadataOrEntry === "string" ? {} : metadataOrEntry;
11443
11557
  const prog = expandCompact(source);
11444
11558
  const resolved = resolveTable(prog);
11445
11559
  const cache = new AssemblyCache(prog, resolved);
@@ -11447,7 +11561,7 @@ function tableRules(source, artifactMetadata = {}) {
11447
11561
  const skipOf = prog.scanSkipOf;
11448
11562
  let last;
11449
11563
  let selected;
11450
- return stampRuleMap(prog, {
11564
+ const map = stampRuleMap(prog, {
11451
11565
  runRule: (ri, input, pos, ctx) => {
11452
11566
  const a = selected ?? cache.forCtx(ctx);
11453
11567
  selected = void 0;
@@ -11468,6 +11582,9 @@ function tableRules(source, artifactMetadata = {}) {
11468
11582
  return a.scanSkip[skipOf?.[ri] ?? -1];
11469
11583
  }
11470
11584
  }, artifactMetadata, resolved);
11585
+ if (entry === void 0) return map;
11586
+ if (!Object.hasOwn(map, entry)) throw new Error(`tableRules: the program has no rule ${JSON.stringify(entry)}`);
11587
+ return map[entry];
11471
11588
  }
11472
11589
 
11473
11590
  // src/analysis/gating.ts
@@ -12644,6 +12761,16 @@ var Encoder = class {
12644
12761
  this.kIndex.set(key, i);
12645
12762
  return i;
12646
12763
  }
12764
+ fieldSpecIndex = /* @__PURE__ */ new Map();
12765
+ fieldSpecSlot(name, bits) {
12766
+ const key = JSON.stringify([name, bits]);
12767
+ const hit = this.fieldSpecIndex.get(key);
12768
+ if (hit !== void 0) return hit;
12769
+ const i = this.k.length;
12770
+ this.k.push([name, bits]);
12771
+ this.fieldSpecIndex.set(key, i);
12772
+ return i;
12773
+ }
12647
12774
  /**
12648
12775
  * A `notAdjacent({ kinds })` filter, pooled by its CONTENTS.
12649
12776
  *
@@ -13264,8 +13391,10 @@ var Encoder = class {
13264
13391
  for (let i = 0; i < arms.length; i++) this.code[head + 6 + i] = arms[i];
13265
13392
  return head;
13266
13393
  }
13267
- case "field":
13268
- return this.emit(OP_FIELD, this.constant(d.name), this.node(d.parser).ip);
13394
+ case "field": {
13395
+ const bits = (d.leadingTrivia === true ? FIELD_LEADING_TRIVIA : 0) | (d.trailingTrivia === true ? FIELD_TRAILING_TRIVIA : 0);
13396
+ return this.emit(OP_FIELD, bits === 0 ? this.constant(d.name) : this.fieldSpecSlot(d.name, bits), this.node(d.parser).ip);
13397
+ }
13269
13398
  case "lazy": {
13270
13399
  const refName = p._ruleName;
13271
13400
  const winner = refName === void 0 ? void 0 : this.winners?.[refName];
@@ -13703,11 +13832,15 @@ function emitTableExpression(prog, opts = {}) {
13703
13832
  const entry = opts.entry === void 0 ? "grammar" : opts.entry;
13704
13833
  const ref2 = opts.runtimeRef ?? "tableRules";
13705
13834
  const fns = opts.fnSources ?? prog.fns.map(() => "() => {}");
13706
- const close = `}${opts.metadataSource === void 0 ? "" : `,${opts.metadataSource}`})`;
13835
+ const meta = opts.metadataSource;
13836
+ if (entry !== null && meta !== void 0) {
13837
+ throw new Error("emitTableExpression: metadataSource is for the rule-map form (entry: null); a single entry carries none");
13838
+ }
13839
+ const tail = entry !== null ? `,${jsString(entry)}` : meta === void 0 ? "" : `,${meta}`;
13707
13840
  return [
13708
13841
  `/* @__PURE__ */ ${ref2}({`,
13709
13842
  ...programFields(prog, fns, opts),
13710
- entry === null ? close : `${close}[${jsString(entry)}]`
13843
+ `}${tail})`
13711
13844
  ].join("\n");
13712
13845
  }
13713
13846
  function emitFoldedModule(folded, opts = {}) {
@@ -13911,7 +14044,7 @@ function payloadKey(p, d) {
13911
14044
  case "label":
13912
14045
  return `label\0${d.label}`;
13913
14046
  case "field":
13914
- return `field\0${d.name}`;
14047
+ return `field\0${d.name}\0${d.leadingTrivia === true}\0${d.trailingTrivia === true}`;
13915
14048
  case "node":
13916
14049
  return `node\0${d.type ?? ""}\0${d.unwrap === true}\0${d.collapse === true}\0${fnKey(d.buildSrc, d.build)}`;
13917
14050
  case "transform":