Home | History | Annotate | Download | only in parsing
      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
      3 // found in the LICENSE file.
      4 
      5 // Features shared by parsing and pre-parsing scanners.
      6 
      7 #ifndef V8_PARSING_SCANNER_H_
      8 #define V8_PARSING_SCANNER_H_
      9 
     10 #include "src/allocation.h"
     11 #include "src/base/logging.h"
     12 #include "src/char-predicates.h"
     13 #include "src/globals.h"
     14 #include "src/hashmap.h"
     15 #include "src/list.h"
     16 #include "src/parsing/token.h"
     17 #include "src/unicode.h"
     18 #include "src/unicode-decoder.h"
     19 #include "src/utils.h"
     20 
     21 namespace v8 {
     22 namespace internal {
     23 
     24 
     25 class AstRawString;
     26 class AstValueFactory;
     27 class ParserRecorder;
     28 class UnicodeCache;
     29 
     30 
     31 // ---------------------------------------------------------------------
     32 // Buffered stream of UTF-16 code units, using an internal UTF-16 buffer.
     33 // A code unit is a 16 bit value representing either a 16 bit code point
     34 // or one part of a surrogate pair that make a single 21 bit code point.
     35 
     36 class Utf16CharacterStream {
     37  public:
     38   Utf16CharacterStream() : pos_(0) { }
     39   virtual ~Utf16CharacterStream() { }
     40 
     41   // Returns and advances past the next UTF-16 code unit in the input
     42   // stream. If there are no more code units, it returns a negative
     43   // value.
     44   inline uc32 Advance() {
     45     if (buffer_cursor_ < buffer_end_ || ReadBlock()) {
     46       pos_++;
     47       return static_cast<uc32>(*(buffer_cursor_++));
     48     }
     49     // Note: currently the following increment is necessary to avoid a
     50     // parser problem! The scanner treats the final kEndOfInput as
     51     // a code unit with a position, and does math relative to that
     52     // position.
     53     pos_++;
     54 
     55     return kEndOfInput;
     56   }
     57 
     58   // Return the current position in the code unit stream.
     59   // Starts at zero.
     60   inline size_t pos() const { return pos_; }
     61 
     62   // Skips forward past the next code_unit_count UTF-16 code units
     63   // in the input, or until the end of input if that comes sooner.
     64   // Returns the number of code units actually skipped. If less
     65   // than code_unit_count,
     66   inline size_t SeekForward(size_t code_unit_count) {
     67     size_t buffered_chars = buffer_end_ - buffer_cursor_;
     68     if (code_unit_count <= buffered_chars) {
     69       buffer_cursor_ += code_unit_count;
     70       pos_ += code_unit_count;
     71       return code_unit_count;
     72     }
     73     return SlowSeekForward(code_unit_count);
     74   }
     75 
     76   // Pushes back the most recently read UTF-16 code unit (or negative
     77   // value if at end of input), i.e., the value returned by the most recent
     78   // call to Advance.
     79   // Must not be used right after calling SeekForward.
     80   virtual void PushBack(int32_t code_unit) = 0;
     81 
     82   virtual bool SetBookmark();
     83   virtual void ResetToBookmark();
     84 
     85  protected:
     86   static const uc32 kEndOfInput = -1;
     87 
     88   // Ensures that the buffer_cursor_ points to the code_unit at
     89   // position pos_ of the input, if possible. If the position
     90   // is at or after the end of the input, return false. If there
     91   // are more code_units available, return true.
     92   virtual bool ReadBlock() = 0;
     93   virtual size_t SlowSeekForward(size_t code_unit_count) = 0;
     94 
     95   const uint16_t* buffer_cursor_;
     96   const uint16_t* buffer_end_;
     97   size_t pos_;
     98 };
     99 
    100 
    101 // ---------------------------------------------------------------------
    102 // DuplicateFinder discovers duplicate symbols.
    103 
    104 class DuplicateFinder {
    105  public:
    106   explicit DuplicateFinder(UnicodeCache* constants)
    107       : unicode_constants_(constants),
    108         backing_store_(16),
    109         map_(&Match) { }
    110 
    111   int AddOneByteSymbol(Vector<const uint8_t> key, int value);
    112   int AddTwoByteSymbol(Vector<const uint16_t> key, int value);
    113   // Add a a number literal by converting it (if necessary)
    114   // to the string that ToString(ToNumber(literal)) would generate.
    115   // and then adding that string with AddOneByteSymbol.
    116   // This string is the actual value used as key in an object literal,
    117   // and the one that must be different from the other keys.
    118   int AddNumber(Vector<const uint8_t> key, int value);
    119 
    120  private:
    121   int AddSymbol(Vector<const uint8_t> key, bool is_one_byte, int value);
    122   // Backs up the key and its length in the backing store.
    123   // The backup is stored with a base 127 encoding of the
    124   // length (plus a bit saying whether the string is one byte),
    125   // followed by the bytes of the key.
    126   uint8_t* BackupKey(Vector<const uint8_t> key, bool is_one_byte);
    127 
    128   // Compare two encoded keys (both pointing into the backing store)
    129   // for having the same base-127 encoded lengths and representation.
    130   // and then having the same 'length' bytes following.
    131   static bool Match(void* first, void* second);
    132   // Creates a hash from a sequence of bytes.
    133   static uint32_t Hash(Vector<const uint8_t> key, bool is_one_byte);
    134   // Checks whether a string containing a JS number is its canonical
    135   // form.
    136   static bool IsNumberCanonical(Vector<const uint8_t> key);
    137 
    138   // Size of buffer. Sufficient for using it to call DoubleToCString in
    139   // from conversions.h.
    140   static const int kBufferSize = 100;
    141 
    142   UnicodeCache* unicode_constants_;
    143   // Backing store used to store strings used as hashmap keys.
    144   SequenceCollector<unsigned char> backing_store_;
    145   HashMap map_;
    146   // Buffer used for string->number->canonical string conversions.
    147   char number_buffer_[kBufferSize];
    148 };
    149 
    150 
    151 // ----------------------------------------------------------------------------
    152 // LiteralBuffer -  Collector of chars of literals.
    153 
    154 class LiteralBuffer {
    155  public:
    156   LiteralBuffer() : is_one_byte_(true), position_(0), backing_store_() { }
    157 
    158   ~LiteralBuffer() { backing_store_.Dispose(); }
    159 
    160   INLINE(void AddChar(uint32_t code_unit)) {
    161     if (position_ >= backing_store_.length()) ExpandBuffer();
    162     if (is_one_byte_) {
    163       if (code_unit <= unibrow::Latin1::kMaxChar) {
    164         backing_store_[position_] = static_cast<byte>(code_unit);
    165         position_ += kOneByteSize;
    166         return;
    167       }
    168       ConvertToTwoByte();
    169     }
    170     if (code_unit <= unibrow::Utf16::kMaxNonSurrogateCharCode) {
    171       *reinterpret_cast<uint16_t*>(&backing_store_[position_]) = code_unit;
    172       position_ += kUC16Size;
    173     } else {
    174       *reinterpret_cast<uint16_t*>(&backing_store_[position_]) =
    175           unibrow::Utf16::LeadSurrogate(code_unit);
    176       position_ += kUC16Size;
    177       if (position_ >= backing_store_.length()) ExpandBuffer();
    178       *reinterpret_cast<uint16_t*>(&backing_store_[position_]) =
    179           unibrow::Utf16::TrailSurrogate(code_unit);
    180       position_ += kUC16Size;
    181     }
    182   }
    183 
    184   bool is_one_byte() const { return is_one_byte_; }
    185 
    186   bool is_contextual_keyword(Vector<const char> keyword) const {
    187     return is_one_byte() && keyword.length() == position_ &&
    188         (memcmp(keyword.start(), backing_store_.start(), position_) == 0);
    189   }
    190 
    191   Vector<const uint16_t> two_byte_literal() const {
    192     DCHECK(!is_one_byte_);
    193     DCHECK((position_ & 0x1) == 0);
    194     return Vector<const uint16_t>(
    195         reinterpret_cast<const uint16_t*>(backing_store_.start()),
    196         position_ >> 1);
    197   }
    198 
    199   Vector<const uint8_t> one_byte_literal() const {
    200     DCHECK(is_one_byte_);
    201     return Vector<const uint8_t>(
    202         reinterpret_cast<const uint8_t*>(backing_store_.start()),
    203         position_);
    204   }
    205 
    206   int length() const {
    207     return is_one_byte_ ? position_ : (position_ >> 1);
    208   }
    209 
    210   void ReduceLength(int delta) {
    211     position_ -= delta * (is_one_byte_ ? kOneByteSize : kUC16Size);
    212   }
    213 
    214   void Reset() {
    215     position_ = 0;
    216     is_one_byte_ = true;
    217   }
    218 
    219   Handle<String> Internalize(Isolate* isolate) const;
    220 
    221   void CopyFrom(const LiteralBuffer* other) {
    222     if (other == nullptr) {
    223       Reset();
    224     } else {
    225       is_one_byte_ = other->is_one_byte_;
    226       position_ = other->position_;
    227       backing_store_.Dispose();
    228       backing_store_ = other->backing_store_.Clone();
    229     }
    230   }
    231 
    232  private:
    233   static const int kInitialCapacity = 16;
    234   static const int kGrowthFactory = 4;
    235   static const int kMinConversionSlack = 256;
    236   static const int kMaxGrowth = 1 * MB;
    237   inline int NewCapacity(int min_capacity) {
    238     int capacity = Max(min_capacity, backing_store_.length());
    239     int new_capacity = Min(capacity * kGrowthFactory, capacity + kMaxGrowth);
    240     return new_capacity;
    241   }
    242 
    243   void ExpandBuffer() {
    244     Vector<byte> new_store = Vector<byte>::New(NewCapacity(kInitialCapacity));
    245     MemCopy(new_store.start(), backing_store_.start(), position_);
    246     backing_store_.Dispose();
    247     backing_store_ = new_store;
    248   }
    249 
    250   void ConvertToTwoByte() {
    251     DCHECK(is_one_byte_);
    252     Vector<byte> new_store;
    253     int new_content_size = position_ * kUC16Size;
    254     if (new_content_size >= backing_store_.length()) {
    255       // Ensure room for all currently read code units as UC16 as well
    256       // as the code unit about to be stored.
    257       new_store = Vector<byte>::New(NewCapacity(new_content_size));
    258     } else {
    259       new_store = backing_store_;
    260     }
    261     uint8_t* src = backing_store_.start();
    262     uint16_t* dst = reinterpret_cast<uint16_t*>(new_store.start());
    263     for (int i = position_ - 1; i >= 0; i--) {
    264       dst[i] = src[i];
    265     }
    266     if (new_store.start() != backing_store_.start()) {
    267       backing_store_.Dispose();
    268       backing_store_ = new_store;
    269     }
    270     position_ = new_content_size;
    271     is_one_byte_ = false;
    272   }
    273 
    274   bool is_one_byte_;
    275   int position_;
    276   Vector<byte> backing_store_;
    277 
    278   DISALLOW_COPY_AND_ASSIGN(LiteralBuffer);
    279 };
    280 
    281 
    282 // ----------------------------------------------------------------------------
    283 // JavaScript Scanner.
    284 
    285 class Scanner {
    286  public:
    287   // Scoped helper for literal recording. Automatically drops the literal
    288   // if aborting the scanning before it's complete.
    289   class LiteralScope {
    290    public:
    291     explicit LiteralScope(Scanner* self) : scanner_(self), complete_(false) {
    292       scanner_->StartLiteral();
    293     }
    294      ~LiteralScope() {
    295        if (!complete_) scanner_->DropLiteral();
    296      }
    297     void Complete() {
    298       complete_ = true;
    299     }
    300 
    301    private:
    302     Scanner* scanner_;
    303     bool complete_;
    304   };
    305 
    306   // Scoped helper for a re-settable bookmark.
    307   class BookmarkScope {
    308    public:
    309     explicit BookmarkScope(Scanner* scanner) : scanner_(scanner) {
    310       DCHECK_NOT_NULL(scanner_);
    311     }
    312     ~BookmarkScope() { scanner_->DropBookmark(); }
    313 
    314     bool Set() { return scanner_->SetBookmark(); }
    315     void Reset() { scanner_->ResetToBookmark(); }
    316     bool HasBeenSet() { return scanner_->BookmarkHasBeenSet(); }
    317     bool HasBeenReset() { return scanner_->BookmarkHasBeenReset(); }
    318 
    319    private:
    320     Scanner* scanner_;
    321 
    322     DISALLOW_COPY_AND_ASSIGN(BookmarkScope);
    323   };
    324 
    325   // Representation of an interval of source positions.
    326   struct Location {
    327     Location(int b, int e) : beg_pos(b), end_pos(e) { }
    328     Location() : beg_pos(0), end_pos(0) { }
    329 
    330     bool IsValid() const {
    331       return beg_pos >= 0 && end_pos >= beg_pos;
    332     }
    333 
    334     static Location invalid() { return Location(-1, -1); }
    335 
    336     int beg_pos;
    337     int end_pos;
    338   };
    339 
    340   // -1 is outside of the range of any real source code.
    341   static const int kNoOctalLocation = -1;
    342 
    343   explicit Scanner(UnicodeCache* scanner_contants);
    344 
    345   void Initialize(Utf16CharacterStream* source);
    346 
    347   // Returns the next token and advances input.
    348   Token::Value Next();
    349   // Returns the token following peek()
    350   Token::Value PeekAhead();
    351   // Returns the current token again.
    352   Token::Value current_token() { return current_.token; }
    353   // Returns the location information for the current token
    354   // (the token last returned by Next()).
    355   Location location() const { return current_.location; }
    356 
    357   // Similar functions for the upcoming token.
    358 
    359   // One token look-ahead (past the token returned by Next()).
    360   Token::Value peek() const { return next_.token; }
    361 
    362   Location peek_location() const { return next_.location; }
    363 
    364   bool literal_contains_escapes() const {
    365     return LiteralContainsEscapes(current_);
    366   }
    367   bool next_literal_contains_escapes() const {
    368     return LiteralContainsEscapes(next_);
    369   }
    370   bool is_literal_contextual_keyword(Vector<const char> keyword) {
    371     DCHECK_NOT_NULL(current_.literal_chars);
    372     return current_.literal_chars->is_contextual_keyword(keyword);
    373   }
    374   bool is_next_contextual_keyword(Vector<const char> keyword) {
    375     DCHECK_NOT_NULL(next_.literal_chars);
    376     return next_.literal_chars->is_contextual_keyword(keyword);
    377   }
    378 
    379   const AstRawString* CurrentSymbol(AstValueFactory* ast_value_factory);
    380   const AstRawString* NextSymbol(AstValueFactory* ast_value_factory);
    381   const AstRawString* CurrentRawSymbol(AstValueFactory* ast_value_factory);
    382 
    383   double DoubleValue();
    384   bool ContainsDot();
    385   bool LiteralMatches(const char* data, int length, bool allow_escapes = true) {
    386     if (is_literal_one_byte() &&
    387         literal_length() == length &&
    388         (allow_escapes || !literal_contains_escapes())) {
    389       const char* token =
    390           reinterpret_cast<const char*>(literal_one_byte_string().start());
    391       return !strncmp(token, data, length);
    392     }
    393     return false;
    394   }
    395   inline bool UnescapedLiteralMatches(const char* data, int length) {
    396     return LiteralMatches(data, length, false);
    397   }
    398 
    399   void IsGetOrSet(bool* is_get, bool* is_set) {
    400     if (is_literal_one_byte() &&
    401         literal_length() == 3 &&
    402         !literal_contains_escapes()) {
    403       const char* token =
    404           reinterpret_cast<const char*>(literal_one_byte_string().start());
    405       *is_get = strncmp(token, "get", 3) == 0;
    406       *is_set = !*is_get && strncmp(token, "set", 3) == 0;
    407     }
    408   }
    409 
    410   int FindSymbol(DuplicateFinder* finder, int value);
    411 
    412   UnicodeCache* unicode_cache() { return unicode_cache_; }
    413 
    414   // Returns the location of the last seen octal literal.
    415   Location octal_position() const { return octal_pos_; }
    416   void clear_octal_position() { octal_pos_ = Location::invalid(); }
    417 
    418   // Returns the value of the last smi that was scanned.
    419   int smi_value() const { return current_.smi_value_; }
    420 
    421   // Seek forward to the given position.  This operation does not
    422   // work in general, for instance when there are pushed back
    423   // characters, but works for seeking forward until simple delimiter
    424   // tokens, which is what it is used for.
    425   void SeekForward(int pos);
    426 
    427   // Returns true if there was a line terminator before the peek'ed token,
    428   // possibly inside a multi-line comment.
    429   bool HasAnyLineTerminatorBeforeNext() const {
    430     return has_line_terminator_before_next_ ||
    431            has_multiline_comment_before_next_;
    432   }
    433 
    434   // Scans the input as a regular expression pattern, previous
    435   // character(s) must be /(=). Returns true if a pattern is scanned.
    436   bool ScanRegExpPattern(bool seen_equal);
    437   // Scans the input as regular expression flags. Returns the flags on success.
    438   Maybe<RegExp::Flags> ScanRegExpFlags();
    439 
    440   // Scans the input as a template literal
    441   Token::Value ScanTemplateStart();
    442   Token::Value ScanTemplateContinuation();
    443 
    444   const LiteralBuffer* source_url() const { return &source_url_; }
    445   const LiteralBuffer* source_mapping_url() const {
    446     return &source_mapping_url_;
    447   }
    448 
    449   bool IdentifierIsFutureStrictReserved(const AstRawString* string) const;
    450 
    451  private:
    452   // The current and look-ahead token.
    453   struct TokenDesc {
    454     Token::Value token;
    455     Location location;
    456     LiteralBuffer* literal_chars;
    457     LiteralBuffer* raw_literal_chars;
    458     int smi_value_;
    459   };
    460 
    461   static const int kCharacterLookaheadBufferSize = 1;
    462 
    463   // Scans octal escape sequence. Also accepts "\0" decimal escape sequence.
    464   template <bool capture_raw>
    465   uc32 ScanOctalEscape(uc32 c, int length);
    466 
    467   // Call this after setting source_ to the input.
    468   void Init() {
    469     // Set c0_ (one character ahead)
    470     STATIC_ASSERT(kCharacterLookaheadBufferSize == 1);
    471     Advance();
    472     // Initialize current_ to not refer to a literal.
    473     current_.literal_chars = NULL;
    474     current_.raw_literal_chars = NULL;
    475     next_next_.token = Token::UNINITIALIZED;
    476   }
    477 
    478   // Support BookmarkScope functionality.
    479   bool SetBookmark();
    480   void ResetToBookmark();
    481   bool BookmarkHasBeenSet();
    482   bool BookmarkHasBeenReset();
    483   void DropBookmark();
    484   static void CopyTokenDesc(TokenDesc* to, TokenDesc* from);
    485 
    486   // Literal buffer support
    487   inline void StartLiteral() {
    488     LiteralBuffer* free_buffer =
    489         (current_.literal_chars == &literal_buffer0_)
    490             ? &literal_buffer1_
    491             : (current_.literal_chars == &literal_buffer1_) ? &literal_buffer2_
    492                                                             : &literal_buffer0_;
    493     free_buffer->Reset();
    494     next_.literal_chars = free_buffer;
    495   }
    496 
    497   inline void StartRawLiteral() {
    498     LiteralBuffer* free_buffer =
    499         (current_.raw_literal_chars == &raw_literal_buffer0_)
    500             ? &raw_literal_buffer1_
    501             : (current_.raw_literal_chars == &raw_literal_buffer1_)
    502                   ? &raw_literal_buffer2_
    503                   : &raw_literal_buffer0_;
    504     free_buffer->Reset();
    505     next_.raw_literal_chars = free_buffer;
    506   }
    507 
    508   INLINE(void AddLiteralChar(uc32 c)) {
    509     DCHECK_NOT_NULL(next_.literal_chars);
    510     next_.literal_chars->AddChar(c);
    511   }
    512 
    513   INLINE(void AddRawLiteralChar(uc32 c)) {
    514     DCHECK_NOT_NULL(next_.raw_literal_chars);
    515     next_.raw_literal_chars->AddChar(c);
    516   }
    517 
    518   INLINE(void ReduceRawLiteralLength(int delta)) {
    519     DCHECK_NOT_NULL(next_.raw_literal_chars);
    520     next_.raw_literal_chars->ReduceLength(delta);
    521   }
    522 
    523   // Stops scanning of a literal and drop the collected characters,
    524   // e.g., due to an encountered error.
    525   inline void DropLiteral() {
    526     next_.literal_chars = NULL;
    527     next_.raw_literal_chars = NULL;
    528   }
    529 
    530   inline void AddLiteralCharAdvance() {
    531     AddLiteralChar(c0_);
    532     Advance();
    533   }
    534 
    535   // Low-level scanning support.
    536   template <bool capture_raw = false, bool check_surrogate = true>
    537   void Advance() {
    538     if (capture_raw) {
    539       AddRawLiteralChar(c0_);
    540     }
    541     c0_ = source_->Advance();
    542     if (check_surrogate) HandleLeadSurrogate();
    543   }
    544 
    545   void HandleLeadSurrogate() {
    546     if (unibrow::Utf16::IsLeadSurrogate(c0_)) {
    547       uc32 c1 = source_->Advance();
    548       if (!unibrow::Utf16::IsTrailSurrogate(c1)) {
    549         source_->PushBack(c1);
    550       } else {
    551         c0_ = unibrow::Utf16::CombineSurrogatePair(c0_, c1);
    552       }
    553     }
    554   }
    555 
    556   void PushBack(uc32 ch) {
    557     if (ch > static_cast<uc32>(unibrow::Utf16::kMaxNonSurrogateCharCode)) {
    558       source_->PushBack(unibrow::Utf16::TrailSurrogate(c0_));
    559       source_->PushBack(unibrow::Utf16::LeadSurrogate(c0_));
    560     } else {
    561       source_->PushBack(c0_);
    562     }
    563     c0_ = ch;
    564   }
    565 
    566   inline Token::Value Select(Token::Value tok) {
    567     Advance();
    568     return tok;
    569   }
    570 
    571   inline Token::Value Select(uc32 next, Token::Value then, Token::Value else_) {
    572     Advance();
    573     if (c0_ == next) {
    574       Advance();
    575       return then;
    576     } else {
    577       return else_;
    578     }
    579   }
    580 
    581   // Returns the literal string, if any, for the current token (the
    582   // token last returned by Next()). The string is 0-terminated.
    583   // Literal strings are collected for identifiers, strings, numbers as well
    584   // as for template literals. For template literals we also collect the raw
    585   // form.
    586   // These functions only give the correct result if the literal was scanned
    587   // when a LiteralScope object is alive.
    588   Vector<const uint8_t> literal_one_byte_string() {
    589     DCHECK_NOT_NULL(current_.literal_chars);
    590     return current_.literal_chars->one_byte_literal();
    591   }
    592   Vector<const uint16_t> literal_two_byte_string() {
    593     DCHECK_NOT_NULL(current_.literal_chars);
    594     return current_.literal_chars->two_byte_literal();
    595   }
    596   bool is_literal_one_byte() {
    597     DCHECK_NOT_NULL(current_.literal_chars);
    598     return current_.literal_chars->is_one_byte();
    599   }
    600   int literal_length() const {
    601     DCHECK_NOT_NULL(current_.literal_chars);
    602     return current_.literal_chars->length();
    603   }
    604   // Returns the literal string for the next token (the token that
    605   // would be returned if Next() were called).
    606   Vector<const uint8_t> next_literal_one_byte_string() {
    607     DCHECK_NOT_NULL(next_.literal_chars);
    608     return next_.literal_chars->one_byte_literal();
    609   }
    610   Vector<const uint16_t> next_literal_two_byte_string() {
    611     DCHECK_NOT_NULL(next_.literal_chars);
    612     return next_.literal_chars->two_byte_literal();
    613   }
    614   bool is_next_literal_one_byte() {
    615     DCHECK_NOT_NULL(next_.literal_chars);
    616     return next_.literal_chars->is_one_byte();
    617   }
    618   Vector<const uint8_t> raw_literal_one_byte_string() {
    619     DCHECK_NOT_NULL(current_.raw_literal_chars);
    620     return current_.raw_literal_chars->one_byte_literal();
    621   }
    622   Vector<const uint16_t> raw_literal_two_byte_string() {
    623     DCHECK_NOT_NULL(current_.raw_literal_chars);
    624     return current_.raw_literal_chars->two_byte_literal();
    625   }
    626   bool is_raw_literal_one_byte() {
    627     DCHECK_NOT_NULL(current_.raw_literal_chars);
    628     return current_.raw_literal_chars->is_one_byte();
    629   }
    630 
    631   template <bool capture_raw>
    632   uc32 ScanHexNumber(int expected_length);
    633   // Scan a number of any length but not bigger than max_value. For example, the
    634   // number can be 000000001, so it's very long in characters but its value is
    635   // small.
    636   template <bool capture_raw>
    637   uc32 ScanUnlimitedLengthHexNumber(int max_value);
    638 
    639   // Scans a single JavaScript token.
    640   void Scan();
    641 
    642   bool SkipWhiteSpace();
    643   Token::Value SkipSingleLineComment();
    644   Token::Value SkipSourceURLComment();
    645   void TryToParseSourceURLComment();
    646   Token::Value SkipMultiLineComment();
    647   // Scans a possible HTML comment -- begins with '<!'.
    648   Token::Value ScanHtmlComment();
    649 
    650   void ScanDecimalDigits();
    651   Token::Value ScanNumber(bool seen_period);
    652   Token::Value ScanIdentifierOrKeyword();
    653   Token::Value ScanIdentifierSuffix(LiteralScope* literal, bool escaped);
    654 
    655   Token::Value ScanString();
    656 
    657   // Scans an escape-sequence which is part of a string and adds the
    658   // decoded character to the current literal. Returns true if a pattern
    659   // is scanned.
    660   template <bool capture_raw, bool in_template_literal>
    661   bool ScanEscape();
    662 
    663   // Decodes a Unicode escape-sequence which is part of an identifier.
    664   // If the escape sequence cannot be decoded the result is kBadChar.
    665   uc32 ScanIdentifierUnicodeEscape();
    666   // Helper for the above functions.
    667   template <bool capture_raw>
    668   uc32 ScanUnicodeEscape();
    669 
    670   Token::Value ScanTemplateSpan();
    671 
    672   // Return the current source position.
    673   int source_pos() {
    674     return static_cast<int>(source_->pos()) - kCharacterLookaheadBufferSize;
    675   }
    676 
    677   static bool LiteralContainsEscapes(const TokenDesc& token) {
    678     Location location = token.location;
    679     int source_length = (location.end_pos - location.beg_pos);
    680     if (token.token == Token::STRING) {
    681       // Subtract delimiters.
    682       source_length -= 2;
    683     }
    684     return token.literal_chars->length() != source_length;
    685   }
    686 
    687   UnicodeCache* unicode_cache_;
    688 
    689   // Buffers collecting literal strings, numbers, etc.
    690   LiteralBuffer literal_buffer0_;
    691   LiteralBuffer literal_buffer1_;
    692   LiteralBuffer literal_buffer2_;
    693 
    694   // Values parsed from magic comments.
    695   LiteralBuffer source_url_;
    696   LiteralBuffer source_mapping_url_;
    697 
    698   // Buffer to store raw string values
    699   LiteralBuffer raw_literal_buffer0_;
    700   LiteralBuffer raw_literal_buffer1_;
    701   LiteralBuffer raw_literal_buffer2_;
    702 
    703   TokenDesc current_;    // desc for current token (as returned by Next())
    704   TokenDesc next_;       // desc for next token (one token look-ahead)
    705   TokenDesc next_next_;  // desc for the token after next (after PeakAhead())
    706 
    707   // Variables for Scanner::BookmarkScope and the *Bookmark implementation.
    708   // These variables contain the scanner state when a bookmark is set.
    709   //
    710   // We will use bookmark_c0_ as a 'control' variable, where:
    711   // - bookmark_c0_ >= 0: A bookmark has been set and this contains c0_.
    712   // - bookmark_c0_ == -1: No bookmark has been set.
    713   // - bookmark_c0_ == -2: The bookmark has been applied (ResetToBookmark).
    714   //
    715   // Which state is being bookmarked? The parser state is distributed over
    716   // several variables, roughly like this:
    717   //   ...    1234        +       5678 ..... [character stream]
    718   //       [current_] [next_] c0_ |      [scanner state]
    719   // So when the scanner is logically at the beginning of an expression
    720   // like "1234 + 4567", then:
    721   // - current_ contains "1234"
    722   // - next_ contains "+"
    723   // - c0_ contains ' ' (the space between "+" and "5678",
    724   // - the source_ character stream points to the beginning of "5678".
    725   // To be able to restore this state, we will keep copies of current_, next_,
    726   // and c0_; we'll ask the stream to bookmark itself, and we'll copy the
    727   // contents of current_'s and next_'s literal buffers to bookmark_*_literal_.
    728   static const uc32 kNoBookmark = -1;
    729   static const uc32 kBookmarkWasApplied = -2;
    730   uc32 bookmark_c0_;
    731   TokenDesc bookmark_current_;
    732   TokenDesc bookmark_next_;
    733   LiteralBuffer bookmark_current_literal_;
    734   LiteralBuffer bookmark_current_raw_literal_;
    735   LiteralBuffer bookmark_next_literal_;
    736   LiteralBuffer bookmark_next_raw_literal_;
    737 
    738   // Input stream. Must be initialized to an Utf16CharacterStream.
    739   Utf16CharacterStream* source_;
    740 
    741 
    742   // Start position of the octal literal last scanned.
    743   Location octal_pos_;
    744 
    745   // One Unicode character look-ahead; c0_ < 0 at the end of the input.
    746   uc32 c0_;
    747 
    748   // Whether there is a line terminator whitespace character after
    749   // the current token, and  before the next. Does not count newlines
    750   // inside multiline comments.
    751   bool has_line_terminator_before_next_;
    752   // Whether there is a multi-line comment that contains a
    753   // line-terminator after the current token, and before the next.
    754   bool has_multiline_comment_before_next_;
    755 };
    756 
    757 }  // namespace internal
    758 }  // namespace v8
    759 
    760 #endif  // V8_PARSING_SCANNER_H_
    761