| 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 7470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7481 // Make sure that the instantiator is captured. | 7481 // Make sure that the instantiator is captured. |
| 7482 CaptureReceiver(); | 7482 CaptureReceiver(); |
| 7483 } | 7483 } |
| 7484 new_object = new ConstructorCallNode( | 7484 new_object = new ConstructorCallNode( |
| 7485 new_pos, type_arguments, constructor, arguments); | 7485 new_pos, type_arguments, constructor, arguments); |
| 7486 } | 7486 } |
| 7487 return new_object; | 7487 return new_object; |
| 7488 } | 7488 } |
| 7489 | 7489 |
| 7490 | 7490 |
| 7491 String& Parser::Interpolate(ArrayNode* values) { |
| 7492 const String& class_name = |
| 7493 String::Handle(String::NewSymbol(kStringClassName)); |
| 7494 const Class& cls = Class::Handle(LookupImplClass(class_name)); |
| 7495 ASSERT(!cls.IsNull()); |
| 7496 const String& func_name = String::Handle(String::NewSymbol(kInterpolateName)); |
| 7497 const Function& func = |
| 7498 Function::Handle(cls.LookupStaticFunction(func_name)); |
| 7499 ASSERT(!func.IsNull()); |
| 7500 |
| 7501 // Build the array of literal values to interpolate. |
| 7502 const Array& value_arr = Array::Handle(Array::New(values->length())); |
| 7503 for (int i = 0; i < values->length(); i++) { |
| 7504 ASSERT(values->ElementAt(i)->IsLiteralNode()); |
| 7505 value_arr.SetAt(i, values->ElementAt(i)->AsLiteralNode()->literal()); |
| 7506 } |
| 7507 |
| 7508 // Build argument array to pass to the interpolation function. |
| 7509 GrowableArray<const Object*> interpolate_arg; |
| 7510 interpolate_arg.Add(&value_arr); |
| 7511 const Array& kNoArgumentNames = Array::Handle(); |
| 7512 |
| 7513 // Call interpolation function. |
| 7514 String& concatenated = String::ZoneHandle(); |
| 7515 concatenated ^= DartEntry::InvokeStatic(func, |
| 7516 interpolate_arg, |
| 7517 kNoArgumentNames); |
| 7518 if (concatenated.IsUnhandledException()) { |
| 7519 ErrorMsg("Exception thrown in Parser::Interpolate"); |
| 7520 } |
| 7521 concatenated = String::NewSymbol(concatenated); |
| 7522 return concatenated; |
| 7523 } |
| 7524 |
| 7525 |
| 7491 // A string literal consists of the concatenation of the next n tokens | 7526 // A string literal consists of the concatenation of the next n tokens |
| 7492 // that satisfy the EBNF grammar: | 7527 // that satisfy the EBNF grammar: |
| 7493 // literal = kSTRING {{ interpol }+ kSTRING } | 7528 // literal = kSTRING {{ interpol } kSTRING } |
| 7494 // interpol = kINTERPOL_VAR | (kINTERPOL_START expression kINTERPOL_END) | 7529 // interpol = kINTERPOL_VAR | (kINTERPOL_START expression kINTERPOL_END) |
| 7495 // In other words, the scanner breaks down interpolated strings so that | 7530 // In other words, the scanner breaks down interpolated strings so that |
| 7496 // a string literal always begins and ends with a kSTRING token, and | 7531 // a string literal always begins and ends with a kSTRING token. |
| 7497 // there are never two kSTRING tokens next to each other. | |
| 7498 AstNode* Parser::ParseStringLiteral() { | 7532 AstNode* Parser::ParseStringLiteral() { |
| 7499 TRACE_PARSER("ParseStringLiteral"); | 7533 TRACE_PARSER("ParseStringLiteral"); |
| 7500 AstNode* primary = NULL; | 7534 AstNode* primary = NULL; |
| 7501 const intptr_t literal_start = token_index_; | 7535 const intptr_t literal_start = token_index_; |
| 7502 if ((CurrentToken() == Token::kSTRING) && | 7536 ASSERT(CurrentToken() == Token::kSTRING); |
| 7503 (LookaheadToken(1) != Token::kINTERPOL_VAR) && | 7537 Token::Kind l1_token = LookaheadToken(1); |
| 7504 (LookaheadToken(1) != Token::kINTERPOL_START)) { | 7538 if ((l1_token != Token::kSTRING) && |
| 7539 (l1_token != Token::kINTERPOL_VAR) && |
| 7540 (l1_token != Token::kINTERPOL_START)) { |
| 7505 // Common case: no interpolation. | 7541 // Common case: no interpolation. |
| 7506 primary = new LiteralNode(literal_start, *CurrentLiteral()); | 7542 primary = new LiteralNode(literal_start, *CurrentLiteral()); |
| 7507 ConsumeToken(); | 7543 ConsumeToken(); |
| 7508 return primary; | 7544 return primary; |
| 7509 } | 7545 } |
| 7510 // String interpolation needed. | 7546 // String interpolation needed. |
| 7547 bool is_compiletime_const = true; |
| 7511 ArrayNode* values = new ArrayNode(token_index_, TypeArguments::ZoneHandle()); | 7548 ArrayNode* values = new ArrayNode(token_index_, TypeArguments::ZoneHandle()); |
| 7512 while (CurrentToken() == Token::kSTRING) { | 7549 while (CurrentToken() == Token::kSTRING) { |
| 7513 values->AddElement(new LiteralNode(token_index_, *CurrentLiteral())); | 7550 values->AddElement(new LiteralNode(token_index_, *CurrentLiteral())); |
| 7514 ConsumeToken(); | 7551 ConsumeToken(); |
| 7515 if ((CurrentToken() != Token::kINTERPOL_VAR) && | |
| 7516 (CurrentToken() != Token::kINTERPOL_START)) { | |
| 7517 break; | |
| 7518 } | |
| 7519 while ((CurrentToken() == Token::kINTERPOL_VAR) || | 7552 while ((CurrentToken() == Token::kINTERPOL_VAR) || |
| 7520 (CurrentToken() == Token::kINTERPOL_START)) { | 7553 (CurrentToken() == Token::kINTERPOL_START)) { |
| 7521 AstNode* expr = NULL; | 7554 AstNode* expr = NULL; |
| 7555 const intptr_t expr_pos = token_index_; |
| 7556 // TODO(hausner): Remove the statement below when we allow interpolated |
| 7557 // strings to be compile time constants. |
| 7558 is_compiletime_const = false; |
| 7522 if (CurrentToken() == Token::kINTERPOL_VAR) { | 7559 if (CurrentToken() == Token::kINTERPOL_VAR) { |
| 7523 expr = ResolveVarOrField(token_index_, *CurrentLiteral()); | 7560 expr = ResolveVarOrField(token_index_, *CurrentLiteral()); |
| 7524 ASSERT(!expr->IsPrimaryNode()); | 7561 ASSERT(!expr->IsPrimaryNode()); |
| 7525 ConsumeToken(); | 7562 ConsumeToken(); |
| 7526 } else { | 7563 } else { |
| 7527 ASSERT(CurrentToken() == Token::kINTERPOL_START); | 7564 ASSERT(CurrentToken() == Token::kINTERPOL_START); |
| 7528 ConsumeToken(); | 7565 ConsumeToken(); |
| 7529 expr = ParseExpr(kAllowConst); | 7566 expr = ParseExpr(kAllowConst); |
| 7530 ExpectToken(Token::kINTERPOL_END); | 7567 ExpectToken(Token::kINTERPOL_END); |
| 7531 } | 7568 } |
| 7569 // Check if this interpolated string is still considered a compile time |
| 7570 // constant. If it is we need to evaluate if the current string part is |
| 7571 // a constant or not. |
| 7572 if (is_compiletime_const) { |
| 7573 const Object* const_expr = expr->EvalConstExpr(); |
| 7574 if (const_expr != NULL) { |
| 7575 // Change expr into a literal. |
| 7576 expr = new LiteralNode(expr_pos, EvaluateConstExpr(expr)); |
| 7577 } else { |
| 7578 is_compiletime_const = false; |
| 7579 } |
| 7580 } |
| 7532 values->AddElement(expr); | 7581 values->AddElement(expr); |
| 7533 } | 7582 } |
| 7534 // A string literal always ends with a kSTRING token. | |
| 7535 ASSERT(CurrentToken() == Token::kSTRING); | |
| 7536 } | 7583 } |
| 7537 ArgumentListNode* interpolate_arg = | 7584 if (is_compiletime_const) { |
| 7538 new ArgumentListNode(values->token_index()); | 7585 primary = new LiteralNode(literal_start, Interpolate(values)); |
| 7539 interpolate_arg->Add(values); | 7586 } else { |
| 7540 primary = MakeStaticCall(kStringClassName, | 7587 ArgumentListNode* interpolate_arg = |
| 7541 kInterpolateName, | 7588 new ArgumentListNode(values->token_index()); |
| 7542 interpolate_arg); | 7589 interpolate_arg->Add(values); |
| 7590 primary = MakeStaticCall(kStringClassName, |
| 7591 kInterpolateName, |
| 7592 interpolate_arg); |
| 7593 } |
| 7543 return primary; | 7594 return primary; |
| 7544 } | 7595 } |
| 7545 | 7596 |
| 7546 | 7597 |
| 7547 // An import string literal consists of the concatenation of the next n tokens | 7598 // An import string literal consists of the concatenation of the next n tokens |
| 7548 // that satisfy the EBNF grammar: | 7599 // that satisfy the EBNF grammar: |
| 7549 // literal = kSTRING {{ interpol }+ kSTRING } | 7600 // literal = kSTRING {{ interpol }+ kSTRING } |
| 7550 // interpol = kINTERPOL_VAR | 7601 // interpol = kINTERPOL_VAR |
| 7551 // In other words, the scanner breaks down interpolated strings so that | 7602 // In other words, the scanner breaks down interpolated strings so that |
| 7552 // a string literal always begins and ends with a kSTRING token, and | 7603 // a string literal always begins and ends with a kSTRING token, and |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7850 return; | 7901 return; |
| 7851 } | 7902 } |
| 7852 } | 7903 } |
| 7853 } | 7904 } |
| 7854 | 7905 |
| 7855 | 7906 |
| 7856 void Parser::SkipStringLiteral() { | 7907 void Parser::SkipStringLiteral() { |
| 7857 ASSERT(CurrentToken() == Token::kSTRING); | 7908 ASSERT(CurrentToken() == Token::kSTRING); |
| 7858 while (CurrentToken() == Token::kSTRING) { | 7909 while (CurrentToken() == Token::kSTRING) { |
| 7859 ConsumeToken(); | 7910 ConsumeToken(); |
| 7860 if ((CurrentToken() != Token::kINTERPOL_VAR) && | |
| 7861 (CurrentToken() != Token::kINTERPOL_START)) { | |
| 7862 break; | |
| 7863 } | |
| 7864 while (true) { | 7911 while (true) { |
| 7865 if (CurrentToken() == Token::kINTERPOL_VAR) { | 7912 if (CurrentToken() == Token::kINTERPOL_VAR) { |
| 7866 ConsumeToken(); | 7913 ConsumeToken(); |
| 7867 } else if (CurrentToken() == Token::kINTERPOL_START) { | 7914 } else if (CurrentToken() == Token::kINTERPOL_START) { |
| 7868 ConsumeToken(); | 7915 ConsumeToken(); |
| 7869 SkipExpr(); | 7916 SkipExpr(); |
| 7870 ExpectToken(Token::kINTERPOL_END); | 7917 ExpectToken(Token::kINTERPOL_END); |
| 7871 } else { | 7918 } else { |
| 7872 break; | 7919 break; |
| 7873 } | 7920 } |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8007 void Parser::SkipQualIdent() { | 8054 void Parser::SkipQualIdent() { |
| 8008 ASSERT(IsIdentifier()); | 8055 ASSERT(IsIdentifier()); |
| 8009 ConsumeToken(); | 8056 ConsumeToken(); |
| 8010 if (CurrentToken() == Token::kPERIOD) { | 8057 if (CurrentToken() == Token::kPERIOD) { |
| 8011 ConsumeToken(); // Consume the kPERIOD token. | 8058 ConsumeToken(); // Consume the kPERIOD token. |
| 8012 ExpectIdentifier("identifier expected after '.'"); | 8059 ExpectIdentifier("identifier expected after '.'"); |
| 8013 } | 8060 } |
| 8014 } | 8061 } |
| 8015 | 8062 |
| 8016 } // namespace dart | 8063 } // namespace dart |
| OLD | NEW |