| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |