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/ast.h" | 8 #include "src/ast/ast.h" |
| 9 #include "src/ast/scopes.h" | 9 #include "src/ast/scopes.h" |
| 10 #include "src/bailout-reason.h" | 10 #include "src/bailout-reason.h" |
| (...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 667 DeclarationScope* result = | 667 DeclarationScope* result = |
| 668 new (zone()) DeclarationScope(zone(), scope(), FUNCTION_SCOPE, kind); | 668 new (zone()) DeclarationScope(zone(), scope(), FUNCTION_SCOPE, kind); |
| 669 // TODO(verwaest): Move into the DeclarationScope constructor. | 669 // TODO(verwaest): Move into the DeclarationScope constructor. |
| 670 if (!IsArrowFunction(kind)) { | 670 if (!IsArrowFunction(kind)) { |
| 671 result->DeclareThis(ast_value_factory()); | 671 result->DeclareThis(ast_value_factory()); |
| 672 result->DeclareDefaultFunctionVariables(ast_value_factory()); | 672 result->DeclareDefaultFunctionVariables(ast_value_factory()); |
| 673 } | 673 } |
| 674 return result; | 674 return result; |
| 675 } | 675 } |
| 676 | 676 |
| 677 V8_INLINE DeclarationScope* GetDeclarationScope() const { | |
| 678 return scope()->GetDeclarationScope(); | |
| 679 } | |
| 680 V8_INLINE DeclarationScope* GetClosureScope() const { | |
| 681 return scope()->GetClosureScope(); | |
| 682 } | |
| 683 | |
| 677 Scanner* scanner() const { return scanner_; } | 684 Scanner* scanner() const { return scanner_; } |
| 678 AstValueFactory* ast_value_factory() const { return ast_value_factory_; } | 685 AstValueFactory* ast_value_factory() const { return ast_value_factory_; } |
| 679 int position() const { return scanner_->location().beg_pos; } | 686 int position() const { return scanner_->location().beg_pos; } |
| 680 int peek_position() const { return scanner_->peek_location().beg_pos; } | 687 int peek_position() const { return scanner_->peek_location().beg_pos; } |
| 681 bool stack_overflow() const { return stack_overflow_; } | 688 bool stack_overflow() const { return stack_overflow_; } |
| 682 void set_stack_overflow() { stack_overflow_ = true; } | 689 void set_stack_overflow() { stack_overflow_ = true; } |
| 683 Mode mode() const { return mode_; } | 690 Mode mode() const { return mode_; } |
| 684 | 691 |
| 685 INLINE(Token::Value peek()) { | 692 INLINE(Token::Value peek()) { |
| 686 if (stack_overflow_) return Token::ILLEGAL; | 693 if (stack_overflow_) return Token::ILLEGAL; |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 874 LanguageMode old = scope()->language_mode(); | 881 LanguageMode old = scope()->language_mode(); |
| 875 impl()->SetLanguageMode(scope(), old > mode ? old : mode); | 882 impl()->SetLanguageMode(scope(), old > mode ? old : mode); |
| 876 } | 883 } |
| 877 bool is_generator() const { return function_state_->is_generator(); } | 884 bool is_generator() const { return function_state_->is_generator(); } |
| 878 bool is_async_function() const { | 885 bool is_async_function() const { |
| 879 return function_state_->is_async_function(); | 886 return function_state_->is_async_function(); |
| 880 } | 887 } |
| 881 bool is_resumable() const { return function_state_->is_resumable(); } | 888 bool is_resumable() const { return function_state_->is_resumable(); } |
| 882 | 889 |
| 883 // Report syntax errors. | 890 // Report syntax errors. |
| 884 void ReportMessage(MessageTemplate::Template message, const char* arg = NULL, | 891 void ReportMessage(MessageTemplate::Template message) { |
| 892 Scanner::Location source_location = scanner()->location(); | |
| 893 impl()->ReportMessageAt(source_location, message, | |
| 894 static_cast<const char*>(nullptr), kSyntaxError); | |
| 895 } | |
| 896 | |
| 897 template <typename T> | |
| 898 void ReportMessage(MessageTemplate::Template message, T arg, | |
| 885 ParseErrorType error_type = kSyntaxError) { | 899 ParseErrorType error_type = kSyntaxError) { |
| 886 Scanner::Location source_location = scanner()->location(); | 900 Scanner::Location source_location = scanner()->location(); |
| 887 impl()->ReportMessageAt(source_location, message, arg, error_type); | 901 impl()->ReportMessageAt(source_location, message, arg, error_type); |
| 888 } | |
| 889 | |
| 890 void ReportMessage(MessageTemplate::Template message, const AstRawString* arg, | |
| 891 ParseErrorType error_type = kSyntaxError) { | |
| 892 Scanner::Location source_location = scanner()->location(); | |
| 893 impl()->ReportMessageAt(source_location, message, arg, error_type); | |
| 894 } | 902 } |
| 895 | 903 |
| 896 void ReportMessageAt(Scanner::Location location, | 904 void ReportMessageAt(Scanner::Location location, |
| 897 MessageTemplate::Template message, | 905 MessageTemplate::Template message, |
| 898 ParseErrorType error_type) { | 906 ParseErrorType error_type) { |
| 899 impl()->ReportMessageAt(location, message, | 907 impl()->ReportMessageAt(location, message, |
| 900 static_cast<const char*>(nullptr), error_type); | 908 static_cast<const char*>(nullptr), error_type); |
| 901 } | 909 } |
| 902 | 910 |
| 903 void GetUnexpectedTokenMessage( | 911 void GetUnexpectedTokenMessage( |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1180 | 1188 |
| 1181 StatementT ParseVariableStatement(VariableDeclarationContext var_context, | 1189 StatementT ParseVariableStatement(VariableDeclarationContext var_context, |
| 1182 ZoneList<const AstRawString*>* names, | 1190 ZoneList<const AstRawString*>* names, |
| 1183 bool* ok); | 1191 bool* ok); |
| 1184 | 1192 |
| 1185 // Magical syntax support. | 1193 // Magical syntax support. |
| 1186 ExpressionT ParseV8Intrinsic(bool* ok); | 1194 ExpressionT ParseV8Intrinsic(bool* ok); |
| 1187 | 1195 |
| 1188 StatementT ParseDebuggerStatement(bool* ok); | 1196 StatementT ParseDebuggerStatement(bool* ok); |
| 1189 | 1197 |
| 1198 StatementT ParseExpressionOrLabelledStatement( | |
| 1199 ZoneList<const AstRawString*>* labels, | |
| 1200 AllowLabelledFunctionStatement allow_function, bool* ok); | |
| 1201 StatementT ParseIfStatement(ZoneList<const AstRawString*>* labels, bool* ok); | |
| 1202 StatementT ParseContinueStatement(bool* ok); | |
| 1203 StatementT ParseBreakStatement(ZoneList<const AstRawString*>* labels, | |
| 1204 bool* ok); | |
| 1205 StatementT ParseReturnStatement(bool* ok); | |
| 1206 StatementT ParseWithStatement(ZoneList<const AstRawString*>* labels, | |
| 1207 bool* ok); | |
| 1208 | |
| 1190 bool IsNextLetKeyword(); | 1209 bool IsNextLetKeyword(); |
| 1191 bool IsTrivialExpression(); | 1210 bool IsTrivialExpression(); |
| 1192 | 1211 |
| 1193 // Checks if the expression is a valid reference expression (e.g., on the | 1212 // Checks if the expression is a valid reference expression (e.g., on the |
| 1194 // left-hand side of assignments). Although ruled out by ECMA as early errors, | 1213 // left-hand side of assignments). Although ruled out by ECMA as early errors, |
| 1195 // we allow calls for web compatibility and rewrite them to a runtime throw. | 1214 // we allow calls for web compatibility and rewrite them to a runtime throw. |
| 1196 ExpressionT CheckAndRewriteReferenceExpression( | 1215 ExpressionT CheckAndRewriteReferenceExpression( |
| 1197 ExpressionT expression, int beg_pos, int end_pos, | 1216 ExpressionT expression, int beg_pos, int end_pos, |
| 1198 MessageTemplate::Template message, bool* ok); | 1217 MessageTemplate::Template message, bool* ok); |
| 1199 ExpressionT CheckAndRewriteReferenceExpression( | 1218 ExpressionT CheckAndRewriteReferenceExpression( |
| (...skipping 3111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4311 // break point is present. | 4330 // break point is present. |
| 4312 // DebuggerStatement :: | 4331 // DebuggerStatement :: |
| 4313 // 'debugger' ';' | 4332 // 'debugger' ';' |
| 4314 | 4333 |
| 4315 int pos = peek_position(); | 4334 int pos = peek_position(); |
| 4316 Expect(Token::DEBUGGER, CHECK_OK); | 4335 Expect(Token::DEBUGGER, CHECK_OK); |
| 4317 ExpectSemicolon(CHECK_OK); | 4336 ExpectSemicolon(CHECK_OK); |
| 4318 return factory()->NewDebuggerStatement(pos); | 4337 return factory()->NewDebuggerStatement(pos); |
| 4319 } | 4338 } |
| 4320 | 4339 |
| 4340 template <typename Impl> | |
| 4341 typename ParserBase<Impl>::StatementT | |
| 4342 ParserBase<Impl>::ParseExpressionOrLabelledStatement( | |
| 4343 ZoneList<const AstRawString*>* labels, | |
| 4344 AllowLabelledFunctionStatement allow_function, bool* ok) { | |
| 4345 // ExpressionStatement | LabelledStatement :: | |
| 4346 // Expression ';' | |
| 4347 // Identifier ':' Statement | |
| 4348 // | |
| 4349 // ExpressionStatement[Yield] : | |
| 4350 // [lookahead ∉ {{, function, class, let [}] Expression[In, ?Yield] ; | |
| 4351 | |
| 4352 int pos = peek_position(); | |
| 4353 | |
| 4354 switch (peek()) { | |
| 4355 case Token::FUNCTION: | |
| 4356 case Token::LBRACE: | |
| 4357 UNREACHABLE(); // Always handled by the callers. | |
| 4358 case Token::CLASS: | |
| 4359 ReportUnexpectedToken(Next()); | |
| 4360 *ok = false; | |
| 4361 return impl()->NullStatement(); | |
| 4362 default: | |
| 4363 break; | |
| 4364 } | |
| 4365 | |
| 4366 bool starts_with_identifier = peek_any_identifier(); | |
| 4367 ExpressionT expr = ParseExpression(true, CHECK_OK); | |
| 4368 if (peek() == Token::COLON && starts_with_identifier && | |
| 4369 impl()->IsIdentifier(expr)) { | |
| 4370 // The whole expression was a single identifier, and not, e.g., | |
| 4371 // something starting with an identifier or a parenthesized identifier. | |
| 4372 labels = impl()->DeclareLabel(labels, expr, CHECK_OK); | |
|
adamk
2016/09/08 18:33:19
Can you add an AsIdentifierExpression() method to
nickie
2016/09/09 09:42:26
Done.
| |
| 4373 Consume(Token::COLON); | |
| 4374 // ES#sec-labelled-function-declarations Labelled Function Declarations | |
| 4375 if (peek() == Token::FUNCTION && is_sloppy(language_mode())) { | |
| 4376 if (allow_function == kAllowLabelledFunctionStatement) { | |
| 4377 return impl()->ParseFunctionDeclaration(ok); | |
| 4378 } else { | |
| 4379 return ParseScopedStatement(labels, true, ok); | |
| 4380 } | |
| 4381 } | |
| 4382 return ParseStatement(labels, kDisallowLabelledFunctionStatement, ok); | |
| 4383 } | |
| 4384 | |
| 4385 // If we have an extension, we allow a native function declaration. | |
| 4386 // A native function declaration starts with "native function" with | |
| 4387 // no line-terminator between the two words. | |
| 4388 if (extension_ != nullptr && peek() == Token::FUNCTION && | |
| 4389 !scanner()->HasAnyLineTerminatorBeforeNext() && impl()->IsNative(expr)) { | |
| 4390 return impl()->ParseNativeDeclaration(ok); | |
| 4391 } | |
| 4392 | |
| 4393 // Parsed expression statement, followed by semicolon. | |
| 4394 ExpectSemicolon(CHECK_OK); | |
| 4395 return factory()->NewExpressionStatement(expr, pos); | |
| 4396 } | |
| 4397 | |
| 4398 template <typename Impl> | |
| 4399 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseIfStatement( | |
| 4400 ZoneList<const AstRawString*>* labels, bool* ok) { | |
| 4401 // IfStatement :: | |
| 4402 // 'if' '(' Expression ')' Statement ('else' Statement)? | |
| 4403 | |
| 4404 int pos = peek_position(); | |
| 4405 Expect(Token::IF, CHECK_OK); | |
| 4406 Expect(Token::LPAREN, CHECK_OK); | |
| 4407 ExpressionT condition = ParseExpression(true, CHECK_OK); | |
| 4408 Expect(Token::RPAREN, CHECK_OK); | |
| 4409 StatementT then_statement = ParseScopedStatement(labels, false, CHECK_OK); | |
| 4410 StatementT else_statement = impl()->NullStatement(); | |
| 4411 if (Check(Token::ELSE)) { | |
| 4412 else_statement = ParseScopedStatement(labels, false, CHECK_OK); | |
| 4413 } else { | |
| 4414 else_statement = factory()->NewEmptyStatement(kNoSourcePosition); | |
| 4415 } | |
| 4416 return factory()->NewIfStatement(condition, then_statement, else_statement, | |
| 4417 pos); | |
| 4418 } | |
| 4419 | |
| 4420 template <typename Impl> | |
| 4421 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseContinueStatement( | |
| 4422 bool* ok) { | |
| 4423 // ContinueStatement :: | |
| 4424 // 'continue' Identifier? ';' | |
| 4425 | |
| 4426 int pos = peek_position(); | |
| 4427 Expect(Token::CONTINUE, CHECK_OK); | |
| 4428 IdentifierT label = impl()->EmptyIdentifier(); | |
| 4429 Token::Value tok = peek(); | |
| 4430 if (!scanner()->HasAnyLineTerminatorBeforeNext() && tok != Token::SEMICOLON && | |
| 4431 tok != Token::RBRACE && tok != Token::EOS) { | |
| 4432 // ECMA allows "eval" or "arguments" as labels even in strict mode. | |
| 4433 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | |
| 4434 } | |
| 4435 typename Types::IterationStatementT target = | |
| 4436 impl()->LookupContinueTarget(label, CHECK_OK); | |
| 4437 if (impl()->IsNullStatement(target)) { | |
| 4438 // Illegal continue statement. | |
| 4439 MessageTemplate::Template message = MessageTemplate::kIllegalContinue; | |
| 4440 if (!impl()->IsEmptyIdentifier(label)) { | |
| 4441 message = MessageTemplate::kUnknownLabel; | |
| 4442 } | |
| 4443 ReportMessage(message, label); | |
| 4444 *ok = false; | |
| 4445 return impl()->NullStatement(); | |
| 4446 } | |
| 4447 ExpectSemicolon(CHECK_OK); | |
| 4448 return factory()->NewContinueStatement(target, pos); | |
| 4449 } | |
| 4450 | |
| 4451 template <typename Impl> | |
| 4452 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseBreakStatement( | |
| 4453 ZoneList<const AstRawString*>* labels, bool* ok) { | |
| 4454 // BreakStatement :: | |
| 4455 // 'break' Identifier? ';' | |
| 4456 | |
| 4457 int pos = peek_position(); | |
| 4458 Expect(Token::BREAK, CHECK_OK); | |
| 4459 IdentifierT label = impl()->EmptyIdentifier(); | |
| 4460 Token::Value tok = peek(); | |
| 4461 if (!scanner()->HasAnyLineTerminatorBeforeNext() && tok != Token::SEMICOLON && | |
| 4462 tok != Token::RBRACE && tok != Token::EOS) { | |
| 4463 // ECMA allows "eval" or "arguments" as labels even in strict mode. | |
| 4464 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | |
| 4465 } | |
| 4466 // Parse labeled break statements that target themselves into | |
| 4467 // empty statements, e.g. 'l1: l2: l3: break l2;' | |
| 4468 if (!impl()->IsEmptyIdentifier(label) && | |
| 4469 impl()->ContainsLabel(labels, label)) { | |
| 4470 ExpectSemicolon(CHECK_OK); | |
| 4471 return factory()->NewEmptyStatement(pos); | |
| 4472 } | |
| 4473 typename Types::BreakableStatementT target = | |
| 4474 impl()->LookupBreakTarget(label, CHECK_OK); | |
| 4475 if (impl()->IsNullStatement(target)) { | |
| 4476 // Illegal break statement. | |
| 4477 MessageTemplate::Template message = MessageTemplate::kIllegalBreak; | |
| 4478 if (!impl()->IsEmptyIdentifier(label)) { | |
| 4479 message = MessageTemplate::kUnknownLabel; | |
| 4480 } | |
| 4481 ReportMessage(message, label); | |
| 4482 *ok = false; | |
| 4483 return impl()->NullStatement(); | |
| 4484 } | |
| 4485 ExpectSemicolon(CHECK_OK); | |
| 4486 return factory()->NewBreakStatement(target, pos); | |
| 4487 } | |
| 4488 | |
| 4489 template <typename Impl> | |
| 4490 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseReturnStatement( | |
| 4491 bool* ok) { | |
| 4492 // ReturnStatement :: | |
| 4493 // 'return' [no line terminator] Expression? ';' | |
| 4494 | |
| 4495 // Consume the return token. It is necessary to do that before | |
| 4496 // reporting any errors on it, because of the way errors are | |
| 4497 // reported (underlining). | |
| 4498 Expect(Token::RETURN, CHECK_OK); | |
| 4499 Scanner::Location loc = scanner()->location(); | |
| 4500 | |
| 4501 Token::Value tok = peek(); | |
| 4502 ExpressionT return_value = impl()->EmptyExpression(); | |
| 4503 if (scanner()->HasAnyLineTerminatorBeforeNext() || tok == Token::SEMICOLON || | |
| 4504 tok == Token::RBRACE || tok == Token::EOS) { | |
| 4505 if (IsSubclassConstructor(function_state_->kind())) { | |
| 4506 return_value = impl()->ThisExpression(loc.beg_pos); | |
| 4507 } else { | |
| 4508 return_value = impl()->GetLiteralUndefined(position()); | |
| 4509 } | |
| 4510 } else { | |
| 4511 if (IsSubclassConstructor(function_state_->kind())) { | |
| 4512 // Because of the return code rewriting that happens in case of a subclass | |
| 4513 // constructor we don't want to accept tail calls, therefore we don't set | |
| 4514 // ReturnExprScope to kInsideValidReturnStatement here. | |
| 4515 return_value = ParseExpression(true, CHECK_OK); | |
| 4516 } else { | |
| 4517 ReturnExprScope maybe_allow_tail_calls( | |
| 4518 function_state_, ReturnExprContext::kInsideValidReturnStatement); | |
| 4519 return_value = ParseExpression(true, CHECK_OK); | |
| 4520 | |
| 4521 if (allow_tailcalls() && !is_sloppy(language_mode()) && !is_resumable()) { | |
| 4522 // ES6 14.6.1 Static Semantics: IsInTailPosition | |
| 4523 function_state_->AddImplicitTailCallExpression(return_value); | |
| 4524 } | |
| 4525 } | |
| 4526 } | |
| 4527 ExpectSemicolon(CHECK_OK); | |
| 4528 return_value = impl()->RewriteReturn(return_value, loc.beg_pos); | |
| 4529 | |
| 4530 DeclarationScope* decl_scope = GetDeclarationScope(); | |
| 4531 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) { | |
| 4532 impl()->ReportMessageAt(loc, MessageTemplate::kIllegalReturn); | |
| 4533 *ok = false; | |
| 4534 return impl()->NullStatement(); | |
| 4535 } | |
| 4536 return factory()->NewReturnStatement(return_value, loc.beg_pos); | |
| 4537 } | |
| 4538 | |
| 4539 template <typename Impl> | |
| 4540 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseWithStatement( | |
| 4541 ZoneList<const AstRawString*>* labels, bool* ok) { | |
| 4542 // WithStatement :: | |
| 4543 // 'with' '(' Expression ')' Statement | |
| 4544 | |
| 4545 Expect(Token::WITH, CHECK_OK); | |
| 4546 int pos = position(); | |
| 4547 | |
| 4548 if (is_strict(language_mode())) { | |
| 4549 ReportMessage(MessageTemplate::kStrictWith); | |
| 4550 *ok = false; | |
| 4551 return impl()->NullStatement(); | |
| 4552 } | |
| 4553 | |
| 4554 Expect(Token::LPAREN, CHECK_OK); | |
| 4555 ExpressionT expr = ParseExpression(true, CHECK_OK); | |
| 4556 Expect(Token::RPAREN, CHECK_OK); | |
| 4557 | |
| 4558 Scope* with_scope = NewScope(WITH_SCOPE); | |
| 4559 StatementT body = impl()->NullStatement(); | |
| 4560 { | |
| 4561 BlockState block_state(&scope_state_, with_scope); | |
| 4562 with_scope->set_start_position(scanner()->peek_location().beg_pos); | |
| 4563 body = ParseScopedStatement(labels, true, CHECK_OK); | |
| 4564 with_scope->set_end_position(scanner()->location().end_pos); | |
| 4565 } | |
| 4566 return factory()->NewWithStatement(with_scope, expr, body, pos); | |
| 4567 } | |
| 4568 | |
| 4321 #undef CHECK_OK | 4569 #undef CHECK_OK |
| 4322 #undef CHECK_OK_CUSTOM | 4570 #undef CHECK_OK_CUSTOM |
| 4323 | 4571 |
| 4324 template <typename Impl> | 4572 template <typename Impl> |
| 4325 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( | 4573 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( |
| 4326 Token::Value property) { | 4574 Token::Value property) { |
| 4327 if (property == Token::SMI || property == Token::NUMBER) return; | 4575 if (property == Token::SMI || property == Token::NUMBER) return; |
| 4328 | 4576 |
| 4329 if (IsProto()) { | 4577 if (IsProto()) { |
| 4330 if (has_seen_proto_) { | 4578 if (has_seen_proto_) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4369 has_seen_constructor_ = true; | 4617 has_seen_constructor_ = true; |
| 4370 return; | 4618 return; |
| 4371 } | 4619 } |
| 4372 } | 4620 } |
| 4373 | 4621 |
| 4374 | 4622 |
| 4375 } // namespace internal | 4623 } // namespace internal |
| 4376 } // namespace v8 | 4624 } // namespace v8 |
| 4377 | 4625 |
| 4378 #endif // V8_PARSING_PARSER_BASE_H | 4626 #endif // V8_PARSING_PARSER_BASE_H |
| OLD | NEW |