00001 #include <stdlib.h>
00002
00003 #include <string>
00004 #include <list>
00005 #include <sstream>
00006 #include <iostream>
00007 #include <exception>
00008 #include <math.h>
00009
00010 #include "QCAD_StringFormulaEvaluator.hpp"
00011
00012 class EvaluateException: public std::exception
00013 {
00014 public:
00015 EvaluateException(std::string message) {
00016 msg = message;
00017 }
00018 ~EvaluateException() throw () {}
00019
00020 virtual const char* what() const throw() {
00021 return msg.c_str();
00022 }
00023
00024 private:
00025 std::string msg;
00026 };
00027
00028 template<typename coordType>
00029 coordType toDbl(std::string s, coordType x, coordType y, coordType z) {
00030 if(s == "x") return x;
00031 if(s == "y") return y;
00032 if(s == "z") return z;
00033 coordType t = atof(s.c_str());
00034 return t;
00035 }
00036
00037
00038 template<typename coordType>
00039 std::string toStr(coordType d) {
00040 std::ostringstream convert;
00041 convert << d;
00042 return convert.str();
00043 }
00044
00045 void printList(std::list<std::string> l) {
00046 for(std::list<std::string>::iterator it = l.begin(); it != l.end(); ++it)
00047 std::cout << "|" << *it;
00048 std::cout << "|" << std::endl;
00049 }
00050
00051
00052 template<typename coordType>
00053 coordType Evaluate(std::string strExpression, coordType x, coordType y, coordType z)
00054 {
00055 bool bDebug = false;
00056
00057
00058 std::string expr;
00059 for(std::string::iterator it = strExpression.begin(); it != strExpression.end(); ++it) {
00060 if(*it == ' ') continue;
00061 expr += *it;
00062 }
00063
00064 if(bDebug) { std::cout << "After manip: " << expr << std::endl; }
00065
00066 std::list<std::string> stack;
00067 std::string value = "";
00068
00069 for (std::size_t i = 0; i < expr.length(); i++) {
00070 if(bDebug) { std::cout << "i = " << i << ": val=" << value << ", stack="; printList(stack); }
00071 std::string s = expr.substr(i, 1);
00072
00073
00074 if (i < expr.length() - 1) {
00075 std::string op = expr.substr(i, 2);
00076 if (op == "<=" || op == ">=" || op == "==") {
00077 stack.push_front(value);
00078 value = "";
00079 stack.push_front(op);
00080 i++;
00081 continue;
00082 }
00083 }
00084
00085 char chr = s[0];
00086 if (!isdigit(chr) && !isalpha(chr) && chr != '.' && value != "") {
00087 stack.push_front(value);
00088 value = "";
00089 }
00090
00091 if (s == "(") {
00092 std::string innerExp = "";
00093 i++;
00094 int bracketCount = 0;
00095 for (; i < expr.length(); i++) {
00096 s = expr.substr(i, 1);
00097 if (s == "(") bracketCount++;
00098 if (s == ")") {
00099 if (bracketCount == 0) break;
00100 bracketCount--;
00101 }
00102 innerExp += s;
00103 }
00104 if(bracketCount != 0)
00105 throw EvaluateException("Mismatched parenthesis");
00106
00107 stack.push_front( toStr(Evaluate(innerExp,x,y,z)) );
00108 }
00109 else if (s == "+" ||
00110 s == "-" ||
00111 s == "*" ||
00112 s == "/" ||
00113 s == "<" ||
00114 s == ">" ||
00115 s == "^") {
00116 stack.push_front(s);
00117 }
00118 else if(isdigit(chr) || isalpha(chr) || chr == '.') {
00119 if(chr == '.' && value.find('.') != std::string::npos)
00120 throw EvaluateException("Invalid decimal.");
00121 value += s;
00122
00123 if (i == (expr.length() - 1))
00124 stack.push_front(value);
00125 }
00126 else {
00127 throw EvaluateException("Invalid character.");
00128 }
00129 }
00130 if(bDebug) { std::cout << "Stack at end = "; printList(stack); }
00131
00132 double result = 0;
00133 std::list<std::string>& list = stack;
00134 std::list<std::string>::reverse_iterator it, itm1, itp1, begin;
00135 begin = list.rbegin(); ++begin;
00136 for( it = begin; it != list.rend(); ++it) {
00137 if (*it == "^") {
00138 it++; itm1 = it; it--; it--; itp1 = it; it++;
00139 *it = toStr( pow(toDbl(*itp1,x,y,z),toDbl(*itm1,x,y,z)) );
00140 list.erase(it.base()); itm1++; list.erase(itm1.base());
00141 }
00142 }
00143 if(bDebug) { std::cout << "List after ^ block = "; printList(list); }
00144
00145 begin = list.rbegin(); ++begin;
00146 for( it = begin; it != list.rend(); ++it) {
00147 if (*it == "/") {
00148 it++; itm1 = it; it--; it--; itp1 = it; it++;
00149 *it = toStr( toDbl(*itp1,x,y,z) / toDbl(*itm1,x,y,z) );
00150 list.erase(it.base()); itm1++; list.erase(itm1.base());
00151 }
00152 }
00153 if(bDebug) { std::cout << "List after / block = "; printList(list); }
00154
00155 begin = list.rbegin(); ++begin;
00156 for( it = begin; it != list.rend(); ++it) {
00157 if (*it == "*") {
00158 it++; itm1 = it; it--; it--; itp1 = it; it++;
00159 *it = toStr( toDbl(*itp1,x,y,z) * toDbl(*itm1,x,y,z) );
00160 list.erase(it.base()); itm1++; list.erase(itm1.base());
00161 }
00162 }
00163 if(bDebug) { std::cout << "List after * block = "; printList(list); }
00164
00165 begin = list.rbegin();
00166 for( it = begin; it != list.rend(); ++it) {
00167 if (*it == "+") {
00168 if (it.base() == list.end()) {
00169 it++; itm1 = it; it--;
00170 *it = toStr( toDbl(*itm1,x,y,z) );
00171 itm1++; list.erase(itm1.base());
00172 }
00173 else {
00174 it++; itm1 = it; it--; it--; itp1 = it; it++;
00175 *it = toStr( toDbl(*itp1,x,y,z) + toDbl(*itm1,x,y,z) );
00176 list.erase(it.base()); itm1++; list.erase(itm1.base());
00177 }
00178 }
00179 }
00180 if(bDebug) { std::cout << "List after + block = "; printList(list); }
00181
00182 begin = list.rbegin();
00183 for( it = begin; it != list.rend(); ++it) {
00184 if (*it == "-") {
00185 if (it.base() == list.end()) {
00186 it++; itm1 = it; it--;
00187 *it = toStr( -toDbl(*itm1,x,y,z) );
00188 itm1++; list.erase(itm1.base());
00189 }
00190 else {
00191 it++; itm1 = it; it--; it--; itp1 = it; it++;
00192 *it = toStr( toDbl(*itp1,x,y,z) - toDbl(*itm1,x,y,z) );
00193 list.erase(it.base()); itm1++; list.erase(itm1.base());
00194 }
00195 }
00196 }
00197 if(bDebug) { std::cout << "List after - block = "; printList(list); }
00198
00199
00200 while (list.size() >= 3) {
00201 coordType right = toDbl(list.back(), x,y,z); list.pop_back();
00202 std::string op = list.back(); list.pop_back();
00203 coordType left = toDbl(list.back(), x,y,z); list.pop_back();
00204
00205 if (op == "<") result = (left < right) ? 1 : 0;
00206 else if (op == ">") result = (left > right) ? 1 : 0;
00207 else if (op == "<=") result = (left <= right) ? 1 : 0;
00208 else if (op == ">=") result = (left >= right) ? 1 : 0;
00209 else if (op == "==") result = (left == right) ? 1 : 0;
00210
00211 list.push_back( toStr(result) );
00212 }
00213
00214 return toDbl(list.back(),x,y,z);
00215 }
00216
00217
00218 #include "PHAL_AlbanyTraits.hpp"
00219
00220 template double Evaluate<double>(std::string, double, double, double);
00221 template FadType Evaluate<FadType>(std::string, FadType, FadType, FadType);
00222 #ifdef ALBANY_FADTYPE_NOTEQUAL_TANFADTYPE
00223 template TanFadType Evaluate<TanFadType>(std::string, TanFadType, TanFadType, TanFadType);
00224 #endif
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253