OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_PARSING_PARSER_BASE_H | 5 #ifndef V8_PARSING_PARSER_BASE_H |
6 #define V8_PARSING_PARSER_BASE_H | 6 #define V8_PARSING_PARSER_BASE_H |
7 | 7 |
8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
9 #include "src/bailout-reason.h" | 9 #include "src/bailout-reason.h" |
10 #include "src/base/hashmap.h" | 10 #include "src/base/hashmap.h" |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 | 112 |
113 struct FormalParametersBase { | 113 struct FormalParametersBase { |
114 explicit FormalParametersBase(Scope* scope) : scope(scope) {} | 114 explicit FormalParametersBase(Scope* scope) : scope(scope) {} |
115 Scope* scope; | 115 Scope* scope; |
116 bool has_rest = false; | 116 bool has_rest = false; |
117 bool is_simple = true; | 117 bool is_simple = true; |
118 int materialized_literals_count = 0; | 118 int materialized_literals_count = 0; |
119 }; | 119 }; |
120 | 120 |
121 | 121 |
| 122 // ---------------------------------------------------------------------------- |
| 123 // The CHECK_OK macro is a convenient macro to enforce error |
| 124 // handling for functions that may fail (by returning !*ok). |
| 125 // |
| 126 // CAUTION: This macro appends extra statements after a call, |
| 127 // thus it must never be used where only a single statement |
| 128 // is correct (e.g. an if statement branch w/o braces)! |
| 129 |
| 130 #define CHECK_OK ok); \ |
| 131 if (!*ok) return this->EmptyExpression(); \ |
| 132 ((void)0 |
| 133 #define DUMMY ) // to make indentation work |
| 134 #undef DUMMY |
| 135 |
| 136 // Used in functions where the return type is not ExpressionT. |
| 137 #define CHECK_OK_CUSTOM(x) ok); \ |
| 138 if (!*ok) return this->x(); \ |
| 139 ((void)0 |
| 140 #define DUMMY ) // to make indentation work |
| 141 #undef DUMMY |
| 142 |
| 143 |
122 // Common base class shared between parser and pre-parser. Traits encapsulate | 144 // Common base class shared between parser and pre-parser. Traits encapsulate |
123 // the differences between Parser and PreParser: | 145 // the differences between Parser and PreParser: |
124 | 146 |
125 // - Return types: For example, Parser functions return Expression* and | 147 // - Return types: For example, Parser functions return Expression* and |
126 // PreParser functions return PreParserExpression. | 148 // PreParser functions return PreParserExpression. |
127 | 149 |
128 // - Creating parse tree nodes: Parser generates an AST during the recursive | 150 // - Creating parse tree nodes: Parser generates an AST during the recursive |
129 // descent. PreParser doesn't create a tree. Instead, it passes around minimal | 151 // descent. PreParser doesn't create a tree. Instead, it passes around minimal |
130 // data objects (PreParserExpression, PreParserIdentifier etc.) which contain | 152 // data objects (PreParserExpression, PreParserIdentifier etc.) which contain |
131 // just enough data for the upper layer functions. PreParserFactory is | 153 // just enough data for the upper layer functions. PreParserFactory is |
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 return; | 685 return; |
664 } | 686 } |
665 if (scanner()->HasAnyLineTerminatorBeforeNext() || | 687 if (scanner()->HasAnyLineTerminatorBeforeNext() || |
666 tok == Token::RBRACE || | 688 tok == Token::RBRACE || |
667 tok == Token::EOS) { | 689 tok == Token::EOS) { |
668 return; | 690 return; |
669 } | 691 } |
670 Expect(Token::SEMICOLON, ok); | 692 Expect(Token::SEMICOLON, ok); |
671 } | 693 } |
672 | 694 |
| 695 // A dummy function, just useful as an argument to CHECK_OK_CUSTOM. |
| 696 static void Void() {} |
| 697 |
673 bool is_any_identifier(Token::Value token) { | 698 bool is_any_identifier(Token::Value token) { |
674 return token == Token::IDENTIFIER || token == Token::ENUM || | 699 return token == Token::IDENTIFIER || token == Token::ENUM || |
675 token == Token::AWAIT || token == Token::ASYNC || | 700 token == Token::AWAIT || token == Token::ASYNC || |
676 token == Token::FUTURE_STRICT_RESERVED_WORD || token == Token::LET || | 701 token == Token::FUTURE_STRICT_RESERVED_WORD || token == Token::LET || |
677 token == Token::STATIC || token == Token::YIELD; | 702 token == Token::STATIC || token == Token::YIELD; |
678 } | 703 } |
679 bool peek_any_identifier() { return is_any_identifier(peek()); } | 704 bool peek_any_identifier() { return is_any_identifier(peek()); } |
680 | 705 |
681 bool CheckContextualKeyword(Vector<const char> keyword) { | 706 bool CheckContextualKeyword(Vector<const char> keyword) { |
682 if (PeekContextualKeyword(keyword)) { | 707 if (PeekContextualKeyword(keyword)) { |
683 Consume(Token::IDENTIFIER); | 708 Consume(Token::IDENTIFIER); |
684 return true; | 709 return true; |
685 } | 710 } |
686 return false; | 711 return false; |
687 } | 712 } |
688 | 713 |
689 bool PeekContextualKeyword(Vector<const char> keyword) { | 714 bool PeekContextualKeyword(Vector<const char> keyword) { |
690 return peek() == Token::IDENTIFIER && | 715 return peek() == Token::IDENTIFIER && |
691 scanner()->is_next_contextual_keyword(keyword); | 716 scanner()->is_next_contextual_keyword(keyword); |
692 } | 717 } |
693 | 718 |
694 void ExpectMetaProperty(Vector<const char> property_name, | 719 void ExpectMetaProperty(Vector<const char> property_name, |
695 const char* full_name, int pos, bool* ok); | 720 const char* full_name, int pos, bool* ok); |
696 | 721 |
697 void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) { | 722 void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) { |
698 Expect(Token::IDENTIFIER, ok); | 723 Expect(Token::IDENTIFIER, CHECK_OK_CUSTOM(Void)); |
699 if (!*ok) return; | |
700 if (!scanner()->is_literal_contextual_keyword(keyword)) { | 724 if (!scanner()->is_literal_contextual_keyword(keyword)) { |
701 ReportUnexpectedToken(scanner()->current_token()); | 725 ReportUnexpectedToken(scanner()->current_token()); |
702 *ok = false; | 726 *ok = false; |
703 } | 727 } |
704 } | 728 } |
705 | 729 |
706 bool CheckInOrOf(ForEachStatement::VisitMode* visit_mode, bool* ok) { | 730 bool CheckInOrOf(ForEachStatement::VisitMode* visit_mode, bool* ok) { |
707 if (Check(Token::IN)) { | 731 if (Check(Token::IN)) { |
708 *visit_mode = ForEachStatement::ENUMERATE; | 732 *visit_mode = ForEachStatement::ENUMERATE; |
709 return true; | 733 return true; |
(...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1304 const char* arg; | 1328 const char* arg; |
1305 GetUnexpectedTokenMessage(token, &message, &source_location, &arg); | 1329 GetUnexpectedTokenMessage(token, &message, &source_location, &arg); |
1306 Traits::ReportMessageAt(source_location, message, arg); | 1330 Traits::ReportMessageAt(source_location, message, arg); |
1307 } | 1331 } |
1308 | 1332 |
1309 | 1333 |
1310 template <class Traits> | 1334 template <class Traits> |
1311 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier( | 1335 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier( |
1312 AllowRestrictedIdentifiers allow_restricted_identifiers, bool* ok) { | 1336 AllowRestrictedIdentifiers allow_restricted_identifiers, bool* ok) { |
1313 ExpressionClassifier classifier(this); | 1337 ExpressionClassifier classifier(this); |
1314 auto result = ParseAndClassifyIdentifier(&classifier, ok); | 1338 auto result = |
1315 if (!*ok) return Traits::EmptyIdentifier(); | 1339 ParseAndClassifyIdentifier(&classifier, CHECK_OK_CUSTOM(EmptyIdentifier)); |
1316 | 1340 |
1317 if (allow_restricted_identifiers == kDontAllowRestrictedIdentifiers) { | 1341 if (allow_restricted_identifiers == kDontAllowRestrictedIdentifiers) { |
1318 ValidateAssignmentPattern(&classifier, ok); | 1342 ValidateAssignmentPattern(&classifier, CHECK_OK_CUSTOM(EmptyIdentifier)); |
1319 if (!*ok) return Traits::EmptyIdentifier(); | 1343 ValidateBindingPattern(&classifier, CHECK_OK_CUSTOM(EmptyIdentifier)); |
1320 ValidateBindingPattern(&classifier, ok); | |
1321 if (!*ok) return Traits::EmptyIdentifier(); | |
1322 } | 1344 } |
1323 | 1345 |
1324 return result; | 1346 return result; |
1325 } | 1347 } |
1326 | 1348 |
1327 | 1349 |
1328 template <class Traits> | 1350 template <class Traits> |
1329 typename ParserBase<Traits>::IdentifierT | 1351 typename ParserBase<Traits>::IdentifierT |
1330 ParserBase<Traits>::ParseAndClassifyIdentifier(ExpressionClassifier* classifier, | 1352 ParserBase<Traits>::ParseAndClassifyIdentifier(ExpressionClassifier* classifier, |
1331 bool* ok) { | 1353 bool* ok) { |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1461 ReportMessage(MessageTemplate::kMalformedRegExpFlags); | 1483 ReportMessage(MessageTemplate::kMalformedRegExpFlags); |
1462 *ok = false; | 1484 *ok = false; |
1463 return Traits::EmptyExpression(); | 1485 return Traits::EmptyExpression(); |
1464 } | 1486 } |
1465 int js_flags = flags.FromJust(); | 1487 int js_flags = flags.FromJust(); |
1466 Next(); | 1488 Next(); |
1467 return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos); | 1489 return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos); |
1468 } | 1490 } |
1469 | 1491 |
1470 | 1492 |
1471 #define CHECK_OK ok); \ | |
1472 if (!*ok) return this->EmptyExpression(); \ | |
1473 ((void)0 | |
1474 #define DUMMY ) // to make indentation work | |
1475 #undef DUMMY | |
1476 | |
1477 // Used in functions where the return type is not ExpressionT. | |
1478 #define CHECK_OK_CUSTOM(x) ok); \ | |
1479 if (!*ok) return this->x(); \ | |
1480 ((void)0 | |
1481 #define DUMMY ) // to make indentation work | |
1482 #undef DUMMY | |
1483 | |
1484 template <class Traits> | 1493 template <class Traits> |
1485 typename ParserBase<Traits>::ExpressionT | 1494 typename ParserBase<Traits>::ExpressionT |
1486 ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, | 1495 ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, |
1487 bool* is_async, bool* ok) { | 1496 bool* is_async, bool* ok) { |
1488 // PrimaryExpression :: | 1497 // PrimaryExpression :: |
1489 // 'this' | 1498 // 'this' |
1490 // 'null' | 1499 // 'null' |
1491 // 'true' | 1500 // 'true' |
1492 // 'false' | 1501 // 'false' |
1493 // Identifier | 1502 // Identifier |
(...skipping 1583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3077 ReportMessageAt(scanner()->location(), MessageTemplate::kUnexpectedSuper); | 3086 ReportMessageAt(scanner()->location(), MessageTemplate::kUnexpectedSuper); |
3078 *ok = false; | 3087 *ok = false; |
3079 return this->EmptyExpression(); | 3088 return this->EmptyExpression(); |
3080 } | 3089 } |
3081 | 3090 |
3082 template <class Traits> | 3091 template <class Traits> |
3083 void ParserBase<Traits>::ExpectMetaProperty(Vector<const char> property_name, | 3092 void ParserBase<Traits>::ExpectMetaProperty(Vector<const char> property_name, |
3084 const char* full_name, int pos, | 3093 const char* full_name, int pos, |
3085 bool* ok) { | 3094 bool* ok) { |
3086 Consume(Token::PERIOD); | 3095 Consume(Token::PERIOD); |
3087 ExpectContextualKeyword(property_name, ok); | 3096 ExpectContextualKeyword(property_name, CHECK_OK_CUSTOM(Void)); |
3088 if (!*ok) return; | |
3089 if (scanner()->literal_contains_escapes()) { | 3097 if (scanner()->literal_contains_escapes()) { |
3090 Traits::ReportMessageAt( | 3098 Traits::ReportMessageAt( |
3091 Scanner::Location(pos, scanner()->location().end_pos), | 3099 Scanner::Location(pos, scanner()->location().end_pos), |
3092 MessageTemplate::kInvalidEscapedMetaProperty, full_name); | 3100 MessageTemplate::kInvalidEscapedMetaProperty, full_name); |
3093 *ok = false; | 3101 *ok = false; |
3094 } | 3102 } |
3095 } | 3103 } |
3096 | 3104 |
3097 template <class Traits> | 3105 template <class Traits> |
3098 typename ParserBase<Traits>::ExpressionT | 3106 typename ParserBase<Traits>::ExpressionT |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3187 } | 3195 } |
3188 | 3196 |
3189 | 3197 |
3190 template <class Traits> | 3198 template <class Traits> |
3191 void ParserBase<Traits>::ParseFormalParameter( | 3199 void ParserBase<Traits>::ParseFormalParameter( |
3192 FormalParametersT* parameters, ExpressionClassifier* classifier, bool* ok) { | 3200 FormalParametersT* parameters, ExpressionClassifier* classifier, bool* ok) { |
3193 // FormalParameter[Yield,GeneratorParameter] : | 3201 // FormalParameter[Yield,GeneratorParameter] : |
3194 // BindingElement[?Yield, ?GeneratorParameter] | 3202 // BindingElement[?Yield, ?GeneratorParameter] |
3195 bool is_rest = parameters->has_rest; | 3203 bool is_rest = parameters->has_rest; |
3196 | 3204 |
3197 ExpressionT pattern = ParsePrimaryExpression(classifier, ok); | 3205 ExpressionT pattern = |
3198 if (!*ok) return; | 3206 ParsePrimaryExpression(classifier, CHECK_OK_CUSTOM(Void)); |
3199 | 3207 ValidateBindingPattern(classifier, CHECK_OK_CUSTOM(Void)); |
3200 ValidateBindingPattern(classifier, ok); | |
3201 if (!*ok) return; | |
3202 | 3208 |
3203 if (!Traits::IsIdentifier(pattern)) { | 3209 if (!Traits::IsIdentifier(pattern)) { |
3204 parameters->is_simple = false; | 3210 parameters->is_simple = false; |
3205 ValidateFormalParameterInitializer(classifier, ok); | 3211 ValidateFormalParameterInitializer(classifier, CHECK_OK_CUSTOM(Void)); |
3206 if (!*ok) return; | |
3207 classifier->RecordNonSimpleParameter(); | 3212 classifier->RecordNonSimpleParameter(); |
3208 } | 3213 } |
3209 | 3214 |
3210 ExpressionT initializer = Traits::EmptyExpression(); | 3215 ExpressionT initializer = Traits::EmptyExpression(); |
3211 if (!is_rest && Check(Token::ASSIGN)) { | 3216 if (!is_rest && Check(Token::ASSIGN)) { |
3212 ExpressionClassifier init_classifier(this); | 3217 ExpressionClassifier init_classifier(this); |
3213 initializer = ParseAssignmentExpression(true, &init_classifier, ok); | 3218 initializer = ParseAssignmentExpression(true, &init_classifier, |
3214 if (!*ok) return; | 3219 CHECK_OK_CUSTOM(Void)); |
3215 Traits::RewriteNonPattern(&init_classifier, ok); | 3220 Traits::RewriteNonPattern(&init_classifier, CHECK_OK_CUSTOM(Void)); |
3216 ValidateFormalParameterInitializer(&init_classifier, ok); | 3221 ValidateFormalParameterInitializer(&init_classifier, CHECK_OK_CUSTOM(Void)); |
3217 if (!*ok) return; | |
3218 parameters->is_simple = false; | 3222 parameters->is_simple = false; |
3219 init_classifier.Discard(); | 3223 init_classifier.Discard(); |
3220 classifier->RecordNonSimpleParameter(); | 3224 classifier->RecordNonSimpleParameter(); |
3221 | 3225 |
3222 Traits::SetFunctionNameFromIdentifierRef(initializer, pattern); | 3226 Traits::SetFunctionNameFromIdentifierRef(initializer, pattern); |
3223 } | 3227 } |
3224 | 3228 |
3225 Traits::AddFormalParameter(parameters, pattern, initializer, | 3229 Traits::AddFormalParameter(parameters, pattern, initializer, |
3226 scanner()->location().end_pos, is_rest); | 3230 scanner()->location().end_pos, is_rest); |
3227 } | 3231 } |
(...skipping 16 matching lines...) Expand all Loading... |
3244 DCHECK_EQ(0, parameters->Arity()); | 3248 DCHECK_EQ(0, parameters->Arity()); |
3245 | 3249 |
3246 if (peek() != Token::RPAREN) { | 3250 if (peek() != Token::RPAREN) { |
3247 while (true) { | 3251 while (true) { |
3248 if (parameters->Arity() > Code::kMaxArguments) { | 3252 if (parameters->Arity() > Code::kMaxArguments) { |
3249 ReportMessage(MessageTemplate::kTooManyParameters); | 3253 ReportMessage(MessageTemplate::kTooManyParameters); |
3250 *ok = false; | 3254 *ok = false; |
3251 return; | 3255 return; |
3252 } | 3256 } |
3253 parameters->has_rest = Check(Token::ELLIPSIS); | 3257 parameters->has_rest = Check(Token::ELLIPSIS); |
3254 ParseFormalParameter(parameters, classifier, ok); | 3258 ParseFormalParameter(parameters, classifier, CHECK_OK_CUSTOM(Void)); |
3255 if (!*ok) return; | |
3256 | 3259 |
3257 if (parameters->has_rest) { | 3260 if (parameters->has_rest) { |
3258 parameters->is_simple = false; | 3261 parameters->is_simple = false; |
3259 classifier->RecordNonSimpleParameter(); | 3262 classifier->RecordNonSimpleParameter(); |
3260 if (peek() == Token::COMMA) { | 3263 if (peek() == Token::COMMA) { |
3261 ReportMessageAt(scanner()->peek_location(), | 3264 ReportMessageAt(scanner()->peek_location(), |
3262 MessageTemplate::kParamAfterRest); | 3265 MessageTemplate::kParamAfterRest); |
3263 *ok = false; | 3266 *ok = false; |
3264 return; | 3267 return; |
3265 } | 3268 } |
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3665 has_seen_constructor_ = true; | 3668 has_seen_constructor_ = true; |
3666 return; | 3669 return; |
3667 } | 3670 } |
3668 } | 3671 } |
3669 | 3672 |
3670 | 3673 |
3671 } // namespace internal | 3674 } // namespace internal |
3672 } // namespace v8 | 3675 } // namespace v8 |
3673 | 3676 |
3674 #endif // V8_PARSING_PARSER_BASE_H | 3677 #endif // V8_PARSING_PARSER_BASE_H |
OLD | NEW |