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/index.js
CHANGED
|
@@ -1659,65 +1659,17 @@ function plainRegexSource(p) {
|
|
|
1659
1659
|
const d = p._def;
|
|
1660
1660
|
return d.tag === "regex" && d.flags === "" ? d.source : null;
|
|
1661
1661
|
}
|
|
1662
|
-
var visitSpec0;
|
|
1663
|
-
var visitSpec1;
|
|
1664
|
-
var visitSpec2;
|
|
1665
|
-
var visitSpec3;
|
|
1666
|
-
var visitValue0;
|
|
1667
|
-
var visitValue1;
|
|
1668
|
-
var visitValue2;
|
|
1669
|
-
var visitValue3;
|
|
1670
1662
|
function commonLabeledTriviaVisitor(spec) {
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
if (spec === visitSpec2) return visitValue2;
|
|
1674
|
-
if (spec === visitSpec3) return visitValue3;
|
|
1675
|
-
const sources = spec.minRepeats <= 1 ? spec.arms.map((arm) => plainRegexSource(arm.parser)) : [];
|
|
1676
|
-
const visitor = commonCssTriviaVisitor(sources);
|
|
1677
|
-
visitSpec3 = visitSpec2;
|
|
1678
|
-
visitValue3 = visitValue2;
|
|
1679
|
-
visitSpec2 = visitSpec1;
|
|
1680
|
-
visitValue2 = visitValue1;
|
|
1681
|
-
visitSpec1 = visitSpec0;
|
|
1682
|
-
visitValue1 = visitValue0;
|
|
1683
|
-
visitSpec0 = spec;
|
|
1684
|
-
visitValue0 = visitor;
|
|
1685
|
-
return visitor;
|
|
1686
|
-
}
|
|
1687
|
-
var armSpec0;
|
|
1688
|
-
var armSpec1;
|
|
1689
|
-
var armSpec2;
|
|
1690
|
-
var armSpec3;
|
|
1691
|
-
var armValue0;
|
|
1692
|
-
var armValue1;
|
|
1693
|
-
var armValue2;
|
|
1694
|
-
var armValue3;
|
|
1663
|
+
return commonCssTriviaVisitor(spec.minRepeats <= 1 ? spec.arms.map((arm) => plainRegexSource(arm.parser)) : []);
|
|
1664
|
+
}
|
|
1695
1665
|
function charArmsFor(spec) {
|
|
1696
|
-
if (spec
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
arms = null;
|
|
1703
|
-
} else {
|
|
1704
|
-
for (const arm of spec.arms) {
|
|
1705
|
-
const c = classifyParser(arm.parser);
|
|
1706
|
-
if (!c) {
|
|
1707
|
-
arms = null;
|
|
1708
|
-
break;
|
|
1709
|
-
}
|
|
1710
|
-
arms.push(c);
|
|
1711
|
-
}
|
|
1666
|
+
if (spec.minRepeats > 1) return null;
|
|
1667
|
+
const arms = [];
|
|
1668
|
+
for (const arm of spec.arms) {
|
|
1669
|
+
const c = classifyParser(arm.parser);
|
|
1670
|
+
if (!c) return null;
|
|
1671
|
+
arms.push(c);
|
|
1712
1672
|
}
|
|
1713
|
-
armSpec3 = armSpec2;
|
|
1714
|
-
armValue3 = armValue2;
|
|
1715
|
-
armSpec2 = armSpec1;
|
|
1716
|
-
armValue2 = armValue1;
|
|
1717
|
-
armSpec1 = armSpec0;
|
|
1718
|
-
armValue1 = armValue0;
|
|
1719
|
-
armSpec0 = spec;
|
|
1720
|
-
armValue0 = arms;
|
|
1721
1673
|
return arms;
|
|
1722
1674
|
}
|
|
1723
1675
|
function charTriviaEnd(input, cur, arms) {
|
|
@@ -1833,12 +1785,16 @@ function analyzeLabeledTrivia(trivia2) {
|
|
|
1833
1785
|
}
|
|
1834
1786
|
arms.push({ label: peeled.label, kindIndex: 0, parser: peeled.parser });
|
|
1835
1787
|
}
|
|
1836
|
-
|
|
1788
|
+
return cacheLabeledTrivia(trivia2, labeledTriviaSpec(arms, minRepeats));
|
|
1789
|
+
}
|
|
1790
|
+
function labeledTriviaSpec(arms, minRepeats) {
|
|
1791
|
+
return {
|
|
1837
1792
|
labels: arms.map((a) => a.label),
|
|
1838
1793
|
arms,
|
|
1839
|
-
minRepeats
|
|
1794
|
+
minRepeats,
|
|
1795
|
+
visitor: commonLabeledTriviaVisitor({ arms, minRepeats }),
|
|
1796
|
+
charArms: charArmsFor({ arms, minRepeats })
|
|
1840
1797
|
};
|
|
1841
|
-
return cacheLabeledTrivia(trivia2, spec);
|
|
1842
1798
|
}
|
|
1843
1799
|
function matchArmAt(input, pos, arm, state) {
|
|
1844
1800
|
if (!startsFirstSet(arm, input, pos)) return null;
|
|
@@ -1868,7 +1824,7 @@ function scanLabeledTriviaChunks(input, cur, spec, state) {
|
|
|
1868
1824
|
return { end: pos, chunks };
|
|
1869
1825
|
}
|
|
1870
1826
|
function scanLabeledTriviaEnd(input, cur, spec, state) {
|
|
1871
|
-
const chars =
|
|
1827
|
+
const chars = spec.charArms;
|
|
1872
1828
|
if (chars !== null) return charTriviaEnd(input, cur, chars);
|
|
1873
1829
|
let pos = cur;
|
|
1874
1830
|
let count = 0;
|
|
@@ -1886,9 +1842,9 @@ function scanLabeledTriviaEnd(input, cur, spec, state) {
|
|
|
1886
1842
|
}
|
|
1887
1843
|
function visitLabeledTrivia(input, cur, spec, state, visit) {
|
|
1888
1844
|
if (spec.minRepeats > 1) return void 0;
|
|
1889
|
-
const common =
|
|
1845
|
+
const common = spec.visitor;
|
|
1890
1846
|
if (common !== null) return common(input, cur, visit);
|
|
1891
|
-
const chars =
|
|
1847
|
+
const chars = spec.charArms;
|
|
1892
1848
|
if (chars !== null) return charTriviaVisit(input, cur, chars, visit);
|
|
1893
1849
|
let pos = cur;
|
|
1894
1850
|
let count = 0;
|
|
@@ -1955,7 +1911,7 @@ function resolveAdjacencyKindMask(trivia2, kinds) {
|
|
|
1955
1911
|
return mask;
|
|
1956
1912
|
}
|
|
1957
1913
|
function triviaKindMaskAt(input, pos, spec, state) {
|
|
1958
|
-
const chars =
|
|
1914
|
+
const chars = spec.charArms;
|
|
1959
1915
|
if (chars !== null) return charTriviaKindMask(input, pos, chars);
|
|
1960
1916
|
let cur = pos;
|
|
1961
1917
|
let mask = 0;
|
|
@@ -2739,6 +2695,23 @@ function scalarRootOf(combinator) {
|
|
|
2739
2695
|
return scalar !== void 0 && def.tag === "grammar" && scalarTree(def.parser, /* @__PURE__ */ new Set()) ? scalar : void 0;
|
|
2740
2696
|
}
|
|
2741
2697
|
|
|
2698
|
+
// src/combinators/field-trivia.ts
|
|
2699
|
+
var LEAD = { at: -1 };
|
|
2700
|
+
var FIELD_LEADING_TRIVIA = 1;
|
|
2701
|
+
var FIELD_TRAILING_TRIVIA = 2;
|
|
2702
|
+
function triviaFieldCapture(name, value, input, start, end, leadFrom, trailEnd) {
|
|
2703
|
+
return {
|
|
2704
|
+
name,
|
|
2705
|
+
value,
|
|
2706
|
+
span: { start, end },
|
|
2707
|
+
leading: leadFrom >= 0 && leadFrom < start ? input.slice(leadFrom, start) : "",
|
|
2708
|
+
trailing: trailEnd > end ? input.slice(end, trailEnd) : ""
|
|
2709
|
+
};
|
|
2710
|
+
}
|
|
2711
|
+
function leadsTrivia(p) {
|
|
2712
|
+
return p._def.tag === "field" && p._def.leadingTrivia === true;
|
|
2713
|
+
}
|
|
2714
|
+
|
|
2742
2715
|
// src/combinators/sequence.ts
|
|
2743
2716
|
function sequence(...parsers) {
|
|
2744
2717
|
let adjacency = null;
|
|
@@ -2754,6 +2727,10 @@ function sequence(...parsers) {
|
|
|
2754
2727
|
(adjacency ??= Array.from({ length: parsers.length }, () => null))[i] = a;
|
|
2755
2728
|
}
|
|
2756
2729
|
const hasAdjacency = adjacency !== null;
|
|
2730
|
+
let leading = null;
|
|
2731
|
+
for (let i = 1; i < parsers.length; i++) {
|
|
2732
|
+
if (leadsTrivia(parsers[i])) (leading ??= Array.from({ length: parsers.length }, () => false))[i] = true;
|
|
2733
|
+
}
|
|
2757
2734
|
const strictArity = !hasAdjacency && (parsers.length === 2 && !matchesEmpty(parsers[1]) || parsers.length === 3 && parsers.every((p) => !matchesEmpty(p))) ? parsers.length : 0;
|
|
2758
2735
|
const meta = {
|
|
2759
2736
|
// Union through the nullable prefix — a leading optional()/many() lets a later
|
|
@@ -2801,7 +2778,7 @@ function sequence(...parsers) {
|
|
|
2801
2778
|
_tag: "sequence",
|
|
2802
2779
|
_meta: meta,
|
|
2803
2780
|
_def: def,
|
|
2804
|
-
_parseScalar: hasAdjacency ? void 0 : parseScalar,
|
|
2781
|
+
_parseScalar: hasAdjacency || leading !== null ? void 0 : parseScalar,
|
|
2805
2782
|
parse(input, pos, ctx) {
|
|
2806
2783
|
const tolerant = ctx._tolerant === true;
|
|
2807
2784
|
if (tolerant) {
|
|
@@ -2835,6 +2812,7 @@ function sequence(...parsers) {
|
|
|
2835
2812
|
const scanTlog = deferredTrivia ? cstTlLen(ctx) : 0;
|
|
2836
2813
|
const scanLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
|
|
2837
2814
|
const scanRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
2815
|
+
if (leading?.[i] === true) LEAD.at = cur;
|
|
2838
2816
|
const result = parsers[i].parse(input, termPos, ctx);
|
|
2839
2817
|
if (!result.ok) return result;
|
|
2840
2818
|
if (values !== void 0) values.push(result.value);
|
|
@@ -3816,6 +3794,7 @@ function unwrapSeparator(separator) {
|
|
|
3816
3794
|
}
|
|
3817
3795
|
function sepBy(combinator, separatorArg, opts = {}) {
|
|
3818
3796
|
const { sep: separator, keep: keepSeparators } = unwrapSeparator(separatorArg);
|
|
3797
|
+
const separatorLeads = leadsTrivia(separator);
|
|
3819
3798
|
const { min, max } = resolveBounds("sepBy()", opts);
|
|
3820
3799
|
const trailing = opts.trailing ?? "forbid";
|
|
3821
3800
|
const meta = {
|
|
@@ -3880,7 +3859,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
|
|
|
3880
3859
|
// this option surface already; parity is held by test/parity, not by hope.
|
|
3881
3860
|
...keepSeparators ? { keepSeparators: true } : {}
|
|
3882
3861
|
},
|
|
3883
|
-
_parseScalar: keepSeparators ? void 0 : parseScalar,
|
|
3862
|
+
_parseScalar: keepSeparators || separatorLeads ? void 0 : parseScalar,
|
|
3884
3863
|
parse(input, pos, ctx) {
|
|
3885
3864
|
const first = combinator.parse(input, pos, ctx);
|
|
3886
3865
|
const values = [];
|
|
@@ -3912,6 +3891,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
|
|
|
3912
3891
|
sepPos = advanceTrivia(input, cur, ctx);
|
|
3913
3892
|
}
|
|
3914
3893
|
}
|
|
3894
|
+
if (separatorLeads) LEAD.at = cur;
|
|
3915
3895
|
const sep = separator.parse(input, sepPos, ctx);
|
|
3916
3896
|
if (!sep.ok) {
|
|
3917
3897
|
rollbackTrivia(ctx, loopMark);
|
|
@@ -4005,6 +3985,7 @@ function withRuleTrivia(trivia2, ctx, run3) {
|
|
|
4005
3985
|
ctx.triviaKindLabels = savedLabels;
|
|
4006
3986
|
}
|
|
4007
3987
|
}
|
|
3988
|
+
var UNDEFINED_REF = new Error("ref<T>() used before .define() was called");
|
|
4008
3989
|
function ref() {
|
|
4009
3990
|
let resolved = null;
|
|
4010
3991
|
let resolvedScalar = null;
|
|
@@ -4020,7 +4001,7 @@ function ref() {
|
|
|
4020
4001
|
_def: {
|
|
4021
4002
|
tag: "lazy",
|
|
4022
4003
|
thunk: () => {
|
|
4023
|
-
if (!resolved) throw
|
|
4004
|
+
if (!resolved) throw UNDEFINED_REF;
|
|
4024
4005
|
return resolved;
|
|
4025
4006
|
}
|
|
4026
4007
|
},
|
|
@@ -4410,6 +4391,7 @@ function collectFromCombinator(parser2, out, seen, followLazy = true) {
|
|
|
4410
4391
|
function collectGrammarReflection(ruleMap, opts) {
|
|
4411
4392
|
const byType = /* @__PURE__ */ new Map();
|
|
4412
4393
|
const followLazy = opts?.followLazy !== false;
|
|
4394
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4413
4395
|
for (const [, rule] of ruleMap) {
|
|
4414
4396
|
if (!followLazy && rule._def.tag === "lazy") {
|
|
4415
4397
|
try {
|
|
@@ -4419,7 +4401,7 @@ function collectGrammarReflection(ruleMap, opts) {
|
|
|
4419
4401
|
}
|
|
4420
4402
|
continue;
|
|
4421
4403
|
}
|
|
4422
|
-
collectFromCombinator(rule, byType,
|
|
4404
|
+
collectFromCombinator(rule, byType, seen, followLazy);
|
|
4423
4405
|
}
|
|
4424
4406
|
return { nodes: [...byType].map(([type, tags]) => ({ type, tags })) };
|
|
4425
4407
|
}
|
|
@@ -4450,9 +4432,26 @@ function isNamedRuleRefForAnotherRule(r, key) {
|
|
|
4450
4432
|
const name = r._def.tag === "lazy" ? ruleNameOf(r) : void 0;
|
|
4451
4433
|
return name !== void 0 && name !== key;
|
|
4452
4434
|
}
|
|
4435
|
+
var claimedRules = /* @__PURE__ */ new WeakSet();
|
|
4436
|
+
function ownRule(p, copies) {
|
|
4437
|
+
if (!claimedRules.has(p) || p._meta.isTrivia) return p;
|
|
4438
|
+
let own = copies.get(p);
|
|
4439
|
+
if (own === void 0) {
|
|
4440
|
+
const { grammarTrivia: _t, grammarScanSkip: _s, grammarHostMode: _h, grammarTrackLines: _l, ...meta } = p._meta;
|
|
4441
|
+
copies.set(p, own = { ...p, _meta: meta });
|
|
4442
|
+
}
|
|
4443
|
+
return own;
|
|
4444
|
+
}
|
|
4453
4445
|
function rules(a, b) {
|
|
4454
4446
|
const factory = typeof a === "function" ? a : b;
|
|
4455
4447
|
const options = typeof a === "function" ? b : a;
|
|
4448
|
+
const recipe = { factory, options };
|
|
4449
|
+
const map = linkRules([recipe]);
|
|
4450
|
+
Object.defineProperty(map, RULES_RECIPE, { value: [recipe], enumerable: false });
|
|
4451
|
+
return map;
|
|
4452
|
+
}
|
|
4453
|
+
var RULES_RECIPE = /* @__PURE__ */ Symbol.for("parseman.rulesRecipe");
|
|
4454
|
+
function linkRules(recipes, link) {
|
|
4456
4455
|
const cache = {};
|
|
4457
4456
|
const proxy = new Proxy(cache, {
|
|
4458
4457
|
get(target, key) {
|
|
@@ -4466,10 +4465,18 @@ function rules(a, b) {
|
|
|
4466
4465
|
return record[key];
|
|
4467
4466
|
}
|
|
4468
4467
|
});
|
|
4469
|
-
const
|
|
4470
|
-
for (const
|
|
4468
|
+
const winners = /* @__PURE__ */ new Map();
|
|
4469
|
+
for (const recipe of recipes) {
|
|
4470
|
+
const definitions = recipe.factory(proxy);
|
|
4471
|
+
for (const key of Object.keys(definitions)) {
|
|
4472
|
+
winners.set(key, { parser: definitions[key], options: recipe.options });
|
|
4473
|
+
}
|
|
4474
|
+
}
|
|
4475
|
+
const keys = [...winners.keys()];
|
|
4476
|
+
const copies = /* @__PURE__ */ new Map();
|
|
4477
|
+
for (const [key, { parser: defined }] of winners) {
|
|
4471
4478
|
const placeholder = cache[key];
|
|
4472
|
-
const parser2 =
|
|
4479
|
+
const parser2 = ownRule(defined, copies);
|
|
4473
4480
|
if (placeholder === parser2) {
|
|
4474
4481
|
throw new Error(`rules(): rule "${key}" cannot be a direct alias to itself`);
|
|
4475
4482
|
}
|
|
@@ -4478,7 +4485,8 @@ function rules(a, b) {
|
|
|
4478
4485
|
placeholder.define(parser2);
|
|
4479
4486
|
placeholder._meta.firstSet = parser2._meta.firstSet;
|
|
4480
4487
|
placeholder._meta.canMatchNewline = parser2._meta.canMatchNewline;
|
|
4481
|
-
} else if (isNamedRuleRefForAnotherRule(parser2, key)) {
|
|
4488
|
+
} else if (isNamedRuleRefForAnotherRule(parser2, key) || link !== void 0) {
|
|
4489
|
+
if (!isNamedRuleRefForAnotherRule(parser2, key)) tagRule(parser2, key);
|
|
4482
4490
|
const alias = ref();
|
|
4483
4491
|
tagRule(alias, key);
|
|
4484
4492
|
alias.define(parser2);
|
|
@@ -4490,48 +4498,34 @@ function rules(a, b) {
|
|
|
4490
4498
|
cache[key] = parser2;
|
|
4491
4499
|
}
|
|
4492
4500
|
}
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
if (
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
}
|
|
4511
|
-
if (options?.trackLines === true) {
|
|
4512
|
-
for (const key of Object.keys(definitions)) {
|
|
4513
|
-
const rule = cache[key];
|
|
4514
|
-
if (rule && !rule._meta.isTrivia) rule._meta.grammarTrackLines = true;
|
|
4515
|
-
}
|
|
4516
|
-
for (const key of Object.keys(definitions)) {
|
|
4517
|
-
const rule = cache[key];
|
|
4518
|
-
if (rule && !rule._meta.isTrivia && rule._def.tag !== "grammar") {
|
|
4519
|
-
const wrapped = parser({ trackLines: true }, rule);
|
|
4520
|
-
tagRule(wrapped, key);
|
|
4521
|
-
wrapped._meta.grammarTrackLines = true;
|
|
4522
|
-
cache[key] = wrapped;
|
|
4501
|
+
for (const key of keys) {
|
|
4502
|
+
const options = winners.get(key).options;
|
|
4503
|
+
let rule = cache[key];
|
|
4504
|
+
if (!rule._meta.isTrivia) {
|
|
4505
|
+
const meta = rule._meta;
|
|
4506
|
+
const trivia2 = link !== void 0 ? link.trivia : options?.trivia;
|
|
4507
|
+
if (trivia2 != null) meta.grammarTrivia = trivia2;
|
|
4508
|
+
if (options?.scanSkip != null) meta.grammarScanSkip = options.scanSkip;
|
|
4509
|
+
if ((link?.hostMode ?? options?.hostMode) === "cst") meta.grammarHostMode = "cst";
|
|
4510
|
+
if (options?.trackLines === true) {
|
|
4511
|
+
meta.grammarTrackLines = true;
|
|
4512
|
+
if (rule._def.tag !== "grammar") {
|
|
4513
|
+
rule = parser({ trackLines: true }, rule);
|
|
4514
|
+
tagRule(rule, key);
|
|
4515
|
+
rule._meta.grammarTrackLines = true;
|
|
4516
|
+
cache[key] = rule;
|
|
4517
|
+
}
|
|
4523
4518
|
}
|
|
4524
4519
|
}
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
markUnusedValues(cache[key]);
|
|
4520
|
+
markUnusedValues(rule);
|
|
4521
|
+
claimedRules.add(winners.get(key).parser).add(rule);
|
|
4528
4522
|
}
|
|
4529
4523
|
Object.defineProperty(cache, RULE_ORDER, {
|
|
4530
|
-
value:
|
|
4524
|
+
value: keys,
|
|
4531
4525
|
enumerable: false,
|
|
4532
4526
|
configurable: true
|
|
4533
4527
|
});
|
|
4534
|
-
attachGrammarReflection(cache, collectGrammarReflection(
|
|
4528
|
+
attachGrammarReflection(cache, collectGrammarReflection(keys.map((key) => [key, cache[key]])));
|
|
4535
4529
|
return cache;
|
|
4536
4530
|
}
|
|
4537
4531
|
|
|
@@ -4914,7 +4908,7 @@ function buildFieldMap(captures) {
|
|
|
4914
4908
|
if (!captures?.length) return void 0;
|
|
4915
4909
|
const out = {};
|
|
4916
4910
|
for (const cap of captures) {
|
|
4917
|
-
const entry = { value: cap.value, span: cap.span };
|
|
4911
|
+
const entry = cap.leading === void 0 ? { value: cap.value, span: cap.span } : { value: cap.value, span: cap.span, leading: cap.leading, trailing: cap.trailing };
|
|
4918
4912
|
const current = out[cap.name];
|
|
4919
4913
|
if (current === void 0) out[cap.name] = entry;
|
|
4920
4914
|
else if (Array.isArray(current)) current.push(entry);
|
|
@@ -5146,16 +5140,41 @@ function label(name, combinator) {
|
|
|
5146
5140
|
}
|
|
5147
5141
|
};
|
|
5148
5142
|
}
|
|
5149
|
-
function field(name, combinator) {
|
|
5143
|
+
function field(name, combinator, opts) {
|
|
5144
|
+
const leadingTrivia = opts?.leadingTrivia === true;
|
|
5145
|
+
const trailingTrivia = opts?.trailingTrivia === true;
|
|
5146
|
+
if (!leadingTrivia && !trailingTrivia) {
|
|
5147
|
+
return {
|
|
5148
|
+
_tag: combinator._tag,
|
|
5149
|
+
_meta: combinator._meta,
|
|
5150
|
+
_def: { tag: "field", name, parser: combinator },
|
|
5151
|
+
parse(input, pos, ctx) {
|
|
5152
|
+
const result = combinator.parse(input, pos, ctx);
|
|
5153
|
+
if (!result.ok) return result;
|
|
5154
|
+
ctx._fields?.push({ name, value: result.value, span: result.span });
|
|
5155
|
+
return result;
|
|
5156
|
+
}
|
|
5157
|
+
};
|
|
5158
|
+
}
|
|
5150
5159
|
return {
|
|
5151
5160
|
_tag: combinator._tag,
|
|
5152
5161
|
_meta: combinator._meta,
|
|
5153
|
-
_def: {
|
|
5162
|
+
_def: {
|
|
5163
|
+
tag: "field",
|
|
5164
|
+
name,
|
|
5165
|
+
parser: combinator,
|
|
5166
|
+
...leadingTrivia ? { leadingTrivia: true } : {},
|
|
5167
|
+
...trailingTrivia ? { trailingTrivia: true } : {}
|
|
5168
|
+
},
|
|
5154
5169
|
parse(input, pos, ctx) {
|
|
5170
|
+
const leadFrom = LEAD.at;
|
|
5171
|
+
LEAD.at = -1;
|
|
5155
5172
|
const result = combinator.parse(input, pos, ctx);
|
|
5156
5173
|
if (!result.ok) return result;
|
|
5157
|
-
|
|
5158
|
-
|
|
5174
|
+
const end = result.span.end;
|
|
5175
|
+
const trailEnd = trailingTrivia && ctx.trivia ? consumeTrivia(input, end, ctx) : end;
|
|
5176
|
+
ctx._fields?.push(triviaFieldCapture(name, result.value, input, result.span.start, end, leadingTrivia ? leadFrom : -1, trailEnd));
|
|
5177
|
+
return trailEnd === end ? result : { ok: true, value: result.value, span: { start: result.span.start, end: trailEnd } };
|
|
5159
5178
|
}
|
|
5160
5179
|
};
|
|
5161
5180
|
}
|
|
@@ -5676,15 +5695,15 @@ function formatGatingWarnings(report) {
|
|
|
5676
5695
|
return lines;
|
|
5677
5696
|
}
|
|
5678
5697
|
function ruleDependencies(ruleMap) {
|
|
5679
|
-
const
|
|
5680
|
-
for (const [name, comb] of ruleMap)
|
|
5698
|
+
const nameOf2 = /* @__PURE__ */ new Map();
|
|
5699
|
+
for (const [name, comb] of ruleMap) nameOf2.set(comb, name);
|
|
5681
5700
|
const deps = /* @__PURE__ */ new Map();
|
|
5682
5701
|
for (const [name, comb] of ruleMap) {
|
|
5683
5702
|
const found = /* @__PURE__ */ new Set();
|
|
5684
5703
|
const seen = /* @__PURE__ */ new Set();
|
|
5685
5704
|
const walk = (p, isRoot) => {
|
|
5686
5705
|
const def = p._def;
|
|
5687
|
-
const boundary = def.tag === "lazy" ?
|
|
5706
|
+
const boundary = def.tag === "lazy" ? nameOf2.get(p) ?? p._ruleName : nameOf2.get(p);
|
|
5688
5707
|
if (!isRoot && boundary !== void 0) {
|
|
5689
5708
|
found.add(boundary);
|
|
5690
5709
|
return;
|
|
@@ -7593,6 +7612,16 @@ var Encoder = class {
|
|
|
7593
7612
|
this.kIndex.set(key, i);
|
|
7594
7613
|
return i;
|
|
7595
7614
|
}
|
|
7615
|
+
fieldSpecIndex = /* @__PURE__ */ new Map();
|
|
7616
|
+
fieldSpecSlot(name, bits) {
|
|
7617
|
+
const key = JSON.stringify([name, bits]);
|
|
7618
|
+
const hit = this.fieldSpecIndex.get(key);
|
|
7619
|
+
if (hit !== void 0) return hit;
|
|
7620
|
+
const i = this.k.length;
|
|
7621
|
+
this.k.push([name, bits]);
|
|
7622
|
+
this.fieldSpecIndex.set(key, i);
|
|
7623
|
+
return i;
|
|
7624
|
+
}
|
|
7596
7625
|
/**
|
|
7597
7626
|
* A `notAdjacent({ kinds })` filter, pooled by its CONTENTS.
|
|
7598
7627
|
*
|
|
@@ -8213,8 +8242,10 @@ var Encoder = class {
|
|
|
8213
8242
|
for (let i = 0; i < arms.length; i++) this.code[head + 6 + i] = arms[i];
|
|
8214
8243
|
return head;
|
|
8215
8244
|
}
|
|
8216
|
-
case "field":
|
|
8217
|
-
|
|
8245
|
+
case "field": {
|
|
8246
|
+
const bits = (d.leadingTrivia === true ? FIELD_LEADING_TRIVIA : 0) | (d.trailingTrivia === true ? FIELD_TRAILING_TRIVIA : 0);
|
|
8247
|
+
return this.emit(OP_FIELD, bits === 0 ? this.constant(d.name) : this.fieldSpecSlot(d.name, bits), this.node(d.parser).ip);
|
|
8248
|
+
}
|
|
8218
8249
|
case "lazy": {
|
|
8219
8250
|
const refName = p._ruleName;
|
|
8220
8251
|
const winner = refName === void 0 ? void 0 : this.winners?.[refName];
|
|
@@ -9890,6 +9921,26 @@ function leadingLiteralFamily(code, constants, ip, minDepth = 2, limit = 4) {
|
|
|
9890
9921
|
};
|
|
9891
9922
|
return walk(ip, 0);
|
|
9892
9923
|
}
|
|
9924
|
+
function largeChoiceLiteralPretest(code, constants, armIp) {
|
|
9925
|
+
const child = leadingScalarTerminal(code, armIp, 2, true, true);
|
|
9926
|
+
if (child >= 0) {
|
|
9927
|
+
const spec = constants[code[child + 1]];
|
|
9928
|
+
if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) return [child];
|
|
9929
|
+
}
|
|
9930
|
+
const family = leadingLiteralFamily(code, constants, armIp);
|
|
9931
|
+
return family !== void 0 && family.length >= 2 && family.every((terminal) => {
|
|
9932
|
+
const value = constants[code[terminal + 1]];
|
|
9933
|
+
return typeof value === "string" && value.length >= 2;
|
|
9934
|
+
}) ? family : void 0;
|
|
9935
|
+
}
|
|
9936
|
+
|
|
9937
|
+
// src/table/field-spec.ts
|
|
9938
|
+
function fieldSpec(slot) {
|
|
9939
|
+
return Array.isArray(slot) ? { name: slot[0], bits: slot[1] } : { name: slot, bits: 0 };
|
|
9940
|
+
}
|
|
9941
|
+
function leadingTriviaFieldAt(code, k, ip) {
|
|
9942
|
+
return code[ip] === OP_FIELD && (fieldSpec(k[code[ip + 1]]).bits & FIELD_LEADING_TRIVIA) !== 0;
|
|
9943
|
+
}
|
|
9893
9944
|
|
|
9894
9945
|
// src/table/emit-assembly.ts
|
|
9895
9946
|
var Unemittable = class extends Error {
|
|
@@ -9964,7 +10015,11 @@ var EMITTED_PARAMS = [
|
|
|
9964
10015
|
// Appended for old precompiled-factory ABI: old factories ignore it.
|
|
9965
10016
|
"adjacencyHolds",
|
|
9966
10017
|
// Appended for selected composite lexical programs; old factories ignore it.
|
|
9967
|
-
"LEXPROG"
|
|
10018
|
+
"LEXPROG",
|
|
10019
|
+
// Appended for trivia-attributing fields (`field(…, { leadingTrivia })`);
|
|
10020
|
+
// old factories ignore them.
|
|
10021
|
+
"LEAD",
|
|
10022
|
+
"triviaFieldCapture"
|
|
9968
10023
|
];
|
|
9969
10024
|
var RUNTIME_PRELUDE = `
|
|
9970
10025
|
let _pfScan=null
|
|
@@ -10224,20 +10279,12 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
|
|
|
10224
10279
|
if (child >= 0) scalarSpecs.add(code[child + 1]);
|
|
10225
10280
|
continue;
|
|
10226
10281
|
}
|
|
10227
|
-
|
|
10228
|
-
|
|
10229
|
-
|
|
10230
|
-
|
|
10231
|
-
continue;
|
|
10232
|
-
}
|
|
10233
|
-
}
|
|
10234
|
-
const family = leadingLiteralFamily(code, k, armIp);
|
|
10235
|
-
if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
|
|
10236
|
-
const value = k[code[terminal + 1]];
|
|
10237
|
-
return typeof value === "string" && value.length >= 2;
|
|
10238
|
-
})) {
|
|
10239
|
-
largeChoiceLiteralFamilies.set(armIp, family);
|
|
10282
|
+
const literals = largeChoiceLiteralPretest(code, k, armIp);
|
|
10283
|
+
if (literals !== void 0 && literals.length === 1 && literals[0] === child) {
|
|
10284
|
+
largeChoiceScalarSpecs.add(code[child + 1]);
|
|
10285
|
+
continue;
|
|
10240
10286
|
}
|
|
10287
|
+
if (literals !== void 0) largeChoiceLiteralFamilies.set(armIp, literals);
|
|
10241
10288
|
const sequence6 = leadingScalarSequence(code, armIp);
|
|
10242
10289
|
if (sequence6 !== void 0 && (sequence6.trivia < 0 || swapLegal && t.triviaScan[sequence6.trivia] != null)) {
|
|
10243
10290
|
largeChoiceScalarSequences.set(armIp, sequence6);
|
|
@@ -10661,14 +10708,31 @@ return v
|
|
|
10661
10708
|
}`;
|
|
10662
10709
|
}
|
|
10663
10710
|
case OP_FIELD: {
|
|
10664
|
-
const
|
|
10711
|
+
const spec = fieldSpec(k[code[ip + 1]]);
|
|
10712
|
+
const name = q(spec.name);
|
|
10665
10713
|
const child = link(code[ip + 2]);
|
|
10666
|
-
|
|
10714
|
+
if (spec.bits === 0) {
|
|
10715
|
+
return `${head}
|
|
10667
10716
|
const v=${child}(input,pos,ctx)
|
|
10668
10717
|
if(v===FAIL)return FAIL
|
|
10669
10718
|
const f=ctx._fields
|
|
10670
10719
|
if(f!==undefined)f.push({name:${name},value:v,span:{start:pos,end:EC.e}})
|
|
10671
10720
|
return v
|
|
10721
|
+
}`;
|
|
10722
|
+
}
|
|
10723
|
+
const leading = (spec.bits & FIELD_LEADING_TRIVIA) !== 0;
|
|
10724
|
+
const trailing = (spec.bits & FIELD_TRAILING_TRIVIA) !== 0;
|
|
10725
|
+
return `${head}
|
|
10726
|
+
const lf=${leading ? "LEAD.at" : "-1"}
|
|
10727
|
+
LEAD.at=-1
|
|
10728
|
+
const v=${child}(input,pos,ctx)
|
|
10729
|
+
if(v===FAIL)return FAIL
|
|
10730
|
+
const e=EC.e
|
|
10731
|
+
const te=${trailing ? "ctx.trivia!==undefined?consumeTrivia(input,e,ctx):e" : "e"}
|
|
10732
|
+
const f=ctx._fields
|
|
10733
|
+
if(f!==undefined)f.push(triviaFieldCapture(${name},v,input,pos,e,lf,te))
|
|
10734
|
+
EC.e=te
|
|
10735
|
+
return v
|
|
10672
10736
|
}`;
|
|
10673
10737
|
}
|
|
10674
10738
|
case OP_EXPECT: {
|
|
@@ -10964,7 +11028,10 @@ return v
|
|
|
10964
11028
|
`if(!adjacencyHolds(input,cur,ctx,${negated ? "true" : "false"},${kinds})){ctx._fe=cur;ctx._fx=${expected};return FAIL}`,
|
|
10965
11029
|
`${vn}=null`
|
|
10966
11030
|
);
|
|
10967
|
-
} else
|
|
11031
|
+
} else {
|
|
11032
|
+
const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
|
|
11033
|
+
parts.push(emitTerm(callee, vn, tmp(), L, skipFor(L)));
|
|
11034
|
+
}
|
|
10968
11035
|
names.push(vn);
|
|
10969
11036
|
}
|
|
10970
11037
|
parts.push("EC.e=cur");
|
|
@@ -11364,7 +11431,7 @@ let sp=cur
|
|
|
11364
11431
|
${hasTrivia === "false" ? "" : hasTrivia === "true" ? `sp=${skip}(input,sp,ctx)
|
|
11365
11432
|
` : `if(hasTrivia)sp=${skip}(input,sp,ctx)
|
|
11366
11433
|
`}ctx._fc=false
|
|
11367
|
-
const sv=${sep}(input,sp,ctx)
|
|
11434
|
+
${sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp) ? "LEAD.at=cur\n" : ""}const sv=${sep}(input,sp,ctx)
|
|
11368
11435
|
if(sv===FAIL){
|
|
11369
11436
|
${rb}
|
|
11370
11437
|
if(ctx._fc===true)return FAIL
|
|
@@ -12474,6 +12541,12 @@ function assemble(t, prog, cfg) {
|
|
|
12474
12541
|
rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
|
|
12475
12542
|
return cur;
|
|
12476
12543
|
}
|
|
12544
|
+
function leadingFieldTerm(step, child, input, cur, ctx) {
|
|
12545
|
+
return step((i, p, c) => {
|
|
12546
|
+
LEAD.at = cur;
|
|
12547
|
+
return child(i, p, c);
|
|
12548
|
+
}, input, cur, ctx);
|
|
12549
|
+
}
|
|
12477
12550
|
function committed3(c) {
|
|
12478
12551
|
return c._fc === true;
|
|
12479
12552
|
}
|
|
@@ -13111,12 +13184,27 @@ function assemble(t, prog, cfg) {
|
|
|
13111
13184
|
};
|
|
13112
13185
|
}
|
|
13113
13186
|
case OP_FIELD: {
|
|
13114
|
-
const name = k[code[ip + 1]];
|
|
13187
|
+
const { name, bits } = fieldSpec(k[code[ip + 1]]);
|
|
13115
13188
|
const child = link(code[ip + 2]);
|
|
13189
|
+
if (bits === 0) {
|
|
13190
|
+
return (input, pos, ctx) => {
|
|
13191
|
+
const v = child(input, pos, ctx);
|
|
13192
|
+
if (v === FAIL) return FAIL;
|
|
13193
|
+
ctx._fields?.push({ name, value: v, span: { start: pos, end: EC.e } });
|
|
13194
|
+
return v;
|
|
13195
|
+
};
|
|
13196
|
+
}
|
|
13197
|
+
const leading = (bits & FIELD_LEADING_TRIVIA) !== 0;
|
|
13198
|
+
const trailing = (bits & FIELD_TRAILING_TRIVIA) !== 0;
|
|
13116
13199
|
return (input, pos, ctx) => {
|
|
13200
|
+
const leadFrom = leading ? LEAD.at : -1;
|
|
13201
|
+
LEAD.at = -1;
|
|
13117
13202
|
const v = child(input, pos, ctx);
|
|
13118
13203
|
if (v === FAIL) return FAIL;
|
|
13119
|
-
|
|
13204
|
+
const end = EC.e;
|
|
13205
|
+
const trailEnd = trailing && ctx.trivia !== void 0 ? consumeTrivia(input, end, ctx) : end;
|
|
13206
|
+
ctx._fields?.push(triviaFieldCapture(name, v, input, pos, end, leadFrom, trailEnd));
|
|
13207
|
+
EC.e = trailEnd;
|
|
13120
13208
|
return v;
|
|
13121
13209
|
};
|
|
13122
13210
|
}
|
|
@@ -13550,6 +13638,12 @@ function assemble(t, prog, cfg) {
|
|
|
13550
13638
|
const kidIp = code[base + i];
|
|
13551
13639
|
if (code[kidIp] !== OP_ADJ) {
|
|
13552
13640
|
const kid = link(kidIp);
|
|
13641
|
+
if (leadingTriviaFieldAt(code, k, kidIp)) {
|
|
13642
|
+
return (input, cur, ctx, inherited) => {
|
|
13643
|
+
ctx._sync = sync ?? inherited;
|
|
13644
|
+
return leadingFieldTerm(step, kid, input, cur, ctx);
|
|
13645
|
+
};
|
|
13646
|
+
}
|
|
13553
13647
|
return (input, cur, ctx, inherited) => {
|
|
13554
13648
|
ctx._sync = sync ?? inherited;
|
|
13555
13649
|
return step(kid, input, cur, ctx);
|
|
@@ -13627,9 +13721,12 @@ function assemble(t, prog, cfg) {
|
|
|
13627
13721
|
};
|
|
13628
13722
|
}
|
|
13629
13723
|
let hasAdj = false;
|
|
13630
|
-
for (let i = 1; i < n; i++)
|
|
13631
|
-
|
|
13632
|
-
|
|
13724
|
+
for (let i = 1; i < n; i++) {
|
|
13725
|
+
const kidIp = code[base + i];
|
|
13726
|
+
if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp)) {
|
|
13727
|
+
hasAdj = true;
|
|
13728
|
+
break;
|
|
13729
|
+
}
|
|
13633
13730
|
}
|
|
13634
13731
|
if (hasAdj) {
|
|
13635
13732
|
const first2 = link(code[base]);
|
|
@@ -13637,6 +13734,9 @@ function assemble(t, prog, cfg) {
|
|
|
13637
13734
|
const kidIp = code[base + i];
|
|
13638
13735
|
if (code[kidIp] !== OP_ADJ) {
|
|
13639
13736
|
const kid = link(kidIp);
|
|
13737
|
+
if (leadingTriviaFieldAt(code, k, kidIp)) {
|
|
13738
|
+
return (input, cur, ctx) => leadingFieldTerm(step, kid, input, cur, ctx);
|
|
13739
|
+
}
|
|
13640
13740
|
return (input, cur, ctx) => step(kid, input, cur, ctx);
|
|
13641
13741
|
}
|
|
13642
13742
|
const negated = code[kidIp + 1] === 1;
|
|
@@ -13999,7 +14099,7 @@ function assemble(t, prog, cfg) {
|
|
|
13999
14099
|
if (n === 2 || n === 3) {
|
|
14000
14100
|
const a0 = link(code[base]), a1 = link(code[base + 1]);
|
|
14001
14101
|
const a2 = n === 3 ? link(code[base + 2]) : void 0;
|
|
14002
|
-
const predecide = !
|
|
14102
|
+
const predecide = !REC2 && !cfg.probe && !cfg.coverage && !cfg.trackLines;
|
|
14003
14103
|
const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
|
|
14004
14104
|
const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
|
|
14005
14105
|
const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
|
|
@@ -14222,6 +14322,75 @@ function assemble(t, prog, cfg) {
|
|
|
14222
14322
|
);
|
|
14223
14323
|
};
|
|
14224
14324
|
const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
|
|
14325
|
+
const pBit = [];
|
|
14326
|
+
const pRec = [];
|
|
14327
|
+
if (!REC2 && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
|
|
14328
|
+
for (let i = 0; i < n; i++) {
|
|
14329
|
+
for (const terminal of largeChoiceLiteralPretest(code, k, code[base + i]) ?? []) {
|
|
14330
|
+
pBit.push(1 << i);
|
|
14331
|
+
pRec.push(scalarFor(terminal));
|
|
14332
|
+
}
|
|
14333
|
+
}
|
|
14334
|
+
}
|
|
14335
|
+
const pn = pBit.length;
|
|
14336
|
+
if (pn !== 0) {
|
|
14337
|
+
return (input, pos, ctx) => {
|
|
14338
|
+
const c = lead(input, pos);
|
|
14339
|
+
const need = markCst(ctx);
|
|
14340
|
+
const mRaw = MRAW;
|
|
14341
|
+
const mTl = MTL;
|
|
14342
|
+
const mLv = MLV;
|
|
14343
|
+
const mFl = need ? ctx._fields?.length ?? 0 : 0;
|
|
14344
|
+
const mEr = need ? ctx._errors?.length ?? 0 : 0;
|
|
14345
|
+
const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
14346
|
+
const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14347
|
+
if (c < 128) {
|
|
14348
|
+
const bits = mask[c < 0 ? 128 : c];
|
|
14349
|
+
let tested = 0;
|
|
14350
|
+
let hit = 0;
|
|
14351
|
+
for (let i = 0; i < pn; i++) {
|
|
14352
|
+
const b = pBit[i];
|
|
14353
|
+
if ((bits & b) === 0 || (hit & b) !== 0) continue;
|
|
14354
|
+
tested |= b;
|
|
14355
|
+
if (pRec[i](input, pos) >= 0) hit |= b;
|
|
14356
|
+
}
|
|
14357
|
+
return masked(
|
|
14358
|
+
input,
|
|
14359
|
+
pos,
|
|
14360
|
+
ctx,
|
|
14361
|
+
bits & (~tested | hit),
|
|
14362
|
+
need,
|
|
14363
|
+
mRaw,
|
|
14364
|
+
mTl,
|
|
14365
|
+
mLv,
|
|
14366
|
+
mFl,
|
|
14367
|
+
mEr,
|
|
14368
|
+
mLog,
|
|
14369
|
+
mRoot,
|
|
14370
|
+
void 0,
|
|
14371
|
+
0,
|
|
14372
|
+
pos
|
|
14373
|
+
);
|
|
14374
|
+
}
|
|
14375
|
+
return general(
|
|
14376
|
+
input,
|
|
14377
|
+
pos,
|
|
14378
|
+
ctx,
|
|
14379
|
+
c,
|
|
14380
|
+
need,
|
|
14381
|
+
mRaw,
|
|
14382
|
+
mTl,
|
|
14383
|
+
mLv,
|
|
14384
|
+
mFl,
|
|
14385
|
+
mEr,
|
|
14386
|
+
mLog,
|
|
14387
|
+
mRoot,
|
|
14388
|
+
void 0,
|
|
14389
|
+
0,
|
|
14390
|
+
pos
|
|
14391
|
+
);
|
|
14392
|
+
};
|
|
14393
|
+
}
|
|
14225
14394
|
return (input, pos, ctx) => {
|
|
14226
14395
|
const c = lead(input, pos);
|
|
14227
14396
|
const need = markCst(ctx);
|
|
@@ -14383,6 +14552,7 @@ function assemble(t, prog, cfg) {
|
|
|
14383
14552
|
const max = code[ip + 3];
|
|
14384
14553
|
const sepIp = code[ip + 4];
|
|
14385
14554
|
const sep = sepIp >= 0 ? link(sepIp) : void 0;
|
|
14555
|
+
const sepLeads = sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp);
|
|
14386
14556
|
const flags = code[ip + 5];
|
|
14387
14557
|
const keepSeparators = (flags & 2) !== 0;
|
|
14388
14558
|
const trailingAllowed = (flags & 1) !== 0;
|
|
@@ -14422,6 +14592,7 @@ function assemble(t, prog, cfg) {
|
|
|
14422
14592
|
let sp = cur;
|
|
14423
14593
|
if (hasTrivia) sp = skipTrivia(input, sp, ctx);
|
|
14424
14594
|
ctx._fc = false;
|
|
14595
|
+
if (sepLeads) LEAD.at = cur;
|
|
14425
14596
|
const sv = sep(input, sp, ctx);
|
|
14426
14597
|
if (sv === FAIL) {
|
|
14427
14598
|
if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
@@ -14511,6 +14682,7 @@ function assemble(t, prog, cfg) {
|
|
|
14511
14682
|
let sp = cur;
|
|
14512
14683
|
if (hasTrivia) sp = skipTrivia(input, sp, ctx);
|
|
14513
14684
|
ctx._fc = false;
|
|
14685
|
+
if (sepLeads) LEAD.at = cur;
|
|
14514
14686
|
const sv = sep(input, sp, ctx);
|
|
14515
14687
|
if (sv === FAIL) {
|
|
14516
14688
|
if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
@@ -14833,20 +15005,9 @@ function assemble(t, prog, cfg) {
|
|
|
14833
15005
|
if (child >= 0) scalarFor(child);
|
|
14834
15006
|
continue;
|
|
14835
15007
|
}
|
|
14836
|
-
|
|
14837
|
-
|
|
14838
|
-
|
|
14839
|
-
scalarFor(child);
|
|
14840
|
-
continue;
|
|
14841
|
-
}
|
|
14842
|
-
}
|
|
14843
|
-
const family = leadingLiteralFamily(code, k, armIp);
|
|
14844
|
-
if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
|
|
14845
|
-
const value = k[code[terminal + 1]];
|
|
14846
|
-
return typeof value === "string" && value.length >= 2;
|
|
14847
|
-
})) {
|
|
14848
|
-
for (const terminal of family) scalarFor(terminal);
|
|
14849
|
-
}
|
|
15008
|
+
const literals = largeChoiceLiteralPretest(code, k, armIp);
|
|
15009
|
+
if (literals !== void 0) for (const terminal of literals) scalarFor(terminal);
|
|
15010
|
+
if (literals !== void 0 && literals.length === 1 && literals[0] === child) continue;
|
|
14850
15011
|
const sequence6 = leadingScalarSequence(code, armIp);
|
|
14851
15012
|
if (sequence6 !== void 0 && (sequence6.trivia < 0 || triviaScan[sequence6.trivia] != null)) {
|
|
14852
15013
|
for (const terminal of sequence6.terminals) scalarFor(terminal);
|
|
@@ -14912,7 +15073,9 @@ function assemble(t, prog, cfg) {
|
|
|
14912
15073
|
scanTriviaCompact,
|
|
14913
15074
|
t.lex,
|
|
14914
15075
|
adjacencyHolds,
|
|
14915
|
-
t.lexPrograms
|
|
15076
|
+
t.lexPrograms,
|
|
15077
|
+
LEAD,
|
|
15078
|
+
triviaFieldCapture
|
|
14916
15079
|
);
|
|
14917
15080
|
emitReached = new Set(pre.reached);
|
|
14918
15081
|
}
|
|
@@ -14994,7 +15157,9 @@ function assemble(t, prog, cfg) {
|
|
|
14994
15157
|
scanTriviaCompact,
|
|
14995
15158
|
t.lex,
|
|
14996
15159
|
adjacencyHolds,
|
|
14997
|
-
t.lexPrograms
|
|
15160
|
+
t.lexPrograms,
|
|
15161
|
+
LEAD,
|
|
15162
|
+
triviaFieldCapture
|
|
14998
15163
|
);
|
|
14999
15164
|
emitReached = em.reached;
|
|
15000
15165
|
} catch (e) {
|
|
@@ -15170,7 +15335,9 @@ var AssemblyCache = class {
|
|
|
15170
15335
|
return made;
|
|
15171
15336
|
}
|
|
15172
15337
|
};
|
|
15173
|
-
function tableRules(source,
|
|
15338
|
+
function tableRules(source, metadataOrEntry = {}) {
|
|
15339
|
+
const entry = typeof metadataOrEntry === "string" ? metadataOrEntry : void 0;
|
|
15340
|
+
const artifactMetadata = typeof metadataOrEntry === "string" ? {} : metadataOrEntry;
|
|
15174
15341
|
const prog = expandCompact(source);
|
|
15175
15342
|
const resolved = resolveTable(prog);
|
|
15176
15343
|
const cache = new AssemblyCache(prog, resolved);
|
|
@@ -15178,7 +15345,7 @@ function tableRules(source, artifactMetadata = {}) {
|
|
|
15178
15345
|
const skipOf = prog.scanSkipOf;
|
|
15179
15346
|
let last;
|
|
15180
15347
|
let selected;
|
|
15181
|
-
|
|
15348
|
+
const map = stampRuleMap(prog, {
|
|
15182
15349
|
runRule: (ri, input, pos, ctx) => {
|
|
15183
15350
|
const a = selected ?? cache.forCtx(ctx);
|
|
15184
15351
|
selected = void 0;
|
|
@@ -15199,6 +15366,9 @@ function tableRules(source, artifactMetadata = {}) {
|
|
|
15199
15366
|
return a.scanSkip[skipOf?.[ri] ?? -1];
|
|
15200
15367
|
}
|
|
15201
15368
|
}, artifactMetadata, resolved);
|
|
15369
|
+
if (entry === void 0) return map;
|
|
15370
|
+
if (!Object.hasOwn(map, entry)) throw new Error(`tableRules: the program has no rule ${JSON.stringify(entry)}`);
|
|
15371
|
+
return map[entry];
|
|
15202
15372
|
}
|
|
15203
15373
|
|
|
15204
15374
|
// src/table/emit.ts
|
|
@@ -15364,11 +15534,15 @@ function emitTableExpression(prog, opts = {}) {
|
|
|
15364
15534
|
const entry = opts.entry === void 0 ? "grammar" : opts.entry;
|
|
15365
15535
|
const ref2 = opts.runtimeRef ?? "tableRules";
|
|
15366
15536
|
const fns = opts.fnSources ?? prog.fns.map(() => "() => {}");
|
|
15367
|
-
const
|
|
15537
|
+
const meta = opts.metadataSource;
|
|
15538
|
+
if (entry !== null && meta !== void 0) {
|
|
15539
|
+
throw new Error("emitTableExpression: metadataSource is for the rule-map form (entry: null); a single entry carries none");
|
|
15540
|
+
}
|
|
15541
|
+
const tail = entry !== null ? `,${jsString(entry)}` : meta === void 0 ? "" : `,${meta}`;
|
|
15368
15542
|
return [
|
|
15369
15543
|
`/* @__PURE__ */ ${ref2}({`,
|
|
15370
15544
|
...programFields(prog, fns, opts),
|
|
15371
|
-
|
|
15545
|
+
`}${tail})`
|
|
15372
15546
|
].join("\n");
|
|
15373
15547
|
}
|
|
15374
15548
|
|
|
@@ -15437,7 +15611,8 @@ function children(def, winners) {
|
|
|
15437
15611
|
return [];
|
|
15438
15612
|
}
|
|
15439
15613
|
const name = resolved._ruleName;
|
|
15440
|
-
|
|
15614
|
+
const winner = name ? winners?.[name] : void 0;
|
|
15615
|
+
return winner !== void 0 && winner._def !== def ? [winner] : [resolved];
|
|
15441
15616
|
}
|
|
15442
15617
|
default:
|
|
15443
15618
|
return [];
|
|
@@ -15462,16 +15637,39 @@ function buildGrammarPlan(entry, winners) {
|
|
|
15462
15637
|
}
|
|
15463
15638
|
}
|
|
15464
15639
|
}
|
|
15640
|
+
const selfWinnerBody = (parser2) => {
|
|
15641
|
+
if (parser2._def.tag !== "lazy" || winners === void 0) return void 0;
|
|
15642
|
+
const name = winnerNames.get(parser2);
|
|
15643
|
+
if (name === void 0 || winners[name] !== parser2) return void 0;
|
|
15644
|
+
try {
|
|
15645
|
+
return parser2._def.thunk();
|
|
15646
|
+
} catch {
|
|
15647
|
+
return void 0;
|
|
15648
|
+
}
|
|
15649
|
+
};
|
|
15650
|
+
const slotsPerBody = /* @__PURE__ */ new Map();
|
|
15651
|
+
if (winners) {
|
|
15652
|
+
for (const winner of Object.values(winners)) {
|
|
15653
|
+
const body = selfWinnerBody(winner);
|
|
15654
|
+
if (body !== void 0) slotsPerBody.set(body, (slotsPerBody.get(body) ?? 0) + 1);
|
|
15655
|
+
}
|
|
15656
|
+
}
|
|
15657
|
+
const sharedBody = (parser2) => (slotsPerBody.get(parser2) ?? 0) > 1;
|
|
15658
|
+
const ownRule2 = (parser2, rule) => {
|
|
15659
|
+
const id = `rule:${rule}`;
|
|
15660
|
+
definitions.set(id, { id, kind: "rule" });
|
|
15661
|
+
rules2.set(parser2, id);
|
|
15662
|
+
};
|
|
15465
15663
|
const seen = /* @__PURE__ */ new Set();
|
|
15466
15664
|
const visit = (parser2, path) => {
|
|
15467
15665
|
if (seen.has(parser2)) return;
|
|
15468
15666
|
seen.add(parser2);
|
|
15469
15667
|
const rule = winnerNames.get(parser2) ?? parser2._ruleName;
|
|
15470
|
-
|
|
15471
|
-
|
|
15472
|
-
|
|
15473
|
-
rules2.set(parser2, id);
|
|
15668
|
+
const body = selfWinnerBody(parser2);
|
|
15669
|
+
if (rule && body === void 0 && !sharedBody(parser2) && (winnerNames.has(parser2) || parser2._def.tag !== "lazy")) {
|
|
15670
|
+
ownRule2(parser2, rule);
|
|
15474
15671
|
}
|
|
15672
|
+
if (rule && body !== void 0 && sharedBody(body)) ownRule2(parser2, rule);
|
|
15475
15673
|
if (parser2._def.tag === "choice") {
|
|
15476
15674
|
const ids = parser2._def.parsers.map((_, index) => `choice:${path}/arm:${index}`);
|
|
15477
15675
|
choices.set(parser2, ids);
|
|
@@ -15492,7 +15690,13 @@ function buildGrammarPlan(entry, winners) {
|
|
|
15492
15690
|
};
|
|
15493
15691
|
const roots = Array.isArray(entry) ? entry : [entry];
|
|
15494
15692
|
for (const root of roots) {
|
|
15495
|
-
|
|
15693
|
+
const name = winnerNames.get(root) ?? root._ruleName ?? "entry";
|
|
15694
|
+
const body = selfWinnerBody(root);
|
|
15695
|
+
if (body !== void 0 && sharedBody(body) && !seen.has(root)) {
|
|
15696
|
+
seen.add(root);
|
|
15697
|
+
ownRule2(root, name);
|
|
15698
|
+
}
|
|
15699
|
+
visit(body ?? root, name);
|
|
15496
15700
|
}
|
|
15497
15701
|
return { definitions: [...definitions.values()].sort((a, b) => a.id.localeCompare(b.id)), choices, dispatches, attempts, labels, rules: rules2 };
|
|
15498
15702
|
}
|
|
@@ -15516,7 +15720,7 @@ function payloadKey(p, d) {
|
|
|
15516
15720
|
case "label":
|
|
15517
15721
|
return `label\0${d.label}`;
|
|
15518
15722
|
case "field":
|
|
15519
|
-
return `field\0${d.name}`;
|
|
15723
|
+
return `field\0${d.name}\0${d.leadingTrivia === true}\0${d.trailingTrivia === true}`;
|
|
15520
15724
|
case "node":
|
|
15521
15725
|
return `node\0${d.type ?? ""}\0${d.unwrap === true}\0${d.collapse === true}\0${fnKey(d.buildSrc, d.build)}`;
|
|
15522
15726
|
case "transform":
|
|
@@ -16798,104 +17002,298 @@ function runDuplicationDiagnosticRules(ruleMap, opt) {
|
|
|
16798
17002
|
return reportDuplication(opt, (o) => analyzeDuplicationRules(ruleMap, o));
|
|
16799
17003
|
}
|
|
16800
17004
|
|
|
16801
|
-
// src/table/compile.ts
|
|
16802
|
-
var
|
|
16803
|
-
function
|
|
16804
|
-
|
|
16805
|
-
const text = Function.prototype.toString.call(fn);
|
|
16806
|
-
if (!text.includes("[native code]")) return text;
|
|
16807
|
-
const name = fn.name;
|
|
16808
|
-
return typeof name === "string" && name.length > 0 && globalThis[name] === fn ? name : null;
|
|
17005
|
+
// src/table/compile-rule-map.ts
|
|
17006
|
+
var DEFAULT_PRECOMPILE_MIN_WORDS = 1024;
|
|
17007
|
+
function resolveHostMode(ruleMap, explicit) {
|
|
17008
|
+
return explicit ?? ruleMap.map(([, r]) => r._meta.grammarHostMode).find(Boolean) ?? "ast";
|
|
16809
17009
|
}
|
|
16810
|
-
function
|
|
16811
|
-
|
|
16812
|
-
const drain = beginCompileDegradationDrain();
|
|
16813
|
-
let compiled = false;
|
|
16814
|
-
try {
|
|
16815
|
-
const out = compileImpl(combinator, mapFnSources, opts);
|
|
16816
|
-
compiled = true;
|
|
16817
|
-
return out;
|
|
16818
|
-
} finally {
|
|
16819
|
-
drain(compiled);
|
|
16820
|
-
}
|
|
17010
|
+
function resolveTrackLines(ruleMap, explicit) {
|
|
17011
|
+
return explicit === true || ruleMap.some(([, r]) => r._meta.grammarTrackLines === true);
|
|
16821
17012
|
}
|
|
16822
|
-
function
|
|
16823
|
-
|
|
16824
|
-
const
|
|
16825
|
-
|
|
16826
|
-
|
|
16827
|
-
|
|
16828
|
-
|
|
16829
|
-
|
|
17013
|
+
function withAmbient(ruleMap, opts) {
|
|
17014
|
+
if (opts.trivia === void 0 && opts.scanSkip === void 0) return ruleMap;
|
|
17015
|
+
const wrappers = /* @__PURE__ */ new Map();
|
|
17016
|
+
return ruleMap.map(([name, rule]) => {
|
|
17017
|
+
if (rule._meta.isTrivia) return [name, rule];
|
|
17018
|
+
const addTrivia = opts.trivia !== void 0 && rule._meta.grammarTrivia === void 0;
|
|
17019
|
+
const addScanSkip = opts.scanSkip !== void 0 && rule._meta.grammarScanSkip === void 0;
|
|
17020
|
+
if (!addTrivia && !addScanSkip) return [name, rule];
|
|
17021
|
+
let wrapped = wrappers.get(rule);
|
|
17022
|
+
if (wrapped === void 0) {
|
|
17023
|
+
wrapped = {
|
|
17024
|
+
...rule,
|
|
17025
|
+
_meta: {
|
|
17026
|
+
...rule._meta,
|
|
17027
|
+
...addTrivia ? { grammarTrivia: opts.trivia } : {},
|
|
17028
|
+
...addScanSkip ? { grammarScanSkip: opts.scanSkip } : {}
|
|
17029
|
+
}
|
|
17030
|
+
};
|
|
17031
|
+
wrappers.set(rule, wrapped);
|
|
17032
|
+
}
|
|
17033
|
+
return [name, wrapped];
|
|
17034
|
+
});
|
|
17035
|
+
}
|
|
17036
|
+
function compileRuleMapRunnable(ruleMap, opts = {}) {
|
|
17037
|
+
const encoded = encodeForRun(ruleMap, opts);
|
|
17038
|
+
if (encoded === null) return null;
|
|
17039
|
+
const { prog, hostMode, plan } = encoded;
|
|
16830
17040
|
const artifact = closureArtifact(prog);
|
|
16831
|
-
const
|
|
16832
|
-
const offered = opts.fnSources ?? mapFnSources;
|
|
16833
|
-
const supplied = offered !== void 0 && offered.length === fnSrcs.length ? offered : void 0;
|
|
16834
|
-
const sources = fnSrcs.map((s, i) => s ?? supplied?.[i] ?? ownSource(prog.fns[i]));
|
|
16835
|
-
const unsourced = sources.reduce((acc, s, i) => s === null ? [...acc, i] : acc, []);
|
|
16836
|
-
const runtimeOnly = [
|
|
16837
|
-
...prog.runtimeOnly ?? [],
|
|
16838
|
-
...unsourced.length === 0 ? [] : [`author reducer source missing for prog.fns[${unsourced.join(", ")}] \u2014 printing would emit \`() => {}\` and the parse would return no value`]
|
|
16839
|
-
];
|
|
16840
|
-
const printable = runtimeOnly.length === 0;
|
|
16841
|
-
const emitOpts = { fnSources: sources };
|
|
16842
|
-
const source = printable ? emitTableModule(artifact, { name: "grammar", ...emitOpts }) : "";
|
|
16843
|
-
const inlineExpression = printable ? emitTableExpression(artifact, { entry: ENTRY, runtimeRef: opts.runtimeRef ?? "tableRules", ...emitOpts }) : null;
|
|
16844
|
-
const runOnce2 = (input, pos, ctx) => entry(input, pos, ctx);
|
|
17041
|
+
const reflection = collectGrammarReflection(ruleMap);
|
|
16845
17042
|
return {
|
|
16846
|
-
|
|
16847
|
-
|
|
16848
|
-
|
|
16849
|
-
|
|
16850
|
-
// `plugin/index.ts` prefers a compiler-supplied `coverageDefinitions` and only
|
|
16851
|
-
// falls back to regex-scanning generated hooks; a table has no hooks to scan,
|
|
16852
|
-
// so this is the channel.
|
|
17043
|
+
keys: ruleMap.map(([key]) => key),
|
|
17044
|
+
hostMode,
|
|
17045
|
+
hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
|
|
17046
|
+
reflection,
|
|
16853
17047
|
...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
|
|
16854
|
-
|
|
16855
|
-
|
|
16856
|
-
},
|
|
16857
|
-
|
|
16858
|
-
return runOnce2(input, pos, parseCtx);
|
|
16859
|
-
},
|
|
16860
|
-
/**
|
|
16861
|
-
* NO LONGER REFUSES. It used to throw unless the caller passed
|
|
16862
|
-
* `{ recovery: true }`, because setting `_tolerant` on a table with no
|
|
16863
|
-
* recovery rows would report a clean parse with an empty error list whatever
|
|
16864
|
-
* the input — refusing was the right answer to that, and OPTIONAL RECOVERY
|
|
16865
|
-
* was the wrong question. `compile()` requires no such flag, so the refusal
|
|
16866
|
-
* was a `CompiledParser` contract break; recovery is now always lowered and
|
|
16867
|
-
* there is nothing left to refuse.
|
|
16868
|
-
*/
|
|
16869
|
-
parseWithErrors(input, pos = 0) {
|
|
16870
|
-
const ctx = createParseContext();
|
|
16871
|
-
const errors = [];
|
|
16872
|
-
ctx._errors = errors;
|
|
16873
|
-
ctx._tolerant = true;
|
|
16874
|
-
const r = runOnce2(input, pos, ctx);
|
|
16875
|
-
return { ...r, errors };
|
|
16876
|
-
}
|
|
17048
|
+
// Reflection rides on the map's metadata prototype from birth. Only `compile()`
|
|
17049
|
+
// asks to specialise; every other caller runs the closure artifact.
|
|
17050
|
+
rules: tableRules(opts.specialise === true ? prog : artifact, { [GRAMMAR_REFLECTION]: reflection }),
|
|
17051
|
+
prog: artifact
|
|
16877
17052
|
};
|
|
16878
17053
|
}
|
|
16879
|
-
|
|
16880
|
-
|
|
16881
|
-
|
|
16882
|
-
const
|
|
16883
|
-
|
|
16884
|
-
|
|
16885
|
-
|
|
16886
|
-
|
|
16887
|
-
|
|
16888
|
-
|
|
16889
|
-
|
|
16890
|
-
|
|
16891
|
-
|
|
16892
|
-
|
|
16893
|
-
|
|
16894
|
-
|
|
16895
|
-
|
|
16896
|
-
|
|
16897
|
-
|
|
17054
|
+
function encodeForRun(ruleMap, opts) {
|
|
17055
|
+
runDuplicationDiagnosticRules(ruleMap, opts.duplication);
|
|
17056
|
+
const encodeMap = withAmbient(ruleMap, opts);
|
|
17057
|
+
const plan = opts.coverage === true ? buildGrammarPlan(
|
|
17058
|
+
encodeMap.map(([, rule]) => rule),
|
|
17059
|
+
Object.fromEntries(encodeMap.filter(([, rule]) => rule._def.tag !== "lazy"))
|
|
17060
|
+
) : void 0;
|
|
17061
|
+
const hostMode = resolveHostMode(ruleMap, opts.hostMode);
|
|
17062
|
+
const settings = {
|
|
17063
|
+
hostMode,
|
|
17064
|
+
...resolveTrackLines(ruleMap, opts.trackLines) ? { trackLines: true } : {},
|
|
17065
|
+
...opts.recovery === true ? { recovery: true } : {},
|
|
17066
|
+
...plan === void 0 ? {} : { coverage: plan }
|
|
17067
|
+
};
|
|
17068
|
+
try {
|
|
17069
|
+
const { prog, fnSrcs } = encodeTableProgram(Object.fromEntries(encodeMap), settings);
|
|
17070
|
+
return { prog, fnSrcs, hostMode, plan };
|
|
17071
|
+
} catch (e) {
|
|
17072
|
+
opts.refusals?.push(e instanceof Error ? e.message : String(e));
|
|
17073
|
+
return null;
|
|
17074
|
+
}
|
|
17075
|
+
}
|
|
17076
|
+
function compileRuleMap(ruleMap, opts = {}) {
|
|
17077
|
+
const encoded = encodeForRun(ruleMap, opts);
|
|
17078
|
+
if (encoded === null) return null;
|
|
17079
|
+
const { prog, fnSrcs, hostMode, plan } = encoded;
|
|
17080
|
+
const artifact = closureArtifact(prog);
|
|
17081
|
+
if (artifact.runtimeOnly !== void 0 && artifact.runtimeOnly.length > 0) {
|
|
17082
|
+
opts.refusals?.push(...artifact.runtimeOnly);
|
|
17083
|
+
return null;
|
|
17084
|
+
}
|
|
17085
|
+
const supplied = opts.fnSources;
|
|
17086
|
+
const sources = fnSrcs.map((s, i) => s ?? supplied?.[i] ?? null);
|
|
17087
|
+
if (sources.some((s) => s === null)) {
|
|
17088
|
+
const missing = sources.flatMap((s, i) => s === null ? [i] : []);
|
|
17089
|
+
opts.refusals?.push(
|
|
17090
|
+
`author reducer source missing for prog.fns[${missing.join(", ")}] \u2014 printing would emit \`() => {}\` and the parse would return no value`
|
|
17091
|
+
);
|
|
17092
|
+
return null;
|
|
17093
|
+
}
|
|
17094
|
+
if (supplied !== void 0 && supplied.length > fnSrcs.length) {
|
|
17095
|
+
throw new Error(
|
|
17096
|
+
`compileRuleMap: got ${supplied.length} fnSources for a pool of ${fnSrcs.length}. The list is positional, in prog.fns order, so a longer one means it belongs to a different encode \u2014 and the entries would be silently misassigned.`
|
|
17097
|
+
);
|
|
17098
|
+
}
|
|
17099
|
+
const replacementWithMetadata = (metadataSource, options = {}) => emitTableExpression(artifact, {
|
|
17100
|
+
entry: null,
|
|
17101
|
+
runtimeRef: opts.runtimeRef ?? "tableRules",
|
|
17102
|
+
fnSources: sources,
|
|
17103
|
+
...options.precompileDefault === true && hostMode === "ast" && prog.lines !== 1 && prog.code.length >= DEFAULT_PRECOMPILE_MIN_WORDS ? { assemblies: defaultAssemblyCfgs(artifact).slice(0, 1) } : {},
|
|
17104
|
+
...metadataSource === void 0 ? {} : { metadataSource }
|
|
17105
|
+
});
|
|
17106
|
+
const replacement = replacementWithMetadata();
|
|
17107
|
+
return {
|
|
17108
|
+
keys: ruleMap.map(([key]) => key),
|
|
17109
|
+
replacement,
|
|
17110
|
+
replacementWithMetadata,
|
|
17111
|
+
hostMode,
|
|
17112
|
+
// WHAT THE FLAG MEANS is "a DIRECT BUILDER's positioned-CST branch was
|
|
17113
|
+
// dropped", which is what the driver's `'ast' artifact + CST host` check keys
|
|
17114
|
+
// off. `mode === 'ast'` alone over-reports it: an all-STRUCTURAL grammar has no
|
|
17115
|
+
// direct builder, so there was no branch to drop and it stays usable with either
|
|
17116
|
+
// host — the long-standing `node(parser)` contract. Same predicate codegen uses
|
|
17117
|
+
// for its own `hasDirectBuilders` (both read `analysis/commitment.ts`), so the two
|
|
17118
|
+
// lowerings stamp the same artifact rather than disagreeing about it.
|
|
17119
|
+
hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
|
|
17120
|
+
reflection: collectGrammarReflection(ruleMap),
|
|
17121
|
+
...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
|
|
17122
|
+
rules: tableRules(artifact),
|
|
17123
|
+
prog: artifact
|
|
17124
|
+
};
|
|
17125
|
+
}
|
|
17126
|
+
|
|
17127
|
+
// src/compiler/borrowed-rules.ts
|
|
17128
|
+
var nameOf = (c) => c._ruleName;
|
|
17129
|
+
function deref(c) {
|
|
17130
|
+
const seen = /* @__PURE__ */ new Set();
|
|
17131
|
+
let current = c;
|
|
17132
|
+
while (current._def.tag === "lazy" && !seen.has(current)) {
|
|
17133
|
+
seen.add(current);
|
|
17134
|
+
try {
|
|
17135
|
+
current = current._def.thunk();
|
|
17136
|
+
} catch {
|
|
17137
|
+
return void 0;
|
|
17138
|
+
}
|
|
17139
|
+
}
|
|
17140
|
+
return current;
|
|
17141
|
+
}
|
|
17142
|
+
function borrowedRuleReference(map) {
|
|
17143
|
+
const seen = /* @__PURE__ */ new Set();
|
|
17144
|
+
for (const [rule, self] of Object.entries(map)) {
|
|
17145
|
+
let found;
|
|
17146
|
+
const visit = (c) => {
|
|
17147
|
+
if (found !== void 0) return;
|
|
17148
|
+
if (c._def.tag === "lazy") {
|
|
17149
|
+
if (!winnerWrapsReference(self, c)) {
|
|
17150
|
+
const name = nameOf(c);
|
|
17151
|
+
const winner = name !== void 0 && Object.hasOwn(map, name) ? map[name] : void 0;
|
|
17152
|
+
if (winner !== void 0) {
|
|
17153
|
+
if (winnerWrapsReference(winner, c) || deref(c) === deref(winner)) return;
|
|
17154
|
+
found = name;
|
|
17155
|
+
return;
|
|
17156
|
+
}
|
|
17157
|
+
}
|
|
17158
|
+
if (seen.has(c)) return;
|
|
17159
|
+
seen.add(c);
|
|
17160
|
+
let body;
|
|
17161
|
+
try {
|
|
17162
|
+
body = c._def.thunk();
|
|
17163
|
+
} catch {
|
|
17164
|
+
return;
|
|
17165
|
+
}
|
|
17166
|
+
visit(body);
|
|
17167
|
+
return;
|
|
16898
17168
|
}
|
|
17169
|
+
if (seen.has(c)) return;
|
|
17170
|
+
seen.add(c);
|
|
17171
|
+
for (const child of childrenOf2(c._def)) visit(child);
|
|
17172
|
+
};
|
|
17173
|
+
visit(self);
|
|
17174
|
+
if (found !== void 0) return { rule, reference: found };
|
|
17175
|
+
}
|
|
17176
|
+
return void 0;
|
|
17177
|
+
}
|
|
17178
|
+
function borrowedRuleMessage(api, hit) {
|
|
17179
|
+
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.`;
|
|
17180
|
+
}
|
|
17181
|
+
|
|
17182
|
+
// src/table/compile.ts
|
|
17183
|
+
var ENTRY = "Entry";
|
|
17184
|
+
function ownSource(fn) {
|
|
17185
|
+
if (typeof fn !== "function") return null;
|
|
17186
|
+
const text = Function.prototype.toString.call(fn);
|
|
17187
|
+
if (!text.includes("[native code]")) return text;
|
|
17188
|
+
const name = fn.name;
|
|
17189
|
+
return typeof name === "string" && name.length > 0 && globalThis[name] === fn ? name : null;
|
|
17190
|
+
}
|
|
17191
|
+
function compile(target, second, third) {
|
|
17192
|
+
if (!isCombinator(target)) return compileMap(target, second);
|
|
17193
|
+
return compileRoot(target, second, third);
|
|
17194
|
+
}
|
|
17195
|
+
function isCombinator(x) {
|
|
17196
|
+
return typeof x === "object" && x !== null && typeof x.parse === "function" && "_def" in x;
|
|
17197
|
+
}
|
|
17198
|
+
function compileMap(grammar, opts = {}) {
|
|
17199
|
+
const entries = [];
|
|
17200
|
+
for (const [key, value] of Object.entries(grammar)) {
|
|
17201
|
+
if (!isCombinator(value)) throw new TypeError(`compile: grammar entry "${key}" is not a parser`);
|
|
17202
|
+
if (value._def.tag === "lazy") {
|
|
17203
|
+
try {
|
|
17204
|
+
value._def.thunk();
|
|
17205
|
+
} catch {
|
|
17206
|
+
continue;
|
|
17207
|
+
}
|
|
17208
|
+
}
|
|
17209
|
+
entries.push([key, value]);
|
|
17210
|
+
}
|
|
17211
|
+
const borrowed = borrowedRuleReference(Object.fromEntries(entries));
|
|
17212
|
+
if (borrowed !== void 0) throw new Error(borrowedRuleMessage("compile", borrowed));
|
|
17213
|
+
const drain = beginCompileDegradationDrain();
|
|
17214
|
+
let done = false;
|
|
17215
|
+
try {
|
|
17216
|
+
const refusals = [];
|
|
17217
|
+
const compiled = compileRuleMapRunnable(entries, {
|
|
17218
|
+
...opts.hostMode ? { hostMode: opts.hostMode } : {},
|
|
17219
|
+
refusals,
|
|
17220
|
+
specialise: true
|
|
17221
|
+
});
|
|
17222
|
+
if (compiled === null) {
|
|
17223
|
+
throw new Error(`compile: this grammar could not be encoded to a table${refusals.length ? ` \u2014 ${refusals.join("; ")}` : ""}`);
|
|
17224
|
+
}
|
|
17225
|
+
done = true;
|
|
17226
|
+
return compiled.rules;
|
|
17227
|
+
} finally {
|
|
17228
|
+
drain(done);
|
|
17229
|
+
}
|
|
17230
|
+
}
|
|
17231
|
+
function compileRoot(combinator, mapFnSources, opts = {}) {
|
|
17232
|
+
runDuplicationDiagnostic(combinator, opts.duplication);
|
|
17233
|
+
const drain = beginCompileDegradationDrain();
|
|
17234
|
+
let compiled = false;
|
|
17235
|
+
try {
|
|
17236
|
+
const out = compileImpl(combinator, mapFnSources, opts);
|
|
17237
|
+
compiled = true;
|
|
17238
|
+
return out;
|
|
17239
|
+
} finally {
|
|
17240
|
+
drain(compiled);
|
|
17241
|
+
}
|
|
17242
|
+
}
|
|
17243
|
+
function compileImpl(combinator, mapFnSources, opts = {}) {
|
|
17244
|
+
const plan = opts.coverage === true ? buildGrammarPlan(combinator) : void 0;
|
|
17245
|
+
const settings = {
|
|
17246
|
+
...opts.hostMode === void 0 ? {} : { hostMode: opts.hostMode },
|
|
17247
|
+
...opts.trackLines === void 0 ? {} : { trackLines: opts.trackLines },
|
|
17248
|
+
...plan === void 0 ? {} : { coverage: plan }
|
|
17249
|
+
};
|
|
17250
|
+
const { prog, fnSrcs } = encodeTableProgram({ [ENTRY]: combinator }, settings);
|
|
17251
|
+
const artifact = closureArtifact(prog);
|
|
17252
|
+
const entry = tableRules(prog)[ENTRY];
|
|
17253
|
+
const offered = opts.fnSources ?? mapFnSources;
|
|
17254
|
+
const supplied = offered !== void 0 && offered.length === fnSrcs.length ? offered : void 0;
|
|
17255
|
+
const sources = fnSrcs.map((s, i) => s ?? supplied?.[i] ?? ownSource(prog.fns[i]));
|
|
17256
|
+
const unsourced = sources.reduce((acc, s, i) => s === null ? [...acc, i] : acc, []);
|
|
17257
|
+
const runtimeOnly = [
|
|
17258
|
+
...prog.runtimeOnly ?? [],
|
|
17259
|
+
...unsourced.length === 0 ? [] : [`author reducer source missing for prog.fns[${unsourced.join(", ")}] \u2014 printing would emit \`() => {}\` and the parse would return no value`]
|
|
17260
|
+
];
|
|
17261
|
+
const printable = runtimeOnly.length === 0;
|
|
17262
|
+
const emitOpts = { fnSources: sources };
|
|
17263
|
+
const source = printable ? emitTableModule(artifact, { name: "grammar", ...emitOpts }) : "";
|
|
17264
|
+
const inlineExpression = printable ? emitTableExpression(artifact, { entry: ENTRY, runtimeRef: opts.runtimeRef ?? "tableRules", ...emitOpts }) : null;
|
|
17265
|
+
const runOnce2 = (input, pos, ctx) => entry(input, pos, ctx);
|
|
17266
|
+
return {
|
|
17267
|
+
source,
|
|
17268
|
+
inlineExpression,
|
|
17269
|
+
...printable ? {} : { runtimeOnly },
|
|
17270
|
+
// The DENOMINATOR, handed back rather than scraped out of the emitted text.
|
|
17271
|
+
// `plugin/index.ts` prefers a compiler-supplied `coverageDefinitions` and only
|
|
17272
|
+
// falls back to regex-scanning generated hooks; a table has no hooks to scan,
|
|
17273
|
+
// so this is the channel.
|
|
17274
|
+
...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
|
|
17275
|
+
parse(input, pos = 0) {
|
|
17276
|
+
return runOnce2(input, pos, createParseContext());
|
|
17277
|
+
},
|
|
17278
|
+
parseWithContext(input, parseCtx, pos = 0) {
|
|
17279
|
+
return runOnce2(input, pos, parseCtx);
|
|
17280
|
+
},
|
|
17281
|
+
/**
|
|
17282
|
+
* NO LONGER REFUSES. It used to throw unless the caller passed
|
|
17283
|
+
* `{ recovery: true }`, because setting `_tolerant` on a table with no
|
|
17284
|
+
* recovery rows would report a clean parse with an empty error list whatever
|
|
17285
|
+
* the input — refusing was the right answer to that, and OPTIONAL RECOVERY
|
|
17286
|
+
* was the wrong question. `compile()` requires no such flag, so the refusal
|
|
17287
|
+
* was a `CompiledParser` contract break; recovery is now always lowered and
|
|
17288
|
+
* there is nothing left to refuse.
|
|
17289
|
+
*/
|
|
17290
|
+
parseWithErrors(input, pos = 0) {
|
|
17291
|
+
const ctx = createParseContext();
|
|
17292
|
+
const errors = [];
|
|
17293
|
+
ctx._errors = errors;
|
|
17294
|
+
ctx._tolerant = true;
|
|
17295
|
+
const r = runOnce2(input, pos, ctx);
|
|
17296
|
+
return { ...r, errors };
|
|
16899
17297
|
}
|
|
16900
17298
|
};
|
|
16901
17299
|
}
|
|
@@ -16996,176 +17394,6 @@ function serializeRuleMap(ruleMap, scanSkip) {
|
|
|
16996
17394
|
throw e;
|
|
16997
17395
|
}
|
|
16998
17396
|
}
|
|
16999
|
-
function evalRuleMapIR(ir) {
|
|
17000
|
-
const _tf = (child, src, recognitionOnly = false) => {
|
|
17001
|
-
let fn2;
|
|
17002
|
-
try {
|
|
17003
|
-
fn2 = (0, eval)(`(${src})`);
|
|
17004
|
-
} catch {
|
|
17005
|
-
fn2 = () => {
|
|
17006
|
-
throw new Error("IR transform fn not materialized");
|
|
17007
|
-
};
|
|
17008
|
-
}
|
|
17009
|
-
const t = transform(child, fn2);
|
|
17010
|
-
t._def.fnSrc = src;
|
|
17011
|
-
if (recognitionOnly) t._def.recognitionOnly = true;
|
|
17012
|
-
return t;
|
|
17013
|
-
};
|
|
17014
|
-
const _lf = (child, src, source = false) => {
|
|
17015
|
-
let fn2;
|
|
17016
|
-
try {
|
|
17017
|
-
fn2 = (0, eval)(`(${src})`);
|
|
17018
|
-
} catch {
|
|
17019
|
-
fn2 = () => {
|
|
17020
|
-
throw new Error("IR leaf fn not materialized");
|
|
17021
|
-
};
|
|
17022
|
-
}
|
|
17023
|
-
const l = source ? sourceLeaf(child, fn2) : leaf(child, fn2);
|
|
17024
|
-
l._def.fnSrc = src;
|
|
17025
|
-
return l;
|
|
17026
|
-
};
|
|
17027
|
-
const _nd = (type, child, src, opts, staticError, sigSrc, buildImports, rawUnused) => {
|
|
17028
|
-
if (staticError !== void 0 && staticError.length > 0) {
|
|
17029
|
-
throw new Error(`IR direct node builder for ${type} must be macro-static and self-contained; unsupported binding(s): ${staticError.join(", ")}`);
|
|
17030
|
-
}
|
|
17031
|
-
const n = node(type, child, (() => {
|
|
17032
|
-
throw new Error("IR node build requires static re-lowering");
|
|
17033
|
-
}), opts);
|
|
17034
|
-
n._def.buildSrc = src;
|
|
17035
|
-
if (staticError !== void 0) n._def.buildStaticError = staticError;
|
|
17036
|
-
if (sigSrc !== void 0) n._def.buildSigSrc = sigSrc;
|
|
17037
|
-
if (rawUnused === true) n._def.buildRawUnused = true;
|
|
17038
|
-
if (buildImports !== void 0) n._def.buildImports = buildImports;
|
|
17039
|
-
return n;
|
|
17040
|
-
};
|
|
17041
|
-
const _gch = (items) => {
|
|
17042
|
-
const gateSrcs = [];
|
|
17043
|
-
const arms = items.map((it) => {
|
|
17044
|
-
if (Array.isArray(it)) {
|
|
17045
|
-
const [src, comb] = it;
|
|
17046
|
-
gateSrcs.push(src);
|
|
17047
|
-
let gate2;
|
|
17048
|
-
try {
|
|
17049
|
-
gate2 = (0, eval)(`(${src})`);
|
|
17050
|
-
} catch {
|
|
17051
|
-
gate2 = () => {
|
|
17052
|
-
throw new Error("IR gate fn not materialized");
|
|
17053
|
-
};
|
|
17054
|
-
}
|
|
17055
|
-
return { gate: gate2, combinator: comb };
|
|
17056
|
-
}
|
|
17057
|
-
gateSrcs.push(null);
|
|
17058
|
-
return it;
|
|
17059
|
-
});
|
|
17060
|
-
const c = choice(...arms);
|
|
17061
|
-
const gates = c._def.gates;
|
|
17062
|
-
if (gates && gates.length !== gateSrcs.length) {
|
|
17063
|
-
throw new Error(`_gch: gateSrcs length ${gateSrcs.length} != choice gates length ${gates.length}`);
|
|
17064
|
-
}
|
|
17065
|
-
;
|
|
17066
|
-
c._def.gateSrcs = gateSrcs;
|
|
17067
|
-
return c;
|
|
17068
|
-
};
|
|
17069
|
-
const _wc = (src, inner) => {
|
|
17070
|
-
let extra;
|
|
17071
|
-
try {
|
|
17072
|
-
extra = (0, eval)(`(${src})`);
|
|
17073
|
-
} catch {
|
|
17074
|
-
extra = void 0;
|
|
17075
|
-
}
|
|
17076
|
-
const w = withCtx(extra, inner);
|
|
17077
|
-
w._def.extraSrc = src;
|
|
17078
|
-
return w;
|
|
17079
|
-
};
|
|
17080
|
-
const fn = new Function(
|
|
17081
|
-
"rules",
|
|
17082
|
-
"ref",
|
|
17083
|
-
"regex",
|
|
17084
|
-
"literal",
|
|
17085
|
-
"keywords",
|
|
17086
|
-
"sequence",
|
|
17087
|
-
"choice",
|
|
17088
|
-
"dispatch",
|
|
17089
|
-
"when",
|
|
17090
|
-
"startsWith",
|
|
17091
|
-
"endsWith",
|
|
17092
|
-
"matches",
|
|
17093
|
-
"otherwise",
|
|
17094
|
-
"routed",
|
|
17095
|
-
"attempt",
|
|
17096
|
-
"many",
|
|
17097
|
-
"oneOrMore",
|
|
17098
|
-
"optional",
|
|
17099
|
-
"sepBy",
|
|
17100
|
-
"keepSeparator",
|
|
17101
|
-
"not",
|
|
17102
|
-
"peek",
|
|
17103
|
-
"node",
|
|
17104
|
-
"parser",
|
|
17105
|
-
"scanTo",
|
|
17106
|
-
"balanced",
|
|
17107
|
-
"token",
|
|
17108
|
-
"leaf",
|
|
17109
|
-
"transform",
|
|
17110
|
-
"trivia",
|
|
17111
|
-
"classifiedTrivia",
|
|
17112
|
-
"label",
|
|
17113
|
-
"field",
|
|
17114
|
-
"expect",
|
|
17115
|
-
"adjacent",
|
|
17116
|
-
"notAdjacent",
|
|
17117
|
-
"_tf",
|
|
17118
|
-
"_lf",
|
|
17119
|
-
"_nd",
|
|
17120
|
-
"_gch",
|
|
17121
|
-
"_wc",
|
|
17122
|
-
`return (${ir})`
|
|
17123
|
-
);
|
|
17124
|
-
const map = fn(
|
|
17125
|
-
rules,
|
|
17126
|
-
ref,
|
|
17127
|
-
regex,
|
|
17128
|
-
literal,
|
|
17129
|
-
keywords,
|
|
17130
|
-
sequence,
|
|
17131
|
-
choice,
|
|
17132
|
-
dispatch,
|
|
17133
|
-
when,
|
|
17134
|
-
startsWith,
|
|
17135
|
-
endsWith,
|
|
17136
|
-
matches,
|
|
17137
|
-
otherwise,
|
|
17138
|
-
routed,
|
|
17139
|
-
attempt,
|
|
17140
|
-
many,
|
|
17141
|
-
oneOrMore,
|
|
17142
|
-
optional,
|
|
17143
|
-
sepBy,
|
|
17144
|
-
keepSeparator,
|
|
17145
|
-
not,
|
|
17146
|
-
peek,
|
|
17147
|
-
node,
|
|
17148
|
-
parser,
|
|
17149
|
-
scanTo,
|
|
17150
|
-
balanced,
|
|
17151
|
-
token,
|
|
17152
|
-
leaf,
|
|
17153
|
-
transform,
|
|
17154
|
-
trivia,
|
|
17155
|
-
classifiedTrivia,
|
|
17156
|
-
label,
|
|
17157
|
-
field,
|
|
17158
|
-
expect,
|
|
17159
|
-
adjacent,
|
|
17160
|
-
notAdjacent,
|
|
17161
|
-
_tf,
|
|
17162
|
-
_lf,
|
|
17163
|
-
_nd,
|
|
17164
|
-
_gch,
|
|
17165
|
-
_wc
|
|
17166
|
-
);
|
|
17167
|
-
return Object.entries(map);
|
|
17168
|
-
}
|
|
17169
17397
|
var Serializer = class {
|
|
17170
17398
|
counts = /* @__PURE__ */ new Map();
|
|
17171
17399
|
selfRef = /* @__PURE__ */ new Set();
|
|
@@ -17428,7 +17656,7 @@ ${outerDecls.map((d) => " " + d).join("\n")}
|
|
|
17428
17656
|
case "label":
|
|
17429
17657
|
return `label(${JSON.stringify(def.label)}, ${kid(def.parser)})`;
|
|
17430
17658
|
case "field":
|
|
17431
|
-
return `field(${JSON.stringify(def.name)}, ${kid(def.parser)})`;
|
|
17659
|
+
return `field(${JSON.stringify(def.name)}, ${kid(def.parser)}${fieldOptionsSrc(def)})`;
|
|
17432
17660
|
case "expect":
|
|
17433
17661
|
return `expect(${kid(def.parser)}${def.label !== void 0 ? `, ${JSON.stringify(def.label)}` : ""})`;
|
|
17434
17662
|
case "scanTo":
|
|
@@ -17491,128 +17719,13 @@ ${outerDecls.map((d) => " " + d).join("\n")}
|
|
|
17491
17719
|
}
|
|
17492
17720
|
}
|
|
17493
17721
|
};
|
|
17494
|
-
|
|
17495
|
-
|
|
17496
|
-
|
|
17497
|
-
function resolveHostMode(ruleMap, explicit) {
|
|
17498
|
-
return explicit ?? ruleMap.map(([, r]) => r._meta.grammarHostMode).find(Boolean) ?? "ast";
|
|
17499
|
-
}
|
|
17500
|
-
function resolveTrackLines(ruleMap, explicit) {
|
|
17501
|
-
return explicit === true || ruleMap.some(([, r]) => r._meta.grammarTrackLines === true);
|
|
17502
|
-
}
|
|
17503
|
-
function withAmbient(ruleMap, opts) {
|
|
17504
|
-
if (opts.trivia === void 0 && opts.scanSkip === void 0) return ruleMap;
|
|
17505
|
-
const wrappers = /* @__PURE__ */ new Map();
|
|
17506
|
-
return ruleMap.map(([name, rule]) => {
|
|
17507
|
-
if (rule._meta.isTrivia) return [name, rule];
|
|
17508
|
-
const addTrivia = opts.trivia !== void 0 && rule._meta.grammarTrivia === void 0;
|
|
17509
|
-
const addScanSkip = opts.scanSkip !== void 0 && rule._meta.grammarScanSkip === void 0;
|
|
17510
|
-
if (!addTrivia && !addScanSkip) return [name, rule];
|
|
17511
|
-
let wrapped = wrappers.get(rule);
|
|
17512
|
-
if (wrapped === void 0) {
|
|
17513
|
-
wrapped = {
|
|
17514
|
-
...rule,
|
|
17515
|
-
_meta: {
|
|
17516
|
-
...rule._meta,
|
|
17517
|
-
...addTrivia ? { grammarTrivia: opts.trivia } : {},
|
|
17518
|
-
...addScanSkip ? { grammarScanSkip: opts.scanSkip } : {}
|
|
17519
|
-
}
|
|
17520
|
-
};
|
|
17521
|
-
wrappers.set(rule, wrapped);
|
|
17522
|
-
}
|
|
17523
|
-
return [name, wrapped];
|
|
17524
|
-
});
|
|
17525
|
-
}
|
|
17526
|
-
function compileRuleMapRunnable(ruleMap, opts = {}) {
|
|
17527
|
-
const encoded = encodeForRun(ruleMap, opts);
|
|
17528
|
-
if (encoded === null) return null;
|
|
17529
|
-
const { prog, hostMode, plan } = encoded;
|
|
17530
|
-
const artifact = closureArtifact(prog);
|
|
17531
|
-
return {
|
|
17532
|
-
keys: ruleMap.map(([key]) => key),
|
|
17533
|
-
hostMode,
|
|
17534
|
-
hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
|
|
17535
|
-
reflection: collectGrammarReflection(ruleMap),
|
|
17536
|
-
...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
|
|
17537
|
-
rules: tableRules(prog),
|
|
17538
|
-
prog: artifact
|
|
17539
|
-
};
|
|
17540
|
-
}
|
|
17541
|
-
function encodeForRun(ruleMap, opts) {
|
|
17542
|
-
runDuplicationDiagnosticRules(ruleMap, opts.duplication);
|
|
17543
|
-
const encodeMap = withAmbient(ruleMap, opts);
|
|
17544
|
-
const plan = opts.coverage === true ? buildGrammarPlan(
|
|
17545
|
-
encodeMap.map(([, rule]) => rule),
|
|
17546
|
-
Object.fromEntries(encodeMap.filter(([, rule]) => rule._def.tag !== "lazy"))
|
|
17547
|
-
) : void 0;
|
|
17548
|
-
const hostMode = resolveHostMode(ruleMap, opts.hostMode);
|
|
17549
|
-
const settings = {
|
|
17550
|
-
hostMode,
|
|
17551
|
-
...resolveTrackLines(ruleMap, opts.trackLines) ? { trackLines: true } : {},
|
|
17552
|
-
...opts.recovery === true ? { recovery: true } : {},
|
|
17553
|
-
...plan === void 0 ? {} : { coverage: plan }
|
|
17554
|
-
};
|
|
17555
|
-
try {
|
|
17556
|
-
const { prog, fnSrcs } = encodeTableProgram(Object.fromEntries(encodeMap), settings);
|
|
17557
|
-
return { prog, fnSrcs, hostMode, plan };
|
|
17558
|
-
} catch (e) {
|
|
17559
|
-
opts.refusals?.push(e instanceof Error ? e.message : String(e));
|
|
17560
|
-
return null;
|
|
17561
|
-
}
|
|
17562
|
-
}
|
|
17563
|
-
function compileRuleMap(ruleMap, opts = {}) {
|
|
17564
|
-
const encoded = encodeForRun(ruleMap, opts);
|
|
17565
|
-
if (encoded === null) return null;
|
|
17566
|
-
const { prog, fnSrcs, hostMode, plan } = encoded;
|
|
17567
|
-
const artifact = closureArtifact(prog);
|
|
17568
|
-
if (artifact.runtimeOnly !== void 0 && artifact.runtimeOnly.length > 0) {
|
|
17569
|
-
opts.refusals?.push(...artifact.runtimeOnly);
|
|
17570
|
-
return null;
|
|
17571
|
-
}
|
|
17572
|
-
const supplied = opts.fnSources;
|
|
17573
|
-
const sources = fnSrcs.map((s, i) => s ?? supplied?.[i] ?? null);
|
|
17574
|
-
if (sources.some((s) => s === null)) {
|
|
17575
|
-
const missing = sources.flatMap((s, i) => s === null ? [i] : []);
|
|
17576
|
-
opts.refusals?.push(
|
|
17577
|
-
`author reducer source missing for prog.fns[${missing.join(", ")}] \u2014 printing would emit \`() => {}\` and the parse would return no value`
|
|
17578
|
-
);
|
|
17579
|
-
return null;
|
|
17580
|
-
}
|
|
17581
|
-
if (supplied !== void 0 && supplied.length > fnSrcs.length) {
|
|
17582
|
-
throw new Error(
|
|
17583
|
-
`compileRuleMap: got ${supplied.length} fnSources for a pool of ${fnSrcs.length}. The list is positional, in prog.fns order, so a longer one means it belongs to a different encode \u2014 and the entries would be silently misassigned.`
|
|
17584
|
-
);
|
|
17585
|
-
}
|
|
17586
|
-
const replacementWithMetadata = (metadataSource, options = {}) => emitTableExpression(artifact, {
|
|
17587
|
-
entry: null,
|
|
17588
|
-
runtimeRef: opts.runtimeRef ?? "tableRules",
|
|
17589
|
-
fnSources: sources,
|
|
17590
|
-
...options.precompileDefault === true && hostMode === "ast" && prog.lines !== 1 && prog.code.length >= DEFAULT_PRECOMPILE_MIN_WORDS ? { assemblies: defaultAssemblyCfgs(artifact).slice(0, 1) } : {},
|
|
17591
|
-
...metadataSource === void 0 ? {} : { metadataSource }
|
|
17592
|
-
});
|
|
17593
|
-
const replacement = replacementWithMetadata();
|
|
17594
|
-
return {
|
|
17595
|
-
keys: ruleMap.map(([key]) => key),
|
|
17596
|
-
replacement,
|
|
17597
|
-
replacementWithMetadata,
|
|
17598
|
-
hostMode,
|
|
17599
|
-
// WHAT THE FLAG MEANS is "a DIRECT BUILDER's positioned-CST branch was
|
|
17600
|
-
// dropped", which is what the driver's `'ast' artifact + CST host` check keys
|
|
17601
|
-
// off. `mode === 'ast'` alone over-reports it: an all-STRUCTURAL grammar has no
|
|
17602
|
-
// direct builder, so there was no branch to drop and it stays usable with either
|
|
17603
|
-
// host — the long-standing `node(parser)` contract. Same predicate codegen uses
|
|
17604
|
-
// for its own `hasDirectBuilders` (both read `analysis/commitment.ts`), so the two
|
|
17605
|
-
// lowerings stamp the same artifact rather than disagreeing about it.
|
|
17606
|
-
hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
|
|
17607
|
-
reflection: collectGrammarReflection(ruleMap),
|
|
17608
|
-
...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
|
|
17609
|
-
rules: tableRules(prog),
|
|
17610
|
-
prog: artifact
|
|
17611
|
-
};
|
|
17722
|
+
function fieldOptionsSrc(def) {
|
|
17723
|
+
if (def.leadingTrivia !== true && def.trailingTrivia !== true) return "";
|
|
17724
|
+
return `, { ${[def.leadingTrivia === true ? "leadingTrivia: true" : "", def.trailingTrivia === true ? "trailingTrivia: true" : ""].filter(Boolean).join(", ")} }`;
|
|
17612
17725
|
}
|
|
17613
17726
|
|
|
17614
17727
|
// src/version.ts
|
|
17615
|
-
var PARSEMAN_VERSION = "0.
|
|
17728
|
+
var PARSEMAN_VERSION = "0.54.0";
|
|
17616
17729
|
|
|
17617
17730
|
// src/compiler/compile-linkable-table.ts
|
|
17618
17731
|
function isLocal(rule) {
|
|
@@ -17680,16 +17793,6 @@ function compileLinkableTable(ruleMapArg, ns, opts = {}) {
|
|
|
17680
17793
|
}
|
|
17681
17794
|
|
|
17682
17795
|
// src/compiler/linker.ts
|
|
17683
|
-
var _nsCounter = 0;
|
|
17684
|
-
function linkable(rulesMap, ns, trivia2, hostMode) {
|
|
17685
|
-
const piece = compileLinkableTable(
|
|
17686
|
-
Object.entries(rulesMap),
|
|
17687
|
-
ns ?? `_lk${_nsCounter++}_`,
|
|
17688
|
-
{ ...trivia2 ? { trivia: trivia2 } : {}, ...hostMode ? { hostMode } : {} }
|
|
17689
|
-
);
|
|
17690
|
-
if (!piece) throw new Error("linkable(): this grammar cannot be compiled to a linkable artifact (contains a runtime-only parser fallback)");
|
|
17691
|
-
return piece;
|
|
17692
|
-
}
|
|
17693
17796
|
function normalizeCstCollapse(collapse) {
|
|
17694
17797
|
if (collapse === true) return () => true;
|
|
17695
17798
|
if (Array.isArray(collapse)) {
|
|
@@ -17713,107 +17816,6 @@ function cstBuildHost(typeOrOptions, children2, _fields, span, rawChildren, triv
|
|
|
17713
17816
|
return host;
|
|
17714
17817
|
}
|
|
17715
17818
|
cstBuildHost._parsemanCstOutput = true;
|
|
17716
|
-
function fuseCarried(carried, trivia2, hostMode) {
|
|
17717
|
-
const maps = [];
|
|
17718
|
-
for (const p of carried) {
|
|
17719
|
-
if (!isIRPiece(p)) {
|
|
17720
|
-
if (typeof p.v !== "string") {
|
|
17721
|
-
throw new Error(
|
|
17722
|
-
`parseman: artifact "${p.ns}" is UNSTAMPED (compiled before the version-lock invariant). Recompile the grammar with parseman ${PARSEMAN_VERSION}; parseman does not fuse unversioned or cross-version artifacts.`
|
|
17723
|
-
);
|
|
17724
|
-
}
|
|
17725
|
-
if (p.v !== PARSEMAN_VERSION) {
|
|
17726
|
-
throw new Error(
|
|
17727
|
-
`parseman: artifact "${p.ns}" was compiled with parseman ${p.v}, but is being fused with parseman ${PARSEMAN_VERSION}. Compiled grammar artifacts are version-locked \u2014 recompile the grammar with parseman ${PARSEMAN_VERSION}; parseman does not fuse across versions.`
|
|
17728
|
-
);
|
|
17729
|
-
}
|
|
17730
|
-
}
|
|
17731
|
-
const rules2 = ruleMapOfCarried(p);
|
|
17732
|
-
if (rules2 === void 0) {
|
|
17733
|
-
throw new Error(`compose: carried piece "${p.ns}" has no re-lowerable IR and cannot be fused`);
|
|
17734
|
-
}
|
|
17735
|
-
maps.push(rules2);
|
|
17736
|
-
}
|
|
17737
|
-
const merged = mergeCarriedRuleMaps(maps);
|
|
17738
|
-
materializeDirectBuilders(merged);
|
|
17739
|
-
if (trivia2) {
|
|
17740
|
-
for (const [, rule] of merged) {
|
|
17741
|
-
if (rule._meta.isTrivia) continue;
|
|
17742
|
-
rule._meta.grammarTrivia = trivia2;
|
|
17743
|
-
}
|
|
17744
|
-
}
|
|
17745
|
-
const refusals = [];
|
|
17746
|
-
const compiled = compileRuleMapRunnable(merged, {
|
|
17747
|
-
...trivia2 ? { trivia: trivia2 } : {},
|
|
17748
|
-
...hostMode ? { hostMode } : {},
|
|
17749
|
-
refusals
|
|
17750
|
-
});
|
|
17751
|
-
if (compiled === null) {
|
|
17752
|
-
throw new Error(`compose: the merged grammar could not be encoded to a table${refusals.length ? ` \u2014 ${refusals.join("; ")}` : ""}`);
|
|
17753
|
-
}
|
|
17754
|
-
const map = tableRules(compiled.prog);
|
|
17755
|
-
for (const k of Object.keys(map)) {
|
|
17756
|
-
Object.defineProperty(map[k], FUSED_HOST_MODE, { value: compiled.hostMode, enumerable: false });
|
|
17757
|
-
Object.defineProperty(map[k], FUSED_HOST_ELIDED, { value: compiled.hostBranchElided, enumerable: false });
|
|
17758
|
-
}
|
|
17759
|
-
Object.defineProperty(map, FUSED_HOST_MODE, { value: compiled.hostMode, enumerable: false });
|
|
17760
|
-
Object.defineProperty(map, FUSED_HOST_ELIDED, { value: compiled.hostBranchElided, enumerable: false });
|
|
17761
|
-
Object.defineProperty(map, GRAMMAR_REFLECTION, { value: compiled.reflection, enumerable: false });
|
|
17762
|
-
return map;
|
|
17763
|
-
}
|
|
17764
|
-
function materializeDirectBuilders(ruleMap) {
|
|
17765
|
-
const seen = /* @__PURE__ */ new Set();
|
|
17766
|
-
const visit = (p) => {
|
|
17767
|
-
if (seen.has(p)) return;
|
|
17768
|
-
seen.add(p);
|
|
17769
|
-
const d = p._def;
|
|
17770
|
-
if (d.tag === "node" && typeof d.buildSrc === "string") {
|
|
17771
|
-
if (d.buildImports !== void 0 && d.buildImports.length > 0) {
|
|
17772
|
-
throw new Error(
|
|
17773
|
-
`IR direct node builder for ${d.type ?? "<anonymous>"} references module import(s) ${d.buildImports.map((bi) => bi.local).join(", ")} that a runtime compose() cannot supply; compose at build time via the parseman macro plugin, which re-emits the imports.`
|
|
17774
|
-
);
|
|
17775
|
-
}
|
|
17776
|
-
try {
|
|
17777
|
-
const fn = (0, eval)(`(${d.buildSrc})`);
|
|
17778
|
-
if (typeof fn === "function") d.build = fn;
|
|
17779
|
-
} catch {
|
|
17780
|
-
}
|
|
17781
|
-
}
|
|
17782
|
-
if (d.tag === "lazy") {
|
|
17783
|
-
let resolved;
|
|
17784
|
-
try {
|
|
17785
|
-
resolved = d.thunk();
|
|
17786
|
-
} catch {
|
|
17787
|
-
return;
|
|
17788
|
-
}
|
|
17789
|
-
if (resolved) visit(resolved);
|
|
17790
|
-
return;
|
|
17791
|
-
}
|
|
17792
|
-
for (const child of childrenOf2(p._def)) visit(child);
|
|
17793
|
-
};
|
|
17794
|
-
for (const [, rule] of ruleMap) visit(rule);
|
|
17795
|
-
}
|
|
17796
|
-
function ruleMapOfCarried(p) {
|
|
17797
|
-
if (isIRPiece(p)) return evalRuleMapIR(p.ir);
|
|
17798
|
-
if (p.ir !== null) return evalRuleMapIR(p.ir);
|
|
17799
|
-
return p.ruleMap.length > 0 ? p.ruleMap.map(([k, v]) => [k, v]) : void 0;
|
|
17800
|
-
}
|
|
17801
|
-
function mergeCarriedRuleMaps(maps) {
|
|
17802
|
-
const winners = /* @__PURE__ */ new Map();
|
|
17803
|
-
for (const map of maps) {
|
|
17804
|
-
for (const [name, rule] of map) {
|
|
17805
|
-
if (rule._def.tag === "lazy") {
|
|
17806
|
-
try {
|
|
17807
|
-
rule._def.thunk();
|
|
17808
|
-
} catch {
|
|
17809
|
-
continue;
|
|
17810
|
-
}
|
|
17811
|
-
}
|
|
17812
|
-
winners.set(name, rule);
|
|
17813
|
-
}
|
|
17814
|
-
}
|
|
17815
|
-
return [...winners];
|
|
17816
|
-
}
|
|
17817
17819
|
function fusedHostModeOf(registry) {
|
|
17818
17820
|
const m = registry[FUSED_HOST_MODE];
|
|
17819
17821
|
return m === "cst" ? "cst" : "ast";
|
|
@@ -17828,13 +17830,17 @@ function composedPiecesOf(grammar) {
|
|
|
17828
17830
|
}
|
|
17829
17831
|
var LEAF_COMPOSED = /* @__PURE__ */ Symbol.for("parseman.leafComposed");
|
|
17830
17832
|
var COMPOSED_TRIVIA = /* @__PURE__ */ Symbol.for("parseman.composedTrivia");
|
|
17831
|
-
var
|
|
17833
|
+
var LINKED = /* @__PURE__ */ Symbol.for("parseman.linkedComposition");
|
|
17832
17834
|
function isIRPiece(p) {
|
|
17833
17835
|
return !!p && typeof p === "object" && typeof p.ir === "string" && typeof p.ns === "string" && !("keys" in p);
|
|
17834
17836
|
}
|
|
17835
17837
|
function isLinkableTable(p) {
|
|
17836
17838
|
return !!p && typeof p === "object" && typeof p.ns === "string" && Array.isArray(p.keys);
|
|
17837
17839
|
}
|
|
17840
|
+
function ruleMapOfCarried(p) {
|
|
17841
|
+
if (isIRPiece(p)) return void 0;
|
|
17842
|
+
return p.ruleMap.length > 0 ? p.ruleMap.map(([k, v]) => [k, v]) : void 0;
|
|
17843
|
+
}
|
|
17838
17844
|
function carriedRuleMapsDetailed(carried) {
|
|
17839
17845
|
const maps = [];
|
|
17840
17846
|
const opaque = [];
|
|
@@ -17865,250 +17871,97 @@ function recoverComposedRules(grammar) {
|
|
|
17865
17871
|
}
|
|
17866
17872
|
return { rules: rules2, opaque };
|
|
17867
17873
|
}
|
|
17868
|
-
function coverageRulesOf(carried) {
|
|
17869
|
-
const winners = {};
|
|
17870
|
-
for (const piece of carried) {
|
|
17871
|
-
if (!isIRPiece(piece)) return void 0;
|
|
17872
|
-
const map = evalRuleMapIR(piece.ir);
|
|
17873
|
-
for (const [name, rule] of map) {
|
|
17874
|
-
if (rule._def.tag === "lazy") {
|
|
17875
|
-
try {
|
|
17876
|
-
rule._def.thunk();
|
|
17877
|
-
} catch {
|
|
17878
|
-
continue;
|
|
17879
|
-
}
|
|
17880
|
-
}
|
|
17881
|
-
winners[name] = rule;
|
|
17882
|
-
}
|
|
17883
|
-
}
|
|
17884
|
-
return winners;
|
|
17885
|
-
}
|
|
17886
17874
|
function composedCoverageRules(grammar) {
|
|
17887
|
-
|
|
17888
|
-
|
|
17889
|
-
|
|
17890
|
-
|
|
17891
|
-
|
|
17892
|
-
|
|
17893
|
-
|
|
17894
|
-
|
|
17895
|
-
|
|
17896
|
-
|
|
17897
|
-
|
|
17898
|
-
|
|
17899
|
-
|
|
17900
|
-
|
|
17901
|
-
for (const p of items) used.add(p.ns);
|
|
17902
|
-
return items;
|
|
17903
|
-
}
|
|
17904
|
-
if (isLinkableTable(item)) {
|
|
17905
|
-
used.add(item.ns);
|
|
17906
|
-
return [item];
|
|
17907
|
-
}
|
|
17908
|
-
const map = item;
|
|
17909
|
-
const ns = nextComposeNs(used);
|
|
17910
|
-
const entries = Object.entries(map).filter(([, val]) => {
|
|
17911
|
-
const d = val._def;
|
|
17912
|
-
if (d.tag !== "lazy") return true;
|
|
17913
|
-
try {
|
|
17914
|
-
d.thunk();
|
|
17915
|
-
return true;
|
|
17916
|
-
} catch {
|
|
17917
|
-
return false;
|
|
17918
|
-
}
|
|
17919
|
-
});
|
|
17920
|
-
const scanSkip = entries.map(([, val]) => val._meta.grammarScanSkip).find(Boolean);
|
|
17921
|
-
const ir = serializeRuleMap(entries, scanSkip);
|
|
17922
|
-
return ir ? [{ ns, ir }] : [linkable(map, ns, trivia2, hostMode)];
|
|
17875
|
+
const link = grammar[LINKED];
|
|
17876
|
+
return link?.();
|
|
17877
|
+
}
|
|
17878
|
+
var LINKED_WINNERS = /* @__PURE__ */ new WeakMap();
|
|
17879
|
+
function linkedWinnersOf(rule) {
|
|
17880
|
+
return LINKED_WINNERS.get(rule);
|
|
17881
|
+
}
|
|
17882
|
+
function recipesOf(item) {
|
|
17883
|
+
const recipes = item[RULES_RECIPE];
|
|
17884
|
+
if (Array.isArray(recipes)) return recipes;
|
|
17885
|
+
const what = isLinkableTable(item) ? `the table artifact "${item.ns}"` : composedPiecesOf(item) !== void 0 ? "a build-compiled compose() result" : "a value that is not a rules() grammar";
|
|
17886
|
+
throw new Error(
|
|
17887
|
+
`compose: ${what} has no live rules to link. At runtime compose() links interpreter grammars \u2014 rules() maps and runtime compose() results \u2014 and never evaluates carried IR or source text. Compose compiled grammars at build time (the parseman macro does), or compose the interpreter builds of both.`
|
|
17888
|
+
);
|
|
17923
17889
|
}
|
|
17924
17890
|
function composingTriviaOf(items) {
|
|
17925
17891
|
for (let i = items.length - 1; i >= 0; i--) {
|
|
17926
17892
|
const item = items[i];
|
|
17927
|
-
if (
|
|
17928
|
-
|
|
17929
|
-
|
|
17930
|
-
|
|
17931
|
-
for (const v of Object.values(item)) {
|
|
17932
|
-
const t = v?._meta?.grammarTrivia;
|
|
17933
|
-
if (t) return t;
|
|
17893
|
+
if (item[LINKED] !== void 0) {
|
|
17894
|
+
const stamped = item[COMPOSED_TRIVIA];
|
|
17895
|
+
if (stamped) return stamped;
|
|
17896
|
+
continue;
|
|
17934
17897
|
}
|
|
17898
|
+
const recipes = item[RULES_RECIPE];
|
|
17899
|
+
const trivia2 = recipes?.[recipes.length - 1]?.options?.trivia;
|
|
17900
|
+
if (trivia2 != null) return trivia2;
|
|
17935
17901
|
}
|
|
17936
17902
|
return void 0;
|
|
17937
17903
|
}
|
|
17938
|
-
function
|
|
17939
|
-
|
|
17940
|
-
|
|
17941
|
-
|
|
17942
|
-
|
|
17943
|
-
|
|
17944
|
-
const carried = items.flatMap((item) => itemCarried(item, used, trivia2, opts?.hostMode));
|
|
17945
|
-
const map = fuseCarried(carried, trivia2, opts?.hostMode);
|
|
17946
|
-
Object.defineProperty(map, COMPOSED_PIECES, { value: carried, enumerable: false });
|
|
17947
|
-
if (trivia2) Object.defineProperty(map, COMPOSED_TRIVIA, { value: trivia2, enumerable: false });
|
|
17948
|
-
const coverageRules = coverageRulesOf(carried);
|
|
17949
|
-
if (coverageRules) Object.defineProperty(map, COMPOSED_COVERAGE_RULES, { value: coverageRules, enumerable: false });
|
|
17950
|
-
return map;
|
|
17951
|
-
}
|
|
17952
|
-
function composeLeaf(items) {
|
|
17953
|
-
const pieces = items.flatMap(interpretedPieces);
|
|
17954
|
-
let fused;
|
|
17955
|
-
const map = {};
|
|
17956
|
-
for (const name of ruleNamesOf(pieces)) {
|
|
17957
|
-
Object.defineProperty(map, name, {
|
|
17958
|
-
enumerable: true,
|
|
17959
|
-
configurable: true,
|
|
17960
|
-
get: () => (fused ??= fusePieces(pieces))[name]
|
|
17961
|
-
});
|
|
17962
|
-
}
|
|
17963
|
-
Object.defineProperty(map, LEAF_COMPOSED, { value: true, enumerable: false });
|
|
17964
|
-
Object.defineProperty(map, INTERPRETED_PIECES, {
|
|
17965
|
-
value: pieces.filter((p) => p.plain).map((p) => p.entries),
|
|
17966
|
-
enumerable: false
|
|
17967
|
-
});
|
|
17968
|
-
return map;
|
|
17969
|
-
}
|
|
17970
|
-
function isRefSlot(c) {
|
|
17971
|
-
return c._def.tag === "lazy" && typeof c.define === "function";
|
|
17972
|
-
}
|
|
17973
|
-
var FUSE_ORIGINAL = /* @__PURE__ */ Symbol.for("parseman.interpretedFuseOriginal");
|
|
17974
|
-
var FUSE_TARGET = /* @__PURE__ */ Symbol.for("parseman.interpretedFuseTarget");
|
|
17975
|
-
var INTERPRETED_PIECES = /* @__PURE__ */ Symbol.for("parseman.interpretedPieces");
|
|
17976
|
-
function definitionOf(entry) {
|
|
17977
|
-
if (isRefSlot(entry)) {
|
|
17978
|
-
const original = entry[FUSE_ORIGINAL];
|
|
17979
|
-
if (original !== void 0) return original ?? void 0;
|
|
17980
|
-
try {
|
|
17981
|
-
return entry._def.thunk();
|
|
17982
|
-
} catch {
|
|
17983
|
-
return void 0;
|
|
17984
|
-
}
|
|
17985
|
-
}
|
|
17986
|
-
if (entry._def.tag === "lazy") {
|
|
17987
|
-
try {
|
|
17988
|
-
entry._def.thunk();
|
|
17989
|
-
} catch {
|
|
17990
|
-
return void 0;
|
|
17991
|
-
}
|
|
17904
|
+
function declaredNamesOf(items) {
|
|
17905
|
+
const names = /* @__PURE__ */ new Set();
|
|
17906
|
+
for (const item of items) {
|
|
17907
|
+
const linked = item[LINKED] !== void 0;
|
|
17908
|
+
const order = linked ? Object.keys(item) : isLinkableTable(item) ? item.keys : item[RULE_ORDER];
|
|
17909
|
+
for (const name of order ?? Object.keys(item)) names.add(name);
|
|
17992
17910
|
}
|
|
17993
|
-
return
|
|
17911
|
+
return [...names];
|
|
17994
17912
|
}
|
|
17995
|
-
function
|
|
17996
|
-
const
|
|
17997
|
-
const
|
|
17998
|
-
const
|
|
17913
|
+
function linkComposition(recipes, link) {
|
|
17914
|
+
const map = linkRules(recipes, link);
|
|
17915
|
+
const missing = [];
|
|
17916
|
+
for (const [name, rule] of Object.entries(map)) {
|
|
17917
|
+
if (rule._def.tag !== "lazy") continue;
|
|
17999
17918
|
try {
|
|
18000
|
-
|
|
17919
|
+
rule._def.thunk();
|
|
18001
17920
|
} catch {
|
|
18002
|
-
|
|
18003
|
-
}
|
|
18004
|
-
})();
|
|
18005
|
-
if ((bound ?? original) === target) return;
|
|
18006
|
-
if (bound !== void 0) {
|
|
18007
|
-
throw new Error(
|
|
18008
|
-
`fuseInterpreted: rule "${name}" is already bound by a DIFFERENT interpreted fusion of the same grammar piece. An interpreted fuse binds the shared placeholder objects in place, so two fusions cannot share a piece \u2014 build a fresh instance of the piece (call its rules() factory again, or import the module under a distinct specifier) for the second fusion.`
|
|
18009
|
-
);
|
|
18010
|
-
}
|
|
18011
|
-
if (!(FUSE_ORIGINAL in tagged)) Object.defineProperty(slot, FUSE_ORIGINAL, { value: original, enumerable: false });
|
|
18012
|
-
Object.defineProperty(slot, FUSE_TARGET, { value: target, enumerable: false });
|
|
18013
|
-
slot._def.thunk = () => target;
|
|
18014
|
-
slot.parse = (input, pos, ctx) => target.parse(input, pos, ctx);
|
|
18015
|
-
const meta = slot._meta;
|
|
18016
|
-
meta.firstSet = target._meta.firstSet;
|
|
18017
|
-
meta.canMatchNewline = target._meta.canMatchNewline;
|
|
18018
|
-
meta.isTrivia = target._meta.isTrivia;
|
|
18019
|
-
if (target._meta.triviaKindLabels !== void 0) meta.triviaKindLabels = target._meta.triviaKindLabels;
|
|
18020
|
-
else meta.triviaKindLabels = void 0;
|
|
18021
|
-
if (target._meta.disjoint !== void 0) meta.disjoint = target._meta.disjoint;
|
|
18022
|
-
else meta.disjoint = void 0;
|
|
18023
|
-
}
|
|
18024
|
-
function interpretedPieces(item) {
|
|
18025
|
-
const fused = item[INTERPRETED_PIECES];
|
|
18026
|
-
if (Array.isArray(fused)) return fused.map((entries) => ({ entries, plain: false }));
|
|
18027
|
-
const carried = composedPiecesOf(item);
|
|
18028
|
-
if (carried !== void 0) {
|
|
18029
|
-
const { maps, opaque } = carriedRuleMapsDetailed(carried);
|
|
18030
|
-
if (opaque.length > 0) {
|
|
18031
|
-
throw new Error(
|
|
18032
|
-
`fuseInterpreted: cannot interpret a composed grammar containing precompiled artifact(s) ${opaque.map((o) => `"${o.ns}" (${o.ruleNames.length} rules)`).join(", ")} \u2014 they carry compiled functions, not a combinator graph. Pass the source grammars (the same items you passed to compose()) instead.`
|
|
18033
|
-
);
|
|
17921
|
+
missing.push(name);
|
|
18034
17922
|
}
|
|
18035
|
-
return maps.map((entries) => ({ entries, plain: false }));
|
|
18036
17923
|
}
|
|
18037
|
-
if (
|
|
18038
|
-
const
|
|
18039
|
-
|
|
18040
|
-
|
|
17924
|
+
if (missing.length > 0) {
|
|
17925
|
+
const holes = new Set(missing);
|
|
17926
|
+
for (const [name, deps] of ruleDependencies(Object.entries(map).filter(([n]) => !holes.has(n)))) {
|
|
17927
|
+
for (const dep of deps) if (holes.has(dep)) throw new Error(`compose: rule "${name}" references missing rule "${dep}"`);
|
|
18041
17928
|
}
|
|
18042
|
-
|
|
17929
|
+
throw new Error(`compose: rule(s) ${missing.map((n) => `"${n}"`).join(", ")} are referenced but defined by no composed grammar`);
|
|
18043
17930
|
}
|
|
18044
|
-
|
|
17931
|
+
const borrowed = borrowedRuleReference(map);
|
|
17932
|
+
if (borrowed !== void 0) throw new Error(borrowedRuleMessage("compose", borrowed));
|
|
17933
|
+
for (const rule of Object.values(map)) LINKED_WINNERS.set(rule, map);
|
|
17934
|
+
Object.defineProperty(map, RULES_RECIPE, { value: recipes, enumerable: false });
|
|
17935
|
+
Object.defineProperty(map, LINKED, { value: () => map, enumerable: false });
|
|
17936
|
+
if (link.trivia) Object.defineProperty(map, COMPOSED_TRIVIA, { value: link.trivia, enumerable: false });
|
|
17937
|
+
return map;
|
|
18045
17938
|
}
|
|
18046
|
-
function
|
|
18047
|
-
|
|
18048
|
-
|
|
18049
|
-
for (const [name, value] of piece.entries) if (definitionOf(value) !== void 0) names.add(name);
|
|
17939
|
+
function compose(items, opts) {
|
|
17940
|
+
if (items.some((item) => item[LEAF_COMPOSED] === true)) {
|
|
17941
|
+
throw new Error("compose: a composeLeaf() result is terminal and cannot be composed again");
|
|
18050
17942
|
}
|
|
18051
|
-
return
|
|
17943
|
+
return linkedMap(items, opts, false);
|
|
18052
17944
|
}
|
|
18053
|
-
function
|
|
18054
|
-
|
|
18055
|
-
|
|
18056
|
-
|
|
18057
|
-
|
|
18058
|
-
|
|
18059
|
-
|
|
18060
|
-
|
|
18061
|
-
|
|
18062
|
-
}
|
|
18063
|
-
}
|
|
18064
|
-
}
|
|
18065
|
-
const winner = /* @__PURE__ */ new Map();
|
|
18066
|
-
const entry = /* @__PURE__ */ new Map();
|
|
18067
|
-
for (const piece of pieces) {
|
|
18068
|
-
for (const [name, value] of piece.entries) {
|
|
18069
|
-
const def = definitionOf(value);
|
|
18070
|
-
if (def === void 0) continue;
|
|
18071
|
-
winner.set(name, def);
|
|
18072
|
-
entry.set(name, value);
|
|
18073
|
-
}
|
|
18074
|
-
}
|
|
18075
|
-
const missing = /* @__PURE__ */ new Set();
|
|
18076
|
-
for (const piece of pieces) {
|
|
18077
|
-
for (const [name, value] of piece.entries) {
|
|
18078
|
-
if (!isRefSlot(value)) continue;
|
|
18079
|
-
const target = winner.get(name);
|
|
18080
|
-
if (target === void 0) {
|
|
18081
|
-
missing.add(name);
|
|
18082
|
-
continue;
|
|
18083
|
-
}
|
|
18084
|
-
repointRef(value, target, name);
|
|
18085
|
-
}
|
|
17945
|
+
function linkedMap(items, opts, leaf2) {
|
|
17946
|
+
const recipes = items.flatMap(recipesOf);
|
|
17947
|
+
const trivia2 = composingTriviaOf(items);
|
|
17948
|
+
const names = declaredNamesOf(items);
|
|
17949
|
+
let linked;
|
|
17950
|
+
const link = () => linked ??= linkComposition(recipes, { trivia: trivia2, ...opts?.hostMode === void 0 ? {} : { hostMode: opts.hostMode } });
|
|
17951
|
+
const map = {};
|
|
17952
|
+
for (const name of names) {
|
|
17953
|
+
Object.defineProperty(map, name, { enumerable: true, configurable: true, get: () => link()[name] });
|
|
18086
17954
|
}
|
|
18087
|
-
|
|
18088
|
-
|
|
18089
|
-
|
|
18090
|
-
|
|
18091
|
-
|
|
18092
|
-
|
|
18093
|
-
|
|
18094
|
-
if (opts.hostMode === "cst") meta.grammarHostMode = "cst";
|
|
18095
|
-
else meta.grammarHostMode = void 0;
|
|
18096
|
-
}
|
|
18097
|
-
}
|
|
18098
|
-
Object.defineProperty(out, INTERPRETED_PIECES, {
|
|
18099
|
-
value: pieces.filter((p) => p.plain).map((p) => p.entries),
|
|
18100
|
-
enumerable: false
|
|
18101
|
-
});
|
|
18102
|
-
return out;
|
|
17955
|
+
Object.defineProperty(map, RULES_RECIPE, { value: recipes, enumerable: false });
|
|
17956
|
+
Object.defineProperty(map, RULE_ORDER, { value: names, enumerable: false });
|
|
17957
|
+
Object.defineProperty(map, LINKED, { value: link, enumerable: false });
|
|
17958
|
+
Object.defineProperty(map, GRAMMAR_REFLECTION, { enumerable: false, configurable: true, get: () => link()[GRAMMAR_REFLECTION] });
|
|
17959
|
+
if (trivia2) Object.defineProperty(map, COMPOSED_TRIVIA, { value: trivia2, enumerable: false });
|
|
17960
|
+
if (leaf2) Object.defineProperty(map, LEAF_COMPOSED, { value: true, enumerable: false });
|
|
17961
|
+
return map;
|
|
18103
17962
|
}
|
|
18104
|
-
function
|
|
18105
|
-
|
|
18106
|
-
const deps = ruleDependencies(piece.entries.filter(([, v]) => definitionOf(v) !== void 0));
|
|
18107
|
-
for (const [name, ds] of deps) {
|
|
18108
|
-
for (const d of ds) if (missing.has(d)) return `fuseInterpreted: rule "${name}" references missing rule "${d}"`;
|
|
18109
|
-
}
|
|
18110
|
-
}
|
|
18111
|
-
return `fuseInterpreted: missing rule(s) ${[...missing].map((n) => `"${n}"`).join(", ")}`;
|
|
17963
|
+
function composeLeaf(items) {
|
|
17964
|
+
return linkedMap(items, void 0, true);
|
|
18112
17965
|
}
|
|
18113
17966
|
|
|
18114
17967
|
// src/analysis/grammar.ts
|
|
@@ -18141,7 +17994,7 @@ function analyzeGrammarGating(grammar, opts) {
|
|
|
18141
17994
|
}
|
|
18142
17995
|
|
|
18143
17996
|
// src/analysis/diagnose.ts
|
|
18144
|
-
var
|
|
17997
|
+
var isCombinator2 = (g) => typeof g === "object" && g !== null && "_def" in g;
|
|
18145
17998
|
var isRuleEntries = (g) => Array.isArray(g);
|
|
18146
17999
|
function diagnoseGrammar(grammar, opts) {
|
|
18147
18000
|
const depth = degradationCaptureDepth();
|
|
@@ -18185,7 +18038,7 @@ function formatGrammarDiagnosis(d) {
|
|
|
18185
18038
|
return lines;
|
|
18186
18039
|
}
|
|
18187
18040
|
function runAnalysis(grammar, opts) {
|
|
18188
|
-
if (
|
|
18041
|
+
if (isCombinator2(grammar)) return analyzeGating(grammar, opts);
|
|
18189
18042
|
if (isRuleEntries(grammar)) return analyzeGatingRules(grammar, opts);
|
|
18190
18043
|
return analyzeGrammarGating(grammar, opts);
|
|
18191
18044
|
}
|
|
@@ -19453,6 +19306,29 @@ function gate(predicate) {
|
|
|
19453
19306
|
};
|
|
19454
19307
|
}
|
|
19455
19308
|
|
|
19309
|
+
// src/combinators/withCtx.ts
|
|
19310
|
+
function withCtx(extra, combinator) {
|
|
19311
|
+
const meta = {
|
|
19312
|
+
firstSet: combinator._meta.firstSet,
|
|
19313
|
+
canMatchNewline: combinator._meta.canMatchNewline,
|
|
19314
|
+
isTrivia: false
|
|
19315
|
+
};
|
|
19316
|
+
return {
|
|
19317
|
+
_tag: "withCtx",
|
|
19318
|
+
_meta: meta,
|
|
19319
|
+
_def: { tag: "withCtx", extra, parser: combinator },
|
|
19320
|
+
parse(input, pos, ctx) {
|
|
19321
|
+
const saved = ctx.state;
|
|
19322
|
+
ctx.state = extra;
|
|
19323
|
+
try {
|
|
19324
|
+
return combinator.parse(input, pos, ctx);
|
|
19325
|
+
} finally {
|
|
19326
|
+
ctx.state = saved;
|
|
19327
|
+
}
|
|
19328
|
+
}
|
|
19329
|
+
};
|
|
19330
|
+
}
|
|
19331
|
+
|
|
19456
19332
|
// src/combinators/completions.ts
|
|
19457
19333
|
function completionsAt(target, input, offset, options = {}) {
|
|
19458
19334
|
const probe = { offset, best: null };
|
|
@@ -20135,7 +20011,7 @@ function grammarCoverageDefinitions(entry, winners) {
|
|
|
20135
20011
|
}
|
|
20136
20012
|
function composedGrammarCoverageDefinitions(grammar, startRule) {
|
|
20137
20013
|
const winners = composedCoverageRules(grammar);
|
|
20138
|
-
if (!winners) throw new TypeError("semantic coverage needs
|
|
20014
|
+
if (!winners) throw new TypeError("semantic coverage needs a runtime compose() result (a linked interpreter grammar); this is not one");
|
|
20139
20015
|
const entry = winners[startRule];
|
|
20140
20016
|
if (!entry) throw new TypeError(`semantic coverage start rule ${JSON.stringify(startRule)} is not a final winner`);
|
|
20141
20017
|
return grammarCoverageDefinitions(entry, winners);
|
|
@@ -20327,7 +20203,7 @@ function coverageEntry(entry, collector, maps, trace) {
|
|
|
20327
20203
|
case "leaf":
|
|
20328
20204
|
return def.cstValue === "source" ? sourceLeaf(build(def.parser), def.fn) : leaf(build(def.parser), def.fn);
|
|
20329
20205
|
case "field":
|
|
20330
|
-
return field(def.name, build(def.parser));
|
|
20206
|
+
return field(def.name, build(def.parser), { leadingTrivia: def.leadingTrivia === true, trailingTrivia: def.trailingTrivia === true });
|
|
20331
20207
|
case "grammar":
|
|
20332
20208
|
return parser({
|
|
20333
20209
|
...def.triviaParser === void 0 ? def.clearTrivia ? { trivia: null } : {} : { trivia: build(def.triviaParser) },
|
|
@@ -20377,7 +20253,7 @@ function coverageEntry(entry, collector, maps, trace) {
|
|
|
20377
20253
|
}
|
|
20378
20254
|
function runWithGrammarCoverage(entry, input, options = {}) {
|
|
20379
20255
|
if (typeof entry === "function") throw new TypeError("runWithGrammarCoverage currently requires an interpreter combinator entry");
|
|
20380
|
-
const plan = buildGrammarPlan(entry);
|
|
20256
|
+
const plan = buildGrammarPlan(entry, linkedWinnersOf(entry));
|
|
20381
20257
|
const definitions = plan.definitions;
|
|
20382
20258
|
const collector = options.collector ?? createGrammarCoverageCollector(definitions);
|
|
20383
20259
|
const { collector: _collector, trace, ...runOptions } = options;
|
|
@@ -20451,13 +20327,13 @@ function buildTriviaIndex(root, input = "", opts) {
|
|
|
20451
20327
|
}
|
|
20452
20328
|
|
|
20453
20329
|
// src/cst/walk.ts
|
|
20454
|
-
function
|
|
20330
|
+
function isCombinator3(value) {
|
|
20455
20331
|
return !!value && typeof value === "object" && "_def" in value && "_meta" in value && typeof value.parse === "function";
|
|
20456
20332
|
}
|
|
20457
20333
|
function reflectionFor(grammar) {
|
|
20458
20334
|
const stamped = grammarReflectionOf(grammar);
|
|
20459
20335
|
if (stamped) return stamped;
|
|
20460
|
-
const entries = Object.entries(grammar).filter((entry) =>
|
|
20336
|
+
const entries = Object.entries(grammar).filter((entry) => isCombinator3(entry[1]));
|
|
20461
20337
|
return collectGrammarReflection(entries);
|
|
20462
20338
|
}
|
|
20463
20339
|
function createVisitor(grammar, spec) {
|