parseman 0.59.3 → 0.60.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analysis/diagnostics.js +874 -188
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/cli/index.js +874 -188
- package/dist/cli/index.js.map +3 -3
- package/dist/combinators/dispatch.d.ts +13 -1
- package/dist/combinators/dispatch.d.ts.map +1 -1
- package/dist/combinators/first-set.d.ts +35 -2
- package/dist/combinators/first-set.d.ts.map +1 -1
- package/dist/combinators/regex.d.ts.map +1 -1
- package/dist/combinators/trivia-boundary.d.ts +11 -0
- package/dist/combinators/trivia-boundary.d.ts.map +1 -1
- package/dist/combinators/trivia-skip.d.ts +1 -1
- package/dist/combinators/trivia-skip.d.ts.map +1 -1
- package/dist/compiler/token-alphabet.d.ts +2 -0
- package/dist/compiler/token-alphabet.d.ts.map +1 -1
- package/dist/compiler/token-capability.js +65 -53
- package/dist/compiler/token-capability.js.map +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +894 -197
- package/dist/index.js.map +3 -3
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.js +901 -199
- package/dist/plugin/index.js.map +3 -3
- package/dist/regex/first-set.d.ts +19 -0
- package/dist/regex/first-set.d.ts.map +1 -1
- package/dist/table/assemble.d.ts +14 -0
- package/dist/table/assemble.d.ts.map +1 -1
- package/dist/table/child-slots.d.ts.map +1 -1
- package/dist/table/compile-rule-map.d.ts.map +1 -1
- package/dist/table/emit-assembly.d.ts +8 -2
- package/dist/table/emit-assembly.d.ts.map +1 -1
- package/dist/table/emit.d.ts +4 -3
- package/dist/table/emit.d.ts.map +1 -1
- package/dist/table/encode.d.ts.map +1 -1
- package/dist/table/exec.d.ts.map +1 -1
- package/dist/table/factor-choice.d.ts +27 -0
- package/dist/table/factor-choice.d.ts.map +1 -1
- package/dist/table/gap-gate.d.ts +11 -0
- package/dist/table/gap-gate.d.ts.map +1 -0
- package/dist/table/index.js +924 -199
- package/dist/table/index.js.map +3 -3
- package/dist/table/lex-program.d.ts.map +1 -1
- package/dist/table/ops.d.ts +34 -6
- package/dist/table/ops.d.ts.map +1 -1
- package/dist/table/program.d.ts +6 -1
- package/dist/table/program.d.ts.map +1 -1
- package/dist/types.d.ts +16 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/analysis/duplication.ts +1 -1
- package/src/combinators/attempt.ts +1 -1
- package/src/combinators/dispatch.ts +30 -6
- package/src/combinators/first-set.ts +55 -12
- package/src/combinators/node.ts +1 -1
- package/src/combinators/regex.ts +9 -4
- package/src/combinators/repeat.ts +6 -6
- package/src/combinators/sequence.ts +1 -1
- package/src/combinators/trivia-boundary.ts +18 -0
- package/src/combinators/trivia-skip.ts +1 -1
- package/src/compiler/ir-serialize.ts +1 -1
- package/src/compiler/token-alphabet.ts +3 -1
- package/src/coverage.ts +1 -1
- package/src/index.ts +1 -1
- package/src/plugin/evaluator.ts +8 -3
- package/src/regex/first-set.ts +37 -3
- package/src/table/assemble.ts +171 -25
- package/src/table/child-slots.ts +8 -3
- package/src/table/compile-rule-map.ts +6 -3
- package/src/table/emit-assembly.ts +182 -31
- package/src/table/emit.ts +6 -4
- package/src/table/encode.ts +468 -73
- package/src/table/exec.ts +38 -13
- package/src/table/factor-choice.ts +62 -0
- package/src/table/fail-clean.ts +2 -2
- package/src/table/gap-gate.ts +55 -0
- package/src/table/hold-gap.ts +2 -2
- package/src/table/lex-program.ts +15 -6
- package/src/table/ops.ts +37 -6
- package/src/table/program.ts +7 -2
- package/src/table/select-hot.ts +7 -2
- package/src/types.ts +12 -5
- package/src/version.ts +1 -1
|
@@ -27,15 +27,56 @@ function implicitLeadsDropped(ranges) {
|
|
|
27
27
|
return out;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
// src/combinators/trivia-boundary.ts
|
|
31
|
+
var MAX_DEPTH = 12;
|
|
32
|
+
function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
|
|
33
|
+
if (depth === 0) return true;
|
|
34
|
+
const d = p._def;
|
|
35
|
+
switch (d.tag) {
|
|
36
|
+
// Multi-term forms: the gaps BETWEEN terms are the ambient-trivia positions.
|
|
37
|
+
case "sequence":
|
|
38
|
+
return d.parsers.length > 1;
|
|
39
|
+
case "many":
|
|
40
|
+
case "oneOrMore":
|
|
41
|
+
case "sepBy":
|
|
42
|
+
return true;
|
|
43
|
+
// Transparent wrappers — they add no position, so ask what they wrap.
|
|
44
|
+
case "node":
|
|
45
|
+
case "transform":
|
|
46
|
+
case "leaf":
|
|
47
|
+
case "label":
|
|
48
|
+
case "field":
|
|
49
|
+
case "token":
|
|
50
|
+
case "attempt":
|
|
51
|
+
case "optional":
|
|
52
|
+
case "expect":
|
|
53
|
+
case "withCtx":
|
|
54
|
+
case "recover":
|
|
55
|
+
case "trivia":
|
|
56
|
+
return hasOwnTriviaBoundary(d.parser, depth - 1);
|
|
57
|
+
// An alternation adds no position either, but ONE arm that has one is enough
|
|
58
|
+
// to make the scope meaningful for this rule.
|
|
59
|
+
case "choice":
|
|
60
|
+
return d.parsers.some((a) => hasOwnTriviaBoundary(a, depth - 1));
|
|
61
|
+
default:
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function triviaThroughRef(ref2, target, trivia2) {
|
|
66
|
+
if (trivia2 !== void 0 && trivia2 !== null) return trivia2;
|
|
67
|
+
const amb = ref2._meta.grammarTrivia ?? target._meta.grammarTrivia;
|
|
68
|
+
return amb !== void 0 && hasOwnTriviaBoundary(target) ? amb : trivia2;
|
|
69
|
+
}
|
|
70
|
+
|
|
30
71
|
// src/combinators/first-set.ts
|
|
31
|
-
function classifyFinalChoice(arms, resolve, activeTrivia) {
|
|
72
|
+
function classifyFinalChoice(arms, resolve, activeTrivia, consuming = true, constructionSets = false) {
|
|
32
73
|
const firstSets = [];
|
|
33
74
|
const nullable2 = [];
|
|
34
75
|
let exclusive = true;
|
|
35
76
|
for (const arm of arms) {
|
|
36
77
|
const empty2 = matchesEmpty(arm, /* @__PURE__ */ new Set(), resolve);
|
|
37
78
|
nullable2.push(empty2);
|
|
38
|
-
firstSets.push(empty2 ? { kind: "any" } : firstSetOf(arm, /* @__PURE__ */ new Set(), resolve, activeTrivia));
|
|
79
|
+
firstSets.push(empty2 ? { kind: "any" } : constructionSets ? arm._meta.firstSet : firstSetOf(arm, /* @__PURE__ */ new Set(), resolve, activeTrivia, consuming));
|
|
39
80
|
if (empty2) exclusive = false;
|
|
40
81
|
}
|
|
41
82
|
if (exclusive) {
|
|
@@ -220,7 +261,7 @@ function narrowBy(acc, constraint) {
|
|
|
220
261
|
function applyAssertion(fs, assertion) {
|
|
221
262
|
return assertion === null ? fs : fs.kind === "empty" ? assertion : narrowBy(fs, assertion);
|
|
222
263
|
}
|
|
223
|
-
function sequenceSet(parsers, fs, empties, trivia2) {
|
|
264
|
+
function sequenceSet(parsers, fs, empties, trivia2, consuming = true) {
|
|
224
265
|
const afterBoundary = (i) => {
|
|
225
266
|
const rest = at(i);
|
|
226
267
|
return trivia2 ? union(rest, fs(trivia2)) : rest;
|
|
@@ -236,24 +277,24 @@ function sequenceSet(parsers, fs, empties, trivia2) {
|
|
|
236
277
|
}
|
|
237
278
|
const first = fs(p);
|
|
238
279
|
if (!empties(p) || i + 1 === parsers.length) return first;
|
|
239
|
-
return union(first, afterBoundary(i + 1));
|
|
280
|
+
return union((consuming ? p._meta.consumingFirstSet : void 0) ?? first, afterBoundary(i + 1));
|
|
240
281
|
};
|
|
241
282
|
return at(0);
|
|
242
283
|
}
|
|
243
284
|
function sequenceFirstSet(parsers) {
|
|
244
|
-
return sequenceSet(parsers, (p) => p._meta.firstSet, matchesEmpty);
|
|
285
|
+
return sequenceSet(parsers, (p) => p._meta.firstSet, matchesEmpty, void 0, false);
|
|
245
286
|
}
|
|
246
|
-
function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve, activeTrivia) {
|
|
287
|
+
function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve, activeTrivia, consuming = true) {
|
|
247
288
|
if (seen.has(p)) return any();
|
|
248
289
|
seen.add(p);
|
|
249
290
|
try {
|
|
250
|
-
return firstSetBody(p, seen, resolve, activeTrivia);
|
|
291
|
+
return firstSetBody(p, seen, resolve, activeTrivia, consuming);
|
|
251
292
|
} finally {
|
|
252
293
|
seen.delete(p);
|
|
253
294
|
}
|
|
254
295
|
}
|
|
255
|
-
function firstSetBody(p, seen, resolve, activeTrivia) {
|
|
256
|
-
const fs = (c) => firstSetOf(c, seen, resolve, activeTrivia);
|
|
296
|
+
function firstSetBody(p, seen, resolve, activeTrivia, consuming) {
|
|
297
|
+
const fs = (c) => firstSetOf(c, seen, resolve, activeTrivia, consuming);
|
|
257
298
|
const empties = (c) => matchesEmpty(c, /* @__PURE__ */ new Set(), resolve);
|
|
258
299
|
const d = p._def;
|
|
259
300
|
switch (d.tag) {
|
|
@@ -265,13 +306,16 @@ function firstSetBody(p, seen, resolve, activeTrivia) {
|
|
|
265
306
|
case "dispatch":
|
|
266
307
|
return fs(d.selector);
|
|
267
308
|
case "lazy": {
|
|
268
|
-
|
|
269
|
-
if (
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
309
|
+
let target = winnerForRef(p, resolve);
|
|
310
|
+
if (target === void 0) {
|
|
311
|
+
try {
|
|
312
|
+
target = d.thunk();
|
|
313
|
+
} catch {
|
|
314
|
+
return any();
|
|
315
|
+
}
|
|
274
316
|
}
|
|
317
|
+
const through = activeTrivia === null && resolve !== void 0;
|
|
318
|
+
return firstSetOf(target, seen, resolve, through ? triviaThroughRef(p, target, null) : activeTrivia, consuming);
|
|
275
319
|
}
|
|
276
320
|
case "choice": {
|
|
277
321
|
let out = empty();
|
|
@@ -279,7 +323,7 @@ function firstSetBody(p, seen, resolve, activeTrivia) {
|
|
|
279
323
|
return out;
|
|
280
324
|
}
|
|
281
325
|
case "sequence": {
|
|
282
|
-
return sequenceSet(d.parsers, fs, empties, activeTrivia);
|
|
326
|
+
return sequenceSet(d.parsers, fs, empties, activeTrivia, consuming);
|
|
283
327
|
}
|
|
284
328
|
case "peek": {
|
|
285
329
|
const inner = d.parser;
|
|
@@ -291,7 +335,6 @@ function firstSetBody(p, seen, resolve, activeTrivia) {
|
|
|
291
335
|
case "transform":
|
|
292
336
|
case "label":
|
|
293
337
|
case "trivia":
|
|
294
|
-
case "token":
|
|
295
338
|
case "leaf":
|
|
296
339
|
case "node":
|
|
297
340
|
case "sepBy":
|
|
@@ -301,12 +344,16 @@ function firstSetBody(p, seen, resolve, activeTrivia) {
|
|
|
301
344
|
// with a rule reference — resolve through it like any other wrapper.
|
|
302
345
|
case "attempt":
|
|
303
346
|
return fs(d.parser);
|
|
347
|
+
// A token runs its body with trivia cleared (`token.ts`).
|
|
348
|
+
case "token":
|
|
349
|
+
return firstSetOf(d.parser, seen, resolve, activeTrivia === void 0 ? void 0 : null, consuming);
|
|
304
350
|
case "grammar":
|
|
305
351
|
return firstSetOf(
|
|
306
352
|
d.parser,
|
|
307
353
|
seen,
|
|
308
354
|
resolve,
|
|
309
|
-
d.clearTrivia ? null : d.triviaParser ?? activeTrivia
|
|
355
|
+
d.clearTrivia ? null : d.triviaParser ?? activeTrivia,
|
|
356
|
+
consuming
|
|
310
357
|
);
|
|
311
358
|
// A run starts with its first line's prefix; a nullable prefix starts with anything.
|
|
312
359
|
case "lines": {
|
|
@@ -1783,10 +1830,6 @@ function scanTriviaCompact(input, cur, ctx) {
|
|
|
1783
1830
|
const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
|
|
1784
1831
|
return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
|
|
1785
1832
|
}
|
|
1786
|
-
function scanTrivia(input, cur, ctx) {
|
|
1787
|
-
const scan = scanTriviaCompact(input, cur, ctx);
|
|
1788
|
-
return typeof scan === "number" ? { end: scan, commit: NOOP_COMMIT } : scan;
|
|
1789
|
-
}
|
|
1790
1833
|
function skipTriviaScanned(s, input, cur, ctx) {
|
|
1791
1834
|
const end = s(input, cur);
|
|
1792
1835
|
if (end !== cur) {
|
|
@@ -3093,9 +3136,9 @@ function many(combinator, opts = {}) {
|
|
|
3093
3136
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
3094
3137
|
isTrivia: false
|
|
3095
3138
|
};
|
|
3096
|
-
const def = { tag: "many", parser: combinator, min: 0, ...max === Infinity ? {} : { max } };
|
|
3097
|
-
let expected;
|
|
3098
3139
|
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
3140
|
+
const def = { tag: "many", parser: combinator, min: 0, ...max === Infinity ? {} : { max }, ...guardable ? { guarded: true } : {} };
|
|
3141
|
+
let expected;
|
|
3099
3142
|
const scalarChild = scalarOf(combinator);
|
|
3100
3143
|
const parseScalar = (input, pos, ctx) => repeatScalarTail(combinator, scalarChild, input, pos, ctx, guardable, def.valueUnused ? void 0 : [], max);
|
|
3101
3144
|
return {
|
|
@@ -3142,9 +3185,9 @@ function atLeast(combinator, min, max) {
|
|
|
3142
3185
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
3143
3186
|
isTrivia: false
|
|
3144
3187
|
};
|
|
3145
|
-
const def = { tag: "oneOrMore", parser: combinator, min, ...max === Infinity ? {} : { max } };
|
|
3146
|
-
let expected;
|
|
3147
3188
|
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
3189
|
+
const def = { tag: "oneOrMore", parser: combinator, min, ...max === Infinity ? {} : { max }, ...guardable ? { guarded: true } : {} };
|
|
3190
|
+
let expected;
|
|
3148
3191
|
const scalarChild = scalarOf(combinator);
|
|
3149
3192
|
const parseScalar = (input, pos, ctx) => {
|
|
3150
3193
|
let cur = scalarChild(input, pos, ctx);
|
|
@@ -3632,10 +3675,12 @@ function parseRegex(src, unicode = false, sets = false) {
|
|
|
3632
3675
|
const parseGroup = () => {
|
|
3633
3676
|
i++;
|
|
3634
3677
|
let lookaround = false;
|
|
3678
|
+
let lookahead = false;
|
|
3635
3679
|
if (src[i] === "?") {
|
|
3636
3680
|
const c1 = src[i + 1];
|
|
3637
3681
|
if (c1 === ":") i += 2;
|
|
3638
3682
|
else if (c1 === "=" || c1 === "!") {
|
|
3683
|
+
lookahead = c1 === "=";
|
|
3639
3684
|
i += 2;
|
|
3640
3685
|
lookaround = true;
|
|
3641
3686
|
} else if (c1 === "<") {
|
|
@@ -3653,7 +3698,8 @@ function parseRegex(src, unicode = false, sets = false) {
|
|
|
3653
3698
|
const inner = parseAlt();
|
|
3654
3699
|
if (src[i] !== ")") throw BAIL;
|
|
3655
3700
|
i++;
|
|
3656
|
-
|
|
3701
|
+
if (lookaround) return lookahead ? { t: "empty", look: inner } : EMPTY2;
|
|
3702
|
+
return inner;
|
|
3657
3703
|
};
|
|
3658
3704
|
const parseClass = () => {
|
|
3659
3705
|
let k = i + 1;
|
|
@@ -3846,6 +3892,13 @@ function regexCanMatchEmpty(source) {
|
|
|
3846
3892
|
return true;
|
|
3847
3893
|
}
|
|
3848
3894
|
}
|
|
3895
|
+
function consumingFirstSetFromRegex(source, flags = "") {
|
|
3896
|
+
try {
|
|
3897
|
+
return firstSet(parseRegex(source, flags.includes("u") || flags.includes("v"), flags.includes("v")));
|
|
3898
|
+
} catch {
|
|
3899
|
+
return any();
|
|
3900
|
+
}
|
|
3901
|
+
}
|
|
3849
3902
|
function firstSetFromRegex(source, flags = "") {
|
|
3850
3903
|
let ast;
|
|
3851
3904
|
try {
|
|
@@ -3856,6 +3909,20 @@ function firstSetFromRegex(source, flags = "") {
|
|
|
3856
3909
|
if (nullable(ast)) return { firstSet: any(), canMatchNewline: canConsumeNewline(ast) };
|
|
3857
3910
|
return { firstSet: firstSet(ast), canMatchNewline: canConsumeNewline(ast) };
|
|
3858
3911
|
}
|
|
3912
|
+
function regexFirstTwo(source, flags = "") {
|
|
3913
|
+
let ast;
|
|
3914
|
+
try {
|
|
3915
|
+
ast = parseRegex(source, flags.includes("u") || flags.includes("v"), flags.includes("v"));
|
|
3916
|
+
} catch {
|
|
3917
|
+
return void 0;
|
|
3918
|
+
}
|
|
3919
|
+
const parts = ast.t === "seq" ? ast.parts : [ast];
|
|
3920
|
+
const a = parts[0];
|
|
3921
|
+
const b = parts[1];
|
|
3922
|
+
if (a === void 0 || a.t !== "char" || a.set.kind !== "ranges" || b === void 0) return void 0;
|
|
3923
|
+
const second = b.t === "char" ? b.set : b.t === "empty" && b.look !== void 0 && !nullable(b.look) ? firstSet(b.look) : void 0;
|
|
3924
|
+
return second !== void 0 && second.kind === "ranges" ? { first: a.set, second } : void 0;
|
|
3925
|
+
}
|
|
3859
3926
|
|
|
3860
3927
|
// src/combinators/regex.ts
|
|
3861
3928
|
import { PlainLeaf as PlainLeaf3, PlainSpan as PlainSpan5 } from "../cst/plain.js";
|
|
@@ -3936,9 +4003,14 @@ function regex(pattern, flags = "") {
|
|
|
3936
4003
|
const anchored = new RegExp(source, "y" + resolvedFlags.replace(/[gy]/g, ""));
|
|
3937
4004
|
const scan = shortScanner(source, resolvedFlags);
|
|
3938
4005
|
const raw = firstSetFromRegex(source, resolvedFlags);
|
|
3939
|
-
const
|
|
4006
|
+
const forFlags = (fs) => !resolvedFlags.includes("i") ? fs : resolvedFlags.includes("u") || resolvedFlags.includes("v") ? any() : asciiCaseFold(fs);
|
|
4007
|
+
const firstSet2 = forFlags(raw.firstSet);
|
|
3940
4008
|
const canMatchNewline = raw.canMatchNewline;
|
|
3941
4009
|
const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
|
|
4010
|
+
if (firstSet2.kind === "any" && regexCanMatchEmpty(source)) {
|
|
4011
|
+
const consuming = forFlags(consumingFirstSetFromRegex(source, resolvedFlags));
|
|
4012
|
+
if (consuming.kind !== "any") meta.consumingFirstSet = consuming;
|
|
4013
|
+
}
|
|
3942
4014
|
const def = { tag: "regex", source, flags: resolvedFlags };
|
|
3943
4015
|
const expected = directTerminalFailureExpected(def);
|
|
3944
4016
|
const parseScalar = (input, pos, ctx) => {
|
|
@@ -4213,14 +4285,15 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
4213
4285
|
return end < 0 ? next(input, pos) : end;
|
|
4214
4286
|
};
|
|
4215
4287
|
}
|
|
4216
|
-
let tail = (
|
|
4288
|
+
let tail = (input, pos, ctx, _lead, acc, _best, entered) => {
|
|
4289
|
+
if (!entered && ctx._probe !== void 0) for (const arm of arms) arm.run(input, pos, ctx);
|
|
4217
4290
|
ctx._fe = pos;
|
|
4218
4291
|
ctx._fx = acc ?? choiceExpected;
|
|
4219
4292
|
return -1;
|
|
4220
4293
|
};
|
|
4221
4294
|
for (let i = arms.length - 1; i >= 0; i--) {
|
|
4222
4295
|
const armRun = arms[i].run, cls = classes[i], staticExpected = armExpected[i], next = tail;
|
|
4223
|
-
tail = (input, pos, ctx, lead2, acc, best) => {
|
|
4296
|
+
tail = (input, pos, ctx, lead2, acc, best, entered) => {
|
|
4224
4297
|
if (cls !== void 0 && !classHas(cls, lead2)) {
|
|
4225
4298
|
return next(
|
|
4226
4299
|
input,
|
|
@@ -4228,7 +4301,8 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
4228
4301
|
ctx,
|
|
4229
4302
|
lead2,
|
|
4230
4303
|
best === pos ? appendExpected(acc, staticExpected) : acc,
|
|
4231
|
-
best
|
|
4304
|
+
best,
|
|
4305
|
+
entered
|
|
4232
4306
|
);
|
|
4233
4307
|
}
|
|
4234
4308
|
ctx._fc = false;
|
|
@@ -4244,7 +4318,7 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
4244
4318
|
if (nextAcc !== void 0) ctx._fx = nextAcc;
|
|
4245
4319
|
return -1;
|
|
4246
4320
|
}
|
|
4247
|
-
return next(input, pos, ctx, lead2, nextAcc, best);
|
|
4321
|
+
return next(input, pos, ctx, lead2, nextAcc, best, true);
|
|
4248
4322
|
};
|
|
4249
4323
|
}
|
|
4250
4324
|
return {
|
|
@@ -4255,7 +4329,8 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
4255
4329
|
ctx,
|
|
4256
4330
|
pos < input.length ? input.codePointAt(pos) : -1,
|
|
4257
4331
|
void 0,
|
|
4258
|
-
pos
|
|
4332
|
+
pos,
|
|
4333
|
+
false
|
|
4259
4334
|
)
|
|
4260
4335
|
};
|
|
4261
4336
|
}
|
|
@@ -4293,6 +4368,7 @@ function exclusiveChoiceNode(arms, classes, choiceFx) {
|
|
|
4293
4368
|
return -1;
|
|
4294
4369
|
}
|
|
4295
4370
|
}
|
|
4371
|
+
if (arm < 0 && ctx._probe !== void 0) for (const a of arms) a.run(input, pos, ctx);
|
|
4296
4372
|
ctx._fe = pos;
|
|
4297
4373
|
ctx._fx = choiceFx;
|
|
4298
4374
|
return -1;
|
|
@@ -4517,6 +4593,7 @@ function buildLexProgramRunner(spec, matchers, classes, expected) {
|
|
|
4517
4593
|
if (!classHas(cls, lead2)) {
|
|
4518
4594
|
ctx._fe = pos;
|
|
4519
4595
|
ctx._fx = choiceFx.slice();
|
|
4596
|
+
if (ctx._probe !== void 0) failAt(ctx, [...x0, ...x1, ...x2, ...x3], pos);
|
|
4520
4597
|
return -1;
|
|
4521
4598
|
}
|
|
4522
4599
|
let acc;
|
|
@@ -4628,7 +4705,7 @@ function validateDispatchSpec(spec, arity, fallbackRouted) {
|
|
|
4628
4705
|
for (const arm of arms) if (!Number.isInteger(arm) || arm < 0 || arm >= arity) return true;
|
|
4629
4706
|
return false;
|
|
4630
4707
|
};
|
|
4631
|
-
if (spec === void 0 || !Number.isInteger(arity) || arity < 0 || fallbackRouted
|
|
4708
|
+
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]]))) {
|
|
4632
4709
|
throw new TypeError("table: malformed dispatch");
|
|
4633
4710
|
}
|
|
4634
4711
|
}
|
|
@@ -4942,7 +5019,7 @@ function sequence(...parsers) {
|
|
|
4942
5019
|
if (tolerant) {
|
|
4943
5020
|
followSentinels ??= parsers.map((_, i) => firstSetSentinel(
|
|
4944
5021
|
parsers.slice(i + 1).reduce(
|
|
4945
|
-
(set, parser2) => union(set, firstSetOf(parser2)),
|
|
5022
|
+
(set, parser2) => union(set, firstSetOf(parser2, /* @__PURE__ */ new Set(), void 0, void 0, false)),
|
|
4946
5023
|
{ kind: "empty" }
|
|
4947
5024
|
)
|
|
4948
5025
|
));
|
|
@@ -5398,7 +5475,7 @@ function attempt(parser2, options) {
|
|
|
5398
5475
|
return {
|
|
5399
5476
|
_tag: "attempt",
|
|
5400
5477
|
_meta: parser2._meta,
|
|
5401
|
-
_def:
|
|
5478
|
+
_def: { tag: "attempt", parser: parser2, ...contain ? { contain: true } : {}, ...guardable ? { guarded: true } : {} },
|
|
5402
5479
|
parse(input, pos, ctx) {
|
|
5403
5480
|
if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(parser2, input, pos)) {
|
|
5404
5481
|
if (failExpected === void 0) {
|
|
@@ -6215,6 +6292,7 @@ function reachesMarked(root, successors, memo) {
|
|
|
6215
6292
|
}
|
|
6216
6293
|
|
|
6217
6294
|
// src/table/factor-choice.ts
|
|
6295
|
+
var factoredChoices = /* @__PURE__ */ new WeakSet();
|
|
6218
6296
|
var DERIVED = /* @__PURE__ */ new Set(["_tag", "_meta", "_def", "_parseScalar", "_stickyRegex", "parse"]);
|
|
6219
6297
|
function isCombinator(v) {
|
|
6220
6298
|
return typeof v === "object" && v !== null && "_def" in v && "_meta" in v;
|
|
@@ -6306,6 +6384,7 @@ function factorSharedEnds(d) {
|
|
|
6306
6384
|
for (let i = at + 1; i < n; i++) if (!never(first.terms[i])) return void 0;
|
|
6307
6385
|
if (arms.some((a) => mayCommitFailure(a))) return void 0;
|
|
6308
6386
|
const middle = choice(...shapes.map((s) => s.terms[at]));
|
|
6387
|
+
factoredChoices.add(middle);
|
|
6309
6388
|
if (middle._def.tag === "choice" && middle._def.autoNot.some((a) => a !== null)) return void 0;
|
|
6310
6389
|
const st = middle._def.tag === "choice" ? middle._def.strategy : void 0;
|
|
6311
6390
|
if (st === void 0 || st.tag !== "firstMatch" && st.tag !== "sharedPrefix" && !(st.tag === "literalsLongestFirst" && st.sortedIndices.every((x, i) => x === i))) return void 0;
|
|
@@ -6318,6 +6397,37 @@ function factorSharedEnds(d) {
|
|
|
6318
6397
|
for (let j = first.wrappers.length - 1; j >= 0 && out !== void 0; j--) out = rewrap(first.wrappers[j], out);
|
|
6319
6398
|
return out === void 0 ? void 0 : attempt(out);
|
|
6320
6399
|
}
|
|
6400
|
+
function factorPrefixArms(d) {
|
|
6401
|
+
const arms = d.parsers;
|
|
6402
|
+
if (arms.length < 2) return void 0;
|
|
6403
|
+
if (d.strategy.tag !== "firstMatch" && d.strategy.tag !== "sharedPrefix") return void 0;
|
|
6404
|
+
if (d.gates.some((g) => g !== null) || d.autoNot.some((a) => a !== null)) return void 0;
|
|
6405
|
+
const out = [...arms];
|
|
6406
|
+
let changed = false;
|
|
6407
|
+
for (let i = 0; i + 1 < arms.length; i++) {
|
|
6408
|
+
const arm = arms[i];
|
|
6409
|
+
if (arm._def.tag !== "sequence" || arm._def.valueUnused !== true) continue;
|
|
6410
|
+
const terms = arm._def.parsers;
|
|
6411
|
+
const next = arms[i + 1];
|
|
6412
|
+
const prefix = next._def.tag === "sequence" && next._def.valueUnused === true ? next._def.parsers : [next];
|
|
6413
|
+
if (prefix.length >= terms.length) continue;
|
|
6414
|
+
if (!prefix.every((t2, j) => sameComb(t2, terms[j], 0))) continue;
|
|
6415
|
+
const rest = terms.slice(prefix.length);
|
|
6416
|
+
if (rest.every(never)) continue;
|
|
6417
|
+
const tail = rest.length === 1 ? rest[0] : sequence(...rest);
|
|
6418
|
+
if (tail !== rest[0]) tail._def.valueUnused = true;
|
|
6419
|
+
const parts = [...terms.slice(0, prefix.length), optional(tail)];
|
|
6420
|
+
const seq = sequence(...parts);
|
|
6421
|
+
seq._def.valueUnused = true;
|
|
6422
|
+
out[i] = seq;
|
|
6423
|
+
changed = true;
|
|
6424
|
+
}
|
|
6425
|
+
if (!changed) return void 0;
|
|
6426
|
+
const rebuilt = choice(...out);
|
|
6427
|
+
factoredChoices.add(rebuilt);
|
|
6428
|
+
const st = rebuilt._def.tag === "choice" ? rebuilt._def.strategy : void 0;
|
|
6429
|
+
return st !== void 0 && (st.tag === "firstMatch" || st.tag === "sharedPrefix") ? rebuilt : void 0;
|
|
6430
|
+
}
|
|
6321
6431
|
|
|
6322
6432
|
// src/compiler/fields.ts
|
|
6323
6433
|
function buildReadsFields(def) {
|
|
@@ -6503,6 +6613,9 @@ var OP_LEX_BODY = 42;
|
|
|
6503
6613
|
var OP_LEX_PROGRAM = 43;
|
|
6504
6614
|
var OP_SOURCE_LEAF = 44;
|
|
6505
6615
|
var OP_RGATE = 45;
|
|
6616
|
+
var OP_GAPGATE = 46;
|
|
6617
|
+
var OP_RGATE2 = 47;
|
|
6618
|
+
var OP_STRICT = 48;
|
|
6506
6619
|
var OP_DISPATCH = 25;
|
|
6507
6620
|
var OP_ROUTED = 26;
|
|
6508
6621
|
var OP_NAMES = {
|
|
@@ -6550,7 +6663,10 @@ var OP_NAMES = {
|
|
|
6550
6663
|
[OP_COV]: "COV",
|
|
6551
6664
|
[OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
|
|
6552
6665
|
[OP_LEX_BODY]: "LEX_BODY",
|
|
6553
|
-
[OP_LEX_PROGRAM]: "LEX_PROGRAM"
|
|
6666
|
+
[OP_LEX_PROGRAM]: "LEX_PROGRAM",
|
|
6667
|
+
[OP_GAPGATE]: "GAPGATE",
|
|
6668
|
+
[OP_RGATE2]: "RGATE2",
|
|
6669
|
+
[OP_STRICT]: "STRICT"
|
|
6554
6670
|
};
|
|
6555
6671
|
|
|
6556
6672
|
// src/combinators/node.ts
|
|
@@ -6595,7 +6711,7 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
6595
6711
|
if (project !== void 0 && build !== void 0) {
|
|
6596
6712
|
throw new Error("node() options cannot combine project with a build callback");
|
|
6597
6713
|
}
|
|
6598
|
-
const baseDef = { tag: "node", parser: combinator, ...type === void 0 ? {} : { type }, ...build === void 0 ? {} : { build } };
|
|
6714
|
+
const baseDef = { tag: "node", parser: combinator, ...type === void 0 ? {} : { type }, ...build === void 0 ? {} : { build }, ...combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator) ? { guarded: true } : {} };
|
|
6599
6715
|
const meta = {
|
|
6600
6716
|
firstSet: combinator._meta.firstSet,
|
|
6601
6717
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
@@ -6670,42 +6786,6 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
6670
6786
|
};
|
|
6671
6787
|
}
|
|
6672
6788
|
|
|
6673
|
-
// src/combinators/trivia-boundary.ts
|
|
6674
|
-
var MAX_DEPTH = 12;
|
|
6675
|
-
function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
|
|
6676
|
-
if (depth === 0) return true;
|
|
6677
|
-
const d = p._def;
|
|
6678
|
-
switch (d.tag) {
|
|
6679
|
-
// Multi-term forms: the gaps BETWEEN terms are the ambient-trivia positions.
|
|
6680
|
-
case "sequence":
|
|
6681
|
-
return d.parsers.length > 1;
|
|
6682
|
-
case "many":
|
|
6683
|
-
case "oneOrMore":
|
|
6684
|
-
case "sepBy":
|
|
6685
|
-
return true;
|
|
6686
|
-
// Transparent wrappers — they add no position, so ask what they wrap.
|
|
6687
|
-
case "node":
|
|
6688
|
-
case "transform":
|
|
6689
|
-
case "leaf":
|
|
6690
|
-
case "label":
|
|
6691
|
-
case "field":
|
|
6692
|
-
case "token":
|
|
6693
|
-
case "attempt":
|
|
6694
|
-
case "optional":
|
|
6695
|
-
case "expect":
|
|
6696
|
-
case "withCtx":
|
|
6697
|
-
case "recover":
|
|
6698
|
-
case "trivia":
|
|
6699
|
-
return hasOwnTriviaBoundary(d.parser, depth - 1);
|
|
6700
|
-
// An alternation adds no position either, but ONE arm that has one is enough
|
|
6701
|
-
// to make the scope meaningful for this rule.
|
|
6702
|
-
case "choice":
|
|
6703
|
-
return d.parsers.some((a) => hasOwnTriviaBoundary(a, depth - 1));
|
|
6704
|
-
default:
|
|
6705
|
-
return false;
|
|
6706
|
-
}
|
|
6707
|
-
}
|
|
6708
|
-
|
|
6709
6789
|
// src/compiler/direct-projection.ts
|
|
6710
6790
|
function directArrayProjection(fn, fnSrc, arity) {
|
|
6711
6791
|
let source = fnSrc;
|
|
@@ -6994,6 +7074,7 @@ function directFixedLexNode(parser2, resolve, active, pureOnly = false, cleared
|
|
|
6994
7074
|
arms,
|
|
6995
7075
|
parsers: def.parsers,
|
|
6996
7076
|
cleared,
|
|
7077
|
+
disjoint: def.disjoint,
|
|
6997
7078
|
armExpected: def.parsers.map(deriveExpected),
|
|
6998
7079
|
expected: def.parsers.flatMap(deriveExpected)
|
|
6999
7080
|
};
|
|
@@ -7103,6 +7184,29 @@ var UnsupportedConstruct = class extends Error {
|
|
|
7103
7184
|
this.tag = tag;
|
|
7104
7185
|
}
|
|
7105
7186
|
};
|
|
7187
|
+
function firstTwo(p) {
|
|
7188
|
+
const d = p._def;
|
|
7189
|
+
if (d.tag === "label" || d.tag === "grammar") return firstTwo(d.parser);
|
|
7190
|
+
let two;
|
|
7191
|
+
if (d.tag === "literal" && d.value.length >= 2 && d.caseInsensitive !== true) {
|
|
7192
|
+
const second = d.value.codePointAt(1);
|
|
7193
|
+
two = { first: { kind: "ranges", ranges: [{ lo: d.value.charCodeAt(0), hi: d.value.charCodeAt(0) }] }, second: { kind: "ranges", ranges: [{ lo: second, hi: second }] } };
|
|
7194
|
+
} else if (d.tag === "regex" && !d.flags.includes("i")) {
|
|
7195
|
+
const units = regexFirstTwo(d.source, d.flags);
|
|
7196
|
+
if (units !== void 0) two = units;
|
|
7197
|
+
}
|
|
7198
|
+
if (two === void 0 || two.first.kind !== "ranges") return void 0;
|
|
7199
|
+
return two.first.ranges.every((r) => r.hi < 55296 || r.lo > 57343 && r.hi <= 65535) ? two : void 0;
|
|
7200
|
+
}
|
|
7201
|
+
var GAP_CHARS = /* @__PURE__ */ new Set([9, 10, 12, 13, 32, 47]);
|
|
7202
|
+
function isGap(p) {
|
|
7203
|
+
if (matchesEmpty(p)) return true;
|
|
7204
|
+
const fs = p._meta.firstSet;
|
|
7205
|
+
return fs.kind === "ranges" && fs.ranges.every((r) => {
|
|
7206
|
+
for (let c = r.lo; c <= r.hi; c++) if (!GAP_CHARS.has(c)) return false;
|
|
7207
|
+
return true;
|
|
7208
|
+
});
|
|
7209
|
+
}
|
|
7106
7210
|
var Encoder = class {
|
|
7107
7211
|
code = [];
|
|
7108
7212
|
k = [];
|
|
@@ -7150,8 +7254,33 @@ var Encoder = class {
|
|
|
7150
7254
|
*/
|
|
7151
7255
|
commitFailureMemo = /* @__PURE__ */ new Map();
|
|
7152
7256
|
labels = void 0;
|
|
7257
|
+
/** The choice being encoded as written, for `OP_STRICT`'s tolerant child. */
|
|
7258
|
+
unfactoredChoice = void 0;
|
|
7153
7259
|
/** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
|
|
7154
7260
|
activeTrivia = void 0;
|
|
7261
|
+
/**
|
|
7262
|
+
* Is the trivia live at this row known? It is not in the body of an entry
|
|
7263
|
+
* that installs none of its own: that body runs under whatever trivia its
|
|
7264
|
+
* caller has (a compiled rule inside another grammar, `run({ trivia })`).
|
|
7265
|
+
* Every scope (`parser({ trivia })`, `noTrivia`, `token()`, a rule's install)
|
|
7266
|
+
* makes it known again.
|
|
7267
|
+
*/
|
|
7268
|
+
triviaKnown = true;
|
|
7269
|
+
/**
|
|
7270
|
+
* The trivia a gate's first set is derived under: the live table, `null` for a
|
|
7271
|
+
* scope known to have none, or `undefined` where it is not known.
|
|
7272
|
+
*/
|
|
7273
|
+
gateTrivia() {
|
|
7274
|
+
return this.activeTrivia ?? (this.triviaKnown ? null : void 0);
|
|
7275
|
+
}
|
|
7276
|
+
/**
|
|
7277
|
+
* Whether a gate may read a nullable pad through its non-empty matches
|
|
7278
|
+
* (`firstSetOf`'s `consuming`): only where the trivia that may follow the pad
|
|
7279
|
+
* is known. Elsewhere a gate reads first sets as 0.58.0 did.
|
|
7280
|
+
*/
|
|
7281
|
+
gateConsuming() {
|
|
7282
|
+
return this.activeTrivia !== void 0 || this.triviaKnown;
|
|
7283
|
+
}
|
|
7155
7284
|
classified = false;
|
|
7156
7285
|
scans = [];
|
|
7157
7286
|
/** Ambient `scanSkip` sets, pooled by the ARRAY's identity (stable per grammar). */
|
|
@@ -7278,10 +7407,12 @@ var Encoder = class {
|
|
|
7278
7407
|
const final = classifyFinalChoice(
|
|
7279
7408
|
node2.parsers,
|
|
7280
7409
|
this.refResolver(),
|
|
7281
|
-
node2.cleared ?
|
|
7410
|
+
node2.cleared ? null : this.gateTrivia(),
|
|
7411
|
+
false,
|
|
7412
|
+
node2.disjoint
|
|
7282
7413
|
);
|
|
7283
7414
|
const classes = final.firstSets.map((first, i) => final.nullable[i] ? -1 : this.charClass(first));
|
|
7284
|
-
const exclusive = final.exclusive && classes.every((cls) => cls >= 0);
|
|
7415
|
+
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;
|
|
7285
7416
|
words.push(LEX_NODE_CHOICE, node2.arms.length, exclusive ? 1 : 0, this.expected(node2.expected));
|
|
7286
7417
|
for (let i = 0; i < node2.arms.length; i++) {
|
|
7287
7418
|
words.push(classes[i], this.expected(node2.armExpected[i]));
|
|
@@ -7436,16 +7567,117 @@ var Encoder = class {
|
|
|
7436
7567
|
kIndex = /* @__PURE__ */ new Map();
|
|
7437
7568
|
ccIndex = /* @__PURE__ */ new Map();
|
|
7438
7569
|
fxIndex = /* @__PURE__ */ new Map();
|
|
7439
|
-
/** Memoized by combinator identity: a shared sub-combinator is ONE row. */
|
|
7440
|
-
memo = /* @__PURE__ */ new Map();
|
|
7441
7570
|
/**
|
|
7442
|
-
*
|
|
7443
|
-
*
|
|
7444
|
-
*
|
|
7445
|
-
*
|
|
7571
|
+
* Memoized by combinator identity AND the trivia scope it is encoded under
|
|
7572
|
+
* (`scopeKey`): a shared sub-combinator is ONE row per scope it runs in.
|
|
7573
|
+
*
|
|
7574
|
+
* A construct's rows depend on that scope. A first set derived through a
|
|
7575
|
+
* nullable term takes in the trivia that may follow it, a gap gate holds only
|
|
7576
|
+
* where no trivia runs, a routed gate reads what may follow its token, and a
|
|
7577
|
+
* cross-rule reference installs its rule's trivia only from a cleared region
|
|
7578
|
+
* (`scopedRef`). One memo slot per combinator froze the FIRST scope it was
|
|
7579
|
+
* reached under onto every later one: a rule body encoded as an entry with no
|
|
7580
|
+
* trivia, then run under a caller's comment trivia, gated its repeats as if no
|
|
7581
|
+
* comment could come between their terms.
|
|
7446
7582
|
*/
|
|
7447
|
-
|
|
7583
|
+
memo = /* @__PURE__ */ new Map();
|
|
7448
7584
|
pending = /* @__PURE__ */ new Map();
|
|
7585
|
+
triviaSignatures = /* @__PURE__ */ new Map();
|
|
7586
|
+
/**
|
|
7587
|
+
* What of the live trivia an encoding can depend on: none, or its first set.
|
|
7588
|
+
* Every derivation reads trivia only through `firstSetOf(trivia)` or whether it
|
|
7589
|
+
* is live, so two scopes whose trivia opens on the same characters encode the
|
|
7590
|
+
* same rows and share them. A construct that reads no scope (`readsScope`)
|
|
7591
|
+
* has one encoding.
|
|
7592
|
+
*/
|
|
7593
|
+
scopeKey(p) {
|
|
7594
|
+
const t2 = this.activeTrivia;
|
|
7595
|
+
if (!this.readsScope(p)) return "";
|
|
7596
|
+
if (t2 === void 0) return this.triviaKnown ? "" : "?";
|
|
7597
|
+
let sig = this.triviaSignatures.get(t2);
|
|
7598
|
+
if (sig === void 0) {
|
|
7599
|
+
sig = `t${JSON.stringify(firstSetOf(t2, /* @__PURE__ */ new Set(), this.refResolver()))}`;
|
|
7600
|
+
this.triviaSignatures.set(t2, sig);
|
|
7601
|
+
}
|
|
7602
|
+
return sig;
|
|
7603
|
+
}
|
|
7604
|
+
readsScopeMemo = /* @__PURE__ */ new Map();
|
|
7605
|
+
/**
|
|
7606
|
+
* Can `p`'s rows depend on the trivia scope it is encoded under? No for a
|
|
7607
|
+
* terminal, a scope of its own (`parser({ trivia })`, `noTrivia`, `token()`),
|
|
7608
|
+
* and a wrapper over a construct that reads none; yes wherever a first set, a gate or
|
|
7609
|
+
* a reference's install is derived with the scope: a sequence with a nullable
|
|
7610
|
+
* term before another (the trivia between them), a routed arm (the trivia after
|
|
7611
|
+
* its token), a reference that installs its rule's trivia from a cleared
|
|
7612
|
+
* region, and anything not modelled here — a cycle included.
|
|
7613
|
+
*/
|
|
7614
|
+
readsScope(p) {
|
|
7615
|
+
const hit = this.readsScopeMemo.get(p);
|
|
7616
|
+
if (hit !== void 0) return hit;
|
|
7617
|
+
this.readsScopeMemo.set(p, true);
|
|
7618
|
+
const d = p._def;
|
|
7619
|
+
const rr = this.refResolver();
|
|
7620
|
+
let out;
|
|
7621
|
+
switch (d.tag) {
|
|
7622
|
+
case "literal":
|
|
7623
|
+
case "regex":
|
|
7624
|
+
case "keywords":
|
|
7625
|
+
case "token":
|
|
7626
|
+
out = false;
|
|
7627
|
+
break;
|
|
7628
|
+
// `routed()` encodes its fallback under the scope that reaches it.
|
|
7629
|
+
case "routed":
|
|
7630
|
+
out = d.fallback !== void 0 && this.readsScope(d.fallback);
|
|
7631
|
+
break;
|
|
7632
|
+
case "grammar":
|
|
7633
|
+
out = d.clearTrivia !== true && d.triviaParser === void 0 && this.readsScope(d.parser);
|
|
7634
|
+
break;
|
|
7635
|
+
case "node":
|
|
7636
|
+
case "label":
|
|
7637
|
+
case "leaf":
|
|
7638
|
+
case "transform":
|
|
7639
|
+
case "attempt":
|
|
7640
|
+
case "expect":
|
|
7641
|
+
case "not":
|
|
7642
|
+
case "peek":
|
|
7643
|
+
case "optional":
|
|
7644
|
+
case "many":
|
|
7645
|
+
case "oneOrMore":
|
|
7646
|
+
case "field":
|
|
7647
|
+
out = this.readsScope(d.parser);
|
|
7648
|
+
break;
|
|
7649
|
+
case "sepBy":
|
|
7650
|
+
out = this.readsScope(d.parser) || this.readsScope(d.separator);
|
|
7651
|
+
break;
|
|
7652
|
+
case "choice":
|
|
7653
|
+
out = d.parsers.some((a) => this.readsScope(a));
|
|
7654
|
+
break;
|
|
7655
|
+
case "dispatch":
|
|
7656
|
+
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);
|
|
7657
|
+
break;
|
|
7658
|
+
case "sequence": {
|
|
7659
|
+
const ps = d.parsers;
|
|
7660
|
+
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));
|
|
7661
|
+
break;
|
|
7662
|
+
}
|
|
7663
|
+
case "lazy": {
|
|
7664
|
+
let target = winnerForRef(p, rr);
|
|
7665
|
+
if (target === void 0) {
|
|
7666
|
+
try {
|
|
7667
|
+
target = d.thunk();
|
|
7668
|
+
} catch {
|
|
7669
|
+
target = void 0;
|
|
7670
|
+
}
|
|
7671
|
+
}
|
|
7672
|
+
out = target === void 0 || triviaThroughRef(p, target, null) !== null || this.readsScope(target);
|
|
7673
|
+
break;
|
|
7674
|
+
}
|
|
7675
|
+
default:
|
|
7676
|
+
out = true;
|
|
7677
|
+
}
|
|
7678
|
+
this.readsScopeMemo.set(p, out);
|
|
7679
|
+
return out;
|
|
7680
|
+
}
|
|
7449
7681
|
settings;
|
|
7450
7682
|
/** Resolved once, HERE, at table-build time — never consulted at run time. */
|
|
7451
7683
|
track;
|
|
@@ -7473,7 +7705,7 @@ var Encoder = class {
|
|
|
7473
7705
|
let fs = { kind: "empty" };
|
|
7474
7706
|
const rr = this.refResolver();
|
|
7475
7707
|
for (let j = i + 1; j < parsers.length; j++) {
|
|
7476
|
-
fs = union(fs, firstSetOf(parsers[j], /* @__PURE__ */ new Set(), rr,
|
|
7708
|
+
fs = union(fs, firstSetOf(parsers[j], /* @__PURE__ */ new Set(), rr, void 0, false));
|
|
7477
7709
|
}
|
|
7478
7710
|
return this.charClass(fs);
|
|
7479
7711
|
}
|
|
@@ -7641,7 +7873,7 @@ var Encoder = class {
|
|
|
7641
7873
|
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;
|
|
7642
7874
|
const rr = this.refResolver();
|
|
7643
7875
|
if (matchesEmpty(p, /* @__PURE__ */ new Set(), rr)) return child;
|
|
7644
|
-
const cls = this.charClass(firstSetOf(p, /* @__PURE__ */ new Set(), rr, this.activeTrivia));
|
|
7876
|
+
const cls = this.charClass(firstSetOf(p, /* @__PURE__ */ new Set(), rr, this.activeTrivia, false));
|
|
7645
7877
|
if (cls < 0) return child;
|
|
7646
7878
|
const e = deriveExpected(p);
|
|
7647
7879
|
return this.emit(OP_GATE, cls, child, this.expected(e.length > 0 ? e : [p._tag]));
|
|
@@ -7667,9 +7899,27 @@ var Encoder = class {
|
|
|
7667
7899
|
* `{`, `Call` at `}`). The resolved set is the one a choice arm's gate uses,
|
|
7668
7900
|
* over the final merged map.
|
|
7669
7901
|
*/
|
|
7670
|
-
|
|
7902
|
+
/**
|
|
7903
|
+
* The arms whose first set under `gateTrivia()` is wider than under the
|
|
7904
|
+
* active trivia alone — a reference's installed trivia read through from a
|
|
7905
|
+
* region with none. Empty for construction-set (disjoint) choices, whose
|
|
7906
|
+
* sets do not depend on trivia.
|
|
7907
|
+
*/
|
|
7908
|
+
wideArms(arms, wide, constructionSets, wideTrivia = this.gateTrivia(), base = this.activeTrivia) {
|
|
7909
|
+
if (constructionSets || wideTrivia === base) return [];
|
|
7910
|
+
const narrow = classifyFinalChoice(arms, this.refResolver(), base, false, false).firstSets;
|
|
7911
|
+
const out = [];
|
|
7912
|
+
for (let i = 0; i < arms.length; i++) {
|
|
7913
|
+
if (this.charClass(wide[i]) !== this.charClass(narrow[i])) out.push(i);
|
|
7914
|
+
}
|
|
7915
|
+
return out;
|
|
7916
|
+
}
|
|
7917
|
+
gateFirstSet(p, guarded, narrowed) {
|
|
7671
7918
|
const cached = p._meta.firstSet;
|
|
7672
|
-
|
|
7919
|
+
if (p._def.tag !== "lazy" && cached.kind !== "any") return cached;
|
|
7920
|
+
const rr = this.refResolver();
|
|
7921
|
+
if (guarded) return firstSetOf(p, /* @__PURE__ */ new Set(), rr, void 0, false);
|
|
7922
|
+
return firstSetOf(p, /* @__PURE__ */ new Set(), rr, this.gateTrivia(), narrowed && this.gateConsuming());
|
|
7673
7923
|
}
|
|
7674
7924
|
/**
|
|
7675
7925
|
* Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
|
|
@@ -7701,6 +7951,135 @@ var Encoder = class {
|
|
|
7701
7951
|
for (const w of words) this.code.push(w);
|
|
7702
7952
|
return ip;
|
|
7703
7953
|
}
|
|
7954
|
+
/**
|
|
7955
|
+
* An optional repeat item tests the item's class before it runs it (`OP_REP`
|
|
7956
|
+
* ip+7), wherever the item's own first-set gate would also run. So a sequence
|
|
7957
|
+
* item whose first term is a gate on that same class gets its own copy of the
|
|
7958
|
+
* sequence row with the gate's child as that term: the test runs once. The
|
|
7959
|
+
* shared row is left as it is for its other references.
|
|
7960
|
+
*/
|
|
7961
|
+
withoutLeadGate(seq, cls) {
|
|
7962
|
+
const op = this.code[seq];
|
|
7963
|
+
if (op !== OP_SEQ && op !== OP_SEQV) return seq;
|
|
7964
|
+
const first = this.code[seq + 2];
|
|
7965
|
+
if (this.code[first] !== OP_GATE || this.code[first + 1] !== cls) return seq;
|
|
7966
|
+
const n = this.code[seq + 1];
|
|
7967
|
+
const width = 1 + 2 * n;
|
|
7968
|
+
const head = this.emitHead(op, width);
|
|
7969
|
+
for (let i = 1; i <= width; i++) this.code[head + i] = this.code[seq + i];
|
|
7970
|
+
this.code[head + 2] = this.code[first + 2];
|
|
7971
|
+
return head;
|
|
7972
|
+
}
|
|
7973
|
+
/**
|
|
7974
|
+
* An optional repeat item that opens with a GAP — a regex that may match
|
|
7975
|
+
* empty, or one that starts only with whitespace or a comment's `/` — and
|
|
7976
|
+
* then a term with a finite first set gets an `OP_GAPGATE` row
|
|
7977
|
+
* (`gap-gate.ts`): the repeat reads the gap once, ends where the character
|
|
7978
|
+
* after it opens neither that term nor an arm without the gap, and hands the
|
|
7979
|
+
* gap's end to the regex row. Anything the walk cannot prove keeps the item as
|
|
7980
|
+
* written.
|
|
7981
|
+
*/
|
|
7982
|
+
gapGated(item, ip) {
|
|
7983
|
+
if (this.activeTrivia === void 0 && !this.triviaKnown) return ip;
|
|
7984
|
+
const lead2 = this.gapLead(item, this.activeTrivia, 0);
|
|
7985
|
+
if (lead2 === void 0) return ip;
|
|
7986
|
+
const cls = this.charClass(lead2.follow);
|
|
7987
|
+
if (cls < 0) return ip;
|
|
7988
|
+
const other = lead2.other.kind === "empty" ? -1 : this.charClass(lead2.other);
|
|
7989
|
+
if (lead2.other.kind !== "empty" && other < 0) return ip;
|
|
7990
|
+
const p = this.node(lead2.p).ip;
|
|
7991
|
+
if (this.code[p] !== OP_RX && this.code[p] !== OP_RX_TRACK) return ip;
|
|
7992
|
+
return this.emit(OP_GAPGATE, ip, p, cls, other);
|
|
7993
|
+
}
|
|
7994
|
+
/**
|
|
7995
|
+
* The gap an item opens with: the regex `p`, the first set `follow` of what
|
|
7996
|
+
* must come straight after it, and the first set `other` of choice arms that
|
|
7997
|
+
* do not open with `p`. Only through wrappers that consume nothing before
|
|
7998
|
+
* their body, a sequence's first term, and a choice's arms; the gap must sit
|
|
7999
|
+
* in a sequence with no trivia between its terms.
|
|
8000
|
+
*/
|
|
8001
|
+
gapLead(c, trivia2, depth) {
|
|
8002
|
+
if (depth > 24) return void 0;
|
|
8003
|
+
const rr = this.refResolver();
|
|
8004
|
+
const d = c._def;
|
|
8005
|
+
switch (d.tag) {
|
|
8006
|
+
case "lazy": {
|
|
8007
|
+
let target = winnerForRef(c, rr);
|
|
8008
|
+
if (target === void 0) {
|
|
8009
|
+
try {
|
|
8010
|
+
target = d.thunk();
|
|
8011
|
+
} catch {
|
|
8012
|
+
return void 0;
|
|
8013
|
+
}
|
|
8014
|
+
}
|
|
8015
|
+
return this.gapLead(target, triviaThroughRef(c, target, trivia2), depth + 1);
|
|
8016
|
+
}
|
|
8017
|
+
case "node":
|
|
8018
|
+
case "leaf":
|
|
8019
|
+
case "label":
|
|
8020
|
+
case "attempt":
|
|
8021
|
+
return this.gapLead(d.parser, trivia2, depth + 1);
|
|
8022
|
+
case "field":
|
|
8023
|
+
return d.leadingTrivia === true ? void 0 : this.gapLead(d.parser, trivia2, depth + 1);
|
|
8024
|
+
case "grammar":
|
|
8025
|
+
return this.gapLead(d.parser, d.clearTrivia === true ? null : d.triviaParser ?? trivia2, depth + 1);
|
|
8026
|
+
case "sequence": {
|
|
8027
|
+
const [first, ...rest] = d.parsers;
|
|
8028
|
+
if (first === void 0) return void 0;
|
|
8029
|
+
if (first._def.tag !== "regex" || !isGap(first)) {
|
|
8030
|
+
return this.gapLead(first, trivia2, depth + 1);
|
|
8031
|
+
}
|
|
8032
|
+
if (trivia2 !== void 0 && trivia2 !== null || rest.length === 0) return void 0;
|
|
8033
|
+
let follow = empty();
|
|
8034
|
+
let closed = false;
|
|
8035
|
+
for (const t2 of rest) {
|
|
8036
|
+
const fs = firstSetOf(t2, /* @__PURE__ */ new Set(), rr, null);
|
|
8037
|
+
if (fs.kind === "any") return void 0;
|
|
8038
|
+
follow = union(follow, fs);
|
|
8039
|
+
if (!matchesEmpty(t2, /* @__PURE__ */ new Set(), rr)) {
|
|
8040
|
+
closed = true;
|
|
8041
|
+
break;
|
|
8042
|
+
}
|
|
8043
|
+
}
|
|
8044
|
+
return closed ? { p: first, follow, other: empty() } : void 0;
|
|
8045
|
+
}
|
|
8046
|
+
case "choice": {
|
|
8047
|
+
let p;
|
|
8048
|
+
let follow = empty();
|
|
8049
|
+
let other = empty();
|
|
8050
|
+
for (const arm of d.parsers) {
|
|
8051
|
+
const lead2 = this.gapLead(arm, trivia2, depth + 1);
|
|
8052
|
+
if (lead2 !== void 0 && (p === void 0 || lead2.p === p)) {
|
|
8053
|
+
p = lead2.p;
|
|
8054
|
+
follow = union(follow, lead2.follow);
|
|
8055
|
+
other = union(other, lead2.other);
|
|
8056
|
+
continue;
|
|
8057
|
+
}
|
|
8058
|
+
if (matchesEmpty(arm, /* @__PURE__ */ new Set(), rr)) return void 0;
|
|
8059
|
+
const fs = firstSetOf(arm, /* @__PURE__ */ new Set(), rr, trivia2 ?? null);
|
|
8060
|
+
if (fs.kind === "any") return void 0;
|
|
8061
|
+
other = union(other, fs);
|
|
8062
|
+
}
|
|
8063
|
+
return p === void 0 ? void 0 : { p, follow, other };
|
|
8064
|
+
}
|
|
8065
|
+
default:
|
|
8066
|
+
return void 0;
|
|
8067
|
+
}
|
|
8068
|
+
}
|
|
8069
|
+
/**
|
|
8070
|
+
* The class a strict list may end on — a character its separator `p` (row
|
|
8071
|
+
* `ip`) cannot start — without entering the separator, or −1.
|
|
8072
|
+
*
|
|
8073
|
+
* The test runs before every separator, to save the one that fails at the
|
|
8074
|
+
* list's end, so it is laid down only where entering the separator costs more
|
|
8075
|
+
* than the test: not on a terminal row, which is itself one character test.
|
|
8076
|
+
*/
|
|
8077
|
+
sepGate(p, ip) {
|
|
8078
|
+
const op = this.code[ip];
|
|
8079
|
+
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;
|
|
8080
|
+
if (matchesEmpty(p, /* @__PURE__ */ new Set(), this.refResolver())) return -1;
|
|
8081
|
+
return this.charClass(firstSetOf(p, /* @__PURE__ */ new Set(), this.refResolver(), this.gateTrivia(), this.gateConsuming()));
|
|
8082
|
+
}
|
|
7704
8083
|
/** Reserve `n` operand slots to patch once children are laid out. */
|
|
7705
8084
|
emitHead(op, n) {
|
|
7706
8085
|
const ip = this.code.length;
|
|
@@ -7744,8 +8123,10 @@ var Encoder = class {
|
|
|
7744
8123
|
}
|
|
7745
8124
|
encodeRule(name, p) {
|
|
7746
8125
|
this.activeTrivia = p._meta.grammarTrivia;
|
|
8126
|
+
this.triviaKnown = p._meta.grammarTrivia !== void 0;
|
|
7747
8127
|
const body = this.node(p).ip;
|
|
7748
8128
|
this.activeTrivia = void 0;
|
|
8129
|
+
this.triviaKnown = true;
|
|
7749
8130
|
const gss = p._meta.grammarScanSkip;
|
|
7750
8131
|
this.scanSkipOf.push(gss === void 0 ? -1 : this.scanSkipSlot(gss));
|
|
7751
8132
|
const amb = p._meta.grammarTrivia;
|
|
@@ -7791,11 +8172,15 @@ var Encoder = class {
|
|
|
7791
8172
|
* silently produced the ONE keyword `bc`.
|
|
7792
8173
|
*/
|
|
7793
8174
|
scopedRef(p, target) {
|
|
8175
|
+
const runsUnder = triviaThroughRef(p, target, this.activeTrivia);
|
|
8176
|
+
if (this.activeTrivia !== void 0 || runsUnder === void 0 || runsUnder === null) return this.node(target).ip;
|
|
8177
|
+
const savedKnown = this.triviaKnown;
|
|
8178
|
+
this.activeTrivia = runsUnder;
|
|
8179
|
+
this.triviaKnown = true;
|
|
7794
8180
|
const ip = this.node(target).ip;
|
|
7795
|
-
|
|
7796
|
-
|
|
7797
|
-
|
|
7798
|
-
return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), ip);
|
|
8181
|
+
this.activeTrivia = void 0;
|
|
8182
|
+
this.triviaKnown = savedKnown;
|
|
8183
|
+
return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(runsUnder), ip);
|
|
7799
8184
|
}
|
|
7800
8185
|
/**
|
|
7801
8186
|
* The `OP_RGATE` operands of a choice arm that opens with `routed()`, or
|
|
@@ -7836,38 +8221,43 @@ var Encoder = class {
|
|
|
7836
8221
|
if (matchesEmpty(next, /* @__PURE__ */ new Set(), rr) || mayCommitFailure(next, rr, this.commitFailureMemo)) return void 0;
|
|
7837
8222
|
const nextDef = next._def;
|
|
7838
8223
|
if (nextDef.tag !== "literal" && nextDef.tag !== "regex" && nextDef.tag !== "keywords" && nextDef.tag !== "label") return void 0;
|
|
7839
|
-
|
|
8224
|
+
if (boundary === void 0 && !this.triviaKnown) return void 0;
|
|
8225
|
+
const first = firstSetOf(next, /* @__PURE__ */ new Set(), rr, boundary ?? null);
|
|
7840
8226
|
const cls = this.charClass(boundary === void 0 ? first : union(first, firstSetOf(boundary, /* @__PURE__ */ new Set(), rr)));
|
|
7841
8227
|
if (cls < 0) return void 0;
|
|
7842
|
-
const
|
|
7843
|
-
|
|
8228
|
+
const fx = this.expected(nextDef.tag === "label" ? deriveExpected(next) : directTerminalFailureExpected(nextDef));
|
|
8229
|
+
const two = firstTwo(next);
|
|
8230
|
+
if (two === void 0) return { cls, fx };
|
|
8231
|
+
if (boundary !== void 0 && intersects(two.first, firstSetOf(boundary, /* @__PURE__ */ new Set(), rr))) return { cls, fx };
|
|
8232
|
+
const a = this.charClass(two.first);
|
|
8233
|
+
const b = this.charClass(two.second);
|
|
8234
|
+
return a < 0 || b < 0 ? { cls, fx } : { cls, fx, two: [a, b] };
|
|
7844
8235
|
}
|
|
7845
8236
|
node(p) {
|
|
7846
|
-
const
|
|
7847
|
-
|
|
7848
|
-
const
|
|
7849
|
-
const hit = lazyRef ? refMemo.get(p)?.get(scopeKey) : this.memo.get(p);
|
|
8237
|
+
const key = this.scopeKey(p);
|
|
8238
|
+
let byScope = this.memo.get(p);
|
|
8239
|
+
const hit = byScope?.get(key);
|
|
7850
8240
|
if (hit !== void 0) return { ip: hit };
|
|
7851
|
-
|
|
8241
|
+
let inFlightByScope = this.pending.get(p);
|
|
8242
|
+
const inFlight = inFlightByScope?.get(key);
|
|
7852
8243
|
if (inFlight !== void 0) {
|
|
7853
8244
|
const ip2 = this.emitHead(OP_RULE, 1);
|
|
7854
8245
|
inFlight.push(ip2 + 1);
|
|
7855
8246
|
return { ip: ip2 };
|
|
7856
8247
|
}
|
|
7857
8248
|
const patches = [];
|
|
7858
|
-
|
|
8249
|
+
if (inFlightByScope === void 0) {
|
|
8250
|
+
inFlightByScope = /* @__PURE__ */ new Map();
|
|
8251
|
+
this.pending.set(p, inFlightByScope);
|
|
8252
|
+
}
|
|
8253
|
+
inFlightByScope.set(key, patches);
|
|
7859
8254
|
const ip = this.covWrap(this.encodeDef(p), this.plan?.rules.get(p), 0);
|
|
7860
|
-
|
|
7861
|
-
if (
|
|
7862
|
-
|
|
7863
|
-
|
|
7864
|
-
byScope = /* @__PURE__ */ new Map();
|
|
7865
|
-
refMemo.set(p, byScope);
|
|
7866
|
-
}
|
|
7867
|
-
byScope.set(scopeKey, ip);
|
|
7868
|
-
} else {
|
|
7869
|
-
this.memo.set(p, ip);
|
|
8255
|
+
inFlightByScope.delete(key);
|
|
8256
|
+
if (byScope === void 0) {
|
|
8257
|
+
byScope = /* @__PURE__ */ new Map();
|
|
8258
|
+
this.memo.set(p, byScope);
|
|
7870
8259
|
}
|
|
8260
|
+
byScope.set(key, ip);
|
|
7871
8261
|
for (const slot of patches) {
|
|
7872
8262
|
if (slot - 1 === ip) {
|
|
7873
8263
|
const rule2 = p._ruleName;
|
|
@@ -7965,8 +8355,19 @@ var Encoder = class {
|
|
|
7965
8355
|
}
|
|
7966
8356
|
case "choice": {
|
|
7967
8357
|
if (this.plan === void 0) {
|
|
7968
|
-
const
|
|
7969
|
-
if (
|
|
8358
|
+
const shared = factorSharedEnds(d);
|
|
8359
|
+
if (shared !== void 0) return this.node(shared).ip;
|
|
8360
|
+
if (this.unfactoredChoice !== p) {
|
|
8361
|
+
const prefix = factorPrefixArms(d);
|
|
8362
|
+
if (prefix !== void 0) {
|
|
8363
|
+
const strict = this.node(prefix).ip;
|
|
8364
|
+
const saved = this.unfactoredChoice;
|
|
8365
|
+
this.unfactoredChoice = p;
|
|
8366
|
+
const tolerant = this.encodeDef(p);
|
|
8367
|
+
this.unfactoredChoice = saved;
|
|
8368
|
+
return this.emit(OP_STRICT, strict, tolerant);
|
|
8369
|
+
}
|
|
8370
|
+
}
|
|
7970
8371
|
}
|
|
7971
8372
|
if (d.strategy.tag === "greedyClassify") {
|
|
7972
8373
|
const superIndex = d.strategy.superIndex;
|
|
@@ -7995,18 +8396,20 @@ var Encoder = class {
|
|
|
7995
8396
|
const plain2 = (checks === null || checks === void 0 || checks.length === 0) && (gate === null || gate === void 0);
|
|
7996
8397
|
const routedGate = plain2 ? this.routedArmGate(c) : void 0;
|
|
7997
8398
|
const body = this.node(c).ip;
|
|
7998
|
-
const inner = routedGate === void 0 ? body : this.emit(OP_RGATE, routedGate.cls, body, routedGate.fx);
|
|
8399
|
+
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]);
|
|
7999
8400
|
const ip = checks === null || checks === void 0 || checks.length === 0 ? inner : this.reject(inner, checks);
|
|
8000
8401
|
const gated = gate === null || gate === void 0 ? ip : this.emit(OP_ARMGATE, this.fn(gate, d.gateSrcs?.[src] ?? null), ip, this.expected(deriveExpected(c)));
|
|
8001
8402
|
return this.covWrap(gated, armCovIds?.[src], 1);
|
|
8002
8403
|
});
|
|
8003
8404
|
const rr = this.refResolver();
|
|
8004
|
-
const
|
|
8405
|
+
const constructionSets = d.disjoint && !factoredChoices.has(p);
|
|
8406
|
+
const finalChoice = classifyFinalChoice(arms, rr, this.gateTrivia(), false, constructionSets);
|
|
8407
|
+
const wideArms = this.wideArms(arms, finalChoice.firstSets, constructionSets);
|
|
8005
8408
|
const transactionalFirst = arms.map((arm, i) => {
|
|
8006
8409
|
if (!finalChoice.nullable[i]) return void 0;
|
|
8007
8410
|
const def = arm._def;
|
|
8008
8411
|
if (def.tag !== "attempt" || matchesEmpty(def.parser, /* @__PURE__ */ new Set(), rr)) return void 0;
|
|
8009
|
-
return firstSetOf(def.parser, /* @__PURE__ */ new Set(), rr, this.activeTrivia);
|
|
8412
|
+
return firstSetOf(def.parser, /* @__PURE__ */ new Set(), rr, this.activeTrivia, false);
|
|
8010
8413
|
});
|
|
8011
8414
|
const gateFirst = finalChoice.firstSets.map((first, i) => transactionalFirst[i] ?? first);
|
|
8012
8415
|
const classes = gateFirst.map((first, i) => finalChoice.nullable[i] && transactionalFirst[i] === void 0 ? -1 : this.charClass(first));
|
|
@@ -8024,6 +8427,9 @@ var Encoder = class {
|
|
|
8024
8427
|
if (transactionalFirst[i] !== void 0) classes[i] = -1;
|
|
8025
8428
|
}
|
|
8026
8429
|
}
|
|
8430
|
+
if (wideArms.length > 0 && dispatchIsExclusive(classes, this.cc)) {
|
|
8431
|
+
for (const i of wideArms) classes[i] = -1;
|
|
8432
|
+
}
|
|
8027
8433
|
if (d.gates.some((g) => g !== null && g !== void 0) && !dispatchIsExclusive(classes, this.cc)) {
|
|
8028
8434
|
for (let k = 0; k < classes.length; k++) {
|
|
8029
8435
|
const gate = d.gates[order[k]];
|
|
@@ -8057,27 +8463,34 @@ var Encoder = class {
|
|
|
8057
8463
|
}
|
|
8058
8464
|
case "many":
|
|
8059
8465
|
case "oneOrMore": {
|
|
8060
|
-
const child = this.node(d.parser).ip;
|
|
8061
8466
|
const rr = this.refResolver();
|
|
8062
|
-
const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.charClass(
|
|
8467
|
+
const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.charClass(this.gateFirstSet(d.parser, d.guarded === true, true));
|
|
8063
8468
|
const op = d.valueUnused ? OP_REPV : OP_REP;
|
|
8064
8469
|
const min = d.tag === "many" ? 0 : d.min;
|
|
8470
|
+
const item = min === 0 && itemClass >= 0 ? this.withoutLeadGate(this.node(d.parser).ip, itemClass) : this.node(d.parser).ip;
|
|
8471
|
+
const child = min === 0 && itemClass >= 0 ? this.gapGated(d.parser, item) : item;
|
|
8065
8472
|
return this.emit(op, child, min, d.max ?? -1, -1, 0, this.expected(deriveExpected(d.parser)), itemClass);
|
|
8066
8473
|
}
|
|
8067
8474
|
case "sepBy": {
|
|
8068
8475
|
const child = this.node(d.parser).ip;
|
|
8069
8476
|
const sep = this.node(d.separator).ip;
|
|
8070
|
-
const
|
|
8071
|
-
|
|
8072
|
-
|
|
8477
|
+
const gate = this.sepGate(d.separator, sep);
|
|
8478
|
+
const itemSet = deriveExpected(d.parser);
|
|
8479
|
+
const itemFx = this.expected(itemSet.length > 0 ? itemSet : [d.parser._tag]);
|
|
8480
|
+
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);
|
|
8481
|
+
const ops = [
|
|
8073
8482
|
child,
|
|
8074
8483
|
d.min,
|
|
8075
8484
|
d.max ?? -1,
|
|
8076
8485
|
sep,
|
|
8077
8486
|
flags,
|
|
8078
|
-
|
|
8079
|
-
|
|
8080
|
-
|
|
8487
|
+
itemFx,
|
|
8488
|
+
// As 0.58.0: the interpreter resyncs on the separator itself
|
|
8489
|
+
// (`orSentinel`), which runs under the live trivia.
|
|
8490
|
+
this.charClass(firstSetOf(d.separator, /* @__PURE__ */ new Set(), this.refResolver(), this.activeTrivia, false))
|
|
8491
|
+
];
|
|
8492
|
+
if (gate >= 0) ops.push(gate);
|
|
8493
|
+
return this.emit(OP_REP, ...ops);
|
|
8081
8494
|
}
|
|
8082
8495
|
case "optional": {
|
|
8083
8496
|
const head = this.emit(OP_OPT, this.lookaheadGate(d.parser, this.node(d.parser).ip));
|
|
@@ -8086,7 +8499,7 @@ var Encoder = class {
|
|
|
8086
8499
|
}
|
|
8087
8500
|
case "transform": {
|
|
8088
8501
|
const inner = d.parser._def;
|
|
8089
|
-
if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
|
|
8502
|
+
if (inner.tag === "sequence" && !this.memo.get(d.parser)?.has(this.scopeKey(d.parser)) && !this.pending.get(d.parser)?.has(this.scopeKey(d.parser))) {
|
|
8090
8503
|
const kids = inner.parsers.map((c) => this.node(c).ip);
|
|
8091
8504
|
const head = this.emitHead(OP_SEQX, 2 + 2 * kids.length);
|
|
8092
8505
|
const projection = directArrayProjection(d.fn, d.fnSrc, kids.length);
|
|
@@ -8127,7 +8540,7 @@ var Encoder = class {
|
|
|
8127
8540
|
d.tags === void 0 ? -1 : this.constant(d.tags)
|
|
8128
8541
|
);
|
|
8129
8542
|
if (matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return body;
|
|
8130
|
-
const fs = this.gateFirstSet(d.parser);
|
|
8543
|
+
const fs = this.gateFirstSet(d.parser, d.guarded === true, false);
|
|
8131
8544
|
if (fs.kind === "any") return body;
|
|
8132
8545
|
const cls = this.charClass(fs);
|
|
8133
8546
|
if (cls < 0) return body;
|
|
@@ -8135,7 +8548,14 @@ var Encoder = class {
|
|
|
8135
8548
|
return this.emit(OP_GATE, cls, body, this.expected(e.length > 0 ? e : [d.parser._tag]));
|
|
8136
8549
|
}
|
|
8137
8550
|
case "token": {
|
|
8138
|
-
|
|
8551
|
+
const saved = this.activeTrivia;
|
|
8552
|
+
const savedKnown = this.triviaKnown;
|
|
8553
|
+
this.activeTrivia = void 0;
|
|
8554
|
+
this.triviaKnown = true;
|
|
8555
|
+
const body = this.node(d.parser).ip;
|
|
8556
|
+
this.activeTrivia = saved;
|
|
8557
|
+
this.triviaKnown = savedKnown;
|
|
8558
|
+
return this.emit(OP_TOKEN, body);
|
|
8139
8559
|
}
|
|
8140
8560
|
case "routed":
|
|
8141
8561
|
return this.emit(OP_ROUTED, d.fallback === void 0 ? -1 : this.node(d.fallback).ip);
|
|
@@ -8191,7 +8611,7 @@ var Encoder = class {
|
|
|
8191
8611
|
this.code[head + 2] = dspIdx;
|
|
8192
8612
|
this.code[head + 3] = other;
|
|
8193
8613
|
const otherRouted = d.otherwise === void 0 ? false : branchUsesRouted({ parser: d.otherwise, usesRouted: d.otherwiseUsesRouted === true });
|
|
8194
|
-
this.code[head + 4] = otherRouted ? 1 : 0;
|
|
8614
|
+
this.code[head + 4] = (otherRouted ? 1 : 0) | (d.otherwiseCommit === false ? 2 : 0);
|
|
8195
8615
|
this.code[head + 5] = arms.length;
|
|
8196
8616
|
for (let i = 0; i < arms.length; i++) this.code[head + 6 + i] = arms[i];
|
|
8197
8617
|
return head;
|
|
@@ -8246,7 +8666,7 @@ var Encoder = class {
|
|
|
8246
8666
|
case "attempt": {
|
|
8247
8667
|
const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip, d.contain === true ? 1 : 0);
|
|
8248
8668
|
if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
|
|
8249
|
-
const fs = this.gateFirstSet(d.parser);
|
|
8669
|
+
const fs = this.gateFirstSet(d.parser, d.guarded === true, false);
|
|
8250
8670
|
if (fs.kind === "any" || matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return inner;
|
|
8251
8671
|
const cls = this.charClass(fs);
|
|
8252
8672
|
if (cls < 0) return inner;
|
|
@@ -8272,10 +8692,17 @@ var Encoder = class {
|
|
|
8272
8692
|
const op = cap ? OP_SCOPE_CAP : OP_SCOPE;
|
|
8273
8693
|
const flags = (d.rootCapture === "opaque" ? 1 : 0) | (d.triviaParser !== void 0 && d.triviaParser._meta.rootTriviaClassified !== true && d.rootCapture !== "opaque" ? 2 : 0);
|
|
8274
8694
|
const savedTrivia = this.activeTrivia;
|
|
8275
|
-
|
|
8276
|
-
|
|
8695
|
+
const savedKnown = this.triviaKnown;
|
|
8696
|
+
if (d.clearTrivia === true) {
|
|
8697
|
+
this.activeTrivia = void 0;
|
|
8698
|
+
this.triviaKnown = true;
|
|
8699
|
+
} else if (d.triviaParser !== void 0) {
|
|
8700
|
+
this.activeTrivia = d.triviaParser;
|
|
8701
|
+
this.triviaKnown = true;
|
|
8702
|
+
}
|
|
8277
8703
|
const bodyIp = this.node(d.parser).ip;
|
|
8278
8704
|
this.activeTrivia = savedTrivia;
|
|
8705
|
+
this.triviaKnown = savedKnown;
|
|
8279
8706
|
if (d.clearTrivia === true) return this.emit(op, -1, bodyIp, flags);
|
|
8280
8707
|
if (d.triviaParser === void 0) {
|
|
8281
8708
|
return cap || flags !== 0 ? this.emit(op, -1, bodyIp, flags) : bodyIp;
|
|
@@ -8316,6 +8743,7 @@ var Encoder = class {
|
|
|
8316
8743
|
switch (this.code[ip]) {
|
|
8317
8744
|
case OP_GATE:
|
|
8318
8745
|
case OP_RGATE:
|
|
8746
|
+
case OP_RGATE2:
|
|
8319
8747
|
return [ip + 2];
|
|
8320
8748
|
case OP_RULE:
|
|
8321
8749
|
case OP_OPT:
|
|
@@ -8325,6 +8753,7 @@ var Encoder = class {
|
|
|
8325
8753
|
case OP_ATTEMPT:
|
|
8326
8754
|
case OP_LABEL:
|
|
8327
8755
|
case OP_COV:
|
|
8756
|
+
case OP_GAPGATE:
|
|
8328
8757
|
return [ip + 1];
|
|
8329
8758
|
case OP_SCOPE:
|
|
8330
8759
|
case OP_SCOPE_CAP:
|
|
@@ -8361,6 +8790,8 @@ var Encoder = class {
|
|
|
8361
8790
|
case OP_REP:
|
|
8362
8791
|
case OP_REPV:
|
|
8363
8792
|
return this.code[ip + 4] >= 0 ? [ip + 1, ip + 4] : [ip + 1];
|
|
8793
|
+
case OP_STRICT:
|
|
8794
|
+
return [ip + 1, ip + 2];
|
|
8364
8795
|
default:
|
|
8365
8796
|
return [];
|
|
8366
8797
|
}
|
|
@@ -9518,6 +9949,7 @@ function childSlots(code, ip, out) {
|
|
|
9518
9949
|
case OP_LABEL:
|
|
9519
9950
|
case OP_COV:
|
|
9520
9951
|
case OP_REJECT:
|
|
9952
|
+
case OP_GAPGATE:
|
|
9521
9953
|
out.push(code[ip + 1]);
|
|
9522
9954
|
return true;
|
|
9523
9955
|
// Single child at `ip + 2`.
|
|
@@ -9534,8 +9966,13 @@ function childSlots(code, ip, out) {
|
|
|
9534
9966
|
case OP_SOURCE_LEAF:
|
|
9535
9967
|
case OP_ARMGATE:
|
|
9536
9968
|
case OP_RGATE:
|
|
9969
|
+
case OP_RGATE2:
|
|
9537
9970
|
out.push(code[ip + 2]);
|
|
9538
9971
|
return true;
|
|
9972
|
+
// `STRICT strict tolerant` — both encodings are reachable; an assembly keeps one.
|
|
9973
|
+
case OP_STRICT:
|
|
9974
|
+
out.push(code[ip + 1], code[ip + 2]);
|
|
9975
|
+
return true;
|
|
9539
9976
|
// `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
|
|
9540
9977
|
// data the enclosing `dispatch()` already consumed, so the only edge is the
|
|
9541
9978
|
// fallback.
|
|
@@ -9983,7 +10420,8 @@ var WRAPPERS = /* @__PURE__ */ new Set([
|
|
|
9983
10420
|
OP_WITHCTX,
|
|
9984
10421
|
OP_RULE,
|
|
9985
10422
|
OP_ATTEMPT,
|
|
9986
|
-
OP_COV
|
|
10423
|
+
OP_COV,
|
|
10424
|
+
OP_GAPGATE
|
|
9987
10425
|
]);
|
|
9988
10426
|
function rowNullable(code, k, ip, memo) {
|
|
9989
10427
|
const hit = memo.get(ip);
|
|
@@ -10020,7 +10458,31 @@ function holdsGap(code, k, base, n, i, memo) {
|
|
|
10020
10458
|
return !rowNullable(code, k, next, memo);
|
|
10021
10459
|
}
|
|
10022
10460
|
|
|
10461
|
+
// src/table/gap-gate.ts
|
|
10462
|
+
function newGapSlot() {
|
|
10463
|
+
return { row: -1, at: -1, end: -1, input: void 0 };
|
|
10464
|
+
}
|
|
10465
|
+
function gapRows(code, roots) {
|
|
10466
|
+
const rows = /* @__PURE__ */ new Set();
|
|
10467
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10468
|
+
const stack = [...roots];
|
|
10469
|
+
const kids = [];
|
|
10470
|
+
while (stack.length > 0) {
|
|
10471
|
+
const ip = stack.pop();
|
|
10472
|
+
if (seen.has(ip)) continue;
|
|
10473
|
+
seen.add(ip);
|
|
10474
|
+
if (code[ip] === OP_GAPGATE) rows.add(code[ip + 2]);
|
|
10475
|
+
kids.length = 0;
|
|
10476
|
+
childSlots(code, ip, kids);
|
|
10477
|
+
for (const c of kids) stack.push(c);
|
|
10478
|
+
}
|
|
10479
|
+
return rows;
|
|
10480
|
+
}
|
|
10481
|
+
|
|
10023
10482
|
// src/table/emit-assembly.ts
|
|
10483
|
+
function gapRegexLowers(re) {
|
|
10484
|
+
return re instanceof RegExp && scanShapeFromRegex(re.source, re.flags) !== null;
|
|
10485
|
+
}
|
|
10024
10486
|
var Unemittable = class extends Error {
|
|
10025
10487
|
construct;
|
|
10026
10488
|
constructor(construct) {
|
|
@@ -10039,7 +10501,6 @@ var EMITTED_PARAMS = [
|
|
|
10039
10501
|
"CLS",
|
|
10040
10502
|
"AFX",
|
|
10041
10503
|
"TRIVIA",
|
|
10042
|
-
"TRIVIALABELS",
|
|
10043
10504
|
"TRIVIASCAN",
|
|
10044
10505
|
"SCANS",
|
|
10045
10506
|
"DISP",
|
|
@@ -10063,7 +10524,6 @@ var EMITTED_PARAMS = [
|
|
|
10063
10524
|
"cstLeavesLen",
|
|
10064
10525
|
"skipTriviaScanned",
|
|
10065
10526
|
"needsDeferredTriviaCommit",
|
|
10066
|
-
"scanTrivia",
|
|
10067
10527
|
"advanceTrivia",
|
|
10068
10528
|
"refuseUnclassifiedRootScope",
|
|
10069
10529
|
"spanLines",
|
|
@@ -10083,34 +10543,31 @@ var EMITTED_PARAMS = [
|
|
|
10083
10543
|
"orSentinel",
|
|
10084
10544
|
"captureError",
|
|
10085
10545
|
// Pure scalar terminal recognizers, indexed by the terminal's existing const
|
|
10086
|
-
// operand
|
|
10546
|
+
// operand; selected lexical bodies; the adjacency test.
|
|
10087
10547
|
"RECOG",
|
|
10088
|
-
// Appended so precompiled factories produced by earlier runtimes keep every
|
|
10089
|
-
// positional helper binding. Older factories ignore this trailing argument.
|
|
10090
|
-
"commitTriviaScan",
|
|
10091
|
-
"scanTriviaCompact",
|
|
10092
10548
|
"LEX",
|
|
10093
|
-
// Appended for old precompiled-factory ABI: old factories ignore it.
|
|
10094
10549
|
"adjacencyHolds",
|
|
10095
|
-
//
|
|
10550
|
+
// Selected composite lexical programs.
|
|
10096
10551
|
"LEXPROG",
|
|
10097
|
-
//
|
|
10098
|
-
// old factories ignore them.
|
|
10552
|
+
// Trivia-attributing fields (`field(…, { leadingTrivia })`).
|
|
10099
10553
|
"LEAD",
|
|
10100
10554
|
"triviaFieldCapture",
|
|
10101
|
-
//
|
|
10102
|
-
// factories ignore it.
|
|
10555
|
+
// The deferred-commit trivia skip (`trivia-gap.ts`).
|
|
10103
10556
|
"skipDeferredTrivia",
|
|
10104
|
-
//
|
|
10105
|
-
// ignore it.
|
|
10557
|
+
// The pass-through collapse (`run-support.ts`).
|
|
10106
10558
|
"collapseEmpty",
|
|
10107
|
-
//
|
|
10108
|
-
//
|
|
10559
|
+
// Constructor-built tree objects (`cst/plain.d.ts`): a `new` call has no
|
|
10560
|
+
// allocation site, so V8 cannot pretenure them.
|
|
10109
10561
|
"_SP",
|
|
10110
10562
|
"_LF",
|
|
10111
10563
|
"_ND",
|
|
10112
10564
|
"_FC",
|
|
10113
|
-
"_BUF"
|
|
10565
|
+
"_BUF",
|
|
10566
|
+
// The gap gate's slot (`gap-gate.ts`).
|
|
10567
|
+
"GAP"
|
|
10568
|
+
// Artifacts are version-locked (docs/design/artifact-format.md): a factory is
|
|
10569
|
+
// only ever called by the runtime that emitted it, so a name nothing emitted
|
|
10570
|
+
// reads is removed rather than kept for an older factory's positions.
|
|
10114
10571
|
];
|
|
10115
10572
|
var RUNTIME_PRELUDE = `
|
|
10116
10573
|
let _pfScan=null
|
|
@@ -10361,7 +10818,7 @@ function rebuildPools(cc, fx, disp, plan) {
|
|
|
10361
10818
|
})
|
|
10362
10819
|
};
|
|
10363
10820
|
}
|
|
10364
|
-
function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false, select, scanSinkNeutral = false) {
|
|
10821
|
+
function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false, select, scanSinkNeutral = false, gapNeutral = false) {
|
|
10365
10822
|
const { code, k, fx, disp, dsp, triviaLabelled } = t2;
|
|
10366
10823
|
const swapLegal = !cfg.trackLines;
|
|
10367
10824
|
const hostCst = cfg.hostCst;
|
|
@@ -10369,6 +10826,7 @@ function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false, s
|
|
|
10369
10826
|
if (cfg.coverage) throw new Unemittable("a coverage assembly");
|
|
10370
10827
|
const roots = [...Object.values(prog.rules), ...extraIps];
|
|
10371
10828
|
const reachable = [...reachableSites(code, roots)];
|
|
10829
|
+
const GAP_ROWS = gapNeutral ? /* @__PURE__ */ new Set() : new Set([...gapRows(code, roots)].filter((row) => !gapRegexLowers(k[code[row + 1]])));
|
|
10372
10830
|
const labels = computeSiteLabels(code, roots, hostCst);
|
|
10373
10831
|
const scalarSpecs = /* @__PURE__ */ new Set();
|
|
10374
10832
|
const nullable2 = /* @__PURE__ */ new Map();
|
|
@@ -10706,13 +11164,15 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
10706
11164
|
function aliasOf(ip) {
|
|
10707
11165
|
const op = code[ip];
|
|
10708
11166
|
if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
|
|
10709
|
-
if (op === OP_RULE) return code[ip + 1];
|
|
11167
|
+
if (op === OP_RULE || op === OP_GAPGATE) return code[ip + 1];
|
|
11168
|
+
if (op === OP_STRICT) return code[cfg.tolerant || cfg.probe ? ip + 2 : ip + 1];
|
|
10710
11169
|
if (scopeIsIdentity(code, ip, labels.at(ip))) return code[ip + 2];
|
|
10711
11170
|
return void 0;
|
|
10712
11171
|
}
|
|
10713
11172
|
function lower(ip, fname) {
|
|
10714
11173
|
const op = code[ip];
|
|
10715
11174
|
const head = `function ${fname}(input,pos,ctx){`;
|
|
11175
|
+
const outerHead = head;
|
|
10716
11176
|
const L = labels.at(ip);
|
|
10717
11177
|
const sinks = sinksAt(ip);
|
|
10718
11178
|
const pushLeaf = L.buf && !cfg.trackLines ? L.raw === RAW_OMIT ? "_pushLeafNoRawBuf" : L.raw === RAW_CAPTURE ? "_pushLeafBuf" : "_pushLeaf" : "_pushLeaf";
|
|
@@ -10788,9 +11248,27 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
10788
11248
|
case OP_RX_TRACK: {
|
|
10789
11249
|
const xf = fxRef(code[ip + 2]);
|
|
10790
11250
|
const track = op === OP_RX_TRACK;
|
|
11251
|
+
if (GAP_ROWS.has(ip)) {
|
|
11252
|
+
const re2 = hoist("gx", `K[${code[ip + 1]}]`);
|
|
11253
|
+
return `${outerHead}
|
|
11254
|
+
let e
|
|
11255
|
+
if(GAP.row===${ip}&&GAP.at===pos&&GAP.input===input)e=GAP.end
|
|
11256
|
+
else{${re2}.lastIndex=pos;e=${re2}.test(input)?${re2}.lastIndex:-1}
|
|
11257
|
+
if(e>=0){
|
|
11258
|
+
const v=input.slice(pos,e)
|
|
11259
|
+
${captureLeaf("v")}
|
|
11260
|
+
${track ? "_trackLines(ctx,input,e)\n" : ""}EC.e=e
|
|
11261
|
+
return v
|
|
11262
|
+
}
|
|
11263
|
+
ctx._fe=pos;ctx._fx=${xf}
|
|
11264
|
+
${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
11265
|
+
` : ""}return FAIL
|
|
11266
|
+
}`;
|
|
11267
|
+
}
|
|
11268
|
+
const head2 = outerHead;
|
|
10791
11269
|
if (!track && scalarSpecs.has(code[ip + 1])) {
|
|
10792
11270
|
const recognize = recognizerRef(code[ip + 1]);
|
|
10793
|
-
return `${
|
|
11271
|
+
return `${head2}
|
|
10794
11272
|
const e=${recognize}(input,pos)
|
|
10795
11273
|
if(e>=0){
|
|
10796
11274
|
const v=input.slice(pos,e)
|
|
@@ -10803,11 +11281,11 @@ return FAIL
|
|
|
10803
11281
|
}`;
|
|
10804
11282
|
}
|
|
10805
11283
|
const scanned = emitScan(code[ip + 1], xf, track, captureLeaf);
|
|
10806
|
-
if (scanned !== void 0) return `${
|
|
11284
|
+
if (scanned !== void 0) return `${head2}${scanned}}`;
|
|
10807
11285
|
const rxk = k[code[ip + 1]];
|
|
10808
11286
|
if (!(rxk instanceof RegExp) || !rxk.sticky) throw new Unemittable("a non-sticky regex row");
|
|
10809
11287
|
const re = kRef(code[ip + 1]);
|
|
10810
|
-
return `${
|
|
11288
|
+
return `${head2}
|
|
10811
11289
|
${re}.lastIndex=pos
|
|
10812
11290
|
if(${re}.test(input)){
|
|
10813
11291
|
const e=${re}.lastIndex
|
|
@@ -10845,6 +11323,28 @@ return ${child}(input,pos,ctx)
|
|
|
10845
11323
|
const it=ctx._routed
|
|
10846
11324
|
if(it!==undefined&&it.span.start===pos&&!classHas(${cls},lead(input,it.span.end))){ctx._fe=it.span.end;ctx._fx=${xf};return FAIL}
|
|
10847
11325
|
return ${child}(input,pos,ctx)
|
|
11326
|
+
}`;
|
|
11327
|
+
}
|
|
11328
|
+
case OP_RGATE2: {
|
|
11329
|
+
const child = link(code[ip + 2]);
|
|
11330
|
+
if (cfg.tolerant || cfg.probe) return `${head}
|
|
11331
|
+
return ${child}(input,pos,ctx)
|
|
11332
|
+
}`;
|
|
11333
|
+
const idxs = [code[ip + 1], code[ip + 4], code[ip + 5]];
|
|
11334
|
+
const ascii = idxs.every((i) => isAsciiOnlyClass(t2.cc[i]));
|
|
11335
|
+
const ref2 = (idx, tag) => {
|
|
11336
|
+
const ci = classes.push([t2.cc[idx]]) - 1;
|
|
11337
|
+
classPlan.push([idx]);
|
|
11338
|
+
return hoist(tag, `CLS[${ci}][0]`);
|
|
11339
|
+
};
|
|
11340
|
+
const [cls, first, second] = [ref2(idxs[0], "cl"), ref2(idxs[1], "c1"), ref2(idxs[2], "c2")];
|
|
11341
|
+
const has = (c, at) => ascii ? `${c}.ascii[${at}]===1` : `classHas(${c},${at})`;
|
|
11342
|
+
const xf = fxRef(code[ip + 3]);
|
|
11343
|
+
return `${head}
|
|
11344
|
+
const it=ctx._routed
|
|
11345
|
+
if(it!==undefined&&it.span.start===pos){const e=it.span.end;const c=${ascii ? "input.charCodeAt(e)" : "lead(input,e)"}
|
|
11346
|
+
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}}
|
|
11347
|
+
return ${child}(input,pos,ctx)
|
|
10848
11348
|
}`;
|
|
10849
11349
|
}
|
|
10850
11350
|
case OP_ARMGATE: {
|
|
@@ -11254,7 +11754,27 @@ if(ctx._fc===true)return FAIL
|
|
|
11254
11754
|
const af=ctx._fx
|
|
11255
11755
|
if(af!==undefined&&af.length>0){ctx._fe=pos;return FAIL}
|
|
11256
11756
|
}
|
|
11257
|
-
|
|
11757
|
+
${cfg.probe ? `if(arm<0){${arms.map((a) => `${a}(input,pos,ctx)`).join(";")}}
|
|
11758
|
+
` : ""}ctx._fe=pos;ctx._fx=${choiceFx}
|
|
11759
|
+
return FAIL
|
|
11760
|
+
}`;
|
|
11761
|
+
}
|
|
11762
|
+
if (cfg.probe) {
|
|
11763
|
+
const p = tmp();
|
|
11764
|
+
return `${head}
|
|
11765
|
+
${emitMark(p, L.buf, L.raw, sinks)}
|
|
11766
|
+
let acc
|
|
11767
|
+
let best=pos
|
|
11768
|
+
${arms.map((arm) => `{ctx._fc=false
|
|
11769
|
+
const v=${arm}(input,pos,ctx)
|
|
11770
|
+
if(v!==FAIL)return v
|
|
11771
|
+
const at=ctx._fe??pos
|
|
11772
|
+
if(at>best){best=at;acc=undefined}
|
|
11773
|
+
if(at===best)acc=_accSet(ctx._fx,acc)
|
|
11774
|
+
if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
|
|
11775
|
+
${emitRollback(p, L.buf, L.raw, sinks)}
|
|
11776
|
+
}`).join("\n")}
|
|
11777
|
+
ctx._fe=pos;ctx._fx=acc??${choiceFx}
|
|
11258
11778
|
return FAIL
|
|
11259
11779
|
}`;
|
|
11260
11780
|
}
|
|
@@ -11461,7 +11981,8 @@ return FAIL
|
|
|
11461
11981
|
const selector = link(code[ip + 1]);
|
|
11462
11982
|
const otherIp = code[ip + 3];
|
|
11463
11983
|
const other = otherIp >= 0 ? link(otherIp) : void 0;
|
|
11464
|
-
const otherRouted = code[ip + 4] === 1;
|
|
11984
|
+
const otherRouted = (code[ip + 4] & 1) === 1;
|
|
11985
|
+
const otherCommits = (code[ip + 4] & 2) === 0;
|
|
11465
11986
|
const n = code[ip + 5];
|
|
11466
11987
|
validateDispatchSpec(spec, n, code[ip + 4]);
|
|
11467
11988
|
const armBase = ip + 6;
|
|
@@ -11515,7 +12036,7 @@ ${fallbackCase}
|
|
|
11515
12036
|
}
|
|
11516
12037
|
if(v===FAIL){
|
|
11517
12038
|
${emitRollback(m2, L.buf, L.raw, sinks)}
|
|
11518
|
-
ctx._fc=true
|
|
12039
|
+
${other !== void 0 && !otherCommits ? "if(arm!==undefined)" : ""}ctx._fc=true
|
|
11519
12040
|
return FAIL
|
|
11520
12041
|
}
|
|
11521
12042
|
return [key,v]
|
|
@@ -11547,6 +12068,63 @@ return [key,v]
|
|
|
11547
12068
|
}
|
|
11548
12069
|
}
|
|
11549
12070
|
const itemMiss = (at) => itemAscii ? `${itemCls}.ascii[input.charCodeAt(${at})]!==1` : `!classHas(${itemCls},lead(input,${at}))`;
|
|
12071
|
+
let sepCls;
|
|
12072
|
+
let sepAscii = false;
|
|
12073
|
+
if (!REC && sepIp >= 0 && (code[ip + 5] & 8) !== 0 && !leadingTriviaFieldAt(code, k, sepIp) && !rowNullable(code, k, sepIp, nullable2)) {
|
|
12074
|
+
const resolved = t2.cc[code[ip + 8]];
|
|
12075
|
+
const ci = classes.push([resolved]) - 1;
|
|
12076
|
+
classPlan.push([code[ip + 8]]);
|
|
12077
|
+
sepCls = hoist("rs", `CLS[${ci}][0]`);
|
|
12078
|
+
sepAscii = isAsciiOnlyClass(resolved);
|
|
12079
|
+
}
|
|
12080
|
+
const gapIp = !gapNeutral && sepIp < 0 && min === 0 && !REC && code[code[ip + 1]] === OP_GAPGATE ? code[ip + 1] : -1;
|
|
12081
|
+
let gapCode = (_rb) => "";
|
|
12082
|
+
if (gapIp >= 0) {
|
|
12083
|
+
const row = code[gapIp + 2];
|
|
12084
|
+
const rx = k[code[row + 1]];
|
|
12085
|
+
const shape = gapRegexLowers(rx) ? scanShapeFromRegex(rx.source, rx.flags) : null;
|
|
12086
|
+
const cls = (idx) => {
|
|
12087
|
+
const resolved = t2.cc[idx];
|
|
12088
|
+
const ci = classes.push([resolved]) - 1;
|
|
12089
|
+
classPlan.push([idx]);
|
|
12090
|
+
const ref2 = hoist("gc", `CLS[${ci}][0]`);
|
|
12091
|
+
return isAsciiOnlyClass(resolved) ? `${ref2}.ascii[input.charCodeAt(${"@"})]!==1` : `!classHas(${ref2},lead(input,${"@"}))`;
|
|
12092
|
+
};
|
|
12093
|
+
const follow = cls(code[gapIp + 3]).replaceAll("@", "gq");
|
|
12094
|
+
const other = code[gapIp + 4] >= 0 ? cls(code[gapIp + 4]).replaceAll("@", "itemStart") : "true";
|
|
12095
|
+
if (shape !== null) {
|
|
12096
|
+
let n = 0;
|
|
12097
|
+
const q2 = tmp();
|
|
12098
|
+
const m = emitShapeMatch(shape, "itemStart", (prefix = "_v") => `${q2}${prefix}${n++}`, "");
|
|
12099
|
+
gapCode = (rbCode) => `let gapped=false
|
|
12100
|
+
if(ctx._probe===undefined){
|
|
12101
|
+
${m.setup.join("\n")}
|
|
12102
|
+
const gq=${m.ok}?${m.end}:-1
|
|
12103
|
+
if((gq<0||${follow})&&${other}){
|
|
12104
|
+
${rbCode}
|
|
12105
|
+
break
|
|
12106
|
+
}
|
|
12107
|
+
}
|
|
12108
|
+
`;
|
|
12109
|
+
} else {
|
|
12110
|
+
const re = hoist("gr", `K[${code[row + 1]}]`);
|
|
12111
|
+
gapCode = (rbCode) => `let gapped=false
|
|
12112
|
+
if(ctx._probe===undefined){
|
|
12113
|
+
${re}.lastIndex=itemStart
|
|
12114
|
+
const gq=${re}.test(input)?${re}.lastIndex:-1
|
|
12115
|
+
if((gq<0||${follow})&&${other}){
|
|
12116
|
+
${rbCode}
|
|
12117
|
+
break
|
|
12118
|
+
}
|
|
12119
|
+
if(gq>=0){
|
|
12120
|
+
GAP.row=${row};GAP.at=itemStart;GAP.end=gq;GAP.input=input
|
|
12121
|
+
gapped=true
|
|
12122
|
+
}
|
|
12123
|
+
}
|
|
12124
|
+
`;
|
|
12125
|
+
}
|
|
12126
|
+
}
|
|
12127
|
+
const sepMiss = (at) => sepAscii ? `${sepCls}.ascii[input.charCodeAt(${at})]!==1` : `!classHas(${sepCls},lead(input,${at}))`;
|
|
11550
12128
|
const skipBeforeFirst = sepIp < 0 && min === 0;
|
|
11551
12129
|
const p = tmp();
|
|
11552
12130
|
const via = sep !== void 0 ? "false" : min === 0 ? skipBeforeFirst ? "true" : "count>0" : `count>=${min}&&count>0`;
|
|
@@ -11584,7 +12162,7 @@ ${p}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
|
11584
12162
|
${p}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${markSinks}
|
|
11585
12163
|
}`;
|
|
11586
12164
|
const my = `${p}my`;
|
|
11587
|
-
const recFx = REC ? fxRef(code[ip + 6])
|
|
12165
|
+
const recFx = !REC ? "" : (flags & 16) !== 0 ? "[]" : fxRef(code[ip + 6]);
|
|
11588
12166
|
const sepSent = REC ? sentRef(code[ip + 7]) : "undefined";
|
|
11589
12167
|
const recSent = sep === void 0 ? my : sepSent === "undefined" ? `orSentinel(${my},undefined)` : `orSentinel(${sepSent}??${my},${sepSent}===undefined?undefined:${my})`;
|
|
11590
12168
|
const recGate = sep !== void 0 || min === 0 ? "" : `count>=${min}&&`;
|
|
@@ -11600,7 +12178,7 @@ continue
|
|
|
11600
12178
|
return `${head}
|
|
11601
12179
|
const out=${collect ? "[]" : "undefined"}
|
|
11602
12180
|
${knownTrivia === void 0 ? "const hasTrivia=ctx.trivia!==undefined\n" : ""}${L.buf ? "" : "const needMark=_rollbackNeeded(ctx)\n"}${REC ? `const ${my}=ctx._sync
|
|
11603
|
-
` : ""}${itemCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
|
|
12181
|
+
` : ""}${itemCls === void 0 && sepCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
|
|
11604
12182
|
`}let cur=pos
|
|
11605
12183
|
let count=0
|
|
11606
12184
|
for(;;){
|
|
@@ -11616,6 +12194,10 @@ const lb=cstLeavesLen(ctx)
|
|
|
11616
12194
|
let sp=cur
|
|
11617
12195
|
${hasTrivia === "false" ? "" : hasTrivia === "true" ? `sp=${skip}(input,sp,ctx)
|
|
11618
12196
|
` : `if(hasTrivia)sp=${skip}(input,sp,ctx)
|
|
12197
|
+
`}${sepCls === void 0 ? "" : `if(count>=${min}&&${p}gate&&${sepMiss("sp")}){
|
|
12198
|
+
${rb}
|
|
12199
|
+
break
|
|
12200
|
+
}
|
|
11619
12201
|
`}ctx._fc=false
|
|
11620
12202
|
${sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp) ? "LEAD.at=cur\n" : ""}const sv=${sep}(input,sp,ctx)
|
|
11621
12203
|
if(sv===FAIL){
|
|
@@ -11631,13 +12213,13 @@ itemStart=${hasTrivia === "false" ? "EC.e" : hasTrivia === "true" ? `${skip}(inp
|
|
|
11631
12213
|
${rb}
|
|
11632
12214
|
${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
|
|
11633
12215
|
}
|
|
11634
|
-
${itemCls === void 0 ? "" : `if(count>=${min}&&${p}gate&&${itemMiss("itemStart")}){
|
|
12216
|
+
${itemCls === void 0 || sep === void 0 && hasTrivia === "false" ? "" : `if(count>=${min}&&${p}gate&&${sep === void 0 && hasTrivia === "hasTrivia" ? "hasTrivia&&" : ""}${itemMiss("itemStart")}){
|
|
11635
12217
|
${rb}
|
|
11636
12218
|
${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
|
|
11637
12219
|
}
|
|
11638
|
-
`}ctx._fc=false
|
|
12220
|
+
`}${gapCode(rb)}ctx._fc=false
|
|
11639
12221
|
const v=${child}(input,itemStart,ctx)
|
|
11640
|
-
if(v===FAIL){
|
|
12222
|
+
${gapIp >= 0 ? "if(gapped)GAP.at=-1\n" : ""}if(v===FAIL){
|
|
11641
12223
|
${REC ? `if(ctx._fc===true){
|
|
11642
12224
|
${rb}
|
|
11643
12225
|
return FAIL
|
|
@@ -12609,6 +13191,9 @@ function clearOf(ranges, input, from, to) {
|
|
|
12609
13191
|
return true;
|
|
12610
13192
|
}
|
|
12611
13193
|
|
|
13194
|
+
// src/version.ts
|
|
13195
|
+
var PARSEMAN_VERSION = "0.60.0";
|
|
13196
|
+
|
|
12612
13197
|
// src/table/assemble.ts
|
|
12613
13198
|
import { PlainBuf as PlainBuf2, PlainField, PlainLeaf as PlainLeaf9, PlainNode as PlainNode2, PlainSpan as PlainSpan10 } from "../cst/plain.js";
|
|
12614
13199
|
|
|
@@ -12619,6 +13204,7 @@ function passChild(code, ip) {
|
|
|
12619
13204
|
case OP_LABEL:
|
|
12620
13205
|
case OP_COV:
|
|
12621
13206
|
case OP_TOKEN:
|
|
13207
|
+
case OP_GAPGATE:
|
|
12622
13208
|
return code[ip + 1];
|
|
12623
13209
|
case OP_GATE:
|
|
12624
13210
|
case OP_NODE:
|
|
@@ -12871,6 +13457,13 @@ function cfgKeyOf(hostCst, trackLines, tolerant, coverage, probe, hostReadsChild
|
|
|
12871
13457
|
function cfgKey(c) {
|
|
12872
13458
|
return cfgKeyOf(c.hostCst, c.trackLines, c.tolerant, c.coverage, c.probe, c.hostReadsChildren);
|
|
12873
13459
|
}
|
|
13460
|
+
function assertFactoryArity(pre) {
|
|
13461
|
+
if (pre.arity === EMITTED_PARAMS.length) return;
|
|
13462
|
+
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`;
|
|
13463
|
+
throw new Error(
|
|
13464
|
+
`parseman: this parser's printed assembly ${printed}. Reprint the parser with parseman ${PARSEMAN_VERSION}, or run it on the parseman version that printed it.`
|
|
13465
|
+
);
|
|
13466
|
+
}
|
|
12874
13467
|
function assemble(t2, prog, cfg) {
|
|
12875
13468
|
const { code, k, fns, cc, fx, disp, dsp, trivia: trivia2, triviaLabelled } = t2;
|
|
12876
13469
|
const triviaScan = t2.triviaScan;
|
|
@@ -12905,6 +13498,8 @@ function assemble(t2, prog, cfg) {
|
|
|
12905
13498
|
return recognize;
|
|
12906
13499
|
}
|
|
12907
13500
|
const labelExtraIps = assemblyExtraIps(prog);
|
|
13501
|
+
const GAP_ROWS = gapRows(code, [...Object.values(prog.rules), ...labelExtraIps]);
|
|
13502
|
+
const GAP = newGapSlot();
|
|
12908
13503
|
const closureLabels = computeSiteLabels(
|
|
12909
13504
|
code,
|
|
12910
13505
|
[...Object.values(prog.rules), ...labelExtraIps],
|
|
@@ -13123,6 +13718,27 @@ function assemble(t2, prog, cfg) {
|
|
|
13123
13718
|
return node2;
|
|
13124
13719
|
};
|
|
13125
13720
|
}
|
|
13721
|
+
function gapRegexPiece(row, re, xf, track) {
|
|
13722
|
+
return (input, pos, ctx) => {
|
|
13723
|
+
let e;
|
|
13724
|
+
if (GAP.row === row && GAP.at === pos && GAP.input === input) e = GAP.end;
|
|
13725
|
+
else {
|
|
13726
|
+
re.lastIndex = pos;
|
|
13727
|
+
e = re.test(input) ? re.lastIndex : -1;
|
|
13728
|
+
}
|
|
13729
|
+
if (e >= 0) {
|
|
13730
|
+
const v = input.slice(pos, e);
|
|
13731
|
+
if (cstCaptureActive(ctx)) pushLeaf(ctx, v, pos, e);
|
|
13732
|
+
if (track) trackLinesInto(ctx, input, e);
|
|
13733
|
+
EC.e = e;
|
|
13734
|
+
return v;
|
|
13735
|
+
}
|
|
13736
|
+
ctx._fe = pos;
|
|
13737
|
+
ctx._fx = xf;
|
|
13738
|
+
if (ctx._probe !== void 0) failAt(ctx, xf, pos);
|
|
13739
|
+
return FAIL;
|
|
13740
|
+
};
|
|
13741
|
+
}
|
|
13126
13742
|
function passCollapseNode(child, build, readsRaw) {
|
|
13127
13743
|
return (input, pos, ctx) => {
|
|
13128
13744
|
const v = child(input, pos, ctx);
|
|
@@ -13525,7 +14141,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13525
14141
|
return next?.(key);
|
|
13526
14142
|
};
|
|
13527
14143
|
}
|
|
13528
|
-
function dispatchBranch(child, usesRouted) {
|
|
14144
|
+
function dispatchBranch(child, usesRouted, commits = true) {
|
|
13529
14145
|
if (!usesRouted) {
|
|
13530
14146
|
return (input, _pos, selEnd, key, ctx) => {
|
|
13531
14147
|
const need = markCst(ctx);
|
|
@@ -13539,7 +14155,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13539
14155
|
const v = child(input, selEnd, ctx);
|
|
13540
14156
|
if (v === FAIL) {
|
|
13541
14157
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
13542
|
-
ctx._fc = true;
|
|
14158
|
+
if (commits) ctx._fc = true;
|
|
13543
14159
|
return FAIL;
|
|
13544
14160
|
}
|
|
13545
14161
|
return [key, v];
|
|
@@ -13557,7 +14173,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13557
14173
|
}
|
|
13558
14174
|
if (v === FAIL) {
|
|
13559
14175
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
13560
|
-
ctx._fc = true;
|
|
14176
|
+
if (commits) ctx._fc = true;
|
|
13561
14177
|
return FAIL;
|
|
13562
14178
|
}
|
|
13563
14179
|
return [key, v];
|
|
@@ -13798,6 +14414,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13798
14414
|
case OP_RX: {
|
|
13799
14415
|
const re = k[code[ip + 1]];
|
|
13800
14416
|
const xf = fx[code[ip + 2]];
|
|
14417
|
+
if (GAP_ROWS.has(ip)) return gapRegexPiece(ip, re, xf, false);
|
|
13801
14418
|
const shared = rawScalarSpecs.has(code[ip + 1]) ? scalarFor(ip) : void 0;
|
|
13802
14419
|
if (shared !== void 0) {
|
|
13803
14420
|
return (input, pos, ctx) => {
|
|
@@ -13832,6 +14449,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13832
14449
|
case OP_RX_TRACK: {
|
|
13833
14450
|
const re = k[code[ip + 1]];
|
|
13834
14451
|
const xf = fx[code[ip + 2]];
|
|
14452
|
+
if (GAP_ROWS.has(ip)) return gapRegexPiece(ip, re, xf, true);
|
|
13835
14453
|
return (input, pos, ctx) => {
|
|
13836
14454
|
re.lastIndex = pos;
|
|
13837
14455
|
if (re.test(input)) {
|
|
@@ -13962,6 +14580,12 @@ function assemble(t2, prog, cfg) {
|
|
|
13962
14580
|
return v;
|
|
13963
14581
|
};
|
|
13964
14582
|
}
|
|
14583
|
+
// Transparent: only the repeat holding it reads its operands.
|
|
14584
|
+
case OP_GAPGATE:
|
|
14585
|
+
return link(code[ip + 1]);
|
|
14586
|
+
// One encoding per assembly: strict, or the construct as written.
|
|
14587
|
+
case OP_STRICT:
|
|
14588
|
+
return link(code[cfg.tolerant || cfg.probe ? ip + 2 : ip + 1]);
|
|
13965
14589
|
case OP_RULE:
|
|
13966
14590
|
return link(code[ip + 1]);
|
|
13967
14591
|
case OP_LIVE: {
|
|
@@ -14887,7 +15511,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14887
15511
|
if (table.exclusive) {
|
|
14888
15512
|
const ascii = table.ascii;
|
|
14889
15513
|
const hi = table.hi;
|
|
14890
|
-
if (n === 2) {
|
|
15514
|
+
if (n === 2 && !cfg.probe) {
|
|
14891
15515
|
const a0 = link(code[base]), a1 = link(code[base + 1]);
|
|
14892
15516
|
return (input, pos, ctx) => {
|
|
14893
15517
|
const c = lead(input, pos);
|
|
@@ -14919,7 +15543,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14919
15543
|
return FAIL;
|
|
14920
15544
|
};
|
|
14921
15545
|
}
|
|
14922
|
-
if (n === 3) {
|
|
15546
|
+
if (n === 3 && !cfg.probe) {
|
|
14923
15547
|
const a0 = link(code[base]), a1 = link(code[base + 1]), a2 = link(code[base + 2]);
|
|
14924
15548
|
return (input, pos, ctx) => {
|
|
14925
15549
|
const c = lead(input, pos);
|
|
@@ -14964,6 +15588,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14964
15588
|
);
|
|
14965
15589
|
};
|
|
14966
15590
|
const selected = bindExclusive(0);
|
|
15591
|
+
const probeArms = cfg.probe ? Array.from({ length: n }, (_, i) => link(code[base + i])) : void 0;
|
|
14967
15592
|
return (input, pos, ctx) => {
|
|
14968
15593
|
const c = lead(input, pos);
|
|
14969
15594
|
let arm = -1;
|
|
@@ -14989,12 +15614,13 @@ function assemble(t2, prog, cfg) {
|
|
|
14989
15614
|
return FAIL;
|
|
14990
15615
|
}
|
|
14991
15616
|
}
|
|
15617
|
+
if (arm < 0 && probeArms !== void 0) for (const a of probeArms) a(input, pos, ctx);
|
|
14992
15618
|
ctx._fe = pos;
|
|
14993
15619
|
ctx._fx = choiceFx;
|
|
14994
15620
|
return FAIL;
|
|
14995
15621
|
};
|
|
14996
15622
|
}
|
|
14997
|
-
const armCls = table.armCls;
|
|
15623
|
+
const armCls = cfg.probe ? table.armCls.map(() => null) : table.armCls;
|
|
14998
15624
|
if (n === 2 || n === 3) {
|
|
14999
15625
|
const a0 = link(code[base]), a1 = link(code[base + 1]);
|
|
15000
15626
|
const a2 = n === 3 ? link(code[base + 2]) : void 0;
|
|
@@ -15414,6 +16040,43 @@ function assemble(t2, prog, cfg) {
|
|
|
15414
16040
|
return child(input, pos, ctx);
|
|
15415
16041
|
};
|
|
15416
16042
|
}
|
|
16043
|
+
case OP_RGATE2: {
|
|
16044
|
+
const cls = cc[code[ip + 1]];
|
|
16045
|
+
const xf = fx[code[ip + 3]];
|
|
16046
|
+
const first = cc[code[ip + 4]];
|
|
16047
|
+
const second = cc[code[ip + 5]];
|
|
16048
|
+
const child = link(code[ip + 2]);
|
|
16049
|
+
if (cfg.tolerant || cfg.probe) return child;
|
|
16050
|
+
if (cls.hi.length === 0 && first.hi.length === 0 && second.hi.length === 0) {
|
|
16051
|
+
const a0 = cls.ascii, a1 = first.ascii, a2 = second.ascii;
|
|
16052
|
+
return (input, pos, ctx) => {
|
|
16053
|
+
const item = ctx._routed;
|
|
16054
|
+
if (item !== void 0 && item.span.start === pos) {
|
|
16055
|
+
const e = item.span.end;
|
|
16056
|
+
const c = input.charCodeAt(e);
|
|
16057
|
+
if (a0[c] !== 1 || a1[c] === 1 && a2[input.charCodeAt(e + 1)] !== 1) {
|
|
16058
|
+
ctx._fe = e;
|
|
16059
|
+
ctx._fx = xf;
|
|
16060
|
+
return FAIL;
|
|
16061
|
+
}
|
|
16062
|
+
}
|
|
16063
|
+
return child(input, pos, ctx);
|
|
16064
|
+
};
|
|
16065
|
+
}
|
|
16066
|
+
return (input, pos, ctx) => {
|
|
16067
|
+
const item = ctx._routed;
|
|
16068
|
+
if (item !== void 0 && item.span.start === pos) {
|
|
16069
|
+
const e = item.span.end;
|
|
16070
|
+
const c = lead(input, e);
|
|
16071
|
+
if (!classHas2(cls, c) || classHas2(first, c) && !classHas2(second, lead(input, e + 1))) {
|
|
16072
|
+
ctx._fe = e;
|
|
16073
|
+
ctx._fx = xf;
|
|
16074
|
+
return FAIL;
|
|
16075
|
+
}
|
|
16076
|
+
}
|
|
16077
|
+
return child(input, pos, ctx);
|
|
16078
|
+
};
|
|
16079
|
+
}
|
|
15417
16080
|
case OP_ARMGATE: {
|
|
15418
16081
|
const pred = fns[code[ip + 1]];
|
|
15419
16082
|
const child = link(code[ip + 2]);
|
|
@@ -15481,10 +16144,18 @@ function assemble(t2, prog, cfg) {
|
|
|
15481
16144
|
const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
|
|
15482
16145
|
const itemClass = !REC && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
|
|
15483
16146
|
const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
|
|
16147
|
+
const sepClassIndex = sepIp >= 0 && !sepLeads && (flags & 8) !== 0 ? code[ip + 8] : -1;
|
|
16148
|
+
const sepClass = !REC && sepClassIndex >= 0 && !rowNullable(code, k, sepIp, NULLABLE) ? cc[sepClassIndex] : void 0;
|
|
16149
|
+
const gapIp = sepIp < 0 && min === 0 && !REC && code[code[ip + 1]] === OP_GAPGATE ? code[ip + 1] : -1;
|
|
16150
|
+
const gapRow = gapIp >= 0 ? code[gapIp + 2] : -1;
|
|
16151
|
+
const gapRe = gapIp >= 0 ? k[code[gapRow + 1]] : void 0;
|
|
16152
|
+
const gapFollow = gapIp >= 0 ? cc[code[gapIp + 3]] : void 0;
|
|
16153
|
+
const gapOther = gapIp >= 0 && code[gapIp + 4] >= 0 ? cc[code[gapIp + 4]] : void 0;
|
|
15484
16154
|
const skipBeforeFirst = sepIp < 0 && min === 0;
|
|
15485
16155
|
const itemClean = sepIp < 0 && CLEAN(code[ip + 1]) && !rowNullable(code, k, code[ip + 1], NULLABLE);
|
|
15486
16156
|
if (REC) {
|
|
15487
16157
|
const itemFx2 = fx[code[ip + 6]];
|
|
16158
|
+
const recFx = (flags & 16) !== 0 ? EMPTY_FX2 : itemFx2;
|
|
15488
16159
|
const sepSent = sentinelFor(code[ip + 7]);
|
|
15489
16160
|
return (input, pos, ctx) => {
|
|
15490
16161
|
const out = collect ? [] : void 0;
|
|
@@ -15544,7 +16215,7 @@ function assemble(t2, prog, cfg) {
|
|
|
15544
16215
|
itemStart,
|
|
15545
16216
|
ctx,
|
|
15546
16217
|
sep === void 0 ? mySync : orSentinel(sepSent ?? mySync, sepSent === void 0 ? void 0 : mySync),
|
|
15547
|
-
|
|
16218
|
+
recFx
|
|
15548
16219
|
);
|
|
15549
16220
|
if (out !== void 0) out.push(rr.error);
|
|
15550
16221
|
captureError(ctx, rr.error);
|
|
@@ -15582,6 +16253,7 @@ function assemble(t2, prog, cfg) {
|
|
|
15582
16253
|
const markLater = needMark && (!itemClean || hasTrivia);
|
|
15583
16254
|
const markFirst = needMark && (!itemClean || hasTrivia && skipBeforeFirst);
|
|
15584
16255
|
const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
|
|
16256
|
+
const gateSep = sepClass !== void 0 && ctx._probe === void 0;
|
|
15585
16257
|
let cur = pos;
|
|
15586
16258
|
let count = 0;
|
|
15587
16259
|
for (; ; ) {
|
|
@@ -15604,6 +16276,10 @@ function assemble(t2, prog, cfg) {
|
|
|
15604
16276
|
const leavesBefore = cstLeavesLen(ctx);
|
|
15605
16277
|
let sp = cur;
|
|
15606
16278
|
if (hasTrivia) sp = skipTrivia(input, sp, ctx);
|
|
16279
|
+
if (count >= min && gateSep && !classHas2(sepClass, lead(input, sp))) {
|
|
16280
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
16281
|
+
break;
|
|
16282
|
+
}
|
|
15607
16283
|
ctx._fc = false;
|
|
15608
16284
|
if (sepLeads) LEAD.at = cur;
|
|
15609
16285
|
const sv = sep(input, sp, ctx);
|
|
@@ -15623,13 +16299,30 @@ function assemble(t2, prog, cfg) {
|
|
|
15623
16299
|
if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
|
|
15624
16300
|
break;
|
|
15625
16301
|
}
|
|
15626
|
-
if (count >= min && gateItems && !itemMayStart(input, itemStart)) {
|
|
16302
|
+
if (count >= min && gateItems && (sep !== void 0 || hasTrivia) && !itemMayStart(input, itemStart)) {
|
|
15627
16303
|
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
15628
16304
|
if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
|
|
15629
16305
|
break;
|
|
15630
16306
|
}
|
|
16307
|
+
let gapped = false;
|
|
16308
|
+
if (gapRe !== void 0 && ctx._probe === void 0) {
|
|
16309
|
+
gapRe.lastIndex = itemStart;
|
|
16310
|
+
const q2 = gapRe.test(input) ? gapRe.lastIndex : -1;
|
|
16311
|
+
if ((q2 < 0 || !classHas2(gapFollow, lead(input, q2))) && (gapOther === void 0 || !classHas2(gapOther, lead(input, itemStart)))) {
|
|
16312
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
16313
|
+
break;
|
|
16314
|
+
}
|
|
16315
|
+
if (q2 >= 0) {
|
|
16316
|
+
GAP.row = gapRow;
|
|
16317
|
+
GAP.at = itemStart;
|
|
16318
|
+
GAP.end = q2;
|
|
16319
|
+
GAP.input = input;
|
|
16320
|
+
gapped = true;
|
|
16321
|
+
}
|
|
16322
|
+
}
|
|
15631
16323
|
ctx._fc = false;
|
|
15632
16324
|
const v = child(input, itemStart, ctx);
|
|
16325
|
+
if (gapped) GAP.at = -1;
|
|
15633
16326
|
if (v === FAIL) {
|
|
15634
16327
|
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
15635
16328
|
if (committed3(ctx)) return FAIL;
|
|
@@ -15661,7 +16354,8 @@ function assemble(t2, prog, cfg) {
|
|
|
15661
16354
|
const selector = link(code[ip + 1]);
|
|
15662
16355
|
const otherIp = code[ip + 3];
|
|
15663
16356
|
const other = otherIp >= 0 ? link(otherIp) : void 0;
|
|
15664
|
-
const otherRouted = code[ip + 4] === 1;
|
|
16357
|
+
const otherRouted = (code[ip + 4] & 1) === 1;
|
|
16358
|
+
const otherCommits = (code[ip + 4] & 2) === 0;
|
|
15665
16359
|
const n = code[ip + 5];
|
|
15666
16360
|
const armBase = ip + 6;
|
|
15667
16361
|
const byKey = spec.byKey;
|
|
@@ -15709,7 +16403,7 @@ function assemble(t2, prog, cfg) {
|
|
|
15709
16403
|
);
|
|
15710
16404
|
};
|
|
15711
16405
|
const runArm = n === 0 ? void 0 : bindArms(0);
|
|
15712
|
-
const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted);
|
|
16406
|
+
const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted, otherCommits);
|
|
15713
16407
|
return (input, pos, ctx) => {
|
|
15714
16408
|
const need = markCst(ctx);
|
|
15715
16409
|
const mRaw = MRAW;
|
|
@@ -15970,6 +16664,7 @@ function assemble(t2, prog, cfg) {
|
|
|
15970
16664
|
}
|
|
15971
16665
|
const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
|
|
15972
16666
|
if (pre !== void 0) {
|
|
16667
|
+
assertFactoryArity(pre);
|
|
15973
16668
|
const pools = rebuildPools(t2.cc, t2.fx, t2.disp, pre.plan);
|
|
15974
16669
|
emitted = pre.factory(
|
|
15975
16670
|
EC,
|
|
@@ -15981,7 +16676,6 @@ function assemble(t2, prog, cfg) {
|
|
|
15981
16676
|
pools.classes,
|
|
15982
16677
|
pools.armExpected,
|
|
15983
16678
|
trivia2,
|
|
15984
|
-
trivia2.map((tv) => tv?._meta.triviaKindLabels),
|
|
15985
16679
|
triviaScan,
|
|
15986
16680
|
scansArr,
|
|
15987
16681
|
disp,
|
|
@@ -16005,7 +16699,6 @@ function assemble(t2, prog, cfg) {
|
|
|
16005
16699
|
cstLeavesLen,
|
|
16006
16700
|
skipTriviaScanned,
|
|
16007
16701
|
needsDeferredTriviaCommit,
|
|
16008
|
-
scanTrivia,
|
|
16009
16702
|
advanceTrivia,
|
|
16010
16703
|
refuseUnclassifiedRootScope,
|
|
16011
16704
|
spanLines,
|
|
@@ -16019,8 +16712,6 @@ function assemble(t2, prog, cfg) {
|
|
|
16019
16712
|
orSentinel,
|
|
16020
16713
|
captureError,
|
|
16021
16714
|
scalarRecognizers,
|
|
16022
|
-
commitTriviaScan,
|
|
16023
|
-
scanTriviaCompact,
|
|
16024
16715
|
t2.lex,
|
|
16025
16716
|
adjacencyHolds,
|
|
16026
16717
|
t2.lexPrograms,
|
|
@@ -16032,7 +16723,8 @@ function assemble(t2, prog, cfg) {
|
|
|
16032
16723
|
PlainLeaf9,
|
|
16033
16724
|
PlainNode2,
|
|
16034
16725
|
PlainField,
|
|
16035
|
-
PlainBuf2
|
|
16726
|
+
PlainBuf2,
|
|
16727
|
+
GAP
|
|
16036
16728
|
);
|
|
16037
16729
|
emitReached = new Set(pre.reached);
|
|
16038
16730
|
if (emitted.ext !== void 0) HYBRID = emitted;
|
|
@@ -16068,7 +16760,6 @@ function assemble(t2, prog, cfg) {
|
|
|
16068
16760
|
em.classes,
|
|
16069
16761
|
em.armExpected,
|
|
16070
16762
|
trivia2,
|
|
16071
|
-
trivia2.map((tv) => tv?._meta.triviaKindLabels),
|
|
16072
16763
|
triviaScan,
|
|
16073
16764
|
scansArr,
|
|
16074
16765
|
disp,
|
|
@@ -16092,7 +16783,6 @@ function assemble(t2, prog, cfg) {
|
|
|
16092
16783
|
cstLeavesLen,
|
|
16093
16784
|
skipTriviaScanned,
|
|
16094
16785
|
needsDeferredTriviaCommit,
|
|
16095
|
-
scanTrivia,
|
|
16096
16786
|
advanceTrivia,
|
|
16097
16787
|
refuseUnclassifiedRootScope,
|
|
16098
16788
|
spanLines,
|
|
@@ -16111,8 +16801,6 @@ function assemble(t2, prog, cfg) {
|
|
|
16111
16801
|
orSentinel,
|
|
16112
16802
|
captureError,
|
|
16113
16803
|
scalarRecognizers,
|
|
16114
|
-
commitTriviaScan,
|
|
16115
|
-
scanTriviaCompact,
|
|
16116
16804
|
t2.lex,
|
|
16117
16805
|
adjacencyHolds,
|
|
16118
16806
|
t2.lexPrograms,
|
|
@@ -16124,7 +16812,8 @@ function assemble(t2, prog, cfg) {
|
|
|
16124
16812
|
PlainLeaf9,
|
|
16125
16813
|
PlainNode2,
|
|
16126
16814
|
PlainField,
|
|
16127
|
-
PlainBuf2
|
|
16815
|
+
PlainBuf2,
|
|
16816
|
+
GAP
|
|
16128
16817
|
);
|
|
16129
16818
|
emitReached = em.reached;
|
|
16130
16819
|
} catch (e) {
|
|
@@ -16382,11 +17071,8 @@ function tableRules(source, metadataOrEntry = {}) {
|
|
|
16382
17071
|
return map[entry];
|
|
16383
17072
|
}
|
|
16384
17073
|
|
|
16385
|
-
// src/version.ts
|
|
16386
|
-
var PARSEMAN_VERSION = "0.59.3";
|
|
16387
|
-
|
|
16388
17074
|
// src/table/emit.ts
|
|
16389
|
-
var FACTORY_ARITY_GUARD = `if(arguments.length
|
|
17075
|
+
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`)});`;
|
|
16390
17076
|
function jsString(s) {
|
|
16391
17077
|
return JSON.stringify(s);
|
|
16392
17078
|
}
|
|
@@ -16461,7 +17147,7 @@ function emitAssemblies(prog, cfgs) {
|
|
|
16461
17147
|
throw e;
|
|
16462
17148
|
}
|
|
16463
17149
|
const plan = em.plan;
|
|
16464
|
-
out.push(`{key:${key},factory:function(${EMITTED_PARAMS.join(",")}){${FACTORY_ARITY_GUARD}${em.source}
|
|
17150
|
+
out.push(`{key:${key},arity:${EMITTED_PARAMS.length},factory:function(${EMITTED_PARAMS.join(",")}){${FACTORY_ARITY_GUARD}${em.source}
|
|
16465
17151
|
},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(",")}]}`);
|
|
16466
17152
|
}
|
|
16467
17153
|
return [`a:[${out.join(",")}],`];
|
|
@@ -16737,7 +17423,7 @@ function payloadKey(p, d) {
|
|
|
16737
17423
|
case "sepBy":
|
|
16738
17424
|
return `sepBy\0${d.min}\0${d.max ?? ""}\0${d.trailing ?? ""}`;
|
|
16739
17425
|
case "dispatch":
|
|
16740
|
-
return `dispatch\0${d.cases.map((c) => JSON.stringify(c.keys)).join("")}\0${d.otherwise !== void 0}`;
|
|
17426
|
+
return `dispatch\0${d.cases.map((c) => JSON.stringify(c.keys)).join("")}\0${d.otherwise !== void 0}${d.otherwiseCommit === false ? "\0uncommitted" : ""}`;
|
|
16741
17427
|
case "expect":
|
|
16742
17428
|
return `expect\0${d.label ?? ""}\0${d.expected.join("")}`;
|
|
16743
17429
|
case "scanTo":
|