Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(347)

Side by Side Diff: src/parsing/parser-base.h

Issue 2318263002: [parser] Refactor of Parse*Statement*, part 3 (Closed)
Patch Set: Change after reviewers' comments Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/parsing/parser.cc ('k') | src/parsing/preparser.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 794 matching lines...) Expand 10 before | Expand all | Expand 10 after
805 MessageTemplate::Template message, bool* ok) { 805 MessageTemplate::Template message, bool* ok) {
806 Scanner::Location octal = scanner()->octal_position(); 806 Scanner::Location octal = scanner()->octal_position();
807 if (octal.IsValid() && beg_pos <= octal.beg_pos && 807 if (octal.IsValid() && beg_pos <= octal.beg_pos &&
808 octal.end_pos <= end_pos) { 808 octal.end_pos <= end_pos) {
809 impl()->ReportMessageAt(octal, message); 809 impl()->ReportMessageAt(octal, message);
810 scanner()->clear_octal_position(); 810 scanner()->clear_octal_position();
811 *ok = false; 811 *ok = false;
812 } 812 }
813 } 813 }
814 // for now, this check just collects statistics. 814 // for now, this check just collects statistics.
815 void CheckDecimalLiteralWithLeadingZero(int* use_counts, int beg_pos, 815 void CheckDecimalLiteralWithLeadingZero(int beg_pos, int end_pos) {
816 int end_pos) {
817 Scanner::Location token_location = 816 Scanner::Location token_location =
818 scanner()->decimal_with_leading_zero_position(); 817 scanner()->decimal_with_leading_zero_position();
819 if (token_location.IsValid() && beg_pos <= token_location.beg_pos && 818 if (token_location.IsValid() && beg_pos <= token_location.beg_pos &&
820 token_location.end_pos <= end_pos) { 819 token_location.end_pos <= end_pos) {
821 scanner()->clear_decimal_with_leading_zero_position(); 820 scanner()->clear_decimal_with_leading_zero_position();
822 if (use_counts != nullptr) 821 impl()->CountUsage(v8::Isolate::kDecimalWithLeadingZeroInStrictMode);
823 ++use_counts[v8::Isolate::kDecimalWithLeadingZeroInStrictMode];
824 } 822 }
825 } 823 }
826 824
827 inline void CheckStrictOctalLiteral(int beg_pos, int end_pos, bool* ok) { 825 inline void CheckStrictOctalLiteral(int beg_pos, int end_pos, bool* ok) {
828 CheckOctalLiteral(beg_pos, end_pos, MessageTemplate::kStrictOctalLiteral, 826 CheckOctalLiteral(beg_pos, end_pos, MessageTemplate::kStrictOctalLiteral,
829 ok); 827 ok);
830 } 828 }
831 829
832 inline void CheckTemplateOctalLiteral(int beg_pos, int end_pos, bool* ok) { 830 inline void CheckTemplateOctalLiteral(int beg_pos, int end_pos, bool* ok) {
833 CheckOctalLiteral(beg_pos, end_pos, MessageTemplate::kTemplateOctalLiteral, 831 CheckOctalLiteral(beg_pos, end_pos, MessageTemplate::kTemplateOctalLiteral,
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
1164 LazyParsingResult ParseStatementList(StatementListT body, int end_token, 1162 LazyParsingResult ParseStatementList(StatementListT body, int end_token,
1165 bool may_abort, bool* ok); 1163 bool may_abort, bool* ok);
1166 StatementT ParseStatementListItem(bool* ok); 1164 StatementT ParseStatementListItem(bool* ok);
1167 StatementT ParseStatement(ZoneList<const AstRawString*>* labels, 1165 StatementT ParseStatement(ZoneList<const AstRawString*>* labels,
1168 AllowLabelledFunctionStatement allow_function, 1166 AllowLabelledFunctionStatement allow_function,
1169 bool* ok); 1167 bool* ok);
1170 StatementT ParseStatementAsUnlabelled(ZoneList<const AstRawString*>* labels, 1168 StatementT ParseStatementAsUnlabelled(ZoneList<const AstRawString*>* labels,
1171 bool* ok); 1169 bool* ok);
1172 BlockT ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok); 1170 BlockT ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok);
1173 1171
1172 // Parse a SubStatement in strict mode, or with an extra block scope in
1173 // sloppy mode to handle
1174 // ES#sec-functiondeclarations-in-ifstatement-statement-clauses
1175 // The legacy parameter indicates whether function declarations are
1176 // banned by the ES2015 specification in this location, and they are being
1177 // permitted here to match previous V8 behavior.
1178 StatementT ParseScopedStatement(ZoneList<const AstRawString*>* labels,
1179 bool legacy, bool* ok);
1180
1181 StatementT ParseVariableStatement(VariableDeclarationContext var_context,
1182 ZoneList<const AstRawString*>* names,
1183 bool* ok);
1184
1185 // Magical syntax support.
1186 ExpressionT ParseV8Intrinsic(bool* ok);
1187
1188 StatementT ParseDebuggerStatement(bool* ok);
1189
1174 bool IsNextLetKeyword(); 1190 bool IsNextLetKeyword();
1175 bool IsTrivialExpression(); 1191 bool IsTrivialExpression();
1176 1192
1177 // Checks if the expression is a valid reference expression (e.g., on the 1193 // Checks if the expression is a valid reference expression (e.g., on the
1178 // left-hand side of assignments). Although ruled out by ECMA as early errors, 1194 // left-hand side of assignments). Although ruled out by ECMA as early errors,
1179 // we allow calls for web compatibility and rewrite them to a runtime throw. 1195 // we allow calls for web compatibility and rewrite them to a runtime throw.
1180 ExpressionT CheckAndRewriteReferenceExpression( 1196 ExpressionT CheckAndRewriteReferenceExpression(
1181 ExpressionT expression, int beg_pos, int end_pos, 1197 ExpressionT expression, int beg_pos, int end_pos,
1182 MessageTemplate::Template message, bool* ok); 1198 MessageTemplate::Template message, bool* ok);
1183 ExpressionT CheckAndRewriteReferenceExpression( 1199 ExpressionT CheckAndRewriteReferenceExpression(
(...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after
1705 } 1721 }
1706 1722
1707 case Token::TEMPLATE_SPAN: 1723 case Token::TEMPLATE_SPAN:
1708 case Token::TEMPLATE_TAIL: 1724 case Token::TEMPLATE_TAIL:
1709 BindingPatternUnexpectedToken(); 1725 BindingPatternUnexpectedToken();
1710 return ParseTemplateLiteral(impl()->NoTemplateTag(), beg_pos, ok); 1726 return ParseTemplateLiteral(impl()->NoTemplateTag(), beg_pos, ok);
1711 1727
1712 case Token::MOD: 1728 case Token::MOD:
1713 if (allow_natives() || extension_ != NULL) { 1729 if (allow_natives() || extension_ != NULL) {
1714 BindingPatternUnexpectedToken(); 1730 BindingPatternUnexpectedToken();
1715 return impl()->ParseV8Intrinsic(ok); 1731 return ParseV8Intrinsic(ok);
1716 } 1732 }
1717 break; 1733 break;
1718 1734
1719 case Token::DO: 1735 case Token::DO:
1720 if (allow_harmony_do_expressions()) { 1736 if (allow_harmony_do_expressions()) {
1721 BindingPatternUnexpectedToken(); 1737 BindingPatternUnexpectedToken();
1722 return impl()->ParseDoExpression(ok); 1738 return impl()->ParseDoExpression(ok);
1723 } 1739 }
1724 break; 1740 break;
1725 1741
(...skipping 1710 matching lines...) Expand 10 before | Expand all | Expand 10 after
3436 VariableDeclarationContext var_context, 3452 VariableDeclarationContext var_context,
3437 DeclarationParsingResult* parsing_result, 3453 DeclarationParsingResult* parsing_result,
3438 ZoneList<const AstRawString*>* names, bool* ok) { 3454 ZoneList<const AstRawString*>* names, bool* ok) {
3439 // VariableDeclarations :: 3455 // VariableDeclarations ::
3440 // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[','] 3456 // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
3441 // 3457 //
3442 // ES6: 3458 // ES6:
3443 // FIXME(marja, nikolaos): Add an up-to-date comment about ES6 variable 3459 // FIXME(marja, nikolaos): Add an up-to-date comment about ES6 variable
3444 // declaration syntax. 3460 // declaration syntax.
3445 3461
3446 DeclarationParsingResult temp_result; 3462 DCHECK_NOT_NULL(parsing_result);
3447 if (parsing_result == nullptr) {
3448 parsing_result = &temp_result;
3449 }
3450 parsing_result->descriptor.declaration_kind = DeclarationDescriptor::NORMAL; 3463 parsing_result->descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
3451 parsing_result->descriptor.declaration_pos = peek_position(); 3464 parsing_result->descriptor.declaration_pos = peek_position();
3452 parsing_result->descriptor.initialization_pos = peek_position(); 3465 parsing_result->descriptor.initialization_pos = peek_position();
3453 3466
3454 BlockT init_block = impl()->NullBlock(); 3467 BlockT init_block = impl()->NullBlock();
3455 if (var_context != kForStatement) { 3468 if (var_context != kForStatement) {
3456 init_block = impl()->NewBlock(nullptr, 1, true, 3469 init_block = impl()->NewBlock(nullptr, 1, true,
3457 parsing_result->descriptor.declaration_pos); 3470 parsing_result->descriptor.declaration_pos);
3458 } 3471 }
3459 3472
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after
3928 void ParserBase<Impl>::CheckDestructuringElement(ExpressionT expression, 3941 void ParserBase<Impl>::CheckDestructuringElement(ExpressionT expression,
3929 int begin, int end) { 3942 int begin, int end) {
3930 if (!IsValidPattern(expression) && !expression->IsAssignment() && 3943 if (!IsValidPattern(expression) && !expression->IsAssignment() &&
3931 !IsValidReferenceExpression(expression)) { 3944 !IsValidReferenceExpression(expression)) {
3932 classifier()->RecordAssignmentPatternError( 3945 classifier()->RecordAssignmentPatternError(
3933 Scanner::Location(begin, end), 3946 Scanner::Location(begin, end),
3934 MessageTemplate::kInvalidDestructuringTarget); 3947 MessageTemplate::kInvalidDestructuringTarget);
3935 } 3948 }
3936 } 3949 }
3937 3950
3951 template <typename Impl>
3952 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseV8Intrinsic(
3953 bool* ok) {
3954 // CallRuntime ::
3955 // '%' Identifier Arguments
3956
3957 int pos = peek_position();
3958 Expect(Token::MOD, CHECK_OK);
3959 // Allow "eval" or "arguments" for backward compatibility.
3960 IdentifierT name = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
3961 Scanner::Location spread_pos;
3962 ExpressionClassifier classifier(this);
3963 ExpressionListT args = ParseArguments(&spread_pos, CHECK_OK);
3964
3965 DCHECK(!spread_pos.IsValid());
3966
3967 return impl()->NewV8Intrinsic(name, args, pos, ok);
3968 }
3969
3938 // Redefinition of CHECK_OK for parsing statements. 3970 // Redefinition of CHECK_OK for parsing statements.
3939 #undef CHECK_OK 3971 #undef CHECK_OK
3940 #define CHECK_OK CHECK_OK_CUSTOM(NullStatement) 3972 #define CHECK_OK CHECK_OK_CUSTOM(NullStatement)
3941 3973
3942 template <typename Impl> 3974 template <typename Impl>
3943 typename ParserBase<Impl>::LazyParsingResult 3975 typename ParserBase<Impl>::LazyParsingResult
3944 ParserBase<Impl>::ParseStatementList(StatementListT body, int end_token, 3976 ParserBase<Impl>::ParseStatementList(StatementListT body, int end_token,
3945 bool may_abort, bool* ok) { 3977 bool may_abort, bool* ok) {
3946 // StatementList :: 3978 // StatementList ::
3947 // (StatementListItem)* <end_token> 3979 // (StatementListItem)* <end_token>
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
4055 // LetOrConst BindingList[?In, ?Yield] ; 4087 // LetOrConst BindingList[?In, ?Yield] ;
4056 4088
4057 switch (peek()) { 4089 switch (peek()) {
4058 case Token::FUNCTION: 4090 case Token::FUNCTION:
4059 return impl()->ParseHoistableDeclaration(nullptr, false, ok); 4091 return impl()->ParseHoistableDeclaration(nullptr, false, ok);
4060 case Token::CLASS: 4092 case Token::CLASS:
4061 Consume(Token::CLASS); 4093 Consume(Token::CLASS);
4062 return impl()->ParseClassDeclaration(nullptr, false, ok); 4094 return impl()->ParseClassDeclaration(nullptr, false, ok);
4063 case Token::VAR: 4095 case Token::VAR:
4064 case Token::CONST: 4096 case Token::CONST:
4065 return impl()->ParseVariableStatement(kStatementListItem, nullptr, ok); 4097 return ParseVariableStatement(kStatementListItem, nullptr, ok);
4066 case Token::LET: 4098 case Token::LET:
4067 if (IsNextLetKeyword()) { 4099 if (IsNextLetKeyword()) {
4068 return impl()->ParseVariableStatement(kStatementListItem, nullptr, ok); 4100 return ParseVariableStatement(kStatementListItem, nullptr, ok);
4069 } 4101 }
4070 break; 4102 break;
4071 case Token::ASYNC: 4103 case Token::ASYNC:
4072 if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION && 4104 if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION &&
4073 !scanner()->HasAnyLineTerminatorAfterNext()) { 4105 !scanner()->HasAnyLineTerminatorAfterNext()) {
4074 Consume(Token::ASYNC); 4106 Consume(Token::ASYNC);
4075 return impl()->ParseAsyncFunctionDeclaration(nullptr, false, ok); 4107 return impl()->ParseAsyncFunctionDeclaration(nullptr, false, ok);
4076 } 4108 }
4077 /* falls through */ 4109 /* falls through */
4078 default: 4110 default:
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
4152 // ES#sec-functiondeclarations-in-ifstatement-statement-clauses 4184 // ES#sec-functiondeclarations-in-ifstatement-statement-clauses
4153 // are handled by calling ParseScopedStatement rather than 4185 // are handled by calling ParseScopedStatement rather than
4154 // ParseStatement directly. 4186 // ParseStatement directly.
4155 impl()->ReportMessageAt(scanner()->peek_location(), 4187 impl()->ReportMessageAt(scanner()->peek_location(),
4156 is_strict(language_mode()) 4188 is_strict(language_mode())
4157 ? MessageTemplate::kStrictFunction 4189 ? MessageTemplate::kStrictFunction
4158 : MessageTemplate::kSloppyFunction); 4190 : MessageTemplate::kSloppyFunction);
4159 *ok = false; 4191 *ok = false;
4160 return impl()->NullStatement(); 4192 return impl()->NullStatement();
4161 case Token::DEBUGGER: 4193 case Token::DEBUGGER:
4162 return impl()->ParseDebuggerStatement(ok); 4194 return ParseDebuggerStatement(ok);
4163 case Token::VAR: 4195 case Token::VAR:
4164 return impl()->ParseVariableStatement(kStatement, nullptr, ok); 4196 return ParseVariableStatement(kStatement, nullptr, ok);
4165 default: 4197 default:
4166 return impl()->ParseExpressionOrLabelledStatement(labels, allow_function, 4198 return impl()->ParseExpressionOrLabelledStatement(labels, allow_function,
4167 ok); 4199 ok);
4168 } 4200 }
4169 } 4201 }
4170 4202
4171 // This method parses a subset of statements (break, continue, return, throw, 4203 // This method parses a subset of statements (break, continue, return, throw,
4172 // try) which are to be grouped because they all require their labeles to be 4204 // try) which are to be grouped because they all require their labeles to be
4173 // preserved in an enclosing block. 4205 // preserved in an enclosing block.
4174 template <typename Impl> 4206 template <typename Impl>
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
4215 } 4247 }
4216 } 4248 }
4217 4249
4218 Expect(Token::RBRACE, CHECK_OK_CUSTOM(NullBlock)); 4250 Expect(Token::RBRACE, CHECK_OK_CUSTOM(NullBlock));
4219 block_state.set_end_position(scanner()->location().end_pos); 4251 block_state.set_end_position(scanner()->location().end_pos);
4220 body->set_scope(block_state.FinalizedBlockScope()); 4252 body->set_scope(block_state.FinalizedBlockScope());
4221 } 4253 }
4222 return body; 4254 return body;
4223 } 4255 }
4224 4256
4257 template <typename Impl>
4258 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseScopedStatement(
4259 ZoneList<const AstRawString*>* labels, bool legacy, bool* ok) {
4260 if (is_strict(language_mode()) || peek() != Token::FUNCTION ||
4261 (legacy && allow_harmony_restrictive_declarations())) {
4262 return ParseStatement(labels, kDisallowLabelledFunctionStatement, ok);
4263 } else {
4264 if (legacy) {
4265 impl()->CountUsage(v8::Isolate::kLegacyFunctionDeclaration);
4266 }
4267 // Make a block around the statement for a lexical binding
4268 // is introduced by a FunctionDeclaration.
4269 BlockState block_state(&scope_state_);
4270 block_state.set_start_position(scanner()->location().beg_pos);
4271 BlockT block = factory()->NewBlock(NULL, 1, false, kNoSourcePosition);
4272 StatementT body = impl()->ParseFunctionDeclaration(CHECK_OK);
4273 block->statements()->Add(body, zone());
4274 block_state.set_end_position(scanner()->location().end_pos);
4275 block->set_scope(block_state.FinalizedBlockScope());
4276 return block;
4277 }
4278 }
4279
4280 template <typename Impl>
4281 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseVariableStatement(
4282 VariableDeclarationContext var_context,
4283 ZoneList<const AstRawString*>* names, bool* ok) {
4284 // VariableStatement ::
4285 // VariableDeclarations ';'
4286
4287 // The scope of a var declared variable anywhere inside a function
4288 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
4289 // transform a source-level var declaration into a (Function) Scope
4290 // declaration, and rewrite the source-level initialization into an assignment
4291 // statement. We use a block to collect multiple assignments.
4292 //
4293 // We mark the block as initializer block because we don't want the
4294 // rewriter to add a '.result' assignment to such a block (to get compliant
4295 // behavior for code such as print(eval('var x = 7')), and for cosmetic
4296 // reasons when pretty-printing. Also, unless an assignment (initialization)
4297 // is inside an initializer block, it is ignored.
4298
4299 DeclarationParsingResult parsing_result;
4300 StatementT result =
4301 ParseVariableDeclarations(var_context, &parsing_result, names, CHECK_OK);
4302 ExpectSemicolon(CHECK_OK);
4303 return result;
4304 }
4305
4306 template <typename Impl>
4307 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseDebuggerStatement(
4308 bool* ok) {
4309 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
4310 // contexts this is used as a statement which invokes the debugger as i a
4311 // break point is present.
4312 // DebuggerStatement ::
4313 // 'debugger' ';'
4314
4315 int pos = peek_position();
4316 Expect(Token::DEBUGGER, CHECK_OK);
4317 ExpectSemicolon(CHECK_OK);
4318 return factory()->NewDebuggerStatement(pos);
4319 }
4320
4225 #undef CHECK_OK 4321 #undef CHECK_OK
4226 #undef CHECK_OK_CUSTOM 4322 #undef CHECK_OK_CUSTOM
4227 4323
4228 template <typename Impl> 4324 template <typename Impl>
4229 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( 4325 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto(
4230 Token::Value property) { 4326 Token::Value property) {
4231 if (property == Token::SMI || property == Token::NUMBER) return; 4327 if (property == Token::SMI || property == Token::NUMBER) return;
4232 4328
4233 if (IsProto()) { 4329 if (IsProto()) {
4234 if (has_seen_proto_) { 4330 if (has_seen_proto_) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
4273 has_seen_constructor_ = true; 4369 has_seen_constructor_ = true;
4274 return; 4370 return;
4275 } 4371 }
4276 } 4372 }
4277 4373
4278 4374
4279 } // namespace internal 4375 } // namespace internal
4280 } // namespace v8 4376 } // namespace v8
4281 4377
4282 #endif // V8_PARSING_PARSER_BASE_H 4378 #endif // V8_PARSING_PARSER_BASE_H
OLDNEW
« no previous file with comments | « src/parsing/parser.cc ('k') | src/parsing/preparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698