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

Side by Side Diff: runtime/vm/parser.cc

Issue 32513007: Allow string literal concatenation in import clauses (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 2 months 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 | « runtime/vm/parser.h ('k') | tests/co19/co19-dartium.status » ('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 (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/parser.h" 5 #include "vm/parser.h"
6 6
7 #include "lib/invocation_mirror.h" 7 #include "lib/invocation_mirror.h"
8 #include "vm/bigint_operations.h" 8 #include "vm/bigint_operations.h"
9 #include "vm/bootstrap.h" 9 #include "vm/bootstrap.h"
10 #include "vm/class_finalizer.h" 10 #include "vm/class_finalizer.h"
(...skipping 4774 matching lines...) Expand 10 before | Expand all | Expand 10 after
4785 4785
4786 void Parser::ParseLibraryImportExport() { 4786 void Parser::ParseLibraryImportExport() {
4787 bool is_import = (CurrentToken() == Token::kIMPORT); 4787 bool is_import = (CurrentToken() == Token::kIMPORT);
4788 bool is_export = (CurrentToken() == Token::kEXPORT); 4788 bool is_export = (CurrentToken() == Token::kEXPORT);
4789 ASSERT(is_import || is_export); 4789 ASSERT(is_import || is_export);
4790 const intptr_t import_pos = TokenPos(); 4790 const intptr_t import_pos = TokenPos();
4791 ConsumeToken(); 4791 ConsumeToken();
4792 if (CurrentToken() != Token::kSTRING) { 4792 if (CurrentToken() != Token::kSTRING) {
4793 ErrorMsg("library url expected"); 4793 ErrorMsg("library url expected");
4794 } 4794 }
4795 const String& url = *CurrentLiteral(); 4795 AstNode* url_literal = ParseStringLiteral(false);
4796 ASSERT(url_literal->IsLiteralNode());
4797 ASSERT(url_literal->AsLiteralNode()->literal().IsString());
4798 const String& url = String::Cast(url_literal->AsLiteralNode()->literal());
4796 if (url.Length() == 0) { 4799 if (url.Length() == 0) {
4797 ErrorMsg("library url expected"); 4800 ErrorMsg("library url expected");
4798 } 4801 }
4799 ConsumeToken();
4800 String& prefix = String::Handle(); 4802 String& prefix = String::Handle();
4801 if (is_import && (CurrentToken() == Token::kAS)) { 4803 if (is_import && (CurrentToken() == Token::kAS)) {
4802 ConsumeToken(); 4804 ConsumeToken();
4803 prefix = ExpectIdentifier("prefix identifier expected")->raw(); 4805 prefix = ExpectIdentifier("prefix identifier expected")->raw();
4804 } 4806 }
4805 4807
4806 Array& show_names = Array::Handle(); 4808 Array& show_names = Array::Handle();
4807 Array& hide_names = Array::Handle(); 4809 Array& hide_names = Array::Handle();
4808 if (IsLiteral("show") || IsLiteral("hide")) { 4810 if (IsLiteral("show") || IsLiteral("hide")) {
4809 GrowableObjectArray& show_list = 4811 GrowableObjectArray& show_list =
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
4874 } 4876 }
4875 } 4877 }
4876 4878
4877 4879
4878 void Parser::ParseLibraryPart() { 4880 void Parser::ParseLibraryPart() {
4879 const intptr_t source_pos = TokenPos(); 4881 const intptr_t source_pos = TokenPos();
4880 ConsumeToken(); // Consume "part". 4882 ConsumeToken(); // Consume "part".
4881 if (CurrentToken() != Token::kSTRING) { 4883 if (CurrentToken() != Token::kSTRING) {
4882 ErrorMsg("url expected"); 4884 ErrorMsg("url expected");
4883 } 4885 }
4884 const String& url = *CurrentLiteral(); 4886 AstNode* url_literal = ParseStringLiteral(false);
4885 ConsumeToken(); 4887 ASSERT(url_literal->IsLiteralNode());
4888 ASSERT(url_literal->AsLiteralNode()->literal().IsString());
4889 const String& url = String::Cast(url_literal->AsLiteralNode()->literal());
4886 ExpectSemicolon(); 4890 ExpectSemicolon();
4887 const String& canon_url = String::CheckedHandle( 4891 const String& canon_url = String::CheckedHandle(
4888 CallLibraryTagHandler(Dart_kCanonicalizeUrl, source_pos, url)); 4892 CallLibraryTagHandler(Dart_kCanonicalizeUrl, source_pos, url));
4889 CallLibraryTagHandler(Dart_kSourceTag, source_pos, canon_url); 4893 CallLibraryTagHandler(Dart_kSourceTag, source_pos, canon_url);
4890 } 4894 }
4891 4895
4892 4896
4893 void Parser::ParseLibraryDefinition() { 4897 void Parser::ParseLibraryDefinition() {
4894 TRACE_PARSER("ParseLibraryDefinition"); 4898 TRACE_PARSER("ParseLibraryDefinition");
4895 4899
(...skipping 5063 matching lines...) Expand 10 before | Expand all | Expand 10 after
9959 return concatenated; 9963 return concatenated;
9960 } 9964 }
9961 9965
9962 9966
9963 // A string literal consists of the concatenation of the next n tokens 9967 // A string literal consists of the concatenation of the next n tokens
9964 // that satisfy the EBNF grammar: 9968 // that satisfy the EBNF grammar:
9965 // literal = kSTRING {{ interpol } kSTRING } 9969 // literal = kSTRING {{ interpol } kSTRING }
9966 // interpol = kINTERPOL_VAR | (kINTERPOL_START expression kINTERPOL_END) 9970 // interpol = kINTERPOL_VAR | (kINTERPOL_START expression kINTERPOL_END)
9967 // In other words, the scanner breaks down interpolated strings so that 9971 // In other words, the scanner breaks down interpolated strings so that
9968 // a string literal always begins and ends with a kSTRING token. 9972 // a string literal always begins and ends with a kSTRING token.
9969 AstNode* Parser::ParseStringLiteral() { 9973 AstNode* Parser::ParseStringLiteral(bool allow_interpolation) {
9970 TRACE_PARSER("ParseStringLiteral"); 9974 TRACE_PARSER("ParseStringLiteral");
9971 AstNode* primary = NULL; 9975 AstNode* primary = NULL;
9972 const intptr_t literal_start = TokenPos(); 9976 const intptr_t literal_start = TokenPos();
9973 ASSERT(CurrentToken() == Token::kSTRING); 9977 ASSERT(CurrentToken() == Token::kSTRING);
9974 Token::Kind l1_token = LookaheadToken(1); 9978 Token::Kind l1_token = LookaheadToken(1);
9975 if ((l1_token != Token::kSTRING) && 9979 if ((l1_token != Token::kSTRING) &&
9976 (l1_token != Token::kINTERPOL_VAR) && 9980 (l1_token != Token::kINTERPOL_VAR) &&
9977 (l1_token != Token::kINTERPOL_START)) { 9981 (l1_token != Token::kINTERPOL_START)) {
9978 // Common case: no interpolation. 9982 // Common case: no interpolation.
9979 primary = new LiteralNode(literal_start, *CurrentLiteral()); 9983 primary = new LiteralNode(literal_start, *CurrentLiteral());
9980 ConsumeToken(); 9984 ConsumeToken();
9981 return primary; 9985 return primary;
9982 } 9986 }
9983 // String interpolation needed. 9987 // String interpolation needed.
9984 bool is_compiletime_const = true; 9988 bool is_compiletime_const = true;
9989 bool has_interpolation = false;
9985 GrowableArray<AstNode*> values_list; 9990 GrowableArray<AstNode*> values_list;
9986 while (CurrentToken() == Token::kSTRING) { 9991 while (CurrentToken() == Token::kSTRING) {
9987 if (CurrentLiteral()->Length() > 0) { 9992 if (CurrentLiteral()->Length() > 0) {
9988 // Only add non-empty string sections to the values list 9993 // Only add non-empty string sections to the values list
9989 // that will be concatenated. 9994 // that will be concatenated.
9990 values_list.Add(new LiteralNode(TokenPos(), *CurrentLiteral())); 9995 values_list.Add(new LiteralNode(TokenPos(), *CurrentLiteral()));
9991 } 9996 }
9992 ConsumeToken(); 9997 ConsumeToken();
9993 while ((CurrentToken() == Token::kINTERPOL_VAR) || 9998 while ((CurrentToken() == Token::kINTERPOL_VAR) ||
9994 (CurrentToken() == Token::kINTERPOL_START)) { 9999 (CurrentToken() == Token::kINTERPOL_START)) {
10000 if (!allow_interpolation) {
10001 ErrorMsg("string interpolation not allowed in this context");
10002 }
10003 has_interpolation = true;
9995 AstNode* expr = NULL; 10004 AstNode* expr = NULL;
9996 const intptr_t expr_pos = TokenPos(); 10005 const intptr_t expr_pos = TokenPos();
9997 if (CurrentToken() == Token::kINTERPOL_VAR) { 10006 if (CurrentToken() == Token::kINTERPOL_VAR) {
9998 expr = ResolveIdent(TokenPos(), *CurrentLiteral(), true); 10007 expr = ResolveIdent(TokenPos(), *CurrentLiteral(), true);
9999 ConsumeToken(); 10008 ConsumeToken();
10000 } else { 10009 } else {
10001 ASSERT(CurrentToken() == Token::kINTERPOL_START); 10010 ASSERT(CurrentToken() == Token::kINTERPOL_START);
10002 ConsumeToken(); 10011 ConsumeToken();
10003 expr = ParseExpr(kAllowConst, kConsumeCascades); 10012 expr = ParseExpr(kAllowConst, kConsumeCascades);
10004 ExpectToken(Token::kINTERPOL_END); 10013 ExpectToken(Token::kINTERPOL_END);
(...skipping 12 matching lines...) Expand all
10017 // Change expr into a literal. 10026 // Change expr into a literal.
10018 expr = new LiteralNode(expr_pos, EvaluateConstExpr(expr)); 10027 expr = new LiteralNode(expr_pos, EvaluateConstExpr(expr));
10019 } else { 10028 } else {
10020 is_compiletime_const = false; 10029 is_compiletime_const = false;
10021 } 10030 }
10022 } 10031 }
10023 values_list.Add(expr); 10032 values_list.Add(expr);
10024 } 10033 }
10025 } 10034 }
10026 if (is_compiletime_const) { 10035 if (is_compiletime_const) {
10027 primary = new LiteralNode(literal_start, Interpolate(values_list)); 10036 if (has_interpolation) {
10037 primary = new LiteralNode(literal_start, Interpolate(values_list));
10038 } else {
10039 const Array& strings = Array::Handle(Array::New(values_list.length()));
10040 for (int i = 0; i < values_list.length(); i++) {
10041 const Instance& part = values_list[i]->AsLiteralNode()->literal();
10042 ASSERT(part.IsString());
10043 strings.SetAt(i, String::Cast(part));
10044 }
10045 String& lit = String::ZoneHandle(String::ConcatAll(strings, Heap::kOld));
10046 lit = Symbols::New(lit);
10047 primary = new LiteralNode(literal_start, lit);
10048 }
10028 } else { 10049 } else {
10029 ArrayNode* values = new ArrayNode( 10050 ArrayNode* values = new ArrayNode(
10030 TokenPos(), 10051 TokenPos(),
10031 Type::ZoneHandle(Type::ArrayType()), 10052 Type::ZoneHandle(Type::ArrayType()),
10032 values_list); 10053 values_list);
10033 primary = new StringInterpolateNode(TokenPos(), values); 10054 primary = new StringInterpolateNode(TokenPos(), values);
10034 } 10055 }
10035 return primary; 10056 return primary;
10036 } 10057 }
10037 10058
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
10132 SetAllowFunctionLiterals(saved_mode); 10153 SetAllowFunctionLiterals(saved_mode);
10133 ExpectToken(Token::kRPAREN); 10154 ExpectToken(Token::kRPAREN);
10134 } else if (CurrentToken() == Token::kDOUBLE) { 10155 } else if (CurrentToken() == Token::kDOUBLE) {
10135 Double& double_value = Double::ZoneHandle(CurrentDoubleLiteral()); 10156 Double& double_value = Double::ZoneHandle(CurrentDoubleLiteral());
10136 if (double_value.IsNull()) { 10157 if (double_value.IsNull()) {
10137 ErrorMsg("invalid double literal"); 10158 ErrorMsg("invalid double literal");
10138 } 10159 }
10139 primary = new LiteralNode(TokenPos(), double_value); 10160 primary = new LiteralNode(TokenPos(), double_value);
10140 ConsumeToken(); 10161 ConsumeToken();
10141 } else if (CurrentToken() == Token::kSTRING) { 10162 } else if (CurrentToken() == Token::kSTRING) {
10142 primary = ParseStringLiteral(); 10163 primary = ParseStringLiteral(true);
10143 } else if (CurrentToken() == Token::kNEW) { 10164 } else if (CurrentToken() == Token::kNEW) {
10144 ConsumeToken(); 10165 ConsumeToken();
10145 primary = ParseNewOperator(Token::kNEW); 10166 primary = ParseNewOperator(Token::kNEW);
10146 } else if (CurrentToken() == Token::kCONST) { 10167 } else if (CurrentToken() == Token::kCONST) {
10147 if ((LookaheadToken(1) == Token::kLT) || 10168 if ((LookaheadToken(1) == Token::kLT) ||
10148 (LookaheadToken(1) == Token::kLBRACK) || 10169 (LookaheadToken(1) == Token::kLBRACK) ||
10149 (LookaheadToken(1) == Token::kINDEX) || 10170 (LookaheadToken(1) == Token::kINDEX) ||
10150 (LookaheadToken(1) == Token::kLBRACE)) { 10171 (LookaheadToken(1) == Token::kLBRACE)) {
10151 primary = ParseCompoundLiteral(); 10172 primary = ParseCompoundLiteral();
10152 } else { 10173 } else {
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after
10554 void Parser::SkipQualIdent() { 10575 void Parser::SkipQualIdent() {
10555 ASSERT(IsIdentifier()); 10576 ASSERT(IsIdentifier());
10556 ConsumeToken(); 10577 ConsumeToken();
10557 if (CurrentToken() == Token::kPERIOD) { 10578 if (CurrentToken() == Token::kPERIOD) {
10558 ConsumeToken(); // Consume the kPERIOD token. 10579 ConsumeToken(); // Consume the kPERIOD token.
10559 ExpectIdentifier("identifier expected after '.'"); 10580 ExpectIdentifier("identifier expected after '.'");
10560 } 10581 }
10561 } 10582 }
10562 10583
10563 } // namespace dart 10584 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/co19/co19-dartium.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698