| Index: src/parser.cc
|
| diff --git a/src/parser.cc b/src/parser.cc
|
| index c609578365f051239bcd7c94f4794689e2e4f5ff..5ea1c5e083ac44a15ea4ac100f1f6848d9d4fffd 100644
|
| --- a/src/parser.cc
|
| +++ b/src/parser.cc
|
| @@ -4022,9 +4022,21 @@ RegExpTree* RegExpParser::ParseDisjunction() {
|
| builder->AddCharacter('\v');
|
| break;
|
| case 'c': {
|
| - Advance(2);
|
| - uc32 control = ParseControlLetterEscape();
|
| - builder->AddCharacter(control);
|
| + Advance();
|
| + uc32 controlLetter = Next();
|
| + // Special case if it is an ASCII letter.
|
| + // Convert lower case letters to uppercase.
|
| + uc32 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': {
|
| @@ -4299,23 +4311,6 @@ bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
|
| }
|
|
|
|
|
| -// Upper and lower case letters differ by one bit.
|
| -STATIC_CHECK(('a' ^ 'A') == 0x20);
|
| -
|
| -uc32 RegExpParser::ParseControlLetterEscape() {
|
| - if (!has_more())
|
| - return 'c';
|
| - uc32 letter = current() & ~(0x20); // Collapse upper and lower case letters.
|
| - if (letter < 'A' || 'Z' < letter) {
|
| - // Non-spec error-correction: "\c" followed by non-control letter is
|
| - // interpreted as an IdentityEscape of 'c'.
|
| - return 'c';
|
| - }
|
| - Advance();
|
| - return letter & 0x1f; // Remainder modulo 32, per specification.
|
| -}
|
| -
|
| -
|
| uc32 RegExpParser::ParseOctalLiteral() {
|
| ASSERT('0' <= current() && current() <= '7');
|
| // For compatibility with some other browsers (not all), we parse
|
| @@ -4381,9 +4376,23 @@ uc32 RegExpParser::ParseClassCharacterEscape() {
|
| case 'v':
|
| Advance();
|
| return '\v';
|
| - case 'c':
|
| - Advance();
|
| - return ParseControlLetterEscape();
|
| + case 'c': {
|
| + uc32 controlLetter = Next();
|
| + uc32 letter = controlLetter & ~('A' ^ 'a');
|
| + // 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')) {
|
| + Advance(2);
|
| + // Control letters mapped to ASCII control characters in the range
|
| + // 0x00-0x1f.
|
| + return controlLetter & 0x1f;
|
| + }
|
| + // We match JSC in reading the backslash as a literal
|
| + // character instead of as starting an escape.
|
| + return '\\';
|
| + }
|
| 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
|
|
|