Support for some arithmetic operators.

This commit is contained in:
Stephen Williams 2011-02-19 17:47:30 -08:00
parent acc4f73186
commit cbb213d79e
5 changed files with 180 additions and 14 deletions

View File

@ -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

View File

@ -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)

View File

@ -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_;
};
/*

View File

@ -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;
}

View File

@ -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 ';'