scanner.cc revision a7e24c173cf37484693b9abb38e494fa7bd7baeb
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2008 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ast.h"
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "scanner.h"
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Character predicates
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockunibrow::Predicate<IdentifierStart, 128> Scanner::kIsIdentifierStart;
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockunibrow::Predicate<IdentifierPart, 128> Scanner::kIsIdentifierPart;
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockunibrow::Predicate<unibrow::LineTerminator, 128> Scanner::kIsLineTerminator;
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockunibrow::Predicate<unibrow::WhiteSpace, 128> Scanner::kIsWhiteSpace;
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockStaticResource<Scanner::Utf8Decoder> Scanner::utf8_decoder_;
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// UTF8Buffer
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockUTF8Buffer::UTF8Buffer() {
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kInitialCapacity = 1 * KB;
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  data_ = NewArray<char>(kInitialCapacity);
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  limit_ = ComputeLimit(data_, kInitialCapacity);
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Reset();
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(Capacity() == kInitialCapacity && pos() == 0);
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockUTF8Buffer::~UTF8Buffer() {
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DeleteArray(data_);
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid UTF8Buffer::AddCharSlow(uc32 c) {
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kCapacityGrowthLimit = 1 * MB;
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (cursor_ > limit_) {
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int old_capacity = Capacity();
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int old_position = pos();
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int new_capacity =
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Min(old_capacity * 2, old_capacity + kCapacityGrowthLimit);
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    char* new_data = NewArray<char>(new_capacity);
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    memcpy(new_data, data_, old_position);
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    DeleteArray(data_);
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    data_ = new_data;
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cursor_ = new_data + old_position;
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    limit_ = ComputeLimit(new_data, new_capacity);
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(Capacity() == new_capacity && pos() == old_position);
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (static_cast<unsigned>(c) <= unibrow::Utf8::kMaxOneByteChar) {
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *cursor_++ = c;  // Common case: 7-bit ASCII.
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cursor_ += unibrow::Utf8::Encode(cursor_, c);
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(pos() <= Capacity());
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// UTF16Buffer
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockUTF16Buffer::UTF16Buffer()
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : pos_(0), size_(0) { }
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<String> UTF16Buffer::SubString(int start, int end) {
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return internal::SubString(data_, start, end);
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// CharacterStreamUTF16Buffer
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCharacterStreamUTF16Buffer::CharacterStreamUTF16Buffer()
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : pushback_buffer_(0), last_(0), stream_(NULL) { }
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CharacterStreamUTF16Buffer::Initialize(Handle<String> data,
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            unibrow::CharacterStream* input) {
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  data_ = data;
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pos_ = 0;
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream_ = input;
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CharacterStreamUTF16Buffer::PushBack(uc32 ch) {
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pushback_buffer()->Add(last_);
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  last_ = ch;
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pos_--;
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockuc32 CharacterStreamUTF16Buffer::Advance() {
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // NOTE: It is of importance to Persian / Farsi resources that we do
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // *not* strip format control characters in the scanner; see
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //    https://bugzilla.mozilla.org/show_bug.cgi?id=274152
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // So, even though ECMA-262, section 7.1, page 11, dictates that we
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // must remove Unicode format-control characters, we do not. This is
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in line with how IE and SpiderMonkey handles it.
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!pushback_buffer()->is_empty()) {
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pos_++;
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return last_ = pushback_buffer()->RemoveLast();
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (stream_->has_more()) {
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pos_++;
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uc32 next = stream_->GetNext();
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return last_ = next;
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Note: currently the following increment is necessary to avoid a
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // test-parser problem!
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pos_++;
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return last_ = static_cast<uc32>(-1);
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CharacterStreamUTF16Buffer::SeekForward(int pos) {
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pos_ = pos;
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(pushback_buffer()->is_empty());
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream_->Seek(pos);
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// TwoByteStringUTF16Buffer
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTwoByteStringUTF16Buffer::TwoByteStringUTF16Buffer()
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : raw_data_(NULL) { }
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid TwoByteStringUTF16Buffer::Initialize(
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     Handle<ExternalTwoByteString> data) {
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!data.is_null());
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  data_ = data;
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pos_ = 0;
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  raw_data_ = data->resource()->data();
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  size_ = data->length();
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockuc32 TwoByteStringUTF16Buffer::Advance() {
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (pos_ < size_) {
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return raw_data_[pos_++];
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // note: currently the following increment is necessary to avoid a
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // test-parser problem!
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pos_++;
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return static_cast<uc32>(-1);
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid TwoByteStringUTF16Buffer::PushBack(uc32 ch) {
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pos_--;
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(pos_ >= Scanner::kCharacterLookaheadBufferSize);
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(raw_data_[pos_ - Scanner::kCharacterLookaheadBufferSize] == ch);
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid TwoByteStringUTF16Buffer::SeekForward(int pos) {
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pos_ = pos;
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Scanner
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockScanner::Scanner(bool pre) : stack_overflow_(false), is_pre_parsing_(pre) {
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Token::Initialize();
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scanner::Init(Handle<String> source, unibrow::CharacterStream* stream,
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int position) {
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Initialize the source buffer.
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!source.is_null() && StringShape(*source).IsExternalTwoByte()) {
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    two_byte_string_buffer_.Initialize(
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Handle<ExternalTwoByteString>::cast(source));
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    source_ = &two_byte_string_buffer_;
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    char_stream_buffer_.Initialize(source, stream);
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    source_ = &char_stream_buffer_;
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  position_ = position;
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reset literals buffer
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  literals_.Reset();
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set c0_ (one character ahead)
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kCharacterLookaheadBufferSize == 1);
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Skip initial whitespace allowing HTML comment ends just like
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // after a newline and scan first token.
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  has_line_terminator_before_next_ = true;
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SkipWhiteSpace();
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Scan();
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<String> Scanner::SubString(int start, int end) {
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return source_->SubString(start - position_, end - position_);
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockToken::Value Scanner::Next() {
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // BUG 1215673: Find a thread safe way to set a stack limit in
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // pre-parse mode. Otherwise, we cannot safely pre-parse from other
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // threads.
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  current_ = next_;
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for stack-overflow before returning any tokens.
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackLimitCheck check;
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (check.HasOverflowed()) {
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    stack_overflow_ = true;
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    next_.token = Token::ILLEGAL;
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Scan();
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return current_.token;
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scanner::StartLiteral() {
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_.literal_pos = literals_.pos();
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scanner::AddChar(uc32 c) {
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  literals_.AddChar(c);
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scanner::TerminateLiteral() {
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_.literal_end = literals_.pos();
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AddChar(0);
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scanner::AddCharAdvance() {
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AddChar(c0_);
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline bool IsByteOrderMark(uc32 c) {
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The Unicode value U+FFFE is guaranteed never to be assigned as a
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Unicode character; this implies that in a Unicode context the
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 0xFF, 0xFE byte pattern can only be interpreted as the U+FEFF
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // character expressed in little-endian byte order (since it could
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // not be a U+FFFE character expressed in big-endian byte
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // order). Nevertheless, we check for it to be compatible with
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Spidermonkey.
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return c == 0xFEFF || c == 0xFFFE;
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Scanner::SkipWhiteSpace() {
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int start_position = source_pos();
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (true) {
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // We treat byte-order marks (BOMs) as whitespace for better
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // compatibility with Spidermonkey and other JavaScript engines.
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    while (kIsWhiteSpace.get(c0_) || IsByteOrderMark(c0_)) {
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // IsWhiteSpace() includes line terminators!
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (kIsLineTerminator.get(c0_)) {
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Ignore line terminators, but remember them. This is necessary
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // for automatic semicolon insertion.
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        has_line_terminator_before_next_ = true;
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If there is an HTML comment end '-->' at the beginning of a
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // line (with only whitespace in front of it), we treat the rest
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // of the line as a comment. This is in line with the way
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // SpiderMonkey handles it.
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (c0_ == '-' && has_line_terminator_before_next_) {
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (c0_ == '-') {
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (c0_ == '>') {
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // Treat the rest of the line as a comment.
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          SkipSingleLineComment();
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // Continue skipping white space after the comment.
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          continue;
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        PushBack('-');  // undo Advance()
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PushBack('-');  // undo Advance()
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Return whether or not we skipped any characters.
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return source_pos() != start_position;
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockToken::Value Scanner::SkipSingleLineComment() {
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The line terminator at the end of the line is not considered
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to be part of the single-line comment; it is recognized
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // separately by the lexical grammar and becomes part of the
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // stream of input elements for the syntactic grammar (see
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ECMA-262, section 7.4, page 12).
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (c0_ >= 0 && !kIsLineTerminator.get(c0_)) {
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Token::WHITESPACE;
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockToken::Value Scanner::SkipMultiLineComment() {
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(c0_ == '*');
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (c0_ >= 0) {
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    char ch = c0_;
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If we have reached the end of the multi-line comment, we
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // consume the '/' and insert a whitespace. This way all
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // multi-line comments are treated as whitespace - even the ones
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // containing line terminators. This contradicts ECMA-262, section
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // 7.4, page 12, that says that multi-line comments containing
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // line terminators should be treated as a line terminator, but it
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // matches the behaviour of SpiderMonkey and KJS.
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (ch == '*' && c0_ == '/') {
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      c0_ = ' ';
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return Token::WHITESPACE;
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Unterminated multi-line comment.
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Token::ILLEGAL;
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockToken::Value Scanner::ScanHtmlComment() {
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for <!-- comments.
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(c0_ == '!');
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (c0_ == '-') {
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (c0_ == '-') return SkipSingleLineComment();
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PushBack('-');  // undo Advance()
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PushBack('!');  // undo Advance()
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(c0_ == '!');
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Token::LT;
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scanner::Scan() {
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Token::Value token;
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  has_line_terminator_before_next_ = false;
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  do {
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Remember the position of the next token
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    next_.location.beg_pos = source_pos();
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    switch (c0_) {
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case ' ':
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '\t':
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Token::WHITESPACE;
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '\n':
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        has_line_terminator_before_next_ = true;
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Token::WHITESPACE;
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '"': case '\'':
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = ScanString();
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '<':
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // < <= << <<= <!--
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (c0_ == '=') {
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select(Token::LTE);
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (c0_ == '<') {
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select('=', Token::ASSIGN_SHL, Token::SHL);
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (c0_ == '!') {
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = ScanHtmlComment();
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::LT;
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '>':
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // > >= >> >>= >>> >>>=
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (c0_ == '=') {
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select(Token::GTE);
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (c0_ == '>') {
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // >> >>= >>> >>>=
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Advance();
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (c0_ == '=') {
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            token = Select(Token::ASSIGN_SAR);
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else if (c0_ == '>') {
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            token = Select('=', Token::ASSIGN_SHR, Token::SHR);
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            token = Token::SAR;
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::GT;
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '=':
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // = == ===
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (c0_ == '=') {
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select('=', Token::EQ_STRICT, Token::EQ);
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::ASSIGN;
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '!':
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // ! != !==
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (c0_ == '=') {
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select('=', Token::NE_STRICT, Token::NE);
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::NOT;
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '+':
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // + ++ +=
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (c0_ == '+') {
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select(Token::INC);
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (c0_ == '=') {
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select(Token::ASSIGN_ADD);
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::ADD;
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '-':
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // - -- --> -=
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (c0_ == '-') {
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Advance();
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (c0_ == '>' && has_line_terminator_before_next_) {
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            // For compatibility with SpiderMonkey, we skip lines that
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            // start with an HTML comment end '-->'.
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            token = SkipSingleLineComment();
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            token = Token::DEC;
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (c0_ == '=') {
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select(Token::ASSIGN_SUB);
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::SUB;
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '*':
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // * *=
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select('=', Token::ASSIGN_MUL, Token::MUL);
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '%':
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // % %=
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select('=', Token::ASSIGN_MOD, Token::MOD);
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '/':
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // /  // /* /=
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (c0_ == '/') {
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = SkipSingleLineComment();
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (c0_ == '*') {
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = SkipMultiLineComment();
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (c0_ == '=') {
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select(Token::ASSIGN_DIV);
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::DIV;
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '&':
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // & && &=
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (c0_ == '&') {
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select(Token::AND);
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (c0_ == '=') {
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select(Token::ASSIGN_BIT_AND);
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::BIT_AND;
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '|':
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // | || |=
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (c0_ == '|') {
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select(Token::OR);
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (c0_ == '=') {
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select(Token::ASSIGN_BIT_OR);
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::BIT_OR;
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '^':
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // ^ ^=
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select('=', Token::ASSIGN_BIT_XOR, Token::BIT_XOR);
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '.':
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // . Number
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (IsDecimalDigit(c0_)) {
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = ScanNumber(true);
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::PERIOD;
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case ':':
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select(Token::COLON);
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case ';':
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select(Token::SEMICOLON);
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case ',':
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select(Token::COMMA);
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '(':
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select(Token::LPAREN);
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case ')':
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select(Token::RPAREN);
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '[':
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select(Token::LBRACK);
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case ']':
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select(Token::RBRACK);
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '{':
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select(Token::LBRACE);
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '}':
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select(Token::RBRACE);
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '?':
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select(Token::CONDITIONAL);
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '~':
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select(Token::BIT_NOT);
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      default:
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (kIsIdentifierStart.get(c0_)) {
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = ScanIdentifier();
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (IsDecimalDigit(c0_)) {
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = ScanNumber(false);
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (SkipWhiteSpace()) {
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::WHITESPACE;
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (c0_ < 0) {
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::EOS;
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select(Token::ILLEGAL);
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Continue scanning for tokens as long as we're just skipping
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // whitespace.
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } while (token == Token::WHITESPACE);
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_.location.end_pos = source_pos();
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_.token = token;
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scanner::SeekForward(int pos) {
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  source_->SeekForward(pos - 1);
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Scan();
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockuc32 Scanner::ScanHexEscape(uc32 c, int length) {
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(length <= 4);  // prevent overflow
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uc32 digits[4];
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uc32 x = 0;
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < length; i++) {
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    digits[i] = c0_;
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int d = HexValue(c0_);
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (d < 0) {
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // According to ECMA-262, 3rd, 7.8.4, page 18, these hex escapes
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // should be illegal, but other JS VMs just return the
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // non-escaped version of the original character.
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Push back digits read, except the last one (in c0_).
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      for (int j = i-1; j >= 0; j--) {
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        PushBack(digits[j]);
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Notice: No handling of error - treat it as "\u"->"u".
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return c;
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    x = x * 16 + d;
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return x;
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Octal escapes of the forms '\0xx' and '\xxx' are not a part of
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ECMA-262. Other JS VMs support them.
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockuc32 Scanner::ScanOctalEscape(uc32 c, int length) {
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uc32 x = c - '0';
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < length; i++) {
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int d = c0_ - '0';
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (d < 0 || d > 7) break;
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int nx = x * 8 + d;
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (nx >= 256) break;
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    x = nx;
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return x;
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scanner::ScanEscape() {
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uc32 c = c0_;
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Skip escaped newlines.
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (kIsLineTerminator.get(c)) {
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Allow CR+LF newlines in multiline string literals.
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance();
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Allow LF+CR newlines in multiline string literals.
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (IsLineFeed(c) && IsCarriageReturn(c0_)) Advance();
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (c) {
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '\'':  // fall through
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '"' :  // fall through
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '\\': break;
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'b' : c = '\b'; break;
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'f' : c = '\f'; break;
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'n' : c = '\n'; break;
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'r' : c = '\r'; break;
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 't' : c = '\t'; break;
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'u' : c = ScanHexEscape(c, 4); break;
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'v' : c = '\v'; break;
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'x' : c = ScanHexEscape(c, 2); break;
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '0' :  // fall through
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '1' :  // fall through
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '2' :  // fall through
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '3' :  // fall through
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '4' :  // fall through
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '5' :  // fall through
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '6' :  // fall through
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '7' : c = ScanOctalEscape(c, 2); break;
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // According to ECMA-262, 3rd, 7.8.4 (p 18ff) these
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // should be illegal, but they are commonly handled
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // as non-escaped characters by JS VMs.
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AddChar(c);
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockToken::Value Scanner::ScanString() {
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uc32 quote = c0_;
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();  // consume quote
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StartLiteral();
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (c0_ != quote && c0_ >= 0 && !kIsLineTerminator.get(c0_)) {
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uc32 c = c0_;
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (c == '\\') {
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (c0_ < 0) return Token::ILLEGAL;
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ScanEscape();
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AddChar(c);
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (c0_ != quote) {
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return Token::ILLEGAL;
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TerminateLiteral();
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();  // consume quote
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Token::STRING;
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockToken::Value Scanner::Select(Token::Value tok) {
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return tok;
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockToken::Value Scanner::Select(uc32 next, Token::Value then, Token::Value else_) {
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (c0_ == next) {
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return then;
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return else_;
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns true if any decimal digits were scanned, returns false otherwise.
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scanner::ScanDecimalDigits() {
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (IsDecimalDigit(c0_))
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AddCharAdvance();
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockToken::Value Scanner::ScanNumber(bool seen_period) {
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(IsDecimalDigit(c0_));  // the first digit of the number or the fraction
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  enum { DECIMAL, HEX, OCTAL } kind = DECIMAL;
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StartLiteral();
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (seen_period) {
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // we have already seen a decimal point of the float
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AddChar('.');
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ScanDecimalDigits();  // we know we have at least one digit
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // if the first character is '0' we must check for octals and hex
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (c0_ == '0') {
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AddCharAdvance();
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // either 0, 0exxx, 0Exxx, 0.xxx, an octal number, or a hex number
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (c0_ == 'x' || c0_ == 'X') {
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // hex number
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        kind = HEX;
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AddCharAdvance();
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (!IsHexDigit(c0_))
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // we must have at least one hex digit after 'x'/'X'
790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return Token::ILLEGAL;
791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        while (IsHexDigit(c0_))
792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AddCharAdvance();
793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if ('0' <= c0_ && c0_ <= '7') {
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // (possible) octal number
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        kind = OCTAL;
797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        while (true) {
798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (c0_ == '8' || c0_ == '9') {
799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            kind = DECIMAL;
800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (c0_  < '0' || '7'  < c0_) break;
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AddCharAdvance();
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Parse decimal digits and allow trailing fractional part.
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (kind == DECIMAL) {
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ScanDecimalDigits();  // optional
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (c0_ == '.') {
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AddCharAdvance();
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ScanDecimalDigits();  // optional
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scan exponent, if any
819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (c0_ == 'e' || c0_ == 'E') {
820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(kind != HEX);  // 'e'/'E' must be scanned as part of the hex number
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (kind == OCTAL) return Token::ILLEGAL;  // no exponent for octals allowed
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // scan exponent
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AddCharAdvance();
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (c0_ == '+' || c0_ == '-')
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AddCharAdvance();
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!IsDecimalDigit(c0_))
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // we must have at least one decimal digit after 'e'/'E'
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return Token::ILLEGAL;
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ScanDecimalDigits();
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TerminateLiteral();
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The source character immediately following a numeric literal must
834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // not be an identifier start or a decimal digit; see ECMA-262
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // section 7.8.3, page 17 (note that we read only one decimal digit
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // if the value is 0).
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (IsDecimalDigit(c0_) || kIsIdentifierStart.get(c0_))
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return Token::ILLEGAL;
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Token::NUMBER;
841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockuc32 Scanner::ScanIdentifierUnicodeEscape() {
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (c0_ != 'u') return unibrow::Utf8::kBadChar;
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uc32 c = ScanHexEscape('u', 4);
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We do not allow a unicode escape sequence to start another
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // unicode escape sequence.
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (c == '\\') return unibrow::Utf8::kBadChar;
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return c;
853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockToken::Value Scanner::ScanIdentifier() {
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kIsIdentifierStart.get(c0_));
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool has_escapes = false;
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StartLiteral();
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Scan identifier start character.
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (c0_ == '\\') {
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    has_escapes = true;
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uc32 c = ScanIdentifierUnicodeEscape();
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Only allow legal identifier start characters.
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!kIsIdentifierStart.get(c)) return Token::ILLEGAL;
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AddChar(c);
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AddChar(c0_);
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Scan the rest of the identifier characters.
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (kIsIdentifierPart.get(c0_)) {
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (c0_ == '\\') {
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      has_escapes = true;
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      uc32 c = ScanIdentifierUnicodeEscape();
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Only allow legal identifier part characters.
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (!kIsIdentifierPart.get(c)) return Token::ILLEGAL;
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AddChar(c);
881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AddChar(c0_);
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TerminateLiteral();
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We don't have any 1-letter keywords (this is probably a common case).
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((next_.literal_end - next_.literal_pos) == 1) {
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return Token::IDENTIFIER;
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the identifier contains unicode escapes, it must not be
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // resolved to a keyword.
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (has_escapes) {
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return Token::IDENTIFIER;
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Token::Lookup(&literals_.data()[next_.literal_pos]);
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Scanner::IsIdentifier(unibrow::CharacterStream* buffer) {
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Checks whether the buffer contains an identifier (no escape).
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!buffer->has_more()) return false;
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!kIsIdentifierStart.get(buffer->GetNext())) return false;
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (buffer->has_more()) {
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!kIsIdentifierPart.get(buffer->GetNext())) return false;
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Scanner::ScanRegExpPattern(bool seen_equal) {
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Scan: ('/' | '/=') RegularExpressionBody '/' RegularExpressionFlags
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool in_character_class = false;
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Previous token is either '/' or '/=', in the second case, the
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // pattern starts at =.
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_.location.beg_pos = source_pos() - (seen_equal ? 2 : 1);
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_.location.end_pos = source_pos() - (seen_equal ? 1 : 0);
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Scan regular expression body: According to ECMA-262, 3rd, 7.8.5,
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the scanner should pass uninterpreted bodies to the RegExp
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // constructor.
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StartLiteral();
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (seen_equal)
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AddChar('=');
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (c0_ != '/' || in_character_class) {
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (kIsLineTerminator.get(c0_) || c0_ < 0)
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return false;
934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (c0_ == '\\') {  // escaped character
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AddCharAdvance();
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (kIsLineTerminator.get(c0_) || c0_ < 0)
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return false;
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AddCharAdvance();
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {  // unescaped character
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (c0_ == '[')
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        in_character_class = true;
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (c0_ == ']')
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        in_character_class = false;
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AddCharAdvance();
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();  // consume '/'
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TerminateLiteral();
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Scanner::ScanRegExpFlags() {
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Scan regular expression flags.
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StartLiteral();
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (kIsIdentifierPart.get(c0_)) {
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (c0_ == '\\') {
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      uc32 c = ScanIdentifierUnicodeEscape();
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (c != static_cast<uc32>(unibrow::Utf8::kBadChar)) {
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // We allow any escaped character, unlike the restriction on
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // IdentifierPart when it is used to build an IdentifierName.
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AddChar(c);
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        continue;
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AddCharAdvance();
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TerminateLiteral();
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_.location.end_pos = source_pos() - 1;
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
976