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/plugin/index.cjs
CHANGED
|
@@ -34,8 +34,10 @@ __export(plugin_exports, {
|
|
|
34
34
|
transformMacro: () => transformMacro
|
|
35
35
|
});
|
|
36
36
|
module.exports = __toCommonJS(plugin_exports);
|
|
37
|
+
var fs = __toESM(require("node:fs"), 1);
|
|
37
38
|
var import_unplugin = require("unplugin");
|
|
38
39
|
var import_oxc_parser = require("oxc-parser");
|
|
40
|
+
var import_oxc_resolver = require("oxc-resolver");
|
|
39
41
|
var import_magic_string = __toESM(require("magic-string"), 1);
|
|
40
42
|
|
|
41
43
|
// src/combinators/first-set.ts
|
|
@@ -363,15 +365,15 @@ function extractFirstSet(node2) {
|
|
|
363
365
|
case "Alternative": {
|
|
364
366
|
const exprs = node2.expressions;
|
|
365
367
|
if (!exprs || exprs.length === 0) return { firstSet: empty(), canMatchNewline: false };
|
|
366
|
-
let
|
|
368
|
+
let fs2 = empty();
|
|
367
369
|
let canNL = false;
|
|
368
370
|
for (const expr of exprs) {
|
|
369
371
|
const r = extractFirstSet(expr);
|
|
370
|
-
|
|
372
|
+
fs2 = union(fs2, r.firstSet);
|
|
371
373
|
canNL = canNL || r.canMatchNewline;
|
|
372
374
|
if (!canBeEmpty(expr)) break;
|
|
373
375
|
}
|
|
374
|
-
return { firstSet:
|
|
376
|
+
return { firstSet: fs2, canMatchNewline: canNL };
|
|
375
377
|
}
|
|
376
378
|
case "Char": {
|
|
377
379
|
const kind = node2.kind;
|
|
@@ -398,22 +400,22 @@ function extractFirstSet(node2) {
|
|
|
398
400
|
}
|
|
399
401
|
case "CharacterClass": {
|
|
400
402
|
const expressions = node2.expressions;
|
|
401
|
-
let
|
|
403
|
+
let fs2 = empty();
|
|
402
404
|
let canNL = false;
|
|
403
405
|
for (const expr of expressions) {
|
|
404
406
|
if (expr.type === "ClassRange") {
|
|
405
407
|
const from = expr.from.codePoint;
|
|
406
408
|
const to = expr.to.codePoint;
|
|
407
|
-
|
|
409
|
+
fs2 = union(fs2, fromRange(from, to));
|
|
408
410
|
if (from <= 10 && 10 <= to) canNL = true;
|
|
409
411
|
} else if (expr.type === "Char") {
|
|
410
412
|
const r = extractFirstSet(expr);
|
|
411
|
-
|
|
413
|
+
fs2 = union(fs2, r.firstSet);
|
|
412
414
|
canNL = canNL || r.canMatchNewline;
|
|
413
415
|
}
|
|
414
416
|
}
|
|
415
417
|
if (node2.negative) return { firstSet: any(), canMatchNewline: true };
|
|
416
|
-
return { firstSet:
|
|
418
|
+
return { firstSet: fs2, canMatchNewline: canNL };
|
|
417
419
|
}
|
|
418
420
|
case "Repetition": {
|
|
419
421
|
return extractFirstSet(node2.expression);
|
|
@@ -722,10 +724,10 @@ function codesToFirstSet(codes) {
|
|
|
722
724
|
ranges.push({ lo, hi });
|
|
723
725
|
return { kind: "ranges", ranges };
|
|
724
726
|
}
|
|
725
|
-
function inFirstSet(code,
|
|
726
|
-
if (
|
|
727
|
-
if (
|
|
728
|
-
for (const r of
|
|
727
|
+
function inFirstSet(code, fs2) {
|
|
728
|
+
if (fs2.kind === "any") return true;
|
|
729
|
+
if (fs2.kind === "empty") return false;
|
|
730
|
+
for (const r of fs2.ranges) if (code >= r.lo && code <= r.hi) return true;
|
|
729
731
|
return false;
|
|
730
732
|
}
|
|
731
733
|
function areDisjoint(sets) {
|
|
@@ -1374,8 +1376,29 @@ function expect(combinator, label2) {
|
|
|
1374
1376
|
var BACKSLASH = 92;
|
|
1375
1377
|
var CLASS_ESCAPES = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
1376
1378
|
var META = new Set("()[]{}*+?|^$.".split(""));
|
|
1379
|
+
var SPACE_RANGES = [
|
|
1380
|
+
[9, 13],
|
|
1381
|
+
[32, 32],
|
|
1382
|
+
[160, 160],
|
|
1383
|
+
[5760, 5760],
|
|
1384
|
+
[8192, 8202],
|
|
1385
|
+
[8232, 8232],
|
|
1386
|
+
[8233, 8233],
|
|
1387
|
+
[8239, 8239],
|
|
1388
|
+
[8287, 8287],
|
|
1389
|
+
[12288, 12288],
|
|
1390
|
+
[65279, 65279]
|
|
1391
|
+
];
|
|
1377
1392
|
function shorthandRanges(ch) {
|
|
1378
|
-
|
|
1393
|
+
if (ch === "d") return [[48, 57]];
|
|
1394
|
+
if (ch === "s") return SPACE_RANGES;
|
|
1395
|
+
return [[48, 57], [65, 90], [97, 122], [95, 95]];
|
|
1396
|
+
}
|
|
1397
|
+
function readUnicodeEscape(body, i) {
|
|
1398
|
+
if (body[i] !== "\\" || body[i + 1] !== "u") return null;
|
|
1399
|
+
const hex = body.slice(i + 2, i + 6);
|
|
1400
|
+
if (!/^[0-9a-fA-F]{4}$/.test(hex)) return null;
|
|
1401
|
+
return { cp: Number.parseInt(hex, 16), next: i + 6 };
|
|
1379
1402
|
}
|
|
1380
1403
|
function parseClassRanges(body) {
|
|
1381
1404
|
const ranges = [];
|
|
@@ -1384,11 +1407,16 @@ function parseClassRanges(body) {
|
|
|
1384
1407
|
const ch = body[i];
|
|
1385
1408
|
if (ch === void 0) return null;
|
|
1386
1409
|
if (ch === "\\") {
|
|
1410
|
+
const uni = readUnicodeEscape(body, i);
|
|
1411
|
+
if (uni) {
|
|
1412
|
+
i = uni.next;
|
|
1413
|
+
return { cp: uni.cp };
|
|
1414
|
+
}
|
|
1387
1415
|
const e = body[i + 1];
|
|
1388
1416
|
if (e === void 0) return null;
|
|
1389
1417
|
i += 2;
|
|
1390
1418
|
if (e in CLASS_ESCAPES) return { cp: CLASS_ESCAPES[e] };
|
|
1391
|
-
if (e === "d" || e === "w") return { set: shorthandRanges(e) };
|
|
1419
|
+
if (e === "d" || e === "w" || e === "s") return { set: shorthandRanges(e) };
|
|
1392
1420
|
if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
1393
1421
|
return { cp: e.codePointAt(0) };
|
|
1394
1422
|
}
|
|
@@ -1416,10 +1444,16 @@ function parseClassRanges(body) {
|
|
|
1416
1444
|
function classToRanges(cls) {
|
|
1417
1445
|
if (cls === "\\d") return shorthandRanges("d");
|
|
1418
1446
|
if (cls === "\\w") return shorthandRanges("w");
|
|
1447
|
+
if (cls === "\\s") return shorthandRanges("s");
|
|
1419
1448
|
const body = cls.slice(1, -1);
|
|
1420
1449
|
if (body.startsWith("^")) return null;
|
|
1421
1450
|
return parseClassRanges(body);
|
|
1422
1451
|
}
|
|
1452
|
+
var foldEq = (cVar, cp) => {
|
|
1453
|
+
if (cp >= 65 && cp <= 90) return `(${cVar} === ${cp} || ${cVar} === ${cp + 32})`;
|
|
1454
|
+
if (cp >= 97 && cp <= 122) return `(${cVar} === ${cp} || ${cVar} === ${cp - 32})`;
|
|
1455
|
+
return `${cVar} === ${cp}`;
|
|
1456
|
+
};
|
|
1423
1457
|
function literalCodePoints(frag) {
|
|
1424
1458
|
const out = [];
|
|
1425
1459
|
let i = 0;
|
|
@@ -1466,22 +1500,446 @@ function parseStringShape(source) {
|
|
|
1466
1500
|
if (!inSet(qcp) || !inSet(BACKSLASH)) return null;
|
|
1467
1501
|
return { kind: "string", quote: qcp, excluded, escLineTerm: esc !== "." };
|
|
1468
1502
|
}
|
|
1503
|
+
function parseSeqParts(source) {
|
|
1504
|
+
const parts = [];
|
|
1505
|
+
let lit = [];
|
|
1506
|
+
const flush = () => {
|
|
1507
|
+
if (lit.length) {
|
|
1508
|
+
parts.push({ part: "lit", cps: lit, optional: false });
|
|
1509
|
+
lit = [];
|
|
1510
|
+
}
|
|
1511
|
+
};
|
|
1512
|
+
const runFrom = (ranges, negated, q) => {
|
|
1513
|
+
if (q === "+") {
|
|
1514
|
+
parts.push({ part: "run", ranges, negated, min: 1, unbounded: true });
|
|
1515
|
+
return 1;
|
|
1516
|
+
}
|
|
1517
|
+
if (q === "*") {
|
|
1518
|
+
parts.push({ part: "run", ranges, negated, min: 0, unbounded: true });
|
|
1519
|
+
return 1;
|
|
1520
|
+
}
|
|
1521
|
+
if (q === "?") {
|
|
1522
|
+
parts.push({ part: "run", ranges, negated, min: 0, unbounded: false });
|
|
1523
|
+
return 1;
|
|
1524
|
+
}
|
|
1525
|
+
parts.push({ part: "run", ranges, negated, min: 1, unbounded: false });
|
|
1526
|
+
return 0;
|
|
1527
|
+
};
|
|
1528
|
+
let i = 0;
|
|
1529
|
+
while (i < source.length) {
|
|
1530
|
+
const ch = source[i];
|
|
1531
|
+
if (ch === "[") {
|
|
1532
|
+
let k = i + 1;
|
|
1533
|
+
const neg = source[k] === "^";
|
|
1534
|
+
if (neg) k++;
|
|
1535
|
+
let body = "";
|
|
1536
|
+
while (k < source.length && source[k] !== "]") {
|
|
1537
|
+
if (source[k] === "\\") {
|
|
1538
|
+
body += source[k] + (source[k + 1] ?? "");
|
|
1539
|
+
k += 2;
|
|
1540
|
+
} else {
|
|
1541
|
+
body += source[k];
|
|
1542
|
+
k++;
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
if (source[k] !== "]") return null;
|
|
1546
|
+
const ranges = parseClassRanges(body);
|
|
1547
|
+
if (!ranges) return null;
|
|
1548
|
+
flush();
|
|
1549
|
+
i = k + 1;
|
|
1550
|
+
i += runFrom(ranges, neg, source[i]);
|
|
1551
|
+
continue;
|
|
1552
|
+
}
|
|
1553
|
+
if (ch === "\\") {
|
|
1554
|
+
const e = source[i + 1];
|
|
1555
|
+
if (e === "d" || e === "w" || e === "s") {
|
|
1556
|
+
flush();
|
|
1557
|
+
i += 2;
|
|
1558
|
+
i += runFrom(shorthandRanges(e), false, source[i]);
|
|
1559
|
+
continue;
|
|
1560
|
+
}
|
|
1561
|
+
const uni = readUnicodeEscape(source, i);
|
|
1562
|
+
let cp2;
|
|
1563
|
+
if (uni) {
|
|
1564
|
+
cp2 = uni.cp;
|
|
1565
|
+
i = uni.next;
|
|
1566
|
+
} else if (e === void 0) return null;
|
|
1567
|
+
else if (e in CLASS_ESCAPES) {
|
|
1568
|
+
cp2 = CLASS_ESCAPES[e];
|
|
1569
|
+
i += 2;
|
|
1570
|
+
} else if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
1571
|
+
else {
|
|
1572
|
+
cp2 = e.codePointAt(0);
|
|
1573
|
+
i += 2;
|
|
1574
|
+
}
|
|
1575
|
+
if (source[i] === "?") {
|
|
1576
|
+
flush();
|
|
1577
|
+
parts.push({ part: "lit", cps: [cp2], optional: true });
|
|
1578
|
+
i++;
|
|
1579
|
+
} else lit.push(cp2);
|
|
1580
|
+
continue;
|
|
1581
|
+
}
|
|
1582
|
+
if (ch === "(") {
|
|
1583
|
+
if (source[i + 1] !== "?" || source[i + 2] !== ":") return null;
|
|
1584
|
+
let k = i + 3;
|
|
1585
|
+
let depth = 1;
|
|
1586
|
+
while (k < source.length && depth > 0) {
|
|
1587
|
+
const c2 = source[k];
|
|
1588
|
+
if (c2 === "\\") {
|
|
1589
|
+
k += 2;
|
|
1590
|
+
continue;
|
|
1591
|
+
}
|
|
1592
|
+
if (c2 === "[") {
|
|
1593
|
+
let j = k + 1;
|
|
1594
|
+
if (source[j] === "^") j++;
|
|
1595
|
+
while (j < source.length && source[j] !== "]") {
|
|
1596
|
+
if (source[j] === "\\") j += 2;
|
|
1597
|
+
else j++;
|
|
1598
|
+
}
|
|
1599
|
+
if (source[j] !== "]") return null;
|
|
1600
|
+
k = j + 1;
|
|
1601
|
+
continue;
|
|
1602
|
+
}
|
|
1603
|
+
if (c2 === "(") depth++;
|
|
1604
|
+
else if (c2 === ")") depth--;
|
|
1605
|
+
k++;
|
|
1606
|
+
}
|
|
1607
|
+
if (depth !== 0) return null;
|
|
1608
|
+
const body = source.slice(i + 3, k - 1);
|
|
1609
|
+
const inner = parseScanShape(body);
|
|
1610
|
+
if (!inner || !groupInnerSafe(inner)) return null;
|
|
1611
|
+
const q = source[k];
|
|
1612
|
+
if (q === "{") return null;
|
|
1613
|
+
flush();
|
|
1614
|
+
if (q === "+") {
|
|
1615
|
+
if (shapeCanBeEmpty(inner)) return null;
|
|
1616
|
+
parts.push({ part: "group", inner, min: 1, unbounded: true });
|
|
1617
|
+
i = k + 1;
|
|
1618
|
+
} else if (q === "*") {
|
|
1619
|
+
if (shapeCanBeEmpty(inner)) return null;
|
|
1620
|
+
parts.push({ part: "group", inner, min: 0, unbounded: true });
|
|
1621
|
+
i = k + 1;
|
|
1622
|
+
} else if (q === "?") {
|
|
1623
|
+
parts.push({ part: "group", inner, min: 0, unbounded: false });
|
|
1624
|
+
i = k + 1;
|
|
1625
|
+
} else {
|
|
1626
|
+
parts.push({ part: "group", inner, min: 1, unbounded: false });
|
|
1627
|
+
i = k;
|
|
1628
|
+
}
|
|
1629
|
+
continue;
|
|
1630
|
+
}
|
|
1631
|
+
if (META.has(ch)) return null;
|
|
1632
|
+
const cp = ch.codePointAt(0);
|
|
1633
|
+
i += ch.length;
|
|
1634
|
+
if (source[i] === "?") {
|
|
1635
|
+
flush();
|
|
1636
|
+
parts.push({ part: "lit", cps: [cp], optional: true });
|
|
1637
|
+
i++;
|
|
1638
|
+
} else lit.push(cp);
|
|
1639
|
+
}
|
|
1640
|
+
flush();
|
|
1641
|
+
return parts.length ? parts : null;
|
|
1642
|
+
}
|
|
1643
|
+
function seqIsUnambiguous(parts) {
|
|
1644
|
+
let hasMandatory = false;
|
|
1645
|
+
for (let k = 0; k < parts.length; k++) {
|
|
1646
|
+
const p = parts[k];
|
|
1647
|
+
const mandatory = p.part === "lit" ? !p.optional : p.min === 1;
|
|
1648
|
+
if (mandatory) hasMandatory = true;
|
|
1649
|
+
const skippableSingle = p.part === "lit" && p.optional || p.part !== "lit" && !p.unbounded && p.min === 0;
|
|
1650
|
+
const isUnboundedRepeat = p.part !== "lit" && p.unbounded;
|
|
1651
|
+
if (skippableSingle || isUnboundedRepeat) {
|
|
1652
|
+
const rest = seqFirstAccept(parts.slice(k + 1));
|
|
1653
|
+
if (!firstSetsDisjoint(partFirstAccept(p), rest)) return false;
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
return hasMandatory;
|
|
1657
|
+
}
|
|
1658
|
+
function rangesOverlap(a, b) {
|
|
1659
|
+
return a.some(([lo, hi]) => b.some(([lo2, hi2]) => lo <= hi2 && lo2 <= hi));
|
|
1660
|
+
}
|
|
1661
|
+
function rangesSubset(sub, sup) {
|
|
1662
|
+
return sub.every(([lo, hi]) => sup.some(([lo2, hi2]) => lo >= lo2 && hi <= hi2));
|
|
1663
|
+
}
|
|
1664
|
+
function parseClassOperand(body) {
|
|
1665
|
+
if (body === "\\d" || body === "\\w" || body === "\\s") {
|
|
1666
|
+
return { ranges: shorthandRanges(body[1]), negated: false };
|
|
1667
|
+
}
|
|
1668
|
+
if (body.length >= 2 && body[0] === "[" && body[body.length - 1] === "]") {
|
|
1669
|
+
let inner = body.slice(1, -1);
|
|
1670
|
+
const negated = inner.startsWith("^");
|
|
1671
|
+
if (negated) inner = inner.slice(1);
|
|
1672
|
+
const ranges = parseClassRanges(inner);
|
|
1673
|
+
return ranges ? { ranges, negated } : null;
|
|
1674
|
+
}
|
|
1675
|
+
const cps = literalCodePoints(body);
|
|
1676
|
+
if (cps && cps.length === 1) return { ranges: [[cps[0], cps[0]]], negated: false };
|
|
1677
|
+
return null;
|
|
1678
|
+
}
|
|
1679
|
+
function classSubset(t, u) {
|
|
1680
|
+
if (!t.negated && !u.negated) return rangesSubset(t.ranges, u.ranges);
|
|
1681
|
+
if (!t.negated && u.negated) return !rangesOverlap(t.ranges, u.ranges);
|
|
1682
|
+
if (t.negated && !u.negated) return false;
|
|
1683
|
+
return rangesSubset(u.ranges, t.ranges);
|
|
1684
|
+
}
|
|
1685
|
+
function classDisjoint(t, u) {
|
|
1686
|
+
if (!t.negated && !u.negated) return !rangesOverlap(t.ranges, u.ranges);
|
|
1687
|
+
if (!t.negated && u.negated) return rangesSubset(t.ranges, u.ranges);
|
|
1688
|
+
if (t.negated && !u.negated) return rangesSubset(u.ranges, t.ranges);
|
|
1689
|
+
return false;
|
|
1690
|
+
}
|
|
1691
|
+
function firstSetsDisjoint(a, b) {
|
|
1692
|
+
if (a === "any" || b === "any") return false;
|
|
1693
|
+
return classDisjoint(a, b);
|
|
1694
|
+
}
|
|
1695
|
+
function trailingBacktrackClass(shape) {
|
|
1696
|
+
if (shape.kind === "chars") return { ranges: shape.ranges, negated: false };
|
|
1697
|
+
if (shape.kind === "ident") return { ranges: shape.tail, negated: false };
|
|
1698
|
+
if (shape.kind === "litFold") return null;
|
|
1699
|
+
if (shape.kind === "seq") {
|
|
1700
|
+
const last = shape.parts[shape.parts.length - 1];
|
|
1701
|
+
if (last.part === "lit") return null;
|
|
1702
|
+
if (last.part === "run") {
|
|
1703
|
+
if (last.unbounded || last.min === 0) return { ranges: last.ranges, negated: last.negated };
|
|
1704
|
+
return null;
|
|
1705
|
+
}
|
|
1706
|
+
const innerWiggle = trailingBacktrackClass(last.inner);
|
|
1707
|
+
if (innerWiggle === "unsupported") return "unsupported";
|
|
1708
|
+
const requiredOnce = !last.unbounded && last.min === 1;
|
|
1709
|
+
if (requiredOnce) return innerWiggle;
|
|
1710
|
+
const dropExposed = shapeFirstAccept(last.inner);
|
|
1711
|
+
if (dropExposed === "any") return "unsupported";
|
|
1712
|
+
if (innerWiggle === null) return dropExposed;
|
|
1713
|
+
const unioned = unionCharSets([innerWiggle, dropExposed]);
|
|
1714
|
+
return unioned === "any" ? "unsupported" : unioned;
|
|
1715
|
+
}
|
|
1716
|
+
if (shape.kind === "alt") {
|
|
1717
|
+
if (!shape.disjoint) return "unsupported";
|
|
1718
|
+
const classes = shape.arms.map(trailingBacktrackClass);
|
|
1719
|
+
if (classes.some((c) => c === "unsupported")) return "unsupported";
|
|
1720
|
+
const concrete = classes.filter((c) => c !== null);
|
|
1721
|
+
if (concrete.length === 0) return null;
|
|
1722
|
+
const unioned = unionCharSets(concrete);
|
|
1723
|
+
return unioned === "any" ? "unsupported" : unioned;
|
|
1724
|
+
}
|
|
1725
|
+
return "unsupported";
|
|
1726
|
+
}
|
|
1727
|
+
function lookaheadUnambiguous(inner, operand, negative) {
|
|
1728
|
+
const tail = trailingBacktrackClass(inner);
|
|
1729
|
+
if (tail === "unsupported") return false;
|
|
1730
|
+
if (tail === null) return true;
|
|
1731
|
+
return negative ? classSubset(tail, operand) : classDisjoint(tail, operand);
|
|
1732
|
+
}
|
|
1733
|
+
function stripTrailingLookahead(source) {
|
|
1734
|
+
if (!source.endsWith(")")) return null;
|
|
1735
|
+
for (const negative of [true, false]) {
|
|
1736
|
+
const lead = negative ? "(?!" : "(?=";
|
|
1737
|
+
const idx = source.lastIndexOf(lead);
|
|
1738
|
+
if (idx === -1) continue;
|
|
1739
|
+
const body = source.slice(idx + lead.length, -1);
|
|
1740
|
+
const operand = body.length ? parseClassOperand(body) : null;
|
|
1741
|
+
if (!operand) continue;
|
|
1742
|
+
return { base: source.slice(0, idx), ranges: operand.ranges, classNegated: operand.negated, negative };
|
|
1743
|
+
}
|
|
1744
|
+
return null;
|
|
1745
|
+
}
|
|
1746
|
+
function unwrapOuterGroup(source) {
|
|
1747
|
+
while (source.startsWith("(?:")) {
|
|
1748
|
+
let depth = 1;
|
|
1749
|
+
let i = 3;
|
|
1750
|
+
let ok = true;
|
|
1751
|
+
while (i < source.length && depth > 0) {
|
|
1752
|
+
const ch = source[i];
|
|
1753
|
+
if (ch === "\\") {
|
|
1754
|
+
i += 2;
|
|
1755
|
+
continue;
|
|
1756
|
+
}
|
|
1757
|
+
if (ch === "[") {
|
|
1758
|
+
let j = i + 1;
|
|
1759
|
+
if (source[j] === "^") j++;
|
|
1760
|
+
while (j < source.length && source[j] !== "]") {
|
|
1761
|
+
if (source[j] === "\\") j += 2;
|
|
1762
|
+
else j++;
|
|
1763
|
+
}
|
|
1764
|
+
if (source[j] !== "]") {
|
|
1765
|
+
ok = false;
|
|
1766
|
+
break;
|
|
1767
|
+
}
|
|
1768
|
+
i = j + 1;
|
|
1769
|
+
continue;
|
|
1770
|
+
}
|
|
1771
|
+
if (ch === "(") depth++;
|
|
1772
|
+
else if (ch === ")") depth--;
|
|
1773
|
+
i++;
|
|
1774
|
+
}
|
|
1775
|
+
if (!ok || depth !== 0 || i !== source.length) break;
|
|
1776
|
+
source = source.slice(3, -1);
|
|
1777
|
+
}
|
|
1778
|
+
return source;
|
|
1779
|
+
}
|
|
1780
|
+
function splitTopLevelAlternation(source) {
|
|
1781
|
+
const body = unwrapOuterGroup(source);
|
|
1782
|
+
const parts = [];
|
|
1783
|
+
let depth = 0;
|
|
1784
|
+
let last = 0;
|
|
1785
|
+
let i = 0;
|
|
1786
|
+
while (i < body.length) {
|
|
1787
|
+
const ch = body[i];
|
|
1788
|
+
if (ch === "\\") {
|
|
1789
|
+
i += 2;
|
|
1790
|
+
continue;
|
|
1791
|
+
}
|
|
1792
|
+
if (ch === "[") {
|
|
1793
|
+
let j = i + 1;
|
|
1794
|
+
if (body[j] === "^") j++;
|
|
1795
|
+
while (j < body.length && body[j] !== "]") {
|
|
1796
|
+
if (body[j] === "\\") j += 2;
|
|
1797
|
+
else j++;
|
|
1798
|
+
}
|
|
1799
|
+
if (body[j] !== "]") return null;
|
|
1800
|
+
i = j + 1;
|
|
1801
|
+
continue;
|
|
1802
|
+
}
|
|
1803
|
+
if (ch === "(") {
|
|
1804
|
+
depth++;
|
|
1805
|
+
i++;
|
|
1806
|
+
continue;
|
|
1807
|
+
}
|
|
1808
|
+
if (ch === ")") {
|
|
1809
|
+
depth--;
|
|
1810
|
+
if (depth < 0) return null;
|
|
1811
|
+
i++;
|
|
1812
|
+
continue;
|
|
1813
|
+
}
|
|
1814
|
+
if (ch === "|" && depth === 0) {
|
|
1815
|
+
parts.push(body.slice(last, i));
|
|
1816
|
+
last = i + 1;
|
|
1817
|
+
i++;
|
|
1818
|
+
continue;
|
|
1819
|
+
}
|
|
1820
|
+
i++;
|
|
1821
|
+
}
|
|
1822
|
+
if (depth !== 0) return null;
|
|
1823
|
+
parts.push(body.slice(last));
|
|
1824
|
+
if (parts.length < 2 || parts.some((p) => p.length === 0)) return null;
|
|
1825
|
+
return parts;
|
|
1826
|
+
}
|
|
1827
|
+
function shapeCanBeEmpty(shape) {
|
|
1828
|
+
if (shape.kind === "chars") return !shape.minOne;
|
|
1829
|
+
if (shape.kind === "lookahead") return shapeCanBeEmpty(shape.inner);
|
|
1830
|
+
if (shape.kind === "alt") return shape.arms.some(shapeCanBeEmpty);
|
|
1831
|
+
return false;
|
|
1832
|
+
}
|
|
1833
|
+
function unionCharSets(sets) {
|
|
1834
|
+
if (sets.some((s) => s === "any")) return "any";
|
|
1835
|
+
const concrete = sets;
|
|
1836
|
+
if (concrete.length === 1) return concrete[0];
|
|
1837
|
+
if (concrete.some((s) => s.negated)) return "any";
|
|
1838
|
+
return { ranges: concrete.flatMap((s) => s.ranges), negated: false };
|
|
1839
|
+
}
|
|
1840
|
+
function partFirstAccept(part) {
|
|
1841
|
+
if (part.part === "lit") return { ranges: [[part.cps[0], part.cps[0]]], negated: false };
|
|
1842
|
+
if (part.part === "run") return { ranges: part.ranges, negated: part.negated };
|
|
1843
|
+
return shapeFirstAccept(part.inner);
|
|
1844
|
+
}
|
|
1845
|
+
function seqFirstAccept(parts) {
|
|
1846
|
+
const sets = [];
|
|
1847
|
+
for (const p of parts) {
|
|
1848
|
+
const mandatory = p.part === "lit" ? !p.optional : p.min === 1;
|
|
1849
|
+
sets.push(partFirstAccept(p));
|
|
1850
|
+
if (mandatory) break;
|
|
1851
|
+
}
|
|
1852
|
+
return unionCharSets(sets);
|
|
1853
|
+
}
|
|
1854
|
+
function groupInnerSafe(shape) {
|
|
1855
|
+
if (shape.kind === "chars" || shape.kind === "ident" || shape.kind === "seq" || shape.kind === "litFold") return true;
|
|
1856
|
+
if (shape.kind === "lookahead") return groupInnerSafe(shape.inner);
|
|
1857
|
+
if (shape.kind === "alt") return shape.disjoint;
|
|
1858
|
+
return false;
|
|
1859
|
+
}
|
|
1860
|
+
function shapeFirstAccept(shape) {
|
|
1861
|
+
if (shapeCanBeEmpty(shape)) return "any";
|
|
1862
|
+
switch (shape.kind) {
|
|
1863
|
+
case "chars":
|
|
1864
|
+
return { ranges: shape.ranges, negated: false };
|
|
1865
|
+
case "ident":
|
|
1866
|
+
return { ranges: shape.head, negated: false };
|
|
1867
|
+
case "until":
|
|
1868
|
+
return { ranges: [[shape.open[0], shape.open[0]]], negated: false };
|
|
1869
|
+
case "delimited":
|
|
1870
|
+
return { ranges: [[shape.open[0], shape.open[0]]], negated: false };
|
|
1871
|
+
case "string":
|
|
1872
|
+
return { ranges: [[shape.quote, shape.quote]], negated: false };
|
|
1873
|
+
case "litFold": {
|
|
1874
|
+
const cp = shape.open[0];
|
|
1875
|
+
if (cp >= 65 && cp <= 90) return { ranges: [[cp, cp], [cp + 32, cp + 32]], negated: false };
|
|
1876
|
+
if (cp >= 97 && cp <= 122) return { ranges: [[cp, cp], [cp - 32, cp - 32]], negated: false };
|
|
1877
|
+
return { ranges: [[cp, cp]], negated: false };
|
|
1878
|
+
}
|
|
1879
|
+
case "seq":
|
|
1880
|
+
return seqFirstAccept(shape.parts);
|
|
1881
|
+
case "lookahead":
|
|
1882
|
+
return shapeFirstAccept(shape.inner);
|
|
1883
|
+
// zero-width — doesn't change first-char acceptance
|
|
1884
|
+
case "alt": {
|
|
1885
|
+
if (!shape.disjoint) return "any";
|
|
1886
|
+
const sets = shape.firsts.filter((f) => f !== null);
|
|
1887
|
+
return sets.length === shape.arms.length ? unionCharSets(sets) : "any";
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
}
|
|
1891
|
+
function allPairsDisjoint(sets) {
|
|
1892
|
+
for (let i = 0; i < sets.length; i++) {
|
|
1893
|
+
const a = sets[i];
|
|
1894
|
+
if (a === "any") return false;
|
|
1895
|
+
for (let j = i + 1; j < sets.length; j++) {
|
|
1896
|
+
const b = sets[j];
|
|
1897
|
+
if (b === "any" || !classDisjoint(a, b)) return false;
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
return true;
|
|
1901
|
+
}
|
|
1902
|
+
function parseAlternation(source) {
|
|
1903
|
+
const parts = splitTopLevelAlternation(source);
|
|
1904
|
+
if (!parts) return null;
|
|
1905
|
+
const arms = [];
|
|
1906
|
+
for (const p of parts) {
|
|
1907
|
+
const arm = parseScanShape(p);
|
|
1908
|
+
if (!arm) return null;
|
|
1909
|
+
arms.push(arm);
|
|
1910
|
+
}
|
|
1911
|
+
const firstSets = arms.map(shapeFirstAccept);
|
|
1912
|
+
const disjoint = allPairsDisjoint(firstSets);
|
|
1913
|
+
return { kind: "alt", arms, disjoint, firsts: firstSets.map((f) => f === "any" ? null : f) };
|
|
1914
|
+
}
|
|
1469
1915
|
function parseScanShape(source) {
|
|
1916
|
+
const alt = parseAlternation(source);
|
|
1917
|
+
if (alt) return alt;
|
|
1918
|
+
const la = stripTrailingLookahead(source);
|
|
1919
|
+
if (la) {
|
|
1920
|
+
const inner = parseScanShapeCore(la.base);
|
|
1921
|
+
if (!inner) return null;
|
|
1922
|
+
const operand = { ranges: la.ranges, negated: la.classNegated };
|
|
1923
|
+
if (!lookaheadUnambiguous(inner, operand, la.negative)) return null;
|
|
1924
|
+
return { kind: "lookahead", inner, ranges: la.ranges, classNegated: la.classNegated, negative: la.negative };
|
|
1925
|
+
}
|
|
1926
|
+
return parseScanShapeCore(source);
|
|
1927
|
+
}
|
|
1928
|
+
function parseScanShapeCore(source) {
|
|
1470
1929
|
let m = /^\[((?:\\.|[^\]])+)\]([+*])$/.exec(source);
|
|
1471
|
-
if (m) {
|
|
1472
|
-
if (m[1].startsWith("^")) return null;
|
|
1930
|
+
if (m && !m[1].startsWith("^")) {
|
|
1473
1931
|
const ranges = parseClassRanges(m[1]);
|
|
1474
1932
|
return ranges ? { kind: "chars", ranges, minOne: m[2] === "+" } : null;
|
|
1475
1933
|
}
|
|
1476
|
-
m = /^\\([
|
|
1934
|
+
m = /^\\([dws])([+*])$/.exec(source);
|
|
1477
1935
|
if (m) {
|
|
1478
1936
|
return { kind: "chars", ranges: shorthandRanges(m[1]), minOne: m[2] === "+" };
|
|
1479
1937
|
}
|
|
1480
|
-
m = /^(\[(?:\\.|[^\]])+\]|\\[
|
|
1938
|
+
m = /^(\[(?:\\.|[^\]])+\]|\\[dws])(\[(?:\\.|[^\]])+\]|\\[dws])\*$/.exec(source);
|
|
1481
1939
|
if (m) {
|
|
1482
1940
|
const head = classToRanges(m[1]);
|
|
1483
1941
|
const tail = classToRanges(m[2]);
|
|
1484
|
-
|
|
1942
|
+
if (head && tail) return { kind: "ident", head, tail };
|
|
1485
1943
|
}
|
|
1486
1944
|
const str = parseStringShape(source);
|
|
1487
1945
|
if (str) return str;
|
|
@@ -1490,7 +1948,6 @@ function parseScanShape(source) {
|
|
|
1490
1948
|
const open = literalCodePoints(m[1]);
|
|
1491
1949
|
const stop = parseClassRanges(m[2]);
|
|
1492
1950
|
if (open && stop) return { kind: "until", open, stop };
|
|
1493
|
-
return null;
|
|
1494
1951
|
}
|
|
1495
1952
|
if (!source.includes("\\\\")) {
|
|
1496
1953
|
m = /^(.*?)\((?:\?:)?[\s\S]*\)\*(.*?)$/.exec(source);
|
|
@@ -1500,10 +1957,16 @@ function parseScanShape(source) {
|
|
|
1500
1957
|
if (open && close) return { kind: "delimited", open, close };
|
|
1501
1958
|
}
|
|
1502
1959
|
}
|
|
1960
|
+
const parts = parseSeqParts(source);
|
|
1961
|
+
if (parts && seqIsUnambiguous(parts)) return { kind: "seq", parts };
|
|
1503
1962
|
return null;
|
|
1504
1963
|
}
|
|
1505
1964
|
function scanShapeFromRegex(source, flags) {
|
|
1506
|
-
if (/[
|
|
1965
|
+
if (/[msu]/.test(flags)) return null;
|
|
1966
|
+
if (/i/.test(flags)) {
|
|
1967
|
+
const open = literalCodePoints(source);
|
|
1968
|
+
return open ? { kind: "litFold", open } : null;
|
|
1969
|
+
}
|
|
1507
1970
|
return parseScanShape(source);
|
|
1508
1971
|
}
|
|
1509
1972
|
var classCond = (cVar, ranges) => ranges.map(([lo, hi]) => lo === hi ? `${cVar} === ${lo}` : `(${cVar} >= ${lo} && ${cVar} <= ${hi})`).join(" || ");
|
|
@@ -1518,6 +1981,53 @@ function stringHardStop(shape) {
|
|
|
1518
1981
|
}
|
|
1519
1982
|
var codeAt = (start, firstChar) => firstChar ?? `input.charCodeAt(${start})`;
|
|
1520
1983
|
function emitShapeMatch(shape, start, mint, ind2, firstChar) {
|
|
1984
|
+
if (shape.kind === "lookahead") {
|
|
1985
|
+
const inner = emitShapeMatch(shape.inner, start, mint, ind2, firstChar);
|
|
1986
|
+
const okV = mint("_ok");
|
|
1987
|
+
const endV2 = mint("_end");
|
|
1988
|
+
const rawIn = classCond(`input.charCodeAt(${inner.end})`, shape.ranges);
|
|
1989
|
+
const charInClass = shape.classNegated ? `!(${rawIn})` : `(${rawIn})`;
|
|
1990
|
+
const hasMatchingChar = `${inner.end} < input.length && ${charInClass}`;
|
|
1991
|
+
const guardFails = shape.negative ? hasMatchingChar : `!(${hasMatchingChar})`;
|
|
1992
|
+
return {
|
|
1993
|
+
setup: [
|
|
1994
|
+
...inner.setup,
|
|
1995
|
+
`${ind2}let ${okV} = ${inner.ok}`,
|
|
1996
|
+
`${ind2}let ${endV2} = ${inner.end}`,
|
|
1997
|
+
`${ind2}if (${okV} && (${guardFails})) { ${okV} = false; ${endV2} = ${start} }`
|
|
1998
|
+
],
|
|
1999
|
+
ok: okV,
|
|
2000
|
+
end: endV2
|
|
2001
|
+
};
|
|
2002
|
+
}
|
|
2003
|
+
if (shape.kind === "alt") {
|
|
2004
|
+
const okV = mint("_ok");
|
|
2005
|
+
const endV2 = mint("_end");
|
|
2006
|
+
const lines = [`${ind2}let ${okV} = false`, `${ind2}let ${endV2} = ${start}`];
|
|
2007
|
+
if (shape.disjoint) {
|
|
2008
|
+
const c0 = codeAt(start, firstChar);
|
|
2009
|
+
shape.arms.forEach((arm, k) => {
|
|
2010
|
+
const fs2 = shape.firsts[k];
|
|
2011
|
+
const cond = fs2.negated ? `!(${classCond(c0, fs2.ranges)})` : `(${classCond(c0, fs2.ranges)})`;
|
|
2012
|
+
const m = emitShapeMatch(arm, start, mint, `${ind2} `, firstChar);
|
|
2013
|
+
lines.push(`${ind2}${k === 0 ? "if" : "else if"} (${start} < input.length && ${cond}) {`);
|
|
2014
|
+
lines.push(...m.setup);
|
|
2015
|
+
lines.push(`${ind2} ${okV} = ${m.ok}`);
|
|
2016
|
+
lines.push(`${ind2} ${endV2} = ${m.ok} ? ${m.end} : ${start}`);
|
|
2017
|
+
lines.push(`${ind2}}`);
|
|
2018
|
+
});
|
|
2019
|
+
} else {
|
|
2020
|
+
const lbl = mint("_alt");
|
|
2021
|
+
lines.push(`${ind2}${lbl}: {`);
|
|
2022
|
+
for (const arm of shape.arms) {
|
|
2023
|
+
const m = emitShapeMatch(arm, start, mint, `${ind2} `, firstChar);
|
|
2024
|
+
lines.push(...m.setup);
|
|
2025
|
+
lines.push(`${ind2} if (${m.ok}) { ${okV} = true; ${endV2} = ${m.end}; break ${lbl} }`);
|
|
2026
|
+
}
|
|
2027
|
+
lines.push(`${ind2}}`);
|
|
2028
|
+
}
|
|
2029
|
+
return { setup: lines, ok: okV, end: endV2 };
|
|
2030
|
+
}
|
|
1521
2031
|
if (shape.kind === "chars") {
|
|
1522
2032
|
const cur = mint("_e");
|
|
1523
2033
|
return {
|
|
@@ -1544,6 +2054,82 @@ function emitShapeMatch(shape, start, mint, ind2, firstChar) {
|
|
|
1544
2054
|
end: cur
|
|
1545
2055
|
};
|
|
1546
2056
|
}
|
|
2057
|
+
if (shape.kind === "seq") {
|
|
2058
|
+
const endV2 = mint("_e");
|
|
2059
|
+
const okV = mint("_ok");
|
|
2060
|
+
const runCond = (p, at) => {
|
|
2061
|
+
const c = classCond(`input.charCodeAt(${at})`, p.ranges);
|
|
2062
|
+
return p.negated ? `!(${c})` : `(${c})`;
|
|
2063
|
+
};
|
|
2064
|
+
const lines = [`${ind2}let ${endV2} = ${start}`, `${ind2}let ${okV} = false`, `${ind2}do {`];
|
|
2065
|
+
let first = true;
|
|
2066
|
+
for (const p of shape.parts) {
|
|
2067
|
+
if (p.part === "lit") {
|
|
2068
|
+
const L = p.cps.length;
|
|
2069
|
+
const cond = litCond(endV2, p.cps, first ? firstChar : void 0);
|
|
2070
|
+
if (p.optional) {
|
|
2071
|
+
lines.push(`${ind2} if (${endV2} + ${L} <= input.length && (${cond})) ${endV2} += ${L}`);
|
|
2072
|
+
} else {
|
|
2073
|
+
lines.push(`${ind2} if (!(${endV2} + ${L} <= input.length && (${cond}))) break`);
|
|
2074
|
+
lines.push(`${ind2} ${endV2} += ${L}`);
|
|
2075
|
+
}
|
|
2076
|
+
} else if (p.part === "run" && !p.unbounded) {
|
|
2077
|
+
if (p.min === 1) {
|
|
2078
|
+
lines.push(`${ind2} if (!(${endV2} < input.length && ${runCond(p, endV2)})) break`);
|
|
2079
|
+
lines.push(`${ind2} ${endV2}++`);
|
|
2080
|
+
} else {
|
|
2081
|
+
lines.push(`${ind2} if (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
2082
|
+
}
|
|
2083
|
+
} else if (p.part === "run") {
|
|
2084
|
+
const s = mint("_s");
|
|
2085
|
+
lines.push(`${ind2} const ${s} = ${endV2}`);
|
|
2086
|
+
lines.push(`${ind2} while (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
2087
|
+
if (p.min === 1) lines.push(`${ind2} if (${endV2} === ${s}) break`);
|
|
2088
|
+
} else {
|
|
2089
|
+
const inner = emitShapeMatch(p.inner, endV2, mint, `${ind2} `, first ? firstChar : void 0);
|
|
2090
|
+
if (!p.unbounded) {
|
|
2091
|
+
lines.push(...inner.setup);
|
|
2092
|
+
if (p.min === 1) {
|
|
2093
|
+
lines.push(`${ind2} if (!(${inner.ok})) break`);
|
|
2094
|
+
lines.push(`${ind2} ${endV2} = ${inner.end}`);
|
|
2095
|
+
} else {
|
|
2096
|
+
lines.push(`${ind2} if (${inner.ok}) ${endV2} = ${inner.end}`);
|
|
2097
|
+
}
|
|
2098
|
+
} else {
|
|
2099
|
+
const progV = mint("_prog");
|
|
2100
|
+
lines.push(`${ind2} let ${progV} = false`);
|
|
2101
|
+
lines.push(`${ind2} while (true) {`);
|
|
2102
|
+
lines.push(...inner.setup);
|
|
2103
|
+
lines.push(`${ind2} if (!(${inner.ok})) break`);
|
|
2104
|
+
lines.push(`${ind2} ${endV2} = ${inner.end}`);
|
|
2105
|
+
lines.push(`${ind2} ${progV} = true`);
|
|
2106
|
+
lines.push(`${ind2} }`);
|
|
2107
|
+
if (p.min === 1) lines.push(`${ind2} if (!${progV}) break`);
|
|
2108
|
+
}
|
|
2109
|
+
}
|
|
2110
|
+
first = false;
|
|
2111
|
+
}
|
|
2112
|
+
lines.push(`${ind2} ${okV} = true`);
|
|
2113
|
+
lines.push(`${ind2}} while (false)`);
|
|
2114
|
+
lines.push(`${ind2}if (!${okV}) ${endV2} = ${start}`);
|
|
2115
|
+
return { setup: lines, ok: okV, end: endV2 };
|
|
2116
|
+
}
|
|
2117
|
+
if (shape.kind === "litFold") {
|
|
2118
|
+
const openLen2 = shape.open.length;
|
|
2119
|
+
const endV2 = mint("_end");
|
|
2120
|
+
const checks = shape.open.map((cp, k) => {
|
|
2121
|
+
const cVar = k === 0 && firstChar ? firstChar : `input.charCodeAt(${start} + ${k})`;
|
|
2122
|
+
return foldEq(cVar, cp);
|
|
2123
|
+
});
|
|
2124
|
+
return {
|
|
2125
|
+
setup: [
|
|
2126
|
+
`${ind2}let ${endV2} = ${start}`,
|
|
2127
|
+
`${ind2}if (${start} + ${openLen2} <= input.length && (${checks.join(" && ")})) ${endV2} = ${start} + ${openLen2}`
|
|
2128
|
+
],
|
|
2129
|
+
ok: `${endV2} > ${start}`,
|
|
2130
|
+
end: endV2
|
|
2131
|
+
};
|
|
2132
|
+
}
|
|
1547
2133
|
if (shape.kind === "until") {
|
|
1548
2134
|
const j2 = mint("_j");
|
|
1549
2135
|
const openLen2 = shape.open.length;
|
|
@@ -1939,7 +2525,7 @@ function hoistExpected(ctx, constArrSource) {
|
|
|
1939
2525
|
let name = ctx.expectedMap.get(constArrSource);
|
|
1940
2526
|
if (name === void 0) {
|
|
1941
2527
|
name = `_fx${ctx.expectedDecls.length}`;
|
|
1942
|
-
ctx.expectedDecls.push(`const ${name} =
|
|
2528
|
+
ctx.expectedDecls.push(`const ${name} = ${constArrSource}`);
|
|
1943
2529
|
ctx.expectedMap.set(constArrSource, name);
|
|
1944
2530
|
}
|
|
1945
2531
|
return name;
|
|
@@ -2120,10 +2706,10 @@ function ensureTriviaFn(ctx) {
|
|
|
2120
2706
|
function ensureTriviaCaptureFn(ctx) {
|
|
2121
2707
|
return ensureTriviaFn(ctx);
|
|
2122
2708
|
}
|
|
2123
|
-
function firstSetCond(codeVar,
|
|
2124
|
-
if (
|
|
2125
|
-
if (
|
|
2126
|
-
return
|
|
2709
|
+
function firstSetCond(codeVar, fs2) {
|
|
2710
|
+
if (fs2.kind === "any") return "true";
|
|
2711
|
+
if (fs2.kind === "empty") return "false";
|
|
2712
|
+
return fs2.ranges.map(
|
|
2127
2713
|
(r) => r.lo === r.hi ? `${codeVar} === ${r.lo}` : `(${codeVar} >= ${r.lo} && ${codeVar} <= ${r.hi})`
|
|
2128
2714
|
).join(" || ");
|
|
2129
2715
|
}
|
|
@@ -2135,10 +2721,10 @@ function planDisjointDispatch(parsers) {
|
|
|
2135
2721
|
const cases = [];
|
|
2136
2722
|
let total = 0;
|
|
2137
2723
|
for (const p of parsers) {
|
|
2138
|
-
const
|
|
2139
|
-
if (
|
|
2724
|
+
const fs2 = p._meta.firstSet;
|
|
2725
|
+
if (fs2.kind !== "ranges") return { kind: "if" };
|
|
2140
2726
|
const pts = [];
|
|
2141
|
-
for (const r of
|
|
2727
|
+
for (const r of fs2.ranges) {
|
|
2142
2728
|
if (r.hi - r.lo + 1 > SWITCH_RANGE_LIMIT) return { kind: "if" };
|
|
2143
2729
|
for (let cp = r.lo; cp <= r.hi; cp++) pts.push(cp);
|
|
2144
2730
|
}
|
|
@@ -2261,18 +2847,21 @@ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
2261
2847
|
return true;
|
|
2262
2848
|
}
|
|
2263
2849
|
}
|
|
2264
|
-
function emitFallible(inner, ctx, pos) {
|
|
2850
|
+
function emitFallible(inner, ctx, pos, swallow = false) {
|
|
2265
2851
|
const lbl = v(ctx, "_lbl");
|
|
2266
2852
|
const okV = `${lbl}ok`;
|
|
2267
2853
|
const valV = `${lbl}v`;
|
|
2268
2854
|
const endV = `${lbl}e`;
|
|
2269
2855
|
const savedLabel = ctx.failLabel;
|
|
2270
2856
|
const savedIndent = ctx.indent;
|
|
2857
|
+
const savedRecord = ctx.recordFail;
|
|
2271
2858
|
ctx.failLabel = lbl;
|
|
2272
2859
|
ctx.indent = savedIndent + 1;
|
|
2860
|
+
if (swallow) ctx.recordFail = false;
|
|
2273
2861
|
const r = emit(inner, ctx, pos);
|
|
2274
2862
|
ctx.failLabel = savedLabel;
|
|
2275
2863
|
ctx.indent = savedIndent;
|
|
2864
|
+
ctx.recordFail = savedRecord;
|
|
2276
2865
|
const ind0 = ind(ctx);
|
|
2277
2866
|
const needsRollback = ctx.capturing && mayLeavePartialCapture(inner);
|
|
2278
2867
|
const mL = needsRollback ? v(ctx, "_fcl") : null;
|
|
@@ -2295,6 +2884,7 @@ function emitFallible(inner, ctx, pos) {
|
|
|
2295
2884
|
];
|
|
2296
2885
|
return { stmts, okVar: okV, valVar: valV, endVar: endV };
|
|
2297
2886
|
}
|
|
2887
|
+
var CHARCODE_CHAIN_MAX = 16;
|
|
2298
2888
|
function emitLit(def, ctx, pos) {
|
|
2299
2889
|
const { value, caseInsensitive } = def;
|
|
2300
2890
|
const len = value.length;
|
|
@@ -2317,7 +2907,7 @@ function emitLit(def, ctx, pos) {
|
|
|
2317
2907
|
...emitIfFail(ctx, `${pos} >= input.length || input.charCodeAt(${pos}) !== ${code}`, failBody(ctx, expectedStr, pos)),
|
|
2318
2908
|
`${ind(ctx)}const ${vv} = ${JSON.stringify(value)}`
|
|
2319
2909
|
);
|
|
2320
|
-
} else if (len <=
|
|
2910
|
+
} else if (len <= CHARCODE_CHAIN_MAX) {
|
|
2321
2911
|
const checks = Array.from(
|
|
2322
2912
|
{ length: len },
|
|
2323
2913
|
(_, i) => `input.charCodeAt(${pos}${i > 0 ? ` + ${i}` : ""}) !== ${value.codePointAt(i)}`
|
|
@@ -2339,7 +2929,55 @@ function emitLit(def, ctx, pos) {
|
|
|
2339
2929
|
function escapeKeywordRe(s) {
|
|
2340
2930
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2341
2931
|
}
|
|
2932
|
+
function emitKeywordsFast(def, ctx, pos) {
|
|
2933
|
+
if (def.words.length === 0 || def.words.some((w) => w.length === 0)) return null;
|
|
2934
|
+
if (def.words.some((w) => Array.from(w).length !== w.length)) return null;
|
|
2935
|
+
if (def.caseInsensitive && def.boundary) return null;
|
|
2936
|
+
let boundary = null;
|
|
2937
|
+
if (def.boundary) {
|
|
2938
|
+
let body = def.boundary;
|
|
2939
|
+
const negated = body.startsWith("^");
|
|
2940
|
+
if (negated) body = body.slice(1);
|
|
2941
|
+
const ranges = parseClassRanges(body);
|
|
2942
|
+
if (!ranges) return null;
|
|
2943
|
+
boundary = { ranges, negated };
|
|
2944
|
+
}
|
|
2945
|
+
const mint = (prefix = "_v") => v(ctx, prefix);
|
|
2946
|
+
const lbl = v(ctx, "_kwLbl");
|
|
2947
|
+
const valV = v(ctx, "_kwv");
|
|
2948
|
+
const endV = v(ctx, "_kwe");
|
|
2949
|
+
const bodyInd = ind(ctx) + " ";
|
|
2950
|
+
const tries = [];
|
|
2951
|
+
for (const w of def.words) {
|
|
2952
|
+
const cps = Array.from(w, (ch) => ch.codePointAt(0));
|
|
2953
|
+
let shape = def.caseInsensitive ? { kind: "litFold", open: cps } : { kind: "seq", parts: [{ part: "lit", cps, optional: false }] };
|
|
2954
|
+
if (boundary) {
|
|
2955
|
+
shape = { kind: "lookahead", inner: shape, ranges: boundary.ranges, classNegated: boundary.negated, negative: true };
|
|
2956
|
+
}
|
|
2957
|
+
const m = emitShapeMatch(shape, pos, mint, bodyInd);
|
|
2958
|
+
tries.push(
|
|
2959
|
+
...m.setup,
|
|
2960
|
+
// Slice from input rather than reusing the literal word: `caseInsensitive`
|
|
2961
|
+
// must return the text as it actually appeared (e.g. "ABC" for keyword
|
|
2962
|
+
// "abc"), matching what the original `RegExp.exec()[0]` returned.
|
|
2963
|
+
`${bodyInd}if (${m.ok}) { ${valV} = input.slice(${pos}, ${m.end}); ${endV} = ${m.end}; break ${lbl} }`
|
|
2964
|
+
);
|
|
2965
|
+
}
|
|
2966
|
+
const stmts = [
|
|
2967
|
+
`${ind(ctx)}let ${valV} = '', ${endV} = ${pos}`,
|
|
2968
|
+
`${ind(ctx)}${lbl}: {`,
|
|
2969
|
+
...tries,
|
|
2970
|
+
`${ind(ctx)}}`,
|
|
2971
|
+
// Every word has length >= 1 (checked above), so a real match always
|
|
2972
|
+
// advances past `pos` — `endV === pos` only happens when no candidate matched.
|
|
2973
|
+
...emitIfFail(ctx, `${endV} === ${pos}`, failBody(ctx, '"keyword"', pos))
|
|
2974
|
+
];
|
|
2975
|
+
stmts.push(...emitLeafCapture(ctx, valV, pos, endV));
|
|
2976
|
+
return { stmts, valueVar: valV, endVar: endV };
|
|
2977
|
+
}
|
|
2342
2978
|
function emitKeywords(def, ctx, pos) {
|
|
2979
|
+
const fast = emitKeywordsFast(def, ctx, pos);
|
|
2980
|
+
if (fast) return fast;
|
|
2343
2981
|
const alt = def.words.map(escapeKeywordRe).join("|");
|
|
2344
2982
|
const boundary = def.boundary ? `(?![${def.boundary}])` : "";
|
|
2345
2983
|
const flags = def.caseInsensitive ? "iuy" : "uy";
|
|
@@ -2470,6 +3108,31 @@ function failsAtStart(p) {
|
|
|
2470
3108
|
return false;
|
|
2471
3109
|
}
|
|
2472
3110
|
}
|
|
3111
|
+
function armStaticExpected(ctx, p) {
|
|
3112
|
+
return hoistExpected(ctx, staticExpectedArr([p]));
|
|
3113
|
+
}
|
|
3114
|
+
function canMatchEmptyAtStart(p) {
|
|
3115
|
+
const d = p._def;
|
|
3116
|
+
switch (d.tag) {
|
|
3117
|
+
case "regex":
|
|
3118
|
+
return /(?:[*?]|\{0,|\{\d*,)/.test(d.source);
|
|
3119
|
+
case "optional":
|
|
3120
|
+
return true;
|
|
3121
|
+
case "many":
|
|
3122
|
+
return true;
|
|
3123
|
+
case "transform":
|
|
3124
|
+
case "label":
|
|
3125
|
+
return canMatchEmptyAtStart(d.parser);
|
|
3126
|
+
case "literal":
|
|
3127
|
+
return d.value.length === 0;
|
|
3128
|
+
default:
|
|
3129
|
+
return false;
|
|
3130
|
+
}
|
|
3131
|
+
}
|
|
3132
|
+
function needsFirstSetGuard(p) {
|
|
3133
|
+
const fs2 = p._meta.firstSet;
|
|
3134
|
+
return fs2.kind !== "any" && !canMatchEmptyAtStart(p);
|
|
3135
|
+
}
|
|
2473
3136
|
function emitDisjointArm(p, ctx, pos, valV, endV) {
|
|
2474
3137
|
if (failsAtStart(p)) {
|
|
2475
3138
|
const r = emit(p, ctx, pos);
|
|
@@ -2611,16 +3274,21 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
2611
3274
|
const resValV = v(ctx, "_crv");
|
|
2612
3275
|
const resEndV = v(ctx, "_cre");
|
|
2613
3276
|
const resOkV = v(ctx, "_crok");
|
|
3277
|
+
const codeV = v(ctx, "_chcode");
|
|
2614
3278
|
const slots = def.parsers.map(() => v(ctx, "_cfx"));
|
|
2615
3279
|
const ind0 = ind(ctx);
|
|
2616
3280
|
const stmts = [
|
|
2617
3281
|
`${ind0}let ${resValV}, ${resEndV} = ${pos}, ${resOkV} = false`,
|
|
2618
|
-
`${ind0}let ${slots.join(", ")}
|
|
3282
|
+
`${ind0}let ${slots.join(", ")}`,
|
|
3283
|
+
`${ind0}const ${codeV} = ${pos} < input.length ? (input.codePointAt(${pos}) ?? -1) : -1`
|
|
2619
3284
|
];
|
|
2620
3285
|
for (let i = 0; i < def.parsers.length; i++) {
|
|
2621
3286
|
const p = def.parsers[i];
|
|
2622
3287
|
const gate = def.gates[i];
|
|
2623
3288
|
const autoNot = def.autoNot[i];
|
|
3289
|
+
const atStart = failsAtStart(p);
|
|
3290
|
+
const staticFx = armStaticExpected(ctx, p);
|
|
3291
|
+
const fsGuard = needsFirstSetGuard(p) ? firstSetCond(codeV, p._meta.firstSet) : null;
|
|
2624
3292
|
let gateCond = null;
|
|
2625
3293
|
if (gate) {
|
|
2626
3294
|
const gateIdx = ctx.mapFns.length;
|
|
@@ -2635,39 +3303,41 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
2635
3303
|
const markTl = armNeedsRollback ? v(ctx, "_cmtl") : null;
|
|
2636
3304
|
const markLog = armNeedsRollback ? v(ctx, "_cmlg") : null;
|
|
2637
3305
|
const rollback = markLeaves ? captureRestoreBody(markLeaves, markRaw, markTl, markLog) : "";
|
|
3306
|
+
const failSlot = atStart ? staticFx : "_ctx._fx";
|
|
2638
3307
|
stmts.push(`${ind0}if (${skipCond}) {`);
|
|
2639
|
-
ctx
|
|
2640
|
-
|
|
3308
|
+
if (fsGuard) stmts.push(`${ind(ctx)}if (${fsGuard}) {`);
|
|
3309
|
+
ctx.indent += fsGuard ? 2 : 1;
|
|
2641
3310
|
if (markLeaves) {
|
|
2642
3311
|
stmts.push(
|
|
2643
|
-
`${
|
|
2644
|
-
`${
|
|
2645
|
-
`${
|
|
2646
|
-
`${
|
|
3312
|
+
`${ind(ctx)}const ${markLeaves} = _ctx._cstLeaves?.length ?? 0`,
|
|
3313
|
+
`${ind(ctx)}const ${markRaw} = _ctx._cstRawChildren?.length ?? 0`,
|
|
3314
|
+
`${ind(ctx)}const ${markTl} = _ctx._cstTriviaLog?.length ?? 0`,
|
|
3315
|
+
`${ind(ctx)}const ${markLog} = _ctx._triviaLog?.length ?? 0`
|
|
2647
3316
|
);
|
|
2648
3317
|
}
|
|
2649
|
-
const { stmts: armStmts, okVar, valVar, endVar } = emitFallible(p, ctx, pos);
|
|
3318
|
+
const { stmts: armStmts, okVar, valVar, endVar } = emitFallible(p, ctx, pos, atStart);
|
|
2650
3319
|
stmts.push(...armStmts);
|
|
2651
|
-
ctx.indent--;
|
|
2652
3320
|
if (autoNot && autoNot.length > 0) {
|
|
2653
3321
|
const anCode = v(ctx, "_anc");
|
|
2654
3322
|
const rejectCond = autoNot.map(
|
|
2655
3323
|
(check) => check.kind === "firstSet" ? firstSetCond(anCode, check.set) : `input.startsWith(${JSON.stringify(check.value)}, ${endVar})`
|
|
2656
3324
|
).join(" || ");
|
|
2657
|
-
stmts.push(`${
|
|
2658
|
-
stmts.push(`${
|
|
2659
|
-
stmts.push(`${
|
|
2660
|
-
stmts.push(`${
|
|
2661
|
-
stmts.push(`${
|
|
2662
|
-
stmts.push(`${
|
|
2663
|
-
stmts.push(`${
|
|
2664
|
-
stmts.push(`${
|
|
2665
|
-
stmts.push(`${
|
|
2666
|
-
if (rollback) stmts.push(`${
|
|
3325
|
+
stmts.push(`${ind(ctx)}if (${okVar}) {`);
|
|
3326
|
+
stmts.push(`${ind(ctx)} const ${anCode} = ${endVar} < input.length ? input.charCodeAt(${endVar}) : -1`);
|
|
3327
|
+
stmts.push(`${ind(ctx)} if (!(${rejectCond})) {`);
|
|
3328
|
+
stmts.push(`${ind(ctx)} ${resValV} = ${valVar}`);
|
|
3329
|
+
stmts.push(`${ind(ctx)} ${resEndV} = ${endVar}`);
|
|
3330
|
+
stmts.push(`${ind(ctx)} ${resOkV} = true`);
|
|
3331
|
+
stmts.push(`${ind(ctx)} }`);
|
|
3332
|
+
stmts.push(`${ind(ctx)}}`);
|
|
3333
|
+
stmts.push(`${ind(ctx)}else { ${slots[i]} = ${failSlot} }`);
|
|
3334
|
+
if (rollback) stmts.push(`${ind(ctx)}if (!${resOkV}) { ${rollback} }`);
|
|
2667
3335
|
} else {
|
|
2668
|
-
stmts.push(`${
|
|
2669
|
-
stmts.push(`${
|
|
3336
|
+
stmts.push(`${ind(ctx)}if (${okVar}) { ${resValV} = ${valVar}; ${resEndV} = ${endVar}; ${resOkV} = true }`);
|
|
3337
|
+
stmts.push(`${ind(ctx)}else { ${slots[i]} = ${failSlot}${rollback ? `; ${rollback}` : ""} }`);
|
|
2670
3338
|
}
|
|
3339
|
+
ctx.indent -= fsGuard ? 2 : 1;
|
|
3340
|
+
if (fsGuard) stmts.push(`${ind(ctx)}} else { ${slots[i]} = ${staticFx} }`);
|
|
2671
3341
|
stmts.push(`${ind0}}`);
|
|
2672
3342
|
}
|
|
2673
3343
|
const concatExpr = `[${slots.map((s) => `...(${s} || [])`).join(", ")}]`;
|
|
@@ -2700,7 +3370,7 @@ function emitTransformChain(p, baseValue, endV, startPos, ctx) {
|
|
|
2700
3370
|
function emitLiteralCondition(litVal, pos) {
|
|
2701
3371
|
const len = litVal.length;
|
|
2702
3372
|
if (len === 0) return "true";
|
|
2703
|
-
if (len >
|
|
3373
|
+
if (len > CHARCODE_CHAIN_MAX) return `input.startsWith(${JSON.stringify(litVal)}, ${pos})`;
|
|
2704
3374
|
const checks = [`${pos} + ${len} <= input.length`];
|
|
2705
3375
|
for (let i = 0; i < len; i++) {
|
|
2706
3376
|
const code = litVal.codePointAt(i);
|
|
@@ -2749,7 +3419,7 @@ function emitMany(def, ctx, pos) {
|
|
|
2749
3419
|
itemPos = npV;
|
|
2750
3420
|
}
|
|
2751
3421
|
}
|
|
2752
|
-
const { stmts: iterStmts, okVar: iterOk, valVar: iterVal, endVar: iterEnd } = emitFallible(def.parser, ctx, itemPos);
|
|
3422
|
+
const { stmts: iterStmts, okVar: iterOk, valVar: iterVal, endVar: iterEnd } = emitFallible(def.parser, ctx, itemPos, true);
|
|
2753
3423
|
stmts.push(
|
|
2754
3424
|
...iterStmts,
|
|
2755
3425
|
`${ind(ctx)}if (!${iterOk} || ${iterEnd} <= ${itemPos}) { ${rollback}break }`,
|
|
@@ -2763,7 +3433,7 @@ function emitMany(def, ctx, pos) {
|
|
|
2763
3433
|
function emitOptional(def, ctx, pos) {
|
|
2764
3434
|
const valV = v(ctx, "_opt");
|
|
2765
3435
|
const endV = v(ctx, "_opte");
|
|
2766
|
-
const { stmts: lblStmts, okVar, valVar, endVar } = emitFallible(def.parser, ctx, pos);
|
|
3436
|
+
const { stmts: lblStmts, okVar, valVar, endVar } = emitFallible(def.parser, ctx, pos, true);
|
|
2767
3437
|
const ind0 = ind(ctx);
|
|
2768
3438
|
const stmts = [
|
|
2769
3439
|
...lblStmts,
|
|
@@ -2775,7 +3445,7 @@ function emitOptional(def, ctx, pos) {
|
|
|
2775
3445
|
function emitSepBy(_p, def, ctx, pos) {
|
|
2776
3446
|
const arrV = v(ctx, "_arr");
|
|
2777
3447
|
const curV = v(ctx, "_cur");
|
|
2778
|
-
const { stmts: firstStmts, okVar: firstOk, valVar: firstVal, endVar: firstEnd } = emitFallible(def.parser, ctx, pos);
|
|
3448
|
+
const { stmts: firstStmts, okVar: firstOk, valVar: firstVal, endVar: firstEnd } = emitFallible(def.parser, ctx, pos, true);
|
|
2779
3449
|
const stmts = [
|
|
2780
3450
|
`${ind(ctx)}const ${arrV} = []`,
|
|
2781
3451
|
`${ind(ctx)}let ${curV} = ${pos}`,
|
|
@@ -2807,11 +3477,11 @@ function emitSepBy(_p, def, ctx, pos) {
|
|
|
2807
3477
|
);
|
|
2808
3478
|
sepAtPos = spV;
|
|
2809
3479
|
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}; `;
|
|
2810
|
-
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos);
|
|
3480
|
+
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos, true);
|
|
2811
3481
|
stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) { ${rollbackToSep}break }`);
|
|
2812
3482
|
const npV = v(ctx, "_np");
|
|
2813
3483
|
stmts.push(`${ind(ctx)}const ${npV} = ${capFn}(input, ${sepEnd}, _ctx, 1)`);
|
|
2814
|
-
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, npV);
|
|
3484
|
+
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, npV, true);
|
|
2815
3485
|
stmts.push(
|
|
2816
3486
|
...nextStmts,
|
|
2817
3487
|
// item failed → unwind the separator too, back to the end of the last item
|
|
@@ -2824,11 +3494,11 @@ function emitSepBy(_p, def, ctx, pos) {
|
|
|
2824
3494
|
const spV = v(ctx, "_sp");
|
|
2825
3495
|
stmts.push(`${ind(ctx)}const ${spV} = ${trivFn}(input, ${curV}, _ctx)`);
|
|
2826
3496
|
sepAtPos = spV;
|
|
2827
|
-
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos);
|
|
3497
|
+
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos, true);
|
|
2828
3498
|
stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) break`);
|
|
2829
3499
|
const npV = v(ctx, "_np");
|
|
2830
3500
|
stmts.push(`${ind(ctx)}const ${npV} = ${trivFn}(input, ${sepEnd}, _ctx)`);
|
|
2831
|
-
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, npV);
|
|
3501
|
+
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, npV, true);
|
|
2832
3502
|
stmts.push(
|
|
2833
3503
|
...nextStmts,
|
|
2834
3504
|
`${ind(ctx)}if (!${nextOk}) break`,
|
|
@@ -2845,10 +3515,10 @@ function emitSepBy(_p, def, ctx, pos) {
|
|
|
2845
3515
|
`${ind(ctx)}const ${markRw} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`
|
|
2846
3516
|
);
|
|
2847
3517
|
}
|
|
2848
|
-
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos);
|
|
3518
|
+
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos, true);
|
|
2849
3519
|
stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) break`);
|
|
2850
3520
|
const nextRb = markLv ? `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${markLv}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markRw}; ` : "";
|
|
2851
|
-
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, sepEnd);
|
|
3521
|
+
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, sepEnd, true);
|
|
2852
3522
|
stmts.push(
|
|
2853
3523
|
...nextStmts,
|
|
2854
3524
|
`${ind(ctx)}if (!${nextOk}) { ${nextRb}break }`,
|
|
@@ -2906,7 +3576,7 @@ function emitScanTo(def, ctx, pos) {
|
|
|
2906
3576
|
return { stmts, valueVar: valV, endVar: curV };
|
|
2907
3577
|
}
|
|
2908
3578
|
function emitNot(def, ctx, pos) {
|
|
2909
|
-
const { stmts, okVar } = emitFallible(def.parser, ctx, pos);
|
|
3579
|
+
const { stmts, okVar } = emitFallible(def.parser, ctx, pos, true);
|
|
2910
3580
|
const label2 = JSON.stringify(`not(${def.parser._tag})`);
|
|
2911
3581
|
return {
|
|
2912
3582
|
stmts: [
|
|
@@ -2997,11 +3667,14 @@ function emitLazy(p, def, ctx, pos) {
|
|
|
2997
3667
|
}
|
|
2998
3668
|
const savedIndent = ctx.indent;
|
|
2999
3669
|
const savedFailLabel = ctx.failLabel;
|
|
3670
|
+
const savedRecord = ctx.recordFail;
|
|
3000
3671
|
ctx.indent = 1;
|
|
3001
3672
|
ctx.failLabel = "_pfail";
|
|
3673
|
+
ctx.recordFail = true;
|
|
3002
3674
|
const r = emit(resolved, ctx, "_pos");
|
|
3003
3675
|
ctx.indent = savedIndent;
|
|
3004
3676
|
ctx.failLabel = savedFailLabel;
|
|
3677
|
+
ctx.recordFail = savedRecord;
|
|
3005
3678
|
pushNamedFnDecl(ctx, fnName2, r.stmts, r.valueVar, r.endVar);
|
|
3006
3679
|
}
|
|
3007
3680
|
const fnName = ctx.namedParsers.get(p);
|
|
@@ -3181,11 +3854,14 @@ function emit(p, ctx, pos) {
|
|
|
3181
3854
|
ctx.namedParsers.set(innerParser, fnName);
|
|
3182
3855
|
const savedIndent = ctx.indent;
|
|
3183
3856
|
const savedFailLabel = ctx.failLabel;
|
|
3857
|
+
const savedRecord = ctx.recordFail;
|
|
3184
3858
|
ctx.indent = 1;
|
|
3185
3859
|
ctx.failLabel = "_pfail";
|
|
3860
|
+
ctx.recordFail = true;
|
|
3186
3861
|
const innerR = emit(innerParser, ctx, "_pos");
|
|
3187
3862
|
ctx.indent = savedIndent;
|
|
3188
3863
|
ctx.failLabel = savedFailLabel;
|
|
3864
|
+
ctx.recordFail = savedRecord;
|
|
3189
3865
|
pushNamedFnDecl(ctx, fnName, innerR.stmts, innerR.valueVar, innerR.endVar);
|
|
3190
3866
|
}
|
|
3191
3867
|
const fn = ctx.namedParsers.get(innerParser);
|
|
@@ -3333,6 +4009,7 @@ function compile(combinator, mapFnSources) {
|
|
|
3333
4009
|
regexMap: /* @__PURE__ */ new Map(),
|
|
3334
4010
|
expectedDecls: [],
|
|
3335
4011
|
expectedMap: /* @__PURE__ */ new Map(),
|
|
4012
|
+
recordFail: true,
|
|
3336
4013
|
mapFns: [],
|
|
3337
4014
|
mapFnSrcs: [],
|
|
3338
4015
|
buildFns: [],
|
|
@@ -3415,6 +4092,7 @@ function compileRuleMap(ruleMap) {
|
|
|
3415
4092
|
regexMap: /* @__PURE__ */ new Map(),
|
|
3416
4093
|
expectedDecls: [],
|
|
3417
4094
|
expectedMap: /* @__PURE__ */ new Map(),
|
|
4095
|
+
recordFail: true,
|
|
3418
4096
|
mapFns: [],
|
|
3419
4097
|
mapFnSrcs: [],
|
|
3420
4098
|
buildFns: [],
|
|
@@ -3589,11 +4267,11 @@ function balanced(open, close, options = {}) {
|
|
|
3589
4267
|
return combi;
|
|
3590
4268
|
}
|
|
3591
4269
|
function firstSetClassChars(c) {
|
|
3592
|
-
const
|
|
3593
|
-
if (
|
|
3594
|
-
if (
|
|
4270
|
+
const fs2 = c._meta.firstSet;
|
|
4271
|
+
if (fs2.kind === "empty") return [];
|
|
4272
|
+
if (fs2.kind !== "ranges") return null;
|
|
3595
4273
|
const out = [];
|
|
3596
|
-
for (const { lo, hi } of
|
|
4274
|
+
for (const { lo, hi } of fs2.ranges) {
|
|
3597
4275
|
if (hi - lo > 8) return null;
|
|
3598
4276
|
for (let cp = lo; cp <= hi; cp++) out.push(String.fromCodePoint(cp));
|
|
3599
4277
|
}
|
|
@@ -3897,7 +4575,117 @@ function evaluateCombinatorArray(node2, scope, code) {
|
|
|
3897
4575
|
if (!val.every(isCombinator)) return null;
|
|
3898
4576
|
return val;
|
|
3899
4577
|
}
|
|
3900
|
-
function
|
|
4578
|
+
function asFragmentFactory(expr) {
|
|
4579
|
+
if (expr.type !== "ArrowFunctionExpression" && expr.type !== "FunctionExpression" && expr.type !== "FunctionDeclaration") return null;
|
|
4580
|
+
const fn = expr;
|
|
4581
|
+
return factoryBodyAndReturn(fn) ? fn : null;
|
|
4582
|
+
}
|
|
4583
|
+
var unwrapParen = (e) => e && e.type === "ParenthesizedExpression" ? e.expression : e;
|
|
4584
|
+
function factoryBodyAndReturn(fn) {
|
|
4585
|
+
const body = fn.body;
|
|
4586
|
+
if (!body) return null;
|
|
4587
|
+
const b = unwrapParen(body);
|
|
4588
|
+
if (b.type === "ObjectExpression") return { statements: [], retObj: b };
|
|
4589
|
+
if (b.type === "BlockStatement") {
|
|
4590
|
+
const statements = [];
|
|
4591
|
+
for (const stmt of b.body) {
|
|
4592
|
+
if (stmt.type === "ReturnStatement") {
|
|
4593
|
+
const a = unwrapParen(stmt.argument);
|
|
4594
|
+
if (!a || a.type !== "ObjectExpression") return null;
|
|
4595
|
+
return { statements, retObj: a };
|
|
4596
|
+
}
|
|
4597
|
+
if (stmt.type === "VariableDeclaration") statements.push(stmt);
|
|
4598
|
+
else return null;
|
|
4599
|
+
}
|
|
4600
|
+
}
|
|
4601
|
+
return null;
|
|
4602
|
+
}
|
|
4603
|
+
function spreadFactoryCall(spread, resolve) {
|
|
4604
|
+
const call = spread.argument;
|
|
4605
|
+
if (!call || call.type !== "CallExpression") return null;
|
|
4606
|
+
if (!call.callee || call.callee.type !== "Identifier" || !call.callee.name) return null;
|
|
4607
|
+
const resolved = resolve(call.callee.name);
|
|
4608
|
+
return resolved ? { fn: resolved.fn, args: call.arguments ?? [], code: resolved.code } : null;
|
|
4609
|
+
}
|
|
4610
|
+
function factoryCallScope(fn, args, outer) {
|
|
4611
|
+
const s = new Map(outer);
|
|
4612
|
+
const params = fn.params ?? [];
|
|
4613
|
+
for (let i = 0; i < params.length; i++) {
|
|
4614
|
+
const pn = params[i];
|
|
4615
|
+
if (!pn || pn.type !== "Identifier" || !pn.name) continue;
|
|
4616
|
+
const arg = args[i];
|
|
4617
|
+
if (arg && arg.type === "Identifier" && arg.name && outer.has(arg.name)) {
|
|
4618
|
+
s.set(pn.name, outer.get(arg.name));
|
|
4619
|
+
}
|
|
4620
|
+
}
|
|
4621
|
+
return s;
|
|
4622
|
+
}
|
|
4623
|
+
function propKey(prop) {
|
|
4624
|
+
if (prop.type !== "Property" || prop.computed || !prop.key) return null;
|
|
4625
|
+
if (prop.key.type === "Identifier") return prop.key.name ?? null;
|
|
4626
|
+
if (prop.key.type === "Literal") return String(prop.key.value);
|
|
4627
|
+
return null;
|
|
4628
|
+
}
|
|
4629
|
+
function collectRuleKeys(retObj, resolve, seen) {
|
|
4630
|
+
const out = [];
|
|
4631
|
+
for (const prop of retObj.properties) {
|
|
4632
|
+
if (prop.type === "SpreadElement") {
|
|
4633
|
+
const sf = spreadFactoryCall(prop, resolve);
|
|
4634
|
+
if (!sf || seen.has(sf.fn)) return null;
|
|
4635
|
+
const br = factoryBodyAndReturn(sf.fn);
|
|
4636
|
+
if (!br) return null;
|
|
4637
|
+
const nested = collectRuleKeys(br.retObj, resolve, new Set(seen).add(sf.fn));
|
|
4638
|
+
if (!nested) return null;
|
|
4639
|
+
out.push(...nested);
|
|
4640
|
+
continue;
|
|
4641
|
+
}
|
|
4642
|
+
const key = propKey(prop);
|
|
4643
|
+
if (!key) return null;
|
|
4644
|
+
out.push(key);
|
|
4645
|
+
}
|
|
4646
|
+
return out;
|
|
4647
|
+
}
|
|
4648
|
+
function flattenRuleEntries(retObj, scope, code, resolve, seen) {
|
|
4649
|
+
const out = [];
|
|
4650
|
+
for (const prop of retObj.properties) {
|
|
4651
|
+
if (prop.type === "SpreadElement") {
|
|
4652
|
+
const sf = spreadFactoryCall(prop, resolve);
|
|
4653
|
+
if (!sf || seen.has(sf.fn)) return null;
|
|
4654
|
+
const br = factoryBodyAndReturn(sf.fn);
|
|
4655
|
+
if (!br) return null;
|
|
4656
|
+
const fragScope = factoryCallScope(sf.fn, sf.args, scope);
|
|
4657
|
+
if (!evalBodyStatements(br.statements, fragScope, sf.code)) return null;
|
|
4658
|
+
const nested = flattenRuleEntries(br.retObj, fragScope, sf.code, resolve, new Set(seen).add(sf.fn));
|
|
4659
|
+
if (!nested) return null;
|
|
4660
|
+
out.push(...nested);
|
|
4661
|
+
continue;
|
|
4662
|
+
}
|
|
4663
|
+
const key = propKey(prop);
|
|
4664
|
+
if (!key) return null;
|
|
4665
|
+
out.push({ key, value: prop.value, scope, code });
|
|
4666
|
+
}
|
|
4667
|
+
return out;
|
|
4668
|
+
}
|
|
4669
|
+
function evalBodyStatements(statements, scope, code) {
|
|
4670
|
+
const bodyMfs = [];
|
|
4671
|
+
for (const stmt of statements) {
|
|
4672
|
+
for (const d of stmt.declarations) {
|
|
4673
|
+
const decl = d;
|
|
4674
|
+
if (!decl.init) return false;
|
|
4675
|
+
const id = decl.id;
|
|
4676
|
+
if (id.type !== "Identifier" && id.type !== "BindingIdentifier") return false;
|
|
4677
|
+
const name = id.name;
|
|
4678
|
+
const before = bodyMfs.length;
|
|
4679
|
+
const val = anyValue(decl.init, scope, code, bodyMfs);
|
|
4680
|
+
if (val === null) return false;
|
|
4681
|
+
const thisDeclMfSrcs = bodyMfs.slice(before);
|
|
4682
|
+
if (isCombinator(val)) scope.set(name, { combi: val, mfSrcs: thisDeclMfSrcs });
|
|
4683
|
+
else scope.set(name, val);
|
|
4684
|
+
}
|
|
4685
|
+
}
|
|
4686
|
+
return true;
|
|
4687
|
+
}
|
|
4688
|
+
function evaluateParserFactory(factoryNode, scope, code, mapFnSources, resolveFactory = () => null) {
|
|
3901
4689
|
if (factoryNode.type !== "ArrowFunctionExpression" && factoryNode.type !== "FunctionDeclaration" && factoryNode.type !== "FunctionExpression") return null;
|
|
3902
4690
|
const factory = factoryNode;
|
|
3903
4691
|
const params = factory.params;
|
|
@@ -3929,40 +4717,21 @@ function evaluateParserFactory(factoryNode, scope, code, mapFnSources) {
|
|
|
3929
4717
|
if (!returnExpr) return null;
|
|
3930
4718
|
const retObj = returnExpr.type === "ParenthesizedExpression" ? returnExpr.expression : returnExpr;
|
|
3931
4719
|
if (retObj.type !== "ObjectExpression") return null;
|
|
4720
|
+
const keys = collectRuleKeys(retObj, resolveFactory, /* @__PURE__ */ new Set());
|
|
4721
|
+
if (!keys) return null;
|
|
3932
4722
|
const ruleRefs = /* @__PURE__ */ new Map();
|
|
3933
|
-
for (const
|
|
3934
|
-
if (
|
|
3935
|
-
if (prop.computed) return null;
|
|
3936
|
-
const p = prop;
|
|
3937
|
-
const key = p.key.type === "Identifier" ? p.key.name : p.key.type === "Literal" ? String(p.key.value) : null;
|
|
3938
|
-
if (!key) return null;
|
|
3939
|
-
ruleRefs.set(key, ref());
|
|
4723
|
+
for (const key of keys) {
|
|
4724
|
+
if (!ruleRefs.has(key)) ruleRefs.set(key, ref());
|
|
3940
4725
|
}
|
|
3941
4726
|
const localScope = new Map(scope);
|
|
3942
4727
|
localScope.set(proxyName, Object.fromEntries(ruleRefs));
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
const name = id.name;
|
|
3951
|
-
const before = bodyMfs.length;
|
|
3952
|
-
const val = anyValue(decl.init, localScope, code, bodyMfs);
|
|
3953
|
-
if (val === null) return null;
|
|
3954
|
-
const thisDeclMfSrcs = bodyMfs.slice(before);
|
|
3955
|
-
if (isCombinator(val)) {
|
|
3956
|
-
localScope.set(name, { combi: val, mfSrcs: thisDeclMfSrcs });
|
|
3957
|
-
} else {
|
|
3958
|
-
localScope.set(name, val);
|
|
3959
|
-
}
|
|
3960
|
-
}
|
|
3961
|
-
}
|
|
3962
|
-
for (const prop of retObj.properties) {
|
|
3963
|
-
const p = prop;
|
|
3964
|
-
const key = p.key.type === "Identifier" ? p.key.name : String(p.key.value);
|
|
3965
|
-
const val = anyValue(p.value, localScope, code, mapFnSources);
|
|
4728
|
+
if (!evalBodyStatements(statements, localScope, code)) return null;
|
|
4729
|
+
const entries = flattenRuleEntries(retObj, localScope, code, resolveFactory, /* @__PURE__ */ new Set());
|
|
4730
|
+
if (!entries) return null;
|
|
4731
|
+
const finalByKey = /* @__PURE__ */ new Map();
|
|
4732
|
+
for (const e of entries) finalByKey.set(e.key, e);
|
|
4733
|
+
for (const [key, e] of finalByKey) {
|
|
4734
|
+
const val = anyValue(e.value, e.scope, e.code, mapFnSources);
|
|
3966
4735
|
if (!isCombinator(val)) return null;
|
|
3967
4736
|
ruleRefs.get(key).define(val);
|
|
3968
4737
|
}
|
|
@@ -4020,6 +4789,40 @@ function referencesAny(node2, names, scope) {
|
|
|
4020
4789
|
|
|
4021
4790
|
// src/plugin/index.ts
|
|
4022
4791
|
var PARSEMAN_MODULE = "parseman";
|
|
4792
|
+
var _fragmentResolver = null;
|
|
4793
|
+
function getFragmentResolver() {
|
|
4794
|
+
return _fragmentResolver ??= new import_oxc_resolver.ResolverFactory({
|
|
4795
|
+
extensions: [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"],
|
|
4796
|
+
// TS/NodeNext style: a `./x.js` import may point at `./x.ts` source.
|
|
4797
|
+
extensionAlias: {
|
|
4798
|
+
".js": [".ts", ".tsx", ".js", ".jsx"],
|
|
4799
|
+
".mjs": [".mts", ".mjs"],
|
|
4800
|
+
".cjs": [".cts", ".cjs"]
|
|
4801
|
+
},
|
|
4802
|
+
conditionNames: ["source", "development", "import", "require", "default"],
|
|
4803
|
+
mainFields: ["source", "module", "main"]
|
|
4804
|
+
});
|
|
4805
|
+
}
|
|
4806
|
+
var _moduleParseCache = /* @__PURE__ */ new Map();
|
|
4807
|
+
function parseModuleCached(filePath) {
|
|
4808
|
+
let mtimeMs;
|
|
4809
|
+
try {
|
|
4810
|
+
mtimeMs = fs.statSync(filePath).mtimeMs;
|
|
4811
|
+
} catch {
|
|
4812
|
+
return null;
|
|
4813
|
+
}
|
|
4814
|
+
const hit = _moduleParseCache.get(filePath);
|
|
4815
|
+
if (hit && hit.mtimeMs === mtimeMs) return hit.parsed;
|
|
4816
|
+
let parsed = null;
|
|
4817
|
+
try {
|
|
4818
|
+
const src = fs.readFileSync(filePath, "utf8");
|
|
4819
|
+
const r = (0, import_oxc_parser.parseSync)(filePath, src);
|
|
4820
|
+
if (r.errors.length === 0) parsed = { body: r.program.body, src };
|
|
4821
|
+
} catch {
|
|
4822
|
+
}
|
|
4823
|
+
_moduleParseCache.set(filePath, { mtimeMs, parsed });
|
|
4824
|
+
return parsed;
|
|
4825
|
+
}
|
|
4023
4826
|
var plugin_default = (0, import_unplugin.createUnplugin)((opts = {}) => ({
|
|
4024
4827
|
name: "parseman",
|
|
4025
4828
|
// Run BEFORE the bundler's TS/JS transform — otherwise esbuild (Vite) strips
|
|
@@ -4055,15 +4858,23 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
4055
4858
|
const body = result.program.body;
|
|
4056
4859
|
const macroImports = [];
|
|
4057
4860
|
const allNames = /* @__PURE__ */ new Set();
|
|
4861
|
+
const importBindings = /* @__PURE__ */ new Map();
|
|
4058
4862
|
for (const stmt of body) {
|
|
4059
4863
|
if (stmt.type !== "ImportDeclaration") continue;
|
|
4060
4864
|
const s = stmt;
|
|
4061
|
-
|
|
4062
|
-
const isMacro = s.attributes.some((a) => {
|
|
4865
|
+
const isMacro = moduleAliases.has(s.source.value) && s.attributes.some((a) => {
|
|
4063
4866
|
const key = a.key.type === "Identifier" ? a.key.name : String(a.key.value);
|
|
4064
4867
|
return key === "type" && a.value.value === "macro";
|
|
4065
4868
|
});
|
|
4066
|
-
if (!isMacro)
|
|
4869
|
+
if (!isMacro) {
|
|
4870
|
+
for (const spec of s.specifiers) {
|
|
4871
|
+
if (spec.type === "ImportSpecifier") {
|
|
4872
|
+
const imported = spec.imported.name ?? spec.local.name;
|
|
4873
|
+
importBindings.set(spec.local.name, { source: s.source.value, imported });
|
|
4874
|
+
}
|
|
4875
|
+
}
|
|
4876
|
+
continue;
|
|
4877
|
+
}
|
|
4067
4878
|
const names = /* @__PURE__ */ new Set();
|
|
4068
4879
|
for (const spec of s.specifiers) {
|
|
4069
4880
|
if (spec.type === "ImportSpecifier") names.add(spec.local.name);
|
|
@@ -4073,6 +4884,63 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
4073
4884
|
}
|
|
4074
4885
|
if (macroImports.length === 0) return null;
|
|
4075
4886
|
const scope = /* @__PURE__ */ new Map();
|
|
4887
|
+
const factories = /* @__PURE__ */ new Map();
|
|
4888
|
+
const resolver = getFragmentResolver();
|
|
4889
|
+
const importedFactoryCache = /* @__PURE__ */ new Map();
|
|
4890
|
+
const OUTPUT_DIR = /([\\/])(dist|lib|build|out|output|compiled|cjs|esm|es)([\\/])/;
|
|
4891
|
+
const resolveSourcePath = (spec) => {
|
|
4892
|
+
let resolved = null;
|
|
4893
|
+
try {
|
|
4894
|
+
resolved = resolver.resolveFileSync(id, spec).path ?? null;
|
|
4895
|
+
} catch {
|
|
4896
|
+
}
|
|
4897
|
+
if (!resolved) return null;
|
|
4898
|
+
if (OUTPUT_DIR.test(resolved)) {
|
|
4899
|
+
const srcCandidate = resolved.replace(OUTPUT_DIR, "$1src$3").replace(/\.(c|m)?js$/, ".ts");
|
|
4900
|
+
try {
|
|
4901
|
+
if (fs.statSync(srcCandidate).isFile()) return srcCandidate;
|
|
4902
|
+
} catch {
|
|
4903
|
+
}
|
|
4904
|
+
}
|
|
4905
|
+
return resolved;
|
|
4906
|
+
};
|
|
4907
|
+
const resolveImportedFactory = (name) => {
|
|
4908
|
+
if (importedFactoryCache.has(name)) return importedFactoryCache.get(name);
|
|
4909
|
+
let result2 = null;
|
|
4910
|
+
const binding = importBindings.get(name);
|
|
4911
|
+
if (binding) {
|
|
4912
|
+
const filePath = resolveSourcePath(binding.source);
|
|
4913
|
+
const mod = filePath ? parseModuleCached(filePath) : null;
|
|
4914
|
+
if (mod) {
|
|
4915
|
+
for (const st of mod.body) {
|
|
4916
|
+
if (st.type !== "ExportNamedDeclaration" || !st.declaration) continue;
|
|
4917
|
+
const decl = st.declaration;
|
|
4918
|
+
if (decl.type === "VariableDeclaration") {
|
|
4919
|
+
for (const d of decl.declarations ?? []) {
|
|
4920
|
+
if (d.id?.type === "Identifier" && d.id.name === binding.imported && d.init) {
|
|
4921
|
+
const fac = asFragmentFactory(d.init);
|
|
4922
|
+
if (fac) {
|
|
4923
|
+
result2 = { fn: fac, code: mod.src };
|
|
4924
|
+
break;
|
|
4925
|
+
}
|
|
4926
|
+
}
|
|
4927
|
+
}
|
|
4928
|
+
} else if (decl.type === "FunctionDeclaration" && decl.id?.type === "Identifier" && decl.id.name === binding.imported) {
|
|
4929
|
+
const fac = asFragmentFactory(decl);
|
|
4930
|
+
if (fac) result2 = { fn: fac, code: mod.src };
|
|
4931
|
+
}
|
|
4932
|
+
if (result2) break;
|
|
4933
|
+
}
|
|
4934
|
+
}
|
|
4935
|
+
}
|
|
4936
|
+
importedFactoryCache.set(name, result2);
|
|
4937
|
+
return result2;
|
|
4938
|
+
};
|
|
4939
|
+
const resolveFactory = (n) => {
|
|
4940
|
+
const local = factories.get(n);
|
|
4941
|
+
if (local) return { fn: local, code };
|
|
4942
|
+
return resolveImportedFactory(n);
|
|
4943
|
+
};
|
|
4076
4944
|
const replacements = [];
|
|
4077
4945
|
const warnings = [];
|
|
4078
4946
|
let anyUnresolved = false;
|
|
@@ -4093,7 +4961,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
4093
4961
|
warn(init.start, `${label2}: rules() needs a factory argument`);
|
|
4094
4962
|
return null;
|
|
4095
4963
|
}
|
|
4096
|
-
const ruleMap = evaluateParserFactory(factoryArg, scope, code, []);
|
|
4964
|
+
const ruleMap = evaluateParserFactory(factoryArg, scope, code, [], resolveFactory);
|
|
4097
4965
|
if (!ruleMap) {
|
|
4098
4966
|
warn(init.start, `${label2}: rules(...) factory isn't statically evaluable`);
|
|
4099
4967
|
return null;
|
|
@@ -4191,6 +5059,11 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
4191
5059
|
});
|
|
4192
5060
|
continue;
|
|
4193
5061
|
}
|
|
5062
|
+
const frag = asFragmentFactory(init);
|
|
5063
|
+
if (frag) {
|
|
5064
|
+
factories.set(varName, frag);
|
|
5065
|
+
continue;
|
|
5066
|
+
}
|
|
4194
5067
|
const mapFnSources = [];
|
|
4195
5068
|
const parser2 = evaluateExpr(init, scope, code, mapFnSources);
|
|
4196
5069
|
if (parser2 === null) {
|