UNPKG

75.7 kBJavaScriptView Raw
1/*! @author Toru Nagashima <https://github.com/mysticatea> */
2'use strict';
3
4Object.defineProperty(exports, '__esModule', { value: true });
5
6
7
8var ast = /*#__PURE__*/Object.freeze({
9
10});
11
12let largeIdStartRanges = undefined;
13let largeIdContinueRanges = undefined;
14function isIdStart(cp) {
15 if (cp < 0x41)
16 return false;
17 if (cp < 0x5b)
18 return true;
19 if (cp < 0x61)
20 return false;
21 if (cp < 0x7b)
22 return true;
23 return isLargeIdStart(cp);
24}
25function isIdContinue(cp) {
26 if (cp < 0x30)
27 return false;
28 if (cp < 0x3a)
29 return true;
30 if (cp < 0x41)
31 return false;
32 if (cp < 0x5b)
33 return true;
34 if (cp === 0x5f)
35 return true;
36 if (cp < 0x61)
37 return false;
38 if (cp < 0x7b)
39 return true;
40 return isLargeIdStart(cp) || isLargeIdContinue(cp);
41}
42function isLargeIdStart(cp) {
43 return isInRange(cp, largeIdStartRanges || (largeIdStartRanges = initLargeIdStartRanges()));
44}
45function isLargeIdContinue(cp) {
46 return isInRange(cp, largeIdContinueRanges ||
47 (largeIdContinueRanges = initLargeIdContinueRanges()));
48}
49function initLargeIdStartRanges() {
50 return restoreRanges("4q 0 b 0 5 0 6 m 2 u 2 cp 5 b f 4 8 0 2 0 3m 4 2 1 3 3 2 0 7 0 2 2 2 0 2 j 2 2a 2 3u 9 4l 2 11 3 0 7 14 20 q 5 3 1a 16 10 1 2 2q 2 0 g 1 8 1 b 2 3 0 h 0 2 t u 2g c 0 p w a 1 5 0 6 l 5 0 a 0 4 0 o o 8 a 1i k 2 h 1p 1h 4 0 j 0 8 9 g f 5 7 3 1 3 l 2 6 2 0 4 3 4 0 h 0 e 1 2 2 f 1 b 0 9 5 5 1 3 l 2 6 2 1 2 1 2 1 w 3 2 0 k 2 h 8 2 2 2 l 2 6 2 1 2 4 4 0 j 0 g 1 o 0 c 7 3 1 3 l 2 6 2 1 2 4 4 0 v 1 2 2 g 0 i 0 2 5 4 2 2 3 4 1 2 0 2 1 4 1 4 2 4 b n 0 1h 7 2 2 2 m 2 f 4 0 r 2 6 1 v 0 5 7 2 2 2 m 2 9 2 4 4 0 x 0 2 1 g 1 i 8 2 2 2 14 3 0 h 0 6 2 9 2 p 5 6 h 4 n 2 8 2 0 3 6 1n 1b 2 1 d 6 1n 1 2 0 2 4 2 n 2 0 2 9 2 1 a 0 3 4 2 0 m 3 x 0 1s 7 2 z s 4 38 16 l 0 h 5 5 3 4 0 4 1 8 2 5 c d 0 i 11 2 0 6 0 3 16 2 98 2 3 3 6 2 0 2 3 3 14 2 3 3 w 2 3 3 6 2 0 2 3 3 e 2 1k 2 3 3 1u 12 f h 2d 3 5 4 h7 3 g 2 p 6 22 4 a 8 c 2 3 f h f h f c 2 2 g 1f 10 0 5 0 1w 2g 8 14 2 0 6 1x b u 1e t 3 4 c 17 5 p 1j m a 1g 2b 0 2m 1a i 6 1k t e 1 b 17 r z 16 2 b z 3 8 8 16 3 2 16 3 2 5 2 1 4 0 6 5b 1t 7p 3 5 3 11 3 5 3 7 2 0 2 0 2 0 2 u 3 1g 2 6 2 0 4 2 2 6 4 3 3 5 5 c 6 2 2 6 39 0 e 0 h c 2u 0 5 0 3 9 2 0 3 5 7 0 2 0 2 0 2 f 3 3 6 4 5 0 i 14 22g 1a 2 1a 2 3o 7 3 4 1 d 11 2 0 6 0 3 1j 8 0 h m a 6 2 6 2 6 2 6 2 6 2 6 2 6 2 6 fb 2 q 8 8 4 3 4 5 2d 5 4 2 2h 2 3 6 16 2 2l i v 1d f e9 533 1t g70 4 wc 1w 19 3 7g 4 f b 1 l 1a h u 3 27 14 8 3 2u 3 1g 3 8 17 c 2 2 2 3 2 m u 1f f 1d 1r 5 4 0 2 1 c r b m q s 8 1a t 0 h 4 2 9 b 4 2 14 o 2 2 7 l m 4 0 4 1d 2 0 4 1 3 4 3 0 2 0 p 2 3 a 8 2 d 5 3 5 3 5 a 6 2 6 2 16 2 d 7 36 u 8mb d m 5 1c 6it a5 3 2x 13 6 d 4 6 0 2 9 2 c 2 4 2 0 2 1 2 1 2 2z y a2 j 1r 3 1h 15 b 39 4 2 3q 11 p 7 p c 2g 4 5 3 5 3 5 3 2 10 b 2 p 2 i 2 1 2 e 3 d z 3e 1y 1g 7g s 4 1c 1c v e t 6 11 b t 3 z 5 7 2 4 17 4d j z 5 z 5 13 9 1f 4d 8m a l b 7 49 5 3 0 2 17 2 1 4 0 3 m b m a u 1u i 2 1 b l b p 1z 1j 7 1 1t 0 g 3 2 2 2 s 17 s 4 s 10 7 2 r s 1h b l b i e h 33 20 1k 1e e 1e e z 9p 15 7 1 27 s b 0 9 l 2z k s m d 1g 24 18 x o r z u 0 3 0 9 y 4 0 d 1b f 3 m 0 2 0 10 h 2 o 2d 6 2 0 2 3 2 e 2 9 8 1a 13 7 3 1 3 l 2 6 2 1 2 4 4 0 j 0 d 4 4f 1g j 3 l 2 v 1b l 1 2 0 55 1a 16 3 11 1b l 0 1o 16 e 0 20 q 6e 17 39 1r w 7 3 0 3 7 2 1 2 n g 0 2 0 2n 7 3 12 h 0 2 0 t 0 b 13 8 0 m 0 c 19 k 0 z 1k 7c 8 2 10 i 0 1e t 35 6 2 1 2 11 m 0 q 5 2 1 2 v f 0 94 i 5a 0 28 pl 2v 32 i 5f 24d tq 34i g6 6nu fs 8 u 36 t j 1b h 3 w k 6 i j5 1r 3l 22 6 0 1v c 1t 1 2 0 t 4qf 9 yd 17 8 6wo 7y 1e 2 i 3 9 az 1s5 2y 6 c 4 8 8 9 4mf 2c 2 1y 2 1 3 0 3 1 3 3 2 b 2 0 2 6 2 1s 2 3 3 7 2 6 2 r 2 3 2 4 2 0 4 6 2 9f 3 o 2 o 2 u 2 o 2 u 2 o 2 u 2 o 2 u 2 o 2 7 1th 18 b 6 h 0 aa 17 105 5g 1o 1v 8 0 xh 3 2 q 2 1 2 0 3 0 2 9 2 3 2 0 2 0 7 0 5 0 2 0 2 0 2 2 2 1 2 0 3 0 2 0 2 0 2 0 2 0 2 1 2 0 3 3 2 6 2 3 2 3 2 0 2 9 2 g 6 2 2 4 2 g 3et wyl z 378 c 65 3 4g1 f 5rk 2e8 f1 15v 3t6");
51}
52function initLargeIdContinueRanges() {
53 return restoreRanges("53 0 g9 33 o 0 70 4 7e 18 2 0 2 1 2 1 2 0 21 a 1d u 7 0 2u 6 3 5 3 1 2 3 3 9 o 0 v q 2k a g 9 y 8 a 0 p 3 2 8 2 2 2 4 18 2 3c e 2 w 1j 2 2 h 2 6 b 1 3 9 i 2 1l 0 2 6 3 1 3 2 a 0 b 1 3 9 f 0 3 2 1l 0 2 4 5 1 3 2 4 0 l b 4 0 c 2 1l 0 2 7 2 2 2 2 l 1 3 9 b 5 2 2 1l 0 2 6 3 1 3 2 8 2 b 1 3 9 j 0 1o 4 4 2 2 3 a 0 f 9 h 4 1m 6 2 2 2 3 8 1 c 1 3 9 i 2 1l 0 2 6 2 2 2 3 8 1 c 1 3 9 h 3 1k 1 2 6 2 2 2 3 a 0 b 1 3 9 i 2 1z 0 5 5 2 0 2 7 7 9 3 1 1q 0 3 6 d 7 2 9 2g 0 3 8 c 5 3 9 1r 1 7 9 c 0 2 0 2 0 5 1 1e j 2 1 6 a 2 z a 0 2t j 2 9 d 3 5 2 2 2 3 6 4 3 e b 2 e jk 2 a 8 pt 2 u 2 u 1 v 1 1t v a 0 3 9 y 2 3 9 40 0 3b b 5 b b 9 3l a 1p 4 1m 9 2 s 3 a 7 9 n d 2 1 1s 4 1c g c 9 i 8 d 2 v c 3 9 19 d 1d j 9 9 7 9 3b 2 2 k 5 0 7 0 3 2 5j 1l 2 4 g0 1 k 0 3g c 5 0 4 b 2db 2 3y 0 2p v ff 5 2y 1 n7q 9 1y 0 5 9 x 1 29 1 7l 0 4 0 5 0 o 4 5 0 2c 1 1f h b 9 7 h e a t 7 q c 19 3 1c d g 9 c 0 b 9 1c d d 0 9 1 3 9 y 2 1f 0 2 2 3 1 6 1 2 0 16 4 6 1 6l 7 2 1 3 9 fmt 0 ki f h f 4 1 p 2 5d 9 12 0 ji 0 6b 0 46 4 86 9 120 2 2 1 6 3 15 2 5 0 4m 1 fy 3 9 9 aa 1 4a a 4w 2 1i e w 9 g 3 1a a 1i 9 7 2 11 d 2 9 6 1 19 0 d 2 1d d 9 3 2 b 2b b 7 0 4h b 6 9 7 3 1k 1 2 6 3 1 3 2 a 0 b 1 3 6 4 4 5d h a 9 5 0 2a j d 9 5y 6 3 8 s 1 2b g g 9 2a c 9 9 2c e 5 9 6r e 4m 9 1z 5 2 1 3 3 2 0 2 1 d 9 3c 6 3 6 4 0 t 9 15 6 2 3 9 0 a a 1b f ba 7 2 7 h 9 1l l 2 d 3f 5 4 0 2 1 2 6 2 0 9 9 1d 4 2 1 2 4 9 9 96 3 ewa 9 3r 4 1o 6 q 9 s6 0 2 1i 8 3 2a 0 c 1 f58 1 43r 4 4 5 9 7 3 6 v 3 45 2 13e 1d e9 1i 5 1d 9 0 f 0 n 4 2 e 11t 6 2 g 3 6 2 1 2 4 7a 6 a 9 bn d 15j 6 32 6 6 9 3o7 9 gvt3 6n");
54}
55function isInRange(cp, ranges) {
56 let l = 0, r = (ranges.length / 2) | 0, i = 0, min = 0, max = 0;
57 while (l < r) {
58 i = ((l + r) / 2) | 0;
59 min = ranges[2 * i];
60 max = ranges[2 * i + 1];
61 if (cp < min) {
62 r = i;
63 }
64 else if (cp > max) {
65 l = i + 1;
66 }
67 else {
68 return true;
69 }
70 }
71 return false;
72}
73function restoreRanges(data) {
74 let last = 0;
75 return data.split(" ").map(s => (last += parseInt(s, 36) | 0));
76}
77
78class DataSet {
79 constructor(raw2018, raw2019, raw2020, raw2021) {
80 this._raw2018 = raw2018;
81 this._raw2019 = raw2019;
82 this._raw2020 = raw2020;
83 this._raw2021 = raw2021;
84 }
85 get es2018() {
86 return (this._set2018 || (this._set2018 = new Set(this._raw2018.split(" "))));
87 }
88 get es2019() {
89 return (this._set2019 || (this._set2019 = new Set(this._raw2019.split(" "))));
90 }
91 get es2020() {
92 return (this._set2020 || (this._set2020 = new Set(this._raw2020.split(" "))));
93 }
94 get es2021() {
95 return (this._set2021 || (this._set2021 = new Set(this._raw2021.split(" "))));
96 }
97}
98const gcNameSet = new Set(["General_Category", "gc"]);
99const scNameSet = new Set(["Script", "Script_Extensions", "sc", "scx"]);
100const gcValueSets = new DataSet("C Cased_Letter Cc Cf Close_Punctuation Cn Co Combining_Mark Connector_Punctuation Control Cs Currency_Symbol Dash_Punctuation Decimal_Number Enclosing_Mark Final_Punctuation Format Initial_Punctuation L LC Letter Letter_Number Line_Separator Ll Lm Lo Lowercase_Letter Lt Lu M Mark Math_Symbol Mc Me Mn Modifier_Letter Modifier_Symbol N Nd Nl No Nonspacing_Mark Number Open_Punctuation Other Other_Letter Other_Number Other_Punctuation Other_Symbol P Paragraph_Separator Pc Pd Pe Pf Pi Po Private_Use Ps Punctuation S Sc Separator Sk Sm So Space_Separator Spacing_Mark Surrogate Symbol Titlecase_Letter Unassigned Uppercase_Letter Z Zl Zp Zs cntrl digit punct", "", "", "");
101const scValueSets = new DataSet("Adlam Adlm Aghb Ahom Anatolian_Hieroglyphs Arab Arabic Armenian Armi Armn Avestan Avst Bali Balinese Bamu Bamum Bass Bassa_Vah Batak Batk Beng Bengali Bhaiksuki Bhks Bopo Bopomofo Brah Brahmi Brai Braille Bugi Buginese Buhd Buhid Cakm Canadian_Aboriginal Cans Cari Carian Caucasian_Albanian Chakma Cham Cher Cherokee Common Copt Coptic Cprt Cuneiform Cypriot Cyrillic Cyrl Deseret Deva Devanagari Dsrt Dupl Duployan Egyp Egyptian_Hieroglyphs Elba Elbasan Ethi Ethiopic Geor Georgian Glag Glagolitic Gonm Goth Gothic Gran Grantha Greek Grek Gujarati Gujr Gurmukhi Guru Han Hang Hangul Hani Hano Hanunoo Hatr Hatran Hebr Hebrew Hira Hiragana Hluw Hmng Hung Imperial_Aramaic Inherited Inscriptional_Pahlavi Inscriptional_Parthian Ital Java Javanese Kaithi Kali Kana Kannada Katakana Kayah_Li Khar Kharoshthi Khmer Khmr Khoj Khojki Khudawadi Knda Kthi Lana Lao Laoo Latin Latn Lepc Lepcha Limb Limbu Lina Linb Linear_A Linear_B Lisu Lyci Lycian Lydi Lydian Mahajani Mahj Malayalam Mand Mandaic Mani Manichaean Marc Marchen Masaram_Gondi Meetei_Mayek Mend Mende_Kikakui Merc Mero Meroitic_Cursive Meroitic_Hieroglyphs Miao Mlym Modi Mong Mongolian Mro Mroo Mtei Mult Multani Myanmar Mymr Nabataean Narb Nbat New_Tai_Lue Newa Nko Nkoo Nshu Nushu Ogam Ogham Ol_Chiki Olck Old_Hungarian Old_Italic Old_North_Arabian Old_Permic Old_Persian Old_South_Arabian Old_Turkic Oriya Orkh Orya Osage Osge Osma Osmanya Pahawh_Hmong Palm Palmyrene Pau_Cin_Hau Pauc Perm Phag Phags_Pa Phli Phlp Phnx Phoenician Plrd Prti Psalter_Pahlavi Qaac Qaai Rejang Rjng Runic Runr Samaritan Samr Sarb Saur Saurashtra Sgnw Sharada Shavian Shaw Shrd Sidd Siddham SignWriting Sind Sinh Sinhala Sora Sora_Sompeng Soyo Soyombo Sund Sundanese Sylo Syloti_Nagri Syrc Syriac Tagalog Tagb Tagbanwa Tai_Le Tai_Tham Tai_Viet Takr Takri Tale Talu Tamil Taml Tang Tangut Tavt Telu Telugu Tfng Tglg Thaa Thaana Thai Tibetan Tibt Tifinagh Tirh Tirhuta Ugar Ugaritic Vai Vaii Wara Warang_Citi Xpeo Xsux Yi Yiii Zanabazar_Square Zanb Zinh Zyyy", "Dogr Dogra Gong Gunjala_Gondi Hanifi_Rohingya Maka Makasar Medefaidrin Medf Old_Sogdian Rohg Sogd Sogdian Sogo", "Elym Elymaic Hmnp Nand Nandinagari Nyiakeng_Puachue_Hmong Wancho Wcho", "Chorasmian Chrs Diak Dives_Akuru Khitan_Small_Script Kits Yezi Yezidi");
102const binPropertySets = new DataSet("AHex ASCII ASCII_Hex_Digit Alpha Alphabetic Any Assigned Bidi_C Bidi_Control Bidi_M Bidi_Mirrored CI CWCF CWCM CWKCF CWL CWT CWU Case_Ignorable Cased Changes_When_Casefolded Changes_When_Casemapped Changes_When_Lowercased Changes_When_NFKC_Casefolded Changes_When_Titlecased Changes_When_Uppercased DI Dash Default_Ignorable_Code_Point Dep Deprecated Dia Diacritic Emoji Emoji_Component Emoji_Modifier Emoji_Modifier_Base Emoji_Presentation Ext Extender Gr_Base Gr_Ext Grapheme_Base Grapheme_Extend Hex Hex_Digit IDC IDS IDSB IDST IDS_Binary_Operator IDS_Trinary_Operator ID_Continue ID_Start Ideo Ideographic Join_C Join_Control LOE Logical_Order_Exception Lower Lowercase Math NChar Noncharacter_Code_Point Pat_Syn Pat_WS Pattern_Syntax Pattern_White_Space QMark Quotation_Mark RI Radical Regional_Indicator SD STerm Sentence_Terminal Soft_Dotted Term Terminal_Punctuation UIdeo Unified_Ideograph Upper Uppercase VS Variation_Selector White_Space XIDC XIDS XID_Continue XID_Start space", "Extended_Pictographic", "", "EBase EComp EMod EPres ExtPict");
103function isValidUnicodeProperty(version, name, value) {
104 if (gcNameSet.has(name)) {
105 return version >= 2018 && gcValueSets.es2018.has(value);
106 }
107 if (scNameSet.has(name)) {
108 return ((version >= 2018 && scValueSets.es2018.has(value)) ||
109 (version >= 2019 && scValueSets.es2019.has(value)) ||
110 (version >= 2020 && scValueSets.es2020.has(value)) ||
111 (version >= 2021 && scValueSets.es2021.has(value)));
112 }
113 return false;
114}
115function isValidLoneUnicodeProperty(version, value) {
116 return ((version >= 2018 && binPropertySets.es2018.has(value)) ||
117 (version >= 2019 && binPropertySets.es2019.has(value)) ||
118 (version >= 2021 && binPropertySets.es2021.has(value)));
119}
120
121const Backspace = 0x08;
122const CharacterTabulation = 0x09;
123const LineFeed = 0x0a;
124const LineTabulation = 0x0b;
125const FormFeed = 0x0c;
126const CarriageReturn = 0x0d;
127const ExclamationMark = 0x21;
128const DollarSign = 0x24;
129const LeftParenthesis = 0x28;
130const RightParenthesis = 0x29;
131const Asterisk = 0x2a;
132const PlusSign = 0x2b;
133const Comma = 0x2c;
134const HyphenMinus = 0x2d;
135const FullStop = 0x2e;
136const Solidus = 0x2f;
137const DigitZero = 0x30;
138const DigitOne = 0x31;
139const DigitSeven = 0x37;
140const DigitNine = 0x39;
141const Colon = 0x3a;
142const LessThanSign = 0x3c;
143const EqualsSign = 0x3d;
144const GreaterThanSign = 0x3e;
145const QuestionMark = 0x3f;
146const LatinCapitalLetterA = 0x41;
147const LatinCapitalLetterB = 0x42;
148const LatinCapitalLetterD = 0x44;
149const LatinCapitalLetterF = 0x46;
150const LatinCapitalLetterP = 0x50;
151const LatinCapitalLetterS = 0x53;
152const LatinCapitalLetterW = 0x57;
153const LatinCapitalLetterZ = 0x5a;
154const LowLine = 0x5f;
155const LatinSmallLetterA = 0x61;
156const LatinSmallLetterB = 0x62;
157const LatinSmallLetterC = 0x63;
158const LatinSmallLetterD = 0x64;
159const LatinSmallLetterF = 0x66;
160const LatinSmallLetterG = 0x67;
161const LatinSmallLetterI = 0x69;
162const LatinSmallLetterK = 0x6b;
163const LatinSmallLetterM = 0x6d;
164const LatinSmallLetterN = 0x6e;
165const LatinSmallLetterP = 0x70;
166const LatinSmallLetterR = 0x72;
167const LatinSmallLetterS = 0x73;
168const LatinSmallLetterT = 0x74;
169const LatinSmallLetterU = 0x75;
170const LatinSmallLetterV = 0x76;
171const LatinSmallLetterW = 0x77;
172const LatinSmallLetterX = 0x78;
173const LatinSmallLetterY = 0x79;
174const LatinSmallLetterZ = 0x7a;
175const LeftSquareBracket = 0x5b;
176const ReverseSolidus = 0x5c;
177const RightSquareBracket = 0x5d;
178const CircumflexAccent = 0x5e;
179const LeftCurlyBracket = 0x7b;
180const VerticalLine = 0x7c;
181const RightCurlyBracket = 0x7d;
182const ZeroWidthNonJoiner = 0x200c;
183const ZeroWidthJoiner = 0x200d;
184const LineSeparator = 0x2028;
185const ParagraphSeparator = 0x2029;
186const MinCodePoint = 0x00;
187const MaxCodePoint = 0x10ffff;
188function isLatinLetter(code) {
189 return ((code >= LatinCapitalLetterA && code <= LatinCapitalLetterZ) ||
190 (code >= LatinSmallLetterA && code <= LatinSmallLetterZ));
191}
192function isDecimalDigit(code) {
193 return code >= DigitZero && code <= DigitNine;
194}
195function isOctalDigit(code) {
196 return code >= DigitZero && code <= DigitSeven;
197}
198function isHexDigit(code) {
199 return ((code >= DigitZero && code <= DigitNine) ||
200 (code >= LatinCapitalLetterA && code <= LatinCapitalLetterF) ||
201 (code >= LatinSmallLetterA && code <= LatinSmallLetterF));
202}
203function isLineTerminator(code) {
204 return (code === LineFeed ||
205 code === CarriageReturn ||
206 code === LineSeparator ||
207 code === ParagraphSeparator);
208}
209function isValidUnicode(code) {
210 return code >= MinCodePoint && code <= MaxCodePoint;
211}
212function digitToInt(code) {
213 if (code >= LatinSmallLetterA && code <= LatinSmallLetterF) {
214 return code - LatinSmallLetterA + 10;
215 }
216 if (code >= LatinCapitalLetterA && code <= LatinCapitalLetterF) {
217 return code - LatinCapitalLetterA + 10;
218 }
219 return code - DigitZero;
220}
221function isLeadSurrogate(code) {
222 return code >= 0xd800 && code <= 0xdbff;
223}
224function isTrailSurrogate(code) {
225 return code >= 0xdc00 && code <= 0xdfff;
226}
227function combineSurrogatePair(lead, trail) {
228 return (lead - 0xd800) * 0x400 + (trail - 0xdc00) + 0x10000;
229}
230
231const legacyImpl = {
232 at(s, end, i) {
233 return i < end ? s.charCodeAt(i) : -1;
234 },
235 width(c) {
236 return 1;
237 },
238};
239const unicodeImpl = {
240 at(s, end, i) {
241 return i < end ? s.codePointAt(i) : -1;
242 },
243 width(c) {
244 return c > 0xffff ? 2 : 1;
245 },
246};
247class Reader {
248 constructor() {
249 this._impl = legacyImpl;
250 this._s = "";
251 this._i = 0;
252 this._end = 0;
253 this._cp1 = -1;
254 this._w1 = 1;
255 this._cp2 = -1;
256 this._w2 = 1;
257 this._cp3 = -1;
258 this._w3 = 1;
259 this._cp4 = -1;
260 }
261 get source() {
262 return this._s;
263 }
264 get index() {
265 return this._i;
266 }
267 get currentCodePoint() {
268 return this._cp1;
269 }
270 get nextCodePoint() {
271 return this._cp2;
272 }
273 get nextCodePoint2() {
274 return this._cp3;
275 }
276 get nextCodePoint3() {
277 return this._cp4;
278 }
279 reset(source, start, end, uFlag) {
280 this._impl = uFlag ? unicodeImpl : legacyImpl;
281 this._s = source;
282 this._end = end;
283 this.rewind(start);
284 }
285 rewind(index) {
286 const impl = this._impl;
287 this._i = index;
288 this._cp1 = impl.at(this._s, this._end, index);
289 this._w1 = impl.width(this._cp1);
290 this._cp2 = impl.at(this._s, this._end, index + this._w1);
291 this._w2 = impl.width(this._cp2);
292 this._cp3 = impl.at(this._s, this._end, index + this._w1 + this._w2);
293 this._w3 = impl.width(this._cp3);
294 this._cp4 = impl.at(this._s, this._end, index + this._w1 + this._w2 + this._w3);
295 }
296 advance() {
297 if (this._cp1 !== -1) {
298 const impl = this._impl;
299 this._i += this._w1;
300 this._cp1 = this._cp2;
301 this._w1 = this._w2;
302 this._cp2 = this._cp3;
303 this._w2 = impl.width(this._cp2);
304 this._cp3 = this._cp4;
305 this._w3 = impl.width(this._cp3);
306 this._cp4 = impl.at(this._s, this._end, this._i + this._w1 + this._w2 + this._w3);
307 }
308 }
309 eat(cp) {
310 if (this._cp1 === cp) {
311 this.advance();
312 return true;
313 }
314 return false;
315 }
316 eat2(cp1, cp2) {
317 if (this._cp1 === cp1 && this._cp2 === cp2) {
318 this.advance();
319 this.advance();
320 return true;
321 }
322 return false;
323 }
324 eat3(cp1, cp2, cp3) {
325 if (this._cp1 === cp1 && this._cp2 === cp2 && this._cp3 === cp3) {
326 this.advance();
327 this.advance();
328 this.advance();
329 return true;
330 }
331 return false;
332 }
333}
334
335class RegExpSyntaxError extends SyntaxError {
336 constructor(source, uFlag, index, message) {
337 if (source) {
338 if (!source.startsWith("/")) {
339 source = `/${source}/${uFlag ? "u" : ""}`;
340 }
341 source = `: ${source}`;
342 }
343 super(`Invalid regular expression${source}: ${message}`);
344 this.index = index;
345 }
346}
347
348function isSyntaxCharacter(cp) {
349 return (cp === CircumflexAccent ||
350 cp === DollarSign ||
351 cp === ReverseSolidus ||
352 cp === FullStop ||
353 cp === Asterisk ||
354 cp === PlusSign ||
355 cp === QuestionMark ||
356 cp === LeftParenthesis ||
357 cp === RightParenthesis ||
358 cp === LeftSquareBracket ||
359 cp === RightSquareBracket ||
360 cp === LeftCurlyBracket ||
361 cp === RightCurlyBracket ||
362 cp === VerticalLine);
363}
364function isRegExpIdentifierStart(cp) {
365 return isIdStart(cp) || cp === DollarSign || cp === LowLine;
366}
367function isRegExpIdentifierPart(cp) {
368 return (isIdContinue(cp) ||
369 cp === DollarSign ||
370 cp === LowLine ||
371 cp === ZeroWidthNonJoiner ||
372 cp === ZeroWidthJoiner);
373}
374function isUnicodePropertyNameCharacter(cp) {
375 return isLatinLetter(cp) || cp === LowLine;
376}
377function isUnicodePropertyValueCharacter(cp) {
378 return isUnicodePropertyNameCharacter(cp) || isDecimalDigit(cp);
379}
380class RegExpValidator {
381 constructor(options) {
382 this._reader = new Reader();
383 this._uFlag = false;
384 this._nFlag = false;
385 this._lastIntValue = 0;
386 this._lastMinValue = 0;
387 this._lastMaxValue = 0;
388 this._lastStrValue = "";
389 this._lastKeyValue = "";
390 this._lastValValue = "";
391 this._lastAssertionIsQuantifiable = false;
392 this._numCapturingParens = 0;
393 this._groupNames = new Set();
394 this._backreferenceNames = new Set();
395 this._options = options || {};
396 }
397 validateLiteral(source, start = 0, end = source.length) {
398 this._uFlag = this._nFlag = false;
399 this.reset(source, start, end);
400 this.onLiteralEnter(start);
401 if (this.eat(Solidus) && this.eatRegExpBody() && this.eat(Solidus)) {
402 const flagStart = this.index;
403 const uFlag = source.includes("u", flagStart);
404 this.validateFlags(source, flagStart, end);
405 this.validatePattern(source, start + 1, flagStart - 1, uFlag);
406 }
407 else if (start >= end) {
408 this.raise("Empty");
409 }
410 else {
411 const c = String.fromCodePoint(this.currentCodePoint);
412 this.raise(`Unexpected character '${c}'`);
413 }
414 this.onLiteralLeave(start, end);
415 }
416 validateFlags(source, start = 0, end = source.length) {
417 const existingFlags = new Set();
418 let global = false;
419 let ignoreCase = false;
420 let multiline = false;
421 let sticky = false;
422 let unicode = false;
423 let dotAll = false;
424 let hasIndices = false;
425 for (let i = start; i < end; ++i) {
426 const flag = source.charCodeAt(i);
427 if (existingFlags.has(flag)) {
428 this.raise(`Duplicated flag '${source[i]}'`);
429 }
430 existingFlags.add(flag);
431 if (flag === LatinSmallLetterG) {
432 global = true;
433 }
434 else if (flag === LatinSmallLetterI) {
435 ignoreCase = true;
436 }
437 else if (flag === LatinSmallLetterM) {
438 multiline = true;
439 }
440 else if (flag === LatinSmallLetterU && this.ecmaVersion >= 2015) {
441 unicode = true;
442 }
443 else if (flag === LatinSmallLetterY && this.ecmaVersion >= 2015) {
444 sticky = true;
445 }
446 else if (flag === LatinSmallLetterS && this.ecmaVersion >= 2018) {
447 dotAll = true;
448 }
449 else if (flag === LatinSmallLetterD && this.ecmaVersion >= 2022) {
450 hasIndices = true;
451 }
452 else {
453 this.raise(`Invalid flag '${source[i]}'`);
454 }
455 }
456 this.onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices);
457 }
458 validatePattern(source, start = 0, end = source.length, uFlag = false) {
459 this._uFlag = uFlag && this.ecmaVersion >= 2015;
460 this._nFlag = uFlag && this.ecmaVersion >= 2018;
461 this.reset(source, start, end);
462 this.consumePattern();
463 if (!this._nFlag &&
464 this.ecmaVersion >= 2018 &&
465 this._groupNames.size > 0) {
466 this._nFlag = true;
467 this.rewind(start);
468 this.consumePattern();
469 }
470 }
471 get strict() {
472 return Boolean(this._options.strict || this._uFlag);
473 }
474 get ecmaVersion() {
475 return this._options.ecmaVersion || 2022;
476 }
477 onLiteralEnter(start) {
478 if (this._options.onLiteralEnter) {
479 this._options.onLiteralEnter(start);
480 }
481 }
482 onLiteralLeave(start, end) {
483 if (this._options.onLiteralLeave) {
484 this._options.onLiteralLeave(start, end);
485 }
486 }
487 onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices) {
488 if (this._options.onFlags) {
489 this._options.onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices);
490 }
491 }
492 onPatternEnter(start) {
493 if (this._options.onPatternEnter) {
494 this._options.onPatternEnter(start);
495 }
496 }
497 onPatternLeave(start, end) {
498 if (this._options.onPatternLeave) {
499 this._options.onPatternLeave(start, end);
500 }
501 }
502 onDisjunctionEnter(start) {
503 if (this._options.onDisjunctionEnter) {
504 this._options.onDisjunctionEnter(start);
505 }
506 }
507 onDisjunctionLeave(start, end) {
508 if (this._options.onDisjunctionLeave) {
509 this._options.onDisjunctionLeave(start, end);
510 }
511 }
512 onAlternativeEnter(start, index) {
513 if (this._options.onAlternativeEnter) {
514 this._options.onAlternativeEnter(start, index);
515 }
516 }
517 onAlternativeLeave(start, end, index) {
518 if (this._options.onAlternativeLeave) {
519 this._options.onAlternativeLeave(start, end, index);
520 }
521 }
522 onGroupEnter(start) {
523 if (this._options.onGroupEnter) {
524 this._options.onGroupEnter(start);
525 }
526 }
527 onGroupLeave(start, end) {
528 if (this._options.onGroupLeave) {
529 this._options.onGroupLeave(start, end);
530 }
531 }
532 onCapturingGroupEnter(start, name) {
533 if (this._options.onCapturingGroupEnter) {
534 this._options.onCapturingGroupEnter(start, name);
535 }
536 }
537 onCapturingGroupLeave(start, end, name) {
538 if (this._options.onCapturingGroupLeave) {
539 this._options.onCapturingGroupLeave(start, end, name);
540 }
541 }
542 onQuantifier(start, end, min, max, greedy) {
543 if (this._options.onQuantifier) {
544 this._options.onQuantifier(start, end, min, max, greedy);
545 }
546 }
547 onLookaroundAssertionEnter(start, kind, negate) {
548 if (this._options.onLookaroundAssertionEnter) {
549 this._options.onLookaroundAssertionEnter(start, kind, negate);
550 }
551 }
552 onLookaroundAssertionLeave(start, end, kind, negate) {
553 if (this._options.onLookaroundAssertionLeave) {
554 this._options.onLookaroundAssertionLeave(start, end, kind, negate);
555 }
556 }
557 onEdgeAssertion(start, end, kind) {
558 if (this._options.onEdgeAssertion) {
559 this._options.onEdgeAssertion(start, end, kind);
560 }
561 }
562 onWordBoundaryAssertion(start, end, kind, negate) {
563 if (this._options.onWordBoundaryAssertion) {
564 this._options.onWordBoundaryAssertion(start, end, kind, negate);
565 }
566 }
567 onAnyCharacterSet(start, end, kind) {
568 if (this._options.onAnyCharacterSet) {
569 this._options.onAnyCharacterSet(start, end, kind);
570 }
571 }
572 onEscapeCharacterSet(start, end, kind, negate) {
573 if (this._options.onEscapeCharacterSet) {
574 this._options.onEscapeCharacterSet(start, end, kind, negate);
575 }
576 }
577 onUnicodePropertyCharacterSet(start, end, kind, key, value, negate) {
578 if (this._options.onUnicodePropertyCharacterSet) {
579 this._options.onUnicodePropertyCharacterSet(start, end, kind, key, value, negate);
580 }
581 }
582 onCharacter(start, end, value) {
583 if (this._options.onCharacter) {
584 this._options.onCharacter(start, end, value);
585 }
586 }
587 onBackreference(start, end, ref) {
588 if (this._options.onBackreference) {
589 this._options.onBackreference(start, end, ref);
590 }
591 }
592 onCharacterClassEnter(start, negate) {
593 if (this._options.onCharacterClassEnter) {
594 this._options.onCharacterClassEnter(start, negate);
595 }
596 }
597 onCharacterClassLeave(start, end, negate) {
598 if (this._options.onCharacterClassLeave) {
599 this._options.onCharacterClassLeave(start, end, negate);
600 }
601 }
602 onCharacterClassRange(start, end, min, max) {
603 if (this._options.onCharacterClassRange) {
604 this._options.onCharacterClassRange(start, end, min, max);
605 }
606 }
607 get source() {
608 return this._reader.source;
609 }
610 get index() {
611 return this._reader.index;
612 }
613 get currentCodePoint() {
614 return this._reader.currentCodePoint;
615 }
616 get nextCodePoint() {
617 return this._reader.nextCodePoint;
618 }
619 get nextCodePoint2() {
620 return this._reader.nextCodePoint2;
621 }
622 get nextCodePoint3() {
623 return this._reader.nextCodePoint3;
624 }
625 reset(source, start, end) {
626 this._reader.reset(source, start, end, this._uFlag);
627 }
628 rewind(index) {
629 this._reader.rewind(index);
630 }
631 advance() {
632 this._reader.advance();
633 }
634 eat(cp) {
635 return this._reader.eat(cp);
636 }
637 eat2(cp1, cp2) {
638 return this._reader.eat2(cp1, cp2);
639 }
640 eat3(cp1, cp2, cp3) {
641 return this._reader.eat3(cp1, cp2, cp3);
642 }
643 raise(message) {
644 throw new RegExpSyntaxError(this.source, this._uFlag, this.index, message);
645 }
646 eatRegExpBody() {
647 const start = this.index;
648 let inClass = false;
649 let escaped = false;
650 for (;;) {
651 const cp = this.currentCodePoint;
652 if (cp === -1 || isLineTerminator(cp)) {
653 const kind = inClass ? "character class" : "regular expression";
654 this.raise(`Unterminated ${kind}`);
655 }
656 if (escaped) {
657 escaped = false;
658 }
659 else if (cp === ReverseSolidus) {
660 escaped = true;
661 }
662 else if (cp === LeftSquareBracket) {
663 inClass = true;
664 }
665 else if (cp === RightSquareBracket) {
666 inClass = false;
667 }
668 else if ((cp === Solidus && !inClass) ||
669 (cp === Asterisk && this.index === start)) {
670 break;
671 }
672 this.advance();
673 }
674 return this.index !== start;
675 }
676 consumePattern() {
677 const start = this.index;
678 this._numCapturingParens = this.countCapturingParens();
679 this._groupNames.clear();
680 this._backreferenceNames.clear();
681 this.onPatternEnter(start);
682 this.consumeDisjunction();
683 const cp = this.currentCodePoint;
684 if (this.currentCodePoint !== -1) {
685 if (cp === RightParenthesis) {
686 this.raise("Unmatched ')'");
687 }
688 if (cp === ReverseSolidus) {
689 this.raise("\\ at end of pattern");
690 }
691 if (cp === RightSquareBracket || cp === RightCurlyBracket) {
692 this.raise("Lone quantifier brackets");
693 }
694 const c = String.fromCodePoint(cp);
695 this.raise(`Unexpected character '${c}'`);
696 }
697 for (const name of this._backreferenceNames) {
698 if (!this._groupNames.has(name)) {
699 this.raise("Invalid named capture referenced");
700 }
701 }
702 this.onPatternLeave(start, this.index);
703 }
704 countCapturingParens() {
705 const start = this.index;
706 let inClass = false;
707 let escaped = false;
708 let count = 0;
709 let cp = 0;
710 while ((cp = this.currentCodePoint) !== -1) {
711 if (escaped) {
712 escaped = false;
713 }
714 else if (cp === ReverseSolidus) {
715 escaped = true;
716 }
717 else if (cp === LeftSquareBracket) {
718 inClass = true;
719 }
720 else if (cp === RightSquareBracket) {
721 inClass = false;
722 }
723 else if (cp === LeftParenthesis &&
724 !inClass &&
725 (this.nextCodePoint !== QuestionMark ||
726 (this.nextCodePoint2 === LessThanSign &&
727 this.nextCodePoint3 !== EqualsSign &&
728 this.nextCodePoint3 !== ExclamationMark))) {
729 count += 1;
730 }
731 this.advance();
732 }
733 this.rewind(start);
734 return count;
735 }
736 consumeDisjunction() {
737 const start = this.index;
738 let i = 0;
739 this.onDisjunctionEnter(start);
740 do {
741 this.consumeAlternative(i++);
742 } while (this.eat(VerticalLine));
743 if (this.consumeQuantifier(true)) {
744 this.raise("Nothing to repeat");
745 }
746 if (this.eat(LeftCurlyBracket)) {
747 this.raise("Lone quantifier brackets");
748 }
749 this.onDisjunctionLeave(start, this.index);
750 }
751 consumeAlternative(i) {
752 const start = this.index;
753 this.onAlternativeEnter(start, i);
754 while (this.currentCodePoint !== -1 && this.consumeTerm()) {
755 }
756 this.onAlternativeLeave(start, this.index, i);
757 }
758 consumeTerm() {
759 if (this._uFlag || this.strict) {
760 return (this.consumeAssertion() ||
761 (this.consumeAtom() && this.consumeOptionalQuantifier()));
762 }
763 return ((this.consumeAssertion() &&
764 (!this._lastAssertionIsQuantifiable ||
765 this.consumeOptionalQuantifier())) ||
766 (this.consumeExtendedAtom() && this.consumeOptionalQuantifier()));
767 }
768 consumeOptionalQuantifier() {
769 this.consumeQuantifier();
770 return true;
771 }
772 consumeAssertion() {
773 const start = this.index;
774 this._lastAssertionIsQuantifiable = false;
775 if (this.eat(CircumflexAccent)) {
776 this.onEdgeAssertion(start, this.index, "start");
777 return true;
778 }
779 if (this.eat(DollarSign)) {
780 this.onEdgeAssertion(start, this.index, "end");
781 return true;
782 }
783 if (this.eat2(ReverseSolidus, LatinCapitalLetterB)) {
784 this.onWordBoundaryAssertion(start, this.index, "word", true);
785 return true;
786 }
787 if (this.eat2(ReverseSolidus, LatinSmallLetterB)) {
788 this.onWordBoundaryAssertion(start, this.index, "word", false);
789 return true;
790 }
791 if (this.eat2(LeftParenthesis, QuestionMark)) {
792 const lookbehind = this.ecmaVersion >= 2018 && this.eat(LessThanSign);
793 let negate = false;
794 if (this.eat(EqualsSign) || (negate = this.eat(ExclamationMark))) {
795 const kind = lookbehind ? "lookbehind" : "lookahead";
796 this.onLookaroundAssertionEnter(start, kind, negate);
797 this.consumeDisjunction();
798 if (!this.eat(RightParenthesis)) {
799 this.raise("Unterminated group");
800 }
801 this._lastAssertionIsQuantifiable = !lookbehind && !this.strict;
802 this.onLookaroundAssertionLeave(start, this.index, kind, negate);
803 return true;
804 }
805 this.rewind(start);
806 }
807 return false;
808 }
809 consumeQuantifier(noConsume = false) {
810 const start = this.index;
811 let min = 0;
812 let max = 0;
813 let greedy = false;
814 if (this.eat(Asterisk)) {
815 min = 0;
816 max = Number.POSITIVE_INFINITY;
817 }
818 else if (this.eat(PlusSign)) {
819 min = 1;
820 max = Number.POSITIVE_INFINITY;
821 }
822 else if (this.eat(QuestionMark)) {
823 min = 0;
824 max = 1;
825 }
826 else if (this.eatBracedQuantifier(noConsume)) {
827 min = this._lastMinValue;
828 max = this._lastMaxValue;
829 }
830 else {
831 return false;
832 }
833 greedy = !this.eat(QuestionMark);
834 if (!noConsume) {
835 this.onQuantifier(start, this.index, min, max, greedy);
836 }
837 return true;
838 }
839 eatBracedQuantifier(noError) {
840 const start = this.index;
841 if (this.eat(LeftCurlyBracket)) {
842 this._lastMinValue = 0;
843 this._lastMaxValue = Number.POSITIVE_INFINITY;
844 if (this.eatDecimalDigits()) {
845 this._lastMinValue = this._lastMaxValue = this._lastIntValue;
846 if (this.eat(Comma)) {
847 this._lastMaxValue = this.eatDecimalDigits()
848 ? this._lastIntValue
849 : Number.POSITIVE_INFINITY;
850 }
851 if (this.eat(RightCurlyBracket)) {
852 if (!noError && this._lastMaxValue < this._lastMinValue) {
853 this.raise("numbers out of order in {} quantifier");
854 }
855 return true;
856 }
857 }
858 if (!noError && (this._uFlag || this.strict)) {
859 this.raise("Incomplete quantifier");
860 }
861 this.rewind(start);
862 }
863 return false;
864 }
865 consumeAtom() {
866 return (this.consumePatternCharacter() ||
867 this.consumeDot() ||
868 this.consumeReverseSolidusAtomEscape() ||
869 this.consumeCharacterClass() ||
870 this.consumeUncapturingGroup() ||
871 this.consumeCapturingGroup());
872 }
873 consumeDot() {
874 if (this.eat(FullStop)) {
875 this.onAnyCharacterSet(this.index - 1, this.index, "any");
876 return true;
877 }
878 return false;
879 }
880 consumeReverseSolidusAtomEscape() {
881 const start = this.index;
882 if (this.eat(ReverseSolidus)) {
883 if (this.consumeAtomEscape()) {
884 return true;
885 }
886 this.rewind(start);
887 }
888 return false;
889 }
890 consumeUncapturingGroup() {
891 const start = this.index;
892 if (this.eat3(LeftParenthesis, QuestionMark, Colon)) {
893 this.onGroupEnter(start);
894 this.consumeDisjunction();
895 if (!this.eat(RightParenthesis)) {
896 this.raise("Unterminated group");
897 }
898 this.onGroupLeave(start, this.index);
899 return true;
900 }
901 return false;
902 }
903 consumeCapturingGroup() {
904 const start = this.index;
905 if (this.eat(LeftParenthesis)) {
906 let name = null;
907 if (this.ecmaVersion >= 2018) {
908 if (this.consumeGroupSpecifier()) {
909 name = this._lastStrValue;
910 }
911 }
912 else if (this.currentCodePoint === QuestionMark) {
913 this.raise("Invalid group");
914 }
915 this.onCapturingGroupEnter(start, name);
916 this.consumeDisjunction();
917 if (!this.eat(RightParenthesis)) {
918 this.raise("Unterminated group");
919 }
920 this.onCapturingGroupLeave(start, this.index, name);
921 return true;
922 }
923 return false;
924 }
925 consumeExtendedAtom() {
926 return (this.consumeDot() ||
927 this.consumeReverseSolidusAtomEscape() ||
928 this.consumeReverseSolidusFollowedByC() ||
929 this.consumeCharacterClass() ||
930 this.consumeUncapturingGroup() ||
931 this.consumeCapturingGroup() ||
932 this.consumeInvalidBracedQuantifier() ||
933 this.consumeExtendedPatternCharacter());
934 }
935 consumeReverseSolidusFollowedByC() {
936 const start = this.index;
937 if (this.currentCodePoint === ReverseSolidus &&
938 this.nextCodePoint === LatinSmallLetterC) {
939 this._lastIntValue = this.currentCodePoint;
940 this.advance();
941 this.onCharacter(start, this.index, ReverseSolidus);
942 return true;
943 }
944 return false;
945 }
946 consumeInvalidBracedQuantifier() {
947 if (this.eatBracedQuantifier(true)) {
948 this.raise("Nothing to repeat");
949 }
950 return false;
951 }
952 consumePatternCharacter() {
953 const start = this.index;
954 const cp = this.currentCodePoint;
955 if (cp !== -1 && !isSyntaxCharacter(cp)) {
956 this.advance();
957 this.onCharacter(start, this.index, cp);
958 return true;
959 }
960 return false;
961 }
962 consumeExtendedPatternCharacter() {
963 const start = this.index;
964 const cp = this.currentCodePoint;
965 if (cp !== -1 &&
966 cp !== CircumflexAccent &&
967 cp !== DollarSign &&
968 cp !== ReverseSolidus &&
969 cp !== FullStop &&
970 cp !== Asterisk &&
971 cp !== PlusSign &&
972 cp !== QuestionMark &&
973 cp !== LeftParenthesis &&
974 cp !== RightParenthesis &&
975 cp !== LeftSquareBracket &&
976 cp !== VerticalLine) {
977 this.advance();
978 this.onCharacter(start, this.index, cp);
979 return true;
980 }
981 return false;
982 }
983 consumeGroupSpecifier() {
984 if (this.eat(QuestionMark)) {
985 if (this.eatGroupName()) {
986 if (!this._groupNames.has(this._lastStrValue)) {
987 this._groupNames.add(this._lastStrValue);
988 return true;
989 }
990 this.raise("Duplicate capture group name");
991 }
992 this.raise("Invalid group");
993 }
994 return false;
995 }
996 consumeAtomEscape() {
997 if (this.consumeBackreference() ||
998 this.consumeCharacterClassEscape() ||
999 this.consumeCharacterEscape() ||
1000 (this._nFlag && this.consumeKGroupName())) {
1001 return true;
1002 }
1003 if (this.strict || this._uFlag) {
1004 this.raise("Invalid escape");
1005 }
1006 return false;
1007 }
1008 consumeBackreference() {
1009 const start = this.index;
1010 if (this.eatDecimalEscape()) {
1011 const n = this._lastIntValue;
1012 if (n <= this._numCapturingParens) {
1013 this.onBackreference(start - 1, this.index, n);
1014 return true;
1015 }
1016 if (this.strict || this._uFlag) {
1017 this.raise("Invalid escape");
1018 }
1019 this.rewind(start);
1020 }
1021 return false;
1022 }
1023 consumeCharacterClassEscape() {
1024 const start = this.index;
1025 if (this.eat(LatinSmallLetterD)) {
1026 this._lastIntValue = -1;
1027 this.onEscapeCharacterSet(start - 1, this.index, "digit", false);
1028 return true;
1029 }
1030 if (this.eat(LatinCapitalLetterD)) {
1031 this._lastIntValue = -1;
1032 this.onEscapeCharacterSet(start - 1, this.index, "digit", true);
1033 return true;
1034 }
1035 if (this.eat(LatinSmallLetterS)) {
1036 this._lastIntValue = -1;
1037 this.onEscapeCharacterSet(start - 1, this.index, "space", false);
1038 return true;
1039 }
1040 if (this.eat(LatinCapitalLetterS)) {
1041 this._lastIntValue = -1;
1042 this.onEscapeCharacterSet(start - 1, this.index, "space", true);
1043 return true;
1044 }
1045 if (this.eat(LatinSmallLetterW)) {
1046 this._lastIntValue = -1;
1047 this.onEscapeCharacterSet(start - 1, this.index, "word", false);
1048 return true;
1049 }
1050 if (this.eat(LatinCapitalLetterW)) {
1051 this._lastIntValue = -1;
1052 this.onEscapeCharacterSet(start - 1, this.index, "word", true);
1053 return true;
1054 }
1055 let negate = false;
1056 if (this._uFlag &&
1057 this.ecmaVersion >= 2018 &&
1058 (this.eat(LatinSmallLetterP) ||
1059 (negate = this.eat(LatinCapitalLetterP)))) {
1060 this._lastIntValue = -1;
1061 if (this.eat(LeftCurlyBracket) &&
1062 this.eatUnicodePropertyValueExpression() &&
1063 this.eat(RightCurlyBracket)) {
1064 this.onUnicodePropertyCharacterSet(start - 1, this.index, "property", this._lastKeyValue, this._lastValValue || null, negate);
1065 return true;
1066 }
1067 this.raise("Invalid property name");
1068 }
1069 return false;
1070 }
1071 consumeCharacterEscape() {
1072 const start = this.index;
1073 if (this.eatControlEscape() ||
1074 this.eatCControlLetter() ||
1075 this.eatZero() ||
1076 this.eatHexEscapeSequence() ||
1077 this.eatRegExpUnicodeEscapeSequence() ||
1078 (!this.strict &&
1079 !this._uFlag &&
1080 this.eatLegacyOctalEscapeSequence()) ||
1081 this.eatIdentityEscape()) {
1082 this.onCharacter(start - 1, this.index, this._lastIntValue);
1083 return true;
1084 }
1085 return false;
1086 }
1087 consumeKGroupName() {
1088 const start = this.index;
1089 if (this.eat(LatinSmallLetterK)) {
1090 if (this.eatGroupName()) {
1091 const groupName = this._lastStrValue;
1092 this._backreferenceNames.add(groupName);
1093 this.onBackreference(start - 1, this.index, groupName);
1094 return true;
1095 }
1096 this.raise("Invalid named reference");
1097 }
1098 return false;
1099 }
1100 consumeCharacterClass() {
1101 const start = this.index;
1102 if (this.eat(LeftSquareBracket)) {
1103 const negate = this.eat(CircumflexAccent);
1104 this.onCharacterClassEnter(start, negate);
1105 this.consumeClassRanges();
1106 if (!this.eat(RightSquareBracket)) {
1107 this.raise("Unterminated character class");
1108 }
1109 this.onCharacterClassLeave(start, this.index, negate);
1110 return true;
1111 }
1112 return false;
1113 }
1114 consumeClassRanges() {
1115 const strict = this.strict || this._uFlag;
1116 for (;;) {
1117 const rangeStart = this.index;
1118 if (!this.consumeClassAtom()) {
1119 break;
1120 }
1121 const min = this._lastIntValue;
1122 if (!this.eat(HyphenMinus)) {
1123 continue;
1124 }
1125 this.onCharacter(this.index - 1, this.index, HyphenMinus);
1126 if (!this.consumeClassAtom()) {
1127 break;
1128 }
1129 const max = this._lastIntValue;
1130 if (min === -1 || max === -1) {
1131 if (strict) {
1132 this.raise("Invalid character class");
1133 }
1134 continue;
1135 }
1136 if (min > max) {
1137 this.raise("Range out of order in character class");
1138 }
1139 this.onCharacterClassRange(rangeStart, this.index, min, max);
1140 }
1141 }
1142 consumeClassAtom() {
1143 const start = this.index;
1144 const cp = this.currentCodePoint;
1145 if (cp !== -1 && cp !== ReverseSolidus && cp !== RightSquareBracket) {
1146 this.advance();
1147 this._lastIntValue = cp;
1148 this.onCharacter(start, this.index, this._lastIntValue);
1149 return true;
1150 }
1151 if (this.eat(ReverseSolidus)) {
1152 if (this.consumeClassEscape()) {
1153 return true;
1154 }
1155 if (!this.strict && this.currentCodePoint === LatinSmallLetterC) {
1156 this._lastIntValue = ReverseSolidus;
1157 this.onCharacter(start, this.index, this._lastIntValue);
1158 return true;
1159 }
1160 if (this.strict || this._uFlag) {
1161 this.raise("Invalid escape");
1162 }
1163 this.rewind(start);
1164 }
1165 return false;
1166 }
1167 consumeClassEscape() {
1168 const start = this.index;
1169 if (this.eat(LatinSmallLetterB)) {
1170 this._lastIntValue = Backspace;
1171 this.onCharacter(start - 1, this.index, this._lastIntValue);
1172 return true;
1173 }
1174 if (this._uFlag && this.eat(HyphenMinus)) {
1175 this._lastIntValue = HyphenMinus;
1176 this.onCharacter(start - 1, this.index, this._lastIntValue);
1177 return true;
1178 }
1179 let cp = 0;
1180 if (!this.strict &&
1181 !this._uFlag &&
1182 this.currentCodePoint === LatinSmallLetterC &&
1183 (isDecimalDigit((cp = this.nextCodePoint)) || cp === LowLine)) {
1184 this.advance();
1185 this.advance();
1186 this._lastIntValue = cp % 0x20;
1187 this.onCharacter(start - 1, this.index, this._lastIntValue);
1188 return true;
1189 }
1190 return (this.consumeCharacterClassEscape() || this.consumeCharacterEscape());
1191 }
1192 eatGroupName() {
1193 if (this.eat(LessThanSign)) {
1194 if (this.eatRegExpIdentifierName() && this.eat(GreaterThanSign)) {
1195 return true;
1196 }
1197 this.raise("Invalid capture group name");
1198 }
1199 return false;
1200 }
1201 eatRegExpIdentifierName() {
1202 if (this.eatRegExpIdentifierStart()) {
1203 this._lastStrValue = String.fromCodePoint(this._lastIntValue);
1204 while (this.eatRegExpIdentifierPart()) {
1205 this._lastStrValue += String.fromCodePoint(this._lastIntValue);
1206 }
1207 return true;
1208 }
1209 return false;
1210 }
1211 eatRegExpIdentifierStart() {
1212 const start = this.index;
1213 const forceUFlag = !this._uFlag && this.ecmaVersion >= 2020;
1214 let cp = this.currentCodePoint;
1215 this.advance();
1216 if (cp === ReverseSolidus &&
1217 this.eatRegExpUnicodeEscapeSequence(forceUFlag)) {
1218 cp = this._lastIntValue;
1219 }
1220 else if (forceUFlag &&
1221 isLeadSurrogate(cp) &&
1222 isTrailSurrogate(this.currentCodePoint)) {
1223 cp = combineSurrogatePair(cp, this.currentCodePoint);
1224 this.advance();
1225 }
1226 if (isRegExpIdentifierStart(cp)) {
1227 this._lastIntValue = cp;
1228 return true;
1229 }
1230 if (this.index !== start) {
1231 this.rewind(start);
1232 }
1233 return false;
1234 }
1235 eatRegExpIdentifierPart() {
1236 const start = this.index;
1237 const forceUFlag = !this._uFlag && this.ecmaVersion >= 2020;
1238 let cp = this.currentCodePoint;
1239 this.advance();
1240 if (cp === ReverseSolidus &&
1241 this.eatRegExpUnicodeEscapeSequence(forceUFlag)) {
1242 cp = this._lastIntValue;
1243 }
1244 else if (forceUFlag &&
1245 isLeadSurrogate(cp) &&
1246 isTrailSurrogate(this.currentCodePoint)) {
1247 cp = combineSurrogatePair(cp, this.currentCodePoint);
1248 this.advance();
1249 }
1250 if (isRegExpIdentifierPart(cp)) {
1251 this._lastIntValue = cp;
1252 return true;
1253 }
1254 if (this.index !== start) {
1255 this.rewind(start);
1256 }
1257 return false;
1258 }
1259 eatCControlLetter() {
1260 const start = this.index;
1261 if (this.eat(LatinSmallLetterC)) {
1262 if (this.eatControlLetter()) {
1263 return true;
1264 }
1265 this.rewind(start);
1266 }
1267 return false;
1268 }
1269 eatZero() {
1270 if (this.currentCodePoint === DigitZero &&
1271 !isDecimalDigit(this.nextCodePoint)) {
1272 this._lastIntValue = 0;
1273 this.advance();
1274 return true;
1275 }
1276 return false;
1277 }
1278 eatControlEscape() {
1279 if (this.eat(LatinSmallLetterF)) {
1280 this._lastIntValue = FormFeed;
1281 return true;
1282 }
1283 if (this.eat(LatinSmallLetterN)) {
1284 this._lastIntValue = LineFeed;
1285 return true;
1286 }
1287 if (this.eat(LatinSmallLetterR)) {
1288 this._lastIntValue = CarriageReturn;
1289 return true;
1290 }
1291 if (this.eat(LatinSmallLetterT)) {
1292 this._lastIntValue = CharacterTabulation;
1293 return true;
1294 }
1295 if (this.eat(LatinSmallLetterV)) {
1296 this._lastIntValue = LineTabulation;
1297 return true;
1298 }
1299 return false;
1300 }
1301 eatControlLetter() {
1302 const cp = this.currentCodePoint;
1303 if (isLatinLetter(cp)) {
1304 this.advance();
1305 this._lastIntValue = cp % 0x20;
1306 return true;
1307 }
1308 return false;
1309 }
1310 eatRegExpUnicodeEscapeSequence(forceUFlag = false) {
1311 const start = this.index;
1312 const uFlag = forceUFlag || this._uFlag;
1313 if (this.eat(LatinSmallLetterU)) {
1314 if ((uFlag && this.eatRegExpUnicodeSurrogatePairEscape()) ||
1315 this.eatFixedHexDigits(4) ||
1316 (uFlag && this.eatRegExpUnicodeCodePointEscape())) {
1317 return true;
1318 }
1319 if (this.strict || uFlag) {
1320 this.raise("Invalid unicode escape");
1321 }
1322 this.rewind(start);
1323 }
1324 return false;
1325 }
1326 eatRegExpUnicodeSurrogatePairEscape() {
1327 const start = this.index;
1328 if (this.eatFixedHexDigits(4)) {
1329 const lead = this._lastIntValue;
1330 if (isLeadSurrogate(lead) &&
1331 this.eat(ReverseSolidus) &&
1332 this.eat(LatinSmallLetterU) &&
1333 this.eatFixedHexDigits(4)) {
1334 const trail = this._lastIntValue;
1335 if (isTrailSurrogate(trail)) {
1336 this._lastIntValue = combineSurrogatePair(lead, trail);
1337 return true;
1338 }
1339 }
1340 this.rewind(start);
1341 }
1342 return false;
1343 }
1344 eatRegExpUnicodeCodePointEscape() {
1345 const start = this.index;
1346 if (this.eat(LeftCurlyBracket) &&
1347 this.eatHexDigits() &&
1348 this.eat(RightCurlyBracket) &&
1349 isValidUnicode(this._lastIntValue)) {
1350 return true;
1351 }
1352 this.rewind(start);
1353 return false;
1354 }
1355 eatIdentityEscape() {
1356 const cp = this.currentCodePoint;
1357 if (this.isValidIdentityEscape(cp)) {
1358 this._lastIntValue = cp;
1359 this.advance();
1360 return true;
1361 }
1362 return false;
1363 }
1364 isValidIdentityEscape(cp) {
1365 if (cp === -1) {
1366 return false;
1367 }
1368 if (this._uFlag) {
1369 return isSyntaxCharacter(cp) || cp === Solidus;
1370 }
1371 if (this.strict) {
1372 return !isIdContinue(cp);
1373 }
1374 if (this._nFlag) {
1375 return !(cp === LatinSmallLetterC || cp === LatinSmallLetterK);
1376 }
1377 return cp !== LatinSmallLetterC;
1378 }
1379 eatDecimalEscape() {
1380 this._lastIntValue = 0;
1381 let cp = this.currentCodePoint;
1382 if (cp >= DigitOne && cp <= DigitNine) {
1383 do {
1384 this._lastIntValue = 10 * this._lastIntValue + (cp - DigitZero);
1385 this.advance();
1386 } while ((cp = this.currentCodePoint) >= DigitZero &&
1387 cp <= DigitNine);
1388 return true;
1389 }
1390 return false;
1391 }
1392 eatUnicodePropertyValueExpression() {
1393 const start = this.index;
1394 if (this.eatUnicodePropertyName() && this.eat(EqualsSign)) {
1395 this._lastKeyValue = this._lastStrValue;
1396 if (this.eatUnicodePropertyValue()) {
1397 this._lastValValue = this._lastStrValue;
1398 if (isValidUnicodeProperty(this.ecmaVersion, this._lastKeyValue, this._lastValValue)) {
1399 return true;
1400 }
1401 this.raise("Invalid property name");
1402 }
1403 }
1404 this.rewind(start);
1405 if (this.eatLoneUnicodePropertyNameOrValue()) {
1406 const nameOrValue = this._lastStrValue;
1407 if (isValidUnicodeProperty(this.ecmaVersion, "General_Category", nameOrValue)) {
1408 this._lastKeyValue = "General_Category";
1409 this._lastValValue = nameOrValue;
1410 return true;
1411 }
1412 if (isValidLoneUnicodeProperty(this.ecmaVersion, nameOrValue)) {
1413 this._lastKeyValue = nameOrValue;
1414 this._lastValValue = "";
1415 return true;
1416 }
1417 this.raise("Invalid property name");
1418 }
1419 return false;
1420 }
1421 eatUnicodePropertyName() {
1422 this._lastStrValue = "";
1423 while (isUnicodePropertyNameCharacter(this.currentCodePoint)) {
1424 this._lastStrValue += String.fromCodePoint(this.currentCodePoint);
1425 this.advance();
1426 }
1427 return this._lastStrValue !== "";
1428 }
1429 eatUnicodePropertyValue() {
1430 this._lastStrValue = "";
1431 while (isUnicodePropertyValueCharacter(this.currentCodePoint)) {
1432 this._lastStrValue += String.fromCodePoint(this.currentCodePoint);
1433 this.advance();
1434 }
1435 return this._lastStrValue !== "";
1436 }
1437 eatLoneUnicodePropertyNameOrValue() {
1438 return this.eatUnicodePropertyValue();
1439 }
1440 eatHexEscapeSequence() {
1441 const start = this.index;
1442 if (this.eat(LatinSmallLetterX)) {
1443 if (this.eatFixedHexDigits(2)) {
1444 return true;
1445 }
1446 if (this._uFlag || this.strict) {
1447 this.raise("Invalid escape");
1448 }
1449 this.rewind(start);
1450 }
1451 return false;
1452 }
1453 eatDecimalDigits() {
1454 const start = this.index;
1455 this._lastIntValue = 0;
1456 while (isDecimalDigit(this.currentCodePoint)) {
1457 this._lastIntValue =
1458 10 * this._lastIntValue + digitToInt(this.currentCodePoint);
1459 this.advance();
1460 }
1461 return this.index !== start;
1462 }
1463 eatHexDigits() {
1464 const start = this.index;
1465 this._lastIntValue = 0;
1466 while (isHexDigit(this.currentCodePoint)) {
1467 this._lastIntValue =
1468 16 * this._lastIntValue + digitToInt(this.currentCodePoint);
1469 this.advance();
1470 }
1471 return this.index !== start;
1472 }
1473 eatLegacyOctalEscapeSequence() {
1474 if (this.eatOctalDigit()) {
1475 const n1 = this._lastIntValue;
1476 if (this.eatOctalDigit()) {
1477 const n2 = this._lastIntValue;
1478 if (n1 <= 3 && this.eatOctalDigit()) {
1479 this._lastIntValue = n1 * 64 + n2 * 8 + this._lastIntValue;
1480 }
1481 else {
1482 this._lastIntValue = n1 * 8 + n2;
1483 }
1484 }
1485 else {
1486 this._lastIntValue = n1;
1487 }
1488 return true;
1489 }
1490 return false;
1491 }
1492 eatOctalDigit() {
1493 const cp = this.currentCodePoint;
1494 if (isOctalDigit(cp)) {
1495 this.advance();
1496 this._lastIntValue = cp - DigitZero;
1497 return true;
1498 }
1499 this._lastIntValue = 0;
1500 return false;
1501 }
1502 eatFixedHexDigits(length) {
1503 const start = this.index;
1504 this._lastIntValue = 0;
1505 for (let i = 0; i < length; ++i) {
1506 const cp = this.currentCodePoint;
1507 if (!isHexDigit(cp)) {
1508 this.rewind(start);
1509 return false;
1510 }
1511 this._lastIntValue = 16 * this._lastIntValue + digitToInt(cp);
1512 this.advance();
1513 }
1514 return true;
1515 }
1516}
1517
1518const DummyPattern = {};
1519const DummyFlags = {};
1520const DummyCapturingGroup = {};
1521class RegExpParserState {
1522 constructor(options) {
1523 this._node = DummyPattern;
1524 this._flags = DummyFlags;
1525 this._backreferences = [];
1526 this._capturingGroups = [];
1527 this.source = "";
1528 this.strict = Boolean(options && options.strict);
1529 this.ecmaVersion = (options && options.ecmaVersion) || 2022;
1530 }
1531 get pattern() {
1532 if (this._node.type !== "Pattern") {
1533 throw new Error("UnknownError");
1534 }
1535 return this._node;
1536 }
1537 get flags() {
1538 if (this._flags.type !== "Flags") {
1539 throw new Error("UnknownError");
1540 }
1541 return this._flags;
1542 }
1543 onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices) {
1544 this._flags = {
1545 type: "Flags",
1546 parent: null,
1547 start,
1548 end,
1549 raw: this.source.slice(start, end),
1550 global,
1551 ignoreCase,
1552 multiline,
1553 unicode,
1554 sticky,
1555 dotAll,
1556 hasIndices,
1557 };
1558 }
1559 onPatternEnter(start) {
1560 this._node = {
1561 type: "Pattern",
1562 parent: null,
1563 start,
1564 end: start,
1565 raw: "",
1566 alternatives: [],
1567 };
1568 this._backreferences.length = 0;
1569 this._capturingGroups.length = 0;
1570 }
1571 onPatternLeave(start, end) {
1572 this._node.end = end;
1573 this._node.raw = this.source.slice(start, end);
1574 for (const reference of this._backreferences) {
1575 const ref = reference.ref;
1576 const group = typeof ref === "number"
1577 ? this._capturingGroups[ref - 1]
1578 : this._capturingGroups.find(g => g.name === ref);
1579 reference.resolved = group;
1580 group.references.push(reference);
1581 }
1582 }
1583 onAlternativeEnter(start) {
1584 const parent = this._node;
1585 if (parent.type !== "Assertion" &&
1586 parent.type !== "CapturingGroup" &&
1587 parent.type !== "Group" &&
1588 parent.type !== "Pattern") {
1589 throw new Error("UnknownError");
1590 }
1591 this._node = {
1592 type: "Alternative",
1593 parent,
1594 start,
1595 end: start,
1596 raw: "",
1597 elements: [],
1598 };
1599 parent.alternatives.push(this._node);
1600 }
1601 onAlternativeLeave(start, end) {
1602 const node = this._node;
1603 if (node.type !== "Alternative") {
1604 throw new Error("UnknownError");
1605 }
1606 node.end = end;
1607 node.raw = this.source.slice(start, end);
1608 this._node = node.parent;
1609 }
1610 onGroupEnter(start) {
1611 const parent = this._node;
1612 if (parent.type !== "Alternative") {
1613 throw new Error("UnknownError");
1614 }
1615 this._node = {
1616 type: "Group",
1617 parent,
1618 start,
1619 end: start,
1620 raw: "",
1621 alternatives: [],
1622 };
1623 parent.elements.push(this._node);
1624 }
1625 onGroupLeave(start, end) {
1626 const node = this._node;
1627 if (node.type !== "Group" || node.parent.type !== "Alternative") {
1628 throw new Error("UnknownError");
1629 }
1630 node.end = end;
1631 node.raw = this.source.slice(start, end);
1632 this._node = node.parent;
1633 }
1634 onCapturingGroupEnter(start, name) {
1635 const parent = this._node;
1636 if (parent.type !== "Alternative") {
1637 throw new Error("UnknownError");
1638 }
1639 this._node = {
1640 type: "CapturingGroup",
1641 parent,
1642 start,
1643 end: start,
1644 raw: "",
1645 name,
1646 alternatives: [],
1647 references: [],
1648 };
1649 parent.elements.push(this._node);
1650 this._capturingGroups.push(this._node);
1651 }
1652 onCapturingGroupLeave(start, end) {
1653 const node = this._node;
1654 if (node.type !== "CapturingGroup" ||
1655 node.parent.type !== "Alternative") {
1656 throw new Error("UnknownError");
1657 }
1658 node.end = end;
1659 node.raw = this.source.slice(start, end);
1660 this._node = node.parent;
1661 }
1662 onQuantifier(start, end, min, max, greedy) {
1663 const parent = this._node;
1664 if (parent.type !== "Alternative") {
1665 throw new Error("UnknownError");
1666 }
1667 const element = parent.elements.pop();
1668 if (element == null ||
1669 element.type === "Quantifier" ||
1670 (element.type === "Assertion" && element.kind !== "lookahead")) {
1671 throw new Error("UnknownError");
1672 }
1673 const node = {
1674 type: "Quantifier",
1675 parent,
1676 start: element.start,
1677 end,
1678 raw: this.source.slice(element.start, end),
1679 min,
1680 max,
1681 greedy,
1682 element,
1683 };
1684 parent.elements.push(node);
1685 element.parent = node;
1686 }
1687 onLookaroundAssertionEnter(start, kind, negate) {
1688 const parent = this._node;
1689 if (parent.type !== "Alternative") {
1690 throw new Error("UnknownError");
1691 }
1692 const node = (this._node = {
1693 type: "Assertion",
1694 parent,
1695 start,
1696 end: start,
1697 raw: "",
1698 kind,
1699 negate,
1700 alternatives: [],
1701 });
1702 parent.elements.push(node);
1703 }
1704 onLookaroundAssertionLeave(start, end) {
1705 const node = this._node;
1706 if (node.type !== "Assertion" || node.parent.type !== "Alternative") {
1707 throw new Error("UnknownError");
1708 }
1709 node.end = end;
1710 node.raw = this.source.slice(start, end);
1711 this._node = node.parent;
1712 }
1713 onEdgeAssertion(start, end, kind) {
1714 const parent = this._node;
1715 if (parent.type !== "Alternative") {
1716 throw new Error("UnknownError");
1717 }
1718 parent.elements.push({
1719 type: "Assertion",
1720 parent,
1721 start,
1722 end,
1723 raw: this.source.slice(start, end),
1724 kind,
1725 });
1726 }
1727 onWordBoundaryAssertion(start, end, kind, negate) {
1728 const parent = this._node;
1729 if (parent.type !== "Alternative") {
1730 throw new Error("UnknownError");
1731 }
1732 parent.elements.push({
1733 type: "Assertion",
1734 parent,
1735 start,
1736 end,
1737 raw: this.source.slice(start, end),
1738 kind,
1739 negate,
1740 });
1741 }
1742 onAnyCharacterSet(start, end, kind) {
1743 const parent = this._node;
1744 if (parent.type !== "Alternative") {
1745 throw new Error("UnknownError");
1746 }
1747 parent.elements.push({
1748 type: "CharacterSet",
1749 parent,
1750 start,
1751 end,
1752 raw: this.source.slice(start, end),
1753 kind,
1754 });
1755 }
1756 onEscapeCharacterSet(start, end, kind, negate) {
1757 const parent = this._node;
1758 if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
1759 throw new Error("UnknownError");
1760 }
1761 parent.elements.push({
1762 type: "CharacterSet",
1763 parent,
1764 start,
1765 end,
1766 raw: this.source.slice(start, end),
1767 kind,
1768 negate,
1769 });
1770 }
1771 onUnicodePropertyCharacterSet(start, end, kind, key, value, negate) {
1772 const parent = this._node;
1773 if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
1774 throw new Error("UnknownError");
1775 }
1776 parent.elements.push({
1777 type: "CharacterSet",
1778 parent,
1779 start,
1780 end,
1781 raw: this.source.slice(start, end),
1782 kind,
1783 key,
1784 value,
1785 negate,
1786 });
1787 }
1788 onCharacter(start, end, value) {
1789 const parent = this._node;
1790 if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
1791 throw new Error("UnknownError");
1792 }
1793 parent.elements.push({
1794 type: "Character",
1795 parent,
1796 start,
1797 end,
1798 raw: this.source.slice(start, end),
1799 value,
1800 });
1801 }
1802 onBackreference(start, end, ref) {
1803 const parent = this._node;
1804 if (parent.type !== "Alternative") {
1805 throw new Error("UnknownError");
1806 }
1807 const node = {
1808 type: "Backreference",
1809 parent,
1810 start,
1811 end,
1812 raw: this.source.slice(start, end),
1813 ref,
1814 resolved: DummyCapturingGroup,
1815 };
1816 parent.elements.push(node);
1817 this._backreferences.push(node);
1818 }
1819 onCharacterClassEnter(start, negate) {
1820 const parent = this._node;
1821 if (parent.type !== "Alternative") {
1822 throw new Error("UnknownError");
1823 }
1824 this._node = {
1825 type: "CharacterClass",
1826 parent,
1827 start,
1828 end: start,
1829 raw: "",
1830 negate,
1831 elements: [],
1832 };
1833 parent.elements.push(this._node);
1834 }
1835 onCharacterClassLeave(start, end) {
1836 const node = this._node;
1837 if (node.type !== "CharacterClass" ||
1838 node.parent.type !== "Alternative") {
1839 throw new Error("UnknownError");
1840 }
1841 node.end = end;
1842 node.raw = this.source.slice(start, end);
1843 this._node = node.parent;
1844 }
1845 onCharacterClassRange(start, end) {
1846 const parent = this._node;
1847 if (parent.type !== "CharacterClass") {
1848 throw new Error("UnknownError");
1849 }
1850 const elements = parent.elements;
1851 const max = elements.pop();
1852 const hyphen = elements.pop();
1853 const min = elements.pop();
1854 if (!min ||
1855 !max ||
1856 !hyphen ||
1857 min.type !== "Character" ||
1858 max.type !== "Character" ||
1859 hyphen.type !== "Character" ||
1860 hyphen.value !== HyphenMinus) {
1861 throw new Error("UnknownError");
1862 }
1863 const node = {
1864 type: "CharacterClassRange",
1865 parent,
1866 start,
1867 end,
1868 raw: this.source.slice(start, end),
1869 min,
1870 max,
1871 };
1872 min.parent = node;
1873 max.parent = node;
1874 elements.push(node);
1875 }
1876}
1877class RegExpParser {
1878 constructor(options) {
1879 this._state = new RegExpParserState(options);
1880 this._validator = new RegExpValidator(this._state);
1881 }
1882 parseLiteral(source, start = 0, end = source.length) {
1883 this._state.source = source;
1884 this._validator.validateLiteral(source, start, end);
1885 const pattern = this._state.pattern;
1886 const flags = this._state.flags;
1887 const literal = {
1888 type: "RegExpLiteral",
1889 parent: null,
1890 start,
1891 end,
1892 raw: source,
1893 pattern,
1894 flags,
1895 };
1896 pattern.parent = literal;
1897 flags.parent = literal;
1898 return literal;
1899 }
1900 parseFlags(source, start = 0, end = source.length) {
1901 this._state.source = source;
1902 this._validator.validateFlags(source, start, end);
1903 return this._state.flags;
1904 }
1905 parsePattern(source, start = 0, end = source.length, uFlag = false) {
1906 this._state.source = source;
1907 this._validator.validatePattern(source, start, end, uFlag);
1908 return this._state.pattern;
1909 }
1910}
1911
1912class RegExpVisitor {
1913 constructor(handlers) {
1914 this._handlers = handlers;
1915 }
1916 visit(node) {
1917 switch (node.type) {
1918 case "Alternative":
1919 this.visitAlternative(node);
1920 break;
1921 case "Assertion":
1922 this.visitAssertion(node);
1923 break;
1924 case "Backreference":
1925 this.visitBackreference(node);
1926 break;
1927 case "CapturingGroup":
1928 this.visitCapturingGroup(node);
1929 break;
1930 case "Character":
1931 this.visitCharacter(node);
1932 break;
1933 case "CharacterClass":
1934 this.visitCharacterClass(node);
1935 break;
1936 case "CharacterClassRange":
1937 this.visitCharacterClassRange(node);
1938 break;
1939 case "CharacterSet":
1940 this.visitCharacterSet(node);
1941 break;
1942 case "Flags":
1943 this.visitFlags(node);
1944 break;
1945 case "Group":
1946 this.visitGroup(node);
1947 break;
1948 case "Pattern":
1949 this.visitPattern(node);
1950 break;
1951 case "Quantifier":
1952 this.visitQuantifier(node);
1953 break;
1954 case "RegExpLiteral":
1955 this.visitRegExpLiteral(node);
1956 break;
1957 default:
1958 throw new Error(`Unknown type: ${node.type}`);
1959 }
1960 }
1961 visitAlternative(node) {
1962 if (this._handlers.onAlternativeEnter) {
1963 this._handlers.onAlternativeEnter(node);
1964 }
1965 node.elements.forEach(this.visit, this);
1966 if (this._handlers.onAlternativeLeave) {
1967 this._handlers.onAlternativeLeave(node);
1968 }
1969 }
1970 visitAssertion(node) {
1971 if (this._handlers.onAssertionEnter) {
1972 this._handlers.onAssertionEnter(node);
1973 }
1974 if (node.kind === "lookahead" || node.kind === "lookbehind") {
1975 node.alternatives.forEach(this.visit, this);
1976 }
1977 if (this._handlers.onAssertionLeave) {
1978 this._handlers.onAssertionLeave(node);
1979 }
1980 }
1981 visitBackreference(node) {
1982 if (this._handlers.onBackreferenceEnter) {
1983 this._handlers.onBackreferenceEnter(node);
1984 }
1985 if (this._handlers.onBackreferenceLeave) {
1986 this._handlers.onBackreferenceLeave(node);
1987 }
1988 }
1989 visitCapturingGroup(node) {
1990 if (this._handlers.onCapturingGroupEnter) {
1991 this._handlers.onCapturingGroupEnter(node);
1992 }
1993 node.alternatives.forEach(this.visit, this);
1994 if (this._handlers.onCapturingGroupLeave) {
1995 this._handlers.onCapturingGroupLeave(node);
1996 }
1997 }
1998 visitCharacter(node) {
1999 if (this._handlers.onCharacterEnter) {
2000 this._handlers.onCharacterEnter(node);
2001 }
2002 if (this._handlers.onCharacterLeave) {
2003 this._handlers.onCharacterLeave(node);
2004 }
2005 }
2006 visitCharacterClass(node) {
2007 if (this._handlers.onCharacterClassEnter) {
2008 this._handlers.onCharacterClassEnter(node);
2009 }
2010 node.elements.forEach(this.visit, this);
2011 if (this._handlers.onCharacterClassLeave) {
2012 this._handlers.onCharacterClassLeave(node);
2013 }
2014 }
2015 visitCharacterClassRange(node) {
2016 if (this._handlers.onCharacterClassRangeEnter) {
2017 this._handlers.onCharacterClassRangeEnter(node);
2018 }
2019 this.visitCharacter(node.min);
2020 this.visitCharacter(node.max);
2021 if (this._handlers.onCharacterClassRangeLeave) {
2022 this._handlers.onCharacterClassRangeLeave(node);
2023 }
2024 }
2025 visitCharacterSet(node) {
2026 if (this._handlers.onCharacterSetEnter) {
2027 this._handlers.onCharacterSetEnter(node);
2028 }
2029 if (this._handlers.onCharacterSetLeave) {
2030 this._handlers.onCharacterSetLeave(node);
2031 }
2032 }
2033 visitFlags(node) {
2034 if (this._handlers.onFlagsEnter) {
2035 this._handlers.onFlagsEnter(node);
2036 }
2037 if (this._handlers.onFlagsLeave) {
2038 this._handlers.onFlagsLeave(node);
2039 }
2040 }
2041 visitGroup(node) {
2042 if (this._handlers.onGroupEnter) {
2043 this._handlers.onGroupEnter(node);
2044 }
2045 node.alternatives.forEach(this.visit, this);
2046 if (this._handlers.onGroupLeave) {
2047 this._handlers.onGroupLeave(node);
2048 }
2049 }
2050 visitPattern(node) {
2051 if (this._handlers.onPatternEnter) {
2052 this._handlers.onPatternEnter(node);
2053 }
2054 node.alternatives.forEach(this.visit, this);
2055 if (this._handlers.onPatternLeave) {
2056 this._handlers.onPatternLeave(node);
2057 }
2058 }
2059 visitQuantifier(node) {
2060 if (this._handlers.onQuantifierEnter) {
2061 this._handlers.onQuantifierEnter(node);
2062 }
2063 this.visit(node.element);
2064 if (this._handlers.onQuantifierLeave) {
2065 this._handlers.onQuantifierLeave(node);
2066 }
2067 }
2068 visitRegExpLiteral(node) {
2069 if (this._handlers.onRegExpLiteralEnter) {
2070 this._handlers.onRegExpLiteralEnter(node);
2071 }
2072 this.visitPattern(node.pattern);
2073 this.visitFlags(node.flags);
2074 if (this._handlers.onRegExpLiteralLeave) {
2075 this._handlers.onRegExpLiteralLeave(node);
2076 }
2077 }
2078}
2079
2080function parseRegExpLiteral(source, options) {
2081 return new RegExpParser(options).parseLiteral(String(source));
2082}
2083function validateRegExpLiteral(source, options) {
2084 return new RegExpValidator(options).validateLiteral(source);
2085}
2086function visitRegExpAST(node, handlers) {
2087 new RegExpVisitor(handlers).visit(node);
2088}
2089
2090exports.AST = ast;
2091exports.RegExpParser = RegExpParser;
2092exports.RegExpValidator = RegExpValidator;
2093exports.parseRegExpLiteral = parseRegExpLiteral;
2094exports.validateRegExpLiteral = validateRegExpLiteral;
2095exports.visitRegExpAST = visitRegExpAST;
2096//# sourceMappingURL=index.js.map