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.y651
1 files changed, 0 insertions, 651 deletions
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
deleted file mode 100644
index ab0b862246..0000000000
--- a/src/libexpr/parser.y
+++ /dev/null
@@ -1,651 +0,0 @@
-%glr-parser
-%pure-parser
-%locations
-%error-verbose
-%defines
-/* %no-lines */
-%parse-param { void * scanner }
-%parse-param { nix::ParseData * data }
-%lex-param { void * scanner }
-%lex-param { nix::ParseData * data }
-%expect 1
-%expect-rr 1
-
-%code requires {
-
-#ifndef BISON_HEADER
-#define BISON_HEADER
-
-#include "util.hh"
-
-#include "nixexpr.hh"
-#include "eval.hh"
-
-namespace nix {
-
-    struct ParseData
-    {
-        EvalState & state;
-        SymbolTable & symbols;
-        Expr * result;
-        Path basePath;
-        Symbol path;
-        string error;
-        Symbol sLetBody;
-        ParseData(EvalState & state)
-            : state(state)
-            , symbols(state.symbols)
-            , sLetBody(symbols.create("<let-body>"))
-            { };
-    };
-
-}
-
-#define YY_DECL int yylex \
-    (YYSTYPE * yylval_param, YYLTYPE * yylloc_param, yyscan_t yyscanner, nix::ParseData * data)
-
-#endif
-
-}
-
-%{
-
-#include "parser-tab.hh"
-#include "lexer-tab.hh"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-YY_DECL;
-
-using namespace nix;
-
-
-namespace nix {
-
-
-static void dupAttr(const AttrPath & attrPath, const Pos & pos, const Pos & prevPos)
-{
-    throw ParseError(format("attribute `%1%' at %2% already defined at %3%")
-        % showAttrPath(attrPath) % pos % prevPos);
-}
-
-
-static void dupAttr(Symbol attr, const Pos & pos, const Pos & prevPos)
-{
-    throw ParseError(format("attribute `%1%' at %2% already defined at %3%")
-        % attr % pos % prevPos);
-}
-
-
-static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
-    Expr * e, const Pos & pos)
-{
-    AttrPath::iterator i;
-    // All attrpaths have at least one attr
-    assert(!attrPath.empty());
-    for (i = attrPath.begin(); i + 1 < attrPath.end(); i++) {
-        if (i->symbol.set()) {
-            ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol);
-            if (j != attrs->attrs.end()) {
-                if (!j->second.inherited) {
-                    ExprAttrs * attrs2 = dynamic_cast<ExprAttrs *>(j->second.e);
-                    if (!attrs2) dupAttr(attrPath, pos, j->second.pos);
-                    attrs = attrs2;
-                } else
-                    dupAttr(attrPath, pos, j->second.pos);
-            } else {
-                ExprAttrs * nested = new ExprAttrs;
-                attrs->attrs[i->symbol] = ExprAttrs::AttrDef(nested, pos);
-                attrs = nested;
-            }
-        } else {
-            ExprAttrs *nested = new ExprAttrs;
-            attrs->dynamicAttrs.push_back(ExprAttrs::DynamicAttrDef(i->expr, nested, pos));
-            attrs = nested;
-        }
-    }
-    if (i->symbol.set()) {
-        ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol);
-        if (j != attrs->attrs.end()) {
-            dupAttr(attrPath, pos, j->second.pos);
-        } else {
-            attrs->attrs[i->symbol] = ExprAttrs::AttrDef(e, pos);
-            e->setName(i->symbol);
-        }
-    } else {
-        attrs->dynamicAttrs.push_back(ExprAttrs::DynamicAttrDef(i->expr, e, pos));
-    }
-}
-
-
-static void addFormal(const Pos & pos, Formals * formals, const Formal & formal)
-{
-    if (formals->argNames.find(formal.name) != formals->argNames.end())
-        throw ParseError(format("duplicate formal function argument `%1%' at %2%")
-            % formal.name % pos);
-    formals->formals.push_front(formal);
-    formals->argNames.insert(formal.name);
-}
-
-
-static Expr * stripIndentation(SymbolTable & symbols, vector<Expr *> & es)
-{
-    if (es.empty()) return new ExprString(symbols.create(""));
-
-    /* Figure out the minimum indentation.  Note that by design
-       whitespace-only final lines are not taken into account.  (So
-       the " " in "\n ''" is ignored, but the " " in "\n foo''" is.) */
-    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);
-        if (!e) {
-            /* Anti-quotations end the current start-of-line whitespace. */
-            if (atStartOfLine) {
-                atStartOfLine = false;
-                if (curIndent < minIndent) minIndent = curIndent;
-            }
-            continue;
-        }
-        for (unsigned int j = 0; j < e->s.size(); ++j) {
-            if (atStartOfLine) {
-                if (e->s[j] == ' ')
-                    curIndent++;
-                else if (e->s[j] == '\n') {
-                    /* Empty line, doesn't influence minimum
-                       indentation. */
-                    curIndent = 0;
-                } else {
-                    atStartOfLine = false;
-                    if (curIndent < minIndent) minIndent = curIndent;
-                }
-            } else if (e->s[j] == '\n') {
-                atStartOfLine = true;
-                curIndent = 0;
-            }
-        }
-    }
-
-    /* Strip spaces from each line. */
-    vector<Expr *> * es2 = new vector<Expr *>;
-    atStartOfLine = true;
-    unsigned int curDropped = 0;
-    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->push_back(*i);
-            continue;
-        }
-
-        string s2;
-        for (unsigned int j = 0; j < e->s.size(); ++j) {
-            if (atStartOfLine) {
-                if (e->s[j] == ' ') {
-                    if (curDropped++ >= minIndent)
-                        s2 += e->s[j];
-                }
-                else if (e->s[j] == '\n') {
-                    curDropped = 0;
-                    s2 += e->s[j];
-                } else {
-                    atStartOfLine = false;
-                    curDropped = 0;
-                    s2 += e->s[j];
-                }
-            } else {
-                s2 += e->s[j];
-                if (e->s[j] == '\n') atStartOfLine = true;
-            }
-        }
-
-        /* Remove the last line if it is empty and consists only of
-           spaces. */
-        if (n == 1) {
-            string::size_type p = s2.find_last_of('\n');
-            if (p != string::npos && s2.find_first_not_of(' ', p + 1) == string::npos)
-                s2 = string(s2, 0, p + 1);
-        }
-
-        es2->push_back(new ExprString(symbols.create(s2)));
-    }
-
-    /* If this is a single string, then don't do a concatenation. */
-    return es2->size() == 1 && dynamic_cast<ExprString *>((*es2)[0]) ? (*es2)[0] : new ExprConcatStrings(true, es2);
-}
-
-
-void backToString(yyscan_t scanner);
-void backToIndString(yyscan_t scanner);
-
-
-static Pos makeCurPos(const YYLTYPE & loc, ParseData * data)
-{
-    return Pos(data->path, loc.first_line, loc.first_column);
-}
-
-#define CUR_POS makeCurPos(*yylocp, data)
-
-
-}
-
-
-void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * error)
-{
-    data->error = (format("%1%, at %2%")
-        % error % makeCurPos(*loc, data)).str();
-}
-
-
-%}
-
-%union {
-  // !!! We're probably leaking stuff here.
-  nix::Expr * e;
-  nix::ExprList * list;
-  nix::ExprAttrs * attrs;
-  nix::Formals * formals;
-  nix::Formal * formal;
-  nix::NixInt n;
-  const char * id; // !!! -> Symbol
-  char * path;
-  char * uri;
-  std::vector<nix::AttrName> * attrNames;
-  std::vector<nix::Expr *> * string_parts;
-}
-
-%type <e> start expr expr_function expr_if expr_op
-%type <e> expr_app expr_select expr_simple
-%type <list> expr_list
-%type <attrs> binds
-%type <formals> formals
-%type <formal> formal
-%type <attrNames> attrs attrpath
-%type <string_parts> string_parts_interpolated ind_string_parts
-%type <e> string_parts string_attr
-%type <id> attr
-%token <id> ID ATTRPATH
-%token <e> STR IND_STR
-%token <n> INT
-%token <path> PATH SPATH
-%token <uri> URI
-%token IF THEN ELSE ASSERT WITH LET IN REC INHERIT EQ NEQ AND OR IMPL OR_KW
-%token DOLLAR_CURLY /* == ${ */
-%token IND_STRING_OPEN IND_STRING_CLOSE
-%token ELLIPSIS
-
-%nonassoc IMPL
-%left OR
-%left AND
-%nonassoc EQ NEQ
-%left '<' '>' LEQ GEQ
-%right UPDATE
-%left NOT
-%left '+' '-'
-%left '*' '/'
-%right CONCAT
-%nonassoc '?'
-%nonassoc '~'
-%nonassoc NEGATE
-
-%%
-
-start: expr { data->result = $1; };
-
-expr: expr_function;
-
-expr_function
-  : ID ':' expr_function
-    { $$ = new ExprLambda(CUR_POS, data->symbols.create($1), false, 0, $3); }
-  | '{' formals '}' ':' expr_function
-    { $$ = new ExprLambda(CUR_POS, data->symbols.create(""), true, $2, $5); }
-  | '{' formals '}' '@' ID ':' expr_function
-    { $$ = new ExprLambda(CUR_POS, data->symbols.create($5), true, $2, $7); }
-  | ID '@' '{' formals '}' ':' expr_function
-    { $$ = new ExprLambda(CUR_POS, data->symbols.create($1), true, $4, $7); }
-  | ASSERT expr ';' expr_function
-    { $$ = new ExprAssert(CUR_POS, $2, $4); }
-  | WITH expr ';' expr_function
-    { $$ = new ExprWith(CUR_POS, $2, $4); }
-  | LET binds IN expr_function
-    { if (!$2->dynamicAttrs.empty())
-        throw ParseError(format("dynamic attributes not allowed in let at %1%")
-            % CUR_POS);
-      $$ = new ExprLet($2, $4);
-    }
-  | expr_if
-  ;
-
-expr_if
-  : IF expr THEN expr ELSE expr { $$ = new ExprIf($2, $4, $6); }
-  | expr_op
-  ;
-
-expr_op
-  : '!' expr_op %prec NOT { $$ = new ExprOpNot($2); }
-| '-' expr_op %prec NEGATE { $$ = new ExprApp(new ExprApp(new ExprBuiltin(data->symbols.create("sub")), new ExprInt(0)), $2); }
-  | expr_op EQ expr_op { $$ = new ExprOpEq($1, $3); }
-  | expr_op NEQ expr_op { $$ = new ExprOpNEq($1, $3); }
-  | expr_op '<' expr_op { $$ = new ExprApp(new ExprApp(new ExprBuiltin(data->symbols.create("lessThan")), $1), $3); }
-  | expr_op LEQ expr_op { $$ = new ExprOpNot(new ExprApp(new ExprApp(new ExprBuiltin(data->symbols.create("lessThan")), $3), $1)); }
-  | expr_op '>' expr_op { $$ = new ExprApp(new ExprApp(new ExprBuiltin(data->symbols.create("lessThan")), $3), $1); }
-  | expr_op GEQ expr_op { $$ = new ExprOpNot(new ExprApp(new ExprApp(new ExprBuiltin(data->symbols.create("lessThan")), $1), $3)); }
-  | expr_op AND expr_op { $$ = new ExprOpAnd($1, $3); }
-  | expr_op OR expr_op { $$ = new ExprOpOr($1, $3); }
-  | expr_op IMPL expr_op { $$ = new ExprOpImpl($1, $3); }
-  | expr_op UPDATE expr_op { $$ = new ExprOpUpdate($1, $3); }
-  | expr_op '?' attrpath { $$ = new ExprOpHasAttr($1, *$3); }
-  | expr_op '+' expr_op
-    { vector<Expr *> * l = new vector<Expr *>;
-      l->push_back($1);
-      l->push_back($3);
-      $$ = new ExprConcatStrings(false, l);
-    }
-  | expr_op '-' expr_op { $$ = new ExprApp(new ExprApp(new ExprBuiltin(data->symbols.create("sub")), $1), $3); }
-  | expr_op '*' expr_op { $$ = new ExprApp(new ExprApp(new ExprBuiltin(data->symbols.create("mul")), $1), $3); }
-  | expr_op '/' expr_op { $$ = new ExprApp(new ExprApp(new ExprBuiltin(data->symbols.create("div")), $1), $3); }
-  | expr_op CONCAT expr_op { $$ = new ExprOpConcatLists($1, $3); }
-  | expr_app
-  ;
-
-expr_app
-  : expr_app expr_select
-    { $$ = new ExprApp($1, $2); }
-  | expr_select { $$ = $1; }
-  ;
-
-expr_select
-  : expr_simple '.' attrpath
-    { $$ = new ExprSelect($1, *$3, 0); }
-  | expr_simple '.' attrpath OR_KW expr_select
-    { $$ = new ExprSelect($1, *$3, $5); }
-  | /* Backwards compatibility: because Nixpkgs has a rarely used
-       function named ‘or’, allow stuff like ‘map or [...]’. */
-    expr_simple OR_KW
-    { $$ = new ExprApp($1, new ExprVar(CUR_POS, data->symbols.create("or"))); }
-  | expr_simple { $$ = $1; }
-  ;
-
-expr_simple
-  : ID {
-      if (strcmp($1, "__curPos") == 0)
-          $$ = new ExprPos(CUR_POS);
-      else
-          $$ = new ExprVar(CUR_POS, data->symbols.create($1));
-  }
-  | INT { $$ = new ExprInt($1); }
-  | '"' string_parts '"' { $$ = $2; }
-  | IND_STRING_OPEN ind_string_parts IND_STRING_CLOSE {
-      $$ = stripIndentation(data->symbols, *$2);
-  }
-  | PATH { $$ = new ExprPath(absPath($1, data->basePath)); }
-  | SPATH {
-      string path($1 + 1, strlen($1) - 2);
-      Path path2 = data->state.findFile(path);
-      /* The file wasn't found in the search path.  However, we can't
-         throw an error here, because the expression might never be
-         evaluated.  So return an expression that lazily calls
-         ‘throw’. */
-      $$ = path2 == ""
-          ? (Expr * ) new ExprApp(
-              new ExprBuiltin(data->symbols.create("throw")),
-              new ExprString(data->symbols.create(
-                      (format("file `%1%' was not found in the Nix search path (add it using $NIX_PATH or -I)") % path).str())))
-          : (Expr * ) new ExprPath(path2);
-  }
-  | URI { $$ = new ExprString(data->symbols.create($1)); }
-  | '(' expr ')' { $$ = $2; }
-  /* Let expressions `let {..., body = ...}' are just desugared
-     into `(rec {..., body = ...}).body'. */
-  | LET '{' binds '}'
-    { $3->recursive = true; $$ = new ExprSelect($3, data->symbols.create("body")); }
-  | REC '{' binds '}'
-    { $3->recursive = true; $$ = $3; }
-  | '{' binds '}'
-    { $$ = $2; }
-  | '[' expr_list ']' { $$ = $2; }
-  ;
-
-string_parts
-  : STR
-  | string_parts_interpolated { $$ = new ExprConcatStrings(true, $1); }
-  | { $$ = new ExprString(data->symbols.create("")); }
-  ;
-
-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);
-      $$ = 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); }
-  | { $$ = new vector<Expr *>; }
-  ;
-
-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);
-          Pos pos = makeCurPos(@3, data);
-          $$->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($4, i->symbol), makeCurPos(@6, data));
-      }
-    }
-  | { $$ = new ExprAttrs; }
-  ;
-
-attrs
-  : attrs attr { $$ = $1; $1->push_back(AttrName(data->symbols.create($2))); }
-  | attrs string_attr
-    { $$ = $1;
-      ExprString *str = dynamic_cast<ExprString *>($2);
-      if (str) {
-          $$->push_back(AttrName(str->s));
-          delete str;
-      } else
-        throw ParseError(format("dynamic attributes not allowed in inherit at %1%")
-            % makeCurPos(@2, data));
-    }
-  | { $$ = new AttrPath; }
-  ;
-
-attrpath
-  : attrpath '.' attr { $$ = $1; $1->push_back(AttrName(data->symbols.create($3))); }
-  | attrpath '.' string_attr
-    { $$ = $1;
-      ExprString *str = dynamic_cast<ExprString *>($3);
-      if (str) {
-          $$->push_back(AttrName(str->s));
-          delete str;
-      } else
-          $$->push_back(AttrName(static_cast<ExprConcatStrings *>($3)));
-    }
-  | attr { $$ = new vector<AttrName>; $$->push_back(AttrName(data->symbols.create($1))); }
-  | string_attr
-    { $$ = new vector<AttrName>;
-      ExprString *str = dynamic_cast<ExprString *>($1);
-      if (str) {
-          $$->push_back(AttrName(str->s));
-          delete str;
-      } else
-          $$->push_back(AttrName(static_cast<ExprConcatStrings *>($1)));
-    }
-  ;
-
-attr
-  : ID { $$ = $1; }
-  | OR_KW { $$ = "or"; }
-  ;
-
-string_attr
-  : '"' string_parts '"' { $$ = $2; }
-  | DOLLAR_CURLY expr '}' { $$ = new ExprConcatStrings(true, new vector<Expr*>(1, $2)); }
-  ;
-
-expr_list
-  : expr_list expr_select { $$ = $1; $1->elems.push_back($2); /* !!! dangerous */ }
-  | { $$ = new ExprList; }
-  ;
-
-formals
-  : formal ',' formals
-    { $$ = $3; addFormal(CUR_POS, $$, *$1); }
-  | formal
-    { $$ = new Formals; addFormal(CUR_POS, $$, *$1); $$->ellipsis = false; }
-  |
-    { $$ = new Formals; $$->ellipsis = false; }
-  | ELLIPSIS
-    { $$ = new Formals; $$->ellipsis = true; }
-  ;
-
-formal
-  : ID { $$ = new Formal(data->symbols.create($1), 0); }
-  | ID '?' expr { $$ = new Formal(data->symbols.create($1), $3); }
-  ;
-
-%%
-
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <eval.hh>
-
-
-namespace nix {
-
-
-Expr * EvalState::parse(const char * text,
-    const Path & path, const Path & basePath, StaticEnv & staticEnv)
-{
-    yyscan_t scanner;
-    ParseData data(*this);
-    data.basePath = basePath;
-    data.path = data.symbols.create(path);
-
-    yylex_init(&scanner);
-    yy_scan_string(text, scanner);
-    int res = yyparse(scanner, &data);
-    yylex_destroy(scanner);
-
-    if (res) throw ParseError(data.error);
-
-    data.result->bindVars(staticEnv);
-
-    return data.result;
-}
-
-
-Path resolveExprPath(Path path)
-{
-    assert(path[0] == '/');
-
-    /* If `path' is a symlink, follow it.  This is so that relative
-       path references work. */
-    struct stat st;
-    while (true) {
-        if (lstat(path.c_str(), &st))
-            throw SysError(format("getting status of `%1%'") % path);
-        if (!S_ISLNK(st.st_mode)) break;
-        path = absPath(readLink(path), dirOf(path));
-    }
-
-    /* If `path' refers to a directory, append `/default.nix'. */
-    if (S_ISDIR(st.st_mode))
-        path = canonPath(path + "/default.nix");
-
-    return path;
-}
-
-
-Expr * EvalState::parseExprFromFile(const Path & path)
-{
-    return parse(readFile(path).c_str(), path, dirOf(path), staticBaseEnv);
-}
-
-
-Expr * EvalState::parseExprFromString(const string & s, const Path & basePath, StaticEnv & staticEnv)
-{
-    return parse(s.c_str(), "(string)", basePath, staticEnv);
-}
-
-
-Expr * EvalState::parseExprFromString(const string & s, const Path & basePath)
-{
-    return parseExprFromString(s, basePath, staticBaseEnv);
-}
-
-
- void EvalState::addToSearchPath(const string & s, bool warn)
-{
-    size_t pos = s.find('=');
-    string prefix;
-    Path path;
-    if (pos == string::npos) {
-        path = s;
-    } else {
-        prefix = string(s, 0, pos);
-        path = string(s, pos + 1);
-    }
-
-    path = absPath(path);
-    if (pathExists(path)) {
-        debug(format("adding path `%1%' to the search path") % path);
-        searchPath.insert(searchPathInsertionPoint, std::pair<string, Path>(prefix, path));
-    } else if (warn)
-        printMsg(lvlError, format("warning: Nix search path entry `%1%' does not exist, ignoring") % path);
-}
-
-
-Path EvalState::findFile(const string & path)
-{
-    foreach (SearchPath::iterator, i, searchPath) {
-        Path res;
-        if (i->first.empty())
-            res = i->second + "/" + path;
-        else {
-            if (path.compare(0, i->first.size(), i->first) != 0 ||
-                (path.size() > i->first.size() && path[i->first.size()] != '/'))
-                continue;
-            res = i->second +
-                (path.size() == i->first.size() ? "" : "/" + string(path, i->first.size()));
-        }
-        if (pathExists(res)) return canonPath(res);
-    }
-    return "";
-}
-
-
-}