| 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 |