Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(100)

Side by Side Diff: src/preparser.h

Issue 663683006: Implement ES6 Template Literals (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Remove kTemplateLiteral bailout-reason Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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 871 matching lines...) Expand 10 before | Expand all | Expand 10 after
1378 // Utility functions 1384 // Utility functions
1379 int DeclareArrowParametersFromExpression(PreParserExpression expression, 1385 int DeclareArrowParametersFromExpression(PreParserExpression expression,
1380 PreParserScope* scope, 1386 PreParserScope* scope,
1381 Scanner::Location* dupe_loc, 1387 Scanner::Location* dupe_loc,
1382 bool* ok) { 1388 bool* ok) {
1383 // TODO(aperez): Detect duplicated identifiers in paramlists. 1389 // TODO(aperez): Detect duplicated identifiers in paramlists.
1384 *ok = expression.IsValidArrowParamList(); 1390 *ok = expression.IsValidArrowParamList();
1385 return 0; 1391 return 0;
1386 } 1392 }
1387 1393
1394 struct TemplateLiteralState {};
1395
1396 TemplateLiteralState OpenTemplateLiteral(int pos) {
1397 return TemplateLiteralState();
1398 }
1399 void AddTemplateSpan(TemplateLiteralState*, bool) {}
1400 void AddTemplateExpression(TemplateLiteralState*, PreParserExpression) {}
1401 PreParserExpression CloseTemplateLiteral(TemplateLiteralState*, int,
1402 PreParserExpression) {
1403 return EmptyExpression();
1404 }
1405 PreParserExpression NoTemplateTag() {
1406 return PreParserExpression::Default();
1407 }
1388 static AstValueFactory* ast_value_factory() { return NULL; } 1408 static AstValueFactory* ast_value_factory() { return NULL; }
1389 1409
1390 void CheckConflictingVarDeclarations(PreParserScope scope, bool* ok) {} 1410 void CheckConflictingVarDeclarations(PreParserScope scope, bool* ok) {}
1391 1411
1392 // Temporary glue; these functions will move to ParserBase. 1412 // Temporary glue; these functions will move to ParserBase.
1393 PreParserExpression ParseV8Intrinsic(bool* ok); 1413 PreParserExpression ParseV8Intrinsic(bool* ok);
1394 PreParserExpression ParseFunctionLiteral( 1414 PreParserExpression ParseFunctionLiteral(
1395 PreParserIdentifier name, Scanner::Location function_name_location, 1415 PreParserIdentifier name, Scanner::Location function_name_location,
1396 bool name_is_strict_reserved, FunctionKind kind, 1416 bool name_is_strict_reserved, FunctionKind kind,
1397 int function_token_position, FunctionLiteral::FunctionType type, 1417 int function_token_position, FunctionLiteral::FunctionType type,
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
1748 // 'true' 1768 // 'true'
1749 // 'false' 1769 // 'false'
1750 // Identifier 1770 // Identifier
1751 // Number 1771 // Number
1752 // String 1772 // String
1753 // ArrayLiteral 1773 // ArrayLiteral
1754 // ObjectLiteral 1774 // ObjectLiteral
1755 // RegExpLiteral 1775 // RegExpLiteral
1756 // ClassLiteral 1776 // ClassLiteral
1757 // '(' Expression ')' 1777 // '(' Expression ')'
1778 // TemplateLiteral
1758 1779
1759 int pos = peek_position(); 1780 int pos = peek_position();
1760 ExpressionT result = this->EmptyExpression(); 1781 ExpressionT result = this->EmptyExpression();
1761 Token::Value token = peek(); 1782 Token::Value token = peek();
1762 switch (token) { 1783 switch (token) {
1763 case Token::THIS: { 1784 case Token::THIS: {
1764 Consume(Token::THIS); 1785 Consume(Token::THIS);
1765 scope_->RecordThisUsage(); 1786 scope_->RecordThisUsage();
1766 result = this->ThisExpression(scope_, factory()); 1787 result = this->ThisExpression(scope_, factory());
1767 break; 1788 break;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1836 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, 1857 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
1837 CHECK_OK); 1858 CHECK_OK);
1838 class_name_location = scanner()->location(); 1859 class_name_location = scanner()->location();
1839 } 1860 }
1840 result = this->ParseClassLiteral(name, class_name_location, 1861 result = this->ParseClassLiteral(name, class_name_location,
1841 is_strict_reserved_name, 1862 is_strict_reserved_name,
1842 class_token_position, CHECK_OK); 1863 class_token_position, CHECK_OK);
1843 break; 1864 break;
1844 } 1865 }
1845 1866
1867 case Token::TEMPLATE_SPAN:
1868 case Token::TEMPLATE_TAIL:
1869 result = this->ParseTemplateLiteral(Traits::NoTemplateTag(), pos,
1870 CHECK_OK);
1871 break;
1872
1846 case Token::MOD: 1873 case Token::MOD:
1847 if (allow_natives_syntax() || extension_ != NULL) { 1874 if (allow_natives_syntax() || extension_ != NULL) {
1848 result = this->ParseV8Intrinsic(CHECK_OK); 1875 result = this->ParseV8Intrinsic(CHECK_OK);
1849 break; 1876 break;
1850 } 1877 }
1851 // If we're not allowing special syntax we fall-through to the 1878 // If we're not allowing special syntax we fall-through to the
1852 // default case. 1879 // default case.
1853 1880
1854 default: { 1881 default: {
1855 Next(); 1882 Next();
(...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after
2459 // direct eval calls. These calls are all of the form eval(...), with 2486 // direct eval calls. These calls are all of the form eval(...), with
2460 // no explicit receiver. 2487 // no explicit receiver.
2461 // These calls are marked as potentially direct eval calls. Whether 2488 // These calls are marked as potentially direct eval calls. Whether
2462 // they are actually direct calls to eval is determined at run time. 2489 // they are actually direct calls to eval is determined at run time.
2463 this->CheckPossibleEvalCall(result, scope_); 2490 this->CheckPossibleEvalCall(result, scope_);
2464 result = factory()->NewCall(result, args, pos); 2491 result = factory()->NewCall(result, args, pos);
2465 if (fni_ != NULL) fni_->RemoveLastFunction(); 2492 if (fni_ != NULL) fni_->RemoveLastFunction();
2466 break; 2493 break;
2467 } 2494 }
2468 2495
2496 case Token::TEMPLATE_SPAN:
2497 case Token::TEMPLATE_TAIL: {
2498 int pos;
2499 if (scanner()->current_token() == Token::IDENTIFIER) {
2500 pos = position();
2501 } else {
2502 pos = peek_position();
2503 if (result->IsFunctionLiteral() && mode() == PARSE_EAGERLY) {
2504 // If the tag function looks like an IIFE, set_parenthesized() to
2505 // force eager compilation.
2506 result->AsFunctionLiteral()->set_parenthesized();
2507 }
2508 }
2509 result = ParseTemplateLiteral(result, pos, CHECK_OK);
2510 break;
2511 }
2512
2469 case Token::PERIOD: { 2513 case Token::PERIOD: {
2470 Consume(Token::PERIOD); 2514 Consume(Token::PERIOD);
2471 int pos = position(); 2515 int pos = position();
2472 IdentifierT name = ParseIdentifierName(CHECK_OK); 2516 IdentifierT name = ParseIdentifierName(CHECK_OK);
2473 result = factory()->NewProperty( 2517 result = factory()->NewProperty(
2474 result, factory()->NewStringLiteral(name, pos), pos); 2518 result, factory()->NewStringLiteral(name, pos), pos);
2475 if (fni_ != NULL) this->PushLiteralName(fni_, name); 2519 if (fni_ != NULL) this->PushLiteralName(fni_, name);
2476 break; 2520 break;
2477 } 2521 }
2478 2522
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
2804 this->DefaultConstructor(has_extends, scope_, pos, end_pos + 1); 2848 this->DefaultConstructor(has_extends, scope_, pos, end_pos + 1);
2805 } 2849 }
2806 2850
2807 return this->ClassExpression(name, extends, constructor, properties, pos, 2851 return this->ClassExpression(name, extends, constructor, properties, pos,
2808 end_pos + 1, factory()); 2852 end_pos + 1, factory());
2809 } 2853 }
2810 2854
2811 2855
2812 template <typename Traits> 2856 template <typename Traits>
2813 typename ParserBase<Traits>::ExpressionT 2857 typename ParserBase<Traits>::ExpressionT
2858 ParserBase<Traits>::ParseTemplateLiteral(ExpressionT tag, int start, bool* ok) {
2859 // A TemplateLiteral is made up of 0 or more TEMPLATE_SPAN tokens (literal
2860 // text followed by a substitution expression), finalized by a single
2861 // TEMPLATE_TAIL.
2862 //
2863 // In terms of draft language, TEMPLATE_SPAN may be either the TemplateHead or
2864 // TemplateMiddle productions, while TEMPLATE_TAIL is either TemplateTail, or
2865 // NoSubstitutionTemplate.
2866 //
2867 // When parsing a TemplateLiteral, we must have scanned either an initial
2868 // TEMPLATE_SPAN, or a TEMPLATE_TAIL.
2869 CHECK(peek() == Token::TEMPLATE_SPAN || peek() == Token::TEMPLATE_TAIL);
2870
2871 if (peek() == Token::TEMPLATE_SPAN) {
2872 Consume(Token::TEMPLATE_SPAN);
2873 int pos = position();
2874 typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos);
2875 Traits::AddTemplateSpan(&ts, false);
2876
2877 // If we open with a TEMPLATE_SPAN, we must scan the subsequent expression,
2878 // and repeat if the following token is a TEMPLATE_SPAN as well (in this
2879 // case, representing a TemplateMiddle).
2880 while (true) {
2881 Token::Value next = peek();
2882 if (next < 0) {
2883 ReportMessage("unterminated_template");
2884 *ok = false;
2885 return Traits::EmptyExpression();
2886 }
2887
2888 ExpressionT expression = this->ParseExpression(false, CHECK_OK);
2889 Traits::AddTemplateExpression(&ts, expression);
2890
2891 // If we didn't die parsing that expression, our next token should be a
2892 // TEMPLATE_SPAN or TEMPLATE_TAIL.
2893 next = scanner()->ScanTemplateSpan();
2894 Next();
2895
2896 if (next == Token::ILLEGAL || next < 0) {
2897 ReportMessage("unterminated_template");
2898 *ok = false;
2899 return Traits::EmptyExpression();
2900 }
2901
2902 CHECK(next == Token::TEMPLATE_SPAN || next == Token::TEMPLATE_TAIL);
2903 Traits::AddTemplateSpan(&ts, next == Token::TEMPLATE_TAIL);
2904
2905 if (next == Token::TEMPLATE_TAIL) {
2906 // Once we've reached a TEMPLATE_TAIL, we can close the TemplateLiteral.
2907 return Traits::CloseTemplateLiteral(&ts, start, tag);
2908 }
2909 }
2910 DCHECK(false);
arv (Not doing code reviews) 2014/11/11 17:15:15 UNREACHABLE(); But maybe change it to: DCHECK_EQ
2911 }
2912
2913 // If we reach a TEMPLATE_TAIL first, we are parsing a NoSubstitutionTemplate.
2914 // In this case we may simply consume the token and build a template with a
2915 // single TEMPLATE_SPAN and no expressions.
2916 Consume(Token::TEMPLATE_TAIL);
2917 int pos = position();
2918 typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos);
2919 Traits::AddTemplateSpan(&ts, true);
2920 return Traits::CloseTemplateLiteral(&ts, start, tag);
2921 }
2922
2923
2924 template <typename Traits>
2925 typename ParserBase<Traits>::ExpressionT
2814 ParserBase<Traits>::CheckAndRewriteReferenceExpression( 2926 ParserBase<Traits>::CheckAndRewriteReferenceExpression(
2815 ExpressionT expression, 2927 ExpressionT expression,
2816 Scanner::Location location, const char* message, bool* ok) { 2928 Scanner::Location location, const char* message, bool* ok) {
2817 if (strict_mode() == STRICT && this->IsIdentifier(expression) && 2929 if (strict_mode() == STRICT && this->IsIdentifier(expression) &&
2818 this->IsEvalOrArguments(this->AsIdentifier(expression))) { 2930 this->IsEvalOrArguments(this->AsIdentifier(expression))) {
2819 this->ReportMessageAt(location, "strict_eval_arguments", false); 2931 this->ReportMessageAt(location, "strict_eval_arguments", false);
2820 *ok = false; 2932 *ok = false;
2821 return this->EmptyExpression(); 2933 return this->EmptyExpression();
2822 } else if (expression->IsValidReferenceExpression()) { 2934 } else if (expression->IsValidReferenceExpression()) {
2823 return expression; 2935 return expression;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
2861 DCHECK(IsAccessorAccessorConflict(old_type, type)); 2973 DCHECK(IsAccessorAccessorConflict(old_type, type));
2862 // Both accessors of the same type. 2974 // Both accessors of the same type.
2863 parser()->ReportMessage("accessor_get_set"); 2975 parser()->ReportMessage("accessor_get_set");
2864 } 2976 }
2865 *ok = false; 2977 *ok = false;
2866 } 2978 }
2867 } 2979 }
2868 } } // v8::internal 2980 } } // v8::internal
2869 2981
2870 #endif // V8_PREPARSER_H 2982 #endif // V8_PREPARSER_H
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698