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