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.y122
1 files changed, 75 insertions, 47 deletions
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index 26168b2ed420..776e5cb39b81 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -31,10 +31,12 @@ namespace nix {
         Path basePath;
         Symbol path;
         string error;
+        bool atEnd;
         Symbol sLetBody;
         ParseData(EvalState & state)
             : state(state)
             , symbols(state.symbols)
+            , atEnd(false)
             , sLetBody(symbols.create("<let-body>"))
             { };
     };
@@ -136,8 +138,8 @@ static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols, vector<Ex
     bool atStartOfLine = true; /* = seen only whitespace in the current line */
     unsigned int minIndent = 1000000;
     unsigned int curIndent = 0;
-    foreach (vector<Expr *>::iterator, i, es) {
-        ExprIndStr * e = dynamic_cast<ExprIndStr *>(*i);
+    for (auto & i : es) {
+        ExprIndStr * e = dynamic_cast<ExprIndStr *>(i);
         if (!e) {
             /* Anti-quotations end the current start-of-line whitespace. */
             if (atStartOfLine) {
@@ -216,10 +218,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);
@@ -248,6 +246,7 @@ void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * err
   nix::Formals * formals;
   nix::Formal * formal;
   nix::NixInt n;
+  nix::NixFloat nf;
   const char * id; // !!! -> Symbol
   char * path;
   char * uri;
@@ -268,6 +267,7 @@ void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * err
 %token <id> ID ATTRPATH
 %token <e> STR IND_STR
 %token <n> INT
+%token <nf> FLOAT
 %token <path> PATH HPATH SPATH
 %token <uri> URI
 %token IF THEN ELSE ASSERT WITH LET IN REC INHERIT EQ NEQ AND OR IMPL OR_KW
@@ -370,6 +370,7 @@ expr_simple
           $$ = new ExprVar(CUR_POS, data->symbols.create($1));
   }
   | INT { $$ = new ExprInt($1); }
+  | FLOAT { $$ = new ExprFloat($1); }
   | '"' string_parts '"' { $$ = $2; }
   | IND_STRING_OPEN ind_string_parts IND_STRING_CLOSE {
       $$ = stripIndentation(CUR_POS, data->symbols, *$2);
@@ -404,25 +405,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 *>; }
   ;
 
@@ -430,20 +424,20 @@ binds
   : binds attrpath '=' expr ';' { $$ = $1; addAttr($$, *$2, $4, makeCurPos(@2, data)); }
   | binds INHERIT attrs ';'
     { $$ = $1;
-      foreach (AttrPath::iterator, i, *$3) {
-          if ($$->attrs.find(i->symbol) != $$->attrs.end())
-              dupAttr(i->symbol, makeCurPos(@3, data), $$->attrs[i->symbol].pos);
+      for (auto & i : *$3) {
+          if ($$->attrs.find(i.symbol) != $$->attrs.end())
+              dupAttr(i.symbol, makeCurPos(@3, data), $$->attrs[i.symbol].pos);
           Pos pos = makeCurPos(@3, data);
-          $$->attrs[i->symbol] = ExprAttrs::AttrDef(new ExprVar(CUR_POS, i->symbol), pos, true);
+          $$->attrs[i.symbol] = ExprAttrs::AttrDef(new ExprVar(CUR_POS, i.symbol), pos, true);
       }
     }
   | binds INHERIT '(' expr ')' attrs ';'
     { $$ = $1;
       /* !!! Should ensure sharing of the expression in $4. */
-      foreach (AttrPath::iterator, i, *$6) {
-          if ($$->attrs.find(i->symbol) != $$->attrs.end())
-              dupAttr(i->symbol, makeCurPos(@6, data), $$->attrs[i->symbol].pos);
-          $$->attrs[i->symbol] = ExprAttrs::AttrDef(new ExprSelect(CUR_POS, $4, i->symbol), makeCurPos(@6, data));
+      for (auto & i : *$6) {
+          if ($$->attrs.find(i.symbol) != $$->attrs.end())
+              dupAttr(i.symbol, makeCurPos(@6, data), $$->attrs[i.symbol].pos);
+          $$->attrs[i.symbol] = ExprAttrs::AttrDef(new ExprSelect(CUR_POS, $4, i.symbol), makeCurPos(@6, data));
       }
     }
   | { $$ = new ExprAttrs; }
@@ -526,9 +520,10 @@ formal
 #include <fcntl.h>
 #include <unistd.h>
 
-#include <eval.hh>
-#include <download.hh>
-#include <store-api.hh>
+#include "eval.hh"
+#include "download.hh"
+#include "store-api.hh"
+#include "primops/fetchgit.hh"
 
 
 namespace nix {
@@ -547,7 +542,12 @@ Expr * EvalState::parse(const char * text,
     int res = yyparse(scanner, &data);
     yylex_destroy(scanner);
 
-    if (res) throw ParseError(data.error);
+    if (res) {
+      if (data.atEnd)
+        throw IncompleteParseError(data.error);
+      else
+        throw ParseError(data.error);
+    }
 
     data.result->bindVars(staticEnv);
 
@@ -601,7 +601,7 @@ Expr * EvalState::parseExprFromString(const string & s, const Path & basePath)
 }
 
 
-void EvalState::addToSearchPath(const string & s, bool warn)
+void EvalState::addToSearchPath(const string & s)
 {
     size_t pos = s.find('=');
     string prefix;
@@ -613,16 +613,7 @@ void EvalState::addToSearchPath(const string & s, bool warn)
         path = string(s, pos + 1);
     }
 
-    if (isUri(path))
-        path = downloadFileCached(path, true);
-
-    path = absPath(path);
-    if (pathExists(path)) {
-        debug(format("adding path ‘%1%’ to the search path") % path);
-        /* Resolve symlinks in the path to support restricted mode. */
-        searchPath.push_back(std::pair<string, Path>(prefix, canonPath(path, true)));
-    } else if (warn)
-        printMsg(lvlError, format("warning: Nix search path entry ‘%1%’ does not exist, ignoring") % path);
+    searchPath.emplace_back(prefix, path);
 }
 
 
@@ -635,17 +626,19 @@ Path EvalState::findFile(const string & path)
 Path EvalState::findFile(SearchPath & searchPath, const string & path, const Pos & pos)
 {
     for (auto & i : searchPath) {
-        assert(!isUri(i.second));
-        Path res;
+        std::string suffix;
         if (i.first.empty())
-            res = i.second + "/" + path;
+            suffix = "/" + path;
         else {
-            if (path.compare(0, i.first.size(), i.first) != 0 ||
-                (path.size() > i.first.size() && path[i.first.size()] != '/'))
+            auto s = i.first.size();
+            if (path.compare(0, s, i.first) != 0 ||
+                (path.size() > s && path[s] != '/'))
                 continue;
-            res = i.second +
-                (path.size() == i.first.size() ? "" : "/" + string(path, i.first.size()));
+            suffix = path.size() == s ? "" : "/" + string(path, s);
         }
+        auto r = resolveSearchPathElem(i);
+        if (!r.first) continue;
+        Path res = r.second + suffix;
         if (pathExists(res)) return canonPath(res);
     }
     format f = format(
@@ -656,4 +649,39 @@ Path EvalState::findFile(SearchPath & searchPath, const string & path, const Pos
 }
 
 
+std::pair<bool, std::string> EvalState::resolveSearchPathElem(const SearchPathElem & elem)
+{
+    auto i = searchPathResolved.find(elem.second);
+    if (i != searchPathResolved.end()) return i->second;
+
+    std::pair<bool, std::string> res;
+
+    if (isUri(elem.second)) {
+        try {
+            if (hasPrefix(elem.second, "git://") || hasSuffix(elem.second, ".git"))
+                // FIXME: support specifying revision/branch
+                res = { true, exportGit(store, elem.second, "master") };
+            else
+                res = { true, makeDownloader()->downloadCached(store, elem.second, true) };
+        } catch (DownloadError & e) {
+            printMsg(lvlError, format("warning: Nix search path entry ‘%1%’ cannot be downloaded, ignoring") % elem.second);
+            res = { false, "" };
+        }
+    } else {
+        auto path = absPath(elem.second);
+        if (pathExists(path))
+            res = { true, path };
+        else {
+            printMsg(lvlError, format("warning: Nix search path entry ‘%1%’ does not exist, ignoring") % elem.second);
+            res = { false, "" };
+        }
+    }
+
+    debug(format("resolved search path element ‘%s’ to ‘%s’") % elem.second % res.second);
+
+    searchPathResolved[elem.second] = res;
+    return res;
+}
+
+
 }