Chromium Code Reviews| 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 AddTemplateSpan(); | |
| 503 void AddTemplateExpression(ExpressionT); | |
| 497 | 504 |
| 498 // Checks if the expression is a valid reference expression (e.g., on the | 505 // 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, | 506 // 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. | 507 // we allow calls for web compatibility and rewrite them to a runtime throw. |
| 501 ExpressionT CheckAndRewriteReferenceExpression( | 508 ExpressionT CheckAndRewriteReferenceExpression( |
| 502 ExpressionT expression, | 509 ExpressionT expression, |
| 503 Scanner::Location location, const char* message, bool* ok); | 510 Scanner::Location location, const char* message, bool* ok); |
| 504 | 511 |
| 505 // Used to detect duplicates in object literals. Each of the values | 512 // Used to detect duplicates in object literals. Each of the values |
| 506 // kGetterProperty, kSetterProperty and kValueProperty represents | 513 // kGetterProperty, kSetterProperty and kValueProperty represents |
| (...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1378 // Utility functions | 1385 // Utility functions |
| 1379 int DeclareArrowParametersFromExpression(PreParserExpression expression, | 1386 int DeclareArrowParametersFromExpression(PreParserExpression expression, |
| 1380 PreParserScope* scope, | 1387 PreParserScope* scope, |
| 1381 Scanner::Location* dupe_loc, | 1388 Scanner::Location* dupe_loc, |
| 1382 bool* ok) { | 1389 bool* ok) { |
| 1383 // TODO(aperez): Detect duplicated identifiers in paramlists. | 1390 // TODO(aperez): Detect duplicated identifiers in paramlists. |
| 1384 *ok = expression.IsValidArrowParamList(); | 1391 *ok = expression.IsValidArrowParamList(); |
| 1385 return 0; | 1392 return 0; |
| 1386 } | 1393 } |
| 1387 | 1394 |
| 1395 struct TemplateLiteralState {}; | |
| 1396 | |
| 1397 TemplateLiteralState OpenTemplateLiteral(int pos) { | |
| 1398 return TemplateLiteralState(); | |
| 1399 } | |
| 1400 void AddTemplateSpan(TemplateLiteralState* state) { USE(state); } | |
|
marja
2014/11/11 09:47:23
Shorter (here and below):
void AddTemplateSpan(Te
| |
| 1401 void AddTemplateExpression(TemplateLiteralState* state, | |
| 1402 PreParserExpression expression) { | |
| 1403 USE(state); | |
| 1404 USE(expression); | |
| 1405 } | |
| 1406 PreParserExpression CloseTemplateLiteral(TemplateLiteralState* state, | |
| 1407 int start, PreParserExpression tag) { | |
| 1408 USE(state); | |
| 1409 USE(start); | |
| 1410 USE(tag); | |
| 1411 return EmptyExpression(); | |
| 1412 } | |
| 1413 PreParserExpression NoTemplateTag() { | |
| 1414 return PreParserExpression::Default(); | |
| 1415 } | |
| 1388 static AstValueFactory* ast_value_factory() { return NULL; } | 1416 static AstValueFactory* ast_value_factory() { return NULL; } |
| 1389 | 1417 |
| 1390 void CheckConflictingVarDeclarations(PreParserScope scope, bool* ok) {} | 1418 void CheckConflictingVarDeclarations(PreParserScope scope, bool* ok) {} |
| 1391 | 1419 |
| 1392 // Temporary glue; these functions will move to ParserBase. | 1420 // Temporary glue; these functions will move to ParserBase. |
| 1393 PreParserExpression ParseV8Intrinsic(bool* ok); | 1421 PreParserExpression ParseV8Intrinsic(bool* ok); |
| 1394 PreParserExpression ParseFunctionLiteral( | 1422 PreParserExpression ParseFunctionLiteral( |
| 1395 PreParserIdentifier name, Scanner::Location function_name_location, | 1423 PreParserIdentifier name, Scanner::Location function_name_location, |
| 1396 bool name_is_strict_reserved, FunctionKind kind, | 1424 bool name_is_strict_reserved, FunctionKind kind, |
| 1397 int function_token_position, FunctionLiteral::FunctionType type, | 1425 int function_token_position, FunctionLiteral::FunctionType type, |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1748 // 'true' | 1776 // 'true' |
| 1749 // 'false' | 1777 // 'false' |
| 1750 // Identifier | 1778 // Identifier |
| 1751 // Number | 1779 // Number |
| 1752 // String | 1780 // String |
| 1753 // ArrayLiteral | 1781 // ArrayLiteral |
| 1754 // ObjectLiteral | 1782 // ObjectLiteral |
| 1755 // RegExpLiteral | 1783 // RegExpLiteral |
| 1756 // ClassLiteral | 1784 // ClassLiteral |
| 1757 // '(' Expression ')' | 1785 // '(' Expression ')' |
| 1786 // TemplateLiteral | |
| 1758 | 1787 |
| 1759 int pos = peek_position(); | 1788 int pos = peek_position(); |
| 1760 ExpressionT result = this->EmptyExpression(); | 1789 ExpressionT result = this->EmptyExpression(); |
| 1761 Token::Value token = peek(); | 1790 Token::Value token = peek(); |
| 1762 switch (token) { | 1791 switch (token) { |
| 1763 case Token::THIS: { | 1792 case Token::THIS: { |
| 1764 Consume(Token::THIS); | 1793 Consume(Token::THIS); |
| 1765 scope_->RecordThisUsage(); | 1794 scope_->RecordThisUsage(); |
| 1766 result = this->ThisExpression(scope_, factory()); | 1795 result = this->ThisExpression(scope_, factory()); |
| 1767 break; | 1796 break; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1836 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, | 1865 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, |
| 1837 CHECK_OK); | 1866 CHECK_OK); |
| 1838 class_name_location = scanner()->location(); | 1867 class_name_location = scanner()->location(); |
| 1839 } | 1868 } |
| 1840 result = this->ParseClassLiteral(name, class_name_location, | 1869 result = this->ParseClassLiteral(name, class_name_location, |
| 1841 is_strict_reserved_name, | 1870 is_strict_reserved_name, |
| 1842 class_token_position, CHECK_OK); | 1871 class_token_position, CHECK_OK); |
| 1843 break; | 1872 break; |
| 1844 } | 1873 } |
| 1845 | 1874 |
| 1875 case Token::TEMPLATE_SPAN: | |
| 1876 case Token::TEMPLATE_TAIL: | |
| 1877 result = this->ParseTemplateLiteral(Traits::NoTemplateTag(), pos, | |
| 1878 CHECK_OK); | |
| 1879 break; | |
| 1880 | |
| 1846 case Token::MOD: | 1881 case Token::MOD: |
| 1847 if (allow_natives_syntax() || extension_ != NULL) { | 1882 if (allow_natives_syntax() || extension_ != NULL) { |
| 1848 result = this->ParseV8Intrinsic(CHECK_OK); | 1883 result = this->ParseV8Intrinsic(CHECK_OK); |
| 1849 break; | 1884 break; |
| 1850 } | 1885 } |
| 1851 // If we're not allowing special syntax we fall-through to the | 1886 // If we're not allowing special syntax we fall-through to the |
| 1852 // default case. | 1887 // default case. |
| 1853 | 1888 |
| 1854 default: { | 1889 default: { |
| 1855 Next(); | 1890 Next(); |
| (...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2459 // direct eval calls. These calls are all of the form eval(...), with | 2494 // direct eval calls. These calls are all of the form eval(...), with |
| 2460 // no explicit receiver. | 2495 // no explicit receiver. |
| 2461 // These calls are marked as potentially direct eval calls. Whether | 2496 // These calls are marked as potentially direct eval calls. Whether |
| 2462 // they are actually direct calls to eval is determined at run time. | 2497 // they are actually direct calls to eval is determined at run time. |
| 2463 this->CheckPossibleEvalCall(result, scope_); | 2498 this->CheckPossibleEvalCall(result, scope_); |
| 2464 result = factory()->NewCall(result, args, pos); | 2499 result = factory()->NewCall(result, args, pos); |
| 2465 if (fni_ != NULL) fni_->RemoveLastFunction(); | 2500 if (fni_ != NULL) fni_->RemoveLastFunction(); |
| 2466 break; | 2501 break; |
| 2467 } | 2502 } |
| 2468 | 2503 |
| 2504 case Token::TEMPLATE_SPAN: | |
| 2505 case Token::TEMPLATE_TAIL: { | |
| 2506 int pos; | |
| 2507 if (scanner()->current_token() == Token::IDENTIFIER) { | |
| 2508 pos = position(); | |
| 2509 } else { | |
| 2510 pos = peek_position(); | |
| 2511 if (result->IsFunctionLiteral() && mode() == PARSE_EAGERLY) { | |
| 2512 result->AsFunctionLiteral()->set_parenthesized(); | |
| 2513 } | |
| 2514 } | |
| 2515 result = ParseTemplateLiteral(result, pos, CHECK_OK); | |
| 2516 break; | |
| 2517 } | |
| 2518 | |
| 2469 case Token::PERIOD: { | 2519 case Token::PERIOD: { |
| 2470 Consume(Token::PERIOD); | 2520 Consume(Token::PERIOD); |
| 2471 int pos = position(); | 2521 int pos = position(); |
| 2472 IdentifierT name = ParseIdentifierName(CHECK_OK); | 2522 IdentifierT name = ParseIdentifierName(CHECK_OK); |
| 2473 result = factory()->NewProperty( | 2523 result = factory()->NewProperty( |
| 2474 result, factory()->NewStringLiteral(name, pos), pos); | 2524 result, factory()->NewStringLiteral(name, pos), pos); |
| 2475 if (fni_ != NULL) this->PushLiteralName(fni_, name); | 2525 if (fni_ != NULL) this->PushLiteralName(fni_, name); |
| 2476 break; | 2526 break; |
| 2477 } | 2527 } |
| 2478 | 2528 |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2804 this->DefaultConstructor(has_extends, scope_, pos, end_pos + 1); | 2854 this->DefaultConstructor(has_extends, scope_, pos, end_pos + 1); |
| 2805 } | 2855 } |
| 2806 | 2856 |
| 2807 return this->ClassExpression(name, extends, constructor, properties, pos, | 2857 return this->ClassExpression(name, extends, constructor, properties, pos, |
| 2808 end_pos + 1, factory()); | 2858 end_pos + 1, factory()); |
| 2809 } | 2859 } |
| 2810 | 2860 |
| 2811 | 2861 |
| 2812 template <typename Traits> | 2862 template <typename Traits> |
| 2813 typename ParserBase<Traits>::ExpressionT | 2863 typename ParserBase<Traits>::ExpressionT |
| 2864 ParserBase<Traits>::ParseTemplateLiteral(ExpressionT tag, int start, bool* ok) { | |
| 2865 // A TemplateLiteral is made up of 0 or more TEMPLATE_SPAN tokens (literal | |
| 2866 // text followed by a substitution expression), finalized by a single | |
| 2867 // TEMPLATE_TAIL. | |
| 2868 // | |
| 2869 // In terms of draft language, TEMPLATE_SPAN may be either the TemplateHead or | |
| 2870 // TemplateMiddle productions, while TEMPLATE_TAIL is either TemplateTail, or | |
| 2871 // NoSubstitutionTemplate. | |
| 2872 // | |
| 2873 // When parsing a TemplateLiteral, we must have scanned either an initial | |
| 2874 // TEMPLATE_SPAN, or a TEMPLATE_TAIL. | |
| 2875 CHECK(peek() == Token::TEMPLATE_SPAN || peek() == Token::TEMPLATE_TAIL); | |
| 2876 | |
| 2877 // Add TV / TRV | |
|
marja
2014/11/11 09:47:24
This comment is confusing... which part is adding
caitp (gmail)
2014/11/11 13:59:29
I think that's a stray comment, doesn't look like
| |
| 2878 if (peek() == Token::TEMPLATE_SPAN) { | |
| 2879 Consume(Token::TEMPLATE_SPAN); | |
| 2880 int pos = position(); | |
| 2881 typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos); | |
| 2882 Traits::AddTemplateSpan(&ts); | |
| 2883 | |
| 2884 // If we open with a TEMPLATE_SPAN, we must scan the subsequent expression, | |
| 2885 // and repeat if the following token is a TEMPLATE_SPAN as well (in this | |
| 2886 // case, representing a TemplateMiddle). | |
| 2887 for (;;) { | |
|
marja
2014/11/11 09:47:23
Style nit: while(true) seems to be more common.
| |
| 2888 Token::Value next = peek(); | |
| 2889 if (next < 0) { | |
| 2890 ReportMessage("unterminated_template"); | |
| 2891 *ok = false; | |
| 2892 return Traits::EmptyExpression(); | |
| 2893 } | |
| 2894 | |
| 2895 // Parse an Expression | |
|
marja
2014/11/11 09:47:23
Nit: this comment is not needed; it's clear that i
| |
| 2896 ExpressionT expression = this->ParseExpression(false, CHECK_OK); | |
| 2897 Traits::AddTemplateExpression(&ts, expression); | |
| 2898 | |
| 2899 // If we didn't die parsing that expression, our next token should be a | |
| 2900 // TEMPLATE_SPAN or TEMPLATE_TAIL. | |
| 2901 next = scanner()->ScanTemplateSpan(); | |
| 2902 Next(); | |
| 2903 | |
| 2904 if (next == Token::ILLEGAL || next < 0) { | |
| 2905 ReportMessage("unterminated_template"); | |
| 2906 *ok = false; | |
| 2907 return Traits::EmptyExpression(); | |
| 2908 } | |
| 2909 | |
| 2910 CHECK(next == Token::TEMPLATE_SPAN || next == Token::TEMPLATE_TAIL); | |
| 2911 Traits::AddTemplateSpan(&ts); | |
| 2912 | |
| 2913 if (next == Token::TEMPLATE_TAIL) { | |
| 2914 // Once we've reached a TEMPLATE_TAIL, we can close the TemplateLiteral. | |
| 2915 return Traits::CloseTemplateLiteral(&ts, start, tag); | |
| 2916 } | |
| 2917 } | |
| 2918 DCHECK(false); | |
| 2919 } | |
| 2920 | |
| 2921 // If we reach a TEMPLATE_TAIL first, we are parsing a NoSubstitutionTemplate. | |
| 2922 // In this case we may simply consume the token and build a template with a | |
| 2923 // single TEMPLATE_SPAN and no expressions. | |
| 2924 Consume(Token::TEMPLATE_TAIL); | |
| 2925 int pos = position(); | |
| 2926 typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos); | |
| 2927 Traits::AddTemplateSpan(&ts); | |
| 2928 return Traits::CloseTemplateLiteral(&ts, start, tag); | |
| 2929 } | |
| 2930 | |
| 2931 | |
| 2932 template <typename Traits> | |
| 2933 typename ParserBase<Traits>::ExpressionT | |
| 2814 ParserBase<Traits>::CheckAndRewriteReferenceExpression( | 2934 ParserBase<Traits>::CheckAndRewriteReferenceExpression( |
| 2815 ExpressionT expression, | 2935 ExpressionT expression, |
| 2816 Scanner::Location location, const char* message, bool* ok) { | 2936 Scanner::Location location, const char* message, bool* ok) { |
| 2817 if (strict_mode() == STRICT && this->IsIdentifier(expression) && | 2937 if (strict_mode() == STRICT && this->IsIdentifier(expression) && |
| 2818 this->IsEvalOrArguments(this->AsIdentifier(expression))) { | 2938 this->IsEvalOrArguments(this->AsIdentifier(expression))) { |
| 2819 this->ReportMessageAt(location, "strict_eval_arguments", false); | 2939 this->ReportMessageAt(location, "strict_eval_arguments", false); |
| 2820 *ok = false; | 2940 *ok = false; |
| 2821 return this->EmptyExpression(); | 2941 return this->EmptyExpression(); |
| 2822 } else if (expression->IsValidReferenceExpression()) { | 2942 } else if (expression->IsValidReferenceExpression()) { |
| 2823 return expression; | 2943 return expression; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2861 DCHECK(IsAccessorAccessorConflict(old_type, type)); | 2981 DCHECK(IsAccessorAccessorConflict(old_type, type)); |
| 2862 // Both accessors of the same type. | 2982 // Both accessors of the same type. |
| 2863 parser()->ReportMessage("accessor_get_set"); | 2983 parser()->ReportMessage("accessor_get_set"); |
| 2864 } | 2984 } |
| 2865 *ok = false; | 2985 *ok = false; |
| 2866 } | 2986 } |
| 2867 } | 2987 } |
| 2868 } } // v8::internal | 2988 } } // v8::internal |
| 2869 | 2989 |
| 2870 #endif // V8_PREPARSER_H | 2990 #endif // V8_PREPARSER_H |
| OLD | NEW |