diff options
author | Eelco Dolstra <e.dolstra@tudelft.nl> | 2011-07-06T10·58+0000 |
---|---|---|
committer | Eelco Dolstra <e.dolstra@tudelft.nl> | 2011-07-06T10·58+0000 |
commit | 56370378023fc84eb0153b991f4138f6acd011e3 (patch) | |
tree | 19034285effef61c373eef092e91f717c4cea020 /src/libexpr/parser.y | |
parent | 34f4b91820796381d04c6e00ea5e805cf53d25da (diff) |
* In the ‘?’ operator, allow attribute paths. For instance, you can
write ‘attrs ? a.b’ to test whether ‘attrs’ has an attribute ‘a’ containing an attribute ‘b’. This is more convenient than ‘attrs ? a && attrs.a ? b’. Slight change in the semantics: it's no longer an error if the left-hand side of ‘?’ is not an attribute set. In that case it just returns false. So, ‘null ? foo’ no longer throws an error.
Diffstat (limited to 'src/libexpr/parser.y')
-rw-r--r-- | src/libexpr/parser.y | 26 |
1 files changed, 8 insertions, 18 deletions
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index c6d29b6ca8bd..073fac1bee89 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -61,18 +61,7 @@ using namespace nix; namespace nix { -static string showAttrPath(const vector<Symbol> & attrPath) -{ - string s; - foreach (vector<Symbol>::const_iterator, i, attrPath) { - if (!s.empty()) s += '.'; - s += *i; - } - return s; -} - - -static void dupAttr(const vector<Symbol> & attrPath, const Pos & pos, const Pos & prevPos) +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); @@ -81,17 +70,17 @@ static void dupAttr(const vector<Symbol> & attrPath, const Pos & pos, const Pos static void dupAttr(Symbol attr, const Pos & pos, const Pos & prevPos) { - vector<Symbol> attrPath; attrPath.push_back(attr); + AttrPath attrPath; attrPath.push_back(attr); throw ParseError(format("attribute `%1%' at %2% already defined at %3%") % showAttrPath(attrPath) % pos % prevPos); } -static void addAttr(ExprAttrs * attrs, const vector<Symbol> & attrPath, +static void addAttr(ExprAttrs * attrs, AttrPath & attrPath, Expr * e, const Pos & pos) { unsigned int n = 0; - foreach (vector<Symbol>::const_iterator, i, attrPath) { + foreach (AttrPath::const_iterator, i, attrPath) { n++; ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(*i); if (j != attrs->attrs.end()) { @@ -238,6 +227,7 @@ void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * err %} %union { + // !!! We're probably leaking stuff here. nix::Expr * e; nix::ExprList * list; nix::ExprAttrs * attrs; @@ -317,7 +307,7 @@ expr_op | 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 '?' ID { $$ = new ExprOpHasAttr($1, data->symbols.create($3)); } + | expr_op '?' attrpath { $$ = new ExprOpHasAttr($1, *$3); } | expr_op '+' expr_op { vector<Expr *> * l = new vector<Expr *>; l->push_back($1); @@ -382,7 +372,7 @@ binds : binds attrpath '=' expr ';' { $$ = $1; addAttr($$, *$2, $4, makeCurPos(@2, data)); } | binds INHERIT ids ';' { $$ = $1; - foreach (vector<Symbol>::iterator, i, *$3) { + foreach (AttrPath::iterator, i, *$3) { if ($$->attrs.find(*i) != $$->attrs.end()) dupAttr(*i, makeCurPos(@3, data), $$->attrs[*i].pos); Pos pos = makeCurPos(@3, data); @@ -392,7 +382,7 @@ binds | binds INHERIT '(' expr ')' ids ';' { $$ = $1; /* !!! Should ensure sharing of the expression in $4. */ - foreach (vector<Symbol>::iterator, i, *$6) { + foreach (AttrPath::iterator, i, *$6) { if ($$->attrs.find(*i) != $$->attrs.end()) dupAttr(*i, makeCurPos(@6, data), $$->attrs[*i].pos); $$->attrs[*i] = ExprAttrs::AttrDef(new ExprSelect($4, *i), makeCurPos(@6, data)); |