134 lines
2.4 KiB
C++
134 lines
2.4 KiB
C++
#include "expr.hpp"
|
|
|
|
struct EvalVisitor : Visitor {
|
|
|
|
static const uint32_t max_depth = 32;
|
|
|
|
bool fail;
|
|
uint32_t depth;
|
|
double stack[max_depth];
|
|
|
|
EvalVisitor()
|
|
{
|
|
depth = 0;
|
|
fail = false;
|
|
}
|
|
|
|
void visit_int(IntValue *node)
|
|
{
|
|
if (fail) return;
|
|
|
|
if (depth == max_depth) {
|
|
fail = true;
|
|
return;
|
|
}
|
|
|
|
stack[depth++] = node->val;
|
|
}
|
|
|
|
void visit_float(FloatValue *node)
|
|
{
|
|
if (fail) return;
|
|
|
|
if (depth == max_depth) {
|
|
fail = true;
|
|
return;
|
|
}
|
|
|
|
stack[depth++] = node->val;
|
|
}
|
|
|
|
void visit_neg(NegOperation *node)
|
|
{
|
|
node->op->visit(*this);
|
|
|
|
if (fail) return;
|
|
|
|
if (depth < 1) {
|
|
fail = true;
|
|
return;
|
|
}
|
|
|
|
stack[depth-1] = -stack[depth-1];
|
|
}
|
|
|
|
void visit_add(AddOperation *node)
|
|
{
|
|
node->lhs->visit(*this);
|
|
node->rhs->visit(*this);
|
|
|
|
if (fail) return;
|
|
|
|
if (depth < 2) {
|
|
fail = true;
|
|
return;
|
|
}
|
|
|
|
double rhs = stack[--depth];
|
|
double lhs = stack[--depth];
|
|
stack[depth++] = lhs + rhs;
|
|
}
|
|
|
|
void visit_sub(SubOperation *node)
|
|
{
|
|
node->lhs->visit(*this);
|
|
node->rhs->visit(*this);
|
|
|
|
if (fail) return;
|
|
|
|
if (depth < 2) {
|
|
fail = true;
|
|
return;
|
|
}
|
|
|
|
double rhs = stack[--depth];
|
|
double lhs = stack[--depth];
|
|
stack[depth++] = lhs - rhs;
|
|
}
|
|
|
|
void visit_mul(MulOperation *node)
|
|
{
|
|
node->lhs->visit(*this);
|
|
node->rhs->visit(*this);
|
|
|
|
if (fail) return;
|
|
|
|
if (depth < 2) {
|
|
fail = true;
|
|
return;
|
|
}
|
|
|
|
double rhs = stack[--depth];
|
|
double lhs = stack[--depth];
|
|
stack[depth++] = lhs * rhs;
|
|
}
|
|
|
|
void visit_div(DivOperation *node)
|
|
{
|
|
node->lhs->visit(*this);
|
|
node->rhs->visit(*this);
|
|
|
|
if (fail) return;
|
|
|
|
if (depth < 2) {
|
|
fail = true;
|
|
return;
|
|
}
|
|
|
|
double rhs = stack[--depth];
|
|
double lhs = stack[--depth];
|
|
stack[depth++] = lhs / rhs;
|
|
}
|
|
};
|
|
|
|
double eval(Expr *e)
|
|
{
|
|
EvalVisitor visitor;
|
|
e->visit(visitor);
|
|
|
|
if (visitor.fail)
|
|
return 0;
|
|
else
|
|
return visitor.stack[visitor.depth-1];
|
|
}
|