Index: runtime/vm/regexp_parser.cc |
diff --git a/runtime/vm/regexp_parser.cc b/runtime/vm/regexp_parser.cc |
index c4d471ae37f81f424ce2250bee71cba7e1a7dfaf..f75b30f6549d59fb2ca28e2c5a9e3444a2796bd6 100644 |
--- a/runtime/vm/regexp_parser.cc |
+++ b/runtime/vm/regexp_parser.cc |
@@ -21,15 +21,17 @@ RegExpBuilder::RegExpBuilder() |
text_(), |
alternatives_() |
#ifdef DEBUG |
- , last_added_(ADD_NONE) |
+ , |
+ last_added_(ADD_NONE) |
#endif |
- {} |
+{ |
+} |
void RegExpBuilder::FlushCharacters() { |
pending_empty_ = false; |
if (characters_ != NULL) { |
- RegExpTree* atom = new(Z) RegExpAtom(characters_); |
+ RegExpTree* atom = new (Z) RegExpAtom(characters_); |
characters_ = NULL; |
text_.Add(atom); |
LAST(ADD_ATOM); |
@@ -45,7 +47,7 @@ void RegExpBuilder::FlushText() { |
} else if (num_text == 1) { |
terms_.Add(text_.Last()); |
} else { |
- RegExpText* text = new(Z) RegExpText(); |
+ RegExpText* text = new (Z) RegExpText(); |
for (intptr_t i = 0; i < num_text; i++) |
text_[i]->AppendToText(text); |
terms_.Add(text); |
@@ -57,7 +59,7 @@ void RegExpBuilder::FlushText() { |
void RegExpBuilder::AddCharacter(uint16_t c) { |
pending_empty_ = false; |
if (characters_ == NULL) { |
- characters_ = new(Z) ZoneGrowableArray<uint16_t>(4); |
+ characters_ = new (Z) ZoneGrowableArray<uint16_t>(4); |
} |
characters_->Add(c); |
LAST(ADD_CHAR); |
@@ -107,11 +109,11 @@ void RegExpBuilder::FlushTerms() { |
alternative = terms_.Last(); |
} else { |
ZoneGrowableArray<RegExpTree*>* terms = |
- new(Z) ZoneGrowableArray<RegExpTree*>(); |
+ new (Z) ZoneGrowableArray<RegExpTree*>(); |
for (intptr_t i = 0; i < terms_.length(); i++) { |
terms->Add(terms_[i]); |
} |
- alternative = new(Z) RegExpAlternative(terms); |
+ alternative = new (Z) RegExpAlternative(terms); |
} |
alternatives_.Add(alternative); |
terms_.Clear(); |
@@ -129,11 +131,11 @@ RegExpTree* RegExpBuilder::ToRegExp() { |
return alternatives_.Last(); |
} |
ZoneGrowableArray<RegExpTree*>* alternatives = |
- new(Z) ZoneGrowableArray<RegExpTree*>(); |
+ new (Z) ZoneGrowableArray<RegExpTree*>(); |
for (intptr_t i = 0; i < alternatives_.length(); i++) { |
alternatives->Add(alternatives_[i]); |
} |
- return new(Z) RegExpDisjunction(alternatives); |
+ return new (Z) RegExpDisjunction(alternatives); |
} |
@@ -150,23 +152,23 @@ void RegExpBuilder::AddQuantifierToAtom( |
DEBUG_ASSERT(last_added_ == ADD_CHAR); |
// Last atom was character. |
- ZoneGrowableArray<uint16_t> *char_vector = |
- new(Z) ZoneGrowableArray<uint16_t>(); |
+ ZoneGrowableArray<uint16_t>* char_vector = |
+ new (Z) ZoneGrowableArray<uint16_t>(); |
char_vector->AddArray(*characters_); |
intptr_t num_chars = char_vector->length(); |
if (num_chars > 1) { |
- ZoneGrowableArray<uint16_t> *prefix = |
- new(Z) ZoneGrowableArray<uint16_t>(); |
+ ZoneGrowableArray<uint16_t>* prefix = |
+ new (Z) ZoneGrowableArray<uint16_t>(); |
for (intptr_t i = 0; i < num_chars - 1; i++) { |
prefix->Add(char_vector->At(i)); |
} |
- text_.Add(new(Z) RegExpAtom(prefix)); |
- ZoneGrowableArray<uint16_t> *tail = new(Z) ZoneGrowableArray<uint16_t>(); |
+ text_.Add(new (Z) RegExpAtom(prefix)); |
+ ZoneGrowableArray<uint16_t>* tail = new (Z) ZoneGrowableArray<uint16_t>(); |
tail->Add(char_vector->At(num_chars - 1)); |
char_vector = tail; |
} |
characters_ = NULL; |
- atom = new(Z) RegExpAtom(char_vector); |
+ atom = new (Z) RegExpAtom(char_vector); |
FlushText(); |
} else if (text_.length() > 0) { |
DEBUG_ASSERT(last_added_ == ADD_ATOM); |
@@ -189,16 +191,14 @@ void RegExpBuilder::AddQuantifierToAtom( |
UNREACHABLE(); |
return; |
} |
- terms_.Add(new(Z) RegExpQuantifier(min, max, quantifier_type, atom)); |
+ terms_.Add(new (Z) RegExpQuantifier(min, max, quantifier_type, atom)); |
LAST(ADD_TERM); |
} |
// ---------------------------------------------------------------------------- |
// Implementation of Parser |
-RegExpParser::RegExpParser(const String& in, |
- String* error, |
- bool multiline) |
+RegExpParser::RegExpParser(const String& in, String* error, bool multiline) |
: zone_(Thread::Current()->zone()), |
error_(error), |
captures_(NULL), |
@@ -216,7 +216,7 @@ RegExpParser::RegExpParser(const String& in, |
} |
-bool RegExpParser::ParseFunction(ParsedFunction *parsed_function) { |
+bool RegExpParser::ParseFunction(ParsedFunction* parsed_function) { |
VMTagScope tagScope(parsed_function->thread(), |
VMTag::kCompileParseRegExpTagId); |
Zone* zone = parsed_function->zone(); |
@@ -225,7 +225,7 @@ bool RegExpParser::ParseFunction(ParsedFunction *parsed_function) { |
const String& pattern = String::Handle(regexp.pattern()); |
const bool multiline = regexp.is_multi_line(); |
- RegExpCompileData* compile_data = new(zone) RegExpCompileData(); |
+ RegExpCompileData* compile_data = new (zone) RegExpCompileData(); |
if (!RegExpParser::ParseRegExp(pattern, multiline, compile_data)) { |
// Parsing failures are handled in the RegExp factory constructor. |
UNREACHABLE(); |
@@ -327,314 +327,325 @@ RegExpTree* RegExpParser::ParseDisjunction() { |
RegExpBuilder* builder = initial_state.builder(); |
while (true) { |
switch (current()) { |
- case kEndMarker: |
- if (stored_state->IsSubexpression()) { |
- // Inside a parenthesized group when hitting end of input. |
- ReportError("Unterminated group"); |
- UNREACHABLE(); |
- } |
- ASSERT(INITIAL == stored_state->group_type()); |
- // Parsing completed successfully. |
- return builder->ToRegExp(); |
- case ')': { |
- if (!stored_state->IsSubexpression()) { |
- ReportError("Unmatched ')'"); |
- UNREACHABLE(); |
- } |
- ASSERT(INITIAL != stored_state->group_type()); |
- |
- Advance(); |
- // End disjunction parsing and convert builder content to new single |
- // regexp atom. |
- RegExpTree* body = builder->ToRegExp(); |
- |
- intptr_t end_capture_index = captures_started(); |
- |
- intptr_t capture_index = stored_state->capture_index(); |
- SubexpressionType group_type = stored_state->group_type(); |
- |
- // Restore previous state. |
- stored_state = stored_state->previous_state(); |
- builder = stored_state->builder(); |
- |
- // Build result of subexpression. |
- if (group_type == CAPTURE) { |
- RegExpCapture* capture = new(Z) RegExpCapture(body, capture_index); |
- (*captures_)[capture_index - 1] = capture; |
- body = capture; |
- } else if (group_type != GROUPING) { |
- ASSERT(group_type == POSITIVE_LOOKAHEAD || |
- group_type == NEGATIVE_LOOKAHEAD); |
- bool is_positive = (group_type == POSITIVE_LOOKAHEAD); |
- body = new(Z) RegExpLookahead(body, |
- is_positive, |
- end_capture_index - capture_index, |
- capture_index); |
- } |
- builder->AddAtom(body); |
- // For compatibility with JSC and ES3, we allow quantifiers after |
- // lookaheads, and break in all cases. |
- break; |
- } |
- case '|': { |
- Advance(); |
- builder->NewAlternative(); |
- continue; |
- } |
- case '*': |
- case '+': |
- case '?': |
- ReportError("Nothing to repeat"); |
- UNREACHABLE(); |
- case '^': { |
- Advance(); |
- if (multiline_) { |
- builder->AddAssertion( |
- new(Z) RegExpAssertion(RegExpAssertion::START_OF_LINE)); |
- } else { |
- builder->AddAssertion( |
- new(Z) RegExpAssertion(RegExpAssertion::START_OF_INPUT)); |
- set_contains_anchor(); |
- } |
- continue; |
- } |
- case '$': { |
- Advance(); |
- RegExpAssertion::AssertionType assertion_type = |
- multiline_ ? RegExpAssertion::END_OF_LINE : |
- RegExpAssertion::END_OF_INPUT; |
- builder->AddAssertion(new RegExpAssertion(assertion_type)); |
- continue; |
- } |
- case '.': { |
- Advance(); |
- // everything except \x0a, \x0d, \u2028 and \u2029 |
- ZoneGrowableArray<CharacterRange>* ranges = |
- new ZoneGrowableArray<CharacterRange>(2); |
- CharacterRange::AddClassEscape('.', ranges); |
- RegExpTree* atom = new RegExpCharacterClass(ranges, false); |
- builder->AddAtom(atom); |
- break; |
- } |
- case '(': { |
- SubexpressionType subexpr_type = CAPTURE; |
- Advance(); |
- if (current() == '?') { |
- switch (Next()) { |
- case ':': |
- subexpr_type = GROUPING; |
- break; |
- case '=': |
- subexpr_type = POSITIVE_LOOKAHEAD; |
- break; |
- case '!': |
- subexpr_type = NEGATIVE_LOOKAHEAD; |
- break; |
- default: |
- ReportError("Invalid group"); |
- UNREACHABLE(); |
- } |
- Advance(2); |
- } else { |
- if (captures_ == NULL) { |
- captures_ = new ZoneGrowableArray<RegExpCapture*>(2); |
+ case kEndMarker: |
+ if (stored_state->IsSubexpression()) { |
+ // Inside a parenthesized group when hitting end of input. |
+ ReportError("Unterminated group"); |
+ UNREACHABLE(); |
} |
- if (captures_started() >= kMaxCaptures) { |
- ReportError("Too many captures"); |
+ ASSERT(INITIAL == stored_state->group_type()); |
+ // Parsing completed successfully. |
+ return builder->ToRegExp(); |
+ case ')': { |
+ if (!stored_state->IsSubexpression()) { |
+ ReportError("Unmatched ')'"); |
UNREACHABLE(); |
} |
- captures_->Add(NULL); |
+ ASSERT(INITIAL != stored_state->group_type()); |
+ |
+ Advance(); |
+ // End disjunction parsing and convert builder content to new single |
+ // regexp atom. |
+ RegExpTree* body = builder->ToRegExp(); |
+ |
+ intptr_t end_capture_index = captures_started(); |
+ |
+ intptr_t capture_index = stored_state->capture_index(); |
+ SubexpressionType group_type = stored_state->group_type(); |
+ |
+ // Restore previous state. |
+ stored_state = stored_state->previous_state(); |
+ builder = stored_state->builder(); |
+ |
+ // Build result of subexpression. |
+ if (group_type == CAPTURE) { |
+ RegExpCapture* capture = new (Z) RegExpCapture(body, capture_index); |
+ (*captures_)[capture_index - 1] = capture; |
+ body = capture; |
+ } else if (group_type != GROUPING) { |
+ ASSERT(group_type == POSITIVE_LOOKAHEAD || |
+ group_type == NEGATIVE_LOOKAHEAD); |
+ bool is_positive = (group_type == POSITIVE_LOOKAHEAD); |
+ body = new (Z) |
+ RegExpLookahead(body, is_positive, |
+ end_capture_index - capture_index, capture_index); |
+ } |
+ builder->AddAtom(body); |
+ // For compatibility with JSC and ES3, we allow quantifiers after |
+ // lookaheads, and break in all cases. |
+ break; |
} |
- // Store current state and begin new disjunction parsing. |
- stored_state = new RegExpParserState(stored_state, subexpr_type, |
- captures_started(), Z); |
- builder = stored_state->builder(); |
- continue; |
- } |
- case '[': { |
- RegExpTree* atom = ParseCharacterClass(); |
- builder->AddAtom(atom); |
- break; |
- } |
- // Atom :: |
- // \ AtomEscape |
- case '\\': |
- switch (Next()) { |
- case kEndMarker: |
- ReportError("\\ at end of pattern"); |
+ case '|': { |
+ Advance(); |
+ builder->NewAlternative(); |
+ continue; |
+ } |
+ case '*': |
+ case '+': |
+ case '?': |
+ ReportError("Nothing to repeat"); |
UNREACHABLE(); |
- case 'b': |
- Advance(2); |
- builder->AddAssertion( |
- new RegExpAssertion(RegExpAssertion::BOUNDARY)); |
+ case '^': { |
+ Advance(); |
+ if (multiline_) { |
+ builder->AddAssertion( |
+ new (Z) RegExpAssertion(RegExpAssertion::START_OF_LINE)); |
+ } else { |
+ builder->AddAssertion( |
+ new (Z) RegExpAssertion(RegExpAssertion::START_OF_INPUT)); |
+ set_contains_anchor(); |
+ } |
continue; |
- case 'B': |
- Advance(2); |
- builder->AddAssertion( |
- new RegExpAssertion(RegExpAssertion::NON_BOUNDARY)); |
+ } |
+ case '$': { |
+ Advance(); |
+ RegExpAssertion::AssertionType assertion_type = |
+ multiline_ ? RegExpAssertion::END_OF_LINE |
+ : RegExpAssertion::END_OF_INPUT; |
+ builder->AddAssertion(new RegExpAssertion(assertion_type)); |
continue; |
- // AtomEscape :: |
- // CharacterClassEscape |
- // |
- // CharacterClassEscape :: one of |
- // d D s S w W |
- case 'd': case 'D': case 's': case 'S': case 'w': case 'W': { |
- uint32_t c = Next(); |
- Advance(2); |
+ } |
+ case '.': { |
+ Advance(); |
+ // everything except \x0a, \x0d, \u2028 and \u2029 |
ZoneGrowableArray<CharacterRange>* ranges = |
new ZoneGrowableArray<CharacterRange>(2); |
- CharacterRange::AddClassEscape(c, ranges); |
+ CharacterRange::AddClassEscape('.', ranges); |
RegExpTree* atom = new RegExpCharacterClass(ranges, false); |
builder->AddAtom(atom); |
break; |
} |
- case '1': case '2': case '3': case '4': case '5': case '6': |
- case '7': case '8': case '9': { |
- intptr_t index = 0; |
- if (ParseBackReferenceIndex(&index)) { |
- RegExpCapture* capture = NULL; |
- if (captures_ != NULL && index <= captures_->length()) { |
- capture = captures_->At(index - 1); |
- } |
- if (capture == NULL) { |
- builder->AddEmpty(); |
- break; |
+ case '(': { |
+ SubexpressionType subexpr_type = CAPTURE; |
+ Advance(); |
+ if (current() == '?') { |
+ switch (Next()) { |
+ case ':': |
+ subexpr_type = GROUPING; |
+ break; |
+ case '=': |
+ subexpr_type = POSITIVE_LOOKAHEAD; |
+ break; |
+ case '!': |
+ subexpr_type = NEGATIVE_LOOKAHEAD; |
+ break; |
+ default: |
+ ReportError("Invalid group"); |
+ UNREACHABLE(); |
} |
- RegExpTree* atom = new RegExpBackReference(capture); |
- builder->AddAtom(atom); |
- break; |
- } |
- uint32_t first_digit = Next(); |
- if (first_digit == '8' || first_digit == '9') { |
- // Treat as identity escape |
- builder->AddCharacter(first_digit); |
Advance(2); |
- break; |
- } |
- } |
- // FALLTHROUGH |
- case '0': { |
- Advance(); |
- uint32_t octal = ParseOctalLiteral(); |
- builder->AddCharacter(octal); |
- break; |
- } |
- // ControlEscape :: one of |
- // f n r t v |
- case 'f': |
- Advance(2); |
- builder->AddCharacter('\f'); |
- break; |
- case 'n': |
- Advance(2); |
- builder->AddCharacter('\n'); |
- break; |
- case 'r': |
- Advance(2); |
- builder->AddCharacter('\r'); |
- break; |
- case 't': |
- Advance(2); |
- builder->AddCharacter('\t'); |
- break; |
- case 'v': |
- Advance(2); |
- builder->AddCharacter('\v'); |
- break; |
- case 'c': { |
- Advance(); |
- uint32_t controlLetter = Next(); |
- // Special case if it is an ASCII letter. |
- // Convert lower case letters to uppercase. |
- uint32_t letter = controlLetter & ~('a' ^ 'A'); |
- if (letter < 'A' || 'Z' < letter) { |
- // controlLetter is not in range 'A'-'Z' or 'a'-'z'. |
- // This is outside the specification. We match JSC in |
- // reading the backslash as a literal character instead |
- // of as starting an escape. |
- builder->AddCharacter('\\'); |
} else { |
- Advance(2); |
- builder->AddCharacter(controlLetter & 0x1f); |
+ if (captures_ == NULL) { |
+ captures_ = new ZoneGrowableArray<RegExpCapture*>(2); |
+ } |
+ if (captures_started() >= kMaxCaptures) { |
+ ReportError("Too many captures"); |
+ UNREACHABLE(); |
+ } |
+ captures_->Add(NULL); |
} |
- break; |
+ // Store current state and begin new disjunction parsing. |
+ stored_state = new RegExpParserState(stored_state, subexpr_type, |
+ captures_started(), Z); |
+ builder = stored_state->builder(); |
+ continue; |
} |
- case 'x': { |
- Advance(2); |
- uint32_t value; |
- if (ParseHexEscape(2, &value)) { |
- builder->AddCharacter(value); |
- } else { |
- builder->AddCharacter('x'); |
- } |
+ case '[': { |
+ RegExpTree* atom = ParseCharacterClass(); |
+ builder->AddAtom(atom); |
break; |
} |
- case 'u': { |
- Advance(2); |
- uint32_t value; |
- if (ParseHexEscape(4, &value)) { |
- builder->AddCharacter(value); |
- } else { |
- builder->AddCharacter('u'); |
+ // Atom :: |
+ // \ AtomEscape |
+ case '\\': |
+ switch (Next()) { |
+ case kEndMarker: |
+ ReportError("\\ at end of pattern"); |
+ UNREACHABLE(); |
+ case 'b': |
+ Advance(2); |
+ builder->AddAssertion( |
+ new RegExpAssertion(RegExpAssertion::BOUNDARY)); |
+ continue; |
+ case 'B': |
+ Advance(2); |
+ builder->AddAssertion( |
+ new RegExpAssertion(RegExpAssertion::NON_BOUNDARY)); |
+ continue; |
+ // AtomEscape :: |
+ // CharacterClassEscape |
+ // |
+ // CharacterClassEscape :: one of |
+ // d D s S w W |
+ case 'd': |
+ case 'D': |
+ case 's': |
+ case 'S': |
+ case 'w': |
+ case 'W': { |
+ uint32_t c = Next(); |
+ Advance(2); |
+ ZoneGrowableArray<CharacterRange>* ranges = |
+ new ZoneGrowableArray<CharacterRange>(2); |
+ CharacterRange::AddClassEscape(c, ranges); |
+ RegExpTree* atom = new RegExpCharacterClass(ranges, false); |
+ builder->AddAtom(atom); |
+ break; |
+ } |
+ case '1': |
+ case '2': |
+ case '3': |
+ case '4': |
+ case '5': |
+ case '6': |
+ case '7': |
+ case '8': |
+ case '9': { |
+ intptr_t index = 0; |
+ if (ParseBackReferenceIndex(&index)) { |
+ RegExpCapture* capture = NULL; |
+ if (captures_ != NULL && index <= captures_->length()) { |
+ capture = captures_->At(index - 1); |
+ } |
+ if (capture == NULL) { |
+ builder->AddEmpty(); |
+ break; |
+ } |
+ RegExpTree* atom = new RegExpBackReference(capture); |
+ builder->AddAtom(atom); |
+ break; |
+ } |
+ uint32_t first_digit = Next(); |
+ if (first_digit == '8' || first_digit == '9') { |
+ // Treat as identity escape |
+ builder->AddCharacter(first_digit); |
+ Advance(2); |
+ break; |
+ } |
+ } |
+ // FALLTHROUGH |
+ case '0': { |
+ Advance(); |
+ uint32_t octal = ParseOctalLiteral(); |
+ builder->AddCharacter(octal); |
+ break; |
+ } |
+ // ControlEscape :: one of |
+ // f n r t v |
+ case 'f': |
+ Advance(2); |
+ builder->AddCharacter('\f'); |
+ break; |
+ case 'n': |
+ Advance(2); |
+ builder->AddCharacter('\n'); |
+ break; |
+ case 'r': |
+ Advance(2); |
+ builder->AddCharacter('\r'); |
+ break; |
+ case 't': |
+ Advance(2); |
+ builder->AddCharacter('\t'); |
+ break; |
+ case 'v': |
+ Advance(2); |
+ builder->AddCharacter('\v'); |
+ break; |
+ case 'c': { |
+ Advance(); |
+ uint32_t controlLetter = Next(); |
+ // Special case if it is an ASCII letter. |
+ // Convert lower case letters to uppercase. |
+ uint32_t letter = controlLetter & ~('a' ^ 'A'); |
+ if (letter < 'A' || 'Z' < letter) { |
+ // controlLetter is not in range 'A'-'Z' or 'a'-'z'. |
+ // This is outside the specification. We match JSC in |
+ // reading the backslash as a literal character instead |
+ // of as starting an escape. |
+ builder->AddCharacter('\\'); |
+ } else { |
+ Advance(2); |
+ builder->AddCharacter(controlLetter & 0x1f); |
+ } |
+ break; |
+ } |
+ case 'x': { |
+ Advance(2); |
+ uint32_t value; |
+ if (ParseHexEscape(2, &value)) { |
+ builder->AddCharacter(value); |
+ } else { |
+ builder->AddCharacter('x'); |
+ } |
+ break; |
+ } |
+ case 'u': { |
+ Advance(2); |
+ uint32_t value; |
+ if (ParseHexEscape(4, &value)) { |
+ builder->AddCharacter(value); |
+ } else { |
+ builder->AddCharacter('u'); |
+ } |
+ break; |
+ } |
+ default: |
+ // Identity escape. |
+ builder->AddCharacter(Next()); |
+ Advance(2); |
+ break; |
} |
break; |
+ case '{': { |
+ intptr_t dummy; |
+ if (ParseIntervalQuantifier(&dummy, &dummy)) { |
+ ReportError("Nothing to repeat"); |
+ UNREACHABLE(); |
+ } |
+ // fallthrough |
} |
default: |
- // Identity escape. |
- builder->AddCharacter(Next()); |
- Advance(2); |
+ builder->AddCharacter(current()); |
+ Advance(); |
break; |
- } |
- break; |
- case '{': { |
- intptr_t dummy; |
- if (ParseIntervalQuantifier(&dummy, &dummy)) { |
- ReportError("Nothing to repeat"); |
- UNREACHABLE(); |
- } |
- // fallthrough |
- } |
- default: |
- builder->AddCharacter(current()); |
- Advance(); |
- break; |
} // end switch(current()) |
intptr_t min; |
intptr_t max; |
switch (current()) { |
- // QuantifierPrefix :: |
- // * |
- // + |
- // ? |
- // { |
- case '*': |
- min = 0; |
- max = RegExpTree::kInfinity; |
- Advance(); |
- break; |
- case '+': |
- min = 1; |
- max = RegExpTree::kInfinity; |
- Advance(); |
- break; |
- case '?': |
- min = 0; |
- max = 1; |
- Advance(); |
- break; |
- case '{': |
- if (ParseIntervalQuantifier(&min, &max)) { |
- if (max < min) { |
- ReportError("numbers out of order in {} quantifier."); |
- UNREACHABLE(); |
- } |
+ // QuantifierPrefix :: |
+ // * |
+ // + |
+ // ? |
+ // { |
+ case '*': |
+ min = 0; |
+ max = RegExpTree::kInfinity; |
+ Advance(); |
+ break; |
+ case '+': |
+ min = 1; |
+ max = RegExpTree::kInfinity; |
+ Advance(); |
+ break; |
+ case '?': |
+ min = 0; |
+ max = 1; |
+ Advance(); |
break; |
- } else { |
+ case '{': |
+ if (ParseIntervalQuantifier(&min, &max)) { |
+ if (max < min) { |
+ ReportError("numbers out of order in {} quantifier."); |
+ UNREACHABLE(); |
+ } |
+ break; |
+ } else { |
+ continue; |
+ } |
+ default: |
continue; |
- } |
- default: |
- continue; |
} |
RegExpQuantifier::QuantifierType quantifier_type = RegExpQuantifier::GREEDY; |
if (current() == '?') { |
@@ -654,9 +665,12 @@ RegExpTree* RegExpParser::ParseDisjunction() { |
// Currently only used in an ASSERT. |
static bool IsSpecialClassEscape(uint32_t c) { |
switch (c) { |
- case 'd': case 'D': |
- case 's': case 'S': |
- case 'w': case 'W': |
+ case 'd': |
+ case 'D': |
+ case 's': |
+ case 'S': |
+ case 'w': |
+ case 'W': |
return true; |
default: |
return false; |
@@ -843,7 +857,7 @@ static inline intptr_t HexValue(uint32_t c) { |
} |
-bool RegExpParser::ParseHexEscape(intptr_t length, uint32_t *value) { |
+bool RegExpParser::ParseHexEscape(intptr_t length, uint32_t* value) { |
intptr_t start = position(); |
uint32_t val = 0; |
bool done = false; |
@@ -896,8 +910,7 @@ uint32_t RegExpParser::ParseClassCharacterEscape() { |
// For compatibility with JSC, inside a character class |
// we also accept digits and underscore as control characters. |
if ((controlLetter >= '0' && controlLetter <= '9') || |
- controlLetter == '_' || |
- (letter >= 'A' && letter <= 'Z')) { |
+ controlLetter == '_' || (letter >= 'A' && letter <= 'Z')) { |
Advance(2); |
// Control letters mapped to ASCII control characters in the range |
// 0x00-0x1f. |
@@ -907,8 +920,14 @@ uint32_t RegExpParser::ParseClassCharacterEscape() { |
// character instead of as starting an escape. |
return '\\'; |
} |
- case '0': case '1': case '2': case '3': case '4': case '5': |
- case '6': case '7': |
+ case '0': |
+ case '1': |
+ case '2': |
+ case '3': |
+ case '4': |
+ case '5': |
+ case '6': |
+ case '7': |
// For compatibility, we interpret a decimal escape that isn't |
// a back reference (and therefore either \0 or not valid according |
// to the specification) as a 1..3 digit octal character code. |
@@ -951,7 +970,12 @@ CharacterRange RegExpParser::ParseClassAtom(uint16_t* char_class) { |
uint32_t first = current(); |
if (first == '\\') { |
switch (Next()) { |
- case 'w': case 'W': case 'd': case 'D': case 's': case 'S': { |
+ case 'w': |
+ case 'W': |
+ case 'd': |
+ case 'D': |
+ case 's': |
+ case 'S': { |
*char_class = Next(); |
Advance(2); |
return CharacterRange::Singleton(0); // Return dummy value. |
@@ -998,7 +1022,7 @@ RegExpTree* RegExpParser::ParseCharacterClass() { |
Advance(); |
} |
ZoneGrowableArray<CharacterRange>* ranges = |
- new(Z) ZoneGrowableArray<CharacterRange>(2); |
+ new (Z) ZoneGrowableArray<CharacterRange>(2); |
while (has_more() && current() != ']') { |
uint16_t char_class = kNoCharClass; |
CharacterRange first = ParseClassAtom(&char_class); |
@@ -1040,7 +1064,7 @@ RegExpTree* RegExpParser::ParseCharacterClass() { |
ranges->Add(CharacterRange::Everything()); |
is_negated = !is_negated; |
} |
- return new(Z) RegExpCharacterClass(ranges, is_negated); |
+ return new (Z) RegExpCharacterClass(ranges, is_negated); |
} |
@@ -1067,8 +1091,8 @@ bool RegExpParser::ParseRegExp(const String& input, |
Thread::Current()->clear_sticky_error(); |
// Throw a FormatException on parsing failures. |
- const String& message = String::Handle( |
- String::Concat(result->error, input)); |
+ const String& message = |
+ String::Handle(String::Concat(result->error, input)); |
const Array& args = Array::Handle(Array::New(1)); |
args.SetAt(0, message); |