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 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 // | 402 // |
403 // ConstDeclaration :: | 403 // ConstDeclaration :: |
404 // const ConstBinding (',' ConstBinding)* ';' | 404 // const ConstBinding (',' ConstBinding)* ';' |
405 // ConstBinding :: | 405 // ConstBinding :: |
406 // Identifier '=' AssignmentExpression | 406 // Identifier '=' AssignmentExpression |
407 // | 407 // |
408 // TODO(ES6): | 408 // TODO(ES6): |
409 // ConstBinding :: | 409 // ConstBinding :: |
410 // BindingPattern '=' AssignmentExpression | 410 // BindingPattern '=' AssignmentExpression |
411 bool require_initializer = false; | 411 bool require_initializer = false; |
412 bool is_strict_const = false; | |
413 if (peek() == Token::VAR) { | 412 if (peek() == Token::VAR) { |
414 Consume(Token::VAR); | 413 Consume(Token::VAR); |
415 } else if (peek() == Token::CONST) { | 414 } else if (peek() == Token::CONST) { |
416 // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads: | 415 // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads: |
417 // | 416 // |
418 // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';' | 417 // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';' |
419 // | 418 // |
420 // * It is a Syntax Error if the code that matches this production is not | 419 // * It is a Syntax Error if the code that matches this production is not |
421 // contained in extended code. | 420 // contained in extended code. |
422 // | 421 // |
423 // However disallowing const in sloppy mode will break compatibility with | 422 // However disallowing const in sloppy mode will break compatibility with |
424 // existing pages. Therefore we keep allowing const with the old | 423 // existing pages. Therefore we keep allowing const with the old |
425 // non-harmony semantics in sloppy mode. | 424 // non-harmony semantics in sloppy mode. |
426 Consume(Token::CONST); | 425 Consume(Token::CONST); |
427 if (strict_mode() == STRICT) { | 426 if (strict_mode() == STRICT) { |
428 if (allow_harmony_scoping()) { | 427 if (allow_harmony_scoping()) { |
429 if (var_context != kSourceElement && var_context != kForStatement) { | 428 if (var_context != kSourceElement && var_context != kForStatement) { |
430 ReportMessageAt(scanner()->peek_location(), "unprotected_const"); | 429 ReportMessageAt(scanner()->peek_location(), "unprotected_const"); |
431 *ok = false; | 430 *ok = false; |
432 return Statement::Default(); | 431 return Statement::Default(); |
433 } | 432 } |
434 is_strict_const = true; | 433 require_initializer = true; |
435 require_initializer = var_context != kForStatement; | |
436 } else { | 434 } else { |
437 Scanner::Location location = scanner()->peek_location(); | 435 Scanner::Location location = scanner()->peek_location(); |
438 ReportMessageAt(location, "strict_const"); | 436 ReportMessageAt(location, "strict_const"); |
439 *ok = false; | 437 *ok = false; |
440 return Statement::Default(); | 438 return Statement::Default(); |
441 } | 439 } |
442 } | 440 } |
443 } else if (peek() == Token::LET && strict_mode() == STRICT) { | 441 } else if (peek() == Token::LET && strict_mode() == STRICT) { |
444 Consume(Token::LET); | 442 Consume(Token::LET); |
445 if (var_context != kSourceElement && var_context != kForStatement) { | 443 if (var_context != kSourceElement && var_context != kForStatement) { |
446 ReportMessageAt(scanner()->peek_location(), "unprotected_let"); | 444 ReportMessageAt(scanner()->peek_location(), "unprotected_let"); |
447 *ok = false; | 445 *ok = false; |
448 return Statement::Default(); | 446 return Statement::Default(); |
449 } | 447 } |
450 } else { | 448 } else { |
451 *ok = false; | 449 *ok = false; |
452 return Statement::Default(); | 450 return Statement::Default(); |
453 } | 451 } |
454 | 452 |
455 // The scope of a var/const declared variable anywhere inside a function | 453 // The scope of a var/const declared variable anywhere inside a function |
456 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope | 454 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope |
457 // of a let declared variable is the scope of the immediately enclosing | 455 // of a let declared variable is the scope of the immediately enclosing |
458 // block. | 456 // block. |
459 int nvars = 0; // the number of variables declared | 457 int nvars = 0; // the number of variables declared |
460 do { | 458 do { |
461 // Parse variable name. | 459 // Parse variable name. |
462 if (nvars > 0) Consume(Token::COMMA); | 460 if (nvars > 0) Consume(Token::COMMA); |
463 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); | 461 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
464 nvars++; | 462 nvars++; |
465 if (peek() == Token::ASSIGN || require_initializer || | 463 if (peek() == Token::ASSIGN || require_initializer) { |
466 // require initializers for multiple consts. | |
467 (is_strict_const && peek() == Token::COMMA)) { | |
468 Expect(Token::ASSIGN, CHECK_OK); | 464 Expect(Token::ASSIGN, CHECK_OK); |
469 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); | 465 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); |
470 if (decl_props != NULL) *decl_props = kHasInitializers; | 466 if (decl_props != NULL) *decl_props = kHasInitializers; |
471 } | 467 } |
472 } while (peek() == Token::COMMA); | 468 } while (peek() == Token::COMMA); |
473 | 469 |
474 if (num_decl != NULL) *num_decl = nvars; | 470 if (num_decl != NULL) *num_decl = nvars; |
475 return Statement::Default(); | 471 return Statement::Default(); |
476 } | 472 } |
477 | 473 |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 | 671 |
676 PreParser::Statement PreParser::ParseForStatement(bool* ok) { | 672 PreParser::Statement PreParser::ParseForStatement(bool* ok) { |
677 // ForStatement :: | 673 // ForStatement :: |
678 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | 674 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
679 | 675 |
680 Expect(Token::FOR, CHECK_OK); | 676 Expect(Token::FOR, CHECK_OK); |
681 Expect(Token::LPAREN, CHECK_OK); | 677 Expect(Token::LPAREN, CHECK_OK); |
682 if (peek() != Token::SEMICOLON) { | 678 if (peek() != Token::SEMICOLON) { |
683 if (peek() == Token::VAR || peek() == Token::CONST || | 679 if (peek() == Token::VAR || peek() == Token::CONST || |
684 (peek() == Token::LET && strict_mode() == STRICT)) { | 680 (peek() == Token::LET && strict_mode() == STRICT)) { |
685 bool is_lexical = peek() == Token::LET || | 681 bool is_let = peek() == Token::LET; |
686 (peek() == Token::CONST && strict_mode() == STRICT); | |
687 int decl_count; | 682 int decl_count; |
688 VariableDeclarationProperties decl_props = kHasNoInitializers; | 683 VariableDeclarationProperties decl_props = kHasNoInitializers; |
689 ParseVariableDeclarations( | 684 ParseVariableDeclarations( |
690 kForStatement, &decl_props, &decl_count, CHECK_OK); | 685 kForStatement, &decl_props, &decl_count, CHECK_OK); |
691 bool has_initializers = decl_props == kHasInitializers; | 686 bool has_initializers = decl_props == kHasInitializers; |
692 bool accept_IN = decl_count == 1 && !(is_lexical && has_initializers); | 687 bool accept_IN = decl_count == 1 && !(is_let && has_initializers); |
693 bool accept_OF = !has_initializers; | 688 bool accept_OF = !has_initializers; |
694 if (accept_IN && CheckInOrOf(accept_OF)) { | 689 if (accept_IN && CheckInOrOf(accept_OF)) { |
695 ParseExpression(true, CHECK_OK); | 690 ParseExpression(true, CHECK_OK); |
696 Expect(Token::RPAREN, CHECK_OK); | 691 Expect(Token::RPAREN, CHECK_OK); |
697 | 692 |
698 ParseStatement(CHECK_OK); | 693 ParseStatement(CHECK_OK); |
699 return Statement::Default(); | 694 return Statement::Default(); |
700 } | 695 } |
701 } else { | 696 } else { |
702 Expression lhs = ParseExpression(false, CHECK_OK); | 697 Expression lhs = ParseExpression(false, CHECK_OK); |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
939 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); | 934 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
940 ParseArguments(ok); | 935 ParseArguments(ok); |
941 | 936 |
942 return Expression::Default(); | 937 return Expression::Default(); |
943 } | 938 } |
944 | 939 |
945 #undef CHECK_OK | 940 #undef CHECK_OK |
946 | 941 |
947 | 942 |
948 } } // v8::internal | 943 } } // v8::internal |
OLD | NEW |