Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Features shared by parsing and pre-parsing scanners. | 5 // Features shared by parsing and pre-parsing scanners. |
| 6 | 6 |
| 7 #ifndef V8_SCANNER_H_ | 7 #ifndef V8_SCANNER_H_ |
| 8 #define V8_SCANNER_H_ | 8 #define V8_SCANNER_H_ |
| 9 | 9 |
| 10 #include "src/allocation.h" | 10 #include "src/allocation.h" |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 182 UnicodeCache* unicode_constants_; | 182 UnicodeCache* unicode_constants_; |
| 183 // Backing store used to store strings used as hashmap keys. | 183 // Backing store used to store strings used as hashmap keys. |
| 184 SequenceCollector<unsigned char> backing_store_; | 184 SequenceCollector<unsigned char> backing_store_; |
| 185 HashMap map_; | 185 HashMap map_; |
| 186 // Buffer used for string->number->canonical string conversions. | 186 // Buffer used for string->number->canonical string conversions. |
| 187 char number_buffer_[kBufferSize]; | 187 char number_buffer_[kBufferSize]; |
| 188 }; | 188 }; |
| 189 | 189 |
| 190 | 190 |
| 191 // ---------------------------------------------------------------------------- | 191 // ---------------------------------------------------------------------------- |
| 192 // ParamListFinder discovers sequences of tokens which form a valid function | |
| 193 // parameter list. | |
| 194 class Scanner; | |
| 195 | |
| 196 class ParamListFinder { | |
| 197 public: | |
| 198 explicit ParamListFinder(UnicodeCache* unicode_cache) | |
| 199 : state_(Invalid) | |
| 200 , start_pos_(-1) | |
| 201 , identifier_pos_(-1) | |
| 202 , duplicate_pos_(-1) | |
| 203 , duplicate_finder_(unicode_cache) { } | |
| 204 | |
| 205 V8_INLINE void Update(Scanner* scanner); | |
| 206 | |
| 207 bool IsValid(int pos) const { | |
| 208 return (state_ == Valid && start_pos_ == pos) | |
| 209 || (identifier_pos_ == pos); | |
| 210 } | |
| 211 | |
| 212 bool HasDuplicateIdentifiers() const { | |
| 213 return duplicate_pos_ > start_pos_; | |
| 214 } | |
| 215 | |
| 216 int FirstDuplicatePosition() const { | |
| 217 return duplicate_pos_; | |
| 218 } | |
| 219 | |
| 220 private: | |
| 221 enum State { | |
| 222 Invalid, | |
| 223 Valid, | |
| 224 LeftParen, | |
| 225 Identifier, | |
| 226 Comma | |
| 227 }; | |
| 228 | |
| 229 V8_INLINE void AddIdentifier(Scanner* scanner); | |
| 230 | |
| 231 State state_; | |
| 232 int start_pos_; | |
| 233 int identifier_pos_; | |
| 234 int duplicate_pos_; | |
| 235 DuplicateFinder duplicate_finder_; | |
| 236 }; | |
| 237 | |
| 238 | |
| 239 // ---------------------------------------------------------------------------- | |
| 192 // LiteralBuffer - Collector of chars of literals. | 240 // LiteralBuffer - Collector of chars of literals. |
| 193 | 241 |
| 194 class LiteralBuffer { | 242 class LiteralBuffer { |
| 195 public: | 243 public: |
| 196 LiteralBuffer() : is_one_byte_(true), position_(0), backing_store_() { } | 244 LiteralBuffer() : is_one_byte_(true), position_(0), backing_store_() { } |
| 197 | 245 |
| 198 ~LiteralBuffer() { | 246 ~LiteralBuffer() { |
| 199 if (backing_store_.length() > 0) { | 247 if (backing_store_.length() > 0) { |
| 200 backing_store_.Dispose(); | 248 backing_store_.Dispose(); |
| 201 } | 249 } |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 396 if (is_literal_one_byte() && | 444 if (is_literal_one_byte() && |
| 397 literal_length() == 3 && | 445 literal_length() == 3 && |
| 398 !literal_contains_escapes()) { | 446 !literal_contains_escapes()) { |
| 399 const char* token = | 447 const char* token = |
| 400 reinterpret_cast<const char*>(literal_one_byte_string().start()); | 448 reinterpret_cast<const char*>(literal_one_byte_string().start()); |
| 401 *is_get = strncmp(token, "get", 3) == 0; | 449 *is_get = strncmp(token, "get", 3) == 0; |
| 402 *is_set = !*is_get && strncmp(token, "set", 3) == 0; | 450 *is_set = !*is_get && strncmp(token, "set", 3) == 0; |
| 403 } | 451 } |
| 404 } | 452 } |
| 405 | 453 |
| 454 ParamListFinder* parameter_list() { | |
| 455 return ¶m_list_finder_; | |
| 456 } | |
| 457 | |
| 406 int FindNumber(DuplicateFinder* finder, int value); | 458 int FindNumber(DuplicateFinder* finder, int value); |
| 407 int FindSymbol(DuplicateFinder* finder, int value); | 459 int FindSymbol(DuplicateFinder* finder, int value); |
| 408 | 460 |
| 409 UnicodeCache* unicode_cache() { return unicode_cache_; } | 461 UnicodeCache* unicode_cache() { return unicode_cache_; } |
| 410 | 462 |
| 411 // Returns the location of the last seen octal literal. | 463 // Returns the location of the last seen octal literal. |
| 412 Location octal_position() const { return octal_pos_; } | 464 Location octal_position() const { return octal_pos_; } |
| 413 void clear_octal_position() { octal_pos_ = Location::invalid(); } | 465 void clear_octal_position() { octal_pos_ = Location::invalid(); } |
| 414 | 466 |
| 415 // Seek forward to the given position. This operation does not | 467 // Seek forward to the given position. This operation does not |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 444 has_multiline_comment_before_next_; | 496 has_multiline_comment_before_next_; |
| 445 } | 497 } |
| 446 | 498 |
| 447 // Scans the input as a regular expression pattern, previous | 499 // Scans the input as a regular expression pattern, previous |
| 448 // character(s) must be /(=). Returns true if a pattern is scanned. | 500 // character(s) must be /(=). Returns true if a pattern is scanned. |
| 449 bool ScanRegExpPattern(bool seen_equal); | 501 bool ScanRegExpPattern(bool seen_equal); |
| 450 // Returns true if regexp flags are scanned (always since flags can | 502 // Returns true if regexp flags are scanned (always since flags can |
| 451 // be empty). | 503 // be empty). |
| 452 bool ScanRegExpFlags(); | 504 bool ScanRegExpFlags(); |
| 453 | 505 |
| 506 bool IdentifierIsFutureStrictReserved(const AstString* string) const; | |
| 507 | |
| 454 private: | 508 private: |
| 455 // The current and look-ahead token. | 509 // The current and look-ahead token. |
| 456 struct TokenDesc { | 510 struct TokenDesc { |
| 457 Token::Value token; | 511 Token::Value token; |
| 458 Location location; | 512 Location location; |
| 459 LiteralBuffer* literal_chars; | 513 LiteralBuffer* literal_chars; |
| 460 }; | 514 }; |
| 461 | 515 |
| 462 static const int kCharacterLookaheadBufferSize = 1; | 516 static const int kCharacterLookaheadBufferSize = 1; |
| 463 | 517 |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 599 int source_pos() { | 653 int source_pos() { |
| 600 return source_->pos() - kCharacterLookaheadBufferSize; | 654 return source_->pos() - kCharacterLookaheadBufferSize; |
| 601 } | 655 } |
| 602 | 656 |
| 603 UnicodeCache* unicode_cache_; | 657 UnicodeCache* unicode_cache_; |
| 604 | 658 |
| 605 // Buffers collecting literal strings, numbers, etc. | 659 // Buffers collecting literal strings, numbers, etc. |
| 606 LiteralBuffer literal_buffer1_; | 660 LiteralBuffer literal_buffer1_; |
| 607 LiteralBuffer literal_buffer2_; | 661 LiteralBuffer literal_buffer2_; |
| 608 | 662 |
| 663 ParamListFinder param_list_finder_; | |
| 664 | |
| 609 TokenDesc current_; // desc for current token (as returned by Next()) | 665 TokenDesc current_; // desc for current token (as returned by Next()) |
| 610 TokenDesc next_; // desc for next token (one token look-ahead) | 666 TokenDesc next_; // desc for next token (one token look-ahead) |
| 611 | 667 |
| 612 // Input stream. Must be initialized to an Utf16CharacterStream. | 668 // Input stream. Must be initialized to an Utf16CharacterStream. |
| 613 Utf16CharacterStream* source_; | 669 Utf16CharacterStream* source_; |
| 614 | 670 |
| 615 | 671 |
| 616 // Start position of the octal literal last scanned. | 672 // Start position of the octal literal last scanned. |
| 617 Location octal_pos_; | 673 Location octal_pos_; |
| 618 | 674 |
| 619 // One Unicode character look-ahead; c0_ < 0 at the end of the input. | 675 // One Unicode character look-ahead; c0_ < 0 at the end of the input. |
| 620 uc32 c0_; | 676 uc32 c0_; |
| 621 | 677 |
| 622 // Whether there is a line terminator whitespace character after | 678 // Whether there is a line terminator whitespace character after |
| 623 // the current token, and before the next. Does not count newlines | 679 // the current token, and before the next. Does not count newlines |
| 624 // inside multiline comments. | 680 // inside multiline comments. |
| 625 bool has_line_terminator_before_next_; | 681 bool has_line_terminator_before_next_; |
| 626 // Whether there is a multi-line comment that contains a | 682 // Whether there is a multi-line comment that contains a |
| 627 // line-terminator after the current token, and before the next. | 683 // line-terminator after the current token, and before the next. |
| 628 bool has_multiline_comment_before_next_; | 684 bool has_multiline_comment_before_next_; |
| 629 // Whether we scan 'let' as a keyword for harmony block-scoped let bindings. | 685 // Whether we scan 'let' as a keyword for harmony block-scoped let bindings. |
| 630 bool harmony_scoping_; | 686 bool harmony_scoping_; |
| 631 // Whether we scan 'module', 'import', 'export' as keywords. | 687 // Whether we scan 'module', 'import', 'export' as keywords. |
| 632 bool harmony_modules_; | 688 bool harmony_modules_; |
| 633 // Whether we scan 0o777 and 0b111 as numbers. | 689 // Whether we scan 0o777 and 0b111 as numbers. |
| 634 bool harmony_numeric_literals_; | 690 bool harmony_numeric_literals_; |
| 635 }; | 691 }; |
| 636 | 692 |
| 693 | |
| 694 void ParamListFinder::Update(Scanner* scanner) { | |
| 695 const Token::Value token = scanner->current_token(); | |
| 696 | |
| 697 switch (token) { | |
| 698 case Token::IDENTIFIER: | |
| 699 case Token::YIELD: | |
| 700 case Token::FUTURE_STRICT_RESERVED_WORD: | |
| 701 identifier_pos_ = scanner->location().beg_pos; | |
| 702 AddIdentifier(scanner); | |
| 703 break; | |
| 704 default: | |
| 705 identifier_pos_ = -1; | |
| 706 } | |
| 707 | |
| 708 switch (state_) { | |
| 709 case Valid: | |
| 710 state_ = Invalid; | |
| 711 start_pos_ = -1; | |
| 712 // Fall-through. | |
| 713 case Invalid: | |
| 714 switch (token) { | |
| 715 case Token::LPAREN: | |
| 716 state_ = LeftParen; | |
| 717 start_pos_ = scanner->location().beg_pos; | |
| 718 break; | |
| 719 default: | |
| 720 // Stay in Invalid state. | |
| 721 break; | |
| 722 } | |
| 723 break; | |
| 724 | |
| 725 case LeftParen: | |
| 726 switch (token) { | |
| 727 case Token::LPAREN: | |
| 728 start_pos_ = scanner->location().beg_pos; | |
| 729 break; | |
| 730 case Token::RPAREN: | |
| 731 state_ = Valid; | |
| 732 break; | |
| 733 case Token::YIELD: | |
| 734 case Token::IDENTIFIER: | |
| 735 case Token::FUTURE_STRICT_RESERVED_WORD: | |
| 736 state_ = Identifier; | |
| 737 break; | |
| 738 default: | |
| 739 state_ = Invalid; | |
| 740 } | |
| 741 break; | |
| 742 | |
| 743 case Identifier: | |
| 744 switch (token) { | |
| 745 case Token::RPAREN: | |
| 746 state_ = Valid; | |
| 747 break; | |
| 748 case Token::COMMA: | |
| 749 state_ = Comma; | |
| 750 break; | |
| 751 default: | |
| 752 state_ = Invalid; | |
| 753 } | |
| 754 break; | |
| 755 | |
| 756 case Comma: | |
| 757 switch (token) { | |
| 758 case Token::YIELD: | |
| 759 case Token::IDENTIFIER: | |
| 760 case Token::FUTURE_STRICT_RESERVED_WORD: | |
| 761 state_ = Identifier; | |
| 762 break; | |
| 763 default: | |
| 764 state_ = Invalid; | |
| 765 } | |
| 766 break; | |
| 767 } | |
|
marja
2014/06/18 16:21:16
Btw, I don't think this state machine works anyway
| |
| 768 } | |
| 769 | |
| 770 | |
| 771 void ParamListFinder::AddIdentifier(Scanner* scanner) { | |
| 772 // A duplicate has already been found. | |
| 773 if (duplicate_pos_ >= start_pos_) | |
| 774 return; | |
| 775 | |
| 776 int prev_value = scanner->FindSymbol(&duplicate_finder_, 1); | |
| 777 if (prev_value != 0) { | |
| 778 duplicate_pos_ = scanner->location().beg_pos; | |
| 779 } | |
| 780 } | |
| 781 | |
| 637 } } // namespace v8::internal | 782 } } // namespace v8::internal |
| 638 | 783 |
| 639 #endif // V8_SCANNER_H_ | 784 #endif // V8_SCANNER_H_ |
| OLD | NEW |