00001 
00004 #ifndef EXPRESSION_H
00005 #define EXPRESSION_H
00006 
00007 #include <map>
00008 #include <vector>
00009 #include <ostream>
00010 #include <stdexcept>
00011 #include <cmath>
00012 
00015 class CalcNode
00016 {
00017 public:
00020     virtual ~CalcNode()
00021     {
00022     }
00023 
00026     virtual double      evaluate() const = 0;
00027 
00030     virtual void        print(std::ostream &os, unsigned int depth=0) const = 0;
00031 
00033     static inline std::string indent(unsigned int d)
00034     {
00035         return std::string(d * 2, ' ');
00036     }
00037 };
00038 
00040 class CNConstant : public CalcNode
00041 {
00043     double      value;
00044     
00045 public:
00047     explicit CNConstant(double _value)
00048         : CalcNode(), value(_value)
00049     {
00050     }
00051 
00052     virtual double evaluate() const
00053     {
00054         return value;
00055     }
00056 
00057     virtual void print(std::ostream &os, unsigned int depth) const
00058     {
00059         os << indent(depth) << value << std::endl;
00060     }
00061 };
00062 
00064 class CNNegate : public CalcNode
00065 {
00067     CalcNode*   node;
00068 
00069 public:
00070     explicit CNNegate(CalcNode* _node)
00071         : CalcNode(), node(_node)
00072     {
00073     }
00074 
00075     virtual ~CNNegate()
00076     {
00077         delete node;
00078     }
00079 
00080     virtual double evaluate() const
00081     {
00082         return - node->evaluate();
00083     }
00084 
00085     virtual void print(std::ostream &os, unsigned int depth) const
00086     {
00087         os << indent(depth) << "- negate" << std::endl;
00088         node->print(os, depth+1);
00089     }
00090 };
00091 
00093 class CNAdd : public CalcNode
00094 {
00096     CalcNode*   left;
00097 
00099     CalcNode*   right;
00100     
00101 public:
00102     explicit CNAdd(CalcNode* _left, CalcNode* _right)
00103         : CalcNode(), left(_left), right(_right)
00104     {
00105     }
00106 
00107     virtual ~CNAdd()
00108     {
00109         delete left;
00110         delete right;
00111     }
00112 
00113     virtual double evaluate() const
00114     {
00115         return left->evaluate() + right->evaluate();
00116     }
00117 
00118     virtual void print(std::ostream &os, unsigned int depth) const
00119     {
00120         os << indent(depth) << "+ add" << std::endl;
00121         left->print(os, depth+1);
00122         right->print(os, depth+1);
00123     }
00124 };
00125 
00127 class CNSubtract : public CalcNode
00128 {
00130     CalcNode*   left;
00131 
00133     CalcNode*   right;
00134     
00135 public:
00136     explicit CNSubtract(CalcNode* _left, CalcNode* _right)
00137         : CalcNode(), left(_left), right(_right)
00138     {
00139     }
00140 
00141     virtual ~CNSubtract()
00142     {
00143         delete left;
00144         delete right;
00145     }
00146 
00147     virtual double evaluate() const
00148     {
00149         return left->evaluate() - right->evaluate();
00150     }
00151 
00152     virtual void print(std::ostream &os, unsigned int depth) const
00153     {
00154         os << indent(depth) << "- subtract" << std::endl;
00155         left->print(os, depth+1);
00156         right->print(os, depth+1);
00157     }
00158 };
00159 
00161 class CNMultiply : public CalcNode
00162 {
00164     CalcNode*   left;
00165 
00167     CalcNode*   right;
00168     
00169 public:
00170     explicit CNMultiply(CalcNode* _left, CalcNode* _right)
00171         : CalcNode(), left(_left), right(_right)
00172     {
00173     }
00174 
00175     virtual ~CNMultiply()
00176     {
00177         delete left;
00178         delete right;
00179     }
00180 
00181     virtual double evaluate() const
00182     {
00183         return left->evaluate() * right->evaluate();
00184     }
00185 
00186     virtual void print(std::ostream &os, unsigned int depth) const
00187     {
00188         os << indent(depth) << "* multiply" << std::endl;
00189         left->print(os, depth+1);
00190         right->print(os, depth+1);
00191     }
00192 };
00193 
00195 class CNDivide : public CalcNode
00196 {
00198     CalcNode*   left;
00199 
00201     CalcNode*   right;
00202     
00203 public:
00204     explicit CNDivide(CalcNode* _left, CalcNode* _right)
00205         : CalcNode(), left(_left), right(_right)
00206     {
00207     }
00208 
00209     virtual ~CNDivide()
00210     {
00211         delete left;
00212         delete right;
00213     }
00214 
00215     virtual double evaluate() const
00216     {
00217         return left->evaluate() / right->evaluate();
00218     }
00219 
00220     virtual void print(std::ostream &os, unsigned int depth) const
00221     {
00222         os << indent(depth) << "/ divide" << std::endl;
00223         left->print(os, depth+1);
00224         right->print(os, depth+1);
00225     }
00226 };
00227 
00230 class CNModulo : public CalcNode
00231 {
00233     CalcNode*   left;
00234 
00236     CalcNode*   right;
00237     
00238 public:
00239     explicit CNModulo(CalcNode* _left, CalcNode* _right)
00240         : CalcNode(), left(_left), right(_right)
00241     {
00242     }
00243 
00244     virtual ~CNModulo()
00245     {
00246         delete left;
00247         delete right;
00248     }
00249 
00250     virtual double evaluate() const
00251     {
00252         return std::fmod(left->evaluate(), right->evaluate());
00253     }
00254 
00255     virtual void print(std::ostream &os, unsigned int depth) const
00256     {
00257         os << indent(depth) << "% modulo" << std::endl;
00258         left->print(os, depth+1);
00259         right->print(os, depth+1);
00260     }
00261 };
00262 
00264 class CNPower : public CalcNode
00265 {
00267     CalcNode*   left;
00268 
00270     CalcNode*   right;
00271     
00272 public:
00273     explicit CNPower(CalcNode* _left, CalcNode* _right)
00274         : CalcNode(), left(_left), right(_right)
00275     {
00276     }
00277 
00278     virtual ~CNPower()
00279     {
00280         delete left;
00281         delete right;
00282     }
00283 
00284     virtual double evaluate() const
00285     {
00286         return std::pow(left->evaluate(), right->evaluate());
00287     }
00288 
00289     virtual void print(std::ostream &os, unsigned int depth) const
00290     {
00291         os << indent(depth) << "^ power" << std::endl;
00292         left->print(os, depth+1);
00293         right->print(os, depth+1);
00294     }
00295 };
00296 
00300 class CalcContext
00301 {
00302 public:
00303 
00305     typedef std::map<std::string, double> variablemap_type;
00306 
00308     variablemap_type            variables;
00309 
00312     std::vector<CalcNode*>      expressions;
00313 
00315     ~CalcContext()
00316     {
00317         clearExpressions();
00318     }
00319 
00321     void        clearExpressions()
00322     {
00323         for(unsigned int i = 0; i < expressions.size(); ++i)
00324         {
00325             delete expressions[i];
00326         }
00327         expressions.clear();
00328     }
00329 
00331     bool        existsVariable(const std::string &varname) const
00332     {
00333         return variables.find(varname) != variables.end();
00334     }
00335     
00338     double      getVariable(const std::string &varname) const
00339     {
00340         variablemap_type::const_iterator vi = variables.find(varname);
00341         if (vi == variables.end())
00342             throw(std::runtime_error("Unknown variable."));
00343         else
00344             return vi->second;
00345     }
00346 };
00347 
00348 #endif // EXPRESSION_H