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.js
CHANGED
|
@@ -371,9 +371,9 @@ function asciiFoldEq(a, b) {
|
|
|
371
371
|
}
|
|
372
372
|
function literal(value, opts = {}) {
|
|
373
373
|
const caseInsensitive = opts.caseInsensitive ?? false;
|
|
374
|
-
const
|
|
374
|
+
const firstSet2 = value.length > 0 ? fromChar(value.codePointAt(0)) : empty();
|
|
375
375
|
const meta = {
|
|
376
|
-
firstSet,
|
|
376
|
+
firstSet: firstSet2,
|
|
377
377
|
canMatchNewline: value.includes("\n"),
|
|
378
378
|
isTrivia: false
|
|
379
379
|
};
|
|
@@ -385,7 +385,7 @@ function literal(value, opts = {}) {
|
|
|
385
385
|
meta.firstSet = firstLower !== void 0 && firstUpper !== void 0 ? firstLower === firstUpper ? { kind: "ranges", ranges: [{ lo: firstLower, hi: firstLower }] } : { kind: "ranges", ranges: [
|
|
386
386
|
{ lo: firstLower, hi: firstLower },
|
|
387
387
|
{ lo: firstUpper, hi: firstUpper }
|
|
388
|
-
] } :
|
|
388
|
+
] } : firstSet2;
|
|
389
389
|
}
|
|
390
390
|
return {
|
|
391
391
|
_tag: "literal",
|
|
@@ -408,68 +408,66 @@ function literal(value, opts = {}) {
|
|
|
408
408
|
};
|
|
409
409
|
}
|
|
410
410
|
|
|
411
|
-
// src/
|
|
412
|
-
var
|
|
413
|
-
function registerRegexAnalyzer(analyzer) {
|
|
414
|
-
firstSetAnalyzer = analyzer;
|
|
415
|
-
}
|
|
416
|
-
var permissiveFirstSet = () => ({ firstSet: any(), canMatchNewline: true });
|
|
417
|
-
var SCAN_BAIL_AT = 64;
|
|
411
|
+
// src/regex/classes.ts
|
|
412
|
+
var CLASS_ESCAPES = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
418
413
|
var SPACE_RANGES = [
|
|
419
414
|
[9, 13],
|
|
420
415
|
[32, 32],
|
|
421
416
|
[160, 160],
|
|
422
417
|
[5760, 5760],
|
|
423
418
|
[8192, 8202],
|
|
424
|
-
[8232,
|
|
419
|
+
[8232, 8232],
|
|
420
|
+
[8233, 8233],
|
|
425
421
|
[8239, 8239],
|
|
426
422
|
[8287, 8287],
|
|
427
423
|
[12288, 12288],
|
|
428
424
|
[65279, 65279]
|
|
429
425
|
];
|
|
430
|
-
var CLASS_ESCAPES = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
431
426
|
function shorthandRanges(ch) {
|
|
432
427
|
if (ch === "d") return [[48, 57]];
|
|
433
428
|
if (ch === "s") return SPACE_RANGES;
|
|
434
429
|
return [[48, 57], [65, 90], [97, 122], [95, 95]];
|
|
435
430
|
}
|
|
436
|
-
function
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
}
|
|
441
|
-
return false;
|
|
431
|
+
function readUnicodeEscape(body, i) {
|
|
432
|
+
if (body[i] !== "\\" || body[i + 1] !== "u") return null;
|
|
433
|
+
const hex = body.slice(i + 2, i + 6);
|
|
434
|
+
if (!/^[0-9a-fA-F]{4}$/.test(hex)) return null;
|
|
435
|
+
return { cp: Number.parseInt(hex, 16), next: i + 6 };
|
|
442
436
|
}
|
|
443
|
-
function
|
|
444
|
-
if (body.startsWith("^")) return null;
|
|
437
|
+
function parseClassRanges(body) {
|
|
445
438
|
const ranges = [];
|
|
446
439
|
let i = 0;
|
|
447
440
|
const readAtom = () => {
|
|
448
441
|
const ch = body[i];
|
|
449
442
|
if (ch === void 0) return null;
|
|
450
443
|
if (ch === "\\") {
|
|
451
|
-
const
|
|
452
|
-
if (
|
|
444
|
+
const uni = readUnicodeEscape(body, i);
|
|
445
|
+
if (uni) {
|
|
446
|
+
i = uni.next;
|
|
447
|
+
return { cp: uni.cp };
|
|
448
|
+
}
|
|
449
|
+
const e = body[i + 1];
|
|
450
|
+
if (e === void 0) return null;
|
|
453
451
|
i += 2;
|
|
454
|
-
if (
|
|
455
|
-
if (
|
|
456
|
-
if (
|
|
457
|
-
return { cp:
|
|
452
|
+
if (e in CLASS_ESCAPES) return { cp: CLASS_ESCAPES[e] };
|
|
453
|
+
if (e === "d" || e === "w" || e === "s") return { set: shorthandRanges(e) };
|
|
454
|
+
if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
455
|
+
return { cp: e.codePointAt(0) };
|
|
458
456
|
}
|
|
459
|
-
i
|
|
460
|
-
return { cp: ch.
|
|
457
|
+
i += ch.length;
|
|
458
|
+
return { cp: ch.codePointAt(0) };
|
|
461
459
|
};
|
|
462
460
|
while (i < body.length) {
|
|
463
461
|
const lo = readAtom();
|
|
464
|
-
if (
|
|
465
|
-
if ("
|
|
466
|
-
ranges.push(...lo.
|
|
462
|
+
if (lo === null) return null;
|
|
463
|
+
if ("set" in lo) {
|
|
464
|
+
ranges.push(...lo.set);
|
|
467
465
|
continue;
|
|
468
466
|
}
|
|
469
467
|
if (body[i] === "-" && body[i + 1] !== void 0 && body[i + 1] !== "]") {
|
|
470
|
-
i
|
|
468
|
+
i += 1;
|
|
471
469
|
const hi = readAtom();
|
|
472
|
-
if (
|
|
470
|
+
if (hi === null || "set" in hi) return null;
|
|
473
471
|
ranges.push([lo.cp, hi.cp]);
|
|
474
472
|
} else {
|
|
475
473
|
ranges.push([lo.cp, lo.cp]);
|
|
@@ -477,6 +475,25 @@ function readClassRanges(body) {
|
|
|
477
475
|
}
|
|
478
476
|
return ranges.length ? ranges : null;
|
|
479
477
|
}
|
|
478
|
+
|
|
479
|
+
// src/combinators/regex.ts
|
|
480
|
+
var firstSetAnalyzer = null;
|
|
481
|
+
function registerRegexAnalyzer(analyzer) {
|
|
482
|
+
firstSetAnalyzer = analyzer;
|
|
483
|
+
}
|
|
484
|
+
var permissiveFirstSet = () => ({ firstSet: any(), canMatchNewline: true });
|
|
485
|
+
var SCAN_BAIL_AT = 64;
|
|
486
|
+
function inRanges(cp, ranges) {
|
|
487
|
+
for (let i = 0; i < ranges.length; i++) {
|
|
488
|
+
const [lo, hi] = ranges[i];
|
|
489
|
+
if (cp >= lo && cp <= hi) return true;
|
|
490
|
+
}
|
|
491
|
+
return false;
|
|
492
|
+
}
|
|
493
|
+
function readClassRanges(body) {
|
|
494
|
+
if (body.startsWith("^")) return null;
|
|
495
|
+
return parseClassRanges(body);
|
|
496
|
+
}
|
|
480
497
|
function shortScanner(source, flags) {
|
|
481
498
|
if (/[imsuvy]/.test(flags)) return null;
|
|
482
499
|
let ranges = null;
|
|
@@ -510,8 +527,8 @@ function regex(pattern, flags = "") {
|
|
|
510
527
|
const resolvedFlags = typeof pattern === "string" ? flags : pattern.flags;
|
|
511
528
|
const anchored = new RegExp(source, "y" + resolvedFlags.replace(/[gy]/g, ""));
|
|
512
529
|
const scan = shortScanner(source, resolvedFlags);
|
|
513
|
-
const { firstSet, canMatchNewline } = (firstSetAnalyzer ?? permissiveFirstSet)(source);
|
|
514
|
-
const meta = { firstSet, canMatchNewline, isTrivia: false };
|
|
530
|
+
const { firstSet: firstSet2, canMatchNewline } = (firstSetAnalyzer ?? permissiveFirstSet)(source);
|
|
531
|
+
const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
|
|
515
532
|
return {
|
|
516
533
|
_tag: "regex",
|
|
517
534
|
_meta: meta,
|
|
@@ -539,111 +556,266 @@ function regex(pattern, flags = "") {
|
|
|
539
556
|
};
|
|
540
557
|
}
|
|
541
558
|
|
|
542
|
-
// src/
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
return extractFirstSet(ast.body);
|
|
548
|
-
} catch {
|
|
549
|
-
return { firstSet: any(), canMatchNewline: true };
|
|
550
|
-
}
|
|
559
|
+
// src/regex/first-set.ts
|
|
560
|
+
var ANY = { t: "any" };
|
|
561
|
+
var EMPTY2 = { t: "empty" };
|
|
562
|
+
function charNode(set, nl) {
|
|
563
|
+
return { t: "char", set, nl };
|
|
551
564
|
}
|
|
552
|
-
function
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
565
|
+
function rangesToSet(ranges) {
|
|
566
|
+
let fs2 = empty();
|
|
567
|
+
for (const [lo, hi] of ranges) fs2 = union(fs2, fromRange(lo, hi));
|
|
568
|
+
return fs2;
|
|
569
|
+
}
|
|
570
|
+
function rangesHaveNewline(ranges) {
|
|
571
|
+
return ranges.some(([lo, hi]) => lo <= 10 && 10 <= hi);
|
|
572
|
+
}
|
|
573
|
+
var BAIL = /* @__PURE__ */ Symbol("regex-bail");
|
|
574
|
+
function parseRegex(src) {
|
|
575
|
+
let i = 0;
|
|
576
|
+
const parseAlt = () => {
|
|
577
|
+
const arms = [parseSeq()];
|
|
578
|
+
while (src[i] === "|") {
|
|
579
|
+
i++;
|
|
580
|
+
arms.push(parseSeq());
|
|
558
581
|
}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
582
|
+
return arms.length === 1 ? arms[0] : { t: "alt", arms };
|
|
583
|
+
};
|
|
584
|
+
const parseSeq = () => {
|
|
585
|
+
const parts = [];
|
|
586
|
+
while (i < src.length) {
|
|
587
|
+
const ch = src[i];
|
|
588
|
+
if (ch === "|" || ch === ")") break;
|
|
589
|
+
parts.push(parseQuantified());
|
|
590
|
+
}
|
|
591
|
+
if (parts.length === 0) return EMPTY2;
|
|
592
|
+
return parts.length === 1 ? parts[0] : { t: "seq", parts };
|
|
593
|
+
};
|
|
594
|
+
const parseQuantified = () => {
|
|
595
|
+
const atom = parseAtom();
|
|
596
|
+
const ch = src[i];
|
|
597
|
+
let min = null;
|
|
598
|
+
if (ch === "*") {
|
|
599
|
+
min = 0;
|
|
600
|
+
i++;
|
|
601
|
+
} else if (ch === "+") {
|
|
602
|
+
min = 1;
|
|
603
|
+
i++;
|
|
604
|
+
} else if (ch === "?") {
|
|
605
|
+
min = 0;
|
|
606
|
+
i++;
|
|
607
|
+
} else if (ch === "{") {
|
|
608
|
+
min = parseBraceQuantifier();
|
|
562
609
|
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
610
|
+
if (min === null) return atom;
|
|
611
|
+
if (src[i] === "?") i++;
|
|
612
|
+
return { t: "rep", node: atom, min };
|
|
613
|
+
};
|
|
614
|
+
const parseBraceQuantifier = () => {
|
|
615
|
+
const close = src.indexOf("}", i);
|
|
616
|
+
if (close === -1) return null;
|
|
617
|
+
const m = /^(\d+)(?:,(\d*))?$/.exec(src.slice(i + 1, close));
|
|
618
|
+
if (!m) return null;
|
|
619
|
+
i = close + 1;
|
|
620
|
+
return Number.parseInt(m[1], 10);
|
|
621
|
+
};
|
|
622
|
+
const parseAtom = () => {
|
|
623
|
+
const ch = src[i];
|
|
624
|
+
switch (ch) {
|
|
625
|
+
case "(":
|
|
626
|
+
return parseGroup();
|
|
627
|
+
case "[":
|
|
628
|
+
return parseClass();
|
|
629
|
+
case ".":
|
|
630
|
+
i++;
|
|
631
|
+
return charNode(any(), false);
|
|
632
|
+
// `.` matches any char except line terminators
|
|
633
|
+
case "\\":
|
|
634
|
+
return parseEscape();
|
|
635
|
+
case "^":
|
|
636
|
+
case "$":
|
|
637
|
+
i++;
|
|
638
|
+
return EMPTY2;
|
|
639
|
+
// anchors are zero-width
|
|
640
|
+
case "{":
|
|
641
|
+
i++;
|
|
642
|
+
return charNode(fromRange(123, 123), false);
|
|
643
|
+
// a `{` with nothing to quantify is a literal brace
|
|
644
|
+
default:
|
|
645
|
+
i += ch.length;
|
|
646
|
+
return charNode(fromRange(ch.codePointAt(0), ch.codePointAt(0)), ch === "\n");
|
|
581
647
|
}
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
}
|
|
593
|
-
|
|
648
|
+
};
|
|
649
|
+
const parseGroup = () => {
|
|
650
|
+
i++;
|
|
651
|
+
let lookaround = false;
|
|
652
|
+
if (src[i] === "?") {
|
|
653
|
+
const c1 = src[i + 1];
|
|
654
|
+
if (c1 === ":") i += 2;
|
|
655
|
+
else if (c1 === "=" || c1 === "!") {
|
|
656
|
+
i += 2;
|
|
657
|
+
lookaround = true;
|
|
658
|
+
} else if (c1 === "<") {
|
|
659
|
+
const c2 = src[i + 2];
|
|
660
|
+
if (c2 === "=" || c2 === "!") {
|
|
661
|
+
i += 3;
|
|
662
|
+
lookaround = true;
|
|
663
|
+
} else {
|
|
664
|
+
const gt = src.indexOf(">", i);
|
|
665
|
+
if (gt === -1) throw BAIL;
|
|
666
|
+
i = gt + 1;
|
|
667
|
+
}
|
|
668
|
+
} else throw BAIL;
|
|
594
669
|
}
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
};
|
|
613
|
-
if (val === "s") return { firstSet: fromRange(9, 13), canMatchNewline: true };
|
|
614
|
-
if (val === "n") return { firstSet: fromRange(10, 10), canMatchNewline: true };
|
|
670
|
+
const inner = parseAlt();
|
|
671
|
+
if (src[i] !== ")") throw BAIL;
|
|
672
|
+
i++;
|
|
673
|
+
return lookaround ? EMPTY2 : inner;
|
|
674
|
+
};
|
|
675
|
+
const parseClass = () => {
|
|
676
|
+
let k = i + 1;
|
|
677
|
+
const negated = src[k] === "^";
|
|
678
|
+
if (negated) k++;
|
|
679
|
+
let body = "";
|
|
680
|
+
while (k < src.length && src[k] !== "]") {
|
|
681
|
+
if (src[k] === "\\") {
|
|
682
|
+
body += src[k] + (src[k + 1] ?? "");
|
|
683
|
+
k += 2;
|
|
684
|
+
} else {
|
|
685
|
+
body += src[k];
|
|
686
|
+
k++;
|
|
615
687
|
}
|
|
616
|
-
return { firstSet: any(), canMatchNewline: true };
|
|
617
688
|
}
|
|
618
|
-
|
|
619
|
-
|
|
689
|
+
if (src[k] !== "]") throw BAIL;
|
|
690
|
+
i = k + 1;
|
|
691
|
+
if (negated) return charNode(any(), true);
|
|
692
|
+
const ranges = parseClassRanges(body);
|
|
693
|
+
if (!ranges) return charNode(any(), true);
|
|
694
|
+
return charNode(rangesToSet(ranges), rangesHaveNewline(ranges));
|
|
695
|
+
};
|
|
696
|
+
const parseEscape = () => {
|
|
697
|
+
const e = src[i + 1];
|
|
698
|
+
if (e === void 0) throw BAIL;
|
|
699
|
+
if (e === "u" && /^[0-9a-fA-F]{4}$/.test(src.slice(i + 2, i + 6))) {
|
|
700
|
+
const cp = Number.parseInt(src.slice(i + 2, i + 6), 16);
|
|
701
|
+
i += 6;
|
|
702
|
+
return charNode(fromRange(cp, cp), cp === 10);
|
|
703
|
+
}
|
|
704
|
+
if (e === "x" && /^[0-9a-fA-F]{2}$/.test(src.slice(i + 2, i + 4))) {
|
|
705
|
+
const cp = Number.parseInt(src.slice(i + 2, i + 4), 16);
|
|
706
|
+
i += 4;
|
|
707
|
+
return charNode(fromRange(cp, cp), cp === 10);
|
|
708
|
+
}
|
|
709
|
+
i += 2;
|
|
710
|
+
switch (e) {
|
|
711
|
+
case "d":
|
|
712
|
+
return charNode(rangesToSet(shorthandRanges("d")), false);
|
|
713
|
+
case "w":
|
|
714
|
+
return charNode(rangesToSet(shorthandRanges("w")), false);
|
|
715
|
+
case "s":
|
|
716
|
+
return charNode(rangesToSet(shorthandRanges("s")), true);
|
|
717
|
+
case "D":
|
|
718
|
+
case "W":
|
|
719
|
+
case "S":
|
|
720
|
+
return charNode(any(), true);
|
|
721
|
+
// negated shorthand → widen
|
|
722
|
+
case "b":
|
|
723
|
+
case "B":
|
|
724
|
+
return EMPTY2;
|
|
725
|
+
// word boundary: zero-width
|
|
726
|
+
case "n":
|
|
727
|
+
return charNode(fromRange(10, 10), true);
|
|
728
|
+
case "r":
|
|
729
|
+
return charNode(fromRange(13, 13), false);
|
|
730
|
+
case "t":
|
|
731
|
+
return charNode(fromRange(9, 9), false);
|
|
732
|
+
case "f":
|
|
733
|
+
return charNode(fromRange(12, 12), false);
|
|
734
|
+
case "v":
|
|
735
|
+
return charNode(fromRange(11, 11), false);
|
|
736
|
+
case "0":
|
|
737
|
+
return charNode(fromRange(0, 0), false);
|
|
738
|
+
default:
|
|
739
|
+
if (e >= "1" && e <= "9") return ANY;
|
|
740
|
+
return charNode(fromRange(e.codePointAt(0), e.codePointAt(0)), e === "\n");
|
|
741
|
+
}
|
|
742
|
+
};
|
|
743
|
+
const node2 = parseAlt();
|
|
744
|
+
if (i < src.length) throw BAIL;
|
|
745
|
+
return node2;
|
|
746
|
+
}
|
|
747
|
+
function nullable(n) {
|
|
748
|
+
switch (n.t) {
|
|
749
|
+
case "char":
|
|
750
|
+
return false;
|
|
751
|
+
case "any":
|
|
752
|
+
return true;
|
|
753
|
+
case "empty":
|
|
754
|
+
return true;
|
|
755
|
+
case "seq":
|
|
756
|
+
return n.parts.every(nullable);
|
|
757
|
+
case "alt":
|
|
758
|
+
return n.arms.some(nullable);
|
|
759
|
+
case "rep":
|
|
760
|
+
return n.min === 0 || nullable(n.node);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
function firstSet(n) {
|
|
764
|
+
switch (n.t) {
|
|
765
|
+
case "char":
|
|
766
|
+
return n.set;
|
|
767
|
+
case "any":
|
|
768
|
+
return any();
|
|
769
|
+
case "empty":
|
|
770
|
+
return empty();
|
|
771
|
+
case "rep":
|
|
772
|
+
return firstSet(n.node);
|
|
773
|
+
case "alt": {
|
|
774
|
+
let fs2 = empty();
|
|
775
|
+
for (const arm of n.arms) fs2 = union(fs2, firstSet(arm));
|
|
776
|
+
return fs2;
|
|
777
|
+
}
|
|
778
|
+
case "seq": {
|
|
620
779
|
let fs2 = empty();
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
if (
|
|
624
|
-
const from = expr.from.codePoint;
|
|
625
|
-
const to = expr.to.codePoint;
|
|
626
|
-
fs2 = union(fs2, fromRange(from, to));
|
|
627
|
-
if (from <= 10 && 10 <= to) canNL = true;
|
|
628
|
-
} else if (expr.type === "Char") {
|
|
629
|
-
const r = extractFirstSet(expr);
|
|
630
|
-
fs2 = union(fs2, r.firstSet);
|
|
631
|
-
canNL = canNL || r.canMatchNewline;
|
|
632
|
-
}
|
|
780
|
+
for (const part of n.parts) {
|
|
781
|
+
fs2 = union(fs2, firstSet(part));
|
|
782
|
+
if (!nullable(part)) break;
|
|
633
783
|
}
|
|
634
|
-
|
|
635
|
-
return { firstSet: fs2, canMatchNewline: canNL };
|
|
784
|
+
return fs2;
|
|
636
785
|
}
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
function firstCanBeNewline(n) {
|
|
789
|
+
switch (n.t) {
|
|
790
|
+
case "char":
|
|
791
|
+
return n.nl;
|
|
792
|
+
case "any":
|
|
793
|
+
return true;
|
|
794
|
+
case "empty":
|
|
795
|
+
return false;
|
|
796
|
+
case "rep":
|
|
797
|
+
return firstCanBeNewline(n.node);
|
|
798
|
+
case "alt":
|
|
799
|
+
return n.arms.some(firstCanBeNewline);
|
|
800
|
+
case "seq": {
|
|
801
|
+
for (const part of n.parts) {
|
|
802
|
+
if (firstCanBeNewline(part)) return true;
|
|
803
|
+
if (!nullable(part)) break;
|
|
804
|
+
}
|
|
805
|
+
return false;
|
|
642
806
|
}
|
|
643
|
-
default:
|
|
644
|
-
return { firstSet: any(), canMatchNewline: true };
|
|
645
807
|
}
|
|
646
808
|
}
|
|
809
|
+
function firstSetFromRegex(source) {
|
|
810
|
+
let ast;
|
|
811
|
+
try {
|
|
812
|
+
ast = parseRegex(source);
|
|
813
|
+
} catch {
|
|
814
|
+
return { firstSet: any(), canMatchNewline: true };
|
|
815
|
+
}
|
|
816
|
+
if (nullable(ast)) return { firstSet: any(), canMatchNewline: true };
|
|
817
|
+
return { firstSet: firstSet(ast), canMatchNewline: firstCanBeNewline(ast) };
|
|
818
|
+
}
|
|
647
819
|
|
|
648
820
|
// src/combinators/keywords.ts
|
|
649
821
|
function word(str, boundary = "_0-9A-Za-z") {
|
|
@@ -658,19 +830,19 @@ function keywords(words, opts = {}) {
|
|
|
658
830
|
const boundary = opts.boundary ? `(?![${opts.boundary}])` : "";
|
|
659
831
|
const flags = opts.caseInsensitive ? "iuy" : "uy";
|
|
660
832
|
const re = new RegExp(`(?:${alt})${boundary}`, flags);
|
|
661
|
-
let
|
|
833
|
+
let firstSet2 = empty();
|
|
662
834
|
for (const w of sorted) {
|
|
663
835
|
if (w.length === 0) continue;
|
|
664
836
|
const cp = w.codePointAt(0);
|
|
665
|
-
|
|
837
|
+
firstSet2 = union(firstSet2, fromChar(cp));
|
|
666
838
|
if (opts.caseInsensitive) {
|
|
667
839
|
const u = String.fromCodePoint(cp).toUpperCase().codePointAt(0);
|
|
668
840
|
const l = String.fromCodePoint(cp).toLowerCase().codePointAt(0);
|
|
669
|
-
if (u !== void 0)
|
|
670
|
-
if (l !== void 0)
|
|
841
|
+
if (u !== void 0) firstSet2 = union(firstSet2, fromChar(u));
|
|
842
|
+
if (l !== void 0) firstSet2 = union(firstSet2, fromChar(l));
|
|
671
843
|
}
|
|
672
844
|
}
|
|
673
|
-
const meta = { firstSet, canMatchNewline: false, isTrivia: false };
|
|
845
|
+
const meta = { firstSet: firstSet2, canMatchNewline: false, isTrivia: false };
|
|
674
846
|
return {
|
|
675
847
|
_tag: "keywords",
|
|
676
848
|
_meta: meta,
|
|
@@ -1974,77 +2146,11 @@ function expect(combinator, label2) {
|
|
|
1974
2146
|
|
|
1975
2147
|
// src/compiler/scannable-run.ts
|
|
1976
2148
|
var BACKSLASH = 92;
|
|
1977
|
-
var CLASS_ESCAPES2 = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
1978
2149
|
var META = new Set("()[]{}*+?|^$.".split(""));
|
|
1979
|
-
var SPACE_RANGES2 = [
|
|
1980
|
-
[9, 13],
|
|
1981
|
-
[32, 32],
|
|
1982
|
-
[160, 160],
|
|
1983
|
-
[5760, 5760],
|
|
1984
|
-
[8192, 8202],
|
|
1985
|
-
[8232, 8232],
|
|
1986
|
-
[8233, 8233],
|
|
1987
|
-
[8239, 8239],
|
|
1988
|
-
[8287, 8287],
|
|
1989
|
-
[12288, 12288],
|
|
1990
|
-
[65279, 65279]
|
|
1991
|
-
];
|
|
1992
|
-
function shorthandRanges2(ch) {
|
|
1993
|
-
if (ch === "d") return [[48, 57]];
|
|
1994
|
-
if (ch === "s") return SPACE_RANGES2;
|
|
1995
|
-
return [[48, 57], [65, 90], [97, 122], [95, 95]];
|
|
1996
|
-
}
|
|
1997
|
-
function readUnicodeEscape(body, i) {
|
|
1998
|
-
if (body[i] !== "\\" || body[i + 1] !== "u") return null;
|
|
1999
|
-
const hex = body.slice(i + 2, i + 6);
|
|
2000
|
-
if (!/^[0-9a-fA-F]{4}$/.test(hex)) return null;
|
|
2001
|
-
return { cp: Number.parseInt(hex, 16), next: i + 6 };
|
|
2002
|
-
}
|
|
2003
|
-
function parseClassRanges(body) {
|
|
2004
|
-
const ranges = [];
|
|
2005
|
-
let i = 0;
|
|
2006
|
-
const readAtom = () => {
|
|
2007
|
-
const ch = body[i];
|
|
2008
|
-
if (ch === void 0) return null;
|
|
2009
|
-
if (ch === "\\") {
|
|
2010
|
-
const uni = readUnicodeEscape(body, i);
|
|
2011
|
-
if (uni) {
|
|
2012
|
-
i = uni.next;
|
|
2013
|
-
return { cp: uni.cp };
|
|
2014
|
-
}
|
|
2015
|
-
const e = body[i + 1];
|
|
2016
|
-
if (e === void 0) return null;
|
|
2017
|
-
i += 2;
|
|
2018
|
-
if (e in CLASS_ESCAPES2) return { cp: CLASS_ESCAPES2[e] };
|
|
2019
|
-
if (e === "d" || e === "w" || e === "s") return { set: shorthandRanges2(e) };
|
|
2020
|
-
if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
2021
|
-
return { cp: e.codePointAt(0) };
|
|
2022
|
-
}
|
|
2023
|
-
i += ch.length;
|
|
2024
|
-
return { cp: ch.codePointAt(0) };
|
|
2025
|
-
};
|
|
2026
|
-
while (i < body.length) {
|
|
2027
|
-
const lo = readAtom();
|
|
2028
|
-
if (lo === null) return null;
|
|
2029
|
-
if ("set" in lo) {
|
|
2030
|
-
ranges.push(...lo.set);
|
|
2031
|
-
continue;
|
|
2032
|
-
}
|
|
2033
|
-
if (body[i] === "-" && body[i + 1] !== void 0 && body[i + 1] !== "]") {
|
|
2034
|
-
i += 1;
|
|
2035
|
-
const hi = readAtom();
|
|
2036
|
-
if (hi === null || "set" in hi) return null;
|
|
2037
|
-
ranges.push([lo.cp, hi.cp]);
|
|
2038
|
-
} else {
|
|
2039
|
-
ranges.push([lo.cp, lo.cp]);
|
|
2040
|
-
}
|
|
2041
|
-
}
|
|
2042
|
-
return ranges.length ? ranges : null;
|
|
2043
|
-
}
|
|
2044
2150
|
function classToRanges(cls) {
|
|
2045
|
-
if (cls === "\\d") return
|
|
2046
|
-
if (cls === "\\w") return
|
|
2047
|
-
if (cls === "\\s") return
|
|
2151
|
+
if (cls === "\\d") return shorthandRanges("d");
|
|
2152
|
+
if (cls === "\\w") return shorthandRanges("w");
|
|
2153
|
+
if (cls === "\\s") return shorthandRanges("s");
|
|
2048
2154
|
const body = cls.slice(1, -1);
|
|
2049
2155
|
if (body.startsWith("^")) return null;
|
|
2050
2156
|
return parseClassRanges(body);
|
|
@@ -2062,7 +2168,7 @@ function literalCodePoints(frag) {
|
|
|
2062
2168
|
if (ch === "\\") {
|
|
2063
2169
|
const e = frag[i + 1];
|
|
2064
2170
|
if (e === void 0) return null;
|
|
2065
|
-
out.push(e in
|
|
2171
|
+
out.push(e in CLASS_ESCAPES ? CLASS_ESCAPES[e] : e.codePointAt(0));
|
|
2066
2172
|
i += 2;
|
|
2067
2173
|
continue;
|
|
2068
2174
|
}
|
|
@@ -2155,7 +2261,7 @@ function parseSeqParts(source) {
|
|
|
2155
2261
|
if (e === "d" || e === "w" || e === "s") {
|
|
2156
2262
|
flush();
|
|
2157
2263
|
i += 2;
|
|
2158
|
-
i += runFrom(
|
|
2264
|
+
i += runFrom(shorthandRanges(e), false, source[i]);
|
|
2159
2265
|
continue;
|
|
2160
2266
|
}
|
|
2161
2267
|
const uni = readUnicodeEscape(source, i);
|
|
@@ -2164,8 +2270,8 @@ function parseSeqParts(source) {
|
|
|
2164
2270
|
cp2 = uni.cp;
|
|
2165
2271
|
i = uni.next;
|
|
2166
2272
|
} else if (e === void 0) return null;
|
|
2167
|
-
else if (e in
|
|
2168
|
-
cp2 =
|
|
2273
|
+
else if (e in CLASS_ESCAPES) {
|
|
2274
|
+
cp2 = CLASS_ESCAPES[e];
|
|
2169
2275
|
i += 2;
|
|
2170
2276
|
} else if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
2171
2277
|
else {
|
|
@@ -2272,7 +2378,7 @@ function rangesSubset(sub, sup) {
|
|
|
2272
2378
|
}
|
|
2273
2379
|
function parseClassOperand(body) {
|
|
2274
2380
|
if (body === "\\d" || body === "\\w" || body === "\\s") {
|
|
2275
|
-
return { ranges:
|
|
2381
|
+
return { ranges: shorthandRanges(body[1]), negated: false };
|
|
2276
2382
|
}
|
|
2277
2383
|
if (body.length >= 2 && body[0] === "[" && body[body.length - 1] === "]") {
|
|
2278
2384
|
let inner = body.slice(1, -1);
|
|
@@ -2705,7 +2811,7 @@ function parseScanShapeCore(source) {
|
|
|
2705
2811
|
}
|
|
2706
2812
|
m = /^\\([dws])([+*])$/.exec(source);
|
|
2707
2813
|
if (m) {
|
|
2708
|
-
return { kind: "chars", ranges:
|
|
2814
|
+
return { kind: "chars", ranges: shorthandRanges(m[1]), minOne: m[2] === "+" };
|
|
2709
2815
|
}
|
|
2710
2816
|
m = /^(\[(?:\\.|[^\]])+\]|\\[dws])(\[(?:\\.|[^\]])+\]|\\[dws])\*$/.exec(source);
|
|
2711
2817
|
if (m) {
|