parseman 0.50.0 → 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 +455 -226
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/cli/index.js +445 -191
- 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 +446 -192
- 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 -306
- 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/encode.d.ts.map +1 -1
- package/dist/table/index.js +331 -188
- 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/table/encode.ts +30 -10
- package/src/types.ts +8 -0
- package/src/version.ts +1 -1
package/dist/table/index.js
CHANGED
|
@@ -522,6 +522,28 @@ function literal(value, opts = {}) {
|
|
|
522
522
|
isTrivia: false
|
|
523
523
|
};
|
|
524
524
|
const canMatchNewline = meta.canMatchNewline;
|
|
525
|
+
const parseScalar = !caseInsensitive && value.length === 1 ? (() => {
|
|
526
|
+
const code = value.charCodeAt(0);
|
|
527
|
+
return (input, pos, ctx) => {
|
|
528
|
+
if (input.charCodeAt(pos) === code) {
|
|
529
|
+
ctx._sv = value;
|
|
530
|
+
return pos + 1;
|
|
531
|
+
}
|
|
532
|
+
ctx._fx = expected;
|
|
533
|
+
return ~pos;
|
|
534
|
+
};
|
|
535
|
+
})() : (input, pos, ctx) => {
|
|
536
|
+
const end = pos + value.length;
|
|
537
|
+
if (end <= input.length) {
|
|
538
|
+
const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
|
|
539
|
+
if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
|
|
540
|
+
ctx._sv = matchedValue;
|
|
541
|
+
return end;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
ctx._fx = expected;
|
|
545
|
+
return ~pos;
|
|
546
|
+
};
|
|
525
547
|
if (caseInsensitive) {
|
|
526
548
|
const upper = value.toUpperCase();
|
|
527
549
|
const lower = value.toLowerCase();
|
|
@@ -562,6 +584,7 @@ function literal(value, opts = {}) {
|
|
|
562
584
|
_tag: "literal",
|
|
563
585
|
_meta: meta,
|
|
564
586
|
_def: { tag: "literal", value, caseInsensitive },
|
|
587
|
+
_parseScalar: parseScalar,
|
|
565
588
|
parse
|
|
566
589
|
};
|
|
567
590
|
}
|
|
@@ -1018,10 +1041,32 @@ function regex(pattern, flags = "") {
|
|
|
1018
1041
|
const canMatchNewline = raw.canMatchNewline;
|
|
1019
1042
|
const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
|
|
1020
1043
|
const def = { tag: "regex", source, flags: resolvedFlags };
|
|
1044
|
+
const expected = directTerminalFailureExpected(def);
|
|
1045
|
+
const parseScalar = (input, pos, ctx) => {
|
|
1046
|
+
const scanEnd = scan?.(input, pos);
|
|
1047
|
+
if (scanEnd !== void 0) {
|
|
1048
|
+
if (scanEnd === null) {
|
|
1049
|
+
ctx._fx = expected;
|
|
1050
|
+
return ~pos;
|
|
1051
|
+
}
|
|
1052
|
+
ctx._sv = input.slice(pos, scanEnd);
|
|
1053
|
+
return scanEnd;
|
|
1054
|
+
}
|
|
1055
|
+
anchored.lastIndex = pos;
|
|
1056
|
+
const match = anchored.exec(input);
|
|
1057
|
+
if (match === null) {
|
|
1058
|
+
ctx._fx = expected;
|
|
1059
|
+
return ~pos;
|
|
1060
|
+
}
|
|
1061
|
+
ctx._sv = match[0];
|
|
1062
|
+
return pos + match[0].length;
|
|
1063
|
+
};
|
|
1021
1064
|
return {
|
|
1022
1065
|
_tag: "regex",
|
|
1023
1066
|
_meta: meta,
|
|
1024
1067
|
_def: def,
|
|
1068
|
+
_stickyRegex: anchored,
|
|
1069
|
+
_parseScalar: parseScalar,
|
|
1025
1070
|
parse(input, pos, ctx) {
|
|
1026
1071
|
const scanEnd = scan?.(input, pos);
|
|
1027
1072
|
if (scanEnd !== void 0) {
|
|
@@ -1063,6 +1108,7 @@ function createParseContext() {
|
|
|
1063
1108
|
_fe: void 0,
|
|
1064
1109
|
_fx: void 0,
|
|
1065
1110
|
_fc: void 0,
|
|
1111
|
+
_sv: void 0,
|
|
1066
1112
|
_probe: void 0,
|
|
1067
1113
|
_cstChildren: void 0,
|
|
1068
1114
|
_cstLeaves: void 0,
|
|
@@ -1754,6 +1800,9 @@ var fastScanner3;
|
|
|
1754
1800
|
function needsDeferredTriviaCommit(ctx) {
|
|
1755
1801
|
return ctx._triviaLog !== void 0 || ctx._rootTriviaLog !== void 0 || ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0;
|
|
1756
1802
|
}
|
|
1803
|
+
function needsTriviaRollback(ctx) {
|
|
1804
|
+
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;
|
|
1805
|
+
}
|
|
1757
1806
|
function saveTriviaMark(ctx) {
|
|
1758
1807
|
const m = saveCstMark(ctx);
|
|
1759
1808
|
return {
|
|
@@ -1863,7 +1912,8 @@ function advanceTrivia(input, cur, ctx) {
|
|
|
1863
1912
|
const triviaP = ctx.trivia;
|
|
1864
1913
|
if (!triviaP) return cur;
|
|
1865
1914
|
if (!ctx.trackLines) {
|
|
1866
|
-
const
|
|
1915
|
+
const classified = triviaP._meta.triviaScanner;
|
|
1916
|
+
const fast2 = classified === void 0 ? fastTriviaScanner(triviaP) : classified;
|
|
1867
1917
|
if (fast2) return fast2(input, cur);
|
|
1868
1918
|
if (ctx.triviaKindLabels) return skipWithLabels(input, cur, ctx);
|
|
1869
1919
|
const tr2 = triviaP.parse(input, cur, createDetachedParseContext(ctx.trackLines, ctx.state));
|
|
@@ -2416,6 +2466,11 @@ function adjacencyMisuse(polarity) {
|
|
|
2416
2466
|
return new TypeError(`${polarity}(): ${NO_STANDALONE_PARSE}`);
|
|
2417
2467
|
}
|
|
2418
2468
|
|
|
2469
|
+
// src/combinators/scalar.ts
|
|
2470
|
+
function scalarOf(combinator) {
|
|
2471
|
+
return combinator._parseScalar;
|
|
2472
|
+
}
|
|
2473
|
+
|
|
2419
2474
|
// src/combinators/sequence.ts
|
|
2420
2475
|
function sequence(...parsers) {
|
|
2421
2476
|
let adjacency = null;
|
|
@@ -2431,6 +2486,7 @@ function sequence(...parsers) {
|
|
|
2431
2486
|
(adjacency ??= Array.from({ length: parsers.length }, () => null))[i] = a;
|
|
2432
2487
|
}
|
|
2433
2488
|
const hasAdjacency = adjacency !== null;
|
|
2489
|
+
const strictArity = !hasAdjacency && (parsers.length === 2 && !matchesEmpty(parsers[1]) || parsers.length === 3 && parsers.every((p) => !matchesEmpty(p))) ? parsers.length : 0;
|
|
2434
2490
|
const meta = {
|
|
2435
2491
|
// Union through the nullable prefix — a leading optional()/many() lets a later
|
|
2436
2492
|
// term's first char start the sequence. Just `parsers[0]` under-approximates.
|
|
@@ -2439,165 +2495,96 @@ function sequence(...parsers) {
|
|
|
2439
2495
|
isTrivia: false
|
|
2440
2496
|
};
|
|
2441
2497
|
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 : [];
|
|
2498
|
+
const scalarParsers = parsers.map(scalarOf);
|
|
2499
|
+
const parseScalar = (input, pos, ctx) => {
|
|
2452
2500
|
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;
|
|
2501
|
+
if (strictArity !== 0) {
|
|
2502
|
+
cur = scalarParsers[0](input, cur, ctx);
|
|
2503
|
+
if (cur < 0) return cur;
|
|
2504
|
+
const first = ctx._sv;
|
|
2505
|
+
if (ctx.trivia) cur = advanceTrivia(input, cur, ctx);
|
|
2506
|
+
cur = scalarParsers[1](input, cur, ctx);
|
|
2507
|
+
if (cur < 0) return cur;
|
|
2508
|
+
const second = ctx._sv;
|
|
2509
|
+
if (strictArity === 2) {
|
|
2510
|
+
ctx._sv = def.valueUnused ? void 0 : [first, second];
|
|
2511
|
+
return cur;
|
|
2495
2512
|
}
|
|
2496
|
-
|
|
2497
|
-
|
|
2513
|
+
if (ctx.trivia) cur = advanceTrivia(input, cur, ctx);
|
|
2514
|
+
cur = scalarParsers[2](input, cur, ctx);
|
|
2515
|
+
if (cur < 0) return cur;
|
|
2516
|
+
ctx._sv = def.valueUnused ? void 0 : [first, second, ctx._sv];
|
|
2517
|
+
return cur;
|
|
2498
2518
|
}
|
|
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
2519
|
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
|
-
}
|
|
2520
|
+
for (let i = 0; i < scalarParsers.length; i++) {
|
|
2521
|
+
let termPos = cur;
|
|
2522
|
+
if (i > 0 && ctx.trivia) termPos = advanceTrivia(input, cur, ctx);
|
|
2523
|
+
const end = scalarParsers[i](input, termPos, ctx);
|
|
2524
|
+
if (end < 0) return end;
|
|
2525
|
+
if (values !== void 0) values.push(ctx._sv);
|
|
2526
|
+
if (end > termPos || termPos === cur) cur = end;
|
|
2527
|
+
}
|
|
2528
|
+
ctx._sv = values;
|
|
2529
|
+
return cur;
|
|
2530
|
+
};
|
|
2531
|
+
let followSentinels;
|
|
2556
2532
|
return {
|
|
2557
2533
|
_tag: "sequence",
|
|
2558
2534
|
_meta: meta,
|
|
2559
2535
|
_def: def,
|
|
2536
|
+
_parseScalar: hasAdjacency ? void 0 : parseScalar,
|
|
2560
2537
|
parse(input, pos, ctx) {
|
|
2561
|
-
|
|
2562
|
-
if (
|
|
2538
|
+
const tolerant = ctx._tolerant === true;
|
|
2539
|
+
if (tolerant) {
|
|
2540
|
+
followSentinels ??= parsers.map((_, i) => firstSetSentinel(
|
|
2541
|
+
parsers.slice(i + 1).reduce(
|
|
2542
|
+
(set, parser) => union(set, firstSetOf(parser)),
|
|
2543
|
+
{ kind: "empty" }
|
|
2544
|
+
)
|
|
2545
|
+
));
|
|
2546
|
+
}
|
|
2547
|
+
const inheritedSync = ctx._sync;
|
|
2548
|
+
const deferredTrivia = needsDeferredTriviaCommit(ctx);
|
|
2563
2549
|
const values = def.valueUnused ? void 0 : [];
|
|
2564
2550
|
let cur = pos;
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
const
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
} else {
|
|
2574
|
-
scanEnd = advanceTrivia(input, cur, ctx);
|
|
2551
|
+
try {
|
|
2552
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
2553
|
+
if (tolerant) ctx._sync = followSentinels[i] ?? inheritedSync;
|
|
2554
|
+
const assertion = adjacency?.[i];
|
|
2555
|
+
if (assertion) {
|
|
2556
|
+
if (!holdsAdjacency(input, cur, ctx, assertion)) return adjacencyFail(cur, assertion);
|
|
2557
|
+
if (values !== void 0) values.push(null);
|
|
2558
|
+
continue;
|
|
2575
2559
|
}
|
|
2576
|
-
|
|
2577
|
-
const
|
|
2578
|
-
const
|
|
2579
|
-
const
|
|
2580
|
-
if (
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2560
|
+
let termPos = cur;
|
|
2561
|
+
const markTlog = deferredTrivia ? cstTlLen(ctx) : 0;
|
|
2562
|
+
const markLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
|
|
2563
|
+
const markRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
2564
|
+
if (ctx.trivia && i > 0) {
|
|
2565
|
+
termPos = deferredTrivia ? commitTriviaScan(scanTriviaCompact(input, cur, ctx)) : advanceTrivia(input, cur, ctx);
|
|
2566
|
+
}
|
|
2567
|
+
const scanTlog = deferredTrivia ? cstTlLen(ctx) : 0;
|
|
2568
|
+
const scanLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
|
|
2569
|
+
const scanRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
2570
|
+
const result = parsers[i].parse(input, termPos, ctx);
|
|
2571
|
+
if (!result.ok) return result;
|
|
2572
|
+
if (values !== void 0) values.push(result.value);
|
|
2573
|
+
if (result.span.end > termPos || termPos === cur) cur = result.span.end;
|
|
2574
|
+
else if (deferredTrivia) {
|
|
2584
2575
|
rollbackScannedTriviaAt(
|
|
2585
2576
|
ctx,
|
|
2586
|
-
|
|
2577
|
+
markTlog,
|
|
2587
2578
|
scanTlog,
|
|
2588
|
-
|
|
2579
|
+
markLog,
|
|
2589
2580
|
scanLog,
|
|
2590
|
-
|
|
2581
|
+
markRootLog,
|
|
2591
2582
|
scanRootLog
|
|
2592
2583
|
);
|
|
2593
2584
|
}
|
|
2594
|
-
if (values !== void 0) values.push(result2.value);
|
|
2595
|
-
continue;
|
|
2596
2585
|
}
|
|
2597
|
-
|
|
2598
|
-
if (
|
|
2599
|
-
if (values !== void 0) values.push(result.value);
|
|
2600
|
-
cur = result.span.end;
|
|
2586
|
+
} finally {
|
|
2587
|
+
if (tolerant) ctx._sync = inheritedSync;
|
|
2601
2588
|
}
|
|
2602
2589
|
return {
|
|
2603
2590
|
ok: true,
|
|
@@ -2729,7 +2716,8 @@ function choice(...args) {
|
|
|
2729
2716
|
disjoint
|
|
2730
2717
|
};
|
|
2731
2718
|
const strategy = disjoint || hasGates ? null : detectStrategy(parsers);
|
|
2732
|
-
const
|
|
2719
|
+
const ordered = strategy?.tag === "firstMatch" || strategy?.tag === "sharedPrefix";
|
|
2720
|
+
const autoNot = !disjoint && !hasGates && ordered ? computeAutoNot(parsers) : parsers.map(() => null);
|
|
2733
2721
|
let greedyLitMap = null;
|
|
2734
2722
|
let sortedParsers = null;
|
|
2735
2723
|
const asciiDispatch = disjoint ? buildAsciiDispatch(parsers) : null;
|
|
@@ -2743,6 +2731,37 @@ function choice(...args) {
|
|
|
2743
2731
|
} else if (strategy?.tag === "literalsLongestFirst") {
|
|
2744
2732
|
sortedParsers = strategy.sortedIndices.map((i) => parsers[i]);
|
|
2745
2733
|
}
|
|
2734
|
+
const scalarParsers = parsers.map(scalarOf);
|
|
2735
|
+
const scalarEligible = !hasGates && parsers.every((p) => p._parseScalar !== void 0) && (disjoint || ordered);
|
|
2736
|
+
const scalarExpected = parsers.flatMap(deriveExpected);
|
|
2737
|
+
const parseScalar = (input, pos, ctx) => {
|
|
2738
|
+
if (disjoint) {
|
|
2739
|
+
const code = pos < input.length ? input.codePointAt(pos) : -1;
|
|
2740
|
+
let idx = code >= 0 && code < 128 ? asciiDispatch[code] : -1;
|
|
2741
|
+
if (idx < 0 && code >= 0) {
|
|
2742
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
2743
|
+
if (inFirstSet(code, parsers[i]._meta.firstSet)) {
|
|
2744
|
+
idx = i;
|
|
2745
|
+
break;
|
|
2746
|
+
}
|
|
2747
|
+
}
|
|
2748
|
+
}
|
|
2749
|
+
if (idx >= 0) {
|
|
2750
|
+
const gate = gates[idx];
|
|
2751
|
+
if (!gate || gate(ctx.state)) return scalarParsers[idx](input, pos, ctx);
|
|
2752
|
+
ctx._fx = deriveExpected(parsers[idx]);
|
|
2753
|
+
return ~pos;
|
|
2754
|
+
}
|
|
2755
|
+
} else {
|
|
2756
|
+
for (let i = 0; i < scalarParsers.length; i++) {
|
|
2757
|
+
if (gates[i] && !gates[i](ctx.state)) continue;
|
|
2758
|
+
const end = scalarParsers[i](input, pos, ctx);
|
|
2759
|
+
if (end >= 0 && (!autoNot[i] || !autoNotFires(input, end, autoNot[i]))) return end;
|
|
2760
|
+
}
|
|
2761
|
+
}
|
|
2762
|
+
ctx._fx = scalarExpected;
|
|
2763
|
+
return ~pos;
|
|
2764
|
+
};
|
|
2746
2765
|
return {
|
|
2747
2766
|
_tag: "choice",
|
|
2748
2767
|
_meta: meta,
|
|
@@ -2754,6 +2773,7 @@ function choice(...args) {
|
|
|
2754
2773
|
strategy: strategy ?? { tag: "firstMatch" },
|
|
2755
2774
|
autoNot
|
|
2756
2775
|
},
|
|
2776
|
+
_parseScalar: scalarEligible ? parseScalar : void 0,
|
|
2757
2777
|
parse(input, pos, ctx) {
|
|
2758
2778
|
const expected = [];
|
|
2759
2779
|
let expectedAt = pos;
|
|
@@ -3014,8 +3034,8 @@ function buildAsciiDispatch(parsers) {
|
|
|
3014
3034
|
}
|
|
3015
3035
|
|
|
3016
3036
|
// src/combinators/repeat.ts
|
|
3017
|
-
function repItem(combinator, input, cur, ctx, guardable, mandatory) {
|
|
3018
|
-
const mark = saveTriviaMark(ctx);
|
|
3037
|
+
function repItem(combinator, input, cur, ctx, guardable, mandatory, rollbackNeeded) {
|
|
3038
|
+
const mark = rollbackNeeded ? saveTriviaMark(ctx) : void 0;
|
|
3019
3039
|
let pos = cur;
|
|
3020
3040
|
if (ctx.trivia) {
|
|
3021
3041
|
if (needsDeferredTriviaCommit(ctx)) {
|
|
@@ -3025,24 +3045,24 @@ function repItem(combinator, input, cur, ctx, guardable, mandatory) {
|
|
|
3025
3045
|
}
|
|
3026
3046
|
}
|
|
3027
3047
|
if (pos >= input.length && !mandatory) {
|
|
3028
|
-
rollbackTrivia(ctx, mark);
|
|
3048
|
+
if (mark !== void 0) rollbackTrivia(ctx, mark);
|
|
3029
3049
|
return "stop";
|
|
3030
3050
|
}
|
|
3031
3051
|
if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(combinator, input, pos)) {
|
|
3032
|
-
rollbackTrivia(ctx, mark);
|
|
3052
|
+
if (mark !== void 0) rollbackTrivia(ctx, mark);
|
|
3033
3053
|
return "stop";
|
|
3034
3054
|
}
|
|
3035
3055
|
const result = combinator.parse(input, pos, ctx);
|
|
3036
3056
|
if (!result.ok) {
|
|
3037
|
-
rollbackTrivia(ctx, mark);
|
|
3057
|
+
if (mark !== void 0) rollbackTrivia(ctx, mark);
|
|
3038
3058
|
if (result.committed) return { fail: result, failPos: pos };
|
|
3039
3059
|
return { fail: result, failPos: pos };
|
|
3040
3060
|
}
|
|
3041
3061
|
if (result.span.end === pos && !mandatory) {
|
|
3042
|
-
rollbackTrivia(ctx, mark);
|
|
3062
|
+
if (mark !== void 0) rollbackTrivia(ctx, mark);
|
|
3043
3063
|
return "stop";
|
|
3044
3064
|
}
|
|
3045
|
-
return
|
|
3065
|
+
return result;
|
|
3046
3066
|
}
|
|
3047
3067
|
function resolveBounds(what, opts) {
|
|
3048
3068
|
const min = opts.min ?? 0;
|
|
@@ -3055,6 +3075,21 @@ function resolveBounds(what, opts) {
|
|
|
3055
3075
|
if (max < min) bad(`max (${max}) is less than min (${min}) \u2014 the combinator could never succeed`);
|
|
3056
3076
|
return { min, max };
|
|
3057
3077
|
}
|
|
3078
|
+
function repeatScalarTail(combinator, child, input, cur, ctx, guardable, values, remaining) {
|
|
3079
|
+
while (cur < input.length && remaining > 0) {
|
|
3080
|
+
let itemPos = cur;
|
|
3081
|
+
if (ctx.trivia) itemPos = advanceTrivia(input, cur, ctx);
|
|
3082
|
+
if (itemPos >= input.length) break;
|
|
3083
|
+
if (guardable && !startsFirstSet(combinator, input, itemPos)) break;
|
|
3084
|
+
const end = child(input, itemPos, ctx);
|
|
3085
|
+
if (end <= itemPos) break;
|
|
3086
|
+
if (values !== void 0) values.push(ctx._sv);
|
|
3087
|
+
cur = end;
|
|
3088
|
+
remaining--;
|
|
3089
|
+
}
|
|
3090
|
+
ctx._sv = values;
|
|
3091
|
+
return cur;
|
|
3092
|
+
}
|
|
3058
3093
|
function many(combinator, opts = {}) {
|
|
3059
3094
|
const { min, max } = resolveBounds("many()", opts);
|
|
3060
3095
|
if (min >= 1) return atLeast(combinator, min, max);
|
|
@@ -3066,17 +3101,21 @@ function many(combinator, opts = {}) {
|
|
|
3066
3101
|
const def = { tag: "many", parser: combinator, min: 0, ...max === Infinity ? {} : { max } };
|
|
3067
3102
|
let expected;
|
|
3068
3103
|
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
3104
|
+
const scalarChild = scalarOf(combinator);
|
|
3105
|
+
const parseScalar = (input, pos, ctx) => repeatScalarTail(combinator, scalarChild, input, pos, ctx, guardable, def.valueUnused ? void 0 : [], max);
|
|
3069
3106
|
return {
|
|
3070
3107
|
_tag: "many",
|
|
3071
3108
|
_meta: meta,
|
|
3072
3109
|
_def: def,
|
|
3110
|
+
_parseScalar: parseScalar,
|
|
3073
3111
|
parse(input, pos, ctx) {
|
|
3074
3112
|
const values = def.valueUnused ? void 0 : [];
|
|
3113
|
+
const rollbackNeeded = needsTriviaRollback(ctx);
|
|
3075
3114
|
let cur = pos;
|
|
3076
3115
|
let count = 0;
|
|
3077
3116
|
while (cur < input.length) {
|
|
3078
3117
|
if (count >= max) break;
|
|
3079
|
-
const item = repItem(combinator, input, cur, ctx, guardable, false);
|
|
3118
|
+
const item = repItem(combinator, input, cur, ctx, guardable, false, rollbackNeeded);
|
|
3080
3119
|
if (item === "stop") break;
|
|
3081
3120
|
if ("fail" in item) {
|
|
3082
3121
|
if (!item.fail.ok && item.fail.committed) return item.fail;
|
|
@@ -3093,7 +3132,7 @@ function many(combinator, opts = {}) {
|
|
|
3093
3132
|
}
|
|
3094
3133
|
if (values !== void 0) values.push(item.value);
|
|
3095
3134
|
count++;
|
|
3096
|
-
cur = item.end;
|
|
3135
|
+
cur = item.span.end;
|
|
3097
3136
|
}
|
|
3098
3137
|
return { ok: true, value: values ?? void 0, span: { start: pos, end: cur } };
|
|
3099
3138
|
}
|
|
@@ -3111,30 +3150,47 @@ function atLeast(combinator, min, max) {
|
|
|
3111
3150
|
const def = { tag: "oneOrMore", parser: combinator, min, ...max === Infinity ? {} : { max } };
|
|
3112
3151
|
let expected;
|
|
3113
3152
|
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
3153
|
+
const scalarChild = scalarOf(combinator);
|
|
3154
|
+
const parseScalar = (input, pos, ctx) => {
|
|
3155
|
+
let cur = scalarChild(input, pos, ctx);
|
|
3156
|
+
if (cur < 0) return cur;
|
|
3157
|
+
const values = def.valueUnused ? void 0 : [ctx._sv];
|
|
3158
|
+
for (let count = 1; count < min; count++) {
|
|
3159
|
+
let itemPos = cur;
|
|
3160
|
+
if (ctx.trivia) itemPos = advanceTrivia(input, cur, ctx);
|
|
3161
|
+
const end = scalarChild(input, itemPos, ctx);
|
|
3162
|
+
if (end < 0) return ~cur;
|
|
3163
|
+
cur = end;
|
|
3164
|
+
if (values !== void 0) values.push(ctx._sv);
|
|
3165
|
+
}
|
|
3166
|
+
return repeatScalarTail(combinator, scalarChild, input, cur, ctx, guardable, values, max - min);
|
|
3167
|
+
};
|
|
3114
3168
|
return {
|
|
3115
3169
|
_tag: "oneOrMore",
|
|
3116
3170
|
_meta: meta,
|
|
3117
3171
|
_def: def,
|
|
3172
|
+
_parseScalar: parseScalar,
|
|
3118
3173
|
parse(input, pos, ctx) {
|
|
3119
3174
|
const first = combinator.parse(input, pos, ctx);
|
|
3120
3175
|
if (!first.ok) return first;
|
|
3121
3176
|
const values = def.valueUnused ? void 0 : [first.value];
|
|
3177
|
+
const rollbackNeeded = needsTriviaRollback(ctx);
|
|
3122
3178
|
let cur = first.span.end;
|
|
3123
3179
|
let count = 1;
|
|
3124
3180
|
while (count < min) {
|
|
3125
|
-
const item = repItem(combinator, input, cur, ctx, guardable, true);
|
|
3181
|
+
const item = repItem(combinator, input, cur, ctx, guardable, true, rollbackNeeded);
|
|
3126
3182
|
if (item === "stop" || "fail" in item) {
|
|
3127
3183
|
if (item !== "stop" && !item.fail.ok && item.fail.committed) return item.fail;
|
|
3128
3184
|
expected ??= deriveExpected(combinator);
|
|
3129
3185
|
return { ok: false, expected: expected.length > 0 ? expected : [combinator._tag], span: { start: cur, end: cur } };
|
|
3130
3186
|
}
|
|
3131
3187
|
if (values !== void 0) values.push(item.value);
|
|
3132
|
-
cur = item.end;
|
|
3188
|
+
cur = item.span.end;
|
|
3133
3189
|
count++;
|
|
3134
3190
|
}
|
|
3135
3191
|
while (cur < input.length) {
|
|
3136
3192
|
if (count >= max) break;
|
|
3137
|
-
const item = repItem(combinator, input, cur, ctx, guardable, false);
|
|
3193
|
+
const item = repItem(combinator, input, cur, ctx, guardable, false, rollbackNeeded);
|
|
3138
3194
|
if (item === "stop") break;
|
|
3139
3195
|
if ("fail" in item) {
|
|
3140
3196
|
if (!item.fail.ok && item.fail.committed) return item.fail;
|
|
@@ -3151,7 +3207,7 @@ function atLeast(combinator, min, max) {
|
|
|
3151
3207
|
}
|
|
3152
3208
|
if (values !== void 0) values.push(item.value);
|
|
3153
3209
|
count++;
|
|
3154
|
-
cur = item.end;
|
|
3210
|
+
cur = item.span.end;
|
|
3155
3211
|
}
|
|
3156
3212
|
return { ok: true, value: values ?? void 0, span: { start: pos, end: cur } };
|
|
3157
3213
|
}
|
|
@@ -3159,11 +3215,54 @@ function atLeast(combinator, min, max) {
|
|
|
3159
3215
|
}
|
|
3160
3216
|
|
|
3161
3217
|
// src/combinators/map.ts
|
|
3218
|
+
var JSON_STRING_BODY = String.raw`(?:[^"\\]|\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4}))*`;
|
|
3162
3219
|
function transform(combinator, fn) {
|
|
3220
|
+
const observesSpan = fn.length > 1;
|
|
3221
|
+
const sequenceDef = combinator._def.tag === "sequence" ? combinator._def : void 0;
|
|
3222
|
+
const terms = sequenceDef?.parsers;
|
|
3223
|
+
const inner = terms?.[1];
|
|
3224
|
+
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;
|
|
3225
|
+
const child = scalarOf(combinator);
|
|
3226
|
+
const parseScalar = fused ? (() => {
|
|
3227
|
+
const body = inner._stickyRegex;
|
|
3228
|
+
const tuple = ['"', "", '"'];
|
|
3229
|
+
const expected = [JSON.stringify('"')];
|
|
3230
|
+
return (input, pos, ctx) => {
|
|
3231
|
+
if (ctx.trivia !== void 0) {
|
|
3232
|
+
const end2 = child(input, pos, ctx);
|
|
3233
|
+
if (end2 < 0) return end2;
|
|
3234
|
+
ctx._sv = observesSpan ? fn(ctx._sv, { start: pos, end: end2 }) : fn(ctx._sv);
|
|
3235
|
+
return end2;
|
|
3236
|
+
}
|
|
3237
|
+
if (input.charCodeAt(pos) !== 34) {
|
|
3238
|
+
ctx._fx = expected;
|
|
3239
|
+
return ~pos;
|
|
3240
|
+
}
|
|
3241
|
+
body.lastIndex = pos + 1;
|
|
3242
|
+
const match = body.exec(input);
|
|
3243
|
+
const close = pos + 1 + match[0].length;
|
|
3244
|
+
if (input.charCodeAt(close) !== 34) {
|
|
3245
|
+
ctx._fx = expected;
|
|
3246
|
+
return ~close;
|
|
3247
|
+
}
|
|
3248
|
+
tuple[1] = match[0];
|
|
3249
|
+
const end = close + 1;
|
|
3250
|
+
ctx._sv = observesSpan ? fn(tuple, { start: pos, end }) : fn(tuple);
|
|
3251
|
+
return end;
|
|
3252
|
+
};
|
|
3253
|
+
})() : /* @__PURE__ */ (() => {
|
|
3254
|
+
return (input, pos, ctx) => {
|
|
3255
|
+
const end = child(input, pos, ctx);
|
|
3256
|
+
if (end < 0) return end;
|
|
3257
|
+
ctx._sv = observesSpan ? fn(ctx._sv, { start: pos, end }) : fn(ctx._sv);
|
|
3258
|
+
return end;
|
|
3259
|
+
};
|
|
3260
|
+
})();
|
|
3163
3261
|
return {
|
|
3164
3262
|
_tag: "transform",
|
|
3165
3263
|
_meta: combinator._meta,
|
|
3166
3264
|
_def: { tag: "transform", parser: combinator, fn },
|
|
3265
|
+
_parseScalar: parseScalar,
|
|
3167
3266
|
parse(input, pos, ctx) {
|
|
3168
3267
|
const result = combinator.parse(input, pos, ctx);
|
|
3169
3268
|
if (!result.ok) return result;
|
|
@@ -3178,9 +3277,11 @@ function trivia(combinator) {
|
|
|
3178
3277
|
_meta: {
|
|
3179
3278
|
...combinator._meta,
|
|
3180
3279
|
isTrivia: true,
|
|
3280
|
+
triviaScanner: fastTriviaScanner(combinator),
|
|
3181
3281
|
...kindLabels ? { triviaKindLabels: kindLabels } : {}
|
|
3182
3282
|
},
|
|
3183
3283
|
_def: { tag: "trivia", parser: combinator },
|
|
3284
|
+
_parseScalar: scalarOf(combinator),
|
|
3184
3285
|
parse: combinator.parse.bind(combinator)
|
|
3185
3286
|
};
|
|
3186
3287
|
}
|
|
@@ -3253,8 +3354,20 @@ function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
|
|
|
3253
3354
|
}
|
|
3254
3355
|
|
|
3255
3356
|
// src/combinators/ref.ts
|
|
3357
|
+
function withRuleTrivia(trivia2, ctx, run) {
|
|
3358
|
+
const savedLabels = ctx.triviaKindLabels;
|
|
3359
|
+
ctx.trivia = trivia2;
|
|
3360
|
+
ctx.triviaKindLabels = trivia2._meta.triviaKindLabels;
|
|
3361
|
+
try {
|
|
3362
|
+
return run();
|
|
3363
|
+
} finally {
|
|
3364
|
+
ctx.trivia = void 0;
|
|
3365
|
+
ctx.triviaKindLabels = savedLabels;
|
|
3366
|
+
}
|
|
3367
|
+
}
|
|
3256
3368
|
function ref() {
|
|
3257
3369
|
let resolved = null;
|
|
3370
|
+
let resolvedScalar = null;
|
|
3258
3371
|
let ownBoundary = false;
|
|
3259
3372
|
const meta = {
|
|
3260
3373
|
firstSet: any(),
|
|
@@ -3271,25 +3384,28 @@ function ref() {
|
|
|
3271
3384
|
return resolved;
|
|
3272
3385
|
}
|
|
3273
3386
|
},
|
|
3387
|
+
_parseScalar(input, pos, ctx) {
|
|
3388
|
+
const scalar = resolvedScalar;
|
|
3389
|
+
if (!scalar) throw new Error("ref<T>() used before .define() was called");
|
|
3390
|
+
const gt = meta.grammarTrivia;
|
|
3391
|
+
if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
|
|
3392
|
+
return withRuleTrivia(gt, ctx, () => scalar(input, pos, ctx));
|
|
3393
|
+
}
|
|
3394
|
+
return scalar(input, pos, ctx);
|
|
3395
|
+
},
|
|
3274
3396
|
parse(input, pos, ctx) {
|
|
3275
|
-
|
|
3397
|
+
const parser = resolved;
|
|
3398
|
+
if (!parser) throw new Error("ref<T>() used before .define() was called");
|
|
3276
3399
|
const gt = meta.grammarTrivia;
|
|
3277
3400
|
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
|
-
}
|
|
3401
|
+
return withRuleTrivia(gt, ctx, () => parser.parse(input, pos, ctx));
|
|
3287
3402
|
}
|
|
3288
|
-
return
|
|
3403
|
+
return parser.parse(input, pos, ctx);
|
|
3289
3404
|
},
|
|
3290
3405
|
define(p) {
|
|
3291
3406
|
if (resolved) throw new Error("ref<T>() already defined");
|
|
3292
3407
|
resolved = p;
|
|
3408
|
+
resolvedScalar = scalarOf(p);
|
|
3293
3409
|
ownBoundary = hasOwnTriviaBoundary(p);
|
|
3294
3410
|
meta.firstSet = p._meta.firstSet;
|
|
3295
3411
|
meta.canMatchNewline = p._meta.canMatchNewline;
|
|
@@ -6332,6 +6448,9 @@ if(ctx._rootTriviaLog!==undefined&&ctx._rootTriviaLog.length!==rt)ctx._rootTrivi
|
|
|
6332
6448
|
function q(s) {
|
|
6333
6449
|
return JSON.stringify(s);
|
|
6334
6450
|
}
|
|
6451
|
+
function isAsciiOnlyClass(cls) {
|
|
6452
|
+
return cls !== null && cls !== void 0 && cls.hi.length === 0;
|
|
6453
|
+
}
|
|
6335
6454
|
var NO_SINKS = { fd: false, er: false };
|
|
6336
6455
|
function sinkSlots(t, s) {
|
|
6337
6456
|
return `${s.fd ? `,${t}fd=0` : ""}${s.er ? `,${t}er=0` : ""}`;
|
|
@@ -6878,12 +6997,13 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
6878
6997
|
return `${head}EC.e=pos;return ''}`;
|
|
6879
6998
|
case OP_GATE: {
|
|
6880
6999
|
const child = link(code[ip + 2]);
|
|
6881
|
-
const
|
|
7000
|
+
const resolved = t.cc[code[ip + 1]];
|
|
7001
|
+
const ci = classes.push([resolved]) - 1;
|
|
6882
7002
|
classPlan.push([code[ip + 1]]);
|
|
6883
7003
|
const cls = hoist("cl", `CLS[${ci}][0]`);
|
|
6884
7004
|
const xf = fxRef(code[ip + 3]);
|
|
6885
7005
|
return `${head}
|
|
6886
|
-
if(
|
|
7006
|
+
if(${staticBuild && isAsciiOnlyClass(resolved) ? `${cls}.ascii[input.charCodeAt(pos)]!==1` : `!classHas(${cls},lead(input,pos))`}){ctx._fe=pos;ctx._fx=${xf};return FAIL}
|
|
6887
7007
|
return ${child}(input,pos,ctx)
|
|
6888
7008
|
}`;
|
|
6889
7009
|
}
|
|
@@ -7226,10 +7346,11 @@ return v
|
|
|
7226
7346
|
const asc = hoist("as", `DISP[${di}].ascii`);
|
|
7227
7347
|
const hiArr = table.hi;
|
|
7228
7348
|
const armSwitch = arms.map((a, i) => `case ${i}:v=${a}(input,pos,ctx);break`).join("\n");
|
|
7349
|
+
const directAscii = staticBuild && table.hi.length === 0;
|
|
7229
7350
|
return `${head}
|
|
7230
|
-
const c
|
|
7351
|
+
const c=${directAscii ? "input.charCodeAt(pos)" : "lead(input,pos)"}
|
|
7231
7352
|
let arm=-1
|
|
7232
|
-
if(c>=0&&c<128){const a=${asc}[c];if(a!==0)arm=a-1}
|
|
7353
|
+
if(${directAscii ? "c<128" : "c>=0&&c<128"}){const a=${asc}[c];if(a!==0)arm=a-1}
|
|
7233
7354
|
${hiArr.length === 0 ? "" : `else if(c>=128){const h=${hoist("hi", `DISP[${di}].hi`)}
|
|
7234
7355
|
for(let i=0;i<h.length;i+=3){if(c>=h[i]&&c<=h[i+1]){arm=h[i+2];break}}}`}
|
|
7235
7356
|
if(arm>=0){
|
|
@@ -7251,7 +7372,9 @@ return FAIL
|
|
|
7251
7372
|
const di = code[ip + 1];
|
|
7252
7373
|
const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
|
|
7253
7374
|
const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
|
|
7254
|
-
const
|
|
7375
|
+
const maskable = n <= 32;
|
|
7376
|
+
const directAsciiMask = staticBuild && maskable && gates.every(isAsciiOnlyClass);
|
|
7377
|
+
const gateRefs = directAsciiMask ? [] : Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
|
|
7255
7378
|
const tokenCandidate = tokenChoiceCandidates.get(ip);
|
|
7256
7379
|
const pretests = Array.from({ length: n }, (_, i) => {
|
|
7257
7380
|
if (tokenCandidate?.arm === i) {
|
|
@@ -7271,7 +7394,6 @@ return FAIL
|
|
|
7271
7394
|
const sequence6 = largeChoiceScalarSequences.get(code[base + i]);
|
|
7272
7395
|
return sequence6 === void 0 ? void 0 : { sequence: scalarSequenceRef(sequence6) };
|
|
7273
7396
|
});
|
|
7274
|
-
const maskable = n <= 32;
|
|
7275
7397
|
const maskName = maskable ? hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`) : "";
|
|
7276
7398
|
if (maskable) maskPlan.push(~di);
|
|
7277
7399
|
const p = tmp();
|
|
@@ -7333,16 +7455,16 @@ ${merge}
|
|
|
7333
7455
|
ctx._fe=pos;ctx._fx=acc??${choiceFx}
|
|
7334
7456
|
return FAIL`;
|
|
7335
7457
|
return `${head}
|
|
7336
|
-
const c
|
|
7458
|
+
const c=${directAsciiMask ? "input.charCodeAt(pos)" : "lead(input,pos)"}
|
|
7337
7459
|
${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
|
|
7338
7460
|
${deepAt.map((at, i) => `let ${at},${deepFx[i]}`).join("\n")}
|
|
7339
7461
|
${maskable ? `if(c<128){
|
|
7340
|
-
const bits=${maskName}[c<0?128:c]
|
|
7462
|
+
const bits=${maskName}[${directAsciiMask ? "c" : "c<0?128:c"}]
|
|
7341
7463
|
if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
|
|
7342
7464
|
${lazyArms(true)}
|
|
7343
|
-
}else{
|
|
7465
|
+
}${directAsciiMask ? "" : `else{
|
|
7344
7466
|
${lazyArms(false)}
|
|
7345
|
-
}
|
|
7467
|
+
}`}
|
|
7346
7468
|
` : lazyArms(false)}
|
|
7347
7469
|
${finish}
|
|
7348
7470
|
}`;
|
|
@@ -7393,7 +7515,7 @@ if(ctx._fc===true){${startFailureExact ? `if(best===pos){acc=${catchName}(${i},0
|
|
|
7393
7515
|
${rollbackFor(i)}
|
|
7394
7516
|
}${routeMiss}${sequenceMiss}`;
|
|
7395
7517
|
}).join("\n") : "";
|
|
7396
|
-
const generalArms = arms.map((arm, i) => {
|
|
7518
|
+
const generalArms = directAsciiMask ? "" : arms.map((arm, i) => {
|
|
7397
7519
|
const pretest = pretests[i];
|
|
7398
7520
|
const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
|
|
7399
7521
|
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 +7545,12 @@ ${rollbackFor(i)}
|
|
|
7423
7545
|
}${miss}`;
|
|
7424
7546
|
}).join("\n");
|
|
7425
7547
|
return `${head}
|
|
7426
|
-
const c
|
|
7548
|
+
const c=${directAsciiMask ? "input.charCodeAt(pos)" : "lead(input,pos)"}
|
|
7427
7549
|
${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
|
|
7428
7550
|
let acc
|
|
7429
7551
|
let best=pos
|
|
7430
7552
|
${maskable ? `if(c<128){
|
|
7431
|
-
const bits=${maskName}[c<0?128:c]
|
|
7553
|
+
const bits=${maskName}[${directAsciiMask ? "c" : "c<0?128:c"}]
|
|
7432
7554
|
if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
|
|
7433
7555
|
${startFailureExact ? "" : "let prev=0"}
|
|
7434
7556
|
${maskArms}
|
|
@@ -7523,14 +7645,18 @@ return [key,v]
|
|
|
7523
7645
|
const itemFx = reportItem ? fxRef(code[ip + 6]) : "EMPTY_FX";
|
|
7524
7646
|
const collect = op === OP_REP;
|
|
7525
7647
|
let itemCls;
|
|
7648
|
+
let itemAscii = false;
|
|
7526
7649
|
if (!REC) {
|
|
7527
7650
|
const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
|
|
7528
7651
|
if (itemClassIndex >= 0) {
|
|
7529
|
-
const
|
|
7652
|
+
const resolved = t.cc[itemClassIndex];
|
|
7653
|
+
const ci = classes.push([resolved]) - 1;
|
|
7530
7654
|
classPlan.push([itemClassIndex]);
|
|
7531
7655
|
itemCls = hoist("ri", `CLS[${ci}][0]`);
|
|
7656
|
+
itemAscii = staticBuild && isAsciiOnlyClass(resolved);
|
|
7532
7657
|
}
|
|
7533
7658
|
}
|
|
7659
|
+
const itemMiss = (at) => itemAscii ? `${itemCls}.ascii[input.charCodeAt(${at})]!==1` : `!classHas(${itemCls},lead(input,${at}))`;
|
|
7534
7660
|
const skipBeforeFirst = sepIp < 0 && min === 0;
|
|
7535
7661
|
const p = tmp();
|
|
7536
7662
|
const via = sep !== void 0 ? "false" : min === 0 ? skipBeforeFirst ? "true" : "count>0" : `count>=${min}&&count>0`;
|
|
@@ -7590,7 +7716,7 @@ let count=0
|
|
|
7590
7716
|
for(;;){
|
|
7591
7717
|
${max >= 0 ? `if(count>=${max})break
|
|
7592
7718
|
` : ""}${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"}
|
|
7719
|
+
` : ""}${itemCls !== void 0 && sep === void 0 ? `if(count>=${min}&&${p}gate&&${hasTrivia === "false" ? "true" : hasTrivia === "true" ? "false" : "!hasTrivia"}&&${itemMiss("cur")})break
|
|
7594
7720
|
` : ""}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
7721
|
${markBody}
|
|
7596
7722
|
let itemStart=cur
|
|
@@ -7615,7 +7741,7 @@ itemStart=${hasTrivia === "false" ? "EC.e" : hasTrivia === "true" ? `${skip}(inp
|
|
|
7615
7741
|
${rb}
|
|
7616
7742
|
${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
|
|
7617
7743
|
}
|
|
7618
|
-
${itemCls === void 0 ? "" : `if(count>=${min}&&${p}gate
|
|
7744
|
+
${itemCls === void 0 ? "" : `if(count>=${min}&&${p}gate&&${itemMiss("itemStart")}){
|
|
7619
7745
|
${rb}
|
|
7620
7746
|
${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
|
|
7621
7747
|
}
|
|
@@ -11991,6 +12117,22 @@ var Encoder = class {
|
|
|
11991
12117
|
choiceRollbackMasks = /* @__PURE__ */ new Map();
|
|
11992
12118
|
nonCommittingChoiceSites = /* @__PURE__ */ new Set();
|
|
11993
12119
|
failureRollbackCleanSites = /* @__PURE__ */ new Set();
|
|
12120
|
+
/**
|
|
12121
|
+
* `hasSideWriter` memo for `failureNeedsRollback`, shared across every call
|
|
12122
|
+
* for the lifetime of this `Encoder`. A cached entry is written only when
|
|
12123
|
+
* `complete` is true, which means the answer is a path-independent fact
|
|
12124
|
+
* about that combinator node — it does not depend on which root's traversal
|
|
12125
|
+
* asked, only on the node's own reachable subgraph. Scoping the memo per call
|
|
12126
|
+
* (as a local inside `failureNeedsRollback`) was correct but discarded that
|
|
12127
|
+
* fact after every arm, so a grammar with many ordered-choice arms / optional
|
|
12128
|
+
* / attempt sites re-walked the SAME shared rule graph from scratch for each
|
|
12129
|
+
* site — O(sites × graph size) instead of O(graph size). Measured on the
|
|
12130
|
+
* scss-parser grammar (composed CSS-base superset, the deepest/largest of the
|
|
12131
|
+
* four grammars): 47-50s for one `compileRuleMap` with the per-call memo,
|
|
12132
|
+
* versus the whole macro transform completing in under a second once this
|
|
12133
|
+
* memo is hoisted here.
|
|
12134
|
+
*/
|
|
12135
|
+
sideWriterMemo = /* @__PURE__ */ new Map();
|
|
11994
12136
|
labels = void 0;
|
|
11995
12137
|
/** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
|
|
11996
12138
|
activeTrivia = void 0;
|
|
@@ -12416,13 +12558,13 @@ var Encoder = class {
|
|
|
12416
12558
|
const refName = p._ruleName;
|
|
12417
12559
|
const winner = refName === void 0 ? void 0 : this.winners?.[refName];
|
|
12418
12560
|
const root = winner !== void 0 && !winnerWrapsReference2(winner, p) ? winner : p;
|
|
12419
|
-
const sideWriterMemo =
|
|
12420
|
-
const
|
|
12561
|
+
const sideWriterMemo = this.sideWriterMemo;
|
|
12562
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12563
|
+
const hasSideWriter = (current) => {
|
|
12421
12564
|
const cached = sideWriterMemo.get(current);
|
|
12422
12565
|
if (cached !== void 0) return { found: cached, complete: true };
|
|
12423
12566
|
if (seen.has(current)) return { found: false, complete: false };
|
|
12424
|
-
|
|
12425
|
-
next.add(current);
|
|
12567
|
+
seen.add(current);
|
|
12426
12568
|
const def = current._def;
|
|
12427
12569
|
let result;
|
|
12428
12570
|
switch (def.tag) {
|
|
@@ -12437,11 +12579,11 @@ var Encoder = class {
|
|
|
12437
12579
|
const name = current._ruleName;
|
|
12438
12580
|
const resolvedWinner = name === void 0 ? void 0 : this.winners?.[name];
|
|
12439
12581
|
if (resolvedWinner !== void 0 && !winnerWrapsReference2(resolvedWinner, current)) {
|
|
12440
|
-
result = hasSideWriter(resolvedWinner
|
|
12582
|
+
result = hasSideWriter(resolvedWinner);
|
|
12441
12583
|
break;
|
|
12442
12584
|
}
|
|
12443
12585
|
try {
|
|
12444
|
-
result = hasSideWriter(def.thunk()
|
|
12586
|
+
result = hasSideWriter(def.thunk());
|
|
12445
12587
|
} catch {
|
|
12446
12588
|
result = { found: true, complete: true };
|
|
12447
12589
|
}
|
|
@@ -12451,7 +12593,7 @@ var Encoder = class {
|
|
|
12451
12593
|
let complete = true;
|
|
12452
12594
|
result = { found: false, complete: true };
|
|
12453
12595
|
for (const child of childrenOf(def)) {
|
|
12454
|
-
const childResult = hasSideWriter(child
|
|
12596
|
+
const childResult = hasSideWriter(child);
|
|
12455
12597
|
if (childResult.found) {
|
|
12456
12598
|
result = { found: true, complete: true };
|
|
12457
12599
|
break;
|
|
@@ -12461,6 +12603,7 @@ var Encoder = class {
|
|
|
12461
12603
|
if (!result.found) result = { found: false, complete };
|
|
12462
12604
|
}
|
|
12463
12605
|
}
|
|
12606
|
+
seen.delete(current);
|
|
12464
12607
|
if (result.found || result.complete) sideWriterMemo.set(current, result.found);
|
|
12465
12608
|
return result;
|
|
12466
12609
|
};
|