Chromium Code Reviews| 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, true); |
|
Ivan Posva
2013/09/25 16:31:50
Can't you pass string_is_multiline_ here? As this
hausner
2013/09/25 17:06:49
Simplified as you suggested.
| |
| 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 is_first_line) { |
| 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 (string_is_multiline_ && | |
| 596 is_first_line && | |
| 597 (string_chars.Last() == '\n')) { | |
| 598 bool whitespace_only = true; | |
| 599 // Last character is the newline, don't inspect it. | |
| 600 const intptr_t len = string_chars.length() - 1; | |
| 601 for (int i = 0; i < len; i++) { | |
| 602 int32_t ch = string_chars[i]; | |
| 603 if ((ch != ' ') && (ch != '\t')) { | |
|
Ivan Posva
2013/09/25 16:31:50
Please clarify the definition of white-space defin
hausner
2013/09/25 17:06:49
Will do. I used the WHITESPACE production in the s
| |
| 604 // Non-whitespace character, keep the first line. | |
| 605 whitespace_only = false; | |
| 606 break; | |
| 607 } | |
| 608 } | |
| 609 if (whitespace_only) { | |
| 610 string_chars.Clear(); // Discard characters on first line. | |
| 611 } | |
| 612 is_first_line = false; | |
| 613 } | |
| 598 ReadChar(); | 614 ReadChar(); |
| 599 } | 615 } |
| 600 } | 616 } |
| 601 | 617 |
| 602 | 618 |
| 603 void Scanner::Scan() { | 619 void Scanner::Scan() { |
| 604 newline_seen_ = false; | 620 newline_seen_ = false; |
| 605 | 621 |
| 606 do { | 622 do { |
| 607 if (!IsScanningString()) { | 623 if (!IsScanningString()) { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 620 current_token_.kind = Token::kINTERPOL_VAR; | 636 current_token_.kind = Token::kINTERPOL_VAR; |
| 621 } else if (c0_ == '{') { | 637 } else if (c0_ == '{') { |
| 622 Recognize(Token::kINTERPOL_START); | 638 Recognize(Token::kINTERPOL_START); |
| 623 PushContext(); | 639 PushContext(); |
| 624 } else { | 640 } else { |
| 625 ErrorMsg("illegal character after $ in string interpolation"); | 641 ErrorMsg("illegal character after $ in string interpolation"); |
| 626 EndStringLiteral(); | 642 EndStringLiteral(); |
| 627 break; | 643 break; |
| 628 } | 644 } |
| 629 } else { | 645 } else { |
| 630 ScanLiteralStringChars(false); | 646 ScanLiteralStringChars(false, false); |
| 631 } | 647 } |
| 632 break; | 648 break; |
| 633 } | 649 } |
| 634 switch (c0_) { | 650 switch (c0_) { |
| 635 case '\0': | 651 case '\0': |
| 636 current_token_.kind = Token::kEOS; | 652 current_token_.kind = Token::kEOS; |
| 637 break; | 653 break; |
| 638 | 654 |
| 639 case '+': // + ++ += | 655 case '+': // + ++ += |
| 640 Recognize(Token::kADD); | 656 Recognize(Token::kADD); |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 930 "%c%#" Px "", kPrivateKeySeparator, key_value); | 946 "%c%#" Px "", kPrivateKeySeparator, key_value); |
| 931 const String& result = String::Handle(String::New(private_key, Heap::kOld)); | 947 const String& result = String::Handle(String::New(private_key, Heap::kOld)); |
| 932 return result.raw(); | 948 return result.raw(); |
| 933 } | 949 } |
| 934 | 950 |
| 935 | 951 |
| 936 void Scanner::InitOnce() { | 952 void Scanner::InitOnce() { |
| 937 } | 953 } |
| 938 | 954 |
| 939 } // namespace dart | 955 } // namespace dart |
| OLD | NEW |