diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 9efe60931..1ecd867f5 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -818,6 +818,15 @@ ExpUNot::~ExpUNot() { } +ExpUMinus::ExpUMinus(Expression*op1) +: ExpUnary(op1) +{ +} + +ExpUMinus::~ExpUMinus() +{ +} + ExpCast::ExpCast(Expression*base, const VType*type) : base_(base), type_(type) { diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 65e1934bd..ca895967e 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -948,6 +948,19 @@ class ExpUNot : public ExpUnary { void dump(ostream&out, int indent = 0) const; }; +class ExpUMinus : public ExpUnary { + + public: + explicit ExpUMinus(Expression*op1); + ~ExpUMinus(); + + Expression*clone() const { return new ExpUMinus(peek_operand()->clone()); } + + void write_to_stream(std::ostream&fd) const; + int emit(ostream&out, Entity*ent, ScopeBase*scope) const; + void dump(ostream&out, int indent = 0) const; +}; + /* * Class that wraps other expressions to cast them to other types. */ diff --git a/vhdlpp/expression_debug.cc b/vhdlpp/expression_debug.cc index f745f128d..cf6a46902 100644 --- a/vhdlpp/expression_debug.cc +++ b/vhdlpp/expression_debug.cc @@ -142,6 +142,12 @@ void ExpUNot::dump(ostream&out, int indent) const dump_operand1(out, indent+4); } +void ExpUMinus::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "unary_minus() at " << get_fileline() << endl; + dump_operand1(out, indent+4); +} + void ExpTime::dump(ostream&out, int indent) const { out << setw(indent) << "" << "Time "; diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index f490cf4dd..e3c6cb964 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -1048,6 +1048,15 @@ int ExpUNot::emit(ostream&out, Entity*ent, ScopeBase*scope) const return errors; } +int ExpUMinus::emit(ostream&out, Entity*ent, ScopeBase*scope) const +{ + int errors = 0; + out << "-("; + errors += emit_operand1(out, ent, scope); + out << ")"; + return errors; +} + int ExpCast::emit(ostream&out, Entity*ent, ScopeBase*scope) const { int errors = 0; diff --git a/vhdlpp/expression_stream.cc b/vhdlpp/expression_stream.cc index 43756922a..f9f6f40e5 100644 --- a/vhdlpp/expression_stream.cc +++ b/vhdlpp/expression_stream.cc @@ -327,6 +327,13 @@ void ExpUNot::write_to_stream(ostream&fd) const write_to_stream_operand1(fd); } +void ExpUMinus::write_to_stream(ostream&fd) const +{ + fd << "-("; + write_to_stream_operand1(fd); + fd << ")"; +} + void ExpCast::write_to_stream(ostream&fd) const { // Type casting is introduced only for a few specific cases in diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 82ccde7e3..6b4c13e5d 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -2484,11 +2484,6 @@ shift_expression } ; -sign - : '+' - | '-' - ; - signal_declaration_assign_opt : VASSIGN expression { $$ = $2; } | { $$ = 0; } @@ -2514,10 +2509,10 @@ signal_declaration_assign_opt * list fixes up the associations. */ simple_expression - : sign simple_expression_2 - { sorrymsg(@1, "Unary expression +- not supported.\n"); - $$ = $2; - } + : '-' simple_expression_2 + { $$ = new ExpUMinus($2); } + | '+' simple_expression_2 + { $$ = $2; } | simple_expression_2 { $$ = $1; } ;