| 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 3206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3217 ConsumeToken(); | 3217 ConsumeToken(); |
| 3218 ExpectToken(Token::kRPAREN); | 3218 ExpectToken(Token::kRPAREN); |
| 3219 ExpectToken(Token::kSEMICOLON); | 3219 ExpectToken(Token::kSEMICOLON); |
| 3220 library_.SetName(name); | 3220 library_.SetName(name); |
| 3221 } | 3221 } |
| 3222 } | 3222 } |
| 3223 | 3223 |
| 3224 | 3224 |
| 3225 Dart_Handle Parser::CallLibraryTagHandler(Dart_LibraryTag tag, | 3225 Dart_Handle Parser::CallLibraryTagHandler(Dart_LibraryTag tag, |
| 3226 intptr_t token_pos, | 3226 intptr_t token_pos, |
| 3227 const String& url) { | 3227 const String& url, |
| 3228 const Array& import_map) { |
| 3228 Dart_LibraryTagHandler handler = Isolate::Current()->library_tag_handler(); | 3229 Dart_LibraryTagHandler handler = Isolate::Current()->library_tag_handler(); |
| 3229 if (handler == NULL) { | 3230 if (handler == NULL) { |
| 3230 ErrorMsg(token_pos, "no library handler registered"); | 3231 ErrorMsg(token_pos, "no library handler registered"); |
| 3231 } | 3232 } |
| 3232 Dart_Handle result = handler(tag, | 3233 Dart_Handle result = handler(tag, |
| 3233 Api::NewLocalHandle(library_), | 3234 Api::NewLocalHandle(library_), |
| 3234 Api::NewLocalHandle(url)); | 3235 Api::NewLocalHandle(url), |
| 3236 Api::NewLocalHandle(import_map)); |
| 3235 if (Dart_IsError(result)) { | 3237 if (Dart_IsError(result)) { |
| 3236 ErrorMsg(token_pos, "library handler failed: %s", Dart_GetError(result)); | 3238 ErrorMsg(token_pos, "library handler failed: %s", Dart_GetError(result)); |
| 3237 } | 3239 } |
| 3238 return result; | 3240 return result; |
| 3239 } | 3241 } |
| 3240 | 3242 |
| 3241 | 3243 |
| 3242 void Parser::ParseLibraryImport() { | 3244 void Parser::ParseLibraryImport() { |
| 3243 while (CurrentToken() == Token::kIMPORT) { | 3245 while (CurrentToken() == Token::kIMPORT) { |
| 3244 const intptr_t import_pos = token_index_; | 3246 const intptr_t import_pos = token_index_; |
| 3245 ConsumeToken(); | 3247 ConsumeToken(); |
| 3246 ExpectToken(Token::kLPAREN); | 3248 ExpectToken(Token::kLPAREN); |
| 3247 if (CurrentToken() != Token::kSTRING) { | 3249 if (CurrentToken() != Token::kSTRING) { |
| 3248 ErrorMsg("library url expected"); | 3250 ErrorMsg("library url expected"); |
| 3249 } | 3251 } |
| 3250 const String& url = *CurrentLiteral(); | 3252 const String& url = *ParseImportStringLiteral(); |
| 3251 ConsumeToken(); | |
| 3252 String& prefix = String::Handle(); | 3253 String& prefix = String::Handle(); |
| 3253 if (CurrentToken() == Token::kCOMMA) { | 3254 if (CurrentToken() == Token::kCOMMA) { |
| 3254 ConsumeToken(); | 3255 ConsumeToken(); |
| 3255 if (!IsLiteral("prefix")) { | 3256 if (!IsLiteral("prefix")) { |
| 3256 ErrorMsg("prefix: expected"); | 3257 ErrorMsg("prefix: expected"); |
| 3257 } | 3258 } |
| 3258 ConsumeToken(); | 3259 ConsumeToken(); |
| 3259 ExpectToken(Token::kCOLON); | 3260 ExpectToken(Token::kCOLON); |
| 3260 if (CurrentToken() != Token::kSTRING) { | 3261 if (CurrentToken() != Token::kSTRING) { |
| 3261 ErrorMsg("prefix expected"); | 3262 ErrorMsg("prefix expected"); |
| 3262 } | 3263 } |
| 3263 prefix = CurrentLiteral()->raw(); | 3264 prefix = CurrentLiteral()->raw(); |
| 3264 // TODO(asiva): Need to also check that prefix is not a reserved keyword. | 3265 // TODO(asiva): Need to also check that prefix is not a reserved keyword. |
| 3265 if (!Scanner::IsIdent(prefix)) { | 3266 if (!Scanner::IsIdent(prefix)) { |
| 3266 ErrorMsg("prefix should be an identifier"); | 3267 ErrorMsg("prefix should be an identifier"); |
| 3267 } | 3268 } |
| 3268 ConsumeToken(); | 3269 ConsumeToken(); |
| 3269 } | 3270 } |
| 3270 ExpectToken(Token::kRPAREN); | 3271 ExpectToken(Token::kRPAREN); |
| 3271 ExpectToken(Token::kSEMICOLON); | 3272 ExpectToken(Token::kSEMICOLON); |
| 3273 const Array& import_map = Array::Handle(library_.import_map()); |
| 3272 Dart_Handle handle = CallLibraryTagHandler(kCanonicalizeUrl, | 3274 Dart_Handle handle = CallLibraryTagHandler(kCanonicalizeUrl, |
| 3273 import_pos, | 3275 import_pos, |
| 3274 url); | 3276 url, |
| 3277 import_map); |
| 3275 const String& canon_url = String::CheckedHandle(Api::UnwrapHandle(handle)); | 3278 const String& canon_url = String::CheckedHandle(Api::UnwrapHandle(handle)); |
| 3276 // Lookup the library URL. | 3279 // Lookup the library URL. |
| 3277 Library& library = Library::Handle(Library::LookupLibrary(canon_url)); | 3280 Library& library = Library::Handle(Library::LookupLibrary(canon_url)); |
| 3278 if (library.IsNull()) { | 3281 if (library.IsNull()) { |
| 3279 // Call the library tag handler to load the library. | 3282 // Call the library tag handler to load the library. |
| 3280 CallLibraryTagHandler(kImportTag, import_pos, canon_url); | 3283 CallLibraryTagHandler(kImportTag, import_pos, canon_url, import_map); |
| 3281 // If the library tag handler succeded without registering the | 3284 // If the library tag handler succeded without registering the |
| 3282 // library we create an empty library to import. | 3285 // library we create an empty library to import. |
| 3283 library = Library::LookupLibrary(canon_url); | 3286 library = Library::LookupLibrary(canon_url); |
| 3284 if (library.IsNull()) { | 3287 if (library.IsNull()) { |
| 3285 library = Library::New(canon_url); | 3288 library = Library::New(canon_url); |
| 3286 library.Register(); | 3289 library.Register(); |
| 3287 } | 3290 } |
| 3288 } | 3291 } |
| 3289 // Add the import to the library. | 3292 // Add the import to the library. |
| 3290 if (prefix.IsNull() || (prefix.Length() == 0)) { | 3293 if (prefix.IsNull() || (prefix.Length() == 0)) { |
| 3291 library_.AddImport(library); | 3294 library_.AddImport(library); |
| 3292 } else { | 3295 } else { |
| 3293 if (library_.LookupLocalObject(prefix) != Object::null()) { | 3296 if (library_.LookupLocalObject(prefix) != Object::null()) { |
| 3294 ErrorMsg(token_index_, "'%s' is already defined", prefix.ToCString()); | 3297 ErrorMsg(token_index_, "'%s' is already defined", prefix.ToCString()); |
| 3295 } | 3298 } |
| 3296 const LibraryPrefix& library_prefix = | 3299 const LibraryPrefix& library_prefix = |
| 3297 LibraryPrefix::Handle(LibraryPrefix::New(prefix, library)); | 3300 LibraryPrefix::Handle(LibraryPrefix::New(prefix, library)); |
| 3298 library_.AddObject(library_prefix, prefix); | 3301 library_.AddObject(library_prefix, prefix); |
| 3299 } | 3302 } |
| 3300 } | 3303 } |
| 3301 } | 3304 } |
| 3302 | 3305 |
| 3303 | 3306 |
| 3304 void Parser::ParseLibraryInclude() { | 3307 void Parser::ParseLibraryInclude() { |
| 3308 const Array& import_map = Array::Handle(library_.import_map()); |
| 3305 while (CurrentToken() == Token::kSOURCE) { | 3309 while (CurrentToken() == Token::kSOURCE) { |
| 3306 const intptr_t source_pos = token_index_; | 3310 const intptr_t source_pos = token_index_; |
| 3307 ConsumeToken(); | 3311 ConsumeToken(); |
| 3308 ExpectToken(Token::kLPAREN); | 3312 ExpectToken(Token::kLPAREN); |
| 3309 if (CurrentToken() != Token::kSTRING) { | 3313 if (CurrentToken() != Token::kSTRING) { |
| 3310 ErrorMsg("source url expected"); | 3314 ErrorMsg("source url expected"); |
| 3311 } | 3315 } |
| 3312 const String& url = *CurrentLiteral(); | 3316 const String& url = *ParseImportStringLiteral(); |
| 3313 ConsumeToken(); | |
| 3314 ExpectToken(Token::kRPAREN); | 3317 ExpectToken(Token::kRPAREN); |
| 3315 ExpectToken(Token::kSEMICOLON); | 3318 ExpectToken(Token::kSEMICOLON); |
| 3316 Dart_Handle handle = CallLibraryTagHandler(kCanonicalizeUrl, | 3319 Dart_Handle handle = CallLibraryTagHandler(kCanonicalizeUrl, |
| 3317 source_pos, | 3320 source_pos, |
| 3318 url); | 3321 url, |
| 3322 import_map); |
| 3319 const String& canon_url = String::CheckedHandle(Api::UnwrapHandle(handle)); | 3323 const String& canon_url = String::CheckedHandle(Api::UnwrapHandle(handle)); |
| 3320 CallLibraryTagHandler(kSourceTag, source_pos, canon_url); | 3324 CallLibraryTagHandler(kSourceTag, source_pos, canon_url, import_map); |
| 3321 } | 3325 } |
| 3322 } | 3326 } |
| 3323 | 3327 |
| 3324 | 3328 |
| 3325 void Parser::ParseLibraryDefinition() { | 3329 void Parser::ParseLibraryDefinition() { |
| 3326 // Handle the script tag. | 3330 // Handle the script tag. |
| 3327 if (CurrentToken() == Token::kSCRIPTTAG) { | 3331 if (CurrentToken() == Token::kSCRIPTTAG) { |
| 3328 // Nothing to do for script tags except to skip them. | 3332 // Nothing to do for script tags except to skip them. |
| 3329 ConsumeToken(); | 3333 ConsumeToken(); |
| 3330 } | 3334 } |
| (...skipping 3308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6639 } else { | 6643 } else { |
| 6640 ASSERT(primary->primary().IsClass()); | 6644 ASSERT(primary->primary().IsClass()); |
| 6641 ErrorMsg(ident_pos, "illegal reference to class or interface '%s'", | 6645 ErrorMsg(ident_pos, "illegal reference to class or interface '%s'", |
| 6642 ident.ToCString()); | 6646 ident.ToCString()); |
| 6643 } | 6647 } |
| 6644 } | 6648 } |
| 6645 return var_or_field; | 6649 return var_or_field; |
| 6646 } | 6650 } |
| 6647 | 6651 |
| 6648 | 6652 |
| 6653 // Resolve variables used in an import string literal. |
| 6654 // If the variable name cannot be resolved issue an error message. |
| 6655 // Currently we only resolve against the global map which is passed in |
| 6656 // when the script is loaded. |
| 6657 RawString* Parser::ResolveImportVar(intptr_t ident_pos, const String& ident) { |
| 6658 TRACE_PARSER("ResolveImportVar"); |
| 6659 String& map_name = String::Handle(library_.LookupImportMap(ident)); |
| 6660 if (!map_name.IsNull()) { |
| 6661 return map_name.raw(); |
| 6662 } |
| 6663 ErrorMsg(ident_pos, "import variable '%s' has not been defined", |
| 6664 ident.ToCString()); |
| 6665 return String::null(); |
| 6666 } |
| 6667 |
| 6668 |
| 6649 // Parses type = [ident "."] ident ["<" type { "," type } ">"]. | 6669 // Parses type = [ident "."] ident ["<" type { "," type } ">"]. |
| 6650 // Returns the class object if the type can be resolved. Otherwise, either give | 6670 // Returns the class object if the type can be resolved. Otherwise, either give |
| 6651 // an error if type resolution was required, or return the unresolved name as a | 6671 // an error if type resolution was required, or return the unresolved name as a |
| 6652 // string object. | 6672 // string object. |
| 6653 RawAbstractType* Parser::ParseType(TypeResolution type_resolution) { | 6673 RawAbstractType* Parser::ParseType(TypeResolution type_resolution) { |
| 6654 if (CurrentToken() != Token::kIDENT) { | 6674 if (CurrentToken() != Token::kIDENT) { |
| 6655 ErrorMsg("type name expected"); | 6675 ErrorMsg("type name expected"); |
| 6656 } | 6676 } |
| 6657 QualIdent type_name; | 6677 QualIdent type_name; |
| 6658 if (type_resolution == kIgnore) { | 6678 if (type_resolution == kIgnore) { |
| (...skipping 657 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7316 if ((CurrentToken() == Token::kSTRING) && | 7336 if ((CurrentToken() == Token::kSTRING) && |
| 7317 (LookaheadToken(1) != Token::kINTERPOL_VAR) && | 7337 (LookaheadToken(1) != Token::kINTERPOL_VAR) && |
| 7318 (LookaheadToken(1) != Token::kINTERPOL_START)) { | 7338 (LookaheadToken(1) != Token::kINTERPOL_START)) { |
| 7319 // Common case: no interpolation. | 7339 // Common case: no interpolation. |
| 7320 primary = new LiteralNode(literal_start, *CurrentLiteral()); | 7340 primary = new LiteralNode(literal_start, *CurrentLiteral()); |
| 7321 ConsumeToken(); | 7341 ConsumeToken(); |
| 7322 return primary; | 7342 return primary; |
| 7323 } | 7343 } |
| 7324 // String interpolation needed. | 7344 // String interpolation needed. |
| 7325 ArrayNode* values = new ArrayNode(token_index_, TypeArguments::ZoneHandle()); | 7345 ArrayNode* values = new ArrayNode(token_index_, TypeArguments::ZoneHandle()); |
| 7326 GrowableArray<const Object*> arg_values; | |
| 7327 while (CurrentToken() == Token::kSTRING) { | 7346 while (CurrentToken() == Token::kSTRING) { |
| 7328 values->AddElement(new LiteralNode(token_index_, *CurrentLiteral())); | 7347 values->AddElement(new LiteralNode(token_index_, *CurrentLiteral())); |
| 7329 ConsumeToken(); | 7348 ConsumeToken(); |
| 7330 if ((CurrentToken() != Token::kINTERPOL_VAR) && | 7349 if ((CurrentToken() != Token::kINTERPOL_VAR) && |
| 7331 (CurrentToken() != Token::kINTERPOL_START)) { | 7350 (CurrentToken() != Token::kINTERPOL_START)) { |
| 7332 break; | 7351 break; |
| 7333 } | 7352 } |
| 7334 while ((CurrentToken() == Token::kINTERPOL_VAR) || | 7353 while ((CurrentToken() == Token::kINTERPOL_VAR) || |
| 7335 (CurrentToken() == Token::kINTERPOL_START)) { | 7354 (CurrentToken() == Token::kINTERPOL_START)) { |
| 7336 AstNode* expr = NULL; | 7355 AstNode* expr = NULL; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 7352 ArgumentListNode* interpolate_arg = | 7371 ArgumentListNode* interpolate_arg = |
| 7353 new ArgumentListNode(values->token_index()); | 7372 new ArgumentListNode(values->token_index()); |
| 7354 interpolate_arg->Add(values); | 7373 interpolate_arg->Add(values); |
| 7355 primary = MakeStaticCall(kStringClassName, | 7374 primary = MakeStaticCall(kStringClassName, |
| 7356 kInterpolateName, | 7375 kInterpolateName, |
| 7357 interpolate_arg); | 7376 interpolate_arg); |
| 7358 return primary; | 7377 return primary; |
| 7359 } | 7378 } |
| 7360 | 7379 |
| 7361 | 7380 |
| 7381 // An import string literal consists of the concatenation of the next n tokens |
| 7382 // that satisfy the EBNF grammar: |
| 7383 // literal = kSTRING {{ interpol }+ kSTRING } |
| 7384 // interpol = kINTERPOL_VAR |
| 7385 // In other words, the scanner breaks down interpolated strings so that |
| 7386 // a string literal always begins and ends with a kSTRING token, and |
| 7387 // there are never two kSTRING tokens next to each other. |
| 7388 String* Parser::ParseImportStringLiteral() { |
| 7389 if ((CurrentToken() == Token::kSTRING) && |
| 7390 (LookaheadToken(1) != Token::kINTERPOL_VAR) && |
| 7391 (LookaheadToken(1) != Token::kINTERPOL_START)) { |
| 7392 // Common case: no interpolation. |
| 7393 String* result = CurrentLiteral(); |
| 7394 ConsumeToken(); |
| 7395 return result; |
| 7396 } |
| 7397 // String interpolation needed. |
| 7398 String& result = String::ZoneHandle(String::New("")); |
| 7399 String& resolved_name = String::Handle(); |
| 7400 while (CurrentToken() == Token::kSTRING) { |
| 7401 result = String::Concat(result, *CurrentLiteral()); |
| 7402 ConsumeToken(); |
| 7403 if ((CurrentToken() != Token::kINTERPOL_VAR) && |
| 7404 (CurrentToken() != Token::kINTERPOL_START)) { |
| 7405 break; |
| 7406 } |
| 7407 while ((CurrentToken() == Token::kINTERPOL_VAR) || |
| 7408 (CurrentToken() == Token::kINTERPOL_START)) { |
| 7409 if (CurrentToken() == Token::kINTERPOL_START) { |
| 7410 ConsumeToken(); |
| 7411 if (IsIdentifier()) { |
| 7412 resolved_name = ResolveImportVar(token_index_, *CurrentLiteral()); |
| 7413 result = String::Concat(result, resolved_name); |
| 7414 ConsumeToken(); |
| 7415 if (CurrentToken() != Token::kINTERPOL_END) { |
| 7416 ErrorMsg("'}' expected"); |
| 7417 } |
| 7418 ConsumeToken(); |
| 7419 } else { |
| 7420 ErrorMsg("identifier expected"); |
| 7421 } |
| 7422 } else { |
| 7423 ASSERT(CurrentToken() == Token::kINTERPOL_VAR); |
| 7424 resolved_name = ResolveImportVar(token_index_, *CurrentLiteral()); |
| 7425 result = String::Concat(result, resolved_name); |
| 7426 ConsumeToken(); |
| 7427 } |
| 7428 } |
| 7429 // A string literal always ends with a kSTRING token. |
| 7430 ASSERT(CurrentToken() == Token::kSTRING); |
| 7431 } |
| 7432 return &result; |
| 7433 } |
| 7434 |
| 7435 |
| 7362 AstNode* Parser::ParsePrimary() { | 7436 AstNode* Parser::ParsePrimary() { |
| 7363 TRACE_PARSER("ParsePrimary"); | 7437 TRACE_PARSER("ParsePrimary"); |
| 7364 ASSERT(!is_top_level_); | 7438 ASSERT(!is_top_level_); |
| 7365 AstNode* primary = NULL; | 7439 AstNode* primary = NULL; |
| 7366 if (IsFunctionLiteral()) { | 7440 if (IsFunctionLiteral()) { |
| 7367 // The name of a literal function is visible from inside the function, but | 7441 // The name of a literal function is visible from inside the function, but |
| 7368 // must not collide with names in the scope declaring the literal. | 7442 // must not collide with names in the scope declaring the literal. |
| 7369 OpenBlock(); | 7443 OpenBlock(); |
| 7370 primary = ParseFunctionStatement(true); | 7444 primary = ParseFunctionStatement(true); |
| 7371 CloseBlock(); | 7445 CloseBlock(); |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7760 void Parser::SkipQualIdent() { | 7834 void Parser::SkipQualIdent() { |
| 7761 ASSERT(IsIdentifier()); | 7835 ASSERT(IsIdentifier()); |
| 7762 ConsumeToken(); | 7836 ConsumeToken(); |
| 7763 if (CurrentToken() == Token::kPERIOD) { | 7837 if (CurrentToken() == Token::kPERIOD) { |
| 7764 ConsumeToken(); // Consume the kPERIOD token. | 7838 ConsumeToken(); // Consume the kPERIOD token. |
| 7765 ExpectIdentifier("identifier expected after '.'"); | 7839 ExpectIdentifier("identifier expected after '.'"); |
| 7766 } | 7840 } |
| 7767 } | 7841 } |
| 7768 | 7842 |
| 7769 } // namespace dart | 7843 } // namespace dart |
| OLD | NEW |