parseman 0.50.1 → 0.50.4
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 +455 -229
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/cli/index.js +445 -194
- package/dist/cli/index.js.map +3 -3
- package/dist/combinators/choice.d.ts.map +1 -1
- package/dist/combinators/first-set.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 +22 -11
- package/dist/compiler/token-capability.js.map +2 -2
- package/dist/index.js +446 -195
- 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 +491 -309
- 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 +421 -285
- package/dist/spec/index.js.map +3 -3
- package/dist/table/emit-assembly.d.ts.map +1 -1
- package/dist/table/encode.d.ts.map +1 -1
- package/dist/table/index.js +331 -191
- 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 +5 -3
- package/src/combinators/choice.ts +34 -1
- package/src/combinators/first-set.ts +33 -7
- 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/table/encode.ts +14 -2
- package/src/types.ts +8 -0
- package/src/version.ts +1 -1
package/dist/table/index.js
CHANGED
|
@@ -35,10 +35,20 @@ function classifyFinalChoice(arms, resolve) {
|
|
|
35
35
|
}
|
|
36
36
|
return { exclusive, firstSets, nullable: nullable2 };
|
|
37
37
|
}
|
|
38
|
-
function
|
|
38
|
+
function winnerForRef(p, resolve) {
|
|
39
39
|
if (resolve === void 0) return void 0;
|
|
40
40
|
const name = p._ruleName;
|
|
41
|
-
|
|
41
|
+
const w = name === void 0 ? void 0 : resolve(name);
|
|
42
|
+
if (w === void 0 || w === p) return void 0;
|
|
43
|
+
let cur = w;
|
|
44
|
+
for (const seen = /* @__PURE__ */ new Set(); !seen.has(cur); ) {
|
|
45
|
+
if (cur === p) return void 0;
|
|
46
|
+
seen.add(cur);
|
|
47
|
+
const cd = cur._def;
|
|
48
|
+
if (cd.tag !== "grammar" && cd.tag !== "trivia") return w;
|
|
49
|
+
cur = cd.parser;
|
|
50
|
+
}
|
|
51
|
+
return w;
|
|
42
52
|
}
|
|
43
53
|
function union(a, b) {
|
|
44
54
|
if (a.kind === "any" || b.kind === "any") return { kind: "any" };
|
|
@@ -136,13 +146,15 @@ function matchesEmptyBody(p, seen, resolve) {
|
|
|
136
146
|
case "grammar":
|
|
137
147
|
case "recover":
|
|
138
148
|
return me(d.parser);
|
|
139
|
-
case "lazy":
|
|
149
|
+
case "lazy": {
|
|
150
|
+
const w = winnerForRef(p, resolve);
|
|
151
|
+
if (w !== void 0) return me(w);
|
|
140
152
|
try {
|
|
141
153
|
return me(d.thunk());
|
|
142
154
|
} catch {
|
|
143
|
-
|
|
144
|
-
return t ? me(t) : true;
|
|
155
|
+
return true;
|
|
145
156
|
}
|
|
157
|
+
}
|
|
146
158
|
default:
|
|
147
159
|
return true;
|
|
148
160
|
}
|
|
@@ -206,13 +218,15 @@ function firstSetBody(p, seen, resolve) {
|
|
|
206
218
|
// terminals: no refs, cached set is exact
|
|
207
219
|
case "dispatch":
|
|
208
220
|
return fs(d.selector);
|
|
209
|
-
case "lazy":
|
|
221
|
+
case "lazy": {
|
|
222
|
+
const w = winnerForRef(p, resolve);
|
|
223
|
+
if (w !== void 0) return fs(w);
|
|
210
224
|
try {
|
|
211
225
|
return fs(d.thunk());
|
|
212
226
|
} catch {
|
|
213
|
-
|
|
214
|
-
return t ? fs(t) : any();
|
|
227
|
+
return any();
|
|
215
228
|
}
|
|
229
|
+
}
|
|
216
230
|
case "choice": {
|
|
217
231
|
let out = empty();
|
|
218
232
|
for (const arm of d.parsers) out = union(out, fs(arm));
|
|
@@ -522,6 +536,28 @@ function literal(value, opts = {}) {
|
|
|
522
536
|
isTrivia: false
|
|
523
537
|
};
|
|
524
538
|
const canMatchNewline = meta.canMatchNewline;
|
|
539
|
+
const parseScalar = !caseInsensitive && value.length === 1 ? (() => {
|
|
540
|
+
const code = value.charCodeAt(0);
|
|
541
|
+
return (input, pos, ctx) => {
|
|
542
|
+
if (input.charCodeAt(pos) === code) {
|
|
543
|
+
ctx._sv = value;
|
|
544
|
+
return pos + 1;
|
|
545
|
+
}
|
|
546
|
+
ctx._fx = expected;
|
|
547
|
+
return ~pos;
|
|
548
|
+
};
|
|
549
|
+
})() : (input, pos, ctx) => {
|
|
550
|
+
const end = pos + value.length;
|
|
551
|
+
if (end <= input.length) {
|
|
552
|
+
const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
|
|
553
|
+
if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
|
|
554
|
+
ctx._sv = matchedValue;
|
|
555
|
+
return end;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
ctx._fx = expected;
|
|
559
|
+
return ~pos;
|
|
560
|
+
};
|
|
525
561
|
if (caseInsensitive) {
|
|
526
562
|
const upper = value.toUpperCase();
|
|
527
563
|
const lower = value.toLowerCase();
|
|
@@ -562,6 +598,7 @@ function literal(value, opts = {}) {
|
|
|
562
598
|
_tag: "literal",
|
|
563
599
|
_meta: meta,
|
|
564
600
|
_def: { tag: "literal", value, caseInsensitive },
|
|
601
|
+
_parseScalar: parseScalar,
|
|
565
602
|
parse
|
|
566
603
|
};
|
|
567
604
|
}
|
|
@@ -1018,10 +1055,32 @@ function regex(pattern, flags = "") {
|
|
|
1018
1055
|
const canMatchNewline = raw.canMatchNewline;
|
|
1019
1056
|
const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
|
|
1020
1057
|
const def = { tag: "regex", source, flags: resolvedFlags };
|
|
1058
|
+
const expected = directTerminalFailureExpected(def);
|
|
1059
|
+
const parseScalar = (input, pos, ctx) => {
|
|
1060
|
+
const scanEnd = scan?.(input, pos);
|
|
1061
|
+
if (scanEnd !== void 0) {
|
|
1062
|
+
if (scanEnd === null) {
|
|
1063
|
+
ctx._fx = expected;
|
|
1064
|
+
return ~pos;
|
|
1065
|
+
}
|
|
1066
|
+
ctx._sv = input.slice(pos, scanEnd);
|
|
1067
|
+
return scanEnd;
|
|
1068
|
+
}
|
|
1069
|
+
anchored.lastIndex = pos;
|
|
1070
|
+
const match = anchored.exec(input);
|
|
1071
|
+
if (match === null) {
|
|
1072
|
+
ctx._fx = expected;
|
|
1073
|
+
return ~pos;
|
|
1074
|
+
}
|
|
1075
|
+
ctx._sv = match[0];
|
|
1076
|
+
return pos + match[0].length;
|
|
1077
|
+
};
|
|
1021
1078
|
return {
|
|
1022
1079
|
_tag: "regex",
|
|
1023
1080
|
_meta: meta,
|
|
1024
1081
|
_def: def,
|
|
1082
|
+
_stickyRegex: anchored,
|
|
1083
|
+
_parseScalar: parseScalar,
|
|
1025
1084
|
parse(input, pos, ctx) {
|
|
1026
1085
|
const scanEnd = scan?.(input, pos);
|
|
1027
1086
|
if (scanEnd !== void 0) {
|
|
@@ -1063,6 +1122,7 @@ function createParseContext() {
|
|
|
1063
1122
|
_fe: void 0,
|
|
1064
1123
|
_fx: void 0,
|
|
1065
1124
|
_fc: void 0,
|
|
1125
|
+
_sv: void 0,
|
|
1066
1126
|
_probe: void 0,
|
|
1067
1127
|
_cstChildren: void 0,
|
|
1068
1128
|
_cstLeaves: void 0,
|
|
@@ -1754,6 +1814,9 @@ var fastScanner3;
|
|
|
1754
1814
|
function needsDeferredTriviaCommit(ctx) {
|
|
1755
1815
|
return ctx._triviaLog !== void 0 || ctx._rootTriviaLog !== void 0 || ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0;
|
|
1756
1816
|
}
|
|
1817
|
+
function needsTriviaRollback(ctx) {
|
|
1818
|
+
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;
|
|
1819
|
+
}
|
|
1757
1820
|
function saveTriviaMark(ctx) {
|
|
1758
1821
|
const m = saveCstMark(ctx);
|
|
1759
1822
|
return {
|
|
@@ -1863,7 +1926,8 @@ function advanceTrivia(input, cur, ctx) {
|
|
|
1863
1926
|
const triviaP = ctx.trivia;
|
|
1864
1927
|
if (!triviaP) return cur;
|
|
1865
1928
|
if (!ctx.trackLines) {
|
|
1866
|
-
const
|
|
1929
|
+
const classified = triviaP._meta.triviaScanner;
|
|
1930
|
+
const fast2 = classified === void 0 ? fastTriviaScanner(triviaP) : classified;
|
|
1867
1931
|
if (fast2) return fast2(input, cur);
|
|
1868
1932
|
if (ctx.triviaKindLabels) return skipWithLabels(input, cur, ctx);
|
|
1869
1933
|
const tr2 = triviaP.parse(input, cur, createDetachedParseContext(ctx.trackLines, ctx.state));
|
|
@@ -2416,6 +2480,11 @@ function adjacencyMisuse(polarity) {
|
|
|
2416
2480
|
return new TypeError(`${polarity}(): ${NO_STANDALONE_PARSE}`);
|
|
2417
2481
|
}
|
|
2418
2482
|
|
|
2483
|
+
// src/combinators/scalar.ts
|
|
2484
|
+
function scalarOf(combinator) {
|
|
2485
|
+
return combinator._parseScalar;
|
|
2486
|
+
}
|
|
2487
|
+
|
|
2419
2488
|
// src/combinators/sequence.ts
|
|
2420
2489
|
function sequence(...parsers) {
|
|
2421
2490
|
let adjacency = null;
|
|
@@ -2431,6 +2500,7 @@ function sequence(...parsers) {
|
|
|
2431
2500
|
(adjacency ??= Array.from({ length: parsers.length }, () => null))[i] = a;
|
|
2432
2501
|
}
|
|
2433
2502
|
const hasAdjacency = adjacency !== null;
|
|
2503
|
+
const strictArity = !hasAdjacency && (parsers.length === 2 && !matchesEmpty(parsers[1]) || parsers.length === 3 && parsers.every((p) => !matchesEmpty(p))) ? parsers.length : 0;
|
|
2434
2504
|
const meta = {
|
|
2435
2505
|
// Union through the nullable prefix — a leading optional()/many() lets a later
|
|
2436
2506
|
// term's first char start the sequence. Just `parsers[0]` under-approximates.
|
|
@@ -2439,165 +2509,96 @@ function sequence(...parsers) {
|
|
|
2439
2509
|
isTrivia: false
|
|
2440
2510
|
};
|
|
2441
2511
|
const def = { tag: "sequence", parsers };
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
followSentinels ??= parsers.map((_, i) => {
|
|
2445
|
-
const fs = parsers.slice(i + 1).reduce(
|
|
2446
|
-
(acc, p) => union(acc, firstSetOf(p)),
|
|
2447
|
-
{ kind: "empty" }
|
|
2448
|
-
);
|
|
2449
|
-
return firstSetSentinel(fs);
|
|
2450
|
-
});
|
|
2451
|
-
const values = def.valueUnused ? void 0 : [];
|
|
2512
|
+
const scalarParsers = parsers.map(scalarOf);
|
|
2513
|
+
const parseScalar = (input, pos, ctx) => {
|
|
2452
2514
|
let cur = pos;
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
const mTlog = cstTlLen(ctx);
|
|
2465
|
-
const mLog = ctx._triviaLog?.length ?? 0;
|
|
2466
|
-
const mRootLog = ctx._rootTriviaLog?.length ?? 0;
|
|
2467
|
-
let scanEnd;
|
|
2468
|
-
if (needsDeferredTriviaCommit(ctx)) {
|
|
2469
|
-
scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
|
|
2470
|
-
} else {
|
|
2471
|
-
scanEnd = advanceTrivia(input, cur, ctx);
|
|
2472
|
-
}
|
|
2473
|
-
const scanTlog = cstTlLen(ctx);
|
|
2474
|
-
const scanLog = ctx._triviaLog?.length ?? 0;
|
|
2475
|
-
const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
|
|
2476
|
-
const result2 = parsers[i].parse(input, scanEnd, ctx);
|
|
2477
|
-
if (!result2.ok) return result2;
|
|
2478
|
-
if (result2.span.end > scanEnd) cur = result2.span.end;
|
|
2479
|
-
else rollbackScannedTriviaAt(
|
|
2480
|
-
ctx,
|
|
2481
|
-
mTlog,
|
|
2482
|
-
scanTlog,
|
|
2483
|
-
mLog,
|
|
2484
|
-
scanLog,
|
|
2485
|
-
mRootLog,
|
|
2486
|
-
scanRootLog
|
|
2487
|
-
);
|
|
2488
|
-
if (values !== void 0) values.push(result2.value);
|
|
2489
|
-
continue;
|
|
2490
|
-
}
|
|
2491
|
-
const result = parsers[i].parse(input, cur, ctx);
|
|
2492
|
-
if (!result.ok) return result;
|
|
2493
|
-
if (values !== void 0) values.push(result.value);
|
|
2494
|
-
cur = result.span.end;
|
|
2515
|
+
if (strictArity !== 0) {
|
|
2516
|
+
cur = scalarParsers[0](input, cur, ctx);
|
|
2517
|
+
if (cur < 0) return cur;
|
|
2518
|
+
const first = ctx._sv;
|
|
2519
|
+
if (ctx.trivia) cur = advanceTrivia(input, cur, ctx);
|
|
2520
|
+
cur = scalarParsers[1](input, cur, ctx);
|
|
2521
|
+
if (cur < 0) return cur;
|
|
2522
|
+
const second = ctx._sv;
|
|
2523
|
+
if (strictArity === 2) {
|
|
2524
|
+
ctx._sv = def.valueUnused ? void 0 : [first, second];
|
|
2525
|
+
return cur;
|
|
2495
2526
|
}
|
|
2496
|
-
|
|
2497
|
-
|
|
2527
|
+
if (ctx.trivia) cur = advanceTrivia(input, cur, ctx);
|
|
2528
|
+
cur = scalarParsers[2](input, cur, ctx);
|
|
2529
|
+
if (cur < 0) return cur;
|
|
2530
|
+
ctx._sv = def.valueUnused ? void 0 : [first, second, ctx._sv];
|
|
2531
|
+
return cur;
|
|
2498
2532
|
}
|
|
2499
|
-
return {
|
|
2500
|
-
ok: true,
|
|
2501
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
2502
|
-
value: values ?? void 0,
|
|
2503
|
-
span: { start: pos, end: cur }
|
|
2504
|
-
};
|
|
2505
|
-
}
|
|
2506
|
-
function parseAdjacent(input, pos, ctx) {
|
|
2507
2533
|
const values = def.valueUnused ? void 0 : [];
|
|
2508
|
-
let
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
const mRootLog = ctx._rootTriviaLog?.length ?? 0;
|
|
2521
|
-
if (needsDeferredTriviaCommit(ctx)) {
|
|
2522
|
-
scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
|
|
2523
|
-
} else {
|
|
2524
|
-
scanEnd = advanceTrivia(input, cur, ctx);
|
|
2525
|
-
}
|
|
2526
|
-
const scanTlog = cstTlLen(ctx);
|
|
2527
|
-
const scanLog = ctx._triviaLog?.length ?? 0;
|
|
2528
|
-
const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
|
|
2529
|
-
const result2 = parsers[i].parse(input, scanEnd, ctx);
|
|
2530
|
-
if (!result2.ok) return result2;
|
|
2531
|
-
if (result2.span.end > scanEnd) cur = result2.span.end;
|
|
2532
|
-
else rollbackScannedTriviaAt(
|
|
2533
|
-
ctx,
|
|
2534
|
-
mTlog,
|
|
2535
|
-
scanTlog,
|
|
2536
|
-
mLog,
|
|
2537
|
-
scanLog,
|
|
2538
|
-
mRootLog,
|
|
2539
|
-
scanRootLog
|
|
2540
|
-
);
|
|
2541
|
-
if (values !== void 0) values.push(result2.value);
|
|
2542
|
-
continue;
|
|
2543
|
-
}
|
|
2544
|
-
const result = parsers[i].parse(input, cur, ctx);
|
|
2545
|
-
if (!result.ok) return result;
|
|
2546
|
-
if (values !== void 0) values.push(result.value);
|
|
2547
|
-
cur = result.span.end;
|
|
2548
|
-
}
|
|
2549
|
-
return {
|
|
2550
|
-
ok: true,
|
|
2551
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
2552
|
-
value: values ?? void 0,
|
|
2553
|
-
span: { start: pos, end: cur }
|
|
2554
|
-
};
|
|
2555
|
-
}
|
|
2534
|
+
for (let i = 0; i < scalarParsers.length; i++) {
|
|
2535
|
+
let termPos = cur;
|
|
2536
|
+
if (i > 0 && ctx.trivia) termPos = advanceTrivia(input, cur, ctx);
|
|
2537
|
+
const end = scalarParsers[i](input, termPos, ctx);
|
|
2538
|
+
if (end < 0) return end;
|
|
2539
|
+
if (values !== void 0) values.push(ctx._sv);
|
|
2540
|
+
if (end > termPos || termPos === cur) cur = end;
|
|
2541
|
+
}
|
|
2542
|
+
ctx._sv = values;
|
|
2543
|
+
return cur;
|
|
2544
|
+
};
|
|
2545
|
+
let followSentinels;
|
|
2556
2546
|
return {
|
|
2557
2547
|
_tag: "sequence",
|
|
2558
2548
|
_meta: meta,
|
|
2559
2549
|
_def: def,
|
|
2550
|
+
_parseScalar: hasAdjacency ? void 0 : parseScalar,
|
|
2560
2551
|
parse(input, pos, ctx) {
|
|
2561
|
-
|
|
2562
|
-
if (
|
|
2552
|
+
const tolerant = ctx._tolerant === true;
|
|
2553
|
+
if (tolerant) {
|
|
2554
|
+
followSentinels ??= parsers.map((_, i) => firstSetSentinel(
|
|
2555
|
+
parsers.slice(i + 1).reduce(
|
|
2556
|
+
(set, parser) => union(set, firstSetOf(parser)),
|
|
2557
|
+
{ kind: "empty" }
|
|
2558
|
+
)
|
|
2559
|
+
));
|
|
2560
|
+
}
|
|
2561
|
+
const inheritedSync = ctx._sync;
|
|
2562
|
+
const deferredTrivia = needsDeferredTriviaCommit(ctx);
|
|
2563
2563
|
const values = def.valueUnused ? void 0 : [];
|
|
2564
2564
|
let cur = pos;
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
const
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
} else {
|
|
2574
|
-
scanEnd = advanceTrivia(input, cur, ctx);
|
|
2565
|
+
try {
|
|
2566
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
2567
|
+
if (tolerant) ctx._sync = followSentinels[i] ?? inheritedSync;
|
|
2568
|
+
const assertion = adjacency?.[i];
|
|
2569
|
+
if (assertion) {
|
|
2570
|
+
if (!holdsAdjacency(input, cur, ctx, assertion)) return adjacencyFail(cur, assertion);
|
|
2571
|
+
if (values !== void 0) values.push(null);
|
|
2572
|
+
continue;
|
|
2575
2573
|
}
|
|
2576
|
-
|
|
2577
|
-
const
|
|
2578
|
-
const
|
|
2579
|
-
const
|
|
2580
|
-
if (
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2574
|
+
let termPos = cur;
|
|
2575
|
+
const markTlog = deferredTrivia ? cstTlLen(ctx) : 0;
|
|
2576
|
+
const markLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
|
|
2577
|
+
const markRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
2578
|
+
if (ctx.trivia && i > 0) {
|
|
2579
|
+
termPos = deferredTrivia ? commitTriviaScan(scanTriviaCompact(input, cur, ctx)) : advanceTrivia(input, cur, ctx);
|
|
2580
|
+
}
|
|
2581
|
+
const scanTlog = deferredTrivia ? cstTlLen(ctx) : 0;
|
|
2582
|
+
const scanLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
|
|
2583
|
+
const scanRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
2584
|
+
const result = parsers[i].parse(input, termPos, ctx);
|
|
2585
|
+
if (!result.ok) return result;
|
|
2586
|
+
if (values !== void 0) values.push(result.value);
|
|
2587
|
+
if (result.span.end > termPos || termPos === cur) cur = result.span.end;
|
|
2588
|
+
else if (deferredTrivia) {
|
|
2584
2589
|
rollbackScannedTriviaAt(
|
|
2585
2590
|
ctx,
|
|
2586
|
-
|
|
2591
|
+
markTlog,
|
|
2587
2592
|
scanTlog,
|
|
2588
|
-
|
|
2593
|
+
markLog,
|
|
2589
2594
|
scanLog,
|
|
2590
|
-
|
|
2595
|
+
markRootLog,
|
|
2591
2596
|
scanRootLog
|
|
2592
2597
|
);
|
|
2593
2598
|
}
|
|
2594
|
-
if (values !== void 0) values.push(result2.value);
|
|
2595
|
-
continue;
|
|
2596
2599
|
}
|
|
2597
|
-
|
|
2598
|
-
if (
|
|
2599
|
-
if (values !== void 0) values.push(result.value);
|
|
2600
|
-
cur = result.span.end;
|
|
2600
|
+
} finally {
|
|
2601
|
+
if (tolerant) ctx._sync = inheritedSync;
|
|
2601
2602
|
}
|
|
2602
2603
|
return {
|
|
2603
2604
|
ok: true,
|
|
@@ -2729,7 +2730,8 @@ function choice(...args) {
|
|
|
2729
2730
|
disjoint
|
|
2730
2731
|
};
|
|
2731
2732
|
const strategy = disjoint || hasGates ? null : detectStrategy(parsers);
|
|
2732
|
-
const
|
|
2733
|
+
const ordered = strategy?.tag === "firstMatch" || strategy?.tag === "sharedPrefix";
|
|
2734
|
+
const autoNot = !disjoint && !hasGates && ordered ? computeAutoNot(parsers) : parsers.map(() => null);
|
|
2733
2735
|
let greedyLitMap = null;
|
|
2734
2736
|
let sortedParsers = null;
|
|
2735
2737
|
const asciiDispatch = disjoint ? buildAsciiDispatch(parsers) : null;
|
|
@@ -2743,6 +2745,37 @@ function choice(...args) {
|
|
|
2743
2745
|
} else if (strategy?.tag === "literalsLongestFirst") {
|
|
2744
2746
|
sortedParsers = strategy.sortedIndices.map((i) => parsers[i]);
|
|
2745
2747
|
}
|
|
2748
|
+
const scalarParsers = parsers.map(scalarOf);
|
|
2749
|
+
const scalarEligible = !hasGates && parsers.every((p) => p._parseScalar !== void 0) && (disjoint || ordered);
|
|
2750
|
+
const scalarExpected = parsers.flatMap(deriveExpected);
|
|
2751
|
+
const parseScalar = (input, pos, ctx) => {
|
|
2752
|
+
if (disjoint) {
|
|
2753
|
+
const code = pos < input.length ? input.codePointAt(pos) : -1;
|
|
2754
|
+
let idx = code >= 0 && code < 128 ? asciiDispatch[code] : -1;
|
|
2755
|
+
if (idx < 0 && code >= 0) {
|
|
2756
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
2757
|
+
if (inFirstSet(code, parsers[i]._meta.firstSet)) {
|
|
2758
|
+
idx = i;
|
|
2759
|
+
break;
|
|
2760
|
+
}
|
|
2761
|
+
}
|
|
2762
|
+
}
|
|
2763
|
+
if (idx >= 0) {
|
|
2764
|
+
const gate = gates[idx];
|
|
2765
|
+
if (!gate || gate(ctx.state)) return scalarParsers[idx](input, pos, ctx);
|
|
2766
|
+
ctx._fx = deriveExpected(parsers[idx]);
|
|
2767
|
+
return ~pos;
|
|
2768
|
+
}
|
|
2769
|
+
} else {
|
|
2770
|
+
for (let i = 0; i < scalarParsers.length; i++) {
|
|
2771
|
+
if (gates[i] && !gates[i](ctx.state)) continue;
|
|
2772
|
+
const end = scalarParsers[i](input, pos, ctx);
|
|
2773
|
+
if (end >= 0 && (!autoNot[i] || !autoNotFires(input, end, autoNot[i]))) return end;
|
|
2774
|
+
}
|
|
2775
|
+
}
|
|
2776
|
+
ctx._fx = scalarExpected;
|
|
2777
|
+
return ~pos;
|
|
2778
|
+
};
|
|
2746
2779
|
return {
|
|
2747
2780
|
_tag: "choice",
|
|
2748
2781
|
_meta: meta,
|
|
@@ -2754,6 +2787,7 @@ function choice(...args) {
|
|
|
2754
2787
|
strategy: strategy ?? { tag: "firstMatch" },
|
|
2755
2788
|
autoNot
|
|
2756
2789
|
},
|
|
2790
|
+
_parseScalar: scalarEligible ? parseScalar : void 0,
|
|
2757
2791
|
parse(input, pos, ctx) {
|
|
2758
2792
|
const expected = [];
|
|
2759
2793
|
let expectedAt = pos;
|
|
@@ -3014,8 +3048,8 @@ function buildAsciiDispatch(parsers) {
|
|
|
3014
3048
|
}
|
|
3015
3049
|
|
|
3016
3050
|
// src/combinators/repeat.ts
|
|
3017
|
-
function repItem(combinator, input, cur, ctx, guardable, mandatory) {
|
|
3018
|
-
const mark = saveTriviaMark(ctx);
|
|
3051
|
+
function repItem(combinator, input, cur, ctx, guardable, mandatory, rollbackNeeded) {
|
|
3052
|
+
const mark = rollbackNeeded ? saveTriviaMark(ctx) : void 0;
|
|
3019
3053
|
let pos = cur;
|
|
3020
3054
|
if (ctx.trivia) {
|
|
3021
3055
|
if (needsDeferredTriviaCommit(ctx)) {
|
|
@@ -3025,24 +3059,24 @@ function repItem(combinator, input, cur, ctx, guardable, mandatory) {
|
|
|
3025
3059
|
}
|
|
3026
3060
|
}
|
|
3027
3061
|
if (pos >= input.length && !mandatory) {
|
|
3028
|
-
rollbackTrivia(ctx, mark);
|
|
3062
|
+
if (mark !== void 0) rollbackTrivia(ctx, mark);
|
|
3029
3063
|
return "stop";
|
|
3030
3064
|
}
|
|
3031
3065
|
if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(combinator, input, pos)) {
|
|
3032
|
-
rollbackTrivia(ctx, mark);
|
|
3066
|
+
if (mark !== void 0) rollbackTrivia(ctx, mark);
|
|
3033
3067
|
return "stop";
|
|
3034
3068
|
}
|
|
3035
3069
|
const result = combinator.parse(input, pos, ctx);
|
|
3036
3070
|
if (!result.ok) {
|
|
3037
|
-
rollbackTrivia(ctx, mark);
|
|
3071
|
+
if (mark !== void 0) rollbackTrivia(ctx, mark);
|
|
3038
3072
|
if (result.committed) return { fail: result, failPos: pos };
|
|
3039
3073
|
return { fail: result, failPos: pos };
|
|
3040
3074
|
}
|
|
3041
3075
|
if (result.span.end === pos && !mandatory) {
|
|
3042
|
-
rollbackTrivia(ctx, mark);
|
|
3076
|
+
if (mark !== void 0) rollbackTrivia(ctx, mark);
|
|
3043
3077
|
return "stop";
|
|
3044
3078
|
}
|
|
3045
|
-
return
|
|
3079
|
+
return result;
|
|
3046
3080
|
}
|
|
3047
3081
|
function resolveBounds(what, opts) {
|
|
3048
3082
|
const min = opts.min ?? 0;
|
|
@@ -3055,6 +3089,21 @@ function resolveBounds(what, opts) {
|
|
|
3055
3089
|
if (max < min) bad(`max (${max}) is less than min (${min}) \u2014 the combinator could never succeed`);
|
|
3056
3090
|
return { min, max };
|
|
3057
3091
|
}
|
|
3092
|
+
function repeatScalarTail(combinator, child, input, cur, ctx, guardable, values, remaining) {
|
|
3093
|
+
while (cur < input.length && remaining > 0) {
|
|
3094
|
+
let itemPos = cur;
|
|
3095
|
+
if (ctx.trivia) itemPos = advanceTrivia(input, cur, ctx);
|
|
3096
|
+
if (itemPos >= input.length) break;
|
|
3097
|
+
if (guardable && !startsFirstSet(combinator, input, itemPos)) break;
|
|
3098
|
+
const end = child(input, itemPos, ctx);
|
|
3099
|
+
if (end <= itemPos) break;
|
|
3100
|
+
if (values !== void 0) values.push(ctx._sv);
|
|
3101
|
+
cur = end;
|
|
3102
|
+
remaining--;
|
|
3103
|
+
}
|
|
3104
|
+
ctx._sv = values;
|
|
3105
|
+
return cur;
|
|
3106
|
+
}
|
|
3058
3107
|
function many(combinator, opts = {}) {
|
|
3059
3108
|
const { min, max } = resolveBounds("many()", opts);
|
|
3060
3109
|
if (min >= 1) return atLeast(combinator, min, max);
|
|
@@ -3066,17 +3115,21 @@ function many(combinator, opts = {}) {
|
|
|
3066
3115
|
const def = { tag: "many", parser: combinator, min: 0, ...max === Infinity ? {} : { max } };
|
|
3067
3116
|
let expected;
|
|
3068
3117
|
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
3118
|
+
const scalarChild = scalarOf(combinator);
|
|
3119
|
+
const parseScalar = (input, pos, ctx) => repeatScalarTail(combinator, scalarChild, input, pos, ctx, guardable, def.valueUnused ? void 0 : [], max);
|
|
3069
3120
|
return {
|
|
3070
3121
|
_tag: "many",
|
|
3071
3122
|
_meta: meta,
|
|
3072
3123
|
_def: def,
|
|
3124
|
+
_parseScalar: parseScalar,
|
|
3073
3125
|
parse(input, pos, ctx) {
|
|
3074
3126
|
const values = def.valueUnused ? void 0 : [];
|
|
3127
|
+
const rollbackNeeded = needsTriviaRollback(ctx);
|
|
3075
3128
|
let cur = pos;
|
|
3076
3129
|
let count = 0;
|
|
3077
3130
|
while (cur < input.length) {
|
|
3078
3131
|
if (count >= max) break;
|
|
3079
|
-
const item = repItem(combinator, input, cur, ctx, guardable, false);
|
|
3132
|
+
const item = repItem(combinator, input, cur, ctx, guardable, false, rollbackNeeded);
|
|
3080
3133
|
if (item === "stop") break;
|
|
3081
3134
|
if ("fail" in item) {
|
|
3082
3135
|
if (!item.fail.ok && item.fail.committed) return item.fail;
|
|
@@ -3093,7 +3146,7 @@ function many(combinator, opts = {}) {
|
|
|
3093
3146
|
}
|
|
3094
3147
|
if (values !== void 0) values.push(item.value);
|
|
3095
3148
|
count++;
|
|
3096
|
-
cur = item.end;
|
|
3149
|
+
cur = item.span.end;
|
|
3097
3150
|
}
|
|
3098
3151
|
return { ok: true, value: values ?? void 0, span: { start: pos, end: cur } };
|
|
3099
3152
|
}
|
|
@@ -3111,30 +3164,47 @@ function atLeast(combinator, min, max) {
|
|
|
3111
3164
|
const def = { tag: "oneOrMore", parser: combinator, min, ...max === Infinity ? {} : { max } };
|
|
3112
3165
|
let expected;
|
|
3113
3166
|
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
3167
|
+
const scalarChild = scalarOf(combinator);
|
|
3168
|
+
const parseScalar = (input, pos, ctx) => {
|
|
3169
|
+
let cur = scalarChild(input, pos, ctx);
|
|
3170
|
+
if (cur < 0) return cur;
|
|
3171
|
+
const values = def.valueUnused ? void 0 : [ctx._sv];
|
|
3172
|
+
for (let count = 1; count < min; count++) {
|
|
3173
|
+
let itemPos = cur;
|
|
3174
|
+
if (ctx.trivia) itemPos = advanceTrivia(input, cur, ctx);
|
|
3175
|
+
const end = scalarChild(input, itemPos, ctx);
|
|
3176
|
+
if (end < 0) return ~cur;
|
|
3177
|
+
cur = end;
|
|
3178
|
+
if (values !== void 0) values.push(ctx._sv);
|
|
3179
|
+
}
|
|
3180
|
+
return repeatScalarTail(combinator, scalarChild, input, cur, ctx, guardable, values, max - min);
|
|
3181
|
+
};
|
|
3114
3182
|
return {
|
|
3115
3183
|
_tag: "oneOrMore",
|
|
3116
3184
|
_meta: meta,
|
|
3117
3185
|
_def: def,
|
|
3186
|
+
_parseScalar: parseScalar,
|
|
3118
3187
|
parse(input, pos, ctx) {
|
|
3119
3188
|
const first = combinator.parse(input, pos, ctx);
|
|
3120
3189
|
if (!first.ok) return first;
|
|
3121
3190
|
const values = def.valueUnused ? void 0 : [first.value];
|
|
3191
|
+
const rollbackNeeded = needsTriviaRollback(ctx);
|
|
3122
3192
|
let cur = first.span.end;
|
|
3123
3193
|
let count = 1;
|
|
3124
3194
|
while (count < min) {
|
|
3125
|
-
const item = repItem(combinator, input, cur, ctx, guardable, true);
|
|
3195
|
+
const item = repItem(combinator, input, cur, ctx, guardable, true, rollbackNeeded);
|
|
3126
3196
|
if (item === "stop" || "fail" in item) {
|
|
3127
3197
|
if (item !== "stop" && !item.fail.ok && item.fail.committed) return item.fail;
|
|
3128
3198
|
expected ??= deriveExpected(combinator);
|
|
3129
3199
|
return { ok: false, expected: expected.length > 0 ? expected : [combinator._tag], span: { start: cur, end: cur } };
|
|
3130
3200
|
}
|
|
3131
3201
|
if (values !== void 0) values.push(item.value);
|
|
3132
|
-
cur = item.end;
|
|
3202
|
+
cur = item.span.end;
|
|
3133
3203
|
count++;
|
|
3134
3204
|
}
|
|
3135
3205
|
while (cur < input.length) {
|
|
3136
3206
|
if (count >= max) break;
|
|
3137
|
-
const item = repItem(combinator, input, cur, ctx, guardable, false);
|
|
3207
|
+
const item = repItem(combinator, input, cur, ctx, guardable, false, rollbackNeeded);
|
|
3138
3208
|
if (item === "stop") break;
|
|
3139
3209
|
if ("fail" in item) {
|
|
3140
3210
|
if (!item.fail.ok && item.fail.committed) return item.fail;
|
|
@@ -3151,7 +3221,7 @@ function atLeast(combinator, min, max) {
|
|
|
3151
3221
|
}
|
|
3152
3222
|
if (values !== void 0) values.push(item.value);
|
|
3153
3223
|
count++;
|
|
3154
|
-
cur = item.end;
|
|
3224
|
+
cur = item.span.end;
|
|
3155
3225
|
}
|
|
3156
3226
|
return { ok: true, value: values ?? void 0, span: { start: pos, end: cur } };
|
|
3157
3227
|
}
|
|
@@ -3159,11 +3229,54 @@ function atLeast(combinator, min, max) {
|
|
|
3159
3229
|
}
|
|
3160
3230
|
|
|
3161
3231
|
// src/combinators/map.ts
|
|
3232
|
+
var JSON_STRING_BODY = String.raw`(?:[^"\\]|\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4}))*`;
|
|
3162
3233
|
function transform(combinator, fn) {
|
|
3234
|
+
const observesSpan = fn.length > 1;
|
|
3235
|
+
const sequenceDef = combinator._def.tag === "sequence" ? combinator._def : void 0;
|
|
3236
|
+
const terms = sequenceDef?.parsers;
|
|
3237
|
+
const inner = terms?.[1];
|
|
3238
|
+
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;
|
|
3239
|
+
const child = scalarOf(combinator);
|
|
3240
|
+
const parseScalar = fused ? (() => {
|
|
3241
|
+
const body = inner._stickyRegex;
|
|
3242
|
+
const tuple = ['"', "", '"'];
|
|
3243
|
+
const expected = [JSON.stringify('"')];
|
|
3244
|
+
return (input, pos, ctx) => {
|
|
3245
|
+
if (ctx.trivia !== void 0) {
|
|
3246
|
+
const end2 = child(input, pos, ctx);
|
|
3247
|
+
if (end2 < 0) return end2;
|
|
3248
|
+
ctx._sv = observesSpan ? fn(ctx._sv, { start: pos, end: end2 }) : fn(ctx._sv);
|
|
3249
|
+
return end2;
|
|
3250
|
+
}
|
|
3251
|
+
if (input.charCodeAt(pos) !== 34) {
|
|
3252
|
+
ctx._fx = expected;
|
|
3253
|
+
return ~pos;
|
|
3254
|
+
}
|
|
3255
|
+
body.lastIndex = pos + 1;
|
|
3256
|
+
const match = body.exec(input);
|
|
3257
|
+
const close = pos + 1 + match[0].length;
|
|
3258
|
+
if (input.charCodeAt(close) !== 34) {
|
|
3259
|
+
ctx._fx = expected;
|
|
3260
|
+
return ~close;
|
|
3261
|
+
}
|
|
3262
|
+
tuple[1] = match[0];
|
|
3263
|
+
const end = close + 1;
|
|
3264
|
+
ctx._sv = observesSpan ? fn(tuple, { start: pos, end }) : fn(tuple);
|
|
3265
|
+
return end;
|
|
3266
|
+
};
|
|
3267
|
+
})() : /* @__PURE__ */ (() => {
|
|
3268
|
+
return (input, pos, ctx) => {
|
|
3269
|
+
const end = child(input, pos, ctx);
|
|
3270
|
+
if (end < 0) return end;
|
|
3271
|
+
ctx._sv = observesSpan ? fn(ctx._sv, { start: pos, end }) : fn(ctx._sv);
|
|
3272
|
+
return end;
|
|
3273
|
+
};
|
|
3274
|
+
})();
|
|
3163
3275
|
return {
|
|
3164
3276
|
_tag: "transform",
|
|
3165
3277
|
_meta: combinator._meta,
|
|
3166
3278
|
_def: { tag: "transform", parser: combinator, fn },
|
|
3279
|
+
_parseScalar: parseScalar,
|
|
3167
3280
|
parse(input, pos, ctx) {
|
|
3168
3281
|
const result = combinator.parse(input, pos, ctx);
|
|
3169
3282
|
if (!result.ok) return result;
|
|
@@ -3178,9 +3291,11 @@ function trivia(combinator) {
|
|
|
3178
3291
|
_meta: {
|
|
3179
3292
|
...combinator._meta,
|
|
3180
3293
|
isTrivia: true,
|
|
3294
|
+
triviaScanner: fastTriviaScanner(combinator),
|
|
3181
3295
|
...kindLabels ? { triviaKindLabels: kindLabels } : {}
|
|
3182
3296
|
},
|
|
3183
3297
|
_def: { tag: "trivia", parser: combinator },
|
|
3298
|
+
_parseScalar: scalarOf(combinator),
|
|
3184
3299
|
parse: combinator.parse.bind(combinator)
|
|
3185
3300
|
};
|
|
3186
3301
|
}
|
|
@@ -3253,8 +3368,20 @@ function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
|
|
|
3253
3368
|
}
|
|
3254
3369
|
|
|
3255
3370
|
// src/combinators/ref.ts
|
|
3371
|
+
function withRuleTrivia(trivia2, ctx, run) {
|
|
3372
|
+
const savedLabels = ctx.triviaKindLabels;
|
|
3373
|
+
ctx.trivia = trivia2;
|
|
3374
|
+
ctx.triviaKindLabels = trivia2._meta.triviaKindLabels;
|
|
3375
|
+
try {
|
|
3376
|
+
return run();
|
|
3377
|
+
} finally {
|
|
3378
|
+
ctx.trivia = void 0;
|
|
3379
|
+
ctx.triviaKindLabels = savedLabels;
|
|
3380
|
+
}
|
|
3381
|
+
}
|
|
3256
3382
|
function ref() {
|
|
3257
3383
|
let resolved = null;
|
|
3384
|
+
let resolvedScalar = null;
|
|
3258
3385
|
let ownBoundary = false;
|
|
3259
3386
|
const meta = {
|
|
3260
3387
|
firstSet: any(),
|
|
@@ -3271,25 +3398,28 @@ function ref() {
|
|
|
3271
3398
|
return resolved;
|
|
3272
3399
|
}
|
|
3273
3400
|
},
|
|
3401
|
+
_parseScalar(input, pos, ctx) {
|
|
3402
|
+
const scalar = resolvedScalar;
|
|
3403
|
+
if (!scalar) throw new Error("ref<T>() used before .define() was called");
|
|
3404
|
+
const gt = meta.grammarTrivia;
|
|
3405
|
+
if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
|
|
3406
|
+
return withRuleTrivia(gt, ctx, () => scalar(input, pos, ctx));
|
|
3407
|
+
}
|
|
3408
|
+
return scalar(input, pos, ctx);
|
|
3409
|
+
},
|
|
3274
3410
|
parse(input, pos, ctx) {
|
|
3275
|
-
|
|
3411
|
+
const parser = resolved;
|
|
3412
|
+
if (!parser) throw new Error("ref<T>() used before .define() was called");
|
|
3276
3413
|
const gt = meta.grammarTrivia;
|
|
3277
3414
|
if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
|
|
3278
|
-
|
|
3279
|
-
ctx.trivia = gt;
|
|
3280
|
-
ctx.triviaKindLabels = gt._meta.triviaKindLabels;
|
|
3281
|
-
try {
|
|
3282
|
-
return resolved.parse(input, pos, ctx);
|
|
3283
|
-
} finally {
|
|
3284
|
-
ctx.trivia = void 0;
|
|
3285
|
-
ctx.triviaKindLabels = savedLabels;
|
|
3286
|
-
}
|
|
3415
|
+
return withRuleTrivia(gt, ctx, () => parser.parse(input, pos, ctx));
|
|
3287
3416
|
}
|
|
3288
|
-
return
|
|
3417
|
+
return parser.parse(input, pos, ctx);
|
|
3289
3418
|
},
|
|
3290
3419
|
define(p) {
|
|
3291
3420
|
if (resolved) throw new Error("ref<T>() already defined");
|
|
3292
3421
|
resolved = p;
|
|
3422
|
+
resolvedScalar = scalarOf(p);
|
|
3293
3423
|
ownBoundary = hasOwnTriviaBoundary(p);
|
|
3294
3424
|
meta.firstSet = p._meta.firstSet;
|
|
3295
3425
|
meta.canMatchNewline = p._meta.canMatchNewline;
|
|
@@ -6332,6 +6462,9 @@ if(ctx._rootTriviaLog!==undefined&&ctx._rootTriviaLog.length!==rt)ctx._rootTrivi
|
|
|
6332
6462
|
function q(s) {
|
|
6333
6463
|
return JSON.stringify(s);
|
|
6334
6464
|
}
|
|
6465
|
+
function isAsciiOnlyClass(cls) {
|
|
6466
|
+
return cls !== null && cls !== void 0 && cls.hi.length === 0;
|
|
6467
|
+
}
|
|
6335
6468
|
var NO_SINKS = { fd: false, er: false };
|
|
6336
6469
|
function sinkSlots(t, s) {
|
|
6337
6470
|
return `${s.fd ? `,${t}fd=0` : ""}${s.er ? `,${t}er=0` : ""}`;
|
|
@@ -6878,12 +7011,13 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
6878
7011
|
return `${head}EC.e=pos;return ''}`;
|
|
6879
7012
|
case OP_GATE: {
|
|
6880
7013
|
const child = link(code[ip + 2]);
|
|
6881
|
-
const
|
|
7014
|
+
const resolved = t.cc[code[ip + 1]];
|
|
7015
|
+
const ci = classes.push([resolved]) - 1;
|
|
6882
7016
|
classPlan.push([code[ip + 1]]);
|
|
6883
7017
|
const cls = hoist("cl", `CLS[${ci}][0]`);
|
|
6884
7018
|
const xf = fxRef(code[ip + 3]);
|
|
6885
7019
|
return `${head}
|
|
6886
|
-
if(
|
|
7020
|
+
if(${staticBuild && isAsciiOnlyClass(resolved) ? `${cls}.ascii[input.charCodeAt(pos)]!==1` : `!classHas(${cls},lead(input,pos))`}){ctx._fe=pos;ctx._fx=${xf};return FAIL}
|
|
6887
7021
|
return ${child}(input,pos,ctx)
|
|
6888
7022
|
}`;
|
|
6889
7023
|
}
|
|
@@ -7226,10 +7360,11 @@ return v
|
|
|
7226
7360
|
const asc = hoist("as", `DISP[${di}].ascii`);
|
|
7227
7361
|
const hiArr = table.hi;
|
|
7228
7362
|
const armSwitch = arms.map((a, i) => `case ${i}:v=${a}(input,pos,ctx);break`).join("\n");
|
|
7363
|
+
const directAscii = staticBuild && table.hi.length === 0;
|
|
7229
7364
|
return `${head}
|
|
7230
|
-
const c
|
|
7365
|
+
const c=${directAscii ? "input.charCodeAt(pos)" : "lead(input,pos)"}
|
|
7231
7366
|
let arm=-1
|
|
7232
|
-
if(c>=0&&c<128){const a=${asc}[c];if(a!==0)arm=a-1}
|
|
7367
|
+
if(${directAscii ? "c<128" : "c>=0&&c<128"}){const a=${asc}[c];if(a!==0)arm=a-1}
|
|
7233
7368
|
${hiArr.length === 0 ? "" : `else if(c>=128){const h=${hoist("hi", `DISP[${di}].hi`)}
|
|
7234
7369
|
for(let i=0;i<h.length;i+=3){if(c>=h[i]&&c<=h[i+1]){arm=h[i+2];break}}}`}
|
|
7235
7370
|
if(arm>=0){
|
|
@@ -7251,7 +7386,9 @@ return FAIL
|
|
|
7251
7386
|
const di = code[ip + 1];
|
|
7252
7387
|
const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
|
|
7253
7388
|
const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
|
|
7254
|
-
const
|
|
7389
|
+
const maskable = n <= 32;
|
|
7390
|
+
const directAsciiMask = staticBuild && maskable && gates.every(isAsciiOnlyClass);
|
|
7391
|
+
const gateRefs = directAsciiMask ? [] : Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
|
|
7255
7392
|
const tokenCandidate = tokenChoiceCandidates.get(ip);
|
|
7256
7393
|
const pretests = Array.from({ length: n }, (_, i) => {
|
|
7257
7394
|
if (tokenCandidate?.arm === i) {
|
|
@@ -7271,7 +7408,6 @@ return FAIL
|
|
|
7271
7408
|
const sequence6 = largeChoiceScalarSequences.get(code[base + i]);
|
|
7272
7409
|
return sequence6 === void 0 ? void 0 : { sequence: scalarSequenceRef(sequence6) };
|
|
7273
7410
|
});
|
|
7274
|
-
const maskable = n <= 32;
|
|
7275
7411
|
const maskName = maskable ? hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`) : "";
|
|
7276
7412
|
if (maskable) maskPlan.push(~di);
|
|
7277
7413
|
const p = tmp();
|
|
@@ -7333,16 +7469,16 @@ ${merge}
|
|
|
7333
7469
|
ctx._fe=pos;ctx._fx=acc??${choiceFx}
|
|
7334
7470
|
return FAIL`;
|
|
7335
7471
|
return `${head}
|
|
7336
|
-
const c
|
|
7472
|
+
const c=${directAsciiMask ? "input.charCodeAt(pos)" : "lead(input,pos)"}
|
|
7337
7473
|
${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
|
|
7338
7474
|
${deepAt.map((at, i) => `let ${at},${deepFx[i]}`).join("\n")}
|
|
7339
7475
|
${maskable ? `if(c<128){
|
|
7340
|
-
const bits=${maskName}[c<0?128:c]
|
|
7476
|
+
const bits=${maskName}[${directAsciiMask ? "c" : "c<0?128:c"}]
|
|
7341
7477
|
if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
|
|
7342
7478
|
${lazyArms(true)}
|
|
7343
|
-
}else{
|
|
7479
|
+
}${directAsciiMask ? "" : `else{
|
|
7344
7480
|
${lazyArms(false)}
|
|
7345
|
-
}
|
|
7481
|
+
}`}
|
|
7346
7482
|
` : lazyArms(false)}
|
|
7347
7483
|
${finish}
|
|
7348
7484
|
}`;
|
|
@@ -7393,7 +7529,7 @@ if(ctx._fc===true){${startFailureExact ? `if(best===pos){acc=${catchName}(${i},0
|
|
|
7393
7529
|
${rollbackFor(i)}
|
|
7394
7530
|
}${routeMiss}${sequenceMiss}`;
|
|
7395
7531
|
}).join("\n") : "";
|
|
7396
|
-
const generalArms = arms.map((arm, i) => {
|
|
7532
|
+
const generalArms = directAsciiMask ? "" : arms.map((arm, i) => {
|
|
7397
7533
|
const pretest = pretests[i];
|
|
7398
7534
|
const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
|
|
7399
7535
|
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("||")})`;
|
|
@@ -7423,12 +7559,12 @@ ${rollbackFor(i)}
|
|
|
7423
7559
|
}${miss}`;
|
|
7424
7560
|
}).join("\n");
|
|
7425
7561
|
return `${head}
|
|
7426
|
-
const c
|
|
7562
|
+
const c=${directAsciiMask ? "input.charCodeAt(pos)" : "lead(input,pos)"}
|
|
7427
7563
|
${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
|
|
7428
7564
|
let acc
|
|
7429
7565
|
let best=pos
|
|
7430
7566
|
${maskable ? `if(c<128){
|
|
7431
|
-
const bits=${maskName}[c<0?128:c]
|
|
7567
|
+
const bits=${maskName}[${directAsciiMask ? "c" : "c<0?128:c"}]
|
|
7432
7568
|
if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
|
|
7433
7569
|
${startFailureExact ? "" : "let prev=0"}
|
|
7434
7570
|
${maskArms}
|
|
@@ -7523,14 +7659,18 @@ return [key,v]
|
|
|
7523
7659
|
const itemFx = reportItem ? fxRef(code[ip + 6]) : "EMPTY_FX";
|
|
7524
7660
|
const collect = op === OP_REP;
|
|
7525
7661
|
let itemCls;
|
|
7662
|
+
let itemAscii = false;
|
|
7526
7663
|
if (!REC) {
|
|
7527
7664
|
const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
|
|
7528
7665
|
if (itemClassIndex >= 0) {
|
|
7529
|
-
const
|
|
7666
|
+
const resolved = t.cc[itemClassIndex];
|
|
7667
|
+
const ci = classes.push([resolved]) - 1;
|
|
7530
7668
|
classPlan.push([itemClassIndex]);
|
|
7531
7669
|
itemCls = hoist("ri", `CLS[${ci}][0]`);
|
|
7670
|
+
itemAscii = staticBuild && isAsciiOnlyClass(resolved);
|
|
7532
7671
|
}
|
|
7533
7672
|
}
|
|
7673
|
+
const itemMiss = (at) => itemAscii ? `${itemCls}.ascii[input.charCodeAt(${at})]!==1` : `!classHas(${itemCls},lead(input,${at}))`;
|
|
7534
7674
|
const skipBeforeFirst = sepIp < 0 && min === 0;
|
|
7535
7675
|
const p = tmp();
|
|
7536
7676
|
const via = sep !== void 0 ? "false" : min === 0 ? skipBeforeFirst ? "true" : "count>0" : `count>=${min}&&count>0`;
|
|
@@ -7590,7 +7730,7 @@ let count=0
|
|
|
7590
7730
|
for(;;){
|
|
7591
7731
|
${max >= 0 ? `if(count>=${max})break
|
|
7592
7732
|
` : ""}${sep !== void 0 ? `if(count>0&&count>=${min}&&cur>=input.length)break
|
|
7593
|
-
` : ""}${itemCls !== void 0 && sep === void 0 ? `if(count>=${min}&&${p}gate&&${hasTrivia === "false" ? "true" : hasTrivia === "true" ? "false" : "!hasTrivia"}
|
|
7733
|
+
` : ""}${itemCls !== void 0 && sep === void 0 ? `if(count>=${min}&&${p}gate&&${hasTrivia === "false" ? "true" : hasTrivia === "true" ? "false" : "!hasTrivia"}&&${itemMiss("cur")})break
|
|
7594
7734
|
` : ""}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` : ""}
|
|
7595
7735
|
${markBody}
|
|
7596
7736
|
let itemStart=cur
|
|
@@ -7615,7 +7755,7 @@ itemStart=${hasTrivia === "false" ? "EC.e" : hasTrivia === "true" ? `${skip}(inp
|
|
|
7615
7755
|
${rb}
|
|
7616
7756
|
${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
|
|
7617
7757
|
}
|
|
7618
|
-
${itemCls === void 0 ? "" : `if(count>=${min}&&${p}gate
|
|
7758
|
+
${itemCls === void 0 ? "" : `if(count>=${min}&&${p}gate&&${itemMiss("itemStart")}){
|
|
7619
7759
|
${rb}
|
|
7620
7760
|
${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
|
|
7621
7761
|
}
|
|
@@ -12892,7 +13032,7 @@ var Encoder = class {
|
|
|
12892
13032
|
d.tags === void 0 ? -1 : this.constant(d.tags)
|
|
12893
13033
|
);
|
|
12894
13034
|
if (matchesEmpty(d.parser)) return body;
|
|
12895
|
-
const fs = d.parser._meta.firstSet;
|
|
13035
|
+
const fs = d.parser._def.tag === "lazy" ? firstSetOf(d.parser, /* @__PURE__ */ new Set(), this.refResolver()) : d.parser._meta.firstSet;
|
|
12896
13036
|
if (fs.kind === "any") return body;
|
|
12897
13037
|
const cls = this.charClass(fs);
|
|
12898
13038
|
if (cls < 0) return body;
|
|
@@ -13006,7 +13146,7 @@ var Encoder = class {
|
|
|
13006
13146
|
case "attempt": {
|
|
13007
13147
|
const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip);
|
|
13008
13148
|
if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
|
|
13009
|
-
const fs = d.parser._meta.firstSet;
|
|
13149
|
+
const fs = d.parser._def.tag === "lazy" ? firstSetOf(d.parser, /* @__PURE__ */ new Set(), this.refResolver()) : d.parser._meta.firstSet;
|
|
13010
13150
|
if (fs.kind === "any" || matchesEmpty(d.parser)) return inner;
|
|
13011
13151
|
const cls = this.charClass(fs);
|
|
13012
13152
|
if (cls < 0) return inner;
|