| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/scanner.h" | 5 #include "vm/scanner.h" |
| 6 | 6 |
| 7 #include "platform/assert.h" | 7 #include "platform/assert.h" |
| 8 #include "vm/flags.h" | 8 #include "vm/flags.h" |
| 9 #include "vm/object.h" | 9 #include "vm/object.h" |
| 10 #include "vm/object_store.h" | 10 #include "vm/object_store.h" |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 SkipLine(); | 415 SkipLine(); |
| 416 } | 416 } |
| 417 | 417 |
| 418 | 418 |
| 419 void Scanner::ScanLiteralString(bool is_raw) { | 419 void Scanner::ScanLiteralString(bool is_raw) { |
| 420 ASSERT(!IsScanningString()); | 420 ASSERT(!IsScanningString()); |
| 421 ASSERT(c0_ == '"' || c0_ == '\''); | 421 ASSERT(c0_ == '"' || c0_ == '\''); |
| 422 | 422 |
| 423 // Entering string scanning mode. | 423 // Entering string scanning mode. |
| 424 BeginStringLiteral(c0_); | 424 BeginStringLiteral(c0_); |
| 425 string_is_multiline_ = (LookaheadChar(1) == c0_) && | 425 ReadChar(); |
| 426 (LookaheadChar(2) == c0_); | |
| 427 | 426 |
| 428 ReadChar(); // Skip opening delimiter. | 427 if ((c0_ == string_delimiter_) && (LookaheadChar(1) == string_delimiter_)) { |
| 429 if (string_is_multiline_) { | 428 string_is_multiline_ = true; |
| 430 ReadChar(); // Skip two additional string delimiters. | 429 ReadChar(); // Skip two additional string delimiters. |
| 431 ReadChar(); | 430 ReadChar(); |
| 432 if (c0_ == '\n') { | |
| 433 // Skip first character of multiline string if it is a newline. | |
| 434 ReadChar(); | |
| 435 } | |
| 436 } | 431 } |
| 437 ScanLiteralStringChars(is_raw); | 432 ScanLiteralStringChars(is_raw, string_is_multiline_); |
| 438 } | 433 } |
| 439 | 434 |
| 440 | 435 |
| 441 bool Scanner::ScanHexDigits(int digits, int32_t* value) { | 436 bool Scanner::ScanHexDigits(int digits, int32_t* value) { |
| 442 *value = 0; | 437 *value = 0; |
| 443 for (int i = 0; i < digits; ++i) { | 438 for (int i = 0; i < digits; ++i) { |
| 444 ReadChar(); | 439 ReadChar(); |
| 445 if (!IsHexDigit(c0_)) { | 440 if (!IsHexDigit(c0_)) { |
| 446 ErrorMsg("too few hexadecimal digits"); | 441 ErrorMsg("too few hexadecimal digits"); |
| 447 return false; | 442 return false; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 490 } | 485 } |
| 491 } | 486 } |
| 492 if (is_valid && | 487 if (is_valid && |
| 493 ((Utf::IsOutOfRange(*code_point) || | 488 ((Utf::IsOutOfRange(*code_point) || |
| 494 (Utf16::IsSurrogate(*code_point))))) { | 489 (Utf16::IsSurrogate(*code_point))))) { |
| 495 ErrorMsg("invalid code point"); | 490 ErrorMsg("invalid code point"); |
| 496 } | 491 } |
| 497 } | 492 } |
| 498 | 493 |
| 499 | 494 |
| 500 void Scanner::ScanLiteralStringChars(bool is_raw) { | 495 void Scanner::ScanLiteralStringChars(bool is_raw, bool remove_whitespace) { |
| 501 GrowableArray<int32_t> string_chars(64); | 496 GrowableArray<int32_t> string_chars(64); |
| 502 | 497 |
| 503 ASSERT(IsScanningString()); | 498 ASSERT(IsScanningString()); |
| 504 // We are at the first character of a string literal piece. A string literal | 499 // We are at the first character of a string literal piece. A string literal |
| 505 // can be broken up into multiple pieces by string interpolation. | 500 // can be broken up into multiple pieces by string interpolation. |
| 506 while (true) { | 501 while (true) { |
| 507 if ((c0_ == '\0') || ((c0_ == '\n') && !string_is_multiline_)) { | 502 if ((c0_ == '\0') || ((c0_ == '\n') && !string_is_multiline_)) { |
| 508 ErrorMsg("unterminated string literal"); | 503 ErrorMsg("unterminated string literal"); |
| 509 EndStringLiteral(); | 504 EndStringLiteral(); |
| 510 return; | 505 return; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 588 int32_t ch1 = c0_; | 583 int32_t ch1 = c0_; |
| 589 if (Utf16::IsLeadSurrogate(ch1)) { | 584 if (Utf16::IsLeadSurrogate(ch1)) { |
| 590 const int32_t ch2 = LookaheadChar(1); | 585 const int32_t ch2 = LookaheadChar(1); |
| 591 if (Utf16::IsTrailSurrogate(ch2)) { | 586 if (Utf16::IsTrailSurrogate(ch2)) { |
| 592 ch1 = Utf16::Decode(ch1, ch2); | 587 ch1 = Utf16::Decode(ch1, ch2); |
| 593 ReadChar(); | 588 ReadChar(); |
| 594 } | 589 } |
| 595 } | 590 } |
| 596 string_chars.Add(ch1); | 591 string_chars.Add(ch1); |
| 597 } | 592 } |
| 593 // The first line of a multi-line string is discarded if it only |
| 594 // contains whitespace. |
| 595 if (remove_whitespace && (string_chars.Last() == '\n')) { |
| 596 bool whitespace_only = true; |
| 597 // Last character is the newline, don't inspect it. |
| 598 const intptr_t len = string_chars.length() - 1; |
| 599 for (int i = 0; i < len; i++) { |
| 600 int32_t ch = string_chars[i]; |
| 601 if ((ch != ' ') && (ch != '\t')) { |
| 602 // Non-whitespace character, keep the first line. |
| 603 whitespace_only = false; |
| 604 break; |
| 605 } |
| 606 } |
| 607 if (whitespace_only) { |
| 608 string_chars.Clear(); // Discard characters on first line. |
| 609 } |
| 610 remove_whitespace = false; |
| 611 } |
| 598 ReadChar(); | 612 ReadChar(); |
| 599 } | 613 } |
| 600 } | 614 } |
| 601 | 615 |
| 602 | 616 |
| 603 void Scanner::Scan() { | 617 void Scanner::Scan() { |
| 604 newline_seen_ = false; | 618 newline_seen_ = false; |
| 605 | 619 |
| 606 do { | 620 do { |
| 607 if (!IsScanningString()) { | 621 if (!IsScanningString()) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 620 current_token_.kind = Token::kINTERPOL_VAR; | 634 current_token_.kind = Token::kINTERPOL_VAR; |
| 621 } else if (c0_ == '{') { | 635 } else if (c0_ == '{') { |
| 622 Recognize(Token::kINTERPOL_START); | 636 Recognize(Token::kINTERPOL_START); |
| 623 PushContext(); | 637 PushContext(); |
| 624 } else { | 638 } else { |
| 625 ErrorMsg("illegal character after $ in string interpolation"); | 639 ErrorMsg("illegal character after $ in string interpolation"); |
| 626 EndStringLiteral(); | 640 EndStringLiteral(); |
| 627 break; | 641 break; |
| 628 } | 642 } |
| 629 } else { | 643 } else { |
| 630 ScanLiteralStringChars(false); | 644 ScanLiteralStringChars(false, false); |
| 631 } | 645 } |
| 632 break; | 646 break; |
| 633 } | 647 } |
| 634 switch (c0_) { | 648 switch (c0_) { |
| 635 case '\0': | 649 case '\0': |
| 636 current_token_.kind = Token::kEOS; | 650 current_token_.kind = Token::kEOS; |
| 637 break; | 651 break; |
| 638 | 652 |
| 639 case '+': // + ++ += | 653 case '+': // + ++ += |
| 640 Recognize(Token::kADD); | 654 Recognize(Token::kADD); |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 930 "%c%#" Px "", kPrivateKeySeparator, key_value); | 944 "%c%#" Px "", kPrivateKeySeparator, key_value); |
| 931 const String& result = String::Handle(String::New(private_key, Heap::kOld)); | 945 const String& result = String::Handle(String::New(private_key, Heap::kOld)); |
| 932 return result.raw(); | 946 return result.raw(); |
| 933 } | 947 } |
| 934 | 948 |
| 935 | 949 |
| 936 void Scanner::InitOnce() { | 950 void Scanner::InitOnce() { |
| 937 } | 951 } |
| 938 | 952 |
| 939 } // namespace dart | 953 } // namespace dart |
| OLD | NEW |