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.cjs
CHANGED
|
@@ -217,6 +217,13 @@ function ref() {
|
|
|
217
217
|
define(p) {
|
|
218
218
|
if (resolved) throw new Error("ref<T>() already defined");
|
|
219
219
|
resolved = p;
|
|
220
|
+
meta.firstSet = p._meta.firstSet;
|
|
221
|
+
meta.canMatchNewline = p._meta.canMatchNewline;
|
|
222
|
+
meta.isTrivia = p._meta.isTrivia;
|
|
223
|
+
if (p._meta.triviaKindLabels !== void 0) meta.triviaKindLabels = p._meta.triviaKindLabels;
|
|
224
|
+
else delete meta.triviaKindLabels;
|
|
225
|
+
if (p._meta.disjoint !== void 0) meta.disjoint = p._meta.disjoint;
|
|
226
|
+
else delete meta.disjoint;
|
|
220
227
|
}
|
|
221
228
|
};
|
|
222
229
|
return slot;
|
|
@@ -324,7 +331,8 @@ function saveCstMark(ctx) {
|
|
|
324
331
|
return {
|
|
325
332
|
raw: cstRawLen(ctx),
|
|
326
333
|
tlog: cstTlLen(ctx),
|
|
327
|
-
leaves: cstLeavesLen(ctx)
|
|
334
|
+
leaves: cstLeavesLen(ctx),
|
|
335
|
+
fields: ctx._fields?.length ?? 0
|
|
328
336
|
};
|
|
329
337
|
}
|
|
330
338
|
function rollbackBufList(b, keyMulti, keySingle, len) {
|
|
@@ -348,11 +356,13 @@ function rollbackCstCapture(ctx, mark) {
|
|
|
348
356
|
if (mark.tlog === 0) b.tl = void 0;
|
|
349
357
|
else b.tl.length = mark.tlog;
|
|
350
358
|
}
|
|
359
|
+
if (ctx._fields) ctx._fields.length = mark.fields;
|
|
351
360
|
return;
|
|
352
361
|
}
|
|
353
362
|
if (ctx._cstRawChildren) ctx._cstRawChildren.length = mark.raw;
|
|
354
363
|
if (ctx._cstTriviaLog) ctx._cstTriviaLog.length = mark.tlog;
|
|
355
364
|
if (ctx._cstLeaves) ctx._cstLeaves.length = mark.leaves;
|
|
365
|
+
if (ctx._fields) ctx._fields.length = mark.fields;
|
|
356
366
|
}
|
|
357
367
|
function pushCstTriviaEntry(ctx, start, end, kindIndex) {
|
|
358
368
|
const insertIdx = cstRawLen(ctx);
|
|
@@ -421,13 +431,12 @@ function literal(value, opts = {}) {
|
|
|
421
431
|
if (end > input.length) {
|
|
422
432
|
return failAt(ctx, [JSON.stringify(value)], pos);
|
|
423
433
|
}
|
|
424
|
-
const
|
|
425
|
-
|
|
426
|
-
if (matched) {
|
|
434
|
+
const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
|
|
435
|
+
if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
|
|
427
436
|
const span = { start: pos, end };
|
|
428
|
-
const leaf = { _tag: "leaf", value:
|
|
437
|
+
const leaf = { _tag: "leaf", value: matchedValue, span };
|
|
429
438
|
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
|
|
430
|
-
return { ok: true, value:
|
|
439
|
+
return { ok: true, value: matchedValue, span };
|
|
431
440
|
}
|
|
432
441
|
return failAt(ctx, [JSON.stringify(value)], pos);
|
|
433
442
|
}
|
|
@@ -440,10 +449,102 @@ function registerRegexAnalyzer(analyzer) {
|
|
|
440
449
|
firstSetAnalyzer = analyzer;
|
|
441
450
|
}
|
|
442
451
|
var permissiveFirstSet = () => ({ firstSet: any(), canMatchNewline: true });
|
|
452
|
+
var SCAN_BAIL_AT = 64;
|
|
453
|
+
var SPACE_RANGES = [
|
|
454
|
+
[9, 13],
|
|
455
|
+
[32, 32],
|
|
456
|
+
[160, 160],
|
|
457
|
+
[5760, 5760],
|
|
458
|
+
[8192, 8202],
|
|
459
|
+
[8232, 8233],
|
|
460
|
+
[8239, 8239],
|
|
461
|
+
[8287, 8287],
|
|
462
|
+
[12288, 12288],
|
|
463
|
+
[65279, 65279]
|
|
464
|
+
];
|
|
465
|
+
var CLASS_ESCAPES = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
466
|
+
function shorthandRanges(ch) {
|
|
467
|
+
if (ch === "d") return [[48, 57]];
|
|
468
|
+
if (ch === "s") return SPACE_RANGES;
|
|
469
|
+
return [[48, 57], [65, 90], [97, 122], [95, 95]];
|
|
470
|
+
}
|
|
471
|
+
function inRanges(cp, ranges) {
|
|
472
|
+
for (let i = 0; i < ranges.length; i++) {
|
|
473
|
+
const [lo, hi] = ranges[i];
|
|
474
|
+
if (cp >= lo && cp <= hi) return true;
|
|
475
|
+
}
|
|
476
|
+
return false;
|
|
477
|
+
}
|
|
478
|
+
function readClassRanges(body) {
|
|
479
|
+
if (body.startsWith("^")) return null;
|
|
480
|
+
const ranges = [];
|
|
481
|
+
let i = 0;
|
|
482
|
+
const readAtom = () => {
|
|
483
|
+
const ch = body[i];
|
|
484
|
+
if (ch === void 0) return null;
|
|
485
|
+
if (ch === "\\") {
|
|
486
|
+
const esc = body[i + 1];
|
|
487
|
+
if (esc === void 0) return null;
|
|
488
|
+
i += 2;
|
|
489
|
+
if (esc === "d" || esc === "w" || esc === "s") return { ranges: shorthandRanges(esc) };
|
|
490
|
+
if (esc in CLASS_ESCAPES) return { cp: CLASS_ESCAPES[esc] };
|
|
491
|
+
if (esc >= "a" && esc <= "z" || esc >= "A" && esc <= "Z") return null;
|
|
492
|
+
return { cp: esc.charCodeAt(0) };
|
|
493
|
+
}
|
|
494
|
+
i++;
|
|
495
|
+
return { cp: ch.charCodeAt(0) };
|
|
496
|
+
};
|
|
497
|
+
while (i < body.length) {
|
|
498
|
+
const lo = readAtom();
|
|
499
|
+
if (!lo) return null;
|
|
500
|
+
if ("ranges" in lo) {
|
|
501
|
+
ranges.push(...lo.ranges);
|
|
502
|
+
continue;
|
|
503
|
+
}
|
|
504
|
+
if (body[i] === "-" && body[i + 1] !== void 0 && body[i + 1] !== "]") {
|
|
505
|
+
i++;
|
|
506
|
+
const hi = readAtom();
|
|
507
|
+
if (!hi || "ranges" in hi) return null;
|
|
508
|
+
ranges.push([lo.cp, hi.cp]);
|
|
509
|
+
} else {
|
|
510
|
+
ranges.push([lo.cp, lo.cp]);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
return ranges.length ? ranges : null;
|
|
514
|
+
}
|
|
515
|
+
function shortScanner(source, flags) {
|
|
516
|
+
if (/[imsuvy]/.test(flags)) return null;
|
|
517
|
+
let ranges = null;
|
|
518
|
+
let quant = "";
|
|
519
|
+
if (source[0] === "[") {
|
|
520
|
+
let end = 1;
|
|
521
|
+
while (end < source.length && source[end] !== "]") {
|
|
522
|
+
if (source[end] === "\\") end += 2;
|
|
523
|
+
else end++;
|
|
524
|
+
}
|
|
525
|
+
if (source[end] !== "]") return null;
|
|
526
|
+
ranges = readClassRanges(source.slice(1, end));
|
|
527
|
+
quant = source.slice(end + 1);
|
|
528
|
+
} else if (source[0] === "\\" && (source[1] === "d" || source[1] === "w" || source[1] === "s")) {
|
|
529
|
+
ranges = shorthandRanges(source[1]);
|
|
530
|
+
quant = source.slice(2);
|
|
531
|
+
}
|
|
532
|
+
if (!ranges || quant !== "+" && quant !== "*") return null;
|
|
533
|
+
const minOne = quant === "+";
|
|
534
|
+
return (input, pos) => {
|
|
535
|
+
let end = pos;
|
|
536
|
+
while (end < input.length && inRanges(input.charCodeAt(end), ranges)) {
|
|
537
|
+
end++;
|
|
538
|
+
if (end - pos >= SCAN_BAIL_AT) return void 0;
|
|
539
|
+
}
|
|
540
|
+
return minOne && end === pos ? null : end;
|
|
541
|
+
};
|
|
542
|
+
}
|
|
443
543
|
function regex(pattern, flags = "") {
|
|
444
544
|
const source = typeof pattern === "string" ? pattern : pattern.source;
|
|
445
545
|
const resolvedFlags = typeof pattern === "string" ? flags : pattern.flags;
|
|
446
546
|
const anchored = new RegExp(source, "y" + resolvedFlags.replace(/[gy]/g, ""));
|
|
547
|
+
const scan = shortScanner(source, resolvedFlags);
|
|
447
548
|
const { firstSet, canMatchNewline } = (firstSetAnalyzer ?? permissiveFirstSet)(source);
|
|
448
549
|
const meta = { firstSet, canMatchNewline, isTrivia: false };
|
|
449
550
|
return {
|
|
@@ -451,6 +552,15 @@ function regex(pattern, flags = "") {
|
|
|
451
552
|
_meta: meta,
|
|
452
553
|
_def: { tag: "regex", source, flags: resolvedFlags },
|
|
453
554
|
parse(input, pos, ctx) {
|
|
555
|
+
const scanEnd = scan?.(input, pos);
|
|
556
|
+
if (scanEnd !== void 0) {
|
|
557
|
+
if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
|
|
558
|
+
const value = input.slice(pos, scanEnd);
|
|
559
|
+
const span2 = { start: pos, end: scanEnd };
|
|
560
|
+
const leaf2 = { _tag: "leaf", value, span: span2 };
|
|
561
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf2);
|
|
562
|
+
return { ok: true, value, span: span2 };
|
|
563
|
+
}
|
|
454
564
|
anchored.lastIndex = pos;
|
|
455
565
|
const m = anchored.exec(input);
|
|
456
566
|
if (m === null) {
|
|
@@ -631,13 +741,10 @@ function choice(...args) {
|
|
|
631
741
|
};
|
|
632
742
|
const strategy = disjoint || hasGates ? null : detectStrategy(parsers);
|
|
633
743
|
const autoNot = !disjoint && !hasGates && strategy?.tag === "firstMatch" ? computeAutoNot(parsers) : parsers.map(() => null);
|
|
634
|
-
let greedyRe = null;
|
|
635
744
|
let greedyLitMap = null;
|
|
636
745
|
let sortedParsers = null;
|
|
746
|
+
const asciiDispatch = disjoint ? buildAsciiDispatch(parsers) : null;
|
|
637
747
|
if (strategy?.tag === "greedyClassify") {
|
|
638
|
-
const regexDef = getCoreRegexDef(parsers[strategy.superIndex]);
|
|
639
|
-
const flags = "y" + regexDef.flags.replace(/[gy]/g, "");
|
|
640
|
-
greedyRe = new RegExp(regexDef.source, flags);
|
|
641
748
|
greedyLitMap = /* @__PURE__ */ new Map();
|
|
642
749
|
for (let i = 0; i < parsers.length; i++) {
|
|
643
750
|
if (i === strategy.superIndex) continue;
|
|
@@ -662,14 +769,21 @@ function choice(...args) {
|
|
|
662
769
|
const expected = [];
|
|
663
770
|
if (disjoint && pos < input.length) {
|
|
664
771
|
const code = input.codePointAt(pos);
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
if (
|
|
669
|
-
|
|
670
|
-
|
|
772
|
+
let parser2 = code < 128 ? asciiDispatch?.[code] ?? null : null;
|
|
773
|
+
if (!parser2) {
|
|
774
|
+
for (const p of parsers) {
|
|
775
|
+
if (inFirstSet(code, p._meta.firstSet)) {
|
|
776
|
+
parser2 = p;
|
|
777
|
+
break;
|
|
778
|
+
}
|
|
671
779
|
}
|
|
672
780
|
}
|
|
781
|
+
if (parser2) {
|
|
782
|
+
const result = parser2.parse(input, pos, ctx);
|
|
783
|
+
if (result.ok) return result;
|
|
784
|
+
expected.push(...result.expected);
|
|
785
|
+
return { ok: false, expected, span: { start: pos, end: pos } };
|
|
786
|
+
}
|
|
673
787
|
return {
|
|
674
788
|
ok: false,
|
|
675
789
|
expected: parsers.flatMap((p) => {
|
|
@@ -845,6 +959,19 @@ function areDisjoint(sets) {
|
|
|
845
959
|
if (intersects(sets[i], sets[j])) return false;
|
|
846
960
|
return true;
|
|
847
961
|
}
|
|
962
|
+
function buildAsciiDispatch(parsers) {
|
|
963
|
+
const table = Array(128).fill(null);
|
|
964
|
+
for (const parser2 of parsers) {
|
|
965
|
+
const fs2 = parser2._meta.firstSet;
|
|
966
|
+
if (fs2.kind !== "ranges") continue;
|
|
967
|
+
for (const { lo, hi } of fs2.ranges) {
|
|
968
|
+
for (let code = Math.max(0, lo); code <= Math.min(127, hi); code++) {
|
|
969
|
+
table[code] = parser2;
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
return table;
|
|
974
|
+
}
|
|
848
975
|
|
|
849
976
|
// src/cst/trivia-kinds.ts
|
|
850
977
|
function unwrapTrivia(p) {
|
|
@@ -966,15 +1093,16 @@ function recordTriviaChunks(ctx, chunks) {
|
|
|
966
1093
|
// src/combinators/trivia-skip.ts
|
|
967
1094
|
var NOOP_COMMIT = () => {
|
|
968
1095
|
};
|
|
1096
|
+
var fastTriviaCache = /* @__PURE__ */ new WeakMap();
|
|
969
1097
|
function needsDeferredTriviaCommit(ctx) {
|
|
970
1098
|
return ctx._triviaLog !== void 0 || ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0;
|
|
971
1099
|
}
|
|
972
1100
|
function saveTriviaMark(ctx) {
|
|
973
1101
|
const m = saveCstMark(ctx);
|
|
974
|
-
return { raw: m.raw, tlog: m.tlog, leaves: m.leaves, log: ctx._triviaLog ? ctx._triviaLog.length : 0 };
|
|
1102
|
+
return { raw: m.raw, tlog: m.tlog, leaves: m.leaves, fields: m.fields, log: ctx._triviaLog ? ctx._triviaLog.length : 0 };
|
|
975
1103
|
}
|
|
976
1104
|
function rollbackTrivia(ctx, mark) {
|
|
977
|
-
rollbackCstCapture(ctx, { raw: mark.raw, tlog: mark.tlog, leaves: mark.leaves });
|
|
1105
|
+
rollbackCstCapture(ctx, { raw: mark.raw, tlog: mark.tlog, leaves: mark.leaves, fields: mark.fields });
|
|
978
1106
|
if (ctx._triviaLog) ctx._triviaLog.length = mark.log;
|
|
979
1107
|
}
|
|
980
1108
|
function scanWithLabels(input, cur, ctx) {
|
|
@@ -992,6 +1120,8 @@ function scanWithLabels(input, cur, ctx) {
|
|
|
992
1120
|
function advanceTrivia(input, cur, ctx) {
|
|
993
1121
|
const triviaP = ctx.trivia;
|
|
994
1122
|
if (!triviaP) return cur;
|
|
1123
|
+
const fast = fastTriviaScanner(triviaP);
|
|
1124
|
+
if (fast) return fast(input, cur);
|
|
995
1125
|
if (ctx.triviaKindLabels) {
|
|
996
1126
|
const scan = scanWithLabels(input, cur, ctx);
|
|
997
1127
|
return scan.end;
|
|
@@ -1004,6 +1134,10 @@ function scanTrivia(input, cur, ctx) {
|
|
|
1004
1134
|
if (!triviaP) return { end: cur, commit: NOOP_COMMIT };
|
|
1005
1135
|
const log = ctx._triviaLog;
|
|
1006
1136
|
const captureTl = ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0);
|
|
1137
|
+
const fast = !ctx.triviaKindLabels ? fastTriviaScanner(triviaP) : null;
|
|
1138
|
+
if (fast && log === void 0 && !captureTl) {
|
|
1139
|
+
return { end: fast(input, cur), commit: NOOP_COMMIT };
|
|
1140
|
+
}
|
|
1007
1141
|
if (ctx.triviaKindLabels && (log !== void 0 || captureTl)) {
|
|
1008
1142
|
return scanWithLabels(input, cur, ctx);
|
|
1009
1143
|
}
|
|
@@ -1025,6 +1159,79 @@ function scanTrivia(input, cur, ctx) {
|
|
|
1025
1159
|
const tr = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
|
|
1026
1160
|
return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
|
|
1027
1161
|
}
|
|
1162
|
+
function fastTriviaScanner(trivia2) {
|
|
1163
|
+
const cached = fastTriviaCache.get(trivia2);
|
|
1164
|
+
if (cached !== void 0) return cached;
|
|
1165
|
+
const scanner = buildFastTriviaScanner(trivia2);
|
|
1166
|
+
fastTriviaCache.set(trivia2, scanner);
|
|
1167
|
+
return scanner;
|
|
1168
|
+
}
|
|
1169
|
+
function buildFastTriviaScanner(trivia2) {
|
|
1170
|
+
const core = trivia2._def.tag === "trivia" ? trivia2._def.parser : trivia2;
|
|
1171
|
+
const direct = regexTriviaScanner(core);
|
|
1172
|
+
if (direct) return direct;
|
|
1173
|
+
const repeat = core._def.tag === "oneOrMore" || core._def.tag === "many" && core._def.min >= 1 ? core._def.parser : null;
|
|
1174
|
+
if (!repeat) return null;
|
|
1175
|
+
const one = regexTriviaScanner(repeat);
|
|
1176
|
+
if (one) return loopScanner([one]);
|
|
1177
|
+
if (repeat._def.tag !== "choice") return null;
|
|
1178
|
+
const arms = repeat._def.parsers.map(regexTriviaScanner);
|
|
1179
|
+
if (arms.some((s) => s === null)) return null;
|
|
1180
|
+
return loopScanner(arms);
|
|
1181
|
+
}
|
|
1182
|
+
function loopScanner(arms) {
|
|
1183
|
+
return (input, cur) => {
|
|
1184
|
+
let pos = cur;
|
|
1185
|
+
scan: while (pos < input.length) {
|
|
1186
|
+
for (const arm of arms) {
|
|
1187
|
+
const end = arm(input, pos);
|
|
1188
|
+
if (end > pos) {
|
|
1189
|
+
pos = end;
|
|
1190
|
+
continue scan;
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
break;
|
|
1194
|
+
}
|
|
1195
|
+
return pos;
|
|
1196
|
+
};
|
|
1197
|
+
}
|
|
1198
|
+
function regexTriviaScanner(parser2) {
|
|
1199
|
+
if (parser2._def.tag !== "regex" || parser2._def.flags) return null;
|
|
1200
|
+
const ws = whitespaceSource(parser2._def.source);
|
|
1201
|
+
if (ws) return ws;
|
|
1202
|
+
return blockCommentSource(parser2._def.source) ? scanBlockComment : null;
|
|
1203
|
+
}
|
|
1204
|
+
function whitespaceSource(source) {
|
|
1205
|
+
const m = /^\[([ \\tnrf]+)\][*+]$/.exec(source);
|
|
1206
|
+
if (!m) return null;
|
|
1207
|
+
const chars = /* @__PURE__ */ new Set();
|
|
1208
|
+
for (let i = 0; i < m[1].length; i++) {
|
|
1209
|
+
const ch = m[1][i];
|
|
1210
|
+
if (ch !== "\\") {
|
|
1211
|
+
chars.add(ch.charCodeAt(0));
|
|
1212
|
+
continue;
|
|
1213
|
+
}
|
|
1214
|
+
const esc = m[1][++i];
|
|
1215
|
+
if (esc === "t") chars.add(9);
|
|
1216
|
+
else if (esc === "n") chars.add(10);
|
|
1217
|
+
else if (esc === "r") chars.add(13);
|
|
1218
|
+
else if (esc === "f") chars.add(12);
|
|
1219
|
+
else return null;
|
|
1220
|
+
}
|
|
1221
|
+
return (input, cur) => {
|
|
1222
|
+
let pos = cur;
|
|
1223
|
+
while (pos < input.length && chars.has(input.charCodeAt(pos))) pos++;
|
|
1224
|
+
return pos;
|
|
1225
|
+
};
|
|
1226
|
+
}
|
|
1227
|
+
function blockCommentSource(source) {
|
|
1228
|
+
return source === "\\/\\*(?:[^*]|\\*(?!\\/))*\\*\\/" || source === "\\/\\*[^]*?\\*\\/";
|
|
1229
|
+
}
|
|
1230
|
+
function scanBlockComment(input, cur) {
|
|
1231
|
+
if (input.charCodeAt(cur) !== 47 || input.charCodeAt(cur + 1) !== 42) return cur;
|
|
1232
|
+
const close = input.indexOf("*/", cur + 2);
|
|
1233
|
+
return close === -1 ? cur : close + 2;
|
|
1234
|
+
}
|
|
1028
1235
|
|
|
1029
1236
|
// src/combinators/sequence.ts
|
|
1030
1237
|
function sequence(...parsers) {
|
|
@@ -1163,11 +1370,15 @@ function optional(combinator) {
|
|
|
1163
1370
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
1164
1371
|
isTrivia: false
|
|
1165
1372
|
};
|
|
1373
|
+
const firstSetSkippable = !matchesEmpty(combinator);
|
|
1166
1374
|
return {
|
|
1167
1375
|
_tag: "optional",
|
|
1168
1376
|
_meta: meta,
|
|
1169
1377
|
_def: { tag: "optional", parser: combinator },
|
|
1170
1378
|
parse(input, pos, ctx) {
|
|
1379
|
+
if (firstSetSkippable && ctx._probe === void 0 && !startsFirstSet(combinator, input, pos)) {
|
|
1380
|
+
return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
1381
|
+
}
|
|
1171
1382
|
const mark = saveTriviaMark(ctx);
|
|
1172
1383
|
const result = combinator.parse(input, pos, ctx);
|
|
1173
1384
|
if (result.ok) return result;
|
|
@@ -1176,6 +1387,15 @@ function optional(combinator) {
|
|
|
1176
1387
|
}
|
|
1177
1388
|
};
|
|
1178
1389
|
}
|
|
1390
|
+
function startsFirstSet(combinator, input, pos) {
|
|
1391
|
+
const fs2 = combinator._meta.firstSet;
|
|
1392
|
+
if (fs2.kind === "any") return true;
|
|
1393
|
+
if (fs2.kind === "empty") return false;
|
|
1394
|
+
const code = input.codePointAt(pos);
|
|
1395
|
+
if (code === void 0) return false;
|
|
1396
|
+
for (const r of fs2.ranges) if (code >= r.lo && code <= r.hi) return true;
|
|
1397
|
+
return false;
|
|
1398
|
+
}
|
|
1179
1399
|
function sepBy(combinator, separator) {
|
|
1180
1400
|
const meta = {
|
|
1181
1401
|
firstSet: combinator._meta.firstSet,
|
|
@@ -1266,6 +1486,9 @@ function markUnusedValues(root) {
|
|
|
1266
1486
|
case "transform":
|
|
1267
1487
|
visit(def.parser, true);
|
|
1268
1488
|
return;
|
|
1489
|
+
case "field":
|
|
1490
|
+
visit(def.parser, true);
|
|
1491
|
+
return;
|
|
1269
1492
|
case "skip":
|
|
1270
1493
|
visit(def.main, consumed);
|
|
1271
1494
|
visit(def.skipped, false);
|
|
@@ -1317,6 +1540,11 @@ function markUnusedValues(root) {
|
|
|
1317
1540
|
}
|
|
1318
1541
|
|
|
1319
1542
|
// src/combinators/parser.ts
|
|
1543
|
+
function tagRule(r, key) {
|
|
1544
|
+
;
|
|
1545
|
+
r._ruleName = key;
|
|
1546
|
+
if (r._def.tag === "node" && r._def.type === void 0) r._def.type = key;
|
|
1547
|
+
}
|
|
1320
1548
|
function rules(factory) {
|
|
1321
1549
|
const cache = {};
|
|
1322
1550
|
const proxy = new Proxy(cache, {
|
|
@@ -1325,7 +1553,7 @@ function rules(factory) {
|
|
|
1325
1553
|
const record = target;
|
|
1326
1554
|
if (!(key in record)) {
|
|
1327
1555
|
const r = ref();
|
|
1328
|
-
r
|
|
1556
|
+
tagRule(r, key);
|
|
1329
1557
|
record[key] = r;
|
|
1330
1558
|
}
|
|
1331
1559
|
return record[key];
|
|
@@ -1336,12 +1564,12 @@ function rules(factory) {
|
|
|
1336
1564
|
const placeholder = cache[key];
|
|
1337
1565
|
const parser2 = definitions[key];
|
|
1338
1566
|
if (placeholder !== void 0 && typeof placeholder.define === "function") {
|
|
1339
|
-
;
|
|
1567
|
+
tagRule(parser2, key);
|
|
1340
1568
|
placeholder.define(parser2);
|
|
1341
1569
|
placeholder._meta.firstSet = parser2._meta.firstSet;
|
|
1342
1570
|
placeholder._meta.canMatchNewline = parser2._meta.canMatchNewline;
|
|
1343
1571
|
} else {
|
|
1344
|
-
;
|
|
1572
|
+
tagRule(parser2, key);
|
|
1345
1573
|
cache[key] = parser2;
|
|
1346
1574
|
}
|
|
1347
1575
|
}
|
|
@@ -1398,44 +1626,130 @@ function buildReadsTrivia(def) {
|
|
|
1398
1626
|
const src = def.buildSrc ?? def.build.toString();
|
|
1399
1627
|
const arity = confirmedBuildArity(src);
|
|
1400
1628
|
if (arity === null) return true;
|
|
1401
|
-
return arity >=
|
|
1629
|
+
return arity >= 5;
|
|
1402
1630
|
}
|
|
1403
1631
|
function buildReadsState(def) {
|
|
1404
1632
|
if (!def.build) return true;
|
|
1405
1633
|
const src = def.buildSrc ?? def.build.toString();
|
|
1406
1634
|
const arity = confirmedBuildArity(src);
|
|
1407
1635
|
if (arity === null) return true;
|
|
1408
|
-
return arity >=
|
|
1636
|
+
return arity >= 6;
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
// src/compiler/fields.ts
|
|
1640
|
+
function buildReadsFields(def) {
|
|
1641
|
+
if (!def.build) return true;
|
|
1642
|
+
const src = def.buildSrc ?? def.build.toString();
|
|
1643
|
+
const arity = confirmedBuildArity(src);
|
|
1644
|
+
if (arity === null) return true;
|
|
1645
|
+
return arity >= 2;
|
|
1646
|
+
}
|
|
1647
|
+
function parserHasOwnFields(p, seen = /* @__PURE__ */ new Set()) {
|
|
1648
|
+
if (seen.has(p)) return false;
|
|
1649
|
+
seen.add(p);
|
|
1650
|
+
const d = p._def;
|
|
1651
|
+
switch (d.tag) {
|
|
1652
|
+
case "field":
|
|
1653
|
+
return true;
|
|
1654
|
+
case "node":
|
|
1655
|
+
return false;
|
|
1656
|
+
case "lazy": {
|
|
1657
|
+
try {
|
|
1658
|
+
return parserHasOwnFields(d.thunk(), seen);
|
|
1659
|
+
} catch {
|
|
1660
|
+
return false;
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
case "sequence":
|
|
1664
|
+
case "choice":
|
|
1665
|
+
return d.parsers.some((x) => parserHasOwnFields(x, seen));
|
|
1666
|
+
case "sepBy":
|
|
1667
|
+
return parserHasOwnFields(d.parser, seen) || parserHasOwnFields(d.separator, seen);
|
|
1668
|
+
case "skip":
|
|
1669
|
+
return parserHasOwnFields(d.main, seen) || parserHasOwnFields(d.skipped, seen);
|
|
1670
|
+
case "grammar":
|
|
1671
|
+
return parserHasOwnFields(d.parser, seen) || (d.triviaParser ? parserHasOwnFields(d.triviaParser, seen) : false);
|
|
1672
|
+
case "scanTo":
|
|
1673
|
+
return parserHasOwnFields(d.sentinel, seen) || d.skip.some((x) => parserHasOwnFields(x, seen));
|
|
1674
|
+
case "recover":
|
|
1675
|
+
return parserHasOwnFields(d.parser, seen) || parserHasOwnFields(d.sentinel, seen);
|
|
1676
|
+
case "many":
|
|
1677
|
+
case "oneOrMore":
|
|
1678
|
+
case "optional":
|
|
1679
|
+
case "transform":
|
|
1680
|
+
case "trivia":
|
|
1681
|
+
case "token":
|
|
1682
|
+
case "label":
|
|
1683
|
+
case "expect":
|
|
1684
|
+
case "withCtx":
|
|
1685
|
+
case "not":
|
|
1686
|
+
return parserHasOwnFields(d.parser, seen);
|
|
1687
|
+
default:
|
|
1688
|
+
return false;
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
function buildFieldMap(captures) {
|
|
1692
|
+
if (!captures?.length) return void 0;
|
|
1693
|
+
const out = {};
|
|
1694
|
+
for (const cap of captures) {
|
|
1695
|
+
const entry = { value: cap.value, span: cap.span };
|
|
1696
|
+
const current = out[cap.name];
|
|
1697
|
+
if (current === void 0) out[cap.name] = entry;
|
|
1698
|
+
else if (Array.isArray(current)) current.push(entry);
|
|
1699
|
+
else out[cap.name] = [current, entry];
|
|
1700
|
+
}
|
|
1701
|
+
return out;
|
|
1409
1702
|
}
|
|
1410
1703
|
|
|
1411
1704
|
// src/combinators/node.ts
|
|
1412
|
-
function
|
|
1705
|
+
function unwrapChild(child) {
|
|
1413
1706
|
return child !== null && typeof child === "object" && child._tag === "leaf" ? child.value : child;
|
|
1414
1707
|
}
|
|
1415
|
-
function
|
|
1708
|
+
function isCstChild(value) {
|
|
1709
|
+
return typeof value === "object" && value !== null && (value._tag === "node" || value._tag === "leaf" || value._tag === "error");
|
|
1710
|
+
}
|
|
1711
|
+
function missingInferredType() {
|
|
1712
|
+
throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
|
|
1713
|
+
}
|
|
1714
|
+
function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
1715
|
+
const hasExplicitType = typeof typeOrCombinator === "string";
|
|
1716
|
+
const type = hasExplicitType ? typeOrCombinator : void 0;
|
|
1717
|
+
const combinator = hasExplicitType ? combinatorOrBuild : typeOrCombinator;
|
|
1718
|
+
const build = hasExplicitType ? buildOrOpts : combinatorOrBuild;
|
|
1719
|
+
const opts = hasExplicitType ? maybeOpts : buildOrOpts;
|
|
1720
|
+
const baseDef = { tag: "node", parser: combinator, ...type === void 0 ? {} : { type }, ...build === void 0 ? {} : { build } };
|
|
1416
1721
|
const meta = {
|
|
1417
1722
|
firstSet: combinator._meta.firstSet,
|
|
1418
1723
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
1419
1724
|
isTrivia: false
|
|
1420
1725
|
};
|
|
1726
|
+
const unwrap = opts?.unwrap === true;
|
|
1421
1727
|
const collapse = opts?.collapse === true;
|
|
1422
|
-
|
|
1728
|
+
if (unwrap && collapse) {
|
|
1729
|
+
throw new Error("node() options cannot set both unwrap and collapse");
|
|
1730
|
+
}
|
|
1731
|
+
const def = unwrap || collapse ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {} } : baseDef;
|
|
1423
1732
|
const capturesTrivia = build ? buildReadsTrivia(def) : true;
|
|
1424
1733
|
const clonesState = build ? buildReadsState(def) : true;
|
|
1734
|
+
const capturesFields = parserHasOwnFields(combinator) && (build ? buildReadsFields(def) : true);
|
|
1425
1735
|
return {
|
|
1426
1736
|
_tag: "node",
|
|
1427
1737
|
_meta: meta,
|
|
1428
1738
|
_def: def,
|
|
1429
1739
|
parse(input, pos, ctx) {
|
|
1430
1740
|
const saved = beginCstNodeCapture(ctx);
|
|
1741
|
+
const savedFields = ctx._fields;
|
|
1742
|
+
ctx._fields = capturesFields ? [] : void 0;
|
|
1431
1743
|
if (!capturesTrivia) ctx.captureTrivia = false;
|
|
1432
1744
|
const r = combinator.parse(input, pos, ctx);
|
|
1745
|
+
const fields = capturesFields ? buildFieldMap(ctx._fields) : void 0;
|
|
1746
|
+
ctx._fields = savedFields;
|
|
1433
1747
|
const { children, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
|
|
1434
1748
|
if (!r.ok) return r;
|
|
1435
1749
|
const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
|
|
1436
|
-
const
|
|
1437
|
-
const
|
|
1438
|
-
const rawEntry =
|
|
1750
|
+
const nodeType = def.type ?? missingInferredType();
|
|
1751
|
+
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 };
|
|
1752
|
+
const rawEntry = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : "", span: r.span };
|
|
1439
1753
|
if (saved.buf !== void 0 || saved.ch !== void 0) {
|
|
1440
1754
|
pushCstChild(ctx, built, rawEntry);
|
|
1441
1755
|
}
|
|
@@ -1453,7 +1767,7 @@ function transform(combinator, fn) {
|
|
|
1453
1767
|
parse(input, pos, ctx) {
|
|
1454
1768
|
const result = combinator.parse(input, pos, ctx);
|
|
1455
1769
|
if (!result.ok) return result;
|
|
1456
|
-
return {
|
|
1770
|
+
return { ok: true, value: fn(result.value, result.span), span: result.span };
|
|
1457
1771
|
}
|
|
1458
1772
|
};
|
|
1459
1773
|
}
|
|
@@ -1467,7 +1781,7 @@ function skip(main, skipped) {
|
|
|
1467
1781
|
if (!result.ok) return result;
|
|
1468
1782
|
const s = skipped.parse(input, result.span.end, ctx);
|
|
1469
1783
|
if (!s.ok) return result;
|
|
1470
|
-
return {
|
|
1784
|
+
return { ok: true, value: result.value, span: { start: result.span.start, end: s.span.end } };
|
|
1471
1785
|
}
|
|
1472
1786
|
};
|
|
1473
1787
|
}
|
|
@@ -1491,7 +1805,20 @@ function label(name, combinator) {
|
|
|
1491
1805
|
_def: { tag: "label", label: name, parser: combinator },
|
|
1492
1806
|
parse(input, pos, ctx) {
|
|
1493
1807
|
const result = combinator.parse(input, pos, ctx);
|
|
1494
|
-
if (!result.ok) return {
|
|
1808
|
+
if (!result.ok) return { ok: false, expected: [name], span: result.span };
|
|
1809
|
+
return result;
|
|
1810
|
+
}
|
|
1811
|
+
};
|
|
1812
|
+
}
|
|
1813
|
+
function field(name, combinator) {
|
|
1814
|
+
return {
|
|
1815
|
+
_tag: combinator._tag,
|
|
1816
|
+
_meta: combinator._meta,
|
|
1817
|
+
_def: { tag: "field", name, parser: combinator },
|
|
1818
|
+
parse(input, pos, ctx) {
|
|
1819
|
+
const result = combinator.parse(input, pos, ctx);
|
|
1820
|
+
if (!result.ok) return result;
|
|
1821
|
+
ctx._fields?.push({ name, value: result.value, span: result.span });
|
|
1495
1822
|
return result;
|
|
1496
1823
|
}
|
|
1497
1824
|
};
|
|
@@ -1682,9 +2009,9 @@ function expect(combinator, label2) {
|
|
|
1682
2009
|
|
|
1683
2010
|
// src/compiler/scannable-run.ts
|
|
1684
2011
|
var BACKSLASH = 92;
|
|
1685
|
-
var
|
|
2012
|
+
var CLASS_ESCAPES2 = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
1686
2013
|
var META = new Set("()[]{}*+?|^$.".split(""));
|
|
1687
|
-
var
|
|
2014
|
+
var SPACE_RANGES2 = [
|
|
1688
2015
|
[9, 13],
|
|
1689
2016
|
[32, 32],
|
|
1690
2017
|
[160, 160],
|
|
@@ -1697,9 +2024,9 @@ var SPACE_RANGES = [
|
|
|
1697
2024
|
[12288, 12288],
|
|
1698
2025
|
[65279, 65279]
|
|
1699
2026
|
];
|
|
1700
|
-
function
|
|
2027
|
+
function shorthandRanges2(ch) {
|
|
1701
2028
|
if (ch === "d") return [[48, 57]];
|
|
1702
|
-
if (ch === "s") return
|
|
2029
|
+
if (ch === "s") return SPACE_RANGES2;
|
|
1703
2030
|
return [[48, 57], [65, 90], [97, 122], [95, 95]];
|
|
1704
2031
|
}
|
|
1705
2032
|
function readUnicodeEscape(body, i) {
|
|
@@ -1723,8 +2050,8 @@ function parseClassRanges(body) {
|
|
|
1723
2050
|
const e = body[i + 1];
|
|
1724
2051
|
if (e === void 0) return null;
|
|
1725
2052
|
i += 2;
|
|
1726
|
-
if (e in
|
|
1727
|
-
if (e === "d" || e === "w" || e === "s") return { set:
|
|
2053
|
+
if (e in CLASS_ESCAPES2) return { cp: CLASS_ESCAPES2[e] };
|
|
2054
|
+
if (e === "d" || e === "w" || e === "s") return { set: shorthandRanges2(e) };
|
|
1728
2055
|
if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
1729
2056
|
return { cp: e.codePointAt(0) };
|
|
1730
2057
|
}
|
|
@@ -1750,9 +2077,9 @@ function parseClassRanges(body) {
|
|
|
1750
2077
|
return ranges.length ? ranges : null;
|
|
1751
2078
|
}
|
|
1752
2079
|
function classToRanges(cls) {
|
|
1753
|
-
if (cls === "\\d") return
|
|
1754
|
-
if (cls === "\\w") return
|
|
1755
|
-
if (cls === "\\s") return
|
|
2080
|
+
if (cls === "\\d") return shorthandRanges2("d");
|
|
2081
|
+
if (cls === "\\w") return shorthandRanges2("w");
|
|
2082
|
+
if (cls === "\\s") return shorthandRanges2("s");
|
|
1756
2083
|
const body = cls.slice(1, -1);
|
|
1757
2084
|
if (body.startsWith("^")) return null;
|
|
1758
2085
|
return parseClassRanges(body);
|
|
@@ -1770,7 +2097,7 @@ function literalCodePoints(frag) {
|
|
|
1770
2097
|
if (ch === "\\") {
|
|
1771
2098
|
const e = frag[i + 1];
|
|
1772
2099
|
if (e === void 0) return null;
|
|
1773
|
-
out.push(e in
|
|
2100
|
+
out.push(e in CLASS_ESCAPES2 ? CLASS_ESCAPES2[e] : e.codePointAt(0));
|
|
1774
2101
|
i += 2;
|
|
1775
2102
|
continue;
|
|
1776
2103
|
}
|
|
@@ -1863,7 +2190,7 @@ function parseSeqParts(source) {
|
|
|
1863
2190
|
if (e === "d" || e === "w" || e === "s") {
|
|
1864
2191
|
flush();
|
|
1865
2192
|
i += 2;
|
|
1866
|
-
i += runFrom(
|
|
2193
|
+
i += runFrom(shorthandRanges2(e), false, source[i]);
|
|
1867
2194
|
continue;
|
|
1868
2195
|
}
|
|
1869
2196
|
const uni = readUnicodeEscape(source, i);
|
|
@@ -1872,8 +2199,8 @@ function parseSeqParts(source) {
|
|
|
1872
2199
|
cp2 = uni.cp;
|
|
1873
2200
|
i = uni.next;
|
|
1874
2201
|
} else if (e === void 0) return null;
|
|
1875
|
-
else if (e in
|
|
1876
|
-
cp2 =
|
|
2202
|
+
else if (e in CLASS_ESCAPES2) {
|
|
2203
|
+
cp2 = CLASS_ESCAPES2[e];
|
|
1877
2204
|
i += 2;
|
|
1878
2205
|
} else if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
1879
2206
|
else {
|
|
@@ -1980,7 +2307,7 @@ function rangesSubset(sub, sup) {
|
|
|
1980
2307
|
}
|
|
1981
2308
|
function parseClassOperand(body) {
|
|
1982
2309
|
if (body === "\\d" || body === "\\w" || body === "\\s") {
|
|
1983
|
-
return { ranges:
|
|
2310
|
+
return { ranges: shorthandRanges2(body[1]), negated: false };
|
|
1984
2311
|
}
|
|
1985
2312
|
if (body.length >= 2 && body[0] === "[" && body[body.length - 1] === "]") {
|
|
1986
2313
|
let inner = body.slice(1, -1);
|
|
@@ -2413,7 +2740,7 @@ function parseScanShapeCore(source) {
|
|
|
2413
2740
|
}
|
|
2414
2741
|
m = /^\\([dws])([+*])$/.exec(source);
|
|
2415
2742
|
if (m) {
|
|
2416
|
-
return { kind: "chars", ranges:
|
|
2743
|
+
return { kind: "chars", ranges: shorthandRanges2(m[1]), minOne: m[2] === "+" };
|
|
2417
2744
|
}
|
|
2418
2745
|
m = /^(\[(?:\\.|[^\]])+\]|\\[dws])(\[(?:\\.|[^\]])+\]|\\[dws])\*$/.exec(source);
|
|
2419
2746
|
if (m) {
|
|
@@ -2955,21 +3282,22 @@ function emitScannableTerminal(shape, c) {
|
|
|
2955
3282
|
}
|
|
2956
3283
|
|
|
2957
3284
|
// src/compiler/inline-build.ts
|
|
2958
|
-
var MK_BUILD_RE = /^\(\s*(
|
|
3285
|
+
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*$/;
|
|
2959
3286
|
function escapeRegExp(s) {
|
|
2960
3287
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2961
3288
|
}
|
|
2962
3289
|
function looseMkBuildRe(type) {
|
|
2963
3290
|
return new RegExp(
|
|
2964
|
-
String.raw`^\(\s*(
|
|
3291
|
+
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*$`
|
|
2965
3292
|
);
|
|
2966
3293
|
}
|
|
2967
3294
|
function analyzeMkInlineBuild(def) {
|
|
2968
3295
|
if (!def.build) return null;
|
|
3296
|
+
if (def.type === void 0) return null;
|
|
2969
3297
|
const src = (def.buildSrc ?? def.build.toString()).trim();
|
|
2970
3298
|
const strict = src.match(MK_BUILD_RE);
|
|
2971
3299
|
if (strict) {
|
|
2972
|
-
const mkType = strict[
|
|
3300
|
+
const mkType = strict[6];
|
|
2973
3301
|
return mkType === def.type ? def.type : null;
|
|
2974
3302
|
}
|
|
2975
3303
|
if (looseMkBuildRe(def.type).test(src)) return def.type;
|
|
@@ -3304,8 +3632,9 @@ function planDisjointDispatch(parsers) {
|
|
|
3304
3632
|
}
|
|
3305
3633
|
return total >= SWITCH_MIN_CASES ? { kind: "switch", cases } : { kind: "if" };
|
|
3306
3634
|
}
|
|
3307
|
-
function captureRestoreBody(mL, mR, mTl, mLg) {
|
|
3308
|
-
const
|
|
3635
|
+
function captureRestoreBody(mL, mR, mTl, mLg, mF = null) {
|
|
3636
|
+
const fieldRestore = mF ? `; if (_ctx._fields) _ctx._fields.length = ${mF}` : "";
|
|
3637
|
+
const base = `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${mL}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${mR}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${mTl}${fieldRestore}`;
|
|
3309
3638
|
return mLg ? `${base}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${mLg}` : base;
|
|
3310
3639
|
}
|
|
3311
3640
|
function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
|
|
@@ -3353,6 +3682,7 @@ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
3353
3682
|
// Delegating wrappers: defer to the wrapped parser.
|
|
3354
3683
|
case "transform":
|
|
3355
3684
|
case "label":
|
|
3685
|
+
case "field":
|
|
3356
3686
|
case "expect":
|
|
3357
3687
|
case "withCtx":
|
|
3358
3688
|
case "grammar":
|
|
@@ -3399,6 +3729,7 @@ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
3399
3729
|
case "optional":
|
|
3400
3730
|
case "transform":
|
|
3401
3731
|
case "label":
|
|
3732
|
+
case "field":
|
|
3402
3733
|
case "expect":
|
|
3403
3734
|
case "withCtx":
|
|
3404
3735
|
case "grammar":
|
|
@@ -3436,22 +3767,25 @@ function emitFallible(inner, ctx, pos, swallow = false) {
|
|
|
3436
3767
|
ctx.recordFail = savedRecord;
|
|
3437
3768
|
const ind0 = ind(ctx);
|
|
3438
3769
|
const needsRollback = ctx.capturing && mayLeavePartialCapture(inner);
|
|
3770
|
+
const needsFieldRollback = needsRollback && parserHasOwnFields(inner);
|
|
3439
3771
|
const mL = needsRollback ? v(ctx, "_fcl") : null;
|
|
3440
3772
|
const mR = needsRollback ? v(ctx, "_fcr") : null;
|
|
3441
3773
|
const mTl = needsRollback ? v(ctx, "_fctl") : null;
|
|
3774
|
+
const mF = needsFieldRollback ? v(ctx, "_fcf") : null;
|
|
3442
3775
|
const stmts = [
|
|
3443
3776
|
`${ind0}let ${okV} = false, ${valV}, ${endV} = ${pos}`,
|
|
3444
3777
|
...mL ? [
|
|
3445
3778
|
`${ind0}const ${mL} = _ctx._cstLeaves?.length ?? 0`,
|
|
3446
3779
|
`${ind0}const ${mR} = _ctx._cstRawChildren?.length ?? 0`,
|
|
3447
|
-
`${ind0}const ${mTl} = _ctx._cstTriviaLog?.length ?? 0
|
|
3780
|
+
`${ind0}const ${mTl} = _ctx._cstTriviaLog?.length ?? 0`,
|
|
3781
|
+
...mF ? [`${ind0}const ${mF} = _ctx._fields?.length ?? 0`] : []
|
|
3448
3782
|
] : [],
|
|
3449
3783
|
`${ind0}${lbl}: {`,
|
|
3450
3784
|
...r.stmts,
|
|
3451
3785
|
`${ind0} ${valV} = ${r.valueVar}; ${endV} = ${r.endVar}; ${okV} = true`,
|
|
3452
3786
|
`${ind0}}`,
|
|
3453
3787
|
...mL ? [
|
|
3454
|
-
`${ind0}if (!${okV}) { ${captureRestoreBody(mL, mR, mTl, null)} }`
|
|
3788
|
+
`${ind0}if (!${okV}) { ${captureRestoreBody(mL, mR, mTl, null, mF)} }`
|
|
3455
3789
|
] : []
|
|
3456
3790
|
];
|
|
3457
3791
|
return { stmts, okVar: okV, valVar: valV, endVar: endV };
|
|
@@ -3678,6 +4012,7 @@ function failsAtStart(p) {
|
|
|
3678
4012
|
return true;
|
|
3679
4013
|
case "transform":
|
|
3680
4014
|
case "label":
|
|
4015
|
+
case "field":
|
|
3681
4016
|
return failsAtStart(d.parser);
|
|
3682
4017
|
default:
|
|
3683
4018
|
return false;
|
|
@@ -3697,6 +4032,7 @@ function canMatchEmptyAtStart(p) {
|
|
|
3697
4032
|
return true;
|
|
3698
4033
|
case "transform":
|
|
3699
4034
|
case "label":
|
|
4035
|
+
case "field":
|
|
3700
4036
|
return canMatchEmptyAtStart(d.parser);
|
|
3701
4037
|
case "literal":
|
|
3702
4038
|
return d.value.length === 0;
|
|
@@ -3879,11 +4215,13 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
3879
4215
|
const skipCond = gateCond ? `!${resOkV} && ${gateCond}` : `!${resOkV}`;
|
|
3880
4216
|
const armHasAutoNot = !!(autoNot && autoNot.length > 0);
|
|
3881
4217
|
const armNeedsRollback = ctx.capturing && (mayLeavePartialCapture(p) || armHasAutoNot && capturesLeaf(p));
|
|
4218
|
+
const armNeedsFieldRollback = armNeedsRollback && parserHasOwnFields(p);
|
|
3882
4219
|
const markLeaves = armNeedsRollback ? v(ctx, "_cml") : null;
|
|
3883
4220
|
const markRaw = armNeedsRollback ? v(ctx, "_cmr") : null;
|
|
3884
4221
|
const markTl = armNeedsRollback ? v(ctx, "_cmtl") : null;
|
|
3885
4222
|
const markLog = armNeedsRollback ? v(ctx, "_cmlg") : null;
|
|
3886
|
-
const
|
|
4223
|
+
const markFields = armNeedsFieldRollback ? v(ctx, "_cmf") : null;
|
|
4224
|
+
const rollback = markLeaves ? captureRestoreBody(markLeaves, markRaw, markTl, markLog, markFields) : "";
|
|
3887
4225
|
const failSlot = atStart ? staticFx : "_ctx._fx";
|
|
3888
4226
|
stmts.push(`${ind0}if (${skipCond}) {`);
|
|
3889
4227
|
if (fsGuard) stmts.push(`${ind(ctx)}if (${fsGuard}) {`);
|
|
@@ -3893,7 +4231,8 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
3893
4231
|
`${ind(ctx)}const ${markLeaves} = _ctx._cstLeaves?.length ?? 0`,
|
|
3894
4232
|
`${ind(ctx)}const ${markRaw} = _ctx._cstRawChildren?.length ?? 0`,
|
|
3895
4233
|
`${ind(ctx)}const ${markTl} = _ctx._cstTriviaLog?.length ?? 0`,
|
|
3896
|
-
`${ind(ctx)}const ${markLog} = _ctx._triviaLog?.length ?? 0
|
|
4234
|
+
`${ind(ctx)}const ${markLog} = _ctx._triviaLog?.length ?? 0`,
|
|
4235
|
+
...markFields ? [`${ind(ctx)}const ${markFields} = _ctx._fields?.length ?? 0`] : []
|
|
3897
4236
|
);
|
|
3898
4237
|
}
|
|
3899
4238
|
const { stmts: armStmts, okVar, valVar, endVar } = emitFallible(p, ctx, pos, atStart);
|
|
@@ -4286,6 +4625,9 @@ function emitToken(def, ctx, pos) {
|
|
|
4286
4625
|
};
|
|
4287
4626
|
}
|
|
4288
4627
|
function emitNode(def, ctx, pos) {
|
|
4628
|
+
if (def.type === void 0) {
|
|
4629
|
+
throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
|
|
4630
|
+
}
|
|
4289
4631
|
const structural = def.build === void 0;
|
|
4290
4632
|
const mkType = structural ? null : analyzeMkInlineBuild(def);
|
|
4291
4633
|
let buildIdx = null;
|
|
@@ -4297,25 +4639,36 @@ function emitNode(def, ctx, pos) {
|
|
|
4297
4639
|
const i = ind(ctx);
|
|
4298
4640
|
const capturesTrivia = mkType !== null || !structural && buildReadsTrivia(def);
|
|
4299
4641
|
const clonesState = !structural && buildReadsState(def);
|
|
4642
|
+
const hasFields = parserHasOwnFields(def.parser);
|
|
4643
|
+
const capturesFields = hasFields && !structural && buildReadsFields(def);
|
|
4300
4644
|
const chV = v(ctx, "_ch");
|
|
4301
4645
|
const rawV = v(ctx, "_raw");
|
|
4302
4646
|
const capTLv = structural ? v(ctx, "_ctl") : null;
|
|
4303
4647
|
const capSTv = structural ? v(ctx, "_cst") : null;
|
|
4648
|
+
const capFv = structural && hasFields ? v(ctx, "_cf") : null;
|
|
4304
4649
|
const tlV = capturesTrivia || structural ? v(ctx, "_tl") : "_EMPTY_TL";
|
|
4305
4650
|
if (!capturesTrivia) ctx.needsEmptyTl = true;
|
|
4306
4651
|
const sc = v(ctx, "_sc"), sl = v(ctx, "_sl"), sr = v(ctx, "_sr"), st = v(ctx, "_st"), stl = v(ctx, "_stl");
|
|
4307
4652
|
if (structural) ctx.needsHostReads = true;
|
|
4308
|
-
const
|
|
4653
|
+
const hostTriviaGate = `_ctx.build !== undefined && (_ctx.build._parsemanCaptureTrivia !== undefined ? _ctx.build._parsemanCaptureTrivia(${JSON.stringify(def.type)}) : (_ctx._pmCapTL ??= _hostReads(_ctx.build, 5)))`;
|
|
4654
|
+
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)` : ""}
|
|
4309
4655
|
${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capturesTrivia ? `${i}const ${chV} = [], ${rawV} = [], ${tlV} = []` : `${i}const ${chV} = [], ${rawV} = []`;
|
|
4310
4656
|
const innerTl = structural ? `${capTLv} ? ${tlV} : undefined` : capturesTrivia ? tlV : "undefined";
|
|
4657
|
+
const fieldsOn = structural ? capFv ?? "false" : capturesFields ? "true" : "false";
|
|
4658
|
+
const sf = hasFields ? v(ctx, "_sf") : null;
|
|
4659
|
+
const fArr = hasFields ? v(ctx, "_fa") : null;
|
|
4660
|
+
const fObj = hasFields ? v(ctx, "_fields") : "undefined";
|
|
4311
4661
|
const stmts = [
|
|
4312
4662
|
allocStmt,
|
|
4313
|
-
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog`,
|
|
4314
|
-
`${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true; _ctx._cstTriviaLog = ${innerTl}`
|
|
4663
|
+
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog${sf ? `, ${sf} = _ctx._fields` : ""}`,
|
|
4664
|
+
`${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true; _ctx._cstTriviaLog = ${innerTl}${sf ? `; _ctx._fields = ${fieldsOn} ? [] : undefined` : ""}`
|
|
4315
4665
|
];
|
|
4316
4666
|
const { stmts: innerStmts, okVar, endVar } = emitFallible(def.parser, ctx, pos);
|
|
4317
4667
|
stmts.push(...innerStmts);
|
|
4318
|
-
|
|
4668
|
+
if (sf && fArr) {
|
|
4669
|
+
stmts.push(`${i}const ${fArr} = _ctx._fields`);
|
|
4670
|
+
}
|
|
4671
|
+
stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}${sf ? `; _ctx._fields = ${sf}` : ""}`);
|
|
4319
4672
|
stmts.push(...emitIfFail(ctx, `!${okVar}`, propagateFailBody(ctx)));
|
|
4320
4673
|
let stV = "undefined";
|
|
4321
4674
|
if (structural) {
|
|
@@ -4325,14 +4678,33 @@ ${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capt
|
|
|
4325
4678
|
stV = v(ctx, "_nst");
|
|
4326
4679
|
stmts.push(`${i}const ${stV} = _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
|
|
4327
4680
|
}
|
|
4681
|
+
if (sf && fArr) {
|
|
4682
|
+
const fe = v(ctx, "_fe");
|
|
4683
|
+
const cur = v(ctx, "_fc");
|
|
4684
|
+
stmts.push(
|
|
4685
|
+
`${i}let ${fObj} = undefined`,
|
|
4686
|
+
`${i}if (${fArr} && ${fArr}.length) {`,
|
|
4687
|
+
`${i} ${fObj} = {}`,
|
|
4688
|
+
`${i} for (const ${fe} of ${fArr}) {`,
|
|
4689
|
+
`${i} const ${cur} = ${fObj}[${fe}.name], _entry = { value: ${fe}.value, span: ${fe}.span }`,
|
|
4690
|
+
`${i} if (${cur} === undefined) ${fObj}[${fe}.name] = _entry`,
|
|
4691
|
+
`${i} else if (Array.isArray(${cur})) ${cur}.push(_entry)`,
|
|
4692
|
+
`${i} else ${fObj}[${fe}.name] = [${cur}, _entry]`,
|
|
4693
|
+
`${i} }`,
|
|
4694
|
+
`${i}}`
|
|
4695
|
+
);
|
|
4696
|
+
}
|
|
4328
4697
|
const ndV = v(ctx, "_nd");
|
|
4329
|
-
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}, ${
|
|
4330
|
-
const ndExpr = ctx.ns || structural ? `_ctx.build !== undefined ? _ctx.build(${JSON.stringify(def.type)}, ${chV}, ${
|
|
4331
|
-
const
|
|
4698
|
+
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})`;
|
|
4699
|
+
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;
|
|
4700
|
+
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;
|
|
4701
|
+
const unwrapExpr = `${chV}.length === 1 ? (${chV}[0] !== null && typeof ${chV}[0] === 'object' && ${chV}[0]._tag === 'leaf' ? ${chV}[0].value : ${chV}[0]) : (${ndExpr})`;
|
|
4702
|
+
const collapseExpr = `${chV}.length === 1 ? ${chV}[0] : (${ndExpr})`;
|
|
4703
|
+
const finalExpr = def.unwrap ? unwrapExpr : def.collapse ? collapseExpr : hostCollapseExpr;
|
|
4332
4704
|
stmts.push(
|
|
4333
4705
|
`${i}const ${ndV} = ${finalExpr}`,
|
|
4334
4706
|
`${i}if (${sc}) ${sc}.push(${ndV})`,
|
|
4335
|
-
`${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} } })`
|
|
4707
|
+
`${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} } })`
|
|
4336
4708
|
);
|
|
4337
4709
|
return { stmts, valueVar: ndV, endVar };
|
|
4338
4710
|
}
|
|
@@ -4547,6 +4919,17 @@ function emitDispatch(p, ctx, pos) {
|
|
|
4547
4919
|
endVar: inner.endVar
|
|
4548
4920
|
};
|
|
4549
4921
|
}
|
|
4922
|
+
case "field": {
|
|
4923
|
+
const inner = emit(def.parser, ctx, pos);
|
|
4924
|
+
return {
|
|
4925
|
+
stmts: [
|
|
4926
|
+
...inner.stmts,
|
|
4927
|
+
`${ind(ctx)}if (_ctx._fields) _ctx._fields.push({ name: ${JSON.stringify(def.name)}, value: ${inner.valueVar}, span: { start: ${pos}, end: ${inner.endVar} } })`
|
|
4928
|
+
],
|
|
4929
|
+
valueVar: inner.valueVar,
|
|
4930
|
+
endVar: inner.endVar
|
|
4931
|
+
};
|
|
4932
|
+
}
|
|
4550
4933
|
case "grammar": {
|
|
4551
4934
|
const savedTrivia = ctx.activeTrivia;
|
|
4552
4935
|
const savedKindLabels = ctx.triviaKindLabels;
|
|
@@ -4648,6 +5031,7 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
4648
5031
|
case "trivia":
|
|
4649
5032
|
case "token":
|
|
4650
5033
|
case "label":
|
|
5034
|
+
case "field":
|
|
4651
5035
|
case "optional":
|
|
4652
5036
|
case "many":
|
|
4653
5037
|
case "oneOrMore":
|
|
@@ -4684,6 +5068,7 @@ function childrenOf(def) {
|
|
|
4684
5068
|
case "trivia":
|
|
4685
5069
|
case "token":
|
|
4686
5070
|
case "label":
|
|
5071
|
+
case "field":
|
|
4687
5072
|
case "grammar":
|
|
4688
5073
|
case "not":
|
|
4689
5074
|
case "node":
|
|
@@ -4925,6 +5310,11 @@ function assertRuleName(name) {
|
|
|
4925
5310
|
);
|
|
4926
5311
|
}
|
|
4927
5312
|
}
|
|
5313
|
+
function publicRuleWrapperSource(rule, fnSource) {
|
|
5314
|
+
const labels = rule._meta.triviaKindLabels;
|
|
5315
|
+
if (labels === void 0) return fnSource;
|
|
5316
|
+
return `Object.assign(${fnSource}, { _meta: { triviaKindLabels: ${JSON.stringify(labels)} } })`;
|
|
5317
|
+
}
|
|
4928
5318
|
function compileRuleMap(ruleMap) {
|
|
4929
5319
|
for (const [, rule] of ruleMap) markUnusedValues(rule);
|
|
4930
5320
|
const ctx = {
|
|
@@ -4957,7 +5347,7 @@ function compileRuleMap(ruleMap) {
|
|
|
4957
5347
|
ruleNames.set(rule, n === 0 ? base : `${base}$${n}`);
|
|
4958
5348
|
}
|
|
4959
5349
|
ctx.ruleNames = ruleNames;
|
|
4960
|
-
const perEntry = ruleMap.map(([key, rule]) => ({ key, r: emit(rule, ctx, "_pos") }));
|
|
5350
|
+
const perEntry = ruleMap.map(([key, rule]) => ({ key, rule, r: emit(rule, ctx, "_pos") }));
|
|
4961
5351
|
const derivedSrcs = ctx.mapFnSrcs.length === ctx.mapFns.length && ctx.mapFnSrcs.every((s) => s !== null) ? ctx.mapFnSrcs : void 0;
|
|
4962
5352
|
const buildCovered = ctx.buildFns.length === 0 || ctx.buildSrcs.every((s) => s !== null);
|
|
4963
5353
|
const buildSources = ctx.buildFns.length === 0 ? void 0 : ctx.buildSrcs;
|
|
@@ -4987,7 +5377,10 @@ function compileRuleMap(ruleMap) {
|
|
|
4987
5377
|
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
4988
5378
|
`}`
|
|
4989
5379
|
].join("\n");
|
|
4990
|
-
const objBody = perEntry.map(({ key, r }) =>
|
|
5380
|
+
const objBody = perEntry.map(({ key, rule, r }) => {
|
|
5381
|
+
const src = publicRuleWrapperSource(rule, entryFnText(r));
|
|
5382
|
+
return ` ${JSON.stringify(key)}: ${src.split("\n").join("\n ")}`;
|
|
5383
|
+
}).join(",\n");
|
|
4991
5384
|
const replacement = [
|
|
4992
5385
|
`/* @__PURE__ */ (() => {`,
|
|
4993
5386
|
...hoistedDecls,
|
|
@@ -5100,7 +5493,7 @@ function compileLinkable(ruleMapArg, ns) {
|
|
|
5100
5493
|
ctx.recordFail = savedRec;
|
|
5101
5494
|
pushNamedFnDecl(ctx, fn, body.stmts, body.valueVar, body.endVar);
|
|
5102
5495
|
}
|
|
5103
|
-
perEntry.push({ key, r: emitNamedFnCall(ctx, fn, "_pos") });
|
|
5496
|
+
perEntry.push({ key, rule, r: emitNamedFnCall(ctx, fn, "_pos") });
|
|
5104
5497
|
}
|
|
5105
5498
|
if (ctx.runtimeParsers.length !== 0) return null;
|
|
5106
5499
|
const mfSrcs = ctx.mapFns.length > 0 && ctx.mapFnSrcs.every((s) => s !== null) ? ctx.mapFnSrcs : null;
|
|
@@ -5123,14 +5516,14 @@ function compileLinkable(ruleMapArg, ns) {
|
|
|
5123
5516
|
...privateFns
|
|
5124
5517
|
].filter(Boolean);
|
|
5125
5518
|
const wrappers = /* @__PURE__ */ new Map();
|
|
5126
|
-
for (const { key, r } of perEntry) {
|
|
5127
|
-
wrappers.set(key, [
|
|
5519
|
+
for (const { key, rule, r } of perEntry) {
|
|
5520
|
+
wrappers.set(key, publicRuleWrapperSource(rule, [
|
|
5128
5521
|
`function(input, _pos, _ctx) {`,
|
|
5129
5522
|
` let pos = _pos`,
|
|
5130
5523
|
...r.stmts,
|
|
5131
5524
|
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
5132
5525
|
`}`
|
|
5133
|
-
].join("\n"));
|
|
5526
|
+
].join("\n")));
|
|
5134
5527
|
}
|
|
5135
5528
|
const firstSets = /* @__PURE__ */ new Map();
|
|
5136
5529
|
for (const [key, rule] of ruleMap) {
|
|
@@ -5305,6 +5698,7 @@ function childrenOf2(def) {
|
|
|
5305
5698
|
case "trivia":
|
|
5306
5699
|
case "token":
|
|
5307
5700
|
case "label":
|
|
5701
|
+
case "field":
|
|
5308
5702
|
case "not":
|
|
5309
5703
|
case "node":
|
|
5310
5704
|
case "expect":
|
|
@@ -5390,6 +5784,7 @@ function evalRuleMapIR(ir) {
|
|
|
5390
5784
|
"skip",
|
|
5391
5785
|
"trivia",
|
|
5392
5786
|
"label",
|
|
5787
|
+
"field",
|
|
5393
5788
|
"expect",
|
|
5394
5789
|
"_tf",
|
|
5395
5790
|
"_nd",
|
|
@@ -5416,6 +5811,7 @@ function evalRuleMapIR(ir) {
|
|
|
5416
5811
|
skip,
|
|
5417
5812
|
trivia,
|
|
5418
5813
|
label,
|
|
5814
|
+
field,
|
|
5419
5815
|
expect,
|
|
5420
5816
|
_tf,
|
|
5421
5817
|
_nd
|
|
@@ -5549,6 +5945,8 @@ ${body}
|
|
|
5549
5945
|
return `token(${kid(def.parser)})`;
|
|
5550
5946
|
case "label":
|
|
5551
5947
|
return `label(${JSON.stringify(def.label)}, ${kid(def.parser)})`;
|
|
5948
|
+
case "field":
|
|
5949
|
+
return `field(${JSON.stringify(def.name)}, ${kid(def.parser)})`;
|
|
5552
5950
|
case "expect":
|
|
5553
5951
|
return `expect(${kid(def.parser)}${def.label !== void 0 ? `, ${JSON.stringify(def.label)}` : ""})`;
|
|
5554
5952
|
case "skip":
|
|
@@ -5561,7 +5959,11 @@ ${body}
|
|
|
5561
5959
|
}
|
|
5562
5960
|
case "node": {
|
|
5563
5961
|
if (def.build !== void 0 && def.buildSrc === void 0) throw new Unserializable("node build without buildSrc");
|
|
5564
|
-
const opts = def.collapse ? `, { collapse: true }` : "";
|
|
5962
|
+
const opts = def.unwrap || def.collapse ? `, { ${def.unwrap ? "unwrap: true" : "collapse: true"} }` : "";
|
|
5963
|
+
if (def.type === void 0) {
|
|
5964
|
+
if (def.buildSrc !== void 0) throw new Unserializable("inferred node build without inferred type");
|
|
5965
|
+
return opts ? `node(${kid(def.parser)}, undefined${opts})` : `node(${kid(def.parser)})`;
|
|
5966
|
+
}
|
|
5565
5967
|
if (def.buildSrc !== void 0) return `_nd(${JSON.stringify(def.type)}, ${kid(def.parser)}, ${JSON.stringify(def.buildSrc)}${opts})`;
|
|
5566
5968
|
return opts ? `node(${JSON.stringify(def.type)}, ${kid(def.parser)}, undefined${opts})` : `node(${JSON.stringify(def.type)}, ${kid(def.parser)})`;
|
|
5567
5969
|
}
|
|
@@ -5588,8 +5990,9 @@ function fusedBody(pieces) {
|
|
|
5588
5990
|
}
|
|
5589
5991
|
}
|
|
5590
5992
|
const contributing = new Set(winner.values());
|
|
5591
|
-
const
|
|
5592
|
-
const
|
|
5993
|
+
const contributingPieces = [...contributing];
|
|
5994
|
+
const needsEmptyTl = contributingPieces.some((p) => p.needsEmptyTl);
|
|
5995
|
+
const needsHostReads = contributingPieces.some((p) => p.needsHostReads);
|
|
5593
5996
|
const lines = [
|
|
5594
5997
|
// Shared sentinel protocol (must match NAMED_FN_FAIL / NAMED_FN_END in codegen).
|
|
5595
5998
|
"const _pfFail = {}",
|
|
@@ -5597,7 +6000,7 @@ function fusedBody(pieces) {
|
|
|
5597
6000
|
...needsEmptyTl ? ["const _EMPTY_TL = Object.freeze([])"] : [],
|
|
5598
6001
|
...needsHostReads ? [HOST_READS_DECL] : [],
|
|
5599
6002
|
// Each contributing artifact's namespaced private prelude (regexes, _pf, …).
|
|
5600
|
-
...[...
|
|
6003
|
+
...[...new Set(contributingPieces.flatMap((p) => p.prelude))],
|
|
5601
6004
|
// The winning `_r_<Name>` function for each rule (one per name → no redeclare).
|
|
5602
6005
|
...[...winner].map(([k, p]) => p.ruleFns.get(k))
|
|
5603
6006
|
];
|
|
@@ -5620,7 +6023,7 @@ function fusedBody(pieces) {
|
|
|
5620
6023
|
}
|
|
5621
6024
|
);
|
|
5622
6025
|
const env = {};
|
|
5623
|
-
for (const p of
|
|
6026
|
+
for (const p of contributingPieces) {
|
|
5624
6027
|
if (p.mfFns.length) env[`${p.ns}mf`] = p.mfFns;
|
|
5625
6028
|
if (p.buildFns.length) env[`${p.ns}build`] = p.buildFns;
|
|
5626
6029
|
}
|
|
@@ -5668,6 +6071,7 @@ var SUPPORTED = {
|
|
|
5668
6071
|
sepBy: (...a) => sepBy(a[0], a[1]),
|
|
5669
6072
|
trivia: (...a) => trivia(a[0]),
|
|
5670
6073
|
label: (...a) => label(a[0], a[1]),
|
|
6074
|
+
field: (...a) => field(a[0], a[1]),
|
|
5671
6075
|
noTrivia: (...a) => noTrivia(a[0]),
|
|
5672
6076
|
token: (...a) => token(a[0]),
|
|
5673
6077
|
expect: (...a) => expect(a[0], a[1])
|
|
@@ -5688,19 +6092,20 @@ function scopeGet(scope, name, mfs) {
|
|
|
5688
6092
|
if (isCombinator(entry)) return entry;
|
|
5689
6093
|
return null;
|
|
5690
6094
|
}
|
|
5691
|
-
function
|
|
5692
|
-
if (expr.type !== "ObjectExpression") return
|
|
6095
|
+
function staticNodeOptions(expr) {
|
|
6096
|
+
if (expr.type !== "ObjectExpression") return void 0;
|
|
6097
|
+
const opts = {};
|
|
5693
6098
|
for (const prop of expr.properties) {
|
|
5694
6099
|
const p = prop;
|
|
5695
6100
|
if (p.computed) continue;
|
|
5696
6101
|
const key = p.key;
|
|
5697
6102
|
const name = key.type === "Identifier" ? key.name : key.type === "Literal" ? String(key.value) : void 0;
|
|
5698
|
-
if (name === "collapse") {
|
|
6103
|
+
if (name === "unwrap" || name === "collapse") {
|
|
5699
6104
|
const val = p.value;
|
|
5700
|
-
|
|
6105
|
+
if ((val.type === "Literal" || val.type === "BooleanLiteral") && val.value === true) opts[name] = true;
|
|
5701
6106
|
}
|
|
5702
6107
|
}
|
|
5703
|
-
return
|
|
6108
|
+
return opts.unwrap || opts.collapse ? opts : void 0;
|
|
5704
6109
|
}
|
|
5705
6110
|
function exprToCombi(node2, scope, code, mfs) {
|
|
5706
6111
|
if (node2.type === "Identifier") return scopeGet(scope, node2.name, mfs);
|
|
@@ -5750,18 +6155,22 @@ function exprToCombi(node2, scope, code, mfs) {
|
|
|
5750
6155
|
}
|
|
5751
6156
|
}
|
|
5752
6157
|
if (callee.name === "node" && code !== void 0) {
|
|
5753
|
-
const [
|
|
5754
|
-
if (!
|
|
5755
|
-
const
|
|
5756
|
-
|
|
6158
|
+
const [firstArg, secondArg, thirdArg, fourthArg] = node2.arguments;
|
|
6159
|
+
if (!firstArg || firstArg.type === "SpreadElement") return null;
|
|
6160
|
+
const firstVal = anyValue(firstArg, scope, code, mfs);
|
|
6161
|
+
const explicitType = typeof firstVal === "string" ? firstVal : void 0;
|
|
6162
|
+
const parserArg = explicitType !== void 0 ? secondArg : firstArg;
|
|
6163
|
+
const buildArg = explicitType !== void 0 ? thirdArg : secondArg;
|
|
6164
|
+
const optsArg = explicitType !== void 0 ? fourthArg : thirdArg;
|
|
6165
|
+
if (!parserArg || parserArg.type === "SpreadElement") return null;
|
|
5757
6166
|
const inner = anyValue(parserArg, scope, code, mfs);
|
|
5758
6167
|
if (!isCombinator(inner)) return null;
|
|
5759
6168
|
const be = buildArg;
|
|
5760
6169
|
const hasBuild = be !== void 0 && be.type !== "SpreadElement" && !(be.type === "Identifier" && be.name === "undefined");
|
|
5761
6170
|
const buildSrc = hasBuild ? code.slice(be.start, be.end) : void 0;
|
|
5762
|
-
const
|
|
6171
|
+
const opts = optsArg !== void 0 && optsArg.type !== "SpreadElement" ? staticNodeOptions(optsArg) : void 0;
|
|
5763
6172
|
try {
|
|
5764
|
-
const combi = node(
|
|
6173
|
+
const combi = explicitType !== void 0 ? node(explicitType, inner, hasBuild ? () => null : void 0, opts) : node(inner, hasBuild ? () => null : void 0, opts);
|
|
5765
6174
|
if (combi._def.tag === "node" && buildSrc !== void 0) combi._def.buildSrc = buildSrc;
|
|
5766
6175
|
return combi;
|
|
5767
6176
|
} catch {
|
|
@@ -6027,7 +6436,9 @@ function evaluateParserFactory(factoryNode, scope, code, mapFnSources) {
|
|
|
6027
6436
|
if (!keys) return null;
|
|
6028
6437
|
const ruleRefs = /* @__PURE__ */ new Map();
|
|
6029
6438
|
const tagRef = (r, name) => {
|
|
6439
|
+
;
|
|
6030
6440
|
r._ruleName = name;
|
|
6441
|
+
if (r._def.tag === "node" && r._def.type === void 0) r._def.type = name;
|
|
6031
6442
|
};
|
|
6032
6443
|
for (const key of keys) {
|
|
6033
6444
|
if (!ruleRefs.has(key)) {
|
|
@@ -6059,6 +6470,7 @@ function evaluateParserFactory(factoryNode, scope, code, mapFnSources) {
|
|
|
6059
6470
|
for (const [key, e] of finalByKey) {
|
|
6060
6471
|
const val = anyValue(e.value, e.scope, e.code, mapFnSources);
|
|
6061
6472
|
if (!isCombinator(val)) return null;
|
|
6473
|
+
tagRef(val, key);
|
|
6062
6474
|
ruleRefs.get(key).define(val);
|
|
6063
6475
|
}
|
|
6064
6476
|
return ruleRefs;
|