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

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: Clang-formatted 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
« src/parser.cc ('K') | « src/parser.cc ('k') | src/scanner.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 872 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
OLDNEW
« src/parser.cc ('K') | « src/parser.cc ('k') | src/scanner.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698