1 /*! @author Toru Nagashima <https://github.com/mysticatea> */
4 var ast = /*#__PURE__*/Object.freeze({
8 let largeIdStartRanges = undefined;
9 let largeIdContinueRanges = undefined;
10 function isIdStart(cp) {
19 return isLargeIdStart(cp);
21 function isIdContinue(cp) {
36 return isLargeIdStart(cp) || isLargeIdContinue(cp);
38 function isLargeIdStart(cp) {
39 return isInRange(cp, largeIdStartRanges || (largeIdStartRanges = initLargeIdStartRanges()));
41 function isLargeIdContinue(cp) {
42 return isInRange(cp, largeIdContinueRanges ||
43 (largeIdContinueRanges = initLargeIdContinueRanges()));
45 function initLargeIdStartRanges() {
46 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");
48 function initLargeIdContinueRanges() {
49 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");
51 function isInRange(cp, ranges) {
52 let l = 0, r = (ranges.length / 2) | 0, i = 0, min = 0, max = 0;
54 i = ((l + r) / 2) | 0;
56 max = ranges[2 * i + 1];
69 function restoreRanges(data) {
71 return data.split(" ").map(s => (last += parseInt(s, 36) | 0));
75 constructor(raw2018, raw2019, raw2020, raw2021) {
76 this._raw2018 = raw2018;
77 this._raw2019 = raw2019;
78 this._raw2020 = raw2020;
79 this._raw2021 = raw2021;
82 return (this._set2018 || (this._set2018 = new Set(this._raw2018.split(" "))));
85 return (this._set2019 || (this._set2019 = new Set(this._raw2019.split(" "))));
88 return (this._set2020 || (this._set2020 = new Set(this._raw2020.split(" "))));
91 return (this._set2021 || (this._set2021 = new Set(this._raw2021.split(" "))));
94 const gcNameSet = new Set(["General_Category", "gc"]);
95 const scNameSet = new Set(["Script", "Script_Extensions", "sc", "scx"]);
96 const 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", "", "", "");
97 const 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");
98 const 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");
99 function isValidUnicodeProperty(version, name, value) {
100 if (gcNameSet.has(name)) {
101 return version >= 2018 && gcValueSets.es2018.has(value);
103 if (scNameSet.has(name)) {
104 return ((version >= 2018 && scValueSets.es2018.has(value)) ||
105 (version >= 2019 && scValueSets.es2019.has(value)) ||
106 (version >= 2020 && scValueSets.es2020.has(value)) ||
107 (version >= 2021 && scValueSets.es2021.has(value)));
111 function isValidLoneUnicodeProperty(version, value) {
112 return ((version >= 2018 && binPropertySets.es2018.has(value)) ||
113 (version >= 2019 && binPropertySets.es2019.has(value)) ||
114 (version >= 2021 && binPropertySets.es2021.has(value)));
117 const Backspace = 0x08;
118 const CharacterTabulation = 0x09;
119 const LineFeed = 0x0a;
120 const LineTabulation = 0x0b;
121 const FormFeed = 0x0c;
122 const CarriageReturn = 0x0d;
123 const ExclamationMark = 0x21;
124 const DollarSign = 0x24;
125 const LeftParenthesis = 0x28;
126 const RightParenthesis = 0x29;
127 const Asterisk = 0x2a;
128 const PlusSign = 0x2b;
130 const HyphenMinus = 0x2d;
131 const FullStop = 0x2e;
132 const Solidus = 0x2f;
133 const DigitZero = 0x30;
134 const DigitOne = 0x31;
135 const DigitSeven = 0x37;
136 const DigitNine = 0x39;
138 const LessThanSign = 0x3c;
139 const EqualsSign = 0x3d;
140 const GreaterThanSign = 0x3e;
141 const QuestionMark = 0x3f;
142 const LatinCapitalLetterA = 0x41;
143 const LatinCapitalLetterB = 0x42;
144 const LatinCapitalLetterD = 0x44;
145 const LatinCapitalLetterF = 0x46;
146 const LatinCapitalLetterP = 0x50;
147 const LatinCapitalLetterS = 0x53;
148 const LatinCapitalLetterW = 0x57;
149 const LatinCapitalLetterZ = 0x5a;
150 const LowLine = 0x5f;
151 const LatinSmallLetterA = 0x61;
152 const LatinSmallLetterB = 0x62;
153 const LatinSmallLetterC = 0x63;
154 const LatinSmallLetterD = 0x64;
155 const LatinSmallLetterF = 0x66;
156 const LatinSmallLetterG = 0x67;
157 const LatinSmallLetterI = 0x69;
158 const LatinSmallLetterK = 0x6b;
159 const LatinSmallLetterM = 0x6d;
160 const LatinSmallLetterN = 0x6e;
161 const LatinSmallLetterP = 0x70;
162 const LatinSmallLetterR = 0x72;
163 const LatinSmallLetterS = 0x73;
164 const LatinSmallLetterT = 0x74;
165 const LatinSmallLetterU = 0x75;
166 const LatinSmallLetterV = 0x76;
167 const LatinSmallLetterW = 0x77;
168 const LatinSmallLetterX = 0x78;
169 const LatinSmallLetterY = 0x79;
170 const LatinSmallLetterZ = 0x7a;
171 const LeftSquareBracket = 0x5b;
172 const ReverseSolidus = 0x5c;
173 const RightSquareBracket = 0x5d;
174 const CircumflexAccent = 0x5e;
175 const LeftCurlyBracket = 0x7b;
176 const VerticalLine = 0x7c;
177 const RightCurlyBracket = 0x7d;
178 const ZeroWidthNonJoiner = 0x200c;
179 const ZeroWidthJoiner = 0x200d;
180 const LineSeparator = 0x2028;
181 const ParagraphSeparator = 0x2029;
182 const MinCodePoint = 0x00;
183 const MaxCodePoint = 0x10ffff;
184 function isLatinLetter(code) {
185 return ((code >= LatinCapitalLetterA && code <= LatinCapitalLetterZ) ||
186 (code >= LatinSmallLetterA && code <= LatinSmallLetterZ));
188 function isDecimalDigit(code) {
189 return code >= DigitZero && code <= DigitNine;
191 function isOctalDigit(code) {
192 return code >= DigitZero && code <= DigitSeven;
194 function isHexDigit(code) {
195 return ((code >= DigitZero && code <= DigitNine) ||
196 (code >= LatinCapitalLetterA && code <= LatinCapitalLetterF) ||
197 (code >= LatinSmallLetterA && code <= LatinSmallLetterF));
199 function isLineTerminator(code) {
200 return (code === LineFeed ||
201 code === CarriageReturn ||
202 code === LineSeparator ||
203 code === ParagraphSeparator);
205 function isValidUnicode(code) {
206 return code >= MinCodePoint && code <= MaxCodePoint;
208 function digitToInt(code) {
209 if (code >= LatinSmallLetterA && code <= LatinSmallLetterF) {
210 return code - LatinSmallLetterA + 10;
212 if (code >= LatinCapitalLetterA && code <= LatinCapitalLetterF) {
213 return code - LatinCapitalLetterA + 10;
215 return code - DigitZero;
217 function isLeadSurrogate(code) {
218 return code >= 0xd800 && code <= 0xdbff;
220 function isTrailSurrogate(code) {
221 return code >= 0xdc00 && code <= 0xdfff;
223 function combineSurrogatePair(lead, trail) {
224 return (lead - 0xd800) * 0x400 + (trail - 0xdc00) + 0x10000;
229 return i < end ? s.charCodeAt(i) : -1;
235 const unicodeImpl = {
237 return i < end ? s.codePointAt(i) : -1;
240 return c > 0xffff ? 2 : 1;
245 this._impl = legacyImpl;
263 get currentCodePoint() {
266 get nextCodePoint() {
269 get nextCodePoint2() {
272 get nextCodePoint3() {
275 reset(source, start, end, uFlag) {
276 this._impl = uFlag ? unicodeImpl : legacyImpl;
282 const impl = this._impl;
284 this._cp1 = impl.at(this._s, this._end, index);
285 this._w1 = impl.width(this._cp1);
286 this._cp2 = impl.at(this._s, this._end, index + this._w1);
287 this._w2 = impl.width(this._cp2);
288 this._cp3 = impl.at(this._s, this._end, index + this._w1 + this._w2);
289 this._w3 = impl.width(this._cp3);
290 this._cp4 = impl.at(this._s, this._end, index + this._w1 + this._w2 + this._w3);
293 if (this._cp1 !== -1) {
294 const impl = this._impl;
296 this._cp1 = this._cp2;
298 this._cp2 = this._cp3;
299 this._w2 = impl.width(this._cp2);
300 this._cp3 = this._cp4;
301 this._w3 = impl.width(this._cp3);
302 this._cp4 = impl.at(this._s, this._end, this._i + this._w1 + this._w2 + this._w3);
306 if (this._cp1 === cp) {
313 if (this._cp1 === cp1 && this._cp2 === cp2) {
320 eat3(cp1, cp2, cp3) {
321 if (this._cp1 === cp1 && this._cp2 === cp2 && this._cp3 === cp3) {
331 class RegExpSyntaxError extends SyntaxError {
332 constructor(source, uFlag, index, message) {
334 if (!source.startsWith("/")) {
335 source = `/${source}/${uFlag ? "u" : ""}`;
337 source = `: ${source}`;
339 super(`Invalid regular expression${source}: ${message}`);
344 function isSyntaxCharacter(cp) {
345 return (cp === CircumflexAccent ||
347 cp === ReverseSolidus ||
351 cp === QuestionMark ||
352 cp === LeftParenthesis ||
353 cp === RightParenthesis ||
354 cp === LeftSquareBracket ||
355 cp === RightSquareBracket ||
356 cp === LeftCurlyBracket ||
357 cp === RightCurlyBracket ||
358 cp === VerticalLine);
360 function isRegExpIdentifierStart(cp) {
361 return isIdStart(cp) || cp === DollarSign || cp === LowLine;
363 function isRegExpIdentifierPart(cp) {
364 return (isIdContinue(cp) ||
367 cp === ZeroWidthNonJoiner ||
368 cp === ZeroWidthJoiner);
370 function isUnicodePropertyNameCharacter(cp) {
371 return isLatinLetter(cp) || cp === LowLine;
373 function isUnicodePropertyValueCharacter(cp) {
374 return isUnicodePropertyNameCharacter(cp) || isDecimalDigit(cp);
376 class RegExpValidator {
377 constructor(options) {
378 this._reader = new Reader();
381 this._lastIntValue = 0;
382 this._lastMinValue = 0;
383 this._lastMaxValue = 0;
384 this._lastStrValue = "";
385 this._lastKeyValue = "";
386 this._lastValValue = "";
387 this._lastAssertionIsQuantifiable = false;
388 this._numCapturingParens = 0;
389 this._groupNames = new Set();
390 this._backreferenceNames = new Set();
391 this._options = options || {};
393 validateLiteral(source, start = 0, end = source.length) {
394 this._uFlag = this._nFlag = false;
395 this.reset(source, start, end);
396 this.onLiteralEnter(start);
397 if (this.eat(Solidus) && this.eatRegExpBody() && this.eat(Solidus)) {
398 const flagStart = this.index;
399 const uFlag = source.includes("u", flagStart);
400 this.validateFlags(source, flagStart, end);
401 this.validatePattern(source, start + 1, flagStart - 1, uFlag);
403 else if (start >= end) {
407 const c = String.fromCodePoint(this.currentCodePoint);
408 this.raise(`Unexpected character '${c}'`);
410 this.onLiteralLeave(start, end);
412 validateFlags(source, start = 0, end = source.length) {
413 const existingFlags = new Set();
415 let ignoreCase = false;
416 let multiline = false;
420 let hasIndices = false;
421 for (let i = start; i < end; ++i) {
422 const flag = source.charCodeAt(i);
423 if (existingFlags.has(flag)) {
424 this.raise(`Duplicated flag '${source[i]}'`);
426 existingFlags.add(flag);
427 if (flag === LatinSmallLetterG) {
430 else if (flag === LatinSmallLetterI) {
433 else if (flag === LatinSmallLetterM) {
436 else if (flag === LatinSmallLetterU && this.ecmaVersion >= 2015) {
439 else if (flag === LatinSmallLetterY && this.ecmaVersion >= 2015) {
442 else if (flag === LatinSmallLetterS && this.ecmaVersion >= 2018) {
445 else if (flag === LatinSmallLetterD && this.ecmaVersion >= 2022) {
449 this.raise(`Invalid flag '${source[i]}'`);
452 this.onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices);
454 validatePattern(source, start = 0, end = source.length, uFlag = false) {
455 this._uFlag = uFlag && this.ecmaVersion >= 2015;
456 this._nFlag = uFlag && this.ecmaVersion >= 2018;
457 this.reset(source, start, end);
458 this.consumePattern();
460 this.ecmaVersion >= 2018 &&
461 this._groupNames.size > 0) {
464 this.consumePattern();
468 return Boolean(this._options.strict || this._uFlag);
471 return this._options.ecmaVersion || 2022;
473 onLiteralEnter(start) {
474 if (this._options.onLiteralEnter) {
475 this._options.onLiteralEnter(start);
478 onLiteralLeave(start, end) {
479 if (this._options.onLiteralLeave) {
480 this._options.onLiteralLeave(start, end);
483 onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices) {
484 if (this._options.onFlags) {
485 this._options.onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices);
488 onPatternEnter(start) {
489 if (this._options.onPatternEnter) {
490 this._options.onPatternEnter(start);
493 onPatternLeave(start, end) {
494 if (this._options.onPatternLeave) {
495 this._options.onPatternLeave(start, end);
498 onDisjunctionEnter(start) {
499 if (this._options.onDisjunctionEnter) {
500 this._options.onDisjunctionEnter(start);
503 onDisjunctionLeave(start, end) {
504 if (this._options.onDisjunctionLeave) {
505 this._options.onDisjunctionLeave(start, end);
508 onAlternativeEnter(start, index) {
509 if (this._options.onAlternativeEnter) {
510 this._options.onAlternativeEnter(start, index);
513 onAlternativeLeave(start, end, index) {
514 if (this._options.onAlternativeLeave) {
515 this._options.onAlternativeLeave(start, end, index);
518 onGroupEnter(start) {
519 if (this._options.onGroupEnter) {
520 this._options.onGroupEnter(start);
523 onGroupLeave(start, end) {
524 if (this._options.onGroupLeave) {
525 this._options.onGroupLeave(start, end);
528 onCapturingGroupEnter(start, name) {
529 if (this._options.onCapturingGroupEnter) {
530 this._options.onCapturingGroupEnter(start, name);
533 onCapturingGroupLeave(start, end, name) {
534 if (this._options.onCapturingGroupLeave) {
535 this._options.onCapturingGroupLeave(start, end, name);
538 onQuantifier(start, end, min, max, greedy) {
539 if (this._options.onQuantifier) {
540 this._options.onQuantifier(start, end, min, max, greedy);
543 onLookaroundAssertionEnter(start, kind, negate) {
544 if (this._options.onLookaroundAssertionEnter) {
545 this._options.onLookaroundAssertionEnter(start, kind, negate);
548 onLookaroundAssertionLeave(start, end, kind, negate) {
549 if (this._options.onLookaroundAssertionLeave) {
550 this._options.onLookaroundAssertionLeave(start, end, kind, negate);
553 onEdgeAssertion(start, end, kind) {
554 if (this._options.onEdgeAssertion) {
555 this._options.onEdgeAssertion(start, end, kind);
558 onWordBoundaryAssertion(start, end, kind, negate) {
559 if (this._options.onWordBoundaryAssertion) {
560 this._options.onWordBoundaryAssertion(start, end, kind, negate);
563 onAnyCharacterSet(start, end, kind) {
564 if (this._options.onAnyCharacterSet) {
565 this._options.onAnyCharacterSet(start, end, kind);
568 onEscapeCharacterSet(start, end, kind, negate) {
569 if (this._options.onEscapeCharacterSet) {
570 this._options.onEscapeCharacterSet(start, end, kind, negate);
573 onUnicodePropertyCharacterSet(start, end, kind, key, value, negate) {
574 if (this._options.onUnicodePropertyCharacterSet) {
575 this._options.onUnicodePropertyCharacterSet(start, end, kind, key, value, negate);
578 onCharacter(start, end, value) {
579 if (this._options.onCharacter) {
580 this._options.onCharacter(start, end, value);
583 onBackreference(start, end, ref) {
584 if (this._options.onBackreference) {
585 this._options.onBackreference(start, end, ref);
588 onCharacterClassEnter(start, negate) {
589 if (this._options.onCharacterClassEnter) {
590 this._options.onCharacterClassEnter(start, negate);
593 onCharacterClassLeave(start, end, negate) {
594 if (this._options.onCharacterClassLeave) {
595 this._options.onCharacterClassLeave(start, end, negate);
598 onCharacterClassRange(start, end, min, max) {
599 if (this._options.onCharacterClassRange) {
600 this._options.onCharacterClassRange(start, end, min, max);
604 return this._reader.source;
607 return this._reader.index;
609 get currentCodePoint() {
610 return this._reader.currentCodePoint;
612 get nextCodePoint() {
613 return this._reader.nextCodePoint;
615 get nextCodePoint2() {
616 return this._reader.nextCodePoint2;
618 get nextCodePoint3() {
619 return this._reader.nextCodePoint3;
621 reset(source, start, end) {
622 this._reader.reset(source, start, end, this._uFlag);
625 this._reader.rewind(index);
628 this._reader.advance();
631 return this._reader.eat(cp);
634 return this._reader.eat2(cp1, cp2);
636 eat3(cp1, cp2, cp3) {
637 return this._reader.eat3(cp1, cp2, cp3);
640 throw new RegExpSyntaxError(this.source, this._uFlag, this.index, message);
643 const start = this.index;
647 const cp = this.currentCodePoint;
648 if (cp === -1 || isLineTerminator(cp)) {
649 const kind = inClass ? "character class" : "regular expression";
650 this.raise(`Unterminated ${kind}`);
655 else if (cp === ReverseSolidus) {
658 else if (cp === LeftSquareBracket) {
661 else if (cp === RightSquareBracket) {
664 else if ((cp === Solidus && !inClass) ||
665 (cp === Asterisk && this.index === start)) {
670 return this.index !== start;
673 const start = this.index;
674 this._numCapturingParens = this.countCapturingParens();
675 this._groupNames.clear();
676 this._backreferenceNames.clear();
677 this.onPatternEnter(start);
678 this.consumeDisjunction();
679 const cp = this.currentCodePoint;
680 if (this.currentCodePoint !== -1) {
681 if (cp === RightParenthesis) {
682 this.raise("Unmatched ')'");
684 if (cp === ReverseSolidus) {
685 this.raise("\\ at end of pattern");
687 if (cp === RightSquareBracket || cp === RightCurlyBracket) {
688 this.raise("Lone quantifier brackets");
690 const c = String.fromCodePoint(cp);
691 this.raise(`Unexpected character '${c}'`);
693 for (const name of this._backreferenceNames) {
694 if (!this._groupNames.has(name)) {
695 this.raise("Invalid named capture referenced");
698 this.onPatternLeave(start, this.index);
700 countCapturingParens() {
701 const start = this.index;
706 while ((cp = this.currentCodePoint) !== -1) {
710 else if (cp === ReverseSolidus) {
713 else if (cp === LeftSquareBracket) {
716 else if (cp === RightSquareBracket) {
719 else if (cp === LeftParenthesis &&
721 (this.nextCodePoint !== QuestionMark ||
722 (this.nextCodePoint2 === LessThanSign &&
723 this.nextCodePoint3 !== EqualsSign &&
724 this.nextCodePoint3 !== ExclamationMark))) {
732 consumeDisjunction() {
733 const start = this.index;
735 this.onDisjunctionEnter(start);
737 this.consumeAlternative(i++);
738 } while (this.eat(VerticalLine));
739 if (this.consumeQuantifier(true)) {
740 this.raise("Nothing to repeat");
742 if (this.eat(LeftCurlyBracket)) {
743 this.raise("Lone quantifier brackets");
745 this.onDisjunctionLeave(start, this.index);
747 consumeAlternative(i) {
748 const start = this.index;
749 this.onAlternativeEnter(start, i);
750 while (this.currentCodePoint !== -1 && this.consumeTerm()) {
752 this.onAlternativeLeave(start, this.index, i);
755 if (this._uFlag || this.strict) {
756 return (this.consumeAssertion() ||
757 (this.consumeAtom() && this.consumeOptionalQuantifier()));
759 return ((this.consumeAssertion() &&
760 (!this._lastAssertionIsQuantifiable ||
761 this.consumeOptionalQuantifier())) ||
762 (this.consumeExtendedAtom() && this.consumeOptionalQuantifier()));
764 consumeOptionalQuantifier() {
765 this.consumeQuantifier();
769 const start = this.index;
770 this._lastAssertionIsQuantifiable = false;
771 if (this.eat(CircumflexAccent)) {
772 this.onEdgeAssertion(start, this.index, "start");
775 if (this.eat(DollarSign)) {
776 this.onEdgeAssertion(start, this.index, "end");
779 if (this.eat2(ReverseSolidus, LatinCapitalLetterB)) {
780 this.onWordBoundaryAssertion(start, this.index, "word", true);
783 if (this.eat2(ReverseSolidus, LatinSmallLetterB)) {
784 this.onWordBoundaryAssertion(start, this.index, "word", false);
787 if (this.eat2(LeftParenthesis, QuestionMark)) {
788 const lookbehind = this.ecmaVersion >= 2018 && this.eat(LessThanSign);
790 if (this.eat(EqualsSign) || (negate = this.eat(ExclamationMark))) {
791 const kind = lookbehind ? "lookbehind" : "lookahead";
792 this.onLookaroundAssertionEnter(start, kind, negate);
793 this.consumeDisjunction();
794 if (!this.eat(RightParenthesis)) {
795 this.raise("Unterminated group");
797 this._lastAssertionIsQuantifiable = !lookbehind && !this.strict;
798 this.onLookaroundAssertionLeave(start, this.index, kind, negate);
805 consumeQuantifier(noConsume = false) {
806 const start = this.index;
810 if (this.eat(Asterisk)) {
812 max = Number.POSITIVE_INFINITY;
814 else if (this.eat(PlusSign)) {
816 max = Number.POSITIVE_INFINITY;
818 else if (this.eat(QuestionMark)) {
822 else if (this.eatBracedQuantifier(noConsume)) {
823 min = this._lastMinValue;
824 max = this._lastMaxValue;
829 greedy = !this.eat(QuestionMark);
831 this.onQuantifier(start, this.index, min, max, greedy);
835 eatBracedQuantifier(noError) {
836 const start = this.index;
837 if (this.eat(LeftCurlyBracket)) {
838 this._lastMinValue = 0;
839 this._lastMaxValue = Number.POSITIVE_INFINITY;
840 if (this.eatDecimalDigits()) {
841 this._lastMinValue = this._lastMaxValue = this._lastIntValue;
842 if (this.eat(Comma)) {
843 this._lastMaxValue = this.eatDecimalDigits()
845 : Number.POSITIVE_INFINITY;
847 if (this.eat(RightCurlyBracket)) {
848 if (!noError && this._lastMaxValue < this._lastMinValue) {
849 this.raise("numbers out of order in {} quantifier");
854 if (!noError && (this._uFlag || this.strict)) {
855 this.raise("Incomplete quantifier");
862 return (this.consumePatternCharacter() ||
864 this.consumeReverseSolidusAtomEscape() ||
865 this.consumeCharacterClass() ||
866 this.consumeUncapturingGroup() ||
867 this.consumeCapturingGroup());
870 if (this.eat(FullStop)) {
871 this.onAnyCharacterSet(this.index - 1, this.index, "any");
876 consumeReverseSolidusAtomEscape() {
877 const start = this.index;
878 if (this.eat(ReverseSolidus)) {
879 if (this.consumeAtomEscape()) {
886 consumeUncapturingGroup() {
887 const start = this.index;
888 if (this.eat3(LeftParenthesis, QuestionMark, Colon)) {
889 this.onGroupEnter(start);
890 this.consumeDisjunction();
891 if (!this.eat(RightParenthesis)) {
892 this.raise("Unterminated group");
894 this.onGroupLeave(start, this.index);
899 consumeCapturingGroup() {
900 const start = this.index;
901 if (this.eat(LeftParenthesis)) {
903 if (this.ecmaVersion >= 2018) {
904 if (this.consumeGroupSpecifier()) {
905 name = this._lastStrValue;
908 else if (this.currentCodePoint === QuestionMark) {
909 this.raise("Invalid group");
911 this.onCapturingGroupEnter(start, name);
912 this.consumeDisjunction();
913 if (!this.eat(RightParenthesis)) {
914 this.raise("Unterminated group");
916 this.onCapturingGroupLeave(start, this.index, name);
921 consumeExtendedAtom() {
922 return (this.consumeDot() ||
923 this.consumeReverseSolidusAtomEscape() ||
924 this.consumeReverseSolidusFollowedByC() ||
925 this.consumeCharacterClass() ||
926 this.consumeUncapturingGroup() ||
927 this.consumeCapturingGroup() ||
928 this.consumeInvalidBracedQuantifier() ||
929 this.consumeExtendedPatternCharacter());
931 consumeReverseSolidusFollowedByC() {
932 const start = this.index;
933 if (this.currentCodePoint === ReverseSolidus &&
934 this.nextCodePoint === LatinSmallLetterC) {
935 this._lastIntValue = this.currentCodePoint;
937 this.onCharacter(start, this.index, ReverseSolidus);
942 consumeInvalidBracedQuantifier() {
943 if (this.eatBracedQuantifier(true)) {
944 this.raise("Nothing to repeat");
948 consumePatternCharacter() {
949 const start = this.index;
950 const cp = this.currentCodePoint;
951 if (cp !== -1 && !isSyntaxCharacter(cp)) {
953 this.onCharacter(start, this.index, cp);
958 consumeExtendedPatternCharacter() {
959 const start = this.index;
960 const cp = this.currentCodePoint;
962 cp !== CircumflexAccent &&
964 cp !== ReverseSolidus &&
968 cp !== QuestionMark &&
969 cp !== LeftParenthesis &&
970 cp !== RightParenthesis &&
971 cp !== LeftSquareBracket &&
972 cp !== VerticalLine) {
974 this.onCharacter(start, this.index, cp);
979 consumeGroupSpecifier() {
980 if (this.eat(QuestionMark)) {
981 if (this.eatGroupName()) {
982 if (!this._groupNames.has(this._lastStrValue)) {
983 this._groupNames.add(this._lastStrValue);
986 this.raise("Duplicate capture group name");
988 this.raise("Invalid group");
992 consumeAtomEscape() {
993 if (this.consumeBackreference() ||
994 this.consumeCharacterClassEscape() ||
995 this.consumeCharacterEscape() ||
996 (this._nFlag && this.consumeKGroupName())) {
999 if (this.strict || this._uFlag) {
1000 this.raise("Invalid escape");
1004 consumeBackreference() {
1005 const start = this.index;
1006 if (this.eatDecimalEscape()) {
1007 const n = this._lastIntValue;
1008 if (n <= this._numCapturingParens) {
1009 this.onBackreference(start - 1, this.index, n);
1012 if (this.strict || this._uFlag) {
1013 this.raise("Invalid escape");
1019 consumeCharacterClassEscape() {
1020 const start = this.index;
1021 if (this.eat(LatinSmallLetterD)) {
1022 this._lastIntValue = -1;
1023 this.onEscapeCharacterSet(start - 1, this.index, "digit", false);
1026 if (this.eat(LatinCapitalLetterD)) {
1027 this._lastIntValue = -1;
1028 this.onEscapeCharacterSet(start - 1, this.index, "digit", true);
1031 if (this.eat(LatinSmallLetterS)) {
1032 this._lastIntValue = -1;
1033 this.onEscapeCharacterSet(start - 1, this.index, "space", false);
1036 if (this.eat(LatinCapitalLetterS)) {
1037 this._lastIntValue = -1;
1038 this.onEscapeCharacterSet(start - 1, this.index, "space", true);
1041 if (this.eat(LatinSmallLetterW)) {
1042 this._lastIntValue = -1;
1043 this.onEscapeCharacterSet(start - 1, this.index, "word", false);
1046 if (this.eat(LatinCapitalLetterW)) {
1047 this._lastIntValue = -1;
1048 this.onEscapeCharacterSet(start - 1, this.index, "word", true);
1053 this.ecmaVersion >= 2018 &&
1054 (this.eat(LatinSmallLetterP) ||
1055 (negate = this.eat(LatinCapitalLetterP)))) {
1056 this._lastIntValue = -1;
1057 if (this.eat(LeftCurlyBracket) &&
1058 this.eatUnicodePropertyValueExpression() &&
1059 this.eat(RightCurlyBracket)) {
1060 this.onUnicodePropertyCharacterSet(start - 1, this.index, "property", this._lastKeyValue, this._lastValValue || null, negate);
1063 this.raise("Invalid property name");
1067 consumeCharacterEscape() {
1068 const start = this.index;
1069 if (this.eatControlEscape() ||
1070 this.eatCControlLetter() ||
1072 this.eatHexEscapeSequence() ||
1073 this.eatRegExpUnicodeEscapeSequence() ||
1076 this.eatLegacyOctalEscapeSequence()) ||
1077 this.eatIdentityEscape()) {
1078 this.onCharacter(start - 1, this.index, this._lastIntValue);
1083 consumeKGroupName() {
1084 const start = this.index;
1085 if (this.eat(LatinSmallLetterK)) {
1086 if (this.eatGroupName()) {
1087 const groupName = this._lastStrValue;
1088 this._backreferenceNames.add(groupName);
1089 this.onBackreference(start - 1, this.index, groupName);
1092 this.raise("Invalid named reference");
1096 consumeCharacterClass() {
1097 const start = this.index;
1098 if (this.eat(LeftSquareBracket)) {
1099 const negate = this.eat(CircumflexAccent);
1100 this.onCharacterClassEnter(start, negate);
1101 this.consumeClassRanges();
1102 if (!this.eat(RightSquareBracket)) {
1103 this.raise("Unterminated character class");
1105 this.onCharacterClassLeave(start, this.index, negate);
1110 consumeClassRanges() {
1111 const strict = this.strict || this._uFlag;
1113 const rangeStart = this.index;
1114 if (!this.consumeClassAtom()) {
1117 const min = this._lastIntValue;
1118 if (!this.eat(HyphenMinus)) {
1121 this.onCharacter(this.index - 1, this.index, HyphenMinus);
1122 if (!this.consumeClassAtom()) {
1125 const max = this._lastIntValue;
1126 if (min === -1 || max === -1) {
1128 this.raise("Invalid character class");
1133 this.raise("Range out of order in character class");
1135 this.onCharacterClassRange(rangeStart, this.index, min, max);
1138 consumeClassAtom() {
1139 const start = this.index;
1140 const cp = this.currentCodePoint;
1141 if (cp !== -1 && cp !== ReverseSolidus && cp !== RightSquareBracket) {
1143 this._lastIntValue = cp;
1144 this.onCharacter(start, this.index, this._lastIntValue);
1147 if (this.eat(ReverseSolidus)) {
1148 if (this.consumeClassEscape()) {
1151 if (!this.strict && this.currentCodePoint === LatinSmallLetterC) {
1152 this._lastIntValue = ReverseSolidus;
1153 this.onCharacter(start, this.index, this._lastIntValue);
1156 if (this.strict || this._uFlag) {
1157 this.raise("Invalid escape");
1163 consumeClassEscape() {
1164 const start = this.index;
1165 if (this.eat(LatinSmallLetterB)) {
1166 this._lastIntValue = Backspace;
1167 this.onCharacter(start - 1, this.index, this._lastIntValue);
1170 if (this._uFlag && this.eat(HyphenMinus)) {
1171 this._lastIntValue = HyphenMinus;
1172 this.onCharacter(start - 1, this.index, this._lastIntValue);
1178 this.currentCodePoint === LatinSmallLetterC &&
1179 (isDecimalDigit((cp = this.nextCodePoint)) || cp === LowLine)) {
1182 this._lastIntValue = cp % 0x20;
1183 this.onCharacter(start - 1, this.index, this._lastIntValue);
1186 return (this.consumeCharacterClassEscape() || this.consumeCharacterEscape());
1189 if (this.eat(LessThanSign)) {
1190 if (this.eatRegExpIdentifierName() && this.eat(GreaterThanSign)) {
1193 this.raise("Invalid capture group name");
1197 eatRegExpIdentifierName() {
1198 if (this.eatRegExpIdentifierStart()) {
1199 this._lastStrValue = String.fromCodePoint(this._lastIntValue);
1200 while (this.eatRegExpIdentifierPart()) {
1201 this._lastStrValue += String.fromCodePoint(this._lastIntValue);
1207 eatRegExpIdentifierStart() {
1208 const start = this.index;
1209 const forceUFlag = !this._uFlag && this.ecmaVersion >= 2020;
1210 let cp = this.currentCodePoint;
1212 if (cp === ReverseSolidus &&
1213 this.eatRegExpUnicodeEscapeSequence(forceUFlag)) {
1214 cp = this._lastIntValue;
1216 else if (forceUFlag &&
1217 isLeadSurrogate(cp) &&
1218 isTrailSurrogate(this.currentCodePoint)) {
1219 cp = combineSurrogatePair(cp, this.currentCodePoint);
1222 if (isRegExpIdentifierStart(cp)) {
1223 this._lastIntValue = cp;
1226 if (this.index !== start) {
1231 eatRegExpIdentifierPart() {
1232 const start = this.index;
1233 const forceUFlag = !this._uFlag && this.ecmaVersion >= 2020;
1234 let cp = this.currentCodePoint;
1236 if (cp === ReverseSolidus &&
1237 this.eatRegExpUnicodeEscapeSequence(forceUFlag)) {
1238 cp = this._lastIntValue;
1240 else if (forceUFlag &&
1241 isLeadSurrogate(cp) &&
1242 isTrailSurrogate(this.currentCodePoint)) {
1243 cp = combineSurrogatePair(cp, this.currentCodePoint);
1246 if (isRegExpIdentifierPart(cp)) {
1247 this._lastIntValue = cp;
1250 if (this.index !== start) {
1255 eatCControlLetter() {
1256 const start = this.index;
1257 if (this.eat(LatinSmallLetterC)) {
1258 if (this.eatControlLetter()) {
1266 if (this.currentCodePoint === DigitZero &&
1267 !isDecimalDigit(this.nextCodePoint)) {
1268 this._lastIntValue = 0;
1274 eatControlEscape() {
1275 if (this.eat(LatinSmallLetterF)) {
1276 this._lastIntValue = FormFeed;
1279 if (this.eat(LatinSmallLetterN)) {
1280 this._lastIntValue = LineFeed;
1283 if (this.eat(LatinSmallLetterR)) {
1284 this._lastIntValue = CarriageReturn;
1287 if (this.eat(LatinSmallLetterT)) {
1288 this._lastIntValue = CharacterTabulation;
1291 if (this.eat(LatinSmallLetterV)) {
1292 this._lastIntValue = LineTabulation;
1297 eatControlLetter() {
1298 const cp = this.currentCodePoint;
1299 if (isLatinLetter(cp)) {
1301 this._lastIntValue = cp % 0x20;
1306 eatRegExpUnicodeEscapeSequence(forceUFlag = false) {
1307 const start = this.index;
1308 const uFlag = forceUFlag || this._uFlag;
1309 if (this.eat(LatinSmallLetterU)) {
1310 if ((uFlag && this.eatRegExpUnicodeSurrogatePairEscape()) ||
1311 this.eatFixedHexDigits(4) ||
1312 (uFlag && this.eatRegExpUnicodeCodePointEscape())) {
1315 if (this.strict || uFlag) {
1316 this.raise("Invalid unicode escape");
1322 eatRegExpUnicodeSurrogatePairEscape() {
1323 const start = this.index;
1324 if (this.eatFixedHexDigits(4)) {
1325 const lead = this._lastIntValue;
1326 if (isLeadSurrogate(lead) &&
1327 this.eat(ReverseSolidus) &&
1328 this.eat(LatinSmallLetterU) &&
1329 this.eatFixedHexDigits(4)) {
1330 const trail = this._lastIntValue;
1331 if (isTrailSurrogate(trail)) {
1332 this._lastIntValue = combineSurrogatePair(lead, trail);
1340 eatRegExpUnicodeCodePointEscape() {
1341 const start = this.index;
1342 if (this.eat(LeftCurlyBracket) &&
1343 this.eatHexDigits() &&
1344 this.eat(RightCurlyBracket) &&
1345 isValidUnicode(this._lastIntValue)) {
1351 eatIdentityEscape() {
1352 const cp = this.currentCodePoint;
1353 if (this.isValidIdentityEscape(cp)) {
1354 this._lastIntValue = cp;
1360 isValidIdentityEscape(cp) {
1365 return isSyntaxCharacter(cp) || cp === Solidus;
1368 return !isIdContinue(cp);
1371 return !(cp === LatinSmallLetterC || cp === LatinSmallLetterK);
1373 return cp !== LatinSmallLetterC;
1375 eatDecimalEscape() {
1376 this._lastIntValue = 0;
1377 let cp = this.currentCodePoint;
1378 if (cp >= DigitOne && cp <= DigitNine) {
1380 this._lastIntValue = 10 * this._lastIntValue + (cp - DigitZero);
1382 } while ((cp = this.currentCodePoint) >= DigitZero &&
1388 eatUnicodePropertyValueExpression() {
1389 const start = this.index;
1390 if (this.eatUnicodePropertyName() && this.eat(EqualsSign)) {
1391 this._lastKeyValue = this._lastStrValue;
1392 if (this.eatUnicodePropertyValue()) {
1393 this._lastValValue = this._lastStrValue;
1394 if (isValidUnicodeProperty(this.ecmaVersion, this._lastKeyValue, this._lastValValue)) {
1397 this.raise("Invalid property name");
1401 if (this.eatLoneUnicodePropertyNameOrValue()) {
1402 const nameOrValue = this._lastStrValue;
1403 if (isValidUnicodeProperty(this.ecmaVersion, "General_Category", nameOrValue)) {
1404 this._lastKeyValue = "General_Category";
1405 this._lastValValue = nameOrValue;
1408 if (isValidLoneUnicodeProperty(this.ecmaVersion, nameOrValue)) {
1409 this._lastKeyValue = nameOrValue;
1410 this._lastValValue = "";
1413 this.raise("Invalid property name");
1417 eatUnicodePropertyName() {
1418 this._lastStrValue = "";
1419 while (isUnicodePropertyNameCharacter(this.currentCodePoint)) {
1420 this._lastStrValue += String.fromCodePoint(this.currentCodePoint);
1423 return this._lastStrValue !== "";
1425 eatUnicodePropertyValue() {
1426 this._lastStrValue = "";
1427 while (isUnicodePropertyValueCharacter(this.currentCodePoint)) {
1428 this._lastStrValue += String.fromCodePoint(this.currentCodePoint);
1431 return this._lastStrValue !== "";
1433 eatLoneUnicodePropertyNameOrValue() {
1434 return this.eatUnicodePropertyValue();
1436 eatHexEscapeSequence() {
1437 const start = this.index;
1438 if (this.eat(LatinSmallLetterX)) {
1439 if (this.eatFixedHexDigits(2)) {
1442 if (this._uFlag || this.strict) {
1443 this.raise("Invalid escape");
1449 eatDecimalDigits() {
1450 const start = this.index;
1451 this._lastIntValue = 0;
1452 while (isDecimalDigit(this.currentCodePoint)) {
1453 this._lastIntValue =
1454 10 * this._lastIntValue + digitToInt(this.currentCodePoint);
1457 return this.index !== start;
1460 const start = this.index;
1461 this._lastIntValue = 0;
1462 while (isHexDigit(this.currentCodePoint)) {
1463 this._lastIntValue =
1464 16 * this._lastIntValue + digitToInt(this.currentCodePoint);
1467 return this.index !== start;
1469 eatLegacyOctalEscapeSequence() {
1470 if (this.eatOctalDigit()) {
1471 const n1 = this._lastIntValue;
1472 if (this.eatOctalDigit()) {
1473 const n2 = this._lastIntValue;
1474 if (n1 <= 3 && this.eatOctalDigit()) {
1475 this._lastIntValue = n1 * 64 + n2 * 8 + this._lastIntValue;
1478 this._lastIntValue = n1 * 8 + n2;
1482 this._lastIntValue = n1;
1489 const cp = this.currentCodePoint;
1490 if (isOctalDigit(cp)) {
1492 this._lastIntValue = cp - DigitZero;
1495 this._lastIntValue = 0;
1498 eatFixedHexDigits(length) {
1499 const start = this.index;
1500 this._lastIntValue = 0;
1501 for (let i = 0; i < length; ++i) {
1502 const cp = this.currentCodePoint;
1503 if (!isHexDigit(cp)) {
1507 this._lastIntValue = 16 * this._lastIntValue + digitToInt(cp);
1514 const DummyPattern = {};
1515 const DummyFlags = {};
1516 const DummyCapturingGroup = {};
1517 class RegExpParserState {
1518 constructor(options) {
1519 this._node = DummyPattern;
1520 this._flags = DummyFlags;
1521 this._backreferences = [];
1522 this._capturingGroups = [];
1524 this.strict = Boolean(options && options.strict);
1525 this.ecmaVersion = (options && options.ecmaVersion) || 2022;
1528 if (this._node.type !== "Pattern") {
1529 throw new Error("UnknownError");
1534 if (this._flags.type !== "Flags") {
1535 throw new Error("UnknownError");
1539 onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices) {
1545 raw: this.source.slice(start, end),
1555 onPatternEnter(start) {
1564 this._backreferences.length = 0;
1565 this._capturingGroups.length = 0;
1567 onPatternLeave(start, end) {
1568 this._node.end = end;
1569 this._node.raw = this.source.slice(start, end);
1570 for (const reference of this._backreferences) {
1571 const ref = reference.ref;
1572 const group = typeof ref === "number"
1573 ? this._capturingGroups[ref - 1]
1574 : this._capturingGroups.find(g => g.name === ref);
1575 reference.resolved = group;
1576 group.references.push(reference);
1579 onAlternativeEnter(start) {
1580 const parent = this._node;
1581 if (parent.type !== "Assertion" &&
1582 parent.type !== "CapturingGroup" &&
1583 parent.type !== "Group" &&
1584 parent.type !== "Pattern") {
1585 throw new Error("UnknownError");
1588 type: "Alternative",
1595 parent.alternatives.push(this._node);
1597 onAlternativeLeave(start, end) {
1598 const node = this._node;
1599 if (node.type !== "Alternative") {
1600 throw new Error("UnknownError");
1603 node.raw = this.source.slice(start, end);
1604 this._node = node.parent;
1606 onGroupEnter(start) {
1607 const parent = this._node;
1608 if (parent.type !== "Alternative") {
1609 throw new Error("UnknownError");
1619 parent.elements.push(this._node);
1621 onGroupLeave(start, end) {
1622 const node = this._node;
1623 if (node.type !== "Group" || node.parent.type !== "Alternative") {
1624 throw new Error("UnknownError");
1627 node.raw = this.source.slice(start, end);
1628 this._node = node.parent;
1630 onCapturingGroupEnter(start, name) {
1631 const parent = this._node;
1632 if (parent.type !== "Alternative") {
1633 throw new Error("UnknownError");
1636 type: "CapturingGroup",
1645 parent.elements.push(this._node);
1646 this._capturingGroups.push(this._node);
1648 onCapturingGroupLeave(start, end) {
1649 const node = this._node;
1650 if (node.type !== "CapturingGroup" ||
1651 node.parent.type !== "Alternative") {
1652 throw new Error("UnknownError");
1655 node.raw = this.source.slice(start, end);
1656 this._node = node.parent;
1658 onQuantifier(start, end, min, max, greedy) {
1659 const parent = this._node;
1660 if (parent.type !== "Alternative") {
1661 throw new Error("UnknownError");
1663 const element = parent.elements.pop();
1664 if (element == null ||
1665 element.type === "Quantifier" ||
1666 (element.type === "Assertion" && element.kind !== "lookahead")) {
1667 throw new Error("UnknownError");
1672 start: element.start,
1674 raw: this.source.slice(element.start, end),
1680 parent.elements.push(node);
1681 element.parent = node;
1683 onLookaroundAssertionEnter(start, kind, negate) {
1684 const parent = this._node;
1685 if (parent.type !== "Alternative") {
1686 throw new Error("UnknownError");
1688 const node = (this._node = {
1698 parent.elements.push(node);
1700 onLookaroundAssertionLeave(start, end) {
1701 const node = this._node;
1702 if (node.type !== "Assertion" || node.parent.type !== "Alternative") {
1703 throw new Error("UnknownError");
1706 node.raw = this.source.slice(start, end);
1707 this._node = node.parent;
1709 onEdgeAssertion(start, end, kind) {
1710 const parent = this._node;
1711 if (parent.type !== "Alternative") {
1712 throw new Error("UnknownError");
1714 parent.elements.push({
1719 raw: this.source.slice(start, end),
1723 onWordBoundaryAssertion(start, end, kind, negate) {
1724 const parent = this._node;
1725 if (parent.type !== "Alternative") {
1726 throw new Error("UnknownError");
1728 parent.elements.push({
1733 raw: this.source.slice(start, end),
1738 onAnyCharacterSet(start, end, kind) {
1739 const parent = this._node;
1740 if (parent.type !== "Alternative") {
1741 throw new Error("UnknownError");
1743 parent.elements.push({
1744 type: "CharacterSet",
1748 raw: this.source.slice(start, end),
1752 onEscapeCharacterSet(start, end, kind, negate) {
1753 const parent = this._node;
1754 if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
1755 throw new Error("UnknownError");
1757 parent.elements.push({
1758 type: "CharacterSet",
1762 raw: this.source.slice(start, end),
1767 onUnicodePropertyCharacterSet(start, end, kind, key, value, negate) {
1768 const parent = this._node;
1769 if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
1770 throw new Error("UnknownError");
1772 parent.elements.push({
1773 type: "CharacterSet",
1777 raw: this.source.slice(start, end),
1784 onCharacter(start, end, value) {
1785 const parent = this._node;
1786 if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
1787 throw new Error("UnknownError");
1789 parent.elements.push({
1794 raw: this.source.slice(start, end),
1798 onBackreference(start, end, ref) {
1799 const parent = this._node;
1800 if (parent.type !== "Alternative") {
1801 throw new Error("UnknownError");
1804 type: "Backreference",
1808 raw: this.source.slice(start, end),
1810 resolved: DummyCapturingGroup,
1812 parent.elements.push(node);
1813 this._backreferences.push(node);
1815 onCharacterClassEnter(start, negate) {
1816 const parent = this._node;
1817 if (parent.type !== "Alternative") {
1818 throw new Error("UnknownError");
1821 type: "CharacterClass",
1829 parent.elements.push(this._node);
1831 onCharacterClassLeave(start, end) {
1832 const node = this._node;
1833 if (node.type !== "CharacterClass" ||
1834 node.parent.type !== "Alternative") {
1835 throw new Error("UnknownError");
1838 node.raw = this.source.slice(start, end);
1839 this._node = node.parent;
1841 onCharacterClassRange(start, end) {
1842 const parent = this._node;
1843 if (parent.type !== "CharacterClass") {
1844 throw new Error("UnknownError");
1846 const elements = parent.elements;
1847 const max = elements.pop();
1848 const hyphen = elements.pop();
1849 const min = elements.pop();
1853 min.type !== "Character" ||
1854 max.type !== "Character" ||
1855 hyphen.type !== "Character" ||
1856 hyphen.value !== HyphenMinus) {
1857 throw new Error("UnknownError");
1860 type: "CharacterClassRange",
1864 raw: this.source.slice(start, end),
1870 elements.push(node);
1873 class RegExpParser {
1874 constructor(options) {
1875 this._state = new RegExpParserState(options);
1876 this._validator = new RegExpValidator(this._state);
1878 parseLiteral(source, start = 0, end = source.length) {
1879 this._state.source = source;
1880 this._validator.validateLiteral(source, start, end);
1881 const pattern = this._state.pattern;
1882 const flags = this._state.flags;
1884 type: "RegExpLiteral",
1892 pattern.parent = literal;
1893 flags.parent = literal;
1896 parseFlags(source, start = 0, end = source.length) {
1897 this._state.source = source;
1898 this._validator.validateFlags(source, start, end);
1899 return this._state.flags;
1901 parsePattern(source, start = 0, end = source.length, uFlag = false) {
1902 this._state.source = source;
1903 this._validator.validatePattern(source, start, end, uFlag);
1904 return this._state.pattern;
1908 class RegExpVisitor {
1909 constructor(handlers) {
1910 this._handlers = handlers;
1913 switch (node.type) {
1915 this.visitAlternative(node);
1918 this.visitAssertion(node);
1920 case "Backreference":
1921 this.visitBackreference(node);
1923 case "CapturingGroup":
1924 this.visitCapturingGroup(node);
1927 this.visitCharacter(node);
1929 case "CharacterClass":
1930 this.visitCharacterClass(node);
1932 case "CharacterClassRange":
1933 this.visitCharacterClassRange(node);
1935 case "CharacterSet":
1936 this.visitCharacterSet(node);
1939 this.visitFlags(node);
1942 this.visitGroup(node);
1945 this.visitPattern(node);
1948 this.visitQuantifier(node);
1950 case "RegExpLiteral":
1951 this.visitRegExpLiteral(node);
1954 throw new Error(`Unknown type: ${node.type}`);
1957 visitAlternative(node) {
1958 if (this._handlers.onAlternativeEnter) {
1959 this._handlers.onAlternativeEnter(node);
1961 node.elements.forEach(this.visit, this);
1962 if (this._handlers.onAlternativeLeave) {
1963 this._handlers.onAlternativeLeave(node);
1966 visitAssertion(node) {
1967 if (this._handlers.onAssertionEnter) {
1968 this._handlers.onAssertionEnter(node);
1970 if (node.kind === "lookahead" || node.kind === "lookbehind") {
1971 node.alternatives.forEach(this.visit, this);
1973 if (this._handlers.onAssertionLeave) {
1974 this._handlers.onAssertionLeave(node);
1977 visitBackreference(node) {
1978 if (this._handlers.onBackreferenceEnter) {
1979 this._handlers.onBackreferenceEnter(node);
1981 if (this._handlers.onBackreferenceLeave) {
1982 this._handlers.onBackreferenceLeave(node);
1985 visitCapturingGroup(node) {
1986 if (this._handlers.onCapturingGroupEnter) {
1987 this._handlers.onCapturingGroupEnter(node);
1989 node.alternatives.forEach(this.visit, this);
1990 if (this._handlers.onCapturingGroupLeave) {
1991 this._handlers.onCapturingGroupLeave(node);
1994 visitCharacter(node) {
1995 if (this._handlers.onCharacterEnter) {
1996 this._handlers.onCharacterEnter(node);
1998 if (this._handlers.onCharacterLeave) {
1999 this._handlers.onCharacterLeave(node);
2002 visitCharacterClass(node) {
2003 if (this._handlers.onCharacterClassEnter) {
2004 this._handlers.onCharacterClassEnter(node);
2006 node.elements.forEach(this.visit, this);
2007 if (this._handlers.onCharacterClassLeave) {
2008 this._handlers.onCharacterClassLeave(node);
2011 visitCharacterClassRange(node) {
2012 if (this._handlers.onCharacterClassRangeEnter) {
2013 this._handlers.onCharacterClassRangeEnter(node);
2015 this.visitCharacter(node.min);
2016 this.visitCharacter(node.max);
2017 if (this._handlers.onCharacterClassRangeLeave) {
2018 this._handlers.onCharacterClassRangeLeave(node);
2021 visitCharacterSet(node) {
2022 if (this._handlers.onCharacterSetEnter) {
2023 this._handlers.onCharacterSetEnter(node);
2025 if (this._handlers.onCharacterSetLeave) {
2026 this._handlers.onCharacterSetLeave(node);
2030 if (this._handlers.onFlagsEnter) {
2031 this._handlers.onFlagsEnter(node);
2033 if (this._handlers.onFlagsLeave) {
2034 this._handlers.onFlagsLeave(node);
2038 if (this._handlers.onGroupEnter) {
2039 this._handlers.onGroupEnter(node);
2041 node.alternatives.forEach(this.visit, this);
2042 if (this._handlers.onGroupLeave) {
2043 this._handlers.onGroupLeave(node);
2046 visitPattern(node) {
2047 if (this._handlers.onPatternEnter) {
2048 this._handlers.onPatternEnter(node);
2050 node.alternatives.forEach(this.visit, this);
2051 if (this._handlers.onPatternLeave) {
2052 this._handlers.onPatternLeave(node);
2055 visitQuantifier(node) {
2056 if (this._handlers.onQuantifierEnter) {
2057 this._handlers.onQuantifierEnter(node);
2059 this.visit(node.element);
2060 if (this._handlers.onQuantifierLeave) {
2061 this._handlers.onQuantifierLeave(node);
2064 visitRegExpLiteral(node) {
2065 if (this._handlers.onRegExpLiteralEnter) {
2066 this._handlers.onRegExpLiteralEnter(node);
2068 this.visitPattern(node.pattern);
2069 this.visitFlags(node.flags);
2070 if (this._handlers.onRegExpLiteralLeave) {
2071 this._handlers.onRegExpLiteralLeave(node);
2076 function parseRegExpLiteral(source, options) {
2077 return new RegExpParser(options).parseLiteral(String(source));
2079 function validateRegExpLiteral(source, options) {
2080 return new RegExpValidator(options).validateLiteral(source);
2082 function visitRegExpAST(node, handlers) {
2083 new RegExpVisitor(handlers).visit(node);
2086 export { ast as AST, RegExpParser, RegExpValidator, parseRegExpLiteral, validateRegExpLiteral, visitRegExpAST };
2087 //# sourceMappingURL=index.mjs.map