blob: d02491f0da334e8c8d45cbcece512dec595d8ee8 [file] [log] [blame]
Yang Guo4fd355c2019-09-19 10:59:03 +02001/*! @author Toru Nagashima <https://github.com/mysticatea> */
2
3
4var ast = /*#__PURE__*/Object.freeze({
5
6});
7
Tim van der Lippe16aca392020-11-13 11:37:13 +00008let largeIdStartRanges = undefined;
9let largeIdContinueRanges = undefined;
Yang Guo4fd355c2019-09-19 10:59:03 +020010function isIdStart(cp) {
11 if (cp < 0x41)
12 return false;
13 if (cp < 0x5b)
14 return true;
15 if (cp < 0x61)
16 return false;
17 if (cp < 0x7b)
18 return true;
19 return isLargeIdStart(cp);
20}
21function isIdContinue(cp) {
22 if (cp < 0x30)
23 return false;
24 if (cp < 0x3a)
25 return true;
26 if (cp < 0x41)
27 return false;
28 if (cp < 0x5b)
29 return true;
30 if (cp === 0x5f)
31 return true;
32 if (cp < 0x61)
33 return false;
34 if (cp < 0x7b)
35 return true;
36 return isLargeIdStart(cp) || isLargeIdContinue(cp);
37}
38function isLargeIdStart(cp) {
Tim van der Lippe16aca392020-11-13 11:37:13 +000039 return isInRange(cp, largeIdStartRanges || (largeIdStartRanges = initLargeIdStartRanges()));
Yang Guo4fd355c2019-09-19 10:59:03 +020040}
41function isLargeIdContinue(cp) {
Tim van der Lippe16aca392020-11-13 11:37:13 +000042 return isInRange(cp, largeIdContinueRanges ||
43 (largeIdContinueRanges = initLargeIdContinueRanges()));
44}
45function 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");
47}
48function 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");
50}
51function isInRange(cp, ranges) {
52 let l = 0, r = (ranges.length / 2) | 0, i = 0, min = 0, max = 0;
53 while (l < r) {
54 i = ((l + r) / 2) | 0;
55 min = ranges[2 * i];
56 max = ranges[2 * i + 1];
57 if (cp < min) {
58 r = i;
Yang Guo4fd355c2019-09-19 10:59:03 +020059 }
Tim van der Lippe16aca392020-11-13 11:37:13 +000060 else if (cp > max) {
61 l = i + 1;
Yang Guo4fd355c2019-09-19 10:59:03 +020062 }
Tim van der Lippe16aca392020-11-13 11:37:13 +000063 else {
64 return true;
Yang Guo4fd355c2019-09-19 10:59:03 +020065 }
Yang Guo4fd355c2019-09-19 10:59:03 +020066 }
Yang Guo4fd355c2019-09-19 10:59:03 +020067 return false;
68}
Tim van der Lippe16aca392020-11-13 11:37:13 +000069function restoreRanges(data) {
70 let last = 0;
71 return data.split(" ").map(s => (last += parseInt(s, 10) | 0));
72}
Yang Guo4fd355c2019-09-19 10:59:03 +020073
Tim van der Lippe16aca392020-11-13 11:37:13 +000074class DataSet {
75 constructor(raw2018, raw2019, raw2020) {
76 this._raw2018 = raw2018;
77 this._raw2019 = raw2019;
78 this._raw2020 = raw2020;
79 }
80 get es2018() {
81 return (this._set2018 || (this._set2018 = new Set(this._raw2018.split(" "))));
82 }
83 get es2019() {
84 return (this._set2019 || (this._set2019 = new Set(this._raw2019.split(" "))));
85 }
86 get es2020() {
87 return (this._set2020 || (this._set2020 = new Set(this._raw2020.split(" "))));
88 }
89}
90const gcNameSet = new Set(["General_Category", "gc"]);
91const scNameSet = new Set(["Script", "Script_Extensions", "sc", "scx"]);
92const 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", "", "");
93const 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");
94const 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", "");
95function isValidUnicodeProperty(version, name, value) {
96 if (gcNameSet.has(name)) {
97 return version >= 2018 && gcValueSets.es2018.has(value);
98 }
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)));
103 }
104 return false;
105}
106function isValidLoneUnicodeProperty(version, value) {
107 return ((version >= 2018 && binPropertySets.es2018.has(value)) ||
108 (version >= 2019 && binPropertySets.es2019.has(value)));
109}
Yang Guo4fd355c2019-09-19 10:59:03 +0200110
111const Backspace = 0x08;
112const CharacterTabulation = 0x09;
113const LineFeed = 0x0a;
114const LineTabulation = 0x0b;
115const FormFeed = 0x0c;
116const CarriageReturn = 0x0d;
117const ExclamationMark = 0x21;
118const DollarSign = 0x24;
119const LeftParenthesis = 0x28;
120const RightParenthesis = 0x29;
121const Asterisk = 0x2a;
122const PlusSign = 0x2b;
123const Comma = 0x2c;
124const HyphenMinus = 0x2d;
125const FullStop = 0x2e;
126const Solidus = 0x2f;
127const DigitZero = 0x30;
128const DigitOne = 0x31;
129const DigitSeven = 0x37;
130const DigitNine = 0x39;
131const Colon = 0x3a;
132const LessThanSign = 0x3c;
133const EqualsSign = 0x3d;
134const GreaterThanSign = 0x3e;
135const QuestionMark = 0x3f;
136const LatinCapitalLetterA = 0x41;
137const LatinCapitalLetterB = 0x42;
138const LatinCapitalLetterD = 0x44;
139const LatinCapitalLetterF = 0x46;
140const LatinCapitalLetterP = 0x50;
141const LatinCapitalLetterS = 0x53;
142const LatinCapitalLetterW = 0x57;
143const LatinCapitalLetterZ = 0x5a;
144const LowLine = 0x5f;
145const LatinSmallLetterA = 0x61;
146const LatinSmallLetterB = 0x62;
147const LatinSmallLetterC = 0x63;
148const LatinSmallLetterD = 0x64;
149const LatinSmallLetterF = 0x66;
150const LatinSmallLetterG = 0x67;
151const LatinSmallLetterI = 0x69;
152const LatinSmallLetterK = 0x6b;
153const LatinSmallLetterM = 0x6d;
154const LatinSmallLetterN = 0x6e;
155const LatinSmallLetterP = 0x70;
156const LatinSmallLetterR = 0x72;
157const LatinSmallLetterS = 0x73;
158const LatinSmallLetterT = 0x74;
159const LatinSmallLetterU = 0x75;
160const LatinSmallLetterV = 0x76;
161const LatinSmallLetterW = 0x77;
162const LatinSmallLetterX = 0x78;
163const LatinSmallLetterY = 0x79;
164const LatinSmallLetterZ = 0x7a;
165const LeftSquareBracket = 0x5b;
166const ReverseSolidus = 0x5c;
167const RightSquareBracket = 0x5d;
168const CircumflexAccent = 0x5e;
169const LeftCurlyBracket = 0x7b;
170const VerticalLine = 0x7c;
171const RightCurlyBracket = 0x7d;
172const ZeroWidthNonJoiner = 0x200c;
173const ZeroWidthJoiner = 0x200d;
174const LineSeparator = 0x2028;
175const ParagraphSeparator = 0x2029;
176const MinCodePoint = 0x00;
177const MaxCodePoint = 0x10ffff;
178function isLatinLetter(code) {
179 return ((code >= LatinCapitalLetterA && code <= LatinCapitalLetterZ) ||
180 (code >= LatinSmallLetterA && code <= LatinSmallLetterZ));
181}
182function isDecimalDigit(code) {
183 return code >= DigitZero && code <= DigitNine;
184}
185function isOctalDigit(code) {
186 return code >= DigitZero && code <= DigitSeven;
187}
188function isHexDigit(code) {
189 return ((code >= DigitZero && code <= DigitNine) ||
190 (code >= LatinCapitalLetterA && code <= LatinCapitalLetterF) ||
191 (code >= LatinSmallLetterA && code <= LatinSmallLetterF));
192}
193function isLineTerminator(code) {
194 return (code === LineFeed ||
195 code === CarriageReturn ||
196 code === LineSeparator ||
197 code === ParagraphSeparator);
198}
199function isValidUnicode(code) {
200 return code >= MinCodePoint && code <= MaxCodePoint;
201}
202function digitToInt(code) {
203 if (code >= LatinSmallLetterA && code <= LatinSmallLetterF) {
204 return code - LatinSmallLetterA + 10;
205 }
206 if (code >= LatinCapitalLetterA && code <= LatinCapitalLetterF) {
207 return code - LatinCapitalLetterA + 10;
208 }
209 return code - DigitZero;
210}
Tim van der Lippe16aca392020-11-13 11:37:13 +0000211function isLeadSurrogate(code) {
212 return code >= 0xd800 && code <= 0xdbff;
213}
214function isTrailSurrogate(code) {
215 return code >= 0xdc00 && code <= 0xdfff;
216}
217function combineSurrogatePair(lead, trail) {
218 return (lead - 0xd800) * 0x400 + (trail - 0xdc00) + 0x10000;
219}
Yang Guo4fd355c2019-09-19 10:59:03 +0200220
221const legacyImpl = {
222 at(s, end, i) {
223 return i < end ? s.charCodeAt(i) : -1;
224 },
225 width(c) {
226 return 1;
227 },
228};
229const unicodeImpl = {
230 at(s, end, i) {
231 return i < end ? s.codePointAt(i) : -1;
232 },
233 width(c) {
234 return c > 0xffff ? 2 : 1;
235 },
236};
237class Reader {
238 constructor() {
239 this._impl = legacyImpl;
240 this._s = "";
241 this._i = 0;
242 this._end = 0;
243 this._cp1 = -1;
244 this._w1 = 1;
245 this._cp2 = -1;
246 this._w2 = 1;
247 this._cp3 = -1;
248 this._w3 = 1;
249 this._cp4 = -1;
250 }
251 get source() {
252 return this._s;
253 }
254 get index() {
255 return this._i;
256 }
257 get currentCodePoint() {
258 return this._cp1;
259 }
260 get nextCodePoint() {
261 return this._cp2;
262 }
263 get nextCodePoint2() {
264 return this._cp3;
265 }
266 get nextCodePoint3() {
267 return this._cp4;
268 }
269 reset(source, start, end, uFlag) {
270 this._impl = uFlag ? unicodeImpl : legacyImpl;
271 this._s = source;
272 this._end = end;
273 this.rewind(start);
274 }
275 rewind(index) {
276 const impl = this._impl;
277 this._i = index;
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);
285 }
286 advance() {
287 if (this._cp1 !== -1) {
288 const impl = this._impl;
289 this._i += this._w1;
290 this._cp1 = this._cp2;
291 this._w1 = this._w2;
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);
297 }
298 }
299 eat(cp) {
300 if (this._cp1 === cp) {
301 this.advance();
302 return true;
303 }
304 return false;
305 }
306 eat2(cp1, cp2) {
307 if (this._cp1 === cp1 && this._cp2 === cp2) {
308 this.advance();
309 this.advance();
310 return true;
311 }
312 return false;
313 }
314 eat3(cp1, cp2, cp3) {
315 if (this._cp1 === cp1 && this._cp2 === cp2 && this._cp3 === cp3) {
316 this.advance();
317 this.advance();
318 this.advance();
319 return true;
320 }
321 return false;
322 }
323}
324
325class RegExpSyntaxError extends SyntaxError {
326 constructor(source, uFlag, index, message) {
327 if (source) {
Tim van der Lippe16aca392020-11-13 11:37:13 +0000328 if (!source.startsWith("/")) {
Yang Guo4fd355c2019-09-19 10:59:03 +0200329 source = `/${source}/${uFlag ? "u" : ""}`;
330 }
331 source = `: ${source}`;
332 }
333 super(`Invalid regular expression${source}: ${message}`);
334 this.index = index;
335 }
336}
337
338function isSyntaxCharacter(cp) {
339 return (cp === CircumflexAccent ||
340 cp === DollarSign ||
341 cp === ReverseSolidus ||
342 cp === FullStop ||
343 cp === Asterisk ||
344 cp === PlusSign ||
345 cp === QuestionMark ||
346 cp === LeftParenthesis ||
347 cp === RightParenthesis ||
348 cp === LeftSquareBracket ||
349 cp === RightSquareBracket ||
350 cp === LeftCurlyBracket ||
351 cp === RightCurlyBracket ||
352 cp === VerticalLine);
353}
354function isRegExpIdentifierStart(cp) {
355 return isIdStart(cp) || cp === DollarSign || cp === LowLine;
356}
357function isRegExpIdentifierPart(cp) {
358 return (isIdContinue(cp) ||
359 cp === DollarSign ||
360 cp === LowLine ||
361 cp === ZeroWidthNonJoiner ||
362 cp === ZeroWidthJoiner);
363}
364function isUnicodePropertyNameCharacter(cp) {
365 return isLatinLetter(cp) || cp === LowLine;
366}
367function isUnicodePropertyValueCharacter(cp) {
368 return isUnicodePropertyNameCharacter(cp) || isDecimalDigit(cp);
369}
Yang Guo4fd355c2019-09-19 10:59:03 +0200370class RegExpValidator {
371 constructor(options) {
372 this._reader = new Reader();
373 this._uFlag = false;
374 this._nFlag = false;
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 || {};
386 }
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;
Tim van der Lippe16aca392020-11-13 11:37:13 +0000393 const uFlag = source.includes("u", flagStart);
Yang Guo4fd355c2019-09-19 10:59:03 +0200394 this.validateFlags(source, flagStart, end);
395 this.validatePattern(source, start + 1, flagStart - 1, uFlag);
396 }
397 else if (start >= end) {
398 this.raise("Empty");
399 }
400 else {
401 const c = String.fromCodePoint(this.currentCodePoint);
402 this.raise(`Unexpected character '${c}'`);
403 }
404 this.onLiteralLeave(start, end);
405 }
406 validateFlags(source, start = 0, end = source.length) {
407 const existingFlags = new Set();
408 let global = false;
409 let ignoreCase = false;
410 let multiline = false;
411 let sticky = false;
412 let unicode = false;
413 let dotAll = 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]}'`);
418 }
419 existingFlags.add(flag);
420 if (flag === LatinSmallLetterG) {
421 global = true;
422 }
423 else if (flag === LatinSmallLetterI) {
424 ignoreCase = true;
425 }
426 else if (flag === LatinSmallLetterM) {
427 multiline = true;
428 }
429 else if (flag === LatinSmallLetterU && this.ecmaVersion >= 2015) {
430 unicode = true;
431 }
432 else if (flag === LatinSmallLetterY && this.ecmaVersion >= 2015) {
433 sticky = true;
434 }
435 else if (flag === LatinSmallLetterS && this.ecmaVersion >= 2018) {
436 dotAll = true;
437 }
438 else {
439 this.raise(`Invalid flag '${source[i]}'`);
440 }
441 }
442 this.onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll);
443 }
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);
Tim van der Lippe16aca392020-11-13 11:37:13 +0000448 this.consumePattern();
Yang Guo4fd355c2019-09-19 10:59:03 +0200449 if (!this._nFlag &&
450 this.ecmaVersion >= 2018 &&
451 this._groupNames.size > 0) {
452 this._nFlag = true;
453 this.rewind(start);
Tim van der Lippe16aca392020-11-13 11:37:13 +0000454 this.consumePattern();
Yang Guo4fd355c2019-09-19 10:59:03 +0200455 }
456 }
457 get strict() {
458 return Boolean(this._options.strict || this._uFlag);
459 }
460 get ecmaVersion() {
Tim van der Lippe16aca392020-11-13 11:37:13 +0000461 return this._options.ecmaVersion || 2020;
Yang Guo4fd355c2019-09-19 10:59:03 +0200462 }
463 onLiteralEnter(start) {
464 if (this._options.onLiteralEnter) {
465 this._options.onLiteralEnter(start);
466 }
467 }
468 onLiteralLeave(start, end) {
469 if (this._options.onLiteralLeave) {
470 this._options.onLiteralLeave(start, end);
471 }
472 }
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);
476 }
477 }
478 onPatternEnter(start) {
479 if (this._options.onPatternEnter) {
480 this._options.onPatternEnter(start);
481 }
482 }
483 onPatternLeave(start, end) {
484 if (this._options.onPatternLeave) {
485 this._options.onPatternLeave(start, end);
486 }
487 }
488 onDisjunctionEnter(start) {
489 if (this._options.onDisjunctionEnter) {
490 this._options.onDisjunctionEnter(start);
491 }
492 }
493 onDisjunctionLeave(start, end) {
494 if (this._options.onDisjunctionLeave) {
495 this._options.onDisjunctionLeave(start, end);
496 }
497 }
498 onAlternativeEnter(start, index) {
499 if (this._options.onAlternativeEnter) {
500 this._options.onAlternativeEnter(start, index);
501 }
502 }
503 onAlternativeLeave(start, end, index) {
504 if (this._options.onAlternativeLeave) {
505 this._options.onAlternativeLeave(start, end, index);
506 }
507 }
508 onGroupEnter(start) {
509 if (this._options.onGroupEnter) {
510 this._options.onGroupEnter(start);
511 }
512 }
513 onGroupLeave(start, end) {
514 if (this._options.onGroupLeave) {
515 this._options.onGroupLeave(start, end);
516 }
517 }
518 onCapturingGroupEnter(start, name) {
519 if (this._options.onCapturingGroupEnter) {
520 this._options.onCapturingGroupEnter(start, name);
521 }
522 }
523 onCapturingGroupLeave(start, end, name) {
524 if (this._options.onCapturingGroupLeave) {
525 this._options.onCapturingGroupLeave(start, end, name);
526 }
527 }
528 onQuantifier(start, end, min, max, greedy) {
529 if (this._options.onQuantifier) {
530 this._options.onQuantifier(start, end, min, max, greedy);
531 }
532 }
533 onLookaroundAssertionEnter(start, kind, negate) {
534 if (this._options.onLookaroundAssertionEnter) {
535 this._options.onLookaroundAssertionEnter(start, kind, negate);
536 }
537 }
538 onLookaroundAssertionLeave(start, end, kind, negate) {
539 if (this._options.onLookaroundAssertionLeave) {
540 this._options.onLookaroundAssertionLeave(start, end, kind, negate);
541 }
542 }
543 onEdgeAssertion(start, end, kind) {
544 if (this._options.onEdgeAssertion) {
545 this._options.onEdgeAssertion(start, end, kind);
546 }
547 }
548 onWordBoundaryAssertion(start, end, kind, negate) {
549 if (this._options.onWordBoundaryAssertion) {
550 this._options.onWordBoundaryAssertion(start, end, kind, negate);
551 }
552 }
553 onAnyCharacterSet(start, end, kind) {
554 if (this._options.onAnyCharacterSet) {
555 this._options.onAnyCharacterSet(start, end, kind);
556 }
557 }
558 onEscapeCharacterSet(start, end, kind, negate) {
559 if (this._options.onEscapeCharacterSet) {
560 this._options.onEscapeCharacterSet(start, end, kind, negate);
561 }
562 }
563 onUnicodePropertyCharacterSet(start, end, kind, key, value, negate) {
564 if (this._options.onUnicodePropertyCharacterSet) {
565 this._options.onUnicodePropertyCharacterSet(start, end, kind, key, value, negate);
566 }
567 }
568 onCharacter(start, end, value) {
569 if (this._options.onCharacter) {
570 this._options.onCharacter(start, end, value);
571 }
572 }
573 onBackreference(start, end, ref) {
574 if (this._options.onBackreference) {
575 this._options.onBackreference(start, end, ref);
576 }
577 }
578 onCharacterClassEnter(start, negate) {
579 if (this._options.onCharacterClassEnter) {
580 this._options.onCharacterClassEnter(start, negate);
581 }
582 }
583 onCharacterClassLeave(start, end, negate) {
584 if (this._options.onCharacterClassLeave) {
585 this._options.onCharacterClassLeave(start, end, negate);
586 }
587 }
588 onCharacterClassRange(start, end, min, max) {
589 if (this._options.onCharacterClassRange) {
590 this._options.onCharacterClassRange(start, end, min, max);
591 }
592 }
593 get source() {
594 return this._reader.source;
595 }
596 get index() {
597 return this._reader.index;
598 }
599 get currentCodePoint() {
600 return this._reader.currentCodePoint;
601 }
602 get nextCodePoint() {
603 return this._reader.nextCodePoint;
604 }
605 get nextCodePoint2() {
606 return this._reader.nextCodePoint2;
607 }
608 get nextCodePoint3() {
609 return this._reader.nextCodePoint3;
610 }
611 reset(source, start, end) {
612 this._reader.reset(source, start, end, this._uFlag);
613 }
614 rewind(index) {
615 this._reader.rewind(index);
616 }
617 advance() {
618 this._reader.advance();
619 }
620 eat(cp) {
621 return this._reader.eat(cp);
622 }
623 eat2(cp1, cp2) {
624 return this._reader.eat2(cp1, cp2);
625 }
626 eat3(cp1, cp2, cp3) {
627 return this._reader.eat3(cp1, cp2, cp3);
628 }
629 raise(message) {
630 throw new RegExpSyntaxError(this.source, this._uFlag, this.index, message);
631 }
632 eatRegExpBody() {
633 const start = this.index;
634 let inClass = false;
635 let escaped = false;
636 for (;;) {
637 const cp = this.currentCodePoint;
638 if (cp === -1 || isLineTerminator(cp)) {
639 const kind = inClass ? "character class" : "regular expression";
640 this.raise(`Unterminated ${kind}`);
641 }
642 if (escaped) {
643 escaped = false;
644 }
645 else if (cp === ReverseSolidus) {
646 escaped = true;
647 }
648 else if (cp === LeftSquareBracket) {
649 inClass = true;
650 }
651 else if (cp === RightSquareBracket) {
652 inClass = false;
653 }
654 else if ((cp === Solidus && !inClass) ||
655 (cp === Asterisk && this.index === start)) {
656 break;
657 }
658 this.advance();
659 }
660 return this.index !== start;
661 }
Tim van der Lippe16aca392020-11-13 11:37:13 +0000662 consumePattern() {
Yang Guo4fd355c2019-09-19 10:59:03 +0200663 const start = this.index;
664 this._numCapturingParens = this.countCapturingParens();
665 this._groupNames.clear();
666 this._backreferenceNames.clear();
667 this.onPatternEnter(start);
Tim van der Lippe16aca392020-11-13 11:37:13 +0000668 this.consumeDisjunction();
Yang Guo4fd355c2019-09-19 10:59:03 +0200669 const cp = this.currentCodePoint;
670 if (this.currentCodePoint !== -1) {
671 if (cp === RightParenthesis) {
672 this.raise("Unmatched ')'");
673 }
674 if (cp === ReverseSolidus) {
675 this.raise("\\ at end of pattern");
676 }
677 if (cp === RightSquareBracket || cp === RightCurlyBracket) {
678 this.raise("Lone quantifier brackets");
679 }
680 const c = String.fromCodePoint(cp);
681 this.raise(`Unexpected character '${c}'`);
682 }
683 for (const name of this._backreferenceNames) {
684 if (!this._groupNames.has(name)) {
685 this.raise("Invalid named capture referenced");
686 }
687 }
688 this.onPatternLeave(start, this.index);
689 }
690 countCapturingParens() {
691 const start = this.index;
692 let inClass = false;
693 let escaped = false;
694 let count = 0;
695 let cp = 0;
696 while ((cp = this.currentCodePoint) !== -1) {
697 if (escaped) {
698 escaped = false;
699 }
700 else if (cp === ReverseSolidus) {
701 escaped = true;
702 }
703 else if (cp === LeftSquareBracket) {
704 inClass = true;
705 }
706 else if (cp === RightSquareBracket) {
707 inClass = false;
708 }
709 else if (cp === LeftParenthesis &&
710 !inClass &&
711 (this.nextCodePoint !== QuestionMark ||
712 (this.nextCodePoint2 === LessThanSign &&
713 this.nextCodePoint3 !== EqualsSign &&
714 this.nextCodePoint3 !== ExclamationMark))) {
715 count += 1;
716 }
717 this.advance();
718 }
719 this.rewind(start);
720 return count;
721 }
Tim van der Lippe16aca392020-11-13 11:37:13 +0000722 consumeDisjunction() {
Yang Guo4fd355c2019-09-19 10:59:03 +0200723 const start = this.index;
724 let i = 0;
725 this.onDisjunctionEnter(start);
Tim van der Lippe16aca392020-11-13 11:37:13 +0000726 do {
727 this.consumeAlternative(i++);
728 } while (this.eat(VerticalLine));
729 if (this.consumeQuantifier(true)) {
Yang Guo4fd355c2019-09-19 10:59:03 +0200730 this.raise("Nothing to repeat");
731 }
732 if (this.eat(LeftCurlyBracket)) {
733 this.raise("Lone quantifier brackets");
734 }
735 this.onDisjunctionLeave(start, this.index);
736 }
Tim van der Lippe16aca392020-11-13 11:37:13 +0000737 consumeAlternative(i) {
Yang Guo4fd355c2019-09-19 10:59:03 +0200738 const start = this.index;
739 this.onAlternativeEnter(start, i);
Tim van der Lippe16aca392020-11-13 11:37:13 +0000740 while (this.currentCodePoint !== -1 && this.consumeTerm()) {
Yang Guo4fd355c2019-09-19 10:59:03 +0200741 }
742 this.onAlternativeLeave(start, this.index, i);
743 }
Tim van der Lippe16aca392020-11-13 11:37:13 +0000744 consumeTerm() {
745 if (this._uFlag || this.strict) {
746 return (this.consumeAssertion() ||
747 (this.consumeAtom() && this.consumeOptionalQuantifier()));
Yang Guo4fd355c2019-09-19 10:59:03 +0200748 }
Tim van der Lippe16aca392020-11-13 11:37:13 +0000749 return ((this.consumeAssertion() &&
750 (!this._lastAssertionIsQuantifiable ||
751 this.consumeOptionalQuantifier())) ||
752 (this.consumeExtendedAtom() && this.consumeOptionalQuantifier()));
Yang Guo4fd355c2019-09-19 10:59:03 +0200753 }
Tim van der Lippe16aca392020-11-13 11:37:13 +0000754 consumeOptionalQuantifier() {
755 this.consumeQuantifier();
756 return true;
757 }
758 consumeAssertion() {
Yang Guo4fd355c2019-09-19 10:59:03 +0200759 const start = this.index;
760 this._lastAssertionIsQuantifiable = false;
761 if (this.eat(CircumflexAccent)) {
762 this.onEdgeAssertion(start, this.index, "start");
763 return true;
764 }
765 if (this.eat(DollarSign)) {
766 this.onEdgeAssertion(start, this.index, "end");
767 return true;
768 }
769 if (this.eat2(ReverseSolidus, LatinCapitalLetterB)) {
770 this.onWordBoundaryAssertion(start, this.index, "word", true);
771 return true;
772 }
773 if (this.eat2(ReverseSolidus, LatinSmallLetterB)) {
774 this.onWordBoundaryAssertion(start, this.index, "word", false);
775 return true;
776 }
777 if (this.eat2(LeftParenthesis, QuestionMark)) {
778 const lookbehind = this.ecmaVersion >= 2018 && this.eat(LessThanSign);
779 let negate = false;
780 if (this.eat(EqualsSign) || (negate = this.eat(ExclamationMark))) {
781 const kind = lookbehind ? "lookbehind" : "lookahead";
782 this.onLookaroundAssertionEnter(start, kind, negate);
Tim van der Lippe16aca392020-11-13 11:37:13 +0000783 this.consumeDisjunction();
Yang Guo4fd355c2019-09-19 10:59:03 +0200784 if (!this.eat(RightParenthesis)) {
785 this.raise("Unterminated group");
786 }
787 this._lastAssertionIsQuantifiable = !lookbehind && !this.strict;
788 this.onLookaroundAssertionLeave(start, this.index, kind, negate);
789 return true;
790 }
791 this.rewind(start);
792 }
793 return false;
794 }
Tim van der Lippe16aca392020-11-13 11:37:13 +0000795 consumeQuantifier(noConsume = false) {
Yang Guo4fd355c2019-09-19 10:59:03 +0200796 const start = this.index;
797 let min = 0;
798 let max = 0;
799 let greedy = false;
800 if (this.eat(Asterisk)) {
801 min = 0;
802 max = Number.POSITIVE_INFINITY;
803 }
804 else if (this.eat(PlusSign)) {
805 min = 1;
806 max = Number.POSITIVE_INFINITY;
807 }
808 else if (this.eat(QuestionMark)) {
809 min = 0;
810 max = 1;
811 }
Tim van der Lippe16aca392020-11-13 11:37:13 +0000812 else if (this.eatBracedQuantifier(noConsume)) {
Yang Guo4fd355c2019-09-19 10:59:03 +0200813 min = this._lastMinValue;
814 max = this._lastMaxValue;
815 }
816 else {
817 return false;
818 }
819 greedy = !this.eat(QuestionMark);
Tim van der Lippe16aca392020-11-13 11:37:13 +0000820 if (!noConsume) {
Yang Guo4fd355c2019-09-19 10:59:03 +0200821 this.onQuantifier(start, this.index, min, max, greedy);
822 }
823 return true;
824 }
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()
834 ? this._lastIntValue
835 : Number.POSITIVE_INFINITY;
836 }
837 if (this.eat(RightCurlyBracket)) {
838 if (!noError && this._lastMaxValue < this._lastMinValue) {
839 this.raise("numbers out of order in {} quantifier");
840 }
841 return true;
842 }
843 }
Tim van der Lippe16aca392020-11-13 11:37:13 +0000844 if (!noError && (this._uFlag || this.strict)) {
Yang Guo4fd355c2019-09-19 10:59:03 +0200845 this.raise("Incomplete quantifier");
846 }
847 this.rewind(start);
848 }
849 return false;
850 }
Tim van der Lippe16aca392020-11-13 11:37:13 +0000851 consumeAtom() {
852 return (this.consumePatternCharacter() ||
853 this.consumeDot() ||
854 this.consumeReverseSolidusAtomEscape() ||
855 this.consumeCharacterClass() ||
856 this.consumeUncapturingGroup() ||
857 this.consumeCapturingGroup());
Yang Guo4fd355c2019-09-19 10:59:03 +0200858 }
Tim van der Lippe16aca392020-11-13 11:37:13 +0000859 consumeDot() {
Yang Guo4fd355c2019-09-19 10:59:03 +0200860 if (this.eat(FullStop)) {
861 this.onAnyCharacterSet(this.index - 1, this.index, "any");
862 return true;
863 }
864 return false;
865 }
Tim van der Lippe16aca392020-11-13 11:37:13 +0000866 consumeReverseSolidusAtomEscape() {
Yang Guo4fd355c2019-09-19 10:59:03 +0200867 const start = this.index;
868 if (this.eat(ReverseSolidus)) {
Tim van der Lippe16aca392020-11-13 11:37:13 +0000869 if (this.consumeAtomEscape()) {
Yang Guo4fd355c2019-09-19 10:59:03 +0200870 return true;
871 }
872 this.rewind(start);
873 }
874 return false;
875 }
Tim van der Lippe16aca392020-11-13 11:37:13 +0000876 consumeUncapturingGroup() {
Yang Guo4fd355c2019-09-19 10:59:03 +0200877 const start = this.index;
878 if (this.eat3(LeftParenthesis, QuestionMark, Colon)) {
879 this.onGroupEnter(start);
Tim van der Lippe16aca392020-11-13 11:37:13 +0000880 this.consumeDisjunction();
Yang Guo4fd355c2019-09-19 10:59:03 +0200881 if (!this.eat(RightParenthesis)) {
882 this.raise("Unterminated group");
883 }
884 this.onGroupLeave(start, this.index);
885 return true;
886 }
887 return false;
888 }
Tim van der Lippe16aca392020-11-13 11:37:13 +0000889 consumeCapturingGroup() {
Yang Guo4fd355c2019-09-19 10:59:03 +0200890 const start = this.index;
891 if (this.eat(LeftParenthesis)) {
Tim van der Lippe16aca392020-11-13 11:37:13 +0000892 let name = null;
Yang Guo4fd355c2019-09-19 10:59:03 +0200893 if (this.ecmaVersion >= 2018) {
Tim van der Lippe16aca392020-11-13 11:37:13 +0000894 if (this.consumeGroupSpecifier()) {
895 name = this._lastStrValue;
896 }
Yang Guo4fd355c2019-09-19 10:59:03 +0200897 }
898 else if (this.currentCodePoint === QuestionMark) {
899 this.raise("Invalid group");
900 }
Yang Guo4fd355c2019-09-19 10:59:03 +0200901 this.onCapturingGroupEnter(start, name);
Tim van der Lippe16aca392020-11-13 11:37:13 +0000902 this.consumeDisjunction();
Yang Guo4fd355c2019-09-19 10:59:03 +0200903 if (!this.eat(RightParenthesis)) {
904 this.raise("Unterminated group");
905 }
906 this.onCapturingGroupLeave(start, this.index, name);
907 return true;
908 }
909 return false;
910 }
Tim van der Lippe16aca392020-11-13 11:37:13 +0000911 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());
Yang Guo4fd355c2019-09-19 10:59:03 +0200920 }
Tim van der Lippe16aca392020-11-13 11:37:13 +0000921 consumeReverseSolidusFollowedByC() {
922 const start = this.index;
Yang Guo4fd355c2019-09-19 10:59:03 +0200923 if (this.currentCodePoint === ReverseSolidus &&
924 this.nextCodePoint === LatinSmallLetterC) {
925 this._lastIntValue = this.currentCodePoint;
926 this.advance();
Tim van der Lippe16aca392020-11-13 11:37:13 +0000927 this.onCharacter(start, this.index, ReverseSolidus);
Yang Guo4fd355c2019-09-19 10:59:03 +0200928 return true;
929 }
930 return false;
931 }
Tim van der Lippe16aca392020-11-13 11:37:13 +0000932 consumeInvalidBracedQuantifier() {
Yang Guo4fd355c2019-09-19 10:59:03 +0200933 if (this.eatBracedQuantifier(true)) {
934 this.raise("Nothing to repeat");
935 }
936 return false;
937 }
Tim van der Lippe16aca392020-11-13 11:37:13 +0000938 consumePatternCharacter() {
Yang Guo4fd355c2019-09-19 10:59:03 +0200939 const start = this.index;
940 const cp = this.currentCodePoint;
941 if (cp !== -1 && !isSyntaxCharacter(cp)) {
942 this.advance();
943 this.onCharacter(start, this.index, cp);
944 return true;
945 }
946 return false;
947 }
Tim van der Lippe16aca392020-11-13 11:37:13 +0000948 consumeExtendedPatternCharacter() {
Yang Guo4fd355c2019-09-19 10:59:03 +0200949 const start = this.index;
950 const cp = this.currentCodePoint;
951 if (cp !== -1 &&
952 cp !== CircumflexAccent &&
953 cp !== DollarSign &&
954 cp !== ReverseSolidus &&
955 cp !== FullStop &&
956 cp !== Asterisk &&
957 cp !== PlusSign &&
958 cp !== QuestionMark &&
959 cp !== LeftParenthesis &&
960 cp !== RightParenthesis &&
961 cp !== LeftSquareBracket &&
962 cp !== VerticalLine) {
963 this.advance();
964 this.onCharacter(start, this.index, cp);
965 return true;
966 }
967 return false;
968 }
Tim van der Lippe16aca392020-11-13 11:37:13 +0000969 consumeGroupSpecifier() {
Yang Guo4fd355c2019-09-19 10:59:03 +0200970 if (this.eat(QuestionMark)) {
971 if (this.eatGroupName()) {
972 if (!this._groupNames.has(this._lastStrValue)) {
973 this._groupNames.add(this._lastStrValue);
Tim van der Lippe16aca392020-11-13 11:37:13 +0000974 return true;
Yang Guo4fd355c2019-09-19 10:59:03 +0200975 }
976 this.raise("Duplicate capture group name");
977 }
978 this.raise("Invalid group");
979 }
Yang Guo4fd355c2019-09-19 10:59:03 +0200980 return false;
981 }
Tim van der Lippe16aca392020-11-13 11:37:13 +0000982 consumeAtomEscape() {
983 if (this.consumeBackreference() ||
984 this.consumeCharacterClassEscape() ||
985 this.consumeCharacterEscape() ||
986 (this._nFlag && this.consumeKGroupName())) {
Yang Guo4fd355c2019-09-19 10:59:03 +0200987 return true;
988 }
989 if (this.strict || this._uFlag) {
990 this.raise("Invalid escape");
991 }
992 return false;
993 }
Tim van der Lippe16aca392020-11-13 11:37:13 +0000994 consumeBackreference() {
Yang Guo4fd355c2019-09-19 10:59:03 +0200995 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);
1000 return true;
1001 }
Tim van der Lippe16aca392020-11-13 11:37:13 +00001002 if (this.strict || this._uFlag) {
Yang Guo4fd355c2019-09-19 10:59:03 +02001003 this.raise("Invalid escape");
1004 }
1005 this.rewind(start);
1006 }
1007 return false;
1008 }
Tim van der Lippe16aca392020-11-13 11:37:13 +00001009 consumeCharacterClassEscape() {
Yang Guo4fd355c2019-09-19 10:59:03 +02001010 const start = this.index;
1011 if (this.eat(LatinSmallLetterD)) {
1012 this._lastIntValue = -1;
1013 this.onEscapeCharacterSet(start - 1, this.index, "digit", false);
1014 return true;
1015 }
1016 if (this.eat(LatinCapitalLetterD)) {
1017 this._lastIntValue = -1;
1018 this.onEscapeCharacterSet(start - 1, this.index, "digit", true);
1019 return true;
1020 }
1021 if (this.eat(LatinSmallLetterS)) {
1022 this._lastIntValue = -1;
1023 this.onEscapeCharacterSet(start - 1, this.index, "space", false);
1024 return true;
1025 }
1026 if (this.eat(LatinCapitalLetterS)) {
1027 this._lastIntValue = -1;
1028 this.onEscapeCharacterSet(start - 1, this.index, "space", true);
1029 return true;
1030 }
1031 if (this.eat(LatinSmallLetterW)) {
1032 this._lastIntValue = -1;
1033 this.onEscapeCharacterSet(start - 1, this.index, "word", false);
1034 return true;
1035 }
1036 if (this.eat(LatinCapitalLetterW)) {
1037 this._lastIntValue = -1;
1038 this.onEscapeCharacterSet(start - 1, this.index, "word", true);
1039 return true;
1040 }
1041 let negate = false;
1042 if (this._uFlag &&
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);
1051 return true;
1052 }
1053 this.raise("Invalid property name");
1054 }
1055 return false;
1056 }
Tim van der Lippe16aca392020-11-13 11:37:13 +00001057 consumeCharacterEscape() {
1058 const start = this.index;
1059 if (this.eatControlEscape() ||
1060 this.eatCControlLetter() ||
1061 this.eatZero() ||
1062 this.eatHexEscapeSequence() ||
1063 this.eatRegExpUnicodeEscapeSequence() ||
1064 (!this.strict &&
1065 !this._uFlag &&
1066 this.eatLegacyOctalEscapeSequence()) ||
1067 this.eatIdentityEscape()) {
1068 this.onCharacter(start - 1, this.index, this._lastIntValue);
1069 return true;
1070 }
1071 return false;
1072 }
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);
1080 return true;
1081 }
1082 this.raise("Invalid named reference");
1083 }
1084 return false;
1085 }
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");
1094 }
1095 this.onCharacterClassLeave(start, this.index, negate);
1096 return true;
1097 }
1098 return false;
1099 }
1100 consumeClassRanges() {
1101 const strict = this.strict || this._uFlag;
1102 for (;;) {
1103 const rangeStart = this.index;
1104 if (!this.consumeClassAtom()) {
1105 break;
1106 }
1107 const min = this._lastIntValue;
1108 if (!this.eat(HyphenMinus)) {
1109 continue;
1110 }
1111 this.onCharacter(this.index - 1, this.index, HyphenMinus);
1112 if (!this.consumeClassAtom()) {
1113 break;
1114 }
1115 const max = this._lastIntValue;
1116 if (min === -1 || max === -1) {
1117 if (strict) {
1118 this.raise("Invalid character class");
1119 }
1120 continue;
1121 }
1122 if (min > max) {
1123 this.raise("Range out of order in character class");
1124 }
1125 this.onCharacterClassRange(rangeStart, this.index, min, max);
1126 }
1127 }
1128 consumeClassAtom() {
1129 const start = this.index;
1130 const cp = this.currentCodePoint;
1131 if (cp !== -1 && cp !== ReverseSolidus && cp !== RightSquareBracket) {
1132 this.advance();
1133 this._lastIntValue = cp;
1134 this.onCharacter(start, this.index, this._lastIntValue);
1135 return true;
1136 }
1137 if (this.eat(ReverseSolidus)) {
1138 if (this.consumeClassEscape()) {
1139 return true;
1140 }
1141 if (!this.strict && this.currentCodePoint === LatinSmallLetterC) {
1142 this._lastIntValue = ReverseSolidus;
1143 this.onCharacter(start, this.index, this._lastIntValue);
1144 return true;
1145 }
1146 if (this.strict || this._uFlag) {
1147 this.raise("Invalid escape");
1148 }
1149 this.rewind(start);
1150 }
1151 return false;
1152 }
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);
1158 return true;
1159 }
1160 if (this._uFlag && this.eat(HyphenMinus)) {
1161 this._lastIntValue = HyphenMinus;
1162 this.onCharacter(start - 1, this.index, this._lastIntValue);
1163 return true;
1164 }
1165 let cp = 0;
1166 if (!this.strict &&
1167 !this._uFlag &&
1168 this.currentCodePoint === LatinSmallLetterC &&
1169 (isDecimalDigit((cp = this.nextCodePoint)) || cp === LowLine)) {
1170 this.advance();
1171 this.advance();
1172 this._lastIntValue = cp % 0x20;
1173 this.onCharacter(start - 1, this.index, this._lastIntValue);
1174 return true;
1175 }
1176 return (this.consumeCharacterClassEscape() || this.consumeCharacterEscape());
1177 }
1178 eatGroupName() {
1179 if (this.eat(LessThanSign)) {
1180 if (this.eatRegExpIdentifierName() && this.eat(GreaterThanSign)) {
1181 return true;
1182 }
1183 this.raise("Invalid capture group name");
1184 }
1185 return false;
1186 }
1187 eatRegExpIdentifierName() {
1188 if (this.eatRegExpIdentifierStart()) {
1189 this._lastStrValue = String.fromCodePoint(this._lastIntValue);
1190 while (this.eatRegExpIdentifierPart()) {
1191 this._lastStrValue += String.fromCodePoint(this._lastIntValue);
1192 }
1193 return true;
1194 }
1195 return false;
1196 }
1197 eatRegExpIdentifierStart() {
1198 const start = this.index;
1199 const forceUFlag = !this._uFlag && this.ecmaVersion >= 2020;
1200 let cp = this.currentCodePoint;
1201 this.advance();
1202 if (cp === ReverseSolidus &&
1203 this.eatRegExpUnicodeEscapeSequence(forceUFlag)) {
1204 cp = this._lastIntValue;
1205 }
1206 else if (forceUFlag &&
1207 isLeadSurrogate(cp) &&
1208 isTrailSurrogate(this.currentCodePoint)) {
1209 cp = combineSurrogatePair(cp, this.currentCodePoint);
1210 this.advance();
1211 }
1212 if (isRegExpIdentifierStart(cp)) {
1213 this._lastIntValue = cp;
1214 return true;
1215 }
1216 if (this.index !== start) {
1217 this.rewind(start);
1218 }
1219 return false;
1220 }
1221 eatRegExpIdentifierPart() {
1222 const start = this.index;
1223 const forceUFlag = !this._uFlag && this.ecmaVersion >= 2020;
1224 let cp = this.currentCodePoint;
1225 this.advance();
1226 if (cp === ReverseSolidus &&
1227 this.eatRegExpUnicodeEscapeSequence(forceUFlag)) {
1228 cp = this._lastIntValue;
1229 }
1230 else if (forceUFlag &&
1231 isLeadSurrogate(cp) &&
1232 isTrailSurrogate(this.currentCodePoint)) {
1233 cp = combineSurrogatePair(cp, this.currentCodePoint);
1234 this.advance();
1235 }
1236 if (isRegExpIdentifierPart(cp)) {
1237 this._lastIntValue = cp;
1238 return true;
1239 }
1240 if (this.index !== start) {
1241 this.rewind(start);
1242 }
1243 return false;
1244 }
1245 eatCControlLetter() {
1246 const start = this.index;
1247 if (this.eat(LatinSmallLetterC)) {
1248 if (this.eatControlLetter()) {
1249 return true;
1250 }
1251 this.rewind(start);
1252 }
1253 return false;
1254 }
1255 eatZero() {
1256 if (this.currentCodePoint === DigitZero &&
1257 !isDecimalDigit(this.nextCodePoint)) {
1258 this._lastIntValue = 0;
1259 this.advance();
1260 return true;
1261 }
1262 return false;
1263 }
1264 eatControlEscape() {
1265 if (this.eat(LatinSmallLetterF)) {
1266 this._lastIntValue = FormFeed;
1267 return true;
1268 }
1269 if (this.eat(LatinSmallLetterN)) {
1270 this._lastIntValue = LineFeed;
1271 return true;
1272 }
1273 if (this.eat(LatinSmallLetterR)) {
1274 this._lastIntValue = CarriageReturn;
1275 return true;
1276 }
1277 if (this.eat(LatinSmallLetterT)) {
1278 this._lastIntValue = CharacterTabulation;
1279 return true;
1280 }
1281 if (this.eat(LatinSmallLetterV)) {
1282 this._lastIntValue = LineTabulation;
1283 return true;
1284 }
1285 return false;
1286 }
1287 eatControlLetter() {
1288 const cp = this.currentCodePoint;
1289 if (isLatinLetter(cp)) {
1290 this.advance();
1291 this._lastIntValue = cp % 0x20;
1292 return true;
1293 }
1294 return false;
1295 }
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())) {
1303 return true;
1304 }
1305 if (this.strict || uFlag) {
1306 this.raise("Invalid unicode escape");
1307 }
1308 this.rewind(start);
1309 }
1310 return false;
1311 }
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);
1323 return true;
1324 }
1325 }
1326 this.rewind(start);
1327 }
1328 return false;
1329 }
1330 eatRegExpUnicodeCodePointEscape() {
1331 const start = this.index;
1332 if (this.eat(LeftCurlyBracket) &&
1333 this.eatHexDigits() &&
1334 this.eat(RightCurlyBracket) &&
1335 isValidUnicode(this._lastIntValue)) {
1336 return true;
1337 }
1338 this.rewind(start);
1339 return false;
1340 }
1341 eatIdentityEscape() {
1342 const cp = this.currentCodePoint;
1343 if (this.isValidIdentityEscape(cp)) {
1344 this._lastIntValue = cp;
1345 this.advance();
1346 return true;
1347 }
1348 return false;
1349 }
1350 isValidIdentityEscape(cp) {
1351 if (cp === -1) {
1352 return false;
1353 }
1354 if (this._uFlag) {
1355 return isSyntaxCharacter(cp) || cp === Solidus;
1356 }
1357 if (this.strict) {
1358 return !isIdContinue(cp);
1359 }
1360 if (this._nFlag) {
1361 return !(cp === LatinSmallLetterC || cp === LatinSmallLetterK);
1362 }
1363 return cp !== LatinSmallLetterC;
1364 }
1365 eatDecimalEscape() {
1366 this._lastIntValue = 0;
1367 let cp = this.currentCodePoint;
1368 if (cp >= DigitOne && cp <= DigitNine) {
1369 do {
1370 this._lastIntValue = 10 * this._lastIntValue + (cp - DigitZero);
1371 this.advance();
1372 } while ((cp = this.currentCodePoint) >= DigitZero &&
1373 cp <= DigitNine);
1374 return true;
1375 }
1376 return false;
1377 }
Yang Guo4fd355c2019-09-19 10:59:03 +02001378 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;
Tim van der Lippe16aca392020-11-13 11:37:13 +00001384 if (isValidUnicodeProperty(this.ecmaVersion, this._lastKeyValue, this._lastValValue)) {
Yang Guo4fd355c2019-09-19 10:59:03 +02001385 return true;
1386 }
1387 this.raise("Invalid property name");
1388 }
1389 }
1390 this.rewind(start);
1391 if (this.eatLoneUnicodePropertyNameOrValue()) {
1392 const nameOrValue = this._lastStrValue;
Tim van der Lippe16aca392020-11-13 11:37:13 +00001393 if (isValidUnicodeProperty(this.ecmaVersion, "General_Category", nameOrValue)) {
Yang Guo4fd355c2019-09-19 10:59:03 +02001394 this._lastKeyValue = "General_Category";
1395 this._lastValValue = nameOrValue;
1396 return true;
1397 }
Tim van der Lippe16aca392020-11-13 11:37:13 +00001398 if (isValidLoneUnicodeProperty(this.ecmaVersion, nameOrValue)) {
Yang Guo4fd355c2019-09-19 10:59:03 +02001399 this._lastKeyValue = nameOrValue;
1400 this._lastValValue = "";
1401 return true;
1402 }
1403 this.raise("Invalid property name");
1404 }
1405 return false;
1406 }
1407 eatUnicodePropertyName() {
1408 this._lastStrValue = "";
1409 while (isUnicodePropertyNameCharacter(this.currentCodePoint)) {
1410 this._lastStrValue += String.fromCodePoint(this.currentCodePoint);
1411 this.advance();
1412 }
1413 return this._lastStrValue !== "";
1414 }
1415 eatUnicodePropertyValue() {
1416 this._lastStrValue = "";
1417 while (isUnicodePropertyValueCharacter(this.currentCodePoint)) {
1418 this._lastStrValue += String.fromCodePoint(this.currentCodePoint);
1419 this.advance();
1420 }
1421 return this._lastStrValue !== "";
1422 }
1423 eatLoneUnicodePropertyNameOrValue() {
1424 return this.eatUnicodePropertyValue();
1425 }
Yang Guo4fd355c2019-09-19 10:59:03 +02001426 eatHexEscapeSequence() {
1427 const start = this.index;
1428 if (this.eat(LatinSmallLetterX)) {
1429 if (this.eatFixedHexDigits(2)) {
1430 return true;
1431 }
Tim van der Lippe16aca392020-11-13 11:37:13 +00001432 if (this._uFlag || this.strict) {
Yang Guo4fd355c2019-09-19 10:59:03 +02001433 this.raise("Invalid escape");
1434 }
1435 this.rewind(start);
1436 }
1437 return false;
1438 }
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);
1445 this.advance();
1446 }
1447 return this.index !== start;
1448 }
1449 eatHexDigits() {
1450 const start = this.index;
1451 this._lastIntValue = 0;
1452 while (isHexDigit(this.currentCodePoint)) {
1453 this._lastIntValue =
1454 16 * this._lastIntValue + digitToInt(this.currentCodePoint);
1455 this.advance();
1456 }
1457 return this.index !== start;
1458 }
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;
1466 }
1467 else {
1468 this._lastIntValue = n1 * 8 + n2;
1469 }
1470 }
1471 else {
1472 this._lastIntValue = n1;
1473 }
1474 return true;
1475 }
1476 return false;
1477 }
1478 eatOctalDigit() {
1479 const cp = this.currentCodePoint;
1480 if (isOctalDigit(cp)) {
1481 this.advance();
1482 this._lastIntValue = cp - DigitZero;
1483 return true;
1484 }
1485 this._lastIntValue = 0;
1486 return false;
1487 }
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)) {
1494 this.rewind(start);
1495 return false;
1496 }
1497 this._lastIntValue = 16 * this._lastIntValue + digitToInt(cp);
1498 this.advance();
1499 }
1500 return true;
1501 }
1502}
1503
1504const DummyPattern = {};
1505const DummyFlags = {};
1506const DummyCapturingGroup = {};
1507class RegExpParserState {
1508 constructor(options) {
1509 this._node = DummyPattern;
1510 this._flags = DummyFlags;
1511 this._backreferences = [];
1512 this._capturingGroups = [];
1513 this.source = "";
1514 this.strict = Boolean(options && options.strict);
Tim van der Lippe16aca392020-11-13 11:37:13 +00001515 this.ecmaVersion = (options && options.ecmaVersion) || 2020;
Yang Guo4fd355c2019-09-19 10:59:03 +02001516 }
1517 get pattern() {
1518 if (this._node.type !== "Pattern") {
1519 throw new Error("UnknownError");
1520 }
1521 return this._node;
1522 }
1523 get flags() {
1524 if (this._flags.type !== "Flags") {
1525 throw new Error("UnknownError");
1526 }
1527 return this._flags;
1528 }
1529 onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll) {
1530 this._flags = {
1531 type: "Flags",
1532 parent: null,
1533 start,
1534 end,
1535 raw: this.source.slice(start, end),
1536 global,
1537 ignoreCase,
1538 multiline,
1539 unicode,
1540 sticky,
1541 dotAll,
1542 };
1543 }
1544 onPatternEnter(start) {
1545 this._node = {
1546 type: "Pattern",
1547 parent: null,
1548 start,
1549 end: start,
1550 raw: "",
1551 alternatives: [],
1552 };
1553 this._backreferences.length = 0;
1554 this._capturingGroups.length = 0;
1555 }
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);
1566 }
1567 }
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");
1575 }
1576 this._node = {
1577 type: "Alternative",
1578 parent,
1579 start,
1580 end: start,
1581 raw: "",
1582 elements: [],
1583 };
1584 parent.alternatives.push(this._node);
1585 }
1586 onAlternativeLeave(start, end) {
1587 const node = this._node;
1588 if (node.type !== "Alternative") {
1589 throw new Error("UnknownError");
1590 }
1591 node.end = end;
1592 node.raw = this.source.slice(start, end);
1593 this._node = node.parent;
1594 }
1595 onGroupEnter(start) {
1596 const parent = this._node;
1597 if (parent.type !== "Alternative") {
1598 throw new Error("UnknownError");
1599 }
1600 this._node = {
1601 type: "Group",
1602 parent,
1603 start,
1604 end: start,
1605 raw: "",
1606 alternatives: [],
1607 };
1608 parent.elements.push(this._node);
1609 }
1610 onGroupLeave(start, end) {
1611 const node = this._node;
1612 if (node.type !== "Group" || node.parent.type !== "Alternative") {
1613 throw new Error("UnknownError");
1614 }
1615 node.end = end;
1616 node.raw = this.source.slice(start, end);
1617 this._node = node.parent;
1618 }
1619 onCapturingGroupEnter(start, name) {
1620 const parent = this._node;
1621 if (parent.type !== "Alternative") {
1622 throw new Error("UnknownError");
1623 }
1624 this._node = {
1625 type: "CapturingGroup",
1626 parent,
1627 start,
1628 end: start,
1629 raw: "",
1630 name,
1631 alternatives: [],
1632 references: [],
1633 };
1634 parent.elements.push(this._node);
1635 this._capturingGroups.push(this._node);
1636 }
1637 onCapturingGroupLeave(start, end) {
1638 const node = this._node;
1639 if (node.type !== "CapturingGroup" ||
1640 node.parent.type !== "Alternative") {
1641 throw new Error("UnknownError");
1642 }
1643 node.end = end;
1644 node.raw = this.source.slice(start, end);
1645 this._node = node.parent;
1646 }
1647 onQuantifier(start, end, min, max, greedy) {
1648 const parent = this._node;
1649 if (parent.type !== "Alternative") {
1650 throw new Error("UnknownError");
1651 }
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");
1657 }
1658 const node = {
1659 type: "Quantifier",
1660 parent,
1661 start: element.start,
1662 end,
1663 raw: this.source.slice(element.start, end),
1664 min,
1665 max,
1666 greedy,
1667 element,
1668 };
1669 parent.elements.push(node);
1670 element.parent = node;
1671 }
1672 onLookaroundAssertionEnter(start, kind, negate) {
1673 const parent = this._node;
1674 if (parent.type !== "Alternative") {
1675 throw new Error("UnknownError");
1676 }
Tim van der Lippe16aca392020-11-13 11:37:13 +00001677 const node = (this._node = {
Yang Guo4fd355c2019-09-19 10:59:03 +02001678 type: "Assertion",
1679 parent,
1680 start,
1681 end: start,
1682 raw: "",
1683 kind,
1684 negate,
1685 alternatives: [],
Tim van der Lippe16aca392020-11-13 11:37:13 +00001686 });
1687 parent.elements.push(node);
Yang Guo4fd355c2019-09-19 10:59:03 +02001688 }
1689 onLookaroundAssertionLeave(start, end) {
1690 const node = this._node;
1691 if (node.type !== "Assertion" || node.parent.type !== "Alternative") {
1692 throw new Error("UnknownError");
1693 }
1694 node.end = end;
1695 node.raw = this.source.slice(start, end);
1696 this._node = node.parent;
1697 }
1698 onEdgeAssertion(start, end, kind) {
1699 const parent = this._node;
1700 if (parent.type !== "Alternative") {
1701 throw new Error("UnknownError");
1702 }
1703 parent.elements.push({
1704 type: "Assertion",
1705 parent,
1706 start,
1707 end,
1708 raw: this.source.slice(start, end),
1709 kind,
1710 });
1711 }
1712 onWordBoundaryAssertion(start, end, kind, negate) {
1713 const parent = this._node;
1714 if (parent.type !== "Alternative") {
1715 throw new Error("UnknownError");
1716 }
1717 parent.elements.push({
1718 type: "Assertion",
1719 parent,
1720 start,
1721 end,
1722 raw: this.source.slice(start, end),
1723 kind,
1724 negate,
1725 });
1726 }
1727 onAnyCharacterSet(start, end, kind) {
1728 const parent = this._node;
1729 if (parent.type !== "Alternative") {
1730 throw new Error("UnknownError");
1731 }
1732 parent.elements.push({
1733 type: "CharacterSet",
1734 parent,
1735 start,
1736 end,
1737 raw: this.source.slice(start, end),
1738 kind,
1739 });
1740 }
1741 onEscapeCharacterSet(start, end, kind, negate) {
1742 const parent = this._node;
1743 if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
1744 throw new Error("UnknownError");
1745 }
1746 parent.elements.push({
1747 type: "CharacterSet",
1748 parent,
1749 start,
1750 end,
1751 raw: this.source.slice(start, end),
1752 kind,
1753 negate,
1754 });
1755 }
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");
1760 }
1761 parent.elements.push({
1762 type: "CharacterSet",
1763 parent,
1764 start,
1765 end,
1766 raw: this.source.slice(start, end),
1767 kind,
1768 key,
1769 value,
1770 negate,
1771 });
1772 }
1773 onCharacter(start, end, value) {
1774 const parent = this._node;
1775 if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
1776 throw new Error("UnknownError");
1777 }
1778 parent.elements.push({
1779 type: "Character",
1780 parent,
1781 start,
1782 end,
1783 raw: this.source.slice(start, end),
1784 value,
1785 });
1786 }
1787 onBackreference(start, end, ref) {
1788 const parent = this._node;
1789 if (parent.type !== "Alternative") {
1790 throw new Error("UnknownError");
1791 }
1792 const node = {
1793 type: "Backreference",
1794 parent,
1795 start,
1796 end,
1797 raw: this.source.slice(start, end),
1798 ref,
1799 resolved: DummyCapturingGroup,
1800 };
1801 parent.elements.push(node);
1802 this._backreferences.push(node);
1803 }
1804 onCharacterClassEnter(start, negate) {
1805 const parent = this._node;
1806 if (parent.type !== "Alternative") {
1807 throw new Error("UnknownError");
1808 }
1809 this._node = {
1810 type: "CharacterClass",
1811 parent,
1812 start,
1813 end: start,
1814 raw: "",
1815 negate,
1816 elements: [],
1817 };
1818 parent.elements.push(this._node);
1819 }
1820 onCharacterClassLeave(start, end) {
1821 const node = this._node;
1822 if (node.type !== "CharacterClass" ||
1823 node.parent.type !== "Alternative") {
1824 throw new Error("UnknownError");
1825 }
1826 node.end = end;
1827 node.raw = this.source.slice(start, end);
1828 this._node = node.parent;
1829 }
1830 onCharacterClassRange(start, end) {
1831 const parent = this._node;
1832 if (parent.type !== "CharacterClass") {
1833 throw new Error("UnknownError");
1834 }
1835 const elements = parent.elements;
1836 const max = elements.pop();
1837 const hyphen = elements.pop();
1838 const min = elements.pop();
1839 if (!min ||
1840 !max ||
1841 !hyphen ||
1842 min.type !== "Character" ||
1843 max.type !== "Character" ||
1844 hyphen.type !== "Character" ||
1845 hyphen.value !== HyphenMinus) {
1846 throw new Error("UnknownError");
1847 }
1848 const node = {
1849 type: "CharacterClassRange",
1850 parent,
1851 start,
1852 end,
1853 raw: this.source.slice(start, end),
1854 min,
1855 max,
1856 };
1857 min.parent = node;
1858 max.parent = node;
1859 elements.push(node);
1860 }
1861}
1862class RegExpParser {
1863 constructor(options) {
1864 this._state = new RegExpParserState(options);
1865 this._validator = new RegExpValidator(this._state);
1866 }
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;
1872 const literal = {
1873 type: "RegExpLiteral",
1874 parent: null,
1875 start,
1876 end,
1877 raw: source,
1878 pattern,
1879 flags,
1880 };
1881 pattern.parent = literal;
1882 flags.parent = literal;
1883 return literal;
1884 }
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;
1889 }
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;
1894 }
1895}
1896
1897class RegExpVisitor {
1898 constructor(handlers) {
1899 this._handlers = handlers;
1900 }
1901 visit(node) {
1902 switch (node.type) {
1903 case "Alternative":
1904 this.visitAlternative(node);
1905 break;
1906 case "Assertion":
1907 this.visitAssertion(node);
1908 break;
1909 case "Backreference":
1910 this.visitBackreference(node);
1911 break;
1912 case "CapturingGroup":
1913 this.visitCapturingGroup(node);
1914 break;
1915 case "Character":
1916 this.visitCharacter(node);
1917 break;
1918 case "CharacterClass":
1919 this.visitCharacterClass(node);
1920 break;
1921 case "CharacterClassRange":
1922 this.visitCharacterClassRange(node);
1923 break;
1924 case "CharacterSet":
1925 this.visitCharacterSet(node);
1926 break;
1927 case "Flags":
1928 this.visitFlags(node);
1929 break;
1930 case "Group":
1931 this.visitGroup(node);
1932 break;
1933 case "Pattern":
1934 this.visitPattern(node);
1935 break;
1936 case "Quantifier":
1937 this.visitQuantifier(node);
1938 break;
1939 case "RegExpLiteral":
1940 this.visitRegExpLiteral(node);
1941 break;
1942 default:
1943 throw new Error(`Unknown type: ${node.type}`);
1944 }
1945 }
1946 visitAlternative(node) {
1947 if (this._handlers.onAlternativeEnter) {
1948 this._handlers.onAlternativeEnter(node);
1949 }
1950 node.elements.forEach(this.visit, this);
1951 if (this._handlers.onAlternativeLeave) {
1952 this._handlers.onAlternativeLeave(node);
1953 }
1954 }
1955 visitAssertion(node) {
1956 if (this._handlers.onAssertionEnter) {
1957 this._handlers.onAssertionEnter(node);
1958 }
1959 if (node.kind === "lookahead" || node.kind === "lookbehind") {
1960 node.alternatives.forEach(this.visit, this);
1961 }
1962 if (this._handlers.onAssertionLeave) {
1963 this._handlers.onAssertionLeave(node);
1964 }
1965 }
1966 visitBackreference(node) {
1967 if (this._handlers.onBackreferenceEnter) {
1968 this._handlers.onBackreferenceEnter(node);
1969 }
1970 if (this._handlers.onBackreferenceLeave) {
1971 this._handlers.onBackreferenceLeave(node);
1972 }
1973 }
1974 visitCapturingGroup(node) {
1975 if (this._handlers.onCapturingGroupEnter) {
1976 this._handlers.onCapturingGroupEnter(node);
1977 }
1978 node.alternatives.forEach(this.visit, this);
1979 if (this._handlers.onCapturingGroupLeave) {
1980 this._handlers.onCapturingGroupLeave(node);
1981 }
1982 }
1983 visitCharacter(node) {
1984 if (this._handlers.onCharacterEnter) {
1985 this._handlers.onCharacterEnter(node);
1986 }
1987 if (this._handlers.onCharacterLeave) {
1988 this._handlers.onCharacterLeave(node);
1989 }
1990 }
1991 visitCharacterClass(node) {
1992 if (this._handlers.onCharacterClassEnter) {
1993 this._handlers.onCharacterClassEnter(node);
1994 }
1995 node.elements.forEach(this.visit, this);
1996 if (this._handlers.onCharacterClassLeave) {
1997 this._handlers.onCharacterClassLeave(node);
1998 }
1999 }
2000 visitCharacterClassRange(node) {
2001 if (this._handlers.onCharacterClassRangeEnter) {
2002 this._handlers.onCharacterClassRangeEnter(node);
2003 }
2004 this.visitCharacter(node.min);
2005 this.visitCharacter(node.max);
2006 if (this._handlers.onCharacterClassRangeLeave) {
2007 this._handlers.onCharacterClassRangeLeave(node);
2008 }
2009 }
2010 visitCharacterSet(node) {
2011 if (this._handlers.onCharacterSetEnter) {
2012 this._handlers.onCharacterSetEnter(node);
2013 }
2014 if (this._handlers.onCharacterSetLeave) {
2015 this._handlers.onCharacterSetLeave(node);
2016 }
2017 }
2018 visitFlags(node) {
2019 if (this._handlers.onFlagsEnter) {
2020 this._handlers.onFlagsEnter(node);
2021 }
2022 if (this._handlers.onFlagsLeave) {
2023 this._handlers.onFlagsLeave(node);
2024 }
2025 }
2026 visitGroup(node) {
2027 if (this._handlers.onGroupEnter) {
2028 this._handlers.onGroupEnter(node);
2029 }
2030 node.alternatives.forEach(this.visit, this);
2031 if (this._handlers.onGroupLeave) {
2032 this._handlers.onGroupLeave(node);
2033 }
2034 }
2035 visitPattern(node) {
2036 if (this._handlers.onPatternEnter) {
2037 this._handlers.onPatternEnter(node);
2038 }
2039 node.alternatives.forEach(this.visit, this);
2040 if (this._handlers.onPatternLeave) {
2041 this._handlers.onPatternLeave(node);
2042 }
2043 }
2044 visitQuantifier(node) {
2045 if (this._handlers.onQuantifierEnter) {
2046 this._handlers.onQuantifierEnter(node);
2047 }
2048 this.visit(node.element);
2049 if (this._handlers.onQuantifierLeave) {
2050 this._handlers.onQuantifierLeave(node);
2051 }
2052 }
2053 visitRegExpLiteral(node) {
2054 if (this._handlers.onRegExpLiteralEnter) {
2055 this._handlers.onRegExpLiteralEnter(node);
2056 }
2057 this.visitPattern(node.pattern);
2058 this.visitFlags(node.flags);
2059 if (this._handlers.onRegExpLiteralLeave) {
2060 this._handlers.onRegExpLiteralLeave(node);
2061 }
2062 }
2063}
2064
2065function parseRegExpLiteral(source, options) {
2066 return new RegExpParser(options).parseLiteral(String(source));
2067}
2068function validateRegExpLiteral(source, options) {
2069 return new RegExpValidator(options).validateLiteral(source);
2070}
2071function visitRegExpAST(node, handlers) {
2072 new RegExpVisitor(handlers).visit(node);
2073}
2074
2075export { ast as AST, RegExpParser, RegExpValidator, parseRegExpLiteral, validateRegExpLiteral, visitRegExpAST };
2076//# sourceMappingURL=index.mjs.map