vhdlpp: Support for multiple choices in case statements.

This commit is contained in:
Maciej Suminski 2015-02-03 16:52:19 +01:00
parent a1c2a8e605
commit 5b7b980ead
6 changed files with 65 additions and 23 deletions

View File

@ -573,20 +573,40 @@ case_statement_alternative_list
* statement alternative and pass that up instead.
*/
case_statement_alternative
: K_when choice ARROW sequence_of_statements
: K_when choices ARROW sequence_of_statements
{ CaseSeqStmt::CaseStmtAlternative* tmp;
if ($2->others()) {
tmp = new CaseSeqStmt::CaseStmtAlternative(0, $4);
} else if (Expression*ex = $2->simple_expression()) {
tmp = new CaseSeqStmt::CaseStmtAlternative(ex, $4);
} else {
errormsg(@2, "I don't know what to make of the case choice\n");
tmp = 0;
}
if (tmp) FILE_NAME(tmp, @1);
delete $2;
delete $4;
$$ = tmp;
std::list<ExpAggregate::choice_t*>*choices = $2;
std::list<Expression*>*exp_list = new std::list<Expression*>;
bool others = false;
for(std::list<ExpAggregate::choice_t*>::iterator it = choices->begin();
it != choices->end(); ++it) {
if((*it)->others() || others)
// If there is one "others", then it also covers all other alternatives
// Continue the loop to delete every choice_t, but do not
// bother to add the expressions to the exp_list (we are going to
// delete them very soon)
others = true;
else
exp_list->push_back((*it)->simple_expression());
delete (*it);
}
if(others) {
tmp = new CaseSeqStmt::CaseStmtAlternative(0, $4);
for(std::list<Expression*>::iterator it = exp_list->begin();
it != exp_list->end(); ++it) {
delete (*it);
}
} else {
tmp = new CaseSeqStmt::CaseStmtAlternative(exp_list, $4);
}
if (tmp) FILE_NAME(tmp, @1);
delete choices;
delete $4;
$$ = tmp;
}
;

View File

@ -146,7 +146,8 @@ void CaseSeqStmt::visit(SeqStmtVisitor& func)
func(this);
}
CaseSeqStmt::CaseStmtAlternative::CaseStmtAlternative(Expression* exp, list<SequentialStmt*>* stmts)
CaseSeqStmt::CaseStmtAlternative::CaseStmtAlternative(std::list<Expression*>*exp,
list<SequentialStmt*>*stmts)
: exp_(exp)
{
if (stmts) stmts_.splice(stmts_.end(), *stmts);

View File

@ -167,7 +167,7 @@ class CaseSeqStmt : public SequentialStmt {
public:
class CaseStmtAlternative : public LineInfo {
public:
CaseStmtAlternative(Expression* exp, std::list<SequentialStmt*>* stmts);
CaseStmtAlternative(std::list<Expression*>*exp, std::list<SequentialStmt*>*stmts);
~CaseStmtAlternative();
void dump(std::ostream& out, int indent) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
@ -177,7 +177,7 @@ class CaseSeqStmt : public SequentialStmt {
void visit(SeqStmtVisitor& func);
private:
Expression* exp_;
std::list<Expression*>*exp_;
std::list<SequentialStmt*> stmts_;
private: // not implemented
CaseStmtAlternative(const CaseStmtAlternative&);

View File

@ -105,7 +105,9 @@ void CaseSeqStmt::CaseStmtAlternative::dump(ostream& out, int indent) const
out << setw(indent) << "" << "when ";
if (exp_)
exp_->dump(out, 0);
for (list<Expression*>::iterator it = exp_->begin(); it != exp_->end(); ++it) {
(*it)->dump(out, 0);
}
else
out << "others" << endl;

View File

@ -62,8 +62,12 @@ int CaseSeqStmt::elaborate(Entity*ent, ScopeBase*scope)
int CaseSeqStmt::CaseStmtAlternative::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{
int errors = 0;
if (exp_)
errors += exp_->elaborate_expr(ent, scope, ltype);
if (exp_) {
for (list<Expression*>::iterator it = exp_->begin(); it != exp_->end();
++it) {
errors += (*it)->elaborate_expr(ent, scope, ltype);
}
}
return errors;
}

View File

@ -271,12 +271,19 @@ int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, ScopeBase*sc
{
int errors = 0;
bool first = true;
if (exp_) {
errors += exp_->emit(out, ent, scope);
out << ":" << endl;
for (list<Expression*>::iterator it = exp_->begin(); it != exp_->end(); ++it) {
if(first)
first = false;
else
out << ",";
errors += (*it)->emit(out, ent, scope);
}
} else {
out << "default:" << endl;
out << "default";
}
out << ":" << endl;
SequentialStmt*curp;
@ -306,7 +313,15 @@ void CaseSeqStmt::CaseStmtAlternative::write_to_stream(ostream&fd)
{
fd << "when ";
if (exp_) {
exp_->write_to_stream(fd);
bool first = true;
for (list<Expression*>::iterator it = exp_->begin(); it != exp_->end(); ++it) {
if(first)
first = false;
else
fd << "|";
(*it)->write_to_stream(fd);
}
} else {
fd << "others" << endl;
}