📄 scanner.cc.svn-base
字号:
case '"' : // fall through case '\\': break; case 'b' : c = '\b'; break; case 'f' : c = '\f'; break; case 'n' : c = '\n'; break; case 'r' : c = '\r'; break; case 't' : c = '\t'; break; case 'u' : c = ScanHexEscape(c, 4); break; case 'v' : c = '\v'; break; case 'x' : c = ScanHexEscape(c, 2); break; case '0' : // fall through case '1' : // fall through case '2' : // fall through case '3' : // fall through case '4' : // fall through case '5' : // fall through case '6' : // fall through case '7' : c = ScanOctalEscape(c, 2); break; } // According to ECMA-262, 3rd, 7.8.4 (p 18ff) these // should be illegal, but they are commonly handled // as non-escaped characters by JS VMs. AddChar(c);}Token::Value Scanner::ScanString() { uc32 quote = c0_; Advance(); // consume quote StartLiteral(); while (c0_ != quote && c0_ >= 0 && !kIsLineTerminator.get(c0_)) { uc32 c = c0_; Advance(); if (c == '\\') { if (c0_ < 0) return Token::ILLEGAL; ScanEscape(); } else { AddChar(c); } } if (c0_ != quote) { return Token::ILLEGAL; } TerminateLiteral(); Advance(); // consume quote return Token::STRING;}Token::Value Scanner::Select(Token::Value tok) { Advance(); return tok;}Token::Value Scanner::Select(uc32 next, Token::Value then, Token::Value else_) { Advance(); if (c0_ == next) { Advance(); return then; } else { return else_; }}Token::Value Scanner::ScanToken() { switch (c0_) { // strings case '"': case '\'': return ScanString(); case '<': // < <= << <<= <!-- Advance(); if (c0_ == '=') return Select(Token::LTE); if (c0_ == '<') return Select('=', Token::ASSIGN_SHL, Token::SHL); if (c0_ == '!') return ScanHtmlComment(); return Token::LT; case '>': // > >= >> >>= >>> >>>= Advance(); if (c0_ == '=') return Select(Token::GTE); if (c0_ == '>') { // >> >>= >>> >>>= Advance(); if (c0_ == '=') return Select(Token::ASSIGN_SAR); if (c0_ == '>') return Select('=', Token::ASSIGN_SHR, Token::SHR); return Token::SAR; } return Token::GT; case '=': // = == === Advance(); if (c0_ == '=') return Select('=', Token::EQ_STRICT, Token::EQ); return Token::ASSIGN; case '!': // ! != !== Advance(); if (c0_ == '=') return Select('=', Token::NE_STRICT, Token::NE); return Token::NOT; case '+': // + ++ += Advance(); if (c0_ == '+') return Select(Token::INC); if (c0_ == '=') return Select(Token::ASSIGN_ADD); return Token::ADD; case '-': // - -- -= Advance(); if (c0_ == '-') return Select(Token::DEC); if (c0_ == '=') return Select(Token::ASSIGN_SUB); return Token::SUB; case '*': // * *= return Select('=', Token::ASSIGN_MUL, Token::MUL); case '%': // % %= return Select('=', Token::ASSIGN_MOD, Token::MOD); case '/': // / // /* /= Advance(); if (c0_ == '/') return SkipSingleLineComment(); if (c0_ == '*') return SkipMultiLineComment(); if (c0_ == '=') return Select(Token::ASSIGN_DIV); return Token::DIV; case '&': // & && &= Advance(); if (c0_ == '&') return Select(Token::AND); if (c0_ == '=') return Select(Token::ASSIGN_BIT_AND); return Token::BIT_AND; case '|': // | || |= Advance(); if (c0_ == '|') return Select(Token::OR); if (c0_ == '=') return Select(Token::ASSIGN_BIT_OR); return Token::BIT_OR; case '^': // ^ ^= return Select('=', Token::ASSIGN_BIT_XOR, Token::BIT_XOR); case '.': // . Number Advance(); if (IsDecimalDigit(c0_)) return ScanNumber(true); return Token::PERIOD; case ':': return Select(Token::COLON); case ';': return Select(Token::SEMICOLON); case ',': return Select(Token::COMMA); case '(': return Select(Token::LPAREN); case ')': return Select(Token::RPAREN); case '[': return Select(Token::LBRACK); case ']': return Select(Token::RBRACK); case '{': return Select(Token::LBRACE); case '}': return Select(Token::RBRACE); case '?': return Select(Token::CONDITIONAL); case '~': return Select(Token::BIT_NOT); default: if (kIsIdentifierStart.get(c0_)) return ScanIdentifier(); if (IsDecimalDigit(c0_)) return ScanNumber(false); if (c0_ < 0) return Token::EOS; return Select(Token::ILLEGAL); } UNREACHABLE(); return Token::ILLEGAL;}// Returns true if any decimal digits were scanned, returns false otherwise.void Scanner::ScanDecimalDigits() { while (IsDecimalDigit(c0_)) AddCharAdvance();}Token::Value Scanner::ScanNumber(bool seen_period) { ASSERT(IsDecimalDigit(c0_)); // the first digit of the number or the fraction enum { DECIMAL, HEX, OCTAL } kind = DECIMAL; StartLiteral(); if (seen_period) { // we have already seen a decimal point of the float AddChar('.'); ScanDecimalDigits(); // we know we have at least one digit } else { // if the first character is '0' we must check for octals and hex if (c0_ == '0') { AddCharAdvance(); // either 0, 0exxx, 0Exxx, 0.xxx, an octal number, or a hex number if (c0_ == 'x' || c0_ == 'X') { // hex number kind = HEX; AddCharAdvance(); if (!IsHexDigit(c0_)) // we must have at least one hex digit after 'x'/'X' return Token::ILLEGAL; while (IsHexDigit(c0_)) AddCharAdvance(); } else if ('0' <= c0_ && c0_ <= '7') { // (possible) octal number kind = OCTAL; while (true) { if (c0_ == '8' || c0_ == '9') { kind = DECIMAL; break; } if (c0_ < '0' || '7' < c0_) break; AddCharAdvance(); } } } // Parse decimal digits and allow trailing fractional part. if (kind == DECIMAL) { ScanDecimalDigits(); // optional if (c0_ == '.') { AddCharAdvance(); ScanDecimalDigits(); // optional } } } // scan exponent, if any if (c0_ == 'e' || c0_ == 'E') { ASSERT(kind != HEX); // 'e'/'E' must be scanned as part of the hex number if (kind == OCTAL) return Token::ILLEGAL; // no exponent for octals allowed // scan exponent AddCharAdvance(); if (c0_ == '+' || c0_ == '-') AddCharAdvance(); 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 // section 7.8.3, page 17 (note that we read only one decimal digit // if the value is 0). if (IsDecimalDigit(c0_) || kIsIdentifierStart.get(c0_)) return Token::ILLEGAL; return Token::NUMBER;}uc32 Scanner::ScanIdentifierUnicodeEscape() { Advance(); if (c0_ != 'u') return unibrow::Utf8::kBadChar; Advance(); uc32 c = ScanHexEscape('u', 4); // We do not allow a unicode escape sequence to start another // unicode escape sequence. if (c == '\\') return unibrow::Utf8::kBadChar; return c;}Token::Value Scanner::ScanIdentifier() { ASSERT(kIsIdentifierStart.get(c0_)); bool has_escapes = false; StartLiteral(); // Scan identifier start character. if (c0_ == '\\') { has_escapes = true; uc32 c = ScanIdentifierUnicodeEscape(); // Only allow legal identifier start characters. if (!kIsIdentifierStart.get(c)) return Token::ILLEGAL; AddChar(c); } else { AddCharAdvance(); } // Scan the rest of the identifier characters. while (kIsIdentifierPart.get(c0_)) { if (c0_ == '\\') { has_escapes = true; uc32 c = ScanIdentifierUnicodeEscape(); // Only allow legal identifier part characters. if (!kIsIdentifierPart.get(c)) return Token::ILLEGAL; AddChar(c); } else { AddCharAdvance(); } } TerminateLiteral(); // We don't have any 1-letter keywords (this is probably a common case). if ((next_.literal_end - next_.literal_pos) == 1) return Token::IDENTIFIER; // If the identifier contains unicode escapes, it must not be // resolved to a keyword. if (has_escapes) return Token::IDENTIFIER; return Token::Lookup(&literals_.data()[next_.literal_pos]);}bool Scanner::IsIdentifier(unibrow::CharacterStream* buffer) { // Checks whether the buffer contains an identifier (no escapse). if (!buffer->has_more()) return false; if (!kIsIdentifierStart.get(buffer->GetNext())) return false; while (buffer->has_more()) { if (!kIsIdentifierPart.get(buffer->GetNext())) return false; } return true;}bool Scanner::ScanRegExpPattern(bool seen_equal) { // Scan: ('/' | '/=') RegularExpressionBody '/' RegularExpressionFlags bool in_character_class = false; // Previous token is either '/' or '/=', in the second case, the // pattern starts at =. next_.location.beg_pos = source_pos() - (seen_equal ? 2 : 1); next_.location.end_pos = source_pos() - (seen_equal ? 1 : 0); // Scan regular expression body: According to ECMA-262, 3rd, 7.8.5, // the scanner should pass uninterpreted bodies to the RegExp // constructor. StartLiteral(); if (seen_equal) AddChar('='); while (c0_ != '/' || in_character_class) { if (kIsLineTerminator.get(c0_) || c0_ < 0) return false; if (c0_ == '\\') { // escaped character AddCharAdvance(); if (kIsLineTerminator.get(c0_) || c0_ < 0) return false; AddCharAdvance(); } else { // unescaped character if (c0_ == '[') in_character_class = true; if (c0_ == ']') in_character_class = false; AddCharAdvance(); } } Advance(); // consume '/' TerminateLiteral(); return true;}bool Scanner::ScanRegExpFlags() { // Scan regular expression flags. StartLiteral(); while (kIsIdentifierPart.get(c0_)) AddCharAdvance(); TerminateLiteral(); next_.location.end_pos = source_pos() - 1; return true;}} } // namespace v8::internal
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -