parseman 0.26.0 → 0.26.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../../src/plugin/evaluator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EACV,UAAU,EAAE,IAAI,EAMjB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAa7C,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,CAAA;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB,CAAA;AACD,MAAM,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;AAM3C,KAAK,gBAAgB,GAAG;IAAE,GAAG,EAAE,aAAa,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAA;AA4dhE,0EAA0E;AAC1E,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,KAAK,EACZ,IAAI,CAAC,EAAE,MAAM,GACZ,gBAAgB,GAAG,IAAI,CAUzB;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,CAC1B,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,KAAK,EACZ,IAAI,CAAC,EAAE,MAAM,EACb,YAAY,CAAC,EAAE,MAAM,EAAE,GACtB,UAAU,CAAC,OAAO,CAAC,GAAG,IAAI,CAE5B;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,KAAK,EACZ,IAAI,CAAC,EAAE,MAAM,GACZ,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,CAM9B;AAiED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,UAAU,EACvB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EAAE,GACrB,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,GAAG,IAAI,CAqGzC;AAED,oEAAoE;AACpE,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG;IAAE,MAAM,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,IAAI,CAAA;CAAE,CAAA;AAQlF;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,KAAK,GACX,YAAY,GAAG,IAAI,CAQrB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,UAAU,EACpB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,MAAM,GACX,OAAO,CAoBT;AAED,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAcnF"}
1
+ {"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../../src/plugin/evaluator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EACV,UAAU,EAAE,IAAI,EAMjB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AA2E7C,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,CAAA;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB,CAAA;AACD,MAAM,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;AAM3C,KAAK,gBAAgB,GAAG;IAAE,GAAG,EAAE,aAAa,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAA;AA4dhE,0EAA0E;AAC1E,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,KAAK,EACZ,IAAI,CAAC,EAAE,MAAM,GACZ,gBAAgB,GAAG,IAAI,CAUzB;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,CAC1B,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,KAAK,EACZ,IAAI,CAAC,EAAE,MAAM,EACb,YAAY,CAAC,EAAE,MAAM,EAAE,GACtB,UAAU,CAAC,OAAO,CAAC,GAAG,IAAI,CAE5B;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,KAAK,EACZ,IAAI,CAAC,EAAE,MAAM,GACZ,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,CAM9B;AAiED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,UAAU,EACvB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EAAE,GACrB,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,GAAG,IAAI,CAqGzC;AAED,oEAAoE;AACpE,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG;IAAE,MAAM,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,IAAI,CAAA;CAAE,CAAA;AAQlF;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,KAAK,GACX,YAAY,GAAG,IAAI,CAQrB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,UAAU,EACpB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,MAAM,GACX,OAAO,CAoBT;AAED,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAcnF"}
@@ -912,12 +912,159 @@ function keywords(words, opts = {}) {
912
912
  };
913
913
  }
914
914
 
915
+ // src/recovery/scan.ts
916
+ function probeAt(sentinel, input, pos, ctx) {
917
+ const s = {
918
+ _probe: ctx._probe,
919
+ _errors: ctx._errors,
920
+ _cstLeaves: ctx._cstLeaves,
921
+ _cstChildren: ctx._cstChildren,
922
+ _cstRawChildren: ctx._cstRawChildren,
923
+ _cstTriviaLog: ctx._cstTriviaLog,
924
+ _triviaLog: ctx._triviaLog,
925
+ _fields: ctx._fields,
926
+ _cstBuf: ctx._cstBuf,
927
+ _tolerant: ctx._tolerant,
928
+ _sync: ctx._sync
929
+ };
930
+ ctx._probe = void 0;
931
+ ctx._errors = void 0;
932
+ ctx._cstLeaves = void 0;
933
+ ctx._cstChildren = void 0;
934
+ ctx._cstRawChildren = void 0;
935
+ ctx._cstTriviaLog = void 0;
936
+ ctx._triviaLog = void 0;
937
+ ctx._fields = void 0;
938
+ ctx._cstBuf = void 0;
939
+ ctx._tolerant = void 0;
940
+ ctx._sync = void 0;
941
+ try {
942
+ return sentinel.parse(input, pos, ctx).ok;
943
+ } finally {
944
+ ctx._probe = s._probe;
945
+ ctx._errors = s._errors;
946
+ ctx._cstLeaves = s._cstLeaves;
947
+ ctx._cstChildren = s._cstChildren;
948
+ ctx._cstRawChildren = s._cstRawChildren;
949
+ ctx._cstTriviaLog = s._cstTriviaLog;
950
+ ctx._triviaLog = s._triviaLog;
951
+ ctx._fields = s._fields;
952
+ ctx._cstBuf = s._cstBuf;
953
+ ctx._tolerant = s._tolerant;
954
+ ctx._sync = s._sync;
955
+ }
956
+ }
957
+ function orSentinel(a, b) {
958
+ if (b === void 0) return a;
959
+ return {
960
+ _tag: "orSentinel",
961
+ _meta: { firstSet: { kind: "any" }, canMatchNewline: false, isTrivia: false },
962
+ _def: { tag: "unknown" },
963
+ parse(input, pos, ctx) {
964
+ const ra = a.parse(input, pos, ctx);
965
+ if (ra.ok) return ra;
966
+ return b.parse(input, pos, ctx);
967
+ }
968
+ };
969
+ }
970
+ function firstSetSentinel(fs2) {
971
+ if (fs2.kind !== "ranges" || fs2.ranges.length === 0) return null;
972
+ const ranges = fs2.ranges;
973
+ return {
974
+ _tag: "firstSetSentinel",
975
+ _meta: { firstSet: fs2, canMatchNewline: false, isTrivia: false },
976
+ _def: { tag: "unknown" },
977
+ parse(input, pos) {
978
+ const code = pos < input.length ? input.codePointAt(pos) : void 0;
979
+ if (code !== void 0) {
980
+ for (const r of ranges) {
981
+ if (code >= r.lo && code <= r.hi) return { ok: true, value: null, span: { start: pos, end: pos } };
982
+ }
983
+ }
984
+ return { ok: false, expected: [], span: { start: pos, end: pos } };
985
+ }
986
+ };
987
+ }
988
+ function recoverScan(input, from, ctx, sync, expected) {
989
+ let scanPos = from;
990
+ while (scanPos < input.length && !probeAt(sync, input, scanPos, ctx)) scanPos++;
991
+ const error = { _tag: "parseError", span: { start: from, end: scanPos }, expected };
992
+ ctx._errors?.push(error);
993
+ return { error, end: scanPos };
994
+ }
995
+ function matchesAt(sentinel, input, pos, ctx) {
996
+ return probeAt(sentinel, input, pos, ctx);
997
+ }
998
+ function captureError(ctx, error) {
999
+ if (cstCaptureActive(ctx)) pushCstChild(ctx, error, error);
1000
+ }
1001
+
1002
+ // src/combinators/expect.ts
1003
+ function deriveExpected(c) {
1004
+ const def = c._def;
1005
+ switch (def.tag) {
1006
+ case "literal":
1007
+ return [JSON.stringify(def.value)];
1008
+ case "regex":
1009
+ return [`/${def.source}/`];
1010
+ case "keywords":
1011
+ return def.words.map((w) => JSON.stringify(w));
1012
+ case "label":
1013
+ return [def.label];
1014
+ case "choice":
1015
+ return def.parsers.flatMap(deriveExpected);
1016
+ case "sequence":
1017
+ return def.parsers.length > 0 ? deriveExpected(def.parsers[0]) : [];
1018
+ case "node":
1019
+ case "grammar":
1020
+ case "trivia":
1021
+ case "token":
1022
+ case "optional":
1023
+ case "many":
1024
+ case "oneOrMore":
1025
+ case "transform":
1026
+ case "not":
1027
+ return deriveExpected(def.parser);
1028
+ case "lazy": {
1029
+ const name = c._ruleName;
1030
+ try {
1031
+ return deriveExpected(def.thunk());
1032
+ } catch {
1033
+ return name ? [name] : [];
1034
+ }
1035
+ }
1036
+ default:
1037
+ return [];
1038
+ }
1039
+ }
1040
+ function expect(combinator, label2) {
1041
+ const expected = label2 !== void 0 ? [label2] : deriveExpected(combinator);
1042
+ const meta = {
1043
+ firstSet: combinator._meta.firstSet,
1044
+ canMatchNewline: combinator._meta.canMatchNewline,
1045
+ isTrivia: false
1046
+ };
1047
+ return {
1048
+ _tag: "expect",
1049
+ _meta: meta,
1050
+ _def: { tag: "expect", parser: combinator, label: label2, expected },
1051
+ parse(input, pos, ctx) {
1052
+ const result = combinator.parse(input, pos, ctx);
1053
+ if (result.ok) return result;
1054
+ const error = { _tag: "parseError", span: { start: pos, end: pos }, expected };
1055
+ ctx._errors?.push(error);
1056
+ if (ctx._tolerant) captureError(ctx, error);
1057
+ return { ok: true, value: error, span: { start: pos, end: pos } };
1058
+ }
1059
+ };
1060
+ }
1061
+
915
1062
  // src/combinators/choice.ts
916
1063
  function choice(...args) {
917
1064
  const parsers = args.map((a) => "gate" in a ? a.combinator : a);
918
1065
  const gates = args.map((a) => "gate" in a ? a.gate : null);
919
1066
  const hasGates = gates.some((g) => g !== null);
920
- const disjoint = !hasGates && areDisjoint(parsers.map((p) => p._meta.firstSet));
1067
+ const disjoint = areDisjoint(parsers.map((p) => p._meta.firstSet)) && parsers.every((p) => !matchesEmpty(p));
921
1068
  let combined = { kind: "empty" };
922
1069
  for (const p of parsers) combined = union(combined, p._meta.firstSet);
923
1070
  const meta = {
@@ -956,17 +1103,21 @@ function choice(...args) {
956
1103
  const expected = [];
957
1104
  if (disjoint && pos < input.length) {
958
1105
  const code = input.codePointAt(pos);
959
- let parser2 = code < 128 ? asciiDispatch?.[code] ?? null : null;
960
- if (!parser2) {
961
- for (const p of parsers) {
962
- if (inFirstSet(code, p._meta.firstSet)) {
963
- parser2 = p;
1106
+ let idx = code < 128 ? asciiDispatch[code] : -1;
1107
+ if (idx < 0) {
1108
+ for (let i = 0; i < parsers.length; i++) {
1109
+ if (inFirstSet(code, parsers[i]._meta.firstSet)) {
1110
+ idx = i;
964
1111
  break;
965
1112
  }
966
1113
  }
967
1114
  }
968
- if (parser2) {
969
- const result = parser2.parse(input, pos, ctx);
1115
+ if (idx >= 0) {
1116
+ const gate = gates[idx];
1117
+ if (gate && !gate(ctx.state)) {
1118
+ return { ok: false, expected: deriveExpected(parsers[idx]), span: { start: pos, end: pos } };
1119
+ }
1120
+ const result = parsers[idx].parse(input, pos, ctx);
970
1121
  if (result.ok) return result;
971
1122
  expected.push(...result.expected);
972
1123
  return { ok: false, expected, span: { start: pos, end: pos } };
@@ -1147,13 +1298,13 @@ function areDisjoint(sets) {
1147
1298
  return true;
1148
1299
  }
1149
1300
  function buildAsciiDispatch(parsers) {
1150
- const table = Array(128).fill(null);
1151
- for (const parser2 of parsers) {
1152
- const fs2 = parser2._meta.firstSet;
1301
+ const table = Array(128).fill(-1);
1302
+ for (let i = 0; i < parsers.length; i++) {
1303
+ const fs2 = parsers[i]._meta.firstSet;
1153
1304
  if (fs2.kind !== "ranges") continue;
1154
1305
  for (const { lo, hi } of fs2.ranges) {
1155
1306
  for (let code = Math.max(0, lo); code <= Math.min(127, hi); code++) {
1156
- table[code] = parser2;
1307
+ table[code] = i;
1157
1308
  }
1158
1309
  }
1159
1310
  }
@@ -1535,93 +1686,6 @@ function scanBlockComment(input, cur) {
1535
1686
  return close === -1 ? cur : close + 2;
1536
1687
  }
1537
1688
 
1538
- // src/recovery/scan.ts
1539
- function probeAt(sentinel, input, pos, ctx) {
1540
- const s = {
1541
- _probe: ctx._probe,
1542
- _errors: ctx._errors,
1543
- _cstLeaves: ctx._cstLeaves,
1544
- _cstChildren: ctx._cstChildren,
1545
- _cstRawChildren: ctx._cstRawChildren,
1546
- _cstTriviaLog: ctx._cstTriviaLog,
1547
- _triviaLog: ctx._triviaLog,
1548
- _fields: ctx._fields,
1549
- _cstBuf: ctx._cstBuf,
1550
- _tolerant: ctx._tolerant,
1551
- _sync: ctx._sync
1552
- };
1553
- ctx._probe = void 0;
1554
- ctx._errors = void 0;
1555
- ctx._cstLeaves = void 0;
1556
- ctx._cstChildren = void 0;
1557
- ctx._cstRawChildren = void 0;
1558
- ctx._cstTriviaLog = void 0;
1559
- ctx._triviaLog = void 0;
1560
- ctx._fields = void 0;
1561
- ctx._cstBuf = void 0;
1562
- ctx._tolerant = void 0;
1563
- ctx._sync = void 0;
1564
- try {
1565
- return sentinel.parse(input, pos, ctx).ok;
1566
- } finally {
1567
- ctx._probe = s._probe;
1568
- ctx._errors = s._errors;
1569
- ctx._cstLeaves = s._cstLeaves;
1570
- ctx._cstChildren = s._cstChildren;
1571
- ctx._cstRawChildren = s._cstRawChildren;
1572
- ctx._cstTriviaLog = s._cstTriviaLog;
1573
- ctx._triviaLog = s._triviaLog;
1574
- ctx._fields = s._fields;
1575
- ctx._cstBuf = s._cstBuf;
1576
- ctx._tolerant = s._tolerant;
1577
- ctx._sync = s._sync;
1578
- }
1579
- }
1580
- function orSentinel(a, b) {
1581
- if (b === void 0) return a;
1582
- return {
1583
- _tag: "orSentinel",
1584
- _meta: { firstSet: { kind: "any" }, canMatchNewline: false, isTrivia: false },
1585
- _def: { tag: "unknown" },
1586
- parse(input, pos, ctx) {
1587
- const ra = a.parse(input, pos, ctx);
1588
- if (ra.ok) return ra;
1589
- return b.parse(input, pos, ctx);
1590
- }
1591
- };
1592
- }
1593
- function firstSetSentinel(fs2) {
1594
- if (fs2.kind !== "ranges" || fs2.ranges.length === 0) return null;
1595
- const ranges = fs2.ranges;
1596
- return {
1597
- _tag: "firstSetSentinel",
1598
- _meta: { firstSet: fs2, canMatchNewline: false, isTrivia: false },
1599
- _def: { tag: "unknown" },
1600
- parse(input, pos) {
1601
- const code = pos < input.length ? input.codePointAt(pos) : void 0;
1602
- if (code !== void 0) {
1603
- for (const r of ranges) {
1604
- if (code >= r.lo && code <= r.hi) return { ok: true, value: null, span: { start: pos, end: pos } };
1605
- }
1606
- }
1607
- return { ok: false, expected: [], span: { start: pos, end: pos } };
1608
- }
1609
- };
1610
- }
1611
- function recoverScan(input, from, ctx, sync, expected) {
1612
- let scanPos = from;
1613
- while (scanPos < input.length && !probeAt(sync, input, scanPos, ctx)) scanPos++;
1614
- const error = { _tag: "parseError", span: { start: from, end: scanPos }, expected };
1615
- ctx._errors?.push(error);
1616
- return { error, end: scanPos };
1617
- }
1618
- function matchesAt(sentinel, input, pos, ctx) {
1619
- return probeAt(sentinel, input, pos, ctx);
1620
- }
1621
- function captureError(ctx, error) {
1622
- if (cstCaptureActive(ctx)) pushCstChild(ctx, error, error);
1623
- }
1624
-
1625
1689
  // src/combinators/sequence.ts
1626
1690
  function sequence(...parsers) {
1627
1691
  const meta = {
@@ -1723,66 +1787,6 @@ function sequence(...parsers) {
1723
1787
  };
1724
1788
  }
1725
1789
 
1726
- // src/combinators/expect.ts
1727
- function deriveExpected(c) {
1728
- const def = c._def;
1729
- switch (def.tag) {
1730
- case "literal":
1731
- return [JSON.stringify(def.value)];
1732
- case "regex":
1733
- return [`/${def.source}/`];
1734
- case "keywords":
1735
- return def.words.map((w) => JSON.stringify(w));
1736
- case "label":
1737
- return [def.label];
1738
- case "choice":
1739
- return def.parsers.flatMap(deriveExpected);
1740
- case "sequence":
1741
- return def.parsers.length > 0 ? deriveExpected(def.parsers[0]) : [];
1742
- case "node":
1743
- case "grammar":
1744
- case "trivia":
1745
- case "token":
1746
- case "optional":
1747
- case "many":
1748
- case "oneOrMore":
1749
- case "transform":
1750
- case "not":
1751
- return deriveExpected(def.parser);
1752
- case "lazy": {
1753
- const name = c._ruleName;
1754
- try {
1755
- return deriveExpected(def.thunk());
1756
- } catch {
1757
- return name ? [name] : [];
1758
- }
1759
- }
1760
- default:
1761
- return [];
1762
- }
1763
- }
1764
- function expect(combinator, label2) {
1765
- const expected = label2 !== void 0 ? [label2] : deriveExpected(combinator);
1766
- const meta = {
1767
- firstSet: combinator._meta.firstSet,
1768
- canMatchNewline: combinator._meta.canMatchNewline,
1769
- isTrivia: false
1770
- };
1771
- return {
1772
- _tag: "expect",
1773
- _meta: meta,
1774
- _def: { tag: "expect", parser: combinator, label: label2, expected },
1775
- parse(input, pos, ctx) {
1776
- const result = combinator.parse(input, pos, ctx);
1777
- if (result.ok) return result;
1778
- const error = { _tag: "parseError", span: { start: pos, end: pos }, expected };
1779
- ctx._errors?.push(error);
1780
- if (ctx._tolerant) captureError(ctx, error);
1781
- return { ok: true, value: error, span: { start: pos, end: pos } };
1782
- }
1783
- };
1784
- }
1785
-
1786
1790
  // src/combinators/repeat.ts
1787
1791
  function repItem(combinator, input, cur, ctx) {
1788
1792
  const mark = saveTriviaMark(ctx);
@@ -4559,6 +4563,21 @@ function emitDisjointArm(p, ctx, pos, valV, endV) {
4559
4563
  `${ind(ctx)}${endV} = ${endVar}`
4560
4564
  ];
4561
4565
  }
4566
+ function emitDisjointArmGated(def, i, ctx, pos, valV, endV) {
4567
+ const p = def.parsers[i];
4568
+ const gate = def.gates[i];
4569
+ if (!gate) return emitDisjointArm(p, ctx, pos, valV, endV);
4570
+ const gateIdx = ctx.mapFns.length;
4571
+ ctx.mapFns.push(gate);
4572
+ ctx.mapFnSrcs.push(def.gateSrcs?.[i] ?? null);
4573
+ const gateCond = `${mfRef(ctx)}[${gateIdx}](_ctx.state)`;
4574
+ const stmts = [`${ind(ctx)}if (${gateCond}) {`];
4575
+ ctx.indent++;
4576
+ stmts.push(...emitDisjointArm(p, ctx, pos, valV, endV));
4577
+ ctx.indent--;
4578
+ stmts.push(`${ind(ctx)}} else { ${failArrBody(ctx, deriveExpectedArr([p]), pos)} }`);
4579
+ return stmts;
4580
+ }
4562
4581
  function emitChoice(def, ctx, pos) {
4563
4582
  const allExpected = deriveExpectedArr(def.parsers);
4564
4583
  if (def.disjoint) {
@@ -4574,12 +4593,11 @@ function emitChoice(def, ctx, pos) {
4574
4593
  stmts.push(`${ind(ctx)}switch (${codeV}) {`);
4575
4594
  ctx.indent++;
4576
4595
  for (let i = 0; i < def.parsers.length; i++) {
4577
- const p = def.parsers[i];
4578
4596
  for (const cp of plan.cases[i]) stmts.push(`${ind(ctx)}case ${cp}:`);
4579
4597
  stmts.push(`${ind(ctx)}{`);
4580
4598
  ctx.indent++;
4581
4599
  stmts.push(
4582
- ...emitDisjointArm(p, ctx, pos, valV, endV),
4600
+ ...emitDisjointArmGated(def, i, ctx, pos, valV, endV),
4583
4601
  `${ind(ctx)}break`
4584
4602
  );
4585
4603
  ctx.indent--;
@@ -4591,13 +4609,14 @@ function emitChoice(def, ctx, pos) {
4591
4609
  return { stmts, valueVar: valV, endVar: endV };
4592
4610
  }
4593
4611
  let first = true;
4594
- for (const p of def.parsers) {
4612
+ for (let i = 0; i < def.parsers.length; i++) {
4613
+ const p = def.parsers[i];
4595
4614
  const cond = firstSetCond(codeV, p._meta.firstSet);
4596
4615
  const kw = first ? "if" : "else if";
4597
4616
  first = false;
4598
4617
  stmts.push(`${ind(ctx)}${kw} (${cond}) {`);
4599
4618
  ctx.indent++;
4600
- stmts.push(...emitDisjointArm(p, ctx, pos, valV, endV));
4619
+ stmts.push(...emitDisjointArmGated(def, i, ctx, pos, valV, endV));
4601
4620
  ctx.indent--;
4602
4621
  stmts.push(`${ind(ctx)}}`);
4603
4622
  }
@@ -6341,6 +6360,34 @@ function evalRuleMapIR(ir) {
6341
6360
  n._def.buildSrc = src;
6342
6361
  return n;
6343
6362
  };
6363
+ const _gch = (items) => {
6364
+ const gateSrcs = [];
6365
+ const arms = items.map((it) => {
6366
+ if (Array.isArray(it)) {
6367
+ const [src, comb] = it;
6368
+ gateSrcs.push(src);
6369
+ let gate;
6370
+ try {
6371
+ gate = (0, eval)(`(${src})`);
6372
+ } catch {
6373
+ gate = () => {
6374
+ throw new Error("IR gate fn not materialized");
6375
+ };
6376
+ }
6377
+ return { gate, combinator: comb };
6378
+ }
6379
+ gateSrcs.push(null);
6380
+ return it;
6381
+ });
6382
+ const c = choice(...arms);
6383
+ const gates = c._def.gates;
6384
+ if (gates && gates.length !== gateSrcs.length) {
6385
+ throw new Error(`_gch: gateSrcs length ${gateSrcs.length} != choice gates length ${gates.length}`);
6386
+ }
6387
+ ;
6388
+ c._def.gateSrcs = gateSrcs;
6389
+ return c;
6390
+ };
6344
6391
  const fn = new Function(
6345
6392
  "rules",
6346
6393
  "ref",
@@ -6366,6 +6413,7 @@ function evalRuleMapIR(ir) {
6366
6413
  "expect",
6367
6414
  "_tf",
6368
6415
  "_nd",
6416
+ "_gch",
6369
6417
  `return (${ir})`
6370
6418
  );
6371
6419
  const map = fn(
@@ -6392,7 +6440,8 @@ function evalRuleMapIR(ir) {
6392
6440
  field,
6393
6441
  expect,
6394
6442
  _tf,
6395
- _nd
6443
+ _nd,
6444
+ _gch
6396
6445
  );
6397
6446
  return Object.entries(map);
6398
6447
  }
@@ -6504,8 +6553,16 @@ ${body}
6504
6553
  case "sequence":
6505
6554
  return `sequence(${def.parsers.map(kid).join(", ")})`;
6506
6555
  case "choice": {
6507
- if (def.gates.some((g) => g !== null)) throw new Unserializable("choice with a gate() has no source");
6508
- return `choice(${def.parsers.map(kid).join(", ")})`;
6556
+ const gates = def.gates;
6557
+ if (gates.every((g) => g === null)) return `choice(${def.parsers.map(kid).join(", ")})`;
6558
+ const gateSrcs = def.gateSrcs;
6559
+ const items = def.parsers.map((p, i) => {
6560
+ if (gates[i] === null) return kid(p);
6561
+ const src = gateSrcs?.[i];
6562
+ if (src == null) throw new Unserializable("choice gate() has no captured source");
6563
+ return `[${JSON.stringify(src)}, ${kid(p)}]`;
6564
+ });
6565
+ return `_gch([${items.join(", ")}])`;
6509
6566
  }
6510
6567
  case "many":
6511
6568
  return `many(${kid(def.parser)})`;
@@ -6686,6 +6743,48 @@ var { isFinite } = Number;
6686
6743
  registerRegexAnalyzer(firstSetFromRegex);
6687
6744
 
6688
6745
  // src/plugin/evaluator.ts
6746
+ function stripTsFromSource(node2, code) {
6747
+ const cuts = [];
6748
+ const walk2 = (n) => {
6749
+ if (!n || typeof n !== "object") return;
6750
+ const rec = n;
6751
+ if (typeof rec.type === "string" && rec.type.startsWith("TS") && typeof rec.start === "number" && typeof rec.end === "number") {
6752
+ const ex = rec.expression;
6753
+ if ((rec.type === "TSAsExpression" || rec.type === "TSSatisfiesExpression" || rec.type === "TSNonNullExpression" || rec.type === "TSInstantiationExpression") && ex && typeof ex.end === "number") {
6754
+ cuts.push([ex.end, rec.end]);
6755
+ walk2(rec.expression);
6756
+ return;
6757
+ }
6758
+ if (rec.type === "TSTypeAssertion" && ex && typeof ex.start === "number") {
6759
+ cuts.push([rec.start, ex.start]);
6760
+ walk2(rec.expression);
6761
+ return;
6762
+ }
6763
+ cuts.push([rec.start, rec.end]);
6764
+ return;
6765
+ }
6766
+ for (const key of Object.keys(rec)) {
6767
+ if (key === "type" || key === "start" || key === "end") continue;
6768
+ const v2 = rec[key];
6769
+ if (Array.isArray(v2)) {
6770
+ for (const item of v2) walk2(item);
6771
+ } else if (v2 && typeof v2 === "object") walk2(v2);
6772
+ }
6773
+ };
6774
+ walk2(node2);
6775
+ const start = node2.start;
6776
+ const end = node2.end;
6777
+ if (cuts.length === 0) return code.slice(start, end);
6778
+ cuts.sort((a, b) => a[0] - b[0]);
6779
+ let out = "";
6780
+ let cur = start;
6781
+ for (const [s, e] of cuts) {
6782
+ if (s < cur) continue;
6783
+ out += code.slice(cur, s);
6784
+ cur = e;
6785
+ }
6786
+ return out + code.slice(cur, end);
6787
+ }
6689
6788
  function isWordFactory(v2) {
6690
6789
  return !!v2 && typeof v2 === "object" && v2.tag === "wordFactory";
6691
6790
  }
@@ -6961,7 +7060,7 @@ function exprToCombi(node2, scope, code, mfs) {
6961
7060
  if (isGatedArmExpr(argNode)) {
6962
7061
  const parts = gatedArmParts(argNode);
6963
7062
  if (!parts) return null;
6964
- const gateSrc = code.slice(parts.gate.start, parts.gate.end);
7063
+ const gateSrc = stripTsFromSource(parts.gate, code);
6965
7064
  mfs.push(gateSrc);
6966
7065
  const combi = anyValue(parts.combinator, scope, code, mfs);
6967
7066
  if (!isCombinator(combi)) return null;