parseman 0.57.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 +1799 -962
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/cli/index.js +1928 -1091
- package/dist/cli/index.js.map +3 -3
- package/dist/combinators/dispatch.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/index.js +1016 -177
- package/dist/index.js.map +3 -3
- package/dist/plugin/index.d.ts +25 -1
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +1209 -236
- package/dist/plugin/index.js.map +3 -3
- package/dist/table/assemble.d.ts.map +1 -1
- package/dist/table/compile-rule-map.d.ts.map +1 -1
- package/dist/table/emit-assembly.d.ts +1 -1
- package/dist/table/emit-assembly.d.ts.map +1 -1
- package/dist/table/emit.d.ts.map +1 -1
- package/dist/table/encode.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 +1369 -259
- 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 +8 -0
- package/dist/table/ops.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/site-labels.d.ts +66 -0
- package/dist/table/site-labels.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/combinators/dispatch.ts +12 -3
- package/src/compiler/token-alphabet.ts +57 -17
- package/src/cst/capture-buffer.ts +25 -0
- package/src/plugin/index.ts +230 -35
- package/src/table/assemble.ts +252 -62
- package/src/table/child-slots.ts +2 -2
- package/src/table/compile-rule-map.ts +14 -5
- package/src/table/emit-assembly.ts +112 -23
- package/src/table/emit.ts +3 -1
- package/src/table/encode.ts +80 -14
- package/src/table/exec.ts +27 -8
- 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 +9 -1
- package/src/table/run-support.ts +35 -0
- package/src/table/scalar-terminal.ts +8 -0
- package/src/table/site-labels.ts +135 -4
- 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) {
|
|
@@ -2346,6 +2371,9 @@ function parser(opts, root) {
|
|
|
2346
2371
|
};
|
|
2347
2372
|
return grammar;
|
|
2348
2373
|
}
|
|
2374
|
+
function noTrivia(root) {
|
|
2375
|
+
return parser({ trivia: null }, root);
|
|
2376
|
+
}
|
|
2349
2377
|
var _analyzed = /* @__PURE__ */ new WeakSet();
|
|
2350
2378
|
function parse(combinator, input, opts = {}) {
|
|
2351
2379
|
if (!_analyzed.has(combinator)) {
|
|
@@ -3840,17 +3868,59 @@ function buildLexBodyRecognizer(spec, constants) {
|
|
|
3840
3868
|
};
|
|
3841
3869
|
}
|
|
3842
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
|
+
|
|
3843
3914
|
// src/table/lex-program.ts
|
|
3844
3915
|
var LEX_NODE_TERMINAL = 0;
|
|
3845
3916
|
var LEX_NODE_SEQUENCE2 = 1;
|
|
3846
3917
|
var LEX_NODE_SEQUENCE3 = 2;
|
|
3847
3918
|
var LEX_NODE_SEQUENCE4 = 3;
|
|
3848
3919
|
var LEX_NODE_SEQUENCE5 = 4;
|
|
3849
|
-
var
|
|
3850
|
-
var LEX_NODE_CHOICE4 = 6;
|
|
3851
|
-
var LEX_NODE_CHOICE8 = 7;
|
|
3920
|
+
var LEX_NODE_CHOICE = 5;
|
|
3852
3921
|
var LEX_NODE_NOT = 8;
|
|
3853
3922
|
var LEX_NODE_OPTIONAL = 9;
|
|
3923
|
+
var LEX_NODE_REPEAT = 10;
|
|
3854
3924
|
function lexProgramDigest(words) {
|
|
3855
3925
|
let hash = 2166136261;
|
|
3856
3926
|
for (const word of words) {
|
|
@@ -3879,85 +3949,114 @@ function trackLexLines(ctx, input, end) {
|
|
|
3879
3949
|
ctx._lineScannedTo = end;
|
|
3880
3950
|
}
|
|
3881
3951
|
function terminalNode(matcher, failure, tracksLines) {
|
|
3882
|
-
const match = (input, pos) => {
|
|
3883
|
-
const result = matcher(input, pos);
|
|
3884
|
-
return result < 0 ? -1 : result / 2;
|
|
3885
|
-
};
|
|
3886
3952
|
return {
|
|
3887
|
-
match,
|
|
3953
|
+
match: (input, pos) => {
|
|
3954
|
+
const result = matcher(input, pos);
|
|
3955
|
+
return result < 0 ? -1 : result / 2;
|
|
3956
|
+
},
|
|
3888
3957
|
run: (input, pos, ctx) => {
|
|
3889
|
-
const
|
|
3890
|
-
if (
|
|
3958
|
+
const result = matcher(input, pos);
|
|
3959
|
+
if (result < 0) {
|
|
3891
3960
|
ctx._fe = pos;
|
|
3892
3961
|
ctx._fx = failure;
|
|
3893
3962
|
if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
|
|
3894
3963
|
return -1;
|
|
3895
3964
|
}
|
|
3965
|
+
const end = result / 2;
|
|
3896
3966
|
if (tracksLines) trackLexLines(ctx, input, end);
|
|
3897
3967
|
return end;
|
|
3898
3968
|
}
|
|
3899
3969
|
};
|
|
3900
3970
|
}
|
|
3901
3971
|
function sequence2(a, b) {
|
|
3972
|
+
const am = a.match, bm = b.match, ar = a.run, br = b.run;
|
|
3902
3973
|
return {
|
|
3903
3974
|
match: (input, pos) => {
|
|
3904
|
-
const e0 =
|
|
3905
|
-
return e0 < 0 ? -1 :
|
|
3975
|
+
const e0 = am(input, pos);
|
|
3976
|
+
return e0 < 0 ? -1 : bm(input, e0);
|
|
3906
3977
|
},
|
|
3907
3978
|
run: (input, pos, ctx) => {
|
|
3908
|
-
const e0 =
|
|
3979
|
+
const e0 = ar(input, pos, ctx);
|
|
3909
3980
|
if (e0 < 0) return -1;
|
|
3910
3981
|
ctx._fc = false;
|
|
3911
|
-
return
|
|
3982
|
+
return br(input, e0, ctx);
|
|
3912
3983
|
}
|
|
3913
3984
|
};
|
|
3914
3985
|
}
|
|
3915
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;
|
|
3916
3988
|
return {
|
|
3917
3989
|
match: (input, pos) => {
|
|
3918
|
-
const e0 =
|
|
3990
|
+
const e0 = am(input, pos);
|
|
3919
3991
|
if (e0 < 0) return -1;
|
|
3920
|
-
const e1 =
|
|
3921
|
-
return e1 < 0 ? -1 :
|
|
3992
|
+
const e1 = bm(input, e0);
|
|
3993
|
+
return e1 < 0 ? -1 : cm(input, e1);
|
|
3922
3994
|
},
|
|
3923
3995
|
run: (input, pos, ctx) => {
|
|
3924
|
-
const e0 =
|
|
3996
|
+
const e0 = ar(input, pos, ctx);
|
|
3925
3997
|
if (e0 < 0) return -1;
|
|
3926
3998
|
ctx._fc = false;
|
|
3927
|
-
const e1 =
|
|
3999
|
+
const e1 = br(input, e0, ctx);
|
|
3928
4000
|
if (e1 < 0) return -1;
|
|
3929
4001
|
ctx._fc = false;
|
|
3930
|
-
return
|
|
4002
|
+
return cr(input, e1, ctx);
|
|
3931
4003
|
}
|
|
3932
4004
|
};
|
|
3933
4005
|
}
|
|
3934
4006
|
function sequence4(a, b, c, d) {
|
|
3935
|
-
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;
|
|
3936
4009
|
return {
|
|
3937
4010
|
match: (input, pos) => {
|
|
3938
|
-
const
|
|
3939
|
-
|
|
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);
|
|
3940
4017
|
},
|
|
3941
4018
|
run: (input, pos, ctx) => {
|
|
3942
|
-
const
|
|
3943
|
-
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;
|
|
3944
4027
|
ctx._fc = false;
|
|
3945
|
-
return
|
|
4028
|
+
return dr(input, e2, ctx);
|
|
3946
4029
|
}
|
|
3947
4030
|
};
|
|
3948
4031
|
}
|
|
3949
4032
|
function sequence5(a, b, c, d, e) {
|
|
3950
|
-
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;
|
|
3951
4035
|
return {
|
|
3952
4036
|
match: (input, pos) => {
|
|
3953
|
-
const
|
|
3954
|
-
|
|
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);
|
|
3955
4045
|
},
|
|
3956
4046
|
run: (input, pos, ctx) => {
|
|
3957
|
-
const
|
|
3958
|
-
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;
|
|
3959
4055
|
ctx._fc = false;
|
|
3960
|
-
|
|
4056
|
+
const e3 = dr(input, e2, ctx);
|
|
4057
|
+
if (e3 < 0) return -1;
|
|
4058
|
+
ctx._fc = false;
|
|
4059
|
+
return er(input, e3, ctx);
|
|
3961
4060
|
}
|
|
3962
4061
|
};
|
|
3963
4062
|
}
|
|
@@ -3970,9 +4069,9 @@ function appendExpected(acc, values) {
|
|
|
3970
4069
|
function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
3971
4070
|
let matchTail = () => -1;
|
|
3972
4071
|
for (let i = arms.length - 1; i >= 0; i--) {
|
|
3973
|
-
const
|
|
4072
|
+
const armMatch = arms[i].match, next = matchTail;
|
|
3974
4073
|
matchTail = (input, pos) => {
|
|
3975
|
-
const end =
|
|
4074
|
+
const end = armMatch(input, pos);
|
|
3976
4075
|
return end < 0 ? next(input, pos) : end;
|
|
3977
4076
|
};
|
|
3978
4077
|
}
|
|
@@ -3982,7 +4081,7 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
3982
4081
|
return -1;
|
|
3983
4082
|
};
|
|
3984
4083
|
for (let i = arms.length - 1; i >= 0; i--) {
|
|
3985
|
-
const
|
|
4084
|
+
const armRun = arms[i].run, cls = classes[i], staticExpected = armExpected[i], next = tail;
|
|
3986
4085
|
tail = (input, pos, ctx, lead2, acc, best) => {
|
|
3987
4086
|
if (cls !== void 0 && !classHas(cls, lead2)) {
|
|
3988
4087
|
return next(
|
|
@@ -3995,7 +4094,7 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
3995
4094
|
);
|
|
3996
4095
|
}
|
|
3997
4096
|
ctx._fc = false;
|
|
3998
|
-
const end =
|
|
4097
|
+
const end = armRun(input, pos, ctx);
|
|
3999
4098
|
if (end >= 0) return end;
|
|
4000
4099
|
const at = ctx._fe ?? pos;
|
|
4001
4100
|
if (at > best) {
|
|
@@ -4022,11 +4121,58 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
4022
4121
|
)
|
|
4023
4122
|
};
|
|
4024
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
|
+
}
|
|
4025
4170
|
function notNode(body, failure) {
|
|
4171
|
+
const bodyMatch = body.match;
|
|
4026
4172
|
return {
|
|
4027
|
-
match: (input, pos) =>
|
|
4173
|
+
match: (input, pos) => bodyMatch(input, pos) < 0 ? pos : -1,
|
|
4028
4174
|
run: (input, pos, ctx) => {
|
|
4029
|
-
if (
|
|
4175
|
+
if (bodyMatch(input, pos) < 0) return pos;
|
|
4030
4176
|
ctx._fe = pos;
|
|
4031
4177
|
ctx._fx = failure;
|
|
4032
4178
|
return -1;
|
|
@@ -4034,18 +4180,57 @@ function notNode(body, failure) {
|
|
|
4034
4180
|
};
|
|
4035
4181
|
}
|
|
4036
4182
|
function optionalNode(body) {
|
|
4183
|
+
const bodyMatch = body.match, bodyRun = body.run;
|
|
4037
4184
|
return {
|
|
4038
4185
|
match: (input, pos) => {
|
|
4039
|
-
const end =
|
|
4186
|
+
const end = bodyMatch(input, pos);
|
|
4040
4187
|
return end < 0 ? pos : end;
|
|
4041
4188
|
},
|
|
4042
4189
|
run: (input, pos, ctx) => {
|
|
4043
4190
|
ctx._fc = false;
|
|
4044
|
-
const end =
|
|
4191
|
+
const end = bodyRun(input, pos, ctx);
|
|
4045
4192
|
return end < 0 && !committed(ctx) ? pos : end;
|
|
4046
4193
|
}
|
|
4047
4194
|
};
|
|
4048
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
|
+
}
|
|
4049
4234
|
function fixedTreeRunner(words, matchers, classes, expected) {
|
|
4050
4235
|
const stack = [];
|
|
4051
4236
|
const pop = () => {
|
|
@@ -4073,9 +4258,14 @@ function fixedTreeRunner(words, matchers, classes, expected) {
|
|
|
4073
4258
|
else stack.push(sequence5(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4]));
|
|
4074
4259
|
continue;
|
|
4075
4260
|
}
|
|
4076
|
-
if (op
|
|
4077
|
-
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");
|
|
4078
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
|
+
}
|
|
4079
4269
|
if (choiceFx === void 0) throw new TypeError("table lexical tree choice has an invalid expected set");
|
|
4080
4270
|
const armClasses = [];
|
|
4081
4271
|
const armFx = [];
|
|
@@ -4088,7 +4278,7 @@ function fixedTreeRunner(words, matchers, classes, expected) {
|
|
|
4088
4278
|
armFx.push(fx);
|
|
4089
4279
|
}
|
|
4090
4280
|
const arms = Array.from({ length: count }, pop).reverse();
|
|
4091
|
-
stack.push(choiceNode(arms, armClasses, armFx, choiceFx));
|
|
4281
|
+
stack.push(exclusive === 1 ? exclusiveChoiceNode(arms, armClasses, choiceFx) : choiceNode(arms, armClasses, armFx, choiceFx));
|
|
4092
4282
|
continue;
|
|
4093
4283
|
}
|
|
4094
4284
|
if (op === LEX_NODE_NOT) {
|
|
@@ -4101,6 +4291,14 @@ function fixedTreeRunner(words, matchers, classes, expected) {
|
|
|
4101
4291
|
stack.push(optionalNode(pop()));
|
|
4102
4292
|
continue;
|
|
4103
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
|
+
}
|
|
4104
4302
|
throw new TypeError("table lexical tree has an unknown fixed body");
|
|
4105
4303
|
}
|
|
4106
4304
|
if (stack.length !== 1) throw new TypeError("table lexical tree does not resolve to one root body");
|
|
@@ -4469,143 +4667,764 @@ function resolveTable(prog) {
|
|
|
4469
4667
|
return built;
|
|
4470
4668
|
}
|
|
4471
4669
|
|
|
4472
|
-
// src/
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
switch (d.tag) {
|
|
4476
|
-
case "sequence":
|
|
4477
|
-
case "choice":
|
|
4478
|
-
return d.parsers;
|
|
4479
|
-
case "dispatch":
|
|
4480
|
-
return [
|
|
4481
|
-
d.selector,
|
|
4482
|
-
...d.cases.map((c) => c.parser),
|
|
4483
|
-
...d.matchers ? d.matchers.map((c) => c.parser) : [],
|
|
4484
|
-
...d.otherwise === void 0 ? [] : [d.otherwise]
|
|
4485
|
-
];
|
|
4486
|
-
case "sepBy":
|
|
4487
|
-
return [d.parser, d.separator];
|
|
4488
|
-
case "recover":
|
|
4489
|
-
return [d.parser, d.sentinel];
|
|
4490
|
-
case "scanTo":
|
|
4491
|
-
return [
|
|
4492
|
-
d.sentinel,
|
|
4493
|
-
...d.skip,
|
|
4494
|
-
...d.recoverAt === void 0 ? [] : [d.recoverAt],
|
|
4495
|
-
...d.stopAt === void 0 ? [] : [d.stopAt]
|
|
4496
|
-
];
|
|
4497
|
-
case "grammar":
|
|
4498
|
-
return d.triviaParser ? [d.parser, d.triviaParser] : [d.parser];
|
|
4499
|
-
case "routed":
|
|
4500
|
-
return d.fallback ? [d.fallback] : [];
|
|
4501
|
-
case "lines":
|
|
4502
|
-
return [d.prefix, d.body, ...d.first === void 0 ? [] : [d.first], ...d.lazy === void 0 ? [] : [d.lazy]];
|
|
4503
|
-
case "columns":
|
|
4504
|
-
return [];
|
|
4505
|
-
// A `lazy` is a REFERENCE, not a subtree. Descending through it would make
|
|
4506
|
-
// every rule's walk cover the whole reachable grammar — site paths become
|
|
4507
|
-
// nonsense, and a structural hash includes half the grammar. Treated as a
|
|
4508
|
-
// leaf, keyed by the rule name it refers to, which is also the right
|
|
4509
|
-
// semantics: two productions referencing `g.Ident` really do fill that slot
|
|
4510
|
-
// the same way.
|
|
4511
|
-
case "lazy":
|
|
4512
|
-
case "literal":
|
|
4513
|
-
case "regex":
|
|
4514
|
-
case "keywords":
|
|
4515
|
-
case "guard":
|
|
4516
|
-
case "adjacency":
|
|
4517
|
-
case "unknown":
|
|
4518
|
-
return [];
|
|
4519
|
-
default: {
|
|
4520
|
-
const rec = d;
|
|
4521
|
-
return rec.parser ? [rec.parser] : [];
|
|
4522
|
-
}
|
|
4523
|
-
}
|
|
4670
|
+
// src/combinators/adjacency.ts
|
|
4671
|
+
function adjacencyOf(p) {
|
|
4672
|
+
return p._def.tag === "adjacency" ? p._def : null;
|
|
4524
4673
|
}
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
if (b.kind === "any") return a;
|
|
4529
|
-
if (a.kind === "empty" || b.kind === "empty") return { kind: "empty" };
|
|
4530
|
-
const ranges = [];
|
|
4531
|
-
for (const ra of a.ranges) for (const rb of b.ranges) {
|
|
4532
|
-
const lo = Math.max(ra.lo, rb.lo);
|
|
4533
|
-
const hi = Math.min(ra.hi, rb.hi);
|
|
4534
|
-
if (lo <= hi) ranges.push({ lo, hi });
|
|
4535
|
-
}
|
|
4536
|
-
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("|")})`;
|
|
4537
4677
|
}
|
|
4538
|
-
function
|
|
4539
|
-
|
|
4540
|
-
for (const s of sets) {
|
|
4541
|
-
if (s.kind === "any") return { kind: "any" };
|
|
4542
|
-
if (s.kind === "empty") continue;
|
|
4543
|
-
acc = acc.kind === "ranges" ? { kind: "ranges", ranges: [...acc.ranges, ...s.ranges] } : s;
|
|
4544
|
-
}
|
|
4545
|
-
return acc;
|
|
4678
|
+
function holdsAdjacency(input, cur, ctx, def) {
|
|
4679
|
+
return adjacencyHolds(input, cur, ctx, def.polarity === "notAdjacent", def.kinds);
|
|
4546
4680
|
}
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
if (
|
|
4550
|
-
if (
|
|
4551
|
-
|
|
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;
|
|
4552
4689
|
}
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
var SUGGESTIONS = {
|
|
4556
|
-
"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.",
|
|
4557
|
-
"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.",
|
|
4558
|
-
"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.",
|
|
4559
|
-
"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.",
|
|
4560
|
-
"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.",
|
|
4561
|
-
"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."
|
|
4562
|
-
};
|
|
4563
|
-
function refineSuggestion(cause, arm) {
|
|
4564
|
-
if (cause !== "broad-recognizer") return SUGGESTIONS[cause];
|
|
4565
|
-
const lead2 = peelToLeading(arm);
|
|
4566
|
-
const d = lead2._def;
|
|
4567
|
-
if (d.tag === "regex" && KEYWORD_REGEX_RE.test(d.source)) {
|
|
4568
|
-
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.
|
|
4569
|
-
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.`;
|
|
4570
|
-
}
|
|
4571
|
-
if (d.tag === "scanTo") {
|
|
4572
|
-
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.";
|
|
4573
|
-
}
|
|
4574
|
-
return SUGGESTIONS[cause];
|
|
4690
|
+
function adjacencyFail(pos, def) {
|
|
4691
|
+
return { ok: false, expected: [adjacencyExpected(def)], span: { start: pos, end: pos } };
|
|
4575
4692
|
}
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
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;
|
|
5402
|
+
switch (d.tag) {
|
|
5403
|
+
case "literal":
|
|
5404
|
+
case "regex":
|
|
5405
|
+
case "keywords":
|
|
5406
|
+
return isAny(p._meta.firstSet) ? { cause: "broad-recognizer", detail: `broad recognizer (${d.tag})` } : null;
|
|
5407
|
+
case "not":
|
|
5408
|
+
return { cause: "leading-not", detail: "leading not(...) (first-set ANY)" };
|
|
5409
|
+
// peek() CARRIES its body's first-set, so it is only broad when the body is
|
|
5410
|
+
// (or the body is nullable) — walk in for the real cause.
|
|
5411
|
+
case "peek":
|
|
5412
|
+
return walk(d.parser);
|
|
5413
|
+
case "scanTo":
|
|
5414
|
+
return { cause: "broad-recognizer", detail: "scanTo (any first char)" };
|
|
5415
|
+
// A run opens with its first line's prefix.
|
|
5416
|
+
case "lines":
|
|
5417
|
+
return walk(d.first ?? d.prefix);
|
|
5418
|
+
// `guard` (the `gate()` state predicate) has a genuinely-`any` first-set of
|
|
5419
|
+
// its own — it is the poison. `withCtx`/`recover` FORWARD their inner
|
|
5420
|
+
// first-set (see firstSetOf), so a broad result comes from the inner parser:
|
|
5421
|
+
// walk into it for a precise cause.
|
|
5422
|
+
case "guard":
|
|
5423
|
+
return { cause: "opaque-wrapper", detail: `opaque wrapper (${d.tag})` };
|
|
5424
|
+
// Zero-width and dropped from a sequence's first-set (isZeroWidthAssertion),
|
|
5425
|
+
// so it is never the reason an arm is broad — but it can be reached as the
|
|
5426
|
+
// sole term of a degenerate arm. Report it precisely rather than as a wrapper.
|
|
5427
|
+
case "adjacency":
|
|
4609
5428
|
return { cause: "broad-recognizer", detail: `${d.polarity}() (zero-width assertion)` };
|
|
4610
5429
|
// attempt/withCtx/recover FORWARD their inner first-set (transparent for
|
|
4611
5430
|
// dispatch), so a broad result comes from the inner parser — walk into it.
|
|
@@ -5245,284 +6064,124 @@ function reachesMarked(root, successors, memo) {
|
|
|
5245
6064
|
const k = visit(child);
|
|
5246
6065
|
if (low[k] < low[at]) low[at] = low[k];
|
|
5247
6066
|
if (found[k]) found[at] = true;
|
|
5248
|
-
}
|
|
5249
|
-
}
|
|
5250
|
-
if (low[at] === at) {
|
|
5251
|
-
const answer = found[at];
|
|
5252
|
-
let member;
|
|
5253
|
-
do {
|
|
5254
|
-
member = stack.pop();
|
|
5255
|
-
memo.set(member, answer);
|
|
5256
|
-
} while (member !== node2);
|
|
5257
|
-
}
|
|
5258
|
-
return at;
|
|
5259
|
-
};
|
|
5260
|
-
return found[visit(root)];
|
|
5261
|
-
}
|
|
5262
|
-
|
|
5263
|
-
// src/compiler/degradation.ts
|
|
5264
|
-
function formatDegradation(d) {
|
|
5265
|
-
return `[parseman] degraded [${d.code}] ${d.where}: ${d.subject} \u2014 ${d.fellBackTo}; otherwise ${d.otherwise}`;
|
|
5266
|
-
}
|
|
5267
|
-
var DETAIL_CAP = 8;
|
|
5268
|
-
function formatDegradations(list) {
|
|
5269
|
-
const byCode = /* @__PURE__ */ new Map();
|
|
5270
|
-
for (const d of list) {
|
|
5271
|
-
const bucket = byCode.get(d.code);
|
|
5272
|
-
if (bucket) bucket.push(d);
|
|
5273
|
-
else byCode.set(d.code, [d]);
|
|
5274
|
-
}
|
|
5275
|
-
const out = [];
|
|
5276
|
-
for (const [code, items] of byCode) {
|
|
5277
|
-
for (const d of items.slice(0, DETAIL_CAP)) out.push(formatDegradation(d));
|
|
5278
|
-
if (items.length > DETAIL_CAP) {
|
|
5279
|
-
out.push(
|
|
5280
|
-
`[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.`
|
|
5281
|
-
);
|
|
5282
|
-
}
|
|
5283
|
-
}
|
|
5284
|
-
return out;
|
|
5285
|
-
}
|
|
5286
|
-
var _sinks = [];
|
|
5287
|
-
function beginDegradationCapture() {
|
|
5288
|
-
_sinks.push(/* @__PURE__ */ new Map());
|
|
5289
|
-
}
|
|
5290
|
-
function degradationCaptureDepth() {
|
|
5291
|
-
return _sinks.length;
|
|
5292
|
-
}
|
|
5293
|
-
function unwindDegradationCapture(depth) {
|
|
5294
|
-
const found = [];
|
|
5295
|
-
while (_sinks.length > depth) {
|
|
5296
|
-
const sink = _sinks.pop();
|
|
5297
|
-
found.unshift(...sink.values());
|
|
5298
|
-
}
|
|
5299
|
-
return found;
|
|
5300
|
-
}
|
|
5301
|
-
function resolveDegradationLevel(explicit) {
|
|
5302
|
-
if (explicit !== void 0) return explicit;
|
|
5303
|
-
const env = typeof process !== "undefined" ? process.env?.PARSEMAN_DEGRADATION : void 0;
|
|
5304
|
-
if (env === "off" || env === "warn" || env === "error") return env;
|
|
5305
|
-
return "warn";
|
|
5306
|
-
}
|
|
5307
|
-
function degradationKey(d) {
|
|
5308
|
-
return JSON.stringify([d.code, d.where, d.subject]);
|
|
5309
|
-
}
|
|
5310
|
-
function recordDegradation(d) {
|
|
5311
|
-
const level = resolveDegradationLevel();
|
|
5312
|
-
if (level === "off") return;
|
|
5313
|
-
const key = degradationKey(d);
|
|
5314
|
-
const sink = _sinks[_sinks.length - 1];
|
|
5315
|
-
if (sink) {
|
|
5316
|
-
if (!sink.has(key)) sink.set(key, d);
|
|
5317
|
-
return;
|
|
5318
|
-
}
|
|
5319
|
-
if (_immediate.has(key)) return;
|
|
5320
|
-
_immediate.add(key);
|
|
5321
|
-
if (level === "error") throw new Error(`parseman: degraded compilation path
|
|
5322
|
-
${formatDegradation(d)}`);
|
|
5323
|
-
console.warn(formatDegradation(d));
|
|
5324
|
-
}
|
|
5325
|
-
var _immediate = /* @__PURE__ */ new Set();
|
|
5326
|
-
function beginCompileDegradationDrain() {
|
|
5327
|
-
if (resolveDegradationLevel() === "off" || _sinks.length > 0) return () => {
|
|
5328
|
-
};
|
|
5329
|
-
const depth = degradationCaptureDepth();
|
|
5330
|
-
beginDegradationCapture();
|
|
5331
|
-
return (report) => {
|
|
5332
|
-
const found = unwindDegradationCapture(depth);
|
|
5333
|
-
if (!report || found.length === 0) return;
|
|
5334
|
-
const fresh = found.filter((d) => {
|
|
5335
|
-
const k = degradationKey(d);
|
|
5336
|
-
if (_immediate.has(k)) return false;
|
|
5337
|
-
_immediate.add(k);
|
|
5338
|
-
return true;
|
|
5339
|
-
});
|
|
5340
|
-
if (fresh.length === 0) return;
|
|
5341
|
-
const lines2 = formatDegradations(fresh);
|
|
5342
|
-
if (resolveDegradationLevel() === "error") {
|
|
5343
|
-
throw new Error(`parseman: ${fresh.length} degraded compilation path(s)
|
|
5344
|
-
${lines2.join("\n")}`);
|
|
5345
|
-
}
|
|
5346
|
-
for (const l of lines2) console.warn(l);
|
|
5347
|
-
};
|
|
5348
|
-
}
|
|
5349
|
-
|
|
5350
|
-
// src/compiler/build-arity.ts
|
|
5351
|
-
function cstOutputHost(build) {
|
|
5352
|
-
return build?._parsemanCstOutput === true;
|
|
5353
|
-
}
|
|
5354
|
-
var SINGLE_IDENT_ARROW_RE = /^[A-Za-z_$][\w$]*\s*=>/;
|
|
5355
|
-
var PARAM_LIST_OPEN_RE = /^(?:function\b[^(]*)?\(/;
|
|
5356
|
-
var NATIVE_CODE_RE = /\{\s*\[native code\]\s*\}/;
|
|
5357
|
-
var PARAM_HEAD_RE = /^[A-Za-z_$][\w$]*\s*\??\s*/;
|
|
5358
|
-
function confirmedBuildArity(src) {
|
|
5359
|
-
const s = src.trim();
|
|
5360
|
-
if (NATIVE_CODE_RE.test(s)) return null;
|
|
5361
|
-
if (/\barguments\b/.test(s)) return null;
|
|
5362
|
-
if (SINGLE_IDENT_ARROW_RE.test(s)) return 1;
|
|
5363
|
-
const inner = paramListText(s);
|
|
5364
|
-
if (inner === null) return null;
|
|
5365
|
-
if (inner.trim() === "") return 0;
|
|
5366
|
-
const parts = splitTopLevel(inner);
|
|
5367
|
-
if (parts === null) return null;
|
|
5368
|
-
for (const part of parts) {
|
|
5369
|
-
if (!isConfirmableParam(part.trim())) return null;
|
|
5370
|
-
}
|
|
5371
|
-
return parts.length;
|
|
5372
|
-
}
|
|
5373
|
-
function paramListText(s) {
|
|
5374
|
-
const open = PARAM_LIST_OPEN_RE.exec(s);
|
|
5375
|
-
if (!open) return null;
|
|
5376
|
-
const start = open[0].length;
|
|
5377
|
-
const end = matchingParen(s, start);
|
|
5378
|
-
if (end === null) return null;
|
|
5379
|
-
if (!s.startsWith("function") && !/^\s*=>/.test(s.slice(end + 1))) return null;
|
|
5380
|
-
return s.slice(start, end);
|
|
5381
|
-
}
|
|
5382
|
-
function matchingParen(s, start) {
|
|
5383
|
-
let depth = 0;
|
|
5384
|
-
for (let i = start; i < s.length; i++) {
|
|
5385
|
-
const c = s[i];
|
|
5386
|
-
if (c === '"' || c === "'" || c === "`") {
|
|
5387
|
-
const close = skipString(s, i);
|
|
5388
|
-
if (close === null) return null;
|
|
5389
|
-
i = close;
|
|
5390
|
-
continue;
|
|
5391
|
-
}
|
|
5392
|
-
if (c === "(" || c === "[" || c === "{") depth++;
|
|
5393
|
-
else if (c === "]" || c === "}") {
|
|
5394
|
-
if (--depth < 0) return null;
|
|
5395
|
-
} else if (c === ")") {
|
|
5396
|
-
if (depth === 0) return i;
|
|
5397
|
-
depth--;
|
|
5398
|
-
}
|
|
5399
|
-
}
|
|
5400
|
-
return null;
|
|
5401
|
-
}
|
|
5402
|
-
function skipString(s, open) {
|
|
5403
|
-
const quote = s[open];
|
|
5404
|
-
for (let i = open + 1; i < s.length; i++) {
|
|
5405
|
-
if (s[i] === "\\") {
|
|
5406
|
-
i++;
|
|
5407
|
-
continue;
|
|
5408
|
-
}
|
|
5409
|
-
if (s[i] === quote) return i;
|
|
5410
|
-
}
|
|
5411
|
-
return null;
|
|
5412
|
-
}
|
|
5413
|
-
function splitTopLevel(inner) {
|
|
5414
|
-
const parts = [];
|
|
5415
|
-
let depth = 0;
|
|
5416
|
-
let angle = 0;
|
|
5417
|
-
let last = 0;
|
|
5418
|
-
for (let i = 0; i < inner.length; i++) {
|
|
5419
|
-
const c = inner[i];
|
|
5420
|
-
if (c === "=" && inner[i + 1] === ">") {
|
|
5421
|
-
i++;
|
|
5422
|
-
continue;
|
|
5423
|
-
}
|
|
5424
|
-
if (c === '"' || c === "'" || c === "`") {
|
|
5425
|
-
const close = skipString(inner, i);
|
|
5426
|
-
if (close === null) return null;
|
|
5427
|
-
i = close;
|
|
5428
|
-
continue;
|
|
5429
|
-
}
|
|
5430
|
-
if (c === "(" || c === "[" || c === "{") depth++;
|
|
5431
|
-
else if (c === ")" || c === "]" || c === "}") {
|
|
5432
|
-
if (--depth < 0) return null;
|
|
5433
|
-
} else if (c === "<") angle++;
|
|
5434
|
-
else if (c === ">") {
|
|
5435
|
-
if (--angle < 0) return null;
|
|
5436
|
-
} else if (c === "," && depth === 0 && angle === 0) {
|
|
5437
|
-
parts.push(inner.slice(last, i));
|
|
5438
|
-
last = i + 1;
|
|
6067
|
+
}
|
|
5439
6068
|
}
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
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);
|
|
6076
|
+
}
|
|
6077
|
+
return at;
|
|
6078
|
+
};
|
|
6079
|
+
return found[visit(root)];
|
|
5444
6080
|
}
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
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;
|
|
5452
6102
|
}
|
|
5453
|
-
function
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
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;
|
|
5458
6113
|
continue;
|
|
5459
6114
|
}
|
|
5460
|
-
|
|
5461
|
-
if (prev === "<" || prev === ">" || prev === "!" || prev === "=") continue;
|
|
5462
|
-
return true;
|
|
6115
|
+
if (!sameValue(u, v, depth)) return false;
|
|
5463
6116
|
}
|
|
5464
|
-
return
|
|
5465
|
-
}
|
|
5466
|
-
function buildAnalysisSrc(def) {
|
|
5467
|
-
return def.buildSigSrc ?? def.buildSrc ?? def.build.toString();
|
|
6117
|
+
return true;
|
|
5468
6118
|
}
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
|
|
5474
|
-
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
}
|
|
5480
|
-
function
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
const
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
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;
|
|
5489
6182
|
}
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
function confirmedArityForDef(def) {
|
|
5493
|
-
if (def.buildArity !== void 0) return def.buildArity;
|
|
5494
|
-
const src = buildAnalysisSrc(def);
|
|
5495
|
-
const arity = confirmedBuildArity(src);
|
|
5496
|
-
if (arity !== null) return arity;
|
|
5497
|
-
const subject = `build reducer \`${(def.buildSrc ?? "<runtime fn>").trim().split("\n")[0].slice(0, 60)}\``;
|
|
5498
|
-
recordDegradation({
|
|
5499
|
-
code: "build-arity-unconfirmed",
|
|
5500
|
-
severity: "warn",
|
|
5501
|
-
where: `node("${def.type ?? "<inferred>"}")`,
|
|
5502
|
-
subject,
|
|
5503
|
-
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`,
|
|
5504
|
-
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"
|
|
5505
|
-
});
|
|
5506
|
-
return null;
|
|
5507
|
-
}
|
|
5508
|
-
function buildReadsRaw(def) {
|
|
5509
|
-
if (!def.build) return true;
|
|
5510
|
-
if (def.buildRawUnused === true) return false;
|
|
5511
|
-
const arity = confirmedArityForDef(def);
|
|
5512
|
-
if (arity === null) return true;
|
|
5513
|
-
return arity >= 4;
|
|
5514
|
-
}
|
|
5515
|
-
function buildReadsTrivia(def) {
|
|
5516
|
-
if (!def.build) return true;
|
|
5517
|
-
const arity = confirmedArityForDef(def);
|
|
5518
|
-
if (arity === null) return true;
|
|
5519
|
-
return arity >= 5;
|
|
5520
|
-
}
|
|
5521
|
-
function buildReadsState(def) {
|
|
5522
|
-
if (!def.build) return true;
|
|
5523
|
-
const arity = confirmedArityForDef(def);
|
|
5524
|
-
if (arity === null) return true;
|
|
5525
|
-
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);
|
|
5526
6185
|
}
|
|
5527
6186
|
|
|
5528
6187
|
// src/compiler/fields.ts
|
|
@@ -5650,10 +6309,16 @@ function branchUsesRouted(branch) {
|
|
|
5650
6309
|
return branch.usesRouted === true || parserUsesRouted(branch.parser);
|
|
5651
6310
|
}
|
|
5652
6311
|
function asciiFoldKey(key) {
|
|
5653
|
-
let
|
|
5654
|
-
for (
|
|
6312
|
+
let i = 0;
|
|
6313
|
+
for (; i < key.length; i++) {
|
|
5655
6314
|
const c = key.charCodeAt(i);
|
|
5656
|
-
|
|
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++) {
|
|
6320
|
+
const c = key.charCodeAt(i);
|
|
6321
|
+
out += c >= 65 && c <= 90 ? String.fromCharCode(c + 32) : key[i];
|
|
5657
6322
|
}
|
|
5658
6323
|
return out;
|
|
5659
6324
|
}
|
|
@@ -5701,6 +6366,7 @@ var OP_SCOPE_PLAIN = 41;
|
|
|
5701
6366
|
var OP_LEX_BODY = 42;
|
|
5702
6367
|
var OP_LEX_PROGRAM = 43;
|
|
5703
6368
|
var OP_SOURCE_LEAF = 44;
|
|
6369
|
+
var OP_RGATE = 45;
|
|
5704
6370
|
var OP_DISPATCH = 25;
|
|
5705
6371
|
var OP_ROUTED = 26;
|
|
5706
6372
|
var OP_NAMES = {
|
|
@@ -5720,6 +6386,7 @@ var OP_NAMES = {
|
|
|
5720
6386
|
[OP_PEEK]: "PEEK",
|
|
5721
6387
|
[OP_LEAF]: "LEAF",
|
|
5722
6388
|
[OP_SOURCE_LEAF]: "SOURCE_LEAF",
|
|
6389
|
+
[OP_RGATE]: "RGATE",
|
|
5723
6390
|
[OP_EMPTY]: "EMPTY",
|
|
5724
6391
|
[OP_LIT_TRACK]: "LIT_TRACK",
|
|
5725
6392
|
[OP_RX_TRACK]: "RX_TRACK",
|
|
@@ -5750,71 +6417,6 @@ var OP_NAMES = {
|
|
|
5750
6417
|
[OP_LEX_PROGRAM]: "LEX_PROGRAM"
|
|
5751
6418
|
};
|
|
5752
6419
|
|
|
5753
|
-
// src/combinators/adjacency.ts
|
|
5754
|
-
function adjacencyOf(p) {
|
|
5755
|
-
return p._def.tag === "adjacency" ? p._def : null;
|
|
5756
|
-
}
|
|
5757
|
-
function adjacencyExpected(def) {
|
|
5758
|
-
if (def.polarity === "adjacent") return "adjacent";
|
|
5759
|
-
return def.kinds === void 0 ? "notAdjacent" : `notAdjacent(${def.kinds.join("|")})`;
|
|
5760
|
-
}
|
|
5761
|
-
function holdsAdjacency(input, cur, ctx, def) {
|
|
5762
|
-
return adjacencyHolds(input, cur, ctx, def.polarity === "notAdjacent", def.kinds);
|
|
5763
|
-
}
|
|
5764
|
-
function adjacencyHolds(input, cur, ctx, negated, kinds) {
|
|
5765
|
-
const end = probeTriviaEnd(input, cur, ctx);
|
|
5766
|
-
if (!negated) return end === cur;
|
|
5767
|
-
if (end === cur) return false;
|
|
5768
|
-
if (kinds === void 0) return true;
|
|
5769
|
-
const want = resolveAdjacencyKindMask(ctx.trivia, kinds);
|
|
5770
|
-
const spec = analyzeLabeledTrivia(ctx.trivia);
|
|
5771
|
-
return (triviaKindMaskAt(input, cur, spec, ctx.state) & want) !== 0;
|
|
5772
|
-
}
|
|
5773
|
-
function adjacencyFail(pos, def) {
|
|
5774
|
-
return { ok: false, expected: [adjacencyExpected(def)], span: { start: pos, end: pos } };
|
|
5775
|
-
}
|
|
5776
|
-
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.";
|
|
5777
|
-
function adjacencyMisuse(polarity) {
|
|
5778
|
-
return new TypeError(`${polarity}(): ${NO_STANDALONE_PARSE}`);
|
|
5779
|
-
}
|
|
5780
|
-
function adjacencyCombinator(def) {
|
|
5781
|
-
const meta = {
|
|
5782
|
-
// Zero-width and never leading (sequence() rejects index 0), so it contributes
|
|
5783
|
-
// no first char. `isZeroWidthAssertion` drops it from a sequence's first-set
|
|
5784
|
-
// rather than letting `any` poison the enclosing choice's dispatch.
|
|
5785
|
-
firstSet: { kind: "any" },
|
|
5786
|
-
canMatchNewline: false,
|
|
5787
|
-
isTrivia: false
|
|
5788
|
-
};
|
|
5789
|
-
return {
|
|
5790
|
-
_tag: "adjacency",
|
|
5791
|
-
_meta: meta,
|
|
5792
|
-
_def: def,
|
|
5793
|
-
parse() {
|
|
5794
|
-
throw adjacencyMisuse(def.polarity);
|
|
5795
|
-
}
|
|
5796
|
-
};
|
|
5797
|
-
}
|
|
5798
|
-
function adjacent() {
|
|
5799
|
-
return adjacencyCombinator({ tag: "adjacency", polarity: "adjacent" });
|
|
5800
|
-
}
|
|
5801
|
-
function notAdjacent(options) {
|
|
5802
|
-
const kinds = options?.kinds;
|
|
5803
|
-
if (kinds !== void 0) {
|
|
5804
|
-
if (!Array.isArray(kinds) || kinds.length === 0) {
|
|
5805
|
-
throw new TypeError("notAdjacent({ kinds }): kinds must be a non-empty array of trivia category names.");
|
|
5806
|
-
}
|
|
5807
|
-
for (const k of kinds) {
|
|
5808
|
-
if (typeof k !== "string" || k.length === 0) {
|
|
5809
|
-
throw new TypeError(`notAdjacent({ kinds }): every kind must be a non-empty string, got ${JSON.stringify(k)}.`);
|
|
5810
|
-
}
|
|
5811
|
-
}
|
|
5812
|
-
}
|
|
5813
|
-
return adjacencyCombinator(
|
|
5814
|
-
kinds === void 0 ? { tag: "adjacency", polarity: "notAdjacent" } : { tag: "adjacency", polarity: "notAdjacent", kinds: [...kinds] }
|
|
5815
|
-
);
|
|
5816
|
-
}
|
|
5817
|
-
|
|
5818
6420
|
// src/combinators/node.ts
|
|
5819
6421
|
function unwrapChild(child) {
|
|
5820
6422
|
return child !== null && typeof child === "object" && child._tag === "leaf" ? child.value : child;
|
|
@@ -6017,7 +6619,10 @@ function selectOptionalSuffixLexBody(ir) {
|
|
|
6017
6619
|
const token2 = { strategy: "token", estimatedOps: 2, body };
|
|
6018
6620
|
return token2.estimatedOps < character.estimatedOps ? token2 : character;
|
|
6019
6621
|
}
|
|
6020
|
-
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) {
|
|
6021
6626
|
const outer = parser2._def;
|
|
6022
6627
|
if (outer.tag !== "token") return void 0;
|
|
6023
6628
|
let body = outer.parser;
|
|
@@ -6027,12 +6632,13 @@ function directTokenBodyParser(parser2, resolve) {
|
|
|
6027
6632
|
const wrapper = body._def;
|
|
6028
6633
|
if (wrapper.tag === "grammar") {
|
|
6029
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;
|
|
6030
6636
|
body = wrapper.parser;
|
|
6031
6637
|
continue;
|
|
6032
6638
|
}
|
|
6033
6639
|
if (wrapper.tag === "lazy") {
|
|
6034
6640
|
const target = resolvedLazyTarget(body, resolve);
|
|
6035
|
-
if (target === void 0) return void 0;
|
|
6641
|
+
if (target === void 0 || reinstallsRuleTrivia(body, target)) return void 0;
|
|
6036
6642
|
body = target;
|
|
6037
6643
|
continue;
|
|
6038
6644
|
}
|
|
@@ -6204,7 +6810,7 @@ function directNot2TokenBody(parser2, resolve) {
|
|
|
6204
6810
|
terminal
|
|
6205
6811
|
};
|
|
6206
6812
|
}
|
|
6207
|
-
function directFixedLexNode(parser2, resolve, active, pureOnly = false) {
|
|
6813
|
+
function directFixedLexNode(parser2, resolve, active, pureOnly = false, cleared = false) {
|
|
6208
6814
|
let current = parser2;
|
|
6209
6815
|
const wrappers = /* @__PURE__ */ new Set();
|
|
6210
6816
|
while (!wrappers.has(current)) {
|
|
@@ -6212,7 +6818,7 @@ function directFixedLexNode(parser2, resolve, active, pureOnly = false) {
|
|
|
6212
6818
|
const def = current._def;
|
|
6213
6819
|
if (def.tag === "lazy") {
|
|
6214
6820
|
const target = resolvedLazyTarget(current, resolve);
|
|
6215
|
-
if (target === void 0) return void 0;
|
|
6821
|
+
if (target === void 0 || reinstallsRuleTrivia(current, target)) return void 0;
|
|
6216
6822
|
current = target;
|
|
6217
6823
|
continue;
|
|
6218
6824
|
}
|
|
@@ -6230,30 +6836,33 @@ function directFixedLexNode(parser2, resolve, active, pureOnly = false) {
|
|
|
6230
6836
|
if (terminal !== void 0) return { kind: "terminal", terminal };
|
|
6231
6837
|
const def = current._def;
|
|
6232
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
|
+
}
|
|
6233
6842
|
if (!pureOnly || def.parser._def.tag !== "token" && (def.clearTrivia !== true || def.triviaParser !== void 0 || def.captureTrivia === true || def.rootCapture === "opaque")) return void 0;
|
|
6234
|
-
return directFixedLexNode(def.parser, resolve, active, true);
|
|
6843
|
+
return directFixedLexNode(def.parser, resolve, active, true, cleared);
|
|
6235
6844
|
}
|
|
6236
6845
|
if (def.tag === "sequence") {
|
|
6237
6846
|
if (def.parsers.length < 2 || def.parsers.length > 5) return void 0;
|
|
6238
|
-
const parts = def.parsers.map((part) => directFixedLexNode(part, resolve, active, pureOnly));
|
|
6847
|
+
const parts = def.parsers.map((part) => directFixedLexNode(part, resolve, active, pureOnly, cleared));
|
|
6239
6848
|
if (parts.some((part) => part === void 0)) return void 0;
|
|
6240
6849
|
return { kind: "sequence", parts };
|
|
6241
6850
|
}
|
|
6242
6851
|
if (def.tag === "choice") {
|
|
6243
|
-
if (def.parsers.length
|
|
6244
|
-
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));
|
|
6245
6854
|
if (arms.some((arm) => arm === void 0)) return void 0;
|
|
6246
|
-
const final = classifyFinalChoice(def.parsers, resolve);
|
|
6247
6855
|
return {
|
|
6248
6856
|
kind: "choice",
|
|
6249
6857
|
arms,
|
|
6250
|
-
|
|
6858
|
+
parsers: def.parsers,
|
|
6859
|
+
cleared,
|
|
6251
6860
|
armExpected: def.parsers.map(deriveExpected),
|
|
6252
6861
|
expected: def.parsers.flatMap(deriveExpected)
|
|
6253
6862
|
};
|
|
6254
6863
|
}
|
|
6255
6864
|
if (def.tag === "not") {
|
|
6256
|
-
const body = directFixedLexNode(def.parser, resolve, active, true);
|
|
6865
|
+
const body = directFixedLexNode(def.parser, resolve, active, true, cleared);
|
|
6257
6866
|
return body === void 0 ? void 0 : {
|
|
6258
6867
|
kind: "not",
|
|
6259
6868
|
body,
|
|
@@ -6261,18 +6870,28 @@ function directFixedLexNode(parser2, resolve, active, pureOnly = false) {
|
|
|
6261
6870
|
};
|
|
6262
6871
|
}
|
|
6263
6872
|
if (def.tag === "optional") {
|
|
6264
|
-
const body = directFixedLexNode(def.parser, resolve, active, pureOnly);
|
|
6873
|
+
const body = directFixedLexNode(def.parser, resolve, active, pureOnly, cleared);
|
|
6265
6874
|
return body === void 0 ? void 0 : { kind: "optional", body };
|
|
6266
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
|
+
}
|
|
6267
6885
|
return void 0;
|
|
6268
6886
|
} finally {
|
|
6269
6887
|
active.delete(current);
|
|
6270
6888
|
}
|
|
6271
6889
|
}
|
|
6272
6890
|
function directFixedTokenBody(parser2, resolve) {
|
|
6273
|
-
const
|
|
6891
|
+
const scope = { cleared: false };
|
|
6892
|
+
const body = directTokenBodyParser(parser2, resolve, scope);
|
|
6274
6893
|
if (body === void 0) return void 0;
|
|
6275
|
-
const root = directFixedLexNode(body, resolve, /* @__PURE__ */ new Set());
|
|
6894
|
+
const root = directFixedLexNode(body, resolve, /* @__PURE__ */ new Set(), false, scope.cleared);
|
|
6276
6895
|
return root === void 0 ? void 0 : { kind: "fixed-tree", root };
|
|
6277
6896
|
}
|
|
6278
6897
|
function directBalancedTokenBody(parser2, resolve) {
|
|
@@ -6519,13 +7138,16 @@ var Encoder = class {
|
|
|
6519
7138
|
}
|
|
6520
7139
|
case "choice": {
|
|
6521
7140
|
for (const arm of node2.arms) if (!emitNode(arm)) return false;
|
|
6522
|
-
const
|
|
6523
|
-
|
|
6524
|
-
|
|
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));
|
|
6525
7149
|
for (let i = 0; i < node2.arms.length; i++) {
|
|
6526
|
-
|
|
6527
|
-
words.push(first.kind === "ranges" ? this.charClass(first) : -1);
|
|
6528
|
-
words.push(this.expected(node2.armExpected[i]));
|
|
7150
|
+
words.push(classes[i], this.expected(node2.armExpected[i]));
|
|
6529
7151
|
}
|
|
6530
7152
|
return true;
|
|
6531
7153
|
}
|
|
@@ -6537,6 +7159,10 @@ var Encoder = class {
|
|
|
6537
7159
|
if (!emitNode(node2.body)) return false;
|
|
6538
7160
|
words.push(LEX_NODE_OPTIONAL);
|
|
6539
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;
|
|
6540
7166
|
}
|
|
6541
7167
|
};
|
|
6542
7168
|
if (!emitNode(body.root)) return void 0;
|
|
@@ -7042,6 +7668,50 @@ var Encoder = class {
|
|
|
7042
7668
|
if (!hasOwnTriviaBoundary(target)) return ip;
|
|
7043
7669
|
return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), ip);
|
|
7044
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
|
+
}
|
|
7045
7715
|
node(p) {
|
|
7046
7716
|
const lazyRef = p._def.tag === "lazy";
|
|
7047
7717
|
const scopeKey = lazyRef ? this.activeTrivia : void 0;
|
|
@@ -7166,6 +7836,10 @@ var Encoder = class {
|
|
|
7166
7836
|
return head;
|
|
7167
7837
|
}
|
|
7168
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
|
+
}
|
|
7169
7843
|
if (d.strategy.tag === "greedyClassify") {
|
|
7170
7844
|
const superIndex = d.strategy.superIndex;
|
|
7171
7845
|
const sup = this.node(d.parsers[superIndex]).ip;
|
|
@@ -7189,9 +7863,12 @@ var Encoder = class {
|
|
|
7189
7863
|
const kids = arms.map((c, k) => {
|
|
7190
7864
|
const src = order[k];
|
|
7191
7865
|
const checks = d.autoNot[src];
|
|
7192
|
-
const inner = this.node(c).ip;
|
|
7193
|
-
const ip = checks === null || checks === void 0 || checks.length === 0 ? inner : this.reject(inner, checks);
|
|
7194
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);
|
|
7195
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)));
|
|
7196
7873
|
return this.covWrap(gated, armCovIds?.[src], 1);
|
|
7197
7874
|
});
|
|
@@ -7515,6 +8192,7 @@ var Encoder = class {
|
|
|
7515
8192
|
const slots = (ip) => {
|
|
7516
8193
|
switch (this.code[ip]) {
|
|
7517
8194
|
case OP_GATE:
|
|
8195
|
+
case OP_RGATE:
|
|
7518
8196
|
return [ip + 2];
|
|
7519
8197
|
case OP_RULE:
|
|
7520
8198
|
case OP_OPT:
|
|
@@ -8742,6 +9420,7 @@ function childSlots(code, ip, out) {
|
|
|
8742
9420
|
case OP_LEAF:
|
|
8743
9421
|
case OP_SOURCE_LEAF:
|
|
8744
9422
|
case OP_ARMGATE:
|
|
9423
|
+
case OP_RGATE:
|
|
8745
9424
|
out.push(code[ip + 2]);
|
|
8746
9425
|
return true;
|
|
8747
9426
|
// `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
|
|
@@ -8825,6 +9504,42 @@ function reachableSites(code, roots) {
|
|
|
8825
9504
|
}
|
|
8826
9505
|
return seen;
|
|
8827
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
|
+
}
|
|
8828
9543
|
function transfer(code, ip, at, hostCst) {
|
|
8829
9544
|
const op = code[ip];
|
|
8830
9545
|
if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
|
|
@@ -8836,14 +9551,18 @@ function transfer(code, ip, at, hostCst) {
|
|
|
8836
9551
|
}
|
|
8837
9552
|
if (op === OP_NODE || op === OP_NODE_TRACK) {
|
|
8838
9553
|
const flags = code[ip + 3];
|
|
9554
|
+
if (passCollapse(code, ip, hostCst)) return at;
|
|
9555
|
+
const gated = gatedPassCollapse(code, ip, hostCst) !== void 0;
|
|
8839
9556
|
const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && ((flags & ~128) === 2 || flags === 18 || flags === 34);
|
|
8840
9557
|
if (directChildren) {
|
|
8841
|
-
|
|
9558
|
+
const framed2 = { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
|
|
9559
|
+
return gated ? meet(at, framed2) : framed2;
|
|
8842
9560
|
}
|
|
8843
9561
|
const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
|
|
8844
9562
|
const raw = !hostCst && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags & 2) !== 0 ? RAW_OMIT : RAW_CAPTURE;
|
|
8845
9563
|
if (at.buf && raw === at.raw && cap === at.cap) return at;
|
|
8846
|
-
|
|
9564
|
+
const framed = { tri: at.tri, buf: true, raw, cap };
|
|
9565
|
+
return gated ? meet(at, framed) : framed;
|
|
8847
9566
|
}
|
|
8848
9567
|
if (op === OP_TOKEN) {
|
|
8849
9568
|
if (at.tri === TRI_NONE && !at.buf) return at;
|
|
@@ -8881,6 +9600,40 @@ function computeSiteLabels(code, roots, hostCst) {
|
|
|
8881
9600
|
}
|
|
8882
9601
|
return { at: (ip) => labels.get(ip) ?? TOP };
|
|
8883
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
|
+
}
|
|
8884
9637
|
|
|
8885
9638
|
// src/table/scalar-terminal.ts
|
|
8886
9639
|
function makeScalarRecognizer(op, spec) {
|
|
@@ -8918,6 +9671,12 @@ function scalarTerminalNotChild(code, ip) {
|
|
|
8918
9671
|
const op = code[child];
|
|
8919
9672
|
return op === OP_RX || op === OP_LIT ? child : -1;
|
|
8920
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
|
+
}
|
|
8921
9680
|
function leadingScalarTerminal(code, ip, minDepth = 2, throughAttempt = true, throughPeek = false) {
|
|
8922
9681
|
const seen = /* @__PURE__ */ new Set();
|
|
8923
9682
|
let at = ip;
|
|
@@ -9095,6 +9854,59 @@ function leadingTriviaFieldAt(code, k, ip) {
|
|
|
9095
9854
|
return code[ip] === OP_FIELD && (fieldSpec(k[code[ip + 1]]).bits & FIELD_LEADING_TRIVIA) !== 0;
|
|
9096
9855
|
}
|
|
9097
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
|
+
|
|
9098
9910
|
// src/table/emit-assembly.ts
|
|
9099
9911
|
var Unemittable = class extends Error {
|
|
9100
9912
|
construct;
|
|
@@ -9175,7 +9987,10 @@ var EMITTED_PARAMS = [
|
|
|
9175
9987
|
"triviaFieldCapture",
|
|
9176
9988
|
// Appended for the deferred-commit trivia skip (`trivia-gap.ts`); old
|
|
9177
9989
|
// factories ignore it.
|
|
9178
|
-
"skipDeferredTrivia"
|
|
9990
|
+
"skipDeferredTrivia",
|
|
9991
|
+
// Appended for the pass-through collapse (`run-support.ts`); old factories
|
|
9992
|
+
// ignore it.
|
|
9993
|
+
"collapseEmpty"
|
|
9179
9994
|
];
|
|
9180
9995
|
var RUNTIME_PRELUDE = `
|
|
9181
9996
|
let _pfScan=null
|
|
@@ -9372,6 +10187,24 @@ ${fast}
|
|
|
9372
10187
|
${scanned}
|
|
9373
10188
|
}`;
|
|
9374
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
|
+
}
|
|
9375
10208
|
function leadSkip(hasTrivia, leadTrivia, skip) {
|
|
9376
10209
|
if (hasTrivia === "false") return "{}";
|
|
9377
10210
|
const call = `itemStart=${skip}(input,itemStart,ctx)`;
|
|
@@ -9413,6 +10246,7 @@ function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false, s
|
|
|
9413
10246
|
const reachable = [...reachableSites(code, roots)];
|
|
9414
10247
|
const labels = computeSiteLabels(code, roots, hostCst);
|
|
9415
10248
|
const scalarSpecs = /* @__PURE__ */ new Set();
|
|
10249
|
+
const nullable2 = /* @__PURE__ */ new Map();
|
|
9416
10250
|
const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
|
|
9417
10251
|
const largeChoiceLiteralFamilies = /* @__PURE__ */ new Map();
|
|
9418
10252
|
const largeChoiceScalarSequences = /* @__PURE__ */ new Map();
|
|
@@ -9737,9 +10571,7 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
9737
10571
|
const op = code[ip];
|
|
9738
10572
|
if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
|
|
9739
10573
|
if (op === OP_RULE) return code[ip + 1];
|
|
9740
|
-
if ((
|
|
9741
|
-
return code[ip + 2];
|
|
9742
|
-
}
|
|
10574
|
+
if (scopeIsIdentity(code, ip, labels.at(ip))) return code[ip + 2];
|
|
9743
10575
|
return void 0;
|
|
9744
10576
|
}
|
|
9745
10577
|
function lower(ip, fname) {
|
|
@@ -9861,6 +10693,22 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
9861
10693
|
return `${head}
|
|
9862
10694
|
if(${gateMissTest(ip)}){ctx._fe=pos;ctx._fx=${xf};return FAIL}
|
|
9863
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
|
+
}`;
|
|
10703
|
+
const resolved = t2.cc[code[ip + 1]];
|
|
10704
|
+
const ci = classes.push([resolved]) - 1;
|
|
10705
|
+
classPlan.push([code[ip + 1]]);
|
|
10706
|
+
const cls = hoist("cl", `CLS[${ci}][0]`);
|
|
10707
|
+
const xf = fxRef(code[ip + 3]);
|
|
10708
|
+
return `${head}
|
|
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)
|
|
9864
10712
|
}`;
|
|
9865
10713
|
}
|
|
9866
10714
|
case OP_ARMGATE: {
|
|
@@ -10135,23 +10983,33 @@ return FAIL
|
|
|
10135
10983
|
const p = tmp();
|
|
10136
10984
|
return `${head}
|
|
10137
10985
|
${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${emitMark(p, L.buf, L.raw, sinks)}
|
|
10138
|
-
const v=${child}(input,pos,ctx)
|
|
10986
|
+
${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
|
|
10139
10987
|
${emitRollback(p, L.buf, L.raw, sinks)}
|
|
10140
|
-
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}
|
|
10141
10989
|
ctx._fe=pos
|
|
10142
10990
|
ctx._fx=${xf}
|
|
10143
10991
|
return FAIL
|
|
10144
10992
|
}`;
|
|
10145
10993
|
}
|
|
10146
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
|
+
}
|
|
10147
11005
|
const child = link(code[ip + 1]);
|
|
10148
11006
|
const xf = fxRef(code[ip + 2]);
|
|
10149
11007
|
const p = tmp();
|
|
10150
11008
|
return `${head}
|
|
10151
11009
|
${lookaheadMiss(code[ip + 1], `ctx._fe=pos;ctx._fx=${xf};return FAIL`)}${emitMark(p, L.buf, L.raw, sinks)}
|
|
10152
|
-
const v=${child}(input,pos,ctx)
|
|
11010
|
+
${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
|
|
10153
11011
|
${emitRollback(p, L.buf, L.raw, sinks)}
|
|
10154
|
-
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}
|
|
10155
11013
|
EC.e=pos
|
|
10156
11014
|
return null
|
|
10157
11015
|
}`;
|
|
@@ -10222,7 +11080,7 @@ return v
|
|
|
10222
11080
|
);
|
|
10223
11081
|
} else {
|
|
10224
11082
|
const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
|
|
10225
|
-
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)));
|
|
10226
11084
|
}
|
|
10227
11085
|
names.push(vn);
|
|
10228
11086
|
}
|
|
@@ -10705,6 +11563,26 @@ return nd
|
|
|
10705
11563
|
const trailingTrivia = (flags & 128) !== 0;
|
|
10706
11564
|
const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
|
|
10707
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
|
+
` : "";
|
|
10708
11586
|
if (!hostCst && !tracked && build !== void 0 && proj < 0 && (leanFlags === 2 || (flags === 18 || flags === 34))) {
|
|
10709
11587
|
const fields = flags === 18;
|
|
10710
11588
|
const collapseChildren = flags === 34;
|
|
@@ -10739,7 +11617,7 @@ sCh.push(nd)
|
|
|
10739
11617
|
if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
|
|
10740
11618
|
}`;
|
|
10741
11619
|
return `${head}
|
|
10742
|
-
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
|
|
10743
11621
|
const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
|
|
10744
11622
|
const flat=[]
|
|
10745
11623
|
ctx._cstBuf=undefined
|
|
@@ -10814,7 +11692,7 @@ const hostKids=kids
|
|
|
10814
11692
|
const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
|
|
10815
11693
|
const tlog=buf.tl??EMPTY_TLOG`;
|
|
10816
11694
|
return `${head}
|
|
10817
|
-
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
|
|
10818
11696
|
const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf
|
|
10819
11697
|
${openCapture}
|
|
10820
11698
|
ctx.captureTrivia=${captureWide}
|
|
@@ -10884,9 +11762,15 @@ ext:[${externals.join(",")}],
|
|
|
10884
11762
|
bind:function(xs,ps){_xScan=xs
|
|
10885
11763
|
${externals.map((ip, i) => `_xp${ip}=ps[${i}]`).join("\n")}},
|
|
10886
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
|
+
};
|
|
10887
11771
|
const externalDefs = select === void 0 ? "" : `let _xScan
|
|
10888
11772
|
${externals.map((ip) => `let _xp${ip}
|
|
10889
|
-
function _px${ip}(input,pos,ctx){const o=_xScan(
|
|
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")}
|
|
10890
11774
|
`;
|
|
10891
11775
|
const source = `${RUNTIME_PRELUDE}${needsNoRawPrelude ? NO_RAW_RUNTIME_PRELUDE : ""}
|
|
10892
11776
|
${prelude.join("\n")}
|
|
@@ -11203,136 +12087,6 @@ function literal(value, opts = {}) {
|
|
|
11203
12087
|
};
|
|
11204
12088
|
}
|
|
11205
12089
|
|
|
11206
|
-
// src/combinators/sequence.ts
|
|
11207
|
-
function sequence(...parsers) {
|
|
11208
|
-
let adjacency = null;
|
|
11209
|
-
for (let i = 0; i < parsers.length; i++) {
|
|
11210
|
-
const a = adjacencyOf(parsers[i]);
|
|
11211
|
-
if (a === null) continue;
|
|
11212
|
-
if (i === 0) {
|
|
11213
|
-
throw new TypeError(
|
|
11214
|
-
`sequence(): ${a.polarity}() cannot be the FIRST term \u2014 an adjacency assertion tests the gap after the PRECEDING term. Put a concrete term first.`
|
|
11215
|
-
);
|
|
11216
|
-
}
|
|
11217
|
-
;
|
|
11218
|
-
(adjacency ??= Array.from({ length: parsers.length }, () => null))[i] = a;
|
|
11219
|
-
}
|
|
11220
|
-
const hasAdjacency = adjacency !== null;
|
|
11221
|
-
let leading = null;
|
|
11222
|
-
for (let i = 1; i < parsers.length; i++) {
|
|
11223
|
-
if (leadsTrivia(parsers[i])) (leading ??= Array.from({ length: parsers.length }, () => false))[i] = true;
|
|
11224
|
-
}
|
|
11225
|
-
const strictArity = !hasAdjacency && (parsers.length === 2 && !matchesEmpty(parsers[1]) || parsers.length === 3 && parsers.every((p) => !matchesEmpty(p))) ? parsers.length : 0;
|
|
11226
|
-
const meta = {
|
|
11227
|
-
// Union through the nullable prefix — a leading optional()/many() lets a later
|
|
11228
|
-
// term's first char start the sequence. Just `parsers[0]` under-approximates.
|
|
11229
|
-
firstSet: sequenceFirstSet(parsers),
|
|
11230
|
-
canMatchNewline: parsers.some((p) => p._meta.canMatchNewline),
|
|
11231
|
-
isTrivia: false
|
|
11232
|
-
};
|
|
11233
|
-
const def = { tag: "sequence", parsers };
|
|
11234
|
-
const scalarParsers = parsers.map(scalarOf);
|
|
11235
|
-
const parseScalar = (input, pos, ctx) => {
|
|
11236
|
-
let cur = pos;
|
|
11237
|
-
if (strictArity !== 0) {
|
|
11238
|
-
cur = scalarParsers[0](input, cur, ctx);
|
|
11239
|
-
if (cur < 0) return cur;
|
|
11240
|
-
const first = ctx._sv;
|
|
11241
|
-
if (ctx.trivia) cur = advanceTrivia(input, cur, ctx);
|
|
11242
|
-
cur = scalarParsers[1](input, cur, ctx);
|
|
11243
|
-
if (cur < 0) return cur;
|
|
11244
|
-
const second = ctx._sv;
|
|
11245
|
-
if (strictArity === 2) {
|
|
11246
|
-
ctx._sv = def.valueUnused ? void 0 : [first, second];
|
|
11247
|
-
return cur;
|
|
11248
|
-
}
|
|
11249
|
-
if (ctx.trivia) cur = advanceTrivia(input, cur, ctx);
|
|
11250
|
-
cur = scalarParsers[2](input, cur, ctx);
|
|
11251
|
-
if (cur < 0) return cur;
|
|
11252
|
-
ctx._sv = def.valueUnused ? void 0 : [first, second, ctx._sv];
|
|
11253
|
-
return cur;
|
|
11254
|
-
}
|
|
11255
|
-
const values = def.valueUnused ? void 0 : [];
|
|
11256
|
-
for (let i = 0; i < scalarParsers.length; i++) {
|
|
11257
|
-
let termPos = cur;
|
|
11258
|
-
if (i > 0 && ctx.trivia) termPos = advanceTrivia(input, cur, ctx);
|
|
11259
|
-
const end = scalarParsers[i](input, termPos, ctx);
|
|
11260
|
-
if (end < 0) return end;
|
|
11261
|
-
if (values !== void 0) values.push(ctx._sv);
|
|
11262
|
-
if (end > termPos || termPos === cur) cur = end;
|
|
11263
|
-
}
|
|
11264
|
-
ctx._sv = values;
|
|
11265
|
-
return cur;
|
|
11266
|
-
};
|
|
11267
|
-
let followSentinels;
|
|
11268
|
-
return {
|
|
11269
|
-
_tag: "sequence",
|
|
11270
|
-
_meta: meta,
|
|
11271
|
-
_def: def,
|
|
11272
|
-
_parseScalar: hasAdjacency || leading !== null ? void 0 : parseScalar,
|
|
11273
|
-
parse(input, pos, ctx) {
|
|
11274
|
-
const tolerant = ctx._tolerant === true;
|
|
11275
|
-
if (tolerant) {
|
|
11276
|
-
followSentinels ??= parsers.map((_, i) => firstSetSentinel(
|
|
11277
|
-
parsers.slice(i + 1).reduce(
|
|
11278
|
-
(set, parser2) => union(set, firstSetOf(parser2)),
|
|
11279
|
-
{ kind: "empty" }
|
|
11280
|
-
)
|
|
11281
|
-
));
|
|
11282
|
-
}
|
|
11283
|
-
const inheritedSync = ctx._sync;
|
|
11284
|
-
const deferredTrivia = needsDeferredTriviaCommit(ctx);
|
|
11285
|
-
const values = def.valueUnused ? void 0 : [];
|
|
11286
|
-
let cur = pos;
|
|
11287
|
-
try {
|
|
11288
|
-
for (let i = 0; i < parsers.length; i++) {
|
|
11289
|
-
if (tolerant) ctx._sync = followSentinels[i] ?? inheritedSync;
|
|
11290
|
-
const assertion = adjacency?.[i];
|
|
11291
|
-
if (assertion) {
|
|
11292
|
-
if (!holdsAdjacency(input, cur, ctx, assertion)) return adjacencyFail(cur, assertion);
|
|
11293
|
-
if (values !== void 0) values.push(null);
|
|
11294
|
-
continue;
|
|
11295
|
-
}
|
|
11296
|
-
let termPos = cur;
|
|
11297
|
-
const markTlog = deferredTrivia ? cstTlLen(ctx) : 0;
|
|
11298
|
-
const markLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
|
|
11299
|
-
const markRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
11300
|
-
if (ctx.trivia && i > 0) {
|
|
11301
|
-
termPos = deferredTrivia ? commitTriviaScan(scanTriviaCompact(input, cur, ctx)) : advanceTrivia(input, cur, ctx);
|
|
11302
|
-
}
|
|
11303
|
-
const scanTlog = deferredTrivia ? cstTlLen(ctx) : 0;
|
|
11304
|
-
const scanLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
|
|
11305
|
-
const scanRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
11306
|
-
if (leading?.[i] === true) LEAD.at = cur;
|
|
11307
|
-
const result = parsers[i].parse(input, termPos, ctx);
|
|
11308
|
-
if (!result.ok) return result;
|
|
11309
|
-
if (values !== void 0) values.push(result.value);
|
|
11310
|
-
if (result.span.end > termPos || termPos === cur) cur = result.span.end;
|
|
11311
|
-
else if (deferredTrivia) {
|
|
11312
|
-
rollbackScannedTriviaAt(
|
|
11313
|
-
ctx,
|
|
11314
|
-
markTlog,
|
|
11315
|
-
scanTlog,
|
|
11316
|
-
markLog,
|
|
11317
|
-
scanLog,
|
|
11318
|
-
markRootLog,
|
|
11319
|
-
scanRootLog
|
|
11320
|
-
);
|
|
11321
|
-
}
|
|
11322
|
-
}
|
|
11323
|
-
} finally {
|
|
11324
|
-
if (tolerant) ctx._sync = inheritedSync;
|
|
11325
|
-
}
|
|
11326
|
-
return {
|
|
11327
|
-
ok: true,
|
|
11328
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
11329
|
-
value: values ?? void 0,
|
|
11330
|
-
span: { start: pos, end: cur }
|
|
11331
|
-
};
|
|
11332
|
-
}
|
|
11333
|
-
};
|
|
11334
|
-
}
|
|
11335
|
-
|
|
11336
12090
|
// src/combinators/ref.ts
|
|
11337
12091
|
function withRuleTrivia(trivia2, ctx, run) {
|
|
11338
12092
|
const savedLabels = ctx.triviaKindLabels;
|
|
@@ -11358,164 +12112,46 @@ function ref() {
|
|
|
11358
12112
|
const slot = {
|
|
11359
12113
|
_tag: "lazy",
|
|
11360
12114
|
_meta: meta,
|
|
11361
|
-
_def: {
|
|
11362
|
-
tag: "lazy",
|
|
11363
|
-
thunk: () => {
|
|
11364
|
-
if (!resolved) throw UNDEFINED_REF;
|
|
11365
|
-
return resolved;
|
|
11366
|
-
}
|
|
11367
|
-
},
|
|
11368
|
-
_parseScalar(input, pos, ctx) {
|
|
11369
|
-
const scalar = resolvedScalar;
|
|
11370
|
-
if (!scalar) throw new Error("ref<T>() used before .define() was called");
|
|
11371
|
-
const gt = meta.grammarTrivia;
|
|
11372
|
-
if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
|
|
11373
|
-
return withRuleTrivia(gt, ctx, () => scalar(input, pos, ctx));
|
|
11374
|
-
}
|
|
11375
|
-
return scalar(input, pos, ctx);
|
|
11376
|
-
},
|
|
11377
|
-
parse(input, pos, ctx) {
|
|
11378
|
-
const parser2 = resolved;
|
|
11379
|
-
if (!parser2) throw new Error("ref<T>() used before .define() was called");
|
|
11380
|
-
const gt = meta.grammarTrivia;
|
|
11381
|
-
if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
|
|
11382
|
-
return withRuleTrivia(gt, ctx, () => parser2.parse(input, pos, ctx));
|
|
11383
|
-
}
|
|
11384
|
-
return parser2.parse(input, pos, ctx);
|
|
11385
|
-
},
|
|
11386
|
-
define(p) {
|
|
11387
|
-
if (resolved) throw new Error("ref<T>() already defined");
|
|
11388
|
-
resolved = p;
|
|
11389
|
-
resolvedScalar = scalarOf(p);
|
|
11390
|
-
ownBoundary = hasOwnTriviaBoundary(p);
|
|
11391
|
-
meta.firstSet = p._meta.firstSet;
|
|
11392
|
-
meta.canMatchNewline = p._meta.canMatchNewline;
|
|
11393
|
-
meta.isTrivia = p._meta.isTrivia;
|
|
11394
|
-
if (p._meta.triviaKindLabels !== void 0) meta.triviaKindLabels = p._meta.triviaKindLabels;
|
|
11395
|
-
else delete meta.triviaKindLabels;
|
|
11396
|
-
if (p._meta.disjoint !== void 0) meta.disjoint = p._meta.disjoint;
|
|
11397
|
-
else delete meta.disjoint;
|
|
11398
|
-
}
|
|
11399
|
-
};
|
|
11400
|
-
return slot;
|
|
11401
|
-
}
|
|
11402
|
-
|
|
11403
|
-
// src/combinators/token.ts
|
|
11404
|
-
function semanticLeafValue(_ctx, _input, _start, _end, value) {
|
|
11405
|
-
return value;
|
|
11406
|
-
}
|
|
11407
|
-
function sourceLeafValue(ctx, input, start, end, value) {
|
|
11408
|
-
return cstOutputHost(ctx.build) ? input.slice(start, end) : value;
|
|
11409
|
-
}
|
|
11410
|
-
function token(root) {
|
|
11411
|
-
const meta = {
|
|
11412
|
-
firstSet: root._meta.firstSet,
|
|
11413
|
-
canMatchNewline: root._meta.canMatchNewline,
|
|
11414
|
-
isTrivia: false
|
|
11415
|
-
};
|
|
11416
|
-
return {
|
|
11417
|
-
_tag: "token",
|
|
11418
|
-
_meta: meta,
|
|
11419
|
-
_def: { tag: "token", parser: root },
|
|
11420
|
-
parse(input, pos, ctx) {
|
|
11421
|
-
const savedTrivia = ctx.trivia;
|
|
11422
|
-
const savedKinds = ctx.triviaKindLabels;
|
|
11423
|
-
const savedBuf = ctx._cstBuf;
|
|
11424
|
-
const savedChildren = ctx._cstChildren;
|
|
11425
|
-
const savedLeaves = ctx._cstLeaves;
|
|
11426
|
-
const savedRaw = ctx._cstRawChildren;
|
|
11427
|
-
const savedTriviaLog = ctx._cstTriviaLog;
|
|
11428
|
-
const savedOuterTriviaLog = ctx._triviaLog;
|
|
11429
|
-
const savedRootTriviaLog = ctx._rootTriviaLog;
|
|
11430
|
-
const wasCapturing = cstCaptureActive(ctx);
|
|
11431
|
-
ctx.trivia = void 0;
|
|
11432
|
-
ctx.triviaKindLabels = void 0;
|
|
11433
|
-
ctx._cstBuf = void 0;
|
|
11434
|
-
ctx._cstChildren = void 0;
|
|
11435
|
-
ctx._cstLeaves = void 0;
|
|
11436
|
-
ctx._cstRawChildren = void 0;
|
|
11437
|
-
ctx._cstTriviaLog = void 0;
|
|
11438
|
-
ctx._triviaLog = void 0;
|
|
11439
|
-
ctx._rootTriviaLog = void 0;
|
|
11440
|
-
let result;
|
|
11441
|
-
try {
|
|
11442
|
-
result = root.parse(input, pos, ctx);
|
|
11443
|
-
} finally {
|
|
11444
|
-
ctx.trivia = savedTrivia;
|
|
11445
|
-
ctx.triviaKindLabels = savedKinds;
|
|
11446
|
-
ctx._cstBuf = savedBuf;
|
|
11447
|
-
ctx._cstChildren = savedChildren;
|
|
11448
|
-
ctx._cstLeaves = savedLeaves;
|
|
11449
|
-
ctx._cstRawChildren = savedRaw;
|
|
11450
|
-
ctx._cstTriviaLog = savedTriviaLog;
|
|
11451
|
-
ctx._triviaLog = savedOuterTriviaLog;
|
|
11452
|
-
ctx._rootTriviaLog = savedRootTriviaLog;
|
|
11453
|
-
}
|
|
11454
|
-
if (!result.ok) return result;
|
|
11455
|
-
const span = result.span;
|
|
11456
|
-
const value = input.slice(pos, span.end);
|
|
11457
|
-
if (wasCapturing) pushCstLeaf(ctx, { _tag: "leaf", value, span });
|
|
11458
|
-
return { ok: true, value, span };
|
|
11459
|
-
}
|
|
11460
|
-
};
|
|
11461
|
-
}
|
|
11462
|
-
function makeLeaf(root, fn, sourceCstValue) {
|
|
11463
|
-
const cstValue = sourceCstValue ? sourceLeafValue : semanticLeafValue;
|
|
11464
|
-
const meta = {
|
|
11465
|
-
firstSet: root._meta.firstSet,
|
|
11466
|
-
canMatchNewline: root._meta.canMatchNewline,
|
|
11467
|
-
isTrivia: false
|
|
11468
|
-
};
|
|
11469
|
-
return {
|
|
11470
|
-
_tag: "leaf",
|
|
11471
|
-
_meta: meta,
|
|
11472
|
-
_def: {
|
|
11473
|
-
tag: "leaf",
|
|
11474
|
-
parser: root,
|
|
11475
|
-
fn,
|
|
11476
|
-
...sourceCstValue ? { cstValue: "source" } : {}
|
|
12115
|
+
_def: {
|
|
12116
|
+
tag: "lazy",
|
|
12117
|
+
thunk: () => {
|
|
12118
|
+
if (!resolved) throw UNDEFINED_REF;
|
|
12119
|
+
return resolved;
|
|
12120
|
+
}
|
|
12121
|
+
},
|
|
12122
|
+
_parseScalar(input, pos, ctx) {
|
|
12123
|
+
const scalar = resolvedScalar;
|
|
12124
|
+
if (!scalar) throw new Error("ref<T>() used before .define() was called");
|
|
12125
|
+
const gt = meta.grammarTrivia;
|
|
12126
|
+
if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
|
|
12127
|
+
return withRuleTrivia(gt, ctx, () => scalar(input, pos, ctx));
|
|
12128
|
+
}
|
|
12129
|
+
return scalar(input, pos, ctx);
|
|
11477
12130
|
},
|
|
11478
12131
|
parse(input, pos, ctx) {
|
|
11479
|
-
const
|
|
11480
|
-
|
|
11481
|
-
const
|
|
11482
|
-
|
|
11483
|
-
|
|
11484
|
-
const savedOuterTriviaLog = ctx._triviaLog;
|
|
11485
|
-
const wasCapturing = cstCaptureActive(ctx);
|
|
11486
|
-
ctx._cstBuf = void 0;
|
|
11487
|
-
ctx._cstChildren = void 0;
|
|
11488
|
-
ctx._cstLeaves = void 0;
|
|
11489
|
-
ctx._cstRawChildren = void 0;
|
|
11490
|
-
ctx._cstTriviaLog = void 0;
|
|
11491
|
-
ctx._triviaLog = void 0;
|
|
11492
|
-
let result;
|
|
11493
|
-
try {
|
|
11494
|
-
result = root.parse(input, pos, ctx);
|
|
11495
|
-
} finally {
|
|
11496
|
-
ctx._cstBuf = savedBuf;
|
|
11497
|
-
ctx._cstChildren = savedChildren;
|
|
11498
|
-
ctx._cstLeaves = savedLeaves;
|
|
11499
|
-
ctx._cstRawChildren = savedRaw;
|
|
11500
|
-
ctx._cstTriviaLog = savedTriviaLog;
|
|
11501
|
-
ctx._triviaLog = savedOuterTriviaLog;
|
|
12132
|
+
const parser2 = resolved;
|
|
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));
|
|
11502
12137
|
}
|
|
11503
|
-
|
|
11504
|
-
|
|
11505
|
-
|
|
11506
|
-
|
|
11507
|
-
|
|
11508
|
-
|
|
11509
|
-
|
|
11510
|
-
|
|
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;
|
|
11511
12152
|
}
|
|
11512
12153
|
};
|
|
11513
|
-
|
|
11514
|
-
function leaf(root, fn) {
|
|
11515
|
-
return makeLeaf(root, fn, false);
|
|
11516
|
-
}
|
|
11517
|
-
function sourceLeaf(root, fn) {
|
|
11518
|
-
return makeLeaf(root, fn, true);
|
|
12154
|
+
return slot;
|
|
11519
12155
|
}
|
|
11520
12156
|
|
|
11521
12157
|
// src/combinators/scanTo.ts
|
|
@@ -11826,37 +12462,120 @@ function clearOf(ranges, input, from, to) {
|
|
|
11826
12462
|
return true;
|
|
11827
12463
|
}
|
|
11828
12464
|
|
|
11829
|
-
// src/table/
|
|
11830
|
-
function
|
|
11831
|
-
|
|
11832
|
-
|
|
11833
|
-
|
|
11834
|
-
|
|
11835
|
-
|
|
11836
|
-
|
|
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;
|
|
11837
12487
|
}
|
|
11838
|
-
return [lo + 1, offset - starts[lo] + 1];
|
|
11839
|
-
}
|
|
11840
|
-
function spanLines(ctx, start, end) {
|
|
11841
|
-
const s = lineCol(ctx, start), e = lineCol(ctx, end);
|
|
11842
|
-
return { start, end, startLine: s[0], startColumn: s[1], endLine: e[0], endColumn: e[1] };
|
|
11843
12488
|
}
|
|
11844
|
-
function
|
|
11845
|
-
|
|
11846
|
-
|
|
11847
|
-
|
|
11848
|
-
|
|
11849
|
-
|
|
11850
|
-
|
|
11851
|
-
|
|
11852
|
-
|
|
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;
|
|
11853
12516
|
};
|
|
11854
|
-
|
|
11855
|
-
|
|
11856
|
-
|
|
11857
|
-
|
|
11858
|
-
|
|
11859
|
-
|
|
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;
|
|
11860
12579
|
}
|
|
11861
12580
|
|
|
11862
12581
|
// src/cst/host-mode.ts
|
|
@@ -12008,6 +12727,7 @@ function assemble(t2, prog, cfg) {
|
|
|
12008
12727
|
const swapLegal = !cfg.trackLines;
|
|
12009
12728
|
const hostCst = cfg.hostCst;
|
|
12010
12729
|
const REC = prog.rec === 1 && cfg.tolerant;
|
|
12730
|
+
const PROBE = cfg.probe;
|
|
12011
12731
|
const sentinels = /* @__PURE__ */ new Map();
|
|
12012
12732
|
function sentinelFor(cls) {
|
|
12013
12733
|
if (cls < 0) return void 0;
|
|
@@ -12053,6 +12773,8 @@ function assemble(t2, prog, cfg) {
|
|
|
12053
12773
|
}
|
|
12054
12774
|
const memo = /* @__PURE__ */ new Map();
|
|
12055
12775
|
const reached = /* @__PURE__ */ new Set();
|
|
12776
|
+
const NULLABLE = /* @__PURE__ */ new Map();
|
|
12777
|
+
const CLEAN = REC ? () => false : failCleanAnalysis(code);
|
|
12056
12778
|
function pushLeaf(ctx, value, s, e) {
|
|
12057
12779
|
const lf = { _tag: "leaf", value, span: { start: s, end: e } };
|
|
12058
12780
|
pushCstLeaf(ctx, lf);
|
|
@@ -12251,6 +12973,22 @@ function assemble(t2, prog, cfg) {
|
|
|
12251
12973
|
return node2;
|
|
12252
12974
|
};
|
|
12253
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
|
+
}
|
|
12254
12992
|
function plainProjectNode(child, projection, type) {
|
|
12255
12993
|
return (input, pos, ctx) => {
|
|
12256
12994
|
const sCh = ctx._cstChildren;
|
|
@@ -12621,21 +13359,27 @@ function assemble(t2, prog, cfg) {
|
|
|
12621
13359
|
}
|
|
12622
13360
|
function dispatchBranch(child, usesRouted) {
|
|
12623
13361
|
if (!usesRouted) {
|
|
12624
|
-
return (input, _pos, selEnd, key,
|
|
12625
|
-
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;
|
|
12626
13371
|
const v = child(input, selEnd, ctx);
|
|
12627
13372
|
if (v === FAIL) {
|
|
12628
|
-
|
|
13373
|
+
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
12629
13374
|
ctx._fc = true;
|
|
12630
13375
|
return FAIL;
|
|
12631
13376
|
}
|
|
12632
13377
|
return [key, v];
|
|
12633
13378
|
};
|
|
12634
13379
|
}
|
|
12635
|
-
return (input, pos, selEnd, key,
|
|
13380
|
+
return (input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot) => {
|
|
12636
13381
|
const savedRouted = ctx._routed;
|
|
12637
|
-
|
|
12638
|
-
const mark = saveTriviaMark(ctx);
|
|
13382
|
+
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
12639
13383
|
ctx._routed = { value: key, span: { start: pos, end: selEnd } };
|
|
12640
13384
|
let v;
|
|
12641
13385
|
try {
|
|
@@ -12644,7 +13388,7 @@ function assemble(t2, prog, cfg) {
|
|
|
12644
13388
|
ctx._routed = savedRouted;
|
|
12645
13389
|
}
|
|
12646
13390
|
if (v === FAIL) {
|
|
12647
|
-
|
|
13391
|
+
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
12648
13392
|
ctx._fc = true;
|
|
12649
13393
|
return FAIL;
|
|
12650
13394
|
}
|
|
@@ -12652,12 +13396,12 @@ function assemble(t2, prog, cfg) {
|
|
|
12652
13396
|
};
|
|
12653
13397
|
}
|
|
12654
13398
|
function dispatchArmBlock(start, a0, a1, a2, a3, next) {
|
|
12655
|
-
return (arm, input, pos, selEnd, key,
|
|
12656
|
-
if (arm === start) return a0(input, pos, selEnd, key,
|
|
12657
|
-
if (arm === start + 1) return a1(input, pos, selEnd, key,
|
|
12658
|
-
if (arm === start + 2) return a2(input, pos, selEnd, key,
|
|
12659
|
-
if (arm === start + 3) return a3(input, pos, selEnd, key,
|
|
12660
|
-
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);
|
|
12661
13405
|
};
|
|
12662
13406
|
}
|
|
12663
13407
|
function trackLinesInto(ctx, input, end) {
|
|
@@ -12676,7 +13420,7 @@ function assemble(t2, prog, cfg) {
|
|
|
12676
13420
|
if (flight !== void 0) return flight.fwd;
|
|
12677
13421
|
const selected = HYBRID?.byIp[ip];
|
|
12678
13422
|
if (selected !== void 0) {
|
|
12679
|
-
const piece2 = hybridPiece(selected);
|
|
13423
|
+
const piece2 = scanHandoffNeeded(code, ip, closureLabels) ? hybridPiece(selected) : selected;
|
|
12680
13424
|
memo.set(ip, piece2);
|
|
12681
13425
|
reached.add(ip);
|
|
12682
13426
|
return piece2;
|
|
@@ -12687,14 +13431,55 @@ function assemble(t2, prog, cfg) {
|
|
|
12687
13431
|
target = p;
|
|
12688
13432
|
} };
|
|
12689
13433
|
inFlight.set(ip, holder);
|
|
12690
|
-
const
|
|
12691
|
-
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]) : countedPiece(lower(ip), ip);
|
|
13434
|
+
const piece = scopeIsIdentity(code, ip, closureLabels.at(ip)) ? link(code[ip + 2]) : countedPiece(lookaheadLedNode(ip) ?? lower(ip), ip);
|
|
12692
13435
|
inFlight.delete(ip);
|
|
12693
13436
|
holder.set(piece);
|
|
12694
13437
|
memo.set(ip, piece);
|
|
12695
13438
|
reached.add(ip);
|
|
12696
13439
|
return piece;
|
|
12697
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
|
+
}
|
|
12698
13483
|
function lower(ip) {
|
|
12699
13484
|
const op = code[ip];
|
|
12700
13485
|
switch (op) {
|
|
@@ -13239,8 +14024,10 @@ function assemble(t2, prog, cfg) {
|
|
|
13239
14024
|
const mEr = need ? ctx._errors?.length ?? 0 : 0;
|
|
13240
14025
|
const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
13241
14026
|
const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14027
|
+
const probeBest = PROBE ? ctx._probe?.best : void 0;
|
|
13242
14028
|
const v = child(input, pos, ctx);
|
|
13243
14029
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14030
|
+
if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
|
|
13244
14031
|
if (v === FAIL) {
|
|
13245
14032
|
EC.e = pos;
|
|
13246
14033
|
return null;
|
|
@@ -13251,6 +14038,20 @@ function assemble(t2, prog, cfg) {
|
|
|
13251
14038
|
};
|
|
13252
14039
|
}
|
|
13253
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
|
+
}
|
|
13254
14055
|
const child = link(code[ip + 1]);
|
|
13255
14056
|
const xf = fx[code[ip + 2]];
|
|
13256
14057
|
const gate = lookaheadClass(code[ip + 1]);
|
|
@@ -13268,8 +14069,10 @@ function assemble(t2, prog, cfg) {
|
|
|
13268
14069
|
const mEr = need ? ctx._errors?.length ?? 0 : 0;
|
|
13269
14070
|
const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
13270
14071
|
const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14072
|
+
const probeBest = PROBE ? ctx._probe?.best : void 0;
|
|
13271
14073
|
const v = child(input, pos, ctx);
|
|
13272
14074
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14075
|
+
if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
|
|
13273
14076
|
if (v === FAIL) {
|
|
13274
14077
|
ctx._fe = pos;
|
|
13275
14078
|
ctx._fx = xf;
|
|
@@ -13282,12 +14085,13 @@ function assemble(t2, prog, cfg) {
|
|
|
13282
14085
|
case OP_OPT: {
|
|
13283
14086
|
const child = link(code[ip + 1]);
|
|
13284
14087
|
const gate = lookaheadClass(code[ip + 1]);
|
|
14088
|
+
const childClean = CLEAN(code[ip + 1]);
|
|
13285
14089
|
return (input, pos, ctx) => {
|
|
13286
14090
|
if (gate !== null && !classHas2(gate, lead(input, pos))) {
|
|
13287
14091
|
EC.e = pos;
|
|
13288
14092
|
return null;
|
|
13289
14093
|
}
|
|
13290
|
-
const need = markCst(ctx);
|
|
14094
|
+
const need = !childClean && markCst(ctx);
|
|
13291
14095
|
const mRaw = MRAW;
|
|
13292
14096
|
const mTl = MTL;
|
|
13293
14097
|
const mLv = MLV;
|
|
@@ -13485,6 +14289,9 @@ function assemble(t2, prog, cfg) {
|
|
|
13485
14289
|
const projection = reducer < 0 ? ~reducer : -1;
|
|
13486
14290
|
const fn = fused && projection < 0 ? fns[reducer] : void 0;
|
|
13487
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]);
|
|
13488
14295
|
const runnerBlock = (count, r0, r1, r2, r3, next) => {
|
|
13489
14296
|
if (count === 1) return (input, cur, ctx, values, inherited) => {
|
|
13490
14297
|
cur = r0(input, cur, ctx, inherited);
|
|
@@ -13530,7 +14337,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13530
14337
|
};
|
|
13531
14338
|
};
|
|
13532
14339
|
if (REC) {
|
|
13533
|
-
const first2 =
|
|
14340
|
+
const first2 = linkFirst();
|
|
13534
14341
|
const firstSync = sentinelFor(code[base + n]);
|
|
13535
14342
|
const runnerAt = (i) => {
|
|
13536
14343
|
const sync = sentinelFor(code[base + n + i]);
|
|
@@ -13566,13 +14373,13 @@ function assemble(t2, prog, cfg) {
|
|
|
13566
14373
|
const bindRunners = (start) => {
|
|
13567
14374
|
const count = Math.min(4, n - start);
|
|
13568
14375
|
const at = (offset) => runnerAt(start + offset);
|
|
13569
|
-
const
|
|
14376
|
+
const never2 = () => -1;
|
|
13570
14377
|
return runnerBlock(
|
|
13571
14378
|
count,
|
|
13572
14379
|
at(0),
|
|
13573
|
-
count > 1 ? at(1) :
|
|
13574
|
-
count > 2 ? at(2) :
|
|
13575
|
-
count > 3 ? at(3) :
|
|
14380
|
+
count > 1 ? at(1) : never2,
|
|
14381
|
+
count > 2 ? at(2) : never2,
|
|
14382
|
+
count > 3 ? at(3) : never2,
|
|
13576
14383
|
start + count < n ? bindRunners(start + count) : void 0
|
|
13577
14384
|
);
|
|
13578
14385
|
};
|
|
@@ -13622,15 +14429,31 @@ function assemble(t2, prog, cfg) {
|
|
|
13622
14429
|
let hasAdj = false;
|
|
13623
14430
|
for (let i = 1; i < n; i++) {
|
|
13624
14431
|
const kidIp = code[base + i];
|
|
13625
|
-
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)) {
|
|
13626
14433
|
hasAdj = true;
|
|
13627
14434
|
break;
|
|
13628
14435
|
}
|
|
13629
14436
|
}
|
|
13630
14437
|
if (hasAdj) {
|
|
13631
|
-
const first2 =
|
|
14438
|
+
const first2 = linkFirst();
|
|
13632
14439
|
const runnerAt = (i) => {
|
|
13633
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
|
+
}
|
|
13634
14457
|
if (code[kidIp] !== OP_ADJ) {
|
|
13635
14458
|
const kid = link(kidIp);
|
|
13636
14459
|
if (leadingTriviaFieldAt(code, k, kidIp)) {
|
|
@@ -13655,13 +14478,13 @@ function assemble(t2, prog, cfg) {
|
|
|
13655
14478
|
const bindRunners = (start) => {
|
|
13656
14479
|
const count = Math.min(4, n - start);
|
|
13657
14480
|
const at = (offset) => runnerAt(start + offset);
|
|
13658
|
-
const
|
|
14481
|
+
const never2 = () => -1;
|
|
13659
14482
|
return runnerBlock(
|
|
13660
14483
|
count,
|
|
13661
14484
|
at(0),
|
|
13662
|
-
count > 1 ? at(1) :
|
|
13663
|
-
count > 2 ? at(2) :
|
|
13664
|
-
count > 3 ? at(3) :
|
|
14485
|
+
count > 1 ? at(1) : never2,
|
|
14486
|
+
count > 2 ? at(2) : never2,
|
|
14487
|
+
count > 3 ? at(3) : never2,
|
|
13665
14488
|
start + count < n ? bindRunners(start + count) : void 0
|
|
13666
14489
|
);
|
|
13667
14490
|
};
|
|
@@ -13698,7 +14521,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13698
14521
|
};
|
|
13699
14522
|
}
|
|
13700
14523
|
if (n === 1) {
|
|
13701
|
-
const k0 =
|
|
14524
|
+
const k0 = linkFirst();
|
|
13702
14525
|
if (fused) {
|
|
13703
14526
|
return (input, pos, ctx) => {
|
|
13704
14527
|
const v = k0(input, pos, ctx);
|
|
@@ -13720,7 +14543,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13720
14543
|
};
|
|
13721
14544
|
}
|
|
13722
14545
|
if (n === 2) {
|
|
13723
|
-
const k0 =
|
|
14546
|
+
const k0 = linkFirst(), k1 = link(code[base + 1]);
|
|
13724
14547
|
if (fused) {
|
|
13725
14548
|
return (input, pos, ctx) => {
|
|
13726
14549
|
const v0 = k0(input, pos, ctx);
|
|
@@ -13751,7 +14574,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13751
14574
|
};
|
|
13752
14575
|
}
|
|
13753
14576
|
if (n === 3) {
|
|
13754
|
-
const k0 =
|
|
14577
|
+
const k0 = linkFirst(), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
|
|
13755
14578
|
if (fused) {
|
|
13756
14579
|
return (input, pos, ctx) => {
|
|
13757
14580
|
const v0 = k0(input, pos, ctx);
|
|
@@ -13845,7 +14668,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13845
14668
|
start + count < n ? bind(start + count) : void 0
|
|
13846
14669
|
);
|
|
13847
14670
|
};
|
|
13848
|
-
const first =
|
|
14671
|
+
const first = linkFirst();
|
|
13849
14672
|
const tail = bind(1);
|
|
13850
14673
|
const runDirectTerms = (input, pos, ctx, values) => {
|
|
13851
14674
|
const v0 = first(input, pos, ctx);
|
|
@@ -13884,6 +14707,8 @@ function assemble(t2, prog, cfg) {
|
|
|
13884
14707
|
const n = code[ip + 2];
|
|
13885
14708
|
const choiceFx = fx[code[ip + 3]];
|
|
13886
14709
|
const base = ip + 4;
|
|
14710
|
+
for (let i = 0; i < n; i++) link(code[base + i]);
|
|
14711
|
+
const armsClean = CLEAN(ip);
|
|
13887
14712
|
if (table.exclusive) {
|
|
13888
14713
|
const ascii = table.ascii;
|
|
13889
14714
|
const hi = table.hi;
|
|
@@ -14023,7 +14848,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14023
14848
|
if (n === 3) addGate(g2, 4);
|
|
14024
14849
|
return (input, pos, ctx) => {
|
|
14025
14850
|
const c = lead(input, pos);
|
|
14026
|
-
const need = markCst(ctx);
|
|
14851
|
+
const need = !armsClean && markCst(ctx);
|
|
14027
14852
|
const mRaw = MRAW;
|
|
14028
14853
|
const mTl = MTL;
|
|
14029
14854
|
const mLv = MLV;
|
|
@@ -14240,7 +15065,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14240
15065
|
if (pn !== 0) {
|
|
14241
15066
|
return (input, pos, ctx) => {
|
|
14242
15067
|
const c = lead(input, pos);
|
|
14243
|
-
const need = markCst(ctx);
|
|
15068
|
+
const need = !armsClean && markCst(ctx);
|
|
14244
15069
|
const mRaw = MRAW;
|
|
14245
15070
|
const mTl = MTL;
|
|
14246
15071
|
const mLv = MLV;
|
|
@@ -14297,7 +15122,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14297
15122
|
}
|
|
14298
15123
|
return (input, pos, ctx) => {
|
|
14299
15124
|
const c = lead(input, pos);
|
|
14300
|
-
const need = markCst(ctx);
|
|
15125
|
+
const need = !armsClean && markCst(ctx);
|
|
14301
15126
|
const mRaw = MRAW;
|
|
14302
15127
|
const mTl = MTL;
|
|
14303
15128
|
const mLv = MLV;
|
|
@@ -14345,7 +15170,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14345
15170
|
}
|
|
14346
15171
|
return (input, pos, ctx) => {
|
|
14347
15172
|
const c = lead(input, pos);
|
|
14348
|
-
const need = markCst(ctx);
|
|
15173
|
+
const need = !armsClean && markCst(ctx);
|
|
14349
15174
|
const mRaw = MRAW;
|
|
14350
15175
|
const mTl = MTL;
|
|
14351
15176
|
const mLv = MLV;
|
|
@@ -14399,6 +15224,21 @@ function assemble(t2, prog, cfg) {
|
|
|
14399
15224
|
return lit(input, pos, ctx);
|
|
14400
15225
|
};
|
|
14401
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
|
+
}
|
|
14402
15242
|
case OP_ARMGATE: {
|
|
14403
15243
|
const pred = fns[code[ip + 1]];
|
|
14404
15244
|
const child = link(code[ip + 2]);
|
|
@@ -14467,6 +15307,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14467
15307
|
const itemClass = !REC && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
|
|
14468
15308
|
const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
|
|
14469
15309
|
const skipBeforeFirst = sepIp < 0 && min === 0;
|
|
15310
|
+
const itemClean = sepIp < 0 && CLEAN(code[ip + 1]) && !rowNullable(code, k, code[ip + 1], NULLABLE);
|
|
14470
15311
|
if (REC) {
|
|
14471
15312
|
const itemFx2 = fx[code[ip + 6]];
|
|
14472
15313
|
const sepSent = sentinelFor(code[ip + 7]);
|
|
@@ -14563,6 +15404,8 @@ function assemble(t2, prog, cfg) {
|
|
|
14563
15404
|
const out = collect ? [] : void 0;
|
|
14564
15405
|
const hasTrivia = ctx.trivia !== void 0;
|
|
14565
15406
|
const needMark = rollbackNeeded(ctx);
|
|
15407
|
+
const markLater = needMark && (!itemClean || hasTrivia);
|
|
15408
|
+
const markFirst = needMark && (!itemClean || hasTrivia && skipBeforeFirst);
|
|
14566
15409
|
const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
|
|
14567
15410
|
let cur = pos;
|
|
14568
15411
|
let count = 0;
|
|
@@ -14570,14 +15413,15 @@ function assemble(t2, prog, cfg) {
|
|
|
14570
15413
|
if (max >= 0 && count >= max) break;
|
|
14571
15414
|
if (sep !== void 0 && count > 0 && count >= min && cur >= input.length) break;
|
|
14572
15415
|
if (count >= min && sep === void 0 && !hasTrivia && gateItems && !itemMayStart(input, cur)) break;
|
|
14573
|
-
|
|
14574
|
-
|
|
14575
|
-
const
|
|
14576
|
-
const
|
|
14577
|
-
const
|
|
14578
|
-
const
|
|
14579
|
-
const
|
|
14580
|
-
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;
|
|
14581
15425
|
let itemStart = cur;
|
|
14582
15426
|
let sepEnd = -1;
|
|
14583
15427
|
const viaRepItem = sep === void 0 && count >= min && (count > 0 || skipBeforeFirst);
|
|
@@ -14589,7 +15433,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14589
15433
|
if (sepLeads) LEAD.at = cur;
|
|
14590
15434
|
const sv = sep(input, sp, ctx);
|
|
14591
15435
|
if (sv === FAIL) {
|
|
14592
|
-
if (
|
|
15436
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14593
15437
|
if (committed3(ctx)) return FAIL;
|
|
14594
15438
|
break;
|
|
14595
15439
|
}
|
|
@@ -14600,25 +15444,25 @@ function assemble(t2, prog, cfg) {
|
|
|
14600
15444
|
itemStart = skipTrivia(input, itemStart, ctx);
|
|
14601
15445
|
}
|
|
14602
15446
|
if (itemStart >= input.length && viaRepItem) {
|
|
14603
|
-
if (
|
|
15447
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14604
15448
|
if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
|
|
14605
15449
|
break;
|
|
14606
15450
|
}
|
|
14607
15451
|
if (count >= min && gateItems && !itemMayStart(input, itemStart)) {
|
|
14608
|
-
if (
|
|
15452
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14609
15453
|
if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
|
|
14610
15454
|
break;
|
|
14611
15455
|
}
|
|
14612
15456
|
ctx._fc = false;
|
|
14613
15457
|
const v = child(input, itemStart, ctx);
|
|
14614
15458
|
if (v === FAIL) {
|
|
14615
|
-
if (
|
|
15459
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14616
15460
|
if (committed3(ctx)) return FAIL;
|
|
14617
15461
|
if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
|
|
14618
15462
|
break;
|
|
14619
15463
|
}
|
|
14620
15464
|
if (EC.e === itemStart && viaRepItem) {
|
|
14621
|
-
if (
|
|
15465
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14622
15466
|
break;
|
|
14623
15467
|
}
|
|
14624
15468
|
if (out !== void 0) out.push(v);
|
|
@@ -14692,7 +15536,14 @@ function assemble(t2, prog, cfg) {
|
|
|
14692
15536
|
const runArm = n === 0 ? void 0 : bindArms(0);
|
|
14693
15537
|
const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted);
|
|
14694
15538
|
return (input, pos, ctx) => {
|
|
14695
|
-
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;
|
|
14696
15547
|
const selVal = selector(input, pos, ctx);
|
|
14697
15548
|
if (selVal === FAIL) return FAIL;
|
|
14698
15549
|
const selEnd = EC.e;
|
|
@@ -14704,9 +15555,9 @@ function assemble(t2, prog, cfg) {
|
|
|
14704
15555
|
ctx._fx = expected;
|
|
14705
15556
|
return FAIL;
|
|
14706
15557
|
}
|
|
14707
|
-
return runOther(input, pos, selEnd, key,
|
|
15558
|
+
return runOther(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14708
15559
|
}
|
|
14709
|
-
return runArm(arm, input, pos, selEnd, key,
|
|
15560
|
+
return runArm(arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14710
15561
|
};
|
|
14711
15562
|
}
|
|
14712
15563
|
/* ── node ────────────────────────────────────────────────────────────── */
|
|
@@ -14742,7 +15593,8 @@ function assemble(t2, prog, cfg) {
|
|
|
14742
15593
|
return nd;
|
|
14743
15594
|
};
|
|
14744
15595
|
}
|
|
14745
|
-
const child = link(code[ip + 2]);
|
|
15596
|
+
const child = NODE_BODY ?? link(code[ip + 2]);
|
|
15597
|
+
NODE_BODY = void 0;
|
|
14746
15598
|
const proj = code[ip + 4];
|
|
14747
15599
|
const buildIdx = code[ip + 1];
|
|
14748
15600
|
const type = k[code[ip + 5]];
|
|
@@ -14766,6 +15618,30 @@ function assemble(t2, prog, cfg) {
|
|
|
14766
15618
|
if (build !== void 0 && proj < 0 && flags === 18) {
|
|
14767
15619
|
return childrenOnlyFieldsBuildNode(child, build);
|
|
14768
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
|
+
}
|
|
14769
15645
|
if (build !== void 0 && proj < 0 && flags === 32) {
|
|
14770
15646
|
return collapseBuildNode(child, build);
|
|
14771
15647
|
}
|
|
@@ -14914,6 +15790,8 @@ function assemble(t2, prog, cfg) {
|
|
|
14914
15790
|
}
|
|
14915
15791
|
const notChild = scalarTerminalNotChild(code, ip);
|
|
14916
15792
|
if (notChild >= 0) scalarFor(notChild);
|
|
15793
|
+
const peekChild = scalarTerminalPeekChild(code, ip);
|
|
15794
|
+
if (peekChild >= 0) scalarFor(peekChild);
|
|
14917
15795
|
}
|
|
14918
15796
|
const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
|
|
14919
15797
|
if (pre !== void 0) {
|
|
@@ -14973,7 +15851,8 @@ function assemble(t2, prog, cfg) {
|
|
|
14973
15851
|
t2.lexPrograms,
|
|
14974
15852
|
LEAD,
|
|
14975
15853
|
triviaFieldCapture,
|
|
14976
|
-
skipDeferredTrivia
|
|
15854
|
+
skipDeferredTrivia,
|
|
15855
|
+
collapseEmpty
|
|
14977
15856
|
);
|
|
14978
15857
|
emitReached = new Set(pre.reached);
|
|
14979
15858
|
if (emitted.ext !== void 0) HYBRID = emitted;
|
|
@@ -15059,7 +15938,8 @@ function assemble(t2, prog, cfg) {
|
|
|
15059
15938
|
t2.lexPrograms,
|
|
15060
15939
|
LEAD,
|
|
15061
15940
|
triviaFieldCapture,
|
|
15062
|
-
skipDeferredTrivia
|
|
15941
|
+
skipDeferredTrivia,
|
|
15942
|
+
collapseEmpty
|
|
15063
15943
|
);
|
|
15064
15944
|
emitReached = em.reached;
|
|
15065
15945
|
} catch (e) {
|
|
@@ -15326,7 +16206,7 @@ function emitClassPool(classes) {
|
|
|
15326
16206
|
if (classes.length < 2) return array;
|
|
15327
16207
|
const delimiter = "|/~?^`".split("").find((ch2) => classes.every((spec) => !spec.includes(ch2)));
|
|
15328
16208
|
if (delimiter === void 0) return array;
|
|
15329
|
-
const split =
|
|
16209
|
+
const split = `/* @__PURE__ */ ${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
|
|
15330
16210
|
return split.length < array.length ? split : array;
|
|
15331
16211
|
}
|
|
15332
16212
|
function emitConst(v) {
|
|
@@ -17185,16 +18065,16 @@ function ownSource(fn) {
|
|
|
17185
18065
|
return typeof name === "string" && name.length > 0 && globalThis[name] === fn ? name : null;
|
|
17186
18066
|
}
|
|
17187
18067
|
function compile(target, second, third) {
|
|
17188
|
-
if (!
|
|
18068
|
+
if (!isCombinator2(target)) return compileMap(target, second);
|
|
17189
18069
|
return compileRoot(target, second, third);
|
|
17190
18070
|
}
|
|
17191
|
-
function
|
|
18071
|
+
function isCombinator2(x) {
|
|
17192
18072
|
return typeof x === "object" && x !== null && typeof x.parse === "function" && "_def" in x;
|
|
17193
18073
|
}
|
|
17194
18074
|
function compileMap(grammar, opts = {}) {
|
|
17195
18075
|
const entries = [];
|
|
17196
18076
|
for (const [key, value] of Object.entries(grammar)) {
|
|
17197
|
-
if (!
|
|
18077
|
+
if (!isCombinator2(value)) throw new TypeError(`compile: grammar entry "${key}" is not a parser`);
|
|
17198
18078
|
if (value._def.tag === "lazy") {
|
|
17199
18079
|
try {
|
|
17200
18080
|
value._def.thunk();
|
|
@@ -17508,49 +18388,6 @@ function digestValue(value, prefix = "", options) {
|
|
|
17508
18388
|
return sha.digest("hex");
|
|
17509
18389
|
}
|
|
17510
18390
|
|
|
17511
|
-
// src/combinators/attempt.ts
|
|
17512
|
-
function containOption(options) {
|
|
17513
|
-
if (options === void 0) return false;
|
|
17514
|
-
for (const key of Object.keys(options)) {
|
|
17515
|
-
if (key !== "contain") throw new TypeError(`attempt(): unknown option ${JSON.stringify(key)}`);
|
|
17516
|
-
}
|
|
17517
|
-
if (options.contain !== void 0 && typeof options.contain !== "boolean") {
|
|
17518
|
-
throw new TypeError("attempt(): `contain` must be a boolean");
|
|
17519
|
-
}
|
|
17520
|
-
return options.contain === true;
|
|
17521
|
-
}
|
|
17522
|
-
function attempt(parser2, options) {
|
|
17523
|
-
const contain = containOption(options);
|
|
17524
|
-
const guardable = parser2._meta.firstSet.kind !== "any" && !matchesEmpty(parser2);
|
|
17525
|
-
let failExpected;
|
|
17526
|
-
return {
|
|
17527
|
-
_tag: "attempt",
|
|
17528
|
-
_meta: parser2._meta,
|
|
17529
|
-
_def: contain ? { tag: "attempt", parser: parser2, contain: true } : { tag: "attempt", parser: parser2 },
|
|
17530
|
-
parse(input, pos, ctx) {
|
|
17531
|
-
if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(parser2, input, pos)) {
|
|
17532
|
-
if (failExpected === void 0) {
|
|
17533
|
-
const e = deriveExpected(parser2);
|
|
17534
|
-
failExpected = e.length > 0 ? e : [parser2._tag];
|
|
17535
|
-
}
|
|
17536
|
-
return { ok: false, expected: failExpected, span: { start: pos, end: pos } };
|
|
17537
|
-
}
|
|
17538
|
-
const mark = saveCstMark(ctx);
|
|
17539
|
-
const log = ctx._triviaLog?.length;
|
|
17540
|
-
const rootLog = ctx._rootTriviaLog?.length;
|
|
17541
|
-
const split = ctx._columnsSplit;
|
|
17542
|
-
const result = parser2.parse(input, pos, ctx);
|
|
17543
|
-
if (result.ok) return result;
|
|
17544
|
-
rollbackCstCapture(ctx, mark);
|
|
17545
|
-
ctx._columnsSplit = split;
|
|
17546
|
-
if (log !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== log) ctx._triviaLog.length = log;
|
|
17547
|
-
if (rootLog !== void 0 && ctx._rootTriviaLog && ctx._rootTriviaLog.length !== rootLog) ctx._rootTriviaLog.length = rootLog;
|
|
17548
|
-
if (result.committed && !contain) return result;
|
|
17549
|
-
return { ok: false, expected: result.expected, span: { start: pos, end: pos } };
|
|
17550
|
-
}
|
|
17551
|
-
};
|
|
17552
|
-
}
|
|
17553
|
-
|
|
17554
18391
|
// src/combinators/not.ts
|
|
17555
18392
|
function not(combinator) {
|
|
17556
18393
|
const meta = {
|