about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2010-04-12T22·03+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2010-04-12T22·03+0000
commitd4f0b0fc6cdb9ae2fd5fc057d621bc80b36a7b18 (patch)
treecac761afab880a00b3dced69438e006ca2929114
parenta60317f20fbc8be8e339060d932946f6d99ece6a (diff)
* Indented strings.
-rw-r--r--src/libexpr/eval-test.cc1
-rw-r--r--src/libexpr/eval.cc6
-rw-r--r--src/libexpr/lexer.l19
-rw-r--r--src/libexpr/nixexpr.cc19
-rw-r--r--src/libexpr/nixexpr.hh18
-rw-r--r--src/libexpr/parser.y70
-rw-r--r--src/nix-instantiate/nix-instantiate.cc2
7 files changed, 65 insertions, 70 deletions
diff --git a/src/libexpr/eval-test.cc b/src/libexpr/eval-test.cc
index dd8ead04a68f..782e36d386d0 100644
--- a/src/libexpr/eval-test.cc
+++ b/src/libexpr/eval-test.cc
@@ -67,6 +67,7 @@ void run(Strings args)
     doTest(state, "__add 1 2");
     doTest(state, "null");
     doTest(state, "\"foo\"");
+    doTest(state, "''\n  foo\n  bar\n    ''");
     doTest(state, "let s = \"bar\"; in \"foo${s}\"");
     doTest(state, "if true then 1 else 2");
     doTest(state, "if false then 1 else 2");
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 21c22333bf5a..62b493bbf6af 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -367,6 +367,12 @@ bool EvalState::evalBool(Env & env, Expr * e)
 }
 
 
+void Expr::eval(EvalState & state, Env & env, Value & v)
+{
+    abort();
+}
+
+
 void ExprInt::eval(EvalState & state, Env & env, Value & v)
 {
     mkInt(v, n);
diff --git a/src/libexpr/lexer.l b/src/libexpr/lexer.l
index e905700fded5..7aa05db8c447 100644
--- a/src/libexpr/lexer.l
+++ b/src/libexpr/lexer.l
@@ -111,10 +111,11 @@ inherit     { return INHERIT; }
 
 \"          { BEGIN(STRING); return '"'; }
 <STRING>([^\$\"\\]|\$[^\{\"]|\\.)+ {
-/* !!! Not quite right: we want a follow restriction on "$", it
-   shouldn't be followed by a "{".  Right now "$\"" will be consumed
-   as part of a string, rather than a "$" followed by the string
-   terminator.  Disallow "$\"" for now. */
+              /* !!! Not quite right: we want a follow restriction on
+                 "$", it shouldn't be followed by a "{".  Right now
+                 "$\"" will be consumed as part of a string, rather
+                 than a "$" followed by the string terminator.
+                 Disallow "$\"" for now. */
               yylval->e = unescapeStr(yytext);
               return STR;
             }
@@ -124,25 +125,25 @@ inherit     { return INHERIT; }
 
 \'\'(\ *\n)?     { BEGIN(IND_STRING); return IND_STRING_OPEN; }
 <IND_STRING>([^\$\']|\$[^\{\']|\'[^\'\$])+ {
-                   //yylval->t = makeIndStr(toATerm(yytext));
+                   yylval->e = new ExprIndStr(yytext);
                    return IND_STR;
                  }
 <IND_STRING>\'\'\$ {
-                   //yylval->t = makeIndStr(toATerm("$"));
+                   yylval->e = new ExprIndStr("$");
                    return IND_STR;
                  }
 <IND_STRING>\'\'\' {
-                   //yylval->t = makeIndStr(toATerm("''"));
+                   yylval->e = new ExprIndStr("''");
                    return IND_STR;
                  }
 <IND_STRING>\'\'\\. {
-                   //yylval->t = unescapeStr(yytext + 2);
+                   yylval->e = new ExprIndStr(yytext + 2);
                    return IND_STR;
                  }
 <IND_STRING>\$\{ { BEGIN(INITIAL); return DOLLAR_CURLY; }
 <IND_STRING>\'\' { BEGIN(INITIAL); return IND_STRING_CLOSE; }
 <IND_STRING>\'   {
-                   //yylval->t = makeIndStr(toATerm("'"));
+                   yylval->e = new ExprIndStr("'");
                    return IND_STR;
                  }
 <IND_STRING>.    return yytext[0]; /* just in case: shouldn't be reached */
diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc
index b044aaa943d4..6ef996bdca50 100644
--- a/src/libexpr/nixexpr.cc
+++ b/src/libexpr/nixexpr.cc
@@ -15,6 +15,11 @@ std::ostream & operator << (std::ostream & str, Expr & e)
 }
 
 
+void Expr::show(std::ostream & str)
+{
+    abort();
+}
+
 void ExprInt::show(std::ostream & str)
 {
     str << n;
@@ -152,20 +157,6 @@ ATerm bottomupRewrite(TermFun & f, ATerm e)
 }
 
 
-Expr makeAttrs(const ATermMap & attrs)
-{
-    ATermList bnds = ATempty;
-    for (ATermMap::const_iterator i = attrs.begin(); i != attrs.end(); ++i) {
-        Expr e;
-        ATerm pos;
-        if (!matchAttrRHS(i->value, e, pos))
-            abort(); /* can't happen */
-        bnds = ATinsert(bnds, makeBind(i->key, e, pos));
-    }
-    return makeAttrs(bnds);
-}
-
-
 static void varsBoundByPattern(ATermMap & map, Pattern pat)
 {
     ATerm name;
diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh
index d6e088c41661..725f9fe88e52 100644
--- a/src/libexpr/nixexpr.hh
+++ b/src/libexpr/nixexpr.hh
@@ -35,11 +35,8 @@ struct EvalState;
 
 struct Expr
 {
-    virtual void show(std::ostream & str) = 0;
-    virtual void eval(EvalState & state, Env & env, Value & v)
-    {
-        throw Error("not implemented");
-    }
+    virtual void show(std::ostream & str);
+    virtual void eval(EvalState & state, Env & env, Value & v);
 };
 
 std::ostream & operator << (std::ostream & str, Expr & e);
@@ -62,6 +59,13 @@ struct ExprString : Expr
     COMMON_METHODS
 };
 
+/* Temporary class used during parsing of indented strings. */
+struct ExprIndStr : Expr
+{
+    string s;
+    ExprIndStr(const string & s) : s(s) { };
+};
+
 struct ExprPath : Expr
 {
     string s;
@@ -206,10 +210,6 @@ struct TermFun
 ATerm bottomupRewrite(TermFun & f, ATerm e);
 
 
-/* Create an attribute set expression from an Attrs value. */
-Expr makeAttrs(const ATermMap & attrs);
-
-
 /* Check whether all variables are defined in the given expression.
    Throw an exception if this isn't the case. */
 void checkVarDefs(const ATermMap & def, Expr e);
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index 83f454845d01..22ce7e3f3328 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -174,11 +174,12 @@ static void checkPatternVars(ATerm pos, Pattern pat)
     ATermMap map;
     checkPatternVars(pos, map, pat);
 }
+#endif
 
 
-static Expr stripIndentation(ATermList es)
+static Expr * stripIndentation(vector<Expr *> & es)
 {
-    if (es == ATempty) return makeStr("");
+    if (es.empty()) return new ExprString("");
     
     /* Figure out the minimum indentation.  Note that by design
        whitespace-only final lines are not taken into account.  (So
@@ -186,9 +187,9 @@ static Expr stripIndentation(ATermList es)
     bool atStartOfLine = true; /* = seen only whitespace in the current line */
     unsigned int minIndent = 1000000;
     unsigned int curIndent = 0;
-    ATerm e;
-    for (ATermIterator i(es); i; ++i) {
-        if (!matchIndStr(*i, e)) {
+    foreach (vector<Expr *>::iterator, i, es) {
+        ExprIndStr * e = dynamic_cast<ExprIndStr *>(*i);
+        if (!e) {
             /* Anti-quotations end the current start-of-line whitespace. */
             if (atStartOfLine) {
                 atStartOfLine = false;
@@ -196,12 +197,11 @@ static Expr stripIndentation(ATermList es)
             }
             continue;
         }
-        string s = aterm2String(e);
-        for (unsigned int j = 0; j < s.size(); ++j) {
+        for (unsigned int j = 0; j < e->s.size(); ++j) {
             if (atStartOfLine) {
-                if (s[j] == ' ')
+                if (e->s[j] == ' ')
                     curIndent++;
-                else if (s[j] == '\n') {
+                else if (e->s[j] == '\n') {
                     /* Empty line, doesn't influence minimum
                        indentation. */
                     curIndent = 0;
@@ -209,7 +209,7 @@ static Expr stripIndentation(ATermList es)
                     atStartOfLine = false;
                     if (curIndent < minIndent) minIndent = curIndent;
                 }
-            } else if (s[j] == '\n') {
+            } else if (e->s[j] == '\n') {
                 atStartOfLine = true;
                 curIndent = 0;
             }
@@ -217,37 +217,37 @@ static Expr stripIndentation(ATermList es)
     }
 
     /* Strip spaces from each line. */
-    ATermList es2 = ATempty;
+    vector<Expr *> * es2 = new vector<Expr *>;
     atStartOfLine = true;
     unsigned int curDropped = 0;
-    unsigned int n = ATgetLength(es);
-    for (ATermIterator i(es); i; ++i, --n) {
-        if (!matchIndStr(*i, e)) {
+    unsigned int n = es.size();
+    for (vector<Expr *>::iterator i = es.begin(); i != es.end(); ++i, --n) {
+        ExprIndStr * e = dynamic_cast<ExprIndStr *>(*i);
+        if (!e) {
             atStartOfLine = false;
             curDropped = 0;
-            es2 = ATinsert(es2, *i);
+            es2->push_back(*i);
             continue;
         }
         
-        string s = aterm2String(e);
         string s2;
-        for (unsigned int j = 0; j < s.size(); ++j) {
+        for (unsigned int j = 0; j < e->s.size(); ++j) {
             if (atStartOfLine) {
-                if (s[j] == ' ') {
+                if (e->s[j] == ' ') {
                     if (curDropped++ >= minIndent)
-                        s2 += s[j];
+                        s2 += e->s[j];
                 }
-                else if (s[j] == '\n') {
+                else if (e->s[j] == '\n') {
                     curDropped = 0;
-                    s2 += s[j];
+                    s2 += e->s[j];
                 } else {
                     atStartOfLine = false;
                     curDropped = 0;
-                    s2 += s[j];
+                    s2 += e->s[j];
                 }
             } else {
-                s2 += s[j];
-                if (s[j] == '\n') atStartOfLine = true;
+                s2 += e->s[j];
+                if (e->s[j] == '\n') atStartOfLine = true;
             }
         }
 
@@ -258,13 +258,12 @@ static Expr stripIndentation(ATermList es)
             if (p != string::npos && s2.find_first_not_of(' ', p + 1) == string::npos)
                 s2 = string(s2, 0, p + 1);
         }
-            
-        es2 = ATinsert(es2, makeStr(s2));
+
+        es2->push_back(new ExprString(s2));
     }
 
-    return makeConcatStrings(ATreverse(es2));
+    return new ExprConcatStrings(es2);
 }
-#endif
 
 
 void backToString(yyscan_t scanner);
@@ -316,11 +315,10 @@ void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * err
 %type <e> expr_app expr_select expr_simple
 %type <list> expr_list
 %type <attrs> binds
-%type <ts> attrpath ind_string_parts
 %type <formals> formals
 %type <formal> formal
-%type <ids> ids
-%type <string_parts> string_parts
+%type <ids> ids attrpath
+%type <string_parts> string_parts ind_string_parts
 %token <id> ID ATTRPATH
 %token <e> STR IND_STR
 %token <n> INT
@@ -411,11 +409,9 @@ expr_simple
       else if ($2->size() == 1) $$ = $2->front();
       else $$ = new ExprConcatStrings($2);
   }
-  /*
   | IND_STRING_OPEN ind_string_parts IND_STRING_CLOSE {
-      $$ = stripIndentation(ATreverse($2));
+      $$ = stripIndentation(*$2);
   }
-  */
   | PATH { $$ = new ExprPath(absPath($1, data->basePath)); }
   | URI { $$ = new ExprString($1); }
   | '(' expr ')' { $$ = $2; }
@@ -437,9 +433,9 @@ string_parts
   ;
 
 ind_string_parts
-  : ind_string_parts IND_STR { $$ = ATinsert($1, $2); }
-  | ind_string_parts DOLLAR_CURLY expr '}' { backToIndString(scanner); $$ = ATinsert($1, $3); }
-  | { $$ = ATempty; }
+  : ind_string_parts IND_STR { $$ = $1; $1->push_back($2); }
+  | ind_string_parts DOLLAR_CURLY expr '}' { backToIndString(scanner); $$ = $1; $1->push_back($3); }
+  | { $$ = new vector<Expr *>; }
   ;
 
 binds
diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc
index 466c7b499e22..ba34fc63bd94 100644
--- a/src/nix-instantiate/nix-instantiate.cc
+++ b/src/nix-instantiate/nix-instantiate.cc
@@ -42,7 +42,7 @@ void processExpr(EvalState & state, const Strings & attrPaths,
     bool evalOnly, bool xmlOutput, Expr * e)
 {
     if (parseOnly)
-        std::cout << format("%1%\n");
+        std::cout << format("%1%\n") % *e;
     else
         foreach (Strings::const_iterator, i, attrPaths) {
             Value v;