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