about summary refs log tree commit diff
path: root/src/libexpr/parser.y
diff options
context:
space:
mode:
Diffstat (limited to 'src/libexpr/parser.y')
-rw-r--r--src/libexpr/parser.y17
1 files changed, 15 insertions, 2 deletions
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index ec07a0191971..cba390d8dad8 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -25,6 +25,7 @@ void parseError(void * data, char * error, int line, int column);
 ATerm absParsedPath(void * data, ATerm t);
 ATerm fixAttrs(int recursive, ATermList as);
 const char * getPath(void * data);
+void backToString(yyscan_t scanner);
 
 void yyerror(YYLTYPE * loc, yyscan_t scanner, void * data, char * s)
 {
@@ -73,9 +74,10 @@ static void freeAndUnprotect(void * p)
 
 %type <t> start expr expr_function expr_if expr_op
 %type <t> expr_app expr_select expr_simple bind inheritsrc formal
-%type <ts> binds ids expr_list formals
+%type <ts> binds ids expr_list formals string_parts
 %token <t> ID INT STR PATH URI
 %token IF THEN ELSE ASSERT WITH LET REC INHERIT EQ NEQ AND OR IMPL
+%token DOLLAR_CURLY /* == ${ */
 
 %nonassoc IMPL
 %left OR
@@ -142,7 +144,12 @@ expr_select
 expr_simple
   : ID { $$ = makeVar($1); }
   | INT { $$ = makeInt(ATgetInt((ATermInt) $1)); }
-  | STR { $$ = makeStr($1); }
+  | '"' string_parts '"' {
+      /* For efficiency, and to simplify parse trees a bit. */
+      if ($2 == ATempty) $$ = makeStr(toATerm(""));
+      else if (ATgetNext($2) == ATempty) $$ = ATgetFirst($2);
+      else $$ = makeConcatStrings(ATreverse($2));
+  }
   | PATH { $$ = makePath(absParsedPath(data, $1)); }
   | URI { $$ = makeUri($1); }
   | '(' expr ')' { $$ = $2; }
@@ -157,6 +164,12 @@ expr_simple
   | '[' expr_list ']' { $$ = makeList($2); }
   ;
 
+string_parts
+  : string_parts STR { $$ = ATinsert($1, $2); }
+  | string_parts DOLLAR_CURLY expr '}' { backToString(scanner); $$ = ATinsert($1, $3); }
+  | { $$ = ATempty; }
+  ;
+
 binds
   : binds bind { $$ = ATinsert($1, $2); }
   | { $$ = ATempty; }