1 /*! @author Toru Nagashima <https://github.com/mysticatea> */
4 Object.defineProperty(exports, '__esModule', { value: true });
8 var ast = /*#__PURE__*/Object.freeze({
12 let largeIdStartRanges = undefined;
13 let largeIdContinueRanges = undefined;
14 function isIdStart(cp) {
23 return isLargeIdStart(cp);
25 function isIdContinue(cp) {
40 return isLargeIdStart(cp) || isLargeIdContinue(cp);
42 function isLargeIdStart(cp) {
43 return isInRange(cp, largeIdStartRanges || (largeIdStartRanges = initLargeIdStartRanges()));
45 function isLargeIdContinue(cp) {
46 return isInRange(cp, largeIdContinueRanges ||
47 (largeIdContinueRanges = initLargeIdContinueRanges()));
49 function 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");
52 function 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");
55 function isInRange(cp, ranges) {
56 let l = 0, r = (ranges.length / 2) | 0, i = 0, min = 0, max = 0;
58 i = ((l + r) / 2) | 0;
60 max = ranges[2 * i + 1];
73 function restoreRanges(data) {
75 return data.split(" ").map(s => (last += parseInt(s, 36) | 0));
79 constructor(raw2018, raw2019, raw2020, raw2021) {
80 this._raw2018 = raw2018;
81 this._raw2019 = raw2019;
82 this._raw2020 = raw2020;
83 this._raw2021 = raw2021;
86 return (this._set2018 || (this._set2018 = new Set(this._raw2018.split(" "))));
89 return (this._set2019 || (this._set2019 = new Set(this._raw2019.split(" "))));
92 return (this._set2020 || (this._set2020 = new Set(this._raw2020.split(" "))));
95 return (this._set2021 || (this._set2021 = new Set(this._raw2021.split(" "))));
98 const gcNameSet = new Set(["General_Category", "gc"]);
99 const scNameSet = new Set(["Script", "Script_Extensions", "sc", "scx"]);
100 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", "", "", "");
101 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");
102 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");
103 function isValidUnicodeProperty(version, name, value) {
104 if (gcNameSet.has(name)) {
105 return version >= 2018 && gcValueSets.es2018.has(value);
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)));
115 function 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)));
121 const Backspace = 0x08;
122 const CharacterTabulation = 0x09;
123 const LineFeed = 0x0a;
124 const LineTabulation = 0x0b;
125 const FormFeed = 0x0c;
126 const CarriageReturn = 0x0d;
127 const ExclamationMark = 0x21;
128 const DollarSign = 0x24;
129 const LeftParenthesis = 0x28;
130 const RightParenthesis = 0x29;
131 const Asterisk = 0x2a;
132 const PlusSign = 0x2b;
134 const HyphenMinus = 0x2d;
135 const FullStop = 0x2e;
136 const Solidus = 0x2f;
137 const DigitZero = 0x30;
138 const DigitOne = 0x31;
139 const DigitSeven = 0x37;
140 const DigitNine = 0x39;
142 const LessThanSign = 0x3c;
143 const EqualsSign = 0x3d;
144 const GreaterThanSign = 0x3e;
145 const QuestionMark = 0x3f;
146 const LatinCapitalLetterA = 0x41;
147 const LatinCapitalLetterB = 0x42;
148 const LatinCapitalLetterD = 0x44;
149 const LatinCapitalLetterF = 0x46;
150 const LatinCapitalLetterP = 0x50;
151 const LatinCapitalLetterS = 0x53;
152 const LatinCapitalLetterW = 0x57;
153 const LatinCapitalLetterZ = 0x5a;
154 const LowLine = 0x5f;
155 const LatinSmallLetterA = 0x61;
156 const LatinSmallLetterB = 0x62;
157 const LatinSmallLetterC = 0x63;
158 const LatinSmallLetterD = 0x64;
159 const LatinSmallLetterF = 0x66;
160 const LatinSmallLetterG = 0x67;
161 const LatinSmallLetterI = 0x69;
162 const LatinSmallLetterK = 0x6b;
163 const LatinSmallLetterM = 0x6d;
164 const LatinSmallLetterN = 0x6e;
165 const LatinSmallLetterP = 0x70;
166 const LatinSmallLetterR = 0x72;
167 const LatinSmallLetterS = 0x73;
168 const LatinSmallLetterT = 0x74;
169 const LatinSmallLetterU = 0x75;
170 const LatinSmallLetterV = 0x76;
171 const LatinSmallLetterW = 0x77;
172 const LatinSmallLetterX = 0x78;
173 const LatinSmallLetterY = 0x79;
174 const LatinSmallLetterZ = 0x7a;
175 const LeftSquareBracket = 0x5b;
176 const ReverseSolidus = 0x5c;
177 const RightSquareBracket = 0x5d;
178 const CircumflexAccent = 0x5e;
179 const LeftCurlyBracket = 0x7b;
180 const VerticalLine = 0x7c;
181 const RightCurlyBracket = 0x7d;
182 const ZeroWidthNonJoiner = 0x200c;
183 const ZeroWidthJoiner = 0x200d;
184 const LineSeparator = 0x2028;
185 const ParagraphSeparator = 0x2029;
186 const MinCodePoint = 0x00;
187 const MaxCodePoint = 0x10ffff;
188 function isLatinLetter(code) {
189 return ((code >= LatinCapitalLetterA && code <= LatinCapitalLetterZ) ||
190 (code >= LatinSmallLetterA && code <= LatinSmallLetterZ));
192 function isDecimalDigit(code) {
193 return code >= DigitZero && code <= DigitNine;
195 function isOctalDigit(code) {
196 return code >= DigitZero && code <= DigitSeven;
198 function isHexDigit(code) {
199 return ((code >= DigitZero && code <= DigitNine) ||
200 (code >= LatinCapitalLetterA && code <= LatinCapitalLetterF) ||
201 (code >= LatinSmallLetterA && code <= LatinSmallLetterF));
203 function isLineTerminator(code) {
204 return (code === LineFeed ||
205 code === CarriageReturn ||
206 code === LineSeparator ||
207 code === ParagraphSeparator);
209 function isValidUnicode(code) {
210 return code >= MinCodePoint && code <= MaxCodePoint;
212 function digitToInt(code) {
213 if (code >= LatinSmallLetterA && code <= LatinSmallLetterF) {
214 return code - LatinSmallLetterA + 10;
216 if (code >= LatinCapitalLetterA && code <= LatinCapitalLetterF) {
217 return code - LatinCapitalLetterA + 10;
219 return code - DigitZero;
221 function isLeadSurrogate(code) {
222 return code >= 0xd800 && code <= 0xdbff;
224 function isTrailSurrogate(code) {
225 return code >= 0xdc00 && code <= 0xdfff;
227 function combineSurrogatePair(lead, trail) {
228 return (lead - 0xd800) * 0x400 + (trail - 0xdc00) + 0x10000;
233 return i < end ? s.charCodeAt(i) : -1;
239 const unicodeImpl = {
241 return i < end ? s.codePointAt(i) : -1;
244 return c > 0xffff ? 2 : 1;
249 this._impl = legacyImpl;
267 get currentCodePoint() {
270 get nextCodePoint() {
273 get nextCodePoint2() {
276 get nextCodePoint3() {
279 reset(source, start, end, uFlag) {
280 this._impl = uFlag ? unicodeImpl : legacyImpl;
286 const impl = this._impl;
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);
297 if (this._cp1 !== -1) {
298 const impl = this._impl;
300 this._cp1 = this._cp2;
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);
310 if (this._cp1 === cp) {
317 if (this._cp1 === cp1 && this._cp2 === cp2) {
324 eat3(cp1, cp2, cp3) {
325 if (this._cp1 === cp1 && this._cp2 === cp2 && this._cp3 === cp3) {
335 class RegExpSyntaxError extends SyntaxError {
336 constructor(source, uFlag, index, message) {
338 if (!source.startsWith("/")) {
339 source = `/${source}/${uFlag ? "u" : ""}`;
341 source = `: ${source}`;
343 super(`Invalid regular expression${source}: ${message}`);
348 function isSyntaxCharacter(cp) {
349 return (cp === CircumflexAccent ||
351 cp === ReverseSolidus ||
355 cp === QuestionMark ||
356 cp === LeftParenthesis ||
357 cp === RightParenthesis ||
358 cp === LeftSquareBracket ||
359 cp === RightSquareBracket ||
360 cp === LeftCurlyBracket ||
361 cp === RightCurlyBracket ||
362 cp === VerticalLine);
364 function isRegExpIdentifierStart(cp) {
365 return isIdStart(cp) || cp === DollarSign || cp === LowLine;
367 function isRegExpIdentifierPart(cp) {
368 return (isIdContinue(cp) ||
371 cp === ZeroWidthNonJoiner ||
372 cp === ZeroWidthJoiner);
374 function isUnicodePropertyNameCharacter(cp) {
375 return isLatinLetter(cp) || cp === LowLine;
377 function isUnicodePropertyValueCharacter(cp) {
378 return isUnicodePropertyNameCharacter(cp) || isDecimalDigit(cp);
380 class RegExpValidator {
381 constructor(options) {
382 this._reader = new Reader();
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 || {};
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);
407 else if (start >= end) {
411 const c = String.fromCodePoint(this.currentCodePoint);
412 this.raise(`Unexpected character '${c}'`);
414 this.onLiteralLeave(start, end);
416 validateFlags(source, start = 0, end = source.length) {
417 const existingFlags = new Set();
419 let ignoreCase = false;
420 let multiline = 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]}'`);
430 existingFlags.add(flag);
431 if (flag === LatinSmallLetterG) {
434 else if (flag === LatinSmallLetterI) {
437 else if (flag === LatinSmallLetterM) {
440 else if (flag === LatinSmallLetterU && this.ecmaVersion >= 2015) {
443 else if (flag === LatinSmallLetterY && this.ecmaVersion >= 2015) {
446 else if (flag === LatinSmallLetterS && this.ecmaVersion >= 2018) {
449 else if (flag === LatinSmallLetterD && this.ecmaVersion >= 2022) {
453 this.raise(`Invalid flag '${source[i]}'`);
456 this.onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices);
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();
464 this.ecmaVersion >= 2018 &&
465 this._groupNames.size > 0) {
468 this.consumePattern();
472 return Boolean(this._options.strict || this._uFlag);
475 return this._options.ecmaVersion || 2022;
477 onLiteralEnter(start) {
478 if (this._options.onLiteralEnter) {
479 this._options.onLiteralEnter(start);
482 onLiteralLeave(start, end) {
483 if (this._options.onLiteralLeave) {
484 this._options.onLiteralLeave(start, end);
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);
492 onPatternEnter(start) {
493 if (this._options.onPatternEnter) {
494 this._options.onPatternEnter(start);
497 onPatternLeave(start, end) {
498 if (this._options.onPatternLeave) {
499 this._options.onPatternLeave(start, end);
502 onDisjunctionEnter(start) {
503 if (this._options.onDisjunctionEnter) {
504 this._options.onDisjunctionEnter(start);
507 onDisjunctionLeave(start, end) {
508 if (this._options.onDisjunctionLeave) {
509 this._options.onDisjunctionLeave(start, end);
512 onAlternativeEnter(start, index) {
513 if (this._options.onAlternativeEnter) {
514 this._options.onAlternativeEnter(start, index);
517 onAlternativeLeave(start, end, index) {
518 if (this._options.onAlternativeLeave) {
519 this._options.onAlternativeLeave(start, end, index);
522 onGroupEnter(start) {
523 if (this._options.onGroupEnter) {
524 this._options.onGroupEnter(start);
527 onGroupLeave(start, end) {
528 if (this._options.onGroupLeave) {
529 this._options.onGroupLeave(start, end);
532 onCapturingGroupEnter(start, name) {
533 if (this._options.onCapturingGroupEnter) {
534 this._options.onCapturingGroupEnter(start, name);
537 onCapturingGroupLeave(start, end, name) {
538 if (this._options.onCapturingGroupLeave) {
539 this._options.onCapturingGroupLeave(start, end, name);
542 onQuantifier(start, end, min, max, greedy) {
543 if (this._options.onQuantifier) {
544 this._options.onQuantifier(start, end, min, max, greedy);
547 onLookaroundAssertionEnter(start, kind, negate) {
548 if (this._options.onLookaroundAssertionEnter) {
549 this._options.onLookaroundAssertionEnter(start, kind, negate);
552 onLookaroundAssertionLeave(start, end, kind, negate) {
553 if (this._options.onLookaroundAssertionLeave) {
554 this._options.onLookaroundAssertionLeave(start, end, kind, negate);
557 onEdgeAssertion(start, end, kind) {
558 if (this._options.onEdgeAssertion) {
559 this._options.onEdgeAssertion(start, end, kind);
562 onWordBoundaryAssertion(start, end, kind, negate) {
563 if (this._options.onWordBoundaryAssertion) {
564 this._options.onWordBoundaryAssertion(start, end, kind, negate);
567 onAnyCharacterSet(start, end, kind) {
568 if (this._options.onAnyCharacterSet) {
569 this._options.onAnyCharacterSet(start, end, kind);
572 onEscapeCharacterSet(start, end, kind, negate) {
573 if (this._options.onEscapeCharacterSet) {
574 this._options.onEscapeCharacterSet(start, end, kind, negate);
577 onUnicodePropertyCharacterSet(start, end, kind, key, value, negate) {
578 if (this._options.onUnicodePropertyCharacterSet) {
579 this._options.onUnicodePropertyCharacterSet(start, end, kind, key, value, negate);
582 onCharacter(start, end, value) {
583 if (this._options.onCharacter) {
584 this._options.onCharacter(start, end, value);
587 onBackreference(start, end, ref) {
588 if (this._options.onBackreference) {
589 this._options.onBackreference(start, end, ref);
592 onCharacterClassEnter(start, negate) {
593 if (this._options.onCharacterClassEnter) {
594 this._options.onCharacterClassEnter(start, negate);
597 onCharacterClassLeave(start, end, negate) {
598 if (this._options.onCharacterClassLeave) {
599 this._options.onCharacterClassLeave(start, end, negate);
602 onCharacterClassRange(start, end, min, max) {
603 if (this._options.onCharacterClassRange) {
604 this._options.onCharacterClassRange(start, end, min, max);
608 return this._reader.source;
611 return this._reader.index;
613 get currentCodePoint() {
614 return this._reader.currentCodePoint;
616 get nextCodePoint() {
617 return this._reader.nextCodePoint;
619 get nextCodePoint2() {
620 return this._reader.nextCodePoint2;
622 get nextCodePoint3() {
623 return this._reader.nextCodePoint3;
625 reset(source, start, end) {
626 this._reader.reset(source, start, end, this._uFlag);
629 this._reader.rewind(index);
632 this._reader.advance();
635 return this._reader.eat(cp);
638 return this._reader.eat2(cp1, cp2);
640 eat3(cp1, cp2, cp3) {
641 return this._reader.eat3(cp1, cp2, cp3);
644 throw new RegExpSyntaxError(this.source, this._uFlag, this.index, message);
647 const start = this.index;
651 const cp = this.currentCodePoint;
652 if (cp === -1 || isLineTerminator(cp)) {
653 const kind = inClass ? "character class" : "regular expression";
654 this.raise(`Unterminated ${kind}`);
659 else if (cp === ReverseSolidus) {
662 else if (cp === LeftSquareBracket) {
665 else if (cp === RightSquareBracket) {
668 else if ((cp === Solidus && !inClass) ||
669 (cp === Asterisk && this.index === start)) {
674 return this.index !== start;
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 ')'");
688 if (cp === ReverseSolidus) {
689 this.raise("\\ at end of pattern");
691 if (cp === RightSquareBracket || cp === RightCurlyBracket) {
692 this.raise("Lone quantifier brackets");
694 const c = String.fromCodePoint(cp);
695 this.raise(`Unexpected character '${c}'`);
697 for (const name of this._backreferenceNames) {
698 if (!this._groupNames.has(name)) {
699 this.raise("Invalid named capture referenced");
702 this.onPatternLeave(start, this.index);
704 countCapturingParens() {
705 const start = this.index;
710 while ((cp = this.currentCodePoint) !== -1) {
714 else if (cp === ReverseSolidus) {
717 else if (cp === LeftSquareBracket) {
720 else if (cp === RightSquareBracket) {
723 else if (cp === LeftParenthesis &&
725 (this.nextCodePoint !== QuestionMark ||
726 (this.nextCodePoint2 === LessThanSign &&
727 this.nextCodePoint3 !== EqualsSign &&
728 this.nextCodePoint3 !== ExclamationMark))) {
736 consumeDisjunction() {
737 const start = this.index;
739 this.onDisjunctionEnter(start);
741 this.consumeAlternative(i++);
742 } while (this.eat(VerticalLine));
743 if (this.consumeQuantifier(true)) {
744 this.raise("Nothing to repeat");
746 if (this.eat(LeftCurlyBracket)) {
747 this.raise("Lone quantifier brackets");
749 this.onDisjunctionLeave(start, this.index);
751 consumeAlternative(i) {
752 const start = this.index;
753 this.onAlternativeEnter(start, i);
754 while (this.currentCodePoint !== -1 && this.consumeTerm()) {
756 this.onAlternativeLeave(start, this.index, i);
759 if (this._uFlag || this.strict) {
760 return (this.consumeAssertion() ||
761 (this.consumeAtom() && this.consumeOptionalQuantifier()));
763 return ((this.consumeAssertion() &&
764 (!this._lastAssertionIsQuantifiable ||
765 this.consumeOptionalQuantifier())) ||
766 (this.consumeExtendedAtom() && this.consumeOptionalQuantifier()));
768 consumeOptionalQuantifier() {
769 this.consumeQuantifier();
773 const start = this.index;
774 this._lastAssertionIsQuantifiable = false;
775 if (this.eat(CircumflexAccent)) {
776 this.onEdgeAssertion(start, this.index, "start");
779 if (this.eat(DollarSign)) {
780 this.onEdgeAssertion(start, this.index, "end");
783 if (this.eat2(ReverseSolidus, LatinCapitalLetterB)) {
784 this.onWordBoundaryAssertion(start, this.index, "word", true);
787 if (this.eat2(ReverseSolidus, LatinSmallLetterB)) {
788 this.onWordBoundaryAssertion(start, this.index, "word", false);
791 if (this.eat2(LeftParenthesis, QuestionMark)) {
792 const lookbehind = this.ecmaVersion >= 2018 && this.eat(LessThanSign);
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");
801 this._lastAssertionIsQuantifiable = !lookbehind && !this.strict;
802 this.onLookaroundAssertionLeave(start, this.index, kind, negate);
809 consumeQuantifier(noConsume = false) {
810 const start = this.index;
814 if (this.eat(Asterisk)) {
816 max = Number.POSITIVE_INFINITY;
818 else if (this.eat(PlusSign)) {
820 max = Number.POSITIVE_INFINITY;
822 else if (this.eat(QuestionMark)) {
826 else if (this.eatBracedQuantifier(noConsume)) {
827 min = this._lastMinValue;
828 max = this._lastMaxValue;
833 greedy = !this.eat(QuestionMark);
835 this.onQuantifier(start, this.index, min, max, greedy);
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()
849 : Number.POSITIVE_INFINITY;
851 if (this.eat(RightCurlyBracket)) {
852 if (!noError && this._lastMaxValue < this._lastMinValue) {
853 this.raise("numbers out of order in {} quantifier");
858 if (!noError && (this._uFlag || this.strict)) {
859 this.raise("Incomplete quantifier");
866 return (this.consumePatternCharacter() ||
868 this.consumeReverseSolidusAtomEscape() ||
869 this.consumeCharacterClass() ||
870 this.consumeUncapturingGroup() ||
871 this.consumeCapturingGroup());
874 if (this.eat(FullStop)) {
875 this.onAnyCharacterSet(this.index - 1, this.index, "any");
880 consumeReverseSolidusAtomEscape() {
881 const start = this.index;
882 if (this.eat(ReverseSolidus)) {
883 if (this.consumeAtomEscape()) {
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");
898 this.onGroupLeave(start, this.index);
903 consumeCapturingGroup() {
904 const start = this.index;
905 if (this.eat(LeftParenthesis)) {
907 if (this.ecmaVersion >= 2018) {
908 if (this.consumeGroupSpecifier()) {
909 name = this._lastStrValue;
912 else if (this.currentCodePoint === QuestionMark) {
913 this.raise("Invalid group");
915 this.onCapturingGroupEnter(start, name);
916 this.consumeDisjunction();
917 if (!this.eat(RightParenthesis)) {
918 this.raise("Unterminated group");
920 this.onCapturingGroupLeave(start, this.index, name);
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());
935 consumeReverseSolidusFollowedByC() {
936 const start = this.index;
937 if (this.currentCodePoint === ReverseSolidus &&
938 this.nextCodePoint === LatinSmallLetterC) {
939 this._lastIntValue = this.currentCodePoint;
941 this.onCharacter(start, this.index, ReverseSolidus);
946 consumeInvalidBracedQuantifier() {
947 if (this.eatBracedQuantifier(true)) {
948 this.raise("Nothing to repeat");
952 consumePatternCharacter() {
953 const start = this.index;
954 const cp = this.currentCodePoint;
955 if (cp !== -1 && !isSyntaxCharacter(cp)) {
957 this.onCharacter(start, this.index, cp);
962 consumeExtendedPatternCharacter() {
963 const start = this.index;
964 const cp = this.currentCodePoint;
966 cp !== CircumflexAccent &&
968 cp !== ReverseSolidus &&
972 cp !== QuestionMark &&
973 cp !== LeftParenthesis &&
974 cp !== RightParenthesis &&
975 cp !== LeftSquareBracket &&
976 cp !== VerticalLine) {
978 this.onCharacter(start, this.index, cp);
983 consumeGroupSpecifier() {
984 if (this.eat(QuestionMark)) {
985 if (this.eatGroupName()) {
986 if (!this._groupNames.has(this._lastStrValue)) {
987 this._groupNames.add(this._lastStrValue);
990 this.raise("Duplicate capture group name");
992 this.raise("Invalid group");
996 consumeAtomEscape() {
997 if (this.consumeBackreference() ||
998 this.consumeCharacterClassEscape() ||
999 this.consumeCharacterEscape() ||
1000 (this._nFlag && this.consumeKGroupName())) {
1003 if (this.strict || this._uFlag) {
1004 this.raise("Invalid escape");
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);
1016 if (this.strict || this._uFlag) {
1017 this.raise("Invalid escape");
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);
1030 if (this.eat(LatinCapitalLetterD)) {
1031 this._lastIntValue = -1;
1032 this.onEscapeCharacterSet(start - 1, this.index, "digit", true);
1035 if (this.eat(LatinSmallLetterS)) {
1036 this._lastIntValue = -1;
1037 this.onEscapeCharacterSet(start - 1, this.index, "space", false);
1040 if (this.eat(LatinCapitalLetterS)) {
1041 this._lastIntValue = -1;
1042 this.onEscapeCharacterSet(start - 1, this.index, "space", true);
1045 if (this.eat(LatinSmallLetterW)) {
1046 this._lastIntValue = -1;
1047 this.onEscapeCharacterSet(start - 1, this.index, "word", false);
1050 if (this.eat(LatinCapitalLetterW)) {
1051 this._lastIntValue = -1;
1052 this.onEscapeCharacterSet(start - 1, this.index, "word", true);
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);
1067 this.raise("Invalid property name");
1071 consumeCharacterEscape() {
1072 const start = this.index;
1073 if (this.eatControlEscape() ||
1074 this.eatCControlLetter() ||
1076 this.eatHexEscapeSequence() ||
1077 this.eatRegExpUnicodeEscapeSequence() ||
1080 this.eatLegacyOctalEscapeSequence()) ||
1081 this.eatIdentityEscape()) {
1082 this.onCharacter(start - 1, this.index, this._lastIntValue);
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);
1096 this.raise("Invalid named reference");
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");
1109 this.onCharacterClassLeave(start, this.index, negate);
1114 consumeClassRanges() {
1115 const strict = this.strict || this._uFlag;
1117 const rangeStart = this.index;
1118 if (!this.consumeClassAtom()) {
1121 const min = this._lastIntValue;
1122 if (!this.eat(HyphenMinus)) {
1125 this.onCharacter(this.index - 1, this.index, HyphenMinus);
1126 if (!this.consumeClassAtom()) {
1129 const max = this._lastIntValue;
1130 if (min === -1 || max === -1) {
1132 this.raise("Invalid character class");
1137 this.raise("Range out of order in character class");
1139 this.onCharacterClassRange(rangeStart, this.index, min, max);
1142 consumeClassAtom() {
1143 const start = this.index;
1144 const cp = this.currentCodePoint;
1145 if (cp !== -1 && cp !== ReverseSolidus && cp !== RightSquareBracket) {
1147 this._lastIntValue = cp;
1148 this.onCharacter(start, this.index, this._lastIntValue);
1151 if (this.eat(ReverseSolidus)) {
1152 if (this.consumeClassEscape()) {
1155 if (!this.strict && this.currentCodePoint === LatinSmallLetterC) {
1156 this._lastIntValue = ReverseSolidus;
1157 this.onCharacter(start, this.index, this._lastIntValue);
1160 if (this.strict || this._uFlag) {
1161 this.raise("Invalid escape");
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);
1174 if (this._uFlag && this.eat(HyphenMinus)) {
1175 this._lastIntValue = HyphenMinus;
1176 this.onCharacter(start - 1, this.index, this._lastIntValue);
1182 this.currentCodePoint === LatinSmallLetterC &&
1183 (isDecimalDigit((cp = this.nextCodePoint)) || cp === LowLine)) {
1186 this._lastIntValue = cp % 0x20;
1187 this.onCharacter(start - 1, this.index, this._lastIntValue);
1190 return (this.consumeCharacterClassEscape() || this.consumeCharacterEscape());
1193 if (this.eat(LessThanSign)) {
1194 if (this.eatRegExpIdentifierName() && this.eat(GreaterThanSign)) {
1197 this.raise("Invalid capture group name");
1201 eatRegExpIdentifierName() {
1202 if (this.eatRegExpIdentifierStart()) {
1203 this._lastStrValue = String.fromCodePoint(this._lastIntValue);
1204 while (this.eatRegExpIdentifierPart()) {
1205 this._lastStrValue += String.fromCodePoint(this._lastIntValue);
1211 eatRegExpIdentifierStart() {
1212 const start = this.index;
1213 const forceUFlag = !this._uFlag && this.ecmaVersion >= 2020;
1214 let cp = this.currentCodePoint;
1216 if (cp === ReverseSolidus &&
1217 this.eatRegExpUnicodeEscapeSequence(forceUFlag)) {
1218 cp = this._lastIntValue;
1220 else if (forceUFlag &&
1221 isLeadSurrogate(cp) &&
1222 isTrailSurrogate(this.currentCodePoint)) {
1223 cp = combineSurrogatePair(cp, this.currentCodePoint);
1226 if (isRegExpIdentifierStart(cp)) {
1227 this._lastIntValue = cp;
1230 if (this.index !== start) {
1235 eatRegExpIdentifierPart() {
1236 const start = this.index;
1237 const forceUFlag = !this._uFlag && this.ecmaVersion >= 2020;
1238 let cp = this.currentCodePoint;
1240 if (cp === ReverseSolidus &&
1241 this.eatRegExpUnicodeEscapeSequence(forceUFlag)) {
1242 cp = this._lastIntValue;
1244 else if (forceUFlag &&
1245 isLeadSurrogate(cp) &&
1246 isTrailSurrogate(this.currentCodePoint)) {
1247 cp = combineSurrogatePair(cp, this.currentCodePoint);
1250 if (isRegExpIdentifierPart(cp)) {
1251 this._lastIntValue = cp;
1254 if (this.index !== start) {
1259 eatCControlLetter() {
1260 const start = this.index;
1261 if (this.eat(LatinSmallLetterC)) {
1262 if (this.eatControlLetter()) {
1270 if (this.currentCodePoint === DigitZero &&
1271 !isDecimalDigit(this.nextCodePoint)) {
1272 this._lastIntValue = 0;
1278 eatControlEscape() {
1279 if (this.eat(LatinSmallLetterF)) {
1280 this._lastIntValue = FormFeed;
1283 if (this.eat(LatinSmallLetterN)) {
1284 this._lastIntValue = LineFeed;
1287 if (this.eat(LatinSmallLetterR)) {
1288 this._lastIntValue = CarriageReturn;
1291 if (this.eat(LatinSmallLetterT)) {
1292 this._lastIntValue = CharacterTabulation;
1295 if (this.eat(LatinSmallLetterV)) {
1296 this._lastIntValue = LineTabulation;
1301 eatControlLetter() {
1302 const cp = this.currentCodePoint;
1303 if (isLatinLetter(cp)) {
1305 this._lastIntValue = cp % 0x20;
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())) {
1319 if (this.strict || uFlag) {
1320 this.raise("Invalid unicode escape");
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);
1344 eatRegExpUnicodeCodePointEscape() {
1345 const start = this.index;
1346 if (this.eat(LeftCurlyBracket) &&
1347 this.eatHexDigits() &&
1348 this.eat(RightCurlyBracket) &&
1349 isValidUnicode(this._lastIntValue)) {
1355 eatIdentityEscape() {
1356 const cp = this.currentCodePoint;
1357 if (this.isValidIdentityEscape(cp)) {
1358 this._lastIntValue = cp;
1364 isValidIdentityEscape(cp) {
1369 return isSyntaxCharacter(cp) || cp === Solidus;
1372 return !isIdContinue(cp);
1375 return !(cp === LatinSmallLetterC || cp === LatinSmallLetterK);
1377 return cp !== LatinSmallLetterC;
1379 eatDecimalEscape() {
1380 this._lastIntValue = 0;
1381 let cp = this.currentCodePoint;
1382 if (cp >= DigitOne && cp <= DigitNine) {
1384 this._lastIntValue = 10 * this._lastIntValue + (cp - DigitZero);
1386 } while ((cp = this.currentCodePoint) >= DigitZero &&
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)) {
1401 this.raise("Invalid property name");
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;
1412 if (isValidLoneUnicodeProperty(this.ecmaVersion, nameOrValue)) {
1413 this._lastKeyValue = nameOrValue;
1414 this._lastValValue = "";
1417 this.raise("Invalid property name");
1421 eatUnicodePropertyName() {
1422 this._lastStrValue = "";
1423 while (isUnicodePropertyNameCharacter(this.currentCodePoint)) {
1424 this._lastStrValue += String.fromCodePoint(this.currentCodePoint);
1427 return this._lastStrValue !== "";
1429 eatUnicodePropertyValue() {
1430 this._lastStrValue = "";
1431 while (isUnicodePropertyValueCharacter(this.currentCodePoint)) {
1432 this._lastStrValue += String.fromCodePoint(this.currentCodePoint);
1435 return this._lastStrValue !== "";
1437 eatLoneUnicodePropertyNameOrValue() {
1438 return this.eatUnicodePropertyValue();
1440 eatHexEscapeSequence() {
1441 const start = this.index;
1442 if (this.eat(LatinSmallLetterX)) {
1443 if (this.eatFixedHexDigits(2)) {
1446 if (this._uFlag || this.strict) {
1447 this.raise("Invalid escape");
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);
1461 return this.index !== start;
1464 const start = this.index;
1465 this._lastIntValue = 0;
1466 while (isHexDigit(this.currentCodePoint)) {
1467 this._lastIntValue =
1468 16 * this._lastIntValue + digitToInt(this.currentCodePoint);
1471 return this.index !== start;
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;
1482 this._lastIntValue = n1 * 8 + n2;
1486 this._lastIntValue = n1;
1493 const cp = this.currentCodePoint;
1494 if (isOctalDigit(cp)) {
1496 this._lastIntValue = cp - DigitZero;
1499 this._lastIntValue = 0;
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)) {
1511 this._lastIntValue = 16 * this._lastIntValue + digitToInt(cp);
1518 const DummyPattern = {};
1519 const DummyFlags = {};
1520 const DummyCapturingGroup = {};
1521 class RegExpParserState {
1522 constructor(options) {
1523 this._node = DummyPattern;
1524 this._flags = DummyFlags;
1525 this._backreferences = [];
1526 this._capturingGroups = [];
1528 this.strict = Boolean(options && options.strict);
1529 this.ecmaVersion = (options && options.ecmaVersion) || 2022;
1532 if (this._node.type !== "Pattern") {
1533 throw new Error("UnknownError");
1538 if (this._flags.type !== "Flags") {
1539 throw new Error("UnknownError");
1543 onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices) {
1549 raw: this.source.slice(start, end),
1559 onPatternEnter(start) {
1568 this._backreferences.length = 0;
1569 this._capturingGroups.length = 0;
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);
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");
1592 type: "Alternative",
1599 parent.alternatives.push(this._node);
1601 onAlternativeLeave(start, end) {
1602 const node = this._node;
1603 if (node.type !== "Alternative") {
1604 throw new Error("UnknownError");
1607 node.raw = this.source.slice(start, end);
1608 this._node = node.parent;
1610 onGroupEnter(start) {
1611 const parent = this._node;
1612 if (parent.type !== "Alternative") {
1613 throw new Error("UnknownError");
1623 parent.elements.push(this._node);
1625 onGroupLeave(start, end) {
1626 const node = this._node;
1627 if (node.type !== "Group" || node.parent.type !== "Alternative") {
1628 throw new Error("UnknownError");
1631 node.raw = this.source.slice(start, end);
1632 this._node = node.parent;
1634 onCapturingGroupEnter(start, name) {
1635 const parent = this._node;
1636 if (parent.type !== "Alternative") {
1637 throw new Error("UnknownError");
1640 type: "CapturingGroup",
1649 parent.elements.push(this._node);
1650 this._capturingGroups.push(this._node);
1652 onCapturingGroupLeave(start, end) {
1653 const node = this._node;
1654 if (node.type !== "CapturingGroup" ||
1655 node.parent.type !== "Alternative") {
1656 throw new Error("UnknownError");
1659 node.raw = this.source.slice(start, end);
1660 this._node = node.parent;
1662 onQuantifier(start, end, min, max, greedy) {
1663 const parent = this._node;
1664 if (parent.type !== "Alternative") {
1665 throw new Error("UnknownError");
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");
1676 start: element.start,
1678 raw: this.source.slice(element.start, end),
1684 parent.elements.push(node);
1685 element.parent = node;
1687 onLookaroundAssertionEnter(start, kind, negate) {
1688 const parent = this._node;
1689 if (parent.type !== "Alternative") {
1690 throw new Error("UnknownError");
1692 const node = (this._node = {
1702 parent.elements.push(node);
1704 onLookaroundAssertionLeave(start, end) {
1705 const node = this._node;
1706 if (node.type !== "Assertion" || node.parent.type !== "Alternative") {
1707 throw new Error("UnknownError");
1710 node.raw = this.source.slice(start, end);
1711 this._node = node.parent;
1713 onEdgeAssertion(start, end, kind) {
1714 const parent = this._node;
1715 if (parent.type !== "Alternative") {
1716 throw new Error("UnknownError");
1718 parent.elements.push({
1723 raw: this.source.slice(start, end),
1727 onWordBoundaryAssertion(start, end, kind, negate) {
1728 const parent = this._node;
1729 if (parent.type !== "Alternative") {
1730 throw new Error("UnknownError");
1732 parent.elements.push({
1737 raw: this.source.slice(start, end),
1742 onAnyCharacterSet(start, end, kind) {
1743 const parent = this._node;
1744 if (parent.type !== "Alternative") {
1745 throw new Error("UnknownError");
1747 parent.elements.push({
1748 type: "CharacterSet",
1752 raw: this.source.slice(start, end),
1756 onEscapeCharacterSet(start, end, kind, negate) {
1757 const parent = this._node;
1758 if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
1759 throw new Error("UnknownError");
1761 parent.elements.push({
1762 type: "CharacterSet",
1766 raw: this.source.slice(start, end),
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");
1776 parent.elements.push({
1777 type: "CharacterSet",
1781 raw: this.source.slice(start, end),
1788 onCharacter(start, end, value) {
1789 const parent = this._node;
1790 if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
1791 throw new Error("UnknownError");
1793 parent.elements.push({
1798 raw: this.source.slice(start, end),
1802 onBackreference(start, end, ref) {
1803 const parent = this._node;
1804 if (parent.type !== "Alternative") {
1805 throw new Error("UnknownError");
1808 type: "Backreference",
1812 raw: this.source.slice(start, end),
1814 resolved: DummyCapturingGroup,
1816 parent.elements.push(node);
1817 this._backreferences.push(node);
1819 onCharacterClassEnter(start, negate) {
1820 const parent = this._node;
1821 if (parent.type !== "Alternative") {
1822 throw new Error("UnknownError");
1825 type: "CharacterClass",
1833 parent.elements.push(this._node);
1835 onCharacterClassLeave(start, end) {
1836 const node = this._node;
1837 if (node.type !== "CharacterClass" ||
1838 node.parent.type !== "Alternative") {
1839 throw new Error("UnknownError");
1842 node.raw = this.source.slice(start, end);
1843 this._node = node.parent;
1845 onCharacterClassRange(start, end) {
1846 const parent = this._node;
1847 if (parent.type !== "CharacterClass") {
1848 throw new Error("UnknownError");
1850 const elements = parent.elements;
1851 const max = elements.pop();
1852 const hyphen = elements.pop();
1853 const min = elements.pop();
1857 min.type !== "Character" ||
1858 max.type !== "Character" ||
1859 hyphen.type !== "Character" ||
1860 hyphen.value !== HyphenMinus) {
1861 throw new Error("UnknownError");
1864 type: "CharacterClassRange",
1868 raw: this.source.slice(start, end),
1874 elements.push(node);
1877 class RegExpParser {
1878 constructor(options) {
1879 this._state = new RegExpParserState(options);
1880 this._validator = new RegExpValidator(this._state);
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;
1888 type: "RegExpLiteral",
1896 pattern.parent = literal;
1897 flags.parent = literal;
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;
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;
1912 class RegExpVisitor {
1913 constructor(handlers) {
1914 this._handlers = handlers;
1917 switch (node.type) {
1919 this.visitAlternative(node);
1922 this.visitAssertion(node);
1924 case "Backreference":
1925 this.visitBackreference(node);
1927 case "CapturingGroup":
1928 this.visitCapturingGroup(node);
1931 this.visitCharacter(node);
1933 case "CharacterClass":
1934 this.visitCharacterClass(node);
1936 case "CharacterClassRange":
1937 this.visitCharacterClassRange(node);
1939 case "CharacterSet":
1940 this.visitCharacterSet(node);
1943 this.visitFlags(node);
1946 this.visitGroup(node);
1949 this.visitPattern(node);
1952 this.visitQuantifier(node);
1954 case "RegExpLiteral":
1955 this.visitRegExpLiteral(node);
1958 throw new Error(`Unknown type: ${node.type}`);
1961 visitAlternative(node) {
1962 if (this._handlers.onAlternativeEnter) {
1963 this._handlers.onAlternativeEnter(node);
1965 node.elements.forEach(this.visit, this);
1966 if (this._handlers.onAlternativeLeave) {
1967 this._handlers.onAlternativeLeave(node);
1970 visitAssertion(node) {
1971 if (this._handlers.onAssertionEnter) {
1972 this._handlers.onAssertionEnter(node);
1974 if (node.kind === "lookahead" || node.kind === "lookbehind") {
1975 node.alternatives.forEach(this.visit, this);
1977 if (this._handlers.onAssertionLeave) {
1978 this._handlers.onAssertionLeave(node);
1981 visitBackreference(node) {
1982 if (this._handlers.onBackreferenceEnter) {
1983 this._handlers.onBackreferenceEnter(node);
1985 if (this._handlers.onBackreferenceLeave) {
1986 this._handlers.onBackreferenceLeave(node);
1989 visitCapturingGroup(node) {
1990 if (this._handlers.onCapturingGroupEnter) {
1991 this._handlers.onCapturingGroupEnter(node);
1993 node.alternatives.forEach(this.visit, this);
1994 if (this._handlers.onCapturingGroupLeave) {
1995 this._handlers.onCapturingGroupLeave(node);
1998 visitCharacter(node) {
1999 if (this._handlers.onCharacterEnter) {
2000 this._handlers.onCharacterEnter(node);
2002 if (this._handlers.onCharacterLeave) {
2003 this._handlers.onCharacterLeave(node);
2006 visitCharacterClass(node) {
2007 if (this._handlers.onCharacterClassEnter) {
2008 this._handlers.onCharacterClassEnter(node);
2010 node.elements.forEach(this.visit, this);
2011 if (this._handlers.onCharacterClassLeave) {
2012 this._handlers.onCharacterClassLeave(node);
2015 visitCharacterClassRange(node) {
2016 if (this._handlers.onCharacterClassRangeEnter) {
2017 this._handlers.onCharacterClassRangeEnter(node);
2019 this.visitCharacter(node.min);
2020 this.visitCharacter(node.max);
2021 if (this._handlers.onCharacterClassRangeLeave) {
2022 this._handlers.onCharacterClassRangeLeave(node);
2025 visitCharacterSet(node) {
2026 if (this._handlers.onCharacterSetEnter) {
2027 this._handlers.onCharacterSetEnter(node);
2029 if (this._handlers.onCharacterSetLeave) {
2030 this._handlers.onCharacterSetLeave(node);
2034 if (this._handlers.onFlagsEnter) {
2035 this._handlers.onFlagsEnter(node);
2037 if (this._handlers.onFlagsLeave) {
2038 this._handlers.onFlagsLeave(node);
2042 if (this._handlers.onGroupEnter) {
2043 this._handlers.onGroupEnter(node);
2045 node.alternatives.forEach(this.visit, this);
2046 if (this._handlers.onGroupLeave) {
2047 this._handlers.onGroupLeave(node);
2050 visitPattern(node) {
2051 if (this._handlers.onPatternEnter) {
2052 this._handlers.onPatternEnter(node);
2054 node.alternatives.forEach(this.visit, this);
2055 if (this._handlers.onPatternLeave) {
2056 this._handlers.onPatternLeave(node);
2059 visitQuantifier(node) {
2060 if (this._handlers.onQuantifierEnter) {
2061 this._handlers.onQuantifierEnter(node);
2063 this.visit(node.element);
2064 if (this._handlers.onQuantifierLeave) {
2065 this._handlers.onQuantifierLeave(node);
2068 visitRegExpLiteral(node) {
2069 if (this._handlers.onRegExpLiteralEnter) {
2070 this._handlers.onRegExpLiteralEnter(node);
2072 this.visitPattern(node.pattern);
2073 this.visitFlags(node.flags);
2074 if (this._handlers.onRegExpLiteralLeave) {
2075 this._handlers.onRegExpLiteralLeave(node);
2080 function parseRegExpLiteral(source, options) {
2081 return new RegExpParser(options).parseLiteral(String(source));
2083 function validateRegExpLiteral(source, options) {
2084 return new RegExpValidator(options).validateLiteral(source);
2086 function visitRegExpAST(node, handlers) {
2087 new RegExpVisitor(handlers).visit(node);
2091 exports.RegExpParser = RegExpParser;
2092 exports.RegExpValidator = RegExpValidator;
2093 exports.parseRegExpLiteral = parseRegExpLiteral;
2094 exports.validateRegExpLiteral = validateRegExpLiteral;
2095 exports.visitRegExpAST = visitRegExpAST;
2096 //# sourceMappingURL=index.js.map