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

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

Issue 2307073002: [parser] Refactor of Parse*Statement*, part 1 (Closed)
Patch Set: 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
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/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 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 // // not related to pure parsing. 179 // // not related to pure parsing.
180 // typedef GeneratorVariable; 180 // typedef GeneratorVariable;
181 // // Return types for traversing functions. 181 // // Return types for traversing functions.
182 // typedef Identifier; 182 // typedef Identifier;
183 // typedef Expression; 183 // typedef Expression;
184 // typedef FunctionLiteral; 184 // typedef FunctionLiteral;
185 // typedef ObjectLiteralProperty; 185 // typedef ObjectLiteralProperty;
186 // typedef ExpressionList; 186 // typedef ExpressionList;
187 // typedef PropertyList; 187 // typedef PropertyList;
188 // typedef FormalParameters; 188 // typedef FormalParameters;
189 // typedef Statement;
189 // typedef StatementList; 190 // typedef StatementList;
190 // typedef Block; 191 // typedef Block;
191 // // For constructing objects returned by the traversing functions. 192 // // For constructing objects returned by the traversing functions.
192 // typedef Factory; 193 // typedef Factory;
194 // // For other implementation-specific tasks.
195 // typedef Target;
196 // typedef TargetScope;
193 // }; 197 // };
194 198
195 template <typename Impl> 199 template <typename Impl>
196 struct ParserTypes; 200 struct ParserTypes;
197 201
198 template <typename Impl> 202 template <typename Impl>
199 class ParserBase { 203 class ParserBase {
200 public: 204 public:
201 // Shorten type names defined by ParserTypes<Impl>. 205 // Shorten type names defined by ParserTypes<Impl>.
202 typedef ParserTypes<Impl> Types; 206 typedef ParserTypes<Impl> Types;
203 typedef typename Types::Identifier IdentifierT; 207 typedef typename Types::Identifier IdentifierT;
204 typedef typename Types::Expression ExpressionT; 208 typedef typename Types::Expression ExpressionT;
205 typedef typename Types::FunctionLiteral FunctionLiteralT; 209 typedef typename Types::FunctionLiteral FunctionLiteralT;
206 typedef typename Types::ObjectLiteralProperty ObjectLiteralPropertyT; 210 typedef typename Types::ObjectLiteralProperty ObjectLiteralPropertyT;
207 typedef typename Types::ExpressionList ExpressionListT; 211 typedef typename Types::ExpressionList ExpressionListT;
208 typedef typename Types::PropertyList PropertyListT; 212 typedef typename Types::PropertyList PropertyListT;
209 typedef typename Types::FormalParameters FormalParametersT; 213 typedef typename Types::FormalParameters FormalParametersT;
214 typedef typename Types::Statement StatementT;
210 typedef typename Types::StatementList StatementListT; 215 typedef typename Types::StatementList StatementListT;
211 typedef typename Types::Block BlockT; 216 typedef typename Types::Block BlockT;
212 typedef typename v8::internal::ExpressionClassifier<Types> 217 typedef typename v8::internal::ExpressionClassifier<Types>
213 ExpressionClassifier; 218 ExpressionClassifier;
214 219
215 // All implementation-specific methods must be called through this. 220 // All implementation-specific methods must be called through this.
216 Impl* impl() { return static_cast<Impl*>(this); } 221 Impl* impl() { return static_cast<Impl*>(this); }
217 const Impl* impl() const { return static_cast<const Impl*>(this); } 222 const Impl* impl() const { return static_cast<const Impl*>(this); }
218 223
219 ParserBase(Zone* zone, Scanner* scanner, uintptr_t stack_limit, 224 ParserBase(Zone* zone, Scanner* scanner, uintptr_t stack_limit,
(...skipping 689 matching lines...) Expand 10 before | Expand all | Expand 10 after
909 return 0; // 0 precedence will terminate binary expression parsing 914 return 0; // 0 precedence will terminate binary expression parsing
910 return Token::Precedence(token); 915 return Token::Precedence(token);
911 } 916 }
912 917
913 typename Types::Factory* factory() { return &ast_node_factory_; } 918 typename Types::Factory* factory() { return &ast_node_factory_; }
914 919
915 DeclarationScope* GetReceiverScope() const { 920 DeclarationScope* GetReceiverScope() const {
916 return scope()->GetReceiverScope(); 921 return scope()->GetReceiverScope();
917 } 922 }
918 LanguageMode language_mode() { return scope()->language_mode(); } 923 LanguageMode language_mode() { return scope()->language_mode(); }
924 void RaiseLanguageMode(LanguageMode mode) {
925 LanguageMode old = scope()->language_mode();
926 impl()->SetLanguageMode(scope(), old > mode ? old : mode);
927 }
919 bool is_generator() const { return function_state_->is_generator(); } 928 bool is_generator() const { return function_state_->is_generator(); }
920 bool is_async_function() const { 929 bool is_async_function() const {
921 return function_state_->is_async_function(); 930 return function_state_->is_async_function();
922 } 931 }
923 bool is_resumable() const { return function_state_->is_resumable(); } 932 bool is_resumable() const { return function_state_->is_resumable(); }
924 933
925 // Report syntax errors. 934 // Report syntax errors.
926 void ReportMessage(MessageTemplate::Template message, const char* arg = NULL, 935 void ReportMessage(MessageTemplate::Template message, const char* arg = NULL,
927 ParseErrorType error_type = kSyntaxError) { 936 ParseErrorType error_type = kSyntaxError) {
928 Scanner::Location source_location = scanner()->location(); 937 Scanner::Location source_location = scanner()->location();
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
1172 void ParseFormalParameterList(FormalParametersT* parameters, bool* ok); 1181 void ParseFormalParameterList(FormalParametersT* parameters, bool* ok);
1173 void CheckArityRestrictions(int param_count, FunctionKind function_type, 1182 void CheckArityRestrictions(int param_count, FunctionKind function_type,
1174 bool has_rest, int formals_start_pos, 1183 bool has_rest, int formals_start_pos,
1175 int formals_end_pos, bool* ok); 1184 int formals_end_pos, bool* ok);
1176 1185
1177 BlockT ParseVariableDeclarations(VariableDeclarationContext var_context, 1186 BlockT ParseVariableDeclarations(VariableDeclarationContext var_context,
1178 DeclarationParsingResult* parsing_result, 1187 DeclarationParsingResult* parsing_result,
1179 ZoneList<const AstRawString*>* names, 1188 ZoneList<const AstRawString*>* names,
1180 bool* ok); 1189 bool* ok);
1181 1190
1191 static const int kLazyParseTrialLimit = 200;
marja 2016/09/05 08:14:33 This const declaration could use a short comment h
nickie 2016/09/05 11:29:31 Done. It never had one, so I improvised.
1192 V8_INLINE void ParseStatementList(StatementListT body, int end_token,
1193 bool* ok) {
1194 LazyParsingResult result = ParseStatementList(body, end_token, false, ok);
1195 USE(result); // The result is just used in debug modes.
marja 2016/09/05 08:14:33 ... this comment, on the other hand, is not very u
nickie 2016/09/05 11:29:31 Done. Removed.
1196 DCHECK_EQ(result, kLazyParsingComplete);
1197 }
1198 LazyParsingResult ParseStatementList(StatementListT body, int end_token,
1199 bool may_abort, bool* ok);
1200 StatementT ParseStatementListItem(bool* ok);
1201 StatementT ParseStatement(ZoneList<const AstRawString*>* labels,
1202 AllowLabelledFunctionStatement allow_function,
1203 bool* ok);
1204 StatementT ParseStatementAsUnlabelled(ZoneList<const AstRawString*>* labels,
1205 bool* ok);
1206
1182 bool IsNextLetKeyword(); 1207 bool IsNextLetKeyword();
1183 bool IsTrivialExpression(); 1208 bool IsTrivialExpression();
1184 1209
1185 // Checks if the expression is a valid reference expression (e.g., on the 1210 // Checks if the expression is a valid reference expression (e.g., on the
1186 // left-hand side of assignments). Although ruled out by ECMA as early errors, 1211 // left-hand side of assignments). Although ruled out by ECMA as early errors,
1187 // we allow calls for web compatibility and rewrite them to a runtime throw. 1212 // we allow calls for web compatibility and rewrite them to a runtime throw.
1188 ExpressionT CheckAndRewriteReferenceExpression( 1213 ExpressionT CheckAndRewriteReferenceExpression(
1189 ExpressionT expression, int beg_pos, int end_pos, 1214 ExpressionT expression, int beg_pos, int end_pos,
1190 MessageTemplate::Template message, bool* ok); 1215 MessageTemplate::Template message, bool* ok);
1191 ExpressionT CheckAndRewriteReferenceExpression( 1216 ExpressionT CheckAndRewriteReferenceExpression(
(...skipping 2714 matching lines...) Expand 10 before | Expand all | Expand 10 after
3906 void ParserBase<Impl>::CheckDestructuringElement(ExpressionT expression, 3931 void ParserBase<Impl>::CheckDestructuringElement(ExpressionT expression,
3907 int begin, int end) { 3932 int begin, int end) {
3908 if (!IsValidPattern(expression) && !expression->IsAssignment() && 3933 if (!IsValidPattern(expression) && !expression->IsAssignment() &&
3909 !IsValidReferenceExpression(expression)) { 3934 !IsValidReferenceExpression(expression)) {
3910 classifier()->RecordAssignmentPatternError( 3935 classifier()->RecordAssignmentPatternError(
3911 Scanner::Location(begin, end), 3936 Scanner::Location(begin, end),
3912 MessageTemplate::kInvalidDestructuringTarget); 3937 MessageTemplate::kInvalidDestructuringTarget);
3913 } 3938 }
3914 } 3939 }
3915 3940
3941 // Redefinition of CHECK_OK for parsing statements.
3942 #undef CHECK_OK
3943 #define CHECK_OK CHECK_OK_CUSTOM(NullStatement)
3944
3945 template <typename Impl>
3946 typename ParserBase<Impl>::LazyParsingResult
3947 ParserBase<Impl>::ParseStatementList(StatementListT body, int end_token,
3948 bool may_abort, bool* ok) {
3949 // StatementList ::
3950 // (StatementListItem)* <end_token>
3951
3952 // Allocate a target stack to use for this set of source
3953 // elements. This way, all scripts and functions get their own
3954 // target stack thus avoiding illegal breaks and continues across
3955 // functions.
3956 typename Types::TargetScope target_scope(this);
3957 int count_statements = 0;
3958
3959 DCHECK(!impl()->IsNullStatementList(body));
3960 bool directive_prologue = true; // Parsing directive prologue.
3961
3962 while (peek() != end_token) {
3963 if (directive_prologue && peek() != Token::STRING) {
3964 directive_prologue = false;
3965 }
3966
3967 bool starts_with_identifier = peek() == Token::IDENTIFIER;
3968 Scanner::Location token_loc = scanner()->peek_location();
3969 StatementT stat = impl()->ParseStatementListItem(
3970 CHECK_OK_CUSTOM(Return, kLazyParsingComplete));
3971
3972 if (impl()->IsNullOrEmptyStatement(stat)) {
3973 directive_prologue = false; // End of directive prologue.
3974 continue;
3975 }
3976
3977 if (directive_prologue) {
3978 // The length of the token is used to distinguish between strings literals
3979 // that evaluate equal to directives but contain either escape sequences
3980 // (e.g., "use \x73trict") or line continuations (e.g., "use \
3981 // strict").
3982 if (impl()->IsUseStrictDirective(stat) &&
3983 token_loc.end_pos - token_loc.beg_pos == sizeof("use strict") + 1) {
3984 // Directive "use strict" (ES5 14.1).
3985 RaiseLanguageMode(STRICT);
3986 if (!scope()->HasSimpleParameters()) {
3987 // TC39 deemed "use strict" directives to be an error when occurring
3988 // in the body of a function with non-simple parameter list, on
3989 // 29/7/2015. https://goo.gl/ueA7Ln
3990 impl()->ReportMessageAt(
3991 token_loc, MessageTemplate::kIllegalLanguageModeDirective,
3992 "use strict");
3993 *ok = false;
3994 return kLazyParsingComplete;
3995 }
3996 // Because declarations in strict eval code don't leak into the scope
3997 // of the eval call, it is likely that functions declared in strict
3998 // eval code will be used within the eval code, so lazy parsing is
3999 // probably not a win.
4000 if (scope()->is_eval_scope()) mode_ = PARSE_EAGERLY;
4001 } else if (impl()->IsUseAsmDirective(stat) &&
4002 token_loc.end_pos - token_loc.beg_pos ==
4003 sizeof("use asm") + 1) {
4004 // Directive "use asm".
4005 impl()->SetAsmModule();
4006 } else if (impl()->IsStringLiteral(stat)) {
4007 // Possibly an unknown directive.
4008 // TODO(nikolaos): Check if the following is really what we want!
4009 // """Should not change mode, but will increment UseCounter
4010 // if appropriate. Ditto usages below.""" ???
4011 RaiseLanguageMode(SLOPPY);
4012 } else {
nickie 2016/09/05 11:29:31 These were copied from here [1] and history takes
4013 // End of the directive prologue.
4014 directive_prologue = false;
4015 // TODO(nikolaos): Check if the following is really what we want!
4016 RaiseLanguageMode(SLOPPY);
4017 }
4018 } else {
4019 // TODO(nikolaos): Check if the following is really what we want!
4020 RaiseLanguageMode(SLOPPY);
4021 }
4022
4023 // If we're allowed to reset to a bookmark, we will do so when we see a long
4024 // and trivial function.
4025 // Our current definition of 'long and trivial' is:
4026 // - over 200 statements
4027 // - all starting with an identifier (i.e., no if, for, while, etc.)
4028 if (may_abort) {
4029 if (!starts_with_identifier) {
4030 may_abort = false;
4031 } else if (++count_statements > kLazyParseTrialLimit) {
4032 return kLazyParsingAborted;
4033 }
4034 }
4035
4036 body->Add(stat, zone());
4037 }
4038 return kLazyParsingComplete;
4039 }
4040
4041 template <typename Impl>
4042 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatementListItem(
4043 bool* ok) {
4044 // ECMA 262 6th Edition
4045 // StatementListItem[Yield, Return] :
4046 // Statement[?Yield, ?Return]
4047 // Declaration[?Yield]
4048 //
4049 // Declaration[Yield] :
4050 // HoistableDeclaration[?Yield]
4051 // ClassDeclaration[?Yield]
4052 // LexicalDeclaration[In, ?Yield]
4053 //
4054 // HoistableDeclaration[Yield, Default] :
4055 // FunctionDeclaration[?Yield, ?Default]
4056 // GeneratorDeclaration[?Yield, ?Default]
4057 //
4058 // LexicalDeclaration[In, Yield] :
4059 // LetOrConst BindingList[?In, ?Yield] ;
4060
4061 switch (peek()) {
4062 case Token::FUNCTION:
4063 return impl()->ParseHoistableDeclaration(NULL, false, ok);
marja 2016/09/05 08:14:33 Nit: NULL -> nullptr in several places
nickie 2016/09/05 11:29:31 Done.
4064 case Token::CLASS:
4065 Consume(Token::CLASS);
4066 return impl()->ParseClassDeclaration(NULL, false, ok);
4067 case Token::VAR:
4068 case Token::CONST:
4069 return impl()->ParseVariableStatement(kStatementListItem, NULL, ok);
4070 case Token::LET:
4071 if (IsNextLetKeyword()) {
4072 return impl()->ParseVariableStatement(kStatementListItem, NULL, ok);
4073 }
4074 break;
4075 case Token::ASYNC:
4076 if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION &&
4077 !scanner()->HasAnyLineTerminatorAfterNext()) {
4078 Consume(Token::ASYNC);
4079 return impl()->ParseAsyncFunctionDeclaration(NULL, false, ok);
4080 }
4081 /* falls through */
4082 default:
4083 break;
4084 }
4085 return impl()->ParseStatement(NULL, kAllowLabelledFunctionStatement, ok);
4086 }
4087
4088 template <typename Impl>
4089 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatement(
4090 ZoneList<const AstRawString*>* labels,
4091 AllowLabelledFunctionStatement allow_function, bool* ok) {
4092 // Statement ::
4093 // Block
4094 // VariableStatement
4095 // EmptyStatement
4096 // ExpressionStatement
4097 // IfStatement
4098 // IterationStatement
4099 // ContinueStatement
4100 // BreakStatement
4101 // ReturnStatement
4102 // WithStatement
4103 // LabelledStatement
4104 // SwitchStatement
4105 // ThrowStatement
4106 // TryStatement
4107 // DebuggerStatement
4108
4109 // Note: Since labels can only be used by 'break' and 'continue'
4110 // statements, which themselves are only valid within blocks,
4111 // iterations or 'switch' statements (i.e., BreakableStatements),
4112 // labels can be simply ignored in all other cases; except for
4113 // trivial labeled break statements 'label: break label' which is
4114 // parsed into an empty statement.
4115 switch (peek()) {
4116 case Token::LBRACE:
4117 return impl()->ParseBlock(labels, ok);
4118 case Token::SEMICOLON:
4119 Next();
4120 return factory()->NewEmptyStatement(kNoSourcePosition);
4121 case Token::IF:
4122 return impl()->ParseIfStatement(labels, ok);
4123 case Token::DO:
4124 return impl()->ParseDoWhileStatement(labels, ok);
4125 case Token::WHILE:
4126 return impl()->ParseWhileStatement(labels, ok);
4127 case Token::FOR:
4128 return impl()->ParseForStatement(labels, ok);
4129 case Token::CONTINUE:
4130 case Token::BREAK:
4131 case Token::RETURN:
4132 case Token::THROW:
4133 case Token::TRY: {
4134 // These statements must have their labels preserved in an enclosing
4135 // block
4136 if (labels == nullptr) {
4137 return ParseStatementAsUnlabelled(labels, ok);
4138 } else {
4139 BlockT result =
4140 factory()->NewBlock(labels, 1, false, kNoSourcePosition);
4141 typename Types::Target target(this, result);
4142 StatementT statement = ParseStatementAsUnlabelled(labels, CHECK_OK);
marja 2016/09/05 08:14:33 What does "ParseStatementAsUnlabelled" mean? You'r
nickie 2016/09/05 11:29:31 I don't know what it means... :-) (Offline discuss
4143 result->statements()->Add(statement, zone());
4144 return result;
4145 }
4146 }
4147 case Token::WITH:
4148 return impl()->ParseWithStatement(labels, ok);
4149 case Token::SWITCH:
4150 return impl()->ParseSwitchStatement(labels, ok);
4151 case Token::FUNCTION:
4152 // FunctionDeclaration only allowed as a StatementListItem, not in
4153 // an arbitrary Statement position. Exceptions such as
4154 // ES#sec-functiondeclarations-in-ifstatement-statement-clauses
4155 // are handled by calling ParseScopedStatement rather than
4156 // ParseStatement directly.
4157 impl()->ReportMessageAt(scanner()->peek_location(),
4158 is_strict(language_mode())
4159 ? MessageTemplate::kStrictFunction
4160 : MessageTemplate::kSloppyFunction);
4161 *ok = false;
4162 return impl()->NullStatement();
4163 case Token::DEBUGGER:
4164 return impl()->ParseDebuggerStatement(ok);
4165 case Token::VAR:
4166 return impl()->ParseVariableStatement(kStatement, nullptr, ok);
4167 default:
4168 return impl()->ParseExpressionOrLabelledStatement(labels, allow_function,
4169 ok);
4170 }
4171 }
4172
4173 template <typename Impl>
4174 typename ParserBase<Impl>::StatementT
4175 ParserBase<Impl>::ParseStatementAsUnlabelled(
4176 ZoneList<const AstRawString*>* labels, bool* ok) {
4177 switch (peek()) {
4178 case Token::CONTINUE:
4179 return impl()->ParseContinueStatement(ok);
4180 case Token::BREAK:
4181 return impl()->ParseBreakStatement(labels, ok);
4182 case Token::RETURN:
4183 return impl()->ParseReturnStatement(ok);
4184 case Token::THROW:
4185 return impl()->ParseThrowStatement(ok);
4186 case Token::TRY:
4187 return impl()->ParseTryStatement(ok);
4188 default:
4189 UNREACHABLE();
4190 return impl()->NullStatement();
4191 }
4192 }
4193
3916 #undef CHECK_OK 4194 #undef CHECK_OK
3917 #undef CHECK_OK_CUSTOM 4195 #undef CHECK_OK_CUSTOM
3918 4196
3919 template <typename Impl> 4197 template <typename Impl>
3920 void ParserBase<Impl>::ObjectLiteralChecker::CheckProperty( 4198 void ParserBase<Impl>::ObjectLiteralChecker::CheckProperty(
3921 Token::Value property, PropertyKind type, MethodKind method_type, 4199 Token::Value property, PropertyKind type, MethodKind method_type,
3922 bool* ok) { 4200 bool* ok) {
3923 DCHECK(!IsStaticMethod(method_type)); 4201 DCHECK(!IsStaticMethod(method_type));
3924 DCHECK(!IsSpecialMethod(method_type) || 4202 DCHECK(!IsSpecialMethod(method_type) ||
3925 type == PropertyKind::kMethodProperty); 4203 type == PropertyKind::kMethodProperty);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
3971 has_seen_constructor_ = true; 4249 has_seen_constructor_ = true;
3972 return; 4250 return;
3973 } 4251 }
3974 } 4252 }
3975 4253
3976 4254
3977 } // namespace internal 4255 } // namespace internal
3978 } // namespace v8 4256 } // namespace v8
3979 4257
3980 #endif // V8_PARSING_PARSER_BASE_H 4258 #endif // V8_PARSING_PARSER_BASE_H
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698