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 #include "src/parsing/scanner.h" | 7 #include "src/parsing/scanner.h" |
8 | 8 |
9 #include <stdint.h> | 9 #include <stdint.h> |
10 | 10 |
11 #include <cmath> | 11 #include <cmath> |
12 | 12 |
13 #include "src/ast/ast-value-factory.h" | 13 #include "src/ast/ast-value-factory.h" |
14 #include "src/char-predicates-inl.h" | 14 #include "src/char-predicates-inl.h" |
15 #include "src/conversions-inl.h" | 15 #include "src/conversions-inl.h" |
16 #include "src/list-inl.h" | 16 #include "src/list-inl.h" |
17 #include "src/parsing/duplicate-finder.h" // For Scanner::FindSymbol | 17 #include "src/parsing/duplicate-finder.h" // For Scanner::FindSymbol |
18 | 18 |
19 namespace v8 { | 19 namespace v8 { |
20 namespace internal { | 20 namespace internal { |
21 | 21 |
22 Handle<String> Scanner::LiteralBuffer::Internalize(Isolate* isolate) const { | 22 Handle<String> Scanner::LiteralBuffer::Internalize(Isolate* isolate) const { |
23 if (is_one_byte()) { | 23 if (is_one_byte()) { |
24 return isolate->factory()->InternalizeOneByteString(one_byte_literal()); | 24 return isolate->factory()->InternalizeOneByteString(one_byte_literal()); |
25 } | 25 } |
26 return isolate->factory()->InternalizeTwoByteString(two_byte_literal()); | 26 return isolate->factory()->InternalizeTwoByteString(two_byte_literal()); |
27 } | 27 } |
28 | 28 |
| 29 // ---------------------------------------------------------------------------- |
| 30 // Scanner::BookmarkScope |
| 31 |
| 32 const size_t Scanner::BookmarkScope::kBookmarkAtFirstPos = |
| 33 std::numeric_limits<size_t>::max() - 2; |
| 34 const size_t Scanner::BookmarkScope::kNoBookmark = |
| 35 std::numeric_limits<size_t>::max() - 1; |
| 36 const size_t Scanner::BookmarkScope::kBookmarkWasApplied = |
| 37 std::numeric_limits<size_t>::max(); |
| 38 |
| 39 void Scanner::BookmarkScope::Set() { |
| 40 DCHECK_EQ(bookmark_, kNoBookmark); |
| 41 DCHECK_EQ(scanner_->next_next_.token, Token::UNINITIALIZED); |
| 42 |
| 43 // The first token is a bit special, since current_ will still be |
| 44 // uninitialized. In this case, store kBookmarkAtFirstPos and special-case it |
| 45 // when |
| 46 // applying the bookmark. |
| 47 DCHECK_IMPLIES( |
| 48 scanner_->current_.token == Token::UNINITIALIZED, |
| 49 scanner_->current_.location.beg_pos == scanner_->next_.location.beg_pos); |
| 50 bookmark_ = (scanner_->current_.token == Token::UNINITIALIZED) |
| 51 ? kBookmarkAtFirstPos |
| 52 : scanner_->location().beg_pos; |
| 53 } |
| 54 |
| 55 void Scanner::BookmarkScope::Apply() { |
| 56 DCHECK(HasBeenSet()); // Caller hasn't called SetBookmark. |
| 57 if (bookmark_ == kBookmarkAtFirstPos) { |
| 58 scanner_->SeekNext(0); |
| 59 } else { |
| 60 scanner_->SeekNext(bookmark_); |
| 61 scanner_->Next(); |
| 62 DCHECK_EQ(scanner_->location().beg_pos, bookmark_); |
| 63 } |
| 64 bookmark_ = kBookmarkWasApplied; |
| 65 } |
| 66 |
| 67 bool Scanner::BookmarkScope::HasBeenSet() { |
| 68 return bookmark_ != kNoBookmark && bookmark_ != kBookmarkWasApplied; |
| 69 } |
| 70 |
| 71 bool Scanner::BookmarkScope::HasBeenApplied() { |
| 72 return bookmark_ == kBookmarkWasApplied; |
| 73 } |
29 | 74 |
30 // ---------------------------------------------------------------------------- | 75 // ---------------------------------------------------------------------------- |
31 // Scanner | 76 // Scanner |
32 | 77 |
33 Scanner::Scanner(UnicodeCache* unicode_cache) | 78 Scanner::Scanner(UnicodeCache* unicode_cache) |
34 : unicode_cache_(unicode_cache), | 79 : unicode_cache_(unicode_cache), |
35 bookmark_c0_(kNoBookmark), | |
36 bookmark_position_(0), | |
37 octal_pos_(Location::invalid()), | 80 octal_pos_(Location::invalid()), |
38 decimal_with_leading_zero_pos_(Location::invalid()), | 81 decimal_with_leading_zero_pos_(Location::invalid()), |
39 found_html_comment_(false) { | 82 found_html_comment_(false) { |
40 bookmark_current_.literal_chars = &bookmark_current_literal_; | |
41 bookmark_current_.raw_literal_chars = &bookmark_current_raw_literal_; | |
42 bookmark_next_.literal_chars = &bookmark_next_literal_; | |
43 bookmark_next_.raw_literal_chars = &bookmark_next_raw_literal_; | |
44 } | 83 } |
45 | 84 |
46 | 85 |
47 void Scanner::Initialize(Utf16CharacterStream* source) { | 86 void Scanner::Initialize(Utf16CharacterStream* source) { |
48 source_ = source; | 87 source_ = source; |
49 // Need to capture identifiers in order to recognize "get" and "set" | 88 // Need to capture identifiers in order to recognize "get" and "set" |
50 // in object literals. | 89 // in object literals. |
51 Init(); | 90 Init(); |
52 // Skip initial whitespace allowing HTML comment ends just like | 91 // Skip initial whitespace allowing HTML comment ends just like |
53 // after a newline and scan first token. | 92 // after a newline and scan first token. |
(...skipping 1520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1574 | 1613 |
1575 int Scanner::FindSymbol(DuplicateFinder* finder, int value) { | 1614 int Scanner::FindSymbol(DuplicateFinder* finder, int value) { |
1576 // TODO(vogelheim): Move this logic into the calling class; this can be fully | 1615 // TODO(vogelheim): Move this logic into the calling class; this can be fully |
1577 // implemented using the public interface. | 1616 // implemented using the public interface. |
1578 if (is_literal_one_byte()) { | 1617 if (is_literal_one_byte()) { |
1579 return finder->AddOneByteSymbol(literal_one_byte_string(), value); | 1618 return finder->AddOneByteSymbol(literal_one_byte_string(), value); |
1580 } | 1619 } |
1581 return finder->AddTwoByteSymbol(literal_two_byte_string(), value); | 1620 return finder->AddTwoByteSymbol(literal_two_byte_string(), value); |
1582 } | 1621 } |
1583 | 1622 |
1584 void Scanner::SetBookmark() { | 1623 void Scanner::SeekNext(size_t position) { |
1585 DCHECK_EQ(bookmark_c0_, kNoBookmark); | 1624 // Use with care: This cleanly resets most, but not all scanner state. |
1586 DCHECK_EQ(next_next_.token, Token::UNINITIALIZED); | 1625 // TODO(vogelheim): Fix this, or at least DCHECK the relevant conditions. |
1587 bookmark_c0_ = c0_; | 1626 |
1588 bookmark_position_ = source_->pos(); | 1627 // To re-scan from a given character position, we need to: |
1589 CopyTokenDesc(&bookmark_current_, ¤t_); | 1628 // 1, Reset the current_, next_ and next_next_ tokens |
1590 CopyTokenDesc(&bookmark_next_, &next_); | 1629 // (next_ + next_next_ will be overwrittem by Next(), |
| 1630 // current_ will remain unchanged, so overwrite it fully.) |
| 1631 current_ = {{0, 0}, nullptr, nullptr, 0, Token::UNINITIALIZED}; |
| 1632 next_.token = Token::UNINITIALIZED; |
| 1633 next_next_.token = Token::UNINITIALIZED; |
| 1634 // 2, reset the source to the desired position, |
| 1635 source_->Seek(position); |
| 1636 // 3, re-scan, by scanning the look-ahead char + 1 token (next_). |
| 1637 c0_ = source_->Advance(); |
| 1638 Next(); |
| 1639 DCHECK_EQ(next_.location.beg_pos, position); |
1591 } | 1640 } |
1592 | 1641 |
1593 | |
1594 void Scanner::ResetToBookmark() { | |
1595 DCHECK(BookmarkHasBeenSet()); // Caller hasn't called SetBookmark. | |
1596 | |
1597 source_->Seek(bookmark_position_); | |
1598 c0_ = bookmark_c0_; | |
1599 CopyToNextTokenDesc(&bookmark_current_); | |
1600 current_ = next_; | |
1601 CopyToNextTokenDesc(&bookmark_next_); | |
1602 bookmark_c0_ = kBookmarkWasApplied; | |
1603 } | |
1604 | |
1605 bool Scanner::BookmarkHasBeenSet() { | |
1606 return bookmark_c0_ != kNoBookmark && bookmark_c0_ != kBookmarkWasApplied; | |
1607 } | |
1608 | |
1609 bool Scanner::BookmarkHasBeenReset() { | |
1610 return bookmark_c0_ == kBookmarkWasApplied; | |
1611 } | |
1612 | |
1613 | |
1614 void Scanner::DropBookmark() { bookmark_c0_ = kNoBookmark; } | |
1615 | |
1616 void Scanner::CopyToNextTokenDesc(TokenDesc* from) { | |
1617 StartLiteral(); | |
1618 StartRawLiteral(); | |
1619 CopyTokenDesc(&next_, from); | |
1620 if (next_.literal_chars->length() == 0) next_.literal_chars = nullptr; | |
1621 if (next_.raw_literal_chars->length() == 0) next_.raw_literal_chars = nullptr; | |
1622 } | |
1623 | |
1624 void Scanner::CopyTokenDesc(TokenDesc* to, TokenDesc* from) { | |
1625 DCHECK_NOT_NULL(to); | |
1626 DCHECK_NOT_NULL(from); | |
1627 to->token = from->token; | |
1628 to->location = from->location; | |
1629 to->literal_chars->CopyFrom(from->literal_chars); | |
1630 to->raw_literal_chars->CopyFrom(from->raw_literal_chars); | |
1631 } | |
1632 | |
1633 | |
1634 | |
1635 } // namespace internal | 1642 } // namespace internal |
1636 } // namespace v8 | 1643 } // namespace v8 |
OLD | NEW |