parseman 0.18.2 → 0.20.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 -4
- 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 +7 -7
- package/dist/combinators/regex.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/scannable-run.d.ts +2 -10
- package/dist/compiler/scannable-run.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 +568 -262
- 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 +568 -252
- package/dist/index.js.map +4 -4
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.cjs +568 -260
- package/dist/plugin/index.cjs.map +4 -4
- package/dist/plugin/index.js +568 -260
- package/dist/plugin/index.js.map +4 -4
- package/dist/regex/classes.d.ts +40 -0
- package/dist/regex/classes.d.ts.map +1 -0
- package/dist/regex/first-set.d.ts +35 -0
- package/dist/regex/first-set.d.ts.map +1 -0
- package/dist/types.d.ts +31 -8
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -3
- package/dist/combinators/regex-analyze.d.ts +0 -6
- package/dist/combinators/regex-analyze.d.ts.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __export = (target, all) => {
|
|
9
7
|
for (var name in all)
|
|
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
15
|
}
|
|
18
16
|
return to;
|
|
19
17
|
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
19
|
|
|
30
20
|
// src/index.ts
|
|
@@ -49,6 +39,7 @@ __export(index_exports, {
|
|
|
49
39
|
createVisitor: () => createVisitor,
|
|
50
40
|
cstBuildHost: () => cstBuildHost,
|
|
51
41
|
expect: () => expect,
|
|
42
|
+
field: () => field,
|
|
52
43
|
gapIsSignificant: () => gapIsSignificant,
|
|
53
44
|
gapText: () => gapText,
|
|
54
45
|
guard: () => guard,
|
|
@@ -349,7 +340,8 @@ function saveCstMark(ctx) {
|
|
|
349
340
|
return {
|
|
350
341
|
raw: cstRawLen(ctx),
|
|
351
342
|
tlog: cstTlLen(ctx),
|
|
352
|
-
leaves: cstLeavesLen(ctx)
|
|
343
|
+
leaves: cstLeavesLen(ctx),
|
|
344
|
+
fields: ctx._fields?.length ?? 0
|
|
353
345
|
};
|
|
354
346
|
}
|
|
355
347
|
function rollbackBufList(b, keyMulti, keySingle, len) {
|
|
@@ -373,11 +365,13 @@ function rollbackCstCapture(ctx, mark) {
|
|
|
373
365
|
if (mark.tlog === 0) b.tl = void 0;
|
|
374
366
|
else b.tl.length = mark.tlog;
|
|
375
367
|
}
|
|
368
|
+
if (ctx._fields) ctx._fields.length = mark.fields;
|
|
376
369
|
return;
|
|
377
370
|
}
|
|
378
371
|
if (ctx._cstRawChildren) ctx._cstRawChildren.length = mark.raw;
|
|
379
372
|
if (ctx._cstTriviaLog) ctx._cstTriviaLog.length = mark.tlog;
|
|
380
373
|
if (ctx._cstLeaves) ctx._cstLeaves.length = mark.leaves;
|
|
374
|
+
if (ctx._fields) ctx._fields.length = mark.fields;
|
|
381
375
|
}
|
|
382
376
|
function pushCstTriviaEntry(ctx, start, end, kindIndex) {
|
|
383
377
|
const insertIdx = cstRawLen(ctx);
|
|
@@ -421,9 +415,9 @@ function asciiFoldEq(a, b) {
|
|
|
421
415
|
}
|
|
422
416
|
function literal(value, opts = {}) {
|
|
423
417
|
const caseInsensitive = opts.caseInsensitive ?? false;
|
|
424
|
-
const
|
|
418
|
+
const firstSet2 = value.length > 0 ? fromChar(value.codePointAt(0)) : empty();
|
|
425
419
|
const meta = {
|
|
426
|
-
firstSet,
|
|
420
|
+
firstSet: firstSet2,
|
|
427
421
|
canMatchNewline: value.includes("\n"),
|
|
428
422
|
isTrivia: false
|
|
429
423
|
};
|
|
@@ -435,7 +429,7 @@ function literal(value, opts = {}) {
|
|
|
435
429
|
meta.firstSet = firstLower !== void 0 && firstUpper !== void 0 ? firstLower === firstUpper ? { kind: "ranges", ranges: [{ lo: firstLower, hi: firstLower }] } : { kind: "ranges", ranges: [
|
|
436
430
|
{ lo: firstLower, hi: firstLower },
|
|
437
431
|
{ lo: firstUpper, hi: firstUpper }
|
|
438
|
-
] } :
|
|
432
|
+
] } : firstSet2;
|
|
439
433
|
}
|
|
440
434
|
return {
|
|
441
435
|
_tag: "literal",
|
|
@@ -458,68 +452,66 @@ function literal(value, opts = {}) {
|
|
|
458
452
|
};
|
|
459
453
|
}
|
|
460
454
|
|
|
461
|
-
// src/
|
|
462
|
-
var
|
|
463
|
-
function registerRegexAnalyzer(analyzer) {
|
|
464
|
-
firstSetAnalyzer = analyzer;
|
|
465
|
-
}
|
|
466
|
-
var permissiveFirstSet = () => ({ firstSet: any(), canMatchNewline: true });
|
|
467
|
-
var SCAN_BAIL_AT = 64;
|
|
455
|
+
// src/regex/classes.ts
|
|
456
|
+
var CLASS_ESCAPES = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
468
457
|
var SPACE_RANGES = [
|
|
469
458
|
[9, 13],
|
|
470
459
|
[32, 32],
|
|
471
460
|
[160, 160],
|
|
472
461
|
[5760, 5760],
|
|
473
462
|
[8192, 8202],
|
|
474
|
-
[8232,
|
|
463
|
+
[8232, 8232],
|
|
464
|
+
[8233, 8233],
|
|
475
465
|
[8239, 8239],
|
|
476
466
|
[8287, 8287],
|
|
477
467
|
[12288, 12288],
|
|
478
468
|
[65279, 65279]
|
|
479
469
|
];
|
|
480
|
-
var CLASS_ESCAPES = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
481
470
|
function shorthandRanges(ch) {
|
|
482
471
|
if (ch === "d") return [[48, 57]];
|
|
483
472
|
if (ch === "s") return SPACE_RANGES;
|
|
484
473
|
return [[48, 57], [65, 90], [97, 122], [95, 95]];
|
|
485
474
|
}
|
|
486
|
-
function
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
}
|
|
491
|
-
return false;
|
|
475
|
+
function readUnicodeEscape(body, i) {
|
|
476
|
+
if (body[i] !== "\\" || body[i + 1] !== "u") return null;
|
|
477
|
+
const hex = body.slice(i + 2, i + 6);
|
|
478
|
+
if (!/^[0-9a-fA-F]{4}$/.test(hex)) return null;
|
|
479
|
+
return { cp: Number.parseInt(hex, 16), next: i + 6 };
|
|
492
480
|
}
|
|
493
|
-
function
|
|
494
|
-
if (body.startsWith("^")) return null;
|
|
481
|
+
function parseClassRanges(body) {
|
|
495
482
|
const ranges = [];
|
|
496
483
|
let i = 0;
|
|
497
484
|
const readAtom = () => {
|
|
498
485
|
const ch = body[i];
|
|
499
486
|
if (ch === void 0) return null;
|
|
500
487
|
if (ch === "\\") {
|
|
501
|
-
const
|
|
502
|
-
if (
|
|
488
|
+
const uni = readUnicodeEscape(body, i);
|
|
489
|
+
if (uni) {
|
|
490
|
+
i = uni.next;
|
|
491
|
+
return { cp: uni.cp };
|
|
492
|
+
}
|
|
493
|
+
const e = body[i + 1];
|
|
494
|
+
if (e === void 0) return null;
|
|
503
495
|
i += 2;
|
|
504
|
-
if (
|
|
505
|
-
if (
|
|
506
|
-
if (
|
|
507
|
-
return { cp:
|
|
496
|
+
if (e in CLASS_ESCAPES) return { cp: CLASS_ESCAPES[e] };
|
|
497
|
+
if (e === "d" || e === "w" || e === "s") return { set: shorthandRanges(e) };
|
|
498
|
+
if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
499
|
+
return { cp: e.codePointAt(0) };
|
|
508
500
|
}
|
|
509
|
-
i
|
|
510
|
-
return { cp: ch.
|
|
501
|
+
i += ch.length;
|
|
502
|
+
return { cp: ch.codePointAt(0) };
|
|
511
503
|
};
|
|
512
504
|
while (i < body.length) {
|
|
513
505
|
const lo = readAtom();
|
|
514
|
-
if (
|
|
515
|
-
if ("
|
|
516
|
-
ranges.push(...lo.
|
|
506
|
+
if (lo === null) return null;
|
|
507
|
+
if ("set" in lo) {
|
|
508
|
+
ranges.push(...lo.set);
|
|
517
509
|
continue;
|
|
518
510
|
}
|
|
519
511
|
if (body[i] === "-" && body[i + 1] !== void 0 && body[i + 1] !== "]") {
|
|
520
|
-
i
|
|
512
|
+
i += 1;
|
|
521
513
|
const hi = readAtom();
|
|
522
|
-
if (
|
|
514
|
+
if (hi === null || "set" in hi) return null;
|
|
523
515
|
ranges.push([lo.cp, hi.cp]);
|
|
524
516
|
} else {
|
|
525
517
|
ranges.push([lo.cp, lo.cp]);
|
|
@@ -527,6 +519,25 @@ function readClassRanges(body) {
|
|
|
527
519
|
}
|
|
528
520
|
return ranges.length ? ranges : null;
|
|
529
521
|
}
|
|
522
|
+
|
|
523
|
+
// src/combinators/regex.ts
|
|
524
|
+
var firstSetAnalyzer = null;
|
|
525
|
+
function registerRegexAnalyzer(analyzer) {
|
|
526
|
+
firstSetAnalyzer = analyzer;
|
|
527
|
+
}
|
|
528
|
+
var permissiveFirstSet = () => ({ firstSet: any(), canMatchNewline: true });
|
|
529
|
+
var SCAN_BAIL_AT = 64;
|
|
530
|
+
function inRanges(cp, ranges) {
|
|
531
|
+
for (let i = 0; i < ranges.length; i++) {
|
|
532
|
+
const [lo, hi] = ranges[i];
|
|
533
|
+
if (cp >= lo && cp <= hi) return true;
|
|
534
|
+
}
|
|
535
|
+
return false;
|
|
536
|
+
}
|
|
537
|
+
function readClassRanges(body) {
|
|
538
|
+
if (body.startsWith("^")) return null;
|
|
539
|
+
return parseClassRanges(body);
|
|
540
|
+
}
|
|
530
541
|
function shortScanner(source, flags) {
|
|
531
542
|
if (/[imsuvy]/.test(flags)) return null;
|
|
532
543
|
let ranges = null;
|
|
@@ -560,8 +571,8 @@ function regex(pattern, flags = "") {
|
|
|
560
571
|
const resolvedFlags = typeof pattern === "string" ? flags : pattern.flags;
|
|
561
572
|
const anchored = new RegExp(source, "y" + resolvedFlags.replace(/[gy]/g, ""));
|
|
562
573
|
const scan = shortScanner(source, resolvedFlags);
|
|
563
|
-
const { firstSet, canMatchNewline } = (firstSetAnalyzer ?? permissiveFirstSet)(source);
|
|
564
|
-
const meta = { firstSet, canMatchNewline, isTrivia: false };
|
|
574
|
+
const { firstSet: firstSet2, canMatchNewline } = (firstSetAnalyzer ?? permissiveFirstSet)(source);
|
|
575
|
+
const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
|
|
565
576
|
return {
|
|
566
577
|
_tag: "regex",
|
|
567
578
|
_meta: meta,
|
|
@@ -589,111 +600,266 @@ function regex(pattern, flags = "") {
|
|
|
589
600
|
};
|
|
590
601
|
}
|
|
591
602
|
|
|
592
|
-
// src/
|
|
593
|
-
var
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
return extractFirstSet(ast.body);
|
|
598
|
-
} catch {
|
|
599
|
-
return { firstSet: any(), canMatchNewline: true };
|
|
600
|
-
}
|
|
603
|
+
// src/regex/first-set.ts
|
|
604
|
+
var ANY = { t: "any" };
|
|
605
|
+
var EMPTY2 = { t: "empty" };
|
|
606
|
+
function charNode(set, nl) {
|
|
607
|
+
return { t: "char", set, nl };
|
|
601
608
|
}
|
|
602
|
-
function
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
609
|
+
function rangesToSet(ranges) {
|
|
610
|
+
let fs = empty();
|
|
611
|
+
for (const [lo, hi] of ranges) fs = union(fs, fromRange(lo, hi));
|
|
612
|
+
return fs;
|
|
613
|
+
}
|
|
614
|
+
function rangesHaveNewline(ranges) {
|
|
615
|
+
return ranges.some(([lo, hi]) => lo <= 10 && 10 <= hi);
|
|
616
|
+
}
|
|
617
|
+
var BAIL = /* @__PURE__ */ Symbol("regex-bail");
|
|
618
|
+
function parseRegex(src) {
|
|
619
|
+
let i = 0;
|
|
620
|
+
const parseAlt = () => {
|
|
621
|
+
const arms = [parseSeq()];
|
|
622
|
+
while (src[i] === "|") {
|
|
623
|
+
i++;
|
|
624
|
+
arms.push(parseSeq());
|
|
608
625
|
}
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
626
|
+
return arms.length === 1 ? arms[0] : { t: "alt", arms };
|
|
627
|
+
};
|
|
628
|
+
const parseSeq = () => {
|
|
629
|
+
const parts = [];
|
|
630
|
+
while (i < src.length) {
|
|
631
|
+
const ch = src[i];
|
|
632
|
+
if (ch === "|" || ch === ")") break;
|
|
633
|
+
parts.push(parseQuantified());
|
|
634
|
+
}
|
|
635
|
+
if (parts.length === 0) return EMPTY2;
|
|
636
|
+
return parts.length === 1 ? parts[0] : { t: "seq", parts };
|
|
637
|
+
};
|
|
638
|
+
const parseQuantified = () => {
|
|
639
|
+
const atom = parseAtom();
|
|
640
|
+
const ch = src[i];
|
|
641
|
+
let min = null;
|
|
642
|
+
if (ch === "*") {
|
|
643
|
+
min = 0;
|
|
644
|
+
i++;
|
|
645
|
+
} else if (ch === "+") {
|
|
646
|
+
min = 1;
|
|
647
|
+
i++;
|
|
648
|
+
} else if (ch === "?") {
|
|
649
|
+
min = 0;
|
|
650
|
+
i++;
|
|
651
|
+
} else if (ch === "{") {
|
|
652
|
+
min = parseBraceQuantifier();
|
|
612
653
|
}
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
654
|
+
if (min === null) return atom;
|
|
655
|
+
if (src[i] === "?") i++;
|
|
656
|
+
return { t: "rep", node: atom, min };
|
|
657
|
+
};
|
|
658
|
+
const parseBraceQuantifier = () => {
|
|
659
|
+
const close = src.indexOf("}", i);
|
|
660
|
+
if (close === -1) return null;
|
|
661
|
+
const m = /^(\d+)(?:,(\d*))?$/.exec(src.slice(i + 1, close));
|
|
662
|
+
if (!m) return null;
|
|
663
|
+
i = close + 1;
|
|
664
|
+
return Number.parseInt(m[1], 10);
|
|
665
|
+
};
|
|
666
|
+
const parseAtom = () => {
|
|
667
|
+
const ch = src[i];
|
|
668
|
+
switch (ch) {
|
|
669
|
+
case "(":
|
|
670
|
+
return parseGroup();
|
|
671
|
+
case "[":
|
|
672
|
+
return parseClass();
|
|
673
|
+
case ".":
|
|
674
|
+
i++;
|
|
675
|
+
return charNode(any(), false);
|
|
676
|
+
// `.` matches any char except line terminators
|
|
677
|
+
case "\\":
|
|
678
|
+
return parseEscape();
|
|
679
|
+
case "^":
|
|
680
|
+
case "$":
|
|
681
|
+
i++;
|
|
682
|
+
return EMPTY2;
|
|
683
|
+
// anchors are zero-width
|
|
684
|
+
case "{":
|
|
685
|
+
i++;
|
|
686
|
+
return charNode(fromRange(123, 123), false);
|
|
687
|
+
// a `{` with nothing to quantify is a literal brace
|
|
688
|
+
default:
|
|
689
|
+
i += ch.length;
|
|
690
|
+
return charNode(fromRange(ch.codePointAt(0), ch.codePointAt(0)), ch === "\n");
|
|
631
691
|
}
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
}
|
|
643
|
-
|
|
692
|
+
};
|
|
693
|
+
const parseGroup = () => {
|
|
694
|
+
i++;
|
|
695
|
+
let lookaround = false;
|
|
696
|
+
if (src[i] === "?") {
|
|
697
|
+
const c1 = src[i + 1];
|
|
698
|
+
if (c1 === ":") i += 2;
|
|
699
|
+
else if (c1 === "=" || c1 === "!") {
|
|
700
|
+
i += 2;
|
|
701
|
+
lookaround = true;
|
|
702
|
+
} else if (c1 === "<") {
|
|
703
|
+
const c2 = src[i + 2];
|
|
704
|
+
if (c2 === "=" || c2 === "!") {
|
|
705
|
+
i += 3;
|
|
706
|
+
lookaround = true;
|
|
707
|
+
} else {
|
|
708
|
+
const gt = src.indexOf(">", i);
|
|
709
|
+
if (gt === -1) throw BAIL;
|
|
710
|
+
i = gt + 1;
|
|
711
|
+
}
|
|
712
|
+
} else throw BAIL;
|
|
644
713
|
}
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
};
|
|
663
|
-
if (val === "s") return { firstSet: fromRange(9, 13), canMatchNewline: true };
|
|
664
|
-
if (val === "n") return { firstSet: fromRange(10, 10), canMatchNewline: true };
|
|
714
|
+
const inner = parseAlt();
|
|
715
|
+
if (src[i] !== ")") throw BAIL;
|
|
716
|
+
i++;
|
|
717
|
+
return lookaround ? EMPTY2 : inner;
|
|
718
|
+
};
|
|
719
|
+
const parseClass = () => {
|
|
720
|
+
let k = i + 1;
|
|
721
|
+
const negated = src[k] === "^";
|
|
722
|
+
if (negated) k++;
|
|
723
|
+
let body = "";
|
|
724
|
+
while (k < src.length && src[k] !== "]") {
|
|
725
|
+
if (src[k] === "\\") {
|
|
726
|
+
body += src[k] + (src[k + 1] ?? "");
|
|
727
|
+
k += 2;
|
|
728
|
+
} else {
|
|
729
|
+
body += src[k];
|
|
730
|
+
k++;
|
|
665
731
|
}
|
|
666
|
-
return { firstSet: any(), canMatchNewline: true };
|
|
667
732
|
}
|
|
668
|
-
|
|
669
|
-
|
|
733
|
+
if (src[k] !== "]") throw BAIL;
|
|
734
|
+
i = k + 1;
|
|
735
|
+
if (negated) return charNode(any(), true);
|
|
736
|
+
const ranges = parseClassRanges(body);
|
|
737
|
+
if (!ranges) return charNode(any(), true);
|
|
738
|
+
return charNode(rangesToSet(ranges), rangesHaveNewline(ranges));
|
|
739
|
+
};
|
|
740
|
+
const parseEscape = () => {
|
|
741
|
+
const e = src[i + 1];
|
|
742
|
+
if (e === void 0) throw BAIL;
|
|
743
|
+
if (e === "u" && /^[0-9a-fA-F]{4}$/.test(src.slice(i + 2, i + 6))) {
|
|
744
|
+
const cp = Number.parseInt(src.slice(i + 2, i + 6), 16);
|
|
745
|
+
i += 6;
|
|
746
|
+
return charNode(fromRange(cp, cp), cp === 10);
|
|
747
|
+
}
|
|
748
|
+
if (e === "x" && /^[0-9a-fA-F]{2}$/.test(src.slice(i + 2, i + 4))) {
|
|
749
|
+
const cp = Number.parseInt(src.slice(i + 2, i + 4), 16);
|
|
750
|
+
i += 4;
|
|
751
|
+
return charNode(fromRange(cp, cp), cp === 10);
|
|
752
|
+
}
|
|
753
|
+
i += 2;
|
|
754
|
+
switch (e) {
|
|
755
|
+
case "d":
|
|
756
|
+
return charNode(rangesToSet(shorthandRanges("d")), false);
|
|
757
|
+
case "w":
|
|
758
|
+
return charNode(rangesToSet(shorthandRanges("w")), false);
|
|
759
|
+
case "s":
|
|
760
|
+
return charNode(rangesToSet(shorthandRanges("s")), true);
|
|
761
|
+
case "D":
|
|
762
|
+
case "W":
|
|
763
|
+
case "S":
|
|
764
|
+
return charNode(any(), true);
|
|
765
|
+
// negated shorthand → widen
|
|
766
|
+
case "b":
|
|
767
|
+
case "B":
|
|
768
|
+
return EMPTY2;
|
|
769
|
+
// word boundary: zero-width
|
|
770
|
+
case "n":
|
|
771
|
+
return charNode(fromRange(10, 10), true);
|
|
772
|
+
case "r":
|
|
773
|
+
return charNode(fromRange(13, 13), false);
|
|
774
|
+
case "t":
|
|
775
|
+
return charNode(fromRange(9, 9), false);
|
|
776
|
+
case "f":
|
|
777
|
+
return charNode(fromRange(12, 12), false);
|
|
778
|
+
case "v":
|
|
779
|
+
return charNode(fromRange(11, 11), false);
|
|
780
|
+
case "0":
|
|
781
|
+
return charNode(fromRange(0, 0), false);
|
|
782
|
+
default:
|
|
783
|
+
if (e >= "1" && e <= "9") return ANY;
|
|
784
|
+
return charNode(fromRange(e.codePointAt(0), e.codePointAt(0)), e === "\n");
|
|
785
|
+
}
|
|
786
|
+
};
|
|
787
|
+
const node2 = parseAlt();
|
|
788
|
+
if (i < src.length) throw BAIL;
|
|
789
|
+
return node2;
|
|
790
|
+
}
|
|
791
|
+
function nullable(n) {
|
|
792
|
+
switch (n.t) {
|
|
793
|
+
case "char":
|
|
794
|
+
return false;
|
|
795
|
+
case "any":
|
|
796
|
+
return true;
|
|
797
|
+
case "empty":
|
|
798
|
+
return true;
|
|
799
|
+
case "seq":
|
|
800
|
+
return n.parts.every(nullable);
|
|
801
|
+
case "alt":
|
|
802
|
+
return n.arms.some(nullable);
|
|
803
|
+
case "rep":
|
|
804
|
+
return n.min === 0 || nullable(n.node);
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
function firstSet(n) {
|
|
808
|
+
switch (n.t) {
|
|
809
|
+
case "char":
|
|
810
|
+
return n.set;
|
|
811
|
+
case "any":
|
|
812
|
+
return any();
|
|
813
|
+
case "empty":
|
|
814
|
+
return empty();
|
|
815
|
+
case "rep":
|
|
816
|
+
return firstSet(n.node);
|
|
817
|
+
case "alt": {
|
|
670
818
|
let fs = empty();
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
if (expr.type === "ClassRange") {
|
|
674
|
-
const from = expr.from.codePoint;
|
|
675
|
-
const to = expr.to.codePoint;
|
|
676
|
-
fs = union(fs, fromRange(from, to));
|
|
677
|
-
if (from <= 10 && 10 <= to) canNL = true;
|
|
678
|
-
} else if (expr.type === "Char") {
|
|
679
|
-
const r = extractFirstSet(expr);
|
|
680
|
-
fs = union(fs, r.firstSet);
|
|
681
|
-
canNL = canNL || r.canMatchNewline;
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
if (node2.negative) return { firstSet: any(), canMatchNewline: true };
|
|
685
|
-
return { firstSet: fs, canMatchNewline: canNL };
|
|
819
|
+
for (const arm of n.arms) fs = union(fs, firstSet(arm));
|
|
820
|
+
return fs;
|
|
686
821
|
}
|
|
687
|
-
case "
|
|
688
|
-
|
|
822
|
+
case "seq": {
|
|
823
|
+
let fs = empty();
|
|
824
|
+
for (const part of n.parts) {
|
|
825
|
+
fs = union(fs, firstSet(part));
|
|
826
|
+
if (!nullable(part)) break;
|
|
827
|
+
}
|
|
828
|
+
return fs;
|
|
689
829
|
}
|
|
690
|
-
|
|
691
|
-
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
function firstCanBeNewline(n) {
|
|
833
|
+
switch (n.t) {
|
|
834
|
+
case "char":
|
|
835
|
+
return n.nl;
|
|
836
|
+
case "any":
|
|
837
|
+
return true;
|
|
838
|
+
case "empty":
|
|
839
|
+
return false;
|
|
840
|
+
case "rep":
|
|
841
|
+
return firstCanBeNewline(n.node);
|
|
842
|
+
case "alt":
|
|
843
|
+
return n.arms.some(firstCanBeNewline);
|
|
844
|
+
case "seq": {
|
|
845
|
+
for (const part of n.parts) {
|
|
846
|
+
if (firstCanBeNewline(part)) return true;
|
|
847
|
+
if (!nullable(part)) break;
|
|
848
|
+
}
|
|
849
|
+
return false;
|
|
692
850
|
}
|
|
693
|
-
default:
|
|
694
|
-
return { firstSet: any(), canMatchNewline: true };
|
|
695
851
|
}
|
|
696
852
|
}
|
|
853
|
+
function firstSetFromRegex(source) {
|
|
854
|
+
let ast;
|
|
855
|
+
try {
|
|
856
|
+
ast = parseRegex(source);
|
|
857
|
+
} catch {
|
|
858
|
+
return { firstSet: any(), canMatchNewline: true };
|
|
859
|
+
}
|
|
860
|
+
if (nullable(ast)) return { firstSet: any(), canMatchNewline: true };
|
|
861
|
+
return { firstSet: firstSet(ast), canMatchNewline: firstCanBeNewline(ast) };
|
|
862
|
+
}
|
|
697
863
|
|
|
698
864
|
// src/combinators/keywords.ts
|
|
699
865
|
function word(str, boundary = "_0-9A-Za-z") {
|
|
@@ -711,19 +877,19 @@ function keywords(words, opts = {}) {
|
|
|
711
877
|
const boundary = opts.boundary ? `(?![${opts.boundary}])` : "";
|
|
712
878
|
const flags = opts.caseInsensitive ? "iuy" : "uy";
|
|
713
879
|
const re = new RegExp(`(?:${alt})${boundary}`, flags);
|
|
714
|
-
let
|
|
880
|
+
let firstSet2 = empty();
|
|
715
881
|
for (const w of sorted) {
|
|
716
882
|
if (w.length === 0) continue;
|
|
717
883
|
const cp = w.codePointAt(0);
|
|
718
|
-
|
|
884
|
+
firstSet2 = union(firstSet2, fromChar(cp));
|
|
719
885
|
if (opts.caseInsensitive) {
|
|
720
886
|
const u = String.fromCodePoint(cp).toUpperCase().codePointAt(0);
|
|
721
887
|
const l = String.fromCodePoint(cp).toLowerCase().codePointAt(0);
|
|
722
|
-
if (u !== void 0)
|
|
723
|
-
if (l !== void 0)
|
|
888
|
+
if (u !== void 0) firstSet2 = union(firstSet2, fromChar(u));
|
|
889
|
+
if (l !== void 0) firstSet2 = union(firstSet2, fromChar(l));
|
|
724
890
|
}
|
|
725
891
|
}
|
|
726
|
-
const meta = { firstSet, canMatchNewline: false, isTrivia: false };
|
|
892
|
+
const meta = { firstSet: firstSet2, canMatchNewline: false, isTrivia: false };
|
|
727
893
|
return {
|
|
728
894
|
_tag: "keywords",
|
|
729
895
|
_meta: meta,
|
|
@@ -1117,10 +1283,10 @@ function needsDeferredTriviaCommit(ctx) {
|
|
|
1117
1283
|
}
|
|
1118
1284
|
function saveTriviaMark(ctx) {
|
|
1119
1285
|
const m = saveCstMark(ctx);
|
|
1120
|
-
return { raw: m.raw, tlog: m.tlog, leaves: m.leaves, log: ctx._triviaLog ? ctx._triviaLog.length : 0 };
|
|
1286
|
+
return { raw: m.raw, tlog: m.tlog, leaves: m.leaves, fields: m.fields, log: ctx._triviaLog ? ctx._triviaLog.length : 0 };
|
|
1121
1287
|
}
|
|
1122
1288
|
function rollbackTrivia(ctx, mark) {
|
|
1123
|
-
rollbackCstCapture(ctx, { raw: mark.raw, tlog: mark.tlog, leaves: mark.leaves });
|
|
1289
|
+
rollbackCstCapture(ctx, { raw: mark.raw, tlog: mark.tlog, leaves: mark.leaves, fields: mark.fields });
|
|
1124
1290
|
if (ctx._triviaLog) ctx._triviaLog.length = mark.log;
|
|
1125
1291
|
}
|
|
1126
1292
|
function scanWithLabels(input, cur, ctx) {
|
|
@@ -1494,6 +1660,13 @@ function ref() {
|
|
|
1494
1660
|
define(p) {
|
|
1495
1661
|
if (resolved) throw new Error("ref<T>() already defined");
|
|
1496
1662
|
resolved = p;
|
|
1663
|
+
meta.firstSet = p._meta.firstSet;
|
|
1664
|
+
meta.canMatchNewline = p._meta.canMatchNewline;
|
|
1665
|
+
meta.isTrivia = p._meta.isTrivia;
|
|
1666
|
+
if (p._meta.triviaKindLabels !== void 0) meta.triviaKindLabels = p._meta.triviaKindLabels;
|
|
1667
|
+
else delete meta.triviaKindLabels;
|
|
1668
|
+
if (p._meta.disjoint !== void 0) meta.disjoint = p._meta.disjoint;
|
|
1669
|
+
else delete meta.disjoint;
|
|
1497
1670
|
}
|
|
1498
1671
|
};
|
|
1499
1672
|
return slot;
|
|
@@ -1534,6 +1707,9 @@ function markUnusedValues(root) {
|
|
|
1534
1707
|
case "transform":
|
|
1535
1708
|
visit(def.parser, true);
|
|
1536
1709
|
return;
|
|
1710
|
+
case "field":
|
|
1711
|
+
visit(def.parser, true);
|
|
1712
|
+
return;
|
|
1537
1713
|
case "skip":
|
|
1538
1714
|
visit(def.main, consumed);
|
|
1539
1715
|
visit(def.skipped, false);
|
|
@@ -1585,6 +1761,11 @@ function markUnusedValues(root) {
|
|
|
1585
1761
|
}
|
|
1586
1762
|
|
|
1587
1763
|
// src/combinators/parser.ts
|
|
1764
|
+
function tagRule(r, key) {
|
|
1765
|
+
;
|
|
1766
|
+
r._ruleName = key;
|
|
1767
|
+
if (r._def.tag === "node" && r._def.type === void 0) r._def.type = key;
|
|
1768
|
+
}
|
|
1588
1769
|
function rules(factory) {
|
|
1589
1770
|
const cache = {};
|
|
1590
1771
|
const proxy = new Proxy(cache, {
|
|
@@ -1593,7 +1774,7 @@ function rules(factory) {
|
|
|
1593
1774
|
const record = target;
|
|
1594
1775
|
if (!(key in record)) {
|
|
1595
1776
|
const r = ref();
|
|
1596
|
-
r
|
|
1777
|
+
tagRule(r, key);
|
|
1597
1778
|
record[key] = r;
|
|
1598
1779
|
}
|
|
1599
1780
|
return record[key];
|
|
@@ -1604,12 +1785,12 @@ function rules(factory) {
|
|
|
1604
1785
|
const placeholder = cache[key];
|
|
1605
1786
|
const parser2 = definitions[key];
|
|
1606
1787
|
if (placeholder !== void 0 && typeof placeholder.define === "function") {
|
|
1607
|
-
;
|
|
1788
|
+
tagRule(parser2, key);
|
|
1608
1789
|
placeholder.define(parser2);
|
|
1609
1790
|
placeholder._meta.firstSet = parser2._meta.firstSet;
|
|
1610
1791
|
placeholder._meta.canMatchNewline = parser2._meta.canMatchNewline;
|
|
1611
1792
|
} else {
|
|
1612
|
-
;
|
|
1793
|
+
tagRule(parser2, key);
|
|
1613
1794
|
cache[key] = parser2;
|
|
1614
1795
|
}
|
|
1615
1796
|
}
|
|
@@ -1666,44 +1847,130 @@ function buildReadsTrivia(def) {
|
|
|
1666
1847
|
const src = def.buildSrc ?? def.build.toString();
|
|
1667
1848
|
const arity = confirmedBuildArity(src);
|
|
1668
1849
|
if (arity === null) return true;
|
|
1669
|
-
return arity >=
|
|
1850
|
+
return arity >= 5;
|
|
1670
1851
|
}
|
|
1671
1852
|
function buildReadsState(def) {
|
|
1672
1853
|
if (!def.build) return true;
|
|
1673
1854
|
const src = def.buildSrc ?? def.build.toString();
|
|
1674
1855
|
const arity = confirmedBuildArity(src);
|
|
1675
1856
|
if (arity === null) return true;
|
|
1676
|
-
return arity >=
|
|
1857
|
+
return arity >= 6;
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1860
|
+
// src/compiler/fields.ts
|
|
1861
|
+
function buildReadsFields(def) {
|
|
1862
|
+
if (!def.build) return true;
|
|
1863
|
+
const src = def.buildSrc ?? def.build.toString();
|
|
1864
|
+
const arity = confirmedBuildArity(src);
|
|
1865
|
+
if (arity === null) return true;
|
|
1866
|
+
return arity >= 2;
|
|
1867
|
+
}
|
|
1868
|
+
function parserHasOwnFields(p, seen = /* @__PURE__ */ new Set()) {
|
|
1869
|
+
if (seen.has(p)) return false;
|
|
1870
|
+
seen.add(p);
|
|
1871
|
+
const d = p._def;
|
|
1872
|
+
switch (d.tag) {
|
|
1873
|
+
case "field":
|
|
1874
|
+
return true;
|
|
1875
|
+
case "node":
|
|
1876
|
+
return false;
|
|
1877
|
+
case "lazy": {
|
|
1878
|
+
try {
|
|
1879
|
+
return parserHasOwnFields(d.thunk(), seen);
|
|
1880
|
+
} catch {
|
|
1881
|
+
return false;
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1884
|
+
case "sequence":
|
|
1885
|
+
case "choice":
|
|
1886
|
+
return d.parsers.some((x) => parserHasOwnFields(x, seen));
|
|
1887
|
+
case "sepBy":
|
|
1888
|
+
return parserHasOwnFields(d.parser, seen) || parserHasOwnFields(d.separator, seen);
|
|
1889
|
+
case "skip":
|
|
1890
|
+
return parserHasOwnFields(d.main, seen) || parserHasOwnFields(d.skipped, seen);
|
|
1891
|
+
case "grammar":
|
|
1892
|
+
return parserHasOwnFields(d.parser, seen) || (d.triviaParser ? parserHasOwnFields(d.triviaParser, seen) : false);
|
|
1893
|
+
case "scanTo":
|
|
1894
|
+
return parserHasOwnFields(d.sentinel, seen) || d.skip.some((x) => parserHasOwnFields(x, seen));
|
|
1895
|
+
case "recover":
|
|
1896
|
+
return parserHasOwnFields(d.parser, seen) || parserHasOwnFields(d.sentinel, seen);
|
|
1897
|
+
case "many":
|
|
1898
|
+
case "oneOrMore":
|
|
1899
|
+
case "optional":
|
|
1900
|
+
case "transform":
|
|
1901
|
+
case "trivia":
|
|
1902
|
+
case "token":
|
|
1903
|
+
case "label":
|
|
1904
|
+
case "expect":
|
|
1905
|
+
case "withCtx":
|
|
1906
|
+
case "not":
|
|
1907
|
+
return parserHasOwnFields(d.parser, seen);
|
|
1908
|
+
default:
|
|
1909
|
+
return false;
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
function buildFieldMap(captures) {
|
|
1913
|
+
if (!captures?.length) return void 0;
|
|
1914
|
+
const out = {};
|
|
1915
|
+
for (const cap of captures) {
|
|
1916
|
+
const entry = { value: cap.value, span: cap.span };
|
|
1917
|
+
const current = out[cap.name];
|
|
1918
|
+
if (current === void 0) out[cap.name] = entry;
|
|
1919
|
+
else if (Array.isArray(current)) current.push(entry);
|
|
1920
|
+
else out[cap.name] = [current, entry];
|
|
1921
|
+
}
|
|
1922
|
+
return out;
|
|
1677
1923
|
}
|
|
1678
1924
|
|
|
1679
1925
|
// src/combinators/node.ts
|
|
1680
|
-
function
|
|
1926
|
+
function unwrapChild(child) {
|
|
1681
1927
|
return child !== null && typeof child === "object" && child._tag === "leaf" ? child.value : child;
|
|
1682
1928
|
}
|
|
1683
|
-
function
|
|
1929
|
+
function isCstChild(value) {
|
|
1930
|
+
return typeof value === "object" && value !== null && (value._tag === "node" || value._tag === "leaf" || value._tag === "error");
|
|
1931
|
+
}
|
|
1932
|
+
function missingInferredType() {
|
|
1933
|
+
throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
|
|
1934
|
+
}
|
|
1935
|
+
function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
1936
|
+
const hasExplicitType = typeof typeOrCombinator === "string";
|
|
1937
|
+
const type = hasExplicitType ? typeOrCombinator : void 0;
|
|
1938
|
+
const combinator = hasExplicitType ? combinatorOrBuild : typeOrCombinator;
|
|
1939
|
+
const build = hasExplicitType ? buildOrOpts : combinatorOrBuild;
|
|
1940
|
+
const opts = hasExplicitType ? maybeOpts : buildOrOpts;
|
|
1941
|
+
const baseDef = { tag: "node", parser: combinator, ...type === void 0 ? {} : { type }, ...build === void 0 ? {} : { build } };
|
|
1684
1942
|
const meta = {
|
|
1685
1943
|
firstSet: combinator._meta.firstSet,
|
|
1686
1944
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
1687
1945
|
isTrivia: false
|
|
1688
1946
|
};
|
|
1947
|
+
const unwrap = opts?.unwrap === true;
|
|
1689
1948
|
const collapse = opts?.collapse === true;
|
|
1690
|
-
|
|
1949
|
+
if (unwrap && collapse) {
|
|
1950
|
+
throw new Error("node() options cannot set both unwrap and collapse");
|
|
1951
|
+
}
|
|
1952
|
+
const def = unwrap || collapse ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {} } : baseDef;
|
|
1691
1953
|
const capturesTrivia = build ? buildReadsTrivia(def) : true;
|
|
1692
1954
|
const clonesState = build ? buildReadsState(def) : true;
|
|
1955
|
+
const capturesFields = parserHasOwnFields(combinator) && (build ? buildReadsFields(def) : true);
|
|
1693
1956
|
return {
|
|
1694
1957
|
_tag: "node",
|
|
1695
1958
|
_meta: meta,
|
|
1696
1959
|
_def: def,
|
|
1697
1960
|
parse(input, pos, ctx) {
|
|
1698
1961
|
const saved = beginCstNodeCapture(ctx);
|
|
1962
|
+
const savedFields = ctx._fields;
|
|
1963
|
+
ctx._fields = capturesFields ? [] : void 0;
|
|
1699
1964
|
if (!capturesTrivia) ctx.captureTrivia = false;
|
|
1700
1965
|
const r = combinator.parse(input, pos, ctx);
|
|
1966
|
+
const fields = capturesFields ? buildFieldMap(ctx._fields) : void 0;
|
|
1967
|
+
ctx._fields = savedFields;
|
|
1701
1968
|
const { children, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
|
|
1702
1969
|
if (!r.ok) return r;
|
|
1703
1970
|
const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
|
|
1704
|
-
const
|
|
1705
|
-
const
|
|
1706
|
-
const rawEntry =
|
|
1971
|
+
const nodeType = def.type ?? missingInferredType();
|
|
1972
|
+
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 };
|
|
1973
|
+
const rawEntry = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : "", span: r.span };
|
|
1707
1974
|
if (saved.buf !== void 0 || saved.ch !== void 0) {
|
|
1708
1975
|
pushCstChild(ctx, built, rawEntry);
|
|
1709
1976
|
}
|
|
@@ -1764,6 +2031,19 @@ function label(name, combinator) {
|
|
|
1764
2031
|
}
|
|
1765
2032
|
};
|
|
1766
2033
|
}
|
|
2034
|
+
function field(name, combinator) {
|
|
2035
|
+
return {
|
|
2036
|
+
_tag: combinator._tag,
|
|
2037
|
+
_meta: combinator._meta,
|
|
2038
|
+
_def: { tag: "field", name, parser: combinator },
|
|
2039
|
+
parse(input, pos, ctx) {
|
|
2040
|
+
const result = combinator.parse(input, pos, ctx);
|
|
2041
|
+
if (!result.ok) return result;
|
|
2042
|
+
ctx._fields?.push({ name, value: result.value, span: result.span });
|
|
2043
|
+
return result;
|
|
2044
|
+
}
|
|
2045
|
+
};
|
|
2046
|
+
}
|
|
1767
2047
|
|
|
1768
2048
|
// src/compiler/line-index.ts
|
|
1769
2049
|
function buildLineIndex(input) {
|
|
@@ -1973,77 +2253,11 @@ function expect(combinator, label2) {
|
|
|
1973
2253
|
|
|
1974
2254
|
// src/compiler/scannable-run.ts
|
|
1975
2255
|
var BACKSLASH = 92;
|
|
1976
|
-
var CLASS_ESCAPES2 = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
1977
2256
|
var META = new Set("()[]{}*+?|^$.".split(""));
|
|
1978
|
-
var SPACE_RANGES2 = [
|
|
1979
|
-
[9, 13],
|
|
1980
|
-
[32, 32],
|
|
1981
|
-
[160, 160],
|
|
1982
|
-
[5760, 5760],
|
|
1983
|
-
[8192, 8202],
|
|
1984
|
-
[8232, 8232],
|
|
1985
|
-
[8233, 8233],
|
|
1986
|
-
[8239, 8239],
|
|
1987
|
-
[8287, 8287],
|
|
1988
|
-
[12288, 12288],
|
|
1989
|
-
[65279, 65279]
|
|
1990
|
-
];
|
|
1991
|
-
function shorthandRanges2(ch) {
|
|
1992
|
-
if (ch === "d") return [[48, 57]];
|
|
1993
|
-
if (ch === "s") return SPACE_RANGES2;
|
|
1994
|
-
return [[48, 57], [65, 90], [97, 122], [95, 95]];
|
|
1995
|
-
}
|
|
1996
|
-
function readUnicodeEscape(body, i) {
|
|
1997
|
-
if (body[i] !== "\\" || body[i + 1] !== "u") return null;
|
|
1998
|
-
const hex = body.slice(i + 2, i + 6);
|
|
1999
|
-
if (!/^[0-9a-fA-F]{4}$/.test(hex)) return null;
|
|
2000
|
-
return { cp: Number.parseInt(hex, 16), next: i + 6 };
|
|
2001
|
-
}
|
|
2002
|
-
function parseClassRanges(body) {
|
|
2003
|
-
const ranges = [];
|
|
2004
|
-
let i = 0;
|
|
2005
|
-
const readAtom = () => {
|
|
2006
|
-
const ch = body[i];
|
|
2007
|
-
if (ch === void 0) return null;
|
|
2008
|
-
if (ch === "\\") {
|
|
2009
|
-
const uni = readUnicodeEscape(body, i);
|
|
2010
|
-
if (uni) {
|
|
2011
|
-
i = uni.next;
|
|
2012
|
-
return { cp: uni.cp };
|
|
2013
|
-
}
|
|
2014
|
-
const e = body[i + 1];
|
|
2015
|
-
if (e === void 0) return null;
|
|
2016
|
-
i += 2;
|
|
2017
|
-
if (e in CLASS_ESCAPES2) return { cp: CLASS_ESCAPES2[e] };
|
|
2018
|
-
if (e === "d" || e === "w" || e === "s") return { set: shorthandRanges2(e) };
|
|
2019
|
-
if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
2020
|
-
return { cp: e.codePointAt(0) };
|
|
2021
|
-
}
|
|
2022
|
-
i += ch.length;
|
|
2023
|
-
return { cp: ch.codePointAt(0) };
|
|
2024
|
-
};
|
|
2025
|
-
while (i < body.length) {
|
|
2026
|
-
const lo = readAtom();
|
|
2027
|
-
if (lo === null) return null;
|
|
2028
|
-
if ("set" in lo) {
|
|
2029
|
-
ranges.push(...lo.set);
|
|
2030
|
-
continue;
|
|
2031
|
-
}
|
|
2032
|
-
if (body[i] === "-" && body[i + 1] !== void 0 && body[i + 1] !== "]") {
|
|
2033
|
-
i += 1;
|
|
2034
|
-
const hi = readAtom();
|
|
2035
|
-
if (hi === null || "set" in hi) return null;
|
|
2036
|
-
ranges.push([lo.cp, hi.cp]);
|
|
2037
|
-
} else {
|
|
2038
|
-
ranges.push([lo.cp, lo.cp]);
|
|
2039
|
-
}
|
|
2040
|
-
}
|
|
2041
|
-
return ranges.length ? ranges : null;
|
|
2042
|
-
}
|
|
2043
2257
|
function classToRanges(cls) {
|
|
2044
|
-
if (cls === "\\d") return
|
|
2045
|
-
if (cls === "\\w") return
|
|
2046
|
-
if (cls === "\\s") return
|
|
2258
|
+
if (cls === "\\d") return shorthandRanges("d");
|
|
2259
|
+
if (cls === "\\w") return shorthandRanges("w");
|
|
2260
|
+
if (cls === "\\s") return shorthandRanges("s");
|
|
2047
2261
|
const body = cls.slice(1, -1);
|
|
2048
2262
|
if (body.startsWith("^")) return null;
|
|
2049
2263
|
return parseClassRanges(body);
|
|
@@ -2061,7 +2275,7 @@ function literalCodePoints(frag) {
|
|
|
2061
2275
|
if (ch === "\\") {
|
|
2062
2276
|
const e = frag[i + 1];
|
|
2063
2277
|
if (e === void 0) return null;
|
|
2064
|
-
out.push(e in
|
|
2278
|
+
out.push(e in CLASS_ESCAPES ? CLASS_ESCAPES[e] : e.codePointAt(0));
|
|
2065
2279
|
i += 2;
|
|
2066
2280
|
continue;
|
|
2067
2281
|
}
|
|
@@ -2154,7 +2368,7 @@ function parseSeqParts(source) {
|
|
|
2154
2368
|
if (e === "d" || e === "w" || e === "s") {
|
|
2155
2369
|
flush();
|
|
2156
2370
|
i += 2;
|
|
2157
|
-
i += runFrom(
|
|
2371
|
+
i += runFrom(shorthandRanges(e), false, source[i]);
|
|
2158
2372
|
continue;
|
|
2159
2373
|
}
|
|
2160
2374
|
const uni = readUnicodeEscape(source, i);
|
|
@@ -2163,8 +2377,8 @@ function parseSeqParts(source) {
|
|
|
2163
2377
|
cp2 = uni.cp;
|
|
2164
2378
|
i = uni.next;
|
|
2165
2379
|
} else if (e === void 0) return null;
|
|
2166
|
-
else if (e in
|
|
2167
|
-
cp2 =
|
|
2380
|
+
else if (e in CLASS_ESCAPES) {
|
|
2381
|
+
cp2 = CLASS_ESCAPES[e];
|
|
2168
2382
|
i += 2;
|
|
2169
2383
|
} else if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
2170
2384
|
else {
|
|
@@ -2271,7 +2485,7 @@ function rangesSubset(sub, sup) {
|
|
|
2271
2485
|
}
|
|
2272
2486
|
function parseClassOperand(body) {
|
|
2273
2487
|
if (body === "\\d" || body === "\\w" || body === "\\s") {
|
|
2274
|
-
return { ranges:
|
|
2488
|
+
return { ranges: shorthandRanges(body[1]), negated: false };
|
|
2275
2489
|
}
|
|
2276
2490
|
if (body.length >= 2 && body[0] === "[" && body[body.length - 1] === "]") {
|
|
2277
2491
|
let inner = body.slice(1, -1);
|
|
@@ -2704,7 +2918,7 @@ function parseScanShapeCore(source) {
|
|
|
2704
2918
|
}
|
|
2705
2919
|
m = /^\\([dws])([+*])$/.exec(source);
|
|
2706
2920
|
if (m) {
|
|
2707
|
-
return { kind: "chars", ranges:
|
|
2921
|
+
return { kind: "chars", ranges: shorthandRanges(m[1]), minOne: m[2] === "+" };
|
|
2708
2922
|
}
|
|
2709
2923
|
m = /^(\[(?:\\.|[^\]])+\]|\\[dws])(\[(?:\\.|[^\]])+\]|\\[dws])\*$/.exec(source);
|
|
2710
2924
|
if (m) {
|
|
@@ -3246,21 +3460,22 @@ function emitScannableTerminal(shape, c) {
|
|
|
3246
3460
|
}
|
|
3247
3461
|
|
|
3248
3462
|
// src/compiler/inline-build.ts
|
|
3249
|
-
var MK_BUILD_RE = /^\(\s*(
|
|
3463
|
+
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*$/;
|
|
3250
3464
|
function escapeRegExp(s) {
|
|
3251
3465
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3252
3466
|
}
|
|
3253
3467
|
function looseMkBuildRe(type) {
|
|
3254
3468
|
return new RegExp(
|
|
3255
|
-
String.raw`^\(\s*(
|
|
3469
|
+
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*$`
|
|
3256
3470
|
);
|
|
3257
3471
|
}
|
|
3258
3472
|
function analyzeMkInlineBuild(def) {
|
|
3259
3473
|
if (!def.build) return null;
|
|
3474
|
+
if (def.type === void 0) return null;
|
|
3260
3475
|
const src = (def.buildSrc ?? def.build.toString()).trim();
|
|
3261
3476
|
const strict = src.match(MK_BUILD_RE);
|
|
3262
3477
|
if (strict) {
|
|
3263
|
-
const mkType = strict[
|
|
3478
|
+
const mkType = strict[6];
|
|
3264
3479
|
return mkType === def.type ? def.type : null;
|
|
3265
3480
|
}
|
|
3266
3481
|
if (looseMkBuildRe(def.type).test(src)) return def.type;
|
|
@@ -3587,8 +3802,9 @@ function planDisjointDispatch(parsers) {
|
|
|
3587
3802
|
}
|
|
3588
3803
|
return total >= SWITCH_MIN_CASES ? { kind: "switch", cases } : { kind: "if" };
|
|
3589
3804
|
}
|
|
3590
|
-
function captureRestoreBody(mL, mR, mTl, mLg) {
|
|
3591
|
-
const
|
|
3805
|
+
function captureRestoreBody(mL, mR, mTl, mLg, mF = null) {
|
|
3806
|
+
const fieldRestore = mF ? `; if (_ctx._fields) _ctx._fields.length = ${mF}` : "";
|
|
3807
|
+
const base = `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${mL}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${mR}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${mTl}${fieldRestore}`;
|
|
3592
3808
|
return mLg ? `${base}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${mLg}` : base;
|
|
3593
3809
|
}
|
|
3594
3810
|
function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
|
|
@@ -3636,6 +3852,7 @@ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
3636
3852
|
// Delegating wrappers: defer to the wrapped parser.
|
|
3637
3853
|
case "transform":
|
|
3638
3854
|
case "label":
|
|
3855
|
+
case "field":
|
|
3639
3856
|
case "expect":
|
|
3640
3857
|
case "withCtx":
|
|
3641
3858
|
case "grammar":
|
|
@@ -3682,6 +3899,7 @@ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
3682
3899
|
case "optional":
|
|
3683
3900
|
case "transform":
|
|
3684
3901
|
case "label":
|
|
3902
|
+
case "field":
|
|
3685
3903
|
case "expect":
|
|
3686
3904
|
case "withCtx":
|
|
3687
3905
|
case "grammar":
|
|
@@ -3719,22 +3937,25 @@ function emitFallible(inner, ctx, pos, swallow = false) {
|
|
|
3719
3937
|
ctx.recordFail = savedRecord;
|
|
3720
3938
|
const ind0 = ind(ctx);
|
|
3721
3939
|
const needsRollback = ctx.capturing && mayLeavePartialCapture(inner);
|
|
3940
|
+
const needsFieldRollback = needsRollback && parserHasOwnFields(inner);
|
|
3722
3941
|
const mL = needsRollback ? v(ctx, "_fcl") : null;
|
|
3723
3942
|
const mR = needsRollback ? v(ctx, "_fcr") : null;
|
|
3724
3943
|
const mTl = needsRollback ? v(ctx, "_fctl") : null;
|
|
3944
|
+
const mF = needsFieldRollback ? v(ctx, "_fcf") : null;
|
|
3725
3945
|
const stmts = [
|
|
3726
3946
|
`${ind0}let ${okV} = false, ${valV}, ${endV} = ${pos}`,
|
|
3727
3947
|
...mL ? [
|
|
3728
3948
|
`${ind0}const ${mL} = _ctx._cstLeaves?.length ?? 0`,
|
|
3729
3949
|
`${ind0}const ${mR} = _ctx._cstRawChildren?.length ?? 0`,
|
|
3730
|
-
`${ind0}const ${mTl} = _ctx._cstTriviaLog?.length ?? 0
|
|
3950
|
+
`${ind0}const ${mTl} = _ctx._cstTriviaLog?.length ?? 0`,
|
|
3951
|
+
...mF ? [`${ind0}const ${mF} = _ctx._fields?.length ?? 0`] : []
|
|
3731
3952
|
] : [],
|
|
3732
3953
|
`${ind0}${lbl}: {`,
|
|
3733
3954
|
...r.stmts,
|
|
3734
3955
|
`${ind0} ${valV} = ${r.valueVar}; ${endV} = ${r.endVar}; ${okV} = true`,
|
|
3735
3956
|
`${ind0}}`,
|
|
3736
3957
|
...mL ? [
|
|
3737
|
-
`${ind0}if (!${okV}) { ${captureRestoreBody(mL, mR, mTl, null)} }`
|
|
3958
|
+
`${ind0}if (!${okV}) { ${captureRestoreBody(mL, mR, mTl, null, mF)} }`
|
|
3738
3959
|
] : []
|
|
3739
3960
|
];
|
|
3740
3961
|
return { stmts, okVar: okV, valVar: valV, endVar: endV };
|
|
@@ -3961,6 +4182,7 @@ function failsAtStart(p) {
|
|
|
3961
4182
|
return true;
|
|
3962
4183
|
case "transform":
|
|
3963
4184
|
case "label":
|
|
4185
|
+
case "field":
|
|
3964
4186
|
return failsAtStart(d.parser);
|
|
3965
4187
|
default:
|
|
3966
4188
|
return false;
|
|
@@ -3980,6 +4202,7 @@ function canMatchEmptyAtStart(p) {
|
|
|
3980
4202
|
return true;
|
|
3981
4203
|
case "transform":
|
|
3982
4204
|
case "label":
|
|
4205
|
+
case "field":
|
|
3983
4206
|
return canMatchEmptyAtStart(d.parser);
|
|
3984
4207
|
case "literal":
|
|
3985
4208
|
return d.value.length === 0;
|
|
@@ -4162,11 +4385,13 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
4162
4385
|
const skipCond = gateCond ? `!${resOkV} && ${gateCond}` : `!${resOkV}`;
|
|
4163
4386
|
const armHasAutoNot = !!(autoNot && autoNot.length > 0);
|
|
4164
4387
|
const armNeedsRollback = ctx.capturing && (mayLeavePartialCapture(p) || armHasAutoNot && capturesLeaf(p));
|
|
4388
|
+
const armNeedsFieldRollback = armNeedsRollback && parserHasOwnFields(p);
|
|
4165
4389
|
const markLeaves = armNeedsRollback ? v(ctx, "_cml") : null;
|
|
4166
4390
|
const markRaw = armNeedsRollback ? v(ctx, "_cmr") : null;
|
|
4167
4391
|
const markTl = armNeedsRollback ? v(ctx, "_cmtl") : null;
|
|
4168
4392
|
const markLog = armNeedsRollback ? v(ctx, "_cmlg") : null;
|
|
4169
|
-
const
|
|
4393
|
+
const markFields = armNeedsFieldRollback ? v(ctx, "_cmf") : null;
|
|
4394
|
+
const rollback = markLeaves ? captureRestoreBody(markLeaves, markRaw, markTl, markLog, markFields) : "";
|
|
4170
4395
|
const failSlot = atStart ? staticFx : "_ctx._fx";
|
|
4171
4396
|
stmts.push(`${ind0}if (${skipCond}) {`);
|
|
4172
4397
|
if (fsGuard) stmts.push(`${ind(ctx)}if (${fsGuard}) {`);
|
|
@@ -4176,7 +4401,8 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
4176
4401
|
`${ind(ctx)}const ${markLeaves} = _ctx._cstLeaves?.length ?? 0`,
|
|
4177
4402
|
`${ind(ctx)}const ${markRaw} = _ctx._cstRawChildren?.length ?? 0`,
|
|
4178
4403
|
`${ind(ctx)}const ${markTl} = _ctx._cstTriviaLog?.length ?? 0`,
|
|
4179
|
-
`${ind(ctx)}const ${markLog} = _ctx._triviaLog?.length ?? 0
|
|
4404
|
+
`${ind(ctx)}const ${markLog} = _ctx._triviaLog?.length ?? 0`,
|
|
4405
|
+
...markFields ? [`${ind(ctx)}const ${markFields} = _ctx._fields?.length ?? 0`] : []
|
|
4180
4406
|
);
|
|
4181
4407
|
}
|
|
4182
4408
|
const { stmts: armStmts, okVar, valVar, endVar } = emitFallible(p, ctx, pos, atStart);
|
|
@@ -4569,6 +4795,9 @@ function emitToken(def, ctx, pos) {
|
|
|
4569
4795
|
};
|
|
4570
4796
|
}
|
|
4571
4797
|
function emitNode(def, ctx, pos) {
|
|
4798
|
+
if (def.type === void 0) {
|
|
4799
|
+
throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
|
|
4800
|
+
}
|
|
4572
4801
|
const structural = def.build === void 0;
|
|
4573
4802
|
const mkType = structural ? null : analyzeMkInlineBuild(def);
|
|
4574
4803
|
let buildIdx = null;
|
|
@@ -4580,25 +4809,36 @@ function emitNode(def, ctx, pos) {
|
|
|
4580
4809
|
const i = ind(ctx);
|
|
4581
4810
|
const capturesTrivia = mkType !== null || !structural && buildReadsTrivia(def);
|
|
4582
4811
|
const clonesState = !structural && buildReadsState(def);
|
|
4812
|
+
const hasFields = parserHasOwnFields(def.parser);
|
|
4813
|
+
const capturesFields = hasFields && !structural && buildReadsFields(def);
|
|
4583
4814
|
const chV = v(ctx, "_ch");
|
|
4584
4815
|
const rawV = v(ctx, "_raw");
|
|
4585
4816
|
const capTLv = structural ? v(ctx, "_ctl") : null;
|
|
4586
4817
|
const capSTv = structural ? v(ctx, "_cst") : null;
|
|
4818
|
+
const capFv = structural && hasFields ? v(ctx, "_cf") : null;
|
|
4587
4819
|
const tlV = capturesTrivia || structural ? v(ctx, "_tl") : "_EMPTY_TL";
|
|
4588
4820
|
if (!capturesTrivia) ctx.needsEmptyTl = true;
|
|
4589
4821
|
const sc = v(ctx, "_sc"), sl = v(ctx, "_sl"), sr = v(ctx, "_sr"), st = v(ctx, "_st"), stl = v(ctx, "_stl");
|
|
4590
4822
|
if (structural) ctx.needsHostReads = true;
|
|
4591
|
-
const
|
|
4823
|
+
const hostTriviaGate = `_ctx.build !== undefined && (_ctx.build._parsemanCaptureTrivia !== undefined ? _ctx.build._parsemanCaptureTrivia(${JSON.stringify(def.type)}) : (_ctx._pmCapTL ??= _hostReads(_ctx.build, 5)))`;
|
|
4824
|
+
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)` : ""}
|
|
4592
4825
|
${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capturesTrivia ? `${i}const ${chV} = [], ${rawV} = [], ${tlV} = []` : `${i}const ${chV} = [], ${rawV} = []`;
|
|
4593
4826
|
const innerTl = structural ? `${capTLv} ? ${tlV} : undefined` : capturesTrivia ? tlV : "undefined";
|
|
4827
|
+
const fieldsOn = structural ? capFv ?? "false" : capturesFields ? "true" : "false";
|
|
4828
|
+
const sf = hasFields ? v(ctx, "_sf") : null;
|
|
4829
|
+
const fArr = hasFields ? v(ctx, "_fa") : null;
|
|
4830
|
+
const fObj = hasFields ? v(ctx, "_fields") : "undefined";
|
|
4594
4831
|
const stmts = [
|
|
4595
4832
|
allocStmt,
|
|
4596
|
-
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog`,
|
|
4597
|
-
`${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true; _ctx._cstTriviaLog = ${innerTl}`
|
|
4833
|
+
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog${sf ? `, ${sf} = _ctx._fields` : ""}`,
|
|
4834
|
+
`${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true; _ctx._cstTriviaLog = ${innerTl}${sf ? `; _ctx._fields = ${fieldsOn} ? [] : undefined` : ""}`
|
|
4598
4835
|
];
|
|
4599
4836
|
const { stmts: innerStmts, okVar, endVar } = emitFallible(def.parser, ctx, pos);
|
|
4600
4837
|
stmts.push(...innerStmts);
|
|
4601
|
-
|
|
4838
|
+
if (sf && fArr) {
|
|
4839
|
+
stmts.push(`${i}const ${fArr} = _ctx._fields`);
|
|
4840
|
+
}
|
|
4841
|
+
stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}${sf ? `; _ctx._fields = ${sf}` : ""}`);
|
|
4602
4842
|
stmts.push(...emitIfFail(ctx, `!${okVar}`, propagateFailBody(ctx)));
|
|
4603
4843
|
let stV = "undefined";
|
|
4604
4844
|
if (structural) {
|
|
@@ -4608,14 +4848,33 @@ ${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capt
|
|
|
4608
4848
|
stV = v(ctx, "_nst");
|
|
4609
4849
|
stmts.push(`${i}const ${stV} = _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
|
|
4610
4850
|
}
|
|
4851
|
+
if (sf && fArr) {
|
|
4852
|
+
const fe = v(ctx, "_fe");
|
|
4853
|
+
const cur = v(ctx, "_fc");
|
|
4854
|
+
stmts.push(
|
|
4855
|
+
`${i}let ${fObj} = undefined`,
|
|
4856
|
+
`${i}if (${fArr} && ${fArr}.length) {`,
|
|
4857
|
+
`${i} ${fObj} = {}`,
|
|
4858
|
+
`${i} for (const ${fe} of ${fArr}) {`,
|
|
4859
|
+
`${i} const ${cur} = ${fObj}[${fe}.name], _entry = { value: ${fe}.value, span: ${fe}.span }`,
|
|
4860
|
+
`${i} if (${cur} === undefined) ${fObj}[${fe}.name] = _entry`,
|
|
4861
|
+
`${i} else if (Array.isArray(${cur})) ${cur}.push(_entry)`,
|
|
4862
|
+
`${i} else ${fObj}[${fe}.name] = [${cur}, _entry]`,
|
|
4863
|
+
`${i} }`,
|
|
4864
|
+
`${i}}`
|
|
4865
|
+
);
|
|
4866
|
+
}
|
|
4611
4867
|
const ndV = v(ctx, "_nd");
|
|
4612
|
-
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}, ${
|
|
4613
|
-
const ndExpr = ctx.ns || structural ? `_ctx.build !== undefined ? _ctx.build(${JSON.stringify(def.type)}, ${chV}, ${
|
|
4614
|
-
const
|
|
4868
|
+
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})`;
|
|
4869
|
+
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;
|
|
4870
|
+
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;
|
|
4871
|
+
const unwrapExpr = `${chV}.length === 1 ? (${chV}[0] !== null && typeof ${chV}[0] === 'object' && ${chV}[0]._tag === 'leaf' ? ${chV}[0].value : ${chV}[0]) : (${ndExpr})`;
|
|
4872
|
+
const collapseExpr = `${chV}.length === 1 ? ${chV}[0] : (${ndExpr})`;
|
|
4873
|
+
const finalExpr = def.unwrap ? unwrapExpr : def.collapse ? collapseExpr : hostCollapseExpr;
|
|
4615
4874
|
stmts.push(
|
|
4616
4875
|
`${i}const ${ndV} = ${finalExpr}`,
|
|
4617
4876
|
`${i}if (${sc}) ${sc}.push(${ndV})`,
|
|
4618
|
-
`${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} } })`
|
|
4877
|
+
`${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} } })`
|
|
4619
4878
|
);
|
|
4620
4879
|
return { stmts, valueVar: ndV, endVar };
|
|
4621
4880
|
}
|
|
@@ -4830,6 +5089,17 @@ function emitDispatch(p, ctx, pos) {
|
|
|
4830
5089
|
endVar: inner.endVar
|
|
4831
5090
|
};
|
|
4832
5091
|
}
|
|
5092
|
+
case "field": {
|
|
5093
|
+
const inner = emit(def.parser, ctx, pos);
|
|
5094
|
+
return {
|
|
5095
|
+
stmts: [
|
|
5096
|
+
...inner.stmts,
|
|
5097
|
+
`${ind(ctx)}if (_ctx._fields) _ctx._fields.push({ name: ${JSON.stringify(def.name)}, value: ${inner.valueVar}, span: { start: ${pos}, end: ${inner.endVar} } })`
|
|
5098
|
+
],
|
|
5099
|
+
valueVar: inner.valueVar,
|
|
5100
|
+
endVar: inner.endVar
|
|
5101
|
+
};
|
|
5102
|
+
}
|
|
4833
5103
|
case "grammar": {
|
|
4834
5104
|
const savedTrivia = ctx.activeTrivia;
|
|
4835
5105
|
const savedKindLabels = ctx.triviaKindLabels;
|
|
@@ -4931,6 +5201,7 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
4931
5201
|
case "trivia":
|
|
4932
5202
|
case "token":
|
|
4933
5203
|
case "label":
|
|
5204
|
+
case "field":
|
|
4934
5205
|
case "optional":
|
|
4935
5206
|
case "many":
|
|
4936
5207
|
case "oneOrMore":
|
|
@@ -4967,6 +5238,7 @@ function childrenOf(def) {
|
|
|
4967
5238
|
case "trivia":
|
|
4968
5239
|
case "token":
|
|
4969
5240
|
case "label":
|
|
5241
|
+
case "field":
|
|
4970
5242
|
case "grammar":
|
|
4971
5243
|
case "not":
|
|
4972
5244
|
case "node":
|
|
@@ -5208,6 +5480,11 @@ function assertRuleName(name) {
|
|
|
5208
5480
|
);
|
|
5209
5481
|
}
|
|
5210
5482
|
}
|
|
5483
|
+
function publicRuleWrapperSource(rule, fnSource) {
|
|
5484
|
+
const labels = rule._meta.triviaKindLabels;
|
|
5485
|
+
if (labels === void 0) return fnSource;
|
|
5486
|
+
return `Object.assign(${fnSource}, { _meta: { triviaKindLabels: ${JSON.stringify(labels)} } })`;
|
|
5487
|
+
}
|
|
5211
5488
|
function compileLinkable(ruleMapArg, ns) {
|
|
5212
5489
|
if (!ns) throw new Error("compileLinkable: ns must be a non-empty namespace");
|
|
5213
5490
|
for (const [, rule] of ruleMapArg) markUnusedValues(rule);
|
|
@@ -5310,7 +5587,7 @@ function compileLinkable(ruleMapArg, ns) {
|
|
|
5310
5587
|
ctx.recordFail = savedRec;
|
|
5311
5588
|
pushNamedFnDecl(ctx, fn, body.stmts, body.valueVar, body.endVar);
|
|
5312
5589
|
}
|
|
5313
|
-
perEntry.push({ key, r: emitNamedFnCall(ctx, fn, "_pos") });
|
|
5590
|
+
perEntry.push({ key, rule, r: emitNamedFnCall(ctx, fn, "_pos") });
|
|
5314
5591
|
}
|
|
5315
5592
|
if (ctx.runtimeParsers.length !== 0) return null;
|
|
5316
5593
|
const mfSrcs = ctx.mapFns.length > 0 && ctx.mapFnSrcs.every((s) => s !== null) ? ctx.mapFnSrcs : null;
|
|
@@ -5333,14 +5610,14 @@ function compileLinkable(ruleMapArg, ns) {
|
|
|
5333
5610
|
...privateFns
|
|
5334
5611
|
].filter(Boolean);
|
|
5335
5612
|
const wrappers = /* @__PURE__ */ new Map();
|
|
5336
|
-
for (const { key, r } of perEntry) {
|
|
5337
|
-
wrappers.set(key, [
|
|
5613
|
+
for (const { key, rule, r } of perEntry) {
|
|
5614
|
+
wrappers.set(key, publicRuleWrapperSource(rule, [
|
|
5338
5615
|
`function(input, _pos, _ctx) {`,
|
|
5339
5616
|
` let pos = _pos`,
|
|
5340
5617
|
...r.stmts,
|
|
5341
5618
|
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
5342
5619
|
`}`
|
|
5343
|
-
].join("\n"));
|
|
5620
|
+
].join("\n")));
|
|
5344
5621
|
}
|
|
5345
5622
|
const firstSets = /* @__PURE__ */ new Map();
|
|
5346
5623
|
for (const [key, rule] of ruleMap) {
|
|
@@ -5543,6 +5820,7 @@ function evalRuleMapIR(ir) {
|
|
|
5543
5820
|
"skip",
|
|
5544
5821
|
"trivia",
|
|
5545
5822
|
"label",
|
|
5823
|
+
"field",
|
|
5546
5824
|
"expect",
|
|
5547
5825
|
"_tf",
|
|
5548
5826
|
"_nd",
|
|
@@ -5569,6 +5847,7 @@ function evalRuleMapIR(ir) {
|
|
|
5569
5847
|
skip,
|
|
5570
5848
|
trivia,
|
|
5571
5849
|
label,
|
|
5850
|
+
field,
|
|
5572
5851
|
expect,
|
|
5573
5852
|
_tf,
|
|
5574
5853
|
_nd
|
|
@@ -5583,9 +5862,26 @@ function linkable(rulesMap, ns) {
|
|
|
5583
5862
|
if (!pieces) throw new Error("linkable(): this grammar cannot be compiled to a linkable artifact (contains a runtime-only parser fallback)");
|
|
5584
5863
|
return pieces;
|
|
5585
5864
|
}
|
|
5586
|
-
function
|
|
5865
|
+
function normalizeCstCollapse(collapse) {
|
|
5866
|
+
if (collapse === true) return () => true;
|
|
5867
|
+
if (Array.isArray(collapse)) {
|
|
5868
|
+
const types = new Set(collapse);
|
|
5869
|
+
return (type) => types.has(type);
|
|
5870
|
+
}
|
|
5871
|
+
return typeof collapse === "function" ? collapse : void 0;
|
|
5872
|
+
}
|
|
5873
|
+
function buildCstNode(type, children, _fields, span, _rawChildren, _triviaLog, state) {
|
|
5587
5874
|
return { _tag: "node", type, span: { start: span.start, end: span.end }, state: state ?? null, children: [...children] };
|
|
5588
5875
|
}
|
|
5876
|
+
function cstBuildHost(typeOrOptions, children, _fields, span, rawChildren, triviaLog, state) {
|
|
5877
|
+
if (typeof typeOrOptions === "string") {
|
|
5878
|
+
return buildCstNode(typeOrOptions, children ?? [], _fields, span ?? { start: 0, end: 0 }, rawChildren, triviaLog, state);
|
|
5879
|
+
}
|
|
5880
|
+
const collapse = normalizeCstCollapse(typeOrOptions?.collapse);
|
|
5881
|
+
const host = (type, children2, fields, span2, rawChildren2, triviaLog2, state2) => buildCstNode(type, children2, fields, span2, rawChildren2, triviaLog2, state2);
|
|
5882
|
+
if (collapse) host._parsemanCstCollapse = collapse;
|
|
5883
|
+
return host;
|
|
5884
|
+
}
|
|
5589
5885
|
function pick(grammar, names) {
|
|
5590
5886
|
const p = grammar.ruleFns instanceof Map ? grammar : linkable(grammar);
|
|
5591
5887
|
const keep = /* @__PURE__ */ new Set();
|
|
@@ -5617,8 +5913,9 @@ function fusedBody(pieces) {
|
|
|
5617
5913
|
}
|
|
5618
5914
|
}
|
|
5619
5915
|
const contributing = new Set(winner.values());
|
|
5620
|
-
const
|
|
5621
|
-
const
|
|
5916
|
+
const contributingPieces = [...contributing];
|
|
5917
|
+
const needsEmptyTl = contributingPieces.some((p) => p.needsEmptyTl);
|
|
5918
|
+
const needsHostReads = contributingPieces.some((p) => p.needsHostReads);
|
|
5622
5919
|
const lines = [
|
|
5623
5920
|
// Shared sentinel protocol (must match NAMED_FN_FAIL / NAMED_FN_END in codegen).
|
|
5624
5921
|
"const _pfFail = {}",
|
|
@@ -5626,7 +5923,7 @@ function fusedBody(pieces) {
|
|
|
5626
5923
|
...needsEmptyTl ? ["const _EMPTY_TL = Object.freeze([])"] : [],
|
|
5627
5924
|
...needsHostReads ? [HOST_READS_DECL] : [],
|
|
5628
5925
|
// Each contributing artifact's namespaced private prelude (regexes, _pf, …).
|
|
5629
|
-
...[...
|
|
5926
|
+
...[...new Set(contributingPieces.flatMap((p) => p.prelude))],
|
|
5630
5927
|
// The winning `_r_<Name>` function for each rule (one per name → no redeclare).
|
|
5631
5928
|
...[...winner].map(([k, p]) => p.ruleFns.get(k))
|
|
5632
5929
|
];
|
|
@@ -5649,7 +5946,7 @@ function fusedBody(pieces) {
|
|
|
5649
5946
|
}
|
|
5650
5947
|
);
|
|
5651
5948
|
const env = {};
|
|
5652
|
-
for (const p of
|
|
5949
|
+
for (const p of contributingPieces) {
|
|
5653
5950
|
if (p.mfFns.length) env[`${p.ns}mf`] = p.mfFns;
|
|
5654
5951
|
if (p.buildFns.length) env[`${p.ns}build`] = p.buildFns;
|
|
5655
5952
|
}
|
|
@@ -5669,14 +5966,23 @@ function materializePiece(p) {
|
|
|
5669
5966
|
if (!pieces) throw new Error(`compose: carried IR for ns "${p.ns}" could not be re-lowered`);
|
|
5670
5967
|
return pieces;
|
|
5671
5968
|
}
|
|
5672
|
-
function
|
|
5969
|
+
function nextComposeNs(used) {
|
|
5970
|
+
let ns;
|
|
5971
|
+
do {
|
|
5972
|
+
ns = `_lk${_nsCounter++}_`;
|
|
5973
|
+
} while (used.has(ns));
|
|
5974
|
+
used.add(ns);
|
|
5975
|
+
return ns;
|
|
5976
|
+
}
|
|
5977
|
+
function itemPieces(item, used) {
|
|
5673
5978
|
const carried = item[COMPOSED_PIECES];
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
return
|
|
5979
|
+
const pieces = Array.isArray(carried) ? carried.map(materializePiece) : item.ruleFns instanceof Map ? [item] : [linkable(item, nextComposeNs(used))];
|
|
5980
|
+
for (const p of pieces) used.add(p.ns);
|
|
5981
|
+
return pieces;
|
|
5677
5982
|
}
|
|
5678
5983
|
function compose(items) {
|
|
5679
|
-
const
|
|
5984
|
+
const used = /* @__PURE__ */ new Set();
|
|
5985
|
+
const pieces = items.flatMap((item) => itemPieces(item, used));
|
|
5680
5986
|
const map = fuseRules(pieces);
|
|
5681
5987
|
Object.defineProperty(map, COMPOSED_PIECES, { value: pieces, enumerable: false });
|
|
5682
5988
|
return map;
|