From cbb213d79e21f97dd4e228d6e94a4cbf3718f51f Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sat, 19 Feb 2011 17:47:30 -0800 Subject: [PATCH] Support for some arithmetic operators. --- vhdlpp/debug.cc | 37 +++++++++++++++++++++++++-- vhdlpp/expression.cc | 24 +++++++++++++++--- vhdlpp/expression.h | 41 +++++++++++++++++++++++++++--- vhdlpp/expression_emit.cc | 39 ++++++++++++++++++++++++++-- vhdlpp/parse.y | 53 ++++++++++++++++++++++++++++++++++++--- 5 files changed, 180 insertions(+), 14 deletions(-) diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index 31ec3330c..0ef95667e 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -116,6 +116,39 @@ void Expression::dump(ostream&out, int indent) const << " at " << get_fileline()<< endl; } +void ExpArithmetic::dump(ostream&out, int indent) const +{ + const char*fun_name = "?"; + switch (fun_) { + case PLUS: + fun_name = "+"; + break; + case MINUS: + fun_name = "-"; + break; + case MULT: + fun_name = "*"; + break; + case DIV: + fun_name = "/"; + break; + case MOD: + fun_name = "mod"; + break; + case REM: + fun_name = "rem"; + break; + case POW: + fun_name = "**"; + break; + } + + out << setw(indent) << "" << "Arithmetic " << fun_name + << " at " << get_fileline() << endl; + operand1()->dump(out, indent+4); + operand2()->dump(out, indent+4); +} + void ExpInteger::dump(ostream&out, int indent) const { out << setw(indent) << "" << "Integer" << endl; @@ -147,8 +180,8 @@ void ExpLogical::dump(ostream&out, int indent) const out << setw(indent) << "" << "Logical " << fun_name << " at " << get_fileline() << endl; - operand1_->dump(out, indent+4); - operand2_->dump(out, indent+4); + operand1()->dump(out, indent+4); + operand2()->dump(out, indent+4); } void ExpName::dump(ostream&out, int indent) const diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 563de85a6..3021cd833 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -32,6 +32,26 @@ bool Expression::evaluate(int64_t&) const return false; } +ExpBinary::ExpBinary(Expression*op1, Expression*op2) +: operand1_(op1), operand2_(op2) +{ +} + +ExpBinary::~ExpBinary() +{ + delete operand1_; + delete operand2_; +} + +ExpArithmetic::ExpArithmetic(ExpArithmetic::fun_t op, Expression*op1, Expression*op2) +: ExpBinary(op1, op2), fun_(op) +{ +} + +ExpArithmetic::~ExpArithmetic() +{ +} + ExpInteger::ExpInteger(int64_t val) : value_(val) { @@ -48,14 +68,12 @@ bool ExpInteger::evaluate(int64_t&val) const } ExpLogical::ExpLogical(ExpLogical::fun_t ty, Expression*op1, Expression*op2) -: fun_(ty), operand1_(op1), operand2_(op2) +: ExpBinary(op1, op2), fun_(ty) { } ExpLogical::~ExpLogical() { - delete operand1_; - delete operand2_; } ExpName::ExpName(perm_string nn) diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 2be9b628c..2b7f197f9 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -58,6 +58,43 @@ class Expression : public LineInfo { Expression& operator = (const Expression&); }; +/* + * This is an abstract class that collects some of the common features + * of binary operators. + */ +class ExpBinary : public Expression { + + public: + ExpBinary(Expression*op1, Expression*op2); + ~ExpBinary(); + + protected: + inline Expression* operand1() { return operand1_; } + inline Expression* operand2() { return operand2_; } + inline const Expression* operand1() const { return operand1_; } + inline const Expression* operand2() const { return operand2_; } + + private: + Expression*operand1_; + Expression*operand2_; +}; + +class ExpArithmetic : public ExpBinary { + + public: + enum fun_t { PLUS, MINUS, MULT, DIV, MOD, REM, POW }; + + public: + ExpArithmetic(ExpArithmetic::fun_t op, Expression*op1, Expression*op2); + ~ExpArithmetic(); + + int emit(ostream&out, Entity*ent, Architecture*arc); + void dump(ostream&out, int indent) const; + + private: + fun_t fun_; +}; + class ExpInteger : public Expression { public: @@ -72,7 +109,7 @@ class ExpInteger : public Expression { int64_t value_; }; -class ExpLogical : public Expression { +class ExpLogical : public ExpBinary { public: enum fun_t { AND, OR, NAND, NOR, XOR, XNOR }; @@ -86,8 +123,6 @@ class ExpLogical : public Expression { private: fun_t fun_; - Expression*operand1_; - Expression*operand2_; }; /* diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index 43cda40ad..0099fd163 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -31,6 +31,41 @@ int Expression::emit(ostream&out, Entity*, Architecture*) return 1; } +int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc) +{ + int errors = 0; + + errors += operand1()->emit(out, ent, arc); + + switch (fun_) { + case PLUS: + out << " + "; + break; + case MINUS: + out << " - "; + break; + case MULT: + out << " * "; + break; + case DIV: + out << " / "; + break; + case MOD: + out << " % "; + break; + case POW: + out << " ** "; + break; + case REM: + out << " /* ?remainder? */ "; + break; + } + + errors += operand2()->emit(out, ent, arc); + + return errors; +} + int ExpInteger::emit(ostream&out, Entity*, Architecture*) { out << " /* " << get_fileline() << ": internal error: " @@ -42,7 +77,7 @@ int ExpLogical::emit(ostream&out, Entity*ent, Architecture*arc) { int errors = 0; - errors += operand1_->emit(out, ent, arc); + errors += operand1()->emit(out, ent, arc); switch (fun_) { case AND: @@ -65,7 +100,7 @@ int ExpLogical::emit(ostream&out, Entity*ent, Architecture*arc) break; } - errors += operand2_->emit(out, ent, arc); + errors += operand2()->emit(out, ent, arc); return errors; } diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index d2696ab03..079ba521a 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -253,7 +253,8 @@ expression ; expression_logical - : relation K_and relation + : relation { $$ = $1; } + | relation K_and relation { ExpLogical*tmp = new ExpLogical(ExpLogical::AND, $1, $3); FILE_NAME(tmp, @2); $$ = tmp; @@ -285,7 +286,15 @@ expression_logical } ; -factor : primary { $$ = $1; } ; +factor + : primary + { $$ = $1; } + | primary EXP primary + { ExpArithmetic*tmp = new ExpArithmetic(ExpArithmetic::POW, $1, $3); + FILE_NAME(tmp, @2); + $$ = tmp; + } + ; identifier_opt : IDENTIFIER { $$ = $1; } | { $$ = 0; } ; @@ -401,7 +410,20 @@ selected_names_use shift_expression : simple_expression { $$ = $1; } ; -simple_expression : term { $$ = $1; } ; +simple_expression + : term + { $$ = $1; } + | term '+' term + { ExpArithmetic*tmp = new ExpArithmetic(ExpArithmetic::PLUS, $1, $3); + FILE_NAME(tmp, @2); + $$ = tmp; + } + | term '-' term + { ExpArithmetic*tmp = new ExpArithmetic(ExpArithmetic::MINUS, $1, $3); + FILE_NAME(tmp, @2); + $$ = tmp; + } + ; subtype_indication : IDENTIFIER @@ -416,7 +438,30 @@ subtype_indication } ; -term : factor { $$ = $1; } ; +term + : factor + { $$ = $1; } + | factor '*' factor + { ExpArithmetic*tmp = new ExpArithmetic(ExpArithmetic::MULT, $1, $3); + FILE_NAME(tmp, @2); + $$ = tmp; + } + | factor '/' factor + { ExpArithmetic*tmp = new ExpArithmetic(ExpArithmetic::DIV, $1, $3); + FILE_NAME(tmp, @2); + $$ = tmp; + } + | factor K_mod factor + { ExpArithmetic*tmp = new ExpArithmetic(ExpArithmetic::MOD, $1, $3); + FILE_NAME(tmp, @2); + $$ = tmp; + } + | factor K_rem factor + { ExpArithmetic*tmp = new ExpArithmetic(ExpArithmetic::REM, $1, $3); + FILE_NAME(tmp, @2); + $$ = tmp; + } + ; use_clause : K_use selected_names_use ';'