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 #ifndef V8_PARSING_PARSER_BASE_H | 5 #ifndef V8_PARSING_PARSER_BASE_H |
6 #define V8_PARSING_PARSER_BASE_H | 6 #define V8_PARSING_PARSER_BASE_H |
7 | 7 |
8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
9 #include "src/bailout-reason.h" | 9 #include "src/bailout-reason.h" |
10 #include "src/hashmap.h" | 10 #include "src/hashmap.h" |
(...skipping 794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
805 // Checks if the expression is a valid reference expression (e.g., on the | 805 // Checks if the expression is a valid reference expression (e.g., on the |
806 // left-hand side of assignments). Although ruled out by ECMA as early errors, | 806 // left-hand side of assignments). Although ruled out by ECMA as early errors, |
807 // we allow calls for web compatibility and rewrite them to a runtime throw. | 807 // we allow calls for web compatibility and rewrite them to a runtime throw. |
808 ExpressionT CheckAndRewriteReferenceExpression( | 808 ExpressionT CheckAndRewriteReferenceExpression( |
809 ExpressionT expression, int beg_pos, int end_pos, | 809 ExpressionT expression, int beg_pos, int end_pos, |
810 MessageTemplate::Template message, bool* ok); | 810 MessageTemplate::Template message, bool* ok); |
811 ExpressionT ClassifyAndRewriteReferenceExpression( | 811 ExpressionT ClassifyAndRewriteReferenceExpression( |
812 ExpressionClassifier* classifier, ExpressionT expression, int beg_pos, | 812 ExpressionClassifier* classifier, ExpressionT expression, int beg_pos, |
813 int end_pos, MessageTemplate::Template message, | 813 int end_pos, MessageTemplate::Template message, |
814 ParseErrorType type = kSyntaxError); | 814 ParseErrorType type = kSyntaxError); |
815 void ClassifyReferenceExpression(ExpressionClassifier* classifier, | |
816 ExpressionT expression, int beg_pos, | |
817 int end_pos); | |
815 ExpressionT CheckAndRewriteReferenceExpression( | 818 ExpressionT CheckAndRewriteReferenceExpression( |
816 ExpressionT expression, int beg_pos, int end_pos, | 819 ExpressionT expression, int beg_pos, int end_pos, |
817 MessageTemplate::Template message, ParseErrorType type, bool* ok); | 820 MessageTemplate::Template message, ParseErrorType type, bool* ok); |
818 | 821 |
819 bool IsValidReferenceExpression(ExpressionT expression); | 822 bool IsValidReferenceExpression(ExpressionT expression); |
820 | 823 |
821 bool IsAssignableIdentifier(ExpressionT expression) { | 824 bool IsAssignableIdentifier(ExpressionT expression) { |
822 if (!Traits::IsIdentifier(expression)) return false; | 825 if (!Traits::IsIdentifier(expression)) return false; |
823 if (is_strict(language_mode()) && | 826 if (is_strict(language_mode()) && |
824 Traits::IsEvalOrArguments(Traits::AsIdentifier(expression))) { | 827 Traits::IsEvalOrArguments(Traits::AsIdentifier(expression))) { |
(...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1510 MessageTemplate::kStrongEllision); | 1513 MessageTemplate::kStrongEllision); |
1511 *ok = false; | 1514 *ok = false; |
1512 return this->EmptyExpression(); | 1515 return this->EmptyExpression(); |
1513 } | 1516 } |
1514 elem = this->GetLiteralTheHole(peek_position(), factory()); | 1517 elem = this->GetLiteralTheHole(peek_position(), factory()); |
1515 } else if (peek() == Token::ELLIPSIS) { | 1518 } else if (peek() == Token::ELLIPSIS) { |
1516 int start_pos = peek_position(); | 1519 int start_pos = peek_position(); |
1517 Consume(Token::ELLIPSIS); | 1520 Consume(Token::ELLIPSIS); |
1518 ExpressionT argument = | 1521 ExpressionT argument = |
1519 this->ParseAssignmentExpression(true, classifier, CHECK_OK); | 1522 this->ParseAssignmentExpression(true, classifier, CHECK_OK); |
1523 ClassifyReferenceExpression(classifier, argument, start_pos, | |
1524 scanner()->location().end_pos); | |
1520 elem = factory()->NewSpread(argument, start_pos); | 1525 elem = factory()->NewSpread(argument, start_pos); |
1521 | 1526 |
1522 if (first_spread_index < 0) { | 1527 if (first_spread_index < 0) { |
1523 first_spread_index = values->length(); | 1528 first_spread_index = values->length(); |
1524 } | 1529 } |
1525 | 1530 |
1526 CheckDestructuringElement(argument, classifier, start_pos, | 1531 CheckDestructuringElement(argument, classifier, start_pos, |
adamk
2015/12/12 01:03:35
I think CheckDestructuringElement is doing the wor
caitp (gmail)
2015/12/12 01:08:14
Yes, there is some redundant stuff here --- as men
adamk
2015/12/12 01:10:44
Would much prefer less duplication to message clar
| |
1527 scanner()->location().end_pos); | 1532 scanner()->location().end_pos); |
1528 | 1533 |
1529 if (peek() == Token::COMMA) { | 1534 if (peek() == Token::COMMA) { |
1530 classifier->RecordPatternError( | 1535 classifier->RecordPatternError( |
1531 Scanner::Location(start_pos, scanner()->location().end_pos), | 1536 Scanner::Location(start_pos, scanner()->location().end_pos), |
1532 MessageTemplate::kElementAfterRest); | 1537 MessageTemplate::kElementAfterRest); |
1533 } | 1538 } |
1534 } else { | 1539 } else { |
1535 elem = this->ParseAssignmentExpression(true, kIsPatternElement, | 1540 elem = this->ParseAssignmentExpression(true, kIsPatternElement, |
1536 classifier, CHECK_OK); | 1541 classifier, CHECK_OK); |
1542 ClassifyReferenceExpression(classifier, elem, pos, | |
1543 scanner()->location().end_pos); | |
1537 if (!this->IsValidReferenceExpression(elem) && | 1544 if (!this->IsValidReferenceExpression(elem) && |
1538 !classifier->is_valid_assignment_pattern()) { | 1545 !classifier->is_valid_assignment_pattern()) { |
1539 classifier->RecordPatternError( | 1546 classifier->RecordPatternError( |
1540 Scanner::Location(pos, scanner()->location().end_pos), | 1547 Scanner::Location(pos, scanner()->location().end_pos), |
1541 MessageTemplate::kInvalidDestructuringTarget); | 1548 MessageTemplate::kInvalidDestructuringTarget); |
1542 } | 1549 } |
1543 } | 1550 } |
1544 values->Add(elem, zone_); | 1551 values->Add(elem, zone_); |
1545 if (peek() != Token::RBRACK) { | 1552 if (peek() != Token::RBRACK) { |
1546 Expect(Token::COMMA, CHECK_OK); | 1553 Expect(Token::COMMA, CHECK_OK); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1663 // PropertyName ':' AssignmentExpression | 1670 // PropertyName ':' AssignmentExpression |
1664 if (!*is_computed_name) { | 1671 if (!*is_computed_name) { |
1665 checker->CheckProperty(name_token, kValueProperty, false, false, | 1672 checker->CheckProperty(name_token, kValueProperty, false, false, |
1666 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 1673 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
1667 } | 1674 } |
1668 Consume(Token::COLON); | 1675 Consume(Token::COLON); |
1669 int pos = peek_position(); | 1676 int pos = peek_position(); |
1670 value = this->ParseAssignmentExpression( | 1677 value = this->ParseAssignmentExpression( |
1671 true, kIsPatternElement, classifier, | 1678 true, kIsPatternElement, classifier, |
1672 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 1679 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
1673 | 1680 ClassifyReferenceExpression(classifier, value, pos, |
1681 scanner()->location().end_pos); | |
1674 if (!this->IsValidReferenceExpression(value) && | 1682 if (!this->IsValidReferenceExpression(value) && |
1675 !classifier->is_valid_assignment_pattern()) { | 1683 !classifier->is_valid_assignment_pattern()) { |
1676 classifier->RecordPatternError( | 1684 classifier->RecordPatternError( |
1677 Scanner::Location(pos, scanner()->location().end_pos), | 1685 Scanner::Location(pos, scanner()->location().end_pos), |
1678 MessageTemplate::kInvalidDestructuringTarget); | 1686 MessageTemplate::kInvalidDestructuringTarget); |
1679 } | 1687 } |
1680 | 1688 |
1681 return factory()->NewObjectLiteralProperty(name_expression, value, false, | 1689 return factory()->NewObjectLiteralProperty(name_expression, value, false, |
1682 *is_computed_name); | 1690 *is_computed_name); |
1683 } | 1691 } |
(...skipping 20 matching lines...) Expand all Loading... | |
1704 classifier->RecordDuplicateFormalParameterError(scanner()->location()); | 1712 classifier->RecordDuplicateFormalParameterError(scanner()->location()); |
1705 } | 1713 } |
1706 if (name_token == Token::LET) { | 1714 if (name_token == Token::LET) { |
1707 classifier->RecordLetPatternError( | 1715 classifier->RecordLetPatternError( |
1708 scanner()->location(), MessageTemplate::kLetInLexicalBinding); | 1716 scanner()->location(), MessageTemplate::kLetInLexicalBinding); |
1709 } | 1717 } |
1710 | 1718 |
1711 ExpressionT lhs = this->ExpressionFromIdentifier( | 1719 ExpressionT lhs = this->ExpressionFromIdentifier( |
1712 name, next_beg_pos, next_end_pos, scope_, factory()); | 1720 name, next_beg_pos, next_end_pos, scope_, factory()); |
1713 | 1721 |
1722 ClassifyReferenceExpression(classifier, lhs, next_beg_pos, next_end_pos); | |
1723 | |
1714 if (peek() == Token::ASSIGN) { | 1724 if (peek() == Token::ASSIGN) { |
1715 Consume(Token::ASSIGN); | 1725 Consume(Token::ASSIGN); |
1716 ExpressionClassifier rhs_classifier; | 1726 ExpressionClassifier rhs_classifier; |
1717 ExpressionT rhs = this->ParseAssignmentExpression( | 1727 ExpressionT rhs = this->ParseAssignmentExpression( |
1718 true, &rhs_classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 1728 true, &rhs_classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
1719 classifier->Accumulate(rhs_classifier, | 1729 classifier->Accumulate(rhs_classifier, |
1720 ExpressionClassifier::ExpressionProductions); | 1730 ExpressionClassifier::ExpressionProductions); |
1721 value = factory()->NewAssignment(Token::ASSIGN, lhs, rhs, | 1731 value = factory()->NewAssignment(Token::ASSIGN, lhs, rhs, |
1722 RelocInfo::kNoPosition); | 1732 RelocInfo::kNoPosition); |
1723 classifier->RecordCoverInitializedNameError( | 1733 classifier->RecordCoverInitializedNameError( |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2043 ExpressionClassifier::FormalParametersProductions | | 2053 ExpressionClassifier::FormalParametersProductions | |
2044 ExpressionClassifier::CoverInitializedNameProduction); | 2054 ExpressionClassifier::CoverInitializedNameProduction); |
2045 | 2055 |
2046 bool maybe_pattern = | 2056 bool maybe_pattern = |
2047 expression->IsObjectLiteral() || expression->IsArrayLiteral(); | 2057 expression->IsObjectLiteral() || expression->IsArrayLiteral(); |
2048 // bool binding_pattern = | 2058 // bool binding_pattern = |
2049 // allow_harmony_destructuring_bind() && maybe_pattern && !is_rhs; | 2059 // allow_harmony_destructuring_bind() && maybe_pattern && !is_rhs; |
2050 | 2060 |
2051 if (!Token::IsAssignmentOp(peek())) { | 2061 if (!Token::IsAssignmentOp(peek())) { |
2052 // Parsed conditional expression only (no assignment). | 2062 // Parsed conditional expression only (no assignment). |
2063 if (is_pattern_element && !maybe_pattern) { | |
2064 ClassifyReferenceExpression(classifier, expression, lhs_beg_pos, | |
2065 scanner()->location().end_pos); | |
2066 } | |
2053 if (is_pattern_element && !this->IsValidReferenceExpression(expression) && | 2067 if (is_pattern_element && !this->IsValidReferenceExpression(expression) && |
2054 !maybe_pattern) { | 2068 !maybe_pattern) { |
2055 classifier->RecordPatternError( | 2069 classifier->RecordPatternError( |
2056 Scanner::Location(lhs_beg_pos, scanner()->location().end_pos), | 2070 Scanner::Location(lhs_beg_pos, scanner()->location().end_pos), |
2057 MessageTemplate::kInvalidDestructuringTarget); | 2071 MessageTemplate::kInvalidDestructuringTarget); |
2058 } else if (is_rhs && maybe_pattern) { | 2072 } else if (is_rhs && maybe_pattern) { |
2059 ValidateExpression(classifier, CHECK_OK); | 2073 ValidateExpression(classifier, CHECK_OK); |
2060 } | 2074 } |
2061 | 2075 |
2062 return expression; | 2076 return expression; |
(...skipping 1168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3231 ExpressionClassifier classifier; | 3245 ExpressionClassifier classifier; |
3232 ExpressionT result = ClassifyAndRewriteReferenceExpression( | 3246 ExpressionT result = ClassifyAndRewriteReferenceExpression( |
3233 &classifier, expression, beg_pos, end_pos, message, type); | 3247 &classifier, expression, beg_pos, end_pos, message, type); |
3234 ValidateExpression(&classifier, ok); | 3248 ValidateExpression(&classifier, ok); |
3235 if (!*ok) return this->EmptyExpression(); | 3249 if (!*ok) return this->EmptyExpression(); |
3236 return result; | 3250 return result; |
3237 } | 3251 } |
3238 | 3252 |
3239 | 3253 |
3240 template <typename Traits> | 3254 template <typename Traits> |
3255 void ParserBase<Traits>::ClassifyReferenceExpression( | |
adamk
2015/12/12 01:03:35
Indeed, this code is very close to the existing Ch
| |
3256 ExpressionClassifier* classifier, ExpressionT expression, int beg_pos, | |
3257 int end_pos) { | |
3258 if (!this->IsIdentifier(expression)) return; | |
3259 IdentifierT ref = this->AsIdentifier(expression); | |
3260 if (is_strict(language_mode()) && this->IsEvalOrArguments(ref)) { | |
3261 classifier->RecordAssignmentPatternError( | |
3262 Scanner::Location(beg_pos, end_pos), | |
3263 MessageTemplate::kStrictEvalArguments); | |
3264 } else if (is_strong(language_mode()) && this->IsUndefined(ref)) { | |
3265 classifier->RecordAssignmentPatternError( | |
3266 Scanner::Location(beg_pos, end_pos), MessageTemplate::kStrongUndefined); | |
3267 } | |
3268 } | |
3269 | |
3270 | |
3271 template <typename Traits> | |
3241 typename ParserBase<Traits>::ExpressionT | 3272 typename ParserBase<Traits>::ExpressionT |
3242 ParserBase<Traits>::ClassifyAndRewriteReferenceExpression( | 3273 ParserBase<Traits>::ClassifyAndRewriteReferenceExpression( |
3243 ExpressionClassifier* classifier, ExpressionT expression, int beg_pos, | 3274 ExpressionClassifier* classifier, ExpressionT expression, int beg_pos, |
3244 int end_pos, MessageTemplate::Template message, ParseErrorType type) { | 3275 int end_pos, MessageTemplate::Template message, ParseErrorType type) { |
3245 Scanner::Location location(beg_pos, end_pos); | 3276 Scanner::Location location(beg_pos, end_pos); |
3246 if (this->IsIdentifier(expression)) { | 3277 if (this->IsIdentifier(expression)) { |
3247 if (is_strict(language_mode()) && | 3278 if (is_strict(language_mode()) && |
3248 this->IsEvalOrArguments(this->AsIdentifier(expression))) { | 3279 this->IsEvalOrArguments(this->AsIdentifier(expression))) { |
3249 classifier->RecordExpressionError( | 3280 classifier->RecordExpressionError( |
3250 location, MessageTemplate::kStrictEvalArguments, kSyntaxError); | 3281 location, MessageTemplate::kStrictEvalArguments, kSyntaxError); |
3282 classifier->RecordAssignmentPatternError( | |
3283 location, MessageTemplate::kStrictEvalArguments); | |
3251 return expression; | 3284 return expression; |
3252 } | 3285 } |
3253 if (is_strong(language_mode()) && | 3286 if (is_strong(language_mode()) && |
3254 this->IsUndefined(this->AsIdentifier(expression))) { | 3287 this->IsUndefined(this->AsIdentifier(expression))) { |
3255 classifier->RecordExpressionError( | 3288 classifier->RecordExpressionError( |
3256 location, MessageTemplate::kStrongUndefined, kSyntaxError); | 3289 location, MessageTemplate::kStrongUndefined, kSyntaxError); |
3290 classifier->RecordAssignmentPatternError( | |
3291 location, MessageTemplate::kStrongUndefined); | |
3257 return expression; | 3292 return expression; |
3258 } | 3293 } |
3259 } | 3294 } |
3260 if (expression->IsValidReferenceExpression()) { | 3295 if (expression->IsValidReferenceExpression()) { |
3261 return expression; | 3296 return expression; |
3262 } else if (expression->IsCall()) { | 3297 } else if (expression->IsCall()) { |
3263 // If it is a call, make it a runtime error for legacy web compatibility. | 3298 // If it is a call, make it a runtime error for legacy web compatibility. |
3264 // Rewrite `expr' to `expr[throw ReferenceError]'. | 3299 // Rewrite `expr' to `expr[throw ReferenceError]'. |
3265 int pos = location.beg_pos; | 3300 int pos = location.beg_pos; |
3266 ExpressionT error = this->NewThrowReferenceError(message, pos); | 3301 ExpressionT error = this->NewThrowReferenceError(message, pos); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3349 return; | 3384 return; |
3350 } | 3385 } |
3351 has_seen_constructor_ = true; | 3386 has_seen_constructor_ = true; |
3352 return; | 3387 return; |
3353 } | 3388 } |
3354 } | 3389 } |
3355 } // namespace internal | 3390 } // namespace internal |
3356 } // namespace v8 | 3391 } // namespace v8 |
3357 | 3392 |
3358 #endif // V8_PARSING_PARSER_BASE_H | 3393 #endif // V8_PARSING_PARSER_BASE_H |
OLD | NEW |