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
@@ -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];
@@ -7859,6 +7876,9 @@ var Encoder = class {
7859
7876
  this.expected([adjacencyExpected(d)])
7860
7877
  );
7861
7878
  case "withCtx": {
7879
+ if (typeof d.extra === "function") {
7880
+ return this.emit(OP_WITHCTX, ~this.fn(d.extra, d.extraSrc ?? null), this.node(d.parser).ip);
7881
+ }
7862
7882
  if (!emittableConst(d.extra)) {
7863
7883
  this.runtimeOnly.add("withCtx(extra) \u2014 the state object is not serialisable");
7864
7884
  }
@@ -9500,6 +9520,26 @@ function leadingLiteralFamily(code, constants, ip, minDepth = 2, limit = 4) {
9500
9520
  };
9501
9521
  return walk(ip, 0);
9502
9522
  }
9523
+ function largeChoiceLiteralPretest(code, constants, armIp) {
9524
+ const child = leadingScalarTerminal(code, armIp, 2, true, true);
9525
+ if (child >= 0) {
9526
+ const spec = constants[code[child + 1]];
9527
+ if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) return [child];
9528
+ }
9529
+ const family = leadingLiteralFamily(code, constants, armIp);
9530
+ return family !== void 0 && family.length >= 2 && family.every((terminal) => {
9531
+ const value = constants[code[terminal + 1]];
9532
+ return typeof value === "string" && value.length >= 2;
9533
+ }) ? family : void 0;
9534
+ }
9535
+
9536
+ // src/table/field-spec.ts
9537
+ function fieldSpec(slot) {
9538
+ return Array.isArray(slot) ? { name: slot[0], bits: slot[1] } : { name: slot, bits: 0 };
9539
+ }
9540
+ function leadingTriviaFieldAt(code, k, ip) {
9541
+ return code[ip] === OP_FIELD && (fieldSpec(k[code[ip + 1]]).bits & FIELD_LEADING_TRIVIA) !== 0;
9542
+ }
9503
9543
 
9504
9544
  // src/table/emit-assembly.ts
9505
9545
  var Unemittable = class extends Error {
@@ -9574,7 +9614,11 @@ var EMITTED_PARAMS = [
9574
9614
  // Appended for old precompiled-factory ABI: old factories ignore it.
9575
9615
  "adjacencyHolds",
9576
9616
  // Appended for selected composite lexical programs; old factories ignore it.
9577
- "LEXPROG"
9617
+ "LEXPROG",
9618
+ // Appended for trivia-attributing fields (`field(…, { leadingTrivia })`);
9619
+ // old factories ignore them.
9620
+ "LEAD",
9621
+ "triviaFieldCapture"
9578
9622
  ];
9579
9623
  var RUNTIME_PRELUDE = `
9580
9624
  let _pfScan=null
@@ -9834,20 +9878,12 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
9834
9878
  if (child >= 0) scalarSpecs.add(code[child + 1]);
9835
9879
  continue;
9836
9880
  }
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);
9881
+ const literals = largeChoiceLiteralPretest(code, k, armIp);
9882
+ if (literals !== void 0 && literals.length === 1 && literals[0] === child) {
9883
+ largeChoiceScalarSpecs.add(code[child + 1]);
9884
+ continue;
9850
9885
  }
9886
+ if (literals !== void 0) largeChoiceLiteralFamilies.set(armIp, literals);
9851
9887
  const sequence6 = leadingScalarSequence(code, armIp);
9852
9888
  if (sequence6 !== void 0 && (sequence6.trivia < 0 || swapLegal && t.triviaScan[sequence6.trivia] != null)) {
9853
9889
  largeChoiceScalarSequences.set(armIp, sequence6);
@@ -10271,14 +10307,31 @@ return v
10271
10307
  }`;
10272
10308
  }
10273
10309
  case OP_FIELD: {
10274
- const name = q(k[code[ip + 1]]);
10310
+ const spec = fieldSpec(k[code[ip + 1]]);
10311
+ const name = q(spec.name);
10275
10312
  const child = link(code[ip + 2]);
10276
- return `${head}
10313
+ if (spec.bits === 0) {
10314
+ return `${head}
10277
10315
  const v=${child}(input,pos,ctx)
10278
10316
  if(v===FAIL)return FAIL
10279
10317
  const f=ctx._fields
10280
10318
  if(f!==undefined)f.push({name:${name},value:v,span:{start:pos,end:EC.e}})
10281
10319
  return v
10320
+ }`;
10321
+ }
10322
+ const leading = (spec.bits & FIELD_LEADING_TRIVIA) !== 0;
10323
+ const trailing = (spec.bits & FIELD_TRAILING_TRIVIA) !== 0;
10324
+ return `${head}
10325
+ const lf=${leading ? "LEAD.at" : "-1"}
10326
+ LEAD.at=-1
10327
+ const v=${child}(input,pos,ctx)
10328
+ if(v===FAIL)return FAIL
10329
+ const e=EC.e
10330
+ const te=${trailing ? "ctx.trivia!==undefined?consumeTrivia(input,e,ctx):e" : "e"}
10331
+ const f=ctx._fields
10332
+ if(f!==undefined)f.push(triviaFieldCapture(${name},v,input,pos,e,lf,te))
10333
+ EC.e=te
10334
+ return v
10282
10335
  }`;
10283
10336
  }
10284
10337
  case OP_EXPECT: {
@@ -10574,7 +10627,10 @@ return v
10574
10627
  `if(!adjacencyHolds(input,cur,ctx,${negated ? "true" : "false"},${kinds})){ctx._fe=cur;ctx._fx=${expected};return FAIL}`,
10575
10628
  `${vn}=null`
10576
10629
  );
10577
- } else parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
10630
+ } else {
10631
+ const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
10632
+ parts.push(emitTerm(callee, vn, tmp(), L, skipFor(L)));
10633
+ }
10578
10634
  names.push(vn);
10579
10635
  }
10580
10636
  parts.push("EC.e=cur");
@@ -10974,7 +11030,7 @@ let sp=cur
10974
11030
  ${hasTrivia === "false" ? "" : hasTrivia === "true" ? `sp=${skip}(input,sp,ctx)
10975
11031
  ` : `if(hasTrivia)sp=${skip}(input,sp,ctx)
10976
11032
  `}ctx._fc=false
10977
- const sv=${sep2}(input,sp,ctx)
11033
+ ${sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp) ? "LEAD.at=cur\n" : ""}const sv=${sep2}(input,sp,ctx)
10978
11034
  if(sv===FAIL){
10979
11035
  ${rb}
10980
11036
  if(ctx._fc===true)return FAIL
@@ -12071,6 +12127,12 @@ function assemble(t, prog, cfg) {
12071
12127
  rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
12072
12128
  return cur;
12073
12129
  }
12130
+ function leadingFieldTerm(step, child, input, cur, ctx) {
12131
+ return step((i, p, c) => {
12132
+ LEAD.at = cur;
12133
+ return child(i, p, c);
12134
+ }, input, cur, ctx);
12135
+ }
12074
12136
  function committed3(c) {
12075
12137
  return c._fc === true;
12076
12138
  }
@@ -12708,12 +12770,27 @@ function assemble(t, prog, cfg) {
12708
12770
  };
12709
12771
  }
12710
12772
  case OP_FIELD: {
12711
- const name = k[code[ip + 1]];
12773
+ const { name, bits } = fieldSpec(k[code[ip + 1]]);
12712
12774
  const child = link(code[ip + 2]);
12775
+ if (bits === 0) {
12776
+ return (input, pos, ctx) => {
12777
+ const v = child(input, pos, ctx);
12778
+ if (v === FAIL) return FAIL;
12779
+ ctx._fields?.push({ name, value: v, span: { start: pos, end: EC.e } });
12780
+ return v;
12781
+ };
12782
+ }
12783
+ const leading = (bits & FIELD_LEADING_TRIVIA) !== 0;
12784
+ const trailing = (bits & FIELD_TRAILING_TRIVIA) !== 0;
12713
12785
  return (input, pos, ctx) => {
12786
+ const leadFrom = leading ? LEAD.at : -1;
12787
+ LEAD.at = -1;
12714
12788
  const v = child(input, pos, ctx);
12715
12789
  if (v === FAIL) return FAIL;
12716
- ctx._fields?.push({ name, value: v, span: { start: pos, end: EC.e } });
12790
+ const end = EC.e;
12791
+ const trailEnd = trailing && ctx.trivia !== void 0 ? consumeTrivia(input, end, ctx) : end;
12792
+ ctx._fields?.push(triviaFieldCapture(name, v, input, pos, end, leadFrom, trailEnd));
12793
+ EC.e = trailEnd;
12717
12794
  return v;
12718
12795
  };
12719
12796
  }
@@ -12742,8 +12819,21 @@ function assemble(t, prog, cfg) {
12742
12819
  };
12743
12820
  }
12744
12821
  case OP_WITHCTX: {
12745
- const extra = k[code[ip + 1]];
12822
+ const ki = code[ip + 1];
12746
12823
  const child = link(code[ip + 2]);
12824
+ if (ki < 0) {
12825
+ const derive2 = fns[~ki];
12826
+ return (input, pos, ctx) => {
12827
+ const saved = ctx.state;
12828
+ ctx.state = derive2(saved);
12829
+ try {
12830
+ return child(input, pos, ctx);
12831
+ } finally {
12832
+ ctx.state = saved;
12833
+ }
12834
+ };
12835
+ }
12836
+ const extra = k[ki];
12747
12837
  return (input, pos, ctx) => {
12748
12838
  const saved = ctx.state;
12749
12839
  ctx.state = extra;
@@ -13147,6 +13237,12 @@ function assemble(t, prog, cfg) {
13147
13237
  const kidIp = code[base + i];
13148
13238
  if (code[kidIp] !== OP_ADJ) {
13149
13239
  const kid = link(kidIp);
13240
+ if (leadingTriviaFieldAt(code, k, kidIp)) {
13241
+ return (input, cur, ctx, inherited) => {
13242
+ ctx._sync = sync ?? inherited;
13243
+ return leadingFieldTerm(step, kid, input, cur, ctx);
13244
+ };
13245
+ }
13150
13246
  return (input, cur, ctx, inherited) => {
13151
13247
  ctx._sync = sync ?? inherited;
13152
13248
  return step(kid, input, cur, ctx);
@@ -13224,9 +13320,12 @@ function assemble(t, prog, cfg) {
13224
13320
  };
13225
13321
  }
13226
13322
  let hasAdj = false;
13227
- for (let i = 1; i < n; i++) if (code[code[base + i]] === OP_ADJ) {
13228
- hasAdj = true;
13229
- break;
13323
+ for (let i = 1; i < n; i++) {
13324
+ const kidIp = code[base + i];
13325
+ if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp)) {
13326
+ hasAdj = true;
13327
+ break;
13328
+ }
13230
13329
  }
13231
13330
  if (hasAdj) {
13232
13331
  const first2 = link(code[base]);
@@ -13234,6 +13333,9 @@ function assemble(t, prog, cfg) {
13234
13333
  const kidIp = code[base + i];
13235
13334
  if (code[kidIp] !== OP_ADJ) {
13236
13335
  const kid = link(kidIp);
13336
+ if (leadingTriviaFieldAt(code, k, kidIp)) {
13337
+ return (input, cur, ctx) => leadingFieldTerm(step, kid, input, cur, ctx);
13338
+ }
13237
13339
  return (input, cur, ctx) => step(kid, input, cur, ctx);
13238
13340
  }
13239
13341
  const negated = code[kidIp + 1] === 1;
@@ -13596,7 +13698,7 @@ function assemble(t, prog, cfg) {
13596
13698
  if (n === 2 || n === 3) {
13597
13699
  const a0 = link(code[base]), a1 = link(code[base + 1]);
13598
13700
  const a2 = n === 3 ? link(code[base + 2]) : void 0;
13599
- const predecide = !hostCst && !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
13701
+ const predecide = !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
13600
13702
  const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
13601
13703
  const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
13602
13704
  const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
@@ -13819,6 +13921,75 @@ function assemble(t, prog, cfg) {
13819
13921
  );
13820
13922
  };
13821
13923
  const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
13924
+ const pBit = [];
13925
+ const pRec = [];
13926
+ if (!REC && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
13927
+ for (let i = 0; i < n; i++) {
13928
+ for (const terminal of largeChoiceLiteralPretest(code, k, code[base + i]) ?? []) {
13929
+ pBit.push(1 << i);
13930
+ pRec.push(scalarFor(terminal));
13931
+ }
13932
+ }
13933
+ }
13934
+ const pn = pBit.length;
13935
+ if (pn !== 0) {
13936
+ return (input, pos, ctx) => {
13937
+ const c = lead(input, pos);
13938
+ const need = markCst(ctx);
13939
+ const mRaw = MRAW;
13940
+ const mTl = MTL;
13941
+ const mLv = MLV;
13942
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
13943
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
13944
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
13945
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
13946
+ if (c < 128) {
13947
+ const bits = mask[c < 0 ? 128 : c];
13948
+ let tested = 0;
13949
+ let hit = 0;
13950
+ for (let i = 0; i < pn; i++) {
13951
+ const b = pBit[i];
13952
+ if ((bits & b) === 0 || (hit & b) !== 0) continue;
13953
+ tested |= b;
13954
+ if (pRec[i](input, pos) >= 0) hit |= b;
13955
+ }
13956
+ return masked(
13957
+ input,
13958
+ pos,
13959
+ ctx,
13960
+ bits & (~tested | hit),
13961
+ need,
13962
+ mRaw,
13963
+ mTl,
13964
+ mLv,
13965
+ mFl,
13966
+ mEr,
13967
+ mLog,
13968
+ mRoot,
13969
+ void 0,
13970
+ 0,
13971
+ pos
13972
+ );
13973
+ }
13974
+ return general(
13975
+ input,
13976
+ pos,
13977
+ ctx,
13978
+ c,
13979
+ need,
13980
+ mRaw,
13981
+ mTl,
13982
+ mLv,
13983
+ mFl,
13984
+ mEr,
13985
+ mLog,
13986
+ mRoot,
13987
+ void 0,
13988
+ 0,
13989
+ pos
13990
+ );
13991
+ };
13992
+ }
13822
13993
  return (input, pos, ctx) => {
13823
13994
  const c = lead(input, pos);
13824
13995
  const need = markCst(ctx);
@@ -13980,6 +14151,7 @@ function assemble(t, prog, cfg) {
13980
14151
  const max = code[ip + 3];
13981
14152
  const sepIp = code[ip + 4];
13982
14153
  const sep2 = sepIp >= 0 ? link(sepIp) : void 0;
14154
+ const sepLeads = sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp);
13983
14155
  const flags = code[ip + 5];
13984
14156
  const keepSeparators = (flags & 2) !== 0;
13985
14157
  const trailingAllowed = (flags & 1) !== 0;
@@ -14019,6 +14191,7 @@ function assemble(t, prog, cfg) {
14019
14191
  let sp = cur;
14020
14192
  if (hasTrivia) sp = skipTrivia(input, sp, ctx);
14021
14193
  ctx._fc = false;
14194
+ if (sepLeads) LEAD.at = cur;
14022
14195
  const sv = sep2(input, sp, ctx);
14023
14196
  if (sv === FAIL) {
14024
14197
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
@@ -14108,6 +14281,7 @@ function assemble(t, prog, cfg) {
14108
14281
  let sp = cur;
14109
14282
  if (hasTrivia) sp = skipTrivia(input, sp, ctx);
14110
14283
  ctx._fc = false;
14284
+ if (sepLeads) LEAD.at = cur;
14111
14285
  const sv = sep2(input, sp, ctx);
14112
14286
  if (sv === FAIL) {
14113
14287
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
@@ -14430,20 +14604,9 @@ function assemble(t, prog, cfg) {
14430
14604
  if (child >= 0) scalarFor(child);
14431
14605
  continue;
14432
14606
  }
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
- }
14607
+ const literals = largeChoiceLiteralPretest(code, k, armIp);
14608
+ if (literals !== void 0) for (const terminal of literals) scalarFor(terminal);
14609
+ if (literals !== void 0 && literals.length === 1 && literals[0] === child) continue;
14447
14610
  const sequence6 = leadingScalarSequence(code, armIp);
14448
14611
  if (sequence6 !== void 0 && (sequence6.trivia < 0 || triviaScan[sequence6.trivia] != null)) {
14449
14612
  for (const terminal of sequence6.terminals) scalarFor(terminal);
@@ -14509,7 +14672,9 @@ function assemble(t, prog, cfg) {
14509
14672
  scanTriviaCompact,
14510
14673
  t.lex,
14511
14674
  adjacencyHolds,
14512
- t.lexPrograms
14675
+ t.lexPrograms,
14676
+ LEAD,
14677
+ triviaFieldCapture
14513
14678
  );
14514
14679
  emitReached = new Set(pre.reached);
14515
14680
  }
@@ -14591,7 +14756,9 @@ function assemble(t, prog, cfg) {
14591
14756
  scanTriviaCompact,
14592
14757
  t.lex,
14593
14758
  adjacencyHolds,
14594
- t.lexPrograms
14759
+ t.lexPrograms,
14760
+ LEAD,
14761
+ triviaFieldCapture
14595
14762
  );
14596
14763
  emitReached = em.reached;
14597
14764
  } catch (e) {
@@ -14767,7 +14934,9 @@ var AssemblyCache = class {
14767
14934
  return made;
14768
14935
  }
14769
14936
  };
14770
- function tableRules(source, artifactMetadata = {}) {
14937
+ function tableRules(source, metadataOrEntry = {}) {
14938
+ const entry = typeof metadataOrEntry === "string" ? metadataOrEntry : void 0;
14939
+ const artifactMetadata = typeof metadataOrEntry === "string" ? {} : metadataOrEntry;
14771
14940
  const prog = expandCompact(source);
14772
14941
  const resolved = resolveTable(prog);
14773
14942
  const cache = new AssemblyCache(prog, resolved);
@@ -14775,7 +14944,7 @@ function tableRules(source, artifactMetadata = {}) {
14775
14944
  const skipOf = prog.scanSkipOf;
14776
14945
  let last;
14777
14946
  let selected;
14778
- return stampRuleMap(prog, {
14947
+ const map = stampRuleMap(prog, {
14779
14948
  runRule: (ri, input, pos, ctx) => {
14780
14949
  const a = selected ?? cache.forCtx(ctx);
14781
14950
  selected = void 0;
@@ -14796,6 +14965,9 @@ function tableRules(source, artifactMetadata = {}) {
14796
14965
  return a.scanSkip[skipOf?.[ri] ?? -1];
14797
14966
  }
14798
14967
  }, artifactMetadata, resolved);
14968
+ if (entry === void 0) return map;
14969
+ if (!Object.hasOwn(map, entry)) throw new Error(`tableRules: the program has no rule ${JSON.stringify(entry)}`);
14970
+ return map[entry];
14799
14971
  }
14800
14972
 
14801
14973
  // src/table/emit.ts
@@ -14961,11 +15133,15 @@ function emitTableExpression(prog, opts = {}) {
14961
15133
  const entry = opts.entry === void 0 ? "grammar" : opts.entry;
14962
15134
  const ref2 = opts.runtimeRef ?? "tableRules";
14963
15135
  const fns = opts.fnSources ?? prog.fns.map(() => "() => {}");
14964
- const close = `}${opts.metadataSource === void 0 ? "" : `,${opts.metadataSource}`})`;
15136
+ const meta = opts.metadataSource;
15137
+ if (entry !== null && meta !== void 0) {
15138
+ throw new Error("emitTableExpression: metadataSource is for the rule-map form (entry: null); a single entry carries none");
15139
+ }
15140
+ const tail = entry !== null ? `,${jsString(entry)}` : meta === void 0 ? "" : `,${meta}`;
14965
15141
  return [
14966
15142
  `/* @__PURE__ */ ${ref2}({`,
14967
15143
  ...programFields(prog, fns, opts),
14968
- entry === null ? close : `${close}[${jsString(entry)}]`
15144
+ `}${tail})`
14969
15145
  ].join("\n");
14970
15146
  }
14971
15147
 
@@ -15143,7 +15319,7 @@ function payloadKey(p, d) {
15143
15319
  case "label":
15144
15320
  return `label\0${d.label}`;
15145
15321
  case "field":
15146
- return `field\0${d.name}`;
15322
+ return `field\0${d.name}\0${d.leadingTrivia === true}\0${d.trailingTrivia === true}`;
15147
15323
  case "node":
15148
15324
  return `node\0${d.type ?? ""}\0${d.unwrap === true}\0${d.collapse === true}\0${fnKey(d.buildSrc, d.build)}`;
15149
15325
  case "transform":
@@ -17082,7 +17258,7 @@ ${outerDecls.map((d) => " " + d).join("\n")}
17082
17258
  case "label":
17083
17259
  return `label(${JSON.stringify(def.label)}, ${kid(def.parser)})`;
17084
17260
  case "field":
17085
- return `field(${JSON.stringify(def.name)}, ${kid(def.parser)})`;
17261
+ return `field(${JSON.stringify(def.name)}, ${kid(def.parser)}${fieldOptionsSrc(def)})`;
17086
17262
  case "expect":
17087
17263
  return `expect(${kid(def.parser)}${def.label !== void 0 ? `, ${JSON.stringify(def.label)}` : ""})`;
17088
17264
  case "scanTo":
@@ -17145,9 +17321,13 @@ ${outerDecls.map((d) => " " + d).join("\n")}
17145
17321
  }
17146
17322
  }
17147
17323
  };
17324
+ function fieldOptionsSrc(def) {
17325
+ if (def.leadingTrivia !== true && def.trailingTrivia !== true) return "";
17326
+ return `, { ${[def.leadingTrivia === true ? "leadingTrivia: true" : "", def.trailingTrivia === true ? "trailingTrivia: true" : ""].filter(Boolean).join(", ")} }`;
17327
+ }
17148
17328
 
17149
17329
  // src/version.ts
17150
- var PARSEMAN_VERSION = "0.53.0";
17330
+ var PARSEMAN_VERSION = "0.55.0";
17151
17331
 
17152
17332
  // src/compiler/compile-linkable-table.ts
17153
17333
  function isLocal(rule) {
@@ -17266,19 +17446,28 @@ function withCtx(extra, combinator) {
17266
17446
  canMatchNewline: combinator._meta.canMatchNewline,
17267
17447
  isTrivia: false
17268
17448
  };
17449
+ const parse2 = typeof extra === "function" ? (input, pos, ctx) => {
17450
+ const saved = ctx.state;
17451
+ ctx.state = extra(saved);
17452
+ try {
17453
+ return combinator.parse(input, pos, ctx);
17454
+ } finally {
17455
+ ctx.state = saved;
17456
+ }
17457
+ } : (input, pos, ctx) => {
17458
+ const saved = ctx.state;
17459
+ ctx.state = extra;
17460
+ try {
17461
+ return combinator.parse(input, pos, ctx);
17462
+ } finally {
17463
+ ctx.state = saved;
17464
+ }
17465
+ };
17269
17466
  return {
17270
17467
  _tag: "withCtx",
17271
17468
  _meta: meta,
17272
17469
  _def: { tag: "withCtx", extra, parser: combinator },
17273
- parse(input, pos, ctx) {
17274
- const saved = ctx.state;
17275
- ctx.state = extra;
17276
- try {
17277
- return combinator.parse(input, pos, ctx);
17278
- } finally {
17279
- ctx.state = saved;
17280
- }
17281
- }
17470
+ parse: parse2
17282
17471
  };
17283
17472
  }
17284
17473
 
@@ -17557,6 +17746,7 @@ function stripTsFromSource(node2, code) {
17557
17746
  var UnevaluatedExtra = class {
17558
17747
  };
17559
17748
  var UNEVALUATED_EXTRA = new UnevaluatedExtra();
17749
+ var DERIVE_STAND_IN = (state) => state;
17560
17750
  var _reducers = null;
17561
17751
  var _entrySource = null;
17562
17752
  function setReducerResolver(r, entrySource = null) {
@@ -17661,7 +17851,7 @@ var SUPPORTED = {
17661
17851
  a[0]
17662
17852
  ),
17663
17853
  label: (...a) => label(a[0], a[1]),
17664
- field: (...a) => field(a[0], a[1]),
17854
+ field: (...a) => field(a[0], a[1], a[2]),
17665
17855
  noTrivia: (...a) => noTrivia(a[0]),
17666
17856
  token: (...a) => token(a[0]),
17667
17857
  // `routed(fallback)` — the fallback must be forwarded. A zero-arg entry here read
@@ -18160,9 +18350,11 @@ function exprToCombi(node2, scope, code, mfs) {
18160
18350
  const inner = anyValue(innerArg, scope, code, mfs);
18161
18351
  if (!isCombinator2(inner)) return null;
18162
18352
  try {
18163
- const evaluated = anyValue(extraArg, scope, code, []);
18353
+ const extraType = unwrapStaticExpr(extraArg).type;
18354
+ const derives = extraType === "ArrowFunctionExpression" || extraType === "FunctionExpression";
18355
+ const evaluated = derives ? null : anyValue(extraArg, scope, code, []);
18164
18356
  const usable = typeof evaluated === "object" && evaluated !== null && !Array.isArray(evaluated) && Object.getPrototypeOf(evaluated) === Object.prototype;
18165
- const combi = withCtx(usable ? evaluated : UNEVALUATED_EXTRA, inner);
18357
+ const combi = withCtx(derives ? DERIVE_STAND_IN : usable ? evaluated : UNEVALUATED_EXTRA, inner);
18166
18358
  if (combi._def.tag !== "withCtx") return null;
18167
18359
  combi._def.extraSrc = extraSrc;
18168
18360
  return combi;