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/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
|
|
@@ -425,9 +415,9 @@ function asciiFoldEq(a, b) {
|
|
|
425
415
|
}
|
|
426
416
|
function literal(value, opts = {}) {
|
|
427
417
|
const caseInsensitive = opts.caseInsensitive ?? false;
|
|
428
|
-
const
|
|
418
|
+
const firstSet2 = value.length > 0 ? fromChar(value.codePointAt(0)) : empty();
|
|
429
419
|
const meta = {
|
|
430
|
-
firstSet,
|
|
420
|
+
firstSet: firstSet2,
|
|
431
421
|
canMatchNewline: value.includes("\n"),
|
|
432
422
|
isTrivia: false
|
|
433
423
|
};
|
|
@@ -439,7 +429,7 @@ function literal(value, opts = {}) {
|
|
|
439
429
|
meta.firstSet = firstLower !== void 0 && firstUpper !== void 0 ? firstLower === firstUpper ? { kind: "ranges", ranges: [{ lo: firstLower, hi: firstLower }] } : { kind: "ranges", ranges: [
|
|
440
430
|
{ lo: firstLower, hi: firstLower },
|
|
441
431
|
{ lo: firstUpper, hi: firstUpper }
|
|
442
|
-
] } :
|
|
432
|
+
] } : firstSet2;
|
|
443
433
|
}
|
|
444
434
|
return {
|
|
445
435
|
_tag: "literal",
|
|
@@ -462,68 +452,66 @@ function literal(value, opts = {}) {
|
|
|
462
452
|
};
|
|
463
453
|
}
|
|
464
454
|
|
|
465
|
-
// src/
|
|
466
|
-
var
|
|
467
|
-
function registerRegexAnalyzer(analyzer) {
|
|
468
|
-
firstSetAnalyzer = analyzer;
|
|
469
|
-
}
|
|
470
|
-
var permissiveFirstSet = () => ({ firstSet: any(), canMatchNewline: true });
|
|
471
|
-
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 };
|
|
472
457
|
var SPACE_RANGES = [
|
|
473
458
|
[9, 13],
|
|
474
459
|
[32, 32],
|
|
475
460
|
[160, 160],
|
|
476
461
|
[5760, 5760],
|
|
477
462
|
[8192, 8202],
|
|
478
|
-
[8232,
|
|
463
|
+
[8232, 8232],
|
|
464
|
+
[8233, 8233],
|
|
479
465
|
[8239, 8239],
|
|
480
466
|
[8287, 8287],
|
|
481
467
|
[12288, 12288],
|
|
482
468
|
[65279, 65279]
|
|
483
469
|
];
|
|
484
|
-
var CLASS_ESCAPES = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
485
470
|
function shorthandRanges(ch) {
|
|
486
471
|
if (ch === "d") return [[48, 57]];
|
|
487
472
|
if (ch === "s") return SPACE_RANGES;
|
|
488
473
|
return [[48, 57], [65, 90], [97, 122], [95, 95]];
|
|
489
474
|
}
|
|
490
|
-
function
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
}
|
|
495
|
-
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 };
|
|
496
480
|
}
|
|
497
|
-
function
|
|
498
|
-
if (body.startsWith("^")) return null;
|
|
481
|
+
function parseClassRanges(body) {
|
|
499
482
|
const ranges = [];
|
|
500
483
|
let i = 0;
|
|
501
484
|
const readAtom = () => {
|
|
502
485
|
const ch = body[i];
|
|
503
486
|
if (ch === void 0) return null;
|
|
504
487
|
if (ch === "\\") {
|
|
505
|
-
const
|
|
506
|
-
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;
|
|
507
495
|
i += 2;
|
|
508
|
-
if (
|
|
509
|
-
if (
|
|
510
|
-
if (
|
|
511
|
-
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) };
|
|
512
500
|
}
|
|
513
|
-
i
|
|
514
|
-
return { cp: ch.
|
|
501
|
+
i += ch.length;
|
|
502
|
+
return { cp: ch.codePointAt(0) };
|
|
515
503
|
};
|
|
516
504
|
while (i < body.length) {
|
|
517
505
|
const lo = readAtom();
|
|
518
|
-
if (
|
|
519
|
-
if ("
|
|
520
|
-
ranges.push(...lo.
|
|
506
|
+
if (lo === null) return null;
|
|
507
|
+
if ("set" in lo) {
|
|
508
|
+
ranges.push(...lo.set);
|
|
521
509
|
continue;
|
|
522
510
|
}
|
|
523
511
|
if (body[i] === "-" && body[i + 1] !== void 0 && body[i + 1] !== "]") {
|
|
524
|
-
i
|
|
512
|
+
i += 1;
|
|
525
513
|
const hi = readAtom();
|
|
526
|
-
if (
|
|
514
|
+
if (hi === null || "set" in hi) return null;
|
|
527
515
|
ranges.push([lo.cp, hi.cp]);
|
|
528
516
|
} else {
|
|
529
517
|
ranges.push([lo.cp, lo.cp]);
|
|
@@ -531,6 +519,25 @@ function readClassRanges(body) {
|
|
|
531
519
|
}
|
|
532
520
|
return ranges.length ? ranges : null;
|
|
533
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
|
+
}
|
|
534
541
|
function shortScanner(source, flags) {
|
|
535
542
|
if (/[imsuvy]/.test(flags)) return null;
|
|
536
543
|
let ranges = null;
|
|
@@ -564,8 +571,8 @@ function regex(pattern, flags = "") {
|
|
|
564
571
|
const resolvedFlags = typeof pattern === "string" ? flags : pattern.flags;
|
|
565
572
|
const anchored = new RegExp(source, "y" + resolvedFlags.replace(/[gy]/g, ""));
|
|
566
573
|
const scan = shortScanner(source, resolvedFlags);
|
|
567
|
-
const { firstSet, canMatchNewline } = (firstSetAnalyzer ?? permissiveFirstSet)(source);
|
|
568
|
-
const meta = { firstSet, canMatchNewline, isTrivia: false };
|
|
574
|
+
const { firstSet: firstSet2, canMatchNewline } = (firstSetAnalyzer ?? permissiveFirstSet)(source);
|
|
575
|
+
const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
|
|
569
576
|
return {
|
|
570
577
|
_tag: "regex",
|
|
571
578
|
_meta: meta,
|
|
@@ -593,111 +600,266 @@ function regex(pattern, flags = "") {
|
|
|
593
600
|
};
|
|
594
601
|
}
|
|
595
602
|
|
|
596
|
-
// src/
|
|
597
|
-
var
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
return extractFirstSet(ast.body);
|
|
602
|
-
} catch {
|
|
603
|
-
return { firstSet: any(), canMatchNewline: true };
|
|
604
|
-
}
|
|
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 };
|
|
605
608
|
}
|
|
606
|
-
function
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
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());
|
|
612
625
|
}
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
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();
|
|
616
653
|
}
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
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");
|
|
635
691
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
}
|
|
647
|
-
|
|
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;
|
|
648
713
|
}
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
};
|
|
667
|
-
if (val === "s") return { firstSet: fromRange(9, 13), canMatchNewline: true };
|
|
668
|
-
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++;
|
|
669
731
|
}
|
|
670
|
-
return { firstSet: any(), canMatchNewline: true };
|
|
671
732
|
}
|
|
672
|
-
|
|
673
|
-
|
|
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": {
|
|
818
|
+
let fs = empty();
|
|
819
|
+
for (const arm of n.arms) fs = union(fs, firstSet(arm));
|
|
820
|
+
return fs;
|
|
821
|
+
}
|
|
822
|
+
case "seq": {
|
|
674
823
|
let fs = empty();
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
if (
|
|
678
|
-
const from = expr.from.codePoint;
|
|
679
|
-
const to = expr.to.codePoint;
|
|
680
|
-
fs = union(fs, fromRange(from, to));
|
|
681
|
-
if (from <= 10 && 10 <= to) canNL = true;
|
|
682
|
-
} else if (expr.type === "Char") {
|
|
683
|
-
const r = extractFirstSet(expr);
|
|
684
|
-
fs = union(fs, r.firstSet);
|
|
685
|
-
canNL = canNL || r.canMatchNewline;
|
|
686
|
-
}
|
|
824
|
+
for (const part of n.parts) {
|
|
825
|
+
fs = union(fs, firstSet(part));
|
|
826
|
+
if (!nullable(part)) break;
|
|
687
827
|
}
|
|
688
|
-
|
|
689
|
-
return { firstSet: fs, canMatchNewline: canNL };
|
|
828
|
+
return fs;
|
|
690
829
|
}
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
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;
|
|
696
850
|
}
|
|
697
|
-
default:
|
|
698
|
-
return { firstSet: any(), canMatchNewline: true };
|
|
699
851
|
}
|
|
700
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
|
+
}
|
|
701
863
|
|
|
702
864
|
// src/combinators/keywords.ts
|
|
703
865
|
function word(str, boundary = "_0-9A-Za-z") {
|
|
@@ -715,19 +877,19 @@ function keywords(words, opts = {}) {
|
|
|
715
877
|
const boundary = opts.boundary ? `(?![${opts.boundary}])` : "";
|
|
716
878
|
const flags = opts.caseInsensitive ? "iuy" : "uy";
|
|
717
879
|
const re = new RegExp(`(?:${alt})${boundary}`, flags);
|
|
718
|
-
let
|
|
880
|
+
let firstSet2 = empty();
|
|
719
881
|
for (const w of sorted) {
|
|
720
882
|
if (w.length === 0) continue;
|
|
721
883
|
const cp = w.codePointAt(0);
|
|
722
|
-
|
|
884
|
+
firstSet2 = union(firstSet2, fromChar(cp));
|
|
723
885
|
if (opts.caseInsensitive) {
|
|
724
886
|
const u = String.fromCodePoint(cp).toUpperCase().codePointAt(0);
|
|
725
887
|
const l = String.fromCodePoint(cp).toLowerCase().codePointAt(0);
|
|
726
|
-
if (u !== void 0)
|
|
727
|
-
if (l !== void 0)
|
|
888
|
+
if (u !== void 0) firstSet2 = union(firstSet2, fromChar(u));
|
|
889
|
+
if (l !== void 0) firstSet2 = union(firstSet2, fromChar(l));
|
|
728
890
|
}
|
|
729
891
|
}
|
|
730
|
-
const meta = { firstSet, canMatchNewline: false, isTrivia: false };
|
|
892
|
+
const meta = { firstSet: firstSet2, canMatchNewline: false, isTrivia: false };
|
|
731
893
|
return {
|
|
732
894
|
_tag: "keywords",
|
|
733
895
|
_meta: meta,
|
|
@@ -2091,77 +2253,11 @@ function expect(combinator, label2) {
|
|
|
2091
2253
|
|
|
2092
2254
|
// src/compiler/scannable-run.ts
|
|
2093
2255
|
var BACKSLASH = 92;
|
|
2094
|
-
var CLASS_ESCAPES2 = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
2095
2256
|
var META = new Set("()[]{}*+?|^$.".split(""));
|
|
2096
|
-
var SPACE_RANGES2 = [
|
|
2097
|
-
[9, 13],
|
|
2098
|
-
[32, 32],
|
|
2099
|
-
[160, 160],
|
|
2100
|
-
[5760, 5760],
|
|
2101
|
-
[8192, 8202],
|
|
2102
|
-
[8232, 8232],
|
|
2103
|
-
[8233, 8233],
|
|
2104
|
-
[8239, 8239],
|
|
2105
|
-
[8287, 8287],
|
|
2106
|
-
[12288, 12288],
|
|
2107
|
-
[65279, 65279]
|
|
2108
|
-
];
|
|
2109
|
-
function shorthandRanges2(ch) {
|
|
2110
|
-
if (ch === "d") return [[48, 57]];
|
|
2111
|
-
if (ch === "s") return SPACE_RANGES2;
|
|
2112
|
-
return [[48, 57], [65, 90], [97, 122], [95, 95]];
|
|
2113
|
-
}
|
|
2114
|
-
function readUnicodeEscape(body, i) {
|
|
2115
|
-
if (body[i] !== "\\" || body[i + 1] !== "u") return null;
|
|
2116
|
-
const hex = body.slice(i + 2, i + 6);
|
|
2117
|
-
if (!/^[0-9a-fA-F]{4}$/.test(hex)) return null;
|
|
2118
|
-
return { cp: Number.parseInt(hex, 16), next: i + 6 };
|
|
2119
|
-
}
|
|
2120
|
-
function parseClassRanges(body) {
|
|
2121
|
-
const ranges = [];
|
|
2122
|
-
let i = 0;
|
|
2123
|
-
const readAtom = () => {
|
|
2124
|
-
const ch = body[i];
|
|
2125
|
-
if (ch === void 0) return null;
|
|
2126
|
-
if (ch === "\\") {
|
|
2127
|
-
const uni = readUnicodeEscape(body, i);
|
|
2128
|
-
if (uni) {
|
|
2129
|
-
i = uni.next;
|
|
2130
|
-
return { cp: uni.cp };
|
|
2131
|
-
}
|
|
2132
|
-
const e = body[i + 1];
|
|
2133
|
-
if (e === void 0) return null;
|
|
2134
|
-
i += 2;
|
|
2135
|
-
if (e in CLASS_ESCAPES2) return { cp: CLASS_ESCAPES2[e] };
|
|
2136
|
-
if (e === "d" || e === "w" || e === "s") return { set: shorthandRanges2(e) };
|
|
2137
|
-
if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
2138
|
-
return { cp: e.codePointAt(0) };
|
|
2139
|
-
}
|
|
2140
|
-
i += ch.length;
|
|
2141
|
-
return { cp: ch.codePointAt(0) };
|
|
2142
|
-
};
|
|
2143
|
-
while (i < body.length) {
|
|
2144
|
-
const lo = readAtom();
|
|
2145
|
-
if (lo === null) return null;
|
|
2146
|
-
if ("set" in lo) {
|
|
2147
|
-
ranges.push(...lo.set);
|
|
2148
|
-
continue;
|
|
2149
|
-
}
|
|
2150
|
-
if (body[i] === "-" && body[i + 1] !== void 0 && body[i + 1] !== "]") {
|
|
2151
|
-
i += 1;
|
|
2152
|
-
const hi = readAtom();
|
|
2153
|
-
if (hi === null || "set" in hi) return null;
|
|
2154
|
-
ranges.push([lo.cp, hi.cp]);
|
|
2155
|
-
} else {
|
|
2156
|
-
ranges.push([lo.cp, lo.cp]);
|
|
2157
|
-
}
|
|
2158
|
-
}
|
|
2159
|
-
return ranges.length ? ranges : null;
|
|
2160
|
-
}
|
|
2161
2257
|
function classToRanges(cls) {
|
|
2162
|
-
if (cls === "\\d") return
|
|
2163
|
-
if (cls === "\\w") return
|
|
2164
|
-
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");
|
|
2165
2261
|
const body = cls.slice(1, -1);
|
|
2166
2262
|
if (body.startsWith("^")) return null;
|
|
2167
2263
|
return parseClassRanges(body);
|
|
@@ -2179,7 +2275,7 @@ function literalCodePoints(frag) {
|
|
|
2179
2275
|
if (ch === "\\") {
|
|
2180
2276
|
const e = frag[i + 1];
|
|
2181
2277
|
if (e === void 0) return null;
|
|
2182
|
-
out.push(e in
|
|
2278
|
+
out.push(e in CLASS_ESCAPES ? CLASS_ESCAPES[e] : e.codePointAt(0));
|
|
2183
2279
|
i += 2;
|
|
2184
2280
|
continue;
|
|
2185
2281
|
}
|
|
@@ -2272,7 +2368,7 @@ function parseSeqParts(source) {
|
|
|
2272
2368
|
if (e === "d" || e === "w" || e === "s") {
|
|
2273
2369
|
flush();
|
|
2274
2370
|
i += 2;
|
|
2275
|
-
i += runFrom(
|
|
2371
|
+
i += runFrom(shorthandRanges(e), false, source[i]);
|
|
2276
2372
|
continue;
|
|
2277
2373
|
}
|
|
2278
2374
|
const uni = readUnicodeEscape(source, i);
|
|
@@ -2281,8 +2377,8 @@ function parseSeqParts(source) {
|
|
|
2281
2377
|
cp2 = uni.cp;
|
|
2282
2378
|
i = uni.next;
|
|
2283
2379
|
} else if (e === void 0) return null;
|
|
2284
|
-
else if (e in
|
|
2285
|
-
cp2 =
|
|
2380
|
+
else if (e in CLASS_ESCAPES) {
|
|
2381
|
+
cp2 = CLASS_ESCAPES[e];
|
|
2286
2382
|
i += 2;
|
|
2287
2383
|
} else if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
2288
2384
|
else {
|
|
@@ -2389,7 +2485,7 @@ function rangesSubset(sub, sup) {
|
|
|
2389
2485
|
}
|
|
2390
2486
|
function parseClassOperand(body) {
|
|
2391
2487
|
if (body === "\\d" || body === "\\w" || body === "\\s") {
|
|
2392
|
-
return { ranges:
|
|
2488
|
+
return { ranges: shorthandRanges(body[1]), negated: false };
|
|
2393
2489
|
}
|
|
2394
2490
|
if (body.length >= 2 && body[0] === "[" && body[body.length - 1] === "]") {
|
|
2395
2491
|
let inner = body.slice(1, -1);
|
|
@@ -2822,7 +2918,7 @@ function parseScanShapeCore(source) {
|
|
|
2822
2918
|
}
|
|
2823
2919
|
m = /^\\([dws])([+*])$/.exec(source);
|
|
2824
2920
|
if (m) {
|
|
2825
|
-
return { kind: "chars", ranges:
|
|
2921
|
+
return { kind: "chars", ranges: shorthandRanges(m[1]), minOne: m[2] === "+" };
|
|
2826
2922
|
}
|
|
2827
2923
|
m = /^(\[(?:\\.|[^\]])+\]|\\[dws])(\[(?:\\.|[^\]])+\]|\\[dws])\*$/.exec(source);
|
|
2828
2924
|
if (m) {
|