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

Side by Side Diff: src/parsing/preparser.cc

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 unified diff | Download patch
« no previous file with comments | « src/parsing/preparser.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 405 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 return final; 416 return final;
417 } 417 }
418 418
419 419
420 PreParser::Statement PreParser::ParseVariableStatement( 420 PreParser::Statement PreParser::ParseVariableStatement(
421 VariableDeclarationContext var_context, 421 VariableDeclarationContext var_context,
422 bool* ok) { 422 bool* ok) {
423 // VariableStatement :: 423 // VariableStatement ::
424 // VariableDeclarations ';' 424 // VariableDeclarations ';'
425 425
426 Statement result = ParseVariableDeclarations( 426 Statement result =
427 var_context, nullptr, nullptr, nullptr, nullptr, nullptr, CHECK_OK); 427 ParseVariableDeclarations(var_context, nullptr, nullptr, CHECK_OK);
428 ExpectSemicolon(CHECK_OK); 428 ExpectSemicolon(CHECK_OK);
429 return result; 429 return result;
430 } 430 }
431 431
432
433 // If the variable declaration declares exactly one non-const
434 // variable, then *var is set to that variable. In all other cases,
435 // *var is untouched; in particular, it is the caller's responsibility
436 // to initialize it properly. This mechanism is also used for the parsing
437 // of 'for-in' loops.
438 PreParser::Statement PreParser::ParseVariableDeclarations(
439 VariableDeclarationContext var_context, int* num_decl, bool* is_lexical,
440 bool* is_binding_pattern, Scanner::Location* first_initializer_loc,
441 Scanner::Location* bindings_loc, bool* ok) {
442 // VariableDeclarations ::
443 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
444 //
445 // The ES6 Draft Rev3 specifies the following grammar for const declarations
446 //
447 // ConstDeclaration ::
448 // const ConstBinding (',' ConstBinding)* ';'
449 // ConstBinding ::
450 // Identifier '=' AssignmentExpression
451 //
452 // TODO(ES6):
453 // ConstBinding ::
454 // BindingPattern '=' AssignmentExpression
455 bool require_initializer = false;
456 bool lexical = false;
457 bool is_pattern = false;
458 if (peek() == Token::VAR) {
459 Consume(Token::VAR);
460 } else if (peek() == Token::CONST) {
461 // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads:
462 //
463 // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';'
464 //
465 // * It is a Syntax Error if the code that matches this production is not
466 // contained in extended code.
467 //
468 // However disallowing const in sloppy mode will break compatibility with
469 // existing pages. Therefore we keep allowing const with the old
470 // non-harmony semantics in sloppy mode.
471 Consume(Token::CONST);
472 DCHECK(var_context != kStatement);
473 require_initializer = true;
474 lexical = true;
475 } else if (peek() == Token::LET) {
476 Consume(Token::LET);
477 DCHECK(var_context != kStatement);
478 lexical = true;
479 } else {
480 *ok = false;
481 return Statement::Default();
482 }
483
484 // The scope of a var/const declared variable anywhere inside a function
485 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope
486 // of a let declared variable is the scope of the immediately enclosing
487 // block.
488 int nvars = 0; // the number of variables declared
489 int bindings_start = peek_position();
490 do {
491 // Parse binding pattern.
492 if (nvars > 0) Consume(Token::COMMA);
493 int decl_pos = peek_position();
494 PreParserExpression pattern = PreParserExpression::Default();
495 {
496 ExpressionClassifier pattern_classifier(this);
497 pattern = ParsePrimaryExpression(CHECK_OK);
498
499 ValidateBindingPattern(CHECK_OK);
500 if (lexical) ValidateLetPattern(CHECK_OK);
501 }
502
503 is_pattern = pattern.IsObjectLiteral() || pattern.IsArrayLiteral();
504
505 Scanner::Location variable_loc = scanner()->location();
506 nvars++;
507 if (Check(Token::ASSIGN)) {
508 ExpressionClassifier classifier(this);
509 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
510 ValidateExpression(CHECK_OK);
511
512 variable_loc.end_pos = scanner()->location().end_pos;
513 if (first_initializer_loc && !first_initializer_loc->IsValid()) {
514 *first_initializer_loc = variable_loc;
515 }
516 } else if ((require_initializer || is_pattern) &&
517 (var_context != kForStatement || !PeekInOrOf())) {
518 ReportMessageAt(
519 Scanner::Location(decl_pos, scanner()->location().end_pos),
520 MessageTemplate::kDeclarationMissingInitializer,
521 is_pattern ? "destructuring" : "const");
522 *ok = false;
523 return Statement::Default();
524 }
525 } while (peek() == Token::COMMA);
526
527 if (bindings_loc) {
528 *bindings_loc =
529 Scanner::Location(bindings_start, scanner()->location().end_pos);
530 }
531
532 if (num_decl != nullptr) *num_decl = nvars;
533 if (is_lexical != nullptr) *is_lexical = lexical;
534 if (is_binding_pattern != nullptr) *is_binding_pattern = is_pattern;
535 return Statement::Default();
536 }
537
538 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { 432 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
539 Consume(Token::FUNCTION); 433 Consume(Token::FUNCTION);
540 int pos = position(); 434 int pos = position();
541 ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal; 435 ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal;
542 if (Check(Token::MUL)) { 436 if (Check(Token::MUL)) {
543 flags |= ParseFunctionFlags::kIsGenerator; 437 flags |= ParseFunctionFlags::kIsGenerator;
544 if (allow_harmony_restrictive_declarations()) { 438 if (allow_harmony_restrictive_declarations()) {
545 ReportMessageAt(scanner()->location(), 439 ReportMessageAt(scanner()->location(),
546 MessageTemplate::kGeneratorInLegacyContext); 440 MessageTemplate::kGeneratorInLegacyContext);
547 *ok = false; 441 *ok = false;
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
791 // Create an in-between scope for let-bound iteration variables. 685 // Create an in-between scope for let-bound iteration variables.
792 bool has_lexical = false; 686 bool has_lexical = false;
793 687
794 BlockState block_state(&scope_state_); 688 BlockState block_state(&scope_state_);
795 Expect(Token::FOR, CHECK_OK); 689 Expect(Token::FOR, CHECK_OK);
796 Expect(Token::LPAREN, CHECK_OK); 690 Expect(Token::LPAREN, CHECK_OK);
797 if (peek() != Token::SEMICOLON) { 691 if (peek() != Token::SEMICOLON) {
798 ForEachStatement::VisitMode mode; 692 ForEachStatement::VisitMode mode;
799 if (peek() == Token::VAR || peek() == Token::CONST || 693 if (peek() == Token::VAR || peek() == Token::CONST ||
800 (peek() == Token::LET && IsNextLetKeyword())) { 694 (peek() == Token::LET && IsNextLetKeyword())) {
801 int decl_count; 695 DeclarationParsingResult parsing_result;
802 bool is_lexical; 696
803 bool is_binding_pattern; 697 ParseVariableDeclarations(kForStatement, &parsing_result, nullptr,
804 Scanner::Location first_initializer_loc = Scanner::Location::invalid(); 698 CHECK_OK);
805 Scanner::Location bindings_loc = Scanner::Location::invalid(); 699 if (parsing_result.descriptor.mode == CONST ||
806 ParseVariableDeclarations(kForStatement, &decl_count, &is_lexical, 700 parsing_result.descriptor.mode == LET) {
807 &is_binding_pattern, &first_initializer_loc, 701 has_lexical = true;
808 &bindings_loc, CHECK_OK); 702 }
809 if (is_lexical) has_lexical = true;
810 if (CheckInOrOf(&mode)) { 703 if (CheckInOrOf(&mode)) {
811 if (decl_count != 1) { 704 if (!*ok) return Statement::Default();
812 ReportMessageAt(bindings_loc, 705 if (parsing_result.declarations.length() != 1) {
706 ReportMessageAt(parsing_result.bindings_loc,
813 MessageTemplate::kForInOfLoopMultiBindings, 707 MessageTemplate::kForInOfLoopMultiBindings,
814 ForEachStatement::VisitModeString(mode)); 708 ForEachStatement::VisitModeString(mode));
815 *ok = false; 709 *ok = false;
816 return Statement::Default(); 710 return Statement::Default();
817 } 711 }
818 if (first_initializer_loc.IsValid() && 712 bool is_binding_pattern =
713 parsing_result.declarations[0].pattern.IsObjectLiteral() ||
714 parsing_result.declarations[0].pattern.IsArrayLiteral();
715 if (parsing_result.first_initializer_loc.IsValid() &&
819 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE || 716 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE ||
820 is_lexical || is_binding_pattern || allow_harmony_for_in())) { 717 has_lexical || is_binding_pattern || allow_harmony_for_in())) {
821 // Only increment the use count if we would have let this through 718 // Only increment the use count if we would have let this through
822 // without the flag. 719 // without the flag.
823 if (use_counts_ != nullptr && allow_harmony_for_in()) { 720 if (use_counts_ != nullptr && allow_harmony_for_in()) {
824 ++use_counts_[v8::Isolate::kForInInitializer]; 721 ++use_counts_[v8::Isolate::kForInInitializer];
825 } 722 }
826 ReportMessageAt(first_initializer_loc, 723 ReportMessageAt(parsing_result.first_initializer_loc,
827 MessageTemplate::kForInOfLoopInitializer, 724 MessageTemplate::kForInOfLoopInitializer,
828 ForEachStatement::VisitModeString(mode)); 725 ForEachStatement::VisitModeString(mode));
829 *ok = false; 726 *ok = false;
830 return Statement::Default(); 727 return Statement::Default();
831 } 728 }
832 729
833 if (mode == ForEachStatement::ITERATE) { 730 if (mode == ForEachStatement::ITERATE) {
834 ExpressionClassifier classifier(this); 731 ExpressionClassifier classifier(this);
835 ParseAssignmentExpression(true, CHECK_OK); 732 ParseAssignmentExpression(true, CHECK_OK);
836 RewriteNonPattern(CHECK_OK); 733 RewriteNonPattern(CHECK_OK);
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
1219 1116
1220 body->Add(PreParserStatement::ExpressionStatement(return_value), zone()); 1117 body->Add(PreParserStatement::ExpressionStatement(return_value), zone());
1221 } 1118 }
1222 1119
1223 #undef CHECK_OK 1120 #undef CHECK_OK
1224 #undef CHECK_OK_CUSTOM 1121 #undef CHECK_OK_CUSTOM
1225 1122
1226 1123
1227 } // namespace internal 1124 } // namespace internal
1228 } // namespace v8 1125 } // namespace v8
OLDNEW
« no previous file with comments | « src/parsing/preparser.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698