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 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1185 | 1193 |
1186 StatementT ParseVariableStatement(VariableDeclarationContext var_context, | 1194 StatementT ParseVariableStatement(VariableDeclarationContext var_context, |
1187 ZoneList<const AstRawString*>* names, | 1195 ZoneList<const AstRawString*>* names, |
1188 bool* ok); | 1196 bool* ok); |
1189 | 1197 |
1190 // Magical syntax support. | 1198 // Magical syntax support. |
1191 ExpressionT ParseV8Intrinsic(bool* ok); | 1199 ExpressionT ParseV8Intrinsic(bool* ok); |
1192 | 1200 |
1193 StatementT ParseDebuggerStatement(bool* ok); | 1201 StatementT ParseDebuggerStatement(bool* ok); |
1194 | 1202 |
| 1203 StatementT ParseExpressionOrLabelledStatement( |
| 1204 ZoneList<const AstRawString*>* labels, |
| 1205 AllowLabelledFunctionStatement allow_function, bool* ok); |
| 1206 StatementT ParseIfStatement(ZoneList<const AstRawString*>* labels, bool* ok); |
| 1207 StatementT ParseContinueStatement(bool* ok); |
| 1208 StatementT ParseBreakStatement(ZoneList<const AstRawString*>* labels, |
| 1209 bool* ok); |
| 1210 StatementT ParseReturnStatement(bool* ok); |
| 1211 StatementT ParseWithStatement(ZoneList<const AstRawString*>* labels, |
| 1212 bool* ok); |
| 1213 |
1195 bool IsNextLetKeyword(); | 1214 bool IsNextLetKeyword(); |
1196 bool IsTrivialExpression(); | 1215 bool IsTrivialExpression(); |
1197 | 1216 |
1198 // Checks if the expression is a valid reference expression (e.g., on the | 1217 // Checks if the expression is a valid reference expression (e.g., on the |
1199 // left-hand side of assignments). Although ruled out by ECMA as early errors, | 1218 // left-hand side of assignments). Although ruled out by ECMA as early errors, |
1200 // we allow calls for web compatibility and rewrite them to a runtime throw. | 1219 // we allow calls for web compatibility and rewrite them to a runtime throw. |
1201 ExpressionT CheckAndRewriteReferenceExpression( | 1220 ExpressionT CheckAndRewriteReferenceExpression( |
1202 ExpressionT expression, int beg_pos, int end_pos, | 1221 ExpressionT expression, int beg_pos, int end_pos, |
1203 MessageTemplate::Template message, bool* ok); | 1222 MessageTemplate::Template message, bool* ok); |
1204 ExpressionT CheckAndRewriteReferenceExpression( | 1223 ExpressionT CheckAndRewriteReferenceExpression( |
(...skipping 2853 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4058 while (peek() != end_token) { | 4077 while (peek() != end_token) { |
4059 if (directive_prologue && peek() != Token::STRING) { | 4078 if (directive_prologue && peek() != Token::STRING) { |
4060 directive_prologue = false; | 4079 directive_prologue = false; |
4061 } | 4080 } |
4062 | 4081 |
4063 bool starts_with_identifier = peek() == Token::IDENTIFIER; | 4082 bool starts_with_identifier = peek() == Token::IDENTIFIER; |
4064 Scanner::Location token_loc = scanner()->peek_location(); | 4083 Scanner::Location token_loc = scanner()->peek_location(); |
4065 StatementT stat = impl()->ParseStatementListItem( | 4084 StatementT stat = impl()->ParseStatementListItem( |
4066 CHECK_OK_CUSTOM(Return, kLazyParsingComplete)); | 4085 CHECK_OK_CUSTOM(Return, kLazyParsingComplete)); |
4067 | 4086 |
4068 if (impl()->IsNullOrEmptyStatement(stat)) { | 4087 if (impl()->IsNullStatement(stat) || impl()->IsEmptyStatement(stat)) { |
4069 directive_prologue = false; // End of directive prologue. | 4088 directive_prologue = false; // End of directive prologue. |
4070 continue; | 4089 continue; |
4071 } | 4090 } |
4072 | 4091 |
4073 if (directive_prologue) { | 4092 if (directive_prologue) { |
4074 // The length of the token is used to distinguish between strings literals | 4093 // The length of the token is used to distinguish between strings literals |
4075 // that evaluate equal to directives but contain either escape sequences | 4094 // that evaluate equal to directives but contain either escape sequences |
4076 // (e.g., "use \x73trict") or line continuations (e.g., "use \(newline) | 4095 // (e.g., "use \x73trict") or line continuations (e.g., "use \(newline) |
4077 // strict"). | 4096 // strict"). |
4078 if (impl()->IsUseStrictDirective(stat) && | 4097 if (impl()->IsUseStrictDirective(stat) && |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4207 // labels can be simply ignored in all other cases; except for | 4226 // labels can be simply ignored in all other cases; except for |
4208 // trivial labeled break statements 'label: break label' which is | 4227 // trivial labeled break statements 'label: break label' which is |
4209 // parsed into an empty statement. | 4228 // parsed into an empty statement. |
4210 switch (peek()) { | 4229 switch (peek()) { |
4211 case Token::LBRACE: | 4230 case Token::LBRACE: |
4212 return impl()->ParseBlock(labels, ok); | 4231 return impl()->ParseBlock(labels, ok); |
4213 case Token::SEMICOLON: | 4232 case Token::SEMICOLON: |
4214 Next(); | 4233 Next(); |
4215 return factory()->NewEmptyStatement(kNoSourcePosition); | 4234 return factory()->NewEmptyStatement(kNoSourcePosition); |
4216 case Token::IF: | 4235 case Token::IF: |
4217 return impl()->ParseIfStatement(labels, ok); | 4236 return ParseIfStatement(labels, ok); |
4218 case Token::DO: | 4237 case Token::DO: |
4219 return impl()->ParseDoWhileStatement(labels, ok); | 4238 return impl()->ParseDoWhileStatement(labels, ok); |
4220 case Token::WHILE: | 4239 case Token::WHILE: |
4221 return impl()->ParseWhileStatement(labels, ok); | 4240 return impl()->ParseWhileStatement(labels, ok); |
4222 case Token::FOR: | 4241 case Token::FOR: |
4223 return impl()->ParseForStatement(labels, ok); | 4242 return impl()->ParseForStatement(labels, ok); |
4224 case Token::CONTINUE: | 4243 case Token::CONTINUE: |
4225 case Token::BREAK: | 4244 case Token::BREAK: |
4226 case Token::RETURN: | 4245 case Token::RETURN: |
4227 case Token::THROW: | 4246 case Token::THROW: |
4228 case Token::TRY: { | 4247 case Token::TRY: { |
4229 // These statements must have their labels preserved in an enclosing | 4248 // These statements must have their labels preserved in an enclosing |
4230 // block, as the corresponding AST nodes do not currently store their | 4249 // block, as the corresponding AST nodes do not currently store their |
4231 // labels. | 4250 // labels. |
4232 // TODO(nikolaos, marja): Consider adding the labels to the AST nodes. | 4251 // TODO(nikolaos, marja): Consider adding the labels to the AST nodes. |
4233 if (labels == nullptr) { | 4252 if (labels == nullptr) { |
4234 return ParseStatementAsUnlabelled(labels, ok); | 4253 return ParseStatementAsUnlabelled(labels, ok); |
4235 } else { | 4254 } else { |
4236 BlockT result = | 4255 BlockT result = |
4237 factory()->NewBlock(labels, 1, false, kNoSourcePosition); | 4256 factory()->NewBlock(labels, 1, false, kNoSourcePosition); |
4238 typename Types::Target target(this, result); | 4257 typename Types::Target target(this, result); |
4239 StatementT statement = ParseStatementAsUnlabelled(labels, CHECK_OK); | 4258 StatementT statement = ParseStatementAsUnlabelled(labels, CHECK_OK); |
4240 result->statements()->Add(statement, zone()); | 4259 result->statements()->Add(statement, zone()); |
4241 return result; | 4260 return result; |
4242 } | 4261 } |
4243 } | 4262 } |
4244 case Token::WITH: | 4263 case Token::WITH: |
4245 return impl()->ParseWithStatement(labels, ok); | 4264 return ParseWithStatement(labels, ok); |
4246 case Token::SWITCH: | 4265 case Token::SWITCH: |
4247 return impl()->ParseSwitchStatement(labels, ok); | 4266 return impl()->ParseSwitchStatement(labels, ok); |
4248 case Token::FUNCTION: | 4267 case Token::FUNCTION: |
4249 // FunctionDeclaration only allowed as a StatementListItem, not in | 4268 // FunctionDeclaration only allowed as a StatementListItem, not in |
4250 // an arbitrary Statement position. Exceptions such as | 4269 // an arbitrary Statement position. Exceptions such as |
4251 // ES#sec-functiondeclarations-in-ifstatement-statement-clauses | 4270 // ES#sec-functiondeclarations-in-ifstatement-statement-clauses |
4252 // are handled by calling ParseScopedStatement rather than | 4271 // are handled by calling ParseScopedStatement rather than |
4253 // ParseStatement directly. | 4272 // ParseStatement directly. |
4254 impl()->ReportMessageAt(scanner()->peek_location(), | 4273 impl()->ReportMessageAt(scanner()->peek_location(), |
4255 is_strict(language_mode()) | 4274 is_strict(language_mode()) |
4256 ? MessageTemplate::kStrictFunction | 4275 ? MessageTemplate::kStrictFunction |
4257 : MessageTemplate::kSloppyFunction); | 4276 : MessageTemplate::kSloppyFunction); |
4258 *ok = false; | 4277 *ok = false; |
4259 return impl()->NullStatement(); | 4278 return impl()->NullStatement(); |
4260 case Token::DEBUGGER: | 4279 case Token::DEBUGGER: |
4261 return ParseDebuggerStatement(ok); | 4280 return ParseDebuggerStatement(ok); |
4262 case Token::VAR: | 4281 case Token::VAR: |
4263 return ParseVariableStatement(kStatement, nullptr, ok); | 4282 return ParseVariableStatement(kStatement, nullptr, ok); |
4264 default: | 4283 default: |
4265 return impl()->ParseExpressionOrLabelledStatement(labels, allow_function, | 4284 return ParseExpressionOrLabelledStatement(labels, allow_function, ok); |
4266 ok); | |
4267 } | 4285 } |
4268 } | 4286 } |
4269 | 4287 |
4270 // This method parses a subset of statements (break, continue, return, throw, | 4288 // This method parses a subset of statements (break, continue, return, throw, |
4271 // try) which are to be grouped because they all require their labeles to be | 4289 // try) which are to be grouped because they all require their labeles to be |
4272 // preserved in an enclosing block. | 4290 // preserved in an enclosing block. |
4273 template <typename Impl> | 4291 template <typename Impl> |
4274 typename ParserBase<Impl>::StatementT | 4292 typename ParserBase<Impl>::StatementT |
4275 ParserBase<Impl>::ParseStatementAsUnlabelled( | 4293 ParserBase<Impl>::ParseStatementAsUnlabelled( |
4276 ZoneList<const AstRawString*>* labels, bool* ok) { | 4294 ZoneList<const AstRawString*>* labels, bool* ok) { |
4277 switch (peek()) { | 4295 switch (peek()) { |
4278 case Token::CONTINUE: | 4296 case Token::CONTINUE: |
4279 return impl()->ParseContinueStatement(ok); | 4297 return ParseContinueStatement(ok); |
4280 case Token::BREAK: | 4298 case Token::BREAK: |
4281 return impl()->ParseBreakStatement(labels, ok); | 4299 return ParseBreakStatement(labels, ok); |
4282 case Token::RETURN: | 4300 case Token::RETURN: |
4283 return impl()->ParseReturnStatement(ok); | 4301 return ParseReturnStatement(ok); |
4284 case Token::THROW: | 4302 case Token::THROW: |
4285 return impl()->ParseThrowStatement(ok); | 4303 return impl()->ParseThrowStatement(ok); |
4286 case Token::TRY: | 4304 case Token::TRY: |
4287 return impl()->ParseTryStatement(ok); | 4305 return impl()->ParseTryStatement(ok); |
4288 default: | 4306 default: |
4289 UNREACHABLE(); | 4307 UNREACHABLE(); |
4290 return impl()->NullStatement(); | 4308 return impl()->NullStatement(); |
4291 } | 4309 } |
4292 } | 4310 } |
4293 | 4311 |
4294 template <typename Impl> | 4312 template <typename Impl> |
4295 typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseBlock( | 4313 typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseBlock( |
4296 ZoneList<const AstRawString*>* labels, bool* ok) { | 4314 ZoneList<const AstRawString*>* labels, bool* ok) { |
4297 // Block :: | 4315 // Block :: |
4298 // '{' StatementList '}' | 4316 // '{' StatementList '}' |
4299 | 4317 |
4300 // Construct block expecting 16 statements. | 4318 // Construct block expecting 16 statements. |
4301 BlockT body = factory()->NewBlock(labels, 16, false, kNoSourcePosition); | 4319 BlockT body = factory()->NewBlock(labels, 16, false, kNoSourcePosition); |
4302 | 4320 |
4303 // Parse the statements and collect escaping labels. | 4321 // Parse the statements and collect escaping labels. |
4304 Expect(Token::LBRACE, CHECK_OK_CUSTOM(NullBlock)); | 4322 Expect(Token::LBRACE, CHECK_OK_CUSTOM(NullBlock)); |
4305 { | 4323 { |
4306 BlockState block_state(&scope_state_); | 4324 BlockState block_state(&scope_state_); |
4307 block_state.set_start_position(scanner()->location().beg_pos); | 4325 block_state.set_start_position(scanner()->location().beg_pos); |
4308 typename Types::Target target(this, body); | 4326 typename Types::Target target(this, body); |
4309 | 4327 |
4310 while (peek() != Token::RBRACE) { | 4328 while (peek() != Token::RBRACE) { |
4311 StatementT stat = ParseStatementListItem(CHECK_OK_CUSTOM(NullBlock)); | 4329 StatementT stat = ParseStatementListItem(CHECK_OK_CUSTOM(NullBlock)); |
4312 if (!impl()->IsNullOrEmptyStatement(stat)) { | 4330 if (!impl()->IsNullStatement(stat) && !impl()->IsEmptyStatement(stat)) { |
4313 body->statements()->Add(stat, zone()); | 4331 body->statements()->Add(stat, zone()); |
4314 } | 4332 } |
4315 } | 4333 } |
4316 | 4334 |
4317 Expect(Token::RBRACE, CHECK_OK_CUSTOM(NullBlock)); | 4335 Expect(Token::RBRACE, CHECK_OK_CUSTOM(NullBlock)); |
4318 block_state.set_end_position(scanner()->location().end_pos); | 4336 block_state.set_end_position(scanner()->location().end_pos); |
4319 body->set_scope(block_state.FinalizedBlockScope()); | 4337 body->set_scope(block_state.FinalizedBlockScope()); |
4320 } | 4338 } |
4321 return body; | 4339 return body; |
4322 } | 4340 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4378 // break point is present. | 4396 // break point is present. |
4379 // DebuggerStatement :: | 4397 // DebuggerStatement :: |
4380 // 'debugger' ';' | 4398 // 'debugger' ';' |
4381 | 4399 |
4382 int pos = peek_position(); | 4400 int pos = peek_position(); |
4383 Expect(Token::DEBUGGER, CHECK_OK); | 4401 Expect(Token::DEBUGGER, CHECK_OK); |
4384 ExpectSemicolon(CHECK_OK); | 4402 ExpectSemicolon(CHECK_OK); |
4385 return factory()->NewDebuggerStatement(pos); | 4403 return factory()->NewDebuggerStatement(pos); |
4386 } | 4404 } |
4387 | 4405 |
| 4406 template <typename Impl> |
| 4407 typename ParserBase<Impl>::StatementT |
| 4408 ParserBase<Impl>::ParseExpressionOrLabelledStatement( |
| 4409 ZoneList<const AstRawString*>* labels, |
| 4410 AllowLabelledFunctionStatement allow_function, bool* ok) { |
| 4411 // ExpressionStatement | LabelledStatement :: |
| 4412 // Expression ';' |
| 4413 // Identifier ':' Statement |
| 4414 // |
| 4415 // ExpressionStatement[Yield] : |
| 4416 // [lookahead ∉ {{, function, class, let [}] Expression[In, ?Yield] ; |
| 4417 |
| 4418 int pos = peek_position(); |
| 4419 |
| 4420 switch (peek()) { |
| 4421 case Token::FUNCTION: |
| 4422 case Token::LBRACE: |
| 4423 UNREACHABLE(); // Always handled by the callers. |
| 4424 case Token::CLASS: |
| 4425 ReportUnexpectedToken(Next()); |
| 4426 *ok = false; |
| 4427 return impl()->NullStatement(); |
| 4428 default: |
| 4429 break; |
| 4430 } |
| 4431 |
| 4432 bool starts_with_identifier = peek_any_identifier(); |
| 4433 ExpressionT expr = ParseExpression(true, CHECK_OK); |
| 4434 if (peek() == Token::COLON && starts_with_identifier && |
| 4435 impl()->IsIdentifier(expr)) { |
| 4436 // The whole expression was a single identifier, and not, e.g., |
| 4437 // something starting with an identifier or a parenthesized identifier. |
| 4438 labels = impl()->DeclareLabel(labels, impl()->AsIdentifierExpression(expr), |
| 4439 CHECK_OK); |
| 4440 Consume(Token::COLON); |
| 4441 // ES#sec-labelled-function-declarations Labelled Function Declarations |
| 4442 if (peek() == Token::FUNCTION && is_sloppy(language_mode())) { |
| 4443 if (allow_function == kAllowLabelledFunctionStatement) { |
| 4444 return impl()->ParseFunctionDeclaration(ok); |
| 4445 } else { |
| 4446 return ParseScopedStatement(labels, true, ok); |
| 4447 } |
| 4448 } |
| 4449 return ParseStatement(labels, kDisallowLabelledFunctionStatement, ok); |
| 4450 } |
| 4451 |
| 4452 // If we have an extension, we allow a native function declaration. |
| 4453 // A native function declaration starts with "native function" with |
| 4454 // no line-terminator between the two words. |
| 4455 if (extension_ != nullptr && peek() == Token::FUNCTION && |
| 4456 !scanner()->HasAnyLineTerminatorBeforeNext() && impl()->IsNative(expr) && |
| 4457 !scanner()->literal_contains_escapes()) { |
| 4458 return impl()->ParseNativeDeclaration(ok); |
| 4459 } |
| 4460 |
| 4461 // Parsed expression statement, followed by semicolon. |
| 4462 ExpectSemicolon(CHECK_OK); |
| 4463 return factory()->NewExpressionStatement(expr, pos); |
| 4464 } |
| 4465 |
| 4466 template <typename Impl> |
| 4467 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseIfStatement( |
| 4468 ZoneList<const AstRawString*>* labels, bool* ok) { |
| 4469 // IfStatement :: |
| 4470 // 'if' '(' Expression ')' Statement ('else' Statement)? |
| 4471 |
| 4472 int pos = peek_position(); |
| 4473 Expect(Token::IF, CHECK_OK); |
| 4474 Expect(Token::LPAREN, CHECK_OK); |
| 4475 ExpressionT condition = ParseExpression(true, CHECK_OK); |
| 4476 Expect(Token::RPAREN, CHECK_OK); |
| 4477 StatementT then_statement = ParseScopedStatement(labels, false, CHECK_OK); |
| 4478 StatementT else_statement = impl()->NullStatement(); |
| 4479 if (Check(Token::ELSE)) { |
| 4480 else_statement = ParseScopedStatement(labels, false, CHECK_OK); |
| 4481 } else { |
| 4482 else_statement = factory()->NewEmptyStatement(kNoSourcePosition); |
| 4483 } |
| 4484 return factory()->NewIfStatement(condition, then_statement, else_statement, |
| 4485 pos); |
| 4486 } |
| 4487 |
| 4488 template <typename Impl> |
| 4489 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseContinueStatement( |
| 4490 bool* ok) { |
| 4491 // ContinueStatement :: |
| 4492 // 'continue' Identifier? ';' |
| 4493 |
| 4494 int pos = peek_position(); |
| 4495 Expect(Token::CONTINUE, CHECK_OK); |
| 4496 IdentifierT label = impl()->EmptyIdentifier(); |
| 4497 Token::Value tok = peek(); |
| 4498 if (!scanner()->HasAnyLineTerminatorBeforeNext() && tok != Token::SEMICOLON && |
| 4499 tok != Token::RBRACE && tok != Token::EOS) { |
| 4500 // ECMA allows "eval" or "arguments" as labels even in strict mode. |
| 4501 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
| 4502 } |
| 4503 typename Types::IterationStatementT target = |
| 4504 impl()->LookupContinueTarget(label, CHECK_OK); |
| 4505 if (impl()->IsNullStatement(target)) { |
| 4506 // Illegal continue statement. |
| 4507 MessageTemplate::Template message = MessageTemplate::kIllegalContinue; |
| 4508 if (!impl()->IsEmptyIdentifier(label)) { |
| 4509 message = MessageTemplate::kUnknownLabel; |
| 4510 } |
| 4511 ReportMessage(message, label); |
| 4512 *ok = false; |
| 4513 return impl()->NullStatement(); |
| 4514 } |
| 4515 ExpectSemicolon(CHECK_OK); |
| 4516 return factory()->NewContinueStatement(target, pos); |
| 4517 } |
| 4518 |
| 4519 template <typename Impl> |
| 4520 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseBreakStatement( |
| 4521 ZoneList<const AstRawString*>* labels, bool* ok) { |
| 4522 // BreakStatement :: |
| 4523 // 'break' Identifier? ';' |
| 4524 |
| 4525 int pos = peek_position(); |
| 4526 Expect(Token::BREAK, CHECK_OK); |
| 4527 IdentifierT label = impl()->EmptyIdentifier(); |
| 4528 Token::Value tok = peek(); |
| 4529 if (!scanner()->HasAnyLineTerminatorBeforeNext() && tok != Token::SEMICOLON && |
| 4530 tok != Token::RBRACE && tok != Token::EOS) { |
| 4531 // ECMA allows "eval" or "arguments" as labels even in strict mode. |
| 4532 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
| 4533 } |
| 4534 // Parse labeled break statements that target themselves into |
| 4535 // empty statements, e.g. 'l1: l2: l3: break l2;' |
| 4536 if (!impl()->IsEmptyIdentifier(label) && |
| 4537 impl()->ContainsLabel(labels, label)) { |
| 4538 ExpectSemicolon(CHECK_OK); |
| 4539 return factory()->NewEmptyStatement(pos); |
| 4540 } |
| 4541 typename Types::BreakableStatementT target = |
| 4542 impl()->LookupBreakTarget(label, CHECK_OK); |
| 4543 if (impl()->IsNullStatement(target)) { |
| 4544 // Illegal break statement. |
| 4545 MessageTemplate::Template message = MessageTemplate::kIllegalBreak; |
| 4546 if (!impl()->IsEmptyIdentifier(label)) { |
| 4547 message = MessageTemplate::kUnknownLabel; |
| 4548 } |
| 4549 ReportMessage(message, label); |
| 4550 *ok = false; |
| 4551 return impl()->NullStatement(); |
| 4552 } |
| 4553 ExpectSemicolon(CHECK_OK); |
| 4554 return factory()->NewBreakStatement(target, pos); |
| 4555 } |
| 4556 |
| 4557 template <typename Impl> |
| 4558 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseReturnStatement( |
| 4559 bool* ok) { |
| 4560 // ReturnStatement :: |
| 4561 // 'return' [no line terminator] Expression? ';' |
| 4562 |
| 4563 // Consume the return token. It is necessary to do that before |
| 4564 // reporting any errors on it, because of the way errors are |
| 4565 // reported (underlining). |
| 4566 Expect(Token::RETURN, CHECK_OK); |
| 4567 Scanner::Location loc = scanner()->location(); |
| 4568 |
| 4569 Token::Value tok = peek(); |
| 4570 ExpressionT return_value = impl()->EmptyExpression(); |
| 4571 if (scanner()->HasAnyLineTerminatorBeforeNext() || tok == Token::SEMICOLON || |
| 4572 tok == Token::RBRACE || tok == Token::EOS) { |
| 4573 if (IsSubclassConstructor(function_state_->kind())) { |
| 4574 return_value = impl()->ThisExpression(loc.beg_pos); |
| 4575 } else { |
| 4576 return_value = impl()->GetLiteralUndefined(position()); |
| 4577 } |
| 4578 } else { |
| 4579 if (IsSubclassConstructor(function_state_->kind())) { |
| 4580 // Because of the return code rewriting that happens in case of a subclass |
| 4581 // constructor we don't want to accept tail calls, therefore we don't set |
| 4582 // ReturnExprScope to kInsideValidReturnStatement here. |
| 4583 return_value = ParseExpression(true, CHECK_OK); |
| 4584 } else { |
| 4585 ReturnExprScope maybe_allow_tail_calls( |
| 4586 function_state_, ReturnExprContext::kInsideValidReturnStatement); |
| 4587 return_value = ParseExpression(true, CHECK_OK); |
| 4588 |
| 4589 if (allow_tailcalls() && !is_sloppy(language_mode()) && !is_resumable()) { |
| 4590 // ES6 14.6.1 Static Semantics: IsInTailPosition |
| 4591 function_state_->AddImplicitTailCallExpression(return_value); |
| 4592 } |
| 4593 } |
| 4594 } |
| 4595 ExpectSemicolon(CHECK_OK); |
| 4596 return_value = impl()->RewriteReturn(return_value, loc.beg_pos); |
| 4597 |
| 4598 DeclarationScope* decl_scope = GetDeclarationScope(); |
| 4599 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) { |
| 4600 impl()->ReportMessageAt(loc, MessageTemplate::kIllegalReturn); |
| 4601 *ok = false; |
| 4602 return impl()->NullStatement(); |
| 4603 } |
| 4604 return factory()->NewReturnStatement(return_value, loc.beg_pos); |
| 4605 } |
| 4606 |
| 4607 template <typename Impl> |
| 4608 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseWithStatement( |
| 4609 ZoneList<const AstRawString*>* labels, bool* ok) { |
| 4610 // WithStatement :: |
| 4611 // 'with' '(' Expression ')' Statement |
| 4612 |
| 4613 Expect(Token::WITH, CHECK_OK); |
| 4614 int pos = position(); |
| 4615 |
| 4616 if (is_strict(language_mode())) { |
| 4617 ReportMessage(MessageTemplate::kStrictWith); |
| 4618 *ok = false; |
| 4619 return impl()->NullStatement(); |
| 4620 } |
| 4621 |
| 4622 Expect(Token::LPAREN, CHECK_OK); |
| 4623 ExpressionT expr = ParseExpression(true, CHECK_OK); |
| 4624 Expect(Token::RPAREN, CHECK_OK); |
| 4625 |
| 4626 Scope* with_scope = NewScope(WITH_SCOPE); |
| 4627 StatementT body = impl()->NullStatement(); |
| 4628 { |
| 4629 BlockState block_state(&scope_state_, with_scope); |
| 4630 with_scope->set_start_position(scanner()->peek_location().beg_pos); |
| 4631 body = ParseScopedStatement(labels, true, CHECK_OK); |
| 4632 with_scope->set_end_position(scanner()->location().end_pos); |
| 4633 } |
| 4634 return factory()->NewWithStatement(with_scope, expr, body, pos); |
| 4635 } |
| 4636 |
4388 #undef CHECK_OK | 4637 #undef CHECK_OK |
4389 #undef CHECK_OK_CUSTOM | 4638 #undef CHECK_OK_CUSTOM |
4390 | 4639 |
4391 template <typename Impl> | 4640 template <typename Impl> |
4392 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( | 4641 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( |
4393 Token::Value property) { | 4642 Token::Value property) { |
4394 if (property == Token::SMI || property == Token::NUMBER) return; | 4643 if (property == Token::SMI || property == Token::NUMBER) return; |
4395 | 4644 |
4396 if (IsProto()) { | 4645 if (IsProto()) { |
4397 if (has_seen_proto_) { | 4646 if (has_seen_proto_) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4436 has_seen_constructor_ = true; | 4685 has_seen_constructor_ = true; |
4437 return; | 4686 return; |
4438 } | 4687 } |
4439 } | 4688 } |
4440 | 4689 |
4441 | 4690 |
4442 } // namespace internal | 4691 } // namespace internal |
4443 } // namespace v8 | 4692 } // namespace v8 |
4444 | 4693 |
4445 #endif // V8_PARSING_PARSER_BASE_H | 4694 #endif // V8_PARSING_PARSER_BASE_H |
OLD | NEW |