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
@@ -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];
@@ -7231,6 +7243,9 @@ var Encoder = class {
7231
7243
  this.expected([adjacencyExpected(d)])
7232
7244
  );
7233
7245
  case "withCtx": {
7246
+ if (typeof d.extra === "function") {
7247
+ return this.emit(OP_WITHCTX, ~this.fn(d.extra, d.extraSrc ?? null), this.node(d.parser).ip);
7248
+ }
7234
7249
  if (!emittableConst(d.extra)) {
7235
7250
  this.runtimeOnly.add("withCtx(extra) \u2014 the state object is not serialisable");
7236
7251
  }
@@ -8872,6 +8887,26 @@ function leadingLiteralFamily(code, constants, ip, minDepth = 2, limit = 4) {
8872
8887
  };
8873
8888
  return walk(ip, 0);
8874
8889
  }
8890
+ function largeChoiceLiteralPretest(code, constants, armIp) {
8891
+ const child = leadingScalarTerminal(code, armIp, 2, true, true);
8892
+ if (child >= 0) {
8893
+ const spec = constants[code[child + 1]];
8894
+ if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) return [child];
8895
+ }
8896
+ const family = leadingLiteralFamily(code, constants, armIp);
8897
+ return family !== void 0 && family.length >= 2 && family.every((terminal) => {
8898
+ const value = constants[code[terminal + 1]];
8899
+ return typeof value === "string" && value.length >= 2;
8900
+ }) ? family : void 0;
8901
+ }
8902
+
8903
+ // src/table/field-spec.ts
8904
+ function fieldSpec(slot) {
8905
+ return Array.isArray(slot) ? { name: slot[0], bits: slot[1] } : { name: slot, bits: 0 };
8906
+ }
8907
+ function leadingTriviaFieldAt(code, k, ip) {
8908
+ return code[ip] === OP_FIELD && (fieldSpec(k[code[ip + 1]]).bits & FIELD_LEADING_TRIVIA) !== 0;
8909
+ }
8875
8910
 
8876
8911
  // src/table/emit-assembly.ts
8877
8912
  var Unemittable = class extends Error {
@@ -8946,7 +8981,11 @@ var EMITTED_PARAMS = [
8946
8981
  // Appended for old precompiled-factory ABI: old factories ignore it.
8947
8982
  "adjacencyHolds",
8948
8983
  // Appended for selected composite lexical programs; old factories ignore it.
8949
- "LEXPROG"
8984
+ "LEXPROG",
8985
+ // Appended for trivia-attributing fields (`field(…, { leadingTrivia })`);
8986
+ // old factories ignore them.
8987
+ "LEAD",
8988
+ "triviaFieldCapture"
8950
8989
  ];
8951
8990
  var RUNTIME_PRELUDE = `
8952
8991
  let _pfScan=null
@@ -9206,20 +9245,12 @@ function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false) {
9206
9245
  if (child >= 0) scalarSpecs.add(code[child + 1]);
9207
9246
  continue;
9208
9247
  }
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);
9248
+ const literals = largeChoiceLiteralPretest(code, k, armIp);
9249
+ if (literals !== void 0 && literals.length === 1 && literals[0] === child) {
9250
+ largeChoiceScalarSpecs.add(code[child + 1]);
9251
+ continue;
9222
9252
  }
9253
+ if (literals !== void 0) largeChoiceLiteralFamilies.set(armIp, literals);
9223
9254
  const sequence6 = leadingScalarSequence(code, armIp);
9224
9255
  if (sequence6 !== void 0 && (sequence6.trivia < 0 || swapLegal && t2.triviaScan[sequence6.trivia] != null)) {
9225
9256
  largeChoiceScalarSequences.set(armIp, sequence6);
@@ -9643,14 +9674,31 @@ return v
9643
9674
  }`;
9644
9675
  }
9645
9676
  case OP_FIELD: {
9646
- const name = q(k[code[ip + 1]]);
9677
+ const spec = fieldSpec(k[code[ip + 1]]);
9678
+ const name = q(spec.name);
9647
9679
  const child = link(code[ip + 2]);
9648
- return `${head}
9680
+ if (spec.bits === 0) {
9681
+ return `${head}
9649
9682
  const v=${child}(input,pos,ctx)
9650
9683
  if(v===FAIL)return FAIL
9651
9684
  const f=ctx._fields
9652
9685
  if(f!==undefined)f.push({name:${name},value:v,span:{start:pos,end:EC.e}})
9653
9686
  return v
9687
+ }`;
9688
+ }
9689
+ const leading = (spec.bits & FIELD_LEADING_TRIVIA) !== 0;
9690
+ const trailing = (spec.bits & FIELD_TRAILING_TRIVIA) !== 0;
9691
+ return `${head}
9692
+ const lf=${leading ? "LEAD.at" : "-1"}
9693
+ LEAD.at=-1
9694
+ const v=${child}(input,pos,ctx)
9695
+ if(v===FAIL)return FAIL
9696
+ const e=EC.e
9697
+ const te=${trailing ? "ctx.trivia!==undefined?consumeTrivia(input,e,ctx):e" : "e"}
9698
+ const f=ctx._fields
9699
+ if(f!==undefined)f.push(triviaFieldCapture(${name},v,input,pos,e,lf,te))
9700
+ EC.e=te
9701
+ return v
9654
9702
  }`;
9655
9703
  }
9656
9704
  case OP_EXPECT: {
@@ -9946,7 +9994,10 @@ return v
9946
9994
  `if(!adjacencyHolds(input,cur,ctx,${negated ? "true" : "false"},${kinds})){ctx._fe=cur;ctx._fx=${expected};return FAIL}`,
9947
9995
  `${vn}=null`
9948
9996
  );
9949
- } else parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
9997
+ } else {
9998
+ const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
9999
+ parts.push(emitTerm(callee, vn, tmp(), L, skipFor(L)));
10000
+ }
9950
10001
  names.push(vn);
9951
10002
  }
9952
10003
  parts.push("EC.e=cur");
@@ -10346,7 +10397,7 @@ let sp=cur
10346
10397
  ${hasTrivia === "false" ? "" : hasTrivia === "true" ? `sp=${skip}(input,sp,ctx)
10347
10398
  ` : `if(hasTrivia)sp=${skip}(input,sp,ctx)
10348
10399
  `}ctx._fc=false
10349
- const sv=${sep}(input,sp,ctx)
10400
+ ${sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp) ? "LEAD.at=cur\n" : ""}const sv=${sep}(input,sp,ctx)
10350
10401
  if(sv===FAIL){
10351
10402
  ${rb}
10352
10403
  if(ctx._fc===true)return FAIL
@@ -10728,6 +10779,10 @@ function sequence(...parsers) {
10728
10779
  (adjacency ??= Array.from({ length: parsers.length }, () => null))[i] = a;
10729
10780
  }
10730
10781
  const hasAdjacency = adjacency !== null;
10782
+ let leading = null;
10783
+ for (let i = 1; i < parsers.length; i++) {
10784
+ if (leadsTrivia(parsers[i])) (leading ??= Array.from({ length: parsers.length }, () => false))[i] = true;
10785
+ }
10731
10786
  const strictArity = !hasAdjacency && (parsers.length === 2 && !matchesEmpty(parsers[1]) || parsers.length === 3 && parsers.every((p) => !matchesEmpty(p))) ? parsers.length : 0;
10732
10787
  const meta = {
10733
10788
  // Union through the nullable prefix — a leading optional()/many() lets a later
@@ -10775,7 +10830,7 @@ function sequence(...parsers) {
10775
10830
  _tag: "sequence",
10776
10831
  _meta: meta,
10777
10832
  _def: def,
10778
- _parseScalar: hasAdjacency ? void 0 : parseScalar,
10833
+ _parseScalar: hasAdjacency || leading !== null ? void 0 : parseScalar,
10779
10834
  parse(input, pos, ctx) {
10780
10835
  const tolerant = ctx._tolerant === true;
10781
10836
  if (tolerant) {
@@ -10809,6 +10864,7 @@ function sequence(...parsers) {
10809
10864
  const scanTlog = deferredTrivia ? cstTlLen(ctx) : 0;
10810
10865
  const scanLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
10811
10866
  const scanRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
10867
+ if (leading?.[i] === true) LEAD.at = cur;
10812
10868
  const result = parsers[i].parse(input, termPos, ctx);
10813
10869
  if (!result.ok) return result;
10814
10870
  if (values !== void 0) values.push(result.value);
@@ -11841,6 +11897,12 @@ function assemble(t2, prog, cfg) {
11841
11897
  rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
11842
11898
  return cur;
11843
11899
  }
11900
+ function leadingFieldTerm(step, child, input, cur, ctx) {
11901
+ return step((i, p, c) => {
11902
+ LEAD.at = cur;
11903
+ return child(i, p, c);
11904
+ }, input, cur, ctx);
11905
+ }
11844
11906
  function committed3(c) {
11845
11907
  return c._fc === true;
11846
11908
  }
@@ -12478,12 +12540,27 @@ function assemble(t2, prog, cfg) {
12478
12540
  };
12479
12541
  }
12480
12542
  case OP_FIELD: {
12481
- const name = k[code[ip + 1]];
12543
+ const { name, bits } = fieldSpec(k[code[ip + 1]]);
12482
12544
  const child = link(code[ip + 2]);
12545
+ if (bits === 0) {
12546
+ return (input, pos, ctx) => {
12547
+ const v = child(input, pos, ctx);
12548
+ if (v === FAIL) return FAIL;
12549
+ ctx._fields?.push({ name, value: v, span: { start: pos, end: EC.e } });
12550
+ return v;
12551
+ };
12552
+ }
12553
+ const leading = (bits & FIELD_LEADING_TRIVIA) !== 0;
12554
+ const trailing = (bits & FIELD_TRAILING_TRIVIA) !== 0;
12483
12555
  return (input, pos, ctx) => {
12556
+ const leadFrom = leading ? LEAD.at : -1;
12557
+ LEAD.at = -1;
12484
12558
  const v = child(input, pos, ctx);
12485
12559
  if (v === FAIL) return FAIL;
12486
- ctx._fields?.push({ name, value: v, span: { start: pos, end: EC.e } });
12560
+ const end = EC.e;
12561
+ const trailEnd = trailing && ctx.trivia !== void 0 ? consumeTrivia(input, end, ctx) : end;
12562
+ ctx._fields?.push(triviaFieldCapture(name, v, input, pos, end, leadFrom, trailEnd));
12563
+ EC.e = trailEnd;
12487
12564
  return v;
12488
12565
  };
12489
12566
  }
@@ -12512,8 +12589,21 @@ function assemble(t2, prog, cfg) {
12512
12589
  };
12513
12590
  }
12514
12591
  case OP_WITHCTX: {
12515
- const extra = k[code[ip + 1]];
12592
+ const ki = code[ip + 1];
12516
12593
  const child = link(code[ip + 2]);
12594
+ if (ki < 0) {
12595
+ const derive2 = fns[~ki];
12596
+ return (input, pos, ctx) => {
12597
+ const saved = ctx.state;
12598
+ ctx.state = derive2(saved);
12599
+ try {
12600
+ return child(input, pos, ctx);
12601
+ } finally {
12602
+ ctx.state = saved;
12603
+ }
12604
+ };
12605
+ }
12606
+ const extra = k[ki];
12517
12607
  return (input, pos, ctx) => {
12518
12608
  const saved = ctx.state;
12519
12609
  ctx.state = extra;
@@ -12917,6 +13007,12 @@ function assemble(t2, prog, cfg) {
12917
13007
  const kidIp = code[base + i];
12918
13008
  if (code[kidIp] !== OP_ADJ) {
12919
13009
  const kid = link(kidIp);
13010
+ if (leadingTriviaFieldAt(code, k, kidIp)) {
13011
+ return (input, cur, ctx, inherited) => {
13012
+ ctx._sync = sync ?? inherited;
13013
+ return leadingFieldTerm(step, kid, input, cur, ctx);
13014
+ };
13015
+ }
12920
13016
  return (input, cur, ctx, inherited) => {
12921
13017
  ctx._sync = sync ?? inherited;
12922
13018
  return step(kid, input, cur, ctx);
@@ -12994,9 +13090,12 @@ function assemble(t2, prog, cfg) {
12994
13090
  };
12995
13091
  }
12996
13092
  let hasAdj = false;
12997
- for (let i = 1; i < n; i++) if (code[code[base + i]] === OP_ADJ) {
12998
- hasAdj = true;
12999
- break;
13093
+ for (let i = 1; i < n; i++) {
13094
+ const kidIp = code[base + i];
13095
+ if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp)) {
13096
+ hasAdj = true;
13097
+ break;
13098
+ }
13000
13099
  }
13001
13100
  if (hasAdj) {
13002
13101
  const first2 = link(code[base]);
@@ -13004,6 +13103,9 @@ function assemble(t2, prog, cfg) {
13004
13103
  const kidIp = code[base + i];
13005
13104
  if (code[kidIp] !== OP_ADJ) {
13006
13105
  const kid = link(kidIp);
13106
+ if (leadingTriviaFieldAt(code, k, kidIp)) {
13107
+ return (input, cur, ctx) => leadingFieldTerm(step, kid, input, cur, ctx);
13108
+ }
13007
13109
  return (input, cur, ctx) => step(kid, input, cur, ctx);
13008
13110
  }
13009
13111
  const negated = code[kidIp + 1] === 1;
@@ -13366,7 +13468,7 @@ function assemble(t2, prog, cfg) {
13366
13468
  if (n === 2 || n === 3) {
13367
13469
  const a0 = link(code[base]), a1 = link(code[base + 1]);
13368
13470
  const a2 = n === 3 ? link(code[base + 2]) : void 0;
13369
- const predecide = !hostCst && !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
13471
+ const predecide = !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
13370
13472
  const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
13371
13473
  const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
13372
13474
  const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
@@ -13589,6 +13691,75 @@ function assemble(t2, prog, cfg) {
13589
13691
  );
13590
13692
  };
13591
13693
  const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
13694
+ const pBit = [];
13695
+ const pRec = [];
13696
+ if (!REC && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
13697
+ for (let i = 0; i < n; i++) {
13698
+ for (const terminal of largeChoiceLiteralPretest(code, k, code[base + i]) ?? []) {
13699
+ pBit.push(1 << i);
13700
+ pRec.push(scalarFor(terminal));
13701
+ }
13702
+ }
13703
+ }
13704
+ const pn = pBit.length;
13705
+ if (pn !== 0) {
13706
+ return (input, pos, ctx) => {
13707
+ const c = lead(input, pos);
13708
+ const need = markCst(ctx);
13709
+ const mRaw = MRAW;
13710
+ const mTl = MTL;
13711
+ const mLv = MLV;
13712
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
13713
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
13714
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
13715
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
13716
+ if (c < 128) {
13717
+ const bits = mask[c < 0 ? 128 : c];
13718
+ let tested = 0;
13719
+ let hit = 0;
13720
+ for (let i = 0; i < pn; i++) {
13721
+ const b = pBit[i];
13722
+ if ((bits & b) === 0 || (hit & b) !== 0) continue;
13723
+ tested |= b;
13724
+ if (pRec[i](input, pos) >= 0) hit |= b;
13725
+ }
13726
+ return masked(
13727
+ input,
13728
+ pos,
13729
+ ctx,
13730
+ bits & (~tested | hit),
13731
+ need,
13732
+ mRaw,
13733
+ mTl,
13734
+ mLv,
13735
+ mFl,
13736
+ mEr,
13737
+ mLog,
13738
+ mRoot,
13739
+ void 0,
13740
+ 0,
13741
+ pos
13742
+ );
13743
+ }
13744
+ return general(
13745
+ input,
13746
+ pos,
13747
+ ctx,
13748
+ c,
13749
+ need,
13750
+ mRaw,
13751
+ mTl,
13752
+ mLv,
13753
+ mFl,
13754
+ mEr,
13755
+ mLog,
13756
+ mRoot,
13757
+ void 0,
13758
+ 0,
13759
+ pos
13760
+ );
13761
+ };
13762
+ }
13592
13763
  return (input, pos, ctx) => {
13593
13764
  const c = lead(input, pos);
13594
13765
  const need = markCst(ctx);
@@ -13750,6 +13921,7 @@ function assemble(t2, prog, cfg) {
13750
13921
  const max = code[ip + 3];
13751
13922
  const sepIp = code[ip + 4];
13752
13923
  const sep = sepIp >= 0 ? link(sepIp) : void 0;
13924
+ const sepLeads = sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp);
13753
13925
  const flags = code[ip + 5];
13754
13926
  const keepSeparators = (flags & 2) !== 0;
13755
13927
  const trailingAllowed = (flags & 1) !== 0;
@@ -13789,6 +13961,7 @@ function assemble(t2, prog, cfg) {
13789
13961
  let sp = cur;
13790
13962
  if (hasTrivia) sp = skipTrivia(input, sp, ctx);
13791
13963
  ctx._fc = false;
13964
+ if (sepLeads) LEAD.at = cur;
13792
13965
  const sv = sep(input, sp, ctx);
13793
13966
  if (sv === FAIL) {
13794
13967
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
@@ -13878,6 +14051,7 @@ function assemble(t2, prog, cfg) {
13878
14051
  let sp = cur;
13879
14052
  if (hasTrivia) sp = skipTrivia(input, sp, ctx);
13880
14053
  ctx._fc = false;
14054
+ if (sepLeads) LEAD.at = cur;
13881
14055
  const sv = sep(input, sp, ctx);
13882
14056
  if (sv === FAIL) {
13883
14057
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
@@ -14200,20 +14374,9 @@ function assemble(t2, prog, cfg) {
14200
14374
  if (child >= 0) scalarFor(child);
14201
14375
  continue;
14202
14376
  }
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
- }
14377
+ const literals = largeChoiceLiteralPretest(code, k, armIp);
14378
+ if (literals !== void 0) for (const terminal of literals) scalarFor(terminal);
14379
+ if (literals !== void 0 && literals.length === 1 && literals[0] === child) continue;
14217
14380
  const sequence6 = leadingScalarSequence(code, armIp);
14218
14381
  if (sequence6 !== void 0 && (sequence6.trivia < 0 || triviaScan[sequence6.trivia] != null)) {
14219
14382
  for (const terminal of sequence6.terminals) scalarFor(terminal);
@@ -14279,7 +14442,9 @@ function assemble(t2, prog, cfg) {
14279
14442
  scanTriviaCompact,
14280
14443
  t2.lex,
14281
14444
  adjacencyHolds,
14282
- t2.lexPrograms
14445
+ t2.lexPrograms,
14446
+ LEAD,
14447
+ triviaFieldCapture
14283
14448
  );
14284
14449
  emitReached = new Set(pre.reached);
14285
14450
  }
@@ -14361,7 +14526,9 @@ function assemble(t2, prog, cfg) {
14361
14526
  scanTriviaCompact,
14362
14527
  t2.lex,
14363
14528
  adjacencyHolds,
14364
- t2.lexPrograms
14529
+ t2.lexPrograms,
14530
+ LEAD,
14531
+ triviaFieldCapture
14365
14532
  );
14366
14533
  emitReached = em.reached;
14367
14534
  } catch (e) {
@@ -14537,7 +14704,9 @@ var AssemblyCache = class {
14537
14704
  return made;
14538
14705
  }
14539
14706
  };
14540
- function tableRules(source, artifactMetadata = {}) {
14707
+ function tableRules(source, metadataOrEntry = {}) {
14708
+ const entry = typeof metadataOrEntry === "string" ? metadataOrEntry : void 0;
14709
+ const artifactMetadata = typeof metadataOrEntry === "string" ? {} : metadataOrEntry;
14541
14710
  const prog = expandCompact(source);
14542
14711
  const resolved = resolveTable(prog);
14543
14712
  const cache = new AssemblyCache(prog, resolved);
@@ -14545,7 +14714,7 @@ function tableRules(source, artifactMetadata = {}) {
14545
14714
  const skipOf = prog.scanSkipOf;
14546
14715
  let last;
14547
14716
  let selected;
14548
- return stampRuleMap(prog, {
14717
+ const map = stampRuleMap(prog, {
14549
14718
  runRule: (ri, input, pos, ctx) => {
14550
14719
  const a = selected ?? cache.forCtx(ctx);
14551
14720
  selected = void 0;
@@ -14566,6 +14735,9 @@ function tableRules(source, artifactMetadata = {}) {
14566
14735
  return a.scanSkip[skipOf?.[ri] ?? -1];
14567
14736
  }
14568
14737
  }, artifactMetadata, resolved);
14738
+ if (entry === void 0) return map;
14739
+ if (!Object.hasOwn(map, entry)) throw new Error(`tableRules: the program has no rule ${JSON.stringify(entry)}`);
14740
+ return map[entry];
14569
14741
  }
14570
14742
 
14571
14743
  // src/table/emit.ts
@@ -14720,11 +14892,15 @@ function emitTableExpression(prog, opts = {}) {
14720
14892
  const entry = opts.entry === void 0 ? "grammar" : opts.entry;
14721
14893
  const ref2 = opts.runtimeRef ?? "tableRules";
14722
14894
  const fns = opts.fnSources ?? prog.fns.map(() => "() => {}");
14723
- const close = `}${opts.metadataSource === void 0 ? "" : `,${opts.metadataSource}`})`;
14895
+ const meta = opts.metadataSource;
14896
+ if (entry !== null && meta !== void 0) {
14897
+ throw new Error("emitTableExpression: metadataSource is for the rule-map form (entry: null); a single entry carries none");
14898
+ }
14899
+ const tail = entry !== null ? `,${jsString(entry)}` : meta === void 0 ? "" : `,${meta}`;
14724
14900
  return [
14725
14901
  `/* @__PURE__ */ ${ref2}({`,
14726
14902
  ...programFields(prog, fns, opts),
14727
- entry === null ? close : `${close}[${jsString(entry)}]`
14903
+ `}${tail})`
14728
14904
  ].join("\n");
14729
14905
  }
14730
14906
 
@@ -14902,7 +15078,7 @@ function payloadKey(p, d) {
14902
15078
  case "label":
14903
15079
  return `label\0${d.label}`;
14904
15080
  case "field":
14905
- return `field\0${d.name}`;
15081
+ return `field\0${d.name}\0${d.leadingTrivia === true}\0${d.trailingTrivia === true}`;
14906
15082
  case "node":
14907
15083
  return `node\0${d.type ?? ""}\0${d.unwrap === true}\0${d.collapse === true}\0${fnKey(d.buildSrc, d.build)}`;
14908
15084
  case "transform":
@@ -16976,7 +17152,7 @@ function rebuildCombinator(root, replacements) {
16976
17152
  out = label(d.label, one(d.parser));
16977
17153
  break;
16978
17154
  case "field":
16979
- out = field(d.name, one(d.parser));
17155
+ out = field(d.name, one(d.parser), { leadingTrivia: d.leadingTrivia === true, trailingTrivia: d.trailingTrivia === true });
16980
17156
  break;
16981
17157
  case "token":
16982
17158
  out = token(one(d.parser));