@@ -7312,6 +7312,7 @@ final class Parser(AST) : Lexer
73127312 auto s = token.ustring;
73137313 auto len = token.len;
73147314 auto postfix = token.postfix;
7315+ auto interpolate = token.interpolate;
73157316 while (1 )
73167317 {
73177318 const prev = token;
@@ -7324,6 +7325,11 @@ final class Parser(AST) : Lexer
73247325 error(" mismatched string literal postfixes `'%c'` and `'%c'`" , postfix, token.postfix);
73257326 postfix = token.postfix;
73267327 }
7328+ if (interpolate != token.interpolate)
7329+ {
7330+ error(" cannot concatenate interpolated strings with non-interpolated strings" );
7331+ interpolate = true ;
7332+ }
73277333
73287334 deprecation(" Implicit string concatenation is deprecated, use %s ~ %s instead" ,
73297335 prev.toChars(), token.toChars());
@@ -7339,7 +7345,10 @@ final class Parser(AST) : Lexer
73397345 else
73407346 break ;
73417347 }
7342- e = new AST .StringExp(loc, cast (char * )s, len, postfix);
7348+ if (interpolate)
7349+ e = new AST .TupleExp(loc, parseInterpolatedString(loc, s, len, postfix));
7350+ else
7351+ e = new AST .StringExp(loc, cast (char * )s, len, postfix);
73437352 break ;
73447353 }
73457354 case TOK .void_:
@@ -8560,6 +8569,98 @@ final class Parser(AST) : Lexer
85608569 token.lineComment = null ;
85618570 }
85628571 }
8572+
8573+ /**
8574+ Parse the given interpolated string `str` into an array of expressions.
8575+
8576+ Params:
8577+ loc = the location of the interpolated string
8578+ str = the interpolated string to parse
8579+ len = the length of the interpolated string
8580+ postfix = the interpolated string postix, i.e 'c', 'w' or 'd'
8581+
8582+ Returns:
8583+ An array of expressions representing the interpolated string.
8584+ */
8585+ AST .Expressions* parseInterpolatedString (ref const (Loc) loc, const (char )* str, uint len, ubyte postfix)
8586+ {
8587+ // printf("parseInterpolatedString '%.*s'\n", len, str);
8588+ auto parts = new AST .Expressions();
8589+
8590+ auto mark = 0 ;
8591+ auto next = 0 ;
8592+ void addMarkToNext ()
8593+ {
8594+ if (next > mark)
8595+ parts.push(new AST .StringExp(loc, cast (char * )str + mark, next - mark, postfix));
8596+ }
8597+ MainLoop:
8598+ for (; next < len;)
8599+ {
8600+ // printf("[DEBUG] str[%d] = '%c'\n", next, str[next]);
8601+ if (str[next] != ' $' )
8602+ {
8603+ next++ ;
8604+ }
8605+ else
8606+ {
8607+ addMarkToNext();
8608+ if (next + 1 >= len)
8609+ {
8610+ error(" unfinished interpolated string expression '$'" );
8611+ mark = next;
8612+ break ;
8613+ }
8614+ if (str[next + 1 ] == ' (' )
8615+ {
8616+ next += 2 ;
8617+ mark = next;
8618+ for (uint depth = 1 ;; next++ )
8619+ {
8620+ if (next >= len)
8621+ {
8622+ error(" unfinished interpolated string expression '$(...)'" );
8623+ mark = next;
8624+ break MainLoop;
8625+ }
8626+ auto c = str[next];
8627+ if (c == ' )' )
8628+ {
8629+ depth-- ;
8630+ if (depth == 0 )
8631+ break ;
8632+ }
8633+ else if (c == ' (' )
8634+ {
8635+ depth++ ;
8636+ }
8637+ }
8638+ {
8639+ auto expr = str[mark .. next];
8640+ // printf("[DEBUG] parsing the expression '%.*s'\n", expr.length, expr.ptr);
8641+ scope tempParser = new Parser! AST (/* loc, */ mod, expr, false );
8642+ tempParser.nextToken();
8643+ auto result = tempParser.parseExpression();
8644+ // printf("[DEBUG] parsed to '%s'\n", result.toChars());
8645+ if (tempParser.token.value != TOK .rightParentheses)
8646+ {
8647+ error(" invalid expression '%.*s' inside interpolated string" , expr.length, expr.ptr);
8648+ }
8649+ parts.push(result);
8650+ }
8651+ next++ ;
8652+ mark = next;
8653+ }
8654+ else
8655+ {
8656+ assert (0 , " not implemented" );
8657+ }
8658+ }
8659+ }
8660+ addMarkToNext();
8661+
8662+ return parts;
8663+ }
85638664}
85648665
85658666enum PREC : int
0 commit comments