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

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: Add comments describing the parsing and scanning of TemplateLiterals 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 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 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
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); }
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
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
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
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
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
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 (;;) {
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
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 break;
2916 }
2917 }
2918 return Traits::CloseTemplateLiteral(&ts, start, tag);
marja 2014/11/10 16:18:29 Nit: there's only one break above, so you can move
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
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
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