#ifndef EXPRESSION_H
#define EXPRESSION_H
#include <map>
#include <vector>
#include <ostream>
#include <stdexcept>
#include <cmath>
class CalcNode
{
public:
virtual ~CalcNode()
{
}
virtual double evaluate() const = 0;
virtual void print(std::ostream &os, unsigned int depth=0) const = 0;
static inline std::string indent(unsigned int d)
{
return std::string(d * 2, ' ');
}
};
class CNConstant : public CalcNode
{
double value;
public:
explicit CNConstant(double _value)
: CalcNode(), value(_value)
{
}
virtual double evaluate() const
{
return value;
}
virtual void print(std::ostream &os, unsigned int depth) const
{
os << indent(depth) << value << std::endl;
}
};
class CNNegate : public CalcNode
{
CalcNode* node;
public:
explicit CNNegate(CalcNode* _node)
: CalcNode(), node(_node)
{
}
virtual ~CNNegate()
{
delete node;
}
virtual double evaluate() const
{
return - node->evaluate();
}
virtual void print(std::ostream &os, unsigned int depth) const
{
os << indent(depth) << "- negate" << std::endl;
node->print(os, depth+1);
}
};
class CNAdd : public CalcNode
{
CalcNode* left;
CalcNode* right;
public:
explicit CNAdd(CalcNode* _left, CalcNode* _right)
: CalcNode(), left(_left), right(_right)
{
}
virtual ~CNAdd()
{
delete left;
delete right;
}
virtual double evaluate() const
{
return left->evaluate() + right->evaluate();
}
virtual void print(std::ostream &os, unsigned int depth) const
{
os << indent(depth) << "+ add" << std::endl;
left->print(os, depth+1);
right->print(os, depth+1);
}
};
class CNSubtract : public CalcNode
{
CalcNode* left;
CalcNode* right;
public:
explicit CNSubtract(CalcNode* _left, CalcNode* _right)
: CalcNode(), left(_left), right(_right)
{
}
virtual ~CNSubtract()
{
delete left;
delete right;
}
virtual double evaluate() const
{
return left->evaluate() - right->evaluate();
}
virtual void print(std::ostream &os, unsigned int depth) const
{
os << indent(depth) << "- subtract" << std::endl;
left->print(os, depth+1);
right->print(os, depth+1);
}
};
class CNMultiply : public CalcNode
{
CalcNode* left;
CalcNode* right;
public:
explicit CNMultiply(CalcNode* _left, CalcNode* _right)
: CalcNode(), left(_left), right(_right)
{
}
virtual ~CNMultiply()
{
delete left;
delete right;
}
virtual double evaluate() const
{
return left->evaluate() * right->evaluate();
}
virtual void print(std::ostream &os, unsigned int depth) const
{
os << indent(depth) << "* multiply" << std::endl;
left->print(os, depth+1);
right->print(os, depth+1);
}
};
class CNDivide : public CalcNode
{
CalcNode* left;
CalcNode* right;
public:
explicit CNDivide(CalcNode* _left, CalcNode* _right)
: CalcNode(), left(_left), right(_right)
{
}
virtual ~CNDivide()
{
delete left;
delete right;
}
virtual double evaluate() const
{
return left->evaluate() / right->evaluate();
}
virtual void print(std::ostream &os, unsigned int depth) const
{
os << indent(depth) << "/ divide" << std::endl;
left->print(os, depth+1);
right->print(os, depth+1);
}
};
class CNModulo : public CalcNode
{
CalcNode* left;
CalcNode* right;
public:
explicit CNModulo(CalcNode* _left, CalcNode* _right)
: CalcNode(), left(_left), right(_right)
{
}
virtual ~CNModulo()
{
delete left;
delete right;
}
virtual double evaluate() const
{
return std::fmod(left->evaluate(), right->evaluate());
}
virtual void print(std::ostream &os, unsigned int depth) const
{
os << indent(depth) << "% modulo" << std::endl;
left->print(os, depth+1);
right->print(os, depth+1);
}
};
class CNPower : public CalcNode
{
CalcNode* left;
CalcNode* right;
public:
explicit CNPower(CalcNode* _left, CalcNode* _right)
: CalcNode(), left(_left), right(_right)
{
}
virtual ~CNPower()
{
delete left;
delete right;
}
virtual double evaluate() const
{
return std::pow(left->evaluate(), right->evaluate());
}
virtual void print(std::ostream &os, unsigned int depth) const
{
os << indent(depth) << "^ power" << std::endl;
left->print(os, depth+1);
right->print(os, depth+1);
}
};
class CalcContext
{
public:
typedef std::map<std::string, double> variablemap_type;
variablemap_type variables;
std::vector<CalcNode*> expressions;
~CalcContext()
{
clearExpressions();
}
void clearExpressions()
{
for(unsigned int i = 0; i < expressions.size(); ++i)
{
delete expressions[i];
}
expressions.clear();
}
bool existsVariable(const std::string &varname) const
{
return variables.find(varname) != variables.end();
}
double getVariable(const std::string &varname) const
{
variablemap_type::const_iterator vi = variables.find(varname);
if (vi == variables.end())
throw(std::runtime_error("Unknown variable."));
else
return vi->second;
}
};
#endif