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 "vm/bigint_operations.h" | 7 #include "vm/bigint_operations.h" |
8 #include "vm/class_finalizer.h" | 8 #include "vm/class_finalizer.h" |
9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/compiler_stats.h" | 10 #include "vm/compiler_stats.h" |
(...skipping 3942 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3953 | 3953 |
3954 void Parser::ParseLibraryImport() { | 3954 void Parser::ParseLibraryImport() { |
3955 TRACE_PARSER("ParseLibraryImport"); | 3955 TRACE_PARSER("ParseLibraryImport"); |
3956 while (CurrentToken() == Token::kIMPORT) { | 3956 while (CurrentToken() == Token::kIMPORT) { |
3957 const intptr_t import_pos = TokenPos(); | 3957 const intptr_t import_pos = TokenPos(); |
3958 ConsumeToken(); | 3958 ConsumeToken(); |
3959 ExpectToken(Token::kLPAREN); | 3959 ExpectToken(Token::kLPAREN); |
3960 if (CurrentToken() != Token::kSTRING) { | 3960 if (CurrentToken() != Token::kSTRING) { |
3961 ErrorMsg("library url expected"); | 3961 ErrorMsg("library url expected"); |
3962 } | 3962 } |
3963 const String& url = *ParseImportStringLiteral(); | 3963 const String& url = *CurrentLiteral(); |
| 3964 ConsumeToken(); |
3964 String& prefix = String::Handle(); | 3965 String& prefix = String::Handle(); |
3965 if (CurrentToken() == Token::kCOMMA) { | 3966 if (CurrentToken() == Token::kCOMMA) { |
3966 ConsumeToken(); | 3967 ConsumeToken(); |
3967 if (!IsLiteral("prefix")) { | 3968 if (!IsLiteral("prefix")) { |
3968 ErrorMsg("prefix: expected"); | 3969 ErrorMsg("prefix: expected"); |
3969 } | 3970 } |
3970 ConsumeToken(); | 3971 ConsumeToken(); |
3971 ExpectToken(Token::kCOLON); | 3972 ExpectToken(Token::kCOLON); |
3972 if (CurrentToken() != Token::kSTRING) { | 3973 if (CurrentToken() != Token::kSTRING) { |
3973 ErrorMsg("prefix expected"); | 3974 ErrorMsg("prefix expected"); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4017 | 4018 |
4018 void Parser::ParseLibraryInclude() { | 4019 void Parser::ParseLibraryInclude() { |
4019 TRACE_PARSER("ParseLibraryInclude"); | 4020 TRACE_PARSER("ParseLibraryInclude"); |
4020 while (CurrentToken() == Token::kSOURCE) { | 4021 while (CurrentToken() == Token::kSOURCE) { |
4021 const intptr_t source_pos = TokenPos(); | 4022 const intptr_t source_pos = TokenPos(); |
4022 ConsumeToken(); | 4023 ConsumeToken(); |
4023 ExpectToken(Token::kLPAREN); | 4024 ExpectToken(Token::kLPAREN); |
4024 if (CurrentToken() != Token::kSTRING) { | 4025 if (CurrentToken() != Token::kSTRING) { |
4025 ErrorMsg("source url expected"); | 4026 ErrorMsg("source url expected"); |
4026 } | 4027 } |
4027 const String& url = *ParseImportStringLiteral(); | 4028 const String& url = *CurrentLiteral(); |
| 4029 ConsumeToken(); |
4028 ExpectToken(Token::kRPAREN); | 4030 ExpectToken(Token::kRPAREN); |
4029 ExpectToken(Token::kSEMICOLON); | 4031 ExpectToken(Token::kSEMICOLON); |
4030 Dart_Handle handle = CallLibraryTagHandler(kCanonicalizeUrl, | 4032 Dart_Handle handle = CallLibraryTagHandler(kCanonicalizeUrl, |
4031 source_pos, | 4033 source_pos, |
4032 url); | 4034 url); |
4033 const String& canon_url = String::CheckedHandle(Api::UnwrapHandle(handle)); | 4035 const String& canon_url = String::CheckedHandle(Api::UnwrapHandle(handle)); |
4034 CallLibraryTagHandler(kSourceTag, source_pos, canon_url); | 4036 CallLibraryTagHandler(kSourceTag, source_pos, canon_url); |
4035 } | 4037 } |
4036 } | 4038 } |
4037 | 4039 |
(...skipping 3998 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8036 } else { | 8038 } else { |
8037 ASSERT(primary->primary().IsClass()); | 8039 ASSERT(primary->primary().IsClass()); |
8038 ErrorMsg(ident_pos, "illegal reference to class or interface '%s'", | 8040 ErrorMsg(ident_pos, "illegal reference to class or interface '%s'", |
8039 ident.ToCString()); | 8041 ident.ToCString()); |
8040 } | 8042 } |
8041 } | 8043 } |
8042 return resolved; | 8044 return resolved; |
8043 } | 8045 } |
8044 | 8046 |
8045 | 8047 |
8046 // Resolve variables used in an import string literal. | |
8047 // If the variable name cannot be resolved issue an error message. | |
8048 // Currently we only resolve against the global map which is passed in | |
8049 // when the script is loaded. | |
8050 RawString* Parser::ResolveImportVar(intptr_t ident_pos, const String& ident) { | |
8051 TRACE_PARSER("ResolveImportVar"); | |
8052 const Array& import_map = | |
8053 Array::Handle(Isolate::Current()->object_store()->import_map()); | |
8054 if (!import_map.IsNull()) { | |
8055 intptr_t length = import_map.Length(); | |
8056 intptr_t index = 0; | |
8057 String& name = String::Handle(); | |
8058 while (index < (length - 1)) { | |
8059 name ^= import_map.At(index); | |
8060 if (name.Equals(ident)) { | |
8061 name ^= import_map.At(index + 1); | |
8062 return name.raw(); | |
8063 } | |
8064 index += 2; | |
8065 } | |
8066 } | |
8067 ErrorMsg(ident_pos, "import variable '%s' has not been defined", | |
8068 ident.ToCString()); | |
8069 return String::null(); | |
8070 } | |
8071 | |
8072 | |
8073 // Parses type = [ident "."] ident ["<" type { "," type } ">"], then resolve and | 8048 // Parses type = [ident "."] ident ["<" type { "," type } ">"], then resolve and |
8074 // finalize it according to the given type finalization mode. | 8049 // finalize it according to the given type finalization mode. |
8075 RawAbstractType* Parser::ParseType( | 8050 RawAbstractType* Parser::ParseType( |
8076 ClassFinalizer::FinalizationKind finalization) { | 8051 ClassFinalizer::FinalizationKind finalization) { |
8077 TRACE_PARSER("ParseType"); | 8052 TRACE_PARSER("ParseType"); |
8078 if (CurrentToken() != Token::kIDENT) { | 8053 if (CurrentToken() != Token::kIDENT) { |
8079 ErrorMsg("type name expected"); | 8054 ErrorMsg("type name expected"); |
8080 } | 8055 } |
8081 QualIdent type_name; | 8056 QualIdent type_name; |
8082 if (finalization == ClassFinalizer::kIgnore) { | 8057 if (finalization == ClassFinalizer::kIgnore) { |
(...skipping 796 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8879 new ArgumentListNode(values->token_pos()); | 8854 new ArgumentListNode(values->token_pos()); |
8880 interpolate_arg->Add(values); | 8855 interpolate_arg->Add(values); |
8881 const String& cls_name = String::Handle(Symbols::StringBase()); | 8856 const String& cls_name = String::Handle(Symbols::StringBase()); |
8882 const String& func_name = String::Handle(Symbols::Interpolate()); | 8857 const String& func_name = String::Handle(Symbols::Interpolate()); |
8883 primary = MakeStaticCall(cls_name, func_name, interpolate_arg); | 8858 primary = MakeStaticCall(cls_name, func_name, interpolate_arg); |
8884 } | 8859 } |
8885 return primary; | 8860 return primary; |
8886 } | 8861 } |
8887 | 8862 |
8888 | 8863 |
8889 // An import string literal consists of the concatenation of the next n tokens | |
8890 // that satisfy the EBNF grammar: | |
8891 // literal = kSTRING {{ interpol }+ kSTRING } | |
8892 // interpol = kINTERPOL_VAR | |
8893 // In other words, the scanner breaks down interpolated strings so that | |
8894 // a string literal always begins and ends with a kSTRING token, and | |
8895 // there are never two kSTRING tokens next to each other. | |
8896 String* Parser::ParseImportStringLiteral() { | |
8897 TRACE_PARSER("ParseImportStringLiteral"); | |
8898 if ((CurrentToken() == Token::kSTRING) && | |
8899 (LookaheadToken(1) != Token::kINTERPOL_VAR) && | |
8900 (LookaheadToken(1) != Token::kINTERPOL_START)) { | |
8901 // Common case: no interpolation. | |
8902 String* result = CurrentLiteral(); | |
8903 ConsumeToken(); | |
8904 return result; | |
8905 } | |
8906 // String interpolation needed. | |
8907 String& result = String::ZoneHandle(Symbols::Empty()); | |
8908 String& resolved_name = String::Handle(); | |
8909 while (CurrentToken() == Token::kSTRING) { | |
8910 result = String::Concat(result, *CurrentLiteral()); | |
8911 ConsumeToken(); | |
8912 if ((CurrentToken() != Token::kINTERPOL_VAR) && | |
8913 (CurrentToken() != Token::kINTERPOL_START)) { | |
8914 break; | |
8915 } | |
8916 while ((CurrentToken() == Token::kINTERPOL_VAR) || | |
8917 (CurrentToken() == Token::kINTERPOL_START)) { | |
8918 if (CurrentToken() == Token::kINTERPOL_START) { | |
8919 ConsumeToken(); | |
8920 if (IsIdentifier()) { | |
8921 resolved_name = ResolveImportVar(TokenPos(), *CurrentLiteral()); | |
8922 result = String::Concat(result, resolved_name); | |
8923 ConsumeToken(); | |
8924 if (CurrentToken() != Token::kINTERPOL_END) { | |
8925 ErrorMsg("'}' expected"); | |
8926 } | |
8927 ConsumeToken(); | |
8928 } else { | |
8929 ErrorMsg("identifier expected"); | |
8930 } | |
8931 } else { | |
8932 ASSERT(CurrentToken() == Token::kINTERPOL_VAR); | |
8933 resolved_name = ResolveImportVar(TokenPos(), *CurrentLiteral()); | |
8934 result = String::Concat(result, resolved_name); | |
8935 ConsumeToken(); | |
8936 } | |
8937 } | |
8938 // A string literal always ends with a kSTRING token. | |
8939 ASSERT(CurrentToken() == Token::kSTRING); | |
8940 } | |
8941 return &result; | |
8942 } | |
8943 | |
8944 | |
8945 AstNode* Parser::ParseArgumentDefinitionTest() { | 8864 AstNode* Parser::ParseArgumentDefinitionTest() { |
8946 const intptr_t test_pos = TokenPos(); | 8865 const intptr_t test_pos = TokenPos(); |
8947 ConsumeToken(); | 8866 ConsumeToken(); |
8948 const intptr_t ident_pos = TokenPos(); | 8867 const intptr_t ident_pos = TokenPos(); |
8949 String* ident = ExpectIdentifier("parameter name expected"); | 8868 String* ident = ExpectIdentifier("parameter name expected"); |
8950 Function& owner_function = Function::Handle(); | 8869 Function& owner_function = Function::Handle(); |
8951 LocalScope* owner_scope; | 8870 LocalScope* owner_scope; |
8952 intptr_t param_index; | 8871 intptr_t param_index; |
8953 if (!IsFormalParameter(*ident, &owner_function, &owner_scope, ¶m_index)) { | 8872 if (!IsFormalParameter(*ident, &owner_function, &owner_scope, ¶m_index)) { |
8954 ErrorMsg(ident_pos, "formal parameter name expected"); | 8873 ErrorMsg(ident_pos, "formal parameter name expected"); |
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9415 void Parser::SkipQualIdent() { | 9334 void Parser::SkipQualIdent() { |
9416 ASSERT(IsIdentifier()); | 9335 ASSERT(IsIdentifier()); |
9417 ConsumeToken(); | 9336 ConsumeToken(); |
9418 if (CurrentToken() == Token::kPERIOD) { | 9337 if (CurrentToken() == Token::kPERIOD) { |
9419 ConsumeToken(); // Consume the kPERIOD token. | 9338 ConsumeToken(); // Consume the kPERIOD token. |
9420 ExpectIdentifier("identifier expected after '.'"); | 9339 ExpectIdentifier("identifier expected after '.'"); |
9421 } | 9340 } |
9422 } | 9341 } |
9423 | 9342 |
9424 } // namespace dart | 9343 } // namespace dart |
OLD | NEW |