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;
public:
simple_script(const std::string& script){
parse_script(script,expr);
}
public:
void do_script(){
excute_block(expr.begin(),expr.end());
}
protected:
exp_item assign_op(exp_item b, exp_item e){
std::string key = *b++;//var
std::string asg = *b++;// =
if(*b == "function"){
b = skip_function(b,e);
return ++b;
}
exp_item ret = std::find(b,e,";");
results[key] = calculate_string(b,ret);
return ++ret;
}
exp_item test_op(exp_item b, exp_item e){
exp_item te = std::find(b,e,"]");
exp_item tb = std::find(b, te,"[");
std::string rst = calculate_string(tb,te);
tb = get_block_range(++te,e);
if(!rst.empty() && string_cast<int>(rst)){
excute_block(++te,tb);
}
return ++tb;
}
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){
exp_item b = std::find(expr.begin(),expr.end(),function_name);
exp_item e = expr.end();
if(b == e){
return "";
}
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){
for(; b != e;){
std::string key = *b;
if(key == "if"){
b = test_op(b,e);
}else{
b = assign_op(b,e);
}
}
}
exp_item get_block_range(exp_item b ,exp_item e){
int tag = 1;
for(++b; b != e; ++b){
if("{" == *b) ++tag;
if("}" == *b) --tag;
if(0 == tag) 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){
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 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 = results.top();
results.pop();
exp_item it = std::find(b,e,">");
results.push(get_sub_result(l,b,it));
b = it;
break;
}
case '+':{
break;
}
case '-':{
results.push(sub(*(++b)));
break;
}
case '*':{
std::string l = results.top();
results.pop();
results.push(mut(l,*(++b)));
break;
}
case '/':{
std::string l = results.top();
results.pop();
results.push(div(l,*(++b)));
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:
/*
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 '/':{
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+5+6+7+8+9+10*10;\n"
"a= 1*3-4;\n"
"c=a+d;\n"
"test = function<x,y>{\n"
"result = 0;\n"
"if[c]{\n"
"result = 1;\n"
"}"
"test = result + x + y;\n"
"}\n"
"e = test<10,8>;\n"
"f = test<23,32>;";
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;
}