parseman 0.19.0 → 0.21.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 +3 -3
- package/dist/combinators/grammar.d.ts +8 -0
- package/dist/combinators/grammar.d.ts.map +1 -1
- package/dist/combinators/regex.d.ts +7 -7
- package/dist/combinators/regex.d.ts.map +1 -1
- package/dist/compiler/codegen.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/cst/trivia-kinds.d.ts +16 -0
- package/dist/cst/trivia-kinds.d.ts.map +1 -1
- package/dist/functional/run.d.ts +9 -0
- package/dist/functional/run.d.ts.map +1 -1
- package/dist/index.cjs +348 -226
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +348 -216
- package/dist/index.js.map +4 -4
- package/dist/plugin/index.cjs +345 -215
- package/dist/plugin/index.cjs.map +4 -4
- package/dist/plugin/index.js +345 -215
- 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 +22 -0
- 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/plugin/index.cjs
CHANGED
|
@@ -406,9 +406,9 @@ function asciiFoldEq(a, b) {
|
|
|
406
406
|
}
|
|
407
407
|
function literal(value, opts = {}) {
|
|
408
408
|
const caseInsensitive = opts.caseInsensitive ?? false;
|
|
409
|
-
const
|
|
409
|
+
const firstSet2 = value.length > 0 ? fromChar(value.codePointAt(0)) : empty();
|
|
410
410
|
const meta = {
|
|
411
|
-
firstSet,
|
|
411
|
+
firstSet: firstSet2,
|
|
412
412
|
canMatchNewline: value.includes("\n"),
|
|
413
413
|
isTrivia: false
|
|
414
414
|
};
|
|
@@ -420,7 +420,7 @@ function literal(value, opts = {}) {
|
|
|
420
420
|
meta.firstSet = firstLower !== void 0 && firstUpper !== void 0 ? firstLower === firstUpper ? { kind: "ranges", ranges: [{ lo: firstLower, hi: firstLower }] } : { kind: "ranges", ranges: [
|
|
421
421
|
{ lo: firstLower, hi: firstLower },
|
|
422
422
|
{ lo: firstUpper, hi: firstUpper }
|
|
423
|
-
] } :
|
|
423
|
+
] } : firstSet2;
|
|
424
424
|
}
|
|
425
425
|
return {
|
|
426
426
|
_tag: "literal",
|
|
@@ -443,68 +443,66 @@ function literal(value, opts = {}) {
|
|
|
443
443
|
};
|
|
444
444
|
}
|
|
445
445
|
|
|
446
|
-
// src/
|
|
447
|
-
var
|
|
448
|
-
function registerRegexAnalyzer(analyzer) {
|
|
449
|
-
firstSetAnalyzer = analyzer;
|
|
450
|
-
}
|
|
451
|
-
var permissiveFirstSet = () => ({ firstSet: any(), canMatchNewline: true });
|
|
452
|
-
var SCAN_BAIL_AT = 64;
|
|
446
|
+
// src/regex/classes.ts
|
|
447
|
+
var CLASS_ESCAPES = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
453
448
|
var SPACE_RANGES = [
|
|
454
449
|
[9, 13],
|
|
455
450
|
[32, 32],
|
|
456
451
|
[160, 160],
|
|
457
452
|
[5760, 5760],
|
|
458
453
|
[8192, 8202],
|
|
459
|
-
[8232,
|
|
454
|
+
[8232, 8232],
|
|
455
|
+
[8233, 8233],
|
|
460
456
|
[8239, 8239],
|
|
461
457
|
[8287, 8287],
|
|
462
458
|
[12288, 12288],
|
|
463
459
|
[65279, 65279]
|
|
464
460
|
];
|
|
465
|
-
var CLASS_ESCAPES = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
466
461
|
function shorthandRanges(ch) {
|
|
467
462
|
if (ch === "d") return [[48, 57]];
|
|
468
463
|
if (ch === "s") return SPACE_RANGES;
|
|
469
464
|
return [[48, 57], [65, 90], [97, 122], [95, 95]];
|
|
470
465
|
}
|
|
471
|
-
function
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
}
|
|
476
|
-
return false;
|
|
466
|
+
function readUnicodeEscape(body, i) {
|
|
467
|
+
if (body[i] !== "\\" || body[i + 1] !== "u") return null;
|
|
468
|
+
const hex = body.slice(i + 2, i + 6);
|
|
469
|
+
if (!/^[0-9a-fA-F]{4}$/.test(hex)) return null;
|
|
470
|
+
return { cp: Number.parseInt(hex, 16), next: i + 6 };
|
|
477
471
|
}
|
|
478
|
-
function
|
|
479
|
-
if (body.startsWith("^")) return null;
|
|
472
|
+
function parseClassRanges(body) {
|
|
480
473
|
const ranges = [];
|
|
481
474
|
let i = 0;
|
|
482
475
|
const readAtom = () => {
|
|
483
476
|
const ch = body[i];
|
|
484
477
|
if (ch === void 0) return null;
|
|
485
478
|
if (ch === "\\") {
|
|
486
|
-
const
|
|
487
|
-
if (
|
|
479
|
+
const uni = readUnicodeEscape(body, i);
|
|
480
|
+
if (uni) {
|
|
481
|
+
i = uni.next;
|
|
482
|
+
return { cp: uni.cp };
|
|
483
|
+
}
|
|
484
|
+
const e = body[i + 1];
|
|
485
|
+
if (e === void 0) return null;
|
|
488
486
|
i += 2;
|
|
489
|
-
if (
|
|
490
|
-
if (
|
|
491
|
-
if (
|
|
492
|
-
return { cp:
|
|
487
|
+
if (e in CLASS_ESCAPES) return { cp: CLASS_ESCAPES[e] };
|
|
488
|
+
if (e === "d" || e === "w" || e === "s") return { set: shorthandRanges(e) };
|
|
489
|
+
if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
490
|
+
return { cp: e.codePointAt(0) };
|
|
493
491
|
}
|
|
494
|
-
i
|
|
495
|
-
return { cp: ch.
|
|
492
|
+
i += ch.length;
|
|
493
|
+
return { cp: ch.codePointAt(0) };
|
|
496
494
|
};
|
|
497
495
|
while (i < body.length) {
|
|
498
496
|
const lo = readAtom();
|
|
499
|
-
if (
|
|
500
|
-
if ("
|
|
501
|
-
ranges.push(...lo.
|
|
497
|
+
if (lo === null) return null;
|
|
498
|
+
if ("set" in lo) {
|
|
499
|
+
ranges.push(...lo.set);
|
|
502
500
|
continue;
|
|
503
501
|
}
|
|
504
502
|
if (body[i] === "-" && body[i + 1] !== void 0 && body[i + 1] !== "]") {
|
|
505
|
-
i
|
|
503
|
+
i += 1;
|
|
506
504
|
const hi = readAtom();
|
|
507
|
-
if (
|
|
505
|
+
if (hi === null || "set" in hi) return null;
|
|
508
506
|
ranges.push([lo.cp, hi.cp]);
|
|
509
507
|
} else {
|
|
510
508
|
ranges.push([lo.cp, lo.cp]);
|
|
@@ -512,6 +510,25 @@ function readClassRanges(body) {
|
|
|
512
510
|
}
|
|
513
511
|
return ranges.length ? ranges : null;
|
|
514
512
|
}
|
|
513
|
+
|
|
514
|
+
// src/combinators/regex.ts
|
|
515
|
+
var firstSetAnalyzer = null;
|
|
516
|
+
function registerRegexAnalyzer(analyzer) {
|
|
517
|
+
firstSetAnalyzer = analyzer;
|
|
518
|
+
}
|
|
519
|
+
var permissiveFirstSet = () => ({ firstSet: any(), canMatchNewline: true });
|
|
520
|
+
var SCAN_BAIL_AT = 64;
|
|
521
|
+
function inRanges(cp, ranges) {
|
|
522
|
+
for (let i = 0; i < ranges.length; i++) {
|
|
523
|
+
const [lo, hi] = ranges[i];
|
|
524
|
+
if (cp >= lo && cp <= hi) return true;
|
|
525
|
+
}
|
|
526
|
+
return false;
|
|
527
|
+
}
|
|
528
|
+
function readClassRanges(body) {
|
|
529
|
+
if (body.startsWith("^")) return null;
|
|
530
|
+
return parseClassRanges(body);
|
|
531
|
+
}
|
|
515
532
|
function shortScanner(source, flags) {
|
|
516
533
|
if (/[imsuvy]/.test(flags)) return null;
|
|
517
534
|
let ranges = null;
|
|
@@ -545,8 +562,8 @@ function regex(pattern, flags = "") {
|
|
|
545
562
|
const resolvedFlags = typeof pattern === "string" ? flags : pattern.flags;
|
|
546
563
|
const anchored = new RegExp(source, "y" + resolvedFlags.replace(/[gy]/g, ""));
|
|
547
564
|
const scan = shortScanner(source, resolvedFlags);
|
|
548
|
-
const { firstSet, canMatchNewline } = (firstSetAnalyzer ?? permissiveFirstSet)(source);
|
|
549
|
-
const meta = { firstSet, canMatchNewline, isTrivia: false };
|
|
565
|
+
const { firstSet: firstSet2, canMatchNewline } = (firstSetAnalyzer ?? permissiveFirstSet)(source);
|
|
566
|
+
const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
|
|
550
567
|
return {
|
|
551
568
|
_tag: "regex",
|
|
552
569
|
_meta: meta,
|
|
@@ -574,111 +591,266 @@ function regex(pattern, flags = "") {
|
|
|
574
591
|
};
|
|
575
592
|
}
|
|
576
593
|
|
|
577
|
-
// src/
|
|
578
|
-
var
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
594
|
+
// src/regex/first-set.ts
|
|
595
|
+
var ANY = { t: "any" };
|
|
596
|
+
var EMPTY2 = { t: "empty" };
|
|
597
|
+
function charNode(set, nl) {
|
|
598
|
+
return { t: "char", set, nl };
|
|
599
|
+
}
|
|
600
|
+
function rangesToSet(ranges) {
|
|
601
|
+
let fs2 = empty();
|
|
602
|
+
for (const [lo, hi] of ranges) fs2 = union(fs2, fromRange(lo, hi));
|
|
603
|
+
return fs2;
|
|
604
|
+
}
|
|
605
|
+
function rangesHaveNewline(ranges) {
|
|
606
|
+
return ranges.some(([lo, hi]) => lo <= 10 && 10 <= hi);
|
|
586
607
|
}
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
608
|
+
var BAIL = /* @__PURE__ */ Symbol("regex-bail");
|
|
609
|
+
function parseRegex(src) {
|
|
610
|
+
let i = 0;
|
|
611
|
+
const parseAlt = () => {
|
|
612
|
+
const arms = [parseSeq()];
|
|
613
|
+
while (src[i] === "|") {
|
|
614
|
+
i++;
|
|
615
|
+
arms.push(parseSeq());
|
|
593
616
|
}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
617
|
+
return arms.length === 1 ? arms[0] : { t: "alt", arms };
|
|
618
|
+
};
|
|
619
|
+
const parseSeq = () => {
|
|
620
|
+
const parts = [];
|
|
621
|
+
while (i < src.length) {
|
|
622
|
+
const ch = src[i];
|
|
623
|
+
if (ch === "|" || ch === ")") break;
|
|
624
|
+
parts.push(parseQuantified());
|
|
625
|
+
}
|
|
626
|
+
if (parts.length === 0) return EMPTY2;
|
|
627
|
+
return parts.length === 1 ? parts[0] : { t: "seq", parts };
|
|
628
|
+
};
|
|
629
|
+
const parseQuantified = () => {
|
|
630
|
+
const atom = parseAtom();
|
|
631
|
+
const ch = src[i];
|
|
632
|
+
let min = null;
|
|
633
|
+
if (ch === "*") {
|
|
634
|
+
min = 0;
|
|
635
|
+
i++;
|
|
636
|
+
} else if (ch === "+") {
|
|
637
|
+
min = 1;
|
|
638
|
+
i++;
|
|
639
|
+
} else if (ch === "?") {
|
|
640
|
+
min = 0;
|
|
641
|
+
i++;
|
|
642
|
+
} else if (ch === "{") {
|
|
643
|
+
min = parseBraceQuantifier();
|
|
597
644
|
}
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
645
|
+
if (min === null) return atom;
|
|
646
|
+
if (src[i] === "?") i++;
|
|
647
|
+
return { t: "rep", node: atom, min };
|
|
648
|
+
};
|
|
649
|
+
const parseBraceQuantifier = () => {
|
|
650
|
+
const close = src.indexOf("}", i);
|
|
651
|
+
if (close === -1) return null;
|
|
652
|
+
const m = /^(\d+)(?:,(\d*))?$/.exec(src.slice(i + 1, close));
|
|
653
|
+
if (!m) return null;
|
|
654
|
+
i = close + 1;
|
|
655
|
+
return Number.parseInt(m[1], 10);
|
|
656
|
+
};
|
|
657
|
+
const parseAtom = () => {
|
|
658
|
+
const ch = src[i];
|
|
659
|
+
switch (ch) {
|
|
660
|
+
case "(":
|
|
661
|
+
return parseGroup();
|
|
662
|
+
case "[":
|
|
663
|
+
return parseClass();
|
|
664
|
+
case ".":
|
|
665
|
+
i++;
|
|
666
|
+
return charNode(any(), false);
|
|
667
|
+
// `.` matches any char except line terminators
|
|
668
|
+
case "\\":
|
|
669
|
+
return parseEscape();
|
|
670
|
+
case "^":
|
|
671
|
+
case "$":
|
|
672
|
+
i++;
|
|
673
|
+
return EMPTY2;
|
|
674
|
+
// anchors are zero-width
|
|
675
|
+
case "{":
|
|
676
|
+
i++;
|
|
677
|
+
return charNode(fromRange(123, 123), false);
|
|
678
|
+
// a `{` with nothing to quantify is a literal brace
|
|
679
|
+
default:
|
|
680
|
+
i += ch.length;
|
|
681
|
+
return charNode(fromRange(ch.codePointAt(0), ch.codePointAt(0)), ch === "\n");
|
|
616
682
|
}
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
}
|
|
628
|
-
|
|
683
|
+
};
|
|
684
|
+
const parseGroup = () => {
|
|
685
|
+
i++;
|
|
686
|
+
let lookaround = false;
|
|
687
|
+
if (src[i] === "?") {
|
|
688
|
+
const c1 = src[i + 1];
|
|
689
|
+
if (c1 === ":") i += 2;
|
|
690
|
+
else if (c1 === "=" || c1 === "!") {
|
|
691
|
+
i += 2;
|
|
692
|
+
lookaround = true;
|
|
693
|
+
} else if (c1 === "<") {
|
|
694
|
+
const c2 = src[i + 2];
|
|
695
|
+
if (c2 === "=" || c2 === "!") {
|
|
696
|
+
i += 3;
|
|
697
|
+
lookaround = true;
|
|
698
|
+
} else {
|
|
699
|
+
const gt = src.indexOf(">", i);
|
|
700
|
+
if (gt === -1) throw BAIL;
|
|
701
|
+
i = gt + 1;
|
|
702
|
+
}
|
|
703
|
+
} else throw BAIL;
|
|
629
704
|
}
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
};
|
|
648
|
-
if (val === "s") return { firstSet: fromRange(9, 13), canMatchNewline: true };
|
|
649
|
-
if (val === "n") return { firstSet: fromRange(10, 10), canMatchNewline: true };
|
|
705
|
+
const inner = parseAlt();
|
|
706
|
+
if (src[i] !== ")") throw BAIL;
|
|
707
|
+
i++;
|
|
708
|
+
return lookaround ? EMPTY2 : inner;
|
|
709
|
+
};
|
|
710
|
+
const parseClass = () => {
|
|
711
|
+
let k = i + 1;
|
|
712
|
+
const negated = src[k] === "^";
|
|
713
|
+
if (negated) k++;
|
|
714
|
+
let body = "";
|
|
715
|
+
while (k < src.length && src[k] !== "]") {
|
|
716
|
+
if (src[k] === "\\") {
|
|
717
|
+
body += src[k] + (src[k + 1] ?? "");
|
|
718
|
+
k += 2;
|
|
719
|
+
} else {
|
|
720
|
+
body += src[k];
|
|
721
|
+
k++;
|
|
650
722
|
}
|
|
651
|
-
return { firstSet: any(), canMatchNewline: true };
|
|
652
723
|
}
|
|
653
|
-
|
|
654
|
-
|
|
724
|
+
if (src[k] !== "]") throw BAIL;
|
|
725
|
+
i = k + 1;
|
|
726
|
+
if (negated) return charNode(any(), true);
|
|
727
|
+
const ranges = parseClassRanges(body);
|
|
728
|
+
if (!ranges) return charNode(any(), true);
|
|
729
|
+
return charNode(rangesToSet(ranges), rangesHaveNewline(ranges));
|
|
730
|
+
};
|
|
731
|
+
const parseEscape = () => {
|
|
732
|
+
const e = src[i + 1];
|
|
733
|
+
if (e === void 0) throw BAIL;
|
|
734
|
+
if (e === "u" && /^[0-9a-fA-F]{4}$/.test(src.slice(i + 2, i + 6))) {
|
|
735
|
+
const cp = Number.parseInt(src.slice(i + 2, i + 6), 16);
|
|
736
|
+
i += 6;
|
|
737
|
+
return charNode(fromRange(cp, cp), cp === 10);
|
|
738
|
+
}
|
|
739
|
+
if (e === "x" && /^[0-9a-fA-F]{2}$/.test(src.slice(i + 2, i + 4))) {
|
|
740
|
+
const cp = Number.parseInt(src.slice(i + 2, i + 4), 16);
|
|
741
|
+
i += 4;
|
|
742
|
+
return charNode(fromRange(cp, cp), cp === 10);
|
|
743
|
+
}
|
|
744
|
+
i += 2;
|
|
745
|
+
switch (e) {
|
|
746
|
+
case "d":
|
|
747
|
+
return charNode(rangesToSet(shorthandRanges("d")), false);
|
|
748
|
+
case "w":
|
|
749
|
+
return charNode(rangesToSet(shorthandRanges("w")), false);
|
|
750
|
+
case "s":
|
|
751
|
+
return charNode(rangesToSet(shorthandRanges("s")), true);
|
|
752
|
+
case "D":
|
|
753
|
+
case "W":
|
|
754
|
+
case "S":
|
|
755
|
+
return charNode(any(), true);
|
|
756
|
+
// negated shorthand → widen
|
|
757
|
+
case "b":
|
|
758
|
+
case "B":
|
|
759
|
+
return EMPTY2;
|
|
760
|
+
// word boundary: zero-width
|
|
761
|
+
case "n":
|
|
762
|
+
return charNode(fromRange(10, 10), true);
|
|
763
|
+
case "r":
|
|
764
|
+
return charNode(fromRange(13, 13), false);
|
|
765
|
+
case "t":
|
|
766
|
+
return charNode(fromRange(9, 9), false);
|
|
767
|
+
case "f":
|
|
768
|
+
return charNode(fromRange(12, 12), false);
|
|
769
|
+
case "v":
|
|
770
|
+
return charNode(fromRange(11, 11), false);
|
|
771
|
+
case "0":
|
|
772
|
+
return charNode(fromRange(0, 0), false);
|
|
773
|
+
default:
|
|
774
|
+
if (e >= "1" && e <= "9") return ANY;
|
|
775
|
+
return charNode(fromRange(e.codePointAt(0), e.codePointAt(0)), e === "\n");
|
|
776
|
+
}
|
|
777
|
+
};
|
|
778
|
+
const node2 = parseAlt();
|
|
779
|
+
if (i < src.length) throw BAIL;
|
|
780
|
+
return node2;
|
|
781
|
+
}
|
|
782
|
+
function nullable(n) {
|
|
783
|
+
switch (n.t) {
|
|
784
|
+
case "char":
|
|
785
|
+
return false;
|
|
786
|
+
case "any":
|
|
787
|
+
return true;
|
|
788
|
+
case "empty":
|
|
789
|
+
return true;
|
|
790
|
+
case "seq":
|
|
791
|
+
return n.parts.every(nullable);
|
|
792
|
+
case "alt":
|
|
793
|
+
return n.arms.some(nullable);
|
|
794
|
+
case "rep":
|
|
795
|
+
return n.min === 0 || nullable(n.node);
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
function firstSet(n) {
|
|
799
|
+
switch (n.t) {
|
|
800
|
+
case "char":
|
|
801
|
+
return n.set;
|
|
802
|
+
case "any":
|
|
803
|
+
return any();
|
|
804
|
+
case "empty":
|
|
805
|
+
return empty();
|
|
806
|
+
case "rep":
|
|
807
|
+
return firstSet(n.node);
|
|
808
|
+
case "alt": {
|
|
809
|
+
let fs2 = empty();
|
|
810
|
+
for (const arm of n.arms) fs2 = union(fs2, firstSet(arm));
|
|
811
|
+
return fs2;
|
|
812
|
+
}
|
|
813
|
+
case "seq": {
|
|
655
814
|
let fs2 = empty();
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
if (
|
|
659
|
-
const from = expr.from.codePoint;
|
|
660
|
-
const to = expr.to.codePoint;
|
|
661
|
-
fs2 = union(fs2, fromRange(from, to));
|
|
662
|
-
if (from <= 10 && 10 <= to) canNL = true;
|
|
663
|
-
} else if (expr.type === "Char") {
|
|
664
|
-
const r = extractFirstSet(expr);
|
|
665
|
-
fs2 = union(fs2, r.firstSet);
|
|
666
|
-
canNL = canNL || r.canMatchNewline;
|
|
667
|
-
}
|
|
815
|
+
for (const part of n.parts) {
|
|
816
|
+
fs2 = union(fs2, firstSet(part));
|
|
817
|
+
if (!nullable(part)) break;
|
|
668
818
|
}
|
|
669
|
-
|
|
670
|
-
return { firstSet: fs2, canMatchNewline: canNL };
|
|
671
|
-
}
|
|
672
|
-
case "Repetition": {
|
|
673
|
-
return extractFirstSet(node2.expression);
|
|
819
|
+
return fs2;
|
|
674
820
|
}
|
|
675
|
-
|
|
676
|
-
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
function firstCanBeNewline(n) {
|
|
824
|
+
switch (n.t) {
|
|
825
|
+
case "char":
|
|
826
|
+
return n.nl;
|
|
827
|
+
case "any":
|
|
828
|
+
return true;
|
|
829
|
+
case "empty":
|
|
830
|
+
return false;
|
|
831
|
+
case "rep":
|
|
832
|
+
return firstCanBeNewline(n.node);
|
|
833
|
+
case "alt":
|
|
834
|
+
return n.arms.some(firstCanBeNewline);
|
|
835
|
+
case "seq": {
|
|
836
|
+
for (const part of n.parts) {
|
|
837
|
+
if (firstCanBeNewline(part)) return true;
|
|
838
|
+
if (!nullable(part)) break;
|
|
839
|
+
}
|
|
840
|
+
return false;
|
|
677
841
|
}
|
|
678
|
-
default:
|
|
679
|
-
return { firstSet: any(), canMatchNewline: true };
|
|
680
842
|
}
|
|
681
843
|
}
|
|
844
|
+
function firstSetFromRegex(source) {
|
|
845
|
+
let ast;
|
|
846
|
+
try {
|
|
847
|
+
ast = parseRegex(source);
|
|
848
|
+
} catch {
|
|
849
|
+
return { firstSet: any(), canMatchNewline: true };
|
|
850
|
+
}
|
|
851
|
+
if (nullable(ast)) return { firstSet: any(), canMatchNewline: true };
|
|
852
|
+
return { firstSet: firstSet(ast), canMatchNewline: firstCanBeNewline(ast) };
|
|
853
|
+
}
|
|
682
854
|
|
|
683
855
|
// src/combinators/keywords.ts
|
|
684
856
|
function word(str, boundary = "_0-9A-Za-z") {
|
|
@@ -693,19 +865,19 @@ function keywords(words, opts = {}) {
|
|
|
693
865
|
const boundary = opts.boundary ? `(?![${opts.boundary}])` : "";
|
|
694
866
|
const flags = opts.caseInsensitive ? "iuy" : "uy";
|
|
695
867
|
const re = new RegExp(`(?:${alt})${boundary}`, flags);
|
|
696
|
-
let
|
|
868
|
+
let firstSet2 = empty();
|
|
697
869
|
for (const w of sorted) {
|
|
698
870
|
if (w.length === 0) continue;
|
|
699
871
|
const cp = w.codePointAt(0);
|
|
700
|
-
|
|
872
|
+
firstSet2 = union(firstSet2, fromChar(cp));
|
|
701
873
|
if (opts.caseInsensitive) {
|
|
702
874
|
const u = String.fromCodePoint(cp).toUpperCase().codePointAt(0);
|
|
703
875
|
const l = String.fromCodePoint(cp).toLowerCase().codePointAt(0);
|
|
704
|
-
if (u !== void 0)
|
|
705
|
-
if (l !== void 0)
|
|
876
|
+
if (u !== void 0) firstSet2 = union(firstSet2, fromChar(u));
|
|
877
|
+
if (l !== void 0) firstSet2 = union(firstSet2, fromChar(l));
|
|
706
878
|
}
|
|
707
879
|
}
|
|
708
|
-
const meta = { firstSet, canMatchNewline: false, isTrivia: false };
|
|
880
|
+
const meta = { firstSet: firstSet2, canMatchNewline: false, isTrivia: false };
|
|
709
881
|
return {
|
|
710
882
|
_tag: "keywords",
|
|
711
883
|
_meta: meta,
|
|
@@ -1082,13 +1254,25 @@ function tryFastLabeledScan(input, cur, trivia2) {
|
|
|
1082
1254
|
}
|
|
1083
1255
|
function recordTriviaChunks(ctx, chunks) {
|
|
1084
1256
|
const kinds = ctx.triviaKindLabels;
|
|
1257
|
+
const mask = ctx._triviaCaptureMask;
|
|
1085
1258
|
for (const ch of chunks) {
|
|
1086
1259
|
pushTriviaLogEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
|
|
1087
1260
|
if (ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0)) {
|
|
1088
|
-
|
|
1261
|
+
if (mask === void 0 || kinds === void 0 || (mask & 1 << ch.kindIndex) !== 0) {
|
|
1262
|
+
pushCstTriviaEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
|
|
1263
|
+
}
|
|
1089
1264
|
}
|
|
1090
1265
|
}
|
|
1091
1266
|
}
|
|
1267
|
+
function triviaKindMask(labels, keep) {
|
|
1268
|
+
if (!labels) return void 0;
|
|
1269
|
+
let mask = 0;
|
|
1270
|
+
for (const name of keep) {
|
|
1271
|
+
const idx = labels.indexOf(name);
|
|
1272
|
+
if (idx >= 0) mask |= 1 << idx;
|
|
1273
|
+
}
|
|
1274
|
+
return mask;
|
|
1275
|
+
}
|
|
1092
1276
|
|
|
1093
1277
|
// src/combinators/trivia-skip.ts
|
|
1094
1278
|
var NOOP_COMMIT = () => {
|
|
@@ -1740,10 +1924,15 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
1740
1924
|
const saved = beginCstNodeCapture(ctx);
|
|
1741
1925
|
const savedFields = ctx._fields;
|
|
1742
1926
|
ctx._fields = capturesFields ? [] : void 0;
|
|
1927
|
+
const savedMask = ctx._triviaCaptureMask;
|
|
1928
|
+
if (build === void 0 && ctx.build?._parsemanTriviaKinds !== void 0 && def.type !== void 0) {
|
|
1929
|
+
ctx._triviaCaptureMask = ctx.build._parsemanTriviaKinds(def.type);
|
|
1930
|
+
}
|
|
1743
1931
|
if (!capturesTrivia) ctx.captureTrivia = false;
|
|
1744
1932
|
const r = combinator.parse(input, pos, ctx);
|
|
1745
1933
|
const fields = capturesFields ? buildFieldMap(ctx._fields) : void 0;
|
|
1746
1934
|
ctx._fields = savedFields;
|
|
1935
|
+
ctx._triviaCaptureMask = savedMask;
|
|
1747
1936
|
const { children, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
|
|
1748
1937
|
if (!r.ok) return r;
|
|
1749
1938
|
const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
|
|
@@ -1881,7 +2070,13 @@ function parser(opts, root) {
|
|
|
1881
2070
|
trivia: opts.trivia,
|
|
1882
2071
|
...opts.trivia._meta.triviaKindLabels ? { triviaKindLabels: opts.trivia._meta.triviaKindLabels } : {}
|
|
1883
2072
|
} : {},
|
|
1884
|
-
...opts.captureTrivia || _ctx?.captureTrivia ? { captureTrivia: true } : {}
|
|
2073
|
+
...opts.captureTrivia || _ctx?.captureTrivia ? { captureTrivia: true } : {},
|
|
2074
|
+
// Kind-filter for per-node capture. Resolve against this scope's trivia
|
|
2075
|
+
// labels — this parser's own trivia if it declares one, else the INHERITED
|
|
2076
|
+
// labels (`_ctx.triviaKindLabels`), so captureTriviaKinds still applies when
|
|
2077
|
+
// trivia is inherited rather than re-declared here. No labels → undefined
|
|
2078
|
+
// (capture all).
|
|
2079
|
+
...opts.captureTriviaKinds && !clearTrivia ? { _triviaCaptureMask: triviaKindMask(opts.trivia?._meta.triviaKindLabels ?? _ctx?.triviaKindLabels, opts.captureTriviaKinds) } : {}
|
|
1885
2080
|
};
|
|
1886
2081
|
const result = root.parse(input, pos ?? 0, ctx);
|
|
1887
2082
|
if (trackLines) {
|
|
@@ -2009,77 +2204,11 @@ function expect(combinator, label2) {
|
|
|
2009
2204
|
|
|
2010
2205
|
// src/compiler/scannable-run.ts
|
|
2011
2206
|
var BACKSLASH = 92;
|
|
2012
|
-
var CLASS_ESCAPES2 = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
2013
2207
|
var META = new Set("()[]{}*+?|^$.".split(""));
|
|
2014
|
-
var SPACE_RANGES2 = [
|
|
2015
|
-
[9, 13],
|
|
2016
|
-
[32, 32],
|
|
2017
|
-
[160, 160],
|
|
2018
|
-
[5760, 5760],
|
|
2019
|
-
[8192, 8202],
|
|
2020
|
-
[8232, 8232],
|
|
2021
|
-
[8233, 8233],
|
|
2022
|
-
[8239, 8239],
|
|
2023
|
-
[8287, 8287],
|
|
2024
|
-
[12288, 12288],
|
|
2025
|
-
[65279, 65279]
|
|
2026
|
-
];
|
|
2027
|
-
function shorthandRanges2(ch) {
|
|
2028
|
-
if (ch === "d") return [[48, 57]];
|
|
2029
|
-
if (ch === "s") return SPACE_RANGES2;
|
|
2030
|
-
return [[48, 57], [65, 90], [97, 122], [95, 95]];
|
|
2031
|
-
}
|
|
2032
|
-
function readUnicodeEscape(body, i) {
|
|
2033
|
-
if (body[i] !== "\\" || body[i + 1] !== "u") return null;
|
|
2034
|
-
const hex = body.slice(i + 2, i + 6);
|
|
2035
|
-
if (!/^[0-9a-fA-F]{4}$/.test(hex)) return null;
|
|
2036
|
-
return { cp: Number.parseInt(hex, 16), next: i + 6 };
|
|
2037
|
-
}
|
|
2038
|
-
function parseClassRanges(body) {
|
|
2039
|
-
const ranges = [];
|
|
2040
|
-
let i = 0;
|
|
2041
|
-
const readAtom = () => {
|
|
2042
|
-
const ch = body[i];
|
|
2043
|
-
if (ch === void 0) return null;
|
|
2044
|
-
if (ch === "\\") {
|
|
2045
|
-
const uni = readUnicodeEscape(body, i);
|
|
2046
|
-
if (uni) {
|
|
2047
|
-
i = uni.next;
|
|
2048
|
-
return { cp: uni.cp };
|
|
2049
|
-
}
|
|
2050
|
-
const e = body[i + 1];
|
|
2051
|
-
if (e === void 0) return null;
|
|
2052
|
-
i += 2;
|
|
2053
|
-
if (e in CLASS_ESCAPES2) return { cp: CLASS_ESCAPES2[e] };
|
|
2054
|
-
if (e === "d" || e === "w" || e === "s") return { set: shorthandRanges2(e) };
|
|
2055
|
-
if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
2056
|
-
return { cp: e.codePointAt(0) };
|
|
2057
|
-
}
|
|
2058
|
-
i += ch.length;
|
|
2059
|
-
return { cp: ch.codePointAt(0) };
|
|
2060
|
-
};
|
|
2061
|
-
while (i < body.length) {
|
|
2062
|
-
const lo = readAtom();
|
|
2063
|
-
if (lo === null) return null;
|
|
2064
|
-
if ("set" in lo) {
|
|
2065
|
-
ranges.push(...lo.set);
|
|
2066
|
-
continue;
|
|
2067
|
-
}
|
|
2068
|
-
if (body[i] === "-" && body[i + 1] !== void 0 && body[i + 1] !== "]") {
|
|
2069
|
-
i += 1;
|
|
2070
|
-
const hi = readAtom();
|
|
2071
|
-
if (hi === null || "set" in hi) return null;
|
|
2072
|
-
ranges.push([lo.cp, hi.cp]);
|
|
2073
|
-
} else {
|
|
2074
|
-
ranges.push([lo.cp, lo.cp]);
|
|
2075
|
-
}
|
|
2076
|
-
}
|
|
2077
|
-
return ranges.length ? ranges : null;
|
|
2078
|
-
}
|
|
2079
2208
|
function classToRanges(cls) {
|
|
2080
|
-
if (cls === "\\d") return
|
|
2081
|
-
if (cls === "\\w") return
|
|
2082
|
-
if (cls === "\\s") return
|
|
2209
|
+
if (cls === "\\d") return shorthandRanges("d");
|
|
2210
|
+
if (cls === "\\w") return shorthandRanges("w");
|
|
2211
|
+
if (cls === "\\s") return shorthandRanges("s");
|
|
2083
2212
|
const body = cls.slice(1, -1);
|
|
2084
2213
|
if (body.startsWith("^")) return null;
|
|
2085
2214
|
return parseClassRanges(body);
|
|
@@ -2097,7 +2226,7 @@ function literalCodePoints(frag) {
|
|
|
2097
2226
|
if (ch === "\\") {
|
|
2098
2227
|
const e = frag[i + 1];
|
|
2099
2228
|
if (e === void 0) return null;
|
|
2100
|
-
out.push(e in
|
|
2229
|
+
out.push(e in CLASS_ESCAPES ? CLASS_ESCAPES[e] : e.codePointAt(0));
|
|
2101
2230
|
i += 2;
|
|
2102
2231
|
continue;
|
|
2103
2232
|
}
|
|
@@ -2190,7 +2319,7 @@ function parseSeqParts(source) {
|
|
|
2190
2319
|
if (e === "d" || e === "w" || e === "s") {
|
|
2191
2320
|
flush();
|
|
2192
2321
|
i += 2;
|
|
2193
|
-
i += runFrom(
|
|
2322
|
+
i += runFrom(shorthandRanges(e), false, source[i]);
|
|
2194
2323
|
continue;
|
|
2195
2324
|
}
|
|
2196
2325
|
const uni = readUnicodeEscape(source, i);
|
|
@@ -2199,8 +2328,8 @@ function parseSeqParts(source) {
|
|
|
2199
2328
|
cp2 = uni.cp;
|
|
2200
2329
|
i = uni.next;
|
|
2201
2330
|
} else if (e === void 0) return null;
|
|
2202
|
-
else if (e in
|
|
2203
|
-
cp2 =
|
|
2331
|
+
else if (e in CLASS_ESCAPES) {
|
|
2332
|
+
cp2 = CLASS_ESCAPES[e];
|
|
2204
2333
|
i += 2;
|
|
2205
2334
|
} else if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
2206
2335
|
else {
|
|
@@ -2307,7 +2436,7 @@ function rangesSubset(sub, sup) {
|
|
|
2307
2436
|
}
|
|
2308
2437
|
function parseClassOperand(body) {
|
|
2309
2438
|
if (body === "\\d" || body === "\\w" || body === "\\s") {
|
|
2310
|
-
return { ranges:
|
|
2439
|
+
return { ranges: shorthandRanges(body[1]), negated: false };
|
|
2311
2440
|
}
|
|
2312
2441
|
if (body.length >= 2 && body[0] === "[" && body[body.length - 1] === "]") {
|
|
2313
2442
|
let inner = body.slice(1, -1);
|
|
@@ -2740,7 +2869,7 @@ function parseScanShapeCore(source) {
|
|
|
2740
2869
|
}
|
|
2741
2870
|
m = /^\\([dws])([+*])$/.exec(source);
|
|
2742
2871
|
if (m) {
|
|
2743
|
-
return { kind: "chars", ranges:
|
|
2872
|
+
return { kind: "chars", ranges: shorthandRanges(m[1]), minOne: m[2] === "+" };
|
|
2744
2873
|
}
|
|
2745
2874
|
m = /^(\[(?:\\.|[^\]])+\]|\\[dws])(\[(?:\\.|[^\]])+\]|\\[dws])\*$/.exec(source);
|
|
2746
2875
|
if (m) {
|
|
@@ -3097,7 +3226,7 @@ function scanBranchLabeled(shape, kindIndex, mint) {
|
|
|
3097
3226
|
` if (${m.end} > _e) {`,
|
|
3098
3227
|
` if (_cap) {`,
|
|
3099
3228
|
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, ${m.end}, ${kindIndex})`,
|
|
3100
|
-
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_e, ${m.end}, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${kindIndex})`,
|
|
3229
|
+
` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << kindIndex}))) _ctx._cstTriviaLog.push(_e, ${m.end}, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${kindIndex})`,
|
|
3101
3230
|
` }`,
|
|
3102
3231
|
` _e = ${m.end}`,
|
|
3103
3232
|
` continue`,
|
|
@@ -3213,7 +3342,7 @@ function buildLabeledRegexTriviaFnDecl(fnName, spec, reNames) {
|
|
|
3213
3342
|
` const _ce = _e + _m${i}[0].length`,
|
|
3214
3343
|
` if (_cap) {`,
|
|
3215
3344
|
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
|
|
3216
|
-
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
|
|
3345
|
+
` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
|
|
3217
3346
|
` }`,
|
|
3218
3347
|
` _e = _ce`,
|
|
3219
3348
|
` _matched = true`,
|
|
@@ -3251,7 +3380,7 @@ function buildLabeledRuntimeTriviaFnDecl(fnName, spec, rpStartIndex) {
|
|
|
3251
3380
|
` const _ce = _r${i}.span.end`,
|
|
3252
3381
|
` if (_cap) {`,
|
|
3253
3382
|
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
|
|
3254
|
-
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
|
|
3383
|
+
` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
|
|
3255
3384
|
` }`,
|
|
3256
3385
|
` _e = _ce`,
|
|
3257
3386
|
` _matched = true`,
|
|
@@ -4649,6 +4778,7 @@ function emitNode(def, ctx, pos) {
|
|
|
4649
4778
|
const tlV = capturesTrivia || structural ? v(ctx, "_tl") : "_EMPTY_TL";
|
|
4650
4779
|
if (!capturesTrivia) ctx.needsEmptyTl = true;
|
|
4651
4780
|
const sc = v(ctx, "_sc"), sl = v(ctx, "_sl"), sr = v(ctx, "_sr"), st = v(ctx, "_st"), stl = v(ctx, "_stl");
|
|
4781
|
+
const smk = structural ? v(ctx, "_smk") : null;
|
|
4652
4782
|
if (structural) ctx.needsHostReads = true;
|
|
4653
4783
|
const hostTriviaGate = `_ctx.build !== undefined && (_ctx.build._parsemanCaptureTrivia !== undefined ? _ctx.build._parsemanCaptureTrivia(${JSON.stringify(def.type)}) : (_ctx._pmCapTL ??= _hostReads(_ctx.build, 5)))`;
|
|
4654
4784
|
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)` : ""}
|
|
@@ -4660,15 +4790,15 @@ ${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capt
|
|
|
4660
4790
|
const fObj = hasFields ? v(ctx, "_fields") : "undefined";
|
|
4661
4791
|
const stmts = [
|
|
4662
4792
|
allocStmt,
|
|
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` : ""}`
|
|
4793
|
+
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog${smk ? `, ${smk} = _ctx._triviaCaptureMask` : ""}${sf ? `, ${sf} = _ctx._fields` : ""}`,
|
|
4794
|
+
`${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true; _ctx._cstTriviaLog = ${innerTl}${smk ? `; _ctx._triviaCaptureMask = ${capTLv} && _ctx.build._parsemanTriviaKinds !== undefined ? _ctx.build._parsemanTriviaKinds(${JSON.stringify(def.type)}) : ${smk}` : ""}${sf ? `; _ctx._fields = ${fieldsOn} ? [] : undefined` : ""}`
|
|
4665
4795
|
];
|
|
4666
4796
|
const { stmts: innerStmts, okVar, endVar } = emitFallible(def.parser, ctx, pos);
|
|
4667
4797
|
stmts.push(...innerStmts);
|
|
4668
4798
|
if (sf && fArr) {
|
|
4669
4799
|
stmts.push(`${i}const ${fArr} = _ctx._fields`);
|
|
4670
4800
|
}
|
|
4671
|
-
stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}${sf ? `; _ctx._fields = ${sf}` : ""}`);
|
|
4801
|
+
stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}${smk ? `; _ctx._triviaCaptureMask = ${smk}` : ""}${sf ? `; _ctx._fields = ${sf}` : ""}`);
|
|
4672
4802
|
stmts.push(...emitIfFail(ctx, `!${okVar}`, propagateFailBody(ctx)));
|
|
4673
4803
|
let stV = "undefined";
|
|
4674
4804
|
if (structural) {
|