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.cjs
CHANGED
|
@@ -35,8 +35,9 @@ __export(plugin_exports, {
|
|
|
35
35
|
});
|
|
36
36
|
module.exports = __toCommonJS(plugin_exports);
|
|
37
37
|
var fs = __toESM(require("node:fs"), 1);
|
|
38
|
+
var path = __toESM(require("node:path"), 1);
|
|
38
39
|
var import_unplugin = require("unplugin");
|
|
39
|
-
var
|
|
40
|
+
var import_oxc_parser2 = require("oxc-parser");
|
|
40
41
|
var import_oxc_resolver = require("oxc-resolver");
|
|
41
42
|
var import_magic_string = __toESM(require("magic-string"), 1);
|
|
42
43
|
|
|
@@ -101,6 +102,7 @@ function matchesEmpty(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
101
102
|
case "label":
|
|
102
103
|
case "trivia":
|
|
103
104
|
case "token":
|
|
105
|
+
case "leaf":
|
|
104
106
|
case "expect":
|
|
105
107
|
case "withCtx":
|
|
106
108
|
case "node":
|
|
@@ -164,6 +166,7 @@ function firstSetOf(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
164
166
|
case "label":
|
|
165
167
|
case "trivia":
|
|
166
168
|
case "token":
|
|
169
|
+
case "leaf":
|
|
167
170
|
case "node":
|
|
168
171
|
case "grammar":
|
|
169
172
|
case "expect":
|
|
@@ -269,10 +272,10 @@ function beginCstNodeCapture(ctx) {
|
|
|
269
272
|
}
|
|
270
273
|
function finishCstBuf(buf) {
|
|
271
274
|
if (!buf) return { children: EMPTY, rawChildren: EMPTY, triviaLog: EMPTY_TL };
|
|
272
|
-
const
|
|
275
|
+
const children2 = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY);
|
|
273
276
|
const rawChildren = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY);
|
|
274
277
|
const triviaLog = buf.tl ?? EMPTY_TL;
|
|
275
|
-
return { children, rawChildren, triviaLog };
|
|
278
|
+
return { children: children2, rawChildren, triviaLog };
|
|
276
279
|
}
|
|
277
280
|
function endCstNodeCapture(ctx, saved) {
|
|
278
281
|
const materialized = finishCstBuf(ctx._cstBuf);
|
|
@@ -284,8 +287,8 @@ function endCstNodeCapture(ctx, saved) {
|
|
|
284
287
|
ctx.captureTrivia = saved.cap;
|
|
285
288
|
return materialized;
|
|
286
289
|
}
|
|
287
|
-
function pushCstLeaf(ctx,
|
|
288
|
-
pushCstChild(ctx,
|
|
290
|
+
function pushCstLeaf(ctx, leaf2) {
|
|
291
|
+
pushCstChild(ctx, leaf2, leaf2);
|
|
289
292
|
}
|
|
290
293
|
function pushCstChild(ctx, built, rawEntry) {
|
|
291
294
|
const b = ctx._cstBuf;
|
|
@@ -1015,10 +1018,13 @@ function deriveExpected(c) {
|
|
|
1015
1018
|
return def.parsers.flatMap(deriveExpected);
|
|
1016
1019
|
case "sequence":
|
|
1017
1020
|
return def.parsers.length > 0 ? deriveExpected(def.parsers[0]) : [];
|
|
1021
|
+
case "attempt":
|
|
1022
|
+
return deriveExpected(def.parser);
|
|
1018
1023
|
case "node":
|
|
1019
1024
|
case "grammar":
|
|
1020
1025
|
case "trivia":
|
|
1021
1026
|
case "token":
|
|
1027
|
+
case "leaf":
|
|
1022
1028
|
case "optional":
|
|
1023
1029
|
case "many":
|
|
1024
1030
|
case "oneOrMore":
|
|
@@ -1509,6 +1515,12 @@ function scanTrivia(input, cur, ctx) {
|
|
|
1509
1515
|
const tr = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
|
|
1510
1516
|
return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
|
|
1511
1517
|
}
|
|
1518
|
+
function consumeTrivia(input, cur, ctx) {
|
|
1519
|
+
if (!needsDeferredTriviaCommit(ctx)) return advanceTrivia(input, cur, ctx);
|
|
1520
|
+
const scan = scanTrivia(input, cur, ctx);
|
|
1521
|
+
scan.commit();
|
|
1522
|
+
return scan.end;
|
|
1523
|
+
}
|
|
1512
1524
|
function fastTriviaScanner(trivia2) {
|
|
1513
1525
|
const cached = fastTriviaCache.get(trivia2);
|
|
1514
1526
|
if (cached !== void 0) return cached;
|
|
@@ -1787,6 +1799,24 @@ function sequence(...parsers) {
|
|
|
1787
1799
|
};
|
|
1788
1800
|
}
|
|
1789
1801
|
|
|
1802
|
+
// src/combinators/attempt.ts
|
|
1803
|
+
function attempt(parser2) {
|
|
1804
|
+
return {
|
|
1805
|
+
_tag: "attempt",
|
|
1806
|
+
_meta: parser2._meta,
|
|
1807
|
+
_def: { tag: "attempt", parser: parser2 },
|
|
1808
|
+
parse(input, pos, ctx) {
|
|
1809
|
+
const mark = saveCstMark(ctx);
|
|
1810
|
+
const log = ctx._triviaLog?.length;
|
|
1811
|
+
const result = parser2.parse(input, pos, ctx);
|
|
1812
|
+
if (result.ok) return result;
|
|
1813
|
+
rollbackCstCapture(ctx, mark);
|
|
1814
|
+
if (log !== void 0 && ctx._triviaLog) ctx._triviaLog.length = log;
|
|
1815
|
+
return { ok: false, expected: result.expected, span: { start: pos, end: pos } };
|
|
1816
|
+
}
|
|
1817
|
+
};
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1790
1820
|
// src/combinators/repeat.ts
|
|
1791
1821
|
function repItem(combinator, input, cur, ctx) {
|
|
1792
1822
|
const mark = saveTriviaMark(ctx);
|
|
@@ -1962,19 +1992,19 @@ function sepBy(combinator, separator) {
|
|
|
1962
1992
|
sepPos = advanceTrivia(input, cur, ctx);
|
|
1963
1993
|
}
|
|
1964
1994
|
}
|
|
1965
|
-
const
|
|
1966
|
-
if (!
|
|
1995
|
+
const sep2 = separator.parse(input, sepPos, ctx);
|
|
1996
|
+
if (!sep2.ok) {
|
|
1967
1997
|
rollbackTrivia(ctx, loopMark);
|
|
1968
1998
|
break;
|
|
1969
1999
|
}
|
|
1970
|
-
let nextPos =
|
|
2000
|
+
let nextPos = sep2.span.end;
|
|
1971
2001
|
if (ctx.trivia) {
|
|
1972
2002
|
if (needsDeferredTriviaCommit(ctx)) {
|
|
1973
|
-
const scan = scanTrivia(input,
|
|
2003
|
+
const scan = scanTrivia(input, sep2.span.end, ctx);
|
|
1974
2004
|
scan.commit();
|
|
1975
2005
|
nextPos = scan.end;
|
|
1976
2006
|
} else {
|
|
1977
|
-
nextPos = advanceTrivia(input,
|
|
2007
|
+
nextPos = advanceTrivia(input, sep2.span.end, ctx);
|
|
1978
2008
|
}
|
|
1979
2009
|
}
|
|
1980
2010
|
const next = combinator.parse(input, nextPos, ctx);
|
|
@@ -2059,10 +2089,14 @@ function markUnusedValues(root) {
|
|
|
2059
2089
|
case "label":
|
|
2060
2090
|
case "trivia":
|
|
2061
2091
|
case "token":
|
|
2092
|
+
case "attempt":
|
|
2062
2093
|
case "withCtx":
|
|
2063
2094
|
case "expect":
|
|
2064
2095
|
visit(def.parser, consumed);
|
|
2065
2096
|
return;
|
|
2097
|
+
case "leaf":
|
|
2098
|
+
visit(def.parser, true);
|
|
2099
|
+
return;
|
|
2066
2100
|
case "lazy":
|
|
2067
2101
|
return;
|
|
2068
2102
|
default:
|
|
@@ -2185,6 +2219,20 @@ function confirmedBuildArity(src) {
|
|
|
2185
2219
|
if (/\barguments\b/.test(s)) return null;
|
|
2186
2220
|
return parts.length;
|
|
2187
2221
|
}
|
|
2222
|
+
function buildReadsChildren(def) {
|
|
2223
|
+
if (!def.build) return true;
|
|
2224
|
+
const src = def.buildSrc ?? def.build.toString();
|
|
2225
|
+
const arity = confirmedBuildArity(src);
|
|
2226
|
+
if (arity === null) return true;
|
|
2227
|
+
return arity >= 1;
|
|
2228
|
+
}
|
|
2229
|
+
function buildReadsRaw(def) {
|
|
2230
|
+
if (!def.build) return true;
|
|
2231
|
+
const src = def.buildSrc ?? def.build.toString();
|
|
2232
|
+
const arity = confirmedBuildArity(src);
|
|
2233
|
+
if (arity === null) return true;
|
|
2234
|
+
return arity >= 4;
|
|
2235
|
+
}
|
|
2188
2236
|
function buildReadsTrivia(def) {
|
|
2189
2237
|
if (!def.build) return true;
|
|
2190
2238
|
const src = def.buildSrc ?? def.build.toString();
|
|
@@ -2240,9 +2288,11 @@ function parserHasOwnFields(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
2240
2288
|
case "many":
|
|
2241
2289
|
case "oneOrMore":
|
|
2242
2290
|
case "optional":
|
|
2291
|
+
case "attempt":
|
|
2243
2292
|
case "transform":
|
|
2244
2293
|
case "trivia":
|
|
2245
2294
|
case "token":
|
|
2295
|
+
case "leaf":
|
|
2246
2296
|
case "label":
|
|
2247
2297
|
case "expect":
|
|
2248
2298
|
case "withCtx":
|
|
@@ -2275,9 +2325,11 @@ function parserHasTriviaSite(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
2275
2325
|
case "keywords":
|
|
2276
2326
|
case "guard":
|
|
2277
2327
|
case "token":
|
|
2328
|
+
case "leaf":
|
|
2278
2329
|
return false;
|
|
2279
2330
|
// Transparent single-child wrappers: recurse.
|
|
2280
2331
|
case "optional":
|
|
2332
|
+
case "attempt":
|
|
2281
2333
|
case "transform":
|
|
2282
2334
|
case "trivia":
|
|
2283
2335
|
case "label":
|
|
@@ -2301,6 +2353,54 @@ function parserHasTriviaSite(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
2301
2353
|
return true;
|
|
2302
2354
|
}
|
|
2303
2355
|
}
|
|
2356
|
+
function parserEnablesTriviaCapture(p, seen = /* @__PURE__ */ new Set()) {
|
|
2357
|
+
if (seen.has(p)) return false;
|
|
2358
|
+
seen.add(p);
|
|
2359
|
+
const d = p._def;
|
|
2360
|
+
switch (d.tag) {
|
|
2361
|
+
case "grammar":
|
|
2362
|
+
return d.captureTrivia === true || parserEnablesTriviaCapture(d.parser, seen);
|
|
2363
|
+
case "node":
|
|
2364
|
+
return false;
|
|
2365
|
+
case "sequence":
|
|
2366
|
+
case "choice":
|
|
2367
|
+
return d.parsers.some((x) => parserEnablesTriviaCapture(x, seen));
|
|
2368
|
+
case "sepBy":
|
|
2369
|
+
return parserEnablesTriviaCapture(d.parser, seen) || parserEnablesTriviaCapture(d.separator, seen);
|
|
2370
|
+
case "skip":
|
|
2371
|
+
return parserEnablesTriviaCapture(d.main, seen) || parserEnablesTriviaCapture(d.skipped, seen);
|
|
2372
|
+
case "scanTo":
|
|
2373
|
+
return parserEnablesTriviaCapture(d.sentinel, seen) || d.skip.some((x) => parserEnablesTriviaCapture(x, seen));
|
|
2374
|
+
case "recover":
|
|
2375
|
+
return parserEnablesTriviaCapture(d.parser, seen) || parserEnablesTriviaCapture(d.sentinel, seen);
|
|
2376
|
+
case "many":
|
|
2377
|
+
case "oneOrMore":
|
|
2378
|
+
case "optional":
|
|
2379
|
+
case "attempt":
|
|
2380
|
+
case "transform":
|
|
2381
|
+
case "trivia":
|
|
2382
|
+
case "token":
|
|
2383
|
+
case "label":
|
|
2384
|
+
case "field":
|
|
2385
|
+
case "expect":
|
|
2386
|
+
case "withCtx":
|
|
2387
|
+
case "not":
|
|
2388
|
+
return parserEnablesTriviaCapture(d.parser, seen);
|
|
2389
|
+
// leaf() clears the inner CST/trivia collector and publishes only its own
|
|
2390
|
+
// terminal result. An inner parser() capture cannot reach this node.
|
|
2391
|
+
case "leaf":
|
|
2392
|
+
return false;
|
|
2393
|
+
case "lazy": {
|
|
2394
|
+
try {
|
|
2395
|
+
return parserEnablesTriviaCapture(d.thunk(), seen);
|
|
2396
|
+
} catch {
|
|
2397
|
+
return false;
|
|
2398
|
+
}
|
|
2399
|
+
}
|
|
2400
|
+
default:
|
|
2401
|
+
return false;
|
|
2402
|
+
}
|
|
2403
|
+
}
|
|
2304
2404
|
function buildFieldMap(captures) {
|
|
2305
2405
|
if (!captures?.length) return void 0;
|
|
2306
2406
|
const out = {};
|
|
@@ -2338,11 +2438,13 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
2338
2438
|
};
|
|
2339
2439
|
const unwrap = opts?.unwrap === true;
|
|
2340
2440
|
const collapse = opts?.collapse === true;
|
|
2441
|
+
const captureTrivia = opts?.captureTrivia === true;
|
|
2442
|
+
const trailingTrivia = opts?.trailingTrivia === true;
|
|
2341
2443
|
if (unwrap && collapse) {
|
|
2342
2444
|
throw new Error("node() options cannot set both unwrap and collapse");
|
|
2343
2445
|
}
|
|
2344
|
-
const def = unwrap || collapse ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {} } : baseDef;
|
|
2345
|
-
const capturesTrivia = build ? buildReadsTrivia(def) : true;
|
|
2446
|
+
const def = unwrap || collapse || captureTrivia || trailingTrivia ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {}, ...captureTrivia ? { captureTrivia: true } : {}, ...trailingTrivia ? { trailingTrivia: true } : {} } : baseDef;
|
|
2447
|
+
const capturesTrivia = captureTrivia || trailingTrivia || (build ? buildReadsTrivia(def) : true);
|
|
2346
2448
|
const clonesState = build ? buildReadsState(def) : true;
|
|
2347
2449
|
const capturesFields = parserHasOwnFields(combinator) && (build ? buildReadsFields(def) : true);
|
|
2348
2450
|
return {
|
|
@@ -2358,16 +2460,21 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
2358
2460
|
ctx._triviaCaptureMask = ctx.build._parsemanTriviaKinds(def.type);
|
|
2359
2461
|
}
|
|
2360
2462
|
if (!capturesTrivia) ctx.captureTrivia = false;
|
|
2361
|
-
|
|
2463
|
+
let r = combinator.parse(input, pos, ctx);
|
|
2464
|
+
if (r.ok && trailingTrivia && ctx.trivia) {
|
|
2465
|
+
const end = consumeTrivia(input, r.span.end, ctx);
|
|
2466
|
+
r = { ...r, span: { start: r.span.start, end } };
|
|
2467
|
+
}
|
|
2362
2468
|
const fields = capturesFields ? buildFieldMap(ctx._fields) : void 0;
|
|
2363
2469
|
ctx._fields = savedFields;
|
|
2364
2470
|
ctx._triviaCaptureMask = savedMask;
|
|
2365
|
-
const { children, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
|
|
2471
|
+
const { children: children2, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
|
|
2366
2472
|
if (!r.ok) return r;
|
|
2367
2473
|
const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
|
|
2368
2474
|
const nodeType = def.type ?? missingInferredType();
|
|
2369
|
-
const
|
|
2370
|
-
const
|
|
2475
|
+
const cstOutput = ctx.build?._parsemanCstOutput === true;
|
|
2476
|
+
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 };
|
|
2477
|
+
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 };
|
|
2371
2478
|
if (saved.buf !== void 0 || saved.ch !== void 0) {
|
|
2372
2479
|
pushCstChild(ctx, built, rawEntry);
|
|
2373
2480
|
}
|
|
@@ -2484,6 +2591,7 @@ function parser(opts, root) {
|
|
|
2484
2591
|
parser: root,
|
|
2485
2592
|
triviaParser: clearTrivia ? void 0 : opts.trivia ?? void 0,
|
|
2486
2593
|
clearTrivia,
|
|
2594
|
+
...opts.captureTrivia ? { captureTrivia: true } : {},
|
|
2487
2595
|
trackLines: opts.trackLines ?? false
|
|
2488
2596
|
},
|
|
2489
2597
|
parse(input, pos, _ctx) {
|
|
@@ -2571,6 +2679,141 @@ function token(root) {
|
|
|
2571
2679
|
}
|
|
2572
2680
|
};
|
|
2573
2681
|
}
|
|
2682
|
+
function leaf(root, fn) {
|
|
2683
|
+
const meta = {
|
|
2684
|
+
firstSet: root._meta.firstSet,
|
|
2685
|
+
canMatchNewline: root._meta.canMatchNewline,
|
|
2686
|
+
isTrivia: false
|
|
2687
|
+
};
|
|
2688
|
+
return {
|
|
2689
|
+
_tag: "leaf",
|
|
2690
|
+
_meta: meta,
|
|
2691
|
+
_def: { tag: "leaf", parser: root, fn },
|
|
2692
|
+
parse(input, pos, ctx) {
|
|
2693
|
+
const savedBuf = ctx._cstBuf;
|
|
2694
|
+
const savedChildren = ctx._cstChildren;
|
|
2695
|
+
const savedLeaves = ctx._cstLeaves;
|
|
2696
|
+
const savedRaw = ctx._cstRawChildren;
|
|
2697
|
+
const savedTriviaLog = ctx._cstTriviaLog;
|
|
2698
|
+
const savedOuterTriviaLog = ctx._triviaLog;
|
|
2699
|
+
const wasCapturing = cstCaptureActive(ctx);
|
|
2700
|
+
ctx._cstBuf = void 0;
|
|
2701
|
+
ctx._cstChildren = void 0;
|
|
2702
|
+
ctx._cstLeaves = void 0;
|
|
2703
|
+
ctx._cstRawChildren = void 0;
|
|
2704
|
+
ctx._cstTriviaLog = void 0;
|
|
2705
|
+
delete ctx._triviaLog;
|
|
2706
|
+
let result;
|
|
2707
|
+
try {
|
|
2708
|
+
result = root.parse(input, pos, ctx);
|
|
2709
|
+
} finally {
|
|
2710
|
+
ctx._cstBuf = savedBuf;
|
|
2711
|
+
ctx._cstChildren = savedChildren;
|
|
2712
|
+
ctx._cstLeaves = savedLeaves;
|
|
2713
|
+
ctx._cstRawChildren = savedRaw;
|
|
2714
|
+
ctx._cstTriviaLog = savedTriviaLog;
|
|
2715
|
+
if (savedOuterTriviaLog === void 0) delete ctx._triviaLog;
|
|
2716
|
+
else ctx._triviaLog = savedOuterTriviaLog;
|
|
2717
|
+
}
|
|
2718
|
+
if (!result.ok) return result;
|
|
2719
|
+
const value = fn(result.value, result.span);
|
|
2720
|
+
if (wasCapturing) pushCstLeaf(ctx, { _tag: "leaf", value, span: result.span });
|
|
2721
|
+
return { ok: true, value, span: result.span };
|
|
2722
|
+
}
|
|
2723
|
+
};
|
|
2724
|
+
}
|
|
2725
|
+
|
|
2726
|
+
// src/compiler/grammar-coverage-ids.ts
|
|
2727
|
+
function children(def, winners) {
|
|
2728
|
+
switch (def.tag) {
|
|
2729
|
+
case "sequence":
|
|
2730
|
+
case "choice":
|
|
2731
|
+
return def.parsers;
|
|
2732
|
+
case "many":
|
|
2733
|
+
case "oneOrMore":
|
|
2734
|
+
case "optional":
|
|
2735
|
+
case "attempt":
|
|
2736
|
+
case "transform":
|
|
2737
|
+
case "trivia":
|
|
2738
|
+
case "token":
|
|
2739
|
+
case "leaf":
|
|
2740
|
+
case "label":
|
|
2741
|
+
case "field":
|
|
2742
|
+
case "grammar":
|
|
2743
|
+
case "not":
|
|
2744
|
+
case "node":
|
|
2745
|
+
case "guard":
|
|
2746
|
+
case "withCtx":
|
|
2747
|
+
case "recover":
|
|
2748
|
+
case "expect":
|
|
2749
|
+
return "parser" in def ? [def.parser] : [];
|
|
2750
|
+
case "sepBy":
|
|
2751
|
+
return [def.parser, def.separator];
|
|
2752
|
+
case "skip":
|
|
2753
|
+
return [def.main, def.skipped];
|
|
2754
|
+
case "scanTo":
|
|
2755
|
+
return [def.sentinel, ...def.skip];
|
|
2756
|
+
case "lazy": {
|
|
2757
|
+
let resolved;
|
|
2758
|
+
try {
|
|
2759
|
+
resolved = def.thunk();
|
|
2760
|
+
} catch {
|
|
2761
|
+
return [];
|
|
2762
|
+
}
|
|
2763
|
+
const name = resolved._ruleName;
|
|
2764
|
+
return name && winners?.[name] ? [winners[name]] : [resolved];
|
|
2765
|
+
}
|
|
2766
|
+
default:
|
|
2767
|
+
return [];
|
|
2768
|
+
}
|
|
2769
|
+
}
|
|
2770
|
+
function buildGrammarPlan(entry, winners) {
|
|
2771
|
+
const definitions = /* @__PURE__ */ new Map();
|
|
2772
|
+
const choices = /* @__PURE__ */ new WeakMap();
|
|
2773
|
+
const attempts = /* @__PURE__ */ new WeakMap();
|
|
2774
|
+
const labels = /* @__PURE__ */ new WeakMap();
|
|
2775
|
+
const rules2 = /* @__PURE__ */ new WeakMap();
|
|
2776
|
+
const winnerNames = /* @__PURE__ */ new Map();
|
|
2777
|
+
if (winners) {
|
|
2778
|
+
for (const [name, winner] of Object.entries(winners)) {
|
|
2779
|
+
winnerNames.set(winner, name);
|
|
2780
|
+
if (winner._def.tag === "lazy") {
|
|
2781
|
+
try {
|
|
2782
|
+
winnerNames.set(winner._def.thunk(), name);
|
|
2783
|
+
} catch {
|
|
2784
|
+
}
|
|
2785
|
+
}
|
|
2786
|
+
}
|
|
2787
|
+
}
|
|
2788
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2789
|
+
const visit = (parser2, path2) => {
|
|
2790
|
+
if (seen.has(parser2)) return;
|
|
2791
|
+
seen.add(parser2);
|
|
2792
|
+
const rule = winnerNames.get(parser2) ?? parser2._ruleName;
|
|
2793
|
+
if (rule && (winnerNames.has(parser2) || parser2._def.tag !== "lazy")) {
|
|
2794
|
+
const id = `rule:${rule}`;
|
|
2795
|
+
definitions.set(id, { id, kind: "rule" });
|
|
2796
|
+
rules2.set(parser2, id);
|
|
2797
|
+
}
|
|
2798
|
+
if (parser2._def.tag === "choice") {
|
|
2799
|
+
const ids = parser2._def.parsers.map((_, index) => `choice:${path2}/arm:${index}`);
|
|
2800
|
+
choices.set(parser2, ids);
|
|
2801
|
+
ids.forEach((id) => definitions.set(id, { id, kind: "choice-arm" }));
|
|
2802
|
+
}
|
|
2803
|
+
if (parser2._def.tag === "attempt") attempts.set(parser2, `attempt:${path2}`);
|
|
2804
|
+
if (parser2._def.tag === "label") {
|
|
2805
|
+
const id = `label:${path2}`;
|
|
2806
|
+
labels.set(parser2, [id]);
|
|
2807
|
+
definitions.set(id, { id, kind: "label" });
|
|
2808
|
+
}
|
|
2809
|
+
children(parser2._def, winners).forEach((child, index) => visit(child, `${path2}/${parser2._def.tag}:${index}`));
|
|
2810
|
+
};
|
|
2811
|
+
const roots = Array.isArray(entry) ? entry : [entry];
|
|
2812
|
+
for (const root of roots) {
|
|
2813
|
+
visit(root, winnerNames.get(root) ?? root._ruleName ?? "entry");
|
|
2814
|
+
}
|
|
2815
|
+
return { definitions: [...definitions.values()].sort((a, b) => a.id.localeCompare(b.id)), choices, attempts, labels, rules: rules2 };
|
|
2816
|
+
}
|
|
2574
2817
|
|
|
2575
2818
|
// src/compiler/scannable-run.ts
|
|
2576
2819
|
var BACKSLASH = 92;
|
|
@@ -3620,7 +3863,7 @@ function scanBranchLabeled(shape, kindIndex, mint) {
|
|
|
3620
3863
|
` if (${m.end} > _e) {`,
|
|
3621
3864
|
` if (_cap) {`,
|
|
3622
3865
|
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, ${m.end}, ${kindIndex})`,
|
|
3623
|
-
` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << kindIndex}))) _ctx._cstTriviaLog.push(_e, ${m.end}, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${kindIndex})`,
|
|
3866
|
+
` 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})`,
|
|
3624
3867
|
` }`,
|
|
3625
3868
|
` _e = ${m.end}`,
|
|
3626
3869
|
` continue`,
|
|
@@ -3676,7 +3919,7 @@ function analyzeTriviaFastPath(trivia2) {
|
|
|
3676
3919
|
var CAP_RECORD = [
|
|
3677
3920
|
` if (_cap && _e > _pos) {`,
|
|
3678
3921
|
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
|
|
3679
|
-
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
|
|
3922
|
+
` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
|
|
3680
3923
|
` }`
|
|
3681
3924
|
].join("\n");
|
|
3682
3925
|
function composeFastLoop(shapes) {
|
|
@@ -3736,7 +3979,7 @@ function buildLabeledRegexTriviaFnDecl(fnName, spec, reNames) {
|
|
|
3736
3979
|
` const _ce = _e + _m${i}[0].length`,
|
|
3737
3980
|
` if (_cap) {`,
|
|
3738
3981
|
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
|
|
3739
|
-
` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
|
|
3982
|
+
` 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})`,
|
|
3740
3983
|
` }`,
|
|
3741
3984
|
` _e = _ce`,
|
|
3742
3985
|
` _matched = true`,
|
|
@@ -3774,7 +4017,7 @@ function buildLabeledRuntimeTriviaFnDecl(fnName, spec, rpStartIndex) {
|
|
|
3774
4017
|
` const _ce = _r${i}.span.end`,
|
|
3775
4018
|
` if (_cap) {`,
|
|
3776
4019
|
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
|
|
3777
|
-
` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
|
|
4020
|
+
` 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})`,
|
|
3778
4021
|
` }`,
|
|
3779
4022
|
` _e = _ce`,
|
|
3780
4023
|
` _matched = true`,
|
|
@@ -3963,21 +4206,23 @@ function probeUpdate(ctx, expectedArr, posExpr, constant = true) {
|
|
|
3963
4206
|
}
|
|
3964
4207
|
function failBody(ctx, expected, posExpr) {
|
|
3965
4208
|
const probe = probeUpdate(ctx, `[${expected}]`, posExpr);
|
|
4209
|
+
const trace = ctx.activeCoverageRuleId === void 0 ? "" : `_ctx._grammarTrace?.write({ id: ${JSON.stringify(ctx.activeCoverageRuleId)}, phase: 'failure', offset: ${posExpr} }); `;
|
|
3966
4210
|
if (ctx.failLabel) {
|
|
3967
|
-
if (!ctx.recordFail) return probe ? `{ ${probe}break ${ctx.failLabel} }` : `break ${ctx.failLabel}`;
|
|
3968
|
-
return `{ ${probe}_ctx._fe = ${posExpr}; _ctx._fx = ${hoistExpected(ctx, `[${expected}]`)}; break ${ctx.failLabel} }`;
|
|
4211
|
+
if (!ctx.recordFail) return probe ? `{ ${probe}${trace}break ${ctx.failLabel} }` : trace ? `{ ${trace}break ${ctx.failLabel} }` : `break ${ctx.failLabel}`;
|
|
4212
|
+
return `{ ${probe}_ctx._fe = ${posExpr}; _ctx._fx = ${hoistExpected(ctx, `[${expected}]`)}; ${trace}break ${ctx.failLabel} }`;
|
|
3969
4213
|
}
|
|
3970
|
-
return probe + failReturn(expected, posExpr);
|
|
4214
|
+
return probe + trace + failReturn(expected, posExpr);
|
|
3971
4215
|
}
|
|
3972
4216
|
function failArrBody(ctx, expectedArr, posExpr, constant = true) {
|
|
3973
4217
|
const probe = probeUpdate(ctx, expectedArr, posExpr, constant);
|
|
4218
|
+
const trace = ctx.activeCoverageRuleId === void 0 ? "" : `_ctx._grammarTrace?.write({ id: ${JSON.stringify(ctx.activeCoverageRuleId)}, phase: 'failure', offset: ${posExpr} }); `;
|
|
3974
4219
|
if (ctx.failLabel) {
|
|
3975
|
-
if (!ctx.recordFail) return probe ? `{ ${probe}break ${ctx.failLabel} }` : `break ${ctx.failLabel}`;
|
|
4220
|
+
if (!ctx.recordFail) return probe ? `{ ${probe}${trace}break ${ctx.failLabel} }` : trace ? `{ ${trace}break ${ctx.failLabel} }` : `break ${ctx.failLabel}`;
|
|
3976
4221
|
const fx = constant ? hoistExpected(ctx, expectedArr) : expectedArr;
|
|
3977
|
-
return `{ ${probe}_ctx._fe = ${posExpr}; _ctx._fx = ${fx}; break ${ctx.failLabel} }`;
|
|
4222
|
+
return `{ ${probe}_ctx._fe = ${posExpr}; _ctx._fx = ${fx}; ${trace}break ${ctx.failLabel} }`;
|
|
3978
4223
|
}
|
|
3979
|
-
if (!constant) return `${probe}return { ok: false, expected: [...${expectedArr}], span: { start: ${posExpr}, end: ${posExpr} } }`;
|
|
3980
|
-
return probe + failReturnArr(expectedArr, posExpr);
|
|
4224
|
+
if (!constant) return `${probe}${trace}return { ok: false, expected: [...${expectedArr}], span: { start: ${posExpr}, end: ${posExpr} } }`;
|
|
4225
|
+
return probe + trace + failReturnArr(expectedArr, posExpr);
|
|
3981
4226
|
}
|
|
3982
4227
|
function resultFromRecorded(feExpr = "_ctx._fe", fxExpr = "_ctx._fx") {
|
|
3983
4228
|
return `return { ok: false, expected: [...${fxExpr}], span: { start: ${feExpr}, end: ${feExpr} } }`;
|
|
@@ -4012,7 +4257,7 @@ var NAMED_FN_END = "_pfEnd";
|
|
|
4012
4257
|
function namedFnPrelude() {
|
|
4013
4258
|
return [`const ${NAMED_FN_FAIL} = {}`, `let ${NAMED_FN_END}`];
|
|
4014
4259
|
}
|
|
4015
|
-
function pushNamedFnDecl(ctx, fnName, bodyStmts, valueVar, endVar) {
|
|
4260
|
+
function pushNamedFnDecl(ctx, fnName, bodyStmts, valueVar, endVar, failureRuleId) {
|
|
4016
4261
|
ctx.namedFnDecls.push([
|
|
4017
4262
|
`function ${fnName}(input, _pos, _ctx) {`,
|
|
4018
4263
|
` _pfail: {`,
|
|
@@ -4020,6 +4265,7 @@ function pushNamedFnDecl(ctx, fnName, bodyStmts, valueVar, endVar) {
|
|
|
4020
4265
|
` ${NAMED_FN_END} = ${endVar}`,
|
|
4021
4266
|
` return ${valueVar}`,
|
|
4022
4267
|
` }`,
|
|
4268
|
+
...failureRuleId === void 0 ? [] : [` _ctx._grammarTrace?.write({ id: ${JSON.stringify(failureRuleId)}, phase: 'failure', offset: _ctx._fe ?? _pos })`],
|
|
4023
4269
|
` return ${NAMED_FN_FAIL}`,
|
|
4024
4270
|
`}`
|
|
4025
4271
|
].join("\n"));
|
|
@@ -4125,7 +4371,7 @@ function ensureTriviaFn(ctx) {
|
|
|
4125
4371
|
` }`,
|
|
4126
4372
|
` if (_cap && _e > _pos) {`,
|
|
4127
4373
|
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
|
|
4128
|
-
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
|
|
4374
|
+
` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
|
|
4129
4375
|
` }`,
|
|
4130
4376
|
` return _e`,
|
|
4131
4377
|
`}`
|
|
@@ -4181,6 +4427,7 @@ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
4181
4427
|
case "not":
|
|
4182
4428
|
case "trivia":
|
|
4183
4429
|
case "token":
|
|
4430
|
+
case "leaf":
|
|
4184
4431
|
case "scanTo":
|
|
4185
4432
|
case "unknown":
|
|
4186
4433
|
return false;
|
|
@@ -4192,6 +4439,8 @@ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
4192
4439
|
// nothing committed remains.
|
|
4193
4440
|
case "choice":
|
|
4194
4441
|
return false;
|
|
4442
|
+
case "attempt":
|
|
4443
|
+
return false;
|
|
4195
4444
|
// optional never fails; many/oneOrMore only "fail" with zero captured items.
|
|
4196
4445
|
case "optional":
|
|
4197
4446
|
case "many":
|
|
@@ -4244,6 +4493,7 @@ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
4244
4493
|
case "keywords":
|
|
4245
4494
|
case "node":
|
|
4246
4495
|
case "token":
|
|
4496
|
+
case "leaf":
|
|
4247
4497
|
return true;
|
|
4248
4498
|
case "not":
|
|
4249
4499
|
case "guard":
|
|
@@ -4258,6 +4508,7 @@ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
4258
4508
|
case "many":
|
|
4259
4509
|
case "oneOrMore":
|
|
4260
4510
|
case "optional":
|
|
4511
|
+
case "attempt":
|
|
4261
4512
|
case "transform":
|
|
4262
4513
|
case "label":
|
|
4263
4514
|
case "field":
|
|
@@ -4599,35 +4850,55 @@ function needsFirstSetGuard(p) {
|
|
|
4599
4850
|
const fs2 = p._meta.firstSet;
|
|
4600
4851
|
return fs2.kind !== "any" && !canMatchEmptyAtStart(p);
|
|
4601
4852
|
}
|
|
4602
|
-
function
|
|
4603
|
-
|
|
4853
|
+
function coverageHit(ctx, id, offset = "_pos", end) {
|
|
4854
|
+
return id === void 0 ? [] : [
|
|
4855
|
+
`${ind(ctx)}_ctx._grammarCoverage?.(${JSON.stringify(id)})`,
|
|
4856
|
+
`${ind(ctx)}_ctx._grammarTrace?.write({ id: ${JSON.stringify(id)}, phase: 'selected', offset: ${offset}${end === void 0 ? "" : `, end: ${end}`} })`,
|
|
4857
|
+
`${ind(ctx)}_ctx._grammarTrace?.write({ id: ${JSON.stringify(id)}, phase: 'success', offset: ${offset}${end === void 0 ? "" : `, end: ${end}`} })`
|
|
4858
|
+
];
|
|
4859
|
+
}
|
|
4860
|
+
function coverageAttempt(ctx, id, offset) {
|
|
4861
|
+
return id === void 0 ? [] : [`${ind(ctx)}_ctx._grammarTrace?.write({ id: ${JSON.stringify(id)}, phase: 'attempt', offset: ${offset} })`];
|
|
4862
|
+
}
|
|
4863
|
+
function coverageFailureBacktrack(ctx, id, failureOffset, startOffset) {
|
|
4864
|
+
return id === void 0 ? [] : [
|
|
4865
|
+
`${ind(ctx)}_ctx._grammarTrace?.write({ id: ${JSON.stringify(id)}, phase: 'failure', offset: ${failureOffset} })`,
|
|
4866
|
+
`${ind(ctx)}_ctx._grammarTrace?.write({ id: ${JSON.stringify(id)}, phase: 'backtrack', offset: ${startOffset} })`
|
|
4867
|
+
];
|
|
4868
|
+
}
|
|
4869
|
+
function emitDisjointArm(p, ctx, pos, valV, endV, coverageId) {
|
|
4870
|
+
if (failsAtStart(p) && coverageId === void 0) {
|
|
4604
4871
|
const r = emit(p, ctx, pos);
|
|
4605
|
-
return [...r.stmts, `${ind(ctx)}${valV} = ${r.valueVar}`, `${ind(ctx)}${endV} = ${r.endVar}
|
|
4872
|
+
return [...coverageAttempt(ctx, coverageId, pos), ...r.stmts, `${ind(ctx)}${valV} = ${r.valueVar}`, `${ind(ctx)}${endV} = ${r.endVar}`, ...coverageHit(ctx, coverageId, pos, r.endVar)];
|
|
4606
4873
|
}
|
|
4607
4874
|
const { stmts, okVar, valVar, endVar } = emitFallible(p, ctx, pos);
|
|
4608
4875
|
return [
|
|
4876
|
+
...coverageAttempt(ctx, coverageId, pos),
|
|
4609
4877
|
...stmts,
|
|
4610
|
-
...emitIfFail(ctx, `!${okVar}`, failArrBody(ctx, "_ctx._fx", pos, false)),
|
|
4878
|
+
...emitIfFail(ctx, `!${okVar}`, `${coverageFailureBacktrack(ctx, coverageId, "_ctx._fe", pos).join("; ")}; ${failArrBody(ctx, "_ctx._fx", pos, false)}`),
|
|
4611
4879
|
`${ind(ctx)}${valV} = ${valVar}`,
|
|
4612
|
-
`${ind(ctx)}${endV} = ${endVar}
|
|
4880
|
+
`${ind(ctx)}${endV} = ${endVar}`,
|
|
4881
|
+
...coverageHit(ctx, coverageId, pos, endVar)
|
|
4613
4882
|
];
|
|
4614
4883
|
}
|
|
4615
|
-
function emitDisjointArmGated(def, i, ctx, pos, valV, endV) {
|
|
4884
|
+
function emitDisjointArmGated(def, i, ctx, pos, valV, endV, coverageId) {
|
|
4616
4885
|
const p = def.parsers[i];
|
|
4617
4886
|
const gate = def.gates[i];
|
|
4618
|
-
if (!gate) return emitDisjointArm(p, ctx, pos, valV, endV);
|
|
4887
|
+
if (!gate) return emitDisjointArm(p, ctx, pos, valV, endV, coverageId);
|
|
4619
4888
|
const gateIdx = ctx.mapFns.length;
|
|
4620
4889
|
ctx.mapFns.push(gate);
|
|
4621
4890
|
ctx.mapFnSrcs.push(def.gateSrcs?.[i] ?? null);
|
|
4622
4891
|
const gateCond = `${mfRef(ctx)}[${gateIdx}](_ctx.state)`;
|
|
4623
4892
|
const stmts = [`${ind(ctx)}if (${gateCond}) {`];
|
|
4624
4893
|
ctx.indent++;
|
|
4625
|
-
stmts.push(...emitDisjointArm(p, ctx, pos, valV, endV));
|
|
4894
|
+
stmts.push(...emitDisjointArm(p, ctx, pos, valV, endV, coverageId));
|
|
4626
4895
|
ctx.indent--;
|
|
4627
4896
|
stmts.push(`${ind(ctx)}} else { ${failArrBody(ctx, deriveExpectedArr([p]), pos)} }`);
|
|
4628
4897
|
return stmts;
|
|
4629
4898
|
}
|
|
4630
|
-
function emitChoice(def, ctx, pos) {
|
|
4899
|
+
function emitChoice(parser2, def, ctx, pos) {
|
|
4900
|
+
const coverageIds = ctx.coverage?.plan.choices.get(parser2);
|
|
4901
|
+
const coverageBase = coverageIds?.[0]?.slice(0, -1);
|
|
4631
4902
|
const allExpected = deriveExpectedArr(def.parsers);
|
|
4632
4903
|
if (def.disjoint) {
|
|
4633
4904
|
const codeV = v(ctx, "_code");
|
|
@@ -4646,7 +4917,7 @@ function emitChoice(def, ctx, pos) {
|
|
|
4646
4917
|
stmts.push(`${ind(ctx)}{`);
|
|
4647
4918
|
ctx.indent++;
|
|
4648
4919
|
stmts.push(
|
|
4649
|
-
...emitDisjointArmGated(def, i, ctx, pos, valV, endV),
|
|
4920
|
+
...emitDisjointArmGated(def, i, ctx, pos, valV, endV, coverageIds?.[i]),
|
|
4650
4921
|
`${ind(ctx)}break`
|
|
4651
4922
|
);
|
|
4652
4923
|
ctx.indent--;
|
|
@@ -4665,16 +4936,16 @@ function emitChoice(def, ctx, pos) {
|
|
|
4665
4936
|
first = false;
|
|
4666
4937
|
stmts.push(`${ind(ctx)}${kw} (${cond}) {`);
|
|
4667
4938
|
ctx.indent++;
|
|
4668
|
-
stmts.push(...emitDisjointArmGated(def, i, ctx, pos, valV, endV));
|
|
4939
|
+
stmts.push(...emitDisjointArmGated(def, i, ctx, pos, valV, endV, coverageIds?.[i]));
|
|
4669
4940
|
ctx.indent--;
|
|
4670
4941
|
stmts.push(`${ind(ctx)}}`);
|
|
4671
4942
|
}
|
|
4672
4943
|
stmts.push(...emitElseFail(ctx, failArrBody(ctx, allExpected, pos)));
|
|
4673
4944
|
return { stmts, valueVar: valV, endVar: endV };
|
|
4674
4945
|
}
|
|
4675
|
-
return emitNonDisjoint(def, def.strategy, allExpected, ctx, pos);
|
|
4946
|
+
return emitNonDisjoint(def, def.strategy, allExpected, ctx, pos, coverageBase);
|
|
4676
4947
|
}
|
|
4677
|
-
function emitGreedyClassify(def, superIndex, ctx, pos) {
|
|
4948
|
+
function emitGreedyClassify(def, superIndex, ctx, pos, coverageBase) {
|
|
4678
4949
|
const superParser = def.parsers[superIndex];
|
|
4679
4950
|
const regexDef = getCoreRegexDef(superParser);
|
|
4680
4951
|
const cleanFlags = "y" + regexDef.flags.replace(/[gy]/g, "");
|
|
@@ -4690,10 +4961,12 @@ function emitGreedyClassify(def, superIndex, ctx, pos) {
|
|
|
4690
4961
|
const endV = v(ctx, "_ge");
|
|
4691
4962
|
const valV = v(ctx, "_gcv");
|
|
4692
4963
|
const regexExpected = JSON.stringify(deriveExpected(superParser));
|
|
4964
|
+
const superCoverageId = coverageBase === void 0 ? void 0 : `${coverageBase}${superIndex}`;
|
|
4693
4965
|
const stmts = [
|
|
4966
|
+
...coverageAttempt(ctx, superCoverageId, pos),
|
|
4694
4967
|
`${ind(ctx)}${reVar}.lastIndex = ${pos}`,
|
|
4695
4968
|
`${ind(ctx)}const ${matchV} = ${reVar}.exec(input)`,
|
|
4696
|
-
...emitIfFail(ctx, `${matchV} === null`, failArrBody(ctx, regexExpected, pos)),
|
|
4969
|
+
...emitIfFail(ctx, `${matchV} === null`, `${coverageFailureBacktrack(ctx, superCoverageId, pos, pos).join("; ")}; ${failArrBody(ctx, regexExpected, pos)}`),
|
|
4697
4970
|
`${ind(ctx)}const ${wordV} = ${matchV}[0]`,
|
|
4698
4971
|
`${ind(ctx)}const ${endV} = ${pos} + ${wordV}.length`,
|
|
4699
4972
|
`${ind(ctx)}let ${valV}`
|
|
@@ -4709,8 +4982,9 @@ function emitGreedyClassify(def, superIndex, ctx, pos) {
|
|
|
4709
4982
|
stmts.push(`${ind(ctx)}${kw} (${wordV} === ${JSON.stringify(litVal)}) {`);
|
|
4710
4983
|
ctx.indent++;
|
|
4711
4984
|
const tR = emitTransformChain(p, JSON.stringify(litVal), endV, pos, ctx);
|
|
4985
|
+
stmts.push(...coverageFailureBacktrack(ctx, superCoverageId, pos, pos));
|
|
4712
4986
|
stmts.push(...emitLeafCapture(ctx, JSON.stringify(litVal), pos, endV));
|
|
4713
|
-
stmts.push(...tR.stmts, `${ind(ctx)}${valV} = ${tR.valueVar}
|
|
4987
|
+
stmts.push(...tR.stmts, `${ind(ctx)}${valV} = ${tR.valueVar}`, ...coverageHit(ctx, coverageBase === void 0 ? void 0 : `${coverageBase}${i}`, pos, endV));
|
|
4714
4988
|
ctx.indent--;
|
|
4715
4989
|
stmts.push(`${ind(ctx)}}`);
|
|
4716
4990
|
}
|
|
@@ -4718,12 +4992,12 @@ function emitGreedyClassify(def, superIndex, ctx, pos) {
|
|
|
4718
4992
|
const regexKw = first ? "if" : "else";
|
|
4719
4993
|
stmts.push(`${ind(ctx)}${regexKw} {`);
|
|
4720
4994
|
ctx.indent++;
|
|
4721
|
-
stmts.push(...emitLeafCapture(ctx, wordV, pos, endV), ...rR.stmts, `${ind(ctx)}${valV} = ${rR.valueVar}
|
|
4995
|
+
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));
|
|
4722
4996
|
ctx.indent--;
|
|
4723
4997
|
stmts.push(`${ind(ctx)}}`);
|
|
4724
4998
|
return { stmts, valueVar: valV, endVar: endV };
|
|
4725
4999
|
}
|
|
4726
|
-
function emitLiteralsLongestFirst(def, sortedIndices, allExpected, ctx, pos) {
|
|
5000
|
+
function emitLiteralsLongestFirst(def, sortedIndices, allExpected, ctx, pos, coverageBase) {
|
|
4727
5001
|
const valV = v(ctx, "_llv");
|
|
4728
5002
|
const endV = v(ctx, "_lle");
|
|
4729
5003
|
const stmts = [`${ind(ctx)}let ${valV}, ${endV} = ${pos}`];
|
|
@@ -4740,10 +5014,12 @@ function emitLiteralsLongestFirst(def, sortedIndices, allExpected, ctx, pos) {
|
|
|
4740
5014
|
ctx.indent++;
|
|
4741
5015
|
const tR = emitTransformChain(p, JSON.stringify(litVal), litEnd, pos, ctx);
|
|
4742
5016
|
stmts.push(
|
|
5017
|
+
...coverageAttempt(ctx, coverageBase === void 0 ? void 0 : `${coverageBase}${idx}`, pos),
|
|
4743
5018
|
...emitLeafCapture(ctx, JSON.stringify(litVal), pos, litEnd),
|
|
4744
5019
|
...tR.stmts,
|
|
4745
5020
|
`${ind(ctx)}${valV} = ${tR.valueVar}`,
|
|
4746
|
-
`${ind(ctx)}${endV} = ${litEnd}
|
|
5021
|
+
`${ind(ctx)}${endV} = ${litEnd}`,
|
|
5022
|
+
...coverageHit(ctx, coverageBase === void 0 ? void 0 : `${coverageBase}${idx}`, pos, litEnd)
|
|
4747
5023
|
);
|
|
4748
5024
|
ctx.indent--;
|
|
4749
5025
|
stmts.push(`${ind(ctx)}}`);
|
|
@@ -4751,16 +5027,18 @@ function emitLiteralsLongestFirst(def, sortedIndices, allExpected, ctx, pos) {
|
|
|
4751
5027
|
stmts.push(...emitElseFail(ctx, failArrBody(ctx, allExpected, pos)));
|
|
4752
5028
|
return { stmts, valueVar: valV, endVar: endV };
|
|
4753
5029
|
}
|
|
4754
|
-
function emitFirstMatch(def, ctx, pos) {
|
|
5030
|
+
function emitFirstMatch(def, ctx, pos, coverageBase) {
|
|
4755
5031
|
const resValV = v(ctx, "_crv");
|
|
4756
5032
|
const resEndV = v(ctx, "_cre");
|
|
4757
5033
|
const resOkV = v(ctx, "_crok");
|
|
4758
5034
|
const codeV = v(ctx, "_chcode");
|
|
4759
5035
|
const slots = def.parsers.map(() => v(ctx, "_cfx"));
|
|
5036
|
+
const autoRejectedV = coverageBase === void 0 ? void 0 : v(ctx, "_carej");
|
|
4760
5037
|
const ind0 = ind(ctx);
|
|
4761
5038
|
const stmts = [
|
|
4762
5039
|
`${ind0}let ${resValV}, ${resEndV} = ${pos}, ${resOkV} = false`,
|
|
4763
5040
|
`${ind0}let ${slots.join(", ")}`,
|
|
5041
|
+
...autoRejectedV === void 0 ? [] : [`${ind0}const ${autoRejectedV} = []`],
|
|
4764
5042
|
`${ind0}const ${codeV} = ${pos} < input.length ? (input.codePointAt(${pos}) ?? -1) : -1`
|
|
4765
5043
|
];
|
|
4766
5044
|
for (let i = 0; i < def.parsers.length; i++) {
|
|
@@ -4796,6 +5074,7 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
4796
5074
|
stmts.push(`${ind0}if (${skipCond}) {`);
|
|
4797
5075
|
if (fsGuard) stmts.push(`${ind(ctx)}if (${fsGuard}) {`);
|
|
4798
5076
|
ctx.indent += fsGuard ? 2 : 1;
|
|
5077
|
+
if (coverageBase !== void 0) stmts.push(`${ind(ctx)}_ctx._grammarTrace?.write({ id: ${JSON.stringify(`${coverageBase}${i}`)}, phase: 'attempt', offset: ${pos} })`);
|
|
4799
5078
|
if (markLeaves) {
|
|
4800
5079
|
stmts.push(
|
|
4801
5080
|
`${ind(ctx)}const ${markLeaves} = _ctx._cstLeaves?.length ?? 0`,
|
|
@@ -4818,13 +5097,21 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
4818
5097
|
stmts.push(`${ind(ctx)} ${resValV} = ${valVar}`);
|
|
4819
5098
|
stmts.push(`${ind(ctx)} ${resEndV} = ${endVar}`);
|
|
4820
5099
|
stmts.push(`${ind(ctx)} ${resOkV} = true`);
|
|
5100
|
+
if (autoRejectedV !== void 0) {
|
|
5101
|
+
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} }) }`);
|
|
5102
|
+
}
|
|
5103
|
+
stmts.push(...coverageHit(ctx, coverageBase === void 0 ? void 0 : `${coverageBase}${i}`, pos, endVar));
|
|
4821
5104
|
stmts.push(`${ind(ctx)} }`);
|
|
5105
|
+
if (autoRejectedV !== void 0) {
|
|
5106
|
+
stmts.push(`${ind(ctx)} else { ${autoRejectedV}.push(${JSON.stringify(`${coverageBase}${i}`)}) }`);
|
|
5107
|
+
}
|
|
4822
5108
|
stmts.push(`${ind(ctx)}}`);
|
|
4823
|
-
stmts.push(`${ind(ctx)}else { ${slots[i]} = ${failSlot} }`);
|
|
5109
|
+
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} });`} }`);
|
|
4824
5110
|
if (rollback) stmts.push(`${ind(ctx)}if (!${resOkV}) { ${rollback} }`);
|
|
4825
5111
|
} else {
|
|
4826
|
-
|
|
4827
|
-
stmts.push(`${ind(ctx)}
|
|
5112
|
+
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} }) }`;
|
|
5113
|
+
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} })`} }`);
|
|
5114
|
+
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} })`} }`);
|
|
4828
5115
|
}
|
|
4829
5116
|
ctx.indent -= fsGuard ? 2 : 1;
|
|
4830
5117
|
if (fsGuard) stmts.push(`${ind(ctx)}} else { ${slots[i]} = ${staticFx} }`);
|
|
@@ -4834,12 +5121,12 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
4834
5121
|
stmts.push(...emitIfFail(ctx, `!${resOkV}`, failArrBody(ctx, concatExpr, pos, false)));
|
|
4835
5122
|
return { stmts, valueVar: resValV, endVar: resEndV };
|
|
4836
5123
|
}
|
|
4837
|
-
function emitNonDisjoint(def, strategy, allExpected, ctx, pos) {
|
|
5124
|
+
function emitNonDisjoint(def, strategy, allExpected, ctx, pos, coverageBase) {
|
|
4838
5125
|
if (strategy.tag === "greedyClassify")
|
|
4839
|
-
return emitGreedyClassify(def, strategy.superIndex, ctx, pos);
|
|
5126
|
+
return emitGreedyClassify(def, strategy.superIndex, ctx, pos, coverageBase);
|
|
4840
5127
|
if (strategy.tag === "literalsLongestFirst")
|
|
4841
|
-
return emitLiteralsLongestFirst(def, strategy.sortedIndices, allExpected, ctx, pos);
|
|
4842
|
-
return emitFirstMatch(def, ctx, pos);
|
|
5128
|
+
return emitLiteralsLongestFirst(def, strategy.sortedIndices, allExpected, ctx, pos, coverageBase);
|
|
5129
|
+
return emitFirstMatch(def, ctx, pos, coverageBase);
|
|
4843
5130
|
}
|
|
4844
5131
|
function pushMapFn(ctx, fn, src) {
|
|
4845
5132
|
if (src !== null && ctx.mapFns.length === ctx.mapFnSrcs.length) {
|
|
@@ -4957,6 +5244,27 @@ function emitOptional(def, ctx, pos) {
|
|
|
4957
5244
|
];
|
|
4958
5245
|
return { stmts, valueVar: valV, endVar: endV };
|
|
4959
5246
|
}
|
|
5247
|
+
function emitAttempt(p, def, ctx, pos) {
|
|
5248
|
+
const inner = emitFallible(def.parser, ctx, pos);
|
|
5249
|
+
const leaves = v(ctx, "_atl");
|
|
5250
|
+
const raw = v(ctx, "_atr");
|
|
5251
|
+
const trivia2 = v(ctx, "_att");
|
|
5252
|
+
const log = v(ctx, "_atg");
|
|
5253
|
+
const fields = v(ctx, "_atf");
|
|
5254
|
+
const errors = v(ctx, "_ate");
|
|
5255
|
+
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}`;
|
|
5256
|
+
const traceId = ctx.coverage?.plan.attempts.get(p);
|
|
5257
|
+
const traceRollback = traceId === void 0 ? "" : ` _ctx._grammarTrace?.write({ id: ${JSON.stringify(traceId)}, phase: 'rollback', offset: ${pos} });`;
|
|
5258
|
+
return {
|
|
5259
|
+
stmts: [
|
|
5260
|
+
`${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`,
|
|
5261
|
+
...inner.stmts,
|
|
5262
|
+
...emitIfFail(ctx, `!${inner.okVar}`, `{ ${rollback};${traceRollback} _ctx._fe = ${pos}; ${propagateFailBody(ctx)} }`)
|
|
5263
|
+
],
|
|
5264
|
+
valueVar: inner.valVar,
|
|
5265
|
+
endVar: inner.endVar
|
|
5266
|
+
};
|
|
5267
|
+
}
|
|
4960
5268
|
function emitSepBy(_p, def, ctx, pos) {
|
|
4961
5269
|
const arrV = v(ctx, "_arr");
|
|
4962
5270
|
const curV = v(ctx, "_cur");
|
|
@@ -5202,11 +5510,11 @@ function tokenNullableRegex(def) {
|
|
|
5202
5510
|
}
|
|
5203
5511
|
if (inner.tag === "sepBy") {
|
|
5204
5512
|
const item = tokenSequenceSource(inner.parser);
|
|
5205
|
-
const
|
|
5206
|
-
if (!item || !
|
|
5207
|
-
const combined = combineTokenRegexSources([item,
|
|
5513
|
+
const sep2 = tokenSequenceSource(inner.separator);
|
|
5514
|
+
if (!item || !sep2) return null;
|
|
5515
|
+
const combined = combineTokenRegexSources([item, sep2]);
|
|
5208
5516
|
if (!combined) return null;
|
|
5209
|
-
return { tag: "regex", source: `(?:${item.source}(?:${
|
|
5517
|
+
return { tag: "regex", source: `(?:${item.source}(?:${sep2.source}${item.source})*)?`, flags: combined.flags };
|
|
5210
5518
|
}
|
|
5211
5519
|
return null;
|
|
5212
5520
|
}
|
|
@@ -5247,6 +5555,36 @@ function emitToken(def, ctx, pos) {
|
|
|
5247
5555
|
endVar: inner.endVar
|
|
5248
5556
|
};
|
|
5249
5557
|
}
|
|
5558
|
+
function emitLeaf(def, ctx, pos) {
|
|
5559
|
+
const inner = emitFallible(def.parser, ctx, pos);
|
|
5560
|
+
const i = ind(ctx);
|
|
5561
|
+
const sc = v(ctx, "_leafCh");
|
|
5562
|
+
const sl = v(ctx, "_leafLv");
|
|
5563
|
+
const sr = v(ctx, "_leafRaw");
|
|
5564
|
+
const stl = v(ctx, "_leafTl");
|
|
5565
|
+
const sol = v(ctx, "_leafLog");
|
|
5566
|
+
const sb = v(ctx, "_leafBuf");
|
|
5567
|
+
const rawV = v(ctx, "_leafRawValue");
|
|
5568
|
+
const valV = v(ctx, "_leaf");
|
|
5569
|
+
const fnIdx = pushMapFn(ctx, def.fn, def.fnSrc ?? null);
|
|
5570
|
+
return {
|
|
5571
|
+
stmts: [
|
|
5572
|
+
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${stl} = _ctx._cstTriviaLog, ${sol} = _ctx._triviaLog, ${sb} = _ctx._cstBuf`,
|
|
5573
|
+
`${i}_ctx._cstChildren = undefined; _ctx._cstLeaves = undefined; _ctx._cstRawChildren = undefined; _ctx._cstTriviaLog = undefined; _ctx._triviaLog = undefined; _ctx._cstBuf = undefined`,
|
|
5574
|
+
`${i}try {`,
|
|
5575
|
+
...reindentStmts(inner.stmts, ctx.indent + 1).map((stmt) => stmt.replace(/^(\s*)(?:const|let)\s+/, "$1var ")),
|
|
5576
|
+
`${i}} finally {`,
|
|
5577
|
+
`${i} _ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx._cstTriviaLog = ${stl}; _ctx._triviaLog = ${sol}; _ctx._cstBuf = ${sb}`,
|
|
5578
|
+
`${i}}`,
|
|
5579
|
+
...emitIfFail(ctx, `!${inner.okVar}`, propagateFailBody(ctx)),
|
|
5580
|
+
`${i}const ${rawV} = ${inner.valVar}`,
|
|
5581
|
+
`${i}const ${valV} = ${mfRef(ctx)}[${fnIdx}](${rawV}, { start: ${pos}, end: ${inner.endVar} })`,
|
|
5582
|
+
...emitLeafCapture(ctx, valV, pos, inner.endVar)
|
|
5583
|
+
],
|
|
5584
|
+
valueVar: valV,
|
|
5585
|
+
endVar: inner.endVar
|
|
5586
|
+
};
|
|
5587
|
+
}
|
|
5250
5588
|
function emitNode(def, ctx, pos) {
|
|
5251
5589
|
if (def.type === void 0) {
|
|
5252
5590
|
throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
|
|
@@ -5260,17 +5598,20 @@ function emitNode(def, ctx, pos) {
|
|
|
5260
5598
|
ctx.buildSrcs.push(def.buildSrc ?? null);
|
|
5261
5599
|
}
|
|
5262
5600
|
const i = ind(ctx);
|
|
5263
|
-
const capturesTrivia = mkType !== null || !structural && buildReadsTrivia(def);
|
|
5601
|
+
const capturesTrivia = mkType !== null || def.captureTrivia === true || def.trailingTrivia === true || !structural && buildReadsTrivia(def);
|
|
5264
5602
|
const clonesState = !structural && buildReadsState(def);
|
|
5603
|
+
const capturesChildren = !structural && (mkType !== null || def.unwrap || def.collapse || buildReadsChildren(def));
|
|
5604
|
+
const capturesRaw = !structural && (mkType !== null || buildReadsRaw(def));
|
|
5265
5605
|
const hasFields = parserHasOwnFields(def.parser);
|
|
5266
5606
|
const capturesFields = hasFields && !structural && buildReadsFields(def);
|
|
5607
|
+
const innerEnablesTriviaCapture = parserEnablesTriviaCapture(def.parser);
|
|
5267
5608
|
const chV = v(ctx, "_ch");
|
|
5268
5609
|
const rawV = v(ctx, "_raw");
|
|
5269
|
-
const capTLv = structural ? v(ctx, "_ctl") : null;
|
|
5610
|
+
const capTLv = structural || capturesTrivia ? v(ctx, "_ctl") : null;
|
|
5270
5611
|
const capSTv = structural ? v(ctx, "_cst") : null;
|
|
5271
5612
|
const capFv = structural && hasFields ? v(ctx, "_cf") : null;
|
|
5272
5613
|
const tlV = capturesTrivia || structural ? v(ctx, "_tl") : "_EMPTY_TL";
|
|
5273
|
-
if (!capturesTrivia) ctx.needsEmptyTl = true;
|
|
5614
|
+
if (!capturesTrivia || structural) ctx.needsEmptyTl = true;
|
|
5274
5615
|
const sc = v(ctx, "_sc"), sl = v(ctx, "_sl"), sr = v(ctx, "_sr"), st = v(ctx, "_st"), stl = v(ctx, "_stl");
|
|
5275
5616
|
const smk = structural ? v(ctx, "_smk") : null;
|
|
5276
5617
|
if (structural) ctx.needsHostReads = true;
|
|
@@ -5279,16 +5620,21 @@ function emitNode(def, ctx, pos) {
|
|
|
5279
5620
|
const profHoist = `${i}const ${pmV} = _ctx._pmProfile, ${recV} = ${pmV}?.phase === 'recognizer', ${capV} = ${pmV}?.phase === 'capture'`;
|
|
5280
5621
|
const profileRecognizer = recV;
|
|
5281
5622
|
const profileCapture = capV;
|
|
5282
|
-
const
|
|
5283
|
-
|
|
5284
|
-
const
|
|
5623
|
+
const directCstV = !structural && (!capturesChildren || !capturesRaw) ? v(ctx, "_dcst") : null;
|
|
5624
|
+
const directCstGate = directCstV === null ? "false" : `${profileCapture} || _ctx.build?._parsemanCstOutput === true`;
|
|
5625
|
+
const structuralCapturesTrivia = structural && (def.captureTrivia === true || def.trailingTrivia === true);
|
|
5626
|
+
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)))` : ""}
|
|
5627
|
+
${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRecognizer} ? undefined : [], ${tlV} = ${profileRecognizer} ? undefined : ${innerEnablesTriviaCapture ? "[]" : `${capTLv} ? [] : _EMPTY_TL`}` : capturesTrivia ? `${directCstV ? `${i}const ${directCstV} = ${directCstGate}
|
|
5628
|
+
` : ""}${i}const ${capTLv} = !(${profileRecognizer}), ${chV} = ${profileRecognizer} ? undefined : ${capturesChildren ? "[]" : `${directCstV} ? [] : undefined`}, ${rawV} = ${profileRecognizer} ? undefined : ${capturesRaw ? "[]" : `${directCstV} ? [] : undefined`}, ${tlV} = ${profileRecognizer} ? undefined : []` : `${directCstV ? `${i}const ${directCstV} = ${directCstGate}
|
|
5629
|
+
` : ""}${i}const ${chV} = ${profileRecognizer} ? undefined : ${capturesChildren ? "[]" : `${directCstV} ? [] : undefined`}, ${rawV} = ${profileRecognizer} ? undefined : ${capturesRaw ? "[]" : `${directCstV} ? [] : undefined`}`;
|
|
5630
|
+
const innerTl = structural || capturesTrivia ? structural && !innerEnablesTriviaCapture ? `${capTLv} ? ${tlV} : undefined` : tlV : "undefined";
|
|
5285
5631
|
const fieldsOn = structural ? capFv ?? "false" : `${profileRecognizer} ? false : ${capturesFields ? "true" : "false"}`;
|
|
5286
5632
|
const sf = hasFields ? v(ctx, "_sf") : null;
|
|
5287
5633
|
const fArr = hasFields ? v(ctx, "_fa") : null;
|
|
5288
5634
|
const fObj = hasFields ? v(ctx, "_fields") : "undefined";
|
|
5289
|
-
const needsTriviaFrame = parserHasTriviaSite(def.parser);
|
|
5635
|
+
const needsTriviaFrame = def.trailingTrivia === true || parserHasTriviaSite(def.parser);
|
|
5290
5636
|
const saveTrivia = needsTriviaFrame ? `, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog${smk ? `, ${smk} = _ctx._triviaCaptureMask` : ""}` : "";
|
|
5291
|
-
const installTrivia = needsTriviaFrame ? `; _ctx.captureTrivia =
|
|
5637
|
+
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}` : ""}` : "";
|
|
5292
5638
|
const restoreTrivia = needsTriviaFrame ? `; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}${smk ? `; _ctx._triviaCaptureMask = ${smk}` : ""}` : "";
|
|
5293
5639
|
const stmts = [
|
|
5294
5640
|
profHoist,
|
|
@@ -5296,8 +5642,13 @@ ${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRec
|
|
|
5296
5642
|
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren${saveTrivia}${sf ? `, ${sf} = _ctx._fields` : ""}`,
|
|
5297
5643
|
`${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}${installTrivia}${sf ? `; _ctx._fields = ${fieldsOn} ? [] : undefined` : ""}`
|
|
5298
5644
|
];
|
|
5299
|
-
const { stmts: innerStmts, okVar, endVar } = emitFallible(def.parser, ctx, pos);
|
|
5645
|
+
const { stmts: innerStmts, okVar, endVar: innerEndVar } = emitFallible(def.parser, ctx, pos);
|
|
5646
|
+
const endVar = def.trailingTrivia === true && ctx.activeTrivia ? v(ctx, "_trailend") : innerEndVar;
|
|
5300
5647
|
stmts.push(...innerStmts);
|
|
5648
|
+
if (def.trailingTrivia === true && ctx.activeTrivia) {
|
|
5649
|
+
const triviaFn = ensureTriviaFn(ctx);
|
|
5650
|
+
stmts.push(`${i}const ${endVar} = ${okVar} ? ${triviaFn}(input, ${innerEndVar}, _ctx, 1) : ${innerEndVar}`);
|
|
5651
|
+
}
|
|
5301
5652
|
if (sf && fArr) {
|
|
5302
5653
|
stmts.push(`${i}const ${fArr} = _ctx._fields`);
|
|
5303
5654
|
}
|
|
@@ -5337,8 +5688,9 @@ ${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRec
|
|
|
5337
5688
|
}
|
|
5338
5689
|
const ndV = v(ctx, "_nd");
|
|
5339
5690
|
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})`;
|
|
5340
|
-
const
|
|
5341
|
-
const
|
|
5691
|
+
const hostBuildExpr = `_ctx._pmProfile?.phase === 'host' && _ctx._pmProfile.hostCalls++, _ctx.build(${JSON.stringify(def.type)}, ${chV}, ${fObj}, { start: ${pos}, end: ${endVar} }, ${rawV}, ${tlV}, ${stV})`;
|
|
5692
|
+
const ndExpr = structural ? `_ctx.build !== undefined ? (${hostBuildExpr}) : (${buildExpr})` : `_ctx.build?._parsemanCstOutput === true ? (${hostBuildExpr}) : (${buildExpr})`;
|
|
5693
|
+
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;
|
|
5342
5694
|
const unwrapExpr = `${chV}.length === 1 ? (${chV}[0] !== null && typeof ${chV}[0] === 'object' && ${chV}[0]._tag === 'leaf' ? ${chV}[0].value : ${chV}[0]) : (${ndExpr})`;
|
|
5343
5695
|
const collapseExpr = `${chV}.length === 1 ? ${chV}[0] : (${ndExpr})`;
|
|
5344
5696
|
const finalExpr = def.unwrap ? unwrapExpr : def.collapse ? collapseExpr : hostCollapseExpr;
|
|
@@ -5346,7 +5698,7 @@ ${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRec
|
|
|
5346
5698
|
`${i}const ${ndV} = (${profileRecognizer} || ${profileCapture}) ? undefined : (${finalExpr})`,
|
|
5347
5699
|
`${i}if (!(${profileRecognizer})) {`,
|
|
5348
5700
|
`${i} if (${sc}) ${sc}.push(${ndV})`,
|
|
5349
|
-
`${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} } })`,
|
|
5701
|
+
`${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} } })`,
|
|
5350
5702
|
`${i}}`
|
|
5351
5703
|
);
|
|
5352
5704
|
return { stmts, valueVar: ndV, endVar };
|
|
@@ -5391,14 +5743,23 @@ function emitLazy(p, def, ctx, pos) {
|
|
|
5391
5743
|
const savedIndent = ctx.indent;
|
|
5392
5744
|
const savedFailLabel = ctx.failLabel;
|
|
5393
5745
|
const savedRecord = ctx.recordFail;
|
|
5746
|
+
const failureRuleId = p === ctx.coverage?.entry ? void 0 : ctx.coverage?.plan.rules.get(p) ?? ctx.coverage?.plan.rules.get(resolved);
|
|
5747
|
+
const savedActiveRule = ctx.activeCoverageRuleId;
|
|
5748
|
+
const savedSuppressFailure = ctx.suppressCoverageFailure;
|
|
5394
5749
|
ctx.indent = 1;
|
|
5395
5750
|
ctx.failLabel = "_pfail";
|
|
5396
5751
|
ctx.recordFail = true;
|
|
5752
|
+
if (failureRuleId !== void 0) {
|
|
5753
|
+
ctx.activeCoverageRuleId = void 0;
|
|
5754
|
+
ctx.suppressCoverageFailure = true;
|
|
5755
|
+
}
|
|
5397
5756
|
const r = emit(resolved, ctx, "_pos");
|
|
5398
5757
|
ctx.indent = savedIndent;
|
|
5399
5758
|
ctx.failLabel = savedFailLabel;
|
|
5400
5759
|
ctx.recordFail = savedRecord;
|
|
5401
|
-
|
|
5760
|
+
ctx.activeCoverageRuleId = savedActiveRule;
|
|
5761
|
+
ctx.suppressCoverageFailure = savedSuppressFailure;
|
|
5762
|
+
pushNamedFnDecl(ctx, fnName2, r.stmts, r.valueVar, r.endVar, failureRuleId);
|
|
5402
5763
|
}
|
|
5403
5764
|
const fnName = ctx.namedParsers.get(p);
|
|
5404
5765
|
return emitNamedFnCall(ctx, fnName, pos);
|
|
@@ -5449,6 +5810,30 @@ function emitExpect(def, ctx, pos) {
|
|
|
5449
5810
|
return { stmts, valueVar: valVar, endVar };
|
|
5450
5811
|
}
|
|
5451
5812
|
function emit(p, ctx, pos) {
|
|
5813
|
+
const dispatch = (emissionPos = pos) => {
|
|
5814
|
+
const savedRule = ctx.activeCoverageRuleId;
|
|
5815
|
+
const rule = ctx.coverage?.plan.rules.get(p);
|
|
5816
|
+
if (rule && p !== ctx.coverage?.entry && !ctx.suppressCoverageFailure) ctx.activeCoverageRuleId = rule;
|
|
5817
|
+
const result = emitDispatch(p, ctx, emissionPos);
|
|
5818
|
+
ctx.activeCoverageRuleId = savedRule;
|
|
5819
|
+
return result;
|
|
5820
|
+
};
|
|
5821
|
+
const instrument = (r) => {
|
|
5822
|
+
const ruleId = ctx.coverage?.plan.rules.get(p);
|
|
5823
|
+
const labelIds = ctx.coverage?.plan.labels.get(p);
|
|
5824
|
+
if (!ruleId && !labelIds) return r;
|
|
5825
|
+
return {
|
|
5826
|
+
...r,
|
|
5827
|
+
stmts: [
|
|
5828
|
+
...ruleId ? [`${ind(ctx)}_ctx._grammarCoverage?.(${JSON.stringify(ruleId)})`] : [],
|
|
5829
|
+
...ruleId ? [`${ind(ctx)}_ctx._grammarTrace?.write({ id: ${JSON.stringify(ruleId)}, phase: 'enter', offset: ${pos} })`] : [],
|
|
5830
|
+
...r.stmts,
|
|
5831
|
+
...ruleId ? [`${ind(ctx)}_ctx._grammarTrace?.write({ id: ${JSON.stringify(ruleId)}, phase: 'success', offset: ${pos}, end: ${r.endVar} })`] : [],
|
|
5832
|
+
...labelIds?.flatMap((id) => [`${ind(ctx)}_ctx._grammarCoverage?.(${JSON.stringify(id)})`]) ?? [],
|
|
5833
|
+
...labelIds?.flatMap((id) => [`${ind(ctx)}_ctx._grammarTrace?.write({ id: ${JSON.stringify(id)}, phase: 'success', offset: ${pos}, end: ${r.endVar} })`]) ?? []
|
|
5834
|
+
]
|
|
5835
|
+
};
|
|
5836
|
+
};
|
|
5452
5837
|
const usage = ctx.lazyUsage;
|
|
5453
5838
|
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
|
|
5454
5839
|
// overhead. A tiny shared wrapper (e.g. `optional(literal(';'))`) inlines
|
|
@@ -5465,14 +5850,14 @@ function emit(p, ctx, pos) {
|
|
|
5465
5850
|
ctx.indent = 1;
|
|
5466
5851
|
ctx.failLabel = "_pfail";
|
|
5467
5852
|
ctx.recordFail = true;
|
|
5468
|
-
const r =
|
|
5853
|
+
const r = dispatch("_pos");
|
|
5469
5854
|
ctx.indent = savedIndent;
|
|
5470
5855
|
ctx.failLabel = savedFailLabel;
|
|
5471
5856
|
ctx.recordFail = savedRecord;
|
|
5472
5857
|
pushNamedFnDecl(ctx, fnName, r.stmts, r.valueVar, r.endVar);
|
|
5473
|
-
return emitNamedFnCall(ctx, fnName, pos);
|
|
5858
|
+
return instrument(emitNamedFnCall(ctx, fnName, pos));
|
|
5474
5859
|
}
|
|
5475
|
-
return
|
|
5860
|
+
return instrument(dispatch());
|
|
5476
5861
|
}
|
|
5477
5862
|
function emitDispatch(p, ctx, pos) {
|
|
5478
5863
|
const def = p._def;
|
|
@@ -5486,7 +5871,9 @@ function emitDispatch(p, ctx, pos) {
|
|
|
5486
5871
|
case "sequence":
|
|
5487
5872
|
return emitSeq(def, ctx, pos);
|
|
5488
5873
|
case "choice":
|
|
5489
|
-
return emitChoice(def, ctx, pos);
|
|
5874
|
+
return emitChoice(p, def, ctx, pos);
|
|
5875
|
+
case "attempt":
|
|
5876
|
+
return emitAttempt(p, def, ctx, pos);
|
|
5490
5877
|
case "many":
|
|
5491
5878
|
case "oneOrMore":
|
|
5492
5879
|
return emitMany(def, ctx, pos);
|
|
@@ -5555,6 +5942,8 @@ function emitDispatch(p, ctx, pos) {
|
|
|
5555
5942
|
return emit(def.parser, ctx, pos);
|
|
5556
5943
|
case "token":
|
|
5557
5944
|
return emitToken(def, ctx, pos);
|
|
5945
|
+
case "leaf":
|
|
5946
|
+
return emitLeaf(def, ctx, pos);
|
|
5558
5947
|
case "label": {
|
|
5559
5948
|
const inner = emitFallible(def.parser, ctx, pos);
|
|
5560
5949
|
return {
|
|
@@ -5589,10 +5978,19 @@ function emitDispatch(p, ctx, pos) {
|
|
|
5589
5978
|
ctx.triviaKindLabels = def.triviaParser._meta.triviaKindLabels;
|
|
5590
5979
|
}
|
|
5591
5980
|
}
|
|
5981
|
+
const savedCapture = def.captureTrivia ? v(ctx, "_gcap") : null;
|
|
5592
5982
|
const r = emit(def.parser, ctx, pos);
|
|
5593
5983
|
ctx.activeTrivia = savedTrivia;
|
|
5594
5984
|
ctx.triviaKindLabels = savedKindLabels;
|
|
5595
|
-
return r;
|
|
5985
|
+
if (!savedCapture) return r;
|
|
5986
|
+
return {
|
|
5987
|
+
...r,
|
|
5988
|
+
stmts: [
|
|
5989
|
+
`${ind(ctx)}const ${savedCapture} = _ctx.captureTrivia; _ctx.captureTrivia = true`,
|
|
5990
|
+
...r.stmts,
|
|
5991
|
+
`${ind(ctx)}_ctx.captureTrivia = ${savedCapture}`
|
|
5992
|
+
]
|
|
5993
|
+
};
|
|
5596
5994
|
}
|
|
5597
5995
|
case "not":
|
|
5598
5996
|
return emitNot(def, ctx, pos);
|
|
@@ -5677,6 +6075,7 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
5677
6075
|
case "grammar":
|
|
5678
6076
|
case "trivia":
|
|
5679
6077
|
case "token":
|
|
6078
|
+
case "leaf":
|
|
5680
6079
|
case "label":
|
|
5681
6080
|
case "field":
|
|
5682
6081
|
case "optional":
|
|
@@ -5704,16 +6103,32 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
5704
6103
|
return false;
|
|
5705
6104
|
}
|
|
5706
6105
|
}
|
|
6106
|
+
function hasDirectBuildDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
6107
|
+
if (seen.has(p)) return false;
|
|
6108
|
+
seen.add(p);
|
|
6109
|
+
const d = p._def;
|
|
6110
|
+
if (d.tag === "node" && d.build !== void 0) return true;
|
|
6111
|
+
if (d.tag === "lazy") {
|
|
6112
|
+
try {
|
|
6113
|
+
return hasDirectBuildDef(d.thunk(), seen);
|
|
6114
|
+
} catch {
|
|
6115
|
+
return false;
|
|
6116
|
+
}
|
|
6117
|
+
}
|
|
6118
|
+
return childrenOf(d).some((child) => hasDirectBuildDef(child, seen));
|
|
6119
|
+
}
|
|
5707
6120
|
function childrenOf(def) {
|
|
5708
6121
|
switch (def.tag) {
|
|
5709
6122
|
case "sequence":
|
|
5710
6123
|
case "choice":
|
|
5711
6124
|
return def.parsers;
|
|
5712
6125
|
case "many":
|
|
6126
|
+
case "attempt":
|
|
5713
6127
|
case "optional":
|
|
5714
6128
|
case "transform":
|
|
5715
6129
|
case "trivia":
|
|
5716
6130
|
case "token":
|
|
6131
|
+
case "leaf":
|
|
5717
6132
|
case "label":
|
|
5718
6133
|
case "field":
|
|
5719
6134
|
case "grammar":
|
|
@@ -5888,10 +6303,25 @@ function compile(combinator, mapFnSources, opts) {
|
|
|
5888
6303
|
namedFnDecls: [],
|
|
5889
6304
|
capturing: hasNodeDef(combinator),
|
|
5890
6305
|
recovery: opts?.recovery ?? false,
|
|
6306
|
+
...opts?.coverage ? { coverage: { plan: buildGrammarPlan(combinator), entry: combinator } } : {},
|
|
5891
6307
|
lazyUsage: analyzeLazyUsage(combinator),
|
|
5892
6308
|
...grammarTrivia ? { activeTrivia: grammarTrivia, triviaKindLabels: grammarTrivia._meta.triviaKindLabels } : {}
|
|
5893
6309
|
};
|
|
5894
6310
|
const r = emit(combinator, ctx, "_pos");
|
|
6311
|
+
const coverageRootRuleId = ctx.coverage?.plan.rules.get(combinator);
|
|
6312
|
+
const resultBody = coverageRootRuleId === void 0 ? [
|
|
6313
|
+
` let pos = _pos`,
|
|
6314
|
+
...r.stmts,
|
|
6315
|
+
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`
|
|
6316
|
+
] : [
|
|
6317
|
+
` const _coverageResult = (() => {`,
|
|
6318
|
+
` let pos = _pos`,
|
|
6319
|
+
...r.stmts,
|
|
6320
|
+
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
6321
|
+
` })()`,
|
|
6322
|
+
` if (!_coverageResult.ok) _ctx._grammarTrace?.write({ id: ${JSON.stringify(coverageRootRuleId)}, phase: 'failure', offset: _coverageResult.span.start })`,
|
|
6323
|
+
` return _coverageResult`
|
|
6324
|
+
];
|
|
5895
6325
|
const namedPrelude = ctx.namedFnDecls.length > 0 ? [...namedFnPrelude(), ""] : [];
|
|
5896
6326
|
const emptyTlDecls = ctx.needsEmptyTl ? ["const _EMPTY_TL = Object.freeze([])"] : [];
|
|
5897
6327
|
const hostReadsDecls = ctx.needsHostReads ? [HOST_READS_DECL] : [];
|
|
@@ -5904,9 +6334,7 @@ function compile(combinator, mapFnSources, opts) {
|
|
|
5904
6334
|
...namedPrelude,
|
|
5905
6335
|
ctx.namedFnDecls.join("\n\n"),
|
|
5906
6336
|
`function _parse(input, _pos, _rp, _mf, _build, _ctx) {`,
|
|
5907
|
-
|
|
5908
|
-
...r.stmts,
|
|
5909
|
-
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
6337
|
+
...resultBody,
|
|
5910
6338
|
`}`
|
|
5911
6339
|
].join("\n");
|
|
5912
6340
|
const fn = new Function("input", "_pos", "_rp", "_mf", "_build", "_ctx", [
|
|
@@ -5916,9 +6344,15 @@ function compile(combinator, mapFnSources, opts) {
|
|
|
5916
6344
|
...ctx.expectedDecls,
|
|
5917
6345
|
...namedPrelude,
|
|
5918
6346
|
...ctx.namedFnDecls.flatMap((decl, i) => i > 0 ? ["", decl] : [decl]),
|
|
5919
|
-
`let pos = _pos`,
|
|
5920
|
-
|
|
5921
|
-
|
|
6347
|
+
...coverageRootRuleId === void 0 ? [`let pos = _pos`, ...r.stmts, `return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`] : [
|
|
6348
|
+
`const _coverageResult = (() => {`,
|
|
6349
|
+
` let pos = _pos`,
|
|
6350
|
+
...r.stmts,
|
|
6351
|
+
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
6352
|
+
`})()`,
|
|
6353
|
+
`if (!_coverageResult.ok) _ctx._grammarTrace?.write({ id: ${JSON.stringify(coverageRootRuleId)}, phase: 'failure', offset: _coverageResult.span.start })`,
|
|
6354
|
+
`return _coverageResult`
|
|
6355
|
+
]
|
|
5922
6356
|
].join("\n"));
|
|
5923
6357
|
const defaultCtx = {
|
|
5924
6358
|
trackLines: false,
|
|
@@ -5930,10 +6364,11 @@ function compile(combinator, mapFnSources, opts) {
|
|
|
5930
6364
|
const buildSources = ctx.buildFns.length === 0 ? void 0 : ctx.buildSrcs;
|
|
5931
6365
|
const mfCovered = ctx.mapFns.length === 0 || effectiveSources !== void 0 && effectiveSources.length === ctx.mapFns.length;
|
|
5932
6366
|
const canInline = ctx.runtimeParsers.length === 0 && mfCovered && buildCovered;
|
|
5933
|
-
const inlineExpression = canInline ? buildInlineExpression(ctx, r, effectiveSources, buildSources) : null;
|
|
6367
|
+
const inlineExpression = canInline ? buildInlineExpression(ctx, r, effectiveSources, buildSources, coverageRootRuleId) : null;
|
|
5934
6368
|
return {
|
|
5935
6369
|
source,
|
|
5936
6370
|
inlineExpression,
|
|
6371
|
+
...ctx.coverage === void 0 ? {} : { coverageDefinitions: ctx.coverage.plan.definitions },
|
|
5937
6372
|
parse(input, pos = 0) {
|
|
5938
6373
|
return fn(input, pos, ctx.runtimeParsers, ctx.mapFns, ctx.buildFns, defaultCtx);
|
|
5939
6374
|
},
|
|
@@ -5967,6 +6402,7 @@ function publicRuleWrapperSource(rule, fnSource) {
|
|
|
5967
6402
|
}
|
|
5968
6403
|
function compileRuleMap(ruleMap, opts) {
|
|
5969
6404
|
for (const [, rule] of ruleMap) markUnusedValues(rule);
|
|
6405
|
+
const coverageWinners = opts?.coverage ? Object.fromEntries(ruleMap.filter(([, rule]) => rule._def.tag !== "lazy")) : void 0;
|
|
5970
6406
|
const grammarTrivia = opts?.trivia;
|
|
5971
6407
|
const ctx = {
|
|
5972
6408
|
vars: 0,
|
|
@@ -5987,6 +6423,7 @@ function compileRuleMap(ruleMap, opts) {
|
|
|
5987
6423
|
namedFnDecls: [],
|
|
5988
6424
|
capturing: ruleMap.some(([, rule]) => hasNodeDef(rule)),
|
|
5989
6425
|
recovery: opts?.recovery ?? false,
|
|
6426
|
+
...opts?.coverage ? { coverage: { plan: buildGrammarPlan(ruleMap.map(([, rule]) => rule), coverageWinners) } } : {},
|
|
5990
6427
|
lazyUsage: analyzeLazyUsageMulti(ruleMap.map(([, rule]) => rule)),
|
|
5991
6428
|
...grammarTrivia ? { activeTrivia: grammarTrivia, triviaKindLabels: grammarTrivia._meta.triviaKindLabels } : {}
|
|
5992
6429
|
};
|
|
@@ -6029,15 +6466,34 @@ function compileRuleMap(ruleMap, opts) {
|
|
|
6029
6466
|
return i > 0 ? ["", ...lines] : lines;
|
|
6030
6467
|
})
|
|
6031
6468
|
].filter(Boolean);
|
|
6032
|
-
const
|
|
6033
|
-
|
|
6034
|
-
|
|
6035
|
-
|
|
6036
|
-
|
|
6037
|
-
|
|
6038
|
-
|
|
6469
|
+
const entryRuleId = (rule) => {
|
|
6470
|
+
const direct = ctx.coverage?.plan.rules.get(rule);
|
|
6471
|
+
if (direct !== void 0 || rule._def.tag !== "lazy") return direct;
|
|
6472
|
+
try {
|
|
6473
|
+
return ctx.coverage?.plan.rules.get(rule._def.thunk());
|
|
6474
|
+
} catch {
|
|
6475
|
+
return void 0;
|
|
6476
|
+
}
|
|
6477
|
+
};
|
|
6478
|
+
const entryFnText = (r, rule) => {
|
|
6479
|
+
const ruleId = entryRuleId(rule);
|
|
6480
|
+
const body = ruleId === void 0 ? [
|
|
6481
|
+
` let pos = _pos`,
|
|
6482
|
+
...r.stmts,
|
|
6483
|
+
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`
|
|
6484
|
+
] : [
|
|
6485
|
+
` const _coverageResult = (() => {`,
|
|
6486
|
+
` let pos = _pos`,
|
|
6487
|
+
...r.stmts,
|
|
6488
|
+
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
6489
|
+
` })()`,
|
|
6490
|
+
` if (!_coverageResult.ok) _ctx._grammarTrace?.write({ id: ${JSON.stringify(ruleId)}, phase: 'failure', offset: _coverageResult.span.start })`,
|
|
6491
|
+
` return _coverageResult`
|
|
6492
|
+
];
|
|
6493
|
+
return [`function(input, _pos, _ctx) {`, ...body, `}`].join("\n");
|
|
6494
|
+
};
|
|
6039
6495
|
const objBody = perEntry.map(({ key, rule, r }) => {
|
|
6040
|
-
const src = publicRuleWrapperSource(rule, entryFnText(r));
|
|
6496
|
+
const src = publicRuleWrapperSource(rule, entryFnText(r, rule));
|
|
6041
6497
|
return ` ${JSON.stringify(key)}: ${src.split("\n").join("\n ")}`;
|
|
6042
6498
|
}).join(",\n");
|
|
6043
6499
|
const replacement = [
|
|
@@ -6048,7 +6504,11 @@ function compileRuleMap(ruleMap, opts) {
|
|
|
6048
6504
|
` }`,
|
|
6049
6505
|
`})()`
|
|
6050
6506
|
].join("\n");
|
|
6051
|
-
return {
|
|
6507
|
+
return {
|
|
6508
|
+
keys: perEntry.map((e) => e.key),
|
|
6509
|
+
replacement,
|
|
6510
|
+
...ctx.coverage === void 0 ? {} : { coverageDefinitions: ctx.coverage.plan.definitions }
|
|
6511
|
+
};
|
|
6052
6512
|
}
|
|
6053
6513
|
function compileLinkable(ruleMapArg, ns, opts) {
|
|
6054
6514
|
if (!ns) throw new Error("compileLinkable: ns must be a non-empty namespace");
|
|
@@ -6081,8 +6541,13 @@ function compileLinkable(ruleMapArg, ns, opts) {
|
|
|
6081
6541
|
triviaCaptureNames: /* @__PURE__ */ new Map(),
|
|
6082
6542
|
triviaFnNames: /* @__PURE__ */ new Map(),
|
|
6083
6543
|
namedFnDecls: [],
|
|
6084
|
-
|
|
6544
|
+
// A recognition-only fragment normally has no node collector of its own.
|
|
6545
|
+
// Leaf composition can re-lower it beneath a local semantic node, though;
|
|
6546
|
+
// in that case its terminals must feed the caller's collector rather than
|
|
6547
|
+
// merely returning their scalar parse values.
|
|
6548
|
+
capturing: opts?.captureTerminals === true || ruleMap.some(([, rule]) => hasNodeDef(rule)),
|
|
6085
6549
|
recovery: opts?.recovery ?? false,
|
|
6550
|
+
...opts?.coverage ? { coverage: { plan: opts.coverage } } : {},
|
|
6086
6551
|
lazyUsage: analyzeLazyUsageMulti(ruleMap.map(([, rule]) => rule)),
|
|
6087
6552
|
ns,
|
|
6088
6553
|
deferFirstSetRefs: true,
|
|
@@ -6156,7 +6621,14 @@ function compileLinkable(ruleMapArg, ns, opts) {
|
|
|
6156
6621
|
ctx.indent = savedIndent;
|
|
6157
6622
|
ctx.failLabel = savedFail;
|
|
6158
6623
|
ctx.recordFail = savedRec;
|
|
6159
|
-
|
|
6624
|
+
const ruleId = ctx.coverage?.plan.rules.get(rule);
|
|
6625
|
+
const stmts = ruleId === void 0 ? body.stmts : [
|
|
6626
|
+
`${ind(ctx)}_ctx._grammarCoverage?.(${JSON.stringify(ruleId)})`,
|
|
6627
|
+
`${ind(ctx)}_ctx._grammarTrace?.write({ id: ${JSON.stringify(ruleId)}, phase: 'enter', offset: _pos })`,
|
|
6628
|
+
...body.stmts,
|
|
6629
|
+
`${ind(ctx)}_ctx._grammarTrace?.write({ id: ${JSON.stringify(ruleId)}, phase: 'success', offset: _pos, end: ${body.endVar} })`
|
|
6630
|
+
];
|
|
6631
|
+
pushNamedFnDecl(ctx, fn, stmts, body.valueVar, body.endVar);
|
|
6160
6632
|
}
|
|
6161
6633
|
perEntry.push({ key, rule, r: emitNamedFnCall(ctx, fn, "_pos") });
|
|
6162
6634
|
}
|
|
@@ -6213,15 +6685,46 @@ function compileLinkable(ruleMapArg, ns, opts) {
|
|
|
6213
6685
|
deps: ruleDependencies(ruleMap),
|
|
6214
6686
|
needsEmptyTl: !!ctx.needsEmptyTl,
|
|
6215
6687
|
needsHostReads: !!ctx.needsHostReads,
|
|
6688
|
+
hasDirectBuilders: ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
|
|
6689
|
+
isRecognitionOnly: !hasSemanticReduction(ruleMap.map(([, rule]) => rule)),
|
|
6216
6690
|
mfFns: mfSrcs ? [] : ctx.mapFns,
|
|
6217
6691
|
buildFns: buildSrcs ? [] : ctx.buildFns
|
|
6218
6692
|
};
|
|
6219
6693
|
}
|
|
6220
|
-
function
|
|
6221
|
-
const
|
|
6694
|
+
function hasSemanticReduction(roots) {
|
|
6695
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6696
|
+
const visit = (parser2) => {
|
|
6697
|
+
if (seen.has(parser2)) return false;
|
|
6698
|
+
seen.add(parser2);
|
|
6699
|
+
const def = parser2._def;
|
|
6700
|
+
if (def.tag === "transform" && !def.recognitionOnly) return true;
|
|
6701
|
+
if (def.tag === "choice" && def.gates.some(Boolean)) return true;
|
|
6702
|
+
if (def.tag === "guard" || def.tag === "withCtx") return true;
|
|
6703
|
+
if (def.tag === "node" && def.build !== void 0) return true;
|
|
6704
|
+
if (def.tag === "lazy") {
|
|
6705
|
+
try {
|
|
6706
|
+
return visit(def.thunk());
|
|
6707
|
+
} catch {
|
|
6708
|
+
return true;
|
|
6709
|
+
}
|
|
6710
|
+
}
|
|
6711
|
+
return childrenOf(def).some(visit);
|
|
6712
|
+
};
|
|
6713
|
+
return roots.some(visit);
|
|
6714
|
+
}
|
|
6715
|
+
function buildInlineExpression(ctx, r, mapFnSources, buildSources, coverageRootRuleId) {
|
|
6716
|
+
const bodyLines = coverageRootRuleId === void 0 ? [
|
|
6222
6717
|
` let pos = _pos`,
|
|
6223
6718
|
...r.stmts,
|
|
6224
6719
|
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`
|
|
6720
|
+
] : [
|
|
6721
|
+
` const _coverageResult = (() => {`,
|
|
6722
|
+
` let pos = _pos`,
|
|
6723
|
+
...r.stmts,
|
|
6724
|
+
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
6725
|
+
` })()`,
|
|
6726
|
+
` if (!_coverageResult.ok) _ctx._grammarTrace?.write({ id: ${JSON.stringify(coverageRootRuleId)}, phase: 'failure', offset: _coverageResult.span.start })`,
|
|
6727
|
+
` return _coverageResult`
|
|
6225
6728
|
];
|
|
6226
6729
|
const innerFn = [
|
|
6227
6730
|
`function(input, _pos, _ctx) {`,
|
|
@@ -6276,8 +6779,8 @@ function scanTo(sentinel, { skip: skip2 = [], orEOF = false } = {}) {
|
|
|
6276
6779
|
};
|
|
6277
6780
|
const emit2 = (end) => {
|
|
6278
6781
|
if (end > pos && cstCaptureActive(ctx)) {
|
|
6279
|
-
const
|
|
6280
|
-
pushCstLeaf(ctx,
|
|
6782
|
+
const leaf2 = { _tag: "leaf", value: input.slice(pos, end), span: { start: pos, end } };
|
|
6783
|
+
pushCstLeaf(ctx, leaf2);
|
|
6281
6784
|
}
|
|
6282
6785
|
};
|
|
6283
6786
|
while (cur < input.length) {
|
|
@@ -6331,6 +6834,7 @@ function balanced(open, close, options = {}) {
|
|
|
6331
6834
|
);
|
|
6332
6835
|
if (combi._def.tag === "transform") {
|
|
6333
6836
|
combi._def.fnSrc = '([o, parts, c]) => o + parts.map(p => typeof p === "string" ? p : Array.isArray(p) ? p.join("") : "").join("") + (typeof c === "string" ? c : "")';
|
|
6837
|
+
combi._def.recognitionOnly = true;
|
|
6334
6838
|
}
|
|
6335
6839
|
self.define(combi);
|
|
6336
6840
|
return combi;
|
|
@@ -6376,9 +6880,11 @@ function childrenOf2(def) {
|
|
|
6376
6880
|
case "many":
|
|
6377
6881
|
case "oneOrMore":
|
|
6378
6882
|
case "optional":
|
|
6883
|
+
case "attempt":
|
|
6379
6884
|
case "transform":
|
|
6380
6885
|
case "trivia":
|
|
6381
6886
|
case "token":
|
|
6887
|
+
case "leaf":
|
|
6382
6888
|
case "label":
|
|
6383
6889
|
case "field":
|
|
6384
6890
|
case "not":
|
|
@@ -6427,7 +6933,7 @@ function serializeRuleMap(ruleMap) {
|
|
|
6427
6933
|
}
|
|
6428
6934
|
}
|
|
6429
6935
|
function evalRuleMapIR(ir) {
|
|
6430
|
-
const _tf = (child, src) => {
|
|
6936
|
+
const _tf = (child, src, recognitionOnly = false) => {
|
|
6431
6937
|
let fn2;
|
|
6432
6938
|
try {
|
|
6433
6939
|
fn2 = (0, eval)(`(${src})`);
|
|
@@ -6438,11 +6944,31 @@ function evalRuleMapIR(ir) {
|
|
|
6438
6944
|
}
|
|
6439
6945
|
const t = transform(child, fn2);
|
|
6440
6946
|
t._def.fnSrc = src;
|
|
6947
|
+
if (recognitionOnly) t._def.recognitionOnly = true;
|
|
6441
6948
|
return t;
|
|
6442
6949
|
};
|
|
6443
|
-
const
|
|
6444
|
-
|
|
6950
|
+
const _lf = (child, src) => {
|
|
6951
|
+
let fn2;
|
|
6952
|
+
try {
|
|
6953
|
+
fn2 = (0, eval)(`(${src})`);
|
|
6954
|
+
} catch {
|
|
6955
|
+
fn2 = () => {
|
|
6956
|
+
throw new Error("IR leaf fn not materialized");
|
|
6957
|
+
};
|
|
6958
|
+
}
|
|
6959
|
+
const l = leaf(child, fn2);
|
|
6960
|
+
l._def.fnSrc = src;
|
|
6961
|
+
return l;
|
|
6962
|
+
};
|
|
6963
|
+
const _nd = (type, child, src, opts, staticError) => {
|
|
6964
|
+
if (staticError !== void 0 && staticError.length > 0) {
|
|
6965
|
+
throw new Error(`IR direct node builder for ${type} must be macro-static and self-contained; unsupported binding(s): ${staticError.join(", ")}`);
|
|
6966
|
+
}
|
|
6967
|
+
const n = node(type, child, (() => {
|
|
6968
|
+
throw new Error("IR node build requires static re-lowering");
|
|
6969
|
+
}), opts);
|
|
6445
6970
|
n._def.buildSrc = src;
|
|
6971
|
+
if (staticError !== void 0) n._def.buildStaticError = staticError;
|
|
6446
6972
|
return n;
|
|
6447
6973
|
};
|
|
6448
6974
|
const _gch = (items) => {
|
|
@@ -6492,6 +7018,7 @@ function evalRuleMapIR(ir) {
|
|
|
6492
7018
|
"keywords",
|
|
6493
7019
|
"sequence",
|
|
6494
7020
|
"choice",
|
|
7021
|
+
"attempt",
|
|
6495
7022
|
"many",
|
|
6496
7023
|
"oneOrMore",
|
|
6497
7024
|
"optional",
|
|
@@ -6501,6 +7028,7 @@ function evalRuleMapIR(ir) {
|
|
|
6501
7028
|
"parser",
|
|
6502
7029
|
"scanTo",
|
|
6503
7030
|
"token",
|
|
7031
|
+
"leaf",
|
|
6504
7032
|
"transform",
|
|
6505
7033
|
"skip",
|
|
6506
7034
|
"trivia",
|
|
@@ -6508,6 +7036,7 @@ function evalRuleMapIR(ir) {
|
|
|
6508
7036
|
"field",
|
|
6509
7037
|
"expect",
|
|
6510
7038
|
"_tf",
|
|
7039
|
+
"_lf",
|
|
6511
7040
|
"_nd",
|
|
6512
7041
|
"_gch",
|
|
6513
7042
|
"_wc",
|
|
@@ -6521,6 +7050,7 @@ function evalRuleMapIR(ir) {
|
|
|
6521
7050
|
keywords,
|
|
6522
7051
|
sequence,
|
|
6523
7052
|
choice,
|
|
7053
|
+
attempt,
|
|
6524
7054
|
many,
|
|
6525
7055
|
oneOrMore,
|
|
6526
7056
|
optional,
|
|
@@ -6530,6 +7060,7 @@ function evalRuleMapIR(ir) {
|
|
|
6530
7060
|
parser,
|
|
6531
7061
|
scanTo,
|
|
6532
7062
|
token,
|
|
7063
|
+
leaf,
|
|
6533
7064
|
transform,
|
|
6534
7065
|
skip,
|
|
6535
7066
|
trivia,
|
|
@@ -6537,6 +7068,7 @@ function evalRuleMapIR(ir) {
|
|
|
6537
7068
|
field,
|
|
6538
7069
|
expect,
|
|
6539
7070
|
_tf,
|
|
7071
|
+
_lf,
|
|
6540
7072
|
_nd,
|
|
6541
7073
|
_gch,
|
|
6542
7074
|
_wc
|
|
@@ -6668,6 +7200,8 @@ ${body}
|
|
|
6668
7200
|
return `oneOrMore(${kid(def.parser)})`;
|
|
6669
7201
|
case "optional":
|
|
6670
7202
|
return `optional(${kid(def.parser)})`;
|
|
7203
|
+
case "attempt":
|
|
7204
|
+
return `attempt(${kid(def.parser)})`;
|
|
6671
7205
|
case "sepBy":
|
|
6672
7206
|
return `sepBy(${kid(def.parser)}, ${kid(def.separator)})`;
|
|
6673
7207
|
case "not":
|
|
@@ -6676,6 +7210,10 @@ ${body}
|
|
|
6676
7210
|
return `trivia(${kid(def.parser)})`;
|
|
6677
7211
|
case "token":
|
|
6678
7212
|
return `token(${kid(def.parser)})`;
|
|
7213
|
+
case "leaf": {
|
|
7214
|
+
if (def.fnSrc === void 0) throw new Unserializable("leaf without fnSrc");
|
|
7215
|
+
return `_lf(${kid(def.parser)}, ${JSON.stringify(def.fnSrc)})`;
|
|
7216
|
+
}
|
|
6679
7217
|
case "label":
|
|
6680
7218
|
return `label(${JSON.stringify(def.label)}, ${kid(def.parser)})`;
|
|
6681
7219
|
case "field":
|
|
@@ -6688,21 +7226,30 @@ ${body}
|
|
|
6688
7226
|
return `scanTo(${kid(def.sentinel)}, { skip: [${def.skip.map(kid).join(", ")}], orEOF: ${def.orEOF} })`;
|
|
6689
7227
|
case "transform": {
|
|
6690
7228
|
if (def.fnSrc === void 0) throw new Unserializable("transform without fnSrc");
|
|
6691
|
-
return `_tf(${kid(def.parser)}, ${JSON.stringify(def.fnSrc)})`;
|
|
7229
|
+
return `_tf(${kid(def.parser)}, ${JSON.stringify(def.fnSrc)}${def.recognitionOnly ? ", true" : ""})`;
|
|
6692
7230
|
}
|
|
6693
7231
|
case "node": {
|
|
6694
7232
|
if (def.build !== void 0 && def.buildSrc === void 0) throw new Unserializable("node build without buildSrc");
|
|
6695
|
-
const
|
|
7233
|
+
const optEntries = [
|
|
7234
|
+
...def.unwrap ? ["unwrap: true"] : [],
|
|
7235
|
+
...def.collapse ? ["collapse: true"] : [],
|
|
7236
|
+
...def.captureTrivia ? ["captureTrivia: true"] : [],
|
|
7237
|
+
...def.trailingTrivia ? ["trailingTrivia: true"] : []
|
|
7238
|
+
];
|
|
7239
|
+
const opts = optEntries.length > 0 ? `, { ${optEntries.join(", ")} }` : "";
|
|
6696
7240
|
if (def.type === void 0) {
|
|
6697
7241
|
if (def.buildSrc !== void 0) throw new Unserializable("inferred node build without inferred type");
|
|
6698
7242
|
return opts ? `node(${kid(def.parser)}, undefined${opts})` : `node(${kid(def.parser)})`;
|
|
6699
7243
|
}
|
|
6700
|
-
if (def.buildSrc !== void 0)
|
|
7244
|
+
if (def.buildSrc !== void 0) {
|
|
7245
|
+
const staticError = def.buildStaticError === void 0 ? "" : `${opts ? "" : ", undefined"}, ${JSON.stringify(def.buildStaticError)}`;
|
|
7246
|
+
return `_nd(${JSON.stringify(def.type)}, ${kid(def.parser)}, ${JSON.stringify(def.buildSrc)}${opts}${staticError})`;
|
|
7247
|
+
}
|
|
6701
7248
|
return opts ? `node(${JSON.stringify(def.type)}, ${kid(def.parser)}, undefined${opts})` : `node(${JSON.stringify(def.type)}, ${kid(def.parser)})`;
|
|
6702
7249
|
}
|
|
6703
7250
|
case "grammar": {
|
|
6704
7251
|
const trivia2 = def.clearTrivia ? "null" : def.triviaParser ? kid(def.triviaParser) : "undefined";
|
|
6705
|
-
return `parser({ trivia: ${trivia2}${def.trackLines ? ", trackLines: true" : ""} }, ${kid(def.parser)})`;
|
|
7252
|
+
return `parser({ trivia: ${trivia2}${def.captureTrivia ? ", captureTrivia: true" : ""}${def.trackLines ? ", trackLines: true" : ""} }, ${kid(def.parser)})`;
|
|
6706
7253
|
}
|
|
6707
7254
|
case "withCtx": {
|
|
6708
7255
|
if (def.extraSrc === void 0) throw new Unserializable("withCtx without extraSrc");
|
|
@@ -6717,6 +7264,28 @@ ${body}
|
|
|
6717
7264
|
};
|
|
6718
7265
|
|
|
6719
7266
|
// src/compiler/linker.ts
|
|
7267
|
+
function normalizeCstCollapse(collapse) {
|
|
7268
|
+
if (collapse === true) return () => true;
|
|
7269
|
+
if (Array.isArray(collapse)) {
|
|
7270
|
+
const types = new Set(collapse);
|
|
7271
|
+
return (type) => types.has(type);
|
|
7272
|
+
}
|
|
7273
|
+
return typeof collapse === "function" ? collapse : void 0;
|
|
7274
|
+
}
|
|
7275
|
+
function buildCstNode(type, children2, _fields, span, _rawChildren, _triviaLog, state) {
|
|
7276
|
+
return { _tag: "node", type, span: { start: span.start, end: span.end }, state: state ?? null, children: [...children2] };
|
|
7277
|
+
}
|
|
7278
|
+
function cstBuildHost(typeOrOptions, children2, _fields, span, rawChildren, triviaLog, state) {
|
|
7279
|
+
if (typeof typeOrOptions === "string") {
|
|
7280
|
+
return buildCstNode(typeOrOptions, children2 ?? [], _fields, span ?? { start: 0, end: 0 }, rawChildren, triviaLog, state);
|
|
7281
|
+
}
|
|
7282
|
+
const collapse = normalizeCstCollapse(typeOrOptions?.collapse);
|
|
7283
|
+
const host = (type, children3, fields, span2, rawChildren2, triviaLog2, state2) => buildCstNode(type, children3, fields, span2, rawChildren2, triviaLog2, state2);
|
|
7284
|
+
host._parsemanCstOutput = true;
|
|
7285
|
+
if (collapse) host._parsemanCstCollapse = collapse;
|
|
7286
|
+
return host;
|
|
7287
|
+
}
|
|
7288
|
+
cstBuildHost._parsemanCstOutput = true;
|
|
6720
7289
|
function pickPieces(pieces, names) {
|
|
6721
7290
|
const winner = /* @__PURE__ */ new Map();
|
|
6722
7291
|
for (const pc of pieces) for (const k of pc.keys) winner.set(k, pc);
|
|
@@ -6794,9 +7363,12 @@ ${body}
|
|
|
6794
7363
|
function isIRPiece(p) {
|
|
6795
7364
|
return !!p && typeof p === "object" && typeof p.ir === "string" && typeof p.ns === "string" && !("ruleFns" in p);
|
|
6796
7365
|
}
|
|
6797
|
-
function materializePiece(p, trivia2) {
|
|
7366
|
+
function materializePiece(p, trivia2, captureTerminals = false) {
|
|
6798
7367
|
if (!isIRPiece(p)) return p;
|
|
6799
|
-
const pieces = compileLinkable(evalRuleMapIR(p.ir), p.ns,
|
|
7368
|
+
const pieces = compileLinkable(evalRuleMapIR(p.ir), p.ns, {
|
|
7369
|
+
...trivia2 ? { trivia: trivia2 } : {},
|
|
7370
|
+
...captureTerminals ? { captureTerminals: true } : {}
|
|
7371
|
+
});
|
|
6800
7372
|
if (!pieces) throw new Error(`compose: carried IR for ns "${p.ns}" could not be re-lowered`);
|
|
6801
7373
|
return pieces;
|
|
6802
7374
|
}
|
|
@@ -6826,6 +7398,152 @@ var { isFinite } = Number;
|
|
|
6826
7398
|
// src/index.ts
|
|
6827
7399
|
registerRegexAnalyzer(firstSetFromRegex);
|
|
6828
7400
|
|
|
7401
|
+
// src/plugin/direct-builder-static.ts
|
|
7402
|
+
var import_oxc_parser = require("oxc-parser");
|
|
7403
|
+
var STATIC_BUILDER_GLOBALS = /* @__PURE__ */ new Set([
|
|
7404
|
+
"Array",
|
|
7405
|
+
"Boolean",
|
|
7406
|
+
"Date",
|
|
7407
|
+
"JSON",
|
|
7408
|
+
"Math",
|
|
7409
|
+
"NaN",
|
|
7410
|
+
"Number",
|
|
7411
|
+
"Object",
|
|
7412
|
+
"String",
|
|
7413
|
+
"Infinity",
|
|
7414
|
+
"parseFloat",
|
|
7415
|
+
"parseInt",
|
|
7416
|
+
"undefined"
|
|
7417
|
+
]);
|
|
7418
|
+
function astArray(value) {
|
|
7419
|
+
return Array.isArray(value) ? value : [];
|
|
7420
|
+
}
|
|
7421
|
+
function astChild(value) {
|
|
7422
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
7423
|
+
}
|
|
7424
|
+
function unwrapCallbackExpression(node2) {
|
|
7425
|
+
let current = node2;
|
|
7426
|
+
while (current?.type === "ParenthesizedExpression") current = astChild(current.expression) ?? void 0;
|
|
7427
|
+
return current;
|
|
7428
|
+
}
|
|
7429
|
+
function directBuilderUnsupportedBindings(src) {
|
|
7430
|
+
let init;
|
|
7431
|
+
try {
|
|
7432
|
+
const parsed = (0, import_oxc_parser.parseSync)("parseman-direct-builder.ts", `const _direct = (${src})`);
|
|
7433
|
+
if (parsed.errors.length > 0) return ["invalid callback source"];
|
|
7434
|
+
const program = parsed.program;
|
|
7435
|
+
const statement = program.body?.[0];
|
|
7436
|
+
const declaration = statement?.declarations?.[0];
|
|
7437
|
+
init = unwrapCallbackExpression(declaration?.init);
|
|
7438
|
+
} catch {
|
|
7439
|
+
return ["invalid callback source"];
|
|
7440
|
+
}
|
|
7441
|
+
if (init?.type !== "ArrowFunctionExpression" || !Array.isArray(init.params)) return ["unsupported callback shape"];
|
|
7442
|
+
const allowed = new Set(STATIC_BUILDER_GLOBALS);
|
|
7443
|
+
for (const param of init.params) {
|
|
7444
|
+
if (param.type !== "Identifier" || typeof param.name !== "string") return ["unsupported parameter pattern"];
|
|
7445
|
+
allowed.add(param.name);
|
|
7446
|
+
}
|
|
7447
|
+
const unsupported = /* @__PURE__ */ new Set();
|
|
7448
|
+
const reportUnsupportedNode = (ast) => {
|
|
7449
|
+
unsupported.add(`unsupported ${ast.type}`);
|
|
7450
|
+
};
|
|
7451
|
+
const read = (ast, allowedNames) => {
|
|
7452
|
+
if (typeof ast.name === "string" && allowedNames.has(ast.name)) return;
|
|
7453
|
+
unsupported.add(typeof ast.name === "string" ? ast.name : "identifier");
|
|
7454
|
+
};
|
|
7455
|
+
const expression = (node2, allowedNames) => {
|
|
7456
|
+
const ast = astChild(node2);
|
|
7457
|
+
if (!ast) return;
|
|
7458
|
+
switch (ast.type) {
|
|
7459
|
+
case "Literal":
|
|
7460
|
+
return;
|
|
7461
|
+
case "Identifier":
|
|
7462
|
+
read(ast, allowedNames);
|
|
7463
|
+
return;
|
|
7464
|
+
case "ParenthesizedExpression":
|
|
7465
|
+
case "ChainExpression":
|
|
7466
|
+
case "TSAsExpression":
|
|
7467
|
+
case "TSTypeAssertion":
|
|
7468
|
+
case "TSNonNullExpression":
|
|
7469
|
+
expression(ast.expression, allowedNames);
|
|
7470
|
+
return;
|
|
7471
|
+
case "ArrayExpression":
|
|
7472
|
+
for (const element of astArray(ast.elements)) expression(element, allowedNames);
|
|
7473
|
+
return;
|
|
7474
|
+
case "ObjectExpression":
|
|
7475
|
+
for (const property of astArray(ast.properties)) {
|
|
7476
|
+
if (property.type === "SpreadElement") {
|
|
7477
|
+
expression(property.argument, allowedNames);
|
|
7478
|
+
continue;
|
|
7479
|
+
}
|
|
7480
|
+
if (property.type !== "Property" || property.method === true || property.kind !== "init") {
|
|
7481
|
+
reportUnsupportedNode(property);
|
|
7482
|
+
continue;
|
|
7483
|
+
}
|
|
7484
|
+
if (property.computed === true) expression(property.key, allowedNames);
|
|
7485
|
+
expression(property.value, allowedNames);
|
|
7486
|
+
}
|
|
7487
|
+
return;
|
|
7488
|
+
case "MemberExpression":
|
|
7489
|
+
expression(ast.object, allowedNames);
|
|
7490
|
+
if (ast.computed === true) expression(ast.property, allowedNames);
|
|
7491
|
+
return;
|
|
7492
|
+
case "CallExpression":
|
|
7493
|
+
case "NewExpression":
|
|
7494
|
+
expression(ast.callee, allowedNames);
|
|
7495
|
+
for (const argument of astArray(ast.arguments)) expression(argument, allowedNames);
|
|
7496
|
+
return;
|
|
7497
|
+
case "UnaryExpression":
|
|
7498
|
+
case "UpdateExpression":
|
|
7499
|
+
expression(ast.argument, allowedNames);
|
|
7500
|
+
return;
|
|
7501
|
+
case "BinaryExpression":
|
|
7502
|
+
case "LogicalExpression":
|
|
7503
|
+
case "AssignmentExpression":
|
|
7504
|
+
expression(ast.left, allowedNames);
|
|
7505
|
+
expression(ast.right, allowedNames);
|
|
7506
|
+
return;
|
|
7507
|
+
case "ConditionalExpression":
|
|
7508
|
+
expression(ast.test, allowedNames);
|
|
7509
|
+
expression(ast.consequent, allowedNames);
|
|
7510
|
+
expression(ast.alternate, allowedNames);
|
|
7511
|
+
return;
|
|
7512
|
+
case "SequenceExpression":
|
|
7513
|
+
for (const value of astArray(ast.expressions)) expression(value, allowedNames);
|
|
7514
|
+
return;
|
|
7515
|
+
case "TemplateLiteral":
|
|
7516
|
+
for (const value of astArray(ast.expressions)) expression(value, allowedNames);
|
|
7517
|
+
return;
|
|
7518
|
+
case "SpreadElement":
|
|
7519
|
+
expression(ast.argument, allowedNames);
|
|
7520
|
+
return;
|
|
7521
|
+
case "ArrowFunctionExpression": {
|
|
7522
|
+
const nested = new Set(allowedNames);
|
|
7523
|
+
for (const param of astArray(ast.params)) {
|
|
7524
|
+
if (param.type !== "Identifier" || typeof param.name !== "string") {
|
|
7525
|
+
reportUnsupportedNode(param);
|
|
7526
|
+
continue;
|
|
7527
|
+
}
|
|
7528
|
+
nested.add(param.name);
|
|
7529
|
+
}
|
|
7530
|
+
if (astChild(ast.body)?.type === "BlockStatement") {
|
|
7531
|
+
reportUnsupportedNode(astChild(ast.body));
|
|
7532
|
+
return;
|
|
7533
|
+
}
|
|
7534
|
+
expression(ast.body, nested);
|
|
7535
|
+
return;
|
|
7536
|
+
}
|
|
7537
|
+
default:
|
|
7538
|
+
reportUnsupportedNode(ast);
|
|
7539
|
+
return;
|
|
7540
|
+
}
|
|
7541
|
+
};
|
|
7542
|
+
if (astChild(init.body)?.type === "BlockStatement") unsupported.add("unsupported BlockStatement");
|
|
7543
|
+
else expression(init.body, allowed);
|
|
7544
|
+
return [...unsupported];
|
|
7545
|
+
}
|
|
7546
|
+
|
|
6829
7547
|
// src/plugin/evaluator.ts
|
|
6830
7548
|
function stripTsFromSource(node2, code) {
|
|
6831
7549
|
const cuts = [];
|
|
@@ -6879,15 +7597,18 @@ var SUPPORTED = {
|
|
|
6879
7597
|
word: (...a) => word(a[0], a[1]),
|
|
6880
7598
|
sequence: (...a) => sequence(...a),
|
|
6881
7599
|
choice: (...a) => choice(...a),
|
|
7600
|
+
attempt: (...a) => attempt(a[0]),
|
|
6882
7601
|
many: (...a) => many(a[0]),
|
|
6883
7602
|
oneOrMore: (...a) => oneOrMore(a[0]),
|
|
6884
7603
|
optional: (...a) => optional(a[0]),
|
|
7604
|
+
skip: (...a) => skip(a[0], a[1]),
|
|
6885
7605
|
sepBy: (...a) => sepBy(a[0], a[1]),
|
|
6886
7606
|
trivia: (...a) => trivia(a[0]),
|
|
6887
7607
|
label: (...a) => label(a[0], a[1]),
|
|
6888
7608
|
field: (...a) => field(a[0], a[1]),
|
|
6889
7609
|
noTrivia: (...a) => noTrivia(a[0]),
|
|
6890
7610
|
token: (...a) => token(a[0]),
|
|
7611
|
+
leaf: (...a) => leaf(a[0], a[1]),
|
|
6891
7612
|
expect: (...a) => expect(a[0], a[1])
|
|
6892
7613
|
};
|
|
6893
7614
|
function isScopeEntry(v2) {
|
|
@@ -6943,12 +7664,12 @@ function staticNodeOptions(expr) {
|
|
|
6943
7664
|
if (p.computed) continue;
|
|
6944
7665
|
const key = p.key;
|
|
6945
7666
|
const name = key.type === "Identifier" ? key.name : key.type === "Literal" ? String(key.value) : void 0;
|
|
6946
|
-
if (name === "unwrap" || name === "collapse") {
|
|
7667
|
+
if (name === "unwrap" || name === "collapse" || name === "captureTrivia" || name === "trailingTrivia") {
|
|
6947
7668
|
const val = p.value;
|
|
6948
7669
|
if ((val.type === "Literal" || val.type === "BooleanLiteral") && val.value === true) opts[name] = true;
|
|
6949
7670
|
}
|
|
6950
7671
|
}
|
|
6951
|
-
return opts.unwrap || opts.collapse ? opts : void 0;
|
|
7672
|
+
return opts.unwrap || opts.collapse || opts.captureTrivia || opts.trailingTrivia ? opts : void 0;
|
|
6952
7673
|
}
|
|
6953
7674
|
function exprToCombi(node2, scope, code, mfs) {
|
|
6954
7675
|
if (node2.type === "Identifier") return scopeGet(scope, node2.name, mfs);
|
|
@@ -6987,7 +7708,7 @@ function exprToCombi(node2, scope, code, mfs) {
|
|
|
6987
7708
|
if (!parserArg || !fnArg || parserArg.type === "SpreadElement" || fnArg.type === "SpreadElement") return null;
|
|
6988
7709
|
const inner = anyValue(parserArg, scope, code, mfs);
|
|
6989
7710
|
if (!isCombinator(inner)) return null;
|
|
6990
|
-
const fnSrc =
|
|
7711
|
+
const fnSrc = stripTsFromSource(fnArg, code);
|
|
6991
7712
|
mfs.push(fnSrc);
|
|
6992
7713
|
try {
|
|
6993
7714
|
const combi = transform(inner, (v2) => v2);
|
|
@@ -6997,6 +7718,21 @@ function exprToCombi(node2, scope, code, mfs) {
|
|
|
6997
7718
|
return null;
|
|
6998
7719
|
}
|
|
6999
7720
|
}
|
|
7721
|
+
if (callee.name === "leaf" && code !== void 0 && mfs !== void 0) {
|
|
7722
|
+
const [parserArg, fnArg] = node2.arguments;
|
|
7723
|
+
if (!parserArg || !fnArg || parserArg.type === "SpreadElement" || fnArg.type === "SpreadElement") return null;
|
|
7724
|
+
const inner = anyValue(parserArg, scope, code, mfs);
|
|
7725
|
+
if (!isCombinator(inner)) return null;
|
|
7726
|
+
const fnSrc = stripTsFromSource(fnArg, code);
|
|
7727
|
+
mfs.push(fnSrc);
|
|
7728
|
+
try {
|
|
7729
|
+
const combi = leaf(inner, (v2) => v2);
|
|
7730
|
+
if (combi._def.tag === "leaf") combi._def.fnSrc = fnSrc;
|
|
7731
|
+
return combi;
|
|
7732
|
+
} catch {
|
|
7733
|
+
return null;
|
|
7734
|
+
}
|
|
7735
|
+
}
|
|
7000
7736
|
if (callee.name === "node" && code !== void 0) {
|
|
7001
7737
|
const [firstArg, secondArg, thirdArg, fourthArg] = node2.arguments;
|
|
7002
7738
|
if (!firstArg || firstArg.type === "SpreadElement") return null;
|
|
@@ -7010,11 +7746,15 @@ function exprToCombi(node2, scope, code, mfs) {
|
|
|
7010
7746
|
if (!isCombinator(inner)) return null;
|
|
7011
7747
|
const be = buildArg;
|
|
7012
7748
|
const hasBuild = be !== void 0 && be.type !== "SpreadElement" && !(be.type === "Identifier" && be.name === "undefined");
|
|
7013
|
-
const buildSrc = hasBuild ?
|
|
7749
|
+
const buildSrc = hasBuild ? stripTsFromSource(be, code) : void 0;
|
|
7014
7750
|
const opts = optsArg !== void 0 && optsArg.type !== "SpreadElement" ? staticNodeOptions(optsArg) : void 0;
|
|
7015
7751
|
try {
|
|
7016
7752
|
const combi = explicitType !== void 0 ? node(explicitType, inner, hasBuild ? () => null : void 0, opts) : node(inner, hasBuild ? () => null : void 0, opts);
|
|
7017
|
-
if (combi._def.tag === "node" && buildSrc !== void 0)
|
|
7753
|
+
if (combi._def.tag === "node" && buildSrc !== void 0) {
|
|
7754
|
+
combi._def.buildSrc = buildSrc;
|
|
7755
|
+
const staticError = directBuilderUnsupportedBindings(buildSrc);
|
|
7756
|
+
if (staticError.length > 0) combi._def.buildStaticError = staticError;
|
|
7757
|
+
}
|
|
7018
7758
|
return combi;
|
|
7019
7759
|
} catch {
|
|
7020
7760
|
return null;
|
|
@@ -7107,7 +7847,7 @@ function exprToCombi(node2, scope, code, mfs) {
|
|
|
7107
7847
|
if (code === void 0 || mfs === void 0) return null;
|
|
7108
7848
|
const [predArg] = node2.arguments;
|
|
7109
7849
|
if (!predArg || predArg.type === "SpreadElement") return null;
|
|
7110
|
-
const predSrc =
|
|
7850
|
+
const predSrc = stripTsFromSource(predArg, code);
|
|
7111
7851
|
mfs.push(predSrc);
|
|
7112
7852
|
try {
|
|
7113
7853
|
const combi = guard(() => true);
|
|
@@ -7122,7 +7862,7 @@ function exprToCombi(node2, scope, code, mfs) {
|
|
|
7122
7862
|
if (code === void 0 || mfs === void 0) return null;
|
|
7123
7863
|
const [extraArg, innerArg] = node2.arguments;
|
|
7124
7864
|
if (!extraArg || !innerArg || extraArg.type === "SpreadElement" || innerArg.type === "SpreadElement") return null;
|
|
7125
|
-
const extraSrc =
|
|
7865
|
+
const extraSrc = stripTsFromSource(extraArg, code);
|
|
7126
7866
|
mfs.push(extraSrc);
|
|
7127
7867
|
const inner = anyValue(innerArg, scope, code, mfs);
|
|
7128
7868
|
if (!isCombinator(inner)) return null;
|
|
@@ -7445,6 +8185,63 @@ function getCompiledResolver() {
|
|
|
7445
8185
|
mainFields: ["module", "main"]
|
|
7446
8186
|
});
|
|
7447
8187
|
}
|
|
8188
|
+
var PRIVATE_SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".mts", ".cts"]);
|
|
8189
|
+
function nearestPackageRoot(file) {
|
|
8190
|
+
let dir = path.dirname(file);
|
|
8191
|
+
for (; ; ) {
|
|
8192
|
+
try {
|
|
8193
|
+
if (fs.statSync(path.join(dir, "package.json")).isFile()) return fs.realpathSync(dir);
|
|
8194
|
+
} catch {
|
|
8195
|
+
}
|
|
8196
|
+
const parent = path.dirname(dir);
|
|
8197
|
+
if (parent === dir) return null;
|
|
8198
|
+
dir = parent;
|
|
8199
|
+
}
|
|
8200
|
+
}
|
|
8201
|
+
function isWithinPackageRoot(file, root) {
|
|
8202
|
+
const relative2 = path.relative(root, file);
|
|
8203
|
+
return relative2 !== ".." && !relative2.startsWith(`..${path.sep}`) && !path.isAbsolute(relative2);
|
|
8204
|
+
}
|
|
8205
|
+
function resolvePrivateSourceModule(from, specifier) {
|
|
8206
|
+
if (!specifier.startsWith(".") && !path.isAbsolute(specifier)) return null;
|
|
8207
|
+
const packageRoot = nearestPackageRoot(from);
|
|
8208
|
+
if (!packageRoot) return null;
|
|
8209
|
+
const base = path.resolve(path.dirname(from), specifier);
|
|
8210
|
+
const ext = path.extname(base);
|
|
8211
|
+
const candidates = [
|
|
8212
|
+
base,
|
|
8213
|
+
...ext ? [".ts", ".tsx", ".mts", ".cts"].map((next) => `${base.slice(0, -ext.length)}${next}`) : [],
|
|
8214
|
+
...!ext ? [".ts", ".tsx", ".mts", ".cts"].map((next) => `${base}${next}`) : [],
|
|
8215
|
+
...!ext ? ["index.ts", "index.tsx", "index.mts", "index.cts"].map((next) => path.join(base, next)) : []
|
|
8216
|
+
];
|
|
8217
|
+
for (const candidate of candidates) {
|
|
8218
|
+
try {
|
|
8219
|
+
if (!fs.statSync(candidate).isFile()) continue;
|
|
8220
|
+
const real = fs.realpathSync(candidate);
|
|
8221
|
+
if (isWithinPackageRoot(real, packageRoot)) return real;
|
|
8222
|
+
} catch {
|
|
8223
|
+
}
|
|
8224
|
+
}
|
|
8225
|
+
return null;
|
|
8226
|
+
}
|
|
8227
|
+
function resolveGrammarModule(from, specifier) {
|
|
8228
|
+
if (PRIVATE_SOURCE_EXTENSIONS.has(path.extname(specifier))) {
|
|
8229
|
+
const file2 = resolvePrivateSourceModule(from, specifier);
|
|
8230
|
+
return file2 ? { file: file2, source: true } : null;
|
|
8231
|
+
}
|
|
8232
|
+
try {
|
|
8233
|
+
const file2 = getCompiledResolver().resolveFileSync(from, specifier).path;
|
|
8234
|
+
if (file2) return { file: file2, source: false };
|
|
8235
|
+
} catch {
|
|
8236
|
+
}
|
|
8237
|
+
const file = resolvePrivateSourceModule(from, specifier);
|
|
8238
|
+
return file ? { file, source: true } : null;
|
|
8239
|
+
}
|
|
8240
|
+
var _sourceLowering = /* @__PURE__ */ new Set();
|
|
8241
|
+
var _sourceLoweringCache = /* @__PURE__ */ new Map();
|
|
8242
|
+
function sourceLoweringCacheKey(file, moduleAliases, warnUnloweredRegex, recovery) {
|
|
8243
|
+
return `${file}\0${[...moduleAliases].sort().join("\0")}\0${warnUnloweredRegex ? "warn" : ""}\0${recovery ? "recovery" : ""}`;
|
|
8244
|
+
}
|
|
7448
8245
|
var _moduleParseCache = /* @__PURE__ */ new Map();
|
|
7449
8246
|
function parseModuleCached(filePath) {
|
|
7450
8247
|
let mtimeMs;
|
|
@@ -7458,7 +8255,7 @@ function parseModuleCached(filePath) {
|
|
|
7458
8255
|
let parsed = null;
|
|
7459
8256
|
try {
|
|
7460
8257
|
const src = fs.readFileSync(filePath, "utf8");
|
|
7461
|
-
const r = (0,
|
|
8258
|
+
const r = (0, import_oxc_parser2.parseSync)(filePath, src);
|
|
7462
8259
|
if (r.errors.length === 0) parsed = { body: r.program.body, src };
|
|
7463
8260
|
} catch {
|
|
7464
8261
|
}
|
|
@@ -7478,7 +8275,7 @@ var plugin_default = (0, import_unplugin.createUnplugin)((opts = {}) => ({
|
|
|
7478
8275
|
if (!code.includes("parseman")) return null;
|
|
7479
8276
|
if (!code.includes("macro")) return null;
|
|
7480
8277
|
const moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE, ...opts.moduleAliases ?? []]);
|
|
7481
|
-
const result = transformMacro(code, id, moduleAliases, opts.warnUnloweredRegex === true, opts.recovery === true);
|
|
8278
|
+
const result = transformMacro(code, id, moduleAliases, opts.warnUnloweredRegex === true, opts.recovery === true, opts.grammarCoverage === true);
|
|
7482
8279
|
if (result?.warnings.length) {
|
|
7483
8280
|
for (const w of result.warnings) {
|
|
7484
8281
|
if (typeof this?.warn === "function") this.warn(`[parseman] ${w}`);
|
|
@@ -7582,10 +8379,37 @@ function extractImportBindings(body) {
|
|
|
7582
8379
|
}
|
|
7583
8380
|
return out;
|
|
7584
8381
|
}
|
|
7585
|
-
function
|
|
8382
|
+
function lowerPrivateSourceModule(file, moduleAliases, warnUnloweredRegex, recovery) {
|
|
8383
|
+
if (_sourceLowering.has(file)) return null;
|
|
8384
|
+
let mtimeMs;
|
|
8385
|
+
try {
|
|
8386
|
+
mtimeMs = fs.statSync(file).mtimeMs;
|
|
8387
|
+
} catch {
|
|
8388
|
+
return null;
|
|
8389
|
+
}
|
|
8390
|
+
const cacheKey = sourceLoweringCacheKey(file, moduleAliases, warnUnloweredRegex, recovery);
|
|
8391
|
+
const hit = _sourceLoweringCache.get(cacheKey);
|
|
8392
|
+
if (hit && hit.mtimeMs === mtimeMs) return hit.parsed;
|
|
8393
|
+
_sourceLowering.add(file);
|
|
8394
|
+
let parsedModule = null;
|
|
8395
|
+
try {
|
|
8396
|
+
const source = fs.readFileSync(file, "utf8");
|
|
8397
|
+
const transformed = transformMacro(source, file, moduleAliases, warnUnloweredRegex, recovery);
|
|
8398
|
+
if (!transformed || transformed.warnings.length > 0) return null;
|
|
8399
|
+
const parsed = (0, import_oxc_parser2.parseSync)(file, transformed.code);
|
|
8400
|
+
parsedModule = parsed.errors.length === 0 ? { body: parsed.program.body, src: transformed.code } : null;
|
|
8401
|
+
return parsedModule;
|
|
8402
|
+
} catch {
|
|
8403
|
+
return null;
|
|
8404
|
+
} finally {
|
|
8405
|
+
_sourceLoweringCache.set(cacheKey, { mtimeMs, parsed: parsedModule });
|
|
8406
|
+
_sourceLowering.delete(file);
|
|
8407
|
+
}
|
|
8408
|
+
}
|
|
8409
|
+
function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE]), warnUnloweredRegex = false, recovery = false, grammarCoverage = false) {
|
|
7586
8410
|
let result;
|
|
7587
8411
|
try {
|
|
7588
|
-
result = (0,
|
|
8412
|
+
result = (0, import_oxc_parser2.parseSync)(id, code);
|
|
7589
8413
|
} catch {
|
|
7590
8414
|
return null;
|
|
7591
8415
|
}
|
|
@@ -7623,6 +8447,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7623
8447
|
const warnings = [];
|
|
7624
8448
|
beginLoweringCapture();
|
|
7625
8449
|
let anyUnresolved = false;
|
|
8450
|
+
let runtimeComposeFallback = false;
|
|
7626
8451
|
let ruleMapHolderCounter = 0;
|
|
7627
8452
|
const lineOf = (pos) => {
|
|
7628
8453
|
let line = 1;
|
|
@@ -7633,7 +8458,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7633
8458
|
anyUnresolved = true;
|
|
7634
8459
|
warnings.push(`${id}:${lineOf(pos)} \u2014 ${msg} (running via the interpreter; add the plugin or simplify the declaration to compile it)`);
|
|
7635
8460
|
};
|
|
7636
|
-
const
|
|
8461
|
+
const evaluateRulesFactory = (init, label2) => {
|
|
7637
8462
|
const args = init.arguments;
|
|
7638
8463
|
const arg0 = args[0];
|
|
7639
8464
|
const arg1 = args[1];
|
|
@@ -7653,15 +8478,21 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7653
8478
|
(p) => p.key?.name === "trivia"
|
|
7654
8479
|
)?.value : void 0;
|
|
7655
8480
|
const gTrivia = triviaValue ? evaluateExpr(triviaValue, scope, code, []) : void 0;
|
|
7656
|
-
|
|
8481
|
+
return { ruleMap, ...gTrivia ? { trivia: gTrivia } : {} };
|
|
8482
|
+
};
|
|
8483
|
+
const compileRulesFactory = (init, label2) => {
|
|
8484
|
+
const evaluated = evaluateRulesFactory(init, label2);
|
|
8485
|
+
if (!evaluated) return null;
|
|
8486
|
+
const compiled = compileRuleMap([...evaluated.ruleMap], { ...evaluated.trivia ? { trivia: evaluated.trivia } : {}, recovery, coverage: grammarCoverage });
|
|
7657
8487
|
if (!compiled) {
|
|
7658
8488
|
warn(init.start, `${label2}: rule map couldn't be inlined`);
|
|
7659
8489
|
return null;
|
|
7660
8490
|
}
|
|
7661
|
-
return { replacement: compiled.replacement, ruleMap, ...
|
|
8491
|
+
return { replacement: compiled.replacement, ruleMap: evaluated.ruleMap, ...compiled.coverageDefinitions ? { coverageDefinitions: compiled.coverageDefinitions } : {}, ...evaluated.trivia ? { trivia: evaluated.trivia } : {} };
|
|
7662
8492
|
};
|
|
7663
8493
|
const isRulesCall = (init) => init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "rules";
|
|
7664
8494
|
const isComposeCall = (init) => init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "compose";
|
|
8495
|
+
const isComposeLeafCall = (init) => init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "composeLeaf";
|
|
7665
8496
|
const isPickCall = (init) => init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "pick";
|
|
7666
8497
|
const localRuleMaps = /* @__PURE__ */ new Map();
|
|
7667
8498
|
const localGrammarTrivia = /* @__PURE__ */ new Map();
|
|
@@ -7671,18 +8502,29 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7671
8502
|
const mapLit = (m, stripVals = false) => `new Map([${[...m].map(
|
|
7672
8503
|
([k, v2]) => `[${JSON.stringify(k)}, ${JSON.stringify(stripVals && typeof v2 === "string" ? stripIndent(v2) : v2)}]`
|
|
7673
8504
|
).join(", ")}])`;
|
|
7674
|
-
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: [] }`;
|
|
8505
|
+
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: [] }`;
|
|
7675
8506
|
};
|
|
7676
8507
|
const isSpread = (it) => "__spreadLocal" in it;
|
|
7677
8508
|
const isIR = (it) => "ir" in it && !("ruleFns" in it);
|
|
7678
8509
|
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);
|
|
7679
8510
|
const serializeList = (list) => `[${list.map(serializeItem).join(", ")}]`;
|
|
7680
8511
|
const withCarriedPieces = (grammarExpr, list) => `/* @__PURE__ */ Object.defineProperty(${grammarExpr}, Symbol.for('parseman.composedPieces'), { value: ${serializeList(list)}, enumerable: false })`;
|
|
8512
|
+
const withLeafMarker = (grammarExpr) => `/* @__PURE__ */ Object.defineProperty(${grammarExpr}, Symbol.for('parseman.leafComposed'), { value: true, enumerable: false })`;
|
|
8513
|
+
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 })`;
|
|
8514
|
+
const emittedCoverageDefinitions = (source) => {
|
|
8515
|
+
const ids = /* @__PURE__ */ new Set();
|
|
8516
|
+
for (const match of source.matchAll(/id:\s*"([^"]+)"/g)) ids.add(match[1]);
|
|
8517
|
+
return [...ids].sort().map((id2) => ({
|
|
8518
|
+
id: id2,
|
|
8519
|
+
kind: id2.startsWith("rule:") ? "rule" : id2.startsWith("label:") ? "label" : "choice-arm"
|
|
8520
|
+
}));
|
|
8521
|
+
};
|
|
7681
8522
|
const localComposedCarried = /* @__PURE__ */ new Map();
|
|
7682
8523
|
const localComposedTrivia = /* @__PURE__ */ new Map();
|
|
7683
8524
|
const importedPiecesCache = /* @__PURE__ */ new Map();
|
|
7684
|
-
const resolveModulePieces = (
|
|
7685
|
-
const
|
|
8525
|
+
const resolveModulePieces = (module2, exportName, seen) => {
|
|
8526
|
+
const { file } = module2;
|
|
8527
|
+
const mod = module2.source ? lowerPrivateSourceModule(file, moduleAliases, warnUnloweredRegex, recovery) : parseModuleCached(file);
|
|
7686
8528
|
if (!mod) return null;
|
|
7687
8529
|
const localFor = exportLocalName(mod.body, exportName);
|
|
7688
8530
|
const initNode = localFor ? topLevelInit(mod.body, localFor) : null;
|
|
@@ -7701,12 +8543,10 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7701
8543
|
const b = imports.get(local);
|
|
7702
8544
|
let subPieces = [];
|
|
7703
8545
|
if (b) {
|
|
7704
|
-
|
|
7705
|
-
|
|
7706
|
-
|
|
7707
|
-
} catch {
|
|
8546
|
+
const subModule = resolveGrammarModule(file, b.source);
|
|
8547
|
+
if (subModule && !seen.has(subModule.file)) {
|
|
8548
|
+
subPieces = resolveModulePieces(subModule, b.imported, new Set(seen).add(subModule.file)) ?? [];
|
|
7708
8549
|
}
|
|
7709
|
-
if (subFile && !seen.has(subFile)) subPieces = resolveModulePieces(subFile, b.imported, new Set(seen).add(subFile)) ?? [];
|
|
7710
8550
|
}
|
|
7711
8551
|
stubNames.push(local);
|
|
7712
8552
|
stubVals.push({ [/* @__PURE__ */ Symbol.for("parseman.composedPieces")]: subPieces });
|
|
@@ -7723,29 +8563,56 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7723
8563
|
let result2 = null;
|
|
7724
8564
|
const binding = importBindings.get(localName);
|
|
7725
8565
|
if (binding) {
|
|
7726
|
-
|
|
7727
|
-
|
|
7728
|
-
file = getCompiledResolver().resolveFileSync(id, binding.source).path ?? null;
|
|
7729
|
-
} catch {
|
|
7730
|
-
}
|
|
7731
|
-
result2 = file ? resolveModulePieces(file, binding.imported, /* @__PURE__ */ new Set([file])) : null;
|
|
8566
|
+
const module2 = resolveGrammarModule(id, binding.source);
|
|
8567
|
+
result2 = module2 ? resolveModulePieces(module2, binding.imported, /* @__PURE__ */ new Set([module2.file])) : null;
|
|
7732
8568
|
}
|
|
7733
8569
|
importedPiecesCache.set(localName, result2);
|
|
7734
8570
|
return result2;
|
|
7735
8571
|
};
|
|
7736
|
-
const materializeCarried = (items, composing) => {
|
|
8572
|
+
const materializeCarried = (items, composing, captureTerminals = false) => {
|
|
7737
8573
|
const out = [];
|
|
7738
8574
|
for (const it of items) {
|
|
7739
8575
|
if (isSpread(it)) {
|
|
7740
|
-
for (const p of importedPieces(it.__spreadLocal) ?? []) out.push(materializePiece(p, composing));
|
|
8576
|
+
for (const p of importedPieces(it.__spreadLocal) ?? []) out.push(materializePiece(p, composing, captureTerminals));
|
|
7741
8577
|
} else if (isIR(it)) {
|
|
7742
|
-
out.push(materializePiece(it, composing));
|
|
8578
|
+
out.push(materializePiece(it, composing, captureTerminals));
|
|
7743
8579
|
} else {
|
|
7744
8580
|
out.push(it);
|
|
7745
8581
|
}
|
|
7746
8582
|
}
|
|
7747
8583
|
return out;
|
|
7748
8584
|
};
|
|
8585
|
+
const materializeLeafCoverage = (items, localRules, localNs, composing, captureTerminals = false) => {
|
|
8586
|
+
const sources = [];
|
|
8587
|
+
const add = (item) => {
|
|
8588
|
+
if (!isIR(item)) return false;
|
|
8589
|
+
sources.push({ ns: item.ns, rules: evalRuleMapIR(item.ir) });
|
|
8590
|
+
return true;
|
|
8591
|
+
};
|
|
8592
|
+
for (const item of items) {
|
|
8593
|
+
if (isSpread(item)) {
|
|
8594
|
+
const imported = importedPieces(item.__spreadLocal);
|
|
8595
|
+
if (!imported || !imported.every(add)) return null;
|
|
8596
|
+
} else if (!add(item)) return null;
|
|
8597
|
+
}
|
|
8598
|
+
sources.push({ ns: localNs, rules: [...localRules] });
|
|
8599
|
+
const winners = {};
|
|
8600
|
+
for (const source of sources) for (const [name, rule] of source.rules) winners[name] = rule;
|
|
8601
|
+
const plan = buildGrammarPlan(Object.values(winners), winners);
|
|
8602
|
+
const pieces = [];
|
|
8603
|
+
for (let index = 0; index < sources.length; index++) {
|
|
8604
|
+
const source = sources[index];
|
|
8605
|
+
const piece = compileLinkable(source.rules, source.ns, {
|
|
8606
|
+
...composing ? { trivia: composing } : {},
|
|
8607
|
+
recovery,
|
|
8608
|
+
...index < sources.length - 1 && captureTerminals ? { captureTerminals: true } : {},
|
|
8609
|
+
coverage: plan
|
|
8610
|
+
});
|
|
8611
|
+
if (!piece) return null;
|
|
8612
|
+
pieces.push(piece);
|
|
8613
|
+
}
|
|
8614
|
+
return pieces;
|
|
8615
|
+
};
|
|
7749
8616
|
const localCarried = (rm, label2, composing) => {
|
|
7750
8617
|
const entries = [...rm];
|
|
7751
8618
|
const ns = nsFor(label2);
|
|
@@ -7861,6 +8728,64 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7861
8728
|
return null;
|
|
7862
8729
|
}
|
|
7863
8730
|
};
|
|
8731
|
+
const compileComposeLeafCall = (init) => {
|
|
8732
|
+
const args = init.arguments;
|
|
8733
|
+
const arr = args[0];
|
|
8734
|
+
if (!arr || arr.type !== "ArrayExpression") {
|
|
8735
|
+
warn(init.start, "composeLeaf(): expected a static array of grammars");
|
|
8736
|
+
return null;
|
|
8737
|
+
}
|
|
8738
|
+
const elements = arr.elements;
|
|
8739
|
+
if (elements.length < 2) {
|
|
8740
|
+
warn(init.start, "composeLeaf(): needs imported recognition grammar(s) and one local rules() map");
|
|
8741
|
+
return null;
|
|
8742
|
+
}
|
|
8743
|
+
const localArg = elements[elements.length - 1];
|
|
8744
|
+
let localRules = null;
|
|
8745
|
+
if (isRulesCall(localArg)) {
|
|
8746
|
+
const evaluated = evaluateRulesFactory(localArg, `composeLeaf${init.start}`);
|
|
8747
|
+
localRules = evaluated?.ruleMap ?? null;
|
|
8748
|
+
} else if (localArg.type === "Identifier") {
|
|
8749
|
+
localRules = localRuleMaps.get(localArg.name) ?? null;
|
|
8750
|
+
}
|
|
8751
|
+
if (!localRules) {
|
|
8752
|
+
warn(init.start, "composeLeaf(): final argument must be a local rules() map");
|
|
8753
|
+
return null;
|
|
8754
|
+
}
|
|
8755
|
+
const composing = composingTrivia(elements);
|
|
8756
|
+
const carried = [];
|
|
8757
|
+
for (let i = 0; i < elements.length - 1; i++) {
|
|
8758
|
+
const r = argPieces(elements[i], `composeLeaf${init.start}_${i}`, composing);
|
|
8759
|
+
if (!r) {
|
|
8760
|
+
warn(init.start, `composeLeaf(): argument ${i} isn't a build-resolvable recognition grammar`);
|
|
8761
|
+
return null;
|
|
8762
|
+
}
|
|
8763
|
+
carried.push(...r.carried);
|
|
8764
|
+
}
|
|
8765
|
+
try {
|
|
8766
|
+
const localNs = nsFor(`composeLeaf${init.start}`);
|
|
8767
|
+
const plainLocalPiece = compileLinkable([...localRules], localNs, { ...composing ? { trivia: composing } : {}, recovery });
|
|
8768
|
+
if (!plainLocalPiece) {
|
|
8769
|
+
warn(init.start, "composeLeaf(): local rules could not be statically compiled");
|
|
8770
|
+
return null;
|
|
8771
|
+
}
|
|
8772
|
+
const recognitionPieces = grammarCoverage ? materializeLeafCoverage(carried, localRules, localNs, composing, plainLocalPiece.hasDirectBuilders === true) : materializeCarried(carried, composing, plainLocalPiece.hasDirectBuilders === true);
|
|
8773
|
+
if (!recognitionPieces) {
|
|
8774
|
+
warn(init.start, "composeLeaf(): coverage needs re-lowerable recognition IR");
|
|
8775
|
+
return null;
|
|
8776
|
+
}
|
|
8777
|
+
const importedRecognitionPieces = grammarCoverage ? recognitionPieces.slice(0, -1) : recognitionPieces;
|
|
8778
|
+
if (importedRecognitionPieces.some((piece) => piece.hasDirectBuilders !== false || piece.isRecognitionOnly !== true)) {
|
|
8779
|
+
warn(init.start, "composeLeaf(): every pre-final grammar must explicitly prove recognition-only");
|
|
8780
|
+
return null;
|
|
8781
|
+
}
|
|
8782
|
+
const replacement = withLeafMarker(emitFusedSource(grammarCoverage ? recognitionPieces : [...recognitionPieces, plainLocalPiece]));
|
|
8783
|
+
return { replacement: withCoverageDefinitions(replacement, emittedCoverageDefinitions(replacement)) };
|
|
8784
|
+
} catch (e) {
|
|
8785
|
+
warn(init.start, `composeLeaf(): ${e.message}`);
|
|
8786
|
+
return null;
|
|
8787
|
+
}
|
|
8788
|
+
};
|
|
7864
8789
|
const unwrapVd = (stmt) => stmt.type === "VariableDeclaration" ? stmt : stmt.type === "ExportNamedDeclaration" && stmt.declaration?.type === "VariableDeclaration" ? stmt.declaration : null;
|
|
7865
8790
|
const refNames = /* @__PURE__ */ new Set();
|
|
7866
8791
|
for (const stmt of body) {
|
|
@@ -7927,7 +8852,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7927
8852
|
const refEntry = scope.get(varName);
|
|
7928
8853
|
const refCombi = refEntry?.combi ?? null;
|
|
7929
8854
|
if (refCombi) {
|
|
7930
|
-
const compiled2 = compile(refCombi, void 0, { recovery });
|
|
8855
|
+
const compiled2 = compile(refCombi, void 0, { recovery, coverage: grammarCoverage });
|
|
7931
8856
|
if (compiled2.inlineExpression === null) {
|
|
7932
8857
|
warn(init.start, `"${varName}" is a ref() that couldn't be inlined (was .define() called with a static combinator?)`);
|
|
7933
8858
|
continue;
|
|
@@ -7941,7 +8866,10 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7941
8866
|
if (!compiledRules) continue;
|
|
7942
8867
|
localRuleMaps.set(varName, compiledRules.ruleMap);
|
|
7943
8868
|
if (compiledRules.trivia) localGrammarTrivia.set(varName, compiledRules.trivia);
|
|
7944
|
-
let replacement =
|
|
8869
|
+
let replacement = withCoverageDefinitions(
|
|
8870
|
+
compiledRules.replacement,
|
|
8871
|
+
compiledRules.coverageDefinitions?.length ? compiledRules.coverageDefinitions : emittedCoverageDefinitions(compiledRules.replacement)
|
|
8872
|
+
);
|
|
7945
8873
|
if (exportPrefix) {
|
|
7946
8874
|
const ns = nsFor(varName);
|
|
7947
8875
|
const pieces = compileLinkable([...compiledRules.ruleMap], ns, { recovery });
|
|
@@ -7955,11 +8883,22 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7955
8883
|
}
|
|
7956
8884
|
if (isComposeCall(init)) {
|
|
7957
8885
|
const fused = compileComposeCall(init);
|
|
7958
|
-
if (!fused)
|
|
8886
|
+
if (!fused) {
|
|
8887
|
+
runtimeComposeFallback = true;
|
|
8888
|
+
continue;
|
|
8889
|
+
}
|
|
7959
8890
|
localComposedCarried.set(varName, fused.carried);
|
|
7960
8891
|
if (fused.trivia) localComposedTrivia.set(varName, fused.trivia);
|
|
7961
8892
|
const replacement = exportPrefix ? withCarriedPieces(fused.replacement, fused.carried) : fused.replacement;
|
|
7962
|
-
replacements.push({ start: init.start, end: init.end, replacement });
|
|
8893
|
+
replacements.push({ start: init.start, end: init.end, replacement: withCoverageDefinitions(replacement, emittedCoverageDefinitions(replacement)) });
|
|
8894
|
+
continue;
|
|
8895
|
+
}
|
|
8896
|
+
if (isComposeLeafCall(init)) {
|
|
8897
|
+
const fused = compileComposeLeafCall(init);
|
|
8898
|
+
if (!fused) {
|
|
8899
|
+
throw new Error(`${id}:${lineOf(init.start)} \u2014 composeLeaf() must macro-fuse; runtime composition is forbidden`);
|
|
8900
|
+
}
|
|
8901
|
+
replacements.push({ start: init.start, end: init.end, replacement: fused.replacement });
|
|
7963
8902
|
continue;
|
|
7964
8903
|
}
|
|
7965
8904
|
const mapFnSources = [];
|
|
@@ -7980,7 +8919,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7980
8919
|
warn(init.start, `"${varName}" references a parseman macro import but isn't a statically-evaluable combinator`);
|
|
7981
8920
|
continue;
|
|
7982
8921
|
}
|
|
7983
|
-
const compiled = compile(parser2, void 0, { recovery });
|
|
8922
|
+
const compiled = compile(parser2, void 0, { recovery, coverage: grammarCoverage });
|
|
7984
8923
|
if (compiled.inlineExpression === null) {
|
|
7985
8924
|
warn(init.start, `"${varName}" couldn't be inlined (likely closes over a runtime value)`);
|
|
7986
8925
|
continue;
|
|
@@ -8055,7 +8994,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
8055
8994
|
ms.overwrite(imp.start, imp.end, stripped);
|
|
8056
8995
|
}
|
|
8057
8996
|
}
|
|
8058
|
-
for (const { start, end, replacement } of [
|
|
8997
|
+
for (const { start, end, replacement } of (runtimeComposeFallback ? [] : replacements).sort((a, b) => b.start - a.start)) {
|
|
8059
8998
|
ms.overwrite(start, end, replacement);
|
|
8060
8999
|
}
|
|
8061
9000
|
const unlowered = endLoweringCapture();
|