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

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: More tests again 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') | src/scanner.cc » ('J')
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 865 matching lines...) Expand 10 before | Expand all | Expand 10 after
1372 // Utility functions 1379 // Utility functions
1373 int DeclareArrowParametersFromExpression(PreParserExpression expression, 1380 int DeclareArrowParametersFromExpression(PreParserExpression expression,
1374 PreParserScope* scope, 1381 PreParserScope* scope,
1375 Scanner::Location* dupe_loc, 1382 Scanner::Location* dupe_loc,
1376 bool* ok) { 1383 bool* ok) {
1377 // TODO(aperez): Detect duplicated identifiers in paramlists. 1384 // TODO(aperez): Detect duplicated identifiers in paramlists.
1378 *ok = expression.IsValidArrowParamList(); 1385 *ok = expression.IsValidArrowParamList();
1379 return 0; 1386 return 0;
1380 } 1387 }
1381 1388
1389 struct TemplateLiteralState {};
1390
1391 TemplateLiteralState OpenTemplateLiteral(int pos) {
1392 return TemplateLiteralState();
1393 }
1394 void AddTemplateSpan(TemplateLiteralState* state) { USE(state); }
1395 void AddTemplateExpression(TemplateLiteralState* state,
1396 PreParserExpression expression) {
1397 USE(state);
1398 USE(expression);
1399 }
1400 PreParserExpression CloseTemplateLiteral(TemplateLiteralState* state,
1401 int start, PreParserExpression tag) {
1402 USE(state);
1403 USE(start);
1404 USE(tag);
1405 return EmptyExpression();
1406 }
1407 PreParserExpression NoTemplateTag() {
1408 return PreParserExpression::Default();
1409 }
1382 static AstValueFactory* ast_value_factory() { return NULL; } 1410 static AstValueFactory* ast_value_factory() { return NULL; }
1383 1411
1384 void CheckConflictingVarDeclarations(PreParserScope scope, bool* ok) {} 1412 void CheckConflictingVarDeclarations(PreParserScope scope, bool* ok) {}
1385 1413
1386 // Temporary glue; these functions will move to ParserBase. 1414 // Temporary glue; these functions will move to ParserBase.
1387 PreParserExpression ParseV8Intrinsic(bool* ok); 1415 PreParserExpression ParseV8Intrinsic(bool* ok);
1388 PreParserExpression ParseFunctionLiteral( 1416 PreParserExpression ParseFunctionLiteral(
1389 PreParserIdentifier name, Scanner::Location function_name_location, 1417 PreParserIdentifier name, Scanner::Location function_name_location,
1390 bool name_is_strict_reserved, FunctionKind kind, 1418 bool name_is_strict_reserved, FunctionKind kind,
1391 int function_token_position, FunctionLiteral::FunctionType type, 1419 int function_token_position, FunctionLiteral::FunctionType type,
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
1742 // 'true' 1770 // 'true'
1743 // 'false' 1771 // 'false'
1744 // Identifier 1772 // Identifier
1745 // Number 1773 // Number
1746 // String 1774 // String
1747 // ArrayLiteral 1775 // ArrayLiteral
1748 // ObjectLiteral 1776 // ObjectLiteral
1749 // RegExpLiteral 1777 // RegExpLiteral
1750 // ClassLiteral 1778 // ClassLiteral
1751 // '(' Expression ')' 1779 // '(' Expression ')'
1780 // TemplateLiteral
1752 1781
1753 int pos = peek_position(); 1782 int pos = peek_position();
1754 ExpressionT result = this->EmptyExpression(); 1783 ExpressionT result = this->EmptyExpression();
1755 Token::Value token = peek(); 1784 Token::Value token = peek();
1756 switch (token) { 1785 switch (token) {
1757 case Token::THIS: { 1786 case Token::THIS: {
1758 Consume(Token::THIS); 1787 Consume(Token::THIS);
1759 scope_->RecordThisUsage(); 1788 scope_->RecordThisUsage();
1760 result = this->ThisExpression(scope_, factory()); 1789 result = this->ThisExpression(scope_, factory());
1761 break; 1790 break;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1830 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, 1859 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
1831 CHECK_OK); 1860 CHECK_OK);
1832 class_name_location = scanner()->location(); 1861 class_name_location = scanner()->location();
1833 } 1862 }
1834 result = this->ParseClassLiteral(name, class_name_location, 1863 result = this->ParseClassLiteral(name, class_name_location,
1835 is_strict_reserved_name, 1864 is_strict_reserved_name,
1836 class_token_position, CHECK_OK); 1865 class_token_position, CHECK_OK);
1837 break; 1866 break;
1838 } 1867 }
1839 1868
1869 case Token::TEMPLATE_SPAN:
1870 case Token::TEMPLATE_TAIL:
1871 result = this->ParseTemplateLiteral(Traits::NoTemplateTag(), pos,
1872 CHECK_OK);
1873 break;
1874
1840 case Token::MOD: 1875 case Token::MOD:
1841 if (allow_natives_syntax() || extension_ != NULL) { 1876 if (allow_natives_syntax() || extension_ != NULL) {
1842 result = this->ParseV8Intrinsic(CHECK_OK); 1877 result = this->ParseV8Intrinsic(CHECK_OK);
1843 break; 1878 break;
1844 } 1879 }
1845 // If we're not allowing special syntax we fall-through to the 1880 // If we're not allowing special syntax we fall-through to the
1846 // default case. 1881 // default case.
1847 1882
1848 default: { 1883 default: {
1849 Next(); 1884 Next();
(...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after
2453 // direct eval calls. These calls are all of the form eval(...), with 2488 // direct eval calls. These calls are all of the form eval(...), with
2454 // no explicit receiver. 2489 // no explicit receiver.
2455 // These calls are marked as potentially direct eval calls. Whether 2490 // These calls are marked as potentially direct eval calls. Whether
2456 // they are actually direct calls to eval is determined at run time. 2491 // they are actually direct calls to eval is determined at run time.
2457 this->CheckPossibleEvalCall(result, scope_); 2492 this->CheckPossibleEvalCall(result, scope_);
2458 result = factory()->NewCall(result, args, pos); 2493 result = factory()->NewCall(result, args, pos);
2459 if (fni_ != NULL) fni_->RemoveLastFunction(); 2494 if (fni_ != NULL) fni_->RemoveLastFunction();
2460 break; 2495 break;
2461 } 2496 }
2462 2497
2498 case Token::TEMPLATE_SPAN:
2499 case Token::TEMPLATE_TAIL: {
2500 int pos;
2501 if (scanner()->current_token() == Token::IDENTIFIER) {
2502 pos = position();
2503 } else {
2504 pos = peek_position();
2505 if (result->IsFunctionLiteral() && mode() == PARSE_EAGERLY) {
2506 result->AsFunctionLiteral()->set_parenthesized();
marja 2014/11/10 15:32:02 Why?
caitp (gmail) 2014/11/10 15:43:56 It's basically copy/pasted from the MemberExpressi
marja 2014/11/11 09:15:36 I dug up a bit where this is coming from. In any c
2507 }
2508 }
2509 result = ParseTemplateLiteral(result, pos, CHECK_OK);
2510 break;
2511 }
2512
2463 case Token::PERIOD: { 2513 case Token::PERIOD: {
2464 Consume(Token::PERIOD); 2514 Consume(Token::PERIOD);
2465 int pos = position(); 2515 int pos = position();
2466 IdentifierT name = ParseIdentifierName(CHECK_OK); 2516 IdentifierT name = ParseIdentifierName(CHECK_OK);
2467 result = factory()->NewProperty( 2517 result = factory()->NewProperty(
2468 result, factory()->NewStringLiteral(name, pos), pos); 2518 result, factory()->NewStringLiteral(name, pos), pos);
2469 if (fni_ != NULL) this->PushLiteralName(fni_, name); 2519 if (fni_ != NULL) this->PushLiteralName(fni_, name);
2470 break; 2520 break;
2471 } 2521 }
2472 2522
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after
2791 int end_pos = peek_position(); 2841 int end_pos = peek_position();
2792 Expect(Token::RBRACE, CHECK_OK); 2842 Expect(Token::RBRACE, CHECK_OK);
2793 2843
2794 return this->ClassExpression(name, extends, constructor, properties, pos, 2844 return this->ClassExpression(name, extends, constructor, properties, pos,
2795 end_pos + 1, factory()); 2845 end_pos + 1, factory());
2796 } 2846 }
2797 2847
2798 2848
2799 template <typename Traits> 2849 template <typename Traits>
2800 typename ParserBase<Traits>::ExpressionT 2850 typename ParserBase<Traits>::ExpressionT
2851 ParserBase<Traits>::ParseTemplateLiteral(ExpressionT tag, int start, bool* ok) {
marja 2014/11/10 15:32:02 Can you add here a comment about the parse rules w
2852 CHECK(peek() == Token::TEMPLATE_SPAN || peek() == Token::TEMPLATE_TAIL);
2853
2854 // Add TV / TRV
2855 if (peek() == Token::TEMPLATE_SPAN) {
2856 Consume(Token::TEMPLATE_SPAN);
2857 int pos = position();
2858 typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos);
2859 Traits::AddTemplateSpan(&ts);
2860
2861 for (;;) {
2862 Token::Value next = peek();
2863 if (next < 0) {
2864 ReportMessage("unterminated_template");
2865 *ok = false;
2866 return Traits::EmptyExpression();
2867 }
2868
2869 // Parse an Expression
2870 ExpressionT expression = this->ParseExpression(false, CHECK_OK);
marja 2014/11/10 15:32:02 Why expression? Are we now inside the ${... or...
caitp (gmail) 2014/11/10 15:43:56 Yeah, if we get a TEMPLATE_SPAN token, then we jus
2871 Traits::AddTemplateExpression(&ts, expression);
2872
2873 // If we didn't die parsing that expression, our next token should be a
2874 // TEMPLATE_SPAN or
2875 // TEMPLATE_TAIL.
2876 next = scanner()->ScanTemplateSpan();
2877 Next();
2878
2879 if (next == Token::ILLEGAL || next < 0) {
2880 ReportMessage("unterminated_template");
2881 *ok = false;
2882 return Traits::EmptyExpression();
2883 }
2884
2885 CHECK(next == Token::TEMPLATE_SPAN || next == Token::TEMPLATE_TAIL);
2886 Traits::AddTemplateSpan(&ts);
2887
2888 if (next == Token::TEMPLATE_TAIL) {
2889 break;
2890 }
2891 }
2892 return Traits::CloseTemplateLiteral(&ts, start, tag);
2893 }
2894 Consume(Token::TEMPLATE_TAIL);
2895 int pos = position();
2896 typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos);
2897 Traits::AddTemplateSpan(&ts);
2898 return Traits::CloseTemplateLiteral(&ts, start, tag);
2899 }
2900
2901
2902 template <typename Traits>
2903 typename ParserBase<Traits>::ExpressionT
2801 ParserBase<Traits>::CheckAndRewriteReferenceExpression( 2904 ParserBase<Traits>::CheckAndRewriteReferenceExpression(
2802 ExpressionT expression, 2905 ExpressionT expression,
2803 Scanner::Location location, const char* message, bool* ok) { 2906 Scanner::Location location, const char* message, bool* ok) {
2804 if (strict_mode() == STRICT && this->IsIdentifier(expression) && 2907 if (strict_mode() == STRICT && this->IsIdentifier(expression) &&
2805 this->IsEvalOrArguments(this->AsIdentifier(expression))) { 2908 this->IsEvalOrArguments(this->AsIdentifier(expression))) {
2806 this->ReportMessageAt(location, "strict_eval_arguments", false); 2909 this->ReportMessageAt(location, "strict_eval_arguments", false);
2807 *ok = false; 2910 *ok = false;
2808 return this->EmptyExpression(); 2911 return this->EmptyExpression();
2809 } else if (expression->IsValidReferenceExpression()) { 2912 } else if (expression->IsValidReferenceExpression()) {
2810 return expression; 2913 return expression;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
2848 DCHECK(IsAccessorAccessorConflict(old_type, type)); 2951 DCHECK(IsAccessorAccessorConflict(old_type, type));
2849 // Both accessors of the same type. 2952 // Both accessors of the same type.
2850 parser()->ReportMessage("accessor_get_set"); 2953 parser()->ReportMessage("accessor_get_set");
2851 } 2954 }
2852 *ok = false; 2955 *ok = false;
2853 } 2956 }
2854 } 2957 }
2855 } } // v8::internal 2958 } } // v8::internal
2856 2959
2857 #endif // V8_PREPARSER_H 2960 #endif // V8_PREPARSER_H
OLDNEW
« no previous file with comments | « src/parser.cc ('k') | src/scanner.h » ('j') | src/scanner.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698