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.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
|
-
|
|
548
|
-
|
|
549
|
-
|
|
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 };
|
|
564
|
+
}
|
|
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);
|
|
551
572
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
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 };
|
|
636
|
-
}
|
|
637
|
-
case "Repetition": {
|
|
638
|
-
return extractFirstSet(node2.expression);
|
|
784
|
+
return fs2;
|
|
639
785
|
}
|
|
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,
|
|
@@ -1047,13 +1219,25 @@ function tryFastLabeledScan(input, cur, trivia2) {
|
|
|
1047
1219
|
}
|
|
1048
1220
|
function recordTriviaChunks(ctx, chunks) {
|
|
1049
1221
|
const kinds = ctx.triviaKindLabels;
|
|
1222
|
+
const mask = ctx._triviaCaptureMask;
|
|
1050
1223
|
for (const ch of chunks) {
|
|
1051
1224
|
pushTriviaLogEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
|
|
1052
1225
|
if (ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0)) {
|
|
1053
|
-
|
|
1226
|
+
if (mask === void 0 || kinds === void 0 || (mask & 1 << ch.kindIndex) !== 0) {
|
|
1227
|
+
pushCstTriviaEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
|
|
1228
|
+
}
|
|
1054
1229
|
}
|
|
1055
1230
|
}
|
|
1056
1231
|
}
|
|
1232
|
+
function triviaKindMask(labels, keep) {
|
|
1233
|
+
if (!labels) return void 0;
|
|
1234
|
+
let mask = 0;
|
|
1235
|
+
for (const name of keep) {
|
|
1236
|
+
const idx = labels.indexOf(name);
|
|
1237
|
+
if (idx >= 0) mask |= 1 << idx;
|
|
1238
|
+
}
|
|
1239
|
+
return mask;
|
|
1240
|
+
}
|
|
1057
1241
|
|
|
1058
1242
|
// src/combinators/trivia-skip.ts
|
|
1059
1243
|
var NOOP_COMMIT = () => {
|
|
@@ -1705,10 +1889,15 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
1705
1889
|
const saved = beginCstNodeCapture(ctx);
|
|
1706
1890
|
const savedFields = ctx._fields;
|
|
1707
1891
|
ctx._fields = capturesFields ? [] : void 0;
|
|
1892
|
+
const savedMask = ctx._triviaCaptureMask;
|
|
1893
|
+
if (build === void 0 && ctx.build?._parsemanTriviaKinds !== void 0 && def.type !== void 0) {
|
|
1894
|
+
ctx._triviaCaptureMask = ctx.build._parsemanTriviaKinds(def.type);
|
|
1895
|
+
}
|
|
1708
1896
|
if (!capturesTrivia) ctx.captureTrivia = false;
|
|
1709
1897
|
const r = combinator.parse(input, pos, ctx);
|
|
1710
1898
|
const fields = capturesFields ? buildFieldMap(ctx._fields) : void 0;
|
|
1711
1899
|
ctx._fields = savedFields;
|
|
1900
|
+
ctx._triviaCaptureMask = savedMask;
|
|
1712
1901
|
const { children, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
|
|
1713
1902
|
if (!r.ok) return r;
|
|
1714
1903
|
const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
|
|
@@ -1846,7 +2035,13 @@ function parser(opts, root) {
|
|
|
1846
2035
|
trivia: opts.trivia,
|
|
1847
2036
|
...opts.trivia._meta.triviaKindLabels ? { triviaKindLabels: opts.trivia._meta.triviaKindLabels } : {}
|
|
1848
2037
|
} : {},
|
|
1849
|
-
...opts.captureTrivia || _ctx?.captureTrivia ? { captureTrivia: true } : {}
|
|
2038
|
+
...opts.captureTrivia || _ctx?.captureTrivia ? { captureTrivia: true } : {},
|
|
2039
|
+
// Kind-filter for per-node capture. Resolve against this scope's trivia
|
|
2040
|
+
// labels — this parser's own trivia if it declares one, else the INHERITED
|
|
2041
|
+
// labels (`_ctx.triviaKindLabels`), so captureTriviaKinds still applies when
|
|
2042
|
+
// trivia is inherited rather than re-declared here. No labels → undefined
|
|
2043
|
+
// (capture all).
|
|
2044
|
+
...opts.captureTriviaKinds && !clearTrivia ? { _triviaCaptureMask: triviaKindMask(opts.trivia?._meta.triviaKindLabels ?? _ctx?.triviaKindLabels, opts.captureTriviaKinds) } : {}
|
|
1850
2045
|
};
|
|
1851
2046
|
const result = root.parse(input, pos ?? 0, ctx);
|
|
1852
2047
|
if (trackLines) {
|
|
@@ -1974,77 +2169,11 @@ function expect(combinator, label2) {
|
|
|
1974
2169
|
|
|
1975
2170
|
// src/compiler/scannable-run.ts
|
|
1976
2171
|
var BACKSLASH = 92;
|
|
1977
|
-
var CLASS_ESCAPES2 = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
1978
2172
|
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
2173
|
function classToRanges(cls) {
|
|
2045
|
-
if (cls === "\\d") return
|
|
2046
|
-
if (cls === "\\w") return
|
|
2047
|
-
if (cls === "\\s") return
|
|
2174
|
+
if (cls === "\\d") return shorthandRanges("d");
|
|
2175
|
+
if (cls === "\\w") return shorthandRanges("w");
|
|
2176
|
+
if (cls === "\\s") return shorthandRanges("s");
|
|
2048
2177
|
const body = cls.slice(1, -1);
|
|
2049
2178
|
if (body.startsWith("^")) return null;
|
|
2050
2179
|
return parseClassRanges(body);
|
|
@@ -2062,7 +2191,7 @@ function literalCodePoints(frag) {
|
|
|
2062
2191
|
if (ch === "\\") {
|
|
2063
2192
|
const e = frag[i + 1];
|
|
2064
2193
|
if (e === void 0) return null;
|
|
2065
|
-
out.push(e in
|
|
2194
|
+
out.push(e in CLASS_ESCAPES ? CLASS_ESCAPES[e] : e.codePointAt(0));
|
|
2066
2195
|
i += 2;
|
|
2067
2196
|
continue;
|
|
2068
2197
|
}
|
|
@@ -2155,7 +2284,7 @@ function parseSeqParts(source) {
|
|
|
2155
2284
|
if (e === "d" || e === "w" || e === "s") {
|
|
2156
2285
|
flush();
|
|
2157
2286
|
i += 2;
|
|
2158
|
-
i += runFrom(
|
|
2287
|
+
i += runFrom(shorthandRanges(e), false, source[i]);
|
|
2159
2288
|
continue;
|
|
2160
2289
|
}
|
|
2161
2290
|
const uni = readUnicodeEscape(source, i);
|
|
@@ -2164,8 +2293,8 @@ function parseSeqParts(source) {
|
|
|
2164
2293
|
cp2 = uni.cp;
|
|
2165
2294
|
i = uni.next;
|
|
2166
2295
|
} else if (e === void 0) return null;
|
|
2167
|
-
else if (e in
|
|
2168
|
-
cp2 =
|
|
2296
|
+
else if (e in CLASS_ESCAPES) {
|
|
2297
|
+
cp2 = CLASS_ESCAPES[e];
|
|
2169
2298
|
i += 2;
|
|
2170
2299
|
} else if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
2171
2300
|
else {
|
|
@@ -2272,7 +2401,7 @@ function rangesSubset(sub, sup) {
|
|
|
2272
2401
|
}
|
|
2273
2402
|
function parseClassOperand(body) {
|
|
2274
2403
|
if (body === "\\d" || body === "\\w" || body === "\\s") {
|
|
2275
|
-
return { ranges:
|
|
2404
|
+
return { ranges: shorthandRanges(body[1]), negated: false };
|
|
2276
2405
|
}
|
|
2277
2406
|
if (body.length >= 2 && body[0] === "[" && body[body.length - 1] === "]") {
|
|
2278
2407
|
let inner = body.slice(1, -1);
|
|
@@ -2705,7 +2834,7 @@ function parseScanShapeCore(source) {
|
|
|
2705
2834
|
}
|
|
2706
2835
|
m = /^\\([dws])([+*])$/.exec(source);
|
|
2707
2836
|
if (m) {
|
|
2708
|
-
return { kind: "chars", ranges:
|
|
2837
|
+
return { kind: "chars", ranges: shorthandRanges(m[1]), minOne: m[2] === "+" };
|
|
2709
2838
|
}
|
|
2710
2839
|
m = /^(\[(?:\\.|[^\]])+\]|\\[dws])(\[(?:\\.|[^\]])+\]|\\[dws])\*$/.exec(source);
|
|
2711
2840
|
if (m) {
|
|
@@ -3062,7 +3191,7 @@ function scanBranchLabeled(shape, kindIndex, mint) {
|
|
|
3062
3191
|
` if (${m.end} > _e) {`,
|
|
3063
3192
|
` if (_cap) {`,
|
|
3064
3193
|
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, ${m.end}, ${kindIndex})`,
|
|
3065
|
-
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_e, ${m.end}, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${kindIndex})`,
|
|
3194
|
+
` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << kindIndex}))) _ctx._cstTriviaLog.push(_e, ${m.end}, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${kindIndex})`,
|
|
3066
3195
|
` }`,
|
|
3067
3196
|
` _e = ${m.end}`,
|
|
3068
3197
|
` continue`,
|
|
@@ -3178,7 +3307,7 @@ function buildLabeledRegexTriviaFnDecl(fnName, spec, reNames) {
|
|
|
3178
3307
|
` const _ce = _e + _m${i}[0].length`,
|
|
3179
3308
|
` if (_cap) {`,
|
|
3180
3309
|
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
|
|
3181
|
-
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
|
|
3310
|
+
` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
|
|
3182
3311
|
` }`,
|
|
3183
3312
|
` _e = _ce`,
|
|
3184
3313
|
` _matched = true`,
|
|
@@ -3216,7 +3345,7 @@ function buildLabeledRuntimeTriviaFnDecl(fnName, spec, rpStartIndex) {
|
|
|
3216
3345
|
` const _ce = _r${i}.span.end`,
|
|
3217
3346
|
` if (_cap) {`,
|
|
3218
3347
|
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
|
|
3219
|
-
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
|
|
3348
|
+
` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
|
|
3220
3349
|
` }`,
|
|
3221
3350
|
` _e = _ce`,
|
|
3222
3351
|
` _matched = true`,
|
|
@@ -4614,6 +4743,7 @@ function emitNode(def, ctx, pos) {
|
|
|
4614
4743
|
const tlV = capturesTrivia || structural ? v(ctx, "_tl") : "_EMPTY_TL";
|
|
4615
4744
|
if (!capturesTrivia) ctx.needsEmptyTl = true;
|
|
4616
4745
|
const sc = v(ctx, "_sc"), sl = v(ctx, "_sl"), sr = v(ctx, "_sr"), st = v(ctx, "_st"), stl = v(ctx, "_stl");
|
|
4746
|
+
const smk = structural ? v(ctx, "_smk") : null;
|
|
4617
4747
|
if (structural) ctx.needsHostReads = true;
|
|
4618
4748
|
const hostTriviaGate = `_ctx.build !== undefined && (_ctx.build._parsemanCaptureTrivia !== undefined ? _ctx.build._parsemanCaptureTrivia(${JSON.stringify(def.type)}) : (_ctx._pmCapTL ??= _hostReads(_ctx.build, 5)))`;
|
|
4619
4749
|
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)` : ""}
|
|
@@ -4625,15 +4755,15 @@ ${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capt
|
|
|
4625
4755
|
const fObj = hasFields ? v(ctx, "_fields") : "undefined";
|
|
4626
4756
|
const stmts = [
|
|
4627
4757
|
allocStmt,
|
|
4628
|
-
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog${sf ? `, ${sf} = _ctx._fields` : ""}`,
|
|
4629
|
-
`${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true; _ctx._cstTriviaLog = ${innerTl}${sf ? `; _ctx._fields = ${fieldsOn} ? [] : undefined` : ""}`
|
|
4758
|
+
`${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` : ""}`,
|
|
4759
|
+
`${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` : ""}`
|
|
4630
4760
|
];
|
|
4631
4761
|
const { stmts: innerStmts, okVar, endVar } = emitFallible(def.parser, ctx, pos);
|
|
4632
4762
|
stmts.push(...innerStmts);
|
|
4633
4763
|
if (sf && fArr) {
|
|
4634
4764
|
stmts.push(`${i}const ${fArr} = _ctx._fields`);
|
|
4635
4765
|
}
|
|
4636
|
-
stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}${sf ? `; _ctx._fields = ${sf}` : ""}`);
|
|
4766
|
+
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}` : ""}`);
|
|
4637
4767
|
stmts.push(...emitIfFail(ctx, `!${okVar}`, propagateFailBody(ctx)));
|
|
4638
4768
|
let stV = "undefined";
|
|
4639
4769
|
if (structural) {
|