parseman 0.50.1 → 0.50.3
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/README.md +14 -10
- package/dist/analysis/diagnostics.js +431 -219
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/cli/index.js +421 -184
- package/dist/cli/index.js.map +3 -3
- package/dist/combinators/choice.d.ts.map +1 -1
- package/dist/combinators/grammar.d.ts.map +1 -1
- package/dist/combinators/keywords.d.ts.map +1 -1
- package/dist/combinators/literal.d.ts.map +1 -1
- package/dist/combinators/map.d.ts.map +1 -1
- package/dist/combinators/ref.d.ts.map +1 -1
- package/dist/combinators/regex.d.ts.map +1 -1
- package/dist/combinators/repeat.d.ts.map +1 -1
- package/dist/combinators/scalar.d.ts +6 -0
- package/dist/combinators/scalar.d.ts.map +1 -0
- package/dist/combinators/sequence.d.ts.map +1 -1
- package/dist/combinators/trivia-skip.d.ts +2 -0
- package/dist/combinators/trivia-skip.d.ts.map +1 -1
- package/dist/compiler/token-capability.js +0 -3
- package/dist/compiler/token-capability.js.map +2 -2
- package/dist/index.js +422 -185
- package/dist/index.js.map +3 -3
- package/dist/language-service/index.js +68 -172
- package/dist/language-service/index.js.map +3 -3
- package/dist/parse-context.d.ts.map +1 -1
- package/dist/plugin/index.js +467 -299
- package/dist/plugin/index.js.map +3 -3
- package/dist/run/index.js +1 -0
- package/dist/run/index.js.map +1 -1
- package/dist/spec/index.js +399 -277
- package/dist/spec/index.js.map +3 -3
- package/dist/table/emit-assembly.d.ts.map +1 -1
- package/dist/table/index.js +307 -181
- package/dist/table/index.js.map +3 -3
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +4 -2
- package/src/combinators/choice.ts +34 -1
- package/src/combinators/grammar.ts +39 -0
- package/src/combinators/keywords.ts +14 -3
- package/src/combinators/literal.ts +26 -0
- package/src/combinators/map.ts +60 -0
- package/src/combinators/ref.ts +26 -7
- package/src/combinators/regex.ts +23 -0
- package/src/combinators/repeat.ts +109 -16
- package/src/combinators/scalar.ts +30 -0
- package/src/combinators/sequence.ts +76 -161
- package/src/combinators/trivia-skip.ts +14 -1
- package/src/parse-context.ts +1 -0
- package/src/table/emit-assembly.ts +39 -16
- package/src/types.ts +8 -0
- package/src/version.ts +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -689,9 +689,43 @@ function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
|
|
|
689
689
|
}
|
|
690
690
|
}
|
|
691
691
|
|
|
692
|
+
// src/combinators/scalar.ts
|
|
693
|
+
var SCALAR_TAG = /^(?:literal|regex|keywords|sequence|choice|many|oneOrMore|optional|transform|trivia|grammar|sepBy|lazy)$/;
|
|
694
|
+
function scalarOf(combinator) {
|
|
695
|
+
return combinator._parseScalar;
|
|
696
|
+
}
|
|
697
|
+
function scalarTree(parser2, seen) {
|
|
698
|
+
if (seen.has(parser2)) return true;
|
|
699
|
+
if (parser2._parseScalar === void 0) return false;
|
|
700
|
+
seen.add(parser2);
|
|
701
|
+
const def = parser2._def;
|
|
702
|
+
if (!SCALAR_TAG.test(def.tag)) return false;
|
|
703
|
+
if ("parsers" in def && !def.parsers.every((child) => scalarTree(child, seen))) return false;
|
|
704
|
+
if ("parser" in def && !scalarTree(def.parser, seen)) return false;
|
|
705
|
+
if ("separator" in def && !scalarTree(def.separator, seen)) return false;
|
|
706
|
+
return def.tag !== "lazy" || scalarTree(def.thunk(), seen);
|
|
707
|
+
}
|
|
708
|
+
function scalarRootOf(combinator) {
|
|
709
|
+
const scalar = combinator._parseScalar;
|
|
710
|
+
const def = combinator._def;
|
|
711
|
+
return scalar !== void 0 && def.tag === "grammar" && scalarTree(def.parser, /* @__PURE__ */ new Set()) ? scalar : void 0;
|
|
712
|
+
}
|
|
713
|
+
|
|
692
714
|
// src/combinators/ref.ts
|
|
715
|
+
function withRuleTrivia(trivia2, ctx, run) {
|
|
716
|
+
const savedLabels = ctx.triviaKindLabels;
|
|
717
|
+
ctx.trivia = trivia2;
|
|
718
|
+
ctx.triviaKindLabels = trivia2._meta.triviaKindLabels;
|
|
719
|
+
try {
|
|
720
|
+
return run();
|
|
721
|
+
} finally {
|
|
722
|
+
ctx.trivia = void 0;
|
|
723
|
+
ctx.triviaKindLabels = savedLabels;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
693
726
|
function ref() {
|
|
694
727
|
let resolved = null;
|
|
728
|
+
let resolvedScalar = null;
|
|
695
729
|
let ownBoundary = false;
|
|
696
730
|
const meta = {
|
|
697
731
|
firstSet: any(),
|
|
@@ -708,25 +742,28 @@ function ref() {
|
|
|
708
742
|
return resolved;
|
|
709
743
|
}
|
|
710
744
|
},
|
|
745
|
+
_parseScalar(input, pos, ctx) {
|
|
746
|
+
const scalar = resolvedScalar;
|
|
747
|
+
if (!scalar) throw new Error("ref<T>() used before .define() was called");
|
|
748
|
+
const gt = meta.grammarTrivia;
|
|
749
|
+
if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
|
|
750
|
+
return withRuleTrivia(gt, ctx, () => scalar(input, pos, ctx));
|
|
751
|
+
}
|
|
752
|
+
return scalar(input, pos, ctx);
|
|
753
|
+
},
|
|
711
754
|
parse(input, pos, ctx) {
|
|
712
|
-
|
|
755
|
+
const parser2 = resolved;
|
|
756
|
+
if (!parser2) throw new Error("ref<T>() used before .define() was called");
|
|
713
757
|
const gt = meta.grammarTrivia;
|
|
714
758
|
if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
|
|
715
|
-
|
|
716
|
-
ctx.trivia = gt;
|
|
717
|
-
ctx.triviaKindLabels = gt._meta.triviaKindLabels;
|
|
718
|
-
try {
|
|
719
|
-
return resolved.parse(input, pos, ctx);
|
|
720
|
-
} finally {
|
|
721
|
-
ctx.trivia = void 0;
|
|
722
|
-
ctx.triviaKindLabels = savedLabels;
|
|
723
|
-
}
|
|
759
|
+
return withRuleTrivia(gt, ctx, () => parser2.parse(input, pos, ctx));
|
|
724
760
|
}
|
|
725
|
-
return
|
|
761
|
+
return parser2.parse(input, pos, ctx);
|
|
726
762
|
},
|
|
727
763
|
define(p) {
|
|
728
764
|
if (resolved) throw new Error("ref<T>() already defined");
|
|
729
765
|
resolved = p;
|
|
766
|
+
resolvedScalar = scalarOf(p);
|
|
730
767
|
ownBoundary = hasOwnTriviaBoundary(p);
|
|
731
768
|
meta.firstSet = p._meta.firstSet;
|
|
732
769
|
meta.canMatchNewline = p._meta.canMatchNewline;
|
|
@@ -1112,6 +1149,7 @@ function createParseContext() {
|
|
|
1112
1149
|
_fe: void 0,
|
|
1113
1150
|
_fx: void 0,
|
|
1114
1151
|
_fc: void 0,
|
|
1152
|
+
_sv: void 0,
|
|
1115
1153
|
_probe: void 0,
|
|
1116
1154
|
_cstChildren: void 0,
|
|
1117
1155
|
_cstLeaves: void 0,
|
|
@@ -1949,6 +1987,24 @@ function parser(opts, root) {
|
|
|
1949
1987
|
const captureKinds = clearTrivia ? void 0 : opts.captureTriviaKinds;
|
|
1950
1988
|
const ownCaptureMask = captureKinds === void 0 ? void 0 : scopeLabels !== void 0 ? triviaKindMask(scopeLabels, captureKinds) : void 0;
|
|
1951
1989
|
const inheritCaptureMask = captureKinds !== void 0 && scopeLabels === void 0;
|
|
1990
|
+
const rootScalar = scalarOf(root);
|
|
1991
|
+
const scalarEligible = opts.trackLines !== true && opts.recover !== true && !opaqueRootCapture && !forceCaptureTrivia && captureKinds === void 0;
|
|
1992
|
+
const parseScalar = scalarEligible ? (input, pos, ctx) => {
|
|
1993
|
+
const savedTrivia = ctx.trivia;
|
|
1994
|
+
const savedLabels = ctx.triviaKindLabels;
|
|
1995
|
+
if (clearTrivia) {
|
|
1996
|
+
ctx.trivia = void 0;
|
|
1997
|
+
ctx.triviaKindLabels = void 0;
|
|
1998
|
+
} else if (scopeTrivia !== void 0) {
|
|
1999
|
+
ctx.trivia = scopeTrivia;
|
|
2000
|
+
ctx.triviaKindLabels = scopeLabels;
|
|
2001
|
+
}
|
|
2002
|
+
const end = rootScalar(input, pos, ctx);
|
|
2003
|
+
ctx.trivia = savedTrivia;
|
|
2004
|
+
ctx.triviaKindLabels = savedLabels;
|
|
2005
|
+
return end;
|
|
2006
|
+
} : void 0;
|
|
2007
|
+
let publicScalar;
|
|
1952
2008
|
const grammar = {
|
|
1953
2009
|
_tag: "grammar",
|
|
1954
2010
|
_meta: {
|
|
@@ -1972,7 +2028,20 @@ function parser(opts, root) {
|
|
|
1972
2028
|
constructionTrackLines: trackLinesPolicy,
|
|
1973
2029
|
...captureKinds === void 0 ? {} : { constructionCaptureTriviaKinds: captureKinds }
|
|
1974
2030
|
},
|
|
2031
|
+
_parseScalar: parseScalar,
|
|
1975
2032
|
parse(input, pos, _ctx) {
|
|
2033
|
+
if (pos === void 0 && _ctx === void 0) {
|
|
2034
|
+
publicScalar ??= scalarRootOf(grammar) ?? null;
|
|
2035
|
+
if (publicScalar) {
|
|
2036
|
+
const ctx2 = createParseContext();
|
|
2037
|
+
const end = publicScalar(input, 0, ctx2);
|
|
2038
|
+
if (end < 0) {
|
|
2039
|
+
const at = ~end;
|
|
2040
|
+
return { ok: false, expected: ctx2._fx ?? [], span: { start: at, end: at } };
|
|
2041
|
+
}
|
|
2042
|
+
return { ok: true, value: ctx2._sv, span: { start: 0, end } };
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
1976
2045
|
if (refuseUnclassified) refuseUnclassifiedRootScope(_ctx?._rootTriviaStrictScopes);
|
|
1977
2046
|
const trackLines = trackLinesOf(_ctx);
|
|
1978
2047
|
const lineContext = trackLines && _ctx?._lineIndex === void 0 && _ctx?._lineStarts === void 0 ? createParseLineContext(input, pos ?? 0) : void 0;
|
|
@@ -2007,6 +2076,9 @@ function parse(combinator, input, opts = {}) {
|
|
|
2007
2076
|
_analyzed.add(combinator);
|
|
2008
2077
|
markUnusedValues(combinator);
|
|
2009
2078
|
}
|
|
2079
|
+
if (!opts.trackLines && !opts.recover && combinator._def.tag === "grammar" && combinator._meta.grammarScanSkip === void 0) {
|
|
2080
|
+
return combinator.parse(input);
|
|
2081
|
+
}
|
|
2010
2082
|
const trackLines = opts.trackLines ?? combinator._meta.grammarTrackLines ?? false;
|
|
2011
2083
|
const lineContext = trackLines ? createParseLineContext(input, 0) : void 0;
|
|
2012
2084
|
const lineIndex = lineContext?.lineIndex;
|
|
@@ -2601,10 +2673,32 @@ function regex(pattern, flags = "") {
|
|
|
2601
2673
|
const canMatchNewline = raw.canMatchNewline;
|
|
2602
2674
|
const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
|
|
2603
2675
|
const def = { tag: "regex", source, flags: resolvedFlags };
|
|
2676
|
+
const expected = directTerminalFailureExpected(def);
|
|
2677
|
+
const parseScalar = (input, pos, ctx) => {
|
|
2678
|
+
const scanEnd = scan?.(input, pos);
|
|
2679
|
+
if (scanEnd !== void 0) {
|
|
2680
|
+
if (scanEnd === null) {
|
|
2681
|
+
ctx._fx = expected;
|
|
2682
|
+
return ~pos;
|
|
2683
|
+
}
|
|
2684
|
+
ctx._sv = input.slice(pos, scanEnd);
|
|
2685
|
+
return scanEnd;
|
|
2686
|
+
}
|
|
2687
|
+
anchored.lastIndex = pos;
|
|
2688
|
+
const match = anchored.exec(input);
|
|
2689
|
+
if (match === null) {
|
|
2690
|
+
ctx._fx = expected;
|
|
2691
|
+
return ~pos;
|
|
2692
|
+
}
|
|
2693
|
+
ctx._sv = match[0];
|
|
2694
|
+
return pos + match[0].length;
|
|
2695
|
+
};
|
|
2604
2696
|
return {
|
|
2605
2697
|
_tag: "regex",
|
|
2606
2698
|
_meta: meta,
|
|
2607
2699
|
_def: def,
|
|
2700
|
+
_stickyRegex: anchored,
|
|
2701
|
+
_parseScalar: parseScalar,
|
|
2608
2702
|
parse(input, pos, ctx) {
|
|
2609
2703
|
const scanEnd = scan?.(input, pos);
|
|
2610
2704
|
if (scanEnd !== void 0) {
|
|
@@ -2649,6 +2743,28 @@ function literal(value, opts = {}) {
|
|
|
2649
2743
|
isTrivia: false
|
|
2650
2744
|
};
|
|
2651
2745
|
const canMatchNewline = meta.canMatchNewline;
|
|
2746
|
+
const parseScalar = !caseInsensitive && value.length === 1 ? (() => {
|
|
2747
|
+
const code = value.charCodeAt(0);
|
|
2748
|
+
return (input, pos, ctx) => {
|
|
2749
|
+
if (input.charCodeAt(pos) === code) {
|
|
2750
|
+
ctx._sv = value;
|
|
2751
|
+
return pos + 1;
|
|
2752
|
+
}
|
|
2753
|
+
ctx._fx = expected;
|
|
2754
|
+
return ~pos;
|
|
2755
|
+
};
|
|
2756
|
+
})() : (input, pos, ctx) => {
|
|
2757
|
+
const end = pos + value.length;
|
|
2758
|
+
if (end <= input.length) {
|
|
2759
|
+
const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
|
|
2760
|
+
if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
|
|
2761
|
+
ctx._sv = matchedValue;
|
|
2762
|
+
return end;
|
|
2763
|
+
}
|
|
2764
|
+
}
|
|
2765
|
+
ctx._fx = expected;
|
|
2766
|
+
return ~pos;
|
|
2767
|
+
};
|
|
2652
2768
|
if (caseInsensitive) {
|
|
2653
2769
|
const upper = value.toUpperCase();
|
|
2654
2770
|
const lower = value.toLowerCase();
|
|
@@ -2689,6 +2805,7 @@ function literal(value, opts = {}) {
|
|
|
2689
2805
|
_tag: "literal",
|
|
2690
2806
|
_meta: meta,
|
|
2691
2807
|
_def: { tag: "literal", value, caseInsensitive },
|
|
2808
|
+
_parseScalar: parseScalar,
|
|
2692
2809
|
parse: parse2
|
|
2693
2810
|
};
|
|
2694
2811
|
}
|
|
@@ -2756,16 +2873,26 @@ function keywords(words, opts = {}) {
|
|
|
2756
2873
|
caseInsensitive: opts.caseInsensitive ?? false,
|
|
2757
2874
|
boundary: opts.boundary
|
|
2758
2875
|
};
|
|
2876
|
+
const expected = directTerminalFailureExpected(def);
|
|
2877
|
+
const parseScalar = (input, pos, ctx) => {
|
|
2878
|
+
re.lastIndex = pos;
|
|
2879
|
+
const m = re.exec(input);
|
|
2880
|
+
if (m === null) {
|
|
2881
|
+
ctx._fx = expected;
|
|
2882
|
+
return ~pos;
|
|
2883
|
+
}
|
|
2884
|
+
ctx._sv = m[0];
|
|
2885
|
+
return pos + m[0].length;
|
|
2886
|
+
};
|
|
2759
2887
|
return {
|
|
2760
2888
|
_tag: "keywords",
|
|
2761
2889
|
_meta: meta,
|
|
2762
2890
|
_def: def,
|
|
2891
|
+
_parseScalar: parseScalar,
|
|
2763
2892
|
parse(input, pos, ctx) {
|
|
2764
2893
|
re.lastIndex = pos;
|
|
2765
2894
|
const m = re.exec(input);
|
|
2766
|
-
if (m === null
|
|
2767
|
-
return failAt(ctx, directTerminalFailureExpected(def), pos);
|
|
2768
|
-
}
|
|
2895
|
+
if (m === null) return failAt(ctx, directTerminalFailureExpected(def), pos);
|
|
2769
2896
|
const value = m[0];
|
|
2770
2897
|
const span = { start: pos, end: pos + value.length };
|
|
2771
2898
|
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
|
|
@@ -2796,6 +2923,9 @@ var fastScanner3;
|
|
|
2796
2923
|
function needsDeferredTriviaCommit(ctx) {
|
|
2797
2924
|
return ctx._triviaLog !== void 0 || ctx._rootTriviaLog !== void 0 || ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0;
|
|
2798
2925
|
}
|
|
2926
|
+
function needsTriviaRollback(ctx) {
|
|
2927
|
+
return ctx._cstBuf !== void 0 || ctx._cstLeaves !== void 0 || ctx._cstRawChildren !== void 0 || ctx._cstTriviaLog !== void 0 || ctx._fields !== void 0 || ctx._errors !== void 0 || ctx._triviaLog !== void 0 || ctx._rootTriviaLog !== void 0;
|
|
2928
|
+
}
|
|
2799
2929
|
function saveTriviaMark(ctx) {
|
|
2800
2930
|
const m = saveCstMark(ctx);
|
|
2801
2931
|
return {
|
|
@@ -2912,7 +3042,8 @@ function advanceTrivia(input, cur, ctx) {
|
|
|
2912
3042
|
const triviaP = ctx.trivia;
|
|
2913
3043
|
if (!triviaP) return cur;
|
|
2914
3044
|
if (!ctx.trackLines) {
|
|
2915
|
-
const
|
|
3045
|
+
const classified = triviaP._meta.triviaScanner;
|
|
3046
|
+
const fast2 = classified === void 0 ? fastTriviaScanner(triviaP) : classified;
|
|
2916
3047
|
if (fast2) return fast2(input, cur);
|
|
2917
3048
|
if (ctx.triviaKindLabels) return skipWithLabels(input, cur, ctx);
|
|
2918
3049
|
const tr2 = triviaP.parse(input, cur, createDetachedParseContext(ctx.trackLines, ctx.state));
|
|
@@ -3517,6 +3648,7 @@ function sequence(...parsers) {
|
|
|
3517
3648
|
(adjacency ??= Array.from({ length: parsers.length }, () => null))[i] = a;
|
|
3518
3649
|
}
|
|
3519
3650
|
const hasAdjacency = adjacency !== null;
|
|
3651
|
+
const strictArity = !hasAdjacency && (parsers.length === 2 && !matchesEmpty(parsers[1]) || parsers.length === 3 && parsers.every((p) => !matchesEmpty(p))) ? parsers.length : 0;
|
|
3520
3652
|
const meta = {
|
|
3521
3653
|
// Union through the nullable prefix — a leading optional()/many() lets a later
|
|
3522
3654
|
// term's first char start the sequence. Just `parsers[0]` under-approximates.
|
|
@@ -3525,165 +3657,96 @@ function sequence(...parsers) {
|
|
|
3525
3657
|
isTrivia: false
|
|
3526
3658
|
};
|
|
3527
3659
|
const def = { tag: "sequence", parsers };
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
followSentinels ??= parsers.map((_, i) => {
|
|
3531
|
-
const fs = parsers.slice(i + 1).reduce(
|
|
3532
|
-
(acc, p) => union(acc, firstSetOf(p)),
|
|
3533
|
-
{ kind: "empty" }
|
|
3534
|
-
);
|
|
3535
|
-
return firstSetSentinel(fs);
|
|
3536
|
-
});
|
|
3537
|
-
const values = def.valueUnused ? void 0 : [];
|
|
3660
|
+
const scalarParsers = parsers.map(scalarOf);
|
|
3661
|
+
const parseScalar = (input, pos, ctx) => {
|
|
3538
3662
|
let cur = pos;
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
const mTlog = cstTlLen(ctx);
|
|
3551
|
-
const mLog = ctx._triviaLog?.length ?? 0;
|
|
3552
|
-
const mRootLog = ctx._rootTriviaLog?.length ?? 0;
|
|
3553
|
-
let scanEnd;
|
|
3554
|
-
if (needsDeferredTriviaCommit(ctx)) {
|
|
3555
|
-
scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
|
|
3556
|
-
} else {
|
|
3557
|
-
scanEnd = advanceTrivia(input, cur, ctx);
|
|
3558
|
-
}
|
|
3559
|
-
const scanTlog = cstTlLen(ctx);
|
|
3560
|
-
const scanLog = ctx._triviaLog?.length ?? 0;
|
|
3561
|
-
const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
|
|
3562
|
-
const result2 = parsers[i].parse(input, scanEnd, ctx);
|
|
3563
|
-
if (!result2.ok) return result2;
|
|
3564
|
-
if (result2.span.end > scanEnd) cur = result2.span.end;
|
|
3565
|
-
else rollbackScannedTriviaAt(
|
|
3566
|
-
ctx,
|
|
3567
|
-
mTlog,
|
|
3568
|
-
scanTlog,
|
|
3569
|
-
mLog,
|
|
3570
|
-
scanLog,
|
|
3571
|
-
mRootLog,
|
|
3572
|
-
scanRootLog
|
|
3573
|
-
);
|
|
3574
|
-
if (values !== void 0) values.push(result2.value);
|
|
3575
|
-
continue;
|
|
3576
|
-
}
|
|
3577
|
-
const result = parsers[i].parse(input, cur, ctx);
|
|
3578
|
-
if (!result.ok) return result;
|
|
3579
|
-
if (values !== void 0) values.push(result.value);
|
|
3580
|
-
cur = result.span.end;
|
|
3663
|
+
if (strictArity !== 0) {
|
|
3664
|
+
cur = scalarParsers[0](input, cur, ctx);
|
|
3665
|
+
if (cur < 0) return cur;
|
|
3666
|
+
const first = ctx._sv;
|
|
3667
|
+
if (ctx.trivia) cur = advanceTrivia(input, cur, ctx);
|
|
3668
|
+
cur = scalarParsers[1](input, cur, ctx);
|
|
3669
|
+
if (cur < 0) return cur;
|
|
3670
|
+
const second = ctx._sv;
|
|
3671
|
+
if (strictArity === 2) {
|
|
3672
|
+
ctx._sv = def.valueUnused ? void 0 : [first, second];
|
|
3673
|
+
return cur;
|
|
3581
3674
|
}
|
|
3582
|
-
|
|
3583
|
-
|
|
3675
|
+
if (ctx.trivia) cur = advanceTrivia(input, cur, ctx);
|
|
3676
|
+
cur = scalarParsers[2](input, cur, ctx);
|
|
3677
|
+
if (cur < 0) return cur;
|
|
3678
|
+
ctx._sv = def.valueUnused ? void 0 : [first, second, ctx._sv];
|
|
3679
|
+
return cur;
|
|
3584
3680
|
}
|
|
3585
|
-
return {
|
|
3586
|
-
ok: true,
|
|
3587
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
3588
|
-
value: values ?? void 0,
|
|
3589
|
-
span: { start: pos, end: cur }
|
|
3590
|
-
};
|
|
3591
|
-
}
|
|
3592
|
-
function parseAdjacent(input, pos, ctx) {
|
|
3593
3681
|
const values = def.valueUnused ? void 0 : [];
|
|
3594
|
-
let
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
const mRootLog = ctx._rootTriviaLog?.length ?? 0;
|
|
3607
|
-
if (needsDeferredTriviaCommit(ctx)) {
|
|
3608
|
-
scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
|
|
3609
|
-
} else {
|
|
3610
|
-
scanEnd = advanceTrivia(input, cur, ctx);
|
|
3611
|
-
}
|
|
3612
|
-
const scanTlog = cstTlLen(ctx);
|
|
3613
|
-
const scanLog = ctx._triviaLog?.length ?? 0;
|
|
3614
|
-
const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
|
|
3615
|
-
const result2 = parsers[i].parse(input, scanEnd, ctx);
|
|
3616
|
-
if (!result2.ok) return result2;
|
|
3617
|
-
if (result2.span.end > scanEnd) cur = result2.span.end;
|
|
3618
|
-
else rollbackScannedTriviaAt(
|
|
3619
|
-
ctx,
|
|
3620
|
-
mTlog,
|
|
3621
|
-
scanTlog,
|
|
3622
|
-
mLog,
|
|
3623
|
-
scanLog,
|
|
3624
|
-
mRootLog,
|
|
3625
|
-
scanRootLog
|
|
3626
|
-
);
|
|
3627
|
-
if (values !== void 0) values.push(result2.value);
|
|
3628
|
-
continue;
|
|
3629
|
-
}
|
|
3630
|
-
const result = parsers[i].parse(input, cur, ctx);
|
|
3631
|
-
if (!result.ok) return result;
|
|
3632
|
-
if (values !== void 0) values.push(result.value);
|
|
3633
|
-
cur = result.span.end;
|
|
3634
|
-
}
|
|
3635
|
-
return {
|
|
3636
|
-
ok: true,
|
|
3637
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
3638
|
-
value: values ?? void 0,
|
|
3639
|
-
span: { start: pos, end: cur }
|
|
3640
|
-
};
|
|
3641
|
-
}
|
|
3682
|
+
for (let i = 0; i < scalarParsers.length; i++) {
|
|
3683
|
+
let termPos = cur;
|
|
3684
|
+
if (i > 0 && ctx.trivia) termPos = advanceTrivia(input, cur, ctx);
|
|
3685
|
+
const end = scalarParsers[i](input, termPos, ctx);
|
|
3686
|
+
if (end < 0) return end;
|
|
3687
|
+
if (values !== void 0) values.push(ctx._sv);
|
|
3688
|
+
if (end > termPos || termPos === cur) cur = end;
|
|
3689
|
+
}
|
|
3690
|
+
ctx._sv = values;
|
|
3691
|
+
return cur;
|
|
3692
|
+
};
|
|
3693
|
+
let followSentinels;
|
|
3642
3694
|
return {
|
|
3643
3695
|
_tag: "sequence",
|
|
3644
3696
|
_meta: meta,
|
|
3645
3697
|
_def: def,
|
|
3698
|
+
_parseScalar: hasAdjacency ? void 0 : parseScalar,
|
|
3646
3699
|
parse(input, pos, ctx) {
|
|
3647
|
-
|
|
3648
|
-
if (
|
|
3700
|
+
const tolerant = ctx._tolerant === true;
|
|
3701
|
+
if (tolerant) {
|
|
3702
|
+
followSentinels ??= parsers.map((_, i) => firstSetSentinel(
|
|
3703
|
+
parsers.slice(i + 1).reduce(
|
|
3704
|
+
(set, parser2) => union(set, firstSetOf(parser2)),
|
|
3705
|
+
{ kind: "empty" }
|
|
3706
|
+
)
|
|
3707
|
+
));
|
|
3708
|
+
}
|
|
3709
|
+
const inheritedSync = ctx._sync;
|
|
3710
|
+
const deferredTrivia = needsDeferredTriviaCommit(ctx);
|
|
3649
3711
|
const values = def.valueUnused ? void 0 : [];
|
|
3650
3712
|
let cur = pos;
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
const
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
} else {
|
|
3660
|
-
scanEnd = advanceTrivia(input, cur, ctx);
|
|
3713
|
+
try {
|
|
3714
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
3715
|
+
if (tolerant) ctx._sync = followSentinels[i] ?? inheritedSync;
|
|
3716
|
+
const assertion = adjacency?.[i];
|
|
3717
|
+
if (assertion) {
|
|
3718
|
+
if (!holdsAdjacency(input, cur, ctx, assertion)) return adjacencyFail(cur, assertion);
|
|
3719
|
+
if (values !== void 0) values.push(null);
|
|
3720
|
+
continue;
|
|
3661
3721
|
}
|
|
3662
|
-
|
|
3663
|
-
const
|
|
3664
|
-
const
|
|
3665
|
-
const
|
|
3666
|
-
if (
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3722
|
+
let termPos = cur;
|
|
3723
|
+
const markTlog = deferredTrivia ? cstTlLen(ctx) : 0;
|
|
3724
|
+
const markLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
|
|
3725
|
+
const markRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
3726
|
+
if (ctx.trivia && i > 0) {
|
|
3727
|
+
termPos = deferredTrivia ? commitTriviaScan(scanTriviaCompact(input, cur, ctx)) : advanceTrivia(input, cur, ctx);
|
|
3728
|
+
}
|
|
3729
|
+
const scanTlog = deferredTrivia ? cstTlLen(ctx) : 0;
|
|
3730
|
+
const scanLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
|
|
3731
|
+
const scanRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
3732
|
+
const result = parsers[i].parse(input, termPos, ctx);
|
|
3733
|
+
if (!result.ok) return result;
|
|
3734
|
+
if (values !== void 0) values.push(result.value);
|
|
3735
|
+
if (result.span.end > termPos || termPos === cur) cur = result.span.end;
|
|
3736
|
+
else if (deferredTrivia) {
|
|
3670
3737
|
rollbackScannedTriviaAt(
|
|
3671
3738
|
ctx,
|
|
3672
|
-
|
|
3739
|
+
markTlog,
|
|
3673
3740
|
scanTlog,
|
|
3674
|
-
|
|
3741
|
+
markLog,
|
|
3675
3742
|
scanLog,
|
|
3676
|
-
|
|
3743
|
+
markRootLog,
|
|
3677
3744
|
scanRootLog
|
|
3678
3745
|
);
|
|
3679
3746
|
}
|
|
3680
|
-
if (values !== void 0) values.push(result2.value);
|
|
3681
|
-
continue;
|
|
3682
3747
|
}
|
|
3683
|
-
|
|
3684
|
-
if (
|
|
3685
|
-
if (values !== void 0) values.push(result.value);
|
|
3686
|
-
cur = result.span.end;
|
|
3748
|
+
} finally {
|
|
3749
|
+
if (tolerant) ctx._sync = inheritedSync;
|
|
3687
3750
|
}
|
|
3688
3751
|
return {
|
|
3689
3752
|
ok: true,
|
|
@@ -3815,7 +3878,8 @@ function choice(...args) {
|
|
|
3815
3878
|
disjoint
|
|
3816
3879
|
};
|
|
3817
3880
|
const strategy = disjoint || hasGates ? null : detectStrategy(parsers);
|
|
3818
|
-
const
|
|
3881
|
+
const ordered = strategy?.tag === "firstMatch" || strategy?.tag === "sharedPrefix";
|
|
3882
|
+
const autoNot = !disjoint && !hasGates && ordered ? computeAutoNot(parsers) : parsers.map(() => null);
|
|
3819
3883
|
let greedyLitMap = null;
|
|
3820
3884
|
let sortedParsers = null;
|
|
3821
3885
|
const asciiDispatch = disjoint ? buildAsciiDispatch(parsers) : null;
|
|
@@ -3829,6 +3893,37 @@ function choice(...args) {
|
|
|
3829
3893
|
} else if (strategy?.tag === "literalsLongestFirst") {
|
|
3830
3894
|
sortedParsers = strategy.sortedIndices.map((i) => parsers[i]);
|
|
3831
3895
|
}
|
|
3896
|
+
const scalarParsers = parsers.map(scalarOf);
|
|
3897
|
+
const scalarEligible = !hasGates && parsers.every((p) => p._parseScalar !== void 0) && (disjoint || ordered);
|
|
3898
|
+
const scalarExpected = parsers.flatMap(deriveExpected);
|
|
3899
|
+
const parseScalar = (input, pos, ctx) => {
|
|
3900
|
+
if (disjoint) {
|
|
3901
|
+
const code = pos < input.length ? input.codePointAt(pos) : -1;
|
|
3902
|
+
let idx = code >= 0 && code < 128 ? asciiDispatch[code] : -1;
|
|
3903
|
+
if (idx < 0 && code >= 0) {
|
|
3904
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
3905
|
+
if (inFirstSet(code, parsers[i]._meta.firstSet)) {
|
|
3906
|
+
idx = i;
|
|
3907
|
+
break;
|
|
3908
|
+
}
|
|
3909
|
+
}
|
|
3910
|
+
}
|
|
3911
|
+
if (idx >= 0) {
|
|
3912
|
+
const gate = gates[idx];
|
|
3913
|
+
if (!gate || gate(ctx.state)) return scalarParsers[idx](input, pos, ctx);
|
|
3914
|
+
ctx._fx = deriveExpected(parsers[idx]);
|
|
3915
|
+
return ~pos;
|
|
3916
|
+
}
|
|
3917
|
+
} else {
|
|
3918
|
+
for (let i = 0; i < scalarParsers.length; i++) {
|
|
3919
|
+
if (gates[i] && !gates[i](ctx.state)) continue;
|
|
3920
|
+
const end = scalarParsers[i](input, pos, ctx);
|
|
3921
|
+
if (end >= 0 && (!autoNot[i] || !autoNotFires(input, end, autoNot[i]))) return end;
|
|
3922
|
+
}
|
|
3923
|
+
}
|
|
3924
|
+
ctx._fx = scalarExpected;
|
|
3925
|
+
return ~pos;
|
|
3926
|
+
};
|
|
3832
3927
|
return {
|
|
3833
3928
|
_tag: "choice",
|
|
3834
3929
|
_meta: meta,
|
|
@@ -3840,6 +3935,7 @@ function choice(...args) {
|
|
|
3840
3935
|
strategy: strategy ?? { tag: "firstMatch" },
|
|
3841
3936
|
autoNot
|
|
3842
3937
|
},
|
|
3938
|
+
_parseScalar: scalarEligible ? parseScalar : void 0,
|
|
3843
3939
|
parse(input, pos, ctx) {
|
|
3844
3940
|
const expected = [];
|
|
3845
3941
|
let expectedAt = pos;
|
|
@@ -4371,8 +4467,8 @@ function attempt(parser2) {
|
|
|
4371
4467
|
}
|
|
4372
4468
|
|
|
4373
4469
|
// src/combinators/repeat.ts
|
|
4374
|
-
function repItem(combinator, input, cur, ctx, guardable, mandatory) {
|
|
4375
|
-
const mark = saveTriviaMark(ctx);
|
|
4470
|
+
function repItem(combinator, input, cur, ctx, guardable, mandatory, rollbackNeeded) {
|
|
4471
|
+
const mark = rollbackNeeded ? saveTriviaMark(ctx) : void 0;
|
|
4376
4472
|
let pos = cur;
|
|
4377
4473
|
if (ctx.trivia) {
|
|
4378
4474
|
if (needsDeferredTriviaCommit(ctx)) {
|
|
@@ -4382,24 +4478,24 @@ function repItem(combinator, input, cur, ctx, guardable, mandatory) {
|
|
|
4382
4478
|
}
|
|
4383
4479
|
}
|
|
4384
4480
|
if (pos >= input.length && !mandatory) {
|
|
4385
|
-
rollbackTrivia(ctx, mark);
|
|
4481
|
+
if (mark !== void 0) rollbackTrivia(ctx, mark);
|
|
4386
4482
|
return "stop";
|
|
4387
4483
|
}
|
|
4388
4484
|
if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(combinator, input, pos)) {
|
|
4389
|
-
rollbackTrivia(ctx, mark);
|
|
4485
|
+
if (mark !== void 0) rollbackTrivia(ctx, mark);
|
|
4390
4486
|
return "stop";
|
|
4391
4487
|
}
|
|
4392
4488
|
const result = combinator.parse(input, pos, ctx);
|
|
4393
4489
|
if (!result.ok) {
|
|
4394
|
-
rollbackTrivia(ctx, mark);
|
|
4490
|
+
if (mark !== void 0) rollbackTrivia(ctx, mark);
|
|
4395
4491
|
if (result.committed) return { fail: result, failPos: pos };
|
|
4396
4492
|
return { fail: result, failPos: pos };
|
|
4397
4493
|
}
|
|
4398
4494
|
if (result.span.end === pos && !mandatory) {
|
|
4399
|
-
rollbackTrivia(ctx, mark);
|
|
4495
|
+
if (mark !== void 0) rollbackTrivia(ctx, mark);
|
|
4400
4496
|
return "stop";
|
|
4401
4497
|
}
|
|
4402
|
-
return
|
|
4498
|
+
return result;
|
|
4403
4499
|
}
|
|
4404
4500
|
function resolveBounds(what, opts) {
|
|
4405
4501
|
const min = opts.min ?? 0;
|
|
@@ -4412,6 +4508,21 @@ function resolveBounds(what, opts) {
|
|
|
4412
4508
|
if (max < min) bad(`max (${max}) is less than min (${min}) \u2014 the combinator could never succeed`);
|
|
4413
4509
|
return { min, max };
|
|
4414
4510
|
}
|
|
4511
|
+
function repeatScalarTail(combinator, child, input, cur, ctx, guardable, values, remaining) {
|
|
4512
|
+
while (cur < input.length && remaining > 0) {
|
|
4513
|
+
let itemPos = cur;
|
|
4514
|
+
if (ctx.trivia) itemPos = advanceTrivia(input, cur, ctx);
|
|
4515
|
+
if (itemPos >= input.length) break;
|
|
4516
|
+
if (guardable && !startsFirstSet(combinator, input, itemPos)) break;
|
|
4517
|
+
const end = child(input, itemPos, ctx);
|
|
4518
|
+
if (end <= itemPos) break;
|
|
4519
|
+
if (values !== void 0) values.push(ctx._sv);
|
|
4520
|
+
cur = end;
|
|
4521
|
+
remaining--;
|
|
4522
|
+
}
|
|
4523
|
+
ctx._sv = values;
|
|
4524
|
+
return cur;
|
|
4525
|
+
}
|
|
4415
4526
|
function many(combinator, opts = {}) {
|
|
4416
4527
|
const { min, max } = resolveBounds("many()", opts);
|
|
4417
4528
|
if (min >= 1) return atLeast(combinator, min, max);
|
|
@@ -4423,17 +4534,21 @@ function many(combinator, opts = {}) {
|
|
|
4423
4534
|
const def = { tag: "many", parser: combinator, min: 0, ...max === Infinity ? {} : { max } };
|
|
4424
4535
|
let expected;
|
|
4425
4536
|
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
4537
|
+
const scalarChild = scalarOf(combinator);
|
|
4538
|
+
const parseScalar = (input, pos, ctx) => repeatScalarTail(combinator, scalarChild, input, pos, ctx, guardable, def.valueUnused ? void 0 : [], max);
|
|
4426
4539
|
return {
|
|
4427
4540
|
_tag: "many",
|
|
4428
4541
|
_meta: meta,
|
|
4429
4542
|
_def: def,
|
|
4543
|
+
_parseScalar: parseScalar,
|
|
4430
4544
|
parse(input, pos, ctx) {
|
|
4431
4545
|
const values = def.valueUnused ? void 0 : [];
|
|
4546
|
+
const rollbackNeeded = needsTriviaRollback(ctx);
|
|
4432
4547
|
let cur = pos;
|
|
4433
4548
|
let count = 0;
|
|
4434
4549
|
while (cur < input.length) {
|
|
4435
4550
|
if (count >= max) break;
|
|
4436
|
-
const item = repItem(combinator, input, cur, ctx, guardable, false);
|
|
4551
|
+
const item = repItem(combinator, input, cur, ctx, guardable, false, rollbackNeeded);
|
|
4437
4552
|
if (item === "stop") break;
|
|
4438
4553
|
if ("fail" in item) {
|
|
4439
4554
|
if (!item.fail.ok && item.fail.committed) return item.fail;
|
|
@@ -4450,7 +4565,7 @@ function many(combinator, opts = {}) {
|
|
|
4450
4565
|
}
|
|
4451
4566
|
if (values !== void 0) values.push(item.value);
|
|
4452
4567
|
count++;
|
|
4453
|
-
cur = item.end;
|
|
4568
|
+
cur = item.span.end;
|
|
4454
4569
|
}
|
|
4455
4570
|
return { ok: true, value: values ?? void 0, span: { start: pos, end: cur } };
|
|
4456
4571
|
}
|
|
@@ -4468,30 +4583,47 @@ function atLeast(combinator, min, max) {
|
|
|
4468
4583
|
const def = { tag: "oneOrMore", parser: combinator, min, ...max === Infinity ? {} : { max } };
|
|
4469
4584
|
let expected;
|
|
4470
4585
|
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
4586
|
+
const scalarChild = scalarOf(combinator);
|
|
4587
|
+
const parseScalar = (input, pos, ctx) => {
|
|
4588
|
+
let cur = scalarChild(input, pos, ctx);
|
|
4589
|
+
if (cur < 0) return cur;
|
|
4590
|
+
const values = def.valueUnused ? void 0 : [ctx._sv];
|
|
4591
|
+
for (let count = 1; count < min; count++) {
|
|
4592
|
+
let itemPos = cur;
|
|
4593
|
+
if (ctx.trivia) itemPos = advanceTrivia(input, cur, ctx);
|
|
4594
|
+
const end = scalarChild(input, itemPos, ctx);
|
|
4595
|
+
if (end < 0) return ~cur;
|
|
4596
|
+
cur = end;
|
|
4597
|
+
if (values !== void 0) values.push(ctx._sv);
|
|
4598
|
+
}
|
|
4599
|
+
return repeatScalarTail(combinator, scalarChild, input, cur, ctx, guardable, values, max - min);
|
|
4600
|
+
};
|
|
4471
4601
|
return {
|
|
4472
4602
|
_tag: "oneOrMore",
|
|
4473
4603
|
_meta: meta,
|
|
4474
4604
|
_def: def,
|
|
4605
|
+
_parseScalar: parseScalar,
|
|
4475
4606
|
parse(input, pos, ctx) {
|
|
4476
4607
|
const first = combinator.parse(input, pos, ctx);
|
|
4477
4608
|
if (!first.ok) return first;
|
|
4478
4609
|
const values = def.valueUnused ? void 0 : [first.value];
|
|
4610
|
+
const rollbackNeeded = needsTriviaRollback(ctx);
|
|
4479
4611
|
let cur = first.span.end;
|
|
4480
4612
|
let count = 1;
|
|
4481
4613
|
while (count < min) {
|
|
4482
|
-
const item = repItem(combinator, input, cur, ctx, guardable, true);
|
|
4614
|
+
const item = repItem(combinator, input, cur, ctx, guardable, true, rollbackNeeded);
|
|
4483
4615
|
if (item === "stop" || "fail" in item) {
|
|
4484
4616
|
if (item !== "stop" && !item.fail.ok && item.fail.committed) return item.fail;
|
|
4485
4617
|
expected ??= deriveExpected(combinator);
|
|
4486
4618
|
return { ok: false, expected: expected.length > 0 ? expected : [combinator._tag], span: { start: cur, end: cur } };
|
|
4487
4619
|
}
|
|
4488
4620
|
if (values !== void 0) values.push(item.value);
|
|
4489
|
-
cur = item.end;
|
|
4621
|
+
cur = item.span.end;
|
|
4490
4622
|
count++;
|
|
4491
4623
|
}
|
|
4492
4624
|
while (cur < input.length) {
|
|
4493
4625
|
if (count >= max) break;
|
|
4494
|
-
const item = repItem(combinator, input, cur, ctx, guardable, false);
|
|
4626
|
+
const item = repItem(combinator, input, cur, ctx, guardable, false, rollbackNeeded);
|
|
4495
4627
|
if (item === "stop") break;
|
|
4496
4628
|
if ("fail" in item) {
|
|
4497
4629
|
if (!item.fail.ok && item.fail.committed) return item.fail;
|
|
@@ -4508,7 +4640,7 @@ function atLeast(combinator, min, max) {
|
|
|
4508
4640
|
}
|
|
4509
4641
|
if (values !== void 0) values.push(item.value);
|
|
4510
4642
|
count++;
|
|
4511
|
-
cur = item.end;
|
|
4643
|
+
cur = item.span.end;
|
|
4512
4644
|
}
|
|
4513
4645
|
return { ok: true, value: values ?? void 0, span: { start: pos, end: cur } };
|
|
4514
4646
|
}
|
|
@@ -4521,10 +4653,22 @@ function optional(combinator) {
|
|
|
4521
4653
|
isTrivia: false
|
|
4522
4654
|
};
|
|
4523
4655
|
const firstSetSkippable = !matchesEmpty(combinator);
|
|
4656
|
+
const scalarChild = scalarOf(combinator);
|
|
4657
|
+
const parseScalar = (input, pos, ctx) => {
|
|
4658
|
+
if (firstSetSkippable && !startsFirstSet(combinator, input, pos)) {
|
|
4659
|
+
ctx._sv = null;
|
|
4660
|
+
return pos;
|
|
4661
|
+
}
|
|
4662
|
+
const end = scalarChild(input, pos, ctx);
|
|
4663
|
+
if (end >= 0) return end;
|
|
4664
|
+
ctx._sv = null;
|
|
4665
|
+
return pos;
|
|
4666
|
+
};
|
|
4524
4667
|
return {
|
|
4525
4668
|
_tag: "optional",
|
|
4526
4669
|
_meta: meta,
|
|
4527
4670
|
_def: { tag: "optional", parser: combinator },
|
|
4671
|
+
_parseScalar: parseScalar,
|
|
4528
4672
|
parse(input, pos, ctx) {
|
|
4529
4673
|
if (firstSetSkippable && ctx._probe === void 0 && !startsFirstSet(combinator, input, pos)) {
|
|
4530
4674
|
return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
@@ -4558,6 +4702,43 @@ function sepBy(combinator, separatorArg, opts = {}) {
|
|
|
4558
4702
|
expected ??= deriveExpected(combinator);
|
|
4559
4703
|
return { ok: false, expected: expected.length > 0 ? expected : [combinator._tag], span: { start: at, end: at } };
|
|
4560
4704
|
};
|
|
4705
|
+
const scalarExpected = deriveExpected(combinator);
|
|
4706
|
+
const scalarChild = scalarOf(combinator);
|
|
4707
|
+
const scalarSeparator = scalarOf(separator);
|
|
4708
|
+
const parseScalar = (input, pos, ctx) => {
|
|
4709
|
+
let cur = scalarChild(input, pos, ctx);
|
|
4710
|
+
if (cur < 0) {
|
|
4711
|
+
if (min >= 1) {
|
|
4712
|
+
ctx._fx = scalarExpected.length > 0 ? scalarExpected : [combinator._tag];
|
|
4713
|
+
return ~pos;
|
|
4714
|
+
}
|
|
4715
|
+
ctx._sv = [];
|
|
4716
|
+
return pos;
|
|
4717
|
+
}
|
|
4718
|
+
const values = [ctx._sv];
|
|
4719
|
+
while (values.length < max && (cur < input.length || values.length < min)) {
|
|
4720
|
+
const beforeSeparator = cur;
|
|
4721
|
+
let separatorPos = cur;
|
|
4722
|
+
if (ctx.trivia) separatorPos = advanceTrivia(input, cur, ctx);
|
|
4723
|
+
const separatorEnd = scalarSeparator(input, separatorPos, ctx);
|
|
4724
|
+
if (separatorEnd < 0) break;
|
|
4725
|
+
let itemPos = separatorEnd;
|
|
4726
|
+
if (ctx.trivia) itemPos = advanceTrivia(input, itemPos, ctx);
|
|
4727
|
+
const itemEnd = scalarChild(input, itemPos, ctx);
|
|
4728
|
+
if (itemEnd < 0) {
|
|
4729
|
+
cur = trailing === "allow" ? separatorEnd : beforeSeparator;
|
|
4730
|
+
break;
|
|
4731
|
+
}
|
|
4732
|
+
values.push(ctx._sv);
|
|
4733
|
+
cur = itemEnd;
|
|
4734
|
+
}
|
|
4735
|
+
if (values.length < min) {
|
|
4736
|
+
ctx._fx = scalarExpected.length > 0 ? scalarExpected : [combinator._tag];
|
|
4737
|
+
return ~cur;
|
|
4738
|
+
}
|
|
4739
|
+
ctx._sv = values;
|
|
4740
|
+
return cur;
|
|
4741
|
+
};
|
|
4561
4742
|
return {
|
|
4562
4743
|
_tag: "sepBy",
|
|
4563
4744
|
_meta: meta,
|
|
@@ -4573,6 +4754,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
|
|
|
4573
4754
|
// this option surface already; parity is held by test/parity, not by hope.
|
|
4574
4755
|
...keepSeparators ? { keepSeparators: true } : {}
|
|
4575
4756
|
},
|
|
4757
|
+
_parseScalar: keepSeparators ? void 0 : parseScalar,
|
|
4576
4758
|
parse(input, pos, ctx) {
|
|
4577
4759
|
const first = combinator.parse(input, pos, ctx);
|
|
4578
4760
|
const values = [];
|
|
@@ -5155,11 +5337,54 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
5155
5337
|
}
|
|
5156
5338
|
|
|
5157
5339
|
// src/combinators/map.ts
|
|
5340
|
+
var JSON_STRING_BODY = String.raw`(?:[^"\\]|\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4}))*`;
|
|
5158
5341
|
function transform(combinator, fn) {
|
|
5342
|
+
const observesSpan = fn.length > 1;
|
|
5343
|
+
const sequenceDef = combinator._def.tag === "sequence" ? combinator._def : void 0;
|
|
5344
|
+
const terms = sequenceDef?.parsers;
|
|
5345
|
+
const inner = terms?.[1];
|
|
5346
|
+
const fused = terms?.length === 3 && terms[0]._def.tag === "literal" && terms[0]._def.value === '"' && !terms[0]._def.caseInsensitive && inner._def.tag === "regex" && inner._def.source === JSON_STRING_BODY && inner._def.flags === "" && terms[2]._def.tag === "literal" && terms[2]._def.value === '"' && !terms[2]._def.caseInsensitive && inner._stickyRegex !== void 0;
|
|
5347
|
+
const child = scalarOf(combinator);
|
|
5348
|
+
const parseScalar = fused ? (() => {
|
|
5349
|
+
const body = inner._stickyRegex;
|
|
5350
|
+
const tuple = ['"', "", '"'];
|
|
5351
|
+
const expected = [JSON.stringify('"')];
|
|
5352
|
+
return (input, pos, ctx) => {
|
|
5353
|
+
if (ctx.trivia !== void 0) {
|
|
5354
|
+
const end2 = child(input, pos, ctx);
|
|
5355
|
+
if (end2 < 0) return end2;
|
|
5356
|
+
ctx._sv = observesSpan ? fn(ctx._sv, { start: pos, end: end2 }) : fn(ctx._sv);
|
|
5357
|
+
return end2;
|
|
5358
|
+
}
|
|
5359
|
+
if (input.charCodeAt(pos) !== 34) {
|
|
5360
|
+
ctx._fx = expected;
|
|
5361
|
+
return ~pos;
|
|
5362
|
+
}
|
|
5363
|
+
body.lastIndex = pos + 1;
|
|
5364
|
+
const match = body.exec(input);
|
|
5365
|
+
const close = pos + 1 + match[0].length;
|
|
5366
|
+
if (input.charCodeAt(close) !== 34) {
|
|
5367
|
+
ctx._fx = expected;
|
|
5368
|
+
return ~close;
|
|
5369
|
+
}
|
|
5370
|
+
tuple[1] = match[0];
|
|
5371
|
+
const end = close + 1;
|
|
5372
|
+
ctx._sv = observesSpan ? fn(tuple, { start: pos, end }) : fn(tuple);
|
|
5373
|
+
return end;
|
|
5374
|
+
};
|
|
5375
|
+
})() : /* @__PURE__ */ (() => {
|
|
5376
|
+
return (input, pos, ctx) => {
|
|
5377
|
+
const end = child(input, pos, ctx);
|
|
5378
|
+
if (end < 0) return end;
|
|
5379
|
+
ctx._sv = observesSpan ? fn(ctx._sv, { start: pos, end }) : fn(ctx._sv);
|
|
5380
|
+
return end;
|
|
5381
|
+
};
|
|
5382
|
+
})();
|
|
5159
5383
|
return {
|
|
5160
5384
|
_tag: "transform",
|
|
5161
5385
|
_meta: combinator._meta,
|
|
5162
5386
|
_def: { tag: "transform", parser: combinator, fn },
|
|
5387
|
+
_parseScalar: parseScalar,
|
|
5163
5388
|
parse(input, pos, ctx) {
|
|
5164
5389
|
const result = combinator.parse(input, pos, ctx);
|
|
5165
5390
|
if (!result.ok) return result;
|
|
@@ -5174,9 +5399,11 @@ function trivia(combinator) {
|
|
|
5174
5399
|
_meta: {
|
|
5175
5400
|
...combinator._meta,
|
|
5176
5401
|
isTrivia: true,
|
|
5402
|
+
triviaScanner: fastTriviaScanner(combinator),
|
|
5177
5403
|
...kindLabels ? { triviaKindLabels: kindLabels } : {}
|
|
5178
5404
|
},
|
|
5179
5405
|
_def: { tag: "trivia", parser: combinator },
|
|
5406
|
+
_parseScalar: scalarOf(combinator),
|
|
5180
5407
|
parse: combinator.parse.bind(combinator)
|
|
5181
5408
|
};
|
|
5182
5409
|
}
|
|
@@ -9909,6 +10136,9 @@ if(ctx._rootTriviaLog!==undefined&&ctx._rootTriviaLog.length!==rt)ctx._rootTrivi
|
|
|
9909
10136
|
function q(s) {
|
|
9910
10137
|
return JSON.stringify(s);
|
|
9911
10138
|
}
|
|
10139
|
+
function isAsciiOnlyClass(cls) {
|
|
10140
|
+
return cls !== null && cls !== void 0 && cls.hi.length === 0;
|
|
10141
|
+
}
|
|
9912
10142
|
var NO_SINKS = { fd: false, er: false };
|
|
9913
10143
|
function sinkSlots(t2, s) {
|
|
9914
10144
|
return `${s.fd ? `,${t2}fd=0` : ""}${s.er ? `,${t2}er=0` : ""}`;
|
|
@@ -10455,12 +10685,13 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
10455
10685
|
return `${head}EC.e=pos;return ''}`;
|
|
10456
10686
|
case OP_GATE: {
|
|
10457
10687
|
const child = link(code[ip + 2]);
|
|
10458
|
-
const
|
|
10688
|
+
const resolved = t2.cc[code[ip + 1]];
|
|
10689
|
+
const ci = classes.push([resolved]) - 1;
|
|
10459
10690
|
classPlan.push([code[ip + 1]]);
|
|
10460
10691
|
const cls = hoist("cl", `CLS[${ci}][0]`);
|
|
10461
10692
|
const xf = fxRef(code[ip + 3]);
|
|
10462
10693
|
return `${head}
|
|
10463
|
-
if(
|
|
10694
|
+
if(${staticBuild && isAsciiOnlyClass(resolved) ? `${cls}.ascii[input.charCodeAt(pos)]!==1` : `!classHas(${cls},lead(input,pos))`}){ctx._fe=pos;ctx._fx=${xf};return FAIL}
|
|
10464
10695
|
return ${child}(input,pos,ctx)
|
|
10465
10696
|
}`;
|
|
10466
10697
|
}
|
|
@@ -10803,10 +11034,11 @@ return v
|
|
|
10803
11034
|
const asc = hoist("as", `DISP[${di}].ascii`);
|
|
10804
11035
|
const hiArr = table.hi;
|
|
10805
11036
|
const armSwitch = arms.map((a, i) => `case ${i}:v=${a}(input,pos,ctx);break`).join("\n");
|
|
11037
|
+
const directAscii = staticBuild && table.hi.length === 0;
|
|
10806
11038
|
return `${head}
|
|
10807
|
-
const c
|
|
11039
|
+
const c=${directAscii ? "input.charCodeAt(pos)" : "lead(input,pos)"}
|
|
10808
11040
|
let arm=-1
|
|
10809
|
-
if(c>=0&&c<128){const a=${asc}[c];if(a!==0)arm=a-1}
|
|
11041
|
+
if(${directAscii ? "c<128" : "c>=0&&c<128"}){const a=${asc}[c];if(a!==0)arm=a-1}
|
|
10810
11042
|
${hiArr.length === 0 ? "" : `else if(c>=128){const h=${hoist("hi", `DISP[${di}].hi`)}
|
|
10811
11043
|
for(let i=0;i<h.length;i+=3){if(c>=h[i]&&c<=h[i+1]){arm=h[i+2];break}}}`}
|
|
10812
11044
|
if(arm>=0){
|
|
@@ -10828,7 +11060,9 @@ return FAIL
|
|
|
10828
11060
|
const di = code[ip + 1];
|
|
10829
11061
|
const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
|
|
10830
11062
|
const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
|
|
10831
|
-
const
|
|
11063
|
+
const maskable = n <= 32;
|
|
11064
|
+
const directAsciiMask = staticBuild && maskable && gates.every(isAsciiOnlyClass);
|
|
11065
|
+
const gateRefs = directAsciiMask ? [] : Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
|
|
10832
11066
|
const tokenCandidate = tokenChoiceCandidates.get(ip);
|
|
10833
11067
|
const pretests = Array.from({ length: n }, (_, i) => {
|
|
10834
11068
|
if (tokenCandidate?.arm === i) {
|
|
@@ -10848,7 +11082,6 @@ return FAIL
|
|
|
10848
11082
|
const sequence6 = largeChoiceScalarSequences.get(code[base + i]);
|
|
10849
11083
|
return sequence6 === void 0 ? void 0 : { sequence: scalarSequenceRef(sequence6) };
|
|
10850
11084
|
});
|
|
10851
|
-
const maskable = n <= 32;
|
|
10852
11085
|
const maskName = maskable ? hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`) : "";
|
|
10853
11086
|
if (maskable) maskPlan.push(~di);
|
|
10854
11087
|
const p = tmp();
|
|
@@ -10910,16 +11143,16 @@ ${merge}
|
|
|
10910
11143
|
ctx._fe=pos;ctx._fx=acc??${choiceFx}
|
|
10911
11144
|
return FAIL`;
|
|
10912
11145
|
return `${head}
|
|
10913
|
-
const c
|
|
11146
|
+
const c=${directAsciiMask ? "input.charCodeAt(pos)" : "lead(input,pos)"}
|
|
10914
11147
|
${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
|
|
10915
11148
|
${deepAt.map((at, i) => `let ${at},${deepFx[i]}`).join("\n")}
|
|
10916
11149
|
${maskable ? `if(c<128){
|
|
10917
|
-
const bits=${maskName}[c<0?128:c]
|
|
11150
|
+
const bits=${maskName}[${directAsciiMask ? "c" : "c<0?128:c"}]
|
|
10918
11151
|
if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
|
|
10919
11152
|
${lazyArms(true)}
|
|
10920
|
-
}else{
|
|
11153
|
+
}${directAsciiMask ? "" : `else{
|
|
10921
11154
|
${lazyArms(false)}
|
|
10922
|
-
}
|
|
11155
|
+
}`}
|
|
10923
11156
|
` : lazyArms(false)}
|
|
10924
11157
|
${finish}
|
|
10925
11158
|
}`;
|
|
@@ -10970,7 +11203,7 @@ if(ctx._fc===true){${startFailureExact ? `if(best===pos){acc=${catchName}(${i},0
|
|
|
10970
11203
|
${rollbackFor(i)}
|
|
10971
11204
|
}${routeMiss}${sequenceMiss}`;
|
|
10972
11205
|
}).join("\n") : "";
|
|
10973
|
-
const generalArms = arms.map((arm, i) => {
|
|
11206
|
+
const generalArms = directAsciiMask ? "" : arms.map((arm, i) => {
|
|
10974
11207
|
const pretest = pretests[i];
|
|
10975
11208
|
const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
|
|
10976
11209
|
const scalarCondition = pretest?.scalar === void 0 ? "" : pretest.scalar.length === 1 ? `&&${pretest.scalar[0]}(input,pos)>=0` : `&&(${pretest.scalar.map((recognize) => `${recognize}(input,pos)>=0`).join("||")})`;
|
|
@@ -11000,12 +11233,12 @@ ${rollbackFor(i)}
|
|
|
11000
11233
|
}${miss}`;
|
|
11001
11234
|
}).join("\n");
|
|
11002
11235
|
return `${head}
|
|
11003
|
-
const c
|
|
11236
|
+
const c=${directAsciiMask ? "input.charCodeAt(pos)" : "lead(input,pos)"}
|
|
11004
11237
|
${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
|
|
11005
11238
|
let acc
|
|
11006
11239
|
let best=pos
|
|
11007
11240
|
${maskable ? `if(c<128){
|
|
11008
|
-
const bits=${maskName}[c<0?128:c]
|
|
11241
|
+
const bits=${maskName}[${directAsciiMask ? "c" : "c<0?128:c"}]
|
|
11009
11242
|
if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
|
|
11010
11243
|
${startFailureExact ? "" : "let prev=0"}
|
|
11011
11244
|
${maskArms}
|
|
@@ -11100,14 +11333,18 @@ return [key,v]
|
|
|
11100
11333
|
const itemFx = reportItem ? fxRef(code[ip + 6]) : "EMPTY_FX";
|
|
11101
11334
|
const collect = op === OP_REP;
|
|
11102
11335
|
let itemCls;
|
|
11336
|
+
let itemAscii = false;
|
|
11103
11337
|
if (!REC) {
|
|
11104
11338
|
const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
|
|
11105
11339
|
if (itemClassIndex >= 0) {
|
|
11106
|
-
const
|
|
11340
|
+
const resolved = t2.cc[itemClassIndex];
|
|
11341
|
+
const ci = classes.push([resolved]) - 1;
|
|
11107
11342
|
classPlan.push([itemClassIndex]);
|
|
11108
11343
|
itemCls = hoist("ri", `CLS[${ci}][0]`);
|
|
11344
|
+
itemAscii = staticBuild && isAsciiOnlyClass(resolved);
|
|
11109
11345
|
}
|
|
11110
11346
|
}
|
|
11347
|
+
const itemMiss = (at) => itemAscii ? `${itemCls}.ascii[input.charCodeAt(${at})]!==1` : `!classHas(${itemCls},lead(input,${at}))`;
|
|
11111
11348
|
const skipBeforeFirst = sepIp < 0 && min === 0;
|
|
11112
11349
|
const p = tmp();
|
|
11113
11350
|
const via = sep !== void 0 ? "false" : min === 0 ? skipBeforeFirst ? "true" : "count>0" : `count>=${min}&&count>0`;
|
|
@@ -11167,7 +11404,7 @@ let count=0
|
|
|
11167
11404
|
for(;;){
|
|
11168
11405
|
${max >= 0 ? `if(count>=${max})break
|
|
11169
11406
|
` : ""}${sep !== void 0 ? `if(count>0&&count>=${min}&&cur>=input.length)break
|
|
11170
|
-
` : ""}${itemCls !== void 0 && sep === void 0 ? `if(count>=${min}&&${p}gate&&${hasTrivia === "false" ? "true" : hasTrivia === "true" ? "false" : "!hasTrivia"}
|
|
11407
|
+
` : ""}${itemCls !== void 0 && sep === void 0 ? `if(count>=${min}&&${p}gate&&${hasTrivia === "false" ? "true" : hasTrivia === "true" ? "false" : "!hasTrivia"}&&${itemMiss("cur")})break
|
|
11171
11408
|
` : ""}let ${p}raw=0,${p}tl=0,${p}lv=0,${p}lg=0,${p}rt=0${sinks.fd ? `,${p}fd=0` : ""}${sinks.er ? `,${p}er=0` : ""}
|
|
11172
11409
|
${markBody}
|
|
11173
11410
|
let itemStart=cur
|
|
@@ -11192,7 +11429,7 @@ itemStart=${hasTrivia === "false" ? "EC.e" : hasTrivia === "true" ? `${skip}(inp
|
|
|
11192
11429
|
${rb}
|
|
11193
11430
|
${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
|
|
11194
11431
|
}
|
|
11195
|
-
${itemCls === void 0 ? "" : `if(count>=${min}&&${p}gate
|
|
11432
|
+
${itemCls === void 0 ? "" : `if(count>=${min}&&${p}gate&&${itemMiss("itemStart")}){
|
|
11196
11433
|
${rb}
|
|
11197
11434
|
${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
|
|
11198
11435
|
}
|