Index: src/scanner.cc |
diff --git a/src/scanner.cc b/src/scanner.cc |
index 3214c6f1c765ac9005d77179b2014224e3190641..6ce222c871c8c72567ddefd44466105d9fe90d2b 100644 |
--- a/src/scanner.cc |
+++ b/src/scanner.cc |
@@ -39,7 +39,8 @@ Scanner::Scanner(UnicodeCache* unicode_cache) |
harmony_modules_(false), |
harmony_numeric_literals_(false), |
harmony_classes_(false), |
- harmony_templates_(false) {} |
+ harmony_templates_(false), |
+ harmony_unicode_(false) {} |
void Scanner::Initialize(Utf16CharacterStream* source) { |
@@ -72,6 +73,22 @@ uc32 Scanner::ScanHexNumber(int expected_length) { |
} |
+uc32 Scanner::ScanUnlimitedLengthHexNumber(int max_value) { |
+ uc32 x = 0; |
+ int d = HexValue(c0_); |
+ if (d < 0) { |
+ return -1; |
+ } |
+ while (d >= 0) { |
+ x = x * 16 + d; |
+ if (x > max_value) return -1; |
+ Advance(); |
+ d = HexValue(c0_); |
+ } |
+ return x; |
+} |
+ |
+ |
// Ensure that tokens can be stored in a byte. |
STATIC_ASSERT(Token::NUM_TOKENS <= 0x100); |
@@ -700,7 +717,7 @@ bool Scanner::ScanEscape() { |
case 'r' : c = '\r'; break; |
case 't' : c = '\t'; break; |
case 'u' : { |
- c = ScanHexNumber(4); |
+ c = ScanUnicodeEscape(); |
if (c < 0) return false; |
break; |
} |
@@ -964,6 +981,26 @@ uc32 Scanner::ScanIdentifierUnicodeEscape() { |
Advance(); |
if (c0_ != 'u') return -1; |
Advance(); |
+ return ScanUnicodeEscape(); |
+} |
+ |
+ |
+uc32 Scanner::ScanUnicodeEscape() { |
+ // Accept both \uxxxx and \u{xxxxxx} (if harmony unicode escapes are |
+ // allowed). In the latter case, the number of hex digits between { } is |
+ // arbitrary. \ and u have already been read. |
+ if (c0_ == '{' && HarmonyUnicode()) { |
+ Advance(); |
+ uc32 cp = ScanUnlimitedLengthHexNumber(0x10ffff); |
+ if (cp < 0) { |
+ return -1; |
+ } |
+ if (c0_ != '}') { |
+ return -1; |
+ } |
+ Advance(); |
+ return cp; |
+ } |
return ScanHexNumber(4); |
} |