parseman 0.56.0 → 0.58.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 +2232 -1088
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/cli/index.js +2247 -1103
- package/dist/cli/index.js.map +3 -3
- package/dist/combinators/dispatch.d.ts.map +1 -1
- package/dist/combinators/node.d.ts +1 -1
- package/dist/compiler/build-arity.d.ts +1 -1
- package/dist/compiler/build-arity.d.ts.map +1 -1
- package/dist/compiler/token-alphabet.d.ts +11 -1
- package/dist/compiler/token-alphabet.d.ts.map +1 -1
- package/dist/compiler/token-capability.js +69 -16
- package/dist/compiler/token-capability.js.map +2 -2
- package/dist/cst/capture-buffer.d.ts +6 -0
- package/dist/cst/capture-buffer.d.ts.map +1 -1
- package/dist/cst/trivia-kinds.d.ts +9 -1
- package/dist/cst/trivia-kinds.d.ts.map +1 -1
- package/dist/index.js +1446 -236
- package/dist/index.js.map +3 -3
- package/dist/language-service/index.js +1 -0
- package/dist/language-service/index.js.map +1 -1
- package/dist/parse-context.d.ts.map +1 -1
- package/dist/plugin/entry-supercompiler.d.ts +1 -1
- package/dist/plugin/entry-supercompiler.d.ts.map +1 -1
- package/dist/plugin/index.d.ts +51 -1
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +2126 -380
- package/dist/plugin/index.js.map +3 -3
- package/dist/plugin/ir-eval.d.ts +2 -0
- package/dist/plugin/ir-eval.d.ts.map +1 -1
- package/dist/regex/classes.d.ts.map +1 -1
- package/dist/run/index.js +1 -0
- package/dist/run/index.js.map +1 -1
- package/dist/table/assemble.d.ts +9 -0
- package/dist/table/assemble.d.ts.map +1 -1
- package/dist/table/child-slots.d.ts +4 -6
- package/dist/table/child-slots.d.ts.map +1 -1
- package/dist/table/compile-rule-map.d.ts +14 -2
- package/dist/table/compile-rule-map.d.ts.map +1 -1
- package/dist/table/emit-assembly.d.ts +17 -2
- package/dist/table/emit-assembly.d.ts.map +1 -1
- package/dist/table/emit.d.ts +5 -1
- package/dist/table/emit.d.ts.map +1 -1
- package/dist/table/encode.d.ts.map +1 -1
- package/dist/table/exec-baseline.d.ts.map +1 -1
- package/dist/table/exec.d.ts.map +1 -1
- package/dist/table/factor-choice.d.ts +42 -0
- package/dist/table/factor-choice.d.ts.map +1 -0
- package/dist/table/fail-clean.d.ts +3 -0
- package/dist/table/fail-clean.d.ts.map +1 -0
- package/dist/table/hold-gap.d.ts +8 -0
- package/dist/table/hold-gap.d.ts.map +1 -0
- package/dist/table/index.js +1798 -316
- package/dist/table/index.js.map +3 -3
- package/dist/table/lex-program.d.ts +7 -3
- package/dist/table/lex-program.d.ts.map +1 -1
- package/dist/table/ops.d.ts +17 -6
- package/dist/table/ops.d.ts.map +1 -1
- package/dist/table/program.d.ts +13 -0
- package/dist/table/program.d.ts.map +1 -1
- package/dist/table/run-support.d.ts +19 -0
- package/dist/table/run-support.d.ts.map +1 -1
- package/dist/table/scalar-terminal.d.ts +2 -0
- package/dist/table/scalar-terminal.d.ts.map +1 -1
- package/dist/table/select-hot.d.ts +6 -0
- package/dist/table/select-hot.d.ts.map +1 -0
- package/dist/table/site-labels.d.ts +66 -0
- package/dist/table/site-labels.d.ts.map +1 -1
- package/dist/table/trivia-gap.d.ts +31 -0
- package/dist/table/trivia-gap.d.ts.map +1 -0
- package/dist/types.d.ts +17 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +4 -1
- package/src/combinators/dispatch.ts +12 -3
- package/src/combinators/node.ts +6 -13
- package/src/combinators/trivia-skip.ts +44 -1
- package/src/compiler/build-arity.ts +3 -3
- package/src/compiler/token-alphabet.ts +57 -17
- package/src/cst/capture-buffer.ts +25 -0
- package/src/cst/trivia-kinds.ts +12 -1
- package/src/parse-context.ts +1 -0
- package/src/plugin/entry-supercompiler.ts +8 -9
- package/src/plugin/index.ts +362 -42
- package/src/plugin/ir-eval.ts +7 -1
- package/src/regex/classes.ts +3 -0
- package/src/table/assemble.ts +371 -83
- package/src/table/child-slots.ts +6 -8
- package/src/table/compile-rule-map.ts +64 -15
- package/src/table/emit-assembly.ts +244 -42
- package/src/table/emit.ts +11 -8
- package/src/table/encode.ts +149 -35
- package/src/table/exec-baseline.ts +1 -3
- package/src/table/exec.ts +34 -14
- package/src/table/factor-choice.ts +173 -0
- package/src/table/fail-clean.ts +130 -0
- package/src/table/hold-gap.ts +68 -0
- package/src/table/lex-program.ts +197 -43
- package/src/table/ops.ts +18 -7
- package/src/table/program.ts +24 -0
- package/src/table/run-support.ts +35 -0
- package/src/table/scalar-terminal.ts +8 -0
- package/src/table/select-hot.ts +70 -0
- package/src/table/site-labels.ts +135 -4
- package/src/table/trivia-gap.ts +109 -0
- package/src/types.ts +18 -0
- package/src/version.ts +1 -1
|
@@ -478,6 +478,31 @@ function pushCstChild(ctx, built, rawEntry2) {
|
|
|
478
478
|
else if (ctx._cstLeaves) ctx._cstLeaves.push(built);
|
|
479
479
|
if (ctx._cstRawChildren) ctx._cstRawChildren.push(rawEntry2);
|
|
480
480
|
}
|
|
481
|
+
function popCstChild(ctx) {
|
|
482
|
+
const b = ctx._cstBuf;
|
|
483
|
+
if (b) {
|
|
484
|
+
const ch2 = b.ch;
|
|
485
|
+
if (b.rawOnly !== true && ch2) {
|
|
486
|
+
ch2.pop();
|
|
487
|
+
if (ch2.length === 1) {
|
|
488
|
+
b.single = ch2[0];
|
|
489
|
+
b.ch = void 0;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
if (b.noRaw === true) b.rawLen = (b.rawLen ?? 1) - 1;
|
|
493
|
+
else if (b.raw) {
|
|
494
|
+
b.raw.pop();
|
|
495
|
+
if (b.raw.length === 1) {
|
|
496
|
+
b.rawSingle = b.raw[0];
|
|
497
|
+
b.raw = void 0;
|
|
498
|
+
}
|
|
499
|
+
} else b.rawSingle = void 0;
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
if (ctx._cstChildren) ctx._cstChildren.pop();
|
|
503
|
+
else if (ctx._cstLeaves) ctx._cstLeaves.pop();
|
|
504
|
+
if (ctx._cstRawChildren) ctx._cstRawChildren.pop();
|
|
505
|
+
}
|
|
481
506
|
function cstRawLen(ctx) {
|
|
482
507
|
const b = ctx._cstBuf;
|
|
483
508
|
if (b) {
|
|
@@ -707,6 +732,7 @@ function literalCodePoints(frag) {
|
|
|
707
732
|
if (ch2 === "\\") {
|
|
708
733
|
const e = frag[i + 1];
|
|
709
734
|
if (e === void 0) return null;
|
|
735
|
+
if (!(e in CLASS_ESCAPES) && /\w/.test(e)) return null;
|
|
710
736
|
out.push(e in CLASS_ESCAPES ? CLASS_ESCAPES[e] : e.codePointAt(0));
|
|
711
737
|
i += 2;
|
|
712
738
|
continue;
|
|
@@ -819,6 +845,7 @@ function createParseContext() {
|
|
|
819
845
|
_rootTriviaKindIndex: void 0,
|
|
820
846
|
_rootTriviaStrictScopes: void 0,
|
|
821
847
|
_rootTriviaCapture: void 0,
|
|
848
|
+
_gap: void 0,
|
|
822
849
|
_cstTriviaLog: void 0,
|
|
823
850
|
_fields: void 0,
|
|
824
851
|
_cstBuf: void 0,
|
|
@@ -1301,7 +1328,10 @@ function labeledTriviaSpec(arms, minRepeats) {
|
|
|
1301
1328
|
arms,
|
|
1302
1329
|
minRepeats,
|
|
1303
1330
|
visitor: commonLabeledTriviaVisitor({ arms, minRepeats }),
|
|
1304
|
-
charArms: charArmsFor({ arms, minRepeats })
|
|
1331
|
+
charArms: charArmsFor({ arms, minRepeats }),
|
|
1332
|
+
rootKinds: void 0,
|
|
1333
|
+
rootLeaders: [],
|
|
1334
|
+
rootScan: null
|
|
1305
1335
|
};
|
|
1306
1336
|
}
|
|
1307
1337
|
function matchArmAt(input, pos, arm, state) {
|
|
@@ -1761,8 +1791,50 @@ function loopScanner(arms) {
|
|
|
1761
1791
|
function regexTriviaScanner(parser2) {
|
|
1762
1792
|
const d = parser2._def.tag === "label" ? parser2._def.parser._def : parser2._def;
|
|
1763
1793
|
if (d.tag !== "regex" || d.flags) return null;
|
|
1764
|
-
|
|
1765
|
-
|
|
1794
|
+
return sourceScanner(d.source);
|
|
1795
|
+
}
|
|
1796
|
+
function sourceScanner(source) {
|
|
1797
|
+
return classRunSource(source) ?? altStarSource(source) ?? prefixRunSource(source) ?? delimitedSource(source) ?? sharedPrefixAltSource(source);
|
|
1798
|
+
}
|
|
1799
|
+
function sharedPrefixAltSource(source) {
|
|
1800
|
+
const m = /^((?:\\.|[^\\[\]()*+?|^$.{}])+)\(\?:(.*)\)$/.exec(source);
|
|
1801
|
+
if (!m) return null;
|
|
1802
|
+
const alts = [];
|
|
1803
|
+
const body = m[2];
|
|
1804
|
+
let depth = 0;
|
|
1805
|
+
let start = 0;
|
|
1806
|
+
for (let i = 0; i < body.length; i++) {
|
|
1807
|
+
const c = body[i];
|
|
1808
|
+
if (c === "\\") {
|
|
1809
|
+
i++;
|
|
1810
|
+
continue;
|
|
1811
|
+
}
|
|
1812
|
+
if (c === "[") {
|
|
1813
|
+
while (i < body.length && body[i] !== "]") i += body[i] === "\\" ? 2 : 1;
|
|
1814
|
+
continue;
|
|
1815
|
+
}
|
|
1816
|
+
if (c === "(") depth++;
|
|
1817
|
+
else if (c === ")" && --depth < 0) return null;
|
|
1818
|
+
else if (c === "|" && depth === 0) {
|
|
1819
|
+
alts.push(body.slice(start, i));
|
|
1820
|
+
start = i + 1;
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
if (depth !== 0 || alts.length === 0) return null;
|
|
1824
|
+
alts.push(body.slice(start));
|
|
1825
|
+
const scanners = [];
|
|
1826
|
+
for (const alt of alts) {
|
|
1827
|
+
const scanner = sourceScanner(m[1] + alt);
|
|
1828
|
+
if (scanner === null) return null;
|
|
1829
|
+
scanners.push(scanner);
|
|
1830
|
+
}
|
|
1831
|
+
return (input, cur) => {
|
|
1832
|
+
for (const scanner of scanners) {
|
|
1833
|
+
const end = scanner(input, cur);
|
|
1834
|
+
if (end > cur) return end;
|
|
1835
|
+
}
|
|
1836
|
+
return cur;
|
|
1837
|
+
};
|
|
1766
1838
|
}
|
|
1767
1839
|
function bmpString(cps) {
|
|
1768
1840
|
if (!cps) return null;
|
|
@@ -2299,6 +2371,9 @@ function parser(opts, root) {
|
|
|
2299
2371
|
};
|
|
2300
2372
|
return grammar;
|
|
2301
2373
|
}
|
|
2374
|
+
function noTrivia(root) {
|
|
2375
|
+
return parser({ trivia: null }, root);
|
|
2376
|
+
}
|
|
2302
2377
|
var _analyzed = /* @__PURE__ */ new WeakSet();
|
|
2303
2378
|
function parse(combinator, input, opts = {}) {
|
|
2304
2379
|
if (!_analyzed.has(combinator)) {
|
|
@@ -3793,17 +3868,59 @@ function buildLexBodyRecognizer(spec, constants) {
|
|
|
3793
3868
|
};
|
|
3794
3869
|
}
|
|
3795
3870
|
|
|
3871
|
+
// src/table/run-support.ts
|
|
3872
|
+
function lineCol(ctx, offset) {
|
|
3873
|
+
const starts = ctx._lineStarts ?? [0];
|
|
3874
|
+
let lo = 0, hi = starts.length - 1;
|
|
3875
|
+
while (lo < hi) {
|
|
3876
|
+
const mid = lo + hi + 1 >> 1;
|
|
3877
|
+
if (starts[mid] <= offset) lo = mid;
|
|
3878
|
+
else hi = mid - 1;
|
|
3879
|
+
}
|
|
3880
|
+
return [lo + 1, offset - starts[lo] + 1];
|
|
3881
|
+
}
|
|
3882
|
+
function spanLines(ctx, start, end) {
|
|
3883
|
+
const s = lineCol(ctx, start), e = lineCol(ctx, end);
|
|
3884
|
+
return { start, end, startLine: s[0], startColumn: s[1], endLine: e[0], endColumn: e[1] };
|
|
3885
|
+
}
|
|
3886
|
+
function rawEntry(v, input, s, e) {
|
|
3887
|
+
if (typeof v === "object" && v !== null) {
|
|
3888
|
+
const tg = v._tag;
|
|
3889
|
+
if (tg === "node" || tg === "leaf" || tg === "parseError") return v;
|
|
3890
|
+
}
|
|
3891
|
+
return {
|
|
3892
|
+
_tag: "leaf",
|
|
3893
|
+
value: typeof v === "string" ? v : typeof v === "object" && v !== null ? input.slice(s, e) : "",
|
|
3894
|
+
span: { start: s, end: e }
|
|
3895
|
+
};
|
|
3896
|
+
}
|
|
3897
|
+
function lead(input, pos) {
|
|
3898
|
+
if (pos >= input.length) return -1;
|
|
3899
|
+
const c = input.charCodeAt(pos);
|
|
3900
|
+
if (c < 55296 || c > 56319) return c;
|
|
3901
|
+
return input.codePointAt(pos) ?? c;
|
|
3902
|
+
}
|
|
3903
|
+
var EMPTY_KIDS = Object.freeze([]);
|
|
3904
|
+
var EMPTY_TRIVIA = Object.freeze([]);
|
|
3905
|
+
function collapseEmpty(ctx, build, input, pos, end, readsRaw) {
|
|
3906
|
+
const collected = ctx._cstBuf !== void 0 || ctx._cstChildren !== void 0;
|
|
3907
|
+
if (collected) popCstChild(ctx);
|
|
3908
|
+
const raw = readsRaw ? [rawEntry(void 0, input, pos, end)] : EMPTY_KIDS;
|
|
3909
|
+
const nd = build(EMPTY_KIDS, void 0, { start: pos, end }, raw, EMPTY_TRIVIA, void 0);
|
|
3910
|
+
if (collected) pushCstChild(ctx, nd, ctx._cstBuf?.noRaw === true ? void 0 : rawEntry(nd, input, pos, end));
|
|
3911
|
+
return nd;
|
|
3912
|
+
}
|
|
3913
|
+
|
|
3796
3914
|
// src/table/lex-program.ts
|
|
3797
3915
|
var LEX_NODE_TERMINAL = 0;
|
|
3798
3916
|
var LEX_NODE_SEQUENCE2 = 1;
|
|
3799
3917
|
var LEX_NODE_SEQUENCE3 = 2;
|
|
3800
3918
|
var LEX_NODE_SEQUENCE4 = 3;
|
|
3801
3919
|
var LEX_NODE_SEQUENCE5 = 4;
|
|
3802
|
-
var
|
|
3803
|
-
var LEX_NODE_CHOICE4 = 6;
|
|
3804
|
-
var LEX_NODE_CHOICE8 = 7;
|
|
3920
|
+
var LEX_NODE_CHOICE = 5;
|
|
3805
3921
|
var LEX_NODE_NOT = 8;
|
|
3806
3922
|
var LEX_NODE_OPTIONAL = 9;
|
|
3923
|
+
var LEX_NODE_REPEAT = 10;
|
|
3807
3924
|
function lexProgramDigest(words) {
|
|
3808
3925
|
let hash = 2166136261;
|
|
3809
3926
|
for (const word of words) {
|
|
@@ -3832,85 +3949,114 @@ function trackLexLines(ctx, input, end) {
|
|
|
3832
3949
|
ctx._lineScannedTo = end;
|
|
3833
3950
|
}
|
|
3834
3951
|
function terminalNode(matcher, failure, tracksLines) {
|
|
3835
|
-
const match = (input, pos) => {
|
|
3836
|
-
const result = matcher(input, pos);
|
|
3837
|
-
return result < 0 ? -1 : result / 2;
|
|
3838
|
-
};
|
|
3839
3952
|
return {
|
|
3840
|
-
match,
|
|
3953
|
+
match: (input, pos) => {
|
|
3954
|
+
const result = matcher(input, pos);
|
|
3955
|
+
return result < 0 ? -1 : result / 2;
|
|
3956
|
+
},
|
|
3841
3957
|
run: (input, pos, ctx) => {
|
|
3842
|
-
const
|
|
3843
|
-
if (
|
|
3958
|
+
const result = matcher(input, pos);
|
|
3959
|
+
if (result < 0) {
|
|
3844
3960
|
ctx._fe = pos;
|
|
3845
3961
|
ctx._fx = failure;
|
|
3846
3962
|
if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
|
|
3847
3963
|
return -1;
|
|
3848
3964
|
}
|
|
3965
|
+
const end = result / 2;
|
|
3849
3966
|
if (tracksLines) trackLexLines(ctx, input, end);
|
|
3850
3967
|
return end;
|
|
3851
3968
|
}
|
|
3852
3969
|
};
|
|
3853
3970
|
}
|
|
3854
3971
|
function sequence2(a, b) {
|
|
3972
|
+
const am = a.match, bm = b.match, ar = a.run, br = b.run;
|
|
3855
3973
|
return {
|
|
3856
3974
|
match: (input, pos) => {
|
|
3857
|
-
const e0 =
|
|
3858
|
-
return e0 < 0 ? -1 :
|
|
3975
|
+
const e0 = am(input, pos);
|
|
3976
|
+
return e0 < 0 ? -1 : bm(input, e0);
|
|
3859
3977
|
},
|
|
3860
3978
|
run: (input, pos, ctx) => {
|
|
3861
|
-
const e0 =
|
|
3979
|
+
const e0 = ar(input, pos, ctx);
|
|
3862
3980
|
if (e0 < 0) return -1;
|
|
3863
3981
|
ctx._fc = false;
|
|
3864
|
-
return
|
|
3982
|
+
return br(input, e0, ctx);
|
|
3865
3983
|
}
|
|
3866
3984
|
};
|
|
3867
3985
|
}
|
|
3868
3986
|
function sequence3(a, b, c) {
|
|
3987
|
+
const am = a.match, bm = b.match, cm = c.match, ar = a.run, br = b.run, cr = c.run;
|
|
3869
3988
|
return {
|
|
3870
3989
|
match: (input, pos) => {
|
|
3871
|
-
const e0 =
|
|
3990
|
+
const e0 = am(input, pos);
|
|
3872
3991
|
if (e0 < 0) return -1;
|
|
3873
|
-
const e1 =
|
|
3874
|
-
return e1 < 0 ? -1 :
|
|
3992
|
+
const e1 = bm(input, e0);
|
|
3993
|
+
return e1 < 0 ? -1 : cm(input, e1);
|
|
3875
3994
|
},
|
|
3876
3995
|
run: (input, pos, ctx) => {
|
|
3877
|
-
const e0 =
|
|
3996
|
+
const e0 = ar(input, pos, ctx);
|
|
3878
3997
|
if (e0 < 0) return -1;
|
|
3879
3998
|
ctx._fc = false;
|
|
3880
|
-
const e1 =
|
|
3999
|
+
const e1 = br(input, e0, ctx);
|
|
3881
4000
|
if (e1 < 0) return -1;
|
|
3882
4001
|
ctx._fc = false;
|
|
3883
|
-
return
|
|
4002
|
+
return cr(input, e1, ctx);
|
|
3884
4003
|
}
|
|
3885
4004
|
};
|
|
3886
4005
|
}
|
|
3887
4006
|
function sequence4(a, b, c, d) {
|
|
3888
|
-
const
|
|
4007
|
+
const am = a.match, bm = b.match, cm = c.match, dm = d.match;
|
|
4008
|
+
const ar = a.run, br = b.run, cr = c.run, dr = d.run;
|
|
3889
4009
|
return {
|
|
3890
4010
|
match: (input, pos) => {
|
|
3891
|
-
const
|
|
3892
|
-
|
|
4011
|
+
const e0 = am(input, pos);
|
|
4012
|
+
if (e0 < 0) return -1;
|
|
4013
|
+
const e1 = bm(input, e0);
|
|
4014
|
+
if (e1 < 0) return -1;
|
|
4015
|
+
const e2 = cm(input, e1);
|
|
4016
|
+
return e2 < 0 ? -1 : dm(input, e2);
|
|
3893
4017
|
},
|
|
3894
4018
|
run: (input, pos, ctx) => {
|
|
3895
|
-
const
|
|
3896
|
-
if (
|
|
4019
|
+
const e0 = ar(input, pos, ctx);
|
|
4020
|
+
if (e0 < 0) return -1;
|
|
4021
|
+
ctx._fc = false;
|
|
4022
|
+
const e1 = br(input, e0, ctx);
|
|
4023
|
+
if (e1 < 0) return -1;
|
|
4024
|
+
ctx._fc = false;
|
|
4025
|
+
const e2 = cr(input, e1, ctx);
|
|
4026
|
+
if (e2 < 0) return -1;
|
|
3897
4027
|
ctx._fc = false;
|
|
3898
|
-
return
|
|
4028
|
+
return dr(input, e2, ctx);
|
|
3899
4029
|
}
|
|
3900
4030
|
};
|
|
3901
4031
|
}
|
|
3902
4032
|
function sequence5(a, b, c, d, e) {
|
|
3903
|
-
const
|
|
4033
|
+
const am = a.match, bm = b.match, cm = c.match, dm = d.match, em = e.match;
|
|
4034
|
+
const ar = a.run, br = b.run, cr = c.run, dr = d.run, er = e.run;
|
|
3904
4035
|
return {
|
|
3905
4036
|
match: (input, pos) => {
|
|
3906
|
-
const
|
|
3907
|
-
|
|
4037
|
+
const e0 = am(input, pos);
|
|
4038
|
+
if (e0 < 0) return -1;
|
|
4039
|
+
const e1 = bm(input, e0);
|
|
4040
|
+
if (e1 < 0) return -1;
|
|
4041
|
+
const e2 = cm(input, e1);
|
|
4042
|
+
if (e2 < 0) return -1;
|
|
4043
|
+
const e3 = dm(input, e2);
|
|
4044
|
+
return e3 < 0 ? -1 : em(input, e3);
|
|
3908
4045
|
},
|
|
3909
4046
|
run: (input, pos, ctx) => {
|
|
3910
|
-
const
|
|
3911
|
-
if (
|
|
4047
|
+
const e0 = ar(input, pos, ctx);
|
|
4048
|
+
if (e0 < 0) return -1;
|
|
4049
|
+
ctx._fc = false;
|
|
4050
|
+
const e1 = br(input, e0, ctx);
|
|
4051
|
+
if (e1 < 0) return -1;
|
|
4052
|
+
ctx._fc = false;
|
|
4053
|
+
const e2 = cr(input, e1, ctx);
|
|
4054
|
+
if (e2 < 0) return -1;
|
|
3912
4055
|
ctx._fc = false;
|
|
3913
|
-
|
|
4056
|
+
const e3 = dr(input, e2, ctx);
|
|
4057
|
+
if (e3 < 0) return -1;
|
|
4058
|
+
ctx._fc = false;
|
|
4059
|
+
return er(input, e3, ctx);
|
|
3914
4060
|
}
|
|
3915
4061
|
};
|
|
3916
4062
|
}
|
|
@@ -3923,9 +4069,9 @@ function appendExpected(acc, values) {
|
|
|
3923
4069
|
function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
3924
4070
|
let matchTail = () => -1;
|
|
3925
4071
|
for (let i = arms.length - 1; i >= 0; i--) {
|
|
3926
|
-
const
|
|
4072
|
+
const armMatch = arms[i].match, next = matchTail;
|
|
3927
4073
|
matchTail = (input, pos) => {
|
|
3928
|
-
const end =
|
|
4074
|
+
const end = armMatch(input, pos);
|
|
3929
4075
|
return end < 0 ? next(input, pos) : end;
|
|
3930
4076
|
};
|
|
3931
4077
|
}
|
|
@@ -3935,7 +4081,7 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
3935
4081
|
return -1;
|
|
3936
4082
|
};
|
|
3937
4083
|
for (let i = arms.length - 1; i >= 0; i--) {
|
|
3938
|
-
const
|
|
4084
|
+
const armRun = arms[i].run, cls = classes[i], staticExpected = armExpected[i], next = tail;
|
|
3939
4085
|
tail = (input, pos, ctx, lead2, acc, best) => {
|
|
3940
4086
|
if (cls !== void 0 && !classHas(cls, lead2)) {
|
|
3941
4087
|
return next(
|
|
@@ -3948,7 +4094,7 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
3948
4094
|
);
|
|
3949
4095
|
}
|
|
3950
4096
|
ctx._fc = false;
|
|
3951
|
-
const end =
|
|
4097
|
+
const end = armRun(input, pos, ctx);
|
|
3952
4098
|
if (end >= 0) return end;
|
|
3953
4099
|
const at = ctx._fe ?? pos;
|
|
3954
4100
|
if (at > best) {
|
|
@@ -3975,11 +4121,58 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
3975
4121
|
)
|
|
3976
4122
|
};
|
|
3977
4123
|
}
|
|
4124
|
+
function exclusiveChoiceNode(arms, classes, choiceFx) {
|
|
4125
|
+
const ascii = (classes.length <= 128 ? new Int8Array(128) : new Int32Array(128)).fill(-1);
|
|
4126
|
+
const hi = [];
|
|
4127
|
+
for (let i = 0; i < classes.length; i++) {
|
|
4128
|
+
const cls = classes[i];
|
|
4129
|
+
for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) ascii[c] = i;
|
|
4130
|
+
for (let r = 0; r < cls.hi.length; r += 2) hi.push(cls.hi[r], cls.hi[r + 1], i);
|
|
4131
|
+
}
|
|
4132
|
+
const select = (code) => {
|
|
4133
|
+
if (code < 0) return -1;
|
|
4134
|
+
if (code < 128) return ascii[code];
|
|
4135
|
+
for (let r = 0; r < hi.length; r += 3) if (code >= hi[r] && code <= hi[r + 1]) return hi[r + 2];
|
|
4136
|
+
return -1;
|
|
4137
|
+
};
|
|
4138
|
+
let matchArm = () => -1;
|
|
4139
|
+
let selectRun = () => -1;
|
|
4140
|
+
for (let i = arms.length - 1; i >= 0; i--) {
|
|
4141
|
+
const armMatch = arms[i].match, armRun = arms[i].run, nextMatch = matchArm, nextRun = selectRun;
|
|
4142
|
+
matchArm = (selected, input, pos) => selected === i ? armMatch(input, pos) : nextMatch(selected, input, pos);
|
|
4143
|
+
selectRun = (selected, input, pos, ctx) => selected === i ? armRun(input, pos, ctx) : nextRun(selected, input, pos, ctx);
|
|
4144
|
+
}
|
|
4145
|
+
const runArm = (input, pos, ctx) => {
|
|
4146
|
+
const arm = select(lead(input, pos));
|
|
4147
|
+
if (arm >= 0) {
|
|
4148
|
+
ctx._fc = false;
|
|
4149
|
+
const end = selectRun(arm, input, pos, ctx);
|
|
4150
|
+
if (end >= 0) return end;
|
|
4151
|
+
if (committed(ctx)) return -1;
|
|
4152
|
+
const failed = ctx._fx;
|
|
4153
|
+
if (failed !== void 0 && failed.length > 0) {
|
|
4154
|
+
ctx._fe = pos;
|
|
4155
|
+
return -1;
|
|
4156
|
+
}
|
|
4157
|
+
}
|
|
4158
|
+
ctx._fe = pos;
|
|
4159
|
+
ctx._fx = choiceFx;
|
|
4160
|
+
return -1;
|
|
4161
|
+
};
|
|
4162
|
+
return {
|
|
4163
|
+
match: (input, pos) => {
|
|
4164
|
+
const arm = select(lead(input, pos));
|
|
4165
|
+
return arm < 0 ? -1 : matchArm(arm, input, pos);
|
|
4166
|
+
},
|
|
4167
|
+
run: runArm
|
|
4168
|
+
};
|
|
4169
|
+
}
|
|
3978
4170
|
function notNode(body, failure) {
|
|
4171
|
+
const bodyMatch = body.match;
|
|
3979
4172
|
return {
|
|
3980
|
-
match: (input, pos) =>
|
|
4173
|
+
match: (input, pos) => bodyMatch(input, pos) < 0 ? pos : -1,
|
|
3981
4174
|
run: (input, pos, ctx) => {
|
|
3982
|
-
if (
|
|
4175
|
+
if (bodyMatch(input, pos) < 0) return pos;
|
|
3983
4176
|
ctx._fe = pos;
|
|
3984
4177
|
ctx._fx = failure;
|
|
3985
4178
|
return -1;
|
|
@@ -3987,18 +4180,57 @@ function notNode(body, failure) {
|
|
|
3987
4180
|
};
|
|
3988
4181
|
}
|
|
3989
4182
|
function optionalNode(body) {
|
|
4183
|
+
const bodyMatch = body.match, bodyRun = body.run;
|
|
3990
4184
|
return {
|
|
3991
4185
|
match: (input, pos) => {
|
|
3992
|
-
const end =
|
|
4186
|
+
const end = bodyMatch(input, pos);
|
|
3993
4187
|
return end < 0 ? pos : end;
|
|
3994
4188
|
},
|
|
3995
4189
|
run: (input, pos, ctx) => {
|
|
3996
4190
|
ctx._fc = false;
|
|
3997
|
-
const end =
|
|
4191
|
+
const end = bodyRun(input, pos, ctx);
|
|
3998
4192
|
return end < 0 && !committed(ctx) ? pos : end;
|
|
3999
4193
|
}
|
|
4000
4194
|
};
|
|
4001
4195
|
}
|
|
4196
|
+
function repeatNode(item, min, max) {
|
|
4197
|
+
const itemMatch = item.match, itemRun = item.run;
|
|
4198
|
+
return {
|
|
4199
|
+
match: (input, pos) => {
|
|
4200
|
+
let cur = pos;
|
|
4201
|
+
let count = 0;
|
|
4202
|
+
for (; ; ) {
|
|
4203
|
+
if (max >= 0 && count >= max) break;
|
|
4204
|
+
const optional2 = count >= min && (count > 0 || min === 0);
|
|
4205
|
+
if (optional2 && cur >= input.length) break;
|
|
4206
|
+
const end = itemMatch(input, cur);
|
|
4207
|
+
if (end < 0 || optional2 && end === cur) break;
|
|
4208
|
+
cur = end;
|
|
4209
|
+
count++;
|
|
4210
|
+
}
|
|
4211
|
+
return count < min ? -1 : cur;
|
|
4212
|
+
},
|
|
4213
|
+
run: (input, pos, ctx) => {
|
|
4214
|
+
let cur = pos;
|
|
4215
|
+
let count = 0;
|
|
4216
|
+
for (; ; ) {
|
|
4217
|
+
if (max >= 0 && count >= max) break;
|
|
4218
|
+
const optional2 = count >= min && (count > 0 || min === 0);
|
|
4219
|
+
if (optional2 && cur >= input.length) break;
|
|
4220
|
+
ctx._fc = false;
|
|
4221
|
+
const end = itemRun(input, cur, ctx);
|
|
4222
|
+
if (end < 0) {
|
|
4223
|
+
if (committed(ctx)) return -1;
|
|
4224
|
+
break;
|
|
4225
|
+
}
|
|
4226
|
+
if (optional2 && end === cur) break;
|
|
4227
|
+
cur = end;
|
|
4228
|
+
count++;
|
|
4229
|
+
}
|
|
4230
|
+
return count < min ? -1 : cur;
|
|
4231
|
+
}
|
|
4232
|
+
};
|
|
4233
|
+
}
|
|
4002
4234
|
function fixedTreeRunner(words, matchers, classes, expected) {
|
|
4003
4235
|
const stack = [];
|
|
4004
4236
|
const pop = () => {
|
|
@@ -4026,9 +4258,14 @@ function fixedTreeRunner(words, matchers, classes, expected) {
|
|
|
4026
4258
|
else stack.push(sequence5(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4]));
|
|
4027
4259
|
continue;
|
|
4028
4260
|
}
|
|
4029
|
-
if (op
|
|
4030
|
-
const count =
|
|
4261
|
+
if (op === LEX_NODE_CHOICE) {
|
|
4262
|
+
const count = words[at++];
|
|
4263
|
+
const exclusive = words[at++];
|
|
4264
|
+
if (exclusive !== 0 && exclusive !== 1) throw new TypeError("table lexical tree choice has an invalid dispatch mode");
|
|
4031
4265
|
const choiceFx = expected[words[at++]];
|
|
4266
|
+
if (!Number.isInteger(count) || count < 2 || count > stack.length) {
|
|
4267
|
+
throw new TypeError("table lexical tree choice has an invalid arm count");
|
|
4268
|
+
}
|
|
4032
4269
|
if (choiceFx === void 0) throw new TypeError("table lexical tree choice has an invalid expected set");
|
|
4033
4270
|
const armClasses = [];
|
|
4034
4271
|
const armFx = [];
|
|
@@ -4041,7 +4278,7 @@ function fixedTreeRunner(words, matchers, classes, expected) {
|
|
|
4041
4278
|
armFx.push(fx);
|
|
4042
4279
|
}
|
|
4043
4280
|
const arms = Array.from({ length: count }, pop).reverse();
|
|
4044
|
-
stack.push(choiceNode(arms, armClasses, armFx, choiceFx));
|
|
4281
|
+
stack.push(exclusive === 1 ? exclusiveChoiceNode(arms, armClasses, choiceFx) : choiceNode(arms, armClasses, armFx, choiceFx));
|
|
4045
4282
|
continue;
|
|
4046
4283
|
}
|
|
4047
4284
|
if (op === LEX_NODE_NOT) {
|
|
@@ -4054,6 +4291,14 @@ function fixedTreeRunner(words, matchers, classes, expected) {
|
|
|
4054
4291
|
stack.push(optionalNode(pop()));
|
|
4055
4292
|
continue;
|
|
4056
4293
|
}
|
|
4294
|
+
if (op === LEX_NODE_REPEAT) {
|
|
4295
|
+
const min = words[at++], max = words[at++];
|
|
4296
|
+
if (!Number.isInteger(min) || min < 0 || !Number.isInteger(max) || max >= 0 && max < min) {
|
|
4297
|
+
throw new TypeError("table lexical tree repeat has invalid bounds");
|
|
4298
|
+
}
|
|
4299
|
+
stack.push(repeatNode(pop(), min, max));
|
|
4300
|
+
continue;
|
|
4301
|
+
}
|
|
4057
4302
|
throw new TypeError("table lexical tree has an unknown fixed body");
|
|
4058
4303
|
}
|
|
4059
4304
|
if (stack.length !== 1) throw new TypeError("table lexical tree does not resolve to one root body");
|
|
@@ -4208,6 +4453,12 @@ function scanRefs(s) {
|
|
|
4208
4453
|
refs.push(...s.skip);
|
|
4209
4454
|
return refs;
|
|
4210
4455
|
}
|
|
4456
|
+
function assemblyExtraIps(prog) {
|
|
4457
|
+
const ips = [];
|
|
4458
|
+
for (const s of prog.scans ?? []) for (const r of scanRefs(s)) ips.push(r[0]);
|
|
4459
|
+
for (const set of prog.scanSkip ?? []) for (const r of set) ips.push(r[0]);
|
|
4460
|
+
return ips;
|
|
4461
|
+
}
|
|
4211
4462
|
function expandCompact(p) {
|
|
4212
4463
|
if ("code" in p) return p;
|
|
4213
4464
|
return ownTableProgram({
|
|
@@ -4338,6 +4589,11 @@ function classHas2(cls, code) {
|
|
|
4338
4589
|
for (let i = 0; i < hi.length; i += 2) if (code >= hi[i] && code <= hi[i + 1]) return true;
|
|
4339
4590
|
return false;
|
|
4340
4591
|
}
|
|
4592
|
+
function dispatchIsExclusive(arms, cc) {
|
|
4593
|
+
const resolved = [];
|
|
4594
|
+
for (const ci of arms) if (ci >= 0) resolved[ci] = resolveClass(cc[ci]);
|
|
4595
|
+
return resolveDispatch(arms, resolved).exclusive;
|
|
4596
|
+
}
|
|
4341
4597
|
function resolveDispatch(arms, cc) {
|
|
4342
4598
|
const ascii = new Uint8Array(128);
|
|
4343
4599
|
const hi = [];
|
|
@@ -4411,117 +4667,738 @@ function resolveTable(prog) {
|
|
|
4411
4667
|
return built;
|
|
4412
4668
|
}
|
|
4413
4669
|
|
|
4414
|
-
// src/
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
switch (d.tag) {
|
|
4418
|
-
case "sequence":
|
|
4419
|
-
case "choice":
|
|
4420
|
-
return d.parsers;
|
|
4421
|
-
case "dispatch":
|
|
4422
|
-
return [
|
|
4423
|
-
d.selector,
|
|
4424
|
-
...d.cases.map((c) => c.parser),
|
|
4425
|
-
...d.matchers ? d.matchers.map((c) => c.parser) : [],
|
|
4426
|
-
...d.otherwise === void 0 ? [] : [d.otherwise]
|
|
4427
|
-
];
|
|
4428
|
-
case "sepBy":
|
|
4429
|
-
return [d.parser, d.separator];
|
|
4430
|
-
case "recover":
|
|
4431
|
-
return [d.parser, d.sentinel];
|
|
4432
|
-
case "scanTo":
|
|
4433
|
-
return [
|
|
4434
|
-
d.sentinel,
|
|
4435
|
-
...d.skip,
|
|
4436
|
-
...d.recoverAt === void 0 ? [] : [d.recoverAt],
|
|
4437
|
-
...d.stopAt === void 0 ? [] : [d.stopAt]
|
|
4438
|
-
];
|
|
4439
|
-
case "grammar":
|
|
4440
|
-
return d.triviaParser ? [d.parser, d.triviaParser] : [d.parser];
|
|
4441
|
-
case "routed":
|
|
4442
|
-
return d.fallback ? [d.fallback] : [];
|
|
4443
|
-
case "lines":
|
|
4444
|
-
return [d.prefix, d.body, ...d.first === void 0 ? [] : [d.first], ...d.lazy === void 0 ? [] : [d.lazy]];
|
|
4445
|
-
case "columns":
|
|
4446
|
-
return [];
|
|
4447
|
-
// A `lazy` is a REFERENCE, not a subtree. Descending through it would make
|
|
4448
|
-
// every rule's walk cover the whole reachable grammar — site paths become
|
|
4449
|
-
// nonsense, and a structural hash includes half the grammar. Treated as a
|
|
4450
|
-
// leaf, keyed by the rule name it refers to, which is also the right
|
|
4451
|
-
// semantics: two productions referencing `g.Ident` really do fill that slot
|
|
4452
|
-
// the same way.
|
|
4453
|
-
case "lazy":
|
|
4454
|
-
case "literal":
|
|
4455
|
-
case "regex":
|
|
4456
|
-
case "keywords":
|
|
4457
|
-
case "guard":
|
|
4458
|
-
case "adjacency":
|
|
4459
|
-
case "unknown":
|
|
4460
|
-
return [];
|
|
4461
|
-
default: {
|
|
4462
|
-
const rec = d;
|
|
4463
|
-
return rec.parser ? [rec.parser] : [];
|
|
4464
|
-
}
|
|
4465
|
-
}
|
|
4670
|
+
// src/combinators/adjacency.ts
|
|
4671
|
+
function adjacencyOf(p) {
|
|
4672
|
+
return p._def.tag === "adjacency" ? p._def : null;
|
|
4466
4673
|
}
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
if (b.kind === "any") return a;
|
|
4471
|
-
if (a.kind === "empty" || b.kind === "empty") return { kind: "empty" };
|
|
4472
|
-
const ranges = [];
|
|
4473
|
-
for (const ra of a.ranges) for (const rb of b.ranges) {
|
|
4474
|
-
const lo = Math.max(ra.lo, rb.lo);
|
|
4475
|
-
const hi = Math.min(ra.hi, rb.hi);
|
|
4476
|
-
if (lo <= hi) ranges.push({ lo, hi });
|
|
4477
|
-
}
|
|
4478
|
-
return ranges.length === 0 ? { kind: "empty" } : { kind: "ranges", ranges };
|
|
4674
|
+
function adjacencyExpected(def) {
|
|
4675
|
+
if (def.polarity === "adjacent") return "adjacent";
|
|
4676
|
+
return def.kinds === void 0 ? "notAdjacent" : `notAdjacent(${def.kinds.join("|")})`;
|
|
4479
4677
|
}
|
|
4480
|
-
function
|
|
4481
|
-
|
|
4482
|
-
for (const s of sets) {
|
|
4483
|
-
if (s.kind === "any") return { kind: "any" };
|
|
4484
|
-
if (s.kind === "empty") continue;
|
|
4485
|
-
acc = acc.kind === "ranges" ? { kind: "ranges", ranges: [...acc.ranges, ...s.ranges] } : s;
|
|
4486
|
-
}
|
|
4487
|
-
return acc;
|
|
4678
|
+
function holdsAdjacency(input, cur, ctx, def) {
|
|
4679
|
+
return adjacencyHolds(input, cur, ctx, def.polarity === "notAdjacent", def.kinds);
|
|
4488
4680
|
}
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
if (
|
|
4492
|
-
if (
|
|
4493
|
-
|
|
4681
|
+
function adjacencyHolds(input, cur, ctx, negated, kinds) {
|
|
4682
|
+
const end = probeTriviaEnd(input, cur, ctx);
|
|
4683
|
+
if (!negated) return end === cur;
|
|
4684
|
+
if (end === cur) return false;
|
|
4685
|
+
if (kinds === void 0) return true;
|
|
4686
|
+
const want = resolveAdjacencyKindMask(ctx.trivia, kinds);
|
|
4687
|
+
const spec = analyzeLabeledTrivia(ctx.trivia);
|
|
4688
|
+
return (triviaKindMaskAt(input, cur, spec, ctx.state) & want) !== 0;
|
|
4494
4689
|
}
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
var SUGGESTIONS = {
|
|
4498
|
-
"broad-recognizer": "This arm can begin with any character, so no single-character test can rule it out. The parser has to enter it \u2014 set up, try, and undo \u2014 at every position it reaches, instead of skipping it for free.\nTo fix: make the arm begin with a fixed character, word or keyword. If it is meant to be a catch-all that matches anything, leave it and add the choice to the accept list at the end.",
|
|
4499
|
-
"leading-not": "This arm begins with a not(...) check, which matches nothing and so says nothing about which character the arm starts with. The parser then cannot rule the arm out and enters it everywhere.\nTo fix: put the term that actually consumes text first and keep not(...) after it as a trailing boundary. If you need to REQUIRE something ahead without consuming it, use peek(X) \u2014 it checks the same thing but still tells parseman that the arm starts with X.",
|
|
4500
|
-
"nullable-prefix": "This arm begins with something optional \u2014 an optional(...) or a repeat that allows zero items \u2014 so the arm can also start with whatever comes AFTER it, and that is broad enough that no character rules the arm out.\nTo fix: give the optional part its own arm so each arm has a definite beginning, or require at least one item. A plain sepBy(item, sep) also matches nothing at all; pass { min: 1 } when the list must not be empty.",
|
|
4501
|
-
"cross-artifact-ref": "This arm hands off to another rule, and that rule has the same problem \u2014 it can begin with any character \u2014 so the cost is inherited rather than caused here.\nTo fix: run this check on the rule it refers to and fix it there. One rule given a definite beginning fixes every choice that uses it.",
|
|
4502
|
-
"opaque-wrapper": "This arm begins with a wrapper that only inspects parser state (a gate/withCtx/recover) and consumes no text, so it says nothing about which character the arm starts with.\nTo fix: put a term that actually matches text in front of the wrapper.",
|
|
4503
|
-
"ref-cycle": "This arm refers back to itself through a cycle of rules, and parseman could not work out a definite first character for any of them.\nTo fix: make sure the base case of the recursion begins with a fixed character or keyword, so the cycle has somewhere definite to start."
|
|
4504
|
-
};
|
|
4505
|
-
function refineSuggestion(cause, arm) {
|
|
4506
|
-
if (cause !== "broad-recognizer") return SUGGESTIONS[cause];
|
|
4507
|
-
const lead2 = peelToLeading(arm);
|
|
4508
|
-
const d = lead2._def;
|
|
4509
|
-
if (d.tag === "regex" && KEYWORD_REGEX_RE.test(d.source)) {
|
|
4510
|
-
return `This arm matches the fixed word \`${d.source}\` with a regular expression, and parseman cannot always tell from a regular expression which character it starts with.
|
|
4511
|
-
To fix: write it as word('\u2026') or keywords([\u2026]) instead. They match exactly the same text and compile to the same character scan, but they also tell parseman the first character, which is what lets the parser skip this arm when it cannot match.`;
|
|
4512
|
-
}
|
|
4513
|
-
if (d.tag === "scanTo") {
|
|
4514
|
-
return "This arm ends in a scanTo(...) catch-all, which reads forward until it finds something and so can begin at any character. The parser can never rule it out. That is usually exactly what you want from a fallback.\nTo fix: usually nothing. Add this choice to the accept list at the end so the check keeps flagging the choices that are real problems.";
|
|
4515
|
-
}
|
|
4516
|
-
return SUGGESTIONS[cause];
|
|
4690
|
+
function adjacencyFail(pos, def) {
|
|
4691
|
+
return { ok: false, expected: [adjacencyExpected(def)], span: { start: pos, end: pos } };
|
|
4517
4692
|
}
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4693
|
+
var NO_STANDALONE_PARSE = "adjacency assertions are boundary tests: use adjacent()/notAdjacent() as a NON-FIRST term of a sequence(), where the preceding term defines the gap being asserted.";
|
|
4694
|
+
function adjacencyMisuse(polarity) {
|
|
4695
|
+
return new TypeError(`${polarity}(): ${NO_STANDALONE_PARSE}`);
|
|
4696
|
+
}
|
|
4697
|
+
function adjacencyCombinator(def) {
|
|
4698
|
+
const meta = {
|
|
4699
|
+
// Zero-width and never leading (sequence() rejects index 0), so it contributes
|
|
4700
|
+
// no first char. `isZeroWidthAssertion` drops it from a sequence's first-set
|
|
4701
|
+
// rather than letting `any` poison the enclosing choice's dispatch.
|
|
4702
|
+
firstSet: { kind: "any" },
|
|
4703
|
+
canMatchNewline: false,
|
|
4704
|
+
isTrivia: false
|
|
4705
|
+
};
|
|
4706
|
+
return {
|
|
4707
|
+
_tag: "adjacency",
|
|
4708
|
+
_meta: meta,
|
|
4709
|
+
_def: def,
|
|
4710
|
+
parse() {
|
|
4711
|
+
throw adjacencyMisuse(def.polarity);
|
|
4712
|
+
}
|
|
4713
|
+
};
|
|
4714
|
+
}
|
|
4715
|
+
function adjacent() {
|
|
4716
|
+
return adjacencyCombinator({ tag: "adjacency", polarity: "adjacent" });
|
|
4717
|
+
}
|
|
4718
|
+
function notAdjacent(options) {
|
|
4719
|
+
const kinds = options?.kinds;
|
|
4720
|
+
if (kinds !== void 0) {
|
|
4721
|
+
if (!Array.isArray(kinds) || kinds.length === 0) {
|
|
4722
|
+
throw new TypeError("notAdjacent({ kinds }): kinds must be a non-empty array of trivia category names.");
|
|
4723
|
+
}
|
|
4724
|
+
for (const k of kinds) {
|
|
4725
|
+
if (typeof k !== "string" || k.length === 0) {
|
|
4726
|
+
throw new TypeError(`notAdjacent({ kinds }): every kind must be a non-empty string, got ${JSON.stringify(k)}.`);
|
|
4727
|
+
}
|
|
4728
|
+
}
|
|
4729
|
+
}
|
|
4730
|
+
return adjacencyCombinator(
|
|
4731
|
+
kinds === void 0 ? { tag: "adjacency", polarity: "notAdjacent" } : { tag: "adjacency", polarity: "notAdjacent", kinds: [...kinds] }
|
|
4732
|
+
);
|
|
4733
|
+
}
|
|
4734
|
+
|
|
4735
|
+
// src/combinators/sequence.ts
|
|
4736
|
+
function sequence(...parsers) {
|
|
4737
|
+
let adjacency = null;
|
|
4738
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
4739
|
+
const a = adjacencyOf(parsers[i]);
|
|
4740
|
+
if (a === null) continue;
|
|
4741
|
+
if (i === 0) {
|
|
4742
|
+
throw new TypeError(
|
|
4743
|
+
`sequence(): ${a.polarity}() cannot be the FIRST term \u2014 an adjacency assertion tests the gap after the PRECEDING term. Put a concrete term first.`
|
|
4744
|
+
);
|
|
4745
|
+
}
|
|
4746
|
+
;
|
|
4747
|
+
(adjacency ??= Array.from({ length: parsers.length }, () => null))[i] = a;
|
|
4748
|
+
}
|
|
4749
|
+
const hasAdjacency = adjacency !== null;
|
|
4750
|
+
let leading = null;
|
|
4751
|
+
for (let i = 1; i < parsers.length; i++) {
|
|
4752
|
+
if (leadsTrivia(parsers[i])) (leading ??= Array.from({ length: parsers.length }, () => false))[i] = true;
|
|
4753
|
+
}
|
|
4754
|
+
const strictArity = !hasAdjacency && (parsers.length === 2 && !matchesEmpty(parsers[1]) || parsers.length === 3 && parsers.every((p) => !matchesEmpty(p))) ? parsers.length : 0;
|
|
4755
|
+
const meta = {
|
|
4756
|
+
// Union through the nullable prefix — a leading optional()/many() lets a later
|
|
4757
|
+
// term's first char start the sequence. Just `parsers[0]` under-approximates.
|
|
4758
|
+
firstSet: sequenceFirstSet(parsers),
|
|
4759
|
+
canMatchNewline: parsers.some((p) => p._meta.canMatchNewline),
|
|
4760
|
+
isTrivia: false
|
|
4761
|
+
};
|
|
4762
|
+
const def = { tag: "sequence", parsers };
|
|
4763
|
+
const scalarParsers = parsers.map(scalarOf);
|
|
4764
|
+
const parseScalar = (input, pos, ctx) => {
|
|
4765
|
+
let cur = pos;
|
|
4766
|
+
if (strictArity !== 0) {
|
|
4767
|
+
cur = scalarParsers[0](input, cur, ctx);
|
|
4768
|
+
if (cur < 0) return cur;
|
|
4769
|
+
const first = ctx._sv;
|
|
4770
|
+
if (ctx.trivia) cur = advanceTrivia(input, cur, ctx);
|
|
4771
|
+
cur = scalarParsers[1](input, cur, ctx);
|
|
4772
|
+
if (cur < 0) return cur;
|
|
4773
|
+
const second = ctx._sv;
|
|
4774
|
+
if (strictArity === 2) {
|
|
4775
|
+
ctx._sv = def.valueUnused ? void 0 : [first, second];
|
|
4776
|
+
return cur;
|
|
4777
|
+
}
|
|
4778
|
+
if (ctx.trivia) cur = advanceTrivia(input, cur, ctx);
|
|
4779
|
+
cur = scalarParsers[2](input, cur, ctx);
|
|
4780
|
+
if (cur < 0) return cur;
|
|
4781
|
+
ctx._sv = def.valueUnused ? void 0 : [first, second, ctx._sv];
|
|
4782
|
+
return cur;
|
|
4783
|
+
}
|
|
4784
|
+
const values = def.valueUnused ? void 0 : [];
|
|
4785
|
+
for (let i = 0; i < scalarParsers.length; i++) {
|
|
4786
|
+
let termPos = cur;
|
|
4787
|
+
if (i > 0 && ctx.trivia) termPos = advanceTrivia(input, cur, ctx);
|
|
4788
|
+
const end = scalarParsers[i](input, termPos, ctx);
|
|
4789
|
+
if (end < 0) return end;
|
|
4790
|
+
if (values !== void 0) values.push(ctx._sv);
|
|
4791
|
+
if (end > termPos || termPos === cur) cur = end;
|
|
4792
|
+
}
|
|
4793
|
+
ctx._sv = values;
|
|
4794
|
+
return cur;
|
|
4795
|
+
};
|
|
4796
|
+
let followSentinels;
|
|
4797
|
+
return {
|
|
4798
|
+
_tag: "sequence",
|
|
4799
|
+
_meta: meta,
|
|
4800
|
+
_def: def,
|
|
4801
|
+
_parseScalar: hasAdjacency || leading !== null ? void 0 : parseScalar,
|
|
4802
|
+
parse(input, pos, ctx) {
|
|
4803
|
+
const tolerant = ctx._tolerant === true;
|
|
4804
|
+
if (tolerant) {
|
|
4805
|
+
followSentinels ??= parsers.map((_, i) => firstSetSentinel(
|
|
4806
|
+
parsers.slice(i + 1).reduce(
|
|
4807
|
+
(set, parser2) => union(set, firstSetOf(parser2)),
|
|
4808
|
+
{ kind: "empty" }
|
|
4809
|
+
)
|
|
4810
|
+
));
|
|
4811
|
+
}
|
|
4812
|
+
const inheritedSync = ctx._sync;
|
|
4813
|
+
const deferredTrivia = needsDeferredTriviaCommit(ctx);
|
|
4814
|
+
const values = def.valueUnused ? void 0 : [];
|
|
4815
|
+
let cur = pos;
|
|
4816
|
+
try {
|
|
4817
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
4818
|
+
if (tolerant) ctx._sync = followSentinels[i] ?? inheritedSync;
|
|
4819
|
+
const assertion = adjacency?.[i];
|
|
4820
|
+
if (assertion) {
|
|
4821
|
+
if (!holdsAdjacency(input, cur, ctx, assertion)) return adjacencyFail(cur, assertion);
|
|
4822
|
+
if (values !== void 0) values.push(null);
|
|
4823
|
+
continue;
|
|
4824
|
+
}
|
|
4825
|
+
let termPos = cur;
|
|
4826
|
+
const markTlog = deferredTrivia ? cstTlLen(ctx) : 0;
|
|
4827
|
+
const markLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
|
|
4828
|
+
const markRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
4829
|
+
if (ctx.trivia && i > 0) {
|
|
4830
|
+
termPos = deferredTrivia ? commitTriviaScan(scanTriviaCompact(input, cur, ctx)) : advanceTrivia(input, cur, ctx);
|
|
4831
|
+
}
|
|
4832
|
+
const scanTlog = deferredTrivia ? cstTlLen(ctx) : 0;
|
|
4833
|
+
const scanLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
|
|
4834
|
+
const scanRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
4835
|
+
if (leading?.[i] === true) LEAD.at = cur;
|
|
4836
|
+
const result = parsers[i].parse(input, termPos, ctx);
|
|
4837
|
+
if (!result.ok) return result;
|
|
4838
|
+
if (values !== void 0) values.push(result.value);
|
|
4839
|
+
if (result.span.end > termPos || termPos === cur) cur = result.span.end;
|
|
4840
|
+
else if (deferredTrivia) {
|
|
4841
|
+
rollbackScannedTriviaAt(
|
|
4842
|
+
ctx,
|
|
4843
|
+
markTlog,
|
|
4844
|
+
scanTlog,
|
|
4845
|
+
markLog,
|
|
4846
|
+
scanLog,
|
|
4847
|
+
markRootLog,
|
|
4848
|
+
scanRootLog
|
|
4849
|
+
);
|
|
4850
|
+
}
|
|
4851
|
+
}
|
|
4852
|
+
} finally {
|
|
4853
|
+
if (tolerant) ctx._sync = inheritedSync;
|
|
4854
|
+
}
|
|
4855
|
+
return {
|
|
4856
|
+
ok: true,
|
|
4857
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
4858
|
+
value: values ?? void 0,
|
|
4859
|
+
span: { start: pos, end: cur }
|
|
4860
|
+
};
|
|
4861
|
+
}
|
|
4862
|
+
};
|
|
4863
|
+
}
|
|
4864
|
+
|
|
4865
|
+
// src/compiler/degradation.ts
|
|
4866
|
+
function formatDegradation(d) {
|
|
4867
|
+
return `[parseman] degraded [${d.code}] ${d.where}: ${d.subject} \u2014 ${d.fellBackTo}; otherwise ${d.otherwise}`;
|
|
4868
|
+
}
|
|
4869
|
+
var DETAIL_CAP = 8;
|
|
4870
|
+
function formatDegradations(list) {
|
|
4871
|
+
const byCode = /* @__PURE__ */ new Map();
|
|
4872
|
+
for (const d of list) {
|
|
4873
|
+
const bucket = byCode.get(d.code);
|
|
4874
|
+
if (bucket) bucket.push(d);
|
|
4875
|
+
else byCode.set(d.code, [d]);
|
|
4876
|
+
}
|
|
4877
|
+
const out = [];
|
|
4878
|
+
for (const [code, items] of byCode) {
|
|
4879
|
+
for (const d of items.slice(0, DETAIL_CAP)) out.push(formatDegradation(d));
|
|
4880
|
+
if (items.length > DETAIL_CAP) {
|
|
4881
|
+
out.push(
|
|
4882
|
+
`[parseman] degraded [${code}] +${items.length - DETAIL_CAP} more site(s) not listed (${items.length} total). Set PARSEMAN_DEGRADATION=error to fail the build on these.`
|
|
4883
|
+
);
|
|
4884
|
+
}
|
|
4885
|
+
}
|
|
4886
|
+
return out;
|
|
4887
|
+
}
|
|
4888
|
+
var _sinks = [];
|
|
4889
|
+
function beginDegradationCapture() {
|
|
4890
|
+
_sinks.push(/* @__PURE__ */ new Map());
|
|
4891
|
+
}
|
|
4892
|
+
function degradationCaptureDepth() {
|
|
4893
|
+
return _sinks.length;
|
|
4894
|
+
}
|
|
4895
|
+
function unwindDegradationCapture(depth) {
|
|
4896
|
+
const found = [];
|
|
4897
|
+
while (_sinks.length > depth) {
|
|
4898
|
+
const sink = _sinks.pop();
|
|
4899
|
+
found.unshift(...sink.values());
|
|
4900
|
+
}
|
|
4901
|
+
return found;
|
|
4902
|
+
}
|
|
4903
|
+
function resolveDegradationLevel(explicit) {
|
|
4904
|
+
if (explicit !== void 0) return explicit;
|
|
4905
|
+
const env = typeof process !== "undefined" ? process.env?.PARSEMAN_DEGRADATION : void 0;
|
|
4906
|
+
if (env === "off" || env === "warn" || env === "error") return env;
|
|
4907
|
+
return "warn";
|
|
4908
|
+
}
|
|
4909
|
+
function degradationKey(d) {
|
|
4910
|
+
return JSON.stringify([d.code, d.where, d.subject]);
|
|
4911
|
+
}
|
|
4912
|
+
function recordDegradation(d) {
|
|
4913
|
+
const level = resolveDegradationLevel();
|
|
4914
|
+
if (level === "off") return;
|
|
4915
|
+
const key = degradationKey(d);
|
|
4916
|
+
const sink = _sinks[_sinks.length - 1];
|
|
4917
|
+
if (sink) {
|
|
4918
|
+
if (!sink.has(key)) sink.set(key, d);
|
|
4919
|
+
return;
|
|
4920
|
+
}
|
|
4921
|
+
if (_immediate.has(key)) return;
|
|
4922
|
+
_immediate.add(key);
|
|
4923
|
+
if (level === "error") throw new Error(`parseman: degraded compilation path
|
|
4924
|
+
${formatDegradation(d)}`);
|
|
4925
|
+
console.warn(formatDegradation(d));
|
|
4926
|
+
}
|
|
4927
|
+
var _immediate = /* @__PURE__ */ new Set();
|
|
4928
|
+
function beginCompileDegradationDrain() {
|
|
4929
|
+
if (resolveDegradationLevel() === "off" || _sinks.length > 0) return () => {
|
|
4930
|
+
};
|
|
4931
|
+
const depth = degradationCaptureDepth();
|
|
4932
|
+
beginDegradationCapture();
|
|
4933
|
+
return (report) => {
|
|
4934
|
+
const found = unwindDegradationCapture(depth);
|
|
4935
|
+
if (!report || found.length === 0) return;
|
|
4936
|
+
const fresh = found.filter((d) => {
|
|
4937
|
+
const k = degradationKey(d);
|
|
4938
|
+
if (_immediate.has(k)) return false;
|
|
4939
|
+
_immediate.add(k);
|
|
4940
|
+
return true;
|
|
4941
|
+
});
|
|
4942
|
+
if (fresh.length === 0) return;
|
|
4943
|
+
const lines2 = formatDegradations(fresh);
|
|
4944
|
+
if (resolveDegradationLevel() === "error") {
|
|
4945
|
+
throw new Error(`parseman: ${fresh.length} degraded compilation path(s)
|
|
4946
|
+
${lines2.join("\n")}`);
|
|
4947
|
+
}
|
|
4948
|
+
for (const l of lines2) console.warn(l);
|
|
4949
|
+
};
|
|
4950
|
+
}
|
|
4951
|
+
|
|
4952
|
+
// src/compiler/build-arity.ts
|
|
4953
|
+
function cstOutputHost(build) {
|
|
4954
|
+
return build?._parsemanCstOutput === true;
|
|
4955
|
+
}
|
|
4956
|
+
var SINGLE_IDENT_ARROW_RE = /^[A-Za-z_$][\w$]*\s*=>/;
|
|
4957
|
+
var PARAM_LIST_OPEN_RE = /^(?:function\b[^(]*)?\(/;
|
|
4958
|
+
var NATIVE_CODE_RE = /\{\s*\[native code\]\s*\}/;
|
|
4959
|
+
var PARAM_HEAD_RE = /^[A-Za-z_$][\w$]*\s*\??\s*/;
|
|
4960
|
+
function confirmedBuildArity(src) {
|
|
4961
|
+
const s = src.trim();
|
|
4962
|
+
if (NATIVE_CODE_RE.test(s)) return null;
|
|
4963
|
+
if (/\barguments\b/.test(s)) return null;
|
|
4964
|
+
if (SINGLE_IDENT_ARROW_RE.test(s)) return 1;
|
|
4965
|
+
const inner = paramListText(s);
|
|
4966
|
+
if (inner === null) return null;
|
|
4967
|
+
if (inner.trim() === "") return 0;
|
|
4968
|
+
const parts = splitTopLevel(inner);
|
|
4969
|
+
if (parts === null) return null;
|
|
4970
|
+
for (const part of parts) {
|
|
4971
|
+
if (!isConfirmableParam(part.trim())) return null;
|
|
4972
|
+
}
|
|
4973
|
+
return parts.length;
|
|
4974
|
+
}
|
|
4975
|
+
function paramListText(s) {
|
|
4976
|
+
const open = PARAM_LIST_OPEN_RE.exec(s);
|
|
4977
|
+
if (!open) return null;
|
|
4978
|
+
const start = open[0].length;
|
|
4979
|
+
const end = matchingParen(s, start);
|
|
4980
|
+
if (end === null) return null;
|
|
4981
|
+
if (!s.startsWith("function") && !/^\s*=>/.test(s.slice(end + 1))) return null;
|
|
4982
|
+
return s.slice(start, end);
|
|
4983
|
+
}
|
|
4984
|
+
function matchingParen(s, start) {
|
|
4985
|
+
let depth = 0;
|
|
4986
|
+
for (let i = start; i < s.length; i++) {
|
|
4987
|
+
const c = s[i];
|
|
4988
|
+
if (c === '"' || c === "'" || c === "`") {
|
|
4989
|
+
const close = skipString(s, i);
|
|
4990
|
+
if (close === null) return null;
|
|
4991
|
+
i = close;
|
|
4992
|
+
continue;
|
|
4993
|
+
}
|
|
4994
|
+
if (c === "(" || c === "[" || c === "{") depth++;
|
|
4995
|
+
else if (c === "]" || c === "}") {
|
|
4996
|
+
if (--depth < 0) return null;
|
|
4997
|
+
} else if (c === ")") {
|
|
4998
|
+
if (depth === 0) return i;
|
|
4999
|
+
depth--;
|
|
5000
|
+
}
|
|
5001
|
+
}
|
|
5002
|
+
return null;
|
|
5003
|
+
}
|
|
5004
|
+
function skipString(s, open) {
|
|
5005
|
+
const quote = s[open];
|
|
5006
|
+
for (let i = open + 1; i < s.length; i++) {
|
|
5007
|
+
if (s[i] === "\\") {
|
|
5008
|
+
i++;
|
|
5009
|
+
continue;
|
|
5010
|
+
}
|
|
5011
|
+
if (s[i] === quote) return i;
|
|
5012
|
+
}
|
|
5013
|
+
return null;
|
|
5014
|
+
}
|
|
5015
|
+
function splitTopLevel(inner) {
|
|
5016
|
+
const parts = [];
|
|
5017
|
+
let depth = 0;
|
|
5018
|
+
let angle = 0;
|
|
5019
|
+
let last = 0;
|
|
5020
|
+
for (let i = 0; i < inner.length; i++) {
|
|
5021
|
+
const c = inner[i];
|
|
5022
|
+
if (c === "=" && inner[i + 1] === ">") {
|
|
5023
|
+
i++;
|
|
5024
|
+
continue;
|
|
5025
|
+
}
|
|
5026
|
+
if (c === '"' || c === "'" || c === "`") {
|
|
5027
|
+
const close = skipString(inner, i);
|
|
5028
|
+
if (close === null) return null;
|
|
5029
|
+
i = close;
|
|
5030
|
+
continue;
|
|
5031
|
+
}
|
|
5032
|
+
if (c === "(" || c === "[" || c === "{") depth++;
|
|
5033
|
+
else if (c === ")" || c === "]" || c === "}") {
|
|
5034
|
+
if (--depth < 0) return null;
|
|
5035
|
+
} else if (c === "<") angle++;
|
|
5036
|
+
else if (c === ">") {
|
|
5037
|
+
if (--angle < 0) return null;
|
|
5038
|
+
} else if (c === "," && depth === 0 && angle === 0) {
|
|
5039
|
+
parts.push(inner.slice(last, i));
|
|
5040
|
+
last = i + 1;
|
|
5041
|
+
}
|
|
5042
|
+
}
|
|
5043
|
+
if (depth !== 0 || angle !== 0) return null;
|
|
5044
|
+
parts.push(inner.slice(last));
|
|
5045
|
+
return parts;
|
|
5046
|
+
}
|
|
5047
|
+
function isConfirmableParam(part) {
|
|
5048
|
+
const head = PARAM_HEAD_RE.exec(part);
|
|
5049
|
+
if (!head) return false;
|
|
5050
|
+
const rest = part.slice(head[0].length);
|
|
5051
|
+
if (rest === "") return true;
|
|
5052
|
+
if (rest[0] !== ":") return false;
|
|
5053
|
+
return !hasDefaultAssign(rest.slice(1));
|
|
5054
|
+
}
|
|
5055
|
+
function hasDefaultAssign(annotation) {
|
|
5056
|
+
for (let i = 0; i < annotation.length; i++) {
|
|
5057
|
+
if (annotation[i] !== "=") continue;
|
|
5058
|
+
if (annotation[i + 1] === ">" || annotation[i + 1] === "=") {
|
|
5059
|
+
i++;
|
|
5060
|
+
continue;
|
|
5061
|
+
}
|
|
5062
|
+
const prev = annotation[i - 1];
|
|
5063
|
+
if (prev === "<" || prev === ">" || prev === "!" || prev === "=") continue;
|
|
5064
|
+
return true;
|
|
5065
|
+
}
|
|
5066
|
+
return false;
|
|
5067
|
+
}
|
|
5068
|
+
function buildAnalysisSrc(def) {
|
|
5069
|
+
return def.buildSigSrc ?? def.buildSrc ?? def.build.toString();
|
|
5070
|
+
}
|
|
5071
|
+
var RESOLVER_REASONS = {
|
|
5072
|
+
"rest-parameter": "its parameter list uses a rest parameter, so the declared arity is unbounded",
|
|
5073
|
+
"arguments": "its body references `arguments`",
|
|
5074
|
+
"reassigned": "the binding it names is reassigned, so the function read here is not decidable",
|
|
5075
|
+
"not-a-function": "the binding it names is not a function declaration",
|
|
5076
|
+
"unresolved-import": "its module could not be resolved or parsed",
|
|
5077
|
+
"not-found": "the name did not resolve to any binding",
|
|
5078
|
+
"computed": "it is a computed expression",
|
|
5079
|
+
"foreign-source": "it is named in a module the resolver was never told about, so its offsets index no scope tree the resolver holds",
|
|
5080
|
+
"ambiguous-source": "two distinct registered modules hold byte-identical text, so that text no longer names the module its offsets index"
|
|
5081
|
+
};
|
|
5082
|
+
function unconfirmableReason(def, src) {
|
|
5083
|
+
const declared = def.buildArityUnresolved;
|
|
5084
|
+
if (declared !== void 0 && RESOLVER_REASONS[declared]) return RESOLVER_REASONS[declared];
|
|
5085
|
+
const s = src.trim();
|
|
5086
|
+
const params = s.slice(0, s.indexOf(")") + 1);
|
|
5087
|
+
if (params.includes("...")) return RESOLVER_REASONS["rest-parameter"];
|
|
5088
|
+
if (/\barguments\b/.test(s)) return RESOLVER_REASONS["arguments"];
|
|
5089
|
+
if (/^[A-Za-z_$][\w$]*(\s*\.\s*[A-Za-z_$][\w$]*)?$/.test(s)) {
|
|
5090
|
+
return "it names a binding this build could not resolve to a function declaration";
|
|
5091
|
+
}
|
|
5092
|
+
return "its parameter list could not be parsed";
|
|
5093
|
+
}
|
|
5094
|
+
function confirmedArityForDef(def) {
|
|
5095
|
+
if (def.buildArity !== void 0) return def.buildArity;
|
|
5096
|
+
const src = buildAnalysisSrc(def);
|
|
5097
|
+
const arity = confirmedBuildArity(src);
|
|
5098
|
+
if (arity !== null) return arity;
|
|
5099
|
+
const subject = `build reducer \`${(def.buildSrc ?? "<runtime fn>").trim().split("\n")[0].slice(0, 60)}\``;
|
|
5100
|
+
recordDegradation({
|
|
5101
|
+
code: "build-arity-unconfirmed",
|
|
5102
|
+
severity: "warn",
|
|
5103
|
+
where: `node("${def.type ?? "<inferred>"}")`,
|
|
5104
|
+
subject,
|
|
5105
|
+
fellBackTo: `could not confirm its declared arity \u2014 ${unconfirmableReason(def, src)} \u2014 so this node captures children, fields and raw children, logs trivia, and hands it \`_ctx.state\` on every match`,
|
|
5106
|
+
otherwise: "only the tiers the reducer actually declares would be captured (arity >= 1 children, >= 2 fields, >= 4 raw, >= 5 trivia, >= 6 state). Declare it with `node(..., { buildArity: n })` if it cannot be derived"
|
|
5107
|
+
});
|
|
5108
|
+
return null;
|
|
5109
|
+
}
|
|
5110
|
+
function buildReadsRaw(def) {
|
|
5111
|
+
if (!def.build) return true;
|
|
5112
|
+
if (def.buildRawUnused === true) return false;
|
|
5113
|
+
const arity = confirmedArityForDef(def);
|
|
5114
|
+
if (arity === null) return true;
|
|
5115
|
+
return arity >= 4;
|
|
5116
|
+
}
|
|
5117
|
+
function buildReadsTrivia(def) {
|
|
5118
|
+
if (!def.build) return true;
|
|
5119
|
+
const arity = confirmedArityForDef(def);
|
|
5120
|
+
if (arity === null) return true;
|
|
5121
|
+
return arity >= 5;
|
|
5122
|
+
}
|
|
5123
|
+
function buildReadsState(def) {
|
|
5124
|
+
if (!def.build) return true;
|
|
5125
|
+
const arity = confirmedArityForDef(def);
|
|
5126
|
+
if (arity === null) return true;
|
|
5127
|
+
return arity >= 6;
|
|
5128
|
+
}
|
|
5129
|
+
|
|
5130
|
+
// src/combinators/token.ts
|
|
5131
|
+
function semanticLeafValue(_ctx, _input, _start, _end, value) {
|
|
5132
|
+
return value;
|
|
5133
|
+
}
|
|
5134
|
+
function sourceLeafValue(ctx, input, start, end, value) {
|
|
5135
|
+
return cstOutputHost(ctx.build) ? input.slice(start, end) : value;
|
|
5136
|
+
}
|
|
5137
|
+
function token(root) {
|
|
5138
|
+
const meta = {
|
|
5139
|
+
firstSet: root._meta.firstSet,
|
|
5140
|
+
canMatchNewline: root._meta.canMatchNewline,
|
|
5141
|
+
isTrivia: false
|
|
5142
|
+
};
|
|
5143
|
+
return {
|
|
5144
|
+
_tag: "token",
|
|
5145
|
+
_meta: meta,
|
|
5146
|
+
_def: { tag: "token", parser: root },
|
|
5147
|
+
parse(input, pos, ctx) {
|
|
5148
|
+
const savedTrivia = ctx.trivia;
|
|
5149
|
+
const savedKinds = ctx.triviaKindLabels;
|
|
5150
|
+
const savedBuf = ctx._cstBuf;
|
|
5151
|
+
const savedChildren = ctx._cstChildren;
|
|
5152
|
+
const savedLeaves = ctx._cstLeaves;
|
|
5153
|
+
const savedRaw = ctx._cstRawChildren;
|
|
5154
|
+
const savedTriviaLog = ctx._cstTriviaLog;
|
|
5155
|
+
const savedOuterTriviaLog = ctx._triviaLog;
|
|
5156
|
+
const savedRootTriviaLog = ctx._rootTriviaLog;
|
|
5157
|
+
const wasCapturing = cstCaptureActive(ctx);
|
|
5158
|
+
ctx.trivia = void 0;
|
|
5159
|
+
ctx.triviaKindLabels = void 0;
|
|
5160
|
+
ctx._cstBuf = void 0;
|
|
5161
|
+
ctx._cstChildren = void 0;
|
|
5162
|
+
ctx._cstLeaves = void 0;
|
|
5163
|
+
ctx._cstRawChildren = void 0;
|
|
5164
|
+
ctx._cstTriviaLog = void 0;
|
|
5165
|
+
ctx._triviaLog = void 0;
|
|
5166
|
+
ctx._rootTriviaLog = void 0;
|
|
5167
|
+
let result;
|
|
5168
|
+
try {
|
|
5169
|
+
result = root.parse(input, pos, ctx);
|
|
5170
|
+
} finally {
|
|
5171
|
+
ctx.trivia = savedTrivia;
|
|
5172
|
+
ctx.triviaKindLabels = savedKinds;
|
|
5173
|
+
ctx._cstBuf = savedBuf;
|
|
5174
|
+
ctx._cstChildren = savedChildren;
|
|
5175
|
+
ctx._cstLeaves = savedLeaves;
|
|
5176
|
+
ctx._cstRawChildren = savedRaw;
|
|
5177
|
+
ctx._cstTriviaLog = savedTriviaLog;
|
|
5178
|
+
ctx._triviaLog = savedOuterTriviaLog;
|
|
5179
|
+
ctx._rootTriviaLog = savedRootTriviaLog;
|
|
5180
|
+
}
|
|
5181
|
+
if (!result.ok) return result;
|
|
5182
|
+
const span = result.span;
|
|
5183
|
+
const value = input.slice(pos, span.end);
|
|
5184
|
+
if (wasCapturing) pushCstLeaf(ctx, { _tag: "leaf", value, span });
|
|
5185
|
+
return { ok: true, value, span };
|
|
5186
|
+
}
|
|
5187
|
+
};
|
|
5188
|
+
}
|
|
5189
|
+
function makeLeaf(root, fn, sourceCstValue) {
|
|
5190
|
+
const cstValue = sourceCstValue ? sourceLeafValue : semanticLeafValue;
|
|
5191
|
+
const meta = {
|
|
5192
|
+
firstSet: root._meta.firstSet,
|
|
5193
|
+
canMatchNewline: root._meta.canMatchNewline,
|
|
5194
|
+
isTrivia: false
|
|
5195
|
+
};
|
|
5196
|
+
return {
|
|
5197
|
+
_tag: "leaf",
|
|
5198
|
+
_meta: meta,
|
|
5199
|
+
_def: {
|
|
5200
|
+
tag: "leaf",
|
|
5201
|
+
parser: root,
|
|
5202
|
+
fn,
|
|
5203
|
+
...sourceCstValue ? { cstValue: "source" } : {}
|
|
5204
|
+
},
|
|
5205
|
+
parse(input, pos, ctx) {
|
|
5206
|
+
const savedBuf = ctx._cstBuf;
|
|
5207
|
+
const savedChildren = ctx._cstChildren;
|
|
5208
|
+
const savedLeaves = ctx._cstLeaves;
|
|
5209
|
+
const savedRaw = ctx._cstRawChildren;
|
|
5210
|
+
const savedTriviaLog = ctx._cstTriviaLog;
|
|
5211
|
+
const savedOuterTriviaLog = ctx._triviaLog;
|
|
5212
|
+
const wasCapturing = cstCaptureActive(ctx);
|
|
5213
|
+
ctx._cstBuf = void 0;
|
|
5214
|
+
ctx._cstChildren = void 0;
|
|
5215
|
+
ctx._cstLeaves = void 0;
|
|
5216
|
+
ctx._cstRawChildren = void 0;
|
|
5217
|
+
ctx._cstTriviaLog = void 0;
|
|
5218
|
+
ctx._triviaLog = void 0;
|
|
5219
|
+
let result;
|
|
5220
|
+
try {
|
|
5221
|
+
result = root.parse(input, pos, ctx);
|
|
5222
|
+
} finally {
|
|
5223
|
+
ctx._cstBuf = savedBuf;
|
|
5224
|
+
ctx._cstChildren = savedChildren;
|
|
5225
|
+
ctx._cstLeaves = savedLeaves;
|
|
5226
|
+
ctx._cstRawChildren = savedRaw;
|
|
5227
|
+
ctx._cstTriviaLog = savedTriviaLog;
|
|
5228
|
+
ctx._triviaLog = savedOuterTriviaLog;
|
|
5229
|
+
}
|
|
5230
|
+
if (!result.ok) return result;
|
|
5231
|
+
const value = fn(result.value, result.span);
|
|
5232
|
+
if (wasCapturing) pushCstLeaf(ctx, {
|
|
5233
|
+
_tag: "leaf",
|
|
5234
|
+
value: cstValue(ctx, input, pos, result.span.end, value),
|
|
5235
|
+
span: result.span
|
|
5236
|
+
});
|
|
5237
|
+
return { ok: true, value, span: result.span };
|
|
5238
|
+
}
|
|
5239
|
+
};
|
|
5240
|
+
}
|
|
5241
|
+
function leaf(root, fn) {
|
|
5242
|
+
return makeLeaf(root, fn, false);
|
|
5243
|
+
}
|
|
5244
|
+
function sourceLeaf(root, fn) {
|
|
5245
|
+
return makeLeaf(root, fn, true);
|
|
5246
|
+
}
|
|
5247
|
+
|
|
5248
|
+
// src/combinators/attempt.ts
|
|
5249
|
+
function containOption(options) {
|
|
5250
|
+
if (options === void 0) return false;
|
|
5251
|
+
for (const key of Object.keys(options)) {
|
|
5252
|
+
if (key !== "contain") throw new TypeError(`attempt(): unknown option ${JSON.stringify(key)}`);
|
|
5253
|
+
}
|
|
5254
|
+
if (options.contain !== void 0 && typeof options.contain !== "boolean") {
|
|
5255
|
+
throw new TypeError("attempt(): `contain` must be a boolean");
|
|
5256
|
+
}
|
|
5257
|
+
return options.contain === true;
|
|
5258
|
+
}
|
|
5259
|
+
function attempt(parser2, options) {
|
|
5260
|
+
const contain = containOption(options);
|
|
5261
|
+
const guardable = parser2._meta.firstSet.kind !== "any" && !matchesEmpty(parser2);
|
|
5262
|
+
let failExpected;
|
|
5263
|
+
return {
|
|
5264
|
+
_tag: "attempt",
|
|
5265
|
+
_meta: parser2._meta,
|
|
5266
|
+
_def: contain ? { tag: "attempt", parser: parser2, contain: true } : { tag: "attempt", parser: parser2 },
|
|
5267
|
+
parse(input, pos, ctx) {
|
|
5268
|
+
if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(parser2, input, pos)) {
|
|
5269
|
+
if (failExpected === void 0) {
|
|
5270
|
+
const e = deriveExpected(parser2);
|
|
5271
|
+
failExpected = e.length > 0 ? e : [parser2._tag];
|
|
5272
|
+
}
|
|
5273
|
+
return { ok: false, expected: failExpected, span: { start: pos, end: pos } };
|
|
5274
|
+
}
|
|
5275
|
+
const mark = saveCstMark(ctx);
|
|
5276
|
+
const log = ctx._triviaLog?.length;
|
|
5277
|
+
const rootLog = ctx._rootTriviaLog?.length;
|
|
5278
|
+
const split = ctx._columnsSplit;
|
|
5279
|
+
const result = parser2.parse(input, pos, ctx);
|
|
5280
|
+
if (result.ok) return result;
|
|
5281
|
+
rollbackCstCapture(ctx, mark);
|
|
5282
|
+
ctx._columnsSplit = split;
|
|
5283
|
+
if (log !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== log) ctx._triviaLog.length = log;
|
|
5284
|
+
if (rootLog !== void 0 && ctx._rootTriviaLog && ctx._rootTriviaLog.length !== rootLog) ctx._rootTriviaLog.length = rootLog;
|
|
5285
|
+
if (result.committed && !contain) return result;
|
|
5286
|
+
return { ok: false, expected: result.expected, span: { start: pos, end: pos } };
|
|
5287
|
+
}
|
|
5288
|
+
};
|
|
5289
|
+
}
|
|
5290
|
+
|
|
5291
|
+
// src/analysis/gating.ts
|
|
5292
|
+
var choiceArms = (c) => c.arms;
|
|
5293
|
+
function childrenOf(d) {
|
|
5294
|
+
switch (d.tag) {
|
|
5295
|
+
case "sequence":
|
|
5296
|
+
case "choice":
|
|
5297
|
+
return d.parsers;
|
|
5298
|
+
case "dispatch":
|
|
5299
|
+
return [
|
|
5300
|
+
d.selector,
|
|
5301
|
+
...d.cases.map((c) => c.parser),
|
|
5302
|
+
...d.matchers ? d.matchers.map((c) => c.parser) : [],
|
|
5303
|
+
...d.otherwise === void 0 ? [] : [d.otherwise]
|
|
5304
|
+
];
|
|
5305
|
+
case "sepBy":
|
|
5306
|
+
return [d.parser, d.separator];
|
|
5307
|
+
case "recover":
|
|
5308
|
+
return [d.parser, d.sentinel];
|
|
5309
|
+
case "scanTo":
|
|
5310
|
+
return [
|
|
5311
|
+
d.sentinel,
|
|
5312
|
+
...d.skip,
|
|
5313
|
+
...d.recoverAt === void 0 ? [] : [d.recoverAt],
|
|
5314
|
+
...d.stopAt === void 0 ? [] : [d.stopAt]
|
|
5315
|
+
];
|
|
5316
|
+
case "grammar":
|
|
5317
|
+
return d.triviaParser ? [d.parser, d.triviaParser] : [d.parser];
|
|
5318
|
+
case "routed":
|
|
5319
|
+
return d.fallback ? [d.fallback] : [];
|
|
5320
|
+
case "lines":
|
|
5321
|
+
return [d.prefix, d.body, ...d.first === void 0 ? [] : [d.first], ...d.lazy === void 0 ? [] : [d.lazy]];
|
|
5322
|
+
case "columns":
|
|
5323
|
+
return [];
|
|
5324
|
+
// A `lazy` is a REFERENCE, not a subtree. Descending through it would make
|
|
5325
|
+
// every rule's walk cover the whole reachable grammar — site paths become
|
|
5326
|
+
// nonsense, and a structural hash includes half the grammar. Treated as a
|
|
5327
|
+
// leaf, keyed by the rule name it refers to, which is also the right
|
|
5328
|
+
// semantics: two productions referencing `g.Ident` really do fill that slot
|
|
5329
|
+
// the same way.
|
|
5330
|
+
case "lazy":
|
|
5331
|
+
case "literal":
|
|
5332
|
+
case "regex":
|
|
5333
|
+
case "keywords":
|
|
5334
|
+
case "guard":
|
|
5335
|
+
case "adjacency":
|
|
5336
|
+
case "unknown":
|
|
5337
|
+
return [];
|
|
5338
|
+
default: {
|
|
5339
|
+
const rec = d;
|
|
5340
|
+
return rec.parser ? [rec.parser] : [];
|
|
5341
|
+
}
|
|
5342
|
+
}
|
|
5343
|
+
}
|
|
5344
|
+
var isAny = (fs) => fs.kind === "any";
|
|
5345
|
+
function intersection(a, b) {
|
|
5346
|
+
if (a.kind === "any") return b;
|
|
5347
|
+
if (b.kind === "any") return a;
|
|
5348
|
+
if (a.kind === "empty" || b.kind === "empty") return { kind: "empty" };
|
|
5349
|
+
const ranges = [];
|
|
5350
|
+
for (const ra of a.ranges) for (const rb of b.ranges) {
|
|
5351
|
+
const lo = Math.max(ra.lo, rb.lo);
|
|
5352
|
+
const hi = Math.min(ra.hi, rb.hi);
|
|
5353
|
+
if (lo <= hi) ranges.push({ lo, hi });
|
|
5354
|
+
}
|
|
5355
|
+
return ranges.length === 0 ? { kind: "empty" } : { kind: "ranges", ranges };
|
|
5356
|
+
}
|
|
5357
|
+
function combine(sets) {
|
|
5358
|
+
let acc = { kind: "empty" };
|
|
5359
|
+
for (const s of sets) {
|
|
5360
|
+
if (s.kind === "any") return { kind: "any" };
|
|
5361
|
+
if (s.kind === "empty") continue;
|
|
5362
|
+
acc = acc.kind === "ranges" ? { kind: "ranges", ranges: [...acc.ranges, ...s.ranges] } : s;
|
|
5363
|
+
}
|
|
5364
|
+
return acc;
|
|
5365
|
+
}
|
|
5366
|
+
var ch = (c) => c >= 32 && c < 127 ? `'${String.fromCharCode(c)}'` : `\\u${c}`;
|
|
5367
|
+
function firstSetToString(fs) {
|
|
5368
|
+
if (fs.kind === "any") return "ANY";
|
|
5369
|
+
if (fs.kind === "empty") return "(empty)";
|
|
5370
|
+
return fs.ranges.map((r) => r.lo === r.hi ? ch(r.lo) : `${ch(r.lo)}-${ch(r.hi)}`).join(",");
|
|
5371
|
+
}
|
|
5372
|
+
var ruleNameOf = (p) => p._ruleName;
|
|
5373
|
+
var KEYWORD_REGEX_RE = /^\^?[@#.-]?[A-Za-z][\w-]*(\(\?![^)]*\))?\$?$/;
|
|
5374
|
+
var SUGGESTIONS = {
|
|
5375
|
+
"broad-recognizer": "This arm can begin with any character, so no single-character test can rule it out. The parser has to enter it \u2014 set up, try, and undo \u2014 at every position it reaches, instead of skipping it for free.\nTo fix: make the arm begin with a fixed character, word or keyword. If it is meant to be a catch-all that matches anything, leave it and add the choice to the accept list at the end.",
|
|
5376
|
+
"leading-not": "This arm begins with a not(...) check, which matches nothing and so says nothing about which character the arm starts with. The parser then cannot rule the arm out and enters it everywhere.\nTo fix: put the term that actually consumes text first and keep not(...) after it as a trailing boundary. If you need to REQUIRE something ahead without consuming it, use peek(X) \u2014 it checks the same thing but still tells parseman that the arm starts with X.",
|
|
5377
|
+
"nullable-prefix": "This arm begins with something optional \u2014 an optional(...) or a repeat that allows zero items \u2014 so the arm can also start with whatever comes AFTER it, and that is broad enough that no character rules the arm out.\nTo fix: give the optional part its own arm so each arm has a definite beginning, or require at least one item. A plain sepBy(item, sep) also matches nothing at all; pass { min: 1 } when the list must not be empty.",
|
|
5378
|
+
"cross-artifact-ref": "This arm hands off to another rule, and that rule has the same problem \u2014 it can begin with any character \u2014 so the cost is inherited rather than caused here.\nTo fix: run this check on the rule it refers to and fix it there. One rule given a definite beginning fixes every choice that uses it.",
|
|
5379
|
+
"opaque-wrapper": "This arm begins with a wrapper that only inspects parser state (a gate/withCtx/recover) and consumes no text, so it says nothing about which character the arm starts with.\nTo fix: put a term that actually matches text in front of the wrapper.",
|
|
5380
|
+
"ref-cycle": "This arm refers back to itself through a cycle of rules, and parseman could not work out a definite first character for any of them.\nTo fix: make sure the base case of the recursion begins with a fixed character or keyword, so the cycle has somewhere definite to start."
|
|
5381
|
+
};
|
|
5382
|
+
function refineSuggestion(cause, arm) {
|
|
5383
|
+
if (cause !== "broad-recognizer") return SUGGESTIONS[cause];
|
|
5384
|
+
const lead2 = peelToLeading(arm);
|
|
5385
|
+
const d = lead2._def;
|
|
5386
|
+
if (d.tag === "regex" && KEYWORD_REGEX_RE.test(d.source)) {
|
|
5387
|
+
return `This arm matches the fixed word \`${d.source}\` with a regular expression, and parseman cannot always tell from a regular expression which character it starts with.
|
|
5388
|
+
To fix: write it as word('\u2026') or keywords([\u2026]) instead. They match exactly the same text and compile to the same character scan, but they also tell parseman the first character, which is what lets the parser skip this arm when it cannot match.`;
|
|
5389
|
+
}
|
|
5390
|
+
if (d.tag === "scanTo") {
|
|
5391
|
+
return "This arm ends in a scanTo(...) catch-all, which reads forward until it finds something and so can begin at any character. The parser can never rule it out. That is usually exactly what you want from a fallback.\nTo fix: usually nothing. Add this choice to the accept list at the end so the check keeps flagging the choices that are real problems.";
|
|
5392
|
+
}
|
|
5393
|
+
return SUGGESTIONS[cause];
|
|
5394
|
+
}
|
|
5395
|
+
function classifyBroadArm(arm, resolve) {
|
|
5396
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5397
|
+
const relabel = (inner, cause, detail) => ({ cause, detail, ...inner?.unresolvedExternal ? { unresolvedExternal: true } : {} });
|
|
5398
|
+
const walk = (p) => {
|
|
5399
|
+
if (seen.has(p)) return { cause: "ref-cycle", detail: "ref cycle" };
|
|
5400
|
+
seen.add(p);
|
|
5401
|
+
const d = p._def;
|
|
4525
5402
|
switch (d.tag) {
|
|
4526
5403
|
case "literal":
|
|
4527
5404
|
case "regex":
|
|
@@ -5148,323 +6025,163 @@ function commitFailureSuccessors(p, resolve) {
|
|
|
5148
6025
|
return [d.thunk()];
|
|
5149
6026
|
} catch {
|
|
5150
6027
|
const name = p._ruleName;
|
|
5151
|
-
const target = name === void 0 ? void 0 : resolve?.(name);
|
|
5152
|
-
return target === void 0 ? true : [target];
|
|
5153
|
-
}
|
|
5154
|
-
}
|
|
5155
|
-
default:
|
|
5156
|
-
return NO_EDGES;
|
|
5157
|
-
}
|
|
5158
|
-
}
|
|
5159
|
-
function reachesMarked(root, successors, memo) {
|
|
5160
|
-
const known = memo.get(root);
|
|
5161
|
-
if (known !== void 0) return known;
|
|
5162
|
-
const order = /* @__PURE__ */ new Map();
|
|
5163
|
-
const low = [];
|
|
5164
|
-
const found = [];
|
|
5165
|
-
const stack = [];
|
|
5166
|
-
const visit = (node2) => {
|
|
5167
|
-
const at = low.length;
|
|
5168
|
-
order.set(node2, at);
|
|
5169
|
-
low.push(at);
|
|
5170
|
-
found.push(false);
|
|
5171
|
-
stack.push(node2);
|
|
5172
|
-
const next = successors(node2);
|
|
5173
|
-
if (next === true) found[at] = true;
|
|
5174
|
-
else {
|
|
5175
|
-
for (const child of next) {
|
|
5176
|
-
if (found[at]) break;
|
|
5177
|
-
const hit = memo.get(child);
|
|
5178
|
-
if (hit !== void 0) {
|
|
5179
|
-
if (hit) found[at] = true;
|
|
5180
|
-
continue;
|
|
5181
|
-
}
|
|
5182
|
-
const seen = order.get(child);
|
|
5183
|
-
if (seen !== void 0) {
|
|
5184
|
-
if (seen < low[at]) low[at] = seen;
|
|
5185
|
-
continue;
|
|
5186
|
-
}
|
|
5187
|
-
const k = visit(child);
|
|
5188
|
-
if (low[k] < low[at]) low[at] = low[k];
|
|
5189
|
-
if (found[k]) found[at] = true;
|
|
5190
|
-
}
|
|
5191
|
-
}
|
|
5192
|
-
if (low[at] === at) {
|
|
5193
|
-
const answer = found[at];
|
|
5194
|
-
let member;
|
|
5195
|
-
do {
|
|
5196
|
-
member = stack.pop();
|
|
5197
|
-
memo.set(member, answer);
|
|
5198
|
-
} while (member !== node2);
|
|
5199
|
-
}
|
|
5200
|
-
return at;
|
|
5201
|
-
};
|
|
5202
|
-
return found[visit(root)];
|
|
5203
|
-
}
|
|
5204
|
-
|
|
5205
|
-
// src/compiler/degradation.ts
|
|
5206
|
-
function formatDegradation(d) {
|
|
5207
|
-
return `[parseman] degraded [${d.code}] ${d.where}: ${d.subject} \u2014 ${d.fellBackTo}; otherwise ${d.otherwise}`;
|
|
5208
|
-
}
|
|
5209
|
-
var DETAIL_CAP = 8;
|
|
5210
|
-
function formatDegradations(list) {
|
|
5211
|
-
const byCode = /* @__PURE__ */ new Map();
|
|
5212
|
-
for (const d of list) {
|
|
5213
|
-
const bucket = byCode.get(d.code);
|
|
5214
|
-
if (bucket) bucket.push(d);
|
|
5215
|
-
else byCode.set(d.code, [d]);
|
|
5216
|
-
}
|
|
5217
|
-
const out = [];
|
|
5218
|
-
for (const [code, items] of byCode) {
|
|
5219
|
-
for (const d of items.slice(0, DETAIL_CAP)) out.push(formatDegradation(d));
|
|
5220
|
-
if (items.length > DETAIL_CAP) {
|
|
5221
|
-
out.push(
|
|
5222
|
-
`[parseman] degraded [${code}] +${items.length - DETAIL_CAP} more site(s) not listed (${items.length} total). Set PARSEMAN_DEGRADATION=error to fail the build on these.`
|
|
5223
|
-
);
|
|
5224
|
-
}
|
|
5225
|
-
}
|
|
5226
|
-
return out;
|
|
5227
|
-
}
|
|
5228
|
-
var _sinks = [];
|
|
5229
|
-
function beginDegradationCapture() {
|
|
5230
|
-
_sinks.push(/* @__PURE__ */ new Map());
|
|
5231
|
-
}
|
|
5232
|
-
function degradationCaptureDepth() {
|
|
5233
|
-
return _sinks.length;
|
|
5234
|
-
}
|
|
5235
|
-
function unwindDegradationCapture(depth) {
|
|
5236
|
-
const found = [];
|
|
5237
|
-
while (_sinks.length > depth) {
|
|
5238
|
-
const sink = _sinks.pop();
|
|
5239
|
-
found.unshift(...sink.values());
|
|
5240
|
-
}
|
|
5241
|
-
return found;
|
|
5242
|
-
}
|
|
5243
|
-
function resolveDegradationLevel(explicit) {
|
|
5244
|
-
if (explicit !== void 0) return explicit;
|
|
5245
|
-
const env = typeof process !== "undefined" ? process.env?.PARSEMAN_DEGRADATION : void 0;
|
|
5246
|
-
if (env === "off" || env === "warn" || env === "error") return env;
|
|
5247
|
-
return "warn";
|
|
5248
|
-
}
|
|
5249
|
-
function degradationKey(d) {
|
|
5250
|
-
return JSON.stringify([d.code, d.where, d.subject]);
|
|
5251
|
-
}
|
|
5252
|
-
function recordDegradation(d) {
|
|
5253
|
-
const level = resolveDegradationLevel();
|
|
5254
|
-
if (level === "off") return;
|
|
5255
|
-
const key = degradationKey(d);
|
|
5256
|
-
const sink = _sinks[_sinks.length - 1];
|
|
5257
|
-
if (sink) {
|
|
5258
|
-
if (!sink.has(key)) sink.set(key, d);
|
|
5259
|
-
return;
|
|
5260
|
-
}
|
|
5261
|
-
if (_immediate.has(key)) return;
|
|
5262
|
-
_immediate.add(key);
|
|
5263
|
-
if (level === "error") throw new Error(`parseman: degraded compilation path
|
|
5264
|
-
${formatDegradation(d)}`);
|
|
5265
|
-
console.warn(formatDegradation(d));
|
|
5266
|
-
}
|
|
5267
|
-
var _immediate = /* @__PURE__ */ new Set();
|
|
5268
|
-
function beginCompileDegradationDrain() {
|
|
5269
|
-
if (resolveDegradationLevel() === "off" || _sinks.length > 0) return () => {
|
|
5270
|
-
};
|
|
5271
|
-
const depth = degradationCaptureDepth();
|
|
5272
|
-
beginDegradationCapture();
|
|
5273
|
-
return (report) => {
|
|
5274
|
-
const found = unwindDegradationCapture(depth);
|
|
5275
|
-
if (!report || found.length === 0) return;
|
|
5276
|
-
const fresh = found.filter((d) => {
|
|
5277
|
-
const k = degradationKey(d);
|
|
5278
|
-
if (_immediate.has(k)) return false;
|
|
5279
|
-
_immediate.add(k);
|
|
5280
|
-
return true;
|
|
5281
|
-
});
|
|
5282
|
-
if (fresh.length === 0) return;
|
|
5283
|
-
const lines2 = formatDegradations(fresh);
|
|
5284
|
-
if (resolveDegradationLevel() === "error") {
|
|
5285
|
-
throw new Error(`parseman: ${fresh.length} degraded compilation path(s)
|
|
5286
|
-
${lines2.join("\n")}`);
|
|
5287
|
-
}
|
|
5288
|
-
for (const l of lines2) console.warn(l);
|
|
5289
|
-
};
|
|
5290
|
-
}
|
|
5291
|
-
|
|
5292
|
-
// src/compiler/build-arity.ts
|
|
5293
|
-
function cstOutputHost(build) {
|
|
5294
|
-
return build?._parsemanCstOutput === true;
|
|
5295
|
-
}
|
|
5296
|
-
var SINGLE_IDENT_ARROW_RE = /^[A-Za-z_$][\w$]*\s*=>/;
|
|
5297
|
-
var PARAM_LIST_OPEN_RE = /^(?:function\b[^(]*)?\(/;
|
|
5298
|
-
var NATIVE_CODE_RE = /\{\s*\[native code\]\s*\}/;
|
|
5299
|
-
var PARAM_HEAD_RE = /^[A-Za-z_$][\w$]*\s*\??\s*/;
|
|
5300
|
-
function confirmedBuildArity(src) {
|
|
5301
|
-
const s = src.trim();
|
|
5302
|
-
if (NATIVE_CODE_RE.test(s)) return null;
|
|
5303
|
-
if (/\barguments\b/.test(s)) return null;
|
|
5304
|
-
if (SINGLE_IDENT_ARROW_RE.test(s)) return 1;
|
|
5305
|
-
const inner = paramListText(s);
|
|
5306
|
-
if (inner === null) return null;
|
|
5307
|
-
if (inner.trim() === "") return 0;
|
|
5308
|
-
const parts = splitTopLevel(inner);
|
|
5309
|
-
if (parts === null) return null;
|
|
5310
|
-
for (const part of parts) {
|
|
5311
|
-
if (!isConfirmableParam(part.trim())) return null;
|
|
5312
|
-
}
|
|
5313
|
-
return parts.length;
|
|
5314
|
-
}
|
|
5315
|
-
function paramListText(s) {
|
|
5316
|
-
const open = PARAM_LIST_OPEN_RE.exec(s);
|
|
5317
|
-
if (!open) return null;
|
|
5318
|
-
const start = open[0].length;
|
|
5319
|
-
const end = matchingParen(s, start);
|
|
5320
|
-
if (end === null) return null;
|
|
5321
|
-
if (!s.startsWith("function") && !/^\s*=>/.test(s.slice(end + 1))) return null;
|
|
5322
|
-
return s.slice(start, end);
|
|
5323
|
-
}
|
|
5324
|
-
function matchingParen(s, start) {
|
|
5325
|
-
let depth = 0;
|
|
5326
|
-
for (let i = start; i < s.length; i++) {
|
|
5327
|
-
const c = s[i];
|
|
5328
|
-
if (c === '"' || c === "'" || c === "`") {
|
|
5329
|
-
const close = skipString(s, i);
|
|
5330
|
-
if (close === null) return null;
|
|
5331
|
-
i = close;
|
|
5332
|
-
continue;
|
|
5333
|
-
}
|
|
5334
|
-
if (c === "(" || c === "[" || c === "{") depth++;
|
|
5335
|
-
else if (c === "]" || c === "}") {
|
|
5336
|
-
if (--depth < 0) return null;
|
|
5337
|
-
} else if (c === ")") {
|
|
5338
|
-
if (depth === 0) return i;
|
|
5339
|
-
depth--;
|
|
5340
|
-
}
|
|
5341
|
-
}
|
|
5342
|
-
return null;
|
|
5343
|
-
}
|
|
5344
|
-
function skipString(s, open) {
|
|
5345
|
-
const quote = s[open];
|
|
5346
|
-
for (let i = open + 1; i < s.length; i++) {
|
|
5347
|
-
if (s[i] === "\\") {
|
|
5348
|
-
i++;
|
|
5349
|
-
continue;
|
|
6028
|
+
const target = name === void 0 ? void 0 : resolve?.(name);
|
|
6029
|
+
return target === void 0 ? true : [target];
|
|
6030
|
+
}
|
|
5350
6031
|
}
|
|
5351
|
-
|
|
6032
|
+
default:
|
|
6033
|
+
return NO_EDGES;
|
|
5352
6034
|
}
|
|
5353
|
-
return null;
|
|
5354
6035
|
}
|
|
5355
|
-
function
|
|
5356
|
-
const
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
6036
|
+
function reachesMarked(root, successors, memo) {
|
|
6037
|
+
const known = memo.get(root);
|
|
6038
|
+
if (known !== void 0) return known;
|
|
6039
|
+
const order = /* @__PURE__ */ new Map();
|
|
6040
|
+
const low = [];
|
|
6041
|
+
const found = [];
|
|
6042
|
+
const stack = [];
|
|
6043
|
+
const visit = (node2) => {
|
|
6044
|
+
const at = low.length;
|
|
6045
|
+
order.set(node2, at);
|
|
6046
|
+
low.push(at);
|
|
6047
|
+
found.push(false);
|
|
6048
|
+
stack.push(node2);
|
|
6049
|
+
const next = successors(node2);
|
|
6050
|
+
if (next === true) found[at] = true;
|
|
6051
|
+
else {
|
|
6052
|
+
for (const child of next) {
|
|
6053
|
+
if (found[at]) break;
|
|
6054
|
+
const hit = memo.get(child);
|
|
6055
|
+
if (hit !== void 0) {
|
|
6056
|
+
if (hit) found[at] = true;
|
|
6057
|
+
continue;
|
|
6058
|
+
}
|
|
6059
|
+
const seen = order.get(child);
|
|
6060
|
+
if (seen !== void 0) {
|
|
6061
|
+
if (seen < low[at]) low[at] = seen;
|
|
6062
|
+
continue;
|
|
6063
|
+
}
|
|
6064
|
+
const k = visit(child);
|
|
6065
|
+
if (low[k] < low[at]) low[at] = low[k];
|
|
6066
|
+
if (found[k]) found[at] = true;
|
|
6067
|
+
}
|
|
5371
6068
|
}
|
|
5372
|
-
if (
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
parts.push(inner.slice(last, i));
|
|
5380
|
-
last = i + 1;
|
|
6069
|
+
if (low[at] === at) {
|
|
6070
|
+
const answer = found[at];
|
|
6071
|
+
let member;
|
|
6072
|
+
do {
|
|
6073
|
+
member = stack.pop();
|
|
6074
|
+
memo.set(member, answer);
|
|
6075
|
+
} while (member !== node2);
|
|
5381
6076
|
}
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
return parts;
|
|
6077
|
+
return at;
|
|
6078
|
+
};
|
|
6079
|
+
return found[visit(root)];
|
|
5386
6080
|
}
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
6081
|
+
|
|
6082
|
+
// src/table/factor-choice.ts
|
|
6083
|
+
var DERIVED = /* @__PURE__ */ new Set(["_tag", "_meta", "_def", "_parseScalar", "_stickyRegex", "parse"]);
|
|
6084
|
+
function isCombinator(v) {
|
|
6085
|
+
return typeof v === "object" && v !== null && "_def" in v && "_meta" in v;
|
|
6086
|
+
}
|
|
6087
|
+
function sameComb(a, b, depth) {
|
|
6088
|
+
if (a === b) return true;
|
|
6089
|
+
if (depth > 32 || a._tag !== b._tag) return false;
|
|
6090
|
+
for (const k of Object.keys(a)) if (!DERIVED.has(k)) return false;
|
|
6091
|
+
for (const k of Object.keys(b)) if (!DERIVED.has(k)) return false;
|
|
6092
|
+
return sameFields(a._def, b._def, depth, void 0);
|
|
6093
|
+
}
|
|
6094
|
+
function sameValue(u, v, depth) {
|
|
6095
|
+
if (u === v) return true;
|
|
6096
|
+
if (isCombinator(u) && isCombinator(v)) return sameComb(u, v, depth + 1);
|
|
6097
|
+
if (Array.isArray(u) && Array.isArray(v)) return u.length === v.length && u.every((x, i) => sameValue(x, v[i], depth));
|
|
6098
|
+
if (typeof u === "object" && u !== null && typeof v === "object" && v !== null && Object.getPrototypeOf(u) === Object.prototype && Object.getPrototypeOf(v) === Object.prototype) {
|
|
6099
|
+
return sameFields(u, v, depth, void 0);
|
|
6100
|
+
}
|
|
6101
|
+
return false;
|
|
5394
6102
|
}
|
|
5395
|
-
function
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
6103
|
+
function sameFields(x, y, depth, skip) {
|
|
6104
|
+
const kx = Object.keys(x).filter((k) => k !== skip && x[k] !== void 0);
|
|
6105
|
+
const ky = Object.keys(y).filter((k) => k !== skip && y[k] !== void 0);
|
|
6106
|
+
if (kx.length !== ky.length) return false;
|
|
6107
|
+
for (const k of kx) {
|
|
6108
|
+
if (!(k in y)) return false;
|
|
6109
|
+
const u = x[k];
|
|
6110
|
+
const v = y[k];
|
|
6111
|
+
if (k === "fn" && typeof u === "function" && typeof v === "function" && u !== v) {
|
|
6112
|
+
if (typeof x.fnSrc !== "string" || x.fnSrc === "" || x.fnSrc !== y.fnSrc) return false;
|
|
5400
6113
|
continue;
|
|
5401
6114
|
}
|
|
5402
|
-
|
|
5403
|
-
if (prev === "<" || prev === ">" || prev === "!" || prev === "=") continue;
|
|
5404
|
-
return true;
|
|
6115
|
+
if (!sameValue(u, v, depth)) return false;
|
|
5405
6116
|
}
|
|
5406
|
-
return
|
|
5407
|
-
}
|
|
5408
|
-
function buildAnalysisSrc(def) {
|
|
5409
|
-
return def.buildSigSrc ?? def.buildSrc ?? def.build.toString();
|
|
6117
|
+
return true;
|
|
5410
6118
|
}
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
|
|
5421
|
-
}
|
|
5422
|
-
function
|
|
5423
|
-
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
const
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
6119
|
+
function rewrap(w, body) {
|
|
6120
|
+
const d = w._def;
|
|
6121
|
+
let out;
|
|
6122
|
+
if (d.tag === "leaf") {
|
|
6123
|
+
out = d.cstValue === "source" ? sourceLeaf(body, d.fn) : leaf(body, d.fn);
|
|
6124
|
+
if (d.fnSrc !== void 0) out._def.fnSrc = d.fnSrc;
|
|
6125
|
+
} else if (d.tag === "grammar") {
|
|
6126
|
+
out = d.clearTrivia === true ? noTrivia(body) : parser({ trivia: d.triviaParser ?? null }, body);
|
|
6127
|
+
} else return void 0;
|
|
6128
|
+
return sameFields(d, out._def, 0, "parser") ? out : void 0;
|
|
6129
|
+
}
|
|
6130
|
+
function unusedOf(seq) {
|
|
6131
|
+
return seq._def.tag === "sequence" && seq._def.valueUnused === true;
|
|
6132
|
+
}
|
|
6133
|
+
function never(c) {
|
|
6134
|
+
const t2 = c._def.tag;
|
|
6135
|
+
return t2 === "optional" || t2 === "many";
|
|
6136
|
+
}
|
|
6137
|
+
function factorSharedEnds(d) {
|
|
6138
|
+
const arms = d.parsers;
|
|
6139
|
+
if (arms.length < 2) return void 0;
|
|
6140
|
+
if (d.strategy.tag !== "firstMatch" && d.strategy.tag !== "sharedPrefix") return void 0;
|
|
6141
|
+
if (d.gates.some((g) => g !== null) || d.autoNot.some((a) => a !== null)) return void 0;
|
|
6142
|
+
const shapes = [];
|
|
6143
|
+
for (const arm of arms) {
|
|
6144
|
+
const wrappers = [];
|
|
6145
|
+
let c = arm;
|
|
6146
|
+
while ((c._def.tag === "leaf" || c._def.tag === "grammar") && wrappers.length < 4) {
|
|
6147
|
+
wrappers.push(c);
|
|
6148
|
+
c = c._def.parser;
|
|
6149
|
+
}
|
|
6150
|
+
if (c._def.tag !== "sequence" || c._def.parsers.length < 2) return void 0;
|
|
6151
|
+
shapes.push({ wrappers, terms: c._def.parsers, seq: c });
|
|
6152
|
+
}
|
|
6153
|
+
const first = shapes[0];
|
|
6154
|
+
const n = first.terms.length;
|
|
6155
|
+
for (const s of shapes) {
|
|
6156
|
+
if (s.wrappers.length !== first.wrappers.length || s.terms.length !== n) return void 0;
|
|
6157
|
+
if (unusedOf(s.seq) !== unusedOf(first.seq)) return void 0;
|
|
6158
|
+
for (let j = 0; j < s.wrappers.length; j++) {
|
|
6159
|
+
const a = first.wrappers[j]._def;
|
|
6160
|
+
const b = s.wrappers[j]._def;
|
|
6161
|
+
if (a.tag !== b.tag || !sameFields(a, b, 0, "parser")) return void 0;
|
|
6162
|
+
}
|
|
6163
|
+
}
|
|
6164
|
+
let at = -1;
|
|
6165
|
+
for (let i = 0; i < n; i++) {
|
|
6166
|
+
if (shapes.every((s) => sameComb(s.terms[i], first.terms[i], 0))) continue;
|
|
6167
|
+
if (at >= 0) return void 0;
|
|
6168
|
+
at = i;
|
|
6169
|
+
}
|
|
6170
|
+
if (at < 0) return void 0;
|
|
6171
|
+
for (let i = at + 1; i < n; i++) if (!never(first.terms[i])) return void 0;
|
|
6172
|
+
if (arms.some((a) => mayCommitFailure(a))) return void 0;
|
|
6173
|
+
const middle = choice(...shapes.map((s) => s.terms[at]));
|
|
6174
|
+
if (middle._def.tag === "choice" && middle._def.autoNot.some((a) => a !== null)) return void 0;
|
|
6175
|
+
const st = middle._def.tag === "choice" ? middle._def.strategy : void 0;
|
|
6176
|
+
if (st === void 0 || st.tag !== "firstMatch" && st.tag !== "sharedPrefix" && !(st.tag === "literalsLongestFirst" && st.sortedIndices.every((x, i) => x === i))) return void 0;
|
|
6177
|
+
let out = sequence(
|
|
6178
|
+
...[...first.terms.slice(0, at), middle, ...first.terms.slice(at + 1)]
|
|
6179
|
+
);
|
|
6180
|
+
if (unusedOf(first.seq)) {
|
|
6181
|
+
out._def.valueUnused = true;
|
|
5431
6182
|
}
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
function confirmedArityForDef(def) {
|
|
5435
|
-
if (def.buildArity !== void 0) return def.buildArity;
|
|
5436
|
-
const src = buildAnalysisSrc(def);
|
|
5437
|
-
const arity = confirmedBuildArity(src);
|
|
5438
|
-
if (arity !== null) return arity;
|
|
5439
|
-
const subject = `build reducer \`${(def.buildSrc ?? "<runtime fn>").trim().split("\n")[0].slice(0, 60)}\``;
|
|
5440
|
-
recordDegradation({
|
|
5441
|
-
code: "build-arity-unconfirmed",
|
|
5442
|
-
severity: "warn",
|
|
5443
|
-
where: `node("${def.type ?? "<inferred>"}")`,
|
|
5444
|
-
subject,
|
|
5445
|
-
fellBackTo: `could not confirm its declared arity \u2014 ${unconfirmableReason(def, src)} \u2014 so this node captures children, fields and raw children, logs trivia, and clones \`_ctx.state\` on every match`,
|
|
5446
|
-
otherwise: "only the tiers the reducer actually declares would be captured (arity >= 1 children, >= 2 fields, >= 4 raw, >= 5 trivia, >= 6 state). Declare it with `node(..., { buildArity: n })` if it cannot be derived"
|
|
5447
|
-
});
|
|
5448
|
-
return null;
|
|
5449
|
-
}
|
|
5450
|
-
function buildReadsRaw(def) {
|
|
5451
|
-
if (!def.build) return true;
|
|
5452
|
-
if (def.buildRawUnused === true) return false;
|
|
5453
|
-
const arity = confirmedArityForDef(def);
|
|
5454
|
-
if (arity === null) return true;
|
|
5455
|
-
return arity >= 4;
|
|
5456
|
-
}
|
|
5457
|
-
function buildReadsTrivia(def) {
|
|
5458
|
-
if (!def.build) return true;
|
|
5459
|
-
const arity = confirmedArityForDef(def);
|
|
5460
|
-
if (arity === null) return true;
|
|
5461
|
-
return arity >= 5;
|
|
5462
|
-
}
|
|
5463
|
-
function buildReadsState(def) {
|
|
5464
|
-
if (!def.build) return true;
|
|
5465
|
-
const arity = confirmedArityForDef(def);
|
|
5466
|
-
if (arity === null) return true;
|
|
5467
|
-
return arity >= 6;
|
|
6183
|
+
for (let j = first.wrappers.length - 1; j >= 0 && out !== void 0; j--) out = rewrap(first.wrappers[j], out);
|
|
6184
|
+
return out === void 0 ? void 0 : attempt(out);
|
|
5468
6185
|
}
|
|
5469
6186
|
|
|
5470
6187
|
// src/compiler/fields.ts
|
|
@@ -5592,10 +6309,16 @@ function branchUsesRouted(branch) {
|
|
|
5592
6309
|
return branch.usesRouted === true || parserUsesRouted(branch.parser);
|
|
5593
6310
|
}
|
|
5594
6311
|
function asciiFoldKey(key) {
|
|
5595
|
-
let
|
|
5596
|
-
for (
|
|
6312
|
+
let i = 0;
|
|
6313
|
+
for (; i < key.length; i++) {
|
|
6314
|
+
const c = key.charCodeAt(i);
|
|
6315
|
+
if (c >= 65 && c <= 90) break;
|
|
6316
|
+
}
|
|
6317
|
+
if (i === key.length) return key;
|
|
6318
|
+
let out = key.slice(0, i);
|
|
6319
|
+
for (; i < key.length; i++) {
|
|
5597
6320
|
const c = key.charCodeAt(i);
|
|
5598
|
-
out +=
|
|
6321
|
+
out += c >= 65 && c <= 90 ? String.fromCharCode(c + 32) : key[i];
|
|
5599
6322
|
}
|
|
5600
6323
|
return out;
|
|
5601
6324
|
}
|
|
@@ -5643,6 +6366,7 @@ var OP_SCOPE_PLAIN = 41;
|
|
|
5643
6366
|
var OP_LEX_BODY = 42;
|
|
5644
6367
|
var OP_LEX_PROGRAM = 43;
|
|
5645
6368
|
var OP_SOURCE_LEAF = 44;
|
|
6369
|
+
var OP_RGATE = 45;
|
|
5646
6370
|
var OP_DISPATCH = 25;
|
|
5647
6371
|
var OP_ROUTED = 26;
|
|
5648
6372
|
var OP_NAMES = {
|
|
@@ -5662,100 +6386,36 @@ var OP_NAMES = {
|
|
|
5662
6386
|
[OP_PEEK]: "PEEK",
|
|
5663
6387
|
[OP_LEAF]: "LEAF",
|
|
5664
6388
|
[OP_SOURCE_LEAF]: "SOURCE_LEAF",
|
|
6389
|
+
[OP_RGATE]: "RGATE",
|
|
5665
6390
|
[OP_EMPTY]: "EMPTY",
|
|
5666
|
-
[OP_LIT_TRACK]: "LIT_TRACK",
|
|
5667
|
-
[OP_RX_TRACK]: "RX_TRACK",
|
|
5668
|
-
[OP_NODE_TRACK]: "NODE_TRACK",
|
|
5669
|
-
[OP_SCOPE]: "SCOPE",
|
|
5670
|
-
[OP_EXPECT]: "EXPECT",
|
|
5671
|
-
[OP_SEQX]: "SEQX",
|
|
5672
|
-
[OP_SCAN]: "SCAN",
|
|
5673
|
-
[OP_FIELD]: "FIELD",
|
|
5674
|
-
[OP_LIT_CI]: "LIT_CI",
|
|
5675
|
-
[OP_LIT_CI_TRACK]: "LIT_CI_TRACK",
|
|
5676
|
-
[OP_DISPATCH]: "DISPATCH",
|
|
5677
|
-
[OP_ROUTED]: "ROUTED",
|
|
5678
|
-
[OP_TOKEN]: "TOKEN",
|
|
5679
|
-
[OP_SCOPE_CAP]: "SCOPE_CAP",
|
|
5680
|
-
[OP_WITHCTX]: "WITHCTX",
|
|
5681
|
-
[OP_GUARD]: "GUARD",
|
|
5682
|
-
[OP_ADJ]: "ADJ",
|
|
5683
|
-
[OP_GREEDY]: "GREEDY",
|
|
5684
|
-
[OP_REJECT]: "REJECT",
|
|
5685
|
-
[OP_ARMGATE]: "ARMGATE",
|
|
5686
|
-
[OP_LIVE]: "LIVE",
|
|
5687
|
-
[OP_ATTEMPT]: "ATTEMPT",
|
|
5688
|
-
[OP_LABEL]: "LABEL",
|
|
5689
|
-
[OP_COV]: "COV",
|
|
5690
|
-
[OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
|
|
5691
|
-
[OP_LEX_BODY]: "LEX_BODY",
|
|
5692
|
-
[OP_LEX_PROGRAM]: "LEX_PROGRAM"
|
|
5693
|
-
};
|
|
5694
|
-
|
|
5695
|
-
// src/combinators/adjacency.ts
|
|
5696
|
-
function adjacencyOf(p) {
|
|
5697
|
-
return p._def.tag === "adjacency" ? p._def : null;
|
|
5698
|
-
}
|
|
5699
|
-
function adjacencyExpected(def) {
|
|
5700
|
-
if (def.polarity === "adjacent") return "adjacent";
|
|
5701
|
-
return def.kinds === void 0 ? "notAdjacent" : `notAdjacent(${def.kinds.join("|")})`;
|
|
5702
|
-
}
|
|
5703
|
-
function holdsAdjacency(input, cur, ctx, def) {
|
|
5704
|
-
return adjacencyHolds(input, cur, ctx, def.polarity === "notAdjacent", def.kinds);
|
|
5705
|
-
}
|
|
5706
|
-
function adjacencyHolds(input, cur, ctx, negated, kinds) {
|
|
5707
|
-
const end = probeTriviaEnd(input, cur, ctx);
|
|
5708
|
-
if (!negated) return end === cur;
|
|
5709
|
-
if (end === cur) return false;
|
|
5710
|
-
if (kinds === void 0) return true;
|
|
5711
|
-
const want = resolveAdjacencyKindMask(ctx.trivia, kinds);
|
|
5712
|
-
const spec = analyzeLabeledTrivia(ctx.trivia);
|
|
5713
|
-
return (triviaKindMaskAt(input, cur, spec, ctx.state) & want) !== 0;
|
|
5714
|
-
}
|
|
5715
|
-
function adjacencyFail(pos, def) {
|
|
5716
|
-
return { ok: false, expected: [adjacencyExpected(def)], span: { start: pos, end: pos } };
|
|
5717
|
-
}
|
|
5718
|
-
var NO_STANDALONE_PARSE = "adjacency assertions are boundary tests: use adjacent()/notAdjacent() as a NON-FIRST term of a sequence(), where the preceding term defines the gap being asserted.";
|
|
5719
|
-
function adjacencyMisuse(polarity) {
|
|
5720
|
-
return new TypeError(`${polarity}(): ${NO_STANDALONE_PARSE}`);
|
|
5721
|
-
}
|
|
5722
|
-
function adjacencyCombinator(def) {
|
|
5723
|
-
const meta = {
|
|
5724
|
-
// Zero-width and never leading (sequence() rejects index 0), so it contributes
|
|
5725
|
-
// no first char. `isZeroWidthAssertion` drops it from a sequence's first-set
|
|
5726
|
-
// rather than letting `any` poison the enclosing choice's dispatch.
|
|
5727
|
-
firstSet: { kind: "any" },
|
|
5728
|
-
canMatchNewline: false,
|
|
5729
|
-
isTrivia: false
|
|
5730
|
-
};
|
|
5731
|
-
return {
|
|
5732
|
-
_tag: "adjacency",
|
|
5733
|
-
_meta: meta,
|
|
5734
|
-
_def: def,
|
|
5735
|
-
parse() {
|
|
5736
|
-
throw adjacencyMisuse(def.polarity);
|
|
5737
|
-
}
|
|
5738
|
-
};
|
|
5739
|
-
}
|
|
5740
|
-
function adjacent() {
|
|
5741
|
-
return adjacencyCombinator({ tag: "adjacency", polarity: "adjacent" });
|
|
5742
|
-
}
|
|
5743
|
-
function notAdjacent(options) {
|
|
5744
|
-
const kinds = options?.kinds;
|
|
5745
|
-
if (kinds !== void 0) {
|
|
5746
|
-
if (!Array.isArray(kinds) || kinds.length === 0) {
|
|
5747
|
-
throw new TypeError("notAdjacent({ kinds }): kinds must be a non-empty array of trivia category names.");
|
|
5748
|
-
}
|
|
5749
|
-
for (const k of kinds) {
|
|
5750
|
-
if (typeof k !== "string" || k.length === 0) {
|
|
5751
|
-
throw new TypeError(`notAdjacent({ kinds }): every kind must be a non-empty string, got ${JSON.stringify(k)}.`);
|
|
5752
|
-
}
|
|
5753
|
-
}
|
|
5754
|
-
}
|
|
5755
|
-
return adjacencyCombinator(
|
|
5756
|
-
kinds === void 0 ? { tag: "adjacency", polarity: "notAdjacent" } : { tag: "adjacency", polarity: "notAdjacent", kinds: [...kinds] }
|
|
5757
|
-
);
|
|
5758
|
-
}
|
|
6391
|
+
[OP_LIT_TRACK]: "LIT_TRACK",
|
|
6392
|
+
[OP_RX_TRACK]: "RX_TRACK",
|
|
6393
|
+
[OP_NODE_TRACK]: "NODE_TRACK",
|
|
6394
|
+
[OP_SCOPE]: "SCOPE",
|
|
6395
|
+
[OP_EXPECT]: "EXPECT",
|
|
6396
|
+
[OP_SEQX]: "SEQX",
|
|
6397
|
+
[OP_SCAN]: "SCAN",
|
|
6398
|
+
[OP_FIELD]: "FIELD",
|
|
6399
|
+
[OP_LIT_CI]: "LIT_CI",
|
|
6400
|
+
[OP_LIT_CI_TRACK]: "LIT_CI_TRACK",
|
|
6401
|
+
[OP_DISPATCH]: "DISPATCH",
|
|
6402
|
+
[OP_ROUTED]: "ROUTED",
|
|
6403
|
+
[OP_TOKEN]: "TOKEN",
|
|
6404
|
+
[OP_SCOPE_CAP]: "SCOPE_CAP",
|
|
6405
|
+
[OP_WITHCTX]: "WITHCTX",
|
|
6406
|
+
[OP_GUARD]: "GUARD",
|
|
6407
|
+
[OP_ADJ]: "ADJ",
|
|
6408
|
+
[OP_GREEDY]: "GREEDY",
|
|
6409
|
+
[OP_REJECT]: "REJECT",
|
|
6410
|
+
[OP_ARMGATE]: "ARMGATE",
|
|
6411
|
+
[OP_LIVE]: "LIVE",
|
|
6412
|
+
[OP_ATTEMPT]: "ATTEMPT",
|
|
6413
|
+
[OP_LABEL]: "LABEL",
|
|
6414
|
+
[OP_COV]: "COV",
|
|
6415
|
+
[OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
|
|
6416
|
+
[OP_LEX_BODY]: "LEX_BODY",
|
|
6417
|
+
[OP_LEX_PROGRAM]: "LEX_PROGRAM"
|
|
6418
|
+
};
|
|
5759
6419
|
|
|
5760
6420
|
// src/combinators/node.ts
|
|
5761
6421
|
function unwrapChild(child) {
|
|
@@ -5818,7 +6478,7 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
5818
6478
|
}
|
|
5819
6479
|
const def = unwrap || collapse || project !== void 0 || captureTrivia || trailingTrivia || buildArity !== void 0 || tags !== void 0 && tags.length > 0 ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {}, ...project !== void 0 ? { project } : {}, ...captureTrivia ? { captureTrivia: true } : {}, ...trailingTrivia ? { trailingTrivia: true } : {}, ...buildArity !== void 0 ? { buildArity } : {}, ...tags !== void 0 && tags.length > 0 ? { tags } : {} } : baseDef;
|
|
5820
6480
|
const capturesTrivia = captureTrivia || (build ? buildReadsTrivia(def) : project === void 0);
|
|
5821
|
-
const
|
|
6481
|
+
const readsState = build ? buildReadsState(def) : project === void 0;
|
|
5822
6482
|
const hasOwnFields = parserHasOwnFields(combinator);
|
|
5823
6483
|
const capturesFields = hasOwnFields && (build ? buildReadsFields(def) : project === void 0);
|
|
5824
6484
|
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
@@ -5859,12 +6519,11 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
5859
6519
|
ctx._triviaCaptureMask = savedMask;
|
|
5860
6520
|
const { children: children2, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
|
|
5861
6521
|
if (!r.ok) return r;
|
|
5862
|
-
const st =
|
|
6522
|
+
const st = readsState ? ctx.state : void 0;
|
|
5863
6523
|
const nodeType = def.type ?? missingInferredType();
|
|
5864
6524
|
const cstOutput = cstOutputHost(ctx.build);
|
|
5865
6525
|
const span = ctx.trackLines ? annotateSpanFromLineContext(r.span, ctx) : r.span;
|
|
5866
|
-
const
|
|
5867
|
-
const built = unwrap && children2.length === 1 ? unwrapChild(children2[0]) : collapse && children2.length === 1 ? children2[0] : (cstOutput || !build && project === void 0) && ctx.build?._parsemanCstCollapse && children2.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children2[0], children2, rawChildren) ? children2[0] : project !== void 0 ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, hostState, tags) : projectChild(children2, project, nodeType) : build ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, hostState, tags) : build(children2, fields, span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, st, tags) : { _tag: "node", type: nodeType, span: ctx.trackLines ? { ...span } : { start: r.span.start, end: r.span.end }, state: st ?? null, children: children2 };
|
|
6526
|
+
const built = unwrap && children2.length === 1 ? unwrapChild(children2[0]) : collapse && children2.length === 1 ? children2[0] : (cstOutput || !build && project === void 0) && ctx.build?._parsemanCstCollapse && children2.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children2[0], children2, rawChildren) ? children2[0] : project !== void 0 ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, ctx.state, tags) : projectChild(children2, project, nodeType) : build ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, ctx.state, tags) : build(children2, fields, span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, st, tags) : { _tag: "node", type: nodeType, span: ctx.trackLines ? { ...span } : { start: r.span.start, end: r.span.end }, state: st ?? null, children: children2 };
|
|
5868
6527
|
const rawEntry2 = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : typeof built === "object" && built !== null ? input.slice(r.span.start, r.span.end) : "", span };
|
|
5869
6528
|
if (saved.buf !== void 0 || saved.ch !== void 0) {
|
|
5870
6529
|
pushCstChild(ctx, built, rawEntry2);
|
|
@@ -5960,7 +6619,10 @@ function selectOptionalSuffixLexBody(ir) {
|
|
|
5960
6619
|
const token2 = { strategy: "token", estimatedOps: 2, body };
|
|
5961
6620
|
return token2.estimatedOps < character.estimatedOps ? token2 : character;
|
|
5962
6621
|
}
|
|
5963
|
-
function
|
|
6622
|
+
function reinstallsRuleTrivia(reference, target) {
|
|
6623
|
+
return (reference._meta.grammarTrivia ?? target._meta.grammarTrivia) !== void 0 && hasOwnTriviaBoundary(target);
|
|
6624
|
+
}
|
|
6625
|
+
function directTokenBodyParser(parser2, resolve, scope) {
|
|
5964
6626
|
const outer = parser2._def;
|
|
5965
6627
|
if (outer.tag !== "token") return void 0;
|
|
5966
6628
|
let body = outer.parser;
|
|
@@ -5970,12 +6632,13 @@ function directTokenBodyParser(parser2, resolve) {
|
|
|
5970
6632
|
const wrapper = body._def;
|
|
5971
6633
|
if (wrapper.tag === "grammar") {
|
|
5972
6634
|
if (wrapper.clearTrivia !== true || wrapper.triviaParser !== void 0 || wrapper.captureTrivia === true || wrapper.rootCapture === "opaque" || wrapper.constructionTrackLines !== "inherit" || wrapper.constructionCaptureTriviaKinds !== void 0) return void 0;
|
|
6635
|
+
if (scope !== void 0) scope.cleared = true;
|
|
5973
6636
|
body = wrapper.parser;
|
|
5974
6637
|
continue;
|
|
5975
6638
|
}
|
|
5976
6639
|
if (wrapper.tag === "lazy") {
|
|
5977
6640
|
const target = resolvedLazyTarget(body, resolve);
|
|
5978
|
-
if (target === void 0) return void 0;
|
|
6641
|
+
if (target === void 0 || reinstallsRuleTrivia(body, target)) return void 0;
|
|
5979
6642
|
body = target;
|
|
5980
6643
|
continue;
|
|
5981
6644
|
}
|
|
@@ -6147,7 +6810,7 @@ function directNot2TokenBody(parser2, resolve) {
|
|
|
6147
6810
|
terminal
|
|
6148
6811
|
};
|
|
6149
6812
|
}
|
|
6150
|
-
function directFixedLexNode(parser2, resolve, active, pureOnly = false) {
|
|
6813
|
+
function directFixedLexNode(parser2, resolve, active, pureOnly = false, cleared = false) {
|
|
6151
6814
|
let current = parser2;
|
|
6152
6815
|
const wrappers = /* @__PURE__ */ new Set();
|
|
6153
6816
|
while (!wrappers.has(current)) {
|
|
@@ -6155,7 +6818,7 @@ function directFixedLexNode(parser2, resolve, active, pureOnly = false) {
|
|
|
6155
6818
|
const def = current._def;
|
|
6156
6819
|
if (def.tag === "lazy") {
|
|
6157
6820
|
const target = resolvedLazyTarget(current, resolve);
|
|
6158
|
-
if (target === void 0) return void 0;
|
|
6821
|
+
if (target === void 0 || reinstallsRuleTrivia(current, target)) return void 0;
|
|
6159
6822
|
current = target;
|
|
6160
6823
|
continue;
|
|
6161
6824
|
}
|
|
@@ -6173,30 +6836,33 @@ function directFixedLexNode(parser2, resolve, active, pureOnly = false) {
|
|
|
6173
6836
|
if (terminal !== void 0) return { kind: "terminal", terminal };
|
|
6174
6837
|
const def = current._def;
|
|
6175
6838
|
if (def.tag === "grammar") {
|
|
6839
|
+
if (def.triviaParser === void 0 && def.captureTrivia !== true && def.rootCapture !== "opaque" && def.constructionCaptureTriviaKinds === void 0) {
|
|
6840
|
+
return directFixedLexNode(def.parser, resolve, active, pureOnly, cleared || def.clearTrivia === true);
|
|
6841
|
+
}
|
|
6176
6842
|
if (!pureOnly || def.parser._def.tag !== "token" && (def.clearTrivia !== true || def.triviaParser !== void 0 || def.captureTrivia === true || def.rootCapture === "opaque")) return void 0;
|
|
6177
|
-
return directFixedLexNode(def.parser, resolve, active, true);
|
|
6843
|
+
return directFixedLexNode(def.parser, resolve, active, true, cleared);
|
|
6178
6844
|
}
|
|
6179
6845
|
if (def.tag === "sequence") {
|
|
6180
6846
|
if (def.parsers.length < 2 || def.parsers.length > 5) return void 0;
|
|
6181
|
-
const parts = def.parsers.map((part) => directFixedLexNode(part, resolve, active, pureOnly));
|
|
6847
|
+
const parts = def.parsers.map((part) => directFixedLexNode(part, resolve, active, pureOnly, cleared));
|
|
6182
6848
|
if (parts.some((part) => part === void 0)) return void 0;
|
|
6183
6849
|
return { kind: "sequence", parts };
|
|
6184
6850
|
}
|
|
6185
6851
|
if (def.tag === "choice") {
|
|
6186
|
-
if (def.parsers.length
|
|
6187
|
-
const arms = def.parsers.map((arm) => directFixedLexNode(arm, resolve, active, pureOnly));
|
|
6852
|
+
if (def.parsers.length < 2 || def.strategy.tag !== "firstMatch" || def.gates.some((gate) => gate !== null) || def.autoNot.some((check) => check !== null)) return void 0;
|
|
6853
|
+
const arms = def.parsers.map((arm) => directFixedLexNode(arm, resolve, active, pureOnly, cleared));
|
|
6188
6854
|
if (arms.some((arm) => arm === void 0)) return void 0;
|
|
6189
|
-
const final = classifyFinalChoice(def.parsers, resolve);
|
|
6190
6855
|
return {
|
|
6191
6856
|
kind: "choice",
|
|
6192
6857
|
arms,
|
|
6193
|
-
|
|
6858
|
+
parsers: def.parsers,
|
|
6859
|
+
cleared,
|
|
6194
6860
|
armExpected: def.parsers.map(deriveExpected),
|
|
6195
6861
|
expected: def.parsers.flatMap(deriveExpected)
|
|
6196
6862
|
};
|
|
6197
6863
|
}
|
|
6198
6864
|
if (def.tag === "not") {
|
|
6199
|
-
const body = directFixedLexNode(def.parser, resolve, active, true);
|
|
6865
|
+
const body = directFixedLexNode(def.parser, resolve, active, true, cleared);
|
|
6200
6866
|
return body === void 0 ? void 0 : {
|
|
6201
6867
|
kind: "not",
|
|
6202
6868
|
body,
|
|
@@ -6204,18 +6870,28 @@ function directFixedLexNode(parser2, resolve, active, pureOnly = false) {
|
|
|
6204
6870
|
};
|
|
6205
6871
|
}
|
|
6206
6872
|
if (def.tag === "optional") {
|
|
6207
|
-
const body = directFixedLexNode(def.parser, resolve, active, pureOnly);
|
|
6873
|
+
const body = directFixedLexNode(def.parser, resolve, active, pureOnly, cleared);
|
|
6208
6874
|
return body === void 0 ? void 0 : { kind: "optional", body };
|
|
6209
6875
|
}
|
|
6876
|
+
if (def.tag === "many" || def.tag === "oneOrMore") {
|
|
6877
|
+
const body = directFixedLexNode(def.parser, resolve, active, pureOnly, cleared);
|
|
6878
|
+
return body === void 0 ? void 0 : {
|
|
6879
|
+
kind: "repeat",
|
|
6880
|
+
body,
|
|
6881
|
+
min: def.tag === "many" ? 0 : def.min,
|
|
6882
|
+
max: def.max ?? -1
|
|
6883
|
+
};
|
|
6884
|
+
}
|
|
6210
6885
|
return void 0;
|
|
6211
6886
|
} finally {
|
|
6212
6887
|
active.delete(current);
|
|
6213
6888
|
}
|
|
6214
6889
|
}
|
|
6215
6890
|
function directFixedTokenBody(parser2, resolve) {
|
|
6216
|
-
const
|
|
6891
|
+
const scope = { cleared: false };
|
|
6892
|
+
const body = directTokenBodyParser(parser2, resolve, scope);
|
|
6217
6893
|
if (body === void 0) return void 0;
|
|
6218
|
-
const root = directFixedLexNode(body, resolve, /* @__PURE__ */ new Set());
|
|
6894
|
+
const root = directFixedLexNode(body, resolve, /* @__PURE__ */ new Set(), false, scope.cleared);
|
|
6219
6895
|
return root === void 0 ? void 0 : { kind: "fixed-tree", root };
|
|
6220
6896
|
}
|
|
6221
6897
|
function directBalancedTokenBody(parser2, resolve) {
|
|
@@ -6462,13 +7138,16 @@ var Encoder = class {
|
|
|
6462
7138
|
}
|
|
6463
7139
|
case "choice": {
|
|
6464
7140
|
for (const arm of node2.arms) if (!emitNode(arm)) return false;
|
|
6465
|
-
const
|
|
6466
|
-
|
|
6467
|
-
|
|
7141
|
+
const final = classifyFinalChoice(
|
|
7142
|
+
node2.parsers,
|
|
7143
|
+
this.refResolver(),
|
|
7144
|
+
node2.cleared ? void 0 : this.activeTrivia
|
|
7145
|
+
);
|
|
7146
|
+
const classes = final.firstSets.map((first, i) => final.nullable[i] ? -1 : this.charClass(first));
|
|
7147
|
+
const exclusive = final.exclusive && classes.every((cls) => cls >= 0);
|
|
7148
|
+
words.push(LEX_NODE_CHOICE, node2.arms.length, exclusive ? 1 : 0, this.expected(node2.expected));
|
|
6468
7149
|
for (let i = 0; i < node2.arms.length; i++) {
|
|
6469
|
-
|
|
6470
|
-
words.push(first.kind === "ranges" ? this.charClass(first) : -1);
|
|
6471
|
-
words.push(this.expected(node2.armExpected[i]));
|
|
7150
|
+
words.push(classes[i], this.expected(node2.armExpected[i]));
|
|
6472
7151
|
}
|
|
6473
7152
|
return true;
|
|
6474
7153
|
}
|
|
@@ -6480,6 +7159,10 @@ var Encoder = class {
|
|
|
6480
7159
|
if (!emitNode(node2.body)) return false;
|
|
6481
7160
|
words.push(LEX_NODE_OPTIONAL);
|
|
6482
7161
|
return true;
|
|
7162
|
+
case "repeat":
|
|
7163
|
+
if (!emitNode(node2.body)) return false;
|
|
7164
|
+
words.push(LEX_NODE_REPEAT, node2.min, node2.max);
|
|
7165
|
+
return true;
|
|
6483
7166
|
}
|
|
6484
7167
|
};
|
|
6485
7168
|
if (!emitNode(body.root)) return void 0;
|
|
@@ -6807,6 +7490,33 @@ var Encoder = class {
|
|
|
6807
7490
|
return childrenOf(def);
|
|
6808
7491
|
}
|
|
6809
7492
|
}
|
|
7493
|
+
/**
|
|
7494
|
+
* THE FIRST-CHARACTER GATE OF AN `optional`, `not` OR `peek` CHILD.
|
|
7495
|
+
*
|
|
7496
|
+
* A non-nullable child cannot match at a character outside its first set, so
|
|
7497
|
+
* the wrapper's outcome there is already decided: `optional` yields `null`,
|
|
7498
|
+
* `not` succeeds, `peek` fails with its own set. The interpreter's `optional`
|
|
7499
|
+
* makes that test itself (`repeat.ts` `startsFirstSet`); the table entered the
|
|
7500
|
+
* child — a rollback mark, the call, the child's own failure — to learn it.
|
|
7501
|
+
*
|
|
7502
|
+
* The gate is an `OP_GATE` row around the child, so every engine runs it
|
|
7503
|
+
* unchanged, a probe or tolerant parse forwards through it as for a node's
|
|
7504
|
+
* gate, and the wrapper's row keeps its layout. The engines test the class
|
|
7505
|
+
* before taking the wrapper's mark. The first set is resolved through
|
|
7506
|
+
* `winners`, the analysis a choice arm's gate uses, so a composed rule's set
|
|
7507
|
+
* is the merged one. A scalar `not` child stays bare: `scalarTerminalNotChild`
|
|
7508
|
+
* already reduces it to one recognizer call.
|
|
7509
|
+
*/
|
|
7510
|
+
lookaheadGate(p, child) {
|
|
7511
|
+
const op = this.code[child];
|
|
7512
|
+
if (op === OP_GATE || op === OP_LIT || op === OP_LIT_CI || op === OP_LIT_TRACK || op === OP_LIT_CI_TRACK || op === OP_RX || op === OP_RX_TRACK) return child;
|
|
7513
|
+
const rr = this.refResolver();
|
|
7514
|
+
if (matchesEmpty(p, /* @__PURE__ */ new Set(), rr)) return child;
|
|
7515
|
+
const cls = this.charClass(firstSetOf(p, /* @__PURE__ */ new Set(), rr, this.activeTrivia));
|
|
7516
|
+
if (cls < 0) return child;
|
|
7517
|
+
const e = deriveExpected(p);
|
|
7518
|
+
return this.emit(OP_GATE, cls, child, this.expected(e.length > 0 ? e : [p._tag]));
|
|
7519
|
+
}
|
|
6810
7520
|
/** A first set becomes a char class string, or −1 for `any`. */
|
|
6811
7521
|
charClass(fs) {
|
|
6812
7522
|
if (fs.kind !== "ranges" || fs.ranges.length === 0) return -1;
|
|
@@ -6818,12 +7528,19 @@ var Encoder = class {
|
|
|
6818
7528
|
this.ccIndex.set(spec, i);
|
|
6819
7529
|
return i;
|
|
6820
7530
|
}
|
|
6821
|
-
/**
|
|
6822
|
-
*
|
|
6823
|
-
|
|
6824
|
-
|
|
6825
|
-
|
|
6826
|
-
|
|
7531
|
+
/**
|
|
7532
|
+
* The first set a node's or an attempt's fail-fast gate tests. A bare
|
|
7533
|
+
* cross-rule ref resolves through `winners` (a compose OVERRIDE may widen
|
|
7534
|
+
* it). Any other body keeps its construction-time `_meta.firstSet`, except
|
|
7535
|
+
* where that is `any`: under `compose()` a body that reaches a rule of
|
|
7536
|
+
* another piece is built before that rule exists, so its cached set is
|
|
7537
|
+
* `any` and the node got NO gate (jess's `CompoundSelector` was entered at
|
|
7538
|
+
* `{`, `Call` at `}`). The resolved set is the one a choice arm's gate uses,
|
|
7539
|
+
* over the final merged map.
|
|
7540
|
+
*/
|
|
7541
|
+
gateFirstSet(p) {
|
|
7542
|
+
const cached = p._meta.firstSet;
|
|
7543
|
+
return p._def.tag === "lazy" || cached.kind === "any" ? firstSetOf(p, /* @__PURE__ */ new Set(), this.refResolver(), this.activeTrivia) : cached;
|
|
6827
7544
|
}
|
|
6828
7545
|
/**
|
|
6829
7546
|
* Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
|
|
@@ -6951,6 +7668,50 @@ var Encoder = class {
|
|
|
6951
7668
|
if (!hasOwnTriviaBoundary(target)) return ip;
|
|
6952
7669
|
return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), ip);
|
|
6953
7670
|
}
|
|
7671
|
+
/**
|
|
7672
|
+
* The `OP_RGATE` operands of a choice arm that opens with `routed()`, or
|
|
7673
|
+
* `undefined`. Through `node()`/scope wrappers and first sequence terms, the
|
|
7674
|
+
* arm's next term after the routed token is found; the gate is that term's
|
|
7675
|
+
* first characters, with the trivia in force at the boundary before it, so
|
|
7676
|
+
* the arm is entered only where it can get past the token. The term must be
|
|
7677
|
+
* unable to match empty or to commit, so a miss is exactly that term failing
|
|
7678
|
+
* at the token's end with its own set.
|
|
7679
|
+
*/
|
|
7680
|
+
routedArmGate(arm) {
|
|
7681
|
+
const walk = (p, trivia2, depth) => {
|
|
7682
|
+
if (depth > 16) return void 0;
|
|
7683
|
+
const d = p._def;
|
|
7684
|
+
switch (d.tag) {
|
|
7685
|
+
case "routed":
|
|
7686
|
+
return "end";
|
|
7687
|
+
case "node":
|
|
7688
|
+
return walk(d.parser, trivia2, depth + 1);
|
|
7689
|
+
case "grammar":
|
|
7690
|
+
return walk(d.parser, d.clearTrivia === true ? void 0 : d.triviaParser ?? trivia2, depth + 1);
|
|
7691
|
+
case "sequence": {
|
|
7692
|
+
const head = d.parsers[0];
|
|
7693
|
+
if (head === void 0) return void 0;
|
|
7694
|
+
const r = walk(head, trivia2, depth + 1);
|
|
7695
|
+
if (r !== "end") return r;
|
|
7696
|
+
const next2 = d.parsers[1];
|
|
7697
|
+
return next2 === void 0 ? "end" : { next: next2, boundary: trivia2 };
|
|
7698
|
+
}
|
|
7699
|
+
default:
|
|
7700
|
+
return void 0;
|
|
7701
|
+
}
|
|
7702
|
+
};
|
|
7703
|
+
const follow = walk(arm, this.activeTrivia, 0);
|
|
7704
|
+
if (follow === void 0 || follow === "end") return void 0;
|
|
7705
|
+
const rr = this.refResolver();
|
|
7706
|
+
const { next, boundary } = follow;
|
|
7707
|
+
if (matchesEmpty(next, /* @__PURE__ */ new Set(), rr) || mayCommitFailure(next, rr, this.commitFailureMemo)) return void 0;
|
|
7708
|
+
const nextTag = next._def.tag;
|
|
7709
|
+
if (nextTag !== "literal" && nextTag !== "regex" && nextTag !== "keywords" && nextTag !== "label") return void 0;
|
|
7710
|
+
const first = firstSetOf(next, /* @__PURE__ */ new Set(), rr, boundary);
|
|
7711
|
+
const cls = this.charClass(boundary === void 0 ? first : union(first, firstSetOf(boundary, /* @__PURE__ */ new Set(), rr)));
|
|
7712
|
+
if (cls < 0) return void 0;
|
|
7713
|
+
return { cls, fx: this.expected(deriveExpected(next)) };
|
|
7714
|
+
}
|
|
6954
7715
|
node(p) {
|
|
6955
7716
|
const lazyRef = p._def.tag === "lazy";
|
|
6956
7717
|
const scopeKey = lazyRef ? this.activeTrivia : void 0;
|
|
@@ -7075,6 +7836,10 @@ var Encoder = class {
|
|
|
7075
7836
|
return head;
|
|
7076
7837
|
}
|
|
7077
7838
|
case "choice": {
|
|
7839
|
+
if (this.plan === void 0) {
|
|
7840
|
+
const factored = factorSharedEnds(d);
|
|
7841
|
+
if (factored !== void 0) return this.node(factored).ip;
|
|
7842
|
+
}
|
|
7078
7843
|
if (d.strategy.tag === "greedyClassify") {
|
|
7079
7844
|
const superIndex = d.strategy.superIndex;
|
|
7080
7845
|
const sup = this.node(d.parsers[superIndex]).ip;
|
|
@@ -7098,9 +7863,12 @@ var Encoder = class {
|
|
|
7098
7863
|
const kids = arms.map((c, k) => {
|
|
7099
7864
|
const src = order[k];
|
|
7100
7865
|
const checks = d.autoNot[src];
|
|
7101
|
-
const inner = this.node(c).ip;
|
|
7102
|
-
const ip = checks === null || checks === void 0 || checks.length === 0 ? inner : this.reject(inner, checks);
|
|
7103
7866
|
const gate = d.gates[src];
|
|
7867
|
+
const plain2 = (checks === null || checks === void 0 || checks.length === 0) && (gate === null || gate === void 0);
|
|
7868
|
+
const routedGate = plain2 ? this.routedArmGate(c) : void 0;
|
|
7869
|
+
const body = this.node(c).ip;
|
|
7870
|
+
const inner = routedGate === void 0 ? body : this.emit(OP_RGATE, routedGate.cls, body, routedGate.fx);
|
|
7871
|
+
const ip = checks === null || checks === void 0 || checks.length === 0 ? inner : this.reject(inner, checks);
|
|
7104
7872
|
const gated = gate === null || gate === void 0 ? ip : this.emit(OP_ARMGATE, this.fn(gate, d.gateSrcs?.[src] ?? null), ip, this.expected(deriveExpected(c)));
|
|
7105
7873
|
return this.covWrap(gated, armCovIds?.[src], 1);
|
|
7106
7874
|
});
|
|
@@ -7128,6 +7896,12 @@ var Encoder = class {
|
|
|
7128
7896
|
if (transactionalFirst[i] !== void 0) classes[i] = -1;
|
|
7129
7897
|
}
|
|
7130
7898
|
}
|
|
7899
|
+
if (d.gates.some((g) => g !== null && g !== void 0) && !dispatchIsExclusive(classes, this.cc)) {
|
|
7900
|
+
for (let k = 0; k < classes.length; k++) {
|
|
7901
|
+
const gate = d.gates[order[k]];
|
|
7902
|
+
if (gate !== null && gate !== void 0) classes[k] = -1;
|
|
7903
|
+
}
|
|
7904
|
+
}
|
|
7131
7905
|
const dispIdx = this.disp.length;
|
|
7132
7906
|
this.disp.push(classes);
|
|
7133
7907
|
let rollbackMask = kids.length > 31 ? -1 : 0;
|
|
@@ -7157,7 +7931,7 @@ var Encoder = class {
|
|
|
7157
7931
|
case "oneOrMore": {
|
|
7158
7932
|
const child = this.node(d.parser).ip;
|
|
7159
7933
|
const rr = this.refResolver();
|
|
7160
|
-
const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.
|
|
7934
|
+
const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.charClass(firstSetOf(d.parser, /* @__PURE__ */ new Set(), rr, this.activeTrivia));
|
|
7161
7935
|
const op = d.valueUnused ? OP_REPV : OP_REP;
|
|
7162
7936
|
const min = d.tag === "many" ? 0 : d.min;
|
|
7163
7937
|
return this.rec ? this.emit(op, child, min, d.max ?? -1, -1, 0, this.expected(deriveExpected(d.parser)), itemClass) : this.emit(op, child, min, d.max ?? -1, -1, 0);
|
|
@@ -7181,7 +7955,7 @@ var Encoder = class {
|
|
|
7181
7955
|
return d.min >= 2 ? this.emit(OP_REP, child, d.min, d.max ?? -1, sep, flags, this.expected(deriveExpected(d.parser))) : this.emit(OP_REP, child, d.min, d.max ?? -1, sep, flags);
|
|
7182
7956
|
}
|
|
7183
7957
|
case "optional": {
|
|
7184
|
-
const head = this.emit(OP_OPT, this.node(d.parser).ip);
|
|
7958
|
+
const head = this.emit(OP_OPT, this.lookaheadGate(d.parser, this.node(d.parser).ip));
|
|
7185
7959
|
if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(head);
|
|
7186
7960
|
return head;
|
|
7187
7961
|
}
|
|
@@ -7229,8 +8003,8 @@ var Encoder = class {
|
|
|
7229
8003
|
// every CST node, so this is load-bearing, not reflection trivia.
|
|
7230
8004
|
d.tags === void 0 ? -1 : this.constant(d.tags)
|
|
7231
8005
|
);
|
|
7232
|
-
if (matchesEmpty(d.parser)) return body;
|
|
7233
|
-
const fs =
|
|
8006
|
+
if (matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return body;
|
|
8007
|
+
const fs = this.gateFirstSet(d.parser);
|
|
7234
8008
|
if (fs.kind === "any") return body;
|
|
7235
8009
|
const cls = this.charClass(fs);
|
|
7236
8010
|
if (cls < 0) return body;
|
|
@@ -7322,7 +8096,7 @@ var Encoder = class {
|
|
|
7322
8096
|
// other engine reported `['not(literal)']`. It hid because `expected` is a
|
|
7323
8097
|
// TOP-LEVEL field on `RunResult` and is NOT part of the identity digest.
|
|
7324
8098
|
case "not":
|
|
7325
|
-
return this.emit(OP_NOT, this.node(d.parser).ip, this.expected(assertionFailureExpected(false, d.parser._tag)));
|
|
8099
|
+
return this.emit(OP_NOT, this.lookaheadGate(d.parser, this.node(d.parser).ip), this.expected(assertionFailureExpected(false, d.parser._tag)));
|
|
7326
8100
|
case "guard":
|
|
7327
8101
|
return this.emit(OP_GUARD, this.fn(d.predicate, d.predSrc ?? null), this.expected(["gate"]));
|
|
7328
8102
|
case "adjacency":
|
|
@@ -7343,14 +8117,14 @@ var Encoder = class {
|
|
|
7343
8117
|
return this.emit(OP_WITHCTX, this.constant(d.extra), this.node(d.parser).ip);
|
|
7344
8118
|
}
|
|
7345
8119
|
case "peek":
|
|
7346
|
-
return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected(assertionFailureExpected(true, d.parser._tag)));
|
|
8120
|
+
return this.emit(OP_PEEK, this.lookaheadGate(d.parser, this.node(d.parser).ip), this.expected(assertionFailureExpected(true, d.parser._tag)));
|
|
7347
8121
|
// A TRANSACTION IS A ROW. See `OP_ATTEMPT` for why the transparent
|
|
7348
8122
|
// lowering was correct only for a choice arm.
|
|
7349
8123
|
case "attempt": {
|
|
7350
8124
|
const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip, d.contain === true ? 1 : 0);
|
|
7351
8125
|
if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
|
|
7352
|
-
const fs =
|
|
7353
|
-
if (fs.kind === "any" || matchesEmpty(d.parser)) return inner;
|
|
8126
|
+
const fs = this.gateFirstSet(d.parser);
|
|
8127
|
+
if (fs.kind === "any" || matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return inner;
|
|
7354
8128
|
const cls = this.charClass(fs);
|
|
7355
8129
|
if (cls < 0) return inner;
|
|
7356
8130
|
const e = deriveExpected(d.parser);
|
|
@@ -7418,6 +8192,7 @@ var Encoder = class {
|
|
|
7418
8192
|
const slots = (ip) => {
|
|
7419
8193
|
switch (this.code[ip]) {
|
|
7420
8194
|
case OP_GATE:
|
|
8195
|
+
case OP_RGATE:
|
|
7421
8196
|
return [ip + 2];
|
|
7422
8197
|
case OP_RULE:
|
|
7423
8198
|
case OP_OPT:
|
|
@@ -8645,6 +9420,7 @@ function childSlots(code, ip, out) {
|
|
|
8645
9420
|
case OP_LEAF:
|
|
8646
9421
|
case OP_SOURCE_LEAF:
|
|
8647
9422
|
case OP_ARMGATE:
|
|
9423
|
+
case OP_RGATE:
|
|
8648
9424
|
out.push(code[ip + 2]);
|
|
8649
9425
|
return true;
|
|
8650
9426
|
// `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
|
|
@@ -8728,6 +9504,42 @@ function reachableSites(code, roots) {
|
|
|
8728
9504
|
}
|
|
8729
9505
|
return seen;
|
|
8730
9506
|
}
|
|
9507
|
+
function passCollapse(code, ip, hostCst) {
|
|
9508
|
+
const flags = code[ip + 3];
|
|
9509
|
+
if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return false;
|
|
9510
|
+
if (flags !== 32 && flags !== 34) return false;
|
|
9511
|
+
let at = code[ip + 2];
|
|
9512
|
+
for (let n = 0; n < 8; n++) {
|
|
9513
|
+
const op = code[at];
|
|
9514
|
+
if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[at + 3] === 0) at = code[at + 2];
|
|
9515
|
+
else if (op === OP_RULE) at = code[at + 1];
|
|
9516
|
+
else break;
|
|
9517
|
+
}
|
|
9518
|
+
return code[at] === OP_NODE;
|
|
9519
|
+
}
|
|
9520
|
+
function gatedPassCollapse(code, ip, hostCst) {
|
|
9521
|
+
const flags = code[ip + 3];
|
|
9522
|
+
if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return void 0;
|
|
9523
|
+
if (flags !== 32 && flags !== 34) return void 0;
|
|
9524
|
+
const seq = code[ip + 2];
|
|
9525
|
+
if (code[seq] !== OP_SEQ && code[seq] !== OP_SEQV) return void 0;
|
|
9526
|
+
const n = code[seq + 1];
|
|
9527
|
+
if (n < 2) return void 0;
|
|
9528
|
+
const leads = [];
|
|
9529
|
+
const lits = [];
|
|
9530
|
+
for (let i = 0; i < n - 1; i++) {
|
|
9531
|
+
const t2 = code[seq + 2 + i];
|
|
9532
|
+
if (code[t2] !== OP_OPT && code[t2] !== OP_NOT) return void 0;
|
|
9533
|
+
const g = code[t2 + 1];
|
|
9534
|
+
if (code[g] === OP_GATE) leads.push(g);
|
|
9535
|
+
else if (code[g] === OP_LIT) lits.push(code[g + 1]);
|
|
9536
|
+
else return void 0;
|
|
9537
|
+
}
|
|
9538
|
+
const last = code[seq + 2 + n - 1];
|
|
9539
|
+
let at = last;
|
|
9540
|
+
for (let k = 0; k < 8 && (code[at] === OP_GATE || code[at] === OP_RULE); k++) at = code[at] === OP_RULE ? code[at + 1] : code[at + 2];
|
|
9541
|
+
return code[at] === OP_NODE ? { leads, lits, last } : void 0;
|
|
9542
|
+
}
|
|
8731
9543
|
function transfer(code, ip, at, hostCst) {
|
|
8732
9544
|
const op = code[ip];
|
|
8733
9545
|
if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
|
|
@@ -8739,14 +9551,18 @@ function transfer(code, ip, at, hostCst) {
|
|
|
8739
9551
|
}
|
|
8740
9552
|
if (op === OP_NODE || op === OP_NODE_TRACK) {
|
|
8741
9553
|
const flags = code[ip + 3];
|
|
9554
|
+
if (passCollapse(code, ip, hostCst)) return at;
|
|
9555
|
+
const gated = gatedPassCollapse(code, ip, hostCst) !== void 0;
|
|
8742
9556
|
const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && ((flags & ~128) === 2 || flags === 18 || flags === 34);
|
|
8743
9557
|
if (directChildren) {
|
|
8744
|
-
|
|
9558
|
+
const framed2 = { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
|
|
9559
|
+
return gated ? meet(at, framed2) : framed2;
|
|
8745
9560
|
}
|
|
8746
9561
|
const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
|
|
8747
9562
|
const raw = !hostCst && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags & 2) !== 0 ? RAW_OMIT : RAW_CAPTURE;
|
|
8748
9563
|
if (at.buf && raw === at.raw && cap === at.cap) return at;
|
|
8749
|
-
|
|
9564
|
+
const framed = { tri: at.tri, buf: true, raw, cap };
|
|
9565
|
+
return gated ? meet(at, framed) : framed;
|
|
8750
9566
|
}
|
|
8751
9567
|
if (op === OP_TOKEN) {
|
|
8752
9568
|
if (at.tri === TRI_NONE && !at.buf) return at;
|
|
@@ -8784,6 +9600,40 @@ function computeSiteLabels(code, roots, hostCst) {
|
|
|
8784
9600
|
}
|
|
8785
9601
|
return { at: (ip) => labels.get(ip) ?? TOP };
|
|
8786
9602
|
}
|
|
9603
|
+
function scopeIsIdentity(code, ip, at) {
|
|
9604
|
+
const op = code[ip];
|
|
9605
|
+
if (op !== OP_SCOPE_PLAIN && !(op === OP_SCOPE && code[ip + 3] === 0)) return false;
|
|
9606
|
+
const ki = code[ip + 1];
|
|
9607
|
+
return at.tri === (ki < 0 ? TRI_NONE : ki);
|
|
9608
|
+
}
|
|
9609
|
+
function scanHandoffNeeded(code, ip, labels) {
|
|
9610
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9611
|
+
const stack = [ip];
|
|
9612
|
+
const kids = [];
|
|
9613
|
+
while (stack.length > 0) {
|
|
9614
|
+
const at = stack.pop();
|
|
9615
|
+
if (seen.has(at)) continue;
|
|
9616
|
+
seen.add(at);
|
|
9617
|
+
const l = labels.at(at);
|
|
9618
|
+
if (l.tri === TRI_UNKNOWN) return true;
|
|
9619
|
+
const op = code[at];
|
|
9620
|
+
if (op === OP_SCAN) return true;
|
|
9621
|
+
if (op === OP_TOKEN || op === OP_SCOPE_CAP) continue;
|
|
9622
|
+
if ((op === OP_SCOPE_PLAIN || op === OP_SCOPE) && !(code[at + 1] >= 0 && l.tri === code[at + 1] && (op === OP_SCOPE_PLAIN || code[at + 3] === 0))) continue;
|
|
9623
|
+
kids.length = 0;
|
|
9624
|
+
if (!childSlots(code, at, kids)) return true;
|
|
9625
|
+
for (const c of kids) stack.push(c);
|
|
9626
|
+
}
|
|
9627
|
+
return false;
|
|
9628
|
+
}
|
|
9629
|
+
function triviaLeadRanges(tri, trivia2) {
|
|
9630
|
+
if (tri === TRI_NONE) return [];
|
|
9631
|
+
if (tri < 0) return void 0;
|
|
9632
|
+
const fs = trivia2[tri]?._meta.firstSet;
|
|
9633
|
+
if (fs === void 0) return void 0;
|
|
9634
|
+
if (fs.kind === "empty") return [];
|
|
9635
|
+
return fs.kind === "ranges" && fs.ranges !== void 0 ? fs.ranges : void 0;
|
|
9636
|
+
}
|
|
8787
9637
|
|
|
8788
9638
|
// src/table/scalar-terminal.ts
|
|
8789
9639
|
function makeScalarRecognizer(op, spec) {
|
|
@@ -8821,6 +9671,12 @@ function scalarTerminalNotChild(code, ip) {
|
|
|
8821
9671
|
const op = code[child];
|
|
8822
9672
|
return op === OP_RX || op === OP_LIT ? child : -1;
|
|
8823
9673
|
}
|
|
9674
|
+
function scalarTerminalPeekChild(code, ip) {
|
|
9675
|
+
if (code[ip] !== OP_PEEK) return -1;
|
|
9676
|
+
const child = code[ip + 1];
|
|
9677
|
+
const op = code[child];
|
|
9678
|
+
return op === OP_RX || op === OP_LIT ? child : -1;
|
|
9679
|
+
}
|
|
8824
9680
|
function leadingScalarTerminal(code, ip, minDepth = 2, throughAttempt = true, throughPeek = false) {
|
|
8825
9681
|
const seen = /* @__PURE__ */ new Set();
|
|
8826
9682
|
let at = ip;
|
|
@@ -8998,6 +9854,59 @@ function leadingTriviaFieldAt(code, k, ip) {
|
|
|
8998
9854
|
return code[ip] === OP_FIELD && (fieldSpec(k[code[ip + 1]]).bits & FIELD_LEADING_TRIVIA) !== 0;
|
|
8999
9855
|
}
|
|
9000
9856
|
|
|
9857
|
+
// src/table/hold-gap.ts
|
|
9858
|
+
var WRAPPERS = /* @__PURE__ */ new Set([
|
|
9859
|
+
OP_NODE,
|
|
9860
|
+
OP_XFORM,
|
|
9861
|
+
OP_LEAF,
|
|
9862
|
+
OP_SOURCE_LEAF,
|
|
9863
|
+
OP_TOKEN,
|
|
9864
|
+
OP_SCOPE,
|
|
9865
|
+
OP_SCOPE_CAP,
|
|
9866
|
+
OP_SCOPE_PLAIN,
|
|
9867
|
+
OP_FIELD,
|
|
9868
|
+
OP_LABEL,
|
|
9869
|
+
OP_EXPECT,
|
|
9870
|
+
OP_WITHCTX,
|
|
9871
|
+
OP_RULE,
|
|
9872
|
+
OP_ATTEMPT,
|
|
9873
|
+
OP_COV
|
|
9874
|
+
]);
|
|
9875
|
+
function rowNullable(code, k, ip, memo) {
|
|
9876
|
+
const hit = memo.get(ip);
|
|
9877
|
+
if (hit !== void 0) return hit;
|
|
9878
|
+
memo.set(ip, true);
|
|
9879
|
+
const op = code[ip];
|
|
9880
|
+
const kids = [];
|
|
9881
|
+
let out = true;
|
|
9882
|
+
if (op === OP_GATE) out = false;
|
|
9883
|
+
else if (op === OP_LIT || op === OP_LIT_CI) out = k[code[ip + 1]].length === 0;
|
|
9884
|
+
else if (op === OP_RX) {
|
|
9885
|
+
const re = k[code[ip + 1]];
|
|
9886
|
+
out = !(re instanceof RegExp) || regexCanMatchEmpty(re.source);
|
|
9887
|
+
} else if (op === OP_SEQ || op === OP_SEQV || op === OP_SEQX) {
|
|
9888
|
+
childSlots(code, ip, kids);
|
|
9889
|
+
out = kids.every((c) => rowNullable(code, k, c, memo));
|
|
9890
|
+
} else if (op === OP_CHOICE) {
|
|
9891
|
+
childSlots(code, ip, kids);
|
|
9892
|
+
out = kids.length === 0 || kids.some((c) => rowNullable(code, k, c, memo));
|
|
9893
|
+
} else if (op === OP_REP || op === OP_REPV) {
|
|
9894
|
+
out = code[ip + 2] === 0 || rowNullable(code, k, code[ip + 1], memo);
|
|
9895
|
+
} else if (WRAPPERS.has(op)) {
|
|
9896
|
+
if (childSlots(code, ip, kids) && kids.length === 1) out = rowNullable(code, k, kids[0], memo);
|
|
9897
|
+
}
|
|
9898
|
+
memo.set(ip, out);
|
|
9899
|
+
return out;
|
|
9900
|
+
}
|
|
9901
|
+
function holdsGap(code, k, base, n, i, memo) {
|
|
9902
|
+
if (i < 1 || i + 1 >= n) return false;
|
|
9903
|
+
const term = code[base + i];
|
|
9904
|
+
if (code[term] !== OP_NOT && code[term] !== OP_PEEK) return false;
|
|
9905
|
+
const next = code[base + i + 1];
|
|
9906
|
+
if (code[next] === OP_ADJ || leadingTriviaFieldAt(code, k, next)) return false;
|
|
9907
|
+
return !rowNullable(code, k, next, memo);
|
|
9908
|
+
}
|
|
9909
|
+
|
|
9001
9910
|
// src/table/emit-assembly.ts
|
|
9002
9911
|
var Unemittable = class extends Error {
|
|
9003
9912
|
construct;
|
|
@@ -9075,7 +9984,13 @@ var EMITTED_PARAMS = [
|
|
|
9075
9984
|
// Appended for trivia-attributing fields (`field(…, { leadingTrivia })`);
|
|
9076
9985
|
// old factories ignore them.
|
|
9077
9986
|
"LEAD",
|
|
9078
|
-
"triviaFieldCapture"
|
|
9987
|
+
"triviaFieldCapture",
|
|
9988
|
+
// Appended for the deferred-commit trivia skip (`trivia-gap.ts`); old
|
|
9989
|
+
// factories ignore it.
|
|
9990
|
+
"skipDeferredTrivia",
|
|
9991
|
+
// Appended for the pass-through collapse (`run-support.ts`); old factories
|
|
9992
|
+
// ignore it.
|
|
9993
|
+
"collapseEmpty"
|
|
9079
9994
|
];
|
|
9080
9995
|
var RUNTIME_PRELUDE = `
|
|
9081
9996
|
let _pfScan=null
|
|
@@ -9096,7 +10011,7 @@ function _skipTrivia(input,cur,ctx){
|
|
|
9096
10011
|
const s=_pfScan
|
|
9097
10012
|
if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
|
|
9098
10013
|
if(s!==null)return skipTriviaScanned(s,input,cur,ctx)
|
|
9099
|
-
if(needsDeferredTriviaCommit(ctx))return
|
|
10014
|
+
if(needsDeferredTriviaCommit(ctx))return skipDeferredTrivia(input,cur,ctx)
|
|
9100
10015
|
return advanceTrivia(input,cur,ctx)
|
|
9101
10016
|
}
|
|
9102
10017
|
function _pushLeaf(ctx,value,s,e){pushCstLeaf(ctx,{_tag:'leaf',value,span:{start:s,end:e}})}
|
|
@@ -9272,6 +10187,24 @@ ${fast}
|
|
|
9272
10187
|
${scanned}
|
|
9273
10188
|
}`;
|
|
9274
10189
|
}
|
|
10190
|
+
function emitHoldTerm(callee, dst, t2, l, skip) {
|
|
10191
|
+
const fast = `const ${t2}v=${callee}(input,cur,ctx)
|
|
10192
|
+
if(${t2}v===FAIL)return FAIL
|
|
10193
|
+
${dst}=${t2}v
|
|
10194
|
+
cur=EC.e`;
|
|
10195
|
+
if (l.tri === TRI_NONE) return fast;
|
|
10196
|
+
const held = `const ${t2}s=${skip}(input,cur,ctx)
|
|
10197
|
+
const ${t2}v=${callee}(input,${t2}s,ctx)
|
|
10198
|
+
if(${t2}v===FAIL)return FAIL
|
|
10199
|
+
${dst}=${t2}v
|
|
10200
|
+
cur=${t2}s`;
|
|
10201
|
+
if (l.tri !== TRI_UNKNOWN) return held;
|
|
10202
|
+
return `if(ctx.trivia===undefined){
|
|
10203
|
+
${fast}
|
|
10204
|
+
}else{
|
|
10205
|
+
${held}
|
|
10206
|
+
}`;
|
|
10207
|
+
}
|
|
9275
10208
|
function leadSkip(hasTrivia, leadTrivia, skip) {
|
|
9276
10209
|
if (hasTrivia === "false") return "{}";
|
|
9277
10210
|
const call = `itemStart=${skip}(input,itemStart,ctx)`;
|
|
@@ -9303,7 +10236,7 @@ function rebuildPools(cc, fx, disp, plan) {
|
|
|
9303
10236
|
})
|
|
9304
10237
|
};
|
|
9305
10238
|
}
|
|
9306
|
-
function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false) {
|
|
10239
|
+
function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false, select) {
|
|
9307
10240
|
const { code, k, fx, disp, dsp, triviaLabelled } = t2;
|
|
9308
10241
|
const swapLegal = !cfg.trackLines;
|
|
9309
10242
|
const hostCst = cfg.hostCst;
|
|
@@ -9313,6 +10246,7 @@ function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false) {
|
|
|
9313
10246
|
const reachable = [...reachableSites(code, roots)];
|
|
9314
10247
|
const labels = computeSiteLabels(code, roots, hostCst);
|
|
9315
10248
|
const scalarSpecs = /* @__PURE__ */ new Set();
|
|
10249
|
+
const nullable2 = /* @__PURE__ */ new Map();
|
|
9316
10250
|
const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
|
|
9317
10251
|
const largeChoiceLiteralFamilies = /* @__PURE__ */ new Map();
|
|
9318
10252
|
const largeChoiceScalarSequences = /* @__PURE__ */ new Map();
|
|
@@ -9402,6 +10336,8 @@ function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false) {
|
|
|
9402
10336
|
};
|
|
9403
10337
|
const bodies = [];
|
|
9404
10338
|
const byIp = /* @__PURE__ */ new Map();
|
|
10339
|
+
const externals = [];
|
|
10340
|
+
const siteBytes = /* @__PURE__ */ new Map();
|
|
9405
10341
|
const reached = /* @__PURE__ */ new Set();
|
|
9406
10342
|
const prelude = [];
|
|
9407
10343
|
const skipDefs = [];
|
|
@@ -9537,6 +10473,18 @@ return 1
|
|
|
9537
10473
|
tokenDecisionRefs.set(dispatchIp, made);
|
|
9538
10474
|
return made;
|
|
9539
10475
|
}
|
|
10476
|
+
function gateMissTest(gip) {
|
|
10477
|
+
const resolved = t2.cc[code[gip + 1]];
|
|
10478
|
+
const ci = classes.push([resolved]) - 1;
|
|
10479
|
+
classPlan.push([code[gip + 1]]);
|
|
10480
|
+
const cls = hoist("cl", `CLS[${ci}][0]`);
|
|
10481
|
+
return isAsciiOnlyClass(resolved) ? `${cls}.ascii[input.charCodeAt(pos)]!==1` : `!classHas(${cls},lead(input,pos))`;
|
|
10482
|
+
}
|
|
10483
|
+
function lookaheadMiss(child, miss) {
|
|
10484
|
+
if (code[child] !== OP_GATE || cfg.tolerant || cfg.probe) return "";
|
|
10485
|
+
return `if(${gateMissTest(child)}){${miss}}
|
|
10486
|
+
`;
|
|
10487
|
+
}
|
|
9540
10488
|
function skipFor(l) {
|
|
9541
10489
|
if (l.tri < 0) return "_skipTrivia";
|
|
9542
10490
|
const ki = l.tri;
|
|
@@ -9547,8 +10495,8 @@ return 1
|
|
|
9547
10495
|
const nm = `_sk${skipPool.size}`;
|
|
9548
10496
|
skipPool.set(key, nm);
|
|
9549
10497
|
if (!hasScan) {
|
|
9550
|
-
skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return
|
|
9551
|
-
if(needsDeferredTriviaCommit(ctx))return
|
|
10498
|
+
skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return skipDeferredTrivia(input,cur,ctx)}` : `function ${nm}(input,cur,ctx){
|
|
10499
|
+
if(needsDeferredTriviaCommit(ctx))return skipDeferredTrivia(input,cur,ctx)
|
|
9552
10500
|
return advanceTrivia(input,cur,ctx)}`);
|
|
9553
10501
|
return nm;
|
|
9554
10502
|
}
|
|
@@ -9593,9 +10541,17 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
9593
10541
|
const target = resolveAlias(ip);
|
|
9594
10542
|
const done = byIp.get(target);
|
|
9595
10543
|
if (done !== void 0) return done;
|
|
10544
|
+
if (select !== void 0 && !select.has(target)) {
|
|
10545
|
+
const ext = `_px${target}`;
|
|
10546
|
+
byIp.set(target, ext);
|
|
10547
|
+
externals.push(target);
|
|
10548
|
+
return ext;
|
|
10549
|
+
}
|
|
9596
10550
|
const fname = `_pf${target}`;
|
|
9597
10551
|
byIp.set(target, fname);
|
|
9598
|
-
|
|
10552
|
+
const body = lower(target, fname);
|
|
10553
|
+
siteBytes.set(target, body.length);
|
|
10554
|
+
bodies.push(body);
|
|
9599
10555
|
return fname;
|
|
9600
10556
|
}
|
|
9601
10557
|
function resolveAlias(ip) {
|
|
@@ -9615,9 +10571,7 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
9615
10571
|
const op = code[ip];
|
|
9616
10572
|
if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
|
|
9617
10573
|
if (op === OP_RULE) return code[ip + 1];
|
|
9618
|
-
if ((
|
|
9619
|
-
return code[ip + 2];
|
|
9620
|
-
}
|
|
10574
|
+
if (scopeIsIdentity(code, ip, labels.at(ip))) return code[ip + 2];
|
|
9621
10575
|
return void 0;
|
|
9622
10576
|
}
|
|
9623
10577
|
function lower(ip, fname) {
|
|
@@ -9735,14 +10689,44 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
9735
10689
|
return `${head}EC.e=pos;return ''}`;
|
|
9736
10690
|
case OP_GATE: {
|
|
9737
10691
|
const child = link(code[ip + 2]);
|
|
10692
|
+
const xf = fxRef(code[ip + 3]);
|
|
10693
|
+
return `${head}
|
|
10694
|
+
if(${gateMissTest(ip)}){ctx._fe=pos;ctx._fx=${xf};return FAIL}
|
|
10695
|
+
return ${child}(input,pos,ctx)
|
|
10696
|
+
}`;
|
|
10697
|
+
}
|
|
10698
|
+
case OP_RGATE: {
|
|
10699
|
+
const child = link(code[ip + 2]);
|
|
10700
|
+
if (cfg.tolerant || cfg.probe) return `${head}
|
|
10701
|
+
return ${child}(input,pos,ctx)
|
|
10702
|
+
}`;
|
|
9738
10703
|
const resolved = t2.cc[code[ip + 1]];
|
|
9739
10704
|
const ci = classes.push([resolved]) - 1;
|
|
9740
10705
|
classPlan.push([code[ip + 1]]);
|
|
9741
10706
|
const cls = hoist("cl", `CLS[${ci}][0]`);
|
|
9742
10707
|
const xf = fxRef(code[ip + 3]);
|
|
9743
10708
|
return `${head}
|
|
9744
|
-
|
|
10709
|
+
const it=ctx._routed
|
|
10710
|
+
if(it!==undefined&&it.span.start===pos&&!classHas(${cls},lead(input,it.span.end))){ctx._fe=it.span.end;ctx._fx=${xf};return FAIL}
|
|
10711
|
+
return ${child}(input,pos,ctx)
|
|
10712
|
+
}`;
|
|
10713
|
+
}
|
|
10714
|
+
case OP_ARMGATE: {
|
|
10715
|
+
const pred = fnRef(code[ip + 1]);
|
|
10716
|
+
const child = link(code[ip + 2]);
|
|
10717
|
+
const xf = fxRef(code[ip + 3]);
|
|
10718
|
+
return `${head}
|
|
10719
|
+
if(!${pred}(ctx.state)){ctx._fc=false;ctx._fe=-1;ctx._fx=${xf};return FAIL}
|
|
9745
10720
|
return ${child}(input,pos,ctx)
|
|
10721
|
+
}`;
|
|
10722
|
+
}
|
|
10723
|
+
case OP_WITHCTX: {
|
|
10724
|
+
const ki = code[ip + 1];
|
|
10725
|
+
const child = link(code[ip + 2]);
|
|
10726
|
+
return `${head}
|
|
10727
|
+
const saved=ctx.state
|
|
10728
|
+
ctx.state=${ki < 0 ? `${fnRef(~ki)}(saved)` : kRef(ki)}
|
|
10729
|
+
try{return ${child}(input,pos,ctx)}finally{ctx.state=saved}
|
|
9746
10730
|
}`;
|
|
9747
10731
|
}
|
|
9748
10732
|
case OP_XFORM: {
|
|
@@ -9998,24 +10982,34 @@ return FAIL
|
|
|
9998
10982
|
const xf = fxRef(code[ip + 2]);
|
|
9999
10983
|
const p = tmp();
|
|
10000
10984
|
return `${head}
|
|
10001
|
-
${emitMark(p, L.buf, L.raw, sinks)}
|
|
10002
|
-
const v=${child}(input,pos,ctx)
|
|
10985
|
+
${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${emitMark(p, L.buf, L.raw, sinks)}
|
|
10986
|
+
${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
|
|
10003
10987
|
${emitRollback(p, L.buf, L.raw, sinks)}
|
|
10004
|
-
if(v===FAIL){EC.e=pos;return null}
|
|
10988
|
+
${cfg.probe ? "if(ctx._probe!==undefined)ctx._probe.best=pb??null\n" : ""}if(v===FAIL){EC.e=pos;return null}
|
|
10005
10989
|
ctx._fe=pos
|
|
10006
10990
|
ctx._fx=${xf}
|
|
10007
10991
|
return FAIL
|
|
10008
10992
|
}`;
|
|
10009
10993
|
}
|
|
10010
10994
|
case OP_PEEK: {
|
|
10995
|
+
const scalarChild = scalarTerminalPeekChild(code, ip);
|
|
10996
|
+
if (scalarChild >= 0) {
|
|
10997
|
+
const recognize = recognizerRef(code[scalarChild + 1]);
|
|
10998
|
+
const xf2 = fxRef(code[ip + 2]);
|
|
10999
|
+
return `${head}
|
|
11000
|
+
if(${recognize}(input,pos)<0){ctx._fe=pos;ctx._fx=${xf2};return FAIL}
|
|
11001
|
+
EC.e=pos
|
|
11002
|
+
return null
|
|
11003
|
+
}`;
|
|
11004
|
+
}
|
|
10011
11005
|
const child = link(code[ip + 1]);
|
|
10012
11006
|
const xf = fxRef(code[ip + 2]);
|
|
10013
11007
|
const p = tmp();
|
|
10014
11008
|
return `${head}
|
|
10015
|
-
${emitMark(p, L.buf, L.raw, sinks)}
|
|
10016
|
-
const v=${child}(input,pos,ctx)
|
|
11009
|
+
${lookaheadMiss(code[ip + 1], `ctx._fe=pos;ctx._fx=${xf};return FAIL`)}${emitMark(p, L.buf, L.raw, sinks)}
|
|
11010
|
+
${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
|
|
10017
11011
|
${emitRollback(p, L.buf, L.raw, sinks)}
|
|
10018
|
-
if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
|
|
11012
|
+
${cfg.probe ? "if(ctx._probe!==undefined)ctx._probe.best=pb??null\n" : ""}if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
|
|
10019
11013
|
EC.e=pos
|
|
10020
11014
|
return null
|
|
10021
11015
|
}`;
|
|
@@ -10025,7 +11019,7 @@ return null
|
|
|
10025
11019
|
const clean = !REC && failureRollbackClean(prog, ip);
|
|
10026
11020
|
const p = tmp();
|
|
10027
11021
|
return `${head}
|
|
10028
|
-
${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
|
|
11022
|
+
${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
|
|
10029
11023
|
ctx._fc=false
|
|
10030
11024
|
const v=${child}(input,pos,ctx)
|
|
10031
11025
|
if(v===FAIL){
|
|
@@ -10086,7 +11080,7 @@ return v
|
|
|
10086
11080
|
);
|
|
10087
11081
|
} else {
|
|
10088
11082
|
const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
|
|
10089
|
-
parts.push(emitTerm(callee, vn, tmp(), L, skipFor(L)));
|
|
11083
|
+
parts.push(holdsGap(code, k, base, n, i, nullable2) ? emitHoldTerm(callee, vn, tmp(), L, skipFor(L)) : emitTerm(callee, vn, tmp(), L, skipFor(L)));
|
|
10090
11084
|
}
|
|
10091
11085
|
names.push(vn);
|
|
10092
11086
|
}
|
|
@@ -10106,7 +11100,7 @@ return v
|
|
|
10106
11100
|
const asc = hoist("as", `DISP[${di}].ascii`);
|
|
10107
11101
|
const hiArr = table.hi;
|
|
10108
11102
|
const armSwitch = arms.map((a, i) => `case ${i}:v=${a}(input,pos,ctx);break`).join("\n");
|
|
10109
|
-
const directAscii =
|
|
11103
|
+
const directAscii = table.hi.length === 0;
|
|
10110
11104
|
return `${head}
|
|
10111
11105
|
const c=${directAscii ? "input.charCodeAt(pos)" : "lead(input,pos)"}
|
|
10112
11106
|
let arm=-1
|
|
@@ -10133,7 +11127,7 @@ return FAIL
|
|
|
10133
11127
|
const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
|
|
10134
11128
|
const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
|
|
10135
11129
|
const maskable = n <= 32;
|
|
10136
|
-
const directAsciiMask =
|
|
11130
|
+
const directAsciiMask = maskable && gates.every(isAsciiOnlyClass);
|
|
10137
11131
|
const gateRefs = directAsciiMask ? [] : Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
|
|
10138
11132
|
const tokenCandidate = tokenChoiceCandidates.get(ip);
|
|
10139
11133
|
const pretests = Array.from({ length: n }, (_, i) => {
|
|
@@ -10175,7 +11169,7 @@ return FAIL
|
|
|
10175
11169
|
if (choiceCannotCommit(prog, ip) && !startFailureExact) {
|
|
10176
11170
|
const deepAt = Array.from({ length: n }, () => tmp());
|
|
10177
11171
|
const deepFx = Array.from({ length: n }, () => tmp());
|
|
10178
|
-
const
|
|
11172
|
+
const remember2 = (i, at, expectedSet) => `${deepAt[i]}=${at};${deepFx[i]}=${expectedSet}`;
|
|
10179
11173
|
const lazyArms = (ascii) => arms.map((arm, i) => {
|
|
10180
11174
|
const pretest = pretests[i];
|
|
10181
11175
|
const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
|
|
@@ -10187,13 +11181,13 @@ return FAIL
|
|
|
10187
11181
|
if(${decision}===0){
|
|
10188
11182
|
ctx._fc=false
|
|
10189
11183
|
{const at=_pfTokEnd
|
|
10190
|
-
${
|
|
11184
|
+
${remember2(i, "at", pretest.token.expected)}}
|
|
10191
11185
|
}`;
|
|
10192
11186
|
const sequenceMiss = pretest?.sequence === void 0 ? "" : `
|
|
10193
11187
|
else if(${ascii ? `(bits&${1 << i})!==0&&` : ""}${decision}<0){
|
|
10194
11188
|
ctx._fc=false
|
|
10195
11189
|
{const at=_pfSeqEnd
|
|
10196
|
-
${
|
|
11190
|
+
${remember2(i, "at", pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("") + pretest.sequence.expected.at(-1))}}
|
|
10197
11191
|
}`;
|
|
10198
11192
|
return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
|
|
10199
11193
|
`}if(${gate}){
|
|
@@ -10201,7 +11195,7 @@ ctx._fc=false
|
|
|
10201
11195
|
{const v=${arm}(input,pos,ctx)
|
|
10202
11196
|
if(v!==FAIL)return v}
|
|
10203
11197
|
{const at=ctx._fe??pos
|
|
10204
|
-
${
|
|
11198
|
+
${remember2(i, "at", "ctx._fx")}}
|
|
10205
11199
|
${rollbackFor(i)}
|
|
10206
11200
|
}${routeMiss}${sequenceMiss}`;
|
|
10207
11201
|
}).join("\n");
|
|
@@ -10314,7 +11308,7 @@ const bits=${maskName}[${directAsciiMask ? "c" : "c<0?128:c"}]
|
|
|
10314
11308
|
if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
|
|
10315
11309
|
${startFailureExact ? "" : "let prev=0"}
|
|
10316
11310
|
${maskArms}
|
|
10317
|
-
${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${n},prev,acc)`}
|
|
11311
|
+
${startFailureExact ? "" : `if(best===pos&&prev!==0)acc=${catchName}(${n},prev,acc)`}
|
|
10318
11312
|
ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
|
|
10319
11313
|
return FAIL
|
|
10320
11314
|
}
|
|
@@ -10413,7 +11407,7 @@ return [key,v]
|
|
|
10413
11407
|
const ci = classes.push([resolved]) - 1;
|
|
10414
11408
|
classPlan.push([itemClassIndex]);
|
|
10415
11409
|
itemCls = hoist("ri", `CLS[${ci}][0]`);
|
|
10416
|
-
itemAscii =
|
|
11410
|
+
itemAscii = isAsciiOnlyClass(resolved);
|
|
10417
11411
|
}
|
|
10418
11412
|
}
|
|
10419
11413
|
const itemMiss = (at) => itemAscii ? `${itemCls}.ascii[input.charCodeAt(${at})]!==1` : `!classHas(${itemCls},lead(input,${at}))`;
|
|
@@ -10569,6 +11563,26 @@ return nd
|
|
|
10569
11563
|
const trailingTrivia = (flags & 128) !== 0;
|
|
10570
11564
|
const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
|
|
10571
11565
|
const leanFlags = flags & ~128;
|
|
11566
|
+
if (build !== void 0 && passCollapse(code, ip, hostCst)) {
|
|
11567
|
+
return `${head}
|
|
11568
|
+
const v=${child}(input,pos,ctx)
|
|
11569
|
+
if(v!==undefined)return v
|
|
11570
|
+
return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
|
|
11571
|
+
}`;
|
|
11572
|
+
}
|
|
11573
|
+
const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
|
|
11574
|
+
const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(labels.at(code[ip + 2]).tri, t2.trivia);
|
|
11575
|
+
const gp = gated !== void 0 && triviaLead !== void 0 && triviaLead.length <= 16 ? `const gc=lead(input,pos)
|
|
11576
|
+
if(!(${[
|
|
11577
|
+
...gated.leads.map((g) => `!(${gateMissTest(g)})`),
|
|
11578
|
+
...gated.lits.map((i) => `gc===${k[i].codePointAt(0)}`),
|
|
11579
|
+
...triviaLead.map((r) => r.lo === r.hi ? `gc===${r.lo}` : `(gc>=${r.lo}&&gc<=${r.hi})`)
|
|
11580
|
+
].join("||") || "false"})){
|
|
11581
|
+
const gv=${link(gated.last)}(input,pos,ctx)
|
|
11582
|
+
if(gv!==undefined)return gv
|
|
11583
|
+
return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
|
|
11584
|
+
}
|
|
11585
|
+
` : "";
|
|
10572
11586
|
if (!hostCst && !tracked && build !== void 0 && proj < 0 && (leanFlags === 2 || (flags === 18 || flags === 34))) {
|
|
10573
11587
|
const fields = flags === 18;
|
|
10574
11588
|
const collapseChildren = flags === 34;
|
|
@@ -10603,7 +11617,7 @@ sCh.push(nd)
|
|
|
10603
11617
|
if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
|
|
10604
11618
|
}`;
|
|
10605
11619
|
return `${head}
|
|
10606
|
-
const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
11620
|
+
${gp}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
10607
11621
|
const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
|
|
10608
11622
|
const flat=[]
|
|
10609
11623
|
ctx._cstBuf=undefined
|
|
@@ -10639,7 +11653,7 @@ return nd
|
|
|
10639
11653
|
const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
|
|
10640
11654
|
const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
|
|
10641
11655
|
const ty = q(type);
|
|
10642
|
-
const stArg =
|
|
11656
|
+
const stArg = "ctx.state";
|
|
10643
11657
|
const hostCall = `_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,${stArg},${tags})`;
|
|
10644
11658
|
let value;
|
|
10645
11659
|
if (proj >= 0) {
|
|
@@ -10678,7 +11692,7 @@ const hostKids=kids
|
|
|
10678
11692
|
const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
|
|
10679
11693
|
const tlog=buf.tl??EMPTY_TLOG`;
|
|
10680
11694
|
return `${head}
|
|
10681
|
-
const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
11695
|
+
${!hostCst && !tracked ? gp : ""}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
10682
11696
|
const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf
|
|
10683
11697
|
${openCapture}
|
|
10684
11698
|
ctx.captureTrivia=${captureWide}
|
|
@@ -10700,7 +11714,7 @@ ctx.captureTrivia=sCap
|
|
|
10700
11714
|
if(v===FAIL)return FAIL
|
|
10701
11715
|
const end=EC.e
|
|
10702
11716
|
const span=${tracked ? "spanLines(ctx,pos,end)" : "{start:pos,end}"}
|
|
10703
|
-
const st=${readsState ? "
|
|
11717
|
+
const st=${readsState ? "ctx.state" : "undefined"}
|
|
10704
11718
|
let nd
|
|
10705
11719
|
${unwrap ? "if(kids.length===1)nd=unwrapChild(kids[0])\nelse " : ""}${collapse ? "if(kids.length===1)nd=kids[0]\nelse " : ""}${collapsible ? `if(_pfHost!==undefined&&_pfHost._parsemanCstCollapse!==undefined&&kids.length===1&&rawKids.length===1&&_pfHost._parsemanCstCollapse(${ty},kids[0],kids,rawKids))nd=kids[0]
|
|
10706
11720
|
else ` : ""}{${value}}
|
|
@@ -10713,21 +11727,57 @@ return nd
|
|
|
10713
11727
|
throw new Unemittable(`OP_${OP_NAMES[op] ?? String(op)}`);
|
|
10714
11728
|
}
|
|
10715
11729
|
}
|
|
11730
|
+
const served = (ip) => select === void 0 || select.has(resolveAlias(ip));
|
|
10716
11731
|
const ruleEntries = [];
|
|
10717
11732
|
for (const [rname, entryIp] of Object.entries(prog.rules)) {
|
|
11733
|
+
if (!served(entryIp)) continue;
|
|
10718
11734
|
const target = link(entryIp);
|
|
10719
11735
|
const rn = `_r_${rname.replace(/[^A-Za-z0-9_$]/g, "_")}`;
|
|
10720
11736
|
bodies.push(`const ${rn}=${target}`);
|
|
10721
11737
|
ruleEntries.push(`${q(rname)}:${rn}`);
|
|
10722
11738
|
}
|
|
10723
11739
|
const extra = [];
|
|
10724
|
-
|
|
11740
|
+
const exported = /* @__PURE__ */ new Set();
|
|
11741
|
+
for (const ip of extraIps) {
|
|
11742
|
+
if (!served(ip)) continue;
|
|
11743
|
+
exported.add(ip);
|
|
11744
|
+
extra.push(`${ip}:${link(ip)}`);
|
|
11745
|
+
}
|
|
11746
|
+
if (select !== void 0) {
|
|
11747
|
+
const kids = [];
|
|
11748
|
+
for (const ip of reachable) {
|
|
11749
|
+
if (select.has(resolveAlias(ip))) continue;
|
|
11750
|
+
kids.length = 0;
|
|
11751
|
+
childSlots(code, ip, kids);
|
|
11752
|
+
for (const kid of kids) {
|
|
11753
|
+
const target = resolveAlias(kid);
|
|
11754
|
+
if (!select.has(target) || exported.has(target)) continue;
|
|
11755
|
+
exported.add(target);
|
|
11756
|
+
extra.push(`${target}:${link(target)}`);
|
|
11757
|
+
}
|
|
11758
|
+
}
|
|
11759
|
+
}
|
|
11760
|
+
const hybrid = select === void 0 ? "" : `,
|
|
11761
|
+
ext:[${externals.join(",")}],
|
|
11762
|
+
bind:function(xs,ps){_xScan=xs
|
|
11763
|
+
${externals.map((ip, i) => `_xp${ip}=ps[${i}]`).join("\n")}},
|
|
11764
|
+
scan:function(s){const o=_pfScan;_pfScan=s;return o}`;
|
|
11765
|
+
const scannerFor = (ip) => {
|
|
11766
|
+
const ki = labels.at(ip).tri;
|
|
11767
|
+
if (ki === TRI_UNKNOWN) return "_pfScan";
|
|
11768
|
+
if (ki === TRI_NONE) return "null";
|
|
11769
|
+
return swapLegal && !triviaLabelled[ki] && t2.triviaScan[ki] != null ? hoist("ts", `TRIVIASCAN[${ki}]`) : "null";
|
|
11770
|
+
};
|
|
11771
|
+
const externalDefs = select === void 0 ? "" : `let _xScan
|
|
11772
|
+
${externals.map((ip) => `let _xp${ip}
|
|
11773
|
+
function _px${ip}(input,pos,ctx){const o=_xScan(${scannerFor(ip)});const v=_xp${ip}(input,pos,ctx);_xScan(o);return v}`).join("\n")}
|
|
11774
|
+
`;
|
|
10725
11775
|
const source = `${RUNTIME_PRELUDE}${needsNoRawPrelude ? NO_RAW_RUNTIME_PRELUDE : ""}
|
|
10726
11776
|
${prelude.join("\n")}
|
|
10727
11777
|
${skipDefs.join("\n")}
|
|
10728
11778
|
${choiceDefs.join("\n")}
|
|
10729
11779
|
${bodies.join("\n")}
|
|
10730
|
-
function _begin(ctx){
|
|
11780
|
+
${externalDefs}function _begin(ctx){
|
|
10731
11781
|
const host=ctx.build
|
|
10732
11782
|
if(_pfDepth>0)_pfFrames.push([_pfScan,_pfHost,EC.e])
|
|
10733
11783
|
_pfDepth++
|
|
@@ -10754,7 +11804,7 @@ pieces:{${ruleEntries.join(",")}},
|
|
|
10754
11804
|
byIp:{${extra.join(",")}},
|
|
10755
11805
|
end:function(){return EC.e},
|
|
10756
11806
|
begin:_begin,
|
|
10757
|
-
finish:_finish
|
|
11807
|
+
finish:_finish${hybrid}
|
|
10758
11808
|
}`;
|
|
10759
11809
|
return {
|
|
10760
11810
|
source,
|
|
@@ -10762,6 +11812,7 @@ finish:_finish
|
|
|
10762
11812
|
masks,
|
|
10763
11813
|
classes,
|
|
10764
11814
|
armExpected,
|
|
11815
|
+
siteBytes,
|
|
10765
11816
|
plan: { classes: classPlan, armExpected: armExpectedPlan, masks: maskPlan }
|
|
10766
11817
|
};
|
|
10767
11818
|
}
|
|
@@ -10982,187 +12033,57 @@ function literal(value, opts = {}) {
|
|
|
10982
12033
|
})() : (input, pos, ctx) => {
|
|
10983
12034
|
const end = pos + value.length;
|
|
10984
12035
|
if (end <= input.length) {
|
|
10985
|
-
const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
|
|
10986
|
-
if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
|
|
10987
|
-
ctx._sv = matchedValue;
|
|
10988
|
-
return end;
|
|
10989
|
-
}
|
|
10990
|
-
}
|
|
10991
|
-
ctx._fx = expected;
|
|
10992
|
-
return ~pos;
|
|
10993
|
-
};
|
|
10994
|
-
if (caseInsensitive) {
|
|
10995
|
-
const upper = value.toUpperCase();
|
|
10996
|
-
const lower = value.toLowerCase();
|
|
10997
|
-
const firstUpper = upper.codePointAt(0);
|
|
10998
|
-
const firstLower = lower.codePointAt(0);
|
|
10999
|
-
meta.firstSet = firstLower !== void 0 && firstUpper !== void 0 ? firstLower === firstUpper ? { kind: "ranges", ranges: [{ lo: firstLower, hi: firstLower }] } : { kind: "ranges", ranges: [
|
|
11000
|
-
{ lo: firstLower, hi: firstLower },
|
|
11001
|
-
{ lo: firstUpper, hi: firstUpper }
|
|
11002
|
-
] } : firstSet2;
|
|
11003
|
-
}
|
|
11004
|
-
const expected = directTerminalFailureExpected({ tag: "literal", value, caseInsensitive });
|
|
11005
|
-
const parse2 = !caseInsensitive && value.length === 1 ? (() => {
|
|
11006
|
-
const code = value.charCodeAt(0);
|
|
11007
|
-
return function parse3(input, pos, ctx) {
|
|
11008
|
-
if (input.charCodeAt(pos) === code) {
|
|
11009
|
-
const span = { start: pos, end: pos + 1 };
|
|
11010
|
-
if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
|
|
11011
|
-
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
|
|
11012
|
-
return { ok: true, value, span };
|
|
11013
|
-
}
|
|
11014
|
-
return failAt(ctx, expected, pos);
|
|
11015
|
-
};
|
|
11016
|
-
})() : function parse3(input, pos, ctx) {
|
|
11017
|
-
const end = pos + value.length;
|
|
11018
|
-
if (end > input.length) {
|
|
11019
|
-
return failAt(ctx, expected, pos);
|
|
11020
|
-
}
|
|
11021
|
-
const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
|
|
11022
|
-
if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
|
|
11023
|
-
const span = { start: pos, end };
|
|
11024
|
-
if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, end);
|
|
11025
|
-
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: matchedValue, span });
|
|
11026
|
-
return { ok: true, value: matchedValue, span };
|
|
11027
|
-
}
|
|
11028
|
-
return failAt(ctx, expected, pos);
|
|
11029
|
-
};
|
|
11030
|
-
return {
|
|
11031
|
-
_tag: "literal",
|
|
11032
|
-
_meta: meta,
|
|
11033
|
-
_def: { tag: "literal", value, caseInsensitive },
|
|
11034
|
-
_parseScalar: parseScalar,
|
|
11035
|
-
parse: parse2
|
|
11036
|
-
};
|
|
11037
|
-
}
|
|
11038
|
-
|
|
11039
|
-
// src/combinators/sequence.ts
|
|
11040
|
-
function sequence(...parsers) {
|
|
11041
|
-
let adjacency = null;
|
|
11042
|
-
for (let i = 0; i < parsers.length; i++) {
|
|
11043
|
-
const a = adjacencyOf(parsers[i]);
|
|
11044
|
-
if (a === null) continue;
|
|
11045
|
-
if (i === 0) {
|
|
11046
|
-
throw new TypeError(
|
|
11047
|
-
`sequence(): ${a.polarity}() cannot be the FIRST term \u2014 an adjacency assertion tests the gap after the PRECEDING term. Put a concrete term first.`
|
|
11048
|
-
);
|
|
11049
|
-
}
|
|
11050
|
-
;
|
|
11051
|
-
(adjacency ??= Array.from({ length: parsers.length }, () => null))[i] = a;
|
|
11052
|
-
}
|
|
11053
|
-
const hasAdjacency = adjacency !== null;
|
|
11054
|
-
let leading = null;
|
|
11055
|
-
for (let i = 1; i < parsers.length; i++) {
|
|
11056
|
-
if (leadsTrivia(parsers[i])) (leading ??= Array.from({ length: parsers.length }, () => false))[i] = true;
|
|
11057
|
-
}
|
|
11058
|
-
const strictArity = !hasAdjacency && (parsers.length === 2 && !matchesEmpty(parsers[1]) || parsers.length === 3 && parsers.every((p) => !matchesEmpty(p))) ? parsers.length : 0;
|
|
11059
|
-
const meta = {
|
|
11060
|
-
// Union through the nullable prefix — a leading optional()/many() lets a later
|
|
11061
|
-
// term's first char start the sequence. Just `parsers[0]` under-approximates.
|
|
11062
|
-
firstSet: sequenceFirstSet(parsers),
|
|
11063
|
-
canMatchNewline: parsers.some((p) => p._meta.canMatchNewline),
|
|
11064
|
-
isTrivia: false
|
|
11065
|
-
};
|
|
11066
|
-
const def = { tag: "sequence", parsers };
|
|
11067
|
-
const scalarParsers = parsers.map(scalarOf);
|
|
11068
|
-
const parseScalar = (input, pos, ctx) => {
|
|
11069
|
-
let cur = pos;
|
|
11070
|
-
if (strictArity !== 0) {
|
|
11071
|
-
cur = scalarParsers[0](input, cur, ctx);
|
|
11072
|
-
if (cur < 0) return cur;
|
|
11073
|
-
const first = ctx._sv;
|
|
11074
|
-
if (ctx.trivia) cur = advanceTrivia(input, cur, ctx);
|
|
11075
|
-
cur = scalarParsers[1](input, cur, ctx);
|
|
11076
|
-
if (cur < 0) return cur;
|
|
11077
|
-
const second = ctx._sv;
|
|
11078
|
-
if (strictArity === 2) {
|
|
11079
|
-
ctx._sv = def.valueUnused ? void 0 : [first, second];
|
|
11080
|
-
return cur;
|
|
12036
|
+
const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
|
|
12037
|
+
if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
|
|
12038
|
+
ctx._sv = matchedValue;
|
|
12039
|
+
return end;
|
|
11081
12040
|
}
|
|
11082
|
-
if (ctx.trivia) cur = advanceTrivia(input, cur, ctx);
|
|
11083
|
-
cur = scalarParsers[2](input, cur, ctx);
|
|
11084
|
-
if (cur < 0) return cur;
|
|
11085
|
-
ctx._sv = def.valueUnused ? void 0 : [first, second, ctx._sv];
|
|
11086
|
-
return cur;
|
|
11087
12041
|
}
|
|
11088
|
-
|
|
11089
|
-
|
|
11090
|
-
|
|
11091
|
-
|
|
11092
|
-
|
|
11093
|
-
|
|
11094
|
-
|
|
11095
|
-
|
|
12042
|
+
ctx._fx = expected;
|
|
12043
|
+
return ~pos;
|
|
12044
|
+
};
|
|
12045
|
+
if (caseInsensitive) {
|
|
12046
|
+
const upper = value.toUpperCase();
|
|
12047
|
+
const lower = value.toLowerCase();
|
|
12048
|
+
const firstUpper = upper.codePointAt(0);
|
|
12049
|
+
const firstLower = lower.codePointAt(0);
|
|
12050
|
+
meta.firstSet = firstLower !== void 0 && firstUpper !== void 0 ? firstLower === firstUpper ? { kind: "ranges", ranges: [{ lo: firstLower, hi: firstLower }] } : { kind: "ranges", ranges: [
|
|
12051
|
+
{ lo: firstLower, hi: firstLower },
|
|
12052
|
+
{ lo: firstUpper, hi: firstUpper }
|
|
12053
|
+
] } : firstSet2;
|
|
12054
|
+
}
|
|
12055
|
+
const expected = directTerminalFailureExpected({ tag: "literal", value, caseInsensitive });
|
|
12056
|
+
const parse2 = !caseInsensitive && value.length === 1 ? (() => {
|
|
12057
|
+
const code = value.charCodeAt(0);
|
|
12058
|
+
return function parse3(input, pos, ctx) {
|
|
12059
|
+
if (input.charCodeAt(pos) === code) {
|
|
12060
|
+
const span = { start: pos, end: pos + 1 };
|
|
12061
|
+
if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
|
|
12062
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
|
|
12063
|
+
return { ok: true, value, span };
|
|
12064
|
+
}
|
|
12065
|
+
return failAt(ctx, expected, pos);
|
|
12066
|
+
};
|
|
12067
|
+
})() : function parse3(input, pos, ctx) {
|
|
12068
|
+
const end = pos + value.length;
|
|
12069
|
+
if (end > input.length) {
|
|
12070
|
+
return failAt(ctx, expected, pos);
|
|
11096
12071
|
}
|
|
11097
|
-
|
|
11098
|
-
|
|
12072
|
+
const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
|
|
12073
|
+
if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
|
|
12074
|
+
const span = { start: pos, end };
|
|
12075
|
+
if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, end);
|
|
12076
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: matchedValue, span });
|
|
12077
|
+
return { ok: true, value: matchedValue, span };
|
|
12078
|
+
}
|
|
12079
|
+
return failAt(ctx, expected, pos);
|
|
11099
12080
|
};
|
|
11100
|
-
let followSentinels;
|
|
11101
12081
|
return {
|
|
11102
|
-
_tag: "
|
|
12082
|
+
_tag: "literal",
|
|
11103
12083
|
_meta: meta,
|
|
11104
|
-
_def:
|
|
11105
|
-
_parseScalar:
|
|
11106
|
-
parse
|
|
11107
|
-
const tolerant = ctx._tolerant === true;
|
|
11108
|
-
if (tolerant) {
|
|
11109
|
-
followSentinels ??= parsers.map((_, i) => firstSetSentinel(
|
|
11110
|
-
parsers.slice(i + 1).reduce(
|
|
11111
|
-
(set, parser2) => union(set, firstSetOf(parser2)),
|
|
11112
|
-
{ kind: "empty" }
|
|
11113
|
-
)
|
|
11114
|
-
));
|
|
11115
|
-
}
|
|
11116
|
-
const inheritedSync = ctx._sync;
|
|
11117
|
-
const deferredTrivia = needsDeferredTriviaCommit(ctx);
|
|
11118
|
-
const values = def.valueUnused ? void 0 : [];
|
|
11119
|
-
let cur = pos;
|
|
11120
|
-
try {
|
|
11121
|
-
for (let i = 0; i < parsers.length; i++) {
|
|
11122
|
-
if (tolerant) ctx._sync = followSentinels[i] ?? inheritedSync;
|
|
11123
|
-
const assertion = adjacency?.[i];
|
|
11124
|
-
if (assertion) {
|
|
11125
|
-
if (!holdsAdjacency(input, cur, ctx, assertion)) return adjacencyFail(cur, assertion);
|
|
11126
|
-
if (values !== void 0) values.push(null);
|
|
11127
|
-
continue;
|
|
11128
|
-
}
|
|
11129
|
-
let termPos = cur;
|
|
11130
|
-
const markTlog = deferredTrivia ? cstTlLen(ctx) : 0;
|
|
11131
|
-
const markLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
|
|
11132
|
-
const markRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
11133
|
-
if (ctx.trivia && i > 0) {
|
|
11134
|
-
termPos = deferredTrivia ? commitTriviaScan(scanTriviaCompact(input, cur, ctx)) : advanceTrivia(input, cur, ctx);
|
|
11135
|
-
}
|
|
11136
|
-
const scanTlog = deferredTrivia ? cstTlLen(ctx) : 0;
|
|
11137
|
-
const scanLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
|
|
11138
|
-
const scanRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
11139
|
-
if (leading?.[i] === true) LEAD.at = cur;
|
|
11140
|
-
const result = parsers[i].parse(input, termPos, ctx);
|
|
11141
|
-
if (!result.ok) return result;
|
|
11142
|
-
if (values !== void 0) values.push(result.value);
|
|
11143
|
-
if (result.span.end > termPos || termPos === cur) cur = result.span.end;
|
|
11144
|
-
else if (deferredTrivia) {
|
|
11145
|
-
rollbackScannedTriviaAt(
|
|
11146
|
-
ctx,
|
|
11147
|
-
markTlog,
|
|
11148
|
-
scanTlog,
|
|
11149
|
-
markLog,
|
|
11150
|
-
scanLog,
|
|
11151
|
-
markRootLog,
|
|
11152
|
-
scanRootLog
|
|
11153
|
-
);
|
|
11154
|
-
}
|
|
11155
|
-
}
|
|
11156
|
-
} finally {
|
|
11157
|
-
if (tolerant) ctx._sync = inheritedSync;
|
|
11158
|
-
}
|
|
11159
|
-
return {
|
|
11160
|
-
ok: true,
|
|
11161
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
11162
|
-
value: values ?? void 0,
|
|
11163
|
-
span: { start: pos, end: cur }
|
|
11164
|
-
};
|
|
11165
|
-
}
|
|
12084
|
+
_def: { tag: "literal", value, caseInsensitive },
|
|
12085
|
+
_parseScalar: parseScalar,
|
|
12086
|
+
parse: parse2
|
|
11166
12087
|
};
|
|
11167
12088
|
}
|
|
11168
12089
|
|
|
@@ -11209,146 +12130,28 @@ function ref() {
|
|
|
11209
12130
|
},
|
|
11210
12131
|
parse(input, pos, ctx) {
|
|
11211
12132
|
const parser2 = resolved;
|
|
11212
|
-
if (!parser2) throw new Error("ref<T>() used before .define() was called");
|
|
11213
|
-
const gt = meta.grammarTrivia;
|
|
11214
|
-
if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
|
|
11215
|
-
return withRuleTrivia(gt, ctx, () => parser2.parse(input, pos, ctx));
|
|
11216
|
-
}
|
|
11217
|
-
return parser2.parse(input, pos, ctx);
|
|
11218
|
-
},
|
|
11219
|
-
define(p) {
|
|
11220
|
-
if (resolved) throw new Error("ref<T>() already defined");
|
|
11221
|
-
resolved = p;
|
|
11222
|
-
resolvedScalar = scalarOf(p);
|
|
11223
|
-
ownBoundary = hasOwnTriviaBoundary(p);
|
|
11224
|
-
meta.firstSet = p._meta.firstSet;
|
|
11225
|
-
meta.canMatchNewline = p._meta.canMatchNewline;
|
|
11226
|
-
meta.isTrivia = p._meta.isTrivia;
|
|
11227
|
-
if (p._meta.triviaKindLabels !== void 0) meta.triviaKindLabels = p._meta.triviaKindLabels;
|
|
11228
|
-
else delete meta.triviaKindLabels;
|
|
11229
|
-
if (p._meta.disjoint !== void 0) meta.disjoint = p._meta.disjoint;
|
|
11230
|
-
else delete meta.disjoint;
|
|
11231
|
-
}
|
|
11232
|
-
};
|
|
11233
|
-
return slot;
|
|
11234
|
-
}
|
|
11235
|
-
|
|
11236
|
-
// src/combinators/token.ts
|
|
11237
|
-
function semanticLeafValue(_ctx, _input, _start, _end, value) {
|
|
11238
|
-
return value;
|
|
11239
|
-
}
|
|
11240
|
-
function sourceLeafValue(ctx, input, start, end, value) {
|
|
11241
|
-
return cstOutputHost(ctx.build) ? input.slice(start, end) : value;
|
|
11242
|
-
}
|
|
11243
|
-
function token(root) {
|
|
11244
|
-
const meta = {
|
|
11245
|
-
firstSet: root._meta.firstSet,
|
|
11246
|
-
canMatchNewline: root._meta.canMatchNewline,
|
|
11247
|
-
isTrivia: false
|
|
11248
|
-
};
|
|
11249
|
-
return {
|
|
11250
|
-
_tag: "token",
|
|
11251
|
-
_meta: meta,
|
|
11252
|
-
_def: { tag: "token", parser: root },
|
|
11253
|
-
parse(input, pos, ctx) {
|
|
11254
|
-
const savedTrivia = ctx.trivia;
|
|
11255
|
-
const savedKinds = ctx.triviaKindLabels;
|
|
11256
|
-
const savedBuf = ctx._cstBuf;
|
|
11257
|
-
const savedChildren = ctx._cstChildren;
|
|
11258
|
-
const savedLeaves = ctx._cstLeaves;
|
|
11259
|
-
const savedRaw = ctx._cstRawChildren;
|
|
11260
|
-
const savedTriviaLog = ctx._cstTriviaLog;
|
|
11261
|
-
const savedOuterTriviaLog = ctx._triviaLog;
|
|
11262
|
-
const savedRootTriviaLog = ctx._rootTriviaLog;
|
|
11263
|
-
const wasCapturing = cstCaptureActive(ctx);
|
|
11264
|
-
ctx.trivia = void 0;
|
|
11265
|
-
ctx.triviaKindLabels = void 0;
|
|
11266
|
-
ctx._cstBuf = void 0;
|
|
11267
|
-
ctx._cstChildren = void 0;
|
|
11268
|
-
ctx._cstLeaves = void 0;
|
|
11269
|
-
ctx._cstRawChildren = void 0;
|
|
11270
|
-
ctx._cstTriviaLog = void 0;
|
|
11271
|
-
ctx._triviaLog = void 0;
|
|
11272
|
-
ctx._rootTriviaLog = void 0;
|
|
11273
|
-
let result;
|
|
11274
|
-
try {
|
|
11275
|
-
result = root.parse(input, pos, ctx);
|
|
11276
|
-
} finally {
|
|
11277
|
-
ctx.trivia = savedTrivia;
|
|
11278
|
-
ctx.triviaKindLabels = savedKinds;
|
|
11279
|
-
ctx._cstBuf = savedBuf;
|
|
11280
|
-
ctx._cstChildren = savedChildren;
|
|
11281
|
-
ctx._cstLeaves = savedLeaves;
|
|
11282
|
-
ctx._cstRawChildren = savedRaw;
|
|
11283
|
-
ctx._cstTriviaLog = savedTriviaLog;
|
|
11284
|
-
ctx._triviaLog = savedOuterTriviaLog;
|
|
11285
|
-
ctx._rootTriviaLog = savedRootTriviaLog;
|
|
11286
|
-
}
|
|
11287
|
-
if (!result.ok) return result;
|
|
11288
|
-
const span = result.span;
|
|
11289
|
-
const value = input.slice(pos, span.end);
|
|
11290
|
-
if (wasCapturing) pushCstLeaf(ctx, { _tag: "leaf", value, span });
|
|
11291
|
-
return { ok: true, value, span };
|
|
11292
|
-
}
|
|
11293
|
-
};
|
|
11294
|
-
}
|
|
11295
|
-
function makeLeaf(root, fn, sourceCstValue) {
|
|
11296
|
-
const cstValue = sourceCstValue ? sourceLeafValue : semanticLeafValue;
|
|
11297
|
-
const meta = {
|
|
11298
|
-
firstSet: root._meta.firstSet,
|
|
11299
|
-
canMatchNewline: root._meta.canMatchNewline,
|
|
11300
|
-
isTrivia: false
|
|
11301
|
-
};
|
|
11302
|
-
return {
|
|
11303
|
-
_tag: "leaf",
|
|
11304
|
-
_meta: meta,
|
|
11305
|
-
_def: {
|
|
11306
|
-
tag: "leaf",
|
|
11307
|
-
parser: root,
|
|
11308
|
-
fn,
|
|
11309
|
-
...sourceCstValue ? { cstValue: "source" } : {}
|
|
11310
|
-
},
|
|
11311
|
-
parse(input, pos, ctx) {
|
|
11312
|
-
const savedBuf = ctx._cstBuf;
|
|
11313
|
-
const savedChildren = ctx._cstChildren;
|
|
11314
|
-
const savedLeaves = ctx._cstLeaves;
|
|
11315
|
-
const savedRaw = ctx._cstRawChildren;
|
|
11316
|
-
const savedTriviaLog = ctx._cstTriviaLog;
|
|
11317
|
-
const savedOuterTriviaLog = ctx._triviaLog;
|
|
11318
|
-
const wasCapturing = cstCaptureActive(ctx);
|
|
11319
|
-
ctx._cstBuf = void 0;
|
|
11320
|
-
ctx._cstChildren = void 0;
|
|
11321
|
-
ctx._cstLeaves = void 0;
|
|
11322
|
-
ctx._cstRawChildren = void 0;
|
|
11323
|
-
ctx._cstTriviaLog = void 0;
|
|
11324
|
-
ctx._triviaLog = void 0;
|
|
11325
|
-
let result;
|
|
11326
|
-
try {
|
|
11327
|
-
result = root.parse(input, pos, ctx);
|
|
11328
|
-
} finally {
|
|
11329
|
-
ctx._cstBuf = savedBuf;
|
|
11330
|
-
ctx._cstChildren = savedChildren;
|
|
11331
|
-
ctx._cstLeaves = savedLeaves;
|
|
11332
|
-
ctx._cstRawChildren = savedRaw;
|
|
11333
|
-
ctx._cstTriviaLog = savedTriviaLog;
|
|
11334
|
-
ctx._triviaLog = savedOuterTriviaLog;
|
|
11335
|
-
}
|
|
11336
|
-
if (!result.ok) return result;
|
|
11337
|
-
const value = fn(result.value, result.span);
|
|
11338
|
-
if (wasCapturing) pushCstLeaf(ctx, {
|
|
11339
|
-
_tag: "leaf",
|
|
11340
|
-
value: cstValue(ctx, input, pos, result.span.end, value),
|
|
11341
|
-
span: result.span
|
|
11342
|
-
});
|
|
11343
|
-
return { ok: true, value, span: result.span };
|
|
12133
|
+
if (!parser2) throw new Error("ref<T>() used before .define() was called");
|
|
12134
|
+
const gt = meta.grammarTrivia;
|
|
12135
|
+
if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
|
|
12136
|
+
return withRuleTrivia(gt, ctx, () => parser2.parse(input, pos, ctx));
|
|
12137
|
+
}
|
|
12138
|
+
return parser2.parse(input, pos, ctx);
|
|
12139
|
+
},
|
|
12140
|
+
define(p) {
|
|
12141
|
+
if (resolved) throw new Error("ref<T>() already defined");
|
|
12142
|
+
resolved = p;
|
|
12143
|
+
resolvedScalar = scalarOf(p);
|
|
12144
|
+
ownBoundary = hasOwnTriviaBoundary(p);
|
|
12145
|
+
meta.firstSet = p._meta.firstSet;
|
|
12146
|
+
meta.canMatchNewline = p._meta.canMatchNewline;
|
|
12147
|
+
meta.isTrivia = p._meta.isTrivia;
|
|
12148
|
+
if (p._meta.triviaKindLabels !== void 0) meta.triviaKindLabels = p._meta.triviaKindLabels;
|
|
12149
|
+
else delete meta.triviaKindLabels;
|
|
12150
|
+
if (p._meta.disjoint !== void 0) meta.disjoint = p._meta.disjoint;
|
|
12151
|
+
else delete meta.disjoint;
|
|
11344
12152
|
}
|
|
11345
12153
|
};
|
|
11346
|
-
|
|
11347
|
-
function leaf(root, fn) {
|
|
11348
|
-
return makeLeaf(root, fn, false);
|
|
11349
|
-
}
|
|
11350
|
-
function sourceLeaf(root, fn) {
|
|
11351
|
-
return makeLeaf(root, fn, true);
|
|
12154
|
+
return slot;
|
|
11352
12155
|
}
|
|
11353
12156
|
|
|
11354
12157
|
// src/combinators/scanTo.ts
|
|
@@ -11595,37 +12398,184 @@ function escapeClassChar(ch2) {
|
|
|
11595
12398
|
return ch2.replace(/[\\\]^-]/g, "\\$&");
|
|
11596
12399
|
}
|
|
11597
12400
|
|
|
11598
|
-
// src/table/
|
|
11599
|
-
function
|
|
11600
|
-
const
|
|
11601
|
-
|
|
11602
|
-
|
|
11603
|
-
|
|
11604
|
-
|
|
11605
|
-
|
|
12401
|
+
// src/table/trivia-gap.ts
|
|
12402
|
+
function skipDeferredTrivia(input, cur, ctx) {
|
|
12403
|
+
const triviaP = ctx.trivia;
|
|
12404
|
+
const plain2 = ctx.trackLines !== true && ctx.captureTrivia !== true;
|
|
12405
|
+
const gap = ctx._gap;
|
|
12406
|
+
if (plain2 && gap !== void 0 && cur === gap.at && input === gap.input && triviaP === gap.of && ctx._rootTriviaCapture === gap.root && ctx.state === gap.state && ctx._rootTriviaKindIndex === gap.rootKinds && ctx._triviaLog === gap.log) return gap.end;
|
|
12407
|
+
const end = clearRunEnd(input, cur, ctx, triviaP, plain2);
|
|
12408
|
+
if (end >= 0) {
|
|
12409
|
+
remember(cur, end, ctx, input, triviaP);
|
|
12410
|
+
return end;
|
|
11606
12411
|
}
|
|
11607
|
-
|
|
12412
|
+
const scan = scanTriviaCompact(input, cur, ctx);
|
|
12413
|
+
if (typeof scan !== "number") return commitTriviaScan(scan);
|
|
12414
|
+
if (plain2) remember(cur, scan, ctx, input, triviaP);
|
|
12415
|
+
return scan;
|
|
11608
12416
|
}
|
|
11609
|
-
function
|
|
11610
|
-
const
|
|
11611
|
-
|
|
12417
|
+
function clearRunEnd(input, cur, ctx, triviaP, plain2) {
|
|
12418
|
+
const rootKinds = ctx._rootTriviaKindIndex;
|
|
12419
|
+
const spec = triviaP?._meta.labeledTriviaSpec;
|
|
12420
|
+
if (!plain2 || triviaP === void 0 || spec == null || rootKinds === void 0 || ctx._triviaLog !== void 0) return -1;
|
|
12421
|
+
if (spec.rootKinds !== rootKinds) prime(spec, triviaP, rootKinds);
|
|
12422
|
+
const fast = spec.rootScan;
|
|
12423
|
+
if (fast === null) return -1;
|
|
12424
|
+
const end = fast(input, cur);
|
|
12425
|
+
return ctx._rootTriviaCapture === false || clearOf(spec.rootLeaders, input, cur, end) ? end : -1;
|
|
12426
|
+
}
|
|
12427
|
+
function remember(cur, end, ctx, input, triviaP) {
|
|
12428
|
+
const gap = ctx._gap;
|
|
12429
|
+
if (gap === void 0) {
|
|
12430
|
+
ctx._gap = { at: cur, end, input, of: triviaP, root: ctx._rootTriviaCapture, rootKinds: ctx._rootTriviaKindIndex, log: ctx._triviaLog, state: ctx.state };
|
|
12431
|
+
return;
|
|
12432
|
+
}
|
|
12433
|
+
gap.at = cur;
|
|
12434
|
+
gap.end = end;
|
|
12435
|
+
gap.input = input;
|
|
12436
|
+
gap.of = triviaP;
|
|
12437
|
+
gap.root = ctx._rootTriviaCapture;
|
|
12438
|
+
gap.rootKinds = ctx._rootTriviaKindIndex;
|
|
12439
|
+
gap.log = ctx._triviaLog;
|
|
12440
|
+
gap.state = ctx.state;
|
|
11612
12441
|
}
|
|
11613
|
-
function
|
|
11614
|
-
|
|
11615
|
-
|
|
11616
|
-
|
|
12442
|
+
function prime(spec, triviaP, rootKinds) {
|
|
12443
|
+
const ranges = [];
|
|
12444
|
+
let bounded = true;
|
|
12445
|
+
for (const arm of spec.arms) {
|
|
12446
|
+
if (rootKinds[arm.label] === void 0) continue;
|
|
12447
|
+
const fs = arm.parser._meta.firstSet;
|
|
12448
|
+
if (fs.kind === "any") bounded = false;
|
|
12449
|
+
else if (fs.kind === "ranges") ranges.push(...fs.ranges);
|
|
12450
|
+
}
|
|
12451
|
+
const classified = triviaP._meta.triviaScanner;
|
|
12452
|
+
spec.rootKinds = rootKinds;
|
|
12453
|
+
spec.rootLeaders = ranges;
|
|
12454
|
+
spec.rootScan = !bounded ? null : classified === void 0 ? fastTriviaScanner(triviaP) : classified;
|
|
12455
|
+
}
|
|
12456
|
+
function clearOf(ranges, input, from, to) {
|
|
12457
|
+
for (let i = from; i < to; i++) {
|
|
12458
|
+
const c = input.charCodeAt(i);
|
|
12459
|
+
if (c >= 55296 && c <= 57343) return false;
|
|
12460
|
+
for (const r of ranges) if (c >= r.lo && c <= r.hi) return false;
|
|
11617
12461
|
}
|
|
11618
|
-
return
|
|
11619
|
-
_tag: "leaf",
|
|
11620
|
-
value: typeof v === "string" ? v : typeof v === "object" && v !== null ? input.slice(s, e) : "",
|
|
11621
|
-
span: { start: s, end: e }
|
|
11622
|
-
};
|
|
12462
|
+
return true;
|
|
11623
12463
|
}
|
|
11624
|
-
|
|
11625
|
-
|
|
11626
|
-
|
|
11627
|
-
|
|
11628
|
-
|
|
12464
|
+
|
|
12465
|
+
// src/table/fail-clean.ts
|
|
12466
|
+
function passChild(code, ip) {
|
|
12467
|
+
switch (code[ip]) {
|
|
12468
|
+
case OP_RULE:
|
|
12469
|
+
case OP_LABEL:
|
|
12470
|
+
case OP_COV:
|
|
12471
|
+
case OP_TOKEN:
|
|
12472
|
+
return code[ip + 1];
|
|
12473
|
+
case OP_GATE:
|
|
12474
|
+
case OP_NODE:
|
|
12475
|
+
case OP_NODE_TRACK:
|
|
12476
|
+
case OP_XFORM:
|
|
12477
|
+
case OP_FIELD:
|
|
12478
|
+
case OP_SCOPE:
|
|
12479
|
+
case OP_SCOPE_CAP:
|
|
12480
|
+
case OP_SCOPE_PLAIN:
|
|
12481
|
+
case OP_WITHCTX:
|
|
12482
|
+
case OP_LEAF:
|
|
12483
|
+
case OP_SOURCE_LEAF:
|
|
12484
|
+
return code[ip + 2];
|
|
12485
|
+
default:
|
|
12486
|
+
return -1;
|
|
12487
|
+
}
|
|
12488
|
+
}
|
|
12489
|
+
function seqCount(code, ip) {
|
|
12490
|
+
const op = code[ip];
|
|
12491
|
+
return op === OP_SEQ || op === OP_SEQV ? ip + 1 : op === OP_SEQX ? ip + 2 : -1;
|
|
12492
|
+
}
|
|
12493
|
+
function failCleanAnalysis(code) {
|
|
12494
|
+
const cleanAt = new Uint8Array(code.length);
|
|
12495
|
+
const neverAt = new Uint8Array(code.length);
|
|
12496
|
+
const neverFails = (ip) => {
|
|
12497
|
+
const hit = neverAt[ip];
|
|
12498
|
+
if (hit !== 0) return hit === 1;
|
|
12499
|
+
neverAt[ip] = 3;
|
|
12500
|
+
let out = false;
|
|
12501
|
+
const op = code[ip];
|
|
12502
|
+
if (op === OP_OPT || op === OP_EMPTY || op === OP_EXPECT) out = true;
|
|
12503
|
+
else if (op === OP_REP || op === OP_REPV) out = code[ip + 2] === 0;
|
|
12504
|
+
else {
|
|
12505
|
+
const at = seqCount(code, ip);
|
|
12506
|
+
if (at >= 0) {
|
|
12507
|
+
out = true;
|
|
12508
|
+
for (let i = 1, n = code[at]; out && i <= n; i++) out = neverFails(code[at + i]);
|
|
12509
|
+
} else if (op !== OP_GATE) {
|
|
12510
|
+
const c = passChild(code, ip);
|
|
12511
|
+
out = c >= 0 && neverFails(c);
|
|
12512
|
+
}
|
|
12513
|
+
}
|
|
12514
|
+
neverAt[ip] = out ? 1 : 2;
|
|
12515
|
+
return out;
|
|
12516
|
+
};
|
|
12517
|
+
const clean = (ip) => {
|
|
12518
|
+
const hit = cleanAt[ip];
|
|
12519
|
+
if (hit !== 0) return hit === 1;
|
|
12520
|
+
cleanAt[ip] = 3;
|
|
12521
|
+
let out = false;
|
|
12522
|
+
switch (code[ip]) {
|
|
12523
|
+
// A terminal pushes its leaf only on a match; NOT/PEEK/ATTEMPT restore
|
|
12524
|
+
// their own mark; OPT, EMPTY and EXPECT do not fail uncommitted.
|
|
12525
|
+
case OP_LIT:
|
|
12526
|
+
case OP_RX:
|
|
12527
|
+
case OP_LIT_TRACK:
|
|
12528
|
+
case OP_RX_TRACK:
|
|
12529
|
+
case OP_LIT_CI:
|
|
12530
|
+
case OP_LIT_CI_TRACK:
|
|
12531
|
+
case OP_GUARD:
|
|
12532
|
+
case OP_NOT:
|
|
12533
|
+
case OP_PEEK:
|
|
12534
|
+
case OP_ATTEMPT:
|
|
12535
|
+
case OP_EMPTY:
|
|
12536
|
+
case OP_OPT:
|
|
12537
|
+
case OP_EXPECT:
|
|
12538
|
+
out = true;
|
|
12539
|
+
break;
|
|
12540
|
+
// Min 0 does not fail uncommitted; min 1 fails only with no item kept, and
|
|
12541
|
+
// restores the failed item itself.
|
|
12542
|
+
case OP_REP:
|
|
12543
|
+
case OP_REPV:
|
|
12544
|
+
out = code[ip + 2] <= 1;
|
|
12545
|
+
break;
|
|
12546
|
+
// Only the first term may fail: a later one fails after the terms before it
|
|
12547
|
+
// wrote, and after the trivia scanned in front of it.
|
|
12548
|
+
case OP_SEQ:
|
|
12549
|
+
case OP_SEQV:
|
|
12550
|
+
case OP_SEQX: {
|
|
12551
|
+
const at = seqCount(code, ip);
|
|
12552
|
+
const n = code[at];
|
|
12553
|
+
out = n > 0 && clean(code[at + 1]);
|
|
12554
|
+
for (let i = 2; out && i <= n; i++) out = neverFails(code[at + i]);
|
|
12555
|
+
break;
|
|
12556
|
+
}
|
|
12557
|
+
case OP_CHOICE: {
|
|
12558
|
+
out = true;
|
|
12559
|
+
for (let i = 0, n = code[ip + 2]; out && i < n; i++) out = clean(code[ip + 4 + i]);
|
|
12560
|
+
break;
|
|
12561
|
+
}
|
|
12562
|
+
case OP_ROUTED:
|
|
12563
|
+
out = code[ip + 1] < 0 || clean(code[ip + 1]);
|
|
12564
|
+
break;
|
|
12565
|
+
// An arm's failure and the fallback's are committed; only the selector's is
|
|
12566
|
+
// not, and without a fallback an unknown key fails after the selector wrote.
|
|
12567
|
+
case OP_DISPATCH:
|
|
12568
|
+
out = code[ip + 3] >= 0 && clean(code[ip + 1]);
|
|
12569
|
+
break;
|
|
12570
|
+
default: {
|
|
12571
|
+
const c = passChild(code, ip);
|
|
12572
|
+
out = c >= 0 && clean(c);
|
|
12573
|
+
}
|
|
12574
|
+
}
|
|
12575
|
+
cleanAt[ip] = out ? 1 : 2;
|
|
12576
|
+
return out;
|
|
12577
|
+
};
|
|
12578
|
+
return clean;
|
|
11629
12579
|
}
|
|
11630
12580
|
|
|
11631
12581
|
// src/cst/host-mode.ts
|
|
@@ -11777,6 +12727,7 @@ function assemble(t2, prog, cfg) {
|
|
|
11777
12727
|
const swapLegal = !cfg.trackLines;
|
|
11778
12728
|
const hostCst = cfg.hostCst;
|
|
11779
12729
|
const REC = prog.rec === 1 && cfg.tolerant;
|
|
12730
|
+
const PROBE = cfg.probe;
|
|
11780
12731
|
const sentinels = /* @__PURE__ */ new Map();
|
|
11781
12732
|
function sentinelFor(cls) {
|
|
11782
12733
|
if (cls < 0) return void 0;
|
|
@@ -11791,6 +12742,9 @@ function assemble(t2, prog, cfg) {
|
|
|
11791
12742
|
const EC = newEndCell();
|
|
11792
12743
|
const scalarRecognizers = [];
|
|
11793
12744
|
const rawScalarSpecs = /* @__PURE__ */ new Set();
|
|
12745
|
+
function lookaheadClass(child) {
|
|
12746
|
+
return code[child] === OP_GATE && !cfg.tolerant && !cfg.probe ? cc[code[child + 1]] : null;
|
|
12747
|
+
}
|
|
11794
12748
|
function scalarFor(child) {
|
|
11795
12749
|
const spec = code[child + 1];
|
|
11796
12750
|
let recognize = scalarRecognizers[spec];
|
|
@@ -11800,17 +12754,27 @@ function assemble(t2, prog, cfg) {
|
|
|
11800
12754
|
}
|
|
11801
12755
|
return recognize;
|
|
11802
12756
|
}
|
|
11803
|
-
const labelExtraIps =
|
|
11804
|
-
for (const s of prog.scans ?? []) for (const r of scanRefs(s)) labelExtraIps.push(r[0]);
|
|
11805
|
-
for (const set of prog.scanSkip ?? []) for (const r of set) labelExtraIps.push(r[0]);
|
|
12757
|
+
const labelExtraIps = assemblyExtraIps(prog);
|
|
11806
12758
|
const closureLabels = computeSiteLabels(
|
|
11807
12759
|
code,
|
|
11808
12760
|
[...Object.values(prog.rules), ...labelExtraIps],
|
|
11809
12761
|
hostCst
|
|
11810
12762
|
);
|
|
11811
12763
|
let SCAN = null;
|
|
12764
|
+
let HYBRID;
|
|
12765
|
+
function hybridPiece(piece) {
|
|
12766
|
+
const setScan = HYBRID.scan;
|
|
12767
|
+
return (input, pos, ctx) => {
|
|
12768
|
+
const saved = setScan(SCAN);
|
|
12769
|
+
const value = piece(input, pos, ctx);
|
|
12770
|
+
setScan(saved);
|
|
12771
|
+
return value;
|
|
12772
|
+
};
|
|
12773
|
+
}
|
|
11812
12774
|
const memo = /* @__PURE__ */ new Map();
|
|
11813
12775
|
const reached = /* @__PURE__ */ new Set();
|
|
12776
|
+
const NULLABLE = /* @__PURE__ */ new Map();
|
|
12777
|
+
const CLEAN = REC ? () => false : failCleanAnalysis(code);
|
|
11814
12778
|
function pushLeaf(ctx, value, s, e) {
|
|
11815
12779
|
const lf = { _tag: "leaf", value, span: { start: s, end: e } };
|
|
11816
12780
|
pushCstLeaf(ctx, lf);
|
|
@@ -12009,6 +12973,22 @@ function assemble(t2, prog, cfg) {
|
|
|
12009
12973
|
return node2;
|
|
12010
12974
|
};
|
|
12011
12975
|
}
|
|
12976
|
+
function passCollapseNode(child, build, readsRaw) {
|
|
12977
|
+
return (input, pos, ctx) => {
|
|
12978
|
+
const v = child(input, pos, ctx);
|
|
12979
|
+
if (v !== void 0) return v;
|
|
12980
|
+
return collapseEmpty(ctx, build, input, pos, EC.e, readsRaw);
|
|
12981
|
+
};
|
|
12982
|
+
}
|
|
12983
|
+
function gatedPassCollapseNode(blockers, last, classic, build, readsRaw) {
|
|
12984
|
+
return (input, pos, ctx) => {
|
|
12985
|
+
const c = lead(input, pos);
|
|
12986
|
+
for (let i = 0; i < blockers.length; i++) if (classHas2(blockers[i], c)) return classic(input, pos, ctx);
|
|
12987
|
+
const v = last(input, pos, ctx);
|
|
12988
|
+
if (v !== void 0) return v;
|
|
12989
|
+
return collapseEmpty(ctx, build, input, pos, EC.e, readsRaw);
|
|
12990
|
+
};
|
|
12991
|
+
}
|
|
12012
12992
|
function plainProjectNode(child, projection, type) {
|
|
12013
12993
|
return (input, pos, ctx) => {
|
|
12014
12994
|
const sCh = ctx._cstChildren;
|
|
@@ -12100,9 +13080,7 @@ function assemble(t2, prog, cfg) {
|
|
|
12100
13080
|
return s(input, cur);
|
|
12101
13081
|
}
|
|
12102
13082
|
if (s !== null) return skipTriviaScanned(s, input, cur, ctx);
|
|
12103
|
-
if (needsDeferredTriviaCommit(ctx))
|
|
12104
|
-
return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
|
|
12105
|
-
}
|
|
13083
|
+
if (needsDeferredTriviaCommit(ctx)) return skipDeferredTrivia(input, cur, ctx);
|
|
12106
13084
|
return advanceTrivia(input, cur, ctx);
|
|
12107
13085
|
}
|
|
12108
13086
|
let TERMV;
|
|
@@ -12272,7 +13250,7 @@ function assemble(t2, prog, cfg) {
|
|
|
12272
13250
|
if (next !== void 0) {
|
|
12273
13251
|
return next(input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best);
|
|
12274
13252
|
}
|
|
12275
|
-
if (best === pos) acc = through(total, prev, acc);
|
|
13253
|
+
if (best === pos && prev !== 0) acc = through(total, prev, acc);
|
|
12276
13254
|
ctx._fe = pos;
|
|
12277
13255
|
ctx._fx = acc ?? choiceFx;
|
|
12278
13256
|
return FAIL;
|
|
@@ -12355,7 +13333,7 @@ function assemble(t2, prog, cfg) {
|
|
|
12355
13333
|
if (next !== void 0) {
|
|
12356
13334
|
return next(input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best);
|
|
12357
13335
|
}
|
|
12358
|
-
if (best === pos) acc = through(total, prev, acc);
|
|
13336
|
+
if (best === pos && prev !== 0) acc = through(total, prev, acc);
|
|
12359
13337
|
ctx._fe = pos;
|
|
12360
13338
|
ctx._fx = acc ?? choiceFx;
|
|
12361
13339
|
return FAIL;
|
|
@@ -12381,21 +13359,27 @@ function assemble(t2, prog, cfg) {
|
|
|
12381
13359
|
}
|
|
12382
13360
|
function dispatchBranch(child, usesRouted) {
|
|
12383
13361
|
if (!usesRouted) {
|
|
12384
|
-
return (input, _pos, selEnd, key,
|
|
12385
|
-
const
|
|
13362
|
+
return (input, _pos, selEnd, key, ctx) => {
|
|
13363
|
+
const need = markCst(ctx);
|
|
13364
|
+
const mRaw = MRAW;
|
|
13365
|
+
const mTl = MTL;
|
|
13366
|
+
const mLv = MLV;
|
|
13367
|
+
const mFl = need ? ctx._fields?.length ?? 0 : 0;
|
|
13368
|
+
const mEr = need ? ctx._errors?.length ?? 0 : 0;
|
|
13369
|
+
const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
13370
|
+
const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
12386
13371
|
const v = child(input, selEnd, ctx);
|
|
12387
13372
|
if (v === FAIL) {
|
|
12388
|
-
|
|
13373
|
+
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
12389
13374
|
ctx._fc = true;
|
|
12390
13375
|
return FAIL;
|
|
12391
13376
|
}
|
|
12392
13377
|
return [key, v];
|
|
12393
13378
|
};
|
|
12394
13379
|
}
|
|
12395
|
-
return (input, pos, selEnd, key,
|
|
13380
|
+
return (input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot) => {
|
|
12396
13381
|
const savedRouted = ctx._routed;
|
|
12397
|
-
|
|
12398
|
-
const mark = saveTriviaMark(ctx);
|
|
13382
|
+
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
12399
13383
|
ctx._routed = { value: key, span: { start: pos, end: selEnd } };
|
|
12400
13384
|
let v;
|
|
12401
13385
|
try {
|
|
@@ -12404,7 +13388,7 @@ function assemble(t2, prog, cfg) {
|
|
|
12404
13388
|
ctx._routed = savedRouted;
|
|
12405
13389
|
}
|
|
12406
13390
|
if (v === FAIL) {
|
|
12407
|
-
|
|
13391
|
+
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
12408
13392
|
ctx._fc = true;
|
|
12409
13393
|
return FAIL;
|
|
12410
13394
|
}
|
|
@@ -12412,12 +13396,12 @@ function assemble(t2, prog, cfg) {
|
|
|
12412
13396
|
};
|
|
12413
13397
|
}
|
|
12414
13398
|
function dispatchArmBlock(start, a0, a1, a2, a3, next) {
|
|
12415
|
-
return (arm, input, pos, selEnd, key,
|
|
12416
|
-
if (arm === start) return a0(input, pos, selEnd, key,
|
|
12417
|
-
if (arm === start + 1) return a1(input, pos, selEnd, key,
|
|
12418
|
-
if (arm === start + 2) return a2(input, pos, selEnd, key,
|
|
12419
|
-
if (arm === start + 3) return a3(input, pos, selEnd, key,
|
|
12420
|
-
return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key,
|
|
13399
|
+
return (arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot) => {
|
|
13400
|
+
if (arm === start) return a0(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
13401
|
+
if (arm === start + 1) return a1(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
13402
|
+
if (arm === start + 2) return a2(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
13403
|
+
if (arm === start + 3) return a3(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
13404
|
+
return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
12421
13405
|
};
|
|
12422
13406
|
}
|
|
12423
13407
|
function trackLinesInto(ctx, input, end) {
|
|
@@ -12434,20 +13418,68 @@ function assemble(t2, prog, cfg) {
|
|
|
12434
13418
|
if (done !== void 0) return done;
|
|
12435
13419
|
const flight = inFlight.get(ip);
|
|
12436
13420
|
if (flight !== void 0) return flight.fwd;
|
|
13421
|
+
const selected = HYBRID?.byIp[ip];
|
|
13422
|
+
if (selected !== void 0) {
|
|
13423
|
+
const piece2 = scanHandoffNeeded(code, ip, closureLabels) ? hybridPiece(selected) : selected;
|
|
13424
|
+
memo.set(ip, piece2);
|
|
13425
|
+
reached.add(ip);
|
|
13426
|
+
return piece2;
|
|
13427
|
+
}
|
|
12437
13428
|
let target;
|
|
12438
13429
|
const fwd = (input, pos, ctx) => target(input, pos, ctx);
|
|
12439
13430
|
const holder = { fwd, set: (p) => {
|
|
12440
13431
|
target = p;
|
|
12441
13432
|
} };
|
|
12442
13433
|
inFlight.set(ip, holder);
|
|
12443
|
-
const
|
|
12444
|
-
const piece = (op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[ip + 3] === 0) && code[ip + 1] >= 0 && closureLabels.at(ip).tri === code[ip + 1] ? link(code[ip + 2]) : lower(ip);
|
|
13434
|
+
const piece = scopeIsIdentity(code, ip, closureLabels.at(ip)) ? link(code[ip + 2]) : countedPiece(lookaheadLedNode(ip) ?? lower(ip), ip);
|
|
12445
13435
|
inFlight.delete(ip);
|
|
12446
13436
|
holder.set(piece);
|
|
12447
13437
|
memo.set(ip, piece);
|
|
12448
13438
|
reached.add(ip);
|
|
12449
13439
|
return piece;
|
|
12450
13440
|
}
|
|
13441
|
+
let FIRST_DECIDED;
|
|
13442
|
+
let NODE_BODY;
|
|
13443
|
+
const DECIDED = (_input, pos) => {
|
|
13444
|
+
EC.e = pos;
|
|
13445
|
+
return null;
|
|
13446
|
+
};
|
|
13447
|
+
function lookaheadLedNode(ip) {
|
|
13448
|
+
const op = code[ip];
|
|
13449
|
+
if (op !== OP_NODE && op !== OP_NODE_TRACK || hostCst || REC || cfg.probe || cfg.coverage || cfg.trackLines) return void 0;
|
|
13450
|
+
if (passCollapse(code, ip, hostCst) || gatedPassCollapse(code, ip, hostCst) !== void 0) return void 0;
|
|
13451
|
+
const body = code[ip + 2];
|
|
13452
|
+
const bop = code[body];
|
|
13453
|
+
if (bop !== OP_SEQ && bop !== OP_SEQV && bop !== OP_SEQX) return void 0;
|
|
13454
|
+
const base = bop === OP_SEQX ? body + 3 : body + 2;
|
|
13455
|
+
if (code[bop === OP_SEQX ? body + 2 : body + 1] < 2) return void 0;
|
|
13456
|
+
const first = code[base];
|
|
13457
|
+
const negative = code[first] === OP_NOT;
|
|
13458
|
+
const terminal = negative ? scalarTerminalNotChild(code, first) : code[first] === OP_PEEK ? scalarTerminalPeekChild(code, first) : -1;
|
|
13459
|
+
if (terminal < 0) return void 0;
|
|
13460
|
+
const recognize = scalarFor(terminal);
|
|
13461
|
+
const xf = fx[code[first + 2]];
|
|
13462
|
+
FIRST_DECIDED = DECIDED;
|
|
13463
|
+
NODE_BODY = lower(body);
|
|
13464
|
+
const node2 = lower(ip);
|
|
13465
|
+
NODE_BODY = void 0;
|
|
13466
|
+
return negative ? (input, pos, ctx) => {
|
|
13467
|
+
if (recognize(input, pos) >= 0) {
|
|
13468
|
+
ctx._fe = pos;
|
|
13469
|
+
ctx._fx = xf;
|
|
13470
|
+
EC.e = pos;
|
|
13471
|
+
return FAIL;
|
|
13472
|
+
}
|
|
13473
|
+
return node2(input, pos, ctx);
|
|
13474
|
+
} : (input, pos, ctx) => {
|
|
13475
|
+
if (recognize(input, pos) < 0) {
|
|
13476
|
+
ctx._fe = pos;
|
|
13477
|
+
ctx._fx = xf;
|
|
13478
|
+
return FAIL;
|
|
13479
|
+
}
|
|
13480
|
+
return node2(input, pos, ctx);
|
|
13481
|
+
};
|
|
13482
|
+
}
|
|
12451
13483
|
function lower(ip) {
|
|
12452
13484
|
const op = code[ip];
|
|
12453
13485
|
switch (op) {
|
|
@@ -12978,7 +14010,12 @@ function assemble(t2, prog, cfg) {
|
|
|
12978
14010
|
}
|
|
12979
14011
|
const child = link(code[ip + 1]);
|
|
12980
14012
|
const xf = fx[code[ip + 2]];
|
|
14013
|
+
const gate = lookaheadClass(code[ip + 1]);
|
|
12981
14014
|
return (input, pos, ctx) => {
|
|
14015
|
+
if (gate !== null && !classHas2(gate, lead(input, pos))) {
|
|
14016
|
+
EC.e = pos;
|
|
14017
|
+
return null;
|
|
14018
|
+
}
|
|
12982
14019
|
const need = markCst(ctx);
|
|
12983
14020
|
const mRaw = MRAW;
|
|
12984
14021
|
const mTl = MTL;
|
|
@@ -12987,8 +14024,10 @@ function assemble(t2, prog, cfg) {
|
|
|
12987
14024
|
const mEr = need ? ctx._errors?.length ?? 0 : 0;
|
|
12988
14025
|
const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
12989
14026
|
const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14027
|
+
const probeBest = PROBE ? ctx._probe?.best : void 0;
|
|
12990
14028
|
const v = child(input, pos, ctx);
|
|
12991
14029
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14030
|
+
if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
|
|
12992
14031
|
if (v === FAIL) {
|
|
12993
14032
|
EC.e = pos;
|
|
12994
14033
|
return null;
|
|
@@ -12999,9 +14038,29 @@ function assemble(t2, prog, cfg) {
|
|
|
12999
14038
|
};
|
|
13000
14039
|
}
|
|
13001
14040
|
case OP_PEEK: {
|
|
14041
|
+
const scalarChild = scalarTerminalPeekChild(code, ip);
|
|
14042
|
+
if (scalarChild >= 0) {
|
|
14043
|
+
const recognize = scalarFor(scalarChild);
|
|
14044
|
+
const xf2 = fx[code[ip + 2]];
|
|
14045
|
+
return (input, pos, ctx) => {
|
|
14046
|
+
if (recognize(input, pos) < 0) {
|
|
14047
|
+
ctx._fe = pos;
|
|
14048
|
+
ctx._fx = xf2;
|
|
14049
|
+
return FAIL;
|
|
14050
|
+
}
|
|
14051
|
+
EC.e = pos;
|
|
14052
|
+
return null;
|
|
14053
|
+
};
|
|
14054
|
+
}
|
|
13002
14055
|
const child = link(code[ip + 1]);
|
|
13003
14056
|
const xf = fx[code[ip + 2]];
|
|
14057
|
+
const gate = lookaheadClass(code[ip + 1]);
|
|
13004
14058
|
return (input, pos, ctx) => {
|
|
14059
|
+
if (gate !== null && !classHas2(gate, lead(input, pos))) {
|
|
14060
|
+
ctx._fe = pos;
|
|
14061
|
+
ctx._fx = xf;
|
|
14062
|
+
return FAIL;
|
|
14063
|
+
}
|
|
13005
14064
|
const need = markCst(ctx);
|
|
13006
14065
|
const mRaw = MRAW;
|
|
13007
14066
|
const mTl = MTL;
|
|
@@ -13010,8 +14069,10 @@ function assemble(t2, prog, cfg) {
|
|
|
13010
14069
|
const mEr = need ? ctx._errors?.length ?? 0 : 0;
|
|
13011
14070
|
const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
13012
14071
|
const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14072
|
+
const probeBest = PROBE ? ctx._probe?.best : void 0;
|
|
13013
14073
|
const v = child(input, pos, ctx);
|
|
13014
14074
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14075
|
+
if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
|
|
13015
14076
|
if (v === FAIL) {
|
|
13016
14077
|
ctx._fe = pos;
|
|
13017
14078
|
ctx._fx = xf;
|
|
@@ -13023,8 +14084,14 @@ function assemble(t2, prog, cfg) {
|
|
|
13023
14084
|
}
|
|
13024
14085
|
case OP_OPT: {
|
|
13025
14086
|
const child = link(code[ip + 1]);
|
|
14087
|
+
const gate = lookaheadClass(code[ip + 1]);
|
|
14088
|
+
const childClean = CLEAN(code[ip + 1]);
|
|
13026
14089
|
return (input, pos, ctx) => {
|
|
13027
|
-
|
|
14090
|
+
if (gate !== null && !classHas2(gate, lead(input, pos))) {
|
|
14091
|
+
EC.e = pos;
|
|
14092
|
+
return null;
|
|
14093
|
+
}
|
|
14094
|
+
const need = !childClean && markCst(ctx);
|
|
13028
14095
|
const mRaw = MRAW;
|
|
13029
14096
|
const mTl = MTL;
|
|
13030
14097
|
const mLv = MLV;
|
|
@@ -13222,6 +14289,9 @@ function assemble(t2, prog, cfg) {
|
|
|
13222
14289
|
const projection = reducer < 0 ? ~reducer : -1;
|
|
13223
14290
|
const fn = fused && projection < 0 ? fns[reducer] : void 0;
|
|
13224
14291
|
const step = closureLabels.at(ip).buf ? nextTermBuffered : nextTerm;
|
|
14292
|
+
const decided = FIRST_DECIDED;
|
|
14293
|
+
FIRST_DECIDED = void 0;
|
|
14294
|
+
const linkFirst = () => decided ?? link(code[base]);
|
|
13225
14295
|
const runnerBlock = (count, r0, r1, r2, r3, next) => {
|
|
13226
14296
|
if (count === 1) return (input, cur, ctx, values, inherited) => {
|
|
13227
14297
|
cur = r0(input, cur, ctx, inherited);
|
|
@@ -13267,7 +14337,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13267
14337
|
};
|
|
13268
14338
|
};
|
|
13269
14339
|
if (REC) {
|
|
13270
|
-
const first2 =
|
|
14340
|
+
const first2 = linkFirst();
|
|
13271
14341
|
const firstSync = sentinelFor(code[base + n]);
|
|
13272
14342
|
const runnerAt = (i) => {
|
|
13273
14343
|
const sync = sentinelFor(code[base + n + i]);
|
|
@@ -13303,13 +14373,13 @@ function assemble(t2, prog, cfg) {
|
|
|
13303
14373
|
const bindRunners = (start) => {
|
|
13304
14374
|
const count = Math.min(4, n - start);
|
|
13305
14375
|
const at = (offset) => runnerAt(start + offset);
|
|
13306
|
-
const
|
|
14376
|
+
const never2 = () => -1;
|
|
13307
14377
|
return runnerBlock(
|
|
13308
14378
|
count,
|
|
13309
14379
|
at(0),
|
|
13310
|
-
count > 1 ? at(1) :
|
|
13311
|
-
count > 2 ? at(2) :
|
|
13312
|
-
count > 3 ? at(3) :
|
|
14380
|
+
count > 1 ? at(1) : never2,
|
|
14381
|
+
count > 2 ? at(2) : never2,
|
|
14382
|
+
count > 3 ? at(3) : never2,
|
|
13313
14383
|
start + count < n ? bindRunners(start + count) : void 0
|
|
13314
14384
|
);
|
|
13315
14385
|
};
|
|
@@ -13359,15 +14429,31 @@ function assemble(t2, prog, cfg) {
|
|
|
13359
14429
|
let hasAdj = false;
|
|
13360
14430
|
for (let i = 1; i < n; i++) {
|
|
13361
14431
|
const kidIp = code[base + i];
|
|
13362
|
-
if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp)) {
|
|
14432
|
+
if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp) || holdsGap(code, k, base, n, i, NULLABLE)) {
|
|
13363
14433
|
hasAdj = true;
|
|
13364
14434
|
break;
|
|
13365
14435
|
}
|
|
13366
14436
|
}
|
|
13367
14437
|
if (hasAdj) {
|
|
13368
|
-
const first2 =
|
|
14438
|
+
const first2 = linkFirst();
|
|
13369
14439
|
const runnerAt = (i) => {
|
|
13370
14440
|
const kidIp = code[base + i];
|
|
14441
|
+
if (holdsGap(code, k, base, n, i, NULLABLE)) {
|
|
14442
|
+
const kid = link(kidIp);
|
|
14443
|
+
return (input, cur, ctx) => {
|
|
14444
|
+
if (ctx.trivia === void 0) {
|
|
14445
|
+
const v2 = kid(input, cur, ctx);
|
|
14446
|
+
if (v2 === FAIL) return -1;
|
|
14447
|
+
TERMV = v2;
|
|
14448
|
+
return EC.e;
|
|
14449
|
+
}
|
|
14450
|
+
const scanEnd = skipTrivia(input, cur, ctx);
|
|
14451
|
+
const v = kid(input, scanEnd, ctx);
|
|
14452
|
+
if (v === FAIL) return -1;
|
|
14453
|
+
TERMV = v;
|
|
14454
|
+
return scanEnd;
|
|
14455
|
+
};
|
|
14456
|
+
}
|
|
13371
14457
|
if (code[kidIp] !== OP_ADJ) {
|
|
13372
14458
|
const kid = link(kidIp);
|
|
13373
14459
|
if (leadingTriviaFieldAt(code, k, kidIp)) {
|
|
@@ -13392,13 +14478,13 @@ function assemble(t2, prog, cfg) {
|
|
|
13392
14478
|
const bindRunners = (start) => {
|
|
13393
14479
|
const count = Math.min(4, n - start);
|
|
13394
14480
|
const at = (offset) => runnerAt(start + offset);
|
|
13395
|
-
const
|
|
14481
|
+
const never2 = () => -1;
|
|
13396
14482
|
return runnerBlock(
|
|
13397
14483
|
count,
|
|
13398
14484
|
at(0),
|
|
13399
|
-
count > 1 ? at(1) :
|
|
13400
|
-
count > 2 ? at(2) :
|
|
13401
|
-
count > 3 ? at(3) :
|
|
14485
|
+
count > 1 ? at(1) : never2,
|
|
14486
|
+
count > 2 ? at(2) : never2,
|
|
14487
|
+
count > 3 ? at(3) : never2,
|
|
13402
14488
|
start + count < n ? bindRunners(start + count) : void 0
|
|
13403
14489
|
);
|
|
13404
14490
|
};
|
|
@@ -13435,7 +14521,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13435
14521
|
};
|
|
13436
14522
|
}
|
|
13437
14523
|
if (n === 1) {
|
|
13438
|
-
const k0 =
|
|
14524
|
+
const k0 = linkFirst();
|
|
13439
14525
|
if (fused) {
|
|
13440
14526
|
return (input, pos, ctx) => {
|
|
13441
14527
|
const v = k0(input, pos, ctx);
|
|
@@ -13457,7 +14543,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13457
14543
|
};
|
|
13458
14544
|
}
|
|
13459
14545
|
if (n === 2) {
|
|
13460
|
-
const k0 =
|
|
14546
|
+
const k0 = linkFirst(), k1 = link(code[base + 1]);
|
|
13461
14547
|
if (fused) {
|
|
13462
14548
|
return (input, pos, ctx) => {
|
|
13463
14549
|
const v0 = k0(input, pos, ctx);
|
|
@@ -13488,7 +14574,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13488
14574
|
};
|
|
13489
14575
|
}
|
|
13490
14576
|
if (n === 3) {
|
|
13491
|
-
const k0 =
|
|
14577
|
+
const k0 = linkFirst(), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
|
|
13492
14578
|
if (fused) {
|
|
13493
14579
|
return (input, pos, ctx) => {
|
|
13494
14580
|
const v0 = k0(input, pos, ctx);
|
|
@@ -13582,7 +14668,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13582
14668
|
start + count < n ? bind(start + count) : void 0
|
|
13583
14669
|
);
|
|
13584
14670
|
};
|
|
13585
|
-
const first =
|
|
14671
|
+
const first = linkFirst();
|
|
13586
14672
|
const tail = bind(1);
|
|
13587
14673
|
const runDirectTerms = (input, pos, ctx, values) => {
|
|
13588
14674
|
const v0 = first(input, pos, ctx);
|
|
@@ -13621,6 +14707,8 @@ function assemble(t2, prog, cfg) {
|
|
|
13621
14707
|
const n = code[ip + 2];
|
|
13622
14708
|
const choiceFx = fx[code[ip + 3]];
|
|
13623
14709
|
const base = ip + 4;
|
|
14710
|
+
for (let i = 0; i < n; i++) link(code[base + i]);
|
|
14711
|
+
const armsClean = CLEAN(ip);
|
|
13624
14712
|
if (table.exclusive) {
|
|
13625
14713
|
const ascii = table.ascii;
|
|
13626
14714
|
const hi = table.hi;
|
|
@@ -13760,7 +14848,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13760
14848
|
if (n === 3) addGate(g2, 4);
|
|
13761
14849
|
return (input, pos, ctx) => {
|
|
13762
14850
|
const c = lead(input, pos);
|
|
13763
|
-
const need = markCst(ctx);
|
|
14851
|
+
const need = !armsClean && markCst(ctx);
|
|
13764
14852
|
const mRaw = MRAW;
|
|
13765
14853
|
const mTl = MTL;
|
|
13766
14854
|
const mLv = MLV;
|
|
@@ -13830,6 +14918,11 @@ function assemble(t2, prog, cfg) {
|
|
|
13830
14918
|
}
|
|
13831
14919
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
13832
14920
|
}
|
|
14921
|
+
if (prev === 0) {
|
|
14922
|
+
ctx._fe = pos;
|
|
14923
|
+
ctx._fx = choiceFx;
|
|
14924
|
+
return FAIL;
|
|
14925
|
+
}
|
|
13833
14926
|
if (best === pos && prev < 1) acc = accSet(e0, acc);
|
|
13834
14927
|
if (best === pos && prev < 2) acc = accSet(e1, acc);
|
|
13835
14928
|
if (best === pos && n === 3 && prev < 3) acc = accSet(e2, acc);
|
|
@@ -13972,7 +15065,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13972
15065
|
if (pn !== 0) {
|
|
13973
15066
|
return (input, pos, ctx) => {
|
|
13974
15067
|
const c = lead(input, pos);
|
|
13975
|
-
const need = markCst(ctx);
|
|
15068
|
+
const need = !armsClean && markCst(ctx);
|
|
13976
15069
|
const mRaw = MRAW;
|
|
13977
15070
|
const mTl = MTL;
|
|
13978
15071
|
const mLv = MLV;
|
|
@@ -14029,7 +15122,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14029
15122
|
}
|
|
14030
15123
|
return (input, pos, ctx) => {
|
|
14031
15124
|
const c = lead(input, pos);
|
|
14032
|
-
const need = markCst(ctx);
|
|
15125
|
+
const need = !armsClean && markCst(ctx);
|
|
14033
15126
|
const mRaw = MRAW;
|
|
14034
15127
|
const mTl = MTL;
|
|
14035
15128
|
const mLv = MLV;
|
|
@@ -14077,7 +15170,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14077
15170
|
}
|
|
14078
15171
|
return (input, pos, ctx) => {
|
|
14079
15172
|
const c = lead(input, pos);
|
|
14080
|
-
const need = markCst(ctx);
|
|
15173
|
+
const need = !armsClean && markCst(ctx);
|
|
14081
15174
|
const mRaw = MRAW;
|
|
14082
15175
|
const mTl = MTL;
|
|
14083
15176
|
const mLv = MLV;
|
|
@@ -14131,6 +15224,21 @@ function assemble(t2, prog, cfg) {
|
|
|
14131
15224
|
return lit(input, pos, ctx);
|
|
14132
15225
|
};
|
|
14133
15226
|
}
|
|
15227
|
+
case OP_RGATE: {
|
|
15228
|
+
const cls = cc[code[ip + 1]];
|
|
15229
|
+
const xf = fx[code[ip + 3]];
|
|
15230
|
+
const child = link(code[ip + 2]);
|
|
15231
|
+
if (cfg.tolerant || cfg.probe) return child;
|
|
15232
|
+
return (input, pos, ctx) => {
|
|
15233
|
+
const item = ctx._routed;
|
|
15234
|
+
if (item !== void 0 && item.span.start === pos && !classHas2(cls, lead(input, item.span.end))) {
|
|
15235
|
+
ctx._fe = item.span.end;
|
|
15236
|
+
ctx._fx = xf;
|
|
15237
|
+
return FAIL;
|
|
15238
|
+
}
|
|
15239
|
+
return child(input, pos, ctx);
|
|
15240
|
+
};
|
|
15241
|
+
}
|
|
14134
15242
|
case OP_ARMGATE: {
|
|
14135
15243
|
const pred = fns[code[ip + 1]];
|
|
14136
15244
|
const child = link(code[ip + 2]);
|
|
@@ -14138,7 +15246,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14138
15246
|
return (input, pos, ctx) => {
|
|
14139
15247
|
if (!pred(ctx.state)) {
|
|
14140
15248
|
ctx._fc = false;
|
|
14141
|
-
ctx._fe =
|
|
15249
|
+
ctx._fe = -1;
|
|
14142
15250
|
ctx._fx = xf;
|
|
14143
15251
|
return FAIL;
|
|
14144
15252
|
}
|
|
@@ -14199,6 +15307,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14199
15307
|
const itemClass = !REC && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
|
|
14200
15308
|
const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
|
|
14201
15309
|
const skipBeforeFirst = sepIp < 0 && min === 0;
|
|
15310
|
+
const itemClean = sepIp < 0 && CLEAN(code[ip + 1]) && !rowNullable(code, k, code[ip + 1], NULLABLE);
|
|
14202
15311
|
if (REC) {
|
|
14203
15312
|
const itemFx2 = fx[code[ip + 6]];
|
|
14204
15313
|
const sepSent = sentinelFor(code[ip + 7]);
|
|
@@ -14295,6 +15404,8 @@ function assemble(t2, prog, cfg) {
|
|
|
14295
15404
|
const out = collect ? [] : void 0;
|
|
14296
15405
|
const hasTrivia = ctx.trivia !== void 0;
|
|
14297
15406
|
const needMark = rollbackNeeded(ctx);
|
|
15407
|
+
const markLater = needMark && (!itemClean || hasTrivia);
|
|
15408
|
+
const markFirst = needMark && (!itemClean || hasTrivia && skipBeforeFirst);
|
|
14298
15409
|
const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
|
|
14299
15410
|
let cur = pos;
|
|
14300
15411
|
let count = 0;
|
|
@@ -14302,14 +15413,15 @@ function assemble(t2, prog, cfg) {
|
|
|
14302
15413
|
if (max >= 0 && count >= max) break;
|
|
14303
15414
|
if (sep !== void 0 && count > 0 && count >= min && cur >= input.length) break;
|
|
14304
15415
|
if (count >= min && sep === void 0 && !hasTrivia && gateItems && !itemMayStart(input, cur)) break;
|
|
14305
|
-
|
|
14306
|
-
|
|
14307
|
-
const
|
|
14308
|
-
const
|
|
14309
|
-
const
|
|
14310
|
-
const
|
|
14311
|
-
const
|
|
14312
|
-
const
|
|
15416
|
+
const markIt = count > 0 ? markLater : markFirst;
|
|
15417
|
+
if (markIt) markCst(ctx);
|
|
15418
|
+
const mRaw = markIt ? MRAW : 0;
|
|
15419
|
+
const mTl = markIt ? MTL : 0;
|
|
15420
|
+
const mLv = markIt ? MLV : 0;
|
|
15421
|
+
const mFl = markIt ? ctx._fields?.length ?? 0 : 0;
|
|
15422
|
+
const mEr = markIt ? ctx._errors?.length ?? 0 : 0;
|
|
15423
|
+
const mLog = markIt ? ctx._triviaLog?.length ?? 0 : 0;
|
|
15424
|
+
const mRoot = markIt ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14313
15425
|
let itemStart = cur;
|
|
14314
15426
|
let sepEnd = -1;
|
|
14315
15427
|
const viaRepItem = sep === void 0 && count >= min && (count > 0 || skipBeforeFirst);
|
|
@@ -14321,7 +15433,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14321
15433
|
if (sepLeads) LEAD.at = cur;
|
|
14322
15434
|
const sv = sep(input, sp, ctx);
|
|
14323
15435
|
if (sv === FAIL) {
|
|
14324
|
-
if (
|
|
15436
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14325
15437
|
if (committed3(ctx)) return FAIL;
|
|
14326
15438
|
break;
|
|
14327
15439
|
}
|
|
@@ -14332,25 +15444,25 @@ function assemble(t2, prog, cfg) {
|
|
|
14332
15444
|
itemStart = skipTrivia(input, itemStart, ctx);
|
|
14333
15445
|
}
|
|
14334
15446
|
if (itemStart >= input.length && viaRepItem) {
|
|
14335
|
-
if (
|
|
15447
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14336
15448
|
if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
|
|
14337
15449
|
break;
|
|
14338
15450
|
}
|
|
14339
15451
|
if (count >= min && gateItems && !itemMayStart(input, itemStart)) {
|
|
14340
|
-
if (
|
|
15452
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14341
15453
|
if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
|
|
14342
15454
|
break;
|
|
14343
15455
|
}
|
|
14344
15456
|
ctx._fc = false;
|
|
14345
15457
|
const v = child(input, itemStart, ctx);
|
|
14346
15458
|
if (v === FAIL) {
|
|
14347
|
-
if (
|
|
15459
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14348
15460
|
if (committed3(ctx)) return FAIL;
|
|
14349
15461
|
if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
|
|
14350
15462
|
break;
|
|
14351
15463
|
}
|
|
14352
15464
|
if (EC.e === itemStart && viaRepItem) {
|
|
14353
|
-
if (
|
|
15465
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14354
15466
|
break;
|
|
14355
15467
|
}
|
|
14356
15468
|
if (out !== void 0) out.push(v);
|
|
@@ -14424,7 +15536,14 @@ function assemble(t2, prog, cfg) {
|
|
|
14424
15536
|
const runArm = n === 0 ? void 0 : bindArms(0);
|
|
14425
15537
|
const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted);
|
|
14426
15538
|
return (input, pos, ctx) => {
|
|
14427
|
-
const
|
|
15539
|
+
const need = markCst(ctx);
|
|
15540
|
+
const mRaw = MRAW;
|
|
15541
|
+
const mTl = MTL;
|
|
15542
|
+
const mLv = MLV;
|
|
15543
|
+
const mFl = need ? ctx._fields?.length ?? 0 : 0;
|
|
15544
|
+
const mEr = need ? ctx._errors?.length ?? 0 : 0;
|
|
15545
|
+
const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
15546
|
+
const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14428
15547
|
const selVal = selector(input, pos, ctx);
|
|
14429
15548
|
if (selVal === FAIL) return FAIL;
|
|
14430
15549
|
const selEnd = EC.e;
|
|
@@ -14436,9 +15555,9 @@ function assemble(t2, prog, cfg) {
|
|
|
14436
15555
|
ctx._fx = expected;
|
|
14437
15556
|
return FAIL;
|
|
14438
15557
|
}
|
|
14439
|
-
return runOther(input, pos, selEnd, key,
|
|
15558
|
+
return runOther(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14440
15559
|
}
|
|
14441
|
-
return runArm(arm, input, pos, selEnd, key,
|
|
15560
|
+
return runArm(arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14442
15561
|
};
|
|
14443
15562
|
}
|
|
14444
15563
|
/* ── node ────────────────────────────────────────────────────────────── */
|
|
@@ -14474,7 +15593,8 @@ function assemble(t2, prog, cfg) {
|
|
|
14474
15593
|
return nd;
|
|
14475
15594
|
};
|
|
14476
15595
|
}
|
|
14477
|
-
const child = link(code[ip + 2]);
|
|
15596
|
+
const child = NODE_BODY ?? link(code[ip + 2]);
|
|
15597
|
+
NODE_BODY = void 0;
|
|
14478
15598
|
const proj = code[ip + 4];
|
|
14479
15599
|
const buildIdx = code[ip + 1];
|
|
14480
15600
|
const type = k[code[ip + 5]];
|
|
@@ -14498,6 +15618,30 @@ function assemble(t2, prog, cfg) {
|
|
|
14498
15618
|
if (build !== void 0 && proj < 0 && flags === 18) {
|
|
14499
15619
|
return childrenOnlyFieldsBuildNode(child, build);
|
|
14500
15620
|
}
|
|
15621
|
+
if (build !== void 0 && passCollapse(code, ip, hostCst)) {
|
|
15622
|
+
return passCollapseNode(child, build, flags === 32);
|
|
15623
|
+
}
|
|
15624
|
+
const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
|
|
15625
|
+
const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(closureLabels.at(code[ip + 2]).tri, trivia2);
|
|
15626
|
+
if (build !== void 0 && gated !== void 0 && triviaLead !== void 0) {
|
|
15627
|
+
const classic = flags === 32 ? collapseBuildNode(child, build) : childrenOnlyCollapseBuildNode(child, build);
|
|
15628
|
+
return gatedPassCollapseNode(
|
|
15629
|
+
[
|
|
15630
|
+
...gated.leads.map((g) => cc[code[g + 1]]),
|
|
15631
|
+
resolveClass(encodeClassSpec([
|
|
15632
|
+
...triviaLead,
|
|
15633
|
+
...gated.lits.map((i) => {
|
|
15634
|
+
const c = k[i].codePointAt(0);
|
|
15635
|
+
return { lo: c, hi: c };
|
|
15636
|
+
})
|
|
15637
|
+
]))
|
|
15638
|
+
],
|
|
15639
|
+
link(gated.last),
|
|
15640
|
+
classic,
|
|
15641
|
+
build,
|
|
15642
|
+
flags === 32
|
|
15643
|
+
);
|
|
15644
|
+
}
|
|
14501
15645
|
if (build !== void 0 && proj < 0 && flags === 32) {
|
|
14502
15646
|
return collapseBuildNode(child, build);
|
|
14503
15647
|
}
|
|
@@ -14544,7 +15688,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14544
15688
|
if (v === FAIL) return FAIL;
|
|
14545
15689
|
const end = EC.e;
|
|
14546
15690
|
const span = tracked ? spanLines(ctx, pos, end) : { start: pos, end };
|
|
14547
|
-
const st = readsState
|
|
15691
|
+
const st = readsState ? ctx.state : void 0;
|
|
14548
15692
|
let nd;
|
|
14549
15693
|
if (unwrap && kids.length === 1) {
|
|
14550
15694
|
nd = unwrapChild(kids[0]);
|
|
@@ -14557,10 +15701,10 @@ function assemble(t2, prog, cfg) {
|
|
|
14557
15701
|
) {
|
|
14558
15702
|
nd = kids[0];
|
|
14559
15703
|
} else if (proj >= 0) {
|
|
14560
|
-
nd = hostCst && host !== void 0 ? host(type, kids, fieldMap, span, rawKids, tlog,
|
|
15704
|
+
nd = hostCst && host !== void 0 ? host(type, kids, fieldMap, span, rawKids, tlog, ctx.state, tags) : projectChild(kids, proj, type);
|
|
14561
15705
|
} else if (build !== void 0) {
|
|
14562
15706
|
if (hostCst && host !== void 0) {
|
|
14563
|
-
nd = host(type, kids, fieldMap, span, rawKids, tlog,
|
|
15707
|
+
nd = host(type, kids, fieldMap, span, rawKids, tlog, ctx.state, tags);
|
|
14564
15708
|
} else {
|
|
14565
15709
|
nd = build(kids, fieldMap, span, rawKids, captureWide ? tlog : EMPTY_TL2, st);
|
|
14566
15710
|
}
|
|
@@ -14611,9 +15755,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14611
15755
|
let emitRefusal;
|
|
14612
15756
|
let emitReached;
|
|
14613
15757
|
{
|
|
14614
|
-
const extraIps =
|
|
14615
|
-
for (const s of prog.scans ?? []) for (const r of scanRefs(s)) extraIps.push(r[0]);
|
|
14616
|
-
for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
|
|
15758
|
+
const extraIps = assemblyExtraIps(prog);
|
|
14617
15759
|
const roots = [...Object.values(prog.rules), ...extraIps];
|
|
14618
15760
|
for (const ip of reachableSites(code, roots)) {
|
|
14619
15761
|
if (code[ip] === OP_DISPATCH) {
|
|
@@ -14648,6 +15790,8 @@ function assemble(t2, prog, cfg) {
|
|
|
14648
15790
|
}
|
|
14649
15791
|
const notChild = scalarTerminalNotChild(code, ip);
|
|
14650
15792
|
if (notChild >= 0) scalarFor(notChild);
|
|
15793
|
+
const peekChild = scalarTerminalPeekChild(code, ip);
|
|
15794
|
+
if (peekChild >= 0) scalarFor(peekChild);
|
|
14651
15795
|
}
|
|
14652
15796
|
const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
|
|
14653
15797
|
if (pre !== void 0) {
|
|
@@ -14706,9 +15850,12 @@ function assemble(t2, prog, cfg) {
|
|
|
14706
15850
|
adjacencyHolds,
|
|
14707
15851
|
t2.lexPrograms,
|
|
14708
15852
|
LEAD,
|
|
14709
|
-
triviaFieldCapture
|
|
15853
|
+
triviaFieldCapture,
|
|
15854
|
+
skipDeferredTrivia,
|
|
15855
|
+
collapseEmpty
|
|
14710
15856
|
);
|
|
14711
15857
|
emitReached = new Set(pre.reached);
|
|
15858
|
+
if (emitted.ext !== void 0) HYBRID = emitted;
|
|
14712
15859
|
}
|
|
14713
15860
|
try {
|
|
14714
15861
|
if (emitted !== void 0) throw new ServedByBuild();
|
|
@@ -14790,7 +15937,9 @@ function assemble(t2, prog, cfg) {
|
|
|
14790
15937
|
adjacencyHolds,
|
|
14791
15938
|
t2.lexPrograms,
|
|
14792
15939
|
LEAD,
|
|
14793
|
-
triviaFieldCapture
|
|
15940
|
+
triviaFieldCapture,
|
|
15941
|
+
skipDeferredTrivia,
|
|
15942
|
+
collapseEmpty
|
|
14794
15943
|
);
|
|
14795
15944
|
emitReached = em.reached;
|
|
14796
15945
|
} catch (e) {
|
|
@@ -14801,7 +15950,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14801
15950
|
}
|
|
14802
15951
|
function pieceAt(ip) {
|
|
14803
15952
|
const em = emitted;
|
|
14804
|
-
if (em !== void 0) {
|
|
15953
|
+
if (em !== void 0 && HYBRID === void 0) {
|
|
14805
15954
|
const p = em.byIp[ip];
|
|
14806
15955
|
if (p === void 0) throw new Error(`table emitter: no emitted body for site ${ip}`);
|
|
14807
15956
|
return p;
|
|
@@ -14831,6 +15980,37 @@ function assemble(t2, prog, cfg) {
|
|
|
14831
15980
|
}
|
|
14832
15981
|
const scans = scansArr;
|
|
14833
15982
|
const scanSkip = (prog.scanSkip ?? []).map((set) => set.map((r) => subtreeComb(r)));
|
|
15983
|
+
if (HYBRID !== void 0) {
|
|
15984
|
+
const em = HYBRID;
|
|
15985
|
+
em.bind(
|
|
15986
|
+
(s) => {
|
|
15987
|
+
const saved = SCAN;
|
|
15988
|
+
SCAN = s;
|
|
15989
|
+
return saved;
|
|
15990
|
+
},
|
|
15991
|
+
em.ext.map((ip) => link(ip))
|
|
15992
|
+
);
|
|
15993
|
+
const pieces2 = {};
|
|
15994
|
+
for (const [name, entryIp] of Object.entries(prog.rules)) {
|
|
15995
|
+
pieces2[name] = em.pieces[name] ?? link(entryIp);
|
|
15996
|
+
}
|
|
15997
|
+
for (const ip of emitReached) reached.add(ip);
|
|
15998
|
+
return {
|
|
15999
|
+
pieces: pieces2,
|
|
16000
|
+
end: () => EC.e,
|
|
16001
|
+
begin: (ctx) => {
|
|
16002
|
+
begin(ctx);
|
|
16003
|
+
em.begin(ctx);
|
|
16004
|
+
},
|
|
16005
|
+
finish: () => {
|
|
16006
|
+
em.finish();
|
|
16007
|
+
finish();
|
|
16008
|
+
},
|
|
16009
|
+
scanSkip,
|
|
16010
|
+
reached,
|
|
16011
|
+
emitRefusal: void 0
|
|
16012
|
+
};
|
|
16013
|
+
}
|
|
14834
16014
|
if (emitted !== void 0) {
|
|
14835
16015
|
const em = emitted;
|
|
14836
16016
|
return {
|
|
@@ -14866,6 +16046,15 @@ function assemble(t2, prog, cfg) {
|
|
|
14866
16046
|
}
|
|
14867
16047
|
return { pieces, end: () => EC.e, begin, finish, scanSkip, reached, emitRefusal };
|
|
14868
16048
|
}
|
|
16049
|
+
var SITE_COUNTS;
|
|
16050
|
+
function countedPiece(piece, ip) {
|
|
16051
|
+
const counts = SITE_COUNTS;
|
|
16052
|
+
if (counts === void 0) return piece;
|
|
16053
|
+
return (input, pos, ctx) => {
|
|
16054
|
+
counts[ip]++;
|
|
16055
|
+
return piece(input, pos, ctx);
|
|
16056
|
+
};
|
|
16057
|
+
}
|
|
14869
16058
|
var AssemblyCache = class {
|
|
14870
16059
|
t;
|
|
14871
16060
|
prog;
|
|
@@ -15017,7 +16206,7 @@ function emitClassPool(classes) {
|
|
|
15017
16206
|
if (classes.length < 2) return array;
|
|
15018
16207
|
const delimiter = "|/~?^`".split("").find((ch2) => classes.every((spec) => !spec.includes(ch2)));
|
|
15019
16208
|
if (delimiter === void 0) return array;
|
|
15020
|
-
const split =
|
|
16209
|
+
const split = `/* @__PURE__ */ ${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
|
|
15021
16210
|
return split.length < array.length ? split : array;
|
|
15022
16211
|
}
|
|
15023
16212
|
function emitConst(v) {
|
|
@@ -15068,9 +16257,7 @@ function emitDispatchSpec(d) {
|
|
|
15068
16257
|
function emitAssemblies(prog, cfgs) {
|
|
15069
16258
|
if (cfgs.length === 0) return ["a:[],"];
|
|
15070
16259
|
const t2 = resolveTable(prog);
|
|
15071
|
-
const extraIps =
|
|
15072
|
-
for (const s of prog.scans ?? []) for (const r of scanRefs(s)) extraIps.push(r[0]);
|
|
15073
|
-
for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
|
|
16260
|
+
const extraIps = assemblyExtraIps(prog);
|
|
15074
16261
|
const out = [];
|
|
15075
16262
|
const seen = /* @__PURE__ */ new Set();
|
|
15076
16263
|
for (const cfg of cfgs) {
|
|
@@ -15079,7 +16266,7 @@ function emitAssemblies(prog, cfgs) {
|
|
|
15079
16266
|
seen.add(key);
|
|
15080
16267
|
let em;
|
|
15081
16268
|
try {
|
|
15082
|
-
em = emitAssemblySource(t2, prog, cfg, extraIps, true);
|
|
16269
|
+
em = emitAssemblySource(t2, prog, cfg, extraIps, true, cfg.select);
|
|
15083
16270
|
} catch (e) {
|
|
15084
16271
|
if (e instanceof Unemittable) continue;
|
|
15085
16272
|
throw e;
|
|
@@ -16878,16 +18065,16 @@ function ownSource(fn) {
|
|
|
16878
18065
|
return typeof name === "string" && name.length > 0 && globalThis[name] === fn ? name : null;
|
|
16879
18066
|
}
|
|
16880
18067
|
function compile(target, second, third) {
|
|
16881
|
-
if (!
|
|
18068
|
+
if (!isCombinator2(target)) return compileMap(target, second);
|
|
16882
18069
|
return compileRoot(target, second, third);
|
|
16883
18070
|
}
|
|
16884
|
-
function
|
|
18071
|
+
function isCombinator2(x) {
|
|
16885
18072
|
return typeof x === "object" && x !== null && typeof x.parse === "function" && "_def" in x;
|
|
16886
18073
|
}
|
|
16887
18074
|
function compileMap(grammar, opts = {}) {
|
|
16888
18075
|
const entries = [];
|
|
16889
18076
|
for (const [key, value] of Object.entries(grammar)) {
|
|
16890
|
-
if (!
|
|
18077
|
+
if (!isCombinator2(value)) throw new TypeError(`compile: grammar entry "${key}" is not a parser`);
|
|
16891
18078
|
if (value._def.tag === "lazy") {
|
|
16892
18079
|
try {
|
|
16893
18080
|
value._def.thunk();
|
|
@@ -17201,49 +18388,6 @@ function digestValue(value, prefix = "", options) {
|
|
|
17201
18388
|
return sha.digest("hex");
|
|
17202
18389
|
}
|
|
17203
18390
|
|
|
17204
|
-
// src/combinators/attempt.ts
|
|
17205
|
-
function containOption(options) {
|
|
17206
|
-
if (options === void 0) return false;
|
|
17207
|
-
for (const key of Object.keys(options)) {
|
|
17208
|
-
if (key !== "contain") throw new TypeError(`attempt(): unknown option ${JSON.stringify(key)}`);
|
|
17209
|
-
}
|
|
17210
|
-
if (options.contain !== void 0 && typeof options.contain !== "boolean") {
|
|
17211
|
-
throw new TypeError("attempt(): `contain` must be a boolean");
|
|
17212
|
-
}
|
|
17213
|
-
return options.contain === true;
|
|
17214
|
-
}
|
|
17215
|
-
function attempt(parser2, options) {
|
|
17216
|
-
const contain = containOption(options);
|
|
17217
|
-
const guardable = parser2._meta.firstSet.kind !== "any" && !matchesEmpty(parser2);
|
|
17218
|
-
let failExpected;
|
|
17219
|
-
return {
|
|
17220
|
-
_tag: "attempt",
|
|
17221
|
-
_meta: parser2._meta,
|
|
17222
|
-
_def: contain ? { tag: "attempt", parser: parser2, contain: true } : { tag: "attempt", parser: parser2 },
|
|
17223
|
-
parse(input, pos, ctx) {
|
|
17224
|
-
if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(parser2, input, pos)) {
|
|
17225
|
-
if (failExpected === void 0) {
|
|
17226
|
-
const e = deriveExpected(parser2);
|
|
17227
|
-
failExpected = e.length > 0 ? e : [parser2._tag];
|
|
17228
|
-
}
|
|
17229
|
-
return { ok: false, expected: failExpected, span: { start: pos, end: pos } };
|
|
17230
|
-
}
|
|
17231
|
-
const mark = saveCstMark(ctx);
|
|
17232
|
-
const log = ctx._triviaLog?.length;
|
|
17233
|
-
const rootLog = ctx._rootTriviaLog?.length;
|
|
17234
|
-
const split = ctx._columnsSplit;
|
|
17235
|
-
const result = parser2.parse(input, pos, ctx);
|
|
17236
|
-
if (result.ok) return result;
|
|
17237
|
-
rollbackCstCapture(ctx, mark);
|
|
17238
|
-
ctx._columnsSplit = split;
|
|
17239
|
-
if (log !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== log) ctx._triviaLog.length = log;
|
|
17240
|
-
if (rootLog !== void 0 && ctx._rootTriviaLog && ctx._rootTriviaLog.length !== rootLog) ctx._rootTriviaLog.length = rootLog;
|
|
17241
|
-
if (result.committed && !contain) return result;
|
|
17242
|
-
return { ok: false, expected: result.expected, span: { start: pos, end: pos } };
|
|
17243
|
-
}
|
|
17244
|
-
};
|
|
17245
|
-
}
|
|
17246
|
-
|
|
17247
18391
|
// src/combinators/not.ts
|
|
17248
18392
|
function not(combinator) {
|
|
17249
18393
|
const meta = {
|