| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 int beg_pos; | 60 int beg_pos; |
| 61 int end_pos; | 61 int end_pos; |
| 62 }; | 62 }; |
| 63 | 63 |
| 64 explicit ScannerBase(Isolate* isolate) | 64 explicit ScannerBase(Isolate* isolate) |
| 65 : isolate_(isolate), | 65 : isolate_(isolate), |
| 66 unicode_cache_(isolate->unicode_cache()), | 66 unicode_cache_(isolate->unicode_cache()), |
| 67 has_line_terminator_before_next_(true), | 67 has_line_terminator_before_next_(true), |
| 68 current_literal_(&literals_[0]), | 68 current_literal_(&literals_[0]), |
| 69 next_literal_(&literals_[1]), | 69 next_literal_(&literals_[1]), |
| 70 octal_pos_(Location::invalid()), | |
| 71 harmony_numeric_literals_(false), | 70 harmony_numeric_literals_(false), |
| 72 harmony_modules_(false), | 71 harmony_modules_(false), |
| 73 harmony_scoping_(false) { | 72 harmony_scoping_(false) { |
| 74 if (!scanners_) { | 73 if (!scanners_) { |
| 75 scanners_ = new std::set<ScannerBase*>(); | 74 scanners_ = new std::set<ScannerBase*>(); |
| 76 isolate->heap()->AddGCEpilogueCallback(&ScannerBase::UpdateBuffersAfterGC, | 75 isolate->heap()->AddGCEpilogueCallback(&ScannerBase::UpdateBuffersAfterGC, |
| 77 kGCTypeAll, false); | 76 kGCTypeAll, false); |
| 78 } | 77 } |
| 79 scanners_->insert(this); | 78 scanners_->insert(this); |
| 80 } | 79 } |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 return next_literal_->is_ascii; | 209 return next_literal_->is_ascii; |
| 211 } | 210 } |
| 212 | 211 |
| 213 bool is_next_contextual_keyword(Vector<const char> keyword) { | 212 bool is_next_contextual_keyword(Vector<const char> keyword) { |
| 214 if (!is_next_literal_ascii()) return false; | 213 if (!is_next_literal_ascii()) return false; |
| 215 Vector<const char> literal = next_literal_ascii_string(); | 214 Vector<const char> literal = next_literal_ascii_string(); |
| 216 return literal.length() == keyword.length() && | 215 return literal.length() == keyword.length() && |
| 217 (memcmp(literal.start(), keyword.start(), literal.length()) == 0); | 216 (memcmp(literal.start(), keyword.start(), literal.length()) == 0); |
| 218 } | 217 } |
| 219 | 218 |
| 220 // Returns the location of the last seen octal literal. | |
| 221 Location octal_position() const { return octal_pos_; } | |
| 222 void clear_octal_position() { octal_pos_ = Location::invalid(); } | |
| 223 | |
| 224 // Seek forward to the given position. This operation works for simple cases | 219 // Seek forward to the given position. This operation works for simple cases |
| 225 // such as seeking forward until simple delimiter tokens, which is what it is | 220 // such as seeking forward until simple delimiter tokens, which is what it is |
| 226 // used for. After this call, we will have the token at the given position as | 221 // used for. After this call, we will have the token at the given position as |
| 227 // the "next" token. The "current" token will be invalid. FIXME: for utf-8, | 222 // the "next" token. The "current" token will be invalid. FIXME: for utf-8, |
| 228 // we need to decide if pos is counted in characters or in bytes. | 223 // we need to decide if pos is counted in characters or in bytes. |
| 229 virtual void SeekForward(int pos) = 0; | 224 virtual void SeekForward(int pos) = 0; |
| 230 virtual void SetEnd(int pos) = 0; | 225 virtual void SetEnd(int pos) = 0; |
| 231 | 226 |
| 232 // Scans the input as a regular expression pattern, previous character(s) must | 227 // Scans the input as a regular expression pattern, previous character(s) must |
| 233 // be /(=). Returns true if a pattern is scanned. FIXME: this won't work for | 228 // be /(=). Returns true if a pattern is scanned. FIXME: this won't work for |
| 234 // utf-8 newlines. | 229 // utf-8 newlines. |
| 235 virtual bool ScanRegExpPattern(bool seen_equal) = 0; | 230 virtual bool ScanRegExpPattern(bool seen_equal) = 0; |
| 236 // Returns true if regexp flags are scanned (always since flags can | 231 // Returns true if regexp flags are scanned (always since flags can |
| 237 // be empty). | 232 // be empty). |
| 238 virtual bool ScanRegExpFlags() = 0; | 233 virtual bool ScanRegExpFlags() = 0; |
| 239 | 234 |
| 235 // Returns the location of the last seen octal literal. |
| 236 virtual Location octal_position() const = 0; |
| 237 virtual void clear_octal_position() = 0; |
| 238 |
| 240 protected: | 239 protected: |
| 241 struct TokenDesc { | 240 struct TokenDesc { |
| 242 Token::Value token; | 241 Token::Value token; |
| 243 int beg_pos; | 242 int beg_pos; |
| 244 int end_pos; | 243 int end_pos; |
| 245 bool has_escapes; | 244 bool has_escapes; |
| 246 }; | 245 }; |
| 247 | 246 |
| 248 struct LiteralDesc { | 247 struct LiteralDesc { |
| 249 int beg_pos; | 248 int beg_pos; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 266 | 265 |
| 267 bool has_line_terminator_before_next_; | 266 bool has_line_terminator_before_next_; |
| 268 | 267 |
| 269 TokenDesc current_; // desc for current token (as returned by Next()) | 268 TokenDesc current_; // desc for current token (as returned by Next()) |
| 270 TokenDesc next_; // desc for next token (one token look-ahead) | 269 TokenDesc next_; // desc for next token (one token look-ahead) |
| 271 | 270 |
| 272 LiteralDesc* current_literal_; | 271 LiteralDesc* current_literal_; |
| 273 LiteralDesc* next_literal_; | 272 LiteralDesc* next_literal_; |
| 274 LiteralDesc literals_[2]; | 273 LiteralDesc literals_[2]; |
| 275 | 274 |
| 276 Location octal_pos_; | |
| 277 | |
| 278 bool harmony_numeric_literals_; | 275 bool harmony_numeric_literals_; |
| 279 bool harmony_modules_; | 276 bool harmony_modules_; |
| 280 bool harmony_scoping_; | 277 bool harmony_scoping_; |
| 281 | 278 |
| 282 private: | 279 private: |
| 283 static std::set<ScannerBase*>* scanners_; | 280 static std::set<ScannerBase*>* scanners_; |
| 284 }; | 281 }; |
| 285 | 282 |
| 286 | 283 |
| 287 template<typename Char> | 284 template<typename Char> |
| 288 class ExperimentalScanner : public ScannerBase { | 285 class ExperimentalScanner : public ScannerBase { |
| 289 public: | 286 public: |
| 290 explicit ExperimentalScanner( | 287 explicit ExperimentalScanner( |
| 291 Handle<String> source, | 288 Handle<String> source, |
| 292 Isolate* isolate) | 289 Isolate* isolate) |
| 293 : ScannerBase(isolate), | 290 : ScannerBase(isolate), |
| 294 source_handle_(source), | 291 source_handle_(source), |
| 295 buffer_(NULL), | 292 buffer_(NULL), |
| 296 buffer_end_(NULL), | 293 buffer_end_(NULL), |
| 297 start_(NULL), | 294 start_(NULL), |
| 298 cursor_(NULL), | 295 cursor_(NULL), |
| 299 marker_(NULL) { | 296 marker_(NULL), |
| 297 last_octal_end_(NULL) { |
| 300 ASSERT(source->IsFlat()); | 298 ASSERT(source->IsFlat()); |
| 301 SetBufferBasedOnHandle(); | 299 SetBufferBasedOnHandle(); |
| 302 Scan(); | 300 Scan(); |
| 303 } | 301 } |
| 304 | 302 |
| 305 virtual ~ExperimentalScanner() { } | 303 virtual ~ExperimentalScanner() { } |
| 306 | 304 |
| 307 protected: | |
| 308 virtual void Scan(); | |
| 309 virtual void SeekForward(int pos); | 305 virtual void SeekForward(int pos); |
| 310 virtual void SetEnd(int pos); | 306 virtual void SetEnd(int pos); |
| 311 virtual bool ScanRegExpPattern(bool seen_equal); | 307 virtual bool ScanRegExpPattern(bool seen_equal); |
| 312 virtual bool ScanRegExpFlags(); | 308 virtual bool ScanRegExpFlags(); |
| 309 virtual Location octal_position() const; |
| 310 virtual void clear_octal_position() { |
| 311 last_octal_end_ = NULL; |
| 312 } |
| 313 |
| 314 protected: |
| 315 virtual void Scan(); |
| 313 | 316 |
| 314 virtual void SetBufferBasedOnHandle() { | 317 virtual void SetBufferBasedOnHandle() { |
| 315 // We get a raw pointer from the Handle, but we also update it every time | 318 // We get a raw pointer from the Handle, but we also update it every time |
| 316 // there is a GC, so it is safe. | 319 // there is a GC, so it is safe. |
| 317 DisallowHeapAllocation no_gc; | 320 DisallowHeapAllocation no_gc; |
| 318 const Char* new_buffer = GetNewBufferBasedOnHandle(); | 321 const Char* new_buffer = GetNewBufferBasedOnHandle(); |
| 319 if (new_buffer != buffer_) { | 322 if (new_buffer != buffer_) { |
| 320 int start_offset = start_ - buffer_; | 323 int start_offset = start_ - buffer_; |
| 321 int cursor_offset = cursor_ - buffer_; | 324 int cursor_offset = cursor_ - buffer_; |
| 322 int marker_offset = marker_ - buffer_; | 325 int marker_offset = marker_ - buffer_; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 const Char* ScanEscape(const Char* start, | 359 const Char* ScanEscape(const Char* start, |
| 357 const Char* end, | 360 const Char* end, |
| 358 LiteralBuffer* literal); | 361 LiteralBuffer* literal); |
| 359 | 362 |
| 360 Handle<String> source_handle_; | 363 Handle<String> source_handle_; |
| 361 const Char* buffer_; | 364 const Char* buffer_; |
| 362 const Char* buffer_end_; | 365 const Char* buffer_end_; |
| 363 const Char* start_; | 366 const Char* start_; |
| 364 const Char* cursor_; | 367 const Char* cursor_; |
| 365 const Char* marker_; | 368 const Char* marker_; |
| 369 |
| 370 // Where we have seen the last octal number or an octal escape inside a |
| 371 // string. Used by octal_position(). |
| 372 const Char* last_octal_end_; |
| 366 }; | 373 }; |
| 367 | 374 |
| 368 | 375 |
| 369 template<typename Char> | 376 template<typename Char> |
| 370 void ExperimentalScanner<Char>::SeekForward(int pos) { | 377 void ExperimentalScanner<Char>::SeekForward(int pos) { |
| 371 cursor_ = buffer_ + pos; | 378 cursor_ = buffer_ + pos; |
| 372 start_ = cursor_; | 379 start_ = cursor_; |
| 373 marker_ = cursor_; | 380 marker_ = cursor_; |
| 374 has_line_terminator_before_next_ = false; | 381 has_line_terminator_before_next_ = false; |
| 375 Scan(); // Fills in next_. | 382 Scan(); // Fills in next_. |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 481 const Char* start, const Char* end, uc32* result) { | 488 const Char* start, const Char* end, uc32* result) { |
| 482 uc32 x = *result - '0'; | 489 uc32 x = *result - '0'; |
| 483 const Char* cursor; | 490 const Char* cursor; |
| 484 for (cursor = start; cursor < end; cursor++) { | 491 for (cursor = start; cursor < end; cursor++) { |
| 485 int d = *cursor - '0'; | 492 int d = *cursor - '0'; |
| 486 if (d < 0 || d > 7) break; | 493 if (d < 0 || d > 7) break; |
| 487 int nx = x * 8 + d; | 494 int nx = x * 8 + d; |
| 488 if (nx >= 256) break; | 495 if (nx >= 256) break; |
| 489 x = nx; | 496 x = nx; |
| 490 } | 497 } |
| 491 // Anything except '\0' is an octal escape sequence, illegal in strict mode. | |
| 492 // Remember the position of octal escape sequences so that an error | |
| 493 // can be reported later (in strict mode). | |
| 494 // We don't report the error immediately, because the octal escape can | |
| 495 // occur before the "use strict" directive. | |
| 496 if (*result != '0' || cursor > start) { | |
| 497 octal_pos_ = Location(start - 1 - buffer_, cursor - 1 - buffer_); | |
| 498 } | |
| 499 *result = x; | 498 *result = x; |
| 500 return cursor; | 499 return cursor; |
| 501 } | 500 } |
| 502 | 501 |
| 503 | 502 |
| 504 template<typename Char> | 503 template<typename Char> |
| 505 bool ExperimentalScanner<Char>::ScanLiteralUnicodeEscape() { | 504 bool ExperimentalScanner<Char>::ScanLiteralUnicodeEscape() { |
| 506 ASSERT(cursor_ < buffer_end_); | 505 ASSERT(cursor_ < buffer_end_); |
| 507 Char primary_char = *(cursor_); | 506 Char primary_char = *(cursor_); |
| 508 ASSERT(primary_char == '\\'); | 507 ASSERT(primary_char == '\\'); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 586 cursor = ScanOctalEscape(cursor, end, &c); break; | 585 cursor = ScanOctalEscape(cursor, end, &c); break; |
| 587 } | 586 } |
| 588 | 587 |
| 589 // According to ECMA-262, section 7.8.4, characters not covered by the | 588 // According to ECMA-262, section 7.8.4, characters not covered by the |
| 590 // above cases should be illegal, but they are commonly handled as | 589 // above cases should be illegal, but they are commonly handled as |
| 591 // non-escaped characters by JS VMs. | 590 // non-escaped characters by JS VMs. |
| 592 literal->AddChar(c); | 591 literal->AddChar(c); |
| 593 return cursor; | 592 return cursor; |
| 594 } | 593 } |
| 595 | 594 |
| 595 template<typename Char> |
| 596 ScannerBase::Location ExperimentalScanner<Char>::octal_position() const { |
| 597 if (!last_octal_end_) |
| 598 return Location::invalid(); |
| 599 // The last octal might be an octal escape or an octal number. Whichever it |
| 600 // is, we'll find the start by just scanning back until we hit a non-octal |
| 601 // character. |
| 602 const Char* temp_cursor = last_octal_end_ - 1; |
| 603 while (temp_cursor >= buffer_ && *temp_cursor >= '0' && *temp_cursor <= '7') |
| 604 --temp_cursor; |
| 605 return Location(temp_cursor - buffer_ + 1, last_octal_end_ - buffer_); |
| 606 } |
| 596 | 607 |
| 597 } } | 608 } } |
| 598 | 609 |
| 599 #endif // V8_LEXER_EXPERIMENTAL_SCANNER_H | 610 #endif // V8_LEXER_EXPERIMENTAL_SCANNER_H |
| OLD | NEW |