LCOV - code coverage report
Current view: top level - src/parsing - scanner-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 115 116 99.1 %
Date: 2019-01-20 Functions: 4 4 100.0 %

          Line data    Source code
       1             : // Copyright 2018 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_PARSING_SCANNER_INL_H_
       6             : #define V8_PARSING_SCANNER_INL_H_
       7             : 
       8             : #include "src/char-predicates-inl.h"
       9             : #include "src/parsing/keywords-gen.h"
      10             : #include "src/parsing/scanner.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : 
      15             : // ----------------------------------------------------------------------------
      16             : // Keyword Matcher
      17             : 
      18             : #define KEYWORDS(KEYWORD_GROUP, KEYWORD)                    \
      19             :   KEYWORD_GROUP('a')                                        \
      20             :   KEYWORD("async", Token::ASYNC)                            \
      21             :   KEYWORD("await", Token::AWAIT)                            \
      22             :   KEYWORD_GROUP('b')                                        \
      23             :   KEYWORD("break", Token::BREAK)                            \
      24             :   KEYWORD_GROUP('c')                                        \
      25             :   KEYWORD("case", Token::CASE)                              \
      26             :   KEYWORD("catch", Token::CATCH)                            \
      27             :   KEYWORD("class", Token::CLASS)                            \
      28             :   KEYWORD("const", Token::CONST)                            \
      29             :   KEYWORD("continue", Token::CONTINUE)                      \
      30             :   KEYWORD_GROUP('d')                                        \
      31             :   KEYWORD("debugger", Token::DEBUGGER)                      \
      32             :   KEYWORD("default", Token::DEFAULT)                        \
      33             :   KEYWORD("delete", Token::DELETE)                          \
      34             :   KEYWORD("do", Token::DO)                                  \
      35             :   KEYWORD_GROUP('e')                                        \
      36             :   KEYWORD("else", Token::ELSE)                              \
      37             :   KEYWORD("enum", Token::ENUM)                              \
      38             :   KEYWORD("export", Token::EXPORT)                          \
      39             :   KEYWORD("extends", Token::EXTENDS)                        \
      40             :   KEYWORD_GROUP('f')                                        \
      41             :   KEYWORD("false", Token::FALSE_LITERAL)                    \
      42             :   KEYWORD("finally", Token::FINALLY)                        \
      43             :   KEYWORD("for", Token::FOR)                                \
      44             :   KEYWORD("function", Token::FUNCTION)                      \
      45             :   KEYWORD_GROUP('i')                                        \
      46             :   KEYWORD("if", Token::IF)                                  \
      47             :   KEYWORD("implements", Token::FUTURE_STRICT_RESERVED_WORD) \
      48             :   KEYWORD("import", Token::IMPORT)                          \
      49             :   KEYWORD("in", Token::IN)                                  \
      50             :   KEYWORD("instanceof", Token::INSTANCEOF)                  \
      51             :   KEYWORD("interface", Token::FUTURE_STRICT_RESERVED_WORD)  \
      52             :   KEYWORD_GROUP('l')                                        \
      53             :   KEYWORD("let", Token::LET)                                \
      54             :   KEYWORD_GROUP('n')                                        \
      55             :   KEYWORD("new", Token::NEW)                                \
      56             :   KEYWORD("null", Token::NULL_LITERAL)                      \
      57             :   KEYWORD_GROUP('p')                                        \
      58             :   KEYWORD("package", Token::FUTURE_STRICT_RESERVED_WORD)    \
      59             :   KEYWORD("private", Token::FUTURE_STRICT_RESERVED_WORD)    \
      60             :   KEYWORD("protected", Token::FUTURE_STRICT_RESERVED_WORD)  \
      61             :   KEYWORD("public", Token::FUTURE_STRICT_RESERVED_WORD)     \
      62             :   KEYWORD_GROUP('r')                                        \
      63             :   KEYWORD("return", Token::RETURN)                          \
      64             :   KEYWORD_GROUP('s')                                        \
      65             :   KEYWORD("static", Token::STATIC)                          \
      66             :   KEYWORD("super", Token::SUPER)                            \
      67             :   KEYWORD("switch", Token::SWITCH)                          \
      68             :   KEYWORD_GROUP('t')                                        \
      69             :   KEYWORD("this", Token::THIS)                              \
      70             :   KEYWORD("throw", Token::THROW)                            \
      71             :   KEYWORD("true", Token::TRUE_LITERAL)                      \
      72             :   KEYWORD("try", Token::TRY)                                \
      73             :   KEYWORD("typeof", Token::TYPEOF)                          \
      74             :   KEYWORD_GROUP('v')                                        \
      75             :   KEYWORD("var", Token::VAR)                                \
      76             :   KEYWORD("void", Token::VOID)                              \
      77             :   KEYWORD_GROUP('w')                                        \
      78             :   KEYWORD("while", Token::WHILE)                            \
      79             :   KEYWORD("with", Token::WITH)                              \
      80             :   KEYWORD_GROUP('y')                                        \
      81             :   KEYWORD("yield", Token::YIELD)
      82             : 
      83             : constexpr bool IsKeywordStart(char c) {
      84             : #define KEYWORD_GROUP_CHECK(ch) c == ch ||
      85             : #define KEYWORD_CHECK(keyword, token)
      86             :   return KEYWORDS(KEYWORD_GROUP_CHECK, KEYWORD_CHECK) /* || */ false;
      87             : #undef KEYWORD_GROUP_CHECK
      88             : #undef KEYWORD_CHECK
      89             : }
      90             : 
      91             : V8_INLINE Token::Value KeywordOrIdentifierToken(const uint8_t* input,
      92             :                                                 int input_length) {
      93             :   DCHECK_GE(input_length, 1);
      94             :   return PerfectKeywordHash::GetToken(reinterpret_cast<const char*>(input),
      95    76442136 :                                       input_length);
      96             : }
      97             : 
      98             : // Recursive constexpr template magic to check if a character is in a given
      99             : // string.
     100             : template <int N>
     101             : constexpr bool IsInString(const char (&s)[N], char c, size_t i = 0) {
     102             :   return i >= N ? false : s[i] == c ? true : IsInString(s, c, i + 1);
     103             : }
     104             : 
     105             : inline constexpr bool CanBeKeywordCharacter(char c) {
     106             :   return IsInString(
     107             : #define KEYWORD_GROUP_CASE(ch)  // Nothing
     108             : #define KEYWORD(keyword, token) keyword
     109             :       // Use C string literal concatenation ("a" "b" becomes "ab") to build one
     110             :       // giant string containing all the keywords.
     111             :       KEYWORDS(KEYWORD_GROUP_CASE, KEYWORD)
     112             : #undef KEYWORD
     113             : #undef KEYWORD_GROUP_CASE
     114             :           ,
     115             :       c);
     116             : }
     117             : 
     118             : // Make sure tokens are stored as a single byte.
     119             : STATIC_ASSERT(sizeof(Token::Value) == 1);
     120             : 
     121             : // Get the shortest token that this character starts, the token may change
     122             : // depending on subsequent characters.
     123             : constexpr Token::Value GetOneCharToken(char c) {
     124             :   // clang-format off
     125             :   return
     126             :       c == '(' ? Token::LPAREN :
     127             :       c == ')' ? Token::RPAREN :
     128             :       c == '{' ? Token::LBRACE :
     129             :       c == '}' ? Token::RBRACE :
     130             :       c == '[' ? Token::LBRACK :
     131             :       c == ']' ? Token::RBRACK :
     132             :       c == '?' ? Token::CONDITIONAL :
     133             :       c == ':' ? Token::COLON :
     134             :       c == ';' ? Token::SEMICOLON :
     135             :       c == ',' ? Token::COMMA :
     136             :       c == '.' ? Token::PERIOD :
     137             :       c == '|' ? Token::BIT_OR :
     138             :       c == '&' ? Token::BIT_AND :
     139             :       c == '^' ? Token::BIT_XOR :
     140             :       c == '~' ? Token::BIT_NOT :
     141             :       c == '!' ? Token::NOT :
     142             :       c == '<' ? Token::LT :
     143             :       c == '>' ? Token::GT :
     144             :       c == '%' ? Token::MOD :
     145             :       c == '=' ? Token::ASSIGN :
     146             :       c == '+' ? Token::ADD :
     147             :       c == '-' ? Token::SUB :
     148             :       c == '*' ? Token::MUL :
     149             :       c == '/' ? Token::DIV :
     150             :       c == '#' ? Token::PRIVATE_NAME :
     151             :       c == '"' ? Token::STRING :
     152             :       c == '\'' ? Token::STRING :
     153             :       c == '`' ? Token::TEMPLATE_SPAN :
     154             :       c == '\\' ? Token::IDENTIFIER :
     155             :       // Whitespace or line terminator
     156             :       c == ' ' ? Token::WHITESPACE :
     157             :       c == '\t' ? Token::WHITESPACE :
     158             :       c == '\v' ? Token::WHITESPACE :
     159             :       c == '\f' ? Token::WHITESPACE :
     160             :       c == '\r' ? Token::WHITESPACE :
     161             :       c == '\n' ? Token::WHITESPACE :
     162             :       // IsDecimalDigit must be tested before IsAsciiIdentifier
     163             :       IsDecimalDigit(c) ? Token::NUMBER :
     164             :       IsAsciiIdentifier(c) ? Token::IDENTIFIER :
     165             :       Token::ILLEGAL;
     166             :   // clang-format on
     167             : }
     168             : 
     169             : // Table of one-character tokens, by character (0x00..0x7F only).
     170             : static const constexpr Token::Value one_char_tokens[128] = {
     171             : #define CALL_GET_SCAN_FLAGS(N) GetOneCharToken(N),
     172             :     INT_0_TO_127_LIST(CALL_GET_SCAN_FLAGS)
     173             : #undef CALL_GET_SCAN_FLAGS
     174             : };
     175             : 
     176             : #undef KEYWORDS
     177             : 
     178   129993811 : V8_INLINE Token::Value Scanner::ScanIdentifierOrKeyword() {
     179   129993811 :   next().literal_chars.Start();
     180             :   return ScanIdentifierOrKeywordInner();
     181             : }
     182             : 
     183             : // Character flags for the fast path of scanning a keyword or identifier token.
     184             : enum class ScanFlags : uint8_t {
     185             :   kTerminatesLiteral = 1 << 0,
     186             :   // "Cannot" rather than "can" so that this flag can be ORed together across
     187             :   // multiple characters.
     188             :   kCannotBeKeyword = 1 << 1,
     189             :   kCannotBeKeywordStart = 1 << 2,
     190             :   kStringTerminator = 1 << 3,
     191             :   kNeedsSlowPath = 1 << 4,
     192             : };
     193             : constexpr uint8_t GetScanFlags(char c) {
     194             :   return
     195             :       // Keywords are all lowercase and only contain letters.
     196             :       // Note that non-identifier characters do not set this flag, so
     197             :       // that it plays well with kTerminatesLiteral.
     198             :       (IsAsciiIdentifier(c) && !CanBeKeywordCharacter(c)
     199             :            ? static_cast<uint8_t>(ScanFlags::kCannotBeKeyword)
     200             :            : 0) |
     201             :       (IsKeywordStart(c)
     202             :            ? 0
     203             :            : static_cast<uint8_t>(ScanFlags::kCannotBeKeywordStart)) |
     204             :       // Anything that isn't an identifier character will terminate the
     205             :       // literal, or at least terminates the literal fast path processing
     206             :       // (like an escape).
     207             :       (!IsAsciiIdentifier(c)
     208             :            ? static_cast<uint8_t>(ScanFlags::kTerminatesLiteral)
     209             :            : 0) |
     210             :       // Possible string termination characters.
     211             :       ((c == '\'' || c == '"' || c == '\n' || c == '\r' || c == '\\')
     212             :            ? static_cast<uint8_t>(ScanFlags::kStringTerminator)
     213             :            : 0) |
     214             :       // Escapes are processed on the slow path.
     215             :       (c == '\\' ? static_cast<uint8_t>(ScanFlags::kNeedsSlowPath) : 0);
     216             : }
     217             : inline bool TerminatesLiteral(uint8_t scan_flags) {
     218   767273406 :   return (scan_flags & static_cast<uint8_t>(ScanFlags::kTerminatesLiteral));
     219             : }
     220   130062849 : inline bool CanBeKeyword(uint8_t scan_flags) {
     221   130117012 :   return !(scan_flags & static_cast<uint8_t>(ScanFlags::kCannotBeKeyword));
     222             : }
     223   130061895 : inline bool NeedsSlowPath(uint8_t scan_flags) {
     224   130061895 :   return (scan_flags & static_cast<uint8_t>(ScanFlags::kNeedsSlowPath));
     225             : }
     226             : inline bool MayTerminateString(uint8_t scan_flags) {
     227   183299922 :   return (scan_flags & static_cast<uint8_t>(ScanFlags::kStringTerminator));
     228             : }
     229             : // Table of precomputed scan flags for the 128 ASCII characters, for branchless
     230             : // flag calculation during the scan.
     231             : static constexpr const uint8_t character_scan_flags[128] = {
     232             : #define CALL_GET_SCAN_FLAGS(N) GetScanFlags(N),
     233             :     INT_0_TO_127_LIST(CALL_GET_SCAN_FLAGS)
     234             : #undef CALL_GET_SCAN_FLAGS
     235             : };
     236             : 
     237        2316 : inline bool CharCanBeKeyword(uc32 c) {
     238      108963 :   return static_cast<uint32_t>(c) < arraysize(character_scan_flags) &&
     239       56479 :          CanBeKeyword(character_scan_flags[c]);
     240             : }
     241             : 
     242   206335561 : V8_INLINE Token::Value Scanner::ScanIdentifierOrKeywordInner() {
     243             :   DCHECK(IsIdentifierStart(c0_));
     244             :   bool escaped = false;
     245             :   bool can_be_keyword = true;
     246             : 
     247             :   STATIC_ASSERT(arraysize(character_scan_flags) == kMaxAscii + 1);
     248   130046444 :   if (V8_LIKELY(static_cast<uint32_t>(c0_) <= kMaxAscii)) {
     249   130047198 :     if (V8_LIKELY(c0_ != '\\')) {
     250   130037267 :       uint8_t scan_flags = character_scan_flags[c0_];
     251             :       DCHECK(!TerminatesLiteral(scan_flags));
     252             :       STATIC_ASSERT(static_cast<uint8_t>(ScanFlags::kCannotBeKeywordStart) ==
     253             :                     static_cast<uint8_t>(ScanFlags::kCannotBeKeyword) << 1);
     254   130037267 :       scan_flags >>= 1;
     255             :       // Make sure the shifting above doesn't set NeedsSlowPath. Otherwise we'll
     256             :       // fall into the slow path after scanning the identifier.
     257             :       DCHECK(!NeedsSlowPath(scan_flags));
     258             :       AddLiteralChar(static_cast<char>(c0_));
     259   767273753 :       AdvanceUntil([this, &scan_flags](uc32 c0) {
     260   767273753 :         if (V8_UNLIKELY(static_cast<uint32_t>(c0) > kMaxAscii)) {
     261             :           // A non-ascii character means we need to drop through to the slow
     262             :           // path.
     263             :           // TODO(leszeks): This would be most efficient as a goto to the slow
     264             :           // path, check codegen and maybe use a bool instead.
     265         347 :           scan_flags |= static_cast<uint8_t>(ScanFlags::kNeedsSlowPath);
     266         347 :           return true;
     267             :         }
     268   767273406 :         uint8_t char_flags = character_scan_flags[c0];
     269   767273406 :         scan_flags |= char_flags;
     270   767273406 :         if (TerminatesLiteral(char_flags)) {
     271             :           return true;
     272             :         } else {
     273   637590458 :           AddLiteralChar(static_cast<char>(c0));
     274   637511715 :           return false;
     275             :         }
     276             :       });
     277             : 
     278   130049338 :       if (V8_LIKELY(!NeedsSlowPath(scan_flags))) {
     279   130051213 :         if (!CanBeKeyword(scan_flags)) return Token::IDENTIFIER;
     280             :         // Could be a keyword or identifier.
     281    76434936 :         Vector<const uint8_t> chars = next().literal_chars.one_byte_literal();
     282    76429820 :         return KeywordOrIdentifierToken(chars.start(), chars.length());
     283             :       }
     284             : 
     285       13596 :       can_be_keyword = CanBeKeyword(scan_flags);
     286             :     } else {
     287             :       // Special case for escapes at the start of an identifier.
     288             :       escaped = true;
     289        9931 :       uc32 c = ScanIdentifierUnicodeEscape();
     290             :       DCHECK(!IsIdentifierStart(-1));
     291        9931 :       if (c == '\\' || !IsIdentifierStart(c)) {
     292             :         return Token::ILLEGAL;
     293             :       }
     294             :       AddLiteralChar(c);
     295        2316 :       can_be_keyword = CharCanBeKeyword(c);
     296             :     }
     297             :   }
     298             : 
     299       15158 :   return ScanIdentifierOrKeywordInnerSlow(escaped, can_be_keyword);
     300             : }
     301             : 
     302   724741396 : V8_INLINE Token::Value Scanner::SkipWhiteSpace() {
     303   168842632 :   int start_position = source_pos();
     304             : 
     305             :   // We won't skip behind the end of input.
     306             :   DCHECK(!IsWhiteSpaceOrLineTerminator(kEndOfInput));
     307             : 
     308             :   // Advance as long as character is a WhiteSpace or LineTerminator.
     309   518830475 :   while (IsWhiteSpaceOrLineTerminator(c0_)) {
     310   521810420 :     if (!next().after_line_terminator && unibrow::IsLineTerminator(c0_)) {
     311    37044556 :       next().after_line_terminator = true;
     312             :     }
     313   350023180 :     Advance();
     314             :   }
     315             : 
     316             :   // Return whether or not we skipped any characters.
     317   168820081 :   if (source_pos() == start_position) {
     318             :     DCHECK_NE('0', c0_);
     319             :     return Token::ILLEGAL;
     320             :   }
     321             : 
     322             :   return Token::WHITESPACE;
     323             : }
     324             : 
     325  1192129877 : V8_INLINE Token::Value Scanner::ScanSingleToken() {
     326             :   Token::Value token;
     327   175890798 :   do {
     328  1125262004 :     next().location.beg_pos = source_pos();
     329             : 
     330   563494389 :     if (V8_LIKELY(static_cast<unsigned>(c0_) <= kMaxAscii)) {
     331   558766021 :       token = one_char_tokens[c0_];
     332             : 
     333   558766021 :       switch (token) {
     334             :         case Token::LPAREN:
     335             :         case Token::RPAREN:
     336             :         case Token::LBRACE:
     337             :         case Token::RBRACE:
     338             :         case Token::LBRACK:
     339             :         case Token::RBRACK:
     340             :         case Token::CONDITIONAL:
     341             :         case Token::COLON:
     342             :         case Token::SEMICOLON:
     343             :         case Token::COMMA:
     344             :         case Token::BIT_NOT:
     345             :         case Token::ILLEGAL:
     346             :           // One character tokens.
     347   156752990 :           return Select(token);
     348             : 
     349             :         case Token::STRING:
     350    10078947 :           return ScanString();
     351             : 
     352             :         case Token::LT:
     353             :           // < <= << <<= <!--
     354     1038136 :           Advance();
     355     1038182 :           if (c0_ == '=') return Select(Token::LTE);
     356      963019 :           if (c0_ == '<') return Select('=', Token::ASSIGN_SHL, Token::SHL);
     357      534197 :           if (c0_ == '!') {
     358          73 :             token = ScanHtmlComment();
     359             :             continue;
     360             :           }
     361             :           return Token::LT;
     362             : 
     363             :         case Token::GT:
     364             :           // > >= >> >>= >>> >>>=
     365      588342 :           Advance();
     366      588338 :           if (c0_ == '=') return Select(Token::GTE);
     367      525842 :           if (c0_ == '>') {
     368             :             // >> >>= >>> >>>=
     369      284243 :             Advance();
     370      284245 :             if (c0_ == '=') return Select(Token::ASSIGN_SAR);
     371      279106 :             if (c0_ == '>') return Select('=', Token::ASSIGN_SHR, Token::SHR);
     372             :             return Token::SAR;
     373             :           }
     374             :           return Token::GT;
     375             : 
     376             :         case Token::ASSIGN:
     377             :           // = == === =>
     378    25567883 :           Advance();
     379    25568258 :           if (c0_ == '=') return Select('=', Token::EQ_STRICT, Token::EQ);
     380    23930431 :           if (c0_ == '>') return Select(Token::ARROW);
     381             :           return Token::ASSIGN;
     382             : 
     383             :         case Token::NOT:
     384             :           // ! != !==
     385     1964313 :           Advance();
     386     1964317 :           if (c0_ == '=') return Select('=', Token::NE_STRICT, Token::NE);
     387             :           return Token::NOT;
     388             : 
     389             :         case Token::ADD:
     390             :           // + ++ +=
     391     4397096 :           Advance();
     392     4397089 :           if (c0_ == '+') return Select(Token::INC);
     393     3451430 :           if (c0_ == '=') return Select(Token::ASSIGN_ADD);
     394             :           return Token::ADD;
     395             : 
     396             :         case Token::SUB:
     397             :           // - -- --> -=
     398      818047 :           Advance();
     399      818038 :           if (c0_ == '-') {
     400      101805 :             Advance();
     401      102012 :             if (c0_ == '>' && next().after_line_terminator) {
     402             :               // For compatibility with SpiderMonkey, we skip lines that
     403             :               // start with an HTML comment end '-->'.
     404         154 :               token = SkipSingleHTMLComment();
     405             :               continue;
     406             :             }
     407             :             return Token::DEC;
     408             :           }
     409      716233 :           if (c0_ == '=') return Select(Token::ASSIGN_SUB);
     410             :           return Token::SUB;
     411             : 
     412             :         case Token::MUL:
     413             :           // * *=
     414      513385 :           Advance();
     415      513383 :           if (c0_ == '*') return Select('=', Token::ASSIGN_EXP, Token::EXP);
     416      504046 :           if (c0_ == '=') return Select(Token::ASSIGN_MUL);
     417             :           return Token::MUL;
     418             : 
     419             :         case Token::MOD:
     420             :           // % %=
     421      151641 :           return Select('=', Token::ASSIGN_MOD, Token::MOD);
     422             : 
     423             :         case Token::DIV:
     424             :           // /  // /* /=
     425     7484340 :           Advance();
     426     7484132 :           if (c0_ == '/') {
     427     7033332 :             uc32 c = Peek();
     428     7033120 :             if (c == '#' || c == '@') {
     429        4074 :               Advance();
     430        4074 :               Advance();
     431        4074 :               token = SkipSourceURLComment();
     432             :               continue;
     433             :             }
     434     7029046 :             token = SkipSingleLineComment();
     435             :             continue;
     436             :           }
     437      450800 :           if (c0_ == '*') {
     438       56301 :             token = SkipMultiLineComment();
     439             :             continue;
     440             :           }
     441      394499 :           if (c0_ == '=') return Select(Token::ASSIGN_DIV);
     442             :           return Token::DIV;
     443             : 
     444             :         case Token::BIT_AND:
     445             :           // & && &=
     446     1101387 :           Advance();
     447     1101412 :           if (c0_ == '&') return Select(Token::AND);
     448      671062 :           if (c0_ == '=') return Select(Token::ASSIGN_BIT_AND);
     449             :           return Token::BIT_AND;
     450             : 
     451             :         case Token::BIT_OR:
     452             :           // | || |=
     453      893247 :           Advance();
     454      893239 :           if (c0_ == '|') return Select(Token::OR);
     455      415520 :           if (c0_ == '=') return Select(Token::ASSIGN_BIT_OR);
     456             :           return Token::BIT_OR;
     457             : 
     458             :         case Token::BIT_XOR:
     459             :           // ^ ^=
     460       18598 :           return Select('=', Token::ASSIGN_BIT_XOR, Token::BIT_XOR);
     461             : 
     462             :         case Token::PERIOD:
     463             :           // . Number
     464    14672109 :           Advance();
     465    14672114 :           if (IsDecimalDigit(c0_)) return ScanNumber(true);
     466    14668903 :           if (c0_ == '.') {
     467      108474 :             if (Peek() == '.') {
     468      108098 :               Advance();
     469      108097 :               Advance();
     470             :               return Token::ELLIPSIS;
     471             :             }
     472             :           }
     473             :           return Token::PERIOD;
     474             : 
     475             :         case Token::TEMPLATE_SPAN:
     476       77184 :           Advance();
     477       77183 :           return ScanTemplateSpan();
     478             : 
     479             :         case Token::PRIVATE_NAME:
     480      260765 :           return ScanPrivateName();
     481             : 
     482             :         case Token::WHITESPACE:
     483             :           token = SkipWhiteSpace();
     484             :           continue;
     485             : 
     486             :         case Token::NUMBER:
     487    33552111 :           return ScanNumber(false);
     488             : 
     489             :         case Token::IDENTIFIER:
     490             :           return ScanIdentifierOrKeyword();
     491             : 
     492             :         default:
     493           0 :           UNREACHABLE();
     494             :       }
     495             :     }
     496             : 
     497    14184784 :     if (IsIdentifierStart(c0_) ||
     498     4728306 :         (CombineSurrogatePair() && IsIdentifierStart(c0_))) {
     499             :       return ScanIdentifierOrKeyword();
     500             :     }
     501     4728112 :     if (c0_ == kEndOfInput) {
     502     4727271 :       return source_->has_parser_error() ? Token::ILLEGAL : Token::EOS;
     503             :     }
     504             :     token = SkipWhiteSpace();
     505             : 
     506             :     // Continue scanning for tokens as long as we're just skipping whitespace.
     507             :   } while (token == Token::WHITESPACE);
     508             : 
     509             :   return token;
     510             : }
     511             : 
     512   387558639 : void Scanner::Scan(TokenDesc* next_desc) {
     513             :   DCHECK_EQ(next_desc, &next());
     514             : 
     515   387558639 :   next_desc->token = ScanSingleToken();
     516             :   DCHECK_IMPLIES(has_parser_error(), next_desc->token == Token::ILLEGAL);
     517   387558639 :   next_desc->location.end_pos = source_pos();
     518             : 
     519             : #ifdef DEBUG
     520             :   SanityCheckTokenDesc(current());
     521             :   SanityCheckTokenDesc(next());
     522             :   SanityCheckTokenDesc(next_next());
     523             : #endif
     524             : }
     525             : 
     526     4975118 : void Scanner::Scan() { Scan(next_); }
     527             : 
     528             : }  // namespace internal
     529             : }  // namespace v8
     530             : 
     531             : #endif  // V8_PARSING_SCANNER_INL_H_

Generated by: LCOV version 1.10