parseman 0.6.1 → 0.7.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.
package/dist/index.d.ts CHANGED
@@ -13,7 +13,7 @@ export { not } from './combinators/not.ts';
13
13
  export { node } from './combinators/node.ts';
14
14
  export type { BuildNode } from './combinators/node.ts';
15
15
  export { transform, skip, trivia, label } from './combinators/map.ts';
16
- export { parse, parser } from './combinators/grammar.ts';
16
+ export { parse, parser, noTrivia } from './combinators/grammar.ts';
17
17
  export type { ParseOptions, ParserOptions, ParsemanParser } from './combinators/grammar.ts';
18
18
  export { compile } from './compiler/codegen.ts';
19
19
  export type { CompiledParser } from './compiler/codegen.ts';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAEjM,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAA;AAClD,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAE9D,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAC9C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AACpE,YAAY,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAEhE,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAChD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AAC1E,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AAC/C,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAC1C,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAA;AAC5C,YAAY,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAEtD,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AACrE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAA;AACxD,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAE3F,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAA;AAC/C,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAE3D,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACxF,YAAY,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAEzD,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAA;AAClD,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAC5D,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAC1D,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAE5D,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAE5G,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,YAAY,EAAE,aAAa,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAChG,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AACzF,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACvD,YAAY,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAEjM,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAA;AAClD,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAE9D,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAC9C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AACpE,YAAY,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAEhE,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAChD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AAC1E,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AAC/C,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAC1C,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAA;AAC5C,YAAY,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAEtD,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AACrE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAClE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAE3F,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAA;AAC/C,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAE3D,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACxF,YAAY,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAEzD,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAA;AAClD,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAC5D,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAC1D,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAE5D,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAE5G,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,YAAY,EAAE,aAAa,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAChG,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AACzF,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACvD,YAAY,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA"}
package/dist/index.js CHANGED
@@ -982,8 +982,10 @@ function optional(combinator) {
982
982
  _meta: meta,
983
983
  _def: { tag: "optional", parser: combinator },
984
984
  parse(input, pos, ctx) {
985
+ const mark = saveTriviaMark(ctx);
985
986
  const result = combinator.parse(input, pos, ctx);
986
987
  if (result.ok) return result;
988
+ rollbackTrivia(ctx, mark);
987
989
  return { ok: true, value: null, span: { start: pos, end: pos } };
988
990
  }
989
991
  };
@@ -1004,7 +1006,7 @@ function sepBy(combinator, separator) {
1004
1006
  const values = [first.value];
1005
1007
  let cur = first.span.end;
1006
1008
  while (cur < input.length) {
1007
- let mark = saveTriviaMark(ctx);
1009
+ const loopMark = saveTriviaMark(ctx);
1008
1010
  let sepPos = cur;
1009
1011
  if (ctx.trivia) {
1010
1012
  if (needsDeferredTriviaCommit(ctx)) {
@@ -1017,10 +1019,9 @@ function sepBy(combinator, separator) {
1017
1019
  }
1018
1020
  const sep = separator.parse(input, sepPos, ctx);
1019
1021
  if (!sep.ok) {
1020
- rollbackTrivia(ctx, mark);
1022
+ rollbackTrivia(ctx, loopMark);
1021
1023
  break;
1022
1024
  }
1023
- mark = saveTriviaMark(ctx);
1024
1025
  let nextPos = sep.span.end;
1025
1026
  if (ctx.trivia) {
1026
1027
  if (needsDeferredTriviaCommit(ctx)) {
@@ -1033,7 +1034,7 @@ function sepBy(combinator, separator) {
1033
1034
  }
1034
1035
  const next = combinator.parse(input, nextPos, ctx);
1035
1036
  if (!next.ok) {
1036
- rollbackTrivia(ctx, mark);
1037
+ rollbackTrivia(ctx, loopMark);
1037
1038
  break;
1038
1039
  }
1039
1040
  values.push(next.value);
@@ -1236,13 +1237,15 @@ function annotateSpan(span, index) {
1236
1237
 
1237
1238
  // src/combinators/grammar.ts
1238
1239
  function parser(opts, root) {
1240
+ const clearTrivia = opts.trivia === null;
1239
1241
  return {
1240
1242
  _tag: "grammar",
1241
1243
  _meta: root._meta,
1242
1244
  _def: {
1243
1245
  tag: "grammar",
1244
1246
  parser: root,
1245
- triviaParser: opts.trivia,
1247
+ triviaParser: clearTrivia ? void 0 : opts.trivia ?? void 0,
1248
+ clearTrivia,
1246
1249
  trackLines: opts.trackLines ?? false
1247
1250
  },
1248
1251
  parse(input, pos, _ctx) {
@@ -1250,7 +1253,11 @@ function parser(opts, root) {
1250
1253
  const ctx = {
1251
1254
  ..._ctx,
1252
1255
  trackLines,
1253
- ...opts.trivia !== void 0 ? {
1256
+ // trivia: null clears (contiguous terms); a Combinator sets; undefined inherits.
1257
+ ...clearTrivia ? {
1258
+ trivia: void 0,
1259
+ triviaKindLabels: void 0
1260
+ } : opts.trivia != null ? {
1254
1261
  trivia: opts.trivia,
1255
1262
  ...opts.trivia._meta.triviaKindLabels ? { triviaKindLabels: opts.trivia._meta.triviaKindLabels } : {}
1256
1263
  } : {},
@@ -1265,6 +1272,9 @@ function parser(opts, root) {
1265
1272
  }
1266
1273
  };
1267
1274
  }
1275
+ function noTrivia(root) {
1276
+ return parser({ trivia: null }, root);
1277
+ }
1268
1278
  function parse(combinator, input, opts = {}) {
1269
1279
  const trackLines = opts.trackLines ?? false;
1270
1280
  const _errors = opts.recover ? [] : void 0;
@@ -1603,6 +1613,41 @@ function v(ctx, prefix = "_v") {
1603
1613
  function ind(ctx) {
1604
1614
  return " ".repeat(ctx.indent);
1605
1615
  }
1616
+ function reindentStmts(stmts, targetLevels) {
1617
+ const nonEmpty = stmts.filter((s) => s.trim().length > 0);
1618
+ if (nonEmpty.length === 0) return stmts;
1619
+ const minLeading = Math.min(...nonEmpty.map((s) => s.length - s.trimStart().length));
1620
+ const targetPrefix = " ".repeat(targetLevels);
1621
+ return stmts.map((s) => s.trim().length === 0 ? "" : targetPrefix + s.slice(minLeading));
1622
+ }
1623
+ function failReturn(expected, posExpr) {
1624
+ return `return { ok: false, expected: [${expected}], span: { start: ${posExpr}, end: ${posExpr} } }`;
1625
+ }
1626
+ function failReturnArr(expectedArr, posExpr) {
1627
+ return `return { ok: false, expected: ${expectedArr}, span: { start: ${posExpr}, end: ${posExpr} } }`;
1628
+ }
1629
+ function failBody(ctx, expected, posExpr) {
1630
+ if (ctx.failLabel) return `break ${ctx.failLabel}`;
1631
+ return failReturn(expected, posExpr);
1632
+ }
1633
+ function failArrBody(ctx, expectedArr, posExpr) {
1634
+ if (ctx.failLabel) return `break ${ctx.failLabel}`;
1635
+ return failReturnArr(expectedArr, posExpr);
1636
+ }
1637
+ function emitIfFail(ctx, cond, body) {
1638
+ return [
1639
+ `${ind(ctx)}if (${cond}) {`,
1640
+ `${ind(ctx)} ${body}`,
1641
+ `${ind(ctx)}}`
1642
+ ];
1643
+ }
1644
+ function emitElseFail(ctx, body) {
1645
+ return [
1646
+ `${ind(ctx)}else {`,
1647
+ `${ind(ctx)} ${body}`,
1648
+ `${ind(ctx)}}`
1649
+ ];
1650
+ }
1606
1651
  var NAMED_FN_FAIL = "_pfFail";
1607
1652
  var NAMED_FN_END = "_pfEnd";
1608
1653
  function namedFnPrelude() {
@@ -1613,8 +1658,10 @@ function pushNamedFnDecl(ctx, fnName, bodyStmts, valueVar, endVar) {
1613
1658
  `function ${fnName}(input, _pos, _ctx) {`,
1614
1659
  ` let _pfok = false, _pfv, _pfe = _pos`,
1615
1660
  ` _pfail: {`,
1616
- ...bodyStmts,
1617
- ` _pfv = ${valueVar}; _pfe = ${endVar}; _pfok = true`,
1661
+ ...reindentStmts(bodyStmts, 2),
1662
+ ` _pfv = ${valueVar}`,
1663
+ ` _pfe = ${endVar}`,
1664
+ ` _pfok = true`,
1618
1665
  ` }`,
1619
1666
  ` if (!_pfok) return ${NAMED_FN_FAIL}`,
1620
1667
  ` ${NAMED_FN_END} = _pfe`,
@@ -1628,7 +1675,7 @@ function emitNamedFnCall(ctx, fnName, pos, failExpected) {
1628
1675
  return {
1629
1676
  stmts: [
1630
1677
  `${ind(ctx)}const ${vv} = ${fnName}(input, ${pos}, _ctx)`,
1631
- `${ind(ctx)}if (${vv} === ${NAMED_FN_FAIL}) ${failStmt({ ...ctx, indent: 0 }, failExpected, pos).trim()}`,
1678
+ ...emitIfFail(ctx, `${vv} === ${NAMED_FN_FAIL}`, failBody(ctx, failExpected, pos)),
1632
1679
  `${ind(ctx)}const ${ev} = ${NAMED_FN_END}`
1633
1680
  ],
1634
1681
  valueVar: vv,
@@ -1711,7 +1758,7 @@ function ensureTriviaFn(ctx) {
1711
1758
  `function ${fnName}(input, _pos, _ctx, _cap) {`,
1712
1759
  ` let _e = _pos`,
1713
1760
  ` _triv: {`,
1714
- ...r.stmts,
1761
+ ...reindentStmts(r.stmts, 2),
1715
1762
  ` _e = ${r.endVar}`,
1716
1763
  ` }`,
1717
1764
  ` if (_cap && _e > _pos) {`,
@@ -1726,14 +1773,6 @@ function ensureTriviaFn(ctx) {
1726
1773
  function ensureTriviaCaptureFn(ctx) {
1727
1774
  return ensureTriviaFn(ctx);
1728
1775
  }
1729
- function failStmt(ctx, expected, posExpr) {
1730
- if (ctx.failLabel) return `${ind(ctx)}break ${ctx.failLabel}`;
1731
- return `${ind(ctx)}return { ok: false, expected: [${expected}], span: { start: ${posExpr}, end: ${posExpr} } }`;
1732
- }
1733
- function failArr(ctx, expectedArr, posExpr) {
1734
- if (ctx.failLabel) return `${ind(ctx)}break ${ctx.failLabel}`;
1735
- return `${ind(ctx)}return { ok: false, expected: ${expectedArr}, span: { start: ${posExpr}, end: ${posExpr} } }`;
1736
- }
1737
1776
  function firstSetCond(codeVar, fs) {
1738
1777
  if (fs.kind === "any") return "true";
1739
1778
  if (fs.kind === "empty") return "false";
@@ -1749,19 +1788,32 @@ function emitFallible(inner, ctx, pos) {
1749
1788
  const savedLabel = ctx.failLabel;
1750
1789
  const savedIndent = ctx.indent;
1751
1790
  ctx.failLabel = lbl;
1752
- ctx.indent = 0;
1791
+ ctx.indent = savedIndent + 1;
1753
1792
  const r = emit(inner, ctx, pos);
1754
1793
  ctx.failLabel = savedLabel;
1755
1794
  ctx.indent = savedIndent;
1756
1795
  const ind0 = ind(ctx);
1796
+ const mL = ctx.capturing ? v(ctx, "_fcl") : null;
1797
+ const mR = ctx.capturing ? v(ctx, "_fcr") : null;
1798
+ const mTl = ctx.capturing ? v(ctx, "_fctl") : null;
1799
+ const mLg = ctx.capturing ? v(ctx, "_fclg") : null;
1757
1800
  const stmts = [
1758
1801
  `${ind0}let ${okV} = false, ${valV}, ${endV} = ${pos}`,
1802
+ ...mL ? [
1803
+ `${ind0}const ${mL} = _ctx._cstLeaves?.length ?? 0`,
1804
+ `${ind0}const ${mR} = _ctx._cstRawChildren?.length ?? 0`,
1805
+ `${ind0}const ${mTl} = _ctx._cstTriviaLog?.length ?? 0`,
1806
+ `${ind0}const ${mLg} = _ctx._triviaLog?.length ?? 0`
1807
+ ] : [],
1759
1808
  `${ind0}${lbl}: {`,
1760
1809
  ...r.stmts,
1761
1810
  `${ind0} ${valV} = ${r.valueVar}`,
1762
1811
  `${ind0} ${endV} = ${r.endVar}`,
1763
1812
  `${ind0} ${okV} = true`,
1764
- `${ind0}}`
1813
+ `${ind0}}`,
1814
+ ...mL ? [
1815
+ `${ind0}if (!${okV}) { if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${mL}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${mR}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${mTl}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${mLg} }`
1816
+ ] : []
1765
1817
  ];
1766
1818
  return { stmts, okVar: okV, valVar: valV, endVar: endV };
1767
1819
  }
@@ -1774,9 +1826,9 @@ function emitLit(def, ctx, pos) {
1774
1826
  if (caseInsensitive) {
1775
1827
  ctx.needsCollator = true;
1776
1828
  stmts.push(
1777
- `${ind(ctx)}if (${pos} + ${len} > input.length) ${failStmt({ ...ctx, indent: 0 }, expectedStr, pos).trim()}`,
1829
+ ...emitIfFail(ctx, `${pos} + ${len} > input.length`, failBody(ctx, expectedStr, pos)),
1778
1830
  `${ind(ctx)}const ${vv}_s = input.slice(${pos}, ${pos} + ${len})`,
1779
- `${ind(ctx)}if (_collator.compare(${vv}_s, ${JSON.stringify(value)}) !== 0) ${failStmt({ ...ctx, indent: 0 }, expectedStr, pos).trim()}`,
1831
+ ...emitIfFail(ctx, `_collator.compare(${vv}_s, ${JSON.stringify(value)}) !== 0`, failBody(ctx, expectedStr, pos)),
1780
1832
  `${ind(ctx)}const ${vv} = ${vv}_s`
1781
1833
  );
1782
1834
  } else if (len === 0) {
@@ -1784,7 +1836,7 @@ function emitLit(def, ctx, pos) {
1784
1836
  } else if (len === 1) {
1785
1837
  const code = value.codePointAt(0);
1786
1838
  stmts.push(
1787
- `${ind(ctx)}if (${pos} >= input.length || input.charCodeAt(${pos}) !== ${code}) ${failStmt({ ...ctx, indent: 0 }, expectedStr, pos).trim()}`,
1839
+ ...emitIfFail(ctx, `${pos} >= input.length || input.charCodeAt(${pos}) !== ${code}`, failBody(ctx, expectedStr, pos)),
1788
1840
  `${ind(ctx)}const ${vv} = ${JSON.stringify(value)}`
1789
1841
  );
1790
1842
  } else if (len <= 4) {
@@ -1793,12 +1845,12 @@ function emitLit(def, ctx, pos) {
1793
1845
  (_, i) => `input.charCodeAt(${pos}${i > 0 ? ` + ${i}` : ""}) !== ${value.codePointAt(i)}`
1794
1846
  ).join(" || ");
1795
1847
  stmts.push(
1796
- `${ind(ctx)}if (${pos} + ${len} > input.length || ${checks}) ${failStmt({ ...ctx, indent: 0 }, expectedStr, pos).trim()}`,
1848
+ ...emitIfFail(ctx, `${pos} + ${len} > input.length || ${checks}`, failBody(ctx, expectedStr, pos)),
1797
1849
  `${ind(ctx)}const ${vv} = ${JSON.stringify(value)}`
1798
1850
  );
1799
1851
  } else {
1800
1852
  stmts.push(
1801
- `${ind(ctx)}if (!input.startsWith(${JSON.stringify(value)}, ${pos})) ${failStmt({ ...ctx, indent: 0 }, expectedStr, pos).trim()}`,
1853
+ ...emitIfFail(ctx, `!input.startsWith(${JSON.stringify(value)}, ${pos})`, failBody(ctx, expectedStr, pos)),
1802
1854
  `${ind(ctx)}const ${vv} = ${JSON.stringify(value)}`
1803
1855
  );
1804
1856
  }
@@ -1826,7 +1878,7 @@ function emitKeywords(def, ctx, pos) {
1826
1878
  const stmts = [
1827
1879
  `${ind(ctx)}${rName}.lastIndex = ${pos}`,
1828
1880
  `${ind(ctx)}const ${mv} = ${rName}.exec(input)`,
1829
- `${ind(ctx)}if (${mv} === null) ${failStmt({ ...ctx, indent: 0 }, '"keyword"', pos).trim()}`,
1881
+ ...emitIfFail(ctx, `${mv} === null`, failBody(ctx, '"keyword"', pos)),
1830
1882
  `${ind(ctx)}const ${vv} = ${mv}[0]`
1831
1883
  ];
1832
1884
  const endVar = `${pos} + ${vv}.length`;
@@ -1848,7 +1900,7 @@ function emitRegex(def, ctx, pos) {
1848
1900
  const stmts = [
1849
1901
  `${ind(ctx)}${rName}.lastIndex = ${pos}`,
1850
1902
  `${ind(ctx)}const ${mv} = ${rName}.exec(input)`,
1851
- `${ind(ctx)}if (${mv} === null) ${failStmt({ ...ctx, indent: 0 }, expectedStr, pos).trim()}`,
1903
+ ...emitIfFail(ctx, `${mv} === null`, failBody(ctx, expectedStr, pos)),
1852
1904
  `${ind(ctx)}const ${vv} = ${mv}[0]`
1853
1905
  ];
1854
1906
  const endVar = `${pos} + ${vv}.length`;
@@ -1929,11 +1981,12 @@ function emitChoice(def, ctx, pos) {
1929
1981
  ctx.indent++;
1930
1982
  const r = emit(p, ctx, pos);
1931
1983
  stmts.push(...r.stmts);
1932
- stmts.push(`${ind(ctx)}${valV} = ${r.valueVar}; ${endV} = ${r.endVar}`);
1984
+ stmts.push(`${ind(ctx)}${valV} = ${r.valueVar}`);
1985
+ stmts.push(`${ind(ctx)}${endV} = ${r.endVar}`);
1933
1986
  ctx.indent--;
1934
1987
  stmts.push(`${ind(ctx)}}`);
1935
1988
  }
1936
- stmts.push(`${ind(ctx)}else ${failArr({ ...ctx, indent: 0 }, allExpected, pos)}`);
1989
+ stmts.push(...emitElseFail(ctx, failArrBody(ctx, allExpected, pos)));
1937
1990
  return { stmts, valueVar: valV, endVar: endV };
1938
1991
  }
1939
1992
  return emitNonDisjoint(def, def.strategy, allExpected, ctx, pos);
@@ -1956,7 +2009,7 @@ function emitGreedyClassify(def, superIndex, allExpected, ctx, pos) {
1956
2009
  const stmts = [
1957
2010
  `${ind(ctx)}${reVar}.lastIndex = ${pos}`,
1958
2011
  `${ind(ctx)}const ${matchV} = ${reVar}.exec(input)`,
1959
- `${ind(ctx)}if (${matchV} === null) ${failArr({ ...ctx, indent: 0 }, allExpected, pos)}`,
2012
+ ...emitIfFail(ctx, `${matchV} === null`, failArrBody(ctx, allExpected, pos)),
1960
2013
  `${ind(ctx)}const ${wordV} = ${matchV}[0]`,
1961
2014
  `${ind(ctx)}const ${endV} = ${pos} + ${wordV}.length`,
1962
2015
  `${ind(ctx)}let ${valV}`
@@ -2005,12 +2058,13 @@ function emitLiteralsLongestFirst(def, sortedIndices, allExpected, ctx, pos) {
2005
2058
  stmts.push(
2006
2059
  ...emitLeafCapture(ctx, JSON.stringify(litVal), pos, litEnd),
2007
2060
  ...tR.stmts,
2008
- `${ind(ctx)}${valV} = ${tR.valueVar}; ${endV} = ${litEnd}`
2061
+ `${ind(ctx)}${valV} = ${tR.valueVar}`,
2062
+ `${ind(ctx)}${endV} = ${litEnd}`
2009
2063
  );
2010
2064
  ctx.indent--;
2011
2065
  stmts.push(`${ind(ctx)}}`);
2012
2066
  }
2013
- stmts.push(`${ind(ctx)}else ${failArr({ ...ctx, indent: 0 }, allExpected, pos)}`);
2067
+ stmts.push(...emitElseFail(ctx, failArrBody(ctx, allExpected, pos)));
2014
2068
  return { stmts, valueVar: valV, endVar: endV };
2015
2069
  }
2016
2070
  function emitFirstMatch(def, allExpected, ctx, pos) {
@@ -2056,17 +2110,26 @@ function emitFirstMatch(def, allExpected, ctx, pos) {
2056
2110
  const rejectCond = autoNot.map(
2057
2111
  (check) => check.kind === "firstSet" ? firstSetCond(anCode, check.set) : `input.startsWith(${JSON.stringify(check.value)}, ${endVar})`
2058
2112
  ).join(" || ");
2059
- stmts.push(
2060
- `${ind0} if (${okVar}) { const ${anCode} = ${endVar} < input.length ? input.charCodeAt(${endVar}) : -1; if (!(${rejectCond})) { ${resValV} = ${valVar}; ${resEndV} = ${endVar}; ${resOkV} = true } }`
2061
- );
2113
+ stmts.push(`${ind0} if (${okVar}) {`);
2114
+ stmts.push(`${ind0} const ${anCode} = ${endVar} < input.length ? input.charCodeAt(${endVar}) : -1`);
2115
+ stmts.push(`${ind0} if (!(${rejectCond})) {`);
2116
+ stmts.push(`${ind0} ${resValV} = ${valVar}`);
2117
+ stmts.push(`${ind0} ${resEndV} = ${endVar}`);
2118
+ stmts.push(`${ind0} ${resOkV} = true`);
2119
+ stmts.push(`${ind0} }`);
2120
+ stmts.push(`${ind0} }`);
2062
2121
  if (rollback) stmts.push(`${ind0} if (!${resOkV}) { ${rollback} }`);
2063
2122
  } else {
2064
- stmts.push(`${ind0} if (${okVar}) { ${resValV} = ${valVar}; ${resEndV} = ${endVar}; ${resOkV} = true }`);
2123
+ stmts.push(`${ind0} if (${okVar}) {`);
2124
+ stmts.push(`${ind0} ${resValV} = ${valVar}`);
2125
+ stmts.push(`${ind0} ${resEndV} = ${endVar}`);
2126
+ stmts.push(`${ind0} ${resOkV} = true`);
2127
+ stmts.push(`${ind0} }`);
2065
2128
  if (rollback) stmts.push(`${ind0} else { ${rollback} }`);
2066
2129
  }
2067
2130
  stmts.push(`${ind0}}`);
2068
2131
  }
2069
- stmts.push(`${ind0}if (!${resOkV}) ${failArr({ ...ctx, indent: 0 }, allExpected, pos)}`);
2132
+ stmts.push(...emitIfFail(ctx, `!${resOkV}`, failArrBody(ctx, allExpected, pos)));
2070
2133
  return { stmts, valueVar: resValV, endVar: resEndV };
2071
2134
  }
2072
2135
  function emitNonDisjoint(def, strategy, allExpected, ctx, pos) {
@@ -2191,32 +2254,26 @@ function emitSepBy(_p, def, ctx, pos) {
2191
2254
  const markV = v(ctx, "_mk");
2192
2255
  const markTl = v(ctx, "_mktl");
2193
2256
  const markLog = v(ctx, "_mklg");
2257
+ const markLv = v(ctx, "_mklv");
2194
2258
  const spV = v(ctx, "_sp");
2195
2259
  stmts.push(
2196
2260
  `${ind(ctx)}const ${markV} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`,
2197
2261
  `${ind(ctx)}const ${markTl} = _ctx._cstTriviaLog ? _ctx._cstTriviaLog.length : 0`,
2198
2262
  `${ind(ctx)}const ${markLog} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`,
2263
+ `${ind(ctx)}const ${markLv} = _ctx._cstLeaves ? _ctx._cstLeaves.length : 0`,
2199
2264
  `${ind(ctx)}const ${spV} = ${capFn}(input, ${curV}, _ctx, 1)`
2200
2265
  );
2201
2266
  sepAtPos = spV;
2202
- const sepRollback = `if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markV}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${markTl}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${markLog}; `;
2267
+ const rollbackToSep = `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${markLv}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markV}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${markTl}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${markLog}; `;
2203
2268
  const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos);
2204
- stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) { ${sepRollback}break }`);
2205
- const mark2V = v(ctx, "_mk2");
2206
- const mark2Tl = v(ctx, "_mktl2");
2207
- const mark2Log = v(ctx, "_mklg2");
2269
+ stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) { ${rollbackToSep}break }`);
2208
2270
  const npV = v(ctx, "_np");
2209
- stmts.push(
2210
- `${ind(ctx)}const ${mark2V} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`,
2211
- `${ind(ctx)}const ${mark2Tl} = _ctx._cstTriviaLog ? _ctx._cstTriviaLog.length : 0`,
2212
- `${ind(ctx)}const ${mark2Log} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`,
2213
- `${ind(ctx)}const ${npV} = ${capFn}(input, ${sepEnd}, _ctx, 1)`
2214
- );
2215
- const nextRollback = `if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${mark2V}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${mark2Tl}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${mark2Log}; `;
2271
+ stmts.push(`${ind(ctx)}const ${npV} = ${capFn}(input, ${sepEnd}, _ctx, 1)`);
2216
2272
  const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, npV);
2217
2273
  stmts.push(
2218
2274
  ...nextStmts,
2219
- `${ind(ctx)}if (!${nextOk}) { ${nextRollback}break }`,
2275
+ // item failed → unwind the separator too, back to the end of the last item
2276
+ `${ind(ctx)}if (!${nextOk}) { ${rollbackToSep}break }`,
2220
2277
  `${ind(ctx)}${arrV}.push(${nextVal})`,
2221
2278
  `${ind(ctx)}${curV} = ${nextEnd}`
2222
2279
  );
@@ -2238,12 +2295,21 @@ function emitSepBy(_p, def, ctx, pos) {
2238
2295
  );
2239
2296
  }
2240
2297
  } else {
2298
+ const markLv = ctx.capturing ? v(ctx, "_mklv") : null;
2299
+ const markRw = ctx.capturing ? v(ctx, "_mkrw") : null;
2300
+ if (markLv) {
2301
+ stmts.push(
2302
+ `${ind(ctx)}const ${markLv} = _ctx._cstLeaves ? _ctx._cstLeaves.length : 0`,
2303
+ `${ind(ctx)}const ${markRw} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`
2304
+ );
2305
+ }
2241
2306
  const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos);
2242
2307
  stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) break`);
2308
+ const nextRb = markLv ? `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${markLv}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markRw}; ` : "";
2243
2309
  const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, sepEnd);
2244
2310
  stmts.push(
2245
2311
  ...nextStmts,
2246
- `${ind(ctx)}if (!${nextOk}) break`,
2312
+ `${ind(ctx)}if (!${nextOk}) { ${nextRb}break }`,
2247
2313
  `${ind(ctx)}${arrV}.push(${nextVal})`,
2248
2314
  `${ind(ctx)}${curV} = ${nextEnd}`
2249
2315
  );
@@ -2287,12 +2353,12 @@ function emitScanTo(def, ctx, pos) {
2287
2353
  if (!def.orEOF) {
2288
2354
  const sentDef = def.sentinel._def;
2289
2355
  const expectedStr = sentDef.tag === "literal" ? JSON.stringify([JSON.stringify(sentDef.value)]) : `["sentinel"]`;
2290
- stmts.push(`${ind(ctx)}if (!${foundV}) ${failArr({ ...ctx, indent: 0 }, expectedStr, pos)}`);
2356
+ stmts.push(...emitIfFail(ctx, `!${foundV}`, failArrBody(ctx, expectedStr, pos)));
2291
2357
  }
2292
2358
  const valV = v(ctx);
2293
2359
  stmts.push(`${ind(ctx)}const ${valV} = input.slice(${pos}, ${curV})`);
2294
2360
  if (ctx.capturing) {
2295
- const cap = emitLeafCapture(ctx, valV, pos, curV).map((s) => " " + s);
2361
+ const cap = reindentStmts(emitLeafCapture(ctx, valV, pos, curV), ctx.indent + 1);
2296
2362
  stmts.push(`${ind(ctx)}if (${curV} > ${pos}) {`, ...cap, `${ind(ctx)}}`);
2297
2363
  }
2298
2364
  return { stmts, valueVar: valV, endVar: curV };
@@ -2302,7 +2368,7 @@ function emitNot(def, ctx, pos) {
2302
2368
  return {
2303
2369
  stmts: [
2304
2370
  ...stmts,
2305
- `${ind(ctx)}if (${okVar}) ${failStmt({ ...ctx, indent: 0 }, '"not"', pos).trim()}`
2371
+ ...emitIfFail(ctx, okVar, failBody(ctx, '"not"', pos))
2306
2372
  ],
2307
2373
  valueVar: "null",
2308
2374
  endVar: pos
@@ -2329,7 +2395,7 @@ function emitNode(def, ctx, pos) {
2329
2395
  const { stmts: innerStmts, okVar, endVar } = emitFallible(def.parser, ctx, pos);
2330
2396
  stmts.push(...innerStmts);
2331
2397
  stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}`);
2332
- stmts.push(`${i}if (!${okVar}) ${failStmt({ ...ctx, indent: 0 }, '"node"', pos).trim()}`);
2398
+ stmts.push(...emitIfFail(ctx, `!${okVar}`, failBody(ctx, '"node"', pos)));
2333
2399
  const stV = v(ctx, "_nst");
2334
2400
  stmts.push(`${i}const ${stV} = _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
2335
2401
  const ndV = v(ctx, "_nd");
@@ -2349,7 +2415,7 @@ function emitRuntimeFallback(parser2, ctx, pos) {
2349
2415
  const ev = v(ctx, "_rte");
2350
2416
  const stmts = [
2351
2417
  `${ind(ctx)}const ${rv} = _rp[${idx}].parse(input, ${pos}, _ctx)`,
2352
- `${ind(ctx)}if (!${rv}.ok) ${failStmt({ ...ctx, indent: 0 }, '"runtime"', pos).trim()}`,
2418
+ ...emitIfFail(ctx, `!${rv}.ok`, failBody(ctx, '"runtime"', pos)),
2353
2419
  `${ind(ctx)}const ${vv} = ${rv}.value`,
2354
2420
  `${ind(ctx)}const ${ev} = ${rv}.span.end`
2355
2421
  ];
@@ -2383,16 +2449,14 @@ function emitRecover(def, ctx, pos) {
2383
2449
  const ind0 = ind(ctx);
2384
2450
  const scanV = v(ctx, "_sc");
2385
2451
  const errV = v(ctx, "_err");
2386
- const savedIndent = ctx.indent;
2387
- ctx.indent += 2;
2452
+ const whileBodyLevels = ctx.indent + 2;
2388
2453
  const { stmts: sentStmts, okVar: sentOk } = emitFallible(def.sentinel, ctx, scanV);
2389
- ctx.indent = savedIndent;
2390
2454
  const stmts = [
2391
2455
  ...innerStmts,
2392
2456
  `${ind0}if (!${okVar}) {`,
2393
2457
  `${ind0} let ${scanV} = ${pos}`,
2394
2458
  `${ind0} while (${scanV} < input.length) {`,
2395
- ...sentStmts,
2459
+ ...reindentStmts(sentStmts, whileBodyLevels),
2396
2460
  `${ind0} if (${sentOk}) break`,
2397
2461
  `${ind0} ${scanV}++`,
2398
2462
  `${ind0} }`,
@@ -2474,7 +2538,7 @@ function emit(p, ctx, pos) {
2474
2538
  // try skipped; if fails, keep main end
2475
2539
  `${ind(ctx)}let ${endV} = ${mainR.endVar}`,
2476
2540
  `${ind(ctx)}try {`,
2477
- ...skipR.stmts.map((s) => " " + s),
2541
+ ...reindentStmts(skipR.stmts, ctx.indent + 1),
2478
2542
  `${ind(ctx)} ${endV} = ${skipR.endVar}`,
2479
2543
  `${ind(ctx)}} catch {}`
2480
2544
  ],
@@ -2491,7 +2555,10 @@ function emit(p, ctx, pos) {
2491
2555
  case "grammar": {
2492
2556
  const savedTrivia = ctx.activeTrivia;
2493
2557
  const savedKindLabels = ctx.triviaKindLabels;
2494
- if (def.triviaParser) {
2558
+ if (def.clearTrivia) {
2559
+ ctx.activeTrivia = void 0;
2560
+ ctx.triviaKindLabels = void 0;
2561
+ } else if (def.triviaParser) {
2495
2562
  ctx.activeTrivia = def.triviaParser;
2496
2563
  if (def.triviaParser._meta.triviaKindLabels) {
2497
2564
  ctx.triviaKindLabels = def.triviaParser._meta.triviaKindLabels;
@@ -2516,7 +2583,7 @@ function emit(p, ctx, pos) {
2516
2583
  const vv = v(ctx);
2517
2584
  return {
2518
2585
  stmts: [
2519
- `${ind(ctx)}if (!_mf[${fnIdx}](_ctx.state)) ${failStmt({ ...ctx, indent: 0 }, '"gate"', pos).trim()}`,
2586
+ ...emitIfFail(ctx, `!_mf[${fnIdx}](_ctx.state)`, failBody(ctx, '"gate"', pos)),
2520
2587
  `${ind(ctx)}const ${vv} = null`
2521
2588
  ],
2522
2589
  valueVar: vv,
@@ -2548,7 +2615,7 @@ function emit(p, ctx, pos) {
2548
2615
  stmts: [
2549
2616
  `${ind(ctx)}const ${rv} = { ..._ctx, state: _mf[${evIdx}]() }`,
2550
2617
  `${ind(ctx)}const ${vv} = ${fn}(input, ${pos}, ${rv})`,
2551
- `${ind(ctx)}if (${vv} === ${NAMED_FN_FAIL}) ${failStmt({ ...ctx, indent: 0 }, '"withCtx"', pos).trim()}`,
2618
+ ...emitIfFail(ctx, `${vv} === ${NAMED_FN_FAIL}`, failBody(ctx, '"withCtx"', pos)),
2552
2619
  `${ind(ctx)}const ${ev} = ${NAMED_FN_END}`
2553
2620
  ],
2554
2621
  valueVar: vv,
@@ -2625,7 +2692,7 @@ function compile(combinator, mapFnSources) {
2625
2692
  ...ctx.regexDecls,
2626
2693
  "",
2627
2694
  ...namedPrelude,
2628
- ...ctx.namedFnDecls,
2695
+ ctx.namedFnDecls.join("\n\n"),
2629
2696
  `${collatorDecl}function _parse(input, _pos, _rp, _mf, _build, _ctx) {`,
2630
2697
  ` let pos = _pos`,
2631
2698
  ...r.stmts,
@@ -2636,7 +2703,7 @@ function compile(combinator, mapFnSources) {
2636
2703
  ...ctx.regexDecls,
2637
2704
  collatorDecl,
2638
2705
  ...namedPrelude,
2639
- ...ctx.namedFnDecls,
2706
+ ...ctx.namedFnDecls.flatMap((decl, i) => i > 0 ? ["", decl] : [decl]),
2640
2707
  `let pos = _pos`,
2641
2708
  ...r.stmts,
2642
2709
  `return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`
@@ -2671,7 +2738,7 @@ function compile(combinator, mapFnSources) {
2671
2738
  function buildInlineExpression(ctx, r, collatorDecl, mapFnSources, buildSources) {
2672
2739
  const bodyLines = [
2673
2740
  ` let pos = _pos`,
2674
- ...r.stmts.map((s) => ` ${s}`),
2741
+ ...r.stmts,
2675
2742
  ` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`
2676
2743
  ];
2677
2744
  const innerFn = [
@@ -2684,17 +2751,23 @@ function buildInlineExpression(ctx, r, collatorDecl, mapFnSources, buildSources)
2684
2751
  const needsWrapper = ctx.regexDecls.length > 0 || !!collatorDecl || ctx.namedFnDecls.length > 0 || !!mfDecl || !!buildDecl;
2685
2752
  if (!needsWrapper) return innerFn;
2686
2753
  const namedPrelude = ctx.namedFnDecls.length > 0 ? namedFnPrelude() : [];
2687
- return [
2688
- `/* @__PURE__ */ (() => {`,
2754
+ const hoistedDecls = [
2689
2755
  ...ctx.regexDecls.map((d) => ` ${d}`),
2690
2756
  collatorDecl ? ` ${collatorDecl.trim()}` : "",
2691
2757
  mfDecl,
2692
2758
  buildDecl,
2693
2759
  ...namedPrelude.map((l) => ` ${l}`),
2694
- ...ctx.namedFnDecls.flatMap((f) => f.split("\n").map((l) => ` ${l}`)),
2760
+ ...ctx.namedFnDecls.flatMap((decl, i) => {
2761
+ const lines = decl.split("\n").map((l) => ` ${l}`);
2762
+ return i > 0 ? ["", ...lines] : lines;
2763
+ })
2764
+ ].filter(Boolean);
2765
+ return [
2766
+ `/* @__PURE__ */ (() => {`,
2767
+ ...hoistedDecls,
2695
2768
  ` return ${innerFn}`,
2696
2769
  `})()`
2697
- ].filter(Boolean).join("\n");
2770
+ ].join("\n");
2698
2771
  }
2699
2772
 
2700
2773
  // src/combinators/guard.ts
@@ -3046,6 +3119,7 @@ export {
3046
3119
  makeFunctionalDoc,
3047
3120
  makeWord,
3048
3121
  many,
3122
+ noTrivia,
3049
3123
  node,
3050
3124
  not,
3051
3125
  offsetToLineCol,