| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 #include "hashmap.h" | 37 #include "hashmap.h" |
| 38 #include "list.h" | 38 #include "list.h" |
| 39 #include "token.h" | 39 #include "token.h" |
| 40 #include "unicode-inl.h" | 40 #include "unicode-inl.h" |
| 41 #include "utils.h" | 41 #include "utils.h" |
| 42 | 42 |
| 43 namespace v8 { | 43 namespace v8 { |
| 44 namespace internal { | 44 namespace internal { |
| 45 | 45 |
| 46 | 46 |
| 47 class ParserRecorder; |
| 48 |
| 49 |
| 47 // Returns the value (0 .. 15) of a hexadecimal character c. | 50 // Returns the value (0 .. 15) of a hexadecimal character c. |
| 48 // If c is not a legal hexadecimal character, returns a value < 0. | 51 // If c is not a legal hexadecimal character, returns a value < 0. |
| 49 inline int HexValue(uc32 c) { | 52 inline int HexValue(uc32 c) { |
| 50 c -= '0'; | 53 c -= '0'; |
| 51 if (static_cast<unsigned>(c) <= 9) return c; | 54 if (static_cast<unsigned>(c) <= 9) return c; |
| 52 c = (c | 0x20) - ('a' - '0'); // detect 0x11..0x16 and 0x31..0x36. | 55 c = (c | 0x20) - ('a' - '0'); // detect 0x11..0x16 and 0x31..0x36. |
| 53 if (static_cast<unsigned>(c) <= 5) return c + 10; | 56 if (static_cast<unsigned>(c) <= 5) return c + 10; |
| 54 return -1; | 57 return -1; |
| 55 } | 58 } |
| 56 | 59 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 protected: | 116 protected: |
| 114 static const uc32 kEndOfInput = -1; | 117 static const uc32 kEndOfInput = -1; |
| 115 | 118 |
| 116 // Ensures that the buffer_cursor_ points to the code_unit at | 119 // Ensures that the buffer_cursor_ points to the code_unit at |
| 117 // position pos_ of the input, if possible. If the position | 120 // position pos_ of the input, if possible. If the position |
| 118 // is at or after the end of the input, return false. If there | 121 // is at or after the end of the input, return false. If there |
| 119 // are more code_units available, return true. | 122 // are more code_units available, return true. |
| 120 virtual bool ReadBlock() = 0; | 123 virtual bool ReadBlock() = 0; |
| 121 virtual unsigned SlowSeekForward(unsigned code_unit_count) = 0; | 124 virtual unsigned SlowSeekForward(unsigned code_unit_count) = 0; |
| 122 | 125 |
| 123 const uc16* buffer_cursor_; | 126 const uint16_t* buffer_cursor_; |
| 124 const uc16* buffer_end_; | 127 const uint16_t* buffer_end_; |
| 125 unsigned pos_; | 128 unsigned pos_; |
| 126 }; | 129 }; |
| 127 | 130 |
| 128 | 131 |
| 129 #else | 132 #else |
| 130 | 133 |
| 131 class Utf16CharacterStream { | 134 class Utf16CharacterStream { |
| 132 public: | 135 public: |
| 133 enum StreamType { | 136 enum StreamType { |
| 134 kUtf8ToUtf16, kGenericStringUtf16, kExternalTwoByteStringUtf16 | 137 kUtf8ToUtf16, kGenericStringUtf16, kExternalTwoByteStringUtf16 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 // --------------------------------------------------------------------- | 193 // --------------------------------------------------------------------- |
| 191 // DuplicateFinder discovers duplicate symbols. | 194 // DuplicateFinder discovers duplicate symbols. |
| 192 | 195 |
| 193 class DuplicateFinder { | 196 class DuplicateFinder { |
| 194 public: | 197 public: |
| 195 explicit DuplicateFinder(UnicodeCache* constants) | 198 explicit DuplicateFinder(UnicodeCache* constants) |
| 196 : unicode_constants_(constants), | 199 : unicode_constants_(constants), |
| 197 backing_store_(16), | 200 backing_store_(16), |
| 198 map_(&Match) { } | 201 map_(&Match) { } |
| 199 | 202 |
| 200 int AddAsciiSymbol(Vector<const char> key, int value); | 203 int AddOneByteSymbol(Vector<const uint8_t> key, int value); |
| 201 int AddUtf16Symbol(Vector<const uint16_t> key, int value); | 204 int AddTwoByteSymbol(Vector<const uint16_t> key, int value); |
| 202 // Add a a number literal by converting it (if necessary) | 205 // Add a a number literal by converting it (if necessary) |
| 203 // to the string that ToString(ToNumber(literal)) would generate. | 206 // to the string that ToString(ToNumber(literal)) would generate. |
| 204 // and then adding that string with AddAsciiSymbol. | 207 // and then adding that string with AddAsciiSymbol. |
| 205 // This string is the actual value used as key in an object literal, | 208 // This string is the actual value used as key in an object literal, |
| 206 // and the one that must be different from the other keys. | 209 // and the one that must be different from the other keys. |
| 207 int AddNumber(Vector<const char> key, int value); | 210 int AddNumber(Vector<const uint8_t> key, int value); |
| 208 | 211 |
| 209 private: | 212 private: |
| 210 int AddSymbol(Vector<const byte> key, bool is_ascii, int value); | 213 int AddSymbol(Vector<const uint8_t> key, bool is_one_byte, int value); |
| 211 // Backs up the key and its length in the backing store. | 214 // Backs up the key and its length in the backing store. |
| 212 // The backup is stored with a base 127 encoding of the | 215 // The backup is stored with a base 127 encoding of the |
| 213 // length (plus a bit saying whether the string is ASCII), | 216 // length (plus a bit saying whether the string is one byte), |
| 214 // followed by the bytes of the key. | 217 // followed by the bytes of the key. |
| 215 byte* BackupKey(Vector<const byte> key, bool is_ascii); | 218 uint8_t* BackupKey(Vector<const uint8_t> key, bool is_one_byte); |
| 216 | 219 |
| 217 // Compare two encoded keys (both pointing into the backing store) | 220 // Compare two encoded keys (both pointing into the backing store) |
| 218 // for having the same base-127 encoded lengths and ASCII-ness, | 221 // for having the same base-127 encoded lengths and ASCII-ness, |
| 219 // and then having the same 'length' bytes following. | 222 // and then having the same 'length' bytes following. |
| 220 static bool Match(void* first, void* second); | 223 static bool Match(void* first, void* second); |
| 221 // Creates a hash from a sequence of bytes. | 224 // Creates a hash from a sequence of bytes. |
| 222 static uint32_t Hash(Vector<const byte> key, bool is_ascii); | 225 static uint32_t Hash(Vector<const uint8_t> key, bool is_one_byte); |
| 223 // Checks whether a string containing a JS number is its canonical | 226 // Checks whether a string containing a JS number is its canonical |
| 224 // form. | 227 // form. |
| 225 static bool IsNumberCanonical(Vector<const char> key); | 228 static bool IsNumberCanonical(Vector<const uint8_t> key); |
| 226 | 229 |
| 227 // Size of buffer. Sufficient for using it to call DoubleToCString in | 230 // Size of buffer. Sufficient for using it to call DoubleToCString in |
| 228 // from conversions.h. | 231 // from conversions.h. |
| 229 static const int kBufferSize = 100; | 232 static const int kBufferSize = 100; |
| 230 | 233 |
| 231 UnicodeCache* unicode_constants_; | 234 UnicodeCache* unicode_constants_; |
| 232 // Backing store used to store strings used as hashmap keys. | 235 // Backing store used to store strings used as hashmap keys. |
| 233 SequenceCollector<unsigned char> backing_store_; | 236 SequenceCollector<unsigned char> backing_store_; |
| 234 HashMap map_; | 237 HashMap map_; |
| 235 // Buffer used for string->number->canonical string conversions. | 238 // Buffer used for string->number->canonical string conversions. |
| 236 char number_buffer_[kBufferSize]; | 239 char number_buffer_[kBufferSize]; |
| 237 }; | 240 }; |
| 238 | 241 |
| 239 | 242 |
| 240 // ---------------------------------------------------------------------------- | 243 // ---------------------------------------------------------------------------- |
| 241 // LiteralBuffer - Collector of chars of literals. | 244 // LiteralBuffer - Collector of chars of literals. |
| 242 | 245 |
| 243 class LiteralBuffer { | 246 class LiteralBuffer { |
| 244 public: | 247 public: |
| 245 LiteralBuffer() : is_ascii_(true), position_(0), backing_store_() { } | 248 LiteralBuffer() : is_one_byte_(true), position_(0), backing_store_() { } |
| 246 | 249 |
| 247 ~LiteralBuffer() { | 250 ~LiteralBuffer() { |
| 248 if (backing_store_.length() > 0) { | 251 if (backing_store_.length() > 0) { |
| 249 backing_store_.Dispose(); | 252 backing_store_.Dispose(); |
| 250 } | 253 } |
| 251 } | 254 } |
| 252 | 255 |
| 253 INLINE(void AddChar(uint32_t code_unit)) { | 256 INLINE(void AddChar(uint32_t code_unit)) { |
| 254 if (position_ >= backing_store_.length()) ExpandBuffer(); | 257 if (position_ >= backing_store_.length()) ExpandBuffer(); |
| 255 if (is_ascii_) { | 258 if (is_one_byte_) { |
| 256 if (code_unit <= unibrow::Latin1::kMaxChar) { | 259 if (code_unit <= unibrow::Latin1::kMaxChar) { |
| 257 backing_store_[position_] = static_cast<byte>(code_unit); | 260 backing_store_[position_] = static_cast<byte>(code_unit); |
| 258 position_ += kOneByteSize; | 261 position_ += kOneByteSize; |
| 259 return; | 262 return; |
| 260 } | 263 } |
| 261 ConvertToUtf16(); | 264 ConvertToTwoByte(); |
| 262 } | 265 } |
| 263 ASSERT(code_unit < 0x10000u); | 266 ASSERT(code_unit < 0x10000u); |
| 264 *reinterpret_cast<uc16*>(&backing_store_[position_]) = code_unit; | 267 *reinterpret_cast<uint16_t*>(&backing_store_[position_]) = code_unit; |
| 265 position_ += kUC16Size; | 268 position_ += kUC16Size; |
| 266 } | 269 } |
| 267 | 270 |
| 268 bool is_ascii() { return is_ascii_; } | 271 bool is_one_byte() { return is_one_byte_; } |
| 269 | 272 |
| 270 bool is_contextual_keyword(Vector<const char> keyword) { | 273 bool is_contextual_keyword(Vector<const char> keyword) { |
| 271 return is_ascii() && keyword.length() == position_ && | 274 return is_one_byte() && keyword.length() == position_ && |
| 272 (memcmp(keyword.start(), backing_store_.start(), position_) == 0); | 275 (memcmp(keyword.start(), backing_store_.start(), position_) == 0); |
| 273 } | 276 } |
| 274 | 277 |
| 275 Vector<const uc16> utf16_literal() { | 278 Vector<const uint16_t> two_byte_literal() { |
| 276 ASSERT(!is_ascii_); | 279 ASSERT(!is_one_byte_); |
| 277 ASSERT((position_ & 0x1) == 0); | 280 ASSERT((position_ & 0x1) == 0); |
| 278 return Vector<const uc16>( | 281 return Vector<const uint16_t>( |
| 279 reinterpret_cast<const uc16*>(backing_store_.start()), | 282 reinterpret_cast<const uint16_t*>(backing_store_.start()), |
| 280 position_ >> 1); | 283 position_ >> 1); |
| 281 } | 284 } |
| 282 | 285 |
| 283 Vector<const char> ascii_literal() { | 286 Vector<const uint8_t> one_byte_literal() { |
| 284 ASSERT(is_ascii_); | 287 ASSERT(is_one_byte_); |
| 285 return Vector<const char>( | 288 return Vector<const uint8_t>( |
| 286 reinterpret_cast<const char*>(backing_store_.start()), | 289 reinterpret_cast<const uint8_t*>(backing_store_.start()), |
| 287 position_); | 290 position_); |
| 288 } | 291 } |
| 289 | 292 |
| 290 int length() { | 293 int length() { |
| 291 return is_ascii_ ? position_ : (position_ >> 1); | 294 return is_one_byte_ ? position_ : (position_ >> 1); |
| 292 } | 295 } |
| 293 | 296 |
| 294 void Reset() { | 297 void Reset() { |
| 295 position_ = 0; | 298 position_ = 0; |
| 296 is_ascii_ = true; | 299 is_one_byte_ = true; |
| 297 } | 300 } |
| 298 | 301 |
| 299 private: | 302 private: |
| 300 static const int kInitialCapacity = 16; | 303 static const int kInitialCapacity = 16; |
| 301 static const int kGrowthFactory = 4; | 304 static const int kGrowthFactory = 4; |
| 302 static const int kMinConversionSlack = 256; | 305 static const int kMinConversionSlack = 256; |
| 303 static const int kMaxGrowth = 1 * MB; | 306 static const int kMaxGrowth = 1 * MB; |
| 304 inline int NewCapacity(int min_capacity) { | 307 inline int NewCapacity(int min_capacity) { |
| 305 int capacity = Max(min_capacity, backing_store_.length()); | 308 int capacity = Max(min_capacity, backing_store_.length()); |
| 306 int new_capacity = Min(capacity * kGrowthFactory, capacity + kMaxGrowth); | 309 int new_capacity = Min(capacity * kGrowthFactory, capacity + kMaxGrowth); |
| 307 return new_capacity; | 310 return new_capacity; |
| 308 } | 311 } |
| 309 | 312 |
| 310 void ExpandBuffer() { | 313 void ExpandBuffer() { |
| 311 Vector<byte> new_store = Vector<byte>::New(NewCapacity(kInitialCapacity)); | 314 Vector<byte> new_store = Vector<byte>::New(NewCapacity(kInitialCapacity)); |
| 312 OS::MemCopy(new_store.start(), backing_store_.start(), position_); | 315 OS::MemCopy(new_store.start(), backing_store_.start(), position_); |
| 313 backing_store_.Dispose(); | 316 backing_store_.Dispose(); |
| 314 backing_store_ = new_store; | 317 backing_store_ = new_store; |
| 315 } | 318 } |
| 316 | 319 |
| 317 void ConvertToUtf16() { | 320 void ConvertToTwoByte() { |
| 318 ASSERT(is_ascii_); | 321 ASSERT(is_one_byte_); |
| 319 Vector<byte> new_store; | 322 Vector<byte> new_store; |
| 320 int new_content_size = position_ * kUC16Size; | 323 int new_content_size = position_ * kUC16Size; |
| 321 if (new_content_size >= backing_store_.length()) { | 324 if (new_content_size >= backing_store_.length()) { |
| 322 // Ensure room for all currently read code units as UC16 as well | 325 // Ensure room for all currently read code units as UC16 as well |
| 323 // as the code unit about to be stored. | 326 // as the code unit about to be stored. |
| 324 new_store = Vector<byte>::New(NewCapacity(new_content_size)); | 327 new_store = Vector<byte>::New(NewCapacity(new_content_size)); |
| 325 } else { | 328 } else { |
| 326 new_store = backing_store_; | 329 new_store = backing_store_; |
| 327 } | 330 } |
| 328 uint8_t* src = backing_store_.start(); | 331 uint8_t* src = backing_store_.start(); |
| 329 uc16* dst = reinterpret_cast<uc16*>(new_store.start()); | 332 uint16_t* dst = reinterpret_cast<uint16_t*>(new_store.start()); |
| 330 for (int i = position_ - 1; i >= 0; i--) { | 333 for (int i = position_ - 1; i >= 0; i--) { |
| 331 dst[i] = src[i]; | 334 dst[i] = src[i]; |
| 332 } | 335 } |
| 333 if (new_store.start() != backing_store_.start()) { | 336 if (new_store.start() != backing_store_.start()) { |
| 334 backing_store_.Dispose(); | 337 backing_store_.Dispose(); |
| 335 backing_store_ = new_store; | 338 backing_store_ = new_store; |
| 336 } | 339 } |
| 337 position_ = new_content_size; | 340 position_ = new_content_size; |
| 338 is_ascii_ = false; | 341 is_one_byte_ = false; |
| 339 } | 342 } |
| 340 | 343 |
| 341 bool is_ascii_; | 344 bool is_one_byte_; |
| 342 int position_; | 345 int position_; |
| 343 Vector<byte> backing_store_; | 346 Vector<byte> backing_store_; |
| 344 | 347 |
| 345 DISALLOW_COPY_AND_ASSIGN(LiteralBuffer); | 348 DISALLOW_COPY_AND_ASSIGN(LiteralBuffer); |
| 346 }; | 349 }; |
| 347 | 350 |
| 348 | 351 |
| 349 #ifndef V8_USE_GENERATED_LEXER | 352 #ifndef V8_USE_GENERATED_LEXER |
| 350 | 353 |
| 351 | 354 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 | 400 |
| 398 void Initialize(Utf16CharacterStream* source); | 401 void Initialize(Utf16CharacterStream* source); |
| 399 | 402 |
| 400 // Returns the next token and advances input. | 403 // Returns the next token and advances input. |
| 401 Token::Value Next(); | 404 Token::Value Next(); |
| 402 // Returns the current token again. | 405 // Returns the current token again. |
| 403 Token::Value current_token() { return current_.token; } | 406 Token::Value current_token() { return current_.token; } |
| 404 // Returns the location information for the current token | 407 // Returns the location information for the current token |
| 405 // (the token last returned by Next()). | 408 // (the token last returned by Next()). |
| 406 Location location() const { return current_.location; } | 409 Location location() const { return current_.location; } |
| 407 // Returns the literal string, if any, for the current token (the | 410 |
| 408 // token last returned by Next()). The string is 0-terminated. | 411 // Similar functions for the upcoming token. |
| 409 // Literal strings are collected for identifiers, strings, and | 412 |
| 410 // numbers. | 413 // One token look-ahead (past the token returned by Next()). |
| 411 // These functions only give the correct result if the literal | 414 Token::Value peek() const { return next_.token; } |
| 412 // was scanned between calls to StartLiteral() and TerminateLiteral(). | 415 |
| 413 Vector<const char> literal_ascii_string() { | 416 Location peek_location() const { return next_.location; } |
| 414 ASSERT_NOT_NULL(current_.literal_chars); | |
| 415 return current_.literal_chars->ascii_literal(); | |
| 416 } | |
| 417 Vector<const uc16> literal_utf16_string() { | |
| 418 ASSERT_NOT_NULL(current_.literal_chars); | |
| 419 return current_.literal_chars->utf16_literal(); | |
| 420 } | |
| 421 bool is_literal_ascii() { | |
| 422 ASSERT_NOT_NULL(current_.literal_chars); | |
| 423 return current_.literal_chars->is_ascii(); | |
| 424 } | |
| 425 bool is_literal_contextual_keyword(Vector<const char> keyword) { | |
| 426 ASSERT_NOT_NULL(current_.literal_chars); | |
| 427 return current_.literal_chars->is_contextual_keyword(keyword); | |
| 428 } | |
| 429 int literal_length() const { | |
| 430 ASSERT_NOT_NULL(current_.literal_chars); | |
| 431 return current_.literal_chars->length(); | |
| 432 } | |
| 433 | 417 |
| 434 bool literal_contains_escapes() const { | 418 bool literal_contains_escapes() const { |
| 435 Location location = current_.location; | 419 Location location = current_.location; |
| 436 int source_length = (location.end_pos - location.beg_pos); | 420 int source_length = (location.end_pos - location.beg_pos); |
| 437 if (current_.token == Token::STRING) { | 421 if (current_.token == Token::STRING) { |
| 438 // Subtract delimiters. | 422 // Subtract delimiters. |
| 439 source_length -= 2; | 423 source_length -= 2; |
| 440 } | 424 } |
| 441 return current_.literal_chars->length() != source_length; | 425 return current_.literal_chars->length() != source_length; |
| 442 } | 426 } |
| 443 | 427 bool is_literal_contextual_keyword(Vector<const char> keyword) { |
| 444 // Similar functions for the upcoming token. | 428 ASSERT_NOT_NULL(current_.literal_chars); |
| 445 | 429 return current_.literal_chars->is_contextual_keyword(keyword); |
| 446 // One token look-ahead (past the token returned by Next()). | |
| 447 Token::Value peek() const { return next_.token; } | |
| 448 | |
| 449 Location peek_location() const { return next_.location; } | |
| 450 | |
| 451 // Returns the literal string for the next token (the token that | |
| 452 // would be returned if Next() were called). | |
| 453 Vector<const char> next_literal_ascii_string() { | |
| 454 ASSERT_NOT_NULL(next_.literal_chars); | |
| 455 return next_.literal_chars->ascii_literal(); | |
| 456 } | |
| 457 Vector<const uc16> next_literal_utf16_string() { | |
| 458 ASSERT_NOT_NULL(next_.literal_chars); | |
| 459 return next_.literal_chars->utf16_literal(); | |
| 460 } | |
| 461 bool is_next_literal_ascii() { | |
| 462 ASSERT_NOT_NULL(next_.literal_chars); | |
| 463 return next_.literal_chars->is_ascii(); | |
| 464 } | 430 } |
| 465 bool is_next_contextual_keyword(Vector<const char> keyword) { | 431 bool is_next_contextual_keyword(Vector<const char> keyword) { |
| 466 ASSERT_NOT_NULL(next_.literal_chars); | 432 ASSERT_NOT_NULL(next_.literal_chars); |
| 467 return next_.literal_chars->is_contextual_keyword(keyword); | 433 return next_.literal_chars->is_contextual_keyword(keyword); |
| 468 } | 434 } |
| 469 int next_literal_length() const { | 435 |
| 470 ASSERT_NOT_NULL(next_.literal_chars); | 436 Handle<String> AllocateNextLiteralString(Isolate* isolate, |
| 471 return next_.literal_chars->length(); | 437 PretenureFlag tenured); |
| 438 Handle<String> AllocateInternalizedString(Isolate* isolate); |
| 439 |
| 440 double DoubleValue(); |
| 441 bool UnescapedLiteralMatches(const char* data, int length) { |
| 442 if (is_literal_one_byte() && |
| 443 literal_length() == length && |
| 444 !literal_contains_escapes()) { |
| 445 const char* token = |
| 446 reinterpret_cast<const char*>(literal_one_byte_string().start()); |
| 447 return !strncmp(token, data, length); |
| 448 } |
| 449 return false; |
| 472 } | 450 } |
| 451 void IsGetOrSet(bool* is_get, bool* is_set) { |
| 452 if (is_literal_one_byte() && |
| 453 literal_length() == 3 && |
| 454 !literal_contains_escapes()) { |
| 455 const char* token = |
| 456 reinterpret_cast<const char*>(literal_one_byte_string().start()); |
| 457 *is_get = strncmp(token, "get", 3) == 0; |
| 458 *is_set = !*is_get && strncmp(token, "set", 3) == 0; |
| 459 } |
| 460 } |
| 461 |
| 462 int FindNumber(DuplicateFinder* finder, int value); |
| 463 int FindSymbol(DuplicateFinder* finder, int value); |
| 464 |
| 465 void LogSymbol(ParserRecorder* log, int position); |
| 473 | 466 |
| 474 UnicodeCache* unicode_cache() { return unicode_cache_; } | 467 UnicodeCache* unicode_cache() { return unicode_cache_; } |
| 475 | 468 |
| 476 static const int kCharacterLookaheadBufferSize = 1; | |
| 477 | |
| 478 // Scans octal escape sequence. Also accepts "\0" decimal escape sequence. | |
| 479 uc32 ScanOctalEscape(uc32 c, int length); | |
| 480 | |
| 481 // Returns the location of the last seen octal literal. | 469 // Returns the location of the last seen octal literal. |
| 482 Location octal_position() const { return octal_pos_; } | 470 Location octal_position() const { return octal_pos_; } |
| 483 void clear_octal_position() { octal_pos_ = Location::invalid(); } | 471 void clear_octal_position() { octal_pos_ = Location::invalid(); } |
| 484 | 472 |
| 485 // Seek forward to the given position. This operation does not | 473 // Seek forward to the given position. This operation does not |
| 486 // work in general, for instance when there are pushed back | 474 // work in general, for instance when there are pushed back |
| 487 // characters, but works for seeking forward until simple delimiter | 475 // characters, but works for seeking forward until simple delimiter |
| 488 // tokens, which is what it is used for. | 476 // tokens, which is what it is used for. |
| 489 void SeekForward(int pos); | 477 void SeekForward(int pos); |
| 490 | 478 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 522 bool ScanRegExpFlags(); | 510 bool ScanRegExpFlags(); |
| 523 | 511 |
| 524 private: | 512 private: |
| 525 // The current and look-ahead token. | 513 // The current and look-ahead token. |
| 526 struct TokenDesc { | 514 struct TokenDesc { |
| 527 Token::Value token; | 515 Token::Value token; |
| 528 Location location; | 516 Location location; |
| 529 LiteralBuffer* literal_chars; | 517 LiteralBuffer* literal_chars; |
| 530 }; | 518 }; |
| 531 | 519 |
| 520 static const int kCharacterLookaheadBufferSize = 1; |
| 521 |
| 522 // Scans octal escape sequence. Also accepts "\0" decimal escape sequence. |
| 523 uc32 ScanOctalEscape(uc32 c, int length); |
| 524 |
| 532 // Call this after setting source_ to the input. | 525 // Call this after setting source_ to the input. |
| 533 void Init() { | 526 void Init() { |
| 534 // Set c0_ (one character ahead) | 527 // Set c0_ (one character ahead) |
| 535 STATIC_ASSERT(kCharacterLookaheadBufferSize == 1); | 528 STATIC_ASSERT(kCharacterLookaheadBufferSize == 1); |
| 536 Advance(); | 529 Advance(); |
| 537 // Initialize current_ to not refer to a literal. | 530 // Initialize current_ to not refer to a literal. |
| 538 current_.literal_chars = NULL; | 531 current_.literal_chars = NULL; |
| 539 } | 532 } |
| 540 | 533 |
| 541 // Literal buffer support | 534 // Literal buffer support |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 582 inline Token::Value Select(uc32 next, Token::Value then, Token::Value else_) { | 575 inline Token::Value Select(uc32 next, Token::Value then, Token::Value else_) { |
| 583 Advance(); | 576 Advance(); |
| 584 if (c0_ == next) { | 577 if (c0_ == next) { |
| 585 Advance(); | 578 Advance(); |
| 586 return then; | 579 return then; |
| 587 } else { | 580 } else { |
| 588 return else_; | 581 return else_; |
| 589 } | 582 } |
| 590 } | 583 } |
| 591 | 584 |
| 585 // Returns the literal string, if any, for the current token (the |
| 586 // token last returned by Next()). The string is 0-terminated. |
| 587 // Literal strings are collected for identifiers, strings, and |
| 588 // numbers. |
| 589 // These functions only give the correct result if the literal |
| 590 // was scanned between calls to StartLiteral() and TerminateLiteral(). |
| 591 Vector<const uint8_t> literal_one_byte_string() { |
| 592 ASSERT_NOT_NULL(current_.literal_chars); |
| 593 return current_.literal_chars->one_byte_literal(); |
| 594 } |
| 595 Vector<const uint16_t> literal_two_byte_string() { |
| 596 ASSERT_NOT_NULL(current_.literal_chars); |
| 597 return current_.literal_chars->two_byte_literal(); |
| 598 } |
| 599 bool is_literal_one_byte() { |
| 600 ASSERT_NOT_NULL(current_.literal_chars); |
| 601 return current_.literal_chars->is_one_byte(); |
| 602 } |
| 603 int literal_length() const { |
| 604 ASSERT_NOT_NULL(current_.literal_chars); |
| 605 return current_.literal_chars->length(); |
| 606 } |
| 607 // Returns the literal string for the next token (the token that |
| 608 // would be returned if Next() were called). |
| 609 Vector<const uint8_t> next_literal_one_byte_string() { |
| 610 ASSERT_NOT_NULL(next_.literal_chars); |
| 611 return next_.literal_chars->one_byte_literal(); |
| 612 } |
| 613 Vector<const uint16_t> next_literal_two_byte_string() { |
| 614 ASSERT_NOT_NULL(next_.literal_chars); |
| 615 return next_.literal_chars->two_byte_literal(); |
| 616 } |
| 617 bool is_next_literal_one_byte() { |
| 618 ASSERT_NOT_NULL(next_.literal_chars); |
| 619 return next_.literal_chars->is_one_byte(); |
| 620 } |
| 621 int next_literal_length() const { |
| 622 ASSERT_NOT_NULL(next_.literal_chars); |
| 623 return next_.literal_chars->length(); |
| 624 } |
| 625 |
| 592 uc32 ScanHexNumber(int expected_length); | 626 uc32 ScanHexNumber(int expected_length); |
| 593 | 627 |
| 594 // Scans a single JavaScript token. | 628 // Scans a single JavaScript token. |
| 595 void Scan(); | 629 void Scan(); |
| 596 | 630 |
| 597 bool SkipWhiteSpace(); | 631 bool SkipWhiteSpace(); |
| 598 Token::Value SkipSingleLineComment(); | 632 Token::Value SkipSingleLineComment(); |
| 599 Token::Value SkipMultiLineComment(); | 633 Token::Value SkipMultiLineComment(); |
| 600 // Scans a possible HTML comment -- begins with '<!'. | 634 // Scans a possible HTML comment -- begins with '<!'. |
| 601 Token::Value ScanHtmlComment(); | 635 Token::Value ScanHtmlComment(); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 658 bool harmony_numeric_literals_; | 692 bool harmony_numeric_literals_; |
| 659 }; | 693 }; |
| 660 | 694 |
| 661 | 695 |
| 662 #endif | 696 #endif |
| 663 | 697 |
| 664 | 698 |
| 665 } } // namespace v8::internal | 699 } } // namespace v8::internal |
| 666 | 700 |
| 667 #endif // V8_SCANNER_H_ | 701 #endif // V8_SCANNER_H_ |
| OLD | NEW |