OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
290 static int Precedence(Token::Value token, bool accept_IN) { | 290 static int Precedence(Token::Value token, bool accept_IN) { |
291 if (token == Token::IN && !accept_IN) | 291 if (token == Token::IN && !accept_IN) |
292 return 0; // 0 precedence will terminate binary expression parsing | 292 return 0; // 0 precedence will terminate binary expression parsing |
293 return Token::Precedence(token); | 293 return Token::Precedence(token); |
294 } | 294 } |
295 | 295 |
296 typename Traits::Type::Factory* factory() { | 296 typename Traits::Type::Factory* factory() { |
297 return function_state_->factory(); | 297 return function_state_->factory(); |
298 } | 298 } |
299 | 299 |
300 bool is_sloppy_mode() const { return scope_->is_sloppy_mode(); } | 300 StrictMode strict_mode() { return scope_->strict_mode(); } |
301 | |
302 bool is_generator() const { return function_state_->is_generator(); } | 301 bool is_generator() const { return function_state_->is_generator(); } |
303 | 302 |
304 // Report syntax errors. | 303 // Report syntax errors. |
305 void ReportMessage(const char* message, Vector<const char*> args) { | 304 void ReportMessage(const char* message, Vector<const char*> args) { |
306 Scanner::Location source_location = scanner()->location(); | 305 Scanner::Location source_location = scanner()->location(); |
307 Traits::ReportMessageAt(source_location, message, args); | 306 Traits::ReportMessageAt(source_location, message, args); |
308 } | 307 } |
309 | 308 |
310 void ReportMessageAt(Scanner::Location location, const char* message) { | 309 void ReportMessageAt(Scanner::Location location, const char* message) { |
311 Traits::ReportMessageAt(location, message, Vector<const char*>::empty()); | 310 Traits::ReportMessageAt(location, message, Vector<const char*>::empty()); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 kGetterProperty = 1, | 357 kGetterProperty = 1, |
359 kSetterProperty = 2, | 358 kSetterProperty = 2, |
360 kValueProperty = 7, | 359 kValueProperty = 7, |
361 // Helper constants. | 360 // Helper constants. |
362 kValueFlag = 4 | 361 kValueFlag = 4 |
363 }; | 362 }; |
364 | 363 |
365 // Validation per ECMA 262 - 11.1.5 "Object Initialiser". | 364 // Validation per ECMA 262 - 11.1.5 "Object Initialiser". |
366 class ObjectLiteralChecker { | 365 class ObjectLiteralChecker { |
367 public: | 366 public: |
368 ObjectLiteralChecker(ParserBase* parser, LanguageMode mode) | 367 ObjectLiteralChecker(ParserBase* parser, StrictMode strict_mode) |
369 : parser_(parser), | 368 : parser_(parser), |
370 finder_(scanner()->unicode_cache()), | 369 finder_(scanner()->unicode_cache()), |
371 language_mode_(mode) { } | 370 strict_mode_(strict_mode) { } |
372 | 371 |
373 void CheckProperty(Token::Value property, PropertyKind type, bool* ok); | 372 void CheckProperty(Token::Value property, PropertyKind type, bool* ok); |
374 | 373 |
375 private: | 374 private: |
376 ParserBase* parser() const { return parser_; } | 375 ParserBase* parser() const { return parser_; } |
377 Scanner* scanner() const { return parser_->scanner(); } | 376 Scanner* scanner() const { return parser_->scanner(); } |
378 | 377 |
379 // Checks the type of conflict based on values coming from PropertyType. | 378 // Checks the type of conflict based on values coming from PropertyType. |
380 bool HasConflict(PropertyKind type1, PropertyKind type2) { | 379 bool HasConflict(PropertyKind type1, PropertyKind type2) { |
381 return (type1 & type2) != 0; | 380 return (type1 & type2) != 0; |
382 } | 381 } |
383 bool IsDataDataConflict(PropertyKind type1, PropertyKind type2) { | 382 bool IsDataDataConflict(PropertyKind type1, PropertyKind type2) { |
384 return ((type1 & type2) & kValueFlag) != 0; | 383 return ((type1 & type2) & kValueFlag) != 0; |
385 } | 384 } |
386 bool IsDataAccessorConflict(PropertyKind type1, PropertyKind type2) { | 385 bool IsDataAccessorConflict(PropertyKind type1, PropertyKind type2) { |
387 return ((type1 ^ type2) & kValueFlag) != 0; | 386 return ((type1 ^ type2) & kValueFlag) != 0; |
388 } | 387 } |
389 bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) { | 388 bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) { |
390 return ((type1 | type2) & kValueFlag) == 0; | 389 return ((type1 | type2) & kValueFlag) == 0; |
391 } | 390 } |
392 | 391 |
393 ParserBase* parser_; | 392 ParserBase* parser_; |
394 DuplicateFinder finder_; | 393 DuplicateFinder finder_; |
395 LanguageMode language_mode_; | 394 StrictMode strict_mode_; |
396 }; | 395 }; |
397 | 396 |
398 // If true, the next (and immediately following) function literal is | 397 // If true, the next (and immediately following) function literal is |
399 // preceded by a parenthesis. | 398 // preceded by a parenthesis. |
400 // Heuristically that means that the function will be called immediately, | 399 // Heuristically that means that the function will be called immediately, |
401 // so never lazily compile it. | 400 // so never lazily compile it. |
402 bool parenthesized_function_; | 401 bool parenthesized_function_; |
403 | 402 |
404 typename Traits::Type::Scope* scope_; // Scope stack. | 403 typename Traits::Type::Scope* scope_; // Scope stack. |
405 FunctionState* function_state_; // Function state stack. | 404 FunctionState* function_state_; // Function state stack. |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
556 PreParserExpressionList* operator->() { return this; } | 555 PreParserExpressionList* operator->() { return this; } |
557 void Add(PreParserExpression, void*) { } | 556 void Add(PreParserExpression, void*) { } |
558 }; | 557 }; |
559 | 558 |
560 | 559 |
561 class PreParserScope { | 560 class PreParserScope { |
562 public: | 561 public: |
563 explicit PreParserScope(PreParserScope* outer_scope, ScopeType scope_type) | 562 explicit PreParserScope(PreParserScope* outer_scope, ScopeType scope_type) |
564 : scope_type_(scope_type) { | 563 : scope_type_(scope_type) { |
565 if (outer_scope) { | 564 if (outer_scope) { |
566 scope_inside_with_ = | 565 scope_inside_with_ = outer_scope->scope_inside_with_ || is_with_scope(); |
567 outer_scope->scope_inside_with_ || is_with_scope(); | 566 strict_mode_ = outer_scope->strict_mode(); |
568 language_mode_ = outer_scope->language_mode(); | |
569 } else { | 567 } else { |
570 scope_inside_with_ = is_with_scope(); | 568 scope_inside_with_ = is_with_scope(); |
571 language_mode_ = SLOPPY_MODE; | 569 strict_mode_ = SLOPPY; |
572 } | 570 } |
573 } | 571 } |
574 | 572 |
575 bool is_with_scope() const { return scope_type_ == WITH_SCOPE; } | 573 bool is_with_scope() const { return scope_type_ == WITH_SCOPE; } |
576 bool is_sloppy_mode() const { | |
577 return language_mode() == SLOPPY_MODE; | |
578 } | |
579 bool is_extended_mode() { | |
580 return language_mode() == EXTENDED_MODE; | |
581 } | |
582 bool inside_with() const { | 574 bool inside_with() const { |
583 return scope_inside_with_; | 575 return scope_inside_with_; |
584 } | 576 } |
585 | 577 |
586 ScopeType type() { return scope_type_; } | 578 ScopeType type() { return scope_type_; } |
587 LanguageMode language_mode() const { return language_mode_; } | 579 StrictMode strict_mode() const { return strict_mode_; } |
588 void SetLanguageMode(LanguageMode language_mode) { | 580 void SetStrictMode(StrictMode strict_mode) { strict_mode_ = strict_mode; } |
589 language_mode_ = language_mode; | |
590 } | |
591 | 581 |
592 private: | 582 private: |
593 ScopeType scope_type_; | 583 ScopeType scope_type_; |
594 bool scope_inside_with_; | 584 bool scope_inside_with_; |
595 LanguageMode language_mode_; | 585 StrictMode strict_mode_; |
596 }; | 586 }; |
597 | 587 |
598 | 588 |
599 class PreParserFactory { | 589 class PreParserFactory { |
600 public: | 590 public: |
601 explicit PreParserFactory(void* extra_param) {} | 591 explicit PreParserFactory(void* extra_param) {} |
602 | 592 |
603 PreParserExpression NewRegExpLiteral(PreParserIdentifier js_pattern, | 593 PreParserExpression NewRegExpLiteral(PreParserIdentifier js_pattern, |
604 PreParserIdentifier js_flags, | 594 PreParserIdentifier js_flags, |
605 int literal_index, | 595 int literal_index, |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
756 // during parsing. | 746 // during parsing. |
757 PreParseResult PreParseProgram() { | 747 PreParseResult PreParseProgram() { |
758 PreParserScope scope(scope_, GLOBAL_SCOPE); | 748 PreParserScope scope(scope_, GLOBAL_SCOPE); |
759 FunctionState top_scope(&function_state_, &scope_, &scope, NULL); | 749 FunctionState top_scope(&function_state_, &scope_, &scope, NULL); |
760 bool ok = true; | 750 bool ok = true; |
761 int start_position = scanner()->peek_location().beg_pos; | 751 int start_position = scanner()->peek_location().beg_pos; |
762 ParseSourceElements(Token::EOS, &ok); | 752 ParseSourceElements(Token::EOS, &ok); |
763 if (stack_overflow()) return kPreParseStackOverflow; | 753 if (stack_overflow()) return kPreParseStackOverflow; |
764 if (!ok) { | 754 if (!ok) { |
765 ReportUnexpectedToken(scanner()->current_token()); | 755 ReportUnexpectedToken(scanner()->current_token()); |
766 } else if (!scope_->is_sloppy_mode()) { | 756 } else if (scope_->strict_mode() == STRICT) { |
767 CheckOctalLiteral(start_position, scanner()->location().end_pos, &ok); | 757 CheckOctalLiteral(start_position, scanner()->location().end_pos, &ok); |
768 } | 758 } |
769 return kPreParseSuccess; | 759 return kPreParseSuccess; |
770 } | 760 } |
771 | 761 |
772 // Parses a single function literal, from the opening parentheses before | 762 // Parses a single function literal, from the opening parentheses before |
773 // parameters to the closing brace after the body. | 763 // parameters to the closing brace after the body. |
774 // Returns a FunctionEntry describing the body of the function in enough | 764 // Returns a FunctionEntry describing the body of the function in enough |
775 // detail that it can be lazily compiled. | 765 // detail that it can be lazily compiled. |
776 // The scanner is expected to have matched the "function" or "function*" | 766 // The scanner is expected to have matched the "function" or "function*" |
777 // keyword and parameters, and have consumed the initial '{'. | 767 // keyword and parameters, and have consumed the initial '{'. |
778 // At return, unless an error occurred, the scanner is positioned before the | 768 // At return, unless an error occurred, the scanner is positioned before the |
779 // the final '}'. | 769 // the final '}'. |
780 PreParseResult PreParseLazyFunction(LanguageMode mode, | 770 PreParseResult PreParseLazyFunction(StrictMode strict_mode, |
781 bool is_generator, | 771 bool is_generator, |
782 ParserRecorder* log); | 772 ParserRecorder* log); |
783 | 773 |
784 private: | 774 private: |
785 friend class PreParserTraits; | 775 friend class PreParserTraits; |
786 | 776 |
787 // These types form an algebra over syntactic categories that is just | 777 // These types form an algebra over syntactic categories that is just |
788 // rich enough to let us recognize and propagate the constructs that | 778 // rich enough to let us recognize and propagate the constructs that |
789 // are either being counted in the preparser data, or is important | 779 // are either being counted in the preparser data, or is important |
790 // to throw the correct syntax error exceptions. | 780 // to throw the correct syntax error exceptions. |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
966 case Token::NUMBER: | 956 case Token::NUMBER: |
967 return ReportMessageAt(source_location, "unexpected_token_number"); | 957 return ReportMessageAt(source_location, "unexpected_token_number"); |
968 case Token::STRING: | 958 case Token::STRING: |
969 return ReportMessageAt(source_location, "unexpected_token_string"); | 959 return ReportMessageAt(source_location, "unexpected_token_string"); |
970 case Token::IDENTIFIER: | 960 case Token::IDENTIFIER: |
971 return ReportMessageAt(source_location, "unexpected_token_identifier"); | 961 return ReportMessageAt(source_location, "unexpected_token_identifier"); |
972 case Token::FUTURE_RESERVED_WORD: | 962 case Token::FUTURE_RESERVED_WORD: |
973 return ReportMessageAt(source_location, "unexpected_reserved"); | 963 return ReportMessageAt(source_location, "unexpected_reserved"); |
974 case Token::YIELD: | 964 case Token::YIELD: |
975 case Token::FUTURE_STRICT_RESERVED_WORD: | 965 case Token::FUTURE_STRICT_RESERVED_WORD: |
976 return ReportMessageAt(source_location, | 966 return ReportMessageAt(source_location, strict_mode() == SLOPPY |
977 is_sloppy_mode() ? "unexpected_token_identifier" | 967 ? "unexpected_token_identifier" : "unexpected_strict_reserved"); |
978 : "unexpected_strict_reserved"); | |
979 default: | 968 default: |
980 const char* name = Token::String(token); | 969 const char* name = Token::String(token); |
981 ASSERT(name != NULL); | 970 ASSERT(name != NULL); |
982 Traits::ReportMessageAt( | 971 Traits::ReportMessageAt( |
983 source_location, "unexpected_token", Vector<const char*>(&name, 1)); | 972 source_location, "unexpected_token", Vector<const char*>(&name, 1)); |
984 } | 973 } |
985 } | 974 } |
986 | 975 |
987 | 976 |
988 template<class Traits> | 977 template<class Traits> |
989 typename Traits::Type::Identifier ParserBase<Traits>::ParseIdentifier( | 978 typename Traits::Type::Identifier ParserBase<Traits>::ParseIdentifier( |
990 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments, | 979 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments, |
991 bool* ok) { | 980 bool* ok) { |
992 Token::Value next = Next(); | 981 Token::Value next = Next(); |
993 if (next == Token::IDENTIFIER) { | 982 if (next == Token::IDENTIFIER) { |
994 typename Traits::Type::Identifier name = this->GetSymbol(scanner()); | 983 typename Traits::Type::Identifier name = this->GetSymbol(scanner()); |
995 if (allow_eval_or_arguments == kDontAllowEvalOrArguments && | 984 if (allow_eval_or_arguments == kDontAllowEvalOrArguments && |
996 !is_sloppy_mode() && this->IsEvalOrArguments(name)) { | 985 strict_mode() == STRICT && this->IsEvalOrArguments(name)) { |
997 ReportMessageAt(scanner()->location(), "strict_eval_arguments"); | 986 ReportMessageAt(scanner()->location(), "strict_eval_arguments"); |
998 *ok = false; | 987 *ok = false; |
999 } | 988 } |
1000 return name; | 989 return name; |
1001 } else if (is_sloppy_mode() && (next == Token::FUTURE_STRICT_RESERVED_WORD || | 990 } else if (strict_mode() == SLOPPY && |
1002 (next == Token::YIELD && !is_generator()))) { | 991 (next == Token::FUTURE_STRICT_RESERVED_WORD || |
| 992 (next == Token::YIELD && !is_generator()))) { |
1003 return this->GetSymbol(scanner()); | 993 return this->GetSymbol(scanner()); |
1004 } else { | 994 } else { |
1005 this->ReportUnexpectedToken(next); | 995 this->ReportUnexpectedToken(next); |
1006 *ok = false; | 996 *ok = false; |
1007 return Traits::EmptyIdentifier(); | 997 return Traits::EmptyIdentifier(); |
1008 } | 998 } |
1009 } | 999 } |
1010 | 1000 |
1011 | 1001 |
1012 template <class Traits> | 1002 template <class Traits> |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1251 old = finder_.AddNumber(scanner()->literal_ascii_string(), type); | 1241 old = finder_.AddNumber(scanner()->literal_ascii_string(), type); |
1252 } else if (scanner()->is_literal_ascii()) { | 1242 } else if (scanner()->is_literal_ascii()) { |
1253 old = finder_.AddAsciiSymbol(scanner()->literal_ascii_string(), type); | 1243 old = finder_.AddAsciiSymbol(scanner()->literal_ascii_string(), type); |
1254 } else { | 1244 } else { |
1255 old = finder_.AddUtf16Symbol(scanner()->literal_utf16_string(), type); | 1245 old = finder_.AddUtf16Symbol(scanner()->literal_utf16_string(), type); |
1256 } | 1246 } |
1257 PropertyKind old_type = static_cast<PropertyKind>(old); | 1247 PropertyKind old_type = static_cast<PropertyKind>(old); |
1258 if (HasConflict(old_type, type)) { | 1248 if (HasConflict(old_type, type)) { |
1259 if (IsDataDataConflict(old_type, type)) { | 1249 if (IsDataDataConflict(old_type, type)) { |
1260 // Both are data properties. | 1250 // Both are data properties. |
1261 if (language_mode_ == SLOPPY_MODE) return; | 1251 if (strict_mode_ == SLOPPY) return; |
1262 parser()->ReportMessageAt(scanner()->location(), | 1252 parser()->ReportMessageAt(scanner()->location(), |
1263 "strict_duplicate_property"); | 1253 "strict_duplicate_property"); |
1264 } else if (IsDataAccessorConflict(old_type, type)) { | 1254 } else if (IsDataAccessorConflict(old_type, type)) { |
1265 // Both a data and an accessor property with the same name. | 1255 // Both a data and an accessor property with the same name. |
1266 parser()->ReportMessageAt(scanner()->location(), | 1256 parser()->ReportMessageAt(scanner()->location(), |
1267 "accessor_data_property"); | 1257 "accessor_data_property"); |
1268 } else { | 1258 } else { |
1269 ASSERT(IsAccessorAccessorConflict(old_type, type)); | 1259 ASSERT(IsAccessorAccessorConflict(old_type, type)); |
1270 // Both accessors of the same type. | 1260 // Both accessors of the same type. |
1271 parser()->ReportMessageAt(scanner()->location(), | 1261 parser()->ReportMessageAt(scanner()->location(), |
1272 "accessor_get_set"); | 1262 "accessor_get_set"); |
1273 } | 1263 } |
1274 *ok = false; | 1264 *ok = false; |
1275 } | 1265 } |
1276 } | 1266 } |
1277 | 1267 |
1278 | 1268 |
1279 } } // v8::internal | 1269 } } // v8::internal |
1280 | 1270 |
1281 #endif // V8_PREPARSER_H | 1271 #endif // V8_PREPARSER_H |
OLD | NEW |