scanner.cc revision 80d68eab642096c1a48b6474d6ec33064b0ad1f5
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"
316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "handles.h"
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "scanner.h"
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Character predicates
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockunibrow::Predicate<IdentifierStart, 128> Scanner::kIsIdentifierStart;
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockunibrow::Predicate<IdentifierPart, 128> Scanner::kIsIdentifierPart;
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockunibrow::Predicate<unibrow::LineTerminator, 128> Scanner::kIsLineTerminator;
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockunibrow::Predicate<unibrow::WhiteSpace, 128> Scanner::kIsWhiteSpace;
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockStaticResource<Scanner::Utf8Decoder> Scanner::utf8_decoder_;
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// UTF8Buffer
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian MonsenUTF8Buffer::UTF8Buffer() : buffer_(kInitialCapacity) { }
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian MonsenUTF8Buffer::~UTF8Buffer() {}
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid UTF8Buffer::AddCharSlow(uc32 c) {
6080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(static_cast<unsigned>(c) > unibrow::Utf8::kMaxOneByteChar);
6180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int length = unibrow::Utf8::Length(c);
6280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Vector<char> block = buffer_.AddBlock(length, '\0');
6380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef DEBUG
6480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int written_length = unibrow::Utf8::Encode(block.start(), c);
6580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CHECK_EQ(length, written_length);
6680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#else
6780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  unibrow::Utf8::Encode(block.start(), c);
6880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#endif
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// UTF16Buffer
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockUTF16Buffer::UTF16Buffer()
776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    : pos_(0), end_(Scanner::kNoEndPosition) { }
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// CharacterStreamUTF16Buffer
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCharacterStreamUTF16Buffer::CharacterStreamUTF16Buffer()
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : pushback_buffer_(0), last_(0), stream_(NULL) { }
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CharacterStreamUTF16Buffer::Initialize(Handle<String> data,
866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                            unibrow::CharacterStream* input,
876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                            int start_position,
886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                            int end_position) {
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream_ = input;
906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (start_position > 0) {
916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SeekForward(start_position);
926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  end_ = end_position != Scanner::kNoEndPosition ? end_position : kMaxInt;
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CharacterStreamUTF16Buffer::PushBack(uc32 ch) {
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pushback_buffer()->Add(last_);
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  last_ = ch;
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pos_--;
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockuc32 CharacterStreamUTF16Buffer::Advance() {
1056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(end_ != Scanner::kNoEndPosition);
1066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(end_ >= 0);
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // NOTE: It is of importance to Persian / Farsi resources that we do
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // *not* strip format control characters in the scanner; see
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //    https://bugzilla.mozilla.org/show_bug.cgi?id=274152
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // So, even though ECMA-262, section 7.1, page 11, dictates that we
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // must remove Unicode format-control characters, we do not. This is
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in line with how IE and SpiderMonkey handles it.
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!pushback_buffer()->is_empty()) {
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pos_++;
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return last_ = pushback_buffer()->RemoveLast();
1186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else if (stream_->has_more() && pos_ < end_) {
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pos_++;
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uc32 next = stream_->GetNext();
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return last_ = next;
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Note: currently the following increment is necessary to avoid a
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // test-parser problem!
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pos_++;
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return last_ = static_cast<uc32>(-1);
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CharacterStreamUTF16Buffer::SeekForward(int pos) {
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pos_ = pos;
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(pushback_buffer()->is_empty());
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream_->Seek(pos);
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// ExternalStringUTF16Buffer
1396ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate <typename StringType, typename CharType>
1406ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockExternalStringUTF16Buffer<StringType, CharType>::ExternalStringUTF16Buffer()
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : raw_data_(NULL) { }
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1446ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate <typename StringType, typename CharType>
1456ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid ExternalStringUTF16Buffer<StringType, CharType>::Initialize(
1466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block     Handle<StringType> data,
1476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block     int start_position,
1486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block     int end_position) {
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!data.is_null());
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  raw_data_ = data->resource()->data();
1516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(end_position <= data->length());
1536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (start_position > 0) {
1546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SeekForward(start_position);
1556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  end_ =
1576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      end_position != Scanner::kNoEndPosition ? end_position : data->length();
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1616ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate <typename StringType, typename CharType>
1626ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockuc32 ExternalStringUTF16Buffer<StringType, CharType>::Advance() {
1636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (pos_ < end_) {
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return raw_data_[pos_++];
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // note: currently the following increment is necessary to avoid a
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // test-parser problem!
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pos_++;
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return static_cast<uc32>(-1);
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1746ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate <typename StringType, typename CharType>
1756ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid ExternalStringUTF16Buffer<StringType, CharType>::PushBack(uc32 ch) {
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pos_--;
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(pos_ >= Scanner::kCharacterLookaheadBufferSize);
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(raw_data_[pos_ - Scanner::kCharacterLookaheadBufferSize] == ch);
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1826ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate <typename StringType, typename CharType>
1836ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid ExternalStringUTF16Buffer<StringType, CharType>::SeekForward(int pos) {
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pos_ = pos;
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Keyword Matcher
1909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
191d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockKeywordMatcher::FirstState KeywordMatcher::first_states_[] = {
192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { "break",  KEYWORD_PREFIX, Token::BREAK },
193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { NULL,     C,              Token::ILLEGAL },
194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { NULL,     D,              Token::ILLEGAL },
195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { "else",   KEYWORD_PREFIX, Token::ELSE },
196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { NULL,     F,              Token::ILLEGAL },
197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { NULL,     UNMATCHABLE,    Token::ILLEGAL },
198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { NULL,     UNMATCHABLE,    Token::ILLEGAL },
199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { NULL,     I,              Token::ILLEGAL },
200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { NULL,     UNMATCHABLE,    Token::ILLEGAL },
201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { NULL,     UNMATCHABLE,    Token::ILLEGAL },
202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { NULL,     UNMATCHABLE,    Token::ILLEGAL },
203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { NULL,     UNMATCHABLE,    Token::ILLEGAL },
204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { NULL,     N,              Token::ILLEGAL },
205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { NULL,     UNMATCHABLE,    Token::ILLEGAL },
206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { NULL,     UNMATCHABLE,    Token::ILLEGAL },
207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { NULL,     UNMATCHABLE,    Token::ILLEGAL },
208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { "return", KEYWORD_PREFIX, Token::RETURN },
209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { "switch", KEYWORD_PREFIX, Token::SWITCH },
210d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { NULL,     T,              Token::ILLEGAL },
211d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { NULL,     UNMATCHABLE,    Token::ILLEGAL },
212d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { NULL,     V,              Token::ILLEGAL },
213d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  { NULL,     W,              Token::ILLEGAL }
214d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block};
215d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
216d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid KeywordMatcher::Step(uc32 input) {
218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (state_) {
219d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case INITIAL: {
220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // matching the first character is the only state with significant fanout.
221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Match only lower-case letters in range 'b'..'w'.
222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      unsigned int offset = input - kFirstCharRangeMin;
223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (offset < kFirstCharRangeLength) {
224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        state_ = first_states_[offset].state;
225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (state_ == KEYWORD_PREFIX) {
226d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          keyword_ = first_states_[offset].keyword;
227d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          counter_ = 1;
228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          keyword_token_ = first_states_[offset].token;
229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        return;
231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case KEYWORD_PREFIX:
235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (keyword_[counter_] == input) {
236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        ASSERT_NE(input, '\0');
237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        counter_++;
238d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (keyword_[counter_] == '\0') {
239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          state_ = KEYWORD_MATCHED;
240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          token_ = keyword_token_;
241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        return;
243d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case KEYWORD_MATCHED:
246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      token_ = Token::IDENTIFIER;
247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case C:
249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchState(input, 'a', CA)) return;
250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchState(input, 'o', CO)) return;
251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case CA:
253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "case", 2, Token::CASE)) return;
254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "catch", 2, Token::CATCH)) return;
255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case CO:
257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchState(input, 'n', CON)) return;
258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case CON:
260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "const", 3, Token::CONST)) return;
261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "continue", 3, Token::CONTINUE)) return;
262d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case D:
264d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchState(input, 'e', DE)) return;
265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeyword(input, 'o', KEYWORD_MATCHED, Token::DO)) return;
266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
267d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case DE:
268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "debugger", 2, Token::DEBUGGER)) return;
269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "default", 2, Token::DEFAULT)) return;
270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "delete", 2, Token::DELETE)) return;
271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case F:
273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "false", 1, Token::FALSE_LITERAL)) return;
274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "finally", 1, Token::FINALLY)) return;
275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "for", 1, Token::FOR)) return;
276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "function", 1, Token::FUNCTION)) return;
277d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case I:
279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeyword(input, 'f', KEYWORD_MATCHED, Token::IF)) return;
280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeyword(input, 'n', IN, Token::IN)) return;
281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case IN:
283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      token_ = Token::IDENTIFIER;
284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "instanceof", 2, Token::INSTANCEOF)) {
285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        return;
286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case N:
289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "native", 1, Token::NATIVE)) return;
290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "new", 1, Token::NEW)) return;
291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "null", 1, Token::NULL_LITERAL)) return;
292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case T:
294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchState(input, 'h', TH)) return;
295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchState(input, 'r', TR)) return;
296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "typeof", 1, Token::TYPEOF)) return;
297d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
298d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case TH:
299d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "this", 2, Token::THIS)) return;
300d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "throw", 2, Token::THROW)) return;
301d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
302d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case TR:
303d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "true", 2, Token::TRUE_LITERAL)) return;
304d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeyword(input, 'y', KEYWORD_MATCHED, Token::TRY)) return;
305d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
306d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case V:
307d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "var", 1, Token::VAR)) return;
308d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "void", 1, Token::VOID)) return;
309d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case W:
311d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "while", 1, Token::WHILE)) return;
312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (MatchKeywordStart(input, "with", 1, Token::WITH)) return;
313d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
314d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default:
315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
316d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
317d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // On fallthrough, it's a failure.
318d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  state_ = UNMATCHABLE;
319d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
320d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
321d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
32280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
32380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// ----------------------------------------------------------------------------
32480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// Scanner::LiteralScope
32580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
32680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian MonsenScanner::LiteralScope::LiteralScope(Scanner* self)
32780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    : scanner_(self), complete_(false) {
32880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  self->StartLiteral();
32980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
33080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
33180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
33280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian MonsenScanner::LiteralScope::~LiteralScope() {
33380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (!complete_) scanner_->DropLiteral();
33480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
33580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
33680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
33780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid Scanner::LiteralScope::Complete() {
33880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  scanner_->TerminateLiteral();
33980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  complete_ = true;
34080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
34180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
342d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// ----------------------------------------------------------------------------
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Scanner
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3454515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeScanner::Scanner(ParserMode pre)
3469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    : is_pre_parsing_(pre == PREPARSE), stack_overflow_(false) { }
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3496ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Scanner::Initialize(Handle<String> source,
3506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                         ParserLanguage language) {
3513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Init(source, NULL, 0, source->length(), language);
3526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
3536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3556ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Scanner::Initialize(Handle<String> source,
3566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                         unibrow::CharacterStream* stream,
3576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                         ParserLanguage language) {
3586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Init(source, stream, 0, kNoEndPosition, language);
3596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
3606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3626ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Scanner::Initialize(Handle<String> source,
3636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                         int start_position,
3646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                         int end_position,
3656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                         ParserLanguage language) {
3663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Init(source, NULL, start_position, end_position, language);
3676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
3686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid Scanner::Init(Handle<String> source,
3714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                   unibrow::CharacterStream* stream,
3726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                   int start_position,
3736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                   int end_position,
3744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                   ParserLanguage language) {
3753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Either initialize the scanner from a character stream or from a
3763bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // string.
3773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(source.is_null() || stream == NULL);
3783bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Initialize the source buffer.
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!source.is_null() && StringShape(*source).IsExternalTwoByte()) {
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    two_byte_string_buffer_.Initialize(
3826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Handle<ExternalTwoByteString>::cast(source),
3836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        start_position,
3846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        end_position);
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    source_ = &two_byte_string_buffer_;
3866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else if (!source.is_null() && StringShape(*source).IsExternalAscii()) {
3876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ascii_string_buffer_.Initialize(
3886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Handle<ExternalAsciiString>::cast(source),
3896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        start_position,
3906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        end_position);
3916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    source_ = &ascii_string_buffer_;
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
3933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    if (!source.is_null()) {
3943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      safe_string_input_buffer_.Reset(source.location());
3953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      stream = &safe_string_input_buffer_;
3963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    }
3976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    char_stream_buffer_.Initialize(source,
3986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                   stream,
3996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                   start_position,
4006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                   end_position);
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    source_ = &char_stream_buffer_;
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  is_parsing_json_ = (language == JSON);
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set c0_ (one character ahead)
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kCharacterLookaheadBufferSize == 1);
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
40980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Initialize current_ to not refer to a literal.
41080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  current_.literal_chars = Vector<const char>();
41180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Reset literal buffer.
41280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  literal_buffer_.Reset();
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Skip initial whitespace allowing HTML comment ends just like
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // after a newline and scan first token.
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  has_line_terminator_before_next_ = true;
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SkipWhiteSpace();
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Scan();
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockToken::Value Scanner::Next() {
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // BUG 1215673: Find a thread safe way to set a stack limit in
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // pre-parse mode. Otherwise, we cannot safely pre-parse from other
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // threads.
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  current_ = next_;
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for stack-overflow before returning any tokens.
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackLimitCheck check;
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (check.HasOverflowed()) {
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    stack_overflow_ = true;
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    next_.token = Token::ILLEGAL;
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Scan();
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return current_.token;
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scanner::StartLiteral() {
44080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  literal_buffer_.StartLiteral();
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scanner::AddChar(uc32 c) {
44580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  literal_buffer_.AddChar(c);
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scanner::TerminateLiteral() {
45080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  next_.literal_chars = literal_buffer_.EndLiteral();
45180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
45280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
45380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
45480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid Scanner::DropLiteral() {
45580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  literal_buffer_.DropLiteral();
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scanner::AddCharAdvance() {
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AddChar(c0_);
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline bool IsByteOrderMark(uc32 c) {
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The Unicode value U+FFFE is guaranteed never to be assigned as a
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Unicode character; this implies that in a Unicode context the
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 0xFF, 0xFE byte pattern can only be interpreted as the U+FEFF
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // character expressed in little-endian byte order (since it could
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // not be a U+FFFE character expressed in big-endian byte
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // order). Nevertheless, we check for it to be compatible with
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Spidermonkey.
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return c == 0xFEFF || c == 0xFFFE;
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkebool Scanner::SkipJsonWhiteSpace() {
4784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  int start_position = source_pos();
4794515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // JSON WhiteSpace is tab, carrige-return, newline and space.
4804515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  while (c0_ == ' ' || c0_ == '\n' || c0_ == '\r' || c0_ == '\t') {
4814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    Advance();
4824515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
4834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  return source_pos() != start_position;
4844515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
4854515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
4864515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
4874515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkebool Scanner::SkipJavaScriptWhiteSpace() {
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int start_position = source_pos();
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (true) {
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // We treat byte-order marks (BOMs) as whitespace for better
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // compatibility with Spidermonkey and other JavaScript engines.
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    while (kIsWhiteSpace.get(c0_) || IsByteOrderMark(c0_)) {
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // IsWhiteSpace() includes line terminators!
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (kIsLineTerminator.get(c0_)) {
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Ignore line terminators, but remember them. This is necessary
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // for automatic semicolon insertion.
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        has_line_terminator_before_next_ = true;
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If there is an HTML comment end '-->' at the beginning of a
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // line (with only whitespace in front of it), we treat the rest
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // of the line as a comment. This is in line with the way
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // SpiderMonkey handles it.
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (c0_ == '-' && has_line_terminator_before_next_) {
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (c0_ == '-') {
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (c0_ == '>') {
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // Treat the rest of the line as a comment.
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          SkipSingleLineComment();
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // Continue skipping white space after the comment.
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          continue;
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        PushBack('-');  // undo Advance()
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PushBack('-');  // undo Advance()
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Return whether or not we skipped any characters.
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return source_pos() != start_position;
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockToken::Value Scanner::SkipSingleLineComment() {
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The line terminator at the end of the line is not considered
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to be part of the single-line comment; it is recognized
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // separately by the lexical grammar and becomes part of the
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // stream of input elements for the syntactic grammar (see
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ECMA-262, section 7.4, page 12).
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (c0_ >= 0 && !kIsLineTerminator.get(c0_)) {
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Token::WHITESPACE;
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockToken::Value Scanner::SkipMultiLineComment() {
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(c0_ == '*');
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (c0_ >= 0) {
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    char ch = c0_;
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If we have reached the end of the multi-line comment, we
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // consume the '/' and insert a whitespace. This way all
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // multi-line comments are treated as whitespace - even the ones
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // containing line terminators. This contradicts ECMA-262, section
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // 7.4, page 12, that says that multi-line comments containing
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // line terminators should be treated as a line terminator, but it
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // matches the behaviour of SpiderMonkey and KJS.
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (ch == '*' && c0_ == '/') {
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      c0_ = ' ';
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return Token::WHITESPACE;
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Unterminated multi-line comment.
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Token::ILLEGAL;
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockToken::Value Scanner::ScanHtmlComment() {
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for <!-- comments.
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(c0_ == '!');
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (c0_ == '-') {
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (c0_ == '-') return SkipSingleLineComment();
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PushBack('-');  // undo Advance()
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PushBack('!');  // undo Advance()
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(c0_ == '!');
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Token::LT;
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5844515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid Scanner::ScanJson() {
58580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  next_.literal_chars = Vector<const char>();
5864515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  Token::Value token;
5874515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  has_line_terminator_before_next_ = false;
5884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  do {
5894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    // Remember the position of the next token
5904515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    next_.location.beg_pos = source_pos();
5914515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    switch (c0_) {
5924515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case '\t':
5934515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case '\r':
5944515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case '\n':
5954515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case ' ':
5964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        Advance();
5974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        token = Token::WHITESPACE;
5984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        break;
5994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case '{':
6004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        Advance();
6014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        token = Token::LBRACE;
6024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        break;
6034515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case '}':
6044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        Advance();
6054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        token = Token::RBRACE;
6064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        break;
6074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case '[':
6084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        Advance();
6094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        token = Token::LBRACK;
6104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        break;
6114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case ']':
6124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        Advance();
6134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        token = Token::RBRACK;
6144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        break;
6154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case ':':
6164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        Advance();
6174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        token = Token::COLON;
6184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        break;
6194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case ',':
6204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        Advance();
6214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        token = Token::COMMA;
6224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        break;
6234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case '"':
6244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        token = ScanJsonString();
6254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        break;
6264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case '-':
6274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case '0':
6284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case '1':
6294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case '2':
6304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case '3':
6314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case '4':
6324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case '5':
6334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case '6':
6344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case '7':
6354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case '8':
6364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case '9':
6374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        token = ScanJsonNumber();
6384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        break;
6394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case 't':
6404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        token = ScanJsonIdentifier("true", Token::TRUE_LITERAL);
6414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        break;
6424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case 'f':
6434515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        token = ScanJsonIdentifier("false", Token::FALSE_LITERAL);
6444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        break;
6454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      case 'n':
6464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        token = ScanJsonIdentifier("null", Token::NULL_LITERAL);
6474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        break;
6484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      default:
6494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        if (c0_ < 0) {
6504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          Advance();
6514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          token = Token::EOS;
6524515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        } else {
6534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          Advance();
6544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          token = Select(Token::ILLEGAL);
6554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        }
6564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
6574515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  } while (token == Token::WHITESPACE);
6584515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
6594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  next_.location.end_pos = source_pos();
6604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  next_.token = token;
6614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
6624515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
6634515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
6644515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeToken::Value Scanner::ScanJsonString() {
6654515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT_EQ('"', c0_);
6664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  Advance();
66780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  LiteralScope literal(this);
6684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  while (c0_ != '"' && c0_ > 0) {
6694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    // Check for control character (0x00-0x1f) or unterminated string (<0).
6704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    if (c0_ < 0x20) return Token::ILLEGAL;
6714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    if (c0_ != '\\') {
6724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      AddCharAdvance();
6734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    } else {
6744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Advance();
6754515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      switch (c0_) {
6764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        case '"':
6774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        case '\\':
6784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        case '/':
6794515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          AddChar(c0_);
6804515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          break;
6814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        case 'b':
6824515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          AddChar('\x08');
6834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          break;
6844515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        case 'f':
6854515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          AddChar('\x0c');
6864515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          break;
6874515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        case 'n':
6884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          AddChar('\x0a');
6894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          break;
6904515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        case 'r':
6914515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          AddChar('\x0d');
6924515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          break;
6934515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        case 't':
6944515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          AddChar('\x09');
6954515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          break;
6964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        case 'u': {
6974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          uc32 value = 0;
6984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          for (int i = 0; i < 4; i++) {
6994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke            Advance();
7004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke            int digit = HexValue(c0_);
70180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen            if (digit < 0) {
70280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen              return Token::ILLEGAL;
70380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen            }
7044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke            value = value * 16 + digit;
7054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          }
7064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          AddChar(value);
7074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          break;
7084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        }
7094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke        default:
7104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          return Token::ILLEGAL;
7114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      }
7124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Advance();
7134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
7144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
7154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (c0_ != '"') {
7164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    return Token::ILLEGAL;
7174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
71880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  literal.Complete();
7194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  Advance();
7204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  return Token::STRING;
7214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
7224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
7234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
7244515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeToken::Value Scanner::ScanJsonNumber() {
72580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  LiteralScope literal(this);
7264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (c0_ == '-') AddCharAdvance();
7274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (c0_ == '0') {
7284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    AddCharAdvance();
7294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    // Prefix zero is only allowed if it's the only digit before
7304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    // a decimal point or exponent.
7314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    if ('0' <= c0_ && c0_ <= '9') return Token::ILLEGAL;
7324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  } else {
7334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    if (c0_ < '1' || c0_ > '9') return Token::ILLEGAL;
7344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    do {
7354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      AddCharAdvance();
7364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    } while (c0_ >= '0' && c0_ <= '9');
7374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
7384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (c0_ == '.') {
7394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    AddCharAdvance();
7404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    if (c0_ < '0' || c0_ > '9') return Token::ILLEGAL;
7414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    do {
7424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      AddCharAdvance();
7434515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    } while (c0_ >= '0' && c0_ <= '9');
7444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
7454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if ((c0_ | 0x20) == 'e') {
7464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    AddCharAdvance();
7474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    if (c0_ == '-' || c0_ == '+') AddCharAdvance();
7484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    if (c0_ < '0' || c0_ > '9') return Token::ILLEGAL;
7494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    do {
7504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      AddCharAdvance();
7514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    } while (c0_ >= '0' && c0_ <= '9');
7524515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
75380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  literal.Complete();
7544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  return Token::NUMBER;
7554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
7564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
7574515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
7584515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeToken::Value Scanner::ScanJsonIdentifier(const char* text,
7594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                         Token::Value token) {
76080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  LiteralScope literal(this);
7614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  while (*text != '\0') {
7624515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    if (c0_ != *text) return Token::ILLEGAL;
7634515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    Advance();
7644515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    text++;
7654515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
7664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (kIsIdentifierPart.get(c0_)) return Token::ILLEGAL;
76780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  literal.Complete();
7684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  return token;
7694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
7704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
7714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
7724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid Scanner::ScanJavaScript() {
77380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  next_.literal_chars = Vector<const char>();
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Token::Value token;
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  has_line_terminator_before_next_ = false;
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  do {
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Remember the position of the next token
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    next_.location.beg_pos = source_pos();
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    switch (c0_) {
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case ' ':
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '\t':
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Token::WHITESPACE;
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '\n':
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        has_line_terminator_before_next_ = true;
790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Token::WHITESPACE;
791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '"': case '\'':
794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = ScanString();
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '<':
798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // < <= << <<= <!--
799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (c0_ == '=') {
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select(Token::LTE);
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (c0_ == '<') {
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select('=', Token::ASSIGN_SHL, Token::SHL);
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (c0_ == '!') {
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = ScanHtmlComment();
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::LT;
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '>':
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // > >= >> >>= >>> >>>=
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (c0_ == '=') {
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select(Token::GTE);
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (c0_ == '>') {
817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // >> >>= >>> >>>=
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Advance();
819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (c0_ == '=') {
820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            token = Select(Token::ASSIGN_SAR);
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else if (c0_ == '>') {
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            token = Select('=', Token::ASSIGN_SHR, Token::SHR);
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            token = Token::SAR;
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::GT;
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '=':
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // = == ===
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (c0_ == '=') {
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select('=', Token::EQ_STRICT, Token::EQ);
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::ASSIGN;
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '!':
842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // ! != !==
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (c0_ == '=') {
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select('=', Token::NE_STRICT, Token::NE);
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::NOT;
848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '+':
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // + ++ +=
853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (c0_ == '+') {
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select(Token::INC);
856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (c0_ == '=') {
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select(Token::ASSIGN_ADD);
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::ADD;
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '-':
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // - -- --> -=
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (c0_ == '-') {
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Advance();
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (c0_ == '>' && has_line_terminator_before_next_) {
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            // For compatibility with SpiderMonkey, we skip lines that
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            // start with an HTML comment end '-->'.
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            token = SkipSingleLineComment();
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            token = Token::DEC;
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (c0_ == '=') {
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select(Token::ASSIGN_SUB);
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::SUB;
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '*':
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // * *=
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select('=', Token::ASSIGN_MUL, Token::MUL);
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '%':
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // % %=
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select('=', Token::ASSIGN_MOD, Token::MOD);
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '/':
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // /  // /* /=
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (c0_ == '/') {
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = SkipSingleLineComment();
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (c0_ == '*') {
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = SkipMultiLineComment();
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (c0_ == '=') {
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select(Token::ASSIGN_DIV);
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::DIV;
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '&':
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // & && &=
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (c0_ == '&') {
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select(Token::AND);
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (c0_ == '=') {
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select(Token::ASSIGN_BIT_AND);
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::BIT_AND;
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '|':
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // | || |=
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (c0_ == '|') {
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select(Token::OR);
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (c0_ == '=') {
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select(Token::ASSIGN_BIT_OR);
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::BIT_OR;
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '^':
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // ^ ^=
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select('=', Token::ASSIGN_BIT_XOR, Token::BIT_XOR);
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '.':
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // . Number
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (IsDecimalDigit(c0_)) {
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = ScanNumber(true);
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::PERIOD;
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case ':':
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select(Token::COLON);
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case ';':
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select(Token::SEMICOLON);
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case ',':
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select(Token::COMMA);
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '(':
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select(Token::LPAREN);
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case ')':
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select(Token::RPAREN);
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '[':
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select(Token::LBRACK);
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case ']':
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select(Token::RBRACK);
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '{':
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select(Token::LBRACE);
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '}':
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select(Token::RBRACE);
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '?':
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select(Token::CONDITIONAL);
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '~':
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        token = Select(Token::BIT_NOT);
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      default:
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (kIsIdentifierStart.get(c0_)) {
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = ScanIdentifier();
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (IsDecimalDigit(c0_)) {
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = ScanNumber(false);
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (SkipWhiteSpace()) {
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::WHITESPACE;
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (c0_ < 0) {
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Token::EOS;
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          token = Select(Token::ILLEGAL);
1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Continue scanning for tokens as long as we're just skipping
1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // whitespace.
1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } while (token == Token::WHITESPACE);
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_.location.end_pos = source_pos();
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_.token = token;
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scanner::SeekForward(int pos) {
1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  source_->SeekForward(pos - 1);
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Scan();
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockuc32 Scanner::ScanHexEscape(uc32 c, int length) {
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(length <= 4);  // prevent overflow
1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uc32 digits[4];
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uc32 x = 0;
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < length; i++) {
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    digits[i] = c0_;
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int d = HexValue(c0_);
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (d < 0) {
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // According to ECMA-262, 3rd, 7.8.4, page 18, these hex escapes
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // should be illegal, but other JS VMs just return the
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // non-escaped version of the original character.
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Push back digits read, except the last one (in c0_).
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      for (int j = i-1; j >= 0; j--) {
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        PushBack(digits[j]);
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Notice: No handling of error - treat it as "\u"->"u".
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return c;
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    x = x * 16 + d;
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return x;
1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Octal escapes of the forms '\0xx' and '\xxx' are not a part of
1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ECMA-262. Other JS VMs support them.
1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockuc32 Scanner::ScanOctalEscape(uc32 c, int length) {
1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uc32 x = c - '0';
1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < length; i++) {
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int d = c0_ - '0';
1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (d < 0 || d > 7) break;
1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int nx = x * 8 + d;
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (nx >= 256) break;
1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    x = nx;
1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return x;
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scanner::ScanEscape() {
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uc32 c = c0_;
1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Skip escaped newlines.
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (kIsLineTerminator.get(c)) {
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Allow CR+LF newlines in multiline string literals.
1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance();
1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Allow LF+CR newlines in multiline string literals.
1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (IsLineFeed(c) && IsCarriageReturn(c0_)) Advance();
1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (c) {
1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '\'':  // fall through
1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '"' :  // fall through
1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '\\': break;
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'b' : c = '\b'; break;
1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'f' : c = '\f'; break;
1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'n' : c = '\n'; break;
1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'r' : c = '\r'; break;
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 't' : c = '\t'; break;
1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'u' : c = ScanHexEscape(c, 4); break;
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'v' : c = '\v'; break;
1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'x' : c = ScanHexEscape(c, 2); break;
1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '0' :  // fall through
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '1' :  // fall through
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '2' :  // fall through
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '3' :  // fall through
1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '4' :  // fall through
1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '5' :  // fall through
1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '6' :  // fall through
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '7' : c = ScanOctalEscape(c, 2); break;
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // According to ECMA-262, 3rd, 7.8.4 (p 18ff) these
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // should be illegal, but they are commonly handled
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // as non-escaped characters by JS VMs.
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AddChar(c);
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockToken::Value Scanner::ScanString() {
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uc32 quote = c0_;
1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();  // consume quote
1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
111080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  LiteralScope literal(this);
1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (c0_ != quote && c0_ >= 0 && !kIsLineTerminator.get(c0_)) {
1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uc32 c = c0_;
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (c == '\\') {
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (c0_ < 0) return Token::ILLEGAL;
1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ScanEscape();
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AddChar(c);
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
112180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (c0_ != quote) return Token::ILLEGAL;
112280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  literal.Complete();
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();  // consume quote
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Token::STRING;
1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockToken::Value Scanner::Select(Token::Value tok) {
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return tok;
1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockToken::Value Scanner::Select(uc32 next, Token::Value then, Token::Value else_) {
1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (c0_ == next) {
1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return then;
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return else_;
1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns true if any decimal digits were scanned, returns false otherwise.
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scanner::ScanDecimalDigits() {
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (IsDecimalDigit(c0_))
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AddCharAdvance();
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockToken::Value Scanner::ScanNumber(bool seen_period) {
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(IsDecimalDigit(c0_));  // the first digit of the number or the fraction
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  enum { DECIMAL, HEX, OCTAL } kind = DECIMAL;
1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
115880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  LiteralScope literal(this);
1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (seen_period) {
1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // we have already seen a decimal point of the float
1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AddChar('.');
1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ScanDecimalDigits();  // we know we have at least one digit
1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // if the first character is '0' we must check for octals and hex
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (c0_ == '0') {
1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AddCharAdvance();
1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // either 0, 0exxx, 0Exxx, 0.xxx, an octal number, or a hex number
1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (c0_ == 'x' || c0_ == 'X') {
1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // hex number
1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        kind = HEX;
1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AddCharAdvance();
117480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        if (!IsHexDigit(c0_)) {
1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // we must have at least one hex digit after 'x'/'X'
1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return Token::ILLEGAL;
117780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        }
117880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        while (IsHexDigit(c0_)) {
1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AddCharAdvance();
118080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        }
1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if ('0' <= c0_ && c0_ <= '7') {
1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // (possible) octal number
1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        kind = OCTAL;
1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        while (true) {
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (c0_ == '8' || c0_ == '9') {
1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            kind = DECIMAL;
1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (c0_  < '0' || '7'  < c0_) break;
1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AddCharAdvance();
1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Parse decimal digits and allow trailing fractional part.
1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (kind == DECIMAL) {
1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ScanDecimalDigits();  // optional
1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (c0_ == '.') {
1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AddCharAdvance();
1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ScanDecimalDigits();  // optional
1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scan exponent, if any
1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (c0_ == 'e' || c0_ == 'E') {
1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(kind != HEX);  // 'e'/'E' must be scanned as part of the hex number
1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (kind == OCTAL) return Token::ILLEGAL;  // no exponent for octals allowed
1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // scan exponent
1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AddCharAdvance();
1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (c0_ == '+' || c0_ == '-')
1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AddCharAdvance();
121380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (!IsDecimalDigit(c0_)) {
1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // we must have at least one decimal digit after 'e'/'E'
1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return Token::ILLEGAL;
121680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ScanDecimalDigits();
1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The source character immediately following a numeric literal must
1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // not be an identifier start or a decimal digit; see ECMA-262
1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // section 7.8.3, page 17 (note that we read only one decimal digit
1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // if the value is 0).
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (IsDecimalDigit(c0_) || kIsIdentifierStart.get(c0_))
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return Token::ILLEGAL;
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
122780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  literal.Complete();
122880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Token::NUMBER;
1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockuc32 Scanner::ScanIdentifierUnicodeEscape() {
1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (c0_ != 'u') return unibrow::Utf8::kBadChar;
1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uc32 c = ScanHexEscape('u', 4);
1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We do not allow a unicode escape sequence to start another
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // unicode escape sequence.
1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (c == '\\') return unibrow::Utf8::kBadChar;
1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return c;
1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockToken::Value Scanner::ScanIdentifier() {
1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kIsIdentifierStart.get(c0_));
1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
124880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  LiteralScope literal(this);
1249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  KeywordMatcher keyword_match;
1250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Scan identifier start character.
1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (c0_ == '\\') {
1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uc32 c = ScanIdentifierUnicodeEscape();
1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Only allow legal identifier start characters.
1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!kIsIdentifierStart.get(c)) return Token::ILLEGAL;
1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AddChar(c);
1257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    keyword_match.Fail();
1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AddChar(c0_);
1260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    keyword_match.AddChar(c0_);
1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Scan the rest of the identifier characters.
1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (kIsIdentifierPart.get(c0_)) {
1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (c0_ == '\\') {
1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      uc32 c = ScanIdentifierUnicodeEscape();
1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Only allow legal identifier part characters.
1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (!kIsIdentifierPart.get(c)) return Token::ILLEGAL;
1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AddChar(c);
1271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      keyword_match.Fail();
1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AddChar(c0_);
1274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      keyword_match.AddChar(c0_);
1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
127880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  literal.Complete();
1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return keyword_match.token();
1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Scanner::IsIdentifier(unibrow::CharacterStream* buffer) {
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Checks whether the buffer contains an identifier (no escape).
1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!buffer->has_more()) return false;
1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!kIsIdentifierStart.get(buffer->GetNext())) return false;
1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (buffer->has_more()) {
1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!kIsIdentifierPart.get(buffer->GetNext())) return false;
1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Scanner::ScanRegExpPattern(bool seen_equal) {
1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Scan: ('/' | '/=') RegularExpressionBody '/' RegularExpressionFlags
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool in_character_class = false;
1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Previous token is either '/' or '/=', in the second case, the
1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // pattern starts at =.
1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_.location.beg_pos = source_pos() - (seen_equal ? 2 : 1);
1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_.location.end_pos = source_pos() - (seen_equal ? 1 : 0);
1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Scan regular expression body: According to ECMA-262, 3rd, 7.8.5,
1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the scanner should pass uninterpreted bodies to the RegExp
1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // constructor.
130880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  LiteralScope literal(this);
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (seen_equal)
1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AddChar('=');
1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (c0_ != '/' || in_character_class) {
131380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (kIsLineTerminator.get(c0_) || c0_ < 0) return false;
1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (c0_ == '\\') {  // escaped character
1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AddCharAdvance();
131680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      if (kIsLineTerminator.get(c0_) || c0_ < 0) return false;
1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AddCharAdvance();
1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {  // unescaped character
131980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      if (c0_ == '[') in_character_class = true;
132080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      if (c0_ == ']') in_character_class = false;
1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AddCharAdvance();
1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();  // consume '/'
1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
132680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  literal.Complete();
1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Scanner::ScanRegExpFlags() {
1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Scan regular expression flags.
133380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  LiteralScope literal(this);
1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (kIsIdentifierPart.get(c0_)) {
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (c0_ == '\\') {
1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      uc32 c = ScanIdentifierUnicodeEscape();
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (c != static_cast<uc32>(unibrow::Utf8::kBadChar)) {
1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // We allow any escaped character, unlike the restriction on
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // IdentifierPart when it is used to build an IdentifierName.
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AddChar(c);
1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        continue;
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AddCharAdvance();
1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
134680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  literal.Complete();
1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_.location.end_pos = source_pos() - 1;
1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
1353