Fold dynamic binds handling into addAttr

Since addAttr has to iterate through the AttrPath we pass it, it makes
more sense to just iterate through the AttrNames in addAttr instead. As
an added bonus, this allows attrsets where two dynamic attribute paths
have the same static leading part (see added test case for an example
that failed previously).

Signed-off-by: Shea Levy <shea@shealevy.com>
This commit is contained in:
Shea Levy 2013-12-31 17:57:10 -05:00
parent 18fefacf7d
commit 6f3a51809a
3 changed files with 37 additions and 55 deletions

View file

@ -89,31 +89,47 @@ static void dupAttr(Symbol attr, const Pos & pos, const Pos & prevPos)
} }
static void addAttr(ExprAttrs * attrs, AttrPath & attrPath, static void addAttr(ExprAttrs * attrs, AttrNames & attrNames,
Expr * e, const Pos & pos) Expr * e, const Pos & pos)
{ {
unsigned int n = 0; AttrPath path;
foreach (AttrPath::const_iterator, i, attrPath) { AttrNames::iterator i;
n++; // All attrpaths have at least one attr
ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(*i); assert(!attrNames.empty());
if (j != attrs->attrs.end()) { for (i = attrNames.begin(); i + 1 < attrNames.end(); i++) {
if (!j->second.inherited) { if (i->symbol.set()) {
ExprAttrs * attrs2 = dynamic_cast<ExprAttrs *>(j->second.e); path.push_back(i->symbol);
if (!attrs2 || n == attrPath.size()) dupAttr(attrPath, pos, j->second.pos); ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol);
attrs = attrs2; if (j != attrs->attrs.end()) {
} else if (!j->second.inherited) {
dupAttr(attrPath, pos, j->second.pos); ExprAttrs * attrs2 = dynamic_cast<ExprAttrs *>(j->second.e);
} else { if (!attrs2) dupAttr(path, pos, j->second.pos);
if (n == attrPath.size()) attrs = attrs2;
attrs->attrs[*i] = ExprAttrs::AttrDef(e, pos); } else
else { dupAttr(path, pos, j->second.pos);
} else {
path.clear();
ExprAttrs * nested = new ExprAttrs; ExprAttrs * nested = new ExprAttrs;
attrs->attrs[*i] = ExprAttrs::AttrDef(nested, pos); attrs->attrs[i->symbol] = ExprAttrs::AttrDef(nested, pos);
attrs = nested; attrs = nested;
} }
} else {
ExprAttrs *nested = new ExprAttrs;
attrs->dynamicAttrs.push_back(ExprAttrs::DynamicAttrDef(i->expr, nested, pos));
attrs = nested;
} }
} }
e->setName(attrPath.back()); if (i->symbol.set()) {
ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol);
if (j != attrs->attrs.end()) {
dupAttr(path, 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));
}
} }
@ -522,43 +538,7 @@ ind_string_parts
; ;
binds binds
: binds attrpath '=' expr ';' : binds attrpath '=' expr ';' { $$ = $1; addAttr($$, *$2, $4, makeCurPos(@2, data)); }
{
ExprAttrs *curAttrs = $1;
AttrPath path;
vector<AttrName>::iterator i;
// All attrpaths have at least one attr
assert(!$2->empty());
for (i = $2->begin(); i + 1 < $2->end(); i++) {
if (i->symbol.set()) {
path.push_back(i->symbol);
} else {
ExprAttrs *temp;
if (!path.empty()) {
temp = curAttrs;
curAttrs = new ExprAttrs;
addAttr(temp, path, curAttrs, makeCurPos(@2, data));
}
path.clear();
temp = curAttrs;
curAttrs = new ExprAttrs;
temp->dynamicAttrs.push_back(ExprAttrs::DynamicAttrDef(i->expr, curAttrs, makeCurPos(@2, data)));
}
}
if (i->symbol.set()) {
path.push_back(i->symbol);
addAttr(curAttrs, path, $4, makeCurPos(@2, data));
} else {
if (!path.empty()) {
ExprAttrs *temp = curAttrs;
curAttrs = new ExprAttrs;
addAttr(temp, path, curAttrs, makeCurPos(@2, data));
}
curAttrs->dynamicAttrs.push_back(ExprAttrs::DynamicAttrDef(i->expr, $4, makeCurPos(@2, data)));
}
$$ = $1;
}
| binds INHERIT attrs ';' | binds INHERIT attrs ';'
{ $$ = $1; { $$ = $1;
foreach (AttrPath::iterator, i, *$3) { foreach (AttrPath::iterator, i, *$3) {

View file

@ -0,0 +1 @@
true

View file

@ -0,0 +1 @@
{ a."${"b"}" = true; a."${"c"}" = false; }.a.b