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_PREPARSER_H | 5 #ifndef V8_PREPARSER_H |
6 #define V8_PREPARSER_H | 6 #define V8_PREPARSER_H |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/bailout-reason.h" | 10 #include "src/bailout-reason.h" |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 bool allow_arrow_functions() const { return allow_arrow_functions_; } | 95 bool allow_arrow_functions() const { return allow_arrow_functions_; } |
96 bool allow_modules() const { return scanner()->HarmonyModules(); } | 96 bool allow_modules() const { return scanner()->HarmonyModules(); } |
97 bool allow_harmony_scoping() const { return scanner()->HarmonyScoping(); } | 97 bool allow_harmony_scoping() const { return scanner()->HarmonyScoping(); } |
98 bool allow_harmony_numeric_literals() const { | 98 bool allow_harmony_numeric_literals() const { |
99 return scanner()->HarmonyNumericLiterals(); | 99 return scanner()->HarmonyNumericLiterals(); |
100 } | 100 } |
101 bool allow_classes() const { return scanner()->HarmonyClasses(); } | 101 bool allow_classes() const { return scanner()->HarmonyClasses(); } |
102 bool allow_harmony_object_literals() const { | 102 bool allow_harmony_object_literals() const { |
103 return allow_harmony_object_literals_; | 103 return allow_harmony_object_literals_; |
104 } | 104 } |
| 105 bool allow_harmony_templates() const { return scanner()->HarmonyTemplates(); } |
105 | 106 |
106 // Setters that determine whether certain syntactical constructs are | 107 // Setters that determine whether certain syntactical constructs are |
107 // allowed to be parsed by this instance of the parser. | 108 // allowed to be parsed by this instance of the parser. |
108 void set_allow_lazy(bool allow) { allow_lazy_ = allow; } | 109 void set_allow_lazy(bool allow) { allow_lazy_ = allow; } |
109 void set_allow_natives_syntax(bool allow) { allow_natives_syntax_ = allow; } | 110 void set_allow_natives_syntax(bool allow) { allow_natives_syntax_ = allow; } |
110 void set_allow_arrow_functions(bool allow) { allow_arrow_functions_ = allow; } | 111 void set_allow_arrow_functions(bool allow) { allow_arrow_functions_ = allow; } |
111 void set_allow_modules(bool allow) { scanner()->SetHarmonyModules(allow); } | 112 void set_allow_modules(bool allow) { scanner()->SetHarmonyModules(allow); } |
112 void set_allow_harmony_scoping(bool allow) { | 113 void set_allow_harmony_scoping(bool allow) { |
113 scanner()->SetHarmonyScoping(allow); | 114 scanner()->SetHarmonyScoping(allow); |
114 } | 115 } |
115 void set_allow_harmony_numeric_literals(bool allow) { | 116 void set_allow_harmony_numeric_literals(bool allow) { |
116 scanner()->SetHarmonyNumericLiterals(allow); | 117 scanner()->SetHarmonyNumericLiterals(allow); |
117 } | 118 } |
118 void set_allow_classes(bool allow) { scanner()->SetHarmonyClasses(allow); } | 119 void set_allow_classes(bool allow) { scanner()->SetHarmonyClasses(allow); } |
119 void set_allow_harmony_object_literals(bool allow) { | 120 void set_allow_harmony_object_literals(bool allow) { |
120 allow_harmony_object_literals_ = allow; | 121 allow_harmony_object_literals_ = allow; |
121 } | 122 } |
| 123 void set_allow_harmony_templates(bool allow) { |
| 124 scanner()->SetHarmonyTemplates(allow); |
| 125 } |
122 | 126 |
123 protected: | 127 protected: |
124 enum AllowEvalOrArgumentsAsIdentifier { | 128 enum AllowEvalOrArgumentsAsIdentifier { |
125 kAllowEvalOrArguments, | 129 kAllowEvalOrArguments, |
126 kDontAllowEvalOrArguments | 130 kDontAllowEvalOrArguments |
127 }; | 131 }; |
128 | 132 |
129 enum Mode { | 133 enum Mode { |
130 PARSE_LAZILY, | 134 PARSE_LAZILY, |
131 PARSE_EAGERLY | 135 PARSE_EAGERLY |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
487 ExpressionT ParseMemberWithNewPrefixesExpression(bool* ok); | 491 ExpressionT ParseMemberWithNewPrefixesExpression(bool* ok); |
488 ExpressionT ParseMemberExpression(bool* ok); | 492 ExpressionT ParseMemberExpression(bool* ok); |
489 ExpressionT ParseMemberExpressionContinuation(ExpressionT expression, | 493 ExpressionT ParseMemberExpressionContinuation(ExpressionT expression, |
490 bool* ok); | 494 bool* ok); |
491 ExpressionT ParseArrowFunctionLiteral(int start_pos, ExpressionT params_ast, | 495 ExpressionT ParseArrowFunctionLiteral(int start_pos, ExpressionT params_ast, |
492 bool* ok); | 496 bool* ok); |
493 ExpressionT ParseClassLiteral(IdentifierT name, | 497 ExpressionT ParseClassLiteral(IdentifierT name, |
494 Scanner::Location function_name_location, | 498 Scanner::Location function_name_location, |
495 bool name_is_strict_reserved, int pos, | 499 bool name_is_strict_reserved, int pos, |
496 bool* ok); | 500 bool* ok); |
| 501 ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, bool* ok); |
| 502 void AddTemplateExpression(ExpressionT); |
497 | 503 |
498 // Checks if the expression is a valid reference expression (e.g., on the | 504 // Checks if the expression is a valid reference expression (e.g., on the |
499 // left-hand side of assignments). Although ruled out by ECMA as early errors, | 505 // left-hand side of assignments). Although ruled out by ECMA as early errors, |
500 // we allow calls for web compatibility and rewrite them to a runtime throw. | 506 // we allow calls for web compatibility and rewrite them to a runtime throw. |
501 ExpressionT CheckAndRewriteReferenceExpression( | 507 ExpressionT CheckAndRewriteReferenceExpression( |
502 ExpressionT expression, | 508 ExpressionT expression, |
503 Scanner::Location location, const char* message, bool* ok); | 509 Scanner::Location location, const char* message, bool* ok); |
504 | 510 |
505 // Used to detect duplicates in object literals. Each of the values | 511 // Used to detect duplicates in object literals. Each of the values |
506 // kGetterProperty, kSetterProperty and kValueProperty represents | 512 // kGetterProperty, kSetterProperty and kValueProperty represents |
(...skipping 872 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1379 // Utility functions | 1385 // Utility functions |
1380 int DeclareArrowParametersFromExpression(PreParserExpression expression, | 1386 int DeclareArrowParametersFromExpression(PreParserExpression expression, |
1381 PreParserScope* scope, | 1387 PreParserScope* scope, |
1382 Scanner::Location* dupe_loc, | 1388 Scanner::Location* dupe_loc, |
1383 bool* ok) { | 1389 bool* ok) { |
1384 // TODO(aperez): Detect duplicated identifiers in paramlists. | 1390 // TODO(aperez): Detect duplicated identifiers in paramlists. |
1385 *ok = expression.IsValidArrowParamList(); | 1391 *ok = expression.IsValidArrowParamList(); |
1386 return 0; | 1392 return 0; |
1387 } | 1393 } |
1388 | 1394 |
| 1395 struct TemplateLiteralState {}; |
| 1396 |
| 1397 TemplateLiteralState OpenTemplateLiteral(int pos) { |
| 1398 return TemplateLiteralState(); |
| 1399 } |
| 1400 void AddTemplateSpan(TemplateLiteralState*, bool) {} |
| 1401 void AddTemplateExpression(TemplateLiteralState*, PreParserExpression) {} |
| 1402 PreParserExpression CloseTemplateLiteral(TemplateLiteralState*, int, |
| 1403 PreParserExpression) { |
| 1404 return EmptyExpression(); |
| 1405 } |
| 1406 PreParserExpression NoTemplateTag() { return PreParserExpression::Default(); } |
1389 static AstValueFactory* ast_value_factory() { return NULL; } | 1407 static AstValueFactory* ast_value_factory() { return NULL; } |
1390 | 1408 |
1391 void CheckConflictingVarDeclarations(PreParserScope scope, bool* ok) {} | 1409 void CheckConflictingVarDeclarations(PreParserScope scope, bool* ok) {} |
1392 | 1410 |
1393 // Temporary glue; these functions will move to ParserBase. | 1411 // Temporary glue; these functions will move to ParserBase. |
1394 PreParserExpression ParseV8Intrinsic(bool* ok); | 1412 PreParserExpression ParseV8Intrinsic(bool* ok); |
1395 PreParserExpression ParseFunctionLiteral( | 1413 PreParserExpression ParseFunctionLiteral( |
1396 PreParserIdentifier name, Scanner::Location function_name_location, | 1414 PreParserIdentifier name, Scanner::Location function_name_location, |
1397 bool name_is_strict_reserved, FunctionKind kind, | 1415 bool name_is_strict_reserved, FunctionKind kind, |
1398 int function_token_position, FunctionLiteral::FunctionType type, | 1416 int function_token_position, FunctionLiteral::FunctionType type, |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1749 // 'true' | 1767 // 'true' |
1750 // 'false' | 1768 // 'false' |
1751 // Identifier | 1769 // Identifier |
1752 // Number | 1770 // Number |
1753 // String | 1771 // String |
1754 // ArrayLiteral | 1772 // ArrayLiteral |
1755 // ObjectLiteral | 1773 // ObjectLiteral |
1756 // RegExpLiteral | 1774 // RegExpLiteral |
1757 // ClassLiteral | 1775 // ClassLiteral |
1758 // '(' Expression ')' | 1776 // '(' Expression ')' |
| 1777 // TemplateLiteral |
1759 | 1778 |
1760 int pos = peek_position(); | 1779 int pos = peek_position(); |
1761 ExpressionT result = this->EmptyExpression(); | 1780 ExpressionT result = this->EmptyExpression(); |
1762 Token::Value token = peek(); | 1781 Token::Value token = peek(); |
1763 switch (token) { | 1782 switch (token) { |
1764 case Token::THIS: { | 1783 case Token::THIS: { |
1765 Consume(Token::THIS); | 1784 Consume(Token::THIS); |
1766 scope_->RecordThisUsage(); | 1785 scope_->RecordThisUsage(); |
1767 result = this->ThisExpression(scope_, factory()); | 1786 result = this->ThisExpression(scope_, factory()); |
1768 break; | 1787 break; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1837 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, | 1856 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, |
1838 CHECK_OK); | 1857 CHECK_OK); |
1839 class_name_location = scanner()->location(); | 1858 class_name_location = scanner()->location(); |
1840 } | 1859 } |
1841 result = this->ParseClassLiteral(name, class_name_location, | 1860 result = this->ParseClassLiteral(name, class_name_location, |
1842 is_strict_reserved_name, | 1861 is_strict_reserved_name, |
1843 class_token_position, CHECK_OK); | 1862 class_token_position, CHECK_OK); |
1844 break; | 1863 break; |
1845 } | 1864 } |
1846 | 1865 |
| 1866 case Token::TEMPLATE_SPAN: |
| 1867 case Token::TEMPLATE_TAIL: |
| 1868 result = |
| 1869 this->ParseTemplateLiteral(Traits::NoTemplateTag(), pos, CHECK_OK); |
| 1870 break; |
| 1871 |
1847 case Token::MOD: | 1872 case Token::MOD: |
1848 if (allow_natives_syntax() || extension_ != NULL) { | 1873 if (allow_natives_syntax() || extension_ != NULL) { |
1849 result = this->ParseV8Intrinsic(CHECK_OK); | 1874 result = this->ParseV8Intrinsic(CHECK_OK); |
1850 break; | 1875 break; |
1851 } | 1876 } |
1852 // If we're not allowing special syntax we fall-through to the | 1877 // If we're not allowing special syntax we fall-through to the |
1853 // default case. | 1878 // default case. |
1854 | 1879 |
1855 default: { | 1880 default: { |
1856 Next(); | 1881 Next(); |
(...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2460 // direct eval calls. These calls are all of the form eval(...), with | 2485 // direct eval calls. These calls are all of the form eval(...), with |
2461 // no explicit receiver. | 2486 // no explicit receiver. |
2462 // These calls are marked as potentially direct eval calls. Whether | 2487 // These calls are marked as potentially direct eval calls. Whether |
2463 // they are actually direct calls to eval is determined at run time. | 2488 // they are actually direct calls to eval is determined at run time. |
2464 this->CheckPossibleEvalCall(result, scope_); | 2489 this->CheckPossibleEvalCall(result, scope_); |
2465 result = factory()->NewCall(result, args, pos); | 2490 result = factory()->NewCall(result, args, pos); |
2466 if (fni_ != NULL) fni_->RemoveLastFunction(); | 2491 if (fni_ != NULL) fni_->RemoveLastFunction(); |
2467 break; | 2492 break; |
2468 } | 2493 } |
2469 | 2494 |
| 2495 case Token::TEMPLATE_SPAN: |
| 2496 case Token::TEMPLATE_TAIL: { |
| 2497 int pos; |
| 2498 if (scanner()->current_token() == Token::IDENTIFIER) { |
| 2499 pos = position(); |
| 2500 } else { |
| 2501 pos = peek_position(); |
| 2502 if (result->IsFunctionLiteral() && mode() == PARSE_EAGERLY) { |
| 2503 // If the tag function looks like an IIFE, set_parenthesized() to |
| 2504 // force eager compilation. |
| 2505 result->AsFunctionLiteral()->set_parenthesized(); |
| 2506 } |
| 2507 } |
| 2508 result = ParseTemplateLiteral(result, pos, CHECK_OK); |
| 2509 break; |
| 2510 } |
| 2511 |
2470 case Token::PERIOD: { | 2512 case Token::PERIOD: { |
2471 Consume(Token::PERIOD); | 2513 Consume(Token::PERIOD); |
2472 int pos = position(); | 2514 int pos = position(); |
2473 IdentifierT name = ParseIdentifierName(CHECK_OK); | 2515 IdentifierT name = ParseIdentifierName(CHECK_OK); |
2474 result = factory()->NewProperty( | 2516 result = factory()->NewProperty( |
2475 result, factory()->NewStringLiteral(name, pos), pos); | 2517 result, factory()->NewStringLiteral(name, pos), pos); |
2476 if (fni_ != NULL) this->PushLiteralName(fni_, name); | 2518 if (fni_ != NULL) this->PushLiteralName(fni_, name); |
2477 break; | 2519 break; |
2478 } | 2520 } |
2479 | 2521 |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2807 this->DefaultConstructor(has_extends, scope_, pos, end_pos + 1); | 2849 this->DefaultConstructor(has_extends, scope_, pos, end_pos + 1); |
2808 } | 2850 } |
2809 | 2851 |
2810 return this->ClassExpression(name, extends, constructor, properties, pos, | 2852 return this->ClassExpression(name, extends, constructor, properties, pos, |
2811 end_pos + 1, factory()); | 2853 end_pos + 1, factory()); |
2812 } | 2854 } |
2813 | 2855 |
2814 | 2856 |
2815 template <typename Traits> | 2857 template <typename Traits> |
2816 typename ParserBase<Traits>::ExpressionT | 2858 typename ParserBase<Traits>::ExpressionT |
2817 ParserBase<Traits>::CheckAndRewriteReferenceExpression( | 2859 ParserBase<Traits>::ParseTemplateLiteral(ExpressionT tag, int start, bool* ok) { |
2818 ExpressionT expression, | 2860 // A TemplateLiteral is made up of 0 or more TEMPLATE_SPAN tokens (literal |
2819 Scanner::Location location, const char* message, bool* ok) { | 2861 // text followed by a substitution expression), finalized by a single |
| 2862 // TEMPLATE_TAIL. |
| 2863 // |
| 2864 // In terms of draft language, TEMPLATE_SPAN may be either the TemplateHead or |
| 2865 // TemplateMiddle productions, while TEMPLATE_TAIL is either TemplateTail, or |
| 2866 // NoSubstitutionTemplate. |
| 2867 // |
| 2868 // When parsing a TemplateLiteral, we must have scanned either an initial |
| 2869 // TEMPLATE_SPAN, or a TEMPLATE_TAIL. |
| 2870 CHECK(peek() == Token::TEMPLATE_SPAN || peek() == Token::TEMPLATE_TAIL); |
| 2871 |
| 2872 // If we reach a TEMPLATE_TAIL first, we are parsing a NoSubstitutionTemplate. |
| 2873 // In this case we may simply consume the token and build a template with a |
| 2874 // single TEMPLATE_SPAN and no expressions. |
| 2875 if (peek() == Token::TEMPLATE_TAIL) { |
| 2876 Consume(Token::TEMPLATE_TAIL); |
| 2877 int pos = position(); |
| 2878 typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos); |
| 2879 Traits::AddTemplateSpan(&ts, true); |
| 2880 return Traits::CloseTemplateLiteral(&ts, start, tag); |
| 2881 } |
| 2882 |
| 2883 Consume(Token::TEMPLATE_SPAN); |
| 2884 int pos = position(); |
| 2885 typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos); |
| 2886 Traits::AddTemplateSpan(&ts, false); |
| 2887 Token::Value next; |
| 2888 |
| 2889 // If we open with a TEMPLATE_SPAN, we must scan the subsequent expression, |
| 2890 // and repeat if the following token is a TEMPLATE_SPAN as well (in this |
| 2891 // case, representing a TemplateMiddle). |
| 2892 |
| 2893 do { |
| 2894 next = peek(); |
| 2895 if (!next) { |
| 2896 ReportMessageAt(Scanner::Location(start, peek_position()), |
| 2897 "unterminated_template"); |
| 2898 *ok = false; |
| 2899 return Traits::EmptyExpression(); |
| 2900 } |
| 2901 |
| 2902 int pos = peek_position(); |
| 2903 ExpressionT expression = this->ParseExpression(true, CHECK_OK); |
| 2904 Traits::AddTemplateExpression(&ts, expression); |
| 2905 |
| 2906 if (peek() != Token::RBRACE) { |
| 2907 ReportMessageAt(Scanner::Location(pos, peek_position()), |
| 2908 "unterminated_template_expr"); |
| 2909 *ok = false; |
| 2910 return Traits::EmptyExpression(); |
| 2911 } |
| 2912 |
| 2913 // If we didn't die parsing that expression, our next token should be a |
| 2914 // TEMPLATE_SPAN or TEMPLATE_TAIL. |
| 2915 next = scanner()->ScanTemplateSpan(); |
| 2916 Next(); |
| 2917 |
| 2918 if (!next) { |
| 2919 ReportMessageAt(Scanner::Location(start, position()), |
| 2920 "unterminated_template"); |
| 2921 *ok = false; |
| 2922 return Traits::EmptyExpression(); |
| 2923 } |
| 2924 |
| 2925 Traits::AddTemplateSpan(&ts, next == Token::TEMPLATE_TAIL); |
| 2926 } while (next == Token::TEMPLATE_SPAN); |
| 2927 |
| 2928 DCHECK_EQ(next, Token::TEMPLATE_TAIL); |
| 2929 // Once we've reached a TEMPLATE_TAIL, we can close the TemplateLiteral. |
| 2930 return Traits::CloseTemplateLiteral(&ts, start, tag); |
| 2931 } |
| 2932 |
| 2933 |
| 2934 template <typename Traits> |
| 2935 typename ParserBase<Traits>::ExpressionT ParserBase< |
| 2936 Traits>::CheckAndRewriteReferenceExpression(ExpressionT expression, |
| 2937 Scanner::Location location, |
| 2938 const char* message, bool* ok) { |
2820 if (strict_mode() == STRICT && this->IsIdentifier(expression) && | 2939 if (strict_mode() == STRICT && this->IsIdentifier(expression) && |
2821 this->IsEvalOrArguments(this->AsIdentifier(expression))) { | 2940 this->IsEvalOrArguments(this->AsIdentifier(expression))) { |
2822 this->ReportMessageAt(location, "strict_eval_arguments", false); | 2941 this->ReportMessageAt(location, "strict_eval_arguments", false); |
2823 *ok = false; | 2942 *ok = false; |
2824 return this->EmptyExpression(); | 2943 return this->EmptyExpression(); |
2825 } else if (expression->IsValidReferenceExpression()) { | 2944 } else if (expression->IsValidReferenceExpression()) { |
2826 return expression; | 2945 return expression; |
2827 } else if (expression->IsCall()) { | 2946 } else if (expression->IsCall()) { |
2828 // If it is a call, make it a runtime error for legacy web compatibility. | 2947 // If it is a call, make it a runtime error for legacy web compatibility. |
2829 // Rewrite `expr' to `expr[throw ReferenceError]'. | 2948 // Rewrite `expr' to `expr[throw ReferenceError]'. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2864 DCHECK(IsAccessorAccessorConflict(old_type, type)); | 2983 DCHECK(IsAccessorAccessorConflict(old_type, type)); |
2865 // Both accessors of the same type. | 2984 // Both accessors of the same type. |
2866 parser()->ReportMessage("accessor_get_set"); | 2985 parser()->ReportMessage("accessor_get_set"); |
2867 } | 2986 } |
2868 *ok = false; | 2987 *ok = false; |
2869 } | 2988 } |
2870 } | 2989 } |
2871 } } // v8::internal | 2990 } } // v8::internal |
2872 | 2991 |
2873 #endif // V8_PREPARSER_H | 2992 #endif // V8_PREPARSER_H |
OLD | NEW |