From ebade9ff8b8557bdae7cdaf9f70c12ceeb3dc02c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 22 Apr 2010 11:02:24 +0000 Subject: * Check for duplicate attribute names / function arguments. `make check' now succeeds :-) * An attribute set such as `{ foo = { enable = true; }; foo.port = 23; }' now parses. It was previously rejected, but I'm too lazy to implement the check. (The only reason to reject it is that the reverse, `{ foo.port = 23; foo = { enable = true; }; }', is rejected, which is kind of ugly.) --- src/libexpr/parser.y | 83 +++++++++++++++++++++++++--------------------------- 1 file changed, 40 insertions(+), 43 deletions(-) (limited to 'src/libexpr/parser.y') diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 06fcc72fc542..66da769402dc 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -59,6 +59,21 @@ static string showAttrPath(const vector & attrPath) } return s; } + + +static void dupAttr(const vector & attrPath, const Pos & pos) +{ + throw ParseError(format("attribute `%1%' at %2% already defined at ") + % showAttrPath(attrPath) % pos); +} + + +static void dupAttr(Symbol attr, const Pos & pos) +{ + vector attrPath; attrPath.push_back(attr); + throw ParseError(format("attribute `%1%' at %2% already defined at ") + % showAttrPath(attrPath) % pos); +} static void addAttr(ExprAttrs * attrs, const vector & attrPath, @@ -69,11 +84,12 @@ static void addAttr(ExprAttrs * attrs, const vector & attrPath, n++; if (attrs->attrs[*i]) { ExprAttrs * attrs2 = dynamic_cast(attrs->attrs[*i]); - if (!attrs2) - throw ParseError(format("attribute `%1%' at %2% already defined at ") - % showAttrPath(attrPath) % pos); + if (!attrs2 || n == attrPath.size()) dupAttr(attrPath, pos); attrs = attrs2; } else { + if (attrs->attrNames.find(*i) != attrs->attrNames.end()) + dupAttr(attrPath, pos); + attrs->attrNames.insert(*i); if (n == attrPath.size()) attrs->attrs[*i] = e; else { @@ -86,43 +102,16 @@ static void addAttr(ExprAttrs * attrs, const vector & attrPath, } -#if 0 -static void checkPatternVars(ATerm pos, ATermMap & map, Pattern pat) +static void addFormal(const Pos & pos, Formals * formals, const Formal & formal) { - ATerm name = sNoAlias; - ATermList formals; - ATermBool ellipsis; - - if (matchAttrsPat(pat, formals, ellipsis, name)) { - for (ATermIterator i(formals); i; ++i) { - ATerm d1, name2; - if (!matchFormal(*i, name2, d1)) abort(); - if (map.get(name2)) - throw ParseError(format("duplicate formal function argument `%1%' at %2%") - % aterm2String(name2) % showPos(pos)); - map.set(name2, name2); - } - } - - else matchVarPat(pat, name); - - if (name != sNoAlias) { - if (map.get(name)) - throw ParseError(format("duplicate formal function argument `%1%' at %2%") - % aterm2String(name) % showPos(pos)); - map.set(name, name); - } + 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 void checkPatternVars(ATerm pos, Pattern pat) -{ - ATermMap map; - checkPatternVars(pos, map, pat); -} -#endif - - static Expr * stripIndentation(vector & es) { if (es.empty()) return new ExprString(""); @@ -294,7 +283,7 @@ expr: expr_function; expr_function : ID ':' expr_function - { $$ = new ExprLambda(CUR_POS, data->symbols.create($1), false, 0, $3); /* checkPatternVars(CUR_POS, $1); */ } + { $$ = 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 @@ -388,14 +377,22 @@ binds : binds attrpath '=' expr ';' { $$ = $1; addAttr($$, *$2, $4, CUR_POS); } | binds INHERIT ids ';' { $$ = $1; - foreach (vector::iterator, i, *$3) - $$->inherited.push_back(*i); + foreach (vector::iterator, i, *$3) { + if ($$->attrNames.find(*i) != $$->attrNames.end()) + dupAttr(*i, CUR_POS); + $$->inherited.push_back(*i); + $$->attrNames.insert(*i); + } } | binds INHERIT '(' expr ')' ids ';' { $$ = $1; /* !!! Should ensure sharing of the expression in $4. */ - foreach (vector::iterator, i, *$6) - $$->attrs[*i] = new ExprSelect($4, *i); + foreach (vector::iterator, i, *$6) { + if ($$->attrNames.find(*i) != $$->attrNames.end()) + dupAttr(*i, CUR_POS); + $$->attrs[*i] = new ExprSelect($4, *i); + $$->attrNames.insert(*i); + } } | { $$ = new ExprAttrs; } ; @@ -417,9 +414,9 @@ expr_list formals : formal ',' formals - { $$ = $3; $$->formals.push_front(*$1); /* !!! dangerous */ } + { $$ = $3; addFormal(CUR_POS, $$, *$1); } | formal - { $$ = new Formals; $$->formals.push_back(*$1); $$->ellipsis = false; } + { $$ = new Formals; addFormal(CUR_POS, $$, *$1); $$->ellipsis = false; } | { $$ = new Formals; $$->ellipsis = false; } | ELLIPSIS -- cgit 1.4.1