parseman 0.19.0 → 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 +3 -3
- package/dist/combinators/regex.d.ts +7 -7
- package/dist/combinators/regex.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/index.cjs +313 -217
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +313 -207
- package/dist/index.js.map +4 -4
- package/dist/plugin/index.cjs +313 -207
- package/dist/plugin/index.cjs.map +4 -4
- package/dist/plugin/index.js +313 -207
- 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/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
|
-
return extractFirstSet(ast.body);
|
|
583
|
-
} catch {
|
|
584
|
-
return { firstSet: any(), canMatchNewline: true };
|
|
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 };
|
|
586
599
|
}
|
|
587
|
-
function
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
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);
|
|
607
|
+
}
|
|
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 };
|
|
819
|
+
return fs2;
|
|
671
820
|
}
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
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,
|
|
@@ -2009,77 +2181,11 @@ function expect(combinator, label2) {
|
|
|
2009
2181
|
|
|
2010
2182
|
// src/compiler/scannable-run.ts
|
|
2011
2183
|
var BACKSLASH = 92;
|
|
2012
|
-
var CLASS_ESCAPES2 = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
2013
2184
|
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
2185
|
function classToRanges(cls) {
|
|
2080
|
-
if (cls === "\\d") return
|
|
2081
|
-
if (cls === "\\w") return
|
|
2082
|
-
if (cls === "\\s") return
|
|
2186
|
+
if (cls === "\\d") return shorthandRanges("d");
|
|
2187
|
+
if (cls === "\\w") return shorthandRanges("w");
|
|
2188
|
+
if (cls === "\\s") return shorthandRanges("s");
|
|
2083
2189
|
const body = cls.slice(1, -1);
|
|
2084
2190
|
if (body.startsWith("^")) return null;
|
|
2085
2191
|
return parseClassRanges(body);
|
|
@@ -2097,7 +2203,7 @@ function literalCodePoints(frag) {
|
|
|
2097
2203
|
if (ch === "\\") {
|
|
2098
2204
|
const e = frag[i + 1];
|
|
2099
2205
|
if (e === void 0) return null;
|
|
2100
|
-
out.push(e in
|
|
2206
|
+
out.push(e in CLASS_ESCAPES ? CLASS_ESCAPES[e] : e.codePointAt(0));
|
|
2101
2207
|
i += 2;
|
|
2102
2208
|
continue;
|
|
2103
2209
|
}
|
|
@@ -2190,7 +2296,7 @@ function parseSeqParts(source) {
|
|
|
2190
2296
|
if (e === "d" || e === "w" || e === "s") {
|
|
2191
2297
|
flush();
|
|
2192
2298
|
i += 2;
|
|
2193
|
-
i += runFrom(
|
|
2299
|
+
i += runFrom(shorthandRanges(e), false, source[i]);
|
|
2194
2300
|
continue;
|
|
2195
2301
|
}
|
|
2196
2302
|
const uni = readUnicodeEscape(source, i);
|
|
@@ -2199,8 +2305,8 @@ function parseSeqParts(source) {
|
|
|
2199
2305
|
cp2 = uni.cp;
|
|
2200
2306
|
i = uni.next;
|
|
2201
2307
|
} else if (e === void 0) return null;
|
|
2202
|
-
else if (e in
|
|
2203
|
-
cp2 =
|
|
2308
|
+
else if (e in CLASS_ESCAPES) {
|
|
2309
|
+
cp2 = CLASS_ESCAPES[e];
|
|
2204
2310
|
i += 2;
|
|
2205
2311
|
} else if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
2206
2312
|
else {
|
|
@@ -2307,7 +2413,7 @@ function rangesSubset(sub, sup) {
|
|
|
2307
2413
|
}
|
|
2308
2414
|
function parseClassOperand(body) {
|
|
2309
2415
|
if (body === "\\d" || body === "\\w" || body === "\\s") {
|
|
2310
|
-
return { ranges:
|
|
2416
|
+
return { ranges: shorthandRanges(body[1]), negated: false };
|
|
2311
2417
|
}
|
|
2312
2418
|
if (body.length >= 2 && body[0] === "[" && body[body.length - 1] === "]") {
|
|
2313
2419
|
let inner = body.slice(1, -1);
|
|
@@ -2740,7 +2846,7 @@ function parseScanShapeCore(source) {
|
|
|
2740
2846
|
}
|
|
2741
2847
|
m = /^\\([dws])([+*])$/.exec(source);
|
|
2742
2848
|
if (m) {
|
|
2743
|
-
return { kind: "chars", ranges:
|
|
2849
|
+
return { kind: "chars", ranges: shorthandRanges(m[1]), minOne: m[2] === "+" };
|
|
2744
2850
|
}
|
|
2745
2851
|
m = /^(\[(?:\\.|[^\]])+\]|\\[dws])(\[(?:\\.|[^\]])+\]|\\[dws])\*$/.exec(source);
|
|
2746
2852
|
if (m) {
|