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

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

Issue 9582040: Re-introduce string concatenation (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 9 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-runtime.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 "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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/co19/co19-runtime.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698