parseman 0.57.0 → 0.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analysis/diagnostics.js +1799 -962
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/cli/index.js +1928 -1091
- package/dist/cli/index.js.map +3 -3
- package/dist/combinators/dispatch.d.ts.map +1 -1
- package/dist/compiler/token-alphabet.d.ts +11 -1
- package/dist/compiler/token-alphabet.d.ts.map +1 -1
- package/dist/compiler/token-capability.js +69 -16
- package/dist/compiler/token-capability.js.map +2 -2
- package/dist/cst/capture-buffer.d.ts +6 -0
- package/dist/cst/capture-buffer.d.ts.map +1 -1
- package/dist/index.js +1016 -177
- package/dist/index.js.map +3 -3
- package/dist/plugin/index.d.ts +25 -1
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +1209 -236
- package/dist/plugin/index.js.map +3 -3
- package/dist/table/assemble.d.ts.map +1 -1
- package/dist/table/compile-rule-map.d.ts.map +1 -1
- package/dist/table/emit-assembly.d.ts +1 -1
- package/dist/table/emit-assembly.d.ts.map +1 -1
- package/dist/table/emit.d.ts.map +1 -1
- package/dist/table/encode.d.ts.map +1 -1
- package/dist/table/exec.d.ts.map +1 -1
- package/dist/table/factor-choice.d.ts +42 -0
- package/dist/table/factor-choice.d.ts.map +1 -0
- package/dist/table/fail-clean.d.ts +3 -0
- package/dist/table/fail-clean.d.ts.map +1 -0
- package/dist/table/hold-gap.d.ts +8 -0
- package/dist/table/hold-gap.d.ts.map +1 -0
- package/dist/table/index.js +1369 -259
- package/dist/table/index.js.map +3 -3
- package/dist/table/lex-program.d.ts +7 -3
- package/dist/table/lex-program.d.ts.map +1 -1
- package/dist/table/ops.d.ts +8 -0
- package/dist/table/ops.d.ts.map +1 -1
- package/dist/table/run-support.d.ts +19 -0
- package/dist/table/run-support.d.ts.map +1 -1
- package/dist/table/scalar-terminal.d.ts +2 -0
- package/dist/table/scalar-terminal.d.ts.map +1 -1
- package/dist/table/site-labels.d.ts +66 -0
- package/dist/table/site-labels.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/combinators/dispatch.ts +12 -3
- package/src/compiler/token-alphabet.ts +57 -17
- package/src/cst/capture-buffer.ts +25 -0
- package/src/plugin/index.ts +230 -35
- package/src/table/assemble.ts +252 -62
- package/src/table/child-slots.ts +2 -2
- package/src/table/compile-rule-map.ts +14 -5
- package/src/table/emit-assembly.ts +112 -23
- package/src/table/emit.ts +3 -1
- package/src/table/encode.ts +80 -14
- package/src/table/exec.ts +27 -8
- package/src/table/factor-choice.ts +173 -0
- package/src/table/fail-clean.ts +130 -0
- package/src/table/hold-gap.ts +68 -0
- package/src/table/lex-program.ts +197 -43
- package/src/table/ops.ts +9 -1
- package/src/table/run-support.ts +35 -0
- package/src/table/scalar-terminal.ts +8 -0
- package/src/table/site-labels.ts +135 -4
- package/src/version.ts +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -819,6 +819,31 @@ function pushCstChild(ctx, built, rawEntry2) {
|
|
|
819
819
|
else if (ctx._cstLeaves) ctx._cstLeaves.push(built);
|
|
820
820
|
if (ctx._cstRawChildren) ctx._cstRawChildren.push(rawEntry2);
|
|
821
821
|
}
|
|
822
|
+
function popCstChild(ctx) {
|
|
823
|
+
const b = ctx._cstBuf;
|
|
824
|
+
if (b) {
|
|
825
|
+
const ch2 = b.ch;
|
|
826
|
+
if (b.rawOnly !== true && ch2) {
|
|
827
|
+
ch2.pop();
|
|
828
|
+
if (ch2.length === 1) {
|
|
829
|
+
b.single = ch2[0];
|
|
830
|
+
b.ch = void 0;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
if (b.noRaw === true) b.rawLen = (b.rawLen ?? 1) - 1;
|
|
834
|
+
else if (b.raw) {
|
|
835
|
+
b.raw.pop();
|
|
836
|
+
if (b.raw.length === 1) {
|
|
837
|
+
b.rawSingle = b.raw[0];
|
|
838
|
+
b.raw = void 0;
|
|
839
|
+
}
|
|
840
|
+
} else b.rawSingle = void 0;
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
843
|
+
if (ctx._cstChildren) ctx._cstChildren.pop();
|
|
844
|
+
else if (ctx._cstLeaves) ctx._cstLeaves.pop();
|
|
845
|
+
if (ctx._cstRawChildren) ctx._cstRawChildren.pop();
|
|
846
|
+
}
|
|
822
847
|
function cstRawLen(ctx) {
|
|
823
848
|
const b = ctx._cstBuf;
|
|
824
849
|
if (b) {
|
|
@@ -2395,10 +2420,16 @@ function branchUsesRouted(branch) {
|
|
|
2395
2420
|
return branch.usesRouted === true || parserUsesRouted(branch.parser);
|
|
2396
2421
|
}
|
|
2397
2422
|
function asciiFoldKey(key) {
|
|
2398
|
-
let
|
|
2399
|
-
for (
|
|
2423
|
+
let i = 0;
|
|
2424
|
+
for (; i < key.length; i++) {
|
|
2425
|
+
const c = key.charCodeAt(i);
|
|
2426
|
+
if (c >= 65 && c <= 90) break;
|
|
2427
|
+
}
|
|
2428
|
+
if (i === key.length) return key;
|
|
2429
|
+
let out = key.slice(0, i);
|
|
2430
|
+
for (; i < key.length; i++) {
|
|
2400
2431
|
const c = key.charCodeAt(i);
|
|
2401
|
-
out +=
|
|
2432
|
+
out += c >= 65 && c <= 90 ? String.fromCharCode(c + 32) : key[i];
|
|
2402
2433
|
}
|
|
2403
2434
|
return out;
|
|
2404
2435
|
}
|
|
@@ -2727,6 +2758,42 @@ function keywords(words, opts = {}) {
|
|
|
2727
2758
|
};
|
|
2728
2759
|
}
|
|
2729
2760
|
|
|
2761
|
+
// src/combinators/trivia-boundary.ts
|
|
2762
|
+
var MAX_DEPTH = 12;
|
|
2763
|
+
function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
|
|
2764
|
+
if (depth === 0) return true;
|
|
2765
|
+
const d = p._def;
|
|
2766
|
+
switch (d.tag) {
|
|
2767
|
+
// Multi-term forms: the gaps BETWEEN terms are the ambient-trivia positions.
|
|
2768
|
+
case "sequence":
|
|
2769
|
+
return d.parsers.length > 1;
|
|
2770
|
+
case "many":
|
|
2771
|
+
case "oneOrMore":
|
|
2772
|
+
case "sepBy":
|
|
2773
|
+
return true;
|
|
2774
|
+
// Transparent wrappers — they add no position, so ask what they wrap.
|
|
2775
|
+
case "node":
|
|
2776
|
+
case "transform":
|
|
2777
|
+
case "leaf":
|
|
2778
|
+
case "label":
|
|
2779
|
+
case "field":
|
|
2780
|
+
case "token":
|
|
2781
|
+
case "attempt":
|
|
2782
|
+
case "optional":
|
|
2783
|
+
case "expect":
|
|
2784
|
+
case "withCtx":
|
|
2785
|
+
case "recover":
|
|
2786
|
+
case "trivia":
|
|
2787
|
+
return hasOwnTriviaBoundary(d.parser, depth - 1);
|
|
2788
|
+
// An alternation adds no position either, but ONE arm that has one is enough
|
|
2789
|
+
// to make the scope meaningful for this rule.
|
|
2790
|
+
case "choice":
|
|
2791
|
+
return d.parsers.some((a) => hasOwnTriviaBoundary(a, depth - 1));
|
|
2792
|
+
default:
|
|
2793
|
+
return false;
|
|
2794
|
+
}
|
|
2795
|
+
}
|
|
2796
|
+
|
|
2730
2797
|
// src/compiler/token-alphabet.ts
|
|
2731
2798
|
function optionalSuffixLexBody(ir) {
|
|
2732
2799
|
if (ir.kind !== "sequence" || ir.parts.length !== 2) return void 0;
|
|
@@ -2746,7 +2813,10 @@ function selectOptionalSuffixLexBody(ir) {
|
|
|
2746
2813
|
const token2 = { strategy: "token", estimatedOps: 2, body };
|
|
2747
2814
|
return token2.estimatedOps < character.estimatedOps ? token2 : character;
|
|
2748
2815
|
}
|
|
2749
|
-
function
|
|
2816
|
+
function reinstallsRuleTrivia(reference, target) {
|
|
2817
|
+
return (reference._meta.grammarTrivia ?? target._meta.grammarTrivia) !== void 0 && hasOwnTriviaBoundary(target);
|
|
2818
|
+
}
|
|
2819
|
+
function directTokenBodyParser(parser2, resolve2, scope) {
|
|
2750
2820
|
const outer = parser2._def;
|
|
2751
2821
|
if (outer.tag !== "token") return void 0;
|
|
2752
2822
|
let body = outer.parser;
|
|
@@ -2756,12 +2826,13 @@ function directTokenBodyParser(parser2, resolve2) {
|
|
|
2756
2826
|
const wrapper = body._def;
|
|
2757
2827
|
if (wrapper.tag === "grammar") {
|
|
2758
2828
|
if (wrapper.clearTrivia !== true || wrapper.triviaParser !== void 0 || wrapper.captureTrivia === true || wrapper.rootCapture === "opaque" || wrapper.constructionTrackLines !== "inherit" || wrapper.constructionCaptureTriviaKinds !== void 0) return void 0;
|
|
2829
|
+
if (scope !== void 0) scope.cleared = true;
|
|
2759
2830
|
body = wrapper.parser;
|
|
2760
2831
|
continue;
|
|
2761
2832
|
}
|
|
2762
2833
|
if (wrapper.tag === "lazy") {
|
|
2763
2834
|
const target = resolvedLazyTarget(body, resolve2);
|
|
2764
|
-
if (target === void 0) return void 0;
|
|
2835
|
+
if (target === void 0 || reinstallsRuleTrivia(body, target)) return void 0;
|
|
2765
2836
|
body = target;
|
|
2766
2837
|
continue;
|
|
2767
2838
|
}
|
|
@@ -2933,7 +3004,7 @@ function directNot2TokenBody(parser2, resolve2) {
|
|
|
2933
3004
|
terminal
|
|
2934
3005
|
};
|
|
2935
3006
|
}
|
|
2936
|
-
function directFixedLexNode(parser2, resolve2, active, pureOnly = false) {
|
|
3007
|
+
function directFixedLexNode(parser2, resolve2, active, pureOnly = false, cleared = false) {
|
|
2937
3008
|
let current = parser2;
|
|
2938
3009
|
const wrappers = /* @__PURE__ */ new Set();
|
|
2939
3010
|
while (!wrappers.has(current)) {
|
|
@@ -2941,7 +3012,7 @@ function directFixedLexNode(parser2, resolve2, active, pureOnly = false) {
|
|
|
2941
3012
|
const def = current._def;
|
|
2942
3013
|
if (def.tag === "lazy") {
|
|
2943
3014
|
const target = resolvedLazyTarget(current, resolve2);
|
|
2944
|
-
if (target === void 0) return void 0;
|
|
3015
|
+
if (target === void 0 || reinstallsRuleTrivia(current, target)) return void 0;
|
|
2945
3016
|
current = target;
|
|
2946
3017
|
continue;
|
|
2947
3018
|
}
|
|
@@ -2959,30 +3030,33 @@ function directFixedLexNode(parser2, resolve2, active, pureOnly = false) {
|
|
|
2959
3030
|
if (terminal !== void 0) return { kind: "terminal", terminal };
|
|
2960
3031
|
const def = current._def;
|
|
2961
3032
|
if (def.tag === "grammar") {
|
|
3033
|
+
if (def.triviaParser === void 0 && def.captureTrivia !== true && def.rootCapture !== "opaque" && def.constructionCaptureTriviaKinds === void 0) {
|
|
3034
|
+
return directFixedLexNode(def.parser, resolve2, active, pureOnly, cleared || def.clearTrivia === true);
|
|
3035
|
+
}
|
|
2962
3036
|
if (!pureOnly || def.parser._def.tag !== "token" && (def.clearTrivia !== true || def.triviaParser !== void 0 || def.captureTrivia === true || def.rootCapture === "opaque")) return void 0;
|
|
2963
|
-
return directFixedLexNode(def.parser, resolve2, active, true);
|
|
3037
|
+
return directFixedLexNode(def.parser, resolve2, active, true, cleared);
|
|
2964
3038
|
}
|
|
2965
3039
|
if (def.tag === "sequence") {
|
|
2966
3040
|
if (def.parsers.length < 2 || def.parsers.length > 5) return void 0;
|
|
2967
|
-
const parts = def.parsers.map((part) => directFixedLexNode(part, resolve2, active, pureOnly));
|
|
3041
|
+
const parts = def.parsers.map((part) => directFixedLexNode(part, resolve2, active, pureOnly, cleared));
|
|
2968
3042
|
if (parts.some((part) => part === void 0)) return void 0;
|
|
2969
3043
|
return { kind: "sequence", parts };
|
|
2970
3044
|
}
|
|
2971
3045
|
if (def.tag === "choice") {
|
|
2972
|
-
if (def.parsers.length
|
|
2973
|
-
const arms = def.parsers.map((arm) => directFixedLexNode(arm, resolve2, active, pureOnly));
|
|
3046
|
+
if (def.parsers.length < 2 || def.strategy.tag !== "firstMatch" || def.gates.some((gate) => gate !== null) || def.autoNot.some((check) => check !== null)) return void 0;
|
|
3047
|
+
const arms = def.parsers.map((arm) => directFixedLexNode(arm, resolve2, active, pureOnly, cleared));
|
|
2974
3048
|
if (arms.some((arm) => arm === void 0)) return void 0;
|
|
2975
|
-
const final = classifyFinalChoice(def.parsers, resolve2);
|
|
2976
3049
|
return {
|
|
2977
3050
|
kind: "choice",
|
|
2978
3051
|
arms,
|
|
2979
|
-
|
|
3052
|
+
parsers: def.parsers,
|
|
3053
|
+
cleared,
|
|
2980
3054
|
armExpected: def.parsers.map(deriveExpected),
|
|
2981
3055
|
expected: def.parsers.flatMap(deriveExpected)
|
|
2982
3056
|
};
|
|
2983
3057
|
}
|
|
2984
3058
|
if (def.tag === "not") {
|
|
2985
|
-
const body = directFixedLexNode(def.parser, resolve2, active, true);
|
|
3059
|
+
const body = directFixedLexNode(def.parser, resolve2, active, true, cleared);
|
|
2986
3060
|
return body === void 0 ? void 0 : {
|
|
2987
3061
|
kind: "not",
|
|
2988
3062
|
body,
|
|
@@ -2990,18 +3064,28 @@ function directFixedLexNode(parser2, resolve2, active, pureOnly = false) {
|
|
|
2990
3064
|
};
|
|
2991
3065
|
}
|
|
2992
3066
|
if (def.tag === "optional") {
|
|
2993
|
-
const body = directFixedLexNode(def.parser, resolve2, active, pureOnly);
|
|
3067
|
+
const body = directFixedLexNode(def.parser, resolve2, active, pureOnly, cleared);
|
|
2994
3068
|
return body === void 0 ? void 0 : { kind: "optional", body };
|
|
2995
3069
|
}
|
|
3070
|
+
if (def.tag === "many" || def.tag === "oneOrMore") {
|
|
3071
|
+
const body = directFixedLexNode(def.parser, resolve2, active, pureOnly, cleared);
|
|
3072
|
+
return body === void 0 ? void 0 : {
|
|
3073
|
+
kind: "repeat",
|
|
3074
|
+
body,
|
|
3075
|
+
min: def.tag === "many" ? 0 : def.min,
|
|
3076
|
+
max: def.max ?? -1
|
|
3077
|
+
};
|
|
3078
|
+
}
|
|
2996
3079
|
return void 0;
|
|
2997
3080
|
} finally {
|
|
2998
3081
|
active.delete(current);
|
|
2999
3082
|
}
|
|
3000
3083
|
}
|
|
3001
3084
|
function directFixedTokenBody(parser2, resolve2) {
|
|
3002
|
-
const
|
|
3085
|
+
const scope = { cleared: false };
|
|
3086
|
+
const body = directTokenBodyParser(parser2, resolve2, scope);
|
|
3003
3087
|
if (body === void 0) return void 0;
|
|
3004
|
-
const root = directFixedLexNode(body, resolve2, /* @__PURE__ */ new Set());
|
|
3088
|
+
const root = directFixedLexNode(body, resolve2, /* @__PURE__ */ new Set(), false, scope.cleared);
|
|
3005
3089
|
return root === void 0 ? void 0 : { kind: "fixed-tree", root };
|
|
3006
3090
|
}
|
|
3007
3091
|
function directBalancedTokenBody(parser2, resolve2) {
|
|
@@ -4910,17 +4994,59 @@ function buildLexBodyRecognizer(spec, constants) {
|
|
|
4910
4994
|
};
|
|
4911
4995
|
}
|
|
4912
4996
|
|
|
4997
|
+
// src/table/run-support.ts
|
|
4998
|
+
function lineCol(ctx, offset) {
|
|
4999
|
+
const starts = ctx._lineStarts ?? [0];
|
|
5000
|
+
let lo = 0, hi = starts.length - 1;
|
|
5001
|
+
while (lo < hi) {
|
|
5002
|
+
const mid = lo + hi + 1 >> 1;
|
|
5003
|
+
if (starts[mid] <= offset) lo = mid;
|
|
5004
|
+
else hi = mid - 1;
|
|
5005
|
+
}
|
|
5006
|
+
return [lo + 1, offset - starts[lo] + 1];
|
|
5007
|
+
}
|
|
5008
|
+
function spanLines(ctx, start, end) {
|
|
5009
|
+
const s = lineCol(ctx, start), e = lineCol(ctx, end);
|
|
5010
|
+
return { start, end, startLine: s[0], startColumn: s[1], endLine: e[0], endColumn: e[1] };
|
|
5011
|
+
}
|
|
5012
|
+
function rawEntry(v, input, s, e) {
|
|
5013
|
+
if (typeof v === "object" && v !== null) {
|
|
5014
|
+
const tg = v._tag;
|
|
5015
|
+
if (tg === "node" || tg === "leaf" || tg === "parseError") return v;
|
|
5016
|
+
}
|
|
5017
|
+
return {
|
|
5018
|
+
_tag: "leaf",
|
|
5019
|
+
value: typeof v === "string" ? v : typeof v === "object" && v !== null ? input.slice(s, e) : "",
|
|
5020
|
+
span: { start: s, end: e }
|
|
5021
|
+
};
|
|
5022
|
+
}
|
|
5023
|
+
function lead(input, pos) {
|
|
5024
|
+
if (pos >= input.length) return -1;
|
|
5025
|
+
const c = input.charCodeAt(pos);
|
|
5026
|
+
if (c < 55296 || c > 56319) return c;
|
|
5027
|
+
return input.codePointAt(pos) ?? c;
|
|
5028
|
+
}
|
|
5029
|
+
var EMPTY_KIDS = Object.freeze([]);
|
|
5030
|
+
var EMPTY_TRIVIA = Object.freeze([]);
|
|
5031
|
+
function collapseEmpty(ctx, build, input, pos, end, readsRaw) {
|
|
5032
|
+
const collected = ctx._cstBuf !== void 0 || ctx._cstChildren !== void 0;
|
|
5033
|
+
if (collected) popCstChild(ctx);
|
|
5034
|
+
const raw = readsRaw ? [rawEntry(void 0, input, pos, end)] : EMPTY_KIDS;
|
|
5035
|
+
const nd = build(EMPTY_KIDS, void 0, { start: pos, end }, raw, EMPTY_TRIVIA, void 0);
|
|
5036
|
+
if (collected) pushCstChild(ctx, nd, ctx._cstBuf?.noRaw === true ? void 0 : rawEntry(nd, input, pos, end));
|
|
5037
|
+
return nd;
|
|
5038
|
+
}
|
|
5039
|
+
|
|
4913
5040
|
// src/table/lex-program.ts
|
|
4914
5041
|
var LEX_NODE_TERMINAL = 0;
|
|
4915
5042
|
var LEX_NODE_SEQUENCE2 = 1;
|
|
4916
5043
|
var LEX_NODE_SEQUENCE3 = 2;
|
|
4917
5044
|
var LEX_NODE_SEQUENCE4 = 3;
|
|
4918
5045
|
var LEX_NODE_SEQUENCE5 = 4;
|
|
4919
|
-
var
|
|
4920
|
-
var LEX_NODE_CHOICE4 = 6;
|
|
4921
|
-
var LEX_NODE_CHOICE8 = 7;
|
|
5046
|
+
var LEX_NODE_CHOICE = 5;
|
|
4922
5047
|
var LEX_NODE_NOT = 8;
|
|
4923
5048
|
var LEX_NODE_OPTIONAL = 9;
|
|
5049
|
+
var LEX_NODE_REPEAT = 10;
|
|
4924
5050
|
function lexProgramDigest(words) {
|
|
4925
5051
|
let hash = 2166136261;
|
|
4926
5052
|
for (const word of words) {
|
|
@@ -4949,85 +5075,114 @@ function trackLexLines(ctx, input, end) {
|
|
|
4949
5075
|
ctx._lineScannedTo = end;
|
|
4950
5076
|
}
|
|
4951
5077
|
function terminalNode(matcher, failure, tracksLines) {
|
|
4952
|
-
const match = (input, pos) => {
|
|
4953
|
-
const result = matcher(input, pos);
|
|
4954
|
-
return result < 0 ? -1 : result / 2;
|
|
4955
|
-
};
|
|
4956
5078
|
return {
|
|
4957
|
-
match,
|
|
5079
|
+
match: (input, pos) => {
|
|
5080
|
+
const result = matcher(input, pos);
|
|
5081
|
+
return result < 0 ? -1 : result / 2;
|
|
5082
|
+
},
|
|
4958
5083
|
run: (input, pos, ctx) => {
|
|
4959
|
-
const
|
|
4960
|
-
if (
|
|
5084
|
+
const result = matcher(input, pos);
|
|
5085
|
+
if (result < 0) {
|
|
4961
5086
|
ctx._fe = pos;
|
|
4962
5087
|
ctx._fx = failure;
|
|
4963
5088
|
if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
|
|
4964
5089
|
return -1;
|
|
4965
5090
|
}
|
|
5091
|
+
const end = result / 2;
|
|
4966
5092
|
if (tracksLines) trackLexLines(ctx, input, end);
|
|
4967
5093
|
return end;
|
|
4968
5094
|
}
|
|
4969
5095
|
};
|
|
4970
5096
|
}
|
|
4971
5097
|
function sequence2(a, b) {
|
|
5098
|
+
const am = a.match, bm = b.match, ar = a.run, br = b.run;
|
|
4972
5099
|
return {
|
|
4973
5100
|
match: (input, pos) => {
|
|
4974
|
-
const e0 =
|
|
4975
|
-
return e0 < 0 ? -1 :
|
|
5101
|
+
const e0 = am(input, pos);
|
|
5102
|
+
return e0 < 0 ? -1 : bm(input, e0);
|
|
4976
5103
|
},
|
|
4977
5104
|
run: (input, pos, ctx) => {
|
|
4978
|
-
const e0 =
|
|
5105
|
+
const e0 = ar(input, pos, ctx);
|
|
4979
5106
|
if (e0 < 0) return -1;
|
|
4980
5107
|
ctx._fc = false;
|
|
4981
|
-
return
|
|
5108
|
+
return br(input, e0, ctx);
|
|
4982
5109
|
}
|
|
4983
5110
|
};
|
|
4984
5111
|
}
|
|
4985
5112
|
function sequence3(a, b, c) {
|
|
5113
|
+
const am = a.match, bm = b.match, cm = c.match, ar = a.run, br = b.run, cr = c.run;
|
|
4986
5114
|
return {
|
|
4987
5115
|
match: (input, pos) => {
|
|
4988
|
-
const e0 =
|
|
5116
|
+
const e0 = am(input, pos);
|
|
4989
5117
|
if (e0 < 0) return -1;
|
|
4990
|
-
const e1 =
|
|
4991
|
-
return e1 < 0 ? -1 :
|
|
5118
|
+
const e1 = bm(input, e0);
|
|
5119
|
+
return e1 < 0 ? -1 : cm(input, e1);
|
|
4992
5120
|
},
|
|
4993
5121
|
run: (input, pos, ctx) => {
|
|
4994
|
-
const e0 =
|
|
5122
|
+
const e0 = ar(input, pos, ctx);
|
|
4995
5123
|
if (e0 < 0) return -1;
|
|
4996
5124
|
ctx._fc = false;
|
|
4997
|
-
const e1 =
|
|
5125
|
+
const e1 = br(input, e0, ctx);
|
|
4998
5126
|
if (e1 < 0) return -1;
|
|
4999
5127
|
ctx._fc = false;
|
|
5000
|
-
return
|
|
5128
|
+
return cr(input, e1, ctx);
|
|
5001
5129
|
}
|
|
5002
5130
|
};
|
|
5003
5131
|
}
|
|
5004
5132
|
function sequence4(a, b, c, d) {
|
|
5005
|
-
const
|
|
5133
|
+
const am = a.match, bm = b.match, cm = c.match, dm = d.match;
|
|
5134
|
+
const ar = a.run, br = b.run, cr = c.run, dr = d.run;
|
|
5006
5135
|
return {
|
|
5007
5136
|
match: (input, pos) => {
|
|
5008
|
-
const
|
|
5009
|
-
|
|
5137
|
+
const e0 = am(input, pos);
|
|
5138
|
+
if (e0 < 0) return -1;
|
|
5139
|
+
const e1 = bm(input, e0);
|
|
5140
|
+
if (e1 < 0) return -1;
|
|
5141
|
+
const e2 = cm(input, e1);
|
|
5142
|
+
return e2 < 0 ? -1 : dm(input, e2);
|
|
5010
5143
|
},
|
|
5011
5144
|
run: (input, pos, ctx) => {
|
|
5012
|
-
const
|
|
5013
|
-
if (
|
|
5145
|
+
const e0 = ar(input, pos, ctx);
|
|
5146
|
+
if (e0 < 0) return -1;
|
|
5147
|
+
ctx._fc = false;
|
|
5148
|
+
const e1 = br(input, e0, ctx);
|
|
5149
|
+
if (e1 < 0) return -1;
|
|
5014
5150
|
ctx._fc = false;
|
|
5015
|
-
|
|
5151
|
+
const e2 = cr(input, e1, ctx);
|
|
5152
|
+
if (e2 < 0) return -1;
|
|
5153
|
+
ctx._fc = false;
|
|
5154
|
+
return dr(input, e2, ctx);
|
|
5016
5155
|
}
|
|
5017
5156
|
};
|
|
5018
5157
|
}
|
|
5019
5158
|
function sequence5(a, b, c, d, e) {
|
|
5020
|
-
const
|
|
5159
|
+
const am = a.match, bm = b.match, cm = c.match, dm = d.match, em = e.match;
|
|
5160
|
+
const ar = a.run, br = b.run, cr = c.run, dr = d.run, er = e.run;
|
|
5021
5161
|
return {
|
|
5022
5162
|
match: (input, pos) => {
|
|
5023
|
-
const
|
|
5024
|
-
|
|
5163
|
+
const e0 = am(input, pos);
|
|
5164
|
+
if (e0 < 0) return -1;
|
|
5165
|
+
const e1 = bm(input, e0);
|
|
5166
|
+
if (e1 < 0) return -1;
|
|
5167
|
+
const e2 = cm(input, e1);
|
|
5168
|
+
if (e2 < 0) return -1;
|
|
5169
|
+
const e3 = dm(input, e2);
|
|
5170
|
+
return e3 < 0 ? -1 : em(input, e3);
|
|
5025
5171
|
},
|
|
5026
5172
|
run: (input, pos, ctx) => {
|
|
5027
|
-
const
|
|
5028
|
-
if (
|
|
5173
|
+
const e0 = ar(input, pos, ctx);
|
|
5174
|
+
if (e0 < 0) return -1;
|
|
5175
|
+
ctx._fc = false;
|
|
5176
|
+
const e1 = br(input, e0, ctx);
|
|
5177
|
+
if (e1 < 0) return -1;
|
|
5178
|
+
ctx._fc = false;
|
|
5179
|
+
const e2 = cr(input, e1, ctx);
|
|
5180
|
+
if (e2 < 0) return -1;
|
|
5181
|
+
ctx._fc = false;
|
|
5182
|
+
const e3 = dr(input, e2, ctx);
|
|
5183
|
+
if (e3 < 0) return -1;
|
|
5029
5184
|
ctx._fc = false;
|
|
5030
|
-
return
|
|
5185
|
+
return er(input, e3, ctx);
|
|
5031
5186
|
}
|
|
5032
5187
|
};
|
|
5033
5188
|
}
|
|
@@ -5040,9 +5195,9 @@ function appendExpected(acc, values) {
|
|
|
5040
5195
|
function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
5041
5196
|
let matchTail = () => -1;
|
|
5042
5197
|
for (let i = arms.length - 1; i >= 0; i--) {
|
|
5043
|
-
const
|
|
5198
|
+
const armMatch = arms[i].match, next = matchTail;
|
|
5044
5199
|
matchTail = (input, pos) => {
|
|
5045
|
-
const end =
|
|
5200
|
+
const end = armMatch(input, pos);
|
|
5046
5201
|
return end < 0 ? next(input, pos) : end;
|
|
5047
5202
|
};
|
|
5048
5203
|
}
|
|
@@ -5052,7 +5207,7 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
5052
5207
|
return -1;
|
|
5053
5208
|
};
|
|
5054
5209
|
for (let i = arms.length - 1; i >= 0; i--) {
|
|
5055
|
-
const
|
|
5210
|
+
const armRun = arms[i].run, cls = classes[i], staticExpected = armExpected[i], next = tail;
|
|
5056
5211
|
tail = (input, pos, ctx, lead2, acc, best) => {
|
|
5057
5212
|
if (cls !== void 0 && !classHas(cls, lead2)) {
|
|
5058
5213
|
return next(
|
|
@@ -5065,7 +5220,7 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
5065
5220
|
);
|
|
5066
5221
|
}
|
|
5067
5222
|
ctx._fc = false;
|
|
5068
|
-
const end =
|
|
5223
|
+
const end = armRun(input, pos, ctx);
|
|
5069
5224
|
if (end >= 0) return end;
|
|
5070
5225
|
const at = ctx._fe ?? pos;
|
|
5071
5226
|
if (at > best) {
|
|
@@ -5092,11 +5247,58 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
5092
5247
|
)
|
|
5093
5248
|
};
|
|
5094
5249
|
}
|
|
5250
|
+
function exclusiveChoiceNode(arms, classes, choiceFx) {
|
|
5251
|
+
const ascii = (classes.length <= 128 ? new Int8Array(128) : new Int32Array(128)).fill(-1);
|
|
5252
|
+
const hi = [];
|
|
5253
|
+
for (let i = 0; i < classes.length; i++) {
|
|
5254
|
+
const cls = classes[i];
|
|
5255
|
+
for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) ascii[c] = i;
|
|
5256
|
+
for (let r = 0; r < cls.hi.length; r += 2) hi.push(cls.hi[r], cls.hi[r + 1], i);
|
|
5257
|
+
}
|
|
5258
|
+
const select = (code) => {
|
|
5259
|
+
if (code < 0) return -1;
|
|
5260
|
+
if (code < 128) return ascii[code];
|
|
5261
|
+
for (let r = 0; r < hi.length; r += 3) if (code >= hi[r] && code <= hi[r + 1]) return hi[r + 2];
|
|
5262
|
+
return -1;
|
|
5263
|
+
};
|
|
5264
|
+
let matchArm = () => -1;
|
|
5265
|
+
let selectRun = () => -1;
|
|
5266
|
+
for (let i = arms.length - 1; i >= 0; i--) {
|
|
5267
|
+
const armMatch = arms[i].match, armRun = arms[i].run, nextMatch = matchArm, nextRun = selectRun;
|
|
5268
|
+
matchArm = (selected, input, pos) => selected === i ? armMatch(input, pos) : nextMatch(selected, input, pos);
|
|
5269
|
+
selectRun = (selected, input, pos, ctx) => selected === i ? armRun(input, pos, ctx) : nextRun(selected, input, pos, ctx);
|
|
5270
|
+
}
|
|
5271
|
+
const runArm = (input, pos, ctx) => {
|
|
5272
|
+
const arm = select(lead(input, pos));
|
|
5273
|
+
if (arm >= 0) {
|
|
5274
|
+
ctx._fc = false;
|
|
5275
|
+
const end = selectRun(arm, input, pos, ctx);
|
|
5276
|
+
if (end >= 0) return end;
|
|
5277
|
+
if (committed(ctx)) return -1;
|
|
5278
|
+
const failed = ctx._fx;
|
|
5279
|
+
if (failed !== void 0 && failed.length > 0) {
|
|
5280
|
+
ctx._fe = pos;
|
|
5281
|
+
return -1;
|
|
5282
|
+
}
|
|
5283
|
+
}
|
|
5284
|
+
ctx._fe = pos;
|
|
5285
|
+
ctx._fx = choiceFx;
|
|
5286
|
+
return -1;
|
|
5287
|
+
};
|
|
5288
|
+
return {
|
|
5289
|
+
match: (input, pos) => {
|
|
5290
|
+
const arm = select(lead(input, pos));
|
|
5291
|
+
return arm < 0 ? -1 : matchArm(arm, input, pos);
|
|
5292
|
+
},
|
|
5293
|
+
run: runArm
|
|
5294
|
+
};
|
|
5295
|
+
}
|
|
5095
5296
|
function notNode(body, failure) {
|
|
5297
|
+
const bodyMatch = body.match;
|
|
5096
5298
|
return {
|
|
5097
|
-
match: (input, pos) =>
|
|
5299
|
+
match: (input, pos) => bodyMatch(input, pos) < 0 ? pos : -1,
|
|
5098
5300
|
run: (input, pos, ctx) => {
|
|
5099
|
-
if (
|
|
5301
|
+
if (bodyMatch(input, pos) < 0) return pos;
|
|
5100
5302
|
ctx._fe = pos;
|
|
5101
5303
|
ctx._fx = failure;
|
|
5102
5304
|
return -1;
|
|
@@ -5104,18 +5306,57 @@ function notNode(body, failure) {
|
|
|
5104
5306
|
};
|
|
5105
5307
|
}
|
|
5106
5308
|
function optionalNode(body) {
|
|
5309
|
+
const bodyMatch = body.match, bodyRun = body.run;
|
|
5107
5310
|
return {
|
|
5108
5311
|
match: (input, pos) => {
|
|
5109
|
-
const end =
|
|
5312
|
+
const end = bodyMatch(input, pos);
|
|
5110
5313
|
return end < 0 ? pos : end;
|
|
5111
5314
|
},
|
|
5112
5315
|
run: (input, pos, ctx) => {
|
|
5113
5316
|
ctx._fc = false;
|
|
5114
|
-
const end =
|
|
5317
|
+
const end = bodyRun(input, pos, ctx);
|
|
5115
5318
|
return end < 0 && !committed(ctx) ? pos : end;
|
|
5116
5319
|
}
|
|
5117
5320
|
};
|
|
5118
5321
|
}
|
|
5322
|
+
function repeatNode(item, min, max) {
|
|
5323
|
+
const itemMatch = item.match, itemRun = item.run;
|
|
5324
|
+
return {
|
|
5325
|
+
match: (input, pos) => {
|
|
5326
|
+
let cur = pos;
|
|
5327
|
+
let count = 0;
|
|
5328
|
+
for (; ; ) {
|
|
5329
|
+
if (max >= 0 && count >= max) break;
|
|
5330
|
+
const optional2 = count >= min && (count > 0 || min === 0);
|
|
5331
|
+
if (optional2 && cur >= input.length) break;
|
|
5332
|
+
const end = itemMatch(input, cur);
|
|
5333
|
+
if (end < 0 || optional2 && end === cur) break;
|
|
5334
|
+
cur = end;
|
|
5335
|
+
count++;
|
|
5336
|
+
}
|
|
5337
|
+
return count < min ? -1 : cur;
|
|
5338
|
+
},
|
|
5339
|
+
run: (input, pos, ctx) => {
|
|
5340
|
+
let cur = pos;
|
|
5341
|
+
let count = 0;
|
|
5342
|
+
for (; ; ) {
|
|
5343
|
+
if (max >= 0 && count >= max) break;
|
|
5344
|
+
const optional2 = count >= min && (count > 0 || min === 0);
|
|
5345
|
+
if (optional2 && cur >= input.length) break;
|
|
5346
|
+
ctx._fc = false;
|
|
5347
|
+
const end = itemRun(input, cur, ctx);
|
|
5348
|
+
if (end < 0) {
|
|
5349
|
+
if (committed(ctx)) return -1;
|
|
5350
|
+
break;
|
|
5351
|
+
}
|
|
5352
|
+
if (optional2 && end === cur) break;
|
|
5353
|
+
cur = end;
|
|
5354
|
+
count++;
|
|
5355
|
+
}
|
|
5356
|
+
return count < min ? -1 : cur;
|
|
5357
|
+
}
|
|
5358
|
+
};
|
|
5359
|
+
}
|
|
5119
5360
|
function fixedTreeRunner(words, matchers, classes, expected) {
|
|
5120
5361
|
const stack = [];
|
|
5121
5362
|
const pop = () => {
|
|
@@ -5143,9 +5384,14 @@ function fixedTreeRunner(words, matchers, classes, expected) {
|
|
|
5143
5384
|
else stack.push(sequence5(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4]));
|
|
5144
5385
|
continue;
|
|
5145
5386
|
}
|
|
5146
|
-
if (op
|
|
5147
|
-
const count =
|
|
5387
|
+
if (op === LEX_NODE_CHOICE) {
|
|
5388
|
+
const count = words[at++];
|
|
5389
|
+
const exclusive = words[at++];
|
|
5390
|
+
if (exclusive !== 0 && exclusive !== 1) throw new TypeError("table lexical tree choice has an invalid dispatch mode");
|
|
5148
5391
|
const choiceFx = expected[words[at++]];
|
|
5392
|
+
if (!Number.isInteger(count) || count < 2 || count > stack.length) {
|
|
5393
|
+
throw new TypeError("table lexical tree choice has an invalid arm count");
|
|
5394
|
+
}
|
|
5149
5395
|
if (choiceFx === void 0) throw new TypeError("table lexical tree choice has an invalid expected set");
|
|
5150
5396
|
const armClasses = [];
|
|
5151
5397
|
const armFx = [];
|
|
@@ -5158,7 +5404,7 @@ function fixedTreeRunner(words, matchers, classes, expected) {
|
|
|
5158
5404
|
armFx.push(fx);
|
|
5159
5405
|
}
|
|
5160
5406
|
const arms = Array.from({ length: count }, pop).reverse();
|
|
5161
|
-
stack.push(choiceNode(arms, armClasses, armFx, choiceFx));
|
|
5407
|
+
stack.push(exclusive === 1 ? exclusiveChoiceNode(arms, armClasses, choiceFx) : choiceNode(arms, armClasses, armFx, choiceFx));
|
|
5162
5408
|
continue;
|
|
5163
5409
|
}
|
|
5164
5410
|
if (op === LEX_NODE_NOT) {
|
|
@@ -5171,6 +5417,14 @@ function fixedTreeRunner(words, matchers, classes, expected) {
|
|
|
5171
5417
|
stack.push(optionalNode(pop()));
|
|
5172
5418
|
continue;
|
|
5173
5419
|
}
|
|
5420
|
+
if (op === LEX_NODE_REPEAT) {
|
|
5421
|
+
const min = words[at++], max = words[at++];
|
|
5422
|
+
if (!Number.isInteger(min) || min < 0 || !Number.isInteger(max) || max >= 0 && max < min) {
|
|
5423
|
+
throw new TypeError("table lexical tree repeat has invalid bounds");
|
|
5424
|
+
}
|
|
5425
|
+
stack.push(repeatNode(pop(), min, max));
|
|
5426
|
+
continue;
|
|
5427
|
+
}
|
|
5174
5428
|
throw new TypeError("table lexical tree has an unknown fixed body");
|
|
5175
5429
|
}
|
|
5176
5430
|
if (stack.length !== 1) throw new TypeError("table lexical tree does not resolve to one root body");
|
|
@@ -5539,75 +5793,270 @@ function resolveTable(prog) {
|
|
|
5539
5793
|
return built;
|
|
5540
5794
|
}
|
|
5541
5795
|
|
|
5542
|
-
// src/
|
|
5543
|
-
function
|
|
5544
|
-
return
|
|
5796
|
+
// src/combinators/adjacency.ts
|
|
5797
|
+
function adjacencyOf(p) {
|
|
5798
|
+
return p._def.tag === "adjacency" ? p._def : null;
|
|
5545
5799
|
}
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
for (const d of list) {
|
|
5550
|
-
const bucket = byCode.get(d.code);
|
|
5551
|
-
if (bucket) bucket.push(d);
|
|
5552
|
-
else byCode.set(d.code, [d]);
|
|
5553
|
-
}
|
|
5554
|
-
const out = [];
|
|
5555
|
-
for (const [code, items] of byCode) {
|
|
5556
|
-
for (const d of items.slice(0, DETAIL_CAP)) out.push(formatDegradation(d));
|
|
5557
|
-
if (items.length > DETAIL_CAP) {
|
|
5558
|
-
out.push(
|
|
5559
|
-
`[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.`
|
|
5560
|
-
);
|
|
5561
|
-
}
|
|
5562
|
-
}
|
|
5563
|
-
return out;
|
|
5800
|
+
function adjacencyExpected(def) {
|
|
5801
|
+
if (def.polarity === "adjacent") return "adjacent";
|
|
5802
|
+
return def.kinds === void 0 ? "notAdjacent" : `notAdjacent(${def.kinds.join("|")})`;
|
|
5564
5803
|
}
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
_sinks.push(/* @__PURE__ */ new Map());
|
|
5804
|
+
function holdsAdjacency(input, cur, ctx, def) {
|
|
5805
|
+
return adjacencyHolds(input, cur, ctx, def.polarity === "notAdjacent", def.kinds);
|
|
5568
5806
|
}
|
|
5569
|
-
function
|
|
5570
|
-
|
|
5807
|
+
function adjacencyHolds(input, cur, ctx, negated, kinds) {
|
|
5808
|
+
const end = probeTriviaEnd(input, cur, ctx);
|
|
5809
|
+
if (!negated) return end === cur;
|
|
5810
|
+
if (end === cur) return false;
|
|
5811
|
+
if (kinds === void 0) return true;
|
|
5812
|
+
const want = resolveAdjacencyKindMask(ctx.trivia, kinds);
|
|
5813
|
+
const spec = analyzeLabeledTrivia(ctx.trivia);
|
|
5814
|
+
return (triviaKindMaskAt(input, cur, spec, ctx.state) & want) !== 0;
|
|
5571
5815
|
}
|
|
5572
|
-
function
|
|
5573
|
-
|
|
5574
|
-
while (_sinks.length > depth) {
|
|
5575
|
-
const sink = _sinks.pop();
|
|
5576
|
-
found.unshift(...sink.values());
|
|
5577
|
-
}
|
|
5578
|
-
return found;
|
|
5816
|
+
function adjacencyFail(pos, def) {
|
|
5817
|
+
return { ok: false, expected: [adjacencyExpected(def)], span: { start: pos, end: pos } };
|
|
5579
5818
|
}
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
if (env === "off" || env === "warn" || env === "error") return env;
|
|
5584
|
-
return "warn";
|
|
5819
|
+
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.";
|
|
5820
|
+
function adjacencyMisuse(polarity) {
|
|
5821
|
+
return new TypeError(`${polarity}(): ${NO_STANDALONE_PARSE}`);
|
|
5585
5822
|
}
|
|
5586
|
-
function
|
|
5587
|
-
|
|
5823
|
+
function adjacencyCombinator(def) {
|
|
5824
|
+
const meta = {
|
|
5825
|
+
// Zero-width and never leading (sequence() rejects index 0), so it contributes
|
|
5826
|
+
// no first char. `isZeroWidthAssertion` drops it from a sequence's first-set
|
|
5827
|
+
// rather than letting `any` poison the enclosing choice's dispatch.
|
|
5828
|
+
firstSet: { kind: "any" },
|
|
5829
|
+
canMatchNewline: false,
|
|
5830
|
+
isTrivia: false
|
|
5831
|
+
};
|
|
5832
|
+
return {
|
|
5833
|
+
_tag: "adjacency",
|
|
5834
|
+
_meta: meta,
|
|
5835
|
+
_def: def,
|
|
5836
|
+
parse() {
|
|
5837
|
+
throw adjacencyMisuse(def.polarity);
|
|
5838
|
+
}
|
|
5839
|
+
};
|
|
5588
5840
|
}
|
|
5589
|
-
function
|
|
5590
|
-
|
|
5591
|
-
if (level === "off") return;
|
|
5592
|
-
const key = degradationKey(d);
|
|
5593
|
-
const sink = _sinks[_sinks.length - 1];
|
|
5594
|
-
if (sink) {
|
|
5595
|
-
if (!sink.has(key)) sink.set(key, d);
|
|
5596
|
-
return;
|
|
5597
|
-
}
|
|
5598
|
-
if (_immediate.has(key)) return;
|
|
5599
|
-
_immediate.add(key);
|
|
5600
|
-
if (level === "error") throw new Error(`parseman: degraded compilation path
|
|
5601
|
-
${formatDegradation(d)}`);
|
|
5602
|
-
console.warn(formatDegradation(d));
|
|
5841
|
+
function adjacent() {
|
|
5842
|
+
return adjacencyCombinator({ tag: "adjacency", polarity: "adjacent" });
|
|
5603
5843
|
}
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
if (
|
|
5607
|
-
|
|
5608
|
-
|
|
5609
|
-
|
|
5610
|
-
|
|
5844
|
+
function notAdjacent(options) {
|
|
5845
|
+
const kinds = options?.kinds;
|
|
5846
|
+
if (kinds !== void 0) {
|
|
5847
|
+
if (!Array.isArray(kinds) || kinds.length === 0) {
|
|
5848
|
+
throw new TypeError("notAdjacent({ kinds }): kinds must be a non-empty array of trivia category names.");
|
|
5849
|
+
}
|
|
5850
|
+
for (const k of kinds) {
|
|
5851
|
+
if (typeof k !== "string" || k.length === 0) {
|
|
5852
|
+
throw new TypeError(`notAdjacent({ kinds }): every kind must be a non-empty string, got ${JSON.stringify(k)}.`);
|
|
5853
|
+
}
|
|
5854
|
+
}
|
|
5855
|
+
}
|
|
5856
|
+
return adjacencyCombinator(
|
|
5857
|
+
kinds === void 0 ? { tag: "adjacency", polarity: "notAdjacent" } : { tag: "adjacency", polarity: "notAdjacent", kinds: [...kinds] }
|
|
5858
|
+
);
|
|
5859
|
+
}
|
|
5860
|
+
|
|
5861
|
+
// src/combinators/sequence.ts
|
|
5862
|
+
function sequence(...parsers) {
|
|
5863
|
+
let adjacency = null;
|
|
5864
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
5865
|
+
const a = adjacencyOf(parsers[i]);
|
|
5866
|
+
if (a === null) continue;
|
|
5867
|
+
if (i === 0) {
|
|
5868
|
+
throw new TypeError(
|
|
5869
|
+
`sequence(): ${a.polarity}() cannot be the FIRST term \u2014 an adjacency assertion tests the gap after the PRECEDING term. Put a concrete term first.`
|
|
5870
|
+
);
|
|
5871
|
+
}
|
|
5872
|
+
;
|
|
5873
|
+
(adjacency ??= Array.from({ length: parsers.length }, () => null))[i] = a;
|
|
5874
|
+
}
|
|
5875
|
+
const hasAdjacency = adjacency !== null;
|
|
5876
|
+
let leading = null;
|
|
5877
|
+
for (let i = 1; i < parsers.length; i++) {
|
|
5878
|
+
if (leadsTrivia(parsers[i])) (leading ??= Array.from({ length: parsers.length }, () => false))[i] = true;
|
|
5879
|
+
}
|
|
5880
|
+
const strictArity = !hasAdjacency && (parsers.length === 2 && !matchesEmpty(parsers[1]) || parsers.length === 3 && parsers.every((p) => !matchesEmpty(p))) ? parsers.length : 0;
|
|
5881
|
+
const meta = {
|
|
5882
|
+
// Union through the nullable prefix — a leading optional()/many() lets a later
|
|
5883
|
+
// term's first char start the sequence. Just `parsers[0]` under-approximates.
|
|
5884
|
+
firstSet: sequenceFirstSet(parsers),
|
|
5885
|
+
canMatchNewline: parsers.some((p) => p._meta.canMatchNewline),
|
|
5886
|
+
isTrivia: false
|
|
5887
|
+
};
|
|
5888
|
+
const def = { tag: "sequence", parsers };
|
|
5889
|
+
const scalarParsers = parsers.map(scalarOf);
|
|
5890
|
+
const parseScalar = (input, pos, ctx) => {
|
|
5891
|
+
let cur = pos;
|
|
5892
|
+
if (strictArity !== 0) {
|
|
5893
|
+
cur = scalarParsers[0](input, cur, ctx);
|
|
5894
|
+
if (cur < 0) return cur;
|
|
5895
|
+
const first = ctx._sv;
|
|
5896
|
+
if (ctx.trivia) cur = advanceTrivia(input, cur, ctx);
|
|
5897
|
+
cur = scalarParsers[1](input, cur, ctx);
|
|
5898
|
+
if (cur < 0) return cur;
|
|
5899
|
+
const second = ctx._sv;
|
|
5900
|
+
if (strictArity === 2) {
|
|
5901
|
+
ctx._sv = def.valueUnused ? void 0 : [first, second];
|
|
5902
|
+
return cur;
|
|
5903
|
+
}
|
|
5904
|
+
if (ctx.trivia) cur = advanceTrivia(input, cur, ctx);
|
|
5905
|
+
cur = scalarParsers[2](input, cur, ctx);
|
|
5906
|
+
if (cur < 0) return cur;
|
|
5907
|
+
ctx._sv = def.valueUnused ? void 0 : [first, second, ctx._sv];
|
|
5908
|
+
return cur;
|
|
5909
|
+
}
|
|
5910
|
+
const values = def.valueUnused ? void 0 : [];
|
|
5911
|
+
for (let i = 0; i < scalarParsers.length; i++) {
|
|
5912
|
+
let termPos = cur;
|
|
5913
|
+
if (i > 0 && ctx.trivia) termPos = advanceTrivia(input, cur, ctx);
|
|
5914
|
+
const end = scalarParsers[i](input, termPos, ctx);
|
|
5915
|
+
if (end < 0) return end;
|
|
5916
|
+
if (values !== void 0) values.push(ctx._sv);
|
|
5917
|
+
if (end > termPos || termPos === cur) cur = end;
|
|
5918
|
+
}
|
|
5919
|
+
ctx._sv = values;
|
|
5920
|
+
return cur;
|
|
5921
|
+
};
|
|
5922
|
+
let followSentinels;
|
|
5923
|
+
return {
|
|
5924
|
+
_tag: "sequence",
|
|
5925
|
+
_meta: meta,
|
|
5926
|
+
_def: def,
|
|
5927
|
+
_parseScalar: hasAdjacency || leading !== null ? void 0 : parseScalar,
|
|
5928
|
+
parse(input, pos, ctx) {
|
|
5929
|
+
const tolerant = ctx._tolerant === true;
|
|
5930
|
+
if (tolerant) {
|
|
5931
|
+
followSentinels ??= parsers.map((_, i) => firstSetSentinel(
|
|
5932
|
+
parsers.slice(i + 1).reduce(
|
|
5933
|
+
(set, parser2) => union(set, firstSetOf(parser2)),
|
|
5934
|
+
{ kind: "empty" }
|
|
5935
|
+
)
|
|
5936
|
+
));
|
|
5937
|
+
}
|
|
5938
|
+
const inheritedSync = ctx._sync;
|
|
5939
|
+
const deferredTrivia = needsDeferredTriviaCommit(ctx);
|
|
5940
|
+
const values = def.valueUnused ? void 0 : [];
|
|
5941
|
+
let cur = pos;
|
|
5942
|
+
try {
|
|
5943
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
5944
|
+
if (tolerant) ctx._sync = followSentinels[i] ?? inheritedSync;
|
|
5945
|
+
const assertion = adjacency?.[i];
|
|
5946
|
+
if (assertion) {
|
|
5947
|
+
if (!holdsAdjacency(input, cur, ctx, assertion)) return adjacencyFail(cur, assertion);
|
|
5948
|
+
if (values !== void 0) values.push(null);
|
|
5949
|
+
continue;
|
|
5950
|
+
}
|
|
5951
|
+
let termPos = cur;
|
|
5952
|
+
const markTlog = deferredTrivia ? cstTlLen(ctx) : 0;
|
|
5953
|
+
const markLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
|
|
5954
|
+
const markRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
5955
|
+
if (ctx.trivia && i > 0) {
|
|
5956
|
+
termPos = deferredTrivia ? commitTriviaScan(scanTriviaCompact(input, cur, ctx)) : advanceTrivia(input, cur, ctx);
|
|
5957
|
+
}
|
|
5958
|
+
const scanTlog = deferredTrivia ? cstTlLen(ctx) : 0;
|
|
5959
|
+
const scanLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
|
|
5960
|
+
const scanRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
5961
|
+
if (leading?.[i] === true) LEAD.at = cur;
|
|
5962
|
+
const result = parsers[i].parse(input, termPos, ctx);
|
|
5963
|
+
if (!result.ok) return result;
|
|
5964
|
+
if (values !== void 0) values.push(result.value);
|
|
5965
|
+
if (result.span.end > termPos || termPos === cur) cur = result.span.end;
|
|
5966
|
+
else if (deferredTrivia) {
|
|
5967
|
+
rollbackScannedTriviaAt(
|
|
5968
|
+
ctx,
|
|
5969
|
+
markTlog,
|
|
5970
|
+
scanTlog,
|
|
5971
|
+
markLog,
|
|
5972
|
+
scanLog,
|
|
5973
|
+
markRootLog,
|
|
5974
|
+
scanRootLog
|
|
5975
|
+
);
|
|
5976
|
+
}
|
|
5977
|
+
}
|
|
5978
|
+
} finally {
|
|
5979
|
+
if (tolerant) ctx._sync = inheritedSync;
|
|
5980
|
+
}
|
|
5981
|
+
return {
|
|
5982
|
+
ok: true,
|
|
5983
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
5984
|
+
value: values ?? void 0,
|
|
5985
|
+
span: { start: pos, end: cur }
|
|
5986
|
+
};
|
|
5987
|
+
}
|
|
5988
|
+
};
|
|
5989
|
+
}
|
|
5990
|
+
|
|
5991
|
+
// src/compiler/degradation.ts
|
|
5992
|
+
function formatDegradation(d) {
|
|
5993
|
+
return `[parseman] degraded [${d.code}] ${d.where}: ${d.subject} \u2014 ${d.fellBackTo}; otherwise ${d.otherwise}`;
|
|
5994
|
+
}
|
|
5995
|
+
var DETAIL_CAP = 8;
|
|
5996
|
+
function formatDegradations(list) {
|
|
5997
|
+
const byCode = /* @__PURE__ */ new Map();
|
|
5998
|
+
for (const d of list) {
|
|
5999
|
+
const bucket = byCode.get(d.code);
|
|
6000
|
+
if (bucket) bucket.push(d);
|
|
6001
|
+
else byCode.set(d.code, [d]);
|
|
6002
|
+
}
|
|
6003
|
+
const out = [];
|
|
6004
|
+
for (const [code, items] of byCode) {
|
|
6005
|
+
for (const d of items.slice(0, DETAIL_CAP)) out.push(formatDegradation(d));
|
|
6006
|
+
if (items.length > DETAIL_CAP) {
|
|
6007
|
+
out.push(
|
|
6008
|
+
`[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.`
|
|
6009
|
+
);
|
|
6010
|
+
}
|
|
6011
|
+
}
|
|
6012
|
+
return out;
|
|
6013
|
+
}
|
|
6014
|
+
var _sinks = [];
|
|
6015
|
+
function beginDegradationCapture() {
|
|
6016
|
+
_sinks.push(/* @__PURE__ */ new Map());
|
|
6017
|
+
}
|
|
6018
|
+
function degradationCaptureDepth() {
|
|
6019
|
+
return _sinks.length;
|
|
6020
|
+
}
|
|
6021
|
+
function unwindDegradationCapture(depth) {
|
|
6022
|
+
const found = [];
|
|
6023
|
+
while (_sinks.length > depth) {
|
|
6024
|
+
const sink = _sinks.pop();
|
|
6025
|
+
found.unshift(...sink.values());
|
|
6026
|
+
}
|
|
6027
|
+
return found;
|
|
6028
|
+
}
|
|
6029
|
+
function resolveDegradationLevel(explicit) {
|
|
6030
|
+
if (explicit !== void 0) return explicit;
|
|
6031
|
+
const env = typeof process !== "undefined" ? process.env?.PARSEMAN_DEGRADATION : void 0;
|
|
6032
|
+
if (env === "off" || env === "warn" || env === "error") return env;
|
|
6033
|
+
return "warn";
|
|
6034
|
+
}
|
|
6035
|
+
function degradationKey(d) {
|
|
6036
|
+
return JSON.stringify([d.code, d.where, d.subject]);
|
|
6037
|
+
}
|
|
6038
|
+
function recordDegradation(d) {
|
|
6039
|
+
const level = resolveDegradationLevel();
|
|
6040
|
+
if (level === "off") return;
|
|
6041
|
+
const key = degradationKey(d);
|
|
6042
|
+
const sink = _sinks[_sinks.length - 1];
|
|
6043
|
+
if (sink) {
|
|
6044
|
+
if (!sink.has(key)) sink.set(key, d);
|
|
6045
|
+
return;
|
|
6046
|
+
}
|
|
6047
|
+
if (_immediate.has(key)) return;
|
|
6048
|
+
_immediate.add(key);
|
|
6049
|
+
if (level === "error") throw new Error(`parseman: degraded compilation path
|
|
6050
|
+
${formatDegradation(d)}`);
|
|
6051
|
+
console.warn(formatDegradation(d));
|
|
6052
|
+
}
|
|
6053
|
+
var _immediate = /* @__PURE__ */ new Set();
|
|
6054
|
+
function beginCompileDegradationDrain() {
|
|
6055
|
+
if (resolveDegradationLevel() === "off" || _sinks.length > 0) return () => {
|
|
6056
|
+
};
|
|
6057
|
+
const depth = degradationCaptureDepth();
|
|
6058
|
+
beginDegradationCapture();
|
|
6059
|
+
return (report) => {
|
|
5611
6060
|
const found = unwindDegradationCapture(depth);
|
|
5612
6061
|
if (!report || found.length === 0) return;
|
|
5613
6062
|
const fresh = found.filter((d) => {
|
|
@@ -5717,91 +6166,620 @@ function splitTopLevel(inner) {
|
|
|
5717
6166
|
last = i + 1;
|
|
5718
6167
|
}
|
|
5719
6168
|
}
|
|
5720
|
-
if (depth !== 0 || angle !== 0) return null;
|
|
5721
|
-
parts.push(inner.slice(last));
|
|
5722
|
-
return parts;
|
|
6169
|
+
if (depth !== 0 || angle !== 0) return null;
|
|
6170
|
+
parts.push(inner.slice(last));
|
|
6171
|
+
return parts;
|
|
6172
|
+
}
|
|
6173
|
+
function isConfirmableParam(part) {
|
|
6174
|
+
const head = PARAM_HEAD_RE.exec(part);
|
|
6175
|
+
if (!head) return false;
|
|
6176
|
+
const rest = part.slice(head[0].length);
|
|
6177
|
+
if (rest === "") return true;
|
|
6178
|
+
if (rest[0] !== ":") return false;
|
|
6179
|
+
return !hasDefaultAssign(rest.slice(1));
|
|
6180
|
+
}
|
|
6181
|
+
function hasDefaultAssign(annotation) {
|
|
6182
|
+
for (let i = 0; i < annotation.length; i++) {
|
|
6183
|
+
if (annotation[i] !== "=") continue;
|
|
6184
|
+
if (annotation[i + 1] === ">" || annotation[i + 1] === "=") {
|
|
6185
|
+
i++;
|
|
6186
|
+
continue;
|
|
6187
|
+
}
|
|
6188
|
+
const prev = annotation[i - 1];
|
|
6189
|
+
if (prev === "<" || prev === ">" || prev === "!" || prev === "=") continue;
|
|
6190
|
+
return true;
|
|
6191
|
+
}
|
|
6192
|
+
return false;
|
|
6193
|
+
}
|
|
6194
|
+
function buildAnalysisSrc(def) {
|
|
6195
|
+
return def.buildSigSrc ?? def.buildSrc ?? def.build.toString();
|
|
6196
|
+
}
|
|
6197
|
+
var RESOLVER_REASONS = {
|
|
6198
|
+
"rest-parameter": "its parameter list uses a rest parameter, so the declared arity is unbounded",
|
|
6199
|
+
"arguments": "its body references `arguments`",
|
|
6200
|
+
"reassigned": "the binding it names is reassigned, so the function read here is not decidable",
|
|
6201
|
+
"not-a-function": "the binding it names is not a function declaration",
|
|
6202
|
+
"unresolved-import": "its module could not be resolved or parsed",
|
|
6203
|
+
"not-found": "the name did not resolve to any binding",
|
|
6204
|
+
"computed": "it is a computed expression",
|
|
6205
|
+
"foreign-source": "it is named in a module the resolver was never told about, so its offsets index no scope tree the resolver holds",
|
|
6206
|
+
"ambiguous-source": "two distinct registered modules hold byte-identical text, so that text no longer names the module its offsets index"
|
|
6207
|
+
};
|
|
6208
|
+
function unconfirmableReason(def, src) {
|
|
6209
|
+
const declared = def.buildArityUnresolved;
|
|
6210
|
+
if (declared !== void 0 && RESOLVER_REASONS[declared]) return RESOLVER_REASONS[declared];
|
|
6211
|
+
const s = src.trim();
|
|
6212
|
+
const params = s.slice(0, s.indexOf(")") + 1);
|
|
6213
|
+
if (params.includes("...")) return RESOLVER_REASONS["rest-parameter"];
|
|
6214
|
+
if (/\barguments\b/.test(s)) return RESOLVER_REASONS["arguments"];
|
|
6215
|
+
if (/^[A-Za-z_$][\w$]*(\s*\.\s*[A-Za-z_$][\w$]*)?$/.test(s)) {
|
|
6216
|
+
return "it names a binding this build could not resolve to a function declaration";
|
|
6217
|
+
}
|
|
6218
|
+
return "its parameter list could not be parsed";
|
|
6219
|
+
}
|
|
6220
|
+
function confirmedArityForDef(def) {
|
|
6221
|
+
if (def.buildArity !== void 0) return def.buildArity;
|
|
6222
|
+
const src = buildAnalysisSrc(def);
|
|
6223
|
+
const arity = confirmedBuildArity(src);
|
|
6224
|
+
if (arity !== null) return arity;
|
|
6225
|
+
const subject = `build reducer \`${(def.buildSrc ?? "<runtime fn>").trim().split("\n")[0].slice(0, 60)}\``;
|
|
6226
|
+
recordDegradation({
|
|
6227
|
+
code: "build-arity-unconfirmed",
|
|
6228
|
+
severity: "warn",
|
|
6229
|
+
where: `node("${def.type ?? "<inferred>"}")`,
|
|
6230
|
+
subject,
|
|
6231
|
+
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`,
|
|
6232
|
+
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"
|
|
6233
|
+
});
|
|
6234
|
+
return null;
|
|
6235
|
+
}
|
|
6236
|
+
function buildReadsRaw(def) {
|
|
6237
|
+
if (!def.build) return true;
|
|
6238
|
+
if (def.buildRawUnused === true) return false;
|
|
6239
|
+
const arity = confirmedArityForDef(def);
|
|
6240
|
+
if (arity === null) return true;
|
|
6241
|
+
return arity >= 4;
|
|
6242
|
+
}
|
|
6243
|
+
function buildReadsTrivia(def) {
|
|
6244
|
+
if (!def.build) return true;
|
|
6245
|
+
const arity = confirmedArityForDef(def);
|
|
6246
|
+
if (arity === null) return true;
|
|
6247
|
+
return arity >= 5;
|
|
6248
|
+
}
|
|
6249
|
+
function buildReadsState(def) {
|
|
6250
|
+
if (!def.build) return true;
|
|
6251
|
+
const arity = confirmedArityForDef(def);
|
|
6252
|
+
if (arity === null) return true;
|
|
6253
|
+
return arity >= 6;
|
|
6254
|
+
}
|
|
6255
|
+
|
|
6256
|
+
// src/combinators/token.ts
|
|
6257
|
+
function semanticLeafValue(_ctx, _input, _start, _end, value) {
|
|
6258
|
+
return value;
|
|
6259
|
+
}
|
|
6260
|
+
function sourceLeafValue(ctx, input, start, end, value) {
|
|
6261
|
+
return cstOutputHost(ctx.build) ? input.slice(start, end) : value;
|
|
6262
|
+
}
|
|
6263
|
+
function token(root) {
|
|
6264
|
+
const meta = {
|
|
6265
|
+
firstSet: root._meta.firstSet,
|
|
6266
|
+
canMatchNewline: root._meta.canMatchNewline,
|
|
6267
|
+
isTrivia: false
|
|
6268
|
+
};
|
|
6269
|
+
return {
|
|
6270
|
+
_tag: "token",
|
|
6271
|
+
_meta: meta,
|
|
6272
|
+
_def: { tag: "token", parser: root },
|
|
6273
|
+
parse(input, pos, ctx) {
|
|
6274
|
+
const savedTrivia = ctx.trivia;
|
|
6275
|
+
const savedKinds = ctx.triviaKindLabels;
|
|
6276
|
+
const savedBuf = ctx._cstBuf;
|
|
6277
|
+
const savedChildren = ctx._cstChildren;
|
|
6278
|
+
const savedLeaves = ctx._cstLeaves;
|
|
6279
|
+
const savedRaw = ctx._cstRawChildren;
|
|
6280
|
+
const savedTriviaLog = ctx._cstTriviaLog;
|
|
6281
|
+
const savedOuterTriviaLog = ctx._triviaLog;
|
|
6282
|
+
const savedRootTriviaLog = ctx._rootTriviaLog;
|
|
6283
|
+
const wasCapturing = cstCaptureActive(ctx);
|
|
6284
|
+
ctx.trivia = void 0;
|
|
6285
|
+
ctx.triviaKindLabels = void 0;
|
|
6286
|
+
ctx._cstBuf = void 0;
|
|
6287
|
+
ctx._cstChildren = void 0;
|
|
6288
|
+
ctx._cstLeaves = void 0;
|
|
6289
|
+
ctx._cstRawChildren = void 0;
|
|
6290
|
+
ctx._cstTriviaLog = void 0;
|
|
6291
|
+
ctx._triviaLog = void 0;
|
|
6292
|
+
ctx._rootTriviaLog = void 0;
|
|
6293
|
+
let result;
|
|
6294
|
+
try {
|
|
6295
|
+
result = root.parse(input, pos, ctx);
|
|
6296
|
+
} finally {
|
|
6297
|
+
ctx.trivia = savedTrivia;
|
|
6298
|
+
ctx.triviaKindLabels = savedKinds;
|
|
6299
|
+
ctx._cstBuf = savedBuf;
|
|
6300
|
+
ctx._cstChildren = savedChildren;
|
|
6301
|
+
ctx._cstLeaves = savedLeaves;
|
|
6302
|
+
ctx._cstRawChildren = savedRaw;
|
|
6303
|
+
ctx._cstTriviaLog = savedTriviaLog;
|
|
6304
|
+
ctx._triviaLog = savedOuterTriviaLog;
|
|
6305
|
+
ctx._rootTriviaLog = savedRootTriviaLog;
|
|
6306
|
+
}
|
|
6307
|
+
if (!result.ok) return result;
|
|
6308
|
+
const span = result.span;
|
|
6309
|
+
const value = input.slice(pos, span.end);
|
|
6310
|
+
if (wasCapturing) pushCstLeaf(ctx, { _tag: "leaf", value, span });
|
|
6311
|
+
return { ok: true, value, span };
|
|
6312
|
+
}
|
|
6313
|
+
};
|
|
6314
|
+
}
|
|
6315
|
+
function makeLeaf(root, fn, sourceCstValue) {
|
|
6316
|
+
const cstValue = sourceCstValue ? sourceLeafValue : semanticLeafValue;
|
|
6317
|
+
const meta = {
|
|
6318
|
+
firstSet: root._meta.firstSet,
|
|
6319
|
+
canMatchNewline: root._meta.canMatchNewline,
|
|
6320
|
+
isTrivia: false
|
|
6321
|
+
};
|
|
6322
|
+
return {
|
|
6323
|
+
_tag: "leaf",
|
|
6324
|
+
_meta: meta,
|
|
6325
|
+
_def: {
|
|
6326
|
+
tag: "leaf",
|
|
6327
|
+
parser: root,
|
|
6328
|
+
fn,
|
|
6329
|
+
...sourceCstValue ? { cstValue: "source" } : {}
|
|
6330
|
+
},
|
|
6331
|
+
parse(input, pos, ctx) {
|
|
6332
|
+
const savedBuf = ctx._cstBuf;
|
|
6333
|
+
const savedChildren = ctx._cstChildren;
|
|
6334
|
+
const savedLeaves = ctx._cstLeaves;
|
|
6335
|
+
const savedRaw = ctx._cstRawChildren;
|
|
6336
|
+
const savedTriviaLog = ctx._cstTriviaLog;
|
|
6337
|
+
const savedOuterTriviaLog = ctx._triviaLog;
|
|
6338
|
+
const wasCapturing = cstCaptureActive(ctx);
|
|
6339
|
+
ctx._cstBuf = void 0;
|
|
6340
|
+
ctx._cstChildren = void 0;
|
|
6341
|
+
ctx._cstLeaves = void 0;
|
|
6342
|
+
ctx._cstRawChildren = void 0;
|
|
6343
|
+
ctx._cstTriviaLog = void 0;
|
|
6344
|
+
ctx._triviaLog = void 0;
|
|
6345
|
+
let result;
|
|
6346
|
+
try {
|
|
6347
|
+
result = root.parse(input, pos, ctx);
|
|
6348
|
+
} finally {
|
|
6349
|
+
ctx._cstBuf = savedBuf;
|
|
6350
|
+
ctx._cstChildren = savedChildren;
|
|
6351
|
+
ctx._cstLeaves = savedLeaves;
|
|
6352
|
+
ctx._cstRawChildren = savedRaw;
|
|
6353
|
+
ctx._cstTriviaLog = savedTriviaLog;
|
|
6354
|
+
ctx._triviaLog = savedOuterTriviaLog;
|
|
6355
|
+
}
|
|
6356
|
+
if (!result.ok) return result;
|
|
6357
|
+
const value = fn(result.value, result.span);
|
|
6358
|
+
if (wasCapturing) pushCstLeaf(ctx, {
|
|
6359
|
+
_tag: "leaf",
|
|
6360
|
+
value: cstValue(ctx, input, pos, result.span.end, value),
|
|
6361
|
+
span: result.span
|
|
6362
|
+
});
|
|
6363
|
+
return { ok: true, value, span: result.span };
|
|
6364
|
+
}
|
|
6365
|
+
};
|
|
6366
|
+
}
|
|
6367
|
+
function leaf(root, fn) {
|
|
6368
|
+
return makeLeaf(root, fn, false);
|
|
6369
|
+
}
|
|
6370
|
+
function sourceLeaf(root, fn) {
|
|
6371
|
+
return makeLeaf(root, fn, true);
|
|
6372
|
+
}
|
|
6373
|
+
|
|
6374
|
+
// src/compiler/value-usage.ts
|
|
6375
|
+
function markUnusedValues(root) {
|
|
6376
|
+
const seenConsumed = /* @__PURE__ */ new WeakSet();
|
|
6377
|
+
const seenUnconsumed = /* @__PURE__ */ new WeakSet();
|
|
6378
|
+
const mark = (def, consumed) => {
|
|
6379
|
+
if (consumed) def.valueUnused = false;
|
|
6380
|
+
else if (def.valueUnused !== false) def.valueUnused = true;
|
|
6381
|
+
};
|
|
6382
|
+
const visit = (c, consumed) => {
|
|
6383
|
+
const seen = consumed ? seenConsumed : seenUnconsumed;
|
|
6384
|
+
if (seen.has(c)) return;
|
|
6385
|
+
seen.add(c);
|
|
6386
|
+
const def = c._def;
|
|
6387
|
+
switch (def.tag) {
|
|
6388
|
+
case "many":
|
|
6389
|
+
case "oneOrMore":
|
|
6390
|
+
mark(def, consumed);
|
|
6391
|
+
visit(def.parser, consumed);
|
|
6392
|
+
return;
|
|
6393
|
+
case "optional":
|
|
6394
|
+
visit(def.parser, consumed);
|
|
6395
|
+
return;
|
|
6396
|
+
case "sequence":
|
|
6397
|
+
mark(def, consumed);
|
|
6398
|
+
for (const p of def.parsers) visit(p, consumed);
|
|
6399
|
+
return;
|
|
6400
|
+
case "choice":
|
|
6401
|
+
for (const p of def.parsers) visit(p, consumed);
|
|
6402
|
+
return;
|
|
6403
|
+
case "dispatch":
|
|
6404
|
+
visit(def.selector, consumed);
|
|
6405
|
+
for (const entry of def.cases) visit(entry.parser, consumed);
|
|
6406
|
+
if (def.matchers) for (const entry of def.matchers) visit(entry.parser, consumed);
|
|
6407
|
+
if (def.otherwise) visit(def.otherwise, consumed);
|
|
6408
|
+
return;
|
|
6409
|
+
case "node":
|
|
6410
|
+
visit(def.parser, false);
|
|
6411
|
+
return;
|
|
6412
|
+
case "transform":
|
|
6413
|
+
visit(def.parser, true);
|
|
6414
|
+
return;
|
|
6415
|
+
case "field":
|
|
6416
|
+
visit(def.parser, true);
|
|
6417
|
+
return;
|
|
6418
|
+
case "sepBy":
|
|
6419
|
+
visit(def.parser, true);
|
|
6420
|
+
visit(def.separator, false);
|
|
6421
|
+
return;
|
|
6422
|
+
case "not":
|
|
6423
|
+
case "peek":
|
|
6424
|
+
visit(def.parser, false);
|
|
6425
|
+
return;
|
|
6426
|
+
case "grammar":
|
|
6427
|
+
visit(def.parser, consumed);
|
|
6428
|
+
if (def.triviaParser) visit(def.triviaParser, false);
|
|
6429
|
+
return;
|
|
6430
|
+
case "recover":
|
|
6431
|
+
visit(def.parser, consumed);
|
|
6432
|
+
visit(def.sentinel, false);
|
|
6433
|
+
return;
|
|
6434
|
+
case "token":
|
|
6435
|
+
visit(def.parser, false);
|
|
6436
|
+
return;
|
|
6437
|
+
case "label":
|
|
6438
|
+
case "trivia":
|
|
6439
|
+
case "attempt":
|
|
6440
|
+
case "withCtx":
|
|
6441
|
+
case "expect":
|
|
6442
|
+
visit(def.parser, consumed);
|
|
6443
|
+
return;
|
|
6444
|
+
case "leaf":
|
|
6445
|
+
visit(def.parser, true);
|
|
6446
|
+
return;
|
|
6447
|
+
case "lazy":
|
|
6448
|
+
return;
|
|
6449
|
+
default:
|
|
6450
|
+
return;
|
|
6451
|
+
}
|
|
6452
|
+
};
|
|
6453
|
+
const resolveRoot = (c) => {
|
|
6454
|
+
const guard = /* @__PURE__ */ new Set();
|
|
6455
|
+
let cur = c;
|
|
6456
|
+
while (!guard.has(cur)) {
|
|
6457
|
+
const d = cur._def;
|
|
6458
|
+
if (d.tag === "grammar") {
|
|
6459
|
+
guard.add(cur);
|
|
6460
|
+
cur = d.parser;
|
|
6461
|
+
continue;
|
|
6462
|
+
}
|
|
6463
|
+
if (d.tag !== "lazy") return cur;
|
|
6464
|
+
guard.add(cur);
|
|
6465
|
+
try {
|
|
6466
|
+
cur = d.thunk();
|
|
6467
|
+
} catch {
|
|
6468
|
+
return c;
|
|
6469
|
+
}
|
|
6470
|
+
}
|
|
6471
|
+
return cur;
|
|
6472
|
+
};
|
|
6473
|
+
visit(resolveRoot(root), true);
|
|
6474
|
+
}
|
|
6475
|
+
|
|
6476
|
+
// src/cst/root-trivia-scope.ts
|
|
6477
|
+
var ROOT_TRIVIA_SCOPE_REFUSAL = "parser(): selected root trivia requires classifiedTrivia() for every local trivia scope, or rootCapture: 'opaque'.";
|
|
6478
|
+
function refuseUnclassifiedRootScope(strict) {
|
|
6479
|
+
if (strict === true) throw new TypeError(ROOT_TRIVIA_SCOPE_REFUSAL);
|
|
6480
|
+
}
|
|
6481
|
+
|
|
6482
|
+
// src/combinators/grammar.ts
|
|
6483
|
+
function annotateResultLines(result, index) {
|
|
6484
|
+
const annotated = { ...result, span: annotateSpan(result.span, index) };
|
|
6485
|
+
const errors = annotated.errors;
|
|
6486
|
+
if (errors) {
|
|
6487
|
+
;
|
|
6488
|
+
annotated.errors = errors.map((error) => ({
|
|
6489
|
+
...error,
|
|
6490
|
+
span: annotateSpan(error.span, index)
|
|
6491
|
+
}));
|
|
6492
|
+
}
|
|
6493
|
+
return annotated;
|
|
6494
|
+
}
|
|
6495
|
+
function createParseLineContext(input, pos) {
|
|
6496
|
+
const lineIndex = createLineIndex();
|
|
6497
|
+
if (pos > 0) recordLineRange(lineIndex, input, 0, pos);
|
|
6498
|
+
return { lineIndex, lineScannedTo: pos };
|
|
6499
|
+
}
|
|
6500
|
+
var TRACK_LINES_ON = () => true;
|
|
6501
|
+
var TRACK_LINES_OFF = () => false;
|
|
6502
|
+
var TRACK_LINES_INHERIT = (ctx) => ctx?.trackLines === true;
|
|
6503
|
+
function parser(opts, root) {
|
|
6504
|
+
const clearTrivia = opts.trivia === null;
|
|
6505
|
+
const opaqueRootCapture = opts.rootCapture === "opaque";
|
|
6506
|
+
if (opaqueRootCapture && opts.trivia === void 0) {
|
|
6507
|
+
throw new TypeError("parser({ rootCapture: 'opaque' }) requires an explicit trivia scope.");
|
|
6508
|
+
}
|
|
6509
|
+
const scopeTrivia = clearTrivia ? void 0 : opts.trivia ?? void 0;
|
|
6510
|
+
const scopeLabels = scopeTrivia?._meta?.triviaKindLabels;
|
|
6511
|
+
const refuseUnclassified = scopeTrivia !== void 0 && !scopeTrivia._meta?.rootTriviaClassified && !opaqueRootCapture;
|
|
6512
|
+
const forceCaptureTrivia = opts.captureTrivia === true;
|
|
6513
|
+
const trackLinesPolicy = opts.trackLines === true ? "on" : opts.trackLines === false ? "off" : "inherit";
|
|
6514
|
+
const trackLinesOf = trackLinesPolicy === "on" ? TRACK_LINES_ON : trackLinesPolicy === "off" ? TRACK_LINES_OFF : TRACK_LINES_INHERIT;
|
|
6515
|
+
const captureKinds = clearTrivia ? void 0 : opts.captureTriviaKinds;
|
|
6516
|
+
const ownCaptureMask = captureKinds === void 0 ? void 0 : scopeLabels !== void 0 ? triviaKindMask(scopeLabels, captureKinds) : void 0;
|
|
6517
|
+
const inheritCaptureMask = captureKinds !== void 0 && scopeLabels === void 0;
|
|
6518
|
+
const rootScalar = scalarOf(root);
|
|
6519
|
+
const scalarEligible = opts.trackLines !== true && opts.recover !== true && !opaqueRootCapture && !forceCaptureTrivia && captureKinds === void 0;
|
|
6520
|
+
const parseScalar = scalarEligible ? (input, pos, ctx) => {
|
|
6521
|
+
const savedTrivia = ctx.trivia;
|
|
6522
|
+
const savedLabels = ctx.triviaKindLabels;
|
|
6523
|
+
if (clearTrivia) {
|
|
6524
|
+
ctx.trivia = void 0;
|
|
6525
|
+
ctx.triviaKindLabels = void 0;
|
|
6526
|
+
} else if (scopeTrivia !== void 0) {
|
|
6527
|
+
ctx.trivia = scopeTrivia;
|
|
6528
|
+
ctx.triviaKindLabels = scopeLabels;
|
|
6529
|
+
}
|
|
6530
|
+
const end = rootScalar(input, pos, ctx);
|
|
6531
|
+
ctx.trivia = savedTrivia;
|
|
6532
|
+
ctx.triviaKindLabels = savedLabels;
|
|
6533
|
+
return end;
|
|
6534
|
+
} : void 0;
|
|
6535
|
+
let publicScalar;
|
|
6536
|
+
const grammar = {
|
|
6537
|
+
_tag: "grammar",
|
|
6538
|
+
_meta: {
|
|
6539
|
+
...root._meta,
|
|
6540
|
+
// Trivia classification describes this grammar's own active trivia
|
|
6541
|
+
// scope. A directly nested grammar may have classified trivia of its
|
|
6542
|
+
// own, but that must not advertise classification for this wrapper.
|
|
6543
|
+
triviaKindLabels: void 0,
|
|
6544
|
+
rootTriviaClassified: void 0,
|
|
6545
|
+
...opts.trivia?._meta?.triviaKindLabels ? { triviaKindLabels: opts.trivia._meta.triviaKindLabels } : {},
|
|
6546
|
+
...opts.trivia?._meta?.rootTriviaClassified ? { rootTriviaClassified: true } : {}
|
|
6547
|
+
},
|
|
6548
|
+
_def: {
|
|
6549
|
+
tag: "grammar",
|
|
6550
|
+
parser: root,
|
|
6551
|
+
triviaParser: scopeTrivia,
|
|
6552
|
+
clearTrivia,
|
|
6553
|
+
...opaqueRootCapture ? { rootCapture: "opaque" } : {},
|
|
6554
|
+
...opts.captureTrivia ? { captureTrivia: true } : {},
|
|
6555
|
+
trackLines: opts.trackLines ?? false,
|
|
6556
|
+
constructionTrackLines: trackLinesPolicy,
|
|
6557
|
+
...captureKinds === void 0 ? {} : { constructionCaptureTriviaKinds: captureKinds }
|
|
6558
|
+
},
|
|
6559
|
+
_parseScalar: parseScalar,
|
|
6560
|
+
parse(input, pos, _ctx) {
|
|
6561
|
+
if (pos === void 0 && _ctx === void 0) {
|
|
6562
|
+
publicScalar ??= scalarRootOf(grammar) ?? null;
|
|
6563
|
+
if (publicScalar) {
|
|
6564
|
+
const ctx2 = createParseContext();
|
|
6565
|
+
const end = publicScalar(input, 0, ctx2);
|
|
6566
|
+
if (end < 0) {
|
|
6567
|
+
const at = ~end;
|
|
6568
|
+
return { ok: false, expected: ctx2._fx ?? [], span: { start: at, end: at } };
|
|
6569
|
+
}
|
|
6570
|
+
return { ok: true, value: ctx2._sv, span: { start: 0, end } };
|
|
6571
|
+
}
|
|
6572
|
+
}
|
|
6573
|
+
if (refuseUnclassified) refuseUnclassifiedRootScope(_ctx?._rootTriviaStrictScopes);
|
|
6574
|
+
const trackLines = trackLinesOf(_ctx);
|
|
6575
|
+
const lineContext = trackLines && _ctx?._lineIndex === void 0 && _ctx?._lineStarts === void 0 ? createParseLineContext(input, pos ?? 0) : void 0;
|
|
6576
|
+
const lineIndex = trackLines ? _ctx?._lineIndex ?? (_ctx?._lineStarts ? { lineStarts: _ctx._lineStarts } : lineContext.lineIndex) : void 0;
|
|
6577
|
+
const ctx = _ctx === void 0 ? createParseContext() : { ..._ctx };
|
|
6578
|
+
ctx.trackLines = trackLines;
|
|
6579
|
+
if (lineIndex) ctx._lineIndex = lineIndex;
|
|
6580
|
+
if (lineContext) ctx._lineScannedTo = lineContext.lineScannedTo;
|
|
6581
|
+
if (clearTrivia) {
|
|
6582
|
+
ctx.trivia = void 0;
|
|
6583
|
+
ctx.triviaKindLabels = void 0;
|
|
6584
|
+
} else if (scopeTrivia !== void 0) {
|
|
6585
|
+
ctx.trivia = scopeTrivia;
|
|
6586
|
+
if (scopeLabels) ctx.triviaKindLabels = scopeLabels;
|
|
6587
|
+
}
|
|
6588
|
+
if (forceCaptureTrivia || _ctx?.captureTrivia) ctx.captureTrivia = true;
|
|
6589
|
+
if (ownCaptureMask !== void 0) ctx._triviaCaptureMask = ownCaptureMask;
|
|
6590
|
+
else if (inheritCaptureMask) ctx._triviaCaptureMask = triviaKindMask(_ctx?.triviaKindLabels, captureKinds);
|
|
6591
|
+
if (opaqueRootCapture) ctx._rootTriviaCapture = false;
|
|
6592
|
+
const result = root.parse(input, pos ?? 0, ctx);
|
|
6593
|
+
if (trackLines && _ctx && ctx._lineScannedTo !== void 0) {
|
|
6594
|
+
_ctx._lineScannedTo = Math.max(_ctx._lineScannedTo ?? 0, ctx._lineScannedTo);
|
|
6595
|
+
}
|
|
6596
|
+
return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
|
|
6597
|
+
}
|
|
6598
|
+
};
|
|
6599
|
+
return grammar;
|
|
6600
|
+
}
|
|
6601
|
+
function noTrivia(root) {
|
|
6602
|
+
return parser({ trivia: null }, root);
|
|
6603
|
+
}
|
|
6604
|
+
var _analyzed = /* @__PURE__ */ new WeakSet();
|
|
6605
|
+
function parse(combinator, input, opts = {}) {
|
|
6606
|
+
if (!_analyzed.has(combinator)) {
|
|
6607
|
+
_analyzed.add(combinator);
|
|
6608
|
+
markUnusedValues(combinator);
|
|
6609
|
+
}
|
|
6610
|
+
if (!opts.trackLines && !opts.recover && combinator._def.tag === "grammar" && combinator._meta.grammarScanSkip === void 0) {
|
|
6611
|
+
return combinator.parse(input);
|
|
6612
|
+
}
|
|
6613
|
+
const trackLines = opts.trackLines ?? combinator._meta.grammarTrackLines ?? false;
|
|
6614
|
+
const lineContext = trackLines ? createParseLineContext(input, 0) : void 0;
|
|
6615
|
+
const lineIndex = lineContext?.lineIndex;
|
|
6616
|
+
const _errors = opts.recover ? [] : void 0;
|
|
6617
|
+
const _probe = opts.recover ? { offset: input.length, best: null } : void 0;
|
|
6618
|
+
const grammarTrivia = combinator._meta.grammarTrivia;
|
|
6619
|
+
const grammarScanSkip = combinator._meta.grammarScanSkip;
|
|
6620
|
+
const ctx = createParseContext();
|
|
6621
|
+
ctx.trackLines = trackLines;
|
|
6622
|
+
if (lineIndex) ctx._lineIndex = lineIndex;
|
|
6623
|
+
if (lineContext) ctx._lineScannedTo = lineContext.lineScannedTo;
|
|
6624
|
+
if (grammarTrivia !== void 0) {
|
|
6625
|
+
ctx.trivia = grammarTrivia;
|
|
6626
|
+
if (grammarTrivia._meta.triviaKindLabels) ctx.triviaKindLabels = grammarTrivia._meta.triviaKindLabels;
|
|
6627
|
+
}
|
|
6628
|
+
if (grammarScanSkip !== void 0) ctx.scanSkip = grammarScanSkip;
|
|
6629
|
+
if (_errors !== void 0) ctx._errors = _errors;
|
|
6630
|
+
if (_probe !== void 0) ctx._probe = _probe;
|
|
6631
|
+
const result = combinator.parse(input, 0, ctx);
|
|
6632
|
+
if (!result.ok) return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
|
|
6633
|
+
const withErrors = _errors !== void 0 ? { ...result, errors: _errors, furthestFail: _probe?.best ?? null } : result;
|
|
6634
|
+
return lineIndex ? annotateResultLines(withErrors, normalizeLineIndex(lineIndex)) : withErrors;
|
|
5723
6635
|
}
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
6636
|
+
|
|
6637
|
+
// src/combinators/attempt.ts
|
|
6638
|
+
function containOption(options) {
|
|
6639
|
+
if (options === void 0) return false;
|
|
6640
|
+
for (const key of Object.keys(options)) {
|
|
6641
|
+
if (key !== "contain") throw new TypeError(`attempt(): unknown option ${JSON.stringify(key)}`);
|
|
6642
|
+
}
|
|
6643
|
+
if (options.contain !== void 0 && typeof options.contain !== "boolean") {
|
|
6644
|
+
throw new TypeError("attempt(): `contain` must be a boolean");
|
|
6645
|
+
}
|
|
6646
|
+
return options.contain === true;
|
|
5731
6647
|
}
|
|
5732
|
-
function
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
6648
|
+
function attempt(parser2, options) {
|
|
6649
|
+
const contain = containOption(options);
|
|
6650
|
+
const guardable = parser2._meta.firstSet.kind !== "any" && !matchesEmpty(parser2);
|
|
6651
|
+
let failExpected;
|
|
6652
|
+
return {
|
|
6653
|
+
_tag: "attempt",
|
|
6654
|
+
_meta: parser2._meta,
|
|
6655
|
+
_def: contain ? { tag: "attempt", parser: parser2, contain: true } : { tag: "attempt", parser: parser2 },
|
|
6656
|
+
parse(input, pos, ctx) {
|
|
6657
|
+
if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(parser2, input, pos)) {
|
|
6658
|
+
if (failExpected === void 0) {
|
|
6659
|
+
const e = deriveExpected(parser2);
|
|
6660
|
+
failExpected = e.length > 0 ? e : [parser2._tag];
|
|
6661
|
+
}
|
|
6662
|
+
return { ok: false, expected: failExpected, span: { start: pos, end: pos } };
|
|
6663
|
+
}
|
|
6664
|
+
const mark = saveCstMark(ctx);
|
|
6665
|
+
const log = ctx._triviaLog?.length;
|
|
6666
|
+
const rootLog = ctx._rootTriviaLog?.length;
|
|
6667
|
+
const split = ctx._columnsSplit;
|
|
6668
|
+
const result = parser2.parse(input, pos, ctx);
|
|
6669
|
+
if (result.ok) return result;
|
|
6670
|
+
rollbackCstCapture(ctx, mark);
|
|
6671
|
+
ctx._columnsSplit = split;
|
|
6672
|
+
if (log !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== log) ctx._triviaLog.length = log;
|
|
6673
|
+
if (rootLog !== void 0 && ctx._rootTriviaLog && ctx._rootTriviaLog.length !== rootLog) ctx._rootTriviaLog.length = rootLog;
|
|
6674
|
+
if (result.committed && !contain) return result;
|
|
6675
|
+
return { ok: false, expected: result.expected, span: { start: pos, end: pos } };
|
|
5738
6676
|
}
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
6677
|
+
};
|
|
6678
|
+
}
|
|
6679
|
+
|
|
6680
|
+
// src/table/factor-choice.ts
|
|
6681
|
+
var DERIVED = /* @__PURE__ */ new Set(["_tag", "_meta", "_def", "_parseScalar", "_stickyRegex", "parse"]);
|
|
6682
|
+
function isCombinator(v) {
|
|
6683
|
+
return typeof v === "object" && v !== null && "_def" in v && "_meta" in v;
|
|
6684
|
+
}
|
|
6685
|
+
function sameComb(a, b, depth) {
|
|
6686
|
+
if (a === b) return true;
|
|
6687
|
+
if (depth > 32 || a._tag !== b._tag) return false;
|
|
6688
|
+
for (const k of Object.keys(a)) if (!DERIVED.has(k)) return false;
|
|
6689
|
+
for (const k of Object.keys(b)) if (!DERIVED.has(k)) return false;
|
|
6690
|
+
return sameFields(a._def, b._def, depth, void 0);
|
|
6691
|
+
}
|
|
6692
|
+
function sameValue(u, v, depth) {
|
|
6693
|
+
if (u === v) return true;
|
|
6694
|
+
if (isCombinator(u) && isCombinator(v)) return sameComb(u, v, depth + 1);
|
|
6695
|
+
if (Array.isArray(u) && Array.isArray(v)) return u.length === v.length && u.every((x, i) => sameValue(x, v[i], depth));
|
|
6696
|
+
if (typeof u === "object" && u !== null && typeof v === "object" && v !== null && Object.getPrototypeOf(u) === Object.prototype && Object.getPrototypeOf(v) === Object.prototype) {
|
|
6697
|
+
return sameFields(u, v, depth, void 0);
|
|
5742
6698
|
}
|
|
5743
6699
|
return false;
|
|
5744
6700
|
}
|
|
5745
|
-
function
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
};
|
|
5759
|
-
function unconfirmableReason(def, src) {
|
|
5760
|
-
const declared = def.buildArityUnresolved;
|
|
5761
|
-
if (declared !== void 0 && RESOLVER_REASONS[declared]) return RESOLVER_REASONS[declared];
|
|
5762
|
-
const s = src.trim();
|
|
5763
|
-
const params = s.slice(0, s.indexOf(")") + 1);
|
|
5764
|
-
if (params.includes("...")) return RESOLVER_REASONS["rest-parameter"];
|
|
5765
|
-
if (/\barguments\b/.test(s)) return RESOLVER_REASONS["arguments"];
|
|
5766
|
-
if (/^[A-Za-z_$][\w$]*(\s*\.\s*[A-Za-z_$][\w$]*)?$/.test(s)) {
|
|
5767
|
-
return "it names a binding this build could not resolve to a function declaration";
|
|
6701
|
+
function sameFields(x, y, depth, skip) {
|
|
6702
|
+
const kx = Object.keys(x).filter((k) => k !== skip && x[k] !== void 0);
|
|
6703
|
+
const ky = Object.keys(y).filter((k) => k !== skip && y[k] !== void 0);
|
|
6704
|
+
if (kx.length !== ky.length) return false;
|
|
6705
|
+
for (const k of kx) {
|
|
6706
|
+
if (!(k in y)) return false;
|
|
6707
|
+
const u = x[k];
|
|
6708
|
+
const v = y[k];
|
|
6709
|
+
if (k === "fn" && typeof u === "function" && typeof v === "function" && u !== v) {
|
|
6710
|
+
if (typeof x.fnSrc !== "string" || x.fnSrc === "" || x.fnSrc !== y.fnSrc) return false;
|
|
6711
|
+
continue;
|
|
6712
|
+
}
|
|
6713
|
+
if (!sameValue(u, v, depth)) return false;
|
|
5768
6714
|
}
|
|
5769
|
-
return
|
|
5770
|
-
}
|
|
5771
|
-
function confirmedArityForDef(def) {
|
|
5772
|
-
if (def.buildArity !== void 0) return def.buildArity;
|
|
5773
|
-
const src = buildAnalysisSrc(def);
|
|
5774
|
-
const arity = confirmedBuildArity(src);
|
|
5775
|
-
if (arity !== null) return arity;
|
|
5776
|
-
const subject = `build reducer \`${(def.buildSrc ?? "<runtime fn>").trim().split("\n")[0].slice(0, 60)}\``;
|
|
5777
|
-
recordDegradation({
|
|
5778
|
-
code: "build-arity-unconfirmed",
|
|
5779
|
-
severity: "warn",
|
|
5780
|
-
where: `node("${def.type ?? "<inferred>"}")`,
|
|
5781
|
-
subject,
|
|
5782
|
-
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`,
|
|
5783
|
-
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"
|
|
5784
|
-
});
|
|
5785
|
-
return null;
|
|
5786
|
-
}
|
|
5787
|
-
function buildReadsRaw(def) {
|
|
5788
|
-
if (!def.build) return true;
|
|
5789
|
-
if (def.buildRawUnused === true) return false;
|
|
5790
|
-
const arity = confirmedArityForDef(def);
|
|
5791
|
-
if (arity === null) return true;
|
|
5792
|
-
return arity >= 4;
|
|
5793
|
-
}
|
|
5794
|
-
function buildReadsTrivia(def) {
|
|
5795
|
-
if (!def.build) return true;
|
|
5796
|
-
const arity = confirmedArityForDef(def);
|
|
5797
|
-
if (arity === null) return true;
|
|
5798
|
-
return arity >= 5;
|
|
6715
|
+
return true;
|
|
5799
6716
|
}
|
|
5800
|
-
function
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
if (
|
|
5804
|
-
|
|
6717
|
+
function rewrap(w, body) {
|
|
6718
|
+
const d = w._def;
|
|
6719
|
+
let out;
|
|
6720
|
+
if (d.tag === "leaf") {
|
|
6721
|
+
out = d.cstValue === "source" ? sourceLeaf(body, d.fn) : leaf(body, d.fn);
|
|
6722
|
+
if (d.fnSrc !== void 0) out._def.fnSrc = d.fnSrc;
|
|
6723
|
+
} else if (d.tag === "grammar") {
|
|
6724
|
+
out = d.clearTrivia === true ? noTrivia(body) : parser({ trivia: d.triviaParser ?? null }, body);
|
|
6725
|
+
} else return void 0;
|
|
6726
|
+
return sameFields(d, out._def, 0, "parser") ? out : void 0;
|
|
6727
|
+
}
|
|
6728
|
+
function unusedOf(seq) {
|
|
6729
|
+
return seq._def.tag === "sequence" && seq._def.valueUnused === true;
|
|
6730
|
+
}
|
|
6731
|
+
function never(c) {
|
|
6732
|
+
const t2 = c._def.tag;
|
|
6733
|
+
return t2 === "optional" || t2 === "many";
|
|
6734
|
+
}
|
|
6735
|
+
function factorSharedEnds(d) {
|
|
6736
|
+
const arms = d.parsers;
|
|
6737
|
+
if (arms.length < 2) return void 0;
|
|
6738
|
+
if (d.strategy.tag !== "firstMatch" && d.strategy.tag !== "sharedPrefix") return void 0;
|
|
6739
|
+
if (d.gates.some((g) => g !== null) || d.autoNot.some((a) => a !== null)) return void 0;
|
|
6740
|
+
const shapes = [];
|
|
6741
|
+
for (const arm of arms) {
|
|
6742
|
+
const wrappers = [];
|
|
6743
|
+
let c = arm;
|
|
6744
|
+
while ((c._def.tag === "leaf" || c._def.tag === "grammar") && wrappers.length < 4) {
|
|
6745
|
+
wrappers.push(c);
|
|
6746
|
+
c = c._def.parser;
|
|
6747
|
+
}
|
|
6748
|
+
if (c._def.tag !== "sequence" || c._def.parsers.length < 2) return void 0;
|
|
6749
|
+
shapes.push({ wrappers, terms: c._def.parsers, seq: c });
|
|
6750
|
+
}
|
|
6751
|
+
const first = shapes[0];
|
|
6752
|
+
const n = first.terms.length;
|
|
6753
|
+
for (const s of shapes) {
|
|
6754
|
+
if (s.wrappers.length !== first.wrappers.length || s.terms.length !== n) return void 0;
|
|
6755
|
+
if (unusedOf(s.seq) !== unusedOf(first.seq)) return void 0;
|
|
6756
|
+
for (let j = 0; j < s.wrappers.length; j++) {
|
|
6757
|
+
const a = first.wrappers[j]._def;
|
|
6758
|
+
const b = s.wrappers[j]._def;
|
|
6759
|
+
if (a.tag !== b.tag || !sameFields(a, b, 0, "parser")) return void 0;
|
|
6760
|
+
}
|
|
6761
|
+
}
|
|
6762
|
+
let at = -1;
|
|
6763
|
+
for (let i = 0; i < n; i++) {
|
|
6764
|
+
if (shapes.every((s) => sameComb(s.terms[i], first.terms[i], 0))) continue;
|
|
6765
|
+
if (at >= 0) return void 0;
|
|
6766
|
+
at = i;
|
|
6767
|
+
}
|
|
6768
|
+
if (at < 0) return void 0;
|
|
6769
|
+
for (let i = at + 1; i < n; i++) if (!never(first.terms[i])) return void 0;
|
|
6770
|
+
if (arms.some((a) => mayCommitFailure(a))) return void 0;
|
|
6771
|
+
const middle = choice(...shapes.map((s) => s.terms[at]));
|
|
6772
|
+
if (middle._def.tag === "choice" && middle._def.autoNot.some((a) => a !== null)) return void 0;
|
|
6773
|
+
const st = middle._def.tag === "choice" ? middle._def.strategy : void 0;
|
|
6774
|
+
if (st === void 0 || st.tag !== "firstMatch" && st.tag !== "sharedPrefix" && !(st.tag === "literalsLongestFirst" && st.sortedIndices.every((x, i) => x === i))) return void 0;
|
|
6775
|
+
let out = sequence(
|
|
6776
|
+
...[...first.terms.slice(0, at), middle, ...first.terms.slice(at + 1)]
|
|
6777
|
+
);
|
|
6778
|
+
if (unusedOf(first.seq)) {
|
|
6779
|
+
out._def.valueUnused = true;
|
|
6780
|
+
}
|
|
6781
|
+
for (let j = first.wrappers.length - 1; j >= 0 && out !== void 0; j--) out = rewrap(first.wrappers[j], out);
|
|
6782
|
+
return out === void 0 ? void 0 : attempt(out);
|
|
5805
6783
|
}
|
|
5806
6784
|
|
|
5807
6785
|
// src/compiler/fields.ts
|
|
@@ -5918,6 +6896,7 @@ var OP_SCOPE_PLAIN = 41;
|
|
|
5918
6896
|
var OP_LEX_BODY = 42;
|
|
5919
6897
|
var OP_LEX_PROGRAM = 43;
|
|
5920
6898
|
var OP_SOURCE_LEAF = 44;
|
|
6899
|
+
var OP_RGATE = 45;
|
|
5921
6900
|
var OP_DISPATCH = 25;
|
|
5922
6901
|
var OP_ROUTED = 26;
|
|
5923
6902
|
var OP_NAMES = {
|
|
@@ -5937,6 +6916,7 @@ var OP_NAMES = {
|
|
|
5937
6916
|
[OP_PEEK]: "PEEK",
|
|
5938
6917
|
[OP_LEAF]: "LEAF",
|
|
5939
6918
|
[OP_SOURCE_LEAF]: "SOURCE_LEAF",
|
|
6919
|
+
[OP_RGATE]: "RGATE",
|
|
5940
6920
|
[OP_EMPTY]: "EMPTY",
|
|
5941
6921
|
[OP_LIT_TRACK]: "LIT_TRACK",
|
|
5942
6922
|
[OP_RX_TRACK]: "RX_TRACK",
|
|
@@ -5967,71 +6947,6 @@ var OP_NAMES = {
|
|
|
5967
6947
|
[OP_LEX_PROGRAM]: "LEX_PROGRAM"
|
|
5968
6948
|
};
|
|
5969
6949
|
|
|
5970
|
-
// src/combinators/adjacency.ts
|
|
5971
|
-
function adjacencyOf(p) {
|
|
5972
|
-
return p._def.tag === "adjacency" ? p._def : null;
|
|
5973
|
-
}
|
|
5974
|
-
function adjacencyExpected(def) {
|
|
5975
|
-
if (def.polarity === "adjacent") return "adjacent";
|
|
5976
|
-
return def.kinds === void 0 ? "notAdjacent" : `notAdjacent(${def.kinds.join("|")})`;
|
|
5977
|
-
}
|
|
5978
|
-
function holdsAdjacency(input, cur, ctx, def) {
|
|
5979
|
-
return adjacencyHolds(input, cur, ctx, def.polarity === "notAdjacent", def.kinds);
|
|
5980
|
-
}
|
|
5981
|
-
function adjacencyHolds(input, cur, ctx, negated, kinds) {
|
|
5982
|
-
const end = probeTriviaEnd(input, cur, ctx);
|
|
5983
|
-
if (!negated) return end === cur;
|
|
5984
|
-
if (end === cur) return false;
|
|
5985
|
-
if (kinds === void 0) return true;
|
|
5986
|
-
const want = resolveAdjacencyKindMask(ctx.trivia, kinds);
|
|
5987
|
-
const spec = analyzeLabeledTrivia(ctx.trivia);
|
|
5988
|
-
return (triviaKindMaskAt(input, cur, spec, ctx.state) & want) !== 0;
|
|
5989
|
-
}
|
|
5990
|
-
function adjacencyFail(pos, def) {
|
|
5991
|
-
return { ok: false, expected: [adjacencyExpected(def)], span: { start: pos, end: pos } };
|
|
5992
|
-
}
|
|
5993
|
-
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.";
|
|
5994
|
-
function adjacencyMisuse(polarity) {
|
|
5995
|
-
return new TypeError(`${polarity}(): ${NO_STANDALONE_PARSE}`);
|
|
5996
|
-
}
|
|
5997
|
-
function adjacencyCombinator(def) {
|
|
5998
|
-
const meta = {
|
|
5999
|
-
// Zero-width and never leading (sequence() rejects index 0), so it contributes
|
|
6000
|
-
// no first char. `isZeroWidthAssertion` drops it from a sequence's first-set
|
|
6001
|
-
// rather than letting `any` poison the enclosing choice's dispatch.
|
|
6002
|
-
firstSet: { kind: "any" },
|
|
6003
|
-
canMatchNewline: false,
|
|
6004
|
-
isTrivia: false
|
|
6005
|
-
};
|
|
6006
|
-
return {
|
|
6007
|
-
_tag: "adjacency",
|
|
6008
|
-
_meta: meta,
|
|
6009
|
-
_def: def,
|
|
6010
|
-
parse() {
|
|
6011
|
-
throw adjacencyMisuse(def.polarity);
|
|
6012
|
-
}
|
|
6013
|
-
};
|
|
6014
|
-
}
|
|
6015
|
-
function adjacent() {
|
|
6016
|
-
return adjacencyCombinator({ tag: "adjacency", polarity: "adjacent" });
|
|
6017
|
-
}
|
|
6018
|
-
function notAdjacent(options) {
|
|
6019
|
-
const kinds = options?.kinds;
|
|
6020
|
-
if (kinds !== void 0) {
|
|
6021
|
-
if (!Array.isArray(kinds) || kinds.length === 0) {
|
|
6022
|
-
throw new TypeError("notAdjacent({ kinds }): kinds must be a non-empty array of trivia category names.");
|
|
6023
|
-
}
|
|
6024
|
-
for (const k of kinds) {
|
|
6025
|
-
if (typeof k !== "string" || k.length === 0) {
|
|
6026
|
-
throw new TypeError(`notAdjacent({ kinds }): every kind must be a non-empty string, got ${JSON.stringify(k)}.`);
|
|
6027
|
-
}
|
|
6028
|
-
}
|
|
6029
|
-
}
|
|
6030
|
-
return adjacencyCombinator(
|
|
6031
|
-
kinds === void 0 ? { tag: "adjacency", polarity: "notAdjacent" } : { tag: "adjacency", polarity: "notAdjacent", kinds: [...kinds] }
|
|
6032
|
-
);
|
|
6033
|
-
}
|
|
6034
|
-
|
|
6035
6950
|
// src/combinators/node.ts
|
|
6036
6951
|
function unwrapChild(child) {
|
|
6037
6952
|
return child !== null && typeof child === "object" && child._tag === "leaf" ? child.value : child;
|
|
@@ -6148,42 +7063,6 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
6148
7063
|
};
|
|
6149
7064
|
}
|
|
6150
7065
|
|
|
6151
|
-
// src/combinators/trivia-boundary.ts
|
|
6152
|
-
var MAX_DEPTH = 12;
|
|
6153
|
-
function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
|
|
6154
|
-
if (depth === 0) return true;
|
|
6155
|
-
const d = p._def;
|
|
6156
|
-
switch (d.tag) {
|
|
6157
|
-
// Multi-term forms: the gaps BETWEEN terms are the ambient-trivia positions.
|
|
6158
|
-
case "sequence":
|
|
6159
|
-
return d.parsers.length > 1;
|
|
6160
|
-
case "many":
|
|
6161
|
-
case "oneOrMore":
|
|
6162
|
-
case "sepBy":
|
|
6163
|
-
return true;
|
|
6164
|
-
// Transparent wrappers — they add no position, so ask what they wrap.
|
|
6165
|
-
case "node":
|
|
6166
|
-
case "transform":
|
|
6167
|
-
case "leaf":
|
|
6168
|
-
case "label":
|
|
6169
|
-
case "field":
|
|
6170
|
-
case "token":
|
|
6171
|
-
case "attempt":
|
|
6172
|
-
case "optional":
|
|
6173
|
-
case "expect":
|
|
6174
|
-
case "withCtx":
|
|
6175
|
-
case "recover":
|
|
6176
|
-
case "trivia":
|
|
6177
|
-
return hasOwnTriviaBoundary(d.parser, depth - 1);
|
|
6178
|
-
// An alternation adds no position either, but ONE arm that has one is enough
|
|
6179
|
-
// to make the scope meaningful for this rule.
|
|
6180
|
-
case "choice":
|
|
6181
|
-
return d.parsers.some((a) => hasOwnTriviaBoundary(a, depth - 1));
|
|
6182
|
-
default:
|
|
6183
|
-
return false;
|
|
6184
|
-
}
|
|
6185
|
-
}
|
|
6186
|
-
|
|
6187
7066
|
// src/compiler/direct-projection.ts
|
|
6188
7067
|
function directArrayProjection(fn, fnSrc, arity) {
|
|
6189
7068
|
let source = fnSrc;
|
|
@@ -6404,13 +7283,16 @@ var Encoder = class {
|
|
|
6404
7283
|
}
|
|
6405
7284
|
case "choice": {
|
|
6406
7285
|
for (const arm of node2.arms) if (!emitNode(arm)) return false;
|
|
6407
|
-
const
|
|
6408
|
-
|
|
6409
|
-
|
|
7286
|
+
const final = classifyFinalChoice(
|
|
7287
|
+
node2.parsers,
|
|
7288
|
+
this.refResolver(),
|
|
7289
|
+
node2.cleared ? void 0 : this.activeTrivia
|
|
7290
|
+
);
|
|
7291
|
+
const classes = final.firstSets.map((first, i) => final.nullable[i] ? -1 : this.charClass(first));
|
|
7292
|
+
const exclusive = final.exclusive && classes.every((cls) => cls >= 0);
|
|
7293
|
+
words.push(LEX_NODE_CHOICE, node2.arms.length, exclusive ? 1 : 0, this.expected(node2.expected));
|
|
6410
7294
|
for (let i = 0; i < node2.arms.length; i++) {
|
|
6411
|
-
|
|
6412
|
-
words.push(first.kind === "ranges" ? this.charClass(first) : -1);
|
|
6413
|
-
words.push(this.expected(node2.armExpected[i]));
|
|
7295
|
+
words.push(classes[i], this.expected(node2.armExpected[i]));
|
|
6414
7296
|
}
|
|
6415
7297
|
return true;
|
|
6416
7298
|
}
|
|
@@ -6422,6 +7304,10 @@ var Encoder = class {
|
|
|
6422
7304
|
if (!emitNode(node2.body)) return false;
|
|
6423
7305
|
words.push(LEX_NODE_OPTIONAL);
|
|
6424
7306
|
return true;
|
|
7307
|
+
case "repeat":
|
|
7308
|
+
if (!emitNode(node2.body)) return false;
|
|
7309
|
+
words.push(LEX_NODE_REPEAT, node2.min, node2.max);
|
|
7310
|
+
return true;
|
|
6425
7311
|
}
|
|
6426
7312
|
};
|
|
6427
7313
|
if (!emitNode(body.root)) return void 0;
|
|
@@ -6927,6 +7813,50 @@ var Encoder = class {
|
|
|
6927
7813
|
if (!hasOwnTriviaBoundary(target)) return ip;
|
|
6928
7814
|
return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), ip);
|
|
6929
7815
|
}
|
|
7816
|
+
/**
|
|
7817
|
+
* The `OP_RGATE` operands of a choice arm that opens with `routed()`, or
|
|
7818
|
+
* `undefined`. Through `node()`/scope wrappers and first sequence terms, the
|
|
7819
|
+
* arm's next term after the routed token is found; the gate is that term's
|
|
7820
|
+
* first characters, with the trivia in force at the boundary before it, so
|
|
7821
|
+
* the arm is entered only where it can get past the token. The term must be
|
|
7822
|
+
* unable to match empty or to commit, so a miss is exactly that term failing
|
|
7823
|
+
* at the token's end with its own set.
|
|
7824
|
+
*/
|
|
7825
|
+
routedArmGate(arm) {
|
|
7826
|
+
const walk = (p, trivia2, depth) => {
|
|
7827
|
+
if (depth > 16) return void 0;
|
|
7828
|
+
const d = p._def;
|
|
7829
|
+
switch (d.tag) {
|
|
7830
|
+
case "routed":
|
|
7831
|
+
return "end";
|
|
7832
|
+
case "node":
|
|
7833
|
+
return walk(d.parser, trivia2, depth + 1);
|
|
7834
|
+
case "grammar":
|
|
7835
|
+
return walk(d.parser, d.clearTrivia === true ? void 0 : d.triviaParser ?? trivia2, depth + 1);
|
|
7836
|
+
case "sequence": {
|
|
7837
|
+
const head = d.parsers[0];
|
|
7838
|
+
if (head === void 0) return void 0;
|
|
7839
|
+
const r = walk(head, trivia2, depth + 1);
|
|
7840
|
+
if (r !== "end") return r;
|
|
7841
|
+
const next2 = d.parsers[1];
|
|
7842
|
+
return next2 === void 0 ? "end" : { next: next2, boundary: trivia2 };
|
|
7843
|
+
}
|
|
7844
|
+
default:
|
|
7845
|
+
return void 0;
|
|
7846
|
+
}
|
|
7847
|
+
};
|
|
7848
|
+
const follow = walk(arm, this.activeTrivia, 0);
|
|
7849
|
+
if (follow === void 0 || follow === "end") return void 0;
|
|
7850
|
+
const rr = this.refResolver();
|
|
7851
|
+
const { next, boundary } = follow;
|
|
7852
|
+
if (matchesEmpty(next, /* @__PURE__ */ new Set(), rr) || mayCommitFailure(next, rr, this.commitFailureMemo)) return void 0;
|
|
7853
|
+
const nextTag = next._def.tag;
|
|
7854
|
+
if (nextTag !== "literal" && nextTag !== "regex" && nextTag !== "keywords" && nextTag !== "label") return void 0;
|
|
7855
|
+
const first = firstSetOf(next, /* @__PURE__ */ new Set(), rr, boundary);
|
|
7856
|
+
const cls = this.charClass(boundary === void 0 ? first : union(first, firstSetOf(boundary, /* @__PURE__ */ new Set(), rr)));
|
|
7857
|
+
if (cls < 0) return void 0;
|
|
7858
|
+
return { cls, fx: this.expected(deriveExpected(next)) };
|
|
7859
|
+
}
|
|
6930
7860
|
node(p) {
|
|
6931
7861
|
const lazyRef = p._def.tag === "lazy";
|
|
6932
7862
|
const scopeKey = lazyRef ? this.activeTrivia : void 0;
|
|
@@ -7051,6 +7981,10 @@ var Encoder = class {
|
|
|
7051
7981
|
return head;
|
|
7052
7982
|
}
|
|
7053
7983
|
case "choice": {
|
|
7984
|
+
if (this.plan === void 0) {
|
|
7985
|
+
const factored = factorSharedEnds(d);
|
|
7986
|
+
if (factored !== void 0) return this.node(factored).ip;
|
|
7987
|
+
}
|
|
7054
7988
|
if (d.strategy.tag === "greedyClassify") {
|
|
7055
7989
|
const superIndex = d.strategy.superIndex;
|
|
7056
7990
|
const sup = this.node(d.parsers[superIndex]).ip;
|
|
@@ -7074,9 +8008,12 @@ var Encoder = class {
|
|
|
7074
8008
|
const kids = arms.map((c, k) => {
|
|
7075
8009
|
const src = order[k];
|
|
7076
8010
|
const checks = d.autoNot[src];
|
|
7077
|
-
const inner = this.node(c).ip;
|
|
7078
|
-
const ip = checks === null || checks === void 0 || checks.length === 0 ? inner : this.reject(inner, checks);
|
|
7079
8011
|
const gate = d.gates[src];
|
|
8012
|
+
const plain2 = (checks === null || checks === void 0 || checks.length === 0) && (gate === null || gate === void 0);
|
|
8013
|
+
const routedGate = plain2 ? this.routedArmGate(c) : void 0;
|
|
8014
|
+
const body = this.node(c).ip;
|
|
8015
|
+
const inner = routedGate === void 0 ? body : this.emit(OP_RGATE, routedGate.cls, body, routedGate.fx);
|
|
8016
|
+
const ip = checks === null || checks === void 0 || checks.length === 0 ? inner : this.reject(inner, checks);
|
|
7080
8017
|
const gated = gate === null || gate === void 0 ? ip : this.emit(OP_ARMGATE, this.fn(gate, d.gateSrcs?.[src] ?? null), ip, this.expected(deriveExpected(c)));
|
|
7081
8018
|
return this.covWrap(gated, armCovIds?.[src], 1);
|
|
7082
8019
|
});
|
|
@@ -7400,6 +8337,7 @@ var Encoder = class {
|
|
|
7400
8337
|
const slots = (ip) => {
|
|
7401
8338
|
switch (this.code[ip]) {
|
|
7402
8339
|
case OP_GATE:
|
|
8340
|
+
case OP_RGATE:
|
|
7403
8341
|
return [ip + 2];
|
|
7404
8342
|
case OP_RULE:
|
|
7405
8343
|
case OP_OPT:
|
|
@@ -8627,6 +9565,7 @@ function childSlots(code, ip, out) {
|
|
|
8627
9565
|
case OP_LEAF:
|
|
8628
9566
|
case OP_SOURCE_LEAF:
|
|
8629
9567
|
case OP_ARMGATE:
|
|
9568
|
+
case OP_RGATE:
|
|
8630
9569
|
out.push(code[ip + 2]);
|
|
8631
9570
|
return true;
|
|
8632
9571
|
// `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
|
|
@@ -8710,6 +9649,42 @@ function reachableSites(code, roots) {
|
|
|
8710
9649
|
}
|
|
8711
9650
|
return seen;
|
|
8712
9651
|
}
|
|
9652
|
+
function passCollapse(code, ip, hostCst) {
|
|
9653
|
+
const flags = code[ip + 3];
|
|
9654
|
+
if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return false;
|
|
9655
|
+
if (flags !== 32 && flags !== 34) return false;
|
|
9656
|
+
let at = code[ip + 2];
|
|
9657
|
+
for (let n = 0; n < 8; n++) {
|
|
9658
|
+
const op = code[at];
|
|
9659
|
+
if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[at + 3] === 0) at = code[at + 2];
|
|
9660
|
+
else if (op === OP_RULE) at = code[at + 1];
|
|
9661
|
+
else break;
|
|
9662
|
+
}
|
|
9663
|
+
return code[at] === OP_NODE;
|
|
9664
|
+
}
|
|
9665
|
+
function gatedPassCollapse(code, ip, hostCst) {
|
|
9666
|
+
const flags = code[ip + 3];
|
|
9667
|
+
if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return void 0;
|
|
9668
|
+
if (flags !== 32 && flags !== 34) return void 0;
|
|
9669
|
+
const seq = code[ip + 2];
|
|
9670
|
+
if (code[seq] !== OP_SEQ && code[seq] !== OP_SEQV) return void 0;
|
|
9671
|
+
const n = code[seq + 1];
|
|
9672
|
+
if (n < 2) return void 0;
|
|
9673
|
+
const leads = [];
|
|
9674
|
+
const lits = [];
|
|
9675
|
+
for (let i = 0; i < n - 1; i++) {
|
|
9676
|
+
const t2 = code[seq + 2 + i];
|
|
9677
|
+
if (code[t2] !== OP_OPT && code[t2] !== OP_NOT) return void 0;
|
|
9678
|
+
const g = code[t2 + 1];
|
|
9679
|
+
if (code[g] === OP_GATE) leads.push(g);
|
|
9680
|
+
else if (code[g] === OP_LIT) lits.push(code[g + 1]);
|
|
9681
|
+
else return void 0;
|
|
9682
|
+
}
|
|
9683
|
+
const last = code[seq + 2 + n - 1];
|
|
9684
|
+
let at = last;
|
|
9685
|
+
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];
|
|
9686
|
+
return code[at] === OP_NODE ? { leads, lits, last } : void 0;
|
|
9687
|
+
}
|
|
8713
9688
|
function transfer(code, ip, at, hostCst) {
|
|
8714
9689
|
const op = code[ip];
|
|
8715
9690
|
if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
|
|
@@ -8721,14 +9696,18 @@ function transfer(code, ip, at, hostCst) {
|
|
|
8721
9696
|
}
|
|
8722
9697
|
if (op === OP_NODE || op === OP_NODE_TRACK) {
|
|
8723
9698
|
const flags = code[ip + 3];
|
|
9699
|
+
if (passCollapse(code, ip, hostCst)) return at;
|
|
9700
|
+
const gated = gatedPassCollapse(code, ip, hostCst) !== void 0;
|
|
8724
9701
|
const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && ((flags & ~128) === 2 || flags === 18 || flags === 34);
|
|
8725
9702
|
if (directChildren) {
|
|
8726
|
-
|
|
9703
|
+
const framed2 = { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
|
|
9704
|
+
return gated ? meet(at, framed2) : framed2;
|
|
8727
9705
|
}
|
|
8728
9706
|
const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
|
|
8729
9707
|
const raw = !hostCst && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags & 2) !== 0 ? RAW_OMIT : RAW_CAPTURE;
|
|
8730
9708
|
if (at.buf && raw === at.raw && cap === at.cap) return at;
|
|
8731
|
-
|
|
9709
|
+
const framed = { tri: at.tri, buf: true, raw, cap };
|
|
9710
|
+
return gated ? meet(at, framed) : framed;
|
|
8732
9711
|
}
|
|
8733
9712
|
if (op === OP_TOKEN) {
|
|
8734
9713
|
if (at.tri === TRI_NONE && !at.buf) return at;
|
|
@@ -8766,6 +9745,40 @@ function computeSiteLabels(code, roots, hostCst) {
|
|
|
8766
9745
|
}
|
|
8767
9746
|
return { at: (ip) => labels.get(ip) ?? TOP };
|
|
8768
9747
|
}
|
|
9748
|
+
function scopeIsIdentity(code, ip, at) {
|
|
9749
|
+
const op = code[ip];
|
|
9750
|
+
if (op !== OP_SCOPE_PLAIN && !(op === OP_SCOPE && code[ip + 3] === 0)) return false;
|
|
9751
|
+
const ki = code[ip + 1];
|
|
9752
|
+
return at.tri === (ki < 0 ? TRI_NONE : ki);
|
|
9753
|
+
}
|
|
9754
|
+
function scanHandoffNeeded(code, ip, labels) {
|
|
9755
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9756
|
+
const stack = [ip];
|
|
9757
|
+
const kids = [];
|
|
9758
|
+
while (stack.length > 0) {
|
|
9759
|
+
const at = stack.pop();
|
|
9760
|
+
if (seen.has(at)) continue;
|
|
9761
|
+
seen.add(at);
|
|
9762
|
+
const l = labels.at(at);
|
|
9763
|
+
if (l.tri === TRI_UNKNOWN) return true;
|
|
9764
|
+
const op = code[at];
|
|
9765
|
+
if (op === OP_SCAN) return true;
|
|
9766
|
+
if (op === OP_TOKEN || op === OP_SCOPE_CAP) continue;
|
|
9767
|
+
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;
|
|
9768
|
+
kids.length = 0;
|
|
9769
|
+
if (!childSlots(code, at, kids)) return true;
|
|
9770
|
+
for (const c of kids) stack.push(c);
|
|
9771
|
+
}
|
|
9772
|
+
return false;
|
|
9773
|
+
}
|
|
9774
|
+
function triviaLeadRanges(tri, trivia2) {
|
|
9775
|
+
if (tri === TRI_NONE) return [];
|
|
9776
|
+
if (tri < 0) return void 0;
|
|
9777
|
+
const fs = trivia2[tri]?._meta.firstSet;
|
|
9778
|
+
if (fs === void 0) return void 0;
|
|
9779
|
+
if (fs.kind === "empty") return [];
|
|
9780
|
+
return fs.kind === "ranges" && fs.ranges !== void 0 ? fs.ranges : void 0;
|
|
9781
|
+
}
|
|
8769
9782
|
|
|
8770
9783
|
// src/table/scalar-terminal.ts
|
|
8771
9784
|
function makeScalarRecognizer(op, spec) {
|
|
@@ -8803,6 +9816,12 @@ function scalarTerminalNotChild(code, ip) {
|
|
|
8803
9816
|
const op = code[child];
|
|
8804
9817
|
return op === OP_RX || op === OP_LIT ? child : -1;
|
|
8805
9818
|
}
|
|
9819
|
+
function scalarTerminalPeekChild(code, ip) {
|
|
9820
|
+
if (code[ip] !== OP_PEEK) return -1;
|
|
9821
|
+
const child = code[ip + 1];
|
|
9822
|
+
const op = code[child];
|
|
9823
|
+
return op === OP_RX || op === OP_LIT ? child : -1;
|
|
9824
|
+
}
|
|
8806
9825
|
function leadingScalarTerminal(code, ip, minDepth = 2, throughAttempt = true, throughPeek = false) {
|
|
8807
9826
|
const seen = /* @__PURE__ */ new Set();
|
|
8808
9827
|
let at = ip;
|
|
@@ -8980,6 +9999,59 @@ function leadingTriviaFieldAt(code, k, ip) {
|
|
|
8980
9999
|
return code[ip] === OP_FIELD && (fieldSpec(k[code[ip + 1]]).bits & FIELD_LEADING_TRIVIA) !== 0;
|
|
8981
10000
|
}
|
|
8982
10001
|
|
|
10002
|
+
// src/table/hold-gap.ts
|
|
10003
|
+
var WRAPPERS = /* @__PURE__ */ new Set([
|
|
10004
|
+
OP_NODE,
|
|
10005
|
+
OP_XFORM,
|
|
10006
|
+
OP_LEAF,
|
|
10007
|
+
OP_SOURCE_LEAF,
|
|
10008
|
+
OP_TOKEN,
|
|
10009
|
+
OP_SCOPE,
|
|
10010
|
+
OP_SCOPE_CAP,
|
|
10011
|
+
OP_SCOPE_PLAIN,
|
|
10012
|
+
OP_FIELD,
|
|
10013
|
+
OP_LABEL,
|
|
10014
|
+
OP_EXPECT,
|
|
10015
|
+
OP_WITHCTX,
|
|
10016
|
+
OP_RULE,
|
|
10017
|
+
OP_ATTEMPT,
|
|
10018
|
+
OP_COV
|
|
10019
|
+
]);
|
|
10020
|
+
function rowNullable(code, k, ip, memo) {
|
|
10021
|
+
const hit = memo.get(ip);
|
|
10022
|
+
if (hit !== void 0) return hit;
|
|
10023
|
+
memo.set(ip, true);
|
|
10024
|
+
const op = code[ip];
|
|
10025
|
+
const kids = [];
|
|
10026
|
+
let out = true;
|
|
10027
|
+
if (op === OP_GATE) out = false;
|
|
10028
|
+
else if (op === OP_LIT || op === OP_LIT_CI) out = k[code[ip + 1]].length === 0;
|
|
10029
|
+
else if (op === OP_RX) {
|
|
10030
|
+
const re = k[code[ip + 1]];
|
|
10031
|
+
out = !(re instanceof RegExp) || regexCanMatchEmpty(re.source);
|
|
10032
|
+
} else if (op === OP_SEQ || op === OP_SEQV || op === OP_SEQX) {
|
|
10033
|
+
childSlots(code, ip, kids);
|
|
10034
|
+
out = kids.every((c) => rowNullable(code, k, c, memo));
|
|
10035
|
+
} else if (op === OP_CHOICE) {
|
|
10036
|
+
childSlots(code, ip, kids);
|
|
10037
|
+
out = kids.length === 0 || kids.some((c) => rowNullable(code, k, c, memo));
|
|
10038
|
+
} else if (op === OP_REP || op === OP_REPV) {
|
|
10039
|
+
out = code[ip + 2] === 0 || rowNullable(code, k, code[ip + 1], memo);
|
|
10040
|
+
} else if (WRAPPERS.has(op)) {
|
|
10041
|
+
if (childSlots(code, ip, kids) && kids.length === 1) out = rowNullable(code, k, kids[0], memo);
|
|
10042
|
+
}
|
|
10043
|
+
memo.set(ip, out);
|
|
10044
|
+
return out;
|
|
10045
|
+
}
|
|
10046
|
+
function holdsGap(code, k, base, n, i, memo) {
|
|
10047
|
+
if (i < 1 || i + 1 >= n) return false;
|
|
10048
|
+
const term = code[base + i];
|
|
10049
|
+
if (code[term] !== OP_NOT && code[term] !== OP_PEEK) return false;
|
|
10050
|
+
const next = code[base + i + 1];
|
|
10051
|
+
if (code[next] === OP_ADJ || leadingTriviaFieldAt(code, k, next)) return false;
|
|
10052
|
+
return !rowNullable(code, k, next, memo);
|
|
10053
|
+
}
|
|
10054
|
+
|
|
8983
10055
|
// src/table/emit-assembly.ts
|
|
8984
10056
|
var Unemittable = class extends Error {
|
|
8985
10057
|
construct;
|
|
@@ -9060,7 +10132,10 @@ var EMITTED_PARAMS = [
|
|
|
9060
10132
|
"triviaFieldCapture",
|
|
9061
10133
|
// Appended for the deferred-commit trivia skip (`trivia-gap.ts`); old
|
|
9062
10134
|
// factories ignore it.
|
|
9063
|
-
"skipDeferredTrivia"
|
|
10135
|
+
"skipDeferredTrivia",
|
|
10136
|
+
// Appended for the pass-through collapse (`run-support.ts`); old factories
|
|
10137
|
+
// ignore it.
|
|
10138
|
+
"collapseEmpty"
|
|
9064
10139
|
];
|
|
9065
10140
|
var RUNTIME_PRELUDE = `
|
|
9066
10141
|
let _pfScan=null
|
|
@@ -9257,6 +10332,24 @@ ${fast}
|
|
|
9257
10332
|
${scanned}
|
|
9258
10333
|
}`;
|
|
9259
10334
|
}
|
|
10335
|
+
function emitHoldTerm(callee, dst, t2, l, skip) {
|
|
10336
|
+
const fast = `const ${t2}v=${callee}(input,cur,ctx)
|
|
10337
|
+
if(${t2}v===FAIL)return FAIL
|
|
10338
|
+
${dst}=${t2}v
|
|
10339
|
+
cur=EC.e`;
|
|
10340
|
+
if (l.tri === TRI_NONE) return fast;
|
|
10341
|
+
const held = `const ${t2}s=${skip}(input,cur,ctx)
|
|
10342
|
+
const ${t2}v=${callee}(input,${t2}s,ctx)
|
|
10343
|
+
if(${t2}v===FAIL)return FAIL
|
|
10344
|
+
${dst}=${t2}v
|
|
10345
|
+
cur=${t2}s`;
|
|
10346
|
+
if (l.tri !== TRI_UNKNOWN) return held;
|
|
10347
|
+
return `if(ctx.trivia===undefined){
|
|
10348
|
+
${fast}
|
|
10349
|
+
}else{
|
|
10350
|
+
${held}
|
|
10351
|
+
}`;
|
|
10352
|
+
}
|
|
9260
10353
|
function leadSkip(hasTrivia, leadTrivia, skip) {
|
|
9261
10354
|
if (hasTrivia === "false") return "{}";
|
|
9262
10355
|
const call = `itemStart=${skip}(input,itemStart,ctx)`;
|
|
@@ -9298,6 +10391,7 @@ function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false, s
|
|
|
9298
10391
|
const reachable = [...reachableSites(code, roots)];
|
|
9299
10392
|
const labels = computeSiteLabels(code, roots, hostCst);
|
|
9300
10393
|
const scalarSpecs = /* @__PURE__ */ new Set();
|
|
10394
|
+
const nullable2 = /* @__PURE__ */ new Map();
|
|
9301
10395
|
const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
|
|
9302
10396
|
const largeChoiceLiteralFamilies = /* @__PURE__ */ new Map();
|
|
9303
10397
|
const largeChoiceScalarSequences = /* @__PURE__ */ new Map();
|
|
@@ -9622,9 +10716,7 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
9622
10716
|
const op = code[ip];
|
|
9623
10717
|
if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
|
|
9624
10718
|
if (op === OP_RULE) return code[ip + 1];
|
|
9625
|
-
if ((
|
|
9626
|
-
return code[ip + 2];
|
|
9627
|
-
}
|
|
10719
|
+
if (scopeIsIdentity(code, ip, labels.at(ip))) return code[ip + 2];
|
|
9628
10720
|
return void 0;
|
|
9629
10721
|
}
|
|
9630
10722
|
function lower(ip, fname) {
|
|
@@ -9746,6 +10838,22 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
9746
10838
|
return `${head}
|
|
9747
10839
|
if(${gateMissTest(ip)}){ctx._fe=pos;ctx._fx=${xf};return FAIL}
|
|
9748
10840
|
return ${child}(input,pos,ctx)
|
|
10841
|
+
}`;
|
|
10842
|
+
}
|
|
10843
|
+
case OP_RGATE: {
|
|
10844
|
+
const child = link(code[ip + 2]);
|
|
10845
|
+
if (cfg.tolerant || cfg.probe) return `${head}
|
|
10846
|
+
return ${child}(input,pos,ctx)
|
|
10847
|
+
}`;
|
|
10848
|
+
const resolved = t2.cc[code[ip + 1]];
|
|
10849
|
+
const ci = classes.push([resolved]) - 1;
|
|
10850
|
+
classPlan.push([code[ip + 1]]);
|
|
10851
|
+
const cls = hoist("cl", `CLS[${ci}][0]`);
|
|
10852
|
+
const xf = fxRef(code[ip + 3]);
|
|
10853
|
+
return `${head}
|
|
10854
|
+
const it=ctx._routed
|
|
10855
|
+
if(it!==undefined&&it.span.start===pos&&!classHas(${cls},lead(input,it.span.end))){ctx._fe=it.span.end;ctx._fx=${xf};return FAIL}
|
|
10856
|
+
return ${child}(input,pos,ctx)
|
|
9749
10857
|
}`;
|
|
9750
10858
|
}
|
|
9751
10859
|
case OP_ARMGATE: {
|
|
@@ -10020,23 +11128,33 @@ return FAIL
|
|
|
10020
11128
|
const p = tmp();
|
|
10021
11129
|
return `${head}
|
|
10022
11130
|
${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${emitMark(p, L.buf, L.raw, sinks)}
|
|
10023
|
-
const v=${child}(input,pos,ctx)
|
|
11131
|
+
${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
|
|
10024
11132
|
${emitRollback(p, L.buf, L.raw, sinks)}
|
|
10025
|
-
if(v===FAIL){EC.e=pos;return null}
|
|
11133
|
+
${cfg.probe ? "if(ctx._probe!==undefined)ctx._probe.best=pb??null\n" : ""}if(v===FAIL){EC.e=pos;return null}
|
|
10026
11134
|
ctx._fe=pos
|
|
10027
11135
|
ctx._fx=${xf}
|
|
10028
11136
|
return FAIL
|
|
10029
11137
|
}`;
|
|
10030
11138
|
}
|
|
10031
11139
|
case OP_PEEK: {
|
|
11140
|
+
const scalarChild = scalarTerminalPeekChild(code, ip);
|
|
11141
|
+
if (scalarChild >= 0) {
|
|
11142
|
+
const recognize = recognizerRef(code[scalarChild + 1]);
|
|
11143
|
+
const xf2 = fxRef(code[ip + 2]);
|
|
11144
|
+
return `${head}
|
|
11145
|
+
if(${recognize}(input,pos)<0){ctx._fe=pos;ctx._fx=${xf2};return FAIL}
|
|
11146
|
+
EC.e=pos
|
|
11147
|
+
return null
|
|
11148
|
+
}`;
|
|
11149
|
+
}
|
|
10032
11150
|
const child = link(code[ip + 1]);
|
|
10033
11151
|
const xf = fxRef(code[ip + 2]);
|
|
10034
11152
|
const p = tmp();
|
|
10035
11153
|
return `${head}
|
|
10036
11154
|
${lookaheadMiss(code[ip + 1], `ctx._fe=pos;ctx._fx=${xf};return FAIL`)}${emitMark(p, L.buf, L.raw, sinks)}
|
|
10037
|
-
const v=${child}(input,pos,ctx)
|
|
11155
|
+
${cfg.probe ? "const pb=ctx._probe?.best\n" : ""}const v=${child}(input,pos,ctx)
|
|
10038
11156
|
${emitRollback(p, L.buf, L.raw, sinks)}
|
|
10039
|
-
if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
|
|
11157
|
+
${cfg.probe ? "if(ctx._probe!==undefined)ctx._probe.best=pb??null\n" : ""}if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
|
|
10040
11158
|
EC.e=pos
|
|
10041
11159
|
return null
|
|
10042
11160
|
}`;
|
|
@@ -10107,7 +11225,7 @@ return v
|
|
|
10107
11225
|
);
|
|
10108
11226
|
} else {
|
|
10109
11227
|
const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
|
|
10110
|
-
parts.push(emitTerm(callee, vn, tmp(), L, skipFor(L)));
|
|
11228
|
+
parts.push(holdsGap(code, k, base, n, i, nullable2) ? emitHoldTerm(callee, vn, tmp(), L, skipFor(L)) : emitTerm(callee, vn, tmp(), L, skipFor(L)));
|
|
10111
11229
|
}
|
|
10112
11230
|
names.push(vn);
|
|
10113
11231
|
}
|
|
@@ -10590,6 +11708,26 @@ return nd
|
|
|
10590
11708
|
const trailingTrivia = (flags & 128) !== 0;
|
|
10591
11709
|
const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
|
|
10592
11710
|
const leanFlags = flags & ~128;
|
|
11711
|
+
if (build !== void 0 && passCollapse(code, ip, hostCst)) {
|
|
11712
|
+
return `${head}
|
|
11713
|
+
const v=${child}(input,pos,ctx)
|
|
11714
|
+
if(v!==undefined)return v
|
|
11715
|
+
return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
|
|
11716
|
+
}`;
|
|
11717
|
+
}
|
|
11718
|
+
const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
|
|
11719
|
+
const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(labels.at(code[ip + 2]).tri, t2.trivia);
|
|
11720
|
+
const gp = gated !== void 0 && triviaLead !== void 0 && triviaLead.length <= 16 ? `const gc=lead(input,pos)
|
|
11721
|
+
if(!(${[
|
|
11722
|
+
...gated.leads.map((g) => `!(${gateMissTest(g)})`),
|
|
11723
|
+
...gated.lits.map((i) => `gc===${k[i].codePointAt(0)}`),
|
|
11724
|
+
...triviaLead.map((r) => r.lo === r.hi ? `gc===${r.lo}` : `(gc>=${r.lo}&&gc<=${r.hi})`)
|
|
11725
|
+
].join("||") || "false"})){
|
|
11726
|
+
const gv=${link(gated.last)}(input,pos,ctx)
|
|
11727
|
+
if(gv!==undefined)return gv
|
|
11728
|
+
return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
|
|
11729
|
+
}
|
|
11730
|
+
` : "";
|
|
10593
11731
|
if (!hostCst && !tracked && build !== void 0 && proj < 0 && (leanFlags === 2 || (flags === 18 || flags === 34))) {
|
|
10594
11732
|
const fields = flags === 18;
|
|
10595
11733
|
const collapseChildren = flags === 34;
|
|
@@ -10624,7 +11762,7 @@ sCh.push(nd)
|
|
|
10624
11762
|
if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
|
|
10625
11763
|
}`;
|
|
10626
11764
|
return `${head}
|
|
10627
|
-
const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
11765
|
+
${gp}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
10628
11766
|
const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
|
|
10629
11767
|
const flat=[]
|
|
10630
11768
|
ctx._cstBuf=undefined
|
|
@@ -10699,7 +11837,7 @@ const hostKids=kids
|
|
|
10699
11837
|
const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
|
|
10700
11838
|
const tlog=buf.tl??EMPTY_TLOG`;
|
|
10701
11839
|
return `${head}
|
|
10702
|
-
const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
11840
|
+
${!hostCst && !tracked ? gp : ""}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
10703
11841
|
const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf
|
|
10704
11842
|
${openCapture}
|
|
10705
11843
|
ctx.captureTrivia=${captureWide}
|
|
@@ -10769,9 +11907,15 @@ ext:[${externals.join(",")}],
|
|
|
10769
11907
|
bind:function(xs,ps){_xScan=xs
|
|
10770
11908
|
${externals.map((ip, i) => `_xp${ip}=ps[${i}]`).join("\n")}},
|
|
10771
11909
|
scan:function(s){const o=_pfScan;_pfScan=s;return o}`;
|
|
11910
|
+
const scannerFor = (ip) => {
|
|
11911
|
+
const ki = labels.at(ip).tri;
|
|
11912
|
+
if (ki === TRI_UNKNOWN) return "_pfScan";
|
|
11913
|
+
if (ki === TRI_NONE) return "null";
|
|
11914
|
+
return swapLegal && !triviaLabelled[ki] && t2.triviaScan[ki] != null ? hoist("ts", `TRIVIASCAN[${ki}]`) : "null";
|
|
11915
|
+
};
|
|
10772
11916
|
const externalDefs = select === void 0 ? "" : `let _xScan
|
|
10773
11917
|
${externals.map((ip) => `let _xp${ip}
|
|
10774
|
-
function _px${ip}(input,pos,ctx){const o=_xScan(
|
|
11918
|
+
function _px${ip}(input,pos,ctx){const o=_xScan(${scannerFor(ip)});const v=_xp${ip}(input,pos,ctx);_xScan(o);return v}`).join("\n")}
|
|
10775
11919
|
`;
|
|
10776
11920
|
const source = `${RUNTIME_PRELUDE}${needsNoRawPrelude ? NO_RAW_RUNTIME_PRELUDE : ""}
|
|
10777
11921
|
${prelude.join("\n")}
|
|
@@ -11023,198 +12167,68 @@ function literal(value, opts = {}) {
|
|
|
11023
12167
|
const canMatchNewline = meta.canMatchNewline;
|
|
11024
12168
|
const parseScalar = !caseInsensitive && value.length === 1 ? (() => {
|
|
11025
12169
|
const code = value.charCodeAt(0);
|
|
11026
|
-
return (input, pos, ctx) => {
|
|
11027
|
-
if (input.charCodeAt(pos) === code) {
|
|
11028
|
-
ctx._sv = value;
|
|
11029
|
-
return pos + 1;
|
|
11030
|
-
}
|
|
11031
|
-
ctx._fx = expected;
|
|
11032
|
-
return ~pos;
|
|
11033
|
-
};
|
|
11034
|
-
})() : (input, pos, ctx) => {
|
|
11035
|
-
const end = pos + value.length;
|
|
11036
|
-
if (end <= input.length) {
|
|
11037
|
-
const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
|
|
11038
|
-
if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
|
|
11039
|
-
ctx._sv = matchedValue;
|
|
11040
|
-
return end;
|
|
11041
|
-
}
|
|
11042
|
-
}
|
|
11043
|
-
ctx._fx = expected;
|
|
11044
|
-
return ~pos;
|
|
11045
|
-
};
|
|
11046
|
-
if (caseInsensitive) {
|
|
11047
|
-
const upper = value.toUpperCase();
|
|
11048
|
-
const lower = value.toLowerCase();
|
|
11049
|
-
const firstUpper = upper.codePointAt(0);
|
|
11050
|
-
const firstLower = lower.codePointAt(0);
|
|
11051
|
-
meta.firstSet = firstLower !== void 0 && firstUpper !== void 0 ? firstLower === firstUpper ? { kind: "ranges", ranges: [{ lo: firstLower, hi: firstLower }] } : { kind: "ranges", ranges: [
|
|
11052
|
-
{ lo: firstLower, hi: firstLower },
|
|
11053
|
-
{ lo: firstUpper, hi: firstUpper }
|
|
11054
|
-
] } : firstSet2;
|
|
11055
|
-
}
|
|
11056
|
-
const expected = directTerminalFailureExpected({ tag: "literal", value, caseInsensitive });
|
|
11057
|
-
const parse2 = !caseInsensitive && value.length === 1 ? (() => {
|
|
11058
|
-
const code = value.charCodeAt(0);
|
|
11059
|
-
return function parse3(input, pos, ctx) {
|
|
11060
|
-
if (input.charCodeAt(pos) === code) {
|
|
11061
|
-
const span = { start: pos, end: pos + 1 };
|
|
11062
|
-
if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
|
|
11063
|
-
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
|
|
11064
|
-
return { ok: true, value, span };
|
|
11065
|
-
}
|
|
11066
|
-
return failAt(ctx, expected, pos);
|
|
11067
|
-
};
|
|
11068
|
-
})() : function parse3(input, pos, ctx) {
|
|
11069
|
-
const end = pos + value.length;
|
|
11070
|
-
if (end > input.length) {
|
|
11071
|
-
return failAt(ctx, expected, pos);
|
|
11072
|
-
}
|
|
11073
|
-
const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
|
|
11074
|
-
if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
|
|
11075
|
-
const span = { start: pos, end };
|
|
11076
|
-
if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, end);
|
|
11077
|
-
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: matchedValue, span });
|
|
11078
|
-
return { ok: true, value: matchedValue, span };
|
|
11079
|
-
}
|
|
11080
|
-
return failAt(ctx, expected, pos);
|
|
11081
|
-
};
|
|
11082
|
-
return {
|
|
11083
|
-
_tag: "literal",
|
|
11084
|
-
_meta: meta,
|
|
11085
|
-
_def: { tag: "literal", value, caseInsensitive },
|
|
11086
|
-
_parseScalar: parseScalar,
|
|
11087
|
-
parse: parse2
|
|
11088
|
-
};
|
|
11089
|
-
}
|
|
11090
|
-
|
|
11091
|
-
// src/combinators/sequence.ts
|
|
11092
|
-
function sequence(...parsers) {
|
|
11093
|
-
let adjacency = null;
|
|
11094
|
-
for (let i = 0; i < parsers.length; i++) {
|
|
11095
|
-
const a = adjacencyOf(parsers[i]);
|
|
11096
|
-
if (a === null) continue;
|
|
11097
|
-
if (i === 0) {
|
|
11098
|
-
throw new TypeError(
|
|
11099
|
-
`sequence(): ${a.polarity}() cannot be the FIRST term \u2014 an adjacency assertion tests the gap after the PRECEDING term. Put a concrete term first.`
|
|
11100
|
-
);
|
|
11101
|
-
}
|
|
11102
|
-
;
|
|
11103
|
-
(adjacency ??= Array.from({ length: parsers.length }, () => null))[i] = a;
|
|
11104
|
-
}
|
|
11105
|
-
const hasAdjacency = adjacency !== null;
|
|
11106
|
-
let leading = null;
|
|
11107
|
-
for (let i = 1; i < parsers.length; i++) {
|
|
11108
|
-
if (leadsTrivia(parsers[i])) (leading ??= Array.from({ length: parsers.length }, () => false))[i] = true;
|
|
11109
|
-
}
|
|
11110
|
-
const strictArity = !hasAdjacency && (parsers.length === 2 && !matchesEmpty(parsers[1]) || parsers.length === 3 && parsers.every((p) => !matchesEmpty(p))) ? parsers.length : 0;
|
|
11111
|
-
const meta = {
|
|
11112
|
-
// Union through the nullable prefix — a leading optional()/many() lets a later
|
|
11113
|
-
// term's first char start the sequence. Just `parsers[0]` under-approximates.
|
|
11114
|
-
firstSet: sequenceFirstSet(parsers),
|
|
11115
|
-
canMatchNewline: parsers.some((p) => p._meta.canMatchNewline),
|
|
11116
|
-
isTrivia: false
|
|
11117
|
-
};
|
|
11118
|
-
const def = { tag: "sequence", parsers };
|
|
11119
|
-
const scalarParsers = parsers.map(scalarOf);
|
|
11120
|
-
const parseScalar = (input, pos, ctx) => {
|
|
11121
|
-
let cur = pos;
|
|
11122
|
-
if (strictArity !== 0) {
|
|
11123
|
-
cur = scalarParsers[0](input, cur, ctx);
|
|
11124
|
-
if (cur < 0) return cur;
|
|
11125
|
-
const first = ctx._sv;
|
|
11126
|
-
if (ctx.trivia) cur = advanceTrivia(input, cur, ctx);
|
|
11127
|
-
cur = scalarParsers[1](input, cur, ctx);
|
|
11128
|
-
if (cur < 0) return cur;
|
|
11129
|
-
const second = ctx._sv;
|
|
11130
|
-
if (strictArity === 2) {
|
|
11131
|
-
ctx._sv = def.valueUnused ? void 0 : [first, second];
|
|
11132
|
-
return cur;
|
|
11133
|
-
}
|
|
11134
|
-
if (ctx.trivia) cur = advanceTrivia(input, cur, ctx);
|
|
11135
|
-
cur = scalarParsers[2](input, cur, ctx);
|
|
11136
|
-
if (cur < 0) return cur;
|
|
11137
|
-
ctx._sv = def.valueUnused ? void 0 : [first, second, ctx._sv];
|
|
11138
|
-
return cur;
|
|
11139
|
-
}
|
|
11140
|
-
const values = def.valueUnused ? void 0 : [];
|
|
11141
|
-
for (let i = 0; i < scalarParsers.length; i++) {
|
|
11142
|
-
let termPos = cur;
|
|
11143
|
-
if (i > 0 && ctx.trivia) termPos = advanceTrivia(input, cur, ctx);
|
|
11144
|
-
const end = scalarParsers[i](input, termPos, ctx);
|
|
11145
|
-
if (end < 0) return end;
|
|
11146
|
-
if (values !== void 0) values.push(ctx._sv);
|
|
11147
|
-
if (end > termPos || termPos === cur) cur = end;
|
|
11148
|
-
}
|
|
11149
|
-
ctx._sv = values;
|
|
11150
|
-
return cur;
|
|
11151
|
-
};
|
|
11152
|
-
let followSentinels;
|
|
11153
|
-
return {
|
|
11154
|
-
_tag: "sequence",
|
|
11155
|
-
_meta: meta,
|
|
11156
|
-
_def: def,
|
|
11157
|
-
_parseScalar: hasAdjacency || leading !== null ? void 0 : parseScalar,
|
|
11158
|
-
parse(input, pos, ctx) {
|
|
11159
|
-
const tolerant = ctx._tolerant === true;
|
|
11160
|
-
if (tolerant) {
|
|
11161
|
-
followSentinels ??= parsers.map((_, i) => firstSetSentinel(
|
|
11162
|
-
parsers.slice(i + 1).reduce(
|
|
11163
|
-
(set, parser2) => union(set, firstSetOf(parser2)),
|
|
11164
|
-
{ kind: "empty" }
|
|
11165
|
-
)
|
|
11166
|
-
));
|
|
11167
|
-
}
|
|
11168
|
-
const inheritedSync = ctx._sync;
|
|
11169
|
-
const deferredTrivia = needsDeferredTriviaCommit(ctx);
|
|
11170
|
-
const values = def.valueUnused ? void 0 : [];
|
|
11171
|
-
let cur = pos;
|
|
11172
|
-
try {
|
|
11173
|
-
for (let i = 0; i < parsers.length; i++) {
|
|
11174
|
-
if (tolerant) ctx._sync = followSentinels[i] ?? inheritedSync;
|
|
11175
|
-
const assertion = adjacency?.[i];
|
|
11176
|
-
if (assertion) {
|
|
11177
|
-
if (!holdsAdjacency(input, cur, ctx, assertion)) return adjacencyFail(cur, assertion);
|
|
11178
|
-
if (values !== void 0) values.push(null);
|
|
11179
|
-
continue;
|
|
11180
|
-
}
|
|
11181
|
-
let termPos = cur;
|
|
11182
|
-
const markTlog = deferredTrivia ? cstTlLen(ctx) : 0;
|
|
11183
|
-
const markLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
|
|
11184
|
-
const markRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
11185
|
-
if (ctx.trivia && i > 0) {
|
|
11186
|
-
termPos = deferredTrivia ? commitTriviaScan(scanTriviaCompact(input, cur, ctx)) : advanceTrivia(input, cur, ctx);
|
|
11187
|
-
}
|
|
11188
|
-
const scanTlog = deferredTrivia ? cstTlLen(ctx) : 0;
|
|
11189
|
-
const scanLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
|
|
11190
|
-
const scanRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
11191
|
-
if (leading?.[i] === true) LEAD.at = cur;
|
|
11192
|
-
const result = parsers[i].parse(input, termPos, ctx);
|
|
11193
|
-
if (!result.ok) return result;
|
|
11194
|
-
if (values !== void 0) values.push(result.value);
|
|
11195
|
-
if (result.span.end > termPos || termPos === cur) cur = result.span.end;
|
|
11196
|
-
else if (deferredTrivia) {
|
|
11197
|
-
rollbackScannedTriviaAt(
|
|
11198
|
-
ctx,
|
|
11199
|
-
markTlog,
|
|
11200
|
-
scanTlog,
|
|
11201
|
-
markLog,
|
|
11202
|
-
scanLog,
|
|
11203
|
-
markRootLog,
|
|
11204
|
-
scanRootLog
|
|
11205
|
-
);
|
|
11206
|
-
}
|
|
11207
|
-
}
|
|
11208
|
-
} finally {
|
|
11209
|
-
if (tolerant) ctx._sync = inheritedSync;
|
|
12170
|
+
return (input, pos, ctx) => {
|
|
12171
|
+
if (input.charCodeAt(pos) === code) {
|
|
12172
|
+
ctx._sv = value;
|
|
12173
|
+
return pos + 1;
|
|
11210
12174
|
}
|
|
11211
|
-
|
|
11212
|
-
|
|
11213
|
-
|
|
11214
|
-
|
|
11215
|
-
|
|
11216
|
-
|
|
12175
|
+
ctx._fx = expected;
|
|
12176
|
+
return ~pos;
|
|
12177
|
+
};
|
|
12178
|
+
})() : (input, pos, ctx) => {
|
|
12179
|
+
const end = pos + value.length;
|
|
12180
|
+
if (end <= input.length) {
|
|
12181
|
+
const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
|
|
12182
|
+
if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
|
|
12183
|
+
ctx._sv = matchedValue;
|
|
12184
|
+
return end;
|
|
12185
|
+
}
|
|
12186
|
+
}
|
|
12187
|
+
ctx._fx = expected;
|
|
12188
|
+
return ~pos;
|
|
12189
|
+
};
|
|
12190
|
+
if (caseInsensitive) {
|
|
12191
|
+
const upper = value.toUpperCase();
|
|
12192
|
+
const lower = value.toLowerCase();
|
|
12193
|
+
const firstUpper = upper.codePointAt(0);
|
|
12194
|
+
const firstLower = lower.codePointAt(0);
|
|
12195
|
+
meta.firstSet = firstLower !== void 0 && firstUpper !== void 0 ? firstLower === firstUpper ? { kind: "ranges", ranges: [{ lo: firstLower, hi: firstLower }] } : { kind: "ranges", ranges: [
|
|
12196
|
+
{ lo: firstLower, hi: firstLower },
|
|
12197
|
+
{ lo: firstUpper, hi: firstUpper }
|
|
12198
|
+
] } : firstSet2;
|
|
12199
|
+
}
|
|
12200
|
+
const expected = directTerminalFailureExpected({ tag: "literal", value, caseInsensitive });
|
|
12201
|
+
const parse2 = !caseInsensitive && value.length === 1 ? (() => {
|
|
12202
|
+
const code = value.charCodeAt(0);
|
|
12203
|
+
return function parse3(input, pos, ctx) {
|
|
12204
|
+
if (input.charCodeAt(pos) === code) {
|
|
12205
|
+
const span = { start: pos, end: pos + 1 };
|
|
12206
|
+
if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
|
|
12207
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
|
|
12208
|
+
return { ok: true, value, span };
|
|
12209
|
+
}
|
|
12210
|
+
return failAt(ctx, expected, pos);
|
|
12211
|
+
};
|
|
12212
|
+
})() : function parse3(input, pos, ctx) {
|
|
12213
|
+
const end = pos + value.length;
|
|
12214
|
+
if (end > input.length) {
|
|
12215
|
+
return failAt(ctx, expected, pos);
|
|
12216
|
+
}
|
|
12217
|
+
const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
|
|
12218
|
+
if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
|
|
12219
|
+
const span = { start: pos, end };
|
|
12220
|
+
if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, end);
|
|
12221
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: matchedValue, span });
|
|
12222
|
+
return { ok: true, value: matchedValue, span };
|
|
11217
12223
|
}
|
|
12224
|
+
return failAt(ctx, expected, pos);
|
|
12225
|
+
};
|
|
12226
|
+
return {
|
|
12227
|
+
_tag: "literal",
|
|
12228
|
+
_meta: meta,
|
|
12229
|
+
_def: { tag: "literal", value, caseInsensitive },
|
|
12230
|
+
_parseScalar: parseScalar,
|
|
12231
|
+
parse: parse2
|
|
11218
12232
|
};
|
|
11219
12233
|
}
|
|
11220
12234
|
|
|
@@ -11285,124 +12299,6 @@ function ref() {
|
|
|
11285
12299
|
return slot;
|
|
11286
12300
|
}
|
|
11287
12301
|
|
|
11288
|
-
// src/combinators/token.ts
|
|
11289
|
-
function semanticLeafValue(_ctx, _input, _start, _end, value) {
|
|
11290
|
-
return value;
|
|
11291
|
-
}
|
|
11292
|
-
function sourceLeafValue(ctx, input, start, end, value) {
|
|
11293
|
-
return cstOutputHost(ctx.build) ? input.slice(start, end) : value;
|
|
11294
|
-
}
|
|
11295
|
-
function token(root) {
|
|
11296
|
-
const meta = {
|
|
11297
|
-
firstSet: root._meta.firstSet,
|
|
11298
|
-
canMatchNewline: root._meta.canMatchNewline,
|
|
11299
|
-
isTrivia: false
|
|
11300
|
-
};
|
|
11301
|
-
return {
|
|
11302
|
-
_tag: "token",
|
|
11303
|
-
_meta: meta,
|
|
11304
|
-
_def: { tag: "token", parser: root },
|
|
11305
|
-
parse(input, pos, ctx) {
|
|
11306
|
-
const savedTrivia = ctx.trivia;
|
|
11307
|
-
const savedKinds = ctx.triviaKindLabels;
|
|
11308
|
-
const savedBuf = ctx._cstBuf;
|
|
11309
|
-
const savedChildren = ctx._cstChildren;
|
|
11310
|
-
const savedLeaves = ctx._cstLeaves;
|
|
11311
|
-
const savedRaw = ctx._cstRawChildren;
|
|
11312
|
-
const savedTriviaLog = ctx._cstTriviaLog;
|
|
11313
|
-
const savedOuterTriviaLog = ctx._triviaLog;
|
|
11314
|
-
const savedRootTriviaLog = ctx._rootTriviaLog;
|
|
11315
|
-
const wasCapturing = cstCaptureActive(ctx);
|
|
11316
|
-
ctx.trivia = void 0;
|
|
11317
|
-
ctx.triviaKindLabels = void 0;
|
|
11318
|
-
ctx._cstBuf = void 0;
|
|
11319
|
-
ctx._cstChildren = void 0;
|
|
11320
|
-
ctx._cstLeaves = void 0;
|
|
11321
|
-
ctx._cstRawChildren = void 0;
|
|
11322
|
-
ctx._cstTriviaLog = void 0;
|
|
11323
|
-
ctx._triviaLog = void 0;
|
|
11324
|
-
ctx._rootTriviaLog = void 0;
|
|
11325
|
-
let result;
|
|
11326
|
-
try {
|
|
11327
|
-
result = root.parse(input, pos, ctx);
|
|
11328
|
-
} finally {
|
|
11329
|
-
ctx.trivia = savedTrivia;
|
|
11330
|
-
ctx.triviaKindLabels = savedKinds;
|
|
11331
|
-
ctx._cstBuf = savedBuf;
|
|
11332
|
-
ctx._cstChildren = savedChildren;
|
|
11333
|
-
ctx._cstLeaves = savedLeaves;
|
|
11334
|
-
ctx._cstRawChildren = savedRaw;
|
|
11335
|
-
ctx._cstTriviaLog = savedTriviaLog;
|
|
11336
|
-
ctx._triviaLog = savedOuterTriviaLog;
|
|
11337
|
-
ctx._rootTriviaLog = savedRootTriviaLog;
|
|
11338
|
-
}
|
|
11339
|
-
if (!result.ok) return result;
|
|
11340
|
-
const span = result.span;
|
|
11341
|
-
const value = input.slice(pos, span.end);
|
|
11342
|
-
if (wasCapturing) pushCstLeaf(ctx, { _tag: "leaf", value, span });
|
|
11343
|
-
return { ok: true, value, span };
|
|
11344
|
-
}
|
|
11345
|
-
};
|
|
11346
|
-
}
|
|
11347
|
-
function makeLeaf(root, fn, sourceCstValue) {
|
|
11348
|
-
const cstValue = sourceCstValue ? sourceLeafValue : semanticLeafValue;
|
|
11349
|
-
const meta = {
|
|
11350
|
-
firstSet: root._meta.firstSet,
|
|
11351
|
-
canMatchNewline: root._meta.canMatchNewline,
|
|
11352
|
-
isTrivia: false
|
|
11353
|
-
};
|
|
11354
|
-
return {
|
|
11355
|
-
_tag: "leaf",
|
|
11356
|
-
_meta: meta,
|
|
11357
|
-
_def: {
|
|
11358
|
-
tag: "leaf",
|
|
11359
|
-
parser: root,
|
|
11360
|
-
fn,
|
|
11361
|
-
...sourceCstValue ? { cstValue: "source" } : {}
|
|
11362
|
-
},
|
|
11363
|
-
parse(input, pos, ctx) {
|
|
11364
|
-
const savedBuf = ctx._cstBuf;
|
|
11365
|
-
const savedChildren = ctx._cstChildren;
|
|
11366
|
-
const savedLeaves = ctx._cstLeaves;
|
|
11367
|
-
const savedRaw = ctx._cstRawChildren;
|
|
11368
|
-
const savedTriviaLog = ctx._cstTriviaLog;
|
|
11369
|
-
const savedOuterTriviaLog = ctx._triviaLog;
|
|
11370
|
-
const wasCapturing = cstCaptureActive(ctx);
|
|
11371
|
-
ctx._cstBuf = void 0;
|
|
11372
|
-
ctx._cstChildren = void 0;
|
|
11373
|
-
ctx._cstLeaves = void 0;
|
|
11374
|
-
ctx._cstRawChildren = void 0;
|
|
11375
|
-
ctx._cstTriviaLog = void 0;
|
|
11376
|
-
ctx._triviaLog = void 0;
|
|
11377
|
-
let result;
|
|
11378
|
-
try {
|
|
11379
|
-
result = root.parse(input, pos, ctx);
|
|
11380
|
-
} finally {
|
|
11381
|
-
ctx._cstBuf = savedBuf;
|
|
11382
|
-
ctx._cstChildren = savedChildren;
|
|
11383
|
-
ctx._cstLeaves = savedLeaves;
|
|
11384
|
-
ctx._cstRawChildren = savedRaw;
|
|
11385
|
-
ctx._cstTriviaLog = savedTriviaLog;
|
|
11386
|
-
ctx._triviaLog = savedOuterTriviaLog;
|
|
11387
|
-
}
|
|
11388
|
-
if (!result.ok) return result;
|
|
11389
|
-
const value = fn(result.value, result.span);
|
|
11390
|
-
if (wasCapturing) pushCstLeaf(ctx, {
|
|
11391
|
-
_tag: "leaf",
|
|
11392
|
-
value: cstValue(ctx, input, pos, result.span.end, value),
|
|
11393
|
-
span: result.span
|
|
11394
|
-
});
|
|
11395
|
-
return { ok: true, value, span: result.span };
|
|
11396
|
-
}
|
|
11397
|
-
};
|
|
11398
|
-
}
|
|
11399
|
-
function leaf(root, fn) {
|
|
11400
|
-
return makeLeaf(root, fn, false);
|
|
11401
|
-
}
|
|
11402
|
-
function sourceLeaf(root, fn) {
|
|
11403
|
-
return makeLeaf(root, fn, true);
|
|
11404
|
-
}
|
|
11405
|
-
|
|
11406
12302
|
// src/combinators/scanTo.ts
|
|
11407
12303
|
function resolveScanSkip(explicitSkip, raw, ctx) {
|
|
11408
12304
|
if (raw) return [];
|
|
@@ -11711,37 +12607,120 @@ function clearOf(ranges, input, from, to) {
|
|
|
11711
12607
|
return true;
|
|
11712
12608
|
}
|
|
11713
12609
|
|
|
11714
|
-
// src/table/
|
|
11715
|
-
function
|
|
11716
|
-
|
|
11717
|
-
|
|
11718
|
-
|
|
11719
|
-
|
|
11720
|
-
|
|
11721
|
-
|
|
12610
|
+
// src/table/fail-clean.ts
|
|
12611
|
+
function passChild(code, ip) {
|
|
12612
|
+
switch (code[ip]) {
|
|
12613
|
+
case OP_RULE:
|
|
12614
|
+
case OP_LABEL:
|
|
12615
|
+
case OP_COV:
|
|
12616
|
+
case OP_TOKEN:
|
|
12617
|
+
return code[ip + 1];
|
|
12618
|
+
case OP_GATE:
|
|
12619
|
+
case OP_NODE:
|
|
12620
|
+
case OP_NODE_TRACK:
|
|
12621
|
+
case OP_XFORM:
|
|
12622
|
+
case OP_FIELD:
|
|
12623
|
+
case OP_SCOPE:
|
|
12624
|
+
case OP_SCOPE_CAP:
|
|
12625
|
+
case OP_SCOPE_PLAIN:
|
|
12626
|
+
case OP_WITHCTX:
|
|
12627
|
+
case OP_LEAF:
|
|
12628
|
+
case OP_SOURCE_LEAF:
|
|
12629
|
+
return code[ip + 2];
|
|
12630
|
+
default:
|
|
12631
|
+
return -1;
|
|
11722
12632
|
}
|
|
11723
|
-
return [lo + 1, offset - starts[lo] + 1];
|
|
11724
|
-
}
|
|
11725
|
-
function spanLines(ctx, start, end) {
|
|
11726
|
-
const s = lineCol(ctx, start), e = lineCol(ctx, end);
|
|
11727
|
-
return { start, end, startLine: s[0], startColumn: s[1], endLine: e[0], endColumn: e[1] };
|
|
11728
12633
|
}
|
|
11729
|
-
function
|
|
11730
|
-
|
|
11731
|
-
|
|
11732
|
-
|
|
11733
|
-
|
|
11734
|
-
|
|
11735
|
-
|
|
11736
|
-
|
|
11737
|
-
|
|
12634
|
+
function seqCount(code, ip) {
|
|
12635
|
+
const op = code[ip];
|
|
12636
|
+
return op === OP_SEQ || op === OP_SEQV ? ip + 1 : op === OP_SEQX ? ip + 2 : -1;
|
|
12637
|
+
}
|
|
12638
|
+
function failCleanAnalysis(code) {
|
|
12639
|
+
const cleanAt = new Uint8Array(code.length);
|
|
12640
|
+
const neverAt = new Uint8Array(code.length);
|
|
12641
|
+
const neverFails = (ip) => {
|
|
12642
|
+
const hit = neverAt[ip];
|
|
12643
|
+
if (hit !== 0) return hit === 1;
|
|
12644
|
+
neverAt[ip] = 3;
|
|
12645
|
+
let out = false;
|
|
12646
|
+
const op = code[ip];
|
|
12647
|
+
if (op === OP_OPT || op === OP_EMPTY || op === OP_EXPECT) out = true;
|
|
12648
|
+
else if (op === OP_REP || op === OP_REPV) out = code[ip + 2] === 0;
|
|
12649
|
+
else {
|
|
12650
|
+
const at = seqCount(code, ip);
|
|
12651
|
+
if (at >= 0) {
|
|
12652
|
+
out = true;
|
|
12653
|
+
for (let i = 1, n = code[at]; out && i <= n; i++) out = neverFails(code[at + i]);
|
|
12654
|
+
} else if (op !== OP_GATE) {
|
|
12655
|
+
const c = passChild(code, ip);
|
|
12656
|
+
out = c >= 0 && neverFails(c);
|
|
12657
|
+
}
|
|
12658
|
+
}
|
|
12659
|
+
neverAt[ip] = out ? 1 : 2;
|
|
12660
|
+
return out;
|
|
11738
12661
|
};
|
|
11739
|
-
|
|
11740
|
-
|
|
11741
|
-
|
|
11742
|
-
|
|
11743
|
-
|
|
11744
|
-
|
|
12662
|
+
const clean = (ip) => {
|
|
12663
|
+
const hit = cleanAt[ip];
|
|
12664
|
+
if (hit !== 0) return hit === 1;
|
|
12665
|
+
cleanAt[ip] = 3;
|
|
12666
|
+
let out = false;
|
|
12667
|
+
switch (code[ip]) {
|
|
12668
|
+
// A terminal pushes its leaf only on a match; NOT/PEEK/ATTEMPT restore
|
|
12669
|
+
// their own mark; OPT, EMPTY and EXPECT do not fail uncommitted.
|
|
12670
|
+
case OP_LIT:
|
|
12671
|
+
case OP_RX:
|
|
12672
|
+
case OP_LIT_TRACK:
|
|
12673
|
+
case OP_RX_TRACK:
|
|
12674
|
+
case OP_LIT_CI:
|
|
12675
|
+
case OP_LIT_CI_TRACK:
|
|
12676
|
+
case OP_GUARD:
|
|
12677
|
+
case OP_NOT:
|
|
12678
|
+
case OP_PEEK:
|
|
12679
|
+
case OP_ATTEMPT:
|
|
12680
|
+
case OP_EMPTY:
|
|
12681
|
+
case OP_OPT:
|
|
12682
|
+
case OP_EXPECT:
|
|
12683
|
+
out = true;
|
|
12684
|
+
break;
|
|
12685
|
+
// Min 0 does not fail uncommitted; min 1 fails only with no item kept, and
|
|
12686
|
+
// restores the failed item itself.
|
|
12687
|
+
case OP_REP:
|
|
12688
|
+
case OP_REPV:
|
|
12689
|
+
out = code[ip + 2] <= 1;
|
|
12690
|
+
break;
|
|
12691
|
+
// Only the first term may fail: a later one fails after the terms before it
|
|
12692
|
+
// wrote, and after the trivia scanned in front of it.
|
|
12693
|
+
case OP_SEQ:
|
|
12694
|
+
case OP_SEQV:
|
|
12695
|
+
case OP_SEQX: {
|
|
12696
|
+
const at = seqCount(code, ip);
|
|
12697
|
+
const n = code[at];
|
|
12698
|
+
out = n > 0 && clean(code[at + 1]);
|
|
12699
|
+
for (let i = 2; out && i <= n; i++) out = neverFails(code[at + i]);
|
|
12700
|
+
break;
|
|
12701
|
+
}
|
|
12702
|
+
case OP_CHOICE: {
|
|
12703
|
+
out = true;
|
|
12704
|
+
for (let i = 0, n = code[ip + 2]; out && i < n; i++) out = clean(code[ip + 4 + i]);
|
|
12705
|
+
break;
|
|
12706
|
+
}
|
|
12707
|
+
case OP_ROUTED:
|
|
12708
|
+
out = code[ip + 1] < 0 || clean(code[ip + 1]);
|
|
12709
|
+
break;
|
|
12710
|
+
// An arm's failure and the fallback's are committed; only the selector's is
|
|
12711
|
+
// not, and without a fallback an unknown key fails after the selector wrote.
|
|
12712
|
+
case OP_DISPATCH:
|
|
12713
|
+
out = code[ip + 3] >= 0 && clean(code[ip + 1]);
|
|
12714
|
+
break;
|
|
12715
|
+
default: {
|
|
12716
|
+
const c = passChild(code, ip);
|
|
12717
|
+
out = c >= 0 && clean(c);
|
|
12718
|
+
}
|
|
12719
|
+
}
|
|
12720
|
+
cleanAt[ip] = out ? 1 : 2;
|
|
12721
|
+
return out;
|
|
12722
|
+
};
|
|
12723
|
+
return clean;
|
|
11745
12724
|
}
|
|
11746
12725
|
|
|
11747
12726
|
// src/grammar-metadata.ts
|
|
@@ -11839,12 +12818,6 @@ function hasDirectBuilder(prog) {
|
|
|
11839
12818
|
return false;
|
|
11840
12819
|
}
|
|
11841
12820
|
|
|
11842
|
-
// src/cst/root-trivia-scope.ts
|
|
11843
|
-
var ROOT_TRIVIA_SCOPE_REFUSAL = "parser(): selected root trivia requires classifiedTrivia() for every local trivia scope, or rootCapture: 'opaque'.";
|
|
11844
|
-
function refuseUnclassifiedRootScope(strict) {
|
|
11845
|
-
if (strict === true) throw new TypeError(ROOT_TRIVIA_SCOPE_REFUSAL);
|
|
11846
|
-
}
|
|
11847
|
-
|
|
11848
12821
|
// src/table/cell.ts
|
|
11849
12822
|
var FAIL = /* @__PURE__ */ Symbol("pm.fail");
|
|
11850
12823
|
var newEndCell = () => ({ e: 0 });
|
|
@@ -11895,6 +12868,7 @@ function assemble(t2, prog, cfg) {
|
|
|
11895
12868
|
const swapLegal = !cfg.trackLines;
|
|
11896
12869
|
const hostCst = cfg.hostCst;
|
|
11897
12870
|
const REC = prog.rec === 1 && cfg.tolerant;
|
|
12871
|
+
const PROBE = cfg.probe;
|
|
11898
12872
|
const sentinels = /* @__PURE__ */ new Map();
|
|
11899
12873
|
function sentinelFor(cls) {
|
|
11900
12874
|
if (cls < 0) return void 0;
|
|
@@ -11940,6 +12914,8 @@ function assemble(t2, prog, cfg) {
|
|
|
11940
12914
|
}
|
|
11941
12915
|
const memo = /* @__PURE__ */ new Map();
|
|
11942
12916
|
const reached = /* @__PURE__ */ new Set();
|
|
12917
|
+
const NULLABLE = /* @__PURE__ */ new Map();
|
|
12918
|
+
const CLEAN = REC ? () => false : failCleanAnalysis(code);
|
|
11943
12919
|
function pushLeaf(ctx, value, s, e) {
|
|
11944
12920
|
const lf = { _tag: "leaf", value, span: { start: s, end: e } };
|
|
11945
12921
|
pushCstLeaf(ctx, lf);
|
|
@@ -12138,6 +13114,22 @@ function assemble(t2, prog, cfg) {
|
|
|
12138
13114
|
return node2;
|
|
12139
13115
|
};
|
|
12140
13116
|
}
|
|
13117
|
+
function passCollapseNode(child, build, readsRaw) {
|
|
13118
|
+
return (input, pos, ctx) => {
|
|
13119
|
+
const v = child(input, pos, ctx);
|
|
13120
|
+
if (v !== void 0) return v;
|
|
13121
|
+
return collapseEmpty(ctx, build, input, pos, EC.e, readsRaw);
|
|
13122
|
+
};
|
|
13123
|
+
}
|
|
13124
|
+
function gatedPassCollapseNode(blockers, last, classic, build, readsRaw) {
|
|
13125
|
+
return (input, pos, ctx) => {
|
|
13126
|
+
const c = lead(input, pos);
|
|
13127
|
+
for (let i = 0; i < blockers.length; i++) if (classHas2(blockers[i], c)) return classic(input, pos, ctx);
|
|
13128
|
+
const v = last(input, pos, ctx);
|
|
13129
|
+
if (v !== void 0) return v;
|
|
13130
|
+
return collapseEmpty(ctx, build, input, pos, EC.e, readsRaw);
|
|
13131
|
+
};
|
|
13132
|
+
}
|
|
12141
13133
|
function plainProjectNode(child, projection, type) {
|
|
12142
13134
|
return (input, pos, ctx) => {
|
|
12143
13135
|
const sCh = ctx._cstChildren;
|
|
@@ -12508,21 +13500,27 @@ function assemble(t2, prog, cfg) {
|
|
|
12508
13500
|
}
|
|
12509
13501
|
function dispatchBranch(child, usesRouted) {
|
|
12510
13502
|
if (!usesRouted) {
|
|
12511
|
-
return (input, _pos, selEnd, key,
|
|
12512
|
-
const
|
|
13503
|
+
return (input, _pos, selEnd, key, ctx) => {
|
|
13504
|
+
const need = markCst(ctx);
|
|
13505
|
+
const mRaw = MRAW;
|
|
13506
|
+
const mTl = MTL;
|
|
13507
|
+
const mLv = MLV;
|
|
13508
|
+
const mFl = need ? ctx._fields?.length ?? 0 : 0;
|
|
13509
|
+
const mEr = need ? ctx._errors?.length ?? 0 : 0;
|
|
13510
|
+
const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
13511
|
+
const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
12513
13512
|
const v = child(input, selEnd, ctx);
|
|
12514
13513
|
if (v === FAIL) {
|
|
12515
|
-
|
|
13514
|
+
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
12516
13515
|
ctx._fc = true;
|
|
12517
13516
|
return FAIL;
|
|
12518
13517
|
}
|
|
12519
13518
|
return [key, v];
|
|
12520
13519
|
};
|
|
12521
13520
|
}
|
|
12522
|
-
return (input, pos, selEnd, key,
|
|
13521
|
+
return (input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot) => {
|
|
12523
13522
|
const savedRouted = ctx._routed;
|
|
12524
|
-
|
|
12525
|
-
const mark = saveTriviaMark(ctx);
|
|
13523
|
+
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
12526
13524
|
ctx._routed = { value: key, span: { start: pos, end: selEnd } };
|
|
12527
13525
|
let v;
|
|
12528
13526
|
try {
|
|
@@ -12531,7 +13529,7 @@ function assemble(t2, prog, cfg) {
|
|
|
12531
13529
|
ctx._routed = savedRouted;
|
|
12532
13530
|
}
|
|
12533
13531
|
if (v === FAIL) {
|
|
12534
|
-
|
|
13532
|
+
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
12535
13533
|
ctx._fc = true;
|
|
12536
13534
|
return FAIL;
|
|
12537
13535
|
}
|
|
@@ -12539,12 +13537,12 @@ function assemble(t2, prog, cfg) {
|
|
|
12539
13537
|
};
|
|
12540
13538
|
}
|
|
12541
13539
|
function dispatchArmBlock(start, a0, a1, a2, a3, next) {
|
|
12542
|
-
return (arm, input, pos, selEnd, key,
|
|
12543
|
-
if (arm === start) return a0(input, pos, selEnd, key,
|
|
12544
|
-
if (arm === start + 1) return a1(input, pos, selEnd, key,
|
|
12545
|
-
if (arm === start + 2) return a2(input, pos, selEnd, key,
|
|
12546
|
-
if (arm === start + 3) return a3(input, pos, selEnd, key,
|
|
12547
|
-
return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key,
|
|
13540
|
+
return (arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot) => {
|
|
13541
|
+
if (arm === start) return a0(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
13542
|
+
if (arm === start + 1) return a1(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
13543
|
+
if (arm === start + 2) return a2(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
13544
|
+
if (arm === start + 3) return a3(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
13545
|
+
return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
12548
13546
|
};
|
|
12549
13547
|
}
|
|
12550
13548
|
function trackLinesInto(ctx, input, end) {
|
|
@@ -12563,7 +13561,7 @@ function assemble(t2, prog, cfg) {
|
|
|
12563
13561
|
if (flight !== void 0) return flight.fwd;
|
|
12564
13562
|
const selected = HYBRID?.byIp[ip];
|
|
12565
13563
|
if (selected !== void 0) {
|
|
12566
|
-
const piece2 = hybridPiece(selected);
|
|
13564
|
+
const piece2 = scanHandoffNeeded(code, ip, closureLabels) ? hybridPiece(selected) : selected;
|
|
12567
13565
|
memo.set(ip, piece2);
|
|
12568
13566
|
reached.add(ip);
|
|
12569
13567
|
return piece2;
|
|
@@ -12574,14 +13572,55 @@ function assemble(t2, prog, cfg) {
|
|
|
12574
13572
|
target = p;
|
|
12575
13573
|
} };
|
|
12576
13574
|
inFlight.set(ip, holder);
|
|
12577
|
-
const
|
|
12578
|
-
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);
|
|
13575
|
+
const piece = scopeIsIdentity(code, ip, closureLabels.at(ip)) ? link(code[ip + 2]) : countedPiece(lookaheadLedNode(ip) ?? lower(ip), ip);
|
|
12579
13576
|
inFlight.delete(ip);
|
|
12580
13577
|
holder.set(piece);
|
|
12581
13578
|
memo.set(ip, piece);
|
|
12582
13579
|
reached.add(ip);
|
|
12583
13580
|
return piece;
|
|
12584
13581
|
}
|
|
13582
|
+
let FIRST_DECIDED;
|
|
13583
|
+
let NODE_BODY;
|
|
13584
|
+
const DECIDED = (_input, pos) => {
|
|
13585
|
+
EC.e = pos;
|
|
13586
|
+
return null;
|
|
13587
|
+
};
|
|
13588
|
+
function lookaheadLedNode(ip) {
|
|
13589
|
+
const op = code[ip];
|
|
13590
|
+
if (op !== OP_NODE && op !== OP_NODE_TRACK || hostCst || REC || cfg.probe || cfg.coverage || cfg.trackLines) return void 0;
|
|
13591
|
+
if (passCollapse(code, ip, hostCst) || gatedPassCollapse(code, ip, hostCst) !== void 0) return void 0;
|
|
13592
|
+
const body = code[ip + 2];
|
|
13593
|
+
const bop = code[body];
|
|
13594
|
+
if (bop !== OP_SEQ && bop !== OP_SEQV && bop !== OP_SEQX) return void 0;
|
|
13595
|
+
const base = bop === OP_SEQX ? body + 3 : body + 2;
|
|
13596
|
+
if (code[bop === OP_SEQX ? body + 2 : body + 1] < 2) return void 0;
|
|
13597
|
+
const first = code[base];
|
|
13598
|
+
const negative = code[first] === OP_NOT;
|
|
13599
|
+
const terminal = negative ? scalarTerminalNotChild(code, first) : code[first] === OP_PEEK ? scalarTerminalPeekChild(code, first) : -1;
|
|
13600
|
+
if (terminal < 0) return void 0;
|
|
13601
|
+
const recognize = scalarFor(terminal);
|
|
13602
|
+
const xf = fx[code[first + 2]];
|
|
13603
|
+
FIRST_DECIDED = DECIDED;
|
|
13604
|
+
NODE_BODY = lower(body);
|
|
13605
|
+
const node2 = lower(ip);
|
|
13606
|
+
NODE_BODY = void 0;
|
|
13607
|
+
return negative ? (input, pos, ctx) => {
|
|
13608
|
+
if (recognize(input, pos) >= 0) {
|
|
13609
|
+
ctx._fe = pos;
|
|
13610
|
+
ctx._fx = xf;
|
|
13611
|
+
EC.e = pos;
|
|
13612
|
+
return FAIL;
|
|
13613
|
+
}
|
|
13614
|
+
return node2(input, pos, ctx);
|
|
13615
|
+
} : (input, pos, ctx) => {
|
|
13616
|
+
if (recognize(input, pos) < 0) {
|
|
13617
|
+
ctx._fe = pos;
|
|
13618
|
+
ctx._fx = xf;
|
|
13619
|
+
return FAIL;
|
|
13620
|
+
}
|
|
13621
|
+
return node2(input, pos, ctx);
|
|
13622
|
+
};
|
|
13623
|
+
}
|
|
12585
13624
|
function lower(ip) {
|
|
12586
13625
|
const op = code[ip];
|
|
12587
13626
|
switch (op) {
|
|
@@ -13126,8 +14165,10 @@ function assemble(t2, prog, cfg) {
|
|
|
13126
14165
|
const mEr = need ? ctx._errors?.length ?? 0 : 0;
|
|
13127
14166
|
const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
13128
14167
|
const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14168
|
+
const probeBest = PROBE ? ctx._probe?.best : void 0;
|
|
13129
14169
|
const v = child(input, pos, ctx);
|
|
13130
14170
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14171
|
+
if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
|
|
13131
14172
|
if (v === FAIL) {
|
|
13132
14173
|
EC.e = pos;
|
|
13133
14174
|
return null;
|
|
@@ -13138,6 +14179,20 @@ function assemble(t2, prog, cfg) {
|
|
|
13138
14179
|
};
|
|
13139
14180
|
}
|
|
13140
14181
|
case OP_PEEK: {
|
|
14182
|
+
const scalarChild = scalarTerminalPeekChild(code, ip);
|
|
14183
|
+
if (scalarChild >= 0) {
|
|
14184
|
+
const recognize = scalarFor(scalarChild);
|
|
14185
|
+
const xf2 = fx[code[ip + 2]];
|
|
14186
|
+
return (input, pos, ctx) => {
|
|
14187
|
+
if (recognize(input, pos) < 0) {
|
|
14188
|
+
ctx._fe = pos;
|
|
14189
|
+
ctx._fx = xf2;
|
|
14190
|
+
return FAIL;
|
|
14191
|
+
}
|
|
14192
|
+
EC.e = pos;
|
|
14193
|
+
return null;
|
|
14194
|
+
};
|
|
14195
|
+
}
|
|
13141
14196
|
const child = link(code[ip + 1]);
|
|
13142
14197
|
const xf = fx[code[ip + 2]];
|
|
13143
14198
|
const gate = lookaheadClass(code[ip + 1]);
|
|
@@ -13155,8 +14210,10 @@ function assemble(t2, prog, cfg) {
|
|
|
13155
14210
|
const mEr = need ? ctx._errors?.length ?? 0 : 0;
|
|
13156
14211
|
const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
13157
14212
|
const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14213
|
+
const probeBest = PROBE ? ctx._probe?.best : void 0;
|
|
13158
14214
|
const v = child(input, pos, ctx);
|
|
13159
14215
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14216
|
+
if (PROBE && ctx._probe !== void 0) ctx._probe.best = probeBest ?? null;
|
|
13160
14217
|
if (v === FAIL) {
|
|
13161
14218
|
ctx._fe = pos;
|
|
13162
14219
|
ctx._fx = xf;
|
|
@@ -13169,12 +14226,13 @@ function assemble(t2, prog, cfg) {
|
|
|
13169
14226
|
case OP_OPT: {
|
|
13170
14227
|
const child = link(code[ip + 1]);
|
|
13171
14228
|
const gate = lookaheadClass(code[ip + 1]);
|
|
14229
|
+
const childClean = CLEAN(code[ip + 1]);
|
|
13172
14230
|
return (input, pos, ctx) => {
|
|
13173
14231
|
if (gate !== null && !classHas2(gate, lead(input, pos))) {
|
|
13174
14232
|
EC.e = pos;
|
|
13175
14233
|
return null;
|
|
13176
14234
|
}
|
|
13177
|
-
const need = markCst(ctx);
|
|
14235
|
+
const need = !childClean && markCst(ctx);
|
|
13178
14236
|
const mRaw = MRAW;
|
|
13179
14237
|
const mTl = MTL;
|
|
13180
14238
|
const mLv = MLV;
|
|
@@ -13372,6 +14430,9 @@ function assemble(t2, prog, cfg) {
|
|
|
13372
14430
|
const projection = reducer < 0 ? ~reducer : -1;
|
|
13373
14431
|
const fn = fused && projection < 0 ? fns[reducer] : void 0;
|
|
13374
14432
|
const step = closureLabels.at(ip).buf ? nextTermBuffered : nextTerm;
|
|
14433
|
+
const decided = FIRST_DECIDED;
|
|
14434
|
+
FIRST_DECIDED = void 0;
|
|
14435
|
+
const linkFirst = () => decided ?? link(code[base]);
|
|
13375
14436
|
const runnerBlock = (count, r0, r1, r2, r3, next) => {
|
|
13376
14437
|
if (count === 1) return (input, cur, ctx, values, inherited) => {
|
|
13377
14438
|
cur = r0(input, cur, ctx, inherited);
|
|
@@ -13417,7 +14478,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13417
14478
|
};
|
|
13418
14479
|
};
|
|
13419
14480
|
if (REC) {
|
|
13420
|
-
const first2 =
|
|
14481
|
+
const first2 = linkFirst();
|
|
13421
14482
|
const firstSync = sentinelFor(code[base + n]);
|
|
13422
14483
|
const runnerAt = (i) => {
|
|
13423
14484
|
const sync = sentinelFor(code[base + n + i]);
|
|
@@ -13453,13 +14514,13 @@ function assemble(t2, prog, cfg) {
|
|
|
13453
14514
|
const bindRunners = (start) => {
|
|
13454
14515
|
const count = Math.min(4, n - start);
|
|
13455
14516
|
const at = (offset) => runnerAt(start + offset);
|
|
13456
|
-
const
|
|
14517
|
+
const never2 = () => -1;
|
|
13457
14518
|
return runnerBlock(
|
|
13458
14519
|
count,
|
|
13459
14520
|
at(0),
|
|
13460
|
-
count > 1 ? at(1) :
|
|
13461
|
-
count > 2 ? at(2) :
|
|
13462
|
-
count > 3 ? at(3) :
|
|
14521
|
+
count > 1 ? at(1) : never2,
|
|
14522
|
+
count > 2 ? at(2) : never2,
|
|
14523
|
+
count > 3 ? at(3) : never2,
|
|
13463
14524
|
start + count < n ? bindRunners(start + count) : void 0
|
|
13464
14525
|
);
|
|
13465
14526
|
};
|
|
@@ -13509,15 +14570,31 @@ function assemble(t2, prog, cfg) {
|
|
|
13509
14570
|
let hasAdj = false;
|
|
13510
14571
|
for (let i = 1; i < n; i++) {
|
|
13511
14572
|
const kidIp = code[base + i];
|
|
13512
|
-
if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp)) {
|
|
14573
|
+
if (code[kidIp] === OP_ADJ || leadingTriviaFieldAt(code, k, kidIp) || holdsGap(code, k, base, n, i, NULLABLE)) {
|
|
13513
14574
|
hasAdj = true;
|
|
13514
14575
|
break;
|
|
13515
14576
|
}
|
|
13516
14577
|
}
|
|
13517
14578
|
if (hasAdj) {
|
|
13518
|
-
const first2 =
|
|
14579
|
+
const first2 = linkFirst();
|
|
13519
14580
|
const runnerAt = (i) => {
|
|
13520
14581
|
const kidIp = code[base + i];
|
|
14582
|
+
if (holdsGap(code, k, base, n, i, NULLABLE)) {
|
|
14583
|
+
const kid = link(kidIp);
|
|
14584
|
+
return (input, cur, ctx) => {
|
|
14585
|
+
if (ctx.trivia === void 0) {
|
|
14586
|
+
const v2 = kid(input, cur, ctx);
|
|
14587
|
+
if (v2 === FAIL) return -1;
|
|
14588
|
+
TERMV = v2;
|
|
14589
|
+
return EC.e;
|
|
14590
|
+
}
|
|
14591
|
+
const scanEnd = skipTrivia(input, cur, ctx);
|
|
14592
|
+
const v = kid(input, scanEnd, ctx);
|
|
14593
|
+
if (v === FAIL) return -1;
|
|
14594
|
+
TERMV = v;
|
|
14595
|
+
return scanEnd;
|
|
14596
|
+
};
|
|
14597
|
+
}
|
|
13521
14598
|
if (code[kidIp] !== OP_ADJ) {
|
|
13522
14599
|
const kid = link(kidIp);
|
|
13523
14600
|
if (leadingTriviaFieldAt(code, k, kidIp)) {
|
|
@@ -13542,13 +14619,13 @@ function assemble(t2, prog, cfg) {
|
|
|
13542
14619
|
const bindRunners = (start) => {
|
|
13543
14620
|
const count = Math.min(4, n - start);
|
|
13544
14621
|
const at = (offset) => runnerAt(start + offset);
|
|
13545
|
-
const
|
|
14622
|
+
const never2 = () => -1;
|
|
13546
14623
|
return runnerBlock(
|
|
13547
14624
|
count,
|
|
13548
14625
|
at(0),
|
|
13549
|
-
count > 1 ? at(1) :
|
|
13550
|
-
count > 2 ? at(2) :
|
|
13551
|
-
count > 3 ? at(3) :
|
|
14626
|
+
count > 1 ? at(1) : never2,
|
|
14627
|
+
count > 2 ? at(2) : never2,
|
|
14628
|
+
count > 3 ? at(3) : never2,
|
|
13552
14629
|
start + count < n ? bindRunners(start + count) : void 0
|
|
13553
14630
|
);
|
|
13554
14631
|
};
|
|
@@ -13585,7 +14662,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13585
14662
|
};
|
|
13586
14663
|
}
|
|
13587
14664
|
if (n === 1) {
|
|
13588
|
-
const k0 =
|
|
14665
|
+
const k0 = linkFirst();
|
|
13589
14666
|
if (fused) {
|
|
13590
14667
|
return (input, pos, ctx) => {
|
|
13591
14668
|
const v = k0(input, pos, ctx);
|
|
@@ -13607,7 +14684,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13607
14684
|
};
|
|
13608
14685
|
}
|
|
13609
14686
|
if (n === 2) {
|
|
13610
|
-
const k0 =
|
|
14687
|
+
const k0 = linkFirst(), k1 = link(code[base + 1]);
|
|
13611
14688
|
if (fused) {
|
|
13612
14689
|
return (input, pos, ctx) => {
|
|
13613
14690
|
const v0 = k0(input, pos, ctx);
|
|
@@ -13638,7 +14715,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13638
14715
|
};
|
|
13639
14716
|
}
|
|
13640
14717
|
if (n === 3) {
|
|
13641
|
-
const k0 =
|
|
14718
|
+
const k0 = linkFirst(), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
|
|
13642
14719
|
if (fused) {
|
|
13643
14720
|
return (input, pos, ctx) => {
|
|
13644
14721
|
const v0 = k0(input, pos, ctx);
|
|
@@ -13732,7 +14809,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13732
14809
|
start + count < n ? bind(start + count) : void 0
|
|
13733
14810
|
);
|
|
13734
14811
|
};
|
|
13735
|
-
const first =
|
|
14812
|
+
const first = linkFirst();
|
|
13736
14813
|
const tail = bind(1);
|
|
13737
14814
|
const runDirectTerms = (input, pos, ctx, values) => {
|
|
13738
14815
|
const v0 = first(input, pos, ctx);
|
|
@@ -13771,6 +14848,8 @@ function assemble(t2, prog, cfg) {
|
|
|
13771
14848
|
const n = code[ip + 2];
|
|
13772
14849
|
const choiceFx = fx[code[ip + 3]];
|
|
13773
14850
|
const base = ip + 4;
|
|
14851
|
+
for (let i = 0; i < n; i++) link(code[base + i]);
|
|
14852
|
+
const armsClean = CLEAN(ip);
|
|
13774
14853
|
if (table.exclusive) {
|
|
13775
14854
|
const ascii = table.ascii;
|
|
13776
14855
|
const hi = table.hi;
|
|
@@ -13910,7 +14989,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13910
14989
|
if (n === 3) addGate(g2, 4);
|
|
13911
14990
|
return (input, pos, ctx) => {
|
|
13912
14991
|
const c = lead(input, pos);
|
|
13913
|
-
const need = markCst(ctx);
|
|
14992
|
+
const need = !armsClean && markCst(ctx);
|
|
13914
14993
|
const mRaw = MRAW;
|
|
13915
14994
|
const mTl = MTL;
|
|
13916
14995
|
const mLv = MLV;
|
|
@@ -14127,7 +15206,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14127
15206
|
if (pn !== 0) {
|
|
14128
15207
|
return (input, pos, ctx) => {
|
|
14129
15208
|
const c = lead(input, pos);
|
|
14130
|
-
const need = markCst(ctx);
|
|
15209
|
+
const need = !armsClean && markCst(ctx);
|
|
14131
15210
|
const mRaw = MRAW;
|
|
14132
15211
|
const mTl = MTL;
|
|
14133
15212
|
const mLv = MLV;
|
|
@@ -14184,7 +15263,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14184
15263
|
}
|
|
14185
15264
|
return (input, pos, ctx) => {
|
|
14186
15265
|
const c = lead(input, pos);
|
|
14187
|
-
const need = markCst(ctx);
|
|
15266
|
+
const need = !armsClean && markCst(ctx);
|
|
14188
15267
|
const mRaw = MRAW;
|
|
14189
15268
|
const mTl = MTL;
|
|
14190
15269
|
const mLv = MLV;
|
|
@@ -14232,7 +15311,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14232
15311
|
}
|
|
14233
15312
|
return (input, pos, ctx) => {
|
|
14234
15313
|
const c = lead(input, pos);
|
|
14235
|
-
const need = markCst(ctx);
|
|
15314
|
+
const need = !armsClean && markCst(ctx);
|
|
14236
15315
|
const mRaw = MRAW;
|
|
14237
15316
|
const mTl = MTL;
|
|
14238
15317
|
const mLv = MLV;
|
|
@@ -14286,6 +15365,21 @@ function assemble(t2, prog, cfg) {
|
|
|
14286
15365
|
return lit(input, pos, ctx);
|
|
14287
15366
|
};
|
|
14288
15367
|
}
|
|
15368
|
+
case OP_RGATE: {
|
|
15369
|
+
const cls = cc[code[ip + 1]];
|
|
15370
|
+
const xf = fx[code[ip + 3]];
|
|
15371
|
+
const child = link(code[ip + 2]);
|
|
15372
|
+
if (cfg.tolerant || cfg.probe) return child;
|
|
15373
|
+
return (input, pos, ctx) => {
|
|
15374
|
+
const item = ctx._routed;
|
|
15375
|
+
if (item !== void 0 && item.span.start === pos && !classHas2(cls, lead(input, item.span.end))) {
|
|
15376
|
+
ctx._fe = item.span.end;
|
|
15377
|
+
ctx._fx = xf;
|
|
15378
|
+
return FAIL;
|
|
15379
|
+
}
|
|
15380
|
+
return child(input, pos, ctx);
|
|
15381
|
+
};
|
|
15382
|
+
}
|
|
14289
15383
|
case OP_ARMGATE: {
|
|
14290
15384
|
const pred = fns[code[ip + 1]];
|
|
14291
15385
|
const child = link(code[ip + 2]);
|
|
@@ -14354,6 +15448,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14354
15448
|
const itemClass = !REC && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
|
|
14355
15449
|
const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
|
|
14356
15450
|
const skipBeforeFirst = sepIp < 0 && min === 0;
|
|
15451
|
+
const itemClean = sepIp < 0 && CLEAN(code[ip + 1]) && !rowNullable(code, k, code[ip + 1], NULLABLE);
|
|
14357
15452
|
if (REC) {
|
|
14358
15453
|
const itemFx2 = fx[code[ip + 6]];
|
|
14359
15454
|
const sepSent = sentinelFor(code[ip + 7]);
|
|
@@ -14450,6 +15545,8 @@ function assemble(t2, prog, cfg) {
|
|
|
14450
15545
|
const out = collect ? [] : void 0;
|
|
14451
15546
|
const hasTrivia = ctx.trivia !== void 0;
|
|
14452
15547
|
const needMark = rollbackNeeded(ctx);
|
|
15548
|
+
const markLater = needMark && (!itemClean || hasTrivia);
|
|
15549
|
+
const markFirst = needMark && (!itemClean || hasTrivia && skipBeforeFirst);
|
|
14453
15550
|
const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
|
|
14454
15551
|
let cur = pos;
|
|
14455
15552
|
let count = 0;
|
|
@@ -14457,14 +15554,15 @@ function assemble(t2, prog, cfg) {
|
|
|
14457
15554
|
if (max >= 0 && count >= max) break;
|
|
14458
15555
|
if (sep !== void 0 && count > 0 && count >= min && cur >= input.length) break;
|
|
14459
15556
|
if (count >= min && sep === void 0 && !hasTrivia && gateItems && !itemMayStart(input, cur)) break;
|
|
14460
|
-
|
|
14461
|
-
|
|
14462
|
-
const
|
|
14463
|
-
const
|
|
14464
|
-
const
|
|
14465
|
-
const
|
|
14466
|
-
const
|
|
14467
|
-
const
|
|
15557
|
+
const markIt = count > 0 ? markLater : markFirst;
|
|
15558
|
+
if (markIt) markCst(ctx);
|
|
15559
|
+
const mRaw = markIt ? MRAW : 0;
|
|
15560
|
+
const mTl = markIt ? MTL : 0;
|
|
15561
|
+
const mLv = markIt ? MLV : 0;
|
|
15562
|
+
const mFl = markIt ? ctx._fields?.length ?? 0 : 0;
|
|
15563
|
+
const mEr = markIt ? ctx._errors?.length ?? 0 : 0;
|
|
15564
|
+
const mLog = markIt ? ctx._triviaLog?.length ?? 0 : 0;
|
|
15565
|
+
const mRoot = markIt ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14468
15566
|
let itemStart = cur;
|
|
14469
15567
|
let sepEnd = -1;
|
|
14470
15568
|
const viaRepItem = sep === void 0 && count >= min && (count > 0 || skipBeforeFirst);
|
|
@@ -14476,7 +15574,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14476
15574
|
if (sepLeads) LEAD.at = cur;
|
|
14477
15575
|
const sv = sep(input, sp, ctx);
|
|
14478
15576
|
if (sv === FAIL) {
|
|
14479
|
-
if (
|
|
15577
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14480
15578
|
if (committed3(ctx)) return FAIL;
|
|
14481
15579
|
break;
|
|
14482
15580
|
}
|
|
@@ -14487,25 +15585,25 @@ function assemble(t2, prog, cfg) {
|
|
|
14487
15585
|
itemStart = skipTrivia(input, itemStart, ctx);
|
|
14488
15586
|
}
|
|
14489
15587
|
if (itemStart >= input.length && viaRepItem) {
|
|
14490
|
-
if (
|
|
15588
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14491
15589
|
if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
|
|
14492
15590
|
break;
|
|
14493
15591
|
}
|
|
14494
15592
|
if (count >= min && gateItems && !itemMayStart(input, itemStart)) {
|
|
14495
|
-
if (
|
|
15593
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14496
15594
|
if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
|
|
14497
15595
|
break;
|
|
14498
15596
|
}
|
|
14499
15597
|
ctx._fc = false;
|
|
14500
15598
|
const v = child(input, itemStart, ctx);
|
|
14501
15599
|
if (v === FAIL) {
|
|
14502
|
-
if (
|
|
15600
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14503
15601
|
if (committed3(ctx)) return FAIL;
|
|
14504
15602
|
if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
|
|
14505
15603
|
break;
|
|
14506
15604
|
}
|
|
14507
15605
|
if (EC.e === itemStart && viaRepItem) {
|
|
14508
|
-
if (
|
|
15606
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14509
15607
|
break;
|
|
14510
15608
|
}
|
|
14511
15609
|
if (out !== void 0) out.push(v);
|
|
@@ -14579,7 +15677,14 @@ function assemble(t2, prog, cfg) {
|
|
|
14579
15677
|
const runArm = n === 0 ? void 0 : bindArms(0);
|
|
14580
15678
|
const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted);
|
|
14581
15679
|
return (input, pos, ctx) => {
|
|
14582
|
-
const
|
|
15680
|
+
const need = markCst(ctx);
|
|
15681
|
+
const mRaw = MRAW;
|
|
15682
|
+
const mTl = MTL;
|
|
15683
|
+
const mLv = MLV;
|
|
15684
|
+
const mFl = need ? ctx._fields?.length ?? 0 : 0;
|
|
15685
|
+
const mEr = need ? ctx._errors?.length ?? 0 : 0;
|
|
15686
|
+
const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
15687
|
+
const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14583
15688
|
const selVal = selector(input, pos, ctx);
|
|
14584
15689
|
if (selVal === FAIL) return FAIL;
|
|
14585
15690
|
const selEnd = EC.e;
|
|
@@ -14591,9 +15696,9 @@ function assemble(t2, prog, cfg) {
|
|
|
14591
15696
|
ctx._fx = expected;
|
|
14592
15697
|
return FAIL;
|
|
14593
15698
|
}
|
|
14594
|
-
return runOther(input, pos, selEnd, key,
|
|
15699
|
+
return runOther(input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14595
15700
|
}
|
|
14596
|
-
return runArm(arm, input, pos, selEnd, key,
|
|
15701
|
+
return runArm(arm, input, pos, selEnd, key, ctx, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14597
15702
|
};
|
|
14598
15703
|
}
|
|
14599
15704
|
/* ── node ────────────────────────────────────────────────────────────── */
|
|
@@ -14629,7 +15734,8 @@ function assemble(t2, prog, cfg) {
|
|
|
14629
15734
|
return nd;
|
|
14630
15735
|
};
|
|
14631
15736
|
}
|
|
14632
|
-
const child = link(code[ip + 2]);
|
|
15737
|
+
const child = NODE_BODY ?? link(code[ip + 2]);
|
|
15738
|
+
NODE_BODY = void 0;
|
|
14633
15739
|
const proj = code[ip + 4];
|
|
14634
15740
|
const buildIdx = code[ip + 1];
|
|
14635
15741
|
const type = k[code[ip + 5]];
|
|
@@ -14653,6 +15759,30 @@ function assemble(t2, prog, cfg) {
|
|
|
14653
15759
|
if (build !== void 0 && proj < 0 && flags === 18) {
|
|
14654
15760
|
return childrenOnlyFieldsBuildNode(child, build);
|
|
14655
15761
|
}
|
|
15762
|
+
if (build !== void 0 && passCollapse(code, ip, hostCst)) {
|
|
15763
|
+
return passCollapseNode(child, build, flags === 32);
|
|
15764
|
+
}
|
|
15765
|
+
const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
|
|
15766
|
+
const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(closureLabels.at(code[ip + 2]).tri, trivia2);
|
|
15767
|
+
if (build !== void 0 && gated !== void 0 && triviaLead !== void 0) {
|
|
15768
|
+
const classic = flags === 32 ? collapseBuildNode(child, build) : childrenOnlyCollapseBuildNode(child, build);
|
|
15769
|
+
return gatedPassCollapseNode(
|
|
15770
|
+
[
|
|
15771
|
+
...gated.leads.map((g) => cc[code[g + 1]]),
|
|
15772
|
+
resolveClass(encodeClassSpec([
|
|
15773
|
+
...triviaLead,
|
|
15774
|
+
...gated.lits.map((i) => {
|
|
15775
|
+
const c = k[i].codePointAt(0);
|
|
15776
|
+
return { lo: c, hi: c };
|
|
15777
|
+
})
|
|
15778
|
+
]))
|
|
15779
|
+
],
|
|
15780
|
+
link(gated.last),
|
|
15781
|
+
classic,
|
|
15782
|
+
build,
|
|
15783
|
+
flags === 32
|
|
15784
|
+
);
|
|
15785
|
+
}
|
|
14656
15786
|
if (build !== void 0 && proj < 0 && flags === 32) {
|
|
14657
15787
|
return collapseBuildNode(child, build);
|
|
14658
15788
|
}
|
|
@@ -14801,6 +15931,8 @@ function assemble(t2, prog, cfg) {
|
|
|
14801
15931
|
}
|
|
14802
15932
|
const notChild = scalarTerminalNotChild(code, ip);
|
|
14803
15933
|
if (notChild >= 0) scalarFor(notChild);
|
|
15934
|
+
const peekChild = scalarTerminalPeekChild(code, ip);
|
|
15935
|
+
if (peekChild >= 0) scalarFor(peekChild);
|
|
14804
15936
|
}
|
|
14805
15937
|
const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
|
|
14806
15938
|
if (pre !== void 0) {
|
|
@@ -14860,7 +15992,8 @@ function assemble(t2, prog, cfg) {
|
|
|
14860
15992
|
t2.lexPrograms,
|
|
14861
15993
|
LEAD,
|
|
14862
15994
|
triviaFieldCapture,
|
|
14863
|
-
skipDeferredTrivia
|
|
15995
|
+
skipDeferredTrivia,
|
|
15996
|
+
collapseEmpty
|
|
14864
15997
|
);
|
|
14865
15998
|
emitReached = new Set(pre.reached);
|
|
14866
15999
|
if (emitted.ext !== void 0) HYBRID = emitted;
|
|
@@ -14946,7 +16079,8 @@ function assemble(t2, prog, cfg) {
|
|
|
14946
16079
|
t2.lexPrograms,
|
|
14947
16080
|
LEAD,
|
|
14948
16081
|
triviaFieldCapture,
|
|
14949
|
-
skipDeferredTrivia
|
|
16082
|
+
skipDeferredTrivia,
|
|
16083
|
+
collapseEmpty
|
|
14950
16084
|
);
|
|
14951
16085
|
emitReached = em.reached;
|
|
14952
16086
|
} catch (e) {
|
|
@@ -15213,7 +16347,7 @@ function emitClassPool(classes) {
|
|
|
15213
16347
|
if (classes.length < 2) return array;
|
|
15214
16348
|
const delimiter = "|/~?^`".split("").find((ch2) => classes.every((spec) => !spec.includes(ch2)));
|
|
15215
16349
|
if (delimiter === void 0) return array;
|
|
15216
|
-
const split =
|
|
16350
|
+
const split = `/* @__PURE__ */ ${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
|
|
15217
16351
|
return split.length < array.length ? split : array;
|
|
15218
16352
|
}
|
|
15219
16353
|
function emitConst(v) {
|
|
@@ -16820,339 +17954,85 @@ function reportDuplication(opt, analyze) {
|
|
|
16820
17954
|
if (level === "error") throw new Error(`parseman: ${duplicationFindingCount(report)} duplication/overlap finding(s)
|
|
16821
17955
|
${lines2.join("\n")}`);
|
|
16822
17956
|
for (const l of lines2) console.warn(l);
|
|
16823
|
-
}
|
|
16824
|
-
return report;
|
|
16825
|
-
}
|
|
16826
|
-
function runDuplicationDiagnostic(combinator, opt) {
|
|
16827
|
-
return reportDuplication(opt, (o) => analyzeDuplication(combinator, o));
|
|
16828
|
-
}
|
|
16829
|
-
function runDuplicationDiagnosticRules(ruleMap, opt) {
|
|
16830
|
-
return reportDuplication(opt, (o) => analyzeDuplicationRules(ruleMap, o));
|
|
16831
|
-
}
|
|
16832
|
-
|
|
16833
|
-
// src/table/compile-rule-map.ts
|
|
16834
|
-
function resolveHostMode(ruleMap, explicit) {
|
|
16835
|
-
return explicit ?? ruleMap.map(([, r]) => r._meta.grammarHostMode).find(Boolean) ?? "ast";
|
|
16836
|
-
}
|
|
16837
|
-
function resolveTrackLines(ruleMap, explicit) {
|
|
16838
|
-
return explicit === true || ruleMap.some(([, r]) => r._meta.grammarTrackLines === true);
|
|
16839
|
-
}
|
|
16840
|
-
function withAmbient(ruleMap, opts) {
|
|
16841
|
-
if (opts.trivia === void 0 && opts.scanSkip === void 0) return ruleMap;
|
|
16842
|
-
const wrappers = /* @__PURE__ */ new Map();
|
|
16843
|
-
return ruleMap.map(([name, rule2]) => {
|
|
16844
|
-
if (rule2._meta.isTrivia) return [name, rule2];
|
|
16845
|
-
const addTrivia = opts.trivia !== void 0 && rule2._meta.grammarTrivia === void 0;
|
|
16846
|
-
const addScanSkip = opts.scanSkip !== void 0 && rule2._meta.grammarScanSkip === void 0;
|
|
16847
|
-
if (!addTrivia && !addScanSkip) return [name, rule2];
|
|
16848
|
-
let wrapped = wrappers.get(rule2);
|
|
16849
|
-
if (wrapped === void 0) {
|
|
16850
|
-
wrapped = {
|
|
16851
|
-
...rule2,
|
|
16852
|
-
_meta: {
|
|
16853
|
-
...rule2._meta,
|
|
16854
|
-
...addTrivia ? { grammarTrivia: opts.trivia } : {},
|
|
16855
|
-
...addScanSkip ? { grammarScanSkip: opts.scanSkip } : {}
|
|
16856
|
-
}
|
|
16857
|
-
};
|
|
16858
|
-
wrappers.set(rule2, wrapped);
|
|
16859
|
-
}
|
|
16860
|
-
return [name, wrapped];
|
|
16861
|
-
});
|
|
16862
|
-
}
|
|
16863
|
-
function compileRuleMapRunnable(ruleMap, opts = {}) {
|
|
16864
|
-
const encoded = encodeForRun(ruleMap, opts);
|
|
16865
|
-
if (encoded === null) return null;
|
|
16866
|
-
const { prog, hostMode, plan } = encoded;
|
|
16867
|
-
const artifact = closureArtifact(prog);
|
|
16868
|
-
const reflection = collectGrammarReflection(ruleMap);
|
|
16869
|
-
return {
|
|
16870
|
-
keys: ruleMap.map(([key]) => key),
|
|
16871
|
-
hostMode,
|
|
16872
|
-
hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule2]) => hasDirectBuildDef(rule2)),
|
|
16873
|
-
reflection,
|
|
16874
|
-
...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
|
|
16875
|
-
// Reflection rides on the map's metadata prototype from birth. Only `compile()`
|
|
16876
|
-
// asks to specialise; every other caller runs the closure artifact.
|
|
16877
|
-
rules: tableRules(opts.specialise === true ? prog : artifact, { [GRAMMAR_REFLECTION]: reflection }),
|
|
16878
|
-
prog: artifact
|
|
16879
|
-
};
|
|
16880
|
-
}
|
|
16881
|
-
function encodeForRun(ruleMap, opts) {
|
|
16882
|
-
runDuplicationDiagnosticRules(ruleMap, opts.duplication);
|
|
16883
|
-
const encodeMap = withAmbient(ruleMap, opts);
|
|
16884
|
-
const plan = opts.coverage === true ? buildGrammarPlan(
|
|
16885
|
-
encodeMap.map(([, rule2]) => rule2),
|
|
16886
|
-
Object.fromEntries(encodeMap.filter(([, rule2]) => rule2._def.tag !== "lazy"))
|
|
16887
|
-
) : void 0;
|
|
16888
|
-
const hostMode = resolveHostMode(ruleMap, opts.hostMode);
|
|
16889
|
-
const settings = {
|
|
16890
|
-
hostMode,
|
|
16891
|
-
...resolveTrackLines(ruleMap, opts.trackLines) ? { trackLines: true } : {},
|
|
16892
|
-
...opts.recovery === true ? { recovery: true } : {},
|
|
16893
|
-
...plan === void 0 ? {} : { coverage: plan }
|
|
16894
|
-
};
|
|
16895
|
-
try {
|
|
16896
|
-
const { prog, fnSrcs } = encodeTableProgram(Object.fromEntries(encodeMap), settings);
|
|
16897
|
-
return { prog, fnSrcs, hostMode, plan };
|
|
16898
|
-
} catch (e) {
|
|
16899
|
-
opts.refusals?.push(e instanceof Error ? e.message : String(e));
|
|
16900
|
-
return null;
|
|
16901
|
-
}
|
|
16902
|
-
}
|
|
16903
|
-
|
|
16904
|
-
// src/compiler/value-usage.ts
|
|
16905
|
-
function markUnusedValues(root) {
|
|
16906
|
-
const seenConsumed = /* @__PURE__ */ new WeakSet();
|
|
16907
|
-
const seenUnconsumed = /* @__PURE__ */ new WeakSet();
|
|
16908
|
-
const mark = (def, consumed) => {
|
|
16909
|
-
if (consumed) def.valueUnused = false;
|
|
16910
|
-
else if (def.valueUnused !== false) def.valueUnused = true;
|
|
16911
|
-
};
|
|
16912
|
-
const visit = (c, consumed) => {
|
|
16913
|
-
const seen = consumed ? seenConsumed : seenUnconsumed;
|
|
16914
|
-
if (seen.has(c)) return;
|
|
16915
|
-
seen.add(c);
|
|
16916
|
-
const def = c._def;
|
|
16917
|
-
switch (def.tag) {
|
|
16918
|
-
case "many":
|
|
16919
|
-
case "oneOrMore":
|
|
16920
|
-
mark(def, consumed);
|
|
16921
|
-
visit(def.parser, consumed);
|
|
16922
|
-
return;
|
|
16923
|
-
case "optional":
|
|
16924
|
-
visit(def.parser, consumed);
|
|
16925
|
-
return;
|
|
16926
|
-
case "sequence":
|
|
16927
|
-
mark(def, consumed);
|
|
16928
|
-
for (const p of def.parsers) visit(p, consumed);
|
|
16929
|
-
return;
|
|
16930
|
-
case "choice":
|
|
16931
|
-
for (const p of def.parsers) visit(p, consumed);
|
|
16932
|
-
return;
|
|
16933
|
-
case "dispatch":
|
|
16934
|
-
visit(def.selector, consumed);
|
|
16935
|
-
for (const entry of def.cases) visit(entry.parser, consumed);
|
|
16936
|
-
if (def.matchers) for (const entry of def.matchers) visit(entry.parser, consumed);
|
|
16937
|
-
if (def.otherwise) visit(def.otherwise, consumed);
|
|
16938
|
-
return;
|
|
16939
|
-
case "node":
|
|
16940
|
-
visit(def.parser, false);
|
|
16941
|
-
return;
|
|
16942
|
-
case "transform":
|
|
16943
|
-
visit(def.parser, true);
|
|
16944
|
-
return;
|
|
16945
|
-
case "field":
|
|
16946
|
-
visit(def.parser, true);
|
|
16947
|
-
return;
|
|
16948
|
-
case "sepBy":
|
|
16949
|
-
visit(def.parser, true);
|
|
16950
|
-
visit(def.separator, false);
|
|
16951
|
-
return;
|
|
16952
|
-
case "not":
|
|
16953
|
-
case "peek":
|
|
16954
|
-
visit(def.parser, false);
|
|
16955
|
-
return;
|
|
16956
|
-
case "grammar":
|
|
16957
|
-
visit(def.parser, consumed);
|
|
16958
|
-
if (def.triviaParser) visit(def.triviaParser, false);
|
|
16959
|
-
return;
|
|
16960
|
-
case "recover":
|
|
16961
|
-
visit(def.parser, consumed);
|
|
16962
|
-
visit(def.sentinel, false);
|
|
16963
|
-
return;
|
|
16964
|
-
case "token":
|
|
16965
|
-
visit(def.parser, false);
|
|
16966
|
-
return;
|
|
16967
|
-
case "label":
|
|
16968
|
-
case "trivia":
|
|
16969
|
-
case "attempt":
|
|
16970
|
-
case "withCtx":
|
|
16971
|
-
case "expect":
|
|
16972
|
-
visit(def.parser, consumed);
|
|
16973
|
-
return;
|
|
16974
|
-
case "leaf":
|
|
16975
|
-
visit(def.parser, true);
|
|
16976
|
-
return;
|
|
16977
|
-
case "lazy":
|
|
16978
|
-
return;
|
|
16979
|
-
default:
|
|
16980
|
-
return;
|
|
16981
|
-
}
|
|
16982
|
-
};
|
|
16983
|
-
const resolveRoot = (c) => {
|
|
16984
|
-
const guard = /* @__PURE__ */ new Set();
|
|
16985
|
-
let cur = c;
|
|
16986
|
-
while (!guard.has(cur)) {
|
|
16987
|
-
const d = cur._def;
|
|
16988
|
-
if (d.tag === "grammar") {
|
|
16989
|
-
guard.add(cur);
|
|
16990
|
-
cur = d.parser;
|
|
16991
|
-
continue;
|
|
16992
|
-
}
|
|
16993
|
-
if (d.tag !== "lazy") return cur;
|
|
16994
|
-
guard.add(cur);
|
|
16995
|
-
try {
|
|
16996
|
-
cur = d.thunk();
|
|
16997
|
-
} catch {
|
|
16998
|
-
return c;
|
|
16999
|
-
}
|
|
17000
|
-
}
|
|
17001
|
-
return cur;
|
|
17002
|
-
};
|
|
17003
|
-
visit(resolveRoot(root), true);
|
|
17957
|
+
}
|
|
17958
|
+
return report;
|
|
17959
|
+
}
|
|
17960
|
+
function runDuplicationDiagnostic(combinator, opt) {
|
|
17961
|
+
return reportDuplication(opt, (o) => analyzeDuplication(combinator, o));
|
|
17962
|
+
}
|
|
17963
|
+
function runDuplicationDiagnosticRules(ruleMap, opt) {
|
|
17964
|
+
return reportDuplication(opt, (o) => analyzeDuplicationRules(ruleMap, o));
|
|
17004
17965
|
}
|
|
17005
17966
|
|
|
17006
|
-
// src/
|
|
17007
|
-
function
|
|
17008
|
-
|
|
17009
|
-
const errors = annotated.errors;
|
|
17010
|
-
if (errors) {
|
|
17011
|
-
;
|
|
17012
|
-
annotated.errors = errors.map((error) => ({
|
|
17013
|
-
...error,
|
|
17014
|
-
span: annotateSpan(error.span, index)
|
|
17015
|
-
}));
|
|
17016
|
-
}
|
|
17017
|
-
return annotated;
|
|
17967
|
+
// src/table/compile-rule-map.ts
|
|
17968
|
+
function resolveHostMode(ruleMap, explicit) {
|
|
17969
|
+
return explicit ?? ruleMap.map(([, r]) => r._meta.grammarHostMode).find(Boolean) ?? "ast";
|
|
17018
17970
|
}
|
|
17019
|
-
function
|
|
17020
|
-
|
|
17021
|
-
if (pos > 0) recordLineRange(lineIndex, input, 0, pos);
|
|
17022
|
-
return { lineIndex, lineScannedTo: pos };
|
|
17971
|
+
function resolveTrackLines(ruleMap, explicit) {
|
|
17972
|
+
return explicit === true || ruleMap.some(([, r]) => r._meta.grammarTrackLines === true);
|
|
17023
17973
|
}
|
|
17024
|
-
|
|
17025
|
-
|
|
17026
|
-
|
|
17027
|
-
|
|
17028
|
-
|
|
17029
|
-
|
|
17030
|
-
|
|
17031
|
-
|
|
17032
|
-
|
|
17033
|
-
|
|
17034
|
-
|
|
17035
|
-
|
|
17036
|
-
|
|
17037
|
-
|
|
17038
|
-
|
|
17039
|
-
|
|
17040
|
-
const ownCaptureMask = captureKinds === void 0 ? void 0 : scopeLabels !== void 0 ? triviaKindMask(scopeLabels, captureKinds) : void 0;
|
|
17041
|
-
const inheritCaptureMask = captureKinds !== void 0 && scopeLabels === void 0;
|
|
17042
|
-
const rootScalar = scalarOf(root);
|
|
17043
|
-
const scalarEligible = opts.trackLines !== true && opts.recover !== true && !opaqueRootCapture && !forceCaptureTrivia && captureKinds === void 0;
|
|
17044
|
-
const parseScalar = scalarEligible ? (input, pos, ctx) => {
|
|
17045
|
-
const savedTrivia = ctx.trivia;
|
|
17046
|
-
const savedLabels = ctx.triviaKindLabels;
|
|
17047
|
-
if (clearTrivia) {
|
|
17048
|
-
ctx.trivia = void 0;
|
|
17049
|
-
ctx.triviaKindLabels = void 0;
|
|
17050
|
-
} else if (scopeTrivia !== void 0) {
|
|
17051
|
-
ctx.trivia = scopeTrivia;
|
|
17052
|
-
ctx.triviaKindLabels = scopeLabels;
|
|
17053
|
-
}
|
|
17054
|
-
const end = rootScalar(input, pos, ctx);
|
|
17055
|
-
ctx.trivia = savedTrivia;
|
|
17056
|
-
ctx.triviaKindLabels = savedLabels;
|
|
17057
|
-
return end;
|
|
17058
|
-
} : void 0;
|
|
17059
|
-
let publicScalar;
|
|
17060
|
-
const grammar = {
|
|
17061
|
-
_tag: "grammar",
|
|
17062
|
-
_meta: {
|
|
17063
|
-
...root._meta,
|
|
17064
|
-
// Trivia classification describes this grammar's own active trivia
|
|
17065
|
-
// scope. A directly nested grammar may have classified trivia of its
|
|
17066
|
-
// own, but that must not advertise classification for this wrapper.
|
|
17067
|
-
triviaKindLabels: void 0,
|
|
17068
|
-
rootTriviaClassified: void 0,
|
|
17069
|
-
...opts.trivia?._meta?.triviaKindLabels ? { triviaKindLabels: opts.trivia._meta.triviaKindLabels } : {},
|
|
17070
|
-
...opts.trivia?._meta?.rootTriviaClassified ? { rootTriviaClassified: true } : {}
|
|
17071
|
-
},
|
|
17072
|
-
_def: {
|
|
17073
|
-
tag: "grammar",
|
|
17074
|
-
parser: root,
|
|
17075
|
-
triviaParser: scopeTrivia,
|
|
17076
|
-
clearTrivia,
|
|
17077
|
-
...opaqueRootCapture ? { rootCapture: "opaque" } : {},
|
|
17078
|
-
...opts.captureTrivia ? { captureTrivia: true } : {},
|
|
17079
|
-
trackLines: opts.trackLines ?? false,
|
|
17080
|
-
constructionTrackLines: trackLinesPolicy,
|
|
17081
|
-
...captureKinds === void 0 ? {} : { constructionCaptureTriviaKinds: captureKinds }
|
|
17082
|
-
},
|
|
17083
|
-
_parseScalar: parseScalar,
|
|
17084
|
-
parse(input, pos, _ctx) {
|
|
17085
|
-
if (pos === void 0 && _ctx === void 0) {
|
|
17086
|
-
publicScalar ??= scalarRootOf(grammar) ?? null;
|
|
17087
|
-
if (publicScalar) {
|
|
17088
|
-
const ctx2 = createParseContext();
|
|
17089
|
-
const end = publicScalar(input, 0, ctx2);
|
|
17090
|
-
if (end < 0) {
|
|
17091
|
-
const at = ~end;
|
|
17092
|
-
return { ok: false, expected: ctx2._fx ?? [], span: { start: at, end: at } };
|
|
17093
|
-
}
|
|
17094
|
-
return { ok: true, value: ctx2._sv, span: { start: 0, end } };
|
|
17974
|
+
function withAmbient(ruleMap, opts) {
|
|
17975
|
+
if (opts.trivia === void 0 && opts.scanSkip === void 0) return ruleMap;
|
|
17976
|
+
const wrappers = /* @__PURE__ */ new Map();
|
|
17977
|
+
return ruleMap.map(([name, rule2]) => {
|
|
17978
|
+
if (rule2._meta.isTrivia) return [name, rule2];
|
|
17979
|
+
const addTrivia = opts.trivia !== void 0 && rule2._meta.grammarTrivia === void 0;
|
|
17980
|
+
const addScanSkip = opts.scanSkip !== void 0 && rule2._meta.grammarScanSkip === void 0;
|
|
17981
|
+
if (!addTrivia && !addScanSkip) return [name, rule2];
|
|
17982
|
+
let wrapped = wrappers.get(rule2);
|
|
17983
|
+
if (wrapped === void 0) {
|
|
17984
|
+
wrapped = {
|
|
17985
|
+
...rule2,
|
|
17986
|
+
_meta: {
|
|
17987
|
+
...rule2._meta,
|
|
17988
|
+
...addTrivia ? { grammarTrivia: opts.trivia } : {},
|
|
17989
|
+
...addScanSkip ? { grammarScanSkip: opts.scanSkip } : {}
|
|
17095
17990
|
}
|
|
17096
|
-
}
|
|
17097
|
-
|
|
17098
|
-
const trackLines = trackLinesOf(_ctx);
|
|
17099
|
-
const lineContext = trackLines && _ctx?._lineIndex === void 0 && _ctx?._lineStarts === void 0 ? createParseLineContext(input, pos ?? 0) : void 0;
|
|
17100
|
-
const lineIndex = trackLines ? _ctx?._lineIndex ?? (_ctx?._lineStarts ? { lineStarts: _ctx._lineStarts } : lineContext.lineIndex) : void 0;
|
|
17101
|
-
const ctx = _ctx === void 0 ? createParseContext() : { ..._ctx };
|
|
17102
|
-
ctx.trackLines = trackLines;
|
|
17103
|
-
if (lineIndex) ctx._lineIndex = lineIndex;
|
|
17104
|
-
if (lineContext) ctx._lineScannedTo = lineContext.lineScannedTo;
|
|
17105
|
-
if (clearTrivia) {
|
|
17106
|
-
ctx.trivia = void 0;
|
|
17107
|
-
ctx.triviaKindLabels = void 0;
|
|
17108
|
-
} else if (scopeTrivia !== void 0) {
|
|
17109
|
-
ctx.trivia = scopeTrivia;
|
|
17110
|
-
if (scopeLabels) ctx.triviaKindLabels = scopeLabels;
|
|
17111
|
-
}
|
|
17112
|
-
if (forceCaptureTrivia || _ctx?.captureTrivia) ctx.captureTrivia = true;
|
|
17113
|
-
if (ownCaptureMask !== void 0) ctx._triviaCaptureMask = ownCaptureMask;
|
|
17114
|
-
else if (inheritCaptureMask) ctx._triviaCaptureMask = triviaKindMask(_ctx?.triviaKindLabels, captureKinds);
|
|
17115
|
-
if (opaqueRootCapture) ctx._rootTriviaCapture = false;
|
|
17116
|
-
const result = root.parse(input, pos ?? 0, ctx);
|
|
17117
|
-
if (trackLines && _ctx && ctx._lineScannedTo !== void 0) {
|
|
17118
|
-
_ctx._lineScannedTo = Math.max(_ctx._lineScannedTo ?? 0, ctx._lineScannedTo);
|
|
17119
|
-
}
|
|
17120
|
-
return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
|
|
17991
|
+
};
|
|
17992
|
+
wrappers.set(rule2, wrapped);
|
|
17121
17993
|
}
|
|
17994
|
+
return [name, wrapped];
|
|
17995
|
+
});
|
|
17996
|
+
}
|
|
17997
|
+
function compileRuleMapRunnable(ruleMap, opts = {}) {
|
|
17998
|
+
const encoded = encodeForRun(ruleMap, opts);
|
|
17999
|
+
if (encoded === null) return null;
|
|
18000
|
+
const { prog, hostMode, plan } = encoded;
|
|
18001
|
+
const artifact = closureArtifact(prog);
|
|
18002
|
+
const reflection = collectGrammarReflection(ruleMap);
|
|
18003
|
+
return {
|
|
18004
|
+
keys: ruleMap.map(([key]) => key),
|
|
18005
|
+
hostMode,
|
|
18006
|
+
hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule2]) => hasDirectBuildDef(rule2)),
|
|
18007
|
+
reflection,
|
|
18008
|
+
...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
|
|
18009
|
+
// Reflection rides on the map's metadata prototype from birth. Only `compile()`
|
|
18010
|
+
// asks to specialise; every other caller runs the closure artifact.
|
|
18011
|
+
rules: tableRules(opts.specialise === true ? prog : artifact, { [GRAMMAR_REFLECTION]: reflection }),
|
|
18012
|
+
prog: artifact
|
|
17122
18013
|
};
|
|
17123
|
-
return grammar;
|
|
17124
18014
|
}
|
|
17125
|
-
|
|
17126
|
-
|
|
17127
|
-
|
|
17128
|
-
|
|
17129
|
-
|
|
17130
|
-
|
|
17131
|
-
|
|
17132
|
-
|
|
17133
|
-
|
|
17134
|
-
|
|
17135
|
-
|
|
17136
|
-
|
|
17137
|
-
|
|
17138
|
-
|
|
17139
|
-
|
|
17140
|
-
|
|
17141
|
-
|
|
17142
|
-
|
|
17143
|
-
|
|
17144
|
-
|
|
17145
|
-
if (grammarTrivia !== void 0) {
|
|
17146
|
-
ctx.trivia = grammarTrivia;
|
|
17147
|
-
if (grammarTrivia._meta.triviaKindLabels) ctx.triviaKindLabels = grammarTrivia._meta.triviaKindLabels;
|
|
18015
|
+
function encodeForRun(ruleMap, opts) {
|
|
18016
|
+
runDuplicationDiagnosticRules(ruleMap, opts.duplication);
|
|
18017
|
+
const encodeMap = withAmbient(ruleMap, opts);
|
|
18018
|
+
const plan = opts.coverage === true ? buildGrammarPlan(
|
|
18019
|
+
encodeMap.map(([, rule2]) => rule2),
|
|
18020
|
+
Object.fromEntries(encodeMap.filter(([, rule2]) => rule2._def.tag !== "lazy"))
|
|
18021
|
+
) : void 0;
|
|
18022
|
+
const hostMode = resolveHostMode(ruleMap, opts.hostMode);
|
|
18023
|
+
const settings = {
|
|
18024
|
+
hostMode,
|
|
18025
|
+
...resolveTrackLines(ruleMap, opts.trackLines) ? { trackLines: true } : {},
|
|
18026
|
+
...opts.recovery === true ? { recovery: true } : {},
|
|
18027
|
+
...plan === void 0 ? {} : { coverage: plan }
|
|
18028
|
+
};
|
|
18029
|
+
try {
|
|
18030
|
+
const { prog, fnSrcs } = encodeTableProgram(Object.fromEntries(encodeMap), settings);
|
|
18031
|
+
return { prog, fnSrcs, hostMode, plan };
|
|
18032
|
+
} catch (e) {
|
|
18033
|
+
opts.refusals?.push(e instanceof Error ? e.message : String(e));
|
|
18034
|
+
return null;
|
|
17148
18035
|
}
|
|
17149
|
-
if (grammarScanSkip !== void 0) ctx.scanSkip = grammarScanSkip;
|
|
17150
|
-
if (_errors !== void 0) ctx._errors = _errors;
|
|
17151
|
-
if (_probe !== void 0) ctx._probe = _probe;
|
|
17152
|
-
const result = combinator.parse(input, 0, ctx);
|
|
17153
|
-
if (!result.ok) return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
|
|
17154
|
-
const withErrors = _errors !== void 0 ? { ...result, errors: _errors, furthestFail: _probe?.best ?? null } : result;
|
|
17155
|
-
return lineIndex ? annotateResultLines(withErrors, normalizeLineIndex(lineIndex)) : withErrors;
|
|
17156
18036
|
}
|
|
17157
18037
|
|
|
17158
18038
|
// src/compiler/linker.ts
|
|
@@ -17252,7 +18132,7 @@ function analyzeGrammarGating(grammar, opts) {
|
|
|
17252
18132
|
}
|
|
17253
18133
|
|
|
17254
18134
|
// src/analysis/diagnose.ts
|
|
17255
|
-
var
|
|
18135
|
+
var isCombinator2 = (g) => typeof g === "object" && g !== null && "_def" in g;
|
|
17256
18136
|
var isRuleEntries = (g) => Array.isArray(g);
|
|
17257
18137
|
function diagnoseGrammar(grammar, opts) {
|
|
17258
18138
|
const depth = degradationCaptureDepth();
|
|
@@ -17273,7 +18153,7 @@ function examinedNothing(d) {
|
|
|
17273
18153
|
return d.summary.totalChoices === 0 && d.summary.unanalysable > 0;
|
|
17274
18154
|
}
|
|
17275
18155
|
function runAnalysis(grammar, opts) {
|
|
17276
|
-
if (
|
|
18156
|
+
if (isCombinator2(grammar)) return analyzeGating(grammar, opts);
|
|
17277
18157
|
if (isRuleEntries(grammar)) return analyzeGatingRules(grammar, opts);
|
|
17278
18158
|
return analyzeGrammarGating(grammar, opts);
|
|
17279
18159
|
}
|
|
@@ -18032,16 +18912,16 @@ function ownSource(fn) {
|
|
|
18032
18912
|
return typeof name === "string" && name.length > 0 && globalThis[name] === fn ? name : null;
|
|
18033
18913
|
}
|
|
18034
18914
|
function compile(target, second, third) {
|
|
18035
|
-
if (!
|
|
18915
|
+
if (!isCombinator3(target)) return compileMap(target, second);
|
|
18036
18916
|
return compileRoot(target, second, third);
|
|
18037
18917
|
}
|
|
18038
|
-
function
|
|
18918
|
+
function isCombinator3(x) {
|
|
18039
18919
|
return typeof x === "object" && x !== null && typeof x.parse === "function" && "_def" in x;
|
|
18040
18920
|
}
|
|
18041
18921
|
function compileMap(grammar, opts = {}) {
|
|
18042
18922
|
const entries = [];
|
|
18043
18923
|
for (const [key, value] of Object.entries(grammar)) {
|
|
18044
|
-
if (!
|
|
18924
|
+
if (!isCombinator3(value)) throw new TypeError(`compile: grammar entry "${key}" is not a parser`);
|
|
18045
18925
|
if (value._def.tag === "lazy") {
|
|
18046
18926
|
try {
|
|
18047
18927
|
value._def.thunk();
|
|
@@ -18355,49 +19235,6 @@ function digestValue(value, prefix = "", options) {
|
|
|
18355
19235
|
return sha.digest("hex");
|
|
18356
19236
|
}
|
|
18357
19237
|
|
|
18358
|
-
// src/combinators/attempt.ts
|
|
18359
|
-
function containOption(options) {
|
|
18360
|
-
if (options === void 0) return false;
|
|
18361
|
-
for (const key of Object.keys(options)) {
|
|
18362
|
-
if (key !== "contain") throw new TypeError(`attempt(): unknown option ${JSON.stringify(key)}`);
|
|
18363
|
-
}
|
|
18364
|
-
if (options.contain !== void 0 && typeof options.contain !== "boolean") {
|
|
18365
|
-
throw new TypeError("attempt(): `contain` must be a boolean");
|
|
18366
|
-
}
|
|
18367
|
-
return options.contain === true;
|
|
18368
|
-
}
|
|
18369
|
-
function attempt(parser2, options) {
|
|
18370
|
-
const contain = containOption(options);
|
|
18371
|
-
const guardable = parser2._meta.firstSet.kind !== "any" && !matchesEmpty(parser2);
|
|
18372
|
-
let failExpected;
|
|
18373
|
-
return {
|
|
18374
|
-
_tag: "attempt",
|
|
18375
|
-
_meta: parser2._meta,
|
|
18376
|
-
_def: contain ? { tag: "attempt", parser: parser2, contain: true } : { tag: "attempt", parser: parser2 },
|
|
18377
|
-
parse(input, pos, ctx) {
|
|
18378
|
-
if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(parser2, input, pos)) {
|
|
18379
|
-
if (failExpected === void 0) {
|
|
18380
|
-
const e = deriveExpected(parser2);
|
|
18381
|
-
failExpected = e.length > 0 ? e : [parser2._tag];
|
|
18382
|
-
}
|
|
18383
|
-
return { ok: false, expected: failExpected, span: { start: pos, end: pos } };
|
|
18384
|
-
}
|
|
18385
|
-
const mark = saveCstMark(ctx);
|
|
18386
|
-
const log = ctx._triviaLog?.length;
|
|
18387
|
-
const rootLog = ctx._rootTriviaLog?.length;
|
|
18388
|
-
const split = ctx._columnsSplit;
|
|
18389
|
-
const result = parser2.parse(input, pos, ctx);
|
|
18390
|
-
if (result.ok) return result;
|
|
18391
|
-
rollbackCstCapture(ctx, mark);
|
|
18392
|
-
ctx._columnsSplit = split;
|
|
18393
|
-
if (log !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== log) ctx._triviaLog.length = log;
|
|
18394
|
-
if (rootLog !== void 0 && ctx._rootTriviaLog && ctx._rootTriviaLog.length !== rootLog) ctx._rootTriviaLog.length = rootLog;
|
|
18395
|
-
if (result.committed && !contain) return result;
|
|
18396
|
-
return { ok: false, expected: result.expected, span: { start: pos, end: pos } };
|
|
18397
|
-
}
|
|
18398
|
-
};
|
|
18399
|
-
}
|
|
18400
|
-
|
|
18401
19238
|
// src/combinators/not.ts
|
|
18402
19239
|
function not(combinator) {
|
|
18403
19240
|
const meta = {
|