parseman 0.59.3 → 0.60.1
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 +876 -190
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/cli/index.js +876 -190
- 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 +896 -199
- package/dist/index.js.map +3 -3
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.js +903 -201
- 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 +15 -1
- 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 +1 -1
- package/dist/table/compile-rule-map.d.ts.map +1 -1
- package/dist/table/compile.d.ts +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 +0 -35
- 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 +926 -201
- package/dist/table/index.js.map +3 -3
- package/dist/table/lex-program.d.ts.map +1 -1
- package/dist/table/ops.d.ts +35 -16
- 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 +2 -4
- 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 +176 -30
- package/src/table/child-slots.ts +8 -3
- package/src/table/compile-rule-map.ts +7 -4
- package/src/table/compile.ts +1 -1
- package/src/table/emit-assembly.ts +184 -33
- package/src/table/emit.ts +6 -4
- package/src/table/encode.ts +469 -74
- package/src/table/exec.ts +38 -82
- 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 +38 -16
- 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/table/encode-baseline.d.ts +0 -16
- package/dist/table/encode-baseline.d.ts.map +0 -1
- package/dist/table/exec-baseline.d.ts +0 -9
- package/dist/table/exec-baseline.d.ts.map +0 -1
- package/src/table/encode-baseline.ts +0 -346
- package/src/table/exec-baseline.ts +0 -557
package/dist/cli/index.js
CHANGED
|
@@ -35,15 +35,56 @@ function implicitLeadsDropped(ranges) {
|
|
|
35
35
|
return out;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
// src/combinators/trivia-boundary.ts
|
|
39
|
+
var MAX_DEPTH = 12;
|
|
40
|
+
function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
|
|
41
|
+
if (depth === 0) return true;
|
|
42
|
+
const d = p._def;
|
|
43
|
+
switch (d.tag) {
|
|
44
|
+
// Multi-term forms: the gaps BETWEEN terms are the ambient-trivia positions.
|
|
45
|
+
case "sequence":
|
|
46
|
+
return d.parsers.length > 1;
|
|
47
|
+
case "many":
|
|
48
|
+
case "oneOrMore":
|
|
49
|
+
case "sepBy":
|
|
50
|
+
return true;
|
|
51
|
+
// Transparent wrappers — they add no position, so ask what they wrap.
|
|
52
|
+
case "node":
|
|
53
|
+
case "transform":
|
|
54
|
+
case "leaf":
|
|
55
|
+
case "label":
|
|
56
|
+
case "field":
|
|
57
|
+
case "token":
|
|
58
|
+
case "attempt":
|
|
59
|
+
case "optional":
|
|
60
|
+
case "expect":
|
|
61
|
+
case "withCtx":
|
|
62
|
+
case "recover":
|
|
63
|
+
case "trivia":
|
|
64
|
+
return hasOwnTriviaBoundary(d.parser, depth - 1);
|
|
65
|
+
// An alternation adds no position either, but ONE arm that has one is enough
|
|
66
|
+
// to make the scope meaningful for this rule.
|
|
67
|
+
case "choice":
|
|
68
|
+
return d.parsers.some((a) => hasOwnTriviaBoundary(a, depth - 1));
|
|
69
|
+
default:
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function triviaThroughRef(ref2, target, trivia2) {
|
|
74
|
+
if (trivia2 !== void 0 && trivia2 !== null) return trivia2;
|
|
75
|
+
const amb = ref2._meta.grammarTrivia ?? target._meta.grammarTrivia;
|
|
76
|
+
return amb !== void 0 && hasOwnTriviaBoundary(target) ? amb : trivia2;
|
|
77
|
+
}
|
|
78
|
+
|
|
38
79
|
// src/combinators/first-set.ts
|
|
39
|
-
function classifyFinalChoice(arms, resolve2, activeTrivia) {
|
|
80
|
+
function classifyFinalChoice(arms, resolve2, activeTrivia, consuming = true, constructionSets = false) {
|
|
40
81
|
const firstSets = [];
|
|
41
82
|
const nullable2 = [];
|
|
42
83
|
let exclusive = true;
|
|
43
84
|
for (const arm of arms) {
|
|
44
85
|
const empty2 = matchesEmpty(arm, /* @__PURE__ */ new Set(), resolve2);
|
|
45
86
|
nullable2.push(empty2);
|
|
46
|
-
firstSets.push(empty2 ? { kind: "any" } : firstSetOf(arm, /* @__PURE__ */ new Set(), resolve2, activeTrivia));
|
|
87
|
+
firstSets.push(empty2 ? { kind: "any" } : constructionSets ? arm._meta.firstSet : firstSetOf(arm, /* @__PURE__ */ new Set(), resolve2, activeTrivia, consuming));
|
|
47
88
|
if (empty2) exclusive = false;
|
|
48
89
|
}
|
|
49
90
|
if (exclusive) {
|
|
@@ -228,7 +269,7 @@ function narrowBy(acc, constraint) {
|
|
|
228
269
|
function applyAssertion(fs, assertion) {
|
|
229
270
|
return assertion === null ? fs : fs.kind === "empty" ? assertion : narrowBy(fs, assertion);
|
|
230
271
|
}
|
|
231
|
-
function sequenceSet(parsers, fs, empties, trivia2) {
|
|
272
|
+
function sequenceSet(parsers, fs, empties, trivia2, consuming = true) {
|
|
232
273
|
const afterBoundary = (i) => {
|
|
233
274
|
const rest = at(i);
|
|
234
275
|
return trivia2 ? union(rest, fs(trivia2)) : rest;
|
|
@@ -244,24 +285,24 @@ function sequenceSet(parsers, fs, empties, trivia2) {
|
|
|
244
285
|
}
|
|
245
286
|
const first = fs(p);
|
|
246
287
|
if (!empties(p) || i + 1 === parsers.length) return first;
|
|
247
|
-
return union(first, afterBoundary(i + 1));
|
|
288
|
+
return union((consuming ? p._meta.consumingFirstSet : void 0) ?? first, afterBoundary(i + 1));
|
|
248
289
|
};
|
|
249
290
|
return at(0);
|
|
250
291
|
}
|
|
251
292
|
function sequenceFirstSet(parsers) {
|
|
252
|
-
return sequenceSet(parsers, (p) => p._meta.firstSet, matchesEmpty);
|
|
293
|
+
return sequenceSet(parsers, (p) => p._meta.firstSet, matchesEmpty, void 0, false);
|
|
253
294
|
}
|
|
254
|
-
function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve2, activeTrivia) {
|
|
295
|
+
function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve2, activeTrivia, consuming = true) {
|
|
255
296
|
if (seen.has(p)) return any();
|
|
256
297
|
seen.add(p);
|
|
257
298
|
try {
|
|
258
|
-
return firstSetBody(p, seen, resolve2, activeTrivia);
|
|
299
|
+
return firstSetBody(p, seen, resolve2, activeTrivia, consuming);
|
|
259
300
|
} finally {
|
|
260
301
|
seen.delete(p);
|
|
261
302
|
}
|
|
262
303
|
}
|
|
263
|
-
function firstSetBody(p, seen, resolve2, activeTrivia) {
|
|
264
|
-
const fs = (c) => firstSetOf(c, seen, resolve2, activeTrivia);
|
|
304
|
+
function firstSetBody(p, seen, resolve2, activeTrivia, consuming) {
|
|
305
|
+
const fs = (c) => firstSetOf(c, seen, resolve2, activeTrivia, consuming);
|
|
265
306
|
const empties = (c) => matchesEmpty(c, /* @__PURE__ */ new Set(), resolve2);
|
|
266
307
|
const d = p._def;
|
|
267
308
|
switch (d.tag) {
|
|
@@ -273,13 +314,16 @@ function firstSetBody(p, seen, resolve2, activeTrivia) {
|
|
|
273
314
|
case "dispatch":
|
|
274
315
|
return fs(d.selector);
|
|
275
316
|
case "lazy": {
|
|
276
|
-
|
|
277
|
-
if (
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
317
|
+
let target = winnerForRef(p, resolve2);
|
|
318
|
+
if (target === void 0) {
|
|
319
|
+
try {
|
|
320
|
+
target = d.thunk();
|
|
321
|
+
} catch {
|
|
322
|
+
return any();
|
|
323
|
+
}
|
|
282
324
|
}
|
|
325
|
+
const through = activeTrivia === null && resolve2 !== void 0;
|
|
326
|
+
return firstSetOf(target, seen, resolve2, through ? triviaThroughRef(p, target, null) : activeTrivia, consuming);
|
|
283
327
|
}
|
|
284
328
|
case "choice": {
|
|
285
329
|
let out = empty();
|
|
@@ -287,7 +331,7 @@ function firstSetBody(p, seen, resolve2, activeTrivia) {
|
|
|
287
331
|
return out;
|
|
288
332
|
}
|
|
289
333
|
case "sequence": {
|
|
290
|
-
return sequenceSet(d.parsers, fs, empties, activeTrivia);
|
|
334
|
+
return sequenceSet(d.parsers, fs, empties, activeTrivia, consuming);
|
|
291
335
|
}
|
|
292
336
|
case "peek": {
|
|
293
337
|
const inner = d.parser;
|
|
@@ -299,7 +343,6 @@ function firstSetBody(p, seen, resolve2, activeTrivia) {
|
|
|
299
343
|
case "transform":
|
|
300
344
|
case "label":
|
|
301
345
|
case "trivia":
|
|
302
|
-
case "token":
|
|
303
346
|
case "leaf":
|
|
304
347
|
case "node":
|
|
305
348
|
case "sepBy":
|
|
@@ -309,12 +352,16 @@ function firstSetBody(p, seen, resolve2, activeTrivia) {
|
|
|
309
352
|
// with a rule reference — resolve through it like any other wrapper.
|
|
310
353
|
case "attempt":
|
|
311
354
|
return fs(d.parser);
|
|
355
|
+
// A token runs its body with trivia cleared (`token.ts`).
|
|
356
|
+
case "token":
|
|
357
|
+
return firstSetOf(d.parser, seen, resolve2, activeTrivia === void 0 ? void 0 : null, consuming);
|
|
312
358
|
case "grammar":
|
|
313
359
|
return firstSetOf(
|
|
314
360
|
d.parser,
|
|
315
361
|
seen,
|
|
316
362
|
resolve2,
|
|
317
|
-
d.clearTrivia ? null : d.triviaParser ?? activeTrivia
|
|
363
|
+
d.clearTrivia ? null : d.triviaParser ?? activeTrivia,
|
|
364
|
+
consuming
|
|
318
365
|
);
|
|
319
366
|
// A run starts with its first line's prefix; a nullable prefix starts with anything.
|
|
320
367
|
case "lines": {
|
|
@@ -2052,10 +2099,6 @@ function scanTriviaCompact(input, cur, ctx) {
|
|
|
2052
2099
|
const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
|
|
2053
2100
|
return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
|
|
2054
2101
|
}
|
|
2055
|
-
function scanTrivia(input, cur, ctx) {
|
|
2056
|
-
const scan = scanTriviaCompact(input, cur, ctx);
|
|
2057
|
-
return typeof scan === "number" ? { end: scan, commit: NOOP_COMMIT } : scan;
|
|
2058
|
-
}
|
|
2059
2102
|
function skipTriviaScanned(s, input, cur, ctx) {
|
|
2060
2103
|
const end = s(input, cur);
|
|
2061
2104
|
if (end !== cur) {
|
|
@@ -2828,42 +2871,6 @@ function keywords(words, opts = {}) {
|
|
|
2828
2871
|
};
|
|
2829
2872
|
}
|
|
2830
2873
|
|
|
2831
|
-
// src/combinators/trivia-boundary.ts
|
|
2832
|
-
var MAX_DEPTH = 12;
|
|
2833
|
-
function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
|
|
2834
|
-
if (depth === 0) return true;
|
|
2835
|
-
const d = p._def;
|
|
2836
|
-
switch (d.tag) {
|
|
2837
|
-
// Multi-term forms: the gaps BETWEEN terms are the ambient-trivia positions.
|
|
2838
|
-
case "sequence":
|
|
2839
|
-
return d.parsers.length > 1;
|
|
2840
|
-
case "many":
|
|
2841
|
-
case "oneOrMore":
|
|
2842
|
-
case "sepBy":
|
|
2843
|
-
return true;
|
|
2844
|
-
// Transparent wrappers — they add no position, so ask what they wrap.
|
|
2845
|
-
case "node":
|
|
2846
|
-
case "transform":
|
|
2847
|
-
case "leaf":
|
|
2848
|
-
case "label":
|
|
2849
|
-
case "field":
|
|
2850
|
-
case "token":
|
|
2851
|
-
case "attempt":
|
|
2852
|
-
case "optional":
|
|
2853
|
-
case "expect":
|
|
2854
|
-
case "withCtx":
|
|
2855
|
-
case "recover":
|
|
2856
|
-
case "trivia":
|
|
2857
|
-
return hasOwnTriviaBoundary(d.parser, depth - 1);
|
|
2858
|
-
// An alternation adds no position either, but ONE arm that has one is enough
|
|
2859
|
-
// to make the scope meaningful for this rule.
|
|
2860
|
-
case "choice":
|
|
2861
|
-
return d.parsers.some((a) => hasOwnTriviaBoundary(a, depth - 1));
|
|
2862
|
-
default:
|
|
2863
|
-
return false;
|
|
2864
|
-
}
|
|
2865
|
-
}
|
|
2866
|
-
|
|
2867
2874
|
// src/compiler/token-alphabet.ts
|
|
2868
2875
|
function optionalSuffixLexBody(ir) {
|
|
2869
2876
|
if (ir.kind !== "sequence" || ir.parts.length !== 2) return void 0;
|
|
@@ -3121,6 +3128,7 @@ function directFixedLexNode(parser2, resolve2, active, pureOnly = false, cleared
|
|
|
3121
3128
|
arms,
|
|
3122
3129
|
parsers: def.parsers,
|
|
3123
3130
|
cleared,
|
|
3131
|
+
disjoint: def.disjoint,
|
|
3124
3132
|
armExpected: def.parsers.map(deriveExpected),
|
|
3125
3133
|
expected: def.parsers.flatMap(deriveExpected)
|
|
3126
3134
|
};
|
|
@@ -3471,10 +3479,12 @@ function parseRegex(src, unicode = false, sets = false) {
|
|
|
3471
3479
|
const parseGroup = () => {
|
|
3472
3480
|
i++;
|
|
3473
3481
|
let lookaround = false;
|
|
3482
|
+
let lookahead = false;
|
|
3474
3483
|
if (src[i] === "?") {
|
|
3475
3484
|
const c1 = src[i + 1];
|
|
3476
3485
|
if (c1 === ":") i += 2;
|
|
3477
3486
|
else if (c1 === "=" || c1 === "!") {
|
|
3487
|
+
lookahead = c1 === "=";
|
|
3478
3488
|
i += 2;
|
|
3479
3489
|
lookaround = true;
|
|
3480
3490
|
} else if (c1 === "<") {
|
|
@@ -3492,7 +3502,8 @@ function parseRegex(src, unicode = false, sets = false) {
|
|
|
3492
3502
|
const inner = parseAlt();
|
|
3493
3503
|
if (src[i] !== ")") throw BAIL;
|
|
3494
3504
|
i++;
|
|
3495
|
-
|
|
3505
|
+
if (lookaround) return lookahead ? { t: "empty", look: inner } : EMPTY2;
|
|
3506
|
+
return inner;
|
|
3496
3507
|
};
|
|
3497
3508
|
const parseClass = () => {
|
|
3498
3509
|
let k = i + 1;
|
|
@@ -3685,6 +3696,13 @@ function regexCanMatchEmpty(source) {
|
|
|
3685
3696
|
return true;
|
|
3686
3697
|
}
|
|
3687
3698
|
}
|
|
3699
|
+
function consumingFirstSetFromRegex(source, flags = "") {
|
|
3700
|
+
try {
|
|
3701
|
+
return firstSet(parseRegex(source, flags.includes("u") || flags.includes("v"), flags.includes("v")));
|
|
3702
|
+
} catch {
|
|
3703
|
+
return any();
|
|
3704
|
+
}
|
|
3705
|
+
}
|
|
3688
3706
|
function firstSetFromRegex(source, flags = "") {
|
|
3689
3707
|
let ast;
|
|
3690
3708
|
try {
|
|
@@ -3695,6 +3713,20 @@ function firstSetFromRegex(source, flags = "") {
|
|
|
3695
3713
|
if (nullable(ast)) return { firstSet: any(), canMatchNewline: canConsumeNewline(ast) };
|
|
3696
3714
|
return { firstSet: firstSet(ast), canMatchNewline: canConsumeNewline(ast) };
|
|
3697
3715
|
}
|
|
3716
|
+
function regexFirstTwo(source, flags = "") {
|
|
3717
|
+
let ast;
|
|
3718
|
+
try {
|
|
3719
|
+
ast = parseRegex(source, flags.includes("u") || flags.includes("v"), flags.includes("v"));
|
|
3720
|
+
} catch {
|
|
3721
|
+
return void 0;
|
|
3722
|
+
}
|
|
3723
|
+
const parts = ast.t === "seq" ? ast.parts : [ast];
|
|
3724
|
+
const a = parts[0];
|
|
3725
|
+
const b = parts[1];
|
|
3726
|
+
if (a === void 0 || a.t !== "char" || a.set.kind !== "ranges" || b === void 0) return void 0;
|
|
3727
|
+
const second = b.t === "char" ? b.set : b.t === "empty" && b.look !== void 0 && !nullable(b.look) ? firstSet(b.look) : void 0;
|
|
3728
|
+
return second !== void 0 && second.kind === "ranges" ? { first: a.set, second } : void 0;
|
|
3729
|
+
}
|
|
3698
3730
|
|
|
3699
3731
|
// src/analysis/commitment.ts
|
|
3700
3732
|
function mayFail(p, seen = /* @__PURE__ */ new Set()) {
|
|
@@ -4540,9 +4572,9 @@ function many(combinator, opts = {}) {
|
|
|
4540
4572
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
4541
4573
|
isTrivia: false
|
|
4542
4574
|
};
|
|
4543
|
-
const def = { tag: "many", parser: combinator, min: 0, ...max === Infinity ? {} : { max } };
|
|
4544
|
-
let expected;
|
|
4545
4575
|
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
4576
|
+
const def = { tag: "many", parser: combinator, min: 0, ...max === Infinity ? {} : { max }, ...guardable ? { guarded: true } : {} };
|
|
4577
|
+
let expected;
|
|
4546
4578
|
const scalarChild = scalarOf(combinator);
|
|
4547
4579
|
const parseScalar = (input, pos, ctx) => repeatScalarTail(combinator, scalarChild, input, pos, ctx, guardable, def.valueUnused ? void 0 : [], max);
|
|
4548
4580
|
return {
|
|
@@ -4589,9 +4621,9 @@ function atLeast(combinator, min, max) {
|
|
|
4589
4621
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
4590
4622
|
isTrivia: false
|
|
4591
4623
|
};
|
|
4592
|
-
const def = { tag: "oneOrMore", parser: combinator, min, ...max === Infinity ? {} : { max } };
|
|
4593
|
-
let expected;
|
|
4594
4624
|
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
4625
|
+
const def = { tag: "oneOrMore", parser: combinator, min, ...max === Infinity ? {} : { max }, ...guardable ? { guarded: true } : {} };
|
|
4626
|
+
let expected;
|
|
4595
4627
|
const scalarChild = scalarOf(combinator);
|
|
4596
4628
|
const parseScalar = (input, pos, ctx) => {
|
|
4597
4629
|
let cur = scalarChild(input, pos, ctx);
|
|
@@ -5063,9 +5095,14 @@ function regex(pattern, flags = "") {
|
|
|
5063
5095
|
const anchored = new RegExp(source, "y" + resolvedFlags.replace(/[gy]/g, ""));
|
|
5064
5096
|
const scan = shortScanner(source, resolvedFlags);
|
|
5065
5097
|
const raw = firstSetFromRegex(source, resolvedFlags);
|
|
5066
|
-
const
|
|
5098
|
+
const forFlags = (fs) => !resolvedFlags.includes("i") ? fs : resolvedFlags.includes("u") || resolvedFlags.includes("v") ? any() : asciiCaseFold(fs);
|
|
5099
|
+
const firstSet2 = forFlags(raw.firstSet);
|
|
5067
5100
|
const canMatchNewline = raw.canMatchNewline;
|
|
5068
5101
|
const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
|
|
5102
|
+
if (firstSet2.kind === "any" && regexCanMatchEmpty(source)) {
|
|
5103
|
+
const consuming = forFlags(consumingFirstSetFromRegex(source, resolvedFlags));
|
|
5104
|
+
if (consuming.kind !== "any") meta.consumingFirstSet = consuming;
|
|
5105
|
+
}
|
|
5069
5106
|
const def = { tag: "regex", source, flags: resolvedFlags };
|
|
5070
5107
|
const expected = directTerminalFailureExpected(def);
|
|
5071
5108
|
const parseScalar = (input, pos, ctx) => {
|
|
@@ -5340,14 +5377,15 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
5340
5377
|
return end < 0 ? next(input, pos) : end;
|
|
5341
5378
|
};
|
|
5342
5379
|
}
|
|
5343
|
-
let tail = (
|
|
5380
|
+
let tail = (input, pos, ctx, _lead, acc, _best, entered) => {
|
|
5381
|
+
if (!entered && ctx._probe !== void 0) for (const arm of arms) arm.run(input, pos, ctx);
|
|
5344
5382
|
ctx._fe = pos;
|
|
5345
5383
|
ctx._fx = acc ?? choiceExpected;
|
|
5346
5384
|
return -1;
|
|
5347
5385
|
};
|
|
5348
5386
|
for (let i = arms.length - 1; i >= 0; i--) {
|
|
5349
5387
|
const armRun = arms[i].run, cls = classes[i], staticExpected = armExpected[i], next = tail;
|
|
5350
|
-
tail = (input, pos, ctx, lead2, acc, best) => {
|
|
5388
|
+
tail = (input, pos, ctx, lead2, acc, best, entered) => {
|
|
5351
5389
|
if (cls !== void 0 && !classHas(cls, lead2)) {
|
|
5352
5390
|
return next(
|
|
5353
5391
|
input,
|
|
@@ -5355,7 +5393,8 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
5355
5393
|
ctx,
|
|
5356
5394
|
lead2,
|
|
5357
5395
|
best === pos ? appendExpected(acc, staticExpected) : acc,
|
|
5358
|
-
best
|
|
5396
|
+
best,
|
|
5397
|
+
entered
|
|
5359
5398
|
);
|
|
5360
5399
|
}
|
|
5361
5400
|
ctx._fc = false;
|
|
@@ -5371,7 +5410,7 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
5371
5410
|
if (nextAcc !== void 0) ctx._fx = nextAcc;
|
|
5372
5411
|
return -1;
|
|
5373
5412
|
}
|
|
5374
|
-
return next(input, pos, ctx, lead2, nextAcc, best);
|
|
5413
|
+
return next(input, pos, ctx, lead2, nextAcc, best, true);
|
|
5375
5414
|
};
|
|
5376
5415
|
}
|
|
5377
5416
|
return {
|
|
@@ -5382,7 +5421,8 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
5382
5421
|
ctx,
|
|
5383
5422
|
pos < input.length ? input.codePointAt(pos) : -1,
|
|
5384
5423
|
void 0,
|
|
5385
|
-
pos
|
|
5424
|
+
pos,
|
|
5425
|
+
false
|
|
5386
5426
|
)
|
|
5387
5427
|
};
|
|
5388
5428
|
}
|
|
@@ -5420,6 +5460,7 @@ function exclusiveChoiceNode(arms, classes, choiceFx) {
|
|
|
5420
5460
|
return -1;
|
|
5421
5461
|
}
|
|
5422
5462
|
}
|
|
5463
|
+
if (arm < 0 && ctx._probe !== void 0) for (const a of arms) a.run(input, pos, ctx);
|
|
5423
5464
|
ctx._fe = pos;
|
|
5424
5465
|
ctx._fx = choiceFx;
|
|
5425
5466
|
return -1;
|
|
@@ -5644,6 +5685,7 @@ function buildLexProgramRunner(spec, matchers, classes, expected) {
|
|
|
5644
5685
|
if (!classHas(cls, lead2)) {
|
|
5645
5686
|
ctx._fe = pos;
|
|
5646
5687
|
ctx._fx = choiceFx.slice();
|
|
5688
|
+
if (ctx._probe !== void 0) failAt(ctx, [...x0, ...x1, ...x2, ...x3], pos);
|
|
5647
5689
|
return -1;
|
|
5648
5690
|
}
|
|
5649
5691
|
let acc;
|
|
@@ -5755,7 +5797,7 @@ function validateDispatchSpec(spec, arity, fallbackRouted) {
|
|
|
5755
5797
|
for (const arm of arms) if (!Number.isInteger(arm) || arm < 0 || arm >= arity) return true;
|
|
5756
5798
|
return false;
|
|
5757
5799
|
};
|
|
5758
|
-
if (spec === void 0 || !Number.isInteger(arity) || arity < 0 || fallbackRouted
|
|
5800
|
+
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]]))) {
|
|
5759
5801
|
throw new TypeError("table: malformed dispatch");
|
|
5760
5802
|
}
|
|
5761
5803
|
}
|
|
@@ -6069,7 +6111,7 @@ function sequence(...parsers) {
|
|
|
6069
6111
|
if (tolerant) {
|
|
6070
6112
|
followSentinels ??= parsers.map((_, i) => firstSetSentinel(
|
|
6071
6113
|
parsers.slice(i + 1).reduce(
|
|
6072
|
-
(set, parser2) => union(set, firstSetOf(parser2)),
|
|
6114
|
+
(set, parser2) => union(set, firstSetOf(parser2, /* @__PURE__ */ new Set(), void 0, void 0, false)),
|
|
6073
6115
|
{ kind: "empty" }
|
|
6074
6116
|
)
|
|
6075
6117
|
));
|
|
@@ -6788,7 +6830,7 @@ function attempt(parser2, options) {
|
|
|
6788
6830
|
return {
|
|
6789
6831
|
_tag: "attempt",
|
|
6790
6832
|
_meta: parser2._meta,
|
|
6791
|
-
_def:
|
|
6833
|
+
_def: { tag: "attempt", parser: parser2, ...contain ? { contain: true } : {}, ...guardable ? { guarded: true } : {} },
|
|
6792
6834
|
parse(input, pos, ctx) {
|
|
6793
6835
|
if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(parser2, input, pos)) {
|
|
6794
6836
|
if (failExpected === void 0) {
|
|
@@ -6814,6 +6856,7 @@ function attempt(parser2, options) {
|
|
|
6814
6856
|
}
|
|
6815
6857
|
|
|
6816
6858
|
// src/table/factor-choice.ts
|
|
6859
|
+
var factoredChoices = /* @__PURE__ */ new WeakSet();
|
|
6817
6860
|
var DERIVED = /* @__PURE__ */ new Set(["_tag", "_meta", "_def", "_parseScalar", "_stickyRegex", "parse"]);
|
|
6818
6861
|
function isCombinator(v) {
|
|
6819
6862
|
return typeof v === "object" && v !== null && "_def" in v && "_meta" in v;
|
|
@@ -6905,6 +6948,7 @@ function factorSharedEnds(d) {
|
|
|
6905
6948
|
for (let i = at + 1; i < n; i++) if (!never(first.terms[i])) return void 0;
|
|
6906
6949
|
if (arms.some((a) => mayCommitFailure(a))) return void 0;
|
|
6907
6950
|
const middle = choice(...shapes.map((s) => s.terms[at]));
|
|
6951
|
+
factoredChoices.add(middle);
|
|
6908
6952
|
if (middle._def.tag === "choice" && middle._def.autoNot.some((a) => a !== null)) return void 0;
|
|
6909
6953
|
const st = middle._def.tag === "choice" ? middle._def.strategy : void 0;
|
|
6910
6954
|
if (st === void 0 || st.tag !== "firstMatch" && st.tag !== "sharedPrefix" && !(st.tag === "literalsLongestFirst" && st.sortedIndices.every((x, i) => x === i))) return void 0;
|
|
@@ -6917,6 +6961,37 @@ function factorSharedEnds(d) {
|
|
|
6917
6961
|
for (let j = first.wrappers.length - 1; j >= 0 && out !== void 0; j--) out = rewrap(first.wrappers[j], out);
|
|
6918
6962
|
return out === void 0 ? void 0 : attempt(out);
|
|
6919
6963
|
}
|
|
6964
|
+
function factorPrefixArms(d) {
|
|
6965
|
+
const arms = d.parsers;
|
|
6966
|
+
if (arms.length < 2) return void 0;
|
|
6967
|
+
if (d.strategy.tag !== "firstMatch" && d.strategy.tag !== "sharedPrefix") return void 0;
|
|
6968
|
+
if (d.gates.some((g) => g !== null) || d.autoNot.some((a) => a !== null)) return void 0;
|
|
6969
|
+
const out = [...arms];
|
|
6970
|
+
let changed = false;
|
|
6971
|
+
for (let i = 0; i + 1 < arms.length; i++) {
|
|
6972
|
+
const arm = arms[i];
|
|
6973
|
+
if (arm._def.tag !== "sequence" || arm._def.valueUnused !== true) continue;
|
|
6974
|
+
const terms = arm._def.parsers;
|
|
6975
|
+
const next = arms[i + 1];
|
|
6976
|
+
const prefix = next._def.tag === "sequence" && next._def.valueUnused === true ? next._def.parsers : [next];
|
|
6977
|
+
if (prefix.length >= terms.length) continue;
|
|
6978
|
+
if (!prefix.every((t2, j) => sameComb(t2, terms[j], 0))) continue;
|
|
6979
|
+
const rest = terms.slice(prefix.length);
|
|
6980
|
+
if (rest.every(never)) continue;
|
|
6981
|
+
const tail = rest.length === 1 ? rest[0] : sequence(...rest);
|
|
6982
|
+
if (tail !== rest[0]) tail._def.valueUnused = true;
|
|
6983
|
+
const parts = [...terms.slice(0, prefix.length), optional(tail)];
|
|
6984
|
+
const seq = sequence(...parts);
|
|
6985
|
+
seq._def.valueUnused = true;
|
|
6986
|
+
out[i] = seq;
|
|
6987
|
+
changed = true;
|
|
6988
|
+
}
|
|
6989
|
+
if (!changed) return void 0;
|
|
6990
|
+
const rebuilt = choice(...out);
|
|
6991
|
+
factoredChoices.add(rebuilt);
|
|
6992
|
+
const st = rebuilt._def.tag === "choice" ? rebuilt._def.strategy : void 0;
|
|
6993
|
+
return st !== void 0 && (st.tag === "firstMatch" || st.tag === "sharedPrefix") ? rebuilt : void 0;
|
|
6994
|
+
}
|
|
6920
6995
|
|
|
6921
6996
|
// src/compiler/fields.ts
|
|
6922
6997
|
function buildReadsFields(def) {
|
|
@@ -7033,6 +7108,9 @@ var OP_LEX_BODY = 42;
|
|
|
7033
7108
|
var OP_LEX_PROGRAM = 43;
|
|
7034
7109
|
var OP_SOURCE_LEAF = 44;
|
|
7035
7110
|
var OP_RGATE = 45;
|
|
7111
|
+
var OP_GAPGATE = 46;
|
|
7112
|
+
var OP_RGATE2 = 47;
|
|
7113
|
+
var OP_STRICT = 48;
|
|
7036
7114
|
var OP_DISPATCH = 25;
|
|
7037
7115
|
var OP_ROUTED = 26;
|
|
7038
7116
|
var OP_NAMES = {
|
|
@@ -7080,7 +7158,10 @@ var OP_NAMES = {
|
|
|
7080
7158
|
[OP_COV]: "COV",
|
|
7081
7159
|
[OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
|
|
7082
7160
|
[OP_LEX_BODY]: "LEX_BODY",
|
|
7083
|
-
[OP_LEX_PROGRAM]: "LEX_PROGRAM"
|
|
7161
|
+
[OP_LEX_PROGRAM]: "LEX_PROGRAM",
|
|
7162
|
+
[OP_GAPGATE]: "GAPGATE",
|
|
7163
|
+
[OP_RGATE2]: "RGATE2",
|
|
7164
|
+
[OP_STRICT]: "STRICT"
|
|
7084
7165
|
};
|
|
7085
7166
|
|
|
7086
7167
|
// src/combinators/node.ts
|
|
@@ -7125,7 +7206,7 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
7125
7206
|
if (project !== void 0 && build !== void 0) {
|
|
7126
7207
|
throw new Error("node() options cannot combine project with a build callback");
|
|
7127
7208
|
}
|
|
7128
|
-
const baseDef = { tag: "node", parser: combinator, ...type === void 0 ? {} : { type }, ...build === void 0 ? {} : { build } };
|
|
7209
|
+
const baseDef = { tag: "node", parser: combinator, ...type === void 0 ? {} : { type }, ...build === void 0 ? {} : { build }, ...combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator) ? { guarded: true } : {} };
|
|
7129
7210
|
const meta = {
|
|
7130
7211
|
firstSet: combinator._meta.firstSet,
|
|
7131
7212
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
@@ -7248,6 +7329,29 @@ var UnsupportedConstruct = class extends Error {
|
|
|
7248
7329
|
this.tag = tag;
|
|
7249
7330
|
}
|
|
7250
7331
|
};
|
|
7332
|
+
function firstTwo(p) {
|
|
7333
|
+
const d = p._def;
|
|
7334
|
+
if (d.tag === "label" || d.tag === "grammar") return firstTwo(d.parser);
|
|
7335
|
+
let two;
|
|
7336
|
+
if (d.tag === "literal" && d.value.length >= 2 && d.caseInsensitive !== true) {
|
|
7337
|
+
const second = d.value.codePointAt(1);
|
|
7338
|
+
two = { first: { kind: "ranges", ranges: [{ lo: d.value.charCodeAt(0), hi: d.value.charCodeAt(0) }] }, second: { kind: "ranges", ranges: [{ lo: second, hi: second }] } };
|
|
7339
|
+
} else if (d.tag === "regex" && !d.flags.includes("i")) {
|
|
7340
|
+
const units = regexFirstTwo(d.source, d.flags);
|
|
7341
|
+
if (units !== void 0) two = units;
|
|
7342
|
+
}
|
|
7343
|
+
if (two === void 0 || two.first.kind !== "ranges") return void 0;
|
|
7344
|
+
return two.first.ranges.every((r) => r.hi < 55296 || r.lo > 57343 && r.hi <= 65535) ? two : void 0;
|
|
7345
|
+
}
|
|
7346
|
+
var GAP_CHARS = /* @__PURE__ */ new Set([9, 10, 12, 13, 32, 47]);
|
|
7347
|
+
function isGap(p) {
|
|
7348
|
+
if (matchesEmpty(p)) return true;
|
|
7349
|
+
const fs = p._meta.firstSet;
|
|
7350
|
+
return fs.kind === "ranges" && fs.ranges.every((r) => {
|
|
7351
|
+
for (let c = r.lo; c <= r.hi; c++) if (!GAP_CHARS.has(c)) return false;
|
|
7352
|
+
return true;
|
|
7353
|
+
});
|
|
7354
|
+
}
|
|
7251
7355
|
var Encoder = class {
|
|
7252
7356
|
code = [];
|
|
7253
7357
|
k = [];
|
|
@@ -7295,8 +7399,33 @@ var Encoder = class {
|
|
|
7295
7399
|
*/
|
|
7296
7400
|
commitFailureMemo = /* @__PURE__ */ new Map();
|
|
7297
7401
|
labels = void 0;
|
|
7402
|
+
/** The choice being encoded as written, for `OP_STRICT`'s tolerant child. */
|
|
7403
|
+
unfactoredChoice = void 0;
|
|
7298
7404
|
/** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
|
|
7299
7405
|
activeTrivia = void 0;
|
|
7406
|
+
/**
|
|
7407
|
+
* Is the trivia live at this row known? It is not in the body of an entry
|
|
7408
|
+
* that installs none of its own: that body runs under whatever trivia its
|
|
7409
|
+
* caller has (a compiled rule inside another grammar, `run({ trivia })`).
|
|
7410
|
+
* Every scope (`parser({ trivia })`, `noTrivia`, `token()`, a rule's install)
|
|
7411
|
+
* makes it known again.
|
|
7412
|
+
*/
|
|
7413
|
+
triviaKnown = true;
|
|
7414
|
+
/**
|
|
7415
|
+
* The trivia a gate's first set is derived under: the live table, `null` for a
|
|
7416
|
+
* scope known to have none, or `undefined` where it is not known.
|
|
7417
|
+
*/
|
|
7418
|
+
gateTrivia() {
|
|
7419
|
+
return this.activeTrivia ?? (this.triviaKnown ? null : void 0);
|
|
7420
|
+
}
|
|
7421
|
+
/**
|
|
7422
|
+
* Whether a gate may read a nullable pad through its non-empty matches
|
|
7423
|
+
* (`firstSetOf`'s `consuming`): only where the trivia that may follow the pad
|
|
7424
|
+
* is known. Elsewhere a gate reads first sets as 0.58.0 did.
|
|
7425
|
+
*/
|
|
7426
|
+
gateConsuming() {
|
|
7427
|
+
return this.activeTrivia !== void 0 || this.triviaKnown;
|
|
7428
|
+
}
|
|
7300
7429
|
classified = false;
|
|
7301
7430
|
scans = [];
|
|
7302
7431
|
/** Ambient `scanSkip` sets, pooled by the ARRAY's identity (stable per grammar). */
|
|
@@ -7423,10 +7552,12 @@ var Encoder = class {
|
|
|
7423
7552
|
const final = classifyFinalChoice(
|
|
7424
7553
|
node2.parsers,
|
|
7425
7554
|
this.refResolver(),
|
|
7426
|
-
node2.cleared ?
|
|
7555
|
+
node2.cleared ? null : this.gateTrivia(),
|
|
7556
|
+
false,
|
|
7557
|
+
node2.disjoint
|
|
7427
7558
|
);
|
|
7428
7559
|
const classes = final.firstSets.map((first, i) => final.nullable[i] ? -1 : this.charClass(first));
|
|
7429
|
-
const exclusive = final.exclusive && classes.every((cls) => cls >= 0);
|
|
7560
|
+
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;
|
|
7430
7561
|
words.push(LEX_NODE_CHOICE, node2.arms.length, exclusive ? 1 : 0, this.expected(node2.expected));
|
|
7431
7562
|
for (let i = 0; i < node2.arms.length; i++) {
|
|
7432
7563
|
words.push(classes[i], this.expected(node2.armExpected[i]));
|
|
@@ -7581,16 +7712,117 @@ var Encoder = class {
|
|
|
7581
7712
|
kIndex = /* @__PURE__ */ new Map();
|
|
7582
7713
|
ccIndex = /* @__PURE__ */ new Map();
|
|
7583
7714
|
fxIndex = /* @__PURE__ */ new Map();
|
|
7584
|
-
/** Memoized by combinator identity: a shared sub-combinator is ONE row. */
|
|
7585
|
-
memo = /* @__PURE__ */ new Map();
|
|
7586
7715
|
/**
|
|
7587
|
-
*
|
|
7588
|
-
*
|
|
7589
|
-
*
|
|
7590
|
-
*
|
|
7716
|
+
* Memoized by combinator identity AND the trivia scope it is encoded under
|
|
7717
|
+
* (`scopeKey`): a shared sub-combinator is ONE row per scope it runs in.
|
|
7718
|
+
*
|
|
7719
|
+
* A construct's rows depend on that scope. A first set derived through a
|
|
7720
|
+
* nullable term takes in the trivia that may follow it, a gap gate holds only
|
|
7721
|
+
* where no trivia runs, a routed gate reads what may follow its token, and a
|
|
7722
|
+
* cross-rule reference installs its rule's trivia only from a cleared region
|
|
7723
|
+
* (`scopedRef`). One memo slot per combinator froze the FIRST scope it was
|
|
7724
|
+
* reached under onto every later one: a rule body encoded as an entry with no
|
|
7725
|
+
* trivia, then run under a caller's comment trivia, gated its repeats as if no
|
|
7726
|
+
* comment could come between their terms.
|
|
7591
7727
|
*/
|
|
7592
|
-
|
|
7728
|
+
memo = /* @__PURE__ */ new Map();
|
|
7593
7729
|
pending = /* @__PURE__ */ new Map();
|
|
7730
|
+
triviaSignatures = /* @__PURE__ */ new Map();
|
|
7731
|
+
/**
|
|
7732
|
+
* What of the live trivia an encoding can depend on: none, or its first set.
|
|
7733
|
+
* Every derivation reads trivia only through `firstSetOf(trivia)` or whether it
|
|
7734
|
+
* is live, so two scopes whose trivia opens on the same characters encode the
|
|
7735
|
+
* same rows and share them. A construct that reads no scope (`readsScope`)
|
|
7736
|
+
* has one encoding.
|
|
7737
|
+
*/
|
|
7738
|
+
scopeKey(p) {
|
|
7739
|
+
const t2 = this.activeTrivia;
|
|
7740
|
+
if (!this.readsScope(p)) return "";
|
|
7741
|
+
if (t2 === void 0) return this.triviaKnown ? "" : "?";
|
|
7742
|
+
let sig = this.triviaSignatures.get(t2);
|
|
7743
|
+
if (sig === void 0) {
|
|
7744
|
+
sig = `t${JSON.stringify(firstSetOf(t2, /* @__PURE__ */ new Set(), this.refResolver()))}`;
|
|
7745
|
+
this.triviaSignatures.set(t2, sig);
|
|
7746
|
+
}
|
|
7747
|
+
return sig;
|
|
7748
|
+
}
|
|
7749
|
+
readsScopeMemo = /* @__PURE__ */ new Map();
|
|
7750
|
+
/**
|
|
7751
|
+
* Can `p`'s rows depend on the trivia scope it is encoded under? No for a
|
|
7752
|
+
* terminal, a scope of its own (`parser({ trivia })`, `noTrivia`, `token()`),
|
|
7753
|
+
* and a wrapper over a construct that reads none; yes wherever a first set, a gate or
|
|
7754
|
+
* a reference's install is derived with the scope: a sequence with a nullable
|
|
7755
|
+
* term before another (the trivia between them), a routed arm (the trivia after
|
|
7756
|
+
* its token), a reference that installs its rule's trivia from a cleared
|
|
7757
|
+
* region, and anything not modelled here — a cycle included.
|
|
7758
|
+
*/
|
|
7759
|
+
readsScope(p) {
|
|
7760
|
+
const hit = this.readsScopeMemo.get(p);
|
|
7761
|
+
if (hit !== void 0) return hit;
|
|
7762
|
+
this.readsScopeMemo.set(p, true);
|
|
7763
|
+
const d = p._def;
|
|
7764
|
+
const rr = this.refResolver();
|
|
7765
|
+
let out;
|
|
7766
|
+
switch (d.tag) {
|
|
7767
|
+
case "literal":
|
|
7768
|
+
case "regex":
|
|
7769
|
+
case "keywords":
|
|
7770
|
+
case "token":
|
|
7771
|
+
out = false;
|
|
7772
|
+
break;
|
|
7773
|
+
// `routed()` encodes its fallback under the scope that reaches it.
|
|
7774
|
+
case "routed":
|
|
7775
|
+
out = d.fallback !== void 0 && this.readsScope(d.fallback);
|
|
7776
|
+
break;
|
|
7777
|
+
case "grammar":
|
|
7778
|
+
out = d.clearTrivia !== true && d.triviaParser === void 0 && this.readsScope(d.parser);
|
|
7779
|
+
break;
|
|
7780
|
+
case "node":
|
|
7781
|
+
case "label":
|
|
7782
|
+
case "leaf":
|
|
7783
|
+
case "transform":
|
|
7784
|
+
case "attempt":
|
|
7785
|
+
case "expect":
|
|
7786
|
+
case "not":
|
|
7787
|
+
case "peek":
|
|
7788
|
+
case "optional":
|
|
7789
|
+
case "many":
|
|
7790
|
+
case "oneOrMore":
|
|
7791
|
+
case "field":
|
|
7792
|
+
out = this.readsScope(d.parser);
|
|
7793
|
+
break;
|
|
7794
|
+
case "sepBy":
|
|
7795
|
+
out = this.readsScope(d.parser) || this.readsScope(d.separator);
|
|
7796
|
+
break;
|
|
7797
|
+
case "choice":
|
|
7798
|
+
out = d.parsers.some((a) => this.readsScope(a));
|
|
7799
|
+
break;
|
|
7800
|
+
case "dispatch":
|
|
7801
|
+
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);
|
|
7802
|
+
break;
|
|
7803
|
+
case "sequence": {
|
|
7804
|
+
const ps = d.parsers;
|
|
7805
|
+
out = ps.some((t2) => this.readsScope(t2)) || ps[0] !== void 0 && (ps[0]._def.tag === "routed" || ps[0]._def.tag === "regex" && isGap(ps[0])) || ps.some((t2, i) => i + 1 < ps.length && matchesEmpty(t2, /* @__PURE__ */ new Set(), rr));
|
|
7806
|
+
break;
|
|
7807
|
+
}
|
|
7808
|
+
case "lazy": {
|
|
7809
|
+
let target = winnerForRef(p, rr);
|
|
7810
|
+
if (target === void 0) {
|
|
7811
|
+
try {
|
|
7812
|
+
target = d.thunk();
|
|
7813
|
+
} catch {
|
|
7814
|
+
target = void 0;
|
|
7815
|
+
}
|
|
7816
|
+
}
|
|
7817
|
+
out = target === void 0 || triviaThroughRef(p, target, null) !== null || this.readsScope(target);
|
|
7818
|
+
break;
|
|
7819
|
+
}
|
|
7820
|
+
default:
|
|
7821
|
+
out = true;
|
|
7822
|
+
}
|
|
7823
|
+
this.readsScopeMemo.set(p, out);
|
|
7824
|
+
return out;
|
|
7825
|
+
}
|
|
7594
7826
|
settings;
|
|
7595
7827
|
/** Resolved once, HERE, at table-build time — never consulted at run time. */
|
|
7596
7828
|
track;
|
|
@@ -7618,7 +7850,7 @@ var Encoder = class {
|
|
|
7618
7850
|
let fs = { kind: "empty" };
|
|
7619
7851
|
const rr = this.refResolver();
|
|
7620
7852
|
for (let j = i + 1; j < parsers.length; j++) {
|
|
7621
|
-
fs = union(fs, firstSetOf(parsers[j], /* @__PURE__ */ new Set(), rr,
|
|
7853
|
+
fs = union(fs, firstSetOf(parsers[j], /* @__PURE__ */ new Set(), rr, void 0, false));
|
|
7622
7854
|
}
|
|
7623
7855
|
return this.charClass(fs);
|
|
7624
7856
|
}
|
|
@@ -7696,7 +7928,7 @@ var Encoder = class {
|
|
|
7696
7928
|
* simply parses it with the gate switched off at every choice arm that reaches
|
|
7697
7929
|
* a hole.
|
|
7698
7930
|
*
|
|
7699
|
-
* Measured on jess's less grammar (`
|
|
7931
|
+
* Measured on jess's less grammar (with the one-off `macro-program-diff` bench, last at `4a5d0341`): 195 of
|
|
7700
7932
|
* 562 reachable choice arms carried NO first set in the shipped artifact
|
|
7701
7933
|
* against 103 of 540 in the runtime encode, and 10 dispatch sites lost the O(1)
|
|
7702
7934
|
* `exclusive` piece (`assemble.ts:1758`) for the candidate-mask loop. With this
|
|
@@ -7786,7 +8018,7 @@ var Encoder = class {
|
|
|
7786
8018
|
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;
|
|
7787
8019
|
const rr = this.refResolver();
|
|
7788
8020
|
if (matchesEmpty(p, /* @__PURE__ */ new Set(), rr)) return child;
|
|
7789
|
-
const cls = this.charClass(firstSetOf(p, /* @__PURE__ */ new Set(), rr, this.activeTrivia));
|
|
8021
|
+
const cls = this.charClass(firstSetOf(p, /* @__PURE__ */ new Set(), rr, this.activeTrivia, false));
|
|
7790
8022
|
if (cls < 0) return child;
|
|
7791
8023
|
const e = deriveExpected(p);
|
|
7792
8024
|
return this.emit(OP_GATE, cls, child, this.expected(e.length > 0 ? e : [p._tag]));
|
|
@@ -7812,9 +8044,27 @@ var Encoder = class {
|
|
|
7812
8044
|
* `{`, `Call` at `}`). The resolved set is the one a choice arm's gate uses,
|
|
7813
8045
|
* over the final merged map.
|
|
7814
8046
|
*/
|
|
7815
|
-
|
|
8047
|
+
/**
|
|
8048
|
+
* The arms whose first set under `gateTrivia()` is wider than under the
|
|
8049
|
+
* active trivia alone — a reference's installed trivia read through from a
|
|
8050
|
+
* region with none. Empty for construction-set (disjoint) choices, whose
|
|
8051
|
+
* sets do not depend on trivia.
|
|
8052
|
+
*/
|
|
8053
|
+
wideArms(arms, wide, constructionSets, wideTrivia = this.gateTrivia(), base = this.activeTrivia) {
|
|
8054
|
+
if (constructionSets || wideTrivia === base) return [];
|
|
8055
|
+
const narrow = classifyFinalChoice(arms, this.refResolver(), base, false, false).firstSets;
|
|
8056
|
+
const out = [];
|
|
8057
|
+
for (let i = 0; i < arms.length; i++) {
|
|
8058
|
+
if (this.charClass(wide[i]) !== this.charClass(narrow[i])) out.push(i);
|
|
8059
|
+
}
|
|
8060
|
+
return out;
|
|
8061
|
+
}
|
|
8062
|
+
gateFirstSet(p, guarded, narrowed) {
|
|
7816
8063
|
const cached = p._meta.firstSet;
|
|
7817
|
-
|
|
8064
|
+
if (p._def.tag !== "lazy" && cached.kind !== "any") return cached;
|
|
8065
|
+
const rr = this.refResolver();
|
|
8066
|
+
if (guarded) return firstSetOf(p, /* @__PURE__ */ new Set(), rr, void 0, false);
|
|
8067
|
+
return firstSetOf(p, /* @__PURE__ */ new Set(), rr, this.gateTrivia(), narrowed && this.gateConsuming());
|
|
7818
8068
|
}
|
|
7819
8069
|
/**
|
|
7820
8070
|
* Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
|
|
@@ -7846,6 +8096,135 @@ var Encoder = class {
|
|
|
7846
8096
|
for (const w of words) this.code.push(w);
|
|
7847
8097
|
return ip;
|
|
7848
8098
|
}
|
|
8099
|
+
/**
|
|
8100
|
+
* An optional repeat item tests the item's class before it runs it (`OP_REP`
|
|
8101
|
+
* ip+7), wherever the item's own first-set gate would also run. So a sequence
|
|
8102
|
+
* item whose first term is a gate on that same class gets its own copy of the
|
|
8103
|
+
* sequence row with the gate's child as that term: the test runs once. The
|
|
8104
|
+
* shared row is left as it is for its other references.
|
|
8105
|
+
*/
|
|
8106
|
+
withoutLeadGate(seq, cls) {
|
|
8107
|
+
const op = this.code[seq];
|
|
8108
|
+
if (op !== OP_SEQ && op !== OP_SEQV) return seq;
|
|
8109
|
+
const first = this.code[seq + 2];
|
|
8110
|
+
if (this.code[first] !== OP_GATE || this.code[first + 1] !== cls) return seq;
|
|
8111
|
+
const n = this.code[seq + 1];
|
|
8112
|
+
const width = 1 + 2 * n;
|
|
8113
|
+
const head = this.emitHead(op, width);
|
|
8114
|
+
for (let i = 1; i <= width; i++) this.code[head + i] = this.code[seq + i];
|
|
8115
|
+
this.code[head + 2] = this.code[first + 2];
|
|
8116
|
+
return head;
|
|
8117
|
+
}
|
|
8118
|
+
/**
|
|
8119
|
+
* An optional repeat item that opens with a GAP — a regex that may match
|
|
8120
|
+
* empty, or one that starts only with whitespace or a comment's `/` — and
|
|
8121
|
+
* then a term with a finite first set gets an `OP_GAPGATE` row
|
|
8122
|
+
* (`gap-gate.ts`): the repeat reads the gap once, ends where the character
|
|
8123
|
+
* after it opens neither that term nor an arm without the gap, and hands the
|
|
8124
|
+
* gap's end to the regex row. Anything the walk cannot prove keeps the item as
|
|
8125
|
+
* written.
|
|
8126
|
+
*/
|
|
8127
|
+
gapGated(item, ip) {
|
|
8128
|
+
if (this.activeTrivia === void 0 && !this.triviaKnown) return ip;
|
|
8129
|
+
const lead2 = this.gapLead(item, this.activeTrivia, 0);
|
|
8130
|
+
if (lead2 === void 0) return ip;
|
|
8131
|
+
const cls = this.charClass(lead2.follow);
|
|
8132
|
+
if (cls < 0) return ip;
|
|
8133
|
+
const other = lead2.other.kind === "empty" ? -1 : this.charClass(lead2.other);
|
|
8134
|
+
if (lead2.other.kind !== "empty" && other < 0) return ip;
|
|
8135
|
+
const p = this.node(lead2.p).ip;
|
|
8136
|
+
if (this.code[p] !== OP_RX && this.code[p] !== OP_RX_TRACK) return ip;
|
|
8137
|
+
return this.emit(OP_GAPGATE, ip, p, cls, other);
|
|
8138
|
+
}
|
|
8139
|
+
/**
|
|
8140
|
+
* The gap an item opens with: the regex `p`, the first set `follow` of what
|
|
8141
|
+
* must come straight after it, and the first set `other` of choice arms that
|
|
8142
|
+
* do not open with `p`. Only through wrappers that consume nothing before
|
|
8143
|
+
* their body, a sequence's first term, and a choice's arms; the gap must sit
|
|
8144
|
+
* in a sequence with no trivia between its terms.
|
|
8145
|
+
*/
|
|
8146
|
+
gapLead(c, trivia2, depth) {
|
|
8147
|
+
if (depth > 24) return void 0;
|
|
8148
|
+
const rr = this.refResolver();
|
|
8149
|
+
const d = c._def;
|
|
8150
|
+
switch (d.tag) {
|
|
8151
|
+
case "lazy": {
|
|
8152
|
+
let target = winnerForRef(c, rr);
|
|
8153
|
+
if (target === void 0) {
|
|
8154
|
+
try {
|
|
8155
|
+
target = d.thunk();
|
|
8156
|
+
} catch {
|
|
8157
|
+
return void 0;
|
|
8158
|
+
}
|
|
8159
|
+
}
|
|
8160
|
+
return this.gapLead(target, triviaThroughRef(c, target, trivia2), depth + 1);
|
|
8161
|
+
}
|
|
8162
|
+
case "node":
|
|
8163
|
+
case "leaf":
|
|
8164
|
+
case "label":
|
|
8165
|
+
case "attempt":
|
|
8166
|
+
return this.gapLead(d.parser, trivia2, depth + 1);
|
|
8167
|
+
case "field":
|
|
8168
|
+
return d.leadingTrivia === true ? void 0 : this.gapLead(d.parser, trivia2, depth + 1);
|
|
8169
|
+
case "grammar":
|
|
8170
|
+
return this.gapLead(d.parser, d.clearTrivia === true ? null : d.triviaParser ?? trivia2, depth + 1);
|
|
8171
|
+
case "sequence": {
|
|
8172
|
+
const [first, ...rest] = d.parsers;
|
|
8173
|
+
if (first === void 0) return void 0;
|
|
8174
|
+
if (first._def.tag !== "regex" || !isGap(first)) {
|
|
8175
|
+
return this.gapLead(first, trivia2, depth + 1);
|
|
8176
|
+
}
|
|
8177
|
+
if (trivia2 !== void 0 && trivia2 !== null || rest.length === 0) return void 0;
|
|
8178
|
+
let follow = empty();
|
|
8179
|
+
let closed = false;
|
|
8180
|
+
for (const t2 of rest) {
|
|
8181
|
+
const fs = firstSetOf(t2, /* @__PURE__ */ new Set(), rr, null);
|
|
8182
|
+
if (fs.kind === "any") return void 0;
|
|
8183
|
+
follow = union(follow, fs);
|
|
8184
|
+
if (!matchesEmpty(t2, /* @__PURE__ */ new Set(), rr)) {
|
|
8185
|
+
closed = true;
|
|
8186
|
+
break;
|
|
8187
|
+
}
|
|
8188
|
+
}
|
|
8189
|
+
return closed ? { p: first, follow, other: empty() } : void 0;
|
|
8190
|
+
}
|
|
8191
|
+
case "choice": {
|
|
8192
|
+
let p;
|
|
8193
|
+
let follow = empty();
|
|
8194
|
+
let other = empty();
|
|
8195
|
+
for (const arm of d.parsers) {
|
|
8196
|
+
const lead2 = this.gapLead(arm, trivia2, depth + 1);
|
|
8197
|
+
if (lead2 !== void 0 && (p === void 0 || lead2.p === p)) {
|
|
8198
|
+
p = lead2.p;
|
|
8199
|
+
follow = union(follow, lead2.follow);
|
|
8200
|
+
other = union(other, lead2.other);
|
|
8201
|
+
continue;
|
|
8202
|
+
}
|
|
8203
|
+
if (matchesEmpty(arm, /* @__PURE__ */ new Set(), rr)) return void 0;
|
|
8204
|
+
const fs = firstSetOf(arm, /* @__PURE__ */ new Set(), rr, trivia2 ?? null);
|
|
8205
|
+
if (fs.kind === "any") return void 0;
|
|
8206
|
+
other = union(other, fs);
|
|
8207
|
+
}
|
|
8208
|
+
return p === void 0 ? void 0 : { p, follow, other };
|
|
8209
|
+
}
|
|
8210
|
+
default:
|
|
8211
|
+
return void 0;
|
|
8212
|
+
}
|
|
8213
|
+
}
|
|
8214
|
+
/**
|
|
8215
|
+
* The class a strict list may end on — a character its separator `p` (row
|
|
8216
|
+
* `ip`) cannot start — without entering the separator, or −1.
|
|
8217
|
+
*
|
|
8218
|
+
* The test runs before every separator, to save the one that fails at the
|
|
8219
|
+
* list's end, so it is laid down only where entering the separator costs more
|
|
8220
|
+
* than the test: not on a terminal row, which is itself one character test.
|
|
8221
|
+
*/
|
|
8222
|
+
sepGate(p, ip) {
|
|
8223
|
+
const op = this.code[ip];
|
|
8224
|
+
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;
|
|
8225
|
+
if (matchesEmpty(p, /* @__PURE__ */ new Set(), this.refResolver())) return -1;
|
|
8226
|
+
return this.charClass(firstSetOf(p, /* @__PURE__ */ new Set(), this.refResolver(), this.gateTrivia(), this.gateConsuming()));
|
|
8227
|
+
}
|
|
7849
8228
|
/** Reserve `n` operand slots to patch once children are laid out. */
|
|
7850
8229
|
emitHead(op, n) {
|
|
7851
8230
|
const ip = this.code.length;
|
|
@@ -7889,8 +8268,10 @@ var Encoder = class {
|
|
|
7889
8268
|
}
|
|
7890
8269
|
encodeRule(name, p) {
|
|
7891
8270
|
this.activeTrivia = p._meta.grammarTrivia;
|
|
8271
|
+
this.triviaKnown = p._meta.grammarTrivia !== void 0;
|
|
7892
8272
|
const body = this.node(p).ip;
|
|
7893
8273
|
this.activeTrivia = void 0;
|
|
8274
|
+
this.triviaKnown = true;
|
|
7894
8275
|
const gss = p._meta.grammarScanSkip;
|
|
7895
8276
|
this.scanSkipOf.push(gss === void 0 ? -1 : this.scanSkipSlot(gss));
|
|
7896
8277
|
const amb = p._meta.grammarTrivia;
|
|
@@ -7936,11 +8317,15 @@ var Encoder = class {
|
|
|
7936
8317
|
* silently produced the ONE keyword `bc`.
|
|
7937
8318
|
*/
|
|
7938
8319
|
scopedRef(p, target) {
|
|
8320
|
+
const runsUnder = triviaThroughRef(p, target, this.activeTrivia);
|
|
8321
|
+
if (this.activeTrivia !== void 0 || runsUnder === void 0 || runsUnder === null) return this.node(target).ip;
|
|
8322
|
+
const savedKnown = this.triviaKnown;
|
|
8323
|
+
this.activeTrivia = runsUnder;
|
|
8324
|
+
this.triviaKnown = true;
|
|
7939
8325
|
const ip = this.node(target).ip;
|
|
7940
|
-
|
|
7941
|
-
|
|
7942
|
-
|
|
7943
|
-
return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), ip);
|
|
8326
|
+
this.activeTrivia = void 0;
|
|
8327
|
+
this.triviaKnown = savedKnown;
|
|
8328
|
+
return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(runsUnder), ip);
|
|
7944
8329
|
}
|
|
7945
8330
|
/**
|
|
7946
8331
|
* The `OP_RGATE` operands of a choice arm that opens with `routed()`, or
|
|
@@ -7981,38 +8366,43 @@ var Encoder = class {
|
|
|
7981
8366
|
if (matchesEmpty(next, /* @__PURE__ */ new Set(), rr) || mayCommitFailure(next, rr, this.commitFailureMemo)) return void 0;
|
|
7982
8367
|
const nextDef = next._def;
|
|
7983
8368
|
if (nextDef.tag !== "literal" && nextDef.tag !== "regex" && nextDef.tag !== "keywords" && nextDef.tag !== "label") return void 0;
|
|
7984
|
-
|
|
8369
|
+
if (boundary === void 0 && !this.triviaKnown) return void 0;
|
|
8370
|
+
const first = firstSetOf(next, /* @__PURE__ */ new Set(), rr, boundary ?? null);
|
|
7985
8371
|
const cls = this.charClass(boundary === void 0 ? first : union(first, firstSetOf(boundary, /* @__PURE__ */ new Set(), rr)));
|
|
7986
8372
|
if (cls < 0) return void 0;
|
|
7987
|
-
const
|
|
7988
|
-
|
|
8373
|
+
const fx = this.expected(nextDef.tag === "label" ? deriveExpected(next) : directTerminalFailureExpected(nextDef));
|
|
8374
|
+
const two = firstTwo(next);
|
|
8375
|
+
if (two === void 0) return { cls, fx };
|
|
8376
|
+
if (boundary !== void 0 && intersects(two.first, firstSetOf(boundary, /* @__PURE__ */ new Set(), rr))) return { cls, fx };
|
|
8377
|
+
const a = this.charClass(two.first);
|
|
8378
|
+
const b = this.charClass(two.second);
|
|
8379
|
+
return a < 0 || b < 0 ? { cls, fx } : { cls, fx, two: [a, b] };
|
|
7989
8380
|
}
|
|
7990
8381
|
node(p) {
|
|
7991
|
-
const
|
|
7992
|
-
|
|
7993
|
-
const
|
|
7994
|
-
const hit = lazyRef ? refMemo.get(p)?.get(scopeKey) : this.memo.get(p);
|
|
8382
|
+
const key = this.scopeKey(p);
|
|
8383
|
+
let byScope = this.memo.get(p);
|
|
8384
|
+
const hit = byScope?.get(key);
|
|
7995
8385
|
if (hit !== void 0) return { ip: hit };
|
|
7996
|
-
|
|
8386
|
+
let inFlightByScope = this.pending.get(p);
|
|
8387
|
+
const inFlight = inFlightByScope?.get(key);
|
|
7997
8388
|
if (inFlight !== void 0) {
|
|
7998
8389
|
const ip2 = this.emitHead(OP_RULE, 1);
|
|
7999
8390
|
inFlight.push(ip2 + 1);
|
|
8000
8391
|
return { ip: ip2 };
|
|
8001
8392
|
}
|
|
8002
8393
|
const patches = [];
|
|
8003
|
-
|
|
8394
|
+
if (inFlightByScope === void 0) {
|
|
8395
|
+
inFlightByScope = /* @__PURE__ */ new Map();
|
|
8396
|
+
this.pending.set(p, inFlightByScope);
|
|
8397
|
+
}
|
|
8398
|
+
inFlightByScope.set(key, patches);
|
|
8004
8399
|
const ip = this.covWrap(this.encodeDef(p), this.plan?.rules.get(p), 0);
|
|
8005
|
-
|
|
8006
|
-
if (
|
|
8007
|
-
|
|
8008
|
-
|
|
8009
|
-
byScope = /* @__PURE__ */ new Map();
|
|
8010
|
-
refMemo.set(p, byScope);
|
|
8011
|
-
}
|
|
8012
|
-
byScope.set(scopeKey, ip);
|
|
8013
|
-
} else {
|
|
8014
|
-
this.memo.set(p, ip);
|
|
8400
|
+
inFlightByScope.delete(key);
|
|
8401
|
+
if (byScope === void 0) {
|
|
8402
|
+
byScope = /* @__PURE__ */ new Map();
|
|
8403
|
+
this.memo.set(p, byScope);
|
|
8015
8404
|
}
|
|
8405
|
+
byScope.set(key, ip);
|
|
8016
8406
|
for (const slot of patches) {
|
|
8017
8407
|
if (slot - 1 === ip) {
|
|
8018
8408
|
const rule2 = p._ruleName;
|
|
@@ -8110,8 +8500,19 @@ var Encoder = class {
|
|
|
8110
8500
|
}
|
|
8111
8501
|
case "choice": {
|
|
8112
8502
|
if (this.plan === void 0) {
|
|
8113
|
-
const
|
|
8114
|
-
if (
|
|
8503
|
+
const shared = factorSharedEnds(d);
|
|
8504
|
+
if (shared !== void 0) return this.node(shared).ip;
|
|
8505
|
+
if (this.unfactoredChoice !== p) {
|
|
8506
|
+
const prefix = factorPrefixArms(d);
|
|
8507
|
+
if (prefix !== void 0) {
|
|
8508
|
+
const strict = this.node(prefix).ip;
|
|
8509
|
+
const saved = this.unfactoredChoice;
|
|
8510
|
+
this.unfactoredChoice = p;
|
|
8511
|
+
const tolerant = this.encodeDef(p);
|
|
8512
|
+
this.unfactoredChoice = saved;
|
|
8513
|
+
return this.emit(OP_STRICT, strict, tolerant);
|
|
8514
|
+
}
|
|
8515
|
+
}
|
|
8115
8516
|
}
|
|
8116
8517
|
if (d.strategy.tag === "greedyClassify") {
|
|
8117
8518
|
const superIndex = d.strategy.superIndex;
|
|
@@ -8140,18 +8541,20 @@ var Encoder = class {
|
|
|
8140
8541
|
const plain2 = (checks === null || checks === void 0 || checks.length === 0) && (gate === null || gate === void 0);
|
|
8141
8542
|
const routedGate = plain2 ? this.routedArmGate(c) : void 0;
|
|
8142
8543
|
const body = this.node(c).ip;
|
|
8143
|
-
const inner = routedGate === void 0 ? body : this.emit(OP_RGATE, routedGate.cls, body, routedGate.fx);
|
|
8544
|
+
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]);
|
|
8144
8545
|
const ip = checks === null || checks === void 0 || checks.length === 0 ? inner : this.reject(inner, checks);
|
|
8145
8546
|
const gated = gate === null || gate === void 0 ? ip : this.emit(OP_ARMGATE, this.fn(gate, d.gateSrcs?.[src] ?? null), ip, this.expected(deriveExpected(c)));
|
|
8146
8547
|
return this.covWrap(gated, armCovIds?.[src], 1);
|
|
8147
8548
|
});
|
|
8148
8549
|
const rr = this.refResolver();
|
|
8149
|
-
const
|
|
8550
|
+
const constructionSets = d.disjoint && !factoredChoices.has(p);
|
|
8551
|
+
const finalChoice = classifyFinalChoice(arms, rr, this.gateTrivia(), false, constructionSets);
|
|
8552
|
+
const wideArms = this.wideArms(arms, finalChoice.firstSets, constructionSets);
|
|
8150
8553
|
const transactionalFirst = arms.map((arm, i) => {
|
|
8151
8554
|
if (!finalChoice.nullable[i]) return void 0;
|
|
8152
8555
|
const def = arm._def;
|
|
8153
8556
|
if (def.tag !== "attempt" || matchesEmpty(def.parser, /* @__PURE__ */ new Set(), rr)) return void 0;
|
|
8154
|
-
return firstSetOf(def.parser, /* @__PURE__ */ new Set(), rr, this.activeTrivia);
|
|
8557
|
+
return firstSetOf(def.parser, /* @__PURE__ */ new Set(), rr, this.activeTrivia, false);
|
|
8155
8558
|
});
|
|
8156
8559
|
const gateFirst = finalChoice.firstSets.map((first, i) => transactionalFirst[i] ?? first);
|
|
8157
8560
|
const classes = gateFirst.map((first, i) => finalChoice.nullable[i] && transactionalFirst[i] === void 0 ? -1 : this.charClass(first));
|
|
@@ -8169,6 +8572,9 @@ var Encoder = class {
|
|
|
8169
8572
|
if (transactionalFirst[i] !== void 0) classes[i] = -1;
|
|
8170
8573
|
}
|
|
8171
8574
|
}
|
|
8575
|
+
if (wideArms.length > 0 && dispatchIsExclusive(classes, this.cc)) {
|
|
8576
|
+
for (const i of wideArms) classes[i] = -1;
|
|
8577
|
+
}
|
|
8172
8578
|
if (d.gates.some((g) => g !== null && g !== void 0) && !dispatchIsExclusive(classes, this.cc)) {
|
|
8173
8579
|
for (let k = 0; k < classes.length; k++) {
|
|
8174
8580
|
const gate = d.gates[order[k]];
|
|
@@ -8202,27 +8608,34 @@ var Encoder = class {
|
|
|
8202
8608
|
}
|
|
8203
8609
|
case "many":
|
|
8204
8610
|
case "oneOrMore": {
|
|
8205
|
-
const child = this.node(d.parser).ip;
|
|
8206
8611
|
const rr = this.refResolver();
|
|
8207
|
-
const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.charClass(
|
|
8612
|
+
const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.charClass(this.gateFirstSet(d.parser, d.guarded === true, true));
|
|
8208
8613
|
const op = d.valueUnused ? OP_REPV : OP_REP;
|
|
8209
8614
|
const min = d.tag === "many" ? 0 : d.min;
|
|
8615
|
+
const item = min === 0 && itemClass >= 0 ? this.withoutLeadGate(this.node(d.parser).ip, itemClass) : this.node(d.parser).ip;
|
|
8616
|
+
const child = min === 0 && itemClass >= 0 ? this.gapGated(d.parser, item) : item;
|
|
8210
8617
|
return this.emit(op, child, min, d.max ?? -1, -1, 0, this.expected(deriveExpected(d.parser)), itemClass);
|
|
8211
8618
|
}
|
|
8212
8619
|
case "sepBy": {
|
|
8213
8620
|
const child = this.node(d.parser).ip;
|
|
8214
8621
|
const sep = this.node(d.separator).ip;
|
|
8215
|
-
const
|
|
8216
|
-
|
|
8217
|
-
|
|
8622
|
+
const gate = this.sepGate(d.separator, sep);
|
|
8623
|
+
const itemSet = deriveExpected(d.parser);
|
|
8624
|
+
const itemFx = this.expected(itemSet.length > 0 ? itemSet : [d.parser._tag]);
|
|
8625
|
+
const flags = (d.trailing === "allow" ? 1 : 0) | (d.keepSeparators === true ? 2 : 0) | (d.min >= 1 ? 4 : 0) | (gate >= 0 ? 8 : 0) | (itemSet.length === 0 ? 16 : 0);
|
|
8626
|
+
const ops = [
|
|
8218
8627
|
child,
|
|
8219
8628
|
d.min,
|
|
8220
8629
|
d.max ?? -1,
|
|
8221
8630
|
sep,
|
|
8222
8631
|
flags,
|
|
8223
|
-
|
|
8224
|
-
|
|
8225
|
-
|
|
8632
|
+
itemFx,
|
|
8633
|
+
// As 0.58.0: the interpreter resyncs on the separator itself
|
|
8634
|
+
// (`orSentinel`), which runs under the live trivia.
|
|
8635
|
+
this.charClass(firstSetOf(d.separator, /* @__PURE__ */ new Set(), this.refResolver(), this.activeTrivia, false))
|
|
8636
|
+
];
|
|
8637
|
+
if (gate >= 0) ops.push(gate);
|
|
8638
|
+
return this.emit(OP_REP, ...ops);
|
|
8226
8639
|
}
|
|
8227
8640
|
case "optional": {
|
|
8228
8641
|
const head = this.emit(OP_OPT, this.lookaheadGate(d.parser, this.node(d.parser).ip));
|
|
@@ -8231,7 +8644,7 @@ var Encoder = class {
|
|
|
8231
8644
|
}
|
|
8232
8645
|
case "transform": {
|
|
8233
8646
|
const inner = d.parser._def;
|
|
8234
|
-
if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
|
|
8647
|
+
if (inner.tag === "sequence" && !this.memo.get(d.parser)?.has(this.scopeKey(d.parser)) && !this.pending.get(d.parser)?.has(this.scopeKey(d.parser))) {
|
|
8235
8648
|
const kids = inner.parsers.map((c) => this.node(c).ip);
|
|
8236
8649
|
const head = this.emitHead(OP_SEQX, 2 + 2 * kids.length);
|
|
8237
8650
|
const projection = directArrayProjection(d.fn, d.fnSrc, kids.length);
|
|
@@ -8272,7 +8685,7 @@ var Encoder = class {
|
|
|
8272
8685
|
d.tags === void 0 ? -1 : this.constant(d.tags)
|
|
8273
8686
|
);
|
|
8274
8687
|
if (matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return body;
|
|
8275
|
-
const fs = this.gateFirstSet(d.parser);
|
|
8688
|
+
const fs = this.gateFirstSet(d.parser, d.guarded === true, false);
|
|
8276
8689
|
if (fs.kind === "any") return body;
|
|
8277
8690
|
const cls = this.charClass(fs);
|
|
8278
8691
|
if (cls < 0) return body;
|
|
@@ -8280,7 +8693,14 @@ var Encoder = class {
|
|
|
8280
8693
|
return this.emit(OP_GATE, cls, body, this.expected(e.length > 0 ? e : [d.parser._tag]));
|
|
8281
8694
|
}
|
|
8282
8695
|
case "token": {
|
|
8283
|
-
|
|
8696
|
+
const saved = this.activeTrivia;
|
|
8697
|
+
const savedKnown = this.triviaKnown;
|
|
8698
|
+
this.activeTrivia = void 0;
|
|
8699
|
+
this.triviaKnown = true;
|
|
8700
|
+
const body = this.node(d.parser).ip;
|
|
8701
|
+
this.activeTrivia = saved;
|
|
8702
|
+
this.triviaKnown = savedKnown;
|
|
8703
|
+
return this.emit(OP_TOKEN, body);
|
|
8284
8704
|
}
|
|
8285
8705
|
case "routed":
|
|
8286
8706
|
return this.emit(OP_ROUTED, d.fallback === void 0 ? -1 : this.node(d.fallback).ip);
|
|
@@ -8336,7 +8756,7 @@ var Encoder = class {
|
|
|
8336
8756
|
this.code[head + 2] = dspIdx;
|
|
8337
8757
|
this.code[head + 3] = other;
|
|
8338
8758
|
const otherRouted = d.otherwise === void 0 ? false : branchUsesRouted({ parser: d.otherwise, usesRouted: d.otherwiseUsesRouted === true });
|
|
8339
|
-
this.code[head + 4] = otherRouted ? 1 : 0;
|
|
8759
|
+
this.code[head + 4] = (otherRouted ? 1 : 0) | (d.otherwiseCommit === false ? 2 : 0);
|
|
8340
8760
|
this.code[head + 5] = arms.length;
|
|
8341
8761
|
for (let i = 0; i < arms.length; i++) this.code[head + 6 + i] = arms[i];
|
|
8342
8762
|
return head;
|
|
@@ -8391,7 +8811,7 @@ var Encoder = class {
|
|
|
8391
8811
|
case "attempt": {
|
|
8392
8812
|
const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip, d.contain === true ? 1 : 0);
|
|
8393
8813
|
if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
|
|
8394
|
-
const fs = this.gateFirstSet(d.parser);
|
|
8814
|
+
const fs = this.gateFirstSet(d.parser, d.guarded === true, false);
|
|
8395
8815
|
if (fs.kind === "any" || matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return inner;
|
|
8396
8816
|
const cls = this.charClass(fs);
|
|
8397
8817
|
if (cls < 0) return inner;
|
|
@@ -8417,10 +8837,17 @@ var Encoder = class {
|
|
|
8417
8837
|
const op = cap ? OP_SCOPE_CAP : OP_SCOPE;
|
|
8418
8838
|
const flags = (d.rootCapture === "opaque" ? 1 : 0) | (d.triviaParser !== void 0 && d.triviaParser._meta.rootTriviaClassified !== true && d.rootCapture !== "opaque" ? 2 : 0);
|
|
8419
8839
|
const savedTrivia = this.activeTrivia;
|
|
8420
|
-
|
|
8421
|
-
|
|
8840
|
+
const savedKnown = this.triviaKnown;
|
|
8841
|
+
if (d.clearTrivia === true) {
|
|
8842
|
+
this.activeTrivia = void 0;
|
|
8843
|
+
this.triviaKnown = true;
|
|
8844
|
+
} else if (d.triviaParser !== void 0) {
|
|
8845
|
+
this.activeTrivia = d.triviaParser;
|
|
8846
|
+
this.triviaKnown = true;
|
|
8847
|
+
}
|
|
8422
8848
|
const bodyIp = this.node(d.parser).ip;
|
|
8423
8849
|
this.activeTrivia = savedTrivia;
|
|
8850
|
+
this.triviaKnown = savedKnown;
|
|
8424
8851
|
if (d.clearTrivia === true) return this.emit(op, -1, bodyIp, flags);
|
|
8425
8852
|
if (d.triviaParser === void 0) {
|
|
8426
8853
|
return cap || flags !== 0 ? this.emit(op, -1, bodyIp, flags) : bodyIp;
|
|
@@ -8461,6 +8888,7 @@ var Encoder = class {
|
|
|
8461
8888
|
switch (this.code[ip]) {
|
|
8462
8889
|
case OP_GATE:
|
|
8463
8890
|
case OP_RGATE:
|
|
8891
|
+
case OP_RGATE2:
|
|
8464
8892
|
return [ip + 2];
|
|
8465
8893
|
case OP_RULE:
|
|
8466
8894
|
case OP_OPT:
|
|
@@ -8470,6 +8898,7 @@ var Encoder = class {
|
|
|
8470
8898
|
case OP_ATTEMPT:
|
|
8471
8899
|
case OP_LABEL:
|
|
8472
8900
|
case OP_COV:
|
|
8901
|
+
case OP_GAPGATE:
|
|
8473
8902
|
return [ip + 1];
|
|
8474
8903
|
case OP_SCOPE:
|
|
8475
8904
|
case OP_SCOPE_CAP:
|
|
@@ -8506,6 +8935,8 @@ var Encoder = class {
|
|
|
8506
8935
|
case OP_REP:
|
|
8507
8936
|
case OP_REPV:
|
|
8508
8937
|
return this.code[ip + 4] >= 0 ? [ip + 1, ip + 4] : [ip + 1];
|
|
8938
|
+
case OP_STRICT:
|
|
8939
|
+
return [ip + 1, ip + 2];
|
|
8509
8940
|
default:
|
|
8510
8941
|
return [];
|
|
8511
8942
|
}
|
|
@@ -9663,6 +10094,7 @@ function childSlots(code, ip, out) {
|
|
|
9663
10094
|
case OP_LABEL:
|
|
9664
10095
|
case OP_COV:
|
|
9665
10096
|
case OP_REJECT:
|
|
10097
|
+
case OP_GAPGATE:
|
|
9666
10098
|
out.push(code[ip + 1]);
|
|
9667
10099
|
return true;
|
|
9668
10100
|
// Single child at `ip + 2`.
|
|
@@ -9679,8 +10111,13 @@ function childSlots(code, ip, out) {
|
|
|
9679
10111
|
case OP_SOURCE_LEAF:
|
|
9680
10112
|
case OP_ARMGATE:
|
|
9681
10113
|
case OP_RGATE:
|
|
10114
|
+
case OP_RGATE2:
|
|
9682
10115
|
out.push(code[ip + 2]);
|
|
9683
10116
|
return true;
|
|
10117
|
+
// `STRICT strict tolerant` — both encodings are reachable; an assembly keeps one.
|
|
10118
|
+
case OP_STRICT:
|
|
10119
|
+
out.push(code[ip + 1], code[ip + 2]);
|
|
10120
|
+
return true;
|
|
9684
10121
|
// `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
|
|
9685
10122
|
// data the enclosing `dispatch()` already consumed, so the only edge is the
|
|
9686
10123
|
// fallback.
|
|
@@ -10128,7 +10565,8 @@ var WRAPPERS = /* @__PURE__ */ new Set([
|
|
|
10128
10565
|
OP_WITHCTX,
|
|
10129
10566
|
OP_RULE,
|
|
10130
10567
|
OP_ATTEMPT,
|
|
10131
|
-
OP_COV
|
|
10568
|
+
OP_COV,
|
|
10569
|
+
OP_GAPGATE
|
|
10132
10570
|
]);
|
|
10133
10571
|
function rowNullable(code, k, ip, memo) {
|
|
10134
10572
|
const hit = memo.get(ip);
|
|
@@ -10165,7 +10603,31 @@ function holdsGap(code, k, base, n, i, memo) {
|
|
|
10165
10603
|
return !rowNullable(code, k, next, memo);
|
|
10166
10604
|
}
|
|
10167
10605
|
|
|
10606
|
+
// src/table/gap-gate.ts
|
|
10607
|
+
function newGapSlot() {
|
|
10608
|
+
return { row: -1, at: -1, end: -1, input: void 0 };
|
|
10609
|
+
}
|
|
10610
|
+
function gapRows(code, roots) {
|
|
10611
|
+
const rows = /* @__PURE__ */ new Set();
|
|
10612
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10613
|
+
const stack = [...roots];
|
|
10614
|
+
const kids = [];
|
|
10615
|
+
while (stack.length > 0) {
|
|
10616
|
+
const ip = stack.pop();
|
|
10617
|
+
if (seen.has(ip)) continue;
|
|
10618
|
+
seen.add(ip);
|
|
10619
|
+
if (code[ip] === OP_GAPGATE) rows.add(code[ip + 2]);
|
|
10620
|
+
kids.length = 0;
|
|
10621
|
+
childSlots(code, ip, kids);
|
|
10622
|
+
for (const c of kids) stack.push(c);
|
|
10623
|
+
}
|
|
10624
|
+
return rows;
|
|
10625
|
+
}
|
|
10626
|
+
|
|
10168
10627
|
// src/table/emit-assembly.ts
|
|
10628
|
+
function gapRegexLowers(re) {
|
|
10629
|
+
return re instanceof RegExp && scanShapeFromRegex(re.source, re.flags) !== null;
|
|
10630
|
+
}
|
|
10169
10631
|
var Unemittable = class extends Error {
|
|
10170
10632
|
construct;
|
|
10171
10633
|
constructor(construct) {
|
|
@@ -10184,7 +10646,6 @@ var EMITTED_PARAMS = [
|
|
|
10184
10646
|
"CLS",
|
|
10185
10647
|
"AFX",
|
|
10186
10648
|
"TRIVIA",
|
|
10187
|
-
"TRIVIALABELS",
|
|
10188
10649
|
"TRIVIASCAN",
|
|
10189
10650
|
"SCANS",
|
|
10190
10651
|
"DISP",
|
|
@@ -10208,7 +10669,6 @@ var EMITTED_PARAMS = [
|
|
|
10208
10669
|
"cstLeavesLen",
|
|
10209
10670
|
"skipTriviaScanned",
|
|
10210
10671
|
"needsDeferredTriviaCommit",
|
|
10211
|
-
"scanTrivia",
|
|
10212
10672
|
"advanceTrivia",
|
|
10213
10673
|
"refuseUnclassifiedRootScope",
|
|
10214
10674
|
"spanLines",
|
|
@@ -10228,34 +10688,31 @@ var EMITTED_PARAMS = [
|
|
|
10228
10688
|
"orSentinel",
|
|
10229
10689
|
"captureError",
|
|
10230
10690
|
// Pure scalar terminal recognizers, indexed by the terminal's existing const
|
|
10231
|
-
// operand
|
|
10691
|
+
// operand; selected lexical bodies; the adjacency test.
|
|
10232
10692
|
"RECOG",
|
|
10233
|
-
// Appended so precompiled factories produced by earlier runtimes keep every
|
|
10234
|
-
// positional helper binding. Older factories ignore this trailing argument.
|
|
10235
|
-
"commitTriviaScan",
|
|
10236
|
-
"scanTriviaCompact",
|
|
10237
10693
|
"LEX",
|
|
10238
|
-
// Appended for old precompiled-factory ABI: old factories ignore it.
|
|
10239
10694
|
"adjacencyHolds",
|
|
10240
|
-
//
|
|
10695
|
+
// Selected composite lexical programs.
|
|
10241
10696
|
"LEXPROG",
|
|
10242
|
-
//
|
|
10243
|
-
// old factories ignore them.
|
|
10697
|
+
// Trivia-attributing fields (`field(…, { leadingTrivia })`).
|
|
10244
10698
|
"LEAD",
|
|
10245
10699
|
"triviaFieldCapture",
|
|
10246
|
-
//
|
|
10247
|
-
// factories ignore it.
|
|
10700
|
+
// The deferred-commit trivia skip (`trivia-gap.ts`).
|
|
10248
10701
|
"skipDeferredTrivia",
|
|
10249
|
-
//
|
|
10250
|
-
// ignore it.
|
|
10702
|
+
// The pass-through collapse (`run-support.ts`).
|
|
10251
10703
|
"collapseEmpty",
|
|
10252
|
-
//
|
|
10253
|
-
//
|
|
10704
|
+
// Constructor-built tree objects (`cst/plain.d.ts`): a `new` call has no
|
|
10705
|
+
// allocation site, so V8 cannot pretenure them.
|
|
10254
10706
|
"_SP",
|
|
10255
10707
|
"_LF",
|
|
10256
10708
|
"_ND",
|
|
10257
10709
|
"_FC",
|
|
10258
|
-
"_BUF"
|
|
10710
|
+
"_BUF",
|
|
10711
|
+
// The gap gate's slot (`gap-gate.ts`).
|
|
10712
|
+
"GAP"
|
|
10713
|
+
// Artifacts are version-locked (docs/design/artifact-format.md): a factory is
|
|
10714
|
+
// only ever called by the runtime that emitted it, so a name nothing emitted
|
|
10715
|
+
// reads is removed rather than kept for an older factory's positions.
|
|
10259
10716
|
];
|
|
10260
10717
|
var RUNTIME_PRELUDE = `
|
|
10261
10718
|
let _pfScan=null
|
|
@@ -10506,7 +10963,7 @@ function rebuildPools(cc, fx, disp, plan) {
|
|
|
10506
10963
|
})
|
|
10507
10964
|
};
|
|
10508
10965
|
}
|
|
10509
|
-
function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false, select, scanSinkNeutral = false) {
|
|
10966
|
+
function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false, select, scanSinkNeutral = false, gapNeutral = false) {
|
|
10510
10967
|
const { code, k, fx, disp, dsp, triviaLabelled } = t2;
|
|
10511
10968
|
const swapLegal = !cfg.trackLines;
|
|
10512
10969
|
const hostCst = cfg.hostCst;
|
|
@@ -10514,6 +10971,7 @@ function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false, s
|
|
|
10514
10971
|
if (cfg.coverage) throw new Unemittable("a coverage assembly");
|
|
10515
10972
|
const roots = [...Object.values(prog.rules), ...extraIps];
|
|
10516
10973
|
const reachable = [...reachableSites(code, roots)];
|
|
10974
|
+
const GAP_ROWS = gapNeutral ? /* @__PURE__ */ new Set() : new Set([...gapRows(code, roots)].filter((row) => !gapRegexLowers(k[code[row + 1]])));
|
|
10517
10975
|
const labels = computeSiteLabels(code, roots, hostCst);
|
|
10518
10976
|
const scalarSpecs = /* @__PURE__ */ new Set();
|
|
10519
10977
|
const nullable2 = /* @__PURE__ */ new Map();
|
|
@@ -10851,13 +11309,15 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
10851
11309
|
function aliasOf(ip) {
|
|
10852
11310
|
const op = code[ip];
|
|
10853
11311
|
if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
|
|
10854
|
-
if (op === OP_RULE) return code[ip + 1];
|
|
11312
|
+
if (op === OP_RULE || op === OP_GAPGATE) return code[ip + 1];
|
|
11313
|
+
if (op === OP_STRICT) return code[cfg.tolerant || cfg.probe ? ip + 2 : ip + 1];
|
|
10855
11314
|
if (scopeIsIdentity(code, ip, labels.at(ip))) return code[ip + 2];
|
|
10856
11315
|
return void 0;
|
|
10857
11316
|
}
|
|
10858
11317
|
function lower(ip, fname) {
|
|
10859
11318
|
const op = code[ip];
|
|
10860
11319
|
const head = `function ${fname}(input,pos,ctx){`;
|
|
11320
|
+
const outerHead = head;
|
|
10861
11321
|
const L = labels.at(ip);
|
|
10862
11322
|
const sinks = sinksAt(ip);
|
|
10863
11323
|
const pushLeaf = L.buf && !cfg.trackLines ? L.raw === RAW_OMIT ? "_pushLeafNoRawBuf" : L.raw === RAW_CAPTURE ? "_pushLeafBuf" : "_pushLeaf" : "_pushLeaf";
|
|
@@ -10933,9 +11393,27 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
10933
11393
|
case OP_RX_TRACK: {
|
|
10934
11394
|
const xf = fxRef(code[ip + 2]);
|
|
10935
11395
|
const track = op === OP_RX_TRACK;
|
|
11396
|
+
if (GAP_ROWS.has(ip)) {
|
|
11397
|
+
const re2 = hoist("gx", `K[${code[ip + 1]}]`);
|
|
11398
|
+
return `${outerHead}
|
|
11399
|
+
let e
|
|
11400
|
+
if(GAP.row===${ip}&&GAP.at===pos&&GAP.input===input)e=GAP.end
|
|
11401
|
+
else{${re2}.lastIndex=pos;e=${re2}.test(input)?${re2}.lastIndex:-1}
|
|
11402
|
+
if(e>=0){
|
|
11403
|
+
const v=input.slice(pos,e)
|
|
11404
|
+
${captureLeaf("v")}
|
|
11405
|
+
${track ? "_trackLines(ctx,input,e)\n" : ""}EC.e=e
|
|
11406
|
+
return v
|
|
11407
|
+
}
|
|
11408
|
+
ctx._fe=pos;ctx._fx=${xf}
|
|
11409
|
+
${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
11410
|
+
` : ""}return FAIL
|
|
11411
|
+
}`;
|
|
11412
|
+
}
|
|
11413
|
+
const head2 = outerHead;
|
|
10936
11414
|
if (!track && scalarSpecs.has(code[ip + 1])) {
|
|
10937
11415
|
const recognize = recognizerRef(code[ip + 1]);
|
|
10938
|
-
return `${
|
|
11416
|
+
return `${head2}
|
|
10939
11417
|
const e=${recognize}(input,pos)
|
|
10940
11418
|
if(e>=0){
|
|
10941
11419
|
const v=input.slice(pos,e)
|
|
@@ -10948,11 +11426,11 @@ return FAIL
|
|
|
10948
11426
|
}`;
|
|
10949
11427
|
}
|
|
10950
11428
|
const scanned = emitScan(code[ip + 1], xf, track, captureLeaf);
|
|
10951
|
-
if (scanned !== void 0) return `${
|
|
11429
|
+
if (scanned !== void 0) return `${head2}${scanned}}`;
|
|
10952
11430
|
const rxk = k[code[ip + 1]];
|
|
10953
11431
|
if (!(rxk instanceof RegExp) || !rxk.sticky) throw new Unemittable("a non-sticky regex row");
|
|
10954
11432
|
const re = kRef(code[ip + 1]);
|
|
10955
|
-
return `${
|
|
11433
|
+
return `${head2}
|
|
10956
11434
|
${re}.lastIndex=pos
|
|
10957
11435
|
if(${re}.test(input)){
|
|
10958
11436
|
const e=${re}.lastIndex
|
|
@@ -10990,6 +11468,28 @@ return ${child}(input,pos,ctx)
|
|
|
10990
11468
|
const it=ctx._routed
|
|
10991
11469
|
if(it!==undefined&&it.span.start===pos&&!classHas(${cls},lead(input,it.span.end))){ctx._fe=it.span.end;ctx._fx=${xf};return FAIL}
|
|
10992
11470
|
return ${child}(input,pos,ctx)
|
|
11471
|
+
}`;
|
|
11472
|
+
}
|
|
11473
|
+
case OP_RGATE2: {
|
|
11474
|
+
const child = link(code[ip + 2]);
|
|
11475
|
+
if (cfg.tolerant || cfg.probe) return `${head}
|
|
11476
|
+
return ${child}(input,pos,ctx)
|
|
11477
|
+
}`;
|
|
11478
|
+
const idxs = [code[ip + 1], code[ip + 4], code[ip + 5]];
|
|
11479
|
+
const ascii = idxs.every((i) => isAsciiOnlyClass(t2.cc[i]));
|
|
11480
|
+
const ref2 = (idx, tag) => {
|
|
11481
|
+
const ci = classes.push([t2.cc[idx]]) - 1;
|
|
11482
|
+
classPlan.push([idx]);
|
|
11483
|
+
return hoist(tag, `CLS[${ci}][0]`);
|
|
11484
|
+
};
|
|
11485
|
+
const [cls, first, second] = [ref2(idxs[0], "cl"), ref2(idxs[1], "c1"), ref2(idxs[2], "c2")];
|
|
11486
|
+
const has = (c, at) => ascii ? `${c}.ascii[${at}]===1` : `classHas(${c},${at})`;
|
|
11487
|
+
const xf = fxRef(code[ip + 3]);
|
|
11488
|
+
return `${head}
|
|
11489
|
+
const it=ctx._routed
|
|
11490
|
+
if(it!==undefined&&it.span.start===pos){const e=it.span.end;const c=${ascii ? "input.charCodeAt(e)" : "lead(input,e)"}
|
|
11491
|
+
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}}
|
|
11492
|
+
return ${child}(input,pos,ctx)
|
|
10993
11493
|
}`;
|
|
10994
11494
|
}
|
|
10995
11495
|
case OP_ARMGATE: {
|
|
@@ -11399,7 +11899,27 @@ if(ctx._fc===true)return FAIL
|
|
|
11399
11899
|
const af=ctx._fx
|
|
11400
11900
|
if(af!==undefined&&af.length>0){ctx._fe=pos;return FAIL}
|
|
11401
11901
|
}
|
|
11402
|
-
|
|
11902
|
+
${cfg.probe ? `if(arm<0){${arms.map((a) => `${a}(input,pos,ctx)`).join(";")}}
|
|
11903
|
+
` : ""}ctx._fe=pos;ctx._fx=${choiceFx}
|
|
11904
|
+
return FAIL
|
|
11905
|
+
}`;
|
|
11906
|
+
}
|
|
11907
|
+
if (cfg.probe) {
|
|
11908
|
+
const p = tmp();
|
|
11909
|
+
return `${head}
|
|
11910
|
+
${emitMark(p, L.buf, L.raw, sinks)}
|
|
11911
|
+
let acc
|
|
11912
|
+
let best=pos
|
|
11913
|
+
${arms.map((arm) => `{ctx._fc=false
|
|
11914
|
+
const v=${arm}(input,pos,ctx)
|
|
11915
|
+
if(v!==FAIL)return v
|
|
11916
|
+
const at=ctx._fe??pos
|
|
11917
|
+
if(at>best){best=at;acc=undefined}
|
|
11918
|
+
if(at===best)acc=_accSet(ctx._fx,acc)
|
|
11919
|
+
if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
|
|
11920
|
+
${emitRollback(p, L.buf, L.raw, sinks)}
|
|
11921
|
+
}`).join("\n")}
|
|
11922
|
+
ctx._fe=pos;ctx._fx=acc??${choiceFx}
|
|
11403
11923
|
return FAIL
|
|
11404
11924
|
}`;
|
|
11405
11925
|
}
|
|
@@ -11606,7 +12126,8 @@ return FAIL
|
|
|
11606
12126
|
const selector = link(code[ip + 1]);
|
|
11607
12127
|
const otherIp = code[ip + 3];
|
|
11608
12128
|
const other = otherIp >= 0 ? link(otherIp) : void 0;
|
|
11609
|
-
const otherRouted = code[ip + 4] === 1;
|
|
12129
|
+
const otherRouted = (code[ip + 4] & 1) === 1;
|
|
12130
|
+
const otherCommits = (code[ip + 4] & 2) === 0;
|
|
11610
12131
|
const n = code[ip + 5];
|
|
11611
12132
|
validateDispatchSpec(spec, n, code[ip + 4]);
|
|
11612
12133
|
const armBase = ip + 6;
|
|
@@ -11660,7 +12181,7 @@ ${fallbackCase}
|
|
|
11660
12181
|
}
|
|
11661
12182
|
if(v===FAIL){
|
|
11662
12183
|
${emitRollback(m2, L.buf, L.raw, sinks)}
|
|
11663
|
-
ctx._fc=true
|
|
12184
|
+
${other !== void 0 && !otherCommits ? "if(arm!==undefined)" : ""}ctx._fc=true
|
|
11664
12185
|
return FAIL
|
|
11665
12186
|
}
|
|
11666
12187
|
return [key,v]
|
|
@@ -11692,6 +12213,63 @@ return [key,v]
|
|
|
11692
12213
|
}
|
|
11693
12214
|
}
|
|
11694
12215
|
const itemMiss = (at) => itemAscii ? `${itemCls}.ascii[input.charCodeAt(${at})]!==1` : `!classHas(${itemCls},lead(input,${at}))`;
|
|
12216
|
+
let sepCls;
|
|
12217
|
+
let sepAscii = false;
|
|
12218
|
+
if (!REC && sepIp >= 0 && (code[ip + 5] & 8) !== 0 && !leadingTriviaFieldAt(code, k, sepIp) && !rowNullable(code, k, sepIp, nullable2)) {
|
|
12219
|
+
const resolved = t2.cc[code[ip + 8]];
|
|
12220
|
+
const ci = classes.push([resolved]) - 1;
|
|
12221
|
+
classPlan.push([code[ip + 8]]);
|
|
12222
|
+
sepCls = hoist("rs", `CLS[${ci}][0]`);
|
|
12223
|
+
sepAscii = isAsciiOnlyClass(resolved);
|
|
12224
|
+
}
|
|
12225
|
+
const gapIp = !gapNeutral && sepIp < 0 && min === 0 && !REC && code[code[ip + 1]] === OP_GAPGATE ? code[ip + 1] : -1;
|
|
12226
|
+
let gapCode = (_rb) => "";
|
|
12227
|
+
if (gapIp >= 0) {
|
|
12228
|
+
const row = code[gapIp + 2];
|
|
12229
|
+
const rx = k[code[row + 1]];
|
|
12230
|
+
const shape = gapRegexLowers(rx) ? scanShapeFromRegex(rx.source, rx.flags) : null;
|
|
12231
|
+
const cls = (idx) => {
|
|
12232
|
+
const resolved = t2.cc[idx];
|
|
12233
|
+
const ci = classes.push([resolved]) - 1;
|
|
12234
|
+
classPlan.push([idx]);
|
|
12235
|
+
const ref2 = hoist("gc", `CLS[${ci}][0]`);
|
|
12236
|
+
return isAsciiOnlyClass(resolved) ? `${ref2}.ascii[input.charCodeAt(${"@"})]!==1` : `!classHas(${ref2},lead(input,${"@"}))`;
|
|
12237
|
+
};
|
|
12238
|
+
const follow = cls(code[gapIp + 3]).replaceAll("@", "gq");
|
|
12239
|
+
const other = code[gapIp + 4] >= 0 ? cls(code[gapIp + 4]).replaceAll("@", "itemStart") : "true";
|
|
12240
|
+
if (shape !== null) {
|
|
12241
|
+
let n = 0;
|
|
12242
|
+
const q2 = tmp();
|
|
12243
|
+
const m = emitShapeMatch(shape, "itemStart", (prefix = "_v") => `${q2}${prefix}${n++}`, "");
|
|
12244
|
+
gapCode = (rbCode) => `let gapped=false
|
|
12245
|
+
if(ctx._probe===undefined){
|
|
12246
|
+
${m.setup.join("\n")}
|
|
12247
|
+
const gq=${m.ok}?${m.end}:-1
|
|
12248
|
+
if((gq<0||${follow})&&${other}){
|
|
12249
|
+
${rbCode}
|
|
12250
|
+
break
|
|
12251
|
+
}
|
|
12252
|
+
}
|
|
12253
|
+
`;
|
|
12254
|
+
} else {
|
|
12255
|
+
const re = hoist("gr", `K[${code[row + 1]}]`);
|
|
12256
|
+
gapCode = (rbCode) => `let gapped=false
|
|
12257
|
+
if(ctx._probe===undefined){
|
|
12258
|
+
${re}.lastIndex=itemStart
|
|
12259
|
+
const gq=${re}.test(input)?${re}.lastIndex:-1
|
|
12260
|
+
if((gq<0||${follow})&&${other}){
|
|
12261
|
+
${rbCode}
|
|
12262
|
+
break
|
|
12263
|
+
}
|
|
12264
|
+
if(gq>=0){
|
|
12265
|
+
GAP.row=${row};GAP.at=itemStart;GAP.end=gq;GAP.input=input
|
|
12266
|
+
gapped=true
|
|
12267
|
+
}
|
|
12268
|
+
}
|
|
12269
|
+
`;
|
|
12270
|
+
}
|
|
12271
|
+
}
|
|
12272
|
+
const sepMiss = (at) => sepAscii ? `${sepCls}.ascii[input.charCodeAt(${at})]!==1` : `!classHas(${sepCls},lead(input,${at}))`;
|
|
11695
12273
|
const skipBeforeFirst = sepIp < 0 && min === 0;
|
|
11696
12274
|
const p = tmp();
|
|
11697
12275
|
const via = sep !== void 0 ? "false" : min === 0 ? skipBeforeFirst ? "true" : "count>0" : `count>=${min}&&count>0`;
|
|
@@ -11729,7 +12307,7 @@ ${p}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
|
11729
12307
|
${p}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${markSinks}
|
|
11730
12308
|
}`;
|
|
11731
12309
|
const my = `${p}my`;
|
|
11732
|
-
const recFx = REC ? fxRef(code[ip + 6])
|
|
12310
|
+
const recFx = !REC ? "" : (flags & 16) !== 0 ? "[]" : fxRef(code[ip + 6]);
|
|
11733
12311
|
const sepSent = REC ? sentRef(code[ip + 7]) : "undefined";
|
|
11734
12312
|
const recSent = sep === void 0 ? my : sepSent === "undefined" ? `orSentinel(${my},undefined)` : `orSentinel(${sepSent}??${my},${sepSent}===undefined?undefined:${my})`;
|
|
11735
12313
|
const recGate = sep !== void 0 || min === 0 ? "" : `count>=${min}&&`;
|
|
@@ -11745,7 +12323,7 @@ continue
|
|
|
11745
12323
|
return `${head}
|
|
11746
12324
|
const out=${collect ? "[]" : "undefined"}
|
|
11747
12325
|
${knownTrivia === void 0 ? "const hasTrivia=ctx.trivia!==undefined\n" : ""}${L.buf ? "" : "const needMark=_rollbackNeeded(ctx)\n"}${REC ? `const ${my}=ctx._sync
|
|
11748
|
-
` : ""}${itemCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
|
|
12326
|
+
` : ""}${itemCls === void 0 && sepCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
|
|
11749
12327
|
`}let cur=pos
|
|
11750
12328
|
let count=0
|
|
11751
12329
|
for(;;){
|
|
@@ -11761,6 +12339,10 @@ const lb=cstLeavesLen(ctx)
|
|
|
11761
12339
|
let sp=cur
|
|
11762
12340
|
${hasTrivia === "false" ? "" : hasTrivia === "true" ? `sp=${skip}(input,sp,ctx)
|
|
11763
12341
|
` : `if(hasTrivia)sp=${skip}(input,sp,ctx)
|
|
12342
|
+
`}${sepCls === void 0 ? "" : `if(count>=${min}&&${p}gate&&${sepMiss("sp")}){
|
|
12343
|
+
${rb}
|
|
12344
|
+
break
|
|
12345
|
+
}
|
|
11764
12346
|
`}ctx._fc=false
|
|
11765
12347
|
${sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp) ? "LEAD.at=cur\n" : ""}const sv=${sep}(input,sp,ctx)
|
|
11766
12348
|
if(sv===FAIL){
|
|
@@ -11776,13 +12358,13 @@ itemStart=${hasTrivia === "false" ? "EC.e" : hasTrivia === "true" ? `${skip}(inp
|
|
|
11776
12358
|
${rb}
|
|
11777
12359
|
${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
|
|
11778
12360
|
}
|
|
11779
|
-
${itemCls === void 0 ? "" : `if(count>=${min}&&${p}gate&&${itemMiss("itemStart")}){
|
|
12361
|
+
${itemCls === void 0 || sep === void 0 && hasTrivia === "false" ? "" : `if(count>=${min}&&${p}gate&&${sep === void 0 && hasTrivia === "hasTrivia" ? "hasTrivia&&" : ""}${itemMiss("itemStart")}){
|
|
11780
12362
|
${rb}
|
|
11781
12363
|
${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
|
|
11782
12364
|
}
|
|
11783
|
-
`}ctx._fc=false
|
|
12365
|
+
`}${gapCode(rb)}ctx._fc=false
|
|
11784
12366
|
const v=${child}(input,itemStart,ctx)
|
|
11785
|
-
if(v===FAIL){
|
|
12367
|
+
${gapIp >= 0 ? "if(gapped)GAP.at=-1\n" : ""}if(v===FAIL){
|
|
11786
12368
|
${REC ? `if(ctx._fc===true){
|
|
11787
12369
|
${rb}
|
|
11788
12370
|
return FAIL
|
|
@@ -12754,6 +13336,9 @@ function clearOf(ranges, input, from, to) {
|
|
|
12754
13336
|
return true;
|
|
12755
13337
|
}
|
|
12756
13338
|
|
|
13339
|
+
// src/version.ts
|
|
13340
|
+
var PARSEMAN_VERSION = "0.60.1";
|
|
13341
|
+
|
|
12757
13342
|
// src/table/assemble.ts
|
|
12758
13343
|
import { PlainBuf as PlainBuf2, PlainField, PlainLeaf as PlainLeaf9, PlainNode as PlainNode2, PlainSpan as PlainSpan10 } from "../cst/plain.js";
|
|
12759
13344
|
|
|
@@ -12764,6 +13349,7 @@ function passChild(code, ip) {
|
|
|
12764
13349
|
case OP_LABEL:
|
|
12765
13350
|
case OP_COV:
|
|
12766
13351
|
case OP_TOKEN:
|
|
13352
|
+
case OP_GAPGATE:
|
|
12767
13353
|
return code[ip + 1];
|
|
12768
13354
|
case OP_GATE:
|
|
12769
13355
|
case OP_NODE:
|
|
@@ -13012,6 +13598,13 @@ function cfgKeyOf(hostCst, trackLines, tolerant, coverage, probe, hostReadsChild
|
|
|
13012
13598
|
function cfgKey(c) {
|
|
13013
13599
|
return cfgKeyOf(c.hostCst, c.trackLines, c.tolerant, c.coverage, c.probe, c.hostReadsChildren);
|
|
13014
13600
|
}
|
|
13601
|
+
function assertFactoryArity(pre) {
|
|
13602
|
+
if (pre.arity === EMITTED_PARAMS.length) return;
|
|
13603
|
+
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`;
|
|
13604
|
+
throw new Error(
|
|
13605
|
+
`parseman: this parser's printed assembly ${printed}. Reprint the parser with parseman ${PARSEMAN_VERSION}, or run it on the parseman version that printed it.`
|
|
13606
|
+
);
|
|
13607
|
+
}
|
|
13015
13608
|
function assemble(t2, prog, cfg) {
|
|
13016
13609
|
const { code, k, fns, cc, fx, disp, dsp, trivia: trivia2, triviaLabelled } = t2;
|
|
13017
13610
|
const triviaScan = t2.triviaScan;
|
|
@@ -13046,6 +13639,8 @@ function assemble(t2, prog, cfg) {
|
|
|
13046
13639
|
return recognize;
|
|
13047
13640
|
}
|
|
13048
13641
|
const labelExtraIps = assemblyExtraIps(prog);
|
|
13642
|
+
const GAP_ROWS = gapRows(code, [...Object.values(prog.rules), ...labelExtraIps]);
|
|
13643
|
+
const GAP = newGapSlot();
|
|
13049
13644
|
const closureLabels = computeSiteLabels(
|
|
13050
13645
|
code,
|
|
13051
13646
|
[...Object.values(prog.rules), ...labelExtraIps],
|
|
@@ -13264,6 +13859,27 @@ function assemble(t2, prog, cfg) {
|
|
|
13264
13859
|
return node2;
|
|
13265
13860
|
};
|
|
13266
13861
|
}
|
|
13862
|
+
function gapRegexPiece(row, re, xf, track) {
|
|
13863
|
+
return (input, pos, ctx) => {
|
|
13864
|
+
let e;
|
|
13865
|
+
if (GAP.row === row && GAP.at === pos && GAP.input === input) e = GAP.end;
|
|
13866
|
+
else {
|
|
13867
|
+
re.lastIndex = pos;
|
|
13868
|
+
e = re.test(input) ? re.lastIndex : -1;
|
|
13869
|
+
}
|
|
13870
|
+
if (e >= 0) {
|
|
13871
|
+
const v = input.slice(pos, e);
|
|
13872
|
+
if (cstCaptureActive(ctx)) pushLeaf(ctx, v, pos, e);
|
|
13873
|
+
if (track) trackLinesInto(ctx, input, e);
|
|
13874
|
+
EC.e = e;
|
|
13875
|
+
return v;
|
|
13876
|
+
}
|
|
13877
|
+
ctx._fe = pos;
|
|
13878
|
+
ctx._fx = xf;
|
|
13879
|
+
if (ctx._probe !== void 0) failAt(ctx, xf, pos);
|
|
13880
|
+
return FAIL;
|
|
13881
|
+
};
|
|
13882
|
+
}
|
|
13267
13883
|
function passCollapseNode(child, build, readsRaw) {
|
|
13268
13884
|
return (input, pos, ctx) => {
|
|
13269
13885
|
const v = child(input, pos, ctx);
|
|
@@ -13666,7 +14282,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13666
14282
|
return next?.(key);
|
|
13667
14283
|
};
|
|
13668
14284
|
}
|
|
13669
|
-
function dispatchBranch(child, usesRouted) {
|
|
14285
|
+
function dispatchBranch(child, usesRouted, commits = true) {
|
|
13670
14286
|
if (!usesRouted) {
|
|
13671
14287
|
return (input, _pos, selEnd, key, ctx) => {
|
|
13672
14288
|
const need = markCst(ctx);
|
|
@@ -13680,7 +14296,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13680
14296
|
const v = child(input, selEnd, ctx);
|
|
13681
14297
|
if (v === FAIL) {
|
|
13682
14298
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
13683
|
-
ctx._fc = true;
|
|
14299
|
+
if (commits) ctx._fc = true;
|
|
13684
14300
|
return FAIL;
|
|
13685
14301
|
}
|
|
13686
14302
|
return [key, v];
|
|
@@ -13698,7 +14314,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13698
14314
|
}
|
|
13699
14315
|
if (v === FAIL) {
|
|
13700
14316
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
13701
|
-
ctx._fc = true;
|
|
14317
|
+
if (commits) ctx._fc = true;
|
|
13702
14318
|
return FAIL;
|
|
13703
14319
|
}
|
|
13704
14320
|
return [key, v];
|
|
@@ -13939,6 +14555,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13939
14555
|
case OP_RX: {
|
|
13940
14556
|
const re = k[code[ip + 1]];
|
|
13941
14557
|
const xf = fx[code[ip + 2]];
|
|
14558
|
+
if (GAP_ROWS.has(ip)) return gapRegexPiece(ip, re, xf, false);
|
|
13942
14559
|
const shared = rawScalarSpecs.has(code[ip + 1]) ? scalarFor(ip) : void 0;
|
|
13943
14560
|
if (shared !== void 0) {
|
|
13944
14561
|
return (input, pos, ctx) => {
|
|
@@ -13973,6 +14590,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13973
14590
|
case OP_RX_TRACK: {
|
|
13974
14591
|
const re = k[code[ip + 1]];
|
|
13975
14592
|
const xf = fx[code[ip + 2]];
|
|
14593
|
+
if (GAP_ROWS.has(ip)) return gapRegexPiece(ip, re, xf, true);
|
|
13976
14594
|
return (input, pos, ctx) => {
|
|
13977
14595
|
re.lastIndex = pos;
|
|
13978
14596
|
if (re.test(input)) {
|
|
@@ -14103,6 +14721,12 @@ function assemble(t2, prog, cfg) {
|
|
|
14103
14721
|
return v;
|
|
14104
14722
|
};
|
|
14105
14723
|
}
|
|
14724
|
+
// Transparent: only the repeat holding it reads its operands.
|
|
14725
|
+
case OP_GAPGATE:
|
|
14726
|
+
return link(code[ip + 1]);
|
|
14727
|
+
// One encoding per assembly: strict, or the construct as written.
|
|
14728
|
+
case OP_STRICT:
|
|
14729
|
+
return link(code[cfg.tolerant || cfg.probe ? ip + 2 : ip + 1]);
|
|
14106
14730
|
case OP_RULE:
|
|
14107
14731
|
return link(code[ip + 1]);
|
|
14108
14732
|
case OP_LIVE: {
|
|
@@ -15028,7 +15652,7 @@ function assemble(t2, prog, cfg) {
|
|
|
15028
15652
|
if (table.exclusive) {
|
|
15029
15653
|
const ascii = table.ascii;
|
|
15030
15654
|
const hi = table.hi;
|
|
15031
|
-
if (n === 2) {
|
|
15655
|
+
if (n === 2 && !cfg.probe) {
|
|
15032
15656
|
const a0 = link(code[base]), a1 = link(code[base + 1]);
|
|
15033
15657
|
return (input, pos, ctx) => {
|
|
15034
15658
|
const c = lead(input, pos);
|
|
@@ -15060,7 +15684,7 @@ function assemble(t2, prog, cfg) {
|
|
|
15060
15684
|
return FAIL;
|
|
15061
15685
|
};
|
|
15062
15686
|
}
|
|
15063
|
-
if (n === 3) {
|
|
15687
|
+
if (n === 3 && !cfg.probe) {
|
|
15064
15688
|
const a0 = link(code[base]), a1 = link(code[base + 1]), a2 = link(code[base + 2]);
|
|
15065
15689
|
return (input, pos, ctx) => {
|
|
15066
15690
|
const c = lead(input, pos);
|
|
@@ -15105,6 +15729,7 @@ function assemble(t2, prog, cfg) {
|
|
|
15105
15729
|
);
|
|
15106
15730
|
};
|
|
15107
15731
|
const selected = bindExclusive(0);
|
|
15732
|
+
const probeArms = cfg.probe ? Array.from({ length: n }, (_, i) => link(code[base + i])) : void 0;
|
|
15108
15733
|
return (input, pos, ctx) => {
|
|
15109
15734
|
const c = lead(input, pos);
|
|
15110
15735
|
let arm = -1;
|
|
@@ -15130,12 +15755,13 @@ function assemble(t2, prog, cfg) {
|
|
|
15130
15755
|
return FAIL;
|
|
15131
15756
|
}
|
|
15132
15757
|
}
|
|
15758
|
+
if (arm < 0 && probeArms !== void 0) for (const a of probeArms) a(input, pos, ctx);
|
|
15133
15759
|
ctx._fe = pos;
|
|
15134
15760
|
ctx._fx = choiceFx;
|
|
15135
15761
|
return FAIL;
|
|
15136
15762
|
};
|
|
15137
15763
|
}
|
|
15138
|
-
const armCls = table.armCls;
|
|
15764
|
+
const armCls = cfg.probe ? table.armCls.map(() => null) : table.armCls;
|
|
15139
15765
|
if (n === 2 || n === 3) {
|
|
15140
15766
|
const a0 = link(code[base]), a1 = link(code[base + 1]);
|
|
15141
15767
|
const a2 = n === 3 ? link(code[base + 2]) : void 0;
|
|
@@ -15555,6 +16181,43 @@ function assemble(t2, prog, cfg) {
|
|
|
15555
16181
|
return child(input, pos, ctx);
|
|
15556
16182
|
};
|
|
15557
16183
|
}
|
|
16184
|
+
case OP_RGATE2: {
|
|
16185
|
+
const cls = cc[code[ip + 1]];
|
|
16186
|
+
const xf = fx[code[ip + 3]];
|
|
16187
|
+
const first = cc[code[ip + 4]];
|
|
16188
|
+
const second = cc[code[ip + 5]];
|
|
16189
|
+
const child = link(code[ip + 2]);
|
|
16190
|
+
if (cfg.tolerant || cfg.probe) return child;
|
|
16191
|
+
if (cls.hi.length === 0 && first.hi.length === 0 && second.hi.length === 0) {
|
|
16192
|
+
const a0 = cls.ascii, a1 = first.ascii, a2 = second.ascii;
|
|
16193
|
+
return (input, pos, ctx) => {
|
|
16194
|
+
const item = ctx._routed;
|
|
16195
|
+
if (item !== void 0 && item.span.start === pos) {
|
|
16196
|
+
const e = item.span.end;
|
|
16197
|
+
const c = input.charCodeAt(e);
|
|
16198
|
+
if (a0[c] !== 1 || a1[c] === 1 && a2[input.charCodeAt(e + 1)] !== 1) {
|
|
16199
|
+
ctx._fe = e;
|
|
16200
|
+
ctx._fx = xf;
|
|
16201
|
+
return FAIL;
|
|
16202
|
+
}
|
|
16203
|
+
}
|
|
16204
|
+
return child(input, pos, ctx);
|
|
16205
|
+
};
|
|
16206
|
+
}
|
|
16207
|
+
return (input, pos, ctx) => {
|
|
16208
|
+
const item = ctx._routed;
|
|
16209
|
+
if (item !== void 0 && item.span.start === pos) {
|
|
16210
|
+
const e = item.span.end;
|
|
16211
|
+
const c = lead(input, e);
|
|
16212
|
+
if (!classHas2(cls, c) || classHas2(first, c) && !classHas2(second, lead(input, e + 1))) {
|
|
16213
|
+
ctx._fe = e;
|
|
16214
|
+
ctx._fx = xf;
|
|
16215
|
+
return FAIL;
|
|
16216
|
+
}
|
|
16217
|
+
}
|
|
16218
|
+
return child(input, pos, ctx);
|
|
16219
|
+
};
|
|
16220
|
+
}
|
|
15558
16221
|
case OP_ARMGATE: {
|
|
15559
16222
|
const pred = fns[code[ip + 1]];
|
|
15560
16223
|
const child = link(code[ip + 2]);
|
|
@@ -15622,10 +16285,18 @@ function assemble(t2, prog, cfg) {
|
|
|
15622
16285
|
const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
|
|
15623
16286
|
const itemClass = !REC && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
|
|
15624
16287
|
const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
|
|
16288
|
+
const sepClassIndex = sepIp >= 0 && !sepLeads && (flags & 8) !== 0 ? code[ip + 8] : -1;
|
|
16289
|
+
const sepClass = !REC && sepClassIndex >= 0 && !rowNullable(code, k, sepIp, NULLABLE) ? cc[sepClassIndex] : void 0;
|
|
16290
|
+
const gapIp = sepIp < 0 && min === 0 && !REC && code[code[ip + 1]] === OP_GAPGATE ? code[ip + 1] : -1;
|
|
16291
|
+
const gapRow = gapIp >= 0 ? code[gapIp + 2] : -1;
|
|
16292
|
+
const gapRe = gapIp >= 0 ? k[code[gapRow + 1]] : void 0;
|
|
16293
|
+
const gapFollow = gapIp >= 0 ? cc[code[gapIp + 3]] : void 0;
|
|
16294
|
+
const gapOther = gapIp >= 0 && code[gapIp + 4] >= 0 ? cc[code[gapIp + 4]] : void 0;
|
|
15625
16295
|
const skipBeforeFirst = sepIp < 0 && min === 0;
|
|
15626
16296
|
const itemClean = sepIp < 0 && CLEAN(code[ip + 1]) && !rowNullable(code, k, code[ip + 1], NULLABLE);
|
|
15627
16297
|
if (REC) {
|
|
15628
16298
|
const itemFx2 = fx[code[ip + 6]];
|
|
16299
|
+
const recFx = (flags & 16) !== 0 ? EMPTY_FX2 : itemFx2;
|
|
15629
16300
|
const sepSent = sentinelFor(code[ip + 7]);
|
|
15630
16301
|
return (input, pos, ctx) => {
|
|
15631
16302
|
const out = collect ? [] : void 0;
|
|
@@ -15685,7 +16356,7 @@ function assemble(t2, prog, cfg) {
|
|
|
15685
16356
|
itemStart,
|
|
15686
16357
|
ctx,
|
|
15687
16358
|
sep === void 0 ? mySync : orSentinel(sepSent ?? mySync, sepSent === void 0 ? void 0 : mySync),
|
|
15688
|
-
|
|
16359
|
+
recFx
|
|
15689
16360
|
);
|
|
15690
16361
|
if (out !== void 0) out.push(rr.error);
|
|
15691
16362
|
captureError(ctx, rr.error);
|
|
@@ -15723,6 +16394,7 @@ function assemble(t2, prog, cfg) {
|
|
|
15723
16394
|
const markLater = needMark && (!itemClean || hasTrivia);
|
|
15724
16395
|
const markFirst = needMark && (!itemClean || hasTrivia && skipBeforeFirst);
|
|
15725
16396
|
const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
|
|
16397
|
+
const gateSep = sepClass !== void 0 && ctx._probe === void 0;
|
|
15726
16398
|
let cur = pos;
|
|
15727
16399
|
let count = 0;
|
|
15728
16400
|
for (; ; ) {
|
|
@@ -15745,6 +16417,10 @@ function assemble(t2, prog, cfg) {
|
|
|
15745
16417
|
const leavesBefore = cstLeavesLen(ctx);
|
|
15746
16418
|
let sp = cur;
|
|
15747
16419
|
if (hasTrivia) sp = skipTrivia(input, sp, ctx);
|
|
16420
|
+
if (count >= min && gateSep && !classHas2(sepClass, lead(input, sp))) {
|
|
16421
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
16422
|
+
break;
|
|
16423
|
+
}
|
|
15748
16424
|
ctx._fc = false;
|
|
15749
16425
|
if (sepLeads) LEAD.at = cur;
|
|
15750
16426
|
const sv = sep(input, sp, ctx);
|
|
@@ -15764,13 +16440,30 @@ function assemble(t2, prog, cfg) {
|
|
|
15764
16440
|
if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
|
|
15765
16441
|
break;
|
|
15766
16442
|
}
|
|
15767
|
-
if (count >= min && gateItems && !itemMayStart(input, itemStart)) {
|
|
16443
|
+
if (count >= min && gateItems && (sep !== void 0 || hasTrivia) && !itemMayStart(input, itemStart)) {
|
|
15768
16444
|
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
15769
16445
|
if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
|
|
15770
16446
|
break;
|
|
15771
16447
|
}
|
|
16448
|
+
let gapped = false;
|
|
16449
|
+
if (gapRe !== void 0 && ctx._probe === void 0) {
|
|
16450
|
+
gapRe.lastIndex = itemStart;
|
|
16451
|
+
const q2 = gapRe.test(input) ? gapRe.lastIndex : -1;
|
|
16452
|
+
if ((q2 < 0 || !classHas2(gapFollow, lead(input, q2))) && (gapOther === void 0 || !classHas2(gapOther, lead(input, itemStart)))) {
|
|
16453
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
16454
|
+
break;
|
|
16455
|
+
}
|
|
16456
|
+
if (q2 >= 0) {
|
|
16457
|
+
GAP.row = gapRow;
|
|
16458
|
+
GAP.at = itemStart;
|
|
16459
|
+
GAP.end = q2;
|
|
16460
|
+
GAP.input = input;
|
|
16461
|
+
gapped = true;
|
|
16462
|
+
}
|
|
16463
|
+
}
|
|
15772
16464
|
ctx._fc = false;
|
|
15773
16465
|
const v = child(input, itemStart, ctx);
|
|
16466
|
+
if (gapped) GAP.at = -1;
|
|
15774
16467
|
if (v === FAIL) {
|
|
15775
16468
|
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
15776
16469
|
if (committed3(ctx)) return FAIL;
|
|
@@ -15802,7 +16495,8 @@ function assemble(t2, prog, cfg) {
|
|
|
15802
16495
|
const selector = link(code[ip + 1]);
|
|
15803
16496
|
const otherIp = code[ip + 3];
|
|
15804
16497
|
const other = otherIp >= 0 ? link(otherIp) : void 0;
|
|
15805
|
-
const otherRouted = code[ip + 4] === 1;
|
|
16498
|
+
const otherRouted = (code[ip + 4] & 1) === 1;
|
|
16499
|
+
const otherCommits = (code[ip + 4] & 2) === 0;
|
|
15806
16500
|
const n = code[ip + 5];
|
|
15807
16501
|
const armBase = ip + 6;
|
|
15808
16502
|
const byKey = spec.byKey;
|
|
@@ -15850,7 +16544,7 @@ function assemble(t2, prog, cfg) {
|
|
|
15850
16544
|
);
|
|
15851
16545
|
};
|
|
15852
16546
|
const runArm = n === 0 ? void 0 : bindArms(0);
|
|
15853
|
-
const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted);
|
|
16547
|
+
const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted, otherCommits);
|
|
15854
16548
|
return (input, pos, ctx) => {
|
|
15855
16549
|
const need = markCst(ctx);
|
|
15856
16550
|
const mRaw = MRAW;
|
|
@@ -16111,6 +16805,7 @@ function assemble(t2, prog, cfg) {
|
|
|
16111
16805
|
}
|
|
16112
16806
|
const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
|
|
16113
16807
|
if (pre !== void 0) {
|
|
16808
|
+
assertFactoryArity(pre);
|
|
16114
16809
|
const pools = rebuildPools(t2.cc, t2.fx, t2.disp, pre.plan);
|
|
16115
16810
|
emitted = pre.factory(
|
|
16116
16811
|
EC,
|
|
@@ -16122,7 +16817,6 @@ function assemble(t2, prog, cfg) {
|
|
|
16122
16817
|
pools.classes,
|
|
16123
16818
|
pools.armExpected,
|
|
16124
16819
|
trivia2,
|
|
16125
|
-
trivia2.map((tv) => tv?._meta.triviaKindLabels),
|
|
16126
16820
|
triviaScan,
|
|
16127
16821
|
scansArr,
|
|
16128
16822
|
disp,
|
|
@@ -16146,7 +16840,6 @@ function assemble(t2, prog, cfg) {
|
|
|
16146
16840
|
cstLeavesLen,
|
|
16147
16841
|
skipTriviaScanned,
|
|
16148
16842
|
needsDeferredTriviaCommit,
|
|
16149
|
-
scanTrivia,
|
|
16150
16843
|
advanceTrivia,
|
|
16151
16844
|
refuseUnclassifiedRootScope,
|
|
16152
16845
|
spanLines,
|
|
@@ -16160,8 +16853,6 @@ function assemble(t2, prog, cfg) {
|
|
|
16160
16853
|
orSentinel,
|
|
16161
16854
|
captureError,
|
|
16162
16855
|
scalarRecognizers,
|
|
16163
|
-
commitTriviaScan,
|
|
16164
|
-
scanTriviaCompact,
|
|
16165
16856
|
t2.lex,
|
|
16166
16857
|
adjacencyHolds,
|
|
16167
16858
|
t2.lexPrograms,
|
|
@@ -16173,7 +16864,8 @@ function assemble(t2, prog, cfg) {
|
|
|
16173
16864
|
PlainLeaf9,
|
|
16174
16865
|
PlainNode2,
|
|
16175
16866
|
PlainField,
|
|
16176
|
-
PlainBuf2
|
|
16867
|
+
PlainBuf2,
|
|
16868
|
+
GAP
|
|
16177
16869
|
);
|
|
16178
16870
|
emitReached = new Set(pre.reached);
|
|
16179
16871
|
if (emitted.ext !== void 0) HYBRID = emitted;
|
|
@@ -16209,7 +16901,6 @@ function assemble(t2, prog, cfg) {
|
|
|
16209
16901
|
em.classes,
|
|
16210
16902
|
em.armExpected,
|
|
16211
16903
|
trivia2,
|
|
16212
|
-
trivia2.map((tv) => tv?._meta.triviaKindLabels),
|
|
16213
16904
|
triviaScan,
|
|
16214
16905
|
scansArr,
|
|
16215
16906
|
disp,
|
|
@@ -16233,7 +16924,6 @@ function assemble(t2, prog, cfg) {
|
|
|
16233
16924
|
cstLeavesLen,
|
|
16234
16925
|
skipTriviaScanned,
|
|
16235
16926
|
needsDeferredTriviaCommit,
|
|
16236
|
-
scanTrivia,
|
|
16237
16927
|
advanceTrivia,
|
|
16238
16928
|
refuseUnclassifiedRootScope,
|
|
16239
16929
|
spanLines,
|
|
@@ -16252,8 +16942,6 @@ function assemble(t2, prog, cfg) {
|
|
|
16252
16942
|
orSentinel,
|
|
16253
16943
|
captureError,
|
|
16254
16944
|
scalarRecognizers,
|
|
16255
|
-
commitTriviaScan,
|
|
16256
|
-
scanTriviaCompact,
|
|
16257
16945
|
t2.lex,
|
|
16258
16946
|
adjacencyHolds,
|
|
16259
16947
|
t2.lexPrograms,
|
|
@@ -16265,7 +16953,8 @@ function assemble(t2, prog, cfg) {
|
|
|
16265
16953
|
PlainLeaf9,
|
|
16266
16954
|
PlainNode2,
|
|
16267
16955
|
PlainField,
|
|
16268
|
-
PlainBuf2
|
|
16956
|
+
PlainBuf2,
|
|
16957
|
+
GAP
|
|
16269
16958
|
);
|
|
16270
16959
|
emitReached = em.reached;
|
|
16271
16960
|
} catch (e) {
|
|
@@ -16431,7 +17120,7 @@ var AssemblyCache = class {
|
|
|
16431
17120
|
* That is not a hole in G5, it is G5's own first clause: "quickly building the
|
|
16432
17121
|
* grammar reference ON RUN START, making some swaps on rules or sub-rules, and
|
|
16433
17122
|
* then the run actually runs with no logic branching for that option input"
|
|
16434
|
-
* (`notes/TABLE-DRIVER.md`). This IS the run-start step. What the criterion
|
|
17123
|
+
* (`notes/history/TABLE-DRIVER.md`). This IS the run-start step. What the criterion
|
|
16435
17124
|
* forbids is the second sentence, and past this call there is no option read
|
|
16436
17125
|
* anywhere — `scripts/check-invariants.mjs` INV-6 decides that mechanically.
|
|
16437
17126
|
*
|
|
@@ -16523,11 +17212,8 @@ function tableRules(source, metadataOrEntry = {}) {
|
|
|
16523
17212
|
return map[entry];
|
|
16524
17213
|
}
|
|
16525
17214
|
|
|
16526
|
-
// src/version.ts
|
|
16527
|
-
var PARSEMAN_VERSION = "0.59.3";
|
|
16528
|
-
|
|
16529
17215
|
// src/table/emit.ts
|
|
16530
|
-
var FACTORY_ARITY_GUARD = `if(arguments.length
|
|
17216
|
+
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`)});`;
|
|
16531
17217
|
function jsString(s) {
|
|
16532
17218
|
return JSON.stringify(s);
|
|
16533
17219
|
}
|
|
@@ -16602,7 +17288,7 @@ function emitAssemblies(prog, cfgs) {
|
|
|
16602
17288
|
throw e;
|
|
16603
17289
|
}
|
|
16604
17290
|
const plan = em.plan;
|
|
16605
|
-
out.push(`{key:${key},factory:function(${EMITTED_PARAMS.join(",")}){${FACTORY_ARITY_GUARD}${em.source}
|
|
17291
|
+
out.push(`{key:${key},arity:${EMITTED_PARAMS.length},factory:function(${EMITTED_PARAMS.join(",")}){${FACTORY_ARITY_GUARD}${em.source}
|
|
16606
17292
|
},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(",")}]}`);
|
|
16607
17293
|
}
|
|
16608
17294
|
return [`a:[${out.join(",")}],`];
|
|
@@ -16878,7 +17564,7 @@ function payloadKey(p, d) {
|
|
|
16878
17564
|
case "sepBy":
|
|
16879
17565
|
return `sepBy\0${d.min}\0${d.max ?? ""}\0${d.trailing ?? ""}`;
|
|
16880
17566
|
case "dispatch":
|
|
16881
|
-
return `dispatch\0${d.cases.map((c) => JSON.stringify(c.keys)).join("")}\0${d.otherwise !== void 0}`;
|
|
17567
|
+
return `dispatch\0${d.cases.map((c) => JSON.stringify(c.keys)).join("")}\0${d.otherwise !== void 0}${d.otherwiseCommit === false ? "\0uncommitted" : ""}`;
|
|
16882
17568
|
case "expect":
|
|
16883
17569
|
return `expect\0${d.label ?? ""}\0${d.expected.join("")}`;
|
|
16884
17570
|
case "scanTo":
|