Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| 11 // with the distribution. | 11 // with the distribution. |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 28 // Features shared by parsing and pre-parsing scanners. | 28 // Features shared by parsing and pre-parsing scanners. |
| 29 | 29 |
| 30 #include "../include/v8stdint.h" | 30 #include "../include/v8stdint.h" |
| 31 #include "scanner-base.h" | 31 #include "scanner-base.h" |
| 32 #include "char-predicates-inl.h" | 32 #include "char-predicates-inl.h" |
| 33 | 33 |
| 34 namespace v8 { | 34 namespace v8 { |
| 35 namespace internal { | 35 namespace internal { |
| 36 | 36 |
| 37 // ---------------------------------------------------------------------------- | 37 // ---------------------------------------------------------------------------- |
| 38 // Compound predicates. | |
| 39 | |
| 40 bool ScannerConstants::IsIdentifier(unibrow::CharacterStream* buffer) { | |
| 41 // Checks whether the buffer contains an identifier (no escape). | |
| 42 if (!buffer->has_more()) return false; | |
| 43 if (!kIsIdentifierStart.get(buffer->GetNext())) { | |
| 44 return false; | |
| 45 } | |
| 46 while (buffer->has_more()) { | |
| 47 if (!kIsIdentifierPart.get(buffer->GetNext())) { | |
| 48 return false; | |
| 49 } | |
| 50 } | |
| 51 return true; | |
| 52 } | |
| 53 | |
| 54 // ---------------------------------------------------------------------------- | |
| 55 // Scanner | 38 // Scanner |
| 56 | 39 |
| 57 Scanner::Scanner(ScannerConstants* scanner_constants) | 40 Scanner::Scanner(UnicodeCache* unicode_cache) |
| 58 : scanner_constants_(scanner_constants), | 41 : unicode_cache_(unicode_cache), |
| 59 octal_pos_(kNoOctalLocation) { | 42 octal_pos_(kNoOctalLocation) { |
|
Karl Klose
2011/04/12 07:55:40
I think this newline should be removed.
Lasse Reichstein
2011/04/12 08:18:47
Done.
| |
| 60 } | 43 } |
| 61 | 44 |
| 62 | 45 |
| 63 uc32 Scanner::ScanHexEscape(uc32 c, int length) { | 46 uc32 Scanner::ScanHexEscape(uc32 c, int length) { |
| 64 ASSERT(length <= 4); // prevent overflow | 47 ASSERT(length <= 4); // prevent overflow |
| 65 | 48 |
| 66 uc32 digits[4]; | 49 uc32 digits[4]; |
| 67 uc32 x = 0; | 50 uc32 x = 0; |
| 68 for (int i = 0; i < length; i++) { | 51 for (int i = 0; i < length; i++) { |
| 69 digits[i] = c0_; | 52 digits[i] = c0_; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 107 if (c != '0' || i > 0) { | 90 if (c != '0' || i > 0) { |
| 108 octal_pos_ = source_pos() - i - 1; // Already advanced | 91 octal_pos_ = source_pos() - i - 1; // Already advanced |
| 109 } | 92 } |
| 110 return x; | 93 return x; |
| 111 } | 94 } |
| 112 | 95 |
| 113 | 96 |
| 114 // ---------------------------------------------------------------------------- | 97 // ---------------------------------------------------------------------------- |
| 115 // JavaScriptScanner | 98 // JavaScriptScanner |
| 116 | 99 |
| 117 JavaScriptScanner::JavaScriptScanner(ScannerConstants* scanner_contants) | 100 JavaScriptScanner::JavaScriptScanner(UnicodeCache* scanner_contants) |
| 118 : Scanner(scanner_contants) { } | 101 : Scanner(scanner_contants) { } |
| 119 | 102 |
| 120 | 103 |
| 121 Token::Value JavaScriptScanner::Next() { | 104 Token::Value JavaScriptScanner::Next() { |
| 122 current_ = next_; | 105 current_ = next_; |
| 123 has_line_terminator_before_next_ = false; | 106 has_line_terminator_before_next_ = false; |
| 124 Scan(); | 107 Scan(); |
| 125 return current_.token; | 108 return current_.token; |
| 126 } | 109 } |
| 127 | 110 |
| 128 | 111 |
| 129 static inline bool IsByteOrderMark(uc32 c) { | 112 static inline bool IsByteOrderMark(uc32 c) { |
| 130 // The Unicode value U+FFFE is guaranteed never to be assigned as a | 113 // The Unicode value U+FFFE is guaranteed never to be assigned as a |
| 131 // Unicode character; this implies that in a Unicode context the | 114 // Unicode character; this implies that in a Unicode context the |
| 132 // 0xFF, 0xFE byte pattern can only be interpreted as the U+FEFF | 115 // 0xFF, 0xFE byte pattern can only be interpreted as the U+FEFF |
| 133 // character expressed in little-endian byte order (since it could | 116 // character expressed in little-endian byte order (since it could |
| 134 // not be a U+FFFE character expressed in big-endian byte | 117 // not be a U+FFFE character expressed in big-endian byte |
| 135 // order). Nevertheless, we check for it to be compatible with | 118 // order). Nevertheless, we check for it to be compatible with |
| 136 // Spidermonkey. | 119 // Spidermonkey. |
| 137 return c == 0xFEFF || c == 0xFFFE; | 120 return c == 0xFEFF || c == 0xFFFE; |
| 138 } | 121 } |
| 139 | 122 |
| 140 | 123 |
| 141 bool JavaScriptScanner::SkipWhiteSpace() { | 124 bool JavaScriptScanner::SkipWhiteSpace() { |
| 142 int start_position = source_pos(); | 125 int start_position = source_pos(); |
| 143 | 126 |
| 144 while (true) { | 127 while (true) { |
| 145 // We treat byte-order marks (BOMs) as whitespace for better | 128 // We treat byte-order marks (BOMs) as whitespace for better |
| 146 // compatibility with Spidermonkey and other JavaScript engines. | 129 // compatibility with Spidermonkey and other JavaScript engines. |
| 147 while (scanner_constants_->IsWhiteSpace(c0_) || IsByteOrderMark(c0_)) { | 130 while (unicode_cache_->IsWhiteSpace(c0_) || IsByteOrderMark(c0_)) { |
| 148 // IsWhiteSpace() includes line terminators! | 131 // IsWhiteSpace() includes line terminators! |
| 149 if (scanner_constants_->IsLineTerminator(c0_)) { | 132 if (unicode_cache_->IsLineTerminator(c0_)) { |
| 150 // Ignore line terminators, but remember them. This is necessary | 133 // Ignore line terminators, but remember them. This is necessary |
| 151 // for automatic semicolon insertion. | 134 // for automatic semicolon insertion. |
| 152 has_line_terminator_before_next_ = true; | 135 has_line_terminator_before_next_ = true; |
| 153 } | 136 } |
| 154 Advance(); | 137 Advance(); |
| 155 } | 138 } |
| 156 | 139 |
| 157 // If there is an HTML comment end '-->' at the beginning of a | 140 // If there is an HTML comment end '-->' at the beginning of a |
| 158 // line (with only whitespace in front of it), we treat the rest | 141 // line (with only whitespace in front of it), we treat the rest |
| 159 // of the line as a comment. This is in line with the way | 142 // of the line as a comment. This is in line with the way |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 179 | 162 |
| 180 | 163 |
| 181 Token::Value JavaScriptScanner::SkipSingleLineComment() { | 164 Token::Value JavaScriptScanner::SkipSingleLineComment() { |
| 182 Advance(); | 165 Advance(); |
| 183 | 166 |
| 184 // The line terminator at the end of the line is not considered | 167 // The line terminator at the end of the line is not considered |
| 185 // to be part of the single-line comment; it is recognized | 168 // to be part of the single-line comment; it is recognized |
| 186 // separately by the lexical grammar and becomes part of the | 169 // separately by the lexical grammar and becomes part of the |
| 187 // stream of input elements for the syntactic grammar (see | 170 // stream of input elements for the syntactic grammar (see |
| 188 // ECMA-262, section 7.4, page 12). | 171 // ECMA-262, section 7.4, page 12). |
| 189 while (c0_ >= 0 && !scanner_constants_->IsLineTerminator(c0_)) { | 172 while (c0_ >= 0 && !unicode_cache_->IsLineTerminator(c0_)) { |
| 190 Advance(); | 173 Advance(); |
| 191 } | 174 } |
| 192 | 175 |
| 193 return Token::WHITESPACE; | 176 return Token::WHITESPACE; |
| 194 } | 177 } |
| 195 | 178 |
| 196 | 179 |
| 197 Token::Value JavaScriptScanner::SkipMultiLineComment() { | 180 Token::Value JavaScriptScanner::SkipMultiLineComment() { |
| 198 ASSERT(c0_ == '*'); | 181 ASSERT(c0_ == '*'); |
| 199 Advance(); | 182 Advance(); |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 444 | 427 |
| 445 case '?': | 428 case '?': |
| 446 token = Select(Token::CONDITIONAL); | 429 token = Select(Token::CONDITIONAL); |
| 447 break; | 430 break; |
| 448 | 431 |
| 449 case '~': | 432 case '~': |
| 450 token = Select(Token::BIT_NOT); | 433 token = Select(Token::BIT_NOT); |
| 451 break; | 434 break; |
| 452 | 435 |
| 453 default: | 436 default: |
| 454 if (scanner_constants_->IsIdentifierStart(c0_)) { | 437 if (unicode_cache_->IsIdentifierStart(c0_)) { |
| 455 token = ScanIdentifierOrKeyword(); | 438 token = ScanIdentifierOrKeyword(); |
| 456 } else if (IsDecimalDigit(c0_)) { | 439 } else if (IsDecimalDigit(c0_)) { |
| 457 token = ScanNumber(false); | 440 token = ScanNumber(false); |
| 458 } else if (SkipWhiteSpace()) { | 441 } else if (SkipWhiteSpace()) { |
| 459 token = Token::WHITESPACE; | 442 token = Token::WHITESPACE; |
| 460 } else if (c0_ < 0) { | 443 } else if (c0_ < 0) { |
| 461 token = Token::EOS; | 444 token = Token::EOS; |
| 462 } else { | 445 } else { |
| 463 token = Select(Token::ILLEGAL); | 446 token = Select(Token::ILLEGAL); |
| 464 } | 447 } |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 492 } | 475 } |
| 493 Scan(); | 476 Scan(); |
| 494 } | 477 } |
| 495 | 478 |
| 496 | 479 |
| 497 void JavaScriptScanner::ScanEscape() { | 480 void JavaScriptScanner::ScanEscape() { |
| 498 uc32 c = c0_; | 481 uc32 c = c0_; |
| 499 Advance(); | 482 Advance(); |
| 500 | 483 |
| 501 // Skip escaped newlines. | 484 // Skip escaped newlines. |
| 502 if (scanner_constants_->IsLineTerminator(c)) { | 485 if (unicode_cache_->IsLineTerminator(c)) { |
| 503 // Allow CR+LF newlines in multiline string literals. | 486 // Allow CR+LF newlines in multiline string literals. |
| 504 if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance(); | 487 if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance(); |
| 505 // Allow LF+CR newlines in multiline string literals. | 488 // Allow LF+CR newlines in multiline string literals. |
| 506 if (IsLineFeed(c) && IsCarriageReturn(c0_)) Advance(); | 489 if (IsLineFeed(c) && IsCarriageReturn(c0_)) Advance(); |
| 507 return; | 490 return; |
| 508 } | 491 } |
| 509 | 492 |
| 510 switch (c) { | 493 switch (c) { |
| 511 case '\'': // fall through | 494 case '\'': // fall through |
| 512 case '"' : // fall through | 495 case '"' : // fall through |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 535 AddLiteralChar(c); | 518 AddLiteralChar(c); |
| 536 } | 519 } |
| 537 | 520 |
| 538 | 521 |
| 539 Token::Value JavaScriptScanner::ScanString() { | 522 Token::Value JavaScriptScanner::ScanString() { |
| 540 uc32 quote = c0_; | 523 uc32 quote = c0_; |
| 541 Advance(); // consume quote | 524 Advance(); // consume quote |
| 542 | 525 |
| 543 LiteralScope literal(this); | 526 LiteralScope literal(this); |
| 544 while (c0_ != quote && c0_ >= 0 | 527 while (c0_ != quote && c0_ >= 0 |
| 545 && !scanner_constants_->IsLineTerminator(c0_)) { | 528 && !unicode_cache_->IsLineTerminator(c0_)) { |
| 546 uc32 c = c0_; | 529 uc32 c = c0_; |
| 547 Advance(); | 530 Advance(); |
| 548 if (c == '\\') { | 531 if (c == '\\') { |
| 549 if (c0_ < 0) return Token::ILLEGAL; | 532 if (c0_ < 0) return Token::ILLEGAL; |
| 550 ScanEscape(); | 533 ScanEscape(); |
| 551 } else { | 534 } else { |
| 552 AddLiteralChar(c); | 535 AddLiteralChar(c); |
| 553 } | 536 } |
| 554 } | 537 } |
| 555 if (c0_ != quote) return Token::ILLEGAL; | 538 if (c0_ != quote) return Token::ILLEGAL; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 634 // we must have at least one decimal digit after 'e'/'E' | 617 // we must have at least one decimal digit after 'e'/'E' |
| 635 return Token::ILLEGAL; | 618 return Token::ILLEGAL; |
| 636 } | 619 } |
| 637 ScanDecimalDigits(); | 620 ScanDecimalDigits(); |
| 638 } | 621 } |
| 639 | 622 |
| 640 // The source character immediately following a numeric literal must | 623 // The source character immediately following a numeric literal must |
| 641 // not be an identifier start or a decimal digit; see ECMA-262 | 624 // not be an identifier start or a decimal digit; see ECMA-262 |
| 642 // section 7.8.3, page 17 (note that we read only one decimal digit | 625 // section 7.8.3, page 17 (note that we read only one decimal digit |
| 643 // if the value is 0). | 626 // if the value is 0). |
| 644 if (IsDecimalDigit(c0_) || scanner_constants_->IsIdentifierStart(c0_)) | 627 if (IsDecimalDigit(c0_) || unicode_cache_->IsIdentifierStart(c0_)) |
| 645 return Token::ILLEGAL; | 628 return Token::ILLEGAL; |
| 646 | 629 |
| 647 literal.Complete(); | 630 literal.Complete(); |
| 648 | 631 |
| 649 return Token::NUMBER; | 632 return Token::NUMBER; |
| 650 } | 633 } |
| 651 | 634 |
| 652 | 635 |
| 653 uc32 JavaScriptScanner::ScanIdentifierUnicodeEscape() { | 636 uc32 JavaScriptScanner::ScanIdentifierUnicodeEscape() { |
| 654 Advance(); | 637 Advance(); |
| 655 if (c0_ != 'u') return unibrow::Utf8::kBadChar; | 638 if (c0_ != 'u') return unibrow::Utf8::kBadChar; |
| 656 Advance(); | 639 Advance(); |
| 657 uc32 c = ScanHexEscape('u', 4); | 640 uc32 c = ScanHexEscape('u', 4); |
| 658 // We do not allow a unicode escape sequence to start another | 641 // We do not allow a unicode escape sequence to start another |
| 659 // unicode escape sequence. | 642 // unicode escape sequence. |
| 660 if (c == '\\') return unibrow::Utf8::kBadChar; | 643 if (c == '\\') return unibrow::Utf8::kBadChar; |
| 661 return c; | 644 return c; |
| 662 } | 645 } |
| 663 | 646 |
| 664 | 647 |
| 665 Token::Value JavaScriptScanner::ScanIdentifierOrKeyword() { | 648 Token::Value JavaScriptScanner::ScanIdentifierOrKeyword() { |
| 666 ASSERT(scanner_constants_->IsIdentifierStart(c0_)); | 649 ASSERT(unicode_cache_->IsIdentifierStart(c0_)); |
| 667 LiteralScope literal(this); | 650 LiteralScope literal(this); |
| 668 KeywordMatcher keyword_match; | 651 KeywordMatcher keyword_match; |
| 669 // Scan identifier start character. | 652 // Scan identifier start character. |
| 670 if (c0_ == '\\') { | 653 if (c0_ == '\\') { |
| 671 uc32 c = ScanIdentifierUnicodeEscape(); | 654 uc32 c = ScanIdentifierUnicodeEscape(); |
| 672 // Only allow legal identifier start characters. | 655 // Only allow legal identifier start characters. |
| 673 if (!scanner_constants_->IsIdentifierStart(c)) return Token::ILLEGAL; | 656 if (!unicode_cache_->IsIdentifierStart(c)) return Token::ILLEGAL; |
| 674 AddLiteralChar(c); | 657 AddLiteralChar(c); |
| 675 return ScanIdentifierSuffix(&literal); | 658 return ScanIdentifierSuffix(&literal); |
| 676 } | 659 } |
| 677 | 660 |
| 678 uc32 first_char = c0_; | 661 uc32 first_char = c0_; |
| 679 Advance(); | 662 Advance(); |
| 680 AddLiteralChar(first_char); | 663 AddLiteralChar(first_char); |
| 681 if (!keyword_match.AddChar(first_char)) { | 664 if (!keyword_match.AddChar(first_char)) { |
| 682 return ScanIdentifierSuffix(&literal); | 665 return ScanIdentifierSuffix(&literal); |
| 683 } | 666 } |
| 684 | 667 |
| 685 // Scan the rest of the identifier characters. | 668 // Scan the rest of the identifier characters. |
| 686 while (scanner_constants_->IsIdentifierPart(c0_)) { | 669 while (unicode_cache_->IsIdentifierPart(c0_)) { |
| 687 if (c0_ != '\\') { | 670 if (c0_ != '\\') { |
| 688 uc32 next_char = c0_; | 671 uc32 next_char = c0_; |
| 689 Advance(); | 672 Advance(); |
| 690 AddLiteralChar(next_char); | 673 AddLiteralChar(next_char); |
| 691 if (keyword_match.AddChar(next_char)) continue; | 674 if (keyword_match.AddChar(next_char)) continue; |
| 692 } | 675 } |
| 693 // Fallthrough if no loner able to complete keyword. | 676 // Fallthrough if no loner able to complete keyword. |
| 694 return ScanIdentifierSuffix(&literal); | 677 return ScanIdentifierSuffix(&literal); |
| 695 } | 678 } |
| 696 literal.Complete(); | 679 literal.Complete(); |
| 697 | 680 |
| 698 return keyword_match.token(); | 681 return keyword_match.token(); |
| 699 } | 682 } |
| 700 | 683 |
| 701 | 684 |
| 702 Token::Value JavaScriptScanner::ScanIdentifierSuffix(LiteralScope* literal) { | 685 Token::Value JavaScriptScanner::ScanIdentifierSuffix(LiteralScope* literal) { |
| 703 // Scan the rest of the identifier characters. | 686 // Scan the rest of the identifier characters. |
| 704 while (scanner_constants_->IsIdentifierPart(c0_)) { | 687 while (unicode_cache_->IsIdentifierPart(c0_)) { |
| 705 if (c0_ == '\\') { | 688 if (c0_ == '\\') { |
| 706 uc32 c = ScanIdentifierUnicodeEscape(); | 689 uc32 c = ScanIdentifierUnicodeEscape(); |
| 707 // Only allow legal identifier part characters. | 690 // Only allow legal identifier part characters. |
| 708 if (!scanner_constants_->IsIdentifierPart(c)) return Token::ILLEGAL; | 691 if (!unicode_cache_->IsIdentifierPart(c)) return Token::ILLEGAL; |
| 709 AddLiteralChar(c); | 692 AddLiteralChar(c); |
| 710 } else { | 693 } else { |
| 711 AddLiteralChar(c0_); | 694 AddLiteralChar(c0_); |
| 712 Advance(); | 695 Advance(); |
| 713 } | 696 } |
| 714 } | 697 } |
| 715 literal->Complete(); | 698 literal->Complete(); |
| 716 | 699 |
| 717 return Token::IDENTIFIER; | 700 return Token::IDENTIFIER; |
| 718 } | 701 } |
| 719 | 702 |
| 720 | 703 |
| 721 bool JavaScriptScanner::ScanRegExpPattern(bool seen_equal) { | 704 bool JavaScriptScanner::ScanRegExpPattern(bool seen_equal) { |
| 722 // Scan: ('/' | '/=') RegularExpressionBody '/' RegularExpressionFlags | 705 // Scan: ('/' | '/=') RegularExpressionBody '/' RegularExpressionFlags |
| 723 bool in_character_class = false; | 706 bool in_character_class = false; |
| 724 | 707 |
| 725 // Previous token is either '/' or '/=', in the second case, the | 708 // Previous token is either '/' or '/=', in the second case, the |
| 726 // pattern starts at =. | 709 // pattern starts at =. |
| 727 next_.location.beg_pos = source_pos() - (seen_equal ? 2 : 1); | 710 next_.location.beg_pos = source_pos() - (seen_equal ? 2 : 1); |
| 728 next_.location.end_pos = source_pos() - (seen_equal ? 1 : 0); | 711 next_.location.end_pos = source_pos() - (seen_equal ? 1 : 0); |
| 729 | 712 |
| 730 // Scan regular expression body: According to ECMA-262, 3rd, 7.8.5, | 713 // Scan regular expression body: According to ECMA-262, 3rd, 7.8.5, |
| 731 // the scanner should pass uninterpreted bodies to the RegExp | 714 // the scanner should pass uninterpreted bodies to the RegExp |
| 732 // constructor. | 715 // constructor. |
| 733 LiteralScope literal(this); | 716 LiteralScope literal(this); |
| 734 if (seen_equal) | 717 if (seen_equal) |
| 735 AddLiteralChar('='); | 718 AddLiteralChar('='); |
| 736 | 719 |
| 737 while (c0_ != '/' || in_character_class) { | 720 while (c0_ != '/' || in_character_class) { |
| 738 if (scanner_constants_->IsLineTerminator(c0_) || c0_ < 0) return false; | 721 if (unicode_cache_->IsLineTerminator(c0_) || c0_ < 0) return false; |
| 739 if (c0_ == '\\') { // Escape sequence. | 722 if (c0_ == '\\') { // Escape sequence. |
| 740 AddLiteralCharAdvance(); | 723 AddLiteralCharAdvance(); |
| 741 if (scanner_constants_->IsLineTerminator(c0_) || c0_ < 0) return false; | 724 if (unicode_cache_->IsLineTerminator(c0_) || c0_ < 0) return false; |
| 742 AddLiteralCharAdvance(); | 725 AddLiteralCharAdvance(); |
| 743 // If the escape allows more characters, i.e., \x??, \u????, or \c?, | 726 // If the escape allows more characters, i.e., \x??, \u????, or \c?, |
| 744 // only "safe" characters are allowed (letters, digits, underscore), | 727 // only "safe" characters are allowed (letters, digits, underscore), |
| 745 // otherwise the escape isn't valid and the invalid character has | 728 // otherwise the escape isn't valid and the invalid character has |
| 746 // its normal meaning. I.e., we can just continue scanning without | 729 // its normal meaning. I.e., we can just continue scanning without |
| 747 // worrying whether the following characters are part of the escape | 730 // worrying whether the following characters are part of the escape |
| 748 // or not, since any '/', '\\' or '[' is guaranteed to not be part | 731 // or not, since any '/', '\\' or '[' is guaranteed to not be part |
| 749 // of the escape sequence. | 732 // of the escape sequence. |
| 750 } else { // Unescaped character. | 733 } else { // Unescaped character. |
| 751 if (c0_ == '[') in_character_class = true; | 734 if (c0_ == '[') in_character_class = true; |
| 752 if (c0_ == ']') in_character_class = false; | 735 if (c0_ == ']') in_character_class = false; |
| 753 AddLiteralCharAdvance(); | 736 AddLiteralCharAdvance(); |
| 754 } | 737 } |
| 755 } | 738 } |
| 756 Advance(); // consume '/' | 739 Advance(); // consume '/' |
| 757 | 740 |
| 758 literal.Complete(); | 741 literal.Complete(); |
| 759 | 742 |
| 760 return true; | 743 return true; |
| 761 } | 744 } |
| 762 | 745 |
| 763 | 746 |
| 764 bool JavaScriptScanner::ScanRegExpFlags() { | 747 bool JavaScriptScanner::ScanRegExpFlags() { |
| 765 // Scan regular expression flags. | 748 // Scan regular expression flags. |
| 766 LiteralScope literal(this); | 749 LiteralScope literal(this); |
| 767 while (scanner_constants_->IsIdentifierPart(c0_)) { | 750 while (unicode_cache_->IsIdentifierPart(c0_)) { |
| 768 if (c0_ == '\\') { | 751 if (c0_ == '\\') { |
| 769 uc32 c = ScanIdentifierUnicodeEscape(); | 752 uc32 c = ScanIdentifierUnicodeEscape(); |
| 770 if (c != static_cast<uc32>(unibrow::Utf8::kBadChar)) { | 753 if (c != static_cast<uc32>(unibrow::Utf8::kBadChar)) { |
| 771 // We allow any escaped character, unlike the restriction on | 754 // We allow any escaped character, unlike the restriction on |
| 772 // IdentifierPart when it is used to build an IdentifierName. | 755 // IdentifierPart when it is used to build an IdentifierName. |
| 773 AddLiteralChar(c); | 756 AddLiteralChar(c); |
| 774 continue; | 757 continue; |
| 775 } | 758 } |
| 776 } | 759 } |
| 777 AddLiteralCharAdvance(); | 760 AddLiteralCharAdvance(); |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 955 if (MatchKeywordStart(input, "with", 1, Token::WITH)) return; | 938 if (MatchKeywordStart(input, "with", 1, Token::WITH)) return; |
| 956 break; | 939 break; |
| 957 case UNMATCHABLE: | 940 case UNMATCHABLE: |
| 958 break; | 941 break; |
| 959 } | 942 } |
| 960 // On fallthrough, it's a failure. | 943 // On fallthrough, it's a failure. |
| 961 state_ = UNMATCHABLE; | 944 state_ = UNMATCHABLE; |
| 962 } | 945 } |
| 963 | 946 |
| 964 } } // namespace v8::internal | 947 } } // namespace v8::internal |
| OLD | NEW |