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
@@ -1155,65 +1155,17 @@ function plainRegexSource(p) {
1155
1155
  const d = p._def;
1156
1156
  return d.tag === "regex" && d.flags === "" ? d.source : null;
1157
1157
  }
1158
- var visitSpec0;
1159
- var visitSpec1;
1160
- var visitSpec2;
1161
- var visitSpec3;
1162
- var visitValue0;
1163
- var visitValue1;
1164
- var visitValue2;
1165
- var visitValue3;
1166
1158
  function commonLabeledTriviaVisitor(spec) {
1167
- if (spec === visitSpec0) return visitValue0;
1168
- if (spec === visitSpec1) return visitValue1;
1169
- if (spec === visitSpec2) return visitValue2;
1170
- if (spec === visitSpec3) return visitValue3;
1171
- const sources = spec.minRepeats <= 1 ? spec.arms.map((arm) => plainRegexSource(arm.parser)) : [];
1172
- const visitor = commonCssTriviaVisitor(sources);
1173
- visitSpec3 = visitSpec2;
1174
- visitValue3 = visitValue2;
1175
- visitSpec2 = visitSpec1;
1176
- visitValue2 = visitValue1;
1177
- visitSpec1 = visitSpec0;
1178
- visitValue1 = visitValue0;
1179
- visitSpec0 = spec;
1180
- visitValue0 = visitor;
1181
- return visitor;
1182
- }
1183
- var armSpec0;
1184
- var armSpec1;
1185
- var armSpec2;
1186
- var armSpec3;
1187
- var armValue0;
1188
- var armValue1;
1189
- var armValue2;
1190
- var armValue3;
1159
+ return commonCssTriviaVisitor(spec.minRepeats <= 1 ? spec.arms.map((arm) => plainRegexSource(arm.parser)) : []);
1160
+ }
1191
1161
  function charArmsFor(spec) {
1192
- if (spec === armSpec0) return armValue0;
1193
- if (spec === armSpec1) return armValue1;
1194
- if (spec === armSpec2) return armValue2;
1195
- if (spec === armSpec3) return armValue3;
1196
- let arms = [];
1197
- if (spec.minRepeats > 1) {
1198
- arms = null;
1199
- } else {
1200
- for (const arm of spec.arms) {
1201
- const c = classifyParser(arm.parser);
1202
- if (!c) {
1203
- arms = null;
1204
- break;
1205
- }
1206
- arms.push(c);
1207
- }
1162
+ if (spec.minRepeats > 1) return null;
1163
+ const arms = [];
1164
+ for (const arm of spec.arms) {
1165
+ const c = classifyParser(arm.parser);
1166
+ if (!c) return null;
1167
+ arms.push(c);
1208
1168
  }
1209
- armSpec3 = armSpec2;
1210
- armValue3 = armValue2;
1211
- armSpec2 = armSpec1;
1212
- armValue2 = armValue1;
1213
- armSpec1 = armSpec0;
1214
- armValue1 = armValue0;
1215
- armSpec0 = spec;
1216
- armValue0 = arms;
1217
1169
  return arms;
1218
1170
  }
1219
1171
  function charTriviaEnd(input, cur, arms) {
@@ -1329,12 +1281,16 @@ function analyzeLabeledTrivia(trivia2) {
1329
1281
  }
1330
1282
  arms.push({ label: peeled.label, kindIndex: 0, parser: peeled.parser });
1331
1283
  }
1332
- const spec = {
1284
+ return cacheLabeledTrivia(trivia2, labeledTriviaSpec(arms, minRepeats));
1285
+ }
1286
+ function labeledTriviaSpec(arms, minRepeats) {
1287
+ return {
1333
1288
  labels: arms.map((a) => a.label),
1334
1289
  arms,
1335
- minRepeats
1290
+ minRepeats,
1291
+ visitor: commonLabeledTriviaVisitor({ arms, minRepeats }),
1292
+ charArms: charArmsFor({ arms, minRepeats })
1336
1293
  };
1337
- return cacheLabeledTrivia(trivia2, spec);
1338
1294
  }
1339
1295
  function matchArmAt(input, pos, arm, state) {
1340
1296
  if (!startsFirstSet(arm, input, pos)) return null;
@@ -1364,7 +1320,7 @@ function scanLabeledTriviaChunks(input, cur, spec, state) {
1364
1320
  return { end: pos, chunks };
1365
1321
  }
1366
1322
  function scanLabeledTriviaEnd(input, cur, spec, state) {
1367
- const chars = charArmsFor(spec);
1323
+ const chars = spec.charArms;
1368
1324
  if (chars !== null) return charTriviaEnd(input, cur, chars);
1369
1325
  let pos = cur;
1370
1326
  let count = 0;
@@ -1382,9 +1338,9 @@ function scanLabeledTriviaEnd(input, cur, spec, state) {
1382
1338
  }
1383
1339
  function visitLabeledTrivia(input, cur, spec, state, visit) {
1384
1340
  if (spec.minRepeats > 1) return void 0;
1385
- const common = commonLabeledTriviaVisitor(spec);
1341
+ const common = spec.visitor;
1386
1342
  if (common !== null) return common(input, cur, visit);
1387
- const chars = charArmsFor(spec);
1343
+ const chars = spec.charArms;
1388
1344
  if (chars !== null) return charTriviaVisit(input, cur, chars, visit);
1389
1345
  let pos = cur;
1390
1346
  let count = 0;
@@ -1451,7 +1407,7 @@ function resolveAdjacencyKindMask(trivia2, kinds) {
1451
1407
  return mask;
1452
1408
  }
1453
1409
  function triviaKindMaskAt(input, pos, spec, state) {
1454
- const chars = charArmsFor(spec);
1410
+ const chars = spec.charArms;
1455
1411
  if (chars !== null) return charTriviaKindMask(input, pos, chars);
1456
1412
  let cur = pos;
1457
1413
  let mask = 0;
@@ -4200,7 +4156,7 @@ function buildFieldMap(captures) {
4200
4156
  if (!captures?.length) return void 0;
4201
4157
  const out = {};
4202
4158
  for (const cap of captures) {
4203
- const entry = { value: cap.value, span: cap.span };
4159
+ const entry = cap.leading === void 0 ? { value: cap.value, span: cap.span } : { value: cap.value, span: cap.span, leading: cap.leading, trailing: cap.trailing };
4204
4160
  const current = out[cap.name];
4205
4161
  if (current === void 0) out[cap.name] = entry;
4206
4162
  else if (Array.isArray(current)) current.push(entry);
@@ -4209,6 +4165,23 @@ function buildFieldMap(captures) {
4209
4165
  return out;
4210
4166
  }
4211
4167
 
4168
+ // src/combinators/field-trivia.ts
4169
+ var LEAD = { at: -1 };
4170
+ var FIELD_LEADING_TRIVIA = 1;
4171
+ var FIELD_TRAILING_TRIVIA = 2;
4172
+ function triviaFieldCapture(name, value, input, start, end, leadFrom, trailEnd) {
4173
+ return {
4174
+ name,
4175
+ value,
4176
+ span: { start, end },
4177
+ leading: leadFrom >= 0 && leadFrom < start ? input.slice(leadFrom, start) : "",
4178
+ trailing: trailEnd > end ? input.slice(end, trailEnd) : ""
4179
+ };
4180
+ }
4181
+ function leadsTrivia(p) {
4182
+ return p._def.tag === "field" && p._def.leadingTrivia === true;
4183
+ }
4184
+
4212
4185
  // src/combinators/dispatch.ts
4213
4186
  function parserUsesRouted(parser2, seen = /* @__PURE__ */ new Set()) {
4214
4187
  if (seen.has(parser2)) return false;
@@ -5177,6 +5150,7 @@ function unwrapSeparator(separator) {
5177
5150
  }
5178
5151
  function sepBy(combinator, separatorArg, opts = {}) {
5179
5152
  const { sep: separator, keep: keepSeparators } = unwrapSeparator(separatorArg);
5153
+ const separatorLeads = leadsTrivia(separator);
5180
5154
  const { min, max } = resolveBounds("sepBy()", opts);
5181
5155
  const trailing = opts.trailing ?? "forbid";
5182
5156
  const meta = {
@@ -5241,7 +5215,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
5241
5215
  // this option surface already; parity is held by test/parity, not by hope.
5242
5216
  ...keepSeparators ? { keepSeparators: true } : {}
5243
5217
  },
5244
- _parseScalar: keepSeparators ? void 0 : parseScalar,
5218
+ _parseScalar: keepSeparators || separatorLeads ? void 0 : parseScalar,
5245
5219
  parse(input, pos, ctx) {
5246
5220
  const first = combinator.parse(input, pos, ctx);
5247
5221
  const values = [];
@@ -5273,6 +5247,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
5273
5247
  sepPos = advanceTrivia(input, cur, ctx);
5274
5248
  }
5275
5249
  }
5250
+ if (separatorLeads) LEAD.at = cur;
5276
5251
  const sep = separator.parse(input, sepPos, ctx);
5277
5252
  if (!sep.ok) {
5278
5253
  rollbackTrivia(ctx, loopMark);
@@ -5424,16 +5399,41 @@ function label(name, combinator) {
5424
5399
  }
5425
5400
  };
5426
5401
  }
5427
- function field(name, combinator) {
5402
+ function field(name, combinator, opts) {
5403
+ const leadingTrivia = opts?.leadingTrivia === true;
5404
+ const trailingTrivia = opts?.trailingTrivia === true;
5405
+ if (!leadingTrivia && !trailingTrivia) {
5406
+ return {
5407
+ _tag: combinator._tag,
5408
+ _meta: combinator._meta,
5409
+ _def: { tag: "field", name, parser: combinator },
5410
+ parse(input, pos, ctx) {
5411
+ const result = combinator.parse(input, pos, ctx);
5412
+ if (!result.ok) return result;
5413
+ ctx._fields?.push({ name, value: result.value, span: result.span });
5414
+ return result;
5415
+ }
5416
+ };
5417
+ }
5428
5418
  return {
5429
5419
  _tag: combinator._tag,
5430
5420
  _meta: combinator._meta,
5431
- _def: { tag: "field", name, parser: combinator },
5421
+ _def: {
5422
+ tag: "field",
5423
+ name,
5424
+ parser: combinator,
5425
+ ...leadingTrivia ? { leadingTrivia: true } : {},
5426
+ ...trailingTrivia ? { trailingTrivia: true } : {}
5427
+ },
5432
5428
  parse(input, pos, ctx) {
5429
+ const leadFrom = LEAD.at;
5430
+ LEAD.at = -1;
5433
5431
  const result = combinator.parse(input, pos, ctx);
5434
5432
  if (!result.ok) return result;
5435
- ctx._fields?.push({ name, value: result.value, span: result.span });
5436
- return result;
5433
+ const end = result.span.end;
5434
+ const trailEnd = trailingTrivia && ctx.trivia ? consumeTrivia(input, end, ctx) : end;
5435
+ ctx._fields?.push(triviaFieldCapture(name, result.value, input, result.span.start, end, leadingTrivia ? leadFrom : -1, trailEnd));
5436
+ return trailEnd === end ? result : { ok: true, value: result.value, span: { start: result.span.start, end: trailEnd } };
5437
5437
  }
5438
5438
  };
5439
5439
  }
@@ -6578,6 +6578,16 @@ var Encoder = class {
6578
6578
  this.kIndex.set(key, i);
6579
6579
  return i;
6580
6580
  }
6581
+ fieldSpecIndex = /* @__PURE__ */ new Map();
6582
+ fieldSpecSlot(name, bits) {
6583
+ const key = JSON.stringify([name, bits]);
6584
+ const hit = this.fieldSpecIndex.get(key);
6585
+ if (hit !== void 0) return hit;
6586
+ const i = this.k.length;
6587
+ this.k.push([name, bits]);
6588
+ this.fieldSpecIndex.set(key, i);
6589
+ return i;
6590
+ }
6581
6591
  /**
6582
6592
  * A `notAdjacent({ kinds })` filter, pooled by its CONTENTS.
6583
6593
  *
@@ -7198,8 +7208,10 @@ var Encoder = class {
7198
7208
  for (let i = 0; i < arms.length; i++) this.code[head + 6 + i] = arms[i];
7199
7209
  return head;
7200
7210
  }
7201
- case "field":
7202
- return this.emit(OP_FIELD, this.constant(d.name), this.node(d.parser).ip);
7211
+ case "field": {
7212
+ const bits = (d.leadingTrivia === true ? FIELD_LEADING_TRIVIA : 0) | (d.trailingTrivia === true ? FIELD_TRAILING_TRIVIA : 0);
7213
+ return this.emit(OP_FIELD, bits === 0 ? this.constant(d.name) : this.fieldSpecSlot(d.name, bits), this.node(d.parser).ip);
7214
+ }
7203
7215
  case "lazy": {
7204
7216
  const refName = p._ruleName;
7205
7217
  const winner = refName === void 0 ? void 0 : this.winners?.[refName];
@@ -8872,6 +8884,26 @@ function leadingLiteralFamily(code, constants, ip, minDepth = 2, limit = 4) {
8872
8884
  };
8873
8885
  return walk(ip, 0);
8874
8886
  }
8887
+ function largeChoiceLiteralPretest(code, constants, armIp) {
8888
+ const child = leadingScalarTerminal(code, armIp, 2, true, true);
8889
+ if (child >= 0) {
8890
+ const spec = constants[code[child + 1]];
8891
+ if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) return [child];
8892
+ }
8893
+ const family = leadingLiteralFamily(code, constants, armIp);
8894
+ return family !== void 0 && family.length >= 2 && family.every((terminal) => {
8895
+ const value = constants[code[terminal + 1]];
8896
+ return typeof value === "string" && value.length >= 2;
8897
+ }) ? family : void 0;
8898
+ }
8899
+
8900
+ // src/table/field-spec.ts
8901
+ function fieldSpec(slot) {
8902
+ return Array.isArray(slot) ? { name: slot[0], bits: slot[1] } : { name: slot, bits: 0 };
8903
+ }
8904
+ function leadingTriviaFieldAt(code, k, ip) {
8905
+ return code[ip] === OP_FIELD && (fieldSpec(k[code[ip + 1]]).bits & FIELD_LEADING_TRIVIA) !== 0;
8906
+ }
8875
8907
 
8876
8908
  // src/table/emit-assembly.ts
8877
8909
  var Unemittable = class extends Error {
@@ -8946,7 +8978,11 @@ var EMITTED_PARAMS = [
8946
8978
  // Appended for old precompiled-factory ABI: old factories ignore it.
8947
8979
  "adjacencyHolds",
8948
8980
  // Appended for selected composite lexical programs; old factories ignore it.
8949
- "LEXPROG"
8981
+ "LEXPROG",
8982
+ // Appended for trivia-attributing fields (`field(…, { leadingTrivia })`);
8983
+ // old factories ignore them.
8984
+ "LEAD",
8985
+ "triviaFieldCapture"
8950
8986
  ];
8951
8987
  var RUNTIME_PRELUDE = `
8952
8988
  let _pfScan=null
@@ -9206,20 +9242,12 @@ function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false) {
9206
9242
  if (child >= 0) scalarSpecs.add(code[child + 1]);
9207
9243
  continue;
9208
9244
  }
9209
- if (child >= 0) {
9210
- const spec = k[code[child + 1]];
9211
- if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
9212
- largeChoiceScalarSpecs.add(code[child + 1]);
9213
- continue;
9214
- }
9215
- }
9216
- const family = leadingLiteralFamily(code, k, armIp);
9217
- if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
9218
- const value = k[code[terminal + 1]];
9219
- return typeof value === "string" && value.length >= 2;
9220
- })) {
9221
- largeChoiceLiteralFamilies.set(armIp, family);
9245
+ const literals = largeChoiceLiteralPretest(code, k, armIp);
9246
+ if (literals !== void 0 && literals.length === 1 && literals[0] === child) {
9247
+ largeChoiceScalarSpecs.add(code[child + 1]);
9248
+ continue;
9222
9249
  }
9250
+ if (literals !== void 0) largeChoiceLiteralFamilies.set(armIp, literals);
9223
9251
  const sequence6 = leadingScalarSequence(code, armIp);
9224
9252
  if (sequence6 !== void 0 && (sequence6.trivia < 0 || swapLegal && t2.triviaScan[sequence6.trivia] != null)) {
9225
9253
  largeChoiceScalarSequences.set(armIp, sequence6);
@@ -9643,14 +9671,31 @@ return v
9643
9671
  }`;
9644
9672
  }
9645
9673
  case OP_FIELD: {
9646
- const name = q(k[code[ip + 1]]);
9674
+ const spec = fieldSpec(k[code[ip + 1]]);
9675
+ const name = q(spec.name);
9647
9676
  const child = link(code[ip + 2]);
9648
- return `${head}
9677
+ if (spec.bits === 0) {
9678
+ return `${head}
9649
9679
  const v=${child}(input,pos,ctx)
9650
9680
  if(v===FAIL)return FAIL
9651
9681
  const f=ctx._fields
9652
9682
  if(f!==undefined)f.push({name:${name},value:v,span:{start:pos,end:EC.e}})
9653
9683
  return v
9684
+ }`;
9685
+ }
9686
+ const leading = (spec.bits & FIELD_LEADING_TRIVIA) !== 0;
9687
+ const trailing = (spec.bits & FIELD_TRAILING_TRIVIA) !== 0;
9688
+ return `${head}
9689
+ const lf=${leading ? "LEAD.at" : "-1"}
9690
+ LEAD.at=-1
9691
+ const v=${child}(input,pos,ctx)
9692
+ if(v===FAIL)return FAIL
9693
+ const e=EC.e
9694
+ const te=${trailing ? "ctx.trivia!==undefined?consumeTrivia(input,e,ctx):e" : "e"}
9695
+ const f=ctx._fields
9696
+ if(f!==undefined)f.push(triviaFieldCapture(${name},v,input,pos,e,lf,te))
9697
+ EC.e=te
9698
+ return v
9654
9699
  }`;
9655
9700
  }
9656
9701
  case OP_EXPECT: {
@@ -9946,7 +9991,10 @@ return v
9946
9991
  `if(!adjacencyHolds(input,cur,ctx,${negated ? "true" : "false"},${kinds})){ctx._fe=cur;ctx._fx=${expected};return FAIL}`,
9947
9992
  `${vn}=null`
9948
9993
  );
9949
- } else parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
9994
+ } else {
9995
+ const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
9996
+ parts.push(emitTerm(callee, vn, tmp(), L, skipFor(L)));
9997
+ }
9950
9998
  names.push(vn);
9951
9999
  }
9952
10000
  parts.push("EC.e=cur");
@@ -10346,7 +10394,7 @@ let sp=cur
10346
10394
  ${hasTrivia === "false" ? "" : hasTrivia === "true" ? `sp=${skip}(input,sp,ctx)
10347
10395
  ` : `if(hasTrivia)sp=${skip}(input,sp,ctx)
10348
10396
  `}ctx._fc=false
10349
- const sv=${sep}(input,sp,ctx)
10397
+ ${sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp) ? "LEAD.at=cur\n" : ""}const sv=${sep}(input,sp,ctx)
10350
10398
  if(sv===FAIL){
10351
10399
  ${rb}
10352
10400
  if(ctx._fc===true)return FAIL
@@ -10728,6 +10776,10 @@ function sequence(...parsers) {
10728
10776
  (adjacency ??= Array.from({ length: parsers.length }, () => null))[i] = a;
10729
10777
  }
10730
10778
  const hasAdjacency = adjacency !== null;
10779
+ let leading = null;
10780
+ for (let i = 1; i < parsers.length; i++) {
10781
+ if (leadsTrivia(parsers[i])) (leading ??= Array.from({ length: parsers.length }, () => false))[i] = true;
10782
+ }
10731
10783
  const strictArity = !hasAdjacency && (parsers.length === 2 && !matchesEmpty(parsers[1]) || parsers.length === 3 && parsers.every((p) => !matchesEmpty(p))) ? parsers.length : 0;
10732
10784
  const meta = {
10733
10785
  // Union through the nullable prefix — a leading optional()/many() lets a later
@@ -10775,7 +10827,7 @@ function sequence(...parsers) {
10775
10827
  _tag: "sequence",
10776
10828
  _meta: meta,
10777
10829
  _def: def,
10778
- _parseScalar: hasAdjacency ? void 0 : parseScalar,
10830
+ _parseScalar: hasAdjacency || leading !== null ? void 0 : parseScalar,
10779
10831
  parse(input, pos, ctx) {
10780
10832
  const tolerant = ctx._tolerant === true;
10781
10833
  if (tolerant) {
@@ -10809,6 +10861,7 @@ function sequence(...parsers) {
10809
10861
  const scanTlog = deferredTrivia ? cstTlLen(ctx) : 0;
10810
10862
  const scanLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
10811
10863
  const scanRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
10864
+ if (leading?.[i] === true) LEAD.at = cur;
10812
10865
  const result = parsers[i].parse(input, termPos, ctx);
10813
10866
  if (!result.ok) return result;
10814
10867
  if (values !== void 0) values.push(result.value);
@@ -11841,6 +11894,12 @@ function assemble(t2, prog, cfg) {
11841
11894
  rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
11842
11895
  return cur;
11843
11896
  }
11897
+ function leadingFieldTerm(step, child, input, cur, ctx) {
11898
+ return step((i, p, c) => {
11899
+ LEAD.at = cur;
11900
+ return child(i, p, c);
11901
+ }, input, cur, ctx);
11902
+ }
11844
11903
  function committed3(c) {
11845
11904
  return c._fc === true;
11846
11905
  }
@@ -12478,12 +12537,27 @@ function assemble(t2, prog, cfg) {
12478
12537
  };
12479
12538
  }
12480
12539
  case OP_FIELD: {
12481
- const name = k[code[ip + 1]];
12540
+ const { name, bits } = fieldSpec(k[code[ip + 1]]);
12482
12541
  const child = link(code[ip + 2]);
12542
+ if (bits === 0) {
12543
+ return (input, pos, ctx) => {
12544
+ const v = child(input, pos, ctx);
12545
+ if (v === FAIL) return FAIL;
12546
+ ctx._fields?.push({ name, value: v, span: { start: pos, end: EC.e } });
12547
+ return v;
12548
+ };
12549
+ }
12550
+ const leading = (bits & FIELD_LEADING_TRIVIA) !== 0;
12551
+ const trailing = (bits & FIELD_TRAILING_TRIVIA) !== 0;
12483
12552
  return (input, pos, ctx) => {
12553
+ const leadFrom = leading ? LEAD.at : -1;
12554
+ LEAD.at = -1;
12484
12555
  const v = child(input, pos, ctx);
12485
12556
  if (v === FAIL) return FAIL;
12486
- ctx._fields?.push({ name, value: v, span: { start: pos, end: EC.e } });
12557
+ const end = EC.e;
12558
+ const trailEnd = trailing && ctx.trivia !== void 0 ? consumeTrivia(input, end, ctx) : end;
12559
+ ctx._fields?.push(triviaFieldCapture(name, v, input, pos, end, leadFrom, trailEnd));
12560
+ EC.e = trailEnd;
12487
12561
  return v;
12488
12562
  };
12489
12563
  }
@@ -12917,6 +12991,12 @@ function assemble(t2, prog, cfg) {
12917
12991
  const kidIp = code[base + i];
12918
12992
  if (code[kidIp] !== OP_ADJ) {
12919
12993
  const kid = link(kidIp);
12994
+ if (leadingTriviaFieldAt(code, k, kidIp)) {
12995
+ return (input, cur, ctx, inherited) => {
12996
+ ctx._sync = sync ?? inherited;
12997
+ return leadingFieldTerm(step, kid, input, cur, ctx);
12998
+ };
12999
+ }
12920
13000
  return (input, cur, ctx, inherited) => {
12921
13001
  ctx._sync = sync ?? inherited;
12922
13002
  return step(kid, input, cur, ctx);
@@ -12994,9 +13074,12 @@ function assemble(t2, prog, cfg) {
12994
13074
  };
12995
13075
  }
12996
13076
  let hasAdj = false;
12997
- for (let i = 1; i < n; i++) if (code[code[base + i]] === OP_ADJ) {
12998
- hasAdj = true;
12999
- break;
13077
+ for (let i = 1; i < n; i++) {
13078
+ const kidIp = code[base + i];
13079
+ if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp)) {
13080
+ hasAdj = true;
13081
+ break;
13082
+ }
13000
13083
  }
13001
13084
  if (hasAdj) {
13002
13085
  const first2 = link(code[base]);
@@ -13004,6 +13087,9 @@ function assemble(t2, prog, cfg) {
13004
13087
  const kidIp = code[base + i];
13005
13088
  if (code[kidIp] !== OP_ADJ) {
13006
13089
  const kid = link(kidIp);
13090
+ if (leadingTriviaFieldAt(code, k, kidIp)) {
13091
+ return (input, cur, ctx) => leadingFieldTerm(step, kid, input, cur, ctx);
13092
+ }
13007
13093
  return (input, cur, ctx) => step(kid, input, cur, ctx);
13008
13094
  }
13009
13095
  const negated = code[kidIp + 1] === 1;
@@ -13366,7 +13452,7 @@ function assemble(t2, prog, cfg) {
13366
13452
  if (n === 2 || n === 3) {
13367
13453
  const a0 = link(code[base]), a1 = link(code[base + 1]);
13368
13454
  const a2 = n === 3 ? link(code[base + 2]) : void 0;
13369
- const predecide = !hostCst && !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
13455
+ const predecide = !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
13370
13456
  const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
13371
13457
  const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
13372
13458
  const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
@@ -13589,6 +13675,75 @@ function assemble(t2, prog, cfg) {
13589
13675
  );
13590
13676
  };
13591
13677
  const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
13678
+ const pBit = [];
13679
+ const pRec = [];
13680
+ if (!REC && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
13681
+ for (let i = 0; i < n; i++) {
13682
+ for (const terminal of largeChoiceLiteralPretest(code, k, code[base + i]) ?? []) {
13683
+ pBit.push(1 << i);
13684
+ pRec.push(scalarFor(terminal));
13685
+ }
13686
+ }
13687
+ }
13688
+ const pn = pBit.length;
13689
+ if (pn !== 0) {
13690
+ return (input, pos, ctx) => {
13691
+ const c = lead(input, pos);
13692
+ const need = markCst(ctx);
13693
+ const mRaw = MRAW;
13694
+ const mTl = MTL;
13695
+ const mLv = MLV;
13696
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
13697
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
13698
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
13699
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
13700
+ if (c < 128) {
13701
+ const bits = mask[c < 0 ? 128 : c];
13702
+ let tested = 0;
13703
+ let hit = 0;
13704
+ for (let i = 0; i < pn; i++) {
13705
+ const b = pBit[i];
13706
+ if ((bits & b) === 0 || (hit & b) !== 0) continue;
13707
+ tested |= b;
13708
+ if (pRec[i](input, pos) >= 0) hit |= b;
13709
+ }
13710
+ return masked(
13711
+ input,
13712
+ pos,
13713
+ ctx,
13714
+ bits & (~tested | hit),
13715
+ need,
13716
+ mRaw,
13717
+ mTl,
13718
+ mLv,
13719
+ mFl,
13720
+ mEr,
13721
+ mLog,
13722
+ mRoot,
13723
+ void 0,
13724
+ 0,
13725
+ pos
13726
+ );
13727
+ }
13728
+ return general(
13729
+ input,
13730
+ pos,
13731
+ ctx,
13732
+ c,
13733
+ need,
13734
+ mRaw,
13735
+ mTl,
13736
+ mLv,
13737
+ mFl,
13738
+ mEr,
13739
+ mLog,
13740
+ mRoot,
13741
+ void 0,
13742
+ 0,
13743
+ pos
13744
+ );
13745
+ };
13746
+ }
13592
13747
  return (input, pos, ctx) => {
13593
13748
  const c = lead(input, pos);
13594
13749
  const need = markCst(ctx);
@@ -13750,6 +13905,7 @@ function assemble(t2, prog, cfg) {
13750
13905
  const max = code[ip + 3];
13751
13906
  const sepIp = code[ip + 4];
13752
13907
  const sep = sepIp >= 0 ? link(sepIp) : void 0;
13908
+ const sepLeads = sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp);
13753
13909
  const flags = code[ip + 5];
13754
13910
  const keepSeparators = (flags & 2) !== 0;
13755
13911
  const trailingAllowed = (flags & 1) !== 0;
@@ -13789,6 +13945,7 @@ function assemble(t2, prog, cfg) {
13789
13945
  let sp = cur;
13790
13946
  if (hasTrivia) sp = skipTrivia(input, sp, ctx);
13791
13947
  ctx._fc = false;
13948
+ if (sepLeads) LEAD.at = cur;
13792
13949
  const sv = sep(input, sp, ctx);
13793
13950
  if (sv === FAIL) {
13794
13951
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
@@ -13878,6 +14035,7 @@ function assemble(t2, prog, cfg) {
13878
14035
  let sp = cur;
13879
14036
  if (hasTrivia) sp = skipTrivia(input, sp, ctx);
13880
14037
  ctx._fc = false;
14038
+ if (sepLeads) LEAD.at = cur;
13881
14039
  const sv = sep(input, sp, ctx);
13882
14040
  if (sv === FAIL) {
13883
14041
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
@@ -14200,20 +14358,9 @@ function assemble(t2, prog, cfg) {
14200
14358
  if (child >= 0) scalarFor(child);
14201
14359
  continue;
14202
14360
  }
14203
- if (child >= 0) {
14204
- const spec = k[code[child + 1]];
14205
- if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
14206
- scalarFor(child);
14207
- continue;
14208
- }
14209
- }
14210
- const family = leadingLiteralFamily(code, k, armIp);
14211
- if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
14212
- const value = k[code[terminal + 1]];
14213
- return typeof value === "string" && value.length >= 2;
14214
- })) {
14215
- for (const terminal of family) scalarFor(terminal);
14216
- }
14361
+ const literals = largeChoiceLiteralPretest(code, k, armIp);
14362
+ if (literals !== void 0) for (const terminal of literals) scalarFor(terminal);
14363
+ if (literals !== void 0 && literals.length === 1 && literals[0] === child) continue;
14217
14364
  const sequence6 = leadingScalarSequence(code, armIp);
14218
14365
  if (sequence6 !== void 0 && (sequence6.trivia < 0 || triviaScan[sequence6.trivia] != null)) {
14219
14366
  for (const terminal of sequence6.terminals) scalarFor(terminal);
@@ -14279,7 +14426,9 @@ function assemble(t2, prog, cfg) {
14279
14426
  scanTriviaCompact,
14280
14427
  t2.lex,
14281
14428
  adjacencyHolds,
14282
- t2.lexPrograms
14429
+ t2.lexPrograms,
14430
+ LEAD,
14431
+ triviaFieldCapture
14283
14432
  );
14284
14433
  emitReached = new Set(pre.reached);
14285
14434
  }
@@ -14361,7 +14510,9 @@ function assemble(t2, prog, cfg) {
14361
14510
  scanTriviaCompact,
14362
14511
  t2.lex,
14363
14512
  adjacencyHolds,
14364
- t2.lexPrograms
14513
+ t2.lexPrograms,
14514
+ LEAD,
14515
+ triviaFieldCapture
14365
14516
  );
14366
14517
  emitReached = em.reached;
14367
14518
  } catch (e) {
@@ -14537,7 +14688,9 @@ var AssemblyCache = class {
14537
14688
  return made;
14538
14689
  }
14539
14690
  };
14540
- function tableRules(source, artifactMetadata = {}) {
14691
+ function tableRules(source, metadataOrEntry = {}) {
14692
+ const entry = typeof metadataOrEntry === "string" ? metadataOrEntry : void 0;
14693
+ const artifactMetadata = typeof metadataOrEntry === "string" ? {} : metadataOrEntry;
14541
14694
  const prog = expandCompact(source);
14542
14695
  const resolved = resolveTable(prog);
14543
14696
  const cache = new AssemblyCache(prog, resolved);
@@ -14545,7 +14698,7 @@ function tableRules(source, artifactMetadata = {}) {
14545
14698
  const skipOf = prog.scanSkipOf;
14546
14699
  let last;
14547
14700
  let selected;
14548
- return stampRuleMap(prog, {
14701
+ const map = stampRuleMap(prog, {
14549
14702
  runRule: (ri, input, pos, ctx) => {
14550
14703
  const a = selected ?? cache.forCtx(ctx);
14551
14704
  selected = void 0;
@@ -14566,6 +14719,9 @@ function tableRules(source, artifactMetadata = {}) {
14566
14719
  return a.scanSkip[skipOf?.[ri] ?? -1];
14567
14720
  }
14568
14721
  }, artifactMetadata, resolved);
14722
+ if (entry === void 0) return map;
14723
+ if (!Object.hasOwn(map, entry)) throw new Error(`tableRules: the program has no rule ${JSON.stringify(entry)}`);
14724
+ return map[entry];
14569
14725
  }
14570
14726
 
14571
14727
  // src/table/emit.ts
@@ -14720,11 +14876,15 @@ function emitTableExpression(prog, opts = {}) {
14720
14876
  const entry = opts.entry === void 0 ? "grammar" : opts.entry;
14721
14877
  const ref2 = opts.runtimeRef ?? "tableRules";
14722
14878
  const fns = opts.fnSources ?? prog.fns.map(() => "() => {}");
14723
- const close = `}${opts.metadataSource === void 0 ? "" : `,${opts.metadataSource}`})`;
14879
+ const meta = opts.metadataSource;
14880
+ if (entry !== null && meta !== void 0) {
14881
+ throw new Error("emitTableExpression: metadataSource is for the rule-map form (entry: null); a single entry carries none");
14882
+ }
14883
+ const tail = entry !== null ? `,${jsString(entry)}` : meta === void 0 ? "" : `,${meta}`;
14724
14884
  return [
14725
14885
  `/* @__PURE__ */ ${ref2}({`,
14726
14886
  ...programFields(prog, fns, opts),
14727
- entry === null ? close : `${close}[${jsString(entry)}]`
14887
+ `}${tail})`
14728
14888
  ].join("\n");
14729
14889
  }
14730
14890
 
@@ -14902,7 +15062,7 @@ function payloadKey(p, d) {
14902
15062
  case "label":
14903
15063
  return `label\0${d.label}`;
14904
15064
  case "field":
14905
- return `field\0${d.name}`;
15065
+ return `field\0${d.name}\0${d.leadingTrivia === true}\0${d.trailingTrivia === true}`;
14906
15066
  case "node":
14907
15067
  return `node\0${d.type ?? ""}\0${d.unwrap === true}\0${d.collapse === true}\0${fnKey(d.buildSrc, d.build)}`;
14908
15068
  case "transform":
@@ -16976,7 +17136,7 @@ function rebuildCombinator(root, replacements) {
16976
17136
  out = label(d.label, one(d.parser));
16977
17137
  break;
16978
17138
  case "field":
16979
- out = field(d.name, one(d.parser));
17139
+ out = field(d.name, one(d.parser), { leadingTrivia: d.leadingTrivia === true, trailingTrivia: d.trailingTrivia === true });
16980
17140
  break;
16981
17141
  case "token":
16982
17142
  out = token(one(d.parser));