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.
- package/dist/combinators/choice.d.ts.map +1 -1
- package/dist/compiler/codegen.d.ts.map +1 -1
- package/dist/compiler/ir-serialize.d.ts.map +1 -1
- package/dist/index.cjs +227 -170
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +227 -170
- package/dist/index.js.map +4 -4
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.cjs +266 -167
- package/dist/plugin/index.cjs.map +4 -4
- package/dist/plugin/index.js +266 -167
- package/dist/plugin/index.js.map +4 -4
- package/package.json +1 -1
package/dist/plugin/index.js
CHANGED
|
@@ -877,12 +877,159 @@ function keywords(words, opts = {}) {
|
|
|
877
877
|
};
|
|
878
878
|
}
|
|
879
879
|
|
|
880
|
+
// src/recovery/scan.ts
|
|
881
|
+
function probeAt(sentinel, input, pos, ctx) {
|
|
882
|
+
const s = {
|
|
883
|
+
_probe: ctx._probe,
|
|
884
|
+
_errors: ctx._errors,
|
|
885
|
+
_cstLeaves: ctx._cstLeaves,
|
|
886
|
+
_cstChildren: ctx._cstChildren,
|
|
887
|
+
_cstRawChildren: ctx._cstRawChildren,
|
|
888
|
+
_cstTriviaLog: ctx._cstTriviaLog,
|
|
889
|
+
_triviaLog: ctx._triviaLog,
|
|
890
|
+
_fields: ctx._fields,
|
|
891
|
+
_cstBuf: ctx._cstBuf,
|
|
892
|
+
_tolerant: ctx._tolerant,
|
|
893
|
+
_sync: ctx._sync
|
|
894
|
+
};
|
|
895
|
+
ctx._probe = void 0;
|
|
896
|
+
ctx._errors = void 0;
|
|
897
|
+
ctx._cstLeaves = void 0;
|
|
898
|
+
ctx._cstChildren = void 0;
|
|
899
|
+
ctx._cstRawChildren = void 0;
|
|
900
|
+
ctx._cstTriviaLog = void 0;
|
|
901
|
+
ctx._triviaLog = void 0;
|
|
902
|
+
ctx._fields = void 0;
|
|
903
|
+
ctx._cstBuf = void 0;
|
|
904
|
+
ctx._tolerant = void 0;
|
|
905
|
+
ctx._sync = void 0;
|
|
906
|
+
try {
|
|
907
|
+
return sentinel.parse(input, pos, ctx).ok;
|
|
908
|
+
} finally {
|
|
909
|
+
ctx._probe = s._probe;
|
|
910
|
+
ctx._errors = s._errors;
|
|
911
|
+
ctx._cstLeaves = s._cstLeaves;
|
|
912
|
+
ctx._cstChildren = s._cstChildren;
|
|
913
|
+
ctx._cstRawChildren = s._cstRawChildren;
|
|
914
|
+
ctx._cstTriviaLog = s._cstTriviaLog;
|
|
915
|
+
ctx._triviaLog = s._triviaLog;
|
|
916
|
+
ctx._fields = s._fields;
|
|
917
|
+
ctx._cstBuf = s._cstBuf;
|
|
918
|
+
ctx._tolerant = s._tolerant;
|
|
919
|
+
ctx._sync = s._sync;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
function orSentinel(a, b) {
|
|
923
|
+
if (b === void 0) return a;
|
|
924
|
+
return {
|
|
925
|
+
_tag: "orSentinel",
|
|
926
|
+
_meta: { firstSet: { kind: "any" }, canMatchNewline: false, isTrivia: false },
|
|
927
|
+
_def: { tag: "unknown" },
|
|
928
|
+
parse(input, pos, ctx) {
|
|
929
|
+
const ra = a.parse(input, pos, ctx);
|
|
930
|
+
if (ra.ok) return ra;
|
|
931
|
+
return b.parse(input, pos, ctx);
|
|
932
|
+
}
|
|
933
|
+
};
|
|
934
|
+
}
|
|
935
|
+
function firstSetSentinel(fs2) {
|
|
936
|
+
if (fs2.kind !== "ranges" || fs2.ranges.length === 0) return null;
|
|
937
|
+
const ranges = fs2.ranges;
|
|
938
|
+
return {
|
|
939
|
+
_tag: "firstSetSentinel",
|
|
940
|
+
_meta: { firstSet: fs2, canMatchNewline: false, isTrivia: false },
|
|
941
|
+
_def: { tag: "unknown" },
|
|
942
|
+
parse(input, pos) {
|
|
943
|
+
const code = pos < input.length ? input.codePointAt(pos) : void 0;
|
|
944
|
+
if (code !== void 0) {
|
|
945
|
+
for (const r of ranges) {
|
|
946
|
+
if (code >= r.lo && code <= r.hi) return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
return { ok: false, expected: [], span: { start: pos, end: pos } };
|
|
950
|
+
}
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
function recoverScan(input, from, ctx, sync, expected) {
|
|
954
|
+
let scanPos = from;
|
|
955
|
+
while (scanPos < input.length && !probeAt(sync, input, scanPos, ctx)) scanPos++;
|
|
956
|
+
const error = { _tag: "parseError", span: { start: from, end: scanPos }, expected };
|
|
957
|
+
ctx._errors?.push(error);
|
|
958
|
+
return { error, end: scanPos };
|
|
959
|
+
}
|
|
960
|
+
function matchesAt(sentinel, input, pos, ctx) {
|
|
961
|
+
return probeAt(sentinel, input, pos, ctx);
|
|
962
|
+
}
|
|
963
|
+
function captureError(ctx, error) {
|
|
964
|
+
if (cstCaptureActive(ctx)) pushCstChild(ctx, error, error);
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
// src/combinators/expect.ts
|
|
968
|
+
function deriveExpected(c) {
|
|
969
|
+
const def = c._def;
|
|
970
|
+
switch (def.tag) {
|
|
971
|
+
case "literal":
|
|
972
|
+
return [JSON.stringify(def.value)];
|
|
973
|
+
case "regex":
|
|
974
|
+
return [`/${def.source}/`];
|
|
975
|
+
case "keywords":
|
|
976
|
+
return def.words.map((w) => JSON.stringify(w));
|
|
977
|
+
case "label":
|
|
978
|
+
return [def.label];
|
|
979
|
+
case "choice":
|
|
980
|
+
return def.parsers.flatMap(deriveExpected);
|
|
981
|
+
case "sequence":
|
|
982
|
+
return def.parsers.length > 0 ? deriveExpected(def.parsers[0]) : [];
|
|
983
|
+
case "node":
|
|
984
|
+
case "grammar":
|
|
985
|
+
case "trivia":
|
|
986
|
+
case "token":
|
|
987
|
+
case "optional":
|
|
988
|
+
case "many":
|
|
989
|
+
case "oneOrMore":
|
|
990
|
+
case "transform":
|
|
991
|
+
case "not":
|
|
992
|
+
return deriveExpected(def.parser);
|
|
993
|
+
case "lazy": {
|
|
994
|
+
const name = c._ruleName;
|
|
995
|
+
try {
|
|
996
|
+
return deriveExpected(def.thunk());
|
|
997
|
+
} catch {
|
|
998
|
+
return name ? [name] : [];
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
default:
|
|
1002
|
+
return [];
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
function expect(combinator, label2) {
|
|
1006
|
+
const expected = label2 !== void 0 ? [label2] : deriveExpected(combinator);
|
|
1007
|
+
const meta = {
|
|
1008
|
+
firstSet: combinator._meta.firstSet,
|
|
1009
|
+
canMatchNewline: combinator._meta.canMatchNewline,
|
|
1010
|
+
isTrivia: false
|
|
1011
|
+
};
|
|
1012
|
+
return {
|
|
1013
|
+
_tag: "expect",
|
|
1014
|
+
_meta: meta,
|
|
1015
|
+
_def: { tag: "expect", parser: combinator, label: label2, expected },
|
|
1016
|
+
parse(input, pos, ctx) {
|
|
1017
|
+
const result = combinator.parse(input, pos, ctx);
|
|
1018
|
+
if (result.ok) return result;
|
|
1019
|
+
const error = { _tag: "parseError", span: { start: pos, end: pos }, expected };
|
|
1020
|
+
ctx._errors?.push(error);
|
|
1021
|
+
if (ctx._tolerant) captureError(ctx, error);
|
|
1022
|
+
return { ok: true, value: error, span: { start: pos, end: pos } };
|
|
1023
|
+
}
|
|
1024
|
+
};
|
|
1025
|
+
}
|
|
1026
|
+
|
|
880
1027
|
// src/combinators/choice.ts
|
|
881
1028
|
function choice(...args) {
|
|
882
1029
|
const parsers = args.map((a) => "gate" in a ? a.combinator : a);
|
|
883
1030
|
const gates = args.map((a) => "gate" in a ? a.gate : null);
|
|
884
1031
|
const hasGates = gates.some((g) => g !== null);
|
|
885
|
-
const disjoint =
|
|
1032
|
+
const disjoint = areDisjoint(parsers.map((p) => p._meta.firstSet)) && parsers.every((p) => !matchesEmpty(p));
|
|
886
1033
|
let combined = { kind: "empty" };
|
|
887
1034
|
for (const p of parsers) combined = union(combined, p._meta.firstSet);
|
|
888
1035
|
const meta = {
|
|
@@ -921,17 +1068,21 @@ function choice(...args) {
|
|
|
921
1068
|
const expected = [];
|
|
922
1069
|
if (disjoint && pos < input.length) {
|
|
923
1070
|
const code = input.codePointAt(pos);
|
|
924
|
-
let
|
|
925
|
-
if (
|
|
926
|
-
for (
|
|
927
|
-
if (inFirstSet(code,
|
|
928
|
-
|
|
1071
|
+
let idx = code < 128 ? asciiDispatch[code] : -1;
|
|
1072
|
+
if (idx < 0) {
|
|
1073
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
1074
|
+
if (inFirstSet(code, parsers[i]._meta.firstSet)) {
|
|
1075
|
+
idx = i;
|
|
929
1076
|
break;
|
|
930
1077
|
}
|
|
931
1078
|
}
|
|
932
1079
|
}
|
|
933
|
-
if (
|
|
934
|
-
const
|
|
1080
|
+
if (idx >= 0) {
|
|
1081
|
+
const gate = gates[idx];
|
|
1082
|
+
if (gate && !gate(ctx.state)) {
|
|
1083
|
+
return { ok: false, expected: deriveExpected(parsers[idx]), span: { start: pos, end: pos } };
|
|
1084
|
+
}
|
|
1085
|
+
const result = parsers[idx].parse(input, pos, ctx);
|
|
935
1086
|
if (result.ok) return result;
|
|
936
1087
|
expected.push(...result.expected);
|
|
937
1088
|
return { ok: false, expected, span: { start: pos, end: pos } };
|
|
@@ -1112,13 +1263,13 @@ function areDisjoint(sets) {
|
|
|
1112
1263
|
return true;
|
|
1113
1264
|
}
|
|
1114
1265
|
function buildAsciiDispatch(parsers) {
|
|
1115
|
-
const table = Array(128).fill(
|
|
1116
|
-
for (
|
|
1117
|
-
const fs2 =
|
|
1266
|
+
const table = Array(128).fill(-1);
|
|
1267
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
1268
|
+
const fs2 = parsers[i]._meta.firstSet;
|
|
1118
1269
|
if (fs2.kind !== "ranges") continue;
|
|
1119
1270
|
for (const { lo, hi } of fs2.ranges) {
|
|
1120
1271
|
for (let code = Math.max(0, lo); code <= Math.min(127, hi); code++) {
|
|
1121
|
-
table[code] =
|
|
1272
|
+
table[code] = i;
|
|
1122
1273
|
}
|
|
1123
1274
|
}
|
|
1124
1275
|
}
|
|
@@ -1500,93 +1651,6 @@ function scanBlockComment(input, cur) {
|
|
|
1500
1651
|
return close === -1 ? cur : close + 2;
|
|
1501
1652
|
}
|
|
1502
1653
|
|
|
1503
|
-
// src/recovery/scan.ts
|
|
1504
|
-
function probeAt(sentinel, input, pos, ctx) {
|
|
1505
|
-
const s = {
|
|
1506
|
-
_probe: ctx._probe,
|
|
1507
|
-
_errors: ctx._errors,
|
|
1508
|
-
_cstLeaves: ctx._cstLeaves,
|
|
1509
|
-
_cstChildren: ctx._cstChildren,
|
|
1510
|
-
_cstRawChildren: ctx._cstRawChildren,
|
|
1511
|
-
_cstTriviaLog: ctx._cstTriviaLog,
|
|
1512
|
-
_triviaLog: ctx._triviaLog,
|
|
1513
|
-
_fields: ctx._fields,
|
|
1514
|
-
_cstBuf: ctx._cstBuf,
|
|
1515
|
-
_tolerant: ctx._tolerant,
|
|
1516
|
-
_sync: ctx._sync
|
|
1517
|
-
};
|
|
1518
|
-
ctx._probe = void 0;
|
|
1519
|
-
ctx._errors = void 0;
|
|
1520
|
-
ctx._cstLeaves = void 0;
|
|
1521
|
-
ctx._cstChildren = void 0;
|
|
1522
|
-
ctx._cstRawChildren = void 0;
|
|
1523
|
-
ctx._cstTriviaLog = void 0;
|
|
1524
|
-
ctx._triviaLog = void 0;
|
|
1525
|
-
ctx._fields = void 0;
|
|
1526
|
-
ctx._cstBuf = void 0;
|
|
1527
|
-
ctx._tolerant = void 0;
|
|
1528
|
-
ctx._sync = void 0;
|
|
1529
|
-
try {
|
|
1530
|
-
return sentinel.parse(input, pos, ctx).ok;
|
|
1531
|
-
} finally {
|
|
1532
|
-
ctx._probe = s._probe;
|
|
1533
|
-
ctx._errors = s._errors;
|
|
1534
|
-
ctx._cstLeaves = s._cstLeaves;
|
|
1535
|
-
ctx._cstChildren = s._cstChildren;
|
|
1536
|
-
ctx._cstRawChildren = s._cstRawChildren;
|
|
1537
|
-
ctx._cstTriviaLog = s._cstTriviaLog;
|
|
1538
|
-
ctx._triviaLog = s._triviaLog;
|
|
1539
|
-
ctx._fields = s._fields;
|
|
1540
|
-
ctx._cstBuf = s._cstBuf;
|
|
1541
|
-
ctx._tolerant = s._tolerant;
|
|
1542
|
-
ctx._sync = s._sync;
|
|
1543
|
-
}
|
|
1544
|
-
}
|
|
1545
|
-
function orSentinel(a, b) {
|
|
1546
|
-
if (b === void 0) return a;
|
|
1547
|
-
return {
|
|
1548
|
-
_tag: "orSentinel",
|
|
1549
|
-
_meta: { firstSet: { kind: "any" }, canMatchNewline: false, isTrivia: false },
|
|
1550
|
-
_def: { tag: "unknown" },
|
|
1551
|
-
parse(input, pos, ctx) {
|
|
1552
|
-
const ra = a.parse(input, pos, ctx);
|
|
1553
|
-
if (ra.ok) return ra;
|
|
1554
|
-
return b.parse(input, pos, ctx);
|
|
1555
|
-
}
|
|
1556
|
-
};
|
|
1557
|
-
}
|
|
1558
|
-
function firstSetSentinel(fs2) {
|
|
1559
|
-
if (fs2.kind !== "ranges" || fs2.ranges.length === 0) return null;
|
|
1560
|
-
const ranges = fs2.ranges;
|
|
1561
|
-
return {
|
|
1562
|
-
_tag: "firstSetSentinel",
|
|
1563
|
-
_meta: { firstSet: fs2, canMatchNewline: false, isTrivia: false },
|
|
1564
|
-
_def: { tag: "unknown" },
|
|
1565
|
-
parse(input, pos) {
|
|
1566
|
-
const code = pos < input.length ? input.codePointAt(pos) : void 0;
|
|
1567
|
-
if (code !== void 0) {
|
|
1568
|
-
for (const r of ranges) {
|
|
1569
|
-
if (code >= r.lo && code <= r.hi) return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
1570
|
-
}
|
|
1571
|
-
}
|
|
1572
|
-
return { ok: false, expected: [], span: { start: pos, end: pos } };
|
|
1573
|
-
}
|
|
1574
|
-
};
|
|
1575
|
-
}
|
|
1576
|
-
function recoverScan(input, from, ctx, sync, expected) {
|
|
1577
|
-
let scanPos = from;
|
|
1578
|
-
while (scanPos < input.length && !probeAt(sync, input, scanPos, ctx)) scanPos++;
|
|
1579
|
-
const error = { _tag: "parseError", span: { start: from, end: scanPos }, expected };
|
|
1580
|
-
ctx._errors?.push(error);
|
|
1581
|
-
return { error, end: scanPos };
|
|
1582
|
-
}
|
|
1583
|
-
function matchesAt(sentinel, input, pos, ctx) {
|
|
1584
|
-
return probeAt(sentinel, input, pos, ctx);
|
|
1585
|
-
}
|
|
1586
|
-
function captureError(ctx, error) {
|
|
1587
|
-
if (cstCaptureActive(ctx)) pushCstChild(ctx, error, error);
|
|
1588
|
-
}
|
|
1589
|
-
|
|
1590
1654
|
// src/combinators/sequence.ts
|
|
1591
1655
|
function sequence(...parsers) {
|
|
1592
1656
|
const meta = {
|
|
@@ -1688,66 +1752,6 @@ function sequence(...parsers) {
|
|
|
1688
1752
|
};
|
|
1689
1753
|
}
|
|
1690
1754
|
|
|
1691
|
-
// src/combinators/expect.ts
|
|
1692
|
-
function deriveExpected(c) {
|
|
1693
|
-
const def = c._def;
|
|
1694
|
-
switch (def.tag) {
|
|
1695
|
-
case "literal":
|
|
1696
|
-
return [JSON.stringify(def.value)];
|
|
1697
|
-
case "regex":
|
|
1698
|
-
return [`/${def.source}/`];
|
|
1699
|
-
case "keywords":
|
|
1700
|
-
return def.words.map((w) => JSON.stringify(w));
|
|
1701
|
-
case "label":
|
|
1702
|
-
return [def.label];
|
|
1703
|
-
case "choice":
|
|
1704
|
-
return def.parsers.flatMap(deriveExpected);
|
|
1705
|
-
case "sequence":
|
|
1706
|
-
return def.parsers.length > 0 ? deriveExpected(def.parsers[0]) : [];
|
|
1707
|
-
case "node":
|
|
1708
|
-
case "grammar":
|
|
1709
|
-
case "trivia":
|
|
1710
|
-
case "token":
|
|
1711
|
-
case "optional":
|
|
1712
|
-
case "many":
|
|
1713
|
-
case "oneOrMore":
|
|
1714
|
-
case "transform":
|
|
1715
|
-
case "not":
|
|
1716
|
-
return deriveExpected(def.parser);
|
|
1717
|
-
case "lazy": {
|
|
1718
|
-
const name = c._ruleName;
|
|
1719
|
-
try {
|
|
1720
|
-
return deriveExpected(def.thunk());
|
|
1721
|
-
} catch {
|
|
1722
|
-
return name ? [name] : [];
|
|
1723
|
-
}
|
|
1724
|
-
}
|
|
1725
|
-
default:
|
|
1726
|
-
return [];
|
|
1727
|
-
}
|
|
1728
|
-
}
|
|
1729
|
-
function expect(combinator, label2) {
|
|
1730
|
-
const expected = label2 !== void 0 ? [label2] : deriveExpected(combinator);
|
|
1731
|
-
const meta = {
|
|
1732
|
-
firstSet: combinator._meta.firstSet,
|
|
1733
|
-
canMatchNewline: combinator._meta.canMatchNewline,
|
|
1734
|
-
isTrivia: false
|
|
1735
|
-
};
|
|
1736
|
-
return {
|
|
1737
|
-
_tag: "expect",
|
|
1738
|
-
_meta: meta,
|
|
1739
|
-
_def: { tag: "expect", parser: combinator, label: label2, expected },
|
|
1740
|
-
parse(input, pos, ctx) {
|
|
1741
|
-
const result = combinator.parse(input, pos, ctx);
|
|
1742
|
-
if (result.ok) return result;
|
|
1743
|
-
const error = { _tag: "parseError", span: { start: pos, end: pos }, expected };
|
|
1744
|
-
ctx._errors?.push(error);
|
|
1745
|
-
if (ctx._tolerant) captureError(ctx, error);
|
|
1746
|
-
return { ok: true, value: error, span: { start: pos, end: pos } };
|
|
1747
|
-
}
|
|
1748
|
-
};
|
|
1749
|
-
}
|
|
1750
|
-
|
|
1751
1755
|
// src/combinators/repeat.ts
|
|
1752
1756
|
function repItem(combinator, input, cur, ctx) {
|
|
1753
1757
|
const mark = saveTriviaMark(ctx);
|
|
@@ -4524,6 +4528,21 @@ function emitDisjointArm(p, ctx, pos, valV, endV) {
|
|
|
4524
4528
|
`${ind(ctx)}${endV} = ${endVar}`
|
|
4525
4529
|
];
|
|
4526
4530
|
}
|
|
4531
|
+
function emitDisjointArmGated(def, i, ctx, pos, valV, endV) {
|
|
4532
|
+
const p = def.parsers[i];
|
|
4533
|
+
const gate = def.gates[i];
|
|
4534
|
+
if (!gate) return emitDisjointArm(p, ctx, pos, valV, endV);
|
|
4535
|
+
const gateIdx = ctx.mapFns.length;
|
|
4536
|
+
ctx.mapFns.push(gate);
|
|
4537
|
+
ctx.mapFnSrcs.push(def.gateSrcs?.[i] ?? null);
|
|
4538
|
+
const gateCond = `${mfRef(ctx)}[${gateIdx}](_ctx.state)`;
|
|
4539
|
+
const stmts = [`${ind(ctx)}if (${gateCond}) {`];
|
|
4540
|
+
ctx.indent++;
|
|
4541
|
+
stmts.push(...emitDisjointArm(p, ctx, pos, valV, endV));
|
|
4542
|
+
ctx.indent--;
|
|
4543
|
+
stmts.push(`${ind(ctx)}} else { ${failArrBody(ctx, deriveExpectedArr([p]), pos)} }`);
|
|
4544
|
+
return stmts;
|
|
4545
|
+
}
|
|
4527
4546
|
function emitChoice(def, ctx, pos) {
|
|
4528
4547
|
const allExpected = deriveExpectedArr(def.parsers);
|
|
4529
4548
|
if (def.disjoint) {
|
|
@@ -4539,12 +4558,11 @@ function emitChoice(def, ctx, pos) {
|
|
|
4539
4558
|
stmts.push(`${ind(ctx)}switch (${codeV}) {`);
|
|
4540
4559
|
ctx.indent++;
|
|
4541
4560
|
for (let i = 0; i < def.parsers.length; i++) {
|
|
4542
|
-
const p = def.parsers[i];
|
|
4543
4561
|
for (const cp of plan.cases[i]) stmts.push(`${ind(ctx)}case ${cp}:`);
|
|
4544
4562
|
stmts.push(`${ind(ctx)}{`);
|
|
4545
4563
|
ctx.indent++;
|
|
4546
4564
|
stmts.push(
|
|
4547
|
-
...
|
|
4565
|
+
...emitDisjointArmGated(def, i, ctx, pos, valV, endV),
|
|
4548
4566
|
`${ind(ctx)}break`
|
|
4549
4567
|
);
|
|
4550
4568
|
ctx.indent--;
|
|
@@ -4556,13 +4574,14 @@ function emitChoice(def, ctx, pos) {
|
|
|
4556
4574
|
return { stmts, valueVar: valV, endVar: endV };
|
|
4557
4575
|
}
|
|
4558
4576
|
let first = true;
|
|
4559
|
-
for (
|
|
4577
|
+
for (let i = 0; i < def.parsers.length; i++) {
|
|
4578
|
+
const p = def.parsers[i];
|
|
4560
4579
|
const cond = firstSetCond(codeV, p._meta.firstSet);
|
|
4561
4580
|
const kw = first ? "if" : "else if";
|
|
4562
4581
|
first = false;
|
|
4563
4582
|
stmts.push(`${ind(ctx)}${kw} (${cond}) {`);
|
|
4564
4583
|
ctx.indent++;
|
|
4565
|
-
stmts.push(...
|
|
4584
|
+
stmts.push(...emitDisjointArmGated(def, i, ctx, pos, valV, endV));
|
|
4566
4585
|
ctx.indent--;
|
|
4567
4586
|
stmts.push(`${ind(ctx)}}`);
|
|
4568
4587
|
}
|
|
@@ -6306,6 +6325,34 @@ function evalRuleMapIR(ir) {
|
|
|
6306
6325
|
n._def.buildSrc = src;
|
|
6307
6326
|
return n;
|
|
6308
6327
|
};
|
|
6328
|
+
const _gch = (items) => {
|
|
6329
|
+
const gateSrcs = [];
|
|
6330
|
+
const arms = items.map((it) => {
|
|
6331
|
+
if (Array.isArray(it)) {
|
|
6332
|
+
const [src, comb] = it;
|
|
6333
|
+
gateSrcs.push(src);
|
|
6334
|
+
let gate;
|
|
6335
|
+
try {
|
|
6336
|
+
gate = (0, eval)(`(${src})`);
|
|
6337
|
+
} catch {
|
|
6338
|
+
gate = () => {
|
|
6339
|
+
throw new Error("IR gate fn not materialized");
|
|
6340
|
+
};
|
|
6341
|
+
}
|
|
6342
|
+
return { gate, combinator: comb };
|
|
6343
|
+
}
|
|
6344
|
+
gateSrcs.push(null);
|
|
6345
|
+
return it;
|
|
6346
|
+
});
|
|
6347
|
+
const c = choice(...arms);
|
|
6348
|
+
const gates = c._def.gates;
|
|
6349
|
+
if (gates && gates.length !== gateSrcs.length) {
|
|
6350
|
+
throw new Error(`_gch: gateSrcs length ${gateSrcs.length} != choice gates length ${gates.length}`);
|
|
6351
|
+
}
|
|
6352
|
+
;
|
|
6353
|
+
c._def.gateSrcs = gateSrcs;
|
|
6354
|
+
return c;
|
|
6355
|
+
};
|
|
6309
6356
|
const fn = new Function(
|
|
6310
6357
|
"rules",
|
|
6311
6358
|
"ref",
|
|
@@ -6331,6 +6378,7 @@ function evalRuleMapIR(ir) {
|
|
|
6331
6378
|
"expect",
|
|
6332
6379
|
"_tf",
|
|
6333
6380
|
"_nd",
|
|
6381
|
+
"_gch",
|
|
6334
6382
|
`return (${ir})`
|
|
6335
6383
|
);
|
|
6336
6384
|
const map = fn(
|
|
@@ -6357,7 +6405,8 @@ function evalRuleMapIR(ir) {
|
|
|
6357
6405
|
field,
|
|
6358
6406
|
expect,
|
|
6359
6407
|
_tf,
|
|
6360
|
-
_nd
|
|
6408
|
+
_nd,
|
|
6409
|
+
_gch
|
|
6361
6410
|
);
|
|
6362
6411
|
return Object.entries(map);
|
|
6363
6412
|
}
|
|
@@ -6469,8 +6518,16 @@ ${body}
|
|
|
6469
6518
|
case "sequence":
|
|
6470
6519
|
return `sequence(${def.parsers.map(kid).join(", ")})`;
|
|
6471
6520
|
case "choice": {
|
|
6472
|
-
|
|
6473
|
-
return `choice(${def.parsers.map(kid).join(", ")})`;
|
|
6521
|
+
const gates = def.gates;
|
|
6522
|
+
if (gates.every((g) => g === null)) return `choice(${def.parsers.map(kid).join(", ")})`;
|
|
6523
|
+
const gateSrcs = def.gateSrcs;
|
|
6524
|
+
const items = def.parsers.map((p, i) => {
|
|
6525
|
+
if (gates[i] === null) return kid(p);
|
|
6526
|
+
const src = gateSrcs?.[i];
|
|
6527
|
+
if (src == null) throw new Unserializable("choice gate() has no captured source");
|
|
6528
|
+
return `[${JSON.stringify(src)}, ${kid(p)}]`;
|
|
6529
|
+
});
|
|
6530
|
+
return `_gch([${items.join(", ")}])`;
|
|
6474
6531
|
}
|
|
6475
6532
|
case "many":
|
|
6476
6533
|
return `many(${kid(def.parser)})`;
|
|
@@ -6651,6 +6708,48 @@ var { isFinite } = Number;
|
|
|
6651
6708
|
registerRegexAnalyzer(firstSetFromRegex);
|
|
6652
6709
|
|
|
6653
6710
|
// src/plugin/evaluator.ts
|
|
6711
|
+
function stripTsFromSource(node2, code) {
|
|
6712
|
+
const cuts = [];
|
|
6713
|
+
const walk2 = (n) => {
|
|
6714
|
+
if (!n || typeof n !== "object") return;
|
|
6715
|
+
const rec = n;
|
|
6716
|
+
if (typeof rec.type === "string" && rec.type.startsWith("TS") && typeof rec.start === "number" && typeof rec.end === "number") {
|
|
6717
|
+
const ex = rec.expression;
|
|
6718
|
+
if ((rec.type === "TSAsExpression" || rec.type === "TSSatisfiesExpression" || rec.type === "TSNonNullExpression" || rec.type === "TSInstantiationExpression") && ex && typeof ex.end === "number") {
|
|
6719
|
+
cuts.push([ex.end, rec.end]);
|
|
6720
|
+
walk2(rec.expression);
|
|
6721
|
+
return;
|
|
6722
|
+
}
|
|
6723
|
+
if (rec.type === "TSTypeAssertion" && ex && typeof ex.start === "number") {
|
|
6724
|
+
cuts.push([rec.start, ex.start]);
|
|
6725
|
+
walk2(rec.expression);
|
|
6726
|
+
return;
|
|
6727
|
+
}
|
|
6728
|
+
cuts.push([rec.start, rec.end]);
|
|
6729
|
+
return;
|
|
6730
|
+
}
|
|
6731
|
+
for (const key of Object.keys(rec)) {
|
|
6732
|
+
if (key === "type" || key === "start" || key === "end") continue;
|
|
6733
|
+
const v2 = rec[key];
|
|
6734
|
+
if (Array.isArray(v2)) {
|
|
6735
|
+
for (const item of v2) walk2(item);
|
|
6736
|
+
} else if (v2 && typeof v2 === "object") walk2(v2);
|
|
6737
|
+
}
|
|
6738
|
+
};
|
|
6739
|
+
walk2(node2);
|
|
6740
|
+
const start = node2.start;
|
|
6741
|
+
const end = node2.end;
|
|
6742
|
+
if (cuts.length === 0) return code.slice(start, end);
|
|
6743
|
+
cuts.sort((a, b) => a[0] - b[0]);
|
|
6744
|
+
let out = "";
|
|
6745
|
+
let cur = start;
|
|
6746
|
+
for (const [s, e] of cuts) {
|
|
6747
|
+
if (s < cur) continue;
|
|
6748
|
+
out += code.slice(cur, s);
|
|
6749
|
+
cur = e;
|
|
6750
|
+
}
|
|
6751
|
+
return out + code.slice(cur, end);
|
|
6752
|
+
}
|
|
6654
6753
|
function isWordFactory(v2) {
|
|
6655
6754
|
return !!v2 && typeof v2 === "object" && v2.tag === "wordFactory";
|
|
6656
6755
|
}
|
|
@@ -6926,7 +7025,7 @@ function exprToCombi(node2, scope, code, mfs) {
|
|
|
6926
7025
|
if (isGatedArmExpr(argNode)) {
|
|
6927
7026
|
const parts = gatedArmParts(argNode);
|
|
6928
7027
|
if (!parts) return null;
|
|
6929
|
-
const gateSrc =
|
|
7028
|
+
const gateSrc = stripTsFromSource(parts.gate, code);
|
|
6930
7029
|
mfs.push(gateSrc);
|
|
6931
7030
|
const combi = anyValue(parts.combinator, scope, code, mfs);
|
|
6932
7031
|
if (!isCombinator(combi)) return null;
|