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/token.h" | 13 #include "vm/token.h" |
14 #include "vm/unicode.h" | 14 #include "vm/unicode.h" |
15 | 15 |
16 namespace dart { | 16 namespace dart { |
17 | 17 |
18 DEFINE_FLAG(bool, print_tokens, false, "Print scanned tokens."); | |
19 | |
20 | |
21 // Quick access to the locally defined zone() and thread() methods. | 18 // Quick access to the locally defined zone() and thread() methods. |
22 #define Z (zone()) | 19 #define Z (zone()) |
23 #define T (thread()) | 20 #define T (thread()) |
24 | 21 |
25 | 22 |
26 class ScanContext : public ZoneAllocated { | 23 class ScanContext : public ZoneAllocated { |
27 public: | 24 public: |
28 explicit ScanContext(Scanner* scanner) | 25 explicit ScanContext(Scanner* scanner) |
29 : next_(scanner->saved_context_), | 26 : next_(scanner->saved_context_), |
30 string_delimiter_(scanner->string_delimiter_), | 27 string_delimiter_(scanner->string_delimiter_), |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 } | 171 } |
175 for (int i = 1; i < str.Length(); i++) { | 172 for (int i = 1; i < str.Length(); i++) { |
176 if (!IsIdentChar(CallCharAt()(str, i))) { | 173 if (!IsIdentChar(CallCharAt()(str, i))) { |
177 return false; | 174 return false; |
178 } | 175 } |
179 } | 176 } |
180 return true; | 177 return true; |
181 } | 178 } |
182 | 179 |
183 | 180 |
184 // This method is used when parsing integers and doubles in Dart code. We | 181 // This method is used when parsing integers in Dart code. We |
185 // are reusing the Scanner's handling of number literals in that situation. | 182 // are reusing the Scanner's handling of number literals in that situation. |
186 bool Scanner::IsValidLiteral(const Scanner::GrowableTokenStream& tokens, | 183 bool Scanner::IsValidInteger(const String& str, |
187 Token::Kind literal_kind, | |
188 bool* is_positive, | 184 bool* is_positive, |
189 const String** value) { | 185 const String** value) { |
190 if ((tokens.length() == 2) && | 186 Scanner s(str, Symbols::Empty()); |
191 (tokens[0].kind == literal_kind) && | 187 TokenDescriptor tokens[3]; |
| 188 s.Scan(); |
| 189 tokens[0] = s.current_token(); |
| 190 s.Scan(); |
| 191 tokens[1] = s.current_token(); |
| 192 s.Scan(); |
| 193 tokens[2] = s.current_token(); |
| 194 |
| 195 if ((tokens[0].kind == Token::kINTEGER) && |
192 (tokens[1].kind == Token::kEOS)) { | 196 (tokens[1].kind == Token::kEOS)) { |
193 *is_positive = true; | 197 *is_positive = true; |
194 *value = tokens[0].literal; | 198 *value = tokens[0].literal; |
195 return true; | 199 return true; |
196 } | 200 } |
197 if ((tokens.length() == 3) && | 201 if (((tokens[0].kind == Token::kADD) || |
198 ((tokens[0].kind == Token::kADD) || | |
199 (tokens[0].kind == Token::kSUB)) && | 202 (tokens[0].kind == Token::kSUB)) && |
200 (tokens[1].kind == literal_kind) && | 203 (tokens[1].kind == Token::kINTEGER) && |
201 (tokens[2].kind == Token::kEOS)) { | 204 (tokens[2].kind == Token::kEOS)) { |
202 // Check there is no space between "+/-" and number. | 205 // Check there is no space between "+/-" and number. |
203 if ((tokens[0].offset + 1) != tokens[1].offset) { | 206 if ((tokens[0].offset + 1) != tokens[1].offset) { |
204 return false; | 207 return false; |
205 } | 208 } |
206 *is_positive = tokens[0].kind == Token::kADD; | 209 *is_positive = tokens[0].kind == Token::kADD; |
207 *value = tokens[1].literal; | 210 *value = tokens[1].literal; |
208 return true; | 211 return true; |
209 } | 212 } |
210 return false; | 213 return false; |
(...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
879 OS::SNPrint(msg, sizeof(msg), | 882 OS::SNPrint(msg, sizeof(msg), |
880 "unexpected character: '%s' (U+%04X)\n", utf8_char, c0_); | 883 "unexpected character: '%s' (U+%04X)\n", utf8_char, c0_); |
881 ErrorMsg(msg); | 884 ErrorMsg(msg); |
882 ReadChar(); | 885 ReadChar(); |
883 } | 886 } |
884 } | 887 } |
885 } while (current_token_.kind == Token::kWHITESP); | 888 } while (current_token_.kind == Token::kWHITESP); |
886 } | 889 } |
887 | 890 |
888 | 891 |
889 void Scanner::ScanAll(GrowableTokenStream* token_stream) { | 892 void Scanner::ScanAll(TokenCollector* collector) { |
890 Reset(); | 893 Reset(); |
891 do { | 894 do { |
892 Scan(); | 895 Scan(); |
893 | |
894 bool inserted_new_lines = false; | 896 bool inserted_new_lines = false; |
895 for (intptr_t diff = current_token_.position.line - prev_token_line_; | 897 for (intptr_t diff = current_token_.position.line - prev_token_line_; |
896 diff > 0; | 898 diff > 0; |
897 diff--) { | 899 diff--) { |
898 newline_token_.position.line = current_token_.position.line - diff; | 900 newline_token_.position.line = current_token_.position.line - diff; |
899 token_stream->Add(newline_token_); | 901 collector->AddToken(newline_token_); |
900 inserted_new_lines = true; | 902 inserted_new_lines = true; |
901 } | 903 } |
902 | |
903 if (inserted_new_lines && | 904 if (inserted_new_lines && |
904 ((current_token_.kind == Token::kINTERPOL_VAR) || | 905 ((current_token_.kind == Token::kINTERPOL_VAR) || |
905 (current_token_.kind == Token::kINTERPOL_START))) { | 906 (current_token_.kind == Token::kINTERPOL_START))) { |
906 // NOTE: If this changes, be sure to update | 907 // NOTE: If this changes, be sure to update |
907 // Script::GenerateLineNumberArray to stay in sync. | 908 // Script::GenerateLineNumberArray to stay in sync. |
908 empty_string_token_.position.line = current_token_.position.line; | 909 empty_string_token_.position.line = current_token_.position.line; |
909 token_stream->Add(empty_string_token_); | 910 collector->AddToken(empty_string_token_); |
910 } | 911 } |
911 token_stream->Add(current_token_); | 912 collector->AddToken(current_token_); |
912 prev_token_line_ = current_token_.position.line; | 913 prev_token_line_ = current_token_.position.line; |
913 } while (current_token_.kind != Token::kEOS); | 914 } while (current_token_.kind != Token::kEOS); |
914 } | 915 } |
915 | 916 |
916 | 917 |
917 void Scanner::ScanTo(TokenPosition token_index) { | 918 void Scanner::ScanTo(TokenPosition token_index) { |
918 TokenPosition index = TokenPosition::kMinSource; | 919 TokenPosition index = TokenPosition::kMinSource; |
919 Reset(); | 920 Reset(); |
920 do { | 921 do { |
921 Scan(); | 922 Scan(); |
922 | |
923 bool inserted_new_lines = false; | 923 bool inserted_new_lines = false; |
924 for (intptr_t diff = current_token_.position.line - prev_token_line_; | 924 for (intptr_t diff = current_token_.position.line - prev_token_line_; |
925 diff > 0; | 925 diff > 0; |
926 diff--) { | 926 diff--) { |
927 // Advance the index to account for tokens added in ScanAll. | 927 // Advance the index to account for tokens added in ScanAll. |
928 index.Next(); | 928 index.Next(); |
929 inserted_new_lines = true; | 929 inserted_new_lines = true; |
930 } | 930 } |
931 | |
932 if (inserted_new_lines && | 931 if (inserted_new_lines && |
933 ((current_token_.kind == Token::kINTERPOL_VAR) || | 932 ((current_token_.kind == Token::kINTERPOL_VAR) || |
934 (current_token_.kind == Token::kINTERPOL_START))) { | 933 (current_token_.kind == Token::kINTERPOL_START))) { |
935 // Advance the index to account for tokens added in ScanAll. | 934 // Advance the index to account for tokens added in ScanAll. |
936 index.Next(); | 935 index.Next(); |
937 } | 936 } |
938 index.Next(); | 937 index.Next(); |
939 prev_token_line_ = current_token_.position.line; | 938 prev_token_line_ = current_token_.position.line; |
940 } while ((token_index >= index) && (current_token_.kind != Token::kEOS)); | 939 } while ((token_index >= index) && (current_token_.kind != Token::kEOS)); |
941 } | 940 } |
942 | 941 |
943 | 942 |
944 const Scanner::GrowableTokenStream& Scanner::GetStream() { | |
945 GrowableTokenStream* ts = new(Z) GrowableTokenStream(128); | |
946 ScanAll(ts); | |
947 if (FLAG_print_tokens) { | |
948 Scanner::PrintTokens(*ts); | |
949 } | |
950 return *ts; | |
951 } | |
952 | |
953 | |
954 void Scanner::PrintTokens(const GrowableTokenStream& ts) { | |
955 int currentLine = -1; | |
956 for (int i = 0; i < ts.length(); i++) { | |
957 const TokenDescriptor& td = ts[i]; | |
958 if (currentLine != td.position.line) { | |
959 currentLine = td.position.line; | |
960 OS::Print("\n%d (%d): ", currentLine, i); | |
961 } | |
962 OS::Print("%s ", Token::Name(td.kind)); | |
963 } | |
964 OS::Print("\n"); | |
965 } | |
966 | |
967 | |
968 void Scanner::InitOnce() { | 943 void Scanner::InitOnce() { |
969 ASSERT(Isolate::Current() == Dart::vm_isolate()); | 944 ASSERT(Isolate::Current() == Dart::vm_isolate()); |
970 for (int i = 0; i < kNumLowercaseChars; i++) { | 945 for (int i = 0; i < kNumLowercaseChars; i++) { |
971 keywords_char_offset_[i] = Token::kNumKeywords; | 946 keywords_char_offset_[i] = Token::kNumKeywords; |
972 } | 947 } |
973 for (int i = 0; i < Token::kNumKeywords; i++) { | 948 for (int i = 0; i < Token::kNumKeywords; i++) { |
974 Token::Kind token = static_cast<Token::Kind>(Token::kFirstKeyword + i); | 949 Token::Kind token = static_cast<Token::Kind>(Token::kFirstKeyword + i); |
975 keywords_[i].kind = token; | 950 keywords_[i].kind = token; |
976 keywords_[i].keyword_chars = Token::Str(token); | 951 keywords_[i].keyword_chars = Token::Str(token); |
977 keywords_[i].keyword_len = strlen(Token::Str(token)); | 952 keywords_[i].keyword_len = strlen(Token::Str(token)); |
978 keywords_[i].keyword_symbol = &Symbols::Token(token); | 953 keywords_[i].keyword_symbol = &Symbols::Token(token); |
979 | 954 |
980 int ch = keywords_[i].keyword_chars[0] - 'a'; | 955 int ch = keywords_[i].keyword_chars[0] - 'a'; |
981 if (keywords_char_offset_[ch] == Token::kNumKeywords) { | 956 if (keywords_char_offset_[ch] == Token::kNumKeywords) { |
982 keywords_char_offset_[ch] = i; | 957 keywords_char_offset_[ch] = i; |
983 } | 958 } |
984 } | 959 } |
985 } | 960 } |
986 | 961 |
987 } // namespace dart | 962 } // namespace dart |
OLD | NEW |