| Index: src/scanner-base.h
|
| diff --git a/src/scanner-base.h b/src/scanner-base.h
|
| index 61b1fddda9331837f122028eda31972b80b6177c..3714ae2d1bc626ad2a2127b3fe5dcc6b86cef84b 100644
|
| --- a/src/scanner-base.h
|
| +++ b/src/scanner-base.h
|
| @@ -327,6 +327,42 @@ class Scanner {
|
|
|
| class JavaScriptScanner : public Scanner {
|
| public:
|
| +
|
| + // Bit vector representing set of types of literals.
|
| + enum LiteralType {
|
| + kNoLiterals = 0,
|
| + kLiteralNumber = 1,
|
| + kLiteralIdentifier = 2,
|
| + kLiteralString = 4,
|
| + kLiteralRegExp = 8,
|
| + kLiteralRegExpFlags = 16,
|
| + kAllLiterals = 31
|
| + };
|
| +
|
| + // A LiteralScope that disables recording of some types of JavaScript
|
| + // literals. If the scanner is configured to not record the specific
|
| + // type of literal, the scope will not call StartLiteral.
|
| + class LiteralScope {
|
| + public:
|
| + LiteralScope(JavaScriptScanner* self, LiteralType type)
|
| + : scanner_(self), complete_(false) {
|
| + if (scanner_->RecordsLiteral(type)) {
|
| + scanner_->StartLiteral();
|
| + }
|
| + }
|
| + ~LiteralScope() {
|
| + if (!complete_) scanner_->DropLiteral();
|
| + }
|
| + void Complete() {
|
| + scanner_->TerminateLiteral();
|
| + complete_ = true;
|
| + }
|
| +
|
| + private:
|
| + JavaScriptScanner* scanner_;
|
| + bool complete_;
|
| + };
|
| +
|
| JavaScriptScanner();
|
|
|
| // Returns the next token.
|
| @@ -354,6 +390,11 @@ class JavaScriptScanner : public Scanner {
|
| // tokens, which is what it is used for.
|
| void SeekForward(int pos);
|
|
|
| + // Whether this scanner records the given literal type or not.
|
| + bool RecordsLiteral(LiteralType type) {
|
| + return (literal_flags_ & type) != 0;
|
| + }
|
| +
|
| protected:
|
| bool SkipWhiteSpace();
|
| Token::Value SkipSingleLineComment();
|
| @@ -364,7 +405,8 @@ class JavaScriptScanner : public Scanner {
|
|
|
| void ScanDecimalDigits();
|
| Token::Value ScanNumber(bool seen_period);
|
| - Token::Value ScanIdentifier();
|
| + Token::Value ScanIdentifierOrKeyword();
|
| + Token::Value ScanIdentifierSuffix(LiteralScope* literal);
|
|
|
| void ScanEscape();
|
| Token::Value ScanString();
|
| @@ -376,6 +418,7 @@ class JavaScriptScanner : public Scanner {
|
| // If the escape sequence cannot be decoded the result is kBadChar.
|
| uc32 ScanIdentifierUnicodeEscape();
|
|
|
| + int literal_flags_;
|
| bool has_line_terminator_before_next_;
|
| };
|
|
|
| @@ -404,10 +447,11 @@ class KeywordMatcher {
|
|
|
| Token::Value token() { return token_; }
|
|
|
| - inline void AddChar(unibrow::uchar input) {
|
| + inline bool AddChar(unibrow::uchar input) {
|
| if (state_ != UNMATCHABLE) {
|
| Step(input);
|
| }
|
| + return state_ != UNMATCHABLE;
|
| }
|
|
|
| void Fail() {
|
| @@ -458,23 +502,23 @@ class KeywordMatcher {
|
| const char* keyword,
|
| int position,
|
| Token::Value token_if_match) {
|
| - if (input == static_cast<unibrow::uchar>(keyword[position])) {
|
| - state_ = KEYWORD_PREFIX;
|
| - this->keyword_ = keyword;
|
| - this->counter_ = position + 1;
|
| - this->keyword_token_ = token_if_match;
|
| - return true;
|
| + if (input != static_cast<unibrow::uchar>(keyword[position])) {
|
| + return false;
|
| }
|
| - return false;
|
| + state_ = KEYWORD_PREFIX;
|
| + this->keyword_ = keyword;
|
| + this->counter_ = position + 1;
|
| + this->keyword_token_ = token_if_match;
|
| + return true;
|
| }
|
|
|
| // If input equals match character, transition to new state and return true.
|
| inline bool MatchState(unibrow::uchar input, char match, State new_state) {
|
| - if (input == static_cast<unibrow::uchar>(match)) {
|
| - state_ = new_state;
|
| - return true;
|
| + if (input != static_cast<unibrow::uchar>(match)) {
|
| + return false;
|
| }
|
| - return false;
|
| + state_ = new_state;
|
| + return true;
|
| }
|
|
|
| inline bool MatchKeyword(unibrow::uchar input,
|
|
|