parseman 0.22.0 → 0.24.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/keywords.d.ts.map +1 -1
- package/dist/combinators/literal.d.ts.map +1 -1
- package/dist/combinators/parser.d.ts +6 -0
- package/dist/combinators/parser.d.ts.map +1 -1
- package/dist/combinators/regex.d.ts.map +1 -1
- package/dist/combinators/trivia-skip.d.ts.map +1 -1
- package/dist/compiler/codegen.d.ts +3 -1
- package/dist/compiler/codegen.d.ts.map +1 -1
- package/dist/compiler/linker.d.ts +7 -2
- package/dist/compiler/linker.d.ts.map +1 -1
- package/dist/index.cjs +429 -75
- package/dist/index.cjs.map +3 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +429 -75
- package/dist/index.js.map +3 -3
- package/dist/plugin/index.cjs +284 -66
- package/dist/plugin/index.cjs.map +3 -3
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +284 -66
- package/dist/plugin/index.js.map +3 -3
- package/dist/spec/ebnf.d.ts +13 -0
- package/dist/spec/ebnf.d.ts.map +1 -0
- package/dist/spec/index.cjs +977 -0
- package/dist/spec/index.cjs.map +7 -0
- package/dist/spec/index.d.ts +15 -0
- package/dist/spec/index.d.ts.map +1 -0
- package/dist/spec/index.js +954 -0
- package/dist/spec/index.js.map +7 -0
- package/dist/spec/model.d.ts +117 -0
- package/dist/spec/model.d.ts.map +1 -0
- package/dist/spec/railroad-lib.d.ts +11 -0
- package/dist/spec/railroad-lib.d.ts.map +1 -0
- package/dist/spec/railroad.d.ts +18 -0
- package/dist/spec/railroad.d.ts.map +1 -0
- package/package.json +6 -1
package/dist/plugin/index.cjs
CHANGED
|
@@ -422,24 +422,35 @@ function literal(value, opts = {}) {
|
|
|
422
422
|
{ lo: firstUpper, hi: firstUpper }
|
|
423
423
|
] } : firstSet2;
|
|
424
424
|
}
|
|
425
|
+
const expected = [JSON.stringify(value)];
|
|
426
|
+
const parse2 = !caseInsensitive && value.length === 1 ? (() => {
|
|
427
|
+
const code = value.charCodeAt(0);
|
|
428
|
+
return function parse3(input, pos, ctx) {
|
|
429
|
+
if (input.charCodeAt(pos) === code) {
|
|
430
|
+
const span = { start: pos, end: pos + 1 };
|
|
431
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
|
|
432
|
+
return { ok: true, value, span };
|
|
433
|
+
}
|
|
434
|
+
return failAt(ctx, expected, pos);
|
|
435
|
+
};
|
|
436
|
+
})() : function parse3(input, pos, ctx) {
|
|
437
|
+
const end = pos + value.length;
|
|
438
|
+
if (end > input.length) {
|
|
439
|
+
return failAt(ctx, expected, pos);
|
|
440
|
+
}
|
|
441
|
+
const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
|
|
442
|
+
if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
|
|
443
|
+
const span = { start: pos, end };
|
|
444
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: matchedValue, span });
|
|
445
|
+
return { ok: true, value: matchedValue, span };
|
|
446
|
+
}
|
|
447
|
+
return failAt(ctx, expected, pos);
|
|
448
|
+
};
|
|
425
449
|
return {
|
|
426
450
|
_tag: "literal",
|
|
427
451
|
_meta: meta,
|
|
428
452
|
_def: { tag: "literal", value, caseInsensitive },
|
|
429
|
-
parse
|
|
430
|
-
const end = pos + value.length;
|
|
431
|
-
if (end > input.length) {
|
|
432
|
-
return failAt(ctx, [JSON.stringify(value)], pos);
|
|
433
|
-
}
|
|
434
|
-
const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
|
|
435
|
-
if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
|
|
436
|
-
const span = { start: pos, end };
|
|
437
|
-
const leaf = { _tag: "leaf", value: matchedValue, span };
|
|
438
|
-
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
|
|
439
|
-
return { ok: true, value: matchedValue, span };
|
|
440
|
-
}
|
|
441
|
-
return failAt(ctx, [JSON.stringify(value)], pos);
|
|
442
|
-
}
|
|
453
|
+
parse: parse2
|
|
443
454
|
};
|
|
444
455
|
}
|
|
445
456
|
|
|
@@ -574,8 +585,7 @@ function regex(pattern, flags = "") {
|
|
|
574
585
|
if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
|
|
575
586
|
const value = input.slice(pos, scanEnd);
|
|
576
587
|
const span2 = { start: pos, end: scanEnd };
|
|
577
|
-
|
|
578
|
-
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf2);
|
|
588
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: span2 });
|
|
579
589
|
return { ok: true, value, span: span2 };
|
|
580
590
|
}
|
|
581
591
|
anchored.lastIndex = pos;
|
|
@@ -584,8 +594,7 @@ function regex(pattern, flags = "") {
|
|
|
584
594
|
return failAt(ctx, [`/${source}/`], pos);
|
|
585
595
|
}
|
|
586
596
|
const span = { start: pos, end: pos + m[0].length };
|
|
587
|
-
|
|
588
|
-
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
|
|
597
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: m[0], span });
|
|
589
598
|
return { ok: true, value: m[0], span };
|
|
590
599
|
}
|
|
591
600
|
};
|
|
@@ -890,8 +899,7 @@ function keywords(words, opts = {}) {
|
|
|
890
899
|
}
|
|
891
900
|
const value = m[0];
|
|
892
901
|
const span = { start: pos, end: pos + value.length };
|
|
893
|
-
|
|
894
|
-
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
|
|
902
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
|
|
895
903
|
return { ok: true, value, span };
|
|
896
904
|
}
|
|
897
905
|
};
|
|
@@ -1381,33 +1389,136 @@ function loopScanner(arms) {
|
|
|
1381
1389
|
}
|
|
1382
1390
|
function regexTriviaScanner(parser2) {
|
|
1383
1391
|
if (parser2._def.tag !== "regex" || parser2._def.flags) return null;
|
|
1384
|
-
const
|
|
1385
|
-
|
|
1386
|
-
return blockCommentSource(parser2._def.source) ? scanBlockComment : null;
|
|
1392
|
+
const source = parser2._def.source;
|
|
1393
|
+
return classRunSource(source) ?? altStarSource(source) ?? (blockCommentSource(source) ? scanBlockComment : null);
|
|
1387
1394
|
}
|
|
1388
|
-
function
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1395
|
+
function inRanges2(cp, ranges) {
|
|
1396
|
+
for (let i = 0; i < ranges.length; i++) {
|
|
1397
|
+
const r = ranges[i];
|
|
1398
|
+
if (cp >= r[0] && cp <= r[1]) return true;
|
|
1399
|
+
}
|
|
1400
|
+
return false;
|
|
1401
|
+
}
|
|
1402
|
+
function classScanner(classBody) {
|
|
1403
|
+
const ranges = parseClassRanges(classBody);
|
|
1404
|
+
if (!ranges) return null;
|
|
1405
|
+
return (input, cur) => {
|
|
1406
|
+
let pos = cur;
|
|
1407
|
+
while (pos < input.length && inRanges2(input.charCodeAt(pos), ranges)) pos++;
|
|
1408
|
+
return pos;
|
|
1409
|
+
};
|
|
1410
|
+
}
|
|
1411
|
+
function lineCommentScanner(commentCode) {
|
|
1412
|
+
return (input, cur) => {
|
|
1413
|
+
if (input.charCodeAt(cur) !== commentCode) return cur;
|
|
1414
|
+
let pos = cur + 1;
|
|
1415
|
+
while (pos < input.length) {
|
|
1416
|
+
const cc = input.charCodeAt(pos);
|
|
1417
|
+
if (cc === 10 || cc === 13) break;
|
|
1418
|
+
pos++;
|
|
1397
1419
|
}
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1420
|
+
return pos;
|
|
1421
|
+
};
|
|
1422
|
+
}
|
|
1423
|
+
function classRunSource(source) {
|
|
1424
|
+
const m = /^\[([^\]^](?:[^\]]|\\.)*)\][*+]$/.exec(source);
|
|
1425
|
+
return m ? classScanner(m[1]) : null;
|
|
1426
|
+
}
|
|
1427
|
+
function classifyTriviaArm(arm) {
|
|
1428
|
+
const cls = /^\[([^\]^](?:[^\]]|\\.)*)\][*+]?$/.exec(arm);
|
|
1429
|
+
if (cls) {
|
|
1430
|
+
const ranges = parseClassRanges(cls[1]);
|
|
1431
|
+
return ranges ? { kind: "class", ranges } : null;
|
|
1432
|
+
}
|
|
1433
|
+
const lc = /^(\\?.)\[\^\\n\\r\]\*$/.exec(arm);
|
|
1434
|
+
if (lc) {
|
|
1435
|
+
const marker = lc[1];
|
|
1436
|
+
return { kind: "comment", code: (marker.length === 2 ? marker[1] : marker[0]).charCodeAt(0) };
|
|
1404
1437
|
}
|
|
1438
|
+
return null;
|
|
1439
|
+
}
|
|
1440
|
+
function armScanner(arm) {
|
|
1441
|
+
if (arm.kind === "comment") return lineCommentScanner(arm.code);
|
|
1442
|
+
const ranges = arm.ranges;
|
|
1405
1443
|
return (input, cur) => {
|
|
1406
1444
|
let pos = cur;
|
|
1407
|
-
while (pos < input.length &&
|
|
1445
|
+
while (pos < input.length && inRanges2(input.charCodeAt(pos), ranges)) pos++;
|
|
1408
1446
|
return pos;
|
|
1409
1447
|
};
|
|
1410
1448
|
}
|
|
1449
|
+
function fusedTriviaScanner(ranges, commentCodes) {
|
|
1450
|
+
const c0 = commentCodes[0];
|
|
1451
|
+
const single = commentCodes.length === 1;
|
|
1452
|
+
return (input, cur) => {
|
|
1453
|
+
let pos = cur;
|
|
1454
|
+
const len = input.length;
|
|
1455
|
+
for (; ; ) {
|
|
1456
|
+
const c = input.charCodeAt(pos);
|
|
1457
|
+
if (pos < len && inRanges2(c, ranges)) {
|
|
1458
|
+
pos++;
|
|
1459
|
+
continue;
|
|
1460
|
+
}
|
|
1461
|
+
if (single ? c === c0 : commentCodes.includes(c)) {
|
|
1462
|
+
pos++;
|
|
1463
|
+
while (pos < len) {
|
|
1464
|
+
const cc = input.charCodeAt(pos);
|
|
1465
|
+
if (cc === 10 || cc === 13) break;
|
|
1466
|
+
pos++;
|
|
1467
|
+
}
|
|
1468
|
+
continue;
|
|
1469
|
+
}
|
|
1470
|
+
break;
|
|
1471
|
+
}
|
|
1472
|
+
return pos;
|
|
1473
|
+
};
|
|
1474
|
+
}
|
|
1475
|
+
function splitTopLevelAlts(body) {
|
|
1476
|
+
const arms = [];
|
|
1477
|
+
let inClass = false;
|
|
1478
|
+
let start = 0;
|
|
1479
|
+
for (let i = 0; i < body.length; i++) {
|
|
1480
|
+
const c = body[i];
|
|
1481
|
+
if (c === "\\") {
|
|
1482
|
+
i++;
|
|
1483
|
+
continue;
|
|
1484
|
+
}
|
|
1485
|
+
if (inClass) {
|
|
1486
|
+
if (c === "]") inClass = false;
|
|
1487
|
+
continue;
|
|
1488
|
+
}
|
|
1489
|
+
if (c === "[") inClass = true;
|
|
1490
|
+
else if (c === "(") return null;
|
|
1491
|
+
else if (c === "|") {
|
|
1492
|
+
arms.push(body.slice(start, i));
|
|
1493
|
+
start = i + 1;
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
arms.push(body.slice(start));
|
|
1497
|
+
return arms;
|
|
1498
|
+
}
|
|
1499
|
+
function altStarSource(source) {
|
|
1500
|
+
const m = /^\(\?:(.*)\)[*+]$/.exec(source);
|
|
1501
|
+
if (!m) return null;
|
|
1502
|
+
const armSrcs = splitTopLevelAlts(m[1]);
|
|
1503
|
+
if (!armSrcs || armSrcs.length < 2) return null;
|
|
1504
|
+
const arms = [];
|
|
1505
|
+
for (const src of armSrcs) {
|
|
1506
|
+
const arm = classifyTriviaArm(src);
|
|
1507
|
+
if (!arm) return null;
|
|
1508
|
+
arms.push(arm);
|
|
1509
|
+
}
|
|
1510
|
+
const ranges = [];
|
|
1511
|
+
const commentCodes = [];
|
|
1512
|
+
for (const arm of arms) {
|
|
1513
|
+
if (arm.kind === "class") ranges.push(...arm.ranges);
|
|
1514
|
+
else commentCodes.push(arm.code);
|
|
1515
|
+
}
|
|
1516
|
+
if (commentCodes.some((code) => inRanges2(code, ranges))) {
|
|
1517
|
+
return loopScanner(arms.map(armScanner));
|
|
1518
|
+
}
|
|
1519
|
+
if (commentCodes.length === 0) return armScanner({ kind: "class", ranges });
|
|
1520
|
+
return fusedTriviaScanner(ranges, commentCodes);
|
|
1521
|
+
}
|
|
1411
1522
|
function blockCommentSource(source) {
|
|
1412
1523
|
return source === "\\/\\*(?:[^*]|\\*(?!\\/))*\\*\\/" || source === "\\/\\*[^]*?\\*\\/";
|
|
1413
1524
|
}
|
|
@@ -1724,6 +1835,7 @@ function markUnusedValues(root) {
|
|
|
1724
1835
|
}
|
|
1725
1836
|
|
|
1726
1837
|
// src/combinators/parser.ts
|
|
1838
|
+
var RULE_ORDER = "__parsemanRuleOrder";
|
|
1727
1839
|
function tagRule(r, key) {
|
|
1728
1840
|
;
|
|
1729
1841
|
r._ruleName = key;
|
|
@@ -1768,6 +1880,11 @@ function rules(a, b) {
|
|
|
1768
1880
|
for (const key of Object.keys(definitions)) {
|
|
1769
1881
|
markUnusedValues(cache[key]);
|
|
1770
1882
|
}
|
|
1883
|
+
Object.defineProperty(cache, RULE_ORDER, {
|
|
1884
|
+
value: Object.keys(definitions),
|
|
1885
|
+
enumerable: false,
|
|
1886
|
+
configurable: true
|
|
1887
|
+
});
|
|
1771
1888
|
return cache;
|
|
1772
1889
|
}
|
|
1773
1890
|
|
|
@@ -5539,9 +5656,10 @@ function compileRuleMap(ruleMap, opts) {
|
|
|
5539
5656
|
].join("\n");
|
|
5540
5657
|
return { keys: perEntry.map((e) => e.key), replacement };
|
|
5541
5658
|
}
|
|
5542
|
-
function compileLinkable(ruleMapArg, ns) {
|
|
5659
|
+
function compileLinkable(ruleMapArg, ns, opts) {
|
|
5543
5660
|
if (!ns) throw new Error("compileLinkable: ns must be a non-empty namespace");
|
|
5544
5661
|
for (const [, rule] of ruleMapArg) markUnusedValues(rule);
|
|
5662
|
+
const grammarTrivia = opts?.trivia ?? ruleMapArg.map(([, r]) => r._meta.grammarTrivia).find(Boolean);
|
|
5545
5663
|
const ruleMap = ruleMapArg.filter(([, val]) => {
|
|
5546
5664
|
const d = val._def;
|
|
5547
5665
|
if (d.tag !== "lazy") return true;
|
|
@@ -5572,7 +5690,8 @@ function compileLinkable(ruleMapArg, ns) {
|
|
|
5572
5690
|
capturing: ruleMap.some(([, rule]) => hasNodeDef(rule)),
|
|
5573
5691
|
lazyUsage: analyzeLazyUsageMulti(ruleMap.map(([, rule]) => rule)),
|
|
5574
5692
|
ns,
|
|
5575
|
-
deferFirstSetRefs: true
|
|
5693
|
+
deferFirstSetRefs: true,
|
|
5694
|
+
...grammarTrivia ? { activeTrivia: grammarTrivia, triviaKindLabels: grammarTrivia._meta.triviaKindLabels } : {}
|
|
5576
5695
|
};
|
|
5577
5696
|
const seen = /* @__PURE__ */ new Map();
|
|
5578
5697
|
const ruleNames = /* @__PURE__ */ new Map();
|
|
@@ -5635,7 +5754,10 @@ function compileLinkable(ruleMapArg, ns) {
|
|
|
5635
5754
|
ctx.indent = 1;
|
|
5636
5755
|
ctx.failLabel = "_pfail";
|
|
5637
5756
|
ctx.recordFail = true;
|
|
5757
|
+
const savedTrivia = ctx.activeTrivia;
|
|
5758
|
+
if (rule._meta.isTrivia) ctx.activeTrivia = void 0;
|
|
5638
5759
|
const body = emit(resolved, ctx, "_pos");
|
|
5760
|
+
ctx.activeTrivia = savedTrivia;
|
|
5639
5761
|
ctx.indent = savedIndent;
|
|
5640
5762
|
ctx.failLabel = savedFail;
|
|
5641
5763
|
ctx.recordFail = savedRec;
|
|
@@ -6129,6 +6251,23 @@ ${body}
|
|
|
6129
6251
|
};
|
|
6130
6252
|
|
|
6131
6253
|
// src/compiler/linker.ts
|
|
6254
|
+
function pickPieces(pieces, names) {
|
|
6255
|
+
const winner = /* @__PURE__ */ new Map();
|
|
6256
|
+
for (const pc of pieces) for (const k of pc.keys) winner.set(k, pc);
|
|
6257
|
+
for (const n of names) {
|
|
6258
|
+
if (!winner.has(n)) throw new Error(`pick: rule "${n}" is not in this grammar (available: ${[...winner.keys()].join(", ")})`);
|
|
6259
|
+
}
|
|
6260
|
+
const keep = /* @__PURE__ */ new Set();
|
|
6261
|
+
const visit = (n) => {
|
|
6262
|
+
const w = winner.get(n);
|
|
6263
|
+
if (keep.has(n) || !w) return;
|
|
6264
|
+
keep.add(n);
|
|
6265
|
+
for (const d of w.deps.get(n) ?? []) visit(d);
|
|
6266
|
+
};
|
|
6267
|
+
for (const n of names) visit(n);
|
|
6268
|
+
const filt = (m, pc) => new Map([...m].filter(([k]) => keep.has(k) && winner.get(k) === pc));
|
|
6269
|
+
return pieces.map((pc) => ({ ...pc, keys: pc.keys.filter((k) => keep.has(k) && winner.get(k) === pc), ruleFns: filt(pc.ruleFns, pc), wrappers: filt(pc.wrappers, pc), deps: filt(pc.deps, pc) })).filter((pc) => pc.keys.length > 0);
|
|
6270
|
+
}
|
|
6132
6271
|
function fusedBody(pieces) {
|
|
6133
6272
|
const winner = /* @__PURE__ */ new Map();
|
|
6134
6273
|
for (const p of pieces) for (const k of p.keys) winner.set(k, p);
|
|
@@ -6148,7 +6287,7 @@ function fusedBody(pieces) {
|
|
|
6148
6287
|
...needsEmptyTl ? ["const _EMPTY_TL = Object.freeze([])"] : [],
|
|
6149
6288
|
...needsHostReads ? [HOST_READS_DECL] : [],
|
|
6150
6289
|
// Each contributing artifact's namespaced private prelude (regexes, _pf, …).
|
|
6151
|
-
...
|
|
6290
|
+
...new Set(contributingPieces.flatMap((p) => p.prelude)),
|
|
6152
6291
|
// The winning `_r_<Name>` function for each rule (one per name → no redeclare).
|
|
6153
6292
|
...[...winner].map(([k, p]) => p.ruleFns.get(k))
|
|
6154
6293
|
];
|
|
@@ -6189,9 +6328,9 @@ ${body}
|
|
|
6189
6328
|
function isIRPiece(p) {
|
|
6190
6329
|
return !!p && typeof p === "object" && typeof p.ir === "string" && typeof p.ns === "string" && !("ruleFns" in p);
|
|
6191
6330
|
}
|
|
6192
|
-
function materializePiece(p) {
|
|
6331
|
+
function materializePiece(p, trivia2) {
|
|
6193
6332
|
if (!isIRPiece(p)) return p;
|
|
6194
|
-
const pieces = compileLinkable(evalRuleMapIR(p.ir), p.ns);
|
|
6333
|
+
const pieces = compileLinkable(evalRuleMapIR(p.ir), p.ns, trivia2 ? { trivia: trivia2 } : void 0);
|
|
6195
6334
|
if (!pieces) throw new Error(`compose: carried IR for ns "${p.ns}" could not be re-lowered`);
|
|
6196
6335
|
return pieces;
|
|
6197
6336
|
}
|
|
@@ -6897,11 +7036,13 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
6897
7036
|
warn(init.start, `${label2}: rule map couldn't be inlined`);
|
|
6898
7037
|
return null;
|
|
6899
7038
|
}
|
|
6900
|
-
return { replacement: compiled.replacement, ruleMap };
|
|
7039
|
+
return { replacement: compiled.replacement, ruleMap, ...gTrivia ? { trivia: gTrivia } : {} };
|
|
6901
7040
|
};
|
|
6902
7041
|
const isRulesCall = (init) => init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "rules";
|
|
6903
7042
|
const isComposeCall = (init) => init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "compose";
|
|
7043
|
+
const isPickCall = (init) => init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "pick";
|
|
6904
7044
|
const localRuleMaps = /* @__PURE__ */ new Map();
|
|
7045
|
+
const localGrammarTrivia = /* @__PURE__ */ new Map();
|
|
6905
7046
|
const nsFor = (label2) => `_${(0, import_node_crypto.createHash)("sha1").update(`${id}#${label2}`).digest("hex").slice(0, 8)}_`;
|
|
6906
7047
|
const stripIndent = (s) => s.replace(/\n[ \t]+/g, "\n");
|
|
6907
7048
|
const serializePieces = (p) => {
|
|
@@ -6915,7 +7056,8 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
6915
7056
|
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);
|
|
6916
7057
|
const serializeList = (list) => `[${list.map(serializeItem).join(", ")}]`;
|
|
6917
7058
|
const withCarriedPieces = (grammarExpr, list) => `/* @__PURE__ */ Object.defineProperty(${grammarExpr}, Symbol.for('parseman.composedPieces'), { value: ${serializeList(list)}, enumerable: false })`;
|
|
6918
|
-
const
|
|
7059
|
+
const localComposedCarried = /* @__PURE__ */ new Map();
|
|
7060
|
+
const localComposedTrivia = /* @__PURE__ */ new Map();
|
|
6919
7061
|
const importedPiecesCache = /* @__PURE__ */ new Map();
|
|
6920
7062
|
const resolveModulePieces = (file, exportName, seen) => {
|
|
6921
7063
|
const mod = parseModuleCached(file);
|
|
@@ -6949,7 +7091,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
6949
7091
|
}
|
|
6950
7092
|
try {
|
|
6951
7093
|
const list = new Function(...stubNames, `return (${literal2})`)(...stubVals);
|
|
6952
|
-
return list
|
|
7094
|
+
return list;
|
|
6953
7095
|
} catch {
|
|
6954
7096
|
return null;
|
|
6955
7097
|
}
|
|
@@ -6969,32 +7111,108 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
6969
7111
|
importedPiecesCache.set(localName, result2);
|
|
6970
7112
|
return result2;
|
|
6971
7113
|
};
|
|
6972
|
-
const
|
|
7114
|
+
const materializeCarried = (items, composing) => {
|
|
7115
|
+
const out = [];
|
|
7116
|
+
for (const it of items) {
|
|
7117
|
+
if (isSpread(it)) {
|
|
7118
|
+
for (const p of importedPieces(it.__spreadLocal) ?? []) out.push(materializePiece(p, composing));
|
|
7119
|
+
} else if (isIR(it)) {
|
|
7120
|
+
out.push(materializePiece(it, composing));
|
|
7121
|
+
} else {
|
|
7122
|
+
out.push(it);
|
|
7123
|
+
}
|
|
7124
|
+
}
|
|
7125
|
+
return out;
|
|
7126
|
+
};
|
|
7127
|
+
const localCarried = (rm, label2, composing) => {
|
|
6973
7128
|
const entries = [...rm];
|
|
6974
7129
|
const ns = nsFor(label2);
|
|
6975
|
-
const p = compileLinkable(entries, ns);
|
|
6976
|
-
if (!p) return null;
|
|
6977
7130
|
const ir = serializeRuleMap(entries);
|
|
6978
|
-
|
|
7131
|
+
if (ir) return { carried: [{ ns, ir }] };
|
|
7132
|
+
const p = compileLinkable(entries, ns, composing ? { trivia: composing } : void 0);
|
|
7133
|
+
return p ? { carried: [p] } : null;
|
|
6979
7134
|
};
|
|
6980
|
-
const argPieces = (arg, label2) => {
|
|
7135
|
+
const argPieces = (arg, label2, composing) => {
|
|
7136
|
+
if (isPickCall(arg)) {
|
|
7137
|
+
const pargs = arg.arguments;
|
|
7138
|
+
const inner = pargs[0];
|
|
7139
|
+
const namesArg = pargs[1];
|
|
7140
|
+
if (!inner || namesArg?.type !== "ArrayExpression") return null;
|
|
7141
|
+
const names = [];
|
|
7142
|
+
for (const el of namesArg.elements ?? []) {
|
|
7143
|
+
const v2 = el?.value;
|
|
7144
|
+
if ((el?.type === "Literal" || el?.type === "StringLiteral") && typeof v2 === "string") names.push(v2);
|
|
7145
|
+
else return null;
|
|
7146
|
+
}
|
|
7147
|
+
const innerArg = argPieces(inner, `${label2}_pick`);
|
|
7148
|
+
if (!innerArg) return null;
|
|
7149
|
+
try {
|
|
7150
|
+
return { carried: pickPieces(materializeCarried(innerArg.carried, ownTrivia(inner)), names) };
|
|
7151
|
+
} catch (e) {
|
|
7152
|
+
warn(arg.start, `pick(): ${e.message}`);
|
|
7153
|
+
return null;
|
|
7154
|
+
}
|
|
7155
|
+
}
|
|
6981
7156
|
if (isRulesCall(arg)) {
|
|
6982
|
-
const
|
|
7157
|
+
const rulesArgs = arg.arguments;
|
|
7158
|
+
const a0 = rulesArgs[0];
|
|
7159
|
+
const a1 = rulesArgs[1];
|
|
7160
|
+
const optionsFirst = a0?.type === "ObjectExpression";
|
|
7161
|
+
const factory = optionsFirst ? a1 : a0;
|
|
6983
7162
|
const rm = factory ? evaluateParserFactory(factory, scope, code, []) : null;
|
|
6984
|
-
return rm ?
|
|
7163
|
+
return rm ? localCarried(rm, label2, composing) : null;
|
|
6985
7164
|
}
|
|
6986
7165
|
if (arg.type === "Identifier") {
|
|
6987
7166
|
const name = arg.name;
|
|
6988
7167
|
const rm = localRuleMaps.get(name);
|
|
6989
|
-
if (rm) return
|
|
6990
|
-
const composed =
|
|
6991
|
-
if (composed) return {
|
|
7168
|
+
if (rm) return localCarried(rm, label2, composing);
|
|
7169
|
+
const composed = localComposedCarried.get(name);
|
|
7170
|
+
if (composed) return { carried: composed };
|
|
6992
7171
|
const pieces = importedPieces(name);
|
|
6993
7172
|
if (!pieces) return null;
|
|
6994
|
-
return importBindings.has(name) ? {
|
|
7173
|
+
return { carried: importBindings.has(name) ? [{ __spreadLocal: name }] : [...pieces] };
|
|
6995
7174
|
}
|
|
6996
7175
|
return null;
|
|
6997
7176
|
};
|
|
7177
|
+
const rulesCallTrivia = (el) => {
|
|
7178
|
+
const rulesArgs = el.arguments;
|
|
7179
|
+
const a0 = rulesArgs[0];
|
|
7180
|
+
const a1 = rulesArgs[1];
|
|
7181
|
+
const optExpr = a0?.type === "ObjectExpression" ? a0 : a1?.type === "ObjectExpression" ? a1 : void 0;
|
|
7182
|
+
const triviaProp = (optExpr?.properties ?? []).find(
|
|
7183
|
+
(p) => p.key?.name === "trivia"
|
|
7184
|
+
);
|
|
7185
|
+
if (!triviaProp?.value) return void 0;
|
|
7186
|
+
return evaluateExpr(triviaProp.value, scope, code, []) ?? void 0;
|
|
7187
|
+
};
|
|
7188
|
+
const composingTrivia = (elements) => {
|
|
7189
|
+
for (let i = elements.length - 1; i >= 0; i--) {
|
|
7190
|
+
const el = elements[i];
|
|
7191
|
+
if (!el) continue;
|
|
7192
|
+
if (isRulesCall(el)) {
|
|
7193
|
+
const t = rulesCallTrivia(el);
|
|
7194
|
+
if (t) return t;
|
|
7195
|
+
continue;
|
|
7196
|
+
}
|
|
7197
|
+
if (el.type === "Identifier") {
|
|
7198
|
+
const t = localGrammarTrivia.get(el.name);
|
|
7199
|
+
if (t) return t;
|
|
7200
|
+
}
|
|
7201
|
+
}
|
|
7202
|
+
return void 0;
|
|
7203
|
+
};
|
|
7204
|
+
const ownTrivia = (arg) => {
|
|
7205
|
+
if (isRulesCall(arg)) return rulesCallTrivia(arg);
|
|
7206
|
+
if (isPickCall(arg)) {
|
|
7207
|
+
const inner = arg.arguments[0];
|
|
7208
|
+
return inner ? ownTrivia(inner) : void 0;
|
|
7209
|
+
}
|
|
7210
|
+
if (arg.type === "Identifier") {
|
|
7211
|
+
const name = arg.name;
|
|
7212
|
+
return localGrammarTrivia.get(name) ?? localComposedTrivia.get(name);
|
|
7213
|
+
}
|
|
7214
|
+
return void 0;
|
|
7215
|
+
};
|
|
6998
7216
|
const compileComposeCall = (init) => {
|
|
6999
7217
|
const args = init.arguments;
|
|
7000
7218
|
const arr = args[0];
|
|
@@ -7003,21 +7221,19 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7003
7221
|
return null;
|
|
7004
7222
|
}
|
|
7005
7223
|
const elements = arr.elements;
|
|
7006
|
-
const
|
|
7224
|
+
const composing = composingTrivia(elements);
|
|
7007
7225
|
const carried = [];
|
|
7008
7226
|
for (let i = 0; i < elements.length; i++) {
|
|
7009
|
-
const r = argPieces(elements[i], `compose${init.start}_${i}
|
|
7227
|
+
const r = argPieces(elements[i], `compose${init.start}_${i}`, composing);
|
|
7010
7228
|
if (!r) {
|
|
7011
7229
|
warn(init.start, `compose(): argument ${i} isn't a build-resolvable grammar; falling back to runtime`);
|
|
7012
7230
|
return null;
|
|
7013
7231
|
}
|
|
7014
|
-
|
|
7015
|
-
if (r.spreadLocal) carried.push({ __spreadLocal: r.spreadLocal });
|
|
7016
|
-
else if (r.ir) carried.push(r.ir);
|
|
7017
|
-
else carried.push(...r.pieces);
|
|
7232
|
+
carried.push(...r.carried);
|
|
7018
7233
|
}
|
|
7234
|
+
const pieces = materializeCarried(carried, composing);
|
|
7019
7235
|
try {
|
|
7020
|
-
return { replacement: emitFusedSource(pieces),
|
|
7236
|
+
return { replacement: emitFusedSource(pieces), carried, ...composing ? { trivia: composing } : {} };
|
|
7021
7237
|
} catch (e) {
|
|
7022
7238
|
warn(init.start, `compose(): ${e.message}; falling back to runtime`);
|
|
7023
7239
|
return null;
|
|
@@ -7102,6 +7318,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7102
7318
|
const compiledRules = compileRulesFactory(init, varName);
|
|
7103
7319
|
if (!compiledRules) continue;
|
|
7104
7320
|
localRuleMaps.set(varName, compiledRules.ruleMap);
|
|
7321
|
+
if (compiledRules.trivia) localGrammarTrivia.set(varName, compiledRules.trivia);
|
|
7105
7322
|
let replacement = compiledRules.replacement;
|
|
7106
7323
|
if (exportPrefix) {
|
|
7107
7324
|
const ns = nsFor(varName);
|
|
@@ -7117,7 +7334,8 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
7117
7334
|
if (isComposeCall(init)) {
|
|
7118
7335
|
const fused = compileComposeCall(init);
|
|
7119
7336
|
if (!fused) continue;
|
|
7120
|
-
|
|
7337
|
+
localComposedCarried.set(varName, fused.carried);
|
|
7338
|
+
if (fused.trivia) localComposedTrivia.set(varName, fused.trivia);
|
|
7121
7339
|
const replacement = exportPrefix ? withCarriedPieces(fused.replacement, fused.carried) : fused.replacement;
|
|
7122
7340
|
replacements.push({ start: init.start, end: init.end, replacement });
|
|
7123
7341
|
continue;
|