Add support for nested when/else expressions.
This commit is contained in:
parent
1249b5dd32
commit
9b816f6478
|
|
@ -292,11 +292,22 @@ void ExpConditional::dump(ostream&out, int indent) const
|
||||||
(*cur)->dump(out, indent+4);
|
(*cur)->dump(out, indent+4);
|
||||||
}
|
}
|
||||||
|
|
||||||
out << setw(indent) << "" << " else:" << endl;
|
for (list<else_t*>::const_iterator cur = else_clause_.begin()
|
||||||
for (list<Expression*>::const_iterator cur = else_clause_.begin()
|
|
||||||
; cur != else_clause_.end() ; ++cur) {
|
; cur != else_clause_.end() ; ++cur) {
|
||||||
|
(*cur)->dump(out, indent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpConditional::else_t::dump(ostream&out, int indent) const
|
||||||
|
{
|
||||||
|
out << setw(indent) << "" << "when:" << endl;
|
||||||
|
if (cond_) cond_->dump(out, indent+4);
|
||||||
|
out << setw(indent) << "" << "do:" << endl;
|
||||||
|
for (list<Expression*>::const_iterator cur = true_clause_.begin()
|
||||||
|
; cur != true_clause_.end() ; ++cur) {
|
||||||
(*cur)->dump(out, indent+4);
|
(*cur)->dump(out, indent+4);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExpEdge::dump(ostream&out, int indent) const
|
void ExpEdge::dump(ostream&out, int indent) const
|
||||||
|
|
|
||||||
|
|
@ -256,11 +256,12 @@ ExpCharacter::~ExpCharacter()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpConditional::ExpConditional(Expression*co, list<Expression*>*tru, list<Expression*>*els)
|
ExpConditional::ExpConditional(Expression*co, list<Expression*>*tru,
|
||||||
|
list<ExpConditional::else_t*>*fal)
|
||||||
: cond_(co)
|
: cond_(co)
|
||||||
{
|
{
|
||||||
if (tru) true_clause_.splice(true_clause_.end(), *tru);
|
if (tru) true_clause_.splice(true_clause_.end(), *tru);
|
||||||
if (els) else_clause_.splice(else_clause_.end(), *els);
|
if (fal) else_clause_.splice(else_clause_.end(), *fal);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpConditional::~ExpConditional()
|
ExpConditional::~ExpConditional()
|
||||||
|
|
@ -272,12 +273,29 @@ ExpConditional::~ExpConditional()
|
||||||
delete tmp;
|
delete tmp;
|
||||||
}
|
}
|
||||||
while (! else_clause_.empty()) {
|
while (! else_clause_.empty()) {
|
||||||
Expression*tmp = else_clause_.front();
|
else_t*tmp = else_clause_.front();
|
||||||
else_clause_.pop_front();
|
else_clause_.pop_front();
|
||||||
delete tmp;
|
delete tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExpConditional::else_t::else_t(Expression*cond, std::list<Expression*>*tru)
|
||||||
|
: cond_(cond)
|
||||||
|
{
|
||||||
|
if (tru) true_clause_.splice(true_clause_.end(), *tru);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpConditional::else_t::~else_t()
|
||||||
|
{
|
||||||
|
delete cond_;
|
||||||
|
while (! true_clause_.empty()) {
|
||||||
|
Expression*tmp = true_clause_.front();
|
||||||
|
true_clause_.pop_front();
|
||||||
|
delete tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ExpEdge::ExpEdge(ExpEdge::fun_t typ, Expression*op)
|
ExpEdge::ExpEdge(ExpEdge::fun_t typ, Expression*op)
|
||||||
: ExpUnary(op), fun_(typ)
|
: ExpUnary(op), fun_(typ)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -339,9 +339,25 @@ class ExpCharacter : public Expression {
|
||||||
*/
|
*/
|
||||||
class ExpConditional : public Expression {
|
class ExpConditional : public Expression {
|
||||||
|
|
||||||
|
public:
|
||||||
|
class else_t : public LineInfo {
|
||||||
|
public:
|
||||||
|
else_t(Expression*cond, std::list<Expression*>*tru);
|
||||||
|
~else_t();
|
||||||
|
|
||||||
|
int elaborate_expr(Entity*ent, Architecture*arc, const VType*lt);
|
||||||
|
int emit_when_else(ostream&out, Entity*ent, Architecture*arc);
|
||||||
|
int emit_else(ostream&out, Entity*ent, Architecture*arc);
|
||||||
|
void dump(ostream&out, int indent = 0) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Expression*cond_;
|
||||||
|
std::list<Expression*> true_clause_;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ExpConditional(Expression*cond, std::list<Expression*>*tru,
|
ExpConditional(Expression*cond, std::list<Expression*>*tru,
|
||||||
std::list<Expression*>*els);
|
std::list<else_t*>*fal);
|
||||||
~ExpConditional();
|
~ExpConditional();
|
||||||
|
|
||||||
const VType*probe_type(Entity*ent, Architecture*arc) const;
|
const VType*probe_type(Entity*ent, Architecture*arc) const;
|
||||||
|
|
@ -353,7 +369,7 @@ class ExpConditional : public Expression {
|
||||||
private:
|
private:
|
||||||
Expression*cond_;
|
Expression*cond_;
|
||||||
std::list<Expression*> true_clause_;
|
std::list<Expression*> true_clause_;
|
||||||
std::list<Expression*> else_clause_;
|
std::list<else_t*> else_clause_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -330,7 +330,7 @@ int ExpConditional::elaborate_expr(Entity*ent, Architecture*arc, const VType*lty
|
||||||
errors += (*cur)->elaborate_expr(ent, arc, ltype);
|
errors += (*cur)->elaborate_expr(ent, arc, ltype);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (list<Expression*>::const_iterator cur = else_clause_.begin()
|
for (list<else_t*>::const_iterator cur = else_clause_.begin()
|
||||||
; cur != else_clause_.end() ; ++cur) {
|
; cur != else_clause_.end() ; ++cur) {
|
||||||
errors += (*cur)->elaborate_expr(ent, arc, ltype);
|
errors += (*cur)->elaborate_expr(ent, arc, ltype);
|
||||||
}
|
}
|
||||||
|
|
@ -338,6 +338,21 @@ int ExpConditional::elaborate_expr(Entity*ent, Architecture*arc, const VType*lty
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ExpConditional::else_t::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
||||||
|
{
|
||||||
|
int errors = 0;
|
||||||
|
|
||||||
|
if (cond_)
|
||||||
|
errors += cond_->elaborate_expr(ent, arc, 0);
|
||||||
|
|
||||||
|
for (list<Expression*>::const_iterator cur = true_clause_.begin()
|
||||||
|
; cur != true_clause_.end() ; ++cur) {
|
||||||
|
errors += (*cur)->elaborate_expr(ent, arc, ltype);
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
int ExpFunc::elaborate_expr(Entity*ent, Architecture*arc, const VType*)
|
int ExpFunc::elaborate_expr(Entity*ent, Architecture*arc, const VType*)
|
||||||
{
|
{
|
||||||
int errors = 0;
|
int errors = 0;
|
||||||
|
|
|
||||||
|
|
@ -328,7 +328,7 @@ int ExpConditional::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||||
out << ")? (";
|
out << ")? (";
|
||||||
|
|
||||||
if (true_clause_.size() > 1) {
|
if (true_clause_.size() > 1) {
|
||||||
cerr << get_fileline() << ": sorry: Multiple expressions not supported here." << endl;
|
cerr << get_fileline() << ": sorry: Multiple expression waveforms not supported here." << endl;
|
||||||
errors += 1;
|
errors += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -337,15 +337,66 @@ int ExpConditional::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||||
|
|
||||||
out << ") : (";
|
out << ") : (";
|
||||||
|
|
||||||
|
// Draw out any when-else expressions. These are all the else_
|
||||||
|
// clauses besides the last.
|
||||||
if (else_clause_.size() > 1) {
|
if (else_clause_.size() > 1) {
|
||||||
cerr << get_fileline() << ": sorry: Multiple expressions not supported here." << endl;
|
list<else_t*>::iterator last = else_clause_.end();
|
||||||
|
-- last;
|
||||||
|
|
||||||
|
for (list<else_t*>::iterator cur = else_clause_.begin()
|
||||||
|
; cur != last ; ++cur) {
|
||||||
|
errors += (*cur) ->emit_when_else(out, ent, arc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errors += else_clause_.back()->emit_else(out, ent, arc);
|
||||||
|
out << ")";
|
||||||
|
|
||||||
|
// The emit_when_else() functions do not close the last
|
||||||
|
// parentheses so that the following expression can be
|
||||||
|
// nested. But that means come the end, we have some
|
||||||
|
// expressions to close.
|
||||||
|
for (size_t idx = 1 ; idx < else_clause_.size() ; idx += 1)
|
||||||
|
out << ")";
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ExpConditional::else_t::emit_when_else(ostream&out, Entity*ent, Architecture*arc)
|
||||||
|
{
|
||||||
|
int errors = 0;
|
||||||
|
assert(cond_ != 0);
|
||||||
|
|
||||||
|
out << "(";
|
||||||
|
errors += cond_->emit(out, ent, arc);
|
||||||
|
out << ")? (";
|
||||||
|
|
||||||
|
if (true_clause_.size() > 1) {
|
||||||
|
cerr << get_fileline() << ": sorry: Multiple expression waveforms not supported here." << endl;
|
||||||
errors += 1;
|
errors += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = else_clause_.front();
|
Expression*tmp = true_clause_.front();
|
||||||
errors += tmp->emit(out, ent, arc);
|
errors += tmp->emit(out, ent, arc);
|
||||||
|
|
||||||
out << ")";
|
out << ") : (";
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ExpConditional::else_t::emit_else(ostream&out, Entity*ent, Architecture*arc)
|
||||||
|
{
|
||||||
|
int errors = 0;
|
||||||
|
// Trailing else must have no condition.
|
||||||
|
assert(cond_ == 0);
|
||||||
|
|
||||||
|
if (true_clause_.size() > 1) {
|
||||||
|
cerr << get_fileline() << ": sorry: Multiple expression waveforms not supported here." << endl;
|
||||||
|
errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression*tmp = true_clause_.front();
|
||||||
|
errors += tmp->emit(out, ent, arc);
|
||||||
|
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -205,6 +205,9 @@ static list<VTypeRecord::element_t*>* record_elements(list<perm_string>*names,
|
||||||
IfSequential::Elsif*elsif;
|
IfSequential::Elsif*elsif;
|
||||||
std::list<IfSequential::Elsif*>*elsif_list;
|
std::list<IfSequential::Elsif*>*elsif_list;
|
||||||
|
|
||||||
|
ExpConditional::else_t*exp_else;
|
||||||
|
std::list<ExpConditional::else_t*>*exp_else_list;
|
||||||
|
|
||||||
CaseSeqStmt::CaseStmtAlternative* case_alt;
|
CaseSeqStmt::CaseStmtAlternative* case_alt;
|
||||||
std::list<CaseSeqStmt::CaseStmtAlternative*>* case_alt_list;
|
std::list<CaseSeqStmt::CaseStmtAlternative*>* case_alt_list;
|
||||||
|
|
||||||
|
|
@ -282,7 +285,9 @@ static list<VTypeRecord::element_t*>* record_elements(list<perm_string>*names,
|
||||||
%type <instantiation_list> instantiation_list
|
%type <instantiation_list> instantiation_list
|
||||||
%type <component_specification> component_specification
|
%type <component_specification> component_specification
|
||||||
|
|
||||||
%type <arch_statement> concurrent_statement component_instantiation_statement concurrent_signal_assignment_statement
|
%type <arch_statement> concurrent_statement component_instantiation_statement
|
||||||
|
%type <arch_statement> concurrent_conditional_signal_assignment
|
||||||
|
%type <arch_statement> concurrent_signal_assignment_statement
|
||||||
%type <arch_statement> for_generate_statement generate_statement if_generate_statement
|
%type <arch_statement> for_generate_statement generate_statement if_generate_statement
|
||||||
%type <arch_statement> process_statement
|
%type <arch_statement> process_statement
|
||||||
%type <arch_statement_list> architecture_statement_part generate_statement_body
|
%type <arch_statement_list> architecture_statement_part generate_statement_body
|
||||||
|
|
@ -334,6 +339,9 @@ static list<VTypeRecord::element_t*>* record_elements(list<perm_string>*names,
|
||||||
%type <elsif> if_statement_elsif
|
%type <elsif> if_statement_elsif
|
||||||
%type <elsif_list> if_statement_elsif_list if_statement_elsif_list_opt
|
%type <elsif_list> if_statement_elsif_list if_statement_elsif_list_opt
|
||||||
|
|
||||||
|
%type <exp_else> else_when_waveform
|
||||||
|
%type <exp_else_list> else_when_waveforms
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
/* The design_file is the root for the VHDL parse. This rule is also
|
/* The design_file is the root for the VHDL parse. This rule is also
|
||||||
|
|
@ -653,7 +661,54 @@ composite_type_definition
|
||||||
{ $$ = $1; }
|
{ $$ = $1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
concurrent_signal_assignment_statement
|
|
||||||
|
/* The when...else..when...else syntax is not a general expression
|
||||||
|
in VHDL but a specific sort of assignment statement model. We
|
||||||
|
create Exppression objects for it, but the parser will only
|
||||||
|
recognize it it in specific situations. */
|
||||||
|
concurrent_conditional_signal_assignment /* IEEE 1076-2008 P11.6 */
|
||||||
|
: name LEQ waveform K_when expression else_when_waveforms ';'
|
||||||
|
{ ExpConditional*tmp = new ExpConditional($5, $3, $6);
|
||||||
|
FILE_NAME(tmp, @3);
|
||||||
|
delete $3;
|
||||||
|
delete $6;
|
||||||
|
|
||||||
|
ExpName*name = dynamic_cast<ExpName*> ($1);
|
||||||
|
assert(name);
|
||||||
|
SignalAssignment*tmpa = new SignalAssignment(name, tmp);
|
||||||
|
FILE_NAME(tmpa, @1);
|
||||||
|
|
||||||
|
$$ = tmpa;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
else_when_waveforms
|
||||||
|
: else_when_waveforms else_when_waveform
|
||||||
|
{ list<ExpConditional::else_t*>*tmp = $1;
|
||||||
|
tmp ->push_back($2);
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
| else_when_waveform
|
||||||
|
{ list<ExpConditional::else_t*>*tmp = new list<ExpConditional::else_t*>;
|
||||||
|
tmp->push_back($1);
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
else_when_waveform
|
||||||
|
: K_else waveform K_when expression
|
||||||
|
{ ExpConditional::else_t*tmp = new ExpConditional::else_t($4, $2);
|
||||||
|
FILE_NAME(tmp, @1);
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
| K_else waveform
|
||||||
|
{ ExpConditional::else_t*tmp = new ExpConditional::else_t(0, $2);
|
||||||
|
FILE_NAME(tmp, @1);
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
concurrent_signal_assignment_statement /* IEEE 1076-2008 P11.6 */
|
||||||
: name LEQ waveform ';'
|
: name LEQ waveform ';'
|
||||||
{ ExpName*name = dynamic_cast<ExpName*> ($1);
|
{ ExpName*name = dynamic_cast<ExpName*> ($1);
|
||||||
assert(name);
|
assert(name);
|
||||||
|
|
@ -663,19 +718,9 @@ concurrent_signal_assignment_statement
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
delete $3;
|
delete $3;
|
||||||
}
|
}
|
||||||
| name LEQ waveform K_when expression K_else waveform ';'
|
|
||||||
{ ExpConditional*tmp = new ExpConditional($5, $3, $7);
|
|
||||||
FILE_NAME(tmp, @3);
|
|
||||||
delete $3;
|
|
||||||
delete $7;
|
|
||||||
|
|
||||||
ExpName*name = dynamic_cast<ExpName*> ($1);
|
| concurrent_conditional_signal_assignment
|
||||||
assert(name);
|
|
||||||
SignalAssignment*tmpa = new SignalAssignment(name, tmp);
|
|
||||||
FILE_NAME(tmpa, @1);
|
|
||||||
|
|
||||||
$$ = tmpa;
|
|
||||||
}
|
|
||||||
| name LEQ error ';'
|
| name LEQ error ';'
|
||||||
{ errormsg(@2, "Syntax error in signal assignment waveform.\n");
|
{ errormsg(@2, "Syntax error in signal assignment waveform.\n");
|
||||||
delete $1;
|
delete $1;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue