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