Chromium Code Reviews| 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 |