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/dart.h" | 8 #include "vm/dart.h" |
| 9 #include "vm/flags.h" | 9 #include "vm/flags.h" |
| 10 #include "vm/object.h" | 10 #include "vm/object.h" |
| 11 #include "vm/object_store.h" | 11 #include "vm/object_store.h" |
| 12 #include "vm/symbols.h" | 12 #include "vm/symbols.h" |
| 13 #include "vm/thread.h" | 13 #include "vm/thread.h" |
| 14 #include "vm/token.h" | 14 #include "vm/token.h" |
| 15 #include "vm/unicode.h" | 15 #include "vm/unicode.h" |
| 16 | 16 |
| 17 namespace dart { | 17 namespace dart { |
| 18 | 18 |
| 19 DEFINE_FLAG(bool, print_tokens, false, "Print scanned tokens."); | 19 DEFINE_FLAG(bool, print_tokens, false, "Print scanned tokens."); |
| 20 | 20 |
| 21 | 21 |
| 22 // Quick access to the locally defined isolate() method. | |
| 23 #define I (isolate()) | |
| 24 | |
| 25 | |
| 26 class ScanContext : public ZoneAllocated { | |
| 27 public: | |
| 28 explicit ScanContext(Scanner* scanner) | |
| 29 : next_(scanner->saved_context_), | |
| 30 string_delimiter_(scanner->string_delimiter_), | |
| 31 string_is_multiline_(scanner->string_is_multiline_), | |
| 32 brace_level_(scanner->brace_level_) {} | |
| 33 | |
| 34 void CopyTo(Scanner* scanner) { | |
| 35 scanner->string_delimiter_ = string_delimiter_; | |
| 36 scanner->string_is_multiline_ = string_is_multiline_; | |
| 37 scanner->brace_level_ = brace_level_; | |
| 38 } | |
| 39 | |
| 40 ScanContext* next() const { return next_; } | |
| 41 | |
| 42 private: | |
|
hausner
2014/06/05 21:58:54
IMO it does not really make much sense to make thi
srdjan
2014/06/05 22:03:51
Discussed offline, leaving it as it is.
| |
| 43 ScanContext* next_; | |
| 44 const char string_delimiter_; | |
| 45 const bool string_is_multiline_; | |
| 46 const int brace_level_; | |
| 47 }; | |
| 48 | |
| 49 | |
| 22 Scanner::KeywordTable Scanner::keywords_[Token::kNumKeywords]; | 50 Scanner::KeywordTable Scanner::keywords_[Token::kNumKeywords]; |
| 23 int Scanner::keywords_char_offset_[Scanner::kNumLowercaseChars]; | 51 int Scanner::keywords_char_offset_[Scanner::kNumLowercaseChars]; |
| 24 | 52 |
| 25 | 53 |
| 26 void Scanner::Reset() { | 54 void Scanner::Reset() { |
| 27 // Non-changing newline properties. | 55 // Non-changing newline properties. |
| 28 newline_token_.kind = Token::kNEWLINE; | 56 newline_token_.kind = Token::kNEWLINE; |
| 29 newline_token_.literal = NULL; | 57 newline_token_.literal = NULL; |
| 30 // We don't preserve the column information. | 58 // We don't preserve the column information. |
| 31 newline_token_.position.column = 0; | 59 newline_token_.position.column = 0; |
| 32 | 60 |
| 33 // Non-changing empty string token properties. | 61 // Non-changing empty string token properties. |
| 34 empty_string_token_.kind = Token::kSTRING; | 62 empty_string_token_.kind = Token::kSTRING; |
| 35 empty_string_token_.literal = &Symbols::Empty(); | 63 empty_string_token_.literal = &Symbols::Empty(); |
| 36 empty_string_token_.position.column = 0; | 64 empty_string_token_.position.column = 0; |
| 37 | 65 |
| 38 lookahead_pos_ = -1; | 66 lookahead_pos_ = -1; |
| 39 token_start_ = 0; | 67 token_start_ = 0; |
| 40 c0_ = '\0'; | 68 c0_ = '\0'; |
| 41 newline_seen_ = false; | 69 newline_seen_ = false; |
| 42 prev_token_line_ = 1; | 70 prev_token_line_ = 1; |
| 43 while (saved_context_ != NULL) { | 71 saved_context_ = NULL; |
| 44 ScanContext* ctx = saved_context_; | |
| 45 saved_context_ = ctx->next; | |
| 46 delete ctx; | |
| 47 } | |
| 48 string_delimiter_ = '\0'; | 72 string_delimiter_ = '\0'; |
| 49 string_is_multiline_ = false; | 73 string_is_multiline_ = false; |
| 50 brace_level_ = 0; | 74 brace_level_ = 0; |
| 51 c0_pos_.line = 1; | 75 c0_pos_.line = 1; |
| 52 c0_pos_.column = 0; | 76 c0_pos_.column = 0; |
| 53 ReadChar(); | 77 ReadChar(); |
| 54 } | 78 } |
| 55 | 79 |
| 56 | 80 |
| 57 Scanner::Scanner(const String& src, const String& private_key) | 81 Scanner::Scanner(const String& src, const String& private_key) |
| 58 : source_(src), | 82 : source_(src), |
| 59 source_length_(src.Length()), | 83 source_length_(src.Length()), |
| 60 saved_context_(NULL), | 84 saved_context_(NULL), |
| 61 private_key_(String::ZoneHandle(private_key.raw())), | 85 private_key_(String::ZoneHandle(private_key.raw())), |
| 62 char_at_func_(src.CharAtFunc()), | 86 char_at_func_(src.CharAtFunc()), |
| 63 isolate_(Isolate::Current()) { | 87 isolate_(Isolate::Current()) { |
| 64 Reset(); | 88 Reset(); |
| 65 } | 89 } |
| 66 | 90 |
| 67 | 91 |
| 68 Scanner::~Scanner() { | 92 Scanner::~Scanner() {} |
| 69 while (saved_context_ != NULL) { | |
| 70 ScanContext* ctx = saved_context_; | |
| 71 saved_context_ = ctx->next; | |
| 72 delete ctx; | |
| 73 } | |
| 74 } | |
| 75 | 93 |
| 76 | 94 |
| 77 void Scanner::ErrorMsg(const char* msg) { | 95 void Scanner::ErrorMsg(const char* msg) { |
| 78 current_token_.kind = Token::kERROR; | 96 current_token_.kind = Token::kERROR; |
| 79 current_token_.literal = &String::ZoneHandle(Symbols::New(msg)); | 97 current_token_.literal = &String::ZoneHandle(I, Symbols::New(msg)); |
| 80 current_token_.position = c0_pos_; | 98 current_token_.position = c0_pos_; |
| 81 token_start_ = lookahead_pos_; | 99 token_start_ = lookahead_pos_; |
| 82 current_token_.offset = lookahead_pos_; | 100 current_token_.offset = lookahead_pos_; |
| 83 } | 101 } |
| 84 | 102 |
| 85 | 103 |
| 86 void Scanner::PushContext() { | 104 void Scanner::PushContext() { |
| 87 ScanContext* ctx = new ScanContext; | 105 ScanContext* ctx = new(I) ScanContext(this); |
| 88 ctx->next = saved_context_; | |
| 89 saved_context_ = ctx; | 106 saved_context_ = ctx; |
| 90 ctx->string_delimiter = string_delimiter_; | |
| 91 ctx->string_is_multiline = string_is_multiline_; | |
| 92 ctx->brace_level = brace_level_; | |
| 93 string_delimiter_ = '\0'; | 107 string_delimiter_ = '\0'; |
| 94 string_is_multiline_ = false; | 108 string_is_multiline_ = false; |
| 95 brace_level_ = 1; // Account for the opening ${ token. | 109 brace_level_ = 1; // Account for the opening ${ token. |
| 96 } | 110 } |
| 97 | 111 |
| 98 | 112 |
| 99 void Scanner::PopContext() { | 113 void Scanner::PopContext() { |
| 100 ASSERT(saved_context_ != NULL); | 114 ASSERT(saved_context_ != NULL); |
| 101 ASSERT(brace_level_ == 0); | 115 ASSERT(brace_level_ == 0); |
| 102 ASSERT(string_delimiter_ == '\0'); | 116 ASSERT(string_delimiter_ == '\0'); |
| 103 ScanContext* ctx = saved_context_; | 117 ScanContext* ctx = saved_context_; |
| 104 saved_context_ = ctx->next; | 118 ctx->CopyTo(this); |
| 105 string_delimiter_ = ctx->string_delimiter; | 119 saved_context_ = ctx->next(); |
| 106 ASSERT(string_delimiter_ != '\0'); | 120 ASSERT(string_delimiter_ != '\0'); |
| 107 string_is_multiline_ = ctx->string_is_multiline; | |
| 108 brace_level_ = ctx->brace_level; | |
| 109 delete ctx; | |
| 110 } | 121 } |
| 111 | 122 |
| 112 | 123 |
| 113 void Scanner::BeginStringLiteral(const char delimiter) { | 124 void Scanner::BeginStringLiteral(const char delimiter) { |
| 114 string_delimiter_ = delimiter; | 125 string_delimiter_ = delimiter; |
| 115 } | 126 } |
| 116 | 127 |
| 117 | 128 |
| 118 void Scanner::EndStringLiteral() { | 129 void Scanner::EndStringLiteral() { |
| 119 string_delimiter_ = '\0'; | 130 string_delimiter_ = '\0'; |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 311 return; | 322 return; |
| 312 } | 323 } |
| 313 } | 324 } |
| 314 i++; | 325 i++; |
| 315 } | 326 } |
| 316 } | 327 } |
| 317 | 328 |
| 318 // We did not read a keyword. | 329 // We did not read a keyword. |
| 319 current_token_.kind = Token::kIDENT; | 330 current_token_.kind = Token::kIDENT; |
| 320 String& literal = | 331 String& literal = |
| 321 String::ZoneHandle(Symbols::New(source_, ident_pos, ident_length)); | 332 String::ZoneHandle(I, Symbols::New(source_, ident_pos, ident_length)); |
| 322 if (ident_char0 == Library::kPrivateIdentifierStart) { | 333 if (ident_char0 == Library::kPrivateIdentifierStart) { |
| 323 // Private identifiers are mangled on a per library basis. | 334 // Private identifiers are mangled on a per library basis. |
| 324 literal = String::Concat(literal, private_key_); | 335 literal = String::Concat(literal, private_key_); |
| 325 literal = Symbols::New(literal); | 336 literal = Symbols::New(literal); |
| 326 } | 337 } |
| 327 current_token_.literal = &literal; | 338 current_token_.literal = &literal; |
| 328 } | 339 } |
| 329 | 340 |
| 330 | 341 |
| 331 // Parse integer or double number literal of format: | 342 // Parse integer or double number literal of format: |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 369 ErrorMsg("missing exponent digits"); | 380 ErrorMsg("missing exponent digits"); |
| 370 return; | 381 return; |
| 371 } | 382 } |
| 372 while (IsDecimalDigit(c0_)) { | 383 while (IsDecimalDigit(c0_)) { |
| 373 ReadChar(); | 384 ReadChar(); |
| 374 } | 385 } |
| 375 } | 386 } |
| 376 } | 387 } |
| 377 if (current_token_.kind != Token::kILLEGAL) { | 388 if (current_token_.kind != Token::kILLEGAL) { |
| 378 intptr_t len = lookahead_pos_ - token_start_; | 389 intptr_t len = lookahead_pos_ - token_start_; |
| 379 String& str = String::ZoneHandle( | 390 String& str = String::ZoneHandle(I, |
| 380 String::SubString(source_, token_start_, len, Heap::kOld)); | 391 String::SubString(source_, token_start_, len, Heap::kOld)); |
| 381 str = Symbols::New(str); | 392 str = Symbols::New(str); |
| 382 current_token_.literal = &str; | 393 current_token_.literal = &str; |
| 383 } | 394 } |
| 384 } | 395 } |
| 385 | 396 |
| 386 | 397 |
| 387 void Scanner::SkipLine() { | 398 void Scanner::SkipLine() { |
| 388 while (c0_ != '\n' && c0_ != '\0') { | 399 while (c0_ != '\n' && c0_ != '\0') { |
| 389 ReadChar(); | 400 ReadChar(); |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 524 return; | 535 return; |
| 525 } | 536 } |
| 526 escape_char = c0_; | 537 escape_char = c0_; |
| 527 break; | 538 break; |
| 528 } | 539 } |
| 529 string_chars.Add(escape_char); | 540 string_chars.Add(escape_char); |
| 530 } else if (c0_ == '$' && !is_raw) { | 541 } else if (c0_ == '$' && !is_raw) { |
| 531 // Scanned a string piece. | 542 // Scanned a string piece. |
| 532 ASSERT(string_chars.data() != NULL); | 543 ASSERT(string_chars.data() != NULL); |
| 533 // Strings are canonicalized: Allocate a symbol. | 544 // Strings are canonicalized: Allocate a symbol. |
| 534 current_token_.literal = &String::ZoneHandle( | 545 current_token_.literal = &String::ZoneHandle(I, |
| 535 Symbols::FromUTF32(string_chars.data(), string_chars.length())); | 546 Symbols::FromUTF32(string_chars.data(), string_chars.length())); |
| 536 // Preserve error tokens. | 547 // Preserve error tokens. |
| 537 if (current_token_.kind != Token::kERROR) { | 548 if (current_token_.kind != Token::kERROR) { |
| 538 current_token_.kind = Token::kSTRING; | 549 current_token_.kind = Token::kSTRING; |
| 539 } | 550 } |
| 540 return; | 551 return; |
| 541 } else if (c0_ == string_delimiter_) { | 552 } else if (c0_ == string_delimiter_) { |
| 542 // Check if we are at the end of the string literal. | 553 // Check if we are at the end of the string literal. |
| 543 if (!string_is_multiline_ || | 554 if (!string_is_multiline_ || |
| 544 ((LookaheadChar(1) == string_delimiter_) && | 555 ((LookaheadChar(1) == string_delimiter_) && |
| 545 (LookaheadChar(2) == string_delimiter_))) { | 556 (LookaheadChar(2) == string_delimiter_))) { |
| 546 if (string_is_multiline_) { | 557 if (string_is_multiline_) { |
| 547 ReadChar(); // Skip two string delimiters. | 558 ReadChar(); // Skip two string delimiters. |
| 548 ReadChar(); | 559 ReadChar(); |
| 549 } | 560 } |
| 550 // Preserve error tokens. | 561 // Preserve error tokens. |
| 551 if (current_token_.kind == Token::kERROR) { | 562 if (current_token_.kind == Token::kERROR) { |
| 552 ReadChar(); | 563 ReadChar(); |
| 553 } else { | 564 } else { |
| 554 Recognize(Token::kSTRING); | 565 Recognize(Token::kSTRING); |
| 555 ASSERT(string_chars.data() != NULL); | 566 ASSERT(string_chars.data() != NULL); |
| 556 // Strings are canonicalized: Allocate a symbol. | 567 // Strings are canonicalized: Allocate a symbol. |
| 557 current_token_.literal = &String::ZoneHandle( | 568 current_token_.literal = &String::ZoneHandle(I, |
| 558 Symbols::FromUTF32(string_chars.data(), string_chars.length())); | 569 Symbols::FromUTF32(string_chars.data(), string_chars.length())); |
| 559 } | 570 } |
| 560 EndStringLiteral(); | 571 EndStringLiteral(); |
| 561 return; | 572 return; |
| 562 } else { | 573 } else { |
| 563 string_chars.Add(string_delimiter_); | 574 string_chars.Add(string_delimiter_); |
| 564 } | 575 } |
| 565 } else { | 576 } else { |
| 566 // Test for a two part utf16 sequence, and decode to a code point | 577 // Test for a two part utf16 sequence, and decode to a code point |
| 567 // if we find one. | 578 // if we find one. |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 912 (current_token_.kind == Token::kINTERPOL_START))) { | 923 (current_token_.kind == Token::kINTERPOL_START))) { |
| 913 index++; // Advance the index to account for tokens added in ScanAll. | 924 index++; // Advance the index to account for tokens added in ScanAll. |
| 914 } | 925 } |
| 915 index++; | 926 index++; |
| 916 prev_token_line_ = current_token_.position.line; | 927 prev_token_line_ = current_token_.position.line; |
| 917 } while ((token_index >= index) && (current_token_.kind != Token::kEOS)); | 928 } while ((token_index >= index) && (current_token_.kind != Token::kEOS)); |
| 918 } | 929 } |
| 919 | 930 |
| 920 | 931 |
| 921 const Scanner::GrowableTokenStream& Scanner::GetStream() { | 932 const Scanner::GrowableTokenStream& Scanner::GetStream() { |
| 922 GrowableTokenStream* ts = new GrowableTokenStream(128); | 933 GrowableTokenStream* ts = new(I) GrowableTokenStream(128); |
| 923 ScanAll(ts); | 934 ScanAll(ts); |
| 924 if (FLAG_print_tokens) { | 935 if (FLAG_print_tokens) { |
| 925 Scanner::PrintTokens(*ts); | 936 Scanner::PrintTokens(*ts); |
| 926 } | 937 } |
| 927 return *ts; | 938 return *ts; |
| 928 } | 939 } |
| 929 | 940 |
| 930 | 941 |
| 931 void Scanner::PrintTokens(const GrowableTokenStream& ts) { | 942 void Scanner::PrintTokens(const GrowableTokenStream& ts) { |
| 932 int currentLine = -1; | 943 int currentLine = -1; |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 955 keywords_[i].keyword_symbol = &Symbols::Keyword(token); | 966 keywords_[i].keyword_symbol = &Symbols::Keyword(token); |
| 956 | 967 |
| 957 int ch = keywords_[i].keyword_chars[0] - 'a'; | 968 int ch = keywords_[i].keyword_chars[0] - 'a'; |
| 958 if (keywords_char_offset_[ch] == Token::kNumKeywords) { | 969 if (keywords_char_offset_[ch] == Token::kNumKeywords) { |
| 959 keywords_char_offset_[ch] = i; | 970 keywords_char_offset_[ch] = i; |
| 960 } | 971 } |
| 961 } | 972 } |
| 962 } | 973 } |
| 963 | 974 |
| 964 } // namespace dart | 975 } // namespace dart |
| OLD | NEW |