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

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: Rebased against https://chromium.googlesource.com/v8/v8.git/master 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
« no previous file with comments | « 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 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool* ok); 487 ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
484 ExpressionT ParseUnaryExpression(bool* ok); 488 ExpressionT ParseUnaryExpression(bool* ok);
485 ExpressionT ParsePostfixExpression(bool* ok); 489 ExpressionT ParsePostfixExpression(bool* ok);
486 ExpressionT ParseLeftHandSideExpression(bool* ok); 490 ExpressionT ParseLeftHandSideExpression(bool* ok);
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);
497 ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, bool* ok);
498 void AddTemplateExpression(ExpressionT);
493 499
494 // Checks if the expression is a valid reference expression (e.g., on the 500 // Checks if the expression is a valid reference expression (e.g., on the
495 // left-hand side of assignments). Although ruled out by ECMA as early errors, 501 // left-hand side of assignments). Although ruled out by ECMA as early errors,
496 // we allow calls for web compatibility and rewrite them to a runtime throw. 502 // we allow calls for web compatibility and rewrite them to a runtime throw.
497 ExpressionT CheckAndRewriteReferenceExpression( 503 ExpressionT CheckAndRewriteReferenceExpression(
498 ExpressionT expression, 504 ExpressionT expression,
499 Scanner::Location location, const char* message, bool* ok); 505 Scanner::Location location, const char* message, bool* ok);
500 506
501 // Used to detect duplicates in object literals. Each of the values 507 // Used to detect duplicates in object literals. Each of the values
502 // kGetterProperty, kSetterProperty and kValueProperty represents 508 // kGetterProperty, kSetterProperty and kValueProperty represents
(...skipping 855 matching lines...) Expand 10 before | Expand all | Expand 10 after
1358 // Utility functions 1364 // Utility functions
1359 int DeclareArrowParametersFromExpression(PreParserExpression expression, 1365 int DeclareArrowParametersFromExpression(PreParserExpression expression,
1360 PreParserScope* scope, 1366 PreParserScope* scope,
1361 Scanner::Location* dupe_loc, 1367 Scanner::Location* dupe_loc,
1362 bool* ok) { 1368 bool* ok) {
1363 // TODO(aperez): Detect duplicated identifiers in paramlists. 1369 // TODO(aperez): Detect duplicated identifiers in paramlists.
1364 *ok = expression.IsValidArrowParamList(); 1370 *ok = expression.IsValidArrowParamList();
1365 return 0; 1371 return 0;
1366 } 1372 }
1367 1373
1374 struct TemplateLiteralState {};
1375
1376 TemplateLiteralState OpenTemplateLiteral(int pos) {
1377 return TemplateLiteralState();
1378 }
1379 void AddTemplateSpan(TemplateLiteralState*, bool) {}
1380 void AddTemplateExpression(TemplateLiteralState*, PreParserExpression) {}
1381 PreParserExpression CloseTemplateLiteral(TemplateLiteralState*, int,
1382 PreParserExpression) {
1383 return EmptyExpression();
1384 }
1385 PreParserExpression NoTemplateTag() { return PreParserExpression::Default(); }
1368 static AstValueFactory* ast_value_factory() { return NULL; } 1386 static AstValueFactory* ast_value_factory() { return NULL; }
1369 1387
1370 void CheckConflictingVarDeclarations(PreParserScope scope, bool* ok) {} 1388 void CheckConflictingVarDeclarations(PreParserScope scope, bool* ok) {}
1371 1389
1372 // Temporary glue; these functions will move to ParserBase. 1390 // Temporary glue; these functions will move to ParserBase.
1373 PreParserExpression ParseV8Intrinsic(bool* ok); 1391 PreParserExpression ParseV8Intrinsic(bool* ok);
1374 PreParserExpression ParseFunctionLiteral( 1392 PreParserExpression ParseFunctionLiteral(
1375 PreParserIdentifier name, Scanner::Location function_name_location, 1393 PreParserIdentifier name, Scanner::Location function_name_location,
1376 bool name_is_strict_reserved, FunctionKind kind, 1394 bool name_is_strict_reserved, FunctionKind kind,
1377 int function_token_position, FunctionLiteral::FunctionType type, 1395 int function_token_position, FunctionLiteral::FunctionType type,
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
1592 case Token::IDENTIFIER: 1610 case Token::IDENTIFIER:
1593 return ReportMessageAt(source_location, "unexpected_token_identifier"); 1611 return ReportMessageAt(source_location, "unexpected_token_identifier");
1594 case Token::FUTURE_RESERVED_WORD: 1612 case Token::FUTURE_RESERVED_WORD:
1595 return ReportMessageAt(source_location, "unexpected_reserved"); 1613 return ReportMessageAt(source_location, "unexpected_reserved");
1596 case Token::LET: 1614 case Token::LET:
1597 case Token::STATIC: 1615 case Token::STATIC:
1598 case Token::YIELD: 1616 case Token::YIELD:
1599 case Token::FUTURE_STRICT_RESERVED_WORD: 1617 case Token::FUTURE_STRICT_RESERVED_WORD:
1600 return ReportMessageAt(source_location, strict_mode() == SLOPPY 1618 return ReportMessageAt(source_location, strict_mode() == SLOPPY
1601 ? "unexpected_token_identifier" : "unexpected_strict_reserved"); 1619 ? "unexpected_token_identifier" : "unexpected_strict_reserved");
1620 case Token::TEMPLATE_SPAN:
1621 case Token::TEMPLATE_TAIL:
1622 return Traits::ReportMessageAt(source_location,
1623 "unexpected_template_string");
1602 default: 1624 default:
1603 const char* name = Token::String(token); 1625 const char* name = Token::String(token);
1604 DCHECK(name != NULL); 1626 DCHECK(name != NULL);
1605 Traits::ReportMessageAt(source_location, "unexpected_token", name); 1627 Traits::ReportMessageAt(source_location, "unexpected_token", name);
1606 } 1628 }
1607 } 1629 }
1608 1630
1609 1631
1610 template<class Traits> 1632 template<class Traits>
1611 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier( 1633 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier(
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1738 // 'true' 1760 // 'true'
1739 // 'false' 1761 // 'false'
1740 // Identifier 1762 // Identifier
1741 // Number 1763 // Number
1742 // String 1764 // String
1743 // ArrayLiteral 1765 // ArrayLiteral
1744 // ObjectLiteral 1766 // ObjectLiteral
1745 // RegExpLiteral 1767 // RegExpLiteral
1746 // ClassLiteral 1768 // ClassLiteral
1747 // '(' Expression ')' 1769 // '(' Expression ')'
1770 // TemplateLiteral
1748 1771
1749 int pos = peek_position(); 1772 int pos = peek_position();
1750 ExpressionT result = this->EmptyExpression(); 1773 ExpressionT result = this->EmptyExpression();
1751 Token::Value token = peek(); 1774 Token::Value token = peek();
1752 switch (token) { 1775 switch (token) {
1753 case Token::THIS: { 1776 case Token::THIS: {
1754 Consume(Token::THIS); 1777 Consume(Token::THIS);
1755 scope_->RecordThisUsage(); 1778 scope_->RecordThisUsage();
1756 result = this->ThisExpression(scope_, factory()); 1779 result = this->ThisExpression(scope_, factory());
1757 break; 1780 break;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1826 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, 1849 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
1827 CHECK_OK); 1850 CHECK_OK);
1828 class_name_location = scanner()->location(); 1851 class_name_location = scanner()->location();
1829 } 1852 }
1830 result = this->ParseClassLiteral(name, class_name_location, 1853 result = this->ParseClassLiteral(name, class_name_location,
1831 is_strict_reserved_name, 1854 is_strict_reserved_name,
1832 class_token_position, CHECK_OK); 1855 class_token_position, CHECK_OK);
1833 break; 1856 break;
1834 } 1857 }
1835 1858
1859 case Token::TEMPLATE_SPAN:
1860 case Token::TEMPLATE_TAIL:
1861 result =
1862 this->ParseTemplateLiteral(Traits::NoTemplateTag(), pos, CHECK_OK);
1863 break;
1864
1836 case Token::MOD: 1865 case Token::MOD:
1837 if (allow_natives_syntax() || extension_ != NULL) { 1866 if (allow_natives_syntax() || extension_ != NULL) {
1838 result = this->ParseV8Intrinsic(CHECK_OK); 1867 result = this->ParseV8Intrinsic(CHECK_OK);
1839 break; 1868 break;
1840 } 1869 }
1841 // If we're not allowing special syntax we fall-through to the 1870 // If we're not allowing special syntax we fall-through to the
1842 // default case. 1871 // default case.
1843 1872
1844 default: { 1873 default: {
1845 Next(); 1874 Next();
(...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after
2449 // direct eval calls. These calls are all of the form eval(...), with 2478 // direct eval calls. These calls are all of the form eval(...), with
2450 // no explicit receiver. 2479 // no explicit receiver.
2451 // These calls are marked as potentially direct eval calls. Whether 2480 // These calls are marked as potentially direct eval calls. Whether
2452 // they are actually direct calls to eval is determined at run time. 2481 // they are actually direct calls to eval is determined at run time.
2453 this->CheckPossibleEvalCall(result, scope_); 2482 this->CheckPossibleEvalCall(result, scope_);
2454 result = factory()->NewCall(result, args, pos); 2483 result = factory()->NewCall(result, args, pos);
2455 if (fni_ != NULL) fni_->RemoveLastFunction(); 2484 if (fni_ != NULL) fni_->RemoveLastFunction();
2456 break; 2485 break;
2457 } 2486 }
2458 2487
2488 case Token::TEMPLATE_SPAN:
2489 case Token::TEMPLATE_TAIL: {
2490 int pos;
2491 if (scanner()->current_token() == Token::IDENTIFIER) {
2492 pos = position();
2493 } else {
2494 pos = peek_position();
2495 if (result->IsFunctionLiteral() && mode() == PARSE_EAGERLY) {
2496 // If the tag function looks like an IIFE, set_parenthesized() to
2497 // force eager compilation.
2498 result->AsFunctionLiteral()->set_parenthesized();
2499 }
2500 }
2501 result = ParseTemplateLiteral(result, pos, CHECK_OK);
2502 break;
2503 }
2504
2459 case Token::PERIOD: { 2505 case Token::PERIOD: {
2460 Consume(Token::PERIOD); 2506 Consume(Token::PERIOD);
2461 int pos = position(); 2507 int pos = position();
2462 IdentifierT name = ParseIdentifierName(CHECK_OK); 2508 IdentifierT name = ParseIdentifierName(CHECK_OK);
2463 result = factory()->NewProperty( 2509 result = factory()->NewProperty(
2464 result, factory()->NewStringLiteral(name, pos), pos); 2510 result, factory()->NewStringLiteral(name, pos), pos);
2465 if (fni_ != NULL) this->PushLiteralName(fni_, name); 2511 if (fni_ != NULL) this->PushLiteralName(fni_, name);
2466 break; 2512 break;
2467 } 2513 }
2468 2514
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
2717 function_literal->set_function_token_position(start_pos); 2763 function_literal->set_function_token_position(start_pos);
2718 2764
2719 if (fni_ != NULL) this->InferFunctionName(fni_, function_literal); 2765 if (fni_ != NULL) this->InferFunctionName(fni_, function_literal);
2720 2766
2721 return function_literal; 2767 return function_literal;
2722 } 2768 }
2723 2769
2724 2770
2725 template <typename Traits> 2771 template <typename Traits>
2726 typename ParserBase<Traits>::ExpressionT 2772 typename ParserBase<Traits>::ExpressionT
2727 ParserBase<Traits>::CheckAndRewriteReferenceExpression( 2773 ParserBase<Traits>::ParseTemplateLiteral(ExpressionT tag, int start, bool* ok) {
2728 ExpressionT expression, 2774 // A TemplateLiteral is made up of 0 or more TEMPLATE_SPAN tokens (literal
2729 Scanner::Location location, const char* message, bool* ok) { 2775 // text followed by a substitution expression), finalized by a single
2776 // TEMPLATE_TAIL.
2777 //
2778 // In terms of draft language, TEMPLATE_SPAN may be either the TemplateHead or
2779 // TemplateMiddle productions, while TEMPLATE_TAIL is either TemplateTail, or
2780 // NoSubstitutionTemplate.
2781 //
2782 // When parsing a TemplateLiteral, we must have scanned either an initial
2783 // TEMPLATE_SPAN, or a TEMPLATE_TAIL.
2784 CHECK(peek() == Token::TEMPLATE_SPAN || peek() == Token::TEMPLATE_TAIL);
2785
2786 // If we reach a TEMPLATE_TAIL first, we are parsing a NoSubstitutionTemplate.
2787 // In this case we may simply consume the token and build a template with a
2788 // single TEMPLATE_SPAN and no expressions.
2789 if (peek() == Token::TEMPLATE_TAIL) {
2790 Consume(Token::TEMPLATE_TAIL);
2791 int pos = position();
2792 typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos);
2793 Traits::AddTemplateSpan(&ts, true);
2794 return Traits::CloseTemplateLiteral(&ts, start, tag);
2795 }
2796
2797 Consume(Token::TEMPLATE_SPAN);
2798 int pos = position();
2799 typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos);
2800 Traits::AddTemplateSpan(&ts, false);
2801 Token::Value next;
2802
2803 // If we open with a TEMPLATE_SPAN, we must scan the subsequent expression,
2804 // and repeat if the following token is a TEMPLATE_SPAN as well (in this
2805 // case, representing a TemplateMiddle).
2806
2807 do {
2808 next = peek();
2809 if (!next) {
2810 ReportMessageAt(Scanner::Location(start, peek_position()),
2811 "unterminated_template");
2812 *ok = false;
2813 return Traits::EmptyExpression();
2814 }
2815
2816 int pos = peek_position();
brucedawson 2014/12/09 22:37:13 While running VC++'s /analyze on Chrome I got a wa
Dmitry Lomov (no reviews) 2014/12/09 22:40:49 The usage looks good (we are reporting the error f
caitp (gmail) 2014/12/09 22:42:15 We could rename it to avoid the warning, if that m
2817 ExpressionT expression = this->ParseExpression(true, CHECK_OK);
2818 Traits::AddTemplateExpression(&ts, expression);
2819
2820 if (peek() != Token::RBRACE) {
2821 ReportMessageAt(Scanner::Location(pos, peek_position()),
2822 "unterminated_template_expr");
2823 *ok = false;
2824 return Traits::EmptyExpression();
2825 }
2826
2827 // If we didn't die parsing that expression, our next token should be a
2828 // TEMPLATE_SPAN or TEMPLATE_TAIL.
2829 next = scanner()->ScanTemplateSpan();
2830 Next();
2831
2832 if (!next) {
2833 ReportMessageAt(Scanner::Location(start, position()),
2834 "unterminated_template");
2835 *ok = false;
2836 return Traits::EmptyExpression();
2837 }
2838
2839 Traits::AddTemplateSpan(&ts, next == Token::TEMPLATE_TAIL);
2840 } while (next == Token::TEMPLATE_SPAN);
2841
2842 DCHECK_EQ(next, Token::TEMPLATE_TAIL);
2843 // Once we've reached a TEMPLATE_TAIL, we can close the TemplateLiteral.
2844 return Traits::CloseTemplateLiteral(&ts, start, tag);
2845 }
2846
2847
2848 template <typename Traits>
2849 typename ParserBase<Traits>::ExpressionT ParserBase<
2850 Traits>::CheckAndRewriteReferenceExpression(ExpressionT expression,
2851 Scanner::Location location,
2852 const char* message, bool* ok) {
2730 if (strict_mode() == STRICT && this->IsIdentifier(expression) && 2853 if (strict_mode() == STRICT && this->IsIdentifier(expression) &&
2731 this->IsEvalOrArguments(this->AsIdentifier(expression))) { 2854 this->IsEvalOrArguments(this->AsIdentifier(expression))) {
2732 this->ReportMessageAt(location, "strict_eval_arguments", false); 2855 this->ReportMessageAt(location, "strict_eval_arguments", false);
2733 *ok = false; 2856 *ok = false;
2734 return this->EmptyExpression(); 2857 return this->EmptyExpression();
2735 } else if (expression->IsValidReferenceExpression()) { 2858 } else if (expression->IsValidReferenceExpression()) {
2736 return expression; 2859 return expression;
2737 } else if (expression->IsCall()) { 2860 } else if (expression->IsCall()) {
2738 // If it is a call, make it a runtime error for legacy web compatibility. 2861 // If it is a call, make it a runtime error for legacy web compatibility.
2739 // Rewrite `expr' to `expr[throw ReferenceError]'. 2862 // Rewrite `expr' to `expr[throw ReferenceError]'.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2774 DCHECK(IsAccessorAccessorConflict(old_type, type)); 2897 DCHECK(IsAccessorAccessorConflict(old_type, type));
2775 // Both accessors of the same type. 2898 // Both accessors of the same type.
2776 parser()->ReportMessage("accessor_get_set"); 2899 parser()->ReportMessage("accessor_get_set");
2777 } 2900 }
2778 *ok = false; 2901 *ok = false;
2779 } 2902 }
2780 } 2903 }
2781 } } // v8::internal 2904 } } // v8::internal
2782 2905
2783 #endif // V8_PREPARSER_H 2906 #endif // V8_PREPARSER_H
OLDNEW
« no previous file with comments | « src/parser.cc ('k') | src/scanner.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698