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 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
207 typedef typename Types::Expression ExpressionT; | 207 typedef typename Types::Expression ExpressionT; |
208 typedef typename Types::Identifier IdentifierT; | 208 typedef typename Types::Identifier IdentifierT; |
209 typedef typename Types::FormalParameter FormalParameterT; | 209 typedef typename Types::FormalParameter FormalParameterT; |
210 typedef typename Types::FormalParameters FormalParametersT; | 210 typedef typename Types::FormalParameters FormalParametersT; |
211 typedef typename Types::FunctionLiteral FunctionLiteralT; | 211 typedef typename Types::FunctionLiteral FunctionLiteralT; |
212 typedef typename Types::Literal LiteralT; | 212 typedef typename Types::Literal LiteralT; |
213 typedef typename Types::ObjectLiteralProperty ObjectLiteralPropertyT; | 213 typedef typename Types::ObjectLiteralProperty ObjectLiteralPropertyT; |
214 typedef typename Types::StatementList StatementListT; | 214 typedef typename Types::StatementList StatementListT; |
215 typedef typename v8::internal::ExpressionClassifier<Types> | 215 typedef typename v8::internal::ExpressionClassifier<Types> |
216 ExpressionClassifier; | 216 ExpressionClassifier; |
217 typedef typename Types::Block BlockT; | |
217 | 218 |
218 // All implementation-specific methods must be called through this. | 219 // All implementation-specific methods must be called through this. |
219 Impl* impl() { return static_cast<Impl*>(this); } | 220 Impl* impl() { return static_cast<Impl*>(this); } |
220 const Impl* impl() const { return static_cast<const Impl*>(this); } | 221 const Impl* impl() const { return static_cast<const Impl*>(this); } |
221 | 222 |
222 ParserBase(Zone* zone, Scanner* scanner, uintptr_t stack_limit, | 223 ParserBase(Zone* zone, Scanner* scanner, uintptr_t stack_limit, |
223 v8::Extension* extension, AstValueFactory* ast_value_factory, | 224 v8::Extension* extension, AstValueFactory* ast_value_factory, |
224 ParserRecorder* log) | 225 ParserRecorder* log) |
225 : scope_state_(nullptr), | 226 : scope_state_(nullptr), |
226 function_state_(nullptr), | 227 function_state_(nullptr), |
(...skipping 700 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
927 impl()->ReportMessageAt(source_location, message, arg, error_type); | 928 impl()->ReportMessageAt(source_location, message, arg, error_type); |
928 } | 929 } |
929 | 930 |
930 void ReportMessageAt(Scanner::Location location, | 931 void ReportMessageAt(Scanner::Location location, |
931 MessageTemplate::Template message, | 932 MessageTemplate::Template message, |
932 ParseErrorType error_type) { | 933 ParseErrorType error_type) { |
933 impl()->ReportMessageAt(location, message, | 934 impl()->ReportMessageAt(location, message, |
934 static_cast<const char*>(nullptr), error_type); | 935 static_cast<const char*>(nullptr), error_type); |
935 } | 936 } |
936 | 937 |
938 void ReportMessageAt(Scanner::Location location, | |
939 MessageTemplate::Template message, const char* arg, | |
940 ParseErrorType error_type = kSyntaxError) { | |
941 impl()->ReportMessageAt(location, message, arg, error_type); | |
942 } | |
nickie
2016/09/01 10:53:08
I suppose that by rearranging the parameters and p
marja
2016/09/01 11:16:10
Removed this one, calling impl()->ReportMessage di
| |
943 | |
937 void GetUnexpectedTokenMessage( | 944 void GetUnexpectedTokenMessage( |
938 Token::Value token, MessageTemplate::Template* message, | 945 Token::Value token, MessageTemplate::Template* message, |
939 Scanner::Location* location, const char** arg, | 946 Scanner::Location* location, const char** arg, |
940 MessageTemplate::Template default_ = MessageTemplate::kUnexpectedToken); | 947 MessageTemplate::Template default_ = MessageTemplate::kUnexpectedToken); |
941 | 948 |
942 void ReportUnexpectedToken(Token::Value token); | 949 void ReportUnexpectedToken(Token::Value token); |
943 void ReportUnexpectedTokenAt( | 950 void ReportUnexpectedTokenAt( |
944 Scanner::Location location, Token::Value token, | 951 Scanner::Location location, Token::Value token, |
945 MessageTemplate::Template message = MessageTemplate::kUnexpectedToken); | 952 MessageTemplate::Template message = MessageTemplate::kUnexpectedToken); |
946 | 953 |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1159 ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, bool* ok); | 1166 ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, bool* ok); |
1160 ExpressionT ParseSuperExpression(bool is_new, bool* ok); | 1167 ExpressionT ParseSuperExpression(bool is_new, bool* ok); |
1161 ExpressionT ParseNewTargetExpression(bool* ok); | 1168 ExpressionT ParseNewTargetExpression(bool* ok); |
1162 | 1169 |
1163 void ParseFormalParameter(FormalParametersT* parameters, bool* ok); | 1170 void ParseFormalParameter(FormalParametersT* parameters, bool* ok); |
1164 void ParseFormalParameterList(FormalParametersT* parameters, bool* ok); | 1171 void ParseFormalParameterList(FormalParametersT* parameters, bool* ok); |
1165 void CheckArityRestrictions(int param_count, FunctionKind function_type, | 1172 void CheckArityRestrictions(int param_count, FunctionKind function_type, |
1166 bool has_rest, int formals_start_pos, | 1173 bool has_rest, int formals_start_pos, |
1167 int formals_end_pos, bool* ok); | 1174 int formals_end_pos, bool* ok); |
1168 | 1175 |
1176 BlockT ParseVariableDeclarations(VariableDeclarationContext var_context, | |
1177 DeclarationParsingResult* parsing_result, | |
1178 ZoneList<const AstRawString*>* names, | |
1179 bool* ok); | |
1180 | |
1169 bool IsNextLetKeyword(); | 1181 bool IsNextLetKeyword(); |
1170 bool IsTrivialExpression(); | 1182 bool IsTrivialExpression(); |
1171 | 1183 |
1172 // Checks if the expression is a valid reference expression (e.g., on the | 1184 // Checks if the expression is a valid reference expression (e.g., on the |
1173 // left-hand side of assignments). Although ruled out by ECMA as early errors, | 1185 // left-hand side of assignments). Although ruled out by ECMA as early errors, |
1174 // we allow calls for web compatibility and rewrite them to a runtime throw. | 1186 // we allow calls for web compatibility and rewrite them to a runtime throw. |
1175 ExpressionT CheckAndRewriteReferenceExpression( | 1187 ExpressionT CheckAndRewriteReferenceExpression( |
1176 ExpressionT expression, int beg_pos, int end_pos, | 1188 ExpressionT expression, int beg_pos, int end_pos, |
1177 MessageTemplate::Template message, bool* ok); | 1189 MessageTemplate::Template message, bool* ok); |
1178 ExpressionT CheckAndRewriteReferenceExpression( | 1190 ExpressionT CheckAndRewriteReferenceExpression( |
(...skipping 2213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3392 } | 3404 } |
3393 } | 3405 } |
3394 | 3406 |
3395 for (int i = 0; i < parameters->Arity(); ++i) { | 3407 for (int i = 0; i < parameters->Arity(); ++i) { |
3396 auto parameter = parameters->at(i); | 3408 auto parameter = parameters->at(i); |
3397 impl()->DeclareFormalParameter(parameters->scope, parameter); | 3409 impl()->DeclareFormalParameter(parameters->scope, parameter); |
3398 } | 3410 } |
3399 } | 3411 } |
3400 | 3412 |
3401 template <typename Impl> | 3413 template <typename Impl> |
3414 typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations( | |
3415 VariableDeclarationContext var_context, | |
3416 DeclarationParsingResult* parsing_result, | |
3417 ZoneList<const AstRawString*>* names, bool* ok) { | |
3418 // VariableDeclarations :: | |
3419 // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[','] | |
3420 // | |
3421 // ES6: | |
3422 // FIXME(marja, nikolaos): Add an up-to-date comment about ES6 variable | |
3423 // declaration syntax. | |
3424 | |
3425 DeclarationParsingResult temp_result; | |
3426 if (parsing_result == nullptr) { | |
3427 parsing_result = &temp_result; | |
3428 } | |
3429 parsing_result->descriptor.declaration_kind = DeclarationDescriptor::NORMAL; | |
3430 parsing_result->descriptor.declaration_pos = peek_position(); | |
3431 parsing_result->descriptor.initialization_pos = peek_position(); | |
3432 parsing_result->descriptor.mode = VAR; | |
nickie
2016/09/01 10:53:08
Is there a reason why this line is not after 3441,
marja
2016/09/01 11:16:10
Done.
| |
3433 | |
3434 BlockT init_block = impl()->NullBlock(); | |
3435 if (var_context != kForStatement) { | |
3436 init_block = impl()->NewBlock(nullptr, 1, true, | |
3437 parsing_result->descriptor.declaration_pos); | |
3438 } | |
3439 | |
3440 if (peek() == Token::VAR) { | |
nickie
2016/09/01 10:53:08
Again a matter of taste, but I'd rather use a "swi
marja
2016/09/01 11:16:10
Done. (Replaced w/ switch)
| |
3441 Consume(Token::VAR); | |
3442 } else if (peek() == Token::CONST) { | |
3443 Consume(Token::CONST); | |
3444 DCHECK(var_context != kStatement); | |
3445 parsing_result->descriptor.mode = CONST; | |
3446 } else if (peek() == Token::LET) { | |
3447 Consume(Token::LET); | |
3448 DCHECK(var_context != kStatement); | |
3449 parsing_result->descriptor.mode = LET; | |
3450 } else { | |
3451 UNREACHABLE(); // by current callers | |
3452 } | |
3453 | |
3454 parsing_result->descriptor.scope = scope(); | |
3455 parsing_result->descriptor.hoist_scope = nullptr; | |
3456 | |
3457 // The scope of a var/const declared variable anywhere inside a function | |
3458 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope | |
3459 // of a let declared variable is the scope of the immediately enclosing | |
3460 // block. | |
3461 bool first_declaration = true; | |
3462 int bindings_start = peek_position(); | |
3463 do { | |
3464 // Parse binding pattern. | |
3465 FuncNameInferrer::State fni_state(fni_); | |
3466 | |
3467 if (!first_declaration) Consume(Token::COMMA); | |
3468 first_declaration = false; | |
nickie
2016/09/01 10:53:08
I think you can get rid of these two lines and the
marja
2016/09/01 11:16:10
Done.
| |
3469 | |
3470 ExpressionT pattern = impl()->EmptyExpression(); | |
3471 int decl_pos = peek_position(); | |
3472 { | |
3473 ExpressionClassifier pattern_classifier(this); | |
3474 pattern = ParsePrimaryExpression(CHECK_OK_CUSTOM(NullBlock)); | |
3475 | |
3476 ValidateBindingPattern(CHECK_OK_CUSTOM(NullBlock)); | |
3477 if (IsLexicalVariableMode(parsing_result->descriptor.mode)) { | |
3478 ValidateLetPattern(CHECK_OK_CUSTOM(NullBlock)); | |
3479 } | |
3480 } | |
3481 | |
3482 Scanner::Location variable_loc = scanner()->location(); | |
3483 bool single_name = impl()->IsIdentifier(pattern); | |
3484 | |
3485 if (single_name && fni_ != nullptr) { | |
3486 impl()->PushVariableName(fni_, impl()->AsIdentifier(pattern)); | |
nickie
2016/09/01 10:53:08
I think that impl()->PushVariableName does not nee
marja
2016/09/01 11:16:10
Leaving this as is, to keep PushLiteralName (alrea
| |
3487 } | |
3488 | |
3489 ExpressionT value = impl()->EmptyExpression(); | |
3490 int initializer_position = kNoSourcePosition; | |
3491 if (Check(Token::ASSIGN)) { | |
3492 ExpressionClassifier classifier(this); | |
3493 value = ParseAssignmentExpression(var_context != kForStatement, | |
3494 CHECK_OK_CUSTOM(NullBlock)); | |
3495 impl()->RewriteNonPattern(CHECK_OK_CUSTOM(NullBlock)); | |
3496 variable_loc.end_pos = scanner()->location().end_pos; | |
3497 | |
3498 if (!parsing_result->first_initializer_loc.IsValid()) { | |
3499 parsing_result->first_initializer_loc = variable_loc; | |
3500 } | |
3501 | |
3502 // Don't infer if it is "a = function(){...}();"-like expression. | |
3503 if (single_name && fni_ != nullptr) { | |
3504 if (!value->IsCall() && !value->IsCallNew()) { | |
3505 fni_->Infer(); | |
3506 } else { | |
3507 fni_->RemoveLastFunction(); | |
3508 } | |
3509 } | |
3510 | |
3511 impl()->SetFunctionNameFromIdentifierRef(value, pattern); | |
3512 | |
3513 // End position of the initializer is after the assignment expression. | |
3514 initializer_position = scanner()->location().end_pos; | |
3515 } else { | |
3516 if (var_context != kForStatement || !PeekInOrOf()) { | |
3517 // ES6 'const' and binding patterns require initializers. | |
3518 if (parsing_result->descriptor.mode == CONST || | |
3519 !impl()->IsIdentifier(pattern)) { | |
3520 ReportMessageAt( | |
3521 Scanner::Location(decl_pos, scanner()->location().end_pos), | |
3522 MessageTemplate::kDeclarationMissingInitializer, | |
3523 !impl()->IsIdentifier(pattern) ? "destructuring" : "const"); | |
3524 *ok = false; | |
3525 return impl()->NullBlock(); | |
3526 } | |
3527 // 'let x' initializes 'x' to undefined. | |
3528 if (parsing_result->descriptor.mode == LET) { | |
3529 value = impl()->GetLiteralUndefined(position()); | |
3530 } | |
3531 } | |
3532 | |
3533 // End position of the initializer is after the variable. | |
3534 initializer_position = position(); | |
3535 } | |
3536 | |
3537 typename DeclarationParsingResult::Declaration decl( | |
3538 pattern, initializer_position, value); | |
3539 if (var_context == kForStatement) { | |
3540 // Save the declaration for further handling in ParseForStatement. | |
3541 parsing_result->declarations.Add(decl); | |
3542 } else { | |
3543 // Immediately declare the variable otherwise. This avoids O(N^2) | |
3544 // behavior (where N is the number of variables in a single | |
3545 // declaration) in the PatternRewriter having to do with removing | |
3546 // and adding VariableProxies to the Scope (see bug 4699). | |
3547 impl()->DeclareAndInitializeVariables(init_block, | |
3548 &parsing_result->descriptor, &decl, | |
3549 names, CHECK_OK_CUSTOM(NullBlock)); | |
3550 } | |
3551 } while (peek() == Token::COMMA); | |
3552 | |
3553 parsing_result->bindings_loc = | |
3554 Scanner::Location(bindings_start, scanner()->location().end_pos); | |
3555 | |
3556 DCHECK(*ok); | |
nickie
2016/09/01 10:53:08
This line strikes me as a bit odd. Is there any r
marja
2016/09/01 11:16:10
I think this was just paranoid coding, as we use C
| |
3557 return init_block; | |
3558 } | |
3559 | |
3560 template <typename Impl> | |
3402 void ParserBase<Impl>::CheckArityRestrictions(int param_count, | 3561 void ParserBase<Impl>::CheckArityRestrictions(int param_count, |
3403 FunctionKind function_kind, | 3562 FunctionKind function_kind, |
3404 bool has_rest, | 3563 bool has_rest, |
3405 int formals_start_pos, | 3564 int formals_start_pos, |
3406 int formals_end_pos, bool* ok) { | 3565 int formals_end_pos, bool* ok) { |
3407 if (IsGetterFunction(function_kind)) { | 3566 if (IsGetterFunction(function_kind)) { |
3408 if (param_count != 0) { | 3567 if (param_count != 0) { |
3409 impl()->ReportMessageAt( | 3568 impl()->ReportMessageAt( |
3410 Scanner::Location(formals_start_pos, formals_end_pos), | 3569 Scanner::Location(formals_start_pos, formals_end_pos), |
3411 MessageTemplate::kBadGetterArity); | 3570 MessageTemplate::kBadGetterArity); |
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3792 has_seen_constructor_ = true; | 3951 has_seen_constructor_ = true; |
3793 return; | 3952 return; |
3794 } | 3953 } |
3795 } | 3954 } |
3796 | 3955 |
3797 | 3956 |
3798 } // namespace internal | 3957 } // namespace internal |
3799 } // namespace v8 | 3958 } // namespace v8 |
3800 | 3959 |
3801 #endif // V8_PARSING_PARSER_BASE_H | 3960 #endif // V8_PARSING_PARSER_BASE_H |
OLD | NEW |