| Index: src/scanner.h
|
| diff --git a/src/scanner.h b/src/scanner.h
|
| index 2e96a99d874d8f22d4cf7524768f68c5fb3cd921..5f7a8680d2ccddb2f5bc62f2d62dbc5b2c0bbf6a 100644
|
| --- a/src/scanner.h
|
| +++ b/src/scanner.h
|
| @@ -322,23 +322,30 @@ class LiteralBuffer {
|
| // JavaScript Scanner.
|
|
|
| class Scanner {
|
| + struct TokenDesc;
|
| +
|
| public:
|
| + static const int kMaxLookahead = 2;
|
| +
|
| // Scoped helper for literal recording. Automatically drops the literal
|
| // if aborting the scanning before it's complete.
|
| class LiteralScope {
|
| public:
|
| explicit LiteralScope(Scanner* self) : scanner_(self), complete_(false) {
|
| - scanner_->StartLiteral();
|
| + next_ = scanner_->PeekTokenDesc();
|
| + scanner_->StartLiteral(next_);
|
| }
|
| ~LiteralScope() {
|
| - if (!complete_) scanner_->DropLiteral();
|
| + if (!complete_) scanner_->DropLiteral(next_);
|
| }
|
| void Complete() {
|
| complete_ = true;
|
| }
|
|
|
| private:
|
| + friend class Scanner;
|
| Scanner* scanner_;
|
| + TokenDesc* next_;
|
| bool complete_;
|
| };
|
|
|
| @@ -375,9 +382,11 @@ class Scanner {
|
| // Similar functions for the upcoming token.
|
|
|
| // One token look-ahead (past the token returned by Next()).
|
| - Token::Value peek() const { return next_.token; }
|
| + Token::Value peek() const { return next_[0].token; }
|
| + Token::Value peek(int n);
|
|
|
| - Location peek_location() const { return next_.location; }
|
| + Location peek_location() const { return next_[0].location; }
|
| + Location peek_location(int n);
|
|
|
| bool literal_contains_escapes() const {
|
| Location location = current_.location;
|
| @@ -393,8 +402,8 @@ class Scanner {
|
| return current_.literal_chars->is_contextual_keyword(keyword);
|
| }
|
| bool is_next_contextual_keyword(Vector<const char> keyword) {
|
| - DCHECK_NOT_NULL(next_.literal_chars);
|
| - return next_.literal_chars->is_contextual_keyword(keyword);
|
| + DCHECK_NOT_NULL(next_[0].literal_chars);
|
| + return next_[0].literal_chars->is_contextual_keyword(keyword);
|
| }
|
|
|
| const AstRawString* CurrentSymbol(AstValueFactory* ast_value_factory);
|
| @@ -525,42 +534,43 @@ class Scanner {
|
| }
|
|
|
| // Literal buffer support
|
| - inline void StartLiteral() {
|
| + inline void StartLiteral(TokenDesc* next) {
|
| LiteralBuffer* free_buffer = (current_.literal_chars == &literal_buffer1_) ?
|
| &literal_buffer2_ : &literal_buffer1_;
|
| free_buffer->Reset();
|
| - next_.literal_chars = free_buffer;
|
| + next->literal_chars = free_buffer;
|
| }
|
|
|
| inline void StartRawLiteral() {
|
| + TokenDesc* next = PeekTokenDesc();
|
| raw_literal_buffer_.Reset();
|
| - next_.raw_literal_chars = &raw_literal_buffer_;
|
| + next->raw_literal_chars = &raw_literal_buffer_;
|
| }
|
|
|
| - INLINE(void AddLiteralChar(uc32 c)) {
|
| - DCHECK_NOT_NULL(next_.literal_chars);
|
| - next_.literal_chars->AddChar(c);
|
| + INLINE(void AddLiteralChar(TokenDesc* next, uc32 c)) {
|
| + DCHECK_NOT_NULL(next->literal_chars);
|
| + next->literal_chars->AddChar(c);
|
| }
|
|
|
| - INLINE(void AddRawLiteralChar(uc32 c)) {
|
| - DCHECK_NOT_NULL(next_.raw_literal_chars);
|
| - next_.raw_literal_chars->AddChar(c);
|
| + INLINE(void AddRawLiteralChar(TokenDesc* next, uc32 c)) {
|
| + DCHECK_NOT_NULL(next->raw_literal_chars);
|
| + next->raw_literal_chars->AddChar(c);
|
| }
|
|
|
| - INLINE(void ReduceRawLiteralLength(int delta)) {
|
| - DCHECK_NOT_NULL(next_.raw_literal_chars);
|
| - next_.raw_literal_chars->ReduceLength(delta);
|
| + INLINE(void ReduceRawLiteralLength(TokenDesc* next, int delta)) {
|
| + DCHECK_NOT_NULL(next->raw_literal_chars);
|
| + next->raw_literal_chars->ReduceLength(delta);
|
| }
|
|
|
| // Stops scanning of a literal and drop the collected characters,
|
| // e.g., due to an encountered error.
|
| - inline void DropLiteral() {
|
| - next_.literal_chars = NULL;
|
| - next_.raw_literal_chars = NULL;
|
| + inline void DropLiteral(TokenDesc* next) {
|
| + next->literal_chars = NULL;
|
| + next->raw_literal_chars = NULL;
|
| }
|
|
|
| - inline void AddLiteralCharAdvance() {
|
| - AddLiteralChar(c0_);
|
| + inline void AddLiteralCharAdvance(TokenDesc* next) {
|
| + AddLiteralChar(next, c0_);
|
| Advance();
|
| }
|
|
|
| @@ -568,7 +578,7 @@ class Scanner {
|
| template <bool capture_raw = false, bool check_surrogate = true>
|
| void Advance() {
|
| if (capture_raw) {
|
| - AddRawLiteralChar(c0_);
|
| + AddRawLiteralChar(PeekTokenDesc(), c0_);
|
| }
|
| c0_ = source_->Advance();
|
| if (check_surrogate) HandleLeadSurrogate();
|
| @@ -636,16 +646,16 @@ class Scanner {
|
| // Returns the literal string for the next token (the token that
|
| // would be returned if Next() were called).
|
| Vector<const uint8_t> next_literal_one_byte_string() {
|
| - DCHECK_NOT_NULL(next_.literal_chars);
|
| - return next_.literal_chars->one_byte_literal();
|
| + DCHECK_NOT_NULL(next_[0].literal_chars);
|
| + return next_[0].literal_chars->one_byte_literal();
|
| }
|
| Vector<const uint16_t> next_literal_two_byte_string() {
|
| - DCHECK_NOT_NULL(next_.literal_chars);
|
| - return next_.literal_chars->two_byte_literal();
|
| + DCHECK_NOT_NULL(next_[0].literal_chars);
|
| + return next_[0].literal_chars->two_byte_literal();
|
| }
|
| bool is_next_literal_one_byte() {
|
| - DCHECK_NOT_NULL(next_.literal_chars);
|
| - return next_.literal_chars->is_one_byte();
|
| + DCHECK_NOT_NULL(next_[0].literal_chars);
|
| + return next_[0].literal_chars->is_one_byte();
|
| }
|
| Vector<const uint8_t> raw_literal_one_byte_string() {
|
| DCHECK_NOT_NULL(current_.raw_literal_chars);
|
| @@ -669,7 +679,7 @@ class Scanner {
|
| uc32 ScanUnlimitedLengthHexNumber(int max_value);
|
|
|
| // Scans a single JavaScript token.
|
| - void Scan();
|
| + void Scan(TokenDesc* next);
|
|
|
| bool SkipWhiteSpace();
|
| Token::Value SkipSingleLineComment();
|
| @@ -679,7 +689,7 @@ class Scanner {
|
| // Scans a possible HTML comment -- begins with '<!'.
|
| Token::Value ScanHtmlComment();
|
|
|
| - void ScanDecimalDigits();
|
| + void ScanDecimalDigits(TokenDesc* next);
|
| Token::Value ScanNumber(bool seen_period);
|
| Token::Value ScanIdentifierOrKeyword();
|
| Token::Value ScanIdentifierSuffix(LiteralScope* literal);
|
| @@ -690,7 +700,7 @@ class Scanner {
|
| // decoded character to the current literal. Returns true if a pattern
|
| // is scanned.
|
| template <bool capture_raw, bool in_template_literal>
|
| - bool ScanEscape();
|
| + bool ScanEscape(TokenDesc* next);
|
|
|
| // Decodes a Unicode escape-sequence which is part of an identifier.
|
| // If the escape sequence cannot be decoded the result is kBadChar.
|
| @@ -720,7 +730,18 @@ class Scanner {
|
| LiteralBuffer raw_literal_buffer_;
|
|
|
| TokenDesc current_; // desc for current token (as returned by Next())
|
| - TokenDesc next_; // desc for next token (one token look-ahead)
|
| + TokenDesc next_[kMaxLookahead]; // desc for next (look-ahead) tokens
|
| + int peek_count_; // number of peek tokens available (normally 1)
|
| +
|
| + INLINE(TokenDesc* PeekTokenDesc(int count)) {
|
| + DCHECK(count >= 0 && count < kMaxLookahead);
|
| + return &(next_[count]);
|
| + }
|
| +
|
| + INLINE(TokenDesc* PeekTokenDesc()) { return PeekTokenDesc(peek_count_ - 1); }
|
| +
|
| + // Scan multiple lookahead tokens
|
| + void PeekScan(int count);
|
|
|
| // Input stream. Must be initialized to an Utf16CharacterStream.
|
| Utf16CharacterStream* source_;
|
|
|