Index: src/parsing/preparser.cc |
diff --git a/src/parsing/preparser.cc b/src/parsing/preparser.cc |
index aa0d27ad1d58f614c86526c39a592b719dd0d875..369ff2415efb8dbe3351b73dfb3c818147460c64 100644 |
--- a/src/parsing/preparser.cc |
+++ b/src/parsing/preparser.cc |
@@ -423,118 +423,12 @@ PreParser::Statement PreParser::ParseVariableStatement( |
// VariableStatement :: |
// VariableDeclarations ';' |
- Statement result = ParseVariableDeclarations( |
- var_context, nullptr, nullptr, nullptr, nullptr, nullptr, CHECK_OK); |
+ Statement result = |
+ ParseVariableDeclarations(var_context, nullptr, nullptr, CHECK_OK); |
ExpectSemicolon(CHECK_OK); |
return result; |
} |
- |
-// If the variable declaration declares exactly one non-const |
-// variable, then *var is set to that variable. In all other cases, |
-// *var is untouched; in particular, it is the caller's responsibility |
-// to initialize it properly. This mechanism is also used for the parsing |
-// of 'for-in' loops. |
-PreParser::Statement PreParser::ParseVariableDeclarations( |
- VariableDeclarationContext var_context, int* num_decl, bool* is_lexical, |
- bool* is_binding_pattern, Scanner::Location* first_initializer_loc, |
- Scanner::Location* bindings_loc, bool* ok) { |
- // VariableDeclarations :: |
- // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] |
- // |
- // The ES6 Draft Rev3 specifies the following grammar for const declarations |
- // |
- // ConstDeclaration :: |
- // const ConstBinding (',' ConstBinding)* ';' |
- // ConstBinding :: |
- // Identifier '=' AssignmentExpression |
- // |
- // TODO(ES6): |
- // ConstBinding :: |
- // BindingPattern '=' AssignmentExpression |
- bool require_initializer = false; |
- bool lexical = false; |
- bool is_pattern = false; |
- if (peek() == Token::VAR) { |
- Consume(Token::VAR); |
- } else if (peek() == Token::CONST) { |
- // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads: |
- // |
- // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';' |
- // |
- // * It is a Syntax Error if the code that matches this production is not |
- // contained in extended code. |
- // |
- // However disallowing const in sloppy mode will break compatibility with |
- // existing pages. Therefore we keep allowing const with the old |
- // non-harmony semantics in sloppy mode. |
- Consume(Token::CONST); |
- DCHECK(var_context != kStatement); |
- require_initializer = true; |
- lexical = true; |
- } else if (peek() == Token::LET) { |
- Consume(Token::LET); |
- DCHECK(var_context != kStatement); |
- lexical = true; |
- } else { |
- *ok = false; |
- return Statement::Default(); |
- } |
- |
- // 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 nvars = 0; // the number of variables declared |
- int bindings_start = peek_position(); |
- do { |
- // Parse binding pattern. |
- if (nvars > 0) Consume(Token::COMMA); |
- int decl_pos = peek_position(); |
- PreParserExpression pattern = PreParserExpression::Default(); |
- { |
- ExpressionClassifier pattern_classifier(this); |
- pattern = ParsePrimaryExpression(CHECK_OK); |
- |
- ValidateBindingPattern(CHECK_OK); |
- if (lexical) ValidateLetPattern(CHECK_OK); |
- } |
- |
- is_pattern = pattern.IsObjectLiteral() || pattern.IsArrayLiteral(); |
- |
- Scanner::Location variable_loc = scanner()->location(); |
- nvars++; |
- if (Check(Token::ASSIGN)) { |
- ExpressionClassifier classifier(this); |
- ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); |
- ValidateExpression(CHECK_OK); |
- |
- variable_loc.end_pos = scanner()->location().end_pos; |
- if (first_initializer_loc && !first_initializer_loc->IsValid()) { |
- *first_initializer_loc = variable_loc; |
- } |
- } else if ((require_initializer || is_pattern) && |
- (var_context != kForStatement || !PeekInOrOf())) { |
- ReportMessageAt( |
- Scanner::Location(decl_pos, scanner()->location().end_pos), |
- MessageTemplate::kDeclarationMissingInitializer, |
- is_pattern ? "destructuring" : "const"); |
- *ok = false; |
- return Statement::Default(); |
- } |
- } while (peek() == Token::COMMA); |
- |
- if (bindings_loc) { |
- *bindings_loc = |
- Scanner::Location(bindings_start, scanner()->location().end_pos); |
- } |
- |
- if (num_decl != nullptr) *num_decl = nvars; |
- if (is_lexical != nullptr) *is_lexical = lexical; |
- if (is_binding_pattern != nullptr) *is_binding_pattern = is_pattern; |
- return Statement::Default(); |
-} |
- |
PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { |
Consume(Token::FUNCTION); |
int pos = position(); |
@@ -798,32 +692,35 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) { |
ForEachStatement::VisitMode mode; |
if (peek() == Token::VAR || peek() == Token::CONST || |
(peek() == Token::LET && IsNextLetKeyword())) { |
- int decl_count; |
- bool is_lexical; |
- bool is_binding_pattern; |
- Scanner::Location first_initializer_loc = Scanner::Location::invalid(); |
- Scanner::Location bindings_loc = Scanner::Location::invalid(); |
- ParseVariableDeclarations(kForStatement, &decl_count, &is_lexical, |
- &is_binding_pattern, &first_initializer_loc, |
- &bindings_loc, CHECK_OK); |
- if (is_lexical) has_lexical = true; |
+ DeclarationParsingResult parsing_result; |
+ |
+ ParseVariableDeclarations(kForStatement, &parsing_result, nullptr, |
+ CHECK_OK); |
+ if (parsing_result.descriptor.mode == CONST || |
+ parsing_result.descriptor.mode == LET) { |
+ has_lexical = true; |
+ } |
if (CheckInOrOf(&mode)) { |
- if (decl_count != 1) { |
- ReportMessageAt(bindings_loc, |
+ if (!*ok) return Statement::Default(); |
+ if (parsing_result.declarations.length() != 1) { |
+ ReportMessageAt(parsing_result.bindings_loc, |
MessageTemplate::kForInOfLoopMultiBindings, |
ForEachStatement::VisitModeString(mode)); |
*ok = false; |
return Statement::Default(); |
} |
- if (first_initializer_loc.IsValid() && |
+ bool is_binding_pattern = |
+ parsing_result.declarations[0].pattern.IsObjectLiteral() || |
+ parsing_result.declarations[0].pattern.IsArrayLiteral(); |
+ if (parsing_result.first_initializer_loc.IsValid() && |
(is_strict(language_mode()) || mode == ForEachStatement::ITERATE || |
- is_lexical || is_binding_pattern || allow_harmony_for_in())) { |
+ has_lexical || is_binding_pattern || allow_harmony_for_in())) { |
// Only increment the use count if we would have let this through |
// without the flag. |
if (use_counts_ != nullptr && allow_harmony_for_in()) { |
++use_counts_[v8::Isolate::kForInInitializer]; |
} |
- ReportMessageAt(first_initializer_loc, |
+ ReportMessageAt(parsing_result.first_initializer_loc, |
MessageTemplate::kForInOfLoopInitializer, |
ForEachStatement::VisitModeString(mode)); |
*ok = false; |