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
@@ -1269,65 +1269,17 @@ function plainRegexSource(p) {
1269
1269
  const d = p._def;
1270
1270
  return d.tag === "regex" && d.flags === "" ? d.source : null;
1271
1271
  }
1272
- var visitSpec0;
1273
- var visitSpec1;
1274
- var visitSpec2;
1275
- var visitSpec3;
1276
- var visitValue0;
1277
- var visitValue1;
1278
- var visitValue2;
1279
- var visitValue3;
1280
1272
  function commonLabeledTriviaVisitor(spec) {
1281
- if (spec === visitSpec0) return visitValue0;
1282
- if (spec === visitSpec1) return visitValue1;
1283
- if (spec === visitSpec2) return visitValue2;
1284
- if (spec === visitSpec3) return visitValue3;
1285
- const sources = spec.minRepeats <= 1 ? spec.arms.map((arm) => plainRegexSource(arm.parser)) : [];
1286
- const visitor = commonCssTriviaVisitor(sources);
1287
- visitSpec3 = visitSpec2;
1288
- visitValue3 = visitValue2;
1289
- visitSpec2 = visitSpec1;
1290
- visitValue2 = visitValue1;
1291
- visitSpec1 = visitSpec0;
1292
- visitValue1 = visitValue0;
1293
- visitSpec0 = spec;
1294
- visitValue0 = visitor;
1295
- return visitor;
1296
- }
1297
- var armSpec0;
1298
- var armSpec1;
1299
- var armSpec2;
1300
- var armSpec3;
1301
- var armValue0;
1302
- var armValue1;
1303
- var armValue2;
1304
- var armValue3;
1273
+ return commonCssTriviaVisitor(spec.minRepeats <= 1 ? spec.arms.map((arm) => plainRegexSource(arm.parser)) : []);
1274
+ }
1305
1275
  function charArmsFor(spec) {
1306
- if (spec === armSpec0) return armValue0;
1307
- if (spec === armSpec1) return armValue1;
1308
- if (spec === armSpec2) return armValue2;
1309
- if (spec === armSpec3) return armValue3;
1310
- let arms = [];
1311
- if (spec.minRepeats > 1) {
1312
- arms = null;
1313
- } else {
1314
- for (const arm of spec.arms) {
1315
- const c = classifyParser(arm.parser);
1316
- if (!c) {
1317
- arms = null;
1318
- break;
1319
- }
1320
- arms.push(c);
1321
- }
1276
+ if (spec.minRepeats > 1) return null;
1277
+ const arms = [];
1278
+ for (const arm of spec.arms) {
1279
+ const c = classifyParser(arm.parser);
1280
+ if (!c) return null;
1281
+ arms.push(c);
1322
1282
  }
1323
- armSpec3 = armSpec2;
1324
- armValue3 = armValue2;
1325
- armSpec2 = armSpec1;
1326
- armValue2 = armValue1;
1327
- armSpec1 = armSpec0;
1328
- armValue1 = armValue0;
1329
- armSpec0 = spec;
1330
- armValue0 = arms;
1331
1283
  return arms;
1332
1284
  }
1333
1285
  function charTriviaEnd(input, cur, arms) {
@@ -1443,12 +1395,16 @@ function analyzeLabeledTrivia(trivia2) {
1443
1395
  }
1444
1396
  arms.push({ label: peeled.label, kindIndex: 0, parser: peeled.parser });
1445
1397
  }
1446
- const spec = {
1398
+ return cacheLabeledTrivia(trivia2, labeledTriviaSpec(arms, minRepeats));
1399
+ }
1400
+ function labeledTriviaSpec(arms, minRepeats) {
1401
+ return {
1447
1402
  labels: arms.map((a) => a.label),
1448
1403
  arms,
1449
- minRepeats
1404
+ minRepeats,
1405
+ visitor: commonLabeledTriviaVisitor({ arms, minRepeats }),
1406
+ charArms: charArmsFor({ arms, minRepeats })
1450
1407
  };
1451
- return cacheLabeledTrivia(trivia2, spec);
1452
1408
  }
1453
1409
  function matchArmAt(input, pos, arm, state) {
1454
1410
  if (!startsFirstSet(arm, input, pos)) return null;
@@ -1478,7 +1434,7 @@ function scanLabeledTriviaChunks(input, cur, spec, state) {
1478
1434
  return { end: pos, chunks };
1479
1435
  }
1480
1436
  function scanLabeledTriviaEnd(input, cur, spec, state) {
1481
- const chars = charArmsFor(spec);
1437
+ const chars = spec.charArms;
1482
1438
  if (chars !== null) return charTriviaEnd(input, cur, chars);
1483
1439
  let pos = cur;
1484
1440
  let count = 0;
@@ -1496,9 +1452,9 @@ function scanLabeledTriviaEnd(input, cur, spec, state) {
1496
1452
  }
1497
1453
  function visitLabeledTrivia(input, cur, spec, state, visit) {
1498
1454
  if (spec.minRepeats > 1) return void 0;
1499
- const common = commonLabeledTriviaVisitor(spec);
1455
+ const common = spec.visitor;
1500
1456
  if (common !== null) return common(input, cur, visit);
1501
- const chars = charArmsFor(spec);
1457
+ const chars = spec.charArms;
1502
1458
  if (chars !== null) return charTriviaVisit(input, cur, chars, visit);
1503
1459
  let pos = cur;
1504
1460
  let count = 0;
@@ -1565,7 +1521,7 @@ function resolveAdjacencyKindMask(trivia2, kinds) {
1565
1521
  return mask;
1566
1522
  }
1567
1523
  function triviaKindMaskAt(input, pos, spec, state) {
1568
- const chars = charArmsFor(spec);
1524
+ const chars = spec.charArms;
1569
1525
  if (chars !== null) return charTriviaKindMask(input, pos, chars);
1570
1526
  let cur = pos;
1571
1527
  let mask = 0;
@@ -3279,6 +3235,23 @@ function notAdjacent(options) {
3279
3235
  );
3280
3236
  }
3281
3237
 
3238
+ // src/combinators/field-trivia.ts
3239
+ var LEAD = { at: -1 };
3240
+ var FIELD_LEADING_TRIVIA = 1;
3241
+ var FIELD_TRAILING_TRIVIA = 2;
3242
+ function triviaFieldCapture(name, value, input, start, end, leadFrom, trailEnd) {
3243
+ return {
3244
+ name,
3245
+ value,
3246
+ span: { start, end },
3247
+ leading: leadFrom >= 0 && leadFrom < start ? input.slice(leadFrom, start) : "",
3248
+ trailing: trailEnd > end ? input.slice(end, trailEnd) : ""
3249
+ };
3250
+ }
3251
+ function leadsTrivia(p) {
3252
+ return p._def.tag === "field" && p._def.leadingTrivia === true;
3253
+ }
3254
+
3282
3255
  // src/combinators/sequence.ts
3283
3256
  function sequence(...parsers) {
3284
3257
  let adjacency = null;
@@ -3294,6 +3267,10 @@ function sequence(...parsers) {
3294
3267
  (adjacency ??= Array.from({ length: parsers.length }, () => null))[i] = a;
3295
3268
  }
3296
3269
  const hasAdjacency = adjacency !== null;
3270
+ let leading = null;
3271
+ for (let i = 1; i < parsers.length; i++) {
3272
+ if (leadsTrivia(parsers[i])) (leading ??= Array.from({ length: parsers.length }, () => false))[i] = true;
3273
+ }
3297
3274
  const strictArity = !hasAdjacency && (parsers.length === 2 && !matchesEmpty(parsers[1]) || parsers.length === 3 && parsers.every((p) => !matchesEmpty(p))) ? parsers.length : 0;
3298
3275
  const meta = {
3299
3276
  // Union through the nullable prefix — a leading optional()/many() lets a later
@@ -3341,7 +3318,7 @@ function sequence(...parsers) {
3341
3318
  _tag: "sequence",
3342
3319
  _meta: meta,
3343
3320
  _def: def,
3344
- _parseScalar: hasAdjacency ? void 0 : parseScalar,
3321
+ _parseScalar: hasAdjacency || leading !== null ? void 0 : parseScalar,
3345
3322
  parse(input, pos, ctx) {
3346
3323
  const tolerant = ctx._tolerant === true;
3347
3324
  if (tolerant) {
@@ -3375,6 +3352,7 @@ function sequence(...parsers) {
3375
3352
  const scanTlog = deferredTrivia ? cstTlLen(ctx) : 0;
3376
3353
  const scanLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
3377
3354
  const scanRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
3355
+ if (leading?.[i] === true) LEAD.at = cur;
3378
3356
  const result = parsers[i].parse(input, termPos, ctx);
3379
3357
  if (!result.ok) return result;
3380
3358
  if (values !== void 0) values.push(result.value);
@@ -4350,6 +4328,7 @@ function unwrapSeparator(separator) {
4350
4328
  }
4351
4329
  function sepBy(combinator, separatorArg, opts = {}) {
4352
4330
  const { sep: separator, keep: keepSeparators } = unwrapSeparator(separatorArg);
4331
+ const separatorLeads = leadsTrivia(separator);
4353
4332
  const { min, max } = resolveBounds("sepBy()", opts);
4354
4333
  const trailing = opts.trailing ?? "forbid";
4355
4334
  const meta = {
@@ -4414,7 +4393,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
4414
4393
  // this option surface already; parity is held by test/parity, not by hope.
4415
4394
  ...keepSeparators ? { keepSeparators: true } : {}
4416
4395
  },
4417
- _parseScalar: keepSeparators ? void 0 : parseScalar,
4396
+ _parseScalar: keepSeparators || separatorLeads ? void 0 : parseScalar,
4418
4397
  parse(input, pos, ctx) {
4419
4398
  const first = combinator.parse(input, pos, ctx);
4420
4399
  const values = [];
@@ -4446,6 +4425,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
4446
4425
  sepPos = advanceTrivia(input, cur, ctx);
4447
4426
  }
4448
4427
  }
4428
+ if (separatorLeads) LEAD.at = cur;
4449
4429
  const sep2 = separator.parse(input, sepPos, ctx);
4450
4430
  if (!sep2.ok) {
4451
4431
  rollbackTrivia(ctx, loopMark);
@@ -4903,7 +4883,7 @@ function buildFieldMap(captures) {
4903
4883
  if (!captures?.length) return void 0;
4904
4884
  const out = {};
4905
4885
  for (const cap of captures) {
4906
- const entry = { value: cap.value, span: cap.span };
4886
+ const entry = cap.leading === void 0 ? { value: cap.value, span: cap.span } : { value: cap.value, span: cap.span, leading: cap.leading, trailing: cap.trailing };
4907
4887
  const current = out[cap.name];
4908
4888
  if (current === void 0) out[cap.name] = entry;
4909
4889
  else if (Array.isArray(current)) current.push(entry);
@@ -5135,16 +5115,41 @@ function label(name, combinator) {
5135
5115
  }
5136
5116
  };
5137
5117
  }
5138
- function field(name, combinator) {
5118
+ function field(name, combinator, opts) {
5119
+ const leadingTrivia = opts?.leadingTrivia === true;
5120
+ const trailingTrivia = opts?.trailingTrivia === true;
5121
+ if (!leadingTrivia && !trailingTrivia) {
5122
+ return {
5123
+ _tag: combinator._tag,
5124
+ _meta: combinator._meta,
5125
+ _def: { tag: "field", name, parser: combinator },
5126
+ parse(input, pos, ctx) {
5127
+ const result = combinator.parse(input, pos, ctx);
5128
+ if (!result.ok) return result;
5129
+ ctx._fields?.push({ name, value: result.value, span: result.span });
5130
+ return result;
5131
+ }
5132
+ };
5133
+ }
5139
5134
  return {
5140
5135
  _tag: combinator._tag,
5141
5136
  _meta: combinator._meta,
5142
- _def: { tag: "field", name, parser: combinator },
5137
+ _def: {
5138
+ tag: "field",
5139
+ name,
5140
+ parser: combinator,
5141
+ ...leadingTrivia ? { leadingTrivia: true } : {},
5142
+ ...trailingTrivia ? { trailingTrivia: true } : {}
5143
+ },
5143
5144
  parse(input, pos, ctx) {
5145
+ const leadFrom = LEAD.at;
5146
+ LEAD.at = -1;
5144
5147
  const result = combinator.parse(input, pos, ctx);
5145
5148
  if (!result.ok) return result;
5146
- ctx._fields?.push({ name, value: result.value, span: result.span });
5147
- return result;
5149
+ const end = result.span.end;
5150
+ const trailEnd = trailingTrivia && ctx.trivia ? consumeTrivia(input, end, ctx) : end;
5151
+ ctx._fields?.push(triviaFieldCapture(name, result.value, input, result.span.start, end, leadingTrivia ? leadFrom : -1, trailEnd));
5152
+ return trailEnd === end ? result : { ok: true, value: result.value, span: { start: result.span.start, end: trailEnd } };
5148
5153
  }
5149
5154
  };
5150
5155
  }
@@ -7206,6 +7211,16 @@ var Encoder = class {
7206
7211
  this.kIndex.set(key, i);
7207
7212
  return i;
7208
7213
  }
7214
+ fieldSpecIndex = /* @__PURE__ */ new Map();
7215
+ fieldSpecSlot(name, bits) {
7216
+ const key = JSON.stringify([name, bits]);
7217
+ const hit = this.fieldSpecIndex.get(key);
7218
+ if (hit !== void 0) return hit;
7219
+ const i = this.k.length;
7220
+ this.k.push([name, bits]);
7221
+ this.fieldSpecIndex.set(key, i);
7222
+ return i;
7223
+ }
7209
7224
  /**
7210
7225
  * A `notAdjacent({ kinds })` filter, pooled by its CONTENTS.
7211
7226
  *
@@ -7826,8 +7841,10 @@ var Encoder = class {
7826
7841
  for (let i = 0; i < arms.length; i++) this.code[head + 6 + i] = arms[i];
7827
7842
  return head;
7828
7843
  }
7829
- case "field":
7830
- return this.emit(OP_FIELD, this.constant(d.name), this.node(d.parser).ip);
7844
+ case "field": {
7845
+ const bits = (d.leadingTrivia === true ? FIELD_LEADING_TRIVIA : 0) | (d.trailingTrivia === true ? FIELD_TRAILING_TRIVIA : 0);
7846
+ return this.emit(OP_FIELD, bits === 0 ? this.constant(d.name) : this.fieldSpecSlot(d.name, bits), this.node(d.parser).ip);
7847
+ }
7831
7848
  case "lazy": {
7832
7849
  const refName = p._ruleName;
7833
7850
  const winner = refName === void 0 ? void 0 : this.winners?.[refName];
@@ -9500,6 +9517,26 @@ function leadingLiteralFamily(code, constants, ip, minDepth = 2, limit = 4) {
9500
9517
  };
9501
9518
  return walk(ip, 0);
9502
9519
  }
9520
+ function largeChoiceLiteralPretest(code, constants, armIp) {
9521
+ const child = leadingScalarTerminal(code, armIp, 2, true, true);
9522
+ if (child >= 0) {
9523
+ const spec = constants[code[child + 1]];
9524
+ if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) return [child];
9525
+ }
9526
+ const family = leadingLiteralFamily(code, constants, armIp);
9527
+ return family !== void 0 && family.length >= 2 && family.every((terminal) => {
9528
+ const value = constants[code[terminal + 1]];
9529
+ return typeof value === "string" && value.length >= 2;
9530
+ }) ? family : void 0;
9531
+ }
9532
+
9533
+ // src/table/field-spec.ts
9534
+ function fieldSpec(slot) {
9535
+ return Array.isArray(slot) ? { name: slot[0], bits: slot[1] } : { name: slot, bits: 0 };
9536
+ }
9537
+ function leadingTriviaFieldAt(code, k, ip) {
9538
+ return code[ip] === OP_FIELD && (fieldSpec(k[code[ip + 1]]).bits & FIELD_LEADING_TRIVIA) !== 0;
9539
+ }
9503
9540
 
9504
9541
  // src/table/emit-assembly.ts
9505
9542
  var Unemittable = class extends Error {
@@ -9574,7 +9611,11 @@ var EMITTED_PARAMS = [
9574
9611
  // Appended for old precompiled-factory ABI: old factories ignore it.
9575
9612
  "adjacencyHolds",
9576
9613
  // Appended for selected composite lexical programs; old factories ignore it.
9577
- "LEXPROG"
9614
+ "LEXPROG",
9615
+ // Appended for trivia-attributing fields (`field(…, { leadingTrivia })`);
9616
+ // old factories ignore them.
9617
+ "LEAD",
9618
+ "triviaFieldCapture"
9578
9619
  ];
9579
9620
  var RUNTIME_PRELUDE = `
9580
9621
  let _pfScan=null
@@ -9834,20 +9875,12 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
9834
9875
  if (child >= 0) scalarSpecs.add(code[child + 1]);
9835
9876
  continue;
9836
9877
  }
9837
- if (child >= 0) {
9838
- const spec = k[code[child + 1]];
9839
- if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
9840
- largeChoiceScalarSpecs.add(code[child + 1]);
9841
- continue;
9842
- }
9843
- }
9844
- const family = leadingLiteralFamily(code, k, armIp);
9845
- if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
9846
- const value = k[code[terminal + 1]];
9847
- return typeof value === "string" && value.length >= 2;
9848
- })) {
9849
- largeChoiceLiteralFamilies.set(armIp, family);
9878
+ const literals = largeChoiceLiteralPretest(code, k, armIp);
9879
+ if (literals !== void 0 && literals.length === 1 && literals[0] === child) {
9880
+ largeChoiceScalarSpecs.add(code[child + 1]);
9881
+ continue;
9850
9882
  }
9883
+ if (literals !== void 0) largeChoiceLiteralFamilies.set(armIp, literals);
9851
9884
  const sequence6 = leadingScalarSequence(code, armIp);
9852
9885
  if (sequence6 !== void 0 && (sequence6.trivia < 0 || swapLegal && t.triviaScan[sequence6.trivia] != null)) {
9853
9886
  largeChoiceScalarSequences.set(armIp, sequence6);
@@ -10271,14 +10304,31 @@ return v
10271
10304
  }`;
10272
10305
  }
10273
10306
  case OP_FIELD: {
10274
- const name = q(k[code[ip + 1]]);
10307
+ const spec = fieldSpec(k[code[ip + 1]]);
10308
+ const name = q(spec.name);
10275
10309
  const child = link(code[ip + 2]);
10276
- return `${head}
10310
+ if (spec.bits === 0) {
10311
+ return `${head}
10277
10312
  const v=${child}(input,pos,ctx)
10278
10313
  if(v===FAIL)return FAIL
10279
10314
  const f=ctx._fields
10280
10315
  if(f!==undefined)f.push({name:${name},value:v,span:{start:pos,end:EC.e}})
10281
10316
  return v
10317
+ }`;
10318
+ }
10319
+ const leading = (spec.bits & FIELD_LEADING_TRIVIA) !== 0;
10320
+ const trailing = (spec.bits & FIELD_TRAILING_TRIVIA) !== 0;
10321
+ return `${head}
10322
+ const lf=${leading ? "LEAD.at" : "-1"}
10323
+ LEAD.at=-1
10324
+ const v=${child}(input,pos,ctx)
10325
+ if(v===FAIL)return FAIL
10326
+ const e=EC.e
10327
+ const te=${trailing ? "ctx.trivia!==undefined?consumeTrivia(input,e,ctx):e" : "e"}
10328
+ const f=ctx._fields
10329
+ if(f!==undefined)f.push(triviaFieldCapture(${name},v,input,pos,e,lf,te))
10330
+ EC.e=te
10331
+ return v
10282
10332
  }`;
10283
10333
  }
10284
10334
  case OP_EXPECT: {
@@ -10574,7 +10624,10 @@ return v
10574
10624
  `if(!adjacencyHolds(input,cur,ctx,${negated ? "true" : "false"},${kinds})){ctx._fe=cur;ctx._fx=${expected};return FAIL}`,
10575
10625
  `${vn}=null`
10576
10626
  );
10577
- } else parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
10627
+ } else {
10628
+ const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
10629
+ parts.push(emitTerm(callee, vn, tmp(), L, skipFor(L)));
10630
+ }
10578
10631
  names.push(vn);
10579
10632
  }
10580
10633
  parts.push("EC.e=cur");
@@ -10974,7 +11027,7 @@ let sp=cur
10974
11027
  ${hasTrivia === "false" ? "" : hasTrivia === "true" ? `sp=${skip}(input,sp,ctx)
10975
11028
  ` : `if(hasTrivia)sp=${skip}(input,sp,ctx)
10976
11029
  `}ctx._fc=false
10977
- const sv=${sep2}(input,sp,ctx)
11030
+ ${sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp) ? "LEAD.at=cur\n" : ""}const sv=${sep2}(input,sp,ctx)
10978
11031
  if(sv===FAIL){
10979
11032
  ${rb}
10980
11033
  if(ctx._fc===true)return FAIL
@@ -12071,6 +12124,12 @@ function assemble(t, prog, cfg) {
12071
12124
  rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
12072
12125
  return cur;
12073
12126
  }
12127
+ function leadingFieldTerm(step, child, input, cur, ctx) {
12128
+ return step((i, p, c) => {
12129
+ LEAD.at = cur;
12130
+ return child(i, p, c);
12131
+ }, input, cur, ctx);
12132
+ }
12074
12133
  function committed3(c) {
12075
12134
  return c._fc === true;
12076
12135
  }
@@ -12708,12 +12767,27 @@ function assemble(t, prog, cfg) {
12708
12767
  };
12709
12768
  }
12710
12769
  case OP_FIELD: {
12711
- const name = k[code[ip + 1]];
12770
+ const { name, bits } = fieldSpec(k[code[ip + 1]]);
12712
12771
  const child = link(code[ip + 2]);
12772
+ if (bits === 0) {
12773
+ return (input, pos, ctx) => {
12774
+ const v = child(input, pos, ctx);
12775
+ if (v === FAIL) return FAIL;
12776
+ ctx._fields?.push({ name, value: v, span: { start: pos, end: EC.e } });
12777
+ return v;
12778
+ };
12779
+ }
12780
+ const leading = (bits & FIELD_LEADING_TRIVIA) !== 0;
12781
+ const trailing = (bits & FIELD_TRAILING_TRIVIA) !== 0;
12713
12782
  return (input, pos, ctx) => {
12783
+ const leadFrom = leading ? LEAD.at : -1;
12784
+ LEAD.at = -1;
12714
12785
  const v = child(input, pos, ctx);
12715
12786
  if (v === FAIL) return FAIL;
12716
- ctx._fields?.push({ name, value: v, span: { start: pos, end: EC.e } });
12787
+ const end = EC.e;
12788
+ const trailEnd = trailing && ctx.trivia !== void 0 ? consumeTrivia(input, end, ctx) : end;
12789
+ ctx._fields?.push(triviaFieldCapture(name, v, input, pos, end, leadFrom, trailEnd));
12790
+ EC.e = trailEnd;
12717
12791
  return v;
12718
12792
  };
12719
12793
  }
@@ -13147,6 +13221,12 @@ function assemble(t, prog, cfg) {
13147
13221
  const kidIp = code[base + i];
13148
13222
  if (code[kidIp] !== OP_ADJ) {
13149
13223
  const kid = link(kidIp);
13224
+ if (leadingTriviaFieldAt(code, k, kidIp)) {
13225
+ return (input, cur, ctx, inherited) => {
13226
+ ctx._sync = sync ?? inherited;
13227
+ return leadingFieldTerm(step, kid, input, cur, ctx);
13228
+ };
13229
+ }
13150
13230
  return (input, cur, ctx, inherited) => {
13151
13231
  ctx._sync = sync ?? inherited;
13152
13232
  return step(kid, input, cur, ctx);
@@ -13224,9 +13304,12 @@ function assemble(t, prog, cfg) {
13224
13304
  };
13225
13305
  }
13226
13306
  let hasAdj = false;
13227
- for (let i = 1; i < n; i++) if (code[code[base + i]] === OP_ADJ) {
13228
- hasAdj = true;
13229
- break;
13307
+ for (let i = 1; i < n; i++) {
13308
+ const kidIp = code[base + i];
13309
+ if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp)) {
13310
+ hasAdj = true;
13311
+ break;
13312
+ }
13230
13313
  }
13231
13314
  if (hasAdj) {
13232
13315
  const first2 = link(code[base]);
@@ -13234,6 +13317,9 @@ function assemble(t, prog, cfg) {
13234
13317
  const kidIp = code[base + i];
13235
13318
  if (code[kidIp] !== OP_ADJ) {
13236
13319
  const kid = link(kidIp);
13320
+ if (leadingTriviaFieldAt(code, k, kidIp)) {
13321
+ return (input, cur, ctx) => leadingFieldTerm(step, kid, input, cur, ctx);
13322
+ }
13237
13323
  return (input, cur, ctx) => step(kid, input, cur, ctx);
13238
13324
  }
13239
13325
  const negated = code[kidIp + 1] === 1;
@@ -13596,7 +13682,7 @@ function assemble(t, prog, cfg) {
13596
13682
  if (n === 2 || n === 3) {
13597
13683
  const a0 = link(code[base]), a1 = link(code[base + 1]);
13598
13684
  const a2 = n === 3 ? link(code[base + 2]) : void 0;
13599
- const predecide = !hostCst && !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
13685
+ const predecide = !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
13600
13686
  const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
13601
13687
  const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
13602
13688
  const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
@@ -13819,6 +13905,75 @@ function assemble(t, prog, cfg) {
13819
13905
  );
13820
13906
  };
13821
13907
  const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
13908
+ const pBit = [];
13909
+ const pRec = [];
13910
+ if (!REC && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
13911
+ for (let i = 0; i < n; i++) {
13912
+ for (const terminal of largeChoiceLiteralPretest(code, k, code[base + i]) ?? []) {
13913
+ pBit.push(1 << i);
13914
+ pRec.push(scalarFor(terminal));
13915
+ }
13916
+ }
13917
+ }
13918
+ const pn = pBit.length;
13919
+ if (pn !== 0) {
13920
+ return (input, pos, ctx) => {
13921
+ const c = lead(input, pos);
13922
+ const need = markCst(ctx);
13923
+ const mRaw = MRAW;
13924
+ const mTl = MTL;
13925
+ const mLv = MLV;
13926
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
13927
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
13928
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
13929
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
13930
+ if (c < 128) {
13931
+ const bits = mask[c < 0 ? 128 : c];
13932
+ let tested = 0;
13933
+ let hit = 0;
13934
+ for (let i = 0; i < pn; i++) {
13935
+ const b = pBit[i];
13936
+ if ((bits & b) === 0 || (hit & b) !== 0) continue;
13937
+ tested |= b;
13938
+ if (pRec[i](input, pos) >= 0) hit |= b;
13939
+ }
13940
+ return masked(
13941
+ input,
13942
+ pos,
13943
+ ctx,
13944
+ bits & (~tested | hit),
13945
+ need,
13946
+ mRaw,
13947
+ mTl,
13948
+ mLv,
13949
+ mFl,
13950
+ mEr,
13951
+ mLog,
13952
+ mRoot,
13953
+ void 0,
13954
+ 0,
13955
+ pos
13956
+ );
13957
+ }
13958
+ return general(
13959
+ input,
13960
+ pos,
13961
+ ctx,
13962
+ c,
13963
+ need,
13964
+ mRaw,
13965
+ mTl,
13966
+ mLv,
13967
+ mFl,
13968
+ mEr,
13969
+ mLog,
13970
+ mRoot,
13971
+ void 0,
13972
+ 0,
13973
+ pos
13974
+ );
13975
+ };
13976
+ }
13822
13977
  return (input, pos, ctx) => {
13823
13978
  const c = lead(input, pos);
13824
13979
  const need = markCst(ctx);
@@ -13980,6 +14135,7 @@ function assemble(t, prog, cfg) {
13980
14135
  const max = code[ip + 3];
13981
14136
  const sepIp = code[ip + 4];
13982
14137
  const sep2 = sepIp >= 0 ? link(sepIp) : void 0;
14138
+ const sepLeads = sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp);
13983
14139
  const flags = code[ip + 5];
13984
14140
  const keepSeparators = (flags & 2) !== 0;
13985
14141
  const trailingAllowed = (flags & 1) !== 0;
@@ -14019,6 +14175,7 @@ function assemble(t, prog, cfg) {
14019
14175
  let sp = cur;
14020
14176
  if (hasTrivia) sp = skipTrivia(input, sp, ctx);
14021
14177
  ctx._fc = false;
14178
+ if (sepLeads) LEAD.at = cur;
14022
14179
  const sv = sep2(input, sp, ctx);
14023
14180
  if (sv === FAIL) {
14024
14181
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
@@ -14108,6 +14265,7 @@ function assemble(t, prog, cfg) {
14108
14265
  let sp = cur;
14109
14266
  if (hasTrivia) sp = skipTrivia(input, sp, ctx);
14110
14267
  ctx._fc = false;
14268
+ if (sepLeads) LEAD.at = cur;
14111
14269
  const sv = sep2(input, sp, ctx);
14112
14270
  if (sv === FAIL) {
14113
14271
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
@@ -14430,20 +14588,9 @@ function assemble(t, prog, cfg) {
14430
14588
  if (child >= 0) scalarFor(child);
14431
14589
  continue;
14432
14590
  }
14433
- if (child >= 0) {
14434
- const spec = k[code[child + 1]];
14435
- if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
14436
- scalarFor(child);
14437
- continue;
14438
- }
14439
- }
14440
- const family = leadingLiteralFamily(code, k, armIp);
14441
- if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
14442
- const value = k[code[terminal + 1]];
14443
- return typeof value === "string" && value.length >= 2;
14444
- })) {
14445
- for (const terminal of family) scalarFor(terminal);
14446
- }
14591
+ const literals = largeChoiceLiteralPretest(code, k, armIp);
14592
+ if (literals !== void 0) for (const terminal of literals) scalarFor(terminal);
14593
+ if (literals !== void 0 && literals.length === 1 && literals[0] === child) continue;
14447
14594
  const sequence6 = leadingScalarSequence(code, armIp);
14448
14595
  if (sequence6 !== void 0 && (sequence6.trivia < 0 || triviaScan[sequence6.trivia] != null)) {
14449
14596
  for (const terminal of sequence6.terminals) scalarFor(terminal);
@@ -14509,7 +14656,9 @@ function assemble(t, prog, cfg) {
14509
14656
  scanTriviaCompact,
14510
14657
  t.lex,
14511
14658
  adjacencyHolds,
14512
- t.lexPrograms
14659
+ t.lexPrograms,
14660
+ LEAD,
14661
+ triviaFieldCapture
14513
14662
  );
14514
14663
  emitReached = new Set(pre.reached);
14515
14664
  }
@@ -14591,7 +14740,9 @@ function assemble(t, prog, cfg) {
14591
14740
  scanTriviaCompact,
14592
14741
  t.lex,
14593
14742
  adjacencyHolds,
14594
- t.lexPrograms
14743
+ t.lexPrograms,
14744
+ LEAD,
14745
+ triviaFieldCapture
14595
14746
  );
14596
14747
  emitReached = em.reached;
14597
14748
  } catch (e) {
@@ -14767,7 +14918,9 @@ var AssemblyCache = class {
14767
14918
  return made;
14768
14919
  }
14769
14920
  };
14770
- function tableRules(source, artifactMetadata = {}) {
14921
+ function tableRules(source, metadataOrEntry = {}) {
14922
+ const entry = typeof metadataOrEntry === "string" ? metadataOrEntry : void 0;
14923
+ const artifactMetadata = typeof metadataOrEntry === "string" ? {} : metadataOrEntry;
14771
14924
  const prog = expandCompact(source);
14772
14925
  const resolved = resolveTable(prog);
14773
14926
  const cache = new AssemblyCache(prog, resolved);
@@ -14775,7 +14928,7 @@ function tableRules(source, artifactMetadata = {}) {
14775
14928
  const skipOf = prog.scanSkipOf;
14776
14929
  let last;
14777
14930
  let selected;
14778
- return stampRuleMap(prog, {
14931
+ const map = stampRuleMap(prog, {
14779
14932
  runRule: (ri, input, pos, ctx) => {
14780
14933
  const a = selected ?? cache.forCtx(ctx);
14781
14934
  selected = void 0;
@@ -14796,6 +14949,9 @@ function tableRules(source, artifactMetadata = {}) {
14796
14949
  return a.scanSkip[skipOf?.[ri] ?? -1];
14797
14950
  }
14798
14951
  }, artifactMetadata, resolved);
14952
+ if (entry === void 0) return map;
14953
+ if (!Object.hasOwn(map, entry)) throw new Error(`tableRules: the program has no rule ${JSON.stringify(entry)}`);
14954
+ return map[entry];
14799
14955
  }
14800
14956
 
14801
14957
  // src/table/emit.ts
@@ -14961,11 +15117,15 @@ function emitTableExpression(prog, opts = {}) {
14961
15117
  const entry = opts.entry === void 0 ? "grammar" : opts.entry;
14962
15118
  const ref2 = opts.runtimeRef ?? "tableRules";
14963
15119
  const fns = opts.fnSources ?? prog.fns.map(() => "() => {}");
14964
- const close = `}${opts.metadataSource === void 0 ? "" : `,${opts.metadataSource}`})`;
15120
+ const meta = opts.metadataSource;
15121
+ if (entry !== null && meta !== void 0) {
15122
+ throw new Error("emitTableExpression: metadataSource is for the rule-map form (entry: null); a single entry carries none");
15123
+ }
15124
+ const tail = entry !== null ? `,${jsString(entry)}` : meta === void 0 ? "" : `,${meta}`;
14965
15125
  return [
14966
15126
  `/* @__PURE__ */ ${ref2}({`,
14967
15127
  ...programFields(prog, fns, opts),
14968
- entry === null ? close : `${close}[${jsString(entry)}]`
15128
+ `}${tail})`
14969
15129
  ].join("\n");
14970
15130
  }
14971
15131
 
@@ -15143,7 +15303,7 @@ function payloadKey(p, d) {
15143
15303
  case "label":
15144
15304
  return `label\0${d.label}`;
15145
15305
  case "field":
15146
- return `field\0${d.name}`;
15306
+ return `field\0${d.name}\0${d.leadingTrivia === true}\0${d.trailingTrivia === true}`;
15147
15307
  case "node":
15148
15308
  return `node\0${d.type ?? ""}\0${d.unwrap === true}\0${d.collapse === true}\0${fnKey(d.buildSrc, d.build)}`;
15149
15309
  case "transform":
@@ -17082,7 +17242,7 @@ ${outerDecls.map((d) => " " + d).join("\n")}
17082
17242
  case "label":
17083
17243
  return `label(${JSON.stringify(def.label)}, ${kid(def.parser)})`;
17084
17244
  case "field":
17085
- return `field(${JSON.stringify(def.name)}, ${kid(def.parser)})`;
17245
+ return `field(${JSON.stringify(def.name)}, ${kid(def.parser)}${fieldOptionsSrc(def)})`;
17086
17246
  case "expect":
17087
17247
  return `expect(${kid(def.parser)}${def.label !== void 0 ? `, ${JSON.stringify(def.label)}` : ""})`;
17088
17248
  case "scanTo":
@@ -17145,9 +17305,13 @@ ${outerDecls.map((d) => " " + d).join("\n")}
17145
17305
  }
17146
17306
  }
17147
17307
  };
17308
+ function fieldOptionsSrc(def) {
17309
+ if (def.leadingTrivia !== true && def.trailingTrivia !== true) return "";
17310
+ return `, { ${[def.leadingTrivia === true ? "leadingTrivia: true" : "", def.trailingTrivia === true ? "trailingTrivia: true" : ""].filter(Boolean).join(", ")} }`;
17311
+ }
17148
17312
 
17149
17313
  // src/version.ts
17150
- var PARSEMAN_VERSION = "0.53.0";
17314
+ var PARSEMAN_VERSION = "0.54.0";
17151
17315
 
17152
17316
  // src/compiler/compile-linkable-table.ts
17153
17317
  function isLocal(rule) {
@@ -17661,7 +17825,7 @@ var SUPPORTED = {
17661
17825
  a[0]
17662
17826
  ),
17663
17827
  label: (...a) => label(a[0], a[1]),
17664
- field: (...a) => field(a[0], a[1]),
17828
+ field: (...a) => field(a[0], a[1], a[2]),
17665
17829
  noTrivia: (...a) => noTrivia(a[0]),
17666
17830
  token: (...a) => token(a[0]),
17667
17831
  // `routed(fallback)` — the fallback must be forwarded. A zero-arg entry here read