parseman 0.27.0 → 0.28.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/README.md +1 -1
- package/dist/combinators/attempt.d.ts +8 -0
- package/dist/combinators/attempt.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/grammar.d.ts.map +1 -1
- package/dist/combinators/node.d.ts +8 -0
- package/dist/combinators/node.d.ts.map +1 -1
- package/dist/combinators/scanTo.d.ts.map +1 -1
- package/dist/combinators/token.d.ts +12 -0
- package/dist/combinators/token.d.ts.map +1 -1
- package/dist/compiler/build-arity.d.ts +8 -4
- package/dist/compiler/build-arity.d.ts.map +1 -1
- package/dist/compiler/codegen.d.ts +12 -0
- package/dist/compiler/codegen.d.ts.map +1 -1
- package/dist/compiler/fields.d.ts +7 -0
- package/dist/compiler/fields.d.ts.map +1 -1
- package/dist/compiler/grammar-coverage-ids.d.ts +19 -0
- package/dist/compiler/grammar-coverage-ids.d.ts.map +1 -0
- package/dist/compiler/inline-callback.d.ts.map +1 -1
- package/dist/compiler/ir-serialize.d.ts.map +1 -1
- package/dist/compiler/linker.d.ts +12 -1
- package/dist/compiler/linker.d.ts.map +1 -1
- package/dist/compiler/value-usage.d.ts.map +1 -1
- package/dist/coverage.d.ts +68 -0
- package/dist/coverage.d.ts.map +1 -0
- package/dist/cst/trivia-entries.d.ts +2 -0
- package/dist/cst/trivia-entries.d.ts.map +1 -1
- package/dist/functional/doc.d.ts.map +1 -1
- package/dist/functional/run.d.ts +13 -0
- package/dist/functional/run.d.ts.map +1 -1
- package/dist/index.cjs +936 -103
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +936 -103
- package/dist/index.js.map +4 -4
- package/dist/language-service/index.cjs +7 -2
- package/dist/language-service/index.cjs.map +2 -2
- package/dist/language-service/index.js +7 -2
- package/dist/language-service/index.js.map +2 -2
- package/dist/plugin/direct-builder-static.d.ts +8 -0
- package/dist/plugin/direct-builder-static.d.ts.map +1 -0
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.cjs +1084 -145
- package/dist/plugin/index.cjs.map +4 -4
- package/dist/plugin/index.d.ts +4 -1
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +1084 -145
- package/dist/plugin/index.js.map +4 -4
- package/dist/spec/index.cjs +3 -0
- package/dist/spec/index.cjs.map +2 -2
- package/dist/spec/index.js +3 -0
- package/dist/spec/index.js.map +2 -2
- package/dist/spec/model.d.ts.map +1 -1
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -1
package/dist/plugin/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// src/plugin/index.ts
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
|
+
import * as path from "node:path";
|
|
3
4
|
import { createUnplugin } from "unplugin";
|
|
4
|
-
import { parseSync } from "oxc-parser";
|
|
5
|
+
import { parseSync as parseSync2 } from "oxc-parser";
|
|
5
6
|
import { ResolverFactory } from "oxc-resolver";
|
|
6
7
|
import MagicString from "magic-string";
|
|
7
8
|
|
|
@@ -66,6 +67,7 @@ function matchesEmpty(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
66
67
|
case "label":
|
|
67
68
|
case "trivia":
|
|
68
69
|
case "token":
|
|
70
|
+
case "leaf":
|
|
69
71
|
case "expect":
|
|
70
72
|
case "withCtx":
|
|
71
73
|
case "node":
|
|
@@ -129,6 +131,7 @@ function firstSetOf(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
129
131
|
case "label":
|
|
130
132
|
case "trivia":
|
|
131
133
|
case "token":
|
|
134
|
+
case "leaf":
|
|
132
135
|
case "node":
|
|
133
136
|
case "grammar":
|
|
134
137
|
case "expect":
|
|
@@ -234,10 +237,10 @@ function beginCstNodeCapture(ctx) {
|
|
|
234
237
|
}
|
|
235
238
|
function finishCstBuf(buf) {
|
|
236
239
|
if (!buf) return { children: EMPTY, rawChildren: EMPTY, triviaLog: EMPTY_TL };
|
|
237
|
-
const
|
|
240
|
+
const children2 = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY);
|
|
238
241
|
const rawChildren = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY);
|
|
239
242
|
const triviaLog = buf.tl ?? EMPTY_TL;
|
|
240
|
-
return { children, rawChildren, triviaLog };
|
|
243
|
+
return { children: children2, rawChildren, triviaLog };
|
|
241
244
|
}
|
|
242
245
|
function endCstNodeCapture(ctx, saved) {
|
|
243
246
|
const materialized = finishCstBuf(ctx._cstBuf);
|
|
@@ -249,8 +252,8 @@ function endCstNodeCapture(ctx, saved) {
|
|
|
249
252
|
ctx.captureTrivia = saved.cap;
|
|
250
253
|
return materialized;
|
|
251
254
|
}
|
|
252
|
-
function pushCstLeaf(ctx,
|
|
253
|
-
pushCstChild(ctx,
|
|
255
|
+
function pushCstLeaf(ctx, leaf2) {
|
|
256
|
+
pushCstChild(ctx, leaf2, leaf2);
|
|
254
257
|
}
|
|
255
258
|
function pushCstChild(ctx, built, rawEntry) {
|
|
256
259
|
const b = ctx._cstBuf;
|
|
@@ -980,10 +983,13 @@ function deriveExpected(c) {
|
|
|
980
983
|
return def.parsers.flatMap(deriveExpected);
|
|
981
984
|
case "sequence":
|
|
982
985
|
return def.parsers.length > 0 ? deriveExpected(def.parsers[0]) : [];
|
|
986
|
+
case "attempt":
|
|
987
|
+
return deriveExpected(def.parser);
|
|
983
988
|
case "node":
|
|
984
989
|
case "grammar":
|
|
985
990
|
case "trivia":
|
|
986
991
|
case "token":
|
|
992
|
+
case "leaf":
|
|
987
993
|
case "optional":
|
|
988
994
|
case "many":
|
|
989
995
|
case "oneOrMore":
|
|
@@ -1474,6 +1480,12 @@ function scanTrivia(input, cur, ctx) {
|
|
|
1474
1480
|
const tr = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
|
|
1475
1481
|
return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
|
|
1476
1482
|
}
|
|
1483
|
+
function consumeTrivia(input, cur, ctx) {
|
|
1484
|
+
if (!needsDeferredTriviaCommit(ctx)) return advanceTrivia(input, cur, ctx);
|
|
1485
|
+
const scan = scanTrivia(input, cur, ctx);
|
|
1486
|
+
scan.commit();
|
|
1487
|
+
return scan.end;
|
|
1488
|
+
}
|
|
1477
1489
|
function fastTriviaScanner(trivia2) {
|
|
1478
1490
|
const cached = fastTriviaCache.get(trivia2);
|
|
1479
1491
|
if (cached !== void 0) return cached;
|
|
@@ -1752,6 +1764,24 @@ function sequence(...parsers) {
|
|
|
1752
1764
|
};
|
|
1753
1765
|
}
|
|
1754
1766
|
|
|
1767
|
+
// src/combinators/attempt.ts
|
|
1768
|
+
function attempt(parser2) {
|
|
1769
|
+
return {
|
|
1770
|
+
_tag: "attempt",
|
|
1771
|
+
_meta: parser2._meta,
|
|
1772
|
+
_def: { tag: "attempt", parser: parser2 },
|
|
1773
|
+
parse(input, pos, ctx) {
|
|
1774
|
+
const mark = saveCstMark(ctx);
|
|
1775
|
+
const log = ctx._triviaLog?.length;
|
|
1776
|
+
const result = parser2.parse(input, pos, ctx);
|
|
1777
|
+
if (result.ok) return result;
|
|
1778
|
+
rollbackCstCapture(ctx, mark);
|
|
1779
|
+
if (log !== void 0 && ctx._triviaLog) ctx._triviaLog.length = log;
|
|
1780
|
+
return { ok: false, expected: result.expected, span: { start: pos, end: pos } };
|
|
1781
|
+
}
|
|
1782
|
+
};
|
|
1783
|
+
}
|
|
1784
|
+
|
|
1755
1785
|
// src/combinators/repeat.ts
|
|
1756
1786
|
function repItem(combinator, input, cur, ctx) {
|
|
1757
1787
|
const mark = saveTriviaMark(ctx);
|
|
@@ -1927,19 +1957,19 @@ function sepBy(combinator, separator) {
|
|
|
1927
1957
|
sepPos = advanceTrivia(input, cur, ctx);
|
|
1928
1958
|
}
|
|
1929
1959
|
}
|
|
1930
|
-
const
|
|
1931
|
-
if (!
|
|
1960
|
+
const sep2 = separator.parse(input, sepPos, ctx);
|
|
1961
|
+
if (!sep2.ok) {
|
|
1932
1962
|
rollbackTrivia(ctx, loopMark);
|
|
1933
1963
|
break;
|
|
1934
1964
|
}
|
|
1935
|
-
let nextPos =
|
|
1965
|
+
let nextPos = sep2.span.end;
|
|
1936
1966
|
if (ctx.trivia) {
|
|
1937
1967
|
if (needsDeferredTriviaCommit(ctx)) {
|
|
1938
|
-
const scan = scanTrivia(input,
|
|
1968
|
+
const scan = scanTrivia(input, sep2.span.end, ctx);
|
|
1939
1969
|
scan.commit();
|
|
1940
1970
|
nextPos = scan.end;
|
|
1941
1971
|
} else {
|
|
1942
|
-
nextPos = advanceTrivia(input,
|
|
1972
|
+
nextPos = advanceTrivia(input, sep2.span.end, ctx);
|
|
1943
1973
|
}
|
|
1944
1974
|
}
|
|
1945
1975
|
const next = combinator.parse(input, nextPos, ctx);
|
|
@@ -2024,10 +2054,14 @@ function markUnusedValues(root) {
|
|
|
2024
2054
|
case "label":
|
|
2025
2055
|
case "trivia":
|
|
2026
2056
|
case "token":
|
|
2057
|
+
case "attempt":
|
|
2027
2058
|
case "withCtx":
|
|
2028
2059
|
case "expect":
|
|
2029
2060
|
visit(def.parser, consumed);
|
|
2030
2061
|
return;
|
|
2062
|
+
case "leaf":
|
|
2063
|
+
visit(def.parser, true);
|
|
2064
|
+
return;
|
|
2031
2065
|
case "lazy":
|
|
2032
2066
|
return;
|
|
2033
2067
|
default:
|
|
@@ -2150,6 +2184,20 @@ function confirmedBuildArity(src) {
|
|
|
2150
2184
|
if (/\barguments\b/.test(s)) return null;
|
|
2151
2185
|
return parts.length;
|
|
2152
2186
|
}
|
|
2187
|
+
function buildReadsChildren(def) {
|
|
2188
|
+
if (!def.build) return true;
|
|
2189
|
+
const src = def.buildSrc ?? def.build.toString();
|
|
2190
|
+
const arity = confirmedBuildArity(src);
|
|
2191
|
+
if (arity === null) return true;
|
|
2192
|
+
return arity >= 1;
|
|
2193
|
+
}
|
|
2194
|
+
function buildReadsRaw(def) {
|
|
2195
|
+
if (!def.build) return true;
|
|
2196
|
+
const src = def.buildSrc ?? def.build.toString();
|
|
2197
|
+
const arity = confirmedBuildArity(src);
|
|
2198
|
+
if (arity === null) return true;
|
|
2199
|
+
return arity >= 4;
|
|
2200
|
+
}
|
|
2153
2201
|
function buildReadsTrivia(def) {
|
|
2154
2202
|
if (!def.build) return true;
|
|
2155
2203
|
const src = def.buildSrc ?? def.build.toString();
|
|
@@ -2205,9 +2253,11 @@ function parserHasOwnFields(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
2205
2253
|
case "many":
|
|
2206
2254
|
case "oneOrMore":
|
|
2207
2255
|
case "optional":
|
|
2256
|
+
case "attempt":
|
|
2208
2257
|
case "transform":
|
|
2209
2258
|
case "trivia":
|
|
2210
2259
|
case "token":
|
|
2260
|
+
case "leaf":
|
|
2211
2261
|
case "label":
|
|
2212
2262
|
case "expect":
|
|
2213
2263
|
case "withCtx":
|
|
@@ -2240,9 +2290,11 @@ function parserHasTriviaSite(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
2240
2290
|
case "keywords":
|
|
2241
2291
|
case "guard":
|
|
2242
2292
|
case "token":
|
|
2293
|
+
case "leaf":
|
|
2243
2294
|
return false;
|
|
2244
2295
|
// Transparent single-child wrappers: recurse.
|
|
2245
2296
|
case "optional":
|
|
2297
|
+
case "attempt":
|
|
2246
2298
|
case "transform":
|
|
2247
2299
|
case "trivia":
|
|
2248
2300
|
case "label":
|
|
@@ -2266,6 +2318,54 @@ function parserHasTriviaSite(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
2266
2318
|
return true;
|
|
2267
2319
|
}
|
|
2268
2320
|
}
|
|
2321
|
+
function parserEnablesTriviaCapture(p, seen = /* @__PURE__ */ new Set()) {
|
|
2322
|
+
if (seen.has(p)) return false;
|
|
2323
|
+
seen.add(p);
|
|
2324
|
+
const d = p._def;
|
|
2325
|
+
switch (d.tag) {
|
|
2326
|
+
case "grammar":
|
|
2327
|
+
return d.captureTrivia === true || parserEnablesTriviaCapture(d.parser, seen);
|
|
2328
|
+
case "node":
|
|
2329
|
+
return false;
|
|
2330
|
+
case "sequence":
|
|
2331
|
+
case "choice":
|
|
2332
|
+
return d.parsers.some((x) => parserEnablesTriviaCapture(x, seen));
|
|
2333
|
+
case "sepBy":
|
|
2334
|
+
return parserEnablesTriviaCapture(d.parser, seen) || parserEnablesTriviaCapture(d.separator, seen);
|
|
2335
|
+
case "skip":
|
|
2336
|
+
return parserEnablesTriviaCapture(d.main, seen) || parserEnablesTriviaCapture(d.skipped, seen);
|
|
2337
|
+
case "scanTo":
|
|
2338
|
+
return parserEnablesTriviaCapture(d.sentinel, seen) || d.skip.some((x) => parserEnablesTriviaCapture(x, seen));
|
|
2339
|
+
case "recover":
|
|
2340
|
+
return parserEnablesTriviaCapture(d.parser, seen) || parserEnablesTriviaCapture(d.sentinel, seen);
|
|
2341
|
+
case "many":
|
|
2342
|
+
case "oneOrMore":
|
|
2343
|
+
case "optional":
|
|
2344
|
+
case "attempt":
|
|
2345
|
+
case "transform":
|
|
2346
|
+
case "trivia":
|
|
2347
|
+
case "token":
|
|
2348
|
+
case "label":
|
|
2349
|
+
case "field":
|
|
2350
|
+
case "expect":
|
|
2351
|
+
case "withCtx":
|
|
2352
|
+
case "not":
|
|
2353
|
+
return parserEnablesTriviaCapture(d.parser, seen);
|
|
2354
|
+
// leaf() clears the inner CST/trivia collector and publishes only its own
|
|
2355
|
+
// terminal result. An inner parser() capture cannot reach this node.
|
|
2356
|
+
case "leaf":
|
|
2357
|
+
return false;
|
|
2358
|
+
case "lazy": {
|
|
2359
|
+
try {
|
|
2360
|
+
return parserEnablesTriviaCapture(d.thunk(), seen);
|
|
2361
|
+
} catch {
|
|
2362
|
+
return false;
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
default:
|
|
2366
|
+
return false;
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2269
2369
|
function buildFieldMap(captures) {
|
|
2270
2370
|
if (!captures?.length) return void 0;
|
|
2271
2371
|
const out = {};
|
|
@@ -2303,11 +2403,13 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
2303
2403
|
};
|
|
2304
2404
|
const unwrap = opts?.unwrap === true;
|
|
2305
2405
|
const collapse = opts?.collapse === true;
|
|
2406
|
+
const captureTrivia = opts?.captureTrivia === true;
|
|
2407
|
+
const trailingTrivia = opts?.trailingTrivia === true;
|
|
2306
2408
|
if (unwrap && collapse) {
|
|
2307
2409
|
throw new Error("node() options cannot set both unwrap and collapse");
|
|
2308
2410
|
}
|
|
2309
|
-
const def = unwrap || collapse ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {} } : baseDef;
|
|
2310
|
-
const capturesTrivia = build ? buildReadsTrivia(def) : true;
|
|
2411
|
+
const def = unwrap || collapse || captureTrivia || trailingTrivia ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {}, ...captureTrivia ? { captureTrivia: true } : {}, ...trailingTrivia ? { trailingTrivia: true } : {} } : baseDef;
|
|
2412
|
+
const capturesTrivia = captureTrivia || trailingTrivia || (build ? buildReadsTrivia(def) : true);
|
|
2311
2413
|
const clonesState = build ? buildReadsState(def) : true;
|
|
2312
2414
|
const capturesFields = parserHasOwnFields(combinator) && (build ? buildReadsFields(def) : true);
|
|
2313
2415
|
return {
|
|
@@ -2323,16 +2425,21 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
2323
2425
|
ctx._triviaCaptureMask = ctx.build._parsemanTriviaKinds(def.type);
|
|
2324
2426
|
}
|
|
2325
2427
|
if (!capturesTrivia) ctx.captureTrivia = false;
|
|
2326
|
-
|
|
2428
|
+
let r = combinator.parse(input, pos, ctx);
|
|
2429
|
+
if (r.ok && trailingTrivia && ctx.trivia) {
|
|
2430
|
+
const end = consumeTrivia(input, r.span.end, ctx);
|
|
2431
|
+
r = { ...r, span: { start: r.span.start, end } };
|
|
2432
|
+
}
|
|
2327
2433
|
const fields = capturesFields ? buildFieldMap(ctx._fields) : void 0;
|
|
2328
2434
|
ctx._fields = savedFields;
|
|
2329
2435
|
ctx._triviaCaptureMask = savedMask;
|
|
2330
|
-
const { children, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
|
|
2436
|
+
const { children: children2, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
|
|
2331
2437
|
if (!r.ok) return r;
|
|
2332
2438
|
const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
|
|
2333
2439
|
const nodeType = def.type ?? missingInferredType();
|
|
2334
|
-
const
|
|
2335
|
-
const
|
|
2440
|
+
const cstOutput = ctx.build?._parsemanCstOutput === true;
|
|
2441
|
+
const built = unwrap && children2.length === 1 ? unwrapChild(children2[0]) : collapse && children2.length === 1 ? children2[0] : !build && ctx.build?._parsemanCstCollapse && children2.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children2[0], children2, rawChildren) ? children2[0] : build ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, r.span, rawChildren, triviaLog, st) : build(children2, fields, r.span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children2, fields, r.span, rawChildren, triviaLog, st) : { _tag: "node", type: nodeType, span: { start: r.span.start, end: r.span.end }, state: st ?? null, children: children2 };
|
|
2442
|
+
const rawEntry = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : typeof built === "object" && built !== null ? input.slice(r.span.start, r.span.end) : "", span: r.span };
|
|
2336
2443
|
if (saved.buf !== void 0 || saved.ch !== void 0) {
|
|
2337
2444
|
pushCstChild(ctx, built, rawEntry);
|
|
2338
2445
|
}
|
|
@@ -2449,6 +2556,7 @@ function parser(opts, root) {
|
|
|
2449
2556
|
parser: root,
|
|
2450
2557
|
triviaParser: clearTrivia ? void 0 : opts.trivia ?? void 0,
|
|
2451
2558
|
clearTrivia,
|
|
2559
|
+
...opts.captureTrivia ? { captureTrivia: true } : {},
|
|
2452
2560
|
trackLines: opts.trackLines ?? false
|
|
2453
2561
|
},
|
|
2454
2562
|
parse(input, pos, _ctx) {
|
|
@@ -2536,6 +2644,141 @@ function token(root) {
|
|
|
2536
2644
|
}
|
|
2537
2645
|
};
|
|
2538
2646
|
}
|
|
2647
|
+
function leaf(root, fn) {
|
|
2648
|
+
const meta = {
|
|
2649
|
+
firstSet: root._meta.firstSet,
|
|
2650
|
+
canMatchNewline: root._meta.canMatchNewline,
|
|
2651
|
+
isTrivia: false
|
|
2652
|
+
};
|
|
2653
|
+
return {
|
|
2654
|
+
_tag: "leaf",
|
|
2655
|
+
_meta: meta,
|
|
2656
|
+
_def: { tag: "leaf", parser: root, fn },
|
|
2657
|
+
parse(input, pos, ctx) {
|
|
2658
|
+
const savedBuf = ctx._cstBuf;
|
|
2659
|
+
const savedChildren = ctx._cstChildren;
|
|
2660
|
+
const savedLeaves = ctx._cstLeaves;
|
|
2661
|
+
const savedRaw = ctx._cstRawChildren;
|
|
2662
|
+
const savedTriviaLog = ctx._cstTriviaLog;
|
|
2663
|
+
const savedOuterTriviaLog = ctx._triviaLog;
|
|
2664
|
+
const wasCapturing = cstCaptureActive(ctx);
|
|
2665
|
+
ctx._cstBuf = void 0;
|
|
2666
|
+
ctx._cstChildren = void 0;
|
|
2667
|
+
ctx._cstLeaves = void 0;
|
|
2668
|
+
ctx._cstRawChildren = void 0;
|
|
2669
|
+
ctx._cstTriviaLog = void 0;
|
|
2670
|
+
delete ctx._triviaLog;
|
|
2671
|
+
let result;
|
|
2672
|
+
try {
|
|
2673
|
+
result = root.parse(input, pos, ctx);
|
|
2674
|
+
} finally {
|
|
2675
|
+
ctx._cstBuf = savedBuf;
|
|
2676
|
+
ctx._cstChildren = savedChildren;
|
|
2677
|
+
ctx._cstLeaves = savedLeaves;
|
|
2678
|
+
ctx._cstRawChildren = savedRaw;
|
|
2679
|
+
ctx._cstTriviaLog = savedTriviaLog;
|
|
2680
|
+
if (savedOuterTriviaLog === void 0) delete ctx._triviaLog;
|
|
2681
|
+
else ctx._triviaLog = savedOuterTriviaLog;
|
|
2682
|
+
}
|
|
2683
|
+
if (!result.ok) return result;
|
|
2684
|
+
const value = fn(result.value, result.span);
|
|
2685
|
+
if (wasCapturing) pushCstLeaf(ctx, { _tag: "leaf", value, span: result.span });
|
|
2686
|
+
return { ok: true, value, span: result.span };
|
|
2687
|
+
}
|
|
2688
|
+
};
|
|
2689
|
+
}
|
|
2690
|
+
|
|
2691
|
+
// src/compiler/grammar-coverage-ids.ts
|
|
2692
|
+
function children(def, winners) {
|
|
2693
|
+
switch (def.tag) {
|
|
2694
|
+
case "sequence":
|
|
2695
|
+
case "choice":
|
|
2696
|
+
return def.parsers;
|
|
2697
|
+
case "many":
|
|
2698
|
+
case "oneOrMore":
|
|
2699
|
+
case "optional":
|
|
2700
|
+
case "attempt":
|
|
2701
|
+
case "transform":
|
|
2702
|
+
case "trivia":
|
|
2703
|
+
case "token":
|
|
2704
|
+
case "leaf":
|
|
2705
|
+
case "label":
|
|
2706
|
+
case "field":
|
|
2707
|
+
case "grammar":
|
|
2708
|
+
case "not":
|
|
2709
|
+
case "node":
|
|
2710
|
+
case "guard":
|
|
2711
|
+
case "withCtx":
|
|
2712
|
+
case "recover":
|
|
2713
|
+
case "expect":
|
|
2714
|
+
return "parser" in def ? [def.parser] : [];
|
|
2715
|
+
case "sepBy":
|
|
2716
|
+
return [def.parser, def.separator];
|
|
2717
|
+
case "skip":
|
|
2718
|
+
return [def.main, def.skipped];
|
|
2719
|
+
case "scanTo":
|
|
2720
|
+
return [def.sentinel, ...def.skip];
|
|
2721
|
+
case "lazy": {
|
|
2722
|
+
let resolved;
|
|
2723
|
+
try {
|
|
2724
|
+
resolved = def.thunk();
|
|
2725
|
+
} catch {
|
|
2726
|
+
return [];
|
|
2727
|
+
}
|
|
2728
|
+
const name = resolved._ruleName;
|
|
2729
|
+
return name && winners?.[name] ? [winners[name]] : [resolved];
|
|
2730
|
+
}
|
|
2731
|
+
default:
|
|
2732
|
+
return [];
|
|
2733
|
+
}
|
|
2734
|
+
}
|
|
2735
|
+
function buildGrammarPlan(entry, winners) {
|
|
2736
|
+
const definitions = /* @__PURE__ */ new Map();
|
|
2737
|
+
const choices = /* @__PURE__ */ new WeakMap();
|
|
2738
|
+
const attempts = /* @__PURE__ */ new WeakMap();
|
|
2739
|
+
const labels = /* @__PURE__ */ new WeakMap();
|
|
2740
|
+
const rules2 = /* @__PURE__ */ new WeakMap();
|
|
2741
|
+
const winnerNames = /* @__PURE__ */ new Map();
|
|
2742
|
+
if (winners) {
|
|
2743
|
+
for (const [name, winner] of Object.entries(winners)) {
|
|
2744
|
+
winnerNames.set(winner, name);
|
|
2745
|
+
if (winner._def.tag === "lazy") {
|
|
2746
|
+
try {
|
|
2747
|
+
winnerNames.set(winner._def.thunk(), name);
|
|
2748
|
+
} catch {
|
|
2749
|
+
}
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
2752
|
+
}
|
|
2753
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2754
|
+
const visit = (parser2, path2) => {
|
|
2755
|
+
if (seen.has(parser2)) return;
|
|
2756
|
+
seen.add(parser2);
|
|
2757
|
+
const rule = winnerNames.get(parser2) ?? parser2._ruleName;
|
|
2758
|
+
if (rule && (winnerNames.has(parser2) || parser2._def.tag !== "lazy")) {
|
|
2759
|
+
const id = `rule:${rule}`;
|
|
2760
|
+
definitions.set(id, { id, kind: "rule" });
|
|
2761
|
+
rules2.set(parser2, id);
|
|
2762
|
+
}
|
|
2763
|
+
if (parser2._def.tag === "choice") {
|
|
2764
|
+
const ids = parser2._def.parsers.map((_, index) => `choice:${path2}/arm:${index}`);
|
|
2765
|
+
choices.set(parser2, ids);
|
|
2766
|
+
ids.forEach((id) => definitions.set(id, { id, kind: "choice-arm" }));
|
|
2767
|
+
}
|
|
2768
|
+
if (parser2._def.tag === "attempt") attempts.set(parser2, `attempt:${path2}`);
|
|
2769
|
+
if (parser2._def.tag === "label") {
|
|
2770
|
+
const id = `label:${path2}`;
|
|
2771
|
+
labels.set(parser2, [id]);
|
|
2772
|
+
definitions.set(id, { id, kind: "label" });
|
|
2773
|
+
}
|
|
2774
|
+
children(parser2._def, winners).forEach((child, index) => visit(child, `${path2}/${parser2._def.tag}:${index}`));
|
|
2775
|
+
};
|
|
2776
|
+
const roots = Array.isArray(entry) ? entry : [entry];
|
|
2777
|
+
for (const root of roots) {
|
|
2778
|
+
visit(root, winnerNames.get(root) ?? root._ruleName ?? "entry");
|
|
2779
|
+
}
|
|
2780
|
+
return { definitions: [...definitions.values()].sort((a, b) => a.id.localeCompare(b.id)), choices, attempts, labels, rules: rules2 };
|
|
2781
|
+
}
|
|
2539
2782
|
|
|
2540
2783
|
// src/compiler/scannable-run.ts
|
|
2541
2784
|
var BACKSLASH = 92;
|
|
@@ -3585,7 +3828,7 @@ function scanBranchLabeled(shape, kindIndex, mint) {
|
|
|
3585
3828
|
` if (${m.end} > _e) {`,
|
|
3586
3829
|
` if (_cap) {`,
|
|
3587
3830
|
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, ${m.end}, ${kindIndex})`,
|
|
3588
|
-
` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << kindIndex}))) _ctx._cstTriviaLog.push(_e, ${m.end}, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${kindIndex})`,
|
|
3831
|
+
` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << kindIndex}))) _ctx._cstTriviaLog.push(_e, ${m.end}, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${kindIndex})`,
|
|
3589
3832
|
` }`,
|
|
3590
3833
|
` _e = ${m.end}`,
|
|
3591
3834
|
` continue`,
|
|
@@ -3641,7 +3884,7 @@ function analyzeTriviaFastPath(trivia2) {
|
|
|
3641
3884
|
var CAP_RECORD = [
|
|
3642
3885
|
` if (_cap && _e > _pos) {`,
|
|
3643
3886
|
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
|
|
3644
|
-
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
|
|
3887
|
+
` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
|
|
3645
3888
|
` }`
|
|
3646
3889
|
].join("\n");
|
|
3647
3890
|
function composeFastLoop(shapes) {
|
|
@@ -3701,7 +3944,7 @@ function buildLabeledRegexTriviaFnDecl(fnName, spec, reNames) {
|
|
|
3701
3944
|
` const _ce = _e + _m${i}[0].length`,
|
|
3702
3945
|
` if (_cap) {`,
|
|
3703
3946
|
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
|
|
3704
|
-
` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
|
|
3947
|
+
` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
|
|
3705
3948
|
` }`,
|
|
3706
3949
|
` _e = _ce`,
|
|
3707
3950
|
` _matched = true`,
|
|
@@ -3739,7 +3982,7 @@ function buildLabeledRuntimeTriviaFnDecl(fnName, spec, rpStartIndex) {
|
|
|
3739
3982
|
` const _ce = _r${i}.span.end`,
|
|
3740
3983
|
` if (_cap) {`,
|
|
3741
3984
|
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
|
|
3742
|
-
` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
|
|
3985
|
+
` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
|
|
3743
3986
|
` }`,
|
|
3744
3987
|
` _e = _ce`,
|
|
3745
3988
|
` _matched = true`,
|
|
@@ -3928,21 +4171,23 @@ function probeUpdate(ctx, expectedArr, posExpr, constant = true) {
|
|
|
3928
4171
|
}
|
|
3929
4172
|
function failBody(ctx, expected, posExpr) {
|
|
3930
4173
|
const probe = probeUpdate(ctx, `[${expected}]`, posExpr);
|
|
4174
|
+
const trace = ctx.activeCoverageRuleId === void 0 ? "" : `_ctx._grammarTrace?.write({ id: ${JSON.stringify(ctx.activeCoverageRuleId)}, phase: 'failure', offset: ${posExpr} }); `;
|
|
3931
4175
|
if (ctx.failLabel) {
|
|
3932
|
-
if (!ctx.recordFail) return probe ? `{ ${probe}break ${ctx.failLabel} }` : `break ${ctx.failLabel}`;
|
|
3933
|
-
return `{ ${probe}_ctx._fe = ${posExpr}; _ctx._fx = ${hoistExpected(ctx, `[${expected}]`)}; break ${ctx.failLabel} }`;
|
|
4176
|
+
if (!ctx.recordFail) return probe ? `{ ${probe}${trace}break ${ctx.failLabel} }` : trace ? `{ ${trace}break ${ctx.failLabel} }` : `break ${ctx.failLabel}`;
|
|
4177
|
+
return `{ ${probe}_ctx._fe = ${posExpr}; _ctx._fx = ${hoistExpected(ctx, `[${expected}]`)}; ${trace}break ${ctx.failLabel} }`;
|
|
3934
4178
|
}
|
|
3935
|
-
return probe + failReturn(expected, posExpr);
|
|
4179
|
+
return probe + trace + failReturn(expected, posExpr);
|
|
3936
4180
|
}
|
|
3937
4181
|
function failArrBody(ctx, expectedArr, posExpr, constant = true) {
|
|
3938
4182
|
const probe = probeUpdate(ctx, expectedArr, posExpr, constant);
|
|
4183
|
+
const trace = ctx.activeCoverageRuleId === void 0 ? "" : `_ctx._grammarTrace?.write({ id: ${JSON.stringify(ctx.activeCoverageRuleId)}, phase: 'failure', offset: ${posExpr} }); `;
|
|
3939
4184
|
if (ctx.failLabel) {
|
|
3940
|
-
if (!ctx.recordFail) return probe ? `{ ${probe}break ${ctx.failLabel} }` : `break ${ctx.failLabel}`;
|
|
4185
|
+
if (!ctx.recordFail) return probe ? `{ ${probe}${trace}break ${ctx.failLabel} }` : trace ? `{ ${trace}break ${ctx.failLabel} }` : `break ${ctx.failLabel}`;
|
|
3941
4186
|
const fx = constant ? hoistExpected(ctx, expectedArr) : expectedArr;
|
|
3942
|
-
return `{ ${probe}_ctx._fe = ${posExpr}; _ctx._fx = ${fx}; break ${ctx.failLabel} }`;
|
|
4187
|
+
return `{ ${probe}_ctx._fe = ${posExpr}; _ctx._fx = ${fx}; ${trace}break ${ctx.failLabel} }`;
|
|
3943
4188
|
}
|
|
3944
|
-
if (!constant) return `${probe}return { ok: false, expected: [...${expectedArr}], span: { start: ${posExpr}, end: ${posExpr} } }`;
|
|
3945
|
-
return probe + failReturnArr(expectedArr, posExpr);
|
|
4189
|
+
if (!constant) return `${probe}${trace}return { ok: false, expected: [...${expectedArr}], span: { start: ${posExpr}, end: ${posExpr} } }`;
|
|
4190
|
+
return probe + trace + failReturnArr(expectedArr, posExpr);
|
|
3946
4191
|
}
|
|
3947
4192
|
function resultFromRecorded(feExpr = "_ctx._fe", fxExpr = "_ctx._fx") {
|
|
3948
4193
|
return `return { ok: false, expected: [...${fxExpr}], span: { start: ${feExpr}, end: ${feExpr} } }`;
|
|
@@ -3977,7 +4222,7 @@ var NAMED_FN_END = "_pfEnd";
|
|
|
3977
4222
|
function namedFnPrelude() {
|
|
3978
4223
|
return [`const ${NAMED_FN_FAIL} = {}`, `let ${NAMED_FN_END}`];
|
|
3979
4224
|
}
|
|
3980
|
-
function pushNamedFnDecl(ctx, fnName, bodyStmts, valueVar, endVar) {
|
|
4225
|
+
function pushNamedFnDecl(ctx, fnName, bodyStmts, valueVar, endVar, failureRuleId) {
|
|
3981
4226
|
ctx.namedFnDecls.push([
|
|
3982
4227
|
`function ${fnName}(input, _pos, _ctx) {`,
|
|
3983
4228
|
` _pfail: {`,
|
|
@@ -3985,6 +4230,7 @@ function pushNamedFnDecl(ctx, fnName, bodyStmts, valueVar, endVar) {
|
|
|
3985
4230
|
` ${NAMED_FN_END} = ${endVar}`,
|
|
3986
4231
|
` return ${valueVar}`,
|
|
3987
4232
|
` }`,
|
|
4233
|
+
...failureRuleId === void 0 ? [] : [` _ctx._grammarTrace?.write({ id: ${JSON.stringify(failureRuleId)}, phase: 'failure', offset: _ctx._fe ?? _pos })`],
|
|
3988
4234
|
` return ${NAMED_FN_FAIL}`,
|
|
3989
4235
|
`}`
|
|
3990
4236
|
].join("\n"));
|
|
@@ -4090,7 +4336,7 @@ function ensureTriviaFn(ctx) {
|
|
|
4090
4336
|
` }`,
|
|
4091
4337
|
` if (_cap && _e > _pos) {`,
|
|
4092
4338
|
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
|
|
4093
|
-
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
|
|
4339
|
+
` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
|
|
4094
4340
|
` }`,
|
|
4095
4341
|
` return _e`,
|
|
4096
4342
|
`}`
|
|
@@ -4146,6 +4392,7 @@ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
4146
4392
|
case "not":
|
|
4147
4393
|
case "trivia":
|
|
4148
4394
|
case "token":
|
|
4395
|
+
case "leaf":
|
|
4149
4396
|
case "scanTo":
|
|
4150
4397
|
case "unknown":
|
|
4151
4398
|
return false;
|
|
@@ -4157,6 +4404,8 @@ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
4157
4404
|
// nothing committed remains.
|
|
4158
4405
|
case "choice":
|
|
4159
4406
|
return false;
|
|
4407
|
+
case "attempt":
|
|
4408
|
+
return false;
|
|
4160
4409
|
// optional never fails; many/oneOrMore only "fail" with zero captured items.
|
|
4161
4410
|
case "optional":
|
|
4162
4411
|
case "many":
|
|
@@ -4209,6 +4458,7 @@ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
4209
4458
|
case "keywords":
|
|
4210
4459
|
case "node":
|
|
4211
4460
|
case "token":
|
|
4461
|
+
case "leaf":
|
|
4212
4462
|
return true;
|
|
4213
4463
|
case "not":
|
|
4214
4464
|
case "guard":
|
|
@@ -4223,6 +4473,7 @@ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
4223
4473
|
case "many":
|
|
4224
4474
|
case "oneOrMore":
|
|
4225
4475
|
case "optional":
|
|
4476
|
+
case "attempt":
|
|
4226
4477
|
case "transform":
|
|
4227
4478
|
case "label":
|
|
4228
4479
|
case "field":
|
|
@@ -4564,35 +4815,55 @@ function needsFirstSetGuard(p) {
|
|
|
4564
4815
|
const fs2 = p._meta.firstSet;
|
|
4565
4816
|
return fs2.kind !== "any" && !canMatchEmptyAtStart(p);
|
|
4566
4817
|
}
|
|
4567
|
-
function
|
|
4568
|
-
|
|
4818
|
+
function coverageHit(ctx, id, offset = "_pos", end) {
|
|
4819
|
+
return id === void 0 ? [] : [
|
|
4820
|
+
`${ind(ctx)}_ctx._grammarCoverage?.(${JSON.stringify(id)})`,
|
|
4821
|
+
`${ind(ctx)}_ctx._grammarTrace?.write({ id: ${JSON.stringify(id)}, phase: 'selected', offset: ${offset}${end === void 0 ? "" : `, end: ${end}`} })`,
|
|
4822
|
+
`${ind(ctx)}_ctx._grammarTrace?.write({ id: ${JSON.stringify(id)}, phase: 'success', offset: ${offset}${end === void 0 ? "" : `, end: ${end}`} })`
|
|
4823
|
+
];
|
|
4824
|
+
}
|
|
4825
|
+
function coverageAttempt(ctx, id, offset) {
|
|
4826
|
+
return id === void 0 ? [] : [`${ind(ctx)}_ctx._grammarTrace?.write({ id: ${JSON.stringify(id)}, phase: 'attempt', offset: ${offset} })`];
|
|
4827
|
+
}
|
|
4828
|
+
function coverageFailureBacktrack(ctx, id, failureOffset, startOffset) {
|
|
4829
|
+
return id === void 0 ? [] : [
|
|
4830
|
+
`${ind(ctx)}_ctx._grammarTrace?.write({ id: ${JSON.stringify(id)}, phase: 'failure', offset: ${failureOffset} })`,
|
|
4831
|
+
`${ind(ctx)}_ctx._grammarTrace?.write({ id: ${JSON.stringify(id)}, phase: 'backtrack', offset: ${startOffset} })`
|
|
4832
|
+
];
|
|
4833
|
+
}
|
|
4834
|
+
function emitDisjointArm(p, ctx, pos, valV, endV, coverageId) {
|
|
4835
|
+
if (failsAtStart(p) && coverageId === void 0) {
|
|
4569
4836
|
const r = emit(p, ctx, pos);
|
|
4570
|
-
return [...r.stmts, `${ind(ctx)}${valV} = ${r.valueVar}`, `${ind(ctx)}${endV} = ${r.endVar}
|
|
4837
|
+
return [...coverageAttempt(ctx, coverageId, pos), ...r.stmts, `${ind(ctx)}${valV} = ${r.valueVar}`, `${ind(ctx)}${endV} = ${r.endVar}`, ...coverageHit(ctx, coverageId, pos, r.endVar)];
|
|
4571
4838
|
}
|
|
4572
4839
|
const { stmts, okVar, valVar, endVar } = emitFallible(p, ctx, pos);
|
|
4573
4840
|
return [
|
|
4841
|
+
...coverageAttempt(ctx, coverageId, pos),
|
|
4574
4842
|
...stmts,
|
|
4575
|
-
...emitIfFail(ctx, `!${okVar}`, failArrBody(ctx, "_ctx._fx", pos, false)),
|
|
4843
|
+
...emitIfFail(ctx, `!${okVar}`, `${coverageFailureBacktrack(ctx, coverageId, "_ctx._fe", pos).join("; ")}; ${failArrBody(ctx, "_ctx._fx", pos, false)}`),
|
|
4576
4844
|
`${ind(ctx)}${valV} = ${valVar}`,
|
|
4577
|
-
`${ind(ctx)}${endV} = ${endVar}
|
|
4845
|
+
`${ind(ctx)}${endV} = ${endVar}`,
|
|
4846
|
+
...coverageHit(ctx, coverageId, pos, endVar)
|
|
4578
4847
|
];
|
|
4579
4848
|
}
|
|
4580
|
-
function emitDisjointArmGated(def, i, ctx, pos, valV, endV) {
|
|
4849
|
+
function emitDisjointArmGated(def, i, ctx, pos, valV, endV, coverageId) {
|
|
4581
4850
|
const p = def.parsers[i];
|
|
4582
4851
|
const gate = def.gates[i];
|
|
4583
|
-
if (!gate) return emitDisjointArm(p, ctx, pos, valV, endV);
|
|
4852
|
+
if (!gate) return emitDisjointArm(p, ctx, pos, valV, endV, coverageId);
|
|
4584
4853
|
const gateIdx = ctx.mapFns.length;
|
|
4585
4854
|
ctx.mapFns.push(gate);
|
|
4586
4855
|
ctx.mapFnSrcs.push(def.gateSrcs?.[i] ?? null);
|
|
4587
4856
|
const gateCond = `${mfRef(ctx)}[${gateIdx}](_ctx.state)`;
|
|
4588
4857
|
const stmts = [`${ind(ctx)}if (${gateCond}) {`];
|
|
4589
4858
|
ctx.indent++;
|
|
4590
|
-
stmts.push(...emitDisjointArm(p, ctx, pos, valV, endV));
|
|
4859
|
+
stmts.push(...emitDisjointArm(p, ctx, pos, valV, endV, coverageId));
|
|
4591
4860
|
ctx.indent--;
|
|
4592
4861
|
stmts.push(`${ind(ctx)}} else { ${failArrBody(ctx, deriveExpectedArr([p]), pos)} }`);
|
|
4593
4862
|
return stmts;
|
|
4594
4863
|
}
|
|
4595
|
-
function emitChoice(def, ctx, pos) {
|
|
4864
|
+
function emitChoice(parser2, def, ctx, pos) {
|
|
4865
|
+
const coverageIds = ctx.coverage?.plan.choices.get(parser2);
|
|
4866
|
+
const coverageBase = coverageIds?.[0]?.slice(0, -1);
|
|
4596
4867
|
const allExpected = deriveExpectedArr(def.parsers);
|
|
4597
4868
|
if (def.disjoint) {
|
|
4598
4869
|
const codeV = v(ctx, "_code");
|
|
@@ -4611,7 +4882,7 @@ function emitChoice(def, ctx, pos) {
|
|
|
4611
4882
|
stmts.push(`${ind(ctx)}{`);
|
|
4612
4883
|
ctx.indent++;
|
|
4613
4884
|
stmts.push(
|
|
4614
|
-
...emitDisjointArmGated(def, i, ctx, pos, valV, endV),
|
|
4885
|
+
...emitDisjointArmGated(def, i, ctx, pos, valV, endV, coverageIds?.[i]),
|
|
4615
4886
|
`${ind(ctx)}break`
|
|
4616
4887
|
);
|
|
4617
4888
|
ctx.indent--;
|
|
@@ -4630,16 +4901,16 @@ function emitChoice(def, ctx, pos) {
|
|
|
4630
4901
|
first = false;
|
|
4631
4902
|
stmts.push(`${ind(ctx)}${kw} (${cond}) {`);
|
|
4632
4903
|
ctx.indent++;
|
|
4633
|
-
stmts.push(...emitDisjointArmGated(def, i, ctx, pos, valV, endV));
|
|
4904
|
+
stmts.push(...emitDisjointArmGated(def, i, ctx, pos, valV, endV, coverageIds?.[i]));
|
|
4634
4905
|
ctx.indent--;
|
|
4635
4906
|
stmts.push(`${ind(ctx)}}`);
|
|
4636
4907
|
}
|
|
4637
4908
|
stmts.push(...emitElseFail(ctx, failArrBody(ctx, allExpected, pos)));
|
|
4638
4909
|
return { stmts, valueVar: valV, endVar: endV };
|
|
4639
4910
|
}
|
|
4640
|
-
return emitNonDisjoint(def, def.strategy, allExpected, ctx, pos);
|
|
4911
|
+
return emitNonDisjoint(def, def.strategy, allExpected, ctx, pos, coverageBase);
|
|
4641
4912
|
}
|
|
4642
|
-
function emitGreedyClassify(def, superIndex, ctx, pos) {
|
|
4913
|
+
function emitGreedyClassify(def, superIndex, ctx, pos, coverageBase) {
|
|
4643
4914
|
const superParser = def.parsers[superIndex];
|
|
4644
4915
|
const regexDef = getCoreRegexDef(superParser);
|
|
4645
4916
|
const cleanFlags = "y" + regexDef.flags.replace(/[gy]/g, "");
|
|
@@ -4655,10 +4926,12 @@ function emitGreedyClassify(def, superIndex, ctx, pos) {
|
|
|
4655
4926
|
const endV = v(ctx, "_ge");
|
|
4656
4927
|
const valV = v(ctx, "_gcv");
|
|
4657
4928
|
const regexExpected = JSON.stringify(deriveExpected(superParser));
|
|
4929
|
+
const superCoverageId = coverageBase === void 0 ? void 0 : `${coverageBase}${superIndex}`;
|
|
4658
4930
|
const stmts = [
|
|
4931
|
+
...coverageAttempt(ctx, superCoverageId, pos),
|
|
4659
4932
|
`${ind(ctx)}${reVar}.lastIndex = ${pos}`,
|
|
4660
4933
|
`${ind(ctx)}const ${matchV} = ${reVar}.exec(input)`,
|
|
4661
|
-
...emitIfFail(ctx, `${matchV} === null`, failArrBody(ctx, regexExpected, pos)),
|
|
4934
|
+
...emitIfFail(ctx, `${matchV} === null`, `${coverageFailureBacktrack(ctx, superCoverageId, pos, pos).join("; ")}; ${failArrBody(ctx, regexExpected, pos)}`),
|
|
4662
4935
|
`${ind(ctx)}const ${wordV} = ${matchV}[0]`,
|
|
4663
4936
|
`${ind(ctx)}const ${endV} = ${pos} + ${wordV}.length`,
|
|
4664
4937
|
`${ind(ctx)}let ${valV}`
|
|
@@ -4674,8 +4947,9 @@ function emitGreedyClassify(def, superIndex, ctx, pos) {
|
|
|
4674
4947
|
stmts.push(`${ind(ctx)}${kw} (${wordV} === ${JSON.stringify(litVal)}) {`);
|
|
4675
4948
|
ctx.indent++;
|
|
4676
4949
|
const tR = emitTransformChain(p, JSON.stringify(litVal), endV, pos, ctx);
|
|
4950
|
+
stmts.push(...coverageFailureBacktrack(ctx, superCoverageId, pos, pos));
|
|
4677
4951
|
stmts.push(...emitLeafCapture(ctx, JSON.stringify(litVal), pos, endV));
|
|
4678
|
-
stmts.push(...tR.stmts, `${ind(ctx)}${valV} = ${tR.valueVar}
|
|
4952
|
+
stmts.push(...tR.stmts, `${ind(ctx)}${valV} = ${tR.valueVar}`, ...coverageHit(ctx, coverageBase === void 0 ? void 0 : `${coverageBase}${i}`, pos, endV));
|
|
4679
4953
|
ctx.indent--;
|
|
4680
4954
|
stmts.push(`${ind(ctx)}}`);
|
|
4681
4955
|
}
|
|
@@ -4683,12 +4957,12 @@ function emitGreedyClassify(def, superIndex, ctx, pos) {
|
|
|
4683
4957
|
const regexKw = first ? "if" : "else";
|
|
4684
4958
|
stmts.push(`${ind(ctx)}${regexKw} {`);
|
|
4685
4959
|
ctx.indent++;
|
|
4686
|
-
stmts.push(...emitLeafCapture(ctx, wordV, pos, endV), ...rR.stmts, `${ind(ctx)}${valV} = ${rR.valueVar}
|
|
4960
|
+
stmts.push(...emitLeafCapture(ctx, wordV, pos, endV), ...rR.stmts, `${ind(ctx)}${valV} = ${rR.valueVar}`, ...coverageHit(ctx, coverageBase === void 0 ? void 0 : `${coverageBase}${superIndex}`, pos, endV));
|
|
4687
4961
|
ctx.indent--;
|
|
4688
4962
|
stmts.push(`${ind(ctx)}}`);
|
|
4689
4963
|
return { stmts, valueVar: valV, endVar: endV };
|
|
4690
4964
|
}
|
|
4691
|
-
function emitLiteralsLongestFirst(def, sortedIndices, allExpected, ctx, pos) {
|
|
4965
|
+
function emitLiteralsLongestFirst(def, sortedIndices, allExpected, ctx, pos, coverageBase) {
|
|
4692
4966
|
const valV = v(ctx, "_llv");
|
|
4693
4967
|
const endV = v(ctx, "_lle");
|
|
4694
4968
|
const stmts = [`${ind(ctx)}let ${valV}, ${endV} = ${pos}`];
|
|
@@ -4705,10 +4979,12 @@ function emitLiteralsLongestFirst(def, sortedIndices, allExpected, ctx, pos) {
|
|
|
4705
4979
|
ctx.indent++;
|
|
4706
4980
|
const tR = emitTransformChain(p, JSON.stringify(litVal), litEnd, pos, ctx);
|
|
4707
4981
|
stmts.push(
|
|
4982
|
+
...coverageAttempt(ctx, coverageBase === void 0 ? void 0 : `${coverageBase}${idx}`, pos),
|
|
4708
4983
|
...emitLeafCapture(ctx, JSON.stringify(litVal), pos, litEnd),
|
|
4709
4984
|
...tR.stmts,
|
|
4710
4985
|
`${ind(ctx)}${valV} = ${tR.valueVar}`,
|
|
4711
|
-
`${ind(ctx)}${endV} = ${litEnd}
|
|
4986
|
+
`${ind(ctx)}${endV} = ${litEnd}`,
|
|
4987
|
+
...coverageHit(ctx, coverageBase === void 0 ? void 0 : `${coverageBase}${idx}`, pos, litEnd)
|
|
4712
4988
|
);
|
|
4713
4989
|
ctx.indent--;
|
|
4714
4990
|
stmts.push(`${ind(ctx)}}`);
|
|
@@ -4716,16 +4992,18 @@ function emitLiteralsLongestFirst(def, sortedIndices, allExpected, ctx, pos) {
|
|
|
4716
4992
|
stmts.push(...emitElseFail(ctx, failArrBody(ctx, allExpected, pos)));
|
|
4717
4993
|
return { stmts, valueVar: valV, endVar: endV };
|
|
4718
4994
|
}
|
|
4719
|
-
function emitFirstMatch(def, ctx, pos) {
|
|
4995
|
+
function emitFirstMatch(def, ctx, pos, coverageBase) {
|
|
4720
4996
|
const resValV = v(ctx, "_crv");
|
|
4721
4997
|
const resEndV = v(ctx, "_cre");
|
|
4722
4998
|
const resOkV = v(ctx, "_crok");
|
|
4723
4999
|
const codeV = v(ctx, "_chcode");
|
|
4724
5000
|
const slots = def.parsers.map(() => v(ctx, "_cfx"));
|
|
5001
|
+
const autoRejectedV = coverageBase === void 0 ? void 0 : v(ctx, "_carej");
|
|
4725
5002
|
const ind0 = ind(ctx);
|
|
4726
5003
|
const stmts = [
|
|
4727
5004
|
`${ind0}let ${resValV}, ${resEndV} = ${pos}, ${resOkV} = false`,
|
|
4728
5005
|
`${ind0}let ${slots.join(", ")}`,
|
|
5006
|
+
...autoRejectedV === void 0 ? [] : [`${ind0}const ${autoRejectedV} = []`],
|
|
4729
5007
|
`${ind0}const ${codeV} = ${pos} < input.length ? (input.codePointAt(${pos}) ?? -1) : -1`
|
|
4730
5008
|
];
|
|
4731
5009
|
for (let i = 0; i < def.parsers.length; i++) {
|
|
@@ -4761,6 +5039,7 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
4761
5039
|
stmts.push(`${ind0}if (${skipCond}) {`);
|
|
4762
5040
|
if (fsGuard) stmts.push(`${ind(ctx)}if (${fsGuard}) {`);
|
|
4763
5041
|
ctx.indent += fsGuard ? 2 : 1;
|
|
5042
|
+
if (coverageBase !== void 0) stmts.push(`${ind(ctx)}_ctx._grammarTrace?.write({ id: ${JSON.stringify(`${coverageBase}${i}`)}, phase: 'attempt', offset: ${pos} })`);
|
|
4764
5043
|
if (markLeaves) {
|
|
4765
5044
|
stmts.push(
|
|
4766
5045
|
`${ind(ctx)}const ${markLeaves} = _ctx._cstLeaves?.length ?? 0`,
|
|
@@ -4783,13 +5062,21 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
4783
5062
|
stmts.push(`${ind(ctx)} ${resValV} = ${valVar}`);
|
|
4784
5063
|
stmts.push(`${ind(ctx)} ${resEndV} = ${endVar}`);
|
|
4785
5064
|
stmts.push(`${ind(ctx)} ${resOkV} = true`);
|
|
5065
|
+
if (autoRejectedV !== void 0) {
|
|
5066
|
+
stmts.push(`${ind(ctx)} for (const _rejectedId of ${autoRejectedV}) { _ctx._grammarTrace?.write({ id: _rejectedId, phase: 'failure', offset: ${pos} }); _ctx._grammarTrace?.write({ id: _rejectedId, phase: 'backtrack', offset: ${pos} }) }`);
|
|
5067
|
+
}
|
|
5068
|
+
stmts.push(...coverageHit(ctx, coverageBase === void 0 ? void 0 : `${coverageBase}${i}`, pos, endVar));
|
|
4786
5069
|
stmts.push(`${ind(ctx)} }`);
|
|
5070
|
+
if (autoRejectedV !== void 0) {
|
|
5071
|
+
stmts.push(`${ind(ctx)} else { ${autoRejectedV}.push(${JSON.stringify(`${coverageBase}${i}`)}) }`);
|
|
5072
|
+
}
|
|
4787
5073
|
stmts.push(`${ind(ctx)}}`);
|
|
4788
|
-
stmts.push(`${ind(ctx)}else { ${slots[i]} = ${failSlot} }`);
|
|
5074
|
+
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} });`} }`);
|
|
4789
5075
|
if (rollback) stmts.push(`${ind(ctx)}if (!${resOkV}) { ${rollback} }`);
|
|
4790
5076
|
} else {
|
|
4791
|
-
|
|
4792
|
-
stmts.push(`${ind(ctx)}
|
|
5077
|
+
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} }) }`;
|
|
5078
|
+
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} })`} }`);
|
|
5079
|
+
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} })`} }`);
|
|
4793
5080
|
}
|
|
4794
5081
|
ctx.indent -= fsGuard ? 2 : 1;
|
|
4795
5082
|
if (fsGuard) stmts.push(`${ind(ctx)}} else { ${slots[i]} = ${staticFx} }`);
|
|
@@ -4799,12 +5086,12 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
4799
5086
|
stmts.push(...emitIfFail(ctx, `!${resOkV}`, failArrBody(ctx, concatExpr, pos, false)));
|
|
4800
5087
|
return { stmts, valueVar: resValV, endVar: resEndV };
|
|
4801
5088
|
}
|
|
4802
|
-
function emitNonDisjoint(def, strategy, allExpected, ctx, pos) {
|
|
5089
|
+
function emitNonDisjoint(def, strategy, allExpected, ctx, pos, coverageBase) {
|
|
4803
5090
|
if (strategy.tag === "greedyClassify")
|
|
4804
|
-
return emitGreedyClassify(def, strategy.superIndex, ctx, pos);
|
|
5091
|
+
return emitGreedyClassify(def, strategy.superIndex, ctx, pos, coverageBase);
|
|
4805
5092
|
if (strategy.tag === "literalsLongestFirst")
|
|
4806
|
-
return emitLiteralsLongestFirst(def, strategy.sortedIndices, allExpected, ctx, pos);
|
|
4807
|
-
return emitFirstMatch(def, ctx, pos);
|
|
5093
|
+
return emitLiteralsLongestFirst(def, strategy.sortedIndices, allExpected, ctx, pos, coverageBase);
|
|
5094
|
+
return emitFirstMatch(def, ctx, pos, coverageBase);
|
|
4808
5095
|
}
|
|
4809
5096
|
function pushMapFn(ctx, fn, src) {
|
|
4810
5097
|
if (src !== null && ctx.mapFns.length === ctx.mapFnSrcs.length) {
|
|
@@ -4922,6 +5209,27 @@ function emitOptional(def, ctx, pos) {
|
|
|
4922
5209
|
];
|
|
4923
5210
|
return { stmts, valueVar: valV, endVar: endV };
|
|
4924
5211
|
}
|
|
5212
|
+
function emitAttempt(p, def, ctx, pos) {
|
|
5213
|
+
const inner = emitFallible(def.parser, ctx, pos);
|
|
5214
|
+
const leaves = v(ctx, "_atl");
|
|
5215
|
+
const raw = v(ctx, "_atr");
|
|
5216
|
+
const trivia2 = v(ctx, "_att");
|
|
5217
|
+
const log = v(ctx, "_atg");
|
|
5218
|
+
const fields = v(ctx, "_atf");
|
|
5219
|
+
const errors = v(ctx, "_ate");
|
|
5220
|
+
const rollback = `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${leaves}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${raw}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${trivia2}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${log}; if (_ctx._fields) _ctx._fields.length = ${fields}; if (_ctx._errors) _ctx._errors.length = ${errors}`;
|
|
5221
|
+
const traceId = ctx.coverage?.plan.attempts.get(p);
|
|
5222
|
+
const traceRollback = traceId === void 0 ? "" : ` _ctx._grammarTrace?.write({ id: ${JSON.stringify(traceId)}, phase: 'rollback', offset: ${pos} });`;
|
|
5223
|
+
return {
|
|
5224
|
+
stmts: [
|
|
5225
|
+
`${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`,
|
|
5226
|
+
...inner.stmts,
|
|
5227
|
+
...emitIfFail(ctx, `!${inner.okVar}`, `{ ${rollback};${traceRollback} _ctx._fe = ${pos}; ${propagateFailBody(ctx)} }`)
|
|
5228
|
+
],
|
|
5229
|
+
valueVar: inner.valVar,
|
|
5230
|
+
endVar: inner.endVar
|
|
5231
|
+
};
|
|
5232
|
+
}
|
|
4925
5233
|
function emitSepBy(_p, def, ctx, pos) {
|
|
4926
5234
|
const arrV = v(ctx, "_arr");
|
|
4927
5235
|
const curV = v(ctx, "_cur");
|
|
@@ -5167,11 +5475,11 @@ function tokenNullableRegex(def) {
|
|
|
5167
5475
|
}
|
|
5168
5476
|
if (inner.tag === "sepBy") {
|
|
5169
5477
|
const item = tokenSequenceSource(inner.parser);
|
|
5170
|
-
const
|
|
5171
|
-
if (!item || !
|
|
5172
|
-
const combined = combineTokenRegexSources([item,
|
|
5478
|
+
const sep2 = tokenSequenceSource(inner.separator);
|
|
5479
|
+
if (!item || !sep2) return null;
|
|
5480
|
+
const combined = combineTokenRegexSources([item, sep2]);
|
|
5173
5481
|
if (!combined) return null;
|
|
5174
|
-
return { tag: "regex", source: `(?:${item.source}(?:${
|
|
5482
|
+
return { tag: "regex", source: `(?:${item.source}(?:${sep2.source}${item.source})*)?`, flags: combined.flags };
|
|
5175
5483
|
}
|
|
5176
5484
|
return null;
|
|
5177
5485
|
}
|
|
@@ -5212,6 +5520,36 @@ function emitToken(def, ctx, pos) {
|
|
|
5212
5520
|
endVar: inner.endVar
|
|
5213
5521
|
};
|
|
5214
5522
|
}
|
|
5523
|
+
function emitLeaf(def, ctx, pos) {
|
|
5524
|
+
const inner = emitFallible(def.parser, ctx, pos);
|
|
5525
|
+
const i = ind(ctx);
|
|
5526
|
+
const sc = v(ctx, "_leafCh");
|
|
5527
|
+
const sl = v(ctx, "_leafLv");
|
|
5528
|
+
const sr = v(ctx, "_leafRaw");
|
|
5529
|
+
const stl = v(ctx, "_leafTl");
|
|
5530
|
+
const sol = v(ctx, "_leafLog");
|
|
5531
|
+
const sb = v(ctx, "_leafBuf");
|
|
5532
|
+
const rawV = v(ctx, "_leafRawValue");
|
|
5533
|
+
const valV = v(ctx, "_leaf");
|
|
5534
|
+
const fnIdx = pushMapFn(ctx, def.fn, def.fnSrc ?? null);
|
|
5535
|
+
return {
|
|
5536
|
+
stmts: [
|
|
5537
|
+
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${stl} = _ctx._cstTriviaLog, ${sol} = _ctx._triviaLog, ${sb} = _ctx._cstBuf`,
|
|
5538
|
+
`${i}_ctx._cstChildren = undefined; _ctx._cstLeaves = undefined; _ctx._cstRawChildren = undefined; _ctx._cstTriviaLog = undefined; _ctx._triviaLog = undefined; _ctx._cstBuf = undefined`,
|
|
5539
|
+
`${i}try {`,
|
|
5540
|
+
...reindentStmts(inner.stmts, ctx.indent + 1).map((stmt) => stmt.replace(/^(\s*)(?:const|let)\s+/, "$1var ")),
|
|
5541
|
+
`${i}} finally {`,
|
|
5542
|
+
`${i} _ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx._cstTriviaLog = ${stl}; _ctx._triviaLog = ${sol}; _ctx._cstBuf = ${sb}`,
|
|
5543
|
+
`${i}}`,
|
|
5544
|
+
...emitIfFail(ctx, `!${inner.okVar}`, propagateFailBody(ctx)),
|
|
5545
|
+
`${i}const ${rawV} = ${inner.valVar}`,
|
|
5546
|
+
`${i}const ${valV} = ${mfRef(ctx)}[${fnIdx}](${rawV}, { start: ${pos}, end: ${inner.endVar} })`,
|
|
5547
|
+
...emitLeafCapture(ctx, valV, pos, inner.endVar)
|
|
5548
|
+
],
|
|
5549
|
+
valueVar: valV,
|
|
5550
|
+
endVar: inner.endVar
|
|
5551
|
+
};
|
|
5552
|
+
}
|
|
5215
5553
|
function emitNode(def, ctx, pos) {
|
|
5216
5554
|
if (def.type === void 0) {
|
|
5217
5555
|
throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
|
|
@@ -5225,17 +5563,20 @@ function emitNode(def, ctx, pos) {
|
|
|
5225
5563
|
ctx.buildSrcs.push(def.buildSrc ?? null);
|
|
5226
5564
|
}
|
|
5227
5565
|
const i = ind(ctx);
|
|
5228
|
-
const capturesTrivia = mkType !== null || !structural && buildReadsTrivia(def);
|
|
5566
|
+
const capturesTrivia = mkType !== null || def.captureTrivia === true || def.trailingTrivia === true || !structural && buildReadsTrivia(def);
|
|
5229
5567
|
const clonesState = !structural && buildReadsState(def);
|
|
5568
|
+
const capturesChildren = !structural && (mkType !== null || def.unwrap || def.collapse || buildReadsChildren(def));
|
|
5569
|
+
const capturesRaw = !structural && (mkType !== null || buildReadsRaw(def));
|
|
5230
5570
|
const hasFields = parserHasOwnFields(def.parser);
|
|
5231
5571
|
const capturesFields = hasFields && !structural && buildReadsFields(def);
|
|
5572
|
+
const innerEnablesTriviaCapture = parserEnablesTriviaCapture(def.parser);
|
|
5232
5573
|
const chV = v(ctx, "_ch");
|
|
5233
5574
|
const rawV = v(ctx, "_raw");
|
|
5234
|
-
const capTLv = structural ? v(ctx, "_ctl") : null;
|
|
5575
|
+
const capTLv = structural || capturesTrivia ? v(ctx, "_ctl") : null;
|
|
5235
5576
|
const capSTv = structural ? v(ctx, "_cst") : null;
|
|
5236
5577
|
const capFv = structural && hasFields ? v(ctx, "_cf") : null;
|
|
5237
5578
|
const tlV = capturesTrivia || structural ? v(ctx, "_tl") : "_EMPTY_TL";
|
|
5238
|
-
if (!capturesTrivia) ctx.needsEmptyTl = true;
|
|
5579
|
+
if (!capturesTrivia || structural) ctx.needsEmptyTl = true;
|
|
5239
5580
|
const sc = v(ctx, "_sc"), sl = v(ctx, "_sl"), sr = v(ctx, "_sr"), st = v(ctx, "_st"), stl = v(ctx, "_stl");
|
|
5240
5581
|
const smk = structural ? v(ctx, "_smk") : null;
|
|
5241
5582
|
if (structural) ctx.needsHostReads = true;
|
|
@@ -5244,16 +5585,21 @@ function emitNode(def, ctx, pos) {
|
|
|
5244
5585
|
const profHoist = `${i}const ${pmV} = _ctx._pmProfile, ${recV} = ${pmV}?.phase === 'recognizer', ${capV} = ${pmV}?.phase === 'capture'`;
|
|
5245
5586
|
const profileRecognizer = recV;
|
|
5246
5587
|
const profileCapture = capV;
|
|
5247
|
-
const
|
|
5248
|
-
|
|
5249
|
-
const
|
|
5588
|
+
const directCstV = !structural && (!capturesChildren || !capturesRaw) ? v(ctx, "_dcst") : null;
|
|
5589
|
+
const directCstGate = directCstV === null ? "false" : `${profileCapture} || _ctx.build?._parsemanCstOutput === true`;
|
|
5590
|
+
const structuralCapturesTrivia = structural && (def.captureTrivia === true || def.trailingTrivia === true);
|
|
5591
|
+
const allocStmt = structural ? `${i}const ${capTLv} = !(${profileRecognizer}) && (${profileCapture} || ${structuralCapturesTrivia ? "true" : hostTriviaGate}), ${capSTv} = !(${profileRecognizer} || ${profileCapture}) && (_ctx._pmCapST ??= (_ctx.build === undefined || _hostReads(_ctx.build, 6)))${capFv ? `, ${capFv} = !(${profileRecognizer}) && (${profileCapture} || (_ctx.build !== undefined && _hostReads(_ctx.build, 2)))` : ""}
|
|
5592
|
+
${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRecognizer} ? undefined : [], ${tlV} = ${profileRecognizer} ? undefined : ${innerEnablesTriviaCapture ? "[]" : `${capTLv} ? [] : _EMPTY_TL`}` : capturesTrivia ? `${directCstV ? `${i}const ${directCstV} = ${directCstGate}
|
|
5593
|
+
` : ""}${i}const ${capTLv} = !(${profileRecognizer}), ${chV} = ${profileRecognizer} ? undefined : ${capturesChildren ? "[]" : `${directCstV} ? [] : undefined`}, ${rawV} = ${profileRecognizer} ? undefined : ${capturesRaw ? "[]" : `${directCstV} ? [] : undefined`}, ${tlV} = ${profileRecognizer} ? undefined : []` : `${directCstV ? `${i}const ${directCstV} = ${directCstGate}
|
|
5594
|
+
` : ""}${i}const ${chV} = ${profileRecognizer} ? undefined : ${capturesChildren ? "[]" : `${directCstV} ? [] : undefined`}, ${rawV} = ${profileRecognizer} ? undefined : ${capturesRaw ? "[]" : `${directCstV} ? [] : undefined`}`;
|
|
5595
|
+
const innerTl = structural || capturesTrivia ? structural && !innerEnablesTriviaCapture ? `${capTLv} ? ${tlV} : undefined` : tlV : "undefined";
|
|
5250
5596
|
const fieldsOn = structural ? capFv ?? "false" : `${profileRecognizer} ? false : ${capturesFields ? "true" : "false"}`;
|
|
5251
5597
|
const sf = hasFields ? v(ctx, "_sf") : null;
|
|
5252
5598
|
const fArr = hasFields ? v(ctx, "_fa") : null;
|
|
5253
5599
|
const fObj = hasFields ? v(ctx, "_fields") : "undefined";
|
|
5254
|
-
const needsTriviaFrame = parserHasTriviaSite(def.parser);
|
|
5600
|
+
const needsTriviaFrame = def.trailingTrivia === true || parserHasTriviaSite(def.parser);
|
|
5255
5601
|
const saveTrivia = needsTriviaFrame ? `, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog${smk ? `, ${smk} = _ctx._triviaCaptureMask` : ""}` : "";
|
|
5256
|
-
const installTrivia = needsTriviaFrame ? `; _ctx.captureTrivia =
|
|
5602
|
+
const installTrivia = needsTriviaFrame ? `; _ctx.captureTrivia = ${capTLv ?? "false"}; _ctx._cstTriviaLog = ${innerTl}${smk ? `; _ctx._triviaCaptureMask = ${capTLv} && _ctx.build !== undefined && _ctx.build._parsemanTriviaKinds !== undefined ? _ctx.build._parsemanTriviaKinds(${JSON.stringify(def.type)}) : ${smk}` : ""}` : "";
|
|
5257
5603
|
const restoreTrivia = needsTriviaFrame ? `; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}${smk ? `; _ctx._triviaCaptureMask = ${smk}` : ""}` : "";
|
|
5258
5604
|
const stmts = [
|
|
5259
5605
|
profHoist,
|
|
@@ -5261,8 +5607,13 @@ ${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRec
|
|
|
5261
5607
|
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren${saveTrivia}${sf ? `, ${sf} = _ctx._fields` : ""}`,
|
|
5262
5608
|
`${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}${installTrivia}${sf ? `; _ctx._fields = ${fieldsOn} ? [] : undefined` : ""}`
|
|
5263
5609
|
];
|
|
5264
|
-
const { stmts: innerStmts, okVar, endVar } = emitFallible(def.parser, ctx, pos);
|
|
5610
|
+
const { stmts: innerStmts, okVar, endVar: innerEndVar } = emitFallible(def.parser, ctx, pos);
|
|
5611
|
+
const endVar = def.trailingTrivia === true && ctx.activeTrivia ? v(ctx, "_trailend") : innerEndVar;
|
|
5265
5612
|
stmts.push(...innerStmts);
|
|
5613
|
+
if (def.trailingTrivia === true && ctx.activeTrivia) {
|
|
5614
|
+
const triviaFn = ensureTriviaFn(ctx);
|
|
5615
|
+
stmts.push(`${i}const ${endVar} = ${okVar} ? ${triviaFn}(input, ${innerEndVar}, _ctx, 1) : ${innerEndVar}`);
|
|
5616
|
+
}
|
|
5266
5617
|
if (sf && fArr) {
|
|
5267
5618
|
stmts.push(`${i}const ${fArr} = _ctx._fields`);
|
|
5268
5619
|
}
|
|
@@ -5302,8 +5653,9 @@ ${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRec
|
|
|
5302
5653
|
}
|
|
5303
5654
|
const ndV = v(ctx, "_nd");
|
|
5304
5655
|
const buildExpr = structural ? `{ _tag: 'node', type: ${JSON.stringify(def.type)}, span: { start: ${pos}, end: ${endVar} }, state: ${stV} ?? null, children: ${chV} }` : mkType ? emitInlineMkNodeExpr(mkType, chV, rawV, pos, endVar, tlV) : `${buildRef(ctx)}[${buildIdx}](${chV}, ${fObj}, { start: ${pos}, end: ${endVar} }, ${rawV}, ${tlV}, ${stV})`;
|
|
5305
|
-
const
|
|
5306
|
-
const
|
|
5656
|
+
const hostBuildExpr = `_ctx._pmProfile?.phase === 'host' && _ctx._pmProfile.hostCalls++, _ctx.build(${JSON.stringify(def.type)}, ${chV}, ${fObj}, { start: ${pos}, end: ${endVar} }, ${rawV}, ${tlV}, ${stV})`;
|
|
5657
|
+
const ndExpr = structural ? `_ctx.build !== undefined ? (${hostBuildExpr}) : (${buildExpr})` : `_ctx.build?._parsemanCstOutput === true ? (${hostBuildExpr}) : (${buildExpr})`;
|
|
5658
|
+
const hostCollapseExpr = structural ? `_ctx.build !== undefined && _ctx.build._parsemanCstCollapse !== undefined && ${chV}.length === 1 && ${rawV}.length === 1 && _ctx.build._parsemanCstCollapse(${JSON.stringify(def.type)}, ${chV}[0], ${chV}, ${rawV}) ? ${chV}[0] : (${ndExpr})` : ndExpr;
|
|
5307
5659
|
const unwrapExpr = `${chV}.length === 1 ? (${chV}[0] !== null && typeof ${chV}[0] === 'object' && ${chV}[0]._tag === 'leaf' ? ${chV}[0].value : ${chV}[0]) : (${ndExpr})`;
|
|
5308
5660
|
const collapseExpr = `${chV}.length === 1 ? ${chV}[0] : (${ndExpr})`;
|
|
5309
5661
|
const finalExpr = def.unwrap ? unwrapExpr : def.collapse ? collapseExpr : hostCollapseExpr;
|
|
@@ -5311,7 +5663,7 @@ ${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRec
|
|
|
5311
5663
|
`${i}const ${ndV} = (${profileRecognizer} || ${profileCapture}) ? undefined : (${finalExpr})`,
|
|
5312
5664
|
`${i}if (!(${profileRecognizer})) {`,
|
|
5313
5665
|
`${i} if (${sc}) ${sc}.push(${ndV})`,
|
|
5314
|
-
`${i} if (${sr}) ${sr}.push((typeof ${ndV} === 'object' && ${ndV} !== null && (${ndV}._tag === 'node' || ${ndV}._tag === 'leaf' || ${ndV}._tag === 'parseError')) ? ${ndV} : { _tag: 'leaf', value: typeof ${ndV} === 'string' ? ${ndV} : '', span: { start: ${pos}, end: ${endVar} } })`,
|
|
5666
|
+
`${i} if (${sr}) ${sr}.push((typeof ${ndV} === 'object' && ${ndV} !== null && (${ndV}._tag === 'node' || ${ndV}._tag === 'leaf' || ${ndV}._tag === 'parseError')) ? ${ndV} : { _tag: 'leaf', value: typeof ${ndV} === 'string' ? ${ndV} : (typeof ${ndV} === 'object' && ${ndV} !== null ? input.slice(${pos}, ${endVar}) : ''), span: { start: ${pos}, end: ${endVar} } })`,
|
|
5315
5667
|
`${i}}`
|
|
5316
5668
|
);
|
|
5317
5669
|
return { stmts, valueVar: ndV, endVar };
|
|
@@ -5356,14 +5708,23 @@ function emitLazy(p, def, ctx, pos) {
|
|
|
5356
5708
|
const savedIndent = ctx.indent;
|
|
5357
5709
|
const savedFailLabel = ctx.failLabel;
|
|
5358
5710
|
const savedRecord = ctx.recordFail;
|
|
5711
|
+
const failureRuleId = p === ctx.coverage?.entry ? void 0 : ctx.coverage?.plan.rules.get(p) ?? ctx.coverage?.plan.rules.get(resolved);
|
|
5712
|
+
const savedActiveRule = ctx.activeCoverageRuleId;
|
|
5713
|
+
const savedSuppressFailure = ctx.suppressCoverageFailure;
|
|
5359
5714
|
ctx.indent = 1;
|
|
5360
5715
|
ctx.failLabel = "_pfail";
|
|
5361
5716
|
ctx.recordFail = true;
|
|
5717
|
+
if (failureRuleId !== void 0) {
|
|
5718
|
+
ctx.activeCoverageRuleId = void 0;
|
|
5719
|
+
ctx.suppressCoverageFailure = true;
|
|
5720
|
+
}
|
|
5362
5721
|
const r = emit(resolved, ctx, "_pos");
|
|
5363
5722
|
ctx.indent = savedIndent;
|
|
5364
5723
|
ctx.failLabel = savedFailLabel;
|
|
5365
5724
|
ctx.recordFail = savedRecord;
|
|
5366
|
-
|
|
5725
|
+
ctx.activeCoverageRuleId = savedActiveRule;
|
|
5726
|
+
ctx.suppressCoverageFailure = savedSuppressFailure;
|
|
5727
|
+
pushNamedFnDecl(ctx, fnName2, r.stmts, r.valueVar, r.endVar, failureRuleId);
|
|
5367
5728
|
}
|
|
5368
5729
|
const fnName = ctx.namedParsers.get(p);
|
|
5369
5730
|
return emitNamedFnCall(ctx, fnName, pos);
|
|
@@ -5414,6 +5775,30 @@ function emitExpect(def, ctx, pos) {
|
|
|
5414
5775
|
return { stmts, valueVar: valVar, endVar };
|
|
5415
5776
|
}
|
|
5416
5777
|
function emit(p, ctx, pos) {
|
|
5778
|
+
const dispatch = (emissionPos = pos) => {
|
|
5779
|
+
const savedRule = ctx.activeCoverageRuleId;
|
|
5780
|
+
const rule = ctx.coverage?.plan.rules.get(p);
|
|
5781
|
+
if (rule && p !== ctx.coverage?.entry && !ctx.suppressCoverageFailure) ctx.activeCoverageRuleId = rule;
|
|
5782
|
+
const result = emitDispatch(p, ctx, emissionPos);
|
|
5783
|
+
ctx.activeCoverageRuleId = savedRule;
|
|
5784
|
+
return result;
|
|
5785
|
+
};
|
|
5786
|
+
const instrument = (r) => {
|
|
5787
|
+
const ruleId = ctx.coverage?.plan.rules.get(p);
|
|
5788
|
+
const labelIds = ctx.coverage?.plan.labels.get(p);
|
|
5789
|
+
if (!ruleId && !labelIds) return r;
|
|
5790
|
+
return {
|
|
5791
|
+
...r,
|
|
5792
|
+
stmts: [
|
|
5793
|
+
...ruleId ? [`${ind(ctx)}_ctx._grammarCoverage?.(${JSON.stringify(ruleId)})`] : [],
|
|
5794
|
+
...ruleId ? [`${ind(ctx)}_ctx._grammarTrace?.write({ id: ${JSON.stringify(ruleId)}, phase: 'enter', offset: ${pos} })`] : [],
|
|
5795
|
+
...r.stmts,
|
|
5796
|
+
...ruleId ? [`${ind(ctx)}_ctx._grammarTrace?.write({ id: ${JSON.stringify(ruleId)}, phase: 'success', offset: ${pos}, end: ${r.endVar} })`] : [],
|
|
5797
|
+
...labelIds?.flatMap((id) => [`${ind(ctx)}_ctx._grammarCoverage?.(${JSON.stringify(id)})`]) ?? [],
|
|
5798
|
+
...labelIds?.flatMap((id) => [`${ind(ctx)}_ctx._grammarTrace?.write({ id: ${JSON.stringify(id)}, phase: 'success', offset: ${pos}, end: ${r.endVar} })`]) ?? []
|
|
5799
|
+
]
|
|
5800
|
+
};
|
|
5801
|
+
};
|
|
5417
5802
|
const usage = ctx.lazyUsage;
|
|
5418
5803
|
if (usage && !ctx.noHoist && !ctx.capAsTrivia && !ctx.ruleNames?.has(p) && isHoistableTag(p._def.tag) && (usage.counts.get(p) ?? 0) > 1 && // Only hoist subtrees big enough that de-duplicating them beats the call
|
|
5419
5804
|
// overhead. A tiny shared wrapper (e.g. `optional(literal(';'))`) inlines
|
|
@@ -5430,14 +5815,14 @@ function emit(p, ctx, pos) {
|
|
|
5430
5815
|
ctx.indent = 1;
|
|
5431
5816
|
ctx.failLabel = "_pfail";
|
|
5432
5817
|
ctx.recordFail = true;
|
|
5433
|
-
const r =
|
|
5818
|
+
const r = dispatch("_pos");
|
|
5434
5819
|
ctx.indent = savedIndent;
|
|
5435
5820
|
ctx.failLabel = savedFailLabel;
|
|
5436
5821
|
ctx.recordFail = savedRecord;
|
|
5437
5822
|
pushNamedFnDecl(ctx, fnName, r.stmts, r.valueVar, r.endVar);
|
|
5438
|
-
return emitNamedFnCall(ctx, fnName, pos);
|
|
5823
|
+
return instrument(emitNamedFnCall(ctx, fnName, pos));
|
|
5439
5824
|
}
|
|
5440
|
-
return
|
|
5825
|
+
return instrument(dispatch());
|
|
5441
5826
|
}
|
|
5442
5827
|
function emitDispatch(p, ctx, pos) {
|
|
5443
5828
|
const def = p._def;
|
|
@@ -5451,7 +5836,9 @@ function emitDispatch(p, ctx, pos) {
|
|
|
5451
5836
|
case "sequence":
|
|
5452
5837
|
return emitSeq(def, ctx, pos);
|
|
5453
5838
|
case "choice":
|
|
5454
|
-
return emitChoice(def, ctx, pos);
|
|
5839
|
+
return emitChoice(p, def, ctx, pos);
|
|
5840
|
+
case "attempt":
|
|
5841
|
+
return emitAttempt(p, def, ctx, pos);
|
|
5455
5842
|
case "many":
|
|
5456
5843
|
case "oneOrMore":
|
|
5457
5844
|
return emitMany(def, ctx, pos);
|
|
@@ -5520,6 +5907,8 @@ function emitDispatch(p, ctx, pos) {
|
|
|
5520
5907
|
return emit(def.parser, ctx, pos);
|
|
5521
5908
|
case "token":
|
|
5522
5909
|
return emitToken(def, ctx, pos);
|
|
5910
|
+
case "leaf":
|
|
5911
|
+
return emitLeaf(def, ctx, pos);
|
|
5523
5912
|
case "label": {
|
|
5524
5913
|
const inner = emitFallible(def.parser, ctx, pos);
|
|
5525
5914
|
return {
|
|
@@ -5554,10 +5943,19 @@ function emitDispatch(p, ctx, pos) {
|
|
|
5554
5943
|
ctx.triviaKindLabels = def.triviaParser._meta.triviaKindLabels;
|
|
5555
5944
|
}
|
|
5556
5945
|
}
|
|
5946
|
+
const savedCapture = def.captureTrivia ? v(ctx, "_gcap") : null;
|
|
5557
5947
|
const r = emit(def.parser, ctx, pos);
|
|
5558
5948
|
ctx.activeTrivia = savedTrivia;
|
|
5559
5949
|
ctx.triviaKindLabels = savedKindLabels;
|
|
5560
|
-
return r;
|
|
5950
|
+
if (!savedCapture) return r;
|
|
5951
|
+
return {
|
|
5952
|
+
...r,
|
|
5953
|
+
stmts: [
|
|
5954
|
+
`${ind(ctx)}const ${savedCapture} = _ctx.captureTrivia; _ctx.captureTrivia = true`,
|
|
5955
|
+
...r.stmts,
|
|
5956
|
+
`${ind(ctx)}_ctx.captureTrivia = ${savedCapture}`
|
|
5957
|
+
]
|
|
5958
|
+
};
|
|
5561
5959
|
}
|
|
5562
5960
|
case "not":
|
|
5563
5961
|
return emitNot(def, ctx, pos);
|
|
@@ -5642,6 +6040,7 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
5642
6040
|
case "grammar":
|
|
5643
6041
|
case "trivia":
|
|
5644
6042
|
case "token":
|
|
6043
|
+
case "leaf":
|
|
5645
6044
|
case "label":
|
|
5646
6045
|
case "field":
|
|
5647
6046
|
case "optional":
|
|
@@ -5669,16 +6068,32 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
5669
6068
|
return false;
|
|
5670
6069
|
}
|
|
5671
6070
|
}
|
|
6071
|
+
function hasDirectBuildDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
6072
|
+
if (seen.has(p)) return false;
|
|
6073
|
+
seen.add(p);
|
|
6074
|
+
const d = p._def;
|
|
6075
|
+
if (d.tag === "node" && d.build !== void 0) return true;
|
|
6076
|
+
if (d.tag === "lazy") {
|
|
6077
|
+
try {
|
|
6078
|
+
return hasDirectBuildDef(d.thunk(), seen);
|
|
6079
|
+
} catch {
|
|
6080
|
+
return false;
|
|
6081
|
+
}
|
|
6082
|
+
}
|
|
6083
|
+
return childrenOf(d).some((child) => hasDirectBuildDef(child, seen));
|
|
6084
|
+
}
|
|
5672
6085
|
function childrenOf(def) {
|
|
5673
6086
|
switch (def.tag) {
|
|
5674
6087
|
case "sequence":
|
|
5675
6088
|
case "choice":
|
|
5676
6089
|
return def.parsers;
|
|
5677
6090
|
case "many":
|
|
6091
|
+
case "attempt":
|
|
5678
6092
|
case "optional":
|
|
5679
6093
|
case "transform":
|
|
5680
6094
|
case "trivia":
|
|
5681
6095
|
case "token":
|
|
6096
|
+
case "leaf":
|
|
5682
6097
|
case "label":
|
|
5683
6098
|
case "field":
|
|
5684
6099
|
case "grammar":
|
|
@@ -5853,10 +6268,25 @@ function compile(combinator, mapFnSources, opts) {
|
|
|
5853
6268
|
namedFnDecls: [],
|
|
5854
6269
|
capturing: hasNodeDef(combinator),
|
|
5855
6270
|
recovery: opts?.recovery ?? false,
|
|
6271
|
+
...opts?.coverage ? { coverage: { plan: buildGrammarPlan(combinator), entry: combinator } } : {},
|
|
5856
6272
|
lazyUsage: analyzeLazyUsage(combinator),
|
|
5857
6273
|
...grammarTrivia ? { activeTrivia: grammarTrivia, triviaKindLabels: grammarTrivia._meta.triviaKindLabels } : {}
|
|
5858
6274
|
};
|
|
5859
6275
|
const r = emit(combinator, ctx, "_pos");
|
|
6276
|
+
const coverageRootRuleId = ctx.coverage?.plan.rules.get(combinator);
|
|
6277
|
+
const resultBody = coverageRootRuleId === void 0 ? [
|
|
6278
|
+
` let pos = _pos`,
|
|
6279
|
+
...r.stmts,
|
|
6280
|
+
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`
|
|
6281
|
+
] : [
|
|
6282
|
+
` const _coverageResult = (() => {`,
|
|
6283
|
+
` let pos = _pos`,
|
|
6284
|
+
...r.stmts,
|
|
6285
|
+
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
6286
|
+
` })()`,
|
|
6287
|
+
` if (!_coverageResult.ok) _ctx._grammarTrace?.write({ id: ${JSON.stringify(coverageRootRuleId)}, phase: 'failure', offset: _coverageResult.span.start })`,
|
|
6288
|
+
` return _coverageResult`
|
|
6289
|
+
];
|
|
5860
6290
|
const namedPrelude = ctx.namedFnDecls.length > 0 ? [...namedFnPrelude(), ""] : [];
|
|
5861
6291
|
const emptyTlDecls = ctx.needsEmptyTl ? ["const _EMPTY_TL = Object.freeze([])"] : [];
|
|
5862
6292
|
const hostReadsDecls = ctx.needsHostReads ? [HOST_READS_DECL] : [];
|
|
@@ -5869,9 +6299,7 @@ function compile(combinator, mapFnSources, opts) {
|
|
|
5869
6299
|
...namedPrelude,
|
|
5870
6300
|
ctx.namedFnDecls.join("\n\n"),
|
|
5871
6301
|
`function _parse(input, _pos, _rp, _mf, _build, _ctx) {`,
|
|
5872
|
-
|
|
5873
|
-
...r.stmts,
|
|
5874
|
-
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
6302
|
+
...resultBody,
|
|
5875
6303
|
`}`
|
|
5876
6304
|
].join("\n");
|
|
5877
6305
|
const fn = new Function("input", "_pos", "_rp", "_mf", "_build", "_ctx", [
|
|
@@ -5881,9 +6309,15 @@ function compile(combinator, mapFnSources, opts) {
|
|
|
5881
6309
|
...ctx.expectedDecls,
|
|
5882
6310
|
...namedPrelude,
|
|
5883
6311
|
...ctx.namedFnDecls.flatMap((decl, i) => i > 0 ? ["", decl] : [decl]),
|
|
5884
|
-
`let pos = _pos`,
|
|
5885
|
-
|
|
5886
|
-
|
|
6312
|
+
...coverageRootRuleId === void 0 ? [`let pos = _pos`, ...r.stmts, `return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`] : [
|
|
6313
|
+
`const _coverageResult = (() => {`,
|
|
6314
|
+
` let pos = _pos`,
|
|
6315
|
+
...r.stmts,
|
|
6316
|
+
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
6317
|
+
`})()`,
|
|
6318
|
+
`if (!_coverageResult.ok) _ctx._grammarTrace?.write({ id: ${JSON.stringify(coverageRootRuleId)}, phase: 'failure', offset: _coverageResult.span.start })`,
|
|
6319
|
+
`return _coverageResult`
|
|
6320
|
+
]
|
|
5887
6321
|
].join("\n"));
|
|
5888
6322
|
const defaultCtx = {
|
|
5889
6323
|
trackLines: false,
|
|
@@ -5895,10 +6329,11 @@ function compile(combinator, mapFnSources, opts) {
|
|
|
5895
6329
|
const buildSources = ctx.buildFns.length === 0 ? void 0 : ctx.buildSrcs;
|
|
5896
6330
|
const mfCovered = ctx.mapFns.length === 0 || effectiveSources !== void 0 && effectiveSources.length === ctx.mapFns.length;
|
|
5897
6331
|
const canInline = ctx.runtimeParsers.length === 0 && mfCovered && buildCovered;
|
|
5898
|
-
const inlineExpression = canInline ? buildInlineExpression(ctx, r, effectiveSources, buildSources) : null;
|
|
6332
|
+
const inlineExpression = canInline ? buildInlineExpression(ctx, r, effectiveSources, buildSources, coverageRootRuleId) : null;
|
|
5899
6333
|
return {
|
|
5900
6334
|
source,
|
|
5901
6335
|
inlineExpression,
|
|
6336
|
+
...ctx.coverage === void 0 ? {} : { coverageDefinitions: ctx.coverage.plan.definitions },
|
|
5902
6337
|
parse(input, pos = 0) {
|
|
5903
6338
|
return fn(input, pos, ctx.runtimeParsers, ctx.mapFns, ctx.buildFns, defaultCtx);
|
|
5904
6339
|
},
|
|
@@ -5932,6 +6367,7 @@ function publicRuleWrapperSource(rule, fnSource) {
|
|
|
5932
6367
|
}
|
|
5933
6368
|
function compileRuleMap(ruleMap, opts) {
|
|
5934
6369
|
for (const [, rule] of ruleMap) markUnusedValues(rule);
|
|
6370
|
+
const coverageWinners = opts?.coverage ? Object.fromEntries(ruleMap.filter(([, rule]) => rule._def.tag !== "lazy")) : void 0;
|
|
5935
6371
|
const grammarTrivia = opts?.trivia;
|
|
5936
6372
|
const ctx = {
|
|
5937
6373
|
vars: 0,
|
|
@@ -5952,6 +6388,7 @@ function compileRuleMap(ruleMap, opts) {
|
|
|
5952
6388
|
namedFnDecls: [],
|
|
5953
6389
|
capturing: ruleMap.some(([, rule]) => hasNodeDef(rule)),
|
|
5954
6390
|
recovery: opts?.recovery ?? false,
|
|
6391
|
+
...opts?.coverage ? { coverage: { plan: buildGrammarPlan(ruleMap.map(([, rule]) => rule), coverageWinners) } } : {},
|
|
5955
6392
|
lazyUsage: analyzeLazyUsageMulti(ruleMap.map(([, rule]) => rule)),
|
|
5956
6393
|
...grammarTrivia ? { activeTrivia: grammarTrivia, triviaKindLabels: grammarTrivia._meta.triviaKindLabels } : {}
|
|
5957
6394
|
};
|
|
@@ -5994,15 +6431,34 @@ function compileRuleMap(ruleMap, opts) {
|
|
|
5994
6431
|
return i > 0 ? ["", ...lines] : lines;
|
|
5995
6432
|
})
|
|
5996
6433
|
].filter(Boolean);
|
|
5997
|
-
const
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6434
|
+
const entryRuleId = (rule) => {
|
|
6435
|
+
const direct = ctx.coverage?.plan.rules.get(rule);
|
|
6436
|
+
if (direct !== void 0 || rule._def.tag !== "lazy") return direct;
|
|
6437
|
+
try {
|
|
6438
|
+
return ctx.coverage?.plan.rules.get(rule._def.thunk());
|
|
6439
|
+
} catch {
|
|
6440
|
+
return void 0;
|
|
6441
|
+
}
|
|
6442
|
+
};
|
|
6443
|
+
const entryFnText = (r, rule) => {
|
|
6444
|
+
const ruleId = entryRuleId(rule);
|
|
6445
|
+
const body = ruleId === void 0 ? [
|
|
6446
|
+
` let pos = _pos`,
|
|
6447
|
+
...r.stmts,
|
|
6448
|
+
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`
|
|
6449
|
+
] : [
|
|
6450
|
+
` const _coverageResult = (() => {`,
|
|
6451
|
+
` let pos = _pos`,
|
|
6452
|
+
...r.stmts,
|
|
6453
|
+
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
6454
|
+
` })()`,
|
|
6455
|
+
` if (!_coverageResult.ok) _ctx._grammarTrace?.write({ id: ${JSON.stringify(ruleId)}, phase: 'failure', offset: _coverageResult.span.start })`,
|
|
6456
|
+
` return _coverageResult`
|
|
6457
|
+
];
|
|
6458
|
+
return [`function(input, _pos, _ctx) {`, ...body, `}`].join("\n");
|
|
6459
|
+
};
|
|
6004
6460
|
const objBody = perEntry.map(({ key, rule, r }) => {
|
|
6005
|
-
const src = publicRuleWrapperSource(rule, entryFnText(r));
|
|
6461
|
+
const src = publicRuleWrapperSource(rule, entryFnText(r, rule));
|
|
6006
6462
|
return ` ${JSON.stringify(key)}: ${src.split("\n").join("\n ")}`;
|
|
6007
6463
|
}).join(",\n");
|
|
6008
6464
|
const replacement = [
|
|
@@ -6013,7 +6469,11 @@ function compileRuleMap(ruleMap, opts) {
|
|
|
6013
6469
|
` }`,
|
|
6014
6470
|
`})()`
|
|
6015
6471
|
].join("\n");
|
|
6016
|
-
return {
|
|
6472
|
+
return {
|
|
6473
|
+
keys: perEntry.map((e) => e.key),
|
|
6474
|
+
replacement,
|
|
6475
|
+
...ctx.coverage === void 0 ? {} : { coverageDefinitions: ctx.coverage.plan.definitions }
|
|
6476
|
+
};
|
|
6017
6477
|
}
|
|
6018
6478
|
function compileLinkable(ruleMapArg, ns, opts) {
|
|
6019
6479
|
if (!ns) throw new Error("compileLinkable: ns must be a non-empty namespace");
|
|
@@ -6046,8 +6506,13 @@ function compileLinkable(ruleMapArg, ns, opts) {
|
|
|
6046
6506
|
triviaCaptureNames: /* @__PURE__ */ new Map(),
|
|
6047
6507
|
triviaFnNames: /* @__PURE__ */ new Map(),
|
|
6048
6508
|
namedFnDecls: [],
|
|
6049
|
-
|
|
6509
|
+
// A recognition-only fragment normally has no node collector of its own.
|
|
6510
|
+
// Leaf composition can re-lower it beneath a local semantic node, though;
|
|
6511
|
+
// in that case its terminals must feed the caller's collector rather than
|
|
6512
|
+
// merely returning their scalar parse values.
|
|
6513
|
+
capturing: opts?.captureTerminals === true || ruleMap.some(([, rule]) => hasNodeDef(rule)),
|
|
6050
6514
|
recovery: opts?.recovery ?? false,
|
|
6515
|
+
...opts?.coverage ? { coverage: { plan: opts.coverage } } : {},
|
|
6051
6516
|
lazyUsage: analyzeLazyUsageMulti(ruleMap.map(([, rule]) => rule)),
|
|
6052
6517
|
ns,
|
|
6053
6518
|
deferFirstSetRefs: true,
|
|
@@ -6121,7 +6586,14 @@ function compileLinkable(ruleMapArg, ns, opts) {
|
|
|
6121
6586
|
ctx.indent = savedIndent;
|
|
6122
6587
|
ctx.failLabel = savedFail;
|
|
6123
6588
|
ctx.recordFail = savedRec;
|
|
6124
|
-
|
|
6589
|
+
const ruleId = ctx.coverage?.plan.rules.get(rule);
|
|
6590
|
+
const stmts = ruleId === void 0 ? body.stmts : [
|
|
6591
|
+
`${ind(ctx)}_ctx._grammarCoverage?.(${JSON.stringify(ruleId)})`,
|
|
6592
|
+
`${ind(ctx)}_ctx._grammarTrace?.write({ id: ${JSON.stringify(ruleId)}, phase: 'enter', offset: _pos })`,
|
|
6593
|
+
...body.stmts,
|
|
6594
|
+
`${ind(ctx)}_ctx._grammarTrace?.write({ id: ${JSON.stringify(ruleId)}, phase: 'success', offset: _pos, end: ${body.endVar} })`
|
|
6595
|
+
];
|
|
6596
|
+
pushNamedFnDecl(ctx, fn, stmts, body.valueVar, body.endVar);
|
|
6125
6597
|
}
|
|
6126
6598
|
perEntry.push({ key, rule, r: emitNamedFnCall(ctx, fn, "_pos") });
|
|
6127
6599
|
}
|
|
@@ -6178,15 +6650,46 @@ function compileLinkable(ruleMapArg, ns, opts) {
|
|
|
6178
6650
|
deps: ruleDependencies(ruleMap),
|
|
6179
6651
|
needsEmptyTl: !!ctx.needsEmptyTl,
|
|
6180
6652
|
needsHostReads: !!ctx.needsHostReads,
|
|
6653
|
+
hasDirectBuilders: ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
|
|
6654
|
+
isRecognitionOnly: !hasSemanticReduction(ruleMap.map(([, rule]) => rule)),
|
|
6181
6655
|
mfFns: mfSrcs ? [] : ctx.mapFns,
|
|
6182
6656
|
buildFns: buildSrcs ? [] : ctx.buildFns
|
|
6183
6657
|
};
|
|
6184
6658
|
}
|
|
6185
|
-
function
|
|
6186
|
-
const
|
|
6659
|
+
function hasSemanticReduction(roots) {
|
|
6660
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6661
|
+
const visit = (parser2) => {
|
|
6662
|
+
if (seen.has(parser2)) return false;
|
|
6663
|
+
seen.add(parser2);
|
|
6664
|
+
const def = parser2._def;
|
|
6665
|
+
if (def.tag === "transform" && !def.recognitionOnly) return true;
|
|
6666
|
+
if (def.tag === "choice" && def.gates.some(Boolean)) return true;
|
|
6667
|
+
if (def.tag === "guard" || def.tag === "withCtx") return true;
|
|
6668
|
+
if (def.tag === "node" && def.build !== void 0) return true;
|
|
6669
|
+
if (def.tag === "lazy") {
|
|
6670
|
+
try {
|
|
6671
|
+
return visit(def.thunk());
|
|
6672
|
+
} catch {
|
|
6673
|
+
return true;
|
|
6674
|
+
}
|
|
6675
|
+
}
|
|
6676
|
+
return childrenOf(def).some(visit);
|
|
6677
|
+
};
|
|
6678
|
+
return roots.some(visit);
|
|
6679
|
+
}
|
|
6680
|
+
function buildInlineExpression(ctx, r, mapFnSources, buildSources, coverageRootRuleId) {
|
|
6681
|
+
const bodyLines = coverageRootRuleId === void 0 ? [
|
|
6187
6682
|
` let pos = _pos`,
|
|
6188
6683
|
...r.stmts,
|
|
6189
6684
|
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`
|
|
6685
|
+
] : [
|
|
6686
|
+
` const _coverageResult = (() => {`,
|
|
6687
|
+
` let pos = _pos`,
|
|
6688
|
+
...r.stmts,
|
|
6689
|
+
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
6690
|
+
` })()`,
|
|
6691
|
+
` if (!_coverageResult.ok) _ctx._grammarTrace?.write({ id: ${JSON.stringify(coverageRootRuleId)}, phase: 'failure', offset: _coverageResult.span.start })`,
|
|
6692
|
+
` return _coverageResult`
|
|
6190
6693
|
];
|
|
6191
6694
|
const innerFn = [
|
|
6192
6695
|
`function(input, _pos, _ctx) {`,
|
|
@@ -6241,8 +6744,8 @@ function scanTo(sentinel, { skip: skip2 = [], orEOF = false } = {}) {
|
|
|
6241
6744
|
};
|
|
6242
6745
|
const emit2 = (end) => {
|
|
6243
6746
|
if (end > pos && cstCaptureActive(ctx)) {
|
|
6244
|
-
const
|
|
6245
|
-
pushCstLeaf(ctx,
|
|
6747
|
+
const leaf2 = { _tag: "leaf", value: input.slice(pos, end), span: { start: pos, end } };
|
|
6748
|
+
pushCstLeaf(ctx, leaf2);
|
|
6246
6749
|
}
|
|
6247
6750
|
};
|
|
6248
6751
|
while (cur < input.length) {
|
|
@@ -6296,6 +6799,7 @@ function balanced(open, close, options = {}) {
|
|
|
6296
6799
|
);
|
|
6297
6800
|
if (combi._def.tag === "transform") {
|
|
6298
6801
|
combi._def.fnSrc = '([o, parts, c]) => o + parts.map(p => typeof p === "string" ? p : Array.isArray(p) ? p.join("") : "").join("") + (typeof c === "string" ? c : "")';
|
|
6802
|
+
combi._def.recognitionOnly = true;
|
|
6299
6803
|
}
|
|
6300
6804
|
self.define(combi);
|
|
6301
6805
|
return combi;
|
|
@@ -6341,9 +6845,11 @@ function childrenOf2(def) {
|
|
|
6341
6845
|
case "many":
|
|
6342
6846
|
case "oneOrMore":
|
|
6343
6847
|
case "optional":
|
|
6848
|
+
case "attempt":
|
|
6344
6849
|
case "transform":
|
|
6345
6850
|
case "trivia":
|
|
6346
6851
|
case "token":
|
|
6852
|
+
case "leaf":
|
|
6347
6853
|
case "label":
|
|
6348
6854
|
case "field":
|
|
6349
6855
|
case "not":
|
|
@@ -6392,7 +6898,7 @@ function serializeRuleMap(ruleMap) {
|
|
|
6392
6898
|
}
|
|
6393
6899
|
}
|
|
6394
6900
|
function evalRuleMapIR(ir) {
|
|
6395
|
-
const _tf = (child, src) => {
|
|
6901
|
+
const _tf = (child, src, recognitionOnly = false) => {
|
|
6396
6902
|
let fn2;
|
|
6397
6903
|
try {
|
|
6398
6904
|
fn2 = (0, eval)(`(${src})`);
|
|
@@ -6403,11 +6909,31 @@ function evalRuleMapIR(ir) {
|
|
|
6403
6909
|
}
|
|
6404
6910
|
const t = transform(child, fn2);
|
|
6405
6911
|
t._def.fnSrc = src;
|
|
6912
|
+
if (recognitionOnly) t._def.recognitionOnly = true;
|
|
6406
6913
|
return t;
|
|
6407
6914
|
};
|
|
6408
|
-
const
|
|
6409
|
-
|
|
6915
|
+
const _lf = (child, src) => {
|
|
6916
|
+
let fn2;
|
|
6917
|
+
try {
|
|
6918
|
+
fn2 = (0, eval)(`(${src})`);
|
|
6919
|
+
} catch {
|
|
6920
|
+
fn2 = () => {
|
|
6921
|
+
throw new Error("IR leaf fn not materialized");
|
|
6922
|
+
};
|
|
6923
|
+
}
|
|
6924
|
+
const l = leaf(child, fn2);
|
|
6925
|
+
l._def.fnSrc = src;
|
|
6926
|
+
return l;
|
|
6927
|
+
};
|
|
6928
|
+
const _nd = (type, child, src, opts, staticError) => {
|
|
6929
|
+
if (staticError !== void 0 && staticError.length > 0) {
|
|
6930
|
+
throw new Error(`IR direct node builder for ${type} must be macro-static and self-contained; unsupported binding(s): ${staticError.join(", ")}`);
|
|
6931
|
+
}
|
|
6932
|
+
const n = node(type, child, (() => {
|
|
6933
|
+
throw new Error("IR node build requires static re-lowering");
|
|
6934
|
+
}), opts);
|
|
6410
6935
|
n._def.buildSrc = src;
|
|
6936
|
+
if (staticError !== void 0) n._def.buildStaticError = staticError;
|
|
6411
6937
|
return n;
|
|
6412
6938
|
};
|
|
6413
6939
|
const _gch = (items) => {
|
|
@@ -6457,6 +6983,7 @@ function evalRuleMapIR(ir) {
|
|
|
6457
6983
|
"keywords",
|
|
6458
6984
|
"sequence",
|
|
6459
6985
|
"choice",
|
|
6986
|
+
"attempt",
|
|
6460
6987
|
"many",
|
|
6461
6988
|
"oneOrMore",
|
|
6462
6989
|
"optional",
|
|
@@ -6466,6 +6993,7 @@ function evalRuleMapIR(ir) {
|
|
|
6466
6993
|
"parser",
|
|
6467
6994
|
"scanTo",
|
|
6468
6995
|
"token",
|
|
6996
|
+
"leaf",
|
|
6469
6997
|
"transform",
|
|
6470
6998
|
"skip",
|
|
6471
6999
|
"trivia",
|
|
@@ -6473,6 +7001,7 @@ function evalRuleMapIR(ir) {
|
|
|
6473
7001
|
"field",
|
|
6474
7002
|
"expect",
|
|
6475
7003
|
"_tf",
|
|
7004
|
+
"_lf",
|
|
6476
7005
|
"_nd",
|
|
6477
7006
|
"_gch",
|
|
6478
7007
|
"_wc",
|
|
@@ -6486,6 +7015,7 @@ function evalRuleMapIR(ir) {
|
|
|
6486
7015
|
keywords,
|
|
6487
7016
|
sequence,
|
|
6488
7017
|
choice,
|
|
7018
|
+
attempt,
|
|
6489
7019
|
many,
|
|
6490
7020
|
oneOrMore,
|
|
6491
7021
|
optional,
|
|
@@ -6495,6 +7025,7 @@ function evalRuleMapIR(ir) {
|
|
|
6495
7025
|
parser,
|
|
6496
7026
|
scanTo,
|
|
6497
7027
|
token,
|
|
7028
|
+
leaf,
|
|
6498
7029
|
transform,
|
|
6499
7030
|
skip,
|
|
6500
7031
|
trivia,
|
|
@@ -6502,6 +7033,7 @@ function evalRuleMapIR(ir) {
|
|
|
6502
7033
|
field,
|
|
6503
7034
|
expect,
|
|
6504
7035
|
_tf,
|
|
7036
|
+
_lf,
|
|
6505
7037
|
_nd,
|
|
6506
7038
|
_gch,
|
|
6507
7039
|
_wc
|
|
@@ -6633,6 +7165,8 @@ ${body}
|
|
|
6633
7165
|
return `oneOrMore(${kid(def.parser)})`;
|
|
6634
7166
|
case "optional":
|
|
6635
7167
|
return `optional(${kid(def.parser)})`;
|
|
7168
|
+
case "attempt":
|
|
7169
|
+
return `attempt(${kid(def.parser)})`;
|
|
6636
7170
|
case "sepBy":
|
|
6637
7171
|
return `sepBy(${kid(def.parser)}, ${kid(def.separator)})`;
|
|
6638
7172
|
case "not":
|
|
@@ -6641,6 +7175,10 @@ ${body}
|
|
|
6641
7175
|
return `trivia(${kid(def.parser)})`;
|
|
6642
7176
|
case "token":
|
|
6643
7177
|
return `token(${kid(def.parser)})`;
|
|
7178
|
+
case "leaf": {
|
|
7179
|
+
if (def.fnSrc === void 0) throw new Unserializable("leaf without fnSrc");
|
|
7180
|
+
return `_lf(${kid(def.parser)}, ${JSON.stringify(def.fnSrc)})`;
|
|
7181
|
+
}
|
|
6644
7182
|
case "label":
|
|
6645
7183
|
return `label(${JSON.stringify(def.label)}, ${kid(def.parser)})`;
|
|
6646
7184
|
case "field":
|
|
@@ -6653,21 +7191,30 @@ ${body}
|
|
|
6653
7191
|
return `scanTo(${kid(def.sentinel)}, { skip: [${def.skip.map(kid).join(", ")}], orEOF: ${def.orEOF} })`;
|
|
6654
7192
|
case "transform": {
|
|
6655
7193
|
if (def.fnSrc === void 0) throw new Unserializable("transform without fnSrc");
|
|
6656
|
-
return `_tf(${kid(def.parser)}, ${JSON.stringify(def.fnSrc)})`;
|
|
7194
|
+
return `_tf(${kid(def.parser)}, ${JSON.stringify(def.fnSrc)}${def.recognitionOnly ? ", true" : ""})`;
|
|
6657
7195
|
}
|
|
6658
7196
|
case "node": {
|
|
6659
7197
|
if (def.build !== void 0 && def.buildSrc === void 0) throw new Unserializable("node build without buildSrc");
|
|
6660
|
-
const
|
|
7198
|
+
const optEntries = [
|
|
7199
|
+
...def.unwrap ? ["unwrap: true"] : [],
|
|
7200
|
+
...def.collapse ? ["collapse: true"] : [],
|
|
7201
|
+
...def.captureTrivia ? ["captureTrivia: true"] : [],
|
|
7202
|
+
...def.trailingTrivia ? ["trailingTrivia: true"] : []
|
|
7203
|
+
];
|
|
7204
|
+
const opts = optEntries.length > 0 ? `, { ${optEntries.join(", ")} }` : "";
|
|
6661
7205
|
if (def.type === void 0) {
|
|
6662
7206
|
if (def.buildSrc !== void 0) throw new Unserializable("inferred node build without inferred type");
|
|
6663
7207
|
return opts ? `node(${kid(def.parser)}, undefined${opts})` : `node(${kid(def.parser)})`;
|
|
6664
7208
|
}
|
|
6665
|
-
if (def.buildSrc !== void 0)
|
|
7209
|
+
if (def.buildSrc !== void 0) {
|
|
7210
|
+
const staticError = def.buildStaticError === void 0 ? "" : `${opts ? "" : ", undefined"}, ${JSON.stringify(def.buildStaticError)}`;
|
|
7211
|
+
return `_nd(${JSON.stringify(def.type)}, ${kid(def.parser)}, ${JSON.stringify(def.buildSrc)}${opts}${staticError})`;
|
|
7212
|
+
}
|
|
6666
7213
|
return opts ? `node(${JSON.stringify(def.type)}, ${kid(def.parser)}, undefined${opts})` : `node(${JSON.stringify(def.type)}, ${kid(def.parser)})`;
|
|
6667
7214
|
}
|
|
6668
7215
|
case "grammar": {
|
|
6669
7216
|
const trivia2 = def.clearTrivia ? "null" : def.triviaParser ? kid(def.triviaParser) : "undefined";
|
|
6670
|
-
return `parser({ trivia: ${trivia2}${def.trackLines ? ", trackLines: true" : ""} }, ${kid(def.parser)})`;
|
|
7217
|
+
return `parser({ trivia: ${trivia2}${def.captureTrivia ? ", captureTrivia: true" : ""}${def.trackLines ? ", trackLines: true" : ""} }, ${kid(def.parser)})`;
|
|
6671
7218
|
}
|
|
6672
7219
|
case "withCtx": {
|
|
6673
7220
|
if (def.extraSrc === void 0) throw new Unserializable("withCtx without extraSrc");
|
|
@@ -6682,6 +7229,28 @@ ${body}
|
|
|
6682
7229
|
};
|
|
6683
7230
|
|
|
6684
7231
|
// src/compiler/linker.ts
|
|
7232
|
+
function normalizeCstCollapse(collapse) {
|
|
7233
|
+
if (collapse === true) return () => true;
|
|
7234
|
+
if (Array.isArray(collapse)) {
|
|
7235
|
+
const types = new Set(collapse);
|
|
7236
|
+
return (type) => types.has(type);
|
|
7237
|
+
}
|
|
7238
|
+
return typeof collapse === "function" ? collapse : void 0;
|
|
7239
|
+
}
|
|
7240
|
+
function buildCstNode(type, children2, _fields, span, _rawChildren, _triviaLog, state) {
|
|
7241
|
+
return { _tag: "node", type, span: { start: span.start, end: span.end }, state: state ?? null, children: [...children2] };
|
|
7242
|
+
}
|
|
7243
|
+
function cstBuildHost(typeOrOptions, children2, _fields, span, rawChildren, triviaLog, state) {
|
|
7244
|
+
if (typeof typeOrOptions === "string") {
|
|
7245
|
+
return buildCstNode(typeOrOptions, children2 ?? [], _fields, span ?? { start: 0, end: 0 }, rawChildren, triviaLog, state);
|
|
7246
|
+
}
|
|
7247
|
+
const collapse = normalizeCstCollapse(typeOrOptions?.collapse);
|
|
7248
|
+
const host = (type, children3, fields, span2, rawChildren2, triviaLog2, state2) => buildCstNode(type, children3, fields, span2, rawChildren2, triviaLog2, state2);
|
|
7249
|
+
host._parsemanCstOutput = true;
|
|
7250
|
+
if (collapse) host._parsemanCstCollapse = collapse;
|
|
7251
|
+
return host;
|
|
7252
|
+
}
|
|
7253
|
+
cstBuildHost._parsemanCstOutput = true;
|
|
6685
7254
|
function pickPieces(pieces, names) {
|
|
6686
7255
|
const winner = /* @__PURE__ */ new Map();
|
|
6687
7256
|
for (const pc of pieces) for (const k of pc.keys) winner.set(k, pc);
|
|
@@ -6759,9 +7328,12 @@ ${body}
|
|
|
6759
7328
|
function isIRPiece(p) {
|
|
6760
7329
|
return !!p && typeof p === "object" && typeof p.ir === "string" && typeof p.ns === "string" && !("ruleFns" in p);
|
|
6761
7330
|
}
|
|
6762
|
-
function materializePiece(p, trivia2) {
|
|
7331
|
+
function materializePiece(p, trivia2, captureTerminals = false) {
|
|
6763
7332
|
if (!isIRPiece(p)) return p;
|
|
6764
|
-
const pieces = compileLinkable(evalRuleMapIR(p.ir), p.ns,
|
|
7333
|
+
const pieces = compileLinkable(evalRuleMapIR(p.ir), p.ns, {
|
|
7334
|
+
...trivia2 ? { trivia: trivia2 } : {},
|
|
7335
|
+
...captureTerminals ? { captureTerminals: true } : {}
|
|
7336
|
+
});
|
|
6765
7337
|
if (!pieces) throw new Error(`compose: carried IR for ns "${p.ns}" could not be re-lowered`);
|
|
6766
7338
|
return pieces;
|
|
6767
7339
|
}
|
|
@@ -6791,6 +7363,152 @@ var { isFinite } = Number;
|
|
|
6791
7363
|
// src/index.ts
|
|
6792
7364
|
registerRegexAnalyzer(firstSetFromRegex);
|
|
6793
7365
|
|
|
7366
|
+
// src/plugin/direct-builder-static.ts
|
|
7367
|
+
import { parseSync } from "oxc-parser";
|
|
7368
|
+
var STATIC_BUILDER_GLOBALS = /* @__PURE__ */ new Set([
|
|
7369
|
+
"Array",
|
|
7370
|
+
"Boolean",
|
|
7371
|
+
"Date",
|
|
7372
|
+
"JSON",
|
|
7373
|
+
"Math",
|
|
7374
|
+
"NaN",
|
|
7375
|
+
"Number",
|
|
7376
|
+
"Object",
|
|
7377
|
+
"String",
|
|
7378
|
+
"Infinity",
|
|
7379
|
+
"parseFloat",
|
|
7380
|
+
"parseInt",
|
|
7381
|
+
"undefined"
|
|
7382
|
+
]);
|
|
7383
|
+
function astArray(value) {
|
|
7384
|
+
return Array.isArray(value) ? value : [];
|
|
7385
|
+
}
|
|
7386
|
+
function astChild(value) {
|
|
7387
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
7388
|
+
}
|
|
7389
|
+
function unwrapCallbackExpression(node2) {
|
|
7390
|
+
let current = node2;
|
|
7391
|
+
while (current?.type === "ParenthesizedExpression") current = astChild(current.expression) ?? void 0;
|
|
7392
|
+
return current;
|
|
7393
|
+
}
|
|
7394
|
+
function directBuilderUnsupportedBindings(src) {
|
|
7395
|
+
let init;
|
|
7396
|
+
try {
|
|
7397
|
+
const parsed = parseSync("parseman-direct-builder.ts", `const _direct = (${src})`);
|
|
7398
|
+
if (parsed.errors.length > 0) return ["invalid callback source"];
|
|
7399
|
+
const program = parsed.program;
|
|
7400
|
+
const statement = program.body?.[0];
|
|
7401
|
+
const declaration = statement?.declarations?.[0];
|
|
7402
|
+
init = unwrapCallbackExpression(declaration?.init);
|
|
7403
|
+
} catch {
|
|
7404
|
+
return ["invalid callback source"];
|
|
7405
|
+
}
|
|
7406
|
+
if (init?.type !== "ArrowFunctionExpression" || !Array.isArray(init.params)) return ["unsupported callback shape"];
|
|
7407
|
+
const allowed = new Set(STATIC_BUILDER_GLOBALS);
|
|
7408
|
+
for (const param of init.params) {
|
|
7409
|
+
if (param.type !== "Identifier" || typeof param.name !== "string") return ["unsupported parameter pattern"];
|
|
7410
|
+
allowed.add(param.name);
|
|
7411
|
+
}
|
|
7412
|
+
const unsupported = /* @__PURE__ */ new Set();
|
|
7413
|
+
const reportUnsupportedNode = (ast) => {
|
|
7414
|
+
unsupported.add(`unsupported ${ast.type}`);
|
|
7415
|
+
};
|
|
7416
|
+
const read = (ast, allowedNames) => {
|
|
7417
|
+
if (typeof ast.name === "string" && allowedNames.has(ast.name)) return;
|
|
7418
|
+
unsupported.add(typeof ast.name === "string" ? ast.name : "identifier");
|
|
7419
|
+
};
|
|
7420
|
+
const expression = (node2, allowedNames) => {
|
|
7421
|
+
const ast = astChild(node2);
|
|
7422
|
+
if (!ast) return;
|
|
7423
|
+
switch (ast.type) {
|
|
7424
|
+
case "Literal":
|
|
7425
|
+
return;
|
|
7426
|
+
case "Identifier":
|
|
7427
|
+
read(ast, allowedNames);
|
|
7428
|
+
return;
|
|
7429
|
+
case "ParenthesizedExpression":
|
|
7430
|
+
case "ChainExpression":
|
|
7431
|
+
case "TSAsExpression":
|
|
7432
|
+
case "TSTypeAssertion":
|
|
7433
|
+
case "TSNonNullExpression":
|
|
7434
|
+
expression(ast.expression, allowedNames);
|
|
7435
|
+
return;
|
|
7436
|
+
case "ArrayExpression":
|
|
7437
|
+
for (const element of astArray(ast.elements)) expression(element, allowedNames);
|
|
7438
|
+
return;
|
|
7439
|
+
case "ObjectExpression":
|
|
7440
|
+
for (const property of astArray(ast.properties)) {
|
|
7441
|
+
if (property.type === "SpreadElement") {
|
|
7442
|
+
expression(property.argument, allowedNames);
|
|
7443
|
+
continue;
|
|
7444
|
+
}
|
|
7445
|
+
if (property.type !== "Property" || property.method === true || property.kind !== "init") {
|
|
7446
|
+
reportUnsupportedNode(property);
|
|
7447
|
+
continue;
|
|
7448
|
+
}
|
|
7449
|
+
if (property.computed === true) expression(property.key, allowedNames);
|
|
7450
|
+
expression(property.value, allowedNames);
|
|
7451
|
+
}
|
|
7452
|
+
return;
|
|
7453
|
+
case "MemberExpression":
|
|
7454
|
+
expression(ast.object, allowedNames);
|
|
7455
|
+
if (ast.computed === true) expression(ast.property, allowedNames);
|
|
7456
|
+
return;
|
|
7457
|
+
case "CallExpression":
|
|
7458
|
+
case "NewExpression":
|
|
7459
|
+
expression(ast.callee, allowedNames);
|
|
7460
|
+
for (const argument of astArray(ast.arguments)) expression(argument, allowedNames);
|
|
7461
|
+
return;
|
|
7462
|
+
case "UnaryExpression":
|
|
7463
|
+
case "UpdateExpression":
|
|
7464
|
+
expression(ast.argument, allowedNames);
|
|
7465
|
+
return;
|
|
7466
|
+
case "BinaryExpression":
|
|
7467
|
+
case "LogicalExpression":
|
|
7468
|
+
case "AssignmentExpression":
|
|
7469
|
+
expression(ast.left, allowedNames);
|
|
7470
|
+
expression(ast.right, allowedNames);
|
|
7471
|
+
return;
|
|
7472
|
+
case "ConditionalExpression":
|
|
7473
|
+
expression(ast.test, allowedNames);
|
|
7474
|
+
expression(ast.consequent, allowedNames);
|
|
7475
|
+
expression(ast.alternate, allowedNames);
|
|
7476
|
+
return;
|
|
7477
|
+
case "SequenceExpression":
|
|
7478
|
+
for (const value of astArray(ast.expressions)) expression(value, allowedNames);
|
|
7479
|
+
return;
|
|
7480
|
+
case "TemplateLiteral":
|
|
7481
|
+
for (const value of astArray(ast.expressions)) expression(value, allowedNames);
|
|
7482
|
+
return;
|
|
7483
|
+
case "SpreadElement":
|
|
7484
|
+
expression(ast.argument, allowedNames);
|
|
7485
|
+
return;
|
|
7486
|
+
case "ArrowFunctionExpression": {
|
|
7487
|
+
const nested = new Set(allowedNames);
|
|
7488
|
+
for (const param of astArray(ast.params)) {
|
|
7489
|
+
if (param.type !== "Identifier" || typeof param.name !== "string") {
|
|
7490
|
+
reportUnsupportedNode(param);
|
|
7491
|
+
continue;
|
|
7492
|
+
}
|
|
7493
|
+
nested.add(param.name);
|
|
7494
|
+
}
|
|
7495
|
+
if (astChild(ast.body)?.type === "BlockStatement") {
|
|
7496
|
+
reportUnsupportedNode(astChild(ast.body));
|
|
7497
|
+
return;
|
|
7498
|
+
}
|
|
7499
|
+
expression(ast.body, nested);
|
|
7500
|
+
return;
|
|
7501
|
+
}
|
|
7502
|
+
default:
|
|
7503
|
+
reportUnsupportedNode(ast);
|
|
7504
|
+
return;
|
|
7505
|
+
}
|
|
7506
|
+
};
|
|
7507
|
+
if (astChild(init.body)?.type === "BlockStatement") unsupported.add("unsupported BlockStatement");
|
|
7508
|
+
else expression(init.body, allowed);
|
|
7509
|
+
return [...unsupported];
|
|
7510
|
+
}
|
|
7511
|
+
|
|
6794
7512
|
// src/plugin/evaluator.ts
|
|
6795
7513
|
function stripTsFromSource(node2, code) {
|
|
6796
7514
|
const cuts = [];
|
|
@@ -6844,15 +7562,18 @@ var SUPPORTED = {
|
|
|
6844
7562
|
word: (...a) => word(a[0], a[1]),
|
|
6845
7563
|
sequence: (...a) => sequence(...a),
|
|
6846
7564
|
choice: (...a) => choice(...a),
|
|
7565
|
+
attempt: (...a) => attempt(a[0]),
|
|
6847
7566
|
many: (...a) => many(a[0]),
|
|
6848
7567
|
oneOrMore: (...a) => oneOrMore(a[0]),
|
|
6849
7568
|
optional: (...a) => optional(a[0]),
|
|
7569
|
+
skip: (...a) => skip(a[0], a[1]),
|
|
6850
7570
|
sepBy: (...a) => sepBy(a[0], a[1]),
|
|
6851
7571
|
trivia: (...a) => trivia(a[0]),
|
|
6852
7572
|
label: (...a) => label(a[0], a[1]),
|
|
6853
7573
|
field: (...a) => field(a[0], a[1]),
|
|
6854
7574
|
noTrivia: (...a) => noTrivia(a[0]),
|
|
6855
7575
|
token: (...a) => token(a[0]),
|
|
7576
|
+
leaf: (...a) => leaf(a[0], a[1]),
|
|
6856
7577
|
expect: (...a) => expect(a[0], a[1])
|
|
6857
7578
|
};
|
|
6858
7579
|
function isScopeEntry(v2) {
|
|
@@ -6908,12 +7629,12 @@ function staticNodeOptions(expr) {
|
|
|
6908
7629
|
if (p.computed) continue;
|
|
6909
7630
|
const key = p.key;
|
|
6910
7631
|
const name = key.type === "Identifier" ? key.name : key.type === "Literal" ? String(key.value) : void 0;
|
|
6911
|
-
if (name === "unwrap" || name === "collapse") {
|
|
7632
|
+
if (name === "unwrap" || name === "collapse" || name === "captureTrivia" || name === "trailingTrivia") {
|
|
6912
7633
|
const val = p.value;
|
|
6913
7634
|
if ((val.type === "Literal" || val.type === "BooleanLiteral") && val.value === true) opts[name] = true;
|
|
6914
7635
|
}
|
|
6915
7636
|
}
|
|
6916
|
-
return opts.unwrap || opts.collapse ? opts : void 0;
|
|
7637
|
+
return opts.unwrap || opts.collapse || opts.captureTrivia || opts.trailingTrivia ? opts : void 0;
|
|
6917
7638
|
}
|
|
6918
7639
|
function exprToCombi(node2, scope, code, mfs) {
|
|
6919
7640
|
if (node2.type === "Identifier") return scopeGet(scope, node2.name, mfs);
|
|
@@ -6952,7 +7673,7 @@ function exprToCombi(node2, scope, code, mfs) {
|
|
|
6952
7673
|
if (!parserArg || !fnArg || parserArg.type === "SpreadElement" || fnArg.type === "SpreadElement") return null;
|
|
6953
7674
|
const inner = anyValue(parserArg, scope, code, mfs);
|
|
6954
7675
|
if (!isCombinator(inner)) return null;
|
|
6955
|
-
const fnSrc =
|
|
7676
|
+
const fnSrc = stripTsFromSource(fnArg, code);
|
|
6956
7677
|
mfs.push(fnSrc);
|
|
6957
7678
|
try {
|
|
6958
7679
|
const combi = transform(inner, (v2) => v2);
|
|
@@ -6962,6 +7683,21 @@ function exprToCombi(node2, scope, code, mfs) {
|
|
|
6962
7683
|
return null;
|
|
6963
7684
|
}
|
|
6964
7685
|
}
|
|
7686
|
+
if (callee.name === "leaf" && code !== void 0 && mfs !== void 0) {
|
|
7687
|
+
const [parserArg, fnArg] = node2.arguments;
|
|
7688
|
+
if (!parserArg || !fnArg || parserArg.type === "SpreadElement" || fnArg.type === "SpreadElement") return null;
|
|
7689
|
+
const inner = anyValue(parserArg, scope, code, mfs);
|
|
7690
|
+
if (!isCombinator(inner)) return null;
|
|
7691
|
+
const fnSrc = stripTsFromSource(fnArg, code);
|
|
7692
|
+
mfs.push(fnSrc);
|
|
7693
|
+
try {
|
|
7694
|
+
const combi = leaf(inner, (v2) => v2);
|
|
7695
|
+
if (combi._def.tag === "leaf") combi._def.fnSrc = fnSrc;
|
|
7696
|
+
return combi;
|
|
7697
|
+
} catch {
|
|
7698
|
+
return null;
|
|
7699
|
+
}
|
|
7700
|
+
}
|
|
6965
7701
|
if (callee.name === "node" && code !== void 0) {
|
|
6966
7702
|
const [firstArg, secondArg, thirdArg, fourthArg] = node2.arguments;
|
|
6967
7703
|
if (!firstArg || firstArg.type === "SpreadElement") return null;
|
|
@@ -6975,11 +7711,15 @@ function exprToCombi(node2, scope, code, mfs) {
|
|
|
6975
7711
|
if (!isCombinator(inner)) return null;
|
|
6976
7712
|
const be = buildArg;
|
|
6977
7713
|
const hasBuild = be !== void 0 && be.type !== "SpreadElement" && !(be.type === "Identifier" && be.name === "undefined");
|
|
6978
|
-
const buildSrc = hasBuild ?
|
|
7714
|
+
const buildSrc = hasBuild ? stripTsFromSource(be, code) : void 0;
|
|
6979
7715
|
const opts = optsArg !== void 0 && optsArg.type !== "SpreadElement" ? staticNodeOptions(optsArg) : void 0;
|
|
6980
7716
|
try {
|
|
6981
7717
|
const combi = explicitType !== void 0 ? node(explicitType, inner, hasBuild ? () => null : void 0, opts) : node(inner, hasBuild ? () => null : void 0, opts);
|
|
6982
|
-
if (combi._def.tag === "node" && buildSrc !== void 0)
|
|
7718
|
+
if (combi._def.tag === "node" && buildSrc !== void 0) {
|
|
7719
|
+
combi._def.buildSrc = buildSrc;
|
|
7720
|
+
const staticError = directBuilderUnsupportedBindings(buildSrc);
|
|
7721
|
+
if (staticError.length > 0) combi._def.buildStaticError = staticError;
|
|
7722
|
+
}
|
|
6983
7723
|
return combi;
|
|
6984
7724
|
} catch {
|
|
6985
7725
|
return null;
|
|
@@ -7072,7 +7812,7 @@ function exprToCombi(node2, scope, code, mfs) {
|
|
|
7072
7812
|
if (code === void 0 || mfs === void 0) return null;
|
|
7073
7813
|
const [predArg] = node2.arguments;
|
|
7074
7814
|
if (!predArg || predArg.type === "SpreadElement") return null;
|
|
7075
|
-
const predSrc =
|
|
7815
|
+
const predSrc = stripTsFromSource(predArg, code);
|
|
7076
7816
|
mfs.push(predSrc);
|
|
7077
7817
|
try {
|
|
7078
7818
|
const combi = guard(() => true);
|
|
@@ -7087,7 +7827,7 @@ function exprToCombi(node2, scope, code, mfs) {
|
|
|
7087
7827
|
if (code === void 0 || mfs === void 0) return null;
|
|
7088
7828
|
const [extraArg, innerArg] = node2.arguments;
|
|
7089
7829
|
if (!extraArg || !innerArg || extraArg.type === "SpreadElement" || innerArg.type === "SpreadElement") return null;
|
|
7090
|
-
const extraSrc =
|
|
7830
|
+
const extraSrc = stripTsFromSource(extraArg, code);
|
|
7091
7831
|
mfs.push(extraSrc);
|
|
7092
7832
|
const inner = anyValue(innerArg, scope, code, mfs);
|
|
7093
7833
|
if (!isCombinator(inner)) return null;
|
|
@@ -7410,6 +8150,63 @@ function getCompiledResolver() {
|
|
|
7410
8150
|
mainFields: ["module", "main"]
|
|
7411
8151
|
});
|
|
7412
8152
|
}
|
|
8153
|
+
var PRIVATE_SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".mts", ".cts"]);
|
|
8154
|
+
function nearestPackageRoot(file) {
|
|
8155
|
+
let dir = path.dirname(file);
|
|
8156
|
+
for (; ; ) {
|
|
8157
|
+
try {
|
|
8158
|
+
if (fs.statSync(path.join(dir, "package.json")).isFile()) return fs.realpathSync(dir);
|
|
8159
|
+
} catch {
|
|
8160
|
+
}
|
|
8161
|
+
const parent = path.dirname(dir);
|
|
8162
|
+
if (parent === dir) return null;
|
|
8163
|
+
dir = parent;
|
|
8164
|
+
}
|
|
8165
|
+
}
|
|
8166
|
+
function isWithinPackageRoot(file, root) {
|
|
8167
|
+
const relative2 = path.relative(root, file);
|
|
8168
|
+
return relative2 !== ".." && !relative2.startsWith(`..${path.sep}`) && !path.isAbsolute(relative2);
|
|
8169
|
+
}
|
|
8170
|
+
function resolvePrivateSourceModule(from, specifier) {
|
|
8171
|
+
if (!specifier.startsWith(".") && !path.isAbsolute(specifier)) return null;
|
|
8172
|
+
const packageRoot = nearestPackageRoot(from);
|
|
8173
|
+
if (!packageRoot) return null;
|
|
8174
|
+
const base = path.resolve(path.dirname(from), specifier);
|
|
8175
|
+
const ext = path.extname(base);
|
|
8176
|
+
const candidates = [
|
|
8177
|
+
base,
|
|
8178
|
+
...ext ? [".ts", ".tsx", ".mts", ".cts"].map((next) => `${base.slice(0, -ext.length)}${next}`) : [],
|
|
8179
|
+
...!ext ? [".ts", ".tsx", ".mts", ".cts"].map((next) => `${base}${next}`) : [],
|
|
8180
|
+
...!ext ? ["index.ts", "index.tsx", "index.mts", "index.cts"].map((next) => path.join(base, next)) : []
|
|
8181
|
+
];
|
|
8182
|
+
for (const candidate of candidates) {
|
|
8183
|
+
try {
|
|
8184
|
+
if (!fs.statSync(candidate).isFile()) continue;
|
|
8185
|
+
const real = fs.realpathSync(candidate);
|
|
8186
|
+
if (isWithinPackageRoot(real, packageRoot)) return real;
|
|
8187
|
+
} catch {
|
|
8188
|
+
}
|
|
8189
|
+
}
|
|
8190
|
+
return null;
|
|
8191
|
+
}
|
|
8192
|
+
function resolveGrammarModule(from, specifier) {
|
|
8193
|
+
if (PRIVATE_SOURCE_EXTENSIONS.has(path.extname(specifier))) {
|
|
8194
|
+
const file2 = resolvePrivateSourceModule(from, specifier);
|
|
8195
|
+
return file2 ? { file: file2, source: true } : null;
|
|
8196
|
+
}
|
|
8197
|
+
try {
|
|
8198
|
+
const file2 = getCompiledResolver().resolveFileSync(from, specifier).path;
|
|
8199
|
+
if (file2) return { file: file2, source: false };
|
|
8200
|
+
} catch {
|
|
8201
|
+
}
|
|
8202
|
+
const file = resolvePrivateSourceModule(from, specifier);
|
|
8203
|
+
return file ? { file, source: true } : null;
|
|
8204
|
+
}
|
|
8205
|
+
var _sourceLowering = /* @__PURE__ */ new Set();
|
|
8206
|
+
var _sourceLoweringCache = /* @__PURE__ */ new Map();
|
|
8207
|
+
function sourceLoweringCacheKey(file, moduleAliases, warnUnloweredRegex, recovery) {
|
|
8208
|
+
return `${file}\0${[...moduleAliases].sort().join("\0")}\0${warnUnloweredRegex ? "warn" : ""}\0${recovery ? "recovery" : ""}`;
|
|
8209
|
+
}
|
|
7413
8210
|
var _moduleParseCache = /* @__PURE__ */ new Map();
|
|
7414
8211
|
function parseModuleCached(filePath) {
|
|
7415
8212
|
let mtimeMs;
|
|
@@ -7423,7 +8220,7 @@ function parseModuleCached(filePath) {
|
|
|
7423
8220
|
let parsed = null;
|
|
7424
8221
|
try {
|
|
7425
8222
|
const src = fs.readFileSync(filePath, "utf8");
|
|
7426
|
-
const r =
|
|
8223
|
+
const r = parseSync2(filePath, src);
|
|
7427
8224
|
if (r.errors.length === 0) parsed = { body: r.program.body, src };
|
|
7428
8225
|
} catch {
|
|
7429
8226
|
}
|
|
@@ -7443,7 +8240,7 @@ var plugin_default = createUnplugin((opts = {}) => ({
|
|
|
7443
8240
|
if (!code.includes("parseman")) return null;
|
|
7444
8241
|
if (!code.includes("macro")) return null;
|
|
7445
8242
|
const moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE, ...opts.moduleAliases ?? []]);
|
|
7446
|
-
const result = transformMacro(code, id, moduleAliases, opts.warnUnloweredRegex === true, opts.recovery === true);
|
|
8243
|
+
const result = transformMacro(code, id, moduleAliases, opts.warnUnloweredRegex === true, opts.recovery === true, opts.grammarCoverage === true);
|
|
7447
8244
|
if (result?.warnings.length) {
|
|
7448
8245
|
for (const w of result.warnings) {
|
|
7449
8246
|
if (typeof this?.warn === "function") this.warn(`[parseman] ${w}`);
|
|
@@ -7547,10 +8344,37 @@ function extractImportBindings(body) {
|
|
|
7547
8344
|
}
|
|
7548
8345
|
return out;
|
|
7549
8346
|
}
|
|
7550
|
-
function
|
|
8347
|
+
function lowerPrivateSourceModule(file, moduleAliases, warnUnloweredRegex, recovery) {
|
|
8348
|
+
if (_sourceLowering.has(file)) return null;
|
|
8349
|
+
let mtimeMs;
|
|
8350
|
+
try {
|
|
8351
|
+
mtimeMs = fs.statSync(file).mtimeMs;
|
|
8352
|
+
} catch {
|
|
8353
|
+
return null;
|
|
8354
|
+
}
|
|
8355
|
+
const cacheKey = sourceLoweringCacheKey(file, moduleAliases, warnUnloweredRegex, recovery);
|
|
8356
|
+
const hit = _sourceLoweringCache.get(cacheKey);
|
|
8357
|
+
if (hit && hit.mtimeMs === mtimeMs) return hit.parsed;
|
|
8358
|
+
_sourceLowering.add(file);
|
|
8359
|
+
let parsedModule = null;
|
|
8360
|
+
try {
|
|
8361
|
+
const source = fs.readFileSync(file, "utf8");
|
|
8362
|
+
const transformed = transformMacro(source, file, moduleAliases, warnUnloweredRegex, recovery);
|
|
8363
|
+
if (!transformed || transformed.warnings.length > 0) return null;
|
|
8364
|
+
const parsed = parseSync2(file, transformed.code);
|
|
8365
|
+
parsedModule = parsed.errors.length === 0 ? { body: parsed.program.body, src: transformed.code } : null;
|
|
8366
|
+
return parsedModule;
|
|
8367
|
+
} catch {
|
|
8368
|
+
return null;
|
|
8369
|
+
} finally {
|
|
8370
|
+
_sourceLoweringCache.set(cacheKey, { mtimeMs, parsed: parsedModule });
|
|
8371
|
+
_sourceLowering.delete(file);
|
|
8372
|
+
}
|
|
8373
|
+
}
|
|
8374
|
+
function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE]), warnUnloweredRegex = false, recovery = false, grammarCoverage = false) {
|
|
7551
8375
|
let result;
|
|
7552
8376
|
try {
|
|
7553
|
-
result =
|
|
8377
|
+
result = parseSync2(id, code);
|
|
7554
8378
|
} catch {
|
|
7555
8379
|
return null;
|
|
7556
8380
|
}
|
|
@@ -7588,6 +8412,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7588
8412
|
const warnings = [];
|
|
7589
8413
|
beginLoweringCapture();
|
|
7590
8414
|
let anyUnresolved = false;
|
|
8415
|
+
let runtimeComposeFallback = false;
|
|
7591
8416
|
let ruleMapHolderCounter = 0;
|
|
7592
8417
|
const lineOf = (pos) => {
|
|
7593
8418
|
let line = 1;
|
|
@@ -7598,7 +8423,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7598
8423
|
anyUnresolved = true;
|
|
7599
8424
|
warnings.push(`${id}:${lineOf(pos)} \u2014 ${msg} (running via the interpreter; add the plugin or simplify the declaration to compile it)`);
|
|
7600
8425
|
};
|
|
7601
|
-
const
|
|
8426
|
+
const evaluateRulesFactory = (init, label2) => {
|
|
7602
8427
|
const args = init.arguments;
|
|
7603
8428
|
const arg0 = args[0];
|
|
7604
8429
|
const arg1 = args[1];
|
|
@@ -7618,15 +8443,21 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7618
8443
|
(p) => p.key?.name === "trivia"
|
|
7619
8444
|
)?.value : void 0;
|
|
7620
8445
|
const gTrivia = triviaValue ? evaluateExpr(triviaValue, scope, code, []) : void 0;
|
|
7621
|
-
|
|
8446
|
+
return { ruleMap, ...gTrivia ? { trivia: gTrivia } : {} };
|
|
8447
|
+
};
|
|
8448
|
+
const compileRulesFactory = (init, label2) => {
|
|
8449
|
+
const evaluated = evaluateRulesFactory(init, label2);
|
|
8450
|
+
if (!evaluated) return null;
|
|
8451
|
+
const compiled = compileRuleMap([...evaluated.ruleMap], { ...evaluated.trivia ? { trivia: evaluated.trivia } : {}, recovery, coverage: grammarCoverage });
|
|
7622
8452
|
if (!compiled) {
|
|
7623
8453
|
warn(init.start, `${label2}: rule map couldn't be inlined`);
|
|
7624
8454
|
return null;
|
|
7625
8455
|
}
|
|
7626
|
-
return { replacement: compiled.replacement, ruleMap, ...
|
|
8456
|
+
return { replacement: compiled.replacement, ruleMap: evaluated.ruleMap, ...compiled.coverageDefinitions ? { coverageDefinitions: compiled.coverageDefinitions } : {}, ...evaluated.trivia ? { trivia: evaluated.trivia } : {} };
|
|
7627
8457
|
};
|
|
7628
8458
|
const isRulesCall = (init) => init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "rules";
|
|
7629
8459
|
const isComposeCall = (init) => init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "compose";
|
|
8460
|
+
const isComposeLeafCall = (init) => init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "composeLeaf";
|
|
7630
8461
|
const isPickCall = (init) => init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "pick";
|
|
7631
8462
|
const localRuleMaps = /* @__PURE__ */ new Map();
|
|
7632
8463
|
const localGrammarTrivia = /* @__PURE__ */ new Map();
|
|
@@ -7636,18 +8467,29 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7636
8467
|
const mapLit = (m, stripVals = false) => `new Map([${[...m].map(
|
|
7637
8468
|
([k, v2]) => `[${JSON.stringify(k)}, ${JSON.stringify(stripVals && typeof v2 === "string" ? stripIndent(v2) : v2)}]`
|
|
7638
8469
|
).join(", ")}])`;
|
|
7639
|
-
return `{ ns: ${JSON.stringify(p.ns)}, keys: ${JSON.stringify(p.keys)}, prelude: ${JSON.stringify(p.prelude.map(stripIndent))}, ruleFns: ${mapLit(p.ruleFns, true)}, wrappers: ${mapLit(p.wrappers, true)}, firstSets: ${mapLit(p.firstSets)}, deps: ${mapLit(p.deps)}, needsEmptyTl: ${p.needsEmptyTl}, needsHostReads: ${p.needsHostReads}, mfFns: [], buildFns: [] }`;
|
|
8470
|
+
return `{ ns: ${JSON.stringify(p.ns)}, keys: ${JSON.stringify(p.keys)}, prelude: ${JSON.stringify(p.prelude.map(stripIndent))}, ruleFns: ${mapLit(p.ruleFns, true)}, wrappers: ${mapLit(p.wrappers, true)}, firstSets: ${mapLit(p.firstSets)}, deps: ${mapLit(p.deps)}, needsEmptyTl: ${p.needsEmptyTl}, needsHostReads: ${p.needsHostReads}, hasDirectBuilders: ${p.hasDirectBuilders === true}, isRecognitionOnly: ${p.isRecognitionOnly === true}, mfFns: [], buildFns: [] }`;
|
|
7640
8471
|
};
|
|
7641
8472
|
const isSpread = (it) => "__spreadLocal" in it;
|
|
7642
8473
|
const isIR = (it) => "ir" in it && !("ruleFns" in it);
|
|
7643
8474
|
const serializeItem = (it) => isSpread(it) ? `...(${it.__spreadLocal}[Symbol.for('parseman.composedPieces')] ?? [])` : isIR(it) ? `{ ns: ${JSON.stringify(it.ns)}, ir: ${JSON.stringify(it.ir)} }` : serializePieces(it);
|
|
7644
8475
|
const serializeList = (list) => `[${list.map(serializeItem).join(", ")}]`;
|
|
7645
8476
|
const withCarriedPieces = (grammarExpr, list) => `/* @__PURE__ */ Object.defineProperty(${grammarExpr}, Symbol.for('parseman.composedPieces'), { value: ${serializeList(list)}, enumerable: false })`;
|
|
8477
|
+
const withLeafMarker = (grammarExpr) => `/* @__PURE__ */ Object.defineProperty(${grammarExpr}, Symbol.for('parseman.leafComposed'), { value: true, enumerable: false })`;
|
|
8478
|
+
const withCoverageDefinitions = (grammarExpr, definitions) => !grammarCoverage ? grammarExpr : `/* @__PURE__ */ Object.defineProperty(${grammarExpr}, Symbol.for('parseman.grammarCoverageDefinitions'), { value: Object.freeze(${JSON.stringify(definitions)}.map(Object.freeze)), enumerable: false })`;
|
|
8479
|
+
const emittedCoverageDefinitions = (source) => {
|
|
8480
|
+
const ids = /* @__PURE__ */ new Set();
|
|
8481
|
+
for (const match of source.matchAll(/id:\s*"([^"]+)"/g)) ids.add(match[1]);
|
|
8482
|
+
return [...ids].sort().map((id2) => ({
|
|
8483
|
+
id: id2,
|
|
8484
|
+
kind: id2.startsWith("rule:") ? "rule" : id2.startsWith("label:") ? "label" : "choice-arm"
|
|
8485
|
+
}));
|
|
8486
|
+
};
|
|
7646
8487
|
const localComposedCarried = /* @__PURE__ */ new Map();
|
|
7647
8488
|
const localComposedTrivia = /* @__PURE__ */ new Map();
|
|
7648
8489
|
const importedPiecesCache = /* @__PURE__ */ new Map();
|
|
7649
|
-
const resolveModulePieces = (
|
|
7650
|
-
const
|
|
8490
|
+
const resolveModulePieces = (module, exportName, seen) => {
|
|
8491
|
+
const { file } = module;
|
|
8492
|
+
const mod = module.source ? lowerPrivateSourceModule(file, moduleAliases, warnUnloweredRegex, recovery) : parseModuleCached(file);
|
|
7651
8493
|
if (!mod) return null;
|
|
7652
8494
|
const localFor = exportLocalName(mod.body, exportName);
|
|
7653
8495
|
const initNode = localFor ? topLevelInit(mod.body, localFor) : null;
|
|
@@ -7666,12 +8508,10 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7666
8508
|
const b = imports.get(local);
|
|
7667
8509
|
let subPieces = [];
|
|
7668
8510
|
if (b) {
|
|
7669
|
-
|
|
7670
|
-
|
|
7671
|
-
|
|
7672
|
-
} catch {
|
|
8511
|
+
const subModule = resolveGrammarModule(file, b.source);
|
|
8512
|
+
if (subModule && !seen.has(subModule.file)) {
|
|
8513
|
+
subPieces = resolveModulePieces(subModule, b.imported, new Set(seen).add(subModule.file)) ?? [];
|
|
7673
8514
|
}
|
|
7674
|
-
if (subFile && !seen.has(subFile)) subPieces = resolveModulePieces(subFile, b.imported, new Set(seen).add(subFile)) ?? [];
|
|
7675
8515
|
}
|
|
7676
8516
|
stubNames.push(local);
|
|
7677
8517
|
stubVals.push({ [/* @__PURE__ */ Symbol.for("parseman.composedPieces")]: subPieces });
|
|
@@ -7688,29 +8528,56 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7688
8528
|
let result2 = null;
|
|
7689
8529
|
const binding = importBindings.get(localName);
|
|
7690
8530
|
if (binding) {
|
|
7691
|
-
|
|
7692
|
-
|
|
7693
|
-
file = getCompiledResolver().resolveFileSync(id, binding.source).path ?? null;
|
|
7694
|
-
} catch {
|
|
7695
|
-
}
|
|
7696
|
-
result2 = file ? resolveModulePieces(file, binding.imported, /* @__PURE__ */ new Set([file])) : null;
|
|
8531
|
+
const module = resolveGrammarModule(id, binding.source);
|
|
8532
|
+
result2 = module ? resolveModulePieces(module, binding.imported, /* @__PURE__ */ new Set([module.file])) : null;
|
|
7697
8533
|
}
|
|
7698
8534
|
importedPiecesCache.set(localName, result2);
|
|
7699
8535
|
return result2;
|
|
7700
8536
|
};
|
|
7701
|
-
const materializeCarried = (items, composing) => {
|
|
8537
|
+
const materializeCarried = (items, composing, captureTerminals = false) => {
|
|
7702
8538
|
const out = [];
|
|
7703
8539
|
for (const it of items) {
|
|
7704
8540
|
if (isSpread(it)) {
|
|
7705
|
-
for (const p of importedPieces(it.__spreadLocal) ?? []) out.push(materializePiece(p, composing));
|
|
8541
|
+
for (const p of importedPieces(it.__spreadLocal) ?? []) out.push(materializePiece(p, composing, captureTerminals));
|
|
7706
8542
|
} else if (isIR(it)) {
|
|
7707
|
-
out.push(materializePiece(it, composing));
|
|
8543
|
+
out.push(materializePiece(it, composing, captureTerminals));
|
|
7708
8544
|
} else {
|
|
7709
8545
|
out.push(it);
|
|
7710
8546
|
}
|
|
7711
8547
|
}
|
|
7712
8548
|
return out;
|
|
7713
8549
|
};
|
|
8550
|
+
const materializeLeafCoverage = (items, localRules, localNs, composing, captureTerminals = false) => {
|
|
8551
|
+
const sources = [];
|
|
8552
|
+
const add = (item) => {
|
|
8553
|
+
if (!isIR(item)) return false;
|
|
8554
|
+
sources.push({ ns: item.ns, rules: evalRuleMapIR(item.ir) });
|
|
8555
|
+
return true;
|
|
8556
|
+
};
|
|
8557
|
+
for (const item of items) {
|
|
8558
|
+
if (isSpread(item)) {
|
|
8559
|
+
const imported = importedPieces(item.__spreadLocal);
|
|
8560
|
+
if (!imported || !imported.every(add)) return null;
|
|
8561
|
+
} else if (!add(item)) return null;
|
|
8562
|
+
}
|
|
8563
|
+
sources.push({ ns: localNs, rules: [...localRules] });
|
|
8564
|
+
const winners = {};
|
|
8565
|
+
for (const source of sources) for (const [name, rule] of source.rules) winners[name] = rule;
|
|
8566
|
+
const plan = buildGrammarPlan(Object.values(winners), winners);
|
|
8567
|
+
const pieces = [];
|
|
8568
|
+
for (let index = 0; index < sources.length; index++) {
|
|
8569
|
+
const source = sources[index];
|
|
8570
|
+
const piece = compileLinkable(source.rules, source.ns, {
|
|
8571
|
+
...composing ? { trivia: composing } : {},
|
|
8572
|
+
recovery,
|
|
8573
|
+
...index < sources.length - 1 && captureTerminals ? { captureTerminals: true } : {},
|
|
8574
|
+
coverage: plan
|
|
8575
|
+
});
|
|
8576
|
+
if (!piece) return null;
|
|
8577
|
+
pieces.push(piece);
|
|
8578
|
+
}
|
|
8579
|
+
return pieces;
|
|
8580
|
+
};
|
|
7714
8581
|
const localCarried = (rm, label2, composing) => {
|
|
7715
8582
|
const entries = [...rm];
|
|
7716
8583
|
const ns = nsFor(label2);
|
|
@@ -7826,6 +8693,64 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7826
8693
|
return null;
|
|
7827
8694
|
}
|
|
7828
8695
|
};
|
|
8696
|
+
const compileComposeLeafCall = (init) => {
|
|
8697
|
+
const args = init.arguments;
|
|
8698
|
+
const arr = args[0];
|
|
8699
|
+
if (!arr || arr.type !== "ArrayExpression") {
|
|
8700
|
+
warn(init.start, "composeLeaf(): expected a static array of grammars");
|
|
8701
|
+
return null;
|
|
8702
|
+
}
|
|
8703
|
+
const elements = arr.elements;
|
|
8704
|
+
if (elements.length < 2) {
|
|
8705
|
+
warn(init.start, "composeLeaf(): needs imported recognition grammar(s) and one local rules() map");
|
|
8706
|
+
return null;
|
|
8707
|
+
}
|
|
8708
|
+
const localArg = elements[elements.length - 1];
|
|
8709
|
+
let localRules = null;
|
|
8710
|
+
if (isRulesCall(localArg)) {
|
|
8711
|
+
const evaluated = evaluateRulesFactory(localArg, `composeLeaf${init.start}`);
|
|
8712
|
+
localRules = evaluated?.ruleMap ?? null;
|
|
8713
|
+
} else if (localArg.type === "Identifier") {
|
|
8714
|
+
localRules = localRuleMaps.get(localArg.name) ?? null;
|
|
8715
|
+
}
|
|
8716
|
+
if (!localRules) {
|
|
8717
|
+
warn(init.start, "composeLeaf(): final argument must be a local rules() map");
|
|
8718
|
+
return null;
|
|
8719
|
+
}
|
|
8720
|
+
const composing = composingTrivia(elements);
|
|
8721
|
+
const carried = [];
|
|
8722
|
+
for (let i = 0; i < elements.length - 1; i++) {
|
|
8723
|
+
const r = argPieces(elements[i], `composeLeaf${init.start}_${i}`, composing);
|
|
8724
|
+
if (!r) {
|
|
8725
|
+
warn(init.start, `composeLeaf(): argument ${i} isn't a build-resolvable recognition grammar`);
|
|
8726
|
+
return null;
|
|
8727
|
+
}
|
|
8728
|
+
carried.push(...r.carried);
|
|
8729
|
+
}
|
|
8730
|
+
try {
|
|
8731
|
+
const localNs = nsFor(`composeLeaf${init.start}`);
|
|
8732
|
+
const plainLocalPiece = compileLinkable([...localRules], localNs, { ...composing ? { trivia: composing } : {}, recovery });
|
|
8733
|
+
if (!plainLocalPiece) {
|
|
8734
|
+
warn(init.start, "composeLeaf(): local rules could not be statically compiled");
|
|
8735
|
+
return null;
|
|
8736
|
+
}
|
|
8737
|
+
const recognitionPieces = grammarCoverage ? materializeLeafCoverage(carried, localRules, localNs, composing, plainLocalPiece.hasDirectBuilders === true) : materializeCarried(carried, composing, plainLocalPiece.hasDirectBuilders === true);
|
|
8738
|
+
if (!recognitionPieces) {
|
|
8739
|
+
warn(init.start, "composeLeaf(): coverage needs re-lowerable recognition IR");
|
|
8740
|
+
return null;
|
|
8741
|
+
}
|
|
8742
|
+
const importedRecognitionPieces = grammarCoverage ? recognitionPieces.slice(0, -1) : recognitionPieces;
|
|
8743
|
+
if (importedRecognitionPieces.some((piece) => piece.hasDirectBuilders !== false || piece.isRecognitionOnly !== true)) {
|
|
8744
|
+
warn(init.start, "composeLeaf(): every pre-final grammar must explicitly prove recognition-only");
|
|
8745
|
+
return null;
|
|
8746
|
+
}
|
|
8747
|
+
const replacement = withLeafMarker(emitFusedSource(grammarCoverage ? recognitionPieces : [...recognitionPieces, plainLocalPiece]));
|
|
8748
|
+
return { replacement: withCoverageDefinitions(replacement, emittedCoverageDefinitions(replacement)) };
|
|
8749
|
+
} catch (e) {
|
|
8750
|
+
warn(init.start, `composeLeaf(): ${e.message}`);
|
|
8751
|
+
return null;
|
|
8752
|
+
}
|
|
8753
|
+
};
|
|
7829
8754
|
const unwrapVd = (stmt) => stmt.type === "VariableDeclaration" ? stmt : stmt.type === "ExportNamedDeclaration" && stmt.declaration?.type === "VariableDeclaration" ? stmt.declaration : null;
|
|
7830
8755
|
const refNames = /* @__PURE__ */ new Set();
|
|
7831
8756
|
for (const stmt of body) {
|
|
@@ -7892,7 +8817,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7892
8817
|
const refEntry = scope.get(varName);
|
|
7893
8818
|
const refCombi = refEntry?.combi ?? null;
|
|
7894
8819
|
if (refCombi) {
|
|
7895
|
-
const compiled2 = compile(refCombi, void 0, { recovery });
|
|
8820
|
+
const compiled2 = compile(refCombi, void 0, { recovery, coverage: grammarCoverage });
|
|
7896
8821
|
if (compiled2.inlineExpression === null) {
|
|
7897
8822
|
warn(init.start, `"${varName}" is a ref() that couldn't be inlined (was .define() called with a static combinator?)`);
|
|
7898
8823
|
continue;
|
|
@@ -7906,7 +8831,10 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7906
8831
|
if (!compiledRules) continue;
|
|
7907
8832
|
localRuleMaps.set(varName, compiledRules.ruleMap);
|
|
7908
8833
|
if (compiledRules.trivia) localGrammarTrivia.set(varName, compiledRules.trivia);
|
|
7909
|
-
let replacement =
|
|
8834
|
+
let replacement = withCoverageDefinitions(
|
|
8835
|
+
compiledRules.replacement,
|
|
8836
|
+
compiledRules.coverageDefinitions?.length ? compiledRules.coverageDefinitions : emittedCoverageDefinitions(compiledRules.replacement)
|
|
8837
|
+
);
|
|
7910
8838
|
if (exportPrefix) {
|
|
7911
8839
|
const ns = nsFor(varName);
|
|
7912
8840
|
const pieces = compileLinkable([...compiledRules.ruleMap], ns, { recovery });
|
|
@@ -7920,11 +8848,22 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7920
8848
|
}
|
|
7921
8849
|
if (isComposeCall(init)) {
|
|
7922
8850
|
const fused = compileComposeCall(init);
|
|
7923
|
-
if (!fused)
|
|
8851
|
+
if (!fused) {
|
|
8852
|
+
runtimeComposeFallback = true;
|
|
8853
|
+
continue;
|
|
8854
|
+
}
|
|
7924
8855
|
localComposedCarried.set(varName, fused.carried);
|
|
7925
8856
|
if (fused.trivia) localComposedTrivia.set(varName, fused.trivia);
|
|
7926
8857
|
const replacement = exportPrefix ? withCarriedPieces(fused.replacement, fused.carried) : fused.replacement;
|
|
7927
|
-
replacements.push({ start: init.start, end: init.end, replacement });
|
|
8858
|
+
replacements.push({ start: init.start, end: init.end, replacement: withCoverageDefinitions(replacement, emittedCoverageDefinitions(replacement)) });
|
|
8859
|
+
continue;
|
|
8860
|
+
}
|
|
8861
|
+
if (isComposeLeafCall(init)) {
|
|
8862
|
+
const fused = compileComposeLeafCall(init);
|
|
8863
|
+
if (!fused) {
|
|
8864
|
+
throw new Error(`${id}:${lineOf(init.start)} \u2014 composeLeaf() must macro-fuse; runtime composition is forbidden`);
|
|
8865
|
+
}
|
|
8866
|
+
replacements.push({ start: init.start, end: init.end, replacement: fused.replacement });
|
|
7928
8867
|
continue;
|
|
7929
8868
|
}
|
|
7930
8869
|
const mapFnSources = [];
|
|
@@ -7945,7 +8884,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7945
8884
|
warn(init.start, `"${varName}" references a parseman macro import but isn't a statically-evaluable combinator`);
|
|
7946
8885
|
continue;
|
|
7947
8886
|
}
|
|
7948
|
-
const compiled = compile(parser2, void 0, { recovery });
|
|
8887
|
+
const compiled = compile(parser2, void 0, { recovery, coverage: grammarCoverage });
|
|
7949
8888
|
if (compiled.inlineExpression === null) {
|
|
7950
8889
|
warn(init.start, `"${varName}" couldn't be inlined (likely closes over a runtime value)`);
|
|
7951
8890
|
continue;
|
|
@@ -8020,7 +8959,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
8020
8959
|
ms.overwrite(imp.start, imp.end, stripped);
|
|
8021
8960
|
}
|
|
8022
8961
|
}
|
|
8023
|
-
for (const { start, end, replacement } of [
|
|
8962
|
+
for (const { start, end, replacement } of (runtimeComposeFallback ? [] : replacements).sort((a, b) => b.start - a.start)) {
|
|
8024
8963
|
ms.overwrite(start, end, replacement);
|
|
8025
8964
|
}
|
|
8026
8965
|
const unlowered = endLoweringCapture();
|