parseman 0.40.0 → 0.42.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 (54) hide show
  1. package/README.md +7 -6
  2. package/dist/combinators/expect.d.ts.map +1 -1
  3. package/dist/combinators/grammar.d.ts.map +1 -1
  4. package/dist/combinators/literal.d.ts.map +1 -1
  5. package/dist/combinators/node.d.ts.map +1 -1
  6. package/dist/combinators/regex.d.ts.map +1 -1
  7. package/dist/combinators/scanTo.d.ts.map +1 -1
  8. package/dist/combinators/trivia-skip.d.ts.map +1 -1
  9. package/dist/compiler/codegen.d.ts +3 -0
  10. package/dist/compiler/codegen.d.ts.map +1 -1
  11. package/dist/compiler/inline-build.d.ts +1 -1
  12. package/dist/compiler/inline-build.d.ts.map +1 -1
  13. package/dist/compiler/inline-callback.d.ts +9 -0
  14. package/dist/compiler/inline-callback.d.ts.map +1 -1
  15. package/dist/compiler/line-index.d.ts +1 -15
  16. package/dist/compiler/line-index.d.ts.map +1 -1
  17. package/dist/compiler/value-usage.d.ts.map +1 -1
  18. package/dist/cst/capture-buffer.d.ts.map +1 -1
  19. package/dist/cst/trivia-entries.d.ts +52 -0
  20. package/dist/cst/trivia-entries.d.ts.map +1 -1
  21. package/dist/functional/run.d.ts +11 -2
  22. package/dist/functional/run.d.ts.map +1 -1
  23. package/dist/index.cjs +634 -169
  24. package/dist/index.cjs.map +4 -4
  25. package/dist/index.d.ts +4 -4
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +634 -169
  28. package/dist/index.js.map +4 -4
  29. package/dist/language-service/index.cjs +203 -4
  30. package/dist/language-service/index.cjs.map +4 -4
  31. package/dist/language-service/index.js +203 -4
  32. package/dist/language-service/index.js.map +4 -4
  33. package/dist/line-index.d.ts +41 -0
  34. package/dist/line-index.d.ts.map +1 -0
  35. package/dist/plugin/index.cjs +454 -126
  36. package/dist/plugin/index.cjs.map +4 -4
  37. package/dist/plugin/index.js +454 -126
  38. package/dist/plugin/index.js.map +4 -4
  39. package/dist/recovery/scan.d.ts.map +1 -1
  40. package/dist/regex/first-set.d.ts.map +1 -1
  41. package/dist/run/index.cjs +202 -2
  42. package/dist/run/index.cjs.map +4 -4
  43. package/dist/run/index.d.ts +8 -4
  44. package/dist/run/index.d.ts.map +1 -1
  45. package/dist/run/index.js +202 -2
  46. package/dist/run/index.js.map +4 -4
  47. package/dist/spec/index.cjs +174 -52
  48. package/dist/spec/index.cjs.map +4 -4
  49. package/dist/spec/index.js +174 -52
  50. package/dist/spec/index.js.map +4 -4
  51. package/dist/types.d.ts +12 -0
  52. package/dist/types.d.ts.map +1 -1
  53. package/dist/version.d.ts +1 -1
  54. package/package.json +1 -1
@@ -282,6 +282,65 @@ function failAt(ctx, expected, pos) {
282
282
  return r;
283
283
  }
284
284
 
285
+ // src/line-index.ts
286
+ function createLineIndex() {
287
+ return { lineStarts: [0] };
288
+ }
289
+ function recordLineRange(index, input, start, end) {
290
+ const lineStarts = index.lineStarts;
291
+ for (let i = start; i < end; i++) {
292
+ if (input.charCodeAt(i) === 10) lineStarts.push(i + 1);
293
+ }
294
+ }
295
+ function recordLineRangeFromContext(ctx, input, _startHint, end) {
296
+ if (!ctx.trackLines) return;
297
+ const from = ctx._lineScannedTo ?? 0;
298
+ if (end <= from) return;
299
+ const index = ctx._lineIndex ?? (ctx._lineStarts ? { lineStarts: ctx._lineStarts } : void 0);
300
+ if (!index) return;
301
+ recordLineRange(index, input, from, end);
302
+ ctx._lineScannedTo = end;
303
+ }
304
+ function normalizeLineIndex(index) {
305
+ const starts = index.lineStarts;
306
+ starts.sort((a, b) => a - b);
307
+ let write = 0;
308
+ for (let read = 0; read < starts.length; read++) {
309
+ const value = starts[read];
310
+ if (write === 0 || starts[write - 1] !== value) starts[write++] = value;
311
+ }
312
+ starts.length = write;
313
+ if (starts.length === 0 || starts[0] !== 0) starts.unshift(0);
314
+ return index;
315
+ }
316
+ function offsetToLineCol(index, offset) {
317
+ const { lineStarts } = index;
318
+ let lo = 0;
319
+ let hi = lineStarts.length - 1;
320
+ while (lo < hi) {
321
+ const mid = lo + hi + 1 >> 1;
322
+ if (lineStarts[mid] <= offset) lo = mid;
323
+ else hi = mid - 1;
324
+ }
325
+ return { line: lo + 1, col: offset - lineStarts[lo] + 1 };
326
+ }
327
+ function annotateSpan(span, index) {
328
+ const s = offsetToLineCol(index, span.start);
329
+ const e = offsetToLineCol(index, span.end);
330
+ return {
331
+ ...span,
332
+ startLine: s.line,
333
+ startColumn: s.col,
334
+ endLine: e.line,
335
+ endColumn: e.col
336
+ };
337
+ }
338
+ function annotateSpanFromLineContext(span, ctx) {
339
+ if (!ctx.trackLines) return span;
340
+ const index = ctx._lineIndex ?? (ctx._lineStarts ? { lineStarts: ctx._lineStarts } : void 0);
341
+ return index ? annotateSpan(span, index) : span;
342
+ }
343
+
285
344
  // src/cst/capture-buffer.ts
286
345
  var EMPTY = [];
287
346
  var EMPTY_TL = [];
@@ -323,7 +382,12 @@ function endCstNodeCapture(ctx, saved) {
323
382
  return materialized;
324
383
  }
325
384
  function pushCstLeaf(ctx, leaf2) {
326
- pushCstChild(ctx, leaf2, leaf2);
385
+ if (!ctx.trackLines) {
386
+ pushCstChild(ctx, leaf2, leaf2);
387
+ return;
388
+ }
389
+ const annotated = leaf2 && typeof leaf2 === "object" && leaf2.span ? { ...leaf2, span: annotateSpanFromLineContext(leaf2.span, ctx) } : leaf2;
390
+ pushCstChild(ctx, annotated, annotated);
327
391
  }
328
392
  function pushCstChild(ctx, built, rawEntry) {
329
393
  const b = ctx._cstBuf;
@@ -457,6 +521,7 @@ function literal(value, opts = {}) {
457
521
  canMatchNewline: value.includes("\n"),
458
522
  isTrivia: false
459
523
  };
524
+ const canMatchNewline = meta.canMatchNewline;
460
525
  if (caseInsensitive) {
461
526
  const upper = value.toUpperCase();
462
527
  const lower = value.toLowerCase();
@@ -473,6 +538,7 @@ function literal(value, opts = {}) {
473
538
  return function parse3(input, pos, ctx) {
474
539
  if (input.charCodeAt(pos) === code) {
475
540
  const span = { start: pos, end: pos + 1 };
541
+ if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
476
542
  if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
477
543
  return { ok: true, value, span };
478
544
  }
@@ -486,6 +552,7 @@ function literal(value, opts = {}) {
486
552
  const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
487
553
  if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
488
554
  const span = { start: pos, end };
555
+ if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, end);
489
556
  if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: matchedValue, span });
490
557
  return { ok: true, value: matchedValue, span };
491
558
  }
@@ -653,6 +720,7 @@ function regex(pattern, flags = "") {
653
720
  if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
654
721
  const value = input.slice(pos, scanEnd);
655
722
  const span2 = { start: pos, end: scanEnd };
723
+ if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, scanEnd);
656
724
  if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: span2 });
657
725
  return { ok: true, value, span: span2 };
658
726
  }
@@ -662,6 +730,7 @@ function regex(pattern, flags = "") {
662
730
  return failAt(ctx, [`/${source}/`], pos);
663
731
  }
664
732
  const span = { start: pos, end: pos + m[0].length };
733
+ if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
665
734
  if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: m[0], span });
666
735
  return { ok: true, value: m[0], span };
667
736
  }
@@ -800,8 +869,8 @@ function parseRegex(src) {
800
869
  }
801
870
  if (src[k] !== "]") throw BAIL;
802
871
  i = k + 1;
803
- if (negated) return charNode(any(), true);
804
872
  const ranges = parseClassRanges(body);
873
+ if (negated) return charNode(any(), !ranges || !rangesHaveNewline(ranges));
805
874
  if (!ranges) return charNode(any(), true);
806
875
  return charNode(rangesToSet(ranges), rangesHaveNewline(ranges));
807
876
  };
@@ -897,7 +966,7 @@ function firstSet(n) {
897
966
  }
898
967
  }
899
968
  }
900
- function firstCanBeNewline(n) {
969
+ function canConsumeNewline(n) {
901
970
  switch (n.t) {
902
971
  case "char":
903
972
  return n.nl;
@@ -906,16 +975,11 @@ function firstCanBeNewline(n) {
906
975
  case "empty":
907
976
  return false;
908
977
  case "rep":
909
- return firstCanBeNewline(n.node);
978
+ return canConsumeNewline(n.node);
910
979
  case "alt":
911
- return n.arms.some(firstCanBeNewline);
912
- case "seq": {
913
- for (const part of n.parts) {
914
- if (firstCanBeNewline(part)) return true;
915
- if (!nullable(part)) break;
916
- }
917
- return false;
918
- }
980
+ return n.arms.some(canConsumeNewline);
981
+ case "seq":
982
+ return n.parts.some(canConsumeNewline);
919
983
  }
920
984
  }
921
985
  function firstSetFromRegex(source) {
@@ -925,8 +989,8 @@ function firstSetFromRegex(source) {
925
989
  } catch {
926
990
  return { firstSet: any(), canMatchNewline: true };
927
991
  }
928
- if (nullable(ast)) return { firstSet: any(), canMatchNewline: true };
929
- return { firstSet: firstSet(ast), canMatchNewline: firstCanBeNewline(ast) };
992
+ if (nullable(ast)) return { firstSet: any(), canMatchNewline: canConsumeNewline(ast) };
993
+ return { firstSet: firstSet(ast), canMatchNewline: canConsumeNewline(ast) };
930
994
  }
931
995
 
932
996
  // src/combinators/case-fold.ts
@@ -1083,7 +1147,9 @@ function firstSetSentinel(fs2) {
1083
1147
  function recoverScan(input, from, ctx, sync, expected) {
1084
1148
  let scanPos = from;
1085
1149
  while (scanPos < input.length && !probeAt(sync, input, scanPos, ctx)) scanPos++;
1086
- const error = { _tag: "parseError", span: { start: from, end: scanPos }, expected };
1150
+ const span = { start: from, end: scanPos };
1151
+ if (ctx.trackLines) recordLineRangeFromContext(ctx, input, from, scanPos);
1152
+ const error = { _tag: "parseError", span: ctx.trackLines ? annotateSpanFromLineContext(span, ctx) : span, expected };
1087
1153
  ctx._errors?.push(error);
1088
1154
  return { error, end: scanPos };
1089
1155
  }
@@ -1185,7 +1251,8 @@ function expect(combinator, label2) {
1185
1251
  parse(input, pos, ctx) {
1186
1252
  const result = combinator.parse(input, pos, ctx);
1187
1253
  if (result.ok) return result;
1188
- const error = { _tag: "parseError", span: { start: pos, end: pos }, expected };
1254
+ const span = { start: pos, end: pos };
1255
+ const error = { _tag: "parseError", span: ctx.trackLines ? annotateSpanFromLineContext(span, ctx) : span, expected };
1189
1256
  ctx._errors?.push(error);
1190
1257
  if (ctx._tolerant) captureError(ctx, error);
1191
1258
  return { ok: true, value: error, span: { start: pos, end: pos } };
@@ -1630,6 +1697,18 @@ function rollbackTrivia(ctx, mark) {
1630
1697
  rollbackCstCapture(ctx, { raw: mark.raw, tlog: mark.tlog, leaves: mark.leaves, fields: mark.fields, errors: mark.errors });
1631
1698
  if (ctx._triviaLog && ctx._triviaLog.length !== mark.log) ctx._triviaLog.length = mark.log;
1632
1699
  }
1700
+ function parseTriviaNoCapture(triviaP, input, cur, ctx) {
1701
+ const probeCtx = {
1702
+ trackLines: ctx.trackLines,
1703
+ state: ctx.state,
1704
+ ...ctx._lineIndex ? { _lineIndex: ctx._lineIndex } : {},
1705
+ ...ctx._lineStarts ? { _lineStarts: ctx._lineStarts } : {},
1706
+ ...ctx._lineScannedTo !== void 0 ? { _lineScannedTo: ctx._lineScannedTo } : {}
1707
+ };
1708
+ const result = triviaP.parse(input, cur, probeCtx);
1709
+ ctx._lineScannedTo = probeCtx._lineScannedTo;
1710
+ return result;
1711
+ }
1633
1712
  function saveLookaheadMark(ctx) {
1634
1713
  return { ...saveTriviaMark(ctx), probeBest: ctx._probe ? ctx._probe.best : null };
1635
1714
  }
@@ -1652,13 +1731,29 @@ function scanWithLabels(input, cur, ctx) {
1652
1731
  function advanceTrivia(input, cur, ctx) {
1653
1732
  const triviaP = ctx.trivia;
1654
1733
  if (!triviaP) return cur;
1734
+ if (!ctx.trackLines) {
1735
+ const fast2 = fastTriviaScanner(triviaP);
1736
+ if (fast2) return fast2(input, cur);
1737
+ if (ctx.triviaKindLabels) {
1738
+ const scan = scanWithLabels(input, cur, ctx);
1739
+ return scan.end;
1740
+ }
1741
+ const tr2 = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
1742
+ return tr2.ok && tr2.span.end > cur ? tr2.span.end : cur;
1743
+ }
1744
+ const trackTriviaLines = ctx.trackLines && triviaP._meta.canMatchNewline;
1655
1745
  const fast = fastTriviaScanner(triviaP);
1656
- if (fast) return fast(input, cur);
1746
+ if (fast) {
1747
+ const end = fast(input, cur);
1748
+ if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, end);
1749
+ return end;
1750
+ }
1657
1751
  if (ctx.triviaKindLabels) {
1658
1752
  const scan = scanWithLabels(input, cur, ctx);
1753
+ if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, scan.end);
1659
1754
  return scan.end;
1660
1755
  }
1661
- const tr = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
1756
+ const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
1662
1757
  return tr.ok && tr.span.end > cur ? tr.span.end : cur;
1663
1758
  }
1664
1759
  function scanTrivia(input, cur, ctx) {
@@ -1666,18 +1761,46 @@ function scanTrivia(input, cur, ctx) {
1666
1761
  if (!triviaP) return { end: cur, commit: NOOP_COMMIT };
1667
1762
  const log = ctx._triviaLog;
1668
1763
  const captureTl = ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0);
1764
+ if (!ctx.trackLines) {
1765
+ const fast2 = !ctx.triviaKindLabels ? fastTriviaScanner(triviaP) : null;
1766
+ if (fast2 && log === void 0 && !captureTl) {
1767
+ return { end: fast2(input, cur), commit: NOOP_COMMIT };
1768
+ }
1769
+ if (ctx.triviaKindLabels && (log !== void 0 || captureTl)) {
1770
+ return scanWithLabels(input, cur, ctx);
1771
+ }
1772
+ if (log !== void 0 || captureTl) {
1773
+ const tr3 = triviaP.parse(input, cur, {
1774
+ trackLines: log !== void 0 ? false : ctx.trackLines,
1775
+ state: ctx.state
1776
+ });
1777
+ if (!tr3.ok || tr3.span.end === cur) return { end: cur, commit: NOOP_COMMIT };
1778
+ const end = tr3.span.end;
1779
+ return {
1780
+ end,
1781
+ commit: () => {
1782
+ pushTriviaLogEntry(ctx, cur, end);
1783
+ if (captureTl) pushCstTriviaEntry(ctx, cur, end);
1784
+ }
1785
+ };
1786
+ }
1787
+ const tr2 = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
1788
+ return { end: tr2.ok ? tr2.span.end : cur, commit: NOOP_COMMIT };
1789
+ }
1790
+ const trackTriviaLines = ctx.trackLines && triviaP._meta.canMatchNewline;
1669
1791
  const fast = !ctx.triviaKindLabels ? fastTriviaScanner(triviaP) : null;
1670
1792
  if (fast && log === void 0 && !captureTl) {
1671
- return { end: fast(input, cur), commit: NOOP_COMMIT };
1793
+ const end = fast(input, cur);
1794
+ if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, end);
1795
+ return { end, commit: NOOP_COMMIT };
1672
1796
  }
1673
1797
  if (ctx.triviaKindLabels && (log !== void 0 || captureTl)) {
1674
- return scanWithLabels(input, cur, ctx);
1798
+ const scan = scanWithLabels(input, cur, ctx);
1799
+ if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, scan.end);
1800
+ return scan;
1675
1801
  }
1676
1802
  if (log !== void 0 || captureTl) {
1677
- const tr2 = triviaP.parse(input, cur, {
1678
- trackLines: log !== void 0 ? false : ctx.trackLines,
1679
- state: ctx.state
1680
- });
1803
+ const tr2 = parseTriviaNoCapture(triviaP, input, cur, ctx);
1681
1804
  if (!tr2.ok || tr2.span.end === cur) return { end: cur, commit: NOOP_COMMIT };
1682
1805
  const end = tr2.span.end;
1683
1806
  return {
@@ -1688,7 +1811,7 @@ function scanTrivia(input, cur, ctx) {
1688
1811
  }
1689
1812
  };
1690
1813
  }
1691
- const tr = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
1814
+ const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
1692
1815
  return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
1693
1816
  }
1694
1817
  function consumeTrivia(input, cur, ctx) {
@@ -2582,9 +2705,11 @@ function markUnusedValues(root) {
2582
2705
  visit(def.parser, consumed);
2583
2706
  visit(def.sentinel, false);
2584
2707
  return;
2708
+ case "token":
2709
+ visit(def.parser, false);
2710
+ return;
2585
2711
  case "label":
2586
2712
  case "trivia":
2587
- case "token":
2588
2713
  case "attempt":
2589
2714
  case "withCtx":
2590
2715
  case "expect":
@@ -3070,13 +3195,14 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
3070
3195
  const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
3071
3196
  const nodeType = def.type ?? missingInferredType();
3072
3197
  const cstOutput = cstOutputHost(ctx.build);
3198
+ const span = ctx.trackLines ? annotateSpanFromLineContext(r.span, ctx) : r.span;
3073
3199
  const hostState = clonesState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
3074
- const built = unwrap && children2.length === 1 ? unwrapChild(children2[0]) : collapse && children2.length === 1 ? children2[0] : !build && project === void 0 && ctx.build?._parsemanCstCollapse && children2.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children2[0], children2, rawChildren) ? children2[0] : project !== void 0 ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, r.span, rawChildren, triviaLog, hostState) : projectChild(children2, project, nodeType) : build ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, r.span, rawChildren, triviaLog, hostState) : build(children2, fields, r.span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children2, fields, r.span, rawChildren, triviaLog, st) : { _tag: "node", type: nodeType, span: { start: r.span.start, end: r.span.end }, state: st ?? null, children: children2 };
3075
- const rawEntry = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : typeof built === "object" && built !== null ? input.slice(r.span.start, r.span.end) : "", span: r.span };
3200
+ const built = unwrap && children2.length === 1 ? unwrapChild(children2[0]) : collapse && children2.length === 1 ? children2[0] : !build && project === void 0 && ctx.build?._parsemanCstCollapse && children2.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children2[0], children2, rawChildren) ? children2[0] : project !== void 0 ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, hostState) : projectChild(children2, project, nodeType) : build ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, hostState) : build(children2, fields, span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, st) : { _tag: "node", type: nodeType, span: ctx.trackLines ? { ...span } : { start: r.span.start, end: r.span.end }, state: st ?? null, children: children2 };
3201
+ const rawEntry = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : typeof built === "object" && built !== null ? input.slice(r.span.start, r.span.end) : "", span };
3076
3202
  if (saved.buf !== void 0 || saved.ch !== void 0) {
3077
3203
  pushCstChild(ctx, built, rawEntry);
3078
3204
  }
3079
- return { ok: true, value: built, span: r.span };
3205
+ return { ok: true, value: built, span };
3080
3206
  }
3081
3207
  };
3082
3208
  }
@@ -3147,38 +3273,24 @@ function field(name, combinator) {
3147
3273
  };
3148
3274
  }
3149
3275
 
3150
- // src/compiler/line-index.ts
3151
- function buildLineIndex(input) {
3152
- const lineStarts = [0];
3153
- for (let i = 0; i < input.length; i++) {
3154
- if (input.charCodeAt(i) === 10) lineStarts.push(i + 1);
3276
+ // src/combinators/grammar.ts
3277
+ function annotateResultLines(result, index) {
3278
+ const annotated = { ...result, span: annotateSpan(result.span, index) };
3279
+ const errors = annotated.errors;
3280
+ if (errors) {
3281
+ ;
3282
+ annotated.errors = errors.map((error) => ({
3283
+ ...error,
3284
+ span: annotateSpan(error.span, index)
3285
+ }));
3155
3286
  }
3156
- return { lineStarts };
3287
+ return annotated;
3157
3288
  }
3158
- function offsetToLineCol(index, offset) {
3159
- const { lineStarts } = index;
3160
- let lo = 0;
3161
- let hi = lineStarts.length - 1;
3162
- while (lo < hi) {
3163
- const mid = lo + hi + 1 >> 1;
3164
- if (lineStarts[mid] <= offset) lo = mid;
3165
- else hi = mid - 1;
3166
- }
3167
- return { line: lo + 1, col: offset - lineStarts[lo] + 1 };
3289
+ function createParseLineContext(input, pos) {
3290
+ const lineIndex = createLineIndex();
3291
+ if (pos > 0) recordLineRange(lineIndex, input, 0, pos);
3292
+ return { lineIndex, lineScannedTo: pos };
3168
3293
  }
3169
- function annotateSpan(span, index) {
3170
- const s = offsetToLineCol(index, span.start);
3171
- const e = offsetToLineCol(index, span.end);
3172
- return {
3173
- ...span,
3174
- startLine: s.line,
3175
- startColumn: s.col,
3176
- endLine: e.line,
3177
- endColumn: e.col
3178
- };
3179
- }
3180
-
3181
- // src/combinators/grammar.ts
3182
3294
  function parser(opts, root) {
3183
3295
  const clearTrivia = opts.trivia === null;
3184
3296
  return {
@@ -3194,9 +3306,13 @@ function parser(opts, root) {
3194
3306
  },
3195
3307
  parse(input, pos, _ctx) {
3196
3308
  const trackLines = opts.trackLines ?? _ctx?.trackLines ?? false;
3309
+ const lineContext = trackLines && _ctx?._lineIndex === void 0 && _ctx?._lineStarts === void 0 ? createParseLineContext(input, pos ?? 0) : void 0;
3310
+ const lineIndex = trackLines ? _ctx?._lineIndex ?? (_ctx?._lineStarts ? { lineStarts: _ctx._lineStarts } : lineContext.lineIndex) : void 0;
3197
3311
  const ctx = {
3198
3312
  ..._ctx,
3199
3313
  trackLines,
3314
+ ...lineIndex ? { _lineIndex: lineIndex } : {},
3315
+ ...lineContext ? { _lineScannedTo: lineContext.lineScannedTo } : {},
3200
3316
  // trivia: null clears (contiguous terms); a Combinator sets; undefined inherits.
3201
3317
  ...clearTrivia ? {
3202
3318
  trivia: void 0,
@@ -3214,11 +3330,10 @@ function parser(opts, root) {
3214
3330
  ...opts.captureTriviaKinds && !clearTrivia ? { _triviaCaptureMask: triviaKindMask(opts.trivia?._meta.triviaKindLabels ?? _ctx?.triviaKindLabels, opts.captureTriviaKinds) } : {}
3215
3331
  };
3216
3332
  const result = root.parse(input, pos ?? 0, ctx);
3217
- if (trackLines) {
3218
- const idx = buildLineIndex(input);
3219
- return { ...result, span: annotateSpan(result.span, idx) };
3333
+ if (trackLines && _ctx && ctx._lineScannedTo !== void 0) {
3334
+ _ctx._lineScannedTo = Math.max(_ctx._lineScannedTo ?? 0, ctx._lineScannedTo);
3220
3335
  }
3221
- return result;
3336
+ return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
3222
3337
  }
3223
3338
  };
3224
3339
  }
@@ -3322,7 +3437,7 @@ function leaf(root, fn) {
3322
3437
  }
3323
3438
 
3324
3439
  // src/version.ts
3325
- var PARSEMAN_VERSION = "0.40.0";
3440
+ var PARSEMAN_VERSION = "0.42.0";
3326
3441
 
3327
3442
  // src/cst/host-mode.ts
3328
3443
  var FUSED_HOST_MODE = /* @__PURE__ */ Symbol.for("parseman.fusedHostMode");
@@ -5006,7 +5121,7 @@ function scanTo(sentinel, { skip: skip2, raw = false, orEOF = false } = {}) {
5006
5121
  let cur = pos;
5007
5122
  const skip3 = resolveScanSkip(explicitSkip, raw, ctx);
5008
5123
  const probeCtx = {
5009
- trackLines: ctx.trackLines,
5124
+ trackLines: false,
5010
5125
  state: ctx.state,
5011
5126
  ...ctx._errors !== void 0 ? { _errors: ctx._errors } : {}
5012
5127
  };
@@ -5019,6 +5134,7 @@ function scanTo(sentinel, { skip: skip2, raw = false, orEOF = false } = {}) {
5019
5134
  while (cur < input.length) {
5020
5135
  const s = sentinel.parse(input, cur, probeCtx);
5021
5136
  if (s.ok) {
5137
+ if (ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, cur);
5022
5138
  emit2(cur);
5023
5139
  return { ok: true, value: input.slice(pos, cur), span: { start: pos, end: cur } };
5024
5140
  }
@@ -5034,6 +5150,7 @@ function scanTo(sentinel, { skip: skip2, raw = false, orEOF = false } = {}) {
5034
5150
  if (!advanced) cur++;
5035
5151
  }
5036
5152
  if (orEOF) {
5153
+ if (ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, cur);
5037
5154
  emit2(cur);
5038
5155
  return { ok: true, value: input.slice(pos, cur), span: { start: pos, end: cur } };
5039
5156
  }
@@ -6266,7 +6383,7 @@ function scanBranchLabeled(shape, kindIndex, mint) {
6266
6383
  ` if (${m.end} > _e) {`,
6267
6384
  ` if (_cap) {`,
6268
6385
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, ${m.end}, ${kindIndex})`,
6269
- ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << kindIndex}))) _ctx._cstTriviaLog.push(_e, ${m.end}, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${kindIndex})`,
6386
+ ` if (_cap === 1 && _ctx._cstTriviaLog !== undefined && _ctx.captureTrivia && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << kindIndex}))) _ctx._cstTriviaLog.push(_e, ${m.end}, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${kindIndex})`,
6270
6387
  ` }`,
6271
6388
  ` _e = ${m.end}`,
6272
6389
  ` continue`,
@@ -6322,7 +6439,7 @@ function analyzeTriviaFastPath(trivia2) {
6322
6439
  var CAP_RECORD = [
6323
6440
  ` if (_cap && _e > _pos) {`,
6324
6441
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
6325
- ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
6442
+ ` if (_cap === 1 && _ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
6326
6443
  ` }`
6327
6444
  ].join("\n");
6328
6445
  function composeFastLoop(shapes) {
@@ -6382,7 +6499,7 @@ function buildLabeledRegexTriviaFnDecl(fnName, spec, reNames) {
6382
6499
  ` const _ce = _e + _m${i}[0].length`,
6383
6500
  ` if (_cap) {`,
6384
6501
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
6385
- ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
6502
+ ` if (_cap === 1 && _ctx._cstTriviaLog !== undefined && _ctx.captureTrivia && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
6386
6503
  ` }`,
6387
6504
  ` _e = _ce`,
6388
6505
  ` _matched = true`,
@@ -6420,7 +6537,7 @@ function buildLabeledRuntimeTriviaFnDecl(fnName, spec, rpStartIndex) {
6420
6537
  ` const _ce = _r${i}.span.end`,
6421
6538
  ` if (_cap) {`,
6422
6539
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
6423
- ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
6540
+ ` if (_cap === 1 && _ctx._cstTriviaLog !== undefined && _ctx.captureTrivia && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
6424
6541
  ` }`,
6425
6542
  ` _e = _ce`,
6426
6543
  ` _matched = true`,
@@ -6472,8 +6589,8 @@ function analyzeMkInlineBuild(def) {
6472
6589
  if (looseMkBuildRe(def.type).test(src)) return def.type;
6473
6590
  return null;
6474
6591
  }
6475
- function emitInlineMkNodeExpr(type, chV, rawV, pos, endVar, tlV) {
6476
- return `{ _tag: 'node', type: ${JSON.stringify(type)}, span: { start: ${pos}, end: ${endVar} }, children: ${chV}, rawCount: ${rawV}.length, localTriviaLen: ${tlV}.length }`;
6592
+ function emitInlineMkNodeExpr(type, chV, rawV, spanExpr, tlV) {
6593
+ return `{ _tag: 'node', type: ${JSON.stringify(type)}, span: ${spanExpr}, children: ${chV}, rawCount: ${rawV}.length, localTriviaLen: ${tlV}.length }`;
6477
6594
  }
6478
6595
 
6479
6596
  // src/compiler/inline-callback.ts
@@ -6506,6 +6623,9 @@ function transformFnSource(fn, fnSrc) {
6506
6623
  function replaceParam(body, param, valueVar) {
6507
6624
  return body.replace(new RegExp(`\\b${escapeRegExp2(param)}\\b`, "g"), valueVar);
6508
6625
  }
6626
+ function hasExplicitObjectKey(body, param) {
6627
+ return new RegExp(`\\b${escapeRegExp2(param)}\\b\\s*:`).test(body);
6628
+ }
6509
6629
  function stripForIdCheck(body) {
6510
6630
  return body.replace(/'[^'\\]*(?:\\.[^'\\]*)*'|"[^"\\]*(?:\\.[^"\\]*)*"/g, '""').replace(/\bas\s+const\b/g, "").replace(/\b[A-Za-z_$][\w$]*\s*:/g, ":");
6511
6631
  }
@@ -6548,10 +6668,19 @@ function tryInlineDestructureTransform(src, valueVars) {
6548
6668
  const allowed = new Set(valueVars);
6549
6669
  for (let i = 0; i < slots.length; i++) {
6550
6670
  const name = slots[i];
6551
- if (name) body = replaceParam(body, name, valueVars[i]);
6671
+ if (!name) continue;
6672
+ if (hasExplicitObjectKey(body, name)) return null;
6673
+ body = replaceParam(body, name, valueVars[i]);
6552
6674
  }
6553
6675
  return hasFreeIdentifiers(body, allowed) ? null : body;
6554
6676
  }
6677
+ function isDispatchTailOnlyTransform(src) {
6678
+ const m = src.match(/^\(\s*\[([^\]]*)\]\s*\)\s*=>\s*(.+)$/s);
6679
+ if (!m) return false;
6680
+ const slots = parseArrayDestructure(m[1], 2);
6681
+ const tail = slots[1];
6682
+ return tail !== null && m[2].trim() === tail;
6683
+ }
6555
6684
 
6556
6685
  // src/compiler/codegen.ts
6557
6686
  function leadingFirstSetRecipe(p, seen = /* @__PURE__ */ new Set()) {
@@ -6643,6 +6772,8 @@ function leadingFirstSetRecipe(p, seen = /* @__PURE__ */ new Set()) {
6643
6772
  }
6644
6773
  }
6645
6774
  var HOST_READS_DECL = "const _hostReads = (b, n) => { if (b === undefined) return false; let s; try { s = Function.prototype.toString.call(b) } catch (e) { return true } if (/\\barguments\\b/.test(s)) return true; const m = /^[^(]*\\(([\\s\\S]*?)\\)/.exec(s); if (m && /\\.\\.\\.|=/.test(m[1])) return true; return b.length > n }";
6775
+ var LINE_TRACK_DECL = "const _trackLines = (_ctx, input, start, end) => { const from = _ctx._lineScannedTo ?? 0; if (end <= from) return; for (let i = from; i < end; i++) if (input.charCodeAt(i) === 10) _ctx._lineStarts.push(i + 1); _ctx._lineScannedTo = end }";
6776
+ var LINE_SPAN_DECL = "const _lineCol = (_ctx, offset) => { const starts = _ctx._lineStarts; let lo = 0, hi = starts.length - 1; while (lo < hi) { const mid = (lo + hi + 1) >> 1; if (starts[mid] <= offset) lo = mid; else hi = mid - 1 } return [lo + 1, offset - starts[lo] + 1] }\nconst _spanLines = (_ctx, start, end) => { const s = _lineCol(_ctx, start), e = _lineCol(_ctx, end); return { start, end, startLine: s[0], startColumn: s[1], endLine: e[0], endColumn: e[1] } }";
6646
6777
  var _loweringSink = null;
6647
6778
  function beginLoweringCapture() {
6648
6779
  _loweringSink = /* @__PURE__ */ new Set();
@@ -6791,14 +6922,46 @@ function emitLeafCapture(ctx, valExpr, startExpr, endExpr) {
6791
6922
  if (ctx.capAsTrivia) return [];
6792
6923
  const i = ind(ctx);
6793
6924
  const lf = v(ctx, "_lf");
6925
+ const spanExpr = emitSpanExpr(ctx, startExpr, endExpr);
6794
6926
  return [
6795
6927
  `${i}if (_ctx._cstLeaves || _ctx._cstRawChildren) {`,
6796
- `${i} const ${lf} = { _tag: 'leaf', value: ${valExpr}, span: { start: ${startExpr}, end: ${endExpr} } }`,
6928
+ `${i} const ${lf} = { _tag: 'leaf', value: ${valExpr}, span: ${spanExpr} }`,
6797
6929
  `${i} if (_ctx._cstLeaves) _ctx._cstLeaves.push(${lf})`,
6798
6930
  `${i} if (_ctx._cstRawChildren) _ctx._cstRawChildren.push(${lf})`,
6799
6931
  `${i}}`
6800
6932
  ];
6801
6933
  }
6934
+ function emitSpanExpr(ctx, startExpr, endExpr) {
6935
+ if (!ctx.lineTracking) return `{ start: ${startExpr}, end: ${endExpr} }`;
6936
+ ctx.needsLineSpan = true;
6937
+ return `_spanLines(_ctx, ${startExpr}, ${endExpr})`;
6938
+ }
6939
+ function emitLineTrack(ctx, startExpr, endExpr) {
6940
+ if (!ctx.lineTracking) return [];
6941
+ ctx.needsLineTrack = true;
6942
+ return [`${ind(ctx)}_trackLines(_ctx, input, ${startExpr}, ${endExpr})`];
6943
+ }
6944
+ function emitLiteralLineTrack(ctx, startExpr, value) {
6945
+ if (!ctx.lineTracking) return [];
6946
+ const lineDeltas = [];
6947
+ for (let i = 0; i < value.length; i++) {
6948
+ if (value.charCodeAt(i) === 10) lineDeltas.push(i + 1);
6949
+ }
6950
+ if (lineDeltas.length === 0) return [];
6951
+ const fromV = v(ctx, "_ltFrom");
6952
+ const endExpr = value.length === 0 ? startExpr : `${startExpr} + ${value.length}`;
6953
+ return [
6954
+ `${ind(ctx)}const ${fromV} = _ctx._lineScannedTo ?? 0`,
6955
+ `${ind(ctx)}if (${endExpr} > ${fromV}) {`,
6956
+ `${ind(ctx)} for (let i = ${fromV}; i < ${startExpr}; i++) if (input.charCodeAt(i) === 10) _ctx._lineStarts.push(i + 1)`,
6957
+ ...lineDeltas.map((delta) => {
6958
+ const lineStart = `${startExpr} + ${delta}`;
6959
+ return `${ind(ctx)} if (${lineStart} > ${fromV}) _ctx._lineStarts.push(${lineStart})`;
6960
+ }),
6961
+ `${ind(ctx)} _ctx._lineScannedTo = ${endExpr}`,
6962
+ `${ind(ctx)}}`
6963
+ ];
6964
+ }
6802
6965
  function ensureRegexDecl(ctx, source, flags) {
6803
6966
  const f = "y" + flags.replace(/[gy]/g, "");
6804
6967
  const key = `${source}/${f}`;
@@ -6810,6 +6973,17 @@ function ensureRegexDecl(ctx, source, flags) {
6810
6973
  }
6811
6974
  return rName;
6812
6975
  }
6976
+ function ensurePlainRegexDecl(ctx, source, flags) {
6977
+ const f = flags.replace(/[gy]/g, "");
6978
+ const key = `${source}/${f}`;
6979
+ let rName = ctx.regexMap.get(key);
6980
+ if (rName === void 0) {
6981
+ rName = `${nsp(ctx)}_re${ctx.regexDecls.length}`;
6982
+ ctx.regexDecls.push(`const ${rName} = ${new RegExp(source, f).toString()}`);
6983
+ ctx.regexMap.set(key, rName);
6984
+ }
6985
+ return rName;
6986
+ }
6813
6987
  function ensureTriviaFn(ctx) {
6814
6988
  const trivia2 = ctx.activeTrivia;
6815
6989
  const existing = ctx.triviaFnNames.get(trivia2);
@@ -6875,7 +7049,7 @@ function ensureTriviaFn(ctx) {
6875
7049
  ` }`,
6876
7050
  ` if (_cap && _e > _pos) {`,
6877
7051
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
6878
- ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
7052
+ ` if (_cap === 1 && _ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
6879
7053
  ` }`,
6880
7054
  ` return _e`,
6881
7055
  `}`
@@ -7172,6 +7346,7 @@ function emitLit(def, ctx, pos) {
7172
7346
  );
7173
7347
  }
7174
7348
  const endVar = len === 0 ? pos : `${pos} + ${len}`;
7349
+ stmts.push(...emitLiteralLineTrack(ctx, pos, value));
7175
7350
  stmts.push(...emitLeafCapture(ctx, vv, pos, endVar));
7176
7351
  return { stmts, valueVar: vv, endVar };
7177
7352
  }
@@ -7251,7 +7426,7 @@ function emitKeywords(def, ctx, pos) {
7251
7426
  stmts.push(...emitLeafCapture(ctx, vv, pos, endVar));
7252
7427
  return { stmts, valueVar: vv, endVar };
7253
7428
  }
7254
- function emitRegex(def, ctx, pos) {
7429
+ function emitRegex(def, ctx, pos, canMatchNewline = true) {
7255
7430
  const expectedStr = JSON.stringify(`/${def.source}/`);
7256
7431
  const shape = scanShapeFromRegex(def.source, def.flags);
7257
7432
  if (shape) {
@@ -7264,7 +7439,11 @@ function emitRegex(def, ctx, pos) {
7264
7439
  fresh: (prefix) => v(ctx, prefix)
7265
7440
  });
7266
7441
  if (scanned) {
7267
- const stmts2 = [...scanned.stmts, ...emitLeafCapture(ctx, vv2, pos, scanned.endVar)];
7442
+ const stmts2 = [
7443
+ ...scanned.stmts,
7444
+ ...canMatchNewline ? emitLineTrack(ctx, pos, scanned.endVar) : [],
7445
+ ...emitLeafCapture(ctx, vv2, pos, scanned.endVar)
7446
+ ];
7268
7447
  return { stmts: stmts2, valueVar: vv2, endVar: scanned.endVar };
7269
7448
  }
7270
7449
  }
@@ -7286,6 +7465,7 @@ function emitRegex(def, ctx, pos) {
7286
7465
  `${ind(ctx)}const ${vv} = ${mv}[0]`
7287
7466
  ];
7288
7467
  const endVar = `${pos} + ${vv}.length`;
7468
+ if (canMatchNewline) stmts.push(...emitLineTrack(ctx, pos, endVar));
7289
7469
  stmts.push(...emitLeafCapture(ctx, vv, pos, endVar));
7290
7470
  return { stmts, valueVar: vv, endVar };
7291
7471
  }
@@ -7323,7 +7503,8 @@ function emitSeqValues(def, ctx, pos) {
7323
7503
  `${ind(ctx)}const ${markV} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`,
7324
7504
  `${ind(ctx)}const ${markTl} = _ctx._cstTriviaLog ? _ctx._cstTriviaLog.length : 0`,
7325
7505
  `${ind(ctx)}const ${markLog} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`,
7326
- `${ind(ctx)}const ${scanEndV} = ${capFn}(input, ${curV}, _ctx, 1)`
7506
+ `${ind(ctx)}const ${scanEndV} = ${capFn}(input, ${curV}, _ctx, 1)`,
7507
+ ...emitLineTrack(ctx, curV, scanEndV)
7327
7508
  );
7328
7509
  const r2 = emit(def.parsers[i], ctx, scanEndV);
7329
7510
  stmts.push(...r2.stmts);
@@ -7336,14 +7517,20 @@ function emitSeqValues(def, ctx, pos) {
7336
7517
  continue;
7337
7518
  } else {
7338
7519
  const trivFn = ensureTriviaFn(ctx);
7520
+ const markLog = v(ctx, "_mklg");
7339
7521
  const scanEndV = v(ctx, "_sne");
7340
- stmts.push(`${ind(ctx)}const ${scanEndV} = ${trivFn}(input, ${curV}, _ctx)`);
7522
+ const capArg = ctx.noHoist ? "0" : "_ctx._triviaLog !== undefined ? 2 : 0";
7523
+ stmts.push(
7524
+ `${ind(ctx)}const ${markLog} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`,
7525
+ `${ind(ctx)}const ${scanEndV} = ${trivFn}(input, ${curV}, _ctx, ${capArg})`,
7526
+ ...emitLineTrack(ctx, curV, scanEndV)
7527
+ );
7341
7528
  const r2 = emit(def.parsers[i], ctx, scanEndV);
7342
7529
  stmts.push(...r2.stmts);
7343
7530
  const endAfterV = v(ctx, "_sea");
7344
7531
  stmts.push(
7345
7532
  `${ind(ctx)}const ${endAfterV} = ${r2.endVar}`,
7346
- `${ind(ctx)}if (${endAfterV} > ${scanEndV}) ${curV} = ${endAfterV}`
7533
+ `${ind(ctx)}if (${endAfterV} > ${scanEndV}) ${curV} = ${endAfterV}; else if (_ctx._triviaLog && _ctx._triviaLog.length !== ${markLog}) _ctx._triviaLog.length = ${markLog}`
7347
7534
  );
7348
7535
  valueVars.push(r2.valueVar);
7349
7536
  continue;
@@ -7573,19 +7760,20 @@ function mayRecordRecoveryError(p, recovery, seen = /* @__PURE__ */ new Set()) {
7573
7760
  return false;
7574
7761
  }
7575
7762
  }
7576
- function emitDispatchCombinator(parser2, def, ctx, pos) {
7763
+ function emitDispatchCombinator(parser2, def, ctx, pos, valueMode = "pair") {
7577
7764
  if (parserUsesRouted2(def.selector)) {
7578
7765
  throw new Error("parseman: routed() can only appear inside a dispatch() branch");
7579
7766
  }
7580
7767
  const coverageIds = ctx.coverage?.plan.dispatches.get(parser2) ?? [];
7581
7768
  const branchUsesRouted2 = (entry) => entry.usesRouted === true || parserUsesRouted2(entry.parser);
7582
7769
  const hasRoutedBranch = def.cases.some(branchUsesRouted2) || (def.matchers ? def.matchers.some(branchUsesRouted2) : false) || (def.otherwise ? def.otherwiseUsesRouted === true || parserUsesRouted2(def.otherwise) : false);
7583
- const selectorLeafMark = hasRoutedBranch ? v(ctx, "_dsl") : null;
7584
- const selectorRawMark = hasRoutedBranch ? v(ctx, "_dsr") : null;
7585
- const selectorTriviaMark = hasRoutedBranch ? v(ctx, "_dst") : null;
7586
- const selectorLogMark = hasRoutedBranch ? v(ctx, "_dsg") : null;
7587
- const selectorFieldMark = hasRoutedBranch ? v(ctx, "_dsf") : null;
7588
- const selectorErrorMark = hasRoutedBranch ? v(ctx, "_dse") : null;
7770
+ const selectorNeedsRollback = hasRoutedBranch && (ctx.capturing === true && capturesLeaf(def.selector) || ctx.activeTrivia !== void 0 && parserHasTriviaSite(def.selector) || parserEnablesTriviaCapture(def.selector) || parserHasOwnFields(def.selector) || mayRecordRecoveryError(def.selector, !!ctx.recovery));
7771
+ const selectorLeafMark = selectorNeedsRollback ? v(ctx, "_dsl") : null;
7772
+ const selectorRawMark = selectorNeedsRollback ? v(ctx, "_dsr") : null;
7773
+ const selectorTriviaMark = selectorNeedsRollback ? v(ctx, "_dst") : null;
7774
+ const selectorLogMark = selectorNeedsRollback ? v(ctx, "_dsg") : null;
7775
+ const selectorFieldMark = selectorNeedsRollback ? v(ctx, "_dsf") : null;
7776
+ const selectorErrorMark = selectorNeedsRollback ? v(ctx, "_dse") : null;
7589
7777
  const selector = emit(def.selector, ctx, pos);
7590
7778
  const outV = v(ctx, "_dval");
7591
7779
  const outE = v(ctx, "_dend");
@@ -7610,13 +7798,14 @@ function emitDispatchCombinator(parser2, def, ctx, pos) {
7610
7798
  stmts.push(head);
7611
7799
  ctx.indent++;
7612
7800
  const usesRouted = branchUsesRouted2(entry);
7613
- const routedV = usesRouted ? v(ctx, "_drt") : null;
7801
+ const needsRoutedContext = usesRouted && routedNeedsContextBridge(parser3, ctx);
7802
+ const routedV = needsRoutedContext ? v(ctx, "_drt") : null;
7614
7803
  const mayError = mayRecordRecoveryError(parser3, !!ctx.recovery);
7615
7804
  const errMark = mayError ? v(ctx, "_derr") : null;
7616
7805
  const logMark = ctx.activeTrivia ? v(ctx, "_dlog") : null;
7617
- if (routedV) {
7806
+ if (usesRouted) {
7618
7807
  stmts.push(
7619
- `${ind(ctx)}const ${routedV} = _ctx._routed; _ctx._routed = { value: ${selector.valueVar}, span: { start: ${pos}, end: ${selector.endVar} } }`,
7808
+ ...routedV ? [`${ind(ctx)}const ${routedV} = _ctx._routed; _ctx._routed = { value: ${selector.valueVar}, span: { start: ${pos}, end: ${selector.endVar} } }`] : [],
7620
7809
  ...selectorLeafMark ? [
7621
7810
  `${ind(ctx)}if (_ctx._cstLeaves && _ctx._cstLeaves.length !== ${selectorLeafMark}) _ctx._cstLeaves.length = ${selectorLeafMark}; if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${selectorRawMark}) _ctx._cstRawChildren.length = ${selectorRawMark}; if (_ctx._cstTriviaLog && _ctx._cstTriviaLog.length !== ${selectorTriviaMark}) _ctx._cstTriviaLog.length = ${selectorTriviaMark}; if (_ctx._triviaLog && _ctx._triviaLog.length !== ${selectorLogMark}) _ctx._triviaLog.length = ${selectorLogMark}; if (_ctx._fields && _ctx._fields.length !== ${selectorFieldMark}) _ctx._fields.length = ${selectorFieldMark}; if (_ctx._errors && _ctx._errors.length !== ${selectorErrorMark}) _ctx._errors.length = ${selectorErrorMark}`
7622
7811
  ] : []
@@ -7624,7 +7813,17 @@ function emitDispatchCombinator(parser2, def, ctx, pos) {
7624
7813
  }
7625
7814
  if (errMark) stmts.push(`${ind(ctx)}const ${errMark} = _ctx._errors?.length ?? 0`);
7626
7815
  if (logMark) stmts.push(`${ind(ctx)}const ${logMark} = _ctx._triviaLog?.length ?? 0`);
7816
+ const savedRoutedLocal = ctx.routedLocal;
7817
+ const savedNoHoist = ctx.noHoist;
7818
+ if (usesRouted && !needsRoutedContext) {
7819
+ ctx.routedLocal = { valueVar: selector.valueVar, startVar: pos, endVar: selector.endVar };
7820
+ ctx.noHoist = true;
7821
+ } else if (usesRouted) {
7822
+ ctx.routedLocal = void 0;
7823
+ }
7627
7824
  const tail = emitTailFallible(parser3, ctx, usesRouted ? pos : selector.endVar);
7825
+ ctx.routedLocal = savedRoutedLocal;
7826
+ ctx.noHoist = savedNoHoist;
7628
7827
  stmts.push(...coverageAttempt(ctx, coverageId, pos));
7629
7828
  const errorRollback = errMark ? `if (_ctx._errors && _ctx._errors.length !== ${errMark}) _ctx._errors.length = ${errMark}; ` : "";
7630
7829
  const logRollback = logMark ? `if (_ctx._triviaLog && _ctx._triviaLog.length !== ${logMark}) _ctx._triviaLog.length = ${logMark}; ` : "";
@@ -7634,7 +7833,7 @@ function emitDispatchCombinator(parser2, def, ctx, pos) {
7634
7833
  ...tail.stmts,
7635
7834
  `${ind(ctx)}if (!${tail.okVar}) { ${routedRollback}${errorRollback}${logRollback}${coverageFailure}${committedFailBody(ctx)} }`,
7636
7835
  ...routedV ? [`${ind(ctx)}_ctx._routed = ${routedV}`] : [],
7637
- `${ind(ctx)}${outV} = [${selector.valueVar}, ${tail.valVar}]`,
7836
+ `${ind(ctx)}${outV} = ${valueMode === "tail" ? tail.valVar : `[${selector.valueVar}, ${tail.valVar}]`}`,
7638
7837
  `${ind(ctx)}${outE} = ${tail.endVar}`,
7639
7838
  ...coverageHit(ctx, coverageId, pos, tail.endVar)
7640
7839
  );
@@ -7649,7 +7848,7 @@ function emitDispatchCombinator(parser2, def, ctx, pos) {
7649
7848
  }
7650
7849
  const emitMatcherTails = () => {
7651
7850
  for (const matcher of def.matchers ?? []) {
7652
- emitSelectedTail(matcher, wroteBranch ? "else if" : "if", emitDispatchMatcherCondition(keyV, matcher), coverageIds[coverageIndex++]);
7851
+ emitSelectedTail(matcher, wroteBranch ? "else if" : "if", emitDispatchMatcherCondition(ctx, keyV, matcher), coverageIds[coverageIndex++]);
7653
7852
  wroteBranch = true;
7654
7853
  }
7655
7854
  };
@@ -7674,10 +7873,10 @@ function emitDispatchKeyCondition(valueVar, key, caseInsensitive) {
7674
7873
  }
7675
7874
  return parts.join(" && ");
7676
7875
  }
7677
- function emitDispatchMatcherCondition(valueVar, matcher) {
7876
+ function emitDispatchMatcherCondition(ctx, valueVar, matcher) {
7678
7877
  if (matcher.kind === "matches") {
7679
7878
  const flags = matcher.caseInsensitive && !matcher.flags?.includes("i") ? `${matcher.flags ?? ""}i` : matcher.flags ?? "";
7680
- return `${new RegExp(matcher.value, flags).toString()}.test(${valueVar})`;
7879
+ return `${ensurePlainRegexDecl(ctx, matcher.value, flags)}.test(${valueVar})`;
7681
7880
  }
7682
7881
  const text = matcher.value;
7683
7882
  const parts = [`${valueVar}.length >= ${text.length}`];
@@ -7880,6 +8079,28 @@ function emitsAsNamedFn(p, ctx) {
7880
8079
  const usage = ctx.lazyUsage;
7881
8080
  return !!usage && !ctx.noHoist && !ctx.capAsTrivia && isHoistableTag(p._def.tag) && (usage.counts.get(p) ?? 0) > 1 && (usage.sizes.get(p) ?? 0) >= HOIST_MIN_SUBTREE;
7882
8081
  }
8082
+ function routedNeedsContextBridge(p, ctx, seen = /* @__PURE__ */ new Set()) {
8083
+ if (seen.has(p)) return false;
8084
+ seen.add(p);
8085
+ if (p._def.tag === "lazy") {
8086
+ if (ctx.ruleNames?.has(p) || ctx.namedParsers.has(p)) return parserUsesRouted2(p);
8087
+ const usage = ctx.lazyUsage;
8088
+ if (usage && (usage.counts.get(p) ?? 0) <= 1 && !usage.recursive.has(p)) {
8089
+ try {
8090
+ return routedNeedsContextBridge(p._def.thunk(), ctx, seen);
8091
+ } catch {
8092
+ return parserUsesRouted2(p);
8093
+ }
8094
+ }
8095
+ return parserUsesRouted2(p);
8096
+ }
8097
+ if (ctx.ruleNames?.has(p)) return parserUsesRouted2(p);
8098
+ if (ctx.namedParsers.has(p)) return parserUsesRouted2(p);
8099
+ const d = p._def;
8100
+ if (d.tag === "dispatch") return false;
8101
+ if (d.tag === "withCtx") return parserUsesRouted2(d.parser);
8102
+ return childrenOf2(d).some((child) => routedNeedsContextBridge(child, ctx, seen));
8103
+ }
7883
8104
  function armReplayInScope(arm, ctx) {
7884
8105
  let p = arm;
7885
8106
  for (; ; ) {
@@ -8002,14 +8223,15 @@ function emitMany(def, ctx, pos) {
8002
8223
  `${ind(ctx)}const ${markV} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`,
8003
8224
  `${ind(ctx)}const ${markTl} = _ctx._cstTriviaLog ? _ctx._cstTriviaLog.length : 0`,
8004
8225
  `${ind(ctx)}const ${markLog} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`,
8005
- `${ind(ctx)}const ${npV} = ${capFn}(input, ${curV}, _ctx, 1)`
8226
+ `${ind(ctx)}const ${npV} = ${capFn}(input, ${curV}, _ctx, 1)`,
8227
+ ...emitLineTrack(ctx, curV, npV)
8006
8228
  );
8007
8229
  itemPos = npV;
8008
8230
  rollback = `if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${markV}) _ctx._cstRawChildren.length = ${markV}; if (_ctx._cstTriviaLog && _ctx._cstTriviaLog.length !== ${markTl}) _ctx._cstTriviaLog.length = ${markTl}; if (_ctx._triviaLog && _ctx._triviaLog.length !== ${markLog}) _ctx._triviaLog.length = ${markLog}; `;
8009
8231
  } else {
8010
8232
  const trivFn = ensureTriviaFn(ctx);
8011
8233
  const npV = v(ctx, "_np");
8012
- stmts.push(`${ind(ctx)}const ${npV} = ${trivFn}(input, ${curV}, _ctx)`);
8234
+ stmts.push(`${ind(ctx)}const ${npV} = ${trivFn}(input, ${curV}, _ctx)`, ...emitLineTrack(ctx, curV, npV));
8013
8235
  itemPos = npV;
8014
8236
  }
8015
8237
  }
@@ -8130,15 +8352,16 @@ function emitSepBy(_p, def, ctx, pos) {
8130
8352
  const itemFailBreak = (sepEndVar, sepRb, postSepRb) => def.trailing === void 0 ? `${sepRb}break` : `${postSepRb}${curV} = ${sepEndVar}; break`;
8131
8353
  const postSepMarks = () => {
8132
8354
  if (def.trailing === void 0 || !ctx.capturing) return { decl: [], rb: "" };
8133
- const lv = v(ctx, "_tlv"), rw = v(ctx, "_trw"), tl = v(ctx, "_ttl"), lg = v(ctx, "_tlg");
8355
+ const lv = v(ctx, "_tlv"), rw = v(ctx, "_trw"), tl = v(ctx, "_ttl"), lg = v(ctx, "_tlg"), fl = v(ctx, "_tlf");
8134
8356
  return {
8135
8357
  decl: [
8136
8358
  `${ind(ctx)}const ${lv} = _ctx._cstLeaves ? _ctx._cstLeaves.length : 0`,
8137
8359
  `${ind(ctx)}const ${rw} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`,
8138
8360
  `${ind(ctx)}const ${tl} = _ctx._cstTriviaLog ? _ctx._cstTriviaLog.length : 0`,
8139
- `${ind(ctx)}const ${lg} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`
8361
+ `${ind(ctx)}const ${lg} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`,
8362
+ `${ind(ctx)}const ${fl} = _ctx._fields ? _ctx._fields.length : 0`
8140
8363
  ],
8141
- rb: `if (_ctx._cstLeaves && _ctx._cstLeaves.length !== ${lv}) _ctx._cstLeaves.length = ${lv}; if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${rw}) _ctx._cstRawChildren.length = ${rw}; if (_ctx._cstTriviaLog && _ctx._cstTriviaLog.length !== ${tl}) _ctx._cstTriviaLog.length = ${tl}; if (_ctx._triviaLog && _ctx._triviaLog.length !== ${lg}) _ctx._triviaLog.length = ${lg}; `
8364
+ rb: `if (_ctx._cstLeaves && _ctx._cstLeaves.length !== ${lv}) _ctx._cstLeaves.length = ${lv}; if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${rw}) _ctx._cstRawChildren.length = ${rw}; if (_ctx._cstTriviaLog && _ctx._cstTriviaLog.length !== ${tl}) _ctx._cstTriviaLog.length = ${tl}; if (_ctx._triviaLog && _ctx._triviaLog.length !== ${lg}) _ctx._triviaLog.length = ${lg}; if (_ctx._fields && _ctx._fields.length !== ${fl}) _ctx._fields.length = ${fl}; `
8142
8365
  };
8143
8366
  };
8144
8367
  if (rec) {
@@ -8177,23 +8400,26 @@ function emitSepBy(_p, def, ctx, pos) {
8177
8400
  const markTl = v(ctx, "_mktl");
8178
8401
  const markLog = v(ctx, "_mklg");
8179
8402
  const markLv = v(ctx, "_mklv");
8403
+ const markFld = v(ctx, "_mkf");
8180
8404
  const spV = v(ctx, "_sp");
8181
8405
  stmts.push(
8182
8406
  `${ind(ctx)}const ${markV} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`,
8183
8407
  `${ind(ctx)}const ${markTl} = _ctx._cstTriviaLog ? _ctx._cstTriviaLog.length : 0`,
8184
8408
  `${ind(ctx)}const ${markLog} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`,
8185
8409
  `${ind(ctx)}const ${markLv} = _ctx._cstLeaves ? _ctx._cstLeaves.length : 0`,
8186
- `${ind(ctx)}const ${spV} = ${capFn}(input, ${curV}, _ctx, 1)`
8410
+ `${ind(ctx)}const ${markFld} = _ctx._fields ? _ctx._fields.length : 0`,
8411
+ `${ind(ctx)}const ${spV} = ${capFn}(input, ${curV}, _ctx, 1)`,
8412
+ ...emitLineTrack(ctx, curV, spV)
8187
8413
  );
8188
8414
  sepAtPos = spV;
8189
- const rollbackToSep = `if (_ctx._cstLeaves && _ctx._cstLeaves.length !== ${markLv}) _ctx._cstLeaves.length = ${markLv}; if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${markV}) _ctx._cstRawChildren.length = ${markV}; if (_ctx._cstTriviaLog && _ctx._cstTriviaLog.length !== ${markTl}) _ctx._cstTriviaLog.length = ${markTl}; if (_ctx._triviaLog && _ctx._triviaLog.length !== ${markLog}) _ctx._triviaLog.length = ${markLog}; `;
8415
+ const rollbackToSep = `if (_ctx._cstLeaves && _ctx._cstLeaves.length !== ${markLv}) _ctx._cstLeaves.length = ${markLv}; if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${markV}) _ctx._cstRawChildren.length = ${markV}; if (_ctx._cstTriviaLog && _ctx._cstTriviaLog.length !== ${markTl}) _ctx._cstTriviaLog.length = ${markTl}; if (_ctx._triviaLog && _ctx._triviaLog.length !== ${markLog}) _ctx._triviaLog.length = ${markLog}; if (_ctx._fields && _ctx._fields.length !== ${markFld}) _ctx._fields.length = ${markFld}; `;
8190
8416
  const sep2 = emitFallible(def.separator, ctx, sepAtPos, true);
8191
8417
  const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = sep2;
8192
8418
  stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) { ${rollbackToSep}${sep2.mayCommit ? `if (_ctx._fc) ${committedFailBody(ctx)}; ` : ""}break }`);
8193
8419
  const post = postSepMarks();
8194
8420
  stmts.push(...post.decl);
8195
8421
  const npV = v(ctx, "_np");
8196
- stmts.push(`${ind(ctx)}const ${npV} = ${capFn}(input, ${sepEnd}, _ctx, 1)`);
8422
+ stmts.push(`${ind(ctx)}const ${npV} = ${capFn}(input, ${sepEnd}, _ctx, 1)`, ...emitLineTrack(ctx, sepEnd, npV));
8197
8423
  const next = emitFallible(def.parser, ctx, npV, true);
8198
8424
  const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = next;
8199
8425
  stmts.push(
@@ -8205,13 +8431,13 @@ function emitSepBy(_p, def, ctx, pos) {
8205
8431
  } else {
8206
8432
  const trivFn = ensureTriviaFn(ctx);
8207
8433
  const spV = v(ctx, "_sp");
8208
- stmts.push(`${ind(ctx)}const ${spV} = ${trivFn}(input, ${curV}, _ctx)`);
8434
+ stmts.push(`${ind(ctx)}const ${spV} = ${trivFn}(input, ${curV}, _ctx)`, ...emitLineTrack(ctx, curV, spV));
8209
8435
  sepAtPos = spV;
8210
8436
  const sep2 = emitFallible(def.separator, ctx, sepAtPos, true);
8211
8437
  const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = sep2;
8212
8438
  stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) { ${sep2.mayCommit ? `if (_ctx._fc) ${committedFailBody(ctx)}; ` : ""}break }`);
8213
8439
  const npV = v(ctx, "_np");
8214
- stmts.push(`${ind(ctx)}const ${npV} = ${trivFn}(input, ${sepEnd}, _ctx)`);
8440
+ stmts.push(`${ind(ctx)}const ${npV} = ${trivFn}(input, ${sepEnd}, _ctx)`, ...emitLineTrack(ctx, sepEnd, npV));
8215
8441
  const next = emitFallible(def.parser, ctx, npV, true);
8216
8442
  const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = next;
8217
8443
  stmts.push(
@@ -8224,16 +8450,18 @@ function emitSepBy(_p, def, ctx, pos) {
8224
8450
  } else {
8225
8451
  const markLv = ctx.capturing ? v(ctx, "_mklv") : null;
8226
8452
  const markRw = ctx.capturing ? v(ctx, "_mkrw") : null;
8453
+ const markFld = ctx.capturing ? v(ctx, "_mkf") : null;
8227
8454
  if (markLv) {
8228
8455
  stmts.push(
8229
8456
  `${ind(ctx)}const ${markLv} = _ctx._cstLeaves ? _ctx._cstLeaves.length : 0`,
8230
- `${ind(ctx)}const ${markRw} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`
8457
+ `${ind(ctx)}const ${markRw} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`,
8458
+ `${ind(ctx)}const ${markFld} = _ctx._fields ? _ctx._fields.length : 0`
8231
8459
  );
8232
8460
  }
8233
8461
  const sep2 = emitFallible(def.separator, ctx, sepAtPos, true);
8234
8462
  const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = sep2;
8235
8463
  stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) { ${sep2.mayCommit ? `if (_ctx._fc) ${committedFailBody(ctx)}; ` : ""}break }`);
8236
- const nextRb = markLv ? `if (_ctx._cstLeaves && _ctx._cstLeaves.length !== ${markLv}) _ctx._cstLeaves.length = ${markLv}; if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${markRw}) _ctx._cstRawChildren.length = ${markRw}; ` : "";
8464
+ const nextRb = markLv ? `if (_ctx._cstLeaves && _ctx._cstLeaves.length !== ${markLv}) _ctx._cstLeaves.length = ${markLv}; if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${markRw}) _ctx._cstRawChildren.length = ${markRw}; if (_ctx._fields && _ctx._fields.length !== ${markFld}) _ctx._fields.length = ${markFld}; ` : "";
8237
8465
  const post = postSepMarks();
8238
8466
  stmts.push(...post.decl);
8239
8467
  const next = emitFallible(def.parser, ctx, sepEnd, true);
@@ -8296,6 +8524,7 @@ function emitScanTo(def, ctx, pos) {
8296
8524
  }
8297
8525
  const valV = v(ctx);
8298
8526
  stmts.push(`${ind(ctx)}const ${valV} = input.slice(${pos}, ${curV})`);
8527
+ stmts.push(...emitLineTrack(ctx, pos, curV));
8299
8528
  if (ctx.capturing) {
8300
8529
  const cap = reindentStmts(emitLeafCapture(ctx, valV, pos, curV), ctx.indent + 1);
8301
8530
  stmts.push(`${ind(ctx)}if (${curV} > ${pos}) {`, ...cap, `${ind(ctx)}}`);
@@ -8303,7 +8532,7 @@ function emitScanTo(def, ctx, pos) {
8303
8532
  return { stmts, valueVar: valV, endVar: curV };
8304
8533
  }
8305
8534
  function emitNot(def, ctx, pos) {
8306
- const sinksLive = !!ctx.capturing || !!ctx.recovery;
8535
+ const sinksLive = !!ctx.capturing || !!ctx.recovery || !!ctx.activeTrivia;
8307
8536
  const leaves = sinksLive ? v(ctx, "_ntl") : null;
8308
8537
  const raw = sinksLive ? v(ctx, "_ntr") : null;
8309
8538
  const tl = sinksLive ? v(ctx, "_ntt") : null;
@@ -8342,6 +8571,17 @@ function emitPeek(def, ctx, pos) {
8342
8571
  };
8343
8572
  }
8344
8573
  function emitRouted(ctx, pos) {
8574
+ const local = ctx.routedLocal;
8575
+ if (local !== void 0) {
8576
+ return {
8577
+ stmts: [
8578
+ ...emitIfFail(ctx, `${local.startVar} !== ${pos}`, failBody(ctx, '"routed()"', pos)),
8579
+ ...emitLeafCapture(ctx, local.valueVar, local.startVar, local.endVar)
8580
+ ],
8581
+ valueVar: local.valueVar,
8582
+ endVar: local.endVar
8583
+ };
8584
+ }
8345
8585
  const item = v(ctx, "_rt");
8346
8586
  return {
8347
8587
  stmts: [
@@ -8428,7 +8668,7 @@ function tokenNullableRegex(def) {
8428
8668
  }
8429
8669
  function emitToken(def, ctx, pos) {
8430
8670
  const lowered = tokenNullableRegex(def);
8431
- if (lowered) return emitRegex(lowered, ctx, pos);
8671
+ if (lowered) return emitRegex(lowered, ctx, pos, def.parser._meta.canMatchNewline);
8432
8672
  const savedTrivia = ctx.activeTrivia;
8433
8673
  const savedKindLabels = ctx.triviaKindLabels;
8434
8674
  ctx.activeTrivia = void 0;
@@ -8578,7 +8818,7 @@ ${i}const ${chV} = ${chAlloc}, ${rawV} = ${profileRecognizer} ? undefined : [],
8578
8818
  stmts.push(...innerStmts);
8579
8819
  if (def.trailingTrivia === true && ctx.activeTrivia) {
8580
8820
  const triviaFn = ensureTriviaFn(ctx);
8581
- stmts.push(`${i}const ${endVar} = ${okVar} ? ${triviaFn}(input, ${innerEndVar}, _ctx, 1) : ${innerEndVar}`);
8821
+ stmts.push(`${i}const ${endVar} = ${okVar} ? ${triviaFn}(input, ${innerEndVar}, _ctx, 1) : ${innerEndVar}`, ...emitLineTrack(ctx, innerEndVar, endVar));
8582
8822
  }
8583
8823
  if (sf && fArr) {
8584
8824
  stmts.push(`${i}const ${fArr} = _ctx._fields`);
@@ -8618,8 +8858,11 @@ ${i}const ${chV} = ${chAlloc}, ${rawV} = ${profileRecognizer} ? undefined : [],
8618
8858
  );
8619
8859
  }
8620
8860
  const ndV = v(ctx, "_nd");
8621
- const buildExpr = structural ? `{ _tag: 'node', type: ${JSON.stringify(def.type)}, span: { start: ${pos}, end: ${endVar} }, state: ${stV} ?? null, children: ${chV} }` : mkType ? emitInlineMkNodeExpr(mkType, chV, rawV, pos, endVar, tlV) : def.project !== void 0 ? emitNodeProjectExpr(def.type, def.project, chV) : `${buildRef(ctx)}[${buildIdx}](${chV}, ${fObj}, { start: ${pos}, end: ${endVar} }, ${rawV}, ${tlV}, ${stV})`;
8622
- const hostBuildExpr = `_ctx._pmProfile?.phase === 'host' && _ctx._pmProfile.hostCalls++, _ctx.build(${JSON.stringify(def.type)}, ${chV}, ${fObj}, { start: ${pos}, end: ${endVar} }, ${rawV}, ${tlV}, ${stV})`;
8861
+ const nodeSpanExpr = emitSpanExpr(ctx, pos, endVar);
8862
+ const nodeSpanV = ctx.lineTracking ? v(ctx, "_nspan") : nodeSpanExpr;
8863
+ if (ctx.lineTracking) stmts.push(`${i}const ${nodeSpanV} = ${nodeSpanExpr}`);
8864
+ const buildExpr = structural ? `{ _tag: 'node', type: ${JSON.stringify(def.type)}, span: ${nodeSpanV}, state: ${stV} ?? null, children: ${chV} }` : mkType ? emitInlineMkNodeExpr(mkType, chV, rawV, nodeSpanV, tlV) : def.project !== void 0 ? emitNodeProjectExpr(def.type, def.project, chV) : `${buildRef(ctx)}[${buildIdx}](${chV}, ${fObj}, ${nodeSpanV}, ${rawV}, ${tlV}, ${stV})`;
8865
+ const hostBuildExpr = `_ctx._pmProfile?.phase === 'host' && _ctx._pmProfile.hostCalls++, _ctx.build(${JSON.stringify(def.type)}, ${chV}, ${fObj}, ${nodeSpanV}, ${rawV}, ${tlV}, ${stV})`;
8623
8866
  const ndExpr = structural ? `_ctx.build !== undefined ? (${hostBuildExpr}) : (${buildExpr})` : cstOut ? hostBuildExpr : buildExpr;
8624
8867
  const hostCollapseExpr = structural ? `_ctx.build !== undefined && _ctx.build._parsemanCstCollapse !== undefined && ${chV}.length === 1 && ${rawV}.length === 1 && _ctx.build._parsemanCstCollapse(${JSON.stringify(def.type)}, ${chV}[0], ${chV}, ${rawV}) ? ${chV}[0] : (${ndExpr})` : ndExpr;
8625
8868
  const unwrapExpr = `${chV}.length === 1 ? (${chV}[0] !== null && typeof ${chV}[0] === 'object' && ${chV}[0]._tag === 'leaf' ? ${chV}[0].value : ${chV}[0]) : (${ndExpr})`;
@@ -8629,7 +8872,7 @@ ${i}const ${chV} = ${chAlloc}, ${rawV} = ${profileRecognizer} ? undefined : [],
8629
8872
  `${i}const ${ndV} = (${profileRecognizer} || ${profileCapture}) ? undefined : (${finalExpr})`,
8630
8873
  `${i}if (!(${profileRecognizer})) {`,
8631
8874
  `${i} if (${sc}) ${sc}.push(${ndV})`,
8632
- `${i} if (${sr}) ${sr}.push((typeof ${ndV} === 'object' && ${ndV} !== null && (${ndV}._tag === 'node' || ${ndV}._tag === 'leaf' || ${ndV}._tag === 'parseError')) ? ${ndV} : { _tag: 'leaf', value: typeof ${ndV} === 'string' ? ${ndV} : (typeof ${ndV} === 'object' && ${ndV} !== null ? input.slice(${pos}, ${endVar}) : ''), span: { start: ${pos}, end: ${endVar} } })`,
8875
+ `${i} if (${sr}) ${sr}.push((typeof ${ndV} === 'object' && ${ndV} !== null && (${ndV}._tag === 'node' || ${ndV}._tag === 'leaf' || ${ndV}._tag === 'parseError')) ? ${ndV} : { _tag: 'leaf', value: typeof ${ndV} === 'string' ? ${ndV} : (typeof ${ndV} === 'object' && ${ndV} !== null ? input.slice(${pos}, ${endVar}) : ''), span: ${nodeSpanV} })`,
8633
8876
  `${i}}`
8634
8877
  );
8635
8878
  return { stmts, valueVar: ndV, endVar };
@@ -8645,7 +8888,8 @@ function emitRuntimeFallback(parser2, ctx, pos) {
8645
8888
  `${ind(ctx)}const ${rv} = _rp[${idx}].parse(input, ${pos}, _ctx)`,
8646
8889
  ...emitIfFail(ctx, `!${rv}.ok`, failStmt),
8647
8890
  `${ind(ctx)}const ${vv} = ${rv}.value`,
8648
- `${ind(ctx)}const ${ev} = ${rv}.span.end`
8891
+ `${ind(ctx)}const ${ev} = ${rv}.span.end`,
8892
+ ...parser2._meta.canMatchNewline ? emitLineTrack(ctx, pos, ev) : []
8649
8893
  ];
8650
8894
  return { stmts, valueVar: vv, endVar: ev };
8651
8895
  }
@@ -8711,7 +8955,8 @@ function emitRecover(def, ctx, pos) {
8711
8955
  `${ind0} if (${sentOk}) break`,
8712
8956
  `${ind0} ${scanV}++`,
8713
8957
  `${ind0} }`,
8714
- `${ind0} const ${errV} = { _tag: 'parseError', span: { start: ${pos}, end: ${scanV} }, expected: ${JSON.stringify(deriveExpected(def.parser))} }`,
8958
+ ...emitLineTrack(ctx, pos, scanV).map((s) => `${ind0} ${s.trim()}`),
8959
+ `${ind0} const ${errV} = { _tag: 'parseError', span: ${emitSpanExpr(ctx, pos, scanV)}, expected: ${JSON.stringify(deriveExpected(def.parser))} }`,
8715
8960
  `${ind0} if (_ctx._errors) _ctx._errors.push(${errV})`,
8716
8961
  `${ind0} ${valVar} = ${errV}`,
8717
8962
  `${ind0} ${endVar} = ${scanV}`,
@@ -8727,7 +8972,7 @@ function emitExpect(def, ctx, pos) {
8727
8972
  const stmts = [
8728
8973
  ...innerStmts,
8729
8974
  `${ind0}if (!${okVar}) {`,
8730
- `${ind0} const ${errV} = { _tag: 'parseError', span: { start: ${pos}, end: ${pos} }, expected: ${JSON.stringify(def.expected)} }`,
8975
+ `${ind0} const ${errV} = { _tag: 'parseError', span: ${emitSpanExpr(ctx, pos, pos)}, expected: ${JSON.stringify(def.expected)} }`,
8731
8976
  `${ind0} if (_ctx._errors) _ctx._errors.push(${errV})`,
8732
8977
  // Embed the missing-token error as a `parseError` CST child, mirroring the
8733
8978
  // interpreter (expect.ts) and the list-recovery emit sites — guarded on
@@ -8817,7 +9062,7 @@ function emitDispatch(p, ctx, pos) {
8817
9062
  case "literal":
8818
9063
  return emitLit(def, ctx, pos);
8819
9064
  case "regex":
8820
- return emitRegex(def, ctx, pos);
9065
+ return emitRegex(def, ctx, pos, p._meta.canMatchNewline);
8821
9066
  case "keywords":
8822
9067
  return emitKeywords(def, ctx, pos);
8823
9068
  case "sequence":
@@ -8837,6 +9082,9 @@ function emitDispatch(p, ctx, pos) {
8837
9082
  return emitSepBy(p, def, ctx, pos);
8838
9083
  case "transform": {
8839
9084
  const fnSrc = transformFnSource(def.fn, def.fnSrc);
9085
+ if (fnSrc && def.parser._def.tag === "dispatch" && isDispatchTailOnlyTransform(fnSrc)) {
9086
+ return emitDispatchCombinator(def.parser, def.parser._def, ctx, pos, "tail");
9087
+ }
8840
9088
  if (fnSrc && def.parser._def.tag === "sequence") {
8841
9089
  const seqR = emitSeqValues(def.parser._def, ctx, pos);
8842
9090
  const inlined = tryInlineDestructureTransform(fnSrc, seqR.valueVars);
@@ -9064,6 +9312,20 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
9064
9312
  return false;
9065
9313
  }
9066
9314
  }
9315
+ function hasLineTrackingDef(p, seen = /* @__PURE__ */ new Set()) {
9316
+ if (seen.has(p)) return false;
9317
+ seen.add(p);
9318
+ const d = p._def;
9319
+ if (d.tag === "grammar" && d.trackLines) return true;
9320
+ if (d.tag === "lazy") {
9321
+ try {
9322
+ return hasLineTrackingDef(d.thunk(), seen);
9323
+ } catch {
9324
+ return false;
9325
+ }
9326
+ }
9327
+ return childrenOf2(d).some((child) => hasLineTrackingDef(child, seen));
9328
+ }
9067
9329
  function parserUsesRouted2(p, seen = /* @__PURE__ */ new Set()) {
9068
9330
  if (seen.has(p)) return false;
9069
9331
  seen.add(p);
@@ -9431,6 +9693,7 @@ function compile(combinator, mapFnSources, opts) {
9431
9693
  capturing: hasNodeDef(combinator),
9432
9694
  recovery: opts?.recovery ?? false,
9433
9695
  hostMode: opts?.hostMode ?? grammarHostMode ?? "ast",
9696
+ lineTracking: opts?.trackLines === true || hasLineTrackingDef(combinator),
9434
9697
  ...opts?.coverage ? { coverage: { plan: buildGrammarPlan(combinator), entry: combinator } } : {},
9435
9698
  lazyUsage: analyzeLazyUsage(combinator),
9436
9699
  ...grammarTrivia ? { activeTrivia: grammarTrivia, triviaKindLabels: grammarTrivia._meta.triviaKindLabels } : {},
@@ -9454,9 +9717,13 @@ function compile(combinator, mapFnSources, opts) {
9454
9717
  const namedPrelude = ctx.namedFnDecls.length > 0 ? [...namedFnPrelude(), ""] : [];
9455
9718
  const emptyTlDecls = ctx.needsEmptyTl ? ["const _EMPTY_TL = Object.freeze([])"] : [];
9456
9719
  const hostReadsDecls = ctx.needsHostReads ? [HOST_READS_DECL] : [];
9720
+ const lineTrackDecls = ctx.needsLineTrack ? [LINE_TRACK_DECL] : [];
9721
+ const lineSpanDecls = ctx.needsLineSpan ? [LINE_SPAN_DECL] : [];
9457
9722
  const source = [
9458
9723
  ...emptyTlDecls,
9459
9724
  ...hostReadsDecls,
9725
+ ...lineTrackDecls,
9726
+ ...lineSpanDecls,
9460
9727
  ...ctx.regexDecls,
9461
9728
  ...ctx.expectedDecls,
9462
9729
  "",
@@ -9469,6 +9736,8 @@ function compile(combinator, mapFnSources, opts) {
9469
9736
  const fn = new Function("input", "_pos", "_rp", "_mf", "_build", "_ctx", [
9470
9737
  ...emptyTlDecls,
9471
9738
  ...hostReadsDecls,
9739
+ ...lineTrackDecls,
9740
+ ...lineSpanDecls,
9472
9741
  ...ctx.regexDecls,
9473
9742
  ...ctx.expectedDecls,
9474
9743
  ...namedPrelude,
@@ -9487,6 +9756,25 @@ function compile(combinator, mapFnSources, opts) {
9487
9756
  trackLines: false,
9488
9757
  ...ctx.triviaKindLabels ? { triviaKindLabels: ctx.triviaKindLabels } : {}
9489
9758
  };
9759
+ const annotateWithTrackedLines = (result, lineStarts) => {
9760
+ const index = normalizeLineIndex({ lineStarts });
9761
+ const annotated = { ...result, span: annotateSpan(result.span, index) };
9762
+ const errors = annotated.errors;
9763
+ if (errors) {
9764
+ ;
9765
+ annotated.errors = errors.map((error) => ({
9766
+ ...error,
9767
+ span: annotateSpan(error.span, index)
9768
+ }));
9769
+ }
9770
+ return annotated;
9771
+ };
9772
+ const trackedCtx = (base, input, pos) => {
9773
+ if (!ctx.lineTracking) return base;
9774
+ const lineIndex = { lineStarts: [0] };
9775
+ if (pos > 0) recordLineRange(lineIndex, input, 0, pos);
9776
+ return { ...base, trackLines: true, _lineStarts: lineIndex.lineStarts, _lineScannedTo: pos };
9777
+ };
9490
9778
  const derivedSrcs = ctx.mapFnSrcs.length === ctx.mapFns.length && ctx.mapFnSrcs.every((s) => s !== null) ? ctx.mapFnSrcs : void 0;
9491
9779
  const effectiveSources = mapFnSources ?? derivedSrcs;
9492
9780
  const buildCovered = ctx.buildFns.length === 0 || ctx.buildSrcs.every((s) => s !== null);
@@ -9494,17 +9782,46 @@ function compile(combinator, mapFnSources, opts) {
9494
9782
  const mfCovered = ctx.mapFns.length === 0 || effectiveSources !== void 0 && effectiveSources.length === ctx.mapFns.length;
9495
9783
  const canInline = ctx.runtimeParsers.length === 0 && mfCovered && buildCovered;
9496
9784
  const inlineExpression = canInline ? buildInlineExpression(ctx, r, effectiveSources, buildSources, coverageRootRuleId) : null;
9497
- return {
9785
+ const compiledMeta = {
9498
9786
  source,
9499
9787
  inlineExpression,
9500
9788
  ...ctx.coverage === void 0 ? {} : { coverageDefinitions: ctx.coverage.plan.definitions },
9501
- ...gatingReport === void 0 ? {} : { gating: gatingReport },
9789
+ ...gatingReport === void 0 ? {} : { gating: gatingReport }
9790
+ };
9791
+ if (!ctx.lineTracking) {
9792
+ return {
9793
+ ...compiledMeta,
9794
+ parse(input, pos = 0) {
9795
+ return fn(input, pos, ctx.runtimeParsers, ctx.mapFns, ctx.buildFns, defaultCtx);
9796
+ },
9797
+ parseWithContext(input, parseCtx, pos = 0) {
9798
+ assertHostModeCompatible(ctx.hostMode ?? "ast", parseCtx.build, !!ctx.hostBranchElided);
9799
+ return fn(input, pos, ctx.runtimeParsers, ctx.mapFns, ctx.buildFns, parseCtx);
9800
+ },
9801
+ // Note: collects expect() errors via _errors. Unlike interpreter
9802
+ // parse({recover:true}) it does NOT populate furthestFail — the compiled path
9803
+ // inlines failures for throughput and deliberately skips _probe bookkeeping.
9804
+ // Callers wanting a furthest-position diagnostic detect unconsumed input
9805
+ // (span.end < input.length) instead, which is mode-agnostic.
9806
+ parseWithErrors(input, pos = 0) {
9807
+ const errors = [];
9808
+ const result = fn(input, pos, ctx.runtimeParsers, ctx.mapFns, ctx.buildFns, { ...defaultCtx, _errors: errors });
9809
+ return { ...result, errors };
9810
+ }
9811
+ };
9812
+ }
9813
+ return {
9814
+ ...compiledMeta,
9502
9815
  parse(input, pos = 0) {
9503
- return fn(input, pos, ctx.runtimeParsers, ctx.mapFns, ctx.buildFns, defaultCtx);
9816
+ const parseCtx = trackedCtx(defaultCtx, input, pos);
9817
+ const result = fn(input, pos, ctx.runtimeParsers, ctx.mapFns, ctx.buildFns, parseCtx);
9818
+ return annotateWithTrackedLines(result, parseCtx._lineStarts);
9504
9819
  },
9505
9820
  parseWithContext(input, parseCtx, pos = 0) {
9506
9821
  assertHostModeCompatible(ctx.hostMode ?? "ast", parseCtx.build, !!ctx.hostBranchElided);
9507
- return fn(input, pos, ctx.runtimeParsers, ctx.mapFns, ctx.buildFns, parseCtx);
9822
+ const activeCtx = trackedCtx(parseCtx, input, pos);
9823
+ const result = fn(input, pos, ctx.runtimeParsers, ctx.mapFns, ctx.buildFns, activeCtx);
9824
+ return activeCtx.trackLines ? annotateWithTrackedLines(result, activeCtx._lineStarts) : result;
9508
9825
  },
9509
9826
  // Note: collects expect() errors via _errors. Unlike interpreter
9510
9827
  // parse({recover:true}) it does NOT populate furthestFail — the compiled path
@@ -9513,8 +9830,9 @@ function compile(combinator, mapFnSources, opts) {
9513
9830
  // (span.end < input.length) instead, which is mode-agnostic.
9514
9831
  parseWithErrors(input, pos = 0) {
9515
9832
  const errors = [];
9516
- const result = fn(input, pos, ctx.runtimeParsers, ctx.mapFns, ctx.buildFns, { ...defaultCtx, _errors: errors });
9517
- return { ...result, errors };
9833
+ const parseCtx = trackedCtx({ ...defaultCtx, _errors: errors }, input, pos);
9834
+ const result = { ...fn(input, pos, ctx.runtimeParsers, ctx.mapFns, ctx.buildFns, parseCtx), errors };
9835
+ return annotateWithTrackedLines(result, parseCtx._lineStarts);
9518
9836
  }
9519
9837
  };
9520
9838
  }
@@ -9526,8 +9844,8 @@ function assertRuleName(name) {
9526
9844
  );
9527
9845
  }
9528
9846
  }
9529
- function publicRuleWrapperSource(rule, fnSource) {
9530
- const labels = rule._meta.triviaKindLabels;
9847
+ function publicRuleWrapperSource(rule, fnSource, ambientTriviaKindLabels) {
9848
+ const labels = rule._meta.triviaKindLabels ?? ambientTriviaKindLabels;
9531
9849
  if (labels === void 0) return fnSource;
9532
9850
  return `Object.assign(${fnSource}, { _meta: { triviaKindLabels: ${JSON.stringify(labels)} } })`;
9533
9851
  }
@@ -9598,6 +9916,8 @@ function compileRuleMap(ruleMap, opts) {
9598
9916
  const hoistedDecls = [
9599
9917
  ctx.needsEmptyTl ? ` const _EMPTY_TL = Object.freeze([])` : "",
9600
9918
  ctx.needsHostReads ? ` ${HOST_READS_DECL}` : "",
9919
+ ctx.needsLineTrack ? ` ${LINE_TRACK_DECL}` : "",
9920
+ ctx.needsLineSpan ? ` ${LINE_SPAN_DECL}` : "",
9601
9921
  ...ctx.regexDecls.map((d) => ` ${d}`),
9602
9922
  ...ctx.expectedDecls.map((d) => ` ${d}`),
9603
9923
  mfDecl,
@@ -9635,7 +9955,7 @@ function compileRuleMap(ruleMap, opts) {
9635
9955
  return [`function(input, _pos, _ctx) {`, ...body, `}`].join("\n");
9636
9956
  };
9637
9957
  const objBody = perEntry.map(({ key, rule, r }) => {
9638
- const src = publicRuleWrapperSource(rule, entryFnText(r, rule));
9958
+ const src = publicRuleWrapperSource(rule, entryFnText(r, rule), ctx.triviaKindLabels);
9639
9959
  return ` ${JSON.stringify(key)}: ${src.split("\n").join("\n ")}`;
9640
9960
  }).join(",\n");
9641
9961
  const replacement = [
@@ -9822,7 +10142,7 @@ function compileLinkable(ruleMapArg, ns, opts) {
9822
10142
  ...r.stmts,
9823
10143
  ` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
9824
10144
  `}`
9825
- ].join("\n")));
10145
+ ].join("\n"), ctx.triviaKindLabels));
9826
10146
  }
9827
10147
  const firstSets = /* @__PURE__ */ new Map();
9828
10148
  const firstSetRecipes = /* @__PURE__ */ new Map();
@@ -9927,12 +10247,16 @@ function buildInlineExpression(ctx, r, mapFnSources, buildSources, coverageRootR
9927
10247
  const buildDecl = buildSources?.length ? ` const _build = [${buildSources.join(", ")}]` : "";
9928
10248
  const emptyTlDecl = ctx.needsEmptyTl ? ` const _EMPTY_TL = Object.freeze([])` : "";
9929
10249
  const hostReadsDecl = ctx.needsHostReads ? ` ${HOST_READS_DECL}` : "";
9930
- const needsWrapper = ctx.regexDecls.length > 0 || ctx.expectedDecls.length > 0 || ctx.namedFnDecls.length > 0 || !!mfDecl || !!buildDecl || !!emptyTlDecl || !!hostReadsDecl;
10250
+ const lineTrackDecl = ctx.needsLineTrack ? ` ${LINE_TRACK_DECL}` : "";
10251
+ const lineSpanDecl = ctx.needsLineSpan ? ` ${LINE_SPAN_DECL}` : "";
10252
+ const needsWrapper = ctx.regexDecls.length > 0 || ctx.expectedDecls.length > 0 || ctx.namedFnDecls.length > 0 || !!mfDecl || !!buildDecl || !!emptyTlDecl || !!hostReadsDecl || !!lineTrackDecl || !!lineSpanDecl;
9931
10253
  if (!needsWrapper) return innerFn;
9932
10254
  const namedPrelude = ctx.namedFnDecls.length > 0 ? namedFnPrelude() : [];
9933
10255
  const hoistedDecls = [
9934
10256
  emptyTlDecl,
9935
10257
  hostReadsDecl,
10258
+ lineTrackDecl,
10259
+ lineSpanDecl,
9936
10260
  ...ctx.regexDecls.map((d) => ` ${d}`),
9937
10261
  ...ctx.expectedDecls.map((d) => ` ${d}`),
9938
10262
  mfDecl,
@@ -10471,7 +10795,7 @@ function normalizeCstCollapse(collapse) {
10471
10795
  return typeof collapse === "function" ? collapse : void 0;
10472
10796
  }
10473
10797
  function buildCstNode(type, children2, _fields, span, _rawChildren, _triviaLog, state) {
10474
- return { _tag: "node", type, span: { start: span.start, end: span.end }, state: state ?? null, children: [...children2] };
10798
+ return { _tag: "node", type, span: { ...span }, state: state ?? null, children: [...children2] };
10475
10799
  }
10476
10800
  function cstBuildHost(typeOrOptions, children2, _fields, span, rawChildren, triviaLog, state) {
10477
10801
  if (typeof typeOrOptions === "string") {
@@ -10675,6 +10999,10 @@ function gate(predicate) {
10675
10999
  };
10676
11000
  }
10677
11001
 
11002
+ // src/cst/trivia-entries.ts
11003
+ var EMPTY_INDICES = Object.freeze([]);
11004
+ var EMPTY_GAPS = Object.freeze([]);
11005
+
10678
11006
  // src/cst/offset-model.ts
10679
11007
  var { isFinite } = Number;
10680
11008