| Index: src/scanner.cc | 
| diff --git a/src/scanner.cc b/src/scanner.cc | 
| index 7911be0cdbd95aed372f94968888d5f9f367d3aa..1a8d721c0ebed544b47efe1612c2ebaee2ec3285 100755 | 
| --- a/src/scanner.cc | 
| +++ b/src/scanner.cc | 
| @@ -319,6 +319,26 @@ void KeywordMatcher::Step(uc32 input) { | 
| } | 
|  | 
|  | 
| + | 
| +// ---------------------------------------------------------------------------- | 
| +// Scanner::LiteralScope | 
| + | 
| +Scanner::LiteralScope::LiteralScope(Scanner* self) | 
| +    : scanner_(self), complete_(false) { | 
| +  self->StartLiteral(); | 
| +} | 
| + | 
| + | 
| +Scanner::LiteralScope::~LiteralScope() { | 
| +  if (!complete_) scanner_->DropLiteral(); | 
| +} | 
| + | 
| + | 
| +void Scanner::LiteralScope::Complete() { | 
| +  scanner_->TerminateLiteral(); | 
| +  complete_ = true; | 
| +} | 
| + | 
| // ---------------------------------------------------------------------------- | 
| // Scanner | 
|  | 
| @@ -386,8 +406,10 @@ void Scanner::Init(Handle<String> source, | 
| // Set c0_ (one character ahead) | 
| ASSERT(kCharacterLookaheadBufferSize == 1); | 
| Advance(); | 
| -  // Initialise current_ to not refer to a literal. | 
| +  // Initialize current_ to not refer to a literal. | 
| current_.literal_chars = Vector<const char>(); | 
| +  // Reset literal buffer. | 
| +  literal_buffer_.Reset(); | 
|  | 
| // Skip initial whitespace allowing HTML comment ends just like | 
| // after a newline and scan first token. | 
| @@ -423,11 +445,17 @@ void Scanner::AddChar(uc32 c) { | 
| literal_buffer_.AddChar(c); | 
| } | 
|  | 
| + | 
| void Scanner::TerminateLiteral() { | 
| next_.literal_chars = literal_buffer_.EndLiteral(); | 
| } | 
|  | 
|  | 
| +void Scanner::DropLiteral() { | 
| +  literal_buffer_.DropLiteral(); | 
| +} | 
| + | 
| + | 
| void Scanner::AddCharAdvance() { | 
| AddChar(c0_); | 
| Advance(); | 
| @@ -636,7 +664,7 @@ void Scanner::ScanJson() { | 
| Token::Value Scanner::ScanJsonString() { | 
| ASSERT_EQ('"', c0_); | 
| Advance(); | 
| -  StartLiteral(); | 
| +  LiteralScope literal(this); | 
| while (c0_ != '"' && c0_ > 0) { | 
| // Check for control character (0x00-0x1f) or unterminated string (<0). | 
| if (c0_ < 0x20) return Token::ILLEGAL; | 
| @@ -670,7 +698,9 @@ Token::Value Scanner::ScanJsonString() { | 
| for (int i = 0; i < 4; i++) { | 
| Advance(); | 
| int digit = HexValue(c0_); | 
| -            if (digit < 0) return Token::ILLEGAL; | 
| +            if (digit < 0) { | 
| +              return Token::ILLEGAL; | 
| +            } | 
| value = value * 16 + digit; | 
| } | 
| AddChar(value); | 
| @@ -685,14 +715,14 @@ Token::Value Scanner::ScanJsonString() { | 
| if (c0_ != '"') { | 
| return Token::ILLEGAL; | 
| } | 
| -  TerminateLiteral(); | 
| +  literal.Complete(); | 
| Advance(); | 
| return Token::STRING; | 
| } | 
|  | 
|  | 
| Token::Value Scanner::ScanJsonNumber() { | 
| -  StartLiteral(); | 
| +  LiteralScope literal(this); | 
| if (c0_ == '-') AddCharAdvance(); | 
| if (c0_ == '0') { | 
| AddCharAdvance(); | 
| @@ -720,21 +750,21 @@ Token::Value Scanner::ScanJsonNumber() { | 
| AddCharAdvance(); | 
| } while (c0_ >= '0' && c0_ <= '9'); | 
| } | 
| -  TerminateLiteral(); | 
| +  literal.Complete(); | 
| return Token::NUMBER; | 
| } | 
|  | 
|  | 
| Token::Value Scanner::ScanJsonIdentifier(const char* text, | 
| Token::Value token) { | 
| -  StartLiteral(); | 
| +  LiteralScope literal(this); | 
| while (*text != '\0') { | 
| if (c0_ != *text) return Token::ILLEGAL; | 
| Advance(); | 
| text++; | 
| } | 
| if (kIsIdentifierPart.get(c0_)) return Token::ILLEGAL; | 
| -  TerminateLiteral(); | 
| +  literal.Complete(); | 
| return token; | 
| } | 
|  | 
| @@ -1077,7 +1107,7 @@ Token::Value Scanner::ScanString() { | 
| uc32 quote = c0_; | 
| Advance();  // consume quote | 
|  | 
| -  StartLiteral(); | 
| +  LiteralScope literal(this); | 
| while (c0_ != quote && c0_ >= 0 && !kIsLineTerminator.get(c0_)) { | 
| uc32 c = c0_; | 
| Advance(); | 
| @@ -1088,10 +1118,8 @@ Token::Value Scanner::ScanString() { | 
| AddChar(c); | 
| } | 
| } | 
| -  if (c0_ != quote) { | 
| -    return Token::ILLEGAL; | 
| -  } | 
| -  TerminateLiteral(); | 
| +  if (c0_ != quote) return Token::ILLEGAL; | 
| +  literal.Complete(); | 
|  | 
| Advance();  // consume quote | 
| return Token::STRING; | 
| @@ -1127,7 +1155,7 @@ Token::Value Scanner::ScanNumber(bool seen_period) { | 
|  | 
| enum { DECIMAL, HEX, OCTAL } kind = DECIMAL; | 
|  | 
| -  StartLiteral(); | 
| +  LiteralScope literal(this); | 
| if (seen_period) { | 
| // we have already seen a decimal point of the float | 
| AddChar('.'); | 
| @@ -1143,12 +1171,13 @@ Token::Value Scanner::ScanNumber(bool seen_period) { | 
| // hex number | 
| kind = HEX; | 
| AddCharAdvance(); | 
| -        if (!IsHexDigit(c0_)) | 
| +        if (!IsHexDigit(c0_)) { | 
| // we must have at least one hex digit after 'x'/'X' | 
| return Token::ILLEGAL; | 
| -        while (IsHexDigit(c0_)) | 
| +        } | 
| +        while (IsHexDigit(c0_)) { | 
| AddCharAdvance(); | 
| - | 
| +        } | 
| } else if ('0' <= c0_ && c0_ <= '7') { | 
| // (possible) octal number | 
| kind = OCTAL; | 
| @@ -1181,12 +1210,12 @@ Token::Value Scanner::ScanNumber(bool seen_period) { | 
| AddCharAdvance(); | 
| if (c0_ == '+' || c0_ == '-') | 
| AddCharAdvance(); | 
| -    if (!IsDecimalDigit(c0_)) | 
| +    if (!IsDecimalDigit(c0_)) { | 
| // we must have at least one decimal digit after 'e'/'E' | 
| return Token::ILLEGAL; | 
| +    } | 
| ScanDecimalDigits(); | 
| } | 
| -  TerminateLiteral(); | 
|  | 
| // The source character immediately following a numeric literal must | 
| // not be an identifier start or a decimal digit; see ECMA-262 | 
| @@ -1195,6 +1224,8 @@ Token::Value Scanner::ScanNumber(bool seen_period) { | 
| if (IsDecimalDigit(c0_) || kIsIdentifierStart.get(c0_)) | 
| return Token::ILLEGAL; | 
|  | 
| +  literal.Complete(); | 
| + | 
| return Token::NUMBER; | 
| } | 
|  | 
| @@ -1214,7 +1245,7 @@ uc32 Scanner::ScanIdentifierUnicodeEscape() { | 
| Token::Value Scanner::ScanIdentifier() { | 
| ASSERT(kIsIdentifierStart.get(c0_)); | 
|  | 
| -  StartLiteral(); | 
| +  LiteralScope literal(this); | 
| KeywordMatcher keyword_match; | 
|  | 
| // Scan identifier start character. | 
| @@ -1244,7 +1275,7 @@ Token::Value Scanner::ScanIdentifier() { | 
| Advance(); | 
| } | 
| } | 
| -  TerminateLiteral(); | 
| +  literal.Complete(); | 
|  | 
| return keyword_match.token(); | 
| } | 
| @@ -1274,36 +1305,32 @@ bool Scanner::ScanRegExpPattern(bool seen_equal) { | 
| // Scan regular expression body: According to ECMA-262, 3rd, 7.8.5, | 
| // the scanner should pass uninterpreted bodies to the RegExp | 
| // constructor. | 
| -  StartLiteral(); | 
| +  LiteralScope literal(this); | 
| if (seen_equal) | 
| AddChar('='); | 
|  | 
| while (c0_ != '/' || in_character_class) { | 
| -    if (kIsLineTerminator.get(c0_) || c0_ < 0) | 
| -      return false; | 
| +    if (kIsLineTerminator.get(c0_) || c0_ < 0) return false; | 
| if (c0_ == '\\') {  // escaped character | 
| AddCharAdvance(); | 
| -      if (kIsLineTerminator.get(c0_) || c0_ < 0) | 
| -        return false; | 
| +      if (kIsLineTerminator.get(c0_) || c0_ < 0) return false; | 
| AddCharAdvance(); | 
| } else {  // unescaped character | 
| -      if (c0_ == '[') | 
| -        in_character_class = true; | 
| -      if (c0_ == ']') | 
| -        in_character_class = false; | 
| +      if (c0_ == '[') in_character_class = true; | 
| +      if (c0_ == ']') in_character_class = false; | 
| AddCharAdvance(); | 
| } | 
| } | 
| Advance();  // consume '/' | 
|  | 
| -  TerminateLiteral(); | 
| +  literal.Complete(); | 
|  | 
| return true; | 
| } | 
|  | 
| bool Scanner::ScanRegExpFlags() { | 
| // Scan regular expression flags. | 
| -  StartLiteral(); | 
| +  LiteralScope literal(this); | 
| while (kIsIdentifierPart.get(c0_)) { | 
| if (c0_ == '\\') { | 
| uc32 c = ScanIdentifierUnicodeEscape(); | 
| @@ -1316,7 +1343,7 @@ bool Scanner::ScanRegExpFlags() { | 
| } | 
| AddCharAdvance(); | 
| } | 
| -  TerminateLiteral(); | 
| +  literal.Complete(); | 
|  | 
| next_.location.end_pos = source_pos() - 1; | 
| return true; | 
|  |