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

Unified Diff: src/parsing/parser-base.h

Issue 2297563007: Move ParseVariableDeclarations to ParserBase. (Closed)
Patch Set: rebased 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/parsing/parser.cc ('k') | src/parsing/preparser.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parsing/parser-base.h
diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h
index aa2a46dc71a2aa849e88af5da77a5b07431d1681..1412748f40524459e082b2d0cf4411e079c14c5e 100644
--- a/src/parsing/parser-base.h
+++ b/src/parsing/parser-base.h
@@ -214,6 +214,7 @@ class ParserBase {
typedef typename Types::StatementList StatementListT;
typedef typename v8::internal::ExpressionClassifier<Types>
ExpressionClassifier;
+ typedef typename Types::Block BlockT;
// All implementation-specific methods must be called through this.
Impl* impl() { return static_cast<Impl*>(this); }
@@ -1177,6 +1178,11 @@ class ParserBase {
bool has_rest, int formals_start_pos,
int formals_end_pos, bool* ok);
+ BlockT ParseVariableDeclarations(VariableDeclarationContext var_context,
+ DeclarationParsingResult* parsing_result,
+ ZoneList<const AstRawString*>* names,
+ bool* ok);
+
bool IsNextLetKeyword();
bool IsTrivialExpression();
@@ -3410,6 +3416,154 @@ void ParserBase<Impl>::ParseFormalParameterList(FormalParametersT* parameters,
}
template <typename Impl>
+typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations(
+ VariableDeclarationContext var_context,
+ DeclarationParsingResult* parsing_result,
+ ZoneList<const AstRawString*>* names, bool* ok) {
+ // VariableDeclarations ::
+ // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
+ //
+ // ES6:
+ // FIXME(marja, nikolaos): Add an up-to-date comment about ES6 variable
+ // declaration syntax.
+
+ DeclarationParsingResult temp_result;
+ if (parsing_result == nullptr) {
+ parsing_result = &temp_result;
+ }
+ parsing_result->descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
+ parsing_result->descriptor.declaration_pos = peek_position();
+ parsing_result->descriptor.initialization_pos = peek_position();
+
+ BlockT init_block = impl()->NullBlock();
+ if (var_context != kForStatement) {
+ init_block = impl()->NewBlock(nullptr, 1, true,
+ parsing_result->descriptor.declaration_pos);
+ }
+
+ switch (peek()) {
+ case Token::VAR:
+ parsing_result->descriptor.mode = VAR;
+ Consume(Token::VAR);
+ break;
+ case Token::CONST:
+ Consume(Token::CONST);
+ DCHECK(var_context != kStatement);
+ parsing_result->descriptor.mode = CONST;
+ break;
+ case Token::LET:
+ Consume(Token::LET);
+ DCHECK(var_context != kStatement);
+ parsing_result->descriptor.mode = LET;
+ break;
+ default:
+ UNREACHABLE(); // by current callers
+ break;
+ }
+
+ parsing_result->descriptor.scope = scope();
+ parsing_result->descriptor.hoist_scope = nullptr;
+
+ // The scope of a var/const declared variable anywhere inside a function
+ // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope
+ // of a let declared variable is the scope of the immediately enclosing
+ // block.
+ int bindings_start = peek_position();
+ do {
+ // Parse binding pattern.
+ FuncNameInferrer::State fni_state(fni_);
+
+ ExpressionT pattern = impl()->EmptyExpression();
+ int decl_pos = peek_position();
+ {
+ ExpressionClassifier pattern_classifier(this);
+ pattern = ParsePrimaryExpression(CHECK_OK_CUSTOM(NullBlock));
+
+ ValidateBindingPattern(CHECK_OK_CUSTOM(NullBlock));
+ if (IsLexicalVariableMode(parsing_result->descriptor.mode)) {
+ ValidateLetPattern(CHECK_OK_CUSTOM(NullBlock));
+ }
+ }
+
+ Scanner::Location variable_loc = scanner()->location();
+ bool single_name = impl()->IsIdentifier(pattern);
+
+ if (single_name && fni_ != nullptr) {
+ impl()->PushVariableName(fni_, impl()->AsIdentifier(pattern));
+ }
+
+ ExpressionT value = impl()->EmptyExpression();
+ int initializer_position = kNoSourcePosition;
+ if (Check(Token::ASSIGN)) {
+ ExpressionClassifier classifier(this);
+ value = ParseAssignmentExpression(var_context != kForStatement,
+ CHECK_OK_CUSTOM(NullBlock));
+ impl()->RewriteNonPattern(CHECK_OK_CUSTOM(NullBlock));
+ variable_loc.end_pos = scanner()->location().end_pos;
+
+ if (!parsing_result->first_initializer_loc.IsValid()) {
+ parsing_result->first_initializer_loc = variable_loc;
+ }
+
+ // Don't infer if it is "a = function(){...}();"-like expression.
+ if (single_name && fni_ != nullptr) {
+ if (!value->IsCall() && !value->IsCallNew()) {
+ fni_->Infer();
+ } else {
+ fni_->RemoveLastFunction();
+ }
+ }
+
+ impl()->SetFunctionNameFromIdentifierRef(value, pattern);
+
+ // End position of the initializer is after the assignment expression.
+ initializer_position = scanner()->location().end_pos;
+ } else {
+ if (var_context != kForStatement || !PeekInOrOf()) {
+ // ES6 'const' and binding patterns require initializers.
+ if (parsing_result->descriptor.mode == CONST ||
+ !impl()->IsIdentifier(pattern)) {
+ impl()->ReportMessageAt(
+ Scanner::Location(decl_pos, scanner()->location().end_pos),
+ MessageTemplate::kDeclarationMissingInitializer,
+ !impl()->IsIdentifier(pattern) ? "destructuring" : "const");
+ *ok = false;
+ return impl()->NullBlock();
+ }
+ // 'let x' initializes 'x' to undefined.
+ if (parsing_result->descriptor.mode == LET) {
+ value = impl()->GetLiteralUndefined(position());
+ }
+ }
+
+ // End position of the initializer is after the variable.
+ initializer_position = position();
+ }
+
+ typename DeclarationParsingResult::Declaration decl(
+ pattern, initializer_position, value);
+ if (var_context == kForStatement) {
+ // Save the declaration for further handling in ParseForStatement.
+ parsing_result->declarations.Add(decl);
+ } else {
+ // Immediately declare the variable otherwise. This avoids O(N^2)
+ // behavior (where N is the number of variables in a single
+ // declaration) in the PatternRewriter having to do with removing
+ // and adding VariableProxies to the Scope (see bug 4699).
+ impl()->DeclareAndInitializeVariables(init_block,
+ &parsing_result->descriptor, &decl,
+ names, CHECK_OK_CUSTOM(NullBlock));
+ }
+ } while (Check(Token::COMMA));
+
+ parsing_result->bindings_loc =
+ Scanner::Location(bindings_start, scanner()->location().end_pos);
+
+ DCHECK(*ok);
+ return init_block;
+}
+
+template <typename Impl>
void ParserBase<Impl>::CheckArityRestrictions(int param_count,
FunctionKind function_kind,
bool has_rest,
« 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