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.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// src/plugin/index.ts
|
|
2
|
+
import * as fs from "node:fs";
|
|
2
3
|
import { createUnplugin } from "unplugin";
|
|
3
4
|
import { parseSync } from "oxc-parser";
|
|
5
|
+
import { ResolverFactory } from "oxc-resolver";
|
|
4
6
|
import MagicString from "magic-string";
|
|
5
7
|
|
|
6
8
|
// src/combinators/first-set.ts
|
|
@@ -328,15 +330,15 @@ function extractFirstSet(node2) {
|
|
|
328
330
|
case "Alternative": {
|
|
329
331
|
const exprs = node2.expressions;
|
|
330
332
|
if (!exprs || exprs.length === 0) return { firstSet: empty(), canMatchNewline: false };
|
|
331
|
-
let
|
|
333
|
+
let fs2 = empty();
|
|
332
334
|
let canNL = false;
|
|
333
335
|
for (const expr of exprs) {
|
|
334
336
|
const r = extractFirstSet(expr);
|
|
335
|
-
|
|
337
|
+
fs2 = union(fs2, r.firstSet);
|
|
336
338
|
canNL = canNL || r.canMatchNewline;
|
|
337
339
|
if (!canBeEmpty(expr)) break;
|
|
338
340
|
}
|
|
339
|
-
return { firstSet:
|
|
341
|
+
return { firstSet: fs2, canMatchNewline: canNL };
|
|
340
342
|
}
|
|
341
343
|
case "Char": {
|
|
342
344
|
const kind = node2.kind;
|
|
@@ -363,22 +365,22 @@ function extractFirstSet(node2) {
|
|
|
363
365
|
}
|
|
364
366
|
case "CharacterClass": {
|
|
365
367
|
const expressions = node2.expressions;
|
|
366
|
-
let
|
|
368
|
+
let fs2 = empty();
|
|
367
369
|
let canNL = false;
|
|
368
370
|
for (const expr of expressions) {
|
|
369
371
|
if (expr.type === "ClassRange") {
|
|
370
372
|
const from = expr.from.codePoint;
|
|
371
373
|
const to = expr.to.codePoint;
|
|
372
|
-
|
|
374
|
+
fs2 = union(fs2, fromRange(from, to));
|
|
373
375
|
if (from <= 10 && 10 <= to) canNL = true;
|
|
374
376
|
} else if (expr.type === "Char") {
|
|
375
377
|
const r = extractFirstSet(expr);
|
|
376
|
-
|
|
378
|
+
fs2 = union(fs2, r.firstSet);
|
|
377
379
|
canNL = canNL || r.canMatchNewline;
|
|
378
380
|
}
|
|
379
381
|
}
|
|
380
382
|
if (node2.negative) return { firstSet: any(), canMatchNewline: true };
|
|
381
|
-
return { firstSet:
|
|
383
|
+
return { firstSet: fs2, canMatchNewline: canNL };
|
|
382
384
|
}
|
|
383
385
|
case "Repetition": {
|
|
384
386
|
return extractFirstSet(node2.expression);
|
|
@@ -687,10 +689,10 @@ function codesToFirstSet(codes) {
|
|
|
687
689
|
ranges.push({ lo, hi });
|
|
688
690
|
return { kind: "ranges", ranges };
|
|
689
691
|
}
|
|
690
|
-
function inFirstSet(code,
|
|
691
|
-
if (
|
|
692
|
-
if (
|
|
693
|
-
for (const r of
|
|
692
|
+
function inFirstSet(code, fs2) {
|
|
693
|
+
if (fs2.kind === "any") return true;
|
|
694
|
+
if (fs2.kind === "empty") return false;
|
|
695
|
+
for (const r of fs2.ranges) if (code >= r.lo && code <= r.hi) return true;
|
|
694
696
|
return false;
|
|
695
697
|
}
|
|
696
698
|
function areDisjoint(sets) {
|
|
@@ -1339,8 +1341,29 @@ function expect(combinator, label2) {
|
|
|
1339
1341
|
var BACKSLASH = 92;
|
|
1340
1342
|
var CLASS_ESCAPES = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
1341
1343
|
var META = new Set("()[]{}*+?|^$.".split(""));
|
|
1344
|
+
var SPACE_RANGES = [
|
|
1345
|
+
[9, 13],
|
|
1346
|
+
[32, 32],
|
|
1347
|
+
[160, 160],
|
|
1348
|
+
[5760, 5760],
|
|
1349
|
+
[8192, 8202],
|
|
1350
|
+
[8232, 8232],
|
|
1351
|
+
[8233, 8233],
|
|
1352
|
+
[8239, 8239],
|
|
1353
|
+
[8287, 8287],
|
|
1354
|
+
[12288, 12288],
|
|
1355
|
+
[65279, 65279]
|
|
1356
|
+
];
|
|
1342
1357
|
function shorthandRanges(ch) {
|
|
1343
|
-
|
|
1358
|
+
if (ch === "d") return [[48, 57]];
|
|
1359
|
+
if (ch === "s") return SPACE_RANGES;
|
|
1360
|
+
return [[48, 57], [65, 90], [97, 122], [95, 95]];
|
|
1361
|
+
}
|
|
1362
|
+
function readUnicodeEscape(body, i) {
|
|
1363
|
+
if (body[i] !== "\\" || body[i + 1] !== "u") return null;
|
|
1364
|
+
const hex = body.slice(i + 2, i + 6);
|
|
1365
|
+
if (!/^[0-9a-fA-F]{4}$/.test(hex)) return null;
|
|
1366
|
+
return { cp: Number.parseInt(hex, 16), next: i + 6 };
|
|
1344
1367
|
}
|
|
1345
1368
|
function parseClassRanges(body) {
|
|
1346
1369
|
const ranges = [];
|
|
@@ -1349,11 +1372,16 @@ function parseClassRanges(body) {
|
|
|
1349
1372
|
const ch = body[i];
|
|
1350
1373
|
if (ch === void 0) return null;
|
|
1351
1374
|
if (ch === "\\") {
|
|
1375
|
+
const uni = readUnicodeEscape(body, i);
|
|
1376
|
+
if (uni) {
|
|
1377
|
+
i = uni.next;
|
|
1378
|
+
return { cp: uni.cp };
|
|
1379
|
+
}
|
|
1352
1380
|
const e = body[i + 1];
|
|
1353
1381
|
if (e === void 0) return null;
|
|
1354
1382
|
i += 2;
|
|
1355
1383
|
if (e in CLASS_ESCAPES) return { cp: CLASS_ESCAPES[e] };
|
|
1356
|
-
if (e === "d" || e === "w") return { set: shorthandRanges(e) };
|
|
1384
|
+
if (e === "d" || e === "w" || e === "s") return { set: shorthandRanges(e) };
|
|
1357
1385
|
if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
1358
1386
|
return { cp: e.codePointAt(0) };
|
|
1359
1387
|
}
|
|
@@ -1381,10 +1409,16 @@ function parseClassRanges(body) {
|
|
|
1381
1409
|
function classToRanges(cls) {
|
|
1382
1410
|
if (cls === "\\d") return shorthandRanges("d");
|
|
1383
1411
|
if (cls === "\\w") return shorthandRanges("w");
|
|
1412
|
+
if (cls === "\\s") return shorthandRanges("s");
|
|
1384
1413
|
const body = cls.slice(1, -1);
|
|
1385
1414
|
if (body.startsWith("^")) return null;
|
|
1386
1415
|
return parseClassRanges(body);
|
|
1387
1416
|
}
|
|
1417
|
+
var foldEq = (cVar, cp) => {
|
|
1418
|
+
if (cp >= 65 && cp <= 90) return `(${cVar} === ${cp} || ${cVar} === ${cp + 32})`;
|
|
1419
|
+
if (cp >= 97 && cp <= 122) return `(${cVar} === ${cp} || ${cVar} === ${cp - 32})`;
|
|
1420
|
+
return `${cVar} === ${cp}`;
|
|
1421
|
+
};
|
|
1388
1422
|
function literalCodePoints(frag) {
|
|
1389
1423
|
const out = [];
|
|
1390
1424
|
let i = 0;
|
|
@@ -1431,22 +1465,446 @@ function parseStringShape(source) {
|
|
|
1431
1465
|
if (!inSet(qcp) || !inSet(BACKSLASH)) return null;
|
|
1432
1466
|
return { kind: "string", quote: qcp, excluded, escLineTerm: esc !== "." };
|
|
1433
1467
|
}
|
|
1468
|
+
function parseSeqParts(source) {
|
|
1469
|
+
const parts = [];
|
|
1470
|
+
let lit = [];
|
|
1471
|
+
const flush = () => {
|
|
1472
|
+
if (lit.length) {
|
|
1473
|
+
parts.push({ part: "lit", cps: lit, optional: false });
|
|
1474
|
+
lit = [];
|
|
1475
|
+
}
|
|
1476
|
+
};
|
|
1477
|
+
const runFrom = (ranges, negated, q) => {
|
|
1478
|
+
if (q === "+") {
|
|
1479
|
+
parts.push({ part: "run", ranges, negated, min: 1, unbounded: true });
|
|
1480
|
+
return 1;
|
|
1481
|
+
}
|
|
1482
|
+
if (q === "*") {
|
|
1483
|
+
parts.push({ part: "run", ranges, negated, min: 0, unbounded: true });
|
|
1484
|
+
return 1;
|
|
1485
|
+
}
|
|
1486
|
+
if (q === "?") {
|
|
1487
|
+
parts.push({ part: "run", ranges, negated, min: 0, unbounded: false });
|
|
1488
|
+
return 1;
|
|
1489
|
+
}
|
|
1490
|
+
parts.push({ part: "run", ranges, negated, min: 1, unbounded: false });
|
|
1491
|
+
return 0;
|
|
1492
|
+
};
|
|
1493
|
+
let i = 0;
|
|
1494
|
+
while (i < source.length) {
|
|
1495
|
+
const ch = source[i];
|
|
1496
|
+
if (ch === "[") {
|
|
1497
|
+
let k = i + 1;
|
|
1498
|
+
const neg = source[k] === "^";
|
|
1499
|
+
if (neg) k++;
|
|
1500
|
+
let body = "";
|
|
1501
|
+
while (k < source.length && source[k] !== "]") {
|
|
1502
|
+
if (source[k] === "\\") {
|
|
1503
|
+
body += source[k] + (source[k + 1] ?? "");
|
|
1504
|
+
k += 2;
|
|
1505
|
+
} else {
|
|
1506
|
+
body += source[k];
|
|
1507
|
+
k++;
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
if (source[k] !== "]") return null;
|
|
1511
|
+
const ranges = parseClassRanges(body);
|
|
1512
|
+
if (!ranges) return null;
|
|
1513
|
+
flush();
|
|
1514
|
+
i = k + 1;
|
|
1515
|
+
i += runFrom(ranges, neg, source[i]);
|
|
1516
|
+
continue;
|
|
1517
|
+
}
|
|
1518
|
+
if (ch === "\\") {
|
|
1519
|
+
const e = source[i + 1];
|
|
1520
|
+
if (e === "d" || e === "w" || e === "s") {
|
|
1521
|
+
flush();
|
|
1522
|
+
i += 2;
|
|
1523
|
+
i += runFrom(shorthandRanges(e), false, source[i]);
|
|
1524
|
+
continue;
|
|
1525
|
+
}
|
|
1526
|
+
const uni = readUnicodeEscape(source, i);
|
|
1527
|
+
let cp2;
|
|
1528
|
+
if (uni) {
|
|
1529
|
+
cp2 = uni.cp;
|
|
1530
|
+
i = uni.next;
|
|
1531
|
+
} else if (e === void 0) return null;
|
|
1532
|
+
else if (e in CLASS_ESCAPES) {
|
|
1533
|
+
cp2 = CLASS_ESCAPES[e];
|
|
1534
|
+
i += 2;
|
|
1535
|
+
} else if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
1536
|
+
else {
|
|
1537
|
+
cp2 = e.codePointAt(0);
|
|
1538
|
+
i += 2;
|
|
1539
|
+
}
|
|
1540
|
+
if (source[i] === "?") {
|
|
1541
|
+
flush();
|
|
1542
|
+
parts.push({ part: "lit", cps: [cp2], optional: true });
|
|
1543
|
+
i++;
|
|
1544
|
+
} else lit.push(cp2);
|
|
1545
|
+
continue;
|
|
1546
|
+
}
|
|
1547
|
+
if (ch === "(") {
|
|
1548
|
+
if (source[i + 1] !== "?" || source[i + 2] !== ":") return null;
|
|
1549
|
+
let k = i + 3;
|
|
1550
|
+
let depth = 1;
|
|
1551
|
+
while (k < source.length && depth > 0) {
|
|
1552
|
+
const c2 = source[k];
|
|
1553
|
+
if (c2 === "\\") {
|
|
1554
|
+
k += 2;
|
|
1555
|
+
continue;
|
|
1556
|
+
}
|
|
1557
|
+
if (c2 === "[") {
|
|
1558
|
+
let j = k + 1;
|
|
1559
|
+
if (source[j] === "^") j++;
|
|
1560
|
+
while (j < source.length && source[j] !== "]") {
|
|
1561
|
+
if (source[j] === "\\") j += 2;
|
|
1562
|
+
else j++;
|
|
1563
|
+
}
|
|
1564
|
+
if (source[j] !== "]") return null;
|
|
1565
|
+
k = j + 1;
|
|
1566
|
+
continue;
|
|
1567
|
+
}
|
|
1568
|
+
if (c2 === "(") depth++;
|
|
1569
|
+
else if (c2 === ")") depth--;
|
|
1570
|
+
k++;
|
|
1571
|
+
}
|
|
1572
|
+
if (depth !== 0) return null;
|
|
1573
|
+
const body = source.slice(i + 3, k - 1);
|
|
1574
|
+
const inner = parseScanShape(body);
|
|
1575
|
+
if (!inner || !groupInnerSafe(inner)) return null;
|
|
1576
|
+
const q = source[k];
|
|
1577
|
+
if (q === "{") return null;
|
|
1578
|
+
flush();
|
|
1579
|
+
if (q === "+") {
|
|
1580
|
+
if (shapeCanBeEmpty(inner)) return null;
|
|
1581
|
+
parts.push({ part: "group", inner, min: 1, unbounded: true });
|
|
1582
|
+
i = k + 1;
|
|
1583
|
+
} else if (q === "*") {
|
|
1584
|
+
if (shapeCanBeEmpty(inner)) return null;
|
|
1585
|
+
parts.push({ part: "group", inner, min: 0, unbounded: true });
|
|
1586
|
+
i = k + 1;
|
|
1587
|
+
} else if (q === "?") {
|
|
1588
|
+
parts.push({ part: "group", inner, min: 0, unbounded: false });
|
|
1589
|
+
i = k + 1;
|
|
1590
|
+
} else {
|
|
1591
|
+
parts.push({ part: "group", inner, min: 1, unbounded: false });
|
|
1592
|
+
i = k;
|
|
1593
|
+
}
|
|
1594
|
+
continue;
|
|
1595
|
+
}
|
|
1596
|
+
if (META.has(ch)) return null;
|
|
1597
|
+
const cp = ch.codePointAt(0);
|
|
1598
|
+
i += ch.length;
|
|
1599
|
+
if (source[i] === "?") {
|
|
1600
|
+
flush();
|
|
1601
|
+
parts.push({ part: "lit", cps: [cp], optional: true });
|
|
1602
|
+
i++;
|
|
1603
|
+
} else lit.push(cp);
|
|
1604
|
+
}
|
|
1605
|
+
flush();
|
|
1606
|
+
return parts.length ? parts : null;
|
|
1607
|
+
}
|
|
1608
|
+
function seqIsUnambiguous(parts) {
|
|
1609
|
+
let hasMandatory = false;
|
|
1610
|
+
for (let k = 0; k < parts.length; k++) {
|
|
1611
|
+
const p = parts[k];
|
|
1612
|
+
const mandatory = p.part === "lit" ? !p.optional : p.min === 1;
|
|
1613
|
+
if (mandatory) hasMandatory = true;
|
|
1614
|
+
const skippableSingle = p.part === "lit" && p.optional || p.part !== "lit" && !p.unbounded && p.min === 0;
|
|
1615
|
+
const isUnboundedRepeat = p.part !== "lit" && p.unbounded;
|
|
1616
|
+
if (skippableSingle || isUnboundedRepeat) {
|
|
1617
|
+
const rest = seqFirstAccept(parts.slice(k + 1));
|
|
1618
|
+
if (!firstSetsDisjoint(partFirstAccept(p), rest)) return false;
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
return hasMandatory;
|
|
1622
|
+
}
|
|
1623
|
+
function rangesOverlap(a, b) {
|
|
1624
|
+
return a.some(([lo, hi]) => b.some(([lo2, hi2]) => lo <= hi2 && lo2 <= hi));
|
|
1625
|
+
}
|
|
1626
|
+
function rangesSubset(sub, sup) {
|
|
1627
|
+
return sub.every(([lo, hi]) => sup.some(([lo2, hi2]) => lo >= lo2 && hi <= hi2));
|
|
1628
|
+
}
|
|
1629
|
+
function parseClassOperand(body) {
|
|
1630
|
+
if (body === "\\d" || body === "\\w" || body === "\\s") {
|
|
1631
|
+
return { ranges: shorthandRanges(body[1]), negated: false };
|
|
1632
|
+
}
|
|
1633
|
+
if (body.length >= 2 && body[0] === "[" && body[body.length - 1] === "]") {
|
|
1634
|
+
let inner = body.slice(1, -1);
|
|
1635
|
+
const negated = inner.startsWith("^");
|
|
1636
|
+
if (negated) inner = inner.slice(1);
|
|
1637
|
+
const ranges = parseClassRanges(inner);
|
|
1638
|
+
return ranges ? { ranges, negated } : null;
|
|
1639
|
+
}
|
|
1640
|
+
const cps = literalCodePoints(body);
|
|
1641
|
+
if (cps && cps.length === 1) return { ranges: [[cps[0], cps[0]]], negated: false };
|
|
1642
|
+
return null;
|
|
1643
|
+
}
|
|
1644
|
+
function classSubset(t, u) {
|
|
1645
|
+
if (!t.negated && !u.negated) return rangesSubset(t.ranges, u.ranges);
|
|
1646
|
+
if (!t.negated && u.negated) return !rangesOverlap(t.ranges, u.ranges);
|
|
1647
|
+
if (t.negated && !u.negated) return false;
|
|
1648
|
+
return rangesSubset(u.ranges, t.ranges);
|
|
1649
|
+
}
|
|
1650
|
+
function classDisjoint(t, u) {
|
|
1651
|
+
if (!t.negated && !u.negated) return !rangesOverlap(t.ranges, u.ranges);
|
|
1652
|
+
if (!t.negated && u.negated) return rangesSubset(t.ranges, u.ranges);
|
|
1653
|
+
if (t.negated && !u.negated) return rangesSubset(u.ranges, t.ranges);
|
|
1654
|
+
return false;
|
|
1655
|
+
}
|
|
1656
|
+
function firstSetsDisjoint(a, b) {
|
|
1657
|
+
if (a === "any" || b === "any") return false;
|
|
1658
|
+
return classDisjoint(a, b);
|
|
1659
|
+
}
|
|
1660
|
+
function trailingBacktrackClass(shape) {
|
|
1661
|
+
if (shape.kind === "chars") return { ranges: shape.ranges, negated: false };
|
|
1662
|
+
if (shape.kind === "ident") return { ranges: shape.tail, negated: false };
|
|
1663
|
+
if (shape.kind === "litFold") return null;
|
|
1664
|
+
if (shape.kind === "seq") {
|
|
1665
|
+
const last = shape.parts[shape.parts.length - 1];
|
|
1666
|
+
if (last.part === "lit") return null;
|
|
1667
|
+
if (last.part === "run") {
|
|
1668
|
+
if (last.unbounded || last.min === 0) return { ranges: last.ranges, negated: last.negated };
|
|
1669
|
+
return null;
|
|
1670
|
+
}
|
|
1671
|
+
const innerWiggle = trailingBacktrackClass(last.inner);
|
|
1672
|
+
if (innerWiggle === "unsupported") return "unsupported";
|
|
1673
|
+
const requiredOnce = !last.unbounded && last.min === 1;
|
|
1674
|
+
if (requiredOnce) return innerWiggle;
|
|
1675
|
+
const dropExposed = shapeFirstAccept(last.inner);
|
|
1676
|
+
if (dropExposed === "any") return "unsupported";
|
|
1677
|
+
if (innerWiggle === null) return dropExposed;
|
|
1678
|
+
const unioned = unionCharSets([innerWiggle, dropExposed]);
|
|
1679
|
+
return unioned === "any" ? "unsupported" : unioned;
|
|
1680
|
+
}
|
|
1681
|
+
if (shape.kind === "alt") {
|
|
1682
|
+
if (!shape.disjoint) return "unsupported";
|
|
1683
|
+
const classes = shape.arms.map(trailingBacktrackClass);
|
|
1684
|
+
if (classes.some((c) => c === "unsupported")) return "unsupported";
|
|
1685
|
+
const concrete = classes.filter((c) => c !== null);
|
|
1686
|
+
if (concrete.length === 0) return null;
|
|
1687
|
+
const unioned = unionCharSets(concrete);
|
|
1688
|
+
return unioned === "any" ? "unsupported" : unioned;
|
|
1689
|
+
}
|
|
1690
|
+
return "unsupported";
|
|
1691
|
+
}
|
|
1692
|
+
function lookaheadUnambiguous(inner, operand, negative) {
|
|
1693
|
+
const tail = trailingBacktrackClass(inner);
|
|
1694
|
+
if (tail === "unsupported") return false;
|
|
1695
|
+
if (tail === null) return true;
|
|
1696
|
+
return negative ? classSubset(tail, operand) : classDisjoint(tail, operand);
|
|
1697
|
+
}
|
|
1698
|
+
function stripTrailingLookahead(source) {
|
|
1699
|
+
if (!source.endsWith(")")) return null;
|
|
1700
|
+
for (const negative of [true, false]) {
|
|
1701
|
+
const lead = negative ? "(?!" : "(?=";
|
|
1702
|
+
const idx = source.lastIndexOf(lead);
|
|
1703
|
+
if (idx === -1) continue;
|
|
1704
|
+
const body = source.slice(idx + lead.length, -1);
|
|
1705
|
+
const operand = body.length ? parseClassOperand(body) : null;
|
|
1706
|
+
if (!operand) continue;
|
|
1707
|
+
return { base: source.slice(0, idx), ranges: operand.ranges, classNegated: operand.negated, negative };
|
|
1708
|
+
}
|
|
1709
|
+
return null;
|
|
1710
|
+
}
|
|
1711
|
+
function unwrapOuterGroup(source) {
|
|
1712
|
+
while (source.startsWith("(?:")) {
|
|
1713
|
+
let depth = 1;
|
|
1714
|
+
let i = 3;
|
|
1715
|
+
let ok = true;
|
|
1716
|
+
while (i < source.length && depth > 0) {
|
|
1717
|
+
const ch = source[i];
|
|
1718
|
+
if (ch === "\\") {
|
|
1719
|
+
i += 2;
|
|
1720
|
+
continue;
|
|
1721
|
+
}
|
|
1722
|
+
if (ch === "[") {
|
|
1723
|
+
let j = i + 1;
|
|
1724
|
+
if (source[j] === "^") j++;
|
|
1725
|
+
while (j < source.length && source[j] !== "]") {
|
|
1726
|
+
if (source[j] === "\\") j += 2;
|
|
1727
|
+
else j++;
|
|
1728
|
+
}
|
|
1729
|
+
if (source[j] !== "]") {
|
|
1730
|
+
ok = false;
|
|
1731
|
+
break;
|
|
1732
|
+
}
|
|
1733
|
+
i = j + 1;
|
|
1734
|
+
continue;
|
|
1735
|
+
}
|
|
1736
|
+
if (ch === "(") depth++;
|
|
1737
|
+
else if (ch === ")") depth--;
|
|
1738
|
+
i++;
|
|
1739
|
+
}
|
|
1740
|
+
if (!ok || depth !== 0 || i !== source.length) break;
|
|
1741
|
+
source = source.slice(3, -1);
|
|
1742
|
+
}
|
|
1743
|
+
return source;
|
|
1744
|
+
}
|
|
1745
|
+
function splitTopLevelAlternation(source) {
|
|
1746
|
+
const body = unwrapOuterGroup(source);
|
|
1747
|
+
const parts = [];
|
|
1748
|
+
let depth = 0;
|
|
1749
|
+
let last = 0;
|
|
1750
|
+
let i = 0;
|
|
1751
|
+
while (i < body.length) {
|
|
1752
|
+
const ch = body[i];
|
|
1753
|
+
if (ch === "\\") {
|
|
1754
|
+
i += 2;
|
|
1755
|
+
continue;
|
|
1756
|
+
}
|
|
1757
|
+
if (ch === "[") {
|
|
1758
|
+
let j = i + 1;
|
|
1759
|
+
if (body[j] === "^") j++;
|
|
1760
|
+
while (j < body.length && body[j] !== "]") {
|
|
1761
|
+
if (body[j] === "\\") j += 2;
|
|
1762
|
+
else j++;
|
|
1763
|
+
}
|
|
1764
|
+
if (body[j] !== "]") return null;
|
|
1765
|
+
i = j + 1;
|
|
1766
|
+
continue;
|
|
1767
|
+
}
|
|
1768
|
+
if (ch === "(") {
|
|
1769
|
+
depth++;
|
|
1770
|
+
i++;
|
|
1771
|
+
continue;
|
|
1772
|
+
}
|
|
1773
|
+
if (ch === ")") {
|
|
1774
|
+
depth--;
|
|
1775
|
+
if (depth < 0) return null;
|
|
1776
|
+
i++;
|
|
1777
|
+
continue;
|
|
1778
|
+
}
|
|
1779
|
+
if (ch === "|" && depth === 0) {
|
|
1780
|
+
parts.push(body.slice(last, i));
|
|
1781
|
+
last = i + 1;
|
|
1782
|
+
i++;
|
|
1783
|
+
continue;
|
|
1784
|
+
}
|
|
1785
|
+
i++;
|
|
1786
|
+
}
|
|
1787
|
+
if (depth !== 0) return null;
|
|
1788
|
+
parts.push(body.slice(last));
|
|
1789
|
+
if (parts.length < 2 || parts.some((p) => p.length === 0)) return null;
|
|
1790
|
+
return parts;
|
|
1791
|
+
}
|
|
1792
|
+
function shapeCanBeEmpty(shape) {
|
|
1793
|
+
if (shape.kind === "chars") return !shape.minOne;
|
|
1794
|
+
if (shape.kind === "lookahead") return shapeCanBeEmpty(shape.inner);
|
|
1795
|
+
if (shape.kind === "alt") return shape.arms.some(shapeCanBeEmpty);
|
|
1796
|
+
return false;
|
|
1797
|
+
}
|
|
1798
|
+
function unionCharSets(sets) {
|
|
1799
|
+
if (sets.some((s) => s === "any")) return "any";
|
|
1800
|
+
const concrete = sets;
|
|
1801
|
+
if (concrete.length === 1) return concrete[0];
|
|
1802
|
+
if (concrete.some((s) => s.negated)) return "any";
|
|
1803
|
+
return { ranges: concrete.flatMap((s) => s.ranges), negated: false };
|
|
1804
|
+
}
|
|
1805
|
+
function partFirstAccept(part) {
|
|
1806
|
+
if (part.part === "lit") return { ranges: [[part.cps[0], part.cps[0]]], negated: false };
|
|
1807
|
+
if (part.part === "run") return { ranges: part.ranges, negated: part.negated };
|
|
1808
|
+
return shapeFirstAccept(part.inner);
|
|
1809
|
+
}
|
|
1810
|
+
function seqFirstAccept(parts) {
|
|
1811
|
+
const sets = [];
|
|
1812
|
+
for (const p of parts) {
|
|
1813
|
+
const mandatory = p.part === "lit" ? !p.optional : p.min === 1;
|
|
1814
|
+
sets.push(partFirstAccept(p));
|
|
1815
|
+
if (mandatory) break;
|
|
1816
|
+
}
|
|
1817
|
+
return unionCharSets(sets);
|
|
1818
|
+
}
|
|
1819
|
+
function groupInnerSafe(shape) {
|
|
1820
|
+
if (shape.kind === "chars" || shape.kind === "ident" || shape.kind === "seq" || shape.kind === "litFold") return true;
|
|
1821
|
+
if (shape.kind === "lookahead") return groupInnerSafe(shape.inner);
|
|
1822
|
+
if (shape.kind === "alt") return shape.disjoint;
|
|
1823
|
+
return false;
|
|
1824
|
+
}
|
|
1825
|
+
function shapeFirstAccept(shape) {
|
|
1826
|
+
if (shapeCanBeEmpty(shape)) return "any";
|
|
1827
|
+
switch (shape.kind) {
|
|
1828
|
+
case "chars":
|
|
1829
|
+
return { ranges: shape.ranges, negated: false };
|
|
1830
|
+
case "ident":
|
|
1831
|
+
return { ranges: shape.head, negated: false };
|
|
1832
|
+
case "until":
|
|
1833
|
+
return { ranges: [[shape.open[0], shape.open[0]]], negated: false };
|
|
1834
|
+
case "delimited":
|
|
1835
|
+
return { ranges: [[shape.open[0], shape.open[0]]], negated: false };
|
|
1836
|
+
case "string":
|
|
1837
|
+
return { ranges: [[shape.quote, shape.quote]], negated: false };
|
|
1838
|
+
case "litFold": {
|
|
1839
|
+
const cp = shape.open[0];
|
|
1840
|
+
if (cp >= 65 && cp <= 90) return { ranges: [[cp, cp], [cp + 32, cp + 32]], negated: false };
|
|
1841
|
+
if (cp >= 97 && cp <= 122) return { ranges: [[cp, cp], [cp - 32, cp - 32]], negated: false };
|
|
1842
|
+
return { ranges: [[cp, cp]], negated: false };
|
|
1843
|
+
}
|
|
1844
|
+
case "seq":
|
|
1845
|
+
return seqFirstAccept(shape.parts);
|
|
1846
|
+
case "lookahead":
|
|
1847
|
+
return shapeFirstAccept(shape.inner);
|
|
1848
|
+
// zero-width — doesn't change first-char acceptance
|
|
1849
|
+
case "alt": {
|
|
1850
|
+
if (!shape.disjoint) return "any";
|
|
1851
|
+
const sets = shape.firsts.filter((f) => f !== null);
|
|
1852
|
+
return sets.length === shape.arms.length ? unionCharSets(sets) : "any";
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
function allPairsDisjoint(sets) {
|
|
1857
|
+
for (let i = 0; i < sets.length; i++) {
|
|
1858
|
+
const a = sets[i];
|
|
1859
|
+
if (a === "any") return false;
|
|
1860
|
+
for (let j = i + 1; j < sets.length; j++) {
|
|
1861
|
+
const b = sets[j];
|
|
1862
|
+
if (b === "any" || !classDisjoint(a, b)) return false;
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
return true;
|
|
1866
|
+
}
|
|
1867
|
+
function parseAlternation(source) {
|
|
1868
|
+
const parts = splitTopLevelAlternation(source);
|
|
1869
|
+
if (!parts) return null;
|
|
1870
|
+
const arms = [];
|
|
1871
|
+
for (const p of parts) {
|
|
1872
|
+
const arm = parseScanShape(p);
|
|
1873
|
+
if (!arm) return null;
|
|
1874
|
+
arms.push(arm);
|
|
1875
|
+
}
|
|
1876
|
+
const firstSets = arms.map(shapeFirstAccept);
|
|
1877
|
+
const disjoint = allPairsDisjoint(firstSets);
|
|
1878
|
+
return { kind: "alt", arms, disjoint, firsts: firstSets.map((f) => f === "any" ? null : f) };
|
|
1879
|
+
}
|
|
1434
1880
|
function parseScanShape(source) {
|
|
1881
|
+
const alt = parseAlternation(source);
|
|
1882
|
+
if (alt) return alt;
|
|
1883
|
+
const la = stripTrailingLookahead(source);
|
|
1884
|
+
if (la) {
|
|
1885
|
+
const inner = parseScanShapeCore(la.base);
|
|
1886
|
+
if (!inner) return null;
|
|
1887
|
+
const operand = { ranges: la.ranges, negated: la.classNegated };
|
|
1888
|
+
if (!lookaheadUnambiguous(inner, operand, la.negative)) return null;
|
|
1889
|
+
return { kind: "lookahead", inner, ranges: la.ranges, classNegated: la.classNegated, negative: la.negative };
|
|
1890
|
+
}
|
|
1891
|
+
return parseScanShapeCore(source);
|
|
1892
|
+
}
|
|
1893
|
+
function parseScanShapeCore(source) {
|
|
1435
1894
|
let m = /^\[((?:\\.|[^\]])+)\]([+*])$/.exec(source);
|
|
1436
|
-
if (m) {
|
|
1437
|
-
if (m[1].startsWith("^")) return null;
|
|
1895
|
+
if (m && !m[1].startsWith("^")) {
|
|
1438
1896
|
const ranges = parseClassRanges(m[1]);
|
|
1439
1897
|
return ranges ? { kind: "chars", ranges, minOne: m[2] === "+" } : null;
|
|
1440
1898
|
}
|
|
1441
|
-
m = /^\\([
|
|
1899
|
+
m = /^\\([dws])([+*])$/.exec(source);
|
|
1442
1900
|
if (m) {
|
|
1443
1901
|
return { kind: "chars", ranges: shorthandRanges(m[1]), minOne: m[2] === "+" };
|
|
1444
1902
|
}
|
|
1445
|
-
m = /^(\[(?:\\.|[^\]])+\]|\\[
|
|
1903
|
+
m = /^(\[(?:\\.|[^\]])+\]|\\[dws])(\[(?:\\.|[^\]])+\]|\\[dws])\*$/.exec(source);
|
|
1446
1904
|
if (m) {
|
|
1447
1905
|
const head = classToRanges(m[1]);
|
|
1448
1906
|
const tail = classToRanges(m[2]);
|
|
1449
|
-
|
|
1907
|
+
if (head && tail) return { kind: "ident", head, tail };
|
|
1450
1908
|
}
|
|
1451
1909
|
const str = parseStringShape(source);
|
|
1452
1910
|
if (str) return str;
|
|
@@ -1455,7 +1913,6 @@ function parseScanShape(source) {
|
|
|
1455
1913
|
const open = literalCodePoints(m[1]);
|
|
1456
1914
|
const stop = parseClassRanges(m[2]);
|
|
1457
1915
|
if (open && stop) return { kind: "until", open, stop };
|
|
1458
|
-
return null;
|
|
1459
1916
|
}
|
|
1460
1917
|
if (!source.includes("\\\\")) {
|
|
1461
1918
|
m = /^(.*?)\((?:\?:)?[\s\S]*\)\*(.*?)$/.exec(source);
|
|
@@ -1465,10 +1922,16 @@ function parseScanShape(source) {
|
|
|
1465
1922
|
if (open && close) return { kind: "delimited", open, close };
|
|
1466
1923
|
}
|
|
1467
1924
|
}
|
|
1925
|
+
const parts = parseSeqParts(source);
|
|
1926
|
+
if (parts && seqIsUnambiguous(parts)) return { kind: "seq", parts };
|
|
1468
1927
|
return null;
|
|
1469
1928
|
}
|
|
1470
1929
|
function scanShapeFromRegex(source, flags) {
|
|
1471
|
-
if (/[
|
|
1930
|
+
if (/[msu]/.test(flags)) return null;
|
|
1931
|
+
if (/i/.test(flags)) {
|
|
1932
|
+
const open = literalCodePoints(source);
|
|
1933
|
+
return open ? { kind: "litFold", open } : null;
|
|
1934
|
+
}
|
|
1472
1935
|
return parseScanShape(source);
|
|
1473
1936
|
}
|
|
1474
1937
|
var classCond = (cVar, ranges) => ranges.map(([lo, hi]) => lo === hi ? `${cVar} === ${lo}` : `(${cVar} >= ${lo} && ${cVar} <= ${hi})`).join(" || ");
|
|
@@ -1483,6 +1946,53 @@ function stringHardStop(shape) {
|
|
|
1483
1946
|
}
|
|
1484
1947
|
var codeAt = (start, firstChar) => firstChar ?? `input.charCodeAt(${start})`;
|
|
1485
1948
|
function emitShapeMatch(shape, start, mint, ind2, firstChar) {
|
|
1949
|
+
if (shape.kind === "lookahead") {
|
|
1950
|
+
const inner = emitShapeMatch(shape.inner, start, mint, ind2, firstChar);
|
|
1951
|
+
const okV = mint("_ok");
|
|
1952
|
+
const endV2 = mint("_end");
|
|
1953
|
+
const rawIn = classCond(`input.charCodeAt(${inner.end})`, shape.ranges);
|
|
1954
|
+
const charInClass = shape.classNegated ? `!(${rawIn})` : `(${rawIn})`;
|
|
1955
|
+
const hasMatchingChar = `${inner.end} < input.length && ${charInClass}`;
|
|
1956
|
+
const guardFails = shape.negative ? hasMatchingChar : `!(${hasMatchingChar})`;
|
|
1957
|
+
return {
|
|
1958
|
+
setup: [
|
|
1959
|
+
...inner.setup,
|
|
1960
|
+
`${ind2}let ${okV} = ${inner.ok}`,
|
|
1961
|
+
`${ind2}let ${endV2} = ${inner.end}`,
|
|
1962
|
+
`${ind2}if (${okV} && (${guardFails})) { ${okV} = false; ${endV2} = ${start} }`
|
|
1963
|
+
],
|
|
1964
|
+
ok: okV,
|
|
1965
|
+
end: endV2
|
|
1966
|
+
};
|
|
1967
|
+
}
|
|
1968
|
+
if (shape.kind === "alt") {
|
|
1969
|
+
const okV = mint("_ok");
|
|
1970
|
+
const endV2 = mint("_end");
|
|
1971
|
+
const lines = [`${ind2}let ${okV} = false`, `${ind2}let ${endV2} = ${start}`];
|
|
1972
|
+
if (shape.disjoint) {
|
|
1973
|
+
const c0 = codeAt(start, firstChar);
|
|
1974
|
+
shape.arms.forEach((arm, k) => {
|
|
1975
|
+
const fs2 = shape.firsts[k];
|
|
1976
|
+
const cond = fs2.negated ? `!(${classCond(c0, fs2.ranges)})` : `(${classCond(c0, fs2.ranges)})`;
|
|
1977
|
+
const m = emitShapeMatch(arm, start, mint, `${ind2} `, firstChar);
|
|
1978
|
+
lines.push(`${ind2}${k === 0 ? "if" : "else if"} (${start} < input.length && ${cond}) {`);
|
|
1979
|
+
lines.push(...m.setup);
|
|
1980
|
+
lines.push(`${ind2} ${okV} = ${m.ok}`);
|
|
1981
|
+
lines.push(`${ind2} ${endV2} = ${m.ok} ? ${m.end} : ${start}`);
|
|
1982
|
+
lines.push(`${ind2}}`);
|
|
1983
|
+
});
|
|
1984
|
+
} else {
|
|
1985
|
+
const lbl = mint("_alt");
|
|
1986
|
+
lines.push(`${ind2}${lbl}: {`);
|
|
1987
|
+
for (const arm of shape.arms) {
|
|
1988
|
+
const m = emitShapeMatch(arm, start, mint, `${ind2} `, firstChar);
|
|
1989
|
+
lines.push(...m.setup);
|
|
1990
|
+
lines.push(`${ind2} if (${m.ok}) { ${okV} = true; ${endV2} = ${m.end}; break ${lbl} }`);
|
|
1991
|
+
}
|
|
1992
|
+
lines.push(`${ind2}}`);
|
|
1993
|
+
}
|
|
1994
|
+
return { setup: lines, ok: okV, end: endV2 };
|
|
1995
|
+
}
|
|
1486
1996
|
if (shape.kind === "chars") {
|
|
1487
1997
|
const cur = mint("_e");
|
|
1488
1998
|
return {
|
|
@@ -1509,6 +2019,82 @@ function emitShapeMatch(shape, start, mint, ind2, firstChar) {
|
|
|
1509
2019
|
end: cur
|
|
1510
2020
|
};
|
|
1511
2021
|
}
|
|
2022
|
+
if (shape.kind === "seq") {
|
|
2023
|
+
const endV2 = mint("_e");
|
|
2024
|
+
const okV = mint("_ok");
|
|
2025
|
+
const runCond = (p, at) => {
|
|
2026
|
+
const c = classCond(`input.charCodeAt(${at})`, p.ranges);
|
|
2027
|
+
return p.negated ? `!(${c})` : `(${c})`;
|
|
2028
|
+
};
|
|
2029
|
+
const lines = [`${ind2}let ${endV2} = ${start}`, `${ind2}let ${okV} = false`, `${ind2}do {`];
|
|
2030
|
+
let first = true;
|
|
2031
|
+
for (const p of shape.parts) {
|
|
2032
|
+
if (p.part === "lit") {
|
|
2033
|
+
const L = p.cps.length;
|
|
2034
|
+
const cond = litCond(endV2, p.cps, first ? firstChar : void 0);
|
|
2035
|
+
if (p.optional) {
|
|
2036
|
+
lines.push(`${ind2} if (${endV2} + ${L} <= input.length && (${cond})) ${endV2} += ${L}`);
|
|
2037
|
+
} else {
|
|
2038
|
+
lines.push(`${ind2} if (!(${endV2} + ${L} <= input.length && (${cond}))) break`);
|
|
2039
|
+
lines.push(`${ind2} ${endV2} += ${L}`);
|
|
2040
|
+
}
|
|
2041
|
+
} else if (p.part === "run" && !p.unbounded) {
|
|
2042
|
+
if (p.min === 1) {
|
|
2043
|
+
lines.push(`${ind2} if (!(${endV2} < input.length && ${runCond(p, endV2)})) break`);
|
|
2044
|
+
lines.push(`${ind2} ${endV2}++`);
|
|
2045
|
+
} else {
|
|
2046
|
+
lines.push(`${ind2} if (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
2047
|
+
}
|
|
2048
|
+
} else if (p.part === "run") {
|
|
2049
|
+
const s = mint("_s");
|
|
2050
|
+
lines.push(`${ind2} const ${s} = ${endV2}`);
|
|
2051
|
+
lines.push(`${ind2} while (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
2052
|
+
if (p.min === 1) lines.push(`${ind2} if (${endV2} === ${s}) break`);
|
|
2053
|
+
} else {
|
|
2054
|
+
const inner = emitShapeMatch(p.inner, endV2, mint, `${ind2} `, first ? firstChar : void 0);
|
|
2055
|
+
if (!p.unbounded) {
|
|
2056
|
+
lines.push(...inner.setup);
|
|
2057
|
+
if (p.min === 1) {
|
|
2058
|
+
lines.push(`${ind2} if (!(${inner.ok})) break`);
|
|
2059
|
+
lines.push(`${ind2} ${endV2} = ${inner.end}`);
|
|
2060
|
+
} else {
|
|
2061
|
+
lines.push(`${ind2} if (${inner.ok}) ${endV2} = ${inner.end}`);
|
|
2062
|
+
}
|
|
2063
|
+
} else {
|
|
2064
|
+
const progV = mint("_prog");
|
|
2065
|
+
lines.push(`${ind2} let ${progV} = false`);
|
|
2066
|
+
lines.push(`${ind2} while (true) {`);
|
|
2067
|
+
lines.push(...inner.setup);
|
|
2068
|
+
lines.push(`${ind2} if (!(${inner.ok})) break`);
|
|
2069
|
+
lines.push(`${ind2} ${endV2} = ${inner.end}`);
|
|
2070
|
+
lines.push(`${ind2} ${progV} = true`);
|
|
2071
|
+
lines.push(`${ind2} }`);
|
|
2072
|
+
if (p.min === 1) lines.push(`${ind2} if (!${progV}) break`);
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
first = false;
|
|
2076
|
+
}
|
|
2077
|
+
lines.push(`${ind2} ${okV} = true`);
|
|
2078
|
+
lines.push(`${ind2}} while (false)`);
|
|
2079
|
+
lines.push(`${ind2}if (!${okV}) ${endV2} = ${start}`);
|
|
2080
|
+
return { setup: lines, ok: okV, end: endV2 };
|
|
2081
|
+
}
|
|
2082
|
+
if (shape.kind === "litFold") {
|
|
2083
|
+
const openLen2 = shape.open.length;
|
|
2084
|
+
const endV2 = mint("_end");
|
|
2085
|
+
const checks = shape.open.map((cp, k) => {
|
|
2086
|
+
const cVar = k === 0 && firstChar ? firstChar : `input.charCodeAt(${start} + ${k})`;
|
|
2087
|
+
return foldEq(cVar, cp);
|
|
2088
|
+
});
|
|
2089
|
+
return {
|
|
2090
|
+
setup: [
|
|
2091
|
+
`${ind2}let ${endV2} = ${start}`,
|
|
2092
|
+
`${ind2}if (${start} + ${openLen2} <= input.length && (${checks.join(" && ")})) ${endV2} = ${start} + ${openLen2}`
|
|
2093
|
+
],
|
|
2094
|
+
ok: `${endV2} > ${start}`,
|
|
2095
|
+
end: endV2
|
|
2096
|
+
};
|
|
2097
|
+
}
|
|
1512
2098
|
if (shape.kind === "until") {
|
|
1513
2099
|
const j2 = mint("_j");
|
|
1514
2100
|
const openLen2 = shape.open.length;
|
|
@@ -1904,7 +2490,7 @@ function hoistExpected(ctx, constArrSource) {
|
|
|
1904
2490
|
let name = ctx.expectedMap.get(constArrSource);
|
|
1905
2491
|
if (name === void 0) {
|
|
1906
2492
|
name = `_fx${ctx.expectedDecls.length}`;
|
|
1907
|
-
ctx.expectedDecls.push(`const ${name} =
|
|
2493
|
+
ctx.expectedDecls.push(`const ${name} = ${constArrSource}`);
|
|
1908
2494
|
ctx.expectedMap.set(constArrSource, name);
|
|
1909
2495
|
}
|
|
1910
2496
|
return name;
|
|
@@ -2085,10 +2671,10 @@ function ensureTriviaFn(ctx) {
|
|
|
2085
2671
|
function ensureTriviaCaptureFn(ctx) {
|
|
2086
2672
|
return ensureTriviaFn(ctx);
|
|
2087
2673
|
}
|
|
2088
|
-
function firstSetCond(codeVar,
|
|
2089
|
-
if (
|
|
2090
|
-
if (
|
|
2091
|
-
return
|
|
2674
|
+
function firstSetCond(codeVar, fs2) {
|
|
2675
|
+
if (fs2.kind === "any") return "true";
|
|
2676
|
+
if (fs2.kind === "empty") return "false";
|
|
2677
|
+
return fs2.ranges.map(
|
|
2092
2678
|
(r) => r.lo === r.hi ? `${codeVar} === ${r.lo}` : `(${codeVar} >= ${r.lo} && ${codeVar} <= ${r.hi})`
|
|
2093
2679
|
).join(" || ");
|
|
2094
2680
|
}
|
|
@@ -2100,10 +2686,10 @@ function planDisjointDispatch(parsers) {
|
|
|
2100
2686
|
const cases = [];
|
|
2101
2687
|
let total = 0;
|
|
2102
2688
|
for (const p of parsers) {
|
|
2103
|
-
const
|
|
2104
|
-
if (
|
|
2689
|
+
const fs2 = p._meta.firstSet;
|
|
2690
|
+
if (fs2.kind !== "ranges") return { kind: "if" };
|
|
2105
2691
|
const pts = [];
|
|
2106
|
-
for (const r of
|
|
2692
|
+
for (const r of fs2.ranges) {
|
|
2107
2693
|
if (r.hi - r.lo + 1 > SWITCH_RANGE_LIMIT) return { kind: "if" };
|
|
2108
2694
|
for (let cp = r.lo; cp <= r.hi; cp++) pts.push(cp);
|
|
2109
2695
|
}
|
|
@@ -2226,18 +2812,21 @@ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
2226
2812
|
return true;
|
|
2227
2813
|
}
|
|
2228
2814
|
}
|
|
2229
|
-
function emitFallible(inner, ctx, pos) {
|
|
2815
|
+
function emitFallible(inner, ctx, pos, swallow = false) {
|
|
2230
2816
|
const lbl = v(ctx, "_lbl");
|
|
2231
2817
|
const okV = `${lbl}ok`;
|
|
2232
2818
|
const valV = `${lbl}v`;
|
|
2233
2819
|
const endV = `${lbl}e`;
|
|
2234
2820
|
const savedLabel = ctx.failLabel;
|
|
2235
2821
|
const savedIndent = ctx.indent;
|
|
2822
|
+
const savedRecord = ctx.recordFail;
|
|
2236
2823
|
ctx.failLabel = lbl;
|
|
2237
2824
|
ctx.indent = savedIndent + 1;
|
|
2825
|
+
if (swallow) ctx.recordFail = false;
|
|
2238
2826
|
const r = emit(inner, ctx, pos);
|
|
2239
2827
|
ctx.failLabel = savedLabel;
|
|
2240
2828
|
ctx.indent = savedIndent;
|
|
2829
|
+
ctx.recordFail = savedRecord;
|
|
2241
2830
|
const ind0 = ind(ctx);
|
|
2242
2831
|
const needsRollback = ctx.capturing && mayLeavePartialCapture(inner);
|
|
2243
2832
|
const mL = needsRollback ? v(ctx, "_fcl") : null;
|
|
@@ -2260,6 +2849,7 @@ function emitFallible(inner, ctx, pos) {
|
|
|
2260
2849
|
];
|
|
2261
2850
|
return { stmts, okVar: okV, valVar: valV, endVar: endV };
|
|
2262
2851
|
}
|
|
2852
|
+
var CHARCODE_CHAIN_MAX = 16;
|
|
2263
2853
|
function emitLit(def, ctx, pos) {
|
|
2264
2854
|
const { value, caseInsensitive } = def;
|
|
2265
2855
|
const len = value.length;
|
|
@@ -2282,7 +2872,7 @@ function emitLit(def, ctx, pos) {
|
|
|
2282
2872
|
...emitIfFail(ctx, `${pos} >= input.length || input.charCodeAt(${pos}) !== ${code}`, failBody(ctx, expectedStr, pos)),
|
|
2283
2873
|
`${ind(ctx)}const ${vv} = ${JSON.stringify(value)}`
|
|
2284
2874
|
);
|
|
2285
|
-
} else if (len <=
|
|
2875
|
+
} else if (len <= CHARCODE_CHAIN_MAX) {
|
|
2286
2876
|
const checks = Array.from(
|
|
2287
2877
|
{ length: len },
|
|
2288
2878
|
(_, i) => `input.charCodeAt(${pos}${i > 0 ? ` + ${i}` : ""}) !== ${value.codePointAt(i)}`
|
|
@@ -2304,7 +2894,55 @@ function emitLit(def, ctx, pos) {
|
|
|
2304
2894
|
function escapeKeywordRe(s) {
|
|
2305
2895
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2306
2896
|
}
|
|
2897
|
+
function emitKeywordsFast(def, ctx, pos) {
|
|
2898
|
+
if (def.words.length === 0 || def.words.some((w) => w.length === 0)) return null;
|
|
2899
|
+
if (def.words.some((w) => Array.from(w).length !== w.length)) return null;
|
|
2900
|
+
if (def.caseInsensitive && def.boundary) return null;
|
|
2901
|
+
let boundary = null;
|
|
2902
|
+
if (def.boundary) {
|
|
2903
|
+
let body = def.boundary;
|
|
2904
|
+
const negated = body.startsWith("^");
|
|
2905
|
+
if (negated) body = body.slice(1);
|
|
2906
|
+
const ranges = parseClassRanges(body);
|
|
2907
|
+
if (!ranges) return null;
|
|
2908
|
+
boundary = { ranges, negated };
|
|
2909
|
+
}
|
|
2910
|
+
const mint = (prefix = "_v") => v(ctx, prefix);
|
|
2911
|
+
const lbl = v(ctx, "_kwLbl");
|
|
2912
|
+
const valV = v(ctx, "_kwv");
|
|
2913
|
+
const endV = v(ctx, "_kwe");
|
|
2914
|
+
const bodyInd = ind(ctx) + " ";
|
|
2915
|
+
const tries = [];
|
|
2916
|
+
for (const w of def.words) {
|
|
2917
|
+
const cps = Array.from(w, (ch) => ch.codePointAt(0));
|
|
2918
|
+
let shape = def.caseInsensitive ? { kind: "litFold", open: cps } : { kind: "seq", parts: [{ part: "lit", cps, optional: false }] };
|
|
2919
|
+
if (boundary) {
|
|
2920
|
+
shape = { kind: "lookahead", inner: shape, ranges: boundary.ranges, classNegated: boundary.negated, negative: true };
|
|
2921
|
+
}
|
|
2922
|
+
const m = emitShapeMatch(shape, pos, mint, bodyInd);
|
|
2923
|
+
tries.push(
|
|
2924
|
+
...m.setup,
|
|
2925
|
+
// Slice from input rather than reusing the literal word: `caseInsensitive`
|
|
2926
|
+
// must return the text as it actually appeared (e.g. "ABC" for keyword
|
|
2927
|
+
// "abc"), matching what the original `RegExp.exec()[0]` returned.
|
|
2928
|
+
`${bodyInd}if (${m.ok}) { ${valV} = input.slice(${pos}, ${m.end}); ${endV} = ${m.end}; break ${lbl} }`
|
|
2929
|
+
);
|
|
2930
|
+
}
|
|
2931
|
+
const stmts = [
|
|
2932
|
+
`${ind(ctx)}let ${valV} = '', ${endV} = ${pos}`,
|
|
2933
|
+
`${ind(ctx)}${lbl}: {`,
|
|
2934
|
+
...tries,
|
|
2935
|
+
`${ind(ctx)}}`,
|
|
2936
|
+
// Every word has length >= 1 (checked above), so a real match always
|
|
2937
|
+
// advances past `pos` — `endV === pos` only happens when no candidate matched.
|
|
2938
|
+
...emitIfFail(ctx, `${endV} === ${pos}`, failBody(ctx, '"keyword"', pos))
|
|
2939
|
+
];
|
|
2940
|
+
stmts.push(...emitLeafCapture(ctx, valV, pos, endV));
|
|
2941
|
+
return { stmts, valueVar: valV, endVar: endV };
|
|
2942
|
+
}
|
|
2307
2943
|
function emitKeywords(def, ctx, pos) {
|
|
2944
|
+
const fast = emitKeywordsFast(def, ctx, pos);
|
|
2945
|
+
if (fast) return fast;
|
|
2308
2946
|
const alt = def.words.map(escapeKeywordRe).join("|");
|
|
2309
2947
|
const boundary = def.boundary ? `(?![${def.boundary}])` : "";
|
|
2310
2948
|
const flags = def.caseInsensitive ? "iuy" : "uy";
|
|
@@ -2435,6 +3073,31 @@ function failsAtStart(p) {
|
|
|
2435
3073
|
return false;
|
|
2436
3074
|
}
|
|
2437
3075
|
}
|
|
3076
|
+
function armStaticExpected(ctx, p) {
|
|
3077
|
+
return hoistExpected(ctx, staticExpectedArr([p]));
|
|
3078
|
+
}
|
|
3079
|
+
function canMatchEmptyAtStart(p) {
|
|
3080
|
+
const d = p._def;
|
|
3081
|
+
switch (d.tag) {
|
|
3082
|
+
case "regex":
|
|
3083
|
+
return /(?:[*?]|\{0,|\{\d*,)/.test(d.source);
|
|
3084
|
+
case "optional":
|
|
3085
|
+
return true;
|
|
3086
|
+
case "many":
|
|
3087
|
+
return true;
|
|
3088
|
+
case "transform":
|
|
3089
|
+
case "label":
|
|
3090
|
+
return canMatchEmptyAtStart(d.parser);
|
|
3091
|
+
case "literal":
|
|
3092
|
+
return d.value.length === 0;
|
|
3093
|
+
default:
|
|
3094
|
+
return false;
|
|
3095
|
+
}
|
|
3096
|
+
}
|
|
3097
|
+
function needsFirstSetGuard(p) {
|
|
3098
|
+
const fs2 = p._meta.firstSet;
|
|
3099
|
+
return fs2.kind !== "any" && !canMatchEmptyAtStart(p);
|
|
3100
|
+
}
|
|
2438
3101
|
function emitDisjointArm(p, ctx, pos, valV, endV) {
|
|
2439
3102
|
if (failsAtStart(p)) {
|
|
2440
3103
|
const r = emit(p, ctx, pos);
|
|
@@ -2576,16 +3239,21 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
2576
3239
|
const resValV = v(ctx, "_crv");
|
|
2577
3240
|
const resEndV = v(ctx, "_cre");
|
|
2578
3241
|
const resOkV = v(ctx, "_crok");
|
|
3242
|
+
const codeV = v(ctx, "_chcode");
|
|
2579
3243
|
const slots = def.parsers.map(() => v(ctx, "_cfx"));
|
|
2580
3244
|
const ind0 = ind(ctx);
|
|
2581
3245
|
const stmts = [
|
|
2582
3246
|
`${ind0}let ${resValV}, ${resEndV} = ${pos}, ${resOkV} = false`,
|
|
2583
|
-
`${ind0}let ${slots.join(", ")}
|
|
3247
|
+
`${ind0}let ${slots.join(", ")}`,
|
|
3248
|
+
`${ind0}const ${codeV} = ${pos} < input.length ? (input.codePointAt(${pos}) ?? -1) : -1`
|
|
2584
3249
|
];
|
|
2585
3250
|
for (let i = 0; i < def.parsers.length; i++) {
|
|
2586
3251
|
const p = def.parsers[i];
|
|
2587
3252
|
const gate = def.gates[i];
|
|
2588
3253
|
const autoNot = def.autoNot[i];
|
|
3254
|
+
const atStart = failsAtStart(p);
|
|
3255
|
+
const staticFx = armStaticExpected(ctx, p);
|
|
3256
|
+
const fsGuard = needsFirstSetGuard(p) ? firstSetCond(codeV, p._meta.firstSet) : null;
|
|
2589
3257
|
let gateCond = null;
|
|
2590
3258
|
if (gate) {
|
|
2591
3259
|
const gateIdx = ctx.mapFns.length;
|
|
@@ -2600,39 +3268,41 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
2600
3268
|
const markTl = armNeedsRollback ? v(ctx, "_cmtl") : null;
|
|
2601
3269
|
const markLog = armNeedsRollback ? v(ctx, "_cmlg") : null;
|
|
2602
3270
|
const rollback = markLeaves ? captureRestoreBody(markLeaves, markRaw, markTl, markLog) : "";
|
|
3271
|
+
const failSlot = atStart ? staticFx : "_ctx._fx";
|
|
2603
3272
|
stmts.push(`${ind0}if (${skipCond}) {`);
|
|
2604
|
-
ctx
|
|
2605
|
-
|
|
3273
|
+
if (fsGuard) stmts.push(`${ind(ctx)}if (${fsGuard}) {`);
|
|
3274
|
+
ctx.indent += fsGuard ? 2 : 1;
|
|
2606
3275
|
if (markLeaves) {
|
|
2607
3276
|
stmts.push(
|
|
2608
|
-
`${
|
|
2609
|
-
`${
|
|
2610
|
-
`${
|
|
2611
|
-
`${
|
|
3277
|
+
`${ind(ctx)}const ${markLeaves} = _ctx._cstLeaves?.length ?? 0`,
|
|
3278
|
+
`${ind(ctx)}const ${markRaw} = _ctx._cstRawChildren?.length ?? 0`,
|
|
3279
|
+
`${ind(ctx)}const ${markTl} = _ctx._cstTriviaLog?.length ?? 0`,
|
|
3280
|
+
`${ind(ctx)}const ${markLog} = _ctx._triviaLog?.length ?? 0`
|
|
2612
3281
|
);
|
|
2613
3282
|
}
|
|
2614
|
-
const { stmts: armStmts, okVar, valVar, endVar } = emitFallible(p, ctx, pos);
|
|
3283
|
+
const { stmts: armStmts, okVar, valVar, endVar } = emitFallible(p, ctx, pos, atStart);
|
|
2615
3284
|
stmts.push(...armStmts);
|
|
2616
|
-
ctx.indent--;
|
|
2617
3285
|
if (autoNot && autoNot.length > 0) {
|
|
2618
3286
|
const anCode = v(ctx, "_anc");
|
|
2619
3287
|
const rejectCond = autoNot.map(
|
|
2620
3288
|
(check) => check.kind === "firstSet" ? firstSetCond(anCode, check.set) : `input.startsWith(${JSON.stringify(check.value)}, ${endVar})`
|
|
2621
3289
|
).join(" || ");
|
|
2622
|
-
stmts.push(`${
|
|
2623
|
-
stmts.push(`${
|
|
2624
|
-
stmts.push(`${
|
|
2625
|
-
stmts.push(`${
|
|
2626
|
-
stmts.push(`${
|
|
2627
|
-
stmts.push(`${
|
|
2628
|
-
stmts.push(`${
|
|
2629
|
-
stmts.push(`${
|
|
2630
|
-
stmts.push(`${
|
|
2631
|
-
if (rollback) stmts.push(`${
|
|
3290
|
+
stmts.push(`${ind(ctx)}if (${okVar}) {`);
|
|
3291
|
+
stmts.push(`${ind(ctx)} const ${anCode} = ${endVar} < input.length ? input.charCodeAt(${endVar}) : -1`);
|
|
3292
|
+
stmts.push(`${ind(ctx)} if (!(${rejectCond})) {`);
|
|
3293
|
+
stmts.push(`${ind(ctx)} ${resValV} = ${valVar}`);
|
|
3294
|
+
stmts.push(`${ind(ctx)} ${resEndV} = ${endVar}`);
|
|
3295
|
+
stmts.push(`${ind(ctx)} ${resOkV} = true`);
|
|
3296
|
+
stmts.push(`${ind(ctx)} }`);
|
|
3297
|
+
stmts.push(`${ind(ctx)}}`);
|
|
3298
|
+
stmts.push(`${ind(ctx)}else { ${slots[i]} = ${failSlot} }`);
|
|
3299
|
+
if (rollback) stmts.push(`${ind(ctx)}if (!${resOkV}) { ${rollback} }`);
|
|
2632
3300
|
} else {
|
|
2633
|
-
stmts.push(`${
|
|
2634
|
-
stmts.push(`${
|
|
3301
|
+
stmts.push(`${ind(ctx)}if (${okVar}) { ${resValV} = ${valVar}; ${resEndV} = ${endVar}; ${resOkV} = true }`);
|
|
3302
|
+
stmts.push(`${ind(ctx)}else { ${slots[i]} = ${failSlot}${rollback ? `; ${rollback}` : ""} }`);
|
|
2635
3303
|
}
|
|
3304
|
+
ctx.indent -= fsGuard ? 2 : 1;
|
|
3305
|
+
if (fsGuard) stmts.push(`${ind(ctx)}} else { ${slots[i]} = ${staticFx} }`);
|
|
2636
3306
|
stmts.push(`${ind0}}`);
|
|
2637
3307
|
}
|
|
2638
3308
|
const concatExpr = `[${slots.map((s) => `...(${s} || [])`).join(", ")}]`;
|
|
@@ -2665,7 +3335,7 @@ function emitTransformChain(p, baseValue, endV, startPos, ctx) {
|
|
|
2665
3335
|
function emitLiteralCondition(litVal, pos) {
|
|
2666
3336
|
const len = litVal.length;
|
|
2667
3337
|
if (len === 0) return "true";
|
|
2668
|
-
if (len >
|
|
3338
|
+
if (len > CHARCODE_CHAIN_MAX) return `input.startsWith(${JSON.stringify(litVal)}, ${pos})`;
|
|
2669
3339
|
const checks = [`${pos} + ${len} <= input.length`];
|
|
2670
3340
|
for (let i = 0; i < len; i++) {
|
|
2671
3341
|
const code = litVal.codePointAt(i);
|
|
@@ -2714,7 +3384,7 @@ function emitMany(def, ctx, pos) {
|
|
|
2714
3384
|
itemPos = npV;
|
|
2715
3385
|
}
|
|
2716
3386
|
}
|
|
2717
|
-
const { stmts: iterStmts, okVar: iterOk, valVar: iterVal, endVar: iterEnd } = emitFallible(def.parser, ctx, itemPos);
|
|
3387
|
+
const { stmts: iterStmts, okVar: iterOk, valVar: iterVal, endVar: iterEnd } = emitFallible(def.parser, ctx, itemPos, true);
|
|
2718
3388
|
stmts.push(
|
|
2719
3389
|
...iterStmts,
|
|
2720
3390
|
`${ind(ctx)}if (!${iterOk} || ${iterEnd} <= ${itemPos}) { ${rollback}break }`,
|
|
@@ -2728,7 +3398,7 @@ function emitMany(def, ctx, pos) {
|
|
|
2728
3398
|
function emitOptional(def, ctx, pos) {
|
|
2729
3399
|
const valV = v(ctx, "_opt");
|
|
2730
3400
|
const endV = v(ctx, "_opte");
|
|
2731
|
-
const { stmts: lblStmts, okVar, valVar, endVar } = emitFallible(def.parser, ctx, pos);
|
|
3401
|
+
const { stmts: lblStmts, okVar, valVar, endVar } = emitFallible(def.parser, ctx, pos, true);
|
|
2732
3402
|
const ind0 = ind(ctx);
|
|
2733
3403
|
const stmts = [
|
|
2734
3404
|
...lblStmts,
|
|
@@ -2740,7 +3410,7 @@ function emitOptional(def, ctx, pos) {
|
|
|
2740
3410
|
function emitSepBy(_p, def, ctx, pos) {
|
|
2741
3411
|
const arrV = v(ctx, "_arr");
|
|
2742
3412
|
const curV = v(ctx, "_cur");
|
|
2743
|
-
const { stmts: firstStmts, okVar: firstOk, valVar: firstVal, endVar: firstEnd } = emitFallible(def.parser, ctx, pos);
|
|
3413
|
+
const { stmts: firstStmts, okVar: firstOk, valVar: firstVal, endVar: firstEnd } = emitFallible(def.parser, ctx, pos, true);
|
|
2744
3414
|
const stmts = [
|
|
2745
3415
|
`${ind(ctx)}const ${arrV} = []`,
|
|
2746
3416
|
`${ind(ctx)}let ${curV} = ${pos}`,
|
|
@@ -2772,11 +3442,11 @@ function emitSepBy(_p, def, ctx, pos) {
|
|
|
2772
3442
|
);
|
|
2773
3443
|
sepAtPos = spV;
|
|
2774
3444
|
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}; `;
|
|
2775
|
-
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos);
|
|
3445
|
+
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos, true);
|
|
2776
3446
|
stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) { ${rollbackToSep}break }`);
|
|
2777
3447
|
const npV = v(ctx, "_np");
|
|
2778
3448
|
stmts.push(`${ind(ctx)}const ${npV} = ${capFn}(input, ${sepEnd}, _ctx, 1)`);
|
|
2779
|
-
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, npV);
|
|
3449
|
+
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, npV, true);
|
|
2780
3450
|
stmts.push(
|
|
2781
3451
|
...nextStmts,
|
|
2782
3452
|
// item failed → unwind the separator too, back to the end of the last item
|
|
@@ -2789,11 +3459,11 @@ function emitSepBy(_p, def, ctx, pos) {
|
|
|
2789
3459
|
const spV = v(ctx, "_sp");
|
|
2790
3460
|
stmts.push(`${ind(ctx)}const ${spV} = ${trivFn}(input, ${curV}, _ctx)`);
|
|
2791
3461
|
sepAtPos = spV;
|
|
2792
|
-
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos);
|
|
3462
|
+
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos, true);
|
|
2793
3463
|
stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) break`);
|
|
2794
3464
|
const npV = v(ctx, "_np");
|
|
2795
3465
|
stmts.push(`${ind(ctx)}const ${npV} = ${trivFn}(input, ${sepEnd}, _ctx)`);
|
|
2796
|
-
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, npV);
|
|
3466
|
+
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, npV, true);
|
|
2797
3467
|
stmts.push(
|
|
2798
3468
|
...nextStmts,
|
|
2799
3469
|
`${ind(ctx)}if (!${nextOk}) break`,
|
|
@@ -2810,10 +3480,10 @@ function emitSepBy(_p, def, ctx, pos) {
|
|
|
2810
3480
|
`${ind(ctx)}const ${markRw} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`
|
|
2811
3481
|
);
|
|
2812
3482
|
}
|
|
2813
|
-
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos);
|
|
3483
|
+
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos, true);
|
|
2814
3484
|
stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) break`);
|
|
2815
3485
|
const nextRb = markLv ? `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${markLv}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markRw}; ` : "";
|
|
2816
|
-
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, sepEnd);
|
|
3486
|
+
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, sepEnd, true);
|
|
2817
3487
|
stmts.push(
|
|
2818
3488
|
...nextStmts,
|
|
2819
3489
|
`${ind(ctx)}if (!${nextOk}) { ${nextRb}break }`,
|
|
@@ -2871,7 +3541,7 @@ function emitScanTo(def, ctx, pos) {
|
|
|
2871
3541
|
return { stmts, valueVar: valV, endVar: curV };
|
|
2872
3542
|
}
|
|
2873
3543
|
function emitNot(def, ctx, pos) {
|
|
2874
|
-
const { stmts, okVar } = emitFallible(def.parser, ctx, pos);
|
|
3544
|
+
const { stmts, okVar } = emitFallible(def.parser, ctx, pos, true);
|
|
2875
3545
|
const label2 = JSON.stringify(`not(${def.parser._tag})`);
|
|
2876
3546
|
return {
|
|
2877
3547
|
stmts: [
|
|
@@ -2962,11 +3632,14 @@ function emitLazy(p, def, ctx, pos) {
|
|
|
2962
3632
|
}
|
|
2963
3633
|
const savedIndent = ctx.indent;
|
|
2964
3634
|
const savedFailLabel = ctx.failLabel;
|
|
3635
|
+
const savedRecord = ctx.recordFail;
|
|
2965
3636
|
ctx.indent = 1;
|
|
2966
3637
|
ctx.failLabel = "_pfail";
|
|
3638
|
+
ctx.recordFail = true;
|
|
2967
3639
|
const r = emit(resolved, ctx, "_pos");
|
|
2968
3640
|
ctx.indent = savedIndent;
|
|
2969
3641
|
ctx.failLabel = savedFailLabel;
|
|
3642
|
+
ctx.recordFail = savedRecord;
|
|
2970
3643
|
pushNamedFnDecl(ctx, fnName2, r.stmts, r.valueVar, r.endVar);
|
|
2971
3644
|
}
|
|
2972
3645
|
const fnName = ctx.namedParsers.get(p);
|
|
@@ -3146,11 +3819,14 @@ function emit(p, ctx, pos) {
|
|
|
3146
3819
|
ctx.namedParsers.set(innerParser, fnName);
|
|
3147
3820
|
const savedIndent = ctx.indent;
|
|
3148
3821
|
const savedFailLabel = ctx.failLabel;
|
|
3822
|
+
const savedRecord = ctx.recordFail;
|
|
3149
3823
|
ctx.indent = 1;
|
|
3150
3824
|
ctx.failLabel = "_pfail";
|
|
3825
|
+
ctx.recordFail = true;
|
|
3151
3826
|
const innerR = emit(innerParser, ctx, "_pos");
|
|
3152
3827
|
ctx.indent = savedIndent;
|
|
3153
3828
|
ctx.failLabel = savedFailLabel;
|
|
3829
|
+
ctx.recordFail = savedRecord;
|
|
3154
3830
|
pushNamedFnDecl(ctx, fnName, innerR.stmts, innerR.valueVar, innerR.endVar);
|
|
3155
3831
|
}
|
|
3156
3832
|
const fn = ctx.namedParsers.get(innerParser);
|
|
@@ -3298,6 +3974,7 @@ function compile(combinator, mapFnSources) {
|
|
|
3298
3974
|
regexMap: /* @__PURE__ */ new Map(),
|
|
3299
3975
|
expectedDecls: [],
|
|
3300
3976
|
expectedMap: /* @__PURE__ */ new Map(),
|
|
3977
|
+
recordFail: true,
|
|
3301
3978
|
mapFns: [],
|
|
3302
3979
|
mapFnSrcs: [],
|
|
3303
3980
|
buildFns: [],
|
|
@@ -3380,6 +4057,7 @@ function compileRuleMap(ruleMap) {
|
|
|
3380
4057
|
regexMap: /* @__PURE__ */ new Map(),
|
|
3381
4058
|
expectedDecls: [],
|
|
3382
4059
|
expectedMap: /* @__PURE__ */ new Map(),
|
|
4060
|
+
recordFail: true,
|
|
3383
4061
|
mapFns: [],
|
|
3384
4062
|
mapFnSrcs: [],
|
|
3385
4063
|
buildFns: [],
|
|
@@ -3554,11 +4232,11 @@ function balanced(open, close, options = {}) {
|
|
|
3554
4232
|
return combi;
|
|
3555
4233
|
}
|
|
3556
4234
|
function firstSetClassChars(c) {
|
|
3557
|
-
const
|
|
3558
|
-
if (
|
|
3559
|
-
if (
|
|
4235
|
+
const fs2 = c._meta.firstSet;
|
|
4236
|
+
if (fs2.kind === "empty") return [];
|
|
4237
|
+
if (fs2.kind !== "ranges") return null;
|
|
3560
4238
|
const out = [];
|
|
3561
|
-
for (const { lo, hi } of
|
|
4239
|
+
for (const { lo, hi } of fs2.ranges) {
|
|
3562
4240
|
if (hi - lo > 8) return null;
|
|
3563
4241
|
for (let cp = lo; cp <= hi; cp++) out.push(String.fromCodePoint(cp));
|
|
3564
4242
|
}
|
|
@@ -3862,7 +4540,117 @@ function evaluateCombinatorArray(node2, scope, code) {
|
|
|
3862
4540
|
if (!val.every(isCombinator)) return null;
|
|
3863
4541
|
return val;
|
|
3864
4542
|
}
|
|
3865
|
-
function
|
|
4543
|
+
function asFragmentFactory(expr) {
|
|
4544
|
+
if (expr.type !== "ArrowFunctionExpression" && expr.type !== "FunctionExpression" && expr.type !== "FunctionDeclaration") return null;
|
|
4545
|
+
const fn = expr;
|
|
4546
|
+
return factoryBodyAndReturn(fn) ? fn : null;
|
|
4547
|
+
}
|
|
4548
|
+
var unwrapParen = (e) => e && e.type === "ParenthesizedExpression" ? e.expression : e;
|
|
4549
|
+
function factoryBodyAndReturn(fn) {
|
|
4550
|
+
const body = fn.body;
|
|
4551
|
+
if (!body) return null;
|
|
4552
|
+
const b = unwrapParen(body);
|
|
4553
|
+
if (b.type === "ObjectExpression") return { statements: [], retObj: b };
|
|
4554
|
+
if (b.type === "BlockStatement") {
|
|
4555
|
+
const statements = [];
|
|
4556
|
+
for (const stmt of b.body) {
|
|
4557
|
+
if (stmt.type === "ReturnStatement") {
|
|
4558
|
+
const a = unwrapParen(stmt.argument);
|
|
4559
|
+
if (!a || a.type !== "ObjectExpression") return null;
|
|
4560
|
+
return { statements, retObj: a };
|
|
4561
|
+
}
|
|
4562
|
+
if (stmt.type === "VariableDeclaration") statements.push(stmt);
|
|
4563
|
+
else return null;
|
|
4564
|
+
}
|
|
4565
|
+
}
|
|
4566
|
+
return null;
|
|
4567
|
+
}
|
|
4568
|
+
function spreadFactoryCall(spread, resolve) {
|
|
4569
|
+
const call = spread.argument;
|
|
4570
|
+
if (!call || call.type !== "CallExpression") return null;
|
|
4571
|
+
if (!call.callee || call.callee.type !== "Identifier" || !call.callee.name) return null;
|
|
4572
|
+
const resolved = resolve(call.callee.name);
|
|
4573
|
+
return resolved ? { fn: resolved.fn, args: call.arguments ?? [], code: resolved.code } : null;
|
|
4574
|
+
}
|
|
4575
|
+
function factoryCallScope(fn, args, outer) {
|
|
4576
|
+
const s = new Map(outer);
|
|
4577
|
+
const params = fn.params ?? [];
|
|
4578
|
+
for (let i = 0; i < params.length; i++) {
|
|
4579
|
+
const pn = params[i];
|
|
4580
|
+
if (!pn || pn.type !== "Identifier" || !pn.name) continue;
|
|
4581
|
+
const arg = args[i];
|
|
4582
|
+
if (arg && arg.type === "Identifier" && arg.name && outer.has(arg.name)) {
|
|
4583
|
+
s.set(pn.name, outer.get(arg.name));
|
|
4584
|
+
}
|
|
4585
|
+
}
|
|
4586
|
+
return s;
|
|
4587
|
+
}
|
|
4588
|
+
function propKey(prop) {
|
|
4589
|
+
if (prop.type !== "Property" || prop.computed || !prop.key) return null;
|
|
4590
|
+
if (prop.key.type === "Identifier") return prop.key.name ?? null;
|
|
4591
|
+
if (prop.key.type === "Literal") return String(prop.key.value);
|
|
4592
|
+
return null;
|
|
4593
|
+
}
|
|
4594
|
+
function collectRuleKeys(retObj, resolve, seen) {
|
|
4595
|
+
const out = [];
|
|
4596
|
+
for (const prop of retObj.properties) {
|
|
4597
|
+
if (prop.type === "SpreadElement") {
|
|
4598
|
+
const sf = spreadFactoryCall(prop, resolve);
|
|
4599
|
+
if (!sf || seen.has(sf.fn)) return null;
|
|
4600
|
+
const br = factoryBodyAndReturn(sf.fn);
|
|
4601
|
+
if (!br) return null;
|
|
4602
|
+
const nested = collectRuleKeys(br.retObj, resolve, new Set(seen).add(sf.fn));
|
|
4603
|
+
if (!nested) return null;
|
|
4604
|
+
out.push(...nested);
|
|
4605
|
+
continue;
|
|
4606
|
+
}
|
|
4607
|
+
const key = propKey(prop);
|
|
4608
|
+
if (!key) return null;
|
|
4609
|
+
out.push(key);
|
|
4610
|
+
}
|
|
4611
|
+
return out;
|
|
4612
|
+
}
|
|
4613
|
+
function flattenRuleEntries(retObj, scope, code, resolve, seen) {
|
|
4614
|
+
const out = [];
|
|
4615
|
+
for (const prop of retObj.properties) {
|
|
4616
|
+
if (prop.type === "SpreadElement") {
|
|
4617
|
+
const sf = spreadFactoryCall(prop, resolve);
|
|
4618
|
+
if (!sf || seen.has(sf.fn)) return null;
|
|
4619
|
+
const br = factoryBodyAndReturn(sf.fn);
|
|
4620
|
+
if (!br) return null;
|
|
4621
|
+
const fragScope = factoryCallScope(sf.fn, sf.args, scope);
|
|
4622
|
+
if (!evalBodyStatements(br.statements, fragScope, sf.code)) return null;
|
|
4623
|
+
const nested = flattenRuleEntries(br.retObj, fragScope, sf.code, resolve, new Set(seen).add(sf.fn));
|
|
4624
|
+
if (!nested) return null;
|
|
4625
|
+
out.push(...nested);
|
|
4626
|
+
continue;
|
|
4627
|
+
}
|
|
4628
|
+
const key = propKey(prop);
|
|
4629
|
+
if (!key) return null;
|
|
4630
|
+
out.push({ key, value: prop.value, scope, code });
|
|
4631
|
+
}
|
|
4632
|
+
return out;
|
|
4633
|
+
}
|
|
4634
|
+
function evalBodyStatements(statements, scope, code) {
|
|
4635
|
+
const bodyMfs = [];
|
|
4636
|
+
for (const stmt of statements) {
|
|
4637
|
+
for (const d of stmt.declarations) {
|
|
4638
|
+
const decl = d;
|
|
4639
|
+
if (!decl.init) return false;
|
|
4640
|
+
const id = decl.id;
|
|
4641
|
+
if (id.type !== "Identifier" && id.type !== "BindingIdentifier") return false;
|
|
4642
|
+
const name = id.name;
|
|
4643
|
+
const before = bodyMfs.length;
|
|
4644
|
+
const val = anyValue(decl.init, scope, code, bodyMfs);
|
|
4645
|
+
if (val === null) return false;
|
|
4646
|
+
const thisDeclMfSrcs = bodyMfs.slice(before);
|
|
4647
|
+
if (isCombinator(val)) scope.set(name, { combi: val, mfSrcs: thisDeclMfSrcs });
|
|
4648
|
+
else scope.set(name, val);
|
|
4649
|
+
}
|
|
4650
|
+
}
|
|
4651
|
+
return true;
|
|
4652
|
+
}
|
|
4653
|
+
function evaluateParserFactory(factoryNode, scope, code, mapFnSources, resolveFactory = () => null) {
|
|
3866
4654
|
if (factoryNode.type !== "ArrowFunctionExpression" && factoryNode.type !== "FunctionDeclaration" && factoryNode.type !== "FunctionExpression") return null;
|
|
3867
4655
|
const factory = factoryNode;
|
|
3868
4656
|
const params = factory.params;
|
|
@@ -3894,40 +4682,21 @@ function evaluateParserFactory(factoryNode, scope, code, mapFnSources) {
|
|
|
3894
4682
|
if (!returnExpr) return null;
|
|
3895
4683
|
const retObj = returnExpr.type === "ParenthesizedExpression" ? returnExpr.expression : returnExpr;
|
|
3896
4684
|
if (retObj.type !== "ObjectExpression") return null;
|
|
4685
|
+
const keys = collectRuleKeys(retObj, resolveFactory, /* @__PURE__ */ new Set());
|
|
4686
|
+
if (!keys) return null;
|
|
3897
4687
|
const ruleRefs = /* @__PURE__ */ new Map();
|
|
3898
|
-
for (const
|
|
3899
|
-
if (
|
|
3900
|
-
if (prop.computed) return null;
|
|
3901
|
-
const p = prop;
|
|
3902
|
-
const key = p.key.type === "Identifier" ? p.key.name : p.key.type === "Literal" ? String(p.key.value) : null;
|
|
3903
|
-
if (!key) return null;
|
|
3904
|
-
ruleRefs.set(key, ref());
|
|
4688
|
+
for (const key of keys) {
|
|
4689
|
+
if (!ruleRefs.has(key)) ruleRefs.set(key, ref());
|
|
3905
4690
|
}
|
|
3906
4691
|
const localScope = new Map(scope);
|
|
3907
4692
|
localScope.set(proxyName, Object.fromEntries(ruleRefs));
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
const name = id.name;
|
|
3916
|
-
const before = bodyMfs.length;
|
|
3917
|
-
const val = anyValue(decl.init, localScope, code, bodyMfs);
|
|
3918
|
-
if (val === null) return null;
|
|
3919
|
-
const thisDeclMfSrcs = bodyMfs.slice(before);
|
|
3920
|
-
if (isCombinator(val)) {
|
|
3921
|
-
localScope.set(name, { combi: val, mfSrcs: thisDeclMfSrcs });
|
|
3922
|
-
} else {
|
|
3923
|
-
localScope.set(name, val);
|
|
3924
|
-
}
|
|
3925
|
-
}
|
|
3926
|
-
}
|
|
3927
|
-
for (const prop of retObj.properties) {
|
|
3928
|
-
const p = prop;
|
|
3929
|
-
const key = p.key.type === "Identifier" ? p.key.name : String(p.key.value);
|
|
3930
|
-
const val = anyValue(p.value, localScope, code, mapFnSources);
|
|
4693
|
+
if (!evalBodyStatements(statements, localScope, code)) return null;
|
|
4694
|
+
const entries = flattenRuleEntries(retObj, localScope, code, resolveFactory, /* @__PURE__ */ new Set());
|
|
4695
|
+
if (!entries) return null;
|
|
4696
|
+
const finalByKey = /* @__PURE__ */ new Map();
|
|
4697
|
+
for (const e of entries) finalByKey.set(e.key, e);
|
|
4698
|
+
for (const [key, e] of finalByKey) {
|
|
4699
|
+
const val = anyValue(e.value, e.scope, e.code, mapFnSources);
|
|
3931
4700
|
if (!isCombinator(val)) return null;
|
|
3932
4701
|
ruleRefs.get(key).define(val);
|
|
3933
4702
|
}
|
|
@@ -3985,6 +4754,40 @@ function referencesAny(node2, names, scope) {
|
|
|
3985
4754
|
|
|
3986
4755
|
// src/plugin/index.ts
|
|
3987
4756
|
var PARSEMAN_MODULE = "parseman";
|
|
4757
|
+
var _fragmentResolver = null;
|
|
4758
|
+
function getFragmentResolver() {
|
|
4759
|
+
return _fragmentResolver ??= new ResolverFactory({
|
|
4760
|
+
extensions: [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"],
|
|
4761
|
+
// TS/NodeNext style: a `./x.js` import may point at `./x.ts` source.
|
|
4762
|
+
extensionAlias: {
|
|
4763
|
+
".js": [".ts", ".tsx", ".js", ".jsx"],
|
|
4764
|
+
".mjs": [".mts", ".mjs"],
|
|
4765
|
+
".cjs": [".cts", ".cjs"]
|
|
4766
|
+
},
|
|
4767
|
+
conditionNames: ["source", "development", "import", "require", "default"],
|
|
4768
|
+
mainFields: ["source", "module", "main"]
|
|
4769
|
+
});
|
|
4770
|
+
}
|
|
4771
|
+
var _moduleParseCache = /* @__PURE__ */ new Map();
|
|
4772
|
+
function parseModuleCached(filePath) {
|
|
4773
|
+
let mtimeMs;
|
|
4774
|
+
try {
|
|
4775
|
+
mtimeMs = fs.statSync(filePath).mtimeMs;
|
|
4776
|
+
} catch {
|
|
4777
|
+
return null;
|
|
4778
|
+
}
|
|
4779
|
+
const hit = _moduleParseCache.get(filePath);
|
|
4780
|
+
if (hit && hit.mtimeMs === mtimeMs) return hit.parsed;
|
|
4781
|
+
let parsed = null;
|
|
4782
|
+
try {
|
|
4783
|
+
const src = fs.readFileSync(filePath, "utf8");
|
|
4784
|
+
const r = parseSync(filePath, src);
|
|
4785
|
+
if (r.errors.length === 0) parsed = { body: r.program.body, src };
|
|
4786
|
+
} catch {
|
|
4787
|
+
}
|
|
4788
|
+
_moduleParseCache.set(filePath, { mtimeMs, parsed });
|
|
4789
|
+
return parsed;
|
|
4790
|
+
}
|
|
3988
4791
|
var plugin_default = createUnplugin((opts = {}) => ({
|
|
3989
4792
|
name: "parseman",
|
|
3990
4793
|
// Run BEFORE the bundler's TS/JS transform — otherwise esbuild (Vite) strips
|
|
@@ -4020,15 +4823,23 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
4020
4823
|
const body = result.program.body;
|
|
4021
4824
|
const macroImports = [];
|
|
4022
4825
|
const allNames = /* @__PURE__ */ new Set();
|
|
4826
|
+
const importBindings = /* @__PURE__ */ new Map();
|
|
4023
4827
|
for (const stmt of body) {
|
|
4024
4828
|
if (stmt.type !== "ImportDeclaration") continue;
|
|
4025
4829
|
const s = stmt;
|
|
4026
|
-
|
|
4027
|
-
const isMacro = s.attributes.some((a) => {
|
|
4830
|
+
const isMacro = moduleAliases.has(s.source.value) && s.attributes.some((a) => {
|
|
4028
4831
|
const key = a.key.type === "Identifier" ? a.key.name : String(a.key.value);
|
|
4029
4832
|
return key === "type" && a.value.value === "macro";
|
|
4030
4833
|
});
|
|
4031
|
-
if (!isMacro)
|
|
4834
|
+
if (!isMacro) {
|
|
4835
|
+
for (const spec of s.specifiers) {
|
|
4836
|
+
if (spec.type === "ImportSpecifier") {
|
|
4837
|
+
const imported = spec.imported.name ?? spec.local.name;
|
|
4838
|
+
importBindings.set(spec.local.name, { source: s.source.value, imported });
|
|
4839
|
+
}
|
|
4840
|
+
}
|
|
4841
|
+
continue;
|
|
4842
|
+
}
|
|
4032
4843
|
const names = /* @__PURE__ */ new Set();
|
|
4033
4844
|
for (const spec of s.specifiers) {
|
|
4034
4845
|
if (spec.type === "ImportSpecifier") names.add(spec.local.name);
|
|
@@ -4038,6 +4849,63 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
4038
4849
|
}
|
|
4039
4850
|
if (macroImports.length === 0) return null;
|
|
4040
4851
|
const scope = /* @__PURE__ */ new Map();
|
|
4852
|
+
const factories = /* @__PURE__ */ new Map();
|
|
4853
|
+
const resolver = getFragmentResolver();
|
|
4854
|
+
const importedFactoryCache = /* @__PURE__ */ new Map();
|
|
4855
|
+
const OUTPUT_DIR = /([\\/])(dist|lib|build|out|output|compiled|cjs|esm|es)([\\/])/;
|
|
4856
|
+
const resolveSourcePath = (spec) => {
|
|
4857
|
+
let resolved = null;
|
|
4858
|
+
try {
|
|
4859
|
+
resolved = resolver.resolveFileSync(id, spec).path ?? null;
|
|
4860
|
+
} catch {
|
|
4861
|
+
}
|
|
4862
|
+
if (!resolved) return null;
|
|
4863
|
+
if (OUTPUT_DIR.test(resolved)) {
|
|
4864
|
+
const srcCandidate = resolved.replace(OUTPUT_DIR, "$1src$3").replace(/\.(c|m)?js$/, ".ts");
|
|
4865
|
+
try {
|
|
4866
|
+
if (fs.statSync(srcCandidate).isFile()) return srcCandidate;
|
|
4867
|
+
} catch {
|
|
4868
|
+
}
|
|
4869
|
+
}
|
|
4870
|
+
return resolved;
|
|
4871
|
+
};
|
|
4872
|
+
const resolveImportedFactory = (name) => {
|
|
4873
|
+
if (importedFactoryCache.has(name)) return importedFactoryCache.get(name);
|
|
4874
|
+
let result2 = null;
|
|
4875
|
+
const binding = importBindings.get(name);
|
|
4876
|
+
if (binding) {
|
|
4877
|
+
const filePath = resolveSourcePath(binding.source);
|
|
4878
|
+
const mod = filePath ? parseModuleCached(filePath) : null;
|
|
4879
|
+
if (mod) {
|
|
4880
|
+
for (const st of mod.body) {
|
|
4881
|
+
if (st.type !== "ExportNamedDeclaration" || !st.declaration) continue;
|
|
4882
|
+
const decl = st.declaration;
|
|
4883
|
+
if (decl.type === "VariableDeclaration") {
|
|
4884
|
+
for (const d of decl.declarations ?? []) {
|
|
4885
|
+
if (d.id?.type === "Identifier" && d.id.name === binding.imported && d.init) {
|
|
4886
|
+
const fac = asFragmentFactory(d.init);
|
|
4887
|
+
if (fac) {
|
|
4888
|
+
result2 = { fn: fac, code: mod.src };
|
|
4889
|
+
break;
|
|
4890
|
+
}
|
|
4891
|
+
}
|
|
4892
|
+
}
|
|
4893
|
+
} else if (decl.type === "FunctionDeclaration" && decl.id?.type === "Identifier" && decl.id.name === binding.imported) {
|
|
4894
|
+
const fac = asFragmentFactory(decl);
|
|
4895
|
+
if (fac) result2 = { fn: fac, code: mod.src };
|
|
4896
|
+
}
|
|
4897
|
+
if (result2) break;
|
|
4898
|
+
}
|
|
4899
|
+
}
|
|
4900
|
+
}
|
|
4901
|
+
importedFactoryCache.set(name, result2);
|
|
4902
|
+
return result2;
|
|
4903
|
+
};
|
|
4904
|
+
const resolveFactory = (n) => {
|
|
4905
|
+
const local = factories.get(n);
|
|
4906
|
+
if (local) return { fn: local, code };
|
|
4907
|
+
return resolveImportedFactory(n);
|
|
4908
|
+
};
|
|
4041
4909
|
const replacements = [];
|
|
4042
4910
|
const warnings = [];
|
|
4043
4911
|
let anyUnresolved = false;
|
|
@@ -4058,7 +4926,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
4058
4926
|
warn(init.start, `${label2}: rules() needs a factory argument`);
|
|
4059
4927
|
return null;
|
|
4060
4928
|
}
|
|
4061
|
-
const ruleMap = evaluateParserFactory(factoryArg, scope, code, []);
|
|
4929
|
+
const ruleMap = evaluateParserFactory(factoryArg, scope, code, [], resolveFactory);
|
|
4062
4930
|
if (!ruleMap) {
|
|
4063
4931
|
warn(init.start, `${label2}: rules(...) factory isn't statically evaluable`);
|
|
4064
4932
|
return null;
|
|
@@ -4156,6 +5024,11 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
4156
5024
|
});
|
|
4157
5025
|
continue;
|
|
4158
5026
|
}
|
|
5027
|
+
const frag = asFragmentFactory(init);
|
|
5028
|
+
if (frag) {
|
|
5029
|
+
factories.set(varName, frag);
|
|
5030
|
+
continue;
|
|
5031
|
+
}
|
|
4159
5032
|
const mapFnSources = [];
|
|
4160
5033
|
const parser2 = evaluateExpr(init, scope, code, mapFnSources);
|
|
4161
5034
|
if (parser2 === null) {
|