Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(139)

Side by Side Diff: runtime/vm/scanner.cc

Issue 2974233002: VM: Re-format to use at most one newline between functions (Closed)
Patch Set: Rebase and merge Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/scanner.h ('k') | runtime/vm/scanner_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 // Quick access to the locally defined zone() and thread() methods. 18 // Quick access to the locally defined zone() and thread() methods.
19 #define Z (zone()) 19 #define Z (zone())
20 #define T (thread()) 20 #define T (thread())
21 21
22
23 class ScanContext : public ZoneAllocated { 22 class ScanContext : public ZoneAllocated {
24 public: 23 public:
25 explicit ScanContext(Scanner* scanner) 24 explicit ScanContext(Scanner* scanner)
26 : next_(scanner->saved_context_), 25 : next_(scanner->saved_context_),
27 string_delimiter_(scanner->string_delimiter_), 26 string_delimiter_(scanner->string_delimiter_),
28 string_is_multiline_(scanner->string_is_multiline_), 27 string_is_multiline_(scanner->string_is_multiline_),
29 brace_level_(scanner->brace_level_) {} 28 brace_level_(scanner->brace_level_) {}
30 29
31 void CopyTo(Scanner* scanner) { 30 void CopyTo(Scanner* scanner) {
32 scanner->string_delimiter_ = string_delimiter_; 31 scanner->string_delimiter_ = string_delimiter_;
33 scanner->string_is_multiline_ = string_is_multiline_; 32 scanner->string_is_multiline_ = string_is_multiline_;
34 scanner->brace_level_ = brace_level_; 33 scanner->brace_level_ = brace_level_;
35 } 34 }
36 35
37 ScanContext* next() const { return next_; } 36 ScanContext* next() const { return next_; }
38 37
39 private: 38 private:
40 ScanContext* next_; 39 ScanContext* next_;
41 const char string_delimiter_; 40 const char string_delimiter_;
42 const bool string_is_multiline_; 41 const bool string_is_multiline_;
43 const int brace_level_; 42 const int brace_level_;
44 }; 43 };
45 44
46
47 Scanner::KeywordTable Scanner::keywords_[Token::kNumKeywords]; 45 Scanner::KeywordTable Scanner::keywords_[Token::kNumKeywords];
48 int Scanner::keywords_char_offset_[Scanner::kNumLowercaseChars]; 46 int Scanner::keywords_char_offset_[Scanner::kNumLowercaseChars];
49 47
50
51 void Scanner::Reset() { 48 void Scanner::Reset() {
52 // Non-changing newline properties. 49 // Non-changing newline properties.
53 newline_token_.kind = Token::kNEWLINE; 50 newline_token_.kind = Token::kNEWLINE;
54 newline_token_.literal = NULL; 51 newline_token_.literal = NULL;
55 // We don't preserve the column information. 52 // We don't preserve the column information.
56 newline_token_.position.column = 0; 53 newline_token_.position.column = 0;
57 54
58 // Non-changing empty string token properties. 55 // Non-changing empty string token properties.
59 empty_string_token_.kind = Token::kSTRING; 56 empty_string_token_.kind = Token::kSTRING;
60 empty_string_token_.literal = &Symbols::Empty(); 57 empty_string_token_.literal = &Symbols::Empty();
61 empty_string_token_.position.column = 0; 58 empty_string_token_.position.column = 0;
62 59
63 lookahead_pos_ = -1; 60 lookahead_pos_ = -1;
64 token_start_ = 0; 61 token_start_ = 0;
65 c0_ = '\0'; 62 c0_ = '\0';
66 newline_seen_ = false; 63 newline_seen_ = false;
67 prev_token_line_ = 1; 64 prev_token_line_ = 1;
68 saved_context_ = NULL; 65 saved_context_ = NULL;
69 string_delimiter_ = '\0'; 66 string_delimiter_ = '\0';
70 string_is_multiline_ = false; 67 string_is_multiline_ = false;
71 brace_level_ = 0; 68 brace_level_ = 0;
72 c0_pos_.line = 1; 69 c0_pos_.line = 1;
73 c0_pos_.column = 0; 70 c0_pos_.column = 0;
74 ReadChar(); 71 ReadChar();
75 } 72 }
76 73
77
78 Scanner::Scanner(const String& src, const String& private_key) 74 Scanner::Scanner(const String& src, const String& private_key)
79 : source_(src), 75 : source_(src),
80 source_length_(src.Length()), 76 source_length_(src.Length()),
81 saved_context_(NULL), 77 saved_context_(NULL),
82 private_key_(String::ZoneHandle(private_key.raw())), 78 private_key_(String::ZoneHandle(private_key.raw())),
83 char_at_func_(src.CharAtFunc()), 79 char_at_func_(src.CharAtFunc()),
84 thread_(Thread::Current()), 80 thread_(Thread::Current()),
85 zone_(thread_->zone()) { 81 zone_(thread_->zone()) {
86 Reset(); 82 Reset();
87 } 83 }
88 84
89
90 Scanner::~Scanner() {} 85 Scanner::~Scanner() {}
91 86
92
93 void Scanner::ErrorMsg(const char* msg) { 87 void Scanner::ErrorMsg(const char* msg) {
94 current_token_.kind = Token::kERROR; 88 current_token_.kind = Token::kERROR;
95 current_token_.literal = &String::ZoneHandle(Z, Symbols::New(T, msg)); 89 current_token_.literal = &String::ZoneHandle(Z, Symbols::New(T, msg));
96 current_token_.position = c0_pos_; 90 current_token_.position = c0_pos_;
97 token_start_ = lookahead_pos_; 91 token_start_ = lookahead_pos_;
98 current_token_.offset = lookahead_pos_; 92 current_token_.offset = lookahead_pos_;
99 } 93 }
100 94
101
102 void Scanner::PushContext() { 95 void Scanner::PushContext() {
103 ScanContext* ctx = new (Z) ScanContext(this); 96 ScanContext* ctx = new (Z) ScanContext(this);
104 saved_context_ = ctx; 97 saved_context_ = ctx;
105 string_delimiter_ = '\0'; 98 string_delimiter_ = '\0';
106 string_is_multiline_ = false; 99 string_is_multiline_ = false;
107 brace_level_ = 1; // Account for the opening ${ token. 100 brace_level_ = 1; // Account for the opening ${ token.
108 } 101 }
109 102
110
111 void Scanner::PopContext() { 103 void Scanner::PopContext() {
112 ASSERT(saved_context_ != NULL); 104 ASSERT(saved_context_ != NULL);
113 ASSERT(brace_level_ == 0); 105 ASSERT(brace_level_ == 0);
114 ASSERT(string_delimiter_ == '\0'); 106 ASSERT(string_delimiter_ == '\0');
115 ScanContext* ctx = saved_context_; 107 ScanContext* ctx = saved_context_;
116 ctx->CopyTo(this); 108 ctx->CopyTo(this);
117 saved_context_ = ctx->next(); 109 saved_context_ = ctx->next();
118 ASSERT(string_delimiter_ != '\0'); 110 ASSERT(string_delimiter_ != '\0');
119 } 111 }
120 112
121
122 void Scanner::BeginStringLiteral(const char delimiter) { 113 void Scanner::BeginStringLiteral(const char delimiter) {
123 string_delimiter_ = delimiter; 114 string_delimiter_ = delimiter;
124 } 115 }
125 116
126
127 void Scanner::EndStringLiteral() { 117 void Scanner::EndStringLiteral() {
128 string_delimiter_ = '\0'; 118 string_delimiter_ = '\0';
129 string_is_multiline_ = false; 119 string_is_multiline_ = false;
130 } 120 }
131 121
132
133 bool Scanner::IsLetter(int32_t c) { 122 bool Scanner::IsLetter(int32_t c) {
134 return (('A' <= c) && (c <= 'Z')) || (('a' <= c) && (c <= 'z')); 123 return (('A' <= c) && (c <= 'Z')) || (('a' <= c) && (c <= 'z'));
135 } 124 }
136 125
137
138 bool Scanner::IsDecimalDigit(int32_t c) { 126 bool Scanner::IsDecimalDigit(int32_t c) {
139 return '0' <= c && c <= '9'; 127 return '0' <= c && c <= '9';
140 } 128 }
141 129
142
143 bool Scanner::IsNumberStart(int32_t ch) { 130 bool Scanner::IsNumberStart(int32_t ch) {
144 return IsDecimalDigit(ch) || ch == '.'; 131 return IsDecimalDigit(ch) || ch == '.';
145 } 132 }
146 133
147
148 bool Scanner::IsHexDigit(int32_t c) { 134 bool Scanner::IsHexDigit(int32_t c) {
149 return IsDecimalDigit(c) || (('A' <= c) && (c <= 'F')) || 135 return IsDecimalDigit(c) || (('A' <= c) && (c <= 'F')) ||
150 (('a' <= c) && (c <= 'f')); 136 (('a' <= c) && (c <= 'f'));
151 } 137 }
152 138
153
154 bool Scanner::IsIdentStartChar(int32_t c) { 139 bool Scanner::IsIdentStartChar(int32_t c) {
155 return IsLetter(c) || (c == '_') || (c == '$'); 140 return IsLetter(c) || (c == '_') || (c == '$');
156 } 141 }
157 142
158
159 bool Scanner::IsIdentChar(int32_t c) { 143 bool Scanner::IsIdentChar(int32_t c) {
160 return IsLetter(c) || IsDecimalDigit(c) || (c == '_') || (c == '$'); 144 return IsLetter(c) || IsDecimalDigit(c) || (c == '_') || (c == '$');
161 } 145 }
162 146
163
164 bool Scanner::IsIdent(const String& str) { 147 bool Scanner::IsIdent(const String& str) {
165 if (!str.IsOneByteString()) { 148 if (!str.IsOneByteString()) {
166 return false; 149 return false;
167 } 150 }
168 if (str.Length() == 0 || !IsIdentStartChar(CallCharAt()(str, 0))) { 151 if (str.Length() == 0 || !IsIdentStartChar(CallCharAt()(str, 0))) {
169 return false; 152 return false;
170 } 153 }
171 for (int i = 1; i < str.Length(); i++) { 154 for (int i = 1; i < str.Length(); i++) {
172 if (!IsIdentChar(CallCharAt()(str, i))) { 155 if (!IsIdentChar(CallCharAt()(str, i))) {
173 return false; 156 return false;
174 } 157 }
175 } 158 }
176 return true; 159 return true;
177 } 160 }
178 161
179
180 // This method is used when parsing integers in Dart code. We 162 // This method is used when parsing integers in Dart code. We
181 // are reusing the Scanner's handling of number literals in that situation. 163 // are reusing the Scanner's handling of number literals in that situation.
182 bool Scanner::IsValidInteger(const String& str, 164 bool Scanner::IsValidInteger(const String& str,
183 bool* is_positive, 165 bool* is_positive,
184 const String** value) { 166 const String** value) {
185 Scanner s(str, Symbols::Empty()); 167 Scanner s(str, Symbols::Empty());
186 TokenDescriptor tokens[3]; 168 TokenDescriptor tokens[3];
187 s.Scan(); 169 s.Scan();
188 tokens[0] = s.current_token(); 170 tokens[0] = s.current_token();
189 s.Scan(); 171 s.Scan();
(...skipping 12 matching lines...) Expand all
202 if ((tokens[0].offset + 1) != tokens[1].offset) { 184 if ((tokens[0].offset + 1) != tokens[1].offset) {
203 return false; 185 return false;
204 } 186 }
205 *is_positive = tokens[0].kind == Token::kADD; 187 *is_positive = tokens[0].kind == Token::kADD;
206 *value = tokens[1].literal; 188 *value = tokens[1].literal;
207 return true; 189 return true;
208 } 190 }
209 return false; 191 return false;
210 } 192 }
211 193
212
213 void Scanner::ReadChar() { 194 void Scanner::ReadChar() {
214 if (lookahead_pos_ < source_length_) { 195 if (lookahead_pos_ < source_length_) {
215 if (c0_ == '\n') { 196 if (c0_ == '\n') {
216 newline_seen_ = true; 197 newline_seen_ = true;
217 c0_pos_.line++; 198 c0_pos_.line++;
218 c0_pos_.column = 0; 199 c0_pos_.column = 0;
219 if (CallCharAt()(source_, lookahead_pos_) == '\r') { 200 if (CallCharAt()(source_, lookahead_pos_) == '\r') {
220 // Replace a sequence of '\r' '\n' with a single '\n'. 201 // Replace a sequence of '\r' '\n' with a single '\n'.
221 if (LookaheadChar(1) == '\n') { 202 if (LookaheadChar(1) == '\n') {
222 lookahead_pos_++; 203 lookahead_pos_++;
223 } 204 }
224 } 205 }
225 } 206 }
226 lookahead_pos_++; 207 lookahead_pos_++;
227 c0_pos_.column++; 208 c0_pos_.column++;
228 c0_ = LookaheadChar(0); 209 c0_ = LookaheadChar(0);
229 // Replace '\r' with '\n'. 210 // Replace '\r' with '\n'.
230 if (c0_ == '\r') { 211 if (c0_ == '\r') {
231 c0_ = '\n'; 212 c0_ = '\n';
232 } 213 }
233 } 214 }
234 } 215 }
235 216
236
237 // Look ahead 'how_many' characters. Returns the character, or '\0' if 217 // Look ahead 'how_many' characters. Returns the character, or '\0' if
238 // the lookahead position is beyond the end of the string. Does not 218 // the lookahead position is beyond the end of the string. Does not
239 // normalize line end characters into '\n'. 219 // normalize line end characters into '\n'.
240 int32_t Scanner::LookaheadChar(int how_many) { 220 int32_t Scanner::LookaheadChar(int how_many) {
241 ASSERT(how_many >= 0); 221 ASSERT(how_many >= 0);
242 int32_t lookahead_char = '\0'; 222 int32_t lookahead_char = '\0';
243 if (lookahead_pos_ + how_many < source_length_) { 223 if (lookahead_pos_ + how_many < source_length_) {
244 lookahead_char = CallCharAt()(source_, lookahead_pos_ + how_many); 224 lookahead_char = CallCharAt()(source_, lookahead_pos_ + how_many);
245 } 225 }
246 return lookahead_char; 226 return lookahead_char;
247 } 227 }
248 228
249
250 void Scanner::ConsumeWhiteSpace() { 229 void Scanner::ConsumeWhiteSpace() {
251 while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n') { 230 while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n') {
252 ReadChar(); 231 ReadChar();
253 } 232 }
254 } 233 }
255 234
256
257 void Scanner::ConsumeLineComment() { 235 void Scanner::ConsumeLineComment() {
258 ASSERT(c0_ == '/'); 236 ASSERT(c0_ == '/');
259 while (c0_ != '\n' && c0_ != '\0') { 237 while (c0_ != '\n' && c0_ != '\0') {
260 ReadChar(); 238 ReadChar();
261 } 239 }
262 ReadChar(); 240 ReadChar();
263 current_token_.kind = Token::kWHITESP; 241 current_token_.kind = Token::kWHITESP;
264 } 242 }
265 243
266
267 void Scanner::ConsumeBlockComment() { 244 void Scanner::ConsumeBlockComment() {
268 ASSERT(c0_ == '*'); 245 ASSERT(c0_ == '*');
269 ReadChar(); 246 ReadChar();
270 int nesting_level = 1; 247 int nesting_level = 1;
271 248
272 while (true) { 249 while (true) {
273 const char c = c0_; 250 const char c = c0_;
274 ReadChar(); 251 ReadChar();
275 if (c0_ == '\0') { 252 if (c0_ == '\0') {
276 break; 253 break;
277 } 254 }
278 if (c == '/' && c0_ == '*') { 255 if (c == '/' && c0_ == '*') {
279 nesting_level++; 256 nesting_level++;
280 ReadChar(); // Consume asterisk. 257 ReadChar(); // Consume asterisk.
281 } else if (c == '*' && c0_ == '/') { 258 } else if (c == '*' && c0_ == '/') {
282 nesting_level--; 259 nesting_level--;
283 ReadChar(); // Consume slash. 260 ReadChar(); // Consume slash.
284 if (nesting_level == 0) { 261 if (nesting_level == 0) {
285 break; 262 break;
286 } 263 }
287 } 264 }
288 } 265 }
289 current_token_.kind = 266 current_token_.kind =
290 (nesting_level == 0) ? Token::kWHITESP : Token::kILLEGAL; 267 (nesting_level == 0) ? Token::kWHITESP : Token::kILLEGAL;
291 } 268 }
292 269
293
294 void Scanner::ScanIdentChars(bool allow_dollar) { 270 void Scanner::ScanIdentChars(bool allow_dollar) {
295 ASSERT(IsIdentStartChar(c0_)); 271 ASSERT(IsIdentStartChar(c0_));
296 ASSERT(allow_dollar || (c0_ != '$')); 272 ASSERT(allow_dollar || (c0_ != '$'));
297 int ident_length = 0; 273 int ident_length = 0;
298 int ident_pos = lookahead_pos_; 274 int ident_pos = lookahead_pos_;
299 int32_t ident_char0 = CallCharAt()(source_, ident_pos); 275 int32_t ident_char0 = CallCharAt()(source_, ident_pos);
300 while (IsIdentChar(c0_) && (allow_dollar || (c0_ != '$'))) { 276 while (IsIdentChar(c0_) && (allow_dollar || (c0_ != '$'))) {
301 ReadChar(); 277 ReadChar();
302 ident_length++; 278 ident_length++;
303 } 279 }
(...skipping 28 matching lines...) Expand all
332 if (ident_char0 == Library::kPrivateIdentifierStart) { 308 if (ident_char0 == Library::kPrivateIdentifierStart) {
333 // Private identifiers are mangled on a per library basis. 309 // Private identifiers are mangled on a per library basis.
334 literal = String::SubString(T, source_, ident_pos, ident_length); 310 literal = String::SubString(T, source_, ident_pos, ident_length);
335 literal = Symbols::FromConcat(T, literal, private_key_); 311 literal = Symbols::FromConcat(T, literal, private_key_);
336 } else { 312 } else {
337 literal = Symbols::New(T, source_, ident_pos, ident_length); 313 literal = Symbols::New(T, source_, ident_pos, ident_length);
338 } 314 }
339 current_token_.literal = &literal; 315 current_token_.literal = &literal;
340 } 316 }
341 317
342
343 // Parse integer or double number literal of format: 318 // Parse integer or double number literal of format:
344 // NUMBER = INTEGER | DOUBLE 319 // NUMBER = INTEGER | DOUBLE
345 // INTEGER = D+ | (("0x" | "0X") H+) 320 // INTEGER = D+ | (("0x" | "0X") H+)
346 // DOUBLE = ((D+ ["." D*]) | ("." D+)) [ EXPONENT ] 321 // DOUBLE = ((D+ ["." D*]) | ("." D+)) [ EXPONENT ]
347 // EXPONENT = ("e" | "E") ["+" | "-"] D+ 322 // EXPONENT = ("e" | "E") ["+" | "-"] D+
348 void Scanner::ScanNumber(bool dec_point_seen) { 323 void Scanner::ScanNumber(bool dec_point_seen) {
349 ASSERT(IsDecimalDigit(c0_)); 324 ASSERT(IsDecimalDigit(c0_));
350 char first_digit = c0_; 325 char first_digit = c0_;
351 326
352 Recognize(dec_point_seen ? Token::kDOUBLE : Token::kINTEGER); 327 Recognize(dec_point_seen ? Token::kDOUBLE : Token::kINTEGER);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 } 361 }
387 } 362 }
388 if (current_token_.kind != Token::kILLEGAL) { 363 if (current_token_.kind != Token::kILLEGAL) {
389 intptr_t len = lookahead_pos_ - token_start_; 364 intptr_t len = lookahead_pos_ - token_start_;
390 const String& str = 365 const String& str =
391 String::ZoneHandle(Z, Symbols::New(T, source_, token_start_, len)); 366 String::ZoneHandle(Z, Symbols::New(T, source_, token_start_, len));
392 current_token_.literal = &str; 367 current_token_.literal = &str;
393 } 368 }
394 } 369 }
395 370
396
397 void Scanner::SkipLine() { 371 void Scanner::SkipLine() {
398 while (c0_ != '\n' && c0_ != '\0') { 372 while (c0_ != '\n' && c0_ != '\0') {
399 ReadChar(); 373 ReadChar();
400 } 374 }
401 } 375 }
402 376
403
404 void Scanner::ScanScriptTag() { 377 void Scanner::ScanScriptTag() {
405 ReadChar(); 378 ReadChar();
406 ASSERT(c0_ == '!'); 379 ASSERT(c0_ == '!');
407 Recognize(Token::kSCRIPTTAG); 380 Recognize(Token::kSCRIPTTAG);
408 // The script tag extends to the end of the line. Just treat this 381 // The script tag extends to the end of the line. Just treat this
409 // similar to a line comment. 382 // similar to a line comment.
410 SkipLine(); 383 SkipLine();
411 } 384 }
412 385
413
414 void Scanner::ScanLiteralString(bool is_raw) { 386 void Scanner::ScanLiteralString(bool is_raw) {
415 ASSERT(!IsScanningString()); 387 ASSERT(!IsScanningString());
416 ASSERT(c0_ == '"' || c0_ == '\''); 388 ASSERT(c0_ == '"' || c0_ == '\'');
417 389
418 // Entering string scanning mode. 390 // Entering string scanning mode.
419 BeginStringLiteral(c0_); 391 BeginStringLiteral(c0_);
420 ReadChar(); 392 ReadChar();
421 393
422 if ((c0_ == string_delimiter_) && (LookaheadChar(1) == string_delimiter_)) { 394 if ((c0_ == string_delimiter_) && (LookaheadChar(1) == string_delimiter_)) {
423 string_is_multiline_ = true; 395 string_is_multiline_ = true;
424 ReadChar(); // Skip two additional string delimiters. 396 ReadChar(); // Skip two additional string delimiters.
425 ReadChar(); 397 ReadChar();
426 } 398 }
427 ScanLiteralStringChars(is_raw, string_is_multiline_); 399 ScanLiteralStringChars(is_raw, string_is_multiline_);
428 } 400 }
429 401
430
431 bool Scanner::ScanHexDigits(int digits, int32_t* value) { 402 bool Scanner::ScanHexDigits(int digits, int32_t* value) {
432 *value = 0; 403 *value = 0;
433 for (int i = 0; i < digits; ++i) { 404 for (int i = 0; i < digits; ++i) {
434 ReadChar(); 405 ReadChar();
435 if (!IsHexDigit(c0_)) { 406 if (!IsHexDigit(c0_)) {
436 ErrorMsg("too few hexadecimal digits"); 407 ErrorMsg("too few hexadecimal digits");
437 return false; 408 return false;
438 } 409 }
439 *value <<= 4; 410 *value <<= 4;
440 *value |= Utils::HexDigitToInt(c0_); 411 *value |= Utils::HexDigitToInt(c0_);
441 } 412 }
442 return true; 413 return true;
443 } 414 }
444 415
445
446 bool Scanner::ScanHexDigits(int min_digits, int max_digits, int32_t* value) { 416 bool Scanner::ScanHexDigits(int min_digits, int max_digits, int32_t* value) {
447 *value = 0; 417 *value = 0;
448 ReadChar(); 418 ReadChar();
449 for (int i = 0; i < max_digits; ++i) { 419 for (int i = 0; i < max_digits; ++i) {
450 if (!IsHexDigit(c0_)) { 420 if (!IsHexDigit(c0_)) {
451 if (i < min_digits) { 421 if (i < min_digits) {
452 ErrorMsg("hexadecimal digit expected"); 422 ErrorMsg("hexadecimal digit expected");
453 return false; 423 return false;
454 } 424 }
455 break; 425 break;
456 } 426 }
457 *value <<= 4; 427 *value <<= 4;
458 *value |= Utils::HexDigitToInt(c0_); 428 *value |= Utils::HexDigitToInt(c0_);
459 ReadChar(); 429 ReadChar();
460 } 430 }
461 return true; 431 return true;
462 } 432 }
463 433
464
465 void Scanner::ScanEscapedCodePoint(int32_t* code_point) { 434 void Scanner::ScanEscapedCodePoint(int32_t* code_point) {
466 ASSERT(c0_ == 'u' || c0_ == 'x'); 435 ASSERT(c0_ == 'u' || c0_ == 'x');
467 bool is_valid; 436 bool is_valid;
468 if (c0_ == 'x') { 437 if (c0_ == 'x') {
469 is_valid = ScanHexDigits(2, code_point); 438 is_valid = ScanHexDigits(2, code_point);
470 } else if (c0_ == 'u' && LookaheadChar(1) != '{') { 439 } else if (c0_ == 'u' && LookaheadChar(1) != '{') {
471 is_valid = ScanHexDigits(4, code_point); 440 is_valid = ScanHexDigits(4, code_point);
472 } else { 441 } else {
473 ReadChar(); // Skip left curly bracket. 442 ReadChar(); // Skip left curly bracket.
474 is_valid = ScanHexDigits(1, 6, code_point); 443 is_valid = ScanHexDigits(1, 6, code_point);
475 if (is_valid) { 444 if (is_valid) {
476 if (c0_ != '}') { 445 if (c0_ != '}') {
477 ErrorMsg("expected '}' after character code"); 446 ErrorMsg("expected '}' after character code");
478 return; 447 return;
479 } 448 }
480 } 449 }
481 } 450 }
482 if (is_valid && (Utf::IsOutOfRange(*code_point))) { 451 if (is_valid && (Utf::IsOutOfRange(*code_point))) {
483 ErrorMsg("invalid code point"); 452 ErrorMsg("invalid code point");
484 } 453 }
485 } 454 }
486 455
487
488 void Scanner::ScanLiteralStringChars(bool is_raw, bool remove_whitespace) { 456 void Scanner::ScanLiteralStringChars(bool is_raw, bool remove_whitespace) {
489 GrowableArray<int32_t> string_chars(64); 457 GrowableArray<int32_t> string_chars(64);
490 458
491 ASSERT(IsScanningString()); 459 ASSERT(IsScanningString());
492 // We are at the first character of a string literal piece. A string literal 460 // We are at the first character of a string literal piece. A string literal
493 // can be broken up into multiple pieces by string interpolation. 461 // can be broken up into multiple pieces by string interpolation.
494 while (true) { 462 while (true) {
495 if ((c0_ == '\0') || ((c0_ == '\n') && !string_is_multiline_)) { 463 if ((c0_ == '\0') || ((c0_ == '\n') && !string_is_multiline_)) {
496 ErrorMsg("unterminated string literal"); 464 ErrorMsg("unterminated string literal");
497 EndStringLiteral(); 465 EndStringLiteral();
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 } 567 }
600 if (whitespace_only) { 568 if (whitespace_only) {
601 string_chars.Clear(); // Discard characters on first line. 569 string_chars.Clear(); // Discard characters on first line.
602 } 570 }
603 remove_whitespace = false; 571 remove_whitespace = false;
604 } 572 }
605 ReadChar(); 573 ReadChar();
606 } 574 }
607 } 575 }
608 576
609
610 void Scanner::Scan() { 577 void Scanner::Scan() {
611 newline_seen_ = false; 578 newline_seen_ = false;
612 579
613 do { 580 do {
614 if (!IsScanningString()) { 581 if (!IsScanningString()) {
615 ConsumeWhiteSpace(); 582 ConsumeWhiteSpace();
616 } 583 }
617 token_start_ = lookahead_pos_; 584 token_start_ = lookahead_pos_;
618 current_token_.offset = lookahead_pos_; 585 current_token_.offset = lookahead_pos_;
619 current_token_.position = c0_pos_; 586 current_token_.position = c0_pos_;
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
873 utf8_char[len] = '\0'; 840 utf8_char[len] = '\0';
874 OS::SNPrint(msg, sizeof(msg), "unexpected character: '%s' (U+%04X)\n", 841 OS::SNPrint(msg, sizeof(msg), "unexpected character: '%s' (U+%04X)\n",
875 utf8_char, c0_); 842 utf8_char, c0_);
876 ErrorMsg(msg); 843 ErrorMsg(msg);
877 ReadChar(); 844 ReadChar();
878 } 845 }
879 } 846 }
880 } while (current_token_.kind == Token::kWHITESP); 847 } while (current_token_.kind == Token::kWHITESP);
881 } 848 }
882 849
883
884 void Scanner::ScanAll(TokenCollector* collector) { 850 void Scanner::ScanAll(TokenCollector* collector) {
885 Reset(); 851 Reset();
886 do { 852 do {
887 Scan(); 853 Scan();
888 bool inserted_new_lines = false; 854 bool inserted_new_lines = false;
889 for (intptr_t diff = current_token_.position.line - prev_token_line_; 855 for (intptr_t diff = current_token_.position.line - prev_token_line_;
890 diff > 0; diff--) { 856 diff > 0; diff--) {
891 newline_token_.position.line = current_token_.position.line - diff; 857 newline_token_.position.line = current_token_.position.line - diff;
892 collector->AddToken(newline_token_); 858 collector->AddToken(newline_token_);
893 inserted_new_lines = true; 859 inserted_new_lines = true;
894 } 860 }
895 if (inserted_new_lines && 861 if (inserted_new_lines &&
896 ((current_token_.kind == Token::kINTERPOL_VAR) || 862 ((current_token_.kind == Token::kINTERPOL_VAR) ||
897 (current_token_.kind == Token::kINTERPOL_START))) { 863 (current_token_.kind == Token::kINTERPOL_START))) {
898 // NOTE: If this changes, be sure to update 864 // NOTE: If this changes, be sure to update
899 // Script::GenerateLineNumberArray to stay in sync. 865 // Script::GenerateLineNumberArray to stay in sync.
900 empty_string_token_.position.line = current_token_.position.line; 866 empty_string_token_.position.line = current_token_.position.line;
901 collector->AddToken(empty_string_token_); 867 collector->AddToken(empty_string_token_);
902 } 868 }
903 collector->AddToken(current_token_); 869 collector->AddToken(current_token_);
904 prev_token_line_ = current_token_.position.line; 870 prev_token_line_ = current_token_.position.line;
905 } while (current_token_.kind != Token::kEOS); 871 } while (current_token_.kind != Token::kEOS);
906 } 872 }
907 873
908
909 void Scanner::ScanTo(intptr_t token_index) { 874 void Scanner::ScanTo(intptr_t token_index) {
910 ASSERT(token_index >= 0); 875 ASSERT(token_index >= 0);
911 intptr_t index = 0; 876 intptr_t index = 0;
912 Reset(); 877 Reset();
913 do { 878 do {
914 Scan(); 879 Scan();
915 bool inserted_new_lines = false; 880 bool inserted_new_lines = false;
916 for (intptr_t diff = current_token_.position.line - prev_token_line_; 881 for (intptr_t diff = current_token_.position.line - prev_token_line_;
917 diff > 0; diff--) { 882 diff > 0; diff--) {
918 // Advance the index to account for tokens added in ScanAll. 883 // Advance the index to account for tokens added in ScanAll.
919 index++; 884 index++;
920 inserted_new_lines = true; 885 inserted_new_lines = true;
921 } 886 }
922 if (inserted_new_lines && 887 if (inserted_new_lines &&
923 ((current_token_.kind == Token::kINTERPOL_VAR) || 888 ((current_token_.kind == Token::kINTERPOL_VAR) ||
924 (current_token_.kind == Token::kINTERPOL_START))) { 889 (current_token_.kind == Token::kINTERPOL_START))) {
925 // Advance the index to account for tokens added in ScanAll. 890 // Advance the index to account for tokens added in ScanAll.
926 index++; 891 index++;
927 } 892 }
928 index++; 893 index++;
929 prev_token_line_ = current_token_.position.line; 894 prev_token_line_ = current_token_.position.line;
930 } while ((token_index >= index) && (current_token_.kind != Token::kEOS)); 895 } while ((token_index >= index) && (current_token_.kind != Token::kEOS));
931 } 896 }
932 897
933
934 void Scanner::InitOnce() { 898 void Scanner::InitOnce() {
935 ASSERT(Isolate::Current() == Dart::vm_isolate()); 899 ASSERT(Isolate::Current() == Dart::vm_isolate());
936 for (int i = 0; i < kNumLowercaseChars; i++) { 900 for (int i = 0; i < kNumLowercaseChars; i++) {
937 keywords_char_offset_[i] = Token::kNumKeywords; 901 keywords_char_offset_[i] = Token::kNumKeywords;
938 } 902 }
939 for (int i = 0; i < Token::kNumKeywords; i++) { 903 for (int i = 0; i < Token::kNumKeywords; i++) {
940 Token::Kind token = static_cast<Token::Kind>(Token::kFirstKeyword + i); 904 Token::Kind token = static_cast<Token::Kind>(Token::kFirstKeyword + i);
941 keywords_[i].kind = token; 905 keywords_[i].kind = token;
942 keywords_[i].keyword_chars = Token::Str(token); 906 keywords_[i].keyword_chars = Token::Str(token);
943 keywords_[i].keyword_len = strlen(Token::Str(token)); 907 keywords_[i].keyword_len = strlen(Token::Str(token));
944 keywords_[i].keyword_symbol = &Symbols::Token(token); 908 keywords_[i].keyword_symbol = &Symbols::Token(token);
945 909
946 int ch = keywords_[i].keyword_chars[0] - 'a'; 910 int ch = keywords_[i].keyword_chars[0] - 'a';
947 if (keywords_char_offset_[ch] == Token::kNumKeywords) { 911 if (keywords_char_offset_[ch] == Token::kNumKeywords) {
948 keywords_char_offset_[ch] = i; 912 keywords_char_offset_[ch] = i;
949 } 913 }
950 } 914 }
951 } 915 }
952 916
953 } // namespace dart 917 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/scanner.h ('k') | runtime/vm/scanner_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698