parseman 0.59.2 → 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/commitment.d.ts +1 -1
- package/dist/analysis/diagnostics.js +877 -191
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/cli/index.js +877 -191
- package/dist/cli/index.js.map +3 -3
- package/dist/combinators/completions.d.ts +3 -3
- package/dist/combinators/completions.d.ts.map +1 -1
- 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/gate.d.ts +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/compile-linkable-table.d.ts +2 -3
- package/dist/compiler/compile-linkable-table.d.ts.map +1 -1
- package/dist/compiler/linker.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/cst/host-mode.d.ts +1 -1
- package/dist/cst/root-trivia-scope.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +897 -200
- package/dist/index.js.map +3 -3
- package/dist/language-service/index.d.ts +1 -1
- package/dist/language-service/index.js.map +1 -1
- package/dist/plugin/entry-supercompiler.d.ts.map +1 -1
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.d.ts +3 -7
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +904 -202
- 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/spec/index.js.map +1 -1
- package/dist/table/assemble.d.ts +16 -3
- 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 +3 -2
- package/dist/table/compile-rule-map.d.ts.map +1 -1
- package/dist/table/compile.d.ts +2 -2
- 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 +8 -8
- package/dist/table/emit.d.ts.map +1 -1
- package/dist/table/encode.d.ts +6 -7
- 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 +927 -202
- package/dist/table/index.js.map +3 -3
- package/dist/table/lex-program.d.ts.map +1 -1
- package/dist/table/ops.d.ts +48 -20
- package/dist/table/ops.d.ts.map +1 -1
- package/dist/table/program.d.ts +13 -8
- package/dist/table/program.d.ts.map +1 -1
- package/dist/types.d.ts +17 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +6 -6
- package/package.json +1 -1
- package/src/analysis/commitment.ts +1 -1
- package/src/analysis/duplication.ts +1 -1
- package/src/analysis/terminal.ts +1 -1
- package/src/combinators/attempt.ts +1 -1
- package/src/combinators/choice.ts +1 -1
- package/src/combinators/completions.ts +3 -3
- package/src/combinators/dispatch.ts +30 -6
- package/src/combinators/first-set.ts +55 -12
- package/src/combinators/gate.ts +1 -1
- 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/compile-linkable-table.ts +2 -3
- package/src/compiler/degradation.ts +2 -2
- package/src/compiler/ir-serialize.ts +1 -1
- package/src/compiler/linker.ts +5 -3
- package/src/compiler/token-alphabet.ts +3 -1
- package/src/coverage.ts +1 -1
- package/src/cst/capture-buffer.ts +2 -2
- package/src/cst/host-mode.ts +1 -1
- package/src/cst/root-trivia-scope.ts +1 -1
- package/src/index.ts +1 -1
- package/src/language-service/index.ts +1 -1
- package/src/plugin/entry-supercompiler.ts +2 -1
- package/src/plugin/evaluator.ts +8 -3
- package/src/plugin/index.ts +11 -16
- package/src/regex/first-set.ts +37 -3
- package/src/table/assemble.ts +180 -35
- package/src/table/child-slots.ts +8 -3
- package/src/table/compile-rule-map.ts +10 -6
- package/src/table/compile.ts +3 -3
- package/src/table/emit-assembly.ts +186 -35
- package/src/table/emit.ts +19 -18
- package/src/table/encode.ts +482 -88
- package/src/table/exec.ts +42 -18
- 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 +51 -20
- package/src/table/program.ts +14 -9
- package/src/table/select-hot.ts +7 -2
- package/src/table/stamp.ts +1 -1
- package/src/types.ts +13 -6
- package/src/version.ts +6 -6
package/dist/plugin/index.js
CHANGED
|
@@ -35,15 +35,56 @@ function implicitLeadsDropped(ranges) {
|
|
|
35
35
|
return out;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
// src/combinators/trivia-boundary.ts
|
|
39
|
+
var MAX_DEPTH = 12;
|
|
40
|
+
function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
|
|
41
|
+
if (depth === 0) return true;
|
|
42
|
+
const d = p._def;
|
|
43
|
+
switch (d.tag) {
|
|
44
|
+
// Multi-term forms: the gaps BETWEEN terms are the ambient-trivia positions.
|
|
45
|
+
case "sequence":
|
|
46
|
+
return d.parsers.length > 1;
|
|
47
|
+
case "many":
|
|
48
|
+
case "oneOrMore":
|
|
49
|
+
case "sepBy":
|
|
50
|
+
return true;
|
|
51
|
+
// Transparent wrappers — they add no position, so ask what they wrap.
|
|
52
|
+
case "node":
|
|
53
|
+
case "transform":
|
|
54
|
+
case "leaf":
|
|
55
|
+
case "label":
|
|
56
|
+
case "field":
|
|
57
|
+
case "token":
|
|
58
|
+
case "attempt":
|
|
59
|
+
case "optional":
|
|
60
|
+
case "expect":
|
|
61
|
+
case "withCtx":
|
|
62
|
+
case "recover":
|
|
63
|
+
case "trivia":
|
|
64
|
+
return hasOwnTriviaBoundary(d.parser, depth - 1);
|
|
65
|
+
// An alternation adds no position either, but ONE arm that has one is enough
|
|
66
|
+
// to make the scope meaningful for this rule.
|
|
67
|
+
case "choice":
|
|
68
|
+
return d.parsers.some((a) => hasOwnTriviaBoundary(a, depth - 1));
|
|
69
|
+
default:
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function triviaThroughRef(ref2, target, trivia2) {
|
|
74
|
+
if (trivia2 !== void 0 && trivia2 !== null) return trivia2;
|
|
75
|
+
const amb = ref2._meta.grammarTrivia ?? target._meta.grammarTrivia;
|
|
76
|
+
return amb !== void 0 && hasOwnTriviaBoundary(target) ? amb : trivia2;
|
|
77
|
+
}
|
|
78
|
+
|
|
38
79
|
// src/combinators/first-set.ts
|
|
39
|
-
function classifyFinalChoice(arms, resolve3, activeTrivia) {
|
|
80
|
+
function classifyFinalChoice(arms, resolve3, activeTrivia, consuming = true, constructionSets = false) {
|
|
40
81
|
const firstSets = [];
|
|
41
82
|
const nullable2 = [];
|
|
42
83
|
let exclusive = true;
|
|
43
84
|
for (const arm of arms) {
|
|
44
85
|
const empty2 = matchesEmpty(arm, /* @__PURE__ */ new Set(), resolve3);
|
|
45
86
|
nullable2.push(empty2);
|
|
46
|
-
firstSets.push(empty2 ? { kind: "any" } : firstSetOf(arm, /* @__PURE__ */ new Set(), resolve3, activeTrivia));
|
|
87
|
+
firstSets.push(empty2 ? { kind: "any" } : constructionSets ? arm._meta.firstSet : firstSetOf(arm, /* @__PURE__ */ new Set(), resolve3, activeTrivia, consuming));
|
|
47
88
|
if (empty2) exclusive = false;
|
|
48
89
|
}
|
|
49
90
|
if (exclusive) {
|
|
@@ -228,7 +269,7 @@ function narrowBy(acc, constraint) {
|
|
|
228
269
|
function applyAssertion(fs3, assertion) {
|
|
229
270
|
return assertion === null ? fs3 : fs3.kind === "empty" ? assertion : narrowBy(fs3, assertion);
|
|
230
271
|
}
|
|
231
|
-
function sequenceSet(parsers, fs3, empties, trivia2) {
|
|
272
|
+
function sequenceSet(parsers, fs3, empties, trivia2, consuming = true) {
|
|
232
273
|
const afterBoundary = (i) => {
|
|
233
274
|
const rest = at(i);
|
|
234
275
|
return trivia2 ? union(rest, fs3(trivia2)) : rest;
|
|
@@ -244,24 +285,24 @@ function sequenceSet(parsers, fs3, empties, trivia2) {
|
|
|
244
285
|
}
|
|
245
286
|
const first = fs3(p);
|
|
246
287
|
if (!empties(p) || i + 1 === parsers.length) return first;
|
|
247
|
-
return union(first, afterBoundary(i + 1));
|
|
288
|
+
return union((consuming ? p._meta.consumingFirstSet : void 0) ?? first, afterBoundary(i + 1));
|
|
248
289
|
};
|
|
249
290
|
return at(0);
|
|
250
291
|
}
|
|
251
292
|
function sequenceFirstSet(parsers) {
|
|
252
|
-
return sequenceSet(parsers, (p) => p._meta.firstSet, matchesEmpty);
|
|
293
|
+
return sequenceSet(parsers, (p) => p._meta.firstSet, matchesEmpty, void 0, false);
|
|
253
294
|
}
|
|
254
|
-
function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve3, activeTrivia) {
|
|
295
|
+
function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve3, activeTrivia, consuming = true) {
|
|
255
296
|
if (seen.has(p)) return any();
|
|
256
297
|
seen.add(p);
|
|
257
298
|
try {
|
|
258
|
-
return firstSetBody(p, seen, resolve3, activeTrivia);
|
|
299
|
+
return firstSetBody(p, seen, resolve3, activeTrivia, consuming);
|
|
259
300
|
} finally {
|
|
260
301
|
seen.delete(p);
|
|
261
302
|
}
|
|
262
303
|
}
|
|
263
|
-
function firstSetBody(p, seen, resolve3, activeTrivia) {
|
|
264
|
-
const fs3 = (c) => firstSetOf(c, seen, resolve3, activeTrivia);
|
|
304
|
+
function firstSetBody(p, seen, resolve3, activeTrivia, consuming) {
|
|
305
|
+
const fs3 = (c) => firstSetOf(c, seen, resolve3, activeTrivia, consuming);
|
|
265
306
|
const empties = (c) => matchesEmpty(c, /* @__PURE__ */ new Set(), resolve3);
|
|
266
307
|
const d = p._def;
|
|
267
308
|
switch (d.tag) {
|
|
@@ -273,13 +314,16 @@ function firstSetBody(p, seen, resolve3, activeTrivia) {
|
|
|
273
314
|
case "dispatch":
|
|
274
315
|
return fs3(d.selector);
|
|
275
316
|
case "lazy": {
|
|
276
|
-
|
|
277
|
-
if (
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
317
|
+
let target = winnerForRef(p, resolve3);
|
|
318
|
+
if (target === void 0) {
|
|
319
|
+
try {
|
|
320
|
+
target = d.thunk();
|
|
321
|
+
} catch {
|
|
322
|
+
return any();
|
|
323
|
+
}
|
|
282
324
|
}
|
|
325
|
+
const through = activeTrivia === null && resolve3 !== void 0;
|
|
326
|
+
return firstSetOf(target, seen, resolve3, through ? triviaThroughRef(p, target, null) : activeTrivia, consuming);
|
|
283
327
|
}
|
|
284
328
|
case "choice": {
|
|
285
329
|
let out = empty();
|
|
@@ -287,7 +331,7 @@ function firstSetBody(p, seen, resolve3, activeTrivia) {
|
|
|
287
331
|
return out;
|
|
288
332
|
}
|
|
289
333
|
case "sequence": {
|
|
290
|
-
return sequenceSet(d.parsers, fs3, empties, activeTrivia);
|
|
334
|
+
return sequenceSet(d.parsers, fs3, empties, activeTrivia, consuming);
|
|
291
335
|
}
|
|
292
336
|
case "peek": {
|
|
293
337
|
const inner = d.parser;
|
|
@@ -299,7 +343,6 @@ function firstSetBody(p, seen, resolve3, activeTrivia) {
|
|
|
299
343
|
case "transform":
|
|
300
344
|
case "label":
|
|
301
345
|
case "trivia":
|
|
302
|
-
case "token":
|
|
303
346
|
case "leaf":
|
|
304
347
|
case "node":
|
|
305
348
|
case "sepBy":
|
|
@@ -309,12 +352,16 @@ function firstSetBody(p, seen, resolve3, activeTrivia) {
|
|
|
309
352
|
// with a rule reference — resolve through it like any other wrapper.
|
|
310
353
|
case "attempt":
|
|
311
354
|
return fs3(d.parser);
|
|
355
|
+
// A token runs its body with trivia cleared (`token.ts`).
|
|
356
|
+
case "token":
|
|
357
|
+
return firstSetOf(d.parser, seen, resolve3, activeTrivia === void 0 ? void 0 : null, consuming);
|
|
312
358
|
case "grammar":
|
|
313
359
|
return firstSetOf(
|
|
314
360
|
d.parser,
|
|
315
361
|
seen,
|
|
316
362
|
resolve3,
|
|
317
|
-
d.clearTrivia ? null : d.triviaParser ?? activeTrivia
|
|
363
|
+
d.clearTrivia ? null : d.triviaParser ?? activeTrivia,
|
|
364
|
+
consuming
|
|
318
365
|
);
|
|
319
366
|
// A run starts with its first line's prefix; a nullable prefix starts with anything.
|
|
320
367
|
case "lines": {
|
|
@@ -341,42 +388,6 @@ function mergeRanges(ranges) {
|
|
|
341
388
|
return out;
|
|
342
389
|
}
|
|
343
390
|
|
|
344
|
-
// src/combinators/trivia-boundary.ts
|
|
345
|
-
var MAX_DEPTH = 12;
|
|
346
|
-
function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
|
|
347
|
-
if (depth === 0) return true;
|
|
348
|
-
const d = p._def;
|
|
349
|
-
switch (d.tag) {
|
|
350
|
-
// Multi-term forms: the gaps BETWEEN terms are the ambient-trivia positions.
|
|
351
|
-
case "sequence":
|
|
352
|
-
return d.parsers.length > 1;
|
|
353
|
-
case "many":
|
|
354
|
-
case "oneOrMore":
|
|
355
|
-
case "sepBy":
|
|
356
|
-
return true;
|
|
357
|
-
// Transparent wrappers — they add no position, so ask what they wrap.
|
|
358
|
-
case "node":
|
|
359
|
-
case "transform":
|
|
360
|
-
case "leaf":
|
|
361
|
-
case "label":
|
|
362
|
-
case "field":
|
|
363
|
-
case "token":
|
|
364
|
-
case "attempt":
|
|
365
|
-
case "optional":
|
|
366
|
-
case "expect":
|
|
367
|
-
case "withCtx":
|
|
368
|
-
case "recover":
|
|
369
|
-
case "trivia":
|
|
370
|
-
return hasOwnTriviaBoundary(d.parser, depth - 1);
|
|
371
|
-
// An alternation adds no position either, but ONE arm that has one is enough
|
|
372
|
-
// to make the scope meaningful for this rule.
|
|
373
|
-
case "choice":
|
|
374
|
-
return d.parsers.some((a) => hasOwnTriviaBoundary(a, depth - 1));
|
|
375
|
-
default:
|
|
376
|
-
return false;
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
|
|
380
391
|
// src/combinators/scalar.ts
|
|
381
392
|
var SCALAR_TAG = /^(?:literal|regex|keywords|sequence|choice|many|oneOrMore|optional|transform|trivia|grammar|sepBy|lazy)$/;
|
|
382
393
|
function scalarOf(combinator) {
|
|
@@ -2233,10 +2244,12 @@ function parseRegex(src, unicode = false, sets = false) {
|
|
|
2233
2244
|
const parseGroup = () => {
|
|
2234
2245
|
i++;
|
|
2235
2246
|
let lookaround = false;
|
|
2247
|
+
let lookahead = false;
|
|
2236
2248
|
if (src[i] === "?") {
|
|
2237
2249
|
const c1 = src[i + 1];
|
|
2238
2250
|
if (c1 === ":") i += 2;
|
|
2239
2251
|
else if (c1 === "=" || c1 === "!") {
|
|
2252
|
+
lookahead = c1 === "=";
|
|
2240
2253
|
i += 2;
|
|
2241
2254
|
lookaround = true;
|
|
2242
2255
|
} else if (c1 === "<") {
|
|
@@ -2254,7 +2267,8 @@ function parseRegex(src, unicode = false, sets = false) {
|
|
|
2254
2267
|
const inner = parseAlt();
|
|
2255
2268
|
if (src[i] !== ")") throw BAIL;
|
|
2256
2269
|
i++;
|
|
2257
|
-
|
|
2270
|
+
if (lookaround) return lookahead ? { t: "empty", look: inner } : EMPTY2;
|
|
2271
|
+
return inner;
|
|
2258
2272
|
};
|
|
2259
2273
|
const parseClass = () => {
|
|
2260
2274
|
let k = i + 1;
|
|
@@ -2447,6 +2461,13 @@ function regexCanMatchEmpty(source) {
|
|
|
2447
2461
|
return true;
|
|
2448
2462
|
}
|
|
2449
2463
|
}
|
|
2464
|
+
function consumingFirstSetFromRegex(source, flags = "") {
|
|
2465
|
+
try {
|
|
2466
|
+
return firstSet(parseRegex(source, flags.includes("u") || flags.includes("v"), flags.includes("v")));
|
|
2467
|
+
} catch {
|
|
2468
|
+
return any();
|
|
2469
|
+
}
|
|
2470
|
+
}
|
|
2450
2471
|
function firstSetFromRegex(source, flags = "") {
|
|
2451
2472
|
let ast2;
|
|
2452
2473
|
try {
|
|
@@ -2457,6 +2478,20 @@ function firstSetFromRegex(source, flags = "") {
|
|
|
2457
2478
|
if (nullable(ast2)) return { firstSet: any(), canMatchNewline: canConsumeNewline(ast2) };
|
|
2458
2479
|
return { firstSet: firstSet(ast2), canMatchNewline: canConsumeNewline(ast2) };
|
|
2459
2480
|
}
|
|
2481
|
+
function regexFirstTwo(source, flags = "") {
|
|
2482
|
+
let ast2;
|
|
2483
|
+
try {
|
|
2484
|
+
ast2 = parseRegex(source, flags.includes("u") || flags.includes("v"), flags.includes("v"));
|
|
2485
|
+
} catch {
|
|
2486
|
+
return void 0;
|
|
2487
|
+
}
|
|
2488
|
+
const parts = ast2.t === "seq" ? ast2.parts : [ast2];
|
|
2489
|
+
const a = parts[0];
|
|
2490
|
+
const b = parts[1];
|
|
2491
|
+
if (a === void 0 || a.t !== "char" || a.set.kind !== "ranges" || b === void 0) return void 0;
|
|
2492
|
+
const second = b.t === "char" ? b.set : b.t === "empty" && b.look !== void 0 && !nullable(b.look) ? firstSet(b.look) : void 0;
|
|
2493
|
+
return second !== void 0 && second.kind === "ranges" ? { first: a.set, second } : void 0;
|
|
2494
|
+
}
|
|
2460
2495
|
|
|
2461
2496
|
// src/combinators/regex.ts
|
|
2462
2497
|
import { PlainLeaf as PlainLeaf3, PlainSpan as PlainSpan3 } from "../cst/plain.js";
|
|
@@ -2537,9 +2572,14 @@ function regex(pattern, flags = "") {
|
|
|
2537
2572
|
const anchored = new RegExp(source, "y" + resolvedFlags.replace(/[gy]/g, ""));
|
|
2538
2573
|
const scan = shortScanner(source, resolvedFlags);
|
|
2539
2574
|
const raw = firstSetFromRegex(source, resolvedFlags);
|
|
2540
|
-
const
|
|
2575
|
+
const forFlags = (fs3) => !resolvedFlags.includes("i") ? fs3 : resolvedFlags.includes("u") || resolvedFlags.includes("v") ? any() : asciiCaseFold(fs3);
|
|
2576
|
+
const firstSet2 = forFlags(raw.firstSet);
|
|
2541
2577
|
const canMatchNewline = raw.canMatchNewline;
|
|
2542
2578
|
const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
|
|
2579
|
+
if (firstSet2.kind === "any" && regexCanMatchEmpty(source)) {
|
|
2580
|
+
const consuming = forFlags(consumingFirstSetFromRegex(source, resolvedFlags));
|
|
2581
|
+
if (consuming.kind !== "any") meta.consumingFirstSet = consuming;
|
|
2582
|
+
}
|
|
2543
2583
|
const def = { tag: "regex", source, flags: resolvedFlags };
|
|
2544
2584
|
const expected = directTerminalFailureExpected(def);
|
|
2545
2585
|
const parseScalar = (input, pos, ctx) => {
|
|
@@ -2922,10 +2962,6 @@ function scanTriviaCompact(input, cur, ctx) {
|
|
|
2922
2962
|
const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
|
|
2923
2963
|
return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
|
|
2924
2964
|
}
|
|
2925
|
-
function scanTrivia(input, cur, ctx) {
|
|
2926
|
-
const scan = scanTriviaCompact(input, cur, ctx);
|
|
2927
|
-
return typeof scan === "number" ? { end: scan, commit: NOOP_COMMIT } : scan;
|
|
2928
|
-
}
|
|
2929
2965
|
function skipTriviaScanned(s, input, cur, ctx) {
|
|
2930
2966
|
const end = s(input, cur);
|
|
2931
2967
|
if (end !== cur) {
|
|
@@ -3552,7 +3588,7 @@ function sequence(...parsers) {
|
|
|
3552
3588
|
if (tolerant) {
|
|
3553
3589
|
followSentinels ??= parsers.map((_, i) => firstSetSentinel(
|
|
3554
3590
|
parsers.slice(i + 1).reduce(
|
|
3555
|
-
(set, parser2) => union(set, firstSetOf(parser2)),
|
|
3591
|
+
(set, parser2) => union(set, firstSetOf(parser2, /* @__PURE__ */ new Set(), void 0, void 0, false)),
|
|
3556
3592
|
{ kind: "empty" }
|
|
3557
3593
|
)
|
|
3558
3594
|
));
|
|
@@ -4169,8 +4205,9 @@ function when(key, parser2, opts = {}) {
|
|
|
4169
4205
|
}
|
|
4170
4206
|
return { kind: "when", keys, parser: parser2, caseInsensitive: opts.caseInsensitive ?? false, usesRouted };
|
|
4171
4207
|
}
|
|
4172
|
-
function otherwise(parser2) {
|
|
4173
|
-
|
|
4208
|
+
function otherwise(parser2, opts = {}) {
|
|
4209
|
+
const usesRouted = parserUsesRouted(parser2);
|
|
4210
|
+
return opts.commit === false ? { kind: "otherwise", parser: parser2, usesRouted, commit: false } : { kind: "otherwise", parser: parser2, usesRouted };
|
|
4174
4211
|
}
|
|
4175
4212
|
function routed(fallback2) {
|
|
4176
4213
|
return {
|
|
@@ -4202,6 +4239,7 @@ function dispatch(selector, ...arms) {
|
|
|
4202
4239
|
}
|
|
4203
4240
|
let fallback2;
|
|
4204
4241
|
let fallbackUsesRouted = false;
|
|
4242
|
+
let fallbackCommits = true;
|
|
4205
4243
|
const matchers = [];
|
|
4206
4244
|
const cases = [];
|
|
4207
4245
|
const seen = [];
|
|
@@ -4212,6 +4250,7 @@ function dispatch(selector, ...arms) {
|
|
|
4212
4250
|
if (i !== arms.length - 1) throw new Error("parseman: otherwise() must be the last dispatch() arm");
|
|
4213
4251
|
fallback2 = arm.parser;
|
|
4214
4252
|
fallbackUsesRouted = arm.usesRouted === true;
|
|
4253
|
+
fallbackCommits = arm.commit !== false;
|
|
4215
4254
|
continue;
|
|
4216
4255
|
}
|
|
4217
4256
|
if (arm.kind === "whenMatcher") {
|
|
@@ -4262,7 +4301,11 @@ function dispatch(selector, ...arms) {
|
|
|
4262
4301
|
selector,
|
|
4263
4302
|
cases,
|
|
4264
4303
|
...matchers.length === 0 ? {} : { matchers },
|
|
4265
|
-
...fallback2 === void 0 ? {} : {
|
|
4304
|
+
...fallback2 === void 0 ? {} : {
|
|
4305
|
+
otherwise: fallback2,
|
|
4306
|
+
...fallbackUsesRouted ? { otherwiseUsesRouted: true } : {},
|
|
4307
|
+
...fallbackCommits ? {} : { otherwiseCommit: false }
|
|
4308
|
+
}
|
|
4266
4309
|
},
|
|
4267
4310
|
parse(input, pos, ctx) {
|
|
4268
4311
|
if (parserUsesRouted(selector)) {
|
|
@@ -4271,7 +4314,8 @@ function dispatch(selector, ...arms) {
|
|
|
4271
4314
|
const selectorMark = saveTriviaMark(ctx);
|
|
4272
4315
|
const selected = selector.parse(input, pos, ctx);
|
|
4273
4316
|
if (!selected.ok) return selected;
|
|
4274
|
-
const
|
|
4317
|
+
const chosen = byKey.get(selected.value) ?? (byFoldedKey.size === 0 ? void 0 : byFoldedKey.get(asciiFoldKey(selected.value))) ?? matchers.find((matcher) => matchesDispatchMatcher(selected.value, matcher));
|
|
4318
|
+
const branch = chosen ?? (fallback2 === void 0 ? void 0 : { keys: [], parser: fallback2, caseInsensitive: false, usesRouted: fallbackUsesRouted });
|
|
4275
4319
|
if (branch === void 0) {
|
|
4276
4320
|
const expected = cases.flatMap((entry) => entry.keys.map((key) => JSON.stringify(key)));
|
|
4277
4321
|
return { ok: false, expected, span: { start: selected.span.end, end: selected.span.end } };
|
|
@@ -4292,7 +4336,7 @@ function dispatch(selector, ...arms) {
|
|
|
4292
4336
|
}
|
|
4293
4337
|
if (!result.ok) {
|
|
4294
4338
|
rollbackTrivia(ctx, mark);
|
|
4295
|
-
return { ...result, committed: true };
|
|
4339
|
+
return chosen === void 0 && !fallbackCommits ? result : { ...result, committed: true };
|
|
4296
4340
|
}
|
|
4297
4341
|
return {
|
|
4298
4342
|
ok: true,
|
|
@@ -4321,7 +4365,7 @@ function attempt(parser2, options) {
|
|
|
4321
4365
|
return {
|
|
4322
4366
|
_tag: "attempt",
|
|
4323
4367
|
_meta: parser2._meta,
|
|
4324
|
-
_def:
|
|
4368
|
+
_def: { tag: "attempt", parser: parser2, ...contain ? { contain: true } : {}, ...guardable ? { guarded: true } : {} },
|
|
4325
4369
|
parse(input, pos, ctx) {
|
|
4326
4370
|
if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(parser2, input, pos)) {
|
|
4327
4371
|
if (failExpected === void 0) {
|
|
@@ -4411,9 +4455,9 @@ function many(combinator, opts = {}) {
|
|
|
4411
4455
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
4412
4456
|
isTrivia: false
|
|
4413
4457
|
};
|
|
4414
|
-
const def = { tag: "many", parser: combinator, min: 0, ...max === Infinity ? {} : { max } };
|
|
4415
|
-
let expected;
|
|
4416
4458
|
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
4459
|
+
const def = { tag: "many", parser: combinator, min: 0, ...max === Infinity ? {} : { max }, ...guardable ? { guarded: true } : {} };
|
|
4460
|
+
let expected;
|
|
4417
4461
|
const scalarChild = scalarOf(combinator);
|
|
4418
4462
|
const parseScalar = (input, pos, ctx) => repeatScalarTail(combinator, scalarChild, input, pos, ctx, guardable, def.valueUnused ? void 0 : [], max);
|
|
4419
4463
|
return {
|
|
@@ -4460,9 +4504,9 @@ function atLeast(combinator, min, max) {
|
|
|
4460
4504
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
4461
4505
|
isTrivia: false
|
|
4462
4506
|
};
|
|
4463
|
-
const def = { tag: "oneOrMore", parser: combinator, min, ...max === Infinity ? {} : { max } };
|
|
4464
|
-
let expected;
|
|
4465
4507
|
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
4508
|
+
const def = { tag: "oneOrMore", parser: combinator, min, ...max === Infinity ? {} : { max }, ...guardable ? { guarded: true } : {} };
|
|
4509
|
+
let expected;
|
|
4466
4510
|
const scalarChild = scalarOf(combinator);
|
|
4467
4511
|
const parseScalar = (input, pos, ctx) => {
|
|
4468
4512
|
let cur = scalarChild(input, pos, ctx);
|
|
@@ -5181,7 +5225,7 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
5181
5225
|
if (project !== void 0 && build !== void 0) {
|
|
5182
5226
|
throw new Error("node() options cannot combine project with a build callback");
|
|
5183
5227
|
}
|
|
5184
|
-
const baseDef = { tag: "node", parser: combinator, ...type === void 0 ? {} : { type }, ...build === void 0 ? {} : { build } };
|
|
5228
|
+
const baseDef = { tag: "node", parser: combinator, ...type === void 0 ? {} : { type }, ...build === void 0 ? {} : { build }, ...combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator) ? { guarded: true } : {} };
|
|
5185
5229
|
const meta = {
|
|
5186
5230
|
firstSet: combinator._meta.firstSet,
|
|
5187
5231
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
@@ -5740,14 +5784,15 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
5740
5784
|
return end < 0 ? next(input, pos) : end;
|
|
5741
5785
|
};
|
|
5742
5786
|
}
|
|
5743
|
-
let tail = (
|
|
5787
|
+
let tail = (input, pos, ctx, _lead, acc, _best, entered) => {
|
|
5788
|
+
if (!entered && ctx._probe !== void 0) for (const arm of arms) arm.run(input, pos, ctx);
|
|
5744
5789
|
ctx._fe = pos;
|
|
5745
5790
|
ctx._fx = acc ?? choiceExpected;
|
|
5746
5791
|
return -1;
|
|
5747
5792
|
};
|
|
5748
5793
|
for (let i = arms.length - 1; i >= 0; i--) {
|
|
5749
5794
|
const armRun = arms[i].run, cls = classes[i], staticExpected = armExpected[i], next = tail;
|
|
5750
|
-
tail = (input, pos, ctx, lead2, acc, best) => {
|
|
5795
|
+
tail = (input, pos, ctx, lead2, acc, best, entered) => {
|
|
5751
5796
|
if (cls !== void 0 && !classHas(cls, lead2)) {
|
|
5752
5797
|
return next(
|
|
5753
5798
|
input,
|
|
@@ -5755,7 +5800,8 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
5755
5800
|
ctx,
|
|
5756
5801
|
lead2,
|
|
5757
5802
|
best === pos ? appendExpected(acc, staticExpected) : acc,
|
|
5758
|
-
best
|
|
5803
|
+
best,
|
|
5804
|
+
entered
|
|
5759
5805
|
);
|
|
5760
5806
|
}
|
|
5761
5807
|
ctx._fc = false;
|
|
@@ -5771,7 +5817,7 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
5771
5817
|
if (nextAcc !== void 0) ctx._fx = nextAcc;
|
|
5772
5818
|
return -1;
|
|
5773
5819
|
}
|
|
5774
|
-
return next(input, pos, ctx, lead2, nextAcc, best);
|
|
5820
|
+
return next(input, pos, ctx, lead2, nextAcc, best, true);
|
|
5775
5821
|
};
|
|
5776
5822
|
}
|
|
5777
5823
|
return {
|
|
@@ -5782,7 +5828,8 @@ function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
|
5782
5828
|
ctx,
|
|
5783
5829
|
pos < input.length ? input.codePointAt(pos) : -1,
|
|
5784
5830
|
void 0,
|
|
5785
|
-
pos
|
|
5831
|
+
pos,
|
|
5832
|
+
false
|
|
5786
5833
|
)
|
|
5787
5834
|
};
|
|
5788
5835
|
}
|
|
@@ -5820,6 +5867,7 @@ function exclusiveChoiceNode(arms, classes, choiceFx) {
|
|
|
5820
5867
|
return -1;
|
|
5821
5868
|
}
|
|
5822
5869
|
}
|
|
5870
|
+
if (arm < 0 && ctx._probe !== void 0) for (const a of arms) a.run(input, pos, ctx);
|
|
5823
5871
|
ctx._fe = pos;
|
|
5824
5872
|
ctx._fx = choiceFx;
|
|
5825
5873
|
return -1;
|
|
@@ -6044,6 +6092,7 @@ function buildLexProgramRunner(spec, matchers, classes, expected) {
|
|
|
6044
6092
|
if (!classHas(cls, lead2)) {
|
|
6045
6093
|
ctx._fe = pos;
|
|
6046
6094
|
ctx._fx = choiceFx.slice();
|
|
6095
|
+
if (ctx._probe !== void 0) failAt(ctx, [...x0, ...x1, ...x2, ...x3], pos);
|
|
6047
6096
|
return -1;
|
|
6048
6097
|
}
|
|
6049
6098
|
let acc;
|
|
@@ -6155,7 +6204,7 @@ function validateDispatchSpec(spec, arity, fallbackRouted) {
|
|
|
6155
6204
|
for (const arm of arms) if (!Number.isInteger(arm) || arm < 0 || arm >= arity) return true;
|
|
6156
6205
|
return false;
|
|
6157
6206
|
};
|
|
6158
|
-
if (spec === void 0 || !Number.isInteger(arity) || arity < 0 || fallbackRouted
|
|
6207
|
+
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]]))) {
|
|
6159
6208
|
throw new TypeError("table: malformed dispatch");
|
|
6160
6209
|
}
|
|
6161
6210
|
}
|
|
@@ -6851,6 +6900,7 @@ function classifyRuleMap(ruleMap) {
|
|
|
6851
6900
|
}
|
|
6852
6901
|
|
|
6853
6902
|
// src/table/factor-choice.ts
|
|
6903
|
+
var factoredChoices = /* @__PURE__ */ new WeakSet();
|
|
6854
6904
|
var DERIVED = /* @__PURE__ */ new Set(["_tag", "_meta", "_def", "_parseScalar", "_stickyRegex", "parse"]);
|
|
6855
6905
|
function isCombinator(v) {
|
|
6856
6906
|
return typeof v === "object" && v !== null && "_def" in v && "_meta" in v;
|
|
@@ -6942,6 +6992,7 @@ function factorSharedEnds(d) {
|
|
|
6942
6992
|
for (let i = at + 1; i < n; i++) if (!never(first.terms[i])) return void 0;
|
|
6943
6993
|
if (arms.some((a) => mayCommitFailure(a))) return void 0;
|
|
6944
6994
|
const middle = choice(...shapes.map((s) => s.terms[at]));
|
|
6995
|
+
factoredChoices.add(middle);
|
|
6945
6996
|
if (middle._def.tag === "choice" && middle._def.autoNot.some((a) => a !== null)) return void 0;
|
|
6946
6997
|
const st = middle._def.tag === "choice" ? middle._def.strategy : void 0;
|
|
6947
6998
|
if (st === void 0 || st.tag !== "firstMatch" && st.tag !== "sharedPrefix" && !(st.tag === "literalsLongestFirst" && st.sortedIndices.every((x, i) => x === i))) return void 0;
|
|
@@ -6954,6 +7005,37 @@ function factorSharedEnds(d) {
|
|
|
6954
7005
|
for (let j = first.wrappers.length - 1; j >= 0 && out !== void 0; j--) out = rewrap(first.wrappers[j], out);
|
|
6955
7006
|
return out === void 0 ? void 0 : attempt(out);
|
|
6956
7007
|
}
|
|
7008
|
+
function factorPrefixArms(d) {
|
|
7009
|
+
const arms = d.parsers;
|
|
7010
|
+
if (arms.length < 2) return void 0;
|
|
7011
|
+
if (d.strategy.tag !== "firstMatch" && d.strategy.tag !== "sharedPrefix") return void 0;
|
|
7012
|
+
if (d.gates.some((g) => g !== null) || d.autoNot.some((a) => a !== null)) return void 0;
|
|
7013
|
+
const out = [...arms];
|
|
7014
|
+
let changed = false;
|
|
7015
|
+
for (let i = 0; i + 1 < arms.length; i++) {
|
|
7016
|
+
const arm = arms[i];
|
|
7017
|
+
if (arm._def.tag !== "sequence" || arm._def.valueUnused !== true) continue;
|
|
7018
|
+
const terms = arm._def.parsers;
|
|
7019
|
+
const next = arms[i + 1];
|
|
7020
|
+
const prefix = next._def.tag === "sequence" && next._def.valueUnused === true ? next._def.parsers : [next];
|
|
7021
|
+
if (prefix.length >= terms.length) continue;
|
|
7022
|
+
if (!prefix.every((t, j) => sameComb(t, terms[j], 0))) continue;
|
|
7023
|
+
const rest = terms.slice(prefix.length);
|
|
7024
|
+
if (rest.every(never)) continue;
|
|
7025
|
+
const tail = rest.length === 1 ? rest[0] : sequence(...rest);
|
|
7026
|
+
if (tail !== rest[0]) tail._def.valueUnused = true;
|
|
7027
|
+
const parts = [...terms.slice(0, prefix.length), optional(tail)];
|
|
7028
|
+
const seq = sequence(...parts);
|
|
7029
|
+
seq._def.valueUnused = true;
|
|
7030
|
+
out[i] = seq;
|
|
7031
|
+
changed = true;
|
|
7032
|
+
}
|
|
7033
|
+
if (!changed) return void 0;
|
|
7034
|
+
const rebuilt = choice(...out);
|
|
7035
|
+
factoredChoices.add(rebuilt);
|
|
7036
|
+
const st = rebuilt._def.tag === "choice" ? rebuilt._def.strategy : void 0;
|
|
7037
|
+
return st !== void 0 && (st.tag === "firstMatch" || st.tag === "sharedPrefix") ? rebuilt : void 0;
|
|
7038
|
+
}
|
|
6957
7039
|
|
|
6958
7040
|
// src/table/ops.ts
|
|
6959
7041
|
var OP_LIT = 1;
|
|
@@ -6999,6 +7081,9 @@ var OP_LEX_BODY = 42;
|
|
|
6999
7081
|
var OP_LEX_PROGRAM = 43;
|
|
7000
7082
|
var OP_SOURCE_LEAF = 44;
|
|
7001
7083
|
var OP_RGATE = 45;
|
|
7084
|
+
var OP_GAPGATE = 46;
|
|
7085
|
+
var OP_RGATE2 = 47;
|
|
7086
|
+
var OP_STRICT = 48;
|
|
7002
7087
|
var OP_DISPATCH = 25;
|
|
7003
7088
|
var OP_ROUTED = 26;
|
|
7004
7089
|
var OP_NAMES = {
|
|
@@ -7046,7 +7131,10 @@ var OP_NAMES = {
|
|
|
7046
7131
|
[OP_COV]: "COV",
|
|
7047
7132
|
[OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
|
|
7048
7133
|
[OP_LEX_BODY]: "LEX_BODY",
|
|
7049
|
-
[OP_LEX_PROGRAM]: "LEX_PROGRAM"
|
|
7134
|
+
[OP_LEX_PROGRAM]: "LEX_PROGRAM",
|
|
7135
|
+
[OP_GAPGATE]: "GAPGATE",
|
|
7136
|
+
[OP_RGATE2]: "RGATE2",
|
|
7137
|
+
[OP_STRICT]: "STRICT"
|
|
7050
7138
|
};
|
|
7051
7139
|
|
|
7052
7140
|
// src/compiler/direct-projection.ts
|
|
@@ -7337,6 +7425,7 @@ function directFixedLexNode(parser2, resolve3, active, pureOnly = false, cleared
|
|
|
7337
7425
|
arms,
|
|
7338
7426
|
parsers: def.parsers,
|
|
7339
7427
|
cleared,
|
|
7428
|
+
disjoint: def.disjoint,
|
|
7340
7429
|
armExpected: def.parsers.map(deriveExpected),
|
|
7341
7430
|
expected: def.parsers.flatMap(deriveExpected)
|
|
7342
7431
|
};
|
|
@@ -7446,6 +7535,29 @@ var UnsupportedConstruct = class extends Error {
|
|
|
7446
7535
|
this.tag = tag;
|
|
7447
7536
|
}
|
|
7448
7537
|
};
|
|
7538
|
+
function firstTwo(p) {
|
|
7539
|
+
const d = p._def;
|
|
7540
|
+
if (d.tag === "label" || d.tag === "grammar") return firstTwo(d.parser);
|
|
7541
|
+
let two;
|
|
7542
|
+
if (d.tag === "literal" && d.value.length >= 2 && d.caseInsensitive !== true) {
|
|
7543
|
+
const second = d.value.codePointAt(1);
|
|
7544
|
+
two = { first: { kind: "ranges", ranges: [{ lo: d.value.charCodeAt(0), hi: d.value.charCodeAt(0) }] }, second: { kind: "ranges", ranges: [{ lo: second, hi: second }] } };
|
|
7545
|
+
} else if (d.tag === "regex" && !d.flags.includes("i")) {
|
|
7546
|
+
const units = regexFirstTwo(d.source, d.flags);
|
|
7547
|
+
if (units !== void 0) two = units;
|
|
7548
|
+
}
|
|
7549
|
+
if (two === void 0 || two.first.kind !== "ranges") return void 0;
|
|
7550
|
+
return two.first.ranges.every((r) => r.hi < 55296 || r.lo > 57343 && r.hi <= 65535) ? two : void 0;
|
|
7551
|
+
}
|
|
7552
|
+
var GAP_CHARS = /* @__PURE__ */ new Set([9, 10, 12, 13, 32, 47]);
|
|
7553
|
+
function isGap(p) {
|
|
7554
|
+
if (matchesEmpty(p)) return true;
|
|
7555
|
+
const fs3 = p._meta.firstSet;
|
|
7556
|
+
return fs3.kind === "ranges" && fs3.ranges.every((r) => {
|
|
7557
|
+
for (let c = r.lo; c <= r.hi; c++) if (!GAP_CHARS.has(c)) return false;
|
|
7558
|
+
return true;
|
|
7559
|
+
});
|
|
7560
|
+
}
|
|
7449
7561
|
var Encoder = class {
|
|
7450
7562
|
code = [];
|
|
7451
7563
|
k = [];
|
|
@@ -7493,8 +7605,33 @@ var Encoder = class {
|
|
|
7493
7605
|
*/
|
|
7494
7606
|
commitFailureMemo = /* @__PURE__ */ new Map();
|
|
7495
7607
|
labels = void 0;
|
|
7608
|
+
/** The choice being encoded as written, for `OP_STRICT`'s tolerant child. */
|
|
7609
|
+
unfactoredChoice = void 0;
|
|
7496
7610
|
/** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
|
|
7497
7611
|
activeTrivia = void 0;
|
|
7612
|
+
/**
|
|
7613
|
+
* Is the trivia live at this row known? It is not in the body of an entry
|
|
7614
|
+
* that installs none of its own: that body runs under whatever trivia its
|
|
7615
|
+
* caller has (a compiled rule inside another grammar, `run({ trivia })`).
|
|
7616
|
+
* Every scope (`parser({ trivia })`, `noTrivia`, `token()`, a rule's install)
|
|
7617
|
+
* makes it known again.
|
|
7618
|
+
*/
|
|
7619
|
+
triviaKnown = true;
|
|
7620
|
+
/**
|
|
7621
|
+
* The trivia a gate's first set is derived under: the live table, `null` for a
|
|
7622
|
+
* scope known to have none, or `undefined` where it is not known.
|
|
7623
|
+
*/
|
|
7624
|
+
gateTrivia() {
|
|
7625
|
+
return this.activeTrivia ?? (this.triviaKnown ? null : void 0);
|
|
7626
|
+
}
|
|
7627
|
+
/**
|
|
7628
|
+
* Whether a gate may read a nullable pad through its non-empty matches
|
|
7629
|
+
* (`firstSetOf`'s `consuming`): only where the trivia that may follow the pad
|
|
7630
|
+
* is known. Elsewhere a gate reads first sets as 0.58.0 did.
|
|
7631
|
+
*/
|
|
7632
|
+
gateConsuming() {
|
|
7633
|
+
return this.activeTrivia !== void 0 || this.triviaKnown;
|
|
7634
|
+
}
|
|
7498
7635
|
classified = false;
|
|
7499
7636
|
scans = [];
|
|
7500
7637
|
/** Ambient `scanSkip` sets, pooled by the ARRAY's identity (stable per grammar). */
|
|
@@ -7621,10 +7758,12 @@ var Encoder = class {
|
|
|
7621
7758
|
const final = classifyFinalChoice(
|
|
7622
7759
|
node2.parsers,
|
|
7623
7760
|
this.refResolver(),
|
|
7624
|
-
node2.cleared ?
|
|
7761
|
+
node2.cleared ? null : this.gateTrivia(),
|
|
7762
|
+
false,
|
|
7763
|
+
node2.disjoint
|
|
7625
7764
|
);
|
|
7626
7765
|
const classes = final.firstSets.map((first, i) => final.nullable[i] ? -1 : this.charClass(first));
|
|
7627
|
-
const exclusive = final.exclusive && classes.every((cls) => cls >= 0);
|
|
7766
|
+
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;
|
|
7628
7767
|
words.push(LEX_NODE_CHOICE, node2.arms.length, exclusive ? 1 : 0, this.expected(node2.expected));
|
|
7629
7768
|
for (let i = 0; i < node2.arms.length; i++) {
|
|
7630
7769
|
words.push(classes[i], this.expected(node2.armExpected[i]));
|
|
@@ -7779,16 +7918,117 @@ var Encoder = class {
|
|
|
7779
7918
|
kIndex = /* @__PURE__ */ new Map();
|
|
7780
7919
|
ccIndex = /* @__PURE__ */ new Map();
|
|
7781
7920
|
fxIndex = /* @__PURE__ */ new Map();
|
|
7782
|
-
/** Memoized by combinator identity: a shared sub-combinator is ONE row. */
|
|
7783
|
-
memo = /* @__PURE__ */ new Map();
|
|
7784
7921
|
/**
|
|
7785
|
-
*
|
|
7786
|
-
*
|
|
7787
|
-
*
|
|
7788
|
-
*
|
|
7922
|
+
* Memoized by combinator identity AND the trivia scope it is encoded under
|
|
7923
|
+
* (`scopeKey`): a shared sub-combinator is ONE row per scope it runs in.
|
|
7924
|
+
*
|
|
7925
|
+
* A construct's rows depend on that scope. A first set derived through a
|
|
7926
|
+
* nullable term takes in the trivia that may follow it, a gap gate holds only
|
|
7927
|
+
* where no trivia runs, a routed gate reads what may follow its token, and a
|
|
7928
|
+
* cross-rule reference installs its rule's trivia only from a cleared region
|
|
7929
|
+
* (`scopedRef`). One memo slot per combinator froze the FIRST scope it was
|
|
7930
|
+
* reached under onto every later one: a rule body encoded as an entry with no
|
|
7931
|
+
* trivia, then run under a caller's comment trivia, gated its repeats as if no
|
|
7932
|
+
* comment could come between their terms.
|
|
7789
7933
|
*/
|
|
7790
|
-
|
|
7934
|
+
memo = /* @__PURE__ */ new Map();
|
|
7791
7935
|
pending = /* @__PURE__ */ new Map();
|
|
7936
|
+
triviaSignatures = /* @__PURE__ */ new Map();
|
|
7937
|
+
/**
|
|
7938
|
+
* What of the live trivia an encoding can depend on: none, or its first set.
|
|
7939
|
+
* Every derivation reads trivia only through `firstSetOf(trivia)` or whether it
|
|
7940
|
+
* is live, so two scopes whose trivia opens on the same characters encode the
|
|
7941
|
+
* same rows and share them. A construct that reads no scope (`readsScope`)
|
|
7942
|
+
* has one encoding.
|
|
7943
|
+
*/
|
|
7944
|
+
scopeKey(p) {
|
|
7945
|
+
const t = this.activeTrivia;
|
|
7946
|
+
if (!this.readsScope(p)) return "";
|
|
7947
|
+
if (t === void 0) return this.triviaKnown ? "" : "?";
|
|
7948
|
+
let sig = this.triviaSignatures.get(t);
|
|
7949
|
+
if (sig === void 0) {
|
|
7950
|
+
sig = `t${JSON.stringify(firstSetOf(t, /* @__PURE__ */ new Set(), this.refResolver()))}`;
|
|
7951
|
+
this.triviaSignatures.set(t, sig);
|
|
7952
|
+
}
|
|
7953
|
+
return sig;
|
|
7954
|
+
}
|
|
7955
|
+
readsScopeMemo = /* @__PURE__ */ new Map();
|
|
7956
|
+
/**
|
|
7957
|
+
* Can `p`'s rows depend on the trivia scope it is encoded under? No for a
|
|
7958
|
+
* terminal, a scope of its own (`parser({ trivia })`, `noTrivia`, `token()`),
|
|
7959
|
+
* and a wrapper over a construct that reads none; yes wherever a first set, a gate or
|
|
7960
|
+
* a reference's install is derived with the scope: a sequence with a nullable
|
|
7961
|
+
* term before another (the trivia between them), a routed arm (the trivia after
|
|
7962
|
+
* its token), a reference that installs its rule's trivia from a cleared
|
|
7963
|
+
* region, and anything not modelled here — a cycle included.
|
|
7964
|
+
*/
|
|
7965
|
+
readsScope(p) {
|
|
7966
|
+
const hit = this.readsScopeMemo.get(p);
|
|
7967
|
+
if (hit !== void 0) return hit;
|
|
7968
|
+
this.readsScopeMemo.set(p, true);
|
|
7969
|
+
const d = p._def;
|
|
7970
|
+
const rr = this.refResolver();
|
|
7971
|
+
let out;
|
|
7972
|
+
switch (d.tag) {
|
|
7973
|
+
case "literal":
|
|
7974
|
+
case "regex":
|
|
7975
|
+
case "keywords":
|
|
7976
|
+
case "token":
|
|
7977
|
+
out = false;
|
|
7978
|
+
break;
|
|
7979
|
+
// `routed()` encodes its fallback under the scope that reaches it.
|
|
7980
|
+
case "routed":
|
|
7981
|
+
out = d.fallback !== void 0 && this.readsScope(d.fallback);
|
|
7982
|
+
break;
|
|
7983
|
+
case "grammar":
|
|
7984
|
+
out = d.clearTrivia !== true && d.triviaParser === void 0 && this.readsScope(d.parser);
|
|
7985
|
+
break;
|
|
7986
|
+
case "node":
|
|
7987
|
+
case "label":
|
|
7988
|
+
case "leaf":
|
|
7989
|
+
case "transform":
|
|
7990
|
+
case "attempt":
|
|
7991
|
+
case "expect":
|
|
7992
|
+
case "not":
|
|
7993
|
+
case "peek":
|
|
7994
|
+
case "optional":
|
|
7995
|
+
case "many":
|
|
7996
|
+
case "oneOrMore":
|
|
7997
|
+
case "field":
|
|
7998
|
+
out = this.readsScope(d.parser);
|
|
7999
|
+
break;
|
|
8000
|
+
case "sepBy":
|
|
8001
|
+
out = this.readsScope(d.parser) || this.readsScope(d.separator);
|
|
8002
|
+
break;
|
|
8003
|
+
case "choice":
|
|
8004
|
+
out = d.parsers.some((a) => this.readsScope(a));
|
|
8005
|
+
break;
|
|
8006
|
+
case "dispatch":
|
|
8007
|
+
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);
|
|
8008
|
+
break;
|
|
8009
|
+
case "sequence": {
|
|
8010
|
+
const ps = d.parsers;
|
|
8011
|
+
out = ps.some((t) => this.readsScope(t)) || ps[0] !== void 0 && (ps[0]._def.tag === "routed" || ps[0]._def.tag === "regex" && isGap(ps[0])) || ps.some((t, i) => i + 1 < ps.length && matchesEmpty(t, /* @__PURE__ */ new Set(), rr));
|
|
8012
|
+
break;
|
|
8013
|
+
}
|
|
8014
|
+
case "lazy": {
|
|
8015
|
+
let target = winnerForRef(p, rr);
|
|
8016
|
+
if (target === void 0) {
|
|
8017
|
+
try {
|
|
8018
|
+
target = d.thunk();
|
|
8019
|
+
} catch {
|
|
8020
|
+
target = void 0;
|
|
8021
|
+
}
|
|
8022
|
+
}
|
|
8023
|
+
out = target === void 0 || triviaThroughRef(p, target, null) !== null || this.readsScope(target);
|
|
8024
|
+
break;
|
|
8025
|
+
}
|
|
8026
|
+
default:
|
|
8027
|
+
out = true;
|
|
8028
|
+
}
|
|
8029
|
+
this.readsScopeMemo.set(p, out);
|
|
8030
|
+
return out;
|
|
8031
|
+
}
|
|
7792
8032
|
settings;
|
|
7793
8033
|
/** Resolved once, HERE, at table-build time — never consulted at run time. */
|
|
7794
8034
|
track;
|
|
@@ -7806,8 +8046,8 @@ var Encoder = class {
|
|
|
7806
8046
|
/**
|
|
7807
8047
|
* The class of the follow set of term `i` in a sequence — the sync sentinel a
|
|
7808
8048
|
* list nested in that term resyncs to, INFERRED from structure exactly as
|
|
7809
|
-
* `sequence()` (combinators/sequence.ts:58) and
|
|
7810
|
-
*
|
|
8049
|
+
* `sequence()` (combinators/sequence.ts:58) and the source
|
|
8050
|
+
* lowering's `emitSeqValues` infer it: the union of every LATER term's first
|
|
7811
8051
|
* set, not merely up to the first non-nullable one, so a mandatory middle term
|
|
7812
8052
|
* cannot hide a later close. −1 where there is no usable sentinel, which is the
|
|
7813
8053
|
* same set of cases `firstSetSentinel` answers `null` for.
|
|
@@ -7816,7 +8056,7 @@ var Encoder = class {
|
|
|
7816
8056
|
let fs3 = { kind: "empty" };
|
|
7817
8057
|
const rr = this.refResolver();
|
|
7818
8058
|
for (let j = i + 1; j < parsers.length; j++) {
|
|
7819
|
-
fs3 = union(fs3, firstSetOf(parsers[j], /* @__PURE__ */ new Set(), rr,
|
|
8059
|
+
fs3 = union(fs3, firstSetOf(parsers[j], /* @__PURE__ */ new Set(), rr, void 0, false));
|
|
7820
8060
|
}
|
|
7821
8061
|
return this.charClass(fs3);
|
|
7822
8062
|
}
|
|
@@ -7984,7 +8224,7 @@ var Encoder = class {
|
|
|
7984
8224
|
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;
|
|
7985
8225
|
const rr = this.refResolver();
|
|
7986
8226
|
if (matchesEmpty(p, /* @__PURE__ */ new Set(), rr)) return child;
|
|
7987
|
-
const cls = this.charClass(firstSetOf(p, /* @__PURE__ */ new Set(), rr, this.activeTrivia));
|
|
8227
|
+
const cls = this.charClass(firstSetOf(p, /* @__PURE__ */ new Set(), rr, this.activeTrivia, false));
|
|
7988
8228
|
if (cls < 0) return child;
|
|
7989
8229
|
const e = deriveExpected(p);
|
|
7990
8230
|
return this.emit(OP_GATE, cls, child, this.expected(e.length > 0 ? e : [p._tag]));
|
|
@@ -8010,9 +8250,27 @@ var Encoder = class {
|
|
|
8010
8250
|
* `{`, `Call` at `}`). The resolved set is the one a choice arm's gate uses,
|
|
8011
8251
|
* over the final merged map.
|
|
8012
8252
|
*/
|
|
8013
|
-
|
|
8253
|
+
/**
|
|
8254
|
+
* The arms whose first set under `gateTrivia()` is wider than under the
|
|
8255
|
+
* active trivia alone — a reference's installed trivia read through from a
|
|
8256
|
+
* region with none. Empty for construction-set (disjoint) choices, whose
|
|
8257
|
+
* sets do not depend on trivia.
|
|
8258
|
+
*/
|
|
8259
|
+
wideArms(arms, wide, constructionSets, wideTrivia = this.gateTrivia(), base = this.activeTrivia) {
|
|
8260
|
+
if (constructionSets || wideTrivia === base) return [];
|
|
8261
|
+
const narrow = classifyFinalChoice(arms, this.refResolver(), base, false, false).firstSets;
|
|
8262
|
+
const out = [];
|
|
8263
|
+
for (let i = 0; i < arms.length; i++) {
|
|
8264
|
+
if (this.charClass(wide[i]) !== this.charClass(narrow[i])) out.push(i);
|
|
8265
|
+
}
|
|
8266
|
+
return out;
|
|
8267
|
+
}
|
|
8268
|
+
gateFirstSet(p, guarded, narrowed) {
|
|
8014
8269
|
const cached = p._meta.firstSet;
|
|
8015
|
-
|
|
8270
|
+
if (p._def.tag !== "lazy" && cached.kind !== "any") return cached;
|
|
8271
|
+
const rr = this.refResolver();
|
|
8272
|
+
if (guarded) return firstSetOf(p, /* @__PURE__ */ new Set(), rr, void 0, false);
|
|
8273
|
+
return firstSetOf(p, /* @__PURE__ */ new Set(), rr, this.gateTrivia(), narrowed && this.gateConsuming());
|
|
8016
8274
|
}
|
|
8017
8275
|
/**
|
|
8018
8276
|
* Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
|
|
@@ -8044,6 +8302,135 @@ var Encoder = class {
|
|
|
8044
8302
|
for (const w of words) this.code.push(w);
|
|
8045
8303
|
return ip;
|
|
8046
8304
|
}
|
|
8305
|
+
/**
|
|
8306
|
+
* An optional repeat item tests the item's class before it runs it (`OP_REP`
|
|
8307
|
+
* ip+7), wherever the item's own first-set gate would also run. So a sequence
|
|
8308
|
+
* item whose first term is a gate on that same class gets its own copy of the
|
|
8309
|
+
* sequence row with the gate's child as that term: the test runs once. The
|
|
8310
|
+
* shared row is left as it is for its other references.
|
|
8311
|
+
*/
|
|
8312
|
+
withoutLeadGate(seq, cls) {
|
|
8313
|
+
const op = this.code[seq];
|
|
8314
|
+
if (op !== OP_SEQ && op !== OP_SEQV) return seq;
|
|
8315
|
+
const first = this.code[seq + 2];
|
|
8316
|
+
if (this.code[first] !== OP_GATE || this.code[first + 1] !== cls) return seq;
|
|
8317
|
+
const n = this.code[seq + 1];
|
|
8318
|
+
const width = 1 + 2 * n;
|
|
8319
|
+
const head = this.emitHead(op, width);
|
|
8320
|
+
for (let i = 1; i <= width; i++) this.code[head + i] = this.code[seq + i];
|
|
8321
|
+
this.code[head + 2] = this.code[first + 2];
|
|
8322
|
+
return head;
|
|
8323
|
+
}
|
|
8324
|
+
/**
|
|
8325
|
+
* An optional repeat item that opens with a GAP — a regex that may match
|
|
8326
|
+
* empty, or one that starts only with whitespace or a comment's `/` — and
|
|
8327
|
+
* then a term with a finite first set gets an `OP_GAPGATE` row
|
|
8328
|
+
* (`gap-gate.ts`): the repeat reads the gap once, ends where the character
|
|
8329
|
+
* after it opens neither that term nor an arm without the gap, and hands the
|
|
8330
|
+
* gap's end to the regex row. Anything the walk cannot prove keeps the item as
|
|
8331
|
+
* written.
|
|
8332
|
+
*/
|
|
8333
|
+
gapGated(item, ip) {
|
|
8334
|
+
if (this.activeTrivia === void 0 && !this.triviaKnown) return ip;
|
|
8335
|
+
const lead2 = this.gapLead(item, this.activeTrivia, 0);
|
|
8336
|
+
if (lead2 === void 0) return ip;
|
|
8337
|
+
const cls = this.charClass(lead2.follow);
|
|
8338
|
+
if (cls < 0) return ip;
|
|
8339
|
+
const other = lead2.other.kind === "empty" ? -1 : this.charClass(lead2.other);
|
|
8340
|
+
if (lead2.other.kind !== "empty" && other < 0) return ip;
|
|
8341
|
+
const p = this.node(lead2.p).ip;
|
|
8342
|
+
if (this.code[p] !== OP_RX && this.code[p] !== OP_RX_TRACK) return ip;
|
|
8343
|
+
return this.emit(OP_GAPGATE, ip, p, cls, other);
|
|
8344
|
+
}
|
|
8345
|
+
/**
|
|
8346
|
+
* The gap an item opens with: the regex `p`, the first set `follow` of what
|
|
8347
|
+
* must come straight after it, and the first set `other` of choice arms that
|
|
8348
|
+
* do not open with `p`. Only through wrappers that consume nothing before
|
|
8349
|
+
* their body, a sequence's first term, and a choice's arms; the gap must sit
|
|
8350
|
+
* in a sequence with no trivia between its terms.
|
|
8351
|
+
*/
|
|
8352
|
+
gapLead(c, trivia2, depth) {
|
|
8353
|
+
if (depth > 24) return void 0;
|
|
8354
|
+
const rr = this.refResolver();
|
|
8355
|
+
const d = c._def;
|
|
8356
|
+
switch (d.tag) {
|
|
8357
|
+
case "lazy": {
|
|
8358
|
+
let target = winnerForRef(c, rr);
|
|
8359
|
+
if (target === void 0) {
|
|
8360
|
+
try {
|
|
8361
|
+
target = d.thunk();
|
|
8362
|
+
} catch {
|
|
8363
|
+
return void 0;
|
|
8364
|
+
}
|
|
8365
|
+
}
|
|
8366
|
+
return this.gapLead(target, triviaThroughRef(c, target, trivia2), depth + 1);
|
|
8367
|
+
}
|
|
8368
|
+
case "node":
|
|
8369
|
+
case "leaf":
|
|
8370
|
+
case "label":
|
|
8371
|
+
case "attempt":
|
|
8372
|
+
return this.gapLead(d.parser, trivia2, depth + 1);
|
|
8373
|
+
case "field":
|
|
8374
|
+
return d.leadingTrivia === true ? void 0 : this.gapLead(d.parser, trivia2, depth + 1);
|
|
8375
|
+
case "grammar":
|
|
8376
|
+
return this.gapLead(d.parser, d.clearTrivia === true ? null : d.triviaParser ?? trivia2, depth + 1);
|
|
8377
|
+
case "sequence": {
|
|
8378
|
+
const [first, ...rest] = d.parsers;
|
|
8379
|
+
if (first === void 0) return void 0;
|
|
8380
|
+
if (first._def.tag !== "regex" || !isGap(first)) {
|
|
8381
|
+
return this.gapLead(first, trivia2, depth + 1);
|
|
8382
|
+
}
|
|
8383
|
+
if (trivia2 !== void 0 && trivia2 !== null || rest.length === 0) return void 0;
|
|
8384
|
+
let follow = empty();
|
|
8385
|
+
let closed = false;
|
|
8386
|
+
for (const t of rest) {
|
|
8387
|
+
const fs3 = firstSetOf(t, /* @__PURE__ */ new Set(), rr, null);
|
|
8388
|
+
if (fs3.kind === "any") return void 0;
|
|
8389
|
+
follow = union(follow, fs3);
|
|
8390
|
+
if (!matchesEmpty(t, /* @__PURE__ */ new Set(), rr)) {
|
|
8391
|
+
closed = true;
|
|
8392
|
+
break;
|
|
8393
|
+
}
|
|
8394
|
+
}
|
|
8395
|
+
return closed ? { p: first, follow, other: empty() } : void 0;
|
|
8396
|
+
}
|
|
8397
|
+
case "choice": {
|
|
8398
|
+
let p;
|
|
8399
|
+
let follow = empty();
|
|
8400
|
+
let other = empty();
|
|
8401
|
+
for (const arm of d.parsers) {
|
|
8402
|
+
const lead2 = this.gapLead(arm, trivia2, depth + 1);
|
|
8403
|
+
if (lead2 !== void 0 && (p === void 0 || lead2.p === p)) {
|
|
8404
|
+
p = lead2.p;
|
|
8405
|
+
follow = union(follow, lead2.follow);
|
|
8406
|
+
other = union(other, lead2.other);
|
|
8407
|
+
continue;
|
|
8408
|
+
}
|
|
8409
|
+
if (matchesEmpty(arm, /* @__PURE__ */ new Set(), rr)) return void 0;
|
|
8410
|
+
const fs3 = firstSetOf(arm, /* @__PURE__ */ new Set(), rr, trivia2 ?? null);
|
|
8411
|
+
if (fs3.kind === "any") return void 0;
|
|
8412
|
+
other = union(other, fs3);
|
|
8413
|
+
}
|
|
8414
|
+
return p === void 0 ? void 0 : { p, follow, other };
|
|
8415
|
+
}
|
|
8416
|
+
default:
|
|
8417
|
+
return void 0;
|
|
8418
|
+
}
|
|
8419
|
+
}
|
|
8420
|
+
/**
|
|
8421
|
+
* The class a strict list may end on — a character its separator `p` (row
|
|
8422
|
+
* `ip`) cannot start — without entering the separator, or −1.
|
|
8423
|
+
*
|
|
8424
|
+
* The test runs before every separator, to save the one that fails at the
|
|
8425
|
+
* list's end, so it is laid down only where entering the separator costs more
|
|
8426
|
+
* than the test: not on a terminal row, which is itself one character test.
|
|
8427
|
+
*/
|
|
8428
|
+
sepGate(p, ip) {
|
|
8429
|
+
const op = this.code[ip];
|
|
8430
|
+
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;
|
|
8431
|
+
if (matchesEmpty(p, /* @__PURE__ */ new Set(), this.refResolver())) return -1;
|
|
8432
|
+
return this.charClass(firstSetOf(p, /* @__PURE__ */ new Set(), this.refResolver(), this.gateTrivia(), this.gateConsuming()));
|
|
8433
|
+
}
|
|
8047
8434
|
/** Reserve `n` operand slots to patch once children are laid out. */
|
|
8048
8435
|
emitHead(op, n) {
|
|
8049
8436
|
const ip = this.code.length;
|
|
@@ -8087,8 +8474,10 @@ var Encoder = class {
|
|
|
8087
8474
|
}
|
|
8088
8475
|
encodeRule(name, p) {
|
|
8089
8476
|
this.activeTrivia = p._meta.grammarTrivia;
|
|
8477
|
+
this.triviaKnown = p._meta.grammarTrivia !== void 0;
|
|
8090
8478
|
const body = this.node(p).ip;
|
|
8091
8479
|
this.activeTrivia = void 0;
|
|
8480
|
+
this.triviaKnown = true;
|
|
8092
8481
|
const gss = p._meta.grammarScanSkip;
|
|
8093
8482
|
this.scanSkipOf.push(gss === void 0 ? -1 : this.scanSkipSlot(gss));
|
|
8094
8483
|
const amb = p._meta.grammarTrivia;
|
|
@@ -8134,11 +8523,15 @@ var Encoder = class {
|
|
|
8134
8523
|
* silently produced the ONE keyword `bc`.
|
|
8135
8524
|
*/
|
|
8136
8525
|
scopedRef(p, target) {
|
|
8526
|
+
const runsUnder = triviaThroughRef(p, target, this.activeTrivia);
|
|
8527
|
+
if (this.activeTrivia !== void 0 || runsUnder === void 0 || runsUnder === null) return this.node(target).ip;
|
|
8528
|
+
const savedKnown = this.triviaKnown;
|
|
8529
|
+
this.activeTrivia = runsUnder;
|
|
8530
|
+
this.triviaKnown = true;
|
|
8137
8531
|
const ip = this.node(target).ip;
|
|
8138
|
-
|
|
8139
|
-
|
|
8140
|
-
|
|
8141
|
-
return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), ip);
|
|
8532
|
+
this.activeTrivia = void 0;
|
|
8533
|
+
this.triviaKnown = savedKnown;
|
|
8534
|
+
return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(runsUnder), ip);
|
|
8142
8535
|
}
|
|
8143
8536
|
/**
|
|
8144
8537
|
* The `OP_RGATE` operands of a choice arm that opens with `routed()`, or
|
|
@@ -8179,38 +8572,43 @@ var Encoder = class {
|
|
|
8179
8572
|
if (matchesEmpty(next, /* @__PURE__ */ new Set(), rr) || mayCommitFailure(next, rr, this.commitFailureMemo)) return void 0;
|
|
8180
8573
|
const nextDef = next._def;
|
|
8181
8574
|
if (nextDef.tag !== "literal" && nextDef.tag !== "regex" && nextDef.tag !== "keywords" && nextDef.tag !== "label") return void 0;
|
|
8182
|
-
|
|
8575
|
+
if (boundary === void 0 && !this.triviaKnown) return void 0;
|
|
8576
|
+
const first = firstSetOf(next, /* @__PURE__ */ new Set(), rr, boundary ?? null);
|
|
8183
8577
|
const cls = this.charClass(boundary === void 0 ? first : union(first, firstSetOf(boundary, /* @__PURE__ */ new Set(), rr)));
|
|
8184
8578
|
if (cls < 0) return void 0;
|
|
8185
|
-
const
|
|
8186
|
-
|
|
8579
|
+
const fx = this.expected(nextDef.tag === "label" ? deriveExpected(next) : directTerminalFailureExpected(nextDef));
|
|
8580
|
+
const two = firstTwo(next);
|
|
8581
|
+
if (two === void 0) return { cls, fx };
|
|
8582
|
+
if (boundary !== void 0 && intersects(two.first, firstSetOf(boundary, /* @__PURE__ */ new Set(), rr))) return { cls, fx };
|
|
8583
|
+
const a = this.charClass(two.first);
|
|
8584
|
+
const b = this.charClass(two.second);
|
|
8585
|
+
return a < 0 || b < 0 ? { cls, fx } : { cls, fx, two: [a, b] };
|
|
8187
8586
|
}
|
|
8188
8587
|
node(p) {
|
|
8189
|
-
const
|
|
8190
|
-
|
|
8191
|
-
const
|
|
8192
|
-
const hit = lazyRef ? refMemo.get(p)?.get(scopeKey) : this.memo.get(p);
|
|
8588
|
+
const key = this.scopeKey(p);
|
|
8589
|
+
let byScope = this.memo.get(p);
|
|
8590
|
+
const hit = byScope?.get(key);
|
|
8193
8591
|
if (hit !== void 0) return { ip: hit };
|
|
8194
|
-
|
|
8592
|
+
let inFlightByScope = this.pending.get(p);
|
|
8593
|
+
const inFlight = inFlightByScope?.get(key);
|
|
8195
8594
|
if (inFlight !== void 0) {
|
|
8196
8595
|
const ip2 = this.emitHead(OP_RULE, 1);
|
|
8197
8596
|
inFlight.push(ip2 + 1);
|
|
8198
8597
|
return { ip: ip2 };
|
|
8199
8598
|
}
|
|
8200
8599
|
const patches = [];
|
|
8201
|
-
|
|
8600
|
+
if (inFlightByScope === void 0) {
|
|
8601
|
+
inFlightByScope = /* @__PURE__ */ new Map();
|
|
8602
|
+
this.pending.set(p, inFlightByScope);
|
|
8603
|
+
}
|
|
8604
|
+
inFlightByScope.set(key, patches);
|
|
8202
8605
|
const ip = this.covWrap(this.encodeDef(p), this.plan?.rules.get(p), 0);
|
|
8203
|
-
|
|
8204
|
-
if (
|
|
8205
|
-
|
|
8206
|
-
|
|
8207
|
-
byScope = /* @__PURE__ */ new Map();
|
|
8208
|
-
refMemo.set(p, byScope);
|
|
8209
|
-
}
|
|
8210
|
-
byScope.set(scopeKey, ip);
|
|
8211
|
-
} else {
|
|
8212
|
-
this.memo.set(p, ip);
|
|
8606
|
+
inFlightByScope.delete(key);
|
|
8607
|
+
if (byScope === void 0) {
|
|
8608
|
+
byScope = /* @__PURE__ */ new Map();
|
|
8609
|
+
this.memo.set(p, byScope);
|
|
8213
8610
|
}
|
|
8611
|
+
byScope.set(key, ip);
|
|
8214
8612
|
for (const slot of patches) {
|
|
8215
8613
|
if (slot - 1 === ip) {
|
|
8216
8614
|
const rule = p._ruleName;
|
|
@@ -8308,8 +8706,19 @@ var Encoder = class {
|
|
|
8308
8706
|
}
|
|
8309
8707
|
case "choice": {
|
|
8310
8708
|
if (this.plan === void 0) {
|
|
8311
|
-
const
|
|
8312
|
-
if (
|
|
8709
|
+
const shared = factorSharedEnds(d);
|
|
8710
|
+
if (shared !== void 0) return this.node(shared).ip;
|
|
8711
|
+
if (this.unfactoredChoice !== p) {
|
|
8712
|
+
const prefix = factorPrefixArms(d);
|
|
8713
|
+
if (prefix !== void 0) {
|
|
8714
|
+
const strict = this.node(prefix).ip;
|
|
8715
|
+
const saved = this.unfactoredChoice;
|
|
8716
|
+
this.unfactoredChoice = p;
|
|
8717
|
+
const tolerant = this.encodeDef(p);
|
|
8718
|
+
this.unfactoredChoice = saved;
|
|
8719
|
+
return this.emit(OP_STRICT, strict, tolerant);
|
|
8720
|
+
}
|
|
8721
|
+
}
|
|
8313
8722
|
}
|
|
8314
8723
|
if (d.strategy.tag === "greedyClassify") {
|
|
8315
8724
|
const superIndex = d.strategy.superIndex;
|
|
@@ -8338,18 +8747,20 @@ var Encoder = class {
|
|
|
8338
8747
|
const plain = (checks === null || checks === void 0 || checks.length === 0) && (gate2 === null || gate2 === void 0);
|
|
8339
8748
|
const routedGate = plain ? this.routedArmGate(c) : void 0;
|
|
8340
8749
|
const body = this.node(c).ip;
|
|
8341
|
-
const inner = routedGate === void 0 ? body : this.emit(OP_RGATE, routedGate.cls, body, routedGate.fx);
|
|
8750
|
+
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]);
|
|
8342
8751
|
const ip = checks === null || checks === void 0 || checks.length === 0 ? inner : this.reject(inner, checks);
|
|
8343
8752
|
const gated = gate2 === null || gate2 === void 0 ? ip : this.emit(OP_ARMGATE, this.fn(gate2, d.gateSrcs?.[src] ?? null), ip, this.expected(deriveExpected(c)));
|
|
8344
8753
|
return this.covWrap(gated, armCovIds?.[src], 1);
|
|
8345
8754
|
});
|
|
8346
8755
|
const rr = this.refResolver();
|
|
8347
|
-
const
|
|
8756
|
+
const constructionSets = d.disjoint && !factoredChoices.has(p);
|
|
8757
|
+
const finalChoice = classifyFinalChoice(arms, rr, this.gateTrivia(), false, constructionSets);
|
|
8758
|
+
const wideArms = this.wideArms(arms, finalChoice.firstSets, constructionSets);
|
|
8348
8759
|
const transactionalFirst = arms.map((arm, i) => {
|
|
8349
8760
|
if (!finalChoice.nullable[i]) return void 0;
|
|
8350
8761
|
const def = arm._def;
|
|
8351
8762
|
if (def.tag !== "attempt" || matchesEmpty(def.parser, /* @__PURE__ */ new Set(), rr)) return void 0;
|
|
8352
|
-
return firstSetOf(def.parser, /* @__PURE__ */ new Set(), rr, this.activeTrivia);
|
|
8763
|
+
return firstSetOf(def.parser, /* @__PURE__ */ new Set(), rr, this.activeTrivia, false);
|
|
8353
8764
|
});
|
|
8354
8765
|
const gateFirst = finalChoice.firstSets.map((first, i) => transactionalFirst[i] ?? first);
|
|
8355
8766
|
const classes = gateFirst.map((first, i) => finalChoice.nullable[i] && transactionalFirst[i] === void 0 ? -1 : this.charClass(first));
|
|
@@ -8367,6 +8778,9 @@ var Encoder = class {
|
|
|
8367
8778
|
if (transactionalFirst[i] !== void 0) classes[i] = -1;
|
|
8368
8779
|
}
|
|
8369
8780
|
}
|
|
8781
|
+
if (wideArms.length > 0 && dispatchIsExclusive(classes, this.cc)) {
|
|
8782
|
+
for (const i of wideArms) classes[i] = -1;
|
|
8783
|
+
}
|
|
8370
8784
|
if (d.gates.some((g) => g !== null && g !== void 0) && !dispatchIsExclusive(classes, this.cc)) {
|
|
8371
8785
|
for (let k = 0; k < classes.length; k++) {
|
|
8372
8786
|
const gate2 = d.gates[order[k]];
|
|
@@ -8400,27 +8814,34 @@ var Encoder = class {
|
|
|
8400
8814
|
}
|
|
8401
8815
|
case "many":
|
|
8402
8816
|
case "oneOrMore": {
|
|
8403
|
-
const child = this.node(d.parser).ip;
|
|
8404
8817
|
const rr = this.refResolver();
|
|
8405
|
-
const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.charClass(
|
|
8818
|
+
const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.charClass(this.gateFirstSet(d.parser, d.guarded === true, true));
|
|
8406
8819
|
const op = d.valueUnused ? OP_REPV : OP_REP;
|
|
8407
8820
|
const min = d.tag === "many" ? 0 : d.min;
|
|
8821
|
+
const item = min === 0 && itemClass >= 0 ? this.withoutLeadGate(this.node(d.parser).ip, itemClass) : this.node(d.parser).ip;
|
|
8822
|
+
const child = min === 0 && itemClass >= 0 ? this.gapGated(d.parser, item) : item;
|
|
8408
8823
|
return this.emit(op, child, min, d.max ?? -1, -1, 0, this.expected(deriveExpected(d.parser)), itemClass);
|
|
8409
8824
|
}
|
|
8410
8825
|
case "sepBy": {
|
|
8411
8826
|
const child = this.node(d.parser).ip;
|
|
8412
8827
|
const sep2 = this.node(d.separator).ip;
|
|
8413
|
-
const
|
|
8414
|
-
|
|
8415
|
-
|
|
8828
|
+
const gate2 = this.sepGate(d.separator, sep2);
|
|
8829
|
+
const itemSet = deriveExpected(d.parser);
|
|
8830
|
+
const itemFx = this.expected(itemSet.length > 0 ? itemSet : [d.parser._tag]);
|
|
8831
|
+
const flags = (d.trailing === "allow" ? 1 : 0) | (d.keepSeparators === true ? 2 : 0) | (d.min >= 1 ? 4 : 0) | (gate2 >= 0 ? 8 : 0) | (itemSet.length === 0 ? 16 : 0);
|
|
8832
|
+
const ops = [
|
|
8416
8833
|
child,
|
|
8417
8834
|
d.min,
|
|
8418
8835
|
d.max ?? -1,
|
|
8419
8836
|
sep2,
|
|
8420
8837
|
flags,
|
|
8421
|
-
|
|
8422
|
-
|
|
8423
|
-
|
|
8838
|
+
itemFx,
|
|
8839
|
+
// As 0.58.0: the interpreter resyncs on the separator itself
|
|
8840
|
+
// (`orSentinel`), which runs under the live trivia.
|
|
8841
|
+
this.charClass(firstSetOf(d.separator, /* @__PURE__ */ new Set(), this.refResolver(), this.activeTrivia, false))
|
|
8842
|
+
];
|
|
8843
|
+
if (gate2 >= 0) ops.push(gate2);
|
|
8844
|
+
return this.emit(OP_REP, ...ops);
|
|
8424
8845
|
}
|
|
8425
8846
|
case "optional": {
|
|
8426
8847
|
const head = this.emit(OP_OPT, this.lookaheadGate(d.parser, this.node(d.parser).ip));
|
|
@@ -8429,7 +8850,7 @@ var Encoder = class {
|
|
|
8429
8850
|
}
|
|
8430
8851
|
case "transform": {
|
|
8431
8852
|
const inner = d.parser._def;
|
|
8432
|
-
if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
|
|
8853
|
+
if (inner.tag === "sequence" && !this.memo.get(d.parser)?.has(this.scopeKey(d.parser)) && !this.pending.get(d.parser)?.has(this.scopeKey(d.parser))) {
|
|
8433
8854
|
const kids = inner.parsers.map((c) => this.node(c).ip);
|
|
8434
8855
|
const head = this.emitHead(OP_SEQX, 2 + 2 * kids.length);
|
|
8435
8856
|
const projection = directArrayProjection(d.fn, d.fnSrc, kids.length);
|
|
@@ -8470,7 +8891,7 @@ var Encoder = class {
|
|
|
8470
8891
|
d.tags === void 0 ? -1 : this.constant(d.tags)
|
|
8471
8892
|
);
|
|
8472
8893
|
if (matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return body;
|
|
8473
|
-
const fs3 = this.gateFirstSet(d.parser);
|
|
8894
|
+
const fs3 = this.gateFirstSet(d.parser, d.guarded === true, false);
|
|
8474
8895
|
if (fs3.kind === "any") return body;
|
|
8475
8896
|
const cls = this.charClass(fs3);
|
|
8476
8897
|
if (cls < 0) return body;
|
|
@@ -8478,7 +8899,14 @@ var Encoder = class {
|
|
|
8478
8899
|
return this.emit(OP_GATE, cls, body, this.expected(e.length > 0 ? e : [d.parser._tag]));
|
|
8479
8900
|
}
|
|
8480
8901
|
case "token": {
|
|
8481
|
-
|
|
8902
|
+
const saved = this.activeTrivia;
|
|
8903
|
+
const savedKnown = this.triviaKnown;
|
|
8904
|
+
this.activeTrivia = void 0;
|
|
8905
|
+
this.triviaKnown = true;
|
|
8906
|
+
const body = this.node(d.parser).ip;
|
|
8907
|
+
this.activeTrivia = saved;
|
|
8908
|
+
this.triviaKnown = savedKnown;
|
|
8909
|
+
return this.emit(OP_TOKEN, body);
|
|
8482
8910
|
}
|
|
8483
8911
|
case "routed":
|
|
8484
8912
|
return this.emit(OP_ROUTED, d.fallback === void 0 ? -1 : this.node(d.fallback).ip);
|
|
@@ -8534,7 +8962,7 @@ var Encoder = class {
|
|
|
8534
8962
|
this.code[head + 2] = dspIdx;
|
|
8535
8963
|
this.code[head + 3] = other;
|
|
8536
8964
|
const otherRouted = d.otherwise === void 0 ? false : branchUsesRouted({ parser: d.otherwise, usesRouted: d.otherwiseUsesRouted === true });
|
|
8537
|
-
this.code[head + 4] = otherRouted ? 1 : 0;
|
|
8965
|
+
this.code[head + 4] = (otherRouted ? 1 : 0) | (d.otherwiseCommit === false ? 2 : 0);
|
|
8538
8966
|
this.code[head + 5] = arms.length;
|
|
8539
8967
|
for (let i = 0; i < arms.length; i++) this.code[head + 6 + i] = arms[i];
|
|
8540
8968
|
return head;
|
|
@@ -8589,7 +9017,7 @@ var Encoder = class {
|
|
|
8589
9017
|
case "attempt": {
|
|
8590
9018
|
const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip, d.contain === true ? 1 : 0);
|
|
8591
9019
|
if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
|
|
8592
|
-
const fs3 = this.gateFirstSet(d.parser);
|
|
9020
|
+
const fs3 = this.gateFirstSet(d.parser, d.guarded === true, false);
|
|
8593
9021
|
if (fs3.kind === "any" || matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return inner;
|
|
8594
9022
|
const cls = this.charClass(fs3);
|
|
8595
9023
|
if (cls < 0) return inner;
|
|
@@ -8598,7 +9026,7 @@ var Encoder = class {
|
|
|
8598
9026
|
}
|
|
8599
9027
|
// A LABEL IS A ROW — see `OP_LABEL`. It replaces the child's expected set,
|
|
8600
9028
|
// which is the entire combinator.
|
|
8601
|
-
// A LABEL IS CREDITED ON SUCCESS, as
|
|
9029
|
+
// A LABEL IS CREDITED ON SUCCESS, as the source lowering credited it: its hook
|
|
8602
9030
|
// is emitted AFTER the child's statements, where a failed child has already
|
|
8603
9031
|
// broken out of the labelled block.
|
|
8604
9032
|
case "label":
|
|
@@ -8615,10 +9043,17 @@ var Encoder = class {
|
|
|
8615
9043
|
const op = cap ? OP_SCOPE_CAP : OP_SCOPE;
|
|
8616
9044
|
const flags = (d.rootCapture === "opaque" ? 1 : 0) | (d.triviaParser !== void 0 && d.triviaParser._meta.rootTriviaClassified !== true && d.rootCapture !== "opaque" ? 2 : 0);
|
|
8617
9045
|
const savedTrivia = this.activeTrivia;
|
|
8618
|
-
|
|
8619
|
-
|
|
9046
|
+
const savedKnown = this.triviaKnown;
|
|
9047
|
+
if (d.clearTrivia === true) {
|
|
9048
|
+
this.activeTrivia = void 0;
|
|
9049
|
+
this.triviaKnown = true;
|
|
9050
|
+
} else if (d.triviaParser !== void 0) {
|
|
9051
|
+
this.activeTrivia = d.triviaParser;
|
|
9052
|
+
this.triviaKnown = true;
|
|
9053
|
+
}
|
|
8620
9054
|
const bodyIp = this.node(d.parser).ip;
|
|
8621
9055
|
this.activeTrivia = savedTrivia;
|
|
9056
|
+
this.triviaKnown = savedKnown;
|
|
8622
9057
|
if (d.clearTrivia === true) return this.emit(op, -1, bodyIp, flags);
|
|
8623
9058
|
if (d.triviaParser === void 0) {
|
|
8624
9059
|
return cap || flags !== 0 ? this.emit(op, -1, bodyIp, flags) : bodyIp;
|
|
@@ -8659,6 +9094,7 @@ var Encoder = class {
|
|
|
8659
9094
|
switch (this.code[ip]) {
|
|
8660
9095
|
case OP_GATE:
|
|
8661
9096
|
case OP_RGATE:
|
|
9097
|
+
case OP_RGATE2:
|
|
8662
9098
|
return [ip + 2];
|
|
8663
9099
|
case OP_RULE:
|
|
8664
9100
|
case OP_OPT:
|
|
@@ -8668,6 +9104,7 @@ var Encoder = class {
|
|
|
8668
9104
|
case OP_ATTEMPT:
|
|
8669
9105
|
case OP_LABEL:
|
|
8670
9106
|
case OP_COV:
|
|
9107
|
+
case OP_GAPGATE:
|
|
8671
9108
|
return [ip + 1];
|
|
8672
9109
|
case OP_SCOPE:
|
|
8673
9110
|
case OP_SCOPE_CAP:
|
|
@@ -8704,6 +9141,8 @@ var Encoder = class {
|
|
|
8704
9141
|
case OP_REP:
|
|
8705
9142
|
case OP_REPV:
|
|
8706
9143
|
return this.code[ip + 4] >= 0 ? [ip + 1, ip + 4] : [ip + 1];
|
|
9144
|
+
case OP_STRICT:
|
|
9145
|
+
return [ip + 1, ip + 2];
|
|
8707
9146
|
default:
|
|
8708
9147
|
return [];
|
|
8709
9148
|
}
|
|
@@ -9861,6 +10300,7 @@ function childSlots(code, ip, out) {
|
|
|
9861
10300
|
case OP_LABEL:
|
|
9862
10301
|
case OP_COV:
|
|
9863
10302
|
case OP_REJECT:
|
|
10303
|
+
case OP_GAPGATE:
|
|
9864
10304
|
out.push(code[ip + 1]);
|
|
9865
10305
|
return true;
|
|
9866
10306
|
// Single child at `ip + 2`.
|
|
@@ -9877,8 +10317,13 @@ function childSlots(code, ip, out) {
|
|
|
9877
10317
|
case OP_SOURCE_LEAF:
|
|
9878
10318
|
case OP_ARMGATE:
|
|
9879
10319
|
case OP_RGATE:
|
|
10320
|
+
case OP_RGATE2:
|
|
9880
10321
|
out.push(code[ip + 2]);
|
|
9881
10322
|
return true;
|
|
10323
|
+
// `STRICT strict tolerant` — both encodings are reachable; an assembly keeps one.
|
|
10324
|
+
case OP_STRICT:
|
|
10325
|
+
out.push(code[ip + 1], code[ip + 2]);
|
|
10326
|
+
return true;
|
|
9882
10327
|
// `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
|
|
9883
10328
|
// data the enclosing `dispatch()` already consumed, so the only edge is the
|
|
9884
10329
|
// fallback.
|
|
@@ -10326,7 +10771,8 @@ var WRAPPERS = /* @__PURE__ */ new Set([
|
|
|
10326
10771
|
OP_WITHCTX,
|
|
10327
10772
|
OP_RULE,
|
|
10328
10773
|
OP_ATTEMPT,
|
|
10329
|
-
OP_COV
|
|
10774
|
+
OP_COV,
|
|
10775
|
+
OP_GAPGATE
|
|
10330
10776
|
]);
|
|
10331
10777
|
function rowNullable(code, k, ip, memo) {
|
|
10332
10778
|
const hit = memo.get(ip);
|
|
@@ -10363,7 +10809,31 @@ function holdsGap(code, k, base, n, i, memo) {
|
|
|
10363
10809
|
return !rowNullable(code, k, next, memo);
|
|
10364
10810
|
}
|
|
10365
10811
|
|
|
10812
|
+
// src/table/gap-gate.ts
|
|
10813
|
+
function newGapSlot() {
|
|
10814
|
+
return { row: -1, at: -1, end: -1, input: void 0 };
|
|
10815
|
+
}
|
|
10816
|
+
function gapRows(code, roots) {
|
|
10817
|
+
const rows = /* @__PURE__ */ new Set();
|
|
10818
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10819
|
+
const stack = [...roots];
|
|
10820
|
+
const kids = [];
|
|
10821
|
+
while (stack.length > 0) {
|
|
10822
|
+
const ip = stack.pop();
|
|
10823
|
+
if (seen.has(ip)) continue;
|
|
10824
|
+
seen.add(ip);
|
|
10825
|
+
if (code[ip] === OP_GAPGATE) rows.add(code[ip + 2]);
|
|
10826
|
+
kids.length = 0;
|
|
10827
|
+
childSlots(code, ip, kids);
|
|
10828
|
+
for (const c of kids) stack.push(c);
|
|
10829
|
+
}
|
|
10830
|
+
return rows;
|
|
10831
|
+
}
|
|
10832
|
+
|
|
10366
10833
|
// src/table/emit-assembly.ts
|
|
10834
|
+
function gapRegexLowers(re) {
|
|
10835
|
+
return re instanceof RegExp && scanShapeFromRegex(re.source, re.flags) !== null;
|
|
10836
|
+
}
|
|
10367
10837
|
var Unemittable = class extends Error {
|
|
10368
10838
|
construct;
|
|
10369
10839
|
constructor(construct) {
|
|
@@ -10382,7 +10852,6 @@ var EMITTED_PARAMS = [
|
|
|
10382
10852
|
"CLS",
|
|
10383
10853
|
"AFX",
|
|
10384
10854
|
"TRIVIA",
|
|
10385
|
-
"TRIVIALABELS",
|
|
10386
10855
|
"TRIVIASCAN",
|
|
10387
10856
|
"SCANS",
|
|
10388
10857
|
"DISP",
|
|
@@ -10406,7 +10875,6 @@ var EMITTED_PARAMS = [
|
|
|
10406
10875
|
"cstLeavesLen",
|
|
10407
10876
|
"skipTriviaScanned",
|
|
10408
10877
|
"needsDeferredTriviaCommit",
|
|
10409
|
-
"scanTrivia",
|
|
10410
10878
|
"advanceTrivia",
|
|
10411
10879
|
"refuseUnclassifiedRootScope",
|
|
10412
10880
|
"spanLines",
|
|
@@ -10426,34 +10894,31 @@ var EMITTED_PARAMS = [
|
|
|
10426
10894
|
"orSentinel",
|
|
10427
10895
|
"captureError",
|
|
10428
10896
|
// Pure scalar terminal recognizers, indexed by the terminal's existing const
|
|
10429
|
-
// operand
|
|
10897
|
+
// operand; selected lexical bodies; the adjacency test.
|
|
10430
10898
|
"RECOG",
|
|
10431
|
-
// Appended so precompiled factories produced by earlier runtimes keep every
|
|
10432
|
-
// positional helper binding. Older factories ignore this trailing argument.
|
|
10433
|
-
"commitTriviaScan",
|
|
10434
|
-
"scanTriviaCompact",
|
|
10435
10899
|
"LEX",
|
|
10436
|
-
// Appended for old precompiled-factory ABI: old factories ignore it.
|
|
10437
10900
|
"adjacencyHolds",
|
|
10438
|
-
//
|
|
10901
|
+
// Selected composite lexical programs.
|
|
10439
10902
|
"LEXPROG",
|
|
10440
|
-
//
|
|
10441
|
-
// old factories ignore them.
|
|
10903
|
+
// Trivia-attributing fields (`field(…, { leadingTrivia })`).
|
|
10442
10904
|
"LEAD",
|
|
10443
10905
|
"triviaFieldCapture",
|
|
10444
|
-
//
|
|
10445
|
-
// factories ignore it.
|
|
10906
|
+
// The deferred-commit trivia skip (`trivia-gap.ts`).
|
|
10446
10907
|
"skipDeferredTrivia",
|
|
10447
|
-
//
|
|
10448
|
-
// ignore it.
|
|
10908
|
+
// The pass-through collapse (`run-support.ts`).
|
|
10449
10909
|
"collapseEmpty",
|
|
10450
|
-
//
|
|
10451
|
-
//
|
|
10910
|
+
// Constructor-built tree objects (`cst/plain.d.ts`): a `new` call has no
|
|
10911
|
+
// allocation site, so V8 cannot pretenure them.
|
|
10452
10912
|
"_SP",
|
|
10453
10913
|
"_LF",
|
|
10454
10914
|
"_ND",
|
|
10455
10915
|
"_FC",
|
|
10456
|
-
"_BUF"
|
|
10916
|
+
"_BUF",
|
|
10917
|
+
// The gap gate's slot (`gap-gate.ts`).
|
|
10918
|
+
"GAP"
|
|
10919
|
+
// Artifacts are version-locked (docs/design/artifact-format.md): a factory is
|
|
10920
|
+
// only ever called by the runtime that emitted it, so a name nothing emitted
|
|
10921
|
+
// reads is removed rather than kept for an older factory's positions.
|
|
10457
10922
|
];
|
|
10458
10923
|
var RUNTIME_PRELUDE = `
|
|
10459
10924
|
let _pfScan=null
|
|
@@ -10704,7 +11169,7 @@ function rebuildPools(cc, fx, disp, plan) {
|
|
|
10704
11169
|
})
|
|
10705
11170
|
};
|
|
10706
11171
|
}
|
|
10707
|
-
function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, select, scanSinkNeutral = false) {
|
|
11172
|
+
function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, select, scanSinkNeutral = false, gapNeutral = false) {
|
|
10708
11173
|
const { code, k, fx, disp, dsp, triviaLabelled } = t;
|
|
10709
11174
|
const swapLegal = !cfg.trackLines;
|
|
10710
11175
|
const hostCst = cfg.hostCst;
|
|
@@ -10712,6 +11177,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, se
|
|
|
10712
11177
|
if (cfg.coverage) throw new Unemittable("a coverage assembly");
|
|
10713
11178
|
const roots = [...Object.values(prog.rules), ...extraIps];
|
|
10714
11179
|
const reachable = [...reachableSites(code, roots)];
|
|
11180
|
+
const GAP_ROWS = gapNeutral ? /* @__PURE__ */ new Set() : new Set([...gapRows(code, roots)].filter((row) => !gapRegexLowers(k[code[row + 1]])));
|
|
10715
11181
|
const labels = computeSiteLabels(code, roots, hostCst);
|
|
10716
11182
|
const scalarSpecs = /* @__PURE__ */ new Set();
|
|
10717
11183
|
const nullable2 = /* @__PURE__ */ new Map();
|
|
@@ -11049,13 +11515,15 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
11049
11515
|
function aliasOf(ip) {
|
|
11050
11516
|
const op = code[ip];
|
|
11051
11517
|
if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
|
|
11052
|
-
if (op === OP_RULE) return code[ip + 1];
|
|
11518
|
+
if (op === OP_RULE || op === OP_GAPGATE) return code[ip + 1];
|
|
11519
|
+
if (op === OP_STRICT) return code[cfg.tolerant || cfg.probe ? ip + 2 : ip + 1];
|
|
11053
11520
|
if (scopeIsIdentity(code, ip, labels.at(ip))) return code[ip + 2];
|
|
11054
11521
|
return void 0;
|
|
11055
11522
|
}
|
|
11056
11523
|
function lower(ip, fname) {
|
|
11057
11524
|
const op = code[ip];
|
|
11058
11525
|
const head = `function ${fname}(input,pos,ctx){`;
|
|
11526
|
+
const outerHead = head;
|
|
11059
11527
|
const L = labels.at(ip);
|
|
11060
11528
|
const sinks = sinksAt(ip);
|
|
11061
11529
|
const pushLeaf = L.buf && !cfg.trackLines ? L.raw === RAW_OMIT ? "_pushLeafNoRawBuf" : L.raw === RAW_CAPTURE ? "_pushLeafBuf" : "_pushLeaf" : "_pushLeaf";
|
|
@@ -11131,9 +11599,27 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
11131
11599
|
case OP_RX_TRACK: {
|
|
11132
11600
|
const xf = fxRef(code[ip + 2]);
|
|
11133
11601
|
const track = op === OP_RX_TRACK;
|
|
11602
|
+
if (GAP_ROWS.has(ip)) {
|
|
11603
|
+
const re2 = hoist("gx", `K[${code[ip + 1]}]`);
|
|
11604
|
+
return `${outerHead}
|
|
11605
|
+
let e
|
|
11606
|
+
if(GAP.row===${ip}&&GAP.at===pos&&GAP.input===input)e=GAP.end
|
|
11607
|
+
else{${re2}.lastIndex=pos;e=${re2}.test(input)?${re2}.lastIndex:-1}
|
|
11608
|
+
if(e>=0){
|
|
11609
|
+
const v=input.slice(pos,e)
|
|
11610
|
+
${captureLeaf("v")}
|
|
11611
|
+
${track ? "_trackLines(ctx,input,e)\n" : ""}EC.e=e
|
|
11612
|
+
return v
|
|
11613
|
+
}
|
|
11614
|
+
ctx._fe=pos;ctx._fx=${xf}
|
|
11615
|
+
${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
11616
|
+
` : ""}return FAIL
|
|
11617
|
+
}`;
|
|
11618
|
+
}
|
|
11619
|
+
const head2 = outerHead;
|
|
11134
11620
|
if (!track && scalarSpecs.has(code[ip + 1])) {
|
|
11135
11621
|
const recognize = recognizerRef(code[ip + 1]);
|
|
11136
|
-
return `${
|
|
11622
|
+
return `${head2}
|
|
11137
11623
|
const e=${recognize}(input,pos)
|
|
11138
11624
|
if(e>=0){
|
|
11139
11625
|
const v=input.slice(pos,e)
|
|
@@ -11146,11 +11632,11 @@ return FAIL
|
|
|
11146
11632
|
}`;
|
|
11147
11633
|
}
|
|
11148
11634
|
const scanned = emitScan(code[ip + 1], xf, track, captureLeaf);
|
|
11149
|
-
if (scanned !== void 0) return `${
|
|
11635
|
+
if (scanned !== void 0) return `${head2}${scanned}}`;
|
|
11150
11636
|
const rxk = k[code[ip + 1]];
|
|
11151
11637
|
if (!(rxk instanceof RegExp) || !rxk.sticky) throw new Unemittable("a non-sticky regex row");
|
|
11152
11638
|
const re = kRef(code[ip + 1]);
|
|
11153
|
-
return `${
|
|
11639
|
+
return `${head2}
|
|
11154
11640
|
${re}.lastIndex=pos
|
|
11155
11641
|
if(${re}.test(input)){
|
|
11156
11642
|
const e=${re}.lastIndex
|
|
@@ -11188,6 +11674,28 @@ return ${child}(input,pos,ctx)
|
|
|
11188
11674
|
const it=ctx._routed
|
|
11189
11675
|
if(it!==undefined&&it.span.start===pos&&!classHas(${cls},lead(input,it.span.end))){ctx._fe=it.span.end;ctx._fx=${xf};return FAIL}
|
|
11190
11676
|
return ${child}(input,pos,ctx)
|
|
11677
|
+
}`;
|
|
11678
|
+
}
|
|
11679
|
+
case OP_RGATE2: {
|
|
11680
|
+
const child = link(code[ip + 2]);
|
|
11681
|
+
if (cfg.tolerant || cfg.probe) return `${head}
|
|
11682
|
+
return ${child}(input,pos,ctx)
|
|
11683
|
+
}`;
|
|
11684
|
+
const idxs = [code[ip + 1], code[ip + 4], code[ip + 5]];
|
|
11685
|
+
const ascii = idxs.every((i) => isAsciiOnlyClass(t.cc[i]));
|
|
11686
|
+
const ref2 = (idx, tag) => {
|
|
11687
|
+
const ci = classes.push([t.cc[idx]]) - 1;
|
|
11688
|
+
classPlan.push([idx]);
|
|
11689
|
+
return hoist(tag, `CLS[${ci}][0]`);
|
|
11690
|
+
};
|
|
11691
|
+
const [cls, first, second] = [ref2(idxs[0], "cl"), ref2(idxs[1], "c1"), ref2(idxs[2], "c2")];
|
|
11692
|
+
const has = (c, at) => ascii ? `${c}.ascii[${at}]===1` : `classHas(${c},${at})`;
|
|
11693
|
+
const xf = fxRef(code[ip + 3]);
|
|
11694
|
+
return `${head}
|
|
11695
|
+
const it=ctx._routed
|
|
11696
|
+
if(it!==undefined&&it.span.start===pos){const e=it.span.end;const c=${ascii ? "input.charCodeAt(e)" : "lead(input,e)"}
|
|
11697
|
+
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}}
|
|
11698
|
+
return ${child}(input,pos,ctx)
|
|
11191
11699
|
}`;
|
|
11192
11700
|
}
|
|
11193
11701
|
case OP_ARMGATE: {
|
|
@@ -11597,7 +12105,27 @@ if(ctx._fc===true)return FAIL
|
|
|
11597
12105
|
const af=ctx._fx
|
|
11598
12106
|
if(af!==undefined&&af.length>0){ctx._fe=pos;return FAIL}
|
|
11599
12107
|
}
|
|
11600
|
-
|
|
12108
|
+
${cfg.probe ? `if(arm<0){${arms.map((a) => `${a}(input,pos,ctx)`).join(";")}}
|
|
12109
|
+
` : ""}ctx._fe=pos;ctx._fx=${choiceFx}
|
|
12110
|
+
return FAIL
|
|
12111
|
+
}`;
|
|
12112
|
+
}
|
|
12113
|
+
if (cfg.probe) {
|
|
12114
|
+
const p = tmp();
|
|
12115
|
+
return `${head}
|
|
12116
|
+
${emitMark(p, L.buf, L.raw, sinks)}
|
|
12117
|
+
let acc
|
|
12118
|
+
let best=pos
|
|
12119
|
+
${arms.map((arm) => `{ctx._fc=false
|
|
12120
|
+
const v=${arm}(input,pos,ctx)
|
|
12121
|
+
if(v!==FAIL)return v
|
|
12122
|
+
const at=ctx._fe??pos
|
|
12123
|
+
if(at>best){best=at;acc=undefined}
|
|
12124
|
+
if(at===best)acc=_accSet(ctx._fx,acc)
|
|
12125
|
+
if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
|
|
12126
|
+
${emitRollback(p, L.buf, L.raw, sinks)}
|
|
12127
|
+
}`).join("\n")}
|
|
12128
|
+
ctx._fe=pos;ctx._fx=acc??${choiceFx}
|
|
11601
12129
|
return FAIL
|
|
11602
12130
|
}`;
|
|
11603
12131
|
}
|
|
@@ -11804,7 +12332,8 @@ return FAIL
|
|
|
11804
12332
|
const selector = link(code[ip + 1]);
|
|
11805
12333
|
const otherIp = code[ip + 3];
|
|
11806
12334
|
const other = otherIp >= 0 ? link(otherIp) : void 0;
|
|
11807
|
-
const otherRouted = code[ip + 4] === 1;
|
|
12335
|
+
const otherRouted = (code[ip + 4] & 1) === 1;
|
|
12336
|
+
const otherCommits = (code[ip + 4] & 2) === 0;
|
|
11808
12337
|
const n = code[ip + 5];
|
|
11809
12338
|
validateDispatchSpec(spec, n, code[ip + 4]);
|
|
11810
12339
|
const armBase = ip + 6;
|
|
@@ -11858,7 +12387,7 @@ ${fallbackCase}
|
|
|
11858
12387
|
}
|
|
11859
12388
|
if(v===FAIL){
|
|
11860
12389
|
${emitRollback(m2, L.buf, L.raw, sinks)}
|
|
11861
|
-
ctx._fc=true
|
|
12390
|
+
${other !== void 0 && !otherCommits ? "if(arm!==undefined)" : ""}ctx._fc=true
|
|
11862
12391
|
return FAIL
|
|
11863
12392
|
}
|
|
11864
12393
|
return [key,v]
|
|
@@ -11890,6 +12419,63 @@ return [key,v]
|
|
|
11890
12419
|
}
|
|
11891
12420
|
}
|
|
11892
12421
|
const itemMiss = (at) => itemAscii ? `${itemCls}.ascii[input.charCodeAt(${at})]!==1` : `!classHas(${itemCls},lead(input,${at}))`;
|
|
12422
|
+
let sepCls;
|
|
12423
|
+
let sepAscii = false;
|
|
12424
|
+
if (!REC2 && sepIp >= 0 && (code[ip + 5] & 8) !== 0 && !leadingTriviaFieldAt(code, k, sepIp) && !rowNullable(code, k, sepIp, nullable2)) {
|
|
12425
|
+
const resolved = t.cc[code[ip + 8]];
|
|
12426
|
+
const ci = classes.push([resolved]) - 1;
|
|
12427
|
+
classPlan.push([code[ip + 8]]);
|
|
12428
|
+
sepCls = hoist("rs", `CLS[${ci}][0]`);
|
|
12429
|
+
sepAscii = isAsciiOnlyClass(resolved);
|
|
12430
|
+
}
|
|
12431
|
+
const gapIp = !gapNeutral && sepIp < 0 && min === 0 && !REC2 && code[code[ip + 1]] === OP_GAPGATE ? code[ip + 1] : -1;
|
|
12432
|
+
let gapCode = (_rb) => "";
|
|
12433
|
+
if (gapIp >= 0) {
|
|
12434
|
+
const row = code[gapIp + 2];
|
|
12435
|
+
const rx = k[code[row + 1]];
|
|
12436
|
+
const shape = gapRegexLowers(rx) ? scanShapeFromRegex(rx.source, rx.flags) : null;
|
|
12437
|
+
const cls = (idx) => {
|
|
12438
|
+
const resolved = t.cc[idx];
|
|
12439
|
+
const ci = classes.push([resolved]) - 1;
|
|
12440
|
+
classPlan.push([idx]);
|
|
12441
|
+
const ref2 = hoist("gc", `CLS[${ci}][0]`);
|
|
12442
|
+
return isAsciiOnlyClass(resolved) ? `${ref2}.ascii[input.charCodeAt(${"@"})]!==1` : `!classHas(${ref2},lead(input,${"@"}))`;
|
|
12443
|
+
};
|
|
12444
|
+
const follow = cls(code[gapIp + 3]).replaceAll("@", "gq");
|
|
12445
|
+
const other = code[gapIp + 4] >= 0 ? cls(code[gapIp + 4]).replaceAll("@", "itemStart") : "true";
|
|
12446
|
+
if (shape !== null) {
|
|
12447
|
+
let n = 0;
|
|
12448
|
+
const q2 = tmp();
|
|
12449
|
+
const m = emitShapeMatch(shape, "itemStart", (prefix = "_v") => `${q2}${prefix}${n++}`, "");
|
|
12450
|
+
gapCode = (rbCode) => `let gapped=false
|
|
12451
|
+
if(ctx._probe===undefined){
|
|
12452
|
+
${m.setup.join("\n")}
|
|
12453
|
+
const gq=${m.ok}?${m.end}:-1
|
|
12454
|
+
if((gq<0||${follow})&&${other}){
|
|
12455
|
+
${rbCode}
|
|
12456
|
+
break
|
|
12457
|
+
}
|
|
12458
|
+
}
|
|
12459
|
+
`;
|
|
12460
|
+
} else {
|
|
12461
|
+
const re = hoist("gr", `K[${code[row + 1]}]`);
|
|
12462
|
+
gapCode = (rbCode) => `let gapped=false
|
|
12463
|
+
if(ctx._probe===undefined){
|
|
12464
|
+
${re}.lastIndex=itemStart
|
|
12465
|
+
const gq=${re}.test(input)?${re}.lastIndex:-1
|
|
12466
|
+
if((gq<0||${follow})&&${other}){
|
|
12467
|
+
${rbCode}
|
|
12468
|
+
break
|
|
12469
|
+
}
|
|
12470
|
+
if(gq>=0){
|
|
12471
|
+
GAP.row=${row};GAP.at=itemStart;GAP.end=gq;GAP.input=input
|
|
12472
|
+
gapped=true
|
|
12473
|
+
}
|
|
12474
|
+
}
|
|
12475
|
+
`;
|
|
12476
|
+
}
|
|
12477
|
+
}
|
|
12478
|
+
const sepMiss = (at) => sepAscii ? `${sepCls}.ascii[input.charCodeAt(${at})]!==1` : `!classHas(${sepCls},lead(input,${at}))`;
|
|
11893
12479
|
const skipBeforeFirst = sepIp < 0 && min === 0;
|
|
11894
12480
|
const p = tmp();
|
|
11895
12481
|
const via = sep2 !== void 0 ? "false" : min === 0 ? skipBeforeFirst ? "true" : "count>0" : `count>=${min}&&count>0`;
|
|
@@ -11927,7 +12513,7 @@ ${p}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
|
11927
12513
|
${p}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${markSinks}
|
|
11928
12514
|
}`;
|
|
11929
12515
|
const my = `${p}my`;
|
|
11930
|
-
const recFx = REC2 ? fxRef(code[ip + 6])
|
|
12516
|
+
const recFx = !REC2 ? "" : (flags & 16) !== 0 ? "[]" : fxRef(code[ip + 6]);
|
|
11931
12517
|
const sepSent = REC2 ? sentRef(code[ip + 7]) : "undefined";
|
|
11932
12518
|
const recSent = sep2 === void 0 ? my : sepSent === "undefined" ? `orSentinel(${my},undefined)` : `orSentinel(${sepSent}??${my},${sepSent}===undefined?undefined:${my})`;
|
|
11933
12519
|
const recGate = sep2 !== void 0 || min === 0 ? "" : `count>=${min}&&`;
|
|
@@ -11943,7 +12529,7 @@ continue
|
|
|
11943
12529
|
return `${head}
|
|
11944
12530
|
const out=${collect ? "[]" : "undefined"}
|
|
11945
12531
|
${knownTrivia === void 0 ? "const hasTrivia=ctx.trivia!==undefined\n" : ""}${L.buf ? "" : "const needMark=_rollbackNeeded(ctx)\n"}${REC2 ? `const ${my}=ctx._sync
|
|
11946
|
-
` : ""}${itemCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
|
|
12532
|
+
` : ""}${itemCls === void 0 && sepCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
|
|
11947
12533
|
`}let cur=pos
|
|
11948
12534
|
let count=0
|
|
11949
12535
|
for(;;){
|
|
@@ -11959,6 +12545,10 @@ const lb=cstLeavesLen(ctx)
|
|
|
11959
12545
|
let sp=cur
|
|
11960
12546
|
${hasTrivia === "false" ? "" : hasTrivia === "true" ? `sp=${skip}(input,sp,ctx)
|
|
11961
12547
|
` : `if(hasTrivia)sp=${skip}(input,sp,ctx)
|
|
12548
|
+
`}${sepCls === void 0 ? "" : `if(count>=${min}&&${p}gate&&${sepMiss("sp")}){
|
|
12549
|
+
${rb}
|
|
12550
|
+
break
|
|
12551
|
+
}
|
|
11962
12552
|
`}ctx._fc=false
|
|
11963
12553
|
${sepIp >= 0 && leadingTriviaFieldAt(code, k, sepIp) ? "LEAD.at=cur\n" : ""}const sv=${sep2}(input,sp,ctx)
|
|
11964
12554
|
if(sv===FAIL){
|
|
@@ -11974,13 +12564,13 @@ itemStart=${hasTrivia === "false" ? "EC.e" : hasTrivia === "true" ? `${skip}(inp
|
|
|
11974
12564
|
${rb}
|
|
11975
12565
|
${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
|
|
11976
12566
|
}
|
|
11977
|
-
${itemCls === void 0 ? "" : `if(count>=${min}&&${p}gate&&${itemMiss("itemStart")}){
|
|
12567
|
+
${itemCls === void 0 || sep2 === void 0 && hasTrivia === "false" ? "" : `if(count>=${min}&&${p}gate&&${sep2 === void 0 && hasTrivia === "hasTrivia" ? "hasTrivia&&" : ""}${itemMiss("itemStart")}){
|
|
11978
12568
|
${rb}
|
|
11979
12569
|
${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
|
|
11980
12570
|
}
|
|
11981
|
-
`}ctx._fc=false
|
|
12571
|
+
`}${gapCode(rb)}ctx._fc=false
|
|
11982
12572
|
const v=${child}(input,itemStart,ctx)
|
|
11983
|
-
if(v===FAIL){
|
|
12573
|
+
${gapIp >= 0 ? "if(gapped)GAP.at=-1\n" : ""}if(v===FAIL){
|
|
11984
12574
|
${REC2 ? `if(ctx._fc===true){
|
|
11985
12575
|
${rb}
|
|
11986
12576
|
return FAIL
|
|
@@ -12796,6 +13386,9 @@ function clearOf(ranges, input, from, to) {
|
|
|
12796
13386
|
return true;
|
|
12797
13387
|
}
|
|
12798
13388
|
|
|
13389
|
+
// src/version.ts
|
|
13390
|
+
var PARSEMAN_VERSION = "0.60.0";
|
|
13391
|
+
|
|
12799
13392
|
// src/table/assemble.ts
|
|
12800
13393
|
import { PlainBuf as PlainBuf2, PlainField, PlainLeaf as PlainLeaf9, PlainNode as PlainNode2, PlainSpan as PlainSpan10 } from "../cst/plain.js";
|
|
12801
13394
|
|
|
@@ -12806,6 +13399,7 @@ function passChild(code, ip) {
|
|
|
12806
13399
|
case OP_LABEL:
|
|
12807
13400
|
case OP_COV:
|
|
12808
13401
|
case OP_TOKEN:
|
|
13402
|
+
case OP_GAPGATE:
|
|
12809
13403
|
return code[ip + 1];
|
|
12810
13404
|
case OP_GATE:
|
|
12811
13405
|
case OP_NODE:
|
|
@@ -13071,6 +13665,13 @@ function cfgKeyOf(hostCst, trackLines, tolerant, coverage, probe, hostReadsChild
|
|
|
13071
13665
|
function cfgKey(c) {
|
|
13072
13666
|
return cfgKeyOf(c.hostCst, c.trackLines, c.tolerant, c.coverage, c.probe, c.hostReadsChildren);
|
|
13073
13667
|
}
|
|
13668
|
+
function assertFactoryArity(pre) {
|
|
13669
|
+
if (pre.arity === EMITTED_PARAMS.length) return;
|
|
13670
|
+
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`;
|
|
13671
|
+
throw new Error(
|
|
13672
|
+
`parseman: this parser's printed assembly ${printed}. Reprint the parser with parseman ${PARSEMAN_VERSION}, or run it on the parseman version that printed it.`
|
|
13673
|
+
);
|
|
13674
|
+
}
|
|
13074
13675
|
function assemble(t, prog, cfg) {
|
|
13075
13676
|
const { code, k, fns, cc, fx, disp, dsp, trivia: trivia2, triviaLabelled } = t;
|
|
13076
13677
|
const triviaScan = t.triviaScan;
|
|
@@ -13105,6 +13706,8 @@ function assemble(t, prog, cfg) {
|
|
|
13105
13706
|
return recognize;
|
|
13106
13707
|
}
|
|
13107
13708
|
const labelExtraIps = assemblyExtraIps(prog);
|
|
13709
|
+
const GAP_ROWS = gapRows(code, [...Object.values(prog.rules), ...labelExtraIps]);
|
|
13710
|
+
const GAP = newGapSlot();
|
|
13108
13711
|
const closureLabels = computeSiteLabels(
|
|
13109
13712
|
code,
|
|
13110
13713
|
[...Object.values(prog.rules), ...labelExtraIps],
|
|
@@ -13323,6 +13926,27 @@ function assemble(t, prog, cfg) {
|
|
|
13323
13926
|
return node2;
|
|
13324
13927
|
};
|
|
13325
13928
|
}
|
|
13929
|
+
function gapRegexPiece(row, re, xf, track) {
|
|
13930
|
+
return (input, pos, ctx) => {
|
|
13931
|
+
let e;
|
|
13932
|
+
if (GAP.row === row && GAP.at === pos && GAP.input === input) e = GAP.end;
|
|
13933
|
+
else {
|
|
13934
|
+
re.lastIndex = pos;
|
|
13935
|
+
e = re.test(input) ? re.lastIndex : -1;
|
|
13936
|
+
}
|
|
13937
|
+
if (e >= 0) {
|
|
13938
|
+
const v = input.slice(pos, e);
|
|
13939
|
+
if (cstCaptureActive(ctx)) pushLeaf(ctx, v, pos, e);
|
|
13940
|
+
if (track) trackLinesInto(ctx, input, e);
|
|
13941
|
+
EC.e = e;
|
|
13942
|
+
return v;
|
|
13943
|
+
}
|
|
13944
|
+
ctx._fe = pos;
|
|
13945
|
+
ctx._fx = xf;
|
|
13946
|
+
if (ctx._probe !== void 0) failAt(ctx, xf, pos);
|
|
13947
|
+
return FAIL;
|
|
13948
|
+
};
|
|
13949
|
+
}
|
|
13326
13950
|
function passCollapseNode(child, build, readsRaw) {
|
|
13327
13951
|
return (input, pos, ctx) => {
|
|
13328
13952
|
const v = child(input, pos, ctx);
|
|
@@ -13725,7 +14349,7 @@ function assemble(t, prog, cfg) {
|
|
|
13725
14349
|
return next?.(key);
|
|
13726
14350
|
};
|
|
13727
14351
|
}
|
|
13728
|
-
function dispatchBranch(child, usesRouted) {
|
|
14352
|
+
function dispatchBranch(child, usesRouted, commits = true) {
|
|
13729
14353
|
if (!usesRouted) {
|
|
13730
14354
|
return (input, _pos, selEnd, key, ctx) => {
|
|
13731
14355
|
const need = markCst(ctx);
|
|
@@ -13739,7 +14363,7 @@ function assemble(t, prog, cfg) {
|
|
|
13739
14363
|
const v = child(input, selEnd, ctx);
|
|
13740
14364
|
if (v === FAIL) {
|
|
13741
14365
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
13742
|
-
ctx._fc = true;
|
|
14366
|
+
if (commits) ctx._fc = true;
|
|
13743
14367
|
return FAIL;
|
|
13744
14368
|
}
|
|
13745
14369
|
return [key, v];
|
|
@@ -13757,7 +14381,7 @@ function assemble(t, prog, cfg) {
|
|
|
13757
14381
|
}
|
|
13758
14382
|
if (v === FAIL) {
|
|
13759
14383
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
13760
|
-
ctx._fc = true;
|
|
14384
|
+
if (commits) ctx._fc = true;
|
|
13761
14385
|
return FAIL;
|
|
13762
14386
|
}
|
|
13763
14387
|
return [key, v];
|
|
@@ -13998,6 +14622,7 @@ function assemble(t, prog, cfg) {
|
|
|
13998
14622
|
case OP_RX: {
|
|
13999
14623
|
const re = k[code[ip + 1]];
|
|
14000
14624
|
const xf = fx[code[ip + 2]];
|
|
14625
|
+
if (GAP_ROWS.has(ip)) return gapRegexPiece(ip, re, xf, false);
|
|
14001
14626
|
const shared = rawScalarSpecs.has(code[ip + 1]) ? scalarFor(ip) : void 0;
|
|
14002
14627
|
if (shared !== void 0) {
|
|
14003
14628
|
return (input, pos, ctx) => {
|
|
@@ -14032,6 +14657,7 @@ function assemble(t, prog, cfg) {
|
|
|
14032
14657
|
case OP_RX_TRACK: {
|
|
14033
14658
|
const re = k[code[ip + 1]];
|
|
14034
14659
|
const xf = fx[code[ip + 2]];
|
|
14660
|
+
if (GAP_ROWS.has(ip)) return gapRegexPiece(ip, re, xf, true);
|
|
14035
14661
|
return (input, pos, ctx) => {
|
|
14036
14662
|
re.lastIndex = pos;
|
|
14037
14663
|
if (re.test(input)) {
|
|
@@ -14162,6 +14788,12 @@ function assemble(t, prog, cfg) {
|
|
|
14162
14788
|
return v;
|
|
14163
14789
|
};
|
|
14164
14790
|
}
|
|
14791
|
+
// Transparent: only the repeat holding it reads its operands.
|
|
14792
|
+
case OP_GAPGATE:
|
|
14793
|
+
return link(code[ip + 1]);
|
|
14794
|
+
// One encoding per assembly: strict, or the construct as written.
|
|
14795
|
+
case OP_STRICT:
|
|
14796
|
+
return link(code[cfg.tolerant || cfg.probe ? ip + 2 : ip + 1]);
|
|
14165
14797
|
case OP_RULE:
|
|
14166
14798
|
return link(code[ip + 1]);
|
|
14167
14799
|
case OP_LIVE: {
|
|
@@ -15087,7 +15719,7 @@ function assemble(t, prog, cfg) {
|
|
|
15087
15719
|
if (table.exclusive) {
|
|
15088
15720
|
const ascii = table.ascii;
|
|
15089
15721
|
const hi = table.hi;
|
|
15090
|
-
if (n === 2) {
|
|
15722
|
+
if (n === 2 && !cfg.probe) {
|
|
15091
15723
|
const a0 = link(code[base]), a1 = link(code[base + 1]);
|
|
15092
15724
|
return (input, pos, ctx) => {
|
|
15093
15725
|
const c = lead(input, pos);
|
|
@@ -15119,7 +15751,7 @@ function assemble(t, prog, cfg) {
|
|
|
15119
15751
|
return FAIL;
|
|
15120
15752
|
};
|
|
15121
15753
|
}
|
|
15122
|
-
if (n === 3) {
|
|
15754
|
+
if (n === 3 && !cfg.probe) {
|
|
15123
15755
|
const a0 = link(code[base]), a1 = link(code[base + 1]), a2 = link(code[base + 2]);
|
|
15124
15756
|
return (input, pos, ctx) => {
|
|
15125
15757
|
const c = lead(input, pos);
|
|
@@ -15164,6 +15796,7 @@ function assemble(t, prog, cfg) {
|
|
|
15164
15796
|
);
|
|
15165
15797
|
};
|
|
15166
15798
|
const selected = bindExclusive(0);
|
|
15799
|
+
const probeArms = cfg.probe ? Array.from({ length: n }, (_, i) => link(code[base + i])) : void 0;
|
|
15167
15800
|
return (input, pos, ctx) => {
|
|
15168
15801
|
const c = lead(input, pos);
|
|
15169
15802
|
let arm = -1;
|
|
@@ -15189,12 +15822,13 @@ function assemble(t, prog, cfg) {
|
|
|
15189
15822
|
return FAIL;
|
|
15190
15823
|
}
|
|
15191
15824
|
}
|
|
15825
|
+
if (arm < 0 && probeArms !== void 0) for (const a of probeArms) a(input, pos, ctx);
|
|
15192
15826
|
ctx._fe = pos;
|
|
15193
15827
|
ctx._fx = choiceFx;
|
|
15194
15828
|
return FAIL;
|
|
15195
15829
|
};
|
|
15196
15830
|
}
|
|
15197
|
-
const armCls = table.armCls;
|
|
15831
|
+
const armCls = cfg.probe ? table.armCls.map(() => null) : table.armCls;
|
|
15198
15832
|
if (n === 2 || n === 3) {
|
|
15199
15833
|
const a0 = link(code[base]), a1 = link(code[base + 1]);
|
|
15200
15834
|
const a2 = n === 3 ? link(code[base + 2]) : void 0;
|
|
@@ -15614,6 +16248,43 @@ function assemble(t, prog, cfg) {
|
|
|
15614
16248
|
return child(input, pos, ctx);
|
|
15615
16249
|
};
|
|
15616
16250
|
}
|
|
16251
|
+
case OP_RGATE2: {
|
|
16252
|
+
const cls = cc[code[ip + 1]];
|
|
16253
|
+
const xf = fx[code[ip + 3]];
|
|
16254
|
+
const first = cc[code[ip + 4]];
|
|
16255
|
+
const second = cc[code[ip + 5]];
|
|
16256
|
+
const child = link(code[ip + 2]);
|
|
16257
|
+
if (cfg.tolerant || cfg.probe) return child;
|
|
16258
|
+
if (cls.hi.length === 0 && first.hi.length === 0 && second.hi.length === 0) {
|
|
16259
|
+
const a0 = cls.ascii, a1 = first.ascii, a2 = second.ascii;
|
|
16260
|
+
return (input, pos, ctx) => {
|
|
16261
|
+
const item = ctx._routed;
|
|
16262
|
+
if (item !== void 0 && item.span.start === pos) {
|
|
16263
|
+
const e = item.span.end;
|
|
16264
|
+
const c = input.charCodeAt(e);
|
|
16265
|
+
if (a0[c] !== 1 || a1[c] === 1 && a2[input.charCodeAt(e + 1)] !== 1) {
|
|
16266
|
+
ctx._fe = e;
|
|
16267
|
+
ctx._fx = xf;
|
|
16268
|
+
return FAIL;
|
|
16269
|
+
}
|
|
16270
|
+
}
|
|
16271
|
+
return child(input, pos, ctx);
|
|
16272
|
+
};
|
|
16273
|
+
}
|
|
16274
|
+
return (input, pos, ctx) => {
|
|
16275
|
+
const item = ctx._routed;
|
|
16276
|
+
if (item !== void 0 && item.span.start === pos) {
|
|
16277
|
+
const e = item.span.end;
|
|
16278
|
+
const c = lead(input, e);
|
|
16279
|
+
if (!classHas2(cls, c) || classHas2(first, c) && !classHas2(second, lead(input, e + 1))) {
|
|
16280
|
+
ctx._fe = e;
|
|
16281
|
+
ctx._fx = xf;
|
|
16282
|
+
return FAIL;
|
|
16283
|
+
}
|
|
16284
|
+
}
|
|
16285
|
+
return child(input, pos, ctx);
|
|
16286
|
+
};
|
|
16287
|
+
}
|
|
15617
16288
|
case OP_ARMGATE: {
|
|
15618
16289
|
const pred = fns[code[ip + 1]];
|
|
15619
16290
|
const child = link(code[ip + 2]);
|
|
@@ -15681,10 +16352,18 @@ function assemble(t, prog, cfg) {
|
|
|
15681
16352
|
const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
|
|
15682
16353
|
const itemClass = !REC2 && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
|
|
15683
16354
|
const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
|
|
16355
|
+
const sepClassIndex = sepIp >= 0 && !sepLeads && (flags & 8) !== 0 ? code[ip + 8] : -1;
|
|
16356
|
+
const sepClass = !REC2 && sepClassIndex >= 0 && !rowNullable(code, k, sepIp, NULLABLE) ? cc[sepClassIndex] : void 0;
|
|
16357
|
+
const gapIp = sepIp < 0 && min === 0 && !REC2 && code[code[ip + 1]] === OP_GAPGATE ? code[ip + 1] : -1;
|
|
16358
|
+
const gapRow = gapIp >= 0 ? code[gapIp + 2] : -1;
|
|
16359
|
+
const gapRe = gapIp >= 0 ? k[code[gapRow + 1]] : void 0;
|
|
16360
|
+
const gapFollow = gapIp >= 0 ? cc[code[gapIp + 3]] : void 0;
|
|
16361
|
+
const gapOther = gapIp >= 0 && code[gapIp + 4] >= 0 ? cc[code[gapIp + 4]] : void 0;
|
|
15684
16362
|
const skipBeforeFirst = sepIp < 0 && min === 0;
|
|
15685
16363
|
const itemClean = sepIp < 0 && CLEAN(code[ip + 1]) && !rowNullable(code, k, code[ip + 1], NULLABLE);
|
|
15686
16364
|
if (REC2) {
|
|
15687
16365
|
const itemFx2 = fx[code[ip + 6]];
|
|
16366
|
+
const recFx = (flags & 16) !== 0 ? EMPTY_FX2 : itemFx2;
|
|
15688
16367
|
const sepSent = sentinelFor(code[ip + 7]);
|
|
15689
16368
|
return (input, pos, ctx) => {
|
|
15690
16369
|
const out = collect ? [] : void 0;
|
|
@@ -15744,7 +16423,7 @@ function assemble(t, prog, cfg) {
|
|
|
15744
16423
|
itemStart,
|
|
15745
16424
|
ctx,
|
|
15746
16425
|
sep2 === void 0 ? mySync : orSentinel(sepSent ?? mySync, sepSent === void 0 ? void 0 : mySync),
|
|
15747
|
-
|
|
16426
|
+
recFx
|
|
15748
16427
|
);
|
|
15749
16428
|
if (out !== void 0) out.push(rr.error);
|
|
15750
16429
|
captureError(ctx, rr.error);
|
|
@@ -15782,6 +16461,7 @@ function assemble(t, prog, cfg) {
|
|
|
15782
16461
|
const markLater = needMark && (!itemClean || hasTrivia);
|
|
15783
16462
|
const markFirst = needMark && (!itemClean || hasTrivia && skipBeforeFirst);
|
|
15784
16463
|
const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
|
|
16464
|
+
const gateSep = sepClass !== void 0 && ctx._probe === void 0;
|
|
15785
16465
|
let cur = pos;
|
|
15786
16466
|
let count = 0;
|
|
15787
16467
|
for (; ; ) {
|
|
@@ -15804,6 +16484,10 @@ function assemble(t, prog, cfg) {
|
|
|
15804
16484
|
const leavesBefore = cstLeavesLen(ctx);
|
|
15805
16485
|
let sp = cur;
|
|
15806
16486
|
if (hasTrivia) sp = skipTrivia(input, sp, ctx);
|
|
16487
|
+
if (count >= min && gateSep && !classHas2(sepClass, lead(input, sp))) {
|
|
16488
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
16489
|
+
break;
|
|
16490
|
+
}
|
|
15807
16491
|
ctx._fc = false;
|
|
15808
16492
|
if (sepLeads) LEAD.at = cur;
|
|
15809
16493
|
const sv = sep2(input, sp, ctx);
|
|
@@ -15823,13 +16507,30 @@ function assemble(t, prog, cfg) {
|
|
|
15823
16507
|
if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
|
|
15824
16508
|
break;
|
|
15825
16509
|
}
|
|
15826
|
-
if (count >= min && gateItems && !itemMayStart(input, itemStart)) {
|
|
16510
|
+
if (count >= min && gateItems && (sep2 !== void 0 || hasTrivia) && !itemMayStart(input, itemStart)) {
|
|
15827
16511
|
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
15828
16512
|
if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
|
|
15829
16513
|
break;
|
|
15830
16514
|
}
|
|
16515
|
+
let gapped = false;
|
|
16516
|
+
if (gapRe !== void 0 && ctx._probe === void 0) {
|
|
16517
|
+
gapRe.lastIndex = itemStart;
|
|
16518
|
+
const q2 = gapRe.test(input) ? gapRe.lastIndex : -1;
|
|
16519
|
+
if ((q2 < 0 || !classHas2(gapFollow, lead(input, q2))) && (gapOther === void 0 || !classHas2(gapOther, lead(input, itemStart)))) {
|
|
16520
|
+
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
16521
|
+
break;
|
|
16522
|
+
}
|
|
16523
|
+
if (q2 >= 0) {
|
|
16524
|
+
GAP.row = gapRow;
|
|
16525
|
+
GAP.at = itemStart;
|
|
16526
|
+
GAP.end = q2;
|
|
16527
|
+
GAP.input = input;
|
|
16528
|
+
gapped = true;
|
|
16529
|
+
}
|
|
16530
|
+
}
|
|
15831
16531
|
ctx._fc = false;
|
|
15832
16532
|
const v = child(input, itemStart, ctx);
|
|
16533
|
+
if (gapped) GAP.at = -1;
|
|
15833
16534
|
if (v === FAIL) {
|
|
15834
16535
|
if (markIt) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
15835
16536
|
if (committed3(ctx)) return FAIL;
|
|
@@ -15861,7 +16562,8 @@ function assemble(t, prog, cfg) {
|
|
|
15861
16562
|
const selector = link(code[ip + 1]);
|
|
15862
16563
|
const otherIp = code[ip + 3];
|
|
15863
16564
|
const other = otherIp >= 0 ? link(otherIp) : void 0;
|
|
15864
|
-
const otherRouted = code[ip + 4] === 1;
|
|
16565
|
+
const otherRouted = (code[ip + 4] & 1) === 1;
|
|
16566
|
+
const otherCommits = (code[ip + 4] & 2) === 0;
|
|
15865
16567
|
const n = code[ip + 5];
|
|
15866
16568
|
const armBase = ip + 6;
|
|
15867
16569
|
const byKey = spec.byKey;
|
|
@@ -15909,7 +16611,7 @@ function assemble(t, prog, cfg) {
|
|
|
15909
16611
|
);
|
|
15910
16612
|
};
|
|
15911
16613
|
const runArm = n === 0 ? void 0 : bindArms(0);
|
|
15912
|
-
const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted);
|
|
16614
|
+
const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted, otherCommits);
|
|
15913
16615
|
return (input, pos, ctx) => {
|
|
15914
16616
|
const need = markCst(ctx);
|
|
15915
16617
|
const mRaw = MRAW;
|
|
@@ -16170,6 +16872,7 @@ function assemble(t, prog, cfg) {
|
|
|
16170
16872
|
}
|
|
16171
16873
|
const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
|
|
16172
16874
|
if (pre !== void 0) {
|
|
16875
|
+
assertFactoryArity(pre);
|
|
16173
16876
|
const pools = rebuildPools(t.cc, t.fx, t.disp, pre.plan);
|
|
16174
16877
|
emitted = pre.factory(
|
|
16175
16878
|
EC,
|
|
@@ -16181,7 +16884,6 @@ function assemble(t, prog, cfg) {
|
|
|
16181
16884
|
pools.classes,
|
|
16182
16885
|
pools.armExpected,
|
|
16183
16886
|
trivia2,
|
|
16184
|
-
trivia2.map((tv) => tv?._meta.triviaKindLabels),
|
|
16185
16887
|
triviaScan,
|
|
16186
16888
|
scansArr,
|
|
16187
16889
|
disp,
|
|
@@ -16205,7 +16907,6 @@ function assemble(t, prog, cfg) {
|
|
|
16205
16907
|
cstLeavesLen,
|
|
16206
16908
|
skipTriviaScanned,
|
|
16207
16909
|
needsDeferredTriviaCommit,
|
|
16208
|
-
scanTrivia,
|
|
16209
16910
|
advanceTrivia,
|
|
16210
16911
|
refuseUnclassifiedRootScope,
|
|
16211
16912
|
spanLines,
|
|
@@ -16219,8 +16920,6 @@ function assemble(t, prog, cfg) {
|
|
|
16219
16920
|
orSentinel,
|
|
16220
16921
|
captureError,
|
|
16221
16922
|
scalarRecognizers,
|
|
16222
|
-
commitTriviaScan,
|
|
16223
|
-
scanTriviaCompact,
|
|
16224
16923
|
t.lex,
|
|
16225
16924
|
adjacencyHolds,
|
|
16226
16925
|
t.lexPrograms,
|
|
@@ -16232,7 +16931,8 @@ function assemble(t, prog, cfg) {
|
|
|
16232
16931
|
PlainLeaf9,
|
|
16233
16932
|
PlainNode2,
|
|
16234
16933
|
PlainField,
|
|
16235
|
-
PlainBuf2
|
|
16934
|
+
PlainBuf2,
|
|
16935
|
+
GAP
|
|
16236
16936
|
);
|
|
16237
16937
|
emitReached = new Set(pre.reached);
|
|
16238
16938
|
if (emitted.ext !== void 0) HYBRID = emitted;
|
|
@@ -16268,7 +16968,6 @@ function assemble(t, prog, cfg) {
|
|
|
16268
16968
|
em.classes,
|
|
16269
16969
|
em.armExpected,
|
|
16270
16970
|
trivia2,
|
|
16271
|
-
trivia2.map((tv) => tv?._meta.triviaKindLabels),
|
|
16272
16971
|
triviaScan,
|
|
16273
16972
|
scansArr,
|
|
16274
16973
|
disp,
|
|
@@ -16292,7 +16991,6 @@ function assemble(t, prog, cfg) {
|
|
|
16292
16991
|
cstLeavesLen,
|
|
16293
16992
|
skipTriviaScanned,
|
|
16294
16993
|
needsDeferredTriviaCommit,
|
|
16295
|
-
scanTrivia,
|
|
16296
16994
|
advanceTrivia,
|
|
16297
16995
|
refuseUnclassifiedRootScope,
|
|
16298
16996
|
spanLines,
|
|
@@ -16311,8 +17009,6 @@ function assemble(t, prog, cfg) {
|
|
|
16311
17009
|
orSentinel,
|
|
16312
17010
|
captureError,
|
|
16313
17011
|
scalarRecognizers,
|
|
16314
|
-
commitTriviaScan,
|
|
16315
|
-
scanTriviaCompact,
|
|
16316
17012
|
t.lex,
|
|
16317
17013
|
adjacencyHolds,
|
|
16318
17014
|
t.lexPrograms,
|
|
@@ -16324,7 +17020,8 @@ function assemble(t, prog, cfg) {
|
|
|
16324
17020
|
PlainLeaf9,
|
|
16325
17021
|
PlainNode2,
|
|
16326
17022
|
PlainField,
|
|
16327
|
-
PlainBuf2
|
|
17023
|
+
PlainBuf2,
|
|
17024
|
+
GAP
|
|
16328
17025
|
);
|
|
16329
17026
|
emitReached = em.reached;
|
|
16330
17027
|
} catch (e) {
|
|
@@ -16593,11 +17290,8 @@ function tableRules(source, metadataOrEntry = {}) {
|
|
|
16593
17290
|
return map[entry];
|
|
16594
17291
|
}
|
|
16595
17292
|
|
|
16596
|
-
// src/version.ts
|
|
16597
|
-
var PARSEMAN_VERSION = "0.59.2";
|
|
16598
|
-
|
|
16599
17293
|
// src/table/emit.ts
|
|
16600
|
-
var FACTORY_ARITY_GUARD = `if(arguments.length
|
|
17294
|
+
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`)});`;
|
|
16601
17295
|
function jsString(s) {
|
|
16602
17296
|
return JSON.stringify(s);
|
|
16603
17297
|
}
|
|
@@ -16683,7 +17377,7 @@ function emitAssemblies(prog, cfgs) {
|
|
|
16683
17377
|
throw e;
|
|
16684
17378
|
}
|
|
16685
17379
|
const plan = em.plan;
|
|
16686
|
-
out.push(`{key:${key},factory:function(${EMITTED_PARAMS.join(",")}){${FACTORY_ARITY_GUARD}${em.source}
|
|
17380
|
+
out.push(`{key:${key},arity:${EMITTED_PARAMS.length},factory:function(${EMITTED_PARAMS.join(",")}){${FACTORY_ARITY_GUARD}${em.source}
|
|
16687
17381
|
},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(",")}]}`);
|
|
16688
17382
|
}
|
|
16689
17383
|
return [`a:[${out.join(",")}],`];
|
|
@@ -16959,7 +17653,7 @@ function payloadKey(p, d) {
|
|
|
16959
17653
|
case "sepBy":
|
|
16960
17654
|
return `sepBy\0${d.min}\0${d.max ?? ""}\0${d.trailing ?? ""}`;
|
|
16961
17655
|
case "dispatch":
|
|
16962
|
-
return `dispatch\0${d.cases.map((c) => JSON.stringify(c.keys)).join("")}\0${d.otherwise !== void 0}`;
|
|
17656
|
+
return `dispatch\0${d.cases.map((c) => JSON.stringify(c.keys)).join("")}\0${d.otherwise !== void 0}${d.otherwiseCommit === false ? "\0uncommitted" : ""}`;
|
|
16963
17657
|
case "expect":
|
|
16964
17658
|
return `expect\0${d.label ?? ""}\0${d.expected.join("")}`;
|
|
16965
17659
|
case "scanTo":
|
|
@@ -18265,7 +18959,10 @@ function staticWeights(code, entries) {
|
|
|
18265
18959
|
childSlots(code, ip, kids);
|
|
18266
18960
|
const op = code[ip];
|
|
18267
18961
|
const scale = op === OP_REP || op === OP_REPV ? LOOP : op === OP_CHOICE || op === OP_DISPATCH ? 1 / Math.max(1, kids.length) : 1;
|
|
18268
|
-
for (const
|
|
18962
|
+
for (const k of kids) {
|
|
18963
|
+
const kid = code[k] === OP_GAPGATE ? code[k + 1] : k;
|
|
18964
|
+
next.set(kid, Math.min(CAP, (next.get(kid) ?? 0) + w * scale));
|
|
18965
|
+
}
|
|
18269
18966
|
}
|
|
18270
18967
|
weight = next;
|
|
18271
18968
|
}
|
|
@@ -18382,7 +19079,7 @@ function compileRuleMap(ruleMap, opts = {}) {
|
|
|
18382
19079
|
const roots = assemblyExtraIps(artifact);
|
|
18383
19080
|
let siteBytes, fixed;
|
|
18384
19081
|
try {
|
|
18385
|
-
siteBytes = emitAssemblySource(table, artifact, cfg, roots, true, void 0, true).siteBytes;
|
|
19082
|
+
siteBytes = emitAssemblySource(table, artifact, cfg, roots, true, void 0, true, true).siteBytes;
|
|
18386
19083
|
fixed = emitAssemblySource(table, artifact, cfg, roots, true, /* @__PURE__ */ new Set(), true).source.length;
|
|
18387
19084
|
} catch (e) {
|
|
18388
19085
|
if (e instanceof Unemittable) return { ...none, refusal: e.construct };
|
|
@@ -18930,7 +19627,7 @@ ${outerDecls.map((d) => " " + d).join("\n")}
|
|
|
18930
19627
|
arms.push(`when(${matcherExpr(entry)}, ${kid(entry.parser)}${entry.caseInsensitive ? ", { caseInsensitive: true }" : ""})`);
|
|
18931
19628
|
}
|
|
18932
19629
|
}
|
|
18933
|
-
if (def.otherwise) arms.push(`otherwise(${kid(def.otherwise)})`);
|
|
19630
|
+
if (def.otherwise) arms.push(`otherwise(${kid(def.otherwise)}${def.otherwiseCommit === false ? ", { commit: false }" : ""})`);
|
|
18934
19631
|
return `dispatch(${kid(def.selector)}${arms.length === 0 ? "" : `, ${arms.join(", ")}`})`;
|
|
18935
19632
|
}
|
|
18936
19633
|
case "many":
|
|
@@ -19973,11 +20670,16 @@ function dispatchArmValue(node2, scope, code, mfs) {
|
|
|
19973
20670
|
return null;
|
|
19974
20671
|
}
|
|
19975
20672
|
if (callee.name === "otherwise") {
|
|
19976
|
-
const [parserArg] = node2.arguments;
|
|
19977
|
-
if (!parserArg || parserArg.type === "SpreadElement") return null;
|
|
20673
|
+
const [parserArg, optsArg] = node2.arguments;
|
|
20674
|
+
if (!parserArg || parserArg.type === "SpreadElement" || optsArg?.type === "SpreadElement") return null;
|
|
19978
20675
|
const parserValue = anyValue(parserArg, scope, code, mfs);
|
|
19979
20676
|
if (!isCombinator3(parserValue)) return null;
|
|
19980
|
-
return otherwise(parserValue);
|
|
20677
|
+
if (optsArg === void 0) return otherwise(parserValue);
|
|
20678
|
+
const opts = anyValue(optsArg, scope, code, mfs);
|
|
20679
|
+
if (typeof opts !== "object" || opts === null) return null;
|
|
20680
|
+
const commit = opts.commit;
|
|
20681
|
+
if (commit !== void 0 && typeof commit !== "boolean") return null;
|
|
20682
|
+
return otherwise(parserValue, commit === void 0 ? {} : { commit });
|
|
19981
20683
|
}
|
|
19982
20684
|
if (callee.name === "when") {
|
|
19983
20685
|
const [keyArg, parserArg, optsArg] = node2.arguments;
|