parseman 0.52.0 → 0.54.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/analysis/diagnostics.js +636 -126
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/cli/index.js +6191 -6274
- package/dist/cli/index.js.map +3 -3
- package/dist/combinators/field-trivia.d.ts +40 -0
- package/dist/combinators/field-trivia.d.ts.map +1 -0
- package/dist/combinators/map.d.ts +19 -2
- package/dist/combinators/map.d.ts.map +1 -1
- package/dist/combinators/parser.d.ts +34 -0
- package/dist/combinators/parser.d.ts.map +1 -1
- package/dist/combinators/ref.d.ts +0 -13
- package/dist/combinators/ref.d.ts.map +1 -1
- package/dist/combinators/repeat.d.ts.map +1 -1
- package/dist/combinators/sequence.d.ts.map +1 -1
- package/dist/compiler/borrowed-rules.d.ts +30 -0
- package/dist/compiler/borrowed-rules.d.ts.map +1 -0
- package/dist/compiler/compile-linkable-table.d.ts +1 -1
- package/dist/compiler/fields.d.ts +2 -0
- package/dist/compiler/fields.d.ts.map +1 -1
- package/dist/compiler/grammar-coverage-ids.d.ts.map +1 -1
- package/dist/compiler/ir-serialize.d.ts +10 -4
- package/dist/compiler/ir-serialize.d.ts.map +1 -1
- package/dist/compiler/linker.d.ts +48 -91
- package/dist/compiler/linker.d.ts.map +1 -1
- package/dist/coverage.d.ts +1 -1
- package/dist/coverage.d.ts.map +1 -1
- package/dist/cst/reflection.d.ts.map +1 -1
- package/dist/cst/trivia-charscan.d.ts +11 -3
- package/dist/cst/trivia-charscan.d.ts.map +1 -1
- package/dist/cst/trivia-kinds.d.ts +11 -0
- package/dist/cst/trivia-kinds.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +764 -888
- package/dist/index.js.map +3 -3
- package/dist/language-service/index.js.map +1 -1
- package/dist/plugin/evaluator.d.ts +38 -2
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +1443 -729
- package/dist/plugin/index.js.map +3 -3
- package/dist/plugin/ir-eval.d.ts +21 -0
- package/dist/plugin/ir-eval.d.ts.map +1 -0
- package/dist/plugin/reducer-resolver.d.ts +6 -0
- package/dist/plugin/reducer-resolver.d.ts.map +1 -1
- package/dist/spec/index.js +555 -6109
- package/dist/spec/index.js.map +3 -3
- package/dist/spec/railroad-lib.d.ts +7 -2
- package/dist/spec/railroad-lib.d.ts.map +1 -1
- package/dist/spec/railroad.d.ts.map +1 -1
- package/dist/table/assemble.d.ts +9 -0
- package/dist/table/assemble.d.ts.map +1 -1
- package/dist/table/compile-rule-map.d.ts +11 -4
- package/dist/table/compile-rule-map.d.ts.map +1 -1
- package/dist/table/compile.d.ts +16 -0
- package/dist/table/compile.d.ts.map +1 -1
- package/dist/table/emit-assembly.d.ts +1 -1
- package/dist/table/emit-assembly.d.ts.map +1 -1
- package/dist/table/emit.d.ts +6 -2
- package/dist/table/emit.d.ts.map +1 -1
- package/dist/table/encode.d.ts.map +1 -1
- package/dist/table/exec.d.ts.map +1 -1
- package/dist/table/field-spec.d.ts +13 -0
- package/dist/table/field-spec.d.ts.map +1 -0
- package/dist/table/index.js +480 -199
- package/dist/table/index.js.map +2 -2
- package/dist/table/scalar-terminal.d.ts +11 -0
- package/dist/table/scalar-terminal.d.ts.map +1 -1
- package/dist/types.d.ts +14 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/analysis/duplication.ts +1 -1
- package/src/analysis/rebuild.ts +1 -1
- package/src/combinators/field-trivia.ts +44 -0
- package/src/combinators/map.ts +48 -6
- package/src/combinators/parser.ts +133 -67
- package/src/combinators/ref.ts +10 -1
- package/src/combinators/repeat.ts +6 -1
- package/src/combinators/sequence.ts +9 -1
- package/src/compiler/borrowed-rules.ts +88 -0
- package/src/compiler/compile-linkable-table.ts +1 -1
- package/src/compiler/fields.ts +5 -2
- package/src/compiler/grammar-coverage-ids.ts +35 -6
- package/src/compiler/ir-serialize.ts +19 -119
- package/src/compiler/linker.ts +190 -666
- package/src/coverage.ts +7 -5
- package/src/cst/reflection.ts +6 -1
- package/src/cst/trivia-charscan.ts +17 -56
- package/src/cst/trivia-kinds.ts +24 -8
- package/src/index.ts +1 -0
- package/src/plugin/evaluator.ts +114 -14
- package/src/plugin/index.ts +588 -110
- package/src/plugin/ir-eval.ts +165 -0
- package/src/plugin/reducer-resolver.ts +20 -3
- package/src/spec/railroad-lib.ts +18 -8
- package/src/spec/railroad.ts +3 -4
- package/src/table/assemble.ts +126 -22
- package/src/table/compile-rule-map.ts +18 -8
- package/src/table/compile.ts +61 -0
- package/src/table/emit-assembly.ts +38 -18
- package/src/table/emit.ts +15 -4
- package/src/table/encode.ts +18 -2
- package/src/table/exec.ts +15 -1
- package/src/table/field-spec.ts +17 -0
- package/src/table/scalar-terminal.ts +25 -0
- package/src/types.ts +12 -2
- package/src/version.ts +1 -1
package/dist/table/index.js
CHANGED
|
@@ -1485,65 +1485,17 @@ function plainRegexSource(p) {
|
|
|
1485
1485
|
const d = p._def;
|
|
1486
1486
|
return d.tag === "regex" && d.flags === "" ? d.source : null;
|
|
1487
1487
|
}
|
|
1488
|
-
var visitSpec0;
|
|
1489
|
-
var visitSpec1;
|
|
1490
|
-
var visitSpec2;
|
|
1491
|
-
var visitSpec3;
|
|
1492
|
-
var visitValue0;
|
|
1493
|
-
var visitValue1;
|
|
1494
|
-
var visitValue2;
|
|
1495
|
-
var visitValue3;
|
|
1496
1488
|
function commonLabeledTriviaVisitor(spec) {
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
if (spec === visitSpec2) return visitValue2;
|
|
1500
|
-
if (spec === visitSpec3) return visitValue3;
|
|
1501
|
-
const sources = spec.minRepeats <= 1 ? spec.arms.map((arm) => plainRegexSource(arm.parser)) : [];
|
|
1502
|
-
const visitor = commonCssTriviaVisitor(sources);
|
|
1503
|
-
visitSpec3 = visitSpec2;
|
|
1504
|
-
visitValue3 = visitValue2;
|
|
1505
|
-
visitSpec2 = visitSpec1;
|
|
1506
|
-
visitValue2 = visitValue1;
|
|
1507
|
-
visitSpec1 = visitSpec0;
|
|
1508
|
-
visitValue1 = visitValue0;
|
|
1509
|
-
visitSpec0 = spec;
|
|
1510
|
-
visitValue0 = visitor;
|
|
1511
|
-
return visitor;
|
|
1512
|
-
}
|
|
1513
|
-
var armSpec0;
|
|
1514
|
-
var armSpec1;
|
|
1515
|
-
var armSpec2;
|
|
1516
|
-
var armSpec3;
|
|
1517
|
-
var armValue0;
|
|
1518
|
-
var armValue1;
|
|
1519
|
-
var armValue2;
|
|
1520
|
-
var armValue3;
|
|
1489
|
+
return commonCssTriviaVisitor(spec.minRepeats <= 1 ? spec.arms.map((arm) => plainRegexSource(arm.parser)) : []);
|
|
1490
|
+
}
|
|
1521
1491
|
function charArmsFor(spec) {
|
|
1522
|
-
if (spec
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
arms = null;
|
|
1529
|
-
} else {
|
|
1530
|
-
for (const arm of spec.arms) {
|
|
1531
|
-
const c = classifyParser(arm.parser);
|
|
1532
|
-
if (!c) {
|
|
1533
|
-
arms = null;
|
|
1534
|
-
break;
|
|
1535
|
-
}
|
|
1536
|
-
arms.push(c);
|
|
1537
|
-
}
|
|
1492
|
+
if (spec.minRepeats > 1) return null;
|
|
1493
|
+
const arms = [];
|
|
1494
|
+
for (const arm of spec.arms) {
|
|
1495
|
+
const c = classifyParser(arm.parser);
|
|
1496
|
+
if (!c) return null;
|
|
1497
|
+
arms.push(c);
|
|
1538
1498
|
}
|
|
1539
|
-
armSpec3 = armSpec2;
|
|
1540
|
-
armValue3 = armValue2;
|
|
1541
|
-
armSpec2 = armSpec1;
|
|
1542
|
-
armValue2 = armValue1;
|
|
1543
|
-
armSpec1 = armSpec0;
|
|
1544
|
-
armValue1 = armValue0;
|
|
1545
|
-
armSpec0 = spec;
|
|
1546
|
-
armValue0 = arms;
|
|
1547
1499
|
return arms;
|
|
1548
1500
|
}
|
|
1549
1501
|
function charTriviaEnd(input, cur, arms) {
|
|
@@ -1659,12 +1611,16 @@ function analyzeLabeledTrivia(trivia2) {
|
|
|
1659
1611
|
}
|
|
1660
1612
|
arms.push({ label: peeled.label, kindIndex: 0, parser: peeled.parser });
|
|
1661
1613
|
}
|
|
1662
|
-
|
|
1614
|
+
return cacheLabeledTrivia(trivia2, labeledTriviaSpec(arms, minRepeats));
|
|
1615
|
+
}
|
|
1616
|
+
function labeledTriviaSpec(arms, minRepeats) {
|
|
1617
|
+
return {
|
|
1663
1618
|
labels: arms.map((a) => a.label),
|
|
1664
1619
|
arms,
|
|
1665
|
-
minRepeats
|
|
1620
|
+
minRepeats,
|
|
1621
|
+
visitor: commonLabeledTriviaVisitor({ arms, minRepeats }),
|
|
1622
|
+
charArms: charArmsFor({ arms, minRepeats })
|
|
1666
1623
|
};
|
|
1667
|
-
return cacheLabeledTrivia(trivia2, spec);
|
|
1668
1624
|
}
|
|
1669
1625
|
function matchArmAt(input, pos, arm, state) {
|
|
1670
1626
|
if (!startsFirstSet(arm, input, pos)) return null;
|
|
@@ -1694,7 +1650,7 @@ function scanLabeledTriviaChunks(input, cur, spec, state) {
|
|
|
1694
1650
|
return { end: pos, chunks };
|
|
1695
1651
|
}
|
|
1696
1652
|
function scanLabeledTriviaEnd(input, cur, spec, state) {
|
|
1697
|
-
const chars =
|
|
1653
|
+
const chars = spec.charArms;
|
|
1698
1654
|
if (chars !== null) return charTriviaEnd(input, cur, chars);
|
|
1699
1655
|
let pos = cur;
|
|
1700
1656
|
let count = 0;
|
|
@@ -1712,9 +1668,9 @@ function scanLabeledTriviaEnd(input, cur, spec, state) {
|
|
|
1712
1668
|
}
|
|
1713
1669
|
function visitLabeledTrivia(input, cur, spec, state, visit) {
|
|
1714
1670
|
if (spec.minRepeats > 1) return void 0;
|
|
1715
|
-
const common =
|
|
1671
|
+
const common = spec.visitor;
|
|
1716
1672
|
if (common !== null) return common(input, cur, visit);
|
|
1717
|
-
const chars =
|
|
1673
|
+
const chars = spec.charArms;
|
|
1718
1674
|
if (chars !== null) return charTriviaVisit(input, cur, chars, visit);
|
|
1719
1675
|
let pos = cur;
|
|
1720
1676
|
let count = 0;
|
|
@@ -1781,7 +1737,7 @@ function resolveAdjacencyKindMask(trivia2, kinds) {
|
|
|
1781
1737
|
return mask;
|
|
1782
1738
|
}
|
|
1783
1739
|
function triviaKindMaskAt(input, pos, spec, state) {
|
|
1784
|
-
const chars =
|
|
1740
|
+
const chars = spec.charArms;
|
|
1785
1741
|
if (chars !== null) return charTriviaKindMask(input, pos, chars);
|
|
1786
1742
|
let cur = pos;
|
|
1787
1743
|
let mask = 0;
|
|
@@ -2494,6 +2450,23 @@ function scalarOf(combinator) {
|
|
|
2494
2450
|
return combinator._parseScalar;
|
|
2495
2451
|
}
|
|
2496
2452
|
|
|
2453
|
+
// src/combinators/field-trivia.ts
|
|
2454
|
+
var LEAD = { at: -1 };
|
|
2455
|
+
var FIELD_LEADING_TRIVIA = 1;
|
|
2456
|
+
var FIELD_TRAILING_TRIVIA = 2;
|
|
2457
|
+
function triviaFieldCapture(name, value, input, start, end, leadFrom, trailEnd) {
|
|
2458
|
+
return {
|
|
2459
|
+
name,
|
|
2460
|
+
value,
|
|
2461
|
+
span: { start, end },
|
|
2462
|
+
leading: leadFrom >= 0 && leadFrom < start ? input.slice(leadFrom, start) : "",
|
|
2463
|
+
trailing: trailEnd > end ? input.slice(end, trailEnd) : ""
|
|
2464
|
+
};
|
|
2465
|
+
}
|
|
2466
|
+
function leadsTrivia(p) {
|
|
2467
|
+
return p._def.tag === "field" && p._def.leadingTrivia === true;
|
|
2468
|
+
}
|
|
2469
|
+
|
|
2497
2470
|
// src/combinators/sequence.ts
|
|
2498
2471
|
function sequence(...parsers) {
|
|
2499
2472
|
let adjacency = null;
|
|
@@ -2509,6 +2482,10 @@ function sequence(...parsers) {
|
|
|
2509
2482
|
(adjacency ??= Array.from({ length: parsers.length }, () => null))[i] = a;
|
|
2510
2483
|
}
|
|
2511
2484
|
const hasAdjacency = adjacency !== null;
|
|
2485
|
+
let leading = null;
|
|
2486
|
+
for (let i = 1; i < parsers.length; i++) {
|
|
2487
|
+
if (leadsTrivia(parsers[i])) (leading ??= Array.from({ length: parsers.length }, () => false))[i] = true;
|
|
2488
|
+
}
|
|
2512
2489
|
const strictArity = !hasAdjacency && (parsers.length === 2 && !matchesEmpty(parsers[1]) || parsers.length === 3 && parsers.every((p) => !matchesEmpty(p))) ? parsers.length : 0;
|
|
2513
2490
|
const meta = {
|
|
2514
2491
|
// Union through the nullable prefix — a leading optional()/many() lets a later
|
|
@@ -2556,7 +2533,7 @@ function sequence(...parsers) {
|
|
|
2556
2533
|
_tag: "sequence",
|
|
2557
2534
|
_meta: meta,
|
|
2558
2535
|
_def: def,
|
|
2559
|
-
_parseScalar: hasAdjacency ? void 0 : parseScalar,
|
|
2536
|
+
_parseScalar: hasAdjacency || leading !== null ? void 0 : parseScalar,
|
|
2560
2537
|
parse(input, pos, ctx) {
|
|
2561
2538
|
const tolerant = ctx._tolerant === true;
|
|
2562
2539
|
if (tolerant) {
|
|
@@ -2590,6 +2567,7 @@ function sequence(...parsers) {
|
|
|
2590
2567
|
const scanTlog = deferredTrivia ? cstTlLen(ctx) : 0;
|
|
2591
2568
|
const scanLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
|
|
2592
2569
|
const scanRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
2570
|
+
if (leading?.[i] === true) LEAD.at = cur;
|
|
2593
2571
|
const result = parsers[i].parse(input, termPos, ctx);
|
|
2594
2572
|
if (!result.ok) return result;
|
|
2595
2573
|
if (values !== void 0) values.push(result.value);
|
|
@@ -3392,6 +3370,7 @@ function withRuleTrivia(trivia2, ctx, run) {
|
|
|
3392
3370
|
ctx.triviaKindLabels = savedLabels;
|
|
3393
3371
|
}
|
|
3394
3372
|
}
|
|
3373
|
+
var UNDEFINED_REF = new Error("ref<T>() used before .define() was called");
|
|
3395
3374
|
function ref() {
|
|
3396
3375
|
let resolved = null;
|
|
3397
3376
|
let resolvedScalar = null;
|
|
@@ -3407,7 +3386,7 @@ function ref() {
|
|
|
3407
3386
|
_def: {
|
|
3408
3387
|
tag: "lazy",
|
|
3409
3388
|
thunk: () => {
|
|
3410
|
-
if (!resolved) throw
|
|
3389
|
+
if (!resolved) throw UNDEFINED_REF;
|
|
3411
3390
|
return resolved;
|
|
3412
3391
|
}
|
|
3413
3392
|
},
|
|
@@ -4069,7 +4048,7 @@ function buildFieldMap(captures) {
|
|
|
4069
4048
|
if (!captures?.length) return void 0;
|
|
4070
4049
|
const out = {};
|
|
4071
4050
|
for (const cap of captures) {
|
|
4072
|
-
const entry = { value: cap.value, span: cap.span };
|
|
4051
|
+
const entry = cap.leading === void 0 ? { value: cap.value, span: cap.span } : { value: cap.value, span: cap.span, leading: cap.leading, trailing: cap.trailing };
|
|
4073
4052
|
const current = out[cap.name];
|
|
4074
4053
|
if (current === void 0) out[cap.name] = entry;
|
|
4075
4054
|
else if (Array.isArray(current)) current.push(entry);
|
|
@@ -6395,6 +6374,26 @@ function leadingLiteralFamily(code, constants, ip, minDepth = 2, limit = 4) {
|
|
|
6395
6374
|
};
|
|
6396
6375
|
return walk(ip, 0);
|
|
6397
6376
|
}
|
|
6377
|
+
function largeChoiceLiteralPretest(code, constants, armIp) {
|
|
6378
|
+
const child = leadingScalarTerminal(code, armIp, 2, true, true);
|
|
6379
|
+
if (child >= 0) {
|
|
6380
|
+
const spec = constants[code[child + 1]];
|
|
6381
|
+
if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) return [child];
|
|
6382
|
+
}
|
|
6383
|
+
const family = leadingLiteralFamily(code, constants, armIp);
|
|
6384
|
+
return family !== void 0 && family.length >= 2 && family.every((terminal) => {
|
|
6385
|
+
const value = constants[code[terminal + 1]];
|
|
6386
|
+
return typeof value === "string" && value.length >= 2;
|
|
6387
|
+
}) ? family : void 0;
|
|
6388
|
+
}
|
|
6389
|
+
|
|
6390
|
+
// src/table/field-spec.ts
|
|
6391
|
+
function fieldSpec(slot) {
|
|
6392
|
+
return Array.isArray(slot) ? { name: slot[0], bits: slot[1] } : { name: slot, bits: 0 };
|
|
6393
|
+
}
|
|
6394
|
+
function leadingTriviaFieldAt(code, k, ip) {
|
|
6395
|
+
return code[ip] === OP_FIELD && (fieldSpec(k[code[ip + 1]]).bits & FIELD_LEADING_TRIVIA) !== 0;
|
|
6396
|
+
}
|
|
6398
6397
|
|
|
6399
6398
|
// src/table/emit-assembly.ts
|
|
6400
6399
|
var Unemittable = class extends Error {
|
|
@@ -6469,7 +6468,11 @@ var EMITTED_PARAMS = [
|
|
|
6469
6468
|
// Appended for old precompiled-factory ABI: old factories ignore it.
|
|
6470
6469
|
"adjacencyHolds",
|
|
6471
6470
|
// Appended for selected composite lexical programs; old factories ignore it.
|
|
6472
|
-
"LEXPROG"
|
|
6471
|
+
"LEXPROG",
|
|
6472
|
+
// Appended for trivia-attributing fields (`field(…, { leadingTrivia })`);
|
|
6473
|
+
// old factories ignore them.
|
|
6474
|
+
"LEAD",
|
|
6475
|
+
"triviaFieldCapture"
|
|
6473
6476
|
];
|
|
6474
6477
|
var RUNTIME_PRELUDE = `
|
|
6475
6478
|
let _pfScan=null
|
|
@@ -6729,20 +6732,12 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
|
|
|
6729
6732
|
if (child >= 0) scalarSpecs.add(code[child + 1]);
|
|
6730
6733
|
continue;
|
|
6731
6734
|
}
|
|
6732
|
-
|
|
6733
|
-
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
continue;
|
|
6737
|
-
}
|
|
6738
|
-
}
|
|
6739
|
-
const family = leadingLiteralFamily(code, k, armIp);
|
|
6740
|
-
if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
|
|
6741
|
-
const value = k[code[terminal + 1]];
|
|
6742
|
-
return typeof value === "string" && value.length >= 2;
|
|
6743
|
-
})) {
|
|
6744
|
-
largeChoiceLiteralFamilies.set(armIp, family);
|
|
6735
|
+
const literals = largeChoiceLiteralPretest(code, k, armIp);
|
|
6736
|
+
if (literals !== void 0 && literals.length === 1 && literals[0] === child) {
|
|
6737
|
+
largeChoiceScalarSpecs.add(code[child + 1]);
|
|
6738
|
+
continue;
|
|
6745
6739
|
}
|
|
6740
|
+
if (literals !== void 0) largeChoiceLiteralFamilies.set(armIp, literals);
|
|
6746
6741
|
const sequence6 = leadingScalarSequence(code, armIp);
|
|
6747
6742
|
if (sequence6 !== void 0 && (sequence6.trivia < 0 || swapLegal && t.triviaScan[sequence6.trivia] != null)) {
|
|
6748
6743
|
largeChoiceScalarSequences.set(armIp, sequence6);
|
|
@@ -7166,14 +7161,31 @@ return v
|
|
|
7166
7161
|
}`;
|
|
7167
7162
|
}
|
|
7168
7163
|
case OP_FIELD: {
|
|
7169
|
-
const
|
|
7164
|
+
const spec = fieldSpec(k[code[ip + 1]]);
|
|
7165
|
+
const name = q(spec.name);
|
|
7170
7166
|
const child = link(code[ip + 2]);
|
|
7171
|
-
|
|
7167
|
+
if (spec.bits === 0) {
|
|
7168
|
+
return `${head}
|
|
7172
7169
|
const v=${child}(input,pos,ctx)
|
|
7173
7170
|
if(v===FAIL)return FAIL
|
|
7174
7171
|
const f=ctx._fields
|
|
7175
7172
|
if(f!==undefined)f.push({name:${name},value:v,span:{start:pos,end:EC.e}})
|
|
7176
7173
|
return v
|
|
7174
|
+
}`;
|
|
7175
|
+
}
|
|
7176
|
+
const leading = (spec.bits & FIELD_LEADING_TRIVIA) !== 0;
|
|
7177
|
+
const trailing = (spec.bits & FIELD_TRAILING_TRIVIA) !== 0;
|
|
7178
|
+
return `${head}
|
|
7179
|
+
const lf=${leading ? "LEAD.at" : "-1"}
|
|
7180
|
+
LEAD.at=-1
|
|
7181
|
+
const v=${child}(input,pos,ctx)
|
|
7182
|
+
if(v===FAIL)return FAIL
|
|
7183
|
+
const e=EC.e
|
|
7184
|
+
const te=${trailing ? "ctx.trivia!==undefined?consumeTrivia(input,e,ctx):e" : "e"}
|
|
7185
|
+
const f=ctx._fields
|
|
7186
|
+
if(f!==undefined)f.push(triviaFieldCapture(${name},v,input,pos,e,lf,te))
|
|
7187
|
+
EC.e=te
|
|
7188
|
+
return v
|
|
7177
7189
|
}`;
|
|
7178
7190
|
}
|
|
7179
7191
|
case OP_EXPECT: {
|
|
@@ -7469,7 +7481,10 @@ return v
|
|
|
7469
7481
|
`if(!adjacencyHolds(input,cur,ctx,${negated ? "true" : "false"},${kinds})){ctx._fe=cur;ctx._fx=${expected};return FAIL}`,
|
|
7470
7482
|
`${vn}=null`
|
|
7471
7483
|
);
|
|
7472
|
-
} else
|
|
7484
|
+
} else {
|
|
7485
|
+
const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
|
|
7486
|
+
parts.push(emitTerm(callee, vn, tmp(), L, skipFor(L)));
|
|
7487
|
+
}
|
|
7473
7488
|
names.push(vn);
|
|
7474
7489
|
}
|
|
7475
7490
|
parts.push("EC.e=cur");
|
|
@@ -7869,7 +7884,7 @@ let sp=cur
|
|
|
7869
7884
|
${hasTrivia === "false" ? "" : hasTrivia === "true" ? `sp=${skip}(input,sp,ctx)
|
|
7870
7885
|
` : `if(hasTrivia)sp=${skip}(input,sp,ctx)
|
|
7871
7886
|
`}ctx._fc=false
|
|
7872
|
-
const sv=${sep}(input,sp,ctx)
|
|
7887
|
+
${sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp) ? "LEAD.at=cur\n" : ""}const sv=${sep}(input,sp,ctx)
|
|
7873
7888
|
if(sv===FAIL){
|
|
7874
7889
|
${rb}
|
|
7875
7890
|
if(ctx._fc===true)return FAIL
|
|
@@ -8742,6 +8757,12 @@ function assemble(t, prog, cfg) {
|
|
|
8742
8757
|
rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
|
|
8743
8758
|
return cur;
|
|
8744
8759
|
}
|
|
8760
|
+
function leadingFieldTerm(step, child, input, cur, ctx) {
|
|
8761
|
+
return step((i, p, c) => {
|
|
8762
|
+
LEAD.at = cur;
|
|
8763
|
+
return child(i, p, c);
|
|
8764
|
+
}, input, cur, ctx);
|
|
8765
|
+
}
|
|
8745
8766
|
function committed3(c) {
|
|
8746
8767
|
return c._fc === true;
|
|
8747
8768
|
}
|
|
@@ -9379,12 +9400,27 @@ function assemble(t, prog, cfg) {
|
|
|
9379
9400
|
};
|
|
9380
9401
|
}
|
|
9381
9402
|
case OP_FIELD: {
|
|
9382
|
-
const name = k[code[ip + 1]];
|
|
9403
|
+
const { name, bits } = fieldSpec(k[code[ip + 1]]);
|
|
9383
9404
|
const child = link(code[ip + 2]);
|
|
9405
|
+
if (bits === 0) {
|
|
9406
|
+
return (input, pos, ctx) => {
|
|
9407
|
+
const v = child(input, pos, ctx);
|
|
9408
|
+
if (v === FAIL) return FAIL;
|
|
9409
|
+
ctx._fields?.push({ name, value: v, span: { start: pos, end: EC.e } });
|
|
9410
|
+
return v;
|
|
9411
|
+
};
|
|
9412
|
+
}
|
|
9413
|
+
const leading = (bits & FIELD_LEADING_TRIVIA) !== 0;
|
|
9414
|
+
const trailing = (bits & FIELD_TRAILING_TRIVIA) !== 0;
|
|
9384
9415
|
return (input, pos, ctx) => {
|
|
9416
|
+
const leadFrom = leading ? LEAD.at : -1;
|
|
9417
|
+
LEAD.at = -1;
|
|
9385
9418
|
const v = child(input, pos, ctx);
|
|
9386
9419
|
if (v === FAIL) return FAIL;
|
|
9387
|
-
|
|
9420
|
+
const end = EC.e;
|
|
9421
|
+
const trailEnd = trailing && ctx.trivia !== void 0 ? consumeTrivia(input, end, ctx) : end;
|
|
9422
|
+
ctx._fields?.push(triviaFieldCapture(name, v, input, pos, end, leadFrom, trailEnd));
|
|
9423
|
+
EC.e = trailEnd;
|
|
9388
9424
|
return v;
|
|
9389
9425
|
};
|
|
9390
9426
|
}
|
|
@@ -9818,6 +9854,12 @@ function assemble(t, prog, cfg) {
|
|
|
9818
9854
|
const kidIp = code[base + i];
|
|
9819
9855
|
if (code[kidIp] !== OP_ADJ) {
|
|
9820
9856
|
const kid = link(kidIp);
|
|
9857
|
+
if (leadingTriviaFieldAt(code, k, kidIp)) {
|
|
9858
|
+
return (input, cur, ctx, inherited) => {
|
|
9859
|
+
ctx._sync = sync ?? inherited;
|
|
9860
|
+
return leadingFieldTerm(step, kid, input, cur, ctx);
|
|
9861
|
+
};
|
|
9862
|
+
}
|
|
9821
9863
|
return (input, cur, ctx, inherited) => {
|
|
9822
9864
|
ctx._sync = sync ?? inherited;
|
|
9823
9865
|
return step(kid, input, cur, ctx);
|
|
@@ -9895,9 +9937,12 @@ function assemble(t, prog, cfg) {
|
|
|
9895
9937
|
};
|
|
9896
9938
|
}
|
|
9897
9939
|
let hasAdj = false;
|
|
9898
|
-
for (let i = 1; i < n; i++)
|
|
9899
|
-
|
|
9900
|
-
|
|
9940
|
+
for (let i = 1; i < n; i++) {
|
|
9941
|
+
const kidIp = code[base + i];
|
|
9942
|
+
if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp)) {
|
|
9943
|
+
hasAdj = true;
|
|
9944
|
+
break;
|
|
9945
|
+
}
|
|
9901
9946
|
}
|
|
9902
9947
|
if (hasAdj) {
|
|
9903
9948
|
const first2 = link(code[base]);
|
|
@@ -9905,6 +9950,9 @@ function assemble(t, prog, cfg) {
|
|
|
9905
9950
|
const kidIp = code[base + i];
|
|
9906
9951
|
if (code[kidIp] !== OP_ADJ) {
|
|
9907
9952
|
const kid = link(kidIp);
|
|
9953
|
+
if (leadingTriviaFieldAt(code, k, kidIp)) {
|
|
9954
|
+
return (input, cur, ctx) => leadingFieldTerm(step, kid, input, cur, ctx);
|
|
9955
|
+
}
|
|
9908
9956
|
return (input, cur, ctx) => step(kid, input, cur, ctx);
|
|
9909
9957
|
}
|
|
9910
9958
|
const negated = code[kidIp + 1] === 1;
|
|
@@ -10267,7 +10315,7 @@ function assemble(t, prog, cfg) {
|
|
|
10267
10315
|
if (n === 2 || n === 3) {
|
|
10268
10316
|
const a0 = link(code[base]), a1 = link(code[base + 1]);
|
|
10269
10317
|
const a2 = n === 3 ? link(code[base + 2]) : void 0;
|
|
10270
|
-
const predecide = !
|
|
10318
|
+
const predecide = !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
|
|
10271
10319
|
const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
|
|
10272
10320
|
const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
|
|
10273
10321
|
const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
|
|
@@ -10490,6 +10538,75 @@ function assemble(t, prog, cfg) {
|
|
|
10490
10538
|
);
|
|
10491
10539
|
};
|
|
10492
10540
|
const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
|
|
10541
|
+
const pBit = [];
|
|
10542
|
+
const pRec = [];
|
|
10543
|
+
if (!REC && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
|
|
10544
|
+
for (let i = 0; i < n; i++) {
|
|
10545
|
+
for (const terminal of largeChoiceLiteralPretest(code, k, code[base + i]) ?? []) {
|
|
10546
|
+
pBit.push(1 << i);
|
|
10547
|
+
pRec.push(scalarFor(terminal));
|
|
10548
|
+
}
|
|
10549
|
+
}
|
|
10550
|
+
}
|
|
10551
|
+
const pn = pBit.length;
|
|
10552
|
+
if (pn !== 0) {
|
|
10553
|
+
return (input, pos, ctx) => {
|
|
10554
|
+
const c = lead(input, pos);
|
|
10555
|
+
const need = markCst(ctx);
|
|
10556
|
+
const mRaw = MRAW;
|
|
10557
|
+
const mTl = MTL;
|
|
10558
|
+
const mLv = MLV;
|
|
10559
|
+
const mFl = need ? ctx._fields?.length ?? 0 : 0;
|
|
10560
|
+
const mEr = need ? ctx._errors?.length ?? 0 : 0;
|
|
10561
|
+
const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
10562
|
+
const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
10563
|
+
if (c < 128) {
|
|
10564
|
+
const bits = mask[c < 0 ? 128 : c];
|
|
10565
|
+
let tested = 0;
|
|
10566
|
+
let hit = 0;
|
|
10567
|
+
for (let i = 0; i < pn; i++) {
|
|
10568
|
+
const b = pBit[i];
|
|
10569
|
+
if ((bits & b) === 0 || (hit & b) !== 0) continue;
|
|
10570
|
+
tested |= b;
|
|
10571
|
+
if (pRec[i](input, pos) >= 0) hit |= b;
|
|
10572
|
+
}
|
|
10573
|
+
return masked(
|
|
10574
|
+
input,
|
|
10575
|
+
pos,
|
|
10576
|
+
ctx,
|
|
10577
|
+
bits & (~tested | hit),
|
|
10578
|
+
need,
|
|
10579
|
+
mRaw,
|
|
10580
|
+
mTl,
|
|
10581
|
+
mLv,
|
|
10582
|
+
mFl,
|
|
10583
|
+
mEr,
|
|
10584
|
+
mLog,
|
|
10585
|
+
mRoot,
|
|
10586
|
+
void 0,
|
|
10587
|
+
0,
|
|
10588
|
+
pos
|
|
10589
|
+
);
|
|
10590
|
+
}
|
|
10591
|
+
return general(
|
|
10592
|
+
input,
|
|
10593
|
+
pos,
|
|
10594
|
+
ctx,
|
|
10595
|
+
c,
|
|
10596
|
+
need,
|
|
10597
|
+
mRaw,
|
|
10598
|
+
mTl,
|
|
10599
|
+
mLv,
|
|
10600
|
+
mFl,
|
|
10601
|
+
mEr,
|
|
10602
|
+
mLog,
|
|
10603
|
+
mRoot,
|
|
10604
|
+
void 0,
|
|
10605
|
+
0,
|
|
10606
|
+
pos
|
|
10607
|
+
);
|
|
10608
|
+
};
|
|
10609
|
+
}
|
|
10493
10610
|
return (input, pos, ctx) => {
|
|
10494
10611
|
const c = lead(input, pos);
|
|
10495
10612
|
const need = markCst(ctx);
|
|
@@ -10651,6 +10768,7 @@ function assemble(t, prog, cfg) {
|
|
|
10651
10768
|
const max = code[ip + 3];
|
|
10652
10769
|
const sepIp = code[ip + 4];
|
|
10653
10770
|
const sep = sepIp >= 0 ? link(sepIp) : void 0;
|
|
10771
|
+
const sepLeads = sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp);
|
|
10654
10772
|
const flags = code[ip + 5];
|
|
10655
10773
|
const keepSeparators = (flags & 2) !== 0;
|
|
10656
10774
|
const trailingAllowed = (flags & 1) !== 0;
|
|
@@ -10690,6 +10808,7 @@ function assemble(t, prog, cfg) {
|
|
|
10690
10808
|
let sp = cur;
|
|
10691
10809
|
if (hasTrivia) sp = skipTrivia(input, sp, ctx);
|
|
10692
10810
|
ctx._fc = false;
|
|
10811
|
+
if (sepLeads) LEAD.at = cur;
|
|
10693
10812
|
const sv = sep(input, sp, ctx);
|
|
10694
10813
|
if (sv === FAIL) {
|
|
10695
10814
|
if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
@@ -10779,6 +10898,7 @@ function assemble(t, prog, cfg) {
|
|
|
10779
10898
|
let sp = cur;
|
|
10780
10899
|
if (hasTrivia) sp = skipTrivia(input, sp, ctx);
|
|
10781
10900
|
ctx._fc = false;
|
|
10901
|
+
if (sepLeads) LEAD.at = cur;
|
|
10782
10902
|
const sv = sep(input, sp, ctx);
|
|
10783
10903
|
if (sv === FAIL) {
|
|
10784
10904
|
if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
@@ -11101,20 +11221,9 @@ function assemble(t, prog, cfg) {
|
|
|
11101
11221
|
if (child >= 0) scalarFor(child);
|
|
11102
11222
|
continue;
|
|
11103
11223
|
}
|
|
11104
|
-
|
|
11105
|
-
|
|
11106
|
-
|
|
11107
|
-
scalarFor(child);
|
|
11108
|
-
continue;
|
|
11109
|
-
}
|
|
11110
|
-
}
|
|
11111
|
-
const family = leadingLiteralFamily(code, k, armIp);
|
|
11112
|
-
if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
|
|
11113
|
-
const value = k[code[terminal + 1]];
|
|
11114
|
-
return typeof value === "string" && value.length >= 2;
|
|
11115
|
-
})) {
|
|
11116
|
-
for (const terminal of family) scalarFor(terminal);
|
|
11117
|
-
}
|
|
11224
|
+
const literals = largeChoiceLiteralPretest(code, k, armIp);
|
|
11225
|
+
if (literals !== void 0) for (const terminal of literals) scalarFor(terminal);
|
|
11226
|
+
if (literals !== void 0 && literals.length === 1 && literals[0] === child) continue;
|
|
11118
11227
|
const sequence6 = leadingScalarSequence(code, armIp);
|
|
11119
11228
|
if (sequence6 !== void 0 && (sequence6.trivia < 0 || triviaScan[sequence6.trivia] != null)) {
|
|
11120
11229
|
for (const terminal of sequence6.terminals) scalarFor(terminal);
|
|
@@ -11180,7 +11289,9 @@ function assemble(t, prog, cfg) {
|
|
|
11180
11289
|
scanTriviaCompact,
|
|
11181
11290
|
t.lex,
|
|
11182
11291
|
adjacencyHolds,
|
|
11183
|
-
t.lexPrograms
|
|
11292
|
+
t.lexPrograms,
|
|
11293
|
+
LEAD,
|
|
11294
|
+
triviaFieldCapture
|
|
11184
11295
|
);
|
|
11185
11296
|
emitReached = new Set(pre.reached);
|
|
11186
11297
|
}
|
|
@@ -11262,7 +11373,9 @@ function assemble(t, prog, cfg) {
|
|
|
11262
11373
|
scanTriviaCompact,
|
|
11263
11374
|
t.lex,
|
|
11264
11375
|
adjacencyHolds,
|
|
11265
|
-
t.lexPrograms
|
|
11376
|
+
t.lexPrograms,
|
|
11377
|
+
LEAD,
|
|
11378
|
+
triviaFieldCapture
|
|
11266
11379
|
);
|
|
11267
11380
|
emitReached = em.reached;
|
|
11268
11381
|
} catch (e) {
|
|
@@ -11438,7 +11551,9 @@ var AssemblyCache = class {
|
|
|
11438
11551
|
return made;
|
|
11439
11552
|
}
|
|
11440
11553
|
};
|
|
11441
|
-
function tableRules(source,
|
|
11554
|
+
function tableRules(source, metadataOrEntry = {}) {
|
|
11555
|
+
const entry = typeof metadataOrEntry === "string" ? metadataOrEntry : void 0;
|
|
11556
|
+
const artifactMetadata = typeof metadataOrEntry === "string" ? {} : metadataOrEntry;
|
|
11442
11557
|
const prog = expandCompact(source);
|
|
11443
11558
|
const resolved = resolveTable(prog);
|
|
11444
11559
|
const cache = new AssemblyCache(prog, resolved);
|
|
@@ -11446,7 +11561,7 @@ function tableRules(source, artifactMetadata = {}) {
|
|
|
11446
11561
|
const skipOf = prog.scanSkipOf;
|
|
11447
11562
|
let last;
|
|
11448
11563
|
let selected;
|
|
11449
|
-
|
|
11564
|
+
const map = stampRuleMap(prog, {
|
|
11450
11565
|
runRule: (ri, input, pos, ctx) => {
|
|
11451
11566
|
const a = selected ?? cache.forCtx(ctx);
|
|
11452
11567
|
selected = void 0;
|
|
@@ -11467,6 +11582,9 @@ function tableRules(source, artifactMetadata = {}) {
|
|
|
11467
11582
|
return a.scanSkip[skipOf?.[ri] ?? -1];
|
|
11468
11583
|
}
|
|
11469
11584
|
}, artifactMetadata, resolved);
|
|
11585
|
+
if (entry === void 0) return map;
|
|
11586
|
+
if (!Object.hasOwn(map, entry)) throw new Error(`tableRules: the program has no rule ${JSON.stringify(entry)}`);
|
|
11587
|
+
return map[entry];
|
|
11470
11588
|
}
|
|
11471
11589
|
|
|
11472
11590
|
// src/analysis/gating.ts
|
|
@@ -12643,6 +12761,16 @@ var Encoder = class {
|
|
|
12643
12761
|
this.kIndex.set(key, i);
|
|
12644
12762
|
return i;
|
|
12645
12763
|
}
|
|
12764
|
+
fieldSpecIndex = /* @__PURE__ */ new Map();
|
|
12765
|
+
fieldSpecSlot(name, bits) {
|
|
12766
|
+
const key = JSON.stringify([name, bits]);
|
|
12767
|
+
const hit = this.fieldSpecIndex.get(key);
|
|
12768
|
+
if (hit !== void 0) return hit;
|
|
12769
|
+
const i = this.k.length;
|
|
12770
|
+
this.k.push([name, bits]);
|
|
12771
|
+
this.fieldSpecIndex.set(key, i);
|
|
12772
|
+
return i;
|
|
12773
|
+
}
|
|
12646
12774
|
/**
|
|
12647
12775
|
* A `notAdjacent({ kinds })` filter, pooled by its CONTENTS.
|
|
12648
12776
|
*
|
|
@@ -13263,8 +13391,10 @@ var Encoder = class {
|
|
|
13263
13391
|
for (let i = 0; i < arms.length; i++) this.code[head + 6 + i] = arms[i];
|
|
13264
13392
|
return head;
|
|
13265
13393
|
}
|
|
13266
|
-
case "field":
|
|
13267
|
-
|
|
13394
|
+
case "field": {
|
|
13395
|
+
const bits = (d.leadingTrivia === true ? FIELD_LEADING_TRIVIA : 0) | (d.trailingTrivia === true ? FIELD_TRAILING_TRIVIA : 0);
|
|
13396
|
+
return this.emit(OP_FIELD, bits === 0 ? this.constant(d.name) : this.fieldSpecSlot(d.name, bits), this.node(d.parser).ip);
|
|
13397
|
+
}
|
|
13268
13398
|
case "lazy": {
|
|
13269
13399
|
const refName = p._ruleName;
|
|
13270
13400
|
const winner = refName === void 0 ? void 0 : this.winners?.[refName];
|
|
@@ -13702,11 +13832,15 @@ function emitTableExpression(prog, opts = {}) {
|
|
|
13702
13832
|
const entry = opts.entry === void 0 ? "grammar" : opts.entry;
|
|
13703
13833
|
const ref2 = opts.runtimeRef ?? "tableRules";
|
|
13704
13834
|
const fns = opts.fnSources ?? prog.fns.map(() => "() => {}");
|
|
13705
|
-
const
|
|
13835
|
+
const meta = opts.metadataSource;
|
|
13836
|
+
if (entry !== null && meta !== void 0) {
|
|
13837
|
+
throw new Error("emitTableExpression: metadataSource is for the rule-map form (entry: null); a single entry carries none");
|
|
13838
|
+
}
|
|
13839
|
+
const tail = entry !== null ? `,${jsString(entry)}` : meta === void 0 ? "" : `,${meta}`;
|
|
13706
13840
|
return [
|
|
13707
13841
|
`/* @__PURE__ */ ${ref2}({`,
|
|
13708
13842
|
...programFields(prog, fns, opts),
|
|
13709
|
-
|
|
13843
|
+
`}${tail})`
|
|
13710
13844
|
].join("\n");
|
|
13711
13845
|
}
|
|
13712
13846
|
function emitFoldedModule(folded, opts = {}) {
|
|
@@ -13801,7 +13935,8 @@ function children(def, winners) {
|
|
|
13801
13935
|
return [];
|
|
13802
13936
|
}
|
|
13803
13937
|
const name = resolved._ruleName;
|
|
13804
|
-
|
|
13938
|
+
const winner = name ? winners?.[name] : void 0;
|
|
13939
|
+
return winner !== void 0 && winner._def !== def ? [winner] : [resolved];
|
|
13805
13940
|
}
|
|
13806
13941
|
default:
|
|
13807
13942
|
return [];
|
|
@@ -13826,16 +13961,39 @@ function buildGrammarPlan(entry, winners) {
|
|
|
13826
13961
|
}
|
|
13827
13962
|
}
|
|
13828
13963
|
}
|
|
13964
|
+
const selfWinnerBody = (parser) => {
|
|
13965
|
+
if (parser._def.tag !== "lazy" || winners === void 0) return void 0;
|
|
13966
|
+
const name = winnerNames.get(parser);
|
|
13967
|
+
if (name === void 0 || winners[name] !== parser) return void 0;
|
|
13968
|
+
try {
|
|
13969
|
+
return parser._def.thunk();
|
|
13970
|
+
} catch {
|
|
13971
|
+
return void 0;
|
|
13972
|
+
}
|
|
13973
|
+
};
|
|
13974
|
+
const slotsPerBody = /* @__PURE__ */ new Map();
|
|
13975
|
+
if (winners) {
|
|
13976
|
+
for (const winner of Object.values(winners)) {
|
|
13977
|
+
const body = selfWinnerBody(winner);
|
|
13978
|
+
if (body !== void 0) slotsPerBody.set(body, (slotsPerBody.get(body) ?? 0) + 1);
|
|
13979
|
+
}
|
|
13980
|
+
}
|
|
13981
|
+
const sharedBody = (parser) => (slotsPerBody.get(parser) ?? 0) > 1;
|
|
13982
|
+
const ownRule = (parser, rule) => {
|
|
13983
|
+
const id = `rule:${rule}`;
|
|
13984
|
+
definitions.set(id, { id, kind: "rule" });
|
|
13985
|
+
rules.set(parser, id);
|
|
13986
|
+
};
|
|
13829
13987
|
const seen = /* @__PURE__ */ new Set();
|
|
13830
13988
|
const visit = (parser, path) => {
|
|
13831
13989
|
if (seen.has(parser)) return;
|
|
13832
13990
|
seen.add(parser);
|
|
13833
13991
|
const rule = winnerNames.get(parser) ?? parser._ruleName;
|
|
13834
|
-
|
|
13835
|
-
|
|
13836
|
-
|
|
13837
|
-
rules.set(parser, id);
|
|
13992
|
+
const body = selfWinnerBody(parser);
|
|
13993
|
+
if (rule && body === void 0 && !sharedBody(parser) && (winnerNames.has(parser) || parser._def.tag !== "lazy")) {
|
|
13994
|
+
ownRule(parser, rule);
|
|
13838
13995
|
}
|
|
13996
|
+
if (rule && body !== void 0 && sharedBody(body)) ownRule(parser, rule);
|
|
13839
13997
|
if (parser._def.tag === "choice") {
|
|
13840
13998
|
const ids = parser._def.parsers.map((_, index) => `choice:${path}/arm:${index}`);
|
|
13841
13999
|
choices.set(parser, ids);
|
|
@@ -13856,7 +14014,13 @@ function buildGrammarPlan(entry, winners) {
|
|
|
13856
14014
|
};
|
|
13857
14015
|
const roots = Array.isArray(entry) ? entry : [entry];
|
|
13858
14016
|
for (const root of roots) {
|
|
13859
|
-
|
|
14017
|
+
const name = winnerNames.get(root) ?? root._ruleName ?? "entry";
|
|
14018
|
+
const body = selfWinnerBody(root);
|
|
14019
|
+
if (body !== void 0 && sharedBody(body) && !seen.has(root)) {
|
|
14020
|
+
seen.add(root);
|
|
14021
|
+
ownRule(root, name);
|
|
14022
|
+
}
|
|
14023
|
+
visit(body ?? root, name);
|
|
13860
14024
|
}
|
|
13861
14025
|
return { definitions: [...definitions.values()].sort((a, b) => a.id.localeCompare(b.id)), choices, dispatches, attempts, labels, rules };
|
|
13862
14026
|
}
|
|
@@ -13880,7 +14044,7 @@ function payloadKey(p, d) {
|
|
|
13880
14044
|
case "label":
|
|
13881
14045
|
return `label\0${d.label}`;
|
|
13882
14046
|
case "field":
|
|
13883
|
-
return `field\0${d.name}`;
|
|
14047
|
+
return `field\0${d.name}\0${d.leadingTrivia === true}\0${d.trailingTrivia === true}`;
|
|
13884
14048
|
case "node":
|
|
13885
14049
|
return `node\0${d.type ?? ""}\0${d.unwrap === true}\0${d.collapse === true}\0${fnKey(d.buildSrc, d.build)}`;
|
|
13886
14050
|
case "transform":
|
|
@@ -15162,84 +15326,8 @@ function runDuplicationDiagnosticRules(ruleMap, opt) {
|
|
|
15162
15326
|
return reportDuplication(opt, (o) => analyzeDuplicationRules(ruleMap, o));
|
|
15163
15327
|
}
|
|
15164
15328
|
|
|
15165
|
-
// src/
|
|
15166
|
-
var
|
|
15167
|
-
function ownSource(fn) {
|
|
15168
|
-
if (typeof fn !== "function") return null;
|
|
15169
|
-
const text = Function.prototype.toString.call(fn);
|
|
15170
|
-
if (!text.includes("[native code]")) return text;
|
|
15171
|
-
const name = fn.name;
|
|
15172
|
-
return typeof name === "string" && name.length > 0 && globalThis[name] === fn ? name : null;
|
|
15173
|
-
}
|
|
15174
|
-
function compile(combinator, mapFnSources, opts = {}) {
|
|
15175
|
-
runDuplicationDiagnostic(combinator, opts.duplication);
|
|
15176
|
-
const drain = beginCompileDegradationDrain();
|
|
15177
|
-
let compiled = false;
|
|
15178
|
-
try {
|
|
15179
|
-
const out = compileImpl(combinator, mapFnSources, opts);
|
|
15180
|
-
compiled = true;
|
|
15181
|
-
return out;
|
|
15182
|
-
} finally {
|
|
15183
|
-
drain(compiled);
|
|
15184
|
-
}
|
|
15185
|
-
}
|
|
15186
|
-
function compileImpl(combinator, mapFnSources, opts = {}) {
|
|
15187
|
-
const plan = opts.coverage === true ? buildGrammarPlan(combinator) : void 0;
|
|
15188
|
-
const settings = {
|
|
15189
|
-
...opts.hostMode === void 0 ? {} : { hostMode: opts.hostMode },
|
|
15190
|
-
...opts.trackLines === void 0 ? {} : { trackLines: opts.trackLines },
|
|
15191
|
-
...plan === void 0 ? {} : { coverage: plan }
|
|
15192
|
-
};
|
|
15193
|
-
const { prog, fnSrcs } = encodeTableProgram({ [ENTRY]: combinator }, settings);
|
|
15194
|
-
const artifact = closureArtifact(prog);
|
|
15195
|
-
const entry = tableRules(prog)[ENTRY];
|
|
15196
|
-
const offered = opts.fnSources ?? mapFnSources;
|
|
15197
|
-
const supplied = offered !== void 0 && offered.length === fnSrcs.length ? offered : void 0;
|
|
15198
|
-
const sources = fnSrcs.map((s, i) => s ?? supplied?.[i] ?? ownSource(prog.fns[i]));
|
|
15199
|
-
const unsourced = sources.reduce((acc, s, i) => s === null ? [...acc, i] : acc, []);
|
|
15200
|
-
const runtimeOnly = [
|
|
15201
|
-
...prog.runtimeOnly ?? [],
|
|
15202
|
-
...unsourced.length === 0 ? [] : [`author reducer source missing for prog.fns[${unsourced.join(", ")}] \u2014 printing would emit \`() => {}\` and the parse would return no value`]
|
|
15203
|
-
];
|
|
15204
|
-
const printable = runtimeOnly.length === 0;
|
|
15205
|
-
const emitOpts = { fnSources: sources };
|
|
15206
|
-
const source = printable ? emitTableModule(artifact, { name: "grammar", ...emitOpts }) : "";
|
|
15207
|
-
const inlineExpression = printable ? emitTableExpression(artifact, { entry: ENTRY, runtimeRef: opts.runtimeRef ?? "tableRules", ...emitOpts }) : null;
|
|
15208
|
-
const runOnce = (input, pos, ctx) => entry(input, pos, ctx);
|
|
15209
|
-
return {
|
|
15210
|
-
source,
|
|
15211
|
-
inlineExpression,
|
|
15212
|
-
...printable ? {} : { runtimeOnly },
|
|
15213
|
-
// The DENOMINATOR, handed back rather than scraped out of the emitted text.
|
|
15214
|
-
// `plugin/index.ts` prefers a compiler-supplied `coverageDefinitions` and only
|
|
15215
|
-
// falls back to regex-scanning generated hooks; a table has no hooks to scan,
|
|
15216
|
-
// so this is the channel.
|
|
15217
|
-
...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
|
|
15218
|
-
parse(input, pos = 0) {
|
|
15219
|
-
return runOnce(input, pos, createParseContext());
|
|
15220
|
-
},
|
|
15221
|
-
parseWithContext(input, parseCtx, pos = 0) {
|
|
15222
|
-
return runOnce(input, pos, parseCtx);
|
|
15223
|
-
},
|
|
15224
|
-
/**
|
|
15225
|
-
* NO LONGER REFUSES. It used to throw unless the caller passed
|
|
15226
|
-
* `{ recovery: true }`, because setting `_tolerant` on a table with no
|
|
15227
|
-
* recovery rows would report a clean parse with an empty error list whatever
|
|
15228
|
-
* the input — refusing was the right answer to that, and OPTIONAL RECOVERY
|
|
15229
|
-
* was the wrong question. `compile()` requires no such flag, so the refusal
|
|
15230
|
-
* was a `CompiledParser` contract break; recovery is now always lowered and
|
|
15231
|
-
* there is nothing left to refuse.
|
|
15232
|
-
*/
|
|
15233
|
-
parseWithErrors(input, pos = 0) {
|
|
15234
|
-
const ctx = createParseContext();
|
|
15235
|
-
const errors = [];
|
|
15236
|
-
ctx._errors = errors;
|
|
15237
|
-
ctx._tolerant = true;
|
|
15238
|
-
const r = runOnce(input, pos, ctx);
|
|
15239
|
-
return { ...r, errors };
|
|
15240
|
-
}
|
|
15241
|
-
};
|
|
15242
|
-
}
|
|
15329
|
+
// src/cst/reflection-symbols.ts
|
|
15330
|
+
var GRAMMAR_REFLECTION = /* @__PURE__ */ Symbol.for("parseman.grammarReflection");
|
|
15243
15331
|
|
|
15244
15332
|
// src/cst/reflection.ts
|
|
15245
15333
|
function childrenOf2(def) {
|
|
@@ -15326,6 +15414,7 @@ function collectFromCombinator(parser, out, seen, followLazy = true) {
|
|
|
15326
15414
|
function collectGrammarReflection(ruleMap, opts) {
|
|
15327
15415
|
const byType = /* @__PURE__ */ new Map();
|
|
15328
15416
|
const followLazy = opts?.followLazy !== false;
|
|
15417
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15329
15418
|
for (const [, rule] of ruleMap) {
|
|
15330
15419
|
if (!followLazy && rule._def.tag === "lazy") {
|
|
15331
15420
|
try {
|
|
@@ -15335,7 +15424,7 @@ function collectGrammarReflection(ruleMap, opts) {
|
|
|
15335
15424
|
}
|
|
15336
15425
|
continue;
|
|
15337
15426
|
}
|
|
15338
|
-
collectFromCombinator(rule, byType,
|
|
15427
|
+
collectFromCombinator(rule, byType, seen, followLazy);
|
|
15339
15428
|
}
|
|
15340
15429
|
return { nodes: [...byType].map(([type, tags]) => ({ type, tags })) };
|
|
15341
15430
|
}
|
|
@@ -15371,6 +15460,24 @@ function withAmbient(ruleMap, opts) {
|
|
|
15371
15460
|
return [name, wrapped];
|
|
15372
15461
|
});
|
|
15373
15462
|
}
|
|
15463
|
+
function compileRuleMapRunnable(ruleMap, opts = {}) {
|
|
15464
|
+
const encoded = encodeForRun(ruleMap, opts);
|
|
15465
|
+
if (encoded === null) return null;
|
|
15466
|
+
const { prog, hostMode, plan } = encoded;
|
|
15467
|
+
const artifact = closureArtifact(prog);
|
|
15468
|
+
const reflection = collectGrammarReflection(ruleMap);
|
|
15469
|
+
return {
|
|
15470
|
+
keys: ruleMap.map(([key]) => key),
|
|
15471
|
+
hostMode,
|
|
15472
|
+
hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
|
|
15473
|
+
reflection,
|
|
15474
|
+
...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
|
|
15475
|
+
// Reflection rides on the map's metadata prototype from birth. Only `compile()`
|
|
15476
|
+
// asks to specialise; every other caller runs the closure artifact.
|
|
15477
|
+
rules: tableRules(opts.specialise === true ? prog : artifact, { [GRAMMAR_REFLECTION]: reflection }),
|
|
15478
|
+
prog: artifact
|
|
15479
|
+
};
|
|
15480
|
+
}
|
|
15374
15481
|
function encodeForRun(ruleMap, opts) {
|
|
15375
15482
|
runDuplicationDiagnosticRules(ruleMap, opts.duplication);
|
|
15376
15483
|
const encodeMap = withAmbient(ruleMap, opts);
|
|
@@ -15439,11 +15546,185 @@ function compileRuleMap(ruleMap, opts = {}) {
|
|
|
15439
15546
|
hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
|
|
15440
15547
|
reflection: collectGrammarReflection(ruleMap),
|
|
15441
15548
|
...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
|
|
15442
|
-
rules: tableRules(
|
|
15549
|
+
rules: tableRules(artifact),
|
|
15443
15550
|
prog: artifact
|
|
15444
15551
|
};
|
|
15445
15552
|
}
|
|
15446
15553
|
|
|
15554
|
+
// src/compiler/borrowed-rules.ts
|
|
15555
|
+
var nameOf = (c) => c._ruleName;
|
|
15556
|
+
function deref(c) {
|
|
15557
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15558
|
+
let current = c;
|
|
15559
|
+
while (current._def.tag === "lazy" && !seen.has(current)) {
|
|
15560
|
+
seen.add(current);
|
|
15561
|
+
try {
|
|
15562
|
+
current = current._def.thunk();
|
|
15563
|
+
} catch {
|
|
15564
|
+
return void 0;
|
|
15565
|
+
}
|
|
15566
|
+
}
|
|
15567
|
+
return current;
|
|
15568
|
+
}
|
|
15569
|
+
function borrowedRuleReference(map) {
|
|
15570
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15571
|
+
for (const [rule, self] of Object.entries(map)) {
|
|
15572
|
+
let found;
|
|
15573
|
+
const visit = (c) => {
|
|
15574
|
+
if (found !== void 0) return;
|
|
15575
|
+
if (c._def.tag === "lazy") {
|
|
15576
|
+
if (!winnerWrapsReference(self, c)) {
|
|
15577
|
+
const name = nameOf(c);
|
|
15578
|
+
const winner = name !== void 0 && Object.hasOwn(map, name) ? map[name] : void 0;
|
|
15579
|
+
if (winner !== void 0) {
|
|
15580
|
+
if (winnerWrapsReference(winner, c) || deref(c) === deref(winner)) return;
|
|
15581
|
+
found = name;
|
|
15582
|
+
return;
|
|
15583
|
+
}
|
|
15584
|
+
}
|
|
15585
|
+
if (seen.has(c)) return;
|
|
15586
|
+
seen.add(c);
|
|
15587
|
+
let body;
|
|
15588
|
+
try {
|
|
15589
|
+
body = c._def.thunk();
|
|
15590
|
+
} catch {
|
|
15591
|
+
return;
|
|
15592
|
+
}
|
|
15593
|
+
visit(body);
|
|
15594
|
+
return;
|
|
15595
|
+
}
|
|
15596
|
+
if (seen.has(c)) return;
|
|
15597
|
+
seen.add(c);
|
|
15598
|
+
for (const child of childrenOf(c._def)) visit(child);
|
|
15599
|
+
};
|
|
15600
|
+
visit(self);
|
|
15601
|
+
if (found !== void 0) return { rule, reference: found };
|
|
15602
|
+
}
|
|
15603
|
+
return void 0;
|
|
15604
|
+
}
|
|
15605
|
+
function borrowedRuleMessage(api, hit) {
|
|
15606
|
+
return `${api}: rule "${hit.rule}" is a rule object borrowed from another grammar, and its graph references "${hit.reference}", which this grammar also defines. The interpreter would keep the other grammar's "${hit.reference}" while a compiled table binds this grammar's, so the two would accept different input. Compose the grammar that defines "${hit.rule}" instead of borrowing its rule object, so its references resolve to this grammar's rules.`;
|
|
15607
|
+
}
|
|
15608
|
+
|
|
15609
|
+
// src/table/compile.ts
|
|
15610
|
+
var ENTRY = "Entry";
|
|
15611
|
+
function ownSource(fn) {
|
|
15612
|
+
if (typeof fn !== "function") return null;
|
|
15613
|
+
const text = Function.prototype.toString.call(fn);
|
|
15614
|
+
if (!text.includes("[native code]")) return text;
|
|
15615
|
+
const name = fn.name;
|
|
15616
|
+
return typeof name === "string" && name.length > 0 && globalThis[name] === fn ? name : null;
|
|
15617
|
+
}
|
|
15618
|
+
function compile(target, second, third) {
|
|
15619
|
+
if (!isCombinator(target)) return compileMap(target, second);
|
|
15620
|
+
return compileRoot(target, second, third);
|
|
15621
|
+
}
|
|
15622
|
+
function isCombinator(x) {
|
|
15623
|
+
return typeof x === "object" && x !== null && typeof x.parse === "function" && "_def" in x;
|
|
15624
|
+
}
|
|
15625
|
+
function compileMap(grammar, opts = {}) {
|
|
15626
|
+
const entries = [];
|
|
15627
|
+
for (const [key, value] of Object.entries(grammar)) {
|
|
15628
|
+
if (!isCombinator(value)) throw new TypeError(`compile: grammar entry "${key}" is not a parser`);
|
|
15629
|
+
if (value._def.tag === "lazy") {
|
|
15630
|
+
try {
|
|
15631
|
+
value._def.thunk();
|
|
15632
|
+
} catch {
|
|
15633
|
+
continue;
|
|
15634
|
+
}
|
|
15635
|
+
}
|
|
15636
|
+
entries.push([key, value]);
|
|
15637
|
+
}
|
|
15638
|
+
const borrowed = borrowedRuleReference(Object.fromEntries(entries));
|
|
15639
|
+
if (borrowed !== void 0) throw new Error(borrowedRuleMessage("compile", borrowed));
|
|
15640
|
+
const drain = beginCompileDegradationDrain();
|
|
15641
|
+
let done = false;
|
|
15642
|
+
try {
|
|
15643
|
+
const refusals = [];
|
|
15644
|
+
const compiled = compileRuleMapRunnable(entries, {
|
|
15645
|
+
...opts.hostMode ? { hostMode: opts.hostMode } : {},
|
|
15646
|
+
refusals,
|
|
15647
|
+
specialise: true
|
|
15648
|
+
});
|
|
15649
|
+
if (compiled === null) {
|
|
15650
|
+
throw new Error(`compile: this grammar could not be encoded to a table${refusals.length ? ` \u2014 ${refusals.join("; ")}` : ""}`);
|
|
15651
|
+
}
|
|
15652
|
+
done = true;
|
|
15653
|
+
return compiled.rules;
|
|
15654
|
+
} finally {
|
|
15655
|
+
drain(done);
|
|
15656
|
+
}
|
|
15657
|
+
}
|
|
15658
|
+
function compileRoot(combinator, mapFnSources, opts = {}) {
|
|
15659
|
+
runDuplicationDiagnostic(combinator, opts.duplication);
|
|
15660
|
+
const drain = beginCompileDegradationDrain();
|
|
15661
|
+
let compiled = false;
|
|
15662
|
+
try {
|
|
15663
|
+
const out = compileImpl(combinator, mapFnSources, opts);
|
|
15664
|
+
compiled = true;
|
|
15665
|
+
return out;
|
|
15666
|
+
} finally {
|
|
15667
|
+
drain(compiled);
|
|
15668
|
+
}
|
|
15669
|
+
}
|
|
15670
|
+
function compileImpl(combinator, mapFnSources, opts = {}) {
|
|
15671
|
+
const plan = opts.coverage === true ? buildGrammarPlan(combinator) : void 0;
|
|
15672
|
+
const settings = {
|
|
15673
|
+
...opts.hostMode === void 0 ? {} : { hostMode: opts.hostMode },
|
|
15674
|
+
...opts.trackLines === void 0 ? {} : { trackLines: opts.trackLines },
|
|
15675
|
+
...plan === void 0 ? {} : { coverage: plan }
|
|
15676
|
+
};
|
|
15677
|
+
const { prog, fnSrcs } = encodeTableProgram({ [ENTRY]: combinator }, settings);
|
|
15678
|
+
const artifact = closureArtifact(prog);
|
|
15679
|
+
const entry = tableRules(prog)[ENTRY];
|
|
15680
|
+
const offered = opts.fnSources ?? mapFnSources;
|
|
15681
|
+
const supplied = offered !== void 0 && offered.length === fnSrcs.length ? offered : void 0;
|
|
15682
|
+
const sources = fnSrcs.map((s, i) => s ?? supplied?.[i] ?? ownSource(prog.fns[i]));
|
|
15683
|
+
const unsourced = sources.reduce((acc, s, i) => s === null ? [...acc, i] : acc, []);
|
|
15684
|
+
const runtimeOnly = [
|
|
15685
|
+
...prog.runtimeOnly ?? [],
|
|
15686
|
+
...unsourced.length === 0 ? [] : [`author reducer source missing for prog.fns[${unsourced.join(", ")}] \u2014 printing would emit \`() => {}\` and the parse would return no value`]
|
|
15687
|
+
];
|
|
15688
|
+
const printable = runtimeOnly.length === 0;
|
|
15689
|
+
const emitOpts = { fnSources: sources };
|
|
15690
|
+
const source = printable ? emitTableModule(artifact, { name: "grammar", ...emitOpts }) : "";
|
|
15691
|
+
const inlineExpression = printable ? emitTableExpression(artifact, { entry: ENTRY, runtimeRef: opts.runtimeRef ?? "tableRules", ...emitOpts }) : null;
|
|
15692
|
+
const runOnce = (input, pos, ctx) => entry(input, pos, ctx);
|
|
15693
|
+
return {
|
|
15694
|
+
source,
|
|
15695
|
+
inlineExpression,
|
|
15696
|
+
...printable ? {} : { runtimeOnly },
|
|
15697
|
+
// The DENOMINATOR, handed back rather than scraped out of the emitted text.
|
|
15698
|
+
// `plugin/index.ts` prefers a compiler-supplied `coverageDefinitions` and only
|
|
15699
|
+
// falls back to regex-scanning generated hooks; a table has no hooks to scan,
|
|
15700
|
+
// so this is the channel.
|
|
15701
|
+
...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
|
|
15702
|
+
parse(input, pos = 0) {
|
|
15703
|
+
return runOnce(input, pos, createParseContext());
|
|
15704
|
+
},
|
|
15705
|
+
parseWithContext(input, parseCtx, pos = 0) {
|
|
15706
|
+
return runOnce(input, pos, parseCtx);
|
|
15707
|
+
},
|
|
15708
|
+
/**
|
|
15709
|
+
* NO LONGER REFUSES. It used to throw unless the caller passed
|
|
15710
|
+
* `{ recovery: true }`, because setting `_tolerant` on a table with no
|
|
15711
|
+
* recovery rows would report a clean parse with an empty error list whatever
|
|
15712
|
+
* the input — refusing was the right answer to that, and OPTIONAL RECOVERY
|
|
15713
|
+
* was the wrong question. `compile()` requires no such flag, so the refusal
|
|
15714
|
+
* was a `CompiledParser` contract break; recovery is now always lowered and
|
|
15715
|
+
* there is nothing left to refuse.
|
|
15716
|
+
*/
|
|
15717
|
+
parseWithErrors(input, pos = 0) {
|
|
15718
|
+
const ctx = createParseContext();
|
|
15719
|
+
const errors = [];
|
|
15720
|
+
ctx._errors = errors;
|
|
15721
|
+
ctx._tolerant = true;
|
|
15722
|
+
const r = runOnce(input, pos, ctx);
|
|
15723
|
+
return { ...r, errors };
|
|
15724
|
+
}
|
|
15725
|
+
};
|
|
15726
|
+
}
|
|
15727
|
+
|
|
15447
15728
|
// src/table/fold.ts
|
|
15448
15729
|
function tableVariants(source, name) {
|
|
15449
15730
|
const folded = "base" in source ? source : expandCompactFolded(source);
|