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-02-19 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('g')                                        \
      46             :   KEYWORD("get", Token::GET)                                \
      47             :   KEYWORD_GROUP('i')                                        \
      48             :   KEYWORD("if", Token::IF)                                  \
      49             :   KEYWORD("implements", Token::FUTURE_STRICT_RESERVED_WORD) \
      50             :   KEYWORD("import", Token::IMPORT)                          \
      51             :   KEYWORD("in", Token::IN)                                  \
      52             :   KEYWORD("instanceof", Token::INSTANCEOF)                  \
      53             :   KEYWORD("interface", Token::FUTURE_STRICT_RESERVED_WORD)  \
      54             :   KEYWORD_GROUP('l')                                        \
      55             :   KEYWORD("let", Token::LET)                                \
      56             :   KEYWORD_GROUP('n')                                        \
      57             :   KEYWORD("new", Token::NEW)                                \
      58             :   KEYWORD("null", Token::NULL_LITERAL)                      \
      59             :   KEYWORD_GROUP('p')                                        \
      60             :   KEYWORD("package", Token::FUTURE_STRICT_RESERVED_WORD)    \
      61             :   KEYWORD("private", Token::FUTURE_STRICT_RESERVED_WORD)    \
      62             :   KEYWORD("protected", Token::FUTURE_STRICT_RESERVED_WORD)  \
      63             :   KEYWORD("public", Token::FUTURE_STRICT_RESERVED_WORD)     \
      64             :   KEYWORD_GROUP('r')                                        \
      65             :   KEYWORD("return", Token::RETURN)                          \
      66             :   KEYWORD_GROUP('s')                                        \
      67             :   KEYWORD("set", Token::SET)                                \
      68             :   KEYWORD("static", Token::STATIC)                          \
      69             :   KEYWORD("super", Token::SUPER)                            \
      70             :   KEYWORD("switch", Token::SWITCH)                          \
      71             :   KEYWORD_GROUP('t')                                        \
      72             :   KEYWORD("this", Token::THIS)                              \
      73             :   KEYWORD("throw", Token::THROW)                            \
      74             :   KEYWORD("true", Token::TRUE_LITERAL)                      \
      75             :   KEYWORD("try", Token::TRY)                                \
      76             :   KEYWORD("typeof", Token::TYPEOF)                          \
      77             :   KEYWORD_GROUP('v')                                        \
      78             :   KEYWORD("var", Token::VAR)                                \
      79             :   KEYWORD("void", Token::VOID)                              \
      80             :   KEYWORD_GROUP('w')                                        \
      81             :   KEYWORD("while", Token::WHILE)                            \
      82             :   KEYWORD("with", Token::WITH)                              \
      83             :   KEYWORD_GROUP('y')                                        \
      84             :   KEYWORD("yield", Token::YIELD)
      85             : 
      86             : constexpr bool IsKeywordStart(char c) {
      87             : #define KEYWORD_GROUP_CHECK(ch) c == ch ||
      88             : #define KEYWORD_CHECK(keyword, token)
      89             :   return KEYWORDS(KEYWORD_GROUP_CHECK, KEYWORD_CHECK) /* || */ false;
      90             : #undef KEYWORD_GROUP_CHECK
      91             : #undef KEYWORD_CHECK
      92             : }
      93             : 
      94             : V8_INLINE Token::Value KeywordOrIdentifierToken(const uint8_t* input,
      95             :                                                 int input_length) {
      96             :   DCHECK_GE(input_length, 1);
      97             :   return PerfectKeywordHash::GetToken(reinterpret_cast<const char*>(input),
      98    77064244 :                                       input_length);
      99             : }
     100             : 
     101             : // Recursive constexpr template magic to check if a character is in a given
     102             : // string.
     103             : template <int N>
     104             : constexpr bool IsInString(const char (&s)[N], char c, size_t i = 0) {
     105             :   return i >= N ? false : s[i] == c ? true : IsInString(s, c, i + 1);
     106             : }
     107             : 
     108             : inline constexpr bool CanBeKeywordCharacter(char c) {
     109             :   return IsInString(
     110             : #define KEYWORD_GROUP_CASE(ch)  // Nothing
     111             : #define KEYWORD(keyword, token) keyword
     112             :       // Use C string literal concatenation ("a" "b" becomes "ab") to build one
     113             :       // giant string containing all the keywords.
     114             :       KEYWORDS(KEYWORD_GROUP_CASE, KEYWORD)
     115             : #undef KEYWORD
     116             : #undef KEYWORD_GROUP_CASE
     117             :           ,
     118             :       c);
     119             : }
     120             : 
     121             : // Make sure tokens are stored as a single byte.
     122             : STATIC_ASSERT(sizeof(Token::Value) == 1);
     123             : 
     124             : // Get the shortest token that this character starts, the token may change
     125             : // depending on subsequent characters.
     126             : constexpr Token::Value GetOneCharToken(char c) {
     127             :   // clang-format off
     128             :   return
     129             :       c == '(' ? Token::LPAREN :
     130             :       c == ')' ? Token::RPAREN :
     131             :       c == '{' ? Token::LBRACE :
     132             :       c == '}' ? Token::RBRACE :
     133             :       c == '[' ? Token::LBRACK :
     134             :       c == ']' ? Token::RBRACK :
     135             :       c == '?' ? Token::CONDITIONAL :
     136             :       c == ':' ? Token::COLON :
     137             :       c == ';' ? Token::SEMICOLON :
     138             :       c == ',' ? Token::COMMA :
     139             :       c == '.' ? Token::PERIOD :
     140             :       c == '|' ? Token::BIT_OR :
     141             :       c == '&' ? Token::BIT_AND :
     142             :       c == '^' ? Token::BIT_XOR :
     143             :       c == '~' ? Token::BIT_NOT :
     144             :       c == '!' ? Token::NOT :
     145             :       c == '<' ? Token::LT :
     146             :       c == '>' ? Token::GT :
     147             :       c == '%' ? Token::MOD :
     148             :       c == '=' ? Token::ASSIGN :
     149             :       c == '+' ? Token::ADD :
     150             :       c == '-' ? Token::SUB :
     151             :       c == '*' ? Token::MUL :
     152             :       c == '/' ? Token::DIV :
     153             :       c == '#' ? Token::PRIVATE_NAME :
     154             :       c == '"' ? Token::STRING :
     155             :       c == '\'' ? Token::STRING :
     156             :       c == '`' ? Token::TEMPLATE_SPAN :
     157             :       c == '\\' ? Token::IDENTIFIER :
     158             :       // Whitespace or line terminator
     159             :       c == ' ' ? Token::WHITESPACE :
     160             :       c == '\t' ? Token::WHITESPACE :
     161             :       c == '\v' ? Token::WHITESPACE :
     162             :       c == '\f' ? Token::WHITESPACE :
     163             :       c == '\r' ? Token::WHITESPACE :
     164             :       c == '\n' ? Token::WHITESPACE :
     165             :       // IsDecimalDigit must be tested before IsAsciiIdentifier
     166             :       IsDecimalDigit(c) ? Token::NUMBER :
     167             :       IsAsciiIdentifier(c) ? Token::IDENTIFIER :
     168             :       Token::ILLEGAL;
     169             :   // clang-format on
     170             : }
     171             : 
     172             : // Table of one-character tokens, by character (0x00..0x7F only).
     173             : static const constexpr Token::Value one_char_tokens[128] = {
     174             : #define CALL_GET_SCAN_FLAGS(N) GetOneCharToken(N),
     175             :     INT_0_TO_127_LIST(CALL_GET_SCAN_FLAGS)
     176             : #undef CALL_GET_SCAN_FLAGS
     177             : };
     178             : 
     179             : #undef KEYWORDS
     180             : 
     181   131402920 : V8_INLINE Token::Value Scanner::ScanIdentifierOrKeyword() {
     182   131402920 :   next().literal_chars.Start();
     183             :   return ScanIdentifierOrKeywordInner();
     184             : }
     185             : 
     186             : // Character flags for the fast path of scanning a keyword or identifier token.
     187             : enum class ScanFlags : uint8_t {
     188             :   kTerminatesLiteral = 1 << 0,
     189             :   // "Cannot" rather than "can" so that this flag can be ORed together across
     190             :   // multiple characters.
     191             :   kCannotBeKeyword = 1 << 1,
     192             :   kCannotBeKeywordStart = 1 << 2,
     193             :   kStringTerminator = 1 << 3,
     194             :   kNeedsSlowPath = 1 << 4,
     195             : };
     196             : constexpr uint8_t GetScanFlags(char c) {
     197             :   return
     198             :       // Keywords are all lowercase and only contain letters.
     199             :       // Note that non-identifier characters do not set this flag, so
     200             :       // that it plays well with kTerminatesLiteral.
     201             :       (IsAsciiIdentifier(c) && !CanBeKeywordCharacter(c)
     202             :            ? static_cast<uint8_t>(ScanFlags::kCannotBeKeyword)
     203             :            : 0) |
     204             :       (IsKeywordStart(c)
     205             :            ? 0
     206             :            : static_cast<uint8_t>(ScanFlags::kCannotBeKeywordStart)) |
     207             :       // Anything that isn't an identifier character will terminate the
     208             :       // literal, or at least terminates the literal fast path processing
     209             :       // (like an escape).
     210             :       (!IsAsciiIdentifier(c)
     211             :            ? static_cast<uint8_t>(ScanFlags::kTerminatesLiteral)
     212             :            : 0) |
     213             :       // Possible string termination characters.
     214             :       ((c == '\'' || c == '"' || c == '\n' || c == '\r' || c == '\\')
     215             :            ? static_cast<uint8_t>(ScanFlags::kStringTerminator)
     216             :            : 0) |
     217             :       // Escapes are processed on the slow path.
     218             :       (c == '\\' ? static_cast<uint8_t>(ScanFlags::kNeedsSlowPath) : 0);
     219             : }
     220             : inline bool TerminatesLiteral(uint8_t scan_flags) {
     221   786846535 :   return (scan_flags & static_cast<uint8_t>(ScanFlags::kTerminatesLiteral));
     222             : }
     223   131443181 : inline bool CanBeKeyword(uint8_t scan_flags) {
     224   131499044 :   return !(scan_flags & static_cast<uint8_t>(ScanFlags::kCannotBeKeyword));
     225             : }
     226   131442996 : inline bool NeedsSlowPath(uint8_t scan_flags) {
     227   131442996 :   return (scan_flags & static_cast<uint8_t>(ScanFlags::kNeedsSlowPath));
     228             : }
     229             : inline bool MayTerminateString(uint8_t scan_flags) {
     230   187653867 :   return (scan_flags & static_cast<uint8_t>(ScanFlags::kStringTerminator));
     231             : }
     232             : // Table of precomputed scan flags for the 128 ASCII characters, for branchless
     233             : // flag calculation during the scan.
     234             : static constexpr const uint8_t character_scan_flags[128] = {
     235             : #define CALL_GET_SCAN_FLAGS(N) GetScanFlags(N),
     236             :     INT_0_TO_127_LIST(CALL_GET_SCAN_FLAGS)
     237             : #undef CALL_GET_SCAN_FLAGS
     238             : };
     239             : 
     240        2836 : inline bool CharCanBeKeyword(uc32 c) {
     241      112363 :   return static_cast<uint32_t>(c) < arraysize(character_scan_flags) &&
     242       58699 :          CanBeKeyword(character_scan_flags[c]);
     243             : }
     244             : 
     245   208453310 : V8_INLINE Token::Value Scanner::ScanIdentifierOrKeywordInner() {
     246             :   DCHECK(IsIdentifierStart(c0_));
     247             :   bool escaped = false;
     248             :   bool can_be_keyword = true;
     249             : 
     250             :   STATIC_ASSERT(arraysize(character_scan_flags) == kMaxAscii + 1);
     251   131464860 :   if (V8_LIKELY(static_cast<uint32_t>(c0_) <= kMaxAscii)) {
     252   131441813 :     if (V8_LIKELY(c0_ != '\\')) {
     253   131417202 :       uint8_t scan_flags = character_scan_flags[c0_];
     254             :       DCHECK(!TerminatesLiteral(scan_flags));
     255             :       STATIC_ASSERT(static_cast<uint8_t>(ScanFlags::kCannotBeKeywordStart) ==
     256             :                     static_cast<uint8_t>(ScanFlags::kCannotBeKeyword) << 1);
     257   131417202 :       scan_flags >>= 1;
     258             :       // Make sure the shifting above doesn't set NeedsSlowPath. Otherwise we'll
     259             :       // fall into the slow path after scanning the identifier.
     260             :       DCHECK(!NeedsSlowPath(scan_flags));
     261             :       AddLiteralChar(static_cast<char>(c0_));
     262   786846882 :       AdvanceUntil([this, &scan_flags](uc32 c0) {
     263   786846882 :         if (V8_UNLIKELY(static_cast<uint32_t>(c0) > kMaxAscii)) {
     264             :           // A non-ascii character means we need to drop through to the slow
     265             :           // path.
     266             :           // TODO(leszeks): This would be most efficient as a goto to the slow
     267             :           // path, check codegen and maybe use a bool instead.
     268         347 :           scan_flags |= static_cast<uint8_t>(ScanFlags::kNeedsSlowPath);
     269         347 :           return true;
     270             :         }
     271   786846535 :         uint8_t char_flags = character_scan_flags[c0];
     272   786846535 :         scan_flags |= char_flags;
     273   786846535 :         if (TerminatesLiteral(char_flags)) {
     274             :           return true;
     275             :         } else {
     276   655766711 :           AddLiteralChar(static_cast<char>(c0));
     277   655739148 :           return false;
     278             :         }
     279             :       });
     280             : 
     281   131445430 :       if (V8_LIKELY(!NeedsSlowPath(scan_flags))) {
     282   131432239 :         if (!CanBeKeyword(scan_flags)) return Token::IDENTIFIER;
     283             :         // Could be a keyword or identifier.
     284    77053471 :         Vector<const uint8_t> chars = next().literal_chars.one_byte_literal();
     285    77050437 :         return KeywordOrIdentifierToken(chars.start(), chars.length());
     286             :       }
     287             : 
     288       13488 :       can_be_keyword = CanBeKeyword(scan_flags);
     289             :     } else {
     290             :       // Special case for escapes at the start of an identifier.
     291             :       escaped = true;
     292       24611 :       uc32 c = ScanIdentifierUnicodeEscape();
     293             :       DCHECK(!IsIdentifierStart(-1));
     294       24611 :       if (c == '\\' || !IsIdentifierStart(c)) {
     295             :         return Token::ILLEGAL;
     296             :       }
     297             :       AddLiteralChar(c);
     298        2836 :       can_be_keyword = CharCanBeKeyword(c);
     299             :     }
     300             :   }
     301             : 
     302       39371 :   return ScanIdentifierOrKeywordInnerSlow(escaped, can_be_keyword);
     303             : }
     304             : 
     305   730032787 : V8_INLINE Token::Value Scanner::SkipWhiteSpace() {
     306   170514443 :   int start_position = source_pos();
     307             : 
     308             :   // We won't skip behind the end of input.
     309             :   DCHECK(!IsWhiteSpaceOrLineTerminator(kEndOfInput));
     310             : 
     311             :   // Advance as long as character is a WhiteSpace or LineTerminator.
     312   522275706 :   while (IsWhiteSpaceOrLineTerminator(c0_)) {
     313   524680148 :     if (!next().after_line_terminator && unibrow::IsLineTerminator(c0_)) {
     314    37225228 :       next().after_line_terminator = true;
     315             :     }
     316   351796320 :     Advance();
     317             :   }
     318             : 
     319             :   // Return whether or not we skipped any characters.
     320   170490483 :   if (source_pos() == start_position) {
     321             :     DCHECK_NE('0', c0_);
     322             :     return Token::ILLEGAL;
     323             :   }
     324             : 
     325             :   return Token::WHITESPACE;
     326             : }
     327             : 
     328  1201131012 : V8_INLINE Token::Value Scanner::ScanSingleToken() {
     329             :   Token::Value token;
     330   177662195 :   do {
     331  1133646618 :     next().location.beg_pos = source_pos();
     332             : 
     333   567483905 :     if (V8_LIKELY(static_cast<unsigned>(c0_) <= kMaxAscii)) {
     334   562663894 :       token = one_char_tokens[c0_];
     335             : 
     336   562663894 :       switch (token) {
     337             :         case Token::LPAREN:
     338             :         case Token::RPAREN:
     339             :         case Token::LBRACE:
     340             :         case Token::RBRACE:
     341             :         case Token::LBRACK:
     342             :         case Token::RBRACK:
     343             :         case Token::CONDITIONAL:
     344             :         case Token::COLON:
     345             :         case Token::SEMICOLON:
     346             :         case Token::COMMA:
     347             :         case Token::BIT_NOT:
     348             :         case Token::ILLEGAL:
     349             :           // One character tokens.
     350   157199780 :           return Select(token);
     351             : 
     352             :         case Token::STRING:
     353    10352863 :           return ScanString();
     354             : 
     355             :         case Token::LT:
     356             :           // < <= << <<= <!--
     357     1034201 :           Advance();
     358     1034154 :           if (c0_ == '=') return Select(Token::LTE);
     359      952216 :           if (c0_ == '<') return Select('=', Token::ASSIGN_SHL, Token::SHL);
     360      528890 :           if (c0_ == '!') {
     361          72 :             token = ScanHtmlComment();
     362             :             continue;
     363             :           }
     364             :           return Token::LT;
     365             : 
     366             :         case Token::GT:
     367             :           // > >= >> >>= >>> >>>=
     368      524035 :           Advance();
     369      524023 :           if (c0_ == '=') return Select(Token::GTE);
     370      494824 :           if (c0_ == '>') {
     371             :             // >> >>= >>> >>>=
     372      261080 :             Advance();
     373      261082 :             if (c0_ == '=') return Select(Token::ASSIGN_SAR);
     374      255949 :             if (c0_ == '>') return Select('=', Token::ASSIGN_SHR, Token::SHR);
     375             :             return Token::SAR;
     376             :           }
     377             :           return Token::GT;
     378             : 
     379             :         case Token::ASSIGN:
     380             :           // = == === =>
     381    25358715 :           Advance();
     382    25358863 :           if (c0_ == '=') return Select('=', Token::EQ_STRICT, Token::EQ);
     383    23716775 :           if (c0_ == '>') return Select(Token::ARROW);
     384             :           return Token::ASSIGN;
     385             : 
     386             :         case Token::NOT:
     387             :           // ! != !==
     388     2342751 :           Advance();
     389     2342767 :           if (c0_ == '=') return Select('=', Token::NE_STRICT, Token::NE);
     390             :           return Token::NOT;
     391             : 
     392             :         case Token::ADD:
     393             :           // + ++ +=
     394     4704229 :           Advance();
     395     4704185 :           if (c0_ == '+') return Select(Token::INC);
     396     3760857 :           if (c0_ == '=') return Select(Token::ASSIGN_ADD);
     397             :           return Token::ADD;
     398             : 
     399             :         case Token::SUB:
     400             :           // - -- --> -=
     401      808330 :           Advance();
     402      808287 :           if (c0_ == '-') {
     403      102023 :             Advance();
     404      102233 :             if (c0_ == '>' && next().after_line_terminator) {
     405             :               // For compatibility with SpiderMonkey, we skip lines that
     406             :               // start with an HTML comment end '-->'.
     407         154 :               token = SkipSingleHTMLComment();
     408             :               continue;
     409             :             }
     410             :             return Token::DEC;
     411             :           }
     412      706264 :           if (c0_ == '=') return Select(Token::ASSIGN_SUB);
     413             :           return Token::SUB;
     414             : 
     415             :         case Token::MUL:
     416             :           // * *=
     417      511480 :           Advance();
     418      511477 :           if (c0_ == '*') return Select('=', Token::ASSIGN_EXP, Token::EXP);
     419      502097 :           if (c0_ == '=') return Select(Token::ASSIGN_MUL);
     420             :           return Token::MUL;
     421             : 
     422             :         case Token::MOD:
     423             :           // % %=
     424      150332 :           return Select('=', Token::ASSIGN_MOD, Token::MOD);
     425             : 
     426             :         case Token::DIV:
     427             :           // /  // /* /=
     428     7573802 :           Advance();
     429     7573756 :           if (c0_ == '/') {
     430     7123049 :             uc32 c = Peek();
     431     7123000 :             if (c == '#' || c == '@') {
     432        4005 :               Advance();
     433        4005 :               Advance();
     434        4005 :               token = SkipSourceURLComment();
     435             :               continue;
     436             :             }
     437     7118995 :             token = SkipSingleLineComment();
     438             :             continue;
     439             :           }
     440      450707 :           if (c0_ == '*') {
     441       57305 :             token = SkipMultiLineComment();
     442             :             continue;
     443             :           }
     444      393402 :           if (c0_ == '=') return Select(Token::ASSIGN_DIV);
     445             :           return Token::DIV;
     446             : 
     447             :         case Token::BIT_AND:
     448             :           // & && &=
     449     1258583 :           Advance();
     450     1258600 :           if (c0_ == '&') return Select(Token::AND);
     451      661722 :           if (c0_ == '=') return Select(Token::ASSIGN_BIT_AND);
     452             :           return Token::BIT_AND;
     453             : 
     454             :         case Token::BIT_OR:
     455             :           // | || |=
     456      858513 :           Advance();
     457      858505 :           if (c0_ == '|') return Select(Token::OR);
     458      380120 :           if (c0_ == '=') return Select(Token::ASSIGN_BIT_OR);
     459             :           return Token::BIT_OR;
     460             : 
     461             :         case Token::BIT_XOR:
     462             :           // ^ ^=
     463       18418 :           return Select('=', Token::ASSIGN_BIT_XOR, Token::BIT_XOR);
     464             : 
     465             :         case Token::PERIOD:
     466             :           // . Number
     467    14609841 :           Advance();
     468    14609822 :           if (IsDecimalDigit(c0_)) return ScanNumber(true);
     469    14606822 :           if (c0_ == '.') {
     470      110154 :             if (Peek() == '.') {
     471      109779 :               Advance();
     472      109777 :               Advance();
     473             :               return Token::ELLIPSIS;
     474             :             }
     475             :           }
     476             :           return Token::PERIOD;
     477             : 
     478             :         case Token::TEMPLATE_SPAN:
     479       75835 :           Advance();
     480       75836 :           return ScanTemplateSpan();
     481             : 
     482             :         case Token::PRIVATE_NAME:
     483      277960 :           return ScanPrivateName();
     484             : 
     485             :         case Token::WHITESPACE:
     486             :           token = SkipWhiteSpace();
     487             :           continue;
     488             : 
     489             :         case Token::NUMBER:
     490    33087966 :           return ScanNumber(false);
     491             : 
     492             :         case Token::IDENTIFIER:
     493             :           return ScanIdentifierOrKeyword();
     494             : 
     495             :         default:
     496           0 :           UNREACHABLE();
     497             :       }
     498             :     }
     499             : 
     500    14459712 :     if (IsIdentifierStart(c0_) ||
     501     4819965 :         (CombineSurrogatePair() && IsIdentifierStart(c0_))) {
     502             :       return ScanIdentifierOrKeyword();
     503             :     }
     504     4819767 :     if (c0_ == kEndOfInput) {
     505     4818766 :       return source_->has_parser_error() ? Token::ILLEGAL : Token::EOS;
     506             :     }
     507             :     token = SkipWhiteSpace();
     508             : 
     509             :     // Continue scanning for tokens as long as we're just skipping whitespace.
     510             :   } while (token == Token::WHITESPACE);
     511             : 
     512             :   return token;
     513             : }
     514             : 
     515   389791391 : void Scanner::Scan(TokenDesc* next_desc) {
     516             :   DCHECK_EQ(next_desc, &next());
     517             : 
     518   389791391 :   next_desc->token = ScanSingleToken();
     519             :   DCHECK_IMPLIES(has_parser_error(), next_desc->token == Token::ILLEGAL);
     520   389791391 :   next_desc->location.end_pos = source_pos();
     521             : 
     522             : #ifdef DEBUG
     523             :   SanityCheckTokenDesc(current());
     524             :   SanityCheckTokenDesc(next());
     525             :   SanityCheckTokenDesc(next_next());
     526             : #endif
     527             : }
     528             : 
     529     4981748 : void Scanner::Scan() { Scan(next_); }
     530             : 
     531             : }  // namespace internal
     532             : }  // namespace v8
     533             : 
     534             : #endif  // V8_PARSING_SCANNER_INL_H_

Generated by: LCOV version 1.10