OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |