This commit is contained in:
Valk Richard Li 2020-03-10 23:29:42 +08:00 committed by GitHub
parent eda2f7b863
commit ab885724d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 154 additions and 84 deletions

View File

@ -47,6 +47,7 @@ int main()
std::cout<<">> [par ] turn tokens into abstract syntax tree."<<std::endl;
std::cout<<">> [ast ] check the abstract syntax tree."<<std::endl;
std::cout<<">> [run ] run code."<<std::endl;
std::cout<<">> [logo ] print logo of nasal ."<<std::endl;
std::cout<<">> [info ] print lexer,parser and ast on screen."<<std::endl;
std::cout<<">> [exit ] quit nasal interpreter."<<std::endl;
}
@ -160,6 +161,14 @@ int main()
else
std::cout<<">> [Lexer] error occurred,stop."<<std::endl;
}
else if(command=="logo")
{
std::cout<<" __ _ "<<std::endl;
std::cout<<" /\\ \\ \\__ _ ___ __ _| |"<<std::endl;
std::cout<<" / \\/ / _` / __|/ _` | |"<<std::endl;
std::cout<<" / /\\ / (_| \\__ \\ (_| | |"<<std::endl;
std::cout<<" \\_\\ \\/ \\__,_|___/\\__,_|_|"<<std::endl;
}
else if(command=="info")
{
lexer.scanner(resource.get_source());

View File

@ -21,7 +21,7 @@ class nasal_runtime
__stack_overflow,
};
int runtime_error_exit_mark;
void error_interrupt (const int);
void error_interrupt (const int,const int);
int number_generation (abstract_syntax_tree&);
int string_generation (abstract_syntax_tree&);
int vector_generation (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
@ -29,7 +29,6 @@ class nasal_runtime
int function_generation(std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
int calculation (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
int call_identifier (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
int assignment (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
void definition (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
void loop_expr (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
void conditional (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
@ -50,23 +49,23 @@ class nasal_runtime
void main_proc(abstract_syntax_tree&);
};
void nasal_runtime::error_interrupt(const int type)
void nasal_runtime::error_interrupt(const int type,const int line)
{
std::string error_head=">> [Runtime] fatal error: ";
std::cout<<">> [Runtime] line "<<line<<": ";
switch (type)
{
case __incorrect_head_of_tree:
std::cout<<error_head<<"lib hasn\'t been loaded."<<std::endl;break;
std::cout<<"lib hasn\'t been loaded."<<std::endl;break;
case __incorrect_head_of_func:
std::cout<<error_head<<"called identifier is not a function."<<std::endl;break;
std::cout<<"called identifier is not a function."<<std::endl;break;
case __not_numerable_str:
std::cout<<error_head<<"this string is not a numerable one."<<std::endl;break;
std::cout<<"this string is not a numerable one."<<std::endl;break;
case __stack_overflow:
std::cout<<error_head<<"stack overflow."<<std::endl;break;
std::cout<<"stack overflow."<<std::endl;break;
case __error_value_type:
std::cout<<error_head<<"operator gets error value type."<<std::endl;break;
std::cout<<"operator gets error value type."<<std::endl;break;
default:
std::cout<<error_head<<"unknown error."<<std::endl;break;
std::cout<<"unknown error."<<std::endl;break;
}
runtime_error_exit_mark=type;
return;
@ -192,55 +191,58 @@ int nasal_runtime::calculation(std::list<std::map<std::string,int> >& local_scop
return function_generation(local_scope,node);
else if(node_type==__id)
return call_identifier(local_scope,node);
else if(node_type==__add_operator)
else if(node_type==__add_operator || node_type==__sub_operator || node_type==__mul_operator || node_type==__div_operator)
{
// scalar_nil canot be used here
int ret_addr=-1;
int addr_1=calculation(local_scope,node.get_children().front());
int addr_2=calculation(local_scope,node.get_children().back());
int addr_1=-1;
int addr_2=-1;
if(node.get_children().size()==1)
{
// note: sub operator and nor operator may mean that this is unary calculation
addr_1=nasal_gc.gc_alloc();
nasal_gc.get_scalar(addr_1).set_type(scalar_number);
nasal_gc.get_scalar(addr_1).get_number().set_number(0);
addr_2=calculation(local_scope,node.get_children().front());
}
else
{
addr_1=calculation(local_scope,node.get_children().front());
addr_2=calculation(local_scope,node.get_children().back());
}
// check if the address is available
if(addr_1<0 || addr_2<0)
return -1;
int type_1=nasal_gc.get_scalar(addr_1).get_type();
int type_2=nasal_gc.get_scalar(addr_2).get_type();
double num_1=0;
double num_2=0;
if(type_1==scalar_number && type_2==scalar_number)
{
ret_addr=nasal_gc.gc_alloc();
double num_1=nasal_gc.get_scalar(addr_1).get_number().get_number();
double num_2=nasal_gc.get_scalar(addr_2).get_number().get_number();
nasal_gc.get_scalar(ret_addr).set_type(scalar_number);
nasal_gc.get_scalar(ret_addr).get_number().set_number(num_1+num_2);
num_1=nasal_gc.get_scalar(addr_1).get_number().get_number();
num_2=nasal_gc.get_scalar(addr_2).get_number().get_number();
}
else if(type_1==scalar_number && type_2==scalar_string)
{
double num_1=nasal_gc.get_scalar(addr_1).get_number().get_number();
num_1=nasal_gc.get_scalar(addr_1).get_number().get_number();
std::string tmp_str=nasal_gc.get_scalar(addr_2).get_string().get_string();
if(check_numerable_string(tmp_str))
{
ret_addr=nasal_gc.gc_alloc();
double num_2=trans_string_to_number(tmp_str);
nasal_gc.get_scalar(ret_addr).set_type(scalar_number);
nasal_gc.get_scalar(ret_addr).get_number().set_number(num_1+num_2);
}
num_2=trans_string_to_number(tmp_str);
else
{
error_interrupt(__not_numerable_str);
error_interrupt(__not_numerable_str,node.get_node_line());
return -1;
}
}
else if(type_1==scalar_string && type_2==scalar_number)
{
std::string tmp_str=nasal_gc.get_scalar(addr_1).get_string().get_string();
double num_2=nasal_gc.get_scalar(addr_2).get_number().get_number();
num_2=nasal_gc.get_scalar(addr_2).get_number().get_number();
if(check_numerable_string(tmp_str))
{
ret_addr=nasal_gc.gc_alloc();
double num_1=trans_string_to_number(tmp_str);
nasal_gc.get_scalar(ret_addr).set_type(scalar_number);
nasal_gc.get_scalar(ret_addr).get_number().set_number(num_1+num_2);
}
num_1=trans_string_to_number(tmp_str);
else
{
error_interrupt(__not_numerable_str);
error_interrupt(__not_numerable_str,node.get_node_line());
return -1;
}
}
@ -250,71 +252,136 @@ int nasal_runtime::calculation(std::list<std::map<std::string,int> >& local_scop
std::string tmp_str_2=nasal_gc.get_scalar(addr_2).get_string().get_string();
if(check_numerable_string(tmp_str_1) && check_numerable_string(tmp_str_2))
{
num_1=trans_string_to_number(tmp_str_1);
num_2=trans_string_to_number(tmp_str_2);
}
else
{
error_interrupt(__not_numerable_str,node.get_node_line());
return -1;
}
}
else
{
error_interrupt(__error_value_type,node.get_node_line());
return -1;
}
ret_addr=nasal_gc.gc_alloc();
double num_1=trans_string_to_number(tmp_str_1);
double num_2=trans_string_to_number(tmp_str_2);
nasal_gc.get_scalar(ret_addr).set_type(scalar_number);
nasal_gc.get_scalar(ret_addr).get_number().set_number(num_1+num_2);
}
else
switch(node_type)
{
error_interrupt(__not_numerable_str);
return -1;
}
}
else
{
error_interrupt(__error_value_type);;
return -1;
case __add_operator:nasal_gc.get_scalar(ret_addr).get_number().set_number(num_1+num_2);break;
case __sub_operator:nasal_gc.get_scalar(ret_addr).get_number().set_number(num_1-num_2);break;
case __mul_operator:nasal_gc.get_scalar(ret_addr).get_number().set_number(num_1*num_2);break;
case __div_operator:nasal_gc.get_scalar(ret_addr).get_number().set_number(num_1/num_2);break;
}
nasal_gc.reference_delete(addr_1);
nasal_gc.reference_delete(addr_2);
return ret_addr;
}
else if(node_type==__sub_operator)
else if(node_type==__link_operator)
{
// scalar_nil cannot be used here
int ret_addr=-1;
// note: sub operator maybe mean that this is unary calculation
if(node.get_children().size()==1)
{
int addr=calculation(local_scope,node.get_children().front());
if(ret_addr<0)
return -1;
int type=nasal_gc.get_scalar(addr).get_type();
if(type==scalar_number)
{
ret_addr=nasal_gc.gc_alloc();
double num=nasal_gc.get_scalar(addr).get_number().get_number();
nasal_gc.get_scalar(ret_addr).set_type(scalar_number);
nasal_gc.get_scalar(ret_addr).get_number().set_number(-num);
}
else if(type==scalar_string)
{
std::string tmp_str=nasal_gc.get_scalar(ret_addr).get_string().get_string();
if(check_numerable_string(tmp_str))
{
ret_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(ret_addr).set_type(scalar_number);
nasal_gc.get_scalar(ret_addr).get_number().set_number(-trans_string_to_number(tmp_str));
}
else
{
error_interrupt(__not_numerable_str);
return -1;
}
}
nasal_gc.reference_delete(addr);
}
else
{
int addr_1=calculation(local_scope,node.get_children().front());
int addr_2=calculation(local_scope,node.get_children().back());
// check if the address is available
if(addr_1<0 || addr_2<0)
return -1;
// unfinished
int type_1=nasal_gc.get_scalar(addr_1).get_type();
int type_2=nasal_gc.get_scalar(addr_2).get_type();
std::string str_1;
std::string str_2;
if(type_1==scalar_number && type_2==scalar_number)
{
str_1=trans_number_to_string(nasal_gc.get_scalar(addr_1).get_number().get_number());
str_2=trans_number_to_string(nasal_gc.get_scalar(addr_2).get_number().get_number());
}
else if(type_1==scalar_number && type_2==scalar_string)
{
str_1=trans_number_to_string(nasal_gc.get_scalar(addr_1).get_number().get_number());
str_2=nasal_gc.get_scalar(addr_2).get_string().get_string();
}
else if(type_1==scalar_string && type_2==scalar_number)
{
str_1=nasal_gc.get_scalar(addr_1).get_string().get_string();
str_2=trans_number_to_string(nasal_gc.get_scalar(addr_2).get_number().get_number());
}
else if(type_1==scalar_string && type_2==scalar_string)
{
str_1=nasal_gc.get_scalar(addr_1).get_string().get_string();
str_2=nasal_gc.get_scalar(addr_2).get_string().get_string();
}
else
{
error_interrupt(__error_value_type,node.get_node_line());
return -1;
}
ret_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(ret_addr).set_type(scalar_string);
nasal_gc.get_scalar(ret_addr).get_string().set_string(str_1+str_2);
nasal_gc.reference_delete(addr_1);
nasal_gc.reference_delete(addr_2);
return ret_addr;
}
else if(node_type==__cmp_equal || node_type==__cmp_not_equal || node_type==__cmp_less || node_type==__cmp_less_or_equal || node_type==__cmp_more || node_type==__cmp_more_or_equal)
{
int ret_addr=-1;
int addr_1=calculation(local_scope,node.get_children().front());
int addr_2=calculation(local_scope,node.get_children().back());
// check if the address is available
if(addr_1<0 || addr_2<0)
return -1;
int type_1=nasal_gc.get_scalar(addr_1).get_type();
int type_2=nasal_gc.get_scalar(addr_2).get_type();
// note: cmp operator change strings into numbers then making comparation
if(type_1==scalar_number && type_2==scalar_number)
{
;
}
else if(type_1==scalar_number && type_2==scalar_string)
{
;
}
else if(type_1==scalar_string && type_2==scalar_number)
{
;
}
else if(type_1==scalar_string && type_2==scalar_string)
{
;
}
else
{
error_interrupt(__error_value_type,node.get_node_line());
return -1;
}
ret_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(ret_addr).set_type(scalar_number);
//
nasal_gc.reference_delete(addr_1);
nasal_gc.reference_delete(addr_2);
return ret_addr;
}
else if(node_type==__equal)
{
;
}
else if(node_type==__add_equal || node_type==__sub_equal || node_type==__mul_equal || node_type==__div_equal || node_type==__link_equal)
{
// scalar_nil also cannot be used here
;
}
else if(node_type==__and_operator || node_type==__or_operator || node_type==__nor_operator)
{
// or will return the first value that is not null
// and will return the last value that is not null
// nor will return 0 if the value is not null
// nor will return 1 if the value is null(0,nil,'0',"0")
// if or gets all 0,or returns 0
// if and gets a 0,and returns 0
;
}
return -1;
}
int nasal_runtime::call_identifier(std::list<std::map<std::string,int> >& local_scope,abstract_syntax_tree& node)
@ -328,12 +395,6 @@ int nasal_runtime::call_identifier(std::list<std::map<std::string,int> >& local_
addr=(*iter)[tmp_id_name];
return -1;
}
int nasal_runtime::assignment(std::list<std::map<std::string,int> >& local_scope,abstract_syntax_tree& node)
{
if(local_scope.empty())
;
return -1;
}
void nasal_runtime::definition(std::list<std::map<std::string,int> >& local_scope,abstract_syntax_tree& node)
{
if(local_scope.empty())
@ -359,7 +420,7 @@ int nasal_runtime::func_proc(std::list<std::map<std::string,int> >& local_scope,
{
if(func_root.get_node_type()!=__function)
{
error_interrupt(__incorrect_head_of_func);
error_interrupt(__incorrect_head_of_func,func_root.get_node_line());
return -1;
}
std::map<std::string,int> new_scope;
@ -415,7 +476,7 @@ void nasal_runtime::main_proc(abstract_syntax_tree& root)
if(root.get_node_type()!=__root)
{
error_interrupt(__incorrect_head_of_tree);
error_interrupt(__incorrect_head_of_tree,root.get_node_line());
return;
}
for(std::list<abstract_syntax_tree>::iterator iter=root.get_children().begin();iter!=root.get_children().end();++iter)