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/base/hashmap.h" | 10 #include "src/base/hashmap.h" |
(...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
890 } | 890 } |
891 | 891 |
892 bool IsValidArrowFormalParametersStart(Token::Value token) { | 892 bool IsValidArrowFormalParametersStart(Token::Value token) { |
893 return is_any_identifier(token) || token == Token::LPAREN; | 893 return is_any_identifier(token) || token == Token::LPAREN; |
894 } | 894 } |
895 | 895 |
896 void ValidateArrowFormalParameters(const ExpressionClassifier* classifier, | 896 void ValidateArrowFormalParameters(const ExpressionClassifier* classifier, |
897 ExpressionT expr, | 897 ExpressionT expr, |
898 bool parenthesized_formals, bool is_async, | 898 bool parenthesized_formals, bool is_async, |
899 bool* ok) { | 899 bool* ok) { |
900 if (classifier->is_valid_binding_pattern()) { | 900 if (!is_async && classifier->is_valid_binding_pattern()) { |
901 // A simple arrow formal parameter: IDENTIFIER => BODY. | 901 // A simple arrow formal parameter: IDENTIFIER => BODY. |
902 if (!this->IsIdentifier(expr)) { | 902 if (!this->IsIdentifier(expr)) { |
903 Traits::ReportMessageAt(scanner()->location(), | 903 Traits::ReportMessageAt(scanner()->location(), |
904 MessageTemplate::kUnexpectedToken, | 904 MessageTemplate::kUnexpectedToken, |
905 Token::String(scanner()->current_token())); | 905 Token::String(scanner()->current_token())); |
906 *ok = false; | 906 *ok = false; |
907 } | 907 } |
908 } else if (!classifier->is_valid_arrow_formal_parameters()) { | 908 } else if (!classifier->is_valid_arrow_formal_parameters()) { |
909 // If after parsing the expr, we see an error but the expression is | 909 // If after parsing the expr, we see an error but the expression is |
910 // neither a valid binding pattern nor a valid parenthesized formal | 910 // neither a valid binding pattern nor a valid parenthesized formal |
911 // parameter list, show the "arrow formal parameters" error if the formals | 911 // parameter list, show the "arrow formal parameters" error if the formals |
912 // started with a parenthesis, and the binding pattern error otherwise. | 912 // started with a parenthesis, and the binding pattern error otherwise. |
913 const typename ExpressionClassifier::Error& error = | 913 const typename ExpressionClassifier::Error& error = |
914 parenthesized_formals ? classifier->arrow_formal_parameters_error() | 914 parenthesized_formals ? classifier->arrow_formal_parameters_error() |
915 : classifier->binding_pattern_error(); | 915 : classifier->binding_pattern_error(); |
916 ReportClassifierError(error); | 916 ReportClassifierError(error); |
917 *ok = false; | 917 *ok = false; |
918 } | 918 } |
919 if (is_async && !classifier->is_valid_async_arrow_formal_parameters()) { | 919 if (is_async) { |
920 const typename ExpressionClassifier::Error& error = | 920 if (!classifier->is_valid_async_arrow_formal_parameters()) { |
921 classifier->async_arrow_formal_parameters_error(); | 921 const typename ExpressionClassifier::Error& error = |
922 ReportClassifierError(error); | 922 classifier->async_arrow_formal_parameters_error(); |
923 *ok = false; | 923 ReportClassifierError(error); |
924 *ok = false; | |
925 } | |
926 if (!classifier->is_valid_binding_pattern()) { | |
nickie
2016/07/11 13:19:50
Is it possible that we have both !is_valid_async_a
caitp
2016/07/11 13:24:42
Yeah, this is true --- the WebKit style is to just
nickie
2016/07/11 13:32:18
Yes, I think that adding return statements is a be
| |
927 ReportClassifierError(classifier->binding_pattern_error()); | |
928 *ok = false; | |
929 } | |
924 } | 930 } |
925 } | 931 } |
926 | 932 |
927 void ValidateLetPattern(const ExpressionClassifier* classifier, bool* ok) { | 933 void ValidateLetPattern(const ExpressionClassifier* classifier, bool* ok) { |
928 if (!classifier->is_valid_let_pattern()) { | 934 if (!classifier->is_valid_let_pattern()) { |
929 ReportClassifierError(classifier->let_pattern_error()); | 935 ReportClassifierError(classifier->let_pattern_error()); |
930 *ok = false; | 936 *ok = false; |
931 } | 937 } |
932 } | 938 } |
933 | 939 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1017 Scanner::Location* first_spread_pos, bool maybe_arrow, | 1023 Scanner::Location* first_spread_pos, bool maybe_arrow, |
1018 ExpressionClassifier* classifier, bool* ok); | 1024 ExpressionClassifier* classifier, bool* ok); |
1019 typename Traits::Type::ExpressionList ParseArguments( | 1025 typename Traits::Type::ExpressionList ParseArguments( |
1020 Scanner::Location* first_spread_pos, ExpressionClassifier* classifier, | 1026 Scanner::Location* first_spread_pos, ExpressionClassifier* classifier, |
1021 bool* ok) { | 1027 bool* ok) { |
1022 return ParseArguments(first_spread_pos, false, classifier, ok); | 1028 return ParseArguments(first_spread_pos, false, classifier, ok); |
1023 } | 1029 } |
1024 | 1030 |
1025 ExpressionT ParseAssignmentExpression(bool accept_IN, | 1031 ExpressionT ParseAssignmentExpression(bool accept_IN, |
1026 ExpressionClassifier* classifier, | 1032 ExpressionClassifier* classifier, |
1027 bool* ok); | 1033 bool marge_partterns, bool* ok); |
nickie
2016/07/11 13:19:50
Unless I'm missing the pun, "merge_patterns" :-)
caitp
2016/07/11 13:24:42
just a typo, will fix
| |
1034 ExpressionT ParseAssignmentExpression(bool accept_IN, | |
1035 ExpressionClassifier* classifier, | |
1036 bool* ok) { | |
1037 return ParseAssignmentExpression(accept_IN, classifier, false, ok); | |
1038 } | |
1028 ExpressionT ParseYieldExpression(bool accept_IN, | 1039 ExpressionT ParseYieldExpression(bool accept_IN, |
1029 ExpressionClassifier* classifier, bool* ok); | 1040 ExpressionClassifier* classifier, bool* ok); |
1030 ExpressionT ParseTailCallExpression(ExpressionClassifier* classifier, | 1041 ExpressionT ParseTailCallExpression(ExpressionClassifier* classifier, |
1031 bool* ok); | 1042 bool* ok); |
1032 ExpressionT ParseConditionalExpression(bool accept_IN, | 1043 ExpressionT ParseConditionalExpression(bool accept_IN, |
1033 ExpressionClassifier* classifier, | 1044 ExpressionClassifier* classifier, |
1034 bool* ok); | 1045 bool* ok); |
1035 ExpressionT ParseBinaryExpression(int prec, bool accept_IN, | 1046 ExpressionT ParseBinaryExpression(int prec, bool accept_IN, |
1036 ExpressionClassifier* classifier, bool* ok); | 1047 ExpressionClassifier* classifier, bool* ok); |
1037 ExpressionT ParseUnaryExpression(ExpressionClassifier* classifier, bool* ok); | 1048 ExpressionT ParseUnaryExpression(ExpressionClassifier* classifier, bool* ok); |
(...skipping 1127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2165 Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList)); | 2176 Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList)); |
2166 bool done = (peek() == Token::RPAREN); | 2177 bool done = (peek() == Token::RPAREN); |
2167 bool was_unspread = false; | 2178 bool was_unspread = false; |
2168 int unspread_sequences_count = 0; | 2179 int unspread_sequences_count = 0; |
2169 while (!done) { | 2180 while (!done) { |
2170 int start_pos = peek_position(); | 2181 int start_pos = peek_position(); |
2171 bool is_spread = Check(Token::ELLIPSIS); | 2182 bool is_spread = Check(Token::ELLIPSIS); |
2172 int expr_pos = peek_position(); | 2183 int expr_pos = peek_position(); |
2173 | 2184 |
2174 ExpressionT argument = this->ParseAssignmentExpression( | 2185 ExpressionT argument = this->ParseAssignmentExpression( |
2175 true, classifier, CHECK_OK_CUSTOM(NullExpressionList)); | 2186 true, classifier, maybe_arrow, CHECK_OK_CUSTOM(NullExpressionList)); |
2176 CheckNoTailCallExpressions(classifier, CHECK_OK_CUSTOM(NullExpressionList)); | 2187 CheckNoTailCallExpressions(classifier, CHECK_OK_CUSTOM(NullExpressionList)); |
2177 if (!maybe_arrow) { | 2188 if (!maybe_arrow) { |
2178 Traits::RewriteNonPattern(classifier, | 2189 Traits::RewriteNonPattern(classifier, |
2179 CHECK_OK_CUSTOM(NullExpressionList)); | 2190 CHECK_OK_CUSTOM(NullExpressionList)); |
2180 } | 2191 } |
2181 if (is_spread) { | 2192 if (is_spread) { |
2182 if (!spread_arg.IsValid()) { | 2193 if (!spread_arg.IsValid()) { |
2183 spread_arg.beg_pos = start_pos; | 2194 spread_arg.beg_pos = start_pos; |
2184 spread_arg.end_pos = peek_position(); | 2195 spread_arg.end_pos = peek_position(); |
2185 } | 2196 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2232 } | 2243 } |
2233 | 2244 |
2234 return result; | 2245 return result; |
2235 } | 2246 } |
2236 | 2247 |
2237 // Precedence = 2 | 2248 // Precedence = 2 |
2238 template <class Traits> | 2249 template <class Traits> |
2239 typename ParserBase<Traits>::ExpressionT | 2250 typename ParserBase<Traits>::ExpressionT |
2240 ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, | 2251 ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
2241 ExpressionClassifier* classifier, | 2252 ExpressionClassifier* classifier, |
2242 bool* ok) { | 2253 bool merge_patterns, bool* ok) { |
2243 // AssignmentExpression :: | 2254 // AssignmentExpression :: |
2244 // ConditionalExpression | 2255 // ConditionalExpression |
2245 // ArrowFunction | 2256 // ArrowFunction |
2246 // YieldExpression | 2257 // YieldExpression |
2247 // LeftHandSideExpression AssignmentOperator AssignmentExpression | 2258 // LeftHandSideExpression AssignmentOperator AssignmentExpression |
2248 bool is_destructuring_assignment = false; | 2259 bool is_destructuring_assignment = false; |
2249 int lhs_beg_pos = peek_position(); | 2260 int lhs_beg_pos = peek_position(); |
2250 | 2261 |
2251 if (peek() == Token::YIELD && is_generator()) { | 2262 if (peek() == Token::YIELD && is_generator()) { |
2252 return this->ParseYieldExpression(accept_IN, classifier, ok); | 2263 return this->ParseYieldExpression(accept_IN, classifier, ok); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2324 return expression; | 2335 return expression; |
2325 } | 2336 } |
2326 | 2337 |
2327 if (this->IsValidReferenceExpression(expression)) { | 2338 if (this->IsValidReferenceExpression(expression)) { |
2328 arrow_formals_classifier.ForgiveAssignmentPatternError(); | 2339 arrow_formals_classifier.ForgiveAssignmentPatternError(); |
2329 } | 2340 } |
2330 | 2341 |
2331 // "expression" was not itself an arrow function parameter list, but it might | 2342 // "expression" was not itself an arrow function parameter list, but it might |
2332 // form part of one. Propagate speculative formal parameter error locations. | 2343 // form part of one. Propagate speculative formal parameter error locations. |
2333 // Do not merge pending non-pattern expressions yet! | 2344 // Do not merge pending non-pattern expressions yet! |
2334 classifier->Accumulate( | 2345 int productions_to_propagate = |
2335 &arrow_formals_classifier, | |
2336 ExpressionClassifier::StandardProductions | | 2346 ExpressionClassifier::StandardProductions | |
2337 ExpressionClassifier::FormalParametersProductions | | 2347 ExpressionClassifier::FormalParametersProductions | |
2338 ExpressionClassifier::CoverInitializedNameProduction | | 2348 ExpressionClassifier::CoverInitializedNameProduction | |
2339 ExpressionClassifier::AsyncArrowFormalParametersProduction | | 2349 ExpressionClassifier::AsyncArrowFormalParametersProduction | |
2340 ExpressionClassifier::AsyncBindingPatternProduction, | 2350 ExpressionClassifier::AsyncBindingPatternProduction; |
2341 false); | 2351 if (merge_patterns) { |
Dan Ehrenberg
2016/07/11 23:22:47
I find this logic of when to merge_patterns to be
caitp
2016/07/11 23:32:24
That doesn't really work, because then we could fa
Dan Ehrenberg
2016/07/11 23:37:57
I don't understand the issue. The binding pattern
nickie
2016/07/12 13:11:53
I tried the following with Dan's patch and they se
caitp
2016/07/12 14:38:30
What are either of you even talking about? Using p
| |
2352 productions_to_propagate |= ExpressionClassifier::BindingPatternProduction; | |
2353 } | |
2354 | |
2355 classifier->Accumulate(&arrow_formals_classifier, productions_to_propagate, | |
2356 false); | |
2342 | 2357 |
2343 if (!Token::IsAssignmentOp(peek())) { | 2358 if (!Token::IsAssignmentOp(peek())) { |
2344 // Parsed conditional expression only (no assignment). | 2359 // Parsed conditional expression only (no assignment). |
2345 // Now pending non-pattern expressions must be merged. | 2360 // Now pending non-pattern expressions must be merged. |
2346 classifier->MergeNonPatterns(&arrow_formals_classifier); | 2361 classifier->MergeNonPatterns(&arrow_formals_classifier); |
2347 return expression; | 2362 return expression; |
2348 } | 2363 } |
2349 | 2364 |
2350 // Now pending non-pattern expressions must be discarded. | 2365 // Now pending non-pattern expressions must be discarded. |
2351 arrow_formals_classifier.Discard(); | 2366 arrow_formals_classifier.Discard(); |
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2798 Traits::RewriteNonPattern(classifier, CHECK_OK); | 2813 Traits::RewriteNonPattern(classifier, CHECK_OK); |
2799 result = factory()->NewProperty(result, index, pos); | 2814 result = factory()->NewProperty(result, index, pos); |
2800 Expect(Token::RBRACK, CHECK_OK); | 2815 Expect(Token::RBRACK, CHECK_OK); |
2801 break; | 2816 break; |
2802 } | 2817 } |
2803 | 2818 |
2804 case Token::LPAREN: { | 2819 case Token::LPAREN: { |
2805 CheckNoTailCallExpressions(classifier, CHECK_OK); | 2820 CheckNoTailCallExpressions(classifier, CHECK_OK); |
2806 int pos; | 2821 int pos; |
2807 Traits::RewriteNonPattern(classifier, CHECK_OK); | 2822 Traits::RewriteNonPattern(classifier, CHECK_OK); |
2808 BindingPatternUnexpectedToken(classifier); | 2823 |
2824 const char* arg; | |
2825 MessageTemplate::Template message = MessageTemplate::kUnexpectedToken; | |
2826 Scanner::Location location = scanner()->peek_location(); | |
2827 GetUnexpectedTokenMessage(peek(), &message, &location, &arg); | |
2828 | |
2829 if (!is_async) { | |
2830 classifier->RecordBindingPatternError(location, message, arg); | |
2831 } | |
2832 | |
2809 if (scanner()->current_token() == Token::IDENTIFIER || | 2833 if (scanner()->current_token() == Token::IDENTIFIER || |
2810 scanner()->current_token() == Token::SUPER || | 2834 scanner()->current_token() == Token::SUPER || |
2811 scanner()->current_token() == Token::ASYNC) { | 2835 scanner()->current_token() == Token::ASYNC) { |
2812 // For call of an identifier we want to report position of | 2836 // For call of an identifier we want to report position of |
2813 // the identifier as position of the call in the stack trace. | 2837 // the identifier as position of the call in the stack trace. |
2814 pos = position(); | 2838 pos = position(); |
2815 } else { | 2839 } else { |
2816 // For other kinds of calls we record position of the parenthesis as | 2840 // For other kinds of calls we record position of the parenthesis as |
2817 // position of the call. Note that this is extremely important for | 2841 // position of the call. Note that this is extremely important for |
2818 // expressions of the form function(){...}() for which call position | 2842 // expressions of the form function(){...}() for which call position |
(...skipping 11 matching lines...) Expand all Loading... | |
2830 typename Traits::Type::ExpressionList args = | 2854 typename Traits::Type::ExpressionList args = |
2831 ParseArguments(&spread_pos, is_async, classifier, CHECK_OK); | 2855 ParseArguments(&spread_pos, is_async, classifier, CHECK_OK); |
2832 | 2856 |
2833 if (V8_UNLIKELY(is_async && peek() == Token::ARROW)) { | 2857 if (V8_UNLIKELY(is_async && peek() == Token::ARROW)) { |
2834 if (args->length()) { | 2858 if (args->length()) { |
2835 // async ( Arguments ) => ... | 2859 // async ( Arguments ) => ... |
2836 return Traits::ExpressionListToExpression(args); | 2860 return Traits::ExpressionListToExpression(args); |
2837 } | 2861 } |
2838 // async () => ... | 2862 // async () => ... |
2839 return factory()->NewEmptyParentheses(pos); | 2863 return factory()->NewEmptyParentheses(pos); |
2864 } else { | |
2865 classifier->ReplaceBindingPatternError(location, message, arg); | |
Dan Ehrenberg
2016/07/11 23:22:47
I don't understand why this case is added when we'
caitp
2016/07/11 23:32:24
ArrowFormalParameters don't really matter for asyn
Dan Ehrenberg
2016/07/11 23:37:57
Could you write a test for it?
| |
2840 } | 2866 } |
2841 | 2867 |
2842 ArrowFormalParametersUnexpectedToken(classifier); | 2868 ArrowFormalParametersUnexpectedToken(classifier); |
2843 | 2869 |
2844 // Keep track of eval() calls since they disable all local variable | 2870 // Keep track of eval() calls since they disable all local variable |
2845 // optimizations. | 2871 // optimizations. |
2846 // The calls that need special treatment are the | 2872 // The calls that need special treatment are the |
2847 // direct eval calls. These calls are all of the form eval(...), with | 2873 // direct eval calls. These calls are all of the form eval(...), with |
2848 // no explicit receiver. | 2874 // no explicit receiver. |
2849 // These calls are marked as potentially direct eval calls. Whether | 2875 // These calls are marked as potentially direct eval calls. Whether |
(...skipping 801 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3651 has_seen_constructor_ = true; | 3677 has_seen_constructor_ = true; |
3652 return; | 3678 return; |
3653 } | 3679 } |
3654 } | 3680 } |
3655 | 3681 |
3656 | 3682 |
3657 } // namespace internal | 3683 } // namespace internal |
3658 } // namespace v8 | 3684 } // namespace v8 |
3659 | 3685 |
3660 #endif // V8_PARSING_PARSER_BASE_H | 3686 #endif // V8_PARSING_PARSER_BASE_H |
OLD | NEW |