template<class T> T string_cast(const std::string& v){
std::stringstream ss;
ss << v;
T ret;
ss >> ret;
return ret;
}
template<class T> std::string to_string( T v){
std::stringstream ss;
ss << v;
return ss.str();
}
std::string op_v(const char c){
std::string ret;
ret += c;
return ret;
}
typedef std::string (*op_function)(const std::string&l,const std::string& r);
std::string add(const std::string& l,const std::string& r){
double v = string_cast<double>(l);
return to_string(v + string_cast<double>(r));
}
std::string sub(const std::string& l,const std::string& r){
return to_string(string_cast<double>(l) - string_cast<double>(r));
}
std::string mut(const std::string& l,const std::string& r){
return to_string(string_cast<double>(l) * string_cast<double>(r));
}
std::string div(const std::string& l,const std::string& r){
return to_string(string_cast<double>(l) / string_cast<double>(r));
}
std::string assign(const std::string& l,const std::string& r){
return l + "=" + r;
}
struct double_calc{
std::string op;
double_calc *left,*right,*parent;
public:
double_calc():
op(""),left(NULL),right(NULL),parent(this){
}
double_calc(const std::string& v):
op(v),left(NULL),right(NULL),parent(NULL){
}
public:
double_calc* insert_left_node(const std::string& v){
left = new double_calc(v);
left->parent = this;
return left;
}
double_calc* insert_rigt_node(const std::string& p,const std::string& v) {
right = new double_calc(p);
right->insert_left_node(v);
right->parent = this;
return right;
}
double_calc* insert_low_node(const std::string& p,const std::string& v){
double_calc* node = new double_calc(p);
parent->right = node;
node->left = this;
right = new double_calc(v);
parent = node;
return right;
}
public:
void midle_show(){
if(NULL != left){
left->midle_show();
}
std::cout << op ;
if(NULL != right){
right->midle_show();
}
}
};
class alg_calculater {
public:
alg_calculater():calc_tree(){
current_item = &calc_tree;
op_mapping["+"] = add;
op_mapping["-"] = sub;
op_mapping["*"] = mut;
op_mapping["/"] = div;
op_mapping["="] = assign;
}
public:
std::string do_script(const std::string& script){
std::for_each(script.begin(),script.end(),
boost::bind(&alg_calculater::create_inner_tree,this,boost::lambda::_1));
calc_tree.midle_show();
std::cout << std::endl;
return op_tree(&calc_tree);
}
protected:
std::string op_tree(const double_calc*const node){
if(NULL == node->left && NULL == node->right){
return node->op;
}
op_function fun = op_mapping[node->op];
std::string l = op_tree(node->left);
std::string r = op_tree(node->right);
return fun(l,r);
}
protected:
double_calc calc_tree;
double_calc* current_item;
void create_inner_tree(const char c) {
switch (c) {
case ' ': {
break;
}
case ';':{
current_item->right = new double_calc(value);
current_item->right->parent = current_item;
value.clear();
break;
}
case '=':
{
current_item->op = op_v(c);
current_item = current_item->insert_left_node(value);
current_item = current_item->parent;
value.clear();
break;
}
case '+':
case '-':{
if(current_item->op == "*" || current_item->op == "/"){
current_item->right = new double_calc(value);
for(current_item = current_item->parent;current_item;current_item = current_item->parent){
if(current_item->op == "+" || current_item->op == "-" || current_item->op == "="){
break;
}
}
double_calc* node = new double_calc(op_v(c));
node->left = current_item->right;
node->parent = current_item;
current_item->right = node;
current_item = node;
}else{
current_item = current_item->insert_rigt_node(op_v(c),value);
}
value.clear();
break;
}
case '/':
case '*':{
current_item = current_item->insert_rigt_node(op_v(c),value);
value.clear();
break;
}
default: {
value += c;
break;
}
}
}
protected:
std::string value;
std::map<std::string,op_function> op_mapping;
};