parseman 0.38.0 → 0.39.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/duplication.d.ts.map +1 -1
- package/dist/analysis/gating.d.ts.map +1 -1
- package/dist/combinators/attempt.d.ts.map +1 -1
- package/dist/combinators/choice.d.ts.map +1 -1
- package/dist/combinators/dispatch.d.ts +20 -0
- package/dist/combinators/dispatch.d.ts.map +1 -0
- package/dist/combinators/expect.d.ts.map +1 -1
- package/dist/combinators/first-set.d.ts.map +1 -1
- package/dist/combinators/repeat.d.ts.map +1 -1
- package/dist/compiler/codegen.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/value-usage.d.ts.map +1 -1
- package/dist/coverage.d.ts.map +1 -1
- package/dist/index.cjs +383 -31
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +383 -31
- package/dist/index.js.map +4 -4
- package/dist/language-service/index.cjs.map +2 -2
- package/dist/language-service/index.js.map +2 -2
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.cjs +436 -31
- package/dist/plugin/index.cjs.map +4 -4
- package/dist/plugin/index.js +436 -31
- package/dist/plugin/index.js.map +4 -4
- package/dist/spec/index.cjs +107 -0
- package/dist/spec/index.cjs.map +4 -4
- package/dist/spec/index.js +107 -0
- package/dist/spec/index.js.map +4 -4
- package/dist/spec/model.d.ts.map +1 -1
- package/dist/types.d.ts +17 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/plugin/index.cjs
CHANGED
|
@@ -120,6 +120,8 @@ function matchesEmpty(p, seen = /* @__PURE__ */ new Set(), resolve2) {
|
|
|
120
120
|
return d.parsers.every(me);
|
|
121
121
|
case "choice":
|
|
122
122
|
return d.parsers.some(me);
|
|
123
|
+
case "dispatch":
|
|
124
|
+
return me(d.selector);
|
|
123
125
|
case "transform":
|
|
124
126
|
case "label":
|
|
125
127
|
case "trivia":
|
|
@@ -193,6 +195,8 @@ function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve2) {
|
|
|
193
195
|
case "keywords":
|
|
194
196
|
return p._meta.firstSet;
|
|
195
197
|
// terminals: no refs, cached set is exact
|
|
198
|
+
case "dispatch":
|
|
199
|
+
return fs2(d.selector);
|
|
196
200
|
case "lazy":
|
|
197
201
|
try {
|
|
198
202
|
return fs2(d.thunk());
|
|
@@ -1141,6 +1145,8 @@ function derive(c, seen) {
|
|
|
1141
1145
|
return [def.label];
|
|
1142
1146
|
case "choice":
|
|
1143
1147
|
return def.parsers.flatMap(deriveExpected2);
|
|
1148
|
+
case "dispatch":
|
|
1149
|
+
return deriveExpected2(def.selector);
|
|
1144
1150
|
// Union through the NULLABLE prefix, mirroring `sequenceFirstSet`. A leading
|
|
1145
1151
|
// `optional(…)`/`many(…)` can match nothing, so the term after it is equally
|
|
1146
1152
|
// able to fail first — deriving from term 0 alone named a token the parse
|
|
@@ -1279,6 +1285,7 @@ function choice(...args) {
|
|
|
1279
1285
|
const result = parsers[idx].parse(input, pos, ctx);
|
|
1280
1286
|
if (result.ok) return result;
|
|
1281
1287
|
expected.push(...result.expected);
|
|
1288
|
+
if (result.committed) return { ok: false, expected, span: { start: pos, end: pos }, committed: true };
|
|
1282
1289
|
return { ok: false, expected, span: { start: pos, end: pos } };
|
|
1283
1290
|
}
|
|
1284
1291
|
return {
|
|
@@ -1319,6 +1326,7 @@ function choice(...args) {
|
|
|
1319
1326
|
rollbackCstCapture(ctx, mark);
|
|
1320
1327
|
if (logLen !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== logLen) ctx._triviaLog.length = logLen;
|
|
1321
1328
|
expected.push(...result.expected);
|
|
1329
|
+
if (result.committed) return { ok: false, expected, span: result.span, committed: true };
|
|
1322
1330
|
continue;
|
|
1323
1331
|
}
|
|
1324
1332
|
const checks = autoNot[i];
|
|
@@ -1998,6 +2006,75 @@ function sequence(...parsers) {
|
|
|
1998
2006
|
};
|
|
1999
2007
|
}
|
|
2000
2008
|
|
|
2009
|
+
// src/combinators/dispatch.ts
|
|
2010
|
+
function when(key, parser2) {
|
|
2011
|
+
const keys = Array.isArray(key) ? [...key] : [key];
|
|
2012
|
+
if (keys.length === 0) throw new RangeError("parseman: when() requires at least one key");
|
|
2013
|
+
for (const item of keys) {
|
|
2014
|
+
if (typeof item !== "string") throw new TypeError("parseman: when() keys must be strings");
|
|
2015
|
+
}
|
|
2016
|
+
return { kind: "when", keys, parser: parser2 };
|
|
2017
|
+
}
|
|
2018
|
+
function otherwise(parser2) {
|
|
2019
|
+
return { kind: "otherwise", parser: parser2 };
|
|
2020
|
+
}
|
|
2021
|
+
function dispatch(selector, ...arms) {
|
|
2022
|
+
let fallback;
|
|
2023
|
+
const cases = [];
|
|
2024
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2025
|
+
for (let i = 0; i < arms.length; i++) {
|
|
2026
|
+
const arm = arms[i];
|
|
2027
|
+
if (arm.kind === "otherwise") {
|
|
2028
|
+
if (fallback !== void 0) throw new Error("parseman: dispatch() accepts at most one otherwise() arm");
|
|
2029
|
+
if (i !== arms.length - 1) throw new Error("parseman: otherwise() must be the last dispatch() arm");
|
|
2030
|
+
fallback = arm.parser;
|
|
2031
|
+
continue;
|
|
2032
|
+
}
|
|
2033
|
+
for (const key of arm.keys) {
|
|
2034
|
+
if (seen.has(key)) throw new Error(`parseman: duplicate dispatch key ${JSON.stringify(key)}`);
|
|
2035
|
+
seen.add(key);
|
|
2036
|
+
}
|
|
2037
|
+
cases.push({ keys: arm.keys, parser: arm.parser });
|
|
2038
|
+
}
|
|
2039
|
+
const meta = {
|
|
2040
|
+
firstSet: selector._meta.firstSet,
|
|
2041
|
+
canMatchNewline: selector._meta.canMatchNewline || cases.some((entry) => entry.parser._meta.canMatchNewline) || (fallback?._meta.canMatchNewline ?? false),
|
|
2042
|
+
isTrivia: false
|
|
2043
|
+
};
|
|
2044
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
2045
|
+
for (const entry of cases) for (const key of entry.keys) byKey.set(key, entry.parser);
|
|
2046
|
+
return {
|
|
2047
|
+
_tag: "dispatch",
|
|
2048
|
+
_meta: meta,
|
|
2049
|
+
_def: {
|
|
2050
|
+
tag: "dispatch",
|
|
2051
|
+
selector,
|
|
2052
|
+
cases,
|
|
2053
|
+
...fallback === void 0 ? {} : { otherwise: fallback }
|
|
2054
|
+
},
|
|
2055
|
+
parse(input, pos, ctx) {
|
|
2056
|
+
const selected = selector.parse(input, pos, ctx);
|
|
2057
|
+
if (!selected.ok) return selected;
|
|
2058
|
+
const tail = byKey.get(selected.value) ?? fallback;
|
|
2059
|
+
if (tail === void 0) {
|
|
2060
|
+
const expected = cases.flatMap((entry) => entry.keys.map((key) => JSON.stringify(key)));
|
|
2061
|
+
return { ok: false, expected, span: { start: selected.span.end, end: selected.span.end } };
|
|
2062
|
+
}
|
|
2063
|
+
const mark = saveTriviaMark(ctx);
|
|
2064
|
+
const result = tail.parse(input, selected.span.end, ctx);
|
|
2065
|
+
if (!result.ok) {
|
|
2066
|
+
rollbackTrivia(ctx, mark);
|
|
2067
|
+
return { ...result, committed: true };
|
|
2068
|
+
}
|
|
2069
|
+
return {
|
|
2070
|
+
ok: true,
|
|
2071
|
+
value: [selected.value, result.value],
|
|
2072
|
+
span: { start: pos, end: result.span.end }
|
|
2073
|
+
};
|
|
2074
|
+
}
|
|
2075
|
+
};
|
|
2076
|
+
}
|
|
2077
|
+
|
|
2001
2078
|
// src/combinators/attempt.ts
|
|
2002
2079
|
function attempt(parser2) {
|
|
2003
2080
|
const guardable = parser2._meta.firstSet.kind !== "any" && !matchesEmpty(parser2);
|
|
@@ -2020,6 +2097,7 @@ function attempt(parser2) {
|
|
|
2020
2097
|
if (result.ok) return result;
|
|
2021
2098
|
rollbackCstCapture(ctx, mark);
|
|
2022
2099
|
if (log !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== log) ctx._triviaLog.length = log;
|
|
2100
|
+
if (result.committed) return result;
|
|
2023
2101
|
return { ok: false, expected: result.expected, span: { start: pos, end: pos } };
|
|
2024
2102
|
}
|
|
2025
2103
|
};
|
|
@@ -2049,6 +2127,7 @@ function repItem(combinator, input, cur, ctx, guardable) {
|
|
|
2049
2127
|
const result = combinator.parse(input, pos, ctx);
|
|
2050
2128
|
if (!result.ok) {
|
|
2051
2129
|
rollbackTrivia(ctx, mark);
|
|
2130
|
+
if (result.committed) return { fail: result, failPos: pos };
|
|
2052
2131
|
return { fail: result, failPos: pos };
|
|
2053
2132
|
}
|
|
2054
2133
|
if (result.span.end === pos) {
|
|
@@ -2092,6 +2171,7 @@ function many(combinator, opts = {}) {
|
|
|
2092
2171
|
const item = repItem(combinator, input, cur, ctx, guardable);
|
|
2093
2172
|
if (item === "stop") break;
|
|
2094
2173
|
if ("fail" in item) {
|
|
2174
|
+
if (!item.fail.ok && item.fail.committed) return item.fail;
|
|
2095
2175
|
const sync = ctx._tolerant ? ctx._sync : void 0;
|
|
2096
2176
|
if (sync === void 0) break;
|
|
2097
2177
|
if (matchesAt(sync, input, item.failPos, ctx)) break;
|
|
@@ -2136,6 +2216,7 @@ function atLeast(combinator, min, max) {
|
|
|
2136
2216
|
while (count < min) {
|
|
2137
2217
|
const item = repItem(combinator, input, cur, ctx, guardable);
|
|
2138
2218
|
if (item === "stop" || "fail" in item) {
|
|
2219
|
+
if (item !== "stop" && !item.fail.ok && item.fail.committed) return item.fail;
|
|
2139
2220
|
expected ??= deriveExpected(combinator);
|
|
2140
2221
|
return { ok: false, expected: expected.length > 0 ? expected : [combinator._tag], span: { start: cur, end: cur } };
|
|
2141
2222
|
}
|
|
@@ -2148,6 +2229,7 @@ function atLeast(combinator, min, max) {
|
|
|
2148
2229
|
const item = repItem(combinator, input, cur, ctx, guardable);
|
|
2149
2230
|
if (item === "stop") break;
|
|
2150
2231
|
if ("fail" in item) {
|
|
2232
|
+
if (!item.fail.ok && item.fail.committed) return item.fail;
|
|
2151
2233
|
const sync = ctx._tolerant ? ctx._sync : void 0;
|
|
2152
2234
|
if (sync === void 0) break;
|
|
2153
2235
|
if (matchesAt(sync, input, item.failPos, ctx)) break;
|
|
@@ -2186,6 +2268,7 @@ function optional(combinator) {
|
|
|
2186
2268
|
const result = combinator.parse(input, pos, ctx);
|
|
2187
2269
|
if (result.ok) return result;
|
|
2188
2270
|
rollbackTrivia(ctx, mark);
|
|
2271
|
+
if (result.committed) return result;
|
|
2189
2272
|
return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
2190
2273
|
}
|
|
2191
2274
|
};
|
|
@@ -2225,6 +2308,7 @@ function sepBy(combinator, separator, opts = {}) {
|
|
|
2225
2308
|
values.push(first.value);
|
|
2226
2309
|
cur = first.span.end;
|
|
2227
2310
|
} else {
|
|
2311
|
+
if (first.committed) return first;
|
|
2228
2312
|
const term = ctx._tolerant ? ctx._sync : void 0;
|
|
2229
2313
|
if (term === void 0 || matchesAt(term, input, pos, ctx)) {
|
|
2230
2314
|
if (min >= 1) return failAt2(pos);
|
|
@@ -2252,6 +2336,7 @@ function sepBy(combinator, separator, opts = {}) {
|
|
|
2252
2336
|
const sep2 = separator.parse(input, sepPos, ctx);
|
|
2253
2337
|
if (!sep2.ok) {
|
|
2254
2338
|
rollbackTrivia(ctx, loopMark);
|
|
2339
|
+
if (sep2.committed) return sep2;
|
|
2255
2340
|
break;
|
|
2256
2341
|
}
|
|
2257
2342
|
const sepMark = trailing === "forbid" ? void 0 : saveTriviaMark(ctx);
|
|
@@ -2267,6 +2352,7 @@ function sepBy(combinator, separator, opts = {}) {
|
|
|
2267
2352
|
}
|
|
2268
2353
|
const next = combinator.parse(input, nextPos, ctx);
|
|
2269
2354
|
if (!next.ok) {
|
|
2355
|
+
if (next.committed) return next;
|
|
2270
2356
|
const term = ctx._tolerant ? ctx._sync : void 0;
|
|
2271
2357
|
if (term !== void 0 && !matchesAt(term, input, nextPos, ctx)) {
|
|
2272
2358
|
expected ??= deriveExpected(combinator);
|
|
@@ -2322,6 +2408,11 @@ function markUnusedValues(root) {
|
|
|
2322
2408
|
case "choice":
|
|
2323
2409
|
for (const p of def.parsers) visit(p, consumed);
|
|
2324
2410
|
return;
|
|
2411
|
+
case "dispatch":
|
|
2412
|
+
visit(def.selector, consumed);
|
|
2413
|
+
for (const entry of def.cases) visit(entry.parser, consumed);
|
|
2414
|
+
if (def.otherwise) visit(def.otherwise, consumed);
|
|
2415
|
+
return;
|
|
2325
2416
|
case "node":
|
|
2326
2417
|
visit(def.parser, false);
|
|
2327
2418
|
return;
|
|
@@ -2597,6 +2688,8 @@ function parserHasOwnFields(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
2597
2688
|
case "sequence":
|
|
2598
2689
|
case "choice":
|
|
2599
2690
|
return d.parsers.some((x) => parserHasOwnFields(x, seen));
|
|
2691
|
+
case "dispatch":
|
|
2692
|
+
return parserHasOwnFields(d.selector, seen) || d.cases.some((x) => parserHasOwnFields(x.parser, seen)) || (d.otherwise ? parserHasOwnFields(d.otherwise, seen) : false);
|
|
2600
2693
|
case "sepBy":
|
|
2601
2694
|
return parserHasOwnFields(d.parser, seen) || parserHasOwnFields(d.separator, seen);
|
|
2602
2695
|
case "skip":
|
|
@@ -2664,6 +2757,8 @@ function parserHasTriviaSite(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
2664
2757
|
return parserHasTriviaSite(d.parser, seen);
|
|
2665
2758
|
case "choice":
|
|
2666
2759
|
return d.parsers.some((x) => parserHasTriviaSite(x, seen));
|
|
2760
|
+
case "dispatch":
|
|
2761
|
+
return parserHasTriviaSite(d.selector, seen) || d.cases.some((x) => parserHasTriviaSite(x.parser, seen)) || (d.otherwise ? parserHasTriviaSite(d.otherwise, seen) : false);
|
|
2667
2762
|
case "grammar":
|
|
2668
2763
|
return parserHasTriviaSite(d.parser, seen);
|
|
2669
2764
|
case "lazy": {
|
|
@@ -2689,6 +2784,8 @@ function parserEnablesTriviaCapture(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
2689
2784
|
case "sequence":
|
|
2690
2785
|
case "choice":
|
|
2691
2786
|
return d.parsers.some((x) => parserEnablesTriviaCapture(x, seen));
|
|
2787
|
+
case "dispatch":
|
|
2788
|
+
return parserEnablesTriviaCapture(d.selector, seen) || d.cases.some((x) => parserEnablesTriviaCapture(x.parser, seen)) || (d.otherwise ? parserEnablesTriviaCapture(d.otherwise, seen) : false);
|
|
2692
2789
|
case "sepBy":
|
|
2693
2790
|
return parserEnablesTriviaCapture(d.parser, seen) || parserEnablesTriviaCapture(d.separator, seen);
|
|
2694
2791
|
case "skip":
|
|
@@ -3063,7 +3160,7 @@ function leaf(root, fn) {
|
|
|
3063
3160
|
}
|
|
3064
3161
|
|
|
3065
3162
|
// src/version.ts
|
|
3066
|
-
var PARSEMAN_VERSION = "0.
|
|
3163
|
+
var PARSEMAN_VERSION = "0.39.0";
|
|
3067
3164
|
|
|
3068
3165
|
// src/cst/host-mode.ts
|
|
3069
3166
|
var FUSED_HOST_MODE = /* @__PURE__ */ Symbol.for("parseman.fusedHostMode");
|
|
@@ -3219,6 +3316,8 @@ function classifyBroadArm(arm, resolve2) {
|
|
|
3219
3316
|
}
|
|
3220
3317
|
return null;
|
|
3221
3318
|
}
|
|
3319
|
+
case "dispatch":
|
|
3320
|
+
return walk2(d.selector);
|
|
3222
3321
|
default:
|
|
3223
3322
|
return { cause: "broad-recognizer", detail: `unmodeled construct (${d.tag})` };
|
|
3224
3323
|
}
|
|
@@ -3318,6 +3417,11 @@ function analyzeGatingRules(ruleMap, opts) {
|
|
|
3318
3417
|
if (Array.isArray(rec.parsers)) kids.push(...rec.parsers);
|
|
3319
3418
|
for (const k of ["parser", "main", "skipped", "separator", "sentinel"])
|
|
3320
3419
|
if (rec[k]) kids.push(rec[k]);
|
|
3420
|
+
if (d.tag === "dispatch") {
|
|
3421
|
+
kids.push(d.selector);
|
|
3422
|
+
for (const c of d.cases) kids.push(c.parser);
|
|
3423
|
+
if (d.otherwise !== void 0) kids.push(d.otherwise);
|
|
3424
|
+
}
|
|
3321
3425
|
if (Array.isArray(rec.skip)) kids.push(...rec.skip);
|
|
3322
3426
|
if (d.tag === "lazy") {
|
|
3323
3427
|
try {
|
|
@@ -3424,6 +3528,12 @@ function childrenOf(d) {
|
|
|
3424
3528
|
case "sequence":
|
|
3425
3529
|
case "choice":
|
|
3426
3530
|
return d.parsers;
|
|
3531
|
+
case "dispatch":
|
|
3532
|
+
return [
|
|
3533
|
+
d.selector,
|
|
3534
|
+
...d.cases.map((c) => c.parser),
|
|
3535
|
+
...d.otherwise === void 0 ? [] : [d.otherwise]
|
|
3536
|
+
];
|
|
3427
3537
|
case "skip":
|
|
3428
3538
|
return [d.main, d.skipped];
|
|
3429
3539
|
case "sepBy":
|
|
@@ -3480,6 +3590,8 @@ function payloadKey(p, d) {
|
|
|
3480
3590
|
return `${d.tag}\0${d.min}\0${d.max ?? ""}`;
|
|
3481
3591
|
case "sepBy":
|
|
3482
3592
|
return `sepBy\0${d.min}\0${d.max ?? ""}\0${d.trailing ?? ""}`;
|
|
3593
|
+
case "dispatch":
|
|
3594
|
+
return `dispatch\0${d.cases.map((c) => JSON.stringify(c.keys)).join("")}\0${d.otherwise !== void 0}`;
|
|
3483
3595
|
case "expect":
|
|
3484
3596
|
return `expect\0${d.label ?? ""}\0${d.expected.join("")}`;
|
|
3485
3597
|
case "scanTo":
|
|
@@ -3551,6 +3663,11 @@ function render(p, depth = 3) {
|
|
|
3551
3663
|
return `sequence(${kids.join(", ")})`;
|
|
3552
3664
|
case "choice":
|
|
3553
3665
|
return `choice(${kids.join(", ")})`;
|
|
3666
|
+
case "dispatch": {
|
|
3667
|
+
const arms = d.cases.map((c, i) => `when([${c.keys.map((k) => JSON.stringify(k)).join(", ")}], ${kids[i + 1] ?? ""})`);
|
|
3668
|
+
if (d.otherwise !== void 0) arms.push(`otherwise(${kids[kids.length - 1] ?? ""})`);
|
|
3669
|
+
return `dispatch(${kids[0] ?? ""}, ${arms.join(", ")})`;
|
|
3670
|
+
}
|
|
3554
3671
|
case "node":
|
|
3555
3672
|
return `node(${d.type ? `'${d.type}', ` : ""}${kids[0] ?? ""})`;
|
|
3556
3673
|
case "label":
|
|
@@ -3574,6 +3691,10 @@ function segment(d, index) {
|
|
|
3574
3691
|
return `seq[${index}]`;
|
|
3575
3692
|
case "choice":
|
|
3576
3693
|
return `choice[${index}]`;
|
|
3694
|
+
case "dispatch":
|
|
3695
|
+
if (index === 0) return "dispatch.selector";
|
|
3696
|
+
if (index <= d.cases.length) return `dispatch.when[${index - 1}]`;
|
|
3697
|
+
return "dispatch.otherwise";
|
|
3577
3698
|
case "node":
|
|
3578
3699
|
return `node(${d.type ?? ""})`;
|
|
3579
3700
|
case "label":
|
|
@@ -4827,6 +4948,8 @@ function children(def, winners) {
|
|
|
4827
4948
|
case "sequence":
|
|
4828
4949
|
case "choice":
|
|
4829
4950
|
return def.parsers;
|
|
4951
|
+
case "dispatch":
|
|
4952
|
+
return [def.selector, ...def.cases.map((entry) => entry.parser), ...def.otherwise ? [def.otherwise] : []];
|
|
4830
4953
|
case "many":
|
|
4831
4954
|
case "oneOrMore":
|
|
4832
4955
|
case "optional":
|
|
@@ -6291,6 +6414,8 @@ function leadingFirstSetRecipe(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
6291
6414
|
for (const arm of d.parsers) alts.push(...rec(arm).alts);
|
|
6292
6415
|
return { alts };
|
|
6293
6416
|
}
|
|
6417
|
+
case "dispatch":
|
|
6418
|
+
return rec(d.selector);
|
|
6294
6419
|
case "sequence": {
|
|
6295
6420
|
const chain = [];
|
|
6296
6421
|
for (const term of d.parsers) {
|
|
@@ -6373,6 +6498,9 @@ function failReturn(expected, posExpr) {
|
|
|
6373
6498
|
function failReturnArr(expectedArr, posExpr) {
|
|
6374
6499
|
return `return { ok: false, expected: ${expectedArr}, span: { start: ${posExpr}, end: ${posExpr} } }`;
|
|
6375
6500
|
}
|
|
6501
|
+
function committedReturnArr(expectedArr, posExpr) {
|
|
6502
|
+
return `return { ok: false, expected: [...${expectedArr}], span: { start: ${posExpr}, end: ${posExpr} }, committed: true }`;
|
|
6503
|
+
}
|
|
6376
6504
|
function hoistExpected(ctx, constArrSource) {
|
|
6377
6505
|
let name = ctx.expectedMap.get(constArrSource);
|
|
6378
6506
|
if (name === void 0) {
|
|
@@ -6409,15 +6537,22 @@ function failArrBody(ctx, expectedArr, posExpr, constant = true) {
|
|
|
6409
6537
|
return probe + trace + failReturnArr(expectedArr, posExpr);
|
|
6410
6538
|
}
|
|
6411
6539
|
function resultFromRecorded(feExpr = "_ctx._fe", fxExpr = "_ctx._fx") {
|
|
6412
|
-
return `return { ok: false, expected: [...${fxExpr}], span: { start: ${feExpr}, end: ${feExpr} } }`;
|
|
6540
|
+
return `return { ok: false, expected: [...${fxExpr}], span: { start: ${feExpr}, end: ${feExpr} }, ...(_ctx._fc ? { committed: true } : {}) }`;
|
|
6541
|
+
}
|
|
6542
|
+
function committedFailBody(ctx, expectedArr = "_ctx._fx", posExpr = "_ctx._fe") {
|
|
6543
|
+
if (ctx.failLabel) {
|
|
6544
|
+
if (!ctx.recordFail) return `{ _ctx._fc = true; break ${ctx.failLabel} }`;
|
|
6545
|
+
return `{ _ctx._fc = true; _ctx._fe = ${posExpr}; _ctx._fx = ${expectedArr}; break ${ctx.failLabel} }`;
|
|
6546
|
+
}
|
|
6547
|
+
return committedReturnArr(expectedArr, posExpr);
|
|
6413
6548
|
}
|
|
6414
6549
|
function propagateFailBody(ctx, srcCtx = "_ctx") {
|
|
6415
6550
|
if (srcCtx !== "_ctx") {
|
|
6416
6551
|
if (ctx.failLabel) {
|
|
6417
6552
|
if (!ctx.recordFail) return `break ${ctx.failLabel}`;
|
|
6418
|
-
return `{ _ctx._fe = ${srcCtx}._fe; _ctx._fx = ${srcCtx}._fx; break ${ctx.failLabel} }`;
|
|
6553
|
+
return `{ _ctx._fe = ${srcCtx}._fe; _ctx._fx = ${srcCtx}._fx; _ctx._fc = ${srcCtx}._fc; break ${ctx.failLabel} }`;
|
|
6419
6554
|
}
|
|
6420
|
-
return `{ _ctx._fe = ${srcCtx}._fe; _ctx._fx = ${srcCtx}._fx; ${resultFromRecorded()} }`;
|
|
6555
|
+
return `{ _ctx._fe = ${srcCtx}._fe; _ctx._fx = ${srcCtx}._fx; _ctx._fc = ${srcCtx}._fc; ${resultFromRecorded()} }`;
|
|
6421
6556
|
}
|
|
6422
6557
|
if (ctx.failLabel) return `break ${ctx.failLabel}`;
|
|
6423
6558
|
return resultFromRecorded();
|
|
@@ -6630,6 +6765,8 @@ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
6630
6765
|
// nothing committed remains.
|
|
6631
6766
|
case "choice":
|
|
6632
6767
|
return false;
|
|
6768
|
+
case "dispatch":
|
|
6769
|
+
return capturesLeaf(d.selector, seen) || d.cases.some((x) => mayLeavePartialCapture(x.parser, seen) || capturesLeaf(x.parser, seen)) || (d.otherwise ? mayLeavePartialCapture(d.otherwise, seen) || capturesLeaf(d.otherwise, seen) : false);
|
|
6633
6770
|
case "attempt":
|
|
6634
6771
|
return false;
|
|
6635
6772
|
// optional never fails; many/oneOrMore only "fail" with zero captured items.
|
|
@@ -6674,6 +6811,50 @@ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
6674
6811
|
return true;
|
|
6675
6812
|
}
|
|
6676
6813
|
}
|
|
6814
|
+
function mayCommitFailure(p, seen = /* @__PURE__ */ new Set()) {
|
|
6815
|
+
if (seen.has(p)) return false;
|
|
6816
|
+
seen.add(p);
|
|
6817
|
+
const d = p._def;
|
|
6818
|
+
switch (d.tag) {
|
|
6819
|
+
case "dispatch":
|
|
6820
|
+
return true;
|
|
6821
|
+
case "choice":
|
|
6822
|
+
case "sequence":
|
|
6823
|
+
return d.parsers.some((x) => mayCommitFailure(x, seen));
|
|
6824
|
+
case "many":
|
|
6825
|
+
case "oneOrMore":
|
|
6826
|
+
case "optional":
|
|
6827
|
+
case "attempt":
|
|
6828
|
+
case "transform":
|
|
6829
|
+
case "label":
|
|
6830
|
+
case "field":
|
|
6831
|
+
case "grammar":
|
|
6832
|
+
case "node":
|
|
6833
|
+
return mayCommitFailure(d.parser, seen);
|
|
6834
|
+
case "sepBy":
|
|
6835
|
+
return mayCommitFailure(d.parser, seen) || mayCommitFailure(d.separator, seen);
|
|
6836
|
+
case "skip":
|
|
6837
|
+
return mayCommitFailure(d.main, seen) || mayCommitFailure(d.skipped, seen);
|
|
6838
|
+
case "token":
|
|
6839
|
+
case "leaf":
|
|
6840
|
+
return mayCommitFailure(d.parser, seen);
|
|
6841
|
+
case "withCtx":
|
|
6842
|
+
return mayCommitFailure(d.parser, seen);
|
|
6843
|
+
case "scanTo":
|
|
6844
|
+
return mayCommitFailure(d.sentinel, seen) || d.skip.some((x) => mayCommitFailure(x, seen));
|
|
6845
|
+
case "lazy": {
|
|
6846
|
+
try {
|
|
6847
|
+
return mayCommitFailure(d.thunk(), seen);
|
|
6848
|
+
} catch {
|
|
6849
|
+
return true;
|
|
6850
|
+
}
|
|
6851
|
+
}
|
|
6852
|
+
case "unknown":
|
|
6853
|
+
return true;
|
|
6854
|
+
default:
|
|
6855
|
+
return false;
|
|
6856
|
+
}
|
|
6857
|
+
}
|
|
6677
6858
|
function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
|
|
6678
6859
|
if (seen.has(p)) return false;
|
|
6679
6860
|
seen.add(p);
|
|
@@ -6695,6 +6876,8 @@ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
6695
6876
|
case "sequence":
|
|
6696
6877
|
case "choice":
|
|
6697
6878
|
return d.parsers.some((x) => capturesLeaf(x, seen));
|
|
6879
|
+
case "dispatch":
|
|
6880
|
+
return capturesLeaf(d.selector, seen) || d.cases.some((x) => capturesLeaf(x.parser, seen)) || (d.otherwise ? capturesLeaf(d.otherwise, seen) : false);
|
|
6698
6881
|
case "sepBy":
|
|
6699
6882
|
return capturesLeaf(d.parser, seen) || capturesLeaf(d.separator, seen);
|
|
6700
6883
|
case "many":
|
|
@@ -6741,6 +6924,7 @@ function emitFallible(inner, ctx, pos, swallow = false) {
|
|
|
6741
6924
|
ctx.recordFail = savedRecord;
|
|
6742
6925
|
const ind0 = ind(ctx);
|
|
6743
6926
|
const needsRollback = ctx.capturing && mayLeavePartialCapture(inner);
|
|
6927
|
+
const mayCommit = mayCommitFailure(inner);
|
|
6744
6928
|
const needsFieldRollback = needsRollback && parserHasOwnFields(inner);
|
|
6745
6929
|
const mL = needsRollback ? v(ctx, "_fcl") : null;
|
|
6746
6930
|
const mR = needsRollback ? v(ctx, "_fcr") : null;
|
|
@@ -6754,6 +6938,7 @@ function emitFallible(inner, ctx, pos, swallow = false) {
|
|
|
6754
6938
|
`${ind0}const ${mTl} = _ctx._cstTriviaLog?.length ?? 0`,
|
|
6755
6939
|
...mF ? [`${ind0}const ${mF} = _ctx._fields?.length ?? 0`] : []
|
|
6756
6940
|
] : [],
|
|
6941
|
+
...mayCommit ? [`${ind0}_ctx._fc = false`] : [],
|
|
6757
6942
|
`${ind0}${lbl}: {`,
|
|
6758
6943
|
...r.stmts,
|
|
6759
6944
|
`${ind0} ${valV} = ${r.valueVar}; ${endV} = ${r.endVar}; ${okV} = true`,
|
|
@@ -6762,7 +6947,7 @@ function emitFallible(inner, ctx, pos, swallow = false) {
|
|
|
6762
6947
|
`${ind0}if (!${okV}) { ${captureRestoreBody(mL, mR, mTl, null, mF)} }`
|
|
6763
6948
|
] : []
|
|
6764
6949
|
];
|
|
6765
|
-
return { stmts, okVar: okV, valVar: valV, endVar: endV };
|
|
6950
|
+
return { stmts, okVar: okV, valVar: valV, endVar: endV, mayCommit };
|
|
6766
6951
|
}
|
|
6767
6952
|
var CHARCODE_CHAIN_MAX = 16;
|
|
6768
6953
|
function emitLit(def, ctx, pos) {
|
|
@@ -7139,6 +7324,118 @@ function emitChoice(parser2, def, ctx, pos) {
|
|
|
7139
7324
|
}
|
|
7140
7325
|
return emitNonDisjoint(def, def.strategy, allExpected, ctx, pos, coverageBase);
|
|
7141
7326
|
}
|
|
7327
|
+
function emitTailFallible(parser2, ctx, pos) {
|
|
7328
|
+
const savedRecord = ctx.recordFail;
|
|
7329
|
+
ctx.recordFail = true;
|
|
7330
|
+
const out = emitFallible(parser2, ctx, pos);
|
|
7331
|
+
ctx.recordFail = savedRecord;
|
|
7332
|
+
return out;
|
|
7333
|
+
}
|
|
7334
|
+
function mayRecordRecoveryError(p, recovery, seen = /* @__PURE__ */ new Set()) {
|
|
7335
|
+
if (seen.has(p)) return false;
|
|
7336
|
+
seen.add(p);
|
|
7337
|
+
const d = p._def;
|
|
7338
|
+
switch (d.tag) {
|
|
7339
|
+
case "expect":
|
|
7340
|
+
case "recover":
|
|
7341
|
+
return true;
|
|
7342
|
+
case "many":
|
|
7343
|
+
case "oneOrMore":
|
|
7344
|
+
case "sepBy":
|
|
7345
|
+
return recovery || mayRecordRecoveryError(d.parser, recovery, seen);
|
|
7346
|
+
case "choice":
|
|
7347
|
+
case "sequence": {
|
|
7348
|
+
for (const item of d.parsers) {
|
|
7349
|
+
if (mayRecordRecoveryError(item, recovery, seen)) return true;
|
|
7350
|
+
}
|
|
7351
|
+
return false;
|
|
7352
|
+
}
|
|
7353
|
+
case "dispatch": {
|
|
7354
|
+
if (mayRecordRecoveryError(d.selector, recovery, seen)) return true;
|
|
7355
|
+
for (const item of d.cases) {
|
|
7356
|
+
if (mayRecordRecoveryError(item.parser, recovery, seen)) return true;
|
|
7357
|
+
}
|
|
7358
|
+
return d.otherwise ? mayRecordRecoveryError(d.otherwise, recovery, seen) : false;
|
|
7359
|
+
}
|
|
7360
|
+
case "attempt":
|
|
7361
|
+
case "transform":
|
|
7362
|
+
case "label":
|
|
7363
|
+
case "field":
|
|
7364
|
+
case "grammar":
|
|
7365
|
+
case "node":
|
|
7366
|
+
case "token":
|
|
7367
|
+
case "leaf":
|
|
7368
|
+
case "withCtx":
|
|
7369
|
+
case "optional":
|
|
7370
|
+
return mayRecordRecoveryError(d.parser, recovery, seen);
|
|
7371
|
+
case "skip":
|
|
7372
|
+
return mayRecordRecoveryError(d.main, recovery, seen) || mayRecordRecoveryError(d.skipped, recovery, seen);
|
|
7373
|
+
case "scanTo":
|
|
7374
|
+
if (mayRecordRecoveryError(d.sentinel, recovery, seen)) return true;
|
|
7375
|
+
for (const item of d.skip) {
|
|
7376
|
+
if (mayRecordRecoveryError(item, recovery, seen)) return true;
|
|
7377
|
+
}
|
|
7378
|
+
return false;
|
|
7379
|
+
case "lazy": {
|
|
7380
|
+
try {
|
|
7381
|
+
return mayRecordRecoveryError(d.thunk(), recovery, seen);
|
|
7382
|
+
} catch {
|
|
7383
|
+
return true;
|
|
7384
|
+
}
|
|
7385
|
+
}
|
|
7386
|
+
case "unknown":
|
|
7387
|
+
return true;
|
|
7388
|
+
default:
|
|
7389
|
+
return false;
|
|
7390
|
+
}
|
|
7391
|
+
}
|
|
7392
|
+
function emitDispatchCombinator(def, ctx, pos) {
|
|
7393
|
+
const selector = emit(def.selector, ctx, pos);
|
|
7394
|
+
const outV = v(ctx, "_dval");
|
|
7395
|
+
const outE = v(ctx, "_dend");
|
|
7396
|
+
const keyV = v(ctx, "_dkey");
|
|
7397
|
+
const stmts = [
|
|
7398
|
+
...selector.stmts,
|
|
7399
|
+
`${ind(ctx)}const ${keyV} = ${selector.valueVar}`,
|
|
7400
|
+
`${ind(ctx)}let ${outV}, ${outE} = ${selector.endVar}`
|
|
7401
|
+
];
|
|
7402
|
+
let wroteBranch = false;
|
|
7403
|
+
const emitSelectedTail = (parser2, keyword, condition) => {
|
|
7404
|
+
const head = keyword === "else" ? `${ind(ctx)}else {` : `${ind(ctx)}${keyword} (${condition}) {`;
|
|
7405
|
+
stmts.push(head);
|
|
7406
|
+
ctx.indent++;
|
|
7407
|
+
const mayError = mayRecordRecoveryError(parser2, !!ctx.recovery);
|
|
7408
|
+
const errMark = mayError ? v(ctx, "_derr") : null;
|
|
7409
|
+
const logMark = ctx.activeTrivia ? v(ctx, "_dlog") : null;
|
|
7410
|
+
if (errMark) stmts.push(`${ind(ctx)}const ${errMark} = _ctx._errors?.length ?? 0`);
|
|
7411
|
+
if (logMark) stmts.push(`${ind(ctx)}const ${logMark} = _ctx._triviaLog?.length ?? 0`);
|
|
7412
|
+
const tail = emitTailFallible(parser2, ctx, selector.endVar);
|
|
7413
|
+
const errorRollback = errMark ? `if (_ctx._errors && _ctx._errors.length !== ${errMark}) _ctx._errors.length = ${errMark}; ` : "";
|
|
7414
|
+
const logRollback = logMark ? `if (_ctx._triviaLog && _ctx._triviaLog.length !== ${logMark}) _ctx._triviaLog.length = ${logMark}; ` : "";
|
|
7415
|
+
stmts.push(
|
|
7416
|
+
...tail.stmts,
|
|
7417
|
+
`${ind(ctx)}if (!${tail.okVar}) { ${errorRollback}${logRollback}${committedFailBody(ctx)} }`,
|
|
7418
|
+
`${ind(ctx)}${outV} = [${selector.valueVar}, ${tail.valVar}]`,
|
|
7419
|
+
`${ind(ctx)}${outE} = ${tail.endVar}`
|
|
7420
|
+
);
|
|
7421
|
+
ctx.indent--;
|
|
7422
|
+
stmts.push(`${ind(ctx)}}`);
|
|
7423
|
+
};
|
|
7424
|
+
for (const entry of def.cases) {
|
|
7425
|
+
const condition = entry.keys.map((key) => `${keyV} === ${JSON.stringify(key)}`).join(" || ");
|
|
7426
|
+
emitSelectedTail(entry.parser, wroteBranch ? "else if" : "if", condition);
|
|
7427
|
+
wroteBranch = true;
|
|
7428
|
+
}
|
|
7429
|
+
if (def.otherwise) {
|
|
7430
|
+
if (wroteBranch) emitSelectedTail(def.otherwise, "else");
|
|
7431
|
+
else emitSelectedTail(def.otherwise, "if", "true");
|
|
7432
|
+
} else {
|
|
7433
|
+
const expected = JSON.stringify(def.cases.flatMap((entry) => entry.keys.map((key) => JSON.stringify(key))));
|
|
7434
|
+
const fail = failArrBody(ctx, expected, selector.endVar);
|
|
7435
|
+
stmts.push(wroteBranch ? `${ind(ctx)}else { ${fail} }` : `${ind(ctx)}${fail}`);
|
|
7436
|
+
}
|
|
7437
|
+
return { stmts, valueVar: outV, endVar: outE };
|
|
7438
|
+
}
|
|
7142
7439
|
function emitGreedyClassify(def, superIndex, ctx, pos, coverageBase) {
|
|
7143
7440
|
const superParser = def.parsers[superIndex];
|
|
7144
7441
|
const regexDef = getCoreRegexDef(superParser);
|
|
@@ -7260,12 +7557,16 @@ function emitFirstMatch(def, ctx, pos, coverageBase, preStmts, armGuardPrefix) {
|
|
|
7260
7557
|
const armHasAutoNot = !!(autoNot && autoNot.length > 0);
|
|
7261
7558
|
const armNeedsRollback = ctx.capturing && (mayLeavePartialCapture(p) || armHasAutoNot && capturesLeaf(p));
|
|
7262
7559
|
const armNeedsFieldRollback = armNeedsRollback && parserHasOwnFields(p);
|
|
7560
|
+
const armMayRecordError = mayRecordRecoveryError(p, !!ctx.recovery);
|
|
7263
7561
|
const markLeaves = armNeedsRollback ? v(ctx, "_cml") : null;
|
|
7264
7562
|
const markRaw = armNeedsRollback ? v(ctx, "_cmr") : null;
|
|
7265
7563
|
const markTl = armNeedsRollback ? v(ctx, "_cmtl") : null;
|
|
7266
7564
|
const markLog = armNeedsRollback ? v(ctx, "_cmlg") : null;
|
|
7267
7565
|
const markFields = armNeedsFieldRollback ? v(ctx, "_cmf") : null;
|
|
7268
|
-
const
|
|
7566
|
+
const markErrors = armMayRecordError ? v(ctx, "_cme") : null;
|
|
7567
|
+
const captureRollback = markLeaves ? captureRestoreBody(markLeaves, markRaw, markTl, markLog, markFields) : "";
|
|
7568
|
+
const errorRollback = markErrors ? `if (_ctx._errors && _ctx._errors.length !== ${markErrors}) _ctx._errors.length = ${markErrors}` : "";
|
|
7569
|
+
const rollback = [captureRollback, errorRollback].filter(Boolean).join("; ");
|
|
7269
7570
|
const failSlot = atStart ? staticFx : "_ctx._fx";
|
|
7270
7571
|
stmts.push(`${ind0}if (${skipCond}) {`);
|
|
7271
7572
|
if (fsGuard) stmts.push(`${ind(ctx)}if (${fsGuard}) {`);
|
|
@@ -7280,7 +7581,9 @@ function emitFirstMatch(def, ctx, pos, coverageBase, preStmts, armGuardPrefix) {
|
|
|
7280
7581
|
...markFields ? [`${ind(ctx)}const ${markFields} = _ctx._fields?.length ?? 0`] : []
|
|
7281
7582
|
);
|
|
7282
7583
|
}
|
|
7283
|
-
|
|
7584
|
+
if (markErrors) stmts.push(`${ind(ctx)}const ${markErrors} = _ctx._errors?.length ?? 0`);
|
|
7585
|
+
const arm = emitFallible(p, ctx, pos, atStart);
|
|
7586
|
+
const { stmts: armStmts, okVar, valVar, endVar } = arm;
|
|
7284
7587
|
stmts.push(...armStmts);
|
|
7285
7588
|
if (autoNot && autoNot.length > 0) {
|
|
7286
7589
|
const anCode = v(ctx, "_anc");
|
|
@@ -7304,10 +7607,12 @@ function emitFirstMatch(def, ctx, pos, coverageBase, preStmts, armGuardPrefix) {
|
|
|
7304
7607
|
stmts.push(`${ind(ctx)}}`);
|
|
7305
7608
|
stmts.push(`${ind(ctx)}else { ${slots[i]} = ${failSlot}; ${coverageBase === void 0 ? "" : `_ctx._grammarTrace?.write({ id: ${JSON.stringify(`${coverageBase}${i}`)}, phase: 'failure', offset: ${atStart ? pos : "_ctx._fe"} }); _ctx._grammarTrace?.write({ id: ${JSON.stringify(`${coverageBase}${i}`)}, phase: 'backtrack', offset: ${pos} });`} }`);
|
|
7306
7609
|
if (rollback) stmts.push(`${ind(ctx)}if (!${resOkV}) { ${rollback} }`);
|
|
7610
|
+
if (arm.mayCommit) stmts.push(`${ind(ctx)}if (!${resOkV} && _ctx._fc) ${committedFailBody(ctx)}`);
|
|
7307
7611
|
} else {
|
|
7308
7612
|
const rejectedFlush = autoRejectedV === void 0 ? "" : `; for (const _rejectedId of ${autoRejectedV}) { _ctx._grammarTrace?.write({ id: _rejectedId, phase: 'failure', offset: ${pos} }); _ctx._grammarTrace?.write({ id: _rejectedId, phase: 'backtrack', offset: ${pos} }) }`;
|
|
7309
7613
|
stmts.push(`${ind(ctx)}if (${okVar}) { ${resValV} = ${valVar}; ${resEndV} = ${endVar}; ${resOkV} = true${coverageBase === void 0 ? "" : `${rejectedFlush}; _ctx._grammarCoverage?.(${JSON.stringify(`${coverageBase}${i}`)}); _ctx._grammarTrace?.write({ id: ${JSON.stringify(`${coverageBase}${i}`)}, phase: 'selected', offset: ${pos}, end: ${endVar} }); _ctx._grammarTrace?.write({ id: ${JSON.stringify(`${coverageBase}${i}`)}, phase: 'success', offset: ${pos}, end: ${endVar} })`} }`);
|
|
7310
7614
|
stmts.push(`${ind(ctx)}else { ${slots[i]} = ${failSlot}${rollback ? `; ${rollback}` : ""}${coverageBase === void 0 ? "" : `; _ctx._grammarTrace?.write({ id: ${JSON.stringify(`${coverageBase}${i}`)}, phase: 'failure', offset: ${atStart ? pos : "_ctx._fe"} }); _ctx._grammarTrace?.write({ id: ${JSON.stringify(`${coverageBase}${i}`)}, phase: 'backtrack', offset: ${pos} })`} }`);
|
|
7615
|
+
if (arm.mayCommit) stmts.push(`${ind(ctx)}if (!${resOkV} && _ctx._fc) ${committedFailBody(ctx)}`);
|
|
7311
7616
|
}
|
|
7312
7617
|
ctx.indent -= fsGuard ? 2 : 1;
|
|
7313
7618
|
if (fsGuard) stmts.push(`${ind(ctx)}} else { ${slots[i]} = ${staticFx} }`);
|
|
@@ -7464,7 +7769,8 @@ function emitMany(def, ctx, pos) {
|
|
|
7464
7769
|
`${ind(ctx)}if (!(${firstSetCond(lcV, def.parser._meta.firstSet)})) { ${rollback}break }`
|
|
7465
7770
|
);
|
|
7466
7771
|
}
|
|
7467
|
-
const
|
|
7772
|
+
const iter = emitFallible(def.parser, ctx, itemPos, true);
|
|
7773
|
+
const { stmts: iterStmts, okVar: iterOk, valVar: iterVal, endVar: iterEnd } = iter;
|
|
7468
7774
|
stmts.push(...iterStmts);
|
|
7469
7775
|
if (ctx.recovery) {
|
|
7470
7776
|
const rrV = v(ctx, "_rr");
|
|
@@ -7483,7 +7789,8 @@ function emitMany(def, ctx, pos) {
|
|
|
7483
7789
|
`${ind(ctx)}if (${iterEnd} <= ${itemPos}) { ${rollback}break }`
|
|
7484
7790
|
);
|
|
7485
7791
|
} else {
|
|
7486
|
-
stmts.push(`${ind(ctx)}if (!${iterOk}
|
|
7792
|
+
stmts.push(`${ind(ctx)}if (!${iterOk}) { ${rollback}${iter.mayCommit ? `if (_ctx._fc) ${committedFailBody(ctx)}; ` : ""}break }`);
|
|
7793
|
+
stmts.push(`${ind(ctx)}if (${iterEnd} <= ${itemPos}) { ${rollback}break }`);
|
|
7487
7794
|
}
|
|
7488
7795
|
if (wantValue) stmts.push(`${ind(ctx)}${arrV}.push(${iterVal})`);
|
|
7489
7796
|
else if (maxV !== null) stmts.push(`${ind(ctx)}${maxV}++`);
|
|
@@ -7495,10 +7802,12 @@ function emitMany(def, ctx, pos) {
|
|
|
7495
7802
|
function emitOptional(def, ctx, pos) {
|
|
7496
7803
|
const valV = v(ctx, "_opt");
|
|
7497
7804
|
const endV = v(ctx, "_opte");
|
|
7498
|
-
const
|
|
7805
|
+
const inner = emitFallible(def.parser, ctx, pos, true);
|
|
7806
|
+
const { stmts: lblStmts, okVar, valVar, endVar } = inner;
|
|
7499
7807
|
const ind0 = ind(ctx);
|
|
7500
7808
|
const stmts = [
|
|
7501
7809
|
...lblStmts,
|
|
7810
|
+
...inner.mayCommit ? [`${ind0}if (!${okVar} && _ctx._fc) ${committedFailBody(ctx)}`] : [],
|
|
7502
7811
|
`${ind0}const ${valV} = ${okVar} ? ${valVar} : null`,
|
|
7503
7812
|
`${ind0}const ${endV} = ${okVar} ? ${endVar} : ${pos}`
|
|
7504
7813
|
];
|
|
@@ -7530,7 +7839,7 @@ function emitAttempt(p, def, ctx, pos) {
|
|
|
7530
7839
|
...preGuard,
|
|
7531
7840
|
`${ind(ctx)}const ${leaves} = _ctx._cstLeaves?.length ?? 0, ${raw} = _ctx._cstRawChildren?.length ?? 0, ${trivia2} = _ctx._cstTriviaLog?.length ?? 0, ${log} = _ctx._triviaLog?.length ?? 0, ${fields} = _ctx._fields?.length ?? 0, ${errors} = _ctx._errors?.length ?? 0`,
|
|
7532
7841
|
...inner.stmts,
|
|
7533
|
-
...emitIfFail(ctx, `!${inner.okVar}`, `{ ${rollback};${traceRollback} _ctx._fe = ${pos}; ${propagateFailBody(ctx)} }`)
|
|
7842
|
+
...emitIfFail(ctx, `!${inner.okVar}`, `{ ${rollback};${traceRollback}${inner.mayCommit ? ` if (_ctx._fc) ${committedFailBody(ctx)};` : ""} _ctx._fe = ${pos}; ${propagateFailBody(ctx)} }`)
|
|
7534
7843
|
],
|
|
7535
7844
|
valueVar: inner.valVar,
|
|
7536
7845
|
endVar: inner.endVar
|
|
@@ -7544,18 +7853,21 @@ function emitSepBy(_p, def, ctx, pos) {
|
|
|
7544
7853
|
const exp = rec ? hoistExpected(ctx, deriveExpectedArr([def.parser])) : "";
|
|
7545
7854
|
const sepSent = rec ? syncSentinelExpr(firstSetOf(def.separator)) : null;
|
|
7546
7855
|
const scanSync = sepSent ? `_ctx._rec.or(${sepSent}, ${mySyncV})` : mySyncV;
|
|
7547
|
-
const
|
|
7856
|
+
const first = emitFallible(def.parser, ctx, pos, true);
|
|
7857
|
+
const { stmts: firstStmts, okVar: firstOk, valVar: firstVal, endVar: firstEnd } = first;
|
|
7548
7858
|
const stmts = [
|
|
7549
7859
|
`${ind(ctx)}const ${arrV} = []`,
|
|
7550
7860
|
`${ind(ctx)}let ${curV} = ${pos}`,
|
|
7551
7861
|
...rec ? [`${ind(ctx)}const ${mySyncV} = _ctx._sync`] : [],
|
|
7552
7862
|
...firstStmts
|
|
7553
7863
|
];
|
|
7554
|
-
const failItem = (nextOkVar, itemPosVar, breakStmt) => {
|
|
7555
|
-
if (
|
|
7864
|
+
const failItem = (nextOkVar, nextMayCommit, itemPosVar, breakStmt) => {
|
|
7865
|
+
const commit = nextMayCommit ? `if (_ctx._fc) ${committedFailBody(ctx)}; ` : "";
|
|
7866
|
+
if (!rec) return [`${ind(ctx)}if (!${nextOkVar}) { ${commit}${breakStmt} }`];
|
|
7556
7867
|
const rr = v(ctx, "_rr");
|
|
7557
7868
|
return [
|
|
7558
7869
|
`${ind(ctx)}if (!${nextOkVar}) {`,
|
|
7870
|
+
...nextMayCommit ? [`${ind(ctx)} if (_ctx._fc) ${committedFailBody(ctx)}`] : [],
|
|
7559
7871
|
`${ind(ctx)} if (_ctx._tolerant && ${mySyncV} !== undefined && !_ctx._rec.at(${mySyncV}, input, ${itemPosVar}, _ctx)) {`,
|
|
7560
7872
|
`${ind(ctx)} const ${rr} = _ctx._rec.scan(input, ${itemPosVar}, _ctx, ${scanSync}, ${exp})`,
|
|
7561
7873
|
`${ind(ctx)} ${arrV}.push(${rr}.error); _ctx._rec.capture(_ctx, ${rr}.error); ${curV} = ${rr}.end; continue`,
|
|
@@ -7584,6 +7896,7 @@ function emitSepBy(_p, def, ctx, pos) {
|
|
|
7584
7896
|
stmts.push(
|
|
7585
7897
|
`${ind(ctx)}let ${didV} = false`,
|
|
7586
7898
|
`${ind(ctx)}if (${firstOk}) { ${arrV}.push(${firstVal}); ${curV} = ${firstEnd}; ${didV} = true }`,
|
|
7899
|
+
...first.mayCommit ? [`${ind(ctx)}else if (_ctx._fc) ${committedFailBody(ctx)}`] : [],
|
|
7587
7900
|
`${ind(ctx)}else if (_ctx._tolerant && ${mySyncV} !== undefined && !_ctx._rec.at(${mySyncV}, input, ${pos}, _ctx)) {`,
|
|
7588
7901
|
`${ind(ctx)} const ${rr0} = _ctx._rec.scan(input, ${pos}, _ctx, ${scanSync}, ${exp})`,
|
|
7589
7902
|
`${ind(ctx)} ${arrV}.push(${rr0}.error); _ctx._rec.capture(_ctx, ${rr0}.error); ${curV} = ${rr0}.end; ${didV} = true`,
|
|
@@ -7594,6 +7907,7 @@ function emitSepBy(_p, def, ctx, pos) {
|
|
|
7594
7907
|
stmts.push(`${ind(ctx)}while (${curV} < input.length) {`);
|
|
7595
7908
|
ctx.indent++;
|
|
7596
7909
|
} else {
|
|
7910
|
+
if (first.mayCommit) stmts.push(`${ind(ctx)}if (!${firstOk} && _ctx._fc) ${committedFailBody(ctx)}`);
|
|
7597
7911
|
stmts.push(`${ind(ctx)}if (${firstOk}) {`);
|
|
7598
7912
|
ctx.indent++;
|
|
7599
7913
|
stmts.push(
|
|
@@ -7622,16 +7936,18 @@ function emitSepBy(_p, def, ctx, pos) {
|
|
|
7622
7936
|
);
|
|
7623
7937
|
sepAtPos = spV;
|
|
7624
7938
|
const rollbackToSep = `if (_ctx._cstLeaves && _ctx._cstLeaves.length !== ${markLv}) _ctx._cstLeaves.length = ${markLv}; if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${markV}) _ctx._cstRawChildren.length = ${markV}; if (_ctx._cstTriviaLog && _ctx._cstTriviaLog.length !== ${markTl}) _ctx._cstTriviaLog.length = ${markTl}; if (_ctx._triviaLog && _ctx._triviaLog.length !== ${markLog}) _ctx._triviaLog.length = ${markLog}; `;
|
|
7625
|
-
const
|
|
7626
|
-
stmts
|
|
7939
|
+
const sep2 = emitFallible(def.separator, ctx, sepAtPos, true);
|
|
7940
|
+
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = sep2;
|
|
7941
|
+
stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) { ${rollbackToSep}${sep2.mayCommit ? `if (_ctx._fc) ${committedFailBody(ctx)}; ` : ""}break }`);
|
|
7627
7942
|
const post = postSepMarks();
|
|
7628
7943
|
stmts.push(...post.decl);
|
|
7629
7944
|
const npV = v(ctx, "_np");
|
|
7630
7945
|
stmts.push(`${ind(ctx)}const ${npV} = ${capFn}(input, ${sepEnd}, _ctx, 1)`);
|
|
7631
|
-
const
|
|
7946
|
+
const next = emitFallible(def.parser, ctx, npV, true);
|
|
7947
|
+
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = next;
|
|
7632
7948
|
stmts.push(
|
|
7633
7949
|
...nextStmts,
|
|
7634
|
-
...failItem(nextOk, npV, itemFailBreak(sepEnd, rollbackToSep, post.rb)),
|
|
7950
|
+
...failItem(nextOk, next.mayCommit, npV, itemFailBreak(sepEnd, rollbackToSep, post.rb)),
|
|
7635
7951
|
`${ind(ctx)}${arrV}.push(${nextVal})`,
|
|
7636
7952
|
`${ind(ctx)}${curV} = ${nextEnd}`
|
|
7637
7953
|
);
|
|
@@ -7640,14 +7956,16 @@ function emitSepBy(_p, def, ctx, pos) {
|
|
|
7640
7956
|
const spV = v(ctx, "_sp");
|
|
7641
7957
|
stmts.push(`${ind(ctx)}const ${spV} = ${trivFn}(input, ${curV}, _ctx)`);
|
|
7642
7958
|
sepAtPos = spV;
|
|
7643
|
-
const
|
|
7644
|
-
stmts
|
|
7959
|
+
const sep2 = emitFallible(def.separator, ctx, sepAtPos, true);
|
|
7960
|
+
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = sep2;
|
|
7961
|
+
stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) { ${sep2.mayCommit ? `if (_ctx._fc) ${committedFailBody(ctx)}; ` : ""}break }`);
|
|
7645
7962
|
const npV = v(ctx, "_np");
|
|
7646
7963
|
stmts.push(`${ind(ctx)}const ${npV} = ${trivFn}(input, ${sepEnd}, _ctx)`);
|
|
7647
|
-
const
|
|
7964
|
+
const next = emitFallible(def.parser, ctx, npV, true);
|
|
7965
|
+
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = next;
|
|
7648
7966
|
stmts.push(
|
|
7649
7967
|
...nextStmts,
|
|
7650
|
-
...failItem(nextOk, npV, itemFailBreak(sepEnd, "", "")),
|
|
7968
|
+
...failItem(nextOk, next.mayCommit, npV, itemFailBreak(sepEnd, "", "")),
|
|
7651
7969
|
`${ind(ctx)}${arrV}.push(${nextVal})`,
|
|
7652
7970
|
`${ind(ctx)}${curV} = ${nextEnd}`
|
|
7653
7971
|
);
|
|
@@ -7661,15 +7979,17 @@ function emitSepBy(_p, def, ctx, pos) {
|
|
|
7661
7979
|
`${ind(ctx)}const ${markRw} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`
|
|
7662
7980
|
);
|
|
7663
7981
|
}
|
|
7664
|
-
const
|
|
7665
|
-
stmts
|
|
7982
|
+
const sep2 = emitFallible(def.separator, ctx, sepAtPos, true);
|
|
7983
|
+
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = sep2;
|
|
7984
|
+
stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) { ${sep2.mayCommit ? `if (_ctx._fc) ${committedFailBody(ctx)}; ` : ""}break }`);
|
|
7666
7985
|
const nextRb = markLv ? `if (_ctx._cstLeaves && _ctx._cstLeaves.length !== ${markLv}) _ctx._cstLeaves.length = ${markLv}; if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${markRw}) _ctx._cstRawChildren.length = ${markRw}; ` : "";
|
|
7667
7986
|
const post = postSepMarks();
|
|
7668
7987
|
stmts.push(...post.decl);
|
|
7669
|
-
const
|
|
7988
|
+
const next = emitFallible(def.parser, ctx, sepEnd, true);
|
|
7989
|
+
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = next;
|
|
7670
7990
|
stmts.push(
|
|
7671
7991
|
...nextStmts,
|
|
7672
|
-
...failItem(nextOk, sepEnd, itemFailBreak(sepEnd, nextRb, post.rb)),
|
|
7992
|
+
...failItem(nextOk, next.mayCommit, sepEnd, itemFailBreak(sepEnd, nextRb, post.rb)),
|
|
7673
7993
|
`${ind(ctx)}${arrV}.push(${nextVal})`,
|
|
7674
7994
|
`${ind(ctx)}${curV} = ${nextEnd}`
|
|
7675
7995
|
);
|
|
@@ -8050,7 +8370,7 @@ function emitRuntimeFallback(parser2, ctx, pos) {
|
|
|
8050
8370
|
const rv = v(ctx, "_rt");
|
|
8051
8371
|
const vv = v(ctx, "_rtv");
|
|
8052
8372
|
const ev = v(ctx, "_rte");
|
|
8053
|
-
const failStmt = ctx.failLabel ? ctx.recordFail ? `{ _ctx._fe = ${rv}.span.start; _ctx._fx = ${rv}.expected; break ${ctx.failLabel} }` : `break ${ctx.failLabel}` : `return { ok: false, expected: ${rv}.expected, span: ${rv}.span }`;
|
|
8373
|
+
const failStmt = ctx.failLabel ? ctx.recordFail ? `{ _ctx._fe = ${rv}.span.start; _ctx._fx = ${rv}.expected; _ctx._fc = ${rv}.committed === true; break ${ctx.failLabel} }` : `{ _ctx._fc = ${rv}.committed === true; break ${ctx.failLabel} }` : `return { ok: false, expected: ${rv}.expected, span: ${rv}.span, ...(${rv}.committed ? { committed: true } : {}) }`;
|
|
8054
8374
|
const stmts = [
|
|
8055
8375
|
`${ind(ctx)}const ${rv} = _rp[${idx}].parse(input, ${pos}, _ctx)`,
|
|
8056
8376
|
...emitIfFail(ctx, `!${rv}.ok`, failStmt),
|
|
@@ -8131,7 +8451,7 @@ function emitRecover(def, ctx, pos) {
|
|
|
8131
8451
|
return { stmts, valueVar: valVar, endVar };
|
|
8132
8452
|
}
|
|
8133
8453
|
function emitExpect(def, ctx, pos) {
|
|
8134
|
-
const { stmts: innerStmts, okVar, valVar, endVar } = emitFallible(def.parser, ctx, pos);
|
|
8454
|
+
const { stmts: innerStmts, okVar, valVar, endVar, mayCommit } = emitFallible(def.parser, ctx, pos);
|
|
8135
8455
|
const ind0 = ind(ctx);
|
|
8136
8456
|
const errV = v(ctx, "_err");
|
|
8137
8457
|
const stmts = [
|
|
@@ -8143,6 +8463,7 @@ function emitExpect(def, ctx, pos) {
|
|
|
8143
8463
|
// interpreter (expect.ts) and the list-recovery emit sites — guarded on
|
|
8144
8464
|
// `_ctx._tolerant`, under which the driver always installs `_ctx._rec`.
|
|
8145
8465
|
`${ind0} if (_ctx._tolerant) _ctx._rec.capture(_ctx, ${errV})`,
|
|
8466
|
+
...mayCommit ? [`${ind0} _ctx._fc = false`] : [],
|
|
8146
8467
|
`${ind0} ${valVar} = ${errV}`,
|
|
8147
8468
|
`${ind0} ${endVar} = ${pos}`,
|
|
8148
8469
|
`${ind0} ${okVar} = true`,
|
|
@@ -8153,7 +8474,7 @@ function emitExpect(def, ctx, pos) {
|
|
|
8153
8474
|
function emit(p, ctx, pos) {
|
|
8154
8475
|
const replay = ctx.replayPrefix?.get(p);
|
|
8155
8476
|
if (replay !== void 0) return emitReplayPrefixLeaf(ctx, pos, replay);
|
|
8156
|
-
const
|
|
8477
|
+
const dispatch2 = (emissionPos = pos) => {
|
|
8157
8478
|
const savedRule = ctx.activeCoverageRuleId;
|
|
8158
8479
|
const rule = ctx.coverage?.plan.rules.get(p);
|
|
8159
8480
|
if (rule && p !== ctx.coverage?.entry && !ctx.suppressCoverageFailure) ctx.activeCoverageRuleId = rule;
|
|
@@ -8193,14 +8514,14 @@ function emit(p, ctx, pos) {
|
|
|
8193
8514
|
ctx.indent = 1;
|
|
8194
8515
|
ctx.failLabel = "_pfail";
|
|
8195
8516
|
ctx.recordFail = true;
|
|
8196
|
-
const r =
|
|
8517
|
+
const r = dispatch2("_pos");
|
|
8197
8518
|
ctx.indent = savedIndent;
|
|
8198
8519
|
ctx.failLabel = savedFailLabel;
|
|
8199
8520
|
ctx.recordFail = savedRecord;
|
|
8200
8521
|
pushNamedFnDecl(ctx, fnName, r.stmts, r.valueVar, r.endVar);
|
|
8201
8522
|
return instrument(emitNamedFnCall(ctx, fnName, pos));
|
|
8202
8523
|
}
|
|
8203
|
-
return instrument(
|
|
8524
|
+
return instrument(dispatch2());
|
|
8204
8525
|
}
|
|
8205
8526
|
function emitDispatch(p, ctx, pos) {
|
|
8206
8527
|
const bal = p._balancedAmbient;
|
|
@@ -8233,6 +8554,8 @@ function emitDispatch(p, ctx, pos) {
|
|
|
8233
8554
|
return emitSeq(def, ctx, pos);
|
|
8234
8555
|
case "choice":
|
|
8235
8556
|
return emitChoice(p, def, ctx, pos);
|
|
8557
|
+
case "dispatch":
|
|
8558
|
+
return emitDispatchCombinator(def, ctx, pos);
|
|
8236
8559
|
case "attempt":
|
|
8237
8560
|
return emitAttempt(p, def, ctx, pos);
|
|
8238
8561
|
case "many":
|
|
@@ -8453,6 +8776,8 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
8453
8776
|
case "sequence":
|
|
8454
8777
|
case "choice":
|
|
8455
8778
|
return d.parsers.some((x) => hasNodeDef(x, seen));
|
|
8779
|
+
case "dispatch":
|
|
8780
|
+
return hasNodeDef(d.selector, seen) || d.cases.some((x) => hasNodeDef(x.parser, seen)) || (d.otherwise ? hasNodeDef(d.otherwise, seen) : false);
|
|
8456
8781
|
case "sepBy":
|
|
8457
8782
|
return hasNodeDef(d.parser, seen) || hasNodeDef(d.separator, seen);
|
|
8458
8783
|
case "scanTo":
|
|
@@ -8486,6 +8811,8 @@ function childrenOf2(def) {
|
|
|
8486
8811
|
case "sequence":
|
|
8487
8812
|
case "choice":
|
|
8488
8813
|
return def.parsers;
|
|
8814
|
+
case "dispatch":
|
|
8815
|
+
return [def.selector, ...def.cases.map((entry) => entry.parser), ...def.otherwise ? [def.otherwise] : []];
|
|
8489
8816
|
case "many":
|
|
8490
8817
|
case "attempt":
|
|
8491
8818
|
case "optional":
|
|
@@ -8529,6 +8856,7 @@ function childrenOf2(def) {
|
|
|
8529
8856
|
var HOISTABLE_TAGS = /* @__PURE__ */ new Set([
|
|
8530
8857
|
"sequence",
|
|
8531
8858
|
"choice",
|
|
8859
|
+
"dispatch",
|
|
8532
8860
|
"many",
|
|
8533
8861
|
"oneOrMore",
|
|
8534
8862
|
"optional",
|
|
@@ -9353,6 +9681,8 @@ function childrenOf3(def) {
|
|
|
9353
9681
|
case "sequence":
|
|
9354
9682
|
case "choice":
|
|
9355
9683
|
return def.parsers;
|
|
9684
|
+
case "dispatch":
|
|
9685
|
+
return [def.selector, ...def.cases.map((entry) => entry.parser), ...def.otherwise ? [def.otherwise] : []];
|
|
9356
9686
|
case "many":
|
|
9357
9687
|
case "oneOrMore":
|
|
9358
9688
|
case "optional":
|
|
@@ -9502,6 +9832,9 @@ function evalRuleMapIR(ir) {
|
|
|
9502
9832
|
"keywords",
|
|
9503
9833
|
"sequence",
|
|
9504
9834
|
"choice",
|
|
9835
|
+
"dispatch",
|
|
9836
|
+
"when",
|
|
9837
|
+
"otherwise",
|
|
9505
9838
|
"attempt",
|
|
9506
9839
|
"many",
|
|
9507
9840
|
"oneOrMore",
|
|
@@ -9535,6 +9868,9 @@ function evalRuleMapIR(ir) {
|
|
|
9535
9868
|
keywords,
|
|
9536
9869
|
sequence,
|
|
9537
9870
|
choice,
|
|
9871
|
+
dispatch,
|
|
9872
|
+
when,
|
|
9873
|
+
otherwise,
|
|
9538
9874
|
attempt,
|
|
9539
9875
|
many,
|
|
9540
9876
|
oneOrMore,
|
|
@@ -9720,6 +10056,13 @@ ${outerDecls.map((d) => " " + d).join("\n")}
|
|
|
9720
10056
|
});
|
|
9721
10057
|
return `_gch([${items.join(", ")}])`;
|
|
9722
10058
|
}
|
|
10059
|
+
case "dispatch": {
|
|
10060
|
+
const arms = def.cases.map(
|
|
10061
|
+
(entry) => `when(${entry.keys.length === 1 ? JSON.stringify(entry.keys[0]) : JSON.stringify(entry.keys)}, ${kid(entry.parser)})`
|
|
10062
|
+
);
|
|
10063
|
+
if (def.otherwise) arms.push(`otherwise(${kid(def.otherwise)})`);
|
|
10064
|
+
return `dispatch(${kid(def.selector)}${arms.length === 0 ? "" : `, ${arms.join(", ")}`})`;
|
|
10065
|
+
}
|
|
9723
10066
|
case "many":
|
|
9724
10067
|
return `many(${kid(def.parser)}${repeatOpts(def.min, def.max)})`;
|
|
9725
10068
|
// A `oneOrMore` def with min > 1 came from `many(x, { min: n })`; round-trip
|
|
@@ -10205,6 +10548,9 @@ function stripTsFromSource(node2, code) {
|
|
|
10205
10548
|
function isWordFactory(v2) {
|
|
10206
10549
|
return !!v2 && typeof v2 === "object" && v2.tag === "wordFactory";
|
|
10207
10550
|
}
|
|
10551
|
+
function isStaticValueEntry(v2) {
|
|
10552
|
+
return !!v2 && typeof v2 === "object" && "value" in v2 && "mfSrcs" in v2;
|
|
10553
|
+
}
|
|
10208
10554
|
function wordFactoryFromArgs(args, scope, code, mfs) {
|
|
10209
10555
|
const [boundaryOrOptsArg, optsArg] = args;
|
|
10210
10556
|
if (boundaryOrOptsArg?.type === "SpreadElement" || optsArg?.type === "SpreadElement") return null;
|
|
@@ -10274,9 +10620,41 @@ function gatedArmParts(e) {
|
|
|
10274
10620
|
}
|
|
10275
10621
|
return gate2 && combinator ? { gate: gate2, combinator } : null;
|
|
10276
10622
|
}
|
|
10623
|
+
function dispatchArmValue(node2, scope, code, mfs) {
|
|
10624
|
+
if (node2.type === "Identifier") {
|
|
10625
|
+
const value = anyValue(node2, scope, code, mfs);
|
|
10626
|
+
return isDispatchArm(value) ? value : null;
|
|
10627
|
+
}
|
|
10628
|
+
if (node2.type !== "CallExpression") return null;
|
|
10629
|
+
const callee = node2.callee;
|
|
10630
|
+
if (callee.type !== "Identifier") return null;
|
|
10631
|
+
if (callee.name === "otherwise") {
|
|
10632
|
+
const [parserArg] = node2.arguments;
|
|
10633
|
+
if (!parserArg || parserArg.type === "SpreadElement") return null;
|
|
10634
|
+
const parserValue = anyValue(parserArg, scope, code, mfs);
|
|
10635
|
+
if (!isCombinator(parserValue)) return null;
|
|
10636
|
+
return otherwise(parserValue);
|
|
10637
|
+
}
|
|
10638
|
+
if (callee.name === "when") {
|
|
10639
|
+
const [keyArg, parserArg] = node2.arguments;
|
|
10640
|
+
if (!keyArg || !parserArg || keyArg.type === "SpreadElement" || parserArg.type === "SpreadElement") return null;
|
|
10641
|
+
const key = anyValue(keyArg, scope, code, mfs);
|
|
10642
|
+
const parserValue = anyValue(parserArg, scope, code, mfs);
|
|
10643
|
+
if (!isCombinator(parserValue)) return null;
|
|
10644
|
+
if (typeof key === "string") return when(key, parserValue);
|
|
10645
|
+
if (Array.isArray(key) && key.every((item) => typeof item === "string")) return when(key, parserValue);
|
|
10646
|
+
}
|
|
10647
|
+
return null;
|
|
10648
|
+
}
|
|
10277
10649
|
function isCombinator(v2) {
|
|
10278
10650
|
return !!v2 && typeof v2 === "object" && "_def" in v2;
|
|
10279
10651
|
}
|
|
10652
|
+
function isDispatchArm(v2) {
|
|
10653
|
+
if (!v2 || typeof v2 !== "object") return false;
|
|
10654
|
+
const rec = v2;
|
|
10655
|
+
if (rec.kind === "otherwise") return isCombinator(rec.parser);
|
|
10656
|
+
return rec.kind === "when" && Array.isArray(rec.keys) && rec.keys.every((key) => typeof key === "string") && isCombinator(rec.parser);
|
|
10657
|
+
}
|
|
10280
10658
|
function scopeGet(scope, name, mfs) {
|
|
10281
10659
|
const entry = scope.get(name);
|
|
10282
10660
|
if (!entry) return null;
|
|
@@ -10533,6 +10911,25 @@ function exprToCombi(node2, scope, code, mfs) {
|
|
|
10533
10911
|
return null;
|
|
10534
10912
|
}
|
|
10535
10913
|
}
|
|
10914
|
+
if (callee.name === "dispatch") {
|
|
10915
|
+
const [selectorArg, ...armArgs] = node2.arguments;
|
|
10916
|
+
if (!selectorArg || selectorArg.type === "SpreadElement") return null;
|
|
10917
|
+
const selector = anyValue(selectorArg, scope, code, mfs);
|
|
10918
|
+
if (!isCombinator(selector)) return null;
|
|
10919
|
+
const arms = [];
|
|
10920
|
+
for (const arg of armArgs) {
|
|
10921
|
+
if (arg.type === "SpreadElement") return null;
|
|
10922
|
+
const arm = dispatchArmValue(arg, scope, code, mfs);
|
|
10923
|
+
if (!isDispatchArm(arm)) return null;
|
|
10924
|
+
arms.push(arm);
|
|
10925
|
+
}
|
|
10926
|
+
try {
|
|
10927
|
+
const unsafeDispatch = dispatch;
|
|
10928
|
+
return unsafeDispatch(selector, ...arms);
|
|
10929
|
+
} catch {
|
|
10930
|
+
return null;
|
|
10931
|
+
}
|
|
10932
|
+
}
|
|
10536
10933
|
if (callee.name === "choice" && node2.arguments.some((a) => a.type !== "SpreadElement" && isGatedArmExpr(a))) {
|
|
10537
10934
|
if (code === void 0 || mfs === void 0) return null;
|
|
10538
10935
|
const arms = [];
|
|
@@ -10618,6 +11015,10 @@ function anyValue(node2, scope, code, mfs) {
|
|
|
10618
11015
|
if (mfs && entry.mfSrcs.length > 0) mfs.push(...entry.mfSrcs);
|
|
10619
11016
|
return entry.combi;
|
|
10620
11017
|
}
|
|
11018
|
+
if (isStaticValueEntry(entry)) {
|
|
11019
|
+
if (mfs && entry.mfSrcs.length > 0) mfs.push(...entry.mfSrcs);
|
|
11020
|
+
return entry.value;
|
|
11021
|
+
}
|
|
10621
11022
|
return entry;
|
|
10622
11023
|
}
|
|
10623
11024
|
if (node2.type === "MemberExpression") {
|
|
@@ -10638,6 +11039,9 @@ function anyValue(node2, scope, code, mfs) {
|
|
|
10638
11039
|
if (callee.type === "Identifier" && callee.name === "makeWord") {
|
|
10639
11040
|
return wordFactoryFromArgs(node2.arguments, scope, code, mfs);
|
|
10640
11041
|
}
|
|
11042
|
+
if (callee.type === "Identifier" && (callee.name === "when" || callee.name === "otherwise")) {
|
|
11043
|
+
return dispatchArmValue(node2, scope, code, mfs);
|
|
11044
|
+
}
|
|
10641
11045
|
return exprToCombi(node2, scope, code, mfs);
|
|
10642
11046
|
}
|
|
10643
11047
|
return null;
|
|
@@ -10696,6 +11100,7 @@ function evalBodyStatements(statements, scope, code) {
|
|
|
10696
11100
|
if (val === null) return false;
|
|
10697
11101
|
const thisDeclMfSrcs = bodyMfs.slice(before);
|
|
10698
11102
|
if (isCombinator(val)) scope.set(name, { combi: val, mfSrcs: thisDeclMfSrcs });
|
|
11103
|
+
else if (isDispatchArm(val)) scope.set(name, { value: val, mfSrcs: thisDeclMfSrcs });
|
|
10699
11104
|
else scope.set(name, val);
|
|
10700
11105
|
}
|
|
10701
11106
|
}
|