parseman 0.57.0 → 0.58.1
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 +1800 -962
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/cli/index.js +1929 -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 +1017 -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 +1210 -236
- package/dist/plugin/index.js.map +3 -3
- package/dist/run/index.d.ts +2 -0
- package/dist/run/index.d.ts.map +1 -1
- package/dist/run/index.js +9 -0
- package/dist/run/index.js.map +1 -1
- 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 +1370 -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/run/index.ts +5 -0
- 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 +83 -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,51 @@ 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 nextDef = next._def;
|
|
7709
|
+
if (nextDef.tag !== "literal" && nextDef.tag !== "regex" && nextDef.tag !== "keywords" && nextDef.tag !== "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
|
+
const miss = nextDef.tag === "label" ? deriveExpected(next) : directTerminalFailureExpected(nextDef);
|
|
7714
|
+
return { cls, fx: this.expected(miss) };
|
|
7715
|
+
}
|
|
7045
7716
|
node(p) {
|
|
7046
7717
|
const lazyRef = p._def.tag === "lazy";
|
|
7047
7718
|
const scopeKey = lazyRef ? this.activeTrivia : void 0;
|
|
@@ -7166,6 +7837,10 @@ var Encoder = class {
|
|
|
7166
7837
|
return head;
|
|
7167
7838
|
}
|
|
7168
7839
|
case "choice": {
|
|
7840
|
+
if (this.plan === void 0) {
|
|
7841
|
+
const factored = factorSharedEnds(d);
|
|
7842
|
+
if (factored !== void 0) return this.node(factored).ip;
|
|
7843
|
+
}
|
|
7169
7844
|
if (d.strategy.tag === "greedyClassify") {
|
|
7170
7845
|
const superIndex = d.strategy.superIndex;
|
|
7171
7846
|
const sup = this.node(d.parsers[superIndex]).ip;
|
|
@@ -7189,9 +7864,12 @@ var Encoder = class {
|
|
|
7189
7864
|
const kids = arms.map((c, k) => {
|
|
7190
7865
|
const src = order[k];
|
|
7191
7866
|
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
7867
|
const gate = d.gates[src];
|
|
7868
|
+
const plain2 = (checks === null || checks === void 0 || checks.length === 0) && (gate === null || gate === void 0);
|
|
7869
|
+
const routedGate = plain2 ? this.routedArmGate(c) : void 0;
|
|
7870
|
+
const body = this.node(c).ip;
|
|
7871
|
+
const inner = routedGate === void 0 ? body : this.emit(OP_RGATE, routedGate.cls, body, routedGate.fx);
|
|
7872
|
+
const ip = checks === null || checks === void 0 || checks.length === 0 ? inner : this.reject(inner, checks);
|
|
7195
7873
|
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
7874
|
return this.covWrap(gated, armCovIds?.[src], 1);
|
|
7197
7875
|
});
|
|
@@ -7515,6 +8193,7 @@ var Encoder = class {
|
|
|
7515
8193
|
const slots = (ip) => {
|
|
7516
8194
|
switch (this.code[ip]) {
|
|
7517
8195
|
case OP_GATE:
|
|
8196
|
+
case OP_RGATE:
|
|
7518
8197
|
return [ip + 2];
|
|
7519
8198
|
case OP_RULE:
|
|
7520
8199
|
case OP_OPT:
|
|
@@ -8742,6 +9421,7 @@ function childSlots(code, ip, out) {
|
|
|
8742
9421
|
case OP_LEAF:
|
|
8743
9422
|
case OP_SOURCE_LEAF:
|
|
8744
9423
|
case OP_ARMGATE:
|
|
9424
|
+
case OP_RGATE:
|
|
8745
9425
|
out.push(code[ip + 2]);
|
|
8746
9426
|
return true;
|
|
8747
9427
|
// `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
|
|
@@ -8825,6 +9505,42 @@ function reachableSites(code, roots) {
|
|
|
8825
9505
|
}
|
|
8826
9506
|
return seen;
|
|
8827
9507
|
}
|
|
9508
|
+
function passCollapse(code, ip, hostCst) {
|
|
9509
|
+
const flags = code[ip + 3];
|
|
9510
|
+
if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return false;
|
|
9511
|
+
if (flags !== 32 && flags !== 34) return false;
|
|
9512
|
+
let at = code[ip + 2];
|
|
9513
|
+
for (let n = 0; n < 8; n++) {
|
|
9514
|
+
const op = code[at];
|
|
9515
|
+
if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[at + 3] === 0) at = code[at + 2];
|
|
9516
|
+
else if (op === OP_RULE) at = code[at + 1];
|
|
9517
|
+
else break;
|
|
9518
|
+
}
|
|
9519
|
+
return code[at] === OP_NODE;
|
|
9520
|
+
}
|
|
9521
|
+
function gatedPassCollapse(code, ip, hostCst) {
|
|
9522
|
+
const flags = code[ip + 3];
|
|
9523
|
+
if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return void 0;
|
|
9524
|
+
if (flags !== 32 && flags !== 34) return void 0;
|
|
9525
|
+
const seq = code[ip + 2];
|
|
9526
|
+
if (code[seq] !== OP_SEQ && code[seq] !== OP_SEQV) return void 0;
|
|
9527
|
+
const n = code[seq + 1];
|
|
9528
|
+
if (n < 2) return void 0;
|
|
9529
|
+
const leads = [];
|
|
9530
|
+
const lits = [];
|
|
9531
|
+
for (let i = 0; i < n - 1; i++) {
|
|
9532
|
+
const t2 = code[seq + 2 + i];
|
|
9533
|
+
if (code[t2] !== OP_OPT && code[t2] !== OP_NOT) return void 0;
|
|
9534
|
+
const g = code[t2 + 1];
|
|
9535
|
+
if (code[g] === OP_GATE) leads.push(g);
|
|
9536
|
+
else if (code[g] === OP_LIT) lits.push(code[g + 1]);
|
|
9537
|
+
else return void 0;
|
|
9538
|
+
}
|
|
9539
|
+
const last = code[seq + 2 + n - 1];
|
|
9540
|
+
let at = last;
|
|
9541
|
+
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];
|
|
9542
|
+
return code[at] === OP_NODE ? { leads, lits, last } : void 0;
|
|
9543
|
+
}
|
|
8828
9544
|
function transfer(code, ip, at, hostCst) {
|
|
8829
9545
|
const op = code[ip];
|
|
8830
9546
|
if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
|
|
@@ -8836,14 +9552,18 @@ function transfer(code, ip, at, hostCst) {
|
|
|
8836
9552
|
}
|
|
8837
9553
|
if (op === OP_NODE || op === OP_NODE_TRACK) {
|
|
8838
9554
|
const flags = code[ip + 3];
|
|
9555
|
+
if (passCollapse(code, ip, hostCst)) return at;
|
|
9556
|
+
const gated = gatedPassCollapse(code, ip, hostCst) !== void 0;
|
|
8839
9557
|
const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && ((flags & ~128) === 2 || flags === 18 || flags === 34);
|
|
8840
9558
|
if (directChildren) {
|
|
8841
|
-
|
|
9559
|
+
const framed2 = { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
|
|
9560
|
+
return gated ? meet(at, framed2) : framed2;
|
|
8842
9561
|
}
|
|
8843
9562
|
const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
|
|
8844
9563
|
const raw = !hostCst && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags & 2) !== 0 ? RAW_OMIT : RAW_CAPTURE;
|
|
8845
9564
|
if (at.buf && raw === at.raw && cap === at.cap) return at;
|
|
8846
|
-
|
|
9565
|
+
const framed = { tri: at.tri, buf: true, raw, cap };
|
|
9566
|
+
return gated ? meet(at, framed) : framed;
|
|
8847
9567
|
}
|
|
8848
9568
|
if (op === OP_TOKEN) {
|
|
8849
9569
|
if (at.tri === TRI_NONE && !at.buf) return at;
|
|
@@ -8881,6 +9601,40 @@ function computeSiteLabels(code, roots, hostCst) {
|
|
|
8881
9601
|
}
|
|
8882
9602
|
return { at: (ip) => labels.get(ip) ?? TOP };
|
|
8883
9603
|
}
|
|
9604
|
+
function scopeIsIdentity(code, ip, at) {
|
|
9605
|
+
const op = code[ip];
|
|
9606
|
+
if (op !== OP_SCOPE_PLAIN && !(op === OP_SCOPE && code[ip + 3] === 0)) return false;
|
|
9607
|
+
const ki = code[ip + 1];
|
|
9608
|
+
return at.tri === (ki < 0 ? TRI_NONE : ki);
|
|
9609
|
+
}
|
|
9610
|
+
function scanHandoffNeeded(code, ip, labels) {
|
|
9611
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9612
|
+
const stack = [ip];
|
|
9613
|
+
const kids = [];
|
|
9614
|
+
while (stack.length > 0) {
|
|
9615
|
+
const at = stack.pop();
|
|
9616
|
+
if (seen.has(at)) continue;
|
|
9617
|
+
seen.add(at);
|
|
9618
|
+
const l = labels.at(at);
|
|
9619
|
+
if (l.tri === TRI_UNKNOWN) return true;
|
|
9620
|
+
const op = code[at];
|
|
9621
|
+
if (op === OP_SCAN) return true;
|
|
9622
|
+
if (op === OP_TOKEN || op === OP_SCOPE_CAP) continue;
|
|
9623
|
+
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;
|
|
9624
|
+
kids.length = 0;
|
|
9625
|
+
if (!childSlots(code, at, kids)) return true;
|
|
9626
|
+
for (const c of kids) stack.push(c);
|
|
9627
|
+
}
|
|
9628
|
+
return false;
|
|
9629
|
+
}
|
|
9630
|
+
function triviaLeadRanges(tri, trivia2) {
|
|
9631
|
+
if (tri === TRI_NONE) return [];
|
|
9632
|
+
if (tri < 0) return void 0;
|
|
9633
|
+
const fs = trivia2[tri]?._meta.firstSet;
|
|
9634
|
+
if (fs === void 0) return void 0;
|
|
9635
|
+
if (fs.kind === "empty") return [];
|
|
9636
|
+
return fs.kind === "ranges" && fs.ranges !== void 0 ? fs.ranges : void 0;
|
|
9637
|
+
}
|
|
8884
9638
|
|
|
8885
9639
|
// src/table/scalar-terminal.ts
|
|
8886
9640
|
function makeScalarRecognizer(op, spec) {
|
|
@@ -8918,6 +9672,12 @@ function scalarTerminalNotChild(code, ip) {
|
|
|
8918
9672
|
const op = code[child];
|
|
8919
9673
|
return op === OP_RX || op === OP_LIT ? child : -1;
|
|
8920
9674
|
}
|
|
9675
|
+
function scalarTerminalPeekChild(code, ip) {
|
|
9676
|
+
if (code[ip] !== OP_PEEK) return -1;
|
|
9677
|
+
const child = code[ip + 1];
|
|
9678
|
+
const op = code[child];
|
|
9679
|
+
return op === OP_RX || op === OP_LIT ? child : -1;
|
|
9680
|
+
}
|
|
8921
9681
|
function leadingScalarTerminal(code, ip, minDepth = 2, throughAttempt = true, throughPeek = false) {
|
|
8922
9682
|
const seen = /* @__PURE__ */ new Set();
|
|
8923
9683
|
let at = ip;
|
|
@@ -9095,6 +9855,59 @@ function leadingTriviaFieldAt(code, k, ip) {
|
|
|
9095
9855
|
return code[ip] === OP_FIELD && (fieldSpec(k[code[ip + 1]]).bits & FIELD_LEADING_TRIVIA) !== 0;
|
|
9096
9856
|
}
|
|
9097
9857
|
|
|
9858
|
+
// src/table/hold-gap.ts
|
|
9859
|
+
var WRAPPERS = /* @__PURE__ */ new Set([
|
|
9860
|
+
OP_NODE,
|
|
9861
|
+
OP_XFORM,
|
|
9862
|
+
OP_LEAF,
|
|
9863
|
+
OP_SOURCE_LEAF,
|
|
9864
|
+
OP_TOKEN,
|
|
9865
|
+
OP_SCOPE,
|
|
9866
|
+
OP_SCOPE_CAP,
|
|
9867
|
+
OP_SCOPE_PLAIN,
|
|
9868
|
+
OP_FIELD,
|
|
9869
|
+
OP_LABEL,
|
|
9870
|
+
OP_EXPECT,
|
|
9871
|
+
OP_WITHCTX,
|
|
9872
|
+
OP_RULE,
|
|
9873
|
+
OP_ATTEMPT,
|
|
9874
|
+
OP_COV
|
|
9875
|
+
]);
|
|
9876
|
+
function rowNullable(code, k, ip, memo) {
|
|
9877
|
+
const hit = memo.get(ip);
|
|
9878
|
+
if (hit !== void 0) return hit;
|
|
9879
|
+
memo.set(ip, true);
|
|
9880
|
+
const op = code[ip];
|
|
9881
|
+
const kids = [];
|
|
9882
|
+
let out = true;
|
|
9883
|
+
if (op === OP_GATE) out = false;
|
|
9884
|
+
else if (op === OP_LIT || op === OP_LIT_CI) out = k[code[ip + 1]].length === 0;
|
|
9885
|
+
else if (op === OP_RX) {
|
|
9886
|
+
const re = k[code[ip + 1]];
|
|
9887
|
+
out = !(re instanceof RegExp) || regexCanMatchEmpty(re.source);
|
|
9888
|
+
} else if (op === OP_SEQ || op === OP_SEQV || op === OP_SEQX) {
|
|
9889
|
+
childSlots(code, ip, kids);
|
|
9890
|
+
out = kids.every((c) => rowNullable(code, k, c, memo));
|
|
9891
|
+
} else if (op === OP_CHOICE) {
|
|
9892
|
+
childSlots(code, ip, kids);
|
|
9893
|
+
out = kids.length === 0 || kids.some((c) => rowNullable(code, k, c, memo));
|
|
9894
|
+
} else if (op === OP_REP || op === OP_REPV) {
|
|
9895
|
+
out = code[ip + 2] === 0 || rowNullable(code, k, code[ip + 1], memo);
|
|
9896
|
+
} else if (WRAPPERS.has(op)) {
|
|
9897
|
+
if (childSlots(code, ip, kids) && kids.length === 1) out = rowNullable(code, k, kids[0], memo);
|
|
9898
|
+
}
|
|
9899
|
+
memo.set(ip, out);
|
|
9900
|
+
return out;
|
|
9901
|
+
}
|
|
9902
|
+
function holdsGap(code, k, base, n, i, memo) {
|
|
9903
|
+
if (i < 1 || i + 1 >= n) return false;
|
|
9904
|
+
const term = code[base + i];
|
|
9905
|
+
if (code[term] !== OP_NOT && code[term] !== OP_PEEK) return false;
|
|
9906
|
+
const next = code[base + i + 1];
|
|
9907
|
+
if (code[next] === OP_ADJ || leadingTriviaFieldAt(code, k, next)) return false;
|
|
9908
|
+
return !rowNullable(code, k, next, memo);
|
|
9909
|
+
}
|
|
9910
|
+
|
|
9098
9911
|
// src/table/emit-assembly.ts
|
|
9099
9912
|
var Unemittable = class extends Error {
|
|
9100
9913
|
construct;
|
|
@@ -9175,7 +9988,10 @@ var EMITTED_PARAMS = [
|
|
|
9175
9988
|
"triviaFieldCapture",
|
|
9176
9989
|
// Appended for the deferred-commit trivia skip (`trivia-gap.ts`); old
|
|
9177
9990
|
// factories ignore it.
|
|
9178
|
-
"skipDeferredTrivia"
|
|
9991
|
+
"skipDeferredTrivia",
|
|
9992
|
+
// Appended for the pass-through collapse (`run-support.ts`); old factories
|
|
9993
|
+
// ignore it.
|
|
9994
|
+
"collapseEmpty"
|
|
9179
9995
|
];
|
|
9180
9996
|
var RUNTIME_PRELUDE = `
|
|
9181
9997
|
let _pfScan=null
|
|
@@ -9372,6 +10188,24 @@ ${fast}
|
|
|
9372
10188
|
${scanned}
|
|
9373
10189
|
}`;
|
|
9374
10190
|
}
|
|
10191
|
+
function emitHoldTerm(callee, dst, t2, l, skip) {
|
|
10192
|
+
const fast = `const ${t2}v=${callee}(input,cur,ctx)
|
|
10193
|
+
if(${t2}v===FAIL)return FAIL
|
|
10194
|
+
${dst}=${t2}v
|
|
10195
|
+
cur=EC.e`;
|
|
10196
|
+
if (l.tri === TRI_NONE) return fast;
|
|
10197
|
+
const held = `const ${t2}s=${skip}(input,cur,ctx)
|
|
10198
|
+
const ${t2}v=${callee}(input,${t2}s,ctx)
|
|
10199
|
+
if(${t2}v===FAIL)return FAIL
|
|
10200
|
+
${dst}=${t2}v
|
|
10201
|
+
cur=${t2}s`;
|
|
10202
|
+
if (l.tri !== TRI_UNKNOWN) return held;
|
|
10203
|
+
return `if(ctx.trivia===undefined){
|
|
10204
|
+
${fast}
|
|
10205
|
+
}else{
|
|
10206
|
+
${held}
|
|
10207
|
+
}`;
|
|
10208
|
+
}
|
|
9375
10209
|
function leadSkip(hasTrivia, leadTrivia, skip) {
|
|
9376
10210
|
if (hasTrivia === "false") return "{}";
|
|
9377
10211
|
const call = `itemStart=${skip}(input,itemStart,ctx)`;
|
|
@@ -9413,6 +10247,7 @@ function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false, s
|
|
|
9413
10247
|
const reachable = [...reachableSites(code, roots)];
|
|
9414
10248
|
const labels = computeSiteLabels(code, roots, hostCst);
|
|
9415
10249
|
const scalarSpecs = /* @__PURE__ */ new Set();
|
|
10250
|
+
const nullable2 = /* @__PURE__ */ new Map();
|
|
9416
10251
|
const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
|
|
9417
10252
|
const largeChoiceLiteralFamilies = /* @__PURE__ */ new Map();
|
|
9418
10253
|
const largeChoiceScalarSequences = /* @__PURE__ */ new Map();
|
|
@@ -9737,9 +10572,7 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
9737
10572
|
const op = code[ip];
|
|
9738
10573
|
if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
|
|
9739
10574
|
if (op === OP_RULE) return code[ip + 1];
|
|
9740
|
-
if ((
|
|
9741
|
-
return code[ip + 2];
|
|
9742
|
-
}
|
|
10575
|
+
if (scopeIsIdentity(code, ip, labels.at(ip))) return code[ip + 2];
|
|
9743
10576
|
return void 0;
|
|
9744
10577
|
}
|
|
9745
10578
|
function lower(ip, fname) {
|
|
@@ -9861,6 +10694,22 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
9861
10694
|
return `${head}
|
|
9862
10695
|
if(${gateMissTest(ip)}){ctx._fe=pos;ctx._fx=${xf};return FAIL}
|
|
9863
10696
|
return ${child}(input,pos,ctx)
|
|
10697
|
+
}`;
|
|
10698
|
+
}
|
|
10699
|
+
case OP_RGATE: {
|
|
10700
|
+
const child = link(code[ip + 2]);
|
|
10701
|
+
if (cfg.tolerant || cfg.probe) return `${head}
|
|
10702
|
+
return ${child}(input,pos,ctx)
|
|
10703
|
+
}`;
|
|
10704
|
+
const resolved = t2.cc[code[ip + 1]];
|
|
10705
|
+
const ci = classes.push([resolved]) - 1;
|
|
10706
|
+
classPlan.push([code[ip + 1]]);
|
|
10707
|
+
const cls = hoist("cl", `CLS[${ci}][0]`);
|
|
10708
|
+
const xf = fxRef(code[ip + 3]);
|
|
10709
|
+
return `${head}
|
|
10710
|
+
const it=ctx._routed
|
|
10711
|
+
if(it!==undefined&&it.span.start===pos&&!classHas(${cls},lead(input,it.span.end))){ctx._fe=it.span.end;ctx._fx=${xf};return FAIL}
|
|
10712
|
+
return ${child}(input,pos,ctx)
|
|
9864
10713
|
}`;
|
|
9865
10714
|
}
|
|
9866
10715
|
case OP_ARMGATE: {
|
|
@@ -10135,23 +10984,33 @@ return FAIL
|
|
|
10135
10984
|
const p = tmp();
|
|
10136
10985
|
return `${head}
|
|
10137
10986
|
${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${emitMark(p, L.buf, L.raw, sinks)}
|
|
10138
|
-
const v=${child}(input,pos,ctx)
|
|
10987
|
+
${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
|
|
10139
10988
|
${emitRollback(p, L.buf, L.raw, sinks)}
|
|
10140
|
-
if(v===FAIL){EC.e=pos;return null}
|
|
10989
|
+
${cfg.probe ? "if(ctx._probe!==undefined)ctx._probe.best=pb??null\n" : ""}if(v===FAIL){EC.e=pos;return null}
|
|
10141
10990
|
ctx._fe=pos
|
|
10142
10991
|
ctx._fx=${xf}
|
|
10143
10992
|
return FAIL
|
|
10144
10993
|
}`;
|
|
10145
10994
|
}
|
|
10146
10995
|
case OP_PEEK: {
|
|
10996
|
+
const scalarChild = scalarTerminalPeekChild(code, ip);
|
|
10997
|
+
if (scalarChild >= 0) {
|
|
10998
|
+
const recognize = recognizerRef(code[scalarChild + 1]);
|
|
10999
|
+
const xf2 = fxRef(code[ip + 2]);
|
|
11000
|
+
return `${head}
|
|
11001
|
+
if(${recognize}(input,pos)<0){ctx._fe=pos;ctx._fx=${xf2};return FAIL}
|
|
11002
|
+
EC.e=pos
|
|
11003
|
+
return null
|
|
11004
|
+
}`;
|
|
11005
|
+
}
|
|
10147
11006
|
const child = link(code[ip + 1]);
|
|
10148
11007
|
const xf = fxRef(code[ip + 2]);
|
|
10149
11008
|
const p = tmp();
|
|
10150
11009
|
return `${head}
|
|
10151
11010
|
${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)
|
|
11011
|
+
${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
|
|
10153
11012
|
${emitRollback(p, L.buf, L.raw, sinks)}
|
|
10154
|
-
if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
|
|
11013
|
+
${cfg.probe ? "if(ctx._probe!==undefined)ctx._probe.best=pb??null\n" : ""}if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
|
|
10155
11014
|
EC.e=pos
|
|
10156
11015
|
return null
|
|
10157
11016
|
}`;
|
|
@@ -10222,7 +11081,7 @@ return v
|
|
|
10222
11081
|
);
|
|
10223
11082
|
} else {
|
|
10224
11083
|
const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
|
|
10225
|
-
parts.push(emitTerm(callee, vn, tmp(), L, skipFor(L)));
|
|
11084
|
+
parts.push(holdsGap(code, k, base, n, i, nullable2) ? emitHoldTerm(callee, vn, tmp(), L, skipFor(L)) : emitTerm(callee, vn, tmp(), L, skipFor(L)));
|
|
10226
11085
|
}
|
|
10227
11086
|
names.push(vn);
|
|
10228
11087
|
}
|
|
@@ -10705,6 +11564,26 @@ return nd
|
|
|
10705
11564
|
const trailingTrivia = (flags & 128) !== 0;
|
|
10706
11565
|
const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
|
|
10707
11566
|
const leanFlags = flags & ~128;
|
|
11567
|
+
if (build !== void 0 && passCollapse(code, ip, hostCst)) {
|
|
11568
|
+
return `${head}
|
|
11569
|
+
const v=${child}(input,pos,ctx)
|
|
11570
|
+
if(v!==undefined)return v
|
|
11571
|
+
return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
|
|
11572
|
+
}`;
|
|
11573
|
+
}
|
|
11574
|
+
const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
|
|
11575
|
+
const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(labels.at(code[ip + 2]).tri, t2.trivia);
|
|
11576
|
+
const gp = gated !== void 0 && triviaLead !== void 0 && triviaLead.length <= 16 ? `const gc=lead(input,pos)
|
|
11577
|
+
if(!(${[
|
|
11578
|
+
...gated.leads.map((g) => `!(${gateMissTest(g)})`),
|
|
11579
|
+
...gated.lits.map((i) => `gc===${k[i].codePointAt(0)}`),
|
|
11580
|
+
...triviaLead.map((r) => r.lo === r.hi ? `gc===${r.lo}` : `(gc>=${r.lo}&&gc<=${r.hi})`)
|
|
11581
|
+
].join("||") || "false"})){
|
|
11582
|
+
const gv=${link(gated.last)}(input,pos,ctx)
|
|
11583
|
+
if(gv!==undefined)return gv
|
|
11584
|
+
return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
|
|
11585
|
+
}
|
|
11586
|
+
` : "";
|
|
10708
11587
|
if (!hostCst && !tracked && build !== void 0 && proj < 0 && (leanFlags === 2 || (flags === 18 || flags === 34))) {
|
|
10709
11588
|
const fields = flags === 18;
|
|
10710
11589
|
const collapseChildren = flags === 34;
|
|
@@ -10739,7 +11618,7 @@ sCh.push(nd)
|
|
|
10739
11618
|
if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
|
|
10740
11619
|
}`;
|
|
10741
11620
|
return `${head}
|
|
10742
|
-
const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
11621
|
+
${gp}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
10743
11622
|
const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
|
|
10744
11623
|
const flat=[]
|
|
10745
11624
|
ctx._cstBuf=undefined
|
|
@@ -10814,7 +11693,7 @@ const hostKids=kids
|
|
|
10814
11693
|
const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
|
|
10815
11694
|
const tlog=buf.tl??EMPTY_TLOG`;
|
|
10816
11695
|
return `${head}
|
|
10817
|
-
const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
11696
|
+
${!hostCst && !tracked ? gp : ""}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
10818
11697
|
const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf
|
|
10819
11698
|
${openCapture}
|
|
10820
11699
|
ctx.captureTrivia=${captureWide}
|
|
@@ -10884,9 +11763,15 @@ ext:[${externals.join(",")}],
|
|
|
10884
11763
|
bind:function(xs,ps){_xScan=xs
|
|
10885
11764
|
${externals.map((ip, i) => `_xp${ip}=ps[${i}]`).join("\n")}},
|
|
10886
11765
|
scan:function(s){const o=_pfScan;_pfScan=s;return o}`;
|
|
11766
|
+
const scannerFor = (ip) => {
|
|
11767
|
+
const ki = labels.at(ip).tri;
|
|
11768
|
+
if (ki === TRI_UNKNOWN) return "_pfScan";
|
|
11769
|
+
if (ki === TRI_NONE) return "null";
|
|
11770
|
+
return swapLegal && !triviaLabelled[ki] && t2.triviaScan[ki] != null ? hoist("ts", `TRIVIASCAN[${ki}]`) : "null";
|
|
11771
|
+
};
|
|
10887
11772
|
const externalDefs = select === void 0 ? "" : `let _xScan
|
|
10888
11773
|
${externals.map((ip) => `let _xp${ip}
|
|
10889
|
-
function _px${ip}(input,pos,ctx){const o=_xScan(
|
|
11774
|
+
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
11775
|
`;
|
|
10891
11776
|
const source = `${RUNTIME_PRELUDE}${needsNoRawPrelude ? NO_RAW_RUNTIME_PRELUDE : ""}
|
|
10892
11777
|
${prelude.join("\n")}
|
|
@@ -11203,136 +12088,6 @@ function literal(value, opts = {}) {
|
|
|
11203
12088
|
};
|
|
11204
12089
|
}
|
|
11205
12090
|
|
|
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
12091
|
// src/combinators/ref.ts
|
|
11337
12092
|
function withRuleTrivia(trivia2, ctx, run) {
|
|
11338
12093
|
const savedLabels = ctx.triviaKindLabels;
|
|
@@ -11358,164 +12113,46 @@ function ref() {
|
|
|
11358
12113
|
const slot = {
|
|
11359
12114
|
_tag: "lazy",
|
|
11360
12115
|
_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" } : {}
|
|
12116
|
+
_def: {
|
|
12117
|
+
tag: "lazy",
|
|
12118
|
+
thunk: () => {
|
|
12119
|
+
if (!resolved) throw UNDEFINED_REF;
|
|
12120
|
+
return resolved;
|
|
12121
|
+
}
|
|
12122
|
+
},
|
|
12123
|
+
_parseScalar(input, pos, ctx) {
|
|
12124
|
+
const scalar = resolvedScalar;
|
|
12125
|
+
if (!scalar) throw new Error("ref<T>() used before .define() was called");
|
|
12126
|
+
const gt = meta.grammarTrivia;
|
|
12127
|
+
if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
|
|
12128
|
+
return withRuleTrivia(gt, ctx, () => scalar(input, pos, ctx));
|
|
12129
|
+
}
|
|
12130
|
+
return scalar(input, pos, ctx);
|
|
11477
12131
|
},
|
|
11478
12132
|
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;
|
|
12133
|
+
const parser2 = resolved;
|
|
12134
|
+
if (!parser2) throw new Error("ref<T>() used before .define() was called");
|
|
12135
|
+
const gt = meta.grammarTrivia;
|
|
12136
|
+
if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
|
|
12137
|
+
return withRuleTrivia(gt, ctx, () => parser2.parse(input, pos, ctx));
|
|
11502
12138
|
}
|
|
11503
|
-
|
|
11504
|
-
|
|
11505
|
-
|
|
11506
|
-
|
|
11507
|
-
|
|
11508
|
-
|
|
11509
|
-
|
|
11510
|
-
|
|
12139
|
+
return parser2.parse(input, pos, ctx);
|
|
12140
|
+
},
|
|
12141
|
+
define(p) {
|
|
12142
|
+
if (resolved) throw new Error("ref<T>() already defined");
|
|
12143
|
+
resolved = p;
|
|
12144
|
+
resolvedScalar = scalarOf(p);
|
|
12145
|
+
ownBoundary = hasOwnTriviaBoundary(p);
|
|
12146
|
+
meta.firstSet = p._meta.firstSet;
|
|
12147
|
+
meta.canMatchNewline = p._meta.canMatchNewline;
|
|
12148
|
+
meta.isTrivia = p._meta.isTrivia;
|
|
12149
|
+
if (p._meta.triviaKindLabels !== void 0) meta.triviaKindLabels = p._meta.triviaKindLabels;
|
|
12150
|
+
else delete meta.triviaKindLabels;
|
|
12151
|
+
if (p._meta.disjoint !== void 0) meta.disjoint = p._meta.disjoint;
|
|
12152
|
+
else delete meta.disjoint;
|
|
11511
12153
|
}
|
|
11512
12154
|
};
|
|
11513
|
-
|
|
11514
|
-
function leaf(root, fn) {
|
|
11515
|
-
return makeLeaf(root, fn, false);
|
|
11516
|
-
}
|
|
11517
|
-
function sourceLeaf(root, fn) {
|
|
11518
|
-
return makeLeaf(root, fn, true);
|
|
12155
|
+
return slot;
|
|
11519
12156
|
}
|
|
11520
12157
|
|
|
11521
12158
|
// src/combinators/scanTo.ts
|
|
@@ -11826,37 +12463,120 @@ function clearOf(ranges, input, from, to) {
|
|
|
11826
12463
|
return true;
|
|
11827
12464
|
}
|
|
11828
12465
|
|
|
11829
|
-
// src/table/
|
|
11830
|
-
function
|
|
11831
|
-
|
|
11832
|
-
|
|
11833
|
-
|
|
11834
|
-
|
|
11835
|
-
|
|
11836
|
-
|
|
12466
|
+
// src/table/fail-clean.ts
|
|
12467
|
+
function passChild(code, ip) {
|
|
12468
|
+
switch (code[ip]) {
|
|
12469
|
+
case OP_RULE:
|
|
12470
|
+
case OP_LABEL:
|
|
12471
|
+
case OP_COV:
|
|
12472
|
+
case OP_TOKEN:
|
|
12473
|
+
return code[ip + 1];
|
|
12474
|
+
case OP_GATE:
|
|
12475
|
+
case OP_NODE:
|
|
12476
|
+
case OP_NODE_TRACK:
|
|
12477
|
+
case OP_XFORM:
|
|
12478
|
+
case OP_FIELD:
|
|
12479
|
+
case OP_SCOPE:
|
|
12480
|
+
case OP_SCOPE_CAP:
|
|
12481
|
+
case OP_SCOPE_PLAIN:
|
|
12482
|
+
case OP_WITHCTX:
|
|
12483
|
+
case OP_LEAF:
|
|
12484
|
+
case OP_SOURCE_LEAF:
|
|
12485
|
+
return code[ip + 2];
|
|
12486
|
+
default:
|
|
12487
|
+
return -1;
|
|
11837
12488
|
}
|
|
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
12489
|
}
|
|
11844
|
-
function
|
|
11845
|
-
|
|
11846
|
-
|
|
11847
|
-
|
|
11848
|
-
|
|
11849
|
-
|
|
11850
|
-
|
|
11851
|
-
|
|
11852
|
-
|
|
12490
|
+
function seqCount(code, ip) {
|
|
12491
|
+
const op = code[ip];
|
|
12492
|
+
return op === OP_SEQ || op === OP_SEQV ? ip + 1 : op === OP_SEQX ? ip + 2 : -1;
|
|
12493
|
+
}
|
|
12494
|
+
function failCleanAnalysis(code) {
|
|
12495
|
+
const cleanAt = new Uint8Array(code.length);
|
|
12496
|
+
const neverAt = new Uint8Array(code.length);
|
|
12497
|
+
const neverFails = (ip) => {
|
|
12498
|
+
const hit = neverAt[ip];
|
|
12499
|
+
if (hit !== 0) return hit === 1;
|
|
12500
|
+
neverAt[ip] = 3;
|
|
12501
|
+
let out = false;
|
|
12502
|
+
const op = code[ip];
|
|
12503
|
+
if (op === OP_OPT || op === OP_EMPTY || op === OP_EXPECT) out = true;
|
|
12504
|
+
else if (op === OP_REP || op === OP_REPV) out = code[ip + 2] === 0;
|
|
12505
|
+
else {
|
|
12506
|
+
const at = seqCount(code, ip);
|
|
12507
|
+
if (at >= 0) {
|
|
12508
|
+
out = true;
|
|
12509
|
+
for (let i = 1, n = code[at]; out && i <= n; i++) out = neverFails(code[at + i]);
|
|
12510
|
+
} else if (op !== OP_GATE) {
|
|
12511
|
+
const c = passChild(code, ip);
|
|
12512
|
+
out = c >= 0 && neverFails(c);
|
|
12513
|
+
}
|
|
12514
|
+
}
|
|
12515
|
+
neverAt[ip] = out ? 1 : 2;
|
|
12516
|
+
return out;
|
|
11853
12517
|
};
|
|
11854
|
-
|
|
11855
|
-
|
|
11856
|
-
|
|
11857
|
-
|
|
11858
|
-
|
|
11859
|
-
|
|
12518
|
+
const clean = (ip) => {
|
|
12519
|
+
const hit = cleanAt[ip];
|
|
12520
|
+
if (hit !== 0) return hit === 1;
|
|
12521
|
+
cleanAt[ip] = 3;
|
|
12522
|
+
let out = false;
|
|
12523
|
+
switch (code[ip]) {
|
|
12524
|
+
// A terminal pushes its leaf only on a match; NOT/PEEK/ATTEMPT restore
|
|
12525
|
+
// their own mark; OPT, EMPTY and EXPECT do not fail uncommitted.
|
|
12526
|
+
case OP_LIT:
|
|
12527
|
+
case OP_RX:
|
|
12528
|
+
case OP_LIT_TRACK:
|
|
12529
|
+
case OP_RX_TRACK:
|
|
12530
|
+
case OP_LIT_CI:
|
|
12531
|
+
case OP_LIT_CI_TRACK:
|
|
12532
|
+
case OP_GUARD:
|
|
12533
|
+
case OP_NOT:
|
|
12534
|
+
case OP_PEEK:
|
|
12535
|
+
case OP_ATTEMPT:
|
|
12536
|
+
case OP_EMPTY:
|
|
12537
|
+
case OP_OPT:
|
|
12538
|
+
case OP_EXPECT:
|
|
12539
|
+
out = true;
|
|
12540
|
+
break;
|
|
12541
|
+
// Min 0 does not fail uncommitted; min 1 fails only with no item kept, and
|
|
12542
|
+
// restores the failed item itself.
|
|
12543
|
+
case OP_REP:
|
|
12544
|
+
case OP_REPV:
|
|
12545
|
+
out = code[ip + 2] <= 1;
|
|
12546
|
+
break;
|
|
12547
|
+
// Only the first term may fail: a later one fails after the terms before it
|
|
12548
|
+
// wrote, and after the trivia scanned in front of it.
|
|
12549
|
+
case OP_SEQ:
|
|
12550
|
+
case OP_SEQV:
|
|
12551
|
+
case OP_SEQX: {
|
|
12552
|
+
const at = seqCount(code, ip);
|
|
12553
|
+
const n = code[at];
|
|
12554
|
+
out = n > 0 && clean(code[at + 1]);
|
|
12555
|
+
for (let i = 2; out && i <= n; i++) out = neverFails(code[at + i]);
|
|
12556
|
+
break;
|
|
12557
|
+
}
|
|
12558
|
+
case OP_CHOICE: {
|
|
12559
|
+
out = true;
|
|
12560
|
+
for (let i = 0, n = code[ip + 2]; out && i < n; i++) out = clean(code[ip + 4 + i]);
|
|
12561
|
+
break;
|
|
12562
|
+
}
|
|
12563
|
+
case OP_ROUTED:
|
|
12564
|
+
out = code[ip + 1] < 0 || clean(code[ip + 1]);
|
|
12565
|
+
break;
|
|
12566
|
+
// An arm's failure and the fallback's are committed; only the selector's is
|
|
12567
|
+
// not, and without a fallback an unknown key fails after the selector wrote.
|
|
12568
|
+
case OP_DISPATCH:
|
|
12569
|
+
out = code[ip + 3] >= 0 && clean(code[ip + 1]);
|
|
12570
|
+
break;
|
|
12571
|
+
default: {
|
|
12572
|
+
const c = passChild(code, ip);
|
|
12573
|
+
out = c >= 0 && clean(c);
|
|
12574
|
+
}
|
|
12575
|
+
}
|
|
12576
|
+
cleanAt[ip] = out ? 1 : 2;
|
|
12577
|
+
return out;
|
|
12578
|
+
};
|
|
12579
|
+
return clean;
|
|
11860
12580
|
}
|
|
11861
12581
|
|
|
11862
12582
|
// src/cst/host-mode.ts
|
|
@@ -12008,6 +12728,7 @@ function assemble(t2, prog, cfg) {
|
|
|
12008
12728
|
const swapLegal = !cfg.trackLines;
|
|
12009
12729
|
const hostCst = cfg.hostCst;
|
|
12010
12730
|
const REC = prog.rec === 1 && cfg.tolerant;
|
|
12731
|
+
const PROBE = cfg.probe;
|
|
12011
12732
|
const sentinels = /* @__PURE__ */ new Map();
|
|
12012
12733
|
function sentinelFor(cls) {
|
|
12013
12734
|
if (cls < 0) return void 0;
|
|
@@ -12053,6 +12774,8 @@ function assemble(t2, prog, cfg) {
|
|
|
12053
12774
|
}
|
|
12054
12775
|
const memo = /* @__PURE__ */ new Map();
|
|
12055
12776
|
const reached = /* @__PURE__ */ new Set();
|
|
12777
|
+
const NULLABLE = /* @__PURE__ */ new Map();
|
|
12778
|
+
const CLEAN = REC ? () => false : failCleanAnalysis(code);
|
|
12056
12779
|
function pushLeaf(ctx, value, s, e) {
|
|
12057
12780
|
const lf = { _tag: "leaf", value, span: { start: s, end: e } };
|
|
12058
12781
|
pushCstLeaf(ctx, lf);
|
|
@@ -12251,6 +12974,22 @@ function assemble(t2, prog, cfg) {
|
|
|
12251
12974
|
return node2;
|
|
12252
12975
|
};
|
|
12253
12976
|
}
|
|
12977
|
+
function passCollapseNode(child, build, readsRaw) {
|
|
12978
|
+
return (input, pos, ctx) => {
|
|
12979
|
+
const v = child(input, pos, ctx);
|
|
12980
|
+
if (v !== void 0) return v;
|
|
12981
|
+
return collapseEmpty(ctx, build, input, pos, EC.e, readsRaw);
|
|
12982
|
+
};
|
|
12983
|
+
}
|
|
12984
|
+
function gatedPassCollapseNode(blockers, last, classic, build, readsRaw) {
|
|
12985
|
+
return (input, pos, ctx) => {
|
|
12986
|
+
const c = lead(input, pos);
|
|
12987
|
+
for (let i = 0; i < blockers.length; i++) if (classHas2(blockers[i], c)) return classic(input, pos, ctx);
|
|
12988
|
+
const v = last(input, pos, ctx);
|
|
12989
|
+
if (v !== void 0) return v;
|
|
12990
|
+
return collapseEmpty(ctx, build, input, pos, EC.e, readsRaw);
|
|
12991
|
+
};
|
|
12992
|
+
}
|
|
12254
12993
|
function plainProjectNode(child, projection, type) {
|
|
12255
12994
|
return (input, pos, ctx) => {
|
|
12256
12995
|
const sCh = ctx._cstChildren;
|
|
@@ -12621,21 +13360,27 @@ function assemble(t2, prog, cfg) {
|
|
|
12621
13360
|
}
|
|
12622
13361
|
function dispatchBranch(child, usesRouted) {
|
|
12623
13362
|
if (!usesRouted) {
|
|
12624
|
-
return (input, _pos, selEnd, key,
|
|
12625
|
-
const
|
|
13363
|
+
return (input, _pos, selEnd, key, ctx) => {
|
|
13364
|
+
const need = markCst(ctx);
|
|
13365
|
+
const mRaw = MRAW;
|
|
13366
|
+
const mTl = MTL;
|
|
13367
|
+
const mLv = MLV;
|
|
13368
|
+
const mFl = need ? ctx._fields?.length ?? 0 : 0;
|
|
13369
|
+
const mEr = need ? ctx._errors?.length ?? 0 : 0;
|
|
13370
|
+
const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
13371
|
+
const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
12626
13372
|
const v = child(input, selEnd, ctx);
|
|
12627
13373
|
if (v === FAIL) {
|
|
12628
|
-
|
|
13374
|
+
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
12629
13375
|
ctx._fc = true;
|
|
12630
13376
|
return FAIL;
|
|
12631
13377
|
}
|
|
12632
13378
|
return [key, v];
|
|
12633
13379
|
};
|
|
12634
13380
|
}
|
|
12635
|
-
return (input, pos, selEnd, key,
|
|
13381
|
+
return (input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot) => {
|
|
12636
13382
|
const savedRouted = ctx._routed;
|
|
12637
|
-
|
|
12638
|
-
const mark = saveTriviaMark(ctx);
|
|
13383
|
+
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
12639
13384
|
ctx._routed = { value: key, span: { start: pos, end: selEnd } };
|
|
12640
13385
|
let v;
|
|
12641
13386
|
try {
|
|
@@ -12644,7 +13389,7 @@ function assemble(t2, prog, cfg) {
|
|
|
12644
13389
|
ctx._routed = savedRouted;
|
|
12645
13390
|
}
|
|
12646
13391
|
if (v === FAIL) {
|
|
12647
|
-
|
|
13392
|
+
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
12648
13393
|
ctx._fc = true;
|
|
12649
13394
|
return FAIL;
|
|
12650
13395
|
}
|
|
@@ -12652,12 +13397,12 @@ function assemble(t2, prog, cfg) {
|
|
|
12652
13397
|
};
|
|
12653
13398
|
}
|
|
12654
13399
|
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,
|
|
13400
|
+
return (arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot) => {
|
|
13401
|
+
if (arm === start) return a0(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
13402
|
+
if (arm === start + 1) return a1(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
13403
|
+
if (arm === start + 2) return a2(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
13404
|
+
if (arm === start + 3) return a3(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
13405
|
+
return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
12661
13406
|
};
|
|
12662
13407
|
}
|
|
12663
13408
|
function trackLinesInto(ctx, input, end) {
|
|
@@ -12676,7 +13421,7 @@ function assemble(t2, prog, cfg) {
|
|
|
12676
13421
|
if (flight !== void 0) return flight.fwd;
|
|
12677
13422
|
const selected = HYBRID?.byIp[ip];
|
|
12678
13423
|
if (selected !== void 0) {
|
|
12679
|
-
const piece2 = hybridPiece(selected);
|
|
13424
|
+
const piece2 = scanHandoffNeeded(code, ip, closureLabels) ? hybridPiece(selected) : selected;
|
|
12680
13425
|
memo.set(ip, piece2);
|
|
12681
13426
|
reached.add(ip);
|
|
12682
13427
|
return piece2;
|
|
@@ -12687,14 +13432,55 @@ function assemble(t2, prog, cfg) {
|
|
|
12687
13432
|
target = p;
|
|
12688
13433
|
} };
|
|
12689
13434
|
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);
|
|
13435
|
+
const piece = scopeIsIdentity(code, ip, closureLabels.at(ip)) ? link(code[ip + 2]) : countedPiece(lookaheadLedNode(ip) ?? lower(ip), ip);
|
|
12692
13436
|
inFlight.delete(ip);
|
|
12693
13437
|
holder.set(piece);
|
|
12694
13438
|
memo.set(ip, piece);
|
|
12695
13439
|
reached.add(ip);
|
|
12696
13440
|
return piece;
|
|
12697
13441
|
}
|
|
13442
|
+
let FIRST_DECIDED;
|
|
13443
|
+
let NODE_BODY;
|
|
13444
|
+
const DECIDED = (_input, pos) => {
|
|
13445
|
+
EC.e = pos;
|
|
13446
|
+
return null;
|
|
13447
|
+
};
|
|
13448
|
+
function lookaheadLedNode(ip) {
|
|
13449
|
+
const op = code[ip];
|
|
13450
|
+
if (op !== OP_NODE && op !== OP_NODE_TRACK || hostCst || REC || cfg.probe || cfg.coverage || cfg.trackLines) return void 0;
|
|
13451
|
+
if (passCollapse(code, ip, hostCst) || gatedPassCollapse(code, ip, hostCst) !== void 0) return void 0;
|
|
13452
|
+
const body = code[ip + 2];
|
|
13453
|
+
const bop = code[body];
|
|
13454
|
+
if (bop !== OP_SEQ && bop !== OP_SEQV && bop !== OP_SEQX) return void 0;
|
|
13455
|
+
const base = bop === OP_SEQX ? body + 3 : body + 2;
|
|
13456
|
+
if (code[bop === OP_SEQX ? body + 2 : body + 1] < 2) return void 0;
|
|
13457
|
+
const first = code[base];
|
|
13458
|
+
const negative = code[first] === OP_NOT;
|
|
13459
|
+
const terminal = negative ? scalarTerminalNotChild(code, first) : code[first] === OP_PEEK ? scalarTerminalPeekChild(code, first) : -1;
|
|
13460
|
+
if (terminal < 0) return void 0;
|
|
13461
|
+
const recognize = scalarFor(terminal);
|
|
13462
|
+
const xf = fx[code[first + 2]];
|
|
13463
|
+
FIRST_DECIDED = DECIDED;
|
|
13464
|
+
NODE_BODY = lower(body);
|
|
13465
|
+
const node2 = lower(ip);
|
|
13466
|
+
NODE_BODY = void 0;
|
|
13467
|
+
return negative ? (input, pos, ctx) => {
|
|
13468
|
+
if (recognize(input, pos) >= 0) {
|
|
13469
|
+
ctx._fe = pos;
|
|
13470
|
+
ctx._fx = xf;
|
|
13471
|
+
EC.e = pos;
|
|
13472
|
+
return FAIL;
|
|
13473
|
+
}
|
|
13474
|
+
return node2(input, pos, ctx);
|
|
13475
|
+
} : (input, pos, ctx) => {
|
|
13476
|
+
if (recognize(input, pos) < 0) {
|
|
13477
|
+
ctx._fe = pos;
|
|
13478
|
+
ctx._fx = xf;
|
|
13479
|
+
return FAIL;
|
|
13480
|
+
}
|
|
13481
|
+
return node2(input, pos, ctx);
|
|
13482
|
+
};
|
|
13483
|
+
}
|
|
12698
13484
|
function lower(ip) {
|
|
12699
13485
|
const op = code[ip];
|
|
12700
13486
|
switch (op) {
|
|
@@ -13239,8 +14025,10 @@ function assemble(t2, prog, cfg) {
|
|
|
13239
14025
|
const mEr = need ? ctx._errors?.length ?? 0 : 0;
|
|
13240
14026
|
const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
13241
14027
|
const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14028
|
+
const probeBest = PROBE ? ctx._probe?.best : void 0;
|
|
13242
14029
|
const v = child(input, pos, ctx);
|
|
13243
14030
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14031
|
+
if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
|
|
13244
14032
|
if (v === FAIL) {
|
|
13245
14033
|
EC.e = pos;
|
|
13246
14034
|
return null;
|
|
@@ -13251,6 +14039,20 @@ function assemble(t2, prog, cfg) {
|
|
|
13251
14039
|
};
|
|
13252
14040
|
}
|
|
13253
14041
|
case OP_PEEK: {
|
|
14042
|
+
const scalarChild = scalarTerminalPeekChild(code, ip);
|
|
14043
|
+
if (scalarChild >= 0) {
|
|
14044
|
+
const recognize = scalarFor(scalarChild);
|
|
14045
|
+
const xf2 = fx[code[ip + 2]];
|
|
14046
|
+
return (input, pos, ctx) => {
|
|
14047
|
+
if (recognize(input, pos) < 0) {
|
|
14048
|
+
ctx._fe = pos;
|
|
14049
|
+
ctx._fx = xf2;
|
|
14050
|
+
return FAIL;
|
|
14051
|
+
}
|
|
14052
|
+
EC.e = pos;
|
|
14053
|
+
return null;
|
|
14054
|
+
};
|
|
14055
|
+
}
|
|
13254
14056
|
const child = link(code[ip + 1]);
|
|
13255
14057
|
const xf = fx[code[ip + 2]];
|
|
13256
14058
|
const gate = lookaheadClass(code[ip + 1]);
|
|
@@ -13268,8 +14070,10 @@ function assemble(t2, prog, cfg) {
|
|
|
13268
14070
|
const mEr = need ? ctx._errors?.length ?? 0 : 0;
|
|
13269
14071
|
const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
13270
14072
|
const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14073
|
+
const probeBest = PROBE ? ctx._probe?.best : void 0;
|
|
13271
14074
|
const v = child(input, pos, ctx);
|
|
13272
14075
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14076
|
+
if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
|
|
13273
14077
|
if (v === FAIL) {
|
|
13274
14078
|
ctx._fe = pos;
|
|
13275
14079
|
ctx._fx = xf;
|
|
@@ -13282,12 +14086,13 @@ function assemble(t2, prog, cfg) {
|
|
|
13282
14086
|
case OP_OPT: {
|
|
13283
14087
|
const child = link(code[ip + 1]);
|
|
13284
14088
|
const gate = lookaheadClass(code[ip + 1]);
|
|
14089
|
+
const childClean = CLEAN(code[ip + 1]);
|
|
13285
14090
|
return (input, pos, ctx) => {
|
|
13286
14091
|
if (gate !== null && !classHas2(gate, lead(input, pos))) {
|
|
13287
14092
|
EC.e = pos;
|
|
13288
14093
|
return null;
|
|
13289
14094
|
}
|
|
13290
|
-
const need = markCst(ctx);
|
|
14095
|
+
const need = !childClean && markCst(ctx);
|
|
13291
14096
|
const mRaw = MRAW;
|
|
13292
14097
|
const mTl = MTL;
|
|
13293
14098
|
const mLv = MLV;
|
|
@@ -13485,6 +14290,9 @@ function assemble(t2, prog, cfg) {
|
|
|
13485
14290
|
const projection = reducer < 0 ? ~reducer : -1;
|
|
13486
14291
|
const fn = fused && projection < 0 ? fns[reducer] : void 0;
|
|
13487
14292
|
const step = closureLabels.at(ip).buf ? nextTermBuffered : nextTerm;
|
|
14293
|
+
const decided = FIRST_DECIDED;
|
|
14294
|
+
FIRST_DECIDED = void 0;
|
|
14295
|
+
const linkFirst = () => decided ?? link(code[base]);
|
|
13488
14296
|
const runnerBlock = (count, r0, r1, r2, r3, next) => {
|
|
13489
14297
|
if (count === 1) return (input, cur, ctx, values, inherited) => {
|
|
13490
14298
|
cur = r0(input, cur, ctx, inherited);
|
|
@@ -13530,7 +14338,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13530
14338
|
};
|
|
13531
14339
|
};
|
|
13532
14340
|
if (REC) {
|
|
13533
|
-
const first2 =
|
|
14341
|
+
const first2 = linkFirst();
|
|
13534
14342
|
const firstSync = sentinelFor(code[base + n]);
|
|
13535
14343
|
const runnerAt = (i) => {
|
|
13536
14344
|
const sync = sentinelFor(code[base + n + i]);
|
|
@@ -13566,13 +14374,13 @@ function assemble(t2, prog, cfg) {
|
|
|
13566
14374
|
const bindRunners = (start) => {
|
|
13567
14375
|
const count = Math.min(4, n - start);
|
|
13568
14376
|
const at = (offset) => runnerAt(start + offset);
|
|
13569
|
-
const
|
|
14377
|
+
const never2 = () => -1;
|
|
13570
14378
|
return runnerBlock(
|
|
13571
14379
|
count,
|
|
13572
14380
|
at(0),
|
|
13573
|
-
count > 1 ? at(1) :
|
|
13574
|
-
count > 2 ? at(2) :
|
|
13575
|
-
count > 3 ? at(3) :
|
|
14381
|
+
count > 1 ? at(1) : never2,
|
|
14382
|
+
count > 2 ? at(2) : never2,
|
|
14383
|
+
count > 3 ? at(3) : never2,
|
|
13576
14384
|
start + count < n ? bindRunners(start + count) : void 0
|
|
13577
14385
|
);
|
|
13578
14386
|
};
|
|
@@ -13622,15 +14430,31 @@ function assemble(t2, prog, cfg) {
|
|
|
13622
14430
|
let hasAdj = false;
|
|
13623
14431
|
for (let i = 1; i < n; i++) {
|
|
13624
14432
|
const kidIp = code[base + i];
|
|
13625
|
-
if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp)) {
|
|
14433
|
+
if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp) || holdsGap(code, k, base, n, i, NULLABLE)) {
|
|
13626
14434
|
hasAdj = true;
|
|
13627
14435
|
break;
|
|
13628
14436
|
}
|
|
13629
14437
|
}
|
|
13630
14438
|
if (hasAdj) {
|
|
13631
|
-
const first2 =
|
|
14439
|
+
const first2 = linkFirst();
|
|
13632
14440
|
const runnerAt = (i) => {
|
|
13633
14441
|
const kidIp = code[base + i];
|
|
14442
|
+
if (holdsGap(code, k, base, n, i, NULLABLE)) {
|
|
14443
|
+
const kid = link(kidIp);
|
|
14444
|
+
return (input, cur, ctx) => {
|
|
14445
|
+
if (ctx.trivia === void 0) {
|
|
14446
|
+
const v2 = kid(input, cur, ctx);
|
|
14447
|
+
if (v2 === FAIL) return -1;
|
|
14448
|
+
TERMV = v2;
|
|
14449
|
+
return EC.e;
|
|
14450
|
+
}
|
|
14451
|
+
const scanEnd = skipTrivia(input, cur, ctx);
|
|
14452
|
+
const v = kid(input, scanEnd, ctx);
|
|
14453
|
+
if (v === FAIL) return -1;
|
|
14454
|
+
TERMV = v;
|
|
14455
|
+
return scanEnd;
|
|
14456
|
+
};
|
|
14457
|
+
}
|
|
13634
14458
|
if (code[kidIp] !== OP_ADJ) {
|
|
13635
14459
|
const kid = link(kidIp);
|
|
13636
14460
|
if (leadingTriviaFieldAt(code, k, kidIp)) {
|
|
@@ -13655,13 +14479,13 @@ function assemble(t2, prog, cfg) {
|
|
|
13655
14479
|
const bindRunners = (start) => {
|
|
13656
14480
|
const count = Math.min(4, n - start);
|
|
13657
14481
|
const at = (offset) => runnerAt(start + offset);
|
|
13658
|
-
const
|
|
14482
|
+
const never2 = () => -1;
|
|
13659
14483
|
return runnerBlock(
|
|
13660
14484
|
count,
|
|
13661
14485
|
at(0),
|
|
13662
|
-
count > 1 ? at(1) :
|
|
13663
|
-
count > 2 ? at(2) :
|
|
13664
|
-
count > 3 ? at(3) :
|
|
14486
|
+
count > 1 ? at(1) : never2,
|
|
14487
|
+
count > 2 ? at(2) : never2,
|
|
14488
|
+
count > 3 ? at(3) : never2,
|
|
13665
14489
|
start + count < n ? bindRunners(start + count) : void 0
|
|
13666
14490
|
);
|
|
13667
14491
|
};
|
|
@@ -13698,7 +14522,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13698
14522
|
};
|
|
13699
14523
|
}
|
|
13700
14524
|
if (n === 1) {
|
|
13701
|
-
const k0 =
|
|
14525
|
+
const k0 = linkFirst();
|
|
13702
14526
|
if (fused) {
|
|
13703
14527
|
return (input, pos, ctx) => {
|
|
13704
14528
|
const v = k0(input, pos, ctx);
|
|
@@ -13720,7 +14544,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13720
14544
|
};
|
|
13721
14545
|
}
|
|
13722
14546
|
if (n === 2) {
|
|
13723
|
-
const k0 =
|
|
14547
|
+
const k0 = linkFirst(), k1 = link(code[base + 1]);
|
|
13724
14548
|
if (fused) {
|
|
13725
14549
|
return (input, pos, ctx) => {
|
|
13726
14550
|
const v0 = k0(input, pos, ctx);
|
|
@@ -13751,7 +14575,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13751
14575
|
};
|
|
13752
14576
|
}
|
|
13753
14577
|
if (n === 3) {
|
|
13754
|
-
const k0 =
|
|
14578
|
+
const k0 = linkFirst(), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
|
|
13755
14579
|
if (fused) {
|
|
13756
14580
|
return (input, pos, ctx) => {
|
|
13757
14581
|
const v0 = k0(input, pos, ctx);
|
|
@@ -13845,7 +14669,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13845
14669
|
start + count < n ? bind(start + count) : void 0
|
|
13846
14670
|
);
|
|
13847
14671
|
};
|
|
13848
|
-
const first =
|
|
14672
|
+
const first = linkFirst();
|
|
13849
14673
|
const tail = bind(1);
|
|
13850
14674
|
const runDirectTerms = (input, pos, ctx, values) => {
|
|
13851
14675
|
const v0 = first(input, pos, ctx);
|
|
@@ -13884,6 +14708,8 @@ function assemble(t2, prog, cfg) {
|
|
|
13884
14708
|
const n = code[ip + 2];
|
|
13885
14709
|
const choiceFx = fx[code[ip + 3]];
|
|
13886
14710
|
const base = ip + 4;
|
|
14711
|
+
for (let i = 0; i < n; i++) link(code[base + i]);
|
|
14712
|
+
const armsClean = CLEAN(ip);
|
|
13887
14713
|
if (table.exclusive) {
|
|
13888
14714
|
const ascii = table.ascii;
|
|
13889
14715
|
const hi = table.hi;
|
|
@@ -14023,7 +14849,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14023
14849
|
if (n === 3) addGate(g2, 4);
|
|
14024
14850
|
return (input, pos, ctx) => {
|
|
14025
14851
|
const c = lead(input, pos);
|
|
14026
|
-
const need = markCst(ctx);
|
|
14852
|
+
const need = !armsClean && markCst(ctx);
|
|
14027
14853
|
const mRaw = MRAW;
|
|
14028
14854
|
const mTl = MTL;
|
|
14029
14855
|
const mLv = MLV;
|
|
@@ -14240,7 +15066,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14240
15066
|
if (pn !== 0) {
|
|
14241
15067
|
return (input, pos, ctx) => {
|
|
14242
15068
|
const c = lead(input, pos);
|
|
14243
|
-
const need = markCst(ctx);
|
|
15069
|
+
const need = !armsClean && markCst(ctx);
|
|
14244
15070
|
const mRaw = MRAW;
|
|
14245
15071
|
const mTl = MTL;
|
|
14246
15072
|
const mLv = MLV;
|
|
@@ -14297,7 +15123,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14297
15123
|
}
|
|
14298
15124
|
return (input, pos, ctx) => {
|
|
14299
15125
|
const c = lead(input, pos);
|
|
14300
|
-
const need = markCst(ctx);
|
|
15126
|
+
const need = !armsClean && markCst(ctx);
|
|
14301
15127
|
const mRaw = MRAW;
|
|
14302
15128
|
const mTl = MTL;
|
|
14303
15129
|
const mLv = MLV;
|
|
@@ -14345,7 +15171,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14345
15171
|
}
|
|
14346
15172
|
return (input, pos, ctx) => {
|
|
14347
15173
|
const c = lead(input, pos);
|
|
14348
|
-
const need = markCst(ctx);
|
|
15174
|
+
const need = !armsClean && markCst(ctx);
|
|
14349
15175
|
const mRaw = MRAW;
|
|
14350
15176
|
const mTl = MTL;
|
|
14351
15177
|
const mLv = MLV;
|
|
@@ -14399,6 +15225,21 @@ function assemble(t2, prog, cfg) {
|
|
|
14399
15225
|
return lit(input, pos, ctx);
|
|
14400
15226
|
};
|
|
14401
15227
|
}
|
|
15228
|
+
case OP_RGATE: {
|
|
15229
|
+
const cls = cc[code[ip + 1]];
|
|
15230
|
+
const xf = fx[code[ip + 3]];
|
|
15231
|
+
const child = link(code[ip + 2]);
|
|
15232
|
+
if (cfg.tolerant || cfg.probe) return child;
|
|
15233
|
+
return (input, pos, ctx) => {
|
|
15234
|
+
const item = ctx._routed;
|
|
15235
|
+
if (item !== void 0 && item.span.start === pos && !classHas2(cls, lead(input, item.span.end))) {
|
|
15236
|
+
ctx._fe = item.span.end;
|
|
15237
|
+
ctx._fx = xf;
|
|
15238
|
+
return FAIL;
|
|
15239
|
+
}
|
|
15240
|
+
return child(input, pos, ctx);
|
|
15241
|
+
};
|
|
15242
|
+
}
|
|
14402
15243
|
case OP_ARMGATE: {
|
|
14403
15244
|
const pred = fns[code[ip + 1]];
|
|
14404
15245
|
const child = link(code[ip + 2]);
|
|
@@ -14467,6 +15308,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14467
15308
|
const itemClass = !REC && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
|
|
14468
15309
|
const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
|
|
14469
15310
|
const skipBeforeFirst = sepIp < 0 && min === 0;
|
|
15311
|
+
const itemClean = sepIp < 0 && CLEAN(code[ip + 1]) && !rowNullable(code, k, code[ip + 1], NULLABLE);
|
|
14470
15312
|
if (REC) {
|
|
14471
15313
|
const itemFx2 = fx[code[ip + 6]];
|
|
14472
15314
|
const sepSent = sentinelFor(code[ip + 7]);
|
|
@@ -14563,6 +15405,8 @@ function assemble(t2, prog, cfg) {
|
|
|
14563
15405
|
const out = collect ? [] : void 0;
|
|
14564
15406
|
const hasTrivia = ctx.trivia !== void 0;
|
|
14565
15407
|
const needMark = rollbackNeeded(ctx);
|
|
15408
|
+
const markLater = needMark && (!itemClean || hasTrivia);
|
|
15409
|
+
const markFirst = needMark && (!itemClean || hasTrivia && skipBeforeFirst);
|
|
14566
15410
|
const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
|
|
14567
15411
|
let cur = pos;
|
|
14568
15412
|
let count = 0;
|
|
@@ -14570,14 +15414,15 @@ function assemble(t2, prog, cfg) {
|
|
|
14570
15414
|
if (max >= 0 && count >= max) break;
|
|
14571
15415
|
if (sep !== void 0 && count > 0 && count >= min && cur >= input.length) break;
|
|
14572
15416
|
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
|
|
15417
|
+
const markIt = count > 0 ? markLater : markFirst;
|
|
15418
|
+
if (markIt) markCst(ctx);
|
|
15419
|
+
const mRaw = markIt ? MRAW : 0;
|
|
15420
|
+
const mTl = markIt ? MTL : 0;
|
|
15421
|
+
const mLv = markIt ? MLV : 0;
|
|
15422
|
+
const mFl = markIt ? ctx._fields?.length ?? 0 : 0;
|
|
15423
|
+
const mEr = markIt ? ctx._errors?.length ?? 0 : 0;
|
|
15424
|
+
const mLog = markIt ? ctx._triviaLog?.length ?? 0 : 0;
|
|
15425
|
+
const mRoot = markIt ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14581
15426
|
let itemStart = cur;
|
|
14582
15427
|
let sepEnd = -1;
|
|
14583
15428
|
const viaRepItem = sep === void 0 && count >= min && (count > 0 || skipBeforeFirst);
|
|
@@ -14589,7 +15434,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14589
15434
|
if (sepLeads) LEAD.at = cur;
|
|
14590
15435
|
const sv = sep(input, sp, ctx);
|
|
14591
15436
|
if (sv === FAIL) {
|
|
14592
|
-
if (
|
|
15437
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14593
15438
|
if (committed3(ctx)) return FAIL;
|
|
14594
15439
|
break;
|
|
14595
15440
|
}
|
|
@@ -14600,25 +15445,25 @@ function assemble(t2, prog, cfg) {
|
|
|
14600
15445
|
itemStart = skipTrivia(input, itemStart, ctx);
|
|
14601
15446
|
}
|
|
14602
15447
|
if (itemStart >= input.length && viaRepItem) {
|
|
14603
|
-
if (
|
|
15448
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14604
15449
|
if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
|
|
14605
15450
|
break;
|
|
14606
15451
|
}
|
|
14607
15452
|
if (count >= min && gateItems && !itemMayStart(input, itemStart)) {
|
|
14608
|
-
if (
|
|
15453
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14609
15454
|
if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
|
|
14610
15455
|
break;
|
|
14611
15456
|
}
|
|
14612
15457
|
ctx._fc = false;
|
|
14613
15458
|
const v = child(input, itemStart, ctx);
|
|
14614
15459
|
if (v === FAIL) {
|
|
14615
|
-
if (
|
|
15460
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14616
15461
|
if (committed3(ctx)) return FAIL;
|
|
14617
15462
|
if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
|
|
14618
15463
|
break;
|
|
14619
15464
|
}
|
|
14620
15465
|
if (EC.e === itemStart && viaRepItem) {
|
|
14621
|
-
if (
|
|
15466
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14622
15467
|
break;
|
|
14623
15468
|
}
|
|
14624
15469
|
if (out !== void 0) out.push(v);
|
|
@@ -14692,7 +15537,14 @@ function assemble(t2, prog, cfg) {
|
|
|
14692
15537
|
const runArm = n === 0 ? void 0 : bindArms(0);
|
|
14693
15538
|
const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted);
|
|
14694
15539
|
return (input, pos, ctx) => {
|
|
14695
|
-
const
|
|
15540
|
+
const need = markCst(ctx);
|
|
15541
|
+
const mRaw = MRAW;
|
|
15542
|
+
const mTl = MTL;
|
|
15543
|
+
const mLv = MLV;
|
|
15544
|
+
const mFl = need ? ctx._fields?.length ?? 0 : 0;
|
|
15545
|
+
const mEr = need ? ctx._errors?.length ?? 0 : 0;
|
|
15546
|
+
const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
15547
|
+
const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14696
15548
|
const selVal = selector(input, pos, ctx);
|
|
14697
15549
|
if (selVal === FAIL) return FAIL;
|
|
14698
15550
|
const selEnd = EC.e;
|
|
@@ -14704,9 +15556,9 @@ function assemble(t2, prog, cfg) {
|
|
|
14704
15556
|
ctx._fx = expected;
|
|
14705
15557
|
return FAIL;
|
|
14706
15558
|
}
|
|
14707
|
-
return runOther(input, pos, selEnd, key,
|
|
15559
|
+
return runOther(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14708
15560
|
}
|
|
14709
|
-
return runArm(arm, input, pos, selEnd, key,
|
|
15561
|
+
return runArm(arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14710
15562
|
};
|
|
14711
15563
|
}
|
|
14712
15564
|
/* ── node ────────────────────────────────────────────────────────────── */
|
|
@@ -14742,7 +15594,8 @@ function assemble(t2, prog, cfg) {
|
|
|
14742
15594
|
return nd;
|
|
14743
15595
|
};
|
|
14744
15596
|
}
|
|
14745
|
-
const child = link(code[ip + 2]);
|
|
15597
|
+
const child = NODE_BODY ?? link(code[ip + 2]);
|
|
15598
|
+
NODE_BODY = void 0;
|
|
14746
15599
|
const proj = code[ip + 4];
|
|
14747
15600
|
const buildIdx = code[ip + 1];
|
|
14748
15601
|
const type = k[code[ip + 5]];
|
|
@@ -14766,6 +15619,30 @@ function assemble(t2, prog, cfg) {
|
|
|
14766
15619
|
if (build !== void 0 && proj < 0 && flags === 18) {
|
|
14767
15620
|
return childrenOnlyFieldsBuildNode(child, build);
|
|
14768
15621
|
}
|
|
15622
|
+
if (build !== void 0 && passCollapse(code, ip, hostCst)) {
|
|
15623
|
+
return passCollapseNode(child, build, flags === 32);
|
|
15624
|
+
}
|
|
15625
|
+
const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
|
|
15626
|
+
const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(closureLabels.at(code[ip + 2]).tri, trivia2);
|
|
15627
|
+
if (build !== void 0 && gated !== void 0 && triviaLead !== void 0) {
|
|
15628
|
+
const classic = flags === 32 ? collapseBuildNode(child, build) : childrenOnlyCollapseBuildNode(child, build);
|
|
15629
|
+
return gatedPassCollapseNode(
|
|
15630
|
+
[
|
|
15631
|
+
...gated.leads.map((g) => cc[code[g + 1]]),
|
|
15632
|
+
resolveClass(encodeClassSpec([
|
|
15633
|
+
...triviaLead,
|
|
15634
|
+
...gated.lits.map((i) => {
|
|
15635
|
+
const c = k[i].codePointAt(0);
|
|
15636
|
+
return { lo: c, hi: c };
|
|
15637
|
+
})
|
|
15638
|
+
]))
|
|
15639
|
+
],
|
|
15640
|
+
link(gated.last),
|
|
15641
|
+
classic,
|
|
15642
|
+
build,
|
|
15643
|
+
flags === 32
|
|
15644
|
+
);
|
|
15645
|
+
}
|
|
14769
15646
|
if (build !== void 0 && proj < 0 && flags === 32) {
|
|
14770
15647
|
return collapseBuildNode(child, build);
|
|
14771
15648
|
}
|
|
@@ -14914,6 +15791,8 @@ function assemble(t2, prog, cfg) {
|
|
|
14914
15791
|
}
|
|
14915
15792
|
const notChild = scalarTerminalNotChild(code, ip);
|
|
14916
15793
|
if (notChild >= 0) scalarFor(notChild);
|
|
15794
|
+
const peekChild = scalarTerminalPeekChild(code, ip);
|
|
15795
|
+
if (peekChild >= 0) scalarFor(peekChild);
|
|
14917
15796
|
}
|
|
14918
15797
|
const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
|
|
14919
15798
|
if (pre !== void 0) {
|
|
@@ -14973,7 +15852,8 @@ function assemble(t2, prog, cfg) {
|
|
|
14973
15852
|
t2.lexPrograms,
|
|
14974
15853
|
LEAD,
|
|
14975
15854
|
triviaFieldCapture,
|
|
14976
|
-
skipDeferredTrivia
|
|
15855
|
+
skipDeferredTrivia,
|
|
15856
|
+
collapseEmpty
|
|
14977
15857
|
);
|
|
14978
15858
|
emitReached = new Set(pre.reached);
|
|
14979
15859
|
if (emitted.ext !== void 0) HYBRID = emitted;
|
|
@@ -15059,7 +15939,8 @@ function assemble(t2, prog, cfg) {
|
|
|
15059
15939
|
t2.lexPrograms,
|
|
15060
15940
|
LEAD,
|
|
15061
15941
|
triviaFieldCapture,
|
|
15062
|
-
skipDeferredTrivia
|
|
15942
|
+
skipDeferredTrivia,
|
|
15943
|
+
collapseEmpty
|
|
15063
15944
|
);
|
|
15064
15945
|
emitReached = em.reached;
|
|
15065
15946
|
} catch (e) {
|
|
@@ -15326,7 +16207,7 @@ function emitClassPool(classes) {
|
|
|
15326
16207
|
if (classes.length < 2) return array;
|
|
15327
16208
|
const delimiter = "|/~?^`".split("").find((ch2) => classes.every((spec) => !spec.includes(ch2)));
|
|
15328
16209
|
if (delimiter === void 0) return array;
|
|
15329
|
-
const split =
|
|
16210
|
+
const split = `/* @__PURE__ */ ${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
|
|
15330
16211
|
return split.length < array.length ? split : array;
|
|
15331
16212
|
}
|
|
15332
16213
|
function emitConst(v) {
|
|
@@ -17185,16 +18066,16 @@ function ownSource(fn) {
|
|
|
17185
18066
|
return typeof name === "string" && name.length > 0 && globalThis[name] === fn ? name : null;
|
|
17186
18067
|
}
|
|
17187
18068
|
function compile(target, second, third) {
|
|
17188
|
-
if (!
|
|
18069
|
+
if (!isCombinator2(target)) return compileMap(target, second);
|
|
17189
18070
|
return compileRoot(target, second, third);
|
|
17190
18071
|
}
|
|
17191
|
-
function
|
|
18072
|
+
function isCombinator2(x) {
|
|
17192
18073
|
return typeof x === "object" && x !== null && typeof x.parse === "function" && "_def" in x;
|
|
17193
18074
|
}
|
|
17194
18075
|
function compileMap(grammar, opts = {}) {
|
|
17195
18076
|
const entries = [];
|
|
17196
18077
|
for (const [key, value] of Object.entries(grammar)) {
|
|
17197
|
-
if (!
|
|
18078
|
+
if (!isCombinator2(value)) throw new TypeError(`compile: grammar entry "${key}" is not a parser`);
|
|
17198
18079
|
if (value._def.tag === "lazy") {
|
|
17199
18080
|
try {
|
|
17200
18081
|
value._def.thunk();
|
|
@@ -17508,49 +18389,6 @@ function digestValue(value, prefix = "", options) {
|
|
|
17508
18389
|
return sha.digest("hex");
|
|
17509
18390
|
}
|
|
17510
18391
|
|
|
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
18392
|
// src/combinators/not.ts
|
|
17555
18393
|
function not(combinator) {
|
|
17556
18394
|
const meta = {
|