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

Side by Side Diff: src/preparser.cc

Issue 1062263002: [parser] report better errors for multiple ForBindings in ForIn/Of loops (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: add tests for zero declarations Created 5 years, 8 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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 #include <cmath> 5 #include <cmath>
6 6
7 #include "src/allocation.h" 7 #include "src/allocation.h"
8 #include "src/base/logging.h" 8 #include "src/base/logging.h"
9 #include "src/conversions-inl.h" 9 #include "src/conversions-inl.h"
10 #include "src/conversions.h" 10 #include "src/conversions.h"
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 return Statement::Default(); 403 return Statement::Default();
404 } 404 }
405 405
406 406
407 PreParser::Statement PreParser::ParseVariableStatement( 407 PreParser::Statement PreParser::ParseVariableStatement(
408 VariableDeclarationContext var_context, 408 VariableDeclarationContext var_context,
409 bool* ok) { 409 bool* ok) {
410 // VariableStatement :: 410 // VariableStatement ::
411 // VariableDeclarations ';' 411 // VariableDeclarations ';'
412 412
413 Statement result = 413 Statement result = ParseVariableDeclarations(var_context, nullptr, nullptr,
414 ParseVariableDeclarations(var_context, nullptr, nullptr, CHECK_OK); 414 nullptr, CHECK_OK);
415 ExpectSemicolon(CHECK_OK); 415 ExpectSemicolon(CHECK_OK);
416 return result; 416 return result;
417 } 417 }
418 418
419 419
420 // If the variable declaration declares exactly one non-const 420 // If the variable declaration declares exactly one non-const
421 // variable, then *var is set to that variable. In all other cases, 421 // variable, then *var is set to that variable. In all other cases,
422 // *var is untouched; in particular, it is the caller's responsibility 422 // *var is untouched; in particular, it is the caller's responsibility
423 // to initialize it properly. This mechanism is also used for the parsing 423 // to initialize it properly. This mechanism is also used for the parsing
424 // of 'for-in' loops. 424 // of 'for-in' loops.
425 PreParser::Statement PreParser::ParseVariableDeclarations( 425 PreParser::Statement PreParser::ParseVariableDeclarations(
426 VariableDeclarationContext var_context, int* num_decl, 426 VariableDeclarationContext var_context, int* num_decl,
427 Scanner::Location* first_initializer_loc, bool* ok) { 427 Scanner::Location* first_initializer_loc, Scanner::Location* bindings_loc,
428 bool* ok) {
428 // VariableDeclarations :: 429 // VariableDeclarations ::
429 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] 430 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
430 // 431 //
431 // The ES6 Draft Rev3 specifies the following grammar for const declarations 432 // The ES6 Draft Rev3 specifies the following grammar for const declarations
432 // 433 //
433 // ConstDeclaration :: 434 // ConstDeclaration ::
434 // const ConstBinding (',' ConstBinding)* ';' 435 // const ConstBinding (',' ConstBinding)* ';'
435 // ConstBinding :: 436 // ConstBinding ::
436 // Identifier '=' AssignmentExpression 437 // Identifier '=' AssignmentExpression
437 // 438 //
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 } else { 472 } else {
472 *ok = false; 473 *ok = false;
473 return Statement::Default(); 474 return Statement::Default();
474 } 475 }
475 476
476 // The scope of a var/const declared variable anywhere inside a function 477 // The scope of a var/const declared variable anywhere inside a function
477 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope 478 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope
478 // of a let declared variable is the scope of the immediately enclosing 479 // of a let declared variable is the scope of the immediately enclosing
479 // block. 480 // block.
480 int nvars = 0; // the number of variables declared 481 int nvars = 0; // the number of variables declared
482 int bindings_start = peek_position();
481 do { 483 do {
482 // Parse variable name. 484 // Parse variable name.
483 if (nvars > 0) Consume(Token::COMMA); 485 if (nvars > 0) Consume(Token::COMMA);
484 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); 486 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
485 Scanner::Location variable_loc = scanner()->location(); 487 Scanner::Location variable_loc = scanner()->location();
486 nvars++; 488 nvars++;
487 if (peek() == Token::ASSIGN || require_initializer || 489 if (peek() == Token::ASSIGN || require_initializer ||
488 // require initializers for multiple consts. 490 // require initializers for multiple consts.
489 (is_strict_const && peek() == Token::COMMA)) { 491 (is_strict_const && peek() == Token::COMMA)) {
490 Expect(Token::ASSIGN, CHECK_OK); 492 Expect(Token::ASSIGN, CHECK_OK);
491 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); 493 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
492 494
493 variable_loc.end_pos = scanner()->location().end_pos; 495 variable_loc.end_pos = scanner()->location().end_pos;
494 if (first_initializer_loc && !first_initializer_loc->IsValid()) { 496 if (first_initializer_loc && !first_initializer_loc->IsValid()) {
495 *first_initializer_loc = variable_loc; 497 *first_initializer_loc = variable_loc;
496 } 498 }
497 } 499 }
498 } while (peek() == Token::COMMA); 500 } while (peek() == Token::COMMA);
499 501
502 if (bindings_loc) {
503 *bindings_loc =
504 Scanner::Location(bindings_start, scanner()->location().end_pos);
505 }
506
500 if (num_decl != NULL) *num_decl = nvars; 507 if (num_decl != NULL) *num_decl = nvars;
501 return Statement::Default(); 508 return Statement::Default();
502 } 509 }
503 510
504 511
505 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { 512 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
506 // ExpressionStatement | LabelledStatement :: 513 // ExpressionStatement | LabelledStatement ::
507 // Expression ';' 514 // Expression ';'
508 // Identifier ':' Statement 515 // Identifier ':' Statement
509 516
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
725 // ForStatement :: 732 // ForStatement ::
726 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement 733 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
727 734
728 Expect(Token::FOR, CHECK_OK); 735 Expect(Token::FOR, CHECK_OK);
729 Expect(Token::LPAREN, CHECK_OK); 736 Expect(Token::LPAREN, CHECK_OK);
730 bool is_let_identifier_expression = false; 737 bool is_let_identifier_expression = false;
731 if (peek() != Token::SEMICOLON) { 738 if (peek() != Token::SEMICOLON) {
732 ForEachStatement::VisitMode mode; 739 ForEachStatement::VisitMode mode;
733 if (peek() == Token::VAR || peek() == Token::CONST || 740 if (peek() == Token::VAR || peek() == Token::CONST ||
734 (peek() == Token::LET && is_strict(language_mode()))) { 741 (peek() == Token::LET && is_strict(language_mode()))) {
735 bool is_lexical = peek() == Token::LET ||
736 (peek() == Token::CONST && is_strict(language_mode()));
737 int decl_count; 742 int decl_count;
738 Scanner::Location first_initializer_loc = Scanner::Location::invalid(); 743 Scanner::Location first_initializer_loc = Scanner::Location::invalid();
744 Scanner::Location bindings_loc = Scanner::Location::invalid();
739 ParseVariableDeclarations(kForStatement, &decl_count, 745 ParseVariableDeclarations(kForStatement, &decl_count,
740 &first_initializer_loc, CHECK_OK); 746 &first_initializer_loc, &bindings_loc,
741 bool has_initializers = first_initializer_loc.IsValid(); 747 CHECK_OK);
742 bool accept_IN = decl_count == 1 && !(is_lexical && has_initializers); 748 bool accept_IN = decl_count >= 1;
743 bool accept_OF = true; 749 bool accept_OF = true;
744 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) { 750 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) {
745 if (!*ok) return Statement::Default(); 751 if (!*ok) return Statement::Default();
752 if (decl_count != 1) {
753 const char* loop_type =
754 mode == ForEachStatement::ITERATE ? "for-of" : "for-in";
755 PreParserTraits::ReportMessageAt(
756 bindings_loc, "for_inof_loop_multi_bindings", loop_type);
757 *ok = false;
758 return Statement::Default();
759 }
746 if (first_initializer_loc.IsValid() && 760 if (first_initializer_loc.IsValid() &&
747 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) { 761 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) {
748 if (mode == ForEachStatement::ITERATE) { 762 if (mode == ForEachStatement::ITERATE) {
749 ReportMessageAt(first_initializer_loc, "for_of_loop_initializer"); 763 ReportMessageAt(first_initializer_loc, "for_of_loop_initializer");
750 } else { 764 } else {
751 // TODO(caitp): This should be an error in sloppy mode, too. 765 // TODO(caitp): This should be an error in sloppy mode, too.
752 ReportMessageAt(first_initializer_loc, "for_in_loop_initializer"); 766 ReportMessageAt(first_initializer_loc, "for_in_loop_initializer");
753 } 767 }
754 *ok = false; 768 *ok = false;
755 return Statement::Default(); 769 return Statement::Default();
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
1057 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); 1071 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
1058 ParseArguments(ok); 1072 ParseArguments(ok);
1059 1073
1060 return Expression::Default(); 1074 return Expression::Default();
1061 } 1075 }
1062 1076
1063 #undef CHECK_OK 1077 #undef CHECK_OK
1064 1078
1065 1079
1066 } } // v8::internal 1080 } } // v8::internal
OLDNEW
« src/parser.cc ('K') | « src/preparser.h ('k') | test/cctest/test-parsing.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698