diff --git a/nasal_parse.h b/nasal_parse.h index 8600da9..f5f4128 100644 --- a/nasal_parse.h +++ b/nasal_parse.h @@ -802,26 +802,55 @@ nasal_ast nasal_parse::additive_expr() else die(error_line,"expected calculation"); // pre-calculation - if(tmp.get_type()!=ast_link && tmp.get_children()[0].get_type()==ast_number && tmp.get_children()[1].get_type()==ast_number) + if(tmp.get_type()!=ast_link) { - double num1=tmp.get_children()[0].get_num(); - double num2=tmp.get_children()[1].get_num(); - double num; - if(tmp.get_type()==ast_add) - num=num1+num2; - else if(tmp.get_type()==ast_sub) - num=num1-num2; + int type1=tmp.get_children()[0].get_type(); + int type2=tmp.get_children()[1].get_type(); + double num1,num2,num; + if(type1==ast_number && type2==ast_number) + { + num1=tmp.get_children()[0].get_num(); + num2=tmp.get_children()[1].get_num(); + } + else if(type1==ast_string && type2==ast_number) + { + std::string str=tmp.get_children()[0].get_str(); + num1=trans_string_to_number(str); + num2=tmp.get_children()[1].get_num(); + if(std::isnan(num1)) + die(tmp.get_children()[0].get_line(),"plus/minus a string: "+str); + } + else if(type1==ast_number && type2==ast_string) + { + std::string str=tmp.get_children()[1].get_str(); + num1=tmp.get_children()[0].get_num(); + num2=trans_string_to_number(str); + if(std::isnan(num2)) + die(tmp.get_children()[1].get_line(),"plus/minus a string: "+str); + } + else if(type1==ast_string && type2==ast_string) + { + std::string str1=tmp.get_children()[0].get_str(); + std::string str2=tmp.get_children()[1].get_str(); + num1=trans_string_to_number(str1); + num2=trans_string_to_number(str2); + if(std::isnan(num1)) + die(tmp.get_children()[0].get_line(),"plus/minus a string: "+str1); + if(std::isnan(num2)) + die(tmp.get_children()[1].get_line(),"plus/minus a string: "+str2); + } + num=(tmp.get_type()==ast_add? num1+num2:num1-num2); tmp.set_type(ast_number); tmp.set_num(num); tmp.get_children().clear(); } - else if(tmp.get_type()==ast_link) + else { int type1=tmp.get_children()[0].get_type(); int type2=tmp.get_children()[1].get_type(); + std::string s1,s2; if((type1==ast_number || type1==ast_string) && (type2==ast_number || type2==ast_string)) { - std::string s1,s2; if(type1==ast_number) s1=trans_number_to_string(tmp.get_children()[0].get_num()); else @@ -830,11 +859,17 @@ nasal_ast nasal_parse::additive_expr() s2=trans_number_to_string(tmp.get_children()[1].get_num()); else s2=tmp.get_children()[1].get_str(); - s1+=s2; - tmp.set_type(ast_string); - tmp.set_str(s1); - tmp.get_children().clear(); } + else if(type1==ast_string && type2==ast_string) + { + s1=tmp.get_children()[0].get_str(); + s2=tmp.get_children()[1].get_str(); + s1+=s2; + } + s1+=s2; + tmp.set_type(ast_string); + tmp.set_str(s1); + tmp.get_children().clear(); } node=tmp; ++ptr; @@ -866,15 +901,45 @@ nasal_ast nasal_parse::multive_expr() break; } // pre-calculation - if(tmp.get_children()[0].get_type()==ast_number && tmp.get_children()[1].get_type()==ast_number) + int type1=tmp.get_children()[0].get_type(); + int type2=tmp.get_children()[1].get_type(); + double num1,num2,num; + if(type1==ast_number && type2==ast_number) { - double num1=tmp.get_children()[0].get_num(); - double num2=tmp.get_children()[1].get_num(); - double num=(tmp.get_type()==ast_mult? num1*num2:num1/num2); - tmp.set_type(ast_number); - tmp.set_num(num); - tmp.get_children().clear(); + num1=tmp.get_children()[0].get_num(); + num2=tmp.get_children()[1].get_num(); } + else if(type1==ast_string && type2==ast_number) + { + std::string str=tmp.get_children()[0].get_str(); + num1=trans_string_to_number(str); + num2=tmp.get_children()[1].get_num(); + if(std::isnan(num1)) + die(tmp.get_children()[0].get_line(),"multiply a string: "+str); + } + else if(type1==ast_number && type2==ast_string) + { + std::string str=tmp.get_children()[1].get_str(); + num1=tmp.get_children()[0].get_num(); + num2=trans_string_to_number(str); + if(std::isnan(num2)) + die(tmp.get_children()[1].get_line(),"multiply a string: "+str); + } + else if(type1==ast_string && type2==ast_string) + { + std::string str1=tmp.get_children()[0].get_str(); + std::string str2=tmp.get_children()[1].get_str(); + num1=trans_string_to_number(str1); + num2=trans_string_to_number(str2); + if(std::isnan(num1)) + die(tmp.get_children()[0].get_line(),"multiply a string: "+str1); + if(std::isnan(num2)) + die(tmp.get_children()[1].get_line(),"multiply a string: "+str2); + } + num=(tmp.get_type()==ast_mult? num1*num2:num1/num2); + tmp.set_type(ast_number); + tmp.set_num(num); + tmp.get_children().clear(); node=tmp; ++ptr; } @@ -912,6 +977,37 @@ nasal_ast nasal_parse::unary() node.set_num(num); node.get_children().clear(); } + else if(node.get_children()[0].get_type()==ast_string) + { + std::string str=node.get_children()[0].get_str(); + double num=trans_string_to_number(str); + if(node.get_type()==ast_unary_sub) + { + if(std::isnan(num)) + die(node.get_line(),"cannot get negative value of this string: "+str); + else + { + node.set_type(ast_number); + node.set_num(-num); + node.get_children().clear(); + } + } + else if(node.get_type()==ast_unary_not) + { + if(std::isnan(num)) + { + node.set_type(ast_number); + node.set_num(!str.length()); + node.get_children().clear(); + } + else + { + node.set_type(ast_number); + node.set_num(num==0); + node.get_children().clear(); + } + } + } return node; } nasal_ast nasal_parse::scalar() diff --git a/nasal_runtime.h b/nasal_runtime.h index 4093828..56a46e6 100644 --- a/nasal_runtime.h +++ b/nasal_runtime.h @@ -725,7 +725,7 @@ int nasal_runtime::call_vector(nasal_ast& node,int base_value_addr,int local_sco nasal_ast& tmp=node.get_children()[0]; if(tmp.get_type()==ast_subvec) { - die(tmp.get_line(),"cannot slice string (use subvec)"); + die(tmp.get_line(),"cannot slice string (use substr)"); return -1; } int index_value_addr=calculation(tmp,local_scope_addr); @@ -1486,6 +1486,8 @@ void nasal_runtime::multi_assignment(nasal_ast& node,int local_scope_addr) die(value_node.get_line(),"size of calls and size of values do not match"); return; } + // use value_table to store values temprorarily + // so that (a,b)=(b,a) can run correctly std::vector value_table; for(int i=0;i