parseman 0.7.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/combinators/expect.d.ts +36 -0
- package/dist/combinators/expect.d.ts.map +1 -0
- package/dist/combinators/grammar.d.ts.map +1 -1
- package/dist/combinators/scanTo.d.ts.map +1 -1
- package/dist/compiler/codegen.d.ts +33 -0
- package/dist/compiler/codegen.d.ts.map +1 -1
- package/dist/compiler/scannable-run.d.ts +46 -0
- package/dist/compiler/scannable-run.d.ts.map +1 -0
- package/dist/compiler/trivia-fast-path.d.ts +27 -14
- package/dist/compiler/trivia-fast-path.d.ts.map +1 -1
- package/dist/index.cjs +534 -144
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +534 -144
- package/dist/index.js.map +4 -4
- package/dist/plugin/evaluator.d.ts +18 -0
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.cjs +701 -162
- package/dist/plugin/index.cjs.map +4 -4
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +701 -162
- package/dist/plugin/index.js.map +4 -4
- package/dist/types.d.ts +12 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -2
package/dist/plugin/index.cjs
CHANGED
|
@@ -1269,14 +1269,140 @@ function noTrivia(root) {
|
|
|
1269
1269
|
return parser({ trivia: null }, root);
|
|
1270
1270
|
}
|
|
1271
1271
|
|
|
1272
|
+
// src/compiler/scannable-run.ts
|
|
1273
|
+
var CLASS_ESCAPES = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
1274
|
+
var META = new Set("()[]{}*+?|^$.".split(""));
|
|
1275
|
+
function parseClassRanges(body) {
|
|
1276
|
+
const ranges = [];
|
|
1277
|
+
let i = 0;
|
|
1278
|
+
const readCp = () => {
|
|
1279
|
+
const ch = body[i];
|
|
1280
|
+
if (ch === void 0) return null;
|
|
1281
|
+
if (ch === "\\") {
|
|
1282
|
+
const e = body[i + 1];
|
|
1283
|
+
if (e === void 0) return null;
|
|
1284
|
+
i += 2;
|
|
1285
|
+
return e in CLASS_ESCAPES ? CLASS_ESCAPES[e] : e.codePointAt(0);
|
|
1286
|
+
}
|
|
1287
|
+
i += ch.length;
|
|
1288
|
+
return ch.codePointAt(0);
|
|
1289
|
+
};
|
|
1290
|
+
while (i < body.length) {
|
|
1291
|
+
const lo = readCp();
|
|
1292
|
+
if (lo === null) return null;
|
|
1293
|
+
if (body[i] === "-" && body[i + 1] !== void 0 && body[i + 1] !== "]") {
|
|
1294
|
+
i += 1;
|
|
1295
|
+
const hi = readCp();
|
|
1296
|
+
if (hi === null) return null;
|
|
1297
|
+
ranges.push([lo, hi]);
|
|
1298
|
+
} else {
|
|
1299
|
+
ranges.push([lo, lo]);
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
return ranges.length ? ranges : null;
|
|
1303
|
+
}
|
|
1304
|
+
function literalCodePoints(frag) {
|
|
1305
|
+
const out = [];
|
|
1306
|
+
let i = 0;
|
|
1307
|
+
while (i < frag.length) {
|
|
1308
|
+
const ch = frag[i];
|
|
1309
|
+
if (ch === "\\") {
|
|
1310
|
+
const e = frag[i + 1];
|
|
1311
|
+
if (e === void 0) return null;
|
|
1312
|
+
out.push(e in CLASS_ESCAPES ? CLASS_ESCAPES[e] : e.codePointAt(0));
|
|
1313
|
+
i += 2;
|
|
1314
|
+
continue;
|
|
1315
|
+
}
|
|
1316
|
+
if (META.has(ch)) return null;
|
|
1317
|
+
out.push(ch.codePointAt(0));
|
|
1318
|
+
i += 1;
|
|
1319
|
+
}
|
|
1320
|
+
return out.length ? out : null;
|
|
1321
|
+
}
|
|
1322
|
+
function parseScanShape(source) {
|
|
1323
|
+
let m = /^\[((?:\\.|[^\]])+)\]([+*])$/.exec(source);
|
|
1324
|
+
if (m) {
|
|
1325
|
+
if (m[1].startsWith("^")) return null;
|
|
1326
|
+
const ranges = parseClassRanges(m[1]);
|
|
1327
|
+
return ranges ? { kind: "chars", ranges } : null;
|
|
1328
|
+
}
|
|
1329
|
+
m = /^(.*?)\[\^((?:\\.|[^\]])+)\]\*$/.exec(source);
|
|
1330
|
+
if (m) {
|
|
1331
|
+
const open = literalCodePoints(m[1]);
|
|
1332
|
+
const stop = parseClassRanges(m[2]);
|
|
1333
|
+
if (open && stop) return { kind: "until", open, stop };
|
|
1334
|
+
return null;
|
|
1335
|
+
}
|
|
1336
|
+
if (!source.includes("\\\\")) {
|
|
1337
|
+
m = /^(.*?)\((?:\?:)?[\s\S]*\)\*(.*?)$/.exec(source);
|
|
1338
|
+
if (m && m[1] && m[2]) {
|
|
1339
|
+
const open = literalCodePoints(m[1]);
|
|
1340
|
+
const close = literalCodePoints(m[2]);
|
|
1341
|
+
if (open && close) return { kind: "delimited", open, close };
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
return null;
|
|
1345
|
+
}
|
|
1346
|
+
var classCond = (cVar, ranges) => ranges.map(([lo, hi]) => lo === hi ? `${cVar} === ${lo}` : `(${cVar} >= ${lo} && ${cVar} <= ${hi})`).join(" || ");
|
|
1347
|
+
var litCond = (base, cps, firstVar) => cps.map(
|
|
1348
|
+
(cp, k) => k === 0 && firstVar ? `${firstVar} === ${cp}` : `input.charCodeAt(${base}${k ? ` + ${k}` : ""}) === ${cp}`
|
|
1349
|
+
).join(" && ");
|
|
1350
|
+
function advanceExpr(shape) {
|
|
1351
|
+
if (shape.kind === "chars") {
|
|
1352
|
+
return {
|
|
1353
|
+
setup: [
|
|
1354
|
+
` _e++`,
|
|
1355
|
+
` while (_e < input.length) { const c2 = input.charCodeAt(_e); if (${classCond("c2", shape.ranges)}) _e++; else break }`
|
|
1356
|
+
],
|
|
1357
|
+
endVar: "_e"
|
|
1358
|
+
};
|
|
1359
|
+
}
|
|
1360
|
+
if (shape.kind === "until") {
|
|
1361
|
+
return {
|
|
1362
|
+
setup: [
|
|
1363
|
+
` let j = _e + ${shape.open.length}`,
|
|
1364
|
+
` while (j < input.length && !(${classCond("input.charCodeAt(j)", shape.stop)})) j++`
|
|
1365
|
+
],
|
|
1366
|
+
endVar: "j"
|
|
1367
|
+
};
|
|
1368
|
+
}
|
|
1369
|
+
const n = shape.close.length;
|
|
1370
|
+
return {
|
|
1371
|
+
setup: [
|
|
1372
|
+
` let j = _e + ${shape.open.length}`,
|
|
1373
|
+
` while (j + ${n - 1} < input.length && !(${litCond("j", shape.close)})) j++`
|
|
1374
|
+
],
|
|
1375
|
+
endVar: n === 1 ? "(j + 1 <= input.length ? j + 1 : input.length)" : `(j + ${n} <= input.length ? j + ${n} : input.length)`
|
|
1376
|
+
};
|
|
1377
|
+
}
|
|
1378
|
+
function guardLine(shape) {
|
|
1379
|
+
const cond = shape.kind === "chars" ? classCond("c", shape.ranges) : litCond("_e", shape.open, "c");
|
|
1380
|
+
return ` if (${cond}) {`;
|
|
1381
|
+
}
|
|
1382
|
+
function scanBranch(shape) {
|
|
1383
|
+
if (shape.kind === "chars") {
|
|
1384
|
+
return ` if (${classCond("c", shape.ranges)}) { _e++; continue }`;
|
|
1385
|
+
}
|
|
1386
|
+
const { setup, endVar } = advanceExpr(shape);
|
|
1387
|
+
return [guardLine(shape), ...setup, ` _e = ${endVar}`, ` continue`, ` }`].join("\n");
|
|
1388
|
+
}
|
|
1389
|
+
function captureChunk(startVar, kindIndex) {
|
|
1390
|
+
return [
|
|
1391
|
+
` if (_cap) {`,
|
|
1392
|
+
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(${startVar}, _e, ${kindIndex})`,
|
|
1393
|
+
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(${startVar}, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${kindIndex})`,
|
|
1394
|
+
` }`
|
|
1395
|
+
];
|
|
1396
|
+
}
|
|
1397
|
+
function scanBranchLabeled(shape, kindIndex) {
|
|
1398
|
+
const { setup, endVar } = advanceExpr(shape);
|
|
1399
|
+
const lines = [guardLine(shape), ` const _cs = _e`, ...setup];
|
|
1400
|
+
if (endVar !== "_e") lines.push(` _e = ${endVar}`);
|
|
1401
|
+
lines.push(...captureChunk("_cs", kindIndex), ` continue`, ` }`);
|
|
1402
|
+
return lines.join("\n");
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1272
1405
|
// src/compiler/trivia-fast-path.ts
|
|
1273
|
-
var BLOCK_COMMENT = String.raw`\/\*(?:[^*]|\*(?!\/))*\*\/`;
|
|
1274
|
-
var WS_CLASS_SOURCES = /* @__PURE__ */ new Set([
|
|
1275
|
-
String.raw`[ \t\n\r\f]+`,
|
|
1276
|
-
String.raw`[ \t\n]+`,
|
|
1277
|
-
String.raw`[ \t]+`,
|
|
1278
|
-
String.raw`[\t\n\f\r ]+`
|
|
1279
|
-
]);
|
|
1280
1406
|
function unwrapTrivia2(p) {
|
|
1281
1407
|
let cur = p;
|
|
1282
1408
|
while (cur._def.tag === "trivia") cur = cur._def.parser;
|
|
@@ -1292,36 +1418,30 @@ function choiceArms(p) {
|
|
|
1292
1418
|
if (p._def.tag === "choice") return p._def.parsers;
|
|
1293
1419
|
return null;
|
|
1294
1420
|
}
|
|
1295
|
-
function
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
function isBlockCommentSource(source) {
|
|
1299
|
-
return source === BLOCK_COMMENT;
|
|
1421
|
+
function armShape(arm) {
|
|
1422
|
+
const src = getCoreRegexDef(arm)?.source;
|
|
1423
|
+
return src ? parseScanShape(src) : null;
|
|
1300
1424
|
}
|
|
1301
1425
|
function analyzeTriviaFastPath(trivia2) {
|
|
1302
1426
|
const core = unwrapTrivia2(trivia2);
|
|
1303
|
-
const
|
|
1304
|
-
if (
|
|
1305
|
-
|
|
1306
|
-
return null;
|
|
1427
|
+
const directSrc = getCoreRegexDef(core)?.source;
|
|
1428
|
+
if (directSrc) {
|
|
1429
|
+
const shape = parseScanShape(directSrc);
|
|
1430
|
+
return shape && shape.kind === "chars" ? [shape] : null;
|
|
1307
1431
|
}
|
|
1308
1432
|
const inner = oneOrMoreInner(core);
|
|
1309
1433
|
if (!inner) return null;
|
|
1310
|
-
const
|
|
1311
|
-
if (
|
|
1434
|
+
const innerShape = armShape(inner);
|
|
1435
|
+
if (innerShape) return innerShape.kind === "chars" ? [innerShape] : null;
|
|
1312
1436
|
const arms = choiceArms(inner);
|
|
1313
|
-
if (!arms || arms.length
|
|
1314
|
-
|
|
1315
|
-
let hasComment = false;
|
|
1437
|
+
if (!arms || arms.length < 2) return null;
|
|
1438
|
+
const shapes = [];
|
|
1316
1439
|
for (const arm of arms) {
|
|
1317
|
-
const
|
|
1318
|
-
if (!
|
|
1319
|
-
|
|
1320
|
-
else if (isBlockCommentSource(src)) hasComment = true;
|
|
1321
|
-
else return null;
|
|
1440
|
+
const shape = armShape(arm);
|
|
1441
|
+
if (!shape) return null;
|
|
1442
|
+
shapes.push(shape);
|
|
1322
1443
|
}
|
|
1323
|
-
|
|
1324
|
-
return null;
|
|
1444
|
+
return shapes;
|
|
1325
1445
|
}
|
|
1326
1446
|
var CAP_RECORD = [
|
|
1327
1447
|
` if (_cap && _e > _pos) {`,
|
|
@@ -1329,80 +1449,49 @@ var CAP_RECORD = [
|
|
|
1329
1449
|
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
|
|
1330
1450
|
` }`
|
|
1331
1451
|
].join("\n");
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
` if (c === 47 && input.charCodeAt(_e + 1) === 42) {`,
|
|
1344
|
-
` let j = _e + 2`,
|
|
1345
|
-
` while (j + 1 < input.length && !(input.charCodeAt(j) === 42 && input.charCodeAt(j + 1) === 47)) j++`,
|
|
1346
|
-
` _e = j + 2 <= input.length ? j + 2 : input.length`,
|
|
1347
|
-
` continue`,
|
|
1348
|
-
` }`,
|
|
1349
|
-
` break`,
|
|
1350
|
-
` }`
|
|
1351
|
-
].join("\n");
|
|
1352
|
-
var CAP_CHUNK = (wsKind, commentKind) => [
|
|
1353
|
-
` if (c === 32 || c === 9 || c === 10 || c === 13 || c === 12) {`,
|
|
1354
|
-
` const _cs = _e`,
|
|
1355
|
-
` _e++`,
|
|
1356
|
-
` while (_e < input.length) {`,
|
|
1357
|
-
` const c2 = input.charCodeAt(_e)`,
|
|
1358
|
-
` if (c2 === 32 || c2 === 9 || c2 === 10 || c2 === 13 || c2 === 12) _e++`,
|
|
1359
|
-
` else break`,
|
|
1360
|
-
` }`,
|
|
1361
|
-
` if (_cap) {`,
|
|
1362
|
-
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_cs, _e, ${wsKind})`,
|
|
1363
|
-
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_cs, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${wsKind})`,
|
|
1364
|
-
` }`,
|
|
1365
|
-
` continue`,
|
|
1366
|
-
` }`,
|
|
1367
|
-
` if (c === 47 && input.charCodeAt(_e + 1) === 42) {`,
|
|
1368
|
-
` const _cs = _e`,
|
|
1369
|
-
` let j = _e + 2`,
|
|
1370
|
-
` while (j + 1 < input.length && !(input.charCodeAt(j) === 42 && input.charCodeAt(j + 1) === 47)) j++`,
|
|
1371
|
-
` _e = j + 2 <= input.length ? j + 2 : input.length`,
|
|
1372
|
-
` if (_cap) {`,
|
|
1373
|
-
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_cs, _e, ${commentKind})`,
|
|
1374
|
-
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_cs, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${commentKind})`,
|
|
1375
|
-
` }`,
|
|
1376
|
-
` continue`,
|
|
1377
|
-
` }`
|
|
1378
|
-
].join("\n");
|
|
1379
|
-
var WS_COMMENTS_LOOP_LABELED = (wsKind, commentKind) => [
|
|
1380
|
-
` while (_e < input.length) {`,
|
|
1381
|
-
` const c = input.charCodeAt(_e)`,
|
|
1382
|
-
CAP_CHUNK(wsKind, commentKind),
|
|
1383
|
-
` break`,
|
|
1384
|
-
` }`
|
|
1385
|
-
].join("\n");
|
|
1386
|
-
function buildFastTriviaFnDecl(fnName, kind, kindIndices) {
|
|
1387
|
-
const loop = kind === "wsComments" && kindIndices ? WS_COMMENTS_LOOP_LABELED(kindIndices.ws, kindIndices.comment) : kind === "wsComments" ? WS_COMMENTS_LOOP : WS_ONLY_LOOP;
|
|
1388
|
-
const cap = kindIndices ? "" : CAP_RECORD;
|
|
1389
|
-
const lines = [
|
|
1452
|
+
function composeFastLoop(shapes) {
|
|
1453
|
+
return [
|
|
1454
|
+
` while (_e < input.length) {`,
|
|
1455
|
+
` const c = input.charCodeAt(_e)`,
|
|
1456
|
+
...shapes.map(scanBranch),
|
|
1457
|
+
` break`,
|
|
1458
|
+
` }`
|
|
1459
|
+
].join("\n");
|
|
1460
|
+
}
|
|
1461
|
+
function buildFastTriviaFnDecl(fnName, shapes) {
|
|
1462
|
+
return [
|
|
1390
1463
|
`function ${fnName}(input, _pos, _ctx, _cap) {`,
|
|
1391
1464
|
` let _e = _pos`,
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1465
|
+
composeFastLoop(shapes),
|
|
1466
|
+
CAP_RECORD,
|
|
1467
|
+
` return _e`,
|
|
1468
|
+
`}`
|
|
1469
|
+
].join("\n");
|
|
1397
1470
|
}
|
|
1398
|
-
function
|
|
1471
|
+
function analyzeLabeledScannableRun(trivia2) {
|
|
1472
|
+
const spec = analyzeLabeledTrivia(trivia2);
|
|
1473
|
+
if (!spec) return null;
|
|
1474
|
+
const out = [];
|
|
1399
1475
|
for (const arm of spec.arms) {
|
|
1400
1476
|
const src = getCoreRegexDef(arm.parser)?.source;
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1477
|
+
const shape = src ? parseScanShape(src) : null;
|
|
1478
|
+
if (!shape) return null;
|
|
1479
|
+
out.push({ shape, kindIndex: arm.kindIndex });
|
|
1404
1480
|
}
|
|
1405
|
-
return
|
|
1481
|
+
return out;
|
|
1482
|
+
}
|
|
1483
|
+
function buildLabeledScannableTriviaFnDecl(fnName, arms) {
|
|
1484
|
+
return [
|
|
1485
|
+
`function ${fnName}(input, _pos, _ctx, _cap) {`,
|
|
1486
|
+
` let _e = _pos`,
|
|
1487
|
+
` while (_e < input.length) {`,
|
|
1488
|
+
` const c = input.charCodeAt(_e)`,
|
|
1489
|
+
...arms.map((a) => scanBranchLabeled(a.shape, a.kindIndex)),
|
|
1490
|
+
` break`,
|
|
1491
|
+
` }`,
|
|
1492
|
+
` return _e`,
|
|
1493
|
+
`}`
|
|
1494
|
+
].join("\n");
|
|
1406
1495
|
}
|
|
1407
1496
|
function buildLabeledRegexTriviaFnDecl(fnName, spec, reNames) {
|
|
1408
1497
|
const tryArms = spec.arms.map((arm, i) => {
|
|
@@ -1435,14 +1524,6 @@ function buildLabeledRegexTriviaFnDecl(fnName, spec, reNames) {
|
|
|
1435
1524
|
`}`
|
|
1436
1525
|
].join("\n");
|
|
1437
1526
|
}
|
|
1438
|
-
function labeledTriviaKindIndices(trivia2) {
|
|
1439
|
-
const spec = analyzeLabeledTrivia(trivia2);
|
|
1440
|
-
if (!spec || spec.arms.length !== 2) return null;
|
|
1441
|
-
const ws = regexArmIndex(spec, false);
|
|
1442
|
-
const comment = regexArmIndex(spec, true);
|
|
1443
|
-
if (ws === null || comment === null) return null;
|
|
1444
|
-
return { ws, comment };
|
|
1445
|
-
}
|
|
1446
1527
|
function labeledTriviaRegexArms(trivia2) {
|
|
1447
1528
|
const spec = analyzeLabeledTrivia(trivia2);
|
|
1448
1529
|
if (!spec) return null;
|
|
@@ -1690,14 +1771,19 @@ function ensureTriviaFn(ctx) {
|
|
|
1690
1771
|
const fnName = `_tf${ctx.triviaFnNames.size}`;
|
|
1691
1772
|
ctx.triviaFnNames.set(trivia2, fnName);
|
|
1692
1773
|
ctx.triviaCaptureNames.set(trivia2, fnName);
|
|
1693
|
-
const fastKind = analyzeTriviaFastPath(trivia2);
|
|
1694
|
-
const kindIndices = labeledTriviaKindIndices(trivia2);
|
|
1695
|
-
if (fastKind) {
|
|
1696
|
-
ctx.namedFnDecls.push(buildFastTriviaFnDecl(fnName, fastKind, kindIndices ?? void 0));
|
|
1697
|
-
return fnName;
|
|
1698
|
-
}
|
|
1699
1774
|
const labeledSpec = analyzeLabeledTrivia(trivia2);
|
|
1700
|
-
if (labeledSpec) {
|
|
1775
|
+
if (!labeledSpec) {
|
|
1776
|
+
const fastShapes = analyzeTriviaFastPath(trivia2);
|
|
1777
|
+
if (fastShapes) {
|
|
1778
|
+
ctx.namedFnDecls.push(buildFastTriviaFnDecl(fnName, fastShapes));
|
|
1779
|
+
return fnName;
|
|
1780
|
+
}
|
|
1781
|
+
} else {
|
|
1782
|
+
const labeledShapes = analyzeLabeledScannableRun(trivia2);
|
|
1783
|
+
if (labeledShapes) {
|
|
1784
|
+
ctx.namedFnDecls.push(buildLabeledScannableTriviaFnDecl(fnName, labeledShapes));
|
|
1785
|
+
return fnName;
|
|
1786
|
+
}
|
|
1701
1787
|
const regexSpec = labeledTriviaRegexArms(trivia2);
|
|
1702
1788
|
if (regexSpec) {
|
|
1703
1789
|
const reNames = [];
|
|
@@ -1757,6 +1843,119 @@ function firstSetCond(codeVar, fs) {
|
|
|
1757
1843
|
(r) => r.lo === r.hi ? `${codeVar} === ${r.lo}` : `(${codeVar} >= ${r.lo} && ${codeVar} <= ${r.hi})`
|
|
1758
1844
|
).join(" || ");
|
|
1759
1845
|
}
|
|
1846
|
+
function captureRestoreBody(mL, mR, mTl, mLg) {
|
|
1847
|
+
const base = `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${mL}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${mR}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${mTl}`;
|
|
1848
|
+
return mLg ? `${base}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${mLg}` : base;
|
|
1849
|
+
}
|
|
1850
|
+
function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
|
|
1851
|
+
if (seen.has(p)) return false;
|
|
1852
|
+
seen.add(p);
|
|
1853
|
+
const d = p._def;
|
|
1854
|
+
switch (d.tag) {
|
|
1855
|
+
// Atomic / non-capturing-then-failing: a failure happens before any push.
|
|
1856
|
+
case "literal":
|
|
1857
|
+
case "regex":
|
|
1858
|
+
case "keywords":
|
|
1859
|
+
case "guard":
|
|
1860
|
+
case "not":
|
|
1861
|
+
case "trivia":
|
|
1862
|
+
case "scanTo":
|
|
1863
|
+
case "unknown":
|
|
1864
|
+
return false;
|
|
1865
|
+
// node() captures into its own private buffers and rolls them back on
|
|
1866
|
+
// failure (emitNode restores _ctx.* and never pushes on the !ok path).
|
|
1867
|
+
case "node":
|
|
1868
|
+
return false;
|
|
1869
|
+
// choice/firstMatch already roll back each failed arm; on overall failure
|
|
1870
|
+
// nothing committed remains.
|
|
1871
|
+
case "choice":
|
|
1872
|
+
return false;
|
|
1873
|
+
// optional never fails; many/oneOrMore only "fail" with zero captured items.
|
|
1874
|
+
case "optional":
|
|
1875
|
+
case "many":
|
|
1876
|
+
case "oneOrMore":
|
|
1877
|
+
return false;
|
|
1878
|
+
// sepBy emits its own per-iteration rollback in emitSepBy.
|
|
1879
|
+
case "sepBy":
|
|
1880
|
+
return false;
|
|
1881
|
+
// A sequence is the real case: an earlier capturing term followed by a term
|
|
1882
|
+
// that can fail leaves the earlier captures buffered.
|
|
1883
|
+
case "sequence": {
|
|
1884
|
+
const parts = d.parsers;
|
|
1885
|
+
if (parts.length < 2) return parts.some((x) => mayLeavePartialCapture(x, seen));
|
|
1886
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
1887
|
+
if (hasNodeDef(parts[i]) || capturesLeaf(parts[i])) return true;
|
|
1888
|
+
}
|
|
1889
|
+
return false;
|
|
1890
|
+
}
|
|
1891
|
+
// Delegating wrappers: defer to the wrapped parser.
|
|
1892
|
+
case "transform":
|
|
1893
|
+
case "label":
|
|
1894
|
+
case "expect":
|
|
1895
|
+
case "withCtx":
|
|
1896
|
+
case "grammar":
|
|
1897
|
+
return mayLeavePartialCapture(d.parser, seen);
|
|
1898
|
+
case "skip":
|
|
1899
|
+
return mayLeavePartialCapture(d.main, seen);
|
|
1900
|
+
case "recover":
|
|
1901
|
+
return mayLeavePartialCapture(d.parser, seen);
|
|
1902
|
+
case "lazy": {
|
|
1903
|
+
try {
|
|
1904
|
+
return mayLeavePartialCapture(d.thunk(), seen);
|
|
1905
|
+
} catch {
|
|
1906
|
+
return true;
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
// Unknown shapes: be safe and keep the rollback.
|
|
1910
|
+
default:
|
|
1911
|
+
return true;
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
|
|
1915
|
+
if (seen.has(p)) return false;
|
|
1916
|
+
seen.add(p);
|
|
1917
|
+
const d = p._def;
|
|
1918
|
+
switch (d.tag) {
|
|
1919
|
+
case "literal":
|
|
1920
|
+
case "regex":
|
|
1921
|
+
case "keywords":
|
|
1922
|
+
case "node":
|
|
1923
|
+
return true;
|
|
1924
|
+
case "not":
|
|
1925
|
+
case "guard":
|
|
1926
|
+
case "trivia":
|
|
1927
|
+
case "unknown":
|
|
1928
|
+
return false;
|
|
1929
|
+
case "sequence":
|
|
1930
|
+
case "choice":
|
|
1931
|
+
return d.parsers.some((x) => capturesLeaf(x, seen));
|
|
1932
|
+
case "sepBy":
|
|
1933
|
+
return capturesLeaf(d.parser, seen) || capturesLeaf(d.separator, seen);
|
|
1934
|
+
case "many":
|
|
1935
|
+
case "oneOrMore":
|
|
1936
|
+
case "optional":
|
|
1937
|
+
case "transform":
|
|
1938
|
+
case "label":
|
|
1939
|
+
case "expect":
|
|
1940
|
+
case "withCtx":
|
|
1941
|
+
case "grammar":
|
|
1942
|
+
case "recover":
|
|
1943
|
+
return capturesLeaf(d.parser, seen);
|
|
1944
|
+
case "skip":
|
|
1945
|
+
return capturesLeaf(d.main, seen);
|
|
1946
|
+
case "scanTo":
|
|
1947
|
+
return true;
|
|
1948
|
+
case "lazy": {
|
|
1949
|
+
try {
|
|
1950
|
+
return capturesLeaf(d.thunk(), seen);
|
|
1951
|
+
} catch {
|
|
1952
|
+
return true;
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
default:
|
|
1956
|
+
return true;
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1760
1959
|
function emitFallible(inner, ctx, pos) {
|
|
1761
1960
|
const lbl = v(ctx, "_lbl");
|
|
1762
1961
|
const okV = `${lbl}ok`;
|
|
@@ -1770,26 +1969,23 @@ function emitFallible(inner, ctx, pos) {
|
|
|
1770
1969
|
ctx.failLabel = savedLabel;
|
|
1771
1970
|
ctx.indent = savedIndent;
|
|
1772
1971
|
const ind0 = ind(ctx);
|
|
1773
|
-
const
|
|
1774
|
-
const
|
|
1775
|
-
const
|
|
1776
|
-
const
|
|
1972
|
+
const needsRollback = ctx.capturing && mayLeavePartialCapture(inner);
|
|
1973
|
+
const mL = needsRollback ? v(ctx, "_fcl") : null;
|
|
1974
|
+
const mR = needsRollback ? v(ctx, "_fcr") : null;
|
|
1975
|
+
const mTl = needsRollback ? v(ctx, "_fctl") : null;
|
|
1777
1976
|
const stmts = [
|
|
1778
1977
|
`${ind0}let ${okV} = false, ${valV}, ${endV} = ${pos}`,
|
|
1779
1978
|
...mL ? [
|
|
1780
1979
|
`${ind0}const ${mL} = _ctx._cstLeaves?.length ?? 0`,
|
|
1781
1980
|
`${ind0}const ${mR} = _ctx._cstRawChildren?.length ?? 0`,
|
|
1782
|
-
`${ind0}const ${mTl} = _ctx._cstTriviaLog?.length ?? 0
|
|
1783
|
-
`${ind0}const ${mLg} = _ctx._triviaLog?.length ?? 0`
|
|
1981
|
+
`${ind0}const ${mTl} = _ctx._cstTriviaLog?.length ?? 0`
|
|
1784
1982
|
] : [],
|
|
1785
1983
|
`${ind0}${lbl}: {`,
|
|
1786
1984
|
...r.stmts,
|
|
1787
|
-
`${ind0} ${valV} = ${r.valueVar}`,
|
|
1788
|
-
`${ind0} ${endV} = ${r.endVar}`,
|
|
1789
|
-
`${ind0} ${okV} = true`,
|
|
1985
|
+
`${ind0} ${valV} = ${r.valueVar}; ${endV} = ${r.endVar}; ${okV} = true`,
|
|
1790
1986
|
`${ind0}}`,
|
|
1791
1987
|
...mL ? [
|
|
1792
|
-
`${ind0}if (!${okV}) {
|
|
1988
|
+
`${ind0}if (!${okV}) { ${captureRestoreBody(mL, mR, mTl, null)} }`
|
|
1793
1989
|
] : []
|
|
1794
1990
|
];
|
|
1795
1991
|
return { stmts, okVar: okV, valVar: valV, endVar: endV };
|
|
@@ -2025,11 +2221,11 @@ function emitLiteralsLongestFirst(def, sortedIndices, allExpected, ctx, pos) {
|
|
|
2025
2221
|
const p = def.parsers[idx];
|
|
2026
2222
|
const litVal = getCoreLiteralValue(p);
|
|
2027
2223
|
const litLen = litVal.length;
|
|
2028
|
-
const
|
|
2224
|
+
const litCond2 = emitLiteralCondition(litVal, pos);
|
|
2029
2225
|
const kw = first ? "if" : "else if";
|
|
2030
2226
|
first = false;
|
|
2031
2227
|
const litEnd = `${pos} + ${litLen}`;
|
|
2032
|
-
stmts.push(`${ind(ctx)}${kw} (${
|
|
2228
|
+
stmts.push(`${ind(ctx)}${kw} (${litCond2}) {`);
|
|
2033
2229
|
ctx.indent++;
|
|
2034
2230
|
const tR = emitTransformChain(p, JSON.stringify(litVal), litEnd, pos, ctx);
|
|
2035
2231
|
stmts.push(
|
|
@@ -2063,11 +2259,13 @@ function emitFirstMatch(def, allExpected, ctx, pos) {
|
|
|
2063
2259
|
gateCond = `_mf[${gateIdx}](_ctx.state)`;
|
|
2064
2260
|
}
|
|
2065
2261
|
const skipCond = gateCond ? `!${resOkV} && ${gateCond}` : `!${resOkV}`;
|
|
2066
|
-
const
|
|
2067
|
-
const
|
|
2068
|
-
const
|
|
2069
|
-
const
|
|
2070
|
-
const
|
|
2262
|
+
const armHasAutoNot = !!(autoNot && autoNot.length > 0);
|
|
2263
|
+
const armNeedsRollback = ctx.capturing && (mayLeavePartialCapture(p) || armHasAutoNot && capturesLeaf(p));
|
|
2264
|
+
const markLeaves = armNeedsRollback ? v(ctx, "_cml") : null;
|
|
2265
|
+
const markRaw = armNeedsRollback ? v(ctx, "_cmr") : null;
|
|
2266
|
+
const markTl = armNeedsRollback ? v(ctx, "_cmtl") : null;
|
|
2267
|
+
const markLog = armNeedsRollback ? v(ctx, "_cmlg") : null;
|
|
2268
|
+
const rollback = markLeaves ? captureRestoreBody(markLeaves, markRaw, markTl, markLog) : "";
|
|
2071
2269
|
stmts.push(`${ind0}if (${skipCond}) {`);
|
|
2072
2270
|
ctx.indent++;
|
|
2073
2271
|
const ind1 = ind(ctx);
|
|
@@ -2097,11 +2295,7 @@ function emitFirstMatch(def, allExpected, ctx, pos) {
|
|
|
2097
2295
|
stmts.push(`${ind0} }`);
|
|
2098
2296
|
if (rollback) stmts.push(`${ind0} if (!${resOkV}) { ${rollback} }`);
|
|
2099
2297
|
} else {
|
|
2100
|
-
stmts.push(`${ind0} if (${okVar}) {`);
|
|
2101
|
-
stmts.push(`${ind0} ${resValV} = ${valVar}`);
|
|
2102
|
-
stmts.push(`${ind0} ${resEndV} = ${endVar}`);
|
|
2103
|
-
stmts.push(`${ind0} ${resOkV} = true`);
|
|
2104
|
-
stmts.push(`${ind0} }`);
|
|
2298
|
+
stmts.push(`${ind0} if (${okVar}) { ${resValV} = ${valVar}; ${resEndV} = ${endVar}; ${resOkV} = true }`);
|
|
2105
2299
|
if (rollback) stmts.push(`${ind0} else { ${rollback} }`);
|
|
2106
2300
|
}
|
|
2107
2301
|
stmts.push(`${ind0}}`);
|
|
@@ -2399,6 +2593,16 @@ function emitRuntimeFallback(parser2, ctx, pos) {
|
|
|
2399
2593
|
return { stmts, valueVar: vv, endVar: ev };
|
|
2400
2594
|
}
|
|
2401
2595
|
function emitLazy(p, def, ctx, pos) {
|
|
2596
|
+
const usage = ctx.lazyUsage;
|
|
2597
|
+
if (usage && (usage.counts.get(p) ?? 0) <= 1 && !usage.recursive.has(p)) {
|
|
2598
|
+
let resolved;
|
|
2599
|
+
try {
|
|
2600
|
+
resolved = def.thunk();
|
|
2601
|
+
} catch {
|
|
2602
|
+
return emitRuntimeFallback(p, ctx, pos);
|
|
2603
|
+
}
|
|
2604
|
+
return emit(resolved, ctx, pos);
|
|
2605
|
+
}
|
|
2402
2606
|
if (!ctx.namedParsers.has(p)) {
|
|
2403
2607
|
const fnName2 = `_pf${ctx.namedParsers.size}`;
|
|
2404
2608
|
ctx.namedParsers.set(p, fnName2);
|
|
@@ -2446,6 +2650,22 @@ function emitRecover(def, ctx, pos) {
|
|
|
2446
2650
|
];
|
|
2447
2651
|
return { stmts, valueVar: valVar, endVar };
|
|
2448
2652
|
}
|
|
2653
|
+
function emitExpect(def, ctx, pos) {
|
|
2654
|
+
const { stmts: innerStmts, okVar, valVar, endVar } = emitFallible(def.parser, ctx, pos);
|
|
2655
|
+
const ind0 = ind(ctx);
|
|
2656
|
+
const errV = v(ctx, "_err");
|
|
2657
|
+
const stmts = [
|
|
2658
|
+
...innerStmts,
|
|
2659
|
+
`${ind0}if (!${okVar}) {`,
|
|
2660
|
+
`${ind0} const ${errV} = { _tag: 'parseError', span: { start: ${pos}, end: ${pos} }, expected: ${JSON.stringify(def.expected)} }`,
|
|
2661
|
+
`${ind0} if (_ctx._errors) _ctx._errors.push(${errV})`,
|
|
2662
|
+
`${ind0} ${valVar} = ${errV}`,
|
|
2663
|
+
`${ind0} ${endVar} = ${pos}`,
|
|
2664
|
+
`${ind0} ${okVar} = true`,
|
|
2665
|
+
`${ind0}}`
|
|
2666
|
+
];
|
|
2667
|
+
return { stmts, valueVar: valVar, endVar };
|
|
2668
|
+
}
|
|
2449
2669
|
function emit(p, ctx, pos) {
|
|
2450
2670
|
const def = p._def;
|
|
2451
2671
|
switch (def.tag) {
|
|
@@ -2554,6 +2774,8 @@ function emit(p, ctx, pos) {
|
|
|
2554
2774
|
return emitScanTo(def, ctx, pos);
|
|
2555
2775
|
case "recover":
|
|
2556
2776
|
return emitRecover(def, ctx, pos);
|
|
2777
|
+
case "expect":
|
|
2778
|
+
return emitExpect(def, ctx, pos);
|
|
2557
2779
|
case "guard": {
|
|
2558
2780
|
const fnIdx = ctx.mapFns.length;
|
|
2559
2781
|
ctx.mapFns.push(def.predicate);
|
|
@@ -2637,12 +2859,88 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
2637
2859
|
return hasNodeDef(d.sentinel, seen) || d.skip.some((x) => hasNodeDef(x, seen));
|
|
2638
2860
|
case "recover":
|
|
2639
2861
|
return hasNodeDef(d.parser, seen) || hasNodeDef(d.sentinel, seen);
|
|
2862
|
+
case "expect":
|
|
2863
|
+
return hasNodeDef(d.parser, seen);
|
|
2640
2864
|
case "withCtx":
|
|
2641
2865
|
return hasNodeDef(d.parser, seen);
|
|
2642
2866
|
default:
|
|
2643
2867
|
return false;
|
|
2644
2868
|
}
|
|
2645
2869
|
}
|
|
2870
|
+
function childrenOf(def) {
|
|
2871
|
+
switch (def.tag) {
|
|
2872
|
+
case "sequence":
|
|
2873
|
+
case "choice":
|
|
2874
|
+
return def.parsers;
|
|
2875
|
+
case "many":
|
|
2876
|
+
case "optional":
|
|
2877
|
+
case "transform":
|
|
2878
|
+
case "trivia":
|
|
2879
|
+
case "label":
|
|
2880
|
+
case "grammar":
|
|
2881
|
+
case "not":
|
|
2882
|
+
case "node":
|
|
2883
|
+
case "withCtx":
|
|
2884
|
+
case "expect":
|
|
2885
|
+
return [def.parser];
|
|
2886
|
+
// emitMany's oneOrMore branch and emitSepBy both codegen `def.parser` TWICE
|
|
2887
|
+
// (a mandatory first match, then again inside the repeat loop) — two real
|
|
2888
|
+
// emit() call sites, so the usage analysis must see two edges here or it
|
|
2889
|
+
// undercounts a single-use `parser` ref as inline-safe when it's actually
|
|
2890
|
+
// referenced from two positions within this one compiled function.
|
|
2891
|
+
case "oneOrMore":
|
|
2892
|
+
return [def.parser, def.parser];
|
|
2893
|
+
case "sepBy":
|
|
2894
|
+
return [def.parser, def.parser, def.separator];
|
|
2895
|
+
case "skip":
|
|
2896
|
+
return [def.main, def.skipped];
|
|
2897
|
+
case "recover":
|
|
2898
|
+
return [def.parser, def.sentinel];
|
|
2899
|
+
case "scanTo":
|
|
2900
|
+
return [def.sentinel, ...def.skip];
|
|
2901
|
+
case "lazy":
|
|
2902
|
+
case "literal":
|
|
2903
|
+
case "regex":
|
|
2904
|
+
case "keywords":
|
|
2905
|
+
case "guard":
|
|
2906
|
+
case "unknown":
|
|
2907
|
+
return [];
|
|
2908
|
+
}
|
|
2909
|
+
}
|
|
2910
|
+
function analyzeLazyUsage(root) {
|
|
2911
|
+
return analyzeLazyUsageMulti([root]);
|
|
2912
|
+
}
|
|
2913
|
+
function analyzeLazyUsageMulti(roots) {
|
|
2914
|
+
const counts = /* @__PURE__ */ new Map();
|
|
2915
|
+
const recursive = /* @__PURE__ */ new Set();
|
|
2916
|
+
const descended = /* @__PURE__ */ new Set();
|
|
2917
|
+
const active = /* @__PURE__ */ new Set();
|
|
2918
|
+
function walk(p) {
|
|
2919
|
+
const def = p._def;
|
|
2920
|
+
if (def.tag === "lazy") {
|
|
2921
|
+
counts.set(p, (counts.get(p) ?? 0) + 1);
|
|
2922
|
+
if (active.has(p)) {
|
|
2923
|
+
recursive.add(p);
|
|
2924
|
+
return;
|
|
2925
|
+
}
|
|
2926
|
+
if (descended.has(p)) return;
|
|
2927
|
+
descended.add(p);
|
|
2928
|
+
let resolved;
|
|
2929
|
+
try {
|
|
2930
|
+
resolved = def.thunk();
|
|
2931
|
+
} catch {
|
|
2932
|
+
return;
|
|
2933
|
+
}
|
|
2934
|
+
active.add(p);
|
|
2935
|
+
walk(resolved);
|
|
2936
|
+
active.delete(p);
|
|
2937
|
+
return;
|
|
2938
|
+
}
|
|
2939
|
+
for (const child of childrenOf(def)) walk(child);
|
|
2940
|
+
}
|
|
2941
|
+
for (const root of roots) walk(root);
|
|
2942
|
+
return { counts, recursive };
|
|
2943
|
+
}
|
|
2646
2944
|
function compile(combinator, mapFnSources) {
|
|
2647
2945
|
const ctx = {
|
|
2648
2946
|
vars: 0,
|
|
@@ -2659,7 +2957,8 @@ function compile(combinator, mapFnSources) {
|
|
|
2659
2957
|
triviaCaptureNames: /* @__PURE__ */ new Map(),
|
|
2660
2958
|
triviaFnNames: /* @__PURE__ */ new Map(),
|
|
2661
2959
|
namedFnDecls: [],
|
|
2662
|
-
capturing: hasNodeDef(combinator)
|
|
2960
|
+
capturing: hasNodeDef(combinator),
|
|
2961
|
+
lazyUsage: analyzeLazyUsage(combinator)
|
|
2663
2962
|
};
|
|
2664
2963
|
const r = emit(combinator, ctx, "_pos");
|
|
2665
2964
|
const collatorDecl = ctx.needsCollator ? `const _collator = new Intl.Collator(undefined, { sensitivity: 'accent' })
|
|
@@ -2705,6 +3004,11 @@ function compile(combinator, mapFnSources) {
|
|
|
2705
3004
|
parseWithContext(input, parseCtx, pos = 0) {
|
|
2706
3005
|
return fn(input, pos, ctx.runtimeParsers, ctx.mapFns, ctx.buildFns, parseCtx);
|
|
2707
3006
|
},
|
|
3007
|
+
// Note: collects recover()/expect() errors via _errors. Unlike interpreter
|
|
3008
|
+
// parse({recover:true}) it does NOT populate furthestFail — the compiled path
|
|
3009
|
+
// inlines failures for throughput and deliberately skips _probe bookkeeping.
|
|
3010
|
+
// Callers wanting a furthest-position diagnostic detect unconsumed input
|
|
3011
|
+
// (span.end < input.length) instead, which is mode-agnostic.
|
|
2708
3012
|
parseWithErrors(input, pos = 0) {
|
|
2709
3013
|
const errors = [];
|
|
2710
3014
|
const result = fn(input, pos, ctx.runtimeParsers, ctx.mapFns, ctx.buildFns, { ...defaultCtx, _errors: errors });
|
|
@@ -2712,6 +3016,66 @@ function compile(combinator, mapFnSources) {
|
|
|
2712
3016
|
}
|
|
2713
3017
|
};
|
|
2714
3018
|
}
|
|
3019
|
+
function compileRuleMap(ruleMap) {
|
|
3020
|
+
const ctx = {
|
|
3021
|
+
vars: 0,
|
|
3022
|
+
indent: 1,
|
|
3023
|
+
regexDecls: [],
|
|
3024
|
+
regexMap: /* @__PURE__ */ new Map(),
|
|
3025
|
+
mapFns: [],
|
|
3026
|
+
mapFnSrcs: [],
|
|
3027
|
+
buildFns: [],
|
|
3028
|
+
buildSrcs: [],
|
|
3029
|
+
runtimeParsers: [],
|
|
3030
|
+
needsCollator: false,
|
|
3031
|
+
namedParsers: /* @__PURE__ */ new Map(),
|
|
3032
|
+
triviaCaptureNames: /* @__PURE__ */ new Map(),
|
|
3033
|
+
triviaFnNames: /* @__PURE__ */ new Map(),
|
|
3034
|
+
namedFnDecls: [],
|
|
3035
|
+
capturing: ruleMap.some(([, rule]) => hasNodeDef(rule)),
|
|
3036
|
+
lazyUsage: analyzeLazyUsageMulti(ruleMap.map(([, rule]) => rule))
|
|
3037
|
+
};
|
|
3038
|
+
const perEntry = ruleMap.map(([key, rule]) => ({ key, r: emit(rule, ctx, "_pos") }));
|
|
3039
|
+
const collatorDecl = ctx.needsCollator ? `const _collator = new Intl.Collator(undefined, { sensitivity: 'accent' })
|
|
3040
|
+
` : "";
|
|
3041
|
+
const derivedSrcs = ctx.mapFnSrcs.length === ctx.mapFns.length && ctx.mapFnSrcs.every((s) => s !== null) ? ctx.mapFnSrcs : void 0;
|
|
3042
|
+
const buildCovered = ctx.buildFns.length === 0 || ctx.buildSrcs.every((s) => s !== null);
|
|
3043
|
+
const buildSources = ctx.buildFns.length === 0 ? void 0 : ctx.buildSrcs;
|
|
3044
|
+
const mfCovered = ctx.mapFns.length === 0 || derivedSrcs !== void 0;
|
|
3045
|
+
const canInline = ctx.runtimeParsers.length === 0 && mfCovered && buildCovered;
|
|
3046
|
+
if (!canInline) return null;
|
|
3047
|
+
const mfDecl = derivedSrcs?.length ? ` const _mf = [${derivedSrcs.join(", ")}]` : "";
|
|
3048
|
+
const buildDecl = buildSources?.length ? ` const _build = [${buildSources.join(", ")}]` : "";
|
|
3049
|
+
const namedPrelude = ctx.namedFnDecls.length > 0 ? namedFnPrelude() : [];
|
|
3050
|
+
const hoistedDecls = [
|
|
3051
|
+
...ctx.regexDecls.map((d) => ` ${d}`),
|
|
3052
|
+
collatorDecl ? ` ${collatorDecl.trim()}` : "",
|
|
3053
|
+
mfDecl,
|
|
3054
|
+
buildDecl,
|
|
3055
|
+
...namedPrelude.map((l) => ` ${l}`),
|
|
3056
|
+
...ctx.namedFnDecls.flatMap((decl, i) => {
|
|
3057
|
+
const lines = decl.split("\n").map((l) => ` ${l}`);
|
|
3058
|
+
return i > 0 ? ["", ...lines] : lines;
|
|
3059
|
+
})
|
|
3060
|
+
].filter(Boolean);
|
|
3061
|
+
const entryFnText = (r) => [
|
|
3062
|
+
`function(input, _pos, _ctx) {`,
|
|
3063
|
+
` let pos = _pos`,
|
|
3064
|
+
...r.stmts,
|
|
3065
|
+
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
3066
|
+
`}`
|
|
3067
|
+
].join("\n");
|
|
3068
|
+
const objBody = perEntry.map(({ key, r }) => ` ${JSON.stringify(key)}: ${entryFnText(r).split("\n").join("\n ")}`).join(",\n");
|
|
3069
|
+
const replacement = [
|
|
3070
|
+
`/* @__PURE__ */ (() => {`,
|
|
3071
|
+
...hoistedDecls,
|
|
3072
|
+
` return {`,
|
|
3073
|
+
objBody,
|
|
3074
|
+
` }`,
|
|
3075
|
+
`})()`
|
|
3076
|
+
].join("\n");
|
|
3077
|
+
return { keys: perEntry.map((e) => e.key), replacement };
|
|
3078
|
+
}
|
|
2715
3079
|
function buildInlineExpression(ctx, r, collatorDecl, mapFnSources, buildSources) {
|
|
2716
3080
|
const bodyLines = [
|
|
2717
3081
|
` let pos = _pos`,
|
|
@@ -2747,6 +3111,58 @@ function buildInlineExpression(ctx, r, collatorDecl, mapFnSources, buildSources)
|
|
|
2747
3111
|
].join("\n");
|
|
2748
3112
|
}
|
|
2749
3113
|
|
|
3114
|
+
// src/combinators/expect.ts
|
|
3115
|
+
function staticExpected(c) {
|
|
3116
|
+
const def = c._def;
|
|
3117
|
+
switch (def.tag) {
|
|
3118
|
+
case "literal":
|
|
3119
|
+
return [JSON.stringify(def.value)];
|
|
3120
|
+
case "regex":
|
|
3121
|
+
return [`/${def.source}/`];
|
|
3122
|
+
case "keywords":
|
|
3123
|
+
return def.words.map((w) => JSON.stringify(w));
|
|
3124
|
+
case "label":
|
|
3125
|
+
return [def.label];
|
|
3126
|
+
case "choice":
|
|
3127
|
+
return def.parsers.flatMap(staticExpected);
|
|
3128
|
+
case "sequence":
|
|
3129
|
+
return def.parsers.length > 0 ? staticExpected(def.parsers[0]) : [];
|
|
3130
|
+
case "node":
|
|
3131
|
+
case "grammar":
|
|
3132
|
+
case "trivia":
|
|
3133
|
+
case "optional":
|
|
3134
|
+
case "many":
|
|
3135
|
+
case "oneOrMore":
|
|
3136
|
+
case "transform":
|
|
3137
|
+
case "not":
|
|
3138
|
+
return staticExpected(def.parser);
|
|
3139
|
+
case "lazy":
|
|
3140
|
+
return staticExpected(def.thunk());
|
|
3141
|
+
default:
|
|
3142
|
+
return [];
|
|
3143
|
+
}
|
|
3144
|
+
}
|
|
3145
|
+
function expect(combinator, label2) {
|
|
3146
|
+
const expected = label2 !== void 0 ? [label2] : staticExpected(combinator);
|
|
3147
|
+
const meta = {
|
|
3148
|
+
firstSet: combinator._meta.firstSet,
|
|
3149
|
+
canMatchNewline: combinator._meta.canMatchNewline,
|
|
3150
|
+
isTrivia: false
|
|
3151
|
+
};
|
|
3152
|
+
return {
|
|
3153
|
+
_tag: "expect",
|
|
3154
|
+
_meta: meta,
|
|
3155
|
+
_def: { tag: "expect", parser: combinator, label: label2, expected },
|
|
3156
|
+
parse(input, pos, ctx) {
|
|
3157
|
+
const result = combinator.parse(input, pos, ctx);
|
|
3158
|
+
if (result.ok) return result;
|
|
3159
|
+
const error = { _tag: "parseError", span: { start: pos, end: pos }, expected };
|
|
3160
|
+
ctx._errors?.push(error);
|
|
3161
|
+
return { ok: true, value: error, span: { start: pos, end: pos } };
|
|
3162
|
+
}
|
|
3163
|
+
};
|
|
3164
|
+
}
|
|
3165
|
+
|
|
2750
3166
|
// src/combinators/scanTo.ts
|
|
2751
3167
|
function scanTo(sentinel, { skip: skip2 = [], orEOF = false } = {}) {
|
|
2752
3168
|
const meta = {
|
|
@@ -2760,7 +3176,11 @@ function scanTo(sentinel, { skip: skip2 = [], orEOF = false } = {}) {
|
|
|
2760
3176
|
_def: { tag: "scanTo", sentinel, skip: skip2, orEOF },
|
|
2761
3177
|
parse(input, pos, ctx) {
|
|
2762
3178
|
let cur = pos;
|
|
2763
|
-
const probeCtx = {
|
|
3179
|
+
const probeCtx = {
|
|
3180
|
+
trackLines: ctx.trackLines,
|
|
3181
|
+
state: ctx.state,
|
|
3182
|
+
...ctx._errors !== void 0 ? { _errors: ctx._errors } : {}
|
|
3183
|
+
};
|
|
2764
3184
|
const emit2 = (end) => {
|
|
2765
3185
|
if (end > pos && cstCaptureActive(ctx)) {
|
|
2766
3186
|
const leaf = { _tag: "leaf", value: input.slice(pos, end), span: { start: pos, end } };
|
|
@@ -2796,20 +3216,46 @@ function scanTo(sentinel, { skip: skip2 = [], orEOF = false } = {}) {
|
|
|
2796
3216
|
}
|
|
2797
3217
|
function balanced(open, close, options = {}) {
|
|
2798
3218
|
const self = ref();
|
|
2799
|
-
const
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
3219
|
+
const skips = options.skip ?? [];
|
|
3220
|
+
const stop = /* @__PURE__ */ new Set([open, close]);
|
|
3221
|
+
let bounded = true;
|
|
3222
|
+
for (const sk of skips) {
|
|
3223
|
+
const cs = firstSetClassChars(sk);
|
|
3224
|
+
if (cs === null) {
|
|
3225
|
+
bounded = false;
|
|
3226
|
+
break;
|
|
3227
|
+
}
|
|
3228
|
+
for (const ch of cs) stop.add(ch);
|
|
3229
|
+
}
|
|
3230
|
+
const cls = [...stop].map(escapeClassChar).join("");
|
|
3231
|
+
const content = bounded ? regex(new RegExp(`[^${cls}]+`)) : regex(new RegExp(`[^${escapeClassChar(open)}${escapeClassChar(close)}]`));
|
|
3232
|
+
const inner = many(choice(self, ...skips, content));
|
|
2803
3233
|
const combi = transform(
|
|
2804
|
-
sequence(literal(open), inner, literal(close)),
|
|
2805
|
-
(
|
|
3234
|
+
sequence(literal(open), inner, expect(literal(close), close)),
|
|
3235
|
+
// parts: strings (content/self) or arrays (a sequence-shaped skip) or a
|
|
3236
|
+
// ParseError (recovered close). `c` is the close string or a ParseError.
|
|
3237
|
+
([o, parts, c]) => o + parts.map((p) => typeof p === "string" ? p : Array.isArray(p) ? p.join("") : "").join("") + (typeof c === "string" ? c : "")
|
|
2806
3238
|
);
|
|
2807
3239
|
if (combi._def.tag === "transform") {
|
|
2808
|
-
combi._def.fnSrc =
|
|
3240
|
+
combi._def.fnSrc = '([o, parts, c]) => o + parts.map(p => typeof p === "string" ? p : Array.isArray(p) ? p.join("") : "").join("") + (typeof c === "string" ? c : "")';
|
|
2809
3241
|
}
|
|
2810
3242
|
self.define(combi);
|
|
2811
3243
|
return combi;
|
|
2812
3244
|
}
|
|
3245
|
+
function firstSetClassChars(c) {
|
|
3246
|
+
const fs = c._meta.firstSet;
|
|
3247
|
+
if (fs.kind === "empty") return [];
|
|
3248
|
+
if (fs.kind !== "ranges") return null;
|
|
3249
|
+
const out = [];
|
|
3250
|
+
for (const { lo, hi } of fs.ranges) {
|
|
3251
|
+
if (hi - lo > 8) return null;
|
|
3252
|
+
for (let cp = lo; cp <= hi; cp++) out.push(String.fromCodePoint(cp));
|
|
3253
|
+
}
|
|
3254
|
+
return out;
|
|
3255
|
+
}
|
|
3256
|
+
function escapeClassChar(ch) {
|
|
3257
|
+
return ch.replace(/[\\\]^-]/g, "\\$&");
|
|
3258
|
+
}
|
|
2813
3259
|
|
|
2814
3260
|
// src/plugin/evaluator.ts
|
|
2815
3261
|
function isWordFactory(v2) {
|
|
@@ -2828,7 +3274,8 @@ var SUPPORTED = {
|
|
|
2828
3274
|
sepBy: (...a) => sepBy(a[0], a[1]),
|
|
2829
3275
|
trivia: (...a) => trivia(a[0]),
|
|
2830
3276
|
label: (...a) => label(a[0], a[1]),
|
|
2831
|
-
noTrivia: (...a) => noTrivia(a[0])
|
|
3277
|
+
noTrivia: (...a) => noTrivia(a[0]),
|
|
3278
|
+
expect: (...a) => expect(a[0], a[1])
|
|
2832
3279
|
};
|
|
2833
3280
|
function isScopeEntry(v2) {
|
|
2834
3281
|
return !!v2 && typeof v2 === "object" && "combi" in v2 && "mfSrcs" in v2;
|
|
@@ -2910,6 +3357,10 @@ function exprToCombi(node2, scope, code, mfs) {
|
|
|
2910
3357
|
}
|
|
2911
3358
|
}
|
|
2912
3359
|
if (callee.name === "rules") return null;
|
|
3360
|
+
if (callee.name === "ref") {
|
|
3361
|
+
if (node2.arguments.length !== 0) return null;
|
|
3362
|
+
return ref();
|
|
3363
|
+
}
|
|
2913
3364
|
if (callee.name === "parser") {
|
|
2914
3365
|
const [optsArg, rootArg] = node2.arguments;
|
|
2915
3366
|
if (!optsArg || !rootArg || optsArg.type === "SpreadElement" || rootArg.type === "SpreadElement") return null;
|
|
@@ -2964,13 +3415,14 @@ function exprToCombi(node2, scope, code, mfs) {
|
|
|
2964
3415
|
}
|
|
2965
3416
|
}
|
|
2966
3417
|
if (callee.name === "balanced") {
|
|
2967
|
-
const [openArg, closeArg] = node2.arguments;
|
|
3418
|
+
const [openArg, closeArg, optsArg] = node2.arguments;
|
|
2968
3419
|
if (!openArg || !closeArg || openArg.type === "SpreadElement" || closeArg.type === "SpreadElement") return null;
|
|
2969
3420
|
const open = anyValue(openArg, scope, code, []);
|
|
2970
3421
|
const close = anyValue(closeArg, scope, code, []);
|
|
2971
3422
|
if (typeof open !== "string" || typeof close !== "string") return null;
|
|
3423
|
+
const opts = optsArg && optsArg.type !== "SpreadElement" ? anyValue(optsArg, scope, code, []) : void 0;
|
|
2972
3424
|
try {
|
|
2973
|
-
return balanced(open, close);
|
|
3425
|
+
return balanced(open, close, opts);
|
|
2974
3426
|
} catch {
|
|
2975
3427
|
return null;
|
|
2976
3428
|
}
|
|
@@ -3148,6 +3600,40 @@ function evaluateParserFactory(factoryNode, scope, code, mapFnSources) {
|
|
|
3148
3600
|
}
|
|
3149
3601
|
return ruleRefs;
|
|
3150
3602
|
}
|
|
3603
|
+
function isDefinableRef(v2) {
|
|
3604
|
+
return isCombinator(v2) && typeof v2.define === "function" && v2._def.tag === "lazy";
|
|
3605
|
+
}
|
|
3606
|
+
function evaluateRefDeclaration(init, name, scope) {
|
|
3607
|
+
if (init.type !== "CallExpression") return null;
|
|
3608
|
+
const callee = init.callee;
|
|
3609
|
+
if (callee.type !== "Identifier" || callee.name !== "ref") return null;
|
|
3610
|
+
if (init.arguments.length !== 0) return null;
|
|
3611
|
+
const slot = ref();
|
|
3612
|
+
scope.set(name, { combi: slot, mfSrcs: [] });
|
|
3613
|
+
return slot;
|
|
3614
|
+
}
|
|
3615
|
+
function applyDefineStatement(callExpr, scope, code) {
|
|
3616
|
+
if (callExpr.type !== "CallExpression") return false;
|
|
3617
|
+
const callee = callExpr.callee;
|
|
3618
|
+
if (callee.type !== "MemberExpression") return false;
|
|
3619
|
+
const mem = callee;
|
|
3620
|
+
if (mem.computed) return false;
|
|
3621
|
+
if (mem.property.type !== "Identifier" || mem.property.name !== "define") return false;
|
|
3622
|
+
if (mem.object.type !== "Identifier" || !mem.object.name) return false;
|
|
3623
|
+
const target = scope.get(mem.object.name);
|
|
3624
|
+
const refCombi = isScopeEntry(target) ? target.combi : isCombinator(target) ? target : null;
|
|
3625
|
+
if (!refCombi || !isDefinableRef(refCombi)) return false;
|
|
3626
|
+
const args = callExpr.arguments;
|
|
3627
|
+
if (args.length !== 1 || args[0].type === "SpreadElement") return false;
|
|
3628
|
+
const inner = anyValue(args[0], scope, code, []);
|
|
3629
|
+
if (!isCombinator(inner)) return false;
|
|
3630
|
+
try {
|
|
3631
|
+
refCombi.define(inner);
|
|
3632
|
+
} catch {
|
|
3633
|
+
return false;
|
|
3634
|
+
}
|
|
3635
|
+
return true;
|
|
3636
|
+
}
|
|
3151
3637
|
function referencesAny(node2, names, scope) {
|
|
3152
3638
|
if (node2.type === "Identifier") {
|
|
3153
3639
|
return names.has(node2.name) || scope.has(node2.name);
|
|
@@ -3222,6 +3708,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
3222
3708
|
const replacements = [];
|
|
3223
3709
|
const warnings = [];
|
|
3224
3710
|
let anyUnresolved = false;
|
|
3711
|
+
let ruleMapHolderCounter = 0;
|
|
3225
3712
|
const lineOf = (pos) => {
|
|
3226
3713
|
let line = 1;
|
|
3227
3714
|
for (let i = 0; i < pos && i < code.length; i++) if (code.charCodeAt(i) === 10) line++;
|
|
@@ -3243,18 +3730,53 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
3243
3730
|
warn(init.start, `${label2}: rules(...) factory isn't statically evaluable`);
|
|
3244
3731
|
return null;
|
|
3245
3732
|
}
|
|
3246
|
-
const
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
warn(init.start, `${label2}: rule "${ruleKey}" couldn't be inlined`);
|
|
3251
|
-
return null;
|
|
3252
|
-
}
|
|
3253
|
-
entries.push([ruleKey, compiled.inlineExpression]);
|
|
3733
|
+
const compiled = compileRuleMap([...ruleMap]);
|
|
3734
|
+
if (!compiled) {
|
|
3735
|
+
warn(init.start, `${label2}: rule map couldn't be inlined`);
|
|
3736
|
+
return null;
|
|
3254
3737
|
}
|
|
3255
|
-
return {
|
|
3738
|
+
return { replacement: compiled.replacement, ruleMap };
|
|
3256
3739
|
};
|
|
3257
3740
|
const isRulesCall = (init) => init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "rules";
|
|
3741
|
+
const unwrapVd = (stmt) => stmt.type === "VariableDeclaration" ? stmt : stmt.type === "ExportNamedDeclaration" && stmt.declaration?.type === "VariableDeclaration" ? stmt.declaration : null;
|
|
3742
|
+
const refNames = /* @__PURE__ */ new Set();
|
|
3743
|
+
for (const stmt of body) {
|
|
3744
|
+
const innerVd = unwrapVd(stmt);
|
|
3745
|
+
if (!innerVd) continue;
|
|
3746
|
+
for (const decl of innerVd.declarations) {
|
|
3747
|
+
const d = decl;
|
|
3748
|
+
if (!d.init || d.id.type !== "Identifier") continue;
|
|
3749
|
+
const init = d.init;
|
|
3750
|
+
if (init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "ref") {
|
|
3751
|
+
refNames.add(d.id.name);
|
|
3752
|
+
}
|
|
3753
|
+
}
|
|
3754
|
+
}
|
|
3755
|
+
const defineRemovals = [];
|
|
3756
|
+
if (refNames.size > 0) {
|
|
3757
|
+
for (const stmt of body) {
|
|
3758
|
+
if (stmt.type === "ExpressionStatement") {
|
|
3759
|
+
const expr = stmt.expression;
|
|
3760
|
+
if (applyDefineStatement(expr, scope, code)) {
|
|
3761
|
+
defineRemovals.push({ start: stmt.start, end: stmt.end });
|
|
3762
|
+
}
|
|
3763
|
+
continue;
|
|
3764
|
+
}
|
|
3765
|
+
const innerVd = unwrapVd(stmt);
|
|
3766
|
+
if (!innerVd) continue;
|
|
3767
|
+
for (const decl of innerVd.declarations) {
|
|
3768
|
+
const d = decl;
|
|
3769
|
+
if (!d.init || d.id.type !== "Identifier") continue;
|
|
3770
|
+
const name = d.id.name;
|
|
3771
|
+
const init = d.init;
|
|
3772
|
+
if (evaluateRefDeclaration(init, name, scope)) continue;
|
|
3773
|
+
if (scope.has(name)) continue;
|
|
3774
|
+
if (!referencesAny(init, allNames, scope)) continue;
|
|
3775
|
+
const combi = evaluateExpr(init, scope, code, []);
|
|
3776
|
+
if (combi) scope.set(name, { combi, mfSrcs: [] });
|
|
3777
|
+
}
|
|
3778
|
+
}
|
|
3779
|
+
}
|
|
3258
3780
|
for (const stmt of body) {
|
|
3259
3781
|
let vd = null;
|
|
3260
3782
|
let stmtStart = stmt.start;
|
|
@@ -3278,15 +3800,26 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
3278
3800
|
if (d.id.type === "Identifier") {
|
|
3279
3801
|
const varName = d.id.name;
|
|
3280
3802
|
if (!referencesAny(init, allNames, scope)) continue;
|
|
3803
|
+
if (refNames.has(varName)) {
|
|
3804
|
+
const refEntry = scope.get(varName);
|
|
3805
|
+
const refCombi = refEntry?.combi ?? null;
|
|
3806
|
+
if (refCombi) {
|
|
3807
|
+
const compiled2 = compile(refCombi);
|
|
3808
|
+
if (compiled2.inlineExpression === null) {
|
|
3809
|
+
warn(init.start, `"${varName}" is a ref() that couldn't be inlined (was .define() called with a static combinator?)`);
|
|
3810
|
+
continue;
|
|
3811
|
+
}
|
|
3812
|
+
replacements.push({ start: init.start, end: init.end, replacement: compiled2.inlineExpression });
|
|
3813
|
+
continue;
|
|
3814
|
+
}
|
|
3815
|
+
}
|
|
3281
3816
|
if (isRulesCall(init)) {
|
|
3282
3817
|
const compiledRules = compileRulesFactory(init, varName);
|
|
3283
3818
|
if (!compiledRules) continue;
|
|
3284
3819
|
replacements.push({
|
|
3285
3820
|
start: init.start,
|
|
3286
3821
|
end: init.end,
|
|
3287
|
-
replacement:
|
|
3288
|
-
${compiledRules.entries.map(([k, expr]) => ` ${k}: ${expr}`).join(",\n")}
|
|
3289
|
-
}`
|
|
3822
|
+
replacement: compiledRules.replacement
|
|
3290
3823
|
});
|
|
3291
3824
|
continue;
|
|
3292
3825
|
}
|
|
@@ -3321,9 +3854,8 @@ ${compiledRules.entries.map(([k, expr]) => ` ${k}: ${expr}`).join(",\n")}
|
|
|
3321
3854
|
}
|
|
3322
3855
|
const compiledRules = compileRulesFactory(init, "{ \u2026 }");
|
|
3323
3856
|
if (!compiledRules) continue;
|
|
3324
|
-
const byKey = new Map(compiledRules.entries);
|
|
3325
3857
|
const pattern = d.id;
|
|
3326
|
-
const
|
|
3858
|
+
const bindings = [];
|
|
3327
3859
|
let allOk = true;
|
|
3328
3860
|
for (const prop of pattern.properties) {
|
|
3329
3861
|
const p = prop;
|
|
@@ -3338,17 +3870,21 @@ ${compiledRules.entries.map(([k, expr]) => ` ${k}: ${expr}`).join(",\n")}
|
|
|
3338
3870
|
allOk = false;
|
|
3339
3871
|
break;
|
|
3340
3872
|
}
|
|
3341
|
-
|
|
3342
|
-
if (inlineExpr === void 0) {
|
|
3873
|
+
if (!compiledRules.ruleMap.has(ruleKey)) {
|
|
3343
3874
|
warn(init.start, `destructured rule "${ruleKey}" isn't returned by the rules() factory`);
|
|
3344
3875
|
allOk = false;
|
|
3345
3876
|
break;
|
|
3346
3877
|
}
|
|
3347
|
-
|
|
3878
|
+
bindings.push({ ruleKey, localName });
|
|
3348
3879
|
const rule = compiledRules.ruleMap.get(ruleKey);
|
|
3349
3880
|
if (rule) scope.set(localName, { combi: rule, mfSrcs: [] });
|
|
3350
3881
|
}
|
|
3351
3882
|
if (!allOk) continue;
|
|
3883
|
+
const holderVar = `__rules${ruleMapHolderCounter++}`;
|
|
3884
|
+
const lines = [
|
|
3885
|
+
`const ${holderVar} = ${compiledRules.replacement}`,
|
|
3886
|
+
...bindings.map(({ ruleKey, localName }) => `${exportPrefix}${kind} ${localName} = ${holderVar}[${JSON.stringify(ruleKey)}]`)
|
|
3887
|
+
];
|
|
3352
3888
|
replacements.push({
|
|
3353
3889
|
start: stmtStart,
|
|
3354
3890
|
end: stmtEnd,
|
|
@@ -3362,6 +3898,9 @@ ${compiledRules.entries.map(([k, expr]) => ` ${k}: ${expr}`).join(",\n")}
|
|
|
3362
3898
|
imp.fullyResolved = !anyUnresolved;
|
|
3363
3899
|
}
|
|
3364
3900
|
const ms = new import_magic_string.default(code);
|
|
3901
|
+
if (!anyUnresolved) {
|
|
3902
|
+
for (const { start, end } of defineRemovals) ms.remove(start, end);
|
|
3903
|
+
}
|
|
3365
3904
|
for (const imp of macroImports) {
|
|
3366
3905
|
if (imp.fullyResolved) {
|
|
3367
3906
|
ms.remove(imp.start, imp.end);
|