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

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: Even better static error reporting 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 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() {
1407 return PreParserExpression::Default();
1408 }
1389 static AstValueFactory* ast_value_factory() { return NULL; } 1409 static AstValueFactory* ast_value_factory() { return NULL; }
1390 1410
1391 void CheckConflictingVarDeclarations(PreParserScope scope, bool* ok) {} 1411 void CheckConflictingVarDeclarations(PreParserScope scope, bool* ok) {}
1392 1412
1393 // Temporary glue; these functions will move to ParserBase. 1413 // Temporary glue; these functions will move to ParserBase.
1394 PreParserExpression ParseV8Intrinsic(bool* ok); 1414 PreParserExpression ParseV8Intrinsic(bool* ok);
1395 PreParserExpression ParseFunctionLiteral( 1415 PreParserExpression ParseFunctionLiteral(
1396 PreParserIdentifier name, Scanner::Location function_name_location, 1416 PreParserIdentifier name, Scanner::Location function_name_location,
1397 bool name_is_strict_reserved, FunctionKind kind, 1417 bool name_is_strict_reserved, FunctionKind kind,
1398 int function_token_position, FunctionLiteral::FunctionType type, 1418 int function_token_position, FunctionLiteral::FunctionType type,
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
1749 // 'true' 1769 // 'true'
1750 // 'false' 1770 // 'false'
1751 // Identifier 1771 // Identifier
1752 // Number 1772 // Number
1753 // String 1773 // String
1754 // ArrayLiteral 1774 // ArrayLiteral
1755 // ObjectLiteral 1775 // ObjectLiteral
1756 // RegExpLiteral 1776 // RegExpLiteral
1757 // ClassLiteral 1777 // ClassLiteral
1758 // '(' Expression ')' 1778 // '(' Expression ')'
1779 // TemplateLiteral
1759 1780
1760 int pos = peek_position(); 1781 int pos = peek_position();
1761 ExpressionT result = this->EmptyExpression(); 1782 ExpressionT result = this->EmptyExpression();
1762 Token::Value token = peek(); 1783 Token::Value token = peek();
1763 switch (token) { 1784 switch (token) {
1764 case Token::THIS: { 1785 case Token::THIS: {
1765 Consume(Token::THIS); 1786 Consume(Token::THIS);
1766 scope_->RecordThisUsage(); 1787 scope_->RecordThisUsage();
1767 result = this->ThisExpression(scope_, factory()); 1788 result = this->ThisExpression(scope_, factory());
1768 break; 1789 break;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1837 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, 1858 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
1838 CHECK_OK); 1859 CHECK_OK);
1839 class_name_location = scanner()->location(); 1860 class_name_location = scanner()->location();
1840 } 1861 }
1841 result = this->ParseClassLiteral(name, class_name_location, 1862 result = this->ParseClassLiteral(name, class_name_location,
1842 is_strict_reserved_name, 1863 is_strict_reserved_name,
1843 class_token_position, CHECK_OK); 1864 class_token_position, CHECK_OK);
1844 break; 1865 break;
1845 } 1866 }
1846 1867
1868 case Token::TEMPLATE_SPAN:
1869 case Token::TEMPLATE_TAIL:
1870 result = this->ParseTemplateLiteral(Traits::NoTemplateTag(), pos,
1871 CHECK_OK);
1872 break;
1873
1847 case Token::MOD: 1874 case Token::MOD:
1848 if (allow_natives_syntax() || extension_ != NULL) { 1875 if (allow_natives_syntax() || extension_ != NULL) {
1849 result = this->ParseV8Intrinsic(CHECK_OK); 1876 result = this->ParseV8Intrinsic(CHECK_OK);
1850 break; 1877 break;
1851 } 1878 }
1852 // If we're not allowing special syntax we fall-through to the 1879 // If we're not allowing special syntax we fall-through to the
1853 // default case. 1880 // default case.
1854 1881
1855 default: { 1882 default: {
1856 Next(); 1883 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 2487 // direct eval calls. These calls are all of the form eval(...), with
2461 // no explicit receiver. 2488 // no explicit receiver.
2462 // These calls are marked as potentially direct eval calls. Whether 2489 // These calls are marked as potentially direct eval calls. Whether
2463 // they are actually direct calls to eval is determined at run time. 2490 // they are actually direct calls to eval is determined at run time.
2464 this->CheckPossibleEvalCall(result, scope_); 2491 this->CheckPossibleEvalCall(result, scope_);
2465 result = factory()->NewCall(result, args, pos); 2492 result = factory()->NewCall(result, args, pos);
2466 if (fni_ != NULL) fni_->RemoveLastFunction(); 2493 if (fni_ != NULL) fni_->RemoveLastFunction();
2467 break; 2494 break;
2468 } 2495 }
2469 2496
2497 case Token::TEMPLATE_SPAN:
2498 case Token::TEMPLATE_TAIL: {
2499 int pos;
2500 if (scanner()->current_token() == Token::IDENTIFIER) {
2501 pos = position();
2502 } else {
2503 pos = peek_position();
2504 if (result->IsFunctionLiteral() && mode() == PARSE_EAGERLY) {
2505 // If the tag function looks like an IIFE, set_parenthesized() to
2506 // force eager compilation.
2507 result->AsFunctionLiteral()->set_parenthesized();
2508 }
2509 }
2510 result = ParseTemplateLiteral(result, pos, CHECK_OK);
2511 break;
2512 }
2513
2470 case Token::PERIOD: { 2514 case Token::PERIOD: {
2471 Consume(Token::PERIOD); 2515 Consume(Token::PERIOD);
2472 int pos = position(); 2516 int pos = position();
2473 IdentifierT name = ParseIdentifierName(CHECK_OK); 2517 IdentifierT name = ParseIdentifierName(CHECK_OK);
2474 result = factory()->NewProperty( 2518 result = factory()->NewProperty(
2475 result, factory()->NewStringLiteral(name, pos), pos); 2519 result, factory()->NewStringLiteral(name, pos), pos);
2476 if (fni_ != NULL) this->PushLiteralName(fni_, name); 2520 if (fni_ != NULL) this->PushLiteralName(fni_, name);
2477 break; 2521 break;
2478 } 2522 }
2479 2523
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
2807 this->DefaultConstructor(has_extends, scope_, pos, end_pos + 1); 2851 this->DefaultConstructor(has_extends, scope_, pos, end_pos + 1);
2808 } 2852 }
2809 2853
2810 return this->ClassExpression(name, extends, constructor, properties, pos, 2854 return this->ClassExpression(name, extends, constructor, properties, pos,
2811 end_pos + 1, factory()); 2855 end_pos + 1, factory());
2812 } 2856 }
2813 2857
2814 2858
2815 template <typename Traits> 2859 template <typename Traits>
2816 typename ParserBase<Traits>::ExpressionT 2860 typename ParserBase<Traits>::ExpressionT
2861 ParserBase<Traits>::ParseTemplateLiteral(ExpressionT tag, int start, bool* ok) {
2862 // A TemplateLiteral is made up of 0 or more TEMPLATE_SPAN tokens (literal
2863 // text followed by a substitution expression), finalized by a single
2864 // TEMPLATE_TAIL.
2865 //
2866 // In terms of draft language, TEMPLATE_SPAN may be either the TemplateHead or
2867 // TemplateMiddle productions, while TEMPLATE_TAIL is either TemplateTail, or
2868 // NoSubstitutionTemplate.
2869 //
2870 // When parsing a TemplateLiteral, we must have scanned either an initial
2871 // TEMPLATE_SPAN, or a TEMPLATE_TAIL.
2872 CHECK(peek() == Token::TEMPLATE_SPAN || peek() == Token::TEMPLATE_TAIL);
2873
2874 if (peek() == Token::TEMPLATE_SPAN) {
2875 Consume(Token::TEMPLATE_SPAN);
2876 int pos = position();
2877 typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos);
2878 Traits::AddTemplateSpan(&ts, false);
2879 Token::Value next;
2880
2881 // If we open with a TEMPLATE_SPAN, we must scan the subsequent expression,
2882 // and repeat if the following token is a TEMPLATE_SPAN as well (in this
2883 // case, representing a TemplateMiddle).
2884
2885 do {
2886 next = peek();
2887 if (!next) {
2888 ReportMessageAt(Scanner::Location(start, peek_position()),
2889 "unterminated_template");
2890 *ok = false;
2891 return Traits::EmptyExpression();
2892 }
2893
2894 int pos = peek_position();
2895 ExpressionT expression = this->ParseExpression(false, CHECK_OK);
2896 Traits::AddTemplateExpression(&ts, expression);
2897
2898 if (peek() != Token::RBRACE) {
2899 ReportMessageAt(Scanner::Location(pos, peek_position()),
2900 "unterminated_template_expr");
2901 *ok = false;
2902 return Traits::EmptyExpression();
2903 }
2904
2905 // If we didn't die parsing that expression, our next token should be a
2906 // TEMPLATE_SPAN or TEMPLATE_TAIL.
2907 next = scanner()->ScanTemplateSpan();
2908 Next();
2909
2910 if (!next) {
2911 ReportMessageAt(Scanner::Location(start, position()),
2912 "unterminated_template");
2913 *ok = false;
2914 return Traits::EmptyExpression();
2915 }
2916
2917 Traits::AddTemplateSpan(&ts, next == Token::TEMPLATE_TAIL);
2918 } while (next == Token::TEMPLATE_SPAN);
2919
2920 DCHECK_EQ(next, Token::TEMPLATE_TAIL);
2921 // Once we've reached a TEMPLATE_TAIL, we can close the TemplateLiteral.
2922 return Traits::CloseTemplateLiteral(&ts, start, tag);
2923 }
2924
2925 // If we reach a TEMPLATE_TAIL first, we are parsing a NoSubstitutionTemplate.
rossberg 2014/11/14 12:28:07 Nit: put this alternative into a conditional inste
2926 // In this case we may simply consume the token and build a template with a
2927 // single TEMPLATE_SPAN and no expressions.
2928 Consume(Token::TEMPLATE_TAIL);
2929 int pos = position();
2930 typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos);
2931 Traits::AddTemplateSpan(&ts, true);
2932 return Traits::CloseTemplateLiteral(&ts, start, tag);
2933 }
2934
2935
2936 template <typename Traits>
2937 typename ParserBase<Traits>::ExpressionT
2817 ParserBase<Traits>::CheckAndRewriteReferenceExpression( 2938 ParserBase<Traits>::CheckAndRewriteReferenceExpression(
2818 ExpressionT expression, 2939 ExpressionT expression,
2819 Scanner::Location location, const char* message, bool* ok) { 2940 Scanner::Location location, const char* message, bool* ok) {
2820 if (strict_mode() == STRICT && this->IsIdentifier(expression) && 2941 if (strict_mode() == STRICT && this->IsIdentifier(expression) &&
2821 this->IsEvalOrArguments(this->AsIdentifier(expression))) { 2942 this->IsEvalOrArguments(this->AsIdentifier(expression))) {
2822 this->ReportMessageAt(location, "strict_eval_arguments", false); 2943 this->ReportMessageAt(location, "strict_eval_arguments", false);
2823 *ok = false; 2944 *ok = false;
2824 return this->EmptyExpression(); 2945 return this->EmptyExpression();
2825 } else if (expression->IsValidReferenceExpression()) { 2946 } else if (expression->IsValidReferenceExpression()) {
2826 return expression; 2947 return expression;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
2864 DCHECK(IsAccessorAccessorConflict(old_type, type)); 2985 DCHECK(IsAccessorAccessorConflict(old_type, type));
2865 // Both accessors of the same type. 2986 // Both accessors of the same type.
2866 parser()->ReportMessage("accessor_get_set"); 2987 parser()->ReportMessage("accessor_get_set");
2867 } 2988 }
2868 *ok = false; 2989 *ok = false;
2869 } 2990 }
2870 } 2991 }
2871 } } // v8::internal 2992 } } // v8::internal
2872 2993
2873 #endif // V8_PREPARSER_H 2994 #endif // V8_PREPARSER_H
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698