OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/longjump.h" | 5 #include "vm/longjump.h" |
6 #include "vm/object_store.h" | 6 #include "vm/object_store.h" |
7 #include "vm/regexp_parser.h" | 7 #include "vm/regexp_parser.h" |
8 | 8 |
9 namespace dart { | 9 namespace dart { |
10 | 10 |
11 #define I isolate() | 11 #define Z zone() |
12 | 12 |
13 // Enables possessive quantifier syntax for testing. | 13 // Enables possessive quantifier syntax for testing. |
14 static const bool FLAG_regexp_possessive_quantifier = false; | 14 static const bool FLAG_regexp_possessive_quantifier = false; |
15 | 15 |
16 RegExpBuilder::RegExpBuilder() | 16 RegExpBuilder::RegExpBuilder() |
17 : isolate_(Isolate::Current()), | 17 : zone_(Thread::Current()->zone()), |
18 pending_empty_(false), | 18 pending_empty_(false), |
19 characters_(NULL), | 19 characters_(NULL), |
20 terms_(), | 20 terms_(), |
21 text_(), | 21 text_(), |
22 alternatives_() | 22 alternatives_() |
23 #ifdef DEBUG | 23 #ifdef DEBUG |
24 , last_added_(ADD_NONE) | 24 , last_added_(ADD_NONE) |
25 #endif | 25 #endif |
26 {} | 26 {} |
27 | 27 |
28 | 28 |
29 void RegExpBuilder::FlushCharacters() { | 29 void RegExpBuilder::FlushCharacters() { |
30 pending_empty_ = false; | 30 pending_empty_ = false; |
31 if (characters_ != NULL) { | 31 if (characters_ != NULL) { |
32 RegExpTree* atom = new(I) RegExpAtom(characters_); | 32 RegExpTree* atom = new(Z) RegExpAtom(characters_); |
33 characters_ = NULL; | 33 characters_ = NULL; |
34 text_.Add(atom); | 34 text_.Add(atom); |
35 LAST(ADD_ATOM); | 35 LAST(ADD_ATOM); |
36 } | 36 } |
37 } | 37 } |
38 | 38 |
39 | 39 |
40 void RegExpBuilder::FlushText() { | 40 void RegExpBuilder::FlushText() { |
41 FlushCharacters(); | 41 FlushCharacters(); |
42 intptr_t num_text = text_.length(); | 42 intptr_t num_text = text_.length(); |
43 if (num_text == 0) { | 43 if (num_text == 0) { |
44 return; | 44 return; |
45 } else if (num_text == 1) { | 45 } else if (num_text == 1) { |
46 terms_.Add(text_.Last()); | 46 terms_.Add(text_.Last()); |
47 } else { | 47 } else { |
48 RegExpText* text = new(I) RegExpText(); | 48 RegExpText* text = new(Z) RegExpText(); |
49 for (intptr_t i = 0; i < num_text; i++) | 49 for (intptr_t i = 0; i < num_text; i++) |
50 text_[i]->AppendToText(text); | 50 text_[i]->AppendToText(text); |
51 terms_.Add(text); | 51 terms_.Add(text); |
52 } | 52 } |
53 text_.Clear(); | 53 text_.Clear(); |
54 } | 54 } |
55 | 55 |
56 | 56 |
57 void RegExpBuilder::AddCharacter(uint16_t c) { | 57 void RegExpBuilder::AddCharacter(uint16_t c) { |
58 pending_empty_ = false; | 58 pending_empty_ = false; |
59 if (characters_ == NULL) { | 59 if (characters_ == NULL) { |
60 characters_ = new(I) ZoneGrowableArray<uint16_t>(4); | 60 characters_ = new(Z) ZoneGrowableArray<uint16_t>(4); |
61 } | 61 } |
62 characters_->Add(c); | 62 characters_->Add(c); |
63 LAST(ADD_CHAR); | 63 LAST(ADD_CHAR); |
64 } | 64 } |
65 | 65 |
66 | 66 |
67 void RegExpBuilder::AddEmpty() { | 67 void RegExpBuilder::AddEmpty() { |
68 pending_empty_ = true; | 68 pending_empty_ = true; |
69 } | 69 } |
70 | 70 |
(...skipping 29 matching lines...) Expand all Loading... |
100 void RegExpBuilder::FlushTerms() { | 100 void RegExpBuilder::FlushTerms() { |
101 FlushText(); | 101 FlushText(); |
102 intptr_t num_terms = terms_.length(); | 102 intptr_t num_terms = terms_.length(); |
103 RegExpTree* alternative; | 103 RegExpTree* alternative; |
104 if (num_terms == 0) { | 104 if (num_terms == 0) { |
105 alternative = RegExpEmpty::GetInstance(); | 105 alternative = RegExpEmpty::GetInstance(); |
106 } else if (num_terms == 1) { | 106 } else if (num_terms == 1) { |
107 alternative = terms_.Last(); | 107 alternative = terms_.Last(); |
108 } else { | 108 } else { |
109 ZoneGrowableArray<RegExpTree*>* terms = | 109 ZoneGrowableArray<RegExpTree*>* terms = |
110 new(I) ZoneGrowableArray<RegExpTree*>(); | 110 new(Z) ZoneGrowableArray<RegExpTree*>(); |
111 for (intptr_t i = 0; i < terms_.length(); i++) { | 111 for (intptr_t i = 0; i < terms_.length(); i++) { |
112 terms->Add(terms_[i]); | 112 terms->Add(terms_[i]); |
113 } | 113 } |
114 alternative = new(I) RegExpAlternative(terms); | 114 alternative = new(Z) RegExpAlternative(terms); |
115 } | 115 } |
116 alternatives_.Add(alternative); | 116 alternatives_.Add(alternative); |
117 terms_.Clear(); | 117 terms_.Clear(); |
118 LAST(ADD_NONE); | 118 LAST(ADD_NONE); |
119 } | 119 } |
120 | 120 |
121 | 121 |
122 RegExpTree* RegExpBuilder::ToRegExp() { | 122 RegExpTree* RegExpBuilder::ToRegExp() { |
123 FlushTerms(); | 123 FlushTerms(); |
124 intptr_t num_alternatives = alternatives_.length(); | 124 intptr_t num_alternatives = alternatives_.length(); |
125 if (num_alternatives == 0) { | 125 if (num_alternatives == 0) { |
126 return RegExpEmpty::GetInstance(); | 126 return RegExpEmpty::GetInstance(); |
127 } | 127 } |
128 if (num_alternatives == 1) { | 128 if (num_alternatives == 1) { |
129 return alternatives_.Last(); | 129 return alternatives_.Last(); |
130 } | 130 } |
131 ZoneGrowableArray<RegExpTree*>* alternatives = | 131 ZoneGrowableArray<RegExpTree*>* alternatives = |
132 new(I) ZoneGrowableArray<RegExpTree*>(); | 132 new(Z) ZoneGrowableArray<RegExpTree*>(); |
133 for (intptr_t i = 0; i < alternatives_.length(); i++) { | 133 for (intptr_t i = 0; i < alternatives_.length(); i++) { |
134 alternatives->Add(alternatives_[i]); | 134 alternatives->Add(alternatives_[i]); |
135 } | 135 } |
136 return new(I) RegExpDisjunction(alternatives); | 136 return new(Z) RegExpDisjunction(alternatives); |
137 } | 137 } |
138 | 138 |
139 | 139 |
140 void RegExpBuilder::AddQuantifierToAtom( | 140 void RegExpBuilder::AddQuantifierToAtom( |
141 intptr_t min, | 141 intptr_t min, |
142 intptr_t max, | 142 intptr_t max, |
143 RegExpQuantifier::QuantifierType quantifier_type) { | 143 RegExpQuantifier::QuantifierType quantifier_type) { |
144 if (pending_empty_) { | 144 if (pending_empty_) { |
145 pending_empty_ = false; | 145 pending_empty_ = false; |
146 return; | 146 return; |
147 } | 147 } |
148 RegExpTree* atom; | 148 RegExpTree* atom; |
149 if (characters_ != NULL) { | 149 if (characters_ != NULL) { |
150 DEBUG_ASSERT(last_added_ == ADD_CHAR); | 150 DEBUG_ASSERT(last_added_ == ADD_CHAR); |
151 // Last atom was character. | 151 // Last atom was character. |
152 | 152 |
153 ZoneGrowableArray<uint16_t> *char_vector = | 153 ZoneGrowableArray<uint16_t> *char_vector = |
154 new(I) ZoneGrowableArray<uint16_t>(); | 154 new(Z) ZoneGrowableArray<uint16_t>(); |
155 char_vector->AddArray(*characters_); | 155 char_vector->AddArray(*characters_); |
156 intptr_t num_chars = char_vector->length(); | 156 intptr_t num_chars = char_vector->length(); |
157 if (num_chars > 1) { | 157 if (num_chars > 1) { |
158 ZoneGrowableArray<uint16_t> *prefix = | 158 ZoneGrowableArray<uint16_t> *prefix = |
159 new(I) ZoneGrowableArray<uint16_t>(); | 159 new(Z) ZoneGrowableArray<uint16_t>(); |
160 for (intptr_t i = 0; i < num_chars - 1; i++) { | 160 for (intptr_t i = 0; i < num_chars - 1; i++) { |
161 prefix->Add(char_vector->At(i)); | 161 prefix->Add(char_vector->At(i)); |
162 } | 162 } |
163 text_.Add(new(I) RegExpAtom(prefix)); | 163 text_.Add(new(Z) RegExpAtom(prefix)); |
164 ZoneGrowableArray<uint16_t> *tail = new(I) ZoneGrowableArray<uint16_t>(); | 164 ZoneGrowableArray<uint16_t> *tail = new(Z) ZoneGrowableArray<uint16_t>(); |
165 tail->Add(char_vector->At(num_chars - 1)); | 165 tail->Add(char_vector->At(num_chars - 1)); |
166 char_vector = tail; | 166 char_vector = tail; |
167 } | 167 } |
168 characters_ = NULL; | 168 characters_ = NULL; |
169 atom = new(I) RegExpAtom(char_vector); | 169 atom = new(Z) RegExpAtom(char_vector); |
170 FlushText(); | 170 FlushText(); |
171 } else if (text_.length() > 0) { | 171 } else if (text_.length() > 0) { |
172 DEBUG_ASSERT(last_added_ == ADD_ATOM); | 172 DEBUG_ASSERT(last_added_ == ADD_ATOM); |
173 atom = text_.RemoveLast(); | 173 atom = text_.RemoveLast(); |
174 FlushText(); | 174 FlushText(); |
175 } else if (terms_.length() > 0) { | 175 } else if (terms_.length() > 0) { |
176 DEBUG_ASSERT(last_added_ == ADD_ATOM); | 176 DEBUG_ASSERT(last_added_ == ADD_ATOM); |
177 atom = terms_.RemoveLast(); | 177 atom = terms_.RemoveLast(); |
178 if (atom->max_match() == 0) { | 178 if (atom->max_match() == 0) { |
179 // Guaranteed to only match an empty string. | 179 // Guaranteed to only match an empty string. |
180 LAST(ADD_TERM); | 180 LAST(ADD_TERM); |
181 if (min == 0) { | 181 if (min == 0) { |
182 return; | 182 return; |
183 } | 183 } |
184 terms_.Add(atom); | 184 terms_.Add(atom); |
185 return; | 185 return; |
186 } | 186 } |
187 } else { | 187 } else { |
188 // Only call immediately after adding an atom or character! | 188 // Only call immediately after adding an atom or character! |
189 UNREACHABLE(); | 189 UNREACHABLE(); |
190 return; | 190 return; |
191 } | 191 } |
192 terms_.Add(new(I) RegExpQuantifier(min, max, quantifier_type, atom)); | 192 terms_.Add(new(Z) RegExpQuantifier(min, max, quantifier_type, atom)); |
193 LAST(ADD_TERM); | 193 LAST(ADD_TERM); |
194 } | 194 } |
195 | 195 |
196 // ---------------------------------------------------------------------------- | 196 // ---------------------------------------------------------------------------- |
197 // Implementation of Parser | 197 // Implementation of Parser |
198 | 198 |
199 RegExpParser::RegExpParser(const String& in, | 199 RegExpParser::RegExpParser(const String& in, |
200 String* error, | 200 String* error, |
201 bool multiline) | 201 bool multiline) |
202 : isolate_(Isolate::Current()), | 202 : zone_(Thread::Current()->zone()), |
203 error_(error), | 203 error_(error), |
204 captures_(NULL), | 204 captures_(NULL), |
205 in_(in), | 205 in_(in), |
206 current_(kEndMarker), | 206 current_(kEndMarker), |
207 next_pos_(0), | 207 next_pos_(0), |
208 capture_count_(0), | 208 capture_count_(0), |
209 has_more_(true), | 209 has_more_(true), |
210 multiline_(multiline), | 210 multiline_(multiline), |
211 simple_(false), | 211 simple_(false), |
212 contains_anchor_(false), | 212 contains_anchor_(false), |
213 is_scanned_for_captures_(false), | 213 is_scanned_for_captures_(false), |
214 failed_(false) { | 214 failed_(false) { |
215 Advance(); | 215 Advance(); |
216 } | 216 } |
217 | 217 |
218 | 218 |
219 bool RegExpParser::ParseFunction(ParsedFunction *parsed_function) { | 219 bool RegExpParser::ParseFunction(ParsedFunction *parsed_function) { |
220 Isolate* isolate = parsed_function->isolate(); | 220 Zone* zone = parsed_function->zone(); |
221 JSRegExp& regexp = JSRegExp::Handle(parsed_function->function().regexp()); | 221 JSRegExp& regexp = JSRegExp::Handle(parsed_function->function().regexp()); |
222 | 222 |
223 const String& pattern = String::Handle(regexp.pattern()); | 223 const String& pattern = String::Handle(regexp.pattern()); |
224 const bool multiline = regexp.is_multi_line(); | 224 const bool multiline = regexp.is_multi_line(); |
225 | 225 |
226 RegExpCompileData* compile_data = new(isolate) RegExpCompileData(); | 226 RegExpCompileData* compile_data = new(zone) RegExpCompileData(); |
227 if (!RegExpParser::ParseRegExp(pattern, multiline, compile_data)) { | 227 if (!RegExpParser::ParseRegExp(pattern, multiline, compile_data)) { |
228 // Parsing failures are handled in the JSRegExp factory constructor. | 228 // Parsing failures are handled in the JSRegExp factory constructor. |
229 UNREACHABLE(); | 229 UNREACHABLE(); |
230 } | 230 } |
231 | 231 |
232 regexp.set_num_bracket_expressions(compile_data->capture_count); | 232 regexp.set_num_bracket_expressions(compile_data->capture_count); |
233 if (compile_data->simple) { | 233 if (compile_data->simple) { |
234 regexp.set_is_simple(); | 234 regexp.set_is_simple(); |
235 } else { | 235 } else { |
236 regexp.set_is_complex(); | 236 regexp.set_is_complex(); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 // Alternative | Disjunction | 312 // Alternative | Disjunction |
313 // Alternative :: | 313 // Alternative :: |
314 // [empty] | 314 // [empty] |
315 // Term Alternative | 315 // Term Alternative |
316 // Term :: | 316 // Term :: |
317 // Assertion | 317 // Assertion |
318 // Atom | 318 // Atom |
319 // Atom Quantifier | 319 // Atom Quantifier |
320 RegExpTree* RegExpParser::ParseDisjunction() { | 320 RegExpTree* RegExpParser::ParseDisjunction() { |
321 // Used to store current state while parsing subexpressions. | 321 // Used to store current state while parsing subexpressions. |
322 RegExpParserState initial_state(NULL, INITIAL, 0, I); | 322 RegExpParserState initial_state(NULL, INITIAL, 0, Z); |
323 RegExpParserState* stored_state = &initial_state; | 323 RegExpParserState* stored_state = &initial_state; |
324 // Cache the builder in a local variable for quick access. | 324 // Cache the builder in a local variable for quick access. |
325 RegExpBuilder* builder = initial_state.builder(); | 325 RegExpBuilder* builder = initial_state.builder(); |
326 while (true) { | 326 while (true) { |
327 switch (current()) { | 327 switch (current()) { |
328 case kEndMarker: | 328 case kEndMarker: |
329 if (stored_state->IsSubexpression()) { | 329 if (stored_state->IsSubexpression()) { |
330 // Inside a parenthesized group when hitting end of input. | 330 // Inside a parenthesized group when hitting end of input. |
331 ReportError("Unterminated group"); | 331 ReportError("Unterminated group"); |
332 UNREACHABLE(); | 332 UNREACHABLE(); |
(...skipping 17 matching lines...) Expand all Loading... |
350 | 350 |
351 intptr_t capture_index = stored_state->capture_index(); | 351 intptr_t capture_index = stored_state->capture_index(); |
352 SubexpressionType group_type = stored_state->group_type(); | 352 SubexpressionType group_type = stored_state->group_type(); |
353 | 353 |
354 // Restore previous state. | 354 // Restore previous state. |
355 stored_state = stored_state->previous_state(); | 355 stored_state = stored_state->previous_state(); |
356 builder = stored_state->builder(); | 356 builder = stored_state->builder(); |
357 | 357 |
358 // Build result of subexpression. | 358 // Build result of subexpression. |
359 if (group_type == CAPTURE) { | 359 if (group_type == CAPTURE) { |
360 RegExpCapture* capture = new(I) RegExpCapture(body, capture_index); | 360 RegExpCapture* capture = new(Z) RegExpCapture(body, capture_index); |
361 (*captures_)[capture_index - 1] = capture; | 361 (*captures_)[capture_index - 1] = capture; |
362 body = capture; | 362 body = capture; |
363 } else if (group_type != GROUPING) { | 363 } else if (group_type != GROUPING) { |
364 ASSERT(group_type == POSITIVE_LOOKAHEAD || | 364 ASSERT(group_type == POSITIVE_LOOKAHEAD || |
365 group_type == NEGATIVE_LOOKAHEAD); | 365 group_type == NEGATIVE_LOOKAHEAD); |
366 bool is_positive = (group_type == POSITIVE_LOOKAHEAD); | 366 bool is_positive = (group_type == POSITIVE_LOOKAHEAD); |
367 body = new(I) RegExpLookahead(body, | 367 body = new(Z) RegExpLookahead(body, |
368 is_positive, | 368 is_positive, |
369 end_capture_index - capture_index, | 369 end_capture_index - capture_index, |
370 capture_index); | 370 capture_index); |
371 } | 371 } |
372 builder->AddAtom(body); | 372 builder->AddAtom(body); |
373 // For compatibility with JSC and ES3, we allow quantifiers after | 373 // For compatibility with JSC and ES3, we allow quantifiers after |
374 // lookaheads, and break in all cases. | 374 // lookaheads, and break in all cases. |
375 break; | 375 break; |
376 } | 376 } |
377 case '|': { | 377 case '|': { |
378 Advance(); | 378 Advance(); |
379 builder->NewAlternative(); | 379 builder->NewAlternative(); |
380 continue; | 380 continue; |
381 } | 381 } |
382 case '*': | 382 case '*': |
383 case '+': | 383 case '+': |
384 case '?': | 384 case '?': |
385 ReportError("Nothing to repeat"); | 385 ReportError("Nothing to repeat"); |
386 UNREACHABLE(); | 386 UNREACHABLE(); |
387 case '^': { | 387 case '^': { |
388 Advance(); | 388 Advance(); |
389 if (multiline_) { | 389 if (multiline_) { |
390 builder->AddAssertion( | 390 builder->AddAssertion( |
391 new(I) RegExpAssertion(RegExpAssertion::START_OF_LINE)); | 391 new(Z) RegExpAssertion(RegExpAssertion::START_OF_LINE)); |
392 } else { | 392 } else { |
393 builder->AddAssertion( | 393 builder->AddAssertion( |
394 new(I) RegExpAssertion(RegExpAssertion::START_OF_INPUT)); | 394 new(Z) RegExpAssertion(RegExpAssertion::START_OF_INPUT)); |
395 set_contains_anchor(); | 395 set_contains_anchor(); |
396 } | 396 } |
397 continue; | 397 continue; |
398 } | 398 } |
399 case '$': { | 399 case '$': { |
400 Advance(); | 400 Advance(); |
401 RegExpAssertion::AssertionType assertion_type = | 401 RegExpAssertion::AssertionType assertion_type = |
402 multiline_ ? RegExpAssertion::END_OF_LINE : | 402 multiline_ ? RegExpAssertion::END_OF_LINE : |
403 RegExpAssertion::END_OF_INPUT; | 403 RegExpAssertion::END_OF_INPUT; |
404 builder->AddAssertion(new RegExpAssertion(assertion_type)); | 404 builder->AddAssertion(new RegExpAssertion(assertion_type)); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 captures_ = new ZoneGrowableArray<RegExpCapture*>(2); | 438 captures_ = new ZoneGrowableArray<RegExpCapture*>(2); |
439 } | 439 } |
440 if (captures_started() >= kMaxCaptures) { | 440 if (captures_started() >= kMaxCaptures) { |
441 ReportError("Too many captures"); | 441 ReportError("Too many captures"); |
442 UNREACHABLE(); | 442 UNREACHABLE(); |
443 } | 443 } |
444 captures_->Add(NULL); | 444 captures_->Add(NULL); |
445 } | 445 } |
446 // Store current state and begin new disjunction parsing. | 446 // Store current state and begin new disjunction parsing. |
447 stored_state = new RegExpParserState(stored_state, subexpr_type, | 447 stored_state = new RegExpParserState(stored_state, subexpr_type, |
448 captures_started(), I); | 448 captures_started(), Z); |
449 builder = stored_state->builder(); | 449 builder = stored_state->builder(); |
450 continue; | 450 continue; |
451 } | 451 } |
452 case '[': { | 452 case '[': { |
453 RegExpTree* atom = ParseCharacterClass(); | 453 RegExpTree* atom = ParseCharacterClass(); |
454 builder->AddAtom(atom); | 454 builder->AddAtom(atom); |
455 break; | 455 break; |
456 } | 456 } |
457 // Atom :: | 457 // Atom :: |
458 // \ AtomEscape | 458 // \ AtomEscape |
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
989 static const char* kRangeOutOfOrder = "Range out of order in character class"; | 989 static const char* kRangeOutOfOrder = "Range out of order in character class"; |
990 | 990 |
991 ASSERT(current() == '['); | 991 ASSERT(current() == '['); |
992 Advance(); | 992 Advance(); |
993 bool is_negated = false; | 993 bool is_negated = false; |
994 if (current() == '^') { | 994 if (current() == '^') { |
995 is_negated = true; | 995 is_negated = true; |
996 Advance(); | 996 Advance(); |
997 } | 997 } |
998 ZoneGrowableArray<CharacterRange>* ranges = | 998 ZoneGrowableArray<CharacterRange>* ranges = |
999 new(I) ZoneGrowableArray<CharacterRange>(2); | 999 new(Z) ZoneGrowableArray<CharacterRange>(2); |
1000 while (has_more() && current() != ']') { | 1000 while (has_more() && current() != ']') { |
1001 uint16_t char_class = kNoCharClass; | 1001 uint16_t char_class = kNoCharClass; |
1002 CharacterRange first = ParseClassAtom(&char_class); | 1002 CharacterRange first = ParseClassAtom(&char_class); |
1003 if (current() == '-') { | 1003 if (current() == '-') { |
1004 Advance(); | 1004 Advance(); |
1005 if (current() == kEndMarker) { | 1005 if (current() == kEndMarker) { |
1006 // If we reach the end we break out of the loop and let the | 1006 // If we reach the end we break out of the loop and let the |
1007 // following code report an error. | 1007 // following code report an error. |
1008 break; | 1008 break; |
1009 } else if (current() == ']') { | 1009 } else if (current() == ']') { |
(...skipping 21 matching lines...) Expand all Loading... |
1031 } | 1031 } |
1032 if (!has_more()) { | 1032 if (!has_more()) { |
1033 ReportError(kUnterminated); | 1033 ReportError(kUnterminated); |
1034 UNREACHABLE(); | 1034 UNREACHABLE(); |
1035 } | 1035 } |
1036 Advance(); | 1036 Advance(); |
1037 if (ranges->length() == 0) { | 1037 if (ranges->length() == 0) { |
1038 ranges->Add(CharacterRange::Everything()); | 1038 ranges->Add(CharacterRange::Everything()); |
1039 is_negated = !is_negated; | 1039 is_negated = !is_negated; |
1040 } | 1040 } |
1041 return new(I) RegExpCharacterClass(ranges, is_negated); | 1041 return new(Z) RegExpCharacterClass(ranges, is_negated); |
1042 } | 1042 } |
1043 | 1043 |
1044 | 1044 |
1045 // ---------------------------------------------------------------------------- | 1045 // ---------------------------------------------------------------------------- |
1046 // The Parser interface. | 1046 // The Parser interface. |
1047 | 1047 |
1048 bool RegExpParser::ParseRegExp(const String& input, | 1048 bool RegExpParser::ParseRegExp(const String& input, |
1049 bool multiline, | 1049 bool multiline, |
1050 RegExpCompileData* result) { | 1050 RegExpCompileData* result) { |
1051 ASSERT(result != NULL); | 1051 ASSERT(result != NULL); |
(...skipping 17 matching lines...) Expand all Loading... |
1069 String::Concat(result->error, input)); | 1069 String::Concat(result->error, input)); |
1070 const Array& args = Array::Handle(Array::New(1)); | 1070 const Array& args = Array::Handle(Array::New(1)); |
1071 args.SetAt(0, message); | 1071 args.SetAt(0, message); |
1072 | 1072 |
1073 Exceptions::ThrowByType(Exceptions::kFormat, args); | 1073 Exceptions::ThrowByType(Exceptions::kFormat, args); |
1074 } | 1074 } |
1075 return !parser.failed(); | 1075 return !parser.failed(); |
1076 } | 1076 } |
1077 | 1077 |
1078 } // namespace dart | 1078 } // namespace dart |
OLD | NEW |