Index: src/parsing/scanner.cc |
diff --git a/src/parsing/scanner.cc b/src/parsing/scanner.cc |
index a7d0a09b5d723acaa40b3ecc1cff82b7c0a1a7e7..f9438ca11da40ace4cca7b22bee8e96c90da6df8 100644 |
--- a/src/parsing/scanner.cc |
+++ b/src/parsing/scanner.cc |
@@ -260,6 +260,8 @@ Token::Value Scanner::Next() { |
next_.token = token; |
next_.location.beg_pos = pos; |
next_.location.end_pos = pos + 1; |
+ next_.literal_chars = nullptr; |
+ next_.raw_literal_chars = nullptr; |
Advance(); |
return current_.token; |
} |
@@ -270,6 +272,9 @@ Token::Value Scanner::Next() { |
Token::Value Scanner::PeekAhead() { |
+ DCHECK(next_.token != Token::DIV); |
+ DCHECK(next_.token != Token::ASSIGN_DIV); |
+ |
if (next_next_.token != Token::UNINITIALIZED) { |
return next_next_.token; |
} |
@@ -731,8 +736,50 @@ void Scanner::Scan() { |
next_.location.end_pos = source_pos(); |
next_.token = token; |
+ |
+#ifdef DEBUG |
+ SanityCheckTokenDesc(current_); |
+ SanityCheckTokenDesc(next_); |
+ SanityCheckTokenDesc(next_next_); |
+#endif |
} |
+#ifdef DEBUG |
+void Scanner::SanityCheckTokenDesc(const TokenDesc& token) const { |
+ // Most tokens should not have literal_chars or even raw_literal chars. |
+ // The rules are: |
+ // - UNINITIALIZED: we don't care. |
+ // - TEMPLATE_*: need both literal + raw literal chars. |
+ // - IDENTIFIERS, STRINGS, etc.: need a literal, but no raw literal. |
+ // - all others: should have neither. |
+ |
+ switch (token.token) { |
+ case Token::UNINITIALIZED: |
+ // token.literal_chars & other members might be garbage. That's ok. |
+ break; |
+ case Token::TEMPLATE_SPAN: |
+ case Token::TEMPLATE_TAIL: |
+ DCHECK_NOT_NULL(token.raw_literal_chars); |
+ DCHECK_NOT_NULL(token.literal_chars); |
+ break; |
+ case Token::ESCAPED_KEYWORD: |
+ case Token::ESCAPED_STRICT_RESERVED_WORD: |
+ case Token::FUTURE_STRICT_RESERVED_WORD: |
+ case Token::IDENTIFIER: |
+ case Token::NUMBER: |
+ case Token::REGEXP_LITERAL: |
+ case Token::SMI: |
+ case Token::STRING: |
+ DCHECK_NOT_NULL(token.literal_chars); |
+ DCHECK_NULL(token.raw_literal_chars); |
+ break; |
+ default: |
+ DCHECK_NULL(token.literal_chars); |
+ DCHECK_NULL(token.raw_literal_chars); |
+ break; |
+ } |
+} |
+#endif // DEBUG |
void Scanner::SeekForward(int pos) { |
// After this call, we will have the token at the given position as |
@@ -954,6 +1001,7 @@ Token::Value Scanner::ScanTemplateSpan() { |
Token::Value Scanner::ScanTemplateStart() { |
+ DCHECK(next_next_.token == Token::UNINITIALIZED); |
DCHECK(c0_ == '`'); |
next_.location.beg_pos = source_pos(); |
Advance(); // Consume ` |
@@ -1216,7 +1264,7 @@ uc32 Scanner::ScanUnicodeEscape() { |
KEYWORD("yield", Token::YIELD) |
static Token::Value KeywordOrIdentifierToken(const uint8_t* input, |
- int input_length, bool escaped) { |
+ int input_length) { |
DCHECK(input_length >= 1); |
const int kMinLength = 2; |
const int kMaxLength = 10; |
@@ -1244,13 +1292,6 @@ static Token::Value KeywordOrIdentifierToken(const uint8_t* input, |
(keyword_length <= 7 || input[7] == keyword[7]) && \ |
(keyword_length <= 8 || input[8] == keyword[8]) && \ |
(keyword_length <= 9 || input[9] == keyword[9])) { \ |
- if (escaped) { \ |
- /* TODO(adamk): YIELD should be handled specially. */ \ |
- return (token == Token::FUTURE_STRICT_RESERVED_WORD || \ |
- token == Token::LET || token == Token::STATIC) \ |
- ? Token::ESCAPED_STRICT_RESERVED_WORD \ |
- : Token::ESCAPED_KEYWORD; \ |
- } \ |
return token; \ |
} \ |
} |
@@ -1269,7 +1310,7 @@ bool Scanner::IdentifierIsFutureStrictReserved( |
return true; |
} |
return Token::FUTURE_STRICT_RESERVED_WORD == |
- KeywordOrIdentifierToken(string->raw_data(), string->length(), false); |
+ KeywordOrIdentifierToken(string->raw_data(), string->length()); |
} |
@@ -1300,9 +1341,13 @@ Token::Value Scanner::ScanIdentifierOrKeyword() { |
} |
} else if (c0_ <= kMaxAscii && c0_ != '\\') { |
// Only a-z+: could be a keyword or identifier. |
- literal.Complete(); |
Vector<const uint8_t> chars = next_.literal_chars->one_byte_literal(); |
- return KeywordOrIdentifierToken(chars.start(), chars.length(), false); |
+ Token::Value token = |
+ KeywordOrIdentifierToken(chars.start(), chars.length()); |
+ if (token == Token::IDENTIFIER || |
+ token == Token::FUTURE_STRICT_RESERVED_WORD) |
+ literal.Complete(); |
+ return token; |
} |
HandleLeadSurrogate(); |
@@ -1348,12 +1393,14 @@ Token::Value Scanner::ScanIdentifierOrKeyword() { |
return ScanIdentifierSuffix(&literal, false); |
} |
- literal.Complete(); |
- |
if (next_.literal_chars->is_one_byte()) { |
Vector<const uint8_t> chars = next_.literal_chars->one_byte_literal(); |
- return KeywordOrIdentifierToken(chars.start(), chars.length(), false); |
+ Token::Value token = |
+ KeywordOrIdentifierToken(chars.start(), chars.length()); |
+ if (token == Token::IDENTIFIER) literal.Complete(); |
+ return token; |
} |
+ literal.Complete(); |
return Token::IDENTIFIER; |
} |
@@ -1381,15 +1428,28 @@ Token::Value Scanner::ScanIdentifierSuffix(LiteralScope* literal, |
if (escaped && next_.literal_chars->is_one_byte()) { |
Vector<const uint8_t> chars = next_.literal_chars->one_byte_literal(); |
- return KeywordOrIdentifierToken(chars.start(), chars.length(), true); |
+ Token::Value token = |
+ KeywordOrIdentifierToken(chars.start(), chars.length()); |
+ /* TODO(adamk): YIELD should be handled specially. */ |
+ if (token == Token::IDENTIFIER) { |
+ return Token::IDENTIFIER; |
+ } else if (token == Token::FUTURE_STRICT_RESERVED_WORD || |
+ token == Token::LET || token == Token::STATIC) { |
+ return Token::ESCAPED_STRICT_RESERVED_WORD; |
+ } else { |
+ return Token::ESCAPED_KEYWORD; |
+ } |
} |
return Token::IDENTIFIER; |
} |
+bool Scanner::ScanRegExpPattern() { |
+ DCHECK(next_next_.token == Token::UNINITIALIZED); |
+ DCHECK(next_.token == Token::DIV || next_.token == Token::ASSIGN_DIV); |
-bool Scanner::ScanRegExpPattern(bool seen_equal) { |
// Scan: ('/' | '/=') RegularExpressionBody '/' RegularExpressionFlags |
bool in_character_class = false; |
+ bool seen_equal = (next_.token == Token::ASSIGN_DIV); |
// Previous token is either '/' or '/=', in the second case, the |
// pattern starts at =. |
@@ -1429,14 +1489,15 @@ bool Scanner::ScanRegExpPattern(bool seen_equal) { |
Advance(); // consume '/' |
literal.Complete(); |
- |
+ next_.token = Token::REGEXP_LITERAL; |
return true; |
} |
Maybe<RegExp::Flags> Scanner::ScanRegExpFlags() { |
+ DCHECK(next_.token == Token::REGEXP_LITERAL); |
+ |
// Scan regular expression flags. |
- LiteralScope literal(this); |
int flags = 0; |
while (c0_ >= 0 && unicode_cache_->IsIdentifierPart(c0_)) { |
RegExp::Flags flag = RegExp::kNone; |
@@ -1459,11 +1520,12 @@ Maybe<RegExp::Flags> Scanner::ScanRegExpFlags() { |
default: |
return Nothing<RegExp::Flags>(); |
} |
- if (flags & flag) return Nothing<RegExp::Flags>(); |
- AddLiteralCharAdvance(); |
+ if (flags & flag) { |
+ return Nothing<RegExp::Flags>(); |
+ } |
+ Advance(); |
flags |= flag; |
} |
- literal.Complete(); |
next_.location.end_pos = source_pos(); |
return Just(RegExp::Flags(flags)); |