about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libexpr/lexer.l42
-rw-r--r--src/libexpr/parser.y19
2 files changed, 19 insertions, 42 deletions
diff --git a/src/libexpr/lexer.l b/src/libexpr/lexer.l
index 7051909008d1..7483e5cc4acb 100644
--- a/src/libexpr/lexer.l
+++ b/src/libexpr/lexer.l
@@ -1,6 +1,9 @@
 %option reentrant bison-bridge bison-locations
 %option noyywrap
 %option never-interactive
+%option stack
+%option nodefault
+%option nounput noyy_top_state
 
 
 %x STRING
@@ -74,6 +77,9 @@ static Expr * unescapeStr(SymbolTable & symbols, const char * s)
 #define YY_USER_INIT initLoc(yylloc)
 #define YY_USER_ACTION adjustLoc(yylloc, yytext, yyleng);
 
+#define PUSH_STATE(state) yy_push_state(state, yyscanner)
+#define POP_STATE() yy_pop_state(yyscanner)
+
 %}
 
 
@@ -118,9 +124,11 @@ or          { return OR_KW; }
               return INT;
             }
 
-\$\{        { return DOLLAR_CURLY; }
+\$\{        { PUSH_STATE(INITIAL); return DOLLAR_CURLY; }
+\{          { PUSH_STATE(INITIAL); return '{'; }
+\}          { POP_STATE(); return '}'; }
 
-\"          { BEGIN(STRING); return '"'; }
+\"          { PUSH_STATE(STRING); return '"'; }
 <STRING>([^\$\"\\]|\$[^\{\"]|\\.)+ {
               /* !!! Not quite right: we want a follow restriction on
                  "$", it shouldn't be followed by a "{".  Right now
@@ -130,11 +138,11 @@ or          { return OR_KW; }
               yylval->e = unescapeStr(data->symbols, yytext);
               return STR;
             }
-<STRING>\$\{  { BEGIN(INITIAL); return DOLLAR_CURLY; }
-<STRING>\"  { BEGIN(INITIAL); return '"'; }
+<STRING>\$\{  { PUSH_STATE(INITIAL); return DOLLAR_CURLY; }
+<STRING>\"  { POP_STATE(); return '"'; }
 <STRING>.   return yytext[0]; /* just in case: shouldn't be reached */
 
-\'\'(\ *\n)?     { BEGIN(IND_STRING); return IND_STRING_OPEN; }
+\'\'(\ *\n)?     { PUSH_STATE(IND_STRING); return IND_STRING_OPEN; }
 <IND_STRING>([^\$\']|\$[^\{\']|\'[^\'\$])+ {
                    yylval->e = new ExprIndStr(yytext);
                    return IND_STR;
@@ -151,8 +159,8 @@ or          { return OR_KW; }
                    yylval->e = unescapeStr(data->symbols, yytext + 2);
                    return IND_STR;
                  }
-<IND_STRING>\$\{ { BEGIN(INITIAL); return DOLLAR_CURLY; }
-<IND_STRING>\'\' { BEGIN(INITIAL); return IND_STRING_CLOSE; }
+<IND_STRING>\$\{ { PUSH_STATE(INITIAL); return DOLLAR_CURLY; }
+<IND_STRING>\'\' { POP_STATE(); return IND_STRING_CLOSE; }
 <IND_STRING>\'   {
                    yylval->e = new ExprIndStr("'");
                    return IND_STR;
@@ -173,23 +181,3 @@ or          { return OR_KW; }
 
 %%
 
-
-namespace nix {
-
-/* Horrible, disgusting hack: allow the parser to set the scanner
-   start condition back to STRING.  Necessary in interpolations like
-   "foo${expr}bar"; after the close brace we have to go back to the
-   STRING state. */
-void backToString(yyscan_t scanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t *) scanner;
-    BEGIN(STRING);
-}
-
-void backToIndString(yyscan_t scanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t *) scanner;
-    BEGIN(IND_STRING);
-}
-
-}
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index 26168b2ed420..1f830b7e3c15 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -216,10 +216,6 @@ static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols, vector<Ex
 }
 
 
-void backToString(yyscan_t scanner);
-void backToIndString(yyscan_t scanner);
-
-
 static inline Pos makeCurPos(const YYLTYPE & loc, ParseData * data)
 {
     return Pos(data->path, loc.first_line, loc.first_column);
@@ -404,25 +400,18 @@ string_parts
 
 string_parts_interpolated
   : string_parts_interpolated STR { $$ = $1; $1->push_back($2); }
-  | string_parts_interpolated DOLLAR_CURLY expr '}' { backToString(scanner); $$ = $1; $1->push_back($3); }
-  | STR DOLLAR_CURLY expr '}'
-    {
-      backToString(scanner);
+  | string_parts_interpolated DOLLAR_CURLY expr '}' { $$ = $1; $1->push_back($3); }
+  | DOLLAR_CURLY expr '}' { $$ = new vector<Expr *>; $$->push_back($2); }
+  | STR DOLLAR_CURLY expr '}' {
       $$ = new vector<Expr *>;
       $$->push_back($1);
       $$->push_back($3);
     }
-  | DOLLAR_CURLY expr '}'
-    {
-      backToString(scanner);
-      $$ = new vector<Expr *>;
-      $$->push_back($2);
-    }
   ;
 
 ind_string_parts
   : ind_string_parts IND_STR { $$ = $1; $1->push_back($2); }
-  | ind_string_parts DOLLAR_CURLY expr '}' { backToIndString(scanner); $$ = $1; $1->push_back($3); }
+  | ind_string_parts DOLLAR_CURLY expr '}' { $$ = $1; $1->push_back($3); }
   | { $$ = new vector<Expr *>; }
   ;