parseman 0.49.0 → 0.50.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analysis/commitment.d.ts +2 -1
- package/dist/analysis/commitment.d.ts.map +1 -1
- package/dist/analysis/diagnostics.js +1824 -737
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/analysis/rebuild.d.ts.map +1 -1
- package/dist/cli/index.js +1252 -164
- package/dist/cli/index.js.map +3 -3
- package/dist/combinators/trivia-skip.d.ts +1 -1
- package/dist/combinators/trivia-skip.d.ts.map +1 -1
- package/dist/compiler/build-arity.d.ts +16 -0
- package/dist/compiler/build-arity.d.ts.map +1 -1
- package/dist/compiler/degradation.d.ts +0 -2
- package/dist/compiler/degradation.d.ts.map +1 -1
- package/dist/compiler/ir-serialize.d.ts.map +1 -1
- package/dist/compiler/token-alphabet.d.ts +11 -0
- package/dist/compiler/token-alphabet.d.ts.map +1 -1
- package/dist/compiler/token-capability.js +185 -20
- package/dist/compiler/token-capability.js.map +1 -1
- package/dist/cst/capture-buffer.d.ts +5 -1
- package/dist/cst/capture-buffer.d.ts.map +1 -1
- package/dist/index.js +1365 -279
- package/dist/index.js.map +3 -3
- package/dist/language-service/index.js +2 -1
- package/dist/language-service/index.js.map +1 -1
- package/dist/plugin/entry-supercompiler.d.ts +48 -0
- package/dist/plugin/entry-supercompiler.d.ts.map +1 -0
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +1957 -385
- package/dist/plugin/index.js.map +3 -3
- package/dist/run/index.js +2 -1
- package/dist/run/index.js.map +1 -1
- package/dist/spec/index.js +28 -7
- package/dist/spec/index.js.map +1 -1
- package/dist/table/assemble.d.ts.map +1 -1
- package/dist/table/compile-rule-map.d.ts +6 -5
- package/dist/table/compile-rule-map.d.ts.map +1 -1
- package/dist/table/emit-assembly.d.ts +6 -1
- package/dist/table/emit-assembly.d.ts.map +1 -1
- package/dist/table/encode.d.ts.map +1 -1
- package/dist/table/index.js +1315 -231
- package/dist/table/index.js.map +3 -3
- package/dist/table/ops.d.ts +3 -2
- package/dist/table/ops.d.ts.map +1 -1
- package/dist/table/program.d.ts +15 -1
- package/dist/table/program.d.ts.map +1 -1
- package/dist/table/scalar-terminal.d.ts +30 -0
- package/dist/table/scalar-terminal.d.ts.map +1 -1
- package/dist/table/site-labels.d.ts +8 -0
- package/dist/table/site-labels.d.ts.map +1 -1
- package/dist/types.d.ts +2 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/analysis/commitment.ts +19 -8
- package/src/analysis/rebuild.ts +1 -0
- package/src/combinators/trivia-skip.ts +2 -2
- package/src/compiler/build-arity.ts +50 -0
- package/src/compiler/degradation.ts +0 -6
- package/src/compiler/ir-serialize.ts +6 -4
- package/src/compiler/token-alphabet.ts +322 -28
- package/src/cst/capture-buffer.ts +34 -11
- package/src/plugin/entry-supercompiler.ts +567 -0
- package/src/plugin/evaluator.ts +10 -0
- package/src/plugin/index.ts +7 -3
- package/src/table/assemble.ts +125 -42
- package/src/table/compile-rule-map.ts +8 -7
- package/src/table/compile.ts +7 -8
- package/src/table/emit-assembly.ts +646 -126
- package/src/table/emit.ts +1 -1
- package/src/table/encode.ts +152 -7
- package/src/table/ops.ts +3 -2
- package/src/table/program.ts +44 -3
- package/src/table/scalar-terminal.ts +213 -1
- package/src/table/site-labels.ts +22 -9
- package/src/types.ts +1 -1
- package/src/version.ts +1 -1
package/dist/plugin/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import * as fs2 from "node:fs";
|
|
3
3
|
import * as path2 from "node:path";
|
|
4
4
|
import { createUnplugin } from "unplugin";
|
|
5
|
-
import { parseSync as
|
|
5
|
+
import { parseSync as parseSync5 } from "oxc-parser";
|
|
6
6
|
import { ResolverFactory } from "oxc-resolver";
|
|
7
7
|
import MagicString from "magic-string";
|
|
8
8
|
|
|
@@ -27,9 +27,9 @@ function classifyFinalChoice(arms, resolve3) {
|
|
|
27
27
|
break;
|
|
28
28
|
}
|
|
29
29
|
let ownsHigh = false;
|
|
30
|
-
for (const
|
|
31
|
-
if (
|
|
32
|
-
for (let code = Math.max(0,
|
|
30
|
+
for (const range2 of first.ranges) {
|
|
31
|
+
if (range2.hi >= 128) ownsHigh = true;
|
|
32
|
+
for (let code = Math.max(0, range2.lo); code <= Math.min(127, range2.hi); code++) {
|
|
33
33
|
if (ascii[code] !== 0) {
|
|
34
34
|
exclusive = false;
|
|
35
35
|
break;
|
|
@@ -551,10 +551,10 @@ function beginCstNodeCapture(ctx) {
|
|
|
551
551
|
}
|
|
552
552
|
function finishCstBuf(buf) {
|
|
553
553
|
if (!buf) return { children: EMPTY, rawChildren: EMPTY, triviaLog: EMPTY_TL };
|
|
554
|
-
const
|
|
555
|
-
const rawChildren = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY);
|
|
554
|
+
const children3 = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY);
|
|
555
|
+
const rawChildren = buf.noRaw === true ? EMPTY : buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY);
|
|
556
556
|
const triviaLog = buf.tl ?? EMPTY_TL;
|
|
557
|
-
return { children:
|
|
557
|
+
return { children: children3, rawChildren, triviaLog };
|
|
558
558
|
}
|
|
559
559
|
function endCstNodeCapture(ctx, saved) {
|
|
560
560
|
const materialized = finishCstBuf(ctx._cstBuf);
|
|
@@ -584,7 +584,8 @@ function pushCstChild(ctx, built, rawEntry2) {
|
|
|
584
584
|
b.single = void 0;
|
|
585
585
|
} else b.single = built;
|
|
586
586
|
}
|
|
587
|
-
if (b.
|
|
587
|
+
if (b.noRaw === true) b.rawLen = (b.rawLen ?? 0) + 1;
|
|
588
|
+
else if (b.raw) b.raw.push(rawEntry2);
|
|
588
589
|
else if (b.rawSingle !== void 0) {
|
|
589
590
|
b.raw = [b.rawSingle, rawEntry2];
|
|
590
591
|
b.rawSingle = void 0;
|
|
@@ -598,6 +599,7 @@ function pushCstChild(ctx, built, rawEntry2) {
|
|
|
598
599
|
function cstRawLen(ctx) {
|
|
599
600
|
const b = ctx._cstBuf;
|
|
600
601
|
if (b) {
|
|
602
|
+
if (b.noRaw === true) return b.rawLen ?? 0;
|
|
601
603
|
if (b.raw) return b.raw.length;
|
|
602
604
|
return b.rawSingle !== void 0 ? 1 : 0;
|
|
603
605
|
}
|
|
@@ -657,19 +659,37 @@ function rollbackCstCaptureAt(ctx, raw, tlog, leaves, fields, errors) {
|
|
|
657
659
|
if (ctx._errors && errors !== void 0 && ctx._errors.length !== errors) ctx._errors.length = errors;
|
|
658
660
|
const b = ctx._cstBuf;
|
|
659
661
|
if (b) {
|
|
660
|
-
|
|
661
|
-
|
|
662
|
+
if (b.noRaw === true) {
|
|
663
|
+
if (b.rawLen !== raw) b.rawLen = raw;
|
|
664
|
+
} else {
|
|
665
|
+
const rawList = b.raw;
|
|
666
|
+
if (rawList) {
|
|
667
|
+
if (raw === 0) b.raw = void 0;
|
|
668
|
+
else if (raw === 1) {
|
|
669
|
+
b.rawSingle = rawList[0];
|
|
670
|
+
b.raw = void 0;
|
|
671
|
+
} else if (rawList.length !== raw) rawList.length = raw;
|
|
672
|
+
} else if (raw === 0) b.rawSingle = void 0;
|
|
673
|
+
}
|
|
674
|
+
const childList = b.ch;
|
|
675
|
+
if (childList) {
|
|
676
|
+
if (leaves === 0) b.ch = void 0;
|
|
677
|
+
else if (leaves === 1) {
|
|
678
|
+
b.single = childList[0];
|
|
679
|
+
b.ch = void 0;
|
|
680
|
+
} else if (childList.length !== leaves) childList.length = leaves;
|
|
681
|
+
} else if (leaves === 0) b.single = void 0;
|
|
662
682
|
if (b.tl) {
|
|
663
683
|
if (tlog === 0) b.tl = void 0;
|
|
664
684
|
else if (b.tl.length !== tlog) b.tl.length = tlog;
|
|
665
685
|
}
|
|
666
|
-
if (ctx._fields && ctx._fields.length !== fields) ctx._fields.length = fields;
|
|
686
|
+
if (ctx._fields && fields !== void 0 && ctx._fields.length !== fields) ctx._fields.length = fields;
|
|
667
687
|
return;
|
|
668
688
|
}
|
|
669
689
|
if (ctx._cstRawChildren && ctx._cstRawChildren.length !== raw) ctx._cstRawChildren.length = raw;
|
|
670
690
|
if (ctx._cstTriviaLog && ctx._cstTriviaLog.length !== tlog) ctx._cstTriviaLog.length = tlog;
|
|
671
691
|
if (ctx._cstLeaves && ctx._cstLeaves.length !== leaves) ctx._cstLeaves.length = leaves;
|
|
672
|
-
if (ctx._fields && ctx._fields.length !== fields) ctx._fields.length = fields;
|
|
692
|
+
if (ctx._fields && fields !== void 0 && ctx._fields.length !== fields) ctx._fields.length = fields;
|
|
673
693
|
}
|
|
674
694
|
function pushCstTriviaEntry(ctx, start, end, kindIndex) {
|
|
675
695
|
const insertIdx = cstRawLen(ctx);
|
|
@@ -2158,15 +2178,22 @@ function canConsumeNewline(n) {
|
|
|
2158
2178
|
return n.parts.some(canConsumeNewline);
|
|
2159
2179
|
}
|
|
2160
2180
|
}
|
|
2181
|
+
function regexCanMatchEmpty(source) {
|
|
2182
|
+
try {
|
|
2183
|
+
return nullable(parseRegex(source));
|
|
2184
|
+
} catch {
|
|
2185
|
+
return true;
|
|
2186
|
+
}
|
|
2187
|
+
}
|
|
2161
2188
|
function firstSetFromRegex(source) {
|
|
2162
|
-
let
|
|
2189
|
+
let ast2;
|
|
2163
2190
|
try {
|
|
2164
|
-
|
|
2191
|
+
ast2 = parseRegex(source);
|
|
2165
2192
|
} catch {
|
|
2166
2193
|
return { firstSet: any(), canMatchNewline: true };
|
|
2167
2194
|
}
|
|
2168
|
-
if (nullable(
|
|
2169
|
-
return { firstSet: firstSet(
|
|
2195
|
+
if (nullable(ast2)) return { firstSet: any(), canMatchNewline: canConsumeNewline(ast2) };
|
|
2196
|
+
return { firstSet: firstSet(ast2), canMatchNewline: canConsumeNewline(ast2) };
|
|
2170
2197
|
}
|
|
2171
2198
|
|
|
2172
2199
|
// src/combinators/regex.ts
|
|
@@ -3789,21 +3816,21 @@ function when(key, parser2, opts = {}) {
|
|
|
3789
3816
|
function otherwise(parser2) {
|
|
3790
3817
|
return { kind: "otherwise", parser: parser2, usesRouted: parserUsesRouted(parser2) };
|
|
3791
3818
|
}
|
|
3792
|
-
function routed(
|
|
3819
|
+
function routed(fallback2) {
|
|
3793
3820
|
return {
|
|
3794
3821
|
_tag: "routed",
|
|
3795
3822
|
_meta: {
|
|
3796
3823
|
// The routed token is whatever the selector matched, so the first set stays
|
|
3797
3824
|
// `any` even with a fallback — `any` already subsumes the fallback's.
|
|
3798
3825
|
firstSet: { kind: "any" },
|
|
3799
|
-
canMatchNewline:
|
|
3826
|
+
canMatchNewline: fallback2?._meta.canMatchNewline ?? false,
|
|
3800
3827
|
isTrivia: false
|
|
3801
3828
|
},
|
|
3802
|
-
_def:
|
|
3829
|
+
_def: fallback2 === void 0 ? { tag: "routed" } : { tag: "routed", fallback: fallback2 },
|
|
3803
3830
|
parse(_input, pos, ctx) {
|
|
3804
3831
|
const item = ctx._routed;
|
|
3805
3832
|
if (item === void 0 || pos !== item.span.start) {
|
|
3806
|
-
if (
|
|
3833
|
+
if (fallback2 !== void 0) return fallback2.parse(_input, pos, ctx);
|
|
3807
3834
|
return { ok: false, expected: ["routed()"], span: { start: pos, end: pos } };
|
|
3808
3835
|
}
|
|
3809
3836
|
if (cstCaptureActive(ctx)) {
|
|
@@ -3817,7 +3844,7 @@ function dispatch(selector, ...arms) {
|
|
|
3817
3844
|
if (parserUsesRouted(selector)) {
|
|
3818
3845
|
throw new Error("parseman: routed() can only appear inside a dispatch() branch");
|
|
3819
3846
|
}
|
|
3820
|
-
let
|
|
3847
|
+
let fallback2;
|
|
3821
3848
|
let fallbackUsesRouted = false;
|
|
3822
3849
|
const matchers = [];
|
|
3823
3850
|
const cases = [];
|
|
@@ -3825,9 +3852,9 @@ function dispatch(selector, ...arms) {
|
|
|
3825
3852
|
for (let i = 0; i < arms.length; i++) {
|
|
3826
3853
|
const arm = arms[i];
|
|
3827
3854
|
if (arm.kind === "otherwise") {
|
|
3828
|
-
if (
|
|
3855
|
+
if (fallback2 !== void 0) throw new Error("parseman: dispatch() accepts at most one otherwise() arm");
|
|
3829
3856
|
if (i !== arms.length - 1) throw new Error("parseman: otherwise() must be the last dispatch() arm");
|
|
3830
|
-
|
|
3857
|
+
fallback2 = arm.parser;
|
|
3831
3858
|
fallbackUsesRouted = arm.usesRouted === true;
|
|
3832
3859
|
continue;
|
|
3833
3860
|
}
|
|
@@ -3860,7 +3887,7 @@ function dispatch(selector, ...arms) {
|
|
|
3860
3887
|
}
|
|
3861
3888
|
const meta = {
|
|
3862
3889
|
firstSet: selector._meta.firstSet,
|
|
3863
|
-
canMatchNewline: selector._meta.canMatchNewline || cases.some((entry) => entry.parser._meta.canMatchNewline) || matchers.some((entry) => entry.parser._meta.canMatchNewline) || (
|
|
3890
|
+
canMatchNewline: selector._meta.canMatchNewline || cases.some((entry) => entry.parser._meta.canMatchNewline) || matchers.some((entry) => entry.parser._meta.canMatchNewline) || (fallback2?._meta.canMatchNewline ?? false),
|
|
3864
3891
|
isTrivia: false
|
|
3865
3892
|
};
|
|
3866
3893
|
const byKey = /* @__PURE__ */ new Map();
|
|
@@ -3879,7 +3906,7 @@ function dispatch(selector, ...arms) {
|
|
|
3879
3906
|
selector,
|
|
3880
3907
|
cases,
|
|
3881
3908
|
...matchers.length === 0 ? {} : { matchers },
|
|
3882
|
-
...
|
|
3909
|
+
...fallback2 === void 0 ? {} : { otherwise: fallback2, ...fallbackUsesRouted ? { otherwiseUsesRouted: true } : {} }
|
|
3883
3910
|
},
|
|
3884
3911
|
parse(input, pos, ctx) {
|
|
3885
3912
|
if (parserUsesRouted(selector)) {
|
|
@@ -3888,7 +3915,7 @@ function dispatch(selector, ...arms) {
|
|
|
3888
3915
|
const selectorMark = saveTriviaMark(ctx);
|
|
3889
3916
|
const selected = selector.parse(input, pos, ctx);
|
|
3890
3917
|
if (!selected.ok) return selected;
|
|
3891
|
-
const branch = byKey.get(selected.value) ?? (byFoldedKey.size === 0 ? void 0 : byFoldedKey.get(asciiFoldKey(selected.value))) ?? matchers.find((matcher) => matchesDispatchMatcher(selected.value, matcher)) ?? (
|
|
3918
|
+
const branch = byKey.get(selected.value) ?? (byFoldedKey.size === 0 ? void 0 : byFoldedKey.get(asciiFoldKey(selected.value))) ?? matchers.find((matcher) => matchesDispatchMatcher(selected.value, matcher)) ?? (fallback2 === void 0 ? void 0 : { keys: [], parser: fallback2, caseInsensitive: false, usesRouted: fallbackUsesRouted });
|
|
3892
3919
|
if (branch === void 0) {
|
|
3893
3920
|
const expected = cases.flatMap((entry) => entry.keys.map((key) => JSON.stringify(key)));
|
|
3894
3921
|
return { ok: false, expected, span: { start: selected.span.end, end: selected.span.end } };
|
|
@@ -4385,6 +4412,7 @@ var SINGLE_IDENT_ARROW_RE = /^[A-Za-z_$][\w$]*\s*=>/;
|
|
|
4385
4412
|
var PARAM_LIST_OPEN_RE = /^(?:function\b[^(]*)?\(/;
|
|
4386
4413
|
var NATIVE_CODE_RE = /\{\s*\[native code\]\s*\}/;
|
|
4387
4414
|
var PARAM_HEAD_RE = /^[A-Za-z_$][\w$]*\s*\??\s*/;
|
|
4415
|
+
var PARAM_NAME_RE = /^([A-Za-z_$][\w$]*)\s*\??\s*/;
|
|
4388
4416
|
function confirmedBuildArity(src) {
|
|
4389
4417
|
const s = src.trim();
|
|
4390
4418
|
if (NATIVE_CODE_RE.test(s)) return null;
|
|
@@ -4400,6 +4428,34 @@ function confirmedBuildArity(src) {
|
|
|
4400
4428
|
}
|
|
4401
4429
|
return parts.length;
|
|
4402
4430
|
}
|
|
4431
|
+
function confirmedBuildParamUnused(src, index) {
|
|
4432
|
+
if (!Number.isInteger(index) || index < 0) return false;
|
|
4433
|
+
const s = src.trim();
|
|
4434
|
+
if (NATIVE_CODE_RE.test(s) || /\b(?:arguments|eval|Function)\b/.test(s) || /\bwith\s*\(/.test(s)) return false;
|
|
4435
|
+
let names;
|
|
4436
|
+
const single = /^([A-Za-z_$][\w$]*)\s*=>/.exec(s);
|
|
4437
|
+
if (single) {
|
|
4438
|
+
names = [single[1]];
|
|
4439
|
+
} else {
|
|
4440
|
+
const inner = paramListText(s);
|
|
4441
|
+
if (inner === null || inner.trim() === "") return false;
|
|
4442
|
+
const parts = splitTopLevel(inner);
|
|
4443
|
+
if (parts === null) return false;
|
|
4444
|
+
names = [];
|
|
4445
|
+
for (const part of parts) {
|
|
4446
|
+
const trimmed = part.trim();
|
|
4447
|
+
if (!isConfirmableParam(trimmed)) return false;
|
|
4448
|
+
const name2 = PARAM_NAME_RE.exec(trimmed)?.[1];
|
|
4449
|
+
if (name2 === void 0) return false;
|
|
4450
|
+
names.push(name2);
|
|
4451
|
+
}
|
|
4452
|
+
}
|
|
4453
|
+
const name = names[index];
|
|
4454
|
+
if (name === void 0) return false;
|
|
4455
|
+
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4456
|
+
const uses = s.match(new RegExp(`(^|[^A-Za-z0-9_$])${escaped}(?=$|[^A-Za-z0-9_$])`, "g"));
|
|
4457
|
+
return uses?.length === 1;
|
|
4458
|
+
}
|
|
4403
4459
|
function paramListText(s) {
|
|
4404
4460
|
const open = PARAM_LIST_OPEN_RE.exec(s);
|
|
4405
4461
|
if (!open) return null;
|
|
@@ -4537,6 +4593,7 @@ function confirmedArityForDef(def) {
|
|
|
4537
4593
|
}
|
|
4538
4594
|
function buildReadsRaw(def) {
|
|
4539
4595
|
if (!def.build) return true;
|
|
4596
|
+
if (def.buildRawUnused === true) return false;
|
|
4540
4597
|
const arity = confirmedArityForDef(def);
|
|
4541
4598
|
if (arity === null) return true;
|
|
4542
4599
|
return arity >= 4;
|
|
@@ -4647,11 +4704,11 @@ function normalizeProject(project) {
|
|
|
4647
4704
|
}
|
|
4648
4705
|
return project;
|
|
4649
4706
|
}
|
|
4650
|
-
function projectChild(
|
|
4651
|
-
if (!(project in
|
|
4707
|
+
function projectChild(children3, project, type) {
|
|
4708
|
+
if (!(project in children3)) {
|
|
4652
4709
|
throw new Error(`node(${JSON.stringify(type)}) project child ${project} was not captured`);
|
|
4653
4710
|
}
|
|
4654
|
-
return unwrapChild(
|
|
4711
|
+
return unwrapChild(children3[project]);
|
|
4655
4712
|
}
|
|
4656
4713
|
function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
4657
4714
|
const hasExplicitType = typeof typeOrCombinator === "string";
|
|
@@ -4723,14 +4780,14 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
4723
4780
|
const fields = effFields ? buildFieldMap(ctx._fields) : void 0;
|
|
4724
4781
|
ctx._fields = savedFields;
|
|
4725
4782
|
ctx._triviaCaptureMask = savedMask;
|
|
4726
|
-
const { children:
|
|
4783
|
+
const { children: children3, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
|
|
4727
4784
|
if (!r.ok) return r;
|
|
4728
4785
|
const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
|
|
4729
4786
|
const nodeType = def.type ?? missingInferredType();
|
|
4730
4787
|
const cstOutput = cstOutputHost(ctx.build);
|
|
4731
4788
|
const span = ctx.trackLines ? annotateSpanFromLineContext(r.span, ctx) : r.span;
|
|
4732
4789
|
const hostState = clonesState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
|
|
4733
|
-
const built = unwrap &&
|
|
4790
|
+
const built = unwrap && children3.length === 1 ? unwrapChild(children3[0]) : collapse && children3.length === 1 ? children3[0] : (cstOutput || !build && project === void 0) && ctx.build?._parsemanCstCollapse && children3.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children3[0], children3, rawChildren) ? children3[0] : project !== void 0 ? cstOutput && ctx.build ? ctx.build(nodeType, children3, fields, span, rawChildren, triviaLog, hostState, tags) : projectChild(children3, project, nodeType) : build ? cstOutput && ctx.build ? ctx.build(nodeType, children3, fields, span, rawChildren, triviaLog, hostState, tags) : build(children3, fields, span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children3, fields, span, rawChildren, triviaLog, st, tags) : { _tag: "node", type: nodeType, span: ctx.trackLines ? { ...span } : { start: r.span.start, end: r.span.end }, state: st ?? null, children: children3 };
|
|
4734
4791
|
const rawEntry2 = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : typeof built === "object" && built !== null ? input.slice(r.span.start, r.span.end) : "", span };
|
|
4735
4792
|
if (saved.buf !== void 0 || saved.ch !== void 0) {
|
|
4736
4793
|
pushCstChild(ctx, built, rawEntry2);
|
|
@@ -4957,6 +5014,399 @@ function firstSetToString(fs3) {
|
|
|
4957
5014
|
return fs3.ranges.map((r) => r.lo === r.hi ? ch(r.lo) : `${ch(r.lo)}-${ch(r.hi)}`).join(",");
|
|
4958
5015
|
}
|
|
4959
5016
|
|
|
5017
|
+
// src/analysis/commitment.ts
|
|
5018
|
+
function mayFail(p, seen = /* @__PURE__ */ new Set()) {
|
|
5019
|
+
if (seen.has(p)) return true;
|
|
5020
|
+
seen.add(p);
|
|
5021
|
+
const d = p._def;
|
|
5022
|
+
switch (d.tag) {
|
|
5023
|
+
case "literal":
|
|
5024
|
+
return d.value.length > 0;
|
|
5025
|
+
case "trivia":
|
|
5026
|
+
return false;
|
|
5027
|
+
// `optional`/`many`/a min-0 `sepBy` swallow an ORDINARY failure — zero
|
|
5028
|
+
// repetitions is a match. They do NOT swallow a COMMITTED one: a dispatch
|
|
5029
|
+
// that has selected an arm and then failed inside it breaks out past every
|
|
5030
|
+
// enclosing repeat, straight to the fallible boundary. So these are total
|
|
5031
|
+
// exactly when their body cannot commit. (Measured: treating them as
|
|
5032
|
+
// unconditionally total left an extra zero-width leaf in
|
|
5033
|
+
// `BareInterpolatedSelector` on benchmark.less — a rollback the legacy
|
|
5034
|
+
// build fired and this one had deleted.)
|
|
5035
|
+
case "optional":
|
|
5036
|
+
case "many":
|
|
5037
|
+
return mayCommitFailure(d.parser);
|
|
5038
|
+
case "sepBy":
|
|
5039
|
+
return d.min >= 1 ? mayFail(d.parser, seen) : mayCommitFailure(d.parser) || mayCommitFailure(d.separator);
|
|
5040
|
+
case "oneOrMore":
|
|
5041
|
+
return mayFail(d.parser, seen);
|
|
5042
|
+
case "sequence":
|
|
5043
|
+
return d.parsers.some((x) => mayFail(x, seen));
|
|
5044
|
+
// Delegating wrappers: as fallible as what they wrap.
|
|
5045
|
+
case "node":
|
|
5046
|
+
case "transform":
|
|
5047
|
+
case "label":
|
|
5048
|
+
case "field":
|
|
5049
|
+
case "expect":
|
|
5050
|
+
case "withCtx":
|
|
5051
|
+
case "grammar":
|
|
5052
|
+
case "token":
|
|
5053
|
+
case "leaf":
|
|
5054
|
+
return mayFail(d.parser, seen);
|
|
5055
|
+
case "lazy": {
|
|
5056
|
+
try {
|
|
5057
|
+
return mayFail(d.thunk(), seen);
|
|
5058
|
+
} catch {
|
|
5059
|
+
return true;
|
|
5060
|
+
}
|
|
5061
|
+
}
|
|
5062
|
+
// An adjacency assertion is a TEST — failing is its whole job.
|
|
5063
|
+
case "adjacency":
|
|
5064
|
+
return true;
|
|
5065
|
+
default:
|
|
5066
|
+
return true;
|
|
5067
|
+
}
|
|
5068
|
+
}
|
|
5069
|
+
function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set(), triviaActive = true) {
|
|
5070
|
+
if (seen.has(p)) return false;
|
|
5071
|
+
seen.add(p);
|
|
5072
|
+
const d = p._def;
|
|
5073
|
+
switch (d.tag) {
|
|
5074
|
+
// Atomic / non-capturing-then-failing: a failure happens before any push.
|
|
5075
|
+
case "literal":
|
|
5076
|
+
case "regex":
|
|
5077
|
+
case "keywords":
|
|
5078
|
+
case "guard":
|
|
5079
|
+
// Adjacency probes with `_cap = 0` / no `commit()`: it cannot push anything.
|
|
5080
|
+
case "adjacency":
|
|
5081
|
+
case "not":
|
|
5082
|
+
// peek(): emitted under a non-capturing probe ctx and zero-width on both
|
|
5083
|
+
// outcomes, so it can never leave a partial capture behind.
|
|
5084
|
+
case "peek":
|
|
5085
|
+
case "trivia":
|
|
5086
|
+
case "token":
|
|
5087
|
+
case "leaf":
|
|
5088
|
+
case "scanTo":
|
|
5089
|
+
case "unknown":
|
|
5090
|
+
return false;
|
|
5091
|
+
// node() captures into its own private buffers and rolls them back on
|
|
5092
|
+
// failure (emitNode restores _ctx.* and never pushes on the !ok path).
|
|
5093
|
+
case "node":
|
|
5094
|
+
return false;
|
|
5095
|
+
// choice/firstMatch already roll back each failed arm; on overall failure
|
|
5096
|
+
// nothing committed remains.
|
|
5097
|
+
case "choice":
|
|
5098
|
+
return false;
|
|
5099
|
+
case "dispatch":
|
|
5100
|
+
return capturesLeaf(d.selector, new Set(seen)) || d.cases.some((x) => mayLeavePartialCapture(x.parser, new Set(seen), triviaActive) || capturesLeaf(x.parser, new Set(seen))) || (d.matchers ? d.matchers.some((x) => mayLeavePartialCapture(x.parser, new Set(seen), triviaActive) || capturesLeaf(x.parser, new Set(seen))) : false) || (d.otherwise ? mayLeavePartialCapture(d.otherwise, new Set(seen), triviaActive) || capturesLeaf(d.otherwise, new Set(seen)) : false);
|
|
5101
|
+
case "attempt":
|
|
5102
|
+
return false;
|
|
5103
|
+
// optional never fails; many/oneOrMore only "fail" with zero captured items.
|
|
5104
|
+
case "optional":
|
|
5105
|
+
case "many":
|
|
5106
|
+
case "oneOrMore":
|
|
5107
|
+
return false;
|
|
5108
|
+
// sepBy emits its own per-iteration rollback in emitSepBy.
|
|
5109
|
+
case "sepBy":
|
|
5110
|
+
return false;
|
|
5111
|
+
// A sequence is the real case: an earlier capturing term followed by a term
|
|
5112
|
+
// that can fail leaves the earlier captures buffered.
|
|
5113
|
+
//
|
|
5114
|
+
// BOTH halves of that sentence are load-bearing, and the second half is what
|
|
5115
|
+
// this walk exists to exploit. "Some earlier term captures" alone was the old
|
|
5116
|
+
// test, and it is true of very nearly every sequence in a real grammar — a
|
|
5117
|
+
// sequence almost always opens with a literal or a node. The rollback is only
|
|
5118
|
+
// reachable if something AFTER the capture can still fail; once the remainder
|
|
5119
|
+
// is total (`optional`/`many`/trivia/a min-0 `sepBy`), the sequence has no
|
|
5120
|
+
// failure path left to roll back from, and the save+restore is dead code.
|
|
5121
|
+
//
|
|
5122
|
+
// `captured` tracks whether anything is in the buffers yet as the scan moves
|
|
5123
|
+
// left to right. Two things put it there:
|
|
5124
|
+
// - a term that captures (`capturesLeaf`/`hasNodeDef`), and
|
|
5125
|
+
// - the inter-term TRIVIA scan, which under `capturing` pushes into
|
|
5126
|
+
// `_cstRawChildren`/`_cstTriviaLog` BEFORE the term at each boundary
|
|
5127
|
+
// i >= 1. `emitSeqValues` only rewinds that push on the term's SUCCESS
|
|
5128
|
+
// path (the "matched empty, so leave the whitespace out of the span"
|
|
5129
|
+
// branch); a term that FAILS breaks straight out with the trivia still
|
|
5130
|
+
// buffered, so from boundary 1 onward the buffers are dirty regardless of
|
|
5131
|
+
// what the earlier terms did.
|
|
5132
|
+
// Each term is also asked about itself: a nested sequence can leave its own
|
|
5133
|
+
// partial capture behind, and its terms are emitted inline into this same
|
|
5134
|
+
// block with no boundary of their own to roll them back.
|
|
5135
|
+
case "sequence": {
|
|
5136
|
+
const parts = d.parsers;
|
|
5137
|
+
let captured = false;
|
|
5138
|
+
for (let i = 0; i < parts.length; i++) {
|
|
5139
|
+
const part = parts[i];
|
|
5140
|
+
if (i > 0 && triviaActive) captured = true;
|
|
5141
|
+
if (captured && mayFail(part)) return true;
|
|
5142
|
+
if (mayLeavePartialCapture(part, seen, triviaActive)) return true;
|
|
5143
|
+
if (capturesLeaf(part) || hasNodeDef(part)) captured = true;
|
|
5144
|
+
}
|
|
5145
|
+
return false;
|
|
5146
|
+
}
|
|
5147
|
+
// Delegating wrappers: defer to the wrapped parser.
|
|
5148
|
+
case "transform":
|
|
5149
|
+
case "label":
|
|
5150
|
+
case "field":
|
|
5151
|
+
case "expect":
|
|
5152
|
+
case "withCtx":
|
|
5153
|
+
case "grammar":
|
|
5154
|
+
return mayLeavePartialCapture(d.parser, seen, triviaActive);
|
|
5155
|
+
case "recover":
|
|
5156
|
+
return mayLeavePartialCapture(d.parser, seen, triviaActive);
|
|
5157
|
+
case "lazy": {
|
|
5158
|
+
try {
|
|
5159
|
+
return mayLeavePartialCapture(d.thunk(), seen, triviaActive);
|
|
5160
|
+
} catch {
|
|
5161
|
+
return true;
|
|
5162
|
+
}
|
|
5163
|
+
}
|
|
5164
|
+
// Unknown shapes: be safe and keep the rollback.
|
|
5165
|
+
default:
|
|
5166
|
+
return true;
|
|
5167
|
+
}
|
|
5168
|
+
}
|
|
5169
|
+
function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
|
|
5170
|
+
if (seen.has(p)) return false;
|
|
5171
|
+
seen.add(p);
|
|
5172
|
+
const d = p._def;
|
|
5173
|
+
switch (d.tag) {
|
|
5174
|
+
case "literal":
|
|
5175
|
+
case "regex":
|
|
5176
|
+
case "keywords":
|
|
5177
|
+
case "node":
|
|
5178
|
+
case "token":
|
|
5179
|
+
case "routed":
|
|
5180
|
+
case "leaf":
|
|
5181
|
+
return true;
|
|
5182
|
+
case "not":
|
|
5183
|
+
case "peek":
|
|
5184
|
+
case "guard":
|
|
5185
|
+
case "adjacency":
|
|
5186
|
+
case "trivia":
|
|
5187
|
+
case "unknown":
|
|
5188
|
+
return false;
|
|
5189
|
+
case "sequence":
|
|
5190
|
+
case "choice":
|
|
5191
|
+
return d.parsers.some((x) => capturesLeaf(x, seen));
|
|
5192
|
+
case "dispatch":
|
|
5193
|
+
return capturesLeaf(d.selector, seen) || d.cases.some((x) => capturesLeaf(x.parser, seen)) || (d.matchers ? d.matchers.some((entry) => capturesLeaf(entry.parser, seen)) : false) || (d.otherwise ? capturesLeaf(d.otherwise, seen) : false);
|
|
5194
|
+
case "sepBy":
|
|
5195
|
+
return capturesLeaf(d.parser, seen) || capturesLeaf(d.separator, seen);
|
|
5196
|
+
case "many":
|
|
5197
|
+
case "oneOrMore":
|
|
5198
|
+
case "optional":
|
|
5199
|
+
case "attempt":
|
|
5200
|
+
case "transform":
|
|
5201
|
+
case "label":
|
|
5202
|
+
case "field":
|
|
5203
|
+
case "expect":
|
|
5204
|
+
case "withCtx":
|
|
5205
|
+
case "grammar":
|
|
5206
|
+
case "recover":
|
|
5207
|
+
return capturesLeaf(d.parser, seen);
|
|
5208
|
+
case "scanTo":
|
|
5209
|
+
return true;
|
|
5210
|
+
case "lazy": {
|
|
5211
|
+
try {
|
|
5212
|
+
return capturesLeaf(d.thunk(), seen);
|
|
5213
|
+
} catch {
|
|
5214
|
+
return true;
|
|
5215
|
+
}
|
|
5216
|
+
}
|
|
5217
|
+
default:
|
|
5218
|
+
return true;
|
|
5219
|
+
}
|
|
5220
|
+
}
|
|
5221
|
+
function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
5222
|
+
if (seen.has(p)) return false;
|
|
5223
|
+
seen.add(p);
|
|
5224
|
+
const d = p._def;
|
|
5225
|
+
switch (d.tag) {
|
|
5226
|
+
case "node":
|
|
5227
|
+
return true;
|
|
5228
|
+
case "lazy": {
|
|
5229
|
+
try {
|
|
5230
|
+
return hasNodeDef(d.thunk(), seen);
|
|
5231
|
+
} catch {
|
|
5232
|
+
return false;
|
|
5233
|
+
}
|
|
5234
|
+
}
|
|
5235
|
+
case "grammar":
|
|
5236
|
+
case "trivia":
|
|
5237
|
+
case "token":
|
|
5238
|
+
case "leaf":
|
|
5239
|
+
case "label":
|
|
5240
|
+
case "field":
|
|
5241
|
+
case "optional":
|
|
5242
|
+
case "many":
|
|
5243
|
+
case "oneOrMore":
|
|
5244
|
+
case "not":
|
|
5245
|
+
case "peek":
|
|
5246
|
+
case "transform":
|
|
5247
|
+
return hasNodeDef(d.parser, seen);
|
|
5248
|
+
case "sequence":
|
|
5249
|
+
case "choice":
|
|
5250
|
+
return d.parsers.some((x) => hasNodeDef(x, seen));
|
|
5251
|
+
case "dispatch":
|
|
5252
|
+
return hasNodeDef(d.selector, seen) || d.cases.some((x) => hasNodeDef(x.parser, seen)) || (d.matchers ? d.matchers.some((entry) => hasNodeDef(entry.parser, seen)) : false) || (d.otherwise ? hasNodeDef(d.otherwise, seen) : false);
|
|
5253
|
+
case "sepBy":
|
|
5254
|
+
return hasNodeDef(d.parser, seen) || hasNodeDef(d.separator, seen);
|
|
5255
|
+
case "scanTo":
|
|
5256
|
+
return hasNodeDef(d.sentinel, seen) || d.skip.some((x) => hasNodeDef(x, seen));
|
|
5257
|
+
case "recover":
|
|
5258
|
+
return hasNodeDef(d.parser, seen) || hasNodeDef(d.sentinel, seen);
|
|
5259
|
+
case "expect":
|
|
5260
|
+
return hasNodeDef(d.parser, seen);
|
|
5261
|
+
case "withCtx":
|
|
5262
|
+
return hasNodeDef(d.parser, seen);
|
|
5263
|
+
default:
|
|
5264
|
+
return false;
|
|
5265
|
+
}
|
|
5266
|
+
}
|
|
5267
|
+
function hasDirectBuildDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
5268
|
+
if (seen.has(p)) return false;
|
|
5269
|
+
seen.add(p);
|
|
5270
|
+
const d = p._def;
|
|
5271
|
+
switch (d.tag) {
|
|
5272
|
+
case "node":
|
|
5273
|
+
return d.build !== void 0 || hasDirectBuildDef(d.parser, seen);
|
|
5274
|
+
case "lazy": {
|
|
5275
|
+
try {
|
|
5276
|
+
return hasDirectBuildDef(d.thunk(), seen);
|
|
5277
|
+
} catch {
|
|
5278
|
+
return false;
|
|
5279
|
+
}
|
|
5280
|
+
}
|
|
5281
|
+
case "grammar":
|
|
5282
|
+
case "trivia":
|
|
5283
|
+
case "token":
|
|
5284
|
+
case "leaf":
|
|
5285
|
+
case "label":
|
|
5286
|
+
case "field":
|
|
5287
|
+
case "optional":
|
|
5288
|
+
case "many":
|
|
5289
|
+
case "oneOrMore":
|
|
5290
|
+
case "attempt":
|
|
5291
|
+
case "not":
|
|
5292
|
+
case "peek":
|
|
5293
|
+
case "withCtx":
|
|
5294
|
+
case "expect":
|
|
5295
|
+
case "transform":
|
|
5296
|
+
return hasDirectBuildDef(d.parser, seen);
|
|
5297
|
+
case "sequence":
|
|
5298
|
+
case "choice":
|
|
5299
|
+
return d.parsers.some((x) => hasDirectBuildDef(x, seen));
|
|
5300
|
+
case "dispatch":
|
|
5301
|
+
return hasDirectBuildDef(d.selector, seen) || d.cases.some((x) => hasDirectBuildDef(x.parser, seen)) || (d.matchers ? d.matchers.some((x) => hasDirectBuildDef(x.parser, seen)) : false) || (d.otherwise ? hasDirectBuildDef(d.otherwise, seen) : false);
|
|
5302
|
+
case "sepBy":
|
|
5303
|
+
return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.separator, seen);
|
|
5304
|
+
case "scanTo":
|
|
5305
|
+
return hasDirectBuildDef(d.sentinel, seen) || d.skip.some((x) => hasDirectBuildDef(x, seen));
|
|
5306
|
+
case "recover":
|
|
5307
|
+
return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.sentinel, seen);
|
|
5308
|
+
case "routed":
|
|
5309
|
+
return d.fallback ? hasDirectBuildDef(d.fallback, seen) : false;
|
|
5310
|
+
default:
|
|
5311
|
+
return false;
|
|
5312
|
+
}
|
|
5313
|
+
}
|
|
5314
|
+
function mayCommitFailure(p, seen = /* @__PURE__ */ new Set(), resolve3) {
|
|
5315
|
+
if (seen.has(p)) return false;
|
|
5316
|
+
seen.add(p);
|
|
5317
|
+
const d = p._def;
|
|
5318
|
+
switch (d.tag) {
|
|
5319
|
+
case "dispatch":
|
|
5320
|
+
return true;
|
|
5321
|
+
case "choice":
|
|
5322
|
+
case "sequence":
|
|
5323
|
+
return d.parsers.some((x) => mayCommitFailure(x, seen, resolve3));
|
|
5324
|
+
case "many":
|
|
5325
|
+
case "oneOrMore":
|
|
5326
|
+
case "optional":
|
|
5327
|
+
case "attempt":
|
|
5328
|
+
case "transform":
|
|
5329
|
+
case "label":
|
|
5330
|
+
case "field":
|
|
5331
|
+
case "grammar":
|
|
5332
|
+
case "node":
|
|
5333
|
+
return mayCommitFailure(d.parser, seen, resolve3);
|
|
5334
|
+
case "sepBy":
|
|
5335
|
+
return mayCommitFailure(d.parser, seen, resolve3) || mayCommitFailure(d.separator, seen, resolve3);
|
|
5336
|
+
case "token":
|
|
5337
|
+
case "leaf":
|
|
5338
|
+
return mayCommitFailure(d.parser, seen, resolve3);
|
|
5339
|
+
case "withCtx":
|
|
5340
|
+
return mayCommitFailure(d.parser, seen, resolve3);
|
|
5341
|
+
case "scanTo":
|
|
5342
|
+
return mayCommitFailure(d.sentinel, seen, resolve3) || d.skip.some((x) => mayCommitFailure(x, seen, resolve3));
|
|
5343
|
+
case "lazy": {
|
|
5344
|
+
try {
|
|
5345
|
+
return mayCommitFailure(d.thunk(), seen, resolve3);
|
|
5346
|
+
} catch {
|
|
5347
|
+
const name = p._ruleName;
|
|
5348
|
+
const target = name === void 0 ? void 0 : resolve3?.(name);
|
|
5349
|
+
return target === void 0 ? true : mayCommitFailure(target, seen, resolve3);
|
|
5350
|
+
}
|
|
5351
|
+
}
|
|
5352
|
+
case "unknown":
|
|
5353
|
+
return true;
|
|
5354
|
+
default:
|
|
5355
|
+
return false;
|
|
5356
|
+
}
|
|
5357
|
+
}
|
|
5358
|
+
function hasSemanticReduction(roots, externalRefs) {
|
|
5359
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5360
|
+
const visit = (parser2) => {
|
|
5361
|
+
if (seen.has(parser2)) return false;
|
|
5362
|
+
seen.add(parser2);
|
|
5363
|
+
const def = parser2._def;
|
|
5364
|
+
if (def.tag === "transform" && !def.recognitionOnly) return true;
|
|
5365
|
+
if (def.tag === "choice" && def.gates.some(Boolean)) return true;
|
|
5366
|
+
if (def.tag === "guard" || def.tag === "withCtx") return true;
|
|
5367
|
+
if (def.tag === "node" && def.build !== void 0) return true;
|
|
5368
|
+
if (def.tag === "lazy") {
|
|
5369
|
+
if (externalRefs?.has(parser2)) return false;
|
|
5370
|
+
try {
|
|
5371
|
+
return visit(def.thunk());
|
|
5372
|
+
} catch {
|
|
5373
|
+
return true;
|
|
5374
|
+
}
|
|
5375
|
+
}
|
|
5376
|
+
return childrenOf2(def).some(visit);
|
|
5377
|
+
};
|
|
5378
|
+
return roots.some(visit);
|
|
5379
|
+
}
|
|
5380
|
+
function classifyRuleMap(ruleMap) {
|
|
5381
|
+
const externalRefs = /* @__PURE__ */ new Set();
|
|
5382
|
+
const scanned = /* @__PURE__ */ new Set();
|
|
5383
|
+
const scanExternal = (p) => {
|
|
5384
|
+
if (scanned.has(p)) return;
|
|
5385
|
+
scanned.add(p);
|
|
5386
|
+
const def = p._def;
|
|
5387
|
+
if (def.tag === "lazy") {
|
|
5388
|
+
let resolved;
|
|
5389
|
+
try {
|
|
5390
|
+
resolved = def.thunk();
|
|
5391
|
+
} catch {
|
|
5392
|
+
resolved = void 0;
|
|
5393
|
+
}
|
|
5394
|
+
if (resolved === void 0) {
|
|
5395
|
+
if (p._ruleName) externalRefs.add(p);
|
|
5396
|
+
return;
|
|
5397
|
+
}
|
|
5398
|
+
scanExternal(resolved);
|
|
5399
|
+
return;
|
|
5400
|
+
}
|
|
5401
|
+
for (const child of childrenOf2(def)) scanExternal(child);
|
|
5402
|
+
};
|
|
5403
|
+
for (const [, rule] of ruleMap) scanExternal(rule);
|
|
5404
|
+
return {
|
|
5405
|
+
hasDirectBuilders: ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
|
|
5406
|
+
isRecognitionOnly: !hasSemanticReduction(ruleMap.map(([, rule]) => rule), externalRefs)
|
|
5407
|
+
};
|
|
5408
|
+
}
|
|
5409
|
+
|
|
4960
5410
|
// src/table/ops.ts
|
|
4961
5411
|
var OP_LIT = 1;
|
|
4962
5412
|
var OP_RX = 2;
|
|
@@ -5273,11 +5723,11 @@ function fixedTreeRunner(words, matchers, classes, expected) {
|
|
|
5273
5723
|
}
|
|
5274
5724
|
if (op >= LEX_NODE_SEQUENCE2 && op <= LEX_NODE_SEQUENCE5) {
|
|
5275
5725
|
const count = op - LEX_NODE_SEQUENCE2 + 2;
|
|
5276
|
-
const
|
|
5277
|
-
if (count === 2) stack.push(sequence2(
|
|
5278
|
-
else if (count === 3) stack.push(sequence3(
|
|
5279
|
-
else if (count === 4) stack.push(sequence4(
|
|
5280
|
-
else stack.push(sequence5(
|
|
5726
|
+
const nodes2 = Array.from({ length: count }, pop).reverse();
|
|
5727
|
+
if (count === 2) stack.push(sequence2(nodes2[0], nodes2[1]));
|
|
5728
|
+
else if (count === 3) stack.push(sequence3(nodes2[0], nodes2[1], nodes2[2]));
|
|
5729
|
+
else if (count === 4) stack.push(sequence4(nodes2[0], nodes2[1], nodes2[2], nodes2[3]));
|
|
5730
|
+
else stack.push(sequence5(nodes2[0], nodes2[1], nodes2[2], nodes2[3], nodes2[4]));
|
|
5281
5731
|
continue;
|
|
5282
5732
|
}
|
|
5283
5733
|
if (op >= LEX_NODE_CHOICE2 && op <= LEX_NODE_CHOICE8) {
|
|
@@ -5512,8 +5962,26 @@ function validateDispatchSpec(spec, arity, fallbackRouted) {
|
|
|
5512
5962
|
}
|
|
5513
5963
|
}
|
|
5514
5964
|
var TABLE_RUNTIME = /* @__PURE__ */ Symbol("parseman.tableRuntime");
|
|
5515
|
-
function ownTableProgram(prog, resolved) {
|
|
5516
|
-
|
|
5965
|
+
function ownTableProgram(prog, resolved, caches = {}) {
|
|
5966
|
+
const runtime = prog[TABLE_RUNTIME];
|
|
5967
|
+
return {
|
|
5968
|
+
...prog,
|
|
5969
|
+
[TABLE_RUNTIME]: {
|
|
5970
|
+
resolved,
|
|
5971
|
+
choiceRollbackMasks: caches.choiceRollbackMasks ?? runtime?.choiceRollbackMasks,
|
|
5972
|
+
nonCommittingChoiceSites: caches.nonCommittingChoiceSites ?? runtime?.nonCommittingChoiceSites,
|
|
5973
|
+
failureRollbackCleanSites: caches.failureRollbackCleanSites ?? runtime?.failureRollbackCleanSites
|
|
5974
|
+
}
|
|
5975
|
+
};
|
|
5976
|
+
}
|
|
5977
|
+
function choiceRollbackMask(prog, ip) {
|
|
5978
|
+
return prog[TABLE_RUNTIME]?.choiceRollbackMasks?.get(ip);
|
|
5979
|
+
}
|
|
5980
|
+
function choiceCannotCommit(prog, ip) {
|
|
5981
|
+
return prog[TABLE_RUNTIME]?.nonCommittingChoiceSites?.has(ip) === true;
|
|
5982
|
+
}
|
|
5983
|
+
function failureRollbackClean(prog, ip) {
|
|
5984
|
+
return prog[TABLE_RUNTIME]?.failureRollbackCleanSites?.has(ip) === true;
|
|
5517
5985
|
}
|
|
5518
5986
|
var WIDE_CLASS_PREFIX_LO = 65535;
|
|
5519
5987
|
var WIDE_CLASS_PREFIX_HI = 0;
|
|
@@ -5529,22 +5997,22 @@ function validateClassRange(lo, hi) {
|
|
|
5529
5997
|
}
|
|
5530
5998
|
function encodeClassSpec(ranges) {
|
|
5531
5999
|
let wide = false;
|
|
5532
|
-
for (const
|
|
5533
|
-
validateClassRange(
|
|
5534
|
-
if (
|
|
6000
|
+
for (const range2 of ranges) {
|
|
6001
|
+
validateClassRange(range2.lo, range2.hi);
|
|
6002
|
+
if (range2.hi > 65535) wide = true;
|
|
5535
6003
|
}
|
|
5536
6004
|
if (!wide) {
|
|
5537
6005
|
let spec2 = "";
|
|
5538
|
-
for (const
|
|
6006
|
+
for (const range2 of ranges) spec2 += String.fromCharCode(range2.lo, range2.hi);
|
|
5539
6007
|
return spec2;
|
|
5540
6008
|
}
|
|
5541
6009
|
let spec = String.fromCharCode(WIDE_CLASS_PREFIX_LO, WIDE_CLASS_PREFIX_HI);
|
|
5542
|
-
for (const
|
|
6010
|
+
for (const range2 of ranges) {
|
|
5543
6011
|
spec += String.fromCharCode(
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
6012
|
+
range2.lo >>> 16,
|
|
6013
|
+
range2.lo & 65535,
|
|
6014
|
+
range2.hi >>> 16,
|
|
6015
|
+
range2.hi & 65535
|
|
5548
6016
|
);
|
|
5549
6017
|
}
|
|
5550
6018
|
return spec;
|
|
@@ -5688,7 +6156,6 @@ function directArrayProjection(fn, fnSrc, arity) {
|
|
|
5688
6156
|
|
|
5689
6157
|
// src/table/encode.ts
|
|
5690
6158
|
import {
|
|
5691
|
-
assertLexicalCapabilityClosure,
|
|
5692
6159
|
collectLexicalCapabilities,
|
|
5693
6160
|
winnerWrapsReference as winnerWrapsReference2
|
|
5694
6161
|
} from "../compiler/token-capability.js";
|
|
@@ -6070,6 +6537,25 @@ var Encoder = class {
|
|
|
6070
6537
|
lexIndex = /* @__PURE__ */ new Map();
|
|
6071
6538
|
lexPrograms = [];
|
|
6072
6539
|
lexProgramIndex = /* @__PURE__ */ new Map();
|
|
6540
|
+
choiceRollbackMasks = /* @__PURE__ */ new Map();
|
|
6541
|
+
nonCommittingChoiceSites = /* @__PURE__ */ new Set();
|
|
6542
|
+
failureRollbackCleanSites = /* @__PURE__ */ new Set();
|
|
6543
|
+
/**
|
|
6544
|
+
* `hasSideWriter` memo for `failureNeedsRollback`, shared across every call
|
|
6545
|
+
* for the lifetime of this `Encoder`. A cached entry is written only when
|
|
6546
|
+
* `complete` is true, which means the answer is a path-independent fact
|
|
6547
|
+
* about that combinator node — it does not depend on which root's traversal
|
|
6548
|
+
* asked, only on the node's own reachable subgraph. Scoping the memo per call
|
|
6549
|
+
* (as a local inside `failureNeedsRollback`) was correct but discarded that
|
|
6550
|
+
* fact after every arm, so a grammar with many ordered-choice arms / optional
|
|
6551
|
+
* / attempt sites re-walked the SAME shared rule graph from scratch for each
|
|
6552
|
+
* site — O(sites × graph size) instead of O(graph size). Measured on the
|
|
6553
|
+
* scss-parser grammar (composed CSS-base superset, the deepest/largest of the
|
|
6554
|
+
* four grammars): 47-50s for one `compileRuleMap` with the per-call memo,
|
|
6555
|
+
* versus the whole macro transform completing in under a second once this
|
|
6556
|
+
* memo is hoisted here.
|
|
6557
|
+
*/
|
|
6558
|
+
sideWriterMemo = /* @__PURE__ */ new Map();
|
|
6073
6559
|
labels = void 0;
|
|
6074
6560
|
/** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
|
|
6075
6561
|
activeTrivia = void 0;
|
|
@@ -6480,6 +6966,72 @@ var Encoder = class {
|
|
|
6480
6966
|
const w = this.winners;
|
|
6481
6967
|
return w === void 0 ? void 0 : (name) => w[name];
|
|
6482
6968
|
}
|
|
6969
|
+
/**
|
|
6970
|
+
* Whether a failed ordered-choice arm can leave state that the enclosing
|
|
6971
|
+
* choice must restore before trying its successor.
|
|
6972
|
+
*
|
|
6973
|
+
* `mayLeavePartialCapture` is the existing sound CST/trivia proof. The extra
|
|
6974
|
+
* writer census covers the side sinks that proof deliberately does not model:
|
|
6975
|
+
* fields, recovered errors, and interpreted scanners. Strict assemblies do
|
|
6976
|
+
* not run repeat recovery, but these rows can still publish through a caller's
|
|
6977
|
+
* context. Cycles are safe to stop: revisiting the same combinator cannot
|
|
6978
|
+
* discover a writer the first traversal did not already reach.
|
|
6979
|
+
*/
|
|
6980
|
+
failureNeedsRollback(p, autoNot) {
|
|
6981
|
+
const refName = p._ruleName;
|
|
6982
|
+
const winner = refName === void 0 ? void 0 : this.winners?.[refName];
|
|
6983
|
+
const root = winner !== void 0 && !winnerWrapsReference2(winner, p) ? winner : p;
|
|
6984
|
+
const sideWriterMemo = this.sideWriterMemo;
|
|
6985
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6986
|
+
const hasSideWriter = (current) => {
|
|
6987
|
+
const cached = sideWriterMemo.get(current);
|
|
6988
|
+
if (cached !== void 0) return { found: cached, complete: true };
|
|
6989
|
+
if (seen.has(current)) return { found: false, complete: false };
|
|
6990
|
+
seen.add(current);
|
|
6991
|
+
const def = current._def;
|
|
6992
|
+
let result;
|
|
6993
|
+
switch (def.tag) {
|
|
6994
|
+
case "field":
|
|
6995
|
+
case "expect":
|
|
6996
|
+
case "recover":
|
|
6997
|
+
case "scanTo":
|
|
6998
|
+
case "unknown":
|
|
6999
|
+
result = { found: true, complete: true };
|
|
7000
|
+
break;
|
|
7001
|
+
case "lazy": {
|
|
7002
|
+
const name = current._ruleName;
|
|
7003
|
+
const resolvedWinner = name === void 0 ? void 0 : this.winners?.[name];
|
|
7004
|
+
if (resolvedWinner !== void 0 && !winnerWrapsReference2(resolvedWinner, current)) {
|
|
7005
|
+
result = hasSideWriter(resolvedWinner);
|
|
7006
|
+
break;
|
|
7007
|
+
}
|
|
7008
|
+
try {
|
|
7009
|
+
result = hasSideWriter(def.thunk());
|
|
7010
|
+
} catch {
|
|
7011
|
+
result = { found: true, complete: true };
|
|
7012
|
+
}
|
|
7013
|
+
break;
|
|
7014
|
+
}
|
|
7015
|
+
default: {
|
|
7016
|
+
let complete = true;
|
|
7017
|
+
result = { found: false, complete: true };
|
|
7018
|
+
for (const child of childrenOf2(def)) {
|
|
7019
|
+
const childResult = hasSideWriter(child);
|
|
7020
|
+
if (childResult.found) {
|
|
7021
|
+
result = { found: true, complete: true };
|
|
7022
|
+
break;
|
|
7023
|
+
}
|
|
7024
|
+
complete &&= childResult.complete;
|
|
7025
|
+
}
|
|
7026
|
+
if (!result.found) result = { found: false, complete };
|
|
7027
|
+
}
|
|
7028
|
+
}
|
|
7029
|
+
seen.delete(current);
|
|
7030
|
+
if (result.found || result.complete) sideWriterMemo.set(current, result.found);
|
|
7031
|
+
return result;
|
|
7032
|
+
};
|
|
7033
|
+
return mayLeavePartialCapture(root, /* @__PURE__ */ new Set(), true) || hasSideWriter(root).found || (autoNot?.length ?? 0) > 0 && capturesLeaf(root);
|
|
7034
|
+
}
|
|
6483
7035
|
/** A first set becomes a char class string, or −1 for `any`. */
|
|
6484
7036
|
charClass(fs3) {
|
|
6485
7037
|
if (fs3.kind !== "ranges" || fs3.ranges.length === 0) return -1;
|
|
@@ -6765,9 +7317,39 @@ var Encoder = class {
|
|
|
6765
7317
|
});
|
|
6766
7318
|
const rr = this.refResolver();
|
|
6767
7319
|
const finalChoice = classifyFinalChoice(arms, rr);
|
|
6768
|
-
const
|
|
7320
|
+
const transactionalFirst = arms.map((arm, i) => {
|
|
7321
|
+
if (!finalChoice.nullable[i]) return void 0;
|
|
7322
|
+
const def = arm._def;
|
|
7323
|
+
if (def.tag !== "attempt" || matchesEmpty(def.parser, /* @__PURE__ */ new Set(), rr)) return void 0;
|
|
7324
|
+
return firstSetOf(def.parser, /* @__PURE__ */ new Set(), rr);
|
|
7325
|
+
});
|
|
7326
|
+
const gateFirst = finalChoice.firstSets.map((first, i) => transactionalFirst[i] ?? first);
|
|
7327
|
+
const classes = gateFirst.map((first, i) => finalChoice.nullable[i] && transactionalFirst[i] === void 0 ? -1 : this.charClass(first));
|
|
7328
|
+
if (transactionalFirst.some((first) => first !== void 0) && classes.every((cls) => cls >= 0)) {
|
|
7329
|
+
let overlap = false;
|
|
7330
|
+
for (let i = 0; i < gateFirst.length && !overlap; i++) {
|
|
7331
|
+
for (let j = i + 1; j < gateFirst.length; j++) {
|
|
7332
|
+
if (intersects(gateFirst[i], gateFirst[j])) {
|
|
7333
|
+
overlap = true;
|
|
7334
|
+
break;
|
|
7335
|
+
}
|
|
7336
|
+
}
|
|
7337
|
+
}
|
|
7338
|
+
if (!overlap) for (let i = 0; i < classes.length; i++) {
|
|
7339
|
+
if (transactionalFirst[i] !== void 0) classes[i] = -1;
|
|
7340
|
+
}
|
|
7341
|
+
}
|
|
6769
7342
|
const dispIdx = this.disp.length;
|
|
6770
7343
|
this.disp.push(classes);
|
|
7344
|
+
let rollbackMask = kids.length > 31 ? -1 : 0;
|
|
7345
|
+
if (rollbackMask === 0) {
|
|
7346
|
+
for (let i = 0; i < arms.length; i++) {
|
|
7347
|
+
const src = order[i];
|
|
7348
|
+
if (this.failureNeedsRollback(arms[i], d.autoNot[src])) {
|
|
7349
|
+
rollbackMask |= 1 << i;
|
|
7350
|
+
}
|
|
7351
|
+
}
|
|
7352
|
+
}
|
|
6771
7353
|
const head = this.emitHead(OP_CHOICE, 3 + 2 * kids.length);
|
|
6772
7354
|
this.code[head + 1] = dispIdx;
|
|
6773
7355
|
this.code[head + 2] = kids.length;
|
|
@@ -6776,6 +7358,10 @@ var Encoder = class {
|
|
|
6776
7358
|
this.code[head + 4 + i] = kids[i];
|
|
6777
7359
|
this.code[head + 4 + kids.length + i] = this.expected(deriveExpected(arms[i]));
|
|
6778
7360
|
}
|
|
7361
|
+
this.choiceRollbackMasks.set(head, rollbackMask);
|
|
7362
|
+
if (arms.every((arm) => !mayCommitFailure(arm, /* @__PURE__ */ new Set(), rr))) {
|
|
7363
|
+
this.nonCommittingChoiceSites.add(head);
|
|
7364
|
+
}
|
|
6779
7365
|
return head;
|
|
6780
7366
|
}
|
|
6781
7367
|
case "many":
|
|
@@ -6805,8 +7391,11 @@ var Encoder = class {
|
|
|
6805
7391
|
}
|
|
6806
7392
|
return d.min >= 2 ? this.emit(OP_REP, child, d.min, d.max ?? -1, sep2, flags, this.expected(deriveExpected(d.parser))) : this.emit(OP_REP, child, d.min, d.max ?? -1, sep2, flags);
|
|
6807
7393
|
}
|
|
6808
|
-
case "optional":
|
|
6809
|
-
|
|
7394
|
+
case "optional": {
|
|
7395
|
+
const head = this.emit(OP_OPT, this.node(d.parser).ip);
|
|
7396
|
+
if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(head);
|
|
7397
|
+
return head;
|
|
7398
|
+
}
|
|
6810
7399
|
case "transform": {
|
|
6811
7400
|
const inner = d.parser._def;
|
|
6812
7401
|
if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
|
|
@@ -6965,6 +7554,7 @@ var Encoder = class {
|
|
|
6965
7554
|
// lowering was correct only for a choice arm.
|
|
6966
7555
|
case "attempt": {
|
|
6967
7556
|
const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip);
|
|
7557
|
+
if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
|
|
6968
7558
|
const fs3 = d.parser._meta.firstSet;
|
|
6969
7559
|
if (fs3.kind === "any" || matchesEmpty(d.parser)) return inner;
|
|
6970
7560
|
const cls = this.charClass(fs3);
|
|
@@ -7133,6 +7723,10 @@ var Encoder = class {
|
|
|
7133
7723
|
...this.rec ? { rec: 1 } : {},
|
|
7134
7724
|
...this.cov === void 0 ? {} : { cov: this.cov },
|
|
7135
7725
|
lines: this.track ? 1 : 0
|
|
7726
|
+
}, void 0, {
|
|
7727
|
+
choiceRollbackMasks: this.choiceRollbackMasks,
|
|
7728
|
+
failureRollbackCleanSites: this.failureRollbackCleanSites,
|
|
7729
|
+
nonCommittingChoiceSites: this.nonCommittingChoiceSites
|
|
7136
7730
|
});
|
|
7137
7731
|
}
|
|
7138
7732
|
};
|
|
@@ -7177,7 +7771,6 @@ function encodeTableProgram(ruleMap, settings = {}) {
|
|
|
7177
7771
|
const lexicalRoots = [...names].sort().map((name) => ruleMap[name]);
|
|
7178
7772
|
const resolveLexical = (name) => ruleMap[name];
|
|
7179
7773
|
const capabilities = collectLexicalCapabilities(lexicalRoots, resolveLexical);
|
|
7180
|
-
assertLexicalCapabilityClosure(lexicalRoots, capabilities, resolveLexical);
|
|
7181
7774
|
const enc = new Encoder(resolvedSettings, capabilities.capabilityComplete);
|
|
7182
7775
|
enc.winners = ruleMap;
|
|
7183
7776
|
for (const name of names) enc.encodeRule(name, ruleMap[name]);
|
|
@@ -8310,13 +8903,17 @@ var TRI_NONE = -1;
|
|
|
8310
8903
|
var CAP_UNKNOWN = 0;
|
|
8311
8904
|
var CAP_OFF = 1;
|
|
8312
8905
|
var CAP_ON = 2;
|
|
8313
|
-
var
|
|
8906
|
+
var RAW_UNKNOWN = 0;
|
|
8907
|
+
var RAW_CAPTURE = 1;
|
|
8908
|
+
var RAW_OMIT = 2;
|
|
8909
|
+
var TOP = { tri: TRI_UNKNOWN, buf: false, raw: RAW_UNKNOWN, cap: CAP_UNKNOWN };
|
|
8314
8910
|
function meet(a, b) {
|
|
8315
8911
|
const tri = a.tri === b.tri ? a.tri : TRI_UNKNOWN;
|
|
8316
8912
|
const buf = a.buf && b.buf;
|
|
8913
|
+
const raw = a.raw === b.raw ? a.raw : RAW_UNKNOWN;
|
|
8317
8914
|
const cap = a.cap === b.cap ? a.cap : CAP_UNKNOWN;
|
|
8318
|
-
if (tri === a.tri && buf === a.buf && cap === a.cap) return a;
|
|
8319
|
-
return { tri, buf, cap };
|
|
8915
|
+
if (tri === a.tri && buf === a.buf && raw === a.raw && cap === a.cap) return a;
|
|
8916
|
+
return { tri, buf, raw, cap };
|
|
8320
8917
|
}
|
|
8321
8918
|
function reachableSites(code, roots) {
|
|
8322
8919
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -8339,25 +8936,26 @@ function transfer(code, ip, at, hostCst) {
|
|
|
8339
8936
|
const tri = ki < 0 ? TRI_NONE : ki;
|
|
8340
8937
|
const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
|
|
8341
8938
|
if (tri === at.tri && cap === at.cap) return at;
|
|
8342
|
-
return { tri, buf: at.buf, cap };
|
|
8939
|
+
return { tri, buf: at.buf, raw: at.raw, cap };
|
|
8343
8940
|
}
|
|
8344
8941
|
if (op === OP_NODE || op === OP_NODE_TRACK) {
|
|
8345
8942
|
const flags = code[ip + 3];
|
|
8346
8943
|
const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags === 2 || flags === 18 || flags === 34);
|
|
8347
8944
|
if (directChildren) {
|
|
8348
|
-
return { tri: at.tri, buf: false, cap: CAP_OFF };
|
|
8945
|
+
return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
|
|
8349
8946
|
}
|
|
8350
8947
|
const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
|
|
8351
|
-
|
|
8352
|
-
|
|
8948
|
+
const raw = !hostCst && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags & 2) !== 0 ? RAW_OMIT : RAW_CAPTURE;
|
|
8949
|
+
if (at.buf && raw === at.raw && cap === at.cap) return at;
|
|
8950
|
+
return { tri: at.tri, buf: true, raw, cap };
|
|
8353
8951
|
}
|
|
8354
8952
|
if (op === OP_TOKEN) {
|
|
8355
8953
|
if (at.tri === TRI_NONE && !at.buf) return at;
|
|
8356
|
-
return { tri: TRI_NONE, buf: false, cap: at.cap };
|
|
8954
|
+
return { tri: TRI_NONE, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
|
|
8357
8955
|
}
|
|
8358
8956
|
if (op === OP_LEAF) {
|
|
8359
8957
|
if (!at.buf) return at;
|
|
8360
|
-
return { tri: at.tri, buf: false, cap: at.cap };
|
|
8958
|
+
return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
|
|
8361
8959
|
}
|
|
8362
8960
|
return at;
|
|
8363
8961
|
}
|
|
@@ -8424,6 +9022,162 @@ function scalarTerminalNotChild(code, ip) {
|
|
|
8424
9022
|
const op = code[child];
|
|
8425
9023
|
return op === OP_RX || op === OP_LIT ? child : -1;
|
|
8426
9024
|
}
|
|
9025
|
+
function leadingScalarTerminal(code, ip, minDepth = 2, throughAttempt = true, throughPeek = false) {
|
|
9026
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9027
|
+
let at = ip;
|
|
9028
|
+
let depth = 0;
|
|
9029
|
+
while (!seen.has(at)) {
|
|
9030
|
+
seen.add(at);
|
|
9031
|
+
const op = code[at];
|
|
9032
|
+
if (op === OP_LIT || op === OP_RX) return depth >= minDepth ? at : -1;
|
|
9033
|
+
if (op === OP_RULE || op === OP_LABEL || op === OP_TOKEN || throughAttempt && op === OP_ATTEMPT) {
|
|
9034
|
+
at = code[at + 1];
|
|
9035
|
+
depth++;
|
|
9036
|
+
continue;
|
|
9037
|
+
}
|
|
9038
|
+
if (throughPeek && op === OP_PEEK) {
|
|
9039
|
+
at = code[at + 1];
|
|
9040
|
+
depth++;
|
|
9041
|
+
continue;
|
|
9042
|
+
}
|
|
9043
|
+
if (op === OP_GATE || op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
|
|
9044
|
+
at = code[at + 2];
|
|
9045
|
+
depth++;
|
|
9046
|
+
continue;
|
|
9047
|
+
}
|
|
9048
|
+
if (op === OP_SEQ || op === OP_SEQV) {
|
|
9049
|
+
if (code[at + 1] < 1) return -1;
|
|
9050
|
+
at = code[at + 2];
|
|
9051
|
+
depth++;
|
|
9052
|
+
continue;
|
|
9053
|
+
}
|
|
9054
|
+
if (op === OP_SEQX) {
|
|
9055
|
+
if (code[at + 2] < 1) return -1;
|
|
9056
|
+
at = code[at + 3];
|
|
9057
|
+
depth++;
|
|
9058
|
+
continue;
|
|
9059
|
+
}
|
|
9060
|
+
return -1;
|
|
9061
|
+
}
|
|
9062
|
+
return -1;
|
|
9063
|
+
}
|
|
9064
|
+
function leadingScalarSequence(code, ip) {
|
|
9065
|
+
const wholeScalar = (start) => {
|
|
9066
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
9067
|
+
let at2 = start;
|
|
9068
|
+
while (!seen2.has(at2)) {
|
|
9069
|
+
seen2.add(at2);
|
|
9070
|
+
const op = code[at2];
|
|
9071
|
+
if (op === OP_LIT || op === OP_RX) return at2;
|
|
9072
|
+
if (op === OP_RULE || op === OP_TOKEN || op === OP_ATTEMPT) {
|
|
9073
|
+
at2 = code[at2 + 1];
|
|
9074
|
+
continue;
|
|
9075
|
+
}
|
|
9076
|
+
if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
|
|
9077
|
+
at2 = code[at2 + 2];
|
|
9078
|
+
continue;
|
|
9079
|
+
}
|
|
9080
|
+
if (op === OP_SEQ || op === OP_SEQV) {
|
|
9081
|
+
if (code[at2 + 1] !== 1) return -1;
|
|
9082
|
+
at2 = code[at2 + 2];
|
|
9083
|
+
continue;
|
|
9084
|
+
}
|
|
9085
|
+
if (op === OP_SEQX) {
|
|
9086
|
+
if (code[at2 + 2] !== 1) return -1;
|
|
9087
|
+
at2 = code[at2 + 3];
|
|
9088
|
+
continue;
|
|
9089
|
+
}
|
|
9090
|
+
return -1;
|
|
9091
|
+
}
|
|
9092
|
+
return -1;
|
|
9093
|
+
};
|
|
9094
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9095
|
+
let at = ip;
|
|
9096
|
+
let ambientTrivia;
|
|
9097
|
+
while (!seen.has(at)) {
|
|
9098
|
+
seen.add(at);
|
|
9099
|
+
const op = code[at];
|
|
9100
|
+
if (op === OP_RULE) {
|
|
9101
|
+
at = code[at + 1];
|
|
9102
|
+
continue;
|
|
9103
|
+
}
|
|
9104
|
+
if (op === OP_SCOPE_PLAIN) {
|
|
9105
|
+
ambientTrivia = code[at + 1];
|
|
9106
|
+
at = code[at + 2];
|
|
9107
|
+
continue;
|
|
9108
|
+
}
|
|
9109
|
+
if (op === OP_GATE || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
|
|
9110
|
+
at = code[at + 2];
|
|
9111
|
+
continue;
|
|
9112
|
+
}
|
|
9113
|
+
const n = op === OP_SEQ || op === OP_SEQV ? code[at + 1] : op === OP_SEQX ? code[at + 2] : 0;
|
|
9114
|
+
if (n < 3 || ambientTrivia === void 0) return void 0;
|
|
9115
|
+
const base = op === OP_SEQX ? at + 3 : at + 2;
|
|
9116
|
+
const terminals = [
|
|
9117
|
+
wholeScalar(code[base]),
|
|
9118
|
+
wholeScalar(code[base + 1]),
|
|
9119
|
+
wholeScalar(code[base + 2])
|
|
9120
|
+
];
|
|
9121
|
+
return terminals.every((terminal) => terminal >= 0) ? { terminals, trivia: ambientTrivia } : void 0;
|
|
9122
|
+
}
|
|
9123
|
+
return void 0;
|
|
9124
|
+
}
|
|
9125
|
+
function leadingLiteralFamily(code, constants, ip, minDepth = 2, limit = 4) {
|
|
9126
|
+
const active = /* @__PURE__ */ new Set();
|
|
9127
|
+
const walk = (at, depth) => {
|
|
9128
|
+
if (active.has(at)) return void 0;
|
|
9129
|
+
active.add(at);
|
|
9130
|
+
try {
|
|
9131
|
+
const op = code[at];
|
|
9132
|
+
if (op === OP_LIT) {
|
|
9133
|
+
const value = constants[code[at + 1]];
|
|
9134
|
+
return depth >= minDepth && typeof value === "string" && value.length > 0 ? [at] : void 0;
|
|
9135
|
+
}
|
|
9136
|
+
if (op === OP_RULE || op === OP_LABEL || op === OP_TOKEN || op === OP_ATTEMPT || op === OP_PEEK) {
|
|
9137
|
+
return walk(code[at + 1], depth + 1);
|
|
9138
|
+
}
|
|
9139
|
+
if (op === OP_GATE || op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
|
|
9140
|
+
return walk(code[at + 2], depth + 1);
|
|
9141
|
+
}
|
|
9142
|
+
if (op === OP_SEQ || op === OP_SEQV) {
|
|
9143
|
+
return code[at + 1] < 1 ? void 0 : walk(code[at + 2], depth + 1);
|
|
9144
|
+
}
|
|
9145
|
+
if (op === OP_SEQX) {
|
|
9146
|
+
return code[at + 2] < 1 ? void 0 : walk(code[at + 3], depth + 1);
|
|
9147
|
+
}
|
|
9148
|
+
if (op !== OP_CHOICE) return void 0;
|
|
9149
|
+
const n = code[at + 2];
|
|
9150
|
+
if (n < 1) return void 0;
|
|
9151
|
+
const out = [];
|
|
9152
|
+
for (let i = 0; i < n; i++) {
|
|
9153
|
+
const branch = walk(code[at + 4 + i], depth + 1);
|
|
9154
|
+
if (branch === void 0) return void 0;
|
|
9155
|
+
for (const terminal of branch) {
|
|
9156
|
+
const value = constants[code[terminal + 1]];
|
|
9157
|
+
let covered = false;
|
|
9158
|
+
for (let j = 0; j < out.length; j++) {
|
|
9159
|
+
const prior = constants[code[out[j] + 1]];
|
|
9160
|
+
if (value.startsWith(prior)) {
|
|
9161
|
+
covered = true;
|
|
9162
|
+
break;
|
|
9163
|
+
}
|
|
9164
|
+
}
|
|
9165
|
+
if (covered) continue;
|
|
9166
|
+
for (let j = out.length - 1; j >= 0; j--) {
|
|
9167
|
+
const prior = constants[code[out[j] + 1]];
|
|
9168
|
+
if (prior.startsWith(value)) out.splice(j, 1);
|
|
9169
|
+
}
|
|
9170
|
+
out.push(terminal);
|
|
9171
|
+
if (out.length > limit) return void 0;
|
|
9172
|
+
}
|
|
9173
|
+
}
|
|
9174
|
+
return out;
|
|
9175
|
+
} finally {
|
|
9176
|
+
active.delete(at);
|
|
9177
|
+
}
|
|
9178
|
+
};
|
|
9179
|
+
return walk(ip, 0);
|
|
9180
|
+
}
|
|
8427
9181
|
|
|
8428
9182
|
// src/table/emit-assembly.ts
|
|
8429
9183
|
var Unemittable = class extends Error {
|
|
@@ -8505,6 +9259,16 @@ let _pfScan=null
|
|
|
8505
9259
|
let _pfHost
|
|
8506
9260
|
let _pfDepth=0
|
|
8507
9261
|
const _pfFrames=[]
|
|
9262
|
+
let _pfTokInput
|
|
9263
|
+
let _pfTokPos=-1
|
|
9264
|
+
let _pfTokBody=-1
|
|
9265
|
+
let _pfTokPacked=-1
|
|
9266
|
+
let _pfTokValue
|
|
9267
|
+
let _pfTokDispatch=-1
|
|
9268
|
+
let _pfTokArm=-1
|
|
9269
|
+
let _pfTokEnd=-1
|
|
9270
|
+
let _pfSeqEnd=-1
|
|
9271
|
+
function _asciiFoldCode(c){return c>=65&&c<=90?c+32:c}
|
|
8508
9272
|
function _skipTrivia(input,cur,ctx){
|
|
8509
9273
|
const s=_pfScan
|
|
8510
9274
|
if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
|
|
@@ -8570,6 +9334,40 @@ if(ctx._triviaLog!==undefined&&ctx._triviaLog.length!==lg)ctx._triviaLog.length=
|
|
|
8570
9334
|
if(ctx._rootTriviaLog!==undefined&&ctx._rootTriviaLog.length!==rt)ctx._rootTriviaLog.length=rt
|
|
8571
9335
|
}
|
|
8572
9336
|
`;
|
|
9337
|
+
var NO_RAW_RUNTIME_PRELUDE = `
|
|
9338
|
+
function _pushLeafNoRawBuf(ctx,value,s,e){
|
|
9339
|
+
const l={_tag:'leaf',value,span:{start:s,end:e}}
|
|
9340
|
+
const b=ctx._cstBuf
|
|
9341
|
+
if(b.ch!==undefined)b.ch.push(l)
|
|
9342
|
+
else if(b.single!==undefined){b.ch=[b.single,l];b.single=undefined}
|
|
9343
|
+
else b.single=l
|
|
9344
|
+
b.rawLen++
|
|
9345
|
+
}
|
|
9346
|
+
function _pushNodeNoRawBuf(ctx,value){
|
|
9347
|
+
const b=ctx._cstBuf
|
|
9348
|
+
if(b.ch!==undefined)b.ch.push(value)
|
|
9349
|
+
else if(b.single!==undefined){b.ch=[b.single,value];b.single=undefined}
|
|
9350
|
+
else b.single=value
|
|
9351
|
+
b.rawLen++
|
|
9352
|
+
}
|
|
9353
|
+
function _rbNoRawBuf(ctx,raw,tl,lv,lg,rt){
|
|
9354
|
+
const b=ctx._cstBuf
|
|
9355
|
+
if(b.rawLen!==raw)b.rawLen=raw
|
|
9356
|
+
const ch=b.ch
|
|
9357
|
+
if(ch!==undefined){
|
|
9358
|
+
if(lv===0)b.ch=undefined
|
|
9359
|
+
else if(lv===1){b.single=ch[0];b.ch=undefined}
|
|
9360
|
+
else if(ch.length!==lv)ch.length=lv
|
|
9361
|
+
}else if(lv===0)b.single=undefined
|
|
9362
|
+
const bt=b.tl
|
|
9363
|
+
if(bt!==undefined){
|
|
9364
|
+
if(tl===0)b.tl=undefined
|
|
9365
|
+
else if(bt.length!==tl)bt.length=tl
|
|
9366
|
+
}
|
|
9367
|
+
if(ctx._triviaLog!==undefined&&ctx._triviaLog.length!==lg)ctx._triviaLog.length=lg
|
|
9368
|
+
if(ctx._rootTriviaLog!==undefined&&ctx._rootTriviaLog.length!==rt)ctx._rootTriviaLog.length=rt
|
|
9369
|
+
}
|
|
9370
|
+
`;
|
|
8573
9371
|
function q(s) {
|
|
8574
9372
|
return JSON.stringify(s);
|
|
8575
9373
|
}
|
|
@@ -8582,11 +9380,12 @@ function sinkReads(t, s) {
|
|
|
8582
9380
|
${t}fd=ctx._fields!==undefined?ctx._fields.length:0` : ""}${s.er ? `
|
|
8583
9381
|
${t}er=ctx._errors!==undefined?ctx._errors.length:0` : ""}`;
|
|
8584
9382
|
}
|
|
8585
|
-
function emitMark(t, buf, s = NO_SINKS, decl = true) {
|
|
9383
|
+
function emitMark(t, buf, rawMode, s = NO_SINKS, decl = true) {
|
|
8586
9384
|
if (buf) {
|
|
9385
|
+
const raw = rawMode === RAW_OMIT ? `${t}raw=b.rawLen` : rawMode === RAW_CAPTURE ? `const r=b.raw;${t}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0` : `const r=b.raw;${t}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)`;
|
|
8587
9386
|
return `${decl ? `let ${t}raw=0,${t}tl=0,${t}lv=0,${t}lg=0,${t}rt=0${sinkSlots(t, s)}
|
|
8588
9387
|
` : ""}{const b=ctx._cstBuf
|
|
8589
|
-
|
|
9388
|
+
${raw}
|
|
8590
9389
|
const h=b.ch;${t}lv=h!==undefined?h.length:b.single!==undefined?1:0
|
|
8591
9390
|
const l=b.tl;${t}tl=l!==undefined?l.length:0
|
|
8592
9391
|
${t}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
@@ -8596,7 +9395,7 @@ ${t}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${sinkReads(t,
|
|
|
8596
9395
|
` : `${t}n=false
|
|
8597
9396
|
`}{const b=ctx._cstBuf
|
|
8598
9397
|
if(b!==undefined){
|
|
8599
|
-
const r=b.raw;${t}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
|
|
9398
|
+
const r=b.raw;${t}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)
|
|
8600
9399
|
const h=b.ch;${t}lv=h!==undefined?h.length:b.single!==undefined?1:0
|
|
8601
9400
|
const l=b.tl;${t}tl=l!==undefined?l.length:0
|
|
8602
9401
|
${t}n=true
|
|
@@ -8611,14 +9410,16 @@ ${t}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
|
8611
9410
|
${t}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${sinkReads(t, s)}
|
|
8612
9411
|
}}`;
|
|
8613
9412
|
}
|
|
8614
|
-
function emitRollback(t, buf, s = NO_SINKS) {
|
|
9413
|
+
function emitRollback(t, buf, rawMode, s = NO_SINKS) {
|
|
8615
9414
|
const fd = s.fd ? `
|
|
8616
9415
|
if(ctx._fields!==undefined&&ctx._fields.length!==${t}fd)ctx._fields.length=${t}fd` : "";
|
|
8617
9416
|
const er = s.er ? `
|
|
8618
9417
|
if(ctx._errors!==undefined&&ctx._errors.length!==${t}er)ctx._errors.length=${t}er` : "";
|
|
8619
|
-
if (buf) return `
|
|
8620
|
-
if (
|
|
8621
|
-
return `
|
|
9418
|
+
if (buf && rawMode === RAW_OMIT) return `_rbNoRawBuf(ctx,${t}raw,${t}tl,${t}lv,${t}lg,${t}rt)${fd}${er}`;
|
|
9419
|
+
if (buf && rawMode === RAW_CAPTURE) return `_rbBuf(ctx,${t}raw,${t}tl,${t}lv,${t}lg,${t}rt)${fd}${er}`;
|
|
9420
|
+
if (buf) return `rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,${s.fd ? `${t}fd` : "undefined"},${s.er ? `${t}er` : "undefined"},${t}lg,${t}rt)`;
|
|
9421
|
+
if (!s.fd && !s.er) return `if(${t}n)rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,undefined,undefined,${t}lg,${t}rt)`;
|
|
9422
|
+
return `if(${t}n){rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,${s.fd ? `${t}fd` : "undefined"},${s.er ? `${t}er` : "undefined"},${t}lg,${t}rt)}`;
|
|
8622
9423
|
}
|
|
8623
9424
|
function emitTerm(callee, dst, t, l, skip) {
|
|
8624
9425
|
const fast = `const ${t}v=${callee}(input,cur,ctx)
|
|
@@ -8676,37 +9477,111 @@ function rebuildPools(cc, fx, disp, plan) {
|
|
|
8676
9477
|
})
|
|
8677
9478
|
};
|
|
8678
9479
|
}
|
|
8679
|
-
function emitAssemblySource(t, prog, cfg, extraIps = []) {
|
|
8680
|
-
const { code, k, disp, dsp, triviaLabelled } = t;
|
|
9480
|
+
function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
|
|
9481
|
+
const { code, k, fx, disp, dsp, triviaLabelled } = t;
|
|
8681
9482
|
const swapLegal = !cfg.trackLines;
|
|
8682
9483
|
const hostCst = cfg.hostCst;
|
|
8683
9484
|
const REC2 = prog.rec === 1 && cfg.tolerant;
|
|
8684
9485
|
if (cfg.coverage) throw new Unemittable("a coverage assembly");
|
|
8685
9486
|
const roots = [...Object.values(prog.rules), ...extraIps];
|
|
9487
|
+
const reachable = [...reachableSites(code, roots)];
|
|
8686
9488
|
const labels = computeSiteLabels(code, roots, hostCst);
|
|
8687
9489
|
const scalarSpecs = /* @__PURE__ */ new Set();
|
|
9490
|
+
const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
|
|
9491
|
+
const largeChoiceLiteralFamilies = /* @__PURE__ */ new Map();
|
|
9492
|
+
const largeChoiceScalarSequences = /* @__PURE__ */ new Map();
|
|
9493
|
+
const tokenChoiceCandidates = /* @__PURE__ */ new Map();
|
|
9494
|
+
const tokenChoiceDispatches = /* @__PURE__ */ new Set();
|
|
9495
|
+
const tokenChoiceBodies = /* @__PURE__ */ new Set();
|
|
8688
9496
|
if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
|
|
8689
|
-
for (const ip of
|
|
8690
|
-
if (code[ip]
|
|
8691
|
-
|
|
8692
|
-
|
|
9497
|
+
for (const ip of reachable) {
|
|
9498
|
+
if (code[ip] === OP_NODE) {
|
|
9499
|
+
const child = scalarTerminalNodeChild(code, ip);
|
|
9500
|
+
if (child >= 0) scalarSpecs.add(code[child + 1]);
|
|
9501
|
+
continue;
|
|
9502
|
+
}
|
|
9503
|
+
if (code[ip] !== OP_CHOICE || disp[code[ip + 1]].exclusive) continue;
|
|
9504
|
+
const n = code[ip + 2];
|
|
9505
|
+
for (let i = 0; i < n; i++) {
|
|
9506
|
+
const armIp = code[ip + 4 + i];
|
|
9507
|
+
const child = leadingScalarTerminal(code, armIp, 2, true, true);
|
|
9508
|
+
if (n === 2 || n === 3) {
|
|
9509
|
+
if (child >= 0) scalarSpecs.add(code[child + 1]);
|
|
9510
|
+
continue;
|
|
9511
|
+
}
|
|
9512
|
+
if (child >= 0) {
|
|
9513
|
+
const spec = k[code[child + 1]];
|
|
9514
|
+
if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
|
|
9515
|
+
largeChoiceScalarSpecs.add(code[child + 1]);
|
|
9516
|
+
continue;
|
|
9517
|
+
}
|
|
9518
|
+
}
|
|
9519
|
+
const family = leadingLiteralFamily(code, k, armIp);
|
|
9520
|
+
if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
|
|
9521
|
+
const value = k[code[terminal + 1]];
|
|
9522
|
+
return typeof value === "string" && value.length >= 2;
|
|
9523
|
+
})) {
|
|
9524
|
+
largeChoiceLiteralFamilies.set(armIp, family);
|
|
9525
|
+
}
|
|
9526
|
+
const sequence6 = leadingScalarSequence(code, armIp);
|
|
9527
|
+
if (sequence6 !== void 0 && (sequence6.trivia < 0 || swapLegal && t.triviaScan[sequence6.trivia] != null)) {
|
|
9528
|
+
largeChoiceScalarSequences.set(armIp, sequence6);
|
|
9529
|
+
}
|
|
9530
|
+
}
|
|
9531
|
+
let candidate;
|
|
9532
|
+
let ambiguous = false;
|
|
9533
|
+
for (let i = 0; i < n; i++) {
|
|
9534
|
+
const armIp = code[ip + 4 + i];
|
|
9535
|
+
if (code[armIp] !== OP_XFORM) continue;
|
|
9536
|
+
const dispatchIp = code[armIp + 2];
|
|
9537
|
+
if (code[dispatchIp] !== OP_DISPATCH) continue;
|
|
9538
|
+
const selectorIp = code[dispatchIp + 1];
|
|
9539
|
+
if (code[selectorIp] !== OP_LEX_BODY) continue;
|
|
9540
|
+
if (candidate !== void 0) {
|
|
9541
|
+
ambiguous = true;
|
|
9542
|
+
break;
|
|
9543
|
+
}
|
|
9544
|
+
candidate = { arm: i, dispatchIp };
|
|
9545
|
+
}
|
|
9546
|
+
if (!ambiguous && candidate !== void 0) {
|
|
9547
|
+
tokenChoiceCandidates.set(ip, candidate);
|
|
9548
|
+
tokenChoiceDispatches.add(candidate.dispatchIp);
|
|
9549
|
+
tokenChoiceBodies.add(code[code[candidate.dispatchIp + 1] + 1]);
|
|
9550
|
+
}
|
|
8693
9551
|
}
|
|
8694
9552
|
}
|
|
8695
|
-
const
|
|
8696
|
-
|
|
8697
|
-
|
|
8698
|
-
|
|
8699
|
-
|
|
8700
|
-
|
|
8701
|
-
|
|
8702
|
-
|
|
8703
|
-
|
|
9553
|
+
const needsNoRawPrelude = !hostCst && reachable.some((ip) => {
|
|
9554
|
+
const op = code[ip];
|
|
9555
|
+
return (op === OP_NODE || op === OP_NODE_TRACK) && code[ip + 1] >= 0 && code[ip + 4] < 0 && (code[ip + 3] & 2) !== 0;
|
|
9556
|
+
});
|
|
9557
|
+
const sinkSites = reachable;
|
|
9558
|
+
const sinkBits = /* @__PURE__ */ new Map();
|
|
9559
|
+
for (const ip of sinkSites) {
|
|
9560
|
+
const op = code[ip];
|
|
9561
|
+
sinkBits.set(
|
|
9562
|
+
ip,
|
|
9563
|
+
op === OP_SCAN ? 3 : (op === OP_FIELD ? 1 : 0) | (op === OP_EXPECT || REC2 && (op === OP_REP || op === OP_REPV) ? 2 : 0)
|
|
9564
|
+
);
|
|
9565
|
+
}
|
|
9566
|
+
const sinkKids = [];
|
|
9567
|
+
let sinkChanged = true;
|
|
9568
|
+
while (sinkChanged) {
|
|
9569
|
+
sinkChanged = false;
|
|
9570
|
+
for (const ip of sinkSites) {
|
|
9571
|
+
let bits = sinkBits.get(ip) ?? 0;
|
|
9572
|
+
sinkKids.length = 0;
|
|
9573
|
+
childSlots(code, ip, sinkKids);
|
|
9574
|
+
for (let i = 0; i < sinkKids.length; i++) bits |= sinkBits.get(sinkKids[i]) ?? 0;
|
|
9575
|
+
if (bits !== sinkBits.get(ip)) {
|
|
9576
|
+
sinkBits.set(ip, bits);
|
|
9577
|
+
sinkChanged = true;
|
|
8704
9578
|
}
|
|
8705
|
-
if (op === OP_FIELD) fd = true;
|
|
8706
|
-
else if (op === OP_EXPECT) er = true;
|
|
8707
9579
|
}
|
|
8708
|
-
|
|
8709
|
-
|
|
9580
|
+
}
|
|
9581
|
+
const sinksAt = (ip) => {
|
|
9582
|
+
const bits = sinkBits.get(ip) ?? 0;
|
|
9583
|
+
return bits === 0 ? NO_SINKS : { fd: (bits & 1) !== 0, er: (bits & 2) !== 0 };
|
|
9584
|
+
};
|
|
8710
9585
|
const bodies = [];
|
|
8711
9586
|
const byIp = /* @__PURE__ */ new Map();
|
|
8712
9587
|
const reached = /* @__PURE__ */ new Set();
|
|
@@ -8733,9 +9608,117 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
|
|
|
8733
9608
|
const fxRef = (i) => hoist("fx", `FX[${i}]`);
|
|
8734
9609
|
const fnRef = (i) => hoist("fn", `FNS[${i}]`);
|
|
8735
9610
|
const recognizerRef = (i) => hoist("rec", `RECOG[${i}]`);
|
|
9611
|
+
const scalarSequenceRefs = /* @__PURE__ */ new Map();
|
|
9612
|
+
const scalarSequenceRef = (sequence6) => {
|
|
9613
|
+
const key = `${sequence6.trivia}:${sequence6.terminals.map((terminal) => code[terminal + 1]).join(",")}`;
|
|
9614
|
+
const prior = scalarSequenceRefs.get(key);
|
|
9615
|
+
if (prior !== void 0) return prior;
|
|
9616
|
+
const recognizers = sequence6.terminals.map((terminal) => recognizerRef(code[terminal + 1]));
|
|
9617
|
+
const expected = sequence6.terminals.map((terminal) => fxRef(code[terminal + 2]));
|
|
9618
|
+
const scan = sequence6.trivia < 0 ? void 0 : hoist("ts", `TRIVIASCAN[${sequence6.trivia}]`);
|
|
9619
|
+
const name = `_sd${scalarSequenceRefs.size}_`;
|
|
9620
|
+
const steps = recognizers.map((recognize, i) => `${i === 0 ? "let " : ""}at=${i === 0 ? "pos" : scan === void 0 ? "cur" : `${scan}(input,cur)`}
|
|
9621
|
+
${i === 0 ? "let " : ""}cur=${recognize}(input,at)
|
|
9622
|
+
if(cur<0){_pfSeqEnd=at;return ${~i}}`).join("\n");
|
|
9623
|
+
choiceDefs.push(`function ${name}(input,pos){
|
|
9624
|
+
${steps}
|
|
9625
|
+
return cur
|
|
9626
|
+
}`);
|
|
9627
|
+
const made = { name, expected };
|
|
9628
|
+
scalarSequenceRefs.set(key, made);
|
|
9629
|
+
return made;
|
|
9630
|
+
};
|
|
8736
9631
|
const sentRef = (cls) => cls < 0 ? "undefined" : hoist("sent", `SENTS[${cls}]`);
|
|
8737
9632
|
let uid = 0;
|
|
8738
9633
|
const tmp = () => `_t${uid++}_`;
|
|
9634
|
+
const dispatchClaim = (m) => {
|
|
9635
|
+
switch (m[0]) {
|
|
9636
|
+
case 0:
|
|
9637
|
+
return `key.startsWith(${q(m[1])})`;
|
|
9638
|
+
case 1:
|
|
9639
|
+
return `key.endsWith(${q(m[1])})`;
|
|
9640
|
+
case 3:
|
|
9641
|
+
return `asciiFoldKey(key).startsWith(${q(m[1])})`;
|
|
9642
|
+
case 4:
|
|
9643
|
+
return `asciiFoldKey(key).endsWith(${q(m[1])})`;
|
|
9644
|
+
default: {
|
|
9645
|
+
if (!m[2].includes("g") && !m[2].includes("y")) {
|
|
9646
|
+
try {
|
|
9647
|
+
new RegExp(m[1], m[2]);
|
|
9648
|
+
return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
|
|
9649
|
+
} catch {
|
|
9650
|
+
}
|
|
9651
|
+
}
|
|
9652
|
+
return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
|
|
9653
|
+
}
|
|
9654
|
+
}
|
|
9655
|
+
};
|
|
9656
|
+
const tokenDecisionRefs = /* @__PURE__ */ new Map();
|
|
9657
|
+
function tokenDecisionFor(dispatchIp) {
|
|
9658
|
+
const prior = tokenDecisionRefs.get(dispatchIp);
|
|
9659
|
+
if (prior !== void 0) return prior;
|
|
9660
|
+
const selectorIp = code[dispatchIp + 1];
|
|
9661
|
+
const body = code[selectorIp + 1];
|
|
9662
|
+
const lineFlags = code[selectorIp + 4];
|
|
9663
|
+
const hasSuffix = (lineFlags & 4) !== 0;
|
|
9664
|
+
const di = code[dispatchIp + 2];
|
|
9665
|
+
const spec = dsp[di];
|
|
9666
|
+
const n = code[dispatchIp + 5];
|
|
9667
|
+
validateDispatchSpec(spec, n, code[dispatchIp + 4]);
|
|
9668
|
+
const recognize = hoist("lex", `LEX[${body}]`);
|
|
9669
|
+
const bk = hoist("bk", `DSP[${di}].byKey`);
|
|
9670
|
+
const expected = hoist("dx", `DSP[${di}].expected`);
|
|
9671
|
+
const fold = spec.byFold.size > 0 ? `if(arm===undefined)arm=${hoist("bf", `DSP[${di}].byFold`)}.get(asciiFoldKey(key))
|
|
9672
|
+
` : "";
|
|
9673
|
+
const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
|
|
9674
|
+
${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${dispatchClaim(m)})arm=${m[3]}`).join("\n")}
|
|
9675
|
+
}
|
|
9676
|
+
`;
|
|
9677
|
+
const foldedEntries = [...spec.byFold.entries()];
|
|
9678
|
+
const fixedFunctionChoice = spec.byKey.size === 0 && foldedEntries.length === 1 && spec.match.length === 1 && spec.match[0][0] === 2 && spec.match[0][1] === "^(?!(?:url|calc)\\($).+\\($" && spec.match[0][2] === "i" && code[dispatchIp + 3] < 0;
|
|
9679
|
+
const foldedRangeEquals = (value) => {
|
|
9680
|
+
const folded = value.replace(/[A-Z]/g, (c) => c.toLowerCase());
|
|
9681
|
+
return `e-pos===${folded.length}&&${[...folded].map((c, i) => {
|
|
9682
|
+
const cc = c.charCodeAt(0);
|
|
9683
|
+
return `_asciiFoldCode(input.charCodeAt(pos+${i}))===${cc}`;
|
|
9684
|
+
}).join("&&")}`;
|
|
9685
|
+
};
|
|
9686
|
+
const classify = fixedFunctionChoice ? (() => {
|
|
9687
|
+
const [exact, exactArm] = foldedEntries[0];
|
|
9688
|
+
const genericArm = spec.match[0][3];
|
|
9689
|
+
return `let arm
|
|
9690
|
+
if(${foldedRangeEquals(exact)})arm=${exactArm}
|
|
9691
|
+
else if(sm&&e>pos+1){
|
|
9692
|
+
let clean=true
|
|
9693
|
+
for(let i=pos;i<e;i++){const c=input.charCodeAt(i);if(c===10||c===13||c===0x2028||c===0x2029){clean=false;break}}
|
|
9694
|
+
if(clean&&!(${foldedRangeEquals("url(")})&&!(${foldedRangeEquals("calc(")}))arm=${genericArm}
|
|
9695
|
+
}`;
|
|
9696
|
+
})() : `const key=input.slice(pos,e)
|
|
9697
|
+
let arm=${bk}.get(key)
|
|
9698
|
+
${fold}${chain}`;
|
|
9699
|
+
const name = `_td${tokenDecisionRefs.size}_`;
|
|
9700
|
+
choiceDefs.push(`function ${name}(input,pos){
|
|
9701
|
+
const r=${recognize}(input,pos)
|
|
9702
|
+
if(r<0)return -1
|
|
9703
|
+
const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
|
|
9704
|
+
${classify}
|
|
9705
|
+
if(arm===undefined){
|
|
9706
|
+
${code[dispatchIp + 3] < 0 ? "_pfTokEnd=e;return 0" : `arm=${n}`}
|
|
9707
|
+
}
|
|
9708
|
+
${fixedFunctionChoice ? "const key=input.slice(pos,e)" : ""}
|
|
9709
|
+
_pfTokInput=input
|
|
9710
|
+
_pfTokPos=pos
|
|
9711
|
+
_pfTokBody=${body}
|
|
9712
|
+
_pfTokPacked=r
|
|
9713
|
+
_pfTokValue=key
|
|
9714
|
+
_pfTokDispatch=${dispatchIp}
|
|
9715
|
+
_pfTokArm=arm
|
|
9716
|
+
return 1
|
|
9717
|
+
}`);
|
|
9718
|
+
const made = { name, expected };
|
|
9719
|
+
tokenDecisionRefs.set(dispatchIp, made);
|
|
9720
|
+
return made;
|
|
9721
|
+
}
|
|
8739
9722
|
function skipFor(l) {
|
|
8740
9723
|
if (l.tri < 0) return "_skipTrivia";
|
|
8741
9724
|
const ki = l.tri;
|
|
@@ -8823,7 +9806,8 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
8823
9806
|
const op = code[ip];
|
|
8824
9807
|
const head = `function ${fname}(input,pos,ctx){`;
|
|
8825
9808
|
const L = labels.at(ip);
|
|
8826
|
-
const
|
|
9809
|
+
const sinks = sinksAt(ip);
|
|
9810
|
+
const pushLeaf = L.buf && !cfg.trackLines ? L.raw === RAW_OMIT ? "_pushLeafNoRawBuf" : L.raw === RAW_CAPTURE ? "_pushLeafBuf" : "_pushLeaf" : "_pushLeaf";
|
|
8827
9811
|
const captureLeaf = (value) => {
|
|
8828
9812
|
const call = `${pushLeaf}(ctx,${value},pos,e)`;
|
|
8829
9813
|
return L.buf ? call : `if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)${call}`;
|
|
@@ -8987,12 +9971,12 @@ return err
|
|
|
8987
9971
|
}
|
|
8988
9972
|
case OP_ROUTED: {
|
|
8989
9973
|
const fb = code[ip + 1];
|
|
8990
|
-
const
|
|
9974
|
+
const fallback2 = fb >= 0 ? link(fb) : void 0;
|
|
8991
9975
|
const push = `pushCstLeaf(ctx,{_tag:'leaf',value:it.value,span:it.span})`;
|
|
8992
9976
|
return `${head}
|
|
8993
9977
|
const it=ctx._routed
|
|
8994
9978
|
if(it===undefined||pos!==it.span.start){
|
|
8995
|
-
${
|
|
9979
|
+
${fallback2 !== void 0 ? `return ${fallback2}(input,pos,ctx)` : "ctx._fe=pos;ctx._fx=ROUTED_FX;return FAIL"}
|
|
8996
9980
|
}
|
|
8997
9981
|
${L.buf ? push : `if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)${push}`}
|
|
8998
9982
|
EC.e=it.span.end
|
|
@@ -9074,20 +10058,24 @@ return out
|
|
|
9074
10058
|
}`;
|
|
9075
10059
|
}
|
|
9076
10060
|
case OP_LEX_BODY: {
|
|
9077
|
-
const
|
|
10061
|
+
const body = code[ip + 1];
|
|
10062
|
+
const recognize = hoist("lex", `LEX[${body}]`);
|
|
9078
10063
|
const expected = fxRef(code[ip + 2]);
|
|
9079
10064
|
const suffixExpected = fxRef(code[ip + 3]);
|
|
9080
10065
|
const lineFlags = code[ip + 4];
|
|
9081
10066
|
const hasSuffix = (lineFlags & 4) !== 0;
|
|
10067
|
+
const pending = tokenChoiceBodies.has(body);
|
|
9082
10068
|
return `${head}
|
|
9083
|
-
const
|
|
10069
|
+
${pending ? `const tp=_pfTokBody===${body}&&_pfTokInput===input&&_pfTokPos===pos
|
|
10070
|
+
const r=tp?_pfTokPacked:${recognize}(input,pos)` : `const r=${recognize}(input,pos)`}
|
|
9084
10071
|
if(r<0){ctx._fe=pos;ctx._fx=${expected};if(ctx._probe!==undefined)failAt(ctx,${expected},pos);return FAIL}
|
|
9085
10072
|
const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
|
|
9086
10073
|
${(lineFlags & 1) !== 0 ? "_trackLines(ctx,input,sm?e-1:e)" : ""}
|
|
9087
10074
|
${hasSuffix ? "ctx._fc=false" : ""}
|
|
9088
10075
|
${hasSuffix && (lineFlags & 2) !== 0 ? "if(sm)_trackLines(ctx,input,e)" : ""}
|
|
9089
10076
|
${hasSuffix ? `if(!sm){ctx._fe=e;ctx._fx=${suffixExpected};if(ctx._probe!==undefined)failAt(ctx,${suffixExpected},e)}` : ""}
|
|
9090
|
-
const v
|
|
10077
|
+
const v=${pending ? "tp?_pfTokValue:" : ""}input.slice(pos,e)
|
|
10078
|
+
${pending ? "if(tp){_pfTokBody=-1;_pfTokValue=undefined}" : ""}
|
|
9091
10079
|
if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
|
|
9092
10080
|
EC.e=e
|
|
9093
10081
|
return v
|
|
@@ -9143,12 +10131,13 @@ return v
|
|
|
9143
10131
|
/* ── transaction ─────────────────────────────────────────────────────── */
|
|
9144
10132
|
case OP_ATTEMPT: {
|
|
9145
10133
|
const child = link(code[ip + 1]);
|
|
10134
|
+
const clean = !REC2 && failureRollbackClean(prog, ip);
|
|
9146
10135
|
const p = tmp();
|
|
9147
10136
|
return `${head}
|
|
9148
|
-
${emitMark(p, L.buf, sinks)}
|
|
10137
|
+
${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
|
|
9149
10138
|
const v=${child}(input,pos,ctx)
|
|
9150
10139
|
if(v!==FAIL)return v
|
|
9151
|
-
${emitRollback(p, L.buf, sinks)}
|
|
10140
|
+
${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
|
|
9152
10141
|
if(ctx._fc===true)return FAIL
|
|
9153
10142
|
ctx._fe=pos
|
|
9154
10143
|
return FAIL
|
|
@@ -9171,9 +10160,9 @@ return FAIL
|
|
|
9171
10160
|
const xf = fxRef(code[ip + 2]);
|
|
9172
10161
|
const p = tmp();
|
|
9173
10162
|
return `${head}
|
|
9174
|
-
${emitMark(p, L.buf, sinks)}
|
|
10163
|
+
${emitMark(p, L.buf, L.raw, sinks)}
|
|
9175
10164
|
const v=${child}(input,pos,ctx)
|
|
9176
|
-
${emitRollback(p, L.buf, sinks)}
|
|
10165
|
+
${emitRollback(p, L.buf, L.raw, sinks)}
|
|
9177
10166
|
if(v===FAIL){EC.e=pos;return null}
|
|
9178
10167
|
ctx._fe=pos
|
|
9179
10168
|
ctx._fx=${xf}
|
|
@@ -9185,9 +10174,9 @@ return FAIL
|
|
|
9185
10174
|
const xf = fxRef(code[ip + 2]);
|
|
9186
10175
|
const p = tmp();
|
|
9187
10176
|
return `${head}
|
|
9188
|
-
${emitMark(p, L.buf, sinks)}
|
|
10177
|
+
${emitMark(p, L.buf, L.raw, sinks)}
|
|
9189
10178
|
const v=${child}(input,pos,ctx)
|
|
9190
|
-
${emitRollback(p, L.buf, sinks)}
|
|
10179
|
+
${emitRollback(p, L.buf, L.raw, sinks)}
|
|
9191
10180
|
if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
|
|
9192
10181
|
EC.e=pos
|
|
9193
10182
|
return null
|
|
@@ -9195,14 +10184,15 @@ return null
|
|
|
9195
10184
|
}
|
|
9196
10185
|
case OP_OPT: {
|
|
9197
10186
|
const child = link(code[ip + 1]);
|
|
10187
|
+
const clean = !REC2 && failureRollbackClean(prog, ip);
|
|
9198
10188
|
const p = tmp();
|
|
9199
10189
|
return `${head}
|
|
9200
|
-
${emitMark(p, L.buf, sinks)}
|
|
10190
|
+
${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
|
|
9201
10191
|
ctx._fc=false
|
|
9202
10192
|
const v=${child}(input,pos,ctx)
|
|
9203
10193
|
if(v===FAIL){
|
|
9204
10194
|
if(ctx._fc===true)return FAIL
|
|
9205
|
-
${emitRollback(p, L.buf, sinks)}
|
|
10195
|
+
${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
|
|
9206
10196
|
EC.e=pos
|
|
9207
10197
|
return null
|
|
9208
10198
|
}
|
|
@@ -9301,57 +10291,193 @@ return FAIL
|
|
|
9301
10291
|
const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
|
|
9302
10292
|
const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
|
|
9303
10293
|
const gateRefs = Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
|
|
10294
|
+
const tokenCandidate = tokenChoiceCandidates.get(ip);
|
|
10295
|
+
const pretests = Array.from({ length: n }, (_, i) => {
|
|
10296
|
+
if (tokenCandidate?.arm === i) {
|
|
10297
|
+
return { token: tokenDecisionFor(tokenCandidate.dispatchIp) };
|
|
10298
|
+
}
|
|
10299
|
+
const terminal = leadingScalarTerminal(code, code[base + i], 2, true, true);
|
|
10300
|
+
if (terminal >= 0) {
|
|
10301
|
+
const spec = code[terminal + 1];
|
|
10302
|
+
if ((n === 2 || n === 3 ? scalarSpecs : largeChoiceScalarSpecs).has(spec)) {
|
|
10303
|
+
return { scalar: [recognizerRef(spec)] };
|
|
10304
|
+
}
|
|
10305
|
+
}
|
|
10306
|
+
const family = largeChoiceLiteralFamilies.get(code[base + i]);
|
|
10307
|
+
if (family !== void 0) {
|
|
10308
|
+
return { scalar: family.map((member) => recognizerRef(code[member + 1])) };
|
|
10309
|
+
}
|
|
10310
|
+
const sequence6 = largeChoiceScalarSequences.get(code[base + i]);
|
|
10311
|
+
return sequence6 === void 0 ? void 0 : { sequence: scalarSequenceRef(sequence6) };
|
|
10312
|
+
});
|
|
9304
10313
|
const maskable = n <= 32;
|
|
9305
10314
|
const maskName = maskable ? hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`) : "";
|
|
9306
10315
|
if (maskable) maskPlan.push(~di);
|
|
9307
10316
|
const p = tmp();
|
|
9308
|
-
const
|
|
9309
|
-
|
|
10317
|
+
const encodedRollbackMask = choiceRollbackMask(prog, ip) ?? -1;
|
|
10318
|
+
const rollbackMask = REC2 ? -1 : encodedRollbackMask;
|
|
10319
|
+
const hasRollback = rollbackMask !== 0;
|
|
10320
|
+
const startFailureExact = arms.every((_arm, i) => {
|
|
10321
|
+
const terminal = leadingScalarTerminal(code, code[base + i], 0, false);
|
|
10322
|
+
if (terminal < 0) return false;
|
|
10323
|
+
const op2 = code[terminal];
|
|
10324
|
+
const spec = k[code[terminal + 1]];
|
|
10325
|
+
const terminalFx = fx[code[terminal + 2]];
|
|
10326
|
+
const armFx = fx[code[base + n + i]];
|
|
10327
|
+
if (terminalFx.length !== armFx.length || terminalFx.some((expected2, at) => expected2 !== armFx[at])) return false;
|
|
10328
|
+
if (op2 === OP_LIT) return typeof spec === "string" && spec.length > 0;
|
|
10329
|
+
return op2 === OP_RX && spec instanceof RegExp && !regexCanMatchEmpty(spec.source);
|
|
10330
|
+
});
|
|
10331
|
+
const rollbackFor = (i) => rollbackMask === -1 || (rollbackMask & 1 << i) !== 0 ? emitRollback(p, L.buf, L.raw, sinks) : "";
|
|
10332
|
+
if (choiceCannotCommit(prog, ip) && !startFailureExact) {
|
|
10333
|
+
const deepAt = Array.from({ length: n }, () => tmp());
|
|
10334
|
+
const deepFx = Array.from({ length: n }, () => tmp());
|
|
10335
|
+
const remember = (i, at, expectedSet) => `${deepAt[i]}=${at};${deepFx[i]}=${expectedSet}`;
|
|
10336
|
+
const lazyArms = (ascii) => arms.map((arm, i) => {
|
|
10337
|
+
const pretest = pretests[i];
|
|
10338
|
+
const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
|
|
10339
|
+
const scalarCondition = pretest?.scalar === void 0 ? "" : pretest.scalar.length === 1 ? `&&${pretest.scalar[0]}(input,pos)>=0` : `&&(${pretest.scalar.map((recognize) => `${recognize}(input,pos)>=0`).join("||")})`;
|
|
10340
|
+
const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
|
|
10341
|
+
const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
|
|
10342
|
+
const gate2 = ascii ? `(bits&${1 << i})!==0${condition}` : `(${gateRefs[i]}===null||classHas(${gateRefs[i]},c))${condition}`;
|
|
10343
|
+
const routeMiss = pretest?.token === void 0 ? "" : `
|
|
10344
|
+
if(${decision}===0){
|
|
10345
|
+
ctx._fc=false
|
|
10346
|
+
{const at=_pfTokEnd
|
|
10347
|
+
${remember(i, "at", pretest.token.expected)}}
|
|
10348
|
+
}`;
|
|
10349
|
+
const sequenceMiss = pretest?.sequence === void 0 ? "" : `
|
|
10350
|
+
else if(${ascii ? `(bits&${1 << i})!==0&&` : ""}${decision}<0){
|
|
10351
|
+
ctx._fc=false
|
|
10352
|
+
{const at=_pfSeqEnd
|
|
10353
|
+
${remember(i, "at", pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("") + pretest.sequence.expected.at(-1))}}
|
|
10354
|
+
}`;
|
|
10355
|
+
return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
|
|
10356
|
+
`}if(${gate2}){
|
|
10357
|
+
ctx._fc=false
|
|
10358
|
+
{const v=${arm}(input,pos,ctx)
|
|
10359
|
+
if(v!==FAIL)return v}
|
|
10360
|
+
{const at=ctx._fe??pos
|
|
10361
|
+
${remember(i, "at", "ctx._fx")}}
|
|
10362
|
+
${rollbackFor(i)}
|
|
10363
|
+
}${routeMiss}${sequenceMiss}`;
|
|
10364
|
+
}).join("\n");
|
|
10365
|
+
const merge = deepAt.map((at, i) => `{const at=${at}??pos
|
|
10366
|
+
const ex=${at}===undefined?${expected[i]}:${deepFx[i]}
|
|
10367
|
+
if(at>best){best=at;acc=_accSet(ex,undefined)}
|
|
10368
|
+
else if(at===best)acc=_accSet(ex,acc)
|
|
10369
|
+
}`).join("\n");
|
|
10370
|
+
const finish = `let best=pos,acc
|
|
10371
|
+
${merge}
|
|
10372
|
+
ctx._fe=pos;ctx._fx=acc??${choiceFx}
|
|
10373
|
+
return FAIL`;
|
|
10374
|
+
return `${head}
|
|
10375
|
+
const c=lead(input,pos)
|
|
10376
|
+
${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
|
|
10377
|
+
${deepAt.map((at, i) => `let ${at},${deepFx[i]}`).join("\n")}
|
|
10378
|
+
${maskable ? `if(c<128){
|
|
10379
|
+
const bits=${maskName}[c<0?128:c]
|
|
10380
|
+
if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
|
|
10381
|
+
${lazyArms(true)}
|
|
10382
|
+
}else{
|
|
10383
|
+
${lazyArms(false)}
|
|
10384
|
+
}
|
|
10385
|
+
` : lazyArms(false)}
|
|
10386
|
+
${finish}
|
|
10387
|
+
}`;
|
|
10388
|
+
}
|
|
10389
|
+
const needsCatch = maskable || startFailureExact;
|
|
10390
|
+
const catchName = needsCatch ? `_cx${uid++}_` : "";
|
|
10391
|
+
if (needsCatch) {
|
|
9310
10392
|
const catchCases = expected.map((e, i) => `case ${i}:if(target<=${i})return acc;acc=_accSet(${e},acc)`).join("\n");
|
|
9311
10393
|
choiceDefs.push(`function ${catchName}(target,prev,acc){switch(prev){
|
|
9312
10394
|
${catchCases}
|
|
9313
10395
|
}return acc}`);
|
|
9314
10396
|
}
|
|
9315
10397
|
const maskArms = maskable ? arms.map((arm, i) => {
|
|
9316
|
-
|
|
10398
|
+
const pretest = pretests[i];
|
|
10399
|
+
const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
|
|
10400
|
+
const scalarCondition = pretest?.scalar === void 0 ? "" : pretest.scalar.length === 1 ? `&&${pretest.scalar[0]}(input,pos)>=0` : `&&(${pretest.scalar.map((recognize) => `${recognize}(input,pos)>=0`).join("||")})`;
|
|
10401
|
+
const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
|
|
10402
|
+
const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
|
|
10403
|
+
const routeMiss = pretest?.token === void 0 ? "" : `
|
|
10404
|
+
if(${decision}===0){
|
|
10405
|
+
ctx._fc=false
|
|
10406
|
+
${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
|
|
10407
|
+
prev=${i + 1}`}
|
|
10408
|
+
{const at=_pfTokEnd
|
|
10409
|
+
if(at>best){best=at;acc=undefined}
|
|
10410
|
+
if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.token.expected},acc)}
|
|
10411
|
+
}`;
|
|
10412
|
+
const sequenceMiss = pretest?.sequence === void 0 ? "" : `
|
|
10413
|
+
else if((bits&${1 << i})!==0&&${decision}<0){
|
|
10414
|
+
ctx._fc=false
|
|
10415
|
+
${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
|
|
10416
|
+
prev=${i + 1}`}
|
|
10417
|
+
{const at=_pfSeqEnd
|
|
10418
|
+
if(at>best){best=at;acc=undefined}
|
|
10419
|
+
if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("")}${pretest.sequence.expected.at(-1)},acc)}
|
|
10420
|
+
}`;
|
|
10421
|
+
return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
|
|
10422
|
+
`}if((bits&${1 << i})!==0${condition}){
|
|
9317
10423
|
ctx._fc=false
|
|
9318
10424
|
{const v=${arm}(input,pos,ctx)
|
|
9319
10425
|
if(v!==FAIL)return v}
|
|
9320
|
-
if(best===pos)acc=${catchName}(${i},prev,acc)
|
|
9321
|
-
prev=${i + 1}
|
|
10426
|
+
${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
|
|
10427
|
+
prev=${i + 1}`}
|
|
9322
10428
|
{const at=ctx._fe??pos
|
|
9323
10429
|
if(at>best){best=at;acc=undefined}
|
|
9324
|
-
if(at===best)acc=_accSet(ctx._fx,acc)}
|
|
9325
|
-
if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
|
|
9326
|
-
${
|
|
9327
|
-
}`;
|
|
10430
|
+
if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(ctx._fx,acc)}
|
|
10431
|
+
if(ctx._fc===true){${startFailureExact ? `if(best===pos){acc=${catchName}(${i},0,undefined);acc=_accSet(ctx._fx,acc)}` : ""}if(acc!==undefined)ctx._fx=acc;return FAIL}
|
|
10432
|
+
${rollbackFor(i)}
|
|
10433
|
+
}${routeMiss}${sequenceMiss}`;
|
|
9328
10434
|
}).join("\n") : "";
|
|
9329
|
-
const generalArms = arms.map((arm, i) =>
|
|
10435
|
+
const generalArms = arms.map((arm, i) => {
|
|
10436
|
+
const pretest = pretests[i];
|
|
10437
|
+
const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
|
|
10438
|
+
const scalarCondition = pretest?.scalar === void 0 ? "" : pretest.scalar.length === 1 ? `&&${pretest.scalar[0]}(input,pos)>=0` : `&&(${pretest.scalar.map((recognize) => `${recognize}(input,pos)>=0`).join("||")})`;
|
|
10439
|
+
const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
|
|
10440
|
+
const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
|
|
10441
|
+
const miss = pretest?.sequence !== void 0 ? `else if(${decision}<0){
|
|
10442
|
+
ctx._fc=false
|
|
10443
|
+
const at=_pfSeqEnd
|
|
10444
|
+
if(at>best){best=at;acc=undefined}
|
|
10445
|
+
if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("")}${pretest.sequence.expected.at(-1)},acc)
|
|
10446
|
+
}${startFailureExact ? "" : `else if(best===pos)acc=_accSet(${expected[i]},acc)`}` : pretest?.token === void 0 ? startFailureExact ? "" : `else if(best===pos)acc=_accSet(${expected[i]},acc)` : `else if(${decision}===0){
|
|
10447
|
+
ctx._fc=false
|
|
10448
|
+
const at=_pfTokEnd
|
|
10449
|
+
if(at>best){best=at;acc=undefined}
|
|
10450
|
+
if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.token.expected},acc)
|
|
10451
|
+
}${startFailureExact ? "" : `else if(best===pos)acc=_accSet(${expected[i]},acc)`}`;
|
|
10452
|
+
return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
|
|
10453
|
+
`}if((${gateRefs[i]}===null||classHas(${gateRefs[i]},c))${condition}){
|
|
9330
10454
|
ctx._fc=false
|
|
9331
10455
|
{const v=${arm}(input,pos,ctx)
|
|
9332
10456
|
if(v!==FAIL)return v}
|
|
9333
10457
|
{const at=ctx._fe??pos
|
|
9334
10458
|
if(at>best){best=at;acc=undefined}
|
|
9335
|
-
if(at===best)acc=_accSet(ctx._fx,acc)}
|
|
9336
|
-
if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
|
|
9337
|
-
${
|
|
9338
|
-
}
|
|
10459
|
+
if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(ctx._fx,acc)}
|
|
10460
|
+
if(ctx._fc===true){${startFailureExact ? `if(best===pos){acc=${catchName}(${i},0,undefined);acc=_accSet(ctx._fx,acc)}` : ""}if(acc!==undefined)ctx._fx=acc;return FAIL}
|
|
10461
|
+
${rollbackFor(i)}
|
|
10462
|
+
}${miss}`;
|
|
10463
|
+
}).join("\n");
|
|
9339
10464
|
return `${head}
|
|
9340
10465
|
const c=lead(input,pos)
|
|
9341
|
-
${emitMark(p, L.buf, sinks)}
|
|
10466
|
+
${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
|
|
9342
10467
|
let acc
|
|
9343
10468
|
let best=pos
|
|
9344
10469
|
${maskable ? `if(c<128){
|
|
9345
10470
|
const bits=${maskName}[c<0?128:c]
|
|
9346
|
-
|
|
10471
|
+
if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
|
|
10472
|
+
${startFailureExact ? "" : "let prev=0"}
|
|
9347
10473
|
${maskArms}
|
|
9348
|
-
if(best===pos)acc=${catchName}(${n},prev,acc)
|
|
9349
|
-
ctx._fe=pos;ctx._fx
|
|
10474
|
+
${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${n},prev,acc)`}
|
|
10475
|
+
ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
|
|
9350
10476
|
return FAIL
|
|
9351
10477
|
}
|
|
9352
10478
|
` : ""}
|
|
9353
10479
|
${generalArms}
|
|
9354
|
-
ctx._fe=pos;ctx._fx
|
|
10480
|
+
ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
|
|
9355
10481
|
return FAIL
|
|
9356
10482
|
}`;
|
|
9357
10483
|
}
|
|
@@ -9370,30 +10496,8 @@ return FAIL
|
|
|
9370
10496
|
for (let i = 0; i < n; i++) arms.push(link(code[armBase + i]));
|
|
9371
10497
|
const bk = hoist("bk", `DSP[${di}].byKey`);
|
|
9372
10498
|
const dx = hoist("dx", `DSP[${di}].expected`);
|
|
9373
|
-
const claims = (m) => {
|
|
9374
|
-
switch (m[0]) {
|
|
9375
|
-
case 0:
|
|
9376
|
-
return `key.startsWith(${q(m[1])})`;
|
|
9377
|
-
case 1:
|
|
9378
|
-
return `key.endsWith(${q(m[1])})`;
|
|
9379
|
-
case 3:
|
|
9380
|
-
return `asciiFoldKey(key).startsWith(${q(m[1])})`;
|
|
9381
|
-
case 4:
|
|
9382
|
-
return `asciiFoldKey(key).endsWith(${q(m[1])})`;
|
|
9383
|
-
default: {
|
|
9384
|
-
if (!m[2].includes("g") && !m[2].includes("y")) {
|
|
9385
|
-
try {
|
|
9386
|
-
new RegExp(m[1], m[2]);
|
|
9387
|
-
return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
|
|
9388
|
-
} catch {
|
|
9389
|
-
}
|
|
9390
|
-
}
|
|
9391
|
-
return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
|
|
9392
|
-
}
|
|
9393
|
-
}
|
|
9394
|
-
};
|
|
9395
10499
|
const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
|
|
9396
|
-
${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${
|
|
10500
|
+
${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${dispatchClaim(m)})arm=${m[3]}`).join("\n")}
|
|
9397
10501
|
}
|
|
9398
10502
|
`;
|
|
9399
10503
|
const fold = spec.byFold.size > 0 ? `if(arm===undefined)arm=${hoist("bf", `DSP[${di}].byFold`)}.get(asciiFoldKey(key))
|
|
@@ -9401,33 +10505,43 @@ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${claims(m)})arm=${m[3]}
|
|
|
9401
10505
|
const m1 = tmp();
|
|
9402
10506
|
const m2 = tmp();
|
|
9403
10507
|
const routedCall = (target) => `{const savedRouted=ctx._routed
|
|
9404
|
-
${emitRollback(m1, L.buf, sinks)}
|
|
9405
|
-
${emitMark(m2, L.buf, sinks, false)}
|
|
10508
|
+
${emitRollback(m1, L.buf, L.raw, sinks)}
|
|
10509
|
+
${emitMark(m2, L.buf, L.raw, sinks, false)}
|
|
9406
10510
|
ctx._routed={value:key,span:{start:pos,end:selEnd}}
|
|
9407
10511
|
try{v=${target}(input,pos,ctx)}finally{ctx._routed=savedRouted}
|
|
9408
10512
|
break}`;
|
|
9409
10513
|
const plainCall = (target) => `v=${target}(input,selEnd,ctx);break`;
|
|
9410
10514
|
const armCases = arms.map((target, i) => `case ${i}:${spec.routed[i] === 1 ? routedCall(target) : plainCall(target)}`).join("\n");
|
|
9411
10515
|
const fallbackCase = other === void 0 ? "" : `default:${otherRouted ? routedCall(other) : plainCall(other)}`;
|
|
10516
|
+
const armSelection = tokenChoiceDispatches.has(ip) ? `const tp=_pfTokDispatch===${ip}&&_pfTokInput===input&&_pfTokPos===pos
|
|
10517
|
+
let arm
|
|
10518
|
+
if(tp){
|
|
10519
|
+
arm=_pfTokArm
|
|
10520
|
+
_pfTokDispatch=-1
|
|
10521
|
+
_pfTokInput=undefined
|
|
10522
|
+
if(arm===${n})arm=undefined
|
|
10523
|
+
}else{
|
|
10524
|
+
arm=${bk}.get(key)
|
|
10525
|
+
${fold}${chain}}` : `let arm=${bk}.get(key)
|
|
10526
|
+
${fold}${chain}`;
|
|
9412
10527
|
return `${head}
|
|
9413
|
-
${emitMark(m1, L.buf, sinks)}
|
|
10528
|
+
${emitMark(m1, L.buf, L.raw, sinks)}
|
|
9414
10529
|
const sv=${selector}(input,pos,ctx)
|
|
9415
10530
|
if(sv===FAIL)return FAIL
|
|
9416
10531
|
const selEnd=EC.e
|
|
9417
10532
|
const key=sv
|
|
9418
|
-
|
|
9419
|
-
${fold}${chain}
|
|
10533
|
+
${armSelection}
|
|
9420
10534
|
if(arm===undefined){
|
|
9421
10535
|
${other === void 0 ? `ctx._fe=selEnd;ctx._fx=${dx};return FAIL` : ""}
|
|
9422
10536
|
}
|
|
9423
|
-
${emitMark(m2, L.buf, sinks)}
|
|
10537
|
+
${emitMark(m2, L.buf, L.raw, sinks)}
|
|
9424
10538
|
let v
|
|
9425
10539
|
switch(arm){
|
|
9426
10540
|
${armCases}
|
|
9427
10541
|
${fallbackCase}
|
|
9428
10542
|
}
|
|
9429
10543
|
if(v===FAIL){
|
|
9430
|
-
${emitRollback(m2, L.buf, sinks)}
|
|
10544
|
+
${emitRollback(m2, L.buf, L.raw, sinks)}
|
|
9431
10545
|
ctx._fc=true
|
|
9432
10546
|
return FAIL
|
|
9433
10547
|
}
|
|
@@ -9463,23 +10577,25 @@ return [key,v]
|
|
|
9463
10577
|
const skip = skipFor(L);
|
|
9464
10578
|
const knownTrivia = L.tri === TRI_NONE ? false : L.tri !== TRI_UNKNOWN ? true : void 0;
|
|
9465
10579
|
const hasTrivia = knownTrivia === void 0 ? "hasTrivia" : String(knownTrivia);
|
|
9466
|
-
const pfd = sinks.fd ? `${p}fd` : "
|
|
10580
|
+
const pfd = sinks.fd ? `${p}fd` : "undefined";
|
|
9467
10581
|
const per = sinks.er ? `${p}er` : "undefined";
|
|
9468
|
-
const
|
|
10582
|
+
const rbHelper = L.raw === RAW_OMIT ? "_rbNoRawBuf" : "_rbBuf";
|
|
10583
|
+
const rb = L.buf && L.raw !== 0 ? `${rbHelper}(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
|
|
9469
10584
|
if(ctx._fields!==undefined&&ctx._fields.length!==${p}fd)ctx._fields.length=${p}fd` : ""}${sinks.er ? `
|
|
9470
|
-
if(ctx._errors!==undefined&&ctx._errors.length!==${p}er)ctx._errors.length=${p}er` : ""}` : `if(needMark)rollbackTriviaAt(ctx,${p}raw,${p}tl,${p}lv,${pfd},${per},${p}lg,${p}rt)`;
|
|
10585
|
+
if(ctx._errors!==undefined&&ctx._errors.length!==${p}er)ctx._errors.length=${p}er` : ""}` : L.buf ? `rollbackTriviaAt(ctx,${p}raw,${p}tl,${p}lv,${pfd},${per},${p}lg,${p}rt)` : `if(needMark)rollbackTriviaAt(ctx,${p}raw,${p}tl,${p}lv,${pfd},${per},${p}lg,${p}rt)`;
|
|
9471
10586
|
const markSinks = `${sinks.fd ? `
|
|
9472
10587
|
${p}fd=ctx._fields!==undefined?ctx._fields.length:0` : ""}${sinks.er ? `
|
|
9473
10588
|
${p}er=ctx._errors!==undefined?ctx._errors.length:0` : ""}`;
|
|
10589
|
+
const markRaw = L.raw === RAW_OMIT ? `${p}raw=b.rawLen` : L.raw === RAW_CAPTURE ? `const r=b.raw;${p}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0` : `const r=b.raw;${p}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)`;
|
|
9474
10590
|
const markBody = L.buf ? `const b=ctx._cstBuf
|
|
9475
|
-
|
|
10591
|
+
${markRaw}
|
|
9476
10592
|
const h=b.ch;${p}lv=h!==undefined?h.length:b.single!==undefined?1:0
|
|
9477
10593
|
const l=b.tl;${p}tl=l!==undefined?l.length:0
|
|
9478
10594
|
${p}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
9479
10595
|
${p}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${markSinks}` : `if(needMark){
|
|
9480
10596
|
const b=ctx._cstBuf
|
|
9481
10597
|
if(b!==undefined){
|
|
9482
|
-
const r=b.raw;${p}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
|
|
10598
|
+
const r=b.raw;${p}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)
|
|
9483
10599
|
const h=b.ch;${p}lv=h!==undefined?h.length:b.single!==undefined?1:0
|
|
9484
10600
|
const l=b.tl;${p}tl=l!==undefined?l.length:0
|
|
9485
10601
|
}else{
|
|
@@ -9586,7 +10702,7 @@ const leaf={_tag:'leaf',value,span:{start:pos,end}}
|
|
|
9586
10702
|
const kids=[leaf],rawKids=[leaf],span={start:pos,end}
|
|
9587
10703
|
EC.e=end
|
|
9588
10704
|
const nd=${build2}(kids,undefined,span,rawKids,EMPTY_TL,undefined)
|
|
9589
|
-
${L.buf ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : "if(ctx._cstBuf!==undefined||ctx._cstChildren!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
|
|
10705
|
+
${L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : staticBuild ? "if(ctx._cstBuf!==undefined||ctx._cstChildren!==undefined)pushCstChild(ctx,nd,ctx._cstBuf!==undefined&&ctx._cstBuf.noRaw===true?undefined:ctx._cstBuf!==undefined||ctx._cstRawChildren!==undefined?rawEntry(nd,input,pos,end):undefined)" : "if(ctx._cstBuf!==undefined||ctx._cstChildren!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
|
|
9590
10706
|
EC.e=end
|
|
9591
10707
|
return nd
|
|
9592
10708
|
}`;
|
|
@@ -9608,7 +10724,22 @@ return nd
|
|
|
9608
10724
|
if (!hostCst && !tracked && build !== void 0 && proj < 0 && (flags === 2 || flags === 18 || flags === 34)) {
|
|
9609
10725
|
const fields = flags === 18;
|
|
9610
10726
|
const collapseChildren = flags === 34;
|
|
9611
|
-
const publish = `if(sBuf!==undefined){
|
|
10727
|
+
const publish = L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? `if(sBuf!==undefined){
|
|
10728
|
+
if(sBuf.rawOnly!==true){
|
|
10729
|
+
if(sBuf.ch!==undefined)sBuf.ch.push(nd)
|
|
10730
|
+
else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
|
|
10731
|
+
else sBuf.single=nd
|
|
10732
|
+
}
|
|
10733
|
+
const rawNd=rawEntry(nd,input,pos,end)
|
|
10734
|
+
if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
|
|
10735
|
+
else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
|
|
10736
|
+
else sBuf.rawSingle=rawNd
|
|
10737
|
+
}else if(sCh!==undefined){
|
|
10738
|
+
sCh.push(nd)
|
|
10739
|
+
if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
|
|
10740
|
+
}` : `if(sBuf!==undefined){
|
|
10741
|
+
if(sBuf.noRaw===true)_pushNodeNoRawBuf(ctx,nd)
|
|
10742
|
+
else{
|
|
9612
10743
|
if(sBuf.rawOnly!==true){
|
|
9613
10744
|
if(sBuf.ch!==undefined)sBuf.ch.push(nd)
|
|
9614
10745
|
else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
|
|
@@ -9618,6 +10749,7 @@ const rawNd=rawEntry(nd,input,pos,end)
|
|
|
9618
10749
|
if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
|
|
9619
10750
|
else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
|
|
9620
10751
|
else sBuf.rawSingle=rawNd
|
|
10752
|
+
}
|
|
9621
10753
|
}else if(sCh!==undefined){
|
|
9622
10754
|
sCh.push(nd)
|
|
9623
10755
|
if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
|
|
@@ -9656,6 +10788,7 @@ return nd
|
|
|
9656
10788
|
const wantFields = hasFields || hostCst;
|
|
9657
10789
|
const captureWide = readsTrivia || hostCst ? !structural || grammarCapture || hostCapturesThisType !== false : hostCapturesThisType === true;
|
|
9658
10790
|
const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
|
|
10791
|
+
const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
|
|
9659
10792
|
const ty = q(type);
|
|
9660
10793
|
const stArg = readsState ? "st" : "(ctx.state!==undefined?Object.assign({},ctx.state):undefined)";
|
|
9661
10794
|
const hostCall = `_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,${stArg},${tags})`;
|
|
@@ -9669,7 +10802,12 @@ return nd
|
|
|
9669
10802
|
value = `nd=_pfHost!==undefined?_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,st,${tags}):{_tag:'node',type:${ty},span,state:st??null,children:kids}`;
|
|
9670
10803
|
}
|
|
9671
10804
|
const collapsible = keepChildren && (hostCst || build === void 0 && proj < 0);
|
|
9672
|
-
const openCapture =
|
|
10805
|
+
const openCapture = omitsRaw ? `const buf={noRaw:true,rawLen:0}
|
|
10806
|
+
ctx._cstBuf=buf
|
|
10807
|
+
ctx._cstChildren=undefined
|
|
10808
|
+
ctx._cstLeaves=undefined
|
|
10809
|
+
ctx._cstRawChildren=undefined
|
|
10810
|
+
ctx._cstTriviaLog=undefined` : keepChildren ? `const buf={}
|
|
9673
10811
|
ctx._cstBuf=buf
|
|
9674
10812
|
ctx._cstChildren=undefined
|
|
9675
10813
|
ctx._cstLeaves=undefined
|
|
@@ -9680,7 +10818,10 @@ ctx._cstChildren=undefined
|
|
|
9680
10818
|
ctx._cstLeaves=undefined
|
|
9681
10819
|
ctx._cstRawChildren=undefined
|
|
9682
10820
|
ctx._cstTriviaLog=undefined`;
|
|
9683
|
-
const finishCapture =
|
|
10821
|
+
const finishCapture = omitsRaw ? `const kids=buf.ch??(buf.single!==undefined?[buf.single]:EMPTY_CH)
|
|
10822
|
+
const hostKids=kids
|
|
10823
|
+
const rawKids=EMPTY_CH
|
|
10824
|
+
const tlog=buf.tl??EMPTY_TLOG` : keepChildren ? `const kids=buf.ch??(buf.single!==undefined?[buf.single]:EMPTY_CH)
|
|
9684
10825
|
const hostKids=kids
|
|
9685
10826
|
const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
|
|
9686
10827
|
const tlog=buf.tl??EMPTY_TLOG` : `const kids=EMPTY_CH
|
|
@@ -9714,7 +10855,7 @@ const st=${readsState ? "(ctx.state!==undefined?Object.assign({},ctx.state):unde
|
|
|
9714
10855
|
let nd
|
|
9715
10856
|
${unwrap ? "if(kids.length===1)nd=unwrapChild(kids[0])\nelse " : ""}${collapse ? "if(kids.length===1)nd=kids[0]\nelse " : ""}${collapsible ? `if(_pfHost!==undefined&&_pfHost._parsemanCstCollapse!==undefined&&kids.length===1&&rawKids.length===1&&_pfHost._parsemanCstCollapse(${ty},kids[0],kids,rawKids))nd=kids[0]
|
|
9716
10857
|
else ` : ""}{${value}}
|
|
9717
|
-
${L.buf ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : "if(sBuf!==undefined||sCh!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
|
|
10858
|
+
${L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : staticBuild ? "if(sBuf!==undefined||sCh!==undefined)pushCstChild(ctx,nd,sBuf!==undefined?(sBuf.noRaw===true?undefined:rawEntry(nd,input,pos,end)):sRaw!==undefined?rawEntry(nd,input,pos,end):undefined)" : "if(sBuf!==undefined||sCh!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
|
|
9718
10859
|
EC.e=end
|
|
9719
10860
|
return nd
|
|
9720
10861
|
}`;
|
|
@@ -9732,7 +10873,7 @@ return nd
|
|
|
9732
10873
|
}
|
|
9733
10874
|
const extra = [];
|
|
9734
10875
|
for (const ip of extraIps) extra.push(`${ip}:${link(ip)}`);
|
|
9735
|
-
const source = `${RUNTIME_PRELUDE}
|
|
10876
|
+
const source = `${RUNTIME_PRELUDE}${needsNoRawPrelude ? NO_RAW_RUNTIME_PRELUDE : ""}
|
|
9736
10877
|
${prelude.join("\n")}
|
|
9737
10878
|
${skipDefs.join("\n")}
|
|
9738
10879
|
${choiceDefs.join("\n")}
|
|
@@ -9747,7 +10888,13 @@ _pfHost=host
|
|
|
9747
10888
|
function _finish(){
|
|
9748
10889
|
if(_pfDepth<=0)throw new Error('parseman emitted table assembly frame underflow')
|
|
9749
10890
|
_pfDepth--
|
|
9750
|
-
if(_pfDepth===0)
|
|
10891
|
+
if(_pfDepth===0){
|
|
10892
|
+
_pfTokInput=undefined
|
|
10893
|
+
_pfTokBody=-1
|
|
10894
|
+
_pfTokValue=undefined
|
|
10895
|
+
_pfTokDispatch=-1
|
|
10896
|
+
return
|
|
10897
|
+
}
|
|
9751
10898
|
const prior=_pfFrames.pop()
|
|
9752
10899
|
_pfScan=prior[0]
|
|
9753
10900
|
_pfHost=prior[1]
|
|
@@ -10109,6 +11256,17 @@ function assemble(t, prog, cfg) {
|
|
|
10109
11256
|
}
|
|
10110
11257
|
return recognize;
|
|
10111
11258
|
}
|
|
11259
|
+
const labelExtraIps = [];
|
|
11260
|
+
for (const s of prog.scans ?? []) {
|
|
11261
|
+
for (const r of s.skip) labelExtraIps.push(r[0]);
|
|
11262
|
+
if (s.sentinel !== void 0) labelExtraIps.push(s.sentinel[0]);
|
|
11263
|
+
}
|
|
11264
|
+
for (const set of prog.scanSkip ?? []) for (const r of set) labelExtraIps.push(r[0]);
|
|
11265
|
+
const closureLabels = computeSiteLabels(
|
|
11266
|
+
code,
|
|
11267
|
+
[...Object.values(prog.rules), ...labelExtraIps],
|
|
11268
|
+
hostCst
|
|
11269
|
+
);
|
|
10112
11270
|
let SCAN = null;
|
|
10113
11271
|
const memo = /* @__PURE__ */ new Map();
|
|
10114
11272
|
const reached = /* @__PURE__ */ new Set();
|
|
@@ -10154,12 +11312,12 @@ function assemble(t, prog, cfg) {
|
|
|
10154
11312
|
return node2;
|
|
10155
11313
|
};
|
|
10156
11314
|
}
|
|
10157
|
-
function capturedFlatChildren(
|
|
10158
|
-
if (
|
|
10159
|
-
if (
|
|
11315
|
+
function capturedFlatChildren(children3) {
|
|
11316
|
+
if (children3.length === 0) return EMPTY_CH;
|
|
11317
|
+
if (children3[0] !== void 0) return children3;
|
|
10160
11318
|
let first = 1;
|
|
10161
|
-
while (first <
|
|
10162
|
-
return first ===
|
|
11319
|
+
while (first < children3.length && children3[first] === void 0) first++;
|
|
11320
|
+
return first === children3.length ? EMPTY_CH : children3.slice(first);
|
|
10163
11321
|
}
|
|
10164
11322
|
function childrenOnlyBuildNode(child, build) {
|
|
10165
11323
|
return (input, pos, ctx) => {
|
|
@@ -10354,7 +11512,7 @@ function assemble(t, prog, cfg) {
|
|
|
10354
11512
|
const b = ctx._cstBuf;
|
|
10355
11513
|
if (b !== void 0) {
|
|
10356
11514
|
const raw = b.raw;
|
|
10357
|
-
MRAW = raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
|
|
11515
|
+
MRAW = b.noRaw === true ? b.rawLen ?? 0 : raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
|
|
10358
11516
|
const ch2 = b.ch;
|
|
10359
11517
|
MLV = ch2 !== void 0 ? ch2.length : b.single !== void 0 ? 1 : 0;
|
|
10360
11518
|
const tl = b.tl;
|
|
@@ -10438,6 +11596,31 @@ function assemble(t, prog, cfg) {
|
|
|
10438
11596
|
if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
|
|
10439
11597
|
return cur;
|
|
10440
11598
|
}
|
|
11599
|
+
function nextTermBuffered(child, input, cur, ctx) {
|
|
11600
|
+
if (ctx.trivia === void 0) {
|
|
11601
|
+
const v2 = child(input, cur, ctx);
|
|
11602
|
+
if (v2 === FAIL) return -1;
|
|
11603
|
+
TERMV = v2;
|
|
11604
|
+
return EC.e;
|
|
11605
|
+
}
|
|
11606
|
+
const before = ctx._cstBuf;
|
|
11607
|
+
const beforeTl = before.tl;
|
|
11608
|
+
const mTl = beforeTl === void 0 ? 0 : beforeTl.length;
|
|
11609
|
+
const mLog = ctx._triviaLog?.length ?? 0;
|
|
11610
|
+
const mRoot = ctx._rootTriviaLog?.length ?? 0;
|
|
11611
|
+
const scanEnd = skipTrivia(input, cur, ctx);
|
|
11612
|
+
const scanned = ctx._cstBuf;
|
|
11613
|
+
const scannedTl = scanned.tl;
|
|
11614
|
+
const scanTl = scannedTl === void 0 ? 0 : scannedTl.length;
|
|
11615
|
+
const scanLog = ctx._triviaLog?.length ?? 0;
|
|
11616
|
+
const scanRoot = ctx._rootTriviaLog?.length ?? 0;
|
|
11617
|
+
const v = child(input, scanEnd, ctx);
|
|
11618
|
+
if (v === FAIL) return -1;
|
|
11619
|
+
TERMV = v;
|
|
11620
|
+
if (EC.e > scanEnd) return EC.e;
|
|
11621
|
+
rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
|
|
11622
|
+
return cur;
|
|
11623
|
+
}
|
|
10441
11624
|
function committed3(c) {
|
|
10442
11625
|
return c._fc === true;
|
|
10443
11626
|
}
|
|
@@ -10708,7 +11891,8 @@ function assemble(t, prog, cfg) {
|
|
|
10708
11891
|
target = p;
|
|
10709
11892
|
} };
|
|
10710
11893
|
inFlight.set(ip, holder);
|
|
10711
|
-
const
|
|
11894
|
+
const op = code[ip];
|
|
11895
|
+
const piece = (op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[ip + 3] === 0) && code[ip + 1] >= 0 && closureLabels.at(ip).tri === code[ip + 1] ? link(code[ip + 2]) : lower(ip);
|
|
10712
11896
|
inFlight.delete(ip);
|
|
10713
11897
|
holder.set(piece);
|
|
10714
11898
|
memo.set(ip, piece);
|
|
@@ -11160,11 +12344,11 @@ function assemble(t, prog, cfg) {
|
|
|
11160
12344
|
}
|
|
11161
12345
|
case OP_ROUTED: {
|
|
11162
12346
|
const fb = code[ip + 1];
|
|
11163
|
-
const
|
|
12347
|
+
const fallback2 = fb >= 0 ? link(fb) : void 0;
|
|
11164
12348
|
return (input, pos, ctx) => {
|
|
11165
12349
|
const item = ctx._routed;
|
|
11166
12350
|
if (item === void 0 || pos !== item.span.start) {
|
|
11167
|
-
if (
|
|
12351
|
+
if (fallback2 !== void 0) return fallback2(input, pos, ctx);
|
|
11168
12352
|
ctx._fe = pos;
|
|
11169
12353
|
ctx._fx = ROUTED_FX;
|
|
11170
12354
|
return FAIL;
|
|
@@ -11451,6 +12635,7 @@ function assemble(t, prog, cfg) {
|
|
|
11451
12635
|
const reducer = fused ? code[ip + 1] : -1;
|
|
11452
12636
|
const projection = reducer < 0 ? ~reducer : -1;
|
|
11453
12637
|
const fn = fused && projection < 0 ? fns[reducer] : void 0;
|
|
12638
|
+
const step = closureLabels.at(ip).buf ? nextTermBuffered : nextTerm;
|
|
11454
12639
|
const runnerBlock = (count, r0, r1, r2, r3, next) => {
|
|
11455
12640
|
if (count === 1) return (input, cur, ctx, values, inherited) => {
|
|
11456
12641
|
cur = r0(input, cur, ctx, inherited);
|
|
@@ -11505,7 +12690,7 @@ function assemble(t, prog, cfg) {
|
|
|
11505
12690
|
const kid = link(kidIp);
|
|
11506
12691
|
return (input, cur, ctx, inherited) => {
|
|
11507
12692
|
ctx._sync = sync ?? inherited;
|
|
11508
|
-
return
|
|
12693
|
+
return step(kid, input, cur, ctx);
|
|
11509
12694
|
};
|
|
11510
12695
|
}
|
|
11511
12696
|
const negated = code[kidIp + 1] === 1;
|
|
@@ -11590,7 +12775,7 @@ function assemble(t, prog, cfg) {
|
|
|
11590
12775
|
const kidIp = code[base + i];
|
|
11591
12776
|
if (code[kidIp] !== OP_ADJ) {
|
|
11592
12777
|
const kid = link(kidIp);
|
|
11593
|
-
return (input, cur, ctx) =>
|
|
12778
|
+
return (input, cur, ctx) => step(kid, input, cur, ctx);
|
|
11594
12779
|
}
|
|
11595
12780
|
const negated = code[kidIp + 1] === 1;
|
|
11596
12781
|
const ki = code[kidIp + 2];
|
|
@@ -11679,7 +12864,7 @@ function assemble(t, prog, cfg) {
|
|
|
11679
12864
|
return (input, pos, ctx) => {
|
|
11680
12865
|
const v0 = k0(input, pos, ctx);
|
|
11681
12866
|
if (v0 === FAIL) return FAIL;
|
|
11682
|
-
const cur =
|
|
12867
|
+
const cur = step(k1, input, EC.e, ctx);
|
|
11683
12868
|
if (cur < 0) return FAIL;
|
|
11684
12869
|
EC.e = cur;
|
|
11685
12870
|
return projection === 0 ? v0 : projection === 1 ? TERMV : fn([v0, TERMV], { start: pos, end: cur });
|
|
@@ -11689,7 +12874,7 @@ function assemble(t, prog, cfg) {
|
|
|
11689
12874
|
return (input, pos, ctx) => {
|
|
11690
12875
|
const v0 = k0(input, pos, ctx);
|
|
11691
12876
|
if (v0 === FAIL) return FAIL;
|
|
11692
|
-
const cur =
|
|
12877
|
+
const cur = step(k1, input, EC.e, ctx);
|
|
11693
12878
|
if (cur < 0) return FAIL;
|
|
11694
12879
|
EC.e = cur;
|
|
11695
12880
|
return [v0, TERMV];
|
|
@@ -11698,7 +12883,7 @@ function assemble(t, prog, cfg) {
|
|
|
11698
12883
|
return (input, pos, ctx) => {
|
|
11699
12884
|
const v0 = k0(input, pos, ctx);
|
|
11700
12885
|
if (v0 === FAIL) return FAIL;
|
|
11701
|
-
const cur =
|
|
12886
|
+
const cur = step(k1, input, EC.e, ctx);
|
|
11702
12887
|
if (cur < 0) return FAIL;
|
|
11703
12888
|
EC.e = cur;
|
|
11704
12889
|
return void 0;
|
|
@@ -11710,10 +12895,10 @@ function assemble(t, prog, cfg) {
|
|
|
11710
12895
|
return (input, pos, ctx) => {
|
|
11711
12896
|
const v0 = k0(input, pos, ctx);
|
|
11712
12897
|
if (v0 === FAIL) return FAIL;
|
|
11713
|
-
let cur =
|
|
12898
|
+
let cur = step(k1, input, EC.e, ctx);
|
|
11714
12899
|
if (cur < 0) return FAIL;
|
|
11715
12900
|
const v1 = TERMV;
|
|
11716
|
-
cur =
|
|
12901
|
+
cur = step(k2, input, cur, ctx);
|
|
11717
12902
|
if (cur < 0) return FAIL;
|
|
11718
12903
|
EC.e = cur;
|
|
11719
12904
|
return projection === 0 ? v0 : projection === 1 ? v1 : projection === 2 ? TERMV : fn([v0, v1, TERMV], { start: pos, end: cur });
|
|
@@ -11723,10 +12908,10 @@ function assemble(t, prog, cfg) {
|
|
|
11723
12908
|
return (input, pos, ctx) => {
|
|
11724
12909
|
const v0 = k0(input, pos, ctx);
|
|
11725
12910
|
if (v0 === FAIL) return FAIL;
|
|
11726
|
-
let cur =
|
|
12911
|
+
let cur = step(k1, input, EC.e, ctx);
|
|
11727
12912
|
if (cur < 0) return FAIL;
|
|
11728
12913
|
const v1 = TERMV;
|
|
11729
|
-
cur =
|
|
12914
|
+
cur = step(k2, input, cur, ctx);
|
|
11730
12915
|
if (cur < 0) return FAIL;
|
|
11731
12916
|
EC.e = cur;
|
|
11732
12917
|
return [v0, v1, TERMV];
|
|
@@ -11735,9 +12920,9 @@ function assemble(t, prog, cfg) {
|
|
|
11735
12920
|
return (input, pos, ctx) => {
|
|
11736
12921
|
const v0 = k0(input, pos, ctx);
|
|
11737
12922
|
if (v0 === FAIL) return FAIL;
|
|
11738
|
-
let cur =
|
|
12923
|
+
let cur = step(k1, input, EC.e, ctx);
|
|
11739
12924
|
if (cur < 0) return FAIL;
|
|
11740
|
-
cur =
|
|
12925
|
+
cur = step(k2, input, cur, ctx);
|
|
11741
12926
|
if (cur < 0) return FAIL;
|
|
11742
12927
|
EC.e = cur;
|
|
11743
12928
|
return void 0;
|
|
@@ -11745,43 +12930,43 @@ function assemble(t, prog, cfg) {
|
|
|
11745
12930
|
}
|
|
11746
12931
|
const block = (count, k0, k1, k2, k3, next) => {
|
|
11747
12932
|
if (count === 1) return (input, cur, ctx, values) => {
|
|
11748
|
-
cur =
|
|
12933
|
+
cur = step(k0, input, cur, ctx);
|
|
11749
12934
|
if (cur < 0) return -1;
|
|
11750
12935
|
if (values !== void 0) values.push(TERMV);
|
|
11751
12936
|
return next === void 0 ? cur : next(input, cur, ctx, values);
|
|
11752
12937
|
};
|
|
11753
12938
|
if (count === 2) return (input, cur, ctx, values) => {
|
|
11754
|
-
cur =
|
|
12939
|
+
cur = step(k0, input, cur, ctx);
|
|
11755
12940
|
if (cur < 0) return -1;
|
|
11756
12941
|
if (values !== void 0) values.push(TERMV);
|
|
11757
|
-
cur =
|
|
12942
|
+
cur = step(k1, input, cur, ctx);
|
|
11758
12943
|
if (cur < 0) return -1;
|
|
11759
12944
|
if (values !== void 0) values.push(TERMV);
|
|
11760
12945
|
return next === void 0 ? cur : next(input, cur, ctx, values);
|
|
11761
12946
|
};
|
|
11762
12947
|
if (count === 3) return (input, cur, ctx, values) => {
|
|
11763
|
-
cur =
|
|
12948
|
+
cur = step(k0, input, cur, ctx);
|
|
11764
12949
|
if (cur < 0) return -1;
|
|
11765
12950
|
if (values !== void 0) values.push(TERMV);
|
|
11766
|
-
cur =
|
|
12951
|
+
cur = step(k1, input, cur, ctx);
|
|
11767
12952
|
if (cur < 0) return -1;
|
|
11768
12953
|
if (values !== void 0) values.push(TERMV);
|
|
11769
|
-
cur =
|
|
12954
|
+
cur = step(k2, input, cur, ctx);
|
|
11770
12955
|
if (cur < 0) return -1;
|
|
11771
12956
|
if (values !== void 0) values.push(TERMV);
|
|
11772
12957
|
return next === void 0 ? cur : next(input, cur, ctx, values);
|
|
11773
12958
|
};
|
|
11774
12959
|
return (input, cur, ctx, values) => {
|
|
11775
|
-
cur =
|
|
12960
|
+
cur = step(k0, input, cur, ctx);
|
|
11776
12961
|
if (cur < 0) return -1;
|
|
11777
12962
|
if (values !== void 0) values.push(TERMV);
|
|
11778
|
-
cur =
|
|
12963
|
+
cur = step(k1, input, cur, ctx);
|
|
11779
12964
|
if (cur < 0) return -1;
|
|
11780
12965
|
if (values !== void 0) values.push(TERMV);
|
|
11781
|
-
cur =
|
|
12966
|
+
cur = step(k2, input, cur, ctx);
|
|
11782
12967
|
if (cur < 0) return -1;
|
|
11783
12968
|
if (values !== void 0) values.push(TERMV);
|
|
11784
|
-
cur =
|
|
12969
|
+
cur = step(k3, input, cur, ctx);
|
|
11785
12970
|
if (cur < 0) return -1;
|
|
11786
12971
|
if (values !== void 0) values.push(TERMV);
|
|
11787
12972
|
return next === void 0 ? cur : next(input, cur, ctx, values);
|
|
@@ -11952,6 +13137,13 @@ function assemble(t, prog, cfg) {
|
|
|
11952
13137
|
if (n === 2 || n === 3) {
|
|
11953
13138
|
const a0 = link(code[base]), a1 = link(code[base + 1]);
|
|
11954
13139
|
const a2 = n === 3 ? link(code[base + 2]) : void 0;
|
|
13140
|
+
const predecide = !hostCst && !REC2 && !cfg.probe && !cfg.coverage && !cfg.trackLines;
|
|
13141
|
+
const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
|
|
13142
|
+
const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
|
|
13143
|
+
const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
|
|
13144
|
+
const p0 = p0ip < 0 ? void 0 : scalarFor(p0ip);
|
|
13145
|
+
const p1 = p1ip < 0 ? void 0 : scalarFor(p1ip);
|
|
13146
|
+
const p2 = p2ip < 0 ? void 0 : scalarFor(p2ip);
|
|
11955
13147
|
const e0 = fx[code[base + n]];
|
|
11956
13148
|
const e1 = fx[code[base + n + 1]];
|
|
11957
13149
|
const e2 = n === 3 ? fx[code[base + n + 2]] : void 0;
|
|
@@ -11981,7 +13173,10 @@ function assemble(t, prog, cfg) {
|
|
|
11981
13173
|
let acc;
|
|
11982
13174
|
let best = pos;
|
|
11983
13175
|
if (c < 128) {
|
|
11984
|
-
|
|
13176
|
+
let bits = mask[c < 0 ? 128 : c];
|
|
13177
|
+
if ((bits & 1) !== 0 && p0 !== void 0 && p0(input, pos) < 0) bits &= ~1;
|
|
13178
|
+
if ((bits & 2) !== 0 && p1 !== void 0 && p1(input, pos) < 0) bits &= ~2;
|
|
13179
|
+
if ((bits & 4) !== 0 && p2 !== void 0 && p2(input, pos) < 0) bits &= ~4;
|
|
11985
13180
|
let prev = 0;
|
|
11986
13181
|
if ((bits & 1) !== 0) {
|
|
11987
13182
|
ctx._fc = false;
|
|
@@ -12044,7 +13239,7 @@ function assemble(t, prog, cfg) {
|
|
|
12044
13239
|
ctx._fx = acc ?? choiceFx;
|
|
12045
13240
|
return FAIL;
|
|
12046
13241
|
}
|
|
12047
|
-
if (g0 === null || classHas2(g0, c)) {
|
|
13242
|
+
if ((g0 === null || classHas2(g0, c)) && (p0 === void 0 || p0(input, pos) >= 0)) {
|
|
12048
13243
|
ctx._fc = false;
|
|
12049
13244
|
const v = a0(input, pos, ctx);
|
|
12050
13245
|
if (v !== FAIL) return v;
|
|
@@ -12060,7 +13255,7 @@ function assemble(t, prog, cfg) {
|
|
|
12060
13255
|
}
|
|
12061
13256
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
12062
13257
|
} else if (best === pos) acc = accSet(e0, acc);
|
|
12063
|
-
if (g1 === null || classHas2(g1, c)) {
|
|
13258
|
+
if ((g1 === null || classHas2(g1, c)) && (p1 === void 0 || p1(input, pos) >= 0)) {
|
|
12064
13259
|
ctx._fc = false;
|
|
12065
13260
|
const v = a1(input, pos, ctx);
|
|
12066
13261
|
if (v !== FAIL) return v;
|
|
@@ -12077,7 +13272,7 @@ function assemble(t, prog, cfg) {
|
|
|
12077
13272
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
12078
13273
|
} else if (best === pos) acc = accSet(e1, acc);
|
|
12079
13274
|
if (n === 3) {
|
|
12080
|
-
if (g2 === null || classHas2(g2, c)) {
|
|
13275
|
+
if ((g2 === null || classHas2(g2, c)) && (p2 === void 0 || p2(input, pos) >= 0)) {
|
|
12081
13276
|
ctx._fc = false;
|
|
12082
13277
|
const v = a2(input, pos, ctx);
|
|
12083
13278
|
if (v !== FAIL) return v;
|
|
@@ -12650,20 +13845,14 @@ function assemble(t, prog, cfg) {
|
|
|
12650
13845
|
const captureWide = readsTrivia || hostCst ? !structural || grammarCapture || hostCapturesThisType !== false : hostCapturesThisType === true;
|
|
12651
13846
|
const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
|
|
12652
13847
|
const rawOnly = !keepChildren;
|
|
13848
|
+
const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
|
|
12653
13849
|
return (input, pos, ctx) => {
|
|
12654
13850
|
const host = HOST;
|
|
12655
13851
|
const sCh = ctx._cstChildren;
|
|
12656
|
-
const sLv = ctx._cstLeaves;
|
|
12657
|
-
const sRaw = ctx._cstRawChildren;
|
|
12658
|
-
const sTl = ctx._cstTriviaLog;
|
|
12659
13852
|
const sCap = ctx.captureTrivia;
|
|
12660
13853
|
const sBuf = ctx._cstBuf;
|
|
12661
|
-
const buf = rawOnly ? { rawOnly: true } : {};
|
|
13854
|
+
const buf = rawOnly ? { rawOnly: true } : omitsRaw ? { noRaw: true, rawLen: 0 } : {};
|
|
12662
13855
|
ctx._cstBuf = buf;
|
|
12663
|
-
ctx._cstChildren = void 0;
|
|
12664
|
-
ctx._cstLeaves = void 0;
|
|
12665
|
-
ctx._cstRawChildren = void 0;
|
|
12666
|
-
ctx._cstTriviaLog = void 0;
|
|
12667
13856
|
ctx.captureTrivia = captureWide;
|
|
12668
13857
|
const savedFields = ctx._fields;
|
|
12669
13858
|
ctx._fields = wantFields ? [] : void 0;
|
|
@@ -12678,13 +13867,9 @@ function assemble(t, prog, cfg) {
|
|
|
12678
13867
|
if (structural) ctx._triviaCaptureMask = savedMask;
|
|
12679
13868
|
const kids = rawOnly ? EMPTY_CH : buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
|
|
12680
13869
|
const hostKids = kids;
|
|
12681
|
-
const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
|
|
13870
|
+
const rawKids = omitsRaw ? EMPTY_CH : buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
|
|
12682
13871
|
const tlog = buf.tl ?? EMPTY_TLOG;
|
|
12683
13872
|
ctx._cstBuf = sBuf;
|
|
12684
|
-
ctx._cstChildren = sCh;
|
|
12685
|
-
ctx._cstLeaves = sLv;
|
|
12686
|
-
ctx._cstRawChildren = sRaw;
|
|
12687
|
-
ctx._cstTriviaLog = sTl;
|
|
12688
13873
|
ctx.captureTrivia = sCap;
|
|
12689
13874
|
if (v === FAIL) return FAIL;
|
|
12690
13875
|
const end = EC.e;
|
|
@@ -12775,6 +13960,34 @@ function assemble(t, prog, cfg) {
|
|
|
12775
13960
|
rawScalarSpecs.add(code[child + 1]);
|
|
12776
13961
|
scalarFor(child);
|
|
12777
13962
|
}
|
|
13963
|
+
} else if (code[ip] === OP_CHOICE && !disp[code[ip + 1]].exclusive) {
|
|
13964
|
+
const n = code[ip + 2];
|
|
13965
|
+
for (let i = 0; i < n; i++) {
|
|
13966
|
+
const armIp = code[ip + 4 + i];
|
|
13967
|
+
const child = leadingScalarTerminal(code, armIp, 2, true, true);
|
|
13968
|
+
if (n === 2 || n === 3) {
|
|
13969
|
+
if (child >= 0) scalarFor(child);
|
|
13970
|
+
continue;
|
|
13971
|
+
}
|
|
13972
|
+
if (child >= 0) {
|
|
13973
|
+
const spec = k[code[child + 1]];
|
|
13974
|
+
if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
|
|
13975
|
+
scalarFor(child);
|
|
13976
|
+
continue;
|
|
13977
|
+
}
|
|
13978
|
+
}
|
|
13979
|
+
const family = leadingLiteralFamily(code, k, armIp);
|
|
13980
|
+
if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
|
|
13981
|
+
const value = k[code[terminal + 1]];
|
|
13982
|
+
return typeof value === "string" && value.length >= 2;
|
|
13983
|
+
})) {
|
|
13984
|
+
for (const terminal of family) scalarFor(terminal);
|
|
13985
|
+
}
|
|
13986
|
+
const sequence6 = leadingScalarSequence(code, armIp);
|
|
13987
|
+
if (sequence6 !== void 0 && (sequence6.trivia < 0 || triviaScan[sequence6.trivia] != null)) {
|
|
13988
|
+
for (const terminal of sequence6.terminals) scalarFor(terminal);
|
|
13989
|
+
}
|
|
13990
|
+
}
|
|
12778
13991
|
}
|
|
12779
13992
|
}
|
|
12780
13993
|
const notChild = scalarTerminalNotChild(code, ip);
|
|
@@ -13196,7 +14409,7 @@ function emitAssemblies(prog, cfgs) {
|
|
|
13196
14409
|
seen.add(key);
|
|
13197
14410
|
let em;
|
|
13198
14411
|
try {
|
|
13199
|
-
em = emitAssemblySource(t, prog, cfg, extraIps);
|
|
14412
|
+
em = emitAssemblySource(t, prog, cfg, extraIps, true);
|
|
13200
14413
|
} catch (e) {
|
|
13201
14414
|
if (e instanceof Unemittable) continue;
|
|
13202
14415
|
throw e;
|
|
@@ -13655,10 +14868,10 @@ function boundaryMatches(boundary, ch2) {
|
|
|
13655
14868
|
if (/\s/.test(ch2)) return true;
|
|
13656
14869
|
continue;
|
|
13657
14870
|
}
|
|
13658
|
-
const
|
|
13659
|
-
if (
|
|
14871
|
+
const range2 = /^(.|\\u[0-9a-f]{4})-(.|\\u[0-9a-f]{4})$/.exec(m);
|
|
14872
|
+
if (range2 !== null) {
|
|
13660
14873
|
const dec = (t) => t.startsWith("\\u") ? parseInt(t.slice(2), 16) : t.codePointAt(0);
|
|
13661
|
-
if (cp >= dec(
|
|
14874
|
+
if (cp >= dec(range2[1]) && cp <= dec(range2[2])) return true;
|
|
13662
14875
|
continue;
|
|
13663
14876
|
}
|
|
13664
14877
|
if (m === ch2) return true;
|
|
@@ -14732,7 +15945,7 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
|
|
|
14732
15945
|
};
|
|
14733
15946
|
const { prog, fnSrcs } = encodeTableProgram({ [ENTRY]: combinator }, settings);
|
|
14734
15947
|
const artifact = closureArtifact(prog);
|
|
14735
|
-
const entry = tableRules(
|
|
15948
|
+
const entry = tableRules(prog)[ENTRY];
|
|
14736
15949
|
const offered = opts.fnSources ?? mapFnSources;
|
|
14737
15950
|
const supplied = offered !== void 0 && offered.length === fnSrcs.length ? offered : void 0;
|
|
14738
15951
|
const sources = fnSrcs.map((s, i) => s ?? supplied?.[i] ?? ownSource(prog.fns[i]));
|
|
@@ -14781,106 +15994,6 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
|
|
|
14781
15994
|
};
|
|
14782
15995
|
}
|
|
14783
15996
|
|
|
14784
|
-
// src/analysis/commitment.ts
|
|
14785
|
-
function hasDirectBuildDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
14786
|
-
if (seen.has(p)) return false;
|
|
14787
|
-
seen.add(p);
|
|
14788
|
-
const d = p._def;
|
|
14789
|
-
switch (d.tag) {
|
|
14790
|
-
case "node":
|
|
14791
|
-
return d.build !== void 0 || hasDirectBuildDef(d.parser, seen);
|
|
14792
|
-
case "lazy": {
|
|
14793
|
-
try {
|
|
14794
|
-
return hasDirectBuildDef(d.thunk(), seen);
|
|
14795
|
-
} catch {
|
|
14796
|
-
return false;
|
|
14797
|
-
}
|
|
14798
|
-
}
|
|
14799
|
-
case "grammar":
|
|
14800
|
-
case "trivia":
|
|
14801
|
-
case "token":
|
|
14802
|
-
case "leaf":
|
|
14803
|
-
case "label":
|
|
14804
|
-
case "field":
|
|
14805
|
-
case "optional":
|
|
14806
|
-
case "many":
|
|
14807
|
-
case "oneOrMore":
|
|
14808
|
-
case "attempt":
|
|
14809
|
-
case "not":
|
|
14810
|
-
case "peek":
|
|
14811
|
-
case "withCtx":
|
|
14812
|
-
case "expect":
|
|
14813
|
-
case "transform":
|
|
14814
|
-
return hasDirectBuildDef(d.parser, seen);
|
|
14815
|
-
case "sequence":
|
|
14816
|
-
case "choice":
|
|
14817
|
-
return d.parsers.some((x) => hasDirectBuildDef(x, seen));
|
|
14818
|
-
case "dispatch":
|
|
14819
|
-
return hasDirectBuildDef(d.selector, seen) || d.cases.some((x) => hasDirectBuildDef(x.parser, seen)) || (d.matchers ? d.matchers.some((x) => hasDirectBuildDef(x.parser, seen)) : false) || (d.otherwise ? hasDirectBuildDef(d.otherwise, seen) : false);
|
|
14820
|
-
case "sepBy":
|
|
14821
|
-
return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.separator, seen);
|
|
14822
|
-
case "scanTo":
|
|
14823
|
-
return hasDirectBuildDef(d.sentinel, seen) || d.skip.some((x) => hasDirectBuildDef(x, seen));
|
|
14824
|
-
case "recover":
|
|
14825
|
-
return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.sentinel, seen);
|
|
14826
|
-
case "routed":
|
|
14827
|
-
return d.fallback ? hasDirectBuildDef(d.fallback, seen) : false;
|
|
14828
|
-
default:
|
|
14829
|
-
return false;
|
|
14830
|
-
}
|
|
14831
|
-
}
|
|
14832
|
-
function hasSemanticReduction(roots, externalRefs) {
|
|
14833
|
-
const seen = /* @__PURE__ */ new Set();
|
|
14834
|
-
const visit = (parser2) => {
|
|
14835
|
-
if (seen.has(parser2)) return false;
|
|
14836
|
-
seen.add(parser2);
|
|
14837
|
-
const def = parser2._def;
|
|
14838
|
-
if (def.tag === "transform" && !def.recognitionOnly) return true;
|
|
14839
|
-
if (def.tag === "choice" && def.gates.some(Boolean)) return true;
|
|
14840
|
-
if (def.tag === "guard" || def.tag === "withCtx") return true;
|
|
14841
|
-
if (def.tag === "node" && def.build !== void 0) return true;
|
|
14842
|
-
if (def.tag === "lazy") {
|
|
14843
|
-
if (externalRefs?.has(parser2)) return false;
|
|
14844
|
-
try {
|
|
14845
|
-
return visit(def.thunk());
|
|
14846
|
-
} catch {
|
|
14847
|
-
return true;
|
|
14848
|
-
}
|
|
14849
|
-
}
|
|
14850
|
-
return childrenOf2(def).some(visit);
|
|
14851
|
-
};
|
|
14852
|
-
return roots.some(visit);
|
|
14853
|
-
}
|
|
14854
|
-
function classifyRuleMap(ruleMap) {
|
|
14855
|
-
const externalRefs = /* @__PURE__ */ new Set();
|
|
14856
|
-
const scanned = /* @__PURE__ */ new Set();
|
|
14857
|
-
const scanExternal = (p) => {
|
|
14858
|
-
if (scanned.has(p)) return;
|
|
14859
|
-
scanned.add(p);
|
|
14860
|
-
const def = p._def;
|
|
14861
|
-
if (def.tag === "lazy") {
|
|
14862
|
-
let resolved;
|
|
14863
|
-
try {
|
|
14864
|
-
resolved = def.thunk();
|
|
14865
|
-
} catch {
|
|
14866
|
-
resolved = void 0;
|
|
14867
|
-
}
|
|
14868
|
-
if (resolved === void 0) {
|
|
14869
|
-
if (p._ruleName) externalRefs.add(p);
|
|
14870
|
-
return;
|
|
14871
|
-
}
|
|
14872
|
-
scanExternal(resolved);
|
|
14873
|
-
return;
|
|
14874
|
-
}
|
|
14875
|
-
for (const child of childrenOf2(def)) scanExternal(child);
|
|
14876
|
-
};
|
|
14877
|
-
for (const [, rule] of ruleMap) scanExternal(rule);
|
|
14878
|
-
return {
|
|
14879
|
-
hasDirectBuilders: ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
|
|
14880
|
-
isRecognitionOnly: !hasSemanticReduction(ruleMap.map(([, rule]) => rule), externalRefs)
|
|
14881
|
-
};
|
|
14882
|
-
}
|
|
14883
|
-
|
|
14884
15997
|
// src/combinators/withCtx.ts
|
|
14885
15998
|
function withCtx(extra, combinator) {
|
|
14886
15999
|
const meta = {
|
|
@@ -15023,7 +16136,7 @@ function evalRuleMapIR(ir) {
|
|
|
15023
16136
|
l._def.fnSrc = src;
|
|
15024
16137
|
return l;
|
|
15025
16138
|
};
|
|
15026
|
-
const _nd = (type, child, src, opts, staticError, sigSrc, buildImports) => {
|
|
16139
|
+
const _nd = (type, child, src, opts, staticError, sigSrc, buildImports, rawUnused) => {
|
|
15027
16140
|
if (staticError !== void 0 && staticError.length > 0) {
|
|
15028
16141
|
throw new Error(`IR direct node builder for ${type} must be macro-static and self-contained; unsupported binding(s): ${staticError.join(", ")}`);
|
|
15029
16142
|
}
|
|
@@ -15033,6 +16146,7 @@ function evalRuleMapIR(ir) {
|
|
|
15033
16146
|
n._def.buildSrc = src;
|
|
15034
16147
|
if (staticError !== void 0) n._def.buildStaticError = staticError;
|
|
15035
16148
|
if (sigSrc !== void 0) n._def.buildSigSrc = sigSrc;
|
|
16149
|
+
if (rawUnused === true) n._def.buildRawUnused = true;
|
|
15036
16150
|
if (buildImports !== void 0) n._def.buildImports = buildImports;
|
|
15037
16151
|
return n;
|
|
15038
16152
|
};
|
|
@@ -15425,12 +16539,13 @@ ${outerDecls.map((d) => " " + d).join("\n")}
|
|
|
15425
16539
|
}
|
|
15426
16540
|
if (def.buildSrc !== void 0) {
|
|
15427
16541
|
const tail = [];
|
|
15428
|
-
if (def.buildStaticError !== void 0 || def.buildSigSrc !== void 0 || def.buildImports !== void 0) {
|
|
16542
|
+
if (def.buildStaticError !== void 0 || def.buildSigSrc !== void 0 || def.buildImports !== void 0 || def.buildRawUnused === true) {
|
|
15429
16543
|
if (!opts) tail.push("undefined");
|
|
15430
16544
|
tail.push(def.buildStaticError === void 0 ? "undefined" : JSON.stringify(def.buildStaticError));
|
|
15431
16545
|
}
|
|
15432
|
-
if (def.buildSigSrc !== void 0 || def.buildImports !== void 0) tail.push(def.buildSigSrc === void 0 ? "undefined" : JSON.stringify(def.buildSigSrc));
|
|
15433
|
-
if (def.buildImports !== void 0) tail.push(JSON.stringify(def.buildImports));
|
|
16546
|
+
if (def.buildSigSrc !== void 0 || def.buildImports !== void 0 || def.buildRawUnused === true) tail.push(def.buildSigSrc === void 0 ? "undefined" : JSON.stringify(def.buildSigSrc));
|
|
16547
|
+
if (def.buildImports !== void 0 || def.buildRawUnused === true) tail.push(def.buildImports === void 0 ? "undefined" : JSON.stringify(def.buildImports));
|
|
16548
|
+
if (def.buildRawUnused === true) tail.push("true");
|
|
15434
16549
|
const trailing = tail.length > 0 ? `, ${tail.join(", ")}` : "";
|
|
15435
16550
|
return `_nd(${JSON.stringify(def.type)}, ${kid(def.parser)}, ${JSON.stringify(def.buildSrc)}${opts}${trailing})`;
|
|
15436
16551
|
}
|
|
@@ -15499,7 +16614,7 @@ function compileRuleMapRunnable(ruleMap, opts = {}) {
|
|
|
15499
16614
|
hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
|
|
15500
16615
|
reflection: collectGrammarReflection(ruleMap),
|
|
15501
16616
|
...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
|
|
15502
|
-
rules: tableRules(
|
|
16617
|
+
rules: tableRules(prog),
|
|
15503
16618
|
prog: artifact
|
|
15504
16619
|
};
|
|
15505
16620
|
}
|
|
@@ -15571,13 +16686,13 @@ function compileRuleMap(ruleMap, opts = {}) {
|
|
|
15571
16686
|
hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
|
|
15572
16687
|
reflection: collectGrammarReflection(ruleMap),
|
|
15573
16688
|
...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
|
|
15574
|
-
rules: tableRules(
|
|
16689
|
+
rules: tableRules(prog),
|
|
15575
16690
|
prog: artifact
|
|
15576
16691
|
};
|
|
15577
16692
|
}
|
|
15578
16693
|
|
|
15579
16694
|
// src/version.ts
|
|
15580
|
-
var PARSEMAN_VERSION = "0.
|
|
16695
|
+
var PARSEMAN_VERSION = "0.50.1";
|
|
15581
16696
|
|
|
15582
16697
|
// src/compiler/compile-linkable-table.ts
|
|
15583
16698
|
function isLocal(rule) {
|
|
@@ -15653,16 +16768,16 @@ function normalizeCstCollapse(collapse) {
|
|
|
15653
16768
|
}
|
|
15654
16769
|
return typeof collapse === "function" ? collapse : void 0;
|
|
15655
16770
|
}
|
|
15656
|
-
function buildCstNode(type,
|
|
15657
|
-
return tags !== void 0 && tags.length > 0 ? { _tag: "node", type, tags, span: { ...span }, state: state ?? null, children: [...
|
|
16771
|
+
function buildCstNode(type, children3, _fields, span, _rawChildren, _triviaLog, state, tags) {
|
|
16772
|
+
return tags !== void 0 && tags.length > 0 ? { _tag: "node", type, tags, span: { ...span }, state: state ?? null, children: [...children3] } : { _tag: "node", type, span: { ...span }, state: state ?? null, children: [...children3] };
|
|
15658
16773
|
}
|
|
15659
|
-
function cstBuildHost(typeOrOptions,
|
|
16774
|
+
function cstBuildHost(typeOrOptions, children3, _fields, span, rawChildren, triviaLog, state, _tags) {
|
|
15660
16775
|
if (typeof typeOrOptions === "string") {
|
|
15661
|
-
return buildCstNode(typeOrOptions,
|
|
16776
|
+
return buildCstNode(typeOrOptions, children3 ?? [], _fields, span ?? { start: 0, end: 0 }, rawChildren, triviaLog, state);
|
|
15662
16777
|
}
|
|
15663
16778
|
const collapse = normalizeCstCollapse(typeOrOptions?.collapse);
|
|
15664
16779
|
const materializeTags = typeOrOptions?.tags === true;
|
|
15665
|
-
const host = (type,
|
|
16780
|
+
const host = (type, children4, fields, span2, rawChildren2, triviaLog2, state2, tags) => buildCstNode(type, children4 ?? [], fields, span2, rawChildren2, triviaLog2, state2, materializeTags ? tags : void 0);
|
|
15666
16781
|
host._parsemanCstOutput = true;
|
|
15667
16782
|
if (collapse) host._parsemanCstCollapse = collapse;
|
|
15668
16783
|
return host;
|
|
@@ -15818,39 +16933,39 @@ function directBuilderBindings(src) {
|
|
|
15818
16933
|
if (selfName?.type === "Identifier" && typeof selfName.name === "string") allowed.add(selfName.name);
|
|
15819
16934
|
const structural = /* @__PURE__ */ new Set();
|
|
15820
16935
|
const free = /* @__PURE__ */ new Set();
|
|
15821
|
-
const reportUnsupportedNode = (
|
|
15822
|
-
structural.add(`unsupported ${
|
|
16936
|
+
const reportUnsupportedNode = (ast2) => {
|
|
16937
|
+
structural.add(`unsupported ${ast2.type}`);
|
|
15823
16938
|
};
|
|
15824
|
-
const read = (
|
|
15825
|
-
if (typeof
|
|
15826
|
-
if (
|
|
16939
|
+
const read = (ast2, allowedNames) => {
|
|
16940
|
+
if (typeof ast2.name === "string" && allowedNames.has(ast2.name)) return;
|
|
16941
|
+
if (ast2.name === "arguments") {
|
|
15827
16942
|
structural.add("unsupported arguments");
|
|
15828
16943
|
return;
|
|
15829
16944
|
}
|
|
15830
|
-
if (typeof
|
|
16945
|
+
if (typeof ast2.name === "string") free.add(ast2.name);
|
|
15831
16946
|
else structural.add("unsupported identifier");
|
|
15832
16947
|
};
|
|
15833
16948
|
const expression = (node2, allowedNames) => {
|
|
15834
|
-
const
|
|
15835
|
-
if (!
|
|
15836
|
-
switch (
|
|
16949
|
+
const ast2 = astChild(node2);
|
|
16950
|
+
if (!ast2) return;
|
|
16951
|
+
switch (ast2.type) {
|
|
15837
16952
|
case "Literal":
|
|
15838
16953
|
return;
|
|
15839
16954
|
case "Identifier":
|
|
15840
|
-
read(
|
|
16955
|
+
read(ast2, allowedNames);
|
|
15841
16956
|
return;
|
|
15842
16957
|
case "ParenthesizedExpression":
|
|
15843
16958
|
case "ChainExpression":
|
|
15844
16959
|
case "TSAsExpression":
|
|
15845
16960
|
case "TSTypeAssertion":
|
|
15846
16961
|
case "TSNonNullExpression":
|
|
15847
|
-
expression(
|
|
16962
|
+
expression(ast2.expression, allowedNames);
|
|
15848
16963
|
return;
|
|
15849
16964
|
case "ArrayExpression":
|
|
15850
|
-
for (const element of astArray(
|
|
16965
|
+
for (const element of astArray(ast2.elements)) expression(element, allowedNames);
|
|
15851
16966
|
return;
|
|
15852
16967
|
case "ObjectExpression":
|
|
15853
|
-
for (const property of astArray(
|
|
16968
|
+
for (const property of astArray(ast2.properties)) {
|
|
15854
16969
|
if (property.type === "SpreadElement") {
|
|
15855
16970
|
expression(property.argument, allowedNames);
|
|
15856
16971
|
continue;
|
|
@@ -15864,109 +16979,109 @@ function directBuilderBindings(src) {
|
|
|
15864
16979
|
}
|
|
15865
16980
|
return;
|
|
15866
16981
|
case "MemberExpression":
|
|
15867
|
-
expression(
|
|
15868
|
-
if (
|
|
16982
|
+
expression(ast2.object, allowedNames);
|
|
16983
|
+
if (ast2.computed === true) expression(ast2.property, allowedNames);
|
|
15869
16984
|
return;
|
|
15870
16985
|
case "CallExpression":
|
|
15871
16986
|
case "NewExpression":
|
|
15872
|
-
expression(
|
|
15873
|
-
for (const argument of astArray(
|
|
16987
|
+
expression(ast2.callee, allowedNames);
|
|
16988
|
+
for (const argument of astArray(ast2.arguments)) expression(argument, allowedNames);
|
|
15874
16989
|
return;
|
|
15875
16990
|
case "UnaryExpression":
|
|
15876
16991
|
case "UpdateExpression":
|
|
15877
|
-
expression(
|
|
16992
|
+
expression(ast2.argument, allowedNames);
|
|
15878
16993
|
return;
|
|
15879
16994
|
case "BinaryExpression":
|
|
15880
16995
|
case "LogicalExpression":
|
|
15881
16996
|
case "AssignmentExpression":
|
|
15882
|
-
expression(
|
|
15883
|
-
expression(
|
|
16997
|
+
expression(ast2.left, allowedNames);
|
|
16998
|
+
expression(ast2.right, allowedNames);
|
|
15884
16999
|
return;
|
|
15885
17000
|
case "ConditionalExpression":
|
|
15886
|
-
expression(
|
|
15887
|
-
expression(
|
|
15888
|
-
expression(
|
|
17001
|
+
expression(ast2.test, allowedNames);
|
|
17002
|
+
expression(ast2.consequent, allowedNames);
|
|
17003
|
+
expression(ast2.alternate, allowedNames);
|
|
15889
17004
|
return;
|
|
15890
17005
|
case "SequenceExpression":
|
|
15891
|
-
for (const value of astArray(
|
|
17006
|
+
for (const value of astArray(ast2.expressions)) expression(value, allowedNames);
|
|
15892
17007
|
return;
|
|
15893
17008
|
case "TemplateLiteral":
|
|
15894
|
-
for (const value of astArray(
|
|
17009
|
+
for (const value of astArray(ast2.expressions)) expression(value, allowedNames);
|
|
15895
17010
|
return;
|
|
15896
17011
|
case "SpreadElement":
|
|
15897
|
-
expression(
|
|
17012
|
+
expression(ast2.argument, allowedNames);
|
|
15898
17013
|
return;
|
|
15899
17014
|
case "ArrowFunctionExpression": {
|
|
15900
17015
|
const nested = new Set(allowedNames);
|
|
15901
|
-
for (const param of astArray(
|
|
17016
|
+
for (const param of astArray(ast2.params)) {
|
|
15902
17017
|
if (param.type !== "Identifier" || typeof param.name !== "string") {
|
|
15903
17018
|
reportUnsupportedNode(param);
|
|
15904
17019
|
continue;
|
|
15905
17020
|
}
|
|
15906
17021
|
nested.add(param.name);
|
|
15907
17022
|
}
|
|
15908
|
-
const nestedBody = astChild(
|
|
17023
|
+
const nestedBody = astChild(ast2.body);
|
|
15909
17024
|
if (nestedBody?.type === "BlockStatement") {
|
|
15910
17025
|
statement(nestedBody, nested);
|
|
15911
17026
|
return;
|
|
15912
17027
|
}
|
|
15913
|
-
expression(
|
|
17028
|
+
expression(ast2.body, nested);
|
|
15914
17029
|
return;
|
|
15915
17030
|
}
|
|
15916
17031
|
default:
|
|
15917
|
-
reportUnsupportedNode(
|
|
17032
|
+
reportUnsupportedNode(ast2);
|
|
15918
17033
|
return;
|
|
15919
17034
|
}
|
|
15920
17035
|
};
|
|
15921
17036
|
const statement = (node2, names) => {
|
|
15922
|
-
const
|
|
15923
|
-
if (!
|
|
15924
|
-
switch (
|
|
17037
|
+
const ast2 = astChild(node2);
|
|
17038
|
+
if (!ast2) return;
|
|
17039
|
+
switch (ast2.type) {
|
|
15925
17040
|
case "VariableDeclaration":
|
|
15926
|
-
for (const d of astArray(
|
|
17041
|
+
for (const d of astArray(ast2.declarations)) {
|
|
15927
17042
|
expression(d.init, names);
|
|
15928
17043
|
const idAst = astChild(d.id);
|
|
15929
17044
|
if (idAst?.type === "Identifier" && typeof idAst.name === "string") names.add(idAst.name);
|
|
15930
|
-
else reportUnsupportedNode(idAst ??
|
|
17045
|
+
else reportUnsupportedNode(idAst ?? ast2);
|
|
15931
17046
|
}
|
|
15932
17047
|
return;
|
|
15933
17048
|
case "ReturnStatement":
|
|
15934
|
-
expression(
|
|
17049
|
+
expression(ast2.argument, names);
|
|
15935
17050
|
return;
|
|
15936
17051
|
case "ExpressionStatement":
|
|
15937
|
-
expression(
|
|
17052
|
+
expression(ast2.expression, names);
|
|
15938
17053
|
return;
|
|
15939
17054
|
case "ThrowStatement":
|
|
15940
|
-
expression(
|
|
17055
|
+
expression(ast2.argument, names);
|
|
15941
17056
|
return;
|
|
15942
17057
|
case "IfStatement":
|
|
15943
|
-
expression(
|
|
15944
|
-
statement(
|
|
15945
|
-
if (
|
|
17058
|
+
expression(ast2.test, names);
|
|
17059
|
+
statement(ast2.consequent, new Set(names));
|
|
17060
|
+
if (ast2.alternate) statement(ast2.alternate, new Set(names));
|
|
15946
17061
|
return;
|
|
15947
17062
|
case "ForStatement": {
|
|
15948
17063
|
const inner = new Set(names);
|
|
15949
|
-
if (
|
|
15950
|
-
const initAst = astChild(
|
|
17064
|
+
if (ast2.init) {
|
|
17065
|
+
const initAst = astChild(ast2.init);
|
|
15951
17066
|
if (initAst?.type === "VariableDeclaration") statement(initAst, inner);
|
|
15952
17067
|
else expression(initAst, inner);
|
|
15953
17068
|
}
|
|
15954
|
-
if (
|
|
15955
|
-
if (
|
|
15956
|
-
statement(
|
|
17069
|
+
if (ast2.test) expression(ast2.test, inner);
|
|
17070
|
+
if (ast2.update) expression(ast2.update, inner);
|
|
17071
|
+
statement(ast2.body, inner);
|
|
15957
17072
|
return;
|
|
15958
17073
|
}
|
|
15959
17074
|
case "ForOfStatement":
|
|
15960
17075
|
case "ForInStatement": {
|
|
15961
17076
|
const inner = new Set(names);
|
|
15962
|
-
statement(
|
|
15963
|
-
expression(
|
|
15964
|
-
statement(
|
|
17077
|
+
statement(ast2.left, inner);
|
|
17078
|
+
expression(ast2.right, names);
|
|
17079
|
+
statement(ast2.body, inner);
|
|
15965
17080
|
return;
|
|
15966
17081
|
}
|
|
15967
17082
|
case "BlockStatement": {
|
|
15968
17083
|
const inner = new Set(names);
|
|
15969
|
-
for (const s of astArray(
|
|
17084
|
+
for (const s of astArray(ast2.body)) statement(s, inner);
|
|
15970
17085
|
return;
|
|
15971
17086
|
}
|
|
15972
17087
|
case "BreakStatement":
|
|
@@ -15974,7 +17089,7 @@ function directBuilderBindings(src) {
|
|
|
15974
17089
|
case "EmptyStatement":
|
|
15975
17090
|
return;
|
|
15976
17091
|
default:
|
|
15977
|
-
reportUnsupportedNode(
|
|
17092
|
+
reportUnsupportedNode(ast2);
|
|
15978
17093
|
return;
|
|
15979
17094
|
}
|
|
15980
17095
|
};
|
|
@@ -16413,6 +17528,7 @@ function exprToCombi(node2, scope, code, mfs) {
|
|
|
16413
17528
|
try {
|
|
16414
17529
|
const combi = explicitType !== void 0 ? node(explicitType, inner, hasBuild ? () => null : void 0, opts) : node(inner, hasBuild ? () => null : void 0, opts);
|
|
16415
17530
|
if (combi._def.tag === "node" && buildSrc !== void 0) {
|
|
17531
|
+
const authorDeclaredBuildArity = opts?.buildArity !== void 0;
|
|
16416
17532
|
combi._def.buildSrc = buildSrc;
|
|
16417
17533
|
if (explicitType !== void 0 && firstArg.type === "Identifier") {
|
|
16418
17534
|
combi._def.typeSrc = firstArg.name;
|
|
@@ -16427,6 +17543,9 @@ function exprToCombi(node2, scope, code, mfs) {
|
|
|
16427
17543
|
if (resolved.reason !== void 0) combi._def.buildArityUnresolved = resolved.reason;
|
|
16428
17544
|
}
|
|
16429
17545
|
const analysisSrc = combi._def.buildSigSrc ?? buildSrc;
|
|
17546
|
+
if (!authorDeclaredBuildArity && confirmedBuildParamUnused(analysisSrc, 3)) {
|
|
17547
|
+
combi._def.buildRawUnused = true;
|
|
17548
|
+
}
|
|
16430
17549
|
const report = directBuilderBindings(analysisSrc);
|
|
16431
17550
|
const isInlineBuilder = combi._def.buildSigSrc === void 0;
|
|
16432
17551
|
const carriedImports = [];
|
|
@@ -16980,8 +18099,8 @@ var SCOPE_TYPES = /* @__PURE__ */ new Set([
|
|
|
16980
18099
|
"ClassExpression",
|
|
16981
18100
|
"StaticBlock"
|
|
16982
18101
|
]);
|
|
16983
|
-
function newScope(start, end, parent,
|
|
16984
|
-
const s = { start, end, bindings: /* @__PURE__ */ new Map(), children: [], parent, isFunction };
|
|
18102
|
+
function newScope(start, end, parent, isFunction2) {
|
|
18103
|
+
const s = { start, end, bindings: /* @__PURE__ */ new Map(), children: [], parent, isFunction: isFunction2 };
|
|
16985
18104
|
parent?.children.push(s);
|
|
16986
18105
|
return s;
|
|
16987
18106
|
}
|
|
@@ -17567,6 +18686,456 @@ function findFreeIdentifiers(code, filename) {
|
|
|
17567
18686
|
}).map(({ name, line, column, enclosing }) => ({ name, line, column, enclosing }));
|
|
17568
18687
|
}
|
|
17569
18688
|
|
|
18689
|
+
// src/plugin/entry-supercompiler.ts
|
|
18690
|
+
import { parseSync as parseSync4 } from "oxc-parser";
|
|
18691
|
+
var PIECE = /^_pf(\d+)$/;
|
|
18692
|
+
var WRAP = "function __parseman_supercompile__(){\n";
|
|
18693
|
+
var SUFFIX = "\n}";
|
|
18694
|
+
function ast(value) {
|
|
18695
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
18696
|
+
}
|
|
18697
|
+
function nodes(value) {
|
|
18698
|
+
return Array.isArray(value) ? value.filter((v) => ast(v) !== void 0) : [];
|
|
18699
|
+
}
|
|
18700
|
+
function nameOf(node2) {
|
|
18701
|
+
return node2?.type === "Identifier" && typeof node2.name === "string" ? node2.name : void 0;
|
|
18702
|
+
}
|
|
18703
|
+
function range(node2) {
|
|
18704
|
+
if (typeof node2.start !== "number" || typeof node2.end !== "number") throw new Error("entry supercompiler: AST node without range");
|
|
18705
|
+
return { start: node2.start - WRAP.length, end: node2.end - WRAP.length };
|
|
18706
|
+
}
|
|
18707
|
+
function children2(node2) {
|
|
18708
|
+
const out = [];
|
|
18709
|
+
for (const [key, value] of Object.entries(node2)) {
|
|
18710
|
+
if (key === "type" || key === "start" || key === "end") continue;
|
|
18711
|
+
if (Array.isArray(value)) {
|
|
18712
|
+
for (const child of value) {
|
|
18713
|
+
const c = ast(child);
|
|
18714
|
+
if (c !== void 0) out.push(c);
|
|
18715
|
+
}
|
|
18716
|
+
} else {
|
|
18717
|
+
const c = ast(value);
|
|
18718
|
+
if (c !== void 0) out.push(c);
|
|
18719
|
+
}
|
|
18720
|
+
}
|
|
18721
|
+
return out;
|
|
18722
|
+
}
|
|
18723
|
+
function isFunction(node2) {
|
|
18724
|
+
return node2.type === "FunctionDeclaration" || node2.type === "FunctionExpression" || node2.type === "ArrowFunctionExpression";
|
|
18725
|
+
}
|
|
18726
|
+
function isDirectCallUse(call, parent, statement) {
|
|
18727
|
+
if (parent === void 0) return false;
|
|
18728
|
+
if (parent.type === "VariableDeclarator") {
|
|
18729
|
+
const declarations = statement.type === "VariableDeclaration" ? nodes(statement.declarations) : [];
|
|
18730
|
+
return declarations.length === 1 && declarations[0] === parent && parent.init === call;
|
|
18731
|
+
}
|
|
18732
|
+
if (parent.type === "AssignmentExpression") {
|
|
18733
|
+
return statement.type === "ExpressionStatement" && statement.expression === parent && nameOf(ast(parent.left)) !== void 0 && parent.right === call && parent.operator === "=";
|
|
18734
|
+
}
|
|
18735
|
+
if (parent.type === "ReturnStatement") return statement === parent && parent.argument === call;
|
|
18736
|
+
return false;
|
|
18737
|
+
}
|
|
18738
|
+
function isListStatement(statement, parent) {
|
|
18739
|
+
if (parent?.type === "BlockStatement") return nodes(parent.body).includes(statement);
|
|
18740
|
+
if (parent?.type === "SwitchCase") return nodes(parent.consequent).includes(statement);
|
|
18741
|
+
return false;
|
|
18742
|
+
}
|
|
18743
|
+
function hasInlineScopeHazard(fn) {
|
|
18744
|
+
if (fn.node.async === true || fn.node.generator === true) return true;
|
|
18745
|
+
let hazard = false;
|
|
18746
|
+
const walk = (node2) => {
|
|
18747
|
+
if (hazard) return;
|
|
18748
|
+
if (node2.type === "Identifier" && node2.name === "arguments") hazard = true;
|
|
18749
|
+
else if (node2.type === "ThisExpression") hazard = true;
|
|
18750
|
+
else if (node2.type === "VariableDeclaration" && node2.kind === "var") hazard = true;
|
|
18751
|
+
else if (node2.type === "MetaProperty" && nameOf(ast(node2.meta)) === "new" && nameOf(ast(node2.property)) === "target") hazard = true;
|
|
18752
|
+
else for (const child of children2(node2)) walk(child);
|
|
18753
|
+
};
|
|
18754
|
+
walk(fn.body);
|
|
18755
|
+
return hazard;
|
|
18756
|
+
}
|
|
18757
|
+
function hasInlineSignature(fn) {
|
|
18758
|
+
const params = nodes(fn.node.params);
|
|
18759
|
+
return params.length === 3 && nameOf(params[0]) === "input" && nameOf(params[1]) === "pos" && nameOf(params[2]) === "ctx";
|
|
18760
|
+
}
|
|
18761
|
+
function render2(source, start, end, edits) {
|
|
18762
|
+
const ordered = [...edits].sort((a, b) => a.start - b.start || a.end - b.end);
|
|
18763
|
+
let at = start;
|
|
18764
|
+
let out = "";
|
|
18765
|
+
for (const edit of ordered) {
|
|
18766
|
+
if (edit.start < at || edit.end < edit.start || edit.start < start || edit.end > end) {
|
|
18767
|
+
throw new Error("entry supercompiler: overlapping or out-of-range structured edit");
|
|
18768
|
+
}
|
|
18769
|
+
out += source.slice(at, edit.start) + edit.text;
|
|
18770
|
+
at = edit.end;
|
|
18771
|
+
}
|
|
18772
|
+
return out + source.slice(at, end);
|
|
18773
|
+
}
|
|
18774
|
+
function recursiveMembers(fns) {
|
|
18775
|
+
let next = 0;
|
|
18776
|
+
const index = /* @__PURE__ */ new Map();
|
|
18777
|
+
const low = /* @__PURE__ */ new Map();
|
|
18778
|
+
const stack = [];
|
|
18779
|
+
const on = /* @__PURE__ */ new Set();
|
|
18780
|
+
const recursive = /* @__PURE__ */ new Set();
|
|
18781
|
+
const visit = (ip) => {
|
|
18782
|
+
index.set(ip, next);
|
|
18783
|
+
low.set(ip, next);
|
|
18784
|
+
next++;
|
|
18785
|
+
stack.push(ip);
|
|
18786
|
+
on.add(ip);
|
|
18787
|
+
for (const call of fns.get(ip)?.calls ?? []) {
|
|
18788
|
+
if (!fns.has(call.callee)) continue;
|
|
18789
|
+
if (!index.has(call.callee)) {
|
|
18790
|
+
visit(call.callee);
|
|
18791
|
+
low.set(ip, Math.min(low.get(ip), low.get(call.callee)));
|
|
18792
|
+
} else if (on.has(call.callee)) low.set(ip, Math.min(low.get(ip), index.get(call.callee)));
|
|
18793
|
+
}
|
|
18794
|
+
if (low.get(ip) !== index.get(ip)) return;
|
|
18795
|
+
const component = [];
|
|
18796
|
+
for (; ; ) {
|
|
18797
|
+
const member = stack.pop();
|
|
18798
|
+
on.delete(member);
|
|
18799
|
+
component.push(member);
|
|
18800
|
+
if (member === ip) break;
|
|
18801
|
+
}
|
|
18802
|
+
if (component.length > 1 || component.some((member) => fns.get(member).calls.some((c) => c.callee === member))) {
|
|
18803
|
+
for (const member of component) recursive.add(member);
|
|
18804
|
+
}
|
|
18805
|
+
};
|
|
18806
|
+
for (const ip of fns.keys()) if (!index.has(ip)) visit(ip);
|
|
18807
|
+
return recursive;
|
|
18808
|
+
}
|
|
18809
|
+
function fallback(emitted, reason, before) {
|
|
18810
|
+
return {
|
|
18811
|
+
...emitted,
|
|
18812
|
+
supercompile: {
|
|
18813
|
+
...before,
|
|
18814
|
+
activated: false,
|
|
18815
|
+
reason,
|
|
18816
|
+
functionsAfter: before.functionsBefore,
|
|
18817
|
+
pieceCallsAfter: before.pieceCallsBefore,
|
|
18818
|
+
sourceAfter: before.sourceBefore,
|
|
18819
|
+
regions: before.functionsBefore,
|
|
18820
|
+
largestRegionSource: 0,
|
|
18821
|
+
protocolRegions: { node: 0, repv: 0, nodeAndRepv: 0 }
|
|
18822
|
+
}
|
|
18823
|
+
};
|
|
18824
|
+
}
|
|
18825
|
+
function supercompileRuleMapReplacement(prog, replacement) {
|
|
18826
|
+
const cfg = defaultAssemblyCfgs(prog)[0];
|
|
18827
|
+
if (cfg === void 0) return replacement;
|
|
18828
|
+
const extraIps = [];
|
|
18829
|
+
for (const scan of prog.scans ?? []) {
|
|
18830
|
+
for (const ref2 of scan.skip) extraIps.push(ref2[0]);
|
|
18831
|
+
if (scan.sentinel !== void 0) extraIps.push(scan.sentinel[0]);
|
|
18832
|
+
}
|
|
18833
|
+
for (const set of prog.scanSkip ?? []) for (const ref2 of set) extraIps.push(ref2[0]);
|
|
18834
|
+
let canonical2;
|
|
18835
|
+
let candidate;
|
|
18836
|
+
try {
|
|
18837
|
+
canonical2 = emitAssemblySource(resolveTable(prog), prog, cfg, extraIps, true);
|
|
18838
|
+
candidate = supercompileEmittedAssembly(prog, cfg, extraIps, canonical2);
|
|
18839
|
+
} catch {
|
|
18840
|
+
return replacement;
|
|
18841
|
+
}
|
|
18842
|
+
if (!candidate.supercompile.activated) return replacement;
|
|
18843
|
+
const prefix = "const __parseman_macro_replacement__=";
|
|
18844
|
+
const parsed = parseSync4("parseman-entry-supercompile-replacement.js", prefix + replacement);
|
|
18845
|
+
if (parsed.errors.length > 0) return replacement;
|
|
18846
|
+
const program = parsed.program;
|
|
18847
|
+
const declaration = nodes(program.body)[0];
|
|
18848
|
+
const declarator = nodes(declaration?.declarations)[0];
|
|
18849
|
+
const call = ast(declarator?.init);
|
|
18850
|
+
const table = nodes(call?.arguments)[0];
|
|
18851
|
+
if (declaration?.type !== "VariableDeclaration" || declarator?.type !== "VariableDeclarator" || call?.type !== "CallExpression" || table?.type !== "ObjectExpression") return replacement;
|
|
18852
|
+
const property = (object, key) => nodes(object.properties).find((prop) => prop.type === "Property" && nameOf(ast(prop.key)) === key);
|
|
18853
|
+
const assembliesProp = property(table, "a");
|
|
18854
|
+
const assemblies = nodes(ast(assembliesProp?.value)?.elements);
|
|
18855
|
+
if (assembliesProp === void 0 || assemblies.length !== 1 || assemblies[0]?.type !== "ObjectExpression") return replacement;
|
|
18856
|
+
const factoryProp = property(assemblies[0], "factory");
|
|
18857
|
+
const factory = ast(factoryProp?.value);
|
|
18858
|
+
const body = ast(factory?.body);
|
|
18859
|
+
if (factory?.type !== "FunctionExpression" || body?.type !== "BlockStatement") return replacement;
|
|
18860
|
+
if (typeof body.start !== "number" || typeof body.end !== "number") return replacement;
|
|
18861
|
+
const start = body.start - prefix.length + 1;
|
|
18862
|
+
const end = body.end - prefix.length - 1;
|
|
18863
|
+
if (replacement.slice(start, end) !== canonical2.source + "\n") return replacement;
|
|
18864
|
+
const transformed = replacement.slice(0, start) + candidate.source + "\n" + replacement.slice(end);
|
|
18865
|
+
const checked = parseSync4("parseman-entry-supercompile-replacement-result.js", prefix + transformed);
|
|
18866
|
+
return checked.errors.length === 0 ? transformed : replacement;
|
|
18867
|
+
}
|
|
18868
|
+
function supercompileEmittedAssembly(prog, _cfg, extraIps, emitted) {
|
|
18869
|
+
const source = emitted.source;
|
|
18870
|
+
const parsed = parseSync4("parseman-entry-supercompile.js", WRAP + source + SUFFIX);
|
|
18871
|
+
if (parsed.errors.length > 0) {
|
|
18872
|
+
const zero = { functionsBefore: 0, pieceCallsBefore: 0, sourceBefore: source.length, barriers: {} };
|
|
18873
|
+
return fallback(emitted, "canonical emitted source did not parse", zero);
|
|
18874
|
+
}
|
|
18875
|
+
const program = parsed.program;
|
|
18876
|
+
const wrapper = nodes(program.body)[0];
|
|
18877
|
+
const wrapperBody = ast(wrapper?.body);
|
|
18878
|
+
if (wrapper?.type !== "FunctionDeclaration" || wrapperBody?.type !== "BlockStatement") {
|
|
18879
|
+
const zero = { functionsBefore: 0, pieceCallsBefore: 0, sourceBefore: source.length, barriers: {} };
|
|
18880
|
+
return fallback(emitted, "missing compiler wrapper", zero);
|
|
18881
|
+
}
|
|
18882
|
+
const fns = /* @__PURE__ */ new Map();
|
|
18883
|
+
for (const statement of nodes(wrapperBody.body)) {
|
|
18884
|
+
if (statement.type !== "FunctionDeclaration") continue;
|
|
18885
|
+
const name = nameOf(ast(statement.id));
|
|
18886
|
+
const hit = name === void 0 ? void 0 : PIECE.exec(name);
|
|
18887
|
+
const body = ast(statement.body);
|
|
18888
|
+
if (hit !== void 0 && hit !== null && body?.type === "BlockStatement") {
|
|
18889
|
+
const ip = Number(hit[1]);
|
|
18890
|
+
fns.set(ip, { ip, name, node: statement, body, calls: [] });
|
|
18891
|
+
}
|
|
18892
|
+
}
|
|
18893
|
+
const externalRefs = /* @__PURE__ */ new Set();
|
|
18894
|
+
let reservedCollision = false;
|
|
18895
|
+
const allCalls = [];
|
|
18896
|
+
const walk = (node2, current, parent, statement, statementParent) => {
|
|
18897
|
+
if (isFunction(node2) && node2 !== current?.node) {
|
|
18898
|
+
const own = node2.type === "FunctionDeclaration" ? nameOf(ast(node2.id)) : void 0;
|
|
18899
|
+
const hit = own === void 0 ? void 0 : PIECE.exec(own);
|
|
18900
|
+
if (hit !== void 0 && hit !== null) {
|
|
18901
|
+
const fn = fns.get(Number(hit[1]));
|
|
18902
|
+
if (fn !== void 0) {
|
|
18903
|
+
for (const child of children2(node2)) {
|
|
18904
|
+
if (child !== ast(node2.id)) walk(child, fn, node2, void 0, void 0);
|
|
18905
|
+
}
|
|
18906
|
+
return;
|
|
18907
|
+
}
|
|
18908
|
+
}
|
|
18909
|
+
current = void 0;
|
|
18910
|
+
}
|
|
18911
|
+
let owner2 = statement;
|
|
18912
|
+
let ownerParent = statementParent;
|
|
18913
|
+
if (parent?.type === "BlockStatement" && nodes(parent.body).includes(node2)) {
|
|
18914
|
+
owner2 = node2;
|
|
18915
|
+
ownerParent = parent;
|
|
18916
|
+
}
|
|
18917
|
+
if (parent?.type === "SwitchCase" && nodes(parent.consequent).includes(node2)) {
|
|
18918
|
+
owner2 = node2;
|
|
18919
|
+
ownerParent = parent;
|
|
18920
|
+
}
|
|
18921
|
+
if (node2.type === "CallExpression") {
|
|
18922
|
+
const calleeName = nameOf(ast(node2.callee));
|
|
18923
|
+
const hit = calleeName === void 0 ? void 0 : PIECE.exec(calleeName);
|
|
18924
|
+
if (hit !== void 0 && hit !== null) {
|
|
18925
|
+
const callee = Number(hit[1]);
|
|
18926
|
+
const args = nodes(node2.arguments);
|
|
18927
|
+
const transformable = current !== void 0 && owner2 !== void 0 && args.length === 3 && nameOf(args[0]) === "input" && nameOf(args[2]) === "ctx" && isDirectCallUse(node2, parent, owner2) && isListStatement(owner2, ownerParent);
|
|
18928
|
+
if (current === void 0 || owner2 === void 0) externalRefs.add(callee);
|
|
18929
|
+
else {
|
|
18930
|
+
const call = { caller: current.ip, callee, node: node2, statement: owner2, args, transformable };
|
|
18931
|
+
current.calls.push(call);
|
|
18932
|
+
allCalls.push(call);
|
|
18933
|
+
}
|
|
18934
|
+
}
|
|
18935
|
+
}
|
|
18936
|
+
if (node2.type === "Identifier") {
|
|
18937
|
+
if (typeof node2.name === "string" && /^_z\d/.test(node2.name)) reservedCollision = true;
|
|
18938
|
+
const hit = typeof node2.name === "string" ? PIECE.exec(node2.name) : null;
|
|
18939
|
+
if (hit !== null) {
|
|
18940
|
+
const isDecl = parent?.type === "FunctionDeclaration" && parent.id === node2;
|
|
18941
|
+
const isCall = parent?.type === "CallExpression" && parent.callee === node2;
|
|
18942
|
+
if (!isDecl && !isCall) externalRefs.add(Number(hit[1]));
|
|
18943
|
+
}
|
|
18944
|
+
}
|
|
18945
|
+
for (const child of children2(node2)) walk(child, current, node2, owner2, ownerParent);
|
|
18946
|
+
};
|
|
18947
|
+
for (const statement of nodes(wrapperBody.body)) walk(statement, void 0, wrapperBody, void 0, void 0);
|
|
18948
|
+
if (reservedCollision) {
|
|
18949
|
+
const before2 = { functionsBefore: fns.size, pieceCallsBefore: allCalls.length, sourceBefore: source.length, barriers: { name: 1 } };
|
|
18950
|
+
return fallback(emitted, "canonical source uses the reserved _z<N> supercompiler prefix", before2);
|
|
18951
|
+
}
|
|
18952
|
+
const pieceCallsBefore = allCalls.length;
|
|
18953
|
+
const recursive = recursiveMembers(fns);
|
|
18954
|
+
const incoming = /* @__PURE__ */ new Map();
|
|
18955
|
+
for (const call of allCalls) {
|
|
18956
|
+
const list = incoming.get(call.callee) ?? [];
|
|
18957
|
+
list.push(call);
|
|
18958
|
+
incoming.set(call.callee, list);
|
|
18959
|
+
}
|
|
18960
|
+
const publicRoots = /* @__PURE__ */ new Set([...Object.values(prog.rules), ...extraIps]);
|
|
18961
|
+
const barrier = /* @__PURE__ */ new Map();
|
|
18962
|
+
for (const ip of fns.keys()) {
|
|
18963
|
+
if (publicRoots.has(ip) || externalRefs.has(ip)) barrier.set(ip, "public");
|
|
18964
|
+
else if (recursive.has(ip)) barrier.set(ip, "recursive");
|
|
18965
|
+
else if (prog.code[ip] === OP_ATTEMPT || prog.code[ip] === OP_SCAN) barrier.set(ip, "effect");
|
|
18966
|
+
else if (hasInlineScopeHazard(fns.get(ip))) barrier.set(ip, "scope");
|
|
18967
|
+
else if (!hasInlineSignature(fns.get(ip))) barrier.set(ip, "shape");
|
|
18968
|
+
else if ((incoming.get(ip)?.length ?? 0) !== 1) barrier.set(ip, "shared");
|
|
18969
|
+
else if (!incoming.get(ip)[0].transformable) barrier.set(ip, "shape");
|
|
18970
|
+
}
|
|
18971
|
+
const roots = [...fns.keys()].filter((ip) => barrier.has(ip));
|
|
18972
|
+
const owner = /* @__PURE__ */ new Map();
|
|
18973
|
+
const absorb = (ip, root) => {
|
|
18974
|
+
if (owner.has(ip)) return;
|
|
18975
|
+
owner.set(ip, root);
|
|
18976
|
+
for (const call of fns.get(ip)?.calls ?? []) {
|
|
18977
|
+
if (!fns.has(call.callee) || barrier.has(call.callee) || !call.transformable) continue;
|
|
18978
|
+
absorb(call.callee, root);
|
|
18979
|
+
}
|
|
18980
|
+
};
|
|
18981
|
+
for (const root of roots) absorb(root, root);
|
|
18982
|
+
for (const ip of fns.keys()) if (!owner.has(ip)) {
|
|
18983
|
+
barrier.set(ip, "shared");
|
|
18984
|
+
absorb(ip, ip);
|
|
18985
|
+
}
|
|
18986
|
+
let serial = 0;
|
|
18987
|
+
const src = (node2) => {
|
|
18988
|
+
const r = range(node2);
|
|
18989
|
+
return source.slice(r.start, r.end);
|
|
18990
|
+
};
|
|
18991
|
+
const renderBody = (ip, embedded) => {
|
|
18992
|
+
const fn = fns.get(ip);
|
|
18993
|
+
const bodyRange = range(fn.body);
|
|
18994
|
+
const start = bodyRange.start + 1;
|
|
18995
|
+
const end = bodyRange.end - 1;
|
|
18996
|
+
const edits = [];
|
|
18997
|
+
const callsByStatement = /* @__PURE__ */ new Map();
|
|
18998
|
+
for (const call of fn.calls) {
|
|
18999
|
+
if (owner.get(call.callee) !== owner.get(ip) || barrier.has(call.callee) || !call.transformable) continue;
|
|
19000
|
+
const list = callsByStatement.get(call.statement) ?? [];
|
|
19001
|
+
list.push(call);
|
|
19002
|
+
callsByStatement.set(call.statement, list);
|
|
19003
|
+
}
|
|
19004
|
+
const returns = [];
|
|
19005
|
+
const collectReturns = (node2) => {
|
|
19006
|
+
if (node2 !== fn.body && isFunction(node2)) return;
|
|
19007
|
+
if (node2.type === "ReturnStatement") returns.push(node2);
|
|
19008
|
+
for (const child of children2(node2)) collectReturns(child);
|
|
19009
|
+
};
|
|
19010
|
+
if (embedded !== void 0) collectReturns(fn.body);
|
|
19011
|
+
const callPrefix = (call) => {
|
|
19012
|
+
const id = serial++;
|
|
19013
|
+
const result = `_z${id}r`;
|
|
19014
|
+
const label2 = `_z${id}`;
|
|
19015
|
+
const at = `_z${id}p`;
|
|
19016
|
+
const nested = renderBody(call.callee, { result, label: label2 });
|
|
19017
|
+
return {
|
|
19018
|
+
value: result,
|
|
19019
|
+
prefix: `let ${result},${at}=${src(call.args[1])}
|
|
19020
|
+
${label2}:{let pos=${at}
|
|
19021
|
+
${nested}
|
|
19022
|
+
}
|
|
19023
|
+
`
|
|
19024
|
+
};
|
|
19025
|
+
};
|
|
19026
|
+
for (const [statement, calls] of callsByStatement) {
|
|
19027
|
+
let prefix = "";
|
|
19028
|
+
const replacements = [];
|
|
19029
|
+
for (const call of calls) {
|
|
19030
|
+
const made = callPrefix(call);
|
|
19031
|
+
prefix += made.prefix;
|
|
19032
|
+
const cr = range(call.node);
|
|
19033
|
+
replacements.push({ start: cr.start, end: cr.end, text: made.value });
|
|
19034
|
+
}
|
|
19035
|
+
if (statement.type === "ReturnStatement" && embedded !== void 0) {
|
|
19036
|
+
const sr = range(statement);
|
|
19037
|
+
const arg = ast(statement.argument);
|
|
19038
|
+
const value = arg === void 0 ? "undefined" : render2(source, range(arg).start, range(arg).end, replacements);
|
|
19039
|
+
edits.push({ start: sr.start, end: sr.end, text: `{${prefix}${embedded.result}=${value};break ${embedded.label}}` });
|
|
19040
|
+
} else {
|
|
19041
|
+
const sr = range(statement);
|
|
19042
|
+
edits.push({ start: sr.start, end: sr.start, text: prefix });
|
|
19043
|
+
edits.push(...replacements);
|
|
19044
|
+
}
|
|
19045
|
+
}
|
|
19046
|
+
if (embedded !== void 0) {
|
|
19047
|
+
for (const statement of returns) {
|
|
19048
|
+
if (callsByStatement.has(statement)) continue;
|
|
19049
|
+
const sr = range(statement);
|
|
19050
|
+
const arg = ast(statement.argument);
|
|
19051
|
+
edits.push({
|
|
19052
|
+
start: sr.start,
|
|
19053
|
+
end: sr.end,
|
|
19054
|
+
text: `{${embedded.result}=${arg === void 0 ? "undefined" : src(arg)};break ${embedded.label}}`
|
|
19055
|
+
});
|
|
19056
|
+
}
|
|
19057
|
+
}
|
|
19058
|
+
return render2(source, start, end, edits);
|
|
19059
|
+
};
|
|
19060
|
+
const regionSizes = /* @__PURE__ */ new Map();
|
|
19061
|
+
const regionProtocol = /* @__PURE__ */ new Map();
|
|
19062
|
+
for (const [ip, root] of owner) {
|
|
19063
|
+
const r = range(fns.get(ip).node);
|
|
19064
|
+
regionSizes.set(root, (regionSizes.get(root) ?? 0) + r.end - r.start);
|
|
19065
|
+
const op = prog.code[ip];
|
|
19066
|
+
const bits = (op === OP_NODE || op === OP_NODE_TRACK ? 1 : 0) | (op === OP_REPV ? 2 : 0);
|
|
19067
|
+
regionProtocol.set(root, (regionProtocol.get(root) ?? 0) | bits);
|
|
19068
|
+
}
|
|
19069
|
+
const oversized = /* @__PURE__ */ new Set();
|
|
19070
|
+
for (const [ip, size] of regionSizes) if (size > 18e4) oversized.add(ip);
|
|
19071
|
+
if (oversized.size > 0) {
|
|
19072
|
+
const counts2 = Object.fromEntries([...barrier.values()].map((k) => [k, 0]));
|
|
19073
|
+
for (const kind of barrier.values()) counts2[kind] = (counts2[kind] ?? 0) + 1;
|
|
19074
|
+
const before2 = { functionsBefore: fns.size, pieceCallsBefore, sourceBefore: source.length, barriers: counts2 };
|
|
19075
|
+
return fallback(emitted, "a region exceeded the 180KB source cap", before2);
|
|
19076
|
+
}
|
|
19077
|
+
const topEdits = [];
|
|
19078
|
+
for (const [ip, fn] of fns) {
|
|
19079
|
+
if (owner.get(ip) === ip) {
|
|
19080
|
+
const br = range(fn.body);
|
|
19081
|
+
topEdits.push({ start: br.start + 1, end: br.end - 1, text: renderBody(ip, void 0) });
|
|
19082
|
+
} else {
|
|
19083
|
+
const fr = range(fn.node);
|
|
19084
|
+
topEdits.push({ start: fr.start, end: fr.end, text: "" });
|
|
19085
|
+
}
|
|
19086
|
+
}
|
|
19087
|
+
const candidate = render2(source, 0, source.length, topEdits);
|
|
19088
|
+
const counts = {};
|
|
19089
|
+
for (const kind of barrier.values()) counts[kind] = (counts[kind] ?? 0) + 1;
|
|
19090
|
+
const before = { functionsBefore: fns.size, pieceCallsBefore, sourceBefore: source.length, barriers: counts };
|
|
19091
|
+
if (candidate.length > Math.ceil(source.length * 1.05)) {
|
|
19092
|
+
return fallback(emitted, `candidate exceeded the 5% total source cap (${candidate.length} > ${Math.ceil(source.length * 1.05)})`, before);
|
|
19093
|
+
}
|
|
19094
|
+
const functionsAfter = roots.length;
|
|
19095
|
+
const removed = fns.size - functionsAfter;
|
|
19096
|
+
const checked = parseSync4("parseman-entry-supercompile-result.js", WRAP + candidate + SUFFIX);
|
|
19097
|
+
if (checked.errors.length > 0) return fallback(emitted, "structured candidate did not parse", before);
|
|
19098
|
+
const declared = /* @__PURE__ */ new Set();
|
|
19099
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
19100
|
+
const checkRefs = (node2, parent) => {
|
|
19101
|
+
if (node2.type === "FunctionDeclaration") {
|
|
19102
|
+
const name = nameOf(ast(node2.id));
|
|
19103
|
+
if (name !== void 0 && PIECE.test(name)) declared.add(name);
|
|
19104
|
+
}
|
|
19105
|
+
if (node2.type === "Identifier" && typeof node2.name === "string" && PIECE.test(node2.name)) {
|
|
19106
|
+
const isDeclaration = parent?.type === "FunctionDeclaration" && parent.id === node2;
|
|
19107
|
+
if (!isDeclaration) referenced.add(node2.name);
|
|
19108
|
+
}
|
|
19109
|
+
for (const child of children2(node2)) checkRefs(child, node2);
|
|
19110
|
+
};
|
|
19111
|
+
checkRefs(checked.program);
|
|
19112
|
+
if (declared.size !== functionsAfter || [...referenced].some((name) => !declared.has(name))) {
|
|
19113
|
+
return fallback(emitted, "deleted piece body remains reachable after structured relinking", before);
|
|
19114
|
+
}
|
|
19115
|
+
const largestRegion = [...regionSizes].sort((a, b) => b[1] - a[1])[0];
|
|
19116
|
+
const protocolRegions = {
|
|
19117
|
+
node: [...regionProtocol.values()].filter((bits) => (bits & 1) !== 0).length,
|
|
19118
|
+
repv: [...regionProtocol.values()].filter((bits) => (bits & 2) !== 0).length,
|
|
19119
|
+
nodeAndRepv: [...regionProtocol.values()].filter((bits) => bits === 3).length
|
|
19120
|
+
};
|
|
19121
|
+
return {
|
|
19122
|
+
...emitted,
|
|
19123
|
+
source: candidate,
|
|
19124
|
+
supercompile: {
|
|
19125
|
+
...before,
|
|
19126
|
+
activated: removed > 0,
|
|
19127
|
+
...removed > 0 ? {} : { reason: "no uniquely-owned region bodies" },
|
|
19128
|
+
functionsAfter,
|
|
19129
|
+
pieceCallsAfter: pieceCallsBefore - removed,
|
|
19130
|
+
sourceAfter: candidate.length,
|
|
19131
|
+
regions: roots.length,
|
|
19132
|
+
largestRegionSource: Math.max(0, ...regionSizes.values()),
|
|
19133
|
+
...largestRegion === void 0 ? {} : { largestRegionIp: largestRegion[0] },
|
|
19134
|
+
protocolRegions
|
|
19135
|
+
}
|
|
19136
|
+
};
|
|
19137
|
+
}
|
|
19138
|
+
|
|
17570
19139
|
// src/plugin/index.ts
|
|
17571
19140
|
import { createHash } from "node:crypto";
|
|
17572
19141
|
var TABLE_RUNTIME_SPECIFIER = "parseman/table";
|
|
@@ -17669,7 +19238,7 @@ function parseModuleCached(filePath) {
|
|
|
17669
19238
|
let parsed = null;
|
|
17670
19239
|
try {
|
|
17671
19240
|
const src = fs2.readFileSync(filePath, "utf8");
|
|
17672
|
-
const r =
|
|
19241
|
+
const r = parseSync5(filePath, src);
|
|
17673
19242
|
if (r.errors.length === 0) parsed = { body: r.program.body, src };
|
|
17674
19243
|
} catch {
|
|
17675
19244
|
}
|
|
@@ -17818,7 +19387,7 @@ function lowerPrivateSourceModule(file, moduleAliases, warnUnloweredRegex, recov
|
|
|
17818
19387
|
const source = fs2.readFileSync(file, "utf8");
|
|
17819
19388
|
const transformed = transformMacro(source, file, moduleAliases, warnUnloweredRegex, recovery);
|
|
17820
19389
|
if (!transformed || transformed.warnings.length > 0) return null;
|
|
17821
|
-
const parsed =
|
|
19390
|
+
const parsed = parseSync5(file, transformed.code);
|
|
17822
19391
|
parsedModule = parsed.errors.length === 0 ? { body: parsed.program.body, src: transformed.code } : null;
|
|
17823
19392
|
return parsedModule;
|
|
17824
19393
|
} catch {
|
|
@@ -17841,7 +19410,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
17841
19410
|
function transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recovery, grammarCoverage) {
|
|
17842
19411
|
let result;
|
|
17843
19412
|
try {
|
|
17844
|
-
result =
|
|
19413
|
+
result = parseSync5(id, code);
|
|
17845
19414
|
} catch {
|
|
17846
19415
|
return null;
|
|
17847
19416
|
}
|
|
@@ -18462,9 +20031,12 @@ function transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recover
|
|
|
18462
20031
|
if (compiled !== null) {
|
|
18463
20032
|
usedTableRuntime = true;
|
|
18464
20033
|
return {
|
|
18465
|
-
replacement:
|
|
18466
|
-
|
|
18467
|
-
|
|
20034
|
+
replacement: supercompileRuleMapReplacement(
|
|
20035
|
+
compiled.prog,
|
|
20036
|
+
compiled.replacementWithMetadata(
|
|
20037
|
+
staticTableMetadataSource({ reflection: compiled.reflection, leaf: true }),
|
|
20038
|
+
{ precompileDefault: true }
|
|
20039
|
+
)
|
|
18468
20040
|
),
|
|
18469
20041
|
...importedFactories.length ? { importedFactories } : {}
|
|
18470
20042
|
};
|