parseman 0.18.1 → 0.19.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 +7 -3
- package/dist/combinators/choice.d.ts.map +1 -1
- package/dist/combinators/literal.d.ts.map +1 -1
- package/dist/combinators/map.d.ts +5 -0
- package/dist/combinators/map.d.ts.map +1 -1
- package/dist/combinators/node.d.ts +14 -13
- package/dist/combinators/node.d.ts.map +1 -1
- package/dist/combinators/parser.d.ts.map +1 -1
- package/dist/combinators/ref.d.ts.map +1 -1
- package/dist/combinators/regex.d.ts.map +1 -1
- package/dist/combinators/repeat.d.ts.map +1 -1
- package/dist/combinators/trivia-skip.d.ts +1 -0
- package/dist/combinators/trivia-skip.d.ts.map +1 -1
- package/dist/compiler/build-arity.d.ts +3 -3
- package/dist/compiler/codegen.d.ts.map +1 -1
- package/dist/compiler/fields.d.ts +16 -0
- package/dist/compiler/fields.d.ts.map +1 -0
- package/dist/compiler/inline-build.d.ts.map +1 -1
- package/dist/compiler/ir-serialize.d.ts.map +1 -1
- package/dist/compiler/linker.d.ts +17 -3
- package/dist/compiler/linker.d.ts.map +1 -1
- package/dist/compiler/value-usage.d.ts.map +1 -1
- package/dist/cst/capture-buffer.d.ts +1 -0
- package/dist/cst/capture-buffer.d.ts.map +1 -1
- package/dist/index.cjs +498 -78
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +498 -78
- package/dist/index.js.map +4 -4
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.cjs +498 -86
- package/dist/plugin/index.cjs.map +4 -4
- package/dist/plugin/index.js +498 -86
- package/dist/plugin/index.js.map +4 -4
- package/dist/types.d.ts +31 -8
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -1
package/dist/index.js
CHANGED
|
@@ -252,7 +252,8 @@ function saveCstMark(ctx) {
|
|
|
252
252
|
return {
|
|
253
253
|
raw: cstRawLen(ctx),
|
|
254
254
|
tlog: cstTlLen(ctx),
|
|
255
|
-
leaves: cstLeavesLen(ctx)
|
|
255
|
+
leaves: cstLeavesLen(ctx),
|
|
256
|
+
fields: ctx._fields?.length ?? 0
|
|
256
257
|
};
|
|
257
258
|
}
|
|
258
259
|
function rollbackBufList(b, keyMulti, keySingle, len) {
|
|
@@ -276,11 +277,13 @@ function rollbackCstCapture(ctx, mark) {
|
|
|
276
277
|
if (mark.tlog === 0) b.tl = void 0;
|
|
277
278
|
else b.tl.length = mark.tlog;
|
|
278
279
|
}
|
|
280
|
+
if (ctx._fields) ctx._fields.length = mark.fields;
|
|
279
281
|
return;
|
|
280
282
|
}
|
|
281
283
|
if (ctx._cstRawChildren) ctx._cstRawChildren.length = mark.raw;
|
|
282
284
|
if (ctx._cstTriviaLog) ctx._cstTriviaLog.length = mark.tlog;
|
|
283
285
|
if (ctx._cstLeaves) ctx._cstLeaves.length = mark.leaves;
|
|
286
|
+
if (ctx._fields) ctx._fields.length = mark.fields;
|
|
284
287
|
}
|
|
285
288
|
function pushCstTriviaEntry(ctx, start, end, kindIndex) {
|
|
286
289
|
const insertIdx = cstRawLen(ctx);
|
|
@@ -349,13 +352,12 @@ function literal(value, opts = {}) {
|
|
|
349
352
|
if (end > input.length) {
|
|
350
353
|
return failAt(ctx, [JSON.stringify(value)], pos);
|
|
351
354
|
}
|
|
352
|
-
const
|
|
353
|
-
|
|
354
|
-
if (matched) {
|
|
355
|
+
const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
|
|
356
|
+
if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
|
|
355
357
|
const span = { start: pos, end };
|
|
356
|
-
const leaf = { _tag: "leaf", value:
|
|
358
|
+
const leaf = { _tag: "leaf", value: matchedValue, span };
|
|
357
359
|
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
|
|
358
|
-
return { ok: true, value:
|
|
360
|
+
return { ok: true, value: matchedValue, span };
|
|
359
361
|
}
|
|
360
362
|
return failAt(ctx, [JSON.stringify(value)], pos);
|
|
361
363
|
}
|
|
@@ -368,10 +370,102 @@ function registerRegexAnalyzer(analyzer) {
|
|
|
368
370
|
firstSetAnalyzer = analyzer;
|
|
369
371
|
}
|
|
370
372
|
var permissiveFirstSet = () => ({ firstSet: any(), canMatchNewline: true });
|
|
373
|
+
var SCAN_BAIL_AT = 64;
|
|
374
|
+
var SPACE_RANGES = [
|
|
375
|
+
[9, 13],
|
|
376
|
+
[32, 32],
|
|
377
|
+
[160, 160],
|
|
378
|
+
[5760, 5760],
|
|
379
|
+
[8192, 8202],
|
|
380
|
+
[8232, 8233],
|
|
381
|
+
[8239, 8239],
|
|
382
|
+
[8287, 8287],
|
|
383
|
+
[12288, 12288],
|
|
384
|
+
[65279, 65279]
|
|
385
|
+
];
|
|
386
|
+
var CLASS_ESCAPES = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
387
|
+
function shorthandRanges(ch) {
|
|
388
|
+
if (ch === "d") return [[48, 57]];
|
|
389
|
+
if (ch === "s") return SPACE_RANGES;
|
|
390
|
+
return [[48, 57], [65, 90], [97, 122], [95, 95]];
|
|
391
|
+
}
|
|
392
|
+
function inRanges(cp, ranges) {
|
|
393
|
+
for (let i = 0; i < ranges.length; i++) {
|
|
394
|
+
const [lo, hi] = ranges[i];
|
|
395
|
+
if (cp >= lo && cp <= hi) return true;
|
|
396
|
+
}
|
|
397
|
+
return false;
|
|
398
|
+
}
|
|
399
|
+
function readClassRanges(body) {
|
|
400
|
+
if (body.startsWith("^")) return null;
|
|
401
|
+
const ranges = [];
|
|
402
|
+
let i = 0;
|
|
403
|
+
const readAtom = () => {
|
|
404
|
+
const ch = body[i];
|
|
405
|
+
if (ch === void 0) return null;
|
|
406
|
+
if (ch === "\\") {
|
|
407
|
+
const esc = body[i + 1];
|
|
408
|
+
if (esc === void 0) return null;
|
|
409
|
+
i += 2;
|
|
410
|
+
if (esc === "d" || esc === "w" || esc === "s") return { ranges: shorthandRanges(esc) };
|
|
411
|
+
if (esc in CLASS_ESCAPES) return { cp: CLASS_ESCAPES[esc] };
|
|
412
|
+
if (esc >= "a" && esc <= "z" || esc >= "A" && esc <= "Z") return null;
|
|
413
|
+
return { cp: esc.charCodeAt(0) };
|
|
414
|
+
}
|
|
415
|
+
i++;
|
|
416
|
+
return { cp: ch.charCodeAt(0) };
|
|
417
|
+
};
|
|
418
|
+
while (i < body.length) {
|
|
419
|
+
const lo = readAtom();
|
|
420
|
+
if (!lo) return null;
|
|
421
|
+
if ("ranges" in lo) {
|
|
422
|
+
ranges.push(...lo.ranges);
|
|
423
|
+
continue;
|
|
424
|
+
}
|
|
425
|
+
if (body[i] === "-" && body[i + 1] !== void 0 && body[i + 1] !== "]") {
|
|
426
|
+
i++;
|
|
427
|
+
const hi = readAtom();
|
|
428
|
+
if (!hi || "ranges" in hi) return null;
|
|
429
|
+
ranges.push([lo.cp, hi.cp]);
|
|
430
|
+
} else {
|
|
431
|
+
ranges.push([lo.cp, lo.cp]);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
return ranges.length ? ranges : null;
|
|
435
|
+
}
|
|
436
|
+
function shortScanner(source, flags) {
|
|
437
|
+
if (/[imsuvy]/.test(flags)) return null;
|
|
438
|
+
let ranges = null;
|
|
439
|
+
let quant = "";
|
|
440
|
+
if (source[0] === "[") {
|
|
441
|
+
let end = 1;
|
|
442
|
+
while (end < source.length && source[end] !== "]") {
|
|
443
|
+
if (source[end] === "\\") end += 2;
|
|
444
|
+
else end++;
|
|
445
|
+
}
|
|
446
|
+
if (source[end] !== "]") return null;
|
|
447
|
+
ranges = readClassRanges(source.slice(1, end));
|
|
448
|
+
quant = source.slice(end + 1);
|
|
449
|
+
} else if (source[0] === "\\" && (source[1] === "d" || source[1] === "w" || source[1] === "s")) {
|
|
450
|
+
ranges = shorthandRanges(source[1]);
|
|
451
|
+
quant = source.slice(2);
|
|
452
|
+
}
|
|
453
|
+
if (!ranges || quant !== "+" && quant !== "*") return null;
|
|
454
|
+
const minOne = quant === "+";
|
|
455
|
+
return (input, pos) => {
|
|
456
|
+
let end = pos;
|
|
457
|
+
while (end < input.length && inRanges(input.charCodeAt(end), ranges)) {
|
|
458
|
+
end++;
|
|
459
|
+
if (end - pos >= SCAN_BAIL_AT) return void 0;
|
|
460
|
+
}
|
|
461
|
+
return minOne && end === pos ? null : end;
|
|
462
|
+
};
|
|
463
|
+
}
|
|
371
464
|
function regex(pattern, flags = "") {
|
|
372
465
|
const source = typeof pattern === "string" ? pattern : pattern.source;
|
|
373
466
|
const resolvedFlags = typeof pattern === "string" ? flags : pattern.flags;
|
|
374
467
|
const anchored = new RegExp(source, "y" + resolvedFlags.replace(/[gy]/g, ""));
|
|
468
|
+
const scan = shortScanner(source, resolvedFlags);
|
|
375
469
|
const { firstSet, canMatchNewline } = (firstSetAnalyzer ?? permissiveFirstSet)(source);
|
|
376
470
|
const meta = { firstSet, canMatchNewline, isTrivia: false };
|
|
377
471
|
return {
|
|
@@ -379,6 +473,15 @@ function regex(pattern, flags = "") {
|
|
|
379
473
|
_meta: meta,
|
|
380
474
|
_def: { tag: "regex", source, flags: resolvedFlags },
|
|
381
475
|
parse(input, pos, ctx) {
|
|
476
|
+
const scanEnd = scan?.(input, pos);
|
|
477
|
+
if (scanEnd !== void 0) {
|
|
478
|
+
if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
|
|
479
|
+
const value = input.slice(pos, scanEnd);
|
|
480
|
+
const span2 = { start: pos, end: scanEnd };
|
|
481
|
+
const leaf2 = { _tag: "leaf", value, span: span2 };
|
|
482
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf2);
|
|
483
|
+
return { ok: true, value, span: span2 };
|
|
484
|
+
}
|
|
382
485
|
anchored.lastIndex = pos;
|
|
383
486
|
const m = anchored.exec(input);
|
|
384
487
|
if (m === null) {
|
|
@@ -562,13 +665,10 @@ function choice(...args) {
|
|
|
562
665
|
};
|
|
563
666
|
const strategy = disjoint || hasGates ? null : detectStrategy(parsers);
|
|
564
667
|
const autoNot = !disjoint && !hasGates && strategy?.tag === "firstMatch" ? computeAutoNot(parsers) : parsers.map(() => null);
|
|
565
|
-
let greedyRe = null;
|
|
566
668
|
let greedyLitMap = null;
|
|
567
669
|
let sortedParsers = null;
|
|
670
|
+
const asciiDispatch = disjoint ? buildAsciiDispatch(parsers) : null;
|
|
568
671
|
if (strategy?.tag === "greedyClassify") {
|
|
569
|
-
const regexDef = getCoreRegexDef(parsers[strategy.superIndex]);
|
|
570
|
-
const flags = "y" + regexDef.flags.replace(/[gy]/g, "");
|
|
571
|
-
greedyRe = new RegExp(regexDef.source, flags);
|
|
572
672
|
greedyLitMap = /* @__PURE__ */ new Map();
|
|
573
673
|
for (let i = 0; i < parsers.length; i++) {
|
|
574
674
|
if (i === strategy.superIndex) continue;
|
|
@@ -593,14 +693,21 @@ function choice(...args) {
|
|
|
593
693
|
const expected = [];
|
|
594
694
|
if (disjoint && pos < input.length) {
|
|
595
695
|
const code = input.codePointAt(pos);
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
if (
|
|
600
|
-
|
|
601
|
-
|
|
696
|
+
let parser2 = code < 128 ? asciiDispatch?.[code] ?? null : null;
|
|
697
|
+
if (!parser2) {
|
|
698
|
+
for (const p of parsers) {
|
|
699
|
+
if (inFirstSet(code, p._meta.firstSet)) {
|
|
700
|
+
parser2 = p;
|
|
701
|
+
break;
|
|
702
|
+
}
|
|
602
703
|
}
|
|
603
704
|
}
|
|
705
|
+
if (parser2) {
|
|
706
|
+
const result = parser2.parse(input, pos, ctx);
|
|
707
|
+
if (result.ok) return result;
|
|
708
|
+
expected.push(...result.expected);
|
|
709
|
+
return { ok: false, expected, span: { start: pos, end: pos } };
|
|
710
|
+
}
|
|
604
711
|
return {
|
|
605
712
|
ok: false,
|
|
606
713
|
expected: parsers.flatMap((p) => {
|
|
@@ -776,6 +883,19 @@ function areDisjoint(sets) {
|
|
|
776
883
|
if (intersects(sets[i], sets[j])) return false;
|
|
777
884
|
return true;
|
|
778
885
|
}
|
|
886
|
+
function buildAsciiDispatch(parsers) {
|
|
887
|
+
const table = Array(128).fill(null);
|
|
888
|
+
for (const parser2 of parsers) {
|
|
889
|
+
const fs = parser2._meta.firstSet;
|
|
890
|
+
if (fs.kind !== "ranges") continue;
|
|
891
|
+
for (const { lo, hi } of fs.ranges) {
|
|
892
|
+
for (let code = Math.max(0, lo); code <= Math.min(127, hi); code++) {
|
|
893
|
+
table[code] = parser2;
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
return table;
|
|
898
|
+
}
|
|
779
899
|
|
|
780
900
|
// src/cst/trivia-kinds.ts
|
|
781
901
|
function unwrapTrivia(p) {
|
|
@@ -897,15 +1017,16 @@ function recordTriviaChunks(ctx, chunks) {
|
|
|
897
1017
|
// src/combinators/trivia-skip.ts
|
|
898
1018
|
var NOOP_COMMIT = () => {
|
|
899
1019
|
};
|
|
1020
|
+
var fastTriviaCache = /* @__PURE__ */ new WeakMap();
|
|
900
1021
|
function needsDeferredTriviaCommit(ctx) {
|
|
901
1022
|
return ctx._triviaLog !== void 0 || ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0;
|
|
902
1023
|
}
|
|
903
1024
|
function saveTriviaMark(ctx) {
|
|
904
1025
|
const m = saveCstMark(ctx);
|
|
905
|
-
return { raw: m.raw, tlog: m.tlog, leaves: m.leaves, log: ctx._triviaLog ? ctx._triviaLog.length : 0 };
|
|
1026
|
+
return { raw: m.raw, tlog: m.tlog, leaves: m.leaves, fields: m.fields, log: ctx._triviaLog ? ctx._triviaLog.length : 0 };
|
|
906
1027
|
}
|
|
907
1028
|
function rollbackTrivia(ctx, mark) {
|
|
908
|
-
rollbackCstCapture(ctx, { raw: mark.raw, tlog: mark.tlog, leaves: mark.leaves });
|
|
1029
|
+
rollbackCstCapture(ctx, { raw: mark.raw, tlog: mark.tlog, leaves: mark.leaves, fields: mark.fields });
|
|
909
1030
|
if (ctx._triviaLog) ctx._triviaLog.length = mark.log;
|
|
910
1031
|
}
|
|
911
1032
|
function scanWithLabels(input, cur, ctx) {
|
|
@@ -923,6 +1044,8 @@ function scanWithLabels(input, cur, ctx) {
|
|
|
923
1044
|
function advanceTrivia(input, cur, ctx) {
|
|
924
1045
|
const triviaP = ctx.trivia;
|
|
925
1046
|
if (!triviaP) return cur;
|
|
1047
|
+
const fast = fastTriviaScanner(triviaP);
|
|
1048
|
+
if (fast) return fast(input, cur);
|
|
926
1049
|
if (ctx.triviaKindLabels) {
|
|
927
1050
|
const scan = scanWithLabels(input, cur, ctx);
|
|
928
1051
|
return scan.end;
|
|
@@ -935,6 +1058,10 @@ function scanTrivia(input, cur, ctx) {
|
|
|
935
1058
|
if (!triviaP) return { end: cur, commit: NOOP_COMMIT };
|
|
936
1059
|
const log = ctx._triviaLog;
|
|
937
1060
|
const captureTl = ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0);
|
|
1061
|
+
const fast = !ctx.triviaKindLabels ? fastTriviaScanner(triviaP) : null;
|
|
1062
|
+
if (fast && log === void 0 && !captureTl) {
|
|
1063
|
+
return { end: fast(input, cur), commit: NOOP_COMMIT };
|
|
1064
|
+
}
|
|
938
1065
|
if (ctx.triviaKindLabels && (log !== void 0 || captureTl)) {
|
|
939
1066
|
return scanWithLabels(input, cur, ctx);
|
|
940
1067
|
}
|
|
@@ -956,6 +1083,79 @@ function scanTrivia(input, cur, ctx) {
|
|
|
956
1083
|
const tr = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
|
|
957
1084
|
return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
|
|
958
1085
|
}
|
|
1086
|
+
function fastTriviaScanner(trivia2) {
|
|
1087
|
+
const cached = fastTriviaCache.get(trivia2);
|
|
1088
|
+
if (cached !== void 0) return cached;
|
|
1089
|
+
const scanner = buildFastTriviaScanner(trivia2);
|
|
1090
|
+
fastTriviaCache.set(trivia2, scanner);
|
|
1091
|
+
return scanner;
|
|
1092
|
+
}
|
|
1093
|
+
function buildFastTriviaScanner(trivia2) {
|
|
1094
|
+
const core = trivia2._def.tag === "trivia" ? trivia2._def.parser : trivia2;
|
|
1095
|
+
const direct = regexTriviaScanner(core);
|
|
1096
|
+
if (direct) return direct;
|
|
1097
|
+
const repeat = core._def.tag === "oneOrMore" || core._def.tag === "many" && core._def.min >= 1 ? core._def.parser : null;
|
|
1098
|
+
if (!repeat) return null;
|
|
1099
|
+
const one = regexTriviaScanner(repeat);
|
|
1100
|
+
if (one) return loopScanner([one]);
|
|
1101
|
+
if (repeat._def.tag !== "choice") return null;
|
|
1102
|
+
const arms = repeat._def.parsers.map(regexTriviaScanner);
|
|
1103
|
+
if (arms.some((s) => s === null)) return null;
|
|
1104
|
+
return loopScanner(arms);
|
|
1105
|
+
}
|
|
1106
|
+
function loopScanner(arms) {
|
|
1107
|
+
return (input, cur) => {
|
|
1108
|
+
let pos = cur;
|
|
1109
|
+
scan: while (pos < input.length) {
|
|
1110
|
+
for (const arm of arms) {
|
|
1111
|
+
const end = arm(input, pos);
|
|
1112
|
+
if (end > pos) {
|
|
1113
|
+
pos = end;
|
|
1114
|
+
continue scan;
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
break;
|
|
1118
|
+
}
|
|
1119
|
+
return pos;
|
|
1120
|
+
};
|
|
1121
|
+
}
|
|
1122
|
+
function regexTriviaScanner(parser2) {
|
|
1123
|
+
if (parser2._def.tag !== "regex" || parser2._def.flags) return null;
|
|
1124
|
+
const ws = whitespaceSource(parser2._def.source);
|
|
1125
|
+
if (ws) return ws;
|
|
1126
|
+
return blockCommentSource(parser2._def.source) ? scanBlockComment : null;
|
|
1127
|
+
}
|
|
1128
|
+
function whitespaceSource(source) {
|
|
1129
|
+
const m = /^\[([ \\tnrf]+)\][*+]$/.exec(source);
|
|
1130
|
+
if (!m) return null;
|
|
1131
|
+
const chars = /* @__PURE__ */ new Set();
|
|
1132
|
+
for (let i = 0; i < m[1].length; i++) {
|
|
1133
|
+
const ch = m[1][i];
|
|
1134
|
+
if (ch !== "\\") {
|
|
1135
|
+
chars.add(ch.charCodeAt(0));
|
|
1136
|
+
continue;
|
|
1137
|
+
}
|
|
1138
|
+
const esc = m[1][++i];
|
|
1139
|
+
if (esc === "t") chars.add(9);
|
|
1140
|
+
else if (esc === "n") chars.add(10);
|
|
1141
|
+
else if (esc === "r") chars.add(13);
|
|
1142
|
+
else if (esc === "f") chars.add(12);
|
|
1143
|
+
else return null;
|
|
1144
|
+
}
|
|
1145
|
+
return (input, cur) => {
|
|
1146
|
+
let pos = cur;
|
|
1147
|
+
while (pos < input.length && chars.has(input.charCodeAt(pos))) pos++;
|
|
1148
|
+
return pos;
|
|
1149
|
+
};
|
|
1150
|
+
}
|
|
1151
|
+
function blockCommentSource(source) {
|
|
1152
|
+
return source === "\\/\\*(?:[^*]|\\*(?!\\/))*\\*\\/" || source === "\\/\\*[^]*?\\*\\/";
|
|
1153
|
+
}
|
|
1154
|
+
function scanBlockComment(input, cur) {
|
|
1155
|
+
if (input.charCodeAt(cur) !== 47 || input.charCodeAt(cur + 1) !== 42) return cur;
|
|
1156
|
+
const close = input.indexOf("*/", cur + 2);
|
|
1157
|
+
return close === -1 ? cur : close + 2;
|
|
1158
|
+
}
|
|
959
1159
|
|
|
960
1160
|
// src/combinators/sequence.ts
|
|
961
1161
|
function sequence(...parsers) {
|
|
@@ -1094,11 +1294,15 @@ function optional(combinator) {
|
|
|
1094
1294
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
1095
1295
|
isTrivia: false
|
|
1096
1296
|
};
|
|
1297
|
+
const firstSetSkippable = !matchesEmpty(combinator);
|
|
1097
1298
|
return {
|
|
1098
1299
|
_tag: "optional",
|
|
1099
1300
|
_meta: meta,
|
|
1100
1301
|
_def: { tag: "optional", parser: combinator },
|
|
1101
1302
|
parse(input, pos, ctx) {
|
|
1303
|
+
if (firstSetSkippable && ctx._probe === void 0 && !startsFirstSet(combinator, input, pos)) {
|
|
1304
|
+
return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
1305
|
+
}
|
|
1102
1306
|
const mark = saveTriviaMark(ctx);
|
|
1103
1307
|
const result = combinator.parse(input, pos, ctx);
|
|
1104
1308
|
if (result.ok) return result;
|
|
@@ -1107,6 +1311,15 @@ function optional(combinator) {
|
|
|
1107
1311
|
}
|
|
1108
1312
|
};
|
|
1109
1313
|
}
|
|
1314
|
+
function startsFirstSet(combinator, input, pos) {
|
|
1315
|
+
const fs = combinator._meta.firstSet;
|
|
1316
|
+
if (fs.kind === "any") return true;
|
|
1317
|
+
if (fs.kind === "empty") return false;
|
|
1318
|
+
const code = input.codePointAt(pos);
|
|
1319
|
+
if (code === void 0) return false;
|
|
1320
|
+
for (const r of fs.ranges) if (code >= r.lo && code <= r.hi) return true;
|
|
1321
|
+
return false;
|
|
1322
|
+
}
|
|
1110
1323
|
function sepBy(combinator, separator) {
|
|
1111
1324
|
const meta = {
|
|
1112
1325
|
firstSet: combinator._meta.firstSet,
|
|
@@ -1187,6 +1400,13 @@ function ref() {
|
|
|
1187
1400
|
define(p) {
|
|
1188
1401
|
if (resolved) throw new Error("ref<T>() already defined");
|
|
1189
1402
|
resolved = p;
|
|
1403
|
+
meta.firstSet = p._meta.firstSet;
|
|
1404
|
+
meta.canMatchNewline = p._meta.canMatchNewline;
|
|
1405
|
+
meta.isTrivia = p._meta.isTrivia;
|
|
1406
|
+
if (p._meta.triviaKindLabels !== void 0) meta.triviaKindLabels = p._meta.triviaKindLabels;
|
|
1407
|
+
else delete meta.triviaKindLabels;
|
|
1408
|
+
if (p._meta.disjoint !== void 0) meta.disjoint = p._meta.disjoint;
|
|
1409
|
+
else delete meta.disjoint;
|
|
1190
1410
|
}
|
|
1191
1411
|
};
|
|
1192
1412
|
return slot;
|
|
@@ -1227,6 +1447,9 @@ function markUnusedValues(root) {
|
|
|
1227
1447
|
case "transform":
|
|
1228
1448
|
visit(def.parser, true);
|
|
1229
1449
|
return;
|
|
1450
|
+
case "field":
|
|
1451
|
+
visit(def.parser, true);
|
|
1452
|
+
return;
|
|
1230
1453
|
case "skip":
|
|
1231
1454
|
visit(def.main, consumed);
|
|
1232
1455
|
visit(def.skipped, false);
|
|
@@ -1278,6 +1501,11 @@ function markUnusedValues(root) {
|
|
|
1278
1501
|
}
|
|
1279
1502
|
|
|
1280
1503
|
// src/combinators/parser.ts
|
|
1504
|
+
function tagRule(r, key) {
|
|
1505
|
+
;
|
|
1506
|
+
r._ruleName = key;
|
|
1507
|
+
if (r._def.tag === "node" && r._def.type === void 0) r._def.type = key;
|
|
1508
|
+
}
|
|
1281
1509
|
function rules(factory) {
|
|
1282
1510
|
const cache = {};
|
|
1283
1511
|
const proxy = new Proxy(cache, {
|
|
@@ -1286,7 +1514,7 @@ function rules(factory) {
|
|
|
1286
1514
|
const record = target;
|
|
1287
1515
|
if (!(key in record)) {
|
|
1288
1516
|
const r = ref();
|
|
1289
|
-
r
|
|
1517
|
+
tagRule(r, key);
|
|
1290
1518
|
record[key] = r;
|
|
1291
1519
|
}
|
|
1292
1520
|
return record[key];
|
|
@@ -1297,12 +1525,12 @@ function rules(factory) {
|
|
|
1297
1525
|
const placeholder = cache[key];
|
|
1298
1526
|
const parser2 = definitions[key];
|
|
1299
1527
|
if (placeholder !== void 0 && typeof placeholder.define === "function") {
|
|
1300
|
-
;
|
|
1528
|
+
tagRule(parser2, key);
|
|
1301
1529
|
placeholder.define(parser2);
|
|
1302
1530
|
placeholder._meta.firstSet = parser2._meta.firstSet;
|
|
1303
1531
|
placeholder._meta.canMatchNewline = parser2._meta.canMatchNewline;
|
|
1304
1532
|
} else {
|
|
1305
|
-
;
|
|
1533
|
+
tagRule(parser2, key);
|
|
1306
1534
|
cache[key] = parser2;
|
|
1307
1535
|
}
|
|
1308
1536
|
}
|
|
@@ -1359,44 +1587,130 @@ function buildReadsTrivia(def) {
|
|
|
1359
1587
|
const src = def.buildSrc ?? def.build.toString();
|
|
1360
1588
|
const arity = confirmedBuildArity(src);
|
|
1361
1589
|
if (arity === null) return true;
|
|
1362
|
-
return arity >=
|
|
1590
|
+
return arity >= 5;
|
|
1363
1591
|
}
|
|
1364
1592
|
function buildReadsState(def) {
|
|
1365
1593
|
if (!def.build) return true;
|
|
1366
1594
|
const src = def.buildSrc ?? def.build.toString();
|
|
1367
1595
|
const arity = confirmedBuildArity(src);
|
|
1368
1596
|
if (arity === null) return true;
|
|
1369
|
-
return arity >=
|
|
1597
|
+
return arity >= 6;
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1600
|
+
// src/compiler/fields.ts
|
|
1601
|
+
function buildReadsFields(def) {
|
|
1602
|
+
if (!def.build) return true;
|
|
1603
|
+
const src = def.buildSrc ?? def.build.toString();
|
|
1604
|
+
const arity = confirmedBuildArity(src);
|
|
1605
|
+
if (arity === null) return true;
|
|
1606
|
+
return arity >= 2;
|
|
1607
|
+
}
|
|
1608
|
+
function parserHasOwnFields(p, seen = /* @__PURE__ */ new Set()) {
|
|
1609
|
+
if (seen.has(p)) return false;
|
|
1610
|
+
seen.add(p);
|
|
1611
|
+
const d = p._def;
|
|
1612
|
+
switch (d.tag) {
|
|
1613
|
+
case "field":
|
|
1614
|
+
return true;
|
|
1615
|
+
case "node":
|
|
1616
|
+
return false;
|
|
1617
|
+
case "lazy": {
|
|
1618
|
+
try {
|
|
1619
|
+
return parserHasOwnFields(d.thunk(), seen);
|
|
1620
|
+
} catch {
|
|
1621
|
+
return false;
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
case "sequence":
|
|
1625
|
+
case "choice":
|
|
1626
|
+
return d.parsers.some((x) => parserHasOwnFields(x, seen));
|
|
1627
|
+
case "sepBy":
|
|
1628
|
+
return parserHasOwnFields(d.parser, seen) || parserHasOwnFields(d.separator, seen);
|
|
1629
|
+
case "skip":
|
|
1630
|
+
return parserHasOwnFields(d.main, seen) || parserHasOwnFields(d.skipped, seen);
|
|
1631
|
+
case "grammar":
|
|
1632
|
+
return parserHasOwnFields(d.parser, seen) || (d.triviaParser ? parserHasOwnFields(d.triviaParser, seen) : false);
|
|
1633
|
+
case "scanTo":
|
|
1634
|
+
return parserHasOwnFields(d.sentinel, seen) || d.skip.some((x) => parserHasOwnFields(x, seen));
|
|
1635
|
+
case "recover":
|
|
1636
|
+
return parserHasOwnFields(d.parser, seen) || parserHasOwnFields(d.sentinel, seen);
|
|
1637
|
+
case "many":
|
|
1638
|
+
case "oneOrMore":
|
|
1639
|
+
case "optional":
|
|
1640
|
+
case "transform":
|
|
1641
|
+
case "trivia":
|
|
1642
|
+
case "token":
|
|
1643
|
+
case "label":
|
|
1644
|
+
case "expect":
|
|
1645
|
+
case "withCtx":
|
|
1646
|
+
case "not":
|
|
1647
|
+
return parserHasOwnFields(d.parser, seen);
|
|
1648
|
+
default:
|
|
1649
|
+
return false;
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
function buildFieldMap(captures) {
|
|
1653
|
+
if (!captures?.length) return void 0;
|
|
1654
|
+
const out = {};
|
|
1655
|
+
for (const cap of captures) {
|
|
1656
|
+
const entry = { value: cap.value, span: cap.span };
|
|
1657
|
+
const current = out[cap.name];
|
|
1658
|
+
if (current === void 0) out[cap.name] = entry;
|
|
1659
|
+
else if (Array.isArray(current)) current.push(entry);
|
|
1660
|
+
else out[cap.name] = [current, entry];
|
|
1661
|
+
}
|
|
1662
|
+
return out;
|
|
1370
1663
|
}
|
|
1371
1664
|
|
|
1372
1665
|
// src/combinators/node.ts
|
|
1373
|
-
function
|
|
1666
|
+
function unwrapChild(child) {
|
|
1374
1667
|
return child !== null && typeof child === "object" && child._tag === "leaf" ? child.value : child;
|
|
1375
1668
|
}
|
|
1376
|
-
function
|
|
1669
|
+
function isCstChild(value) {
|
|
1670
|
+
return typeof value === "object" && value !== null && (value._tag === "node" || value._tag === "leaf" || value._tag === "error");
|
|
1671
|
+
}
|
|
1672
|
+
function missingInferredType() {
|
|
1673
|
+
throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
|
|
1674
|
+
}
|
|
1675
|
+
function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
1676
|
+
const hasExplicitType = typeof typeOrCombinator === "string";
|
|
1677
|
+
const type = hasExplicitType ? typeOrCombinator : void 0;
|
|
1678
|
+
const combinator = hasExplicitType ? combinatorOrBuild : typeOrCombinator;
|
|
1679
|
+
const build = hasExplicitType ? buildOrOpts : combinatorOrBuild;
|
|
1680
|
+
const opts = hasExplicitType ? maybeOpts : buildOrOpts;
|
|
1681
|
+
const baseDef = { tag: "node", parser: combinator, ...type === void 0 ? {} : { type }, ...build === void 0 ? {} : { build } };
|
|
1377
1682
|
const meta = {
|
|
1378
1683
|
firstSet: combinator._meta.firstSet,
|
|
1379
1684
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
1380
1685
|
isTrivia: false
|
|
1381
1686
|
};
|
|
1687
|
+
const unwrap = opts?.unwrap === true;
|
|
1382
1688
|
const collapse = opts?.collapse === true;
|
|
1383
|
-
|
|
1689
|
+
if (unwrap && collapse) {
|
|
1690
|
+
throw new Error("node() options cannot set both unwrap and collapse");
|
|
1691
|
+
}
|
|
1692
|
+
const def = unwrap || collapse ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {} } : baseDef;
|
|
1384
1693
|
const capturesTrivia = build ? buildReadsTrivia(def) : true;
|
|
1385
1694
|
const clonesState = build ? buildReadsState(def) : true;
|
|
1695
|
+
const capturesFields = parserHasOwnFields(combinator) && (build ? buildReadsFields(def) : true);
|
|
1386
1696
|
return {
|
|
1387
1697
|
_tag: "node",
|
|
1388
1698
|
_meta: meta,
|
|
1389
1699
|
_def: def,
|
|
1390
1700
|
parse(input, pos, ctx) {
|
|
1391
1701
|
const saved = beginCstNodeCapture(ctx);
|
|
1702
|
+
const savedFields = ctx._fields;
|
|
1703
|
+
ctx._fields = capturesFields ? [] : void 0;
|
|
1392
1704
|
if (!capturesTrivia) ctx.captureTrivia = false;
|
|
1393
1705
|
const r = combinator.parse(input, pos, ctx);
|
|
1706
|
+
const fields = capturesFields ? buildFieldMap(ctx._fields) : void 0;
|
|
1707
|
+
ctx._fields = savedFields;
|
|
1394
1708
|
const { children, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
|
|
1395
1709
|
if (!r.ok) return r;
|
|
1396
1710
|
const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
|
|
1397
|
-
const
|
|
1398
|
-
const
|
|
1399
|
-
const rawEntry =
|
|
1711
|
+
const nodeType = def.type ?? missingInferredType();
|
|
1712
|
+
const built = unwrap && children.length === 1 ? unwrapChild(children[0]) : collapse && children.length === 1 ? children[0] : !build && ctx.build?._parsemanCstCollapse && children.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children[0], children, rawChildren) ? children[0] : build ? build(children, fields, r.span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children, fields, r.span, rawChildren, triviaLog, st) : { _tag: "node", type: nodeType, span: { start: r.span.start, end: r.span.end }, state: st ?? null, children };
|
|
1713
|
+
const rawEntry = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : "", span: r.span };
|
|
1400
1714
|
if (saved.buf !== void 0 || saved.ch !== void 0) {
|
|
1401
1715
|
pushCstChild(ctx, built, rawEntry);
|
|
1402
1716
|
}
|
|
@@ -1414,7 +1728,7 @@ function transform(combinator, fn) {
|
|
|
1414
1728
|
parse(input, pos, ctx) {
|
|
1415
1729
|
const result = combinator.parse(input, pos, ctx);
|
|
1416
1730
|
if (!result.ok) return result;
|
|
1417
|
-
return {
|
|
1731
|
+
return { ok: true, value: fn(result.value, result.span), span: result.span };
|
|
1418
1732
|
}
|
|
1419
1733
|
};
|
|
1420
1734
|
}
|
|
@@ -1428,7 +1742,7 @@ function skip(main, skipped) {
|
|
|
1428
1742
|
if (!result.ok) return result;
|
|
1429
1743
|
const s = skipped.parse(input, result.span.end, ctx);
|
|
1430
1744
|
if (!s.ok) return result;
|
|
1431
|
-
return {
|
|
1745
|
+
return { ok: true, value: result.value, span: { start: result.span.start, end: s.span.end } };
|
|
1432
1746
|
}
|
|
1433
1747
|
};
|
|
1434
1748
|
}
|
|
@@ -1452,7 +1766,20 @@ function label(name, combinator) {
|
|
|
1452
1766
|
_def: { tag: "label", label: name, parser: combinator },
|
|
1453
1767
|
parse(input, pos, ctx) {
|
|
1454
1768
|
const result = combinator.parse(input, pos, ctx);
|
|
1455
|
-
if (!result.ok) return {
|
|
1769
|
+
if (!result.ok) return { ok: false, expected: [name], span: result.span };
|
|
1770
|
+
return result;
|
|
1771
|
+
}
|
|
1772
|
+
};
|
|
1773
|
+
}
|
|
1774
|
+
function field(name, combinator) {
|
|
1775
|
+
return {
|
|
1776
|
+
_tag: combinator._tag,
|
|
1777
|
+
_meta: combinator._meta,
|
|
1778
|
+
_def: { tag: "field", name, parser: combinator },
|
|
1779
|
+
parse(input, pos, ctx) {
|
|
1780
|
+
const result = combinator.parse(input, pos, ctx);
|
|
1781
|
+
if (!result.ok) return result;
|
|
1782
|
+
ctx._fields?.push({ name, value: result.value, span: result.span });
|
|
1456
1783
|
return result;
|
|
1457
1784
|
}
|
|
1458
1785
|
};
|
|
@@ -1666,9 +1993,9 @@ function expect(combinator, label2) {
|
|
|
1666
1993
|
|
|
1667
1994
|
// src/compiler/scannable-run.ts
|
|
1668
1995
|
var BACKSLASH = 92;
|
|
1669
|
-
var
|
|
1996
|
+
var CLASS_ESCAPES2 = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
1670
1997
|
var META = new Set("()[]{}*+?|^$.".split(""));
|
|
1671
|
-
var
|
|
1998
|
+
var SPACE_RANGES2 = [
|
|
1672
1999
|
[9, 13],
|
|
1673
2000
|
[32, 32],
|
|
1674
2001
|
[160, 160],
|
|
@@ -1681,9 +2008,9 @@ var SPACE_RANGES = [
|
|
|
1681
2008
|
[12288, 12288],
|
|
1682
2009
|
[65279, 65279]
|
|
1683
2010
|
];
|
|
1684
|
-
function
|
|
2011
|
+
function shorthandRanges2(ch) {
|
|
1685
2012
|
if (ch === "d") return [[48, 57]];
|
|
1686
|
-
if (ch === "s") return
|
|
2013
|
+
if (ch === "s") return SPACE_RANGES2;
|
|
1687
2014
|
return [[48, 57], [65, 90], [97, 122], [95, 95]];
|
|
1688
2015
|
}
|
|
1689
2016
|
function readUnicodeEscape(body, i) {
|
|
@@ -1707,8 +2034,8 @@ function parseClassRanges(body) {
|
|
|
1707
2034
|
const e = body[i + 1];
|
|
1708
2035
|
if (e === void 0) return null;
|
|
1709
2036
|
i += 2;
|
|
1710
|
-
if (e in
|
|
1711
|
-
if (e === "d" || e === "w" || e === "s") return { set:
|
|
2037
|
+
if (e in CLASS_ESCAPES2) return { cp: CLASS_ESCAPES2[e] };
|
|
2038
|
+
if (e === "d" || e === "w" || e === "s") return { set: shorthandRanges2(e) };
|
|
1712
2039
|
if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
1713
2040
|
return { cp: e.codePointAt(0) };
|
|
1714
2041
|
}
|
|
@@ -1734,9 +2061,9 @@ function parseClassRanges(body) {
|
|
|
1734
2061
|
return ranges.length ? ranges : null;
|
|
1735
2062
|
}
|
|
1736
2063
|
function classToRanges(cls) {
|
|
1737
|
-
if (cls === "\\d") return
|
|
1738
|
-
if (cls === "\\w") return
|
|
1739
|
-
if (cls === "\\s") return
|
|
2064
|
+
if (cls === "\\d") return shorthandRanges2("d");
|
|
2065
|
+
if (cls === "\\w") return shorthandRanges2("w");
|
|
2066
|
+
if (cls === "\\s") return shorthandRanges2("s");
|
|
1740
2067
|
const body = cls.slice(1, -1);
|
|
1741
2068
|
if (body.startsWith("^")) return null;
|
|
1742
2069
|
return parseClassRanges(body);
|
|
@@ -1754,7 +2081,7 @@ function literalCodePoints(frag) {
|
|
|
1754
2081
|
if (ch === "\\") {
|
|
1755
2082
|
const e = frag[i + 1];
|
|
1756
2083
|
if (e === void 0) return null;
|
|
1757
|
-
out.push(e in
|
|
2084
|
+
out.push(e in CLASS_ESCAPES2 ? CLASS_ESCAPES2[e] : e.codePointAt(0));
|
|
1758
2085
|
i += 2;
|
|
1759
2086
|
continue;
|
|
1760
2087
|
}
|
|
@@ -1847,7 +2174,7 @@ function parseSeqParts(source) {
|
|
|
1847
2174
|
if (e === "d" || e === "w" || e === "s") {
|
|
1848
2175
|
flush();
|
|
1849
2176
|
i += 2;
|
|
1850
|
-
i += runFrom(
|
|
2177
|
+
i += runFrom(shorthandRanges2(e), false, source[i]);
|
|
1851
2178
|
continue;
|
|
1852
2179
|
}
|
|
1853
2180
|
const uni = readUnicodeEscape(source, i);
|
|
@@ -1856,8 +2183,8 @@ function parseSeqParts(source) {
|
|
|
1856
2183
|
cp2 = uni.cp;
|
|
1857
2184
|
i = uni.next;
|
|
1858
2185
|
} else if (e === void 0) return null;
|
|
1859
|
-
else if (e in
|
|
1860
|
-
cp2 =
|
|
2186
|
+
else if (e in CLASS_ESCAPES2) {
|
|
2187
|
+
cp2 = CLASS_ESCAPES2[e];
|
|
1861
2188
|
i += 2;
|
|
1862
2189
|
} else if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
1863
2190
|
else {
|
|
@@ -1964,7 +2291,7 @@ function rangesSubset(sub, sup) {
|
|
|
1964
2291
|
}
|
|
1965
2292
|
function parseClassOperand(body) {
|
|
1966
2293
|
if (body === "\\d" || body === "\\w" || body === "\\s") {
|
|
1967
|
-
return { ranges:
|
|
2294
|
+
return { ranges: shorthandRanges2(body[1]), negated: false };
|
|
1968
2295
|
}
|
|
1969
2296
|
if (body.length >= 2 && body[0] === "[" && body[body.length - 1] === "]") {
|
|
1970
2297
|
let inner = body.slice(1, -1);
|
|
@@ -2397,7 +2724,7 @@ function parseScanShapeCore(source) {
|
|
|
2397
2724
|
}
|
|
2398
2725
|
m = /^\\([dws])([+*])$/.exec(source);
|
|
2399
2726
|
if (m) {
|
|
2400
|
-
return { kind: "chars", ranges:
|
|
2727
|
+
return { kind: "chars", ranges: shorthandRanges2(m[1]), minOne: m[2] === "+" };
|
|
2401
2728
|
}
|
|
2402
2729
|
m = /^(\[(?:\\.|[^\]])+\]|\\[dws])(\[(?:\\.|[^\]])+\]|\\[dws])\*$/.exec(source);
|
|
2403
2730
|
if (m) {
|
|
@@ -2939,21 +3266,22 @@ function emitScannableTerminal(shape, c) {
|
|
|
2939
3266
|
}
|
|
2940
3267
|
|
|
2941
3268
|
// src/compiler/inline-build.ts
|
|
2942
|
-
var MK_BUILD_RE = /^\(\s*(
|
|
3269
|
+
var MK_BUILD_RE = /^\(\s*(\w+)\s*,\s*\w+\s*,\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*\)\s*=>\s*mk\s*\(\s*(['"])([^'"]+)\5\s*,\s*\1\s*,\s*\3\s*,\s*\2\s*,\s*\4\s*\)\s*$/;
|
|
2943
3270
|
function escapeRegExp(s) {
|
|
2944
3271
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2945
3272
|
}
|
|
2946
3273
|
function looseMkBuildRe(type) {
|
|
2947
3274
|
return new RegExp(
|
|
2948
|
-
String.raw`^\(\s*(
|
|
3275
|
+
String.raw`^\(\s*(\w+)\s*,\s*\w+\s*,\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*\)\s*=>\s*.+\(\s*(['"])${escapeRegExp(type)}\5\s*,\s*\1\s*,\s*\3\s*,\s*\2\s*,\s*\4\s*\)\s*$`
|
|
2949
3276
|
);
|
|
2950
3277
|
}
|
|
2951
3278
|
function analyzeMkInlineBuild(def) {
|
|
2952
3279
|
if (!def.build) return null;
|
|
3280
|
+
if (def.type === void 0) return null;
|
|
2953
3281
|
const src = (def.buildSrc ?? def.build.toString()).trim();
|
|
2954
3282
|
const strict = src.match(MK_BUILD_RE);
|
|
2955
3283
|
if (strict) {
|
|
2956
|
-
const mkType = strict[
|
|
3284
|
+
const mkType = strict[6];
|
|
2957
3285
|
return mkType === def.type ? def.type : null;
|
|
2958
3286
|
}
|
|
2959
3287
|
if (looseMkBuildRe(def.type).test(src)) return def.type;
|
|
@@ -3280,8 +3608,9 @@ function planDisjointDispatch(parsers) {
|
|
|
3280
3608
|
}
|
|
3281
3609
|
return total >= SWITCH_MIN_CASES ? { kind: "switch", cases } : { kind: "if" };
|
|
3282
3610
|
}
|
|
3283
|
-
function captureRestoreBody(mL, mR, mTl, mLg) {
|
|
3284
|
-
const
|
|
3611
|
+
function captureRestoreBody(mL, mR, mTl, mLg, mF = null) {
|
|
3612
|
+
const fieldRestore = mF ? `; if (_ctx._fields) _ctx._fields.length = ${mF}` : "";
|
|
3613
|
+
const base = `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${mL}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${mR}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${mTl}${fieldRestore}`;
|
|
3285
3614
|
return mLg ? `${base}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${mLg}` : base;
|
|
3286
3615
|
}
|
|
3287
3616
|
function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
|
|
@@ -3329,6 +3658,7 @@ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
3329
3658
|
// Delegating wrappers: defer to the wrapped parser.
|
|
3330
3659
|
case "transform":
|
|
3331
3660
|
case "label":
|
|
3661
|
+
case "field":
|
|
3332
3662
|
case "expect":
|
|
3333
3663
|
case "withCtx":
|
|
3334
3664
|
case "grammar":
|
|
@@ -3375,6 +3705,7 @@ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
3375
3705
|
case "optional":
|
|
3376
3706
|
case "transform":
|
|
3377
3707
|
case "label":
|
|
3708
|
+
case "field":
|
|
3378
3709
|
case "expect":
|
|
3379
3710
|
case "withCtx":
|
|
3380
3711
|
case "grammar":
|
|
@@ -3412,22 +3743,25 @@ function emitFallible(inner, ctx, pos, swallow = false) {
|
|
|
3412
3743
|
ctx.recordFail = savedRecord;
|
|
3413
3744
|
const ind0 = ind(ctx);
|
|
3414
3745
|
const needsRollback = ctx.capturing && mayLeavePartialCapture(inner);
|
|
3746
|
+
const needsFieldRollback = needsRollback && parserHasOwnFields(inner);
|
|
3415
3747
|
const mL = needsRollback ? v(ctx, "_fcl") : null;
|
|
3416
3748
|
const mR = needsRollback ? v(ctx, "_fcr") : null;
|
|
3417
3749
|
const mTl = needsRollback ? v(ctx, "_fctl") : null;
|
|
3750
|
+
const mF = needsFieldRollback ? v(ctx, "_fcf") : null;
|
|
3418
3751
|
const stmts = [
|
|
3419
3752
|
`${ind0}let ${okV} = false, ${valV}, ${endV} = ${pos}`,
|
|
3420
3753
|
...mL ? [
|
|
3421
3754
|
`${ind0}const ${mL} = _ctx._cstLeaves?.length ?? 0`,
|
|
3422
3755
|
`${ind0}const ${mR} = _ctx._cstRawChildren?.length ?? 0`,
|
|
3423
|
-
`${ind0}const ${mTl} = _ctx._cstTriviaLog?.length ?? 0
|
|
3756
|
+
`${ind0}const ${mTl} = _ctx._cstTriviaLog?.length ?? 0`,
|
|
3757
|
+
...mF ? [`${ind0}const ${mF} = _ctx._fields?.length ?? 0`] : []
|
|
3424
3758
|
] : [],
|
|
3425
3759
|
`${ind0}${lbl}: {`,
|
|
3426
3760
|
...r.stmts,
|
|
3427
3761
|
`${ind0} ${valV} = ${r.valueVar}; ${endV} = ${r.endVar}; ${okV} = true`,
|
|
3428
3762
|
`${ind0}}`,
|
|
3429
3763
|
...mL ? [
|
|
3430
|
-
`${ind0}if (!${okV}) { ${captureRestoreBody(mL, mR, mTl, null)} }`
|
|
3764
|
+
`${ind0}if (!${okV}) { ${captureRestoreBody(mL, mR, mTl, null, mF)} }`
|
|
3431
3765
|
] : []
|
|
3432
3766
|
];
|
|
3433
3767
|
return { stmts, okVar: okV, valVar: valV, endVar: endV };
|
|
@@ -3654,6 +3988,7 @@ function failsAtStart(p) {
|
|
|
3654
3988
|
return true;
|
|
3655
3989
|
case "transform":
|
|
3656
3990
|
case "label":
|
|
3991
|
+
case "field":
|
|
3657
3992
|
return failsAtStart(d.parser);
|
|
3658
3993
|
default:
|
|
3659
3994
|
return false;
|
|
@@ -3673,6 +4008,7 @@ function canMatchEmptyAtStart(p) {
|
|
|
3673
4008
|
return true;
|
|
3674
4009
|
case "transform":
|
|
3675
4010
|
case "label":
|
|
4011
|
+
case "field":
|
|
3676
4012
|
return canMatchEmptyAtStart(d.parser);
|
|
3677
4013
|
case "literal":
|
|
3678
4014
|
return d.value.length === 0;
|
|
@@ -3855,11 +4191,13 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
3855
4191
|
const skipCond = gateCond ? `!${resOkV} && ${gateCond}` : `!${resOkV}`;
|
|
3856
4192
|
const armHasAutoNot = !!(autoNot && autoNot.length > 0);
|
|
3857
4193
|
const armNeedsRollback = ctx.capturing && (mayLeavePartialCapture(p) || armHasAutoNot && capturesLeaf(p));
|
|
4194
|
+
const armNeedsFieldRollback = armNeedsRollback && parserHasOwnFields(p);
|
|
3858
4195
|
const markLeaves = armNeedsRollback ? v(ctx, "_cml") : null;
|
|
3859
4196
|
const markRaw = armNeedsRollback ? v(ctx, "_cmr") : null;
|
|
3860
4197
|
const markTl = armNeedsRollback ? v(ctx, "_cmtl") : null;
|
|
3861
4198
|
const markLog = armNeedsRollback ? v(ctx, "_cmlg") : null;
|
|
3862
|
-
const
|
|
4199
|
+
const markFields = armNeedsFieldRollback ? v(ctx, "_cmf") : null;
|
|
4200
|
+
const rollback = markLeaves ? captureRestoreBody(markLeaves, markRaw, markTl, markLog, markFields) : "";
|
|
3863
4201
|
const failSlot = atStart ? staticFx : "_ctx._fx";
|
|
3864
4202
|
stmts.push(`${ind0}if (${skipCond}) {`);
|
|
3865
4203
|
if (fsGuard) stmts.push(`${ind(ctx)}if (${fsGuard}) {`);
|
|
@@ -3869,7 +4207,8 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
3869
4207
|
`${ind(ctx)}const ${markLeaves} = _ctx._cstLeaves?.length ?? 0`,
|
|
3870
4208
|
`${ind(ctx)}const ${markRaw} = _ctx._cstRawChildren?.length ?? 0`,
|
|
3871
4209
|
`${ind(ctx)}const ${markTl} = _ctx._cstTriviaLog?.length ?? 0`,
|
|
3872
|
-
`${ind(ctx)}const ${markLog} = _ctx._triviaLog?.length ?? 0
|
|
4210
|
+
`${ind(ctx)}const ${markLog} = _ctx._triviaLog?.length ?? 0`,
|
|
4211
|
+
...markFields ? [`${ind(ctx)}const ${markFields} = _ctx._fields?.length ?? 0`] : []
|
|
3873
4212
|
);
|
|
3874
4213
|
}
|
|
3875
4214
|
const { stmts: armStmts, okVar, valVar, endVar } = emitFallible(p, ctx, pos, atStart);
|
|
@@ -4262,6 +4601,9 @@ function emitToken(def, ctx, pos) {
|
|
|
4262
4601
|
};
|
|
4263
4602
|
}
|
|
4264
4603
|
function emitNode(def, ctx, pos) {
|
|
4604
|
+
if (def.type === void 0) {
|
|
4605
|
+
throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
|
|
4606
|
+
}
|
|
4265
4607
|
const structural = def.build === void 0;
|
|
4266
4608
|
const mkType = structural ? null : analyzeMkInlineBuild(def);
|
|
4267
4609
|
let buildIdx = null;
|
|
@@ -4273,25 +4615,36 @@ function emitNode(def, ctx, pos) {
|
|
|
4273
4615
|
const i = ind(ctx);
|
|
4274
4616
|
const capturesTrivia = mkType !== null || !structural && buildReadsTrivia(def);
|
|
4275
4617
|
const clonesState = !structural && buildReadsState(def);
|
|
4618
|
+
const hasFields = parserHasOwnFields(def.parser);
|
|
4619
|
+
const capturesFields = hasFields && !structural && buildReadsFields(def);
|
|
4276
4620
|
const chV = v(ctx, "_ch");
|
|
4277
4621
|
const rawV = v(ctx, "_raw");
|
|
4278
4622
|
const capTLv = structural ? v(ctx, "_ctl") : null;
|
|
4279
4623
|
const capSTv = structural ? v(ctx, "_cst") : null;
|
|
4624
|
+
const capFv = structural && hasFields ? v(ctx, "_cf") : null;
|
|
4280
4625
|
const tlV = capturesTrivia || structural ? v(ctx, "_tl") : "_EMPTY_TL";
|
|
4281
4626
|
if (!capturesTrivia) ctx.needsEmptyTl = true;
|
|
4282
4627
|
const sc = v(ctx, "_sc"), sl = v(ctx, "_sl"), sr = v(ctx, "_sr"), st = v(ctx, "_st"), stl = v(ctx, "_stl");
|
|
4283
4628
|
if (structural) ctx.needsHostReads = true;
|
|
4284
|
-
const
|
|
4629
|
+
const hostTriviaGate = `_ctx.build !== undefined && (_ctx.build._parsemanCaptureTrivia !== undefined ? _ctx.build._parsemanCaptureTrivia(${JSON.stringify(def.type)}) : (_ctx._pmCapTL ??= _hostReads(_ctx.build, 5)))`;
|
|
4630
|
+
const allocStmt = structural ? `${i}const ${capTLv} = ${hostTriviaGate}, ${capSTv} = _ctx._pmCapST ??= (_ctx.build === undefined || _hostReads(_ctx.build, 6))${capFv ? `, ${capFv} = _ctx.build !== undefined && _hostReads(_ctx.build, 2)` : ""}
|
|
4285
4631
|
${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capturesTrivia ? `${i}const ${chV} = [], ${rawV} = [], ${tlV} = []` : `${i}const ${chV} = [], ${rawV} = []`;
|
|
4286
4632
|
const innerTl = structural ? `${capTLv} ? ${tlV} : undefined` : capturesTrivia ? tlV : "undefined";
|
|
4633
|
+
const fieldsOn = structural ? capFv ?? "false" : capturesFields ? "true" : "false";
|
|
4634
|
+
const sf = hasFields ? v(ctx, "_sf") : null;
|
|
4635
|
+
const fArr = hasFields ? v(ctx, "_fa") : null;
|
|
4636
|
+
const fObj = hasFields ? v(ctx, "_fields") : "undefined";
|
|
4287
4637
|
const stmts = [
|
|
4288
4638
|
allocStmt,
|
|
4289
|
-
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog`,
|
|
4290
|
-
`${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true; _ctx._cstTriviaLog = ${innerTl}`
|
|
4639
|
+
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog${sf ? `, ${sf} = _ctx._fields` : ""}`,
|
|
4640
|
+
`${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true; _ctx._cstTriviaLog = ${innerTl}${sf ? `; _ctx._fields = ${fieldsOn} ? [] : undefined` : ""}`
|
|
4291
4641
|
];
|
|
4292
4642
|
const { stmts: innerStmts, okVar, endVar } = emitFallible(def.parser, ctx, pos);
|
|
4293
4643
|
stmts.push(...innerStmts);
|
|
4294
|
-
|
|
4644
|
+
if (sf && fArr) {
|
|
4645
|
+
stmts.push(`${i}const ${fArr} = _ctx._fields`);
|
|
4646
|
+
}
|
|
4647
|
+
stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}${sf ? `; _ctx._fields = ${sf}` : ""}`);
|
|
4295
4648
|
stmts.push(...emitIfFail(ctx, `!${okVar}`, propagateFailBody(ctx)));
|
|
4296
4649
|
let stV = "undefined";
|
|
4297
4650
|
if (structural) {
|
|
@@ -4301,14 +4654,33 @@ ${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capt
|
|
|
4301
4654
|
stV = v(ctx, "_nst");
|
|
4302
4655
|
stmts.push(`${i}const ${stV} = _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
|
|
4303
4656
|
}
|
|
4657
|
+
if (sf && fArr) {
|
|
4658
|
+
const fe = v(ctx, "_fe");
|
|
4659
|
+
const cur = v(ctx, "_fc");
|
|
4660
|
+
stmts.push(
|
|
4661
|
+
`${i}let ${fObj} = undefined`,
|
|
4662
|
+
`${i}if (${fArr} && ${fArr}.length) {`,
|
|
4663
|
+
`${i} ${fObj} = {}`,
|
|
4664
|
+
`${i} for (const ${fe} of ${fArr}) {`,
|
|
4665
|
+
`${i} const ${cur} = ${fObj}[${fe}.name], _entry = { value: ${fe}.value, span: ${fe}.span }`,
|
|
4666
|
+
`${i} if (${cur} === undefined) ${fObj}[${fe}.name] = _entry`,
|
|
4667
|
+
`${i} else if (Array.isArray(${cur})) ${cur}.push(_entry)`,
|
|
4668
|
+
`${i} else ${fObj}[${fe}.name] = [${cur}, _entry]`,
|
|
4669
|
+
`${i} }`,
|
|
4670
|
+
`${i}}`
|
|
4671
|
+
);
|
|
4672
|
+
}
|
|
4304
4673
|
const ndV = v(ctx, "_nd");
|
|
4305
|
-
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}, ${
|
|
4306
|
-
const ndExpr = ctx.ns || structural ? `_ctx.build !== undefined ? _ctx.build(${JSON.stringify(def.type)}, ${chV}, ${
|
|
4307
|
-
const
|
|
4674
|
+
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})`;
|
|
4675
|
+
const ndExpr = ctx.ns || structural ? `_ctx.build !== undefined ? _ctx.build(${JSON.stringify(def.type)}, ${chV}, ${fObj}, { start: ${pos}, end: ${endVar} }, ${rawV}, ${tlV}, ${stV}) : (${buildExpr})` : buildExpr;
|
|
4676
|
+
const hostCollapseExpr = ctx.ns || 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;
|
|
4677
|
+
const unwrapExpr = `${chV}.length === 1 ? (${chV}[0] !== null && typeof ${chV}[0] === 'object' && ${chV}[0]._tag === 'leaf' ? ${chV}[0].value : ${chV}[0]) : (${ndExpr})`;
|
|
4678
|
+
const collapseExpr = `${chV}.length === 1 ? ${chV}[0] : (${ndExpr})`;
|
|
4679
|
+
const finalExpr = def.unwrap ? unwrapExpr : def.collapse ? collapseExpr : hostCollapseExpr;
|
|
4308
4680
|
stmts.push(
|
|
4309
4681
|
`${i}const ${ndV} = ${finalExpr}`,
|
|
4310
4682
|
`${i}if (${sc}) ${sc}.push(${ndV})`,
|
|
4311
|
-
`${i}if (${sr}) ${sr}.push((typeof ${ndV} === 'object' && ${ndV} !== null && ${ndV}._tag === 'node') ? ${ndV} : { _tag: 'leaf', value: typeof ${ndV} === 'string' ? ${ndV} : '', span: { start: ${pos}, end: ${endVar} } })`
|
|
4683
|
+
`${i}if (${sr}) ${sr}.push((typeof ${ndV} === 'object' && ${ndV} !== null && (${ndV}._tag === 'node' || ${ndV}._tag === 'leaf' || ${ndV}._tag === 'error')) ? ${ndV} : { _tag: 'leaf', value: typeof ${ndV} === 'string' ? ${ndV} : '', span: { start: ${pos}, end: ${endVar} } })`
|
|
4312
4684
|
);
|
|
4313
4685
|
return { stmts, valueVar: ndV, endVar };
|
|
4314
4686
|
}
|
|
@@ -4523,6 +4895,17 @@ function emitDispatch(p, ctx, pos) {
|
|
|
4523
4895
|
endVar: inner.endVar
|
|
4524
4896
|
};
|
|
4525
4897
|
}
|
|
4898
|
+
case "field": {
|
|
4899
|
+
const inner = emit(def.parser, ctx, pos);
|
|
4900
|
+
return {
|
|
4901
|
+
stmts: [
|
|
4902
|
+
...inner.stmts,
|
|
4903
|
+
`${ind(ctx)}if (_ctx._fields) _ctx._fields.push({ name: ${JSON.stringify(def.name)}, value: ${inner.valueVar}, span: { start: ${pos}, end: ${inner.endVar} } })`
|
|
4904
|
+
],
|
|
4905
|
+
valueVar: inner.valueVar,
|
|
4906
|
+
endVar: inner.endVar
|
|
4907
|
+
};
|
|
4908
|
+
}
|
|
4526
4909
|
case "grammar": {
|
|
4527
4910
|
const savedTrivia = ctx.activeTrivia;
|
|
4528
4911
|
const savedKindLabels = ctx.triviaKindLabels;
|
|
@@ -4624,6 +5007,7 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
4624
5007
|
case "trivia":
|
|
4625
5008
|
case "token":
|
|
4626
5009
|
case "label":
|
|
5010
|
+
case "field":
|
|
4627
5011
|
case "optional":
|
|
4628
5012
|
case "many":
|
|
4629
5013
|
case "oneOrMore":
|
|
@@ -4660,6 +5044,7 @@ function childrenOf(def) {
|
|
|
4660
5044
|
case "trivia":
|
|
4661
5045
|
case "token":
|
|
4662
5046
|
case "label":
|
|
5047
|
+
case "field":
|
|
4663
5048
|
case "grammar":
|
|
4664
5049
|
case "not":
|
|
4665
5050
|
case "node":
|
|
@@ -4901,6 +5286,11 @@ function assertRuleName(name) {
|
|
|
4901
5286
|
);
|
|
4902
5287
|
}
|
|
4903
5288
|
}
|
|
5289
|
+
function publicRuleWrapperSource(rule, fnSource) {
|
|
5290
|
+
const labels = rule._meta.triviaKindLabels;
|
|
5291
|
+
if (labels === void 0) return fnSource;
|
|
5292
|
+
return `Object.assign(${fnSource}, { _meta: { triviaKindLabels: ${JSON.stringify(labels)} } })`;
|
|
5293
|
+
}
|
|
4904
5294
|
function compileLinkable(ruleMapArg, ns) {
|
|
4905
5295
|
if (!ns) throw new Error("compileLinkable: ns must be a non-empty namespace");
|
|
4906
5296
|
for (const [, rule] of ruleMapArg) markUnusedValues(rule);
|
|
@@ -5003,7 +5393,7 @@ function compileLinkable(ruleMapArg, ns) {
|
|
|
5003
5393
|
ctx.recordFail = savedRec;
|
|
5004
5394
|
pushNamedFnDecl(ctx, fn, body.stmts, body.valueVar, body.endVar);
|
|
5005
5395
|
}
|
|
5006
|
-
perEntry.push({ key, r: emitNamedFnCall(ctx, fn, "_pos") });
|
|
5396
|
+
perEntry.push({ key, rule, r: emitNamedFnCall(ctx, fn, "_pos") });
|
|
5007
5397
|
}
|
|
5008
5398
|
if (ctx.runtimeParsers.length !== 0) return null;
|
|
5009
5399
|
const mfSrcs = ctx.mapFns.length > 0 && ctx.mapFnSrcs.every((s) => s !== null) ? ctx.mapFnSrcs : null;
|
|
@@ -5026,14 +5416,14 @@ function compileLinkable(ruleMapArg, ns) {
|
|
|
5026
5416
|
...privateFns
|
|
5027
5417
|
].filter(Boolean);
|
|
5028
5418
|
const wrappers = /* @__PURE__ */ new Map();
|
|
5029
|
-
for (const { key, r } of perEntry) {
|
|
5030
|
-
wrappers.set(key, [
|
|
5419
|
+
for (const { key, rule, r } of perEntry) {
|
|
5420
|
+
wrappers.set(key, publicRuleWrapperSource(rule, [
|
|
5031
5421
|
`function(input, _pos, _ctx) {`,
|
|
5032
5422
|
` let pos = _pos`,
|
|
5033
5423
|
...r.stmts,
|
|
5034
5424
|
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
5035
5425
|
`}`
|
|
5036
|
-
].join("\n"));
|
|
5426
|
+
].join("\n")));
|
|
5037
5427
|
}
|
|
5038
5428
|
const firstSets = /* @__PURE__ */ new Map();
|
|
5039
5429
|
for (const [key, rule] of ruleMap) {
|
|
@@ -5236,6 +5626,7 @@ function evalRuleMapIR(ir) {
|
|
|
5236
5626
|
"skip",
|
|
5237
5627
|
"trivia",
|
|
5238
5628
|
"label",
|
|
5629
|
+
"field",
|
|
5239
5630
|
"expect",
|
|
5240
5631
|
"_tf",
|
|
5241
5632
|
"_nd",
|
|
@@ -5262,6 +5653,7 @@ function evalRuleMapIR(ir) {
|
|
|
5262
5653
|
skip,
|
|
5263
5654
|
trivia,
|
|
5264
5655
|
label,
|
|
5656
|
+
field,
|
|
5265
5657
|
expect,
|
|
5266
5658
|
_tf,
|
|
5267
5659
|
_nd
|
|
@@ -5276,9 +5668,26 @@ function linkable(rulesMap, ns) {
|
|
|
5276
5668
|
if (!pieces) throw new Error("linkable(): this grammar cannot be compiled to a linkable artifact (contains a runtime-only parser fallback)");
|
|
5277
5669
|
return pieces;
|
|
5278
5670
|
}
|
|
5279
|
-
function
|
|
5671
|
+
function normalizeCstCollapse(collapse) {
|
|
5672
|
+
if (collapse === true) return () => true;
|
|
5673
|
+
if (Array.isArray(collapse)) {
|
|
5674
|
+
const types = new Set(collapse);
|
|
5675
|
+
return (type) => types.has(type);
|
|
5676
|
+
}
|
|
5677
|
+
return typeof collapse === "function" ? collapse : void 0;
|
|
5678
|
+
}
|
|
5679
|
+
function buildCstNode(type, children, _fields, span, _rawChildren, _triviaLog, state) {
|
|
5280
5680
|
return { _tag: "node", type, span: { start: span.start, end: span.end }, state: state ?? null, children: [...children] };
|
|
5281
5681
|
}
|
|
5682
|
+
function cstBuildHost(typeOrOptions, children, _fields, span, rawChildren, triviaLog, state) {
|
|
5683
|
+
if (typeof typeOrOptions === "string") {
|
|
5684
|
+
return buildCstNode(typeOrOptions, children ?? [], _fields, span ?? { start: 0, end: 0 }, rawChildren, triviaLog, state);
|
|
5685
|
+
}
|
|
5686
|
+
const collapse = normalizeCstCollapse(typeOrOptions?.collapse);
|
|
5687
|
+
const host = (type, children2, fields, span2, rawChildren2, triviaLog2, state2) => buildCstNode(type, children2, fields, span2, rawChildren2, triviaLog2, state2);
|
|
5688
|
+
if (collapse) host._parsemanCstCollapse = collapse;
|
|
5689
|
+
return host;
|
|
5690
|
+
}
|
|
5282
5691
|
function pick(grammar, names) {
|
|
5283
5692
|
const p = grammar.ruleFns instanceof Map ? grammar : linkable(grammar);
|
|
5284
5693
|
const keep = /* @__PURE__ */ new Set();
|
|
@@ -5310,8 +5719,9 @@ function fusedBody(pieces) {
|
|
|
5310
5719
|
}
|
|
5311
5720
|
}
|
|
5312
5721
|
const contributing = new Set(winner.values());
|
|
5313
|
-
const
|
|
5314
|
-
const
|
|
5722
|
+
const contributingPieces = [...contributing];
|
|
5723
|
+
const needsEmptyTl = contributingPieces.some((p) => p.needsEmptyTl);
|
|
5724
|
+
const needsHostReads = contributingPieces.some((p) => p.needsHostReads);
|
|
5315
5725
|
const lines = [
|
|
5316
5726
|
// Shared sentinel protocol (must match NAMED_FN_FAIL / NAMED_FN_END in codegen).
|
|
5317
5727
|
"const _pfFail = {}",
|
|
@@ -5319,7 +5729,7 @@ function fusedBody(pieces) {
|
|
|
5319
5729
|
...needsEmptyTl ? ["const _EMPTY_TL = Object.freeze([])"] : [],
|
|
5320
5730
|
...needsHostReads ? [HOST_READS_DECL] : [],
|
|
5321
5731
|
// Each contributing artifact's namespaced private prelude (regexes, _pf, …).
|
|
5322
|
-
...[...
|
|
5732
|
+
...[...new Set(contributingPieces.flatMap((p) => p.prelude))],
|
|
5323
5733
|
// The winning `_r_<Name>` function for each rule (one per name → no redeclare).
|
|
5324
5734
|
...[...winner].map(([k, p]) => p.ruleFns.get(k))
|
|
5325
5735
|
];
|
|
@@ -5342,7 +5752,7 @@ function fusedBody(pieces) {
|
|
|
5342
5752
|
}
|
|
5343
5753
|
);
|
|
5344
5754
|
const env = {};
|
|
5345
|
-
for (const p of
|
|
5755
|
+
for (const p of contributingPieces) {
|
|
5346
5756
|
if (p.mfFns.length) env[`${p.ns}mf`] = p.mfFns;
|
|
5347
5757
|
if (p.buildFns.length) env[`${p.ns}build`] = p.buildFns;
|
|
5348
5758
|
}
|
|
@@ -5362,14 +5772,23 @@ function materializePiece(p) {
|
|
|
5362
5772
|
if (!pieces) throw new Error(`compose: carried IR for ns "${p.ns}" could not be re-lowered`);
|
|
5363
5773
|
return pieces;
|
|
5364
5774
|
}
|
|
5365
|
-
function
|
|
5775
|
+
function nextComposeNs(used) {
|
|
5776
|
+
let ns;
|
|
5777
|
+
do {
|
|
5778
|
+
ns = `_lk${_nsCounter++}_`;
|
|
5779
|
+
} while (used.has(ns));
|
|
5780
|
+
used.add(ns);
|
|
5781
|
+
return ns;
|
|
5782
|
+
}
|
|
5783
|
+
function itemPieces(item, used) {
|
|
5366
5784
|
const carried = item[COMPOSED_PIECES];
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
return
|
|
5785
|
+
const pieces = Array.isArray(carried) ? carried.map(materializePiece) : item.ruleFns instanceof Map ? [item] : [linkable(item, nextComposeNs(used))];
|
|
5786
|
+
for (const p of pieces) used.add(p.ns);
|
|
5787
|
+
return pieces;
|
|
5370
5788
|
}
|
|
5371
5789
|
function compose(items) {
|
|
5372
|
-
const
|
|
5790
|
+
const used = /* @__PURE__ */ new Set();
|
|
5791
|
+
const pieces = items.flatMap((item) => itemPieces(item, used));
|
|
5373
5792
|
const map = fuseRules(pieces);
|
|
5374
5793
|
Object.defineProperty(map, COMPOSED_PIECES, { value: pieces, enumerable: false });
|
|
5375
5794
|
return map;
|
|
@@ -6095,6 +6514,7 @@ export {
|
|
|
6095
6514
|
createVisitor,
|
|
6096
6515
|
cstBuildHost,
|
|
6097
6516
|
expect,
|
|
6517
|
+
field,
|
|
6098
6518
|
gapIsSignificant,
|
|
6099
6519
|
gapText,
|
|
6100
6520
|
guard,
|