parseman 0.12.0 → 0.13.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/compiler/codegen.d.ts.map +1 -1
- package/dist/compiler/scannable-run.d.ts +80 -2
- package/dist/compiler/scannable-run.d.ts.map +1 -1
- package/dist/cst/types.d.ts +1 -1
- package/dist/functional/doc.d.ts +6 -6
- package/dist/functional/doc.d.ts.map +1 -1
- package/dist/index.cjs +727 -52
- package/dist/index.cjs.map +3 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +727 -52
- package/dist/index.js.map +3 -3
- package/dist/plugin/evaluator.d.ts +28 -2
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.cjs +974 -101
- package/dist/plugin/index.cjs.map +3 -3
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +974 -101
- package/dist/plugin/index.js.map +3 -3
- package/package.json +5 -4
- package/dist/combinators/lazy.d.ts +0 -14
- package/dist/combinators/lazy.d.ts.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -44,7 +44,6 @@ __export(index_exports, {
|
|
|
44
44
|
keywords: () => keywords,
|
|
45
45
|
label: () => label,
|
|
46
46
|
literal: () => literal,
|
|
47
|
-
makeFunctionalDoc: () => makeFunctionalDoc,
|
|
48
47
|
makeWord: () => makeWord,
|
|
49
48
|
many: () => many,
|
|
50
49
|
manyRecover: () => manyRecover,
|
|
@@ -55,6 +54,7 @@ __export(index_exports, {
|
|
|
55
54
|
oneOrMore: () => oneOrMore,
|
|
56
55
|
optional: () => optional,
|
|
57
56
|
parse: () => parse,
|
|
57
|
+
parseDoc: () => parseDoc,
|
|
58
58
|
parser: () => parser,
|
|
59
59
|
recover: () => recover,
|
|
60
60
|
ref: () => ref,
|
|
@@ -1476,8 +1476,29 @@ function expect(combinator, label2) {
|
|
|
1476
1476
|
var BACKSLASH = 92;
|
|
1477
1477
|
var CLASS_ESCAPES = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
1478
1478
|
var META = new Set("()[]{}*+?|^$.".split(""));
|
|
1479
|
+
var SPACE_RANGES = [
|
|
1480
|
+
[9, 13],
|
|
1481
|
+
[32, 32],
|
|
1482
|
+
[160, 160],
|
|
1483
|
+
[5760, 5760],
|
|
1484
|
+
[8192, 8202],
|
|
1485
|
+
[8232, 8232],
|
|
1486
|
+
[8233, 8233],
|
|
1487
|
+
[8239, 8239],
|
|
1488
|
+
[8287, 8287],
|
|
1489
|
+
[12288, 12288],
|
|
1490
|
+
[65279, 65279]
|
|
1491
|
+
];
|
|
1479
1492
|
function shorthandRanges(ch) {
|
|
1480
|
-
|
|
1493
|
+
if (ch === "d") return [[48, 57]];
|
|
1494
|
+
if (ch === "s") return SPACE_RANGES;
|
|
1495
|
+
return [[48, 57], [65, 90], [97, 122], [95, 95]];
|
|
1496
|
+
}
|
|
1497
|
+
function readUnicodeEscape(body, i) {
|
|
1498
|
+
if (body[i] !== "\\" || body[i + 1] !== "u") return null;
|
|
1499
|
+
const hex = body.slice(i + 2, i + 6);
|
|
1500
|
+
if (!/^[0-9a-fA-F]{4}$/.test(hex)) return null;
|
|
1501
|
+
return { cp: Number.parseInt(hex, 16), next: i + 6 };
|
|
1481
1502
|
}
|
|
1482
1503
|
function parseClassRanges(body) {
|
|
1483
1504
|
const ranges = [];
|
|
@@ -1486,11 +1507,16 @@ function parseClassRanges(body) {
|
|
|
1486
1507
|
const ch = body[i];
|
|
1487
1508
|
if (ch === void 0) return null;
|
|
1488
1509
|
if (ch === "\\") {
|
|
1510
|
+
const uni = readUnicodeEscape(body, i);
|
|
1511
|
+
if (uni) {
|
|
1512
|
+
i = uni.next;
|
|
1513
|
+
return { cp: uni.cp };
|
|
1514
|
+
}
|
|
1489
1515
|
const e = body[i + 1];
|
|
1490
1516
|
if (e === void 0) return null;
|
|
1491
1517
|
i += 2;
|
|
1492
1518
|
if (e in CLASS_ESCAPES) return { cp: CLASS_ESCAPES[e] };
|
|
1493
|
-
if (e === "d" || e === "w") return { set: shorthandRanges(e) };
|
|
1519
|
+
if (e === "d" || e === "w" || e === "s") return { set: shorthandRanges(e) };
|
|
1494
1520
|
if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
1495
1521
|
return { cp: e.codePointAt(0) };
|
|
1496
1522
|
}
|
|
@@ -1518,10 +1544,16 @@ function parseClassRanges(body) {
|
|
|
1518
1544
|
function classToRanges(cls) {
|
|
1519
1545
|
if (cls === "\\d") return shorthandRanges("d");
|
|
1520
1546
|
if (cls === "\\w") return shorthandRanges("w");
|
|
1547
|
+
if (cls === "\\s") return shorthandRanges("s");
|
|
1521
1548
|
const body = cls.slice(1, -1);
|
|
1522
1549
|
if (body.startsWith("^")) return null;
|
|
1523
1550
|
return parseClassRanges(body);
|
|
1524
1551
|
}
|
|
1552
|
+
var foldEq = (cVar, cp) => {
|
|
1553
|
+
if (cp >= 65 && cp <= 90) return `(${cVar} === ${cp} || ${cVar} === ${cp + 32})`;
|
|
1554
|
+
if (cp >= 97 && cp <= 122) return `(${cVar} === ${cp} || ${cVar} === ${cp - 32})`;
|
|
1555
|
+
return `${cVar} === ${cp}`;
|
|
1556
|
+
};
|
|
1525
1557
|
function literalCodePoints(frag) {
|
|
1526
1558
|
const out = [];
|
|
1527
1559
|
let i = 0;
|
|
@@ -1568,22 +1600,446 @@ function parseStringShape(source) {
|
|
|
1568
1600
|
if (!inSet(qcp) || !inSet(BACKSLASH)) return null;
|
|
1569
1601
|
return { kind: "string", quote: qcp, excluded, escLineTerm: esc !== "." };
|
|
1570
1602
|
}
|
|
1603
|
+
function parseSeqParts(source) {
|
|
1604
|
+
const parts = [];
|
|
1605
|
+
let lit = [];
|
|
1606
|
+
const flush = () => {
|
|
1607
|
+
if (lit.length) {
|
|
1608
|
+
parts.push({ part: "lit", cps: lit, optional: false });
|
|
1609
|
+
lit = [];
|
|
1610
|
+
}
|
|
1611
|
+
};
|
|
1612
|
+
const runFrom = (ranges, negated, q) => {
|
|
1613
|
+
if (q === "+") {
|
|
1614
|
+
parts.push({ part: "run", ranges, negated, min: 1, unbounded: true });
|
|
1615
|
+
return 1;
|
|
1616
|
+
}
|
|
1617
|
+
if (q === "*") {
|
|
1618
|
+
parts.push({ part: "run", ranges, negated, min: 0, unbounded: true });
|
|
1619
|
+
return 1;
|
|
1620
|
+
}
|
|
1621
|
+
if (q === "?") {
|
|
1622
|
+
parts.push({ part: "run", ranges, negated, min: 0, unbounded: false });
|
|
1623
|
+
return 1;
|
|
1624
|
+
}
|
|
1625
|
+
parts.push({ part: "run", ranges, negated, min: 1, unbounded: false });
|
|
1626
|
+
return 0;
|
|
1627
|
+
};
|
|
1628
|
+
let i = 0;
|
|
1629
|
+
while (i < source.length) {
|
|
1630
|
+
const ch = source[i];
|
|
1631
|
+
if (ch === "[") {
|
|
1632
|
+
let k = i + 1;
|
|
1633
|
+
const neg = source[k] === "^";
|
|
1634
|
+
if (neg) k++;
|
|
1635
|
+
let body = "";
|
|
1636
|
+
while (k < source.length && source[k] !== "]") {
|
|
1637
|
+
if (source[k] === "\\") {
|
|
1638
|
+
body += source[k] + (source[k + 1] ?? "");
|
|
1639
|
+
k += 2;
|
|
1640
|
+
} else {
|
|
1641
|
+
body += source[k];
|
|
1642
|
+
k++;
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
if (source[k] !== "]") return null;
|
|
1646
|
+
const ranges = parseClassRanges(body);
|
|
1647
|
+
if (!ranges) return null;
|
|
1648
|
+
flush();
|
|
1649
|
+
i = k + 1;
|
|
1650
|
+
i += runFrom(ranges, neg, source[i]);
|
|
1651
|
+
continue;
|
|
1652
|
+
}
|
|
1653
|
+
if (ch === "\\") {
|
|
1654
|
+
const e = source[i + 1];
|
|
1655
|
+
if (e === "d" || e === "w" || e === "s") {
|
|
1656
|
+
flush();
|
|
1657
|
+
i += 2;
|
|
1658
|
+
i += runFrom(shorthandRanges(e), false, source[i]);
|
|
1659
|
+
continue;
|
|
1660
|
+
}
|
|
1661
|
+
const uni = readUnicodeEscape(source, i);
|
|
1662
|
+
let cp2;
|
|
1663
|
+
if (uni) {
|
|
1664
|
+
cp2 = uni.cp;
|
|
1665
|
+
i = uni.next;
|
|
1666
|
+
} else if (e === void 0) return null;
|
|
1667
|
+
else if (e in CLASS_ESCAPES) {
|
|
1668
|
+
cp2 = CLASS_ESCAPES[e];
|
|
1669
|
+
i += 2;
|
|
1670
|
+
} else if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
1671
|
+
else {
|
|
1672
|
+
cp2 = e.codePointAt(0);
|
|
1673
|
+
i += 2;
|
|
1674
|
+
}
|
|
1675
|
+
if (source[i] === "?") {
|
|
1676
|
+
flush();
|
|
1677
|
+
parts.push({ part: "lit", cps: [cp2], optional: true });
|
|
1678
|
+
i++;
|
|
1679
|
+
} else lit.push(cp2);
|
|
1680
|
+
continue;
|
|
1681
|
+
}
|
|
1682
|
+
if (ch === "(") {
|
|
1683
|
+
if (source[i + 1] !== "?" || source[i + 2] !== ":") return null;
|
|
1684
|
+
let k = i + 3;
|
|
1685
|
+
let depth = 1;
|
|
1686
|
+
while (k < source.length && depth > 0) {
|
|
1687
|
+
const c2 = source[k];
|
|
1688
|
+
if (c2 === "\\") {
|
|
1689
|
+
k += 2;
|
|
1690
|
+
continue;
|
|
1691
|
+
}
|
|
1692
|
+
if (c2 === "[") {
|
|
1693
|
+
let j = k + 1;
|
|
1694
|
+
if (source[j] === "^") j++;
|
|
1695
|
+
while (j < source.length && source[j] !== "]") {
|
|
1696
|
+
if (source[j] === "\\") j += 2;
|
|
1697
|
+
else j++;
|
|
1698
|
+
}
|
|
1699
|
+
if (source[j] !== "]") return null;
|
|
1700
|
+
k = j + 1;
|
|
1701
|
+
continue;
|
|
1702
|
+
}
|
|
1703
|
+
if (c2 === "(") depth++;
|
|
1704
|
+
else if (c2 === ")") depth--;
|
|
1705
|
+
k++;
|
|
1706
|
+
}
|
|
1707
|
+
if (depth !== 0) return null;
|
|
1708
|
+
const body = source.slice(i + 3, k - 1);
|
|
1709
|
+
const inner = parseScanShape(body);
|
|
1710
|
+
if (!inner || !groupInnerSafe(inner)) return null;
|
|
1711
|
+
const q = source[k];
|
|
1712
|
+
if (q === "{") return null;
|
|
1713
|
+
flush();
|
|
1714
|
+
if (q === "+") {
|
|
1715
|
+
if (shapeCanBeEmpty(inner)) return null;
|
|
1716
|
+
parts.push({ part: "group", inner, min: 1, unbounded: true });
|
|
1717
|
+
i = k + 1;
|
|
1718
|
+
} else if (q === "*") {
|
|
1719
|
+
if (shapeCanBeEmpty(inner)) return null;
|
|
1720
|
+
parts.push({ part: "group", inner, min: 0, unbounded: true });
|
|
1721
|
+
i = k + 1;
|
|
1722
|
+
} else if (q === "?") {
|
|
1723
|
+
parts.push({ part: "group", inner, min: 0, unbounded: false });
|
|
1724
|
+
i = k + 1;
|
|
1725
|
+
} else {
|
|
1726
|
+
parts.push({ part: "group", inner, min: 1, unbounded: false });
|
|
1727
|
+
i = k;
|
|
1728
|
+
}
|
|
1729
|
+
continue;
|
|
1730
|
+
}
|
|
1731
|
+
if (META.has(ch)) return null;
|
|
1732
|
+
const cp = ch.codePointAt(0);
|
|
1733
|
+
i += ch.length;
|
|
1734
|
+
if (source[i] === "?") {
|
|
1735
|
+
flush();
|
|
1736
|
+
parts.push({ part: "lit", cps: [cp], optional: true });
|
|
1737
|
+
i++;
|
|
1738
|
+
} else lit.push(cp);
|
|
1739
|
+
}
|
|
1740
|
+
flush();
|
|
1741
|
+
return parts.length ? parts : null;
|
|
1742
|
+
}
|
|
1743
|
+
function seqIsUnambiguous(parts) {
|
|
1744
|
+
let hasMandatory = false;
|
|
1745
|
+
for (let k = 0; k < parts.length; k++) {
|
|
1746
|
+
const p = parts[k];
|
|
1747
|
+
const mandatory = p.part === "lit" ? !p.optional : p.min === 1;
|
|
1748
|
+
if (mandatory) hasMandatory = true;
|
|
1749
|
+
const skippableSingle = p.part === "lit" && p.optional || p.part !== "lit" && !p.unbounded && p.min === 0;
|
|
1750
|
+
const isUnboundedRepeat = p.part !== "lit" && p.unbounded;
|
|
1751
|
+
if (skippableSingle || isUnboundedRepeat) {
|
|
1752
|
+
const rest = seqFirstAccept(parts.slice(k + 1));
|
|
1753
|
+
if (!firstSetsDisjoint(partFirstAccept(p), rest)) return false;
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
return hasMandatory;
|
|
1757
|
+
}
|
|
1758
|
+
function rangesOverlap(a, b) {
|
|
1759
|
+
return a.some(([lo, hi]) => b.some(([lo2, hi2]) => lo <= hi2 && lo2 <= hi));
|
|
1760
|
+
}
|
|
1761
|
+
function rangesSubset(sub, sup) {
|
|
1762
|
+
return sub.every(([lo, hi]) => sup.some(([lo2, hi2]) => lo >= lo2 && hi <= hi2));
|
|
1763
|
+
}
|
|
1764
|
+
function parseClassOperand(body) {
|
|
1765
|
+
if (body === "\\d" || body === "\\w" || body === "\\s") {
|
|
1766
|
+
return { ranges: shorthandRanges(body[1]), negated: false };
|
|
1767
|
+
}
|
|
1768
|
+
if (body.length >= 2 && body[0] === "[" && body[body.length - 1] === "]") {
|
|
1769
|
+
let inner = body.slice(1, -1);
|
|
1770
|
+
const negated = inner.startsWith("^");
|
|
1771
|
+
if (negated) inner = inner.slice(1);
|
|
1772
|
+
const ranges = parseClassRanges(inner);
|
|
1773
|
+
return ranges ? { ranges, negated } : null;
|
|
1774
|
+
}
|
|
1775
|
+
const cps = literalCodePoints(body);
|
|
1776
|
+
if (cps && cps.length === 1) return { ranges: [[cps[0], cps[0]]], negated: false };
|
|
1777
|
+
return null;
|
|
1778
|
+
}
|
|
1779
|
+
function classSubset(t, u) {
|
|
1780
|
+
if (!t.negated && !u.negated) return rangesSubset(t.ranges, u.ranges);
|
|
1781
|
+
if (!t.negated && u.negated) return !rangesOverlap(t.ranges, u.ranges);
|
|
1782
|
+
if (t.negated && !u.negated) return false;
|
|
1783
|
+
return rangesSubset(u.ranges, t.ranges);
|
|
1784
|
+
}
|
|
1785
|
+
function classDisjoint(t, u) {
|
|
1786
|
+
if (!t.negated && !u.negated) return !rangesOverlap(t.ranges, u.ranges);
|
|
1787
|
+
if (!t.negated && u.negated) return rangesSubset(t.ranges, u.ranges);
|
|
1788
|
+
if (t.negated && !u.negated) return rangesSubset(u.ranges, t.ranges);
|
|
1789
|
+
return false;
|
|
1790
|
+
}
|
|
1791
|
+
function firstSetsDisjoint(a, b) {
|
|
1792
|
+
if (a === "any" || b === "any") return false;
|
|
1793
|
+
return classDisjoint(a, b);
|
|
1794
|
+
}
|
|
1795
|
+
function trailingBacktrackClass(shape) {
|
|
1796
|
+
if (shape.kind === "chars") return { ranges: shape.ranges, negated: false };
|
|
1797
|
+
if (shape.kind === "ident") return { ranges: shape.tail, negated: false };
|
|
1798
|
+
if (shape.kind === "litFold") return null;
|
|
1799
|
+
if (shape.kind === "seq") {
|
|
1800
|
+
const last = shape.parts[shape.parts.length - 1];
|
|
1801
|
+
if (last.part === "lit") return null;
|
|
1802
|
+
if (last.part === "run") {
|
|
1803
|
+
if (last.unbounded || last.min === 0) return { ranges: last.ranges, negated: last.negated };
|
|
1804
|
+
return null;
|
|
1805
|
+
}
|
|
1806
|
+
const innerWiggle = trailingBacktrackClass(last.inner);
|
|
1807
|
+
if (innerWiggle === "unsupported") return "unsupported";
|
|
1808
|
+
const requiredOnce = !last.unbounded && last.min === 1;
|
|
1809
|
+
if (requiredOnce) return innerWiggle;
|
|
1810
|
+
const dropExposed = shapeFirstAccept(last.inner);
|
|
1811
|
+
if (dropExposed === "any") return "unsupported";
|
|
1812
|
+
if (innerWiggle === null) return dropExposed;
|
|
1813
|
+
const unioned = unionCharSets([innerWiggle, dropExposed]);
|
|
1814
|
+
return unioned === "any" ? "unsupported" : unioned;
|
|
1815
|
+
}
|
|
1816
|
+
if (shape.kind === "alt") {
|
|
1817
|
+
if (!shape.disjoint) return "unsupported";
|
|
1818
|
+
const classes = shape.arms.map(trailingBacktrackClass);
|
|
1819
|
+
if (classes.some((c) => c === "unsupported")) return "unsupported";
|
|
1820
|
+
const concrete = classes.filter((c) => c !== null);
|
|
1821
|
+
if (concrete.length === 0) return null;
|
|
1822
|
+
const unioned = unionCharSets(concrete);
|
|
1823
|
+
return unioned === "any" ? "unsupported" : unioned;
|
|
1824
|
+
}
|
|
1825
|
+
return "unsupported";
|
|
1826
|
+
}
|
|
1827
|
+
function lookaheadUnambiguous(inner, operand, negative) {
|
|
1828
|
+
const tail = trailingBacktrackClass(inner);
|
|
1829
|
+
if (tail === "unsupported") return false;
|
|
1830
|
+
if (tail === null) return true;
|
|
1831
|
+
return negative ? classSubset(tail, operand) : classDisjoint(tail, operand);
|
|
1832
|
+
}
|
|
1833
|
+
function stripTrailingLookahead(source) {
|
|
1834
|
+
if (!source.endsWith(")")) return null;
|
|
1835
|
+
for (const negative of [true, false]) {
|
|
1836
|
+
const lead = negative ? "(?!" : "(?=";
|
|
1837
|
+
const idx = source.lastIndexOf(lead);
|
|
1838
|
+
if (idx === -1) continue;
|
|
1839
|
+
const body = source.slice(idx + lead.length, -1);
|
|
1840
|
+
const operand = body.length ? parseClassOperand(body) : null;
|
|
1841
|
+
if (!operand) continue;
|
|
1842
|
+
return { base: source.slice(0, idx), ranges: operand.ranges, classNegated: operand.negated, negative };
|
|
1843
|
+
}
|
|
1844
|
+
return null;
|
|
1845
|
+
}
|
|
1846
|
+
function unwrapOuterGroup(source) {
|
|
1847
|
+
while (source.startsWith("(?:")) {
|
|
1848
|
+
let depth = 1;
|
|
1849
|
+
let i = 3;
|
|
1850
|
+
let ok = true;
|
|
1851
|
+
while (i < source.length && depth > 0) {
|
|
1852
|
+
const ch = source[i];
|
|
1853
|
+
if (ch === "\\") {
|
|
1854
|
+
i += 2;
|
|
1855
|
+
continue;
|
|
1856
|
+
}
|
|
1857
|
+
if (ch === "[") {
|
|
1858
|
+
let j = i + 1;
|
|
1859
|
+
if (source[j] === "^") j++;
|
|
1860
|
+
while (j < source.length && source[j] !== "]") {
|
|
1861
|
+
if (source[j] === "\\") j += 2;
|
|
1862
|
+
else j++;
|
|
1863
|
+
}
|
|
1864
|
+
if (source[j] !== "]") {
|
|
1865
|
+
ok = false;
|
|
1866
|
+
break;
|
|
1867
|
+
}
|
|
1868
|
+
i = j + 1;
|
|
1869
|
+
continue;
|
|
1870
|
+
}
|
|
1871
|
+
if (ch === "(") depth++;
|
|
1872
|
+
else if (ch === ")") depth--;
|
|
1873
|
+
i++;
|
|
1874
|
+
}
|
|
1875
|
+
if (!ok || depth !== 0 || i !== source.length) break;
|
|
1876
|
+
source = source.slice(3, -1);
|
|
1877
|
+
}
|
|
1878
|
+
return source;
|
|
1879
|
+
}
|
|
1880
|
+
function splitTopLevelAlternation(source) {
|
|
1881
|
+
const body = unwrapOuterGroup(source);
|
|
1882
|
+
const parts = [];
|
|
1883
|
+
let depth = 0;
|
|
1884
|
+
let last = 0;
|
|
1885
|
+
let i = 0;
|
|
1886
|
+
while (i < body.length) {
|
|
1887
|
+
const ch = body[i];
|
|
1888
|
+
if (ch === "\\") {
|
|
1889
|
+
i += 2;
|
|
1890
|
+
continue;
|
|
1891
|
+
}
|
|
1892
|
+
if (ch === "[") {
|
|
1893
|
+
let j = i + 1;
|
|
1894
|
+
if (body[j] === "^") j++;
|
|
1895
|
+
while (j < body.length && body[j] !== "]") {
|
|
1896
|
+
if (body[j] === "\\") j += 2;
|
|
1897
|
+
else j++;
|
|
1898
|
+
}
|
|
1899
|
+
if (body[j] !== "]") return null;
|
|
1900
|
+
i = j + 1;
|
|
1901
|
+
continue;
|
|
1902
|
+
}
|
|
1903
|
+
if (ch === "(") {
|
|
1904
|
+
depth++;
|
|
1905
|
+
i++;
|
|
1906
|
+
continue;
|
|
1907
|
+
}
|
|
1908
|
+
if (ch === ")") {
|
|
1909
|
+
depth--;
|
|
1910
|
+
if (depth < 0) return null;
|
|
1911
|
+
i++;
|
|
1912
|
+
continue;
|
|
1913
|
+
}
|
|
1914
|
+
if (ch === "|" && depth === 0) {
|
|
1915
|
+
parts.push(body.slice(last, i));
|
|
1916
|
+
last = i + 1;
|
|
1917
|
+
i++;
|
|
1918
|
+
continue;
|
|
1919
|
+
}
|
|
1920
|
+
i++;
|
|
1921
|
+
}
|
|
1922
|
+
if (depth !== 0) return null;
|
|
1923
|
+
parts.push(body.slice(last));
|
|
1924
|
+
if (parts.length < 2 || parts.some((p) => p.length === 0)) return null;
|
|
1925
|
+
return parts;
|
|
1926
|
+
}
|
|
1927
|
+
function shapeCanBeEmpty(shape) {
|
|
1928
|
+
if (shape.kind === "chars") return !shape.minOne;
|
|
1929
|
+
if (shape.kind === "lookahead") return shapeCanBeEmpty(shape.inner);
|
|
1930
|
+
if (shape.kind === "alt") return shape.arms.some(shapeCanBeEmpty);
|
|
1931
|
+
return false;
|
|
1932
|
+
}
|
|
1933
|
+
function unionCharSets(sets) {
|
|
1934
|
+
if (sets.some((s) => s === "any")) return "any";
|
|
1935
|
+
const concrete = sets;
|
|
1936
|
+
if (concrete.length === 1) return concrete[0];
|
|
1937
|
+
if (concrete.some((s) => s.negated)) return "any";
|
|
1938
|
+
return { ranges: concrete.flatMap((s) => s.ranges), negated: false };
|
|
1939
|
+
}
|
|
1940
|
+
function partFirstAccept(part) {
|
|
1941
|
+
if (part.part === "lit") return { ranges: [[part.cps[0], part.cps[0]]], negated: false };
|
|
1942
|
+
if (part.part === "run") return { ranges: part.ranges, negated: part.negated };
|
|
1943
|
+
return shapeFirstAccept(part.inner);
|
|
1944
|
+
}
|
|
1945
|
+
function seqFirstAccept(parts) {
|
|
1946
|
+
const sets = [];
|
|
1947
|
+
for (const p of parts) {
|
|
1948
|
+
const mandatory = p.part === "lit" ? !p.optional : p.min === 1;
|
|
1949
|
+
sets.push(partFirstAccept(p));
|
|
1950
|
+
if (mandatory) break;
|
|
1951
|
+
}
|
|
1952
|
+
return unionCharSets(sets);
|
|
1953
|
+
}
|
|
1954
|
+
function groupInnerSafe(shape) {
|
|
1955
|
+
if (shape.kind === "chars" || shape.kind === "ident" || shape.kind === "seq" || shape.kind === "litFold") return true;
|
|
1956
|
+
if (shape.kind === "lookahead") return groupInnerSafe(shape.inner);
|
|
1957
|
+
if (shape.kind === "alt") return shape.disjoint;
|
|
1958
|
+
return false;
|
|
1959
|
+
}
|
|
1960
|
+
function shapeFirstAccept(shape) {
|
|
1961
|
+
if (shapeCanBeEmpty(shape)) return "any";
|
|
1962
|
+
switch (shape.kind) {
|
|
1963
|
+
case "chars":
|
|
1964
|
+
return { ranges: shape.ranges, negated: false };
|
|
1965
|
+
case "ident":
|
|
1966
|
+
return { ranges: shape.head, negated: false };
|
|
1967
|
+
case "until":
|
|
1968
|
+
return { ranges: [[shape.open[0], shape.open[0]]], negated: false };
|
|
1969
|
+
case "delimited":
|
|
1970
|
+
return { ranges: [[shape.open[0], shape.open[0]]], negated: false };
|
|
1971
|
+
case "string":
|
|
1972
|
+
return { ranges: [[shape.quote, shape.quote]], negated: false };
|
|
1973
|
+
case "litFold": {
|
|
1974
|
+
const cp = shape.open[0];
|
|
1975
|
+
if (cp >= 65 && cp <= 90) return { ranges: [[cp, cp], [cp + 32, cp + 32]], negated: false };
|
|
1976
|
+
if (cp >= 97 && cp <= 122) return { ranges: [[cp, cp], [cp - 32, cp - 32]], negated: false };
|
|
1977
|
+
return { ranges: [[cp, cp]], negated: false };
|
|
1978
|
+
}
|
|
1979
|
+
case "seq":
|
|
1980
|
+
return seqFirstAccept(shape.parts);
|
|
1981
|
+
case "lookahead":
|
|
1982
|
+
return shapeFirstAccept(shape.inner);
|
|
1983
|
+
// zero-width — doesn't change first-char acceptance
|
|
1984
|
+
case "alt": {
|
|
1985
|
+
if (!shape.disjoint) return "any";
|
|
1986
|
+
const sets = shape.firsts.filter((f) => f !== null);
|
|
1987
|
+
return sets.length === shape.arms.length ? unionCharSets(sets) : "any";
|
|
1988
|
+
}
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
function allPairsDisjoint(sets) {
|
|
1992
|
+
for (let i = 0; i < sets.length; i++) {
|
|
1993
|
+
const a = sets[i];
|
|
1994
|
+
if (a === "any") return false;
|
|
1995
|
+
for (let j = i + 1; j < sets.length; j++) {
|
|
1996
|
+
const b = sets[j];
|
|
1997
|
+
if (b === "any" || !classDisjoint(a, b)) return false;
|
|
1998
|
+
}
|
|
1999
|
+
}
|
|
2000
|
+
return true;
|
|
2001
|
+
}
|
|
2002
|
+
function parseAlternation(source) {
|
|
2003
|
+
const parts = splitTopLevelAlternation(source);
|
|
2004
|
+
if (!parts) return null;
|
|
2005
|
+
const arms = [];
|
|
2006
|
+
for (const p of parts) {
|
|
2007
|
+
const arm = parseScanShape(p);
|
|
2008
|
+
if (!arm) return null;
|
|
2009
|
+
arms.push(arm);
|
|
2010
|
+
}
|
|
2011
|
+
const firstSets = arms.map(shapeFirstAccept);
|
|
2012
|
+
const disjoint = allPairsDisjoint(firstSets);
|
|
2013
|
+
return { kind: "alt", arms, disjoint, firsts: firstSets.map((f) => f === "any" ? null : f) };
|
|
2014
|
+
}
|
|
1571
2015
|
function parseScanShape(source) {
|
|
2016
|
+
const alt = parseAlternation(source);
|
|
2017
|
+
if (alt) return alt;
|
|
2018
|
+
const la = stripTrailingLookahead(source);
|
|
2019
|
+
if (la) {
|
|
2020
|
+
const inner = parseScanShapeCore(la.base);
|
|
2021
|
+
if (!inner) return null;
|
|
2022
|
+
const operand = { ranges: la.ranges, negated: la.classNegated };
|
|
2023
|
+
if (!lookaheadUnambiguous(inner, operand, la.negative)) return null;
|
|
2024
|
+
return { kind: "lookahead", inner, ranges: la.ranges, classNegated: la.classNegated, negative: la.negative };
|
|
2025
|
+
}
|
|
2026
|
+
return parseScanShapeCore(source);
|
|
2027
|
+
}
|
|
2028
|
+
function parseScanShapeCore(source) {
|
|
1572
2029
|
let m = /^\[((?:\\.|[^\]])+)\]([+*])$/.exec(source);
|
|
1573
|
-
if (m) {
|
|
1574
|
-
if (m[1].startsWith("^")) return null;
|
|
2030
|
+
if (m && !m[1].startsWith("^")) {
|
|
1575
2031
|
const ranges = parseClassRanges(m[1]);
|
|
1576
2032
|
return ranges ? { kind: "chars", ranges, minOne: m[2] === "+" } : null;
|
|
1577
2033
|
}
|
|
1578
|
-
m = /^\\([
|
|
2034
|
+
m = /^\\([dws])([+*])$/.exec(source);
|
|
1579
2035
|
if (m) {
|
|
1580
2036
|
return { kind: "chars", ranges: shorthandRanges(m[1]), minOne: m[2] === "+" };
|
|
1581
2037
|
}
|
|
1582
|
-
m = /^(\[(?:\\.|[^\]])+\]|\\[
|
|
2038
|
+
m = /^(\[(?:\\.|[^\]])+\]|\\[dws])(\[(?:\\.|[^\]])+\]|\\[dws])\*$/.exec(source);
|
|
1583
2039
|
if (m) {
|
|
1584
2040
|
const head = classToRanges(m[1]);
|
|
1585
2041
|
const tail = classToRanges(m[2]);
|
|
1586
|
-
|
|
2042
|
+
if (head && tail) return { kind: "ident", head, tail };
|
|
1587
2043
|
}
|
|
1588
2044
|
const str = parseStringShape(source);
|
|
1589
2045
|
if (str) return str;
|
|
@@ -1592,7 +2048,6 @@ function parseScanShape(source) {
|
|
|
1592
2048
|
const open = literalCodePoints(m[1]);
|
|
1593
2049
|
const stop = parseClassRanges(m[2]);
|
|
1594
2050
|
if (open && stop) return { kind: "until", open, stop };
|
|
1595
|
-
return null;
|
|
1596
2051
|
}
|
|
1597
2052
|
if (!source.includes("\\\\")) {
|
|
1598
2053
|
m = /^(.*?)\((?:\?:)?[\s\S]*\)\*(.*?)$/.exec(source);
|
|
@@ -1602,10 +2057,16 @@ function parseScanShape(source) {
|
|
|
1602
2057
|
if (open && close) return { kind: "delimited", open, close };
|
|
1603
2058
|
}
|
|
1604
2059
|
}
|
|
2060
|
+
const parts = parseSeqParts(source);
|
|
2061
|
+
if (parts && seqIsUnambiguous(parts)) return { kind: "seq", parts };
|
|
1605
2062
|
return null;
|
|
1606
2063
|
}
|
|
1607
2064
|
function scanShapeFromRegex(source, flags) {
|
|
1608
|
-
if (/[
|
|
2065
|
+
if (/[msu]/.test(flags)) return null;
|
|
2066
|
+
if (/i/.test(flags)) {
|
|
2067
|
+
const open = literalCodePoints(source);
|
|
2068
|
+
return open ? { kind: "litFold", open } : null;
|
|
2069
|
+
}
|
|
1609
2070
|
return parseScanShape(source);
|
|
1610
2071
|
}
|
|
1611
2072
|
var classCond = (cVar, ranges) => ranges.map(([lo, hi]) => lo === hi ? `${cVar} === ${lo}` : `(${cVar} >= ${lo} && ${cVar} <= ${hi})`).join(" || ");
|
|
@@ -1620,6 +2081,53 @@ function stringHardStop(shape) {
|
|
|
1620
2081
|
}
|
|
1621
2082
|
var codeAt = (start, firstChar) => firstChar ?? `input.charCodeAt(${start})`;
|
|
1622
2083
|
function emitShapeMatch(shape, start, mint, ind2, firstChar) {
|
|
2084
|
+
if (shape.kind === "lookahead") {
|
|
2085
|
+
const inner = emitShapeMatch(shape.inner, start, mint, ind2, firstChar);
|
|
2086
|
+
const okV = mint("_ok");
|
|
2087
|
+
const endV2 = mint("_end");
|
|
2088
|
+
const rawIn = classCond(`input.charCodeAt(${inner.end})`, shape.ranges);
|
|
2089
|
+
const charInClass = shape.classNegated ? `!(${rawIn})` : `(${rawIn})`;
|
|
2090
|
+
const hasMatchingChar = `${inner.end} < input.length && ${charInClass}`;
|
|
2091
|
+
const guardFails = shape.negative ? hasMatchingChar : `!(${hasMatchingChar})`;
|
|
2092
|
+
return {
|
|
2093
|
+
setup: [
|
|
2094
|
+
...inner.setup,
|
|
2095
|
+
`${ind2}let ${okV} = ${inner.ok}`,
|
|
2096
|
+
`${ind2}let ${endV2} = ${inner.end}`,
|
|
2097
|
+
`${ind2}if (${okV} && (${guardFails})) { ${okV} = false; ${endV2} = ${start} }`
|
|
2098
|
+
],
|
|
2099
|
+
ok: okV,
|
|
2100
|
+
end: endV2
|
|
2101
|
+
};
|
|
2102
|
+
}
|
|
2103
|
+
if (shape.kind === "alt") {
|
|
2104
|
+
const okV = mint("_ok");
|
|
2105
|
+
const endV2 = mint("_end");
|
|
2106
|
+
const lines = [`${ind2}let ${okV} = false`, `${ind2}let ${endV2} = ${start}`];
|
|
2107
|
+
if (shape.disjoint) {
|
|
2108
|
+
const c0 = codeAt(start, firstChar);
|
|
2109
|
+
shape.arms.forEach((arm, k) => {
|
|
2110
|
+
const fs = shape.firsts[k];
|
|
2111
|
+
const cond = fs.negated ? `!(${classCond(c0, fs.ranges)})` : `(${classCond(c0, fs.ranges)})`;
|
|
2112
|
+
const m = emitShapeMatch(arm, start, mint, `${ind2} `, firstChar);
|
|
2113
|
+
lines.push(`${ind2}${k === 0 ? "if" : "else if"} (${start} < input.length && ${cond}) {`);
|
|
2114
|
+
lines.push(...m.setup);
|
|
2115
|
+
lines.push(`${ind2} ${okV} = ${m.ok}`);
|
|
2116
|
+
lines.push(`${ind2} ${endV2} = ${m.ok} ? ${m.end} : ${start}`);
|
|
2117
|
+
lines.push(`${ind2}}`);
|
|
2118
|
+
});
|
|
2119
|
+
} else {
|
|
2120
|
+
const lbl = mint("_alt");
|
|
2121
|
+
lines.push(`${ind2}${lbl}: {`);
|
|
2122
|
+
for (const arm of shape.arms) {
|
|
2123
|
+
const m = emitShapeMatch(arm, start, mint, `${ind2} `, firstChar);
|
|
2124
|
+
lines.push(...m.setup);
|
|
2125
|
+
lines.push(`${ind2} if (${m.ok}) { ${okV} = true; ${endV2} = ${m.end}; break ${lbl} }`);
|
|
2126
|
+
}
|
|
2127
|
+
lines.push(`${ind2}}`);
|
|
2128
|
+
}
|
|
2129
|
+
return { setup: lines, ok: okV, end: endV2 };
|
|
2130
|
+
}
|
|
1623
2131
|
if (shape.kind === "chars") {
|
|
1624
2132
|
const cur = mint("_e");
|
|
1625
2133
|
return {
|
|
@@ -1646,6 +2154,82 @@ function emitShapeMatch(shape, start, mint, ind2, firstChar) {
|
|
|
1646
2154
|
end: cur
|
|
1647
2155
|
};
|
|
1648
2156
|
}
|
|
2157
|
+
if (shape.kind === "seq") {
|
|
2158
|
+
const endV2 = mint("_e");
|
|
2159
|
+
const okV = mint("_ok");
|
|
2160
|
+
const runCond = (p, at) => {
|
|
2161
|
+
const c = classCond(`input.charCodeAt(${at})`, p.ranges);
|
|
2162
|
+
return p.negated ? `!(${c})` : `(${c})`;
|
|
2163
|
+
};
|
|
2164
|
+
const lines = [`${ind2}let ${endV2} = ${start}`, `${ind2}let ${okV} = false`, `${ind2}do {`];
|
|
2165
|
+
let first = true;
|
|
2166
|
+
for (const p of shape.parts) {
|
|
2167
|
+
if (p.part === "lit") {
|
|
2168
|
+
const L = p.cps.length;
|
|
2169
|
+
const cond = litCond(endV2, p.cps, first ? firstChar : void 0);
|
|
2170
|
+
if (p.optional) {
|
|
2171
|
+
lines.push(`${ind2} if (${endV2} + ${L} <= input.length && (${cond})) ${endV2} += ${L}`);
|
|
2172
|
+
} else {
|
|
2173
|
+
lines.push(`${ind2} if (!(${endV2} + ${L} <= input.length && (${cond}))) break`);
|
|
2174
|
+
lines.push(`${ind2} ${endV2} += ${L}`);
|
|
2175
|
+
}
|
|
2176
|
+
} else if (p.part === "run" && !p.unbounded) {
|
|
2177
|
+
if (p.min === 1) {
|
|
2178
|
+
lines.push(`${ind2} if (!(${endV2} < input.length && ${runCond(p, endV2)})) break`);
|
|
2179
|
+
lines.push(`${ind2} ${endV2}++`);
|
|
2180
|
+
} else {
|
|
2181
|
+
lines.push(`${ind2} if (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
2182
|
+
}
|
|
2183
|
+
} else if (p.part === "run") {
|
|
2184
|
+
const s = mint("_s");
|
|
2185
|
+
lines.push(`${ind2} const ${s} = ${endV2}`);
|
|
2186
|
+
lines.push(`${ind2} while (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
2187
|
+
if (p.min === 1) lines.push(`${ind2} if (${endV2} === ${s}) break`);
|
|
2188
|
+
} else {
|
|
2189
|
+
const inner = emitShapeMatch(p.inner, endV2, mint, `${ind2} `, first ? firstChar : void 0);
|
|
2190
|
+
if (!p.unbounded) {
|
|
2191
|
+
lines.push(...inner.setup);
|
|
2192
|
+
if (p.min === 1) {
|
|
2193
|
+
lines.push(`${ind2} if (!(${inner.ok})) break`);
|
|
2194
|
+
lines.push(`${ind2} ${endV2} = ${inner.end}`);
|
|
2195
|
+
} else {
|
|
2196
|
+
lines.push(`${ind2} if (${inner.ok}) ${endV2} = ${inner.end}`);
|
|
2197
|
+
}
|
|
2198
|
+
} else {
|
|
2199
|
+
const progV = mint("_prog");
|
|
2200
|
+
lines.push(`${ind2} let ${progV} = false`);
|
|
2201
|
+
lines.push(`${ind2} while (true) {`);
|
|
2202
|
+
lines.push(...inner.setup);
|
|
2203
|
+
lines.push(`${ind2} if (!(${inner.ok})) break`);
|
|
2204
|
+
lines.push(`${ind2} ${endV2} = ${inner.end}`);
|
|
2205
|
+
lines.push(`${ind2} ${progV} = true`);
|
|
2206
|
+
lines.push(`${ind2} }`);
|
|
2207
|
+
if (p.min === 1) lines.push(`${ind2} if (!${progV}) break`);
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
first = false;
|
|
2211
|
+
}
|
|
2212
|
+
lines.push(`${ind2} ${okV} = true`);
|
|
2213
|
+
lines.push(`${ind2}} while (false)`);
|
|
2214
|
+
lines.push(`${ind2}if (!${okV}) ${endV2} = ${start}`);
|
|
2215
|
+
return { setup: lines, ok: okV, end: endV2 };
|
|
2216
|
+
}
|
|
2217
|
+
if (shape.kind === "litFold") {
|
|
2218
|
+
const openLen2 = shape.open.length;
|
|
2219
|
+
const endV2 = mint("_end");
|
|
2220
|
+
const checks = shape.open.map((cp, k) => {
|
|
2221
|
+
const cVar = k === 0 && firstChar ? firstChar : `input.charCodeAt(${start} + ${k})`;
|
|
2222
|
+
return foldEq(cVar, cp);
|
|
2223
|
+
});
|
|
2224
|
+
return {
|
|
2225
|
+
setup: [
|
|
2226
|
+
`${ind2}let ${endV2} = ${start}`,
|
|
2227
|
+
`${ind2}if (${start} + ${openLen2} <= input.length && (${checks.join(" && ")})) ${endV2} = ${start} + ${openLen2}`
|
|
2228
|
+
],
|
|
2229
|
+
ok: `${endV2} > ${start}`,
|
|
2230
|
+
end: endV2
|
|
2231
|
+
};
|
|
2232
|
+
}
|
|
1649
2233
|
if (shape.kind === "until") {
|
|
1650
2234
|
const j2 = mint("_j");
|
|
1651
2235
|
const openLen2 = shape.open.length;
|
|
@@ -2041,7 +2625,7 @@ function hoistExpected(ctx, constArrSource) {
|
|
|
2041
2625
|
let name = ctx.expectedMap.get(constArrSource);
|
|
2042
2626
|
if (name === void 0) {
|
|
2043
2627
|
name = `_fx${ctx.expectedDecls.length}`;
|
|
2044
|
-
ctx.expectedDecls.push(`const ${name} =
|
|
2628
|
+
ctx.expectedDecls.push(`const ${name} = ${constArrSource}`);
|
|
2045
2629
|
ctx.expectedMap.set(constArrSource, name);
|
|
2046
2630
|
}
|
|
2047
2631
|
return name;
|
|
@@ -2363,18 +2947,21 @@ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
2363
2947
|
return true;
|
|
2364
2948
|
}
|
|
2365
2949
|
}
|
|
2366
|
-
function emitFallible(inner, ctx, pos) {
|
|
2950
|
+
function emitFallible(inner, ctx, pos, swallow = false) {
|
|
2367
2951
|
const lbl = v(ctx, "_lbl");
|
|
2368
2952
|
const okV = `${lbl}ok`;
|
|
2369
2953
|
const valV = `${lbl}v`;
|
|
2370
2954
|
const endV = `${lbl}e`;
|
|
2371
2955
|
const savedLabel = ctx.failLabel;
|
|
2372
2956
|
const savedIndent = ctx.indent;
|
|
2957
|
+
const savedRecord = ctx.recordFail;
|
|
2373
2958
|
ctx.failLabel = lbl;
|
|
2374
2959
|
ctx.indent = savedIndent + 1;
|
|
2960
|
+
if (swallow) ctx.recordFail = false;
|
|
2375
2961
|
const r = emit(inner, ctx, pos);
|
|
2376
2962
|
ctx.failLabel = savedLabel;
|
|
2377
2963
|
ctx.indent = savedIndent;
|
|
2964
|
+
ctx.recordFail = savedRecord;
|
|
2378
2965
|
const ind0 = ind(ctx);
|
|
2379
2966
|
const needsRollback = ctx.capturing && mayLeavePartialCapture(inner);
|
|
2380
2967
|
const mL = needsRollback ? v(ctx, "_fcl") : null;
|
|
@@ -2397,6 +2984,7 @@ function emitFallible(inner, ctx, pos) {
|
|
|
2397
2984
|
];
|
|
2398
2985
|
return { stmts, okVar: okV, valVar: valV, endVar: endV };
|
|
2399
2986
|
}
|
|
2987
|
+
var CHARCODE_CHAIN_MAX = 16;
|
|
2400
2988
|
function emitLit(def, ctx, pos) {
|
|
2401
2989
|
const { value, caseInsensitive } = def;
|
|
2402
2990
|
const len = value.length;
|
|
@@ -2419,7 +3007,7 @@ function emitLit(def, ctx, pos) {
|
|
|
2419
3007
|
...emitIfFail(ctx, `${pos} >= input.length || input.charCodeAt(${pos}) !== ${code}`, failBody(ctx, expectedStr, pos)),
|
|
2420
3008
|
`${ind(ctx)}const ${vv} = ${JSON.stringify(value)}`
|
|
2421
3009
|
);
|
|
2422
|
-
} else if (len <=
|
|
3010
|
+
} else if (len <= CHARCODE_CHAIN_MAX) {
|
|
2423
3011
|
const checks = Array.from(
|
|
2424
3012
|
{ length: len },
|
|
2425
3013
|
(_, i) => `input.charCodeAt(${pos}${i > 0 ? ` + ${i}` : ""}) !== ${value.codePointAt(i)}`
|
|
@@ -2441,7 +3029,55 @@ function emitLit(def, ctx, pos) {
|
|
|
2441
3029
|
function escapeKeywordRe(s) {
|
|
2442
3030
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2443
3031
|
}
|
|
3032
|
+
function emitKeywordsFast(def, ctx, pos) {
|
|
3033
|
+
if (def.words.length === 0 || def.words.some((w) => w.length === 0)) return null;
|
|
3034
|
+
if (def.words.some((w) => Array.from(w).length !== w.length)) return null;
|
|
3035
|
+
if (def.caseInsensitive && def.boundary) return null;
|
|
3036
|
+
let boundary = null;
|
|
3037
|
+
if (def.boundary) {
|
|
3038
|
+
let body = def.boundary;
|
|
3039
|
+
const negated = body.startsWith("^");
|
|
3040
|
+
if (negated) body = body.slice(1);
|
|
3041
|
+
const ranges = parseClassRanges(body);
|
|
3042
|
+
if (!ranges) return null;
|
|
3043
|
+
boundary = { ranges, negated };
|
|
3044
|
+
}
|
|
3045
|
+
const mint = (prefix = "_v") => v(ctx, prefix);
|
|
3046
|
+
const lbl = v(ctx, "_kwLbl");
|
|
3047
|
+
const valV = v(ctx, "_kwv");
|
|
3048
|
+
const endV = v(ctx, "_kwe");
|
|
3049
|
+
const bodyInd = ind(ctx) + " ";
|
|
3050
|
+
const tries = [];
|
|
3051
|
+
for (const w of def.words) {
|
|
3052
|
+
const cps = Array.from(w, (ch) => ch.codePointAt(0));
|
|
3053
|
+
let shape = def.caseInsensitive ? { kind: "litFold", open: cps } : { kind: "seq", parts: [{ part: "lit", cps, optional: false }] };
|
|
3054
|
+
if (boundary) {
|
|
3055
|
+
shape = { kind: "lookahead", inner: shape, ranges: boundary.ranges, classNegated: boundary.negated, negative: true };
|
|
3056
|
+
}
|
|
3057
|
+
const m = emitShapeMatch(shape, pos, mint, bodyInd);
|
|
3058
|
+
tries.push(
|
|
3059
|
+
...m.setup,
|
|
3060
|
+
// Slice from input rather than reusing the literal word: `caseInsensitive`
|
|
3061
|
+
// must return the text as it actually appeared (e.g. "ABC" for keyword
|
|
3062
|
+
// "abc"), matching what the original `RegExp.exec()[0]` returned.
|
|
3063
|
+
`${bodyInd}if (${m.ok}) { ${valV} = input.slice(${pos}, ${m.end}); ${endV} = ${m.end}; break ${lbl} }`
|
|
3064
|
+
);
|
|
3065
|
+
}
|
|
3066
|
+
const stmts = [
|
|
3067
|
+
`${ind(ctx)}let ${valV} = '', ${endV} = ${pos}`,
|
|
3068
|
+
`${ind(ctx)}${lbl}: {`,
|
|
3069
|
+
...tries,
|
|
3070
|
+
`${ind(ctx)}}`,
|
|
3071
|
+
// Every word has length >= 1 (checked above), so a real match always
|
|
3072
|
+
// advances past `pos` — `endV === pos` only happens when no candidate matched.
|
|
3073
|
+
...emitIfFail(ctx, `${endV} === ${pos}`, failBody(ctx, '"keyword"', pos))
|
|
3074
|
+
];
|
|
3075
|
+
stmts.push(...emitLeafCapture(ctx, valV, pos, endV));
|
|
3076
|
+
return { stmts, valueVar: valV, endVar: endV };
|
|
3077
|
+
}
|
|
2444
3078
|
function emitKeywords(def, ctx, pos) {
|
|
3079
|
+
const fast = emitKeywordsFast(def, ctx, pos);
|
|
3080
|
+
if (fast) return fast;
|
|
2445
3081
|
const alt = def.words.map(escapeKeywordRe).join("|");
|
|
2446
3082
|
const boundary = def.boundary ? `(?![${def.boundary}])` : "";
|
|
2447
3083
|
const flags = def.caseInsensitive ? "iuy" : "uy";
|
|
@@ -2572,6 +3208,31 @@ function failsAtStart(p) {
|
|
|
2572
3208
|
return false;
|
|
2573
3209
|
}
|
|
2574
3210
|
}
|
|
3211
|
+
function armStaticExpected(ctx, p) {
|
|
3212
|
+
return hoistExpected(ctx, staticExpectedArr([p]));
|
|
3213
|
+
}
|
|
3214
|
+
function canMatchEmptyAtStart(p) {
|
|
3215
|
+
const d = p._def;
|
|
3216
|
+
switch (d.tag) {
|
|
3217
|
+
case "regex":
|
|
3218
|
+
return /(?:[*?]|\{0,|\{\d*,)/.test(d.source);
|
|
3219
|
+
case "optional":
|
|
3220
|
+
return true;
|
|
3221
|
+
case "many":
|
|
3222
|
+
return true;
|
|
3223
|
+
case "transform":
|
|
3224
|
+
case "label":
|
|
3225
|
+
return canMatchEmptyAtStart(d.parser);
|
|
3226
|
+
case "literal":
|
|
3227
|
+
return d.value.length === 0;
|
|
3228
|
+
default:
|
|
3229
|
+
return false;
|
|
3230
|
+
}
|
|
3231
|
+
}
|
|
3232
|
+
function needsFirstSetGuard(p) {
|
|
3233
|
+
const fs = p._meta.firstSet;
|
|
3234
|
+
return fs.kind !== "any" && !canMatchEmptyAtStart(p);
|
|
3235
|
+
}
|
|
2575
3236
|
function emitDisjointArm(p, ctx, pos, valV, endV) {
|
|
2576
3237
|
if (failsAtStart(p)) {
|
|
2577
3238
|
const r = emit(p, ctx, pos);
|
|
@@ -2713,16 +3374,21 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
2713
3374
|
const resValV = v(ctx, "_crv");
|
|
2714
3375
|
const resEndV = v(ctx, "_cre");
|
|
2715
3376
|
const resOkV = v(ctx, "_crok");
|
|
3377
|
+
const codeV = v(ctx, "_chcode");
|
|
2716
3378
|
const slots = def.parsers.map(() => v(ctx, "_cfx"));
|
|
2717
3379
|
const ind0 = ind(ctx);
|
|
2718
3380
|
const stmts = [
|
|
2719
3381
|
`${ind0}let ${resValV}, ${resEndV} = ${pos}, ${resOkV} = false`,
|
|
2720
|
-
`${ind0}let ${slots.join(", ")}
|
|
3382
|
+
`${ind0}let ${slots.join(", ")}`,
|
|
3383
|
+
`${ind0}const ${codeV} = ${pos} < input.length ? (input.codePointAt(${pos}) ?? -1) : -1`
|
|
2721
3384
|
];
|
|
2722
3385
|
for (let i = 0; i < def.parsers.length; i++) {
|
|
2723
3386
|
const p = def.parsers[i];
|
|
2724
3387
|
const gate = def.gates[i];
|
|
2725
3388
|
const autoNot = def.autoNot[i];
|
|
3389
|
+
const atStart = failsAtStart(p);
|
|
3390
|
+
const staticFx = armStaticExpected(ctx, p);
|
|
3391
|
+
const fsGuard = needsFirstSetGuard(p) ? firstSetCond(codeV, p._meta.firstSet) : null;
|
|
2726
3392
|
let gateCond = null;
|
|
2727
3393
|
if (gate) {
|
|
2728
3394
|
const gateIdx = ctx.mapFns.length;
|
|
@@ -2737,39 +3403,41 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
2737
3403
|
const markTl = armNeedsRollback ? v(ctx, "_cmtl") : null;
|
|
2738
3404
|
const markLog = armNeedsRollback ? v(ctx, "_cmlg") : null;
|
|
2739
3405
|
const rollback = markLeaves ? captureRestoreBody(markLeaves, markRaw, markTl, markLog) : "";
|
|
3406
|
+
const failSlot = atStart ? staticFx : "_ctx._fx";
|
|
2740
3407
|
stmts.push(`${ind0}if (${skipCond}) {`);
|
|
2741
|
-
ctx
|
|
2742
|
-
|
|
3408
|
+
if (fsGuard) stmts.push(`${ind(ctx)}if (${fsGuard}) {`);
|
|
3409
|
+
ctx.indent += fsGuard ? 2 : 1;
|
|
2743
3410
|
if (markLeaves) {
|
|
2744
3411
|
stmts.push(
|
|
2745
|
-
`${
|
|
2746
|
-
`${
|
|
2747
|
-
`${
|
|
2748
|
-
`${
|
|
3412
|
+
`${ind(ctx)}const ${markLeaves} = _ctx._cstLeaves?.length ?? 0`,
|
|
3413
|
+
`${ind(ctx)}const ${markRaw} = _ctx._cstRawChildren?.length ?? 0`,
|
|
3414
|
+
`${ind(ctx)}const ${markTl} = _ctx._cstTriviaLog?.length ?? 0`,
|
|
3415
|
+
`${ind(ctx)}const ${markLog} = _ctx._triviaLog?.length ?? 0`
|
|
2749
3416
|
);
|
|
2750
3417
|
}
|
|
2751
|
-
const { stmts: armStmts, okVar, valVar, endVar } = emitFallible(p, ctx, pos);
|
|
3418
|
+
const { stmts: armStmts, okVar, valVar, endVar } = emitFallible(p, ctx, pos, atStart);
|
|
2752
3419
|
stmts.push(...armStmts);
|
|
2753
|
-
ctx.indent--;
|
|
2754
3420
|
if (autoNot && autoNot.length > 0) {
|
|
2755
3421
|
const anCode = v(ctx, "_anc");
|
|
2756
3422
|
const rejectCond = autoNot.map(
|
|
2757
3423
|
(check) => check.kind === "firstSet" ? firstSetCond(anCode, check.set) : `input.startsWith(${JSON.stringify(check.value)}, ${endVar})`
|
|
2758
3424
|
).join(" || ");
|
|
2759
|
-
stmts.push(`${
|
|
2760
|
-
stmts.push(`${
|
|
2761
|
-
stmts.push(`${
|
|
2762
|
-
stmts.push(`${
|
|
2763
|
-
stmts.push(`${
|
|
2764
|
-
stmts.push(`${
|
|
2765
|
-
stmts.push(`${
|
|
2766
|
-
stmts.push(`${
|
|
2767
|
-
stmts.push(`${
|
|
2768
|
-
if (rollback) stmts.push(`${
|
|
3425
|
+
stmts.push(`${ind(ctx)}if (${okVar}) {`);
|
|
3426
|
+
stmts.push(`${ind(ctx)} const ${anCode} = ${endVar} < input.length ? input.charCodeAt(${endVar}) : -1`);
|
|
3427
|
+
stmts.push(`${ind(ctx)} if (!(${rejectCond})) {`);
|
|
3428
|
+
stmts.push(`${ind(ctx)} ${resValV} = ${valVar}`);
|
|
3429
|
+
stmts.push(`${ind(ctx)} ${resEndV} = ${endVar}`);
|
|
3430
|
+
stmts.push(`${ind(ctx)} ${resOkV} = true`);
|
|
3431
|
+
stmts.push(`${ind(ctx)} }`);
|
|
3432
|
+
stmts.push(`${ind(ctx)}}`);
|
|
3433
|
+
stmts.push(`${ind(ctx)}else { ${slots[i]} = ${failSlot} }`);
|
|
3434
|
+
if (rollback) stmts.push(`${ind(ctx)}if (!${resOkV}) { ${rollback} }`);
|
|
2769
3435
|
} else {
|
|
2770
|
-
stmts.push(`${
|
|
2771
|
-
stmts.push(`${
|
|
3436
|
+
stmts.push(`${ind(ctx)}if (${okVar}) { ${resValV} = ${valVar}; ${resEndV} = ${endVar}; ${resOkV} = true }`);
|
|
3437
|
+
stmts.push(`${ind(ctx)}else { ${slots[i]} = ${failSlot}${rollback ? `; ${rollback}` : ""} }`);
|
|
2772
3438
|
}
|
|
3439
|
+
ctx.indent -= fsGuard ? 2 : 1;
|
|
3440
|
+
if (fsGuard) stmts.push(`${ind(ctx)}} else { ${slots[i]} = ${staticFx} }`);
|
|
2773
3441
|
stmts.push(`${ind0}}`);
|
|
2774
3442
|
}
|
|
2775
3443
|
const concatExpr = `[${slots.map((s) => `...(${s} || [])`).join(", ")}]`;
|
|
@@ -2802,7 +3470,7 @@ function emitTransformChain(p, baseValue, endV, startPos, ctx) {
|
|
|
2802
3470
|
function emitLiteralCondition(litVal, pos) {
|
|
2803
3471
|
const len = litVal.length;
|
|
2804
3472
|
if (len === 0) return "true";
|
|
2805
|
-
if (len >
|
|
3473
|
+
if (len > CHARCODE_CHAIN_MAX) return `input.startsWith(${JSON.stringify(litVal)}, ${pos})`;
|
|
2806
3474
|
const checks = [`${pos} + ${len} <= input.length`];
|
|
2807
3475
|
for (let i = 0; i < len; i++) {
|
|
2808
3476
|
const code = litVal.codePointAt(i);
|
|
@@ -2851,7 +3519,7 @@ function emitMany(def, ctx, pos) {
|
|
|
2851
3519
|
itemPos = npV;
|
|
2852
3520
|
}
|
|
2853
3521
|
}
|
|
2854
|
-
const { stmts: iterStmts, okVar: iterOk, valVar: iterVal, endVar: iterEnd } = emitFallible(def.parser, ctx, itemPos);
|
|
3522
|
+
const { stmts: iterStmts, okVar: iterOk, valVar: iterVal, endVar: iterEnd } = emitFallible(def.parser, ctx, itemPos, true);
|
|
2855
3523
|
stmts.push(
|
|
2856
3524
|
...iterStmts,
|
|
2857
3525
|
`${ind(ctx)}if (!${iterOk} || ${iterEnd} <= ${itemPos}) { ${rollback}break }`,
|
|
@@ -2865,7 +3533,7 @@ function emitMany(def, ctx, pos) {
|
|
|
2865
3533
|
function emitOptional(def, ctx, pos) {
|
|
2866
3534
|
const valV = v(ctx, "_opt");
|
|
2867
3535
|
const endV = v(ctx, "_opte");
|
|
2868
|
-
const { stmts: lblStmts, okVar, valVar, endVar } = emitFallible(def.parser, ctx, pos);
|
|
3536
|
+
const { stmts: lblStmts, okVar, valVar, endVar } = emitFallible(def.parser, ctx, pos, true);
|
|
2869
3537
|
const ind0 = ind(ctx);
|
|
2870
3538
|
const stmts = [
|
|
2871
3539
|
...lblStmts,
|
|
@@ -2877,7 +3545,7 @@ function emitOptional(def, ctx, pos) {
|
|
|
2877
3545
|
function emitSepBy(_p, def, ctx, pos) {
|
|
2878
3546
|
const arrV = v(ctx, "_arr");
|
|
2879
3547
|
const curV = v(ctx, "_cur");
|
|
2880
|
-
const { stmts: firstStmts, okVar: firstOk, valVar: firstVal, endVar: firstEnd } = emitFallible(def.parser, ctx, pos);
|
|
3548
|
+
const { stmts: firstStmts, okVar: firstOk, valVar: firstVal, endVar: firstEnd } = emitFallible(def.parser, ctx, pos, true);
|
|
2881
3549
|
const stmts = [
|
|
2882
3550
|
`${ind(ctx)}const ${arrV} = []`,
|
|
2883
3551
|
`${ind(ctx)}let ${curV} = ${pos}`,
|
|
@@ -2909,11 +3577,11 @@ function emitSepBy(_p, def, ctx, pos) {
|
|
|
2909
3577
|
);
|
|
2910
3578
|
sepAtPos = spV;
|
|
2911
3579
|
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}; `;
|
|
2912
|
-
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos);
|
|
3580
|
+
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos, true);
|
|
2913
3581
|
stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) { ${rollbackToSep}break }`);
|
|
2914
3582
|
const npV = v(ctx, "_np");
|
|
2915
3583
|
stmts.push(`${ind(ctx)}const ${npV} = ${capFn}(input, ${sepEnd}, _ctx, 1)`);
|
|
2916
|
-
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, npV);
|
|
3584
|
+
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, npV, true);
|
|
2917
3585
|
stmts.push(
|
|
2918
3586
|
...nextStmts,
|
|
2919
3587
|
// item failed → unwind the separator too, back to the end of the last item
|
|
@@ -2926,11 +3594,11 @@ function emitSepBy(_p, def, ctx, pos) {
|
|
|
2926
3594
|
const spV = v(ctx, "_sp");
|
|
2927
3595
|
stmts.push(`${ind(ctx)}const ${spV} = ${trivFn}(input, ${curV}, _ctx)`);
|
|
2928
3596
|
sepAtPos = spV;
|
|
2929
|
-
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos);
|
|
3597
|
+
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos, true);
|
|
2930
3598
|
stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) break`);
|
|
2931
3599
|
const npV = v(ctx, "_np");
|
|
2932
3600
|
stmts.push(`${ind(ctx)}const ${npV} = ${trivFn}(input, ${sepEnd}, _ctx)`);
|
|
2933
|
-
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, npV);
|
|
3601
|
+
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, npV, true);
|
|
2934
3602
|
stmts.push(
|
|
2935
3603
|
...nextStmts,
|
|
2936
3604
|
`${ind(ctx)}if (!${nextOk}) break`,
|
|
@@ -2947,10 +3615,10 @@ function emitSepBy(_p, def, ctx, pos) {
|
|
|
2947
3615
|
`${ind(ctx)}const ${markRw} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`
|
|
2948
3616
|
);
|
|
2949
3617
|
}
|
|
2950
|
-
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos);
|
|
3618
|
+
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos, true);
|
|
2951
3619
|
stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) break`);
|
|
2952
3620
|
const nextRb = markLv ? `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${markLv}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markRw}; ` : "";
|
|
2953
|
-
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, sepEnd);
|
|
3621
|
+
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, sepEnd, true);
|
|
2954
3622
|
stmts.push(
|
|
2955
3623
|
...nextStmts,
|
|
2956
3624
|
`${ind(ctx)}if (!${nextOk}) { ${nextRb}break }`,
|
|
@@ -3008,7 +3676,7 @@ function emitScanTo(def, ctx, pos) {
|
|
|
3008
3676
|
return { stmts, valueVar: valV, endVar: curV };
|
|
3009
3677
|
}
|
|
3010
3678
|
function emitNot(def, ctx, pos) {
|
|
3011
|
-
const { stmts, okVar } = emitFallible(def.parser, ctx, pos);
|
|
3679
|
+
const { stmts, okVar } = emitFallible(def.parser, ctx, pos, true);
|
|
3012
3680
|
const label2 = JSON.stringify(`not(${def.parser._tag})`);
|
|
3013
3681
|
return {
|
|
3014
3682
|
stmts: [
|
|
@@ -3099,11 +3767,14 @@ function emitLazy(p, def, ctx, pos) {
|
|
|
3099
3767
|
}
|
|
3100
3768
|
const savedIndent = ctx.indent;
|
|
3101
3769
|
const savedFailLabel = ctx.failLabel;
|
|
3770
|
+
const savedRecord = ctx.recordFail;
|
|
3102
3771
|
ctx.indent = 1;
|
|
3103
3772
|
ctx.failLabel = "_pfail";
|
|
3773
|
+
ctx.recordFail = true;
|
|
3104
3774
|
const r = emit(resolved, ctx, "_pos");
|
|
3105
3775
|
ctx.indent = savedIndent;
|
|
3106
3776
|
ctx.failLabel = savedFailLabel;
|
|
3777
|
+
ctx.recordFail = savedRecord;
|
|
3107
3778
|
pushNamedFnDecl(ctx, fnName2, r.stmts, r.valueVar, r.endVar);
|
|
3108
3779
|
}
|
|
3109
3780
|
const fnName = ctx.namedParsers.get(p);
|
|
@@ -3283,11 +3954,14 @@ function emit(p, ctx, pos) {
|
|
|
3283
3954
|
ctx.namedParsers.set(innerParser, fnName);
|
|
3284
3955
|
const savedIndent = ctx.indent;
|
|
3285
3956
|
const savedFailLabel = ctx.failLabel;
|
|
3957
|
+
const savedRecord = ctx.recordFail;
|
|
3286
3958
|
ctx.indent = 1;
|
|
3287
3959
|
ctx.failLabel = "_pfail";
|
|
3960
|
+
ctx.recordFail = true;
|
|
3288
3961
|
const innerR = emit(innerParser, ctx, "_pos");
|
|
3289
3962
|
ctx.indent = savedIndent;
|
|
3290
3963
|
ctx.failLabel = savedFailLabel;
|
|
3964
|
+
ctx.recordFail = savedRecord;
|
|
3291
3965
|
pushNamedFnDecl(ctx, fnName, innerR.stmts, innerR.valueVar, innerR.endVar);
|
|
3292
3966
|
}
|
|
3293
3967
|
const fn = ctx.namedParsers.get(innerParser);
|
|
@@ -3435,6 +4109,7 @@ function compile(combinator, mapFnSources) {
|
|
|
3435
4109
|
regexMap: /* @__PURE__ */ new Map(),
|
|
3436
4110
|
expectedDecls: [],
|
|
3437
4111
|
expectedMap: /* @__PURE__ */ new Map(),
|
|
4112
|
+
recordFail: true,
|
|
3438
4113
|
mapFns: [],
|
|
3439
4114
|
mapFnSrcs: [],
|
|
3440
4115
|
buildFns: [],
|
|
@@ -3804,7 +4479,7 @@ function graftAndShift(root, path, newNode, delta) {
|
|
|
3804
4479
|
children: newChildren
|
|
3805
4480
|
};
|
|
3806
4481
|
}
|
|
3807
|
-
var
|
|
4482
|
+
var ParseDocImpl = class _ParseDocImpl {
|
|
3808
4483
|
_registry;
|
|
3809
4484
|
_rootRule;
|
|
3810
4485
|
_opts;
|
|
@@ -3821,7 +4496,7 @@ var FunctionalDocImpl = class _FunctionalDocImpl {
|
|
|
3821
4496
|
}
|
|
3822
4497
|
edit(from, to, replacement) {
|
|
3823
4498
|
const newInput = this.input.slice(0, from) + replacement + this.input.slice(to);
|
|
3824
|
-
const reparse = () =>
|
|
4499
|
+
const reparse = () => parseDoc(this._registry, this._rootRule, newInput, this._opts);
|
|
3825
4500
|
if (!this.tree) return reparse();
|
|
3826
4501
|
const delta = replacement.length - (to - from);
|
|
3827
4502
|
const found = findContaining(this.tree, from);
|
|
@@ -3843,25 +4518,25 @@ var FunctionalDocImpl = class _FunctionalDocImpl {
|
|
|
3843
4518
|
if (r.span.end === node2.span.end + delta) {
|
|
3844
4519
|
if (delta === 0) {
|
|
3845
4520
|
const newTree2 = replaceAtPath(rebuild, this.tree, path, r.value);
|
|
3846
|
-
return new
|
|
4521
|
+
return new _ParseDocImpl(this._registry, this._rootRule, this._opts, newTree2, [], newInput);
|
|
3847
4522
|
}
|
|
3848
4523
|
if (this._opts.rebuild) return reparse();
|
|
3849
4524
|
const newTree = graftAndShift(this.tree, path, r.value, delta);
|
|
3850
|
-
return new
|
|
4525
|
+
return new _ParseDocImpl(this._registry, this._rootRule, this._opts, newTree, [], newInput);
|
|
3851
4526
|
}
|
|
3852
4527
|
}
|
|
3853
4528
|
return reparse();
|
|
3854
4529
|
}
|
|
3855
4530
|
};
|
|
3856
|
-
function
|
|
4531
|
+
function parseDoc(registry, rootRule, input, opts = {}) {
|
|
3857
4532
|
const ruleFn = registry[rootRule];
|
|
3858
4533
|
if (!ruleFn) throw new Error(`No rule '${rootRule}' in registry`);
|
|
3859
4534
|
const ctx = { trackLines: false, state: opts.state };
|
|
3860
4535
|
const r = ruleFn(input, 0, ctx);
|
|
3861
4536
|
if (r.ok) {
|
|
3862
|
-
return new
|
|
4537
|
+
return new ParseDocImpl(registry, rootRule, opts, r.value, [], input);
|
|
3863
4538
|
}
|
|
3864
|
-
return new
|
|
4539
|
+
return new ParseDocImpl(registry, rootRule, opts, null, [{ ok: false, expected: r.expected, span: r.span }], input);
|
|
3865
4540
|
}
|
|
3866
4541
|
|
|
3867
4542
|
// src/cst/trivia-index.ts
|