OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 if (MatchKeywordStart(input, "with", 1, Token::WITH)) return; | 312 if (MatchKeywordStart(input, "with", 1, Token::WITH)) return; |
313 break; | 313 break; |
314 default: | 314 default: |
315 UNREACHABLE(); | 315 UNREACHABLE(); |
316 } | 316 } |
317 // On fallthrough, it's a failure. | 317 // On fallthrough, it's a failure. |
318 state_ = UNMATCHABLE; | 318 state_ = UNMATCHABLE; |
319 } | 319 } |
320 | 320 |
321 | 321 |
| 322 |
| 323 // ---------------------------------------------------------------------------- |
| 324 // Scanner::LiteralScope |
| 325 |
| 326 Scanner::LiteralScope::LiteralScope(Scanner* self) |
| 327 : scanner_(self), complete_(false) { |
| 328 self->StartLiteral(); |
| 329 } |
| 330 |
| 331 |
| 332 Scanner::LiteralScope::~LiteralScope() { |
| 333 if (!complete_) scanner_->DropLiteral(); |
| 334 } |
| 335 |
| 336 |
| 337 void Scanner::LiteralScope::Complete() { |
| 338 scanner_->TerminateLiteral(); |
| 339 complete_ = true; |
| 340 } |
| 341 |
322 // ---------------------------------------------------------------------------- | 342 // ---------------------------------------------------------------------------- |
323 // Scanner | 343 // Scanner |
324 | 344 |
325 Scanner::Scanner(ParserMode pre) | 345 Scanner::Scanner(ParserMode pre) |
326 : is_pre_parsing_(pre == PREPARSE), stack_overflow_(false) { } | 346 : is_pre_parsing_(pre == PREPARSE), stack_overflow_(false) { } |
327 | 347 |
328 | 348 |
329 void Scanner::Initialize(Handle<String> source, | 349 void Scanner::Initialize(Handle<String> source, |
330 ParserLanguage language) { | 350 ParserLanguage language) { |
331 Init(source, NULL, 0, source->length(), language); | 351 Init(source, NULL, 0, source->length(), language); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 start_position, | 399 start_position, |
380 end_position); | 400 end_position); |
381 source_ = &char_stream_buffer_; | 401 source_ = &char_stream_buffer_; |
382 } | 402 } |
383 | 403 |
384 is_parsing_json_ = (language == JSON); | 404 is_parsing_json_ = (language == JSON); |
385 | 405 |
386 // Set c0_ (one character ahead) | 406 // Set c0_ (one character ahead) |
387 ASSERT(kCharacterLookaheadBufferSize == 1); | 407 ASSERT(kCharacterLookaheadBufferSize == 1); |
388 Advance(); | 408 Advance(); |
389 // Initialise current_ to not refer to a literal. | 409 // Initialize current_ to not refer to a literal. |
390 current_.literal_chars = Vector<const char>(); | 410 current_.literal_chars = Vector<const char>(); |
| 411 // Reset literal buffer. |
| 412 literal_buffer_.Reset(); |
391 | 413 |
392 // Skip initial whitespace allowing HTML comment ends just like | 414 // Skip initial whitespace allowing HTML comment ends just like |
393 // after a newline and scan first token. | 415 // after a newline and scan first token. |
394 has_line_terminator_before_next_ = true; | 416 has_line_terminator_before_next_ = true; |
395 SkipWhiteSpace(); | 417 SkipWhiteSpace(); |
396 Scan(); | 418 Scan(); |
397 } | 419 } |
398 | 420 |
399 | 421 |
400 Token::Value Scanner::Next() { | 422 Token::Value Scanner::Next() { |
(...skipping 15 matching lines...) Expand all Loading... |
416 | 438 |
417 void Scanner::StartLiteral() { | 439 void Scanner::StartLiteral() { |
418 literal_buffer_.StartLiteral(); | 440 literal_buffer_.StartLiteral(); |
419 } | 441 } |
420 | 442 |
421 | 443 |
422 void Scanner::AddChar(uc32 c) { | 444 void Scanner::AddChar(uc32 c) { |
423 literal_buffer_.AddChar(c); | 445 literal_buffer_.AddChar(c); |
424 } | 446 } |
425 | 447 |
| 448 |
426 void Scanner::TerminateLiteral() { | 449 void Scanner::TerminateLiteral() { |
427 next_.literal_chars = literal_buffer_.EndLiteral(); | 450 next_.literal_chars = literal_buffer_.EndLiteral(); |
428 } | 451 } |
429 | 452 |
430 | 453 |
| 454 void Scanner::DropLiteral() { |
| 455 literal_buffer_.DropLiteral(); |
| 456 } |
| 457 |
| 458 |
431 void Scanner::AddCharAdvance() { | 459 void Scanner::AddCharAdvance() { |
432 AddChar(c0_); | 460 AddChar(c0_); |
433 Advance(); | 461 Advance(); |
434 } | 462 } |
435 | 463 |
436 | 464 |
437 static inline bool IsByteOrderMark(uc32 c) { | 465 static inline bool IsByteOrderMark(uc32 c) { |
438 // The Unicode value U+FFFE is guaranteed never to be assigned as a | 466 // The Unicode value U+FFFE is guaranteed never to be assigned as a |
439 // Unicode character; this implies that in a Unicode context the | 467 // Unicode character; this implies that in a Unicode context the |
440 // 0xFF, 0xFE byte pattern can only be interpreted as the U+FEFF | 468 // 0xFF, 0xFE byte pattern can only be interpreted as the U+FEFF |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
629 } while (token == Token::WHITESPACE); | 657 } while (token == Token::WHITESPACE); |
630 | 658 |
631 next_.location.end_pos = source_pos(); | 659 next_.location.end_pos = source_pos(); |
632 next_.token = token; | 660 next_.token = token; |
633 } | 661 } |
634 | 662 |
635 | 663 |
636 Token::Value Scanner::ScanJsonString() { | 664 Token::Value Scanner::ScanJsonString() { |
637 ASSERT_EQ('"', c0_); | 665 ASSERT_EQ('"', c0_); |
638 Advance(); | 666 Advance(); |
639 StartLiteral(); | 667 LiteralScope literal(this); |
640 while (c0_ != '"' && c0_ > 0) { | 668 while (c0_ != '"' && c0_ > 0) { |
641 // Check for control character (0x00-0x1f) or unterminated string (<0). | 669 // Check for control character (0x00-0x1f) or unterminated string (<0). |
642 if (c0_ < 0x20) return Token::ILLEGAL; | 670 if (c0_ < 0x20) return Token::ILLEGAL; |
643 if (c0_ != '\\') { | 671 if (c0_ != '\\') { |
644 AddCharAdvance(); | 672 AddCharAdvance(); |
645 } else { | 673 } else { |
646 Advance(); | 674 Advance(); |
647 switch (c0_) { | 675 switch (c0_) { |
648 case '"': | 676 case '"': |
649 case '\\': | 677 case '\\': |
(...skipping 13 matching lines...) Expand all Loading... |
663 AddChar('\x0d'); | 691 AddChar('\x0d'); |
664 break; | 692 break; |
665 case 't': | 693 case 't': |
666 AddChar('\x09'); | 694 AddChar('\x09'); |
667 break; | 695 break; |
668 case 'u': { | 696 case 'u': { |
669 uc32 value = 0; | 697 uc32 value = 0; |
670 for (int i = 0; i < 4; i++) { | 698 for (int i = 0; i < 4; i++) { |
671 Advance(); | 699 Advance(); |
672 int digit = HexValue(c0_); | 700 int digit = HexValue(c0_); |
673 if (digit < 0) return Token::ILLEGAL; | 701 if (digit < 0) { |
| 702 return Token::ILLEGAL; |
| 703 } |
674 value = value * 16 + digit; | 704 value = value * 16 + digit; |
675 } | 705 } |
676 AddChar(value); | 706 AddChar(value); |
677 break; | 707 break; |
678 } | 708 } |
679 default: | 709 default: |
680 return Token::ILLEGAL; | 710 return Token::ILLEGAL; |
681 } | 711 } |
682 Advance(); | 712 Advance(); |
683 } | 713 } |
684 } | 714 } |
685 if (c0_ != '"') { | 715 if (c0_ != '"') { |
686 return Token::ILLEGAL; | 716 return Token::ILLEGAL; |
687 } | 717 } |
688 TerminateLiteral(); | 718 literal.Complete(); |
689 Advance(); | 719 Advance(); |
690 return Token::STRING; | 720 return Token::STRING; |
691 } | 721 } |
692 | 722 |
693 | 723 |
694 Token::Value Scanner::ScanJsonNumber() { | 724 Token::Value Scanner::ScanJsonNumber() { |
695 StartLiteral(); | 725 LiteralScope literal(this); |
696 if (c0_ == '-') AddCharAdvance(); | 726 if (c0_ == '-') AddCharAdvance(); |
697 if (c0_ == '0') { | 727 if (c0_ == '0') { |
698 AddCharAdvance(); | 728 AddCharAdvance(); |
699 // Prefix zero is only allowed if it's the only digit before | 729 // Prefix zero is only allowed if it's the only digit before |
700 // a decimal point or exponent. | 730 // a decimal point or exponent. |
701 if ('0' <= c0_ && c0_ <= '9') return Token::ILLEGAL; | 731 if ('0' <= c0_ && c0_ <= '9') return Token::ILLEGAL; |
702 } else { | 732 } else { |
703 if (c0_ < '1' || c0_ > '9') return Token::ILLEGAL; | 733 if (c0_ < '1' || c0_ > '9') return Token::ILLEGAL; |
704 do { | 734 do { |
705 AddCharAdvance(); | 735 AddCharAdvance(); |
706 } while (c0_ >= '0' && c0_ <= '9'); | 736 } while (c0_ >= '0' && c0_ <= '9'); |
707 } | 737 } |
708 if (c0_ == '.') { | 738 if (c0_ == '.') { |
709 AddCharAdvance(); | 739 AddCharAdvance(); |
710 if (c0_ < '0' || c0_ > '9') return Token::ILLEGAL; | 740 if (c0_ < '0' || c0_ > '9') return Token::ILLEGAL; |
711 do { | 741 do { |
712 AddCharAdvance(); | 742 AddCharAdvance(); |
713 } while (c0_ >= '0' && c0_ <= '9'); | 743 } while (c0_ >= '0' && c0_ <= '9'); |
714 } | 744 } |
715 if ((c0_ | 0x20) == 'e') { | 745 if ((c0_ | 0x20) == 'e') { |
716 AddCharAdvance(); | 746 AddCharAdvance(); |
717 if (c0_ == '-' || c0_ == '+') AddCharAdvance(); | 747 if (c0_ == '-' || c0_ == '+') AddCharAdvance(); |
718 if (c0_ < '0' || c0_ > '9') return Token::ILLEGAL; | 748 if (c0_ < '0' || c0_ > '9') return Token::ILLEGAL; |
719 do { | 749 do { |
720 AddCharAdvance(); | 750 AddCharAdvance(); |
721 } while (c0_ >= '0' && c0_ <= '9'); | 751 } while (c0_ >= '0' && c0_ <= '9'); |
722 } | 752 } |
723 TerminateLiteral(); | 753 literal.Complete(); |
724 return Token::NUMBER; | 754 return Token::NUMBER; |
725 } | 755 } |
726 | 756 |
727 | 757 |
728 Token::Value Scanner::ScanJsonIdentifier(const char* text, | 758 Token::Value Scanner::ScanJsonIdentifier(const char* text, |
729 Token::Value token) { | 759 Token::Value token) { |
730 StartLiteral(); | 760 LiteralScope literal(this); |
731 while (*text != '\0') { | 761 while (*text != '\0') { |
732 if (c0_ != *text) return Token::ILLEGAL; | 762 if (c0_ != *text) return Token::ILLEGAL; |
733 Advance(); | 763 Advance(); |
734 text++; | 764 text++; |
735 } | 765 } |
736 if (kIsIdentifierPart.get(c0_)) return Token::ILLEGAL; | 766 if (kIsIdentifierPart.get(c0_)) return Token::ILLEGAL; |
737 TerminateLiteral(); | 767 literal.Complete(); |
738 return token; | 768 return token; |
739 } | 769 } |
740 | 770 |
741 | 771 |
742 void Scanner::ScanJavaScript() { | 772 void Scanner::ScanJavaScript() { |
743 next_.literal_chars = Vector<const char>(); | 773 next_.literal_chars = Vector<const char>(); |
744 Token::Value token; | 774 Token::Value token; |
745 has_line_terminator_before_next_ = false; | 775 has_line_terminator_before_next_ = false; |
746 do { | 776 do { |
747 // Remember the position of the next token | 777 // Remember the position of the next token |
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1070 // should be illegal, but they are commonly handled | 1100 // should be illegal, but they are commonly handled |
1071 // as non-escaped characters by JS VMs. | 1101 // as non-escaped characters by JS VMs. |
1072 AddChar(c); | 1102 AddChar(c); |
1073 } | 1103 } |
1074 | 1104 |
1075 | 1105 |
1076 Token::Value Scanner::ScanString() { | 1106 Token::Value Scanner::ScanString() { |
1077 uc32 quote = c0_; | 1107 uc32 quote = c0_; |
1078 Advance(); // consume quote | 1108 Advance(); // consume quote |
1079 | 1109 |
1080 StartLiteral(); | 1110 LiteralScope literal(this); |
1081 while (c0_ != quote && c0_ >= 0 && !kIsLineTerminator.get(c0_)) { | 1111 while (c0_ != quote && c0_ >= 0 && !kIsLineTerminator.get(c0_)) { |
1082 uc32 c = c0_; | 1112 uc32 c = c0_; |
1083 Advance(); | 1113 Advance(); |
1084 if (c == '\\') { | 1114 if (c == '\\') { |
1085 if (c0_ < 0) return Token::ILLEGAL; | 1115 if (c0_ < 0) return Token::ILLEGAL; |
1086 ScanEscape(); | 1116 ScanEscape(); |
1087 } else { | 1117 } else { |
1088 AddChar(c); | 1118 AddChar(c); |
1089 } | 1119 } |
1090 } | 1120 } |
1091 if (c0_ != quote) { | 1121 if (c0_ != quote) return Token::ILLEGAL; |
1092 return Token::ILLEGAL; | 1122 literal.Complete(); |
1093 } | |
1094 TerminateLiteral(); | |
1095 | 1123 |
1096 Advance(); // consume quote | 1124 Advance(); // consume quote |
1097 return Token::STRING; | 1125 return Token::STRING; |
1098 } | 1126 } |
1099 | 1127 |
1100 | 1128 |
1101 Token::Value Scanner::Select(Token::Value tok) { | 1129 Token::Value Scanner::Select(Token::Value tok) { |
1102 Advance(); | 1130 Advance(); |
1103 return tok; | 1131 return tok; |
1104 } | 1132 } |
(...skipping 15 matching lines...) Expand all Loading... |
1120 while (IsDecimalDigit(c0_)) | 1148 while (IsDecimalDigit(c0_)) |
1121 AddCharAdvance(); | 1149 AddCharAdvance(); |
1122 } | 1150 } |
1123 | 1151 |
1124 | 1152 |
1125 Token::Value Scanner::ScanNumber(bool seen_period) { | 1153 Token::Value Scanner::ScanNumber(bool seen_period) { |
1126 ASSERT(IsDecimalDigit(c0_)); // the first digit of the number or the fraction | 1154 ASSERT(IsDecimalDigit(c0_)); // the first digit of the number or the fraction |
1127 | 1155 |
1128 enum { DECIMAL, HEX, OCTAL } kind = DECIMAL; | 1156 enum { DECIMAL, HEX, OCTAL } kind = DECIMAL; |
1129 | 1157 |
1130 StartLiteral(); | 1158 LiteralScope literal(this); |
1131 if (seen_period) { | 1159 if (seen_period) { |
1132 // we have already seen a decimal point of the float | 1160 // we have already seen a decimal point of the float |
1133 AddChar('.'); | 1161 AddChar('.'); |
1134 ScanDecimalDigits(); // we know we have at least one digit | 1162 ScanDecimalDigits(); // we know we have at least one digit |
1135 | 1163 |
1136 } else { | 1164 } else { |
1137 // if the first character is '0' we must check for octals and hex | 1165 // if the first character is '0' we must check for octals and hex |
1138 if (c0_ == '0') { | 1166 if (c0_ == '0') { |
1139 AddCharAdvance(); | 1167 AddCharAdvance(); |
1140 | 1168 |
1141 // either 0, 0exxx, 0Exxx, 0.xxx, an octal number, or a hex number | 1169 // either 0, 0exxx, 0Exxx, 0.xxx, an octal number, or a hex number |
1142 if (c0_ == 'x' || c0_ == 'X') { | 1170 if (c0_ == 'x' || c0_ == 'X') { |
1143 // hex number | 1171 // hex number |
1144 kind = HEX; | 1172 kind = HEX; |
1145 AddCharAdvance(); | 1173 AddCharAdvance(); |
1146 if (!IsHexDigit(c0_)) | 1174 if (!IsHexDigit(c0_)) { |
1147 // we must have at least one hex digit after 'x'/'X' | 1175 // we must have at least one hex digit after 'x'/'X' |
1148 return Token::ILLEGAL; | 1176 return Token::ILLEGAL; |
1149 while (IsHexDigit(c0_)) | 1177 } |
| 1178 while (IsHexDigit(c0_)) { |
1150 AddCharAdvance(); | 1179 AddCharAdvance(); |
1151 | 1180 } |
1152 } else if ('0' <= c0_ && c0_ <= '7') { | 1181 } else if ('0' <= c0_ && c0_ <= '7') { |
1153 // (possible) octal number | 1182 // (possible) octal number |
1154 kind = OCTAL; | 1183 kind = OCTAL; |
1155 while (true) { | 1184 while (true) { |
1156 if (c0_ == '8' || c0_ == '9') { | 1185 if (c0_ == '8' || c0_ == '9') { |
1157 kind = DECIMAL; | 1186 kind = DECIMAL; |
1158 break; | 1187 break; |
1159 } | 1188 } |
1160 if (c0_ < '0' || '7' < c0_) break; | 1189 if (c0_ < '0' || '7' < c0_) break; |
1161 AddCharAdvance(); | 1190 AddCharAdvance(); |
(...skipping 12 matching lines...) Expand all Loading... |
1174 } | 1203 } |
1175 | 1204 |
1176 // scan exponent, if any | 1205 // scan exponent, if any |
1177 if (c0_ == 'e' || c0_ == 'E') { | 1206 if (c0_ == 'e' || c0_ == 'E') { |
1178 ASSERT(kind != HEX); // 'e'/'E' must be scanned as part of the hex number | 1207 ASSERT(kind != HEX); // 'e'/'E' must be scanned as part of the hex number |
1179 if (kind == OCTAL) return Token::ILLEGAL; // no exponent for octals allowed | 1208 if (kind == OCTAL) return Token::ILLEGAL; // no exponent for octals allowed |
1180 // scan exponent | 1209 // scan exponent |
1181 AddCharAdvance(); | 1210 AddCharAdvance(); |
1182 if (c0_ == '+' || c0_ == '-') | 1211 if (c0_ == '+' || c0_ == '-') |
1183 AddCharAdvance(); | 1212 AddCharAdvance(); |
1184 if (!IsDecimalDigit(c0_)) | 1213 if (!IsDecimalDigit(c0_)) { |
1185 // we must have at least one decimal digit after 'e'/'E' | 1214 // we must have at least one decimal digit after 'e'/'E' |
1186 return Token::ILLEGAL; | 1215 return Token::ILLEGAL; |
| 1216 } |
1187 ScanDecimalDigits(); | 1217 ScanDecimalDigits(); |
1188 } | 1218 } |
1189 TerminateLiteral(); | |
1190 | 1219 |
1191 // The source character immediately following a numeric literal must | 1220 // The source character immediately following a numeric literal must |
1192 // not be an identifier start or a decimal digit; see ECMA-262 | 1221 // not be an identifier start or a decimal digit; see ECMA-262 |
1193 // section 7.8.3, page 17 (note that we read only one decimal digit | 1222 // section 7.8.3, page 17 (note that we read only one decimal digit |
1194 // if the value is 0). | 1223 // if the value is 0). |
1195 if (IsDecimalDigit(c0_) || kIsIdentifierStart.get(c0_)) | 1224 if (IsDecimalDigit(c0_) || kIsIdentifierStart.get(c0_)) |
1196 return Token::ILLEGAL; | 1225 return Token::ILLEGAL; |
1197 | 1226 |
| 1227 literal.Complete(); |
| 1228 |
1198 return Token::NUMBER; | 1229 return Token::NUMBER; |
1199 } | 1230 } |
1200 | 1231 |
1201 | 1232 |
1202 uc32 Scanner::ScanIdentifierUnicodeEscape() { | 1233 uc32 Scanner::ScanIdentifierUnicodeEscape() { |
1203 Advance(); | 1234 Advance(); |
1204 if (c0_ != 'u') return unibrow::Utf8::kBadChar; | 1235 if (c0_ != 'u') return unibrow::Utf8::kBadChar; |
1205 Advance(); | 1236 Advance(); |
1206 uc32 c = ScanHexEscape('u', 4); | 1237 uc32 c = ScanHexEscape('u', 4); |
1207 // We do not allow a unicode escape sequence to start another | 1238 // We do not allow a unicode escape sequence to start another |
1208 // unicode escape sequence. | 1239 // unicode escape sequence. |
1209 if (c == '\\') return unibrow::Utf8::kBadChar; | 1240 if (c == '\\') return unibrow::Utf8::kBadChar; |
1210 return c; | 1241 return c; |
1211 } | 1242 } |
1212 | 1243 |
1213 | 1244 |
1214 Token::Value Scanner::ScanIdentifier() { | 1245 Token::Value Scanner::ScanIdentifier() { |
1215 ASSERT(kIsIdentifierStart.get(c0_)); | 1246 ASSERT(kIsIdentifierStart.get(c0_)); |
1216 | 1247 |
1217 StartLiteral(); | 1248 LiteralScope literal(this); |
1218 KeywordMatcher keyword_match; | 1249 KeywordMatcher keyword_match; |
1219 | 1250 |
1220 // Scan identifier start character. | 1251 // Scan identifier start character. |
1221 if (c0_ == '\\') { | 1252 if (c0_ == '\\') { |
1222 uc32 c = ScanIdentifierUnicodeEscape(); | 1253 uc32 c = ScanIdentifierUnicodeEscape(); |
1223 // Only allow legal identifier start characters. | 1254 // Only allow legal identifier start characters. |
1224 if (!kIsIdentifierStart.get(c)) return Token::ILLEGAL; | 1255 if (!kIsIdentifierStart.get(c)) return Token::ILLEGAL; |
1225 AddChar(c); | 1256 AddChar(c); |
1226 keyword_match.Fail(); | 1257 keyword_match.Fail(); |
1227 } else { | 1258 } else { |
1228 AddChar(c0_); | 1259 AddChar(c0_); |
1229 keyword_match.AddChar(c0_); | 1260 keyword_match.AddChar(c0_); |
1230 Advance(); | 1261 Advance(); |
1231 } | 1262 } |
1232 | 1263 |
1233 // Scan the rest of the identifier characters. | 1264 // Scan the rest of the identifier characters. |
1234 while (kIsIdentifierPart.get(c0_)) { | 1265 while (kIsIdentifierPart.get(c0_)) { |
1235 if (c0_ == '\\') { | 1266 if (c0_ == '\\') { |
1236 uc32 c = ScanIdentifierUnicodeEscape(); | 1267 uc32 c = ScanIdentifierUnicodeEscape(); |
1237 // Only allow legal identifier part characters. | 1268 // Only allow legal identifier part characters. |
1238 if (!kIsIdentifierPart.get(c)) return Token::ILLEGAL; | 1269 if (!kIsIdentifierPart.get(c)) return Token::ILLEGAL; |
1239 AddChar(c); | 1270 AddChar(c); |
1240 keyword_match.Fail(); | 1271 keyword_match.Fail(); |
1241 } else { | 1272 } else { |
1242 AddChar(c0_); | 1273 AddChar(c0_); |
1243 keyword_match.AddChar(c0_); | 1274 keyword_match.AddChar(c0_); |
1244 Advance(); | 1275 Advance(); |
1245 } | 1276 } |
1246 } | 1277 } |
1247 TerminateLiteral(); | 1278 literal.Complete(); |
1248 | 1279 |
1249 return keyword_match.token(); | 1280 return keyword_match.token(); |
1250 } | 1281 } |
1251 | 1282 |
1252 | 1283 |
1253 | 1284 |
1254 bool Scanner::IsIdentifier(unibrow::CharacterStream* buffer) { | 1285 bool Scanner::IsIdentifier(unibrow::CharacterStream* buffer) { |
1255 // Checks whether the buffer contains an identifier (no escape). | 1286 // Checks whether the buffer contains an identifier (no escape). |
1256 if (!buffer->has_more()) return false; | 1287 if (!buffer->has_more()) return false; |
1257 if (!kIsIdentifierStart.get(buffer->GetNext())) return false; | 1288 if (!kIsIdentifierStart.get(buffer->GetNext())) return false; |
1258 while (buffer->has_more()) { | 1289 while (buffer->has_more()) { |
1259 if (!kIsIdentifierPart.get(buffer->GetNext())) return false; | 1290 if (!kIsIdentifierPart.get(buffer->GetNext())) return false; |
1260 } | 1291 } |
1261 return true; | 1292 return true; |
1262 } | 1293 } |
1263 | 1294 |
1264 | 1295 |
1265 bool Scanner::ScanRegExpPattern(bool seen_equal) { | 1296 bool Scanner::ScanRegExpPattern(bool seen_equal) { |
1266 // Scan: ('/' | '/=') RegularExpressionBody '/' RegularExpressionFlags | 1297 // Scan: ('/' | '/=') RegularExpressionBody '/' RegularExpressionFlags |
1267 bool in_character_class = false; | 1298 bool in_character_class = false; |
1268 | 1299 |
1269 // Previous token is either '/' or '/=', in the second case, the | 1300 // Previous token is either '/' or '/=', in the second case, the |
1270 // pattern starts at =. | 1301 // pattern starts at =. |
1271 next_.location.beg_pos = source_pos() - (seen_equal ? 2 : 1); | 1302 next_.location.beg_pos = source_pos() - (seen_equal ? 2 : 1); |
1272 next_.location.end_pos = source_pos() - (seen_equal ? 1 : 0); | 1303 next_.location.end_pos = source_pos() - (seen_equal ? 1 : 0); |
1273 | 1304 |
1274 // Scan regular expression body: According to ECMA-262, 3rd, 7.8.5, | 1305 // Scan regular expression body: According to ECMA-262, 3rd, 7.8.5, |
1275 // the scanner should pass uninterpreted bodies to the RegExp | 1306 // the scanner should pass uninterpreted bodies to the RegExp |
1276 // constructor. | 1307 // constructor. |
1277 StartLiteral(); | 1308 LiteralScope literal(this); |
1278 if (seen_equal) | 1309 if (seen_equal) |
1279 AddChar('='); | 1310 AddChar('='); |
1280 | 1311 |
1281 while (c0_ != '/' || in_character_class) { | 1312 while (c0_ != '/' || in_character_class) { |
1282 if (kIsLineTerminator.get(c0_) || c0_ < 0) | 1313 if (kIsLineTerminator.get(c0_) || c0_ < 0) return false; |
1283 return false; | |
1284 if (c0_ == '\\') { // escaped character | 1314 if (c0_ == '\\') { // escaped character |
1285 AddCharAdvance(); | 1315 AddCharAdvance(); |
1286 if (kIsLineTerminator.get(c0_) || c0_ < 0) | 1316 if (kIsLineTerminator.get(c0_) || c0_ < 0) return false; |
1287 return false; | |
1288 AddCharAdvance(); | 1317 AddCharAdvance(); |
1289 } else { // unescaped character | 1318 } else { // unescaped character |
1290 if (c0_ == '[') | 1319 if (c0_ == '[') in_character_class = true; |
1291 in_character_class = true; | 1320 if (c0_ == ']') in_character_class = false; |
1292 if (c0_ == ']') | |
1293 in_character_class = false; | |
1294 AddCharAdvance(); | 1321 AddCharAdvance(); |
1295 } | 1322 } |
1296 } | 1323 } |
1297 Advance(); // consume '/' | 1324 Advance(); // consume '/' |
1298 | 1325 |
1299 TerminateLiteral(); | 1326 literal.Complete(); |
1300 | 1327 |
1301 return true; | 1328 return true; |
1302 } | 1329 } |
1303 | 1330 |
1304 bool Scanner::ScanRegExpFlags() { | 1331 bool Scanner::ScanRegExpFlags() { |
1305 // Scan regular expression flags. | 1332 // Scan regular expression flags. |
1306 StartLiteral(); | 1333 LiteralScope literal(this); |
1307 while (kIsIdentifierPart.get(c0_)) { | 1334 while (kIsIdentifierPart.get(c0_)) { |
1308 if (c0_ == '\\') { | 1335 if (c0_ == '\\') { |
1309 uc32 c = ScanIdentifierUnicodeEscape(); | 1336 uc32 c = ScanIdentifierUnicodeEscape(); |
1310 if (c != static_cast<uc32>(unibrow::Utf8::kBadChar)) { | 1337 if (c != static_cast<uc32>(unibrow::Utf8::kBadChar)) { |
1311 // We allow any escaped character, unlike the restriction on | 1338 // We allow any escaped character, unlike the restriction on |
1312 // IdentifierPart when it is used to build an IdentifierName. | 1339 // IdentifierPart when it is used to build an IdentifierName. |
1313 AddChar(c); | 1340 AddChar(c); |
1314 continue; | 1341 continue; |
1315 } | 1342 } |
1316 } | 1343 } |
1317 AddCharAdvance(); | 1344 AddCharAdvance(); |
1318 } | 1345 } |
1319 TerminateLiteral(); | 1346 literal.Complete(); |
1320 | 1347 |
1321 next_.location.end_pos = source_pos() - 1; | 1348 next_.location.end_pos = source_pos() - 1; |
1322 return true; | 1349 return true; |
1323 } | 1350 } |
1324 | 1351 |
1325 } } // namespace v8::internal | 1352 } } // namespace v8::internal |
OLD | NEW |