parseman 0.55.4 → 0.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analysis/choice-cost.d.ts.map +1 -1
- package/dist/analysis/commitment.d.ts.map +1 -1
- package/dist/analysis/diagnostics.js +3745 -3180
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/analysis/duplication.d.ts.map +1 -1
- package/dist/analysis/gating.d.ts.map +1 -1
- package/dist/cli/index.js +2182 -1617
- package/dist/cli/index.js.map +3 -3
- package/dist/combinators/attempt.d.ts.map +1 -1
- package/dist/combinators/choice.d.ts.map +1 -1
- package/dist/combinators/dispatch.d.ts.map +1 -1
- package/dist/combinators/expect.d.ts.map +1 -1
- package/dist/combinators/first-set.d.ts.map +1 -1
- package/dist/combinators/lines.d.ts +79 -0
- package/dist/combinators/lines.d.ts.map +1 -0
- package/dist/combinators/node.d.ts +1 -1
- package/dist/combinators/trivia-skip.d.ts +1 -0
- package/dist/combinators/trivia-skip.d.ts.map +1 -1
- package/dist/compiler/build-arity.d.ts +1 -1
- package/dist/compiler/build-arity.d.ts.map +1 -1
- package/dist/compiler/fields.d.ts.map +1 -1
- package/dist/compiler/grammar-coverage-ids.d.ts.map +1 -1
- package/dist/compiler/ir-serialize.d.ts.map +1 -1
- package/dist/compiler/token-alphabet.d.ts.map +1 -1
- package/dist/compiler/token-capability.js +25 -0
- package/dist/compiler/token-capability.js.map +1 -1
- package/dist/coverage.d.ts.map +1 -1
- package/dist/cst/reflection.d.ts.map +1 -1
- package/dist/cst/trivia-kinds.d.ts +9 -1
- package/dist/cst/trivia-kinds.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2348 -1697
- package/dist/index.js.map +3 -3
- package/dist/language-service/index.js +3 -0
- package/dist/language-service/index.js.map +1 -1
- package/dist/parse-context.d.ts.map +1 -1
- package/dist/plugin/entry-supercompiler.d.ts +1 -1
- package/dist/plugin/entry-supercompiler.d.ts.map +1 -1
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.d.ts +27 -1
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +2360 -1314
- package/dist/plugin/index.js.map +3 -3
- package/dist/plugin/ir-eval.d.ts +2 -4
- package/dist/plugin/ir-eval.d.ts.map +1 -1
- package/dist/regex/classes.d.ts.map +1 -1
- package/dist/run/index.js +3 -0
- package/dist/run/index.js.map +1 -1
- package/dist/spec/index.js +15 -0
- package/dist/spec/index.js.map +1 -1
- package/dist/spec/model.d.ts.map +1 -1
- package/dist/table/assemble.d.ts +9 -65
- package/dist/table/assemble.d.ts.map +1 -1
- package/dist/table/child-slots.d.ts +4 -6
- package/dist/table/child-slots.d.ts.map +1 -1
- package/dist/table/compile-rule-map.d.ts +14 -2
- package/dist/table/compile-rule-map.d.ts.map +1 -1
- package/dist/table/emit-assembly.d.ts +17 -2
- package/dist/table/emit-assembly.d.ts.map +1 -1
- package/dist/table/emit.d.ts +5 -1
- package/dist/table/emit.d.ts.map +1 -1
- package/dist/table/encode.d.ts.map +1 -1
- package/dist/table/exec-baseline.d.ts.map +1 -1
- package/dist/table/exec.d.ts.map +1 -1
- package/dist/table/index.js +3884 -3262
- package/dist/table/index.js.map +3 -3
- package/dist/table/line-scan.d.ts +9 -0
- package/dist/table/line-scan.d.ts.map +1 -0
- package/dist/table/ops.d.ts +9 -6
- package/dist/table/ops.d.ts.map +1 -1
- package/dist/table/program.d.ts +24 -2
- package/dist/table/program.d.ts.map +1 -1
- package/dist/table/select-hot.d.ts +6 -0
- package/dist/table/select-hot.d.ts.map +1 -0
- package/dist/table/trivia-gap.d.ts +31 -0
- package/dist/table/trivia-gap.d.ts.map +1 -0
- package/dist/types.d.ts +38 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +4 -1
- package/src/analysis/choice-cost.ts +1 -0
- package/src/analysis/commitment.ts +13 -0
- package/src/analysis/duplication.ts +3 -0
- package/src/analysis/gating.ts +5 -0
- package/src/analysis/rebuild.ts +2 -2
- package/src/combinators/attempt.ts +2 -0
- package/src/combinators/choice.ts +3 -0
- package/src/combinators/dispatch.ts +3 -0
- package/src/combinators/expect.ts +5 -0
- package/src/combinators/first-set.ts +9 -1
- package/src/combinators/lines.ts +244 -0
- package/src/combinators/node.ts +6 -13
- package/src/combinators/trivia-skip.ts +48 -3
- package/src/compiler/build-arity.ts +3 -3
- package/src/compiler/fields.ts +3 -0
- package/src/compiler/grammar-coverage-ids.ts +1 -0
- package/src/compiler/ir-serialize.ts +10 -0
- package/src/compiler/token-alphabet.ts +3 -1
- package/src/coverage.ts +6 -0
- package/src/cst/reflection.ts +3 -0
- package/src/cst/trivia-kinds.ts +12 -1
- package/src/index.ts +2 -0
- package/src/parse-context.ts +3 -0
- package/src/plugin/entry-supercompiler.ts +8 -9
- package/src/plugin/evaluator.ts +4 -0
- package/src/plugin/index.ts +138 -13
- package/src/plugin/ir-eval.ts +10 -1
- package/src/regex/classes.ts +3 -0
- package/src/spec/model.ts +15 -0
- package/src/table/assemble.ts +125 -33
- package/src/table/child-slots.ts +4 -6
- package/src/table/compile-rule-map.ts +55 -15
- package/src/table/emit-assembly.ts +139 -26
- package/src/table/emit.ts +13 -11
- package/src/table/encode.ts +87 -27
- package/src/table/exec-baseline.ts +1 -3
- package/src/table/exec.ts +10 -6
- package/src/table/line-scan.ts +19 -0
- package/src/table/ops.ts +9 -6
- package/src/table/program.ts +41 -2
- package/src/table/select-hot.ts +70 -0
- package/src/table/trivia-gap.ts +109 -0
- package/src/types.ts +32 -0
- package/src/version.ts +1 -1
package/dist/plugin/index.js
CHANGED
|
@@ -163,6 +163,11 @@ function matchesEmptyBody(p, seen, resolve3) {
|
|
|
163
163
|
return true;
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
|
+
// A run consumes at least its first line's prefix, and its body after that.
|
|
167
|
+
case "lines":
|
|
168
|
+
return me(d.first ?? d.prefix) && me(d.body);
|
|
169
|
+
case "columns":
|
|
170
|
+
return d.n === 0;
|
|
166
171
|
default:
|
|
167
172
|
return true;
|
|
168
173
|
}
|
|
@@ -277,6 +282,11 @@ function firstSetBody(p, seen, resolve3, activeTrivia) {
|
|
|
277
282
|
resolve3,
|
|
278
283
|
d.clearTrivia ? null : d.triviaParser ?? activeTrivia
|
|
279
284
|
);
|
|
285
|
+
// A run starts with its first line's prefix; a nullable prefix starts with anything.
|
|
286
|
+
case "lines": {
|
|
287
|
+
const opening = d.first ?? d.prefix;
|
|
288
|
+
return empties(opening) ? any() : fs3(opening);
|
|
289
|
+
}
|
|
280
290
|
default:
|
|
281
291
|
return p._meta.firstSet;
|
|
282
292
|
}
|
|
@@ -356,12 +366,12 @@ function scalarRootOf(combinator) {
|
|
|
356
366
|
}
|
|
357
367
|
|
|
358
368
|
// src/combinators/ref.ts
|
|
359
|
-
function withRuleTrivia(trivia2, ctx,
|
|
369
|
+
function withRuleTrivia(trivia2, ctx, run2) {
|
|
360
370
|
const savedLabels = ctx.triviaKindLabels;
|
|
361
371
|
ctx.trivia = trivia2;
|
|
362
372
|
ctx.triviaKindLabels = trivia2._meta.triviaKindLabels;
|
|
363
373
|
try {
|
|
364
|
-
return
|
|
374
|
+
return run2();
|
|
365
375
|
} finally {
|
|
366
376
|
ctx.trivia = void 0;
|
|
367
377
|
ctx.triviaKindLabels = savedLabels;
|
|
@@ -786,6 +796,8 @@ function createParseContext() {
|
|
|
786
796
|
_triviaCaptureMask: void 0,
|
|
787
797
|
trackLines: false,
|
|
788
798
|
state: void 0,
|
|
799
|
+
lineView: void 0,
|
|
800
|
+
_columnsSplit: void 0,
|
|
789
801
|
build: void 0,
|
|
790
802
|
_errors: void 0,
|
|
791
803
|
_tolerant: void 0,
|
|
@@ -804,6 +816,7 @@ function createParseContext() {
|
|
|
804
816
|
_rootTriviaKindIndex: void 0,
|
|
805
817
|
_rootTriviaStrictScopes: void 0,
|
|
806
818
|
_rootTriviaCapture: void 0,
|
|
819
|
+
_gap: void 0,
|
|
807
820
|
_cstTriviaLog: void 0,
|
|
808
821
|
_fields: void 0,
|
|
809
822
|
_cstBuf: void 0,
|
|
@@ -857,6 +870,7 @@ function literalCodePoints(frag) {
|
|
|
857
870
|
if (ch2 === "\\") {
|
|
858
871
|
const e = frag[i + 1];
|
|
859
872
|
if (e === void 0) return null;
|
|
873
|
+
if (!(e in CLASS_ESCAPES) && /\w/.test(e)) return null;
|
|
860
874
|
out.push(e in CLASS_ESCAPES ? CLASS_ESCAPES[e] : e.codePointAt(0));
|
|
861
875
|
i += 2;
|
|
862
876
|
continue;
|
|
@@ -1403,7 +1417,10 @@ function labeledTriviaSpec(arms, minRepeats) {
|
|
|
1403
1417
|
arms,
|
|
1404
1418
|
minRepeats,
|
|
1405
1419
|
visitor: commonLabeledTriviaVisitor({ arms, minRepeats }),
|
|
1406
|
-
charArms: charArmsFor({ arms, minRepeats })
|
|
1420
|
+
charArms: charArmsFor({ arms, minRepeats }),
|
|
1421
|
+
rootKinds: void 0,
|
|
1422
|
+
rootLeaders: [],
|
|
1423
|
+
rootScan: null
|
|
1407
1424
|
};
|
|
1408
1425
|
}
|
|
1409
1426
|
function matchArmAt(input, pos, arm, state) {
|
|
@@ -1726,6 +1743,9 @@ function childrenOf(def) {
|
|
|
1726
1743
|
];
|
|
1727
1744
|
case "routed":
|
|
1728
1745
|
return def.fallback ? [def.fallback] : [];
|
|
1746
|
+
case "lines":
|
|
1747
|
+
return [def.prefix, def.body, ...def.first === void 0 ? [] : [def.first], ...def.lazy === void 0 ? [] : [def.lazy]];
|
|
1748
|
+
case "columns":
|
|
1729
1749
|
case "literal":
|
|
1730
1750
|
case "regex":
|
|
1731
1751
|
case "keywords":
|
|
@@ -2577,11 +2597,12 @@ function parseTriviaNoCapture(triviaP, input, cur, ctx) {
|
|
|
2577
2597
|
return result;
|
|
2578
2598
|
}
|
|
2579
2599
|
function saveLookaheadMark(ctx) {
|
|
2580
|
-
return { ...saveTriviaMark(ctx), probeBest: ctx._probe ? ctx._probe.best : null };
|
|
2600
|
+
return { ...saveTriviaMark(ctx), probeBest: ctx._probe ? ctx._probe.best : null, split: ctx._columnsSplit };
|
|
2581
2601
|
}
|
|
2582
2602
|
function rollbackLookahead(ctx, mark) {
|
|
2583
2603
|
rollbackTrivia(ctx, mark);
|
|
2584
2604
|
if (ctx._probe) ctx._probe.best = mark.probeBest;
|
|
2605
|
+
ctx._columnsSplit = mark.split;
|
|
2585
2606
|
}
|
|
2586
2607
|
function scanWithLabels(input, cur, ctx) {
|
|
2587
2608
|
const triviaP = ctx.trivia;
|
|
@@ -2815,8 +2836,50 @@ function loopScanner(arms) {
|
|
|
2815
2836
|
function regexTriviaScanner(parser2) {
|
|
2816
2837
|
const d = parser2._def.tag === "label" ? parser2._def.parser._def : parser2._def;
|
|
2817
2838
|
if (d.tag !== "regex" || d.flags) return null;
|
|
2818
|
-
|
|
2819
|
-
|
|
2839
|
+
return sourceScanner(d.source);
|
|
2840
|
+
}
|
|
2841
|
+
function sourceScanner(source) {
|
|
2842
|
+
return classRunSource(source) ?? altStarSource(source) ?? prefixRunSource(source) ?? delimitedSource(source) ?? sharedPrefixAltSource(source);
|
|
2843
|
+
}
|
|
2844
|
+
function sharedPrefixAltSource(source) {
|
|
2845
|
+
const m = /^((?:\\.|[^\\[\]()*+?|^$.{}])+)\(\?:(.*)\)$/.exec(source);
|
|
2846
|
+
if (!m) return null;
|
|
2847
|
+
const alts = [];
|
|
2848
|
+
const body = m[2];
|
|
2849
|
+
let depth = 0;
|
|
2850
|
+
let start = 0;
|
|
2851
|
+
for (let i = 0; i < body.length; i++) {
|
|
2852
|
+
const c = body[i];
|
|
2853
|
+
if (c === "\\") {
|
|
2854
|
+
i++;
|
|
2855
|
+
continue;
|
|
2856
|
+
}
|
|
2857
|
+
if (c === "[") {
|
|
2858
|
+
while (i < body.length && body[i] !== "]") i += body[i] === "\\" ? 2 : 1;
|
|
2859
|
+
continue;
|
|
2860
|
+
}
|
|
2861
|
+
if (c === "(") depth++;
|
|
2862
|
+
else if (c === ")" && --depth < 0) return null;
|
|
2863
|
+
else if (c === "|" && depth === 0) {
|
|
2864
|
+
alts.push(body.slice(start, i));
|
|
2865
|
+
start = i + 1;
|
|
2866
|
+
}
|
|
2867
|
+
}
|
|
2868
|
+
if (depth !== 0 || alts.length === 0) return null;
|
|
2869
|
+
alts.push(body.slice(start));
|
|
2870
|
+
const scanners = [];
|
|
2871
|
+
for (const alt of alts) {
|
|
2872
|
+
const scanner = sourceScanner(m[1] + alt);
|
|
2873
|
+
if (scanner === null) return null;
|
|
2874
|
+
scanners.push(scanner);
|
|
2875
|
+
}
|
|
2876
|
+
return (input, cur) => {
|
|
2877
|
+
for (const scanner of scanners) {
|
|
2878
|
+
const end = scanner(input, cur);
|
|
2879
|
+
if (end > cur) return end;
|
|
2880
|
+
}
|
|
2881
|
+
return cur;
|
|
2882
|
+
};
|
|
2820
2883
|
}
|
|
2821
2884
|
function bmpString(cps) {
|
|
2822
2885
|
if (!cps) return null;
|
|
@@ -3169,6 +3232,7 @@ function matchesAt(sentinel, input, pos, ctx) {
|
|
|
3169
3232
|
function captureError(ctx, error) {
|
|
3170
3233
|
if (cstCaptureActive(ctx)) pushCstChild(ctx, error, error);
|
|
3171
3234
|
}
|
|
3235
|
+
var REC = { scan: recoverScan, at: matchesAt, or: orSentinel, sentinel: firstSetSentinel, capture: captureError };
|
|
3172
3236
|
|
|
3173
3237
|
// src/combinators/adjacency.ts
|
|
3174
3238
|
function adjacencyOf(p) {
|
|
@@ -3427,6 +3491,12 @@ function derive(c, seen) {
|
|
|
3427
3491
|
return deriveExpected2(def.parser);
|
|
3428
3492
|
case "expect":
|
|
3429
3493
|
return def.expected;
|
|
3494
|
+
case "lines": {
|
|
3495
|
+
const opening = def.first ?? def.prefix;
|
|
3496
|
+
return matchesEmpty(opening) ? [...deriveExpected2(opening), ...deriveExpected2(def.body)] : deriveExpected2(opening);
|
|
3497
|
+
}
|
|
3498
|
+
case "columns":
|
|
3499
|
+
return [`columns(${def.n})`];
|
|
3430
3500
|
case "node":
|
|
3431
3501
|
case "grammar":
|
|
3432
3502
|
case "trivia":
|
|
@@ -3611,9 +3681,11 @@ function choice(...args) {
|
|
|
3611
3681
|
for (let i = 0; i < parsers.length; i++) {
|
|
3612
3682
|
if (gates[i] && !gates[i](ctx.state)) continue;
|
|
3613
3683
|
const mark = saveTriviaMark(ctx);
|
|
3684
|
+
const split = ctx._columnsSplit;
|
|
3614
3685
|
const result = parsers[i].parse(input, pos, ctx);
|
|
3615
3686
|
if (!result.ok) {
|
|
3616
3687
|
rollbackTrivia(ctx, mark);
|
|
3688
|
+
ctx._columnsSplit = split;
|
|
3617
3689
|
const at = result.span.start;
|
|
3618
3690
|
if (at > expectedAt) {
|
|
3619
3691
|
expectedAt = at;
|
|
@@ -3834,6 +3906,9 @@ function parserUsesRouted(parser2, seen = /* @__PURE__ */ new Set()) {
|
|
|
3834
3906
|
return parserUsesRouted(def.sentinel, seen) || def.skip.some((entry) => parserUsesRouted(entry, seen)) || def.recoverAt !== void 0 && parserUsesRouted(def.recoverAt, seen) || def.stopAt !== void 0 && parserUsesRouted(def.stopAt, seen);
|
|
3835
3907
|
case "recover":
|
|
3836
3908
|
return parserUsesRouted(def.parser, seen) || parserUsesRouted(def.sentinel, seen);
|
|
3909
|
+
// The body parses its own input, so only the checks on this one can reuse a routed head.
|
|
3910
|
+
case "lines":
|
|
3911
|
+
return [def.prefix, def.first, def.lazy].some((entry) => entry !== void 0 && parserUsesRouted(entry, seen));
|
|
3837
3912
|
case "lazy":
|
|
3838
3913
|
try {
|
|
3839
3914
|
return parserUsesRouted(def.thunk(), seen);
|
|
@@ -4084,9 +4159,11 @@ function attempt(parser2, options) {
|
|
|
4084
4159
|
const mark = saveCstMark(ctx);
|
|
4085
4160
|
const log = ctx._triviaLog?.length;
|
|
4086
4161
|
const rootLog = ctx._rootTriviaLog?.length;
|
|
4162
|
+
const split = ctx._columnsSplit;
|
|
4087
4163
|
const result = parser2.parse(input, pos, ctx);
|
|
4088
4164
|
if (result.ok) return result;
|
|
4089
4165
|
rollbackCstCapture(ctx, mark);
|
|
4166
|
+
ctx._columnsSplit = split;
|
|
4090
4167
|
if (log !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== log) ctx._triviaLog.length = log;
|
|
4091
4168
|
if (rootLog !== void 0 && ctx._rootTriviaLog && ctx._rootTriviaLog.length !== rootLog) ctx._rootTriviaLog.length = rootLog;
|
|
4092
4169
|
if (result.committed && !contain) return result;
|
|
@@ -4601,12 +4678,12 @@ function beginCompileDegradationDrain() {
|
|
|
4601
4678
|
return true;
|
|
4602
4679
|
});
|
|
4603
4680
|
if (fresh.length === 0) return;
|
|
4604
|
-
const
|
|
4681
|
+
const lines2 = formatDegradations(fresh);
|
|
4605
4682
|
if (resolveDegradationLevel() === "error") {
|
|
4606
4683
|
throw new Error(`parseman: ${fresh.length} degraded compilation path(s)
|
|
4607
|
-
${
|
|
4684
|
+
${lines2.join("\n")}`);
|
|
4608
4685
|
}
|
|
4609
|
-
for (const l of
|
|
4686
|
+
for (const l of lines2) console.warn(l);
|
|
4610
4687
|
};
|
|
4611
4688
|
}
|
|
4612
4689
|
|
|
@@ -4792,7 +4869,7 @@ function confirmedArityForDef(def) {
|
|
|
4792
4869
|
severity: "warn",
|
|
4793
4870
|
where: `node("${def.type ?? "<inferred>"}")`,
|
|
4794
4871
|
subject,
|
|
4795
|
-
fellBackTo: `could not confirm its declared arity \u2014 ${unconfirmableReason(def, src)} \u2014 so this node captures children, fields and raw children, logs trivia, and
|
|
4872
|
+
fellBackTo: `could not confirm its declared arity \u2014 ${unconfirmableReason(def, src)} \u2014 so this node captures children, fields and raw children, logs trivia, and hands it \`_ctx.state\` on every match`,
|
|
4796
4873
|
otherwise: "only the tiers the reducer actually declares would be captured (arity >= 1 children, >= 2 fields, >= 4 raw, >= 5 trivia, >= 6 state). Declare it with `node(..., { buildArity: n })` if it cannot be derived"
|
|
4797
4874
|
});
|
|
4798
4875
|
return null;
|
|
@@ -4853,6 +4930,8 @@ function parserHasOwnFields(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
4853
4930
|
return parserHasOwnFields(d.sentinel, seen) || d.skip.some((x) => parserHasOwnFields(x, seen)) || d.recoverAt !== void 0 && parserHasOwnFields(d.recoverAt, seen) || d.stopAt !== void 0 && parserHasOwnFields(d.stopAt, seen);
|
|
4854
4931
|
case "recover":
|
|
4855
4932
|
return parserHasOwnFields(d.parser, seen) || parserHasOwnFields(d.sentinel, seen);
|
|
4933
|
+
case "lines":
|
|
4934
|
+
return parserHasOwnFields(d.body, seen);
|
|
4856
4935
|
case "routed":
|
|
4857
4936
|
return d.fallback ? parserHasOwnFields(d.fallback, seen) : false;
|
|
4858
4937
|
case "many":
|
|
@@ -4947,7 +5026,7 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
4947
5026
|
}
|
|
4948
5027
|
const def = unwrap || collapse || project !== void 0 || captureTrivia || trailingTrivia || buildArity !== void 0 || tags !== void 0 && tags.length > 0 ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {}, ...project !== void 0 ? { project } : {}, ...captureTrivia ? { captureTrivia: true } : {}, ...trailingTrivia ? { trailingTrivia: true } : {}, ...buildArity !== void 0 ? { buildArity } : {}, ...tags !== void 0 && tags.length > 0 ? { tags } : {} } : baseDef;
|
|
4949
5028
|
const capturesTrivia = captureTrivia || (build ? buildReadsTrivia(def) : project === void 0);
|
|
4950
|
-
const
|
|
5029
|
+
const readsState = build ? buildReadsState(def) : project === void 0;
|
|
4951
5030
|
const hasOwnFields = parserHasOwnFields(combinator);
|
|
4952
5031
|
const capturesFields = hasOwnFields && (build ? buildReadsFields(def) : project === void 0);
|
|
4953
5032
|
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
@@ -4988,12 +5067,11 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
4988
5067
|
ctx._triviaCaptureMask = savedMask;
|
|
4989
5068
|
const { children: children3, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
|
|
4990
5069
|
if (!r.ok) return r;
|
|
4991
|
-
const st =
|
|
5070
|
+
const st = readsState ? ctx.state : void 0;
|
|
4992
5071
|
const nodeType = def.type ?? missingInferredType();
|
|
4993
5072
|
const cstOutput = cstOutputHost(ctx.build);
|
|
4994
5073
|
const span = ctx.trackLines ? annotateSpanFromLineContext(r.span, ctx) : r.span;
|
|
4995
|
-
const
|
|
4996
|
-
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 };
|
|
5074
|
+
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, ctx.state, tags) : projectChild(children3, project, nodeType) : build ? cstOutput && ctx.build ? ctx.build(nodeType, children3, fields, span, rawChildren, triviaLog, ctx.state, 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 };
|
|
4997
5075
|
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 };
|
|
4998
5076
|
if (saved.buf !== void 0 || saved.ch !== void 0) {
|
|
4999
5077
|
pushCstChild(ctx, built, rawEntry2);
|
|
@@ -5266,1100 +5344,521 @@ function sourceLeaf(root, fn) {
|
|
|
5266
5344
|
return makeLeaf(root, fn, true);
|
|
5267
5345
|
}
|
|
5268
5346
|
|
|
5269
|
-
// src/
|
|
5270
|
-
function
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
return d.parsers;
|
|
5275
|
-
case "dispatch":
|
|
5276
|
-
return [
|
|
5277
|
-
d.selector,
|
|
5278
|
-
...d.cases.map((c) => c.parser),
|
|
5279
|
-
...d.matchers ? d.matchers.map((c) => c.parser) : [],
|
|
5280
|
-
...d.otherwise === void 0 ? [] : [d.otherwise]
|
|
5281
|
-
];
|
|
5282
|
-
case "sepBy":
|
|
5283
|
-
return [d.parser, d.separator];
|
|
5284
|
-
case "recover":
|
|
5285
|
-
return [d.parser, d.sentinel];
|
|
5286
|
-
case "scanTo":
|
|
5287
|
-
return [
|
|
5288
|
-
d.sentinel,
|
|
5289
|
-
...d.skip,
|
|
5290
|
-
...d.recoverAt === void 0 ? [] : [d.recoverAt],
|
|
5291
|
-
...d.stopAt === void 0 ? [] : [d.stopAt]
|
|
5292
|
-
];
|
|
5293
|
-
case "grammar":
|
|
5294
|
-
return d.triviaParser ? [d.parser, d.triviaParser] : [d.parser];
|
|
5295
|
-
case "routed":
|
|
5296
|
-
return d.fallback ? [d.fallback] : [];
|
|
5297
|
-
// A `lazy` is a REFERENCE, not a subtree. Descending through it would make
|
|
5298
|
-
// every rule's walk cover the whole reachable grammar — site paths become
|
|
5299
|
-
// nonsense, and a structural hash includes half the grammar. Treated as a
|
|
5300
|
-
// leaf, keyed by the rule name it refers to, which is also the right
|
|
5301
|
-
// semantics: two productions referencing `g.Ident` really do fill that slot
|
|
5302
|
-
// the same way.
|
|
5303
|
-
case "lazy":
|
|
5304
|
-
case "literal":
|
|
5305
|
-
case "regex":
|
|
5306
|
-
case "keywords":
|
|
5307
|
-
case "guard":
|
|
5308
|
-
case "adjacency":
|
|
5309
|
-
case "unknown":
|
|
5310
|
-
return [];
|
|
5311
|
-
default: {
|
|
5312
|
-
const rec = d;
|
|
5313
|
-
return rec.parser ? [rec.parser] : [];
|
|
5314
|
-
}
|
|
5347
|
+
// src/table/lex-body.ts
|
|
5348
|
+
function buildLexBodyRecognizer(spec, constants) {
|
|
5349
|
+
const raw = constants[spec[0]];
|
|
5350
|
+
if (!(raw instanceof RegExp)) {
|
|
5351
|
+
throw new TypeError("table lexical body does not reference a RegExp constant");
|
|
5315
5352
|
}
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
return
|
|
5353
|
+
if (!Number.isInteger(spec[1]) || spec[1] < -1 || spec[1] > 65535) {
|
|
5354
|
+
throw new TypeError("table lexical body suffix is not absent or one UTF-16 code unit");
|
|
5355
|
+
}
|
|
5356
|
+
const re = raw.sticky ? new RegExp(raw.source, raw.flags) : new RegExp(raw.source, `${raw.flags.replace(/[gy]/g, "")}y`);
|
|
5357
|
+
const suffix = spec[1];
|
|
5358
|
+
return (input, pos) => {
|
|
5359
|
+
re.lastIndex = pos;
|
|
5360
|
+
if (!re.test(input)) return -1;
|
|
5361
|
+
const end = re.lastIndex;
|
|
5362
|
+
if (suffix < 0) return end * 2;
|
|
5363
|
+
return input.charCodeAt(end) === suffix ? (end + 1) * 2 + 1 : end * 2;
|
|
5364
|
+
};
|
|
5322
5365
|
}
|
|
5323
5366
|
|
|
5324
|
-
// src/
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
+
// src/table/lex-program.ts
|
|
5368
|
+
var LEX_NODE_TERMINAL = 0;
|
|
5369
|
+
var LEX_NODE_SEQUENCE2 = 1;
|
|
5370
|
+
var LEX_NODE_SEQUENCE3 = 2;
|
|
5371
|
+
var LEX_NODE_SEQUENCE4 = 3;
|
|
5372
|
+
var LEX_NODE_SEQUENCE5 = 4;
|
|
5373
|
+
var LEX_NODE_CHOICE2 = 5;
|
|
5374
|
+
var LEX_NODE_CHOICE4 = 6;
|
|
5375
|
+
var LEX_NODE_CHOICE8 = 7;
|
|
5376
|
+
var LEX_NODE_NOT = 8;
|
|
5377
|
+
var LEX_NODE_OPTIONAL = 9;
|
|
5378
|
+
function lexProgramDigest(words) {
|
|
5379
|
+
let hash = 2166136261;
|
|
5380
|
+
for (const word2 of words) {
|
|
5381
|
+
hash ^= word2 | 0;
|
|
5382
|
+
hash = Math.imul(hash, 16777619);
|
|
5383
|
+
}
|
|
5384
|
+
return hash | 0;
|
|
5385
|
+
}
|
|
5386
|
+
function classHas(cls, code) {
|
|
5387
|
+
if (code < 0) return false;
|
|
5388
|
+
if (code < 128) return cls.ascii[code] === 1;
|
|
5389
|
+
for (let i = 0; i < cls.hi.length; i += 2) {
|
|
5390
|
+
if (code >= cls.hi[i] && code <= cls.hi[i + 1]) return true;
|
|
5391
|
+
}
|
|
5392
|
+
return false;
|
|
5393
|
+
}
|
|
5394
|
+
var committed = (ctx) => ctx._fc === true;
|
|
5395
|
+
function trackLexLines(ctx, input, end) {
|
|
5396
|
+
let at = ctx._lineScannedTo ?? 0;
|
|
5397
|
+
const starts = ctx._lineStarts;
|
|
5398
|
+
if (starts === void 0 || end <= at) return;
|
|
5399
|
+
while (at < end) {
|
|
5400
|
+
if (input.charCodeAt(at) === 10) starts.push(at + 1);
|
|
5401
|
+
at++;
|
|
5402
|
+
}
|
|
5403
|
+
ctx._lineScannedTo = end;
|
|
5404
|
+
}
|
|
5405
|
+
function terminalNode(matcher, failure, tracksLines) {
|
|
5406
|
+
const match = (input, pos) => {
|
|
5407
|
+
const result = matcher(input, pos);
|
|
5408
|
+
return result < 0 ? -1 : result / 2;
|
|
5409
|
+
};
|
|
5410
|
+
return {
|
|
5411
|
+
match,
|
|
5412
|
+
run: (input, pos, ctx) => {
|
|
5413
|
+
const end = match(input, pos);
|
|
5414
|
+
if (end < 0) {
|
|
5415
|
+
ctx._fe = pos;
|
|
5416
|
+
ctx._fx = failure;
|
|
5417
|
+
if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
|
|
5418
|
+
return -1;
|
|
5367
5419
|
}
|
|
5420
|
+
if (tracksLines) trackLexLines(ctx, input, end);
|
|
5421
|
+
return end;
|
|
5368
5422
|
}
|
|
5369
|
-
|
|
5370
|
-
case "adjacency":
|
|
5371
|
-
return true;
|
|
5372
|
-
default:
|
|
5373
|
-
return true;
|
|
5374
|
-
}
|
|
5423
|
+
};
|
|
5375
5424
|
}
|
|
5376
|
-
function
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
case "adjacency":
|
|
5388
|
-
case "not":
|
|
5389
|
-
// peek(): emitted under a non-capturing probe ctx and zero-width on both
|
|
5390
|
-
// outcomes, so it can never leave a partial capture behind.
|
|
5391
|
-
case "peek":
|
|
5392
|
-
case "trivia":
|
|
5393
|
-
case "token":
|
|
5394
|
-
case "leaf":
|
|
5395
|
-
case "scanTo":
|
|
5396
|
-
case "unknown":
|
|
5397
|
-
return false;
|
|
5398
|
-
// node() captures into its own private buffers and rolls them back on
|
|
5399
|
-
// failure (emitNode restores _ctx.* and never pushes on the !ok path).
|
|
5400
|
-
case "node":
|
|
5401
|
-
return false;
|
|
5402
|
-
// choice/firstMatch already roll back each failed arm; on overall failure
|
|
5403
|
-
// nothing committed remains.
|
|
5404
|
-
case "choice":
|
|
5405
|
-
return false;
|
|
5406
|
-
case "dispatch":
|
|
5407
|
-
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);
|
|
5408
|
-
case "attempt":
|
|
5409
|
-
return false;
|
|
5410
|
-
// optional never fails; many/oneOrMore only "fail" with zero captured items.
|
|
5411
|
-
case "optional":
|
|
5412
|
-
case "many":
|
|
5413
|
-
case "oneOrMore":
|
|
5414
|
-
return false;
|
|
5415
|
-
// sepBy emits its own per-iteration rollback in emitSepBy.
|
|
5416
|
-
case "sepBy":
|
|
5417
|
-
return false;
|
|
5418
|
-
// A sequence is the real case: an earlier capturing term followed by a term
|
|
5419
|
-
// that can fail leaves the earlier captures buffered.
|
|
5420
|
-
//
|
|
5421
|
-
// BOTH halves of that sentence are load-bearing, and the second half is what
|
|
5422
|
-
// this walk exists to exploit. "Some earlier term captures" alone was the old
|
|
5423
|
-
// test, and it is true of very nearly every sequence in a real grammar — a
|
|
5424
|
-
// sequence almost always opens with a literal or a node. The rollback is only
|
|
5425
|
-
// reachable if something AFTER the capture can still fail; once the remainder
|
|
5426
|
-
// is total (`optional`/`many`/trivia/a min-0 `sepBy`), the sequence has no
|
|
5427
|
-
// failure path left to roll back from, and the save+restore is dead code.
|
|
5428
|
-
//
|
|
5429
|
-
// `captured` tracks whether anything is in the buffers yet as the scan moves
|
|
5430
|
-
// left to right. Two things put it there:
|
|
5431
|
-
// - a term that captures (`capturesLeaf`/`hasNodeDef`), and
|
|
5432
|
-
// - the inter-term TRIVIA scan, which under `capturing` pushes into
|
|
5433
|
-
// `_cstRawChildren`/`_cstTriviaLog` BEFORE the term at each boundary
|
|
5434
|
-
// i >= 1. `emitSeqValues` only rewinds that push on the term's SUCCESS
|
|
5435
|
-
// path (the "matched empty, so leave the whitespace out of the span"
|
|
5436
|
-
// branch); a term that FAILS breaks straight out with the trivia still
|
|
5437
|
-
// buffered, so from boundary 1 onward the buffers are dirty regardless of
|
|
5438
|
-
// what the earlier terms did.
|
|
5439
|
-
// Each term is also asked about itself: a nested sequence can leave its own
|
|
5440
|
-
// partial capture behind, and its terms are emitted inline into this same
|
|
5441
|
-
// block with no boundary of their own to roll them back.
|
|
5442
|
-
case "sequence": {
|
|
5443
|
-
const parts = d.parsers;
|
|
5444
|
-
let captured = false;
|
|
5445
|
-
for (let i = 0; i < parts.length; i++) {
|
|
5446
|
-
const part = parts[i];
|
|
5447
|
-
if (i > 0 && triviaActive) captured = true;
|
|
5448
|
-
if (captured && mayFail(part)) return true;
|
|
5449
|
-
if (mayLeavePartialCapture(part, seen, triviaActive)) return true;
|
|
5450
|
-
if (capturesLeaf(part) || hasNodeDef(part)) captured = true;
|
|
5451
|
-
}
|
|
5452
|
-
return false;
|
|
5453
|
-
}
|
|
5454
|
-
// Delegating wrappers: defer to the wrapped parser.
|
|
5455
|
-
case "transform":
|
|
5456
|
-
case "label":
|
|
5457
|
-
case "field":
|
|
5458
|
-
case "expect":
|
|
5459
|
-
case "withCtx":
|
|
5460
|
-
case "grammar":
|
|
5461
|
-
return mayLeavePartialCapture(d.parser, seen, triviaActive);
|
|
5462
|
-
case "recover":
|
|
5463
|
-
return mayLeavePartialCapture(d.parser, seen, triviaActive);
|
|
5464
|
-
case "lazy": {
|
|
5465
|
-
try {
|
|
5466
|
-
return mayLeavePartialCapture(d.thunk(), seen, triviaActive);
|
|
5467
|
-
} catch {
|
|
5468
|
-
return true;
|
|
5469
|
-
}
|
|
5425
|
+
function sequence2(a, b) {
|
|
5426
|
+
return {
|
|
5427
|
+
match: (input, pos) => {
|
|
5428
|
+
const e0 = a.match(input, pos);
|
|
5429
|
+
return e0 < 0 ? -1 : b.match(input, e0);
|
|
5430
|
+
},
|
|
5431
|
+
run: (input, pos, ctx) => {
|
|
5432
|
+
const e0 = a.run(input, pos, ctx);
|
|
5433
|
+
if (e0 < 0) return -1;
|
|
5434
|
+
ctx._fc = false;
|
|
5435
|
+
return b.run(input, e0, ctx);
|
|
5470
5436
|
}
|
|
5471
|
-
|
|
5472
|
-
default:
|
|
5473
|
-
return true;
|
|
5474
|
-
}
|
|
5437
|
+
};
|
|
5475
5438
|
}
|
|
5476
|
-
function
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
case "adjacency":
|
|
5493
|
-
case "trivia":
|
|
5494
|
-
case "unknown":
|
|
5495
|
-
return false;
|
|
5496
|
-
case "sequence":
|
|
5497
|
-
case "choice":
|
|
5498
|
-
return d.parsers.some((x) => capturesLeaf(x, seen));
|
|
5499
|
-
case "dispatch":
|
|
5500
|
-
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);
|
|
5501
|
-
case "sepBy":
|
|
5502
|
-
return capturesLeaf(d.parser, seen) || capturesLeaf(d.separator, seen);
|
|
5503
|
-
case "many":
|
|
5504
|
-
case "oneOrMore":
|
|
5505
|
-
case "optional":
|
|
5506
|
-
case "attempt":
|
|
5507
|
-
case "transform":
|
|
5508
|
-
case "label":
|
|
5509
|
-
case "field":
|
|
5510
|
-
case "expect":
|
|
5511
|
-
case "withCtx":
|
|
5512
|
-
case "grammar":
|
|
5513
|
-
case "recover":
|
|
5514
|
-
return capturesLeaf(d.parser, seen);
|
|
5515
|
-
case "scanTo":
|
|
5516
|
-
return true;
|
|
5517
|
-
case "lazy": {
|
|
5518
|
-
try {
|
|
5519
|
-
return capturesLeaf(d.thunk(), seen);
|
|
5520
|
-
} catch {
|
|
5521
|
-
return true;
|
|
5522
|
-
}
|
|
5439
|
+
function sequence3(a, b, c) {
|
|
5440
|
+
return {
|
|
5441
|
+
match: (input, pos) => {
|
|
5442
|
+
const e0 = a.match(input, pos);
|
|
5443
|
+
if (e0 < 0) return -1;
|
|
5444
|
+
const e1 = b.match(input, e0);
|
|
5445
|
+
return e1 < 0 ? -1 : c.match(input, e1);
|
|
5446
|
+
},
|
|
5447
|
+
run: (input, pos, ctx) => {
|
|
5448
|
+
const e0 = a.run(input, pos, ctx);
|
|
5449
|
+
if (e0 < 0) return -1;
|
|
5450
|
+
ctx._fc = false;
|
|
5451
|
+
const e1 = b.run(input, e0, ctx);
|
|
5452
|
+
if (e1 < 0) return -1;
|
|
5453
|
+
ctx._fc = false;
|
|
5454
|
+
return c.run(input, e1, ctx);
|
|
5523
5455
|
}
|
|
5524
|
-
|
|
5525
|
-
return true;
|
|
5526
|
-
}
|
|
5456
|
+
};
|
|
5527
5457
|
}
|
|
5528
|
-
function
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
|
|
5535
|
-
|
|
5536
|
-
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
}
|
|
5458
|
+
function sequence4(a, b, c, d) {
|
|
5459
|
+
const abc = sequence3(a, b, c);
|
|
5460
|
+
return {
|
|
5461
|
+
match: (input, pos) => {
|
|
5462
|
+
const end = abc.match(input, pos);
|
|
5463
|
+
return end < 0 ? -1 : d.match(input, end);
|
|
5464
|
+
},
|
|
5465
|
+
run: (input, pos, ctx) => {
|
|
5466
|
+
const end = abc.run(input, pos, ctx);
|
|
5467
|
+
if (end < 0) return -1;
|
|
5468
|
+
ctx._fc = false;
|
|
5469
|
+
return d.run(input, end, ctx);
|
|
5541
5470
|
}
|
|
5542
|
-
|
|
5543
|
-
case "trivia":
|
|
5544
|
-
case "token":
|
|
5545
|
-
case "leaf":
|
|
5546
|
-
case "label":
|
|
5547
|
-
case "field":
|
|
5548
|
-
case "optional":
|
|
5549
|
-
case "many":
|
|
5550
|
-
case "oneOrMore":
|
|
5551
|
-
case "not":
|
|
5552
|
-
case "peek":
|
|
5553
|
-
case "transform":
|
|
5554
|
-
return hasNodeDef(d.parser, seen);
|
|
5555
|
-
case "sequence":
|
|
5556
|
-
case "choice":
|
|
5557
|
-
return d.parsers.some((x) => hasNodeDef(x, seen));
|
|
5558
|
-
case "dispatch":
|
|
5559
|
-
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);
|
|
5560
|
-
case "sepBy":
|
|
5561
|
-
return hasNodeDef(d.parser, seen) || hasNodeDef(d.separator, seen);
|
|
5562
|
-
case "scanTo":
|
|
5563
|
-
return hasNodeDef(d.sentinel, seen) || d.skip.some((x) => hasNodeDef(x, seen)) || d.recoverAt !== void 0 && hasNodeDef(d.recoverAt, seen) || d.stopAt !== void 0 && hasNodeDef(d.stopAt, seen);
|
|
5564
|
-
case "recover":
|
|
5565
|
-
return hasNodeDef(d.parser, seen) || hasNodeDef(d.sentinel, seen);
|
|
5566
|
-
case "expect":
|
|
5567
|
-
return hasNodeDef(d.parser, seen);
|
|
5568
|
-
case "withCtx":
|
|
5569
|
-
return hasNodeDef(d.parser, seen);
|
|
5570
|
-
default:
|
|
5571
|
-
return false;
|
|
5572
|
-
}
|
|
5471
|
+
};
|
|
5573
5472
|
}
|
|
5574
|
-
function
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
|
|
5578
|
-
|
|
5579
|
-
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
}
|
|
5473
|
+
function sequence5(a, b, c, d, e) {
|
|
5474
|
+
const abcd = sequence4(a, b, c, d);
|
|
5475
|
+
return {
|
|
5476
|
+
match: (input, pos) => {
|
|
5477
|
+
const end = abcd.match(input, pos);
|
|
5478
|
+
return end < 0 ? -1 : e.match(input, end);
|
|
5479
|
+
},
|
|
5480
|
+
run: (input, pos, ctx) => {
|
|
5481
|
+
const end = abcd.run(input, pos, ctx);
|
|
5482
|
+
if (end < 0) return -1;
|
|
5483
|
+
ctx._fc = false;
|
|
5484
|
+
return e.run(input, end, ctx);
|
|
5587
5485
|
}
|
|
5588
|
-
|
|
5589
|
-
case "trivia":
|
|
5590
|
-
case "token":
|
|
5591
|
-
case "leaf":
|
|
5592
|
-
case "label":
|
|
5593
|
-
case "field":
|
|
5594
|
-
case "optional":
|
|
5595
|
-
case "many":
|
|
5596
|
-
case "oneOrMore":
|
|
5597
|
-
case "attempt":
|
|
5598
|
-
case "not":
|
|
5599
|
-
case "peek":
|
|
5600
|
-
case "withCtx":
|
|
5601
|
-
case "expect":
|
|
5602
|
-
case "transform":
|
|
5603
|
-
return hasDirectBuildDef(d.parser, seen);
|
|
5604
|
-
case "sequence":
|
|
5605
|
-
case "choice":
|
|
5606
|
-
return d.parsers.some((x) => hasDirectBuildDef(x, seen));
|
|
5607
|
-
case "dispatch":
|
|
5608
|
-
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);
|
|
5609
|
-
case "sepBy":
|
|
5610
|
-
return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.separator, seen);
|
|
5611
|
-
case "scanTo":
|
|
5612
|
-
return hasDirectBuildDef(d.sentinel, seen) || d.skip.some((x) => hasDirectBuildDef(x, seen)) || d.recoverAt !== void 0 && hasDirectBuildDef(d.recoverAt, seen) || d.stopAt !== void 0 && hasDirectBuildDef(d.stopAt, seen);
|
|
5613
|
-
case "recover":
|
|
5614
|
-
return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.sentinel, seen);
|
|
5615
|
-
case "routed":
|
|
5616
|
-
return d.fallback ? hasDirectBuildDef(d.fallback, seen) : false;
|
|
5617
|
-
default:
|
|
5618
|
-
return false;
|
|
5619
|
-
}
|
|
5486
|
+
};
|
|
5620
5487
|
}
|
|
5621
|
-
function
|
|
5622
|
-
|
|
5488
|
+
function appendExpected(acc, values) {
|
|
5489
|
+
if (values === void 0 || values.length === 0) return acc;
|
|
5490
|
+
if (acc === void 0) return values.slice();
|
|
5491
|
+
acc.push(...values);
|
|
5492
|
+
return acc;
|
|
5623
5493
|
}
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
return
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
return [d.parser, d.separator];
|
|
5651
|
-
case "scanTo":
|
|
5652
|
-
return [
|
|
5653
|
-
d.sentinel,
|
|
5654
|
-
...d.skip,
|
|
5655
|
-
...d.recoverAt === void 0 ? NO_EDGES : [d.recoverAt],
|
|
5656
|
-
...d.stopAt === void 0 ? NO_EDGES : [d.stopAt]
|
|
5657
|
-
];
|
|
5658
|
-
case "lazy": {
|
|
5659
|
-
try {
|
|
5660
|
-
return [d.thunk()];
|
|
5661
|
-
} catch {
|
|
5662
|
-
const name = p._ruleName;
|
|
5663
|
-
const target = name === void 0 ? void 0 : resolve3?.(name);
|
|
5664
|
-
return target === void 0 ? true : [target];
|
|
5494
|
+
function choiceNode(arms, classes, armExpected, choiceExpected) {
|
|
5495
|
+
let matchTail = () => -1;
|
|
5496
|
+
for (let i = arms.length - 1; i >= 0; i--) {
|
|
5497
|
+
const arm = arms[i], next = matchTail;
|
|
5498
|
+
matchTail = (input, pos) => {
|
|
5499
|
+
const end = arm.match(input, pos);
|
|
5500
|
+
return end < 0 ? next(input, pos) : end;
|
|
5501
|
+
};
|
|
5502
|
+
}
|
|
5503
|
+
let tail = (_input, pos, ctx, _lead, acc) => {
|
|
5504
|
+
ctx._fe = pos;
|
|
5505
|
+
ctx._fx = acc ?? choiceExpected;
|
|
5506
|
+
return -1;
|
|
5507
|
+
};
|
|
5508
|
+
for (let i = arms.length - 1; i >= 0; i--) {
|
|
5509
|
+
const arm = arms[i], cls = classes[i], staticExpected = armExpected[i], next = tail;
|
|
5510
|
+
tail = (input, pos, ctx, lead2, acc, best) => {
|
|
5511
|
+
if (cls !== void 0 && !classHas(cls, lead2)) {
|
|
5512
|
+
return next(
|
|
5513
|
+
input,
|
|
5514
|
+
pos,
|
|
5515
|
+
ctx,
|
|
5516
|
+
lead2,
|
|
5517
|
+
best === pos ? appendExpected(acc, staticExpected) : acc,
|
|
5518
|
+
best
|
|
5519
|
+
);
|
|
5665
5520
|
}
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
return
|
|
5521
|
+
ctx._fc = false;
|
|
5522
|
+
const end = arm.run(input, pos, ctx);
|
|
5523
|
+
if (end >= 0) return end;
|
|
5524
|
+
const at = ctx._fe ?? pos;
|
|
5525
|
+
if (at > best) {
|
|
5526
|
+
best = at;
|
|
5527
|
+
acc = void 0;
|
|
5528
|
+
}
|
|
5529
|
+
const nextAcc = at === best ? appendExpected(acc, ctx._fx) : acc;
|
|
5530
|
+
if (committed(ctx)) {
|
|
5531
|
+
if (nextAcc !== void 0) ctx._fx = nextAcc;
|
|
5532
|
+
return -1;
|
|
5533
|
+
}
|
|
5534
|
+
return next(input, pos, ctx, lead2, nextAcc, best);
|
|
5535
|
+
};
|
|
5669
5536
|
}
|
|
5537
|
+
return {
|
|
5538
|
+
match: matchTail,
|
|
5539
|
+
run: (input, pos, ctx) => tail(
|
|
5540
|
+
input,
|
|
5541
|
+
pos,
|
|
5542
|
+
ctx,
|
|
5543
|
+
pos < input.length ? input.codePointAt(pos) : -1,
|
|
5544
|
+
void 0,
|
|
5545
|
+
pos
|
|
5546
|
+
)
|
|
5547
|
+
};
|
|
5670
5548
|
}
|
|
5671
|
-
function
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
const at = low.length;
|
|
5680
|
-
order.set(node2, at);
|
|
5681
|
-
low.push(at);
|
|
5682
|
-
found.push(false);
|
|
5683
|
-
stack.push(node2);
|
|
5684
|
-
const next = successors(node2);
|
|
5685
|
-
if (next === true) found[at] = true;
|
|
5686
|
-
else {
|
|
5687
|
-
for (const child of next) {
|
|
5688
|
-
if (found[at]) break;
|
|
5689
|
-
const hit = memo.get(child);
|
|
5690
|
-
if (hit !== void 0) {
|
|
5691
|
-
if (hit) found[at] = true;
|
|
5692
|
-
continue;
|
|
5693
|
-
}
|
|
5694
|
-
const seen = order.get(child);
|
|
5695
|
-
if (seen !== void 0) {
|
|
5696
|
-
if (seen < low[at]) low[at] = seen;
|
|
5697
|
-
continue;
|
|
5698
|
-
}
|
|
5699
|
-
const k = visit(child);
|
|
5700
|
-
if (low[k] < low[at]) low[at] = low[k];
|
|
5701
|
-
if (found[k]) found[at] = true;
|
|
5702
|
-
}
|
|
5703
|
-
}
|
|
5704
|
-
if (low[at] === at) {
|
|
5705
|
-
const answer = found[at];
|
|
5706
|
-
let member;
|
|
5707
|
-
do {
|
|
5708
|
-
member = stack.pop();
|
|
5709
|
-
memo.set(member, answer);
|
|
5710
|
-
} while (member !== node2);
|
|
5549
|
+
function notNode(body, failure) {
|
|
5550
|
+
return {
|
|
5551
|
+
match: (input, pos) => body.match(input, pos) < 0 ? pos : -1,
|
|
5552
|
+
run: (input, pos, ctx) => {
|
|
5553
|
+
if (body.match(input, pos) < 0) return pos;
|
|
5554
|
+
ctx._fe = pos;
|
|
5555
|
+
ctx._fx = failure;
|
|
5556
|
+
return -1;
|
|
5711
5557
|
}
|
|
5712
|
-
return at;
|
|
5713
5558
|
};
|
|
5714
|
-
return found[visit(root)];
|
|
5715
5559
|
}
|
|
5716
|
-
function
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
if (def.tag === "lazy") {
|
|
5727
|
-
if (externalRefs?.has(parser2)) return false;
|
|
5728
|
-
try {
|
|
5729
|
-
return visit(def.thunk());
|
|
5730
|
-
} catch {
|
|
5731
|
-
return true;
|
|
5732
|
-
}
|
|
5560
|
+
function optionalNode(body) {
|
|
5561
|
+
return {
|
|
5562
|
+
match: (input, pos) => {
|
|
5563
|
+
const end = body.match(input, pos);
|
|
5564
|
+
return end < 0 ? pos : end;
|
|
5565
|
+
},
|
|
5566
|
+
run: (input, pos, ctx) => {
|
|
5567
|
+
ctx._fc = false;
|
|
5568
|
+
const end = body.run(input, pos, ctx);
|
|
5569
|
+
return end < 0 && !committed(ctx) ? pos : end;
|
|
5733
5570
|
}
|
|
5734
|
-
return childrenOf2(def).some(visit);
|
|
5735
5571
|
};
|
|
5736
|
-
return roots.some(visit);
|
|
5737
5572
|
}
|
|
5738
|
-
function
|
|
5739
|
-
const
|
|
5740
|
-
const
|
|
5741
|
-
|
|
5742
|
-
if (
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5573
|
+
function fixedTreeRunner(words, matchers, classes, expected) {
|
|
5574
|
+
const stack = [];
|
|
5575
|
+
const pop = () => {
|
|
5576
|
+
const value = stack.pop();
|
|
5577
|
+
if (value === void 0) throw new TypeError("table lexical tree has an incomplete fixed body");
|
|
5578
|
+
return value;
|
|
5579
|
+
};
|
|
5580
|
+
for (let at = 0; at < words.length; ) {
|
|
5581
|
+
const op = words[at++];
|
|
5582
|
+
if (op === LEX_NODE_TERMINAL) {
|
|
5583
|
+
const matcher = matchers[words[at++]], failure = expected[words[at++]];
|
|
5584
|
+
const tracks = words[at++];
|
|
5585
|
+
if (matcher === void 0 || failure === void 0 || tracks !== 0 && tracks !== 1) {
|
|
5586
|
+
throw new TypeError("table lexical tree terminal references an invalid pool entry");
|
|
5751
5587
|
}
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5588
|
+
stack.push(terminalNode(matcher, failure, tracks === 1));
|
|
5589
|
+
continue;
|
|
5590
|
+
}
|
|
5591
|
+
if (op >= LEX_NODE_SEQUENCE2 && op <= LEX_NODE_SEQUENCE5) {
|
|
5592
|
+
const count = op - LEX_NODE_SEQUENCE2 + 2;
|
|
5593
|
+
const nodes2 = Array.from({ length: count }, pop).reverse();
|
|
5594
|
+
if (count === 2) stack.push(sequence2(nodes2[0], nodes2[1]));
|
|
5595
|
+
else if (count === 3) stack.push(sequence3(nodes2[0], nodes2[1], nodes2[2]));
|
|
5596
|
+
else if (count === 4) stack.push(sequence4(nodes2[0], nodes2[1], nodes2[2], nodes2[3]));
|
|
5597
|
+
else stack.push(sequence5(nodes2[0], nodes2[1], nodes2[2], nodes2[3], nodes2[4]));
|
|
5598
|
+
continue;
|
|
5599
|
+
}
|
|
5600
|
+
if (op >= LEX_NODE_CHOICE2 && op <= LEX_NODE_CHOICE8) {
|
|
5601
|
+
const count = op === LEX_NODE_CHOICE2 ? 2 : op === LEX_NODE_CHOICE4 ? 4 : 8;
|
|
5602
|
+
const choiceFx = expected[words[at++]];
|
|
5603
|
+
if (choiceFx === void 0) throw new TypeError("table lexical tree choice has an invalid expected set");
|
|
5604
|
+
const armClasses = [];
|
|
5605
|
+
const armFx = [];
|
|
5606
|
+
for (let i = 0; i < count; i++) {
|
|
5607
|
+
const cls = words[at++], fx = expected[words[at++]];
|
|
5608
|
+
if (cls < -1 || cls >= 0 && classes[cls] === void 0 || fx === void 0) {
|
|
5609
|
+
throw new TypeError("table lexical tree choice references an invalid pool entry");
|
|
5610
|
+
}
|
|
5611
|
+
armClasses.push(cls < 0 ? void 0 : classes[cls]);
|
|
5612
|
+
armFx.push(fx);
|
|
5755
5613
|
}
|
|
5756
|
-
|
|
5757
|
-
|
|
5614
|
+
const arms = Array.from({ length: count }, pop).reverse();
|
|
5615
|
+
stack.push(choiceNode(arms, armClasses, armFx, choiceFx));
|
|
5616
|
+
continue;
|
|
5758
5617
|
}
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5618
|
+
if (op === LEX_NODE_NOT) {
|
|
5619
|
+
const failure = expected[words[at++]];
|
|
5620
|
+
if (failure === void 0) throw new TypeError("table lexical tree assertion has an invalid expected set");
|
|
5621
|
+
stack.push(notNode(pop(), failure));
|
|
5622
|
+
continue;
|
|
5623
|
+
}
|
|
5624
|
+
if (op === LEX_NODE_OPTIONAL) {
|
|
5625
|
+
stack.push(optionalNode(pop()));
|
|
5626
|
+
continue;
|
|
5627
|
+
}
|
|
5628
|
+
throw new TypeError("table lexical tree has an unknown fixed body");
|
|
5629
|
+
}
|
|
5630
|
+
if (stack.length !== 1) throw new TypeError("table lexical tree does not resolve to one root body");
|
|
5631
|
+
return stack[0].run;
|
|
5766
5632
|
}
|
|
5767
|
-
|
|
5768
|
-
|
|
5769
|
-
|
|
5770
|
-
var OP_RX = 2;
|
|
5771
|
-
var OP_SEQ = 3;
|
|
5772
|
-
var OP_SEQV = 4;
|
|
5773
|
-
var OP_CHOICE = 5;
|
|
5774
|
-
var OP_REP = 6;
|
|
5775
|
-
var OP_REPV = 7;
|
|
5776
|
-
var OP_OPT = 8;
|
|
5777
|
-
var OP_XFORM = 9;
|
|
5778
|
-
var OP_NODE = 10;
|
|
5779
|
-
var OP_RULE = 11;
|
|
5780
|
-
var OP_GATE = 12;
|
|
5781
|
-
var OP_NOT = 13;
|
|
5782
|
-
var OP_PEEK = 14;
|
|
5783
|
-
var OP_LEAF = 15;
|
|
5784
|
-
var OP_EMPTY = 16;
|
|
5785
|
-
var OP_LIT_TRACK = 17;
|
|
5786
|
-
var OP_RX_TRACK = 18;
|
|
5787
|
-
var OP_NODE_TRACK = 19;
|
|
5788
|
-
var OP_SCOPE = 20;
|
|
5789
|
-
var OP_EXPECT = 21;
|
|
5790
|
-
var OP_SEQX = 22;
|
|
5791
|
-
var OP_SCAN = 23;
|
|
5792
|
-
var OP_FIELD = 24;
|
|
5793
|
-
var OP_LIT_CI = 27;
|
|
5794
|
-
var OP_LIT_CI_TRACK = 28;
|
|
5795
|
-
var OP_TOKEN = 29;
|
|
5796
|
-
var OP_SCOPE_CAP = 30;
|
|
5797
|
-
var OP_WITHCTX = 31;
|
|
5798
|
-
var OP_GUARD = 32;
|
|
5799
|
-
var OP_ADJ = 33;
|
|
5800
|
-
var OP_GREEDY = 34;
|
|
5801
|
-
var OP_REJECT = 35;
|
|
5802
|
-
var OP_ARMGATE = 36;
|
|
5803
|
-
var OP_LIVE = 37;
|
|
5804
|
-
var OP_ATTEMPT = 38;
|
|
5805
|
-
var OP_LABEL = 39;
|
|
5806
|
-
var OP_COV = 40;
|
|
5807
|
-
var OP_SCOPE_PLAIN = 41;
|
|
5808
|
-
var OP_LEX_BODY = 42;
|
|
5809
|
-
var OP_LEX_PROGRAM = 43;
|
|
5810
|
-
var OP_SOURCE_LEAF = 44;
|
|
5811
|
-
var OP_DISPATCH = 25;
|
|
5812
|
-
var OP_ROUTED = 26;
|
|
5813
|
-
var OP_NAMES = {
|
|
5814
|
-
[OP_LIT]: "LIT",
|
|
5815
|
-
[OP_RX]: "RX",
|
|
5816
|
-
[OP_SEQ]: "SEQ",
|
|
5817
|
-
[OP_SEQV]: "SEQV",
|
|
5818
|
-
[OP_CHOICE]: "CHOICE",
|
|
5819
|
-
[OP_REP]: "REP",
|
|
5820
|
-
[OP_REPV]: "REPV",
|
|
5821
|
-
[OP_OPT]: "OPT",
|
|
5822
|
-
[OP_XFORM]: "XFORM",
|
|
5823
|
-
[OP_NODE]: "NODE",
|
|
5824
|
-
[OP_RULE]: "RULE",
|
|
5825
|
-
[OP_GATE]: "GATE",
|
|
5826
|
-
[OP_NOT]: "NOT",
|
|
5827
|
-
[OP_PEEK]: "PEEK",
|
|
5828
|
-
[OP_LEAF]: "LEAF",
|
|
5829
|
-
[OP_SOURCE_LEAF]: "SOURCE_LEAF",
|
|
5830
|
-
[OP_EMPTY]: "EMPTY",
|
|
5831
|
-
[OP_LIT_TRACK]: "LIT_TRACK",
|
|
5832
|
-
[OP_RX_TRACK]: "RX_TRACK",
|
|
5833
|
-
[OP_NODE_TRACK]: "NODE_TRACK",
|
|
5834
|
-
[OP_SCOPE]: "SCOPE",
|
|
5835
|
-
[OP_EXPECT]: "EXPECT",
|
|
5836
|
-
[OP_SEQX]: "SEQX",
|
|
5837
|
-
[OP_SCAN]: "SCAN",
|
|
5838
|
-
[OP_FIELD]: "FIELD",
|
|
5839
|
-
[OP_LIT_CI]: "LIT_CI",
|
|
5840
|
-
[OP_LIT_CI_TRACK]: "LIT_CI_TRACK",
|
|
5841
|
-
[OP_DISPATCH]: "DISPATCH",
|
|
5842
|
-
[OP_ROUTED]: "ROUTED",
|
|
5843
|
-
[OP_TOKEN]: "TOKEN",
|
|
5844
|
-
[OP_SCOPE_CAP]: "SCOPE_CAP",
|
|
5845
|
-
[OP_WITHCTX]: "WITHCTX",
|
|
5846
|
-
[OP_GUARD]: "GUARD",
|
|
5847
|
-
[OP_ADJ]: "ADJ",
|
|
5848
|
-
[OP_GREEDY]: "GREEDY",
|
|
5849
|
-
[OP_REJECT]: "REJECT",
|
|
5850
|
-
[OP_ARMGATE]: "ARMGATE",
|
|
5851
|
-
[OP_LIVE]: "LIVE",
|
|
5852
|
-
[OP_ATTEMPT]: "ATTEMPT",
|
|
5853
|
-
[OP_LABEL]: "LABEL",
|
|
5854
|
-
[OP_COV]: "COV",
|
|
5855
|
-
[OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
|
|
5856
|
-
[OP_LEX_BODY]: "LEX_BODY",
|
|
5857
|
-
[OP_LEX_PROGRAM]: "LEX_PROGRAM"
|
|
5858
|
-
};
|
|
5859
|
-
|
|
5860
|
-
// src/table/lex-program.ts
|
|
5861
|
-
var LEX_NODE_TERMINAL = 0;
|
|
5862
|
-
var LEX_NODE_SEQUENCE2 = 1;
|
|
5863
|
-
var LEX_NODE_SEQUENCE3 = 2;
|
|
5864
|
-
var LEX_NODE_SEQUENCE4 = 3;
|
|
5865
|
-
var LEX_NODE_SEQUENCE5 = 4;
|
|
5866
|
-
var LEX_NODE_CHOICE2 = 5;
|
|
5867
|
-
var LEX_NODE_CHOICE4 = 6;
|
|
5868
|
-
var LEX_NODE_CHOICE8 = 7;
|
|
5869
|
-
var LEX_NODE_NOT = 8;
|
|
5870
|
-
var LEX_NODE_OPTIONAL = 9;
|
|
5871
|
-
function lexProgramDigest(words) {
|
|
5872
|
-
let hash = 2166136261;
|
|
5873
|
-
for (const word2 of words) {
|
|
5874
|
-
hash ^= word2 | 0;
|
|
5875
|
-
hash = Math.imul(hash, 16777619);
|
|
5633
|
+
function buildLexProgramRunner(spec, matchers, classes, expected) {
|
|
5634
|
+
if (spec[0] !== 0 && spec[0] !== 1 && spec[0] !== 2 && spec[0] !== 3 || spec[0] === 0 && spec.length !== 13 || spec[0] === 1 && spec.length !== 12 || spec[0] === 2 && spec.length < 6 || spec[0] === 3 && spec.length !== 3) {
|
|
5635
|
+
throw new TypeError("table lexical program has an invalid fixed body width");
|
|
5876
5636
|
}
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
function classHas(cls, code) {
|
|
5880
|
-
if (code < 0) return false;
|
|
5881
|
-
if (code < 128) return cls.ascii[code] === 1;
|
|
5882
|
-
for (let i = 0; i < cls.hi.length; i += 2) {
|
|
5883
|
-
if (code >= cls.hi[i] && code <= cls.hi[i + 1]) return true;
|
|
5637
|
+
if (spec[1] !== lexProgramDigest(spec.slice(2))) {
|
|
5638
|
+
throw new TypeError("table lexical program semantic digest is inconsistent");
|
|
5884
5639
|
}
|
|
5885
|
-
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
|
|
5640
|
+
if (spec[0] === 3) {
|
|
5641
|
+
if (!Number.isInteger(spec[2]) || spec[2] < 0) {
|
|
5642
|
+
throw new TypeError("table balanced lexical program has an invalid scan reference");
|
|
5643
|
+
}
|
|
5644
|
+
const run2 = (_input, _pos, ctx, scan) => {
|
|
5645
|
+
if (scan === void 0) throw new TypeError("table balanced lexical program lost its scan body");
|
|
5646
|
+
const result = scan.parse(_input, _pos, ctx);
|
|
5647
|
+
if (!result.ok) {
|
|
5648
|
+
ctx._fe = result.span.start;
|
|
5649
|
+
ctx._fx = result.expected ?? [];
|
|
5650
|
+
return -1;
|
|
5651
|
+
}
|
|
5652
|
+
return result.span.end;
|
|
5653
|
+
};
|
|
5654
|
+
return Object.assign(run2, { scan: spec[2] });
|
|
5895
5655
|
}
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
const
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5656
|
+
if (spec[0] === 2) return fixedTreeRunner(spec.slice(2), matchers, classes, expected);
|
|
5657
|
+
if (spec[0] === 1) {
|
|
5658
|
+
const g00 = matchers[spec[2]], g01 = matchers[spec[3]];
|
|
5659
|
+
const g02 = matchers[spec[4]], g03 = matchers[spec[5]];
|
|
5660
|
+
const guard0Fx = expected[spec[6]];
|
|
5661
|
+
const g1 = matchers[spec[7]], guard1Fx = expected[spec[8]];
|
|
5662
|
+
const terminal = matchers[spec[9]], terminalFx = expected[spec[10]];
|
|
5663
|
+
const tracks2 = spec[11];
|
|
5664
|
+
if (g00 === void 0 || g01 === void 0 || g02 === void 0 || g03 === void 0 || guard0Fx === void 0 || g1 === void 0 || guard1Fx === void 0 || terminal === void 0 || terminalFx === void 0 || tracks2 !== 0 && tracks2 !== 1) {
|
|
5665
|
+
throw new TypeError("table lexical program references an invalid pool entry");
|
|
5666
|
+
}
|
|
5667
|
+
return (input, pos, ctx) => {
|
|
5668
|
+
ctx._fc = false;
|
|
5669
|
+
if (g00(input, pos) >= 0 || g01(input, pos) >= 0 || g02(input, pos) >= 0 || g03(input, pos) >= 0) {
|
|
5908
5670
|
ctx._fe = pos;
|
|
5909
|
-
ctx._fx =
|
|
5671
|
+
ctx._fx = guard0Fx;
|
|
5672
|
+
return -1;
|
|
5673
|
+
}
|
|
5674
|
+
ctx._fc = false;
|
|
5675
|
+
if (g1(input, pos) >= 0) {
|
|
5676
|
+
ctx._fe = pos;
|
|
5677
|
+
ctx._fx = guard1Fx;
|
|
5678
|
+
return -1;
|
|
5679
|
+
}
|
|
5680
|
+
ctx._fc = false;
|
|
5681
|
+
const result = terminal(input, pos);
|
|
5682
|
+
if (result < 0) {
|
|
5683
|
+
ctx._fe = pos;
|
|
5684
|
+
ctx._fx = terminalFx;
|
|
5910
5685
|
if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
|
|
5911
5686
|
return -1;
|
|
5912
5687
|
}
|
|
5913
|
-
|
|
5688
|
+
const end = result / 2;
|
|
5689
|
+
if (tracks2 === 1) trackLexLines(ctx, input, end);
|
|
5914
5690
|
return end;
|
|
5691
|
+
};
|
|
5692
|
+
}
|
|
5693
|
+
const cls = classes[spec[2]];
|
|
5694
|
+
const choiceFx = expected[spec[3]];
|
|
5695
|
+
const m0 = matchers[spec[4]], x0 = expected[spec[5]];
|
|
5696
|
+
const m1 = matchers[spec[6]], x1 = expected[spec[7]];
|
|
5697
|
+
const m2 = matchers[spec[8]], x2 = expected[spec[9]];
|
|
5698
|
+
const m3 = matchers[spec[10]], x3 = expected[spec[11]];
|
|
5699
|
+
const tracks = spec[12];
|
|
5700
|
+
if (cls === void 0 || choiceFx === void 0 || m0 === void 0 || x0 === void 0 || m1 === void 0 || x1 === void 0 || m2 === void 0 || x2 === void 0 || m3 === void 0 || x3 === void 0 || tracks !== 0 && tracks !== 1) {
|
|
5701
|
+
throw new TypeError("table lexical program references an invalid pool entry");
|
|
5702
|
+
}
|
|
5703
|
+
return (input, pos, ctx) => {
|
|
5704
|
+
const lead2 = pos < input.length ? input.codePointAt(pos) : -1;
|
|
5705
|
+
if (!classHas(cls, lead2)) {
|
|
5706
|
+
ctx._fe = pos;
|
|
5707
|
+
ctx._fx = choiceFx.slice();
|
|
5708
|
+
return -1;
|
|
5915
5709
|
}
|
|
5710
|
+
let acc;
|
|
5711
|
+
const failed = (fx) => {
|
|
5712
|
+
ctx._fe = pos;
|
|
5713
|
+
ctx._fx = fx;
|
|
5714
|
+
if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
|
|
5715
|
+
if (acc === void 0) acc = fx.slice();
|
|
5716
|
+
else acc.push(...fx);
|
|
5717
|
+
};
|
|
5718
|
+
ctx._fc = false;
|
|
5719
|
+
const success = (result2) => {
|
|
5720
|
+
const end = result2 / 2;
|
|
5721
|
+
if (tracks === 1) trackLexLines(ctx, input, end);
|
|
5722
|
+
return end;
|
|
5723
|
+
};
|
|
5724
|
+
let result = m0(input, pos);
|
|
5725
|
+
if (result >= 0) return success(result);
|
|
5726
|
+
failed(x0);
|
|
5727
|
+
ctx._fc = false;
|
|
5728
|
+
result = m1(input, pos);
|
|
5729
|
+
if (result >= 0) return success(result);
|
|
5730
|
+
failed(x1);
|
|
5731
|
+
ctx._fc = false;
|
|
5732
|
+
result = m2(input, pos);
|
|
5733
|
+
if (result >= 0) return success(result);
|
|
5734
|
+
failed(x2);
|
|
5735
|
+
ctx._fc = false;
|
|
5736
|
+
result = m3(input, pos);
|
|
5737
|
+
if (result >= 0) return success(result);
|
|
5738
|
+
failed(x3);
|
|
5739
|
+
ctx._fe = pos;
|
|
5740
|
+
ctx._fx = acc ?? choiceFx;
|
|
5741
|
+
return -1;
|
|
5916
5742
|
};
|
|
5917
5743
|
}
|
|
5918
|
-
|
|
5919
|
-
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
return e0 < 0 ? -1 : b.match(input, e0);
|
|
5923
|
-
},
|
|
5924
|
-
run: (input, pos, ctx) => {
|
|
5925
|
-
const e0 = a.run(input, pos, ctx);
|
|
5926
|
-
if (e0 < 0) return -1;
|
|
5927
|
-
ctx._fc = false;
|
|
5928
|
-
return b.run(input, e0, ctx);
|
|
5929
|
-
}
|
|
5930
|
-
};
|
|
5744
|
+
|
|
5745
|
+
// src/table/program.ts
|
|
5746
|
+
function closureArtifact(prog) {
|
|
5747
|
+
return { ...prog, asm: [] };
|
|
5931
5748
|
}
|
|
5932
|
-
function
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
ctx._fc = false;
|
|
5944
|
-
const e1 = b.run(input, e0, ctx);
|
|
5945
|
-
if (e1 < 0) return -1;
|
|
5946
|
-
ctx._fc = false;
|
|
5947
|
-
return c.run(input, e1, ctx);
|
|
5948
|
-
}
|
|
5949
|
-
};
|
|
5749
|
+
function covKindCode(kind) {
|
|
5750
|
+
switch (kind) {
|
|
5751
|
+
case "rule":
|
|
5752
|
+
return 0;
|
|
5753
|
+
case "choice-arm":
|
|
5754
|
+
return 1;
|
|
5755
|
+
case "dispatch-arm":
|
|
5756
|
+
return 2;
|
|
5757
|
+
case "label":
|
|
5758
|
+
return 3;
|
|
5759
|
+
}
|
|
5950
5760
|
}
|
|
5951
|
-
function
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
return
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
return d.run(input, end, ctx);
|
|
5963
|
-
}
|
|
5964
|
-
};
|
|
5761
|
+
function covKindName(code) {
|
|
5762
|
+
switch (code) {
|
|
5763
|
+
case 0:
|
|
5764
|
+
return "rule";
|
|
5765
|
+
case 1:
|
|
5766
|
+
return "choice-arm";
|
|
5767
|
+
case 2:
|
|
5768
|
+
return "dispatch-arm";
|
|
5769
|
+
case 3:
|
|
5770
|
+
return "label";
|
|
5771
|
+
}
|
|
5965
5772
|
}
|
|
5966
|
-
function
|
|
5967
|
-
|
|
5968
|
-
return {
|
|
5969
|
-
match: (input, pos) => {
|
|
5970
|
-
const end = abcd.match(input, pos);
|
|
5971
|
-
return end < 0 ? -1 : e.match(input, end);
|
|
5972
|
-
},
|
|
5973
|
-
run: (input, pos, ctx) => {
|
|
5974
|
-
const end = abcd.run(input, pos, ctx);
|
|
5975
|
-
if (end < 0) return -1;
|
|
5976
|
-
ctx._fc = false;
|
|
5977
|
-
return e.run(input, end, ctx);
|
|
5978
|
-
}
|
|
5979
|
-
};
|
|
5773
|
+
function covDefinitions(prog) {
|
|
5774
|
+
return (prog.cov ?? []).map(([id, kind]) => ({ id, kind: covKindName(kind) }));
|
|
5980
5775
|
}
|
|
5981
|
-
function
|
|
5982
|
-
|
|
5983
|
-
if (
|
|
5984
|
-
|
|
5985
|
-
return
|
|
5776
|
+
function scanRefs(s) {
|
|
5777
|
+
const refs = [];
|
|
5778
|
+
for (const r of [s.sentinel, s.recoverAt, s.stopAt, s.prefix, s.body, s.first, s.lazy]) if (r !== void 0) refs.push(r);
|
|
5779
|
+
refs.push(...s.skip);
|
|
5780
|
+
return refs;
|
|
5986
5781
|
}
|
|
5987
|
-
function
|
|
5988
|
-
|
|
5989
|
-
for (
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
|
|
5782
|
+
function assemblyExtraIps(prog) {
|
|
5783
|
+
const ips = [];
|
|
5784
|
+
for (const s of prog.scans ?? []) for (const r of scanRefs(s)) ips.push(r[0]);
|
|
5785
|
+
for (const set of prog.scanSkip ?? []) for (const r of set) ips.push(r[0]);
|
|
5786
|
+
return ips;
|
|
5787
|
+
}
|
|
5788
|
+
function expandCompact(p) {
|
|
5789
|
+
if ("code" in p) return p;
|
|
5790
|
+
return ownTableProgram({
|
|
5791
|
+
code: p.c,
|
|
5792
|
+
k: p.k,
|
|
5793
|
+
cc: p.x,
|
|
5794
|
+
fx: p.e,
|
|
5795
|
+
disp: p.d,
|
|
5796
|
+
rules: p.r,
|
|
5797
|
+
fns: p.f,
|
|
5798
|
+
lines: p.l ?? 0,
|
|
5799
|
+
dsp: p.p ?? [],
|
|
5800
|
+
...p.lx === void 0 ? {} : { lex: p.lx },
|
|
5801
|
+
...p.lp === void 0 ? {} : { lexPrograms: p.lp },
|
|
5802
|
+
...p.lb === void 0 ? {} : { labels: p.lb },
|
|
5803
|
+
...p.rc === void 0 ? {} : { classified: p.rc },
|
|
5804
|
+
...p.h === void 0 ? {} : { hostMode: p.h },
|
|
5805
|
+
...p.tv === void 0 ? {} : { triviaSpecs: p.tv },
|
|
5806
|
+
...p.sc === void 0 ? {} : { scans: p.sc },
|
|
5807
|
+
...p.ss === void 0 ? {} : { scanSkip: p.ss },
|
|
5808
|
+
...p.so === void 0 ? {} : { scanSkipOf: p.so },
|
|
5809
|
+
...p.rv === void 0 ? {} : { rec: p.rv },
|
|
5810
|
+
...p.cv === void 0 ? {} : { cov: p.cv },
|
|
5811
|
+
...p.a === void 0 ? {} : { asm: p.a }
|
|
5812
|
+
});
|
|
5813
|
+
}
|
|
5814
|
+
function validateDispatchSpec(spec, arity, fallbackRouted) {
|
|
5815
|
+
const invalid = (arms) => {
|
|
5816
|
+
for (const arm of arms) if (!Number.isInteger(arm) || arm < 0 || arm >= arity) return true;
|
|
5817
|
+
return false;
|
|
6000
5818
|
};
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
tail = (input, pos, ctx, lead2, acc, best) => {
|
|
6004
|
-
if (cls !== void 0 && !classHas(cls, lead2)) {
|
|
6005
|
-
return next(
|
|
6006
|
-
input,
|
|
6007
|
-
pos,
|
|
6008
|
-
ctx,
|
|
6009
|
-
lead2,
|
|
6010
|
-
best === pos ? appendExpected(acc, staticExpected) : acc,
|
|
6011
|
-
best
|
|
6012
|
-
);
|
|
6013
|
-
}
|
|
6014
|
-
ctx._fc = false;
|
|
6015
|
-
const end = arm.run(input, pos, ctx);
|
|
6016
|
-
if (end >= 0) return end;
|
|
6017
|
-
const at = ctx._fe ?? pos;
|
|
6018
|
-
if (at > best) {
|
|
6019
|
-
best = at;
|
|
6020
|
-
acc = void 0;
|
|
6021
|
-
}
|
|
6022
|
-
const nextAcc = at === best ? appendExpected(acc, ctx._fx) : acc;
|
|
6023
|
-
if (committed(ctx)) {
|
|
6024
|
-
if (nextAcc !== void 0) ctx._fx = nextAcc;
|
|
6025
|
-
return -1;
|
|
6026
|
-
}
|
|
6027
|
-
return next(input, pos, ctx, lead2, nextAcc, best);
|
|
6028
|
-
};
|
|
5819
|
+
if (spec === void 0 || !Number.isInteger(arity) || arity < 0 || fallbackRouted !== 0 && fallbackRouted !== 1 || spec.routed.length !== arity || spec.routed.some((value) => value !== 0 && value !== 1) || invalid(spec.byKey.values()) || invalid(spec.byFold.values()) || spec.match.some((matcher) => invalid([matcher[3]]))) {
|
|
5820
|
+
throw new TypeError("table: malformed dispatch");
|
|
6029
5821
|
}
|
|
6030
|
-
return {
|
|
6031
|
-
match: matchTail,
|
|
6032
|
-
run: (input, pos, ctx) => tail(
|
|
6033
|
-
input,
|
|
6034
|
-
pos,
|
|
6035
|
-
ctx,
|
|
6036
|
-
pos < input.length ? input.codePointAt(pos) : -1,
|
|
6037
|
-
void 0,
|
|
6038
|
-
pos
|
|
6039
|
-
)
|
|
6040
|
-
};
|
|
6041
5822
|
}
|
|
6042
|
-
|
|
5823
|
+
var TABLE_RUNTIME = /* @__PURE__ */ Symbol("parseman.tableRuntime");
|
|
5824
|
+
function ownTableProgram(prog, resolved, caches = {}) {
|
|
5825
|
+
const runtime = prog[TABLE_RUNTIME];
|
|
6043
5826
|
return {
|
|
6044
|
-
|
|
6045
|
-
|
|
6046
|
-
|
|
6047
|
-
|
|
6048
|
-
|
|
6049
|
-
|
|
5827
|
+
...prog,
|
|
5828
|
+
[TABLE_RUNTIME]: {
|
|
5829
|
+
resolved,
|
|
5830
|
+
choiceRollbackMasks: caches.choiceRollbackMasks ?? runtime?.choiceRollbackMasks,
|
|
5831
|
+
nonCommittingChoiceSites: caches.nonCommittingChoiceSites ?? runtime?.nonCommittingChoiceSites,
|
|
5832
|
+
failureRollbackCleanSites: caches.failureRollbackCleanSites ?? runtime?.failureRollbackCleanSites
|
|
6050
5833
|
}
|
|
6051
5834
|
};
|
|
6052
5835
|
}
|
|
6053
|
-
function
|
|
6054
|
-
return
|
|
6055
|
-
match: (input, pos) => {
|
|
6056
|
-
const end = body.match(input, pos);
|
|
6057
|
-
return end < 0 ? pos : end;
|
|
6058
|
-
},
|
|
6059
|
-
run: (input, pos, ctx) => {
|
|
6060
|
-
ctx._fc = false;
|
|
6061
|
-
const end = body.run(input, pos, ctx);
|
|
6062
|
-
return end < 0 && !committed(ctx) ? pos : end;
|
|
6063
|
-
}
|
|
6064
|
-
};
|
|
5836
|
+
function choiceRollbackMask(prog, ip) {
|
|
5837
|
+
return prog[TABLE_RUNTIME]?.choiceRollbackMasks?.get(ip);
|
|
6065
5838
|
}
|
|
6066
|
-
function
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6070
|
-
|
|
6071
|
-
|
|
6072
|
-
|
|
6073
|
-
|
|
6074
|
-
|
|
6075
|
-
|
|
6076
|
-
|
|
6077
|
-
|
|
6078
|
-
if (matcher === void 0 || failure === void 0 || tracks !== 0 && tracks !== 1) {
|
|
6079
|
-
throw new TypeError("table lexical tree terminal references an invalid pool entry");
|
|
6080
|
-
}
|
|
6081
|
-
stack.push(terminalNode(matcher, failure, tracks === 1));
|
|
6082
|
-
continue;
|
|
6083
|
-
}
|
|
6084
|
-
if (op >= LEX_NODE_SEQUENCE2 && op <= LEX_NODE_SEQUENCE5) {
|
|
6085
|
-
const count = op - LEX_NODE_SEQUENCE2 + 2;
|
|
6086
|
-
const nodes2 = Array.from({ length: count }, pop).reverse();
|
|
6087
|
-
if (count === 2) stack.push(sequence2(nodes2[0], nodes2[1]));
|
|
6088
|
-
else if (count === 3) stack.push(sequence3(nodes2[0], nodes2[1], nodes2[2]));
|
|
6089
|
-
else if (count === 4) stack.push(sequence4(nodes2[0], nodes2[1], nodes2[2], nodes2[3]));
|
|
6090
|
-
else stack.push(sequence5(nodes2[0], nodes2[1], nodes2[2], nodes2[3], nodes2[4]));
|
|
6091
|
-
continue;
|
|
6092
|
-
}
|
|
6093
|
-
if (op >= LEX_NODE_CHOICE2 && op <= LEX_NODE_CHOICE8) {
|
|
6094
|
-
const count = op === LEX_NODE_CHOICE2 ? 2 : op === LEX_NODE_CHOICE4 ? 4 : 8;
|
|
6095
|
-
const choiceFx = expected[words[at++]];
|
|
6096
|
-
if (choiceFx === void 0) throw new TypeError("table lexical tree choice has an invalid expected set");
|
|
6097
|
-
const armClasses = [];
|
|
6098
|
-
const armFx = [];
|
|
6099
|
-
for (let i = 0; i < count; i++) {
|
|
6100
|
-
const cls = words[at++], fx = expected[words[at++]];
|
|
6101
|
-
if (cls < -1 || cls >= 0 && classes[cls] === void 0 || fx === void 0) {
|
|
6102
|
-
throw new TypeError("table lexical tree choice references an invalid pool entry");
|
|
6103
|
-
}
|
|
6104
|
-
armClasses.push(cls < 0 ? void 0 : classes[cls]);
|
|
6105
|
-
armFx.push(fx);
|
|
6106
|
-
}
|
|
6107
|
-
const arms = Array.from({ length: count }, pop).reverse();
|
|
6108
|
-
stack.push(choiceNode(arms, armClasses, armFx, choiceFx));
|
|
6109
|
-
continue;
|
|
6110
|
-
}
|
|
6111
|
-
if (op === LEX_NODE_NOT) {
|
|
6112
|
-
const failure = expected[words[at++]];
|
|
6113
|
-
if (failure === void 0) throw new TypeError("table lexical tree assertion has an invalid expected set");
|
|
6114
|
-
stack.push(notNode(pop(), failure));
|
|
6115
|
-
continue;
|
|
6116
|
-
}
|
|
6117
|
-
if (op === LEX_NODE_OPTIONAL) {
|
|
6118
|
-
stack.push(optionalNode(pop()));
|
|
6119
|
-
continue;
|
|
5839
|
+
function choiceCannotCommit(prog, ip) {
|
|
5840
|
+
return prog[TABLE_RUNTIME]?.nonCommittingChoiceSites?.has(ip) === true;
|
|
5841
|
+
}
|
|
5842
|
+
function failureRollbackClean(prog, ip) {
|
|
5843
|
+
return prog[TABLE_RUNTIME]?.failureRollbackCleanSites?.has(ip) === true;
|
|
5844
|
+
}
|
|
5845
|
+
var WIDE_CLASS_PREFIX_LO = 65535;
|
|
5846
|
+
var WIDE_CLASS_PREFIX_HI = 0;
|
|
5847
|
+
function validateClassRange(lo, hi) {
|
|
5848
|
+
for (const cp of [lo, hi]) {
|
|
5849
|
+
if (!Number.isInteger(cp) || cp < 0 || cp > 1114111) {
|
|
5850
|
+
throw new TypeError(`table char-class endpoint is outside Unicode: ${cp}`);
|
|
6120
5851
|
}
|
|
6121
|
-
throw new TypeError("table lexical tree has an unknown fixed body");
|
|
6122
5852
|
}
|
|
6123
|
-
if (
|
|
6124
|
-
|
|
5853
|
+
if (lo > hi) {
|
|
5854
|
+
throw new TypeError(`table char-class range is descending: ${lo} > ${hi}`);
|
|
5855
|
+
}
|
|
6125
5856
|
}
|
|
6126
|
-
function
|
|
6127
|
-
|
|
6128
|
-
|
|
6129
|
-
|
|
6130
|
-
|
|
6131
|
-
throw new TypeError("table lexical program semantic digest is inconsistent");
|
|
6132
|
-
}
|
|
6133
|
-
if (spec[0] === 3) {
|
|
6134
|
-
if (!Number.isInteger(spec[2]) || spec[2] < 0) {
|
|
6135
|
-
throw new TypeError("table balanced lexical program has an invalid scan reference");
|
|
6136
|
-
}
|
|
6137
|
-
const run = (_input, _pos, ctx, scan) => {
|
|
6138
|
-
if (scan === void 0) throw new TypeError("table balanced lexical program lost its scan body");
|
|
6139
|
-
const result = scan.parse(_input, _pos, ctx);
|
|
6140
|
-
if (!result.ok) {
|
|
6141
|
-
ctx._fe = result.span.start;
|
|
6142
|
-
ctx._fx = result.expected ?? [];
|
|
6143
|
-
return -1;
|
|
6144
|
-
}
|
|
6145
|
-
return result.span.end;
|
|
6146
|
-
};
|
|
6147
|
-
return Object.assign(run, { scan: spec[2] });
|
|
6148
|
-
}
|
|
6149
|
-
if (spec[0] === 2) return fixedTreeRunner(spec.slice(2), matchers, classes, expected);
|
|
6150
|
-
if (spec[0] === 1) {
|
|
6151
|
-
const g00 = matchers[spec[2]], g01 = matchers[spec[3]];
|
|
6152
|
-
const g02 = matchers[spec[4]], g03 = matchers[spec[5]];
|
|
6153
|
-
const guard0Fx = expected[spec[6]];
|
|
6154
|
-
const g1 = matchers[spec[7]], guard1Fx = expected[spec[8]];
|
|
6155
|
-
const terminal = matchers[spec[9]], terminalFx = expected[spec[10]];
|
|
6156
|
-
const tracks2 = spec[11];
|
|
6157
|
-
if (g00 === void 0 || g01 === void 0 || g02 === void 0 || g03 === void 0 || guard0Fx === void 0 || g1 === void 0 || guard1Fx === void 0 || terminal === void 0 || terminalFx === void 0 || tracks2 !== 0 && tracks2 !== 1) {
|
|
6158
|
-
throw new TypeError("table lexical program references an invalid pool entry");
|
|
6159
|
-
}
|
|
6160
|
-
return (input, pos, ctx) => {
|
|
6161
|
-
ctx._fc = false;
|
|
6162
|
-
if (g00(input, pos) >= 0 || g01(input, pos) >= 0 || g02(input, pos) >= 0 || g03(input, pos) >= 0) {
|
|
6163
|
-
ctx._fe = pos;
|
|
6164
|
-
ctx._fx = guard0Fx;
|
|
6165
|
-
return -1;
|
|
6166
|
-
}
|
|
6167
|
-
ctx._fc = false;
|
|
6168
|
-
if (g1(input, pos) >= 0) {
|
|
6169
|
-
ctx._fe = pos;
|
|
6170
|
-
ctx._fx = guard1Fx;
|
|
6171
|
-
return -1;
|
|
6172
|
-
}
|
|
6173
|
-
ctx._fc = false;
|
|
6174
|
-
const result = terminal(input, pos);
|
|
6175
|
-
if (result < 0) {
|
|
6176
|
-
ctx._fe = pos;
|
|
6177
|
-
ctx._fx = terminalFx;
|
|
6178
|
-
if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
|
|
6179
|
-
return -1;
|
|
6180
|
-
}
|
|
6181
|
-
const end = result / 2;
|
|
6182
|
-
if (tracks2 === 1) trackLexLines(ctx, input, end);
|
|
6183
|
-
return end;
|
|
6184
|
-
};
|
|
6185
|
-
}
|
|
6186
|
-
const cls = classes[spec[2]];
|
|
6187
|
-
const choiceFx = expected[spec[3]];
|
|
6188
|
-
const m0 = matchers[spec[4]], x0 = expected[spec[5]];
|
|
6189
|
-
const m1 = matchers[spec[6]], x1 = expected[spec[7]];
|
|
6190
|
-
const m2 = matchers[spec[8]], x2 = expected[spec[9]];
|
|
6191
|
-
const m3 = matchers[spec[10]], x3 = expected[spec[11]];
|
|
6192
|
-
const tracks = spec[12];
|
|
6193
|
-
if (cls === void 0 || choiceFx === void 0 || m0 === void 0 || x0 === void 0 || m1 === void 0 || x1 === void 0 || m2 === void 0 || x2 === void 0 || m3 === void 0 || x3 === void 0 || tracks !== 0 && tracks !== 1) {
|
|
6194
|
-
throw new TypeError("table lexical program references an invalid pool entry");
|
|
6195
|
-
}
|
|
6196
|
-
return (input, pos, ctx) => {
|
|
6197
|
-
const lead2 = pos < input.length ? input.codePointAt(pos) : -1;
|
|
6198
|
-
if (!classHas(cls, lead2)) {
|
|
6199
|
-
ctx._fe = pos;
|
|
6200
|
-
ctx._fx = choiceFx.slice();
|
|
6201
|
-
return -1;
|
|
6202
|
-
}
|
|
6203
|
-
let acc;
|
|
6204
|
-
const failed = (fx) => {
|
|
6205
|
-
ctx._fe = pos;
|
|
6206
|
-
ctx._fx = fx;
|
|
6207
|
-
if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
|
|
6208
|
-
if (acc === void 0) acc = fx.slice();
|
|
6209
|
-
else acc.push(...fx);
|
|
6210
|
-
};
|
|
6211
|
-
ctx._fc = false;
|
|
6212
|
-
const success = (result2) => {
|
|
6213
|
-
const end = result2 / 2;
|
|
6214
|
-
if (tracks === 1) trackLexLines(ctx, input, end);
|
|
6215
|
-
return end;
|
|
6216
|
-
};
|
|
6217
|
-
let result = m0(input, pos);
|
|
6218
|
-
if (result >= 0) return success(result);
|
|
6219
|
-
failed(x0);
|
|
6220
|
-
ctx._fc = false;
|
|
6221
|
-
result = m1(input, pos);
|
|
6222
|
-
if (result >= 0) return success(result);
|
|
6223
|
-
failed(x1);
|
|
6224
|
-
ctx._fc = false;
|
|
6225
|
-
result = m2(input, pos);
|
|
6226
|
-
if (result >= 0) return success(result);
|
|
6227
|
-
failed(x2);
|
|
6228
|
-
ctx._fc = false;
|
|
6229
|
-
result = m3(input, pos);
|
|
6230
|
-
if (result >= 0) return success(result);
|
|
6231
|
-
failed(x3);
|
|
6232
|
-
ctx._fe = pos;
|
|
6233
|
-
ctx._fx = acc ?? choiceFx;
|
|
6234
|
-
return -1;
|
|
6235
|
-
};
|
|
6236
|
-
}
|
|
6237
|
-
|
|
6238
|
-
// src/table/lex-body.ts
|
|
6239
|
-
function buildLexBodyRecognizer(spec, constants) {
|
|
6240
|
-
const raw = constants[spec[0]];
|
|
6241
|
-
if (!(raw instanceof RegExp)) {
|
|
6242
|
-
throw new TypeError("table lexical body does not reference a RegExp constant");
|
|
6243
|
-
}
|
|
6244
|
-
if (!Number.isInteger(spec[1]) || spec[1] < -1 || spec[1] > 65535) {
|
|
6245
|
-
throw new TypeError("table lexical body suffix is not absent or one UTF-16 code unit");
|
|
6246
|
-
}
|
|
6247
|
-
const re = raw.sticky ? new RegExp(raw.source, raw.flags) : new RegExp(raw.source, `${raw.flags.replace(/[gy]/g, "")}y`);
|
|
6248
|
-
const suffix = spec[1];
|
|
6249
|
-
return (input, pos) => {
|
|
6250
|
-
re.lastIndex = pos;
|
|
6251
|
-
if (!re.test(input)) return -1;
|
|
6252
|
-
const end = re.lastIndex;
|
|
6253
|
-
if (suffix < 0) return end * 2;
|
|
6254
|
-
return input.charCodeAt(end) === suffix ? (end + 1) * 2 + 1 : end * 2;
|
|
6255
|
-
};
|
|
6256
|
-
}
|
|
6257
|
-
|
|
6258
|
-
// src/table/program.ts
|
|
6259
|
-
function closureArtifact(prog) {
|
|
6260
|
-
return { ...prog, asm: [] };
|
|
6261
|
-
}
|
|
6262
|
-
function covKindCode(kind) {
|
|
6263
|
-
switch (kind) {
|
|
6264
|
-
case "rule":
|
|
6265
|
-
return 0;
|
|
6266
|
-
case "choice-arm":
|
|
6267
|
-
return 1;
|
|
6268
|
-
case "dispatch-arm":
|
|
6269
|
-
return 2;
|
|
6270
|
-
case "label":
|
|
6271
|
-
return 3;
|
|
6272
|
-
}
|
|
6273
|
-
}
|
|
6274
|
-
function covKindName(code) {
|
|
6275
|
-
switch (code) {
|
|
6276
|
-
case 0:
|
|
6277
|
-
return "rule";
|
|
6278
|
-
case 1:
|
|
6279
|
-
return "choice-arm";
|
|
6280
|
-
case 2:
|
|
6281
|
-
return "dispatch-arm";
|
|
6282
|
-
case 3:
|
|
6283
|
-
return "label";
|
|
6284
|
-
}
|
|
6285
|
-
}
|
|
6286
|
-
function covDefinitions(prog) {
|
|
6287
|
-
return (prog.cov ?? []).map(([id, kind]) => ({ id, kind: covKindName(kind) }));
|
|
6288
|
-
}
|
|
6289
|
-
function expandCompact(p) {
|
|
6290
|
-
if ("code" in p) return p;
|
|
6291
|
-
return ownTableProgram({
|
|
6292
|
-
code: p.c,
|
|
6293
|
-
k: p.k,
|
|
6294
|
-
cc: p.x,
|
|
6295
|
-
fx: p.e,
|
|
6296
|
-
disp: p.d,
|
|
6297
|
-
rules: p.r,
|
|
6298
|
-
fns: p.f,
|
|
6299
|
-
lines: p.l ?? 0,
|
|
6300
|
-
dsp: p.p ?? [],
|
|
6301
|
-
...p.lx === void 0 ? {} : { lex: p.lx },
|
|
6302
|
-
...p.lp === void 0 ? {} : { lexPrograms: p.lp },
|
|
6303
|
-
...p.lb === void 0 ? {} : { labels: p.lb },
|
|
6304
|
-
...p.rc === void 0 ? {} : { classified: p.rc },
|
|
6305
|
-
...p.h === void 0 ? {} : { hostMode: p.h },
|
|
6306
|
-
...p.tv === void 0 ? {} : { triviaSpecs: p.tv },
|
|
6307
|
-
...p.sc === void 0 ? {} : { scans: p.sc },
|
|
6308
|
-
...p.ss === void 0 ? {} : { scanSkip: p.ss },
|
|
6309
|
-
...p.so === void 0 ? {} : { scanSkipOf: p.so },
|
|
6310
|
-
...p.rv === void 0 ? {} : { rec: p.rv },
|
|
6311
|
-
...p.cv === void 0 ? {} : { cov: p.cv },
|
|
6312
|
-
...p.a === void 0 ? {} : { asm: p.a }
|
|
6313
|
-
});
|
|
6314
|
-
}
|
|
6315
|
-
function validateDispatchSpec(spec, arity, fallbackRouted) {
|
|
6316
|
-
const invalid = (arms) => {
|
|
6317
|
-
for (const arm of arms) if (!Number.isInteger(arm) || arm < 0 || arm >= arity) return true;
|
|
6318
|
-
return false;
|
|
6319
|
-
};
|
|
6320
|
-
if (spec === void 0 || !Number.isInteger(arity) || arity < 0 || fallbackRouted !== 0 && fallbackRouted !== 1 || spec.routed.length !== arity || spec.routed.some((value) => value !== 0 && value !== 1) || invalid(spec.byKey.values()) || invalid(spec.byFold.values()) || spec.match.some((matcher) => invalid([matcher[3]]))) {
|
|
6321
|
-
throw new TypeError("table: malformed dispatch");
|
|
6322
|
-
}
|
|
6323
|
-
}
|
|
6324
|
-
var TABLE_RUNTIME = /* @__PURE__ */ Symbol("parseman.tableRuntime");
|
|
6325
|
-
function ownTableProgram(prog, resolved, caches = {}) {
|
|
6326
|
-
const runtime = prog[TABLE_RUNTIME];
|
|
6327
|
-
return {
|
|
6328
|
-
...prog,
|
|
6329
|
-
[TABLE_RUNTIME]: {
|
|
6330
|
-
resolved,
|
|
6331
|
-
choiceRollbackMasks: caches.choiceRollbackMasks ?? runtime?.choiceRollbackMasks,
|
|
6332
|
-
nonCommittingChoiceSites: caches.nonCommittingChoiceSites ?? runtime?.nonCommittingChoiceSites,
|
|
6333
|
-
failureRollbackCleanSites: caches.failureRollbackCleanSites ?? runtime?.failureRollbackCleanSites
|
|
6334
|
-
}
|
|
6335
|
-
};
|
|
6336
|
-
}
|
|
6337
|
-
function choiceRollbackMask(prog, ip) {
|
|
6338
|
-
return prog[TABLE_RUNTIME]?.choiceRollbackMasks?.get(ip);
|
|
6339
|
-
}
|
|
6340
|
-
function choiceCannotCommit(prog, ip) {
|
|
6341
|
-
return prog[TABLE_RUNTIME]?.nonCommittingChoiceSites?.has(ip) === true;
|
|
6342
|
-
}
|
|
6343
|
-
function failureRollbackClean(prog, ip) {
|
|
6344
|
-
return prog[TABLE_RUNTIME]?.failureRollbackCleanSites?.has(ip) === true;
|
|
6345
|
-
}
|
|
6346
|
-
var WIDE_CLASS_PREFIX_LO = 65535;
|
|
6347
|
-
var WIDE_CLASS_PREFIX_HI = 0;
|
|
6348
|
-
function validateClassRange(lo, hi) {
|
|
6349
|
-
for (const cp of [lo, hi]) {
|
|
6350
|
-
if (!Number.isInteger(cp) || cp < 0 || cp > 1114111) {
|
|
6351
|
-
throw new TypeError(`table char-class endpoint is outside Unicode: ${cp}`);
|
|
6352
|
-
}
|
|
6353
|
-
}
|
|
6354
|
-
if (lo > hi) {
|
|
6355
|
-
throw new TypeError(`table char-class range is descending: ${lo} > ${hi}`);
|
|
6356
|
-
}
|
|
6357
|
-
}
|
|
6358
|
-
function encodeClassSpec(ranges) {
|
|
6359
|
-
let wide = false;
|
|
6360
|
-
for (const range2 of ranges) {
|
|
6361
|
-
validateClassRange(range2.lo, range2.hi);
|
|
6362
|
-
if (range2.hi > 65535) wide = true;
|
|
5857
|
+
function encodeClassSpec(ranges) {
|
|
5858
|
+
let wide = false;
|
|
5859
|
+
for (const range2 of ranges) {
|
|
5860
|
+
validateClassRange(range2.lo, range2.hi);
|
|
5861
|
+
if (range2.hi > 65535) wide = true;
|
|
6363
5862
|
}
|
|
6364
5863
|
if (!wide) {
|
|
6365
5864
|
let spec2 = "";
|
|
@@ -6416,6 +5915,11 @@ function classHas2(cls, code) {
|
|
|
6416
5915
|
for (let i = 0; i < hi.length; i += 2) if (code >= hi[i] && code <= hi[i + 1]) return true;
|
|
6417
5916
|
return false;
|
|
6418
5917
|
}
|
|
5918
|
+
function dispatchIsExclusive(arms, cc) {
|
|
5919
|
+
const resolved = [];
|
|
5920
|
+
for (const ci of arms) if (ci >= 0) resolved[ci] = resolveClass(cc[ci]);
|
|
5921
|
+
return resolveDispatch(arms, resolved).exclusive;
|
|
5922
|
+
}
|
|
6419
5923
|
function resolveDispatch(arms, cc) {
|
|
6420
5924
|
const ascii = new Uint8Array(128);
|
|
6421
5925
|
const hi = [];
|
|
@@ -6489,6 +5993,616 @@ function resolveTable(prog) {
|
|
|
6489
5993
|
return built;
|
|
6490
5994
|
}
|
|
6491
5995
|
|
|
5996
|
+
// src/analysis/gating.ts
|
|
5997
|
+
function childrenOf2(d) {
|
|
5998
|
+
switch (d.tag) {
|
|
5999
|
+
case "sequence":
|
|
6000
|
+
case "choice":
|
|
6001
|
+
return d.parsers;
|
|
6002
|
+
case "dispatch":
|
|
6003
|
+
return [
|
|
6004
|
+
d.selector,
|
|
6005
|
+
...d.cases.map((c) => c.parser),
|
|
6006
|
+
...d.matchers ? d.matchers.map((c) => c.parser) : [],
|
|
6007
|
+
...d.otherwise === void 0 ? [] : [d.otherwise]
|
|
6008
|
+
];
|
|
6009
|
+
case "sepBy":
|
|
6010
|
+
return [d.parser, d.separator];
|
|
6011
|
+
case "recover":
|
|
6012
|
+
return [d.parser, d.sentinel];
|
|
6013
|
+
case "scanTo":
|
|
6014
|
+
return [
|
|
6015
|
+
d.sentinel,
|
|
6016
|
+
...d.skip,
|
|
6017
|
+
...d.recoverAt === void 0 ? [] : [d.recoverAt],
|
|
6018
|
+
...d.stopAt === void 0 ? [] : [d.stopAt]
|
|
6019
|
+
];
|
|
6020
|
+
case "grammar":
|
|
6021
|
+
return d.triviaParser ? [d.parser, d.triviaParser] : [d.parser];
|
|
6022
|
+
case "routed":
|
|
6023
|
+
return d.fallback ? [d.fallback] : [];
|
|
6024
|
+
case "lines":
|
|
6025
|
+
return [d.prefix, d.body, ...d.first === void 0 ? [] : [d.first], ...d.lazy === void 0 ? [] : [d.lazy]];
|
|
6026
|
+
case "columns":
|
|
6027
|
+
return [];
|
|
6028
|
+
// A `lazy` is a REFERENCE, not a subtree. Descending through it would make
|
|
6029
|
+
// every rule's walk cover the whole reachable grammar — site paths become
|
|
6030
|
+
// nonsense, and a structural hash includes half the grammar. Treated as a
|
|
6031
|
+
// leaf, keyed by the rule name it refers to, which is also the right
|
|
6032
|
+
// semantics: two productions referencing `g.Ident` really do fill that slot
|
|
6033
|
+
// the same way.
|
|
6034
|
+
case "lazy":
|
|
6035
|
+
case "literal":
|
|
6036
|
+
case "regex":
|
|
6037
|
+
case "keywords":
|
|
6038
|
+
case "guard":
|
|
6039
|
+
case "adjacency":
|
|
6040
|
+
case "unknown":
|
|
6041
|
+
return [];
|
|
6042
|
+
default: {
|
|
6043
|
+
const rec = d;
|
|
6044
|
+
return rec.parser ? [rec.parser] : [];
|
|
6045
|
+
}
|
|
6046
|
+
}
|
|
6047
|
+
}
|
|
6048
|
+
var ch = (c) => c >= 32 && c < 127 ? `'${String.fromCharCode(c)}'` : `\\u${c}`;
|
|
6049
|
+
function firstSetToString(fs3) {
|
|
6050
|
+
if (fs3.kind === "any") return "ANY";
|
|
6051
|
+
if (fs3.kind === "empty") return "(empty)";
|
|
6052
|
+
return fs3.ranges.map((r) => r.lo === r.hi ? ch(r.lo) : `${ch(r.lo)}-${ch(r.hi)}`).join(",");
|
|
6053
|
+
}
|
|
6054
|
+
|
|
6055
|
+
// src/analysis/commitment.ts
|
|
6056
|
+
function mayFail(p, seen = /* @__PURE__ */ new Set()) {
|
|
6057
|
+
if (seen.has(p)) return true;
|
|
6058
|
+
seen.add(p);
|
|
6059
|
+
const d = p._def;
|
|
6060
|
+
switch (d.tag) {
|
|
6061
|
+
case "literal":
|
|
6062
|
+
return d.value.length > 0;
|
|
6063
|
+
case "trivia":
|
|
6064
|
+
return false;
|
|
6065
|
+
// `optional`/`many`/a min-0 `sepBy` swallow an ORDINARY failure — zero
|
|
6066
|
+
// repetitions is a match. They do NOT swallow a COMMITTED one: a dispatch
|
|
6067
|
+
// that has selected an arm and then failed inside it breaks out past every
|
|
6068
|
+
// enclosing repeat, straight to the fallible boundary. So these are total
|
|
6069
|
+
// exactly when their body cannot commit. (Measured: treating them as
|
|
6070
|
+
// unconditionally total left an extra zero-width leaf in
|
|
6071
|
+
// `BareInterpolatedSelector` on benchmark.less — a rollback the legacy
|
|
6072
|
+
// build fired and this one had deleted.)
|
|
6073
|
+
case "optional":
|
|
6074
|
+
case "many":
|
|
6075
|
+
return mayCommitFailure(d.parser);
|
|
6076
|
+
case "sepBy":
|
|
6077
|
+
return d.min >= 1 ? mayFail(d.parser, seen) : mayCommitFailure(d.parser) || mayCommitFailure(d.separator);
|
|
6078
|
+
case "oneOrMore":
|
|
6079
|
+
return mayFail(d.parser, seen);
|
|
6080
|
+
case "sequence":
|
|
6081
|
+
return d.parsers.some((x) => mayFail(x, seen));
|
|
6082
|
+
// Delegating wrappers: as fallible as what they wrap.
|
|
6083
|
+
case "node":
|
|
6084
|
+
case "transform":
|
|
6085
|
+
case "label":
|
|
6086
|
+
case "field":
|
|
6087
|
+
case "expect":
|
|
6088
|
+
case "withCtx":
|
|
6089
|
+
case "grammar":
|
|
6090
|
+
case "token":
|
|
6091
|
+
case "leaf":
|
|
6092
|
+
return mayFail(d.parser, seen);
|
|
6093
|
+
case "lazy": {
|
|
6094
|
+
try {
|
|
6095
|
+
return mayFail(d.thunk(), seen);
|
|
6096
|
+
} catch {
|
|
6097
|
+
return true;
|
|
6098
|
+
}
|
|
6099
|
+
}
|
|
6100
|
+
// An adjacency assertion is a TEST — failing is its whole job.
|
|
6101
|
+
case "adjacency":
|
|
6102
|
+
return true;
|
|
6103
|
+
default:
|
|
6104
|
+
return true;
|
|
6105
|
+
}
|
|
6106
|
+
}
|
|
6107
|
+
function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set(), triviaActive = true) {
|
|
6108
|
+
if (seen.has(p)) return false;
|
|
6109
|
+
seen.add(p);
|
|
6110
|
+
const d = p._def;
|
|
6111
|
+
switch (d.tag) {
|
|
6112
|
+
// Atomic / non-capturing-then-failing: a failure happens before any push.
|
|
6113
|
+
case "literal":
|
|
6114
|
+
case "regex":
|
|
6115
|
+
case "keywords":
|
|
6116
|
+
case "guard":
|
|
6117
|
+
// Adjacency probes with `_cap = 0` / no `commit()`: it cannot push anything.
|
|
6118
|
+
case "adjacency":
|
|
6119
|
+
case "not":
|
|
6120
|
+
// peek(): emitted under a non-capturing probe ctx and zero-width on both
|
|
6121
|
+
// outcomes, so it can never leave a partial capture behind.
|
|
6122
|
+
case "peek":
|
|
6123
|
+
case "trivia":
|
|
6124
|
+
case "token":
|
|
6125
|
+
case "leaf":
|
|
6126
|
+
case "scanTo":
|
|
6127
|
+
case "unknown":
|
|
6128
|
+
case "columns":
|
|
6129
|
+
return false;
|
|
6130
|
+
// A run's prefixes are probed detached; only its body can capture.
|
|
6131
|
+
case "lines":
|
|
6132
|
+
return mayLeavePartialCapture(d.body, seen, triviaActive);
|
|
6133
|
+
// node() captures into its own private buffers and rolls them back on
|
|
6134
|
+
// failure (emitNode restores _ctx.* and never pushes on the !ok path).
|
|
6135
|
+
case "node":
|
|
6136
|
+
return false;
|
|
6137
|
+
// choice/firstMatch already roll back each failed arm; on overall failure
|
|
6138
|
+
// nothing committed remains.
|
|
6139
|
+
case "choice":
|
|
6140
|
+
return false;
|
|
6141
|
+
case "dispatch":
|
|
6142
|
+
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);
|
|
6143
|
+
case "attempt":
|
|
6144
|
+
return false;
|
|
6145
|
+
// optional never fails; many/oneOrMore only "fail" with zero captured items.
|
|
6146
|
+
case "optional":
|
|
6147
|
+
case "many":
|
|
6148
|
+
case "oneOrMore":
|
|
6149
|
+
return false;
|
|
6150
|
+
// sepBy emits its own per-iteration rollback in emitSepBy.
|
|
6151
|
+
case "sepBy":
|
|
6152
|
+
return false;
|
|
6153
|
+
// A sequence is the real case: an earlier capturing term followed by a term
|
|
6154
|
+
// that can fail leaves the earlier captures buffered.
|
|
6155
|
+
//
|
|
6156
|
+
// BOTH halves of that sentence are load-bearing, and the second half is what
|
|
6157
|
+
// this walk exists to exploit. "Some earlier term captures" alone was the old
|
|
6158
|
+
// test, and it is true of very nearly every sequence in a real grammar — a
|
|
6159
|
+
// sequence almost always opens with a literal or a node. The rollback is only
|
|
6160
|
+
// reachable if something AFTER the capture can still fail; once the remainder
|
|
6161
|
+
// is total (`optional`/`many`/trivia/a min-0 `sepBy`), the sequence has no
|
|
6162
|
+
// failure path left to roll back from, and the save+restore is dead code.
|
|
6163
|
+
//
|
|
6164
|
+
// `captured` tracks whether anything is in the buffers yet as the scan moves
|
|
6165
|
+
// left to right. Two things put it there:
|
|
6166
|
+
// - a term that captures (`capturesLeaf`/`hasNodeDef`), and
|
|
6167
|
+
// - the inter-term TRIVIA scan, which under `capturing` pushes into
|
|
6168
|
+
// `_cstRawChildren`/`_cstTriviaLog` BEFORE the term at each boundary
|
|
6169
|
+
// i >= 1. `emitSeqValues` only rewinds that push on the term's SUCCESS
|
|
6170
|
+
// path (the "matched empty, so leave the whitespace out of the span"
|
|
6171
|
+
// branch); a term that FAILS breaks straight out with the trivia still
|
|
6172
|
+
// buffered, so from boundary 1 onward the buffers are dirty regardless of
|
|
6173
|
+
// what the earlier terms did.
|
|
6174
|
+
// Each term is also asked about itself: a nested sequence can leave its own
|
|
6175
|
+
// partial capture behind, and its terms are emitted inline into this same
|
|
6176
|
+
// block with no boundary of their own to roll them back.
|
|
6177
|
+
case "sequence": {
|
|
6178
|
+
const parts = d.parsers;
|
|
6179
|
+
let captured = false;
|
|
6180
|
+
for (let i = 0; i < parts.length; i++) {
|
|
6181
|
+
const part = parts[i];
|
|
6182
|
+
if (i > 0 && triviaActive) captured = true;
|
|
6183
|
+
if (captured && mayFail(part)) return true;
|
|
6184
|
+
if (mayLeavePartialCapture(part, seen, triviaActive)) return true;
|
|
6185
|
+
if (capturesLeaf(part) || hasNodeDef(part)) captured = true;
|
|
6186
|
+
}
|
|
6187
|
+
return false;
|
|
6188
|
+
}
|
|
6189
|
+
// Delegating wrappers: defer to the wrapped parser.
|
|
6190
|
+
case "transform":
|
|
6191
|
+
case "label":
|
|
6192
|
+
case "field":
|
|
6193
|
+
case "expect":
|
|
6194
|
+
case "withCtx":
|
|
6195
|
+
case "grammar":
|
|
6196
|
+
return mayLeavePartialCapture(d.parser, seen, triviaActive);
|
|
6197
|
+
case "recover":
|
|
6198
|
+
return mayLeavePartialCapture(d.parser, seen, triviaActive);
|
|
6199
|
+
case "lazy": {
|
|
6200
|
+
try {
|
|
6201
|
+
return mayLeavePartialCapture(d.thunk(), seen, triviaActive);
|
|
6202
|
+
} catch {
|
|
6203
|
+
return true;
|
|
6204
|
+
}
|
|
6205
|
+
}
|
|
6206
|
+
// Unknown shapes: be safe and keep the rollback.
|
|
6207
|
+
default:
|
|
6208
|
+
return true;
|
|
6209
|
+
}
|
|
6210
|
+
}
|
|
6211
|
+
function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
|
|
6212
|
+
if (seen.has(p)) return false;
|
|
6213
|
+
seen.add(p);
|
|
6214
|
+
const d = p._def;
|
|
6215
|
+
switch (d.tag) {
|
|
6216
|
+
case "literal":
|
|
6217
|
+
case "regex":
|
|
6218
|
+
case "keywords":
|
|
6219
|
+
case "node":
|
|
6220
|
+
case "token":
|
|
6221
|
+
case "routed":
|
|
6222
|
+
case "leaf":
|
|
6223
|
+
return true;
|
|
6224
|
+
case "not":
|
|
6225
|
+
case "peek":
|
|
6226
|
+
case "guard":
|
|
6227
|
+
case "adjacency":
|
|
6228
|
+
case "trivia":
|
|
6229
|
+
case "unknown":
|
|
6230
|
+
return false;
|
|
6231
|
+
case "sequence":
|
|
6232
|
+
case "choice":
|
|
6233
|
+
return d.parsers.some((x) => capturesLeaf(x, seen));
|
|
6234
|
+
case "dispatch":
|
|
6235
|
+
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);
|
|
6236
|
+
case "sepBy":
|
|
6237
|
+
return capturesLeaf(d.parser, seen) || capturesLeaf(d.separator, seen);
|
|
6238
|
+
case "many":
|
|
6239
|
+
case "oneOrMore":
|
|
6240
|
+
case "optional":
|
|
6241
|
+
case "attempt":
|
|
6242
|
+
case "transform":
|
|
6243
|
+
case "label":
|
|
6244
|
+
case "field":
|
|
6245
|
+
case "expect":
|
|
6246
|
+
case "withCtx":
|
|
6247
|
+
case "grammar":
|
|
6248
|
+
case "recover":
|
|
6249
|
+
return capturesLeaf(d.parser, seen);
|
|
6250
|
+
case "scanTo":
|
|
6251
|
+
return true;
|
|
6252
|
+
case "lines":
|
|
6253
|
+
return capturesLeaf(d.body, seen);
|
|
6254
|
+
case "columns":
|
|
6255
|
+
return true;
|
|
6256
|
+
case "lazy": {
|
|
6257
|
+
try {
|
|
6258
|
+
return capturesLeaf(d.thunk(), seen);
|
|
6259
|
+
} catch {
|
|
6260
|
+
return true;
|
|
6261
|
+
}
|
|
6262
|
+
}
|
|
6263
|
+
default:
|
|
6264
|
+
return true;
|
|
6265
|
+
}
|
|
6266
|
+
}
|
|
6267
|
+
function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
6268
|
+
if (seen.has(p)) return false;
|
|
6269
|
+
seen.add(p);
|
|
6270
|
+
const d = p._def;
|
|
6271
|
+
switch (d.tag) {
|
|
6272
|
+
case "node":
|
|
6273
|
+
return true;
|
|
6274
|
+
case "lazy": {
|
|
6275
|
+
try {
|
|
6276
|
+
return hasNodeDef(d.thunk(), seen);
|
|
6277
|
+
} catch {
|
|
6278
|
+
return false;
|
|
6279
|
+
}
|
|
6280
|
+
}
|
|
6281
|
+
case "grammar":
|
|
6282
|
+
case "trivia":
|
|
6283
|
+
case "token":
|
|
6284
|
+
case "leaf":
|
|
6285
|
+
case "label":
|
|
6286
|
+
case "field":
|
|
6287
|
+
case "optional":
|
|
6288
|
+
case "many":
|
|
6289
|
+
case "oneOrMore":
|
|
6290
|
+
case "not":
|
|
6291
|
+
case "peek":
|
|
6292
|
+
case "transform":
|
|
6293
|
+
return hasNodeDef(d.parser, seen);
|
|
6294
|
+
case "sequence":
|
|
6295
|
+
case "choice":
|
|
6296
|
+
return d.parsers.some((x) => hasNodeDef(x, seen));
|
|
6297
|
+
case "dispatch":
|
|
6298
|
+
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);
|
|
6299
|
+
case "sepBy":
|
|
6300
|
+
return hasNodeDef(d.parser, seen) || hasNodeDef(d.separator, seen);
|
|
6301
|
+
case "scanTo":
|
|
6302
|
+
return hasNodeDef(d.sentinel, seen) || d.skip.some((x) => hasNodeDef(x, seen)) || d.recoverAt !== void 0 && hasNodeDef(d.recoverAt, seen) || d.stopAt !== void 0 && hasNodeDef(d.stopAt, seen);
|
|
6303
|
+
case "lines":
|
|
6304
|
+
return hasNodeDef(d.body, seen);
|
|
6305
|
+
case "recover":
|
|
6306
|
+
return hasNodeDef(d.parser, seen) || hasNodeDef(d.sentinel, seen);
|
|
6307
|
+
case "expect":
|
|
6308
|
+
return hasNodeDef(d.parser, seen);
|
|
6309
|
+
case "withCtx":
|
|
6310
|
+
return hasNodeDef(d.parser, seen);
|
|
6311
|
+
default:
|
|
6312
|
+
return false;
|
|
6313
|
+
}
|
|
6314
|
+
}
|
|
6315
|
+
function hasDirectBuildDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
6316
|
+
if (seen.has(p)) return false;
|
|
6317
|
+
seen.add(p);
|
|
6318
|
+
const d = p._def;
|
|
6319
|
+
switch (d.tag) {
|
|
6320
|
+
case "node":
|
|
6321
|
+
return d.build !== void 0 || hasDirectBuildDef(d.parser, seen);
|
|
6322
|
+
case "lazy": {
|
|
6323
|
+
try {
|
|
6324
|
+
return hasDirectBuildDef(d.thunk(), seen);
|
|
6325
|
+
} catch {
|
|
6326
|
+
return false;
|
|
6327
|
+
}
|
|
6328
|
+
}
|
|
6329
|
+
case "grammar":
|
|
6330
|
+
case "trivia":
|
|
6331
|
+
case "token":
|
|
6332
|
+
case "leaf":
|
|
6333
|
+
case "label":
|
|
6334
|
+
case "field":
|
|
6335
|
+
case "optional":
|
|
6336
|
+
case "many":
|
|
6337
|
+
case "oneOrMore":
|
|
6338
|
+
case "attempt":
|
|
6339
|
+
case "not":
|
|
6340
|
+
case "peek":
|
|
6341
|
+
case "withCtx":
|
|
6342
|
+
case "expect":
|
|
6343
|
+
case "transform":
|
|
6344
|
+
return hasDirectBuildDef(d.parser, seen);
|
|
6345
|
+
case "sequence":
|
|
6346
|
+
case "choice":
|
|
6347
|
+
return d.parsers.some((x) => hasDirectBuildDef(x, seen));
|
|
6348
|
+
case "dispatch":
|
|
6349
|
+
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);
|
|
6350
|
+
case "sepBy":
|
|
6351
|
+
return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.separator, seen);
|
|
6352
|
+
case "scanTo":
|
|
6353
|
+
return hasDirectBuildDef(d.sentinel, seen) || d.skip.some((x) => hasDirectBuildDef(x, seen)) || d.recoverAt !== void 0 && hasDirectBuildDef(d.recoverAt, seen) || d.stopAt !== void 0 && hasDirectBuildDef(d.stopAt, seen);
|
|
6354
|
+
case "lines":
|
|
6355
|
+
return hasDirectBuildDef(d.body, seen);
|
|
6356
|
+
case "recover":
|
|
6357
|
+
return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.sentinel, seen);
|
|
6358
|
+
case "routed":
|
|
6359
|
+
return d.fallback ? hasDirectBuildDef(d.fallback, seen) : false;
|
|
6360
|
+
default:
|
|
6361
|
+
return false;
|
|
6362
|
+
}
|
|
6363
|
+
}
|
|
6364
|
+
function mayCommitFailure(p, resolve3, memo = /* @__PURE__ */ new Map()) {
|
|
6365
|
+
return reachesMarked(p, (node2) => commitFailureSuccessors(node2, resolve3), memo);
|
|
6366
|
+
}
|
|
6367
|
+
var NO_EDGES = [];
|
|
6368
|
+
function commitFailureSuccessors(p, resolve3) {
|
|
6369
|
+
const d = p._def;
|
|
6370
|
+
switch (d.tag) {
|
|
6371
|
+
case "dispatch":
|
|
6372
|
+
case "unknown":
|
|
6373
|
+
return true;
|
|
6374
|
+
case "choice":
|
|
6375
|
+
case "sequence":
|
|
6376
|
+
return d.parsers;
|
|
6377
|
+
// A contained transaction reports every failure uncommitted.
|
|
6378
|
+
case "attempt":
|
|
6379
|
+
return d.contain === true ? NO_EDGES : [d.parser];
|
|
6380
|
+
case "many":
|
|
6381
|
+
case "oneOrMore":
|
|
6382
|
+
case "optional":
|
|
6383
|
+
case "transform":
|
|
6384
|
+
case "label":
|
|
6385
|
+
case "field":
|
|
6386
|
+
case "grammar":
|
|
6387
|
+
case "node":
|
|
6388
|
+
case "token":
|
|
6389
|
+
case "leaf":
|
|
6390
|
+
case "withCtx":
|
|
6391
|
+
return [d.parser];
|
|
6392
|
+
case "sepBy":
|
|
6393
|
+
return [d.parser, d.separator];
|
|
6394
|
+
case "scanTo":
|
|
6395
|
+
return [
|
|
6396
|
+
d.sentinel,
|
|
6397
|
+
...d.skip,
|
|
6398
|
+
...d.recoverAt === void 0 ? NO_EDGES : [d.recoverAt],
|
|
6399
|
+
...d.stopAt === void 0 ? NO_EDGES : [d.stopAt]
|
|
6400
|
+
];
|
|
6401
|
+
// A run's prefixes are probed detached; a committed failure reaches it only from its body.
|
|
6402
|
+
case "lines":
|
|
6403
|
+
return [d.body];
|
|
6404
|
+
case "lazy": {
|
|
6405
|
+
try {
|
|
6406
|
+
return [d.thunk()];
|
|
6407
|
+
} catch {
|
|
6408
|
+
const name = p._ruleName;
|
|
6409
|
+
const target = name === void 0 ? void 0 : resolve3?.(name);
|
|
6410
|
+
return target === void 0 ? true : [target];
|
|
6411
|
+
}
|
|
6412
|
+
}
|
|
6413
|
+
default:
|
|
6414
|
+
return NO_EDGES;
|
|
6415
|
+
}
|
|
6416
|
+
}
|
|
6417
|
+
function reachesMarked(root, successors, memo) {
|
|
6418
|
+
const known = memo.get(root);
|
|
6419
|
+
if (known !== void 0) return known;
|
|
6420
|
+
const order = /* @__PURE__ */ new Map();
|
|
6421
|
+
const low = [];
|
|
6422
|
+
const found = [];
|
|
6423
|
+
const stack = [];
|
|
6424
|
+
const visit = (node2) => {
|
|
6425
|
+
const at = low.length;
|
|
6426
|
+
order.set(node2, at);
|
|
6427
|
+
low.push(at);
|
|
6428
|
+
found.push(false);
|
|
6429
|
+
stack.push(node2);
|
|
6430
|
+
const next = successors(node2);
|
|
6431
|
+
if (next === true) found[at] = true;
|
|
6432
|
+
else {
|
|
6433
|
+
for (const child of next) {
|
|
6434
|
+
if (found[at]) break;
|
|
6435
|
+
const hit = memo.get(child);
|
|
6436
|
+
if (hit !== void 0) {
|
|
6437
|
+
if (hit) found[at] = true;
|
|
6438
|
+
continue;
|
|
6439
|
+
}
|
|
6440
|
+
const seen = order.get(child);
|
|
6441
|
+
if (seen !== void 0) {
|
|
6442
|
+
if (seen < low[at]) low[at] = seen;
|
|
6443
|
+
continue;
|
|
6444
|
+
}
|
|
6445
|
+
const k = visit(child);
|
|
6446
|
+
if (low[k] < low[at]) low[at] = low[k];
|
|
6447
|
+
if (found[k]) found[at] = true;
|
|
6448
|
+
}
|
|
6449
|
+
}
|
|
6450
|
+
if (low[at] === at) {
|
|
6451
|
+
const answer = found[at];
|
|
6452
|
+
let member;
|
|
6453
|
+
do {
|
|
6454
|
+
member = stack.pop();
|
|
6455
|
+
memo.set(member, answer);
|
|
6456
|
+
} while (member !== node2);
|
|
6457
|
+
}
|
|
6458
|
+
return at;
|
|
6459
|
+
};
|
|
6460
|
+
return found[visit(root)];
|
|
6461
|
+
}
|
|
6462
|
+
function hasSemanticReduction(roots, externalRefs) {
|
|
6463
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6464
|
+
const visit = (parser2) => {
|
|
6465
|
+
if (seen.has(parser2)) return false;
|
|
6466
|
+
seen.add(parser2);
|
|
6467
|
+
const def = parser2._def;
|
|
6468
|
+
if (def.tag === "transform" && !def.recognitionOnly) return true;
|
|
6469
|
+
if (def.tag === "choice" && def.gates.some(Boolean)) return true;
|
|
6470
|
+
if (def.tag === "guard" || def.tag === "withCtx") return true;
|
|
6471
|
+
if (def.tag === "node" && def.build !== void 0) return true;
|
|
6472
|
+
if (def.tag === "lazy") {
|
|
6473
|
+
if (externalRefs?.has(parser2)) return false;
|
|
6474
|
+
try {
|
|
6475
|
+
return visit(def.thunk());
|
|
6476
|
+
} catch {
|
|
6477
|
+
return true;
|
|
6478
|
+
}
|
|
6479
|
+
}
|
|
6480
|
+
return childrenOf2(def).some(visit);
|
|
6481
|
+
};
|
|
6482
|
+
return roots.some(visit);
|
|
6483
|
+
}
|
|
6484
|
+
function classifyRuleMap(ruleMap) {
|
|
6485
|
+
const externalRefs = /* @__PURE__ */ new Set();
|
|
6486
|
+
const scanned = /* @__PURE__ */ new Set();
|
|
6487
|
+
const scanExternal = (p) => {
|
|
6488
|
+
if (scanned.has(p)) return;
|
|
6489
|
+
scanned.add(p);
|
|
6490
|
+
const def = p._def;
|
|
6491
|
+
if (def.tag === "lazy") {
|
|
6492
|
+
let resolved;
|
|
6493
|
+
try {
|
|
6494
|
+
resolved = def.thunk();
|
|
6495
|
+
} catch {
|
|
6496
|
+
resolved = void 0;
|
|
6497
|
+
}
|
|
6498
|
+
if (resolved === void 0) {
|
|
6499
|
+
if (p._ruleName) externalRefs.add(p);
|
|
6500
|
+
return;
|
|
6501
|
+
}
|
|
6502
|
+
scanExternal(resolved);
|
|
6503
|
+
return;
|
|
6504
|
+
}
|
|
6505
|
+
for (const child of childrenOf2(def)) scanExternal(child);
|
|
6506
|
+
};
|
|
6507
|
+
for (const [, rule] of ruleMap) scanExternal(rule);
|
|
6508
|
+
return {
|
|
6509
|
+
hasDirectBuilders: ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
|
|
6510
|
+
isRecognitionOnly: !hasSemanticReduction(ruleMap.map(([, rule]) => rule), externalRefs)
|
|
6511
|
+
};
|
|
6512
|
+
}
|
|
6513
|
+
|
|
6514
|
+
// src/table/ops.ts
|
|
6515
|
+
var OP_LIT = 1;
|
|
6516
|
+
var OP_RX = 2;
|
|
6517
|
+
var OP_SEQ = 3;
|
|
6518
|
+
var OP_SEQV = 4;
|
|
6519
|
+
var OP_CHOICE = 5;
|
|
6520
|
+
var OP_REP = 6;
|
|
6521
|
+
var OP_REPV = 7;
|
|
6522
|
+
var OP_OPT = 8;
|
|
6523
|
+
var OP_XFORM = 9;
|
|
6524
|
+
var OP_NODE = 10;
|
|
6525
|
+
var OP_RULE = 11;
|
|
6526
|
+
var OP_GATE = 12;
|
|
6527
|
+
var OP_NOT = 13;
|
|
6528
|
+
var OP_PEEK = 14;
|
|
6529
|
+
var OP_LEAF = 15;
|
|
6530
|
+
var OP_EMPTY = 16;
|
|
6531
|
+
var OP_LIT_TRACK = 17;
|
|
6532
|
+
var OP_RX_TRACK = 18;
|
|
6533
|
+
var OP_NODE_TRACK = 19;
|
|
6534
|
+
var OP_SCOPE = 20;
|
|
6535
|
+
var OP_EXPECT = 21;
|
|
6536
|
+
var OP_SEQX = 22;
|
|
6537
|
+
var OP_SCAN = 23;
|
|
6538
|
+
var OP_FIELD = 24;
|
|
6539
|
+
var OP_LIT_CI = 27;
|
|
6540
|
+
var OP_LIT_CI_TRACK = 28;
|
|
6541
|
+
var OP_TOKEN = 29;
|
|
6542
|
+
var OP_SCOPE_CAP = 30;
|
|
6543
|
+
var OP_WITHCTX = 31;
|
|
6544
|
+
var OP_GUARD = 32;
|
|
6545
|
+
var OP_ADJ = 33;
|
|
6546
|
+
var OP_GREEDY = 34;
|
|
6547
|
+
var OP_REJECT = 35;
|
|
6548
|
+
var OP_ARMGATE = 36;
|
|
6549
|
+
var OP_LIVE = 37;
|
|
6550
|
+
var OP_ATTEMPT = 38;
|
|
6551
|
+
var OP_LABEL = 39;
|
|
6552
|
+
var OP_COV = 40;
|
|
6553
|
+
var OP_SCOPE_PLAIN = 41;
|
|
6554
|
+
var OP_LEX_BODY = 42;
|
|
6555
|
+
var OP_LEX_PROGRAM = 43;
|
|
6556
|
+
var OP_SOURCE_LEAF = 44;
|
|
6557
|
+
var OP_DISPATCH = 25;
|
|
6558
|
+
var OP_ROUTED = 26;
|
|
6559
|
+
var OP_NAMES = {
|
|
6560
|
+
[OP_LIT]: "LIT",
|
|
6561
|
+
[OP_RX]: "RX",
|
|
6562
|
+
[OP_SEQ]: "SEQ",
|
|
6563
|
+
[OP_SEQV]: "SEQV",
|
|
6564
|
+
[OP_CHOICE]: "CHOICE",
|
|
6565
|
+
[OP_REP]: "REP",
|
|
6566
|
+
[OP_REPV]: "REPV",
|
|
6567
|
+
[OP_OPT]: "OPT",
|
|
6568
|
+
[OP_XFORM]: "XFORM",
|
|
6569
|
+
[OP_NODE]: "NODE",
|
|
6570
|
+
[OP_RULE]: "RULE",
|
|
6571
|
+
[OP_GATE]: "GATE",
|
|
6572
|
+
[OP_NOT]: "NOT",
|
|
6573
|
+
[OP_PEEK]: "PEEK",
|
|
6574
|
+
[OP_LEAF]: "LEAF",
|
|
6575
|
+
[OP_SOURCE_LEAF]: "SOURCE_LEAF",
|
|
6576
|
+
[OP_EMPTY]: "EMPTY",
|
|
6577
|
+
[OP_LIT_TRACK]: "LIT_TRACK",
|
|
6578
|
+
[OP_RX_TRACK]: "RX_TRACK",
|
|
6579
|
+
[OP_NODE_TRACK]: "NODE_TRACK",
|
|
6580
|
+
[OP_SCOPE]: "SCOPE",
|
|
6581
|
+
[OP_EXPECT]: "EXPECT",
|
|
6582
|
+
[OP_SEQX]: "SEQX",
|
|
6583
|
+
[OP_SCAN]: "SCAN",
|
|
6584
|
+
[OP_FIELD]: "FIELD",
|
|
6585
|
+
[OP_LIT_CI]: "LIT_CI",
|
|
6586
|
+
[OP_LIT_CI_TRACK]: "LIT_CI_TRACK",
|
|
6587
|
+
[OP_DISPATCH]: "DISPATCH",
|
|
6588
|
+
[OP_ROUTED]: "ROUTED",
|
|
6589
|
+
[OP_TOKEN]: "TOKEN",
|
|
6590
|
+
[OP_SCOPE_CAP]: "SCOPE_CAP",
|
|
6591
|
+
[OP_WITHCTX]: "WITHCTX",
|
|
6592
|
+
[OP_GUARD]: "GUARD",
|
|
6593
|
+
[OP_ADJ]: "ADJ",
|
|
6594
|
+
[OP_GREEDY]: "GREEDY",
|
|
6595
|
+
[OP_REJECT]: "REJECT",
|
|
6596
|
+
[OP_ARMGATE]: "ARMGATE",
|
|
6597
|
+
[OP_LIVE]: "LIVE",
|
|
6598
|
+
[OP_ATTEMPT]: "ATTEMPT",
|
|
6599
|
+
[OP_LABEL]: "LABEL",
|
|
6600
|
+
[OP_COV]: "COV",
|
|
6601
|
+
[OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
|
|
6602
|
+
[OP_LEX_BODY]: "LEX_BODY",
|
|
6603
|
+
[OP_LEX_PROGRAM]: "LEX_PROGRAM"
|
|
6604
|
+
};
|
|
6605
|
+
|
|
6492
6606
|
// src/compiler/direct-projection.ts
|
|
6493
6607
|
function directArrayProjection(fn, fnSrc, arity) {
|
|
6494
6608
|
let source = fnSrc;
|
|
@@ -7369,6 +7483,7 @@ var Encoder = class {
|
|
|
7369
7483
|
case "expect":
|
|
7370
7484
|
case "recover":
|
|
7371
7485
|
case "scanTo":
|
|
7486
|
+
case "lines":
|
|
7372
7487
|
case "unknown":
|
|
7373
7488
|
return true;
|
|
7374
7489
|
case "lazy": {
|
|
@@ -7385,6 +7500,33 @@ var Encoder = class {
|
|
|
7385
7500
|
return childrenOf2(def);
|
|
7386
7501
|
}
|
|
7387
7502
|
}
|
|
7503
|
+
/**
|
|
7504
|
+
* THE FIRST-CHARACTER GATE OF AN `optional`, `not` OR `peek` CHILD.
|
|
7505
|
+
*
|
|
7506
|
+
* A non-nullable child cannot match at a character outside its first set, so
|
|
7507
|
+
* the wrapper's outcome there is already decided: `optional` yields `null`,
|
|
7508
|
+
* `not` succeeds, `peek` fails with its own set. The interpreter's `optional`
|
|
7509
|
+
* makes that test itself (`repeat.ts` `startsFirstSet`); the table entered the
|
|
7510
|
+
* child — a rollback mark, the call, the child's own failure — to learn it.
|
|
7511
|
+
*
|
|
7512
|
+
* The gate is an `OP_GATE` row around the child, so every engine runs it
|
|
7513
|
+
* unchanged, a probe or tolerant parse forwards through it as for a node's
|
|
7514
|
+
* gate, and the wrapper's row keeps its layout. The engines test the class
|
|
7515
|
+
* before taking the wrapper's mark. The first set is resolved through
|
|
7516
|
+
* `winners`, the analysis a choice arm's gate uses, so a composed rule's set
|
|
7517
|
+
* is the merged one. A scalar `not` child stays bare: `scalarTerminalNotChild`
|
|
7518
|
+
* already reduces it to one recognizer call.
|
|
7519
|
+
*/
|
|
7520
|
+
lookaheadGate(p, child) {
|
|
7521
|
+
const op = this.code[child];
|
|
7522
|
+
if (op === OP_GATE || op === OP_LIT || op === OP_LIT_CI || op === OP_LIT_TRACK || op === OP_LIT_CI_TRACK || op === OP_RX || op === OP_RX_TRACK) return child;
|
|
7523
|
+
const rr = this.refResolver();
|
|
7524
|
+
if (matchesEmpty(p, /* @__PURE__ */ new Set(), rr)) return child;
|
|
7525
|
+
const cls = this.charClass(firstSetOf(p, /* @__PURE__ */ new Set(), rr, this.activeTrivia));
|
|
7526
|
+
if (cls < 0) return child;
|
|
7527
|
+
const e = deriveExpected(p);
|
|
7528
|
+
return this.emit(OP_GATE, cls, child, this.expected(e.length > 0 ? e : [p._tag]));
|
|
7529
|
+
}
|
|
7388
7530
|
/** A first set becomes a char class string, or −1 for `any`. */
|
|
7389
7531
|
charClass(fs3) {
|
|
7390
7532
|
if (fs3.kind !== "ranges" || fs3.ranges.length === 0) return -1;
|
|
@@ -7396,12 +7538,19 @@ var Encoder = class {
|
|
|
7396
7538
|
this.ccIndex.set(spec, i);
|
|
7397
7539
|
return i;
|
|
7398
7540
|
}
|
|
7399
|
-
/**
|
|
7400
|
-
*
|
|
7401
|
-
|
|
7402
|
-
|
|
7403
|
-
|
|
7404
|
-
|
|
7541
|
+
/**
|
|
7542
|
+
* The first set a node's or an attempt's fail-fast gate tests. A bare
|
|
7543
|
+
* cross-rule ref resolves through `winners` (a compose OVERRIDE may widen
|
|
7544
|
+
* it). Any other body keeps its construction-time `_meta.firstSet`, except
|
|
7545
|
+
* where that is `any`: under `compose()` a body that reaches a rule of
|
|
7546
|
+
* another piece is built before that rule exists, so its cached set is
|
|
7547
|
+
* `any` and the node got NO gate (jess's `CompoundSelector` was entered at
|
|
7548
|
+
* `{`, `Call` at `}`). The resolved set is the one a choice arm's gate uses,
|
|
7549
|
+
* over the final merged map.
|
|
7550
|
+
*/
|
|
7551
|
+
gateFirstSet(p) {
|
|
7552
|
+
const cached = p._meta.firstSet;
|
|
7553
|
+
return p._def.tag === "lazy" || cached.kind === "any" ? firstSetOf(p, /* @__PURE__ */ new Set(), this.refResolver(), this.activeTrivia) : cached;
|
|
7405
7554
|
}
|
|
7406
7555
|
/**
|
|
7407
7556
|
* Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
|
|
@@ -7589,6 +7738,18 @@ var Encoder = class {
|
|
|
7589
7738
|
open: bal.open,
|
|
7590
7739
|
close: bal.close
|
|
7591
7740
|
}));
|
|
7741
|
+
if (d.tag === "lines") {
|
|
7742
|
+
return this.emit(OP_SCAN, this.scanSlot({
|
|
7743
|
+
kind: 2,
|
|
7744
|
+
flags: 0,
|
|
7745
|
+
skip: [],
|
|
7746
|
+
prefix: this.subtree(d.prefix),
|
|
7747
|
+
body: this.subtree(d.body),
|
|
7748
|
+
...d.first === void 0 ? {} : { first: this.subtree(d.first) },
|
|
7749
|
+
...d.lazy === void 0 ? {} : { lazy: this.subtree(d.lazy) }
|
|
7750
|
+
}));
|
|
7751
|
+
}
|
|
7752
|
+
if (d.tag === "columns") return this.emit(OP_SCAN, this.scanSlot({ kind: 3, flags: 0, skip: [], n: d.n }));
|
|
7592
7753
|
if (d.tag === "scanTo") {
|
|
7593
7754
|
const sentDef = d.sentinel._def;
|
|
7594
7755
|
return this.emit(OP_SCAN, this.scanSlot({
|
|
@@ -7694,6 +7855,12 @@ var Encoder = class {
|
|
|
7694
7855
|
if (transactionalFirst[i] !== void 0) classes[i] = -1;
|
|
7695
7856
|
}
|
|
7696
7857
|
}
|
|
7858
|
+
if (d.gates.some((g) => g !== null && g !== void 0) && !dispatchIsExclusive(classes, this.cc)) {
|
|
7859
|
+
for (let k = 0; k < classes.length; k++) {
|
|
7860
|
+
const gate2 = d.gates[order[k]];
|
|
7861
|
+
if (gate2 !== null && gate2 !== void 0) classes[k] = -1;
|
|
7862
|
+
}
|
|
7863
|
+
}
|
|
7697
7864
|
const dispIdx = this.disp.length;
|
|
7698
7865
|
this.disp.push(classes);
|
|
7699
7866
|
let rollbackMask = kids.length > 31 ? -1 : 0;
|
|
@@ -7723,7 +7890,7 @@ var Encoder = class {
|
|
|
7723
7890
|
case "oneOrMore": {
|
|
7724
7891
|
const child = this.node(d.parser).ip;
|
|
7725
7892
|
const rr = this.refResolver();
|
|
7726
|
-
const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.
|
|
7893
|
+
const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.charClass(firstSetOf(d.parser, /* @__PURE__ */ new Set(), rr, this.activeTrivia));
|
|
7727
7894
|
const op = d.valueUnused ? OP_REPV : OP_REP;
|
|
7728
7895
|
const min = d.tag === "many" ? 0 : d.min;
|
|
7729
7896
|
return this.rec ? this.emit(op, child, min, d.max ?? -1, -1, 0, this.expected(deriveExpected(d.parser)), itemClass) : this.emit(op, child, min, d.max ?? -1, -1, 0);
|
|
@@ -7747,7 +7914,7 @@ var Encoder = class {
|
|
|
7747
7914
|
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);
|
|
7748
7915
|
}
|
|
7749
7916
|
case "optional": {
|
|
7750
|
-
const head = this.emit(OP_OPT, this.node(d.parser).ip);
|
|
7917
|
+
const head = this.emit(OP_OPT, this.lookaheadGate(d.parser, this.node(d.parser).ip));
|
|
7751
7918
|
if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(head);
|
|
7752
7919
|
return head;
|
|
7753
7920
|
}
|
|
@@ -7795,8 +7962,8 @@ var Encoder = class {
|
|
|
7795
7962
|
// every CST node, so this is load-bearing, not reflection trivia.
|
|
7796
7963
|
d.tags === void 0 ? -1 : this.constant(d.tags)
|
|
7797
7964
|
);
|
|
7798
|
-
if (matchesEmpty(d.parser)) return body;
|
|
7799
|
-
const fs3 =
|
|
7965
|
+
if (matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return body;
|
|
7966
|
+
const fs3 = this.gateFirstSet(d.parser);
|
|
7800
7967
|
if (fs3.kind === "any") return body;
|
|
7801
7968
|
const cls = this.charClass(fs3);
|
|
7802
7969
|
if (cls < 0) return body;
|
|
@@ -7888,7 +8055,7 @@ var Encoder = class {
|
|
|
7888
8055
|
// other engine reported `['not(literal)']`. It hid because `expected` is a
|
|
7889
8056
|
// TOP-LEVEL field on `RunResult` and is NOT part of the identity digest.
|
|
7890
8057
|
case "not":
|
|
7891
|
-
return this.emit(OP_NOT, this.node(d.parser).ip, this.expected(assertionFailureExpected(false, d.parser._tag)));
|
|
8058
|
+
return this.emit(OP_NOT, this.lookaheadGate(d.parser, this.node(d.parser).ip), this.expected(assertionFailureExpected(false, d.parser._tag)));
|
|
7892
8059
|
case "guard":
|
|
7893
8060
|
return this.emit(OP_GUARD, this.fn(d.predicate, d.predSrc ?? null), this.expected(["gate"]));
|
|
7894
8061
|
case "adjacency":
|
|
@@ -7909,14 +8076,14 @@ var Encoder = class {
|
|
|
7909
8076
|
return this.emit(OP_WITHCTX, this.constant(d.extra), this.node(d.parser).ip);
|
|
7910
8077
|
}
|
|
7911
8078
|
case "peek":
|
|
7912
|
-
return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected(assertionFailureExpected(true, d.parser._tag)));
|
|
8079
|
+
return this.emit(OP_PEEK, this.lookaheadGate(d.parser, this.node(d.parser).ip), this.expected(assertionFailureExpected(true, d.parser._tag)));
|
|
7913
8080
|
// A TRANSACTION IS A ROW. See `OP_ATTEMPT` for why the transparent
|
|
7914
8081
|
// lowering was correct only for a choice arm.
|
|
7915
8082
|
case "attempt": {
|
|
7916
8083
|
const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip, d.contain === true ? 1 : 0);
|
|
7917
8084
|
if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
|
|
7918
|
-
const fs3 =
|
|
7919
|
-
if (fs3.kind === "any" || matchesEmpty(d.parser)) return inner;
|
|
8085
|
+
const fs3 = this.gateFirstSet(d.parser);
|
|
8086
|
+
if (fs3.kind === "any" || matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return inner;
|
|
7920
8087
|
const cls = this.charClass(fs3);
|
|
7921
8088
|
if (cls < 0) return inner;
|
|
7922
8089
|
const e = deriveExpected(d.parser);
|
|
@@ -8035,12 +8202,7 @@ var Encoder = class {
|
|
|
8035
8202
|
};
|
|
8036
8203
|
const seen = /* @__PURE__ */ new Set();
|
|
8037
8204
|
const refs = [];
|
|
8038
|
-
for (const s of this.scans)
|
|
8039
|
-
if (s.sentinel !== void 0) refs.push(s.sentinel);
|
|
8040
|
-
if (s.recoverAt !== void 0) refs.push(s.recoverAt);
|
|
8041
|
-
if (s.stopAt !== void 0) refs.push(s.stopAt);
|
|
8042
|
-
refs.push(...s.skip);
|
|
8043
|
-
}
|
|
8205
|
+
for (const s of this.scans) refs.push(...scanRefs(s));
|
|
8044
8206
|
for (const set of this.scanSkipSets) refs.push(...set);
|
|
8045
8207
|
const stack = [...Object.values(this.rules), ...refs.map((r) => r[0])];
|
|
8046
8208
|
while (stack.length > 0) {
|
|
@@ -8060,7 +8222,11 @@ var Encoder = class {
|
|
|
8060
8222
|
skip: s.skip.map(res),
|
|
8061
8223
|
...s.sentinel === void 0 ? {} : { sentinel: res(s.sentinel) },
|
|
8062
8224
|
...s.recoverAt === void 0 ? {} : { recoverAt: res(s.recoverAt) },
|
|
8063
|
-
...s.stopAt === void 0 ? {} : { stopAt: res(s.stopAt) }
|
|
8225
|
+
...s.stopAt === void 0 ? {} : { stopAt: res(s.stopAt) },
|
|
8226
|
+
...s.prefix === void 0 ? {} : { prefix: res(s.prefix) },
|
|
8227
|
+
...s.body === void 0 ? {} : { body: res(s.body) },
|
|
8228
|
+
...s.first === void 0 ? {} : { first: res(s.first) },
|
|
8229
|
+
...s.lazy === void 0 ? {} : { lazy: res(s.lazy) }
|
|
8064
8230
|
}));
|
|
8065
8231
|
this.scanSkipSets = this.scanSkipSets.map((set) => set.map(res));
|
|
8066
8232
|
}
|
|
@@ -8902,7 +9068,7 @@ function emitShapeMatch(shape, start, mint, ind, firstChar) {
|
|
|
8902
9068
|
if (shape.kind === "alt") {
|
|
8903
9069
|
const okV = mint("_ok");
|
|
8904
9070
|
const endV2 = mint("_end");
|
|
8905
|
-
const
|
|
9071
|
+
const lines2 = [`${ind}let ${okV} = false`, `${ind}let ${endV2} = ${start}`];
|
|
8906
9072
|
if (shape.arms.length >= 2 && shape.arms.every((a) => a.kind === "litFold" && a.open.length >= 1)) {
|
|
8907
9073
|
const groups = /* @__PURE__ */ new Map();
|
|
8908
9074
|
for (const a of shape.arms) {
|
|
@@ -8911,60 +9077,60 @@ function emitShapeMatch(shape, start, mint, ind, firstChar) {
|
|
|
8911
9077
|
const lower = f >= 65 && f <= 90 ? f + 32 : f;
|
|
8912
9078
|
(groups.get(lower) ?? groups.set(lower, []).get(lower)).push(open);
|
|
8913
9079
|
}
|
|
8914
|
-
|
|
9080
|
+
lines2.push(`${ind}if (${start} < input.length) switch (${codeAt(start, firstChar)}) {`);
|
|
8915
9081
|
for (const [lower, arms] of groups) {
|
|
8916
9082
|
const labels = lower >= 97 && lower <= 122 ? `case ${lower}: case ${lower - 32}:` : `case ${lower}:`;
|
|
8917
|
-
|
|
9083
|
+
lines2.push(`${ind} ${labels} {`);
|
|
8918
9084
|
for (const open of arms) {
|
|
8919
9085
|
const tail = open.slice(1).map((cp, i) => foldEq(`input.charCodeAt(${start} + ${i + 1})`, cp));
|
|
8920
9086
|
const cond = tail.length ? ` && ${tail.join(" && ")}` : "";
|
|
8921
|
-
|
|
9087
|
+
lines2.push(`${ind} if (${start} + ${open.length} <= input.length${cond}) { ${okV} = true; ${endV2} = ${start} + ${open.length}; break }`);
|
|
8922
9088
|
}
|
|
8923
|
-
|
|
8924
|
-
|
|
9089
|
+
lines2.push(`${ind} break`);
|
|
9090
|
+
lines2.push(`${ind} }`);
|
|
8925
9091
|
}
|
|
8926
|
-
|
|
8927
|
-
return { setup:
|
|
9092
|
+
lines2.push(`${ind}}`);
|
|
9093
|
+
return { setup: lines2, ok: okV, end: endV2 };
|
|
8928
9094
|
}
|
|
8929
9095
|
if (shape.disjoint) {
|
|
8930
9096
|
const plan = planAltSwitch(shape.firsts);
|
|
8931
9097
|
if (plan.kind === "switch") {
|
|
8932
|
-
|
|
9098
|
+
lines2.push(`${ind}if (${start} < input.length) switch (${codeAt(start, firstChar)}) {`);
|
|
8933
9099
|
shape.arms.forEach((arm, k) => {
|
|
8934
9100
|
const labels = plan.cases[k].map((cp) => `case ${cp}:`).join(" ");
|
|
8935
9101
|
const m = emitShapeMatch(arm, start, mint, `${ind} `, firstChar);
|
|
8936
|
-
|
|
8937
|
-
|
|
8938
|
-
|
|
8939
|
-
|
|
8940
|
-
|
|
8941
|
-
|
|
9102
|
+
lines2.push(`${ind} ${labels} {`);
|
|
9103
|
+
lines2.push(...m.setup);
|
|
9104
|
+
lines2.push(`${ind} ${okV} = ${m.ok}`);
|
|
9105
|
+
lines2.push(`${ind} ${endV2} = ${m.ok} ? ${m.end} : ${start}`);
|
|
9106
|
+
lines2.push(`${ind} break`);
|
|
9107
|
+
lines2.push(`${ind} }`);
|
|
8942
9108
|
});
|
|
8943
|
-
|
|
9109
|
+
lines2.push(`${ind}}`);
|
|
8944
9110
|
} else {
|
|
8945
9111
|
const c0 = codeAt(start, firstChar);
|
|
8946
9112
|
shape.arms.forEach((arm, k) => {
|
|
8947
9113
|
const fs3 = shape.firsts[k];
|
|
8948
9114
|
const cond = fs3.negated ? `!(${classCond(c0, fs3.ranges)})` : `(${classCond(c0, fs3.ranges)})`;
|
|
8949
9115
|
const m = emitShapeMatch(arm, start, mint, `${ind} `, firstChar);
|
|
8950
|
-
|
|
8951
|
-
|
|
8952
|
-
|
|
8953
|
-
|
|
8954
|
-
|
|
9116
|
+
lines2.push(`${ind}${k === 0 ? "if" : "else if"} (${start} < input.length && ${cond}) {`);
|
|
9117
|
+
lines2.push(...m.setup);
|
|
9118
|
+
lines2.push(`${ind} ${okV} = ${m.ok}`);
|
|
9119
|
+
lines2.push(`${ind} ${endV2} = ${m.ok} ? ${m.end} : ${start}`);
|
|
9120
|
+
lines2.push(`${ind}}`);
|
|
8955
9121
|
});
|
|
8956
9122
|
}
|
|
8957
9123
|
} else {
|
|
8958
9124
|
const lbl = mint("_alt");
|
|
8959
|
-
|
|
9125
|
+
lines2.push(`${ind}${lbl}: {`);
|
|
8960
9126
|
for (const arm of shape.arms) {
|
|
8961
9127
|
const m = emitShapeMatch(arm, start, mint, `${ind} `, firstChar);
|
|
8962
|
-
|
|
8963
|
-
|
|
9128
|
+
lines2.push(...m.setup);
|
|
9129
|
+
lines2.push(`${ind} if (${m.ok}) { ${okV} = true; ${endV2} = ${m.end}; break ${lbl} }`);
|
|
8964
9130
|
}
|
|
8965
|
-
|
|
9131
|
+
lines2.push(`${ind}}`);
|
|
8966
9132
|
}
|
|
8967
|
-
return { setup:
|
|
9133
|
+
return { setup: lines2, ok: okV, end: endV2 };
|
|
8968
9134
|
}
|
|
8969
9135
|
if (shape.kind === "chars") {
|
|
8970
9136
|
const cur = mint("_e");
|
|
@@ -8999,64 +9165,64 @@ function emitShapeMatch(shape, start, mint, ind, firstChar) {
|
|
|
8999
9165
|
const c = classCond(`input.charCodeAt(${at})`, p.ranges);
|
|
9000
9166
|
return p.negated ? `!(${c})` : `(${c})`;
|
|
9001
9167
|
};
|
|
9002
|
-
const
|
|
9168
|
+
const lines2 = [`${ind}let ${endV2} = ${start}`, `${ind}let ${okV} = false`, `${ind}do {`];
|
|
9003
9169
|
let first = true;
|
|
9004
9170
|
for (const p of shape.parts) {
|
|
9005
9171
|
if (p.part === "lit") {
|
|
9006
9172
|
const L = p.cps.length;
|
|
9007
9173
|
const cond = litCond(endV2, p.cps, first ? firstChar : void 0);
|
|
9008
9174
|
if (p.optional) {
|
|
9009
|
-
|
|
9175
|
+
lines2.push(`${ind} if (${endV2} + ${L} <= input.length && (${cond})) ${endV2} += ${L}`);
|
|
9010
9176
|
} else {
|
|
9011
|
-
|
|
9012
|
-
|
|
9177
|
+
lines2.push(`${ind} if (!(${endV2} + ${L} <= input.length && (${cond}))) break`);
|
|
9178
|
+
lines2.push(`${ind} ${endV2} += ${L}`);
|
|
9013
9179
|
}
|
|
9014
9180
|
} else if (p.part === "run" && p.max === Infinity) {
|
|
9015
9181
|
const s = mint("_s");
|
|
9016
|
-
|
|
9017
|
-
|
|
9018
|
-
if (p.min === 1)
|
|
9019
|
-
else if (p.min > 1)
|
|
9182
|
+
lines2.push(`${ind} const ${s} = ${endV2}`);
|
|
9183
|
+
lines2.push(`${ind} while (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
9184
|
+
if (p.min === 1) lines2.push(`${ind} if (${endV2} === ${s}) break`);
|
|
9185
|
+
else if (p.min > 1) lines2.push(`${ind} if (${endV2} - ${s} < ${p.min}) break`);
|
|
9020
9186
|
} else if (p.part === "run" && p.max === 1) {
|
|
9021
9187
|
if (p.min === 1) {
|
|
9022
|
-
|
|
9023
|
-
|
|
9188
|
+
lines2.push(`${ind} if (!(${endV2} < input.length && ${runCond(p, endV2)})) break`);
|
|
9189
|
+
lines2.push(`${ind} ${endV2}++`);
|
|
9024
9190
|
} else {
|
|
9025
|
-
|
|
9191
|
+
lines2.push(`${ind} if (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
9026
9192
|
}
|
|
9027
9193
|
} else if (p.part === "run") {
|
|
9028
9194
|
const s = mint("_s");
|
|
9029
|
-
|
|
9030
|
-
|
|
9031
|
-
if (p.min > 0)
|
|
9195
|
+
lines2.push(`${ind} const ${s} = ${endV2}`);
|
|
9196
|
+
lines2.push(`${ind} while (${endV2} - ${s} < ${p.max} && ${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
9197
|
+
if (p.min > 0) lines2.push(`${ind} if (${endV2} - ${s} < ${p.min}) break`);
|
|
9032
9198
|
} else {
|
|
9033
9199
|
const inner = emitShapeMatch(p.inner, endV2, mint, `${ind} `, first ? firstChar : void 0);
|
|
9034
9200
|
if (!p.unbounded) {
|
|
9035
|
-
|
|
9201
|
+
lines2.push(...inner.setup);
|
|
9036
9202
|
if (p.min === 1) {
|
|
9037
|
-
|
|
9038
|
-
|
|
9203
|
+
lines2.push(`${ind} if (!(${inner.ok})) break`);
|
|
9204
|
+
lines2.push(`${ind} ${endV2} = ${inner.end}`);
|
|
9039
9205
|
} else {
|
|
9040
|
-
|
|
9206
|
+
lines2.push(`${ind} if (${inner.ok}) ${endV2} = ${inner.end}`);
|
|
9041
9207
|
}
|
|
9042
9208
|
} else {
|
|
9043
9209
|
const progV = mint("_prog");
|
|
9044
|
-
|
|
9045
|
-
|
|
9046
|
-
|
|
9047
|
-
|
|
9048
|
-
|
|
9049
|
-
|
|
9050
|
-
|
|
9051
|
-
if (p.min === 1)
|
|
9210
|
+
lines2.push(`${ind} let ${progV} = false`);
|
|
9211
|
+
lines2.push(`${ind} while (true) {`);
|
|
9212
|
+
lines2.push(...inner.setup);
|
|
9213
|
+
lines2.push(`${ind} if (!(${inner.ok})) break`);
|
|
9214
|
+
lines2.push(`${ind} ${endV2} = ${inner.end}`);
|
|
9215
|
+
lines2.push(`${ind} ${progV} = true`);
|
|
9216
|
+
lines2.push(`${ind} }`);
|
|
9217
|
+
if (p.min === 1) lines2.push(`${ind} if (!${progV}) break`);
|
|
9052
9218
|
}
|
|
9053
9219
|
}
|
|
9054
9220
|
first = false;
|
|
9055
9221
|
}
|
|
9056
|
-
|
|
9057
|
-
|
|
9058
|
-
|
|
9059
|
-
return { setup:
|
|
9222
|
+
lines2.push(`${ind} ${okV} = true`);
|
|
9223
|
+
lines2.push(`${ind}} while (false)`);
|
|
9224
|
+
lines2.push(`${ind}if (!${okV}) ${endV2} = ${start}`);
|
|
9225
|
+
return { setup: lines2, ok: okV, end: endV2 };
|
|
9060
9226
|
}
|
|
9061
9227
|
if (shape.kind === "litFold") {
|
|
9062
9228
|
const openLen2 = shape.open.length;
|
|
@@ -9642,7 +9808,10 @@ var EMITTED_PARAMS = [
|
|
|
9642
9808
|
// Appended for trivia-attributing fields (`field(…, { leadingTrivia })`);
|
|
9643
9809
|
// old factories ignore them.
|
|
9644
9810
|
"LEAD",
|
|
9645
|
-
"triviaFieldCapture"
|
|
9811
|
+
"triviaFieldCapture",
|
|
9812
|
+
// Appended for the deferred-commit trivia skip (`trivia-gap.ts`); old
|
|
9813
|
+
// factories ignore it.
|
|
9814
|
+
"skipDeferredTrivia"
|
|
9646
9815
|
];
|
|
9647
9816
|
var RUNTIME_PRELUDE = `
|
|
9648
9817
|
let _pfScan=null
|
|
@@ -9663,7 +9832,7 @@ function _skipTrivia(input,cur,ctx){
|
|
|
9663
9832
|
const s=_pfScan
|
|
9664
9833
|
if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
|
|
9665
9834
|
if(s!==null)return skipTriviaScanned(s,input,cur,ctx)
|
|
9666
|
-
if(needsDeferredTriviaCommit(ctx))return
|
|
9835
|
+
if(needsDeferredTriviaCommit(ctx))return skipDeferredTrivia(input,cur,ctx)
|
|
9667
9836
|
return advanceTrivia(input,cur,ctx)
|
|
9668
9837
|
}
|
|
9669
9838
|
function _pushLeaf(ctx,value,s,e){pushCstLeaf(ctx,{_tag:'leaf',value,span:{start:s,end:e}})}
|
|
@@ -9870,11 +10039,11 @@ function rebuildPools(cc, fx, disp, plan) {
|
|
|
9870
10039
|
})
|
|
9871
10040
|
};
|
|
9872
10041
|
}
|
|
9873
|
-
function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
|
|
10042
|
+
function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, select) {
|
|
9874
10043
|
const { code, k, fx, disp, dsp, triviaLabelled } = t;
|
|
9875
10044
|
const swapLegal = !cfg.trackLines;
|
|
9876
10045
|
const hostCst = cfg.hostCst;
|
|
9877
|
-
const
|
|
10046
|
+
const REC2 = prog.rec === 1 && cfg.tolerant;
|
|
9878
10047
|
if (cfg.coverage) throw new Unemittable("a coverage assembly");
|
|
9879
10048
|
const roots = [...Object.values(prog.rules), ...extraIps];
|
|
9880
10049
|
const reachable = [...reachableSites(code, roots)];
|
|
@@ -9945,7 +10114,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
|
|
|
9945
10114
|
const op = code[ip];
|
|
9946
10115
|
sinkBits.set(
|
|
9947
10116
|
ip,
|
|
9948
|
-
op === OP_SCAN ? 3 : (op === OP_FIELD ? 1 : 0) | (op === OP_EXPECT ||
|
|
10117
|
+
op === OP_SCAN ? 3 : (op === OP_FIELD ? 1 : 0) | (op === OP_EXPECT || REC2 && (op === OP_REP || op === OP_REPV) ? 2 : 0)
|
|
9949
10118
|
);
|
|
9950
10119
|
}
|
|
9951
10120
|
const sinkKids = [];
|
|
@@ -9969,6 +10138,8 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
|
|
|
9969
10138
|
};
|
|
9970
10139
|
const bodies = [];
|
|
9971
10140
|
const byIp = /* @__PURE__ */ new Map();
|
|
10141
|
+
const externals = [];
|
|
10142
|
+
const siteBytes = /* @__PURE__ */ new Map();
|
|
9972
10143
|
const reached = /* @__PURE__ */ new Set();
|
|
9973
10144
|
const prelude = [];
|
|
9974
10145
|
const skipDefs = [];
|
|
@@ -10104,6 +10275,18 @@ return 1
|
|
|
10104
10275
|
tokenDecisionRefs.set(dispatchIp, made);
|
|
10105
10276
|
return made;
|
|
10106
10277
|
}
|
|
10278
|
+
function gateMissTest(gip) {
|
|
10279
|
+
const resolved = t.cc[code[gip + 1]];
|
|
10280
|
+
const ci = classes.push([resolved]) - 1;
|
|
10281
|
+
classPlan.push([code[gip + 1]]);
|
|
10282
|
+
const cls = hoist("cl", `CLS[${ci}][0]`);
|
|
10283
|
+
return isAsciiOnlyClass(resolved) ? `${cls}.ascii[input.charCodeAt(pos)]!==1` : `!classHas(${cls},lead(input,pos))`;
|
|
10284
|
+
}
|
|
10285
|
+
function lookaheadMiss(child, miss) {
|
|
10286
|
+
if (code[child] !== OP_GATE || cfg.tolerant || cfg.probe) return "";
|
|
10287
|
+
return `if(${gateMissTest(child)}){${miss}}
|
|
10288
|
+
`;
|
|
10289
|
+
}
|
|
10107
10290
|
function skipFor(l) {
|
|
10108
10291
|
if (l.tri < 0) return "_skipTrivia";
|
|
10109
10292
|
const ki = l.tri;
|
|
@@ -10114,8 +10297,8 @@ return 1
|
|
|
10114
10297
|
const nm = `_sk${skipPool.size}`;
|
|
10115
10298
|
skipPool.set(key, nm);
|
|
10116
10299
|
if (!hasScan) {
|
|
10117
|
-
skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return
|
|
10118
|
-
if(needsDeferredTriviaCommit(ctx))return
|
|
10300
|
+
skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return skipDeferredTrivia(input,cur,ctx)}` : `function ${nm}(input,cur,ctx){
|
|
10301
|
+
if(needsDeferredTriviaCommit(ctx))return skipDeferredTrivia(input,cur,ctx)
|
|
10119
10302
|
return advanceTrivia(input,cur,ctx)}`);
|
|
10120
10303
|
return nm;
|
|
10121
10304
|
}
|
|
@@ -10160,9 +10343,17 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
10160
10343
|
const target = resolveAlias(ip);
|
|
10161
10344
|
const done = byIp.get(target);
|
|
10162
10345
|
if (done !== void 0) return done;
|
|
10346
|
+
if (select !== void 0 && !select.has(target)) {
|
|
10347
|
+
const ext = `_px${target}`;
|
|
10348
|
+
byIp.set(target, ext);
|
|
10349
|
+
externals.push(target);
|
|
10350
|
+
return ext;
|
|
10351
|
+
}
|
|
10163
10352
|
const fname = `_pf${target}`;
|
|
10164
10353
|
byIp.set(target, fname);
|
|
10165
|
-
|
|
10354
|
+
const body = lower(target, fname);
|
|
10355
|
+
siteBytes.set(target, body.length);
|
|
10356
|
+
bodies.push(body);
|
|
10166
10357
|
return fname;
|
|
10167
10358
|
}
|
|
10168
10359
|
function resolveAlias(ip) {
|
|
@@ -10302,14 +10493,28 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
10302
10493
|
return `${head}EC.e=pos;return ''}`;
|
|
10303
10494
|
case OP_GATE: {
|
|
10304
10495
|
const child = link(code[ip + 2]);
|
|
10305
|
-
const resolved = t.cc[code[ip + 1]];
|
|
10306
|
-
const ci = classes.push([resolved]) - 1;
|
|
10307
|
-
classPlan.push([code[ip + 1]]);
|
|
10308
|
-
const cls = hoist("cl", `CLS[${ci}][0]`);
|
|
10309
10496
|
const xf = fxRef(code[ip + 3]);
|
|
10310
10497
|
return `${head}
|
|
10311
|
-
if(${
|
|
10498
|
+
if(${gateMissTest(ip)}){ctx._fe=pos;ctx._fx=${xf};return FAIL}
|
|
10499
|
+
return ${child}(input,pos,ctx)
|
|
10500
|
+
}`;
|
|
10501
|
+
}
|
|
10502
|
+
case OP_ARMGATE: {
|
|
10503
|
+
const pred = fnRef(code[ip + 1]);
|
|
10504
|
+
const child = link(code[ip + 2]);
|
|
10505
|
+
const xf = fxRef(code[ip + 3]);
|
|
10506
|
+
return `${head}
|
|
10507
|
+
if(!${pred}(ctx.state)){ctx._fc=false;ctx._fe=-1;ctx._fx=${xf};return FAIL}
|
|
10312
10508
|
return ${child}(input,pos,ctx)
|
|
10509
|
+
}`;
|
|
10510
|
+
}
|
|
10511
|
+
case OP_WITHCTX: {
|
|
10512
|
+
const ki = code[ip + 1];
|
|
10513
|
+
const child = link(code[ip + 2]);
|
|
10514
|
+
return `${head}
|
|
10515
|
+
const saved=ctx.state
|
|
10516
|
+
ctx.state=${ki < 0 ? `${fnRef(~ki)}(saved)` : kRef(ki)}
|
|
10517
|
+
try{return ${child}(input,pos,ctx)}finally{ctx.state=saved}
|
|
10313
10518
|
}`;
|
|
10314
10519
|
}
|
|
10315
10520
|
case OP_XFORM: {
|
|
@@ -10367,7 +10572,7 @@ if(v!==FAIL)return v
|
|
|
10367
10572
|
const err={_tag:'parseError',span:${prog.lines === 1 ? "spanLines(ctx,pos,pos)" : "{start:pos,end:pos}"},expected:${xf}}
|
|
10368
10573
|
const es=ctx._errors
|
|
10369
10574
|
if(es!==undefined)es.push(err)
|
|
10370
|
-
${
|
|
10575
|
+
${REC2 ? "if(ctx._tolerant===true)captureError(ctx,err)\n" : ""}ctx._fc=false
|
|
10371
10576
|
EC.e=pos
|
|
10372
10577
|
return err
|
|
10373
10578
|
}`;
|
|
@@ -10488,7 +10693,7 @@ return v
|
|
|
10488
10693
|
}
|
|
10489
10694
|
case OP_LEX_PROGRAM: {
|
|
10490
10695
|
const programId = code[ip + 1];
|
|
10491
|
-
const
|
|
10696
|
+
const run2 = hoist("lexProgram", `LEXPROG[${programId}]`);
|
|
10492
10697
|
const scanId = t.lexPrograms[programId].scan;
|
|
10493
10698
|
if (scanId !== void 0) return `${head}
|
|
10494
10699
|
const sTri=ctx.trivia,sKinds=ctx.triviaKindLabels,sScan=_pfScan
|
|
@@ -10506,7 +10711,7 @@ ctx._cstTriviaLog=undefined
|
|
|
10506
10711
|
ctx._triviaLog=undefined
|
|
10507
10712
|
ctx._rootTriviaLog=undefined
|
|
10508
10713
|
let e
|
|
10509
|
-
try{e=${
|
|
10714
|
+
try{e=${run2}(input,pos,ctx,SCANS[${scanId}])}finally{
|
|
10510
10715
|
_pfScan=sScan
|
|
10511
10716
|
ctx.trivia=sTri
|
|
10512
10717
|
ctx.triviaKindLabels=sKinds
|
|
@@ -10525,7 +10730,7 @@ EC.e=e
|
|
|
10525
10730
|
return v
|
|
10526
10731
|
}`;
|
|
10527
10732
|
return `${head}
|
|
10528
|
-
const e=${
|
|
10733
|
+
const e=${run2}(input,pos,ctx)
|
|
10529
10734
|
if(e<0)return FAIL
|
|
10530
10735
|
const v=input.slice(pos,e)
|
|
10531
10736
|
if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
|
|
@@ -10536,7 +10741,7 @@ return v
|
|
|
10536
10741
|
/* ── transaction ─────────────────────────────────────────────────────── */
|
|
10537
10742
|
case OP_ATTEMPT: {
|
|
10538
10743
|
const child = link(code[ip + 1]);
|
|
10539
|
-
const clean = !
|
|
10744
|
+
const clean = !REC2 && failureRollbackClean(prog, ip);
|
|
10540
10745
|
const p = tmp();
|
|
10541
10746
|
return `${head}
|
|
10542
10747
|
${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
|
|
@@ -10565,7 +10770,7 @@ return FAIL
|
|
|
10565
10770
|
const xf = fxRef(code[ip + 2]);
|
|
10566
10771
|
const p = tmp();
|
|
10567
10772
|
return `${head}
|
|
10568
|
-
${emitMark(p, L.buf, L.raw, sinks)}
|
|
10773
|
+
${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${emitMark(p, L.buf, L.raw, sinks)}
|
|
10569
10774
|
const v=${child}(input,pos,ctx)
|
|
10570
10775
|
${emitRollback(p, L.buf, L.raw, sinks)}
|
|
10571
10776
|
if(v===FAIL){EC.e=pos;return null}
|
|
@@ -10579,7 +10784,7 @@ return FAIL
|
|
|
10579
10784
|
const xf = fxRef(code[ip + 2]);
|
|
10580
10785
|
const p = tmp();
|
|
10581
10786
|
return `${head}
|
|
10582
|
-
${emitMark(p, L.buf, L.raw, sinks)}
|
|
10787
|
+
${lookaheadMiss(code[ip + 1], `ctx._fe=pos;ctx._fx=${xf};return FAIL`)}${emitMark(p, L.buf, L.raw, sinks)}
|
|
10583
10788
|
const v=${child}(input,pos,ctx)
|
|
10584
10789
|
${emitRollback(p, L.buf, L.raw, sinks)}
|
|
10585
10790
|
if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
|
|
@@ -10589,10 +10794,10 @@ return null
|
|
|
10589
10794
|
}
|
|
10590
10795
|
case OP_OPT: {
|
|
10591
10796
|
const child = link(code[ip + 1]);
|
|
10592
|
-
const clean = !
|
|
10797
|
+
const clean = !REC2 && failureRollbackClean(prog, ip);
|
|
10593
10798
|
const p = tmp();
|
|
10594
10799
|
return `${head}
|
|
10595
|
-
${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
|
|
10800
|
+
${lookaheadMiss(code[ip + 1], "EC.e=pos;return null")}${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
|
|
10596
10801
|
ctx._fc=false
|
|
10597
10802
|
const v=${child}(input,pos,ctx)
|
|
10598
10803
|
if(v===FAIL){
|
|
@@ -10619,15 +10824,15 @@ return v
|
|
|
10619
10824
|
const childIp = code[base + i];
|
|
10620
10825
|
kids.push(code[childIp] === OP_ADJ ? "" : link(childIp));
|
|
10621
10826
|
}
|
|
10622
|
-
const sy =
|
|
10827
|
+
const sy = REC2 ? `${tmp()}sy` : "";
|
|
10623
10828
|
const pub = (i) => {
|
|
10624
10829
|
const s = sentRef(code[base + n + i]);
|
|
10625
10830
|
return s === "undefined" ? `ctx._sync=${sy}` : `ctx._sync=${s}??${sy}`;
|
|
10626
10831
|
};
|
|
10627
10832
|
const parts = [head];
|
|
10628
|
-
if (
|
|
10833
|
+
if (REC2) parts.push(`const ${sy}=ctx._sync`, "try{", pub(0));
|
|
10629
10834
|
parts.push(`const v0=${kids[0]}(input,pos,ctx)`, "if(v0===FAIL)return FAIL");
|
|
10630
|
-
const close = () =>
|
|
10835
|
+
const close = () => REC2 ? `${parts.join("\n")}
|
|
10631
10836
|
}finally{ctx._sync=${sy}}
|
|
10632
10837
|
}` : `${parts.join("\n")}
|
|
10633
10838
|
}`;
|
|
@@ -10640,7 +10845,7 @@ return v
|
|
|
10640
10845
|
for (let i = 1; i < n; i++) {
|
|
10641
10846
|
const vn = `v${i}`;
|
|
10642
10847
|
parts.push(`let ${vn}`);
|
|
10643
|
-
if (
|
|
10848
|
+
if (REC2) parts.push(pub(i));
|
|
10644
10849
|
const childIp = code[base + i];
|
|
10645
10850
|
if (code[childIp] === OP_ADJ) {
|
|
10646
10851
|
const negated = code[childIp + 1] === 1;
|
|
@@ -10673,7 +10878,7 @@ return v
|
|
|
10673
10878
|
const asc = hoist("as", `DISP[${di}].ascii`);
|
|
10674
10879
|
const hiArr = table.hi;
|
|
10675
10880
|
const armSwitch = arms.map((a, i) => `case ${i}:v=${a}(input,pos,ctx);break`).join("\n");
|
|
10676
|
-
const directAscii =
|
|
10881
|
+
const directAscii = table.hi.length === 0;
|
|
10677
10882
|
return `${head}
|
|
10678
10883
|
const c=${directAscii ? "input.charCodeAt(pos)" : "lead(input,pos)"}
|
|
10679
10884
|
let arm=-1
|
|
@@ -10700,7 +10905,7 @@ return FAIL
|
|
|
10700
10905
|
const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
|
|
10701
10906
|
const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
|
|
10702
10907
|
const maskable = n <= 32;
|
|
10703
|
-
const directAsciiMask =
|
|
10908
|
+
const directAsciiMask = maskable && gates.every(isAsciiOnlyClass);
|
|
10704
10909
|
const gateRefs = directAsciiMask ? [] : Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
|
|
10705
10910
|
const tokenCandidate = tokenChoiceCandidates.get(ip);
|
|
10706
10911
|
const pretests = Array.from({ length: n }, (_, i) => {
|
|
@@ -10725,7 +10930,7 @@ return FAIL
|
|
|
10725
10930
|
if (maskable) maskPlan.push(~di);
|
|
10726
10931
|
const p = tmp();
|
|
10727
10932
|
const encodedRollbackMask = choiceRollbackMask(prog, ip) ?? -1;
|
|
10728
|
-
const rollbackMask =
|
|
10933
|
+
const rollbackMask = REC2 ? -1 : encodedRollbackMask;
|
|
10729
10934
|
const hasRollback = rollbackMask !== 0;
|
|
10730
10935
|
const startFailureExact = arms.every((_arm, i) => {
|
|
10731
10936
|
const terminal = leadingScalarTerminal(code, code[base + i], 0, false);
|
|
@@ -10742,7 +10947,7 @@ return FAIL
|
|
|
10742
10947
|
if (choiceCannotCommit(prog, ip) && !startFailureExact) {
|
|
10743
10948
|
const deepAt = Array.from({ length: n }, () => tmp());
|
|
10744
10949
|
const deepFx = Array.from({ length: n }, () => tmp());
|
|
10745
|
-
const
|
|
10950
|
+
const remember2 = (i, at, expectedSet) => `${deepAt[i]}=${at};${deepFx[i]}=${expectedSet}`;
|
|
10746
10951
|
const lazyArms = (ascii) => arms.map((arm, i) => {
|
|
10747
10952
|
const pretest = pretests[i];
|
|
10748
10953
|
const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
|
|
@@ -10754,13 +10959,13 @@ return FAIL
|
|
|
10754
10959
|
if(${decision}===0){
|
|
10755
10960
|
ctx._fc=false
|
|
10756
10961
|
{const at=_pfTokEnd
|
|
10757
|
-
${
|
|
10962
|
+
${remember2(i, "at", pretest.token.expected)}}
|
|
10758
10963
|
}`;
|
|
10759
10964
|
const sequenceMiss = pretest?.sequence === void 0 ? "" : `
|
|
10760
10965
|
else if(${ascii ? `(bits&${1 << i})!==0&&` : ""}${decision}<0){
|
|
10761
10966
|
ctx._fc=false
|
|
10762
10967
|
{const at=_pfSeqEnd
|
|
10763
|
-
${
|
|
10968
|
+
${remember2(i, "at", pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("") + pretest.sequence.expected.at(-1))}}
|
|
10764
10969
|
}`;
|
|
10765
10970
|
return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
|
|
10766
10971
|
`}if(${gate2}){
|
|
@@ -10768,7 +10973,7 @@ ctx._fc=false
|
|
|
10768
10973
|
{const v=${arm}(input,pos,ctx)
|
|
10769
10974
|
if(v!==FAIL)return v}
|
|
10770
10975
|
{const at=ctx._fe??pos
|
|
10771
|
-
${
|
|
10976
|
+
${remember2(i, "at", "ctx._fx")}}
|
|
10772
10977
|
${rollbackFor(i)}
|
|
10773
10978
|
}${routeMiss}${sequenceMiss}`;
|
|
10774
10979
|
}).join("\n");
|
|
@@ -10881,7 +11086,7 @@ const bits=${maskName}[${directAsciiMask ? "c" : "c<0?128:c"}]
|
|
|
10881
11086
|
if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
|
|
10882
11087
|
${startFailureExact ? "" : "let prev=0"}
|
|
10883
11088
|
${maskArms}
|
|
10884
|
-
${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${n},prev,acc)`}
|
|
11089
|
+
${startFailureExact ? "" : `if(best===pos&&prev!==0)acc=${catchName}(${n},prev,acc)`}
|
|
10885
11090
|
ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
|
|
10886
11091
|
return FAIL
|
|
10887
11092
|
}
|
|
@@ -10973,14 +11178,14 @@ return [key,v]
|
|
|
10973
11178
|
const collect = op === OP_REP;
|
|
10974
11179
|
let itemCls;
|
|
10975
11180
|
let itemAscii = false;
|
|
10976
|
-
if (!
|
|
11181
|
+
if (!REC2) {
|
|
10977
11182
|
const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
|
|
10978
11183
|
if (itemClassIndex >= 0) {
|
|
10979
11184
|
const resolved = t.cc[itemClassIndex];
|
|
10980
11185
|
const ci = classes.push([resolved]) - 1;
|
|
10981
11186
|
classPlan.push([itemClassIndex]);
|
|
10982
11187
|
itemCls = hoist("ri", `CLS[${ci}][0]`);
|
|
10983
|
-
itemAscii =
|
|
11188
|
+
itemAscii = isAsciiOnlyClass(resolved);
|
|
10984
11189
|
}
|
|
10985
11190
|
}
|
|
10986
11191
|
const itemMiss = (at) => itemAscii ? `${itemCls}.ascii[input.charCodeAt(${at})]!==1` : `!classHas(${itemCls},lead(input,${at}))`;
|
|
@@ -11021,11 +11226,11 @@ ${p}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
|
11021
11226
|
${p}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${markSinks}
|
|
11022
11227
|
}`;
|
|
11023
11228
|
const my = `${p}my`;
|
|
11024
|
-
const recFx =
|
|
11025
|
-
const sepSent =
|
|
11229
|
+
const recFx = REC2 ? fxRef(code[ip + 6]) : "";
|
|
11230
|
+
const sepSent = REC2 ? sentRef(code[ip + 7]) : "undefined";
|
|
11026
11231
|
const recSent = sep2 === void 0 ? my : sepSent === "undefined" ? `orSentinel(${my},undefined)` : `orSentinel(${sepSent}??${my},${sepSent}===undefined?undefined:${my})`;
|
|
11027
11232
|
const recGate = sep2 !== void 0 || min === 0 ? "" : `count>=${min}&&`;
|
|
11028
|
-
const recBranch = !
|
|
11233
|
+
const recBranch = !REC2 ? "" : `if(ctx._tolerant===true&&${my}!==undefined&&${recGate}!matchesAt(${my},input,itemStart,ctx)){
|
|
11029
11234
|
${sep2 === void 0 ? `${rb}
|
|
11030
11235
|
` : ""}const rr=recoverScan(input,itemStart,ctx,${recSent},${recFx})
|
|
11031
11236
|
${collect ? "out.push(rr.error)\n" : ""}captureError(ctx,rr.error)
|
|
@@ -11036,7 +11241,7 @@ continue
|
|
|
11036
11241
|
`;
|
|
11037
11242
|
return `${head}
|
|
11038
11243
|
const out=${collect ? "[]" : "undefined"}
|
|
11039
|
-
${knownTrivia === void 0 ? "const hasTrivia=ctx.trivia!==undefined\n" : ""}${L.buf ? "" : "const needMark=_rollbackNeeded(ctx)\n"}${
|
|
11244
|
+
${knownTrivia === void 0 ? "const hasTrivia=ctx.trivia!==undefined\n" : ""}${L.buf ? "" : "const needMark=_rollbackNeeded(ctx)\n"}${REC2 ? `const ${my}=ctx._sync
|
|
11040
11245
|
` : ""}${itemCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
|
|
11041
11246
|
`}let cur=pos
|
|
11042
11247
|
let count=0
|
|
@@ -11075,7 +11280,7 @@ ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
|
|
|
11075
11280
|
`}ctx._fc=false
|
|
11076
11281
|
const v=${child}(input,itemStart,ctx)
|
|
11077
11282
|
if(v===FAIL){
|
|
11078
|
-
${
|
|
11283
|
+
${REC2 ? `if(ctx._fc===true){
|
|
11079
11284
|
${rb}
|
|
11080
11285
|
return FAIL
|
|
11081
11286
|
}
|
|
@@ -11206,7 +11411,7 @@ return nd
|
|
|
11206
11411
|
const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
|
|
11207
11412
|
const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
|
|
11208
11413
|
const ty = q(type);
|
|
11209
|
-
const stArg =
|
|
11414
|
+
const stArg = "ctx.state";
|
|
11210
11415
|
const hostCall = `_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,${stArg},${tags})`;
|
|
11211
11416
|
let value;
|
|
11212
11417
|
if (proj >= 0) {
|
|
@@ -11267,7 +11472,7 @@ ctx.captureTrivia=sCap
|
|
|
11267
11472
|
if(v===FAIL)return FAIL
|
|
11268
11473
|
const end=EC.e
|
|
11269
11474
|
const span=${tracked ? "spanLines(ctx,pos,end)" : "{start:pos,end}"}
|
|
11270
|
-
const st=${readsState ? "
|
|
11475
|
+
const st=${readsState ? "ctx.state" : "undefined"}
|
|
11271
11476
|
let nd
|
|
11272
11477
|
${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]
|
|
11273
11478
|
else ` : ""}{${value}}
|
|
@@ -11280,21 +11485,51 @@ return nd
|
|
|
11280
11485
|
throw new Unemittable(`OP_${OP_NAMES[op] ?? String(op)}`);
|
|
11281
11486
|
}
|
|
11282
11487
|
}
|
|
11488
|
+
const served = (ip) => select === void 0 || select.has(resolveAlias(ip));
|
|
11283
11489
|
const ruleEntries = [];
|
|
11284
11490
|
for (const [rname, entryIp] of Object.entries(prog.rules)) {
|
|
11491
|
+
if (!served(entryIp)) continue;
|
|
11285
11492
|
const target = link(entryIp);
|
|
11286
11493
|
const rn = `_r_${rname.replace(/[^A-Za-z0-9_$]/g, "_")}`;
|
|
11287
11494
|
bodies.push(`const ${rn}=${target}`);
|
|
11288
11495
|
ruleEntries.push(`${q(rname)}:${rn}`);
|
|
11289
11496
|
}
|
|
11290
11497
|
const extra = [];
|
|
11291
|
-
|
|
11498
|
+
const exported = /* @__PURE__ */ new Set();
|
|
11499
|
+
for (const ip of extraIps) {
|
|
11500
|
+
if (!served(ip)) continue;
|
|
11501
|
+
exported.add(ip);
|
|
11502
|
+
extra.push(`${ip}:${link(ip)}`);
|
|
11503
|
+
}
|
|
11504
|
+
if (select !== void 0) {
|
|
11505
|
+
const kids = [];
|
|
11506
|
+
for (const ip of reachable) {
|
|
11507
|
+
if (select.has(resolveAlias(ip))) continue;
|
|
11508
|
+
kids.length = 0;
|
|
11509
|
+
childSlots(code, ip, kids);
|
|
11510
|
+
for (const kid of kids) {
|
|
11511
|
+
const target = resolveAlias(kid);
|
|
11512
|
+
if (!select.has(target) || exported.has(target)) continue;
|
|
11513
|
+
exported.add(target);
|
|
11514
|
+
extra.push(`${target}:${link(target)}`);
|
|
11515
|
+
}
|
|
11516
|
+
}
|
|
11517
|
+
}
|
|
11518
|
+
const hybrid = select === void 0 ? "" : `,
|
|
11519
|
+
ext:[${externals.join(",")}],
|
|
11520
|
+
bind:function(xs,ps){_xScan=xs
|
|
11521
|
+
${externals.map((ip, i) => `_xp${ip}=ps[${i}]`).join("\n")}},
|
|
11522
|
+
scan:function(s){const o=_pfScan;_pfScan=s;return o}`;
|
|
11523
|
+
const externalDefs = select === void 0 ? "" : `let _xScan
|
|
11524
|
+
${externals.map((ip) => `let _xp${ip}
|
|
11525
|
+
function _px${ip}(input,pos,ctx){const o=_xScan(_pfScan);const v=_xp${ip}(input,pos,ctx);_xScan(o);return v}`).join("\n")}
|
|
11526
|
+
`;
|
|
11292
11527
|
const source = `${RUNTIME_PRELUDE}${needsNoRawPrelude ? NO_RAW_RUNTIME_PRELUDE : ""}
|
|
11293
11528
|
${prelude.join("\n")}
|
|
11294
11529
|
${skipDefs.join("\n")}
|
|
11295
11530
|
${choiceDefs.join("\n")}
|
|
11296
11531
|
${bodies.join("\n")}
|
|
11297
|
-
function _begin(ctx){
|
|
11532
|
+
${externalDefs}function _begin(ctx){
|
|
11298
11533
|
const host=ctx.build
|
|
11299
11534
|
if(_pfDepth>0)_pfFrames.push([_pfScan,_pfHost,EC.e])
|
|
11300
11535
|
_pfDepth++
|
|
@@ -11321,7 +11556,7 @@ pieces:{${ruleEntries.join(",")}},
|
|
|
11321
11556
|
byIp:{${extra.join(",")}},
|
|
11322
11557
|
end:function(){return EC.e},
|
|
11323
11558
|
begin:_begin,
|
|
11324
|
-
finish:_finish
|
|
11559
|
+
finish:_finish${hybrid}
|
|
11325
11560
|
}`;
|
|
11326
11561
|
return {
|
|
11327
11562
|
source,
|
|
@@ -11329,10 +11564,193 @@ finish:_finish
|
|
|
11329
11564
|
masks,
|
|
11330
11565
|
classes,
|
|
11331
11566
|
armExpected,
|
|
11567
|
+
siteBytes,
|
|
11332
11568
|
plan: { classes: classPlan, armExpected: armExpectedPlan, masks: maskPlan }
|
|
11333
11569
|
};
|
|
11334
11570
|
}
|
|
11335
11571
|
|
|
11572
|
+
// src/combinators/lines.ts
|
|
11573
|
+
function lineIndexAt(view, offset) {
|
|
11574
|
+
const lines2 = view.lines;
|
|
11575
|
+
let lo = 0, hi = lines2.length - 1;
|
|
11576
|
+
while (lo < hi) {
|
|
11577
|
+
const mid = lo + hi + 1 >> 1;
|
|
11578
|
+
if (lines2[mid].offset <= offset) lo = mid;
|
|
11579
|
+
else hi = mid - 1;
|
|
11580
|
+
}
|
|
11581
|
+
return lo;
|
|
11582
|
+
}
|
|
11583
|
+
var lineAt = (view, offset) => view.lines[lineIndexAt(view, offset)];
|
|
11584
|
+
function sourceOffset(view, offset) {
|
|
11585
|
+
const line = lineAt(view, offset);
|
|
11586
|
+
return line === void 0 ? offset : line.source + (offset - line.offset);
|
|
11587
|
+
}
|
|
11588
|
+
function columnAt(input, pos, ctx) {
|
|
11589
|
+
const view = ctx.lineView;
|
|
11590
|
+
let start, column, split;
|
|
11591
|
+
const line = view === void 0 ? void 0 : lineAt(view, pos);
|
|
11592
|
+
if (line !== void 0 && pos >= line.offset) {
|
|
11593
|
+
start = line.offset;
|
|
11594
|
+
column = line.column;
|
|
11595
|
+
split = line.split;
|
|
11596
|
+
} else {
|
|
11597
|
+
start = input.lastIndexOf("\n", pos - 1) + 1;
|
|
11598
|
+
column = 0;
|
|
11599
|
+
split = 0;
|
|
11600
|
+
}
|
|
11601
|
+
for (let i = start; i < pos; i++) {
|
|
11602
|
+
if (input.charCodeAt(i) === 9) {
|
|
11603
|
+
const width = 4 - (column - (i === start ? split : 0)) % 4 - (i === start ? split : 0);
|
|
11604
|
+
column += width;
|
|
11605
|
+
} else column++;
|
|
11606
|
+
split = 0;
|
|
11607
|
+
}
|
|
11608
|
+
return { column, split: pos === start ? split : 0 };
|
|
11609
|
+
}
|
|
11610
|
+
function columns(n) {
|
|
11611
|
+
if (!Number.isInteger(n) || n < 0) throw new TypeError(`columns(n) needs a non-negative integer, got ${n}`);
|
|
11612
|
+
const expected = [`columns(${n})`];
|
|
11613
|
+
const meta = {
|
|
11614
|
+
firstSet: n === 0 ? any() : { kind: "ranges", ranges: [{ lo: 9, hi: 9 }, { lo: 32, hi: 32 }] },
|
|
11615
|
+
canMatchNewline: false,
|
|
11616
|
+
isTrivia: false
|
|
11617
|
+
};
|
|
11618
|
+
return {
|
|
11619
|
+
_tag: "columns",
|
|
11620
|
+
_meta: meta,
|
|
11621
|
+
_def: { tag: "columns", n },
|
|
11622
|
+
parse(input, pos, ctx) {
|
|
11623
|
+
const c = ctx;
|
|
11624
|
+
let { column, split } = columnAt(input, pos, c);
|
|
11625
|
+
const goal = column + n;
|
|
11626
|
+
let at = pos;
|
|
11627
|
+
while (column < goal) {
|
|
11628
|
+
const code = input.charCodeAt(at);
|
|
11629
|
+
if (code === 32) {
|
|
11630
|
+
column++;
|
|
11631
|
+
split = 0;
|
|
11632
|
+
at++;
|
|
11633
|
+
continue;
|
|
11634
|
+
}
|
|
11635
|
+
if (code !== 9) return { ok: false, expected, span: { start: at, end: at } };
|
|
11636
|
+
const width = 4 - (column - split) % 4 - split;
|
|
11637
|
+
if (column + width > goal) {
|
|
11638
|
+
c._columnsSplit = { at, split: split + (goal - column) };
|
|
11639
|
+
return { ok: true, value: input.slice(pos, at), span: { start: pos, end: at } };
|
|
11640
|
+
}
|
|
11641
|
+
column += width;
|
|
11642
|
+
split = 0;
|
|
11643
|
+
at++;
|
|
11644
|
+
}
|
|
11645
|
+
return { ok: true, value: input.slice(pos, at), span: { start: pos, end: at } };
|
|
11646
|
+
}
|
|
11647
|
+
};
|
|
11648
|
+
}
|
|
11649
|
+
function lines(prefix, body, options = {}) {
|
|
11650
|
+
const { first, lazy } = options;
|
|
11651
|
+
const opening = first ?? prefix;
|
|
11652
|
+
const meta = {
|
|
11653
|
+
// An opening that matches empty starts a run at any character.
|
|
11654
|
+
firstSet: matchesEmpty(opening) ? any() : opening._meta.firstSet,
|
|
11655
|
+
canMatchNewline: true,
|
|
11656
|
+
isTrivia: false
|
|
11657
|
+
};
|
|
11658
|
+
return {
|
|
11659
|
+
_tag: "lines",
|
|
11660
|
+
_meta: meta,
|
|
11661
|
+
_def: { tag: "lines", prefix, body, ...first === void 0 ? {} : { first }, ...lazy === void 0 ? {} : { lazy } },
|
|
11662
|
+
parse(input, pos, ctx) {
|
|
11663
|
+
const c = ctx;
|
|
11664
|
+
const probe = createDetachedParseContext(false, ctx.state);
|
|
11665
|
+
probe.lineView = c.lineView;
|
|
11666
|
+
const run2 = [];
|
|
11667
|
+
const parts = [];
|
|
11668
|
+
let offset = 0;
|
|
11669
|
+
for (let start = pos; start < input.length || start === pos; ) {
|
|
11670
|
+
let end2 = input.indexOf("\n", start);
|
|
11671
|
+
if (end2 < 0) end2 = input.length;
|
|
11672
|
+
probe._columnsSplit = void 0;
|
|
11673
|
+
const head = (run2.length === 0 ? opening : prefix).parse(input, start, probe);
|
|
11674
|
+
let content;
|
|
11675
|
+
let joined;
|
|
11676
|
+
if (head.ok && head.span.end <= end2) {
|
|
11677
|
+
content = head.span.end;
|
|
11678
|
+
joined = "prefix";
|
|
11679
|
+
} else if (run2.length === 0) {
|
|
11680
|
+
return { ok: false, expected: head.ok ? ["line prefix"] : head.expected, span: { start, end: start } };
|
|
11681
|
+
} else if (lazy !== void 0 && lazy.parse(input, start, probe).ok) {
|
|
11682
|
+
content = start;
|
|
11683
|
+
joined = "lazy";
|
|
11684
|
+
} else break;
|
|
11685
|
+
const mark = probe._columnsSplit;
|
|
11686
|
+
const here = columnAt(input, content, c);
|
|
11687
|
+
const split = joined === "prefix" && mark !== void 0 && mark.at === content ? mark.split : here.split;
|
|
11688
|
+
run2.push({ offset, source: content, end: end2, column: here.column + (split - here.split), split, lazy: joined === "lazy" });
|
|
11689
|
+
const text = input.slice(content, end2);
|
|
11690
|
+
const newline = end2 < input.length;
|
|
11691
|
+
parts.push(newline ? `${text}
|
|
11692
|
+
` : text);
|
|
11693
|
+
offset += text.length + (newline ? 1 : 0);
|
|
11694
|
+
start = end2 + 1;
|
|
11695
|
+
if (!newline) break;
|
|
11696
|
+
}
|
|
11697
|
+
const view = { lines: run2, parent: c.lineView };
|
|
11698
|
+
const saved = c.lineView, starts = c._lineStarts, lineIndex = c._lineIndex, scanned = c._lineScannedTo, probing = c._probe;
|
|
11699
|
+
const errors = c._errors?.length ?? 0;
|
|
11700
|
+
let cursor = -1;
|
|
11701
|
+
if (probing !== void 0) for (const line2 of run2) {
|
|
11702
|
+
if (probing.offset >= line2.source && probing.offset <= line2.end) {
|
|
11703
|
+
cursor = line2.offset + probing.offset - line2.source;
|
|
11704
|
+
break;
|
|
11705
|
+
}
|
|
11706
|
+
}
|
|
11707
|
+
const inner = cursor < 0 ? void 0 : { offset: cursor, best: null };
|
|
11708
|
+
c.lineView = view;
|
|
11709
|
+
c._lineStarts = void 0;
|
|
11710
|
+
c._lineIndex = void 0;
|
|
11711
|
+
c._lineScannedTo = void 0;
|
|
11712
|
+
c._probe = inner;
|
|
11713
|
+
let result;
|
|
11714
|
+
try {
|
|
11715
|
+
result = body.parse(parts.join(""), 0, ctx);
|
|
11716
|
+
} finally {
|
|
11717
|
+
c.lineView = saved;
|
|
11718
|
+
c._lineStarts = starts;
|
|
11719
|
+
c._lineIndex = lineIndex;
|
|
11720
|
+
c._lineScannedTo = scanned;
|
|
11721
|
+
c._probe = probing;
|
|
11722
|
+
}
|
|
11723
|
+
if (inner?.best) failAt(c, inner.best.expected, sourceOffset(view, inner.best.span.start));
|
|
11724
|
+
if (c._errors !== void 0) for (let i = errors; i < c._errors.length; i++) {
|
|
11725
|
+
const error = c._errors[i];
|
|
11726
|
+
error.span = { start: sourceOffset(view, error.span.start), end: sourceOffset(view, error.span.end) };
|
|
11727
|
+
}
|
|
11728
|
+
if (!result.ok) {
|
|
11729
|
+
const at = sourceOffset(view, result.span.start);
|
|
11730
|
+
return { ...result, span: { start: at, end: at } };
|
|
11731
|
+
}
|
|
11732
|
+
const stop = result.span.end;
|
|
11733
|
+
const index = lineIndexAt(view, stop);
|
|
11734
|
+
const line = run2[index];
|
|
11735
|
+
const end = stop === line.offset && index > 0 ? run2[index - 1].end + 1 : stop - line.offset > line.end - line.source ? line.end + 1 : line.source + (stop - line.offset);
|
|
11736
|
+
recordLineRangeFromContext(c, input, pos, end);
|
|
11737
|
+
return { ok: true, value: result.value, span: { start: pos, end } };
|
|
11738
|
+
}
|
|
11739
|
+
};
|
|
11740
|
+
}
|
|
11741
|
+
|
|
11742
|
+
// src/table/line-scan.ts
|
|
11743
|
+
function rebuildLineScan(s, subtree) {
|
|
11744
|
+
if (s.kind === 2) {
|
|
11745
|
+
return lines(subtree(s.prefix), subtree(s.body), {
|
|
11746
|
+
...s.first === void 0 ? {} : { first: subtree(s.first) },
|
|
11747
|
+
...s.lazy === void 0 ? {} : { lazy: subtree(s.lazy) }
|
|
11748
|
+
});
|
|
11749
|
+
}
|
|
11750
|
+
if (s.kind === 3) return columns(s.n);
|
|
11751
|
+
return void 0;
|
|
11752
|
+
}
|
|
11753
|
+
|
|
11336
11754
|
// src/combinators/scanTo.ts
|
|
11337
11755
|
function resolveScanSkip(explicitSkip, raw, ctx) {
|
|
11338
11756
|
if (raw) return [];
|
|
@@ -11577,6 +11995,70 @@ function escapeClassChar(ch2) {
|
|
|
11577
11995
|
return ch2.replace(/[\\\]^-]/g, "\\$&");
|
|
11578
11996
|
}
|
|
11579
11997
|
|
|
11998
|
+
// src/table/trivia-gap.ts
|
|
11999
|
+
function skipDeferredTrivia(input, cur, ctx) {
|
|
12000
|
+
const triviaP = ctx.trivia;
|
|
12001
|
+
const plain = ctx.trackLines !== true && ctx.captureTrivia !== true;
|
|
12002
|
+
const gap = ctx._gap;
|
|
12003
|
+
if (plain && gap !== void 0 && cur === gap.at && input === gap.input && triviaP === gap.of && ctx._rootTriviaCapture === gap.root && ctx.state === gap.state && ctx._rootTriviaKindIndex === gap.rootKinds && ctx._triviaLog === gap.log) return gap.end;
|
|
12004
|
+
const end = clearRunEnd(input, cur, ctx, triviaP, plain);
|
|
12005
|
+
if (end >= 0) {
|
|
12006
|
+
remember(cur, end, ctx, input, triviaP);
|
|
12007
|
+
return end;
|
|
12008
|
+
}
|
|
12009
|
+
const scan = scanTriviaCompact(input, cur, ctx);
|
|
12010
|
+
if (typeof scan !== "number") return commitTriviaScan(scan);
|
|
12011
|
+
if (plain) remember(cur, scan, ctx, input, triviaP);
|
|
12012
|
+
return scan;
|
|
12013
|
+
}
|
|
12014
|
+
function clearRunEnd(input, cur, ctx, triviaP, plain) {
|
|
12015
|
+
const rootKinds = ctx._rootTriviaKindIndex;
|
|
12016
|
+
const spec = triviaP?._meta.labeledTriviaSpec;
|
|
12017
|
+
if (!plain || triviaP === void 0 || spec == null || rootKinds === void 0 || ctx._triviaLog !== void 0) return -1;
|
|
12018
|
+
if (spec.rootKinds !== rootKinds) prime(spec, triviaP, rootKinds);
|
|
12019
|
+
const fast = spec.rootScan;
|
|
12020
|
+
if (fast === null) return -1;
|
|
12021
|
+
const end = fast(input, cur);
|
|
12022
|
+
return ctx._rootTriviaCapture === false || clearOf(spec.rootLeaders, input, cur, end) ? end : -1;
|
|
12023
|
+
}
|
|
12024
|
+
function remember(cur, end, ctx, input, triviaP) {
|
|
12025
|
+
const gap = ctx._gap;
|
|
12026
|
+
if (gap === void 0) {
|
|
12027
|
+
ctx._gap = { at: cur, end, input, of: triviaP, root: ctx._rootTriviaCapture, rootKinds: ctx._rootTriviaKindIndex, log: ctx._triviaLog, state: ctx.state };
|
|
12028
|
+
return;
|
|
12029
|
+
}
|
|
12030
|
+
gap.at = cur;
|
|
12031
|
+
gap.end = end;
|
|
12032
|
+
gap.input = input;
|
|
12033
|
+
gap.of = triviaP;
|
|
12034
|
+
gap.root = ctx._rootTriviaCapture;
|
|
12035
|
+
gap.rootKinds = ctx._rootTriviaKindIndex;
|
|
12036
|
+
gap.log = ctx._triviaLog;
|
|
12037
|
+
gap.state = ctx.state;
|
|
12038
|
+
}
|
|
12039
|
+
function prime(spec, triviaP, rootKinds) {
|
|
12040
|
+
const ranges = [];
|
|
12041
|
+
let bounded = true;
|
|
12042
|
+
for (const arm of spec.arms) {
|
|
12043
|
+
if (rootKinds[arm.label] === void 0) continue;
|
|
12044
|
+
const fs3 = arm.parser._meta.firstSet;
|
|
12045
|
+
if (fs3.kind === "any") bounded = false;
|
|
12046
|
+
else if (fs3.kind === "ranges") ranges.push(...fs3.ranges);
|
|
12047
|
+
}
|
|
12048
|
+
const classified = triviaP._meta.triviaScanner;
|
|
12049
|
+
spec.rootKinds = rootKinds;
|
|
12050
|
+
spec.rootLeaders = ranges;
|
|
12051
|
+
spec.rootScan = !bounded ? null : classified === void 0 ? fastTriviaScanner(triviaP) : classified;
|
|
12052
|
+
}
|
|
12053
|
+
function clearOf(ranges, input, from, to) {
|
|
12054
|
+
for (let i = from; i < to; i++) {
|
|
12055
|
+
const c = input.charCodeAt(i);
|
|
12056
|
+
if (c >= 55296 && c <= 57343) return false;
|
|
12057
|
+
for (const r of ranges) if (c >= r.lo && c <= r.hi) return false;
|
|
12058
|
+
}
|
|
12059
|
+
return true;
|
|
12060
|
+
}
|
|
12061
|
+
|
|
11580
12062
|
// src/table/run-support.ts
|
|
11581
12063
|
function lineCol(ctx, offset) {
|
|
11582
12064
|
const starts = ctx._lineStarts ?? [0];
|
|
@@ -11613,6 +12095,19 @@ function lead(input, pos) {
|
|
|
11613
12095
|
// src/cst/host-mode.ts
|
|
11614
12096
|
var FUSED_HOST_MODE = /* @__PURE__ */ Symbol.for("parseman.fusedHostMode");
|
|
11615
12097
|
var FUSED_HOST_ELIDED = /* @__PURE__ */ Symbol.for("parseman.fusedHostElided");
|
|
12098
|
+
function assertHostModeCompatible(mode, build, hostBranchElided = true) {
|
|
12099
|
+
const isCstHost = build?._parsemanCstOutput === true;
|
|
12100
|
+
if (mode === "ast" && isCstHost && hostBranchElided) {
|
|
12101
|
+
throw new Error(
|
|
12102
|
+
"parseman: this parser was compiled for host mode \"ast\" (the default), so its nodes build through their own `build` callbacks and no positioned-CST branch was emitted. It cannot be driven with a positioned-CST host (cstBuildHost / a language-service host). Compile a second artifact from the SAME grammar with `compile(grammar, { hostMode: 'cst' })` \u2014 or, under the macro, a second `rules({ hostMode: 'cst' }, factory)` call site \u2014 and drive that one instead."
|
|
12103
|
+
);
|
|
12104
|
+
}
|
|
12105
|
+
if (mode === "cst" && !isCstHost) {
|
|
12106
|
+
throw new Error(
|
|
12107
|
+
'parseman: this parser was compiled for host mode "cst", so every node builds through a positioned-CST `ctx.build` host. Pass one (e.g. `{ build: cstBuildHost }`), or use an artifact compiled with the default `hostMode: "ast"` to get the grammar\'s own AST.'
|
|
12108
|
+
);
|
|
12109
|
+
}
|
|
12110
|
+
}
|
|
11616
12111
|
|
|
11617
12112
|
// src/grammar-metadata.ts
|
|
11618
12113
|
var GRAMMAR_COVERAGE_DEFINITIONS = /* @__PURE__ */ Symbol.for("parseman.grammarCoverageDefinitions");
|
|
@@ -11649,7 +12144,7 @@ function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(pr
|
|
|
11649
12144
|
...prog.labels === void 0 ? {} : { triviaKindLabels: prog.labels },
|
|
11650
12145
|
...prog.classified === 1 ? { rootTriviaClassified: true } : {}
|
|
11651
12146
|
};
|
|
11652
|
-
const
|
|
12147
|
+
const lines2 = prog.lines === 1;
|
|
11653
12148
|
const mode = prog.hostMode ?? "ast";
|
|
11654
12149
|
const elided = mode === "ast" && hasDirectBuilder(prog);
|
|
11655
12150
|
const coverageDefinitions = prog.cov === void 0 ? void 0 : Object.freeze(covDefinitions(prog).map(Object.freeze));
|
|
@@ -11677,7 +12172,7 @@ function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(pr
|
|
|
11677
12172
|
ctx._fe = -1;
|
|
11678
12173
|
ctx._fx = EMPTY_FX;
|
|
11679
12174
|
ctx._fc = false;
|
|
11680
|
-
if (
|
|
12175
|
+
if (lines2 && ctx._lineStarts === void 0) {
|
|
11681
12176
|
ctx._lineStarts = [0];
|
|
11682
12177
|
ctx._lineScannedTo = 0;
|
|
11683
12178
|
}
|
|
@@ -11685,10 +12180,10 @@ function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(pr
|
|
|
11685
12180
|
if (end < 0) {
|
|
11686
12181
|
const fe = ctx._fe;
|
|
11687
12182
|
const at = fe === void 0 || fe < 0 ? pos : fe;
|
|
11688
|
-
const fspan =
|
|
12183
|
+
const fspan = lines2 ? spanLines(ctx, at, at) : { start: at, end: at };
|
|
11689
12184
|
return committed2(ctx) ? { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan, committed: true } : { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan };
|
|
11690
12185
|
}
|
|
11691
|
-
return { ok: true, value: d.lastValue(), span:
|
|
12186
|
+
return { ok: true, value: d.lastValue(), span: lines2 ? spanLines(ctx, pos, end) : { start: pos, end } };
|
|
11692
12187
|
};
|
|
11693
12188
|
const ownTrivia = triviaOfRule(prog.rules[name]);
|
|
11694
12189
|
const meta = ownTrivia === void 0 ? baseMeta : { ...baseMeta, grammarTrivia: ownTrivia };
|
|
@@ -11758,7 +12253,7 @@ function assemble(t, prog, cfg) {
|
|
|
11758
12253
|
const triviaScan = t.triviaScan;
|
|
11759
12254
|
const swapLegal = !cfg.trackLines;
|
|
11760
12255
|
const hostCst = cfg.hostCst;
|
|
11761
|
-
const
|
|
12256
|
+
const REC2 = prog.rec === 1 && cfg.tolerant;
|
|
11762
12257
|
const sentinels = /* @__PURE__ */ new Map();
|
|
11763
12258
|
function sentinelFor(cls) {
|
|
11764
12259
|
if (cls < 0) return void 0;
|
|
@@ -11773,6 +12268,9 @@ function assemble(t, prog, cfg) {
|
|
|
11773
12268
|
const EC = newEndCell();
|
|
11774
12269
|
const scalarRecognizers = [];
|
|
11775
12270
|
const rawScalarSpecs = /* @__PURE__ */ new Set();
|
|
12271
|
+
function lookaheadClass(child) {
|
|
12272
|
+
return code[child] === OP_GATE && !cfg.tolerant && !cfg.probe ? cc[code[child + 1]] : null;
|
|
12273
|
+
}
|
|
11776
12274
|
function scalarFor(child) {
|
|
11777
12275
|
const spec = code[child + 1];
|
|
11778
12276
|
let recognize = scalarRecognizers[spec];
|
|
@@ -11782,20 +12280,23 @@ function assemble(t, prog, cfg) {
|
|
|
11782
12280
|
}
|
|
11783
12281
|
return recognize;
|
|
11784
12282
|
}
|
|
11785
|
-
const labelExtraIps =
|
|
11786
|
-
for (const s of prog.scans ?? []) {
|
|
11787
|
-
for (const r of s.skip) labelExtraIps.push(r[0]);
|
|
11788
|
-
if (s.sentinel !== void 0) labelExtraIps.push(s.sentinel[0]);
|
|
11789
|
-
if (s.recoverAt !== void 0) labelExtraIps.push(s.recoverAt[0]);
|
|
11790
|
-
if (s.stopAt !== void 0) labelExtraIps.push(s.stopAt[0]);
|
|
11791
|
-
}
|
|
11792
|
-
for (const set of prog.scanSkip ?? []) for (const r of set) labelExtraIps.push(r[0]);
|
|
12283
|
+
const labelExtraIps = assemblyExtraIps(prog);
|
|
11793
12284
|
const closureLabels = computeSiteLabels(
|
|
11794
12285
|
code,
|
|
11795
12286
|
[...Object.values(prog.rules), ...labelExtraIps],
|
|
11796
12287
|
hostCst
|
|
11797
12288
|
);
|
|
11798
12289
|
let SCAN = null;
|
|
12290
|
+
let HYBRID;
|
|
12291
|
+
function hybridPiece(piece) {
|
|
12292
|
+
const setScan = HYBRID.scan;
|
|
12293
|
+
return (input, pos, ctx) => {
|
|
12294
|
+
const saved = setScan(SCAN);
|
|
12295
|
+
const value = piece(input, pos, ctx);
|
|
12296
|
+
setScan(saved);
|
|
12297
|
+
return value;
|
|
12298
|
+
};
|
|
12299
|
+
}
|
|
11799
12300
|
const memo = /* @__PURE__ */ new Map();
|
|
11800
12301
|
const reached = /* @__PURE__ */ new Set();
|
|
11801
12302
|
function pushLeaf(ctx, value, s, e) {
|
|
@@ -12087,9 +12588,7 @@ function assemble(t, prog, cfg) {
|
|
|
12087
12588
|
return s(input, cur);
|
|
12088
12589
|
}
|
|
12089
12590
|
if (s !== null) return skipTriviaScanned(s, input, cur, ctx);
|
|
12090
|
-
if (needsDeferredTriviaCommit(ctx))
|
|
12091
|
-
return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
|
|
12092
|
-
}
|
|
12591
|
+
if (needsDeferredTriviaCommit(ctx)) return skipDeferredTrivia(input, cur, ctx);
|
|
12093
12592
|
return advanceTrivia(input, cur, ctx);
|
|
12094
12593
|
}
|
|
12095
12594
|
let TERMV;
|
|
@@ -12259,7 +12758,7 @@ function assemble(t, prog, cfg) {
|
|
|
12259
12758
|
if (next !== void 0) {
|
|
12260
12759
|
return next(input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best);
|
|
12261
12760
|
}
|
|
12262
|
-
if (best === pos) acc = through(total, prev, acc);
|
|
12761
|
+
if (best === pos && prev !== 0) acc = through(total, prev, acc);
|
|
12263
12762
|
ctx._fe = pos;
|
|
12264
12763
|
ctx._fx = acc ?? choiceFx;
|
|
12265
12764
|
return FAIL;
|
|
@@ -12342,7 +12841,7 @@ function assemble(t, prog, cfg) {
|
|
|
12342
12841
|
if (next !== void 0) {
|
|
12343
12842
|
return next(input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best);
|
|
12344
12843
|
}
|
|
12345
|
-
if (best === pos) acc = through(total, prev, acc);
|
|
12844
|
+
if (best === pos && prev !== 0) acc = through(total, prev, acc);
|
|
12346
12845
|
ctx._fe = pos;
|
|
12347
12846
|
ctx._fx = acc ?? choiceFx;
|
|
12348
12847
|
return FAIL;
|
|
@@ -12421,6 +12920,13 @@ function assemble(t, prog, cfg) {
|
|
|
12421
12920
|
if (done !== void 0) return done;
|
|
12422
12921
|
const flight = inFlight.get(ip);
|
|
12423
12922
|
if (flight !== void 0) return flight.fwd;
|
|
12923
|
+
const selected = HYBRID?.byIp[ip];
|
|
12924
|
+
if (selected !== void 0) {
|
|
12925
|
+
const piece2 = hybridPiece(selected);
|
|
12926
|
+
memo.set(ip, piece2);
|
|
12927
|
+
reached.add(ip);
|
|
12928
|
+
return piece2;
|
|
12929
|
+
}
|
|
12424
12930
|
let target;
|
|
12425
12931
|
const fwd = (input, pos, ctx) => target(input, pos, ctx);
|
|
12426
12932
|
const holder = { fwd, set: (p) => {
|
|
@@ -12428,7 +12934,7 @@ function assemble(t, prog, cfg) {
|
|
|
12428
12934
|
} };
|
|
12429
12935
|
inFlight.set(ip, holder);
|
|
12430
12936
|
const op = code[ip];
|
|
12431
|
-
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);
|
|
12937
|
+
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]) : countedPiece(lower(ip), ip);
|
|
12432
12938
|
inFlight.delete(ip);
|
|
12433
12939
|
holder.set(piece);
|
|
12434
12940
|
memo.set(ip, piece);
|
|
@@ -12769,7 +13275,7 @@ function assemble(t, prog, cfg) {
|
|
|
12769
13275
|
const child = link(code[ip + 1]);
|
|
12770
13276
|
const xf = fx[code[ip + 2]];
|
|
12771
13277
|
const expectSpan = (ctx, pos) => prog.lines === 1 ? spanLines(ctx, pos, pos) : { start: pos, end: pos };
|
|
12772
|
-
if (
|
|
13278
|
+
if (REC2) {
|
|
12773
13279
|
return (input, pos, ctx) => {
|
|
12774
13280
|
const v = child(input, pos, ctx);
|
|
12775
13281
|
if (v !== FAIL) return v;
|
|
@@ -12965,7 +13471,12 @@ function assemble(t, prog, cfg) {
|
|
|
12965
13471
|
}
|
|
12966
13472
|
const child = link(code[ip + 1]);
|
|
12967
13473
|
const xf = fx[code[ip + 2]];
|
|
13474
|
+
const gate2 = lookaheadClass(code[ip + 1]);
|
|
12968
13475
|
return (input, pos, ctx) => {
|
|
13476
|
+
if (gate2 !== null && !classHas2(gate2, lead(input, pos))) {
|
|
13477
|
+
EC.e = pos;
|
|
13478
|
+
return null;
|
|
13479
|
+
}
|
|
12969
13480
|
const need = markCst(ctx);
|
|
12970
13481
|
const mRaw = MRAW;
|
|
12971
13482
|
const mTl = MTL;
|
|
@@ -12988,7 +13499,13 @@ function assemble(t, prog, cfg) {
|
|
|
12988
13499
|
case OP_PEEK: {
|
|
12989
13500
|
const child = link(code[ip + 1]);
|
|
12990
13501
|
const xf = fx[code[ip + 2]];
|
|
13502
|
+
const gate2 = lookaheadClass(code[ip + 1]);
|
|
12991
13503
|
return (input, pos, ctx) => {
|
|
13504
|
+
if (gate2 !== null && !classHas2(gate2, lead(input, pos))) {
|
|
13505
|
+
ctx._fe = pos;
|
|
13506
|
+
ctx._fx = xf;
|
|
13507
|
+
return FAIL;
|
|
13508
|
+
}
|
|
12992
13509
|
const need = markCst(ctx);
|
|
12993
13510
|
const mRaw = MRAW;
|
|
12994
13511
|
const mTl = MTL;
|
|
@@ -13010,7 +13527,12 @@ function assemble(t, prog, cfg) {
|
|
|
13010
13527
|
}
|
|
13011
13528
|
case OP_OPT: {
|
|
13012
13529
|
const child = link(code[ip + 1]);
|
|
13530
|
+
const gate2 = lookaheadClass(code[ip + 1]);
|
|
13013
13531
|
return (input, pos, ctx) => {
|
|
13532
|
+
if (gate2 !== null && !classHas2(gate2, lead(input, pos))) {
|
|
13533
|
+
EC.e = pos;
|
|
13534
|
+
return null;
|
|
13535
|
+
}
|
|
13014
13536
|
const need = markCst(ctx);
|
|
13015
13537
|
const mRaw = MRAW;
|
|
13016
13538
|
const mTl = MTL;
|
|
@@ -13108,8 +13630,8 @@ function assemble(t, prog, cfg) {
|
|
|
13108
13630
|
};
|
|
13109
13631
|
}
|
|
13110
13632
|
case OP_LEX_PROGRAM: {
|
|
13111
|
-
const
|
|
13112
|
-
const scanId =
|
|
13633
|
+
const run2 = t.lexPrograms[code[ip + 1]];
|
|
13634
|
+
const scanId = run2.scan;
|
|
13113
13635
|
if (scanId !== void 0) {
|
|
13114
13636
|
return (input, pos, ctx) => {
|
|
13115
13637
|
const sTrivia = ctx.trivia, sKinds = ctx.triviaKindLabels;
|
|
@@ -13130,7 +13652,7 @@ function assemble(t, prog, cfg) {
|
|
|
13130
13652
|
ctx._rootTriviaLog = void 0;
|
|
13131
13653
|
let end;
|
|
13132
13654
|
try {
|
|
13133
|
-
end =
|
|
13655
|
+
end = run2(input, pos, ctx, scans[scanId]);
|
|
13134
13656
|
} finally {
|
|
13135
13657
|
SCAN = sScan;
|
|
13136
13658
|
ctx.trivia = sTrivia;
|
|
@@ -13151,7 +13673,7 @@ function assemble(t, prog, cfg) {
|
|
|
13151
13673
|
};
|
|
13152
13674
|
}
|
|
13153
13675
|
return (input, pos, ctx) => {
|
|
13154
|
-
const end =
|
|
13676
|
+
const end = run2(input, pos, ctx);
|
|
13155
13677
|
if (end < 0) return FAIL;
|
|
13156
13678
|
const value = input.slice(pos, end);
|
|
13157
13679
|
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
|
|
@@ -13253,7 +13775,7 @@ function assemble(t, prog, cfg) {
|
|
|
13253
13775
|
return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
|
|
13254
13776
|
};
|
|
13255
13777
|
};
|
|
13256
|
-
if (
|
|
13778
|
+
if (REC2) {
|
|
13257
13779
|
const first2 = link(code[base]);
|
|
13258
13780
|
const firstSync = sentinelFor(code[base + n]);
|
|
13259
13781
|
const runnerAt = (i) => {
|
|
@@ -13722,7 +14244,7 @@ function assemble(t, prog, cfg) {
|
|
|
13722
14244
|
if (n === 2 || n === 3) {
|
|
13723
14245
|
const a0 = link(code[base]), a1 = link(code[base + 1]);
|
|
13724
14246
|
const a2 = n === 3 ? link(code[base + 2]) : void 0;
|
|
13725
|
-
const predecide = !
|
|
14247
|
+
const predecide = !REC2 && !cfg.probe && !cfg.coverage && !cfg.trackLines;
|
|
13726
14248
|
const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
|
|
13727
14249
|
const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
|
|
13728
14250
|
const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
|
|
@@ -13817,6 +14339,11 @@ function assemble(t, prog, cfg) {
|
|
|
13817
14339
|
}
|
|
13818
14340
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
13819
14341
|
}
|
|
14342
|
+
if (prev === 0) {
|
|
14343
|
+
ctx._fe = pos;
|
|
14344
|
+
ctx._fx = choiceFx;
|
|
14345
|
+
return FAIL;
|
|
14346
|
+
}
|
|
13820
14347
|
if (best === pos && prev < 1) acc = accSet(e0, acc);
|
|
13821
14348
|
if (best === pos && prev < 2) acc = accSet(e1, acc);
|
|
13822
14349
|
if (best === pos && n === 3 && prev < 3) acc = accSet(e2, acc);
|
|
@@ -13947,7 +14474,7 @@ function assemble(t, prog, cfg) {
|
|
|
13947
14474
|
const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
|
|
13948
14475
|
const pBit = [];
|
|
13949
14476
|
const pRec = [];
|
|
13950
|
-
if (!
|
|
14477
|
+
if (!REC2 && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
|
|
13951
14478
|
for (let i = 0; i < n; i++) {
|
|
13952
14479
|
for (const terminal of largeChoiceLiteralPretest(code, k, code[base + i]) ?? []) {
|
|
13953
14480
|
pBit.push(1 << i);
|
|
@@ -14125,7 +14652,7 @@ function assemble(t, prog, cfg) {
|
|
|
14125
14652
|
return (input, pos, ctx) => {
|
|
14126
14653
|
if (!pred(ctx.state)) {
|
|
14127
14654
|
ctx._fc = false;
|
|
14128
|
-
ctx._fe =
|
|
14655
|
+
ctx._fe = -1;
|
|
14129
14656
|
ctx._fx = xf;
|
|
14130
14657
|
return FAIL;
|
|
14131
14658
|
}
|
|
@@ -14183,10 +14710,10 @@ function assemble(t, prog, cfg) {
|
|
|
14183
14710
|
const itemFx = reportItem ? fx[code[ip + 6]] : EMPTY_FX2;
|
|
14184
14711
|
const collect = op === OP_REP;
|
|
14185
14712
|
const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
|
|
14186
|
-
const itemClass = !
|
|
14713
|
+
const itemClass = !REC2 && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
|
|
14187
14714
|
const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
|
|
14188
14715
|
const skipBeforeFirst = sepIp < 0 && min === 0;
|
|
14189
|
-
if (
|
|
14716
|
+
if (REC2) {
|
|
14190
14717
|
const itemFx2 = fx[code[ip + 6]];
|
|
14191
14718
|
const sepSent = sentinelFor(code[ip + 7]);
|
|
14192
14719
|
return (input, pos, ctx) => {
|
|
@@ -14531,7 +15058,7 @@ function assemble(t, prog, cfg) {
|
|
|
14531
15058
|
if (v === FAIL) return FAIL;
|
|
14532
15059
|
const end = EC.e;
|
|
14533
15060
|
const span = tracked ? spanLines(ctx, pos, end) : { start: pos, end };
|
|
14534
|
-
const st = readsState
|
|
15061
|
+
const st = readsState ? ctx.state : void 0;
|
|
14535
15062
|
let nd;
|
|
14536
15063
|
if (unwrap && kids.length === 1) {
|
|
14537
15064
|
nd = unwrapChild(kids[0]);
|
|
@@ -14544,10 +15071,10 @@ function assemble(t, prog, cfg) {
|
|
|
14544
15071
|
) {
|
|
14545
15072
|
nd = kids[0];
|
|
14546
15073
|
} else if (proj >= 0) {
|
|
14547
|
-
nd = hostCst && host !== void 0 ? host(type, kids, fieldMap, span, rawKids, tlog,
|
|
15074
|
+
nd = hostCst && host !== void 0 ? host(type, kids, fieldMap, span, rawKids, tlog, ctx.state, tags) : projectChild(kids, proj, type);
|
|
14548
15075
|
} else if (build !== void 0) {
|
|
14549
15076
|
if (hostCst && host !== void 0) {
|
|
14550
|
-
nd = host(type, kids, fieldMap, span, rawKids, tlog,
|
|
15077
|
+
nd = host(type, kids, fieldMap, span, rawKids, tlog, ctx.state, tags);
|
|
14551
15078
|
} else {
|
|
14552
15079
|
nd = build(kids, fieldMap, span, rawKids, captureWide ? tlog : EMPTY_TL2, st);
|
|
14553
15080
|
}
|
|
@@ -14598,14 +15125,7 @@ function assemble(t, prog, cfg) {
|
|
|
14598
15125
|
let emitRefusal;
|
|
14599
15126
|
let emitReached;
|
|
14600
15127
|
{
|
|
14601
|
-
const extraIps =
|
|
14602
|
-
for (const s of prog.scans ?? []) {
|
|
14603
|
-
for (const r of s.skip) extraIps.push(r[0]);
|
|
14604
|
-
if (s.sentinel !== void 0) extraIps.push(s.sentinel[0]);
|
|
14605
|
-
if (s.recoverAt !== void 0) extraIps.push(s.recoverAt[0]);
|
|
14606
|
-
if (s.stopAt !== void 0) extraIps.push(s.stopAt[0]);
|
|
14607
|
-
}
|
|
14608
|
-
for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
|
|
15128
|
+
const extraIps = assemblyExtraIps(prog);
|
|
14609
15129
|
const roots = [...Object.values(prog.rules), ...extraIps];
|
|
14610
15130
|
for (const ip of reachableSites(code, roots)) {
|
|
14611
15131
|
if (code[ip] === OP_DISPATCH) {
|
|
@@ -14686,7 +15206,7 @@ function assemble(t, prog, cfg) {
|
|
|
14686
15206
|
lead,
|
|
14687
15207
|
asciiFoldKey,
|
|
14688
15208
|
ROUTED_FX,
|
|
14689
|
-
|
|
15209
|
+
REC2 ? prog.cc.map((_, i) => sentinelFor(i)) : EMPTY_SENTS,
|
|
14690
15210
|
matchesAt,
|
|
14691
15211
|
recoverScan,
|
|
14692
15212
|
orSentinel,
|
|
@@ -14698,9 +15218,11 @@ function assemble(t, prog, cfg) {
|
|
|
14698
15218
|
adjacencyHolds,
|
|
14699
15219
|
t.lexPrograms,
|
|
14700
15220
|
LEAD,
|
|
14701
|
-
triviaFieldCapture
|
|
15221
|
+
triviaFieldCapture,
|
|
15222
|
+
skipDeferredTrivia
|
|
14702
15223
|
);
|
|
14703
15224
|
emitReached = new Set(pre.reached);
|
|
15225
|
+
if (emitted.ext !== void 0) HYBRID = emitted;
|
|
14704
15226
|
}
|
|
14705
15227
|
try {
|
|
14706
15228
|
if (emitted !== void 0) throw new ServedByBuild();
|
|
@@ -14770,7 +15292,7 @@ function assemble(t, prog, cfg) {
|
|
|
14770
15292
|
// — a strict one emits no reader — and through the SAME `sentinelFor` memo
|
|
14771
15293
|
// the closure pieces use, so both engines resync to the same combinator
|
|
14772
15294
|
// object rather than to two separately constructed ones.
|
|
14773
|
-
|
|
15295
|
+
REC2 ? prog.cc.map((_, i) => sentinelFor(i)) : EMPTY_SENTS,
|
|
14774
15296
|
matchesAt,
|
|
14775
15297
|
recoverScan,
|
|
14776
15298
|
orSentinel,
|
|
@@ -14782,7 +15304,8 @@ function assemble(t, prog, cfg) {
|
|
|
14782
15304
|
adjacencyHolds,
|
|
14783
15305
|
t.lexPrograms,
|
|
14784
15306
|
LEAD,
|
|
14785
|
-
triviaFieldCapture
|
|
15307
|
+
triviaFieldCapture,
|
|
15308
|
+
skipDeferredTrivia
|
|
14786
15309
|
);
|
|
14787
15310
|
emitReached = em.reached;
|
|
14788
15311
|
} catch (e) {
|
|
@@ -14793,7 +15316,7 @@ function assemble(t, prog, cfg) {
|
|
|
14793
15316
|
}
|
|
14794
15317
|
function pieceAt(ip) {
|
|
14795
15318
|
const em = emitted;
|
|
14796
|
-
if (em !== void 0) {
|
|
15319
|
+
if (em !== void 0 && HYBRID === void 0) {
|
|
14797
15320
|
const p = em.byIp[ip];
|
|
14798
15321
|
if (p === void 0) throw new Error(`table emitter: no emitted body for site ${ip}`);
|
|
14799
15322
|
return p;
|
|
@@ -14801,6 +15324,11 @@ function assemble(t, prog, cfg) {
|
|
|
14801
15324
|
return link(ip);
|
|
14802
15325
|
}
|
|
14803
15326
|
for (const s of prog.scans ?? []) {
|
|
15327
|
+
const rebuilt = rebuildLineScan(s, subtreeComb);
|
|
15328
|
+
if (rebuilt !== void 0) {
|
|
15329
|
+
scansArr.push(rebuilt);
|
|
15330
|
+
continue;
|
|
15331
|
+
}
|
|
14804
15332
|
const skip = s.skip.map((r) => subtreeComb(r));
|
|
14805
15333
|
const raw = (s.flags & 1) !== 0;
|
|
14806
15334
|
if (s.kind === 1) {
|
|
@@ -14818,6 +15346,37 @@ function assemble(t, prog, cfg) {
|
|
|
14818
15346
|
}
|
|
14819
15347
|
const scans = scansArr;
|
|
14820
15348
|
const scanSkip = (prog.scanSkip ?? []).map((set) => set.map((r) => subtreeComb(r)));
|
|
15349
|
+
if (HYBRID !== void 0) {
|
|
15350
|
+
const em = HYBRID;
|
|
15351
|
+
em.bind(
|
|
15352
|
+
(s) => {
|
|
15353
|
+
const saved = SCAN;
|
|
15354
|
+
SCAN = s;
|
|
15355
|
+
return saved;
|
|
15356
|
+
},
|
|
15357
|
+
em.ext.map((ip) => link(ip))
|
|
15358
|
+
);
|
|
15359
|
+
const pieces2 = {};
|
|
15360
|
+
for (const [name, entryIp] of Object.entries(prog.rules)) {
|
|
15361
|
+
pieces2[name] = em.pieces[name] ?? link(entryIp);
|
|
15362
|
+
}
|
|
15363
|
+
for (const ip of emitReached) reached.add(ip);
|
|
15364
|
+
return {
|
|
15365
|
+
pieces: pieces2,
|
|
15366
|
+
end: () => EC.e,
|
|
15367
|
+
begin: (ctx) => {
|
|
15368
|
+
begin(ctx);
|
|
15369
|
+
em.begin(ctx);
|
|
15370
|
+
},
|
|
15371
|
+
finish: () => {
|
|
15372
|
+
em.finish();
|
|
15373
|
+
finish();
|
|
15374
|
+
},
|
|
15375
|
+
scanSkip,
|
|
15376
|
+
reached,
|
|
15377
|
+
emitRefusal: void 0
|
|
15378
|
+
};
|
|
15379
|
+
}
|
|
14821
15380
|
if (emitted !== void 0) {
|
|
14822
15381
|
const em = emitted;
|
|
14823
15382
|
return {
|
|
@@ -14853,6 +15412,26 @@ function assemble(t, prog, cfg) {
|
|
|
14853
15412
|
}
|
|
14854
15413
|
return { pieces, end: () => EC.e, begin, finish, scanSkip, reached, emitRefusal };
|
|
14855
15414
|
}
|
|
15415
|
+
var SITE_COUNTS;
|
|
15416
|
+
function countedPiece(piece, ip) {
|
|
15417
|
+
const counts = SITE_COUNTS;
|
|
15418
|
+
if (counts === void 0) return piece;
|
|
15419
|
+
return (input, pos, ctx) => {
|
|
15420
|
+
counts[ip]++;
|
|
15421
|
+
return piece(input, pos, ctx);
|
|
15422
|
+
};
|
|
15423
|
+
}
|
|
15424
|
+
function countSiteVisits(prog, parse2, fns = prog.fns) {
|
|
15425
|
+
const counts = new Int32Array(prog.code.length);
|
|
15426
|
+
const profiled = ownTableProgram({ ...prog, fns, asm: [] });
|
|
15427
|
+
SITE_COUNTS = counts;
|
|
15428
|
+
try {
|
|
15429
|
+
parse2(tableRules(profiled));
|
|
15430
|
+
} finally {
|
|
15431
|
+
SITE_COUNTS = void 0;
|
|
15432
|
+
}
|
|
15433
|
+
return counts;
|
|
15434
|
+
}
|
|
14856
15435
|
var AssemblyCache = class {
|
|
14857
15436
|
t;
|
|
14858
15437
|
prog;
|
|
@@ -15042,6 +15621,11 @@ function emitScanSpec(s) {
|
|
|
15042
15621
|
if (s.sent !== void 0) parts.push(`sent:${s.sent === null ? "null" : jsString(s.sent)}`);
|
|
15043
15622
|
if (s.open !== void 0) parts.push(`open:${jsString(s.open)}`);
|
|
15044
15623
|
if (s.close !== void 0) parts.push(`close:${jsString(s.close)}`);
|
|
15624
|
+
for (const key of ["prefix", "body", "first", "lazy"]) {
|
|
15625
|
+
const r = s[key];
|
|
15626
|
+
if (r !== void 0) parts.push(`${key}:${emitRef(r)}`);
|
|
15627
|
+
}
|
|
15628
|
+
if (s.n !== void 0) parts.push(`n:${s.n}`);
|
|
15045
15629
|
return `{${parts.join(",")}}`;
|
|
15046
15630
|
}
|
|
15047
15631
|
function emitDispatchSpec(d) {
|
|
@@ -15061,14 +15645,7 @@ function defaultAssemblyCfgs(prog) {
|
|
|
15061
15645
|
function emitAssemblies(prog, cfgs) {
|
|
15062
15646
|
if (cfgs.length === 0) return ["a:[],"];
|
|
15063
15647
|
const t = resolveTable(prog);
|
|
15064
|
-
const extraIps =
|
|
15065
|
-
for (const s of prog.scans ?? []) {
|
|
15066
|
-
for (const r of s.skip) extraIps.push(r[0]);
|
|
15067
|
-
if (s.sentinel !== void 0) extraIps.push(s.sentinel[0]);
|
|
15068
|
-
if (s.recoverAt !== void 0) extraIps.push(s.recoverAt[0]);
|
|
15069
|
-
if (s.stopAt !== void 0) extraIps.push(s.stopAt[0]);
|
|
15070
|
-
}
|
|
15071
|
-
for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
|
|
15648
|
+
const extraIps = assemblyExtraIps(prog);
|
|
15072
15649
|
const out = [];
|
|
15073
15650
|
const seen = /* @__PURE__ */ new Set();
|
|
15074
15651
|
for (const cfg of cfgs) {
|
|
@@ -15077,7 +15654,7 @@ function emitAssemblies(prog, cfgs) {
|
|
|
15077
15654
|
seen.add(key);
|
|
15078
15655
|
let em;
|
|
15079
15656
|
try {
|
|
15080
|
-
em = emitAssemblySource(t, prog, cfg, extraIps, true);
|
|
15657
|
+
em = emitAssemblySource(t, prog, cfg, extraIps, true, cfg.select);
|
|
15081
15658
|
} catch (e) {
|
|
15082
15659
|
if (e instanceof Unemittable) continue;
|
|
15083
15660
|
throw e;
|
|
@@ -15219,6 +15796,8 @@ function children(def, winners) {
|
|
|
15219
15796
|
...def.recoverAt === void 0 ? [] : [def.recoverAt],
|
|
15220
15797
|
...def.stopAt === void 0 ? [] : [def.stopAt]
|
|
15221
15798
|
];
|
|
15799
|
+
case "lines":
|
|
15800
|
+
return [def.prefix, def.body, ...def.first === void 0 ? [] : [def.first], ...def.lazy === void 0 ? [] : [def.lazy]];
|
|
15222
15801
|
case "lazy": {
|
|
15223
15802
|
let resolved;
|
|
15224
15803
|
try {
|
|
@@ -15362,6 +15941,10 @@ function payloadKey(p, d) {
|
|
|
15362
15941
|
return `expect\0${d.label ?? ""}\0${d.expected.join("")}`;
|
|
15363
15942
|
case "scanTo":
|
|
15364
15943
|
return `scanTo\0${d.raw}\0${d.orEOF}\0${d.recoverAt !== void 0}\0${d.stopAt !== void 0}`;
|
|
15944
|
+
case "lines":
|
|
15945
|
+
return `lines\0${d.first !== void 0}\0${d.lazy !== void 0}`;
|
|
15946
|
+
case "columns":
|
|
15947
|
+
return `columns\0${d.n}`;
|
|
15365
15948
|
case "guard":
|
|
15366
15949
|
return `guard\0${fnKey(d.predSrc, d.predicate)}`;
|
|
15367
15950
|
case "adjacency":
|
|
@@ -15482,6 +16065,8 @@ function segment(d, index) {
|
|
|
15482
16065
|
if (d.recoverAt !== void 0 && index === d.skip.length + 1) return "scanTo.recoverAt";
|
|
15483
16066
|
return "scanTo.stopAt";
|
|
15484
16067
|
}
|
|
16068
|
+
case "lines":
|
|
16069
|
+
return ["lines.prefix", "lines.body", d.first === void 0 ? "lines.lazy" : "lines.first", "lines.lazy"][index] ?? "lines";
|
|
15485
16070
|
default:
|
|
15486
16071
|
return d.tag;
|
|
15487
16072
|
}
|
|
@@ -15864,36 +16449,36 @@ function findRegexFragments(visited) {
|
|
|
15864
16449
|
if (branches.length >= 2) runs.add(branches.join("|"));
|
|
15865
16450
|
for (let i = 0; i < branches.length; i++) {
|
|
15866
16451
|
for (let n = 2; n <= Math.min(MAX_RUN, branches.length - i); n++) {
|
|
15867
|
-
const
|
|
15868
|
-
if (
|
|
15869
|
-
runs.add(
|
|
16452
|
+
const run2 = branches.slice(i, i + n).join("|");
|
|
16453
|
+
if (run2.length < 4) continue;
|
|
16454
|
+
runs.add(run2);
|
|
15870
16455
|
}
|
|
15871
16456
|
}
|
|
15872
16457
|
}
|
|
15873
|
-
for (const
|
|
15874
|
-
let e = byRun.get(
|
|
16458
|
+
for (const run2 of runs) {
|
|
16459
|
+
let e = byRun.get(run2);
|
|
15875
16460
|
if (e === void 0) {
|
|
15876
|
-
e = { occ: [], nodes: /* @__PURE__ */ new Set(), branches:
|
|
15877
|
-
byRun.set(
|
|
16461
|
+
e = { occ: [], nodes: /* @__PURE__ */ new Set(), branches: run2.split("|").length };
|
|
16462
|
+
byRun.set(run2, e);
|
|
15878
16463
|
}
|
|
15879
16464
|
if (e.nodes.has(v.p)) continue;
|
|
15880
16465
|
e.nodes.add(v.p);
|
|
15881
16466
|
e.occ.push({ site: v.site, source: d.source });
|
|
15882
16467
|
}
|
|
15883
16468
|
}
|
|
15884
|
-
const candidates = [...byRun.entries()].filter(([, e]) => e.occ.length >= 2).map(([
|
|
16469
|
+
const candidates = [...byRun.entries()].filter(([, e]) => e.occ.length >= 2).map(([run2, e]) => ({ run: run2, e, savings: (e.occ.length - 1) * run2.length })).sort((a, b) => b.e.occ.length - a.e.occ.length || b.savings - a.savings || b.run.length - a.run.length);
|
|
15885
16470
|
const kept = [];
|
|
15886
16471
|
for (const c of candidates) {
|
|
15887
16472
|
if (kept.some((k) => k.e.occ.length >= c.e.occ.length && `|${k.run}|`.includes(`|${c.run}|`))) continue;
|
|
15888
16473
|
kept.push(c);
|
|
15889
16474
|
}
|
|
15890
|
-
return kept.map(({ run, e }) => ({
|
|
16475
|
+
return kept.map(({ run: run2, e }) => ({
|
|
15891
16476
|
kind: "regex-fragment",
|
|
15892
|
-
id: `regex-fragment:${
|
|
15893
|
-
fragment:
|
|
16477
|
+
id: `regex-fragment:${run2}`,
|
|
16478
|
+
fragment: run2,
|
|
15894
16479
|
branches: e.branches,
|
|
15895
16480
|
count: e.occ.length,
|
|
15896
|
-
savings: (e.occ.length - 1) *
|
|
16481
|
+
savings: (e.occ.length - 1) * run2.length,
|
|
15897
16482
|
sources: e.occ.map((o) => `/${o.source}/`),
|
|
15898
16483
|
sites: e.occ.map((o) => o.site),
|
|
15899
16484
|
suggestion: `this ${e.branches}-branch alternation is re-spelled in ${e.occ.length} DISTINCT regex() terminals. Hoist it to one shared source string and interpolate it (\`new RegExp(\\\`\u2026\\\${OP}\u2026\\\`)\`) or lift the shared part into its own terminal \u2014 an edit to the operator set currently has to land in ${e.occ.length} places, and the analysis cannot tell you when one of them drifts.`
|
|
@@ -16524,60 +17109,60 @@ function findKeywordRegexes(visited) {
|
|
|
16524
17109
|
var sitesLine = (sites) => sites.slice(0, 6).map(siteToString).join("\n ") + (sites.length > 6 ? `
|
|
16525
17110
|
\u2026 and ${sites.length - 6} more` : "");
|
|
16526
17111
|
function formatDuplicationFindings(report) {
|
|
16527
|
-
const
|
|
17112
|
+
const lines2 = [];
|
|
16528
17113
|
for (const f of report.structureLoss) {
|
|
16529
|
-
|
|
16530
|
-
|
|
16531
|
-
|
|
16532
|
-
|
|
16533
|
-
|
|
17114
|
+
lines2.push(`parseman BUG [structure-loss] @ ${siteToString(f.site)}: arm[${f.earlier}] flattens \`${f.nodeType}\` where arm[${f.later}] structures it, on ${firstSetToString(f.on)}`);
|
|
17115
|
+
lines2.push(` flat: ${f.earlierShape}`);
|
|
17116
|
+
lines2.push(` rich: ${f.laterShape}`);
|
|
17117
|
+
lines2.push(` lost: ${f.lostNodeTypes.map((t) => `\`${t}\``).join(", ")}`);
|
|
17118
|
+
lines2.push(` fix: ${f.suggestion}`);
|
|
16534
17119
|
}
|
|
16535
17120
|
for (const f of report.rewrites) {
|
|
16536
|
-
|
|
16537
|
-
|
|
16538
|
-
|
|
16539
|
-
|
|
16540
|
-
if (f.perf !== "")
|
|
17121
|
+
lines2.push(`parseman ${f.bug ? "BUG" : "rewrite"} [${f.rewrite}${f.sepByVerdict === void 0 ? "" : `/${f.sepByVerdict}`}] @ ${siteToString(f.site)}${f.astNeutral ? "" : " (candidate \u2014 verify AST identity)"}`);
|
|
17122
|
+
lines2.push(` from: ${f.from}`);
|
|
17123
|
+
lines2.push(` to: ${f.to}`);
|
|
17124
|
+
lines2.push(` fix: ${f.suggestion}`);
|
|
17125
|
+
if (f.perf !== "") lines2.push(` perf: ${f.perf}`);
|
|
16541
17126
|
}
|
|
16542
17127
|
for (const f of report.divergentNodes) {
|
|
16543
|
-
|
|
16544
|
-
for (const p of f.productions)
|
|
17128
|
+
lines2.push(`parseman divergent-node: \`${f.nodeType}\` is built by ${f.count} different productions sharing ${f.sharedTerms.length} term(s): ${f.sharedTerms.map((t) => `\`${t}\``).join(", ")}`);
|
|
17129
|
+
for (const p of f.productions) lines2.push(` ${siteToString(p.site)}
|
|
16545
17130
|
${p.shape}
|
|
16546
17131
|
unique to it: ${p.distinctTerms.length === 0 ? "(none)" : p.distinctTerms.map((t) => `\`${t}\``).join(", ")}`);
|
|
16547
|
-
|
|
17132
|
+
lines2.push(` fix: ${f.suggestion}`);
|
|
16548
17133
|
}
|
|
16549
17134
|
for (const f of report.keywordRegexes) {
|
|
16550
17135
|
const src = f.source.length > 90 ? `${f.source.slice(0, 88)}\u2026` : f.source;
|
|
16551
|
-
|
|
16552
|
-
|
|
17136
|
+
lines2.push(`parseman ${f.bug ? "BUG " : ""}keyword-regex @ ${siteToString(f.site)}: /${src}/${f.flags}${f.vocabulary ? ` [${f.words.length} literal words${f.longestFirst ? "" : ", NOT longest-first"}]` : ""}${f.hazards.length > 0 ? ` [${f.hazards.length} prefix hazard(s)${f.bug ? ", UNRESCUED" : ""}]` : ""}${f.caseFoldRisk ? " [CASE-FOLD RISK]" : ""}`);
|
|
17137
|
+
lines2.push(` fix: ${f.suggestion}`);
|
|
16553
17138
|
}
|
|
16554
17139
|
for (const f of report.duplicates) {
|
|
16555
|
-
|
|
16556
|
-
|
|
16557
|
-
|
|
17140
|
+
lines2.push(`parseman duplication: ${f.count}\xD7 identical ${f.size}-node shape (saves ${f.savings} nodes) \u2014 ${f.shape}`);
|
|
17141
|
+
lines2.push(` at: ${sitesLine(f.sites)}`);
|
|
17142
|
+
lines2.push(` fix: ${f.suggestion}`);
|
|
16558
17143
|
}
|
|
16559
17144
|
for (const f of report.nearDuplicates) {
|
|
16560
|
-
|
|
16561
|
-
|
|
16562
|
-
|
|
16563
|
-
|
|
17145
|
+
lines2.push(`parseman near-duplication: ${f.count} clones of a ${f.sharedSize}-node shape differing at ONE slot (saves ${f.savings} nodes) \u2014 ${f.shape}`);
|
|
17146
|
+
lines2.push(` slot: ${f.slotPath} \u2208 { ${f.variants.join(" | ")} }`);
|
|
17147
|
+
lines2.push(` at: ${sitesLine(f.sites)}`);
|
|
17148
|
+
lines2.push(` fix: ${f.suggestion}`);
|
|
16564
17149
|
}
|
|
16565
17150
|
for (const f of report.regexFragments) {
|
|
16566
|
-
|
|
16567
|
-
|
|
16568
|
-
|
|
17151
|
+
lines2.push(`parseman regex-fragment: \`${f.fragment}\` (${f.branches} branches) re-spelled in ${f.count} regex() terminals`);
|
|
17152
|
+
lines2.push(` at: ${sitesLine(f.sites)}`);
|
|
17153
|
+
lines2.push(` fix: ${f.suggestion}`);
|
|
16569
17154
|
}
|
|
16570
17155
|
for (const f of report.regexClasses) {
|
|
16571
|
-
|
|
16572
|
-
for (const v of f.variants)
|
|
17156
|
+
lines2.push(`parseman regex-class${f.drifted ? " DRIFT" : ""}: [${f.canonical}] across ${f.count} regex() terminals${f.bmpCeiling ? " [BMP ceiling]" : ""}`);
|
|
17157
|
+
for (const v of f.variants) lines2.push(` [${v.source}] \xD7${v.count} ${v.delta}
|
|
16573
17158
|
${sitesLine(v.sites)}`);
|
|
16574
|
-
|
|
17159
|
+
lines2.push(` fix: ${f.suggestion}`);
|
|
16575
17160
|
}
|
|
16576
17161
|
for (const f of report.overlaps) {
|
|
16577
|
-
|
|
16578
|
-
|
|
17162
|
+
lines2.push(`parseman overlap @ ${siteToString(f.site)}: arm[${f.a}] \u2229 arm[${f.b}] on ${firstSetToString(f.on)}${f.sharedPrefix === null ? "" : ` \u2014 shared prefix: ${f.sharedPrefix}`}${f.handledByStrategy ? " [sharedPrefix strategy already handles this]" : ""}`);
|
|
17163
|
+
lines2.push(` fix: ${f.suggestion}`);
|
|
16579
17164
|
}
|
|
16580
|
-
return
|
|
17165
|
+
return lines2;
|
|
16581
17166
|
}
|
|
16582
17167
|
function duplicationFindingCount(report) {
|
|
16583
17168
|
return report.duplicates.length + report.nearDuplicates.length + report.regexFragments.length + report.regexClasses.length + report.overlaps.length + report.rewrites.length + report.divergentNodes.length + report.structureLoss.length + report.keywordRegexes.length;
|
|
@@ -16611,11 +17196,11 @@ function reportDuplication(opt, analyze) {
|
|
|
16611
17196
|
);
|
|
16612
17197
|
return void 0;
|
|
16613
17198
|
}
|
|
16614
|
-
const
|
|
16615
|
-
if (
|
|
17199
|
+
const lines2 = formatDuplicationFindings(report);
|
|
17200
|
+
if (lines2.length > 0) {
|
|
16616
17201
|
if (level === "error") throw new Error(`parseman: ${duplicationFindingCount(report)} duplication/overlap finding(s)
|
|
16617
|
-
${
|
|
16618
|
-
for (const l of
|
|
17202
|
+
${lines2.join("\n")}`);
|
|
17203
|
+
for (const l of lines2) console.warn(l);
|
|
16619
17204
|
}
|
|
16620
17205
|
return report;
|
|
16621
17206
|
}
|
|
@@ -16626,8 +17211,46 @@ function runDuplicationDiagnosticRules(ruleMap, opt) {
|
|
|
16626
17211
|
return reportDuplication(opt, (o) => analyzeDuplicationRules(ruleMap, o));
|
|
16627
17212
|
}
|
|
16628
17213
|
|
|
17214
|
+
// src/table/select-hot.ts
|
|
17215
|
+
var LOOP = 8;
|
|
17216
|
+
var ROUNDS = 60;
|
|
17217
|
+
var CAP = 1e12;
|
|
17218
|
+
function selectHotSites(code, entries, siteBytes, budget, profile) {
|
|
17219
|
+
const selected = /* @__PURE__ */ new Set();
|
|
17220
|
+
if (budget <= 0) return selected;
|
|
17221
|
+
const weight = profile === void 0 ? staticWeights(code, entries) : void 0;
|
|
17222
|
+
const w = (ip) => (weight !== void 0 ? weight.get(ip) : profile[ip]) ?? 0;
|
|
17223
|
+
const ranked = [...siteBytes.keys()].sort((a, b) => w(b) / siteBytes.get(b) - w(a) / siteBytes.get(a) || a - b);
|
|
17224
|
+
let spent = 0;
|
|
17225
|
+
for (const ip of ranked) {
|
|
17226
|
+
if (w(ip) === 0) break;
|
|
17227
|
+
const bytes = siteBytes.get(ip);
|
|
17228
|
+
if (spent + bytes > budget) continue;
|
|
17229
|
+
spent += bytes;
|
|
17230
|
+
selected.add(ip);
|
|
17231
|
+
}
|
|
17232
|
+
return selected;
|
|
17233
|
+
}
|
|
17234
|
+
function staticWeights(code, entries) {
|
|
17235
|
+
let weight = /* @__PURE__ */ new Map();
|
|
17236
|
+
const kids = [];
|
|
17237
|
+
for (let round = 0; round < ROUNDS; round++) {
|
|
17238
|
+
const next = /* @__PURE__ */ new Map();
|
|
17239
|
+
for (const ip of entries) next.set(ip, 1);
|
|
17240
|
+
for (const [ip, w] of weight) {
|
|
17241
|
+
kids.length = 0;
|
|
17242
|
+
childSlots(code, ip, kids);
|
|
17243
|
+
const op = code[ip];
|
|
17244
|
+
const scale = op === OP_REP || op === OP_REPV ? LOOP : op === OP_CHOICE || op === OP_DISPATCH ? 1 / Math.max(1, kids.length) : 1;
|
|
17245
|
+
for (const kid of kids) next.set(kid, Math.min(CAP, (next.get(kid) ?? 0) + w * scale));
|
|
17246
|
+
}
|
|
17247
|
+
weight = next;
|
|
17248
|
+
}
|
|
17249
|
+
return weight;
|
|
17250
|
+
}
|
|
17251
|
+
|
|
16629
17252
|
// src/table/compile-rule-map.ts
|
|
16630
|
-
var
|
|
17253
|
+
var SUPERCOMPILE_GROWTH = 1.05;
|
|
16631
17254
|
function resolveHostMode(ruleMap, explicit) {
|
|
16632
17255
|
return explicit ?? ruleMap.map(([, r]) => r._meta.grammarHostMode).find(Boolean) ?? "ast";
|
|
16633
17256
|
}
|
|
@@ -16724,14 +17347,40 @@ function compileRuleMap(ruleMap, opts = {}) {
|
|
|
16724
17347
|
entry: null,
|
|
16725
17348
|
runtimeRef: opts.runtimeRef ?? "tableRules",
|
|
16726
17349
|
fnSources: sources,
|
|
16727
|
-
...options.
|
|
17350
|
+
...options.select !== void 0 && options.select.size > 0 ? { assemblies: [{ ...defaultAssemblyCfgs(artifact)[0], select: options.select }] } : {},
|
|
16728
17351
|
...metadataSource === void 0 ? {} : { metadataSource }
|
|
16729
17352
|
});
|
|
16730
17353
|
const replacement = replacementWithMetadata();
|
|
17354
|
+
const selectAssembly = (budget, profile) => {
|
|
17355
|
+
const none = { sites: /* @__PURE__ */ new Set(), bytes: 0 };
|
|
17356
|
+
if (hostMode !== "ast" || prog.lines === 1) return none;
|
|
17357
|
+
const table = resolveTable(artifact);
|
|
17358
|
+
const cfg = defaultAssemblyCfgs(artifact)[0];
|
|
17359
|
+
const roots = assemblyExtraIps(artifact);
|
|
17360
|
+
let siteBytes, fixed;
|
|
17361
|
+
try {
|
|
17362
|
+
siteBytes = emitAssemblySource(table, artifact, cfg, roots, true).siteBytes;
|
|
17363
|
+
fixed = emitAssemblySource(table, artifact, cfg, roots, true, /* @__PURE__ */ new Set()).source.length;
|
|
17364
|
+
} catch (e) {
|
|
17365
|
+
if (e instanceof Unemittable) return { ...none, refusal: e.construct };
|
|
17366
|
+
throw e;
|
|
17367
|
+
}
|
|
17368
|
+
const ceiling = budget / SUPERCOMPILE_GROWTH;
|
|
17369
|
+
let target = ceiling;
|
|
17370
|
+
for (let attempt2 = 0; attempt2 < 16; attempt2++) {
|
|
17371
|
+
const sites = selectHotSites(artifact.code, Object.values(artifact.rules), siteBytes, target - fixed, profile);
|
|
17372
|
+
if (sites.size === 0) return none;
|
|
17373
|
+
const bytes = emitAssemblySource(table, artifact, cfg, roots, true, sites).source.length;
|
|
17374
|
+
if (bytes <= ceiling) return { sites, bytes: Math.ceil(bytes * SUPERCOMPILE_GROWTH) };
|
|
17375
|
+
target *= Math.min(ceiling / bytes, 0.99);
|
|
17376
|
+
}
|
|
17377
|
+
return none;
|
|
17378
|
+
};
|
|
16731
17379
|
return {
|
|
16732
17380
|
keys: ruleMap.map(([key]) => key),
|
|
16733
17381
|
replacement,
|
|
16734
17382
|
replacementWithMetadata,
|
|
17383
|
+
selectAssembly,
|
|
16735
17384
|
hostMode,
|
|
16736
17385
|
// WHAT THE FLAG MEANS is "a DIRECT BUILDER's positioned-CST branch was
|
|
16737
17386
|
// dropped", which is what the driver's `'ast' artifact + CST host` check keys
|
|
@@ -16886,7 +17535,7 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
|
|
|
16886
17535
|
const emitOpts = { fnSources: sources };
|
|
16887
17536
|
const source = printable ? emitTableModule(artifact, { name: "grammar", ...emitOpts }) : "";
|
|
16888
17537
|
const inlineExpression = printable ? emitTableExpression(artifact, { entry: ENTRY, runtimeRef: opts.runtimeRef ?? "tableRules", ...emitOpts }) : null;
|
|
16889
|
-
const
|
|
17538
|
+
const runOnce2 = (input, pos, ctx) => entry(input, pos, ctx);
|
|
16890
17539
|
return {
|
|
16891
17540
|
source,
|
|
16892
17541
|
inlineExpression,
|
|
@@ -16900,10 +17549,10 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
|
|
|
16900
17549
|
// parser runs where a combinator does. A caller probing many positions
|
|
16901
17550
|
// passes one context and pays for none per call.
|
|
16902
17551
|
parse(input, pos = 0, ctx) {
|
|
16903
|
-
return
|
|
17552
|
+
return runOnce2(input, pos, ctx ?? createParseContext());
|
|
16904
17553
|
},
|
|
16905
17554
|
parseWithContext(input, parseCtx, pos = 0) {
|
|
16906
|
-
return
|
|
17555
|
+
return runOnce2(input, pos, parseCtx);
|
|
16907
17556
|
},
|
|
16908
17557
|
/**
|
|
16909
17558
|
* NO LONGER REFUSES. It used to throw unless the caller passed
|
|
@@ -16919,7 +17568,7 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
|
|
|
16919
17568
|
const errors = [];
|
|
16920
17569
|
ctx._errors = errors;
|
|
16921
17570
|
ctx._tolerant = true;
|
|
16922
|
-
const r =
|
|
17571
|
+
const r = runOnce2(input, pos, ctx);
|
|
16923
17572
|
return { ...r, errors };
|
|
16924
17573
|
}
|
|
16925
17574
|
};
|
|
@@ -16962,6 +17611,9 @@ function childrenOf3(def) {
|
|
|
16962
17611
|
];
|
|
16963
17612
|
case "routed":
|
|
16964
17613
|
return def.fallback ? [def.fallback] : [];
|
|
17614
|
+
case "lines":
|
|
17615
|
+
return [def.prefix, def.body, ...def.first === void 0 ? [] : [def.first], ...def.lazy === void 0 ? [] : [def.lazy]];
|
|
17616
|
+
case "columns":
|
|
16965
17617
|
case "lazy":
|
|
16966
17618
|
case "literal":
|
|
16967
17619
|
case "regex":
|
|
@@ -17291,6 +17943,15 @@ ${outerDecls.map((d) => " " + d).join("\n")}
|
|
|
17291
17943
|
return `expect(${kid(def.parser)}${def.label !== void 0 ? `, ${JSON.stringify(def.label)}` : ""})`;
|
|
17292
17944
|
case "scanTo":
|
|
17293
17945
|
return `scanTo(${kid(def.sentinel)}, { skip: [${def.skip.map(kid).join(", ")}]${def.raw ? ", raw: true" : ""}, orEOF: ${def.orEOF}${def.recoverAt === void 0 ? "" : `, recoverAt: ${kid(def.recoverAt)}`}${def.stopAt === void 0 ? "" : `, stopAt: ${kid(def.stopAt)}`} })`;
|
|
17946
|
+
case "lines": {
|
|
17947
|
+
const options = [
|
|
17948
|
+
...def.first === void 0 ? [] : [`first: ${kid(def.first)}`],
|
|
17949
|
+
...def.lazy === void 0 ? [] : [`lazy: ${kid(def.lazy)}`]
|
|
17950
|
+
];
|
|
17951
|
+
return `lines(${kid(def.prefix)}, ${kid(def.body)}${options.length === 0 ? "" : `, { ${options.join(", ")} }`})`;
|
|
17952
|
+
}
|
|
17953
|
+
case "columns":
|
|
17954
|
+
return `columns(${def.n})`;
|
|
17294
17955
|
case "transform": {
|
|
17295
17956
|
if (def.fnSrc === void 0) throw new Unserializable("transform without fnSrc");
|
|
17296
17957
|
return `_tf(${kid(def.parser)}, ${JSON.stringify(def.fnSrc)}${def.recognitionOnly ? ", true" : ""})`;
|
|
@@ -17355,7 +18016,7 @@ function fieldOptionsSrc(def) {
|
|
|
17355
18016
|
}
|
|
17356
18017
|
|
|
17357
18018
|
// src/version.ts
|
|
17358
|
-
var PARSEMAN_VERSION = "0.
|
|
18019
|
+
var PARSEMAN_VERSION = "0.57.0";
|
|
17359
18020
|
|
|
17360
18021
|
// src/compiler/compile-linkable-table.ts
|
|
17361
18022
|
function isLocal(rule) {
|
|
@@ -17448,6 +18109,337 @@ function cstBuildHost(typeOrOptions, children3, _fields, span, rawChildren, triv
|
|
|
17448
18109
|
cstBuildHost._parsemanCstOutput = true;
|
|
17449
18110
|
var COMPOSED_PIECES = /* @__PURE__ */ Symbol.for("parseman.composedPieces");
|
|
17450
18111
|
|
|
18112
|
+
// src/cst/trivia-entries.ts
|
|
18113
|
+
var EMPTY_INDICES = Object.freeze([]);
|
|
18114
|
+
var EMPTY_GAPS = Object.freeze([]);
|
|
18115
|
+
var SELECTED_ROOT_STRIDE = 5;
|
|
18116
|
+
function buildRootTriviaIndex(log, labels) {
|
|
18117
|
+
const length = Math.floor(log.length / SELECTED_ROOT_STRIDE);
|
|
18118
|
+
const markerOffset = (i) => i * SELECTED_ROOT_STRIDE;
|
|
18119
|
+
const ownedRangeStart = (i) => log[markerOffset(i)];
|
|
18120
|
+
const ownedRangeEnd = (i) => log[markerOffset(i) + 1];
|
|
18121
|
+
const markerStart = (i) => log[markerOffset(i) + 2];
|
|
18122
|
+
const markerEnd = (i) => log[markerOffset(i) + 3];
|
|
18123
|
+
const markerKind = (i) => log[markerOffset(i) + 4];
|
|
18124
|
+
const entries = {
|
|
18125
|
+
length,
|
|
18126
|
+
labels,
|
|
18127
|
+
stride: SELECTED_ROOT_STRIDE,
|
|
18128
|
+
start: markerStart,
|
|
18129
|
+
end: markerEnd,
|
|
18130
|
+
insertIndex: () => void 0,
|
|
18131
|
+
kindIndex: markerKind,
|
|
18132
|
+
kind(i) {
|
|
18133
|
+
return labels[markerKind(i)];
|
|
18134
|
+
},
|
|
18135
|
+
text(i, input) {
|
|
18136
|
+
return input.slice(markerStart(i), markerEnd(i));
|
|
18137
|
+
}
|
|
18138
|
+
};
|
|
18139
|
+
const lowerBound = (offset, by) => {
|
|
18140
|
+
let lo = 0;
|
|
18141
|
+
let hi = length;
|
|
18142
|
+
while (lo < hi) {
|
|
18143
|
+
const mid = lo + hi >>> 1;
|
|
18144
|
+
if (by(mid) < offset) lo = mid + 1;
|
|
18145
|
+
else hi = mid;
|
|
18146
|
+
}
|
|
18147
|
+
return lo;
|
|
18148
|
+
};
|
|
18149
|
+
const gapRowsAt = (offset, direction) => {
|
|
18150
|
+
const edge = direction === "before" ? ownedRangeEnd : ownedRangeStart;
|
|
18151
|
+
let first = lowerBound(offset, edge);
|
|
18152
|
+
if (first === length || edge(first) !== offset) return void 0;
|
|
18153
|
+
const start = ownedRangeStart(first);
|
|
18154
|
+
const end = ownedRangeEnd(first);
|
|
18155
|
+
while (first > 0 && ownedRangeStart(first - 1) === start && ownedRangeEnd(first - 1) === end) first--;
|
|
18156
|
+
let last = first + 1;
|
|
18157
|
+
while (last < length && ownedRangeStart(last) === start && ownedRangeEnd(last) === end) last++;
|
|
18158
|
+
return [first, last];
|
|
18159
|
+
};
|
|
18160
|
+
const indices = (first, last) => {
|
|
18161
|
+
const out = [];
|
|
18162
|
+
for (let i = first; i < last; i++) out.push(i);
|
|
18163
|
+
return out;
|
|
18164
|
+
};
|
|
18165
|
+
const makeGap = (first, last) => {
|
|
18166
|
+
const start = ownedRangeStart(first);
|
|
18167
|
+
const end = ownedRangeEnd(first);
|
|
18168
|
+
let entryIndices;
|
|
18169
|
+
return {
|
|
18170
|
+
start,
|
|
18171
|
+
end,
|
|
18172
|
+
get entryIndices() {
|
|
18173
|
+
return entryIndices ??= indices(first, last);
|
|
18174
|
+
},
|
|
18175
|
+
hasKind(kind) {
|
|
18176
|
+
for (let i = first; i < last; i++) {
|
|
18177
|
+
if (labels[markerKind(i)] === kind) return true;
|
|
18178
|
+
}
|
|
18179
|
+
return false;
|
|
18180
|
+
},
|
|
18181
|
+
text(input) {
|
|
18182
|
+
return input.slice(start, end);
|
|
18183
|
+
}
|
|
18184
|
+
};
|
|
18185
|
+
};
|
|
18186
|
+
let maps;
|
|
18187
|
+
const getMaps = () => {
|
|
18188
|
+
if (maps !== void 0) return maps;
|
|
18189
|
+
const before = /* @__PURE__ */ new Map();
|
|
18190
|
+
const after = /* @__PURE__ */ new Map();
|
|
18191
|
+
const beforeGaps = /* @__PURE__ */ new Map();
|
|
18192
|
+
const afterGaps = /* @__PURE__ */ new Map();
|
|
18193
|
+
const gaps = [];
|
|
18194
|
+
for (let first = 0; first < length; ) {
|
|
18195
|
+
let last = first + 1;
|
|
18196
|
+
while (last < length && ownedRangeStart(last) === ownedRangeStart(first) && ownedRangeEnd(last) === ownedRangeEnd(first)) last++;
|
|
18197
|
+
const gap = makeGap(first, last);
|
|
18198
|
+
gaps.push(gap);
|
|
18199
|
+
afterGaps.set(gap.start, gap);
|
|
18200
|
+
beforeGaps.set(gap.end, gap);
|
|
18201
|
+
after.set(gap.start, [...gap.entryIndices]);
|
|
18202
|
+
before.set(gap.end, [...gap.entryIndices]);
|
|
18203
|
+
first = last;
|
|
18204
|
+
}
|
|
18205
|
+
maps = { before, after, beforeGaps, afterGaps, gaps };
|
|
18206
|
+
return maps;
|
|
18207
|
+
};
|
|
18208
|
+
return {
|
|
18209
|
+
entries,
|
|
18210
|
+
labels,
|
|
18211
|
+
get before() {
|
|
18212
|
+
return getMaps().before;
|
|
18213
|
+
},
|
|
18214
|
+
get after() {
|
|
18215
|
+
return getMaps().after;
|
|
18216
|
+
},
|
|
18217
|
+
entryIndicesBefore(offset) {
|
|
18218
|
+
const rows = gapRowsAt(offset, "before");
|
|
18219
|
+
return rows ? indices(rows[0], rows[1]) : EMPTY_INDICES;
|
|
18220
|
+
},
|
|
18221
|
+
entryIndicesAfter(offset) {
|
|
18222
|
+
const rows = gapRowsAt(offset, "after");
|
|
18223
|
+
return rows ? indices(rows[0], rows[1]) : EMPTY_INDICES;
|
|
18224
|
+
},
|
|
18225
|
+
gapBefore(offset) {
|
|
18226
|
+
const rows = gapRowsAt(offset, "before");
|
|
18227
|
+
return rows ? makeGap(rows[0], rows[1]) : void 0;
|
|
18228
|
+
},
|
|
18229
|
+
gapAfter(offset) {
|
|
18230
|
+
const rows = gapRowsAt(offset, "after");
|
|
18231
|
+
return rows ? makeGap(rows[0], rows[1]) : void 0;
|
|
18232
|
+
},
|
|
18233
|
+
gaps() {
|
|
18234
|
+
return getMaps().gaps;
|
|
18235
|
+
},
|
|
18236
|
+
gapsWithKind(kind) {
|
|
18237
|
+
const kinds = typeof kind === "string" ? [kind] : kind;
|
|
18238
|
+
const matches2 = [];
|
|
18239
|
+
for (let first = 0; first < length; ) {
|
|
18240
|
+
let last = first + 1;
|
|
18241
|
+
while (last < length && ownedRangeStart(last) === ownedRangeStart(first) && ownedRangeEnd(last) === ownedRangeEnd(first)) last++;
|
|
18242
|
+
let matched = false;
|
|
18243
|
+
for (let i = first; i < last && !matched; i++) {
|
|
18244
|
+
const label2 = labels[markerKind(i)];
|
|
18245
|
+
for (const kind2 of kinds) {
|
|
18246
|
+
if (label2 === kind2) {
|
|
18247
|
+
matched = true;
|
|
18248
|
+
break;
|
|
18249
|
+
}
|
|
18250
|
+
}
|
|
18251
|
+
}
|
|
18252
|
+
if (matched) matches2.push(makeGap(first, last));
|
|
18253
|
+
first = last;
|
|
18254
|
+
}
|
|
18255
|
+
return matches2.length === 0 ? EMPTY_GAPS : matches2;
|
|
18256
|
+
}
|
|
18257
|
+
};
|
|
18258
|
+
}
|
|
18259
|
+
|
|
18260
|
+
// src/functional/run.ts
|
|
18261
|
+
var SELECT_EXAMPLE = "run(entry, input, { rootTrivia: { select: ['blockComment', 'lineComment'] } })";
|
|
18262
|
+
var REMOVED_RUN_RESULT_FIELDS = [
|
|
18263
|
+
[
|
|
18264
|
+
"triviaMap",
|
|
18265
|
+
`It was a dense root-trivia index built on every parse; root trivia is now an OPT-IN sparse capture, because most grammars paid for an index they never read. Migration: name the trivia labels your grammar defines \u2014 ${SELECT_EXAMPLE} \u2014 and read \`RunResult.rootTrivia\`, whose \`.index\` carries the labels and gap lookups \`triviaMap\` exposed.`
|
|
18266
|
+
],
|
|
18267
|
+
[
|
|
18268
|
+
"triviaLog",
|
|
18269
|
+
`It was the flat \`start, end[, kindIndex]\` log every other trivia view was derived from, and it is no longer allocated at all \u2014 not empty, absent. Migration: request the labels you need \u2014 ${SELECT_EXAMPLE} \u2014 and read \`RunResult.rootTrivia.rows\`. Do NOT reuse a stride-2/3 reader: rows are a different width and a different unit (one row per SELECTED marker, not one per trivia chunk), so an old loop reads confidently wrong offsets rather than failing.`
|
|
18270
|
+
],
|
|
18271
|
+
[
|
|
18272
|
+
"triviaKindLabels",
|
|
18273
|
+
`It was already optional, so nothing ever flagged its disappearance \u2014 and \`triviaKindMask(undefined, \u2026)\` means "capture everything", so reading it now silently WIDENS capture instead of erroring. Migration: request labels \u2014 ${SELECT_EXAMPLE} \u2014 then the set you asked for is \`RunResult.rootTrivia.select\` and the resolved table is \`RunResult.rootTrivia.index.labels\`.`
|
|
18274
|
+
]
|
|
18275
|
+
];
|
|
18276
|
+
var RunResultRecord = class {
|
|
18277
|
+
constructor(ok, value, span, expected, errors, unconsumedFrom) {
|
|
18278
|
+
this.ok = ok;
|
|
18279
|
+
this.value = value;
|
|
18280
|
+
this.span = span;
|
|
18281
|
+
this.expected = expected;
|
|
18282
|
+
this.errors = errors;
|
|
18283
|
+
this.unconsumedFrom = unconsumedFrom;
|
|
18284
|
+
}
|
|
18285
|
+
};
|
|
18286
|
+
var RunResultWithRootTrivia = class {
|
|
18287
|
+
constructor(ok, value, span, expected, errors, rootTrivia, unconsumedFrom) {
|
|
18288
|
+
this.ok = ok;
|
|
18289
|
+
this.value = value;
|
|
18290
|
+
this.span = span;
|
|
18291
|
+
this.expected = expected;
|
|
18292
|
+
this.errors = errors;
|
|
18293
|
+
this.rootTrivia = rootTrivia;
|
|
18294
|
+
this.unconsumedFrom = unconsumedFrom;
|
|
18295
|
+
}
|
|
18296
|
+
};
|
|
18297
|
+
for (const proto of [RunResultRecord.prototype, RunResultWithRootTrivia.prototype]) {
|
|
18298
|
+
for (const [name, detail] of REMOVED_RUN_RESULT_FIELDS) {
|
|
18299
|
+
Object.defineProperty(proto, name, {
|
|
18300
|
+
configurable: true,
|
|
18301
|
+
enumerable: false,
|
|
18302
|
+
get() {
|
|
18303
|
+
throw new TypeError(
|
|
18304
|
+
`RunResult.${name} was REMOVED in parseman 0.44.0 and has no default replacement. ${detail}`
|
|
18305
|
+
);
|
|
18306
|
+
}
|
|
18307
|
+
});
|
|
18308
|
+
}
|
|
18309
|
+
}
|
|
18310
|
+
var invoke = (r, input, pos, ctx) => typeof r === "function" ? r(input, pos, ctx) : r.parse(input, pos, ctx);
|
|
18311
|
+
function ambientTriviaFromRunnable(r) {
|
|
18312
|
+
if (!r) return void 0;
|
|
18313
|
+
if (typeof r === "function") return r._meta?.grammarTrivia;
|
|
18314
|
+
if (r._meta.isTrivia) return void 0;
|
|
18315
|
+
return r._meta.grammarTrivia ?? (r._def.tag === "grammar" ? r._def.triviaParser : void 0);
|
|
18316
|
+
}
|
|
18317
|
+
function triviaKindLabelsFromRunnable(r) {
|
|
18318
|
+
if (!r) return void 0;
|
|
18319
|
+
if (typeof r === "function") return r._meta?.triviaKindLabels;
|
|
18320
|
+
const grammarTrivia = r._meta.grammarTrivia;
|
|
18321
|
+
return grammarTrivia?._meta.triviaKindLabels ?? r._meta.triviaKindLabels ?? (r._def.tag === "grammar" ? r._def.triviaParser?._meta.triviaKindLabels : void 0);
|
|
18322
|
+
}
|
|
18323
|
+
function rootTriviaClassifiedFromRunnable(r) {
|
|
18324
|
+
if (!r) return false;
|
|
18325
|
+
if (typeof r === "function") return r._meta?.rootTriviaClassified === true;
|
|
18326
|
+
const grammarTrivia = r._meta.grammarTrivia;
|
|
18327
|
+
return grammarTrivia?._meta.rootTriviaClassified === true || r._meta.rootTriviaClassified === true;
|
|
18328
|
+
}
|
|
18329
|
+
function makeSelectedRootLabelIndex(labels) {
|
|
18330
|
+
const index = /* @__PURE__ */ Object.create(null);
|
|
18331
|
+
for (let i = 0; i < labels.length; i++) {
|
|
18332
|
+
if (index[labels[i]] === void 0) index[labels[i]] = i;
|
|
18333
|
+
}
|
|
18334
|
+
return index;
|
|
18335
|
+
}
|
|
18336
|
+
function growSpanEnd(span, input, end) {
|
|
18337
|
+
if (span.endLine === void 0 || span.endColumn === void 0) {
|
|
18338
|
+
return { start: span.start, end };
|
|
18339
|
+
}
|
|
18340
|
+
let line = span.endLine;
|
|
18341
|
+
let column = span.endColumn;
|
|
18342
|
+
for (let i = span.end; i < end; i++) {
|
|
18343
|
+
if (input.charCodeAt(i) === 10) {
|
|
18344
|
+
line++;
|
|
18345
|
+
column = 1;
|
|
18346
|
+
} else {
|
|
18347
|
+
column++;
|
|
18348
|
+
}
|
|
18349
|
+
}
|
|
18350
|
+
return { ...span, end, endLine: line, endColumn: column };
|
|
18351
|
+
}
|
|
18352
|
+
function runOnce(entry, input, options) {
|
|
18353
|
+
if (typeof entry !== "function" && typeof entry?.parse !== "function") {
|
|
18354
|
+
throw new TypeError(
|
|
18355
|
+
`run(): start production is ${entry === null ? "null" : typeof entry}, not a rule \u2014 the requested grammar rule does not exist (check the rule name).`
|
|
18356
|
+
);
|
|
18357
|
+
}
|
|
18358
|
+
const rootTriviaSelection = options.rootTrivia?.select;
|
|
18359
|
+
const captureRootTrivia = rootTriviaSelection !== void 0 && rootTriviaSelection.length > 0;
|
|
18360
|
+
const selectedRootLog = captureRootTrivia ? [] : void 0;
|
|
18361
|
+
const selectedRootLabelIndex = captureRootTrivia ? makeSelectedRootLabelIndex(rootTriviaSelection) : void 0;
|
|
18362
|
+
const errors = [];
|
|
18363
|
+
const grammarTrivia = typeof entry !== "function" ? entry._meta.grammarTrivia : void 0;
|
|
18364
|
+
const grammarScanSkip = typeof entry !== "function" ? entry._meta.grammarScanSkip : void 0;
|
|
18365
|
+
const triviaKindLabels = triviaKindLabelsFromRunnable(entry) ?? triviaKindLabelsFromRunnable(options.trivia);
|
|
18366
|
+
if (captureRootTrivia && triviaKindLabels === void 0) {
|
|
18367
|
+
throw new TypeError("run(): rootTrivia.select requires labeled grammar trivia.");
|
|
18368
|
+
}
|
|
18369
|
+
if (captureRootTrivia) {
|
|
18370
|
+
for (const label2 of rootTriviaSelection) {
|
|
18371
|
+
if (!triviaKindLabels.includes(label2)) {
|
|
18372
|
+
throw new TypeError(`run(): rootTrivia.select contains unknown trivia label ${JSON.stringify(label2)}.`);
|
|
18373
|
+
}
|
|
18374
|
+
}
|
|
18375
|
+
}
|
|
18376
|
+
if (captureRootTrivia && !rootTriviaClassifiedFromRunnable(entry) && !rootTriviaClassifiedFromRunnable(options.trivia)) {
|
|
18377
|
+
throw new TypeError(
|
|
18378
|
+
"run(): rootTrivia.select requires classifiedTrivia() at the root."
|
|
18379
|
+
);
|
|
18380
|
+
}
|
|
18381
|
+
const stamped = entry;
|
|
18382
|
+
assertHostModeCompatible(
|
|
18383
|
+
typeof entry === "function" ? stamped[FUSED_HOST_MODE] ?? "ast" : entry._meta.grammarHostMode ?? "ast",
|
|
18384
|
+
options.build,
|
|
18385
|
+
typeof entry === "function" && stamped[FUSED_HOST_ELIDED] === true
|
|
18386
|
+
);
|
|
18387
|
+
const ctx = createParseContext();
|
|
18388
|
+
if (captureRootTrivia) {
|
|
18389
|
+
ctx._rootTriviaLog = selectedRootLog;
|
|
18390
|
+
ctx._rootTriviaKindIndex = selectedRootLabelIndex;
|
|
18391
|
+
ctx._rootTriviaStrictScopes = true;
|
|
18392
|
+
}
|
|
18393
|
+
ctx._errors = errors;
|
|
18394
|
+
ctx.build = options.build;
|
|
18395
|
+
ctx.state = options.state;
|
|
18396
|
+
if (grammarTrivia !== void 0) ctx.trivia = grammarTrivia;
|
|
18397
|
+
if (triviaKindLabels) ctx.triviaKindLabels = triviaKindLabels;
|
|
18398
|
+
if (grammarScanSkip !== void 0) ctx.scanSkip = grammarScanSkip;
|
|
18399
|
+
if (options.triviaCaptureMask !== void 0) ctx._triviaCaptureMask = options.triviaCaptureMask;
|
|
18400
|
+
if (options.tolerant) {
|
|
18401
|
+
ctx._tolerant = true;
|
|
18402
|
+
ctx._rec = REC;
|
|
18403
|
+
}
|
|
18404
|
+
if (options.instrumentation !== void 0) {
|
|
18405
|
+
ctx._grammarCoverage = options.instrumentation._grammarCoverage;
|
|
18406
|
+
ctx._grammarTrace = options.instrumentation._grammarTrace;
|
|
18407
|
+
}
|
|
18408
|
+
const r = invoke(entry, input, 0, ctx);
|
|
18409
|
+
const value = r.ok ? r.value : void 0;
|
|
18410
|
+
let span = r.span ?? { start: 0, end: 0 };
|
|
18411
|
+
const expected = r.ok ? [] : r.expected ?? [];
|
|
18412
|
+
let unconsumedFrom = null;
|
|
18413
|
+
if (r.ok) {
|
|
18414
|
+
let pos = span.end;
|
|
18415
|
+
const tail = options.trivia ?? ambientTriviaFromRunnable(entry);
|
|
18416
|
+
if (tail !== void 0 && pos < input.length) {
|
|
18417
|
+
const t = invoke(tail, input, pos, createParseContext());
|
|
18418
|
+
if (t.ok && t.span.end > pos) {
|
|
18419
|
+
span = growSpanEnd(span, input, t.span.end);
|
|
18420
|
+
pos = t.span.end;
|
|
18421
|
+
}
|
|
18422
|
+
}
|
|
18423
|
+
unconsumedFrom = pos < input.length ? pos : null;
|
|
18424
|
+
}
|
|
18425
|
+
return selectedRootLog !== void 0 && selectedRootLog.length > 0 ? new RunResultWithRootTrivia(
|
|
18426
|
+
r.ok,
|
|
18427
|
+
value,
|
|
18428
|
+
span,
|
|
18429
|
+
expected,
|
|
18430
|
+
errors,
|
|
18431
|
+
{
|
|
18432
|
+
rows: selectedRootLog,
|
|
18433
|
+
select: rootTriviaSelection,
|
|
18434
|
+
index: buildRootTriviaIndex(selectedRootLog, rootTriviaSelection)
|
|
18435
|
+
},
|
|
18436
|
+
unconsumedFrom
|
|
18437
|
+
) : new RunResultRecord(r.ok, value, span, expected, errors, unconsumedFrom);
|
|
18438
|
+
}
|
|
18439
|
+
function run(entry, input, options = {}) {
|
|
18440
|
+
return runOnce(entry, input, options);
|
|
18441
|
+
}
|
|
18442
|
+
|
|
17451
18443
|
// src/combinators/gate.ts
|
|
17452
18444
|
function gate(predicate) {
|
|
17453
18445
|
const meta = {
|
|
@@ -17882,6 +18874,10 @@ var SUPPORTED = {
|
|
|
17882
18874
|
field: (...a) => field(a[0], a[1], a[2]),
|
|
17883
18875
|
noTrivia: (...a) => noTrivia(a[0]),
|
|
17884
18876
|
token: (...a) => token(a[0]),
|
|
18877
|
+
// `lines(prefix, body, { first, lazy })`: its options are combinators, which the
|
|
18878
|
+
// generic argument evaluation already resolves; a missing option stays absent.
|
|
18879
|
+
lines: (...a) => lines(a[0], a[1], a[2]),
|
|
18880
|
+
columns: (...a) => columns(a[0]),
|
|
17885
18881
|
// `routed(fallback)` — the fallback must be forwarded. A zero-arg entry here read
|
|
17886
18882
|
// as "routed takes no arguments" and SILENTLY built a bare `routed()`, so a
|
|
17887
18883
|
// production written to work both inside and outside a dispatch branch lost its
|
|
@@ -19519,19 +20515,14 @@ function fallback(emitted, reason, before) {
|
|
|
19519
20515
|
}
|
|
19520
20516
|
};
|
|
19521
20517
|
}
|
|
19522
|
-
function supercompileRuleMapReplacement(prog, replacement) {
|
|
20518
|
+
function supercompileRuleMapReplacement(prog, replacement, select) {
|
|
19523
20519
|
const cfg = defaultAssemblyCfgs(prog)[0];
|
|
19524
20520
|
if (cfg === void 0) return replacement;
|
|
19525
|
-
const extraIps =
|
|
19526
|
-
for (const scan of prog.scans ?? []) {
|
|
19527
|
-
for (const ref2 of scan.skip) extraIps.push(ref2[0]);
|
|
19528
|
-
if (scan.sentinel !== void 0) extraIps.push(scan.sentinel[0]);
|
|
19529
|
-
}
|
|
19530
|
-
for (const set of prog.scanSkip ?? []) for (const ref2 of set) extraIps.push(ref2[0]);
|
|
20521
|
+
const extraIps = assemblyExtraIps(prog);
|
|
19531
20522
|
let canonical2;
|
|
19532
20523
|
let candidate;
|
|
19533
20524
|
try {
|
|
19534
|
-
canonical2 = emitAssemblySource(resolveTable(prog), prog, cfg, extraIps, true);
|
|
20525
|
+
canonical2 = emitAssemblySource(resolveTable(prog), prog, cfg, extraIps, true, select);
|
|
19535
20526
|
candidate = supercompileEmittedAssembly(prog, cfg, extraIps, canonical2);
|
|
19536
20527
|
} catch {
|
|
19537
20528
|
return replacement;
|
|
@@ -19834,6 +20825,7 @@ ${nested}
|
|
|
19834
20825
|
}
|
|
19835
20826
|
|
|
19836
20827
|
// src/plugin/ir-eval.ts
|
|
20828
|
+
var INERT_BUILDER = /* @__PURE__ */ Symbol("parseman.inertBuilder");
|
|
19837
20829
|
function evalRulesIR(ir) {
|
|
19838
20830
|
return evalIR(ir, rules);
|
|
19839
20831
|
}
|
|
@@ -19873,9 +20865,11 @@ function evalIR(ir, rulesImpl) {
|
|
|
19873
20865
|
if (staticError !== void 0 && staticError.length > 0) {
|
|
19874
20866
|
throw new Error(`IR direct node builder for ${type} must be macro-static and self-contained; unsupported binding(s): ${staticError.join(", ")}`);
|
|
19875
20867
|
}
|
|
19876
|
-
const
|
|
20868
|
+
const inert = (() => {
|
|
19877
20869
|
throw new Error("IR node build requires static re-lowering");
|
|
19878
|
-
})
|
|
20870
|
+
});
|
|
20871
|
+
inert[INERT_BUILDER] = type;
|
|
20872
|
+
const n = node(type, child, inert, opts);
|
|
19879
20873
|
n._def.buildSrc = src;
|
|
19880
20874
|
if (staticError !== void 0) n._def.buildStaticError = staticError;
|
|
19881
20875
|
if (sigSrc !== void 0) n._def.buildSigSrc = sigSrc;
|
|
@@ -19964,6 +20958,8 @@ function evalIR(ir, rulesImpl) {
|
|
|
19964
20958
|
"_nd",
|
|
19965
20959
|
"_gch",
|
|
19966
20960
|
"_wc",
|
|
20961
|
+
"lines",
|
|
20962
|
+
"columns",
|
|
19967
20963
|
`return (${ir})`
|
|
19968
20964
|
);
|
|
19969
20965
|
return fn(
|
|
@@ -20007,14 +21003,28 @@ function evalIR(ir, rulesImpl) {
|
|
|
20007
21003
|
_lf,
|
|
20008
21004
|
_nd,
|
|
20009
21005
|
_gch,
|
|
20010
|
-
_wc
|
|
21006
|
+
_wc,
|
|
21007
|
+
lines,
|
|
21008
|
+
columns
|
|
20011
21009
|
);
|
|
20012
21010
|
}
|
|
20013
21011
|
|
|
20014
21012
|
// src/plugin/index.ts
|
|
20015
21013
|
import { createHash } from "node:crypto";
|
|
20016
21014
|
var TABLE_RUNTIME_SPECIFIER = "parseman/table";
|
|
21015
|
+
var corpusCache = /* @__PURE__ */ new Map();
|
|
21016
|
+
function corpusTexts(profile) {
|
|
21017
|
+
return profile.files.map((file) => {
|
|
21018
|
+
const mtimeMs = fs2.statSync(file).mtimeMs;
|
|
21019
|
+
const hit = corpusCache.get(file);
|
|
21020
|
+
if (hit !== void 0 && hit.mtimeMs === mtimeMs) return hit.text;
|
|
21021
|
+
const text = fs2.readFileSync(file, "utf8");
|
|
21022
|
+
corpusCache.set(file, { mtimeMs, text });
|
|
21023
|
+
return text;
|
|
21024
|
+
});
|
|
21025
|
+
}
|
|
20017
21026
|
var PARSEMAN_MODULE = "parseman";
|
|
21027
|
+
var DEFAULT_ASSEMBLY_BUDGET = 0.25;
|
|
20018
21028
|
function reasonSuffix(runtimeOnly) {
|
|
20019
21029
|
return runtimeOnly === void 0 || runtimeOnly.length === 0 ? "" : ` \u2014 ${runtimeOnly.join("; ")}`;
|
|
20020
21030
|
}
|
|
@@ -20132,8 +21142,9 @@ var plugin_default = createUnplugin((opts = {}) => ({
|
|
|
20132
21142
|
transform(code, id) {
|
|
20133
21143
|
if (!code.includes("parseman")) return null;
|
|
20134
21144
|
if (!code.includes("macro")) return null;
|
|
21145
|
+
for (const file of opts.assemblyProfile?.files ?? []) this?.addWatchFile?.(file);
|
|
20135
21146
|
const moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE, ...opts.moduleAliases ?? []]);
|
|
20136
|
-
const result = transformMacro(code, id, moduleAliases, opts.warnUnloweredRegex === true, opts.recovery === true, opts.grammarCoverage === true);
|
|
21147
|
+
const result = transformMacro(code, id, moduleAliases, opts.warnUnloweredRegex === true, opts.recovery === true, opts.grammarCoverage === true, opts.assemblyProfile, opts.assemblyBudget);
|
|
20137
21148
|
if (result?.warnings.length) {
|
|
20138
21149
|
for (const w of result.warnings) {
|
|
20139
21150
|
if (typeof this?.warn === "function") this.warn(`[parseman] ${w}`);
|
|
@@ -20289,17 +21300,17 @@ function lowerPrivateSourceModule(file, moduleAliases, warnUnloweredRegex, recov
|
|
|
20289
21300
|
_sourceLowering.delete(file);
|
|
20290
21301
|
}
|
|
20291
21302
|
}
|
|
20292
|
-
function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE]), warnUnloweredRegex = false, recovery = false, grammarCoverage = false) {
|
|
21303
|
+
function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE]), warnUnloweredRegex = false, recovery = false, grammarCoverage = false, assemblyProfile, assemblyBudget = DEFAULT_ASSEMBLY_BUDGET) {
|
|
20293
21304
|
const depth = degradationCaptureDepth();
|
|
20294
21305
|
try {
|
|
20295
|
-
return transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recovery, grammarCoverage);
|
|
21306
|
+
return transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recovery, grammarCoverage, assemblyProfile, assemblyBudget);
|
|
20296
21307
|
} finally {
|
|
20297
21308
|
setReducerResolver(null);
|
|
20298
21309
|
setBuilderImportResolver(null);
|
|
20299
21310
|
for (const d of unwindDegradationCapture(depth)) console.warn(formatDegradation(d));
|
|
20300
21311
|
}
|
|
20301
21312
|
}
|
|
20302
|
-
function transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recovery, grammarCoverage) {
|
|
21313
|
+
function transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recovery, grammarCoverage, assemblyProfile, assemblyBudgetShare) {
|
|
20303
21314
|
let result;
|
|
20304
21315
|
try {
|
|
20305
21316
|
result = parseSync5(id, code);
|
|
@@ -21125,9 +22136,10 @@ ${names.map((n) => ` - ${n}`).join("\n")}` : " (it is not a static combinator/v
|
|
|
21125
22136
|
carried,
|
|
21126
22137
|
reflection: compiled.reflection
|
|
21127
22138
|
});
|
|
22139
|
+
const select = selectAssembly(init.start, "compose()", compiled, !declaresLeaf());
|
|
21128
22140
|
return {
|
|
21129
|
-
replacement: compiled
|
|
21130
|
-
exportedReplacement: compiled
|
|
22141
|
+
replacement: assembledReplacement(compiled, reflectionMetadata, select),
|
|
22142
|
+
exportedReplacement: assembledReplacement(compiled, exportedMetadata, select),
|
|
21131
22143
|
carried,
|
|
21132
22144
|
...composing ? { trivia: composing } : {},
|
|
21133
22145
|
...importedFactories.length ? { importedFactories } : {},
|
|
@@ -21143,6 +22155,42 @@ ${names.map((n) => ` - ${n}`).join("\n")}` : " (it is not a static combinator/v
|
|
|
21143
22155
|
warn(init.start, "compose(): a carried piece has no re-lowerable IR; leaving the runtime compose() in place");
|
|
21144
22156
|
return null;
|
|
21145
22157
|
};
|
|
22158
|
+
let assemblyBudget = Math.floor(code.length * assemblyBudgetShare);
|
|
22159
|
+
let leafDeclared;
|
|
22160
|
+
const declaresLeaf = () => leafDeclared ??= body.some((stmt) => {
|
|
22161
|
+
const vd = unwrapVd(stmt);
|
|
22162
|
+
return vd !== null && vd.declarations.some((d) => d.init != null && isComposeLeafCall(d.init));
|
|
22163
|
+
});
|
|
22164
|
+
const selectAssembly = (pos, label2, compiled, terminal) => {
|
|
22165
|
+
if (!terminal || grammarCoverage) return /* @__PURE__ */ new Set();
|
|
22166
|
+
const { sites, bytes, refusal } = compiled.selectAssembly(assemblyBudget, profileOf(compiled));
|
|
22167
|
+
if (refusal !== void 0) {
|
|
22168
|
+
warnings.push(`${id}:${lineOf(pos)} \u2014 ${label2}: its precompiled assembly cannot emit ${refusal}; the artifact runs on the closure engine`);
|
|
22169
|
+
}
|
|
22170
|
+
assemblyBudget -= bytes;
|
|
22171
|
+
return sites;
|
|
22172
|
+
};
|
|
22173
|
+
const profileOf = (compiled) => {
|
|
22174
|
+
if (assemblyProfile === void 0 || compiled.hostMode !== "ast" || compiled.prog.lines === 1 || !(assemblyProfile.entry in compiled.prog.rules)) return void 0;
|
|
22175
|
+
let parsed = 0;
|
|
22176
|
+
const fns = compiled.prog.fns.map((fn) => {
|
|
22177
|
+
const type = fn?.[INERT_BUILDER];
|
|
22178
|
+
return type === void 0 ? fn : (children3, _fields, span) => ({ type, span, children: children3 });
|
|
22179
|
+
});
|
|
22180
|
+
const counts = countSiteVisits(compiled.prog, (rules2) => {
|
|
22181
|
+
const entry = rules2[assemblyProfile.entry];
|
|
22182
|
+
for (const text of corpusTexts(assemblyProfile)) {
|
|
22183
|
+
try {
|
|
22184
|
+
if (run(entry, text).ok) parsed++;
|
|
22185
|
+
} catch {
|
|
22186
|
+
}
|
|
22187
|
+
}
|
|
22188
|
+
}, fns);
|
|
22189
|
+
if (parsed > 0) return counts;
|
|
22190
|
+
warnings.push(`${id} \u2014 assemblyProfile: no corpus file parsed from rule "${assemblyProfile.entry}"; using the static ranking`);
|
|
22191
|
+
return void 0;
|
|
22192
|
+
};
|
|
22193
|
+
const assembledReplacement = (compiled, metadata, select) => select.size === 0 ? compiled.replacementWithMetadata(metadata) : supercompileRuleMapReplacement(compiled.prog, compiled.replacementWithMetadata(metadata, { select }), select);
|
|
21146
22194
|
const compileComposeLeafCall = (init) => {
|
|
21147
22195
|
const args = init.arguments;
|
|
21148
22196
|
const arr = args[0];
|
|
@@ -21221,12 +22269,10 @@ ${names.map((n) => ` - ${n}`).join("\n")}` : " (it is not a static combinator/v
|
|
|
21221
22269
|
if (compiled !== null) {
|
|
21222
22270
|
usedTableRuntime = true;
|
|
21223
22271
|
return {
|
|
21224
|
-
replacement:
|
|
21225
|
-
compiled
|
|
21226
|
-
compiled.
|
|
21227
|
-
|
|
21228
|
-
{ precompileDefault: true }
|
|
21229
|
-
)
|
|
22272
|
+
replacement: assembledReplacement(
|
|
22273
|
+
compiled,
|
|
22274
|
+
staticTableMetadataSource({ reflection: compiled.reflection, leaf: true }),
|
|
22275
|
+
selectAssembly(init.start, "composeLeaf()", compiled, true)
|
|
21230
22276
|
),
|
|
21231
22277
|
...importedFactories.length ? { importedFactories } : {}
|
|
21232
22278
|
};
|
|
@@ -21478,14 +22524,14 @@ ${names.map((n) => ` - ${n}`).join("\n")}` : " (it is not a static combinator/v
|
|
|
21478
22524
|
}
|
|
21479
22525
|
if (!allOk) continue;
|
|
21480
22526
|
const holderVar = `__rules${ruleMapHolderCounter++}`;
|
|
21481
|
-
const
|
|
22527
|
+
const lines2 = [
|
|
21482
22528
|
`const ${holderVar} = ${compiledRules.replacement}`,
|
|
21483
22529
|
...bindings.map(({ ruleKey, localName }) => `${exportPrefix}${kind} ${localName} = ${holderVar}[${JSON.stringify(ruleKey)}]`)
|
|
21484
22530
|
];
|
|
21485
22531
|
replacements.push({
|
|
21486
22532
|
start: stmtStart,
|
|
21487
22533
|
end: stmtEnd,
|
|
21488
|
-
replacement:
|
|
22534
|
+
replacement: lines2.join("\n")
|
|
21489
22535
|
});
|
|
21490
22536
|
markUsedImportedFactories(compiledRules.importedFactory ? [compiledRules.importedFactory] : void 0);
|
|
21491
22537
|
}
|
|
@@ -21645,12 +22691,12 @@ ${free.map(where).join("\n")}${cause}`
|
|
|
21645
22691
|
setBuilderImportResolver(null);
|
|
21646
22692
|
const degradations = endDegradationCapture();
|
|
21647
22693
|
if (degradations.length > 0) {
|
|
21648
|
-
const
|
|
22694
|
+
const lines2 = formatDegradations(degradations);
|
|
21649
22695
|
if (resolveDegradationLevel() === "error") {
|
|
21650
22696
|
throw new Error(`parseman: ${degradations.length} degraded compilation path(s) in ${id}
|
|
21651
|
-
${
|
|
22697
|
+
${lines2.join("\n")}`);
|
|
21652
22698
|
}
|
|
21653
|
-
for (const l of
|
|
22699
|
+
for (const l of lines2) warnings.push(`${id}: ${l}`);
|
|
21654
22700
|
}
|
|
21655
22701
|
return {
|
|
21656
22702
|
code: ms.toString(),
|