Index: src/regexp/regexp-parser.cc |
diff --git a/src/regexp/regexp-parser.cc b/src/regexp/regexp-parser.cc |
index 21992e42a64ee337a5448444f30e6f9cb050bf44..cfcc1b43f9bcbb20c1dec7e73c48cdc59a83bcf0 100644 |
--- a/src/regexp/regexp-parser.cc |
+++ b/src/regexp/regexp-parser.cc |
@@ -358,13 +358,20 @@ RegExpTree* RegExpParser::ParseDisjunction() { |
uc32 p = Next(); |
Advance(2); |
if (unicode()) { |
- ZoneList<CharacterRange>* ranges = ParsePropertyClass(); |
- if (ranges == nullptr) { |
- return ReportError(CStrVector("Invalid property name")); |
+ if (FLAG_harmony_regexp_property) { |
+ ZoneList<CharacterRange>* ranges = |
+ new (zone()) ZoneList<CharacterRange>(2, zone()); |
+ if (!ParsePropertyClass(ranges)) { |
+ return ReportError(CStrVector("Invalid property name")); |
+ } |
+ RegExpCharacterClass* cc = |
+ new (zone()) RegExpCharacterClass(ranges, p == 'P'); |
+ builder->AddCharacterClass(cc); |
+ } else { |
+ // With /u, no identity escapes except for syntax characters |
+ // are allowed. Otherwise, all identity escapes are allowed. |
+ return ReportError(CStrVector("Invalid escape")); |
} |
- RegExpCharacterClass* cc = |
- new (zone()) RegExpCharacterClass(ranges, p == 'P'); |
- builder->AddCharacterClass(cc); |
} else { |
builder->AddCharacter(p); |
} |
@@ -836,18 +843,18 @@ bool RegExpParser::ParseUnicodeEscape(uc32* value) { |
return result; |
} |
-ZoneList<CharacterRange>* RegExpParser::ParsePropertyClass() { |
+bool RegExpParser::ParsePropertyClass(ZoneList<CharacterRange>* result) { |
#ifdef V8_I18N_SUPPORT |
ZoneList<char> property_name(0, zone()); |
if (current() == '{') { |
for (Advance(); current() != '}'; Advance()) { |
- if (!has_next()) return nullptr; |
+ if (!has_next()) return false; |
property_name.Add(static_cast<char>(current()), zone()); |
} |
} else if (current() != kEndMarker) { |
property_name.Add(static_cast<char>(current()), zone()); |
} else { |
- return nullptr; |
+ return false; |
} |
Advance(); |
property_name.Add(0, zone()); // null-terminate string. |
@@ -870,27 +877,25 @@ ZoneList<CharacterRange>* RegExpParser::ParsePropertyClass() { |
USet* set = uset_openEmpty(); |
UErrorCode ec = U_ZERO_ERROR; |
uset_applyIntPropertyValue(set, property_class, category, &ec); |
- ZoneList<CharacterRange>* ranges = nullptr; |
if (ec == U_ZERO_ERROR && !uset_isEmpty(set)) { |
uset_removeAllStrings(set); |
int item_count = uset_getItemCount(set); |
- ranges = new (zone()) ZoneList<CharacterRange>(item_count, zone()); |
int item_result = 0; |
for (int i = 0; i < item_count; i++) { |
uc32 start = 0; |
uc32 end = 0; |
item_result += uset_getItem(set, i, &start, &end, nullptr, 0, &ec); |
- ranges->Add(CharacterRange::Range(start, end), zone()); |
+ result->Add(CharacterRange::Range(start, end), zone()); |
} |
DCHECK_EQ(U_ZERO_ERROR, ec); |
DCHECK_EQ(0, item_result); |
} |
uset_close(set); |
- return ranges; |
+ return true; |
} |
#endif // V8_I18N_SUPPORT |
- return nullptr; |
+ return false; |
} |
bool RegExpParser::ParseUnlimitedLengthHexNumber(int max_value, uc32* value) { |
@@ -1070,6 +1075,34 @@ static inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges, |
} |
} |
+bool RegExpParser::ParseClassProperty(ZoneList<CharacterRange>* ranges) { |
+ if (!FLAG_harmony_regexp_property) return false; |
+ if (!unicode()) return false; |
+ if (current() != '\\') return false; |
+ uc32 next = Next(); |
+ bool parse_success = false; |
+ if (next == 'p') { |
+ Advance(2); |
+ parse_success = ParsePropertyClass(ranges); |
+ } else if (next == 'P') { |
+ Advance(2); |
+ ZoneList<CharacterRange>* property_class = |
+ new (zone()) ZoneList<CharacterRange>(2, zone()); |
+ parse_success = ParsePropertyClass(property_class); |
+ if (parse_success) { |
+ ZoneList<CharacterRange>* negated = |
+ new (zone()) ZoneList<CharacterRange>(2, zone()); |
+ CharacterRange::Negate(property_class, negated, zone()); |
+ const Vector<CharacterRange> negated_vector = negated->ToVector(); |
+ ranges->AddAll(negated_vector, zone()); |
+ } |
+ } else { |
+ return false; |
+ } |
+ if (!parse_success) |
+ ReportError(CStrVector("Invalid property name in character class")); |
+ return parse_success; |
+} |
RegExpTree* RegExpParser::ParseCharacterClass() { |
static const char* kUnterminated = "Unterminated character class"; |
@@ -1086,6 +1119,8 @@ RegExpTree* RegExpParser::ParseCharacterClass() { |
ZoneList<CharacterRange>* ranges = |
new (zone()) ZoneList<CharacterRange>(2, zone()); |
while (has_more() && current() != ']') { |
+ bool parsed_property = ParseClassProperty(ranges CHECK_FAILED); |
+ if (parsed_property) continue; |
uc16 char_class = kNoCharClass; |
CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED); |
if (current() == '-') { |