diff options
author | Félix Baylac-Jacqué <felix@alternativebit.fr> | 2018-04-18T16·39+0200 |
---|---|---|
committer | Félix Baylac-Jacqué <felix@alternativebit.fr> | 2018-04-18T16·44+0200 |
commit | 00584bb0915ee21fb01e9390a901161bdd988197 (patch) | |
tree | 27643cb3166fa8d9c989572313623a960ae47ac0 /src/libexpr | |
parent | 10d33452e289ded93e192c7d99c1da08a52448e1 (diff) |
parser: Allow mixed nested and top-level attrpaths
Fixes #2077.
Diffstat (limited to 'src/libexpr')
-rw-r--r-- | src/libexpr/parser.y | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index ef11dd609217..df4fdf032479 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -83,7 +83,9 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath, AttrPath::iterator i; // All attrpaths have at least one attr assert(!attrPath.empty()); - for (i = attrPath.begin(); i + 1 < attrPath.end(); i++) { + // Checking attrPath validity. + // =========================== + 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()) { @@ -104,11 +106,29 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath, attrs = nested; } } - if (i->symbol.set()) { + // Expr insertion. + // ========================== + if (i->symbol.set()) { ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol); if (j != attrs->attrs.end()) { - dupAttr(attrPath, pos, j->second.pos); + // This attr path is already defined. However, if both + // e and the expr pointed by the attr path are two attribute sets, + // we want to merge them. + // Otherwise, throw an error. + ExprAttrs* ae = dynamic_cast<ExprAttrs *>(e); + ExprAttrs* jAttrs = dynamic_cast<ExprAttrs *>(j->second.e); + if (jAttrs && ae) { + for (auto ad: ae->attrs) { + ExprAttrs::AttrDefs::iterator j2 = jAttrs->attrs.find(ad.first); + if (j2 != jAttrs->attrs.end()) // Attr already defined in iAttrs, error. + dupAttr(ad.first, j2->second.pos, ad.second.pos); + jAttrs->attrs[ad.first] = ad.second; + } + } else { + dupAttr(attrPath, pos, j->second.pos); + } } else { + // This attr path is not defined. Let's create it. attrs->attrs[i->symbol] = ExprAttrs::AttrDef(e, pos); e->setName(i->symbol); } |