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