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("170 0 11 0 5 0 6 22 2 30 2 457 5 11 15 4 8 0 2 0 130 4 2 1 3 3 2 0 7 0 2 2 2 0 2 19 2 82 2 138 9 165 2 37 3 0 7 40 72 26 5 3 46 42 36 1 2 98 2 0 16 1 8 1 11 2 3 0 17 0 2 29 30 88 12 0 25 32 10 1 5 0 6 21 5 0 10 0 4 0 24 24 8 10 54 20 2 17 61 53 4 0 19 0 8 9 16 15 5 7 3 1 3 21 2 6 2 0 4 3 4 0 17 0 14 1 2 2 15 1 11 0 9 5 5 1 3 21 2 6 2 1 2 1 2 1 32 3 2 0 20 2 17 8 2 2 2 21 2 6 2 1 2 4 4 0 19 0 16 1 24 0 12 7 3 1 3 21 2 6 2 1 2 4 4 0 31 1 2 2 16 0 18 0 2 5 4 2 2 3 4 1 2 0 2 1 4 1 4 2 4 11 23 0 53 7 2 2 2 22 2 15 4 0 27 2 6 1 31 0 5 7 2 2 2 22 2 9 2 4 4 0 33 0 2 1 16 1 18 8 2 2 2 40 3 0 17 0 6 2 9 2 25 5 6 17 4 23 2 8 2 0 3 6 59 47 2 1 13 6 59 1 2 0 2 4 2 23 2 0 2 9 2 1 10 0 3 4 2 0 22 3 33 0 64 7 2 35 28 4 116 42 21 0 17 5 5 3 4 0 4 1 8 2 5 12 13 0 18 37 2 0 6 0 3 42 2 332 2 3 3 6 2 0 2 3 3 40 2 3 3 32 2 3 3 6 2 0 2 3 3 14 2 56 2 3 3 66 38 15 17 85 3 5 4 619 3 16 2 25 6 74 4 10 8 12 2 3 15 17 15 17 15 12 2 2 16 51 36 0 5 0 68 88 8 40 2 0 6 69 11 30 50 29 3 4 12 43 5 25 55 22 10 52 83 0 94 46 18 6 56 29 14 1 11 43 27 35 42 2 11 35 3 8 8 42 3 2 42 3 2 5 2 1 4 0 6 191 65 277 3 5 3 37 3 5 3 7 2 0 2 0 2 0 2 30 3 52 2 6 2 0 4 2 2 6 4 3 3 5 5 12 6 2 2 6 117 0 14 0 17 12 102 0 5 0 3 9 2 0 3 5 7 0 2 0 2 0 2 15 3 3 6 4 5 0 18 40 2680 46 2 46 2 132 7 3 4 1 13 37 2 0 6 0 3 55 8 0 17 22 10 6 2 6 2 6 2 6 2 6 2 6 2 6 2 6 551 2 26 8 8 4 3 4 5 85 5 4 2 89 2 3 6 42 2 93 18 31 49 15 513 6591 65 20988 4 1164 68 45 3 268 4 15 11 1 21 46 17 30 3 79 40 8 3 102 3 52 3 8 43 12 2 2 2 3 2 22 30 51 15 49 63 5 4 0 2 1 12 27 11 22 26 28 8 46 29 0 17 4 2 9 11 4 2 40 24 2 2 7 21 22 4 0 4 49 2 0 4 1 3 4 3 0 2 0 25 2 3 10 8 2 13 5 3 5 3 5 10 6 2 6 2 42 2 13 7 114 30 11171 13 22 5 48 8453 365 3 105 39 6 13 4 6 0 2 9 2 12 2 4 2 0 2 1 2 1 2 107 34 362 19 63 3 53 41 11 117 4 2 134 37 25 7 25 12 88 4 5 3 5 3 5 3 2 36 11 2 25 2 18 2 1 2 14 3 13 35 122 70 52 268 28 4 48 48 31 14 29 6 37 11 29 3 35 5 7 2 4 43 157 19 35 5 35 5 39 9 51 157 310 10 21 11 7 153 5 3 0 2 43 2 1 4 0 3 22 11 22 10 30 66 18 2 1 11 21 11 25 71 55 7 1 65 0 16 3 2 2 2 28 43 28 4 28 36 7 2 27 28 53 11 21 11 18 14 17 111 72 56 50 14 50 14 35 349 41 7 1 79 28 11 0 9 21 107 20 28 22 13 52 76 44 33 24 27 35 30 0 3 0 9 34 4 0 13 47 15 3 22 0 2 0 36 17 2 24 85 6 2 0 2 3 2 14 2 9 8 46 39 7 3 1 3 21 2 6 2 1 2 4 4 0 19 0 13 4 159 52 19 3 21 2 31 47 21 1 2 0 185 46 42 3 37 47 21 0 60 42 14 0 72 26 230 43 117 63 32 7 3 0 3 7 2 1 2 23 16 0 2 0 95 7 3 38 17 0 2 0 29 0 11 39 8 0 22 0 12 45 20 0 35 56 264 8 2 36 18 0 50 29 113 6 2 1 2 37 22 0 26 5 2 1 2 31 15 0 328 18 190 0 80 921 103 110 18 195 2749 1070 4050 582 8634 568 8 30 114 29 19 47 17 3 32 20 6 18 689 63 129 74 6 0 67 12 65 1 2 0 29 6135 9 1237 43 8 8952 286 50 2 18 3 9 395 2309 106 6 12 4 8 8 9 5991 84 2 70 2 1 3 0 3 1 3 3 2 11 2 0 2 6 2 64 2 3 3 7 2 6 2 27 2 3 2 4 2 0 4 6 2 339 3 24 2 24 2 30 2 24 2 30 2 24 2 30 2 24 2 30 2 24 2 7 2357 44 11 6 17 0 370 43 1301 196 60 67 8 0 1205 3 2 26 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 16 6 2 2 4 2 16 4421 42717 35 4148 12 221 3 5761 15 7472 3104 541 1507 4938");
48 function initLargeIdContinueRanges() {
49 return restoreRanges("183 0 585 111 24 0 252 4 266 44 2 0 2 1 2 1 2 0 73 10 49 30 7 0 102 6 3 5 3 1 2 3 3 9 24 0 31 26 92 10 16 9 34 8 10 0 25 3 2 8 2 2 2 4 44 2 120 14 2 32 55 2 2 17 2 6 11 1 3 9 18 2 57 0 2 6 3 1 3 2 10 0 11 1 3 9 15 0 3 2 57 0 2 4 5 1 3 2 4 0 21 11 4 0 12 2 57 0 2 7 2 2 2 2 21 1 3 9 11 5 2 2 57 0 2 6 3 1 3 2 8 2 11 1 3 9 19 0 60 4 4 2 2 3 10 0 15 9 17 4 58 6 2 2 2 3 8 1 12 1 3 9 18 2 57 0 2 6 2 2 2 3 8 1 12 1 3 9 17 3 56 1 2 6 2 2 2 3 10 0 11 1 3 9 18 2 71 0 5 5 2 0 2 7 7 9 3 1 62 0 3 6 13 7 2 9 88 0 3 8 12 5 3 9 63 1 7 9 12 0 2 0 2 0 5 1 50 19 2 1 6 10 2 35 10 0 101 19 2 9 13 3 5 2 2 2 3 6 4 3 14 11 2 14 704 2 10 8 929 2 30 2 30 1 31 1 65 31 10 0 3 9 34 2 3 9 144 0 119 11 5 11 11 9 129 10 61 4 58 9 2 28 3 10 7 9 23 13 2 1 64 4 48 16 12 9 18 8 13 2 31 12 3 9 45 13 49 19 9 9 7 9 119 2 2 20 5 0 7 0 3 2 199 57 2 4 576 1 20 0 124 12 5 0 4 11 3071 2 142 0 97 31 555 5 106 1 30086 9 70 0 5 9 33 1 81 1 273 0 4 0 5 0 24 4 5 0 84 1 51 17 11 9 7 17 14 10 29 7 26 12 45 3 48 13 16 9 12 0 11 9 48 13 13 0 9 1 3 9 34 2 51 0 2 2 3 1 6 1 2 0 42 4 6 1 237 7 2 1 3 9 20261 0 738 15 17 15 4 1 25 2 193 9 38 0 702 0 227 0 150 4 294 9 1368 2 2 1 6 3 41 2 5 0 166 1 574 3 9 9 370 1 154 10 176 2 54 14 32 9 16 3 46 10 54 9 7 2 37 13 2 9 6 1 45 0 13 2 49 13 9 3 2 11 83 11 7 0 161 11 6 9 7 3 56 1 2 6 3 1 3 2 10 0 11 1 3 6 4 4 193 17 10 9 5 0 82 19 13 9 214 6 3 8 28 1 83 16 16 9 82 12 9 9 84 14 5 9 243 14 166 9 71 5 2 1 3 3 2 0 2 1 13 9 120 6 3 6 4 0 29 9 41 6 2 3 9 0 10 10 47 15 406 7 2 7 17 9 57 21 2 13 123 5 4 0 2 1 2 6 2 0 9 9 49 4 2 1 2 4 9 9 330 3 19306 9 135 4 60 6 26 9 1014 0 2 54 8 3 82 0 12 1 19628 1 5319 4 4 5 9 7 3 6 31 3 149 2 1418 49 513 54 5 49 9 0 15 0 23 4 2 14 1361 6 2 16 3 6 2 1 2 4 262 6 10 9 419 13 1495 6 110 6 6 9 4759 9 787719 239");
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, 10) | 0));
75 constructor(raw2018, raw2019, raw2020) {
76 this._raw2018 = raw2018;
77 this._raw2019 = raw2019;
78 this._raw2020 = raw2020;
81 return (this._set2018 || (this._set2018 = new Set(this._raw2018.split(" "))));
84 return (this._set2019 || (this._set2019 = new Set(this._raw2019.split(" "))));
87 return (this._set2020 || (this._set2020 = new Set(this._raw2020.split(" "))));
90 const gcNameSet = new Set(["General_Category", "gc"]);
91 const scNameSet = new Set(["Script", "Script_Extensions", "sc", "scx"]);
92 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", "", "");
93 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");
94 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", "");
95 function isValidUnicodeProperty(version, name, value) {
96 if (gcNameSet.has(name)) {
97 return version >= 2018 && gcValueSets.es2018.has(value);
99 if (scNameSet.has(name)) {
100 return ((version >= 2018 && scValueSets.es2018.has(value)) ||
101 (version >= 2019 && scValueSets.es2019.has(value)) ||
102 (version >= 2020 && scValueSets.es2020.has(value)));
106 function isValidLoneUnicodeProperty(version, value) {
107 return ((version >= 2018 && binPropertySets.es2018.has(value)) ||
108 (version >= 2019 && binPropertySets.es2019.has(value)));
111 const Backspace = 0x08;
112 const CharacterTabulation = 0x09;
113 const LineFeed = 0x0a;
114 const LineTabulation = 0x0b;
115 const FormFeed = 0x0c;
116 const CarriageReturn = 0x0d;
117 const ExclamationMark = 0x21;
118 const DollarSign = 0x24;
119 const LeftParenthesis = 0x28;
120 const RightParenthesis = 0x29;
121 const Asterisk = 0x2a;
122 const PlusSign = 0x2b;
124 const HyphenMinus = 0x2d;
125 const FullStop = 0x2e;
126 const Solidus = 0x2f;
127 const DigitZero = 0x30;
128 const DigitOne = 0x31;
129 const DigitSeven = 0x37;
130 const DigitNine = 0x39;
132 const LessThanSign = 0x3c;
133 const EqualsSign = 0x3d;
134 const GreaterThanSign = 0x3e;
135 const QuestionMark = 0x3f;
136 const LatinCapitalLetterA = 0x41;
137 const LatinCapitalLetterB = 0x42;
138 const LatinCapitalLetterD = 0x44;
139 const LatinCapitalLetterF = 0x46;
140 const LatinCapitalLetterP = 0x50;
141 const LatinCapitalLetterS = 0x53;
142 const LatinCapitalLetterW = 0x57;
143 const LatinCapitalLetterZ = 0x5a;
144 const LowLine = 0x5f;
145 const LatinSmallLetterA = 0x61;
146 const LatinSmallLetterB = 0x62;
147 const LatinSmallLetterC = 0x63;
148 const LatinSmallLetterD = 0x64;
149 const LatinSmallLetterF = 0x66;
150 const LatinSmallLetterG = 0x67;
151 const LatinSmallLetterI = 0x69;
152 const LatinSmallLetterK = 0x6b;
153 const LatinSmallLetterM = 0x6d;
154 const LatinSmallLetterN = 0x6e;
155 const LatinSmallLetterP = 0x70;
156 const LatinSmallLetterR = 0x72;
157 const LatinSmallLetterS = 0x73;
158 const LatinSmallLetterT = 0x74;
159 const LatinSmallLetterU = 0x75;
160 const LatinSmallLetterV = 0x76;
161 const LatinSmallLetterW = 0x77;
162 const LatinSmallLetterX = 0x78;
163 const LatinSmallLetterY = 0x79;
164 const LatinSmallLetterZ = 0x7a;
165 const LeftSquareBracket = 0x5b;
166 const ReverseSolidus = 0x5c;
167 const RightSquareBracket = 0x5d;
168 const CircumflexAccent = 0x5e;
169 const LeftCurlyBracket = 0x7b;
170 const VerticalLine = 0x7c;
171 const RightCurlyBracket = 0x7d;
172 const ZeroWidthNonJoiner = 0x200c;
173 const ZeroWidthJoiner = 0x200d;
174 const LineSeparator = 0x2028;
175 const ParagraphSeparator = 0x2029;
176 const MinCodePoint = 0x00;
177 const MaxCodePoint = 0x10ffff;
178 function isLatinLetter(code) {
179 return ((code >= LatinCapitalLetterA && code <= LatinCapitalLetterZ) ||
180 (code >= LatinSmallLetterA && code <= LatinSmallLetterZ));
182 function isDecimalDigit(code) {
183 return code >= DigitZero && code <= DigitNine;
185 function isOctalDigit(code) {
186 return code >= DigitZero && code <= DigitSeven;
188 function isHexDigit(code) {
189 return ((code >= DigitZero && code <= DigitNine) ||
190 (code >= LatinCapitalLetterA && code <= LatinCapitalLetterF) ||
191 (code >= LatinSmallLetterA && code <= LatinSmallLetterF));
193 function isLineTerminator(code) {
194 return (code === LineFeed ||
195 code === CarriageReturn ||
196 code === LineSeparator ||
197 code === ParagraphSeparator);
199 function isValidUnicode(code) {
200 return code >= MinCodePoint && code <= MaxCodePoint;
202 function digitToInt(code) {
203 if (code >= LatinSmallLetterA && code <= LatinSmallLetterF) {
204 return code - LatinSmallLetterA + 10;
206 if (code >= LatinCapitalLetterA && code <= LatinCapitalLetterF) {
207 return code - LatinCapitalLetterA + 10;
209 return code - DigitZero;
211 function isLeadSurrogate(code) {
212 return code >= 0xd800 && code <= 0xdbff;
214 function isTrailSurrogate(code) {
215 return code >= 0xdc00 && code <= 0xdfff;
217 function combineSurrogatePair(lead, trail) {
218 return (lead - 0xd800) * 0x400 + (trail - 0xdc00) + 0x10000;
223 return i < end ? s.charCodeAt(i) : -1;
229 const unicodeImpl = {
231 return i < end ? s.codePointAt(i) : -1;
234 return c > 0xffff ? 2 : 1;
239 this._impl = legacyImpl;
257 get currentCodePoint() {
260 get nextCodePoint() {
263 get nextCodePoint2() {
266 get nextCodePoint3() {
269 reset(source, start, end, uFlag) {
270 this._impl = uFlag ? unicodeImpl : legacyImpl;
276 const impl = this._impl;
278 this._cp1 = impl.at(this._s, this._end, index);
279 this._w1 = impl.width(this._cp1);
280 this._cp2 = impl.at(this._s, this._end, index + this._w1);
281 this._w2 = impl.width(this._cp2);
282 this._cp3 = impl.at(this._s, this._end, index + this._w1 + this._w2);
283 this._w3 = impl.width(this._cp3);
284 this._cp4 = impl.at(this._s, this._end, index + this._w1 + this._w2 + this._w3);
287 if (this._cp1 !== -1) {
288 const impl = this._impl;
290 this._cp1 = this._cp2;
292 this._cp2 = this._cp3;
293 this._w2 = impl.width(this._cp2);
294 this._cp3 = this._cp4;
295 this._w3 = impl.width(this._cp3);
296 this._cp4 = impl.at(this._s, this._end, this._i + this._w1 + this._w2 + this._w3);
300 if (this._cp1 === cp) {
307 if (this._cp1 === cp1 && this._cp2 === cp2) {
314 eat3(cp1, cp2, cp3) {
315 if (this._cp1 === cp1 && this._cp2 === cp2 && this._cp3 === cp3) {
325 class RegExpSyntaxError extends SyntaxError {
326 constructor(source, uFlag, index, message) {
328 if (!source.startsWith("/")) {
329 source = `/${source}/${uFlag ? "u" : ""}`;
331 source = `: ${source}`;
333 super(`Invalid regular expression${source}: ${message}`);
338 function isSyntaxCharacter(cp) {
339 return (cp === CircumflexAccent ||
341 cp === ReverseSolidus ||
345 cp === QuestionMark ||
346 cp === LeftParenthesis ||
347 cp === RightParenthesis ||
348 cp === LeftSquareBracket ||
349 cp === RightSquareBracket ||
350 cp === LeftCurlyBracket ||
351 cp === RightCurlyBracket ||
352 cp === VerticalLine);
354 function isRegExpIdentifierStart(cp) {
355 return isIdStart(cp) || cp === DollarSign || cp === LowLine;
357 function isRegExpIdentifierPart(cp) {
358 return (isIdContinue(cp) ||
361 cp === ZeroWidthNonJoiner ||
362 cp === ZeroWidthJoiner);
364 function isUnicodePropertyNameCharacter(cp) {
365 return isLatinLetter(cp) || cp === LowLine;
367 function isUnicodePropertyValueCharacter(cp) {
368 return isUnicodePropertyNameCharacter(cp) || isDecimalDigit(cp);
370 class RegExpValidator {
371 constructor(options) {
372 this._reader = new Reader();
375 this._lastIntValue = 0;
376 this._lastMinValue = 0;
377 this._lastMaxValue = 0;
378 this._lastStrValue = "";
379 this._lastKeyValue = "";
380 this._lastValValue = "";
381 this._lastAssertionIsQuantifiable = false;
382 this._numCapturingParens = 0;
383 this._groupNames = new Set();
384 this._backreferenceNames = new Set();
385 this._options = options || {};
387 validateLiteral(source, start = 0, end = source.length) {
388 this._uFlag = this._nFlag = false;
389 this.reset(source, start, end);
390 this.onLiteralEnter(start);
391 if (this.eat(Solidus) && this.eatRegExpBody() && this.eat(Solidus)) {
392 const flagStart = this.index;
393 const uFlag = source.includes("u", flagStart);
394 this.validateFlags(source, flagStart, end);
395 this.validatePattern(source, start + 1, flagStart - 1, uFlag);
397 else if (start >= end) {
401 const c = String.fromCodePoint(this.currentCodePoint);
402 this.raise(`Unexpected character '${c}'`);
404 this.onLiteralLeave(start, end);
406 validateFlags(source, start = 0, end = source.length) {
407 const existingFlags = new Set();
409 let ignoreCase = false;
410 let multiline = false;
414 for (let i = start; i < end; ++i) {
415 const flag = source.charCodeAt(i);
416 if (existingFlags.has(flag)) {
417 this.raise(`Duplicated flag '${source[i]}'`);
419 existingFlags.add(flag);
420 if (flag === LatinSmallLetterG) {
423 else if (flag === LatinSmallLetterI) {
426 else if (flag === LatinSmallLetterM) {
429 else if (flag === LatinSmallLetterU && this.ecmaVersion >= 2015) {
432 else if (flag === LatinSmallLetterY && this.ecmaVersion >= 2015) {
435 else if (flag === LatinSmallLetterS && this.ecmaVersion >= 2018) {
439 this.raise(`Invalid flag '${source[i]}'`);
442 this.onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll);
444 validatePattern(source, start = 0, end = source.length, uFlag = false) {
445 this._uFlag = uFlag && this.ecmaVersion >= 2015;
446 this._nFlag = uFlag && this.ecmaVersion >= 2018;
447 this.reset(source, start, end);
448 this.consumePattern();
450 this.ecmaVersion >= 2018 &&
451 this._groupNames.size > 0) {
454 this.consumePattern();
458 return Boolean(this._options.strict || this._uFlag);
461 return this._options.ecmaVersion || 2020;
463 onLiteralEnter(start) {
464 if (this._options.onLiteralEnter) {
465 this._options.onLiteralEnter(start);
468 onLiteralLeave(start, end) {
469 if (this._options.onLiteralLeave) {
470 this._options.onLiteralLeave(start, end);
473 onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll) {
474 if (this._options.onFlags) {
475 this._options.onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll);
478 onPatternEnter(start) {
479 if (this._options.onPatternEnter) {
480 this._options.onPatternEnter(start);
483 onPatternLeave(start, end) {
484 if (this._options.onPatternLeave) {
485 this._options.onPatternLeave(start, end);
488 onDisjunctionEnter(start) {
489 if (this._options.onDisjunctionEnter) {
490 this._options.onDisjunctionEnter(start);
493 onDisjunctionLeave(start, end) {
494 if (this._options.onDisjunctionLeave) {
495 this._options.onDisjunctionLeave(start, end);
498 onAlternativeEnter(start, index) {
499 if (this._options.onAlternativeEnter) {
500 this._options.onAlternativeEnter(start, index);
503 onAlternativeLeave(start, end, index) {
504 if (this._options.onAlternativeLeave) {
505 this._options.onAlternativeLeave(start, end, index);
508 onGroupEnter(start) {
509 if (this._options.onGroupEnter) {
510 this._options.onGroupEnter(start);
513 onGroupLeave(start, end) {
514 if (this._options.onGroupLeave) {
515 this._options.onGroupLeave(start, end);
518 onCapturingGroupEnter(start, name) {
519 if (this._options.onCapturingGroupEnter) {
520 this._options.onCapturingGroupEnter(start, name);
523 onCapturingGroupLeave(start, end, name) {
524 if (this._options.onCapturingGroupLeave) {
525 this._options.onCapturingGroupLeave(start, end, name);
528 onQuantifier(start, end, min, max, greedy) {
529 if (this._options.onQuantifier) {
530 this._options.onQuantifier(start, end, min, max, greedy);
533 onLookaroundAssertionEnter(start, kind, negate) {
534 if (this._options.onLookaroundAssertionEnter) {
535 this._options.onLookaroundAssertionEnter(start, kind, negate);
538 onLookaroundAssertionLeave(start, end, kind, negate) {
539 if (this._options.onLookaroundAssertionLeave) {
540 this._options.onLookaroundAssertionLeave(start, end, kind, negate);
543 onEdgeAssertion(start, end, kind) {
544 if (this._options.onEdgeAssertion) {
545 this._options.onEdgeAssertion(start, end, kind);
548 onWordBoundaryAssertion(start, end, kind, negate) {
549 if (this._options.onWordBoundaryAssertion) {
550 this._options.onWordBoundaryAssertion(start, end, kind, negate);
553 onAnyCharacterSet(start, end, kind) {
554 if (this._options.onAnyCharacterSet) {
555 this._options.onAnyCharacterSet(start, end, kind);
558 onEscapeCharacterSet(start, end, kind, negate) {
559 if (this._options.onEscapeCharacterSet) {
560 this._options.onEscapeCharacterSet(start, end, kind, negate);
563 onUnicodePropertyCharacterSet(start, end, kind, key, value, negate) {
564 if (this._options.onUnicodePropertyCharacterSet) {
565 this._options.onUnicodePropertyCharacterSet(start, end, kind, key, value, negate);
568 onCharacter(start, end, value) {
569 if (this._options.onCharacter) {
570 this._options.onCharacter(start, end, value);
573 onBackreference(start, end, ref) {
574 if (this._options.onBackreference) {
575 this._options.onBackreference(start, end, ref);
578 onCharacterClassEnter(start, negate) {
579 if (this._options.onCharacterClassEnter) {
580 this._options.onCharacterClassEnter(start, negate);
583 onCharacterClassLeave(start, end, negate) {
584 if (this._options.onCharacterClassLeave) {
585 this._options.onCharacterClassLeave(start, end, negate);
588 onCharacterClassRange(start, end, min, max) {
589 if (this._options.onCharacterClassRange) {
590 this._options.onCharacterClassRange(start, end, min, max);
594 return this._reader.source;
597 return this._reader.index;
599 get currentCodePoint() {
600 return this._reader.currentCodePoint;
602 get nextCodePoint() {
603 return this._reader.nextCodePoint;
605 get nextCodePoint2() {
606 return this._reader.nextCodePoint2;
608 get nextCodePoint3() {
609 return this._reader.nextCodePoint3;
611 reset(source, start, end) {
612 this._reader.reset(source, start, end, this._uFlag);
615 this._reader.rewind(index);
618 this._reader.advance();
621 return this._reader.eat(cp);
624 return this._reader.eat2(cp1, cp2);
626 eat3(cp1, cp2, cp3) {
627 return this._reader.eat3(cp1, cp2, cp3);
630 throw new RegExpSyntaxError(this.source, this._uFlag, this.index, message);
633 const start = this.index;
637 const cp = this.currentCodePoint;
638 if (cp === -1 || isLineTerminator(cp)) {
639 const kind = inClass ? "character class" : "regular expression";
640 this.raise(`Unterminated ${kind}`);
645 else if (cp === ReverseSolidus) {
648 else if (cp === LeftSquareBracket) {
651 else if (cp === RightSquareBracket) {
654 else if ((cp === Solidus && !inClass) ||
655 (cp === Asterisk && this.index === start)) {
660 return this.index !== start;
663 const start = this.index;
664 this._numCapturingParens = this.countCapturingParens();
665 this._groupNames.clear();
666 this._backreferenceNames.clear();
667 this.onPatternEnter(start);
668 this.consumeDisjunction();
669 const cp = this.currentCodePoint;
670 if (this.currentCodePoint !== -1) {
671 if (cp === RightParenthesis) {
672 this.raise("Unmatched ')'");
674 if (cp === ReverseSolidus) {
675 this.raise("\\ at end of pattern");
677 if (cp === RightSquareBracket || cp === RightCurlyBracket) {
678 this.raise("Lone quantifier brackets");
680 const c = String.fromCodePoint(cp);
681 this.raise(`Unexpected character '${c}'`);
683 for (const name of this._backreferenceNames) {
684 if (!this._groupNames.has(name)) {
685 this.raise("Invalid named capture referenced");
688 this.onPatternLeave(start, this.index);
690 countCapturingParens() {
691 const start = this.index;
696 while ((cp = this.currentCodePoint) !== -1) {
700 else if (cp === ReverseSolidus) {
703 else if (cp === LeftSquareBracket) {
706 else if (cp === RightSquareBracket) {
709 else if (cp === LeftParenthesis &&
711 (this.nextCodePoint !== QuestionMark ||
712 (this.nextCodePoint2 === LessThanSign &&
713 this.nextCodePoint3 !== EqualsSign &&
714 this.nextCodePoint3 !== ExclamationMark))) {
722 consumeDisjunction() {
723 const start = this.index;
725 this.onDisjunctionEnter(start);
727 this.consumeAlternative(i++);
728 } while (this.eat(VerticalLine));
729 if (this.consumeQuantifier(true)) {
730 this.raise("Nothing to repeat");
732 if (this.eat(LeftCurlyBracket)) {
733 this.raise("Lone quantifier brackets");
735 this.onDisjunctionLeave(start, this.index);
737 consumeAlternative(i) {
738 const start = this.index;
739 this.onAlternativeEnter(start, i);
740 while (this.currentCodePoint !== -1 && this.consumeTerm()) {
742 this.onAlternativeLeave(start, this.index, i);
745 if (this._uFlag || this.strict) {
746 return (this.consumeAssertion() ||
747 (this.consumeAtom() && this.consumeOptionalQuantifier()));
749 return ((this.consumeAssertion() &&
750 (!this._lastAssertionIsQuantifiable ||
751 this.consumeOptionalQuantifier())) ||
752 (this.consumeExtendedAtom() && this.consumeOptionalQuantifier()));
754 consumeOptionalQuantifier() {
755 this.consumeQuantifier();
759 const start = this.index;
760 this._lastAssertionIsQuantifiable = false;
761 if (this.eat(CircumflexAccent)) {
762 this.onEdgeAssertion(start, this.index, "start");
765 if (this.eat(DollarSign)) {
766 this.onEdgeAssertion(start, this.index, "end");
769 if (this.eat2(ReverseSolidus, LatinCapitalLetterB)) {
770 this.onWordBoundaryAssertion(start, this.index, "word", true);
773 if (this.eat2(ReverseSolidus, LatinSmallLetterB)) {
774 this.onWordBoundaryAssertion(start, this.index, "word", false);
777 if (this.eat2(LeftParenthesis, QuestionMark)) {
778 const lookbehind = this.ecmaVersion >= 2018 && this.eat(LessThanSign);
780 if (this.eat(EqualsSign) || (negate = this.eat(ExclamationMark))) {
781 const kind = lookbehind ? "lookbehind" : "lookahead";
782 this.onLookaroundAssertionEnter(start, kind, negate);
783 this.consumeDisjunction();
784 if (!this.eat(RightParenthesis)) {
785 this.raise("Unterminated group");
787 this._lastAssertionIsQuantifiable = !lookbehind && !this.strict;
788 this.onLookaroundAssertionLeave(start, this.index, kind, negate);
795 consumeQuantifier(noConsume = false) {
796 const start = this.index;
800 if (this.eat(Asterisk)) {
802 max = Number.POSITIVE_INFINITY;
804 else if (this.eat(PlusSign)) {
806 max = Number.POSITIVE_INFINITY;
808 else if (this.eat(QuestionMark)) {
812 else if (this.eatBracedQuantifier(noConsume)) {
813 min = this._lastMinValue;
814 max = this._lastMaxValue;
819 greedy = !this.eat(QuestionMark);
821 this.onQuantifier(start, this.index, min, max, greedy);
825 eatBracedQuantifier(noError) {
826 const start = this.index;
827 if (this.eat(LeftCurlyBracket)) {
828 this._lastMinValue = 0;
829 this._lastMaxValue = Number.POSITIVE_INFINITY;
830 if (this.eatDecimalDigits()) {
831 this._lastMinValue = this._lastMaxValue = this._lastIntValue;
832 if (this.eat(Comma)) {
833 this._lastMaxValue = this.eatDecimalDigits()
835 : Number.POSITIVE_INFINITY;
837 if (this.eat(RightCurlyBracket)) {
838 if (!noError && this._lastMaxValue < this._lastMinValue) {
839 this.raise("numbers out of order in {} quantifier");
844 if (!noError && (this._uFlag || this.strict)) {
845 this.raise("Incomplete quantifier");
852 return (this.consumePatternCharacter() ||
854 this.consumeReverseSolidusAtomEscape() ||
855 this.consumeCharacterClass() ||
856 this.consumeUncapturingGroup() ||
857 this.consumeCapturingGroup());
860 if (this.eat(FullStop)) {
861 this.onAnyCharacterSet(this.index - 1, this.index, "any");
866 consumeReverseSolidusAtomEscape() {
867 const start = this.index;
868 if (this.eat(ReverseSolidus)) {
869 if (this.consumeAtomEscape()) {
876 consumeUncapturingGroup() {
877 const start = this.index;
878 if (this.eat3(LeftParenthesis, QuestionMark, Colon)) {
879 this.onGroupEnter(start);
880 this.consumeDisjunction();
881 if (!this.eat(RightParenthesis)) {
882 this.raise("Unterminated group");
884 this.onGroupLeave(start, this.index);
889 consumeCapturingGroup() {
890 const start = this.index;
891 if (this.eat(LeftParenthesis)) {
893 if (this.ecmaVersion >= 2018) {
894 if (this.consumeGroupSpecifier()) {
895 name = this._lastStrValue;
898 else if (this.currentCodePoint === QuestionMark) {
899 this.raise("Invalid group");
901 this.onCapturingGroupEnter(start, name);
902 this.consumeDisjunction();
903 if (!this.eat(RightParenthesis)) {
904 this.raise("Unterminated group");
906 this.onCapturingGroupLeave(start, this.index, name);
911 consumeExtendedAtom() {
912 return (this.consumeDot() ||
913 this.consumeReverseSolidusAtomEscape() ||
914 this.consumeReverseSolidusFollowedByC() ||
915 this.consumeCharacterClass() ||
916 this.consumeUncapturingGroup() ||
917 this.consumeCapturingGroup() ||
918 this.consumeInvalidBracedQuantifier() ||
919 this.consumeExtendedPatternCharacter());
921 consumeReverseSolidusFollowedByC() {
922 const start = this.index;
923 if (this.currentCodePoint === ReverseSolidus &&
924 this.nextCodePoint === LatinSmallLetterC) {
925 this._lastIntValue = this.currentCodePoint;
927 this.onCharacter(start, this.index, ReverseSolidus);
932 consumeInvalidBracedQuantifier() {
933 if (this.eatBracedQuantifier(true)) {
934 this.raise("Nothing to repeat");
938 consumePatternCharacter() {
939 const start = this.index;
940 const cp = this.currentCodePoint;
941 if (cp !== -1 && !isSyntaxCharacter(cp)) {
943 this.onCharacter(start, this.index, cp);
948 consumeExtendedPatternCharacter() {
949 const start = this.index;
950 const cp = this.currentCodePoint;
952 cp !== CircumflexAccent &&
954 cp !== ReverseSolidus &&
958 cp !== QuestionMark &&
959 cp !== LeftParenthesis &&
960 cp !== RightParenthesis &&
961 cp !== LeftSquareBracket &&
962 cp !== VerticalLine) {
964 this.onCharacter(start, this.index, cp);
969 consumeGroupSpecifier() {
970 if (this.eat(QuestionMark)) {
971 if (this.eatGroupName()) {
972 if (!this._groupNames.has(this._lastStrValue)) {
973 this._groupNames.add(this._lastStrValue);
976 this.raise("Duplicate capture group name");
978 this.raise("Invalid group");
982 consumeAtomEscape() {
983 if (this.consumeBackreference() ||
984 this.consumeCharacterClassEscape() ||
985 this.consumeCharacterEscape() ||
986 (this._nFlag && this.consumeKGroupName())) {
989 if (this.strict || this._uFlag) {
990 this.raise("Invalid escape");
994 consumeBackreference() {
995 const start = this.index;
996 if (this.eatDecimalEscape()) {
997 const n = this._lastIntValue;
998 if (n <= this._numCapturingParens) {
999 this.onBackreference(start - 1, this.index, n);
1002 if (this.strict || this._uFlag) {
1003 this.raise("Invalid escape");
1009 consumeCharacterClassEscape() {
1010 const start = this.index;
1011 if (this.eat(LatinSmallLetterD)) {
1012 this._lastIntValue = -1;
1013 this.onEscapeCharacterSet(start - 1, this.index, "digit", false);
1016 if (this.eat(LatinCapitalLetterD)) {
1017 this._lastIntValue = -1;
1018 this.onEscapeCharacterSet(start - 1, this.index, "digit", true);
1021 if (this.eat(LatinSmallLetterS)) {
1022 this._lastIntValue = -1;
1023 this.onEscapeCharacterSet(start - 1, this.index, "space", false);
1026 if (this.eat(LatinCapitalLetterS)) {
1027 this._lastIntValue = -1;
1028 this.onEscapeCharacterSet(start - 1, this.index, "space", true);
1031 if (this.eat(LatinSmallLetterW)) {
1032 this._lastIntValue = -1;
1033 this.onEscapeCharacterSet(start - 1, this.index, "word", false);
1036 if (this.eat(LatinCapitalLetterW)) {
1037 this._lastIntValue = -1;
1038 this.onEscapeCharacterSet(start - 1, this.index, "word", true);
1043 this.ecmaVersion >= 2018 &&
1044 (this.eat(LatinSmallLetterP) ||
1045 (negate = this.eat(LatinCapitalLetterP)))) {
1046 this._lastIntValue = -1;
1047 if (this.eat(LeftCurlyBracket) &&
1048 this.eatUnicodePropertyValueExpression() &&
1049 this.eat(RightCurlyBracket)) {
1050 this.onUnicodePropertyCharacterSet(start - 1, this.index, "property", this._lastKeyValue, this._lastValValue || null, negate);
1053 this.raise("Invalid property name");
1057 consumeCharacterEscape() {
1058 const start = this.index;
1059 if (this.eatControlEscape() ||
1060 this.eatCControlLetter() ||
1062 this.eatHexEscapeSequence() ||
1063 this.eatRegExpUnicodeEscapeSequence() ||
1066 this.eatLegacyOctalEscapeSequence()) ||
1067 this.eatIdentityEscape()) {
1068 this.onCharacter(start - 1, this.index, this._lastIntValue);
1073 consumeKGroupName() {
1074 const start = this.index;
1075 if (this.eat(LatinSmallLetterK)) {
1076 if (this.eatGroupName()) {
1077 const groupName = this._lastStrValue;
1078 this._backreferenceNames.add(groupName);
1079 this.onBackreference(start - 1, this.index, groupName);
1082 this.raise("Invalid named reference");
1086 consumeCharacterClass() {
1087 const start = this.index;
1088 if (this.eat(LeftSquareBracket)) {
1089 const negate = this.eat(CircumflexAccent);
1090 this.onCharacterClassEnter(start, negate);
1091 this.consumeClassRanges();
1092 if (!this.eat(RightSquareBracket)) {
1093 this.raise("Unterminated character class");
1095 this.onCharacterClassLeave(start, this.index, negate);
1100 consumeClassRanges() {
1101 const strict = this.strict || this._uFlag;
1103 const rangeStart = this.index;
1104 if (!this.consumeClassAtom()) {
1107 const min = this._lastIntValue;
1108 if (!this.eat(HyphenMinus)) {
1111 this.onCharacter(this.index - 1, this.index, HyphenMinus);
1112 if (!this.consumeClassAtom()) {
1115 const max = this._lastIntValue;
1116 if (min === -1 || max === -1) {
1118 this.raise("Invalid character class");
1123 this.raise("Range out of order in character class");
1125 this.onCharacterClassRange(rangeStart, this.index, min, max);
1128 consumeClassAtom() {
1129 const start = this.index;
1130 const cp = this.currentCodePoint;
1131 if (cp !== -1 && cp !== ReverseSolidus && cp !== RightSquareBracket) {
1133 this._lastIntValue = cp;
1134 this.onCharacter(start, this.index, this._lastIntValue);
1137 if (this.eat(ReverseSolidus)) {
1138 if (this.consumeClassEscape()) {
1141 if (!this.strict && this.currentCodePoint === LatinSmallLetterC) {
1142 this._lastIntValue = ReverseSolidus;
1143 this.onCharacter(start, this.index, this._lastIntValue);
1146 if (this.strict || this._uFlag) {
1147 this.raise("Invalid escape");
1153 consumeClassEscape() {
1154 const start = this.index;
1155 if (this.eat(LatinSmallLetterB)) {
1156 this._lastIntValue = Backspace;
1157 this.onCharacter(start - 1, this.index, this._lastIntValue);
1160 if (this._uFlag && this.eat(HyphenMinus)) {
1161 this._lastIntValue = HyphenMinus;
1162 this.onCharacter(start - 1, this.index, this._lastIntValue);
1168 this.currentCodePoint === LatinSmallLetterC &&
1169 (isDecimalDigit((cp = this.nextCodePoint)) || cp === LowLine)) {
1172 this._lastIntValue = cp % 0x20;
1173 this.onCharacter(start - 1, this.index, this._lastIntValue);
1176 return (this.consumeCharacterClassEscape() || this.consumeCharacterEscape());
1179 if (this.eat(LessThanSign)) {
1180 if (this.eatRegExpIdentifierName() && this.eat(GreaterThanSign)) {
1183 this.raise("Invalid capture group name");
1187 eatRegExpIdentifierName() {
1188 if (this.eatRegExpIdentifierStart()) {
1189 this._lastStrValue = String.fromCodePoint(this._lastIntValue);
1190 while (this.eatRegExpIdentifierPart()) {
1191 this._lastStrValue += String.fromCodePoint(this._lastIntValue);
1197 eatRegExpIdentifierStart() {
1198 const start = this.index;
1199 const forceUFlag = !this._uFlag && this.ecmaVersion >= 2020;
1200 let cp = this.currentCodePoint;
1202 if (cp === ReverseSolidus &&
1203 this.eatRegExpUnicodeEscapeSequence(forceUFlag)) {
1204 cp = this._lastIntValue;
1206 else if (forceUFlag &&
1207 isLeadSurrogate(cp) &&
1208 isTrailSurrogate(this.currentCodePoint)) {
1209 cp = combineSurrogatePair(cp, this.currentCodePoint);
1212 if (isRegExpIdentifierStart(cp)) {
1213 this._lastIntValue = cp;
1216 if (this.index !== start) {
1221 eatRegExpIdentifierPart() {
1222 const start = this.index;
1223 const forceUFlag = !this._uFlag && this.ecmaVersion >= 2020;
1224 let cp = this.currentCodePoint;
1226 if (cp === ReverseSolidus &&
1227 this.eatRegExpUnicodeEscapeSequence(forceUFlag)) {
1228 cp = this._lastIntValue;
1230 else if (forceUFlag &&
1231 isLeadSurrogate(cp) &&
1232 isTrailSurrogate(this.currentCodePoint)) {
1233 cp = combineSurrogatePair(cp, this.currentCodePoint);
1236 if (isRegExpIdentifierPart(cp)) {
1237 this._lastIntValue = cp;
1240 if (this.index !== start) {
1245 eatCControlLetter() {
1246 const start = this.index;
1247 if (this.eat(LatinSmallLetterC)) {
1248 if (this.eatControlLetter()) {
1256 if (this.currentCodePoint === DigitZero &&
1257 !isDecimalDigit(this.nextCodePoint)) {
1258 this._lastIntValue = 0;
1264 eatControlEscape() {
1265 if (this.eat(LatinSmallLetterF)) {
1266 this._lastIntValue = FormFeed;
1269 if (this.eat(LatinSmallLetterN)) {
1270 this._lastIntValue = LineFeed;
1273 if (this.eat(LatinSmallLetterR)) {
1274 this._lastIntValue = CarriageReturn;
1277 if (this.eat(LatinSmallLetterT)) {
1278 this._lastIntValue = CharacterTabulation;
1281 if (this.eat(LatinSmallLetterV)) {
1282 this._lastIntValue = LineTabulation;
1287 eatControlLetter() {
1288 const cp = this.currentCodePoint;
1289 if (isLatinLetter(cp)) {
1291 this._lastIntValue = cp % 0x20;
1296 eatRegExpUnicodeEscapeSequence(forceUFlag = false) {
1297 const start = this.index;
1298 const uFlag = forceUFlag || this._uFlag;
1299 if (this.eat(LatinSmallLetterU)) {
1300 if ((uFlag && this.eatRegExpUnicodeSurrogatePairEscape()) ||
1301 this.eatFixedHexDigits(4) ||
1302 (uFlag && this.eatRegExpUnicodeCodePointEscape())) {
1305 if (this.strict || uFlag) {
1306 this.raise("Invalid unicode escape");
1312 eatRegExpUnicodeSurrogatePairEscape() {
1313 const start = this.index;
1314 if (this.eatFixedHexDigits(4)) {
1315 const lead = this._lastIntValue;
1316 if (isLeadSurrogate(lead) &&
1317 this.eat(ReverseSolidus) &&
1318 this.eat(LatinSmallLetterU) &&
1319 this.eatFixedHexDigits(4)) {
1320 const trail = this._lastIntValue;
1321 if (isTrailSurrogate(trail)) {
1322 this._lastIntValue = combineSurrogatePair(lead, trail);
1330 eatRegExpUnicodeCodePointEscape() {
1331 const start = this.index;
1332 if (this.eat(LeftCurlyBracket) &&
1333 this.eatHexDigits() &&
1334 this.eat(RightCurlyBracket) &&
1335 isValidUnicode(this._lastIntValue)) {
1341 eatIdentityEscape() {
1342 const cp = this.currentCodePoint;
1343 if (this.isValidIdentityEscape(cp)) {
1344 this._lastIntValue = cp;
1350 isValidIdentityEscape(cp) {
1355 return isSyntaxCharacter(cp) || cp === Solidus;
1358 return !isIdContinue(cp);
1361 return !(cp === LatinSmallLetterC || cp === LatinSmallLetterK);
1363 return cp !== LatinSmallLetterC;
1365 eatDecimalEscape() {
1366 this._lastIntValue = 0;
1367 let cp = this.currentCodePoint;
1368 if (cp >= DigitOne && cp <= DigitNine) {
1370 this._lastIntValue = 10 * this._lastIntValue + (cp - DigitZero);
1372 } while ((cp = this.currentCodePoint) >= DigitZero &&
1378 eatUnicodePropertyValueExpression() {
1379 const start = this.index;
1380 if (this.eatUnicodePropertyName() && this.eat(EqualsSign)) {
1381 this._lastKeyValue = this._lastStrValue;
1382 if (this.eatUnicodePropertyValue()) {
1383 this._lastValValue = this._lastStrValue;
1384 if (isValidUnicodeProperty(this.ecmaVersion, this._lastKeyValue, this._lastValValue)) {
1387 this.raise("Invalid property name");
1391 if (this.eatLoneUnicodePropertyNameOrValue()) {
1392 const nameOrValue = this._lastStrValue;
1393 if (isValidUnicodeProperty(this.ecmaVersion, "General_Category", nameOrValue)) {
1394 this._lastKeyValue = "General_Category";
1395 this._lastValValue = nameOrValue;
1398 if (isValidLoneUnicodeProperty(this.ecmaVersion, nameOrValue)) {
1399 this._lastKeyValue = nameOrValue;
1400 this._lastValValue = "";
1403 this.raise("Invalid property name");
1407 eatUnicodePropertyName() {
1408 this._lastStrValue = "";
1409 while (isUnicodePropertyNameCharacter(this.currentCodePoint)) {
1410 this._lastStrValue += String.fromCodePoint(this.currentCodePoint);
1413 return this._lastStrValue !== "";
1415 eatUnicodePropertyValue() {
1416 this._lastStrValue = "";
1417 while (isUnicodePropertyValueCharacter(this.currentCodePoint)) {
1418 this._lastStrValue += String.fromCodePoint(this.currentCodePoint);
1421 return this._lastStrValue !== "";
1423 eatLoneUnicodePropertyNameOrValue() {
1424 return this.eatUnicodePropertyValue();
1426 eatHexEscapeSequence() {
1427 const start = this.index;
1428 if (this.eat(LatinSmallLetterX)) {
1429 if (this.eatFixedHexDigits(2)) {
1432 if (this._uFlag || this.strict) {
1433 this.raise("Invalid escape");
1439 eatDecimalDigits() {
1440 const start = this.index;
1441 this._lastIntValue = 0;
1442 while (isDecimalDigit(this.currentCodePoint)) {
1443 this._lastIntValue =
1444 10 * this._lastIntValue + digitToInt(this.currentCodePoint);
1447 return this.index !== start;
1450 const start = this.index;
1451 this._lastIntValue = 0;
1452 while (isHexDigit(this.currentCodePoint)) {
1453 this._lastIntValue =
1454 16 * this._lastIntValue + digitToInt(this.currentCodePoint);
1457 return this.index !== start;
1459 eatLegacyOctalEscapeSequence() {
1460 if (this.eatOctalDigit()) {
1461 const n1 = this._lastIntValue;
1462 if (this.eatOctalDigit()) {
1463 const n2 = this._lastIntValue;
1464 if (n1 <= 3 && this.eatOctalDigit()) {
1465 this._lastIntValue = n1 * 64 + n2 * 8 + this._lastIntValue;
1468 this._lastIntValue = n1 * 8 + n2;
1472 this._lastIntValue = n1;
1479 const cp = this.currentCodePoint;
1480 if (isOctalDigit(cp)) {
1482 this._lastIntValue = cp - DigitZero;
1485 this._lastIntValue = 0;
1488 eatFixedHexDigits(length) {
1489 const start = this.index;
1490 this._lastIntValue = 0;
1491 for (let i = 0; i < length; ++i) {
1492 const cp = this.currentCodePoint;
1493 if (!isHexDigit(cp)) {
1497 this._lastIntValue = 16 * this._lastIntValue + digitToInt(cp);
1504 const DummyPattern = {};
1505 const DummyFlags = {};
1506 const DummyCapturingGroup = {};
1507 class RegExpParserState {
1508 constructor(options) {
1509 this._node = DummyPattern;
1510 this._flags = DummyFlags;
1511 this._backreferences = [];
1512 this._capturingGroups = [];
1514 this.strict = Boolean(options && options.strict);
1515 this.ecmaVersion = (options && options.ecmaVersion) || 2020;
1518 if (this._node.type !== "Pattern") {
1519 throw new Error("UnknownError");
1524 if (this._flags.type !== "Flags") {
1525 throw new Error("UnknownError");
1529 onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll) {
1535 raw: this.source.slice(start, end),
1544 onPatternEnter(start) {
1553 this._backreferences.length = 0;
1554 this._capturingGroups.length = 0;
1556 onPatternLeave(start, end) {
1557 this._node.end = end;
1558 this._node.raw = this.source.slice(start, end);
1559 for (const reference of this._backreferences) {
1560 const ref = reference.ref;
1561 const group = typeof ref === "number"
1562 ? this._capturingGroups[ref - 1]
1563 : this._capturingGroups.find(g => g.name === ref);
1564 reference.resolved = group;
1565 group.references.push(reference);
1568 onAlternativeEnter(start) {
1569 const parent = this._node;
1570 if (parent.type !== "Assertion" &&
1571 parent.type !== "CapturingGroup" &&
1572 parent.type !== "Group" &&
1573 parent.type !== "Pattern") {
1574 throw new Error("UnknownError");
1577 type: "Alternative",
1584 parent.alternatives.push(this._node);
1586 onAlternativeLeave(start, end) {
1587 const node = this._node;
1588 if (node.type !== "Alternative") {
1589 throw new Error("UnknownError");
1592 node.raw = this.source.slice(start, end);
1593 this._node = node.parent;
1595 onGroupEnter(start) {
1596 const parent = this._node;
1597 if (parent.type !== "Alternative") {
1598 throw new Error("UnknownError");
1608 parent.elements.push(this._node);
1610 onGroupLeave(start, end) {
1611 const node = this._node;
1612 if (node.type !== "Group" || node.parent.type !== "Alternative") {
1613 throw new Error("UnknownError");
1616 node.raw = this.source.slice(start, end);
1617 this._node = node.parent;
1619 onCapturingGroupEnter(start, name) {
1620 const parent = this._node;
1621 if (parent.type !== "Alternative") {
1622 throw new Error("UnknownError");
1625 type: "CapturingGroup",
1634 parent.elements.push(this._node);
1635 this._capturingGroups.push(this._node);
1637 onCapturingGroupLeave(start, end) {
1638 const node = this._node;
1639 if (node.type !== "CapturingGroup" ||
1640 node.parent.type !== "Alternative") {
1641 throw new Error("UnknownError");
1644 node.raw = this.source.slice(start, end);
1645 this._node = node.parent;
1647 onQuantifier(start, end, min, max, greedy) {
1648 const parent = this._node;
1649 if (parent.type !== "Alternative") {
1650 throw new Error("UnknownError");
1652 const element = parent.elements.pop();
1653 if (element == null ||
1654 element.type === "Quantifier" ||
1655 (element.type === "Assertion" && element.kind !== "lookahead")) {
1656 throw new Error("UnknownError");
1661 start: element.start,
1663 raw: this.source.slice(element.start, end),
1669 parent.elements.push(node);
1670 element.parent = node;
1672 onLookaroundAssertionEnter(start, kind, negate) {
1673 const parent = this._node;
1674 if (parent.type !== "Alternative") {
1675 throw new Error("UnknownError");
1677 const node = (this._node = {
1687 parent.elements.push(node);
1689 onLookaroundAssertionLeave(start, end) {
1690 const node = this._node;
1691 if (node.type !== "Assertion" || node.parent.type !== "Alternative") {
1692 throw new Error("UnknownError");
1695 node.raw = this.source.slice(start, end);
1696 this._node = node.parent;
1698 onEdgeAssertion(start, end, kind) {
1699 const parent = this._node;
1700 if (parent.type !== "Alternative") {
1701 throw new Error("UnknownError");
1703 parent.elements.push({
1708 raw: this.source.slice(start, end),
1712 onWordBoundaryAssertion(start, end, kind, negate) {
1713 const parent = this._node;
1714 if (parent.type !== "Alternative") {
1715 throw new Error("UnknownError");
1717 parent.elements.push({
1722 raw: this.source.slice(start, end),
1727 onAnyCharacterSet(start, end, kind) {
1728 const parent = this._node;
1729 if (parent.type !== "Alternative") {
1730 throw new Error("UnknownError");
1732 parent.elements.push({
1733 type: "CharacterSet",
1737 raw: this.source.slice(start, end),
1741 onEscapeCharacterSet(start, end, kind, negate) {
1742 const parent = this._node;
1743 if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
1744 throw new Error("UnknownError");
1746 parent.elements.push({
1747 type: "CharacterSet",
1751 raw: this.source.slice(start, end),
1756 onUnicodePropertyCharacterSet(start, end, kind, key, value, 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),
1773 onCharacter(start, end, value) {
1774 const parent = this._node;
1775 if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
1776 throw new Error("UnknownError");
1778 parent.elements.push({
1783 raw: this.source.slice(start, end),
1787 onBackreference(start, end, ref) {
1788 const parent = this._node;
1789 if (parent.type !== "Alternative") {
1790 throw new Error("UnknownError");
1793 type: "Backreference",
1797 raw: this.source.slice(start, end),
1799 resolved: DummyCapturingGroup,
1801 parent.elements.push(node);
1802 this._backreferences.push(node);
1804 onCharacterClassEnter(start, negate) {
1805 const parent = this._node;
1806 if (parent.type !== "Alternative") {
1807 throw new Error("UnknownError");
1810 type: "CharacterClass",
1818 parent.elements.push(this._node);
1820 onCharacterClassLeave(start, end) {
1821 const node = this._node;
1822 if (node.type !== "CharacterClass" ||
1823 node.parent.type !== "Alternative") {
1824 throw new Error("UnknownError");
1827 node.raw = this.source.slice(start, end);
1828 this._node = node.parent;
1830 onCharacterClassRange(start, end) {
1831 const parent = this._node;
1832 if (parent.type !== "CharacterClass") {
1833 throw new Error("UnknownError");
1835 const elements = parent.elements;
1836 const max = elements.pop();
1837 const hyphen = elements.pop();
1838 const min = elements.pop();
1842 min.type !== "Character" ||
1843 max.type !== "Character" ||
1844 hyphen.type !== "Character" ||
1845 hyphen.value !== HyphenMinus) {
1846 throw new Error("UnknownError");
1849 type: "CharacterClassRange",
1853 raw: this.source.slice(start, end),
1859 elements.push(node);
1862 class RegExpParser {
1863 constructor(options) {
1864 this._state = new RegExpParserState(options);
1865 this._validator = new RegExpValidator(this._state);
1867 parseLiteral(source, start = 0, end = source.length) {
1868 this._state.source = source;
1869 this._validator.validateLiteral(source, start, end);
1870 const pattern = this._state.pattern;
1871 const flags = this._state.flags;
1873 type: "RegExpLiteral",
1881 pattern.parent = literal;
1882 flags.parent = literal;
1885 parseFlags(source, start = 0, end = source.length) {
1886 this._state.source = source;
1887 this._validator.validateFlags(source, start, end);
1888 return this._state.flags;
1890 parsePattern(source, start = 0, end = source.length, uFlag = false) {
1891 this._state.source = source;
1892 this._validator.validatePattern(source, start, end, uFlag);
1893 return this._state.pattern;
1897 class RegExpVisitor {
1898 constructor(handlers) {
1899 this._handlers = handlers;
1902 switch (node.type) {
1904 this.visitAlternative(node);
1907 this.visitAssertion(node);
1909 case "Backreference":
1910 this.visitBackreference(node);
1912 case "CapturingGroup":
1913 this.visitCapturingGroup(node);
1916 this.visitCharacter(node);
1918 case "CharacterClass":
1919 this.visitCharacterClass(node);
1921 case "CharacterClassRange":
1922 this.visitCharacterClassRange(node);
1924 case "CharacterSet":
1925 this.visitCharacterSet(node);
1928 this.visitFlags(node);
1931 this.visitGroup(node);
1934 this.visitPattern(node);
1937 this.visitQuantifier(node);
1939 case "RegExpLiteral":
1940 this.visitRegExpLiteral(node);
1943 throw new Error(`Unknown type: ${node.type}`);
1946 visitAlternative(node) {
1947 if (this._handlers.onAlternativeEnter) {
1948 this._handlers.onAlternativeEnter(node);
1950 node.elements.forEach(this.visit, this);
1951 if (this._handlers.onAlternativeLeave) {
1952 this._handlers.onAlternativeLeave(node);
1955 visitAssertion(node) {
1956 if (this._handlers.onAssertionEnter) {
1957 this._handlers.onAssertionEnter(node);
1959 if (node.kind === "lookahead" || node.kind === "lookbehind") {
1960 node.alternatives.forEach(this.visit, this);
1962 if (this._handlers.onAssertionLeave) {
1963 this._handlers.onAssertionLeave(node);
1966 visitBackreference(node) {
1967 if (this._handlers.onBackreferenceEnter) {
1968 this._handlers.onBackreferenceEnter(node);
1970 if (this._handlers.onBackreferenceLeave) {
1971 this._handlers.onBackreferenceLeave(node);
1974 visitCapturingGroup(node) {
1975 if (this._handlers.onCapturingGroupEnter) {
1976 this._handlers.onCapturingGroupEnter(node);
1978 node.alternatives.forEach(this.visit, this);
1979 if (this._handlers.onCapturingGroupLeave) {
1980 this._handlers.onCapturingGroupLeave(node);
1983 visitCharacter(node) {
1984 if (this._handlers.onCharacterEnter) {
1985 this._handlers.onCharacterEnter(node);
1987 if (this._handlers.onCharacterLeave) {
1988 this._handlers.onCharacterLeave(node);
1991 visitCharacterClass(node) {
1992 if (this._handlers.onCharacterClassEnter) {
1993 this._handlers.onCharacterClassEnter(node);
1995 node.elements.forEach(this.visit, this);
1996 if (this._handlers.onCharacterClassLeave) {
1997 this._handlers.onCharacterClassLeave(node);
2000 visitCharacterClassRange(node) {
2001 if (this._handlers.onCharacterClassRangeEnter) {
2002 this._handlers.onCharacterClassRangeEnter(node);
2004 this.visitCharacter(node.min);
2005 this.visitCharacter(node.max);
2006 if (this._handlers.onCharacterClassRangeLeave) {
2007 this._handlers.onCharacterClassRangeLeave(node);
2010 visitCharacterSet(node) {
2011 if (this._handlers.onCharacterSetEnter) {
2012 this._handlers.onCharacterSetEnter(node);
2014 if (this._handlers.onCharacterSetLeave) {
2015 this._handlers.onCharacterSetLeave(node);
2019 if (this._handlers.onFlagsEnter) {
2020 this._handlers.onFlagsEnter(node);
2022 if (this._handlers.onFlagsLeave) {
2023 this._handlers.onFlagsLeave(node);
2027 if (this._handlers.onGroupEnter) {
2028 this._handlers.onGroupEnter(node);
2030 node.alternatives.forEach(this.visit, this);
2031 if (this._handlers.onGroupLeave) {
2032 this._handlers.onGroupLeave(node);
2035 visitPattern(node) {
2036 if (this._handlers.onPatternEnter) {
2037 this._handlers.onPatternEnter(node);
2039 node.alternatives.forEach(this.visit, this);
2040 if (this._handlers.onPatternLeave) {
2041 this._handlers.onPatternLeave(node);
2044 visitQuantifier(node) {
2045 if (this._handlers.onQuantifierEnter) {
2046 this._handlers.onQuantifierEnter(node);
2048 this.visit(node.element);
2049 if (this._handlers.onQuantifierLeave) {
2050 this._handlers.onQuantifierLeave(node);
2053 visitRegExpLiteral(node) {
2054 if (this._handlers.onRegExpLiteralEnter) {
2055 this._handlers.onRegExpLiteralEnter(node);
2057 this.visitPattern(node.pattern);
2058 this.visitFlags(node.flags);
2059 if (this._handlers.onRegExpLiteralLeave) {
2060 this._handlers.onRegExpLiteralLeave(node);
2065 function parseRegExpLiteral(source, options) {
2066 return new RegExpParser(options).parseLiteral(String(source));
2068 function validateRegExpLiteral(source, options) {
2069 return new RegExpValidator(options).validateLiteral(source);
2071 function visitRegExpAST(node, handlers) {
2072 new RegExpVisitor(handlers).visit(node);
2075 export { ast as AST, RegExpParser, RegExpValidator, parseRegExpLiteral, validateRegExpLiteral, visitRegExpAST };
2076 //# sourceMappingURL=index.mjs.map