parseman 0.59.3 → 0.60.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analysis/diagnostics.js +874 -188
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/cli/index.js +874 -188
- package/dist/cli/index.js.map +3 -3
- package/dist/combinators/dispatch.d.ts +13 -1
- package/dist/combinators/dispatch.d.ts.map +1 -1
- package/dist/combinators/first-set.d.ts +35 -2
- package/dist/combinators/first-set.d.ts.map +1 -1
- package/dist/combinators/regex.d.ts.map +1 -1
- package/dist/combinators/trivia-boundary.d.ts +11 -0
- package/dist/combinators/trivia-boundary.d.ts.map +1 -1
- package/dist/combinators/trivia-skip.d.ts +1 -1
- package/dist/combinators/trivia-skip.d.ts.map +1 -1
- package/dist/compiler/token-alphabet.d.ts +2 -0
- package/dist/compiler/token-alphabet.d.ts.map +1 -1
- package/dist/compiler/token-capability.js +65 -53
- package/dist/compiler/token-capability.js.map +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +894 -197
- package/dist/index.js.map +3 -3
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.js +901 -199
- package/dist/plugin/index.js.map +3 -3
- package/dist/regex/first-set.d.ts +19 -0
- package/dist/regex/first-set.d.ts.map +1 -1
- package/dist/table/assemble.d.ts +14 -0
- package/dist/table/assemble.d.ts.map +1 -1
- package/dist/table/child-slots.d.ts.map +1 -1
- package/dist/table/compile-rule-map.d.ts.map +1 -1
- package/dist/table/emit-assembly.d.ts +8 -2
- package/dist/table/emit-assembly.d.ts.map +1 -1
- package/dist/table/emit.d.ts +4 -3
- package/dist/table/emit.d.ts.map +1 -1
- package/dist/table/encode.d.ts.map +1 -1
- package/dist/table/exec.d.ts.map +1 -1
- package/dist/table/factor-choice.d.ts +27 -0
- package/dist/table/factor-choice.d.ts.map +1 -1
- package/dist/table/gap-gate.d.ts +11 -0
- package/dist/table/gap-gate.d.ts.map +1 -0
- package/dist/table/index.js +924 -199
- package/dist/table/index.js.map +3 -3
- package/dist/table/lex-program.d.ts.map +1 -1
- package/dist/table/ops.d.ts +34 -6
- package/dist/table/ops.d.ts.map +1 -1
- package/dist/table/program.d.ts +6 -1
- package/dist/table/program.d.ts.map +1 -1
- package/dist/types.d.ts +16 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/analysis/duplication.ts +1 -1
- package/src/combinators/attempt.ts +1 -1
- package/src/combinators/dispatch.ts +30 -6
- package/src/combinators/first-set.ts +55 -12
- package/src/combinators/node.ts +1 -1
- package/src/combinators/regex.ts +9 -4
- package/src/combinators/repeat.ts +6 -6
- package/src/combinators/sequence.ts +1 -1
- package/src/combinators/trivia-boundary.ts +18 -0
- package/src/combinators/trivia-skip.ts +1 -1
- package/src/compiler/ir-serialize.ts +1 -1
- package/src/compiler/token-alphabet.ts +3 -1
- package/src/coverage.ts +1 -1
- package/src/index.ts +1 -1
- package/src/plugin/evaluator.ts +8 -3
- package/src/regex/first-set.ts +37 -3
- package/src/table/assemble.ts +171 -25
- package/src/table/child-slots.ts +8 -3
- package/src/table/compile-rule-map.ts +6 -3
- package/src/table/emit-assembly.ts +182 -31
- package/src/table/emit.ts +6 -4
- package/src/table/encode.ts +468 -73
- package/src/table/exec.ts +38 -13
- package/src/table/factor-choice.ts +62 -0
- package/src/table/fail-clean.ts +2 -2
- package/src/table/gap-gate.ts +55 -0
- package/src/table/hold-gap.ts +2 -2
- package/src/table/lex-program.ts +15 -6
- package/src/table/ops.ts +37 -6
- package/src/table/program.ts +7 -2
- package/src/table/select-hot.ts +7 -2
- package/src/types.ts +12 -5
- package/src/version.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -27,15 +27,56 @@ function implicitLeadsDropped(ranges) {
|
|
|
27
27
|
return out;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
// src/combinators/trivia-boundary.ts
|
|
31
|
+
var MAX_DEPTH = 12;
|
|
32
|
+
function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
|
|
33
|
+
if (depth === 0) return true;
|
|
34
|
+
const d = p._def;
|
|
35
|
+
switch (d.tag) {
|
|
36
|
+
// Multi-term forms: the gaps BETWEEN terms are the ambient-trivia positions.
|
|
37
|
+
case "sequence":
|
|
38
|
+
return d.parsers.length > 1;
|
|
39
|
+
case "many":
|
|
40
|
+
case "oneOrMore":
|
|
41
|
+
case "sepBy":
|
|
42
|
+
return true;
|
|
43
|
+
// Transparent wrappers — they add no position, so ask what they wrap.
|
|
44
|
+
case "node":
|
|
45
|
+
case "transform":
|
|
46
|
+
case "leaf":
|
|
47
|
+
case "label":
|
|
48
|
+
case "field":
|
|
49
|
+
case "token":
|
|
50
|
+
case "attempt":
|
|
51
|
+
case "optional":
|
|
52
|
+
case "expect":
|
|
53
|
+
case "withCtx":
|
|
54
|
+
case "recover":
|
|
55
|
+
case "trivia":
|
|
56
|
+
return hasOwnTriviaBoundary(d.parser, depth - 1);
|
|
57
|
+
// An alternation adds no position either, but ONE arm that has one is enough
|
|
58
|
+
// to make the scope meaningful for this rule.
|
|
59
|
+
case "choice":
|
|
60
|
+
return d.parsers.some((a) => hasOwnTriviaBoundary(a, depth - 1));
|
|
61
|
+
default:
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function triviaThroughRef(ref2, target, trivia2) {
|
|
66
|
+
if (trivia2 !== void 0 && trivia2 !== null) return trivia2;
|
|
67
|
+
const amb = ref2._meta.grammarTrivia ?? target._meta.grammarTrivia;
|
|
68
|
+
return amb !== void 0 && hasOwnTriviaBoundary(target) ? amb : trivia2;
|
|
69
|
+
}
|
|
70
|
+
|
|
30
71
|
// src/combinators/first-set.ts
|
|
31
|
-
function classifyFinalChoice(arms, resolve, activeTrivia) {
|
|
72
|
+
function classifyFinalChoice(arms, resolve, activeTrivia, consuming = true, constructionSets = false) {
|
|
32
73
|
const firstSets = [];
|
|
33
74
|
const nullable2 = [];
|
|
34
75
|
let exclusive = true;
|
|
35
76
|
for (const arm of arms) {
|
|
36
77
|
const empty2 = matchesEmpty(arm, /* @__PURE__ */ new Set(), resolve);
|
|
37
78
|
nullable2.push(empty2);
|
|
38
|
-
firstSets.push(empty2 ? { kind: "any" } : firstSetOf(arm, /* @__PURE__ */ new Set(), resolve, activeTrivia));
|
|
79
|
+
firstSets.push(empty2 ? { kind: "any" } : constructionSets ? arm._meta.firstSet : firstSetOf(arm, /* @__PURE__ */ new Set(), resolve, activeTrivia, consuming));
|
|
39
80
|
if (empty2) exclusive = false;
|
|
40
81
|
}
|
|
41
82
|
if (exclusive) {
|
|
@@ -220,7 +261,7 @@ function narrowBy(acc, constraint) {
|
|
|
220
261
|
function applyAssertion(fs, assertion) {
|
|
221
262
|
return assertion === null ? fs : fs.kind === "empty" ? assertion : narrowBy(fs, assertion);
|
|
222
263
|
}
|
|
223
|
-
function sequenceSet(parsers, fs, empties, trivia2) {
|
|
264
|
+
function sequenceSet(parsers, fs, empties, trivia2, consuming = true) {
|
|
224
265
|
const afterBoundary = (i) => {
|
|
225
266
|
const rest = at(i);
|
|
226
267
|
return trivia2 ? union(rest, fs(trivia2)) : rest;
|
|
@@ -236,24 +277,24 @@ function sequenceSet(parsers, fs, empties, trivia2) {
|
|
|
236
277
|
}
|
|
237
278
|
const first = fs(p);
|
|
238
279
|
if (!empties(p) || i + 1 === parsers.length) return first;
|
|
239
|
-
return union(first, afterBoundary(i + 1));
|
|
280
|
+
return union((consuming ? p._meta.consumingFirstSet : void 0) ?? first, afterBoundary(i + 1));
|
|
240
281
|
};
|
|
241
282
|
return at(0);
|
|
242
283
|
}
|
|
243
284
|
function sequenceFirstSet(parsers) {
|
|
244
|
-
return sequenceSet(parsers, (p) => p._meta.firstSet, matchesEmpty);
|
|
285
|
+
return sequenceSet(parsers, (p) => p._meta.firstSet, matchesEmpty, void 0, false);
|
|
245
286
|
}
|
|
246
|
-
function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve, activeTrivia) {
|
|
287
|
+
function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve, activeTrivia, consuming = true) {
|
|
247
288
|
if (seen.has(p)) return any();
|
|
248
289
|
seen.add(p);
|
|
249
290
|
try {
|
|
250
|
-
return firstSetBody(p, seen, resolve, activeTrivia);
|
|
291
|
+
return firstSetBody(p, seen, resolve, activeTrivia, consuming);
|
|
251
292
|
} finally {
|
|
252
293
|
seen.delete(p);
|
|
253
294
|
}
|
|
254
295
|
}
|
|
255
|
-
function firstSetBody(p, seen, resolve, activeTrivia) {
|
|
256
|
-
const fs = (c) => firstSetOf(c, seen, resolve, activeTrivia);
|
|
296
|
+
function firstSetBody(p, seen, resolve, activeTrivia, consuming) {
|
|
297
|
+
const fs = (c) => firstSetOf(c, seen, resolve, activeTrivia, consuming);
|
|
257
298
|
const empties = (c) => matchesEmpty(c, /* @__PURE__ */ new Set(), resolve);
|
|
258
299
|
const d = p._def;
|
|
259
300
|
switch (d.tag) {
|
|
@@ -265,13 +306,16 @@ function firstSetBody(p, seen, resolve, activeTrivia) {
|
|
|
265
306
|
case "dispatch":
|
|
266
307
|
return fs(d.selector);
|
|
267
308
|
case "lazy": {
|
|
268
|
-
|
|
269
|
-
if (
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
309
|
+
let target = winnerForRef(p, resolve);
|
|
310
|
+
if (target === void 0) {
|
|
311
|
+
try {
|
|
312
|
+
target = d.thunk();
|
|
313
|
+
} catch {
|
|
314
|
+
return any();
|
|
315
|
+
}
|
|
274
316
|
}
|
|
317
|
+
const through = activeTrivia === null && resolve !== void 0;
|
|
318
|
+
return firstSetOf(target, seen, resolve, through ? triviaThroughRef(p, target, null) : activeTrivia, consuming);
|
|
275
319
|
}
|
|
276
320
|
case "choice": {
|
|
277
321
|
let out = empty();
|
|
@@ -279,7 +323,7 @@ function firstSetBody(p, seen, resolve, activeTrivia) {
|
|
|
279
323
|
return out;
|
|
280
324
|
}
|
|
281
325
|
case "sequence": {
|
|
282
|
-
return sequenceSet(d.parsers, fs, empties, activeTrivia);
|
|
326
|
+
return sequenceSet(d.parsers, fs, empties, activeTrivia, consuming);
|
|
283
327
|
}
|
|
284
328
|
case "peek": {
|
|
285
329
|
const inner = d.parser;
|
|
@@ -291,7 +335,6 @@ function firstSetBody(p, seen, resolve, activeTrivia) {
|
|
|
291
335
|
case "transform":
|
|
292
336
|
case "label":
|
|
293
337
|
case "trivia":
|
|
294
|
-
case "token":
|
|
295
338
|
case "leaf":
|
|
296
339
|
case "node":
|
|
297
340
|
case "sepBy":
|
|
@@ -301,12 +344,16 @@ function firstSetBody(p, seen, resolve, activeTrivia) {
|
|
|
301
344
|
// with a rule reference — resolve through it like any other wrapper.
|
|
302
345
|
case "attempt":
|
|
303
346
|
return fs(d.parser);
|
|
347
|
+
// A token runs its body with trivia cleared (`token.ts`).
|
|
348
|
+
case "token":
|
|
349
|
+
return firstSetOf(d.parser, seen, resolve, activeTrivia === void 0 ? void 0 : null, consuming);
|
|
304
350
|
case "grammar":
|
|
305
351
|
return firstSetOf(
|
|
306
352
|
d.parser,
|
|
307
353
|
seen,
|
|
308
354
|
resolve,
|
|
309
|
-
d.clearTrivia ? null : d.triviaParser ?? activeTrivia
|
|
355
|
+
d.clearTrivia ? null : d.triviaParser ?? activeTrivia,
|
|
356
|
+
consuming
|
|
310
357
|
);
|
|
311
358
|
// A run starts with its first line's prefix; a nullable prefix starts with anything.
|
|
312
359
|
case "lines": {
|
|
@@ -999,10 +1046,12 @@ function parseRegex(src, unicode = false, sets = false) {
|
|
|
999
1046
|
const parseGroup = () => {
|
|
1000
1047
|
i++;
|
|
1001
1048
|
let lookaround = false;
|
|
1049
|
+
let lookahead = false;
|
|
1002
1050
|
if (src[i] === "?") {
|
|
1003
1051
|
const c1 = src[i + 1];
|
|
1004
1052
|
if (c1 === ":") i += 2;
|
|
1005
1053
|
else if (c1 === "=" || c1 === "!") {
|
|
1054
|
+
lookahead = c1 === "=";
|
|
1006
1055
|
i += 2;
|
|
1007
1056
|
lookaround = true;
|
|
1008
1057
|
} else if (c1 === "<") {
|
|
@@ -1020,7 +1069,8 @@ function parseRegex(src, unicode = false, sets = false) {
|
|
|
1020
1069
|
const inner = parseAlt();
|
|
1021
1070
|
if (src[i] !== ")") throw BAIL;
|
|
1022
1071
|
i++;
|
|
1023
|
-
|
|
1072
|
+
if (lookaround) return lookahead ? { t: "empty", look: inner } : EMPTY2;
|
|
1073
|
+
return inner;
|
|
1024
1074
|
};
|
|
1025
1075
|
const parseClass = () => {
|
|
1026
1076
|
let k = i + 1;
|
|
@@ -1213,6 +1263,13 @@ function regexCanMatchEmpty(source) {
|
|
|
1213
1263
|
return true;
|
|
1214
1264
|
}
|
|
1215
1265
|
}
|
|
1266
|
+
function consumingFirstSetFromRegex(source, flags = "") {
|
|
1267
|
+
try {
|
|
1268
|
+
return firstSet(parseRegex(source, flags.includes("u") || flags.includes("v"), flags.includes("v")));
|
|
1269
|
+
} catch {
|
|
1270
|
+
return any();
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1216
1273
|
function firstSetFromRegex(source, flags = "") {
|
|
1217
1274
|
let ast;
|
|
1218
1275
|
try {
|
|
@@ -1223,6 +1280,20 @@ function firstSetFromRegex(source, flags = "") {
|
|
|
1223
1280
|
if (nullable(ast)) return { firstSet: any(), canMatchNewline: canConsumeNewline(ast) };
|
|
1224
1281
|
return { firstSet: firstSet(ast), canMatchNewline: canConsumeNewline(ast) };
|
|
1225
1282
|
}
|
|
1283
|
+
function regexFirstTwo(source, flags = "") {
|
|
1284
|
+
let ast;
|
|
1285
|
+
try {
|
|
1286
|
+
ast = parseRegex(source, flags.includes("u") || flags.includes("v"), flags.includes("v"));
|
|
1287
|
+
} catch {
|
|
1288
|
+
return void 0;
|
|
1289
|
+
}
|
|
1290
|
+
const parts = ast.t === "seq" ? ast.parts : [ast];
|
|
1291
|
+
const a = parts[0];
|
|
1292
|
+
const b = parts[1];
|
|
1293
|
+
if (a === void 0 || a.t !== "char" || a.set.kind !== "ranges" || b === void 0) return void 0;
|
|
1294
|
+
const second = b.t === "char" ? b.set : b.t === "empty" && b.look !== void 0 && !nullable(b.look) ? firstSet(b.look) : void 0;
|
|
1295
|
+
return second !== void 0 && second.kind === "ranges" ? { first: a.set, second } : void 0;
|
|
1296
|
+
}
|
|
1226
1297
|
|
|
1227
1298
|
// src/combinators/regex.ts
|
|
1228
1299
|
import { PlainLeaf as PlainLeaf3, PlainSpan as PlainSpan3 } from "./cst/plain.js";
|
|
@@ -1303,9 +1374,14 @@ function regex(pattern, flags = "") {
|
|
|
1303
1374
|
const anchored = new RegExp(source, "y" + resolvedFlags.replace(/[gy]/g, ""));
|
|
1304
1375
|
const scan = shortScanner(source, resolvedFlags);
|
|
1305
1376
|
const raw = firstSetFromRegex(source, resolvedFlags);
|
|
1306
|
-
const
|
|
1377
|
+
const forFlags = (fs) => !resolvedFlags.includes("i") ? fs : resolvedFlags.includes("u") || resolvedFlags.includes("v") ? any() : asciiCaseFold(fs);
|
|
1378
|
+
const firstSet2 = forFlags(raw.firstSet);
|
|
1307
1379
|
const canMatchNewline = raw.canMatchNewline;
|
|
1308
1380
|
const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
|
|
1381
|
+
if (firstSet2.kind === "any" && regexCanMatchEmpty(source)) {
|
|
1382
|
+
const consuming = forFlags(consumingFirstSetFromRegex(source, resolvedFlags));
|
|
1383
|
+
if (consuming.kind !== "any") meta.consumingFirstSet = consuming;
|
|
1384
|
+
}
|
|
1309
1385
|
const def = { tag: "regex", source, flags: resolvedFlags };
|
|
1310
1386
|
const expected = directTerminalFailureExpected(def);
|
|
1311
1387
|
const parseScalar = (input, pos, ctx) => {
|
|
@@ -2356,10 +2432,6 @@ function scanTriviaCompact(input, cur, ctx) {
|
|
|
2356
2432
|
const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
|
|
2357
2433
|
return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
|
|
2358
2434
|
}
|
|
2359
|
-
function scanTrivia(input, cur, ctx) {
|
|
2360
|
-
const scan = scanTriviaCompact(input, cur, ctx);
|
|
2361
|
-
return typeof scan === "number" ? { end: scan, commit: NOOP_COMMIT } : scan;
|
|
2362
|
-
}
|
|
2363
2435
|
function skipTriviaScanned(s, input, cur, ctx) {
|
|
2364
2436
|
const end = s(input, cur);
|
|
2365
2437
|
if (end !== cur) {
|
|
@@ -3008,7 +3080,7 @@ function sequence(...parsers) {
|
|
|
3008
3080
|
if (tolerant) {
|
|
3009
3081
|
followSentinels ??= parsers.map((_, i) => firstSetSentinel(
|
|
3010
3082
|
parsers.slice(i + 1).reduce(
|
|
3011
|
-
(set, parser2) => union(set, firstSetOf(parser2)),
|
|
3083
|
+
(set, parser2) => union(set, firstSetOf(parser2, /* @__PURE__ */ new Set(), void 0, void 0, false)),
|
|
3012
3084
|
{ kind: "empty" }
|
|
3013
3085
|
)
|
|
3014
3086
|
));
|
|
@@ -3631,8 +3703,9 @@ function when(key, parser2, opts = {}) {
|
|
|
3631
3703
|
function makeWhen(opts = {}) {
|
|
3632
3704
|
return (key, parser2) => when(key, parser2, opts);
|
|
3633
3705
|
}
|
|
3634
|
-
function otherwise(parser2) {
|
|
3635
|
-
|
|
3706
|
+
function otherwise(parser2, opts = {}) {
|
|
3707
|
+
const usesRouted = parserUsesRouted(parser2);
|
|
3708
|
+
return opts.commit === false ? { kind: "otherwise", parser: parser2, usesRouted, commit: false } : { kind: "otherwise", parser: parser2, usesRouted };
|
|
3636
3709
|
}
|
|
3637
3710
|
function routed(fallback) {
|
|
3638
3711
|
return {
|
|
@@ -3664,6 +3737,7 @@ function dispatch(selector, ...arms) {
|
|
|
3664
3737
|
}
|
|
3665
3738
|
let fallback;
|
|
3666
3739
|
let fallbackUsesRouted = false;
|
|
3740
|
+
let fallbackCommits = true;
|
|
3667
3741
|
const matchers = [];
|
|
3668
3742
|
const cases = [];
|
|
3669
3743
|
const seen = [];
|
|
@@ -3674,6 +3748,7 @@ function dispatch(selector, ...arms) {
|
|
|
3674
3748
|
if (i !== arms.length - 1) throw new Error("parseman: otherwise() must be the last dispatch() arm");
|
|
3675
3749
|
fallback = arm.parser;
|
|
3676
3750
|
fallbackUsesRouted = arm.usesRouted === true;
|
|
3751
|
+
fallbackCommits = arm.commit !== false;
|
|
3677
3752
|
continue;
|
|
3678
3753
|
}
|
|
3679
3754
|
if (arm.kind === "whenMatcher") {
|
|
@@ -3724,7 +3799,11 @@ function dispatch(selector, ...arms) {
|
|
|
3724
3799
|
selector,
|
|
3725
3800
|
cases,
|
|
3726
3801
|
...matchers.length === 0 ? {} : { matchers },
|
|
3727
|
-
...fallback === void 0 ? {} : {
|
|
3802
|
+
...fallback === void 0 ? {} : {
|
|
3803
|
+
otherwise: fallback,
|
|
3804
|
+
...fallbackUsesRouted ? { otherwiseUsesRouted: true } : {},
|
|
3805
|
+
...fallbackCommits ? {} : { otherwiseCommit: false }
|
|
3806
|
+
}
|
|
3728
3807
|
},
|
|
3729
3808
|
parse(input, pos, ctx) {
|
|
3730
3809
|
if (parserUsesRouted(selector)) {
|
|
@@ -3733,7 +3812,8 @@ function dispatch(selector, ...arms) {
|
|
|
3733
3812
|
const selectorMark = saveTriviaMark(ctx);
|
|
3734
3813
|
const selected = selector.parse(input, pos, ctx);
|
|
3735
3814
|
if (!selected.ok) return selected;
|
|
3736
|
-
const
|
|
3815
|
+
const chosen = byKey.get(selected.value) ?? (byFoldedKey.size === 0 ? void 0 : byFoldedKey.get(asciiFoldKey(selected.value))) ?? matchers.find((matcher) => matchesDispatchMatcher(selected.value, matcher));
|
|
3816
|
+
const branch = chosen ?? (fallback === void 0 ? void 0 : { keys: [], parser: fallback, caseInsensitive: false, usesRouted: fallbackUsesRouted });
|
|
3737
3817
|
if (branch === void 0) {
|
|
3738
3818
|
const expected = cases.flatMap((entry) => entry.keys.map((key) => JSON.stringify(key)));
|
|
3739
3819
|
return { ok: false, expected, span: { start: selected.span.end, end: selected.span.end } };
|
|
@@ -3754,7 +3834,7 @@ function dispatch(selector, ...arms) {
|
|
|
3754
3834
|
}
|
|
3755
3835
|
if (!result.ok) {
|
|
3756
3836
|
rollbackTrivia(ctx, mark);
|
|
3757
|
-
return { ...result, committed: true };
|
|
3837
|
+
return chosen === void 0 && !fallbackCommits ? result : { ...result, committed: true };
|
|
3758
3838
|
}
|
|
3759
3839
|
return {
|
|
3760
3840
|
ok: true,
|
|
@@ -3783,7 +3863,7 @@ function attempt(parser2, options) {
|
|
|
3783
3863
|
return {
|
|
3784
3864
|
_tag: "attempt",
|
|
3785
3865
|
_meta: parser2._meta,
|
|
3786
|
-
_def:
|
|
3866
|
+
_def: { tag: "attempt", parser: parser2, ...contain ? { contain: true } : {}, ...guardable ? { guarded: true } : {} },
|
|
3787
3867
|
parse(input, pos, ctx) {
|
|
3788
3868
|
if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(parser2, input, pos)) {
|
|
3789
3869
|
if (failExpected === void 0) {
|
|
@@ -3873,9 +3953,9 @@ function many(combinator, opts = {}) {
|
|
|
3873
3953
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
3874
3954
|
isTrivia: false
|
|
3875
3955
|
};
|
|
3876
|
-
const def = { tag: "many", parser: combinator, min: 0, ...max === Infinity ? {} : { max } };
|
|
3877
|
-
let expected;
|
|
3878
3956
|
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
3957
|
+
const def = { tag: "many", parser: combinator, min: 0, ...max === Infinity ? {} : { max }, ...guardable ? { guarded: true } : {} };
|
|
3958
|
+
let expected;
|
|
3879
3959
|
const scalarChild = scalarOf(combinator);
|
|
3880
3960
|
const parseScalar = (input, pos, ctx) => repeatScalarTail(combinator, scalarChild, input, pos, ctx, guardable, def.valueUnused ? void 0 : [], max);
|
|
3881
3961
|
return {
|
|
@@ -3922,9 +4002,9 @@ function atLeast(combinator, min, max) {
|
|
|
3922
4002
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
3923
4003
|
isTrivia: false
|
|
3924
4004
|
};
|
|
3925
|
-
const def = { tag: "oneOrMore", parser: combinator, min, ...max === Infinity ? {} : { max } };
|
|
3926
|
-
let expected;
|
|
3927
4005
|
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
4006
|
+
const def = { tag: "oneOrMore", parser: combinator, min, ...max === Infinity ? {} : { max }, ...guardable ? { guarded: true } : {} };
|
|
4007
|
+
let expected;
|
|
3928
4008
|
const scalarChild = scalarOf(combinator);
|
|
3929
4009
|
const parseScalar = (input, pos, ctx) => {
|
|
3930
4010
|
let cur = scalarChild(input, pos, ctx);
|
|
@@ -4178,42 +4258,6 @@ function sepBy(combinator, separatorArg, opts = {}) {
|
|
|
4178
4258
|
};
|
|
4179
4259
|
}
|
|
4180
4260
|
|
|
4181
|
-
// src/combinators/trivia-boundary.ts
|
|
4182
|
-
var MAX_DEPTH = 12;
|
|
4183
|
-
function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
|
|
4184
|
-
if (depth === 0) return true;
|
|
4185
|
-
const d = p._def;
|
|
4186
|
-
switch (d.tag) {
|
|
4187
|
-
// Multi-term forms: the gaps BETWEEN terms are the ambient-trivia positions.
|
|
4188
|
-
case "sequence":
|
|
4189
|
-
return d.parsers.length > 1;
|
|
4190
|
-
case "many":
|
|
4191
|
-
case "oneOrMore":
|
|
4192
|
-
case "sepBy":
|
|
4193
|
-
return true;
|
|
4194
|
-
// Transparent wrappers — they add no position, so ask what they wrap.
|
|
4195
|
-
case "node":
|
|
4196
|
-
case "transform":
|
|
4197
|
-
case "leaf":
|
|
4198
|
-
case "label":
|
|
4199
|
-
case "field":
|
|
4200
|
-
case "token":
|
|
4201
|
-
case "attempt":
|
|
4202
|
-
case "optional":
|
|
4203
|
-
case "expect":
|
|
4204
|
-
case "withCtx":
|
|
4205
|
-
case "recover":
|
|
4206
|
-
case "trivia":
|
|
4207
|
-
return hasOwnTriviaBoundary(d.parser, depth - 1);
|
|
4208
|
-
// An alternation adds no position either, but ONE arm that has one is enough
|
|
4209
|
-
// to make the scope meaningful for this rule.
|
|
4210
|
-
case "choice":
|
|
4211
|
-
return d.parsers.some((a) => hasOwnTriviaBoundary(a, depth - 1));
|
|
4212
|
-
default:
|
|
4213
|
-
return false;
|
|
4214
|
-
}
|
|
4215
|
-
}
|
|
4216
|
-
|
|
4217
4261
|
// src/combinators/ref.ts
|
|
4218
4262
|
function withRuleTrivia(trivia2, ctx, run3) {
|
|
4219
4263
|
const savedLabels = ctx.triviaKindLabels;
|
|
@@ -5205,7 +5249,7 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
5205
5249
|
if (project !== void 0 && build !== void 0) {
|
|
5206
5250
|
throw new Error("node() options cannot combine project with a build callback");
|
|
5207
5251
|
}
|
|
5208
|
-
const baseDef = { tag: "node", parser: combinator, ...type === void 0 ? {} : { type }, ...build === void 0 ? {} : { build } };
|
|
5252
|
+
const baseDef = { tag: "node", parser: combinator, ...type === void 0 ? {} : { type }, ...build === void 0 ? {} : { build }, ...combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator) ? { guarded: true } : {} };
|
|
5209
5253
|
const meta = {
|
|
5210
5254
|
firstSet: combinator._meta.firstSet,
|
|
5211
5255
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
@@ -5764,14 +5808,15 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
5764
5808
|
return end < 0 ? next(input, pos) : end;
|
|
5765
5809
|
};
|
|
5766
5810
|
}
|
|
5767
|
-
let tail = (
|
|
5811
|
+
let tail = (input, pos, ctx, _lead, acc, _best, entered) => {
|
|
5812
|
+
if (!entered && ctx._probe !== void 0) for (const arm of arms) arm.run(input, pos, ctx);
|
|
5768
5813
|
ctx._fe = pos;
|
|
5769
5814
|
ctx._fx = acc ?? choiceExpected;
|
|
5770
5815
|
return -1;
|
|
5771
5816
|
};
|
|
5772
5817
|
for (let i = arms.length - 1; i >= 0; i--) {
|
|
5773
5818
|
const armRun = arms[i].run, cls = classes[i], staticExpected = armExpected[i], next = tail;
|
|
5774
|
-
tail = (input, pos, ctx, lead2, acc, best) => {
|
|
5819
|
+
tail = (input, pos, ctx, lead2, acc, best, entered) => {
|
|
5775
5820
|
if (cls !== void 0 && !classHas(cls, lead2)) {
|
|
5776
5821
|
return next(
|
|
5777
5822
|
input,
|
|
@@ -5779,7 +5824,8 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
5779
5824
|
ctx,
|
|
5780
5825
|
lead2,
|
|
5781
5826
|
best === pos ? appendExpected(acc, staticExpected) : acc,
|
|
5782
|
-
best
|
|
5827
|
+
best,
|
|
5828
|
+
entered
|
|
5783
5829
|
);
|
|
5784
5830
|
}
|
|
5785
5831
|
ctx._fc = false;
|
|
@@ -5795,7 +5841,7 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
5795
5841
|
if (nextAcc !== void 0) ctx._fx = nextAcc;
|
|
5796
5842
|
return -1;
|
|
5797
5843
|
}
|
|
5798
|
-
return next(input, pos, ctx, lead2, nextAcc, best);
|
|
5844
|
+
return next(input, pos, ctx, lead2, nextAcc, best, true);
|
|
5799
5845
|
};
|
|
5800
5846
|
}
|
|
5801
5847
|
return {
|
|
@@ -5806,7 +5852,8 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
5806
5852
|
ctx,
|
|
5807
5853
|
pos < input.length ? input.codePointAt(pos) : -1,
|
|
5808
5854
|
void 0,
|
|
5809
|
-
pos
|
|
5855
|
+
pos,
|
|
5856
|
+
false
|
|
5810
5857
|
)
|
|
5811
5858
|
};
|
|
5812
5859
|
}
|
|
@@ -5844,6 +5891,7 @@ function exclusiveChoiceNode(arms, classes, choiceFx) {
|
|
|
5844
5891
|
return -1;
|
|
5845
5892
|
}
|
|
5846
5893
|
}
|
|
5894
|
+
if (arm < 0 && ctx._probe !== void 0) for (const a of arms) a.run(input, pos, ctx);
|
|
5847
5895
|
ctx._fe = pos;
|
|
5848
5896
|
ctx._fx = choiceFx;
|
|
5849
5897
|
return -1;
|
|
@@ -6068,6 +6116,7 @@ function buildLexProgramRunner(spec, matchers, classes, expected) {
|
|
|
6068
6116
|
if (!classHas(cls, lead2)) {
|
|
6069
6117
|
ctx._fe = pos;
|
|
6070
6118
|
ctx._fx = choiceFx.slice();
|
|
6119
|
+
if (ctx._probe !== void 0) failAt(ctx, [...x0, ...x1, ...x2, ...x3], pos);
|
|
6071
6120
|
return -1;
|
|
6072
6121
|
}
|
|
6073
6122
|
let acc;
|
|
@@ -6179,7 +6228,7 @@ function validateDispatchSpec(spec, arity, fallbackRouted) {
|
|
|
6179
6228
|
for (const arm of arms) if (!Number.isInteger(arm) || arm < 0 || arm >= arity) return true;
|
|
6180
6229
|
return false;
|
|
6181
6230
|
};
|
|
6182
|
-
if (spec === void 0 || !Number.isInteger(arity) || arity < 0 || fallbackRouted
|
|
6231
|
+
if (spec === void 0 || !Number.isInteger(arity) || arity < 0 || !Number.isInteger(fallbackRouted) || fallbackRouted < 0 || fallbackRouted > 3 || spec.routed.length !== arity || spec.routed.some((value) => value !== 0 && value !== 1) || invalid(spec.byKey.values()) || invalid(spec.byFold.values()) || spec.match.some((matcher) => invalid([matcher[3]]))) {
|
|
6183
6232
|
throw new TypeError("table: malformed dispatch");
|
|
6184
6233
|
}
|
|
6185
6234
|
}
|
|
@@ -7254,6 +7303,7 @@ function classifyRuleMap(ruleMap) {
|
|
|
7254
7303
|
}
|
|
7255
7304
|
|
|
7256
7305
|
// src/table/factor-choice.ts
|
|
7306
|
+
var factoredChoices = /* @__PURE__ */ new WeakSet();
|
|
7257
7307
|
var DERIVED = /* @__PURE__ */ new Set(["_tag", "_meta", "_def", "_parseScalar", "_stickyRegex", "parse"]);
|
|
7258
7308
|
function isCombinator(v) {
|
|
7259
7309
|
return typeof v === "object" && v !== null && "_def" in v && "_meta" in v;
|
|
@@ -7345,6 +7395,7 @@ function factorSharedEnds(d) {
|
|
|
7345
7395
|
for (let i = at + 1; i < n; i++) if (!never(first.terms[i])) return void 0;
|
|
7346
7396
|
if (arms.some((a) => mayCommitFailure(a))) return void 0;
|
|
7347
7397
|
const middle = choice(...shapes.map((s) => s.terms[at]));
|
|
7398
|
+
factoredChoices.add(middle);
|
|
7348
7399
|
if (middle._def.tag === "choice" && middle._def.autoNot.some((a) => a !== null)) return void 0;
|
|
7349
7400
|
const st = middle._def.tag === "choice" ? middle._def.strategy : void 0;
|
|
7350
7401
|
if (st === void 0 || st.tag !== "firstMatch" && st.tag !== "sharedPrefix" && !(st.tag === "literalsLongestFirst" && st.sortedIndices.every((x, i) => x === i))) return void 0;
|
|
@@ -7357,6 +7408,37 @@ function factorSharedEnds(d) {
|
|
|
7357
7408
|
for (let j = first.wrappers.length - 1; j >= 0 && out !== void 0; j--) out = rewrap(first.wrappers[j], out);
|
|
7358
7409
|
return out === void 0 ? void 0 : attempt(out);
|
|
7359
7410
|
}
|
|
7411
|
+
function factorPrefixArms(d) {
|
|
7412
|
+
const arms = d.parsers;
|
|
7413
|
+
if (arms.length < 2) return void 0;
|
|
7414
|
+
if (d.strategy.tag !== "firstMatch" && d.strategy.tag !== "sharedPrefix") return void 0;
|
|
7415
|
+
if (d.gates.some((g) => g !== null) || d.autoNot.some((a) => a !== null)) return void 0;
|
|
7416
|
+
const out = [...arms];
|
|
7417
|
+
let changed = false;
|
|
7418
|
+
for (let i = 0; i + 1 < arms.length; i++) {
|
|
7419
|
+
const arm = arms[i];
|
|
7420
|
+
if (arm._def.tag !== "sequence" || arm._def.valueUnused !== true) continue;
|
|
7421
|
+
const terms = arm._def.parsers;
|
|
7422
|
+
const next = arms[i + 1];
|
|
7423
|
+
const prefix = next._def.tag === "sequence" && next._def.valueUnused === true ? next._def.parsers : [next];
|
|
7424
|
+
if (prefix.length >= terms.length) continue;
|
|
7425
|
+
if (!prefix.every((t, j) => sameComb(t, terms[j], 0))) continue;
|
|
7426
|
+
const rest = terms.slice(prefix.length);
|
|
7427
|
+
if (rest.every(never)) continue;
|
|
7428
|
+
const tail = rest.length === 1 ? rest[0] : sequence(...rest);
|
|
7429
|
+
if (tail !== rest[0]) tail._def.valueUnused = true;
|
|
7430
|
+
const parts = [...terms.slice(0, prefix.length), optional(tail)];
|
|
7431
|
+
const seq = sequence(...parts);
|
|
7432
|
+
seq._def.valueUnused = true;
|
|
7433
|
+
out[i] = seq;
|
|
7434
|
+
changed = true;
|
|
7435
|
+
}
|
|
7436
|
+
if (!changed) return void 0;
|
|
7437
|
+
const rebuilt = choice(...out);
|
|
7438
|
+
factoredChoices.add(rebuilt);
|
|
7439
|
+
const st = rebuilt._def.tag === "choice" ? rebuilt._def.strategy : void 0;
|
|
7440
|
+
return st !== void 0 && (st.tag === "firstMatch" || st.tag === "sharedPrefix") ? rebuilt : void 0;
|
|
7441
|
+
}
|
|
7360
7442
|
|
|
7361
7443
|
// src/table/ops.ts
|
|
7362
7444
|
var OP_LIT = 1;
|
|
@@ -7402,6 +7484,9 @@ var OP_LEX_BODY = 42;
|
|
|
7402
7484
|
var OP_LEX_PROGRAM = 43;
|
|
7403
7485
|
var OP_SOURCE_LEAF = 44;
|
|
7404
7486
|
var OP_RGATE = 45;
|
|
7487
|
+
var OP_GAPGATE = 46;
|
|
7488
|
+
var OP_RGATE2 = 47;
|
|
7489
|
+
var OP_STRICT = 48;
|
|
7405
7490
|
var OP_DISPATCH = 25;
|
|
7406
7491
|
var OP_ROUTED = 26;
|
|
7407
7492
|
var OP_NAMES = {
|
|
@@ -7449,7 +7534,10 @@ var OP_NAMES = {
|
|
|
7449
7534
|
[OP_COV]: "COV",
|
|
7450
7535
|
[OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
|
|
7451
7536
|
[OP_LEX_BODY]: "LEX_BODY",
|
|
7452
|
-
[OP_LEX_PROGRAM]: "LEX_PROGRAM"
|
|
7537
|
+
[OP_LEX_PROGRAM]: "LEX_PROGRAM",
|
|
7538
|
+
[OP_GAPGATE]: "GAPGATE",
|
|
7539
|
+
[OP_RGATE2]: "RGATE2",
|
|
7540
|
+
[OP_STRICT]: "STRICT"
|
|
7453
7541
|
};
|
|
7454
7542
|
|
|
7455
7543
|
// src/compiler/direct-projection.ts
|
|
@@ -7740,6 +7828,7 @@ function directFixedLexNode(parser2, resolve, active, pureOnly = false, cleared
|
|
|
7740
7828
|
arms,
|
|
7741
7829
|
parsers: def.parsers,
|
|
7742
7830
|
cleared,
|
|
7831
|
+
disjoint: def.disjoint,
|
|
7743
7832
|
armExpected: def.parsers.map(deriveExpected),
|
|
7744
7833
|
expected: def.parsers.flatMap(deriveExpected)
|
|
7745
7834
|
};
|
|
@@ -7849,6 +7938,29 @@ var UnsupportedConstruct = class extends Error {
|
|
|
7849
7938
|
this.tag = tag;
|
|
7850
7939
|
}
|
|
7851
7940
|
};
|
|
7941
|
+
function firstTwo(p) {
|
|
7942
|
+
const d = p._def;
|
|
7943
|
+
if (d.tag === "label" || d.tag === "grammar") return firstTwo(d.parser);
|
|
7944
|
+
let two;
|
|
7945
|
+
if (d.tag === "literal" && d.value.length >= 2 && d.caseInsensitive !== true) {
|
|
7946
|
+
const second = d.value.codePointAt(1);
|
|
7947
|
+
two = { first: { kind: "ranges", ranges: [{ lo: d.value.charCodeAt(0), hi: d.value.charCodeAt(0) }] }, second: { kind: "ranges", ranges: [{ lo: second, hi: second }] } };
|
|
7948
|
+
} else if (d.tag === "regex" && !d.flags.includes("i")) {
|
|
7949
|
+
const units = regexFirstTwo(d.source, d.flags);
|
|
7950
|
+
if (units !== void 0) two = units;
|
|
7951
|
+
}
|
|
7952
|
+
if (two === void 0 || two.first.kind !== "ranges") return void 0;
|
|
7953
|
+
return two.first.ranges.every((r) => r.hi < 55296 || r.lo > 57343 && r.hi <= 65535) ? two : void 0;
|
|
7954
|
+
}
|
|
7955
|
+
var GAP_CHARS = /* @__PURE__ */ new Set([9, 10, 12, 13, 32, 47]);
|
|
7956
|
+
function isGap(p) {
|
|
7957
|
+
if (matchesEmpty(p)) return true;
|
|
7958
|
+
const fs = p._meta.firstSet;
|
|
7959
|
+
return fs.kind === "ranges" && fs.ranges.every((r) => {
|
|
7960
|
+
for (let c = r.lo; c <= r.hi; c++) if (!GAP_CHARS.has(c)) return false;
|
|
7961
|
+
return true;
|
|
7962
|
+
});
|
|
7963
|
+
}
|
|
7852
7964
|
var Encoder = class {
|
|
7853
7965
|
code = [];
|
|
7854
7966
|
k = [];
|
|
@@ -7896,8 +8008,33 @@ var Encoder = class {
|
|
|
7896
8008
|
*/
|
|
7897
8009
|
commitFailureMemo = /* @__PURE__ */ new Map();
|
|
7898
8010
|
labels = void 0;
|
|
8011
|
+
/** The choice being encoded as written, for `OP_STRICT`'s tolerant child. */
|
|
8012
|
+
unfactoredChoice = void 0;
|
|
7899
8013
|
/** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
|
|
7900
8014
|
activeTrivia = void 0;
|
|
8015
|
+
/**
|
|
8016
|
+
* Is the trivia live at this row known? It is not in the body of an entry
|
|
8017
|
+
* that installs none of its own: that body runs under whatever trivia its
|
|
8018
|
+
* caller has (a compiled rule inside another grammar, `run({ trivia })`).
|
|
8019
|
+
* Every scope (`parser({ trivia })`, `noTrivia`, `token()`, a rule's install)
|
|
8020
|
+
* makes it known again.
|
|
8021
|
+
*/
|
|
8022
|
+
triviaKnown = true;
|
|
8023
|
+
/**
|
|
8024
|
+
* The trivia a gate's first set is derived under: the live table, `null` for a
|
|
8025
|
+
* scope known to have none, or `undefined` where it is not known.
|
|
8026
|
+
*/
|
|
8027
|
+
gateTrivia() {
|
|
8028
|
+
return this.activeTrivia ?? (this.triviaKnown ? null : void 0);
|
|
8029
|
+
}
|
|
8030
|
+
/**
|
|
8031
|
+
* Whether a gate may read a nullable pad through its non-empty matches
|
|
8032
|
+
* (`firstSetOf`'s `consuming`): only where the trivia that may follow the pad
|
|
8033
|
+
* is known. Elsewhere a gate reads first sets as 0.58.0 did.
|
|
8034
|
+
*/
|
|
8035
|
+
gateConsuming() {
|
|
8036
|
+
return this.activeTrivia !== void 0 || this.triviaKnown;
|
|
8037
|
+
}
|
|
7901
8038
|
classified = false;
|
|
7902
8039
|
scans = [];
|
|
7903
8040
|
/** Ambient `scanSkip` sets, pooled by the ARRAY's identity (stable per grammar). */
|
|
@@ -8024,10 +8161,12 @@ var Encoder = class {
|
|
|
8024
8161
|
const final = classifyFinalChoice(
|
|
8025
8162
|
node2.parsers,
|
|
8026
8163
|
this.refResolver(),
|
|
8027
|
-
node2.cleared ?
|
|
8164
|
+
node2.cleared ? null : this.gateTrivia(),
|
|
8165
|
+
false,
|
|
8166
|
+
node2.disjoint
|
|
8028
8167
|
);
|
|
8029
8168
|
const classes = final.firstSets.map((first, i) => final.nullable[i] ? -1 : this.charClass(first));
|
|
8030
|
-
const exclusive = final.exclusive && classes.every((cls) => cls >= 0);
|
|
8169
|
+
const exclusive = final.exclusive && classes.every((cls) => cls >= 0) && this.wideArms(node2.parsers, final.firstSets, node2.disjoint, node2.cleared ? null : this.gateTrivia(), node2.cleared ? void 0 : this.activeTrivia).length === 0;
|
|
8031
8170
|
words.push(LEX_NODE_CHOICE, node2.arms.length, exclusive ? 1 : 0, this.expected(node2.expected));
|
|
8032
8171
|
for (let i = 0; i < node2.arms.length; i++) {
|
|
8033
8172
|
words.push(classes[i], this.expected(node2.armExpected[i]));
|
|
@@ -8182,16 +8321,117 @@ var Encoder = class {
|
|
|
8182
8321
|
kIndex = /* @__PURE__ */ new Map();
|
|
8183
8322
|
ccIndex = /* @__PURE__ */ new Map();
|
|
8184
8323
|
fxIndex = /* @__PURE__ */ new Map();
|
|
8185
|
-
/** Memoized by combinator identity: a shared sub-combinator is ONE row. */
|
|
8186
|
-
memo = /* @__PURE__ */ new Map();
|
|
8187
8324
|
/**
|
|
8188
|
-
*
|
|
8189
|
-
*
|
|
8190
|
-
*
|
|
8191
|
-
*
|
|
8325
|
+
* Memoized by combinator identity AND the trivia scope it is encoded under
|
|
8326
|
+
* (`scopeKey`): a shared sub-combinator is ONE row per scope it runs in.
|
|
8327
|
+
*
|
|
8328
|
+
* A construct's rows depend on that scope. A first set derived through a
|
|
8329
|
+
* nullable term takes in the trivia that may follow it, a gap gate holds only
|
|
8330
|
+
* where no trivia runs, a routed gate reads what may follow its token, and a
|
|
8331
|
+
* cross-rule reference installs its rule's trivia only from a cleared region
|
|
8332
|
+
* (`scopedRef`). One memo slot per combinator froze the FIRST scope it was
|
|
8333
|
+
* reached under onto every later one: a rule body encoded as an entry with no
|
|
8334
|
+
* trivia, then run under a caller's comment trivia, gated its repeats as if no
|
|
8335
|
+
* comment could come between their terms.
|
|
8192
8336
|
*/
|
|
8193
|
-
|
|
8337
|
+
memo = /* @__PURE__ */ new Map();
|
|
8194
8338
|
pending = /* @__PURE__ */ new Map();
|
|
8339
|
+
triviaSignatures = /* @__PURE__ */ new Map();
|
|
8340
|
+
/**
|
|
8341
|
+
* What of the live trivia an encoding can depend on: none, or its first set.
|
|
8342
|
+
* Every derivation reads trivia only through `firstSetOf(trivia)` or whether it
|
|
8343
|
+
* is live, so two scopes whose trivia opens on the same characters encode the
|
|
8344
|
+
* same rows and share them. A construct that reads no scope (`readsScope`)
|
|
8345
|
+
* has one encoding.
|
|
8346
|
+
*/
|
|
8347
|
+
scopeKey(p) {
|
|
8348
|
+
const t = this.activeTrivia;
|
|
8349
|
+
if (!this.readsScope(p)) return "";
|
|
8350
|
+
if (t === void 0) return this.triviaKnown ? "" : "?";
|
|
8351
|
+
let sig = this.triviaSignatures.get(t);
|
|
8352
|
+
if (sig === void 0) {
|
|
8353
|
+
sig = `t${JSON.stringify(firstSetOf(t, /* @__PURE__ */ new Set(), this.refResolver()))}`;
|
|
8354
|
+
this.triviaSignatures.set(t, sig);
|
|
8355
|
+
}
|
|
8356
|
+
return sig;
|
|
8357
|
+
}
|
|
8358
|
+
readsScopeMemo = /* @__PURE__ */ new Map();
|
|
8359
|
+
/**
|
|
8360
|
+
* Can `p`'s rows depend on the trivia scope it is encoded under? No for a
|
|
8361
|
+
* terminal, a scope of its own (`parser({ trivia })`, `noTrivia`, `token()`),
|
|
8362
|
+
* and a wrapper over a construct that reads none; yes wherever a first set, a gate or
|
|
8363
|
+
* a reference's install is derived with the scope: a sequence with a nullable
|
|
8364
|
+
* term before another (the trivia between them), a routed arm (the trivia after
|
|
8365
|
+
* its token), a reference that installs its rule's trivia from a cleared
|
|
8366
|
+
* region, and anything not modelled here — a cycle included.
|
|
8367
|
+
*/
|
|
8368
|
+
readsScope(p) {
|
|
8369
|
+
const hit = this.readsScopeMemo.get(p);
|
|
8370
|
+
if (hit !== void 0) return hit;
|
|
8371
|
+
this.readsScopeMemo.set(p, true);
|
|
8372
|
+
const d = p._def;
|
|
8373
|
+
const rr = this.refResolver();
|
|
8374
|
+
let out;
|
|
8375
|
+
switch (d.tag) {
|
|
8376
|
+
case "literal":
|
|
8377
|
+
case "regex":
|
|
8378
|
+
case "keywords":
|
|
8379
|
+
case "token":
|
|
8380
|
+
out = false;
|
|
8381
|
+
break;
|
|
8382
|
+
// `routed()` encodes its fallback under the scope that reaches it.
|
|
8383
|
+
case "routed":
|
|
8384
|
+
out = d.fallback !== void 0 && this.readsScope(d.fallback);
|
|
8385
|
+
break;
|
|
8386
|
+
case "grammar":
|
|
8387
|
+
out = d.clearTrivia !== true && d.triviaParser === void 0 && this.readsScope(d.parser);
|
|
8388
|
+
break;
|
|
8389
|
+
case "node":
|
|
8390
|
+
case "label":
|
|
8391
|
+
case "leaf":
|
|
8392
|
+
case "transform":
|
|
8393
|
+
case "attempt":
|
|
8394
|
+
case "expect":
|
|
8395
|
+
case "not":
|
|
8396
|
+
case "peek":
|
|
8397
|
+
case "optional":
|
|
8398
|
+
case "many":
|
|
8399
|
+
case "oneOrMore":
|
|
8400
|
+
case "field":
|
|
8401
|
+
out = this.readsScope(d.parser);
|
|
8402
|
+
break;
|
|
8403
|
+
case "sepBy":
|
|
8404
|
+
out = this.readsScope(d.parser) || this.readsScope(d.separator);
|
|
8405
|
+
break;
|
|
8406
|
+
case "choice":
|
|
8407
|
+
out = d.parsers.some((a) => this.readsScope(a));
|
|
8408
|
+
break;
|
|
8409
|
+
case "dispatch":
|
|
8410
|
+
out = this.readsScope(d.selector) || d.cases.some((c) => this.readsScope(c.parser)) || (d.matchers?.some((m) => this.readsScope(m.parser)) ?? false) || d.otherwise !== void 0 && this.readsScope(d.otherwise);
|
|
8411
|
+
break;
|
|
8412
|
+
case "sequence": {
|
|
8413
|
+
const ps = d.parsers;
|
|
8414
|
+
out = ps.some((t) => this.readsScope(t)) || ps[0] !== void 0 && (ps[0]._def.tag === "routed" || ps[0]._def.tag === "regex" && isGap(ps[0])) || ps.some((t, i) => i + 1 < ps.length && matchesEmpty(t, /* @__PURE__ */ new Set(), rr));
|
|
8415
|
+
break;
|
|
8416
|
+
}
|
|
8417
|
+
case "lazy": {
|
|
8418
|
+
let target = winnerForRef(p, rr);
|
|
8419
|
+
if (target === void 0) {
|
|
8420
|
+
try {
|
|
8421
|
+
target = d.thunk();
|
|
8422
|
+
} catch {
|
|
8423
|
+
target = void 0;
|
|
8424
|
+
}
|
|
8425
|
+
}
|
|
8426
|
+
out = target === void 0 || triviaThroughRef(p, target, null) !== null || this.readsScope(target);
|
|
8427
|
+
break;
|
|
8428
|
+
}
|
|
8429
|
+
default:
|
|
8430
|
+
out = true;
|
|
8431
|
+
}
|
|
8432
|
+
this.readsScopeMemo.set(p, out);
|
|
8433
|
+
return out;
|
|
8434
|
+
}
|
|
8195
8435
|
settings;
|
|
8196
8436
|
/** Resolved once, HERE, at table-build time — never consulted at run time. */
|
|
8197
8437
|
track;
|
|
@@ -8219,7 +8459,7 @@ var Encoder = class {
|
|
|
8219
8459
|
let fs = { kind: "empty" };
|
|
8220
8460
|
const rr = this.refResolver();
|
|
8221
8461
|
for (let j = i + 1; j < parsers.length; j++) {
|
|
8222
|
-
fs = union(fs, firstSetOf(parsers[j], /* @__PURE__ */ new Set(), rr,
|
|
8462
|
+
fs = union(fs, firstSetOf(parsers[j], /* @__PURE__ */ new Set(), rr, void 0, false));
|
|
8223
8463
|
}
|
|
8224
8464
|
return this.charClass(fs);
|
|
8225
8465
|
}
|
|
@@ -8387,7 +8627,7 @@ var Encoder = class {
|
|
|
8387
8627
|
if (op === OP_GATE || op === OP_LIT || op === OP_LIT_CI || op === OP_LIT_TRACK || op === OP_LIT_CI_TRACK || op === OP_RX || op === OP_RX_TRACK) return child;
|
|
8388
8628
|
const rr = this.refResolver();
|
|
8389
8629
|
if (matchesEmpty(p, /* @__PURE__ */ new Set(), rr)) return child;
|
|
8390
|
-
const cls = this.charClass(firstSetOf(p, /* @__PURE__ */ new Set(), rr, this.activeTrivia));
|
|
8630
|
+
const cls = this.charClass(firstSetOf(p, /* @__PURE__ */ new Set(), rr, this.activeTrivia, false));
|
|
8391
8631
|
if (cls < 0) return child;
|
|
8392
8632
|
const e = deriveExpected(p);
|
|
8393
8633
|
return this.emit(OP_GATE, cls, child, this.expected(e.length > 0 ? e : [p._tag]));
|
|
@@ -8413,9 +8653,27 @@ var Encoder = class {
|
|
|
8413
8653
|
* `{`, `Call` at `}`). The resolved set is the one a choice arm's gate uses,
|
|
8414
8654
|
* over the final merged map.
|
|
8415
8655
|
*/
|
|
8416
|
-
|
|
8656
|
+
/**
|
|
8657
|
+
* The arms whose first set under `gateTrivia()` is wider than under the
|
|
8658
|
+
* active trivia alone — a reference's installed trivia read through from a
|
|
8659
|
+
* region with none. Empty for construction-set (disjoint) choices, whose
|
|
8660
|
+
* sets do not depend on trivia.
|
|
8661
|
+
*/
|
|
8662
|
+
wideArms(arms, wide, constructionSets, wideTrivia = this.gateTrivia(), base = this.activeTrivia) {
|
|
8663
|
+
if (constructionSets || wideTrivia === base) return [];
|
|
8664
|
+
const narrow = classifyFinalChoice(arms, this.refResolver(), base, false, false).firstSets;
|
|
8665
|
+
const out = [];
|
|
8666
|
+
for (let i = 0; i < arms.length; i++) {
|
|
8667
|
+
if (this.charClass(wide[i]) !== this.charClass(narrow[i])) out.push(i);
|
|
8668
|
+
}
|
|
8669
|
+
return out;
|
|
8670
|
+
}
|
|
8671
|
+
gateFirstSet(p, guarded, narrowed) {
|
|
8417
8672
|
const cached = p._meta.firstSet;
|
|
8418
|
-
|
|
8673
|
+
if (p._def.tag !== "lazy" && cached.kind !== "any") return cached;
|
|
8674
|
+
const rr = this.refResolver();
|
|
8675
|
+
if (guarded) return firstSetOf(p, /* @__PURE__ */ new Set(), rr, void 0, false);
|
|
8676
|
+
return firstSetOf(p, /* @__PURE__ */ new Set(), rr, this.gateTrivia(), narrowed && this.gateConsuming());
|
|
8419
8677
|
}
|
|
8420
8678
|
/**
|
|
8421
8679
|
* Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
|
|
@@ -8447,6 +8705,135 @@ var Encoder = class {
|
|
|
8447
8705
|
for (const w of words) this.code.push(w);
|
|
8448
8706
|
return ip;
|
|
8449
8707
|
}
|
|
8708
|
+
/**
|
|
8709
|
+
* An optional repeat item tests the item's class before it runs it (`OP_REP`
|
|
8710
|
+
* ip+7), wherever the item's own first-set gate would also run. So a sequence
|
|
8711
|
+
* item whose first term is a gate on that same class gets its own copy of the
|
|
8712
|
+
* sequence row with the gate's child as that term: the test runs once. The
|
|
8713
|
+
* shared row is left as it is for its other references.
|
|
8714
|
+
*/
|
|
8715
|
+
withoutLeadGate(seq, cls) {
|
|
8716
|
+
const op = this.code[seq];
|
|
8717
|
+
if (op !== OP_SEQ && op !== OP_SEQV) return seq;
|
|
8718
|
+
const first = this.code[seq + 2];
|
|
8719
|
+
if (this.code[first] !== OP_GATE || this.code[first + 1] !== cls) return seq;
|
|
8720
|
+
const n = this.code[seq + 1];
|
|
8721
|
+
const width = 1 + 2 * n;
|
|
8722
|
+
const head = this.emitHead(op, width);
|
|
8723
|
+
for (let i = 1; i <= width; i++) this.code[head + i] = this.code[seq + i];
|
|
8724
|
+
this.code[head + 2] = this.code[first + 2];
|
|
8725
|
+
return head;
|
|
8726
|
+
}
|
|
8727
|
+
/**
|
|
8728
|
+
* An optional repeat item that opens with a GAP — a regex that may match
|
|
8729
|
+
* empty, or one that starts only with whitespace or a comment's `/` — and
|
|
8730
|
+
* then a term with a finite first set gets an `OP_GAPGATE` row
|
|
8731
|
+
* (`gap-gate.ts`): the repeat reads the gap once, ends where the character
|
|
8732
|
+
* after it opens neither that term nor an arm without the gap, and hands the
|
|
8733
|
+
* gap's end to the regex row. Anything the walk cannot prove keeps the item as
|
|
8734
|
+
* written.
|
|
8735
|
+
*/
|
|
8736
|
+
gapGated(item, ip) {
|
|
8737
|
+
if (this.activeTrivia === void 0 && !this.triviaKnown) return ip;
|
|
8738
|
+
const lead2 = this.gapLead(item, this.activeTrivia, 0);
|
|
8739
|
+
if (lead2 === void 0) return ip;
|
|
8740
|
+
const cls = this.charClass(lead2.follow);
|
|
8741
|
+
if (cls < 0) return ip;
|
|
8742
|
+
const other = lead2.other.kind === "empty" ? -1 : this.charClass(lead2.other);
|
|
8743
|
+
if (lead2.other.kind !== "empty" && other < 0) return ip;
|
|
8744
|
+
const p = this.node(lead2.p).ip;
|
|
8745
|
+
if (this.code[p] !== OP_RX && this.code[p] !== OP_RX_TRACK) return ip;
|
|
8746
|
+
return this.emit(OP_GAPGATE, ip, p, cls, other);
|
|
8747
|
+
}
|
|
8748
|
+
/**
|
|
8749
|
+
* The gap an item opens with: the regex `p`, the first set `follow` of what
|
|
8750
|
+
* must come straight after it, and the first set `other` of choice arms that
|
|
8751
|
+
* do not open with `p`. Only through wrappers that consume nothing before
|
|
8752
|
+
* their body, a sequence's first term, and a choice's arms; the gap must sit
|
|
8753
|
+
* in a sequence with no trivia between its terms.
|
|
8754
|
+
*/
|
|
8755
|
+
gapLead(c, trivia2, depth) {
|
|
8756
|
+
if (depth > 24) return void 0;
|
|
8757
|
+
const rr = this.refResolver();
|
|
8758
|
+
const d = c._def;
|
|
8759
|
+
switch (d.tag) {
|
|
8760
|
+
case "lazy": {
|
|
8761
|
+
let target = winnerForRef(c, rr);
|
|
8762
|
+
if (target === void 0) {
|
|
8763
|
+
try {
|
|
8764
|
+
target = d.thunk();
|
|
8765
|
+
} catch {
|
|
8766
|
+
return void 0;
|
|
8767
|
+
}
|
|
8768
|
+
}
|
|
8769
|
+
return this.gapLead(target, triviaThroughRef(c, target, trivia2), depth + 1);
|
|
8770
|
+
}
|
|
8771
|
+
case "node":
|
|
8772
|
+
case "leaf":
|
|
8773
|
+
case "label":
|
|
8774
|
+
case "attempt":
|
|
8775
|
+
return this.gapLead(d.parser, trivia2, depth + 1);
|
|
8776
|
+
case "field":
|
|
8777
|
+
return d.leadingTrivia === true ? void 0 : this.gapLead(d.parser, trivia2, depth + 1);
|
|
8778
|
+
case "grammar":
|
|
8779
|
+
return this.gapLead(d.parser, d.clearTrivia === true ? null : d.triviaParser ?? trivia2, depth + 1);
|
|
8780
|
+
case "sequence": {
|
|
8781
|
+
const [first, ...rest] = d.parsers;
|
|
8782
|
+
if (first === void 0) return void 0;
|
|
8783
|
+
if (first._def.tag !== "regex" || !isGap(first)) {
|
|
8784
|
+
return this.gapLead(first, trivia2, depth + 1);
|
|
8785
|
+
}
|
|
8786
|
+
if (trivia2 !== void 0 && trivia2 !== null || rest.length === 0) return void 0;
|
|
8787
|
+
let follow = empty();
|
|
8788
|
+
let closed = false;
|
|
8789
|
+
for (const t of rest) {
|
|
8790
|
+
const fs = firstSetOf(t, /* @__PURE__ */ new Set(), rr, null);
|
|
8791
|
+
if (fs.kind === "any") return void 0;
|
|
8792
|
+
follow = union(follow, fs);
|
|
8793
|
+
if (!matchesEmpty(t, /* @__PURE__ */ new Set(), rr)) {
|
|
8794
|
+
closed = true;
|
|
8795
|
+
break;
|
|
8796
|
+
}
|
|
8797
|
+
}
|
|
8798
|
+
return closed ? { p: first, follow, other: empty() } : void 0;
|
|
8799
|
+
}
|
|
8800
|
+
case "choice": {
|
|
8801
|
+
let p;
|
|
8802
|
+
let follow = empty();
|
|
8803
|
+
let other = empty();
|
|
8804
|
+
for (const arm of d.parsers) {
|
|
8805
|
+
const lead2 = this.gapLead(arm, trivia2, depth + 1);
|
|
8806
|
+
if (lead2 !== void 0 && (p === void 0 || lead2.p === p)) {
|
|
8807
|
+
p = lead2.p;
|
|
8808
|
+
follow = union(follow, lead2.follow);
|
|
8809
|
+
other = union(other, lead2.other);
|
|
8810
|
+
continue;
|
|
8811
|
+
}
|
|
8812
|
+
if (matchesEmpty(arm, /* @__PURE__ */ new Set(), rr)) return void 0;
|
|
8813
|
+
const fs = firstSetOf(arm, /* @__PURE__ */ new Set(), rr, trivia2 ?? null);
|
|
8814
|
+
if (fs.kind === "any") return void 0;
|
|
8815
|
+
other = union(other, fs);
|
|
8816
|
+
}
|
|
8817
|
+
return p === void 0 ? void 0 : { p, follow, other };
|
|
8818
|
+
}
|
|
8819
|
+
default:
|
|
8820
|
+
return void 0;
|
|
8821
|
+
}
|
|
8822
|
+
}
|
|
8823
|
+
/**
|
|
8824
|
+
* The class a strict list may end on — a character its separator `p` (row
|
|
8825
|
+
* `ip`) cannot start — without entering the separator, or −1.
|
|
8826
|
+
*
|
|
8827
|
+
* The test runs before every separator, to save the one that fails at the
|
|
8828
|
+
* list's end, so it is laid down only where entering the separator costs more
|
|
8829
|
+
* than the test: not on a terminal row, which is itself one character test.
|
|
8830
|
+
*/
|
|
8831
|
+
sepGate(p, ip) {
|
|
8832
|
+
const op = this.code[ip];
|
|
8833
|
+
if (op === OP_LIT || op === OP_LIT_CI || op === OP_RX || op === OP_LIT_TRACK || op === OP_RX_TRACK || op === OP_LIT_CI_TRACK) return -1;
|
|
8834
|
+
if (matchesEmpty(p, /* @__PURE__ */ new Set(), this.refResolver())) return -1;
|
|
8835
|
+
return this.charClass(firstSetOf(p, /* @__PURE__ */ new Set(), this.refResolver(), this.gateTrivia(), this.gateConsuming()));
|
|
8836
|
+
}
|
|
8450
8837
|
/** Reserve `n` operand slots to patch once children are laid out. */
|
|
8451
8838
|
emitHead(op, n) {
|
|
8452
8839
|
const ip = this.code.length;
|
|
@@ -8490,8 +8877,10 @@ var Encoder = class {
|
|
|
8490
8877
|
}
|
|
8491
8878
|
encodeRule(name, p) {
|
|
8492
8879
|
this.activeTrivia = p._meta.grammarTrivia;
|
|
8880
|
+
this.triviaKnown = p._meta.grammarTrivia !== void 0;
|
|
8493
8881
|
const body = this.node(p).ip;
|
|
8494
8882
|
this.activeTrivia = void 0;
|
|
8883
|
+
this.triviaKnown = true;
|
|
8495
8884
|
const gss = p._meta.grammarScanSkip;
|
|
8496
8885
|
this.scanSkipOf.push(gss === void 0 ? -1 : this.scanSkipSlot(gss));
|
|
8497
8886
|
const amb = p._meta.grammarTrivia;
|
|
@@ -8537,11 +8926,15 @@ var Encoder = class {
|
|
|
8537
8926
|
* silently produced the ONE keyword `bc`.
|
|
8538
8927
|
*/
|
|
8539
8928
|
scopedRef(p, target) {
|
|
8929
|
+
const runsUnder = triviaThroughRef(p, target, this.activeTrivia);
|
|
8930
|
+
if (this.activeTrivia !== void 0 || runsUnder === void 0 || runsUnder === null) return this.node(target).ip;
|
|
8931
|
+
const savedKnown = this.triviaKnown;
|
|
8932
|
+
this.activeTrivia = runsUnder;
|
|
8933
|
+
this.triviaKnown = true;
|
|
8540
8934
|
const ip = this.node(target).ip;
|
|
8541
|
-
|
|
8542
|
-
|
|
8543
|
-
|
|
8544
|
-
return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), ip);
|
|
8935
|
+
this.activeTrivia = void 0;
|
|
8936
|
+
this.triviaKnown = savedKnown;
|
|
8937
|
+
return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(runsUnder), ip);
|
|
8545
8938
|
}
|
|
8546
8939
|
/**
|
|
8547
8940
|
* The `OP_RGATE` operands of a choice arm that opens with `routed()`, or
|
|
@@ -8582,38 +8975,43 @@ var Encoder = class {
|
|
|
8582
8975
|
if (matchesEmpty(next, /* @__PURE__ */ new Set(), rr) || mayCommitFailure(next, rr, this.commitFailureMemo)) return void 0;
|
|
8583
8976
|
const nextDef = next._def;
|
|
8584
8977
|
if (nextDef.tag !== "literal" && nextDef.tag !== "regex" && nextDef.tag !== "keywords" && nextDef.tag !== "label") return void 0;
|
|
8585
|
-
|
|
8978
|
+
if (boundary === void 0 && !this.triviaKnown) return void 0;
|
|
8979
|
+
const first = firstSetOf(next, /* @__PURE__ */ new Set(), rr, boundary ?? null);
|
|
8586
8980
|
const cls = this.charClass(boundary === void 0 ? first : union(first, firstSetOf(boundary, /* @__PURE__ */ new Set(), rr)));
|
|
8587
8981
|
if (cls < 0) return void 0;
|
|
8588
|
-
const
|
|
8589
|
-
|
|
8982
|
+
const fx = this.expected(nextDef.tag === "label" ? deriveExpected(next) : directTerminalFailureExpected(nextDef));
|
|
8983
|
+
const two = firstTwo(next);
|
|
8984
|
+
if (two === void 0) return { cls, fx };
|
|
8985
|
+
if (boundary !== void 0 && intersects(two.first, firstSetOf(boundary, /* @__PURE__ */ new Set(), rr))) return { cls, fx };
|
|
8986
|
+
const a = this.charClass(two.first);
|
|
8987
|
+
const b = this.charClass(two.second);
|
|
8988
|
+
return a < 0 || b < 0 ? { cls, fx } : { cls, fx, two: [a, b] };
|
|
8590
8989
|
}
|
|
8591
8990
|
node(p) {
|
|
8592
|
-
const
|
|
8593
|
-
|
|
8594
|
-
const
|
|
8595
|
-
const hit = lazyRef ? refMemo.get(p)?.get(scopeKey) : this.memo.get(p);
|
|
8991
|
+
const key = this.scopeKey(p);
|
|
8992
|
+
let byScope = this.memo.get(p);
|
|
8993
|
+
const hit = byScope?.get(key);
|
|
8596
8994
|
if (hit !== void 0) return { ip: hit };
|
|
8597
|
-
|
|
8995
|
+
let inFlightByScope = this.pending.get(p);
|
|
8996
|
+
const inFlight = inFlightByScope?.get(key);
|
|
8598
8997
|
if (inFlight !== void 0) {
|
|
8599
8998
|
const ip2 = this.emitHead(OP_RULE, 1);
|
|
8600
8999
|
inFlight.push(ip2 + 1);
|
|
8601
9000
|
return { ip: ip2 };
|
|
8602
9001
|
}
|
|
8603
9002
|
const patches = [];
|
|
8604
|
-
|
|
9003
|
+
if (inFlightByScope === void 0) {
|
|
9004
|
+
inFlightByScope = /* @__PURE__ */ new Map();
|
|
9005
|
+
this.pending.set(p, inFlightByScope);
|
|
9006
|
+
}
|
|
9007
|
+
inFlightByScope.set(key, patches);
|
|
8605
9008
|
const ip = this.covWrap(this.encodeDef(p), this.plan?.rules.get(p), 0);
|
|
8606
|
-
|
|
8607
|
-
if (
|
|
8608
|
-
|
|
8609
|
-
|
|
8610
|
-
byScope = /* @__PURE__ */ new Map();
|
|
8611
|
-
refMemo.set(p, byScope);
|
|
8612
|
-
}
|
|
8613
|
-
byScope.set(scopeKey, ip);
|
|
8614
|
-
} else {
|
|
8615
|
-
this.memo.set(p, ip);
|
|
9009
|
+
inFlightByScope.delete(key);
|
|
9010
|
+
if (byScope === void 0) {
|
|
9011
|
+
byScope = /* @__PURE__ */ new Map();
|
|
9012
|
+
this.memo.set(p, byScope);
|
|
8616
9013
|
}
|
|
9014
|
+
byScope.set(key, ip);
|
|
8617
9015
|
for (const slot of patches) {
|
|
8618
9016
|
if (slot - 1 === ip) {
|
|
8619
9017
|
const rule = p._ruleName;
|
|
@@ -8711,8 +9109,19 @@ var Encoder = class {
|
|
|
8711
9109
|
}
|
|
8712
9110
|
case "choice": {
|
|
8713
9111
|
if (this.plan === void 0) {
|
|
8714
|
-
const
|
|
8715
|
-
if (
|
|
9112
|
+
const shared = factorSharedEnds(d);
|
|
9113
|
+
if (shared !== void 0) return this.node(shared).ip;
|
|
9114
|
+
if (this.unfactoredChoice !== p) {
|
|
9115
|
+
const prefix = factorPrefixArms(d);
|
|
9116
|
+
if (prefix !== void 0) {
|
|
9117
|
+
const strict = this.node(prefix).ip;
|
|
9118
|
+
const saved = this.unfactoredChoice;
|
|
9119
|
+
this.unfactoredChoice = p;
|
|
9120
|
+
const tolerant = this.encodeDef(p);
|
|
9121
|
+
this.unfactoredChoice = saved;
|
|
9122
|
+
return this.emit(OP_STRICT, strict, tolerant);
|
|
9123
|
+
}
|
|
9124
|
+
}
|
|
8716
9125
|
}
|
|
8717
9126
|
if (d.strategy.tag === "greedyClassify") {
|
|
8718
9127
|
const superIndex = d.strategy.superIndex;
|
|
@@ -8741,18 +9150,20 @@ var Encoder = class {
|
|
|
8741
9150
|
const plain = (checks === null || checks === void 0 || checks.length === 0) && (gate2 === null || gate2 === void 0);
|
|
8742
9151
|
const routedGate = plain ? this.routedArmGate(c) : void 0;
|
|
8743
9152
|
const body = this.node(c).ip;
|
|
8744
|
-
const inner = routedGate === void 0 ? body : this.emit(OP_RGATE, routedGate.cls, body, routedGate.fx);
|
|
9153
|
+
const inner = routedGate === void 0 ? body : routedGate.two === void 0 ? this.emit(OP_RGATE, routedGate.cls, body, routedGate.fx) : this.emit(OP_RGATE2, routedGate.cls, body, routedGate.fx, routedGate.two[0], routedGate.two[1]);
|
|
8745
9154
|
const ip = checks === null || checks === void 0 || checks.length === 0 ? inner : this.reject(inner, checks);
|
|
8746
9155
|
const gated = gate2 === null || gate2 === void 0 ? ip : this.emit(OP_ARMGATE, this.fn(gate2, d.gateSrcs?.[src] ?? null), ip, this.expected(deriveExpected(c)));
|
|
8747
9156
|
return this.covWrap(gated, armCovIds?.[src], 1);
|
|
8748
9157
|
});
|
|
8749
9158
|
const rr = this.refResolver();
|
|
8750
|
-
const
|
|
9159
|
+
const constructionSets = d.disjoint && !factoredChoices.has(p);
|
|
9160
|
+
const finalChoice = classifyFinalChoice(arms, rr, this.gateTrivia(), false, constructionSets);
|
|
9161
|
+
const wideArms = this.wideArms(arms, finalChoice.firstSets, constructionSets);
|
|
8751
9162
|
const transactionalFirst = arms.map((arm, i) => {
|
|
8752
9163
|
if (!finalChoice.nullable[i]) return void 0;
|
|
8753
9164
|
const def = arm._def;
|
|
8754
9165
|
if (def.tag !== "attempt" || matchesEmpty(def.parser, /* @__PURE__ */ new Set(), rr)) return void 0;
|
|
8755
|
-
return firstSetOf(def.parser, /* @__PURE__ */ new Set(), rr, this.activeTrivia);
|
|
9166
|
+
return firstSetOf(def.parser, /* @__PURE__ */ new Set(), rr, this.activeTrivia, false);
|
|
8756
9167
|
});
|
|
8757
9168
|
const gateFirst = finalChoice.firstSets.map((first, i) => transactionalFirst[i] ?? first);
|
|
8758
9169
|
const classes = gateFirst.map((first, i) => finalChoice.nullable[i] && transactionalFirst[i] === void 0 ? -1 : this.charClass(first));
|
|
@@ -8770,6 +9181,9 @@ var Encoder = class {
|
|
|
8770
9181
|
if (transactionalFirst[i] !== void 0) classes[i] = -1;
|
|
8771
9182
|
}
|
|
8772
9183
|
}
|
|
9184
|
+
if (wideArms.length > 0 && dispatchIsExclusive(classes, this.cc)) {
|
|
9185
|
+
for (const i of wideArms) classes[i] = -1;
|
|
9186
|
+
}
|
|
8773
9187
|
if (d.gates.some((g) => g !== null && g !== void 0) && !dispatchIsExclusive(classes, this.cc)) {
|
|
8774
9188
|
for (let k = 0; k < classes.length; k++) {
|
|
8775
9189
|
const gate2 = d.gates[order[k]];
|
|
@@ -8803,27 +9217,34 @@ var Encoder = class {
|
|
|
8803
9217
|
}
|
|
8804
9218
|
case "many":
|
|
8805
9219
|
case "oneOrMore": {
|
|
8806
|
-
const child = this.node(d.parser).ip;
|
|
8807
9220
|
const rr = this.refResolver();
|
|
8808
|
-
const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.charClass(
|
|
9221
|
+
const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.charClass(this.gateFirstSet(d.parser, d.guarded === true, true));
|
|
8809
9222
|
const op = d.valueUnused ? OP_REPV : OP_REP;
|
|
8810
9223
|
const min = d.tag === "many" ? 0 : d.min;
|
|
9224
|
+
const item = min === 0 && itemClass >= 0 ? this.withoutLeadGate(this.node(d.parser).ip, itemClass) : this.node(d.parser).ip;
|
|
9225
|
+
const child = min === 0 && itemClass >= 0 ? this.gapGated(d.parser, item) : item;
|
|
8811
9226
|
return this.emit(op, child, min, d.max ?? -1, -1, 0, this.expected(deriveExpected(d.parser)), itemClass);
|
|
8812
9227
|
}
|
|
8813
9228
|
case "sepBy": {
|
|
8814
9229
|
const child = this.node(d.parser).ip;
|
|
8815
9230
|
const sep = this.node(d.separator).ip;
|
|
8816
|
-
const
|
|
8817
|
-
|
|
8818
|
-
|
|
9231
|
+
const gate2 = this.sepGate(d.separator, sep);
|
|
9232
|
+
const itemSet = deriveExpected(d.parser);
|
|
9233
|
+
const itemFx = this.expected(itemSet.length > 0 ? itemSet : [d.parser._tag]);
|
|
9234
|
+
const flags = (d.trailing === "allow" ? 1 : 0) | (d.keepSeparators === true ? 2 : 0) | (d.min >= 1 ? 4 : 0) | (gate2 >= 0 ? 8 : 0) | (itemSet.length === 0 ? 16 : 0);
|
|
9235
|
+
const ops = [
|
|
8819
9236
|
child,
|
|
8820
9237
|
d.min,
|
|
8821
9238
|
d.max ?? -1,
|
|
8822
9239
|
sep,
|
|
8823
9240
|
flags,
|
|
8824
|
-
|
|
8825
|
-
|
|
8826
|
-
|
|
9241
|
+
itemFx,
|
|
9242
|
+
// As 0.58.0: the interpreter resyncs on the separator itself
|
|
9243
|
+
// (`orSentinel`), which runs under the live trivia.
|
|
9244
|
+
this.charClass(firstSetOf(d.separator, /* @__PURE__ */ new Set(), this.refResolver(), this.activeTrivia, false))
|
|
9245
|
+
];
|
|
9246
|
+
if (gate2 >= 0) ops.push(gate2);
|
|
9247
|
+
return this.emit(OP_REP, ...ops);
|
|
8827
9248
|
}
|
|
8828
9249
|
case "optional": {
|
|
8829
9250
|
const head = this.emit(OP_OPT, this.lookaheadGate(d.parser, this.node(d.parser).ip));
|
|
@@ -8832,7 +9253,7 @@ var Encoder = class {
|
|
|
8832
9253
|
}
|
|
8833
9254
|
case "transform": {
|
|
8834
9255
|
const inner = d.parser._def;
|
|
8835
|
-
if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
|
|
9256
|
+
if (inner.tag === "sequence" && !this.memo.get(d.parser)?.has(this.scopeKey(d.parser)) && !this.pending.get(d.parser)?.has(this.scopeKey(d.parser))) {
|
|
8836
9257
|
const kids = inner.parsers.map((c) => this.node(c).ip);
|
|
8837
9258
|
const head = this.emitHead(OP_SEQX, 2 + 2 * kids.length);
|
|
8838
9259
|
const projection = directArrayProjection(d.fn, d.fnSrc, kids.length);
|
|
@@ -8873,7 +9294,7 @@ var Encoder = class {
|
|
|
8873
9294
|
d.tags === void 0 ? -1 : this.constant(d.tags)
|
|
8874
9295
|
);
|
|
8875
9296
|
if (matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return body;
|
|
8876
|
-
const fs = this.gateFirstSet(d.parser);
|
|
9297
|
+
const fs = this.gateFirstSet(d.parser, d.guarded === true, false);
|
|
8877
9298
|
if (fs.kind === "any") return body;
|
|
8878
9299
|
const cls = this.charClass(fs);
|
|
8879
9300
|
if (cls < 0) return body;
|
|
@@ -8881,7 +9302,14 @@ var Encoder = class {
|
|
|
8881
9302
|
return this.emit(OP_GATE, cls, body, this.expected(e.length > 0 ? e : [d.parser._tag]));
|
|
8882
9303
|
}
|
|
8883
9304
|
case "token": {
|
|
8884
|
-
|
|
9305
|
+
const saved = this.activeTrivia;
|
|
9306
|
+
const savedKnown = this.triviaKnown;
|
|
9307
|
+
this.activeTrivia = void 0;
|
|
9308
|
+
this.triviaKnown = true;
|
|
9309
|
+
const body = this.node(d.parser).ip;
|
|
9310
|
+
this.activeTrivia = saved;
|
|
9311
|
+
this.triviaKnown = savedKnown;
|
|
9312
|
+
return this.emit(OP_TOKEN, body);
|
|
8885
9313
|
}
|
|
8886
9314
|
case "routed":
|
|
8887
9315
|
return this.emit(OP_ROUTED, d.fallback === void 0 ? -1 : this.node(d.fallback).ip);
|
|
@@ -8937,7 +9365,7 @@ var Encoder = class {
|
|
|
8937
9365
|
this.code[head + 2] = dspIdx;
|
|
8938
9366
|
this.code[head + 3] = other;
|
|
8939
9367
|
const otherRouted = d.otherwise === void 0 ? false : branchUsesRouted({ parser: d.otherwise, usesRouted: d.otherwiseUsesRouted === true });
|
|
8940
|
-
this.code[head + 4] = otherRouted ? 1 : 0;
|
|
9368
|
+
this.code[head + 4] = (otherRouted ? 1 : 0) | (d.otherwiseCommit === false ? 2 : 0);
|
|
8941
9369
|
this.code[head + 5] = arms.length;
|
|
8942
9370
|
for (let i = 0; i < arms.length; i++) this.code[head + 6 + i] = arms[i];
|
|
8943
9371
|
return head;
|
|
@@ -8992,7 +9420,7 @@ var Encoder = class {
|
|
|
8992
9420
|
case "attempt": {
|
|
8993
9421
|
const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip, d.contain === true ? 1 : 0);
|
|
8994
9422
|
if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
|
|
8995
|
-
const fs = this.gateFirstSet(d.parser);
|
|
9423
|
+
const fs = this.gateFirstSet(d.parser, d.guarded === true, false);
|
|
8996
9424
|
if (fs.kind === "any" || matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return inner;
|
|
8997
9425
|
const cls = this.charClass(fs);
|
|
8998
9426
|
if (cls < 0) return inner;
|
|
@@ -9018,10 +9446,17 @@ var Encoder = class {
|
|
|
9018
9446
|
const op = cap ? OP_SCOPE_CAP : OP_SCOPE;
|
|
9019
9447
|
const flags = (d.rootCapture === "opaque" ? 1 : 0) | (d.triviaParser !== void 0 && d.triviaParser._meta.rootTriviaClassified !== true && d.rootCapture !== "opaque" ? 2 : 0);
|
|
9020
9448
|
const savedTrivia = this.activeTrivia;
|
|
9021
|
-
|
|
9022
|
-
|
|
9449
|
+
const savedKnown = this.triviaKnown;
|
|
9450
|
+
if (d.clearTrivia === true) {
|
|
9451
|
+
this.activeTrivia = void 0;
|
|
9452
|
+
this.triviaKnown = true;
|
|
9453
|
+
} else if (d.triviaParser !== void 0) {
|
|
9454
|
+
this.activeTrivia = d.triviaParser;
|
|
9455
|
+
this.triviaKnown = true;
|
|
9456
|
+
}
|
|
9023
9457
|
const bodyIp = this.node(d.parser).ip;
|
|
9024
9458
|
this.activeTrivia = savedTrivia;
|
|
9459
|
+
this.triviaKnown = savedKnown;
|
|
9025
9460
|
if (d.clearTrivia === true) return this.emit(op, -1, bodyIp, flags);
|
|
9026
9461
|
if (d.triviaParser === void 0) {
|
|
9027
9462
|
return cap || flags !== 0 ? this.emit(op, -1, bodyIp, flags) : bodyIp;
|
|
@@ -9062,6 +9497,7 @@ var Encoder = class {
|
|
|
9062
9497
|
switch (this.code[ip]) {
|
|
9063
9498
|
case OP_GATE:
|
|
9064
9499
|
case OP_RGATE:
|
|
9500
|
+
case OP_RGATE2:
|
|
9065
9501
|
return [ip + 2];
|
|
9066
9502
|
case OP_RULE:
|
|
9067
9503
|
case OP_OPT:
|
|
@@ -9071,6 +9507,7 @@ var Encoder = class {
|
|
|
9071
9507
|
case OP_ATTEMPT:
|
|
9072
9508
|
case OP_LABEL:
|
|
9073
9509
|
case OP_COV:
|
|
9510
|
+
case OP_GAPGATE:
|
|
9074
9511
|
return [ip + 1];
|
|
9075
9512
|
case OP_SCOPE:
|
|
9076
9513
|
case OP_SCOPE_CAP:
|
|
@@ -9107,6 +9544,8 @@ var Encoder = class {
|
|
|
9107
9544
|
case OP_REP:
|
|
9108
9545
|
case OP_REPV:
|
|
9109
9546
|
return this.code[ip + 4] >= 0 ? [ip + 1, ip + 4] : [ip + 1];
|
|
9547
|
+
case OP_STRICT:
|
|
9548
|
+
return [ip + 1, ip + 2];
|
|
9110
9549
|
default:
|
|
9111
9550
|
return [];
|
|
9112
9551
|
}
|
|
@@ -10267,6 +10706,7 @@ function childSlots(code, ip, out) {
|
|
|
10267
10706
|
case OP_LABEL:
|
|
10268
10707
|
case OP_COV:
|
|
10269
10708
|
case OP_REJECT:
|
|
10709
|
+
case OP_GAPGATE:
|
|
10270
10710
|
out.push(code[ip + 1]);
|
|
10271
10711
|
return true;
|
|
10272
10712
|
// Single child at `ip + 2`.
|
|
@@ -10283,8 +10723,13 @@ function childSlots(code, ip, out) {
|
|
|
10283
10723
|
case OP_SOURCE_LEAF:
|
|
10284
10724
|
case OP_ARMGATE:
|
|
10285
10725
|
case OP_RGATE:
|
|
10726
|
+
case OP_RGATE2:
|
|
10286
10727
|
out.push(code[ip + 2]);
|
|
10287
10728
|
return true;
|
|
10729
|
+
// `STRICT strict tolerant` — both encodings are reachable; an assembly keeps one.
|
|
10730
|
+
case OP_STRICT:
|
|
10731
|
+
out.push(code[ip + 1], code[ip + 2]);
|
|
10732
|
+
return true;
|
|
10288
10733
|
// `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
|
|
10289
10734
|
// data the enclosing `dispatch()` already consumed, so the only edge is the
|
|
10290
10735
|
// fallback.
|
|
@@ -10732,7 +11177,8 @@ var WRAPPERS = /* @__PURE__ */ new Set([
|
|
|
10732
11177
|
OP_WITHCTX,
|
|
10733
11178
|
OP_RULE,
|
|
10734
11179
|
OP_ATTEMPT,
|
|
10735
|
-
OP_COV
|
|
11180
|
+
OP_COV,
|
|
11181
|
+
OP_GAPGATE
|
|
10736
11182
|
]);
|
|
10737
11183
|
function rowNullable(code, k, ip, memo) {
|
|
10738
11184
|
const hit = memo.get(ip);
|
|
@@ -10769,7 +11215,31 @@ function holdsGap(code, k, base, n, i, memo) {
|
|
|
10769
11215
|
return !rowNullable(code, k, next, memo);
|
|
10770
11216
|
}
|
|
10771
11217
|
|
|
11218
|
+
// src/table/gap-gate.ts
|
|
11219
|
+
function newGapSlot() {
|
|
11220
|
+
return { row: -1, at: -1, end: -1, input: void 0 };
|
|
11221
|
+
}
|
|
11222
|
+
function gapRows(code, roots) {
|
|
11223
|
+
const rows = /* @__PURE__ */ new Set();
|
|
11224
|
+
const seen = /* @__PURE__ */ new Set();
|
|
11225
|
+
const stack = [...roots];
|
|
11226
|
+
const kids = [];
|
|
11227
|
+
while (stack.length > 0) {
|
|
11228
|
+
const ip = stack.pop();
|
|
11229
|
+
if (seen.has(ip)) continue;
|
|
11230
|
+
seen.add(ip);
|
|
11231
|
+
if (code[ip] === OP_GAPGATE) rows.add(code[ip + 2]);
|
|
11232
|
+
kids.length = 0;
|
|
11233
|
+
childSlots(code, ip, kids);
|
|
11234
|
+
for (const c of kids) stack.push(c);
|
|
11235
|
+
}
|
|
11236
|
+
return rows;
|
|
11237
|
+
}
|
|
11238
|
+
|
|
10772
11239
|
// src/table/emit-assembly.ts
|
|
11240
|
+
function gapRegexLowers(re) {
|
|
11241
|
+
return re instanceof RegExp && scanShapeFromRegex(re.source, re.flags) !== null;
|
|
11242
|
+
}
|
|
10773
11243
|
var Unemittable = class extends Error {
|
|
10774
11244
|
construct;
|
|
10775
11245
|
constructor(construct) {
|
|
@@ -10788,7 +11258,6 @@ var EMITTED_PARAMS = [
|
|
|
10788
11258
|
"CLS",
|
|
10789
11259
|
"AFX",
|
|
10790
11260
|
"TRIVIA",
|
|
10791
|
-
"TRIVIALABELS",
|
|
10792
11261
|
"TRIVIASCAN",
|
|
10793
11262
|
"SCANS",
|
|
10794
11263
|
"DISP",
|
|
@@ -10812,7 +11281,6 @@ var EMITTED_PARAMS = [
|
|
|
10812
11281
|
"cstLeavesLen",
|
|
10813
11282
|
"skipTriviaScanned",
|
|
10814
11283
|
"needsDeferredTriviaCommit",
|
|
10815
|
-
"scanTrivia",
|
|
10816
11284
|
"advanceTrivia",
|
|
10817
11285
|
"refuseUnclassifiedRootScope",
|
|
10818
11286
|
"spanLines",
|
|
@@ -10832,34 +11300,31 @@ var EMITTED_PARAMS = [
|
|
|
10832
11300
|
"orSentinel",
|
|
10833
11301
|
"captureError",
|
|
10834
11302
|
// Pure scalar terminal recognizers, indexed by the terminal's existing const
|
|
10835
|
-
// operand
|
|
11303
|
+
// operand; selected lexical bodies; the adjacency test.
|
|
10836
11304
|
"RECOG",
|
|
10837
|
-
// Appended so precompiled factories produced by earlier runtimes keep every
|
|
10838
|
-
// positional helper binding. Older factories ignore this trailing argument.
|
|
10839
|
-
"commitTriviaScan",
|
|
10840
|
-
"scanTriviaCompact",
|
|
10841
11305
|
"LEX",
|
|
10842
|
-
// Appended for old precompiled-factory ABI: old factories ignore it.
|
|
10843
11306
|
"adjacencyHolds",
|
|
10844
|
-
//
|
|
11307
|
+
// Selected composite lexical programs.
|
|
10845
11308
|
"LEXPROG",
|
|
10846
|
-
//
|
|
10847
|
-
// old factories ignore them.
|
|
11309
|
+
// Trivia-attributing fields (`field(…, { leadingTrivia })`).
|
|
10848
11310
|
"LEAD",
|
|
10849
11311
|
"triviaFieldCapture",
|
|
10850
|
-
//
|
|
10851
|
-
// factories ignore it.
|
|
11312
|
+
// The deferred-commit trivia skip (`trivia-gap.ts`).
|
|
10852
11313
|
"skipDeferredTrivia",
|
|
10853
|
-
//
|
|
10854
|
-
// ignore it.
|
|
11314
|
+
// The pass-through collapse (`run-support.ts`).
|
|
10855
11315
|
"collapseEmpty",
|
|
10856
|
-
//
|
|
10857
|
-
//
|
|
11316
|
+
// Constructor-built tree objects (`cst/plain.d.ts`): a `new` call has no
|
|
11317
|
+
// allocation site, so V8 cannot pretenure them.
|
|
10858
11318
|
"_SP",
|
|
10859
11319
|
"_LF",
|
|
10860
11320
|
"_ND",
|
|
10861
11321
|
"_FC",
|
|
10862
|
-
"_BUF"
|
|
11322
|
+
"_BUF",
|
|
11323
|
+
// The gap gate's slot (`gap-gate.ts`).
|
|
11324
|
+
"GAP"
|
|
11325
|
+
// Artifacts are version-locked (docs/design/artifact-format.md): a factory is
|
|
11326
|
+
// only ever called by the runtime that emitted it, so a name nothing emitted
|
|
11327
|
+
// reads is removed rather than kept for an older factory's positions.
|
|
10863
11328
|
];
|
|
10864
11329
|
var RUNTIME_PRELUDE = `
|
|
10865
11330
|
let _pfScan=null
|
|
@@ -11110,7 +11575,7 @@ function rebuildPools(cc, fx, disp, plan) {
|
|
|
11110
11575
|
})
|
|
11111
11576
|
};
|
|
11112
11577
|
}
|
|
11113
|
-
function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, select, scanSinkNeutral = false) {
|
|
11578
|
+
function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, select, scanSinkNeutral = false, gapNeutral = false) {
|
|
11114
11579
|
const { code, k, fx, disp, dsp, triviaLabelled } = t;
|
|
11115
11580
|
const swapLegal = !cfg.trackLines;
|
|
11116
11581
|
const hostCst = cfg.hostCst;
|
|
@@ -11118,6 +11583,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, se
|
|
|
11118
11583
|
if (cfg.coverage) throw new Unemittable("a coverage assembly");
|
|
11119
11584
|
const roots = [...Object.values(prog.rules), ...extraIps];
|
|
11120
11585
|
const reachable = [...reachableSites(code, roots)];
|
|
11586
|
+
const GAP_ROWS = gapNeutral ? /* @__PURE__ */ new Set() : new Set([...gapRows(code, roots)].filter((row) => !gapRegexLowers(k[code[row + 1]])));
|
|
11121
11587
|
const labels = computeSiteLabels(code, roots, hostCst);
|
|
11122
11588
|
const scalarSpecs = /* @__PURE__ */ new Set();
|
|
11123
11589
|
const nullable2 = /* @__PURE__ */ new Map();
|
|
@@ -11455,13 +11921,15 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
11455
11921
|
function aliasOf(ip) {
|
|
11456
11922
|
const op = code[ip];
|
|
11457
11923
|
if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
|
|
11458
|
-
if (op === OP_RULE) return code[ip + 1];
|
|
11924
|
+
if (op === OP_RULE || op === OP_GAPGATE) return code[ip + 1];
|
|
11925
|
+
if (op === OP_STRICT) return code[cfg.tolerant || cfg.probe ? ip + 2 : ip + 1];
|
|
11459
11926
|
if (scopeIsIdentity(code, ip, labels.at(ip))) return code[ip + 2];
|
|
11460
11927
|
return void 0;
|
|
11461
11928
|
}
|
|
11462
11929
|
function lower(ip, fname) {
|
|
11463
11930
|
const op = code[ip];
|
|
11464
11931
|
const head = `function ${fname}(input,pos,ctx){`;
|
|
11932
|
+
const outerHead = head;
|
|
11465
11933
|
const L = labels.at(ip);
|
|
11466
11934
|
const sinks = sinksAt(ip);
|
|
11467
11935
|
const pushLeaf = L.buf && !cfg.trackLines ? L.raw === RAW_OMIT ? "_pushLeafNoRawBuf" : L.raw === RAW_CAPTURE ? "_pushLeafBuf" : "_pushLeaf" : "_pushLeaf";
|
|
@@ -11537,9 +12005,27 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
11537
12005
|
case OP_RX_TRACK: {
|
|
11538
12006
|
const xf = fxRef(code[ip + 2]);
|
|
11539
12007
|
const track = op === OP_RX_TRACK;
|
|
12008
|
+
if (GAP_ROWS.has(ip)) {
|
|
12009
|
+
const re2 = hoist("gx", `K[${code[ip + 1]}]`);
|
|
12010
|
+
return `${outerHead}
|
|
12011
|
+
let e
|
|
12012
|
+
if(GAP.row===${ip}&&GAP.at===pos&&GAP.input===input)e=GAP.end
|
|
12013
|
+
else{${re2}.lastIndex=pos;e=${re2}.test(input)?${re2}.lastIndex:-1}
|
|
12014
|
+
if(e>=0){
|
|
12015
|
+
const v=input.slice(pos,e)
|
|
12016
|
+
${captureLeaf("v")}
|
|
12017
|
+
${track ? "_trackLines(ctx,input,e)\n" : ""}EC.e=e
|
|
12018
|
+
return v
|
|
12019
|
+
}
|
|
12020
|
+
ctx._fe=pos;ctx._fx=${xf}
|
|
12021
|
+
${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
12022
|
+
` : ""}return FAIL
|
|
12023
|
+
}`;
|
|
12024
|
+
}
|
|
12025
|
+
const head2 = outerHead;
|
|
11540
12026
|
if (!track && scalarSpecs.has(code[ip + 1])) {
|
|
11541
12027
|
const recognize = recognizerRef(code[ip + 1]);
|
|
11542
|
-
return `${
|
|
12028
|
+
return `${head2}
|
|
11543
12029
|
const e=${recognize}(input,pos)
|
|
11544
12030
|
if(e>=0){
|
|
11545
12031
|
const v=input.slice(pos,e)
|
|
@@ -11552,11 +12038,11 @@ return FAIL
|
|
|
11552
12038
|
}`;
|
|
11553
12039
|
}
|
|
11554
12040
|
const scanned = emitScan(code[ip + 1], xf, track, captureLeaf);
|
|
11555
|
-
if (scanned !== void 0) return `${
|
|
12041
|
+
if (scanned !== void 0) return `${head2}${scanned}}`;
|
|
11556
12042
|
const rxk = k[code[ip + 1]];
|
|
11557
12043
|
if (!(rxk instanceof RegExp) || !rxk.sticky) throw new Unemittable("a non-sticky regex row");
|
|
11558
12044
|
const re = kRef(code[ip + 1]);
|
|
11559
|
-
return `${
|
|
12045
|
+
return `${head2}
|
|
11560
12046
|
${re}.lastIndex=pos
|
|
11561
12047
|
if(${re}.test(input)){
|
|
11562
12048
|
const e=${re}.lastIndex
|
|
@@ -11594,6 +12080,28 @@ return ${child}(input,pos,ctx)
|
|
|
11594
12080
|
const it=ctx._routed
|
|
11595
12081
|
if(it!==undefined&&it.span.start===pos&&!classHas(${cls},lead(input,it.span.end))){ctx._fe=it.span.end;ctx._fx=${xf};return FAIL}
|
|
11596
12082
|
return ${child}(input,pos,ctx)
|
|
12083
|
+
}`;
|
|
12084
|
+
}
|
|
12085
|
+
case OP_RGATE2: {
|
|
12086
|
+
const child = link(code[ip + 2]);
|
|
12087
|
+
if (cfg.tolerant || cfg.probe) return `${head}
|
|
12088
|
+
return ${child}(input,pos,ctx)
|
|
12089
|
+
}`;
|
|
12090
|
+
const idxs = [code[ip + 1], code[ip + 4], code[ip + 5]];
|
|
12091
|
+
const ascii = idxs.every((i) => isAsciiOnlyClass(t.cc[i]));
|
|
12092
|
+
const ref2 = (idx, tag) => {
|
|
12093
|
+
const ci = classes.push([t.cc[idx]]) - 1;
|
|
12094
|
+
classPlan.push([idx]);
|
|
12095
|
+
return hoist(tag, `CLS[${ci}][0]`);
|
|
12096
|
+
};
|
|
12097
|
+
const [cls, first, second] = [ref2(idxs[0], "cl"), ref2(idxs[1], "c1"), ref2(idxs[2], "c2")];
|
|
12098
|
+
const has = (c, at) => ascii ? `${c}.ascii[${at}]===1` : `classHas(${c},${at})`;
|
|
12099
|
+
const xf = fxRef(code[ip + 3]);
|
|
12100
|
+
return `${head}
|
|
12101
|
+
const it=ctx._routed
|
|
12102
|
+
if(it!==undefined&&it.span.start===pos){const e=it.span.end;const c=${ascii ? "input.charCodeAt(e)" : "lead(input,e)"}
|
|
12103
|
+
if(!(${has(cls, "c")})||(${has(first, "c")}&&!(${has(second, ascii ? "input.charCodeAt(e+1)" : "lead(input,e+1)")}))){ctx._fe=e;ctx._fx=${xf};return FAIL}}
|
|
12104
|
+
return ${child}(input,pos,ctx)
|
|
11597
12105
|
}`;
|
|
11598
12106
|
}
|
|
11599
12107
|
case OP_ARMGATE: {
|
|
@@ -12003,7 +12511,27 @@ if(ctx._fc===true)return FAIL
|
|
|
12003
12511
|
const af=ctx._fx
|
|
12004
12512
|
if(af!==undefined&&af.length>0){ctx._fe=pos;return FAIL}
|
|
12005
12513
|
}
|
|
12006
|
-
|
|
12514
|
+
${cfg.probe ? `if(arm<0){${arms.map((a) => `${a}(input,pos,ctx)`).join(";")}}
|
|
12515
|
+
` : ""}ctx._fe=pos;ctx._fx=${choiceFx}
|
|
12516
|
+
return FAIL
|
|
12517
|
+
}`;
|
|
12518
|
+
}
|
|
12519
|
+
if (cfg.probe) {
|
|
12520
|
+
const p = tmp();
|
|
12521
|
+
return `${head}
|
|
12522
|
+
${emitMark(p, L.buf, L.raw, sinks)}
|
|
12523
|
+
let acc
|
|
12524
|
+
let best=pos
|
|
12525
|
+
${arms.map((arm) => `{ctx._fc=false
|
|
12526
|
+
const v=${arm}(input,pos,ctx)
|
|
12527
|
+
if(v!==FAIL)return v
|
|
12528
|
+
const at=ctx._fe??pos
|
|
12529
|
+
if(at>best){best=at;acc=undefined}
|
|
12530
|
+
if(at===best)acc=_accSet(ctx._fx,acc)
|
|
12531
|
+
if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
|
|
12532
|
+
${emitRollback(p, L.buf, L.raw, sinks)}
|
|
12533
|
+
}`).join("\n")}
|
|
12534
|
+
ctx._fe=pos;ctx._fx=acc??${choiceFx}
|
|
12007
12535
|
return FAIL
|
|
12008
12536
|
}`;
|
|
12009
12537
|
}
|
|
@@ -12210,7 +12738,8 @@ return FAIL
|
|
|
12210
12738
|
const selector = link(code[ip + 1]);
|
|
12211
12739
|
const otherIp = code[ip + 3];
|
|
12212
12740
|
const other = otherIp >= 0 ? link(otherIp) : void 0;
|
|
12213
|
-
const otherRouted = code[ip + 4] === 1;
|
|
12741
|
+
const otherRouted = (code[ip + 4] & 1) === 1;
|
|
12742
|
+
const otherCommits = (code[ip + 4] & 2) === 0;
|
|
12214
12743
|
const n = code[ip + 5];
|
|
12215
12744
|
validateDispatchSpec(spec, n, code[ip + 4]);
|
|
12216
12745
|
const armBase = ip + 6;
|
|
@@ -12264,7 +12793,7 @@ ${fallbackCase}
|
|
|
12264
12793
|
}
|
|
12265
12794
|
if(v===FAIL){
|
|
12266
12795
|
${emitRollback(m2, L.buf, L.raw, sinks)}
|
|
12267
|
-
ctx._fc=true
|
|
12796
|
+
${other !== void 0 && !otherCommits ? "if(arm!==undefined)" : ""}ctx._fc=true
|
|
12268
12797
|
return FAIL
|
|
12269
12798
|
}
|
|
12270
12799
|
return [key,v]
|
|
@@ -12296,6 +12825,63 @@ return [key,v]
|
|
|
12296
12825
|
}
|
|
12297
12826
|
}
|
|
12298
12827
|
const itemMiss = (at) => itemAscii ? `${itemCls}.ascii[input.charCodeAt(${at})]!==1` : `!classHas(${itemCls},lead(input,${at}))`;
|
|
12828
|
+
let sepCls;
|
|
12829
|
+
let sepAscii = false;
|
|
12830
|
+
if (!REC2 && sepIp >= 0 && (code[ip + 5] & 8) !== 0 && !leadingTriviaFieldAt(code, k, sepIp) && !rowNullable(code, k, sepIp, nullable2)) {
|
|
12831
|
+
const resolved = t.cc[code[ip + 8]];
|
|
12832
|
+
const ci = classes.push([resolved]) - 1;
|
|
12833
|
+
classPlan.push([code[ip + 8]]);
|
|
12834
|
+
sepCls = hoist("rs", `CLS[${ci}][0]`);
|
|
12835
|
+
sepAscii = isAsciiOnlyClass(resolved);
|
|
12836
|
+
}
|
|
12837
|
+
const gapIp = !gapNeutral && sepIp < 0 && min === 0 && !REC2 && code[code[ip + 1]] === OP_GAPGATE ? code[ip + 1] : -1;
|
|
12838
|
+
let gapCode = (_rb) => "";
|
|
12839
|
+
if (gapIp >= 0) {
|
|
12840
|
+
const row = code[gapIp + 2];
|
|
12841
|
+
const rx = k[code[row + 1]];
|
|
12842
|
+
const shape = gapRegexLowers(rx) ? scanShapeFromRegex(rx.source, rx.flags) : null;
|
|
12843
|
+
const cls = (idx) => {
|
|
12844
|
+
const resolved = t.cc[idx];
|
|
12845
|
+
const ci = classes.push([resolved]) - 1;
|
|
12846
|
+
classPlan.push([idx]);
|
|
12847
|
+
const ref2 = hoist("gc", `CLS[${ci}][0]`);
|
|
12848
|
+
return isAsciiOnlyClass(resolved) ? `${ref2}.ascii[input.charCodeAt(${"@"})]!==1` : `!classHas(${ref2},lead(input,${"@"}))`;
|
|
12849
|
+
};
|
|
12850
|
+
const follow = cls(code[gapIp + 3]).replaceAll("@", "gq");
|
|
12851
|
+
const other = code[gapIp + 4] >= 0 ? cls(code[gapIp + 4]).replaceAll("@", "itemStart") : "true";
|
|
12852
|
+
if (shape !== null) {
|
|
12853
|
+
let n = 0;
|
|
12854
|
+
const q2 = tmp();
|
|
12855
|
+
const m = emitShapeMatch(shape, "itemStart", (prefix = "_v") => `${q2}${prefix}${n++}`, "");
|
|
12856
|
+
gapCode = (rbCode) => `let gapped=false
|
|
12857
|
+
if(ctx._probe===undefined){
|
|
12858
|
+
${m.setup.join("\n")}
|
|
12859
|
+
const gq=${m.ok}?${m.end}:-1
|
|
12860
|
+
if((gq<0||${follow})&&${other}){
|
|
12861
|
+
${rbCode}
|
|
12862
|
+
break
|
|
12863
|
+
}
|
|
12864
|
+
}
|
|
12865
|
+
`;
|
|
12866
|
+
} else {
|
|
12867
|
+
const re = hoist("gr", `K[${code[row + 1]}]`);
|
|
12868
|
+
gapCode = (rbCode) => `let gapped=false
|
|
12869
|
+
if(ctx._probe===undefined){
|
|
12870
|
+
${re}.lastIndex=itemStart
|
|
12871
|
+
const gq=${re}.test(input)?${re}.lastIndex:-1
|
|
12872
|
+
if((gq<0||${follow})&&${other}){
|
|
12873
|
+
${rbCode}
|
|
12874
|
+
break
|
|
12875
|
+
}
|
|
12876
|
+
if(gq>=0){
|
|
12877
|
+
GAP.row=${row};GAP.at=itemStart;GAP.end=gq;GAP.input=input
|
|
12878
|
+
gapped=true
|
|
12879
|
+
}
|
|
12880
|
+
}
|
|
12881
|
+
`;
|
|
12882
|
+
}
|
|
12883
|
+
}
|
|
12884
|
+
const sepMiss = (at) => sepAscii ? `${sepCls}.ascii[input.charCodeAt(${at})]!==1` : `!classHas(${sepCls},lead(input,${at}))`;
|
|
12299
12885
|
const skipBeforeFirst = sepIp < 0 && min === 0;
|
|
12300
12886
|
const p = tmp();
|
|
12301
12887
|
const via = sep !== void 0 ? "false" : min === 0 ? skipBeforeFirst ? "true" : "count>0" : `count>=${min}&&count>0`;
|
|
@@ -12333,7 +12919,7 @@ ${p}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
|
12333
12919
|
${p}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${markSinks}
|
|
12334
12920
|
}`;
|
|
12335
12921
|
const my = `${p}my`;
|
|
12336
|
-
const recFx = REC2 ? fxRef(code[ip + 6])
|
|
12922
|
+
const recFx = !REC2 ? "" : (flags & 16) !== 0 ? "[]" : fxRef(code[ip + 6]);
|
|
12337
12923
|
const sepSent = REC2 ? sentRef(code[ip + 7]) : "undefined";
|
|
12338
12924
|
const recSent = sep === void 0 ? my : sepSent === "undefined" ? `orSentinel(${my},undefined)` : `orSentinel(${sepSent}??${my},${sepSent}===undefined?undefined:${my})`;
|
|
12339
12925
|
const recGate = sep !== void 0 || min === 0 ? "" : `count>=${min}&&`;
|
|
@@ -12349,7 +12935,7 @@ continue
|
|
|
12349
12935
|
return `${head}
|
|
12350
12936
|
const out=${collect ? "[]" : "undefined"}
|
|
12351
12937
|
${knownTrivia === void 0 ? "const hasTrivia=ctx.trivia!==undefined\n" : ""}${L.buf ? "" : "const needMark=_rollbackNeeded(ctx)\n"}${REC2 ? `const ${my}=ctx._sync
|
|
12352
|
-
` : ""}${itemCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
|
|
12938
|
+
` : ""}${itemCls === void 0 && sepCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
|
|
12353
12939
|
`}let cur=pos
|
|
12354
12940
|
let count=0
|
|
12355
12941
|
for(;;){
|
|
@@ -12365,6 +12951,10 @@ const lb=cstLeavesLen(ctx)
|
|
|
12365
12951
|
let sp=cur
|
|
12366
12952
|
${hasTrivia === "false" ? "" : hasTrivia === "true" ? `sp=${skip}(input,sp,ctx)
|
|
12367
12953
|
` : `if(hasTrivia)sp=${skip}(input,sp,ctx)
|
|
12954
|
+
`}${sepCls === void 0 ? "" : `if(count>=${min}&&${p}gate&&${sepMiss("sp")}){
|
|
12955
|
+
${rb}
|
|
12956
|
+
break
|
|
12957
|
+
}
|
|
12368
12958
|
`}ctx._fc=false
|
|
12369
12959
|
${sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp) ? "LEAD.at=cur\n" : ""}const sv=${sep}(input,sp,ctx)
|
|
12370
12960
|
if(sv===FAIL){
|
|
@@ -12380,13 +12970,13 @@ itemStart=${hasTrivia === "false" ? "EC.e" : hasTrivia === "true" ? `${skip}(inp
|
|
|
12380
12970
|
${rb}
|
|
12381
12971
|
${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
|
|
12382
12972
|
}
|
|
12383
|
-
${itemCls === void 0 ? "" : `if(count>=${min}&&${p}gate&&${itemMiss("itemStart")}){
|
|
12973
|
+
${itemCls === void 0 || sep === void 0 && hasTrivia === "false" ? "" : `if(count>=${min}&&${p}gate&&${sep === void 0 && hasTrivia === "hasTrivia" ? "hasTrivia&&" : ""}${itemMiss("itemStart")}){
|
|
12384
12974
|
${rb}
|
|
12385
12975
|
${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
|
|
12386
12976
|
}
|
|
12387
|
-
`}ctx._fc=false
|
|
12977
|
+
`}${gapCode(rb)}ctx._fc=false
|
|
12388
12978
|
const v=${child}(input,itemStart,ctx)
|
|
12389
|
-
if(v===FAIL){
|
|
12979
|
+
${gapIp >= 0 ? "if(gapped)GAP.at=-1\n" : ""}if(v===FAIL){
|
|
12390
12980
|
${REC2 ? `if(ctx._fc===true){
|
|
12391
12981
|
${rb}
|
|
12392
12982
|
return FAIL
|
|
@@ -13202,6 +13792,9 @@ function clearOf(ranges, input, from, to) {
|
|
|
13202
13792
|
return true;
|
|
13203
13793
|
}
|
|
13204
13794
|
|
|
13795
|
+
// src/version.ts
|
|
13796
|
+
var PARSEMAN_VERSION = "0.60.0";
|
|
13797
|
+
|
|
13205
13798
|
// src/table/assemble.ts
|
|
13206
13799
|
import { PlainBuf as PlainBuf2, PlainField, PlainLeaf as PlainLeaf9, PlainNode as PlainNode2, PlainSpan as PlainSpan10 } from "./cst/plain.js";
|
|
13207
13800
|
|
|
@@ -13212,6 +13805,7 @@ function passChild(code, ip) {
|
|
|
13212
13805
|
case OP_LABEL:
|
|
13213
13806
|
case OP_COV:
|
|
13214
13807
|
case OP_TOKEN:
|
|
13808
|
+
case OP_GAPGATE:
|
|
13215
13809
|
return code[ip + 1];
|
|
13216
13810
|
case OP_GATE:
|
|
13217
13811
|
case OP_NODE:
|
|
@@ -13477,6 +14071,13 @@ function cfgKeyOf(hostCst, trackLines, tolerant, coverage, probe, hostReadsChild
|
|
|
13477
14071
|
function cfgKey(c) {
|
|
13478
14072
|
return cfgKeyOf(c.hostCst, c.trackLines, c.tolerant, c.coverage, c.probe, c.hostReadsChildren);
|
|
13479
14073
|
}
|
|
14074
|
+
function assertFactoryArity(pre) {
|
|
14075
|
+
if (pre.arity === EMITTED_PARAMS.length) return;
|
|
14076
|
+
const printed = pre.arity === void 0 ? "carries no helper count, so it was printed before parseman 0.60.0" : `takes ${pre.arity} helpers, but parseman ${PARSEMAN_VERSION} passes ${EMITTED_PARAMS.length}: it was printed by an older or newer parseman`;
|
|
14077
|
+
throw new Error(
|
|
14078
|
+
`parseman: this parser's printed assembly ${printed}. Reprint the parser with parseman ${PARSEMAN_VERSION}, or run it on the parseman version that printed it.`
|
|
14079
|
+
);
|
|
14080
|
+
}
|
|
13480
14081
|
function assemble(t, prog, cfg) {
|
|
13481
14082
|
const { code, k, fns, cc, fx, disp, dsp, trivia: trivia2, triviaLabelled } = t;
|
|
13482
14083
|
const triviaScan = t.triviaScan;
|
|
@@ -13511,6 +14112,8 @@ function assemble(t, prog, cfg) {
|
|
|
13511
14112
|
return recognize;
|
|
13512
14113
|
}
|
|
13513
14114
|
const labelExtraIps = assemblyExtraIps(prog);
|
|
14115
|
+
const GAP_ROWS = gapRows(code, [...Object.values(prog.rules), ...labelExtraIps]);
|
|
14116
|
+
const GAP = newGapSlot();
|
|
13514
14117
|
const closureLabels = computeSiteLabels(
|
|
13515
14118
|
code,
|
|
13516
14119
|
[...Object.values(prog.rules), ...labelExtraIps],
|
|
@@ -13729,6 +14332,27 @@ function assemble(t, prog, cfg) {
|
|
|
13729
14332
|
return node2;
|
|
13730
14333
|
};
|
|
13731
14334
|
}
|
|
14335
|
+
function gapRegexPiece(row, re, xf, track) {
|
|
14336
|
+
return (input, pos, ctx) => {
|
|
14337
|
+
let e;
|
|
14338
|
+
if (GAP.row === row && GAP.at === pos && GAP.input === input) e = GAP.end;
|
|
14339
|
+
else {
|
|
14340
|
+
re.lastIndex = pos;
|
|
14341
|
+
e = re.test(input) ? re.lastIndex : -1;
|
|
14342
|
+
}
|
|
14343
|
+
if (e >= 0) {
|
|
14344
|
+
const v = input.slice(pos, e);
|
|
14345
|
+
if (cstCaptureActive(ctx)) pushLeaf(ctx, v, pos, e);
|
|
14346
|
+
if (track) trackLinesInto(ctx, input, e);
|
|
14347
|
+
EC.e = e;
|
|
14348
|
+
return v;
|
|
14349
|
+
}
|
|
14350
|
+
ctx._fe = pos;
|
|
14351
|
+
ctx._fx = xf;
|
|
14352
|
+
if (ctx._probe !== void 0) failAt(ctx, xf, pos);
|
|
14353
|
+
return FAIL;
|
|
14354
|
+
};
|
|
14355
|
+
}
|
|
13732
14356
|
function passCollapseNode(child, build, readsRaw) {
|
|
13733
14357
|
return (input, pos, ctx) => {
|
|
13734
14358
|
const v = child(input, pos, ctx);
|
|
@@ -14131,7 +14755,7 @@ function assemble(t, prog, cfg) {
|
|
|
14131
14755
|
return next?.(key);
|
|
14132
14756
|
};
|
|
14133
14757
|
}
|
|
14134
|
-
function dispatchBranch(child, usesRouted) {
|
|
14758
|
+
function dispatchBranch(child, usesRouted, commits = true) {
|
|
14135
14759
|
if (!usesRouted) {
|
|
14136
14760
|
return (input, _pos, selEnd, key, ctx) => {
|
|
14137
14761
|
const need = markCst(ctx);
|
|
@@ -14145,7 +14769,7 @@ function assemble(t, prog, cfg) {
|
|
|
14145
14769
|
const v = child(input, selEnd, ctx);
|
|
14146
14770
|
if (v === FAIL) {
|
|
14147
14771
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14148
|
-
ctx._fc = true;
|
|
14772
|
+
if (commits) ctx._fc = true;
|
|
14149
14773
|
return FAIL;
|
|
14150
14774
|
}
|
|
14151
14775
|
return [key, v];
|
|
@@ -14163,7 +14787,7 @@ function assemble(t, prog, cfg) {
|
|
|
14163
14787
|
}
|
|
14164
14788
|
if (v === FAIL) {
|
|
14165
14789
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
14166
|
-
ctx._fc = true;
|
|
14790
|
+
if (commits) ctx._fc = true;
|
|
14167
14791
|
return FAIL;
|
|
14168
14792
|
}
|
|
14169
14793
|
return [key, v];
|
|
@@ -14404,6 +15028,7 @@ function assemble(t, prog, cfg) {
|
|
|
14404
15028
|
case OP_RX: {
|
|
14405
15029
|
const re = k[code[ip + 1]];
|
|
14406
15030
|
const xf = fx[code[ip + 2]];
|
|
15031
|
+
if (GAP_ROWS.has(ip)) return gapRegexPiece(ip, re, xf, false);
|
|
14407
15032
|
const shared = rawScalarSpecs.has(code[ip + 1]) ? scalarFor(ip) : void 0;
|
|
14408
15033
|
if (shared !== void 0) {
|
|
14409
15034
|
return (input, pos, ctx) => {
|
|
@@ -14438,6 +15063,7 @@ function assemble(t, prog, cfg) {
|
|
|
14438
15063
|
case OP_RX_TRACK: {
|
|
14439
15064
|
const re = k[code[ip + 1]];
|
|
14440
15065
|
const xf = fx[code[ip + 2]];
|
|
15066
|
+
if (GAP_ROWS.has(ip)) return gapRegexPiece(ip, re, xf, true);
|
|
14441
15067
|
return (input, pos, ctx) => {
|
|
14442
15068
|
re.lastIndex = pos;
|
|
14443
15069
|
if (re.test(input)) {
|
|
@@ -14568,6 +15194,12 @@ function assemble(t, prog, cfg) {
|
|
|
14568
15194
|
return v;
|
|
14569
15195
|
};
|
|
14570
15196
|
}
|
|
15197
|
+
// Transparent: only the repeat holding it reads its operands.
|
|
15198
|
+
case OP_GAPGATE:
|
|
15199
|
+
return link(code[ip + 1]);
|
|
15200
|
+
// One encoding per assembly: strict, or the construct as written.
|
|
15201
|
+
case OP_STRICT:
|
|
15202
|
+
return link(code[cfg.tolerant || cfg.probe ? ip + 2 : ip + 1]);
|
|
14571
15203
|
case OP_RULE:
|
|
14572
15204
|
return link(code[ip + 1]);
|
|
14573
15205
|
case OP_LIVE: {
|
|
@@ -15493,7 +16125,7 @@ function assemble(t, prog, cfg) {
|
|
|
15493
16125
|
if (table.exclusive) {
|
|
15494
16126
|
const ascii = table.ascii;
|
|
15495
16127
|
const hi = table.hi;
|
|
15496
|
-
if (n === 2) {
|
|
16128
|
+
if (n === 2 && !cfg.probe) {
|
|
15497
16129
|
const a0 = link(code[base]), a1 = link(code[base + 1]);
|
|
15498
16130
|
return (input, pos, ctx) => {
|
|
15499
16131
|
const c = lead(input, pos);
|
|
@@ -15525,7 +16157,7 @@ function assemble(t, prog, cfg) {
|
|
|
15525
16157
|
return FAIL;
|
|
15526
16158
|
};
|
|
15527
16159
|
}
|
|
15528
|
-
if (n === 3) {
|
|
16160
|
+
if (n === 3 && !cfg.probe) {
|
|
15529
16161
|
const a0 = link(code[base]), a1 = link(code[base + 1]), a2 = link(code[base + 2]);
|
|
15530
16162
|
return (input, pos, ctx) => {
|
|
15531
16163
|
const c = lead(input, pos);
|
|
@@ -15570,6 +16202,7 @@ function assemble(t, prog, cfg) {
|
|
|
15570
16202
|
);
|
|
15571
16203
|
};
|
|
15572
16204
|
const selected = bindExclusive(0);
|
|
16205
|
+
const probeArms = cfg.probe ? Array.from({ length: n }, (_, i) => link(code[base + i])) : void 0;
|
|
15573
16206
|
return (input, pos, ctx) => {
|
|
15574
16207
|
const c = lead(input, pos);
|
|
15575
16208
|
let arm = -1;
|
|
@@ -15595,12 +16228,13 @@ function assemble(t, prog, cfg) {
|
|
|
15595
16228
|
return FAIL;
|
|
15596
16229
|
}
|
|
15597
16230
|
}
|
|
16231
|
+
if (arm < 0 && probeArms !== void 0) for (const a of probeArms) a(input, pos, ctx);
|
|
15598
16232
|
ctx._fe = pos;
|
|
15599
16233
|
ctx._fx = choiceFx;
|
|
15600
16234
|
return FAIL;
|
|
15601
16235
|
};
|
|
15602
16236
|
}
|
|
15603
|
-
const armCls = table.armCls;
|
|
16237
|
+
const armCls = cfg.probe ? table.armCls.map(() => null) : table.armCls;
|
|
15604
16238
|
if (n === 2 || n === 3) {
|
|
15605
16239
|
const a0 = link(code[base]), a1 = link(code[base + 1]);
|
|
15606
16240
|
const a2 = n === 3 ? link(code[base + 2]) : void 0;
|
|
@@ -16020,6 +16654,43 @@ function assemble(t, prog, cfg) {
|
|
|
16020
16654
|
return child(input, pos, ctx);
|
|
16021
16655
|
};
|
|
16022
16656
|
}
|
|
16657
|
+
case OP_RGATE2: {
|
|
16658
|
+
const cls = cc[code[ip + 1]];
|
|
16659
|
+
const xf = fx[code[ip + 3]];
|
|
16660
|
+
const first = cc[code[ip + 4]];
|
|
16661
|
+
const second = cc[code[ip + 5]];
|
|
16662
|
+
const child = link(code[ip + 2]);
|
|
16663
|
+
if (cfg.tolerant || cfg.probe) return child;
|
|
16664
|
+
if (cls.hi.length === 0 && first.hi.length === 0 && second.hi.length === 0) {
|
|
16665
|
+
const a0 = cls.ascii, a1 = first.ascii, a2 = second.ascii;
|
|
16666
|
+
return (input, pos, ctx) => {
|
|
16667
|
+
const item = ctx._routed;
|
|
16668
|
+
if (item !== void 0 && item.span.start === pos) {
|
|
16669
|
+
const e = item.span.end;
|
|
16670
|
+
const c = input.charCodeAt(e);
|
|
16671
|
+
if (a0[c] !== 1 || a1[c] === 1 && a2[input.charCodeAt(e + 1)] !== 1) {
|
|
16672
|
+
ctx._fe = e;
|
|
16673
|
+
ctx._fx = xf;
|
|
16674
|
+
return FAIL;
|
|
16675
|
+
}
|
|
16676
|
+
}
|
|
16677
|
+
return child(input, pos, ctx);
|
|
16678
|
+
};
|
|
16679
|
+
}
|
|
16680
|
+
return (input, pos, ctx) => {
|
|
16681
|
+
const item = ctx._routed;
|
|
16682
|
+
if (item !== void 0 && item.span.start === pos) {
|
|
16683
|
+
const e = item.span.end;
|
|
16684
|
+
const c = lead(input, e);
|
|
16685
|
+
if (!classHas2(cls, c) || classHas2(first, c) && !classHas2(second, lead(input, e + 1))) {
|
|
16686
|
+
ctx._fe = e;
|
|
16687
|
+
ctx._fx = xf;
|
|
16688
|
+
return FAIL;
|
|
16689
|
+
}
|
|
16690
|
+
}
|
|
16691
|
+
return child(input, pos, ctx);
|
|
16692
|
+
};
|
|
16693
|
+
}
|
|
16023
16694
|
case OP_ARMGATE: {
|
|
16024
16695
|
const pred = fns[code[ip + 1]];
|
|
16025
16696
|
const child = link(code[ip + 2]);
|
|
@@ -16087,10 +16758,18 @@ function assemble(t, prog, cfg) {
|
|
|
16087
16758
|
const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
|
|
16088
16759
|
const itemClass = !REC2 && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
|
|
16089
16760
|
const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
|
|
16761
|
+
const sepClassIndex = sepIp >= 0 && !sepLeads && (flags & 8) !== 0 ? code[ip + 8] : -1;
|
|
16762
|
+
const sepClass = !REC2 && sepClassIndex >= 0 && !rowNullable(code, k, sepIp, NULLABLE) ? cc[sepClassIndex] : void 0;
|
|
16763
|
+
const gapIp = sepIp < 0 && min === 0 && !REC2 && code[code[ip + 1]] === OP_GAPGATE ? code[ip + 1] : -1;
|
|
16764
|
+
const gapRow = gapIp >= 0 ? code[gapIp + 2] : -1;
|
|
16765
|
+
const gapRe = gapIp >= 0 ? k[code[gapRow + 1]] : void 0;
|
|
16766
|
+
const gapFollow = gapIp >= 0 ? cc[code[gapIp + 3]] : void 0;
|
|
16767
|
+
const gapOther = gapIp >= 0 && code[gapIp + 4] >= 0 ? cc[code[gapIp + 4]] : void 0;
|
|
16090
16768
|
const skipBeforeFirst = sepIp < 0 && min === 0;
|
|
16091
16769
|
const itemClean = sepIp < 0 && CLEAN(code[ip + 1]) && !rowNullable(code, k, code[ip + 1], NULLABLE);
|
|
16092
16770
|
if (REC2) {
|
|
16093
16771
|
const itemFx2 = fx[code[ip + 6]];
|
|
16772
|
+
const recFx = (flags & 16) !== 0 ? EMPTY_FX2 : itemFx2;
|
|
16094
16773
|
const sepSent = sentinelFor(code[ip + 7]);
|
|
16095
16774
|
return (input, pos, ctx) => {
|
|
16096
16775
|
const out = collect ? [] : void 0;
|
|
@@ -16150,7 +16829,7 @@ function assemble(t, prog, cfg) {
|
|
|
16150
16829
|
itemStart,
|
|
16151
16830
|
ctx,
|
|
16152
16831
|
sep === void 0 ? mySync : orSentinel(sepSent ?? mySync, sepSent === void 0 ? void 0 : mySync),
|
|
16153
|
-
|
|
16832
|
+
recFx
|
|
16154
16833
|
);
|
|
16155
16834
|
if (out !== void 0) out.push(rr.error);
|
|
16156
16835
|
captureError(ctx, rr.error);
|
|
@@ -16188,6 +16867,7 @@ function assemble(t, prog, cfg) {
|
|
|
16188
16867
|
const markLater = needMark && (!itemClean || hasTrivia);
|
|
16189
16868
|
const markFirst = needMark && (!itemClean || hasTrivia && skipBeforeFirst);
|
|
16190
16869
|
const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
|
|
16870
|
+
const gateSep = sepClass !== void 0 && ctx._probe === void 0;
|
|
16191
16871
|
let cur = pos;
|
|
16192
16872
|
let count = 0;
|
|
16193
16873
|
for (; ; ) {
|
|
@@ -16210,6 +16890,10 @@ function assemble(t, prog, cfg) {
|
|
|
16210
16890
|
const leavesBefore = cstLeavesLen(ctx);
|
|
16211
16891
|
let sp = cur;
|
|
16212
16892
|
if (hasTrivia) sp = skipTrivia(input, sp, ctx);
|
|
16893
|
+
if (count >= min && gateSep && !classHas2(sepClass, lead(input, sp))) {
|
|
16894
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
16895
|
+
break;
|
|
16896
|
+
}
|
|
16213
16897
|
ctx._fc = false;
|
|
16214
16898
|
if (sepLeads) LEAD.at = cur;
|
|
16215
16899
|
const sv = sep(input, sp, ctx);
|
|
@@ -16229,13 +16913,30 @@ function assemble(t, prog, cfg) {
|
|
|
16229
16913
|
if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
|
|
16230
16914
|
break;
|
|
16231
16915
|
}
|
|
16232
|
-
if (count >= min && gateItems && !itemMayStart(input, itemStart)) {
|
|
16916
|
+
if (count >= min && gateItems && (sep !== void 0 || hasTrivia) && !itemMayStart(input, itemStart)) {
|
|
16233
16917
|
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
16234
16918
|
if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
|
|
16235
16919
|
break;
|
|
16236
16920
|
}
|
|
16921
|
+
let gapped = false;
|
|
16922
|
+
if (gapRe !== void 0 && ctx._probe === void 0) {
|
|
16923
|
+
gapRe.lastIndex = itemStart;
|
|
16924
|
+
const q2 = gapRe.test(input) ? gapRe.lastIndex : -1;
|
|
16925
|
+
if ((q2 < 0 || !classHas2(gapFollow, lead(input, q2))) && (gapOther === void 0 || !classHas2(gapOther, lead(input, itemStart)))) {
|
|
16926
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
16927
|
+
break;
|
|
16928
|
+
}
|
|
16929
|
+
if (q2 >= 0) {
|
|
16930
|
+
GAP.row = gapRow;
|
|
16931
|
+
GAP.at = itemStart;
|
|
16932
|
+
GAP.end = q2;
|
|
16933
|
+
GAP.input = input;
|
|
16934
|
+
gapped = true;
|
|
16935
|
+
}
|
|
16936
|
+
}
|
|
16237
16937
|
ctx._fc = false;
|
|
16238
16938
|
const v = child(input, itemStart, ctx);
|
|
16939
|
+
if (gapped) GAP.at = -1;
|
|
16239
16940
|
if (v === FAIL) {
|
|
16240
16941
|
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
16241
16942
|
if (committed3(ctx)) return FAIL;
|
|
@@ -16267,7 +16968,8 @@ function assemble(t, prog, cfg) {
|
|
|
16267
16968
|
const selector = link(code[ip + 1]);
|
|
16268
16969
|
const otherIp = code[ip + 3];
|
|
16269
16970
|
const other = otherIp >= 0 ? link(otherIp) : void 0;
|
|
16270
|
-
const otherRouted = code[ip + 4] === 1;
|
|
16971
|
+
const otherRouted = (code[ip + 4] & 1) === 1;
|
|
16972
|
+
const otherCommits = (code[ip + 4] & 2) === 0;
|
|
16271
16973
|
const n = code[ip + 5];
|
|
16272
16974
|
const armBase = ip + 6;
|
|
16273
16975
|
const byKey = spec.byKey;
|
|
@@ -16315,7 +17017,7 @@ function assemble(t, prog, cfg) {
|
|
|
16315
17017
|
);
|
|
16316
17018
|
};
|
|
16317
17019
|
const runArm = n === 0 ? void 0 : bindArms(0);
|
|
16318
|
-
const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted);
|
|
17020
|
+
const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted, otherCommits);
|
|
16319
17021
|
return (input, pos, ctx) => {
|
|
16320
17022
|
const need = markCst(ctx);
|
|
16321
17023
|
const mRaw = MRAW;
|
|
@@ -16576,6 +17278,7 @@ function assemble(t, prog, cfg) {
|
|
|
16576
17278
|
}
|
|
16577
17279
|
const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
|
|
16578
17280
|
if (pre !== void 0) {
|
|
17281
|
+
assertFactoryArity(pre);
|
|
16579
17282
|
const pools = rebuildPools(t.cc, t.fx, t.disp, pre.plan);
|
|
16580
17283
|
emitted = pre.factory(
|
|
16581
17284
|
EC,
|
|
@@ -16587,7 +17290,6 @@ function assemble(t, prog, cfg) {
|
|
|
16587
17290
|
pools.classes,
|
|
16588
17291
|
pools.armExpected,
|
|
16589
17292
|
trivia2,
|
|
16590
|
-
trivia2.map((tv) => tv?._meta.triviaKindLabels),
|
|
16591
17293
|
triviaScan,
|
|
16592
17294
|
scansArr,
|
|
16593
17295
|
disp,
|
|
@@ -16611,7 +17313,6 @@ function assemble(t, prog, cfg) {
|
|
|
16611
17313
|
cstLeavesLen,
|
|
16612
17314
|
skipTriviaScanned,
|
|
16613
17315
|
needsDeferredTriviaCommit,
|
|
16614
|
-
scanTrivia,
|
|
16615
17316
|
advanceTrivia,
|
|
16616
17317
|
refuseUnclassifiedRootScope,
|
|
16617
17318
|
spanLines,
|
|
@@ -16625,8 +17326,6 @@ function assemble(t, prog, cfg) {
|
|
|
16625
17326
|
orSentinel,
|
|
16626
17327
|
captureError,
|
|
16627
17328
|
scalarRecognizers,
|
|
16628
|
-
commitTriviaScan,
|
|
16629
|
-
scanTriviaCompact,
|
|
16630
17329
|
t.lex,
|
|
16631
17330
|
adjacencyHolds,
|
|
16632
17331
|
t.lexPrograms,
|
|
@@ -16638,7 +17337,8 @@ function assemble(t, prog, cfg) {
|
|
|
16638
17337
|
PlainLeaf9,
|
|
16639
17338
|
PlainNode2,
|
|
16640
17339
|
PlainField,
|
|
16641
|
-
PlainBuf2
|
|
17340
|
+
PlainBuf2,
|
|
17341
|
+
GAP
|
|
16642
17342
|
);
|
|
16643
17343
|
emitReached = new Set(pre.reached);
|
|
16644
17344
|
if (emitted.ext !== void 0) HYBRID = emitted;
|
|
@@ -16674,7 +17374,6 @@ function assemble(t, prog, cfg) {
|
|
|
16674
17374
|
em.classes,
|
|
16675
17375
|
em.armExpected,
|
|
16676
17376
|
trivia2,
|
|
16677
|
-
trivia2.map((tv) => tv?._meta.triviaKindLabels),
|
|
16678
17377
|
triviaScan,
|
|
16679
17378
|
scansArr,
|
|
16680
17379
|
disp,
|
|
@@ -16698,7 +17397,6 @@ function assemble(t, prog, cfg) {
|
|
|
16698
17397
|
cstLeavesLen,
|
|
16699
17398
|
skipTriviaScanned,
|
|
16700
17399
|
needsDeferredTriviaCommit,
|
|
16701
|
-
scanTrivia,
|
|
16702
17400
|
advanceTrivia,
|
|
16703
17401
|
refuseUnclassifiedRootScope,
|
|
16704
17402
|
spanLines,
|
|
@@ -16717,8 +17415,6 @@ function assemble(t, prog, cfg) {
|
|
|
16717
17415
|
orSentinel,
|
|
16718
17416
|
captureError,
|
|
16719
17417
|
scalarRecognizers,
|
|
16720
|
-
commitTriviaScan,
|
|
16721
|
-
scanTriviaCompact,
|
|
16722
17418
|
t.lex,
|
|
16723
17419
|
adjacencyHolds,
|
|
16724
17420
|
t.lexPrograms,
|
|
@@ -16730,7 +17426,8 @@ function assemble(t, prog, cfg) {
|
|
|
16730
17426
|
PlainLeaf9,
|
|
16731
17427
|
PlainNode2,
|
|
16732
17428
|
PlainField,
|
|
16733
|
-
PlainBuf2
|
|
17429
|
+
PlainBuf2,
|
|
17430
|
+
GAP
|
|
16734
17431
|
);
|
|
16735
17432
|
emitReached = em.reached;
|
|
16736
17433
|
} catch (e) {
|
|
@@ -16988,11 +17685,8 @@ function tableRules(source, metadataOrEntry = {}) {
|
|
|
16988
17685
|
return map[entry];
|
|
16989
17686
|
}
|
|
16990
17687
|
|
|
16991
|
-
// src/version.ts
|
|
16992
|
-
var PARSEMAN_VERSION = "0.59.3";
|
|
16993
|
-
|
|
16994
17688
|
// src/table/emit.ts
|
|
16995
|
-
var FACTORY_ARITY_GUARD = `if(arguments.length
|
|
17689
|
+
var FACTORY_ARITY_GUARD = `if(arguments.length!==${EMITTED_PARAMS.length})throw new Error(${JSON.stringify(`parseman: this parser was printed by parseman ${PARSEMAN_VERSION}; run it on parseman ${PARSEMAN_VERSION} or reprint it`)});`;
|
|
16996
17690
|
function jsString(s) {
|
|
16997
17691
|
return JSON.stringify(s);
|
|
16998
17692
|
}
|
|
@@ -17078,7 +17772,7 @@ function emitAssemblies(prog, cfgs) {
|
|
|
17078
17772
|
throw e;
|
|
17079
17773
|
}
|
|
17080
17774
|
const plan = em.plan;
|
|
17081
|
-
out.push(`{key:${key},factory:function(${EMITTED_PARAMS.join(",")}){${FACTORY_ARITY_GUARD}${em.source}
|
|
17775
|
+
out.push(`{key:${key},arity:${EMITTED_PARAMS.length},factory:function(${EMITTED_PARAMS.join(",")}){${FACTORY_ARITY_GUARD}${em.source}
|
|
17082
17776
|
},plan:{classes:[${plan.classes.map((r) => `[${r.join(",")}]`).join(",")}],armExpected:[${plan.armExpected.map((r) => `[${r.join(",")}]`).join(",")}],masks:[${plan.masks.join(",")}]},reached:[${[...em.reached].join(",")}]}`);
|
|
17083
17777
|
}
|
|
17084
17778
|
return [`a:[${out.join(",")}],`];
|
|
@@ -17354,7 +18048,7 @@ function payloadKey(p, d) {
|
|
|
17354
18048
|
case "sepBy":
|
|
17355
18049
|
return `sepBy\0${d.min}\0${d.max ?? ""}\0${d.trailing ?? ""}`;
|
|
17356
18050
|
case "dispatch":
|
|
17357
|
-
return `dispatch\0${d.cases.map((c) => JSON.stringify(c.keys)).join("")}\0${d.otherwise !== void 0}`;
|
|
18051
|
+
return `dispatch\0${d.cases.map((c) => JSON.stringify(c.keys)).join("")}\0${d.otherwise !== void 0}${d.otherwiseCommit === false ? "\0uncommitted" : ""}`;
|
|
17358
18052
|
case "expect":
|
|
17359
18053
|
return `expect\0${d.label ?? ""}\0${d.expected.join("")}`;
|
|
17360
18054
|
case "scanTo":
|
|
@@ -18660,7 +19354,10 @@ function staticWeights(code, entries) {
|
|
|
18660
19354
|
childSlots(code, ip, kids);
|
|
18661
19355
|
const op = code[ip];
|
|
18662
19356
|
const scale = op === OP_REP || op === OP_REPV ? LOOP : op === OP_CHOICE || op === OP_DISPATCH ? 1 / Math.max(1, kids.length) : 1;
|
|
18663
|
-
for (const
|
|
19357
|
+
for (const k of kids) {
|
|
19358
|
+
const kid = code[k] === OP_GAPGATE ? code[k + 1] : k;
|
|
19359
|
+
next.set(kid, Math.min(CAP, (next.get(kid) ?? 0) + w * scale));
|
|
19360
|
+
}
|
|
18664
19361
|
}
|
|
18665
19362
|
weight = next;
|
|
18666
19363
|
}
|
|
@@ -18777,7 +19474,7 @@ function compileRuleMap(ruleMap, opts = {}) {
|
|
|
18777
19474
|
const roots = assemblyExtraIps(artifact);
|
|
18778
19475
|
let siteBytes, fixed;
|
|
18779
19476
|
try {
|
|
18780
|
-
siteBytes = emitAssemblySource(table, artifact, cfg, roots, true, void 0, true).siteBytes;
|
|
19477
|
+
siteBytes = emitAssemblySource(table, artifact, cfg, roots, true, void 0, true, true).siteBytes;
|
|
18781
19478
|
fixed = emitAssemblySource(table, artifact, cfg, roots, true, /* @__PURE__ */ new Set(), true).source.length;
|
|
18782
19479
|
} catch (e) {
|
|
18783
19480
|
if (e instanceof Unemittable) return { ...none, refusal: e.construct };
|
|
@@ -19322,7 +20019,7 @@ ${outerDecls.map((d) => " " + d).join("\n")}
|
|
|
19322
20019
|
arms.push(`when(${matcherExpr(entry)}, ${kid(entry.parser)}${entry.caseInsensitive ? ", { caseInsensitive: true }" : ""})`);
|
|
19323
20020
|
}
|
|
19324
20021
|
}
|
|
19325
|
-
if (def.otherwise) arms.push(`otherwise(${kid(def.otherwise)})`);
|
|
20022
|
+
if (def.otherwise) arms.push(`otherwise(${kid(def.otherwise)}${def.otherwiseCommit === false ? ", { commit: false }" : ""})`);
|
|
19326
20023
|
return `dispatch(${kid(def.selector)}${arms.length === 0 ? "" : `, ${arms.join(", ")}`})`;
|
|
19327
20024
|
}
|
|
19328
20025
|
case "many":
|
|
@@ -21879,7 +22576,7 @@ function coverageEntry(entry, collector, maps, trace) {
|
|
|
21879
22576
|
arms.push(when(dispatchMatcher(entry2), wrapArm(entry2.parser, ids[armIndex++]), entry2.caseInsensitive ? { caseInsensitive: true } : void 0));
|
|
21880
22577
|
}
|
|
21881
22578
|
}
|
|
21882
|
-
if (def.otherwise) arms.push(otherwise(wrapArm(def.otherwise, ids[armIndex++])));
|
|
22579
|
+
if (def.otherwise) arms.push(otherwise(wrapArm(def.otherwise, ids[armIndex++]), def.otherwiseCommit === false ? { commit: false } : void 0));
|
|
21883
22580
|
const unsafeDispatch = dispatch;
|
|
21884
22581
|
const base2 = unsafeDispatch(build(def.selector), ...arms);
|
|
21885
22582
|
return {
|