vhdlpp: Support for multiple choices in case statements.
This commit is contained in:
parent
a1c2a8e605
commit
5b7b980ead
|
|
@ -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;
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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&);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue