+_*/ 0.1

#include <map>
#include <string>
#include <iostream>
#include <sstream>
#include <stack>
#include <queue>
#include <list>


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::list<std::string> exp_list;
typedef exp_list::const_iterator exp_item;


class simple_script{
	typedef std::list<std::string> exp_list;
	typedef exp_list::const_iterator exp_item;
	typedef std::map<std::string,std::string> exp_results;
	typedef std::map<std::string,exp_list> function_list;
	function_list function_expr;
public:
	simple_script(const std::string& script){
		parse_script(script,expr);		
		splite_functions(expr,function_expr);
	}
public:
	void do_script(){
		excute_block(expr.begin(),expr.end());
	}
protected:
	exp_item assign_op(exp_item b, exp_item e,const std::string& name = ""){
		std::string key = (name.empty()) ? *b++ : name + "." + (*b++);//var 
		std::string asg = *b++;// =
		exp_item ret;
		switch(b->c_str()[0]){
		case '[':{ //for array
			++b;
			for(int i = 0; *b != "]"; ++b){
				if(*b == ",") continue;
				if(*b == "{") {
					ret = get_block_range(++b,e);
					excute_block(b,ret,key+ "@" + to_string(i++));
					b = ret;
					continue;
				}
				results[key+ "@" + to_string(i++)] = get_result(*b);
			}
			ret = ++b;
			break;
				 }
		case '{':{//for mix
			ret = get_block_range(++b,e);
			excute_block(b,ret,key);			
			++ret;//for last }
			break;
				 }
		default:{
			ret = std::find(b,e,";");
			results[key] = calculate_string(b,ret);
			break;
				}
		}		
		return ++ret;
	}
	exp_item test_op(exp_item b, exp_item e){
		exp_item te = std::find(b,e,"{");
		std::string rst = calculate_string(++b,te);
		exp_item tb = get_block_range(++te,e);	
		if(!rst.empty() && string_cast<int>(rst)){			
			excute_block(te,tb);
		}
		return ++tb;
	}
	exp_item for_op(exp_item b , exp_item e){
		exp_item test = std::find(++b,e,";");//skip (
		exp_item tmp = test;
		exp_item calc = std::find(++tmp,e,";"); // skip ; 
		tmp = calc;
		exp_item block = std::find(++tmp,e, ")"); // 
		tmp = block;++tmp;
		exp_item block_end = get_block_range(++tmp,e);
		for(assign_op(b,test);;assign_op(++tmp, block)){
			tmp = test;
			std::string rst = calculate_string(++tmp,calc);
			if(rst.empty() || 0 == string_cast<int>(rst)){
				break;
			}
			tmp = block;++tmp;
			excute_block(++tmp,block_end);
			tmp = calc;
		}
		return ++block_end;
	}
protected:
	exp_item skip_function(exp_item b, exp_item e){		
		if(b == e || *b !="function"){
			return b;
		}
		b = std::find(b,e,"{");
		return get_block_range(b,e);
	}
public:
	/*
	sub function operation
	*/
	std::string get_sub_result(const std::string& function_name,exp_item pb,exp_item pe){
		function_list::const_iterator it = function_expr.find(function_name);
		if(it == function_expr.end()){
			return "";
		}
		exp_item b = it->second.begin();
		exp_item e = it->second.end();
		b = std::find(b,e,"(");
		for(++b,++pb; b != e && pb != pe && *b != ")"; ++b,++pb){
			if(*b == ",") continue;
			results[*b] = *pb;
		}
		e = get_block_range(++b,e);
		excute_block(++b,e);
		return results[function_name];
	}
	const exp_results& get_results(void)const{
		return results;
	}
protected:
	void excute_block(exp_item b,const exp_item& e,const std::string& name = ""){
		for(; b != e;){
			std::string key = *b;			
			if(key == "if"){
				b = test_op(b,e);
			}else if (key == "for"){
				b = for_op(++b,e);
			}else{
				b = assign_op(b,e,name);
			}
		}
	}
	exp_item get_block_range(exp_item b ,exp_item e,const std::string& tag1 = "{",const std::string& tag2 = "}")const{
		int count = 1;
		for(++b; b != e; ++b){			
			if(tag1 == *b) ++count;
			if(tag2 == *b) --count;
			if(0 == count) break;
		}
		return b;
	}
protected:
	exp_list expr;
protected:
	/*
		the script no local var only glob var
	*/
	exp_results results;
	std::string get_result(const std::string& key)const{
		exp_results::const_iterator it = results.find(key);
		return (it == results.end()) ? key : (it->second);
	}

protected:
	/*
	base operation
	*/
	std::string sub(const std::string& v){
		return "-" + get_result(v);
	}
	std::string add(const std::string& l,const std::string& r){
		const std::string lv = get_result(l);
		const std::string rv = get_result(r);
		return to_string(string_cast<double>(lv) + string_cast<double>(rv));
	}
	std::string mut(const std::string& l,const std::string& r){
		const std::string lv = get_result(l);
		const std::string rv = get_result(r);
		return to_string(string_cast<double>(lv) * string_cast<double>(rv));
	}
	std::string div(const std::string& l,const std::string& r){
		const std::string lv = get_result(l);
		const std::string rv = get_result(r);
		return to_string(string_cast<double>(lv) / string_cast<double>(rv));
	}
	std::string next_result(exp_item& b , exp_item& e){
		++b;
		if(*b == "("){
			exp_item tb = ++b;
			exp_item te = get_block_range(tb,e,"(",")");
			std::string result =  calculate_string(tb,te);
			b = te;
			return result;
		}
		return get_result(*b);
	}
	std::string calculate_string(exp_item& b,exp_item& e){
		std::stack<std::string> results;
		results.push(*b);
		for(++b; b != e; ++b){
			switch(b->c_str()[0]){
			case '<':{
				std::string l = get_result(results.top());
				std::string r = next_result(b,e);
				results.pop();
				results.push(to_string<bool>(string_cast<int>(l) < string_cast<int>(r)));
				break;
					 }
			case '>':{
				std::string l = get_result(results.top());
				std::string r = next_result(b,e);
				results.pop();
				results.push(to_string<bool>(string_cast<int>(l) > string_cast<int>(r)));
				break;
					 }
			case '&':{
				std::string l = get_result(results.top());
				std::string r = next_result(b,e);
				results.pop();
				results.push(to_string(string_cast<int>(l) && string_cast<int>(r)));
				break;
					 }
			case '|':{
				std::string l = get_result(results.top());
				std::string r = next_result(b,e);
				results.pop();
				results.push(to_string(string_cast<int>(l) || string_cast<int>(r)));
				break;
					 }
			case '!':{
				std::string r = next_result(b,e);
				results.push(to_string(!string_cast<int>(r)));
				break;
					 }
			case '(':{
				std::string l = results.top();
				if(function_expr.find(l) != function_expr.end()){
					results.pop();
					exp_item be = std::find(b,e,")");
					results.push(get_sub_result(l,b,be));
					b = be;
				}else{
					results.push("(");
				}
				break;
					 }
			case ')':{
				std::string result = results.top();
				for(results.pop(); results.top() != "(";results.pop()){
					result = add(result,results.top());
				}
				results.pop();
				results.push(result);
				break;
					 }
			case '+':{
				break;
					 }
			case '-':{
				std::string r = next_result(b,e);
				results.push(sub(r));
				break;
					 }
			case '*':{
				std::string l = results.top();
				std::string r = next_result(b,e);
				results.pop();
				results.push(mut(l,r));
				break;
					 }
			case '/':{
				std::string l = results.top();
				std::string r = next_result(b,e);
				results.pop();
				results.push(div(l,r));
				break;
					 }
			default:{
				results.push(*b);
				break;
					}
			}			
		}
		if(results.size() == 1){
			return get_result(results.top());
		}
		std::string result = results.top();	
		for(results.pop();!results.empty();results.pop()){
			result = add(result,results.top());
		}
		return result;
	}
protected:
	void splite_functions(exp_list& exps,function_list& functions){
		exp_item b = exps.begin();
		exp_item e = exps.end();
		for(exp_item it = std::find(b,e,"function"); it != e; it = std::find(b,e,"function")){
			--it;--it;//skip op,get function name
			exp_item function_name = it;
			exp_list& function_exp = functions[*function_name];
			it = std::find(it,e,"{");
			exp_item ite = get_block_range(++it,e);
			function_exp.insert(function_exp.end(),function_name,++ite);
			exps.erase(function_name,ite);
		}
	}
protected:	
	/*
		parse the script
	*/
	void parse_script(const std::string& script,exp_list& results){
		std::string::const_iterator b = script.begin();
		std::string::const_iterator e = script.end();
		std::string value;
		for(; b != e ;++b){
			switch(*b){
			case '\t':
			case '\n':
			case ' ':{
				break;
					 }
			case '&':
			case '|':
			case '!':
			case '[':
			case ']':
			case '<':
			case '>':
			case '=':
			case ';':
			case '(':
			case ')':
			case ',':
			case '{':
			case '}':
			case '+':
			case '-':
			case '*':
			case '/':{					
				if(!value.empty()) results.push_back(value);
				results.push_back(op_v(*b));
				value.clear();
				break;
					 }
			default:{
				value += *b;
				break;
					}
			}
		}
	}
};





int main(int argc, char* argv[]){
	std::string script = "d=(1+2+3+4) * 10 +(5+6+7+8+9+10)*10;\n"
		"a= 2*(3-4);\n"
		"c=a+d;\n"
		"test = function(x,y){\n"
		"	result = 0;\n"
		"	if((c & d) & 0){\n"
		"		result = 1;\n"
		"	}"
		"	test = result + x + y;\n"
		"}\n"
		"for(b = 1; b < (100 - 99);b = b+ 1){\n"
		"	a = a + b;\n"
		"}\n"
		"e = test(10,8);\n"
		"f = test(23,32);\n"
		"h = [1,12,4,a,b,c,{aa=1;bb = 2;}];\n"
		"i = {ia = 1; ib = a;ic = {ic1= 1; ic2 = 2;};};\n"
		"h@0 = 2;\n"
		"i.ia = c;\n"
		"i.ib = i.ib + i.ia;\n";

	std::cout << script << std::endl;
	simple_script ss(script);
	ss.do_script();
	std::list<std::string> param;
	param.push_back("(");
	param.push_back("46");
	param.push_back(",");
	param.push_back("64");
	param.push_back(")");
	std::cout << ss.get_sub_result("test",param.begin(),param.end()) << std::endl;
	std::map<std::string,std::string> vals = ss.get_results();
	std::map<std::string,std::string>::const_iterator b = vals.begin();
	for(; b != vals.end();++b){
		std::cout << b->first << "=" << b->second << std::endl;
	}
	return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值