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

Side by Side Diff: src/parser.cc

Issue 378303003: Make `let` usable as an identifier in ES6 sloppy mode. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 5 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/ast.h" 8 #include "src/ast.h"
9 #include "src/base/platform/platform.h" 9 #include "src/base/platform/platform.h"
10 #include "src/bootstrapper.h" 10 #include "src/bootstrapper.h"
(...skipping 1140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1151 // LetDeclaration 1151 // LetDeclaration
1152 // ConstDeclaration 1152 // ConstDeclaration
1153 // ModuleDeclaration 1153 // ModuleDeclaration
1154 // ImportDeclaration 1154 // ImportDeclaration
1155 // ExportDeclaration 1155 // ExportDeclaration
1156 // GeneratorDeclaration 1156 // GeneratorDeclaration
1157 1157
1158 switch (peek()) { 1158 switch (peek()) {
1159 case Token::FUNCTION: 1159 case Token::FUNCTION:
1160 return ParseFunctionDeclaration(NULL, ok); 1160 return ParseFunctionDeclaration(NULL, ok);
1161 case Token::LET:
1162 case Token::CONST:
1163 return ParseVariableStatement(kModuleElement, NULL, ok);
1164 case Token::IMPORT: 1161 case Token::IMPORT:
1165 return ParseImportDeclaration(ok); 1162 return ParseImportDeclaration(ok);
1166 case Token::EXPORT: 1163 case Token::EXPORT:
1167 return ParseExportDeclaration(ok); 1164 return ParseExportDeclaration(ok);
1165 case Token::CONST:
1166 return ParseVariableStatement(kModuleElement, NULL, ok);
1167 case Token::LET:
1168 if (allow_harmony_scoping() && strict_mode() == STRICT) {
marja 2014/07/09 14:24:45 (See below; isn't allow_harmony_scoping() necessar
1169 return ParseVariableStatement(kModuleElement, NULL, ok);
1170 }
1171 // Fall through.
1168 default: { 1172 default: {
1169 Statement* stmt = ParseStatement(labels, CHECK_OK); 1173 Statement* stmt = ParseStatement(labels, CHECK_OK);
1170 // Handle 'module' as a context-sensitive keyword. 1174 // Handle 'module' as a context-sensitive keyword.
1171 if (FLAG_harmony_modules && 1175 if (FLAG_harmony_modules &&
1172 peek() == Token::IDENTIFIER && 1176 peek() == Token::IDENTIFIER &&
1173 !scanner()->HasAnyLineTerminatorBeforeNext() && 1177 !scanner()->HasAnyLineTerminatorBeforeNext() &&
1174 stmt != NULL) { 1178 stmt != NULL) {
1175 ExpressionStatement* estmt = stmt->AsExpressionStatement(); 1179 ExpressionStatement* estmt = stmt->AsExpressionStatement();
1176 if (estmt != NULL && estmt->expression()->AsVariableProxy() != NULL && 1180 if (estmt != NULL && estmt->expression()->AsVariableProxy() != NULL &&
1177 estmt->expression()->AsVariableProxy()->raw_name() == 1181 estmt->expression()->AsVariableProxy()->raw_name() ==
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
1456 Statement* Parser::ParseExportDeclaration(bool* ok) { 1460 Statement* Parser::ParseExportDeclaration(bool* ok) {
1457 // ExportDeclaration: 1461 // ExportDeclaration:
1458 // 'export' Identifier (',' Identifier)* ';' 1462 // 'export' Identifier (',' Identifier)* ';'
1459 // 'export' VariableDeclaration 1463 // 'export' VariableDeclaration
1460 // 'export' FunctionDeclaration 1464 // 'export' FunctionDeclaration
1461 // 'export' GeneratorDeclaration 1465 // 'export' GeneratorDeclaration
1462 // 'export' ModuleDeclaration 1466 // 'export' ModuleDeclaration
1463 // 1467 //
1464 // TODO(ES6): implement structuring ExportSpecifiers 1468 // TODO(ES6): implement structuring ExportSpecifiers
1465 1469
1470 ASSERT(strict_mode() == STRICT);
1471
1466 Expect(Token::EXPORT, CHECK_OK); 1472 Expect(Token::EXPORT, CHECK_OK);
1467 1473
1468 Statement* result = NULL; 1474 Statement* result = NULL;
1469 ZoneList<const AstRawString*> names(1, zone()); 1475 ZoneList<const AstRawString*> names(1, zone());
1470 switch (peek()) { 1476 switch (peek()) {
1471 case Token::IDENTIFIER: { 1477 case Token::IDENTIFIER: {
1472 int pos = position(); 1478 int pos = position();
1473 const AstRawString* name = 1479 const AstRawString* name =
1474 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); 1480 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
1475 // Handle 'module' as a context-sensitive keyword. 1481 // Handle 'module' as a context-sensitive keyword.
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1538 // 1544 //
1539 // In harmony mode we allow additionally the following productions 1545 // In harmony mode we allow additionally the following productions
1540 // BlockElement (aka SourceElement): 1546 // BlockElement (aka SourceElement):
1541 // LetDeclaration 1547 // LetDeclaration
1542 // ConstDeclaration 1548 // ConstDeclaration
1543 // GeneratorDeclaration 1549 // GeneratorDeclaration
1544 1550
1545 switch (peek()) { 1551 switch (peek()) {
1546 case Token::FUNCTION: 1552 case Token::FUNCTION:
1547 return ParseFunctionDeclaration(NULL, ok); 1553 return ParseFunctionDeclaration(NULL, ok);
1548 case Token::LET:
1549 case Token::CONST: 1554 case Token::CONST:
1550 return ParseVariableStatement(kModuleElement, NULL, ok); 1555 return ParseVariableStatement(kModuleElement, NULL, ok);
1556 case Token::LET:
1557 if (allow_harmony_scoping() && strict_mode() == STRICT) {
marja 2014/07/09 14:24:45 Ditto
1558 return ParseVariableStatement(kModuleElement, NULL, ok);
1559 }
1560 // Fall through.
1551 default: 1561 default:
1552 return ParseStatement(labels, ok); 1562 return ParseStatement(labels, ok);
1553 } 1563 }
1554 } 1564 }
1555 1565
1556 1566
1557 Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels, 1567 Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels,
1558 bool* ok) { 1568 bool* ok) {
1559 // Statement :: 1569 // Statement ::
1560 // Block 1570 // Block
(...skipping 15 matching lines...) Expand all
1576 // Note: Since labels can only be used by 'break' and 'continue' 1586 // Note: Since labels can only be used by 'break' and 'continue'
1577 // statements, which themselves are only valid within blocks, 1587 // statements, which themselves are only valid within blocks,
1578 // iterations or 'switch' statements (i.e., BreakableStatements), 1588 // iterations or 'switch' statements (i.e., BreakableStatements),
1579 // labels can be simply ignored in all other cases; except for 1589 // labels can be simply ignored in all other cases; except for
1580 // trivial labeled break statements 'label: break label' which is 1590 // trivial labeled break statements 'label: break label' which is
1581 // parsed into an empty statement. 1591 // parsed into an empty statement.
1582 switch (peek()) { 1592 switch (peek()) {
1583 case Token::LBRACE: 1593 case Token::LBRACE:
1584 return ParseBlock(labels, ok); 1594 return ParseBlock(labels, ok);
1585 1595
1586 case Token::CONST: // fall through
1587 case Token::LET:
1588 case Token::VAR:
1589 return ParseVariableStatement(kStatement, NULL, ok);
1590
1591 case Token::SEMICOLON: 1596 case Token::SEMICOLON:
1592 Next(); 1597 Next();
1593 return factory()->NewEmptyStatement(RelocInfo::kNoPosition); 1598 return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
1594 1599
1595 case Token::IF: 1600 case Token::IF:
1596 return ParseIfStatement(labels, ok); 1601 return ParseIfStatement(labels, ok);
1597 1602
1598 case Token::DO: 1603 case Token::DO:
1599 return ParseDoWhileStatement(labels, ok); 1604 return ParseDoWhileStatement(labels, ok);
1600 1605
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1652 ReportMessageAt(scanner()->peek_location(), "strict_function"); 1657 ReportMessageAt(scanner()->peek_location(), "strict_function");
1653 *ok = false; 1658 *ok = false;
1654 return NULL; 1659 return NULL;
1655 } 1660 }
1656 return ParseFunctionDeclaration(NULL, ok); 1661 return ParseFunctionDeclaration(NULL, ok);
1657 } 1662 }
1658 1663
1659 case Token::DEBUGGER: 1664 case Token::DEBUGGER:
1660 return ParseDebuggerStatement(ok); 1665 return ParseDebuggerStatement(ok);
1661 1666
1667 case Token::VAR:
1668 case Token::CONST:
1669 return ParseVariableStatement(kStatement, NULL, ok);
1670
1671 case Token::LET:
1672 if (allow_harmony_scoping() && strict_mode() == STRICT) {
marja 2014/07/09 14:24:45 I don't think we need to check allow_harmony_scopi
rossberg 2014/07/09 14:28:50 Yes, this was on purpose -- I wanted to be able to
1673 return ParseVariableStatement(kStatement, NULL, ok);
1674 }
1675 // Fall through.
1662 default: 1676 default:
1663 return ParseExpressionOrLabelledStatement(labels, ok); 1677 return ParseExpressionOrLabelledStatement(labels, ok);
1664 } 1678 }
1665 } 1679 }
1666 1680
1667 1681
1668 VariableProxy* Parser::NewUnresolved(const AstRawString* name, 1682 VariableProxy* Parser::NewUnresolved(const AstRawString* name,
1669 VariableMode mode, Interface* interface) { 1683 VariableMode mode, Interface* interface) {
1670 // If we are inside a function, a declaration of a var/const variable is a 1684 // If we are inside a function, a declaration of a var/const variable is a
1671 // truly local variable, and the scope of the variable is always the function 1685 // truly local variable, and the scope of the variable is always the function
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after
2055 mode = CONST; 2069 mode = CONST;
2056 init_op = Token::INIT_CONST; 2070 init_op = Token::INIT_CONST;
2057 } else { 2071 } else {
2058 ReportMessage("strict_const"); 2072 ReportMessage("strict_const");
2059 *ok = false; 2073 *ok = false;
2060 return NULL; 2074 return NULL;
2061 } 2075 }
2062 } 2076 }
2063 is_const = true; 2077 is_const = true;
2064 needs_init = true; 2078 needs_init = true;
2065 } else if (peek() == Token::LET) { 2079 } else if (peek() == Token::LET && strict_mode() == STRICT) {
2066 // ES6 Draft Rev4 section 12.2.1:
2067 //
2068 // LetDeclaration : let LetBindingList ;
2069 //
2070 // * It is a Syntax Error if the code that matches this production is not
2071 // contained in extended code.
2072 //
2073 // TODO(rossberg): make 'let' a legal identifier in sloppy mode.
2074 if (!allow_harmony_scoping() || strict_mode() == SLOPPY) {
2075 ReportMessage("illegal_let");
2076 *ok = false;
2077 return NULL;
2078 }
2079 Consume(Token::LET); 2080 Consume(Token::LET);
2080 if (var_context == kStatement) { 2081 if (var_context == kStatement) {
2081 // Let declarations are only allowed in source element positions. 2082 // Let declarations are only allowed in source element positions.
2082 ReportMessage("unprotected_let"); 2083 ReportMessage("unprotected_let");
2083 *ok = false; 2084 *ok = false;
2084 return NULL; 2085 return NULL;
2085 } 2086 }
2086 mode = LET; 2087 mode = LET;
2087 needs_init = true; 2088 needs_init = true;
2088 init_op = Token::INIT_LET; 2089 init_op = Token::INIT_LET;
(...skipping 1018 matching lines...) Expand 10 before | Expand all | Expand 10 after
3107 result->AddStatement(loop, zone()); 3108 result->AddStatement(loop, zone());
3108 scope_ = saved_scope; 3109 scope_ = saved_scope;
3109 for_scope->set_end_position(scanner()->location().end_pos); 3110 for_scope->set_end_position(scanner()->location().end_pos);
3110 for_scope = for_scope->FinalizeBlockScope(); 3111 for_scope = for_scope->FinalizeBlockScope();
3111 ASSERT(for_scope == NULL); 3112 ASSERT(for_scope == NULL);
3112 // Parsed for-in loop w/ variable/const declaration. 3113 // Parsed for-in loop w/ variable/const declaration.
3113 return result; 3114 return result;
3114 } else { 3115 } else {
3115 init = variable_statement; 3116 init = variable_statement;
3116 } 3117 }
3117 } else if (peek() == Token::LET) { 3118 } else if (peek() == Token::LET && strict_mode() == STRICT) {
3118 const AstRawString* name = NULL; 3119 const AstRawString* name = NULL;
3119 VariableDeclarationProperties decl_props = kHasNoInitializers; 3120 VariableDeclarationProperties decl_props = kHasNoInitializers;
3120 Block* variable_statement = 3121 Block* variable_statement =
3121 ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings, 3122 ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings,
3122 &name, CHECK_OK); 3123 &name, CHECK_OK);
3123 bool accept_IN = name != NULL && decl_props != kHasInitializers; 3124 bool accept_IN = name != NULL && decl_props != kHasInitializers;
3124 bool accept_OF = decl_props == kHasNoInitializers; 3125 bool accept_OF = decl_props == kHasNoInitializers;
3125 ForEachStatement::VisitMode mode; 3126 ForEachStatement::VisitMode mode;
3126 3127
3127 if (accept_IN && CheckInOrOf(accept_OF, &mode)) { 3128 if (accept_IN && CheckInOrOf(accept_OF, &mode)) {
(...skipping 1758 matching lines...) Expand 10 before | Expand all | Expand 10 after
4886 info()->SetAstValueFactory(ast_value_factory_); 4887 info()->SetAstValueFactory(ast_value_factory_);
4887 } 4888 }
4888 ast_value_factory_ = NULL; 4889 ast_value_factory_ = NULL;
4889 4890
4890 InternalizeUseCounts(); 4891 InternalizeUseCounts();
4891 4892
4892 return (result != NULL); 4893 return (result != NULL);
4893 } 4894 }
4894 4895
4895 } } // namespace v8::internal 4896 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/messages.js ('k') | src/preparser.h » ('j') | src/preparser.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698