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/plugin/index.js
CHANGED
|
@@ -182,6 +182,13 @@ function ref() {
|
|
|
182
182
|
define(p) {
|
|
183
183
|
if (resolved) throw new Error("ref<T>() already defined");
|
|
184
184
|
resolved = p;
|
|
185
|
+
meta.firstSet = p._meta.firstSet;
|
|
186
|
+
meta.canMatchNewline = p._meta.canMatchNewline;
|
|
187
|
+
meta.isTrivia = p._meta.isTrivia;
|
|
188
|
+
if (p._meta.triviaKindLabels !== void 0) meta.triviaKindLabels = p._meta.triviaKindLabels;
|
|
189
|
+
else delete meta.triviaKindLabels;
|
|
190
|
+
if (p._meta.disjoint !== void 0) meta.disjoint = p._meta.disjoint;
|
|
191
|
+
else delete meta.disjoint;
|
|
185
192
|
}
|
|
186
193
|
};
|
|
187
194
|
return slot;
|
|
@@ -289,7 +296,8 @@ function saveCstMark(ctx) {
|
|
|
289
296
|
return {
|
|
290
297
|
raw: cstRawLen(ctx),
|
|
291
298
|
tlog: cstTlLen(ctx),
|
|
292
|
-
leaves: cstLeavesLen(ctx)
|
|
299
|
+
leaves: cstLeavesLen(ctx),
|
|
300
|
+
fields: ctx._fields?.length ?? 0
|
|
293
301
|
};
|
|
294
302
|
}
|
|
295
303
|
function rollbackBufList(b, keyMulti, keySingle, len) {
|
|
@@ -313,11 +321,13 @@ function rollbackCstCapture(ctx, mark) {
|
|
|
313
321
|
if (mark.tlog === 0) b.tl = void 0;
|
|
314
322
|
else b.tl.length = mark.tlog;
|
|
315
323
|
}
|
|
324
|
+
if (ctx._fields) ctx._fields.length = mark.fields;
|
|
316
325
|
return;
|
|
317
326
|
}
|
|
318
327
|
if (ctx._cstRawChildren) ctx._cstRawChildren.length = mark.raw;
|
|
319
328
|
if (ctx._cstTriviaLog) ctx._cstTriviaLog.length = mark.tlog;
|
|
320
329
|
if (ctx._cstLeaves) ctx._cstLeaves.length = mark.leaves;
|
|
330
|
+
if (ctx._fields) ctx._fields.length = mark.fields;
|
|
321
331
|
}
|
|
322
332
|
function pushCstTriviaEntry(ctx, start, end, kindIndex) {
|
|
323
333
|
const insertIdx = cstRawLen(ctx);
|
|
@@ -386,13 +396,12 @@ function literal(value, opts = {}) {
|
|
|
386
396
|
if (end > input.length) {
|
|
387
397
|
return failAt(ctx, [JSON.stringify(value)], pos);
|
|
388
398
|
}
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
if (matched) {
|
|
399
|
+
const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
|
|
400
|
+
if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
|
|
392
401
|
const span = { start: pos, end };
|
|
393
|
-
const leaf = { _tag: "leaf", value:
|
|
402
|
+
const leaf = { _tag: "leaf", value: matchedValue, span };
|
|
394
403
|
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
|
|
395
|
-
return { ok: true, value:
|
|
404
|
+
return { ok: true, value: matchedValue, span };
|
|
396
405
|
}
|
|
397
406
|
return failAt(ctx, [JSON.stringify(value)], pos);
|
|
398
407
|
}
|
|
@@ -405,10 +414,102 @@ function registerRegexAnalyzer(analyzer) {
|
|
|
405
414
|
firstSetAnalyzer = analyzer;
|
|
406
415
|
}
|
|
407
416
|
var permissiveFirstSet = () => ({ firstSet: any(), canMatchNewline: true });
|
|
417
|
+
var SCAN_BAIL_AT = 64;
|
|
418
|
+
var SPACE_RANGES = [
|
|
419
|
+
[9, 13],
|
|
420
|
+
[32, 32],
|
|
421
|
+
[160, 160],
|
|
422
|
+
[5760, 5760],
|
|
423
|
+
[8192, 8202],
|
|
424
|
+
[8232, 8233],
|
|
425
|
+
[8239, 8239],
|
|
426
|
+
[8287, 8287],
|
|
427
|
+
[12288, 12288],
|
|
428
|
+
[65279, 65279]
|
|
429
|
+
];
|
|
430
|
+
var CLASS_ESCAPES = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
431
|
+
function shorthandRanges(ch) {
|
|
432
|
+
if (ch === "d") return [[48, 57]];
|
|
433
|
+
if (ch === "s") return SPACE_RANGES;
|
|
434
|
+
return [[48, 57], [65, 90], [97, 122], [95, 95]];
|
|
435
|
+
}
|
|
436
|
+
function inRanges(cp, ranges) {
|
|
437
|
+
for (let i = 0; i < ranges.length; i++) {
|
|
438
|
+
const [lo, hi] = ranges[i];
|
|
439
|
+
if (cp >= lo && cp <= hi) return true;
|
|
440
|
+
}
|
|
441
|
+
return false;
|
|
442
|
+
}
|
|
443
|
+
function readClassRanges(body) {
|
|
444
|
+
if (body.startsWith("^")) return null;
|
|
445
|
+
const ranges = [];
|
|
446
|
+
let i = 0;
|
|
447
|
+
const readAtom = () => {
|
|
448
|
+
const ch = body[i];
|
|
449
|
+
if (ch === void 0) return null;
|
|
450
|
+
if (ch === "\\") {
|
|
451
|
+
const esc = body[i + 1];
|
|
452
|
+
if (esc === void 0) return null;
|
|
453
|
+
i += 2;
|
|
454
|
+
if (esc === "d" || esc === "w" || esc === "s") return { ranges: shorthandRanges(esc) };
|
|
455
|
+
if (esc in CLASS_ESCAPES) return { cp: CLASS_ESCAPES[esc] };
|
|
456
|
+
if (esc >= "a" && esc <= "z" || esc >= "A" && esc <= "Z") return null;
|
|
457
|
+
return { cp: esc.charCodeAt(0) };
|
|
458
|
+
}
|
|
459
|
+
i++;
|
|
460
|
+
return { cp: ch.charCodeAt(0) };
|
|
461
|
+
};
|
|
462
|
+
while (i < body.length) {
|
|
463
|
+
const lo = readAtom();
|
|
464
|
+
if (!lo) return null;
|
|
465
|
+
if ("ranges" in lo) {
|
|
466
|
+
ranges.push(...lo.ranges);
|
|
467
|
+
continue;
|
|
468
|
+
}
|
|
469
|
+
if (body[i] === "-" && body[i + 1] !== void 0 && body[i + 1] !== "]") {
|
|
470
|
+
i++;
|
|
471
|
+
const hi = readAtom();
|
|
472
|
+
if (!hi || "ranges" in hi) return null;
|
|
473
|
+
ranges.push([lo.cp, hi.cp]);
|
|
474
|
+
} else {
|
|
475
|
+
ranges.push([lo.cp, lo.cp]);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
return ranges.length ? ranges : null;
|
|
479
|
+
}
|
|
480
|
+
function shortScanner(source, flags) {
|
|
481
|
+
if (/[imsuvy]/.test(flags)) return null;
|
|
482
|
+
let ranges = null;
|
|
483
|
+
let quant = "";
|
|
484
|
+
if (source[0] === "[") {
|
|
485
|
+
let end = 1;
|
|
486
|
+
while (end < source.length && source[end] !== "]") {
|
|
487
|
+
if (source[end] === "\\") end += 2;
|
|
488
|
+
else end++;
|
|
489
|
+
}
|
|
490
|
+
if (source[end] !== "]") return null;
|
|
491
|
+
ranges = readClassRanges(source.slice(1, end));
|
|
492
|
+
quant = source.slice(end + 1);
|
|
493
|
+
} else if (source[0] === "\\" && (source[1] === "d" || source[1] === "w" || source[1] === "s")) {
|
|
494
|
+
ranges = shorthandRanges(source[1]);
|
|
495
|
+
quant = source.slice(2);
|
|
496
|
+
}
|
|
497
|
+
if (!ranges || quant !== "+" && quant !== "*") return null;
|
|
498
|
+
const minOne = quant === "+";
|
|
499
|
+
return (input, pos) => {
|
|
500
|
+
let end = pos;
|
|
501
|
+
while (end < input.length && inRanges(input.charCodeAt(end), ranges)) {
|
|
502
|
+
end++;
|
|
503
|
+
if (end - pos >= SCAN_BAIL_AT) return void 0;
|
|
504
|
+
}
|
|
505
|
+
return minOne && end === pos ? null : end;
|
|
506
|
+
};
|
|
507
|
+
}
|
|
408
508
|
function regex(pattern, flags = "") {
|
|
409
509
|
const source = typeof pattern === "string" ? pattern : pattern.source;
|
|
410
510
|
const resolvedFlags = typeof pattern === "string" ? flags : pattern.flags;
|
|
411
511
|
const anchored = new RegExp(source, "y" + resolvedFlags.replace(/[gy]/g, ""));
|
|
512
|
+
const scan = shortScanner(source, resolvedFlags);
|
|
412
513
|
const { firstSet, canMatchNewline } = (firstSetAnalyzer ?? permissiveFirstSet)(source);
|
|
413
514
|
const meta = { firstSet, canMatchNewline, isTrivia: false };
|
|
414
515
|
return {
|
|
@@ -416,6 +517,15 @@ function regex(pattern, flags = "") {
|
|
|
416
517
|
_meta: meta,
|
|
417
518
|
_def: { tag: "regex", source, flags: resolvedFlags },
|
|
418
519
|
parse(input, pos, ctx) {
|
|
520
|
+
const scanEnd = scan?.(input, pos);
|
|
521
|
+
if (scanEnd !== void 0) {
|
|
522
|
+
if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
|
|
523
|
+
const value = input.slice(pos, scanEnd);
|
|
524
|
+
const span2 = { start: pos, end: scanEnd };
|
|
525
|
+
const leaf2 = { _tag: "leaf", value, span: span2 };
|
|
526
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf2);
|
|
527
|
+
return { ok: true, value, span: span2 };
|
|
528
|
+
}
|
|
419
529
|
anchored.lastIndex = pos;
|
|
420
530
|
const m = anchored.exec(input);
|
|
421
531
|
if (m === null) {
|
|
@@ -596,13 +706,10 @@ function choice(...args) {
|
|
|
596
706
|
};
|
|
597
707
|
const strategy = disjoint || hasGates ? null : detectStrategy(parsers);
|
|
598
708
|
const autoNot = !disjoint && !hasGates && strategy?.tag === "firstMatch" ? computeAutoNot(parsers) : parsers.map(() => null);
|
|
599
|
-
let greedyRe = null;
|
|
600
709
|
let greedyLitMap = null;
|
|
601
710
|
let sortedParsers = null;
|
|
711
|
+
const asciiDispatch = disjoint ? buildAsciiDispatch(parsers) : null;
|
|
602
712
|
if (strategy?.tag === "greedyClassify") {
|
|
603
|
-
const regexDef = getCoreRegexDef(parsers[strategy.superIndex]);
|
|
604
|
-
const flags = "y" + regexDef.flags.replace(/[gy]/g, "");
|
|
605
|
-
greedyRe = new RegExp(regexDef.source, flags);
|
|
606
713
|
greedyLitMap = /* @__PURE__ */ new Map();
|
|
607
714
|
for (let i = 0; i < parsers.length; i++) {
|
|
608
715
|
if (i === strategy.superIndex) continue;
|
|
@@ -627,14 +734,21 @@ function choice(...args) {
|
|
|
627
734
|
const expected = [];
|
|
628
735
|
if (disjoint && pos < input.length) {
|
|
629
736
|
const code = input.codePointAt(pos);
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
if (
|
|
634
|
-
|
|
635
|
-
|
|
737
|
+
let parser2 = code < 128 ? asciiDispatch?.[code] ?? null : null;
|
|
738
|
+
if (!parser2) {
|
|
739
|
+
for (const p of parsers) {
|
|
740
|
+
if (inFirstSet(code, p._meta.firstSet)) {
|
|
741
|
+
parser2 = p;
|
|
742
|
+
break;
|
|
743
|
+
}
|
|
636
744
|
}
|
|
637
745
|
}
|
|
746
|
+
if (parser2) {
|
|
747
|
+
const result = parser2.parse(input, pos, ctx);
|
|
748
|
+
if (result.ok) return result;
|
|
749
|
+
expected.push(...result.expected);
|
|
750
|
+
return { ok: false, expected, span: { start: pos, end: pos } };
|
|
751
|
+
}
|
|
638
752
|
return {
|
|
639
753
|
ok: false,
|
|
640
754
|
expected: parsers.flatMap((p) => {
|
|
@@ -810,6 +924,19 @@ function areDisjoint(sets) {
|
|
|
810
924
|
if (intersects(sets[i], sets[j])) return false;
|
|
811
925
|
return true;
|
|
812
926
|
}
|
|
927
|
+
function buildAsciiDispatch(parsers) {
|
|
928
|
+
const table = Array(128).fill(null);
|
|
929
|
+
for (const parser2 of parsers) {
|
|
930
|
+
const fs2 = parser2._meta.firstSet;
|
|
931
|
+
if (fs2.kind !== "ranges") continue;
|
|
932
|
+
for (const { lo, hi } of fs2.ranges) {
|
|
933
|
+
for (let code = Math.max(0, lo); code <= Math.min(127, hi); code++) {
|
|
934
|
+
table[code] = parser2;
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
return table;
|
|
939
|
+
}
|
|
813
940
|
|
|
814
941
|
// src/cst/trivia-kinds.ts
|
|
815
942
|
function unwrapTrivia(p) {
|
|
@@ -931,15 +1058,16 @@ function recordTriviaChunks(ctx, chunks) {
|
|
|
931
1058
|
// src/combinators/trivia-skip.ts
|
|
932
1059
|
var NOOP_COMMIT = () => {
|
|
933
1060
|
};
|
|
1061
|
+
var fastTriviaCache = /* @__PURE__ */ new WeakMap();
|
|
934
1062
|
function needsDeferredTriviaCommit(ctx) {
|
|
935
1063
|
return ctx._triviaLog !== void 0 || ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0;
|
|
936
1064
|
}
|
|
937
1065
|
function saveTriviaMark(ctx) {
|
|
938
1066
|
const m = saveCstMark(ctx);
|
|
939
|
-
return { raw: m.raw, tlog: m.tlog, leaves: m.leaves, log: ctx._triviaLog ? ctx._triviaLog.length : 0 };
|
|
1067
|
+
return { raw: m.raw, tlog: m.tlog, leaves: m.leaves, fields: m.fields, log: ctx._triviaLog ? ctx._triviaLog.length : 0 };
|
|
940
1068
|
}
|
|
941
1069
|
function rollbackTrivia(ctx, mark) {
|
|
942
|
-
rollbackCstCapture(ctx, { raw: mark.raw, tlog: mark.tlog, leaves: mark.leaves });
|
|
1070
|
+
rollbackCstCapture(ctx, { raw: mark.raw, tlog: mark.tlog, leaves: mark.leaves, fields: mark.fields });
|
|
943
1071
|
if (ctx._triviaLog) ctx._triviaLog.length = mark.log;
|
|
944
1072
|
}
|
|
945
1073
|
function scanWithLabels(input, cur, ctx) {
|
|
@@ -957,6 +1085,8 @@ function scanWithLabels(input, cur, ctx) {
|
|
|
957
1085
|
function advanceTrivia(input, cur, ctx) {
|
|
958
1086
|
const triviaP = ctx.trivia;
|
|
959
1087
|
if (!triviaP) return cur;
|
|
1088
|
+
const fast = fastTriviaScanner(triviaP);
|
|
1089
|
+
if (fast) return fast(input, cur);
|
|
960
1090
|
if (ctx.triviaKindLabels) {
|
|
961
1091
|
const scan = scanWithLabels(input, cur, ctx);
|
|
962
1092
|
return scan.end;
|
|
@@ -969,6 +1099,10 @@ function scanTrivia(input, cur, ctx) {
|
|
|
969
1099
|
if (!triviaP) return { end: cur, commit: NOOP_COMMIT };
|
|
970
1100
|
const log = ctx._triviaLog;
|
|
971
1101
|
const captureTl = ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0);
|
|
1102
|
+
const fast = !ctx.triviaKindLabels ? fastTriviaScanner(triviaP) : null;
|
|
1103
|
+
if (fast && log === void 0 && !captureTl) {
|
|
1104
|
+
return { end: fast(input, cur), commit: NOOP_COMMIT };
|
|
1105
|
+
}
|
|
972
1106
|
if (ctx.triviaKindLabels && (log !== void 0 || captureTl)) {
|
|
973
1107
|
return scanWithLabels(input, cur, ctx);
|
|
974
1108
|
}
|
|
@@ -990,6 +1124,79 @@ function scanTrivia(input, cur, ctx) {
|
|
|
990
1124
|
const tr = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
|
|
991
1125
|
return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
|
|
992
1126
|
}
|
|
1127
|
+
function fastTriviaScanner(trivia2) {
|
|
1128
|
+
const cached = fastTriviaCache.get(trivia2);
|
|
1129
|
+
if (cached !== void 0) return cached;
|
|
1130
|
+
const scanner = buildFastTriviaScanner(trivia2);
|
|
1131
|
+
fastTriviaCache.set(trivia2, scanner);
|
|
1132
|
+
return scanner;
|
|
1133
|
+
}
|
|
1134
|
+
function buildFastTriviaScanner(trivia2) {
|
|
1135
|
+
const core = trivia2._def.tag === "trivia" ? trivia2._def.parser : trivia2;
|
|
1136
|
+
const direct = regexTriviaScanner(core);
|
|
1137
|
+
if (direct) return direct;
|
|
1138
|
+
const repeat = core._def.tag === "oneOrMore" || core._def.tag === "many" && core._def.min >= 1 ? core._def.parser : null;
|
|
1139
|
+
if (!repeat) return null;
|
|
1140
|
+
const one = regexTriviaScanner(repeat);
|
|
1141
|
+
if (one) return loopScanner([one]);
|
|
1142
|
+
if (repeat._def.tag !== "choice") return null;
|
|
1143
|
+
const arms = repeat._def.parsers.map(regexTriviaScanner);
|
|
1144
|
+
if (arms.some((s) => s === null)) return null;
|
|
1145
|
+
return loopScanner(arms);
|
|
1146
|
+
}
|
|
1147
|
+
function loopScanner(arms) {
|
|
1148
|
+
return (input, cur) => {
|
|
1149
|
+
let pos = cur;
|
|
1150
|
+
scan: while (pos < input.length) {
|
|
1151
|
+
for (const arm of arms) {
|
|
1152
|
+
const end = arm(input, pos);
|
|
1153
|
+
if (end > pos) {
|
|
1154
|
+
pos = end;
|
|
1155
|
+
continue scan;
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
break;
|
|
1159
|
+
}
|
|
1160
|
+
return pos;
|
|
1161
|
+
};
|
|
1162
|
+
}
|
|
1163
|
+
function regexTriviaScanner(parser2) {
|
|
1164
|
+
if (parser2._def.tag !== "regex" || parser2._def.flags) return null;
|
|
1165
|
+
const ws = whitespaceSource(parser2._def.source);
|
|
1166
|
+
if (ws) return ws;
|
|
1167
|
+
return blockCommentSource(parser2._def.source) ? scanBlockComment : null;
|
|
1168
|
+
}
|
|
1169
|
+
function whitespaceSource(source) {
|
|
1170
|
+
const m = /^\[([ \\tnrf]+)\][*+]$/.exec(source);
|
|
1171
|
+
if (!m) return null;
|
|
1172
|
+
const chars = /* @__PURE__ */ new Set();
|
|
1173
|
+
for (let i = 0; i < m[1].length; i++) {
|
|
1174
|
+
const ch = m[1][i];
|
|
1175
|
+
if (ch !== "\\") {
|
|
1176
|
+
chars.add(ch.charCodeAt(0));
|
|
1177
|
+
continue;
|
|
1178
|
+
}
|
|
1179
|
+
const esc = m[1][++i];
|
|
1180
|
+
if (esc === "t") chars.add(9);
|
|
1181
|
+
else if (esc === "n") chars.add(10);
|
|
1182
|
+
else if (esc === "r") chars.add(13);
|
|
1183
|
+
else if (esc === "f") chars.add(12);
|
|
1184
|
+
else return null;
|
|
1185
|
+
}
|
|
1186
|
+
return (input, cur) => {
|
|
1187
|
+
let pos = cur;
|
|
1188
|
+
while (pos < input.length && chars.has(input.charCodeAt(pos))) pos++;
|
|
1189
|
+
return pos;
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
function blockCommentSource(source) {
|
|
1193
|
+
return source === "\\/\\*(?:[^*]|\\*(?!\\/))*\\*\\/" || source === "\\/\\*[^]*?\\*\\/";
|
|
1194
|
+
}
|
|
1195
|
+
function scanBlockComment(input, cur) {
|
|
1196
|
+
if (input.charCodeAt(cur) !== 47 || input.charCodeAt(cur + 1) !== 42) return cur;
|
|
1197
|
+
const close = input.indexOf("*/", cur + 2);
|
|
1198
|
+
return close === -1 ? cur : close + 2;
|
|
1199
|
+
}
|
|
993
1200
|
|
|
994
1201
|
// src/combinators/sequence.ts
|
|
995
1202
|
function sequence(...parsers) {
|
|
@@ -1128,11 +1335,15 @@ function optional(combinator) {
|
|
|
1128
1335
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
1129
1336
|
isTrivia: false
|
|
1130
1337
|
};
|
|
1338
|
+
const firstSetSkippable = !matchesEmpty(combinator);
|
|
1131
1339
|
return {
|
|
1132
1340
|
_tag: "optional",
|
|
1133
1341
|
_meta: meta,
|
|
1134
1342
|
_def: { tag: "optional", parser: combinator },
|
|
1135
1343
|
parse(input, pos, ctx) {
|
|
1344
|
+
if (firstSetSkippable && ctx._probe === void 0 && !startsFirstSet(combinator, input, pos)) {
|
|
1345
|
+
return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
1346
|
+
}
|
|
1136
1347
|
const mark = saveTriviaMark(ctx);
|
|
1137
1348
|
const result = combinator.parse(input, pos, ctx);
|
|
1138
1349
|
if (result.ok) return result;
|
|
@@ -1141,6 +1352,15 @@ function optional(combinator) {
|
|
|
1141
1352
|
}
|
|
1142
1353
|
};
|
|
1143
1354
|
}
|
|
1355
|
+
function startsFirstSet(combinator, input, pos) {
|
|
1356
|
+
const fs2 = combinator._meta.firstSet;
|
|
1357
|
+
if (fs2.kind === "any") return true;
|
|
1358
|
+
if (fs2.kind === "empty") return false;
|
|
1359
|
+
const code = input.codePointAt(pos);
|
|
1360
|
+
if (code === void 0) return false;
|
|
1361
|
+
for (const r of fs2.ranges) if (code >= r.lo && code <= r.hi) return true;
|
|
1362
|
+
return false;
|
|
1363
|
+
}
|
|
1144
1364
|
function sepBy(combinator, separator) {
|
|
1145
1365
|
const meta = {
|
|
1146
1366
|
firstSet: combinator._meta.firstSet,
|
|
@@ -1231,6 +1451,9 @@ function markUnusedValues(root) {
|
|
|
1231
1451
|
case "transform":
|
|
1232
1452
|
visit(def.parser, true);
|
|
1233
1453
|
return;
|
|
1454
|
+
case "field":
|
|
1455
|
+
visit(def.parser, true);
|
|
1456
|
+
return;
|
|
1234
1457
|
case "skip":
|
|
1235
1458
|
visit(def.main, consumed);
|
|
1236
1459
|
visit(def.skipped, false);
|
|
@@ -1282,6 +1505,11 @@ function markUnusedValues(root) {
|
|
|
1282
1505
|
}
|
|
1283
1506
|
|
|
1284
1507
|
// src/combinators/parser.ts
|
|
1508
|
+
function tagRule(r, key) {
|
|
1509
|
+
;
|
|
1510
|
+
r._ruleName = key;
|
|
1511
|
+
if (r._def.tag === "node" && r._def.type === void 0) r._def.type = key;
|
|
1512
|
+
}
|
|
1285
1513
|
function rules(factory) {
|
|
1286
1514
|
const cache = {};
|
|
1287
1515
|
const proxy = new Proxy(cache, {
|
|
@@ -1290,7 +1518,7 @@ function rules(factory) {
|
|
|
1290
1518
|
const record = target;
|
|
1291
1519
|
if (!(key in record)) {
|
|
1292
1520
|
const r = ref();
|
|
1293
|
-
r
|
|
1521
|
+
tagRule(r, key);
|
|
1294
1522
|
record[key] = r;
|
|
1295
1523
|
}
|
|
1296
1524
|
return record[key];
|
|
@@ -1301,12 +1529,12 @@ function rules(factory) {
|
|
|
1301
1529
|
const placeholder = cache[key];
|
|
1302
1530
|
const parser2 = definitions[key];
|
|
1303
1531
|
if (placeholder !== void 0 && typeof placeholder.define === "function") {
|
|
1304
|
-
;
|
|
1532
|
+
tagRule(parser2, key);
|
|
1305
1533
|
placeholder.define(parser2);
|
|
1306
1534
|
placeholder._meta.firstSet = parser2._meta.firstSet;
|
|
1307
1535
|
placeholder._meta.canMatchNewline = parser2._meta.canMatchNewline;
|
|
1308
1536
|
} else {
|
|
1309
|
-
;
|
|
1537
|
+
tagRule(parser2, key);
|
|
1310
1538
|
cache[key] = parser2;
|
|
1311
1539
|
}
|
|
1312
1540
|
}
|
|
@@ -1363,44 +1591,130 @@ function buildReadsTrivia(def) {
|
|
|
1363
1591
|
const src = def.buildSrc ?? def.build.toString();
|
|
1364
1592
|
const arity = confirmedBuildArity(src);
|
|
1365
1593
|
if (arity === null) return true;
|
|
1366
|
-
return arity >=
|
|
1594
|
+
return arity >= 5;
|
|
1367
1595
|
}
|
|
1368
1596
|
function buildReadsState(def) {
|
|
1369
1597
|
if (!def.build) return true;
|
|
1370
1598
|
const src = def.buildSrc ?? def.build.toString();
|
|
1371
1599
|
const arity = confirmedBuildArity(src);
|
|
1372
1600
|
if (arity === null) return true;
|
|
1373
|
-
return arity >=
|
|
1601
|
+
return arity >= 6;
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
// src/compiler/fields.ts
|
|
1605
|
+
function buildReadsFields(def) {
|
|
1606
|
+
if (!def.build) return true;
|
|
1607
|
+
const src = def.buildSrc ?? def.build.toString();
|
|
1608
|
+
const arity = confirmedBuildArity(src);
|
|
1609
|
+
if (arity === null) return true;
|
|
1610
|
+
return arity >= 2;
|
|
1611
|
+
}
|
|
1612
|
+
function parserHasOwnFields(p, seen = /* @__PURE__ */ new Set()) {
|
|
1613
|
+
if (seen.has(p)) return false;
|
|
1614
|
+
seen.add(p);
|
|
1615
|
+
const d = p._def;
|
|
1616
|
+
switch (d.tag) {
|
|
1617
|
+
case "field":
|
|
1618
|
+
return true;
|
|
1619
|
+
case "node":
|
|
1620
|
+
return false;
|
|
1621
|
+
case "lazy": {
|
|
1622
|
+
try {
|
|
1623
|
+
return parserHasOwnFields(d.thunk(), seen);
|
|
1624
|
+
} catch {
|
|
1625
|
+
return false;
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
case "sequence":
|
|
1629
|
+
case "choice":
|
|
1630
|
+
return d.parsers.some((x) => parserHasOwnFields(x, seen));
|
|
1631
|
+
case "sepBy":
|
|
1632
|
+
return parserHasOwnFields(d.parser, seen) || parserHasOwnFields(d.separator, seen);
|
|
1633
|
+
case "skip":
|
|
1634
|
+
return parserHasOwnFields(d.main, seen) || parserHasOwnFields(d.skipped, seen);
|
|
1635
|
+
case "grammar":
|
|
1636
|
+
return parserHasOwnFields(d.parser, seen) || (d.triviaParser ? parserHasOwnFields(d.triviaParser, seen) : false);
|
|
1637
|
+
case "scanTo":
|
|
1638
|
+
return parserHasOwnFields(d.sentinel, seen) || d.skip.some((x) => parserHasOwnFields(x, seen));
|
|
1639
|
+
case "recover":
|
|
1640
|
+
return parserHasOwnFields(d.parser, seen) || parserHasOwnFields(d.sentinel, seen);
|
|
1641
|
+
case "many":
|
|
1642
|
+
case "oneOrMore":
|
|
1643
|
+
case "optional":
|
|
1644
|
+
case "transform":
|
|
1645
|
+
case "trivia":
|
|
1646
|
+
case "token":
|
|
1647
|
+
case "label":
|
|
1648
|
+
case "expect":
|
|
1649
|
+
case "withCtx":
|
|
1650
|
+
case "not":
|
|
1651
|
+
return parserHasOwnFields(d.parser, seen);
|
|
1652
|
+
default:
|
|
1653
|
+
return false;
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
function buildFieldMap(captures) {
|
|
1657
|
+
if (!captures?.length) return void 0;
|
|
1658
|
+
const out = {};
|
|
1659
|
+
for (const cap of captures) {
|
|
1660
|
+
const entry = { value: cap.value, span: cap.span };
|
|
1661
|
+
const current = out[cap.name];
|
|
1662
|
+
if (current === void 0) out[cap.name] = entry;
|
|
1663
|
+
else if (Array.isArray(current)) current.push(entry);
|
|
1664
|
+
else out[cap.name] = [current, entry];
|
|
1665
|
+
}
|
|
1666
|
+
return out;
|
|
1374
1667
|
}
|
|
1375
1668
|
|
|
1376
1669
|
// src/combinators/node.ts
|
|
1377
|
-
function
|
|
1670
|
+
function unwrapChild(child) {
|
|
1378
1671
|
return child !== null && typeof child === "object" && child._tag === "leaf" ? child.value : child;
|
|
1379
1672
|
}
|
|
1380
|
-
function
|
|
1673
|
+
function isCstChild(value) {
|
|
1674
|
+
return typeof value === "object" && value !== null && (value._tag === "node" || value._tag === "leaf" || value._tag === "error");
|
|
1675
|
+
}
|
|
1676
|
+
function missingInferredType() {
|
|
1677
|
+
throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
|
|
1678
|
+
}
|
|
1679
|
+
function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
1680
|
+
const hasExplicitType = typeof typeOrCombinator === "string";
|
|
1681
|
+
const type = hasExplicitType ? typeOrCombinator : void 0;
|
|
1682
|
+
const combinator = hasExplicitType ? combinatorOrBuild : typeOrCombinator;
|
|
1683
|
+
const build = hasExplicitType ? buildOrOpts : combinatorOrBuild;
|
|
1684
|
+
const opts = hasExplicitType ? maybeOpts : buildOrOpts;
|
|
1685
|
+
const baseDef = { tag: "node", parser: combinator, ...type === void 0 ? {} : { type }, ...build === void 0 ? {} : { build } };
|
|
1381
1686
|
const meta = {
|
|
1382
1687
|
firstSet: combinator._meta.firstSet,
|
|
1383
1688
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
1384
1689
|
isTrivia: false
|
|
1385
1690
|
};
|
|
1691
|
+
const unwrap = opts?.unwrap === true;
|
|
1386
1692
|
const collapse = opts?.collapse === true;
|
|
1387
|
-
|
|
1693
|
+
if (unwrap && collapse) {
|
|
1694
|
+
throw new Error("node() options cannot set both unwrap and collapse");
|
|
1695
|
+
}
|
|
1696
|
+
const def = unwrap || collapse ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {} } : baseDef;
|
|
1388
1697
|
const capturesTrivia = build ? buildReadsTrivia(def) : true;
|
|
1389
1698
|
const clonesState = build ? buildReadsState(def) : true;
|
|
1699
|
+
const capturesFields = parserHasOwnFields(combinator) && (build ? buildReadsFields(def) : true);
|
|
1390
1700
|
return {
|
|
1391
1701
|
_tag: "node",
|
|
1392
1702
|
_meta: meta,
|
|
1393
1703
|
_def: def,
|
|
1394
1704
|
parse(input, pos, ctx) {
|
|
1395
1705
|
const saved = beginCstNodeCapture(ctx);
|
|
1706
|
+
const savedFields = ctx._fields;
|
|
1707
|
+
ctx._fields = capturesFields ? [] : void 0;
|
|
1396
1708
|
if (!capturesTrivia) ctx.captureTrivia = false;
|
|
1397
1709
|
const r = combinator.parse(input, pos, ctx);
|
|
1710
|
+
const fields = capturesFields ? buildFieldMap(ctx._fields) : void 0;
|
|
1711
|
+
ctx._fields = savedFields;
|
|
1398
1712
|
const { children, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
|
|
1399
1713
|
if (!r.ok) return r;
|
|
1400
1714
|
const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
|
|
1401
|
-
const
|
|
1402
|
-
const
|
|
1403
|
-
const rawEntry =
|
|
1715
|
+
const nodeType = def.type ?? missingInferredType();
|
|
1716
|
+
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 };
|
|
1717
|
+
const rawEntry = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : "", span: r.span };
|
|
1404
1718
|
if (saved.buf !== void 0 || saved.ch !== void 0) {
|
|
1405
1719
|
pushCstChild(ctx, built, rawEntry);
|
|
1406
1720
|
}
|
|
@@ -1418,7 +1732,7 @@ function transform(combinator, fn) {
|
|
|
1418
1732
|
parse(input, pos, ctx) {
|
|
1419
1733
|
const result = combinator.parse(input, pos, ctx);
|
|
1420
1734
|
if (!result.ok) return result;
|
|
1421
|
-
return {
|
|
1735
|
+
return { ok: true, value: fn(result.value, result.span), span: result.span };
|
|
1422
1736
|
}
|
|
1423
1737
|
};
|
|
1424
1738
|
}
|
|
@@ -1432,7 +1746,7 @@ function skip(main, skipped) {
|
|
|
1432
1746
|
if (!result.ok) return result;
|
|
1433
1747
|
const s = skipped.parse(input, result.span.end, ctx);
|
|
1434
1748
|
if (!s.ok) return result;
|
|
1435
|
-
return {
|
|
1749
|
+
return { ok: true, value: result.value, span: { start: result.span.start, end: s.span.end } };
|
|
1436
1750
|
}
|
|
1437
1751
|
};
|
|
1438
1752
|
}
|
|
@@ -1456,7 +1770,20 @@ function label(name, combinator) {
|
|
|
1456
1770
|
_def: { tag: "label", label: name, parser: combinator },
|
|
1457
1771
|
parse(input, pos, ctx) {
|
|
1458
1772
|
const result = combinator.parse(input, pos, ctx);
|
|
1459
|
-
if (!result.ok) return {
|
|
1773
|
+
if (!result.ok) return { ok: false, expected: [name], span: result.span };
|
|
1774
|
+
return result;
|
|
1775
|
+
}
|
|
1776
|
+
};
|
|
1777
|
+
}
|
|
1778
|
+
function field(name, combinator) {
|
|
1779
|
+
return {
|
|
1780
|
+
_tag: combinator._tag,
|
|
1781
|
+
_meta: combinator._meta,
|
|
1782
|
+
_def: { tag: "field", name, parser: combinator },
|
|
1783
|
+
parse(input, pos, ctx) {
|
|
1784
|
+
const result = combinator.parse(input, pos, ctx);
|
|
1785
|
+
if (!result.ok) return result;
|
|
1786
|
+
ctx._fields?.push({ name, value: result.value, span: result.span });
|
|
1460
1787
|
return result;
|
|
1461
1788
|
}
|
|
1462
1789
|
};
|
|
@@ -1647,9 +1974,9 @@ function expect(combinator, label2) {
|
|
|
1647
1974
|
|
|
1648
1975
|
// src/compiler/scannable-run.ts
|
|
1649
1976
|
var BACKSLASH = 92;
|
|
1650
|
-
var
|
|
1977
|
+
var CLASS_ESCAPES2 = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
1651
1978
|
var META = new Set("()[]{}*+?|^$.".split(""));
|
|
1652
|
-
var
|
|
1979
|
+
var SPACE_RANGES2 = [
|
|
1653
1980
|
[9, 13],
|
|
1654
1981
|
[32, 32],
|
|
1655
1982
|
[160, 160],
|
|
@@ -1662,9 +1989,9 @@ var SPACE_RANGES = [
|
|
|
1662
1989
|
[12288, 12288],
|
|
1663
1990
|
[65279, 65279]
|
|
1664
1991
|
];
|
|
1665
|
-
function
|
|
1992
|
+
function shorthandRanges2(ch) {
|
|
1666
1993
|
if (ch === "d") return [[48, 57]];
|
|
1667
|
-
if (ch === "s") return
|
|
1994
|
+
if (ch === "s") return SPACE_RANGES2;
|
|
1668
1995
|
return [[48, 57], [65, 90], [97, 122], [95, 95]];
|
|
1669
1996
|
}
|
|
1670
1997
|
function readUnicodeEscape(body, i) {
|
|
@@ -1688,8 +2015,8 @@ function parseClassRanges(body) {
|
|
|
1688
2015
|
const e = body[i + 1];
|
|
1689
2016
|
if (e === void 0) return null;
|
|
1690
2017
|
i += 2;
|
|
1691
|
-
if (e in
|
|
1692
|
-
if (e === "d" || e === "w" || e === "s") return { set:
|
|
2018
|
+
if (e in CLASS_ESCAPES2) return { cp: CLASS_ESCAPES2[e] };
|
|
2019
|
+
if (e === "d" || e === "w" || e === "s") return { set: shorthandRanges2(e) };
|
|
1693
2020
|
if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
1694
2021
|
return { cp: e.codePointAt(0) };
|
|
1695
2022
|
}
|
|
@@ -1715,9 +2042,9 @@ function parseClassRanges(body) {
|
|
|
1715
2042
|
return ranges.length ? ranges : null;
|
|
1716
2043
|
}
|
|
1717
2044
|
function classToRanges(cls) {
|
|
1718
|
-
if (cls === "\\d") return
|
|
1719
|
-
if (cls === "\\w") return
|
|
1720
|
-
if (cls === "\\s") return
|
|
2045
|
+
if (cls === "\\d") return shorthandRanges2("d");
|
|
2046
|
+
if (cls === "\\w") return shorthandRanges2("w");
|
|
2047
|
+
if (cls === "\\s") return shorthandRanges2("s");
|
|
1721
2048
|
const body = cls.slice(1, -1);
|
|
1722
2049
|
if (body.startsWith("^")) return null;
|
|
1723
2050
|
return parseClassRanges(body);
|
|
@@ -1735,7 +2062,7 @@ function literalCodePoints(frag) {
|
|
|
1735
2062
|
if (ch === "\\") {
|
|
1736
2063
|
const e = frag[i + 1];
|
|
1737
2064
|
if (e === void 0) return null;
|
|
1738
|
-
out.push(e in
|
|
2065
|
+
out.push(e in CLASS_ESCAPES2 ? CLASS_ESCAPES2[e] : e.codePointAt(0));
|
|
1739
2066
|
i += 2;
|
|
1740
2067
|
continue;
|
|
1741
2068
|
}
|
|
@@ -1828,7 +2155,7 @@ function parseSeqParts(source) {
|
|
|
1828
2155
|
if (e === "d" || e === "w" || e === "s") {
|
|
1829
2156
|
flush();
|
|
1830
2157
|
i += 2;
|
|
1831
|
-
i += runFrom(
|
|
2158
|
+
i += runFrom(shorthandRanges2(e), false, source[i]);
|
|
1832
2159
|
continue;
|
|
1833
2160
|
}
|
|
1834
2161
|
const uni = readUnicodeEscape(source, i);
|
|
@@ -1837,8 +2164,8 @@ function parseSeqParts(source) {
|
|
|
1837
2164
|
cp2 = uni.cp;
|
|
1838
2165
|
i = uni.next;
|
|
1839
2166
|
} else if (e === void 0) return null;
|
|
1840
|
-
else if (e in
|
|
1841
|
-
cp2 =
|
|
2167
|
+
else if (e in CLASS_ESCAPES2) {
|
|
2168
|
+
cp2 = CLASS_ESCAPES2[e];
|
|
1842
2169
|
i += 2;
|
|
1843
2170
|
} else if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
1844
2171
|
else {
|
|
@@ -1945,7 +2272,7 @@ function rangesSubset(sub, sup) {
|
|
|
1945
2272
|
}
|
|
1946
2273
|
function parseClassOperand(body) {
|
|
1947
2274
|
if (body === "\\d" || body === "\\w" || body === "\\s") {
|
|
1948
|
-
return { ranges:
|
|
2275
|
+
return { ranges: shorthandRanges2(body[1]), negated: false };
|
|
1949
2276
|
}
|
|
1950
2277
|
if (body.length >= 2 && body[0] === "[" && body[body.length - 1] === "]") {
|
|
1951
2278
|
let inner = body.slice(1, -1);
|
|
@@ -2378,7 +2705,7 @@ function parseScanShapeCore(source) {
|
|
|
2378
2705
|
}
|
|
2379
2706
|
m = /^\\([dws])([+*])$/.exec(source);
|
|
2380
2707
|
if (m) {
|
|
2381
|
-
return { kind: "chars", ranges:
|
|
2708
|
+
return { kind: "chars", ranges: shorthandRanges2(m[1]), minOne: m[2] === "+" };
|
|
2382
2709
|
}
|
|
2383
2710
|
m = /^(\[(?:\\.|[^\]])+\]|\\[dws])(\[(?:\\.|[^\]])+\]|\\[dws])\*$/.exec(source);
|
|
2384
2711
|
if (m) {
|
|
@@ -2920,21 +3247,22 @@ function emitScannableTerminal(shape, c) {
|
|
|
2920
3247
|
}
|
|
2921
3248
|
|
|
2922
3249
|
// src/compiler/inline-build.ts
|
|
2923
|
-
var MK_BUILD_RE = /^\(\s*(
|
|
3250
|
+
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*$/;
|
|
2924
3251
|
function escapeRegExp(s) {
|
|
2925
3252
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2926
3253
|
}
|
|
2927
3254
|
function looseMkBuildRe(type) {
|
|
2928
3255
|
return new RegExp(
|
|
2929
|
-
String.raw`^\(\s*(
|
|
3256
|
+
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*$`
|
|
2930
3257
|
);
|
|
2931
3258
|
}
|
|
2932
3259
|
function analyzeMkInlineBuild(def) {
|
|
2933
3260
|
if (!def.build) return null;
|
|
3261
|
+
if (def.type === void 0) return null;
|
|
2934
3262
|
const src = (def.buildSrc ?? def.build.toString()).trim();
|
|
2935
3263
|
const strict = src.match(MK_BUILD_RE);
|
|
2936
3264
|
if (strict) {
|
|
2937
|
-
const mkType = strict[
|
|
3265
|
+
const mkType = strict[6];
|
|
2938
3266
|
return mkType === def.type ? def.type : null;
|
|
2939
3267
|
}
|
|
2940
3268
|
if (looseMkBuildRe(def.type).test(src)) return def.type;
|
|
@@ -3269,8 +3597,9 @@ function planDisjointDispatch(parsers) {
|
|
|
3269
3597
|
}
|
|
3270
3598
|
return total >= SWITCH_MIN_CASES ? { kind: "switch", cases } : { kind: "if" };
|
|
3271
3599
|
}
|
|
3272
|
-
function captureRestoreBody(mL, mR, mTl, mLg) {
|
|
3273
|
-
const
|
|
3600
|
+
function captureRestoreBody(mL, mR, mTl, mLg, mF = null) {
|
|
3601
|
+
const fieldRestore = mF ? `; if (_ctx._fields) _ctx._fields.length = ${mF}` : "";
|
|
3602
|
+
const base = `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${mL}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${mR}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${mTl}${fieldRestore}`;
|
|
3274
3603
|
return mLg ? `${base}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${mLg}` : base;
|
|
3275
3604
|
}
|
|
3276
3605
|
function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
|
|
@@ -3318,6 +3647,7 @@ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
3318
3647
|
// Delegating wrappers: defer to the wrapped parser.
|
|
3319
3648
|
case "transform":
|
|
3320
3649
|
case "label":
|
|
3650
|
+
case "field":
|
|
3321
3651
|
case "expect":
|
|
3322
3652
|
case "withCtx":
|
|
3323
3653
|
case "grammar":
|
|
@@ -3364,6 +3694,7 @@ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
3364
3694
|
case "optional":
|
|
3365
3695
|
case "transform":
|
|
3366
3696
|
case "label":
|
|
3697
|
+
case "field":
|
|
3367
3698
|
case "expect":
|
|
3368
3699
|
case "withCtx":
|
|
3369
3700
|
case "grammar":
|
|
@@ -3401,22 +3732,25 @@ function emitFallible(inner, ctx, pos, swallow = false) {
|
|
|
3401
3732
|
ctx.recordFail = savedRecord;
|
|
3402
3733
|
const ind0 = ind(ctx);
|
|
3403
3734
|
const needsRollback = ctx.capturing && mayLeavePartialCapture(inner);
|
|
3735
|
+
const needsFieldRollback = needsRollback && parserHasOwnFields(inner);
|
|
3404
3736
|
const mL = needsRollback ? v(ctx, "_fcl") : null;
|
|
3405
3737
|
const mR = needsRollback ? v(ctx, "_fcr") : null;
|
|
3406
3738
|
const mTl = needsRollback ? v(ctx, "_fctl") : null;
|
|
3739
|
+
const mF = needsFieldRollback ? v(ctx, "_fcf") : null;
|
|
3407
3740
|
const stmts = [
|
|
3408
3741
|
`${ind0}let ${okV} = false, ${valV}, ${endV} = ${pos}`,
|
|
3409
3742
|
...mL ? [
|
|
3410
3743
|
`${ind0}const ${mL} = _ctx._cstLeaves?.length ?? 0`,
|
|
3411
3744
|
`${ind0}const ${mR} = _ctx._cstRawChildren?.length ?? 0`,
|
|
3412
|
-
`${ind0}const ${mTl} = _ctx._cstTriviaLog?.length ?? 0
|
|
3745
|
+
`${ind0}const ${mTl} = _ctx._cstTriviaLog?.length ?? 0`,
|
|
3746
|
+
...mF ? [`${ind0}const ${mF} = _ctx._fields?.length ?? 0`] : []
|
|
3413
3747
|
] : [],
|
|
3414
3748
|
`${ind0}${lbl}: {`,
|
|
3415
3749
|
...r.stmts,
|
|
3416
3750
|
`${ind0} ${valV} = ${r.valueVar}; ${endV} = ${r.endVar}; ${okV} = true`,
|
|
3417
3751
|
`${ind0}}`,
|
|
3418
3752
|
...mL ? [
|
|
3419
|
-
`${ind0}if (!${okV}) { ${captureRestoreBody(mL, mR, mTl, null)} }`
|
|
3753
|
+
`${ind0}if (!${okV}) { ${captureRestoreBody(mL, mR, mTl, null, mF)} }`
|
|
3420
3754
|
] : []
|
|
3421
3755
|
];
|
|
3422
3756
|
return { stmts, okVar: okV, valVar: valV, endVar: endV };
|
|
@@ -3643,6 +3977,7 @@ function failsAtStart(p) {
|
|
|
3643
3977
|
return true;
|
|
3644
3978
|
case "transform":
|
|
3645
3979
|
case "label":
|
|
3980
|
+
case "field":
|
|
3646
3981
|
return failsAtStart(d.parser);
|
|
3647
3982
|
default:
|
|
3648
3983
|
return false;
|
|
@@ -3662,6 +3997,7 @@ function canMatchEmptyAtStart(p) {
|
|
|
3662
3997
|
return true;
|
|
3663
3998
|
case "transform":
|
|
3664
3999
|
case "label":
|
|
4000
|
+
case "field":
|
|
3665
4001
|
return canMatchEmptyAtStart(d.parser);
|
|
3666
4002
|
case "literal":
|
|
3667
4003
|
return d.value.length === 0;
|
|
@@ -3844,11 +4180,13 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
3844
4180
|
const skipCond = gateCond ? `!${resOkV} && ${gateCond}` : `!${resOkV}`;
|
|
3845
4181
|
const armHasAutoNot = !!(autoNot && autoNot.length > 0);
|
|
3846
4182
|
const armNeedsRollback = ctx.capturing && (mayLeavePartialCapture(p) || armHasAutoNot && capturesLeaf(p));
|
|
4183
|
+
const armNeedsFieldRollback = armNeedsRollback && parserHasOwnFields(p);
|
|
3847
4184
|
const markLeaves = armNeedsRollback ? v(ctx, "_cml") : null;
|
|
3848
4185
|
const markRaw = armNeedsRollback ? v(ctx, "_cmr") : null;
|
|
3849
4186
|
const markTl = armNeedsRollback ? v(ctx, "_cmtl") : null;
|
|
3850
4187
|
const markLog = armNeedsRollback ? v(ctx, "_cmlg") : null;
|
|
3851
|
-
const
|
|
4188
|
+
const markFields = armNeedsFieldRollback ? v(ctx, "_cmf") : null;
|
|
4189
|
+
const rollback = markLeaves ? captureRestoreBody(markLeaves, markRaw, markTl, markLog, markFields) : "";
|
|
3852
4190
|
const failSlot = atStart ? staticFx : "_ctx._fx";
|
|
3853
4191
|
stmts.push(`${ind0}if (${skipCond}) {`);
|
|
3854
4192
|
if (fsGuard) stmts.push(`${ind(ctx)}if (${fsGuard}) {`);
|
|
@@ -3858,7 +4196,8 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
3858
4196
|
`${ind(ctx)}const ${markLeaves} = _ctx._cstLeaves?.length ?? 0`,
|
|
3859
4197
|
`${ind(ctx)}const ${markRaw} = _ctx._cstRawChildren?.length ?? 0`,
|
|
3860
4198
|
`${ind(ctx)}const ${markTl} = _ctx._cstTriviaLog?.length ?? 0`,
|
|
3861
|
-
`${ind(ctx)}const ${markLog} = _ctx._triviaLog?.length ?? 0
|
|
4199
|
+
`${ind(ctx)}const ${markLog} = _ctx._triviaLog?.length ?? 0`,
|
|
4200
|
+
...markFields ? [`${ind(ctx)}const ${markFields} = _ctx._fields?.length ?? 0`] : []
|
|
3862
4201
|
);
|
|
3863
4202
|
}
|
|
3864
4203
|
const { stmts: armStmts, okVar, valVar, endVar } = emitFallible(p, ctx, pos, atStart);
|
|
@@ -4251,6 +4590,9 @@ function emitToken(def, ctx, pos) {
|
|
|
4251
4590
|
};
|
|
4252
4591
|
}
|
|
4253
4592
|
function emitNode(def, ctx, pos) {
|
|
4593
|
+
if (def.type === void 0) {
|
|
4594
|
+
throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
|
|
4595
|
+
}
|
|
4254
4596
|
const structural = def.build === void 0;
|
|
4255
4597
|
const mkType = structural ? null : analyzeMkInlineBuild(def);
|
|
4256
4598
|
let buildIdx = null;
|
|
@@ -4262,25 +4604,36 @@ function emitNode(def, ctx, pos) {
|
|
|
4262
4604
|
const i = ind(ctx);
|
|
4263
4605
|
const capturesTrivia = mkType !== null || !structural && buildReadsTrivia(def);
|
|
4264
4606
|
const clonesState = !structural && buildReadsState(def);
|
|
4607
|
+
const hasFields = parserHasOwnFields(def.parser);
|
|
4608
|
+
const capturesFields = hasFields && !structural && buildReadsFields(def);
|
|
4265
4609
|
const chV = v(ctx, "_ch");
|
|
4266
4610
|
const rawV = v(ctx, "_raw");
|
|
4267
4611
|
const capTLv = structural ? v(ctx, "_ctl") : null;
|
|
4268
4612
|
const capSTv = structural ? v(ctx, "_cst") : null;
|
|
4613
|
+
const capFv = structural && hasFields ? v(ctx, "_cf") : null;
|
|
4269
4614
|
const tlV = capturesTrivia || structural ? v(ctx, "_tl") : "_EMPTY_TL";
|
|
4270
4615
|
if (!capturesTrivia) ctx.needsEmptyTl = true;
|
|
4271
4616
|
const sc = v(ctx, "_sc"), sl = v(ctx, "_sl"), sr = v(ctx, "_sr"), st = v(ctx, "_st"), stl = v(ctx, "_stl");
|
|
4272
4617
|
if (structural) ctx.needsHostReads = true;
|
|
4273
|
-
const
|
|
4618
|
+
const hostTriviaGate = `_ctx.build !== undefined && (_ctx.build._parsemanCaptureTrivia !== undefined ? _ctx.build._parsemanCaptureTrivia(${JSON.stringify(def.type)}) : (_ctx._pmCapTL ??= _hostReads(_ctx.build, 5)))`;
|
|
4619
|
+
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)` : ""}
|
|
4274
4620
|
${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capturesTrivia ? `${i}const ${chV} = [], ${rawV} = [], ${tlV} = []` : `${i}const ${chV} = [], ${rawV} = []`;
|
|
4275
4621
|
const innerTl = structural ? `${capTLv} ? ${tlV} : undefined` : capturesTrivia ? tlV : "undefined";
|
|
4622
|
+
const fieldsOn = structural ? capFv ?? "false" : capturesFields ? "true" : "false";
|
|
4623
|
+
const sf = hasFields ? v(ctx, "_sf") : null;
|
|
4624
|
+
const fArr = hasFields ? v(ctx, "_fa") : null;
|
|
4625
|
+
const fObj = hasFields ? v(ctx, "_fields") : "undefined";
|
|
4276
4626
|
const stmts = [
|
|
4277
4627
|
allocStmt,
|
|
4278
|
-
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog`,
|
|
4279
|
-
`${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true; _ctx._cstTriviaLog = ${innerTl}`
|
|
4628
|
+
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog${sf ? `, ${sf} = _ctx._fields` : ""}`,
|
|
4629
|
+
`${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true; _ctx._cstTriviaLog = ${innerTl}${sf ? `; _ctx._fields = ${fieldsOn} ? [] : undefined` : ""}`
|
|
4280
4630
|
];
|
|
4281
4631
|
const { stmts: innerStmts, okVar, endVar } = emitFallible(def.parser, ctx, pos);
|
|
4282
4632
|
stmts.push(...innerStmts);
|
|
4283
|
-
|
|
4633
|
+
if (sf && fArr) {
|
|
4634
|
+
stmts.push(`${i}const ${fArr} = _ctx._fields`);
|
|
4635
|
+
}
|
|
4636
|
+
stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}${sf ? `; _ctx._fields = ${sf}` : ""}`);
|
|
4284
4637
|
stmts.push(...emitIfFail(ctx, `!${okVar}`, propagateFailBody(ctx)));
|
|
4285
4638
|
let stV = "undefined";
|
|
4286
4639
|
if (structural) {
|
|
@@ -4290,14 +4643,33 @@ ${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capt
|
|
|
4290
4643
|
stV = v(ctx, "_nst");
|
|
4291
4644
|
stmts.push(`${i}const ${stV} = _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
|
|
4292
4645
|
}
|
|
4646
|
+
if (sf && fArr) {
|
|
4647
|
+
const fe = v(ctx, "_fe");
|
|
4648
|
+
const cur = v(ctx, "_fc");
|
|
4649
|
+
stmts.push(
|
|
4650
|
+
`${i}let ${fObj} = undefined`,
|
|
4651
|
+
`${i}if (${fArr} && ${fArr}.length) {`,
|
|
4652
|
+
`${i} ${fObj} = {}`,
|
|
4653
|
+
`${i} for (const ${fe} of ${fArr}) {`,
|
|
4654
|
+
`${i} const ${cur} = ${fObj}[${fe}.name], _entry = { value: ${fe}.value, span: ${fe}.span }`,
|
|
4655
|
+
`${i} if (${cur} === undefined) ${fObj}[${fe}.name] = _entry`,
|
|
4656
|
+
`${i} else if (Array.isArray(${cur})) ${cur}.push(_entry)`,
|
|
4657
|
+
`${i} else ${fObj}[${fe}.name] = [${cur}, _entry]`,
|
|
4658
|
+
`${i} }`,
|
|
4659
|
+
`${i}}`
|
|
4660
|
+
);
|
|
4661
|
+
}
|
|
4293
4662
|
const ndV = v(ctx, "_nd");
|
|
4294
|
-
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}, ${
|
|
4295
|
-
const ndExpr = ctx.ns || structural ? `_ctx.build !== undefined ? _ctx.build(${JSON.stringify(def.type)}, ${chV}, ${
|
|
4296
|
-
const
|
|
4663
|
+
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})`;
|
|
4664
|
+
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;
|
|
4665
|
+
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;
|
|
4666
|
+
const unwrapExpr = `${chV}.length === 1 ? (${chV}[0] !== null && typeof ${chV}[0] === 'object' && ${chV}[0]._tag === 'leaf' ? ${chV}[0].value : ${chV}[0]) : (${ndExpr})`;
|
|
4667
|
+
const collapseExpr = `${chV}.length === 1 ? ${chV}[0] : (${ndExpr})`;
|
|
4668
|
+
const finalExpr = def.unwrap ? unwrapExpr : def.collapse ? collapseExpr : hostCollapseExpr;
|
|
4297
4669
|
stmts.push(
|
|
4298
4670
|
`${i}const ${ndV} = ${finalExpr}`,
|
|
4299
4671
|
`${i}if (${sc}) ${sc}.push(${ndV})`,
|
|
4300
|
-
`${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} } })`
|
|
4672
|
+
`${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} } })`
|
|
4301
4673
|
);
|
|
4302
4674
|
return { stmts, valueVar: ndV, endVar };
|
|
4303
4675
|
}
|
|
@@ -4512,6 +4884,17 @@ function emitDispatch(p, ctx, pos) {
|
|
|
4512
4884
|
endVar: inner.endVar
|
|
4513
4885
|
};
|
|
4514
4886
|
}
|
|
4887
|
+
case "field": {
|
|
4888
|
+
const inner = emit(def.parser, ctx, pos);
|
|
4889
|
+
return {
|
|
4890
|
+
stmts: [
|
|
4891
|
+
...inner.stmts,
|
|
4892
|
+
`${ind(ctx)}if (_ctx._fields) _ctx._fields.push({ name: ${JSON.stringify(def.name)}, value: ${inner.valueVar}, span: { start: ${pos}, end: ${inner.endVar} } })`
|
|
4893
|
+
],
|
|
4894
|
+
valueVar: inner.valueVar,
|
|
4895
|
+
endVar: inner.endVar
|
|
4896
|
+
};
|
|
4897
|
+
}
|
|
4515
4898
|
case "grammar": {
|
|
4516
4899
|
const savedTrivia = ctx.activeTrivia;
|
|
4517
4900
|
const savedKindLabels = ctx.triviaKindLabels;
|
|
@@ -4613,6 +4996,7 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
4613
4996
|
case "trivia":
|
|
4614
4997
|
case "token":
|
|
4615
4998
|
case "label":
|
|
4999
|
+
case "field":
|
|
4616
5000
|
case "optional":
|
|
4617
5001
|
case "many":
|
|
4618
5002
|
case "oneOrMore":
|
|
@@ -4649,6 +5033,7 @@ function childrenOf(def) {
|
|
|
4649
5033
|
case "trivia":
|
|
4650
5034
|
case "token":
|
|
4651
5035
|
case "label":
|
|
5036
|
+
case "field":
|
|
4652
5037
|
case "grammar":
|
|
4653
5038
|
case "not":
|
|
4654
5039
|
case "node":
|
|
@@ -4890,6 +5275,11 @@ function assertRuleName(name) {
|
|
|
4890
5275
|
);
|
|
4891
5276
|
}
|
|
4892
5277
|
}
|
|
5278
|
+
function publicRuleWrapperSource(rule, fnSource) {
|
|
5279
|
+
const labels = rule._meta.triviaKindLabels;
|
|
5280
|
+
if (labels === void 0) return fnSource;
|
|
5281
|
+
return `Object.assign(${fnSource}, { _meta: { triviaKindLabels: ${JSON.stringify(labels)} } })`;
|
|
5282
|
+
}
|
|
4893
5283
|
function compileRuleMap(ruleMap) {
|
|
4894
5284
|
for (const [, rule] of ruleMap) markUnusedValues(rule);
|
|
4895
5285
|
const ctx = {
|
|
@@ -4922,7 +5312,7 @@ function compileRuleMap(ruleMap) {
|
|
|
4922
5312
|
ruleNames.set(rule, n === 0 ? base : `${base}$${n}`);
|
|
4923
5313
|
}
|
|
4924
5314
|
ctx.ruleNames = ruleNames;
|
|
4925
|
-
const perEntry = ruleMap.map(([key, rule]) => ({ key, r: emit(rule, ctx, "_pos") }));
|
|
5315
|
+
const perEntry = ruleMap.map(([key, rule]) => ({ key, rule, r: emit(rule, ctx, "_pos") }));
|
|
4926
5316
|
const derivedSrcs = ctx.mapFnSrcs.length === ctx.mapFns.length && ctx.mapFnSrcs.every((s) => s !== null) ? ctx.mapFnSrcs : void 0;
|
|
4927
5317
|
const buildCovered = ctx.buildFns.length === 0 || ctx.buildSrcs.every((s) => s !== null);
|
|
4928
5318
|
const buildSources = ctx.buildFns.length === 0 ? void 0 : ctx.buildSrcs;
|
|
@@ -4952,7 +5342,10 @@ function compileRuleMap(ruleMap) {
|
|
|
4952
5342
|
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
4953
5343
|
`}`
|
|
4954
5344
|
].join("\n");
|
|
4955
|
-
const objBody = perEntry.map(({ key, r }) =>
|
|
5345
|
+
const objBody = perEntry.map(({ key, rule, r }) => {
|
|
5346
|
+
const src = publicRuleWrapperSource(rule, entryFnText(r));
|
|
5347
|
+
return ` ${JSON.stringify(key)}: ${src.split("\n").join("\n ")}`;
|
|
5348
|
+
}).join(",\n");
|
|
4956
5349
|
const replacement = [
|
|
4957
5350
|
`/* @__PURE__ */ (() => {`,
|
|
4958
5351
|
...hoistedDecls,
|
|
@@ -5065,7 +5458,7 @@ function compileLinkable(ruleMapArg, ns) {
|
|
|
5065
5458
|
ctx.recordFail = savedRec;
|
|
5066
5459
|
pushNamedFnDecl(ctx, fn, body.stmts, body.valueVar, body.endVar);
|
|
5067
5460
|
}
|
|
5068
|
-
perEntry.push({ key, r: emitNamedFnCall(ctx, fn, "_pos") });
|
|
5461
|
+
perEntry.push({ key, rule, r: emitNamedFnCall(ctx, fn, "_pos") });
|
|
5069
5462
|
}
|
|
5070
5463
|
if (ctx.runtimeParsers.length !== 0) return null;
|
|
5071
5464
|
const mfSrcs = ctx.mapFns.length > 0 && ctx.mapFnSrcs.every((s) => s !== null) ? ctx.mapFnSrcs : null;
|
|
@@ -5088,14 +5481,14 @@ function compileLinkable(ruleMapArg, ns) {
|
|
|
5088
5481
|
...privateFns
|
|
5089
5482
|
].filter(Boolean);
|
|
5090
5483
|
const wrappers = /* @__PURE__ */ new Map();
|
|
5091
|
-
for (const { key, r } of perEntry) {
|
|
5092
|
-
wrappers.set(key, [
|
|
5484
|
+
for (const { key, rule, r } of perEntry) {
|
|
5485
|
+
wrappers.set(key, publicRuleWrapperSource(rule, [
|
|
5093
5486
|
`function(input, _pos, _ctx) {`,
|
|
5094
5487
|
` let pos = _pos`,
|
|
5095
5488
|
...r.stmts,
|
|
5096
5489
|
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
5097
5490
|
`}`
|
|
5098
|
-
].join("\n"));
|
|
5491
|
+
].join("\n")));
|
|
5099
5492
|
}
|
|
5100
5493
|
const firstSets = /* @__PURE__ */ new Map();
|
|
5101
5494
|
for (const [key, rule] of ruleMap) {
|
|
@@ -5270,6 +5663,7 @@ function childrenOf2(def) {
|
|
|
5270
5663
|
case "trivia":
|
|
5271
5664
|
case "token":
|
|
5272
5665
|
case "label":
|
|
5666
|
+
case "field":
|
|
5273
5667
|
case "not":
|
|
5274
5668
|
case "node":
|
|
5275
5669
|
case "expect":
|
|
@@ -5355,6 +5749,7 @@ function evalRuleMapIR(ir) {
|
|
|
5355
5749
|
"skip",
|
|
5356
5750
|
"trivia",
|
|
5357
5751
|
"label",
|
|
5752
|
+
"field",
|
|
5358
5753
|
"expect",
|
|
5359
5754
|
"_tf",
|
|
5360
5755
|
"_nd",
|
|
@@ -5381,6 +5776,7 @@ function evalRuleMapIR(ir) {
|
|
|
5381
5776
|
skip,
|
|
5382
5777
|
trivia,
|
|
5383
5778
|
label,
|
|
5779
|
+
field,
|
|
5384
5780
|
expect,
|
|
5385
5781
|
_tf,
|
|
5386
5782
|
_nd
|
|
@@ -5514,6 +5910,8 @@ ${body}
|
|
|
5514
5910
|
return `token(${kid(def.parser)})`;
|
|
5515
5911
|
case "label":
|
|
5516
5912
|
return `label(${JSON.stringify(def.label)}, ${kid(def.parser)})`;
|
|
5913
|
+
case "field":
|
|
5914
|
+
return `field(${JSON.stringify(def.name)}, ${kid(def.parser)})`;
|
|
5517
5915
|
case "expect":
|
|
5518
5916
|
return `expect(${kid(def.parser)}${def.label !== void 0 ? `, ${JSON.stringify(def.label)}` : ""})`;
|
|
5519
5917
|
case "skip":
|
|
@@ -5526,7 +5924,11 @@ ${body}
|
|
|
5526
5924
|
}
|
|
5527
5925
|
case "node": {
|
|
5528
5926
|
if (def.build !== void 0 && def.buildSrc === void 0) throw new Unserializable("node build without buildSrc");
|
|
5529
|
-
const opts = def.collapse ? `, { collapse: true }` : "";
|
|
5927
|
+
const opts = def.unwrap || def.collapse ? `, { ${def.unwrap ? "unwrap: true" : "collapse: true"} }` : "";
|
|
5928
|
+
if (def.type === void 0) {
|
|
5929
|
+
if (def.buildSrc !== void 0) throw new Unserializable("inferred node build without inferred type");
|
|
5930
|
+
return opts ? `node(${kid(def.parser)}, undefined${opts})` : `node(${kid(def.parser)})`;
|
|
5931
|
+
}
|
|
5530
5932
|
if (def.buildSrc !== void 0) return `_nd(${JSON.stringify(def.type)}, ${kid(def.parser)}, ${JSON.stringify(def.buildSrc)}${opts})`;
|
|
5531
5933
|
return opts ? `node(${JSON.stringify(def.type)}, ${kid(def.parser)}, undefined${opts})` : `node(${JSON.stringify(def.type)}, ${kid(def.parser)})`;
|
|
5532
5934
|
}
|
|
@@ -5553,8 +5955,9 @@ function fusedBody(pieces) {
|
|
|
5553
5955
|
}
|
|
5554
5956
|
}
|
|
5555
5957
|
const contributing = new Set(winner.values());
|
|
5556
|
-
const
|
|
5557
|
-
const
|
|
5958
|
+
const contributingPieces = [...contributing];
|
|
5959
|
+
const needsEmptyTl = contributingPieces.some((p) => p.needsEmptyTl);
|
|
5960
|
+
const needsHostReads = contributingPieces.some((p) => p.needsHostReads);
|
|
5558
5961
|
const lines = [
|
|
5559
5962
|
// Shared sentinel protocol (must match NAMED_FN_FAIL / NAMED_FN_END in codegen).
|
|
5560
5963
|
"const _pfFail = {}",
|
|
@@ -5562,7 +5965,7 @@ function fusedBody(pieces) {
|
|
|
5562
5965
|
...needsEmptyTl ? ["const _EMPTY_TL = Object.freeze([])"] : [],
|
|
5563
5966
|
...needsHostReads ? [HOST_READS_DECL] : [],
|
|
5564
5967
|
// Each contributing artifact's namespaced private prelude (regexes, _pf, …).
|
|
5565
|
-
...[...
|
|
5968
|
+
...[...new Set(contributingPieces.flatMap((p) => p.prelude))],
|
|
5566
5969
|
// The winning `_r_<Name>` function for each rule (one per name → no redeclare).
|
|
5567
5970
|
...[...winner].map(([k, p]) => p.ruleFns.get(k))
|
|
5568
5971
|
];
|
|
@@ -5585,7 +5988,7 @@ function fusedBody(pieces) {
|
|
|
5585
5988
|
}
|
|
5586
5989
|
);
|
|
5587
5990
|
const env = {};
|
|
5588
|
-
for (const p of
|
|
5991
|
+
for (const p of contributingPieces) {
|
|
5589
5992
|
if (p.mfFns.length) env[`${p.ns}mf`] = p.mfFns;
|
|
5590
5993
|
if (p.buildFns.length) env[`${p.ns}build`] = p.buildFns;
|
|
5591
5994
|
}
|
|
@@ -5633,6 +6036,7 @@ var SUPPORTED = {
|
|
|
5633
6036
|
sepBy: (...a) => sepBy(a[0], a[1]),
|
|
5634
6037
|
trivia: (...a) => trivia(a[0]),
|
|
5635
6038
|
label: (...a) => label(a[0], a[1]),
|
|
6039
|
+
field: (...a) => field(a[0], a[1]),
|
|
5636
6040
|
noTrivia: (...a) => noTrivia(a[0]),
|
|
5637
6041
|
token: (...a) => token(a[0]),
|
|
5638
6042
|
expect: (...a) => expect(a[0], a[1])
|
|
@@ -5653,19 +6057,20 @@ function scopeGet(scope, name, mfs) {
|
|
|
5653
6057
|
if (isCombinator(entry)) return entry;
|
|
5654
6058
|
return null;
|
|
5655
6059
|
}
|
|
5656
|
-
function
|
|
5657
|
-
if (expr.type !== "ObjectExpression") return
|
|
6060
|
+
function staticNodeOptions(expr) {
|
|
6061
|
+
if (expr.type !== "ObjectExpression") return void 0;
|
|
6062
|
+
const opts = {};
|
|
5658
6063
|
for (const prop of expr.properties) {
|
|
5659
6064
|
const p = prop;
|
|
5660
6065
|
if (p.computed) continue;
|
|
5661
6066
|
const key = p.key;
|
|
5662
6067
|
const name = key.type === "Identifier" ? key.name : key.type === "Literal" ? String(key.value) : void 0;
|
|
5663
|
-
if (name === "collapse") {
|
|
6068
|
+
if (name === "unwrap" || name === "collapse") {
|
|
5664
6069
|
const val = p.value;
|
|
5665
|
-
|
|
6070
|
+
if ((val.type === "Literal" || val.type === "BooleanLiteral") && val.value === true) opts[name] = true;
|
|
5666
6071
|
}
|
|
5667
6072
|
}
|
|
5668
|
-
return
|
|
6073
|
+
return opts.unwrap || opts.collapse ? opts : void 0;
|
|
5669
6074
|
}
|
|
5670
6075
|
function exprToCombi(node2, scope, code, mfs) {
|
|
5671
6076
|
if (node2.type === "Identifier") return scopeGet(scope, node2.name, mfs);
|
|
@@ -5715,18 +6120,22 @@ function exprToCombi(node2, scope, code, mfs) {
|
|
|
5715
6120
|
}
|
|
5716
6121
|
}
|
|
5717
6122
|
if (callee.name === "node" && code !== void 0) {
|
|
5718
|
-
const [
|
|
5719
|
-
if (!
|
|
5720
|
-
const
|
|
5721
|
-
|
|
6123
|
+
const [firstArg, secondArg, thirdArg, fourthArg] = node2.arguments;
|
|
6124
|
+
if (!firstArg || firstArg.type === "SpreadElement") return null;
|
|
6125
|
+
const firstVal = anyValue(firstArg, scope, code, mfs);
|
|
6126
|
+
const explicitType = typeof firstVal === "string" ? firstVal : void 0;
|
|
6127
|
+
const parserArg = explicitType !== void 0 ? secondArg : firstArg;
|
|
6128
|
+
const buildArg = explicitType !== void 0 ? thirdArg : secondArg;
|
|
6129
|
+
const optsArg = explicitType !== void 0 ? fourthArg : thirdArg;
|
|
6130
|
+
if (!parserArg || parserArg.type === "SpreadElement") return null;
|
|
5722
6131
|
const inner = anyValue(parserArg, scope, code, mfs);
|
|
5723
6132
|
if (!isCombinator(inner)) return null;
|
|
5724
6133
|
const be = buildArg;
|
|
5725
6134
|
const hasBuild = be !== void 0 && be.type !== "SpreadElement" && !(be.type === "Identifier" && be.name === "undefined");
|
|
5726
6135
|
const buildSrc = hasBuild ? code.slice(be.start, be.end) : void 0;
|
|
5727
|
-
const
|
|
6136
|
+
const opts = optsArg !== void 0 && optsArg.type !== "SpreadElement" ? staticNodeOptions(optsArg) : void 0;
|
|
5728
6137
|
try {
|
|
5729
|
-
const combi = node(
|
|
6138
|
+
const combi = explicitType !== void 0 ? node(explicitType, inner, hasBuild ? () => null : void 0, opts) : node(inner, hasBuild ? () => null : void 0, opts);
|
|
5730
6139
|
if (combi._def.tag === "node" && buildSrc !== void 0) combi._def.buildSrc = buildSrc;
|
|
5731
6140
|
return combi;
|
|
5732
6141
|
} catch {
|
|
@@ -5992,7 +6401,9 @@ function evaluateParserFactory(factoryNode, scope, code, mapFnSources) {
|
|
|
5992
6401
|
if (!keys) return null;
|
|
5993
6402
|
const ruleRefs = /* @__PURE__ */ new Map();
|
|
5994
6403
|
const tagRef = (r, name) => {
|
|
6404
|
+
;
|
|
5995
6405
|
r._ruleName = name;
|
|
6406
|
+
if (r._def.tag === "node" && r._def.type === void 0) r._def.type = name;
|
|
5996
6407
|
};
|
|
5997
6408
|
for (const key of keys) {
|
|
5998
6409
|
if (!ruleRefs.has(key)) {
|
|
@@ -6024,6 +6435,7 @@ function evaluateParserFactory(factoryNode, scope, code, mapFnSources) {
|
|
|
6024
6435
|
for (const [key, e] of finalByKey) {
|
|
6025
6436
|
const val = anyValue(e.value, e.scope, e.code, mapFnSources);
|
|
6026
6437
|
if (!isCombinator(val)) return null;
|
|
6438
|
+
tagRef(val, key);
|
|
6027
6439
|
ruleRefs.get(key).define(val);
|
|
6028
6440
|
}
|
|
6029
6441
|
return ruleRefs;
|