Finished balloon language

This commit is contained in:
Valk Richard Li
2019-11-14 15:20:48 +08:00
committed by GitHub
parent 53f275ce41
commit ac3b5719bc
5 changed files with 236 additions and 47 deletions
+163 -42
View File
@@ -5,6 +5,7 @@
int exit_type=0; int exit_type=0;
std::stack<var> ret_stack;// for function ret use std::stack<var> ret_stack;// for function ret use
std::list<var> parameter;// for function call use
var abstract_syntax_tree::calculation() var abstract_syntax_tree::calculation()
{ {
@@ -39,7 +40,7 @@ var abstract_syntax_tree::calculation()
} }
else if(this->type==__function) else if(this->type==__function)
{ {
temp.set_type(__function); temp.set_type(__var_function);
temp.set_function(*this); temp.set_function(*this);
return temp; return temp;
} }
@@ -384,7 +385,9 @@ var abstract_syntax_tree::calculation()
else else
{ {
exit_type=__error_value_type; exit_type=__error_value_type;
std::cout<<">>[Runtime-error] line "<<line<<": error type occurred when doing calculation."<<std::endl; std::cout<<">>[Runtime-error] line "<<line<<": error type \'";
print_detail_token(this->type);
std::cout<<"\' occurred when doing calculation."<<std::endl;
} }
return temp; return temp;
} }
@@ -451,7 +454,12 @@ var abstract_syntax_tree::call_identifier()
} }
} }
else if(i->type==__call_function && temp.get_type()==__var_function) else if(i->type==__call_function && temp.get_type()==__var_function)
{
parameter.clear();
for(std::list<abstract_syntax_tree>::iterator j=i->children.begin();j!=i->children.end();++j)
parameter.push_back(j->calculation());
temp=temp.get_function().run_func(); temp=temp.get_function().run_func();
}
else else
{ {
exit_type=__error_value_type; exit_type=__error_value_type;
@@ -460,6 +468,7 @@ var abstract_syntax_tree::call_identifier()
std::cout<<": incorrect type \'"; std::cout<<": incorrect type \'";
print_scalar(temp.get_type()); print_scalar(temp.get_type());
std::cout<<"\'."<<std::endl; std::cout<<"\'."<<std::endl;
break;
} }
} }
} }
@@ -491,44 +500,132 @@ var abstract_syntax_tree::hash_generation()
return new_var; return new_var;
} }
var abstract_syntax_tree::get_value() var* abstract_syntax_tree::get_var_addr()
{ {
var temp; var* addr=&error_var;
temp.set_type(type); if(scope.search_var(name))
if(type==__id) addr=scope.get_addr(name);
temp=call_identifier();
else if(type==__number)
temp.set_number(number);
else if(type==__string)
temp.set_string(str);
else if(type==__array)
{
var new_var;
for(std::list<abstract_syntax_tree>::iterator i=children.begin();i!=children.end();++i)
{
new_var=i->get_value();
temp.append_array(new_var);
}
}
else if(type==__hash)
{
var new_var;
for(std::list<abstract_syntax_tree>::iterator i=children.begin();i!=children.end();++i)
{
new_var=i->children.begin()->get_value();
new_var.set_name(i->name);
temp.append_array(new_var);
}
}
else if(type==__function)
temp.set_function(*this);
else else
{ {
std::cout<<">>[Runtime-error] line "<<line<<": incorrect value."<<std::endl; std::cout<<">>[Runtime-error] line "<<line<<": cannot find a var named \'"<<name<<"\'."<<std::endl;
exit_type=__find_var_failure;
return addr;
}
if(!children.empty())
{
for(std::list<abstract_syntax_tree>::iterator i=children.begin();i!=children.end();++i)
{
if(i->type==__call_array && addr->get_type()==__var_array)
{
var place=i->children.front().calculation();
if(place.get_type()==__var_number)
addr=addr->get_array_member_addr((int)place.get_number());
else
{
exit_type=__error_value_type;
std::cout<<">>[Runtime-error] line "<<line<<": ";
print_detail_token(i->type);
std::cout<<": incorrect type \'";
print_scalar(addr->get_type());
std::cout<<"\'."<<std::endl;
break;
}
}
else if(i->type==__call_hash && addr->get_type()==__var_hash)
{
addr=addr->get_hash_member_addr(i->name);
if(addr->get_type()==__null_type)
{
exit_type=__get_value_failure; exit_type=__get_value_failure;
std::cout<<">>[Runtime-error] line "<<line<<": cannot find a hash-member named \'"<<i->name<<"\'."<<std::endl;
break;
} }
return temp;
} }
else if(i->type==__call_function && addr->get_type()==__var_function)
{
exit_type=__error_value_type;
std::cout<<">>[Runtime-error] line "<<line<<": function-returned value cannot be assigned."<<std::endl;
break;
}
else
{
exit_type=__error_value_type;
std::cout<<">>[Runtime-error] line "<<line<<": ";
print_detail_token(i->type);
std::cout<<": incorrect type \'";
print_scalar(addr->get_type());
std::cout<<"\'."<<std::endl;
break;
}
}
}
return addr;
}
var abstract_syntax_tree::assignment()
{
var ret,temp;
abstract_syntax_tree id=children.front();
abstract_syntax_tree value=children.back();
var* addr=id.get_var_addr();
if(value.type==__equal || value.type==__add_equal || value.type==__sub_equal || value.type==__mul_equal || value.type==__div_equal || value.type==__link_equal)
temp=value.assignment();
else
temp=value.calculation();
if(type==__equal)
{
std::string tname=addr->get_name();
*addr=temp;
addr->set_name(tname);
}
else if(type==__add_equal || type==__sub_equal || type==__mul_equal || type==__div_equal)
{
if(addr->get_type()==__var_number && temp.get_type()==__var_number)
{
switch(type)
{
case __add_equal:addr->set_number(addr->get_number()+temp.get_number());break;
case __sub_equal:addr->set_number(addr->get_number()-temp.get_number());break;
case __mul_equal:addr->set_number(addr->get_number()*temp.get_number());break;
case __div_equal:addr->set_number(addr->get_number()/temp.get_number());break;
}
if(std::isnan(addr->get_number()) || std::isinf(addr->get_number()))
{
exit_type=__sigfpe_arithmetic_exception;
std::cout<<">>[Runtime-error] line "<<line<<": get number \'NaN\' or \'Inf\'."<<std::endl;
}
}
else
{
exit_type=__error_value_type;
std::cout<<">>[Runtime-error] line "<<line<<": incorrect type \'";
print_scalar(addr->get_type());
std::cout<<"\' and \'";
print_scalar(temp.get_type());
std::cout<<"\' but this operator ";
print_detail_token(type);
std::cout<<" must use \'number\' and \'number\'."<<std::endl;
}
}
else if(type==__link_equal)
{
if(addr->get_type()==__var_string && temp.get_type()==__string)
addr->set_string(addr->get_string()+temp.get_string());
else
{
exit_type=__error_value_type;
std::cout<<">>[Runtime-error] line "<<line<<": incorrect type \'";
print_scalar(addr->get_type());
std::cout<<"\' and \'";
print_scalar(temp.get_type());
std::cout<<"\' but this operator ~ must use \'string\' and \'string\'."<<std::endl;
}
}
ret=*addr;
return ret;
}
void abstract_syntax_tree::run_root() void abstract_syntax_tree::run_root()
{ {
while(!ret_stack.empty())ret_stack.pop(); while(!ret_stack.empty())ret_stack.pop();
@@ -560,9 +657,7 @@ void abstract_syntax_tree::run_root()
} }
} }
else if(i->type==__equal || i->type==__add_equal || i->type==__sub_equal || i->type==__mul_equal || i->type==__div_equal || i->type==__link_equal) else if(i->type==__equal || i->type==__add_equal || i->type==__sub_equal || i->type==__mul_equal || i->type==__div_equal || i->type==__link_equal)
{ i->assignment();
;
}
else if(i->type==__add_operator || i->type==__sub_operator || i->type==__mul_operator || i->type==__div_operator || i->type==__link_operator || i->type==__or_operator || i->type==__and_operator || i->type==__nor_operator) else if(i->type==__add_operator || i->type==__sub_operator || i->type==__mul_operator || i->type==__div_operator || i->type==__link_operator || i->type==__or_operator || i->type==__and_operator || i->type==__nor_operator)
{ {
var t=i->calculation(); var t=i->calculation();
@@ -599,7 +694,7 @@ void abstract_syntax_tree::run_root()
break; break;
} }
end_time=time(NULL); end_time=time(NULL);
std::cout<<"--------------------------------------------------------------------------------------"<<std::endl; std::cout<<"------------------------------------------------------------------------------"<<std::endl;
std::cout<<">>[Runtime] process exited after "<<end_time-beg_time<<" sec(s) with returned state \'"; std::cout<<">>[Runtime] process exited after "<<end_time-beg_time<<" sec(s) with returned state \'";
print_exit_type(exit_type); print_exit_type(exit_type);
std::cout<<"\'."<<std::endl; std::cout<<"\'."<<std::endl;
@@ -657,11 +752,39 @@ var abstract_syntax_tree::run_func()
var ret; var ret;
scope.add_new_block_scope(); scope.add_new_block_scope();
scope.add_new_local_scope(); scope.add_new_local_scope();
abstract_syntax_tree para=children.front();
abstract_syntax_tree blk=children.back();
std::list<abstract_syntax_tree>::iterator para_name=para.children.begin();
std::list<var>::iterator para_value=parameter.begin();
for(;para_name!=para.children.end();++para_name,++para_value)
{
if(para_value==parameter.end() && para_name!=para.children.end())
{
exit_type=__lack_parameter;
std::cout<<">>[Runtime-error] line "<<line<<": lack parameter(s)."<<std::endl;
break;
}
var new_var;
new_var=*para_value;
new_var.set_name(para_name->name);
scope.add_new_var(new_var);
}
if(exit_type==__process_exited_successfully)
{
int _t=blk.run_block();
if(_t!=__return)
ret_stack.push(error_var);
}
else
ret_stack.push(error_var);
//get return //get return
scope.pop_last_block_scope(); scope.pop_last_block_scope();
ret=ret_stack.top(); ret=ret_stack.top();
ret_stack.pop(); ret_stack.pop();
return ret; return ret;
} }
@@ -702,9 +825,7 @@ int abstract_syntax_tree::run_block()
std::cout<<t.get_string()<<std::endl; std::cout<<t.get_string()<<std::endl;
} }
else if(i->type==__equal || i->type==__add_equal || i->type==__sub_equal || i->type==__mul_equal || i->type==__div_equal || i->type==__link_equal) else if(i->type==__equal || i->type==__add_equal || i->type==__sub_equal || i->type==__mul_equal || i->type==__div_equal || i->type==__link_equal)
{ i->assignment();
;
}
else if(i->type==__add_operator || i->type==__sub_operator || i->type==__mul_operator || i->type==__div_operator || i->type==__link_operator || i->type==__or_operator || i->type==__and_operator || i->type==__nor_operator) else if(i->type==__add_operator || i->type==__sub_operator || i->type==__mul_operator || i->type==__div_operator || i->type==__link_operator || i->type==__or_operator || i->type==__and_operator || i->type==__nor_operator)
{ {
var t=i->calculation(); var t=i->calculation();
@@ -742,7 +863,7 @@ int abstract_syntax_tree::run_block()
var temp; var temp;
temp.set_type(__null_type); temp.set_type(__null_type);
if(!(i->children.empty())) if(!(i->children.empty()))
temp=i->calculation(); temp=i->children.front().calculation();
ret_stack.push(temp); ret_stack.push(temp);
return __return; return __return;
} }
+2 -1
View File
@@ -203,7 +203,8 @@ class abstract_syntax_tree
var call_identifier(); var call_identifier();
var array_generation(); var array_generation();
var hash_generation(); var hash_generation();
var get_value(); var* get_var_addr();
var assignment();
void run_root(); void run_root();
int run_loop(); int run_loop();
int run_ifelse(); int run_ifelse();
+31
View File
@@ -72,6 +72,37 @@ class balloon_scope
} }
return error_var; return error_var;
} }
var* get_addr(std::string name)
{
var* addr=NULL;
if(!scope_list.empty())
{
std::list<std::list<var> >::iterator i=scope_list.back().end();
--i;
// get the last scope block(std::list<std::list<var> >)
for(;;--i)
{
for(std::list<var>::iterator j=i->begin();j!=i->end();++j)
if(j->get_name()==name)
{
addr=&(*j);
return addr;
}
if(i==scope_list.back().begin())
break;
}
}
if(!global.empty())
{
for(std::list<var>::iterator i=global.begin();i!=global.end();++i)
if(i->get_name()==name)
{
addr=&(*i);
return addr;
}
}
return &error_var;
}
void add_new_block_scope() void add_new_block_scope()
{ {
std::list<std::list<var> > new_list; std::list<std::list<var> > new_list;
+5 -3
View File
@@ -148,7 +148,8 @@ enum runtime_error_type
__error_command_use, __error_command_use,
__sigfpe_arithmetic_exception, __sigfpe_arithmetic_exception,
__sigsegv_segmentation_error, __sigsegv_segmentation_error,
__terminal_interrupt __terminal_interrupt,
__lack_parameter,
}; };
void print_exit_type(int type) void print_exit_type(int type)
@@ -162,9 +163,10 @@ void print_exit_type(int type)
case __find_var_failure: context="find_var_failure";break; case __find_var_failure: context="find_var_failure";break;
case __error_value_type: context="value_type_error";break; case __error_value_type: context="value_type_error";break;
case __error_command_use: context="command_use_error(continue/break/return)";break; case __error_command_use: context="command_use_error(continue/break/return)";break;
case __sigfpe_arithmetic_exception: context="SIGFPE";break; case __sigfpe_arithmetic_exception: context="SIGFPE_arithmetic_exception";break;
case __sigsegv_segmentation_error: context="SIGSEGV";break; case __sigsegv_segmentation_error: context="SIGSEGV_segmentation_error";break;
case __terminal_interrupt: context="interrupt";break; case __terminal_interrupt: context="interrupt";break;
case __lack_parameter: context="lack_parameter(s)";break;
default: context="unknown";break; default: context="unknown";break;
} }
std::cout<<context; std::cout<<context;
+34
View File
@@ -87,7 +87,9 @@ class var
double get_number(); double get_number();
std::string get_string(); std::string get_string();
var& get_array_member(int); var& get_array_member(int);
var* get_array_member_addr(int);
var& get_hash_member(std::string); var& get_hash_member(std::string);
var* get_hash_member_addr(std::string);
abstract_syntax_tree& get_function(); abstract_syntax_tree& get_function();
}; };
@@ -170,6 +172,25 @@ var& var::get_array_member(int _place)
return error_var; return error_var;
} }
var* var::get_array_member_addr(int _place)
{
var* addr=NULL;
if(balloon_array.empty())
{
std::cout<<">>[Runtime-error] overflow when searching member "<<_place<<" but the max size of array \'"<<name<<"\' is 0."<<std::endl;
return &error_var;
}
int cnt=0;
for(std::list<var>::iterator i=balloon_array.begin();i!=balloon_array.end();++i,++cnt)
if(cnt==_place)
{
addr=&(*i);
return addr;
}
std::cout<<">>[Runtime-error] overflow when searching member "<<_place<<" but the max size of array \'"<<name<<"\' is "<<cnt<<"(this means 0-"<<cnt-1<<")."<<std::endl;
return &error_var;
}
var& var::get_hash_member(std::string _name) var& var::get_hash_member(std::string _name)
{ {
for(std::list<var>::iterator i=balloon_hash.begin();i!=balloon_hash.end();++i) for(std::list<var>::iterator i=balloon_hash.begin();i!=balloon_hash.end();++i)
@@ -179,6 +200,19 @@ var& var::get_hash_member(std::string _name)
return error_var; return error_var;
} }
var* var::get_hash_member_addr(std::string _name)
{
var* addr=NULL;
for(std::list<var>::iterator i=balloon_hash.begin();i!=balloon_hash.end();++i)
if(i->name==_name)
{
addr=&(*i);
return addr;
}
std::cout<<">>[Runtime-error] hash \'"<<name<<"\' does not have a member named \'"<<_name<<"\'"<<std::endl;
return &error_var;
}
abstract_syntax_tree& var::get_function() abstract_syntax_tree& var::get_function()
{ {
return function; return function;