finish value search
This commit is contained in:
parent
85310cf2dd
commit
d3d162a83f
|
@ -0,0 +1,757 @@
|
|||
#ifndef __ABSTRACT_SYNTAX_TREE_CPP__
|
||||
#define __ABSTRACT_SYNTAX_TREE_CPP__
|
||||
#include "abstract_syntax_tree.h"
|
||||
|
||||
|
||||
int exit_type=0;
|
||||
std::stack<var> ret_stack;// for function ret use
|
||||
|
||||
var abstract_syntax_tree::calculation()
|
||||
{
|
||||
var temp;
|
||||
temp.set_type(__null_type);
|
||||
if(this->type==__number)
|
||||
{
|
||||
temp.set_type(__var_number);
|
||||
temp.set_number(number);
|
||||
return temp;
|
||||
}
|
||||
else if(this->type==__string)
|
||||
{
|
||||
temp.set_type(__var_string);
|
||||
temp.set_string(str);
|
||||
return temp;
|
||||
}
|
||||
else if(this->type==__id)
|
||||
{
|
||||
temp=this->call_identifier();
|
||||
return temp;
|
||||
}
|
||||
else if(this->type==__array)
|
||||
{
|
||||
temp=this->array_generation();
|
||||
return temp;
|
||||
}
|
||||
else if(this->type==__hash)
|
||||
{
|
||||
temp=this->hash_generation();
|
||||
return temp;
|
||||
}
|
||||
else if(this->type==__function)
|
||||
{
|
||||
temp.set_type(__function);
|
||||
temp.set_function(*this);
|
||||
return temp;
|
||||
}
|
||||
if(this->type==__nor_operator)
|
||||
{
|
||||
temp.set_type(__var_number);
|
||||
temp=children.front().calculation();
|
||||
if(temp.get_type()!=__var_number)
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": must use a number to use \'!\' but use \'";
|
||||
print_scalar(temp.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(temp.get_number())
|
||||
temp.set_number(0);
|
||||
else
|
||||
temp.set_number(1);
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
else if(this->type==__add_operator)
|
||||
{
|
||||
temp.set_type(__var_number);
|
||||
var left_child=children.front().calculation();
|
||||
var right_child=children.back().calculation();
|
||||
if(left_child.get_type()==__var_number && right_child.get_type()==__var_number)
|
||||
temp.set_number(left_child.get_number()+right_child.get_number());
|
||||
else
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": must use a number to use \'+\' but use \'";
|
||||
print_scalar(left_child.get_type());
|
||||
std::cout<<"\' and \'";
|
||||
print_scalar(right_child.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
}
|
||||
else if(this->type==__sub_operator)
|
||||
{
|
||||
temp.set_type(__var_number);
|
||||
std::list<abstract_syntax_tree>::iterator i=children.begin();
|
||||
++i;
|
||||
if(i==children.end())
|
||||
{
|
||||
temp=children.front().calculation();
|
||||
if(temp.get_type()==__var_number)
|
||||
temp.set_number(temp.get_number()*(-1));
|
||||
else
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": must use a number to use \'-\' but use \'";
|
||||
print_scalar(temp.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var left_child=children.front().calculation();
|
||||
var right_child=children.back().calculation();
|
||||
if(left_child.get_type()==__var_number && right_child.get_type()==__var_number)
|
||||
temp.set_number(left_child.get_number()-right_child.get_number());
|
||||
else
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": must use a number to use \'-\' but use \'";
|
||||
print_scalar(left_child.get_type());
|
||||
std::cout<<"\' and \'";
|
||||
print_scalar(right_child.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(this->type==__mul_operator)
|
||||
{
|
||||
temp.set_type(__var_number);
|
||||
var left_child=children.front().calculation();
|
||||
var right_child=children.back().calculation();
|
||||
if(left_child.get_type()==__var_number && right_child.get_type()==__var_number)
|
||||
temp.set_number(left_child.get_number()*right_child.get_number());
|
||||
else
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": must use a number to use \'*\' but use \'";
|
||||
print_scalar(left_child.get_type());
|
||||
std::cout<<"\' and \'";
|
||||
print_scalar(right_child.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
}
|
||||
else if(this->type==__div_operator)
|
||||
{
|
||||
temp.set_type(__var_number);
|
||||
var left_child=children.front().calculation();
|
||||
var right_child=children.back().calculation();
|
||||
if(left_child.get_type()==__var_number && right_child.get_type()==__var_number)
|
||||
{
|
||||
temp.set_number(left_child.get_number()/right_child.get_number());
|
||||
if(std::isnan(temp.get_number()) || std::isinf(temp.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<<": must use a number to use \'/\' but use \'";
|
||||
print_scalar(left_child.get_type());
|
||||
std::cout<<"\' and \'";
|
||||
print_scalar(right_child.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
}
|
||||
else if(this->type==__link_operator)
|
||||
{
|
||||
temp.set_type(__var_string);
|
||||
var left_child=children.front().calculation();
|
||||
var right_child=children.back().calculation();
|
||||
if(left_child.get_type()==__var_string && right_child.get_type()==__var_string)
|
||||
temp.set_string(left_child.get_string()+right_child.get_string());
|
||||
else
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": must use a string to use \'~\' but use \'";
|
||||
print_scalar(left_child.get_type());
|
||||
std::cout<<"\' and \'";
|
||||
print_scalar(right_child.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
}
|
||||
else if(this->type==__cmp_equal)
|
||||
{
|
||||
temp.set_type(__var_number);
|
||||
var left_child=children.front().calculation();
|
||||
var right_child=children.back().calculation();
|
||||
if(left_child.get_type()==right_child.get_type())
|
||||
{
|
||||
if(left_child.get_type()==__var_number)
|
||||
temp.set_number((double)(left_child.get_number()==right_child.get_number()));
|
||||
else if(left_child.get_type()==__var_string)
|
||||
temp.set_number((double)(left_child.get_string()==right_child.get_string()));
|
||||
else
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": must use number or string to use \'==\' but use \'";
|
||||
print_scalar(left_child.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": must use same type to use \'==\' but use \'";
|
||||
print_scalar(left_child.get_type());
|
||||
std::cout<<"\' and \'";
|
||||
print_scalar(right_child.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
}
|
||||
else if(this->type==__cmp_not_equal)
|
||||
{
|
||||
temp.set_type(__var_number);
|
||||
var left_child=children.front().calculation();
|
||||
var right_child=children.back().calculation();
|
||||
if(left_child.get_type()==right_child.get_type())
|
||||
{
|
||||
if(left_child.get_type()==__var_number)
|
||||
temp.set_number((double)(left_child.get_number()!=right_child.get_number()));
|
||||
else if(left_child.get_type()==__var_string)
|
||||
temp.set_number((double)(left_child.get_string()!=right_child.get_string()));
|
||||
else
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": must use number or string to use \'!=\' but use \'";
|
||||
print_scalar(left_child.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": must use same type to use \'!=\' but use \'";
|
||||
print_scalar(left_child.get_type());
|
||||
std::cout<<"\' and \'";
|
||||
print_scalar(right_child.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
}
|
||||
else if(this->type==__cmp_less)
|
||||
{
|
||||
temp.set_type(__var_number);
|
||||
var left_child=children.front().calculation();
|
||||
var right_child=children.back().calculation();
|
||||
if(left_child.get_type()==right_child.get_type())
|
||||
{
|
||||
if(left_child.get_type()==__var_number)
|
||||
temp.set_number((double)(left_child.get_number()<right_child.get_number()));
|
||||
else if(left_child.get_type()==__var_string)
|
||||
temp.set_number((double)(left_child.get_string()<right_child.get_string()));
|
||||
else
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": must use number or string to use \'<\' but use \'";
|
||||
print_scalar(left_child.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": must use same type to use \'<\' but use \'";
|
||||
print_scalar(left_child.get_type());
|
||||
std::cout<<"\' and \'";
|
||||
print_scalar(right_child.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
}
|
||||
else if(this->type==__cmp_more)
|
||||
{
|
||||
temp.set_type(__var_number);
|
||||
var left_child=children.front().calculation();
|
||||
var right_child=children.back().calculation();
|
||||
if(left_child.get_type()==right_child.get_type())
|
||||
{
|
||||
if(left_child.get_type()==__var_number)
|
||||
temp.set_number((double)(left_child.get_number()>right_child.get_number()));
|
||||
else if(left_child.get_type()==__var_string)
|
||||
temp.set_number((double)(left_child.get_string()>right_child.get_string()));
|
||||
else
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": must use number or string to use \'>\' but use \'";
|
||||
print_scalar(left_child.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": must use same type to use \'>\' but use \'";
|
||||
print_scalar(left_child.get_type());
|
||||
std::cout<<"\' and \'";
|
||||
print_scalar(right_child.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
}
|
||||
else if(this->type==__cmp_less_or_equal)
|
||||
{
|
||||
temp.set_type(__var_number);
|
||||
var left_child=children.front().calculation();
|
||||
var right_child=children.back().calculation();
|
||||
if(left_child.get_type()==right_child.get_type())
|
||||
{
|
||||
if(left_child.get_type()==__var_number)
|
||||
temp.set_number((double)(left_child.get_number()<=right_child.get_number()));
|
||||
else if(left_child.get_type()==__var_string)
|
||||
temp.set_number((double)(left_child.get_string()<=right_child.get_string()));
|
||||
else
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": must use number or string to use \'<=\' but use \'";
|
||||
print_scalar(left_child.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": must use same type to use \'<=\' but use \'";
|
||||
print_scalar(left_child.get_type());
|
||||
std::cout<<"\' and \'";
|
||||
print_scalar(right_child.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
}
|
||||
else if(this->type==__cmp_more_or_equal)
|
||||
{
|
||||
temp.set_type(__var_number);
|
||||
var left_child=children.front().calculation();
|
||||
var right_child=children.back().calculation();
|
||||
if(left_child.get_type()==right_child.get_type())
|
||||
{
|
||||
if(left_child.get_type()==__var_number)
|
||||
temp.set_number((double)(left_child.get_number()>=right_child.get_number()));
|
||||
else if(left_child.get_type()==__var_string)
|
||||
temp.set_number((double)(left_child.get_string()>=right_child.get_string()));
|
||||
else
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": must use number or string to use \'>=\' but use \'";
|
||||
print_scalar(left_child.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": must use same type to use \'>=\' but use \'";
|
||||
print_scalar(left_child.get_type());
|
||||
std::cout<<"\' and \'";
|
||||
print_scalar(right_child.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
}
|
||||
else if(this->type==__or_operator)
|
||||
{
|
||||
temp.set_type(__var_number);
|
||||
var left_child=children.front().calculation();
|
||||
var right_child=children.back().calculation();
|
||||
if(left_child.get_type()==__var_number && right_child.get_type()==__var_number)
|
||||
temp.set_number((double)(left_child.get_number() || right_child.get_number()));
|
||||
else
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": must use same type to use \'or\' but use \'";
|
||||
print_scalar(left_child.get_type());
|
||||
std::cout<<"\' and \'";
|
||||
print_scalar(right_child.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
}
|
||||
else if(this->type==__and_operator)
|
||||
{
|
||||
temp.set_type(__var_number);
|
||||
var left_child=children.front().calculation();
|
||||
var right_child=children.back().calculation();
|
||||
if(left_child.get_type()==__var_number && right_child.get_type()==__var_number)
|
||||
temp.set_number((double)(left_child.get_number() && right_child.get_number()));
|
||||
else
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": must use same type to use \'and\' but use \'";
|
||||
print_scalar(left_child.get_type());
|
||||
std::cout<<"\' and \'";
|
||||
print_scalar(right_child.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": error type occurred when doing calculation."<<std::endl;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
bool abstract_syntax_tree::condition_check()
|
||||
{
|
||||
bool ret=false;
|
||||
var temp=calculation();
|
||||
if(temp.get_type()==__var_number)
|
||||
{
|
||||
if(temp.get_number())
|
||||
ret=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": must use a number to make a choice but use \'";
|
||||
print_scalar(temp.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
var abstract_syntax_tree::call_identifier()
|
||||
{
|
||||
var temp;
|
||||
temp.set_type(__null_type);
|
||||
if(scope.search_var(name))
|
||||
temp=scope.get_var(name);
|
||||
else
|
||||
{
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": cannot find a var named \'"<<name<<"\'."<<std::endl;
|
||||
exit_type=__find_var_failure;
|
||||
return temp;
|
||||
}
|
||||
if(!children.empty())
|
||||
{
|
||||
for(std::list<abstract_syntax_tree>::iterator i=children.begin();i!=children.end();++i)
|
||||
{
|
||||
if(i->type==__call_array && temp.get_type()==__var_array)
|
||||
{
|
||||
var place=i->children.front().calculation();
|
||||
if(place.get_type()==__var_number)
|
||||
temp=temp.get_array_member((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(temp.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(i->type==__call_hash && temp.get_type()==__var_hash)
|
||||
{
|
||||
temp=temp.get_hash_member(i->name);
|
||||
if(temp.get_type()==__null_type)
|
||||
{
|
||||
exit_type=__get_value_failure;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": cannot find a hash-member named \'"<<i->name<<"\'."<<std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(i->type==__call_function && temp.get_type()==__var_function)
|
||||
temp=temp.get_function().run_func();
|
||||
else
|
||||
{
|
||||
exit_type=__error_value_type;
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": ";
|
||||
print_detail_token(i->type);
|
||||
std::cout<<": incorrect type \'";
|
||||
print_scalar(temp.get_type());
|
||||
std::cout<<"\'."<<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
var abstract_syntax_tree::array_generation()
|
||||
{
|
||||
var new_var;
|
||||
new_var.set_type(__var_array);
|
||||
if(!children.empty())
|
||||
for(std::list<abstract_syntax_tree>::iterator i=children.begin();i!=children.end();++i)
|
||||
new_var.append_array(i->calculation());
|
||||
return new_var;
|
||||
}
|
||||
|
||||
var abstract_syntax_tree::hash_generation()
|
||||
{
|
||||
var new_var;
|
||||
new_var.set_type(__var_hash);
|
||||
if(!children.empty())
|
||||
for(std::list<abstract_syntax_tree>::iterator i=children.begin();i!=children.end();++i)
|
||||
{
|
||||
var temp;
|
||||
temp=i->children.front().calculation();
|
||||
temp.set_name(i->name);
|
||||
new_var.append_hash(temp);
|
||||
}
|
||||
return new_var;
|
||||
}
|
||||
|
||||
var abstract_syntax_tree::get_value()
|
||||
{
|
||||
var temp;
|
||||
temp.set_type(type);
|
||||
if(type==__id)
|
||||
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
|
||||
{
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": incorrect value."<<std::endl;
|
||||
exit_type=__get_value_failure;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
void abstract_syntax_tree::run_root()
|
||||
{
|
||||
while(!ret_stack.empty())ret_stack.pop();
|
||||
scope.set_clear();
|
||||
int beg_time,end_time;
|
||||
exit_type=__process_exited_successfully;
|
||||
|
||||
beg_time=time(NULL);
|
||||
for(std::list<abstract_syntax_tree>::iterator i=children.begin();i!=children.end();++i)
|
||||
{
|
||||
if(i->type==__definition)
|
||||
{
|
||||
var new_var;
|
||||
std::list<abstract_syntax_tree>::iterator j=i->children.begin();
|
||||
std::string _name=j->name;
|
||||
if(!scope.search_var(_name))
|
||||
{
|
||||
++j;
|
||||
if(j!=i->children.end())
|
||||
new_var=j->calculation();
|
||||
new_var.set_name(_name);
|
||||
scope.add_new_var(new_var);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": redeclaration of \'"<<_name<<"\'."<<std::endl;
|
||||
exit_type=__redeclaration;
|
||||
break;
|
||||
}
|
||||
}
|
||||
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==__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();
|
||||
if(t.get_type()==__var_number)
|
||||
std::cout<<t.get_number()<<std::endl;
|
||||
else if(t.get_type()==__var_string)
|
||||
std::cout<<t.get_string()<<std::endl;
|
||||
}
|
||||
else if(i->type==__number)
|
||||
std::cout<<i->number<<std::endl;
|
||||
else if(i->type==__string)
|
||||
std::cout<<i->str<<std::endl;
|
||||
else if(i->type==__id)
|
||||
{
|
||||
var t=i->call_identifier();
|
||||
if(t.get_type()==__var_number)
|
||||
std::cout<<t.get_number()<<std::endl;
|
||||
else if(t.get_type()==__var_string)
|
||||
std::cout<<t.get_string()<<std::endl;
|
||||
}
|
||||
else if(i->type==__while)
|
||||
{
|
||||
scope.add_new_block_scope();
|
||||
i->run_loop();
|
||||
scope.pop_last_block_scope();
|
||||
}
|
||||
else if(i->type==__ifelse)
|
||||
{
|
||||
scope.add_new_block_scope();
|
||||
i->run_ifelse();
|
||||
scope.pop_last_block_scope();
|
||||
}
|
||||
if(exit_type!=__process_exited_successfully)
|
||||
break;
|
||||
}
|
||||
end_time=time(NULL);
|
||||
std::cout<<"--------------------------------------------------------------------------------------"<<std::endl;
|
||||
std::cout<<">>[Runtime] process exited after "<<end_time-beg_time<<" sec(s) with returned state \'";
|
||||
print_exit_type(exit_type);
|
||||
std::cout<<"\'."<<std::endl;
|
||||
scope.set_clear();
|
||||
return;
|
||||
}
|
||||
|
||||
int abstract_syntax_tree::run_loop()
|
||||
{
|
||||
int ret=0;
|
||||
scope.add_new_local_scope();
|
||||
|
||||
abstract_syntax_tree condition=children.front();
|
||||
abstract_syntax_tree blk=children.back();
|
||||
while(condition.condition_check())
|
||||
{
|
||||
int type=blk.run_block();
|
||||
if(type==__break)
|
||||
break;
|
||||
else if(type==__return)
|
||||
{
|
||||
ret=__return;
|
||||
break;
|
||||
}
|
||||
if(exit_type!=__process_exited_successfully)
|
||||
break;
|
||||
}
|
||||
scope.pop_last_local_scope();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int abstract_syntax_tree::run_ifelse()
|
||||
{
|
||||
int ret=0;
|
||||
scope.add_new_local_scope();
|
||||
for(std::list<abstract_syntax_tree>::iterator i=children.begin();i!=children.end();++i)
|
||||
{
|
||||
if(i->type!=__else && i->children.front().condition_check())
|
||||
{
|
||||
ret=i->children.back().run_block();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret=i->children.back().run_block();
|
||||
break;
|
||||
}
|
||||
}
|
||||
scope.pop_last_local_scope();
|
||||
return ret;
|
||||
}
|
||||
|
||||
var abstract_syntax_tree::run_func()
|
||||
{
|
||||
var ret;
|
||||
scope.add_new_block_scope();
|
||||
scope.add_new_local_scope();
|
||||
|
||||
//get return
|
||||
scope.pop_last_block_scope();
|
||||
ret=ret_stack.top();
|
||||
ret_stack.pop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int abstract_syntax_tree::run_block()
|
||||
{
|
||||
scope.add_new_local_scope();
|
||||
for(std::list<abstract_syntax_tree>::iterator i=children.begin();i!=children.end();++i)
|
||||
{
|
||||
if(i->type==__definition)
|
||||
{
|
||||
var new_var;
|
||||
std::list<abstract_syntax_tree>::iterator j=i->children.begin();
|
||||
std::string _name=j->name;
|
||||
if(!scope.search_var(_name))
|
||||
{
|
||||
++j;
|
||||
if(j!=i->children.end())
|
||||
new_var=j->calculation();
|
||||
new_var.set_name(_name);
|
||||
scope.add_new_var(new_var);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout<<">>[Runtime-error] line "<<line<<": redeclaration of \'"<<_name<<"\'."<<std::endl;
|
||||
exit_type=__redeclaration;
|
||||
}
|
||||
}
|
||||
else if(i->type==__number)
|
||||
std::cout<<i->number<<std::endl;
|
||||
else if(i->type==__string)
|
||||
std::cout<<i->str<<std::endl;
|
||||
else if(i->type==__id)
|
||||
{
|
||||
var t=i->call_identifier();
|
||||
if(t.get_type()==__var_number)
|
||||
std::cout<<t.get_number()<<std::endl;
|
||||
else if(t.get_type()==__var_string)
|
||||
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==__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();
|
||||
if(t.get_type()==__var_number)
|
||||
std::cout<<t.get_number()<<std::endl;
|
||||
else if(t.get_type()==__var_string)
|
||||
std::cout<<t.get_string()<<std::endl;
|
||||
}
|
||||
else if(i->type==__while)
|
||||
{
|
||||
int type=i->run_loop();
|
||||
if(type)
|
||||
{
|
||||
if(type==__return)
|
||||
return type;
|
||||
else
|
||||
{
|
||||
std::cout<<"[Runtime-error] line "<<line<<": incorrect use of break/continue."<<std::endl;
|
||||
exit_type=__error_command_use;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(i->type==__ifelse)
|
||||
{
|
||||
int type=i->run_ifelse();
|
||||
if(type)
|
||||
return type;
|
||||
}
|
||||
else if(i->type==__continue)
|
||||
return __continue;
|
||||
else if(i->type==__break)
|
||||
return __break;
|
||||
else if(i->type==__return)
|
||||
{
|
||||
var temp;
|
||||
temp.set_type(__null_type);
|
||||
if(!(i->children.empty()))
|
||||
temp=i->calculation();
|
||||
ret_stack.push(temp);
|
||||
return __return;
|
||||
}
|
||||
if(exit_type!=__process_exited_successfully)
|
||||
break;
|
||||
}
|
||||
scope.pop_last_local_scope();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,214 @@
|
|||
#ifndef __ABSTRACT_SYNTAX_TREE_H__
|
||||
#define __ABSTRACT_SYNTAX_TREE_H__
|
||||
|
||||
class var;
|
||||
|
||||
class abstract_syntax_tree
|
||||
{
|
||||
protected:
|
||||
int type;
|
||||
int line;
|
||||
double number;
|
||||
std::string str;
|
||||
std::string name;
|
||||
std::list<abstract_syntax_tree> children;
|
||||
public:
|
||||
abstract_syntax_tree()
|
||||
{
|
||||
type=0;
|
||||
line=0;
|
||||
number=0;
|
||||
str="";
|
||||
name="";
|
||||
children.clear();
|
||||
return;
|
||||
}
|
||||
abstract_syntax_tree(const abstract_syntax_tree& p)
|
||||
{
|
||||
type=p.type;
|
||||
line=p.line;
|
||||
number=p.number;
|
||||
str=p.str;
|
||||
name=p.name;
|
||||
children=p.children;
|
||||
return;
|
||||
}
|
||||
~abstract_syntax_tree()
|
||||
{
|
||||
children.clear();
|
||||
return;
|
||||
}
|
||||
abstract_syntax_tree& operator=(const abstract_syntax_tree& p)
|
||||
{
|
||||
type=p.type;
|
||||
line=p.line;
|
||||
number=p.number;
|
||||
str=p.str;
|
||||
name=p.name;
|
||||
children.clear();
|
||||
children=p.children;
|
||||
return *this;
|
||||
}
|
||||
void set_clear()
|
||||
{
|
||||
type=0;
|
||||
line=0;
|
||||
number=0;
|
||||
str="";
|
||||
name="";
|
||||
children.clear();
|
||||
return;
|
||||
}
|
||||
void print_tree(const int n)
|
||||
{
|
||||
std::string _str="";
|
||||
for(int i=0;i<n;++i)
|
||||
_str+="| ";
|
||||
std::cout<<_str;
|
||||
print_detail_token(type);
|
||||
switch(type)
|
||||
{
|
||||
case __number:std::cout<<": "<<number;break;
|
||||
case __string:std::cout<<": "<<str;break;
|
||||
case __id:
|
||||
case __call_array:
|
||||
case __call_hash:
|
||||
case __call_function:std::cout<<": "<<name;break;
|
||||
}
|
||||
std::cout<<std::endl;
|
||||
if(!children.empty())
|
||||
{
|
||||
for(auto i=children.begin();i!=children.end();++i)
|
||||
i->print_tree(n+1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
void set_type(const int _type)
|
||||
{
|
||||
type=_type;
|
||||
return;
|
||||
}
|
||||
void set_line(const int _line)
|
||||
{
|
||||
line=_line;
|
||||
return;
|
||||
}
|
||||
void set_string(std::string _str)
|
||||
{
|
||||
str=_str;
|
||||
return;
|
||||
}
|
||||
void set_number(std::string _str)
|
||||
{
|
||||
if(_str=="nil")
|
||||
{
|
||||
number=0;
|
||||
return;
|
||||
}
|
||||
if((int)_str.length()>2 && (_str[1]=='x' || _str[1]=='o'))
|
||||
{
|
||||
double num=0;
|
||||
double pw=1;
|
||||
if(_str[1]=='x')
|
||||
for(int i=(int)_str.length()-1;i>1;--i)
|
||||
{
|
||||
if('0'<=_str[i] && _str[i]<='9')
|
||||
num+=(_str[i]-'0')*pw;
|
||||
else if('a'<=_str[i] && _str[i]<='f')
|
||||
num+=(10+_str[i]-'a')*pw;
|
||||
else if('A'<=_str[i] && _str[i]<='F')
|
||||
num+=(10+_str[i]-'A')*pw;
|
||||
pw*=16;
|
||||
}
|
||||
else
|
||||
for(int i=(int)_str.length()-1;i>1;--i)
|
||||
{
|
||||
num+=(_str[i]-'0')*pw;
|
||||
pw*=8;
|
||||
}
|
||||
number=num;
|
||||
return;
|
||||
}
|
||||
int dot_place=-1;
|
||||
for(int i=0;i<(int)_str.length();++i)
|
||||
if(_str[i]=='.')
|
||||
{
|
||||
dot_place=i;
|
||||
break;
|
||||
}
|
||||
if(dot_place==-1)
|
||||
{
|
||||
number=0;
|
||||
double pw=1;
|
||||
for(int i=(int)_str.length()-1;i>=0;--i)
|
||||
{
|
||||
number+=(_str[i]-'0')*pw;
|
||||
pw*=10;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
number=0;
|
||||
double pw=0.1;
|
||||
for(int i=dot_place+1;i<(int)_str.length();++i)
|
||||
{
|
||||
number+=(_str[i]-'0')*pw;
|
||||
pw/=10;
|
||||
}
|
||||
pw=1;
|
||||
for(int i=dot_place-1;i>=0;--i)
|
||||
{
|
||||
number+=(_str[i]-'0')*pw;
|
||||
pw*=10;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
void set_name(std::string _str)
|
||||
{
|
||||
name=_str;
|
||||
return;
|
||||
}
|
||||
void add_child(abstract_syntax_tree p)
|
||||
{
|
||||
children.push_back(p);
|
||||
return;
|
||||
}
|
||||
int get_type()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
int get_line()
|
||||
{
|
||||
return line;
|
||||
}
|
||||
double get_number()
|
||||
{
|
||||
return number;
|
||||
}
|
||||
std::string get_string()
|
||||
{
|
||||
return str;
|
||||
}
|
||||
std::string get_name()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
std::list<abstract_syntax_tree>& get_children()
|
||||
{
|
||||
return children;
|
||||
}
|
||||
var calculation();
|
||||
bool condition_check();
|
||||
var call_identifier();
|
||||
var array_generation();
|
||||
var hash_generation();
|
||||
var get_value();
|
||||
void run_root();
|
||||
int run_loop();
|
||||
int run_ifelse();
|
||||
var run_func();
|
||||
int run_block();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef __BALLOON_H__
|
||||
#define __BALLOON_H__
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <cmath>
|
||||
#include <list>
|
||||
#include <stack>
|
||||
#include <ctime>
|
||||
|
||||
#include "balloon_type.h"
|
||||
#include "abstract_syntax_tree.h"
|
||||
#include "balloon_var.h"
|
||||
#include "balloon_lexer.h"
|
||||
#include "balloon_parse.h"
|
||||
#include "balloon_scope.h"
|
||||
|
||||
#include "abstract_syntax_tree.cpp"
|
||||
|
||||
#endif
|
|
@ -0,0 +1,988 @@
|
|||
#ifndef __BALLOON_PARSE_H__
|
||||
#define __BALLOON_PARSE_H__
|
||||
|
||||
class balloon_parse
|
||||
{
|
||||
private:
|
||||
std::stack<token> parse;
|
||||
token this_token;
|
||||
int error;
|
||||
int warning;
|
||||
abstract_syntax_tree root;
|
||||
public:
|
||||
void get_token()
|
||||
{
|
||||
if(!parse.empty())
|
||||
{
|
||||
this_token=parse.top();
|
||||
parse.pop();
|
||||
}
|
||||
else
|
||||
this_token.type=0;
|
||||
return;
|
||||
}
|
||||
void get_detail_token_stream(std::list<token>& tk_list)
|
||||
{
|
||||
root.set_clear();
|
||||
while(!parse.empty())
|
||||
parse.pop();
|
||||
if(tk_list.empty())
|
||||
return;
|
||||
std::stack<token> temp;
|
||||
for(std::list<token>::iterator i=tk_list.begin();i!=tk_list.end();++i)
|
||||
temp.push(*i);
|
||||
while(!temp.empty())
|
||||
{
|
||||
parse.push(temp.top());
|
||||
temp.pop();
|
||||
}
|
||||
return;
|
||||
}
|
||||
void print_parse_stack()
|
||||
{
|
||||
if(parse.empty())
|
||||
return;
|
||||
std::stack<token> temp;
|
||||
int line=parse.top().line;
|
||||
std::cout<<line<<" ";
|
||||
while(!parse.empty())
|
||||
{
|
||||
if(parse.top().line!=line)
|
||||
{
|
||||
line=parse.top().line;
|
||||
std::cout<<std::endl<<line<<" ";
|
||||
}
|
||||
temp.push(parse.top());
|
||||
std::cout<<" ";
|
||||
print_detail_token(temp.top().type);
|
||||
parse.pop();
|
||||
}
|
||||
while(!temp.empty())
|
||||
{
|
||||
parse.push(temp.top());
|
||||
temp.pop();
|
||||
}
|
||||
std::cout<<std::endl;
|
||||
return;
|
||||
}
|
||||
int get_error()
|
||||
{
|
||||
return error;
|
||||
}
|
||||
void print_generated_tree()
|
||||
{
|
||||
std::cout<<">>[Abstract-syntax-tree]"<<std::endl;
|
||||
root.print_tree(1);
|
||||
return;
|
||||
}
|
||||
void run_tree()
|
||||
{
|
||||
std::cout<<">>[Runtime] process begins at addr:"<<(void*)(&root)<<"."<<std::endl;
|
||||
root.run_root();
|
||||
return;
|
||||
}
|
||||
abstract_syntax_tree ret();
|
||||
abstract_syntax_tree choose();
|
||||
abstract_syntax_tree loop();
|
||||
abstract_syntax_tree definition();
|
||||
abstract_syntax_tree assignment();
|
||||
abstract_syntax_tree array_generate();
|
||||
abstract_syntax_tree hash_generate();
|
||||
abstract_syntax_tree check_number();
|
||||
abstract_syntax_tree check_string();
|
||||
abstract_syntax_tree check_unary();
|
||||
abstract_syntax_tree block();
|
||||
abstract_syntax_tree func_generate();
|
||||
abstract_syntax_tree call_identifier();
|
||||
abstract_syntax_tree calculation();
|
||||
abstract_syntax_tree calculation_or();
|
||||
abstract_syntax_tree calculation_and();
|
||||
abstract_syntax_tree calculation_cmp();
|
||||
abstract_syntax_tree calculation_additive();
|
||||
abstract_syntax_tree calculation_multive();
|
||||
abstract_syntax_tree scalar();
|
||||
void check_semi();
|
||||
void parse_main();
|
||||
};
|
||||
|
||||
abstract_syntax_tree balloon_parse::ret()
|
||||
{
|
||||
abstract_syntax_tree new_node;
|
||||
new_node.set_type(__return);
|
||||
get_token();
|
||||
if(this_token.type!=__return)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": must use \'return\' here."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
new_node.set_line(this_token.line);
|
||||
get_token();
|
||||
if(this_token.type==__semi)
|
||||
parse.push(this_token);
|
||||
else
|
||||
{
|
||||
parse.push(this_token);
|
||||
new_node.add_child(scalar());
|
||||
}
|
||||
return new_node;
|
||||
}
|
||||
|
||||
abstract_syntax_tree balloon_parse::choose()
|
||||
{
|
||||
abstract_syntax_tree new_node;
|
||||
abstract_syntax_tree temp;
|
||||
new_node.set_type(__ifelse);
|
||||
temp.set_type(__if);
|
||||
get_token();
|
||||
if(this_token.type!=__if)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": must use \'if\' when generating an if-else statement."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
new_node.set_line(this_token.line);
|
||||
temp.set_line(this_token.line);
|
||||
get_token();
|
||||
if(this_token.type!=__left_curve)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \'(\'."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
temp.add_child(scalar());
|
||||
get_token();
|
||||
if(this_token.type!=__right_curve)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \')\'."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
temp.add_child(block());
|
||||
new_node.add_child(temp);
|
||||
while(1)
|
||||
{
|
||||
temp.set_clear();
|
||||
get_token();
|
||||
if(this_token.type!=__elsif && this_token.type!=__else)
|
||||
{
|
||||
parse.push(this_token);
|
||||
break;
|
||||
}
|
||||
if(this_token.type==__else)
|
||||
{
|
||||
get_token();
|
||||
if(this_token.type==__if)// else if
|
||||
{
|
||||
temp.set_type(__elsif);
|
||||
temp.set_line(this_token.line);
|
||||
get_token();
|
||||
if(this_token.type!=__left_curve)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \'(\'."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
temp.add_child(scalar());
|
||||
get_token();
|
||||
if(this_token.type!=__right_curve)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \')\'."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
temp.add_child(block());
|
||||
}
|
||||
else// real else
|
||||
{
|
||||
temp.set_type(__else);
|
||||
temp.set_line(this_token.line);
|
||||
parse.push(this_token);
|
||||
temp.add_child(block());
|
||||
break;
|
||||
}
|
||||
new_node.add_child(temp);
|
||||
}
|
||||
else if(this_token.type==__elsif)
|
||||
{
|
||||
temp.set_type(__elsif);
|
||||
temp.set_line(this_token.line);
|
||||
get_token();
|
||||
if(this_token.type!=__left_curve)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \'(\'."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
temp.add_child(scalar());
|
||||
get_token();
|
||||
if(this_token.type!=__right_curve)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \')\'."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
temp.add_child(block());
|
||||
new_node.add_child(temp);
|
||||
}
|
||||
}
|
||||
return new_node;
|
||||
}
|
||||
|
||||
abstract_syntax_tree balloon_parse::loop()
|
||||
{
|
||||
abstract_syntax_tree new_node;
|
||||
new_node.set_type(__while);
|
||||
get_token();
|
||||
if(this_token.type!=__while)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": must use \'while\' when generating a loop."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
new_node.set_line(this_token.line);
|
||||
get_token();
|
||||
if(this_token.type!=__left_curve)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \'(\'."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
new_node.add_child(scalar());
|
||||
get_token();
|
||||
if(this_token.type!=__right_curve)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \')\'."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
new_node.add_child(block());
|
||||
return new_node;
|
||||
}
|
||||
|
||||
abstract_syntax_tree balloon_parse::definition()
|
||||
{
|
||||
abstract_syntax_tree new_node;
|
||||
abstract_syntax_tree temp;
|
||||
new_node.set_type(__definition);
|
||||
temp.set_type(__id);
|
||||
get_token();
|
||||
if(this_token.type!=__var)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \'var\' here."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
new_node.set_line(this_token.line);
|
||||
temp.set_line(this_token.line);
|
||||
get_token();
|
||||
if(this_token.type!=__id)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect an identifier here."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
temp.set_name(this_token.str);
|
||||
new_node.add_child(temp);
|
||||
get_token();
|
||||
if(this_token.type!=__equal)
|
||||
{
|
||||
++warning;
|
||||
std::cout<<">>[Parse-warning] line "<<this_token.line<<": every new var should be initialized."<<std::endl;
|
||||
parse.push(this_token);
|
||||
return new_node;
|
||||
}
|
||||
new_node.add_child(scalar());
|
||||
return new_node;
|
||||
}
|
||||
|
||||
abstract_syntax_tree balloon_parse::assignment()
|
||||
{
|
||||
abstract_syntax_tree new_node;
|
||||
get_token();
|
||||
if(!(this_token.type==__equal || this_token.type==__add_equal
|
||||
|| this_token.type==__sub_equal || this_token.type==__mul_equal
|
||||
|| this_token.type==__div_equal || this_token.type==__link_equal))
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect an operator for assignment here."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
new_node.set_line(this_token.line);
|
||||
new_node.set_type(this_token.type);
|
||||
new_node.add_child(scalar());
|
||||
return new_node;
|
||||
}
|
||||
|
||||
abstract_syntax_tree balloon_parse::array_generate()
|
||||
{
|
||||
abstract_syntax_tree new_node;
|
||||
new_node.set_type(__array);
|
||||
get_token();
|
||||
if(this_token.type!=__left_bracket)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \'[\' here."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
new_node.set_line(this_token.line);
|
||||
while(1)
|
||||
{
|
||||
get_token();
|
||||
switch(this_token.type)
|
||||
{
|
||||
case __func:
|
||||
case __left_curve:
|
||||
case __left_bracket:
|
||||
case __left_brace:
|
||||
case __nor_operator:
|
||||
case __sub_operator:
|
||||
case __number:
|
||||
case __string:
|
||||
case __id:parse.push(this_token);new_node.add_child(scalar());break;
|
||||
case __right_bracket:parse.push(this_token);break;
|
||||
default:
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a scalar or \']\' here."<<std::endl;
|
||||
return new_node;
|
||||
break;
|
||||
}
|
||||
get_token();
|
||||
if(this_token.type!=__comma && this_token.type!=__right_bracket)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \',\' or \']\' here."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
else if(this_token.type==__right_bracket)
|
||||
break;
|
||||
}
|
||||
return new_node;
|
||||
}
|
||||
|
||||
abstract_syntax_tree balloon_parse::hash_generate()
|
||||
{
|
||||
abstract_syntax_tree new_node;
|
||||
abstract_syntax_tree temp;
|
||||
new_node.set_type(__hash);
|
||||
get_token();
|
||||
if(this_token.type!=__left_brace)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \'{\' here."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
new_node.set_line(this_token.line);
|
||||
get_token();
|
||||
if(this_token.type!=__right_brace)
|
||||
parse.push(this_token);
|
||||
while(this_token.type!=__right_brace)
|
||||
{
|
||||
temp.set_clear();
|
||||
temp.set_type(__id);
|
||||
get_token();
|
||||
if(this_token.type!=__id)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect an identifier here."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
temp.set_line(this_token.line);
|
||||
temp.set_name(this_token.str);
|
||||
get_token();
|
||||
if(this_token.type!=__colon)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \':\' here."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
get_token();
|
||||
switch(this_token.type)
|
||||
{
|
||||
case __func:
|
||||
case __left_curve:
|
||||
case __left_bracket:
|
||||
case __left_brace:
|
||||
case __nor_operator:
|
||||
case __sub_operator:
|
||||
case __number:
|
||||
case __string:
|
||||
case __id:parse.push(this_token);temp.add_child(scalar());break;
|
||||
case __right_brace:parse.push(this_token);break;
|
||||
default:
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a scalar or \'}\' here."<<std::endl;
|
||||
return new_node;
|
||||
break;
|
||||
}
|
||||
new_node.add_child(temp);
|
||||
get_token();
|
||||
if(this_token.type!=__comma && this_token.type!=__right_brace)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \',\' or \'}\' here."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
}
|
||||
return new_node;
|
||||
}
|
||||
|
||||
abstract_syntax_tree balloon_parse::check_number()
|
||||
{
|
||||
abstract_syntax_tree new_node;
|
||||
new_node.set_type(__number);
|
||||
get_token();
|
||||
if(this_token.type!=__number)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a number here."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
new_node.set_line(this_token.line);
|
||||
new_node.set_number(this_token.str);
|
||||
return new_node;
|
||||
}
|
||||
|
||||
abstract_syntax_tree balloon_parse::check_string()
|
||||
{
|
||||
abstract_syntax_tree new_node;
|
||||
new_node.set_type(__string);
|
||||
get_token();
|
||||
if(this_token.type!=__string)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a string here."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
new_node.set_line(this_token.line);
|
||||
new_node.set_string(this_token.str);
|
||||
return new_node;
|
||||
}
|
||||
|
||||
abstract_syntax_tree balloon_parse::check_unary()
|
||||
{
|
||||
abstract_syntax_tree new_node;
|
||||
get_token();
|
||||
if(this_token.type!=__nor_operator && this_token.type!=__sub_operator)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a unary operator here."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
new_node.set_line(this_token.line);
|
||||
new_node.set_type(this_token.type);
|
||||
get_token();
|
||||
switch(this_token.type)
|
||||
{
|
||||
case __number:parse.push(this_token);new_node.add_child(check_number());break;
|
||||
case __string:parse.push(this_token);new_node.add_child(check_string());break;
|
||||
case __id:parse.push(this_token);new_node.add_child(call_identifier());break;
|
||||
case __left_curve:parse.push(this_token);new_node.add_child(scalar());break;
|
||||
case __nor_operator:parse.push(this_token);new_node.add_child(check_unary());break;
|
||||
default:++error;std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a scalar here."<<std::endl;break;
|
||||
}
|
||||
return new_node;
|
||||
}
|
||||
|
||||
abstract_syntax_tree balloon_parse::block()
|
||||
{
|
||||
abstract_syntax_tree new_node;
|
||||
abstract_syntax_tree temp;
|
||||
new_node.set_type(__block);
|
||||
get_token();
|
||||
if(this_token.type!=__left_brace)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \'{\' ."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
new_node.set_line(this_token.line);
|
||||
while(1)
|
||||
{
|
||||
get_token();
|
||||
switch(this_token.type)
|
||||
{
|
||||
case __var:parse.push(this_token);new_node.add_child(definition());check_semi();break;
|
||||
case __left_curve:
|
||||
case __left_bracket:
|
||||
case __left_brace:
|
||||
case __nor_operator:
|
||||
case __sub_operator:
|
||||
case __number:
|
||||
case __string:
|
||||
case __id:parse.push(this_token);new_node.add_child(scalar());check_semi();break;
|
||||
case __if:parse.push(this_token);new_node.add_child(choose());break;
|
||||
case __for:
|
||||
case __forindex:
|
||||
case __foreach:
|
||||
case __while:parse.push(this_token);new_node.add_child(loop());break;
|
||||
case __semi:break;
|
||||
case __continue:
|
||||
case __break:temp.set_clear();temp.set_type(this_token.type);new_node.add_child(temp);check_semi();break;
|
||||
case __return:parse.push(this_token);new_node.add_child(ret());check_semi();break;
|
||||
case __right_brace:parse.push(this_token);break;
|
||||
default:
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": \'";
|
||||
print_detail_token(this_token.type);
|
||||
std::cout<<"\' should not appear in this scope."<<std::endl;
|
||||
return new_node;
|
||||
break;
|
||||
}
|
||||
get_token();
|
||||
if(this_token.type==__right_brace)
|
||||
break;
|
||||
else
|
||||
parse.push(this_token);
|
||||
}
|
||||
return new_node;
|
||||
}
|
||||
|
||||
abstract_syntax_tree balloon_parse::func_generate()
|
||||
{
|
||||
abstract_syntax_tree new_node;
|
||||
abstract_syntax_tree para;
|
||||
abstract_syntax_tree temp;
|
||||
new_node.set_type(__function);
|
||||
para.set_type(__parameter);
|
||||
get_token();
|
||||
if(this_token.type!=__func)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \'func\' here."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
new_node.set_line(this_token.line);
|
||||
para.set_line(this_token.line);
|
||||
get_token();
|
||||
if(this_token.type==__left_curve)
|
||||
{
|
||||
get_token();
|
||||
if(this_token.type!=__right_curve)
|
||||
parse.push(this_token);
|
||||
while(this_token.type!=__right_curve)
|
||||
{
|
||||
get_token();
|
||||
if(this_token.type!=__id && this_token.type!=__dynamic_id)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect identifier when declaring a new function."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
temp.set_clear();
|
||||
temp.set_line(this_token.line);
|
||||
temp.set_type(this_token.type);
|
||||
temp.set_name(this_token.str);
|
||||
para.add_child(temp);
|
||||
if(this_token.type==__dynamic_id)
|
||||
{
|
||||
get_token();
|
||||
if(this_token.type!=__right_curve)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": dynamic identifier should have \')\' behind it ."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
get_token();
|
||||
if(this_token.type!=__comma && this_token.type!=__right_curve)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect \',\' or \')\' here."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
parse.push(this_token);
|
||||
new_node.add_child(para);
|
||||
new_node.add_child(block());
|
||||
return new_node;
|
||||
}
|
||||
|
||||
abstract_syntax_tree balloon_parse::call_identifier()
|
||||
{
|
||||
abstract_syntax_tree new_node;
|
||||
abstract_syntax_tree temp;
|
||||
get_token();
|
||||
if(this_token.type!=__id)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": must have an identifier here."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
new_node.set_line(this_token.line);
|
||||
new_node.set_type(__id);
|
||||
new_node.set_name(this_token.str);
|
||||
while(1)
|
||||
{
|
||||
get_token();
|
||||
if(this_token.type==__left_curve)
|
||||
{
|
||||
temp.set_clear();
|
||||
temp.set_line(this_token.line);
|
||||
temp.set_type(__call_function);
|
||||
get_token();
|
||||
if(this_token.type!=__right_curve)
|
||||
parse.push(this_token);
|
||||
while(this_token.type!=__right_curve)
|
||||
{
|
||||
temp.add_child(scalar());
|
||||
get_token();
|
||||
if(this_token.type!=__comma && this_token.type!=__right_curve)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \',\' or \')\' here."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
}
|
||||
new_node.add_child(temp);
|
||||
}
|
||||
else if(this_token.type==__left_bracket)
|
||||
{
|
||||
temp.set_clear();
|
||||
temp.set_line(this_token.line);
|
||||
temp.set_type(__call_array);
|
||||
temp.add_child(scalar());
|
||||
get_token();
|
||||
if(this_token.type!=__right_bracket)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \']\' ."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
new_node.add_child(temp);
|
||||
}
|
||||
else if(this_token.type==__dot)
|
||||
{
|
||||
get_token();
|
||||
if(this_token.type!=__id)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect an identifier when calling hash."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
temp.set_clear();
|
||||
temp.set_line(this_token.line);
|
||||
temp.set_type(__call_hash);
|
||||
temp.set_name(this_token.str);
|
||||
new_node.add_child(temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
parse.push(this_token);
|
||||
break;
|
||||
}
|
||||
}
|
||||
get_token();
|
||||
if(this_token.type==__equal || this_token.type==__add_equal
|
||||
|| this_token.type==__sub_equal || this_token.type==__mul_equal
|
||||
|| this_token.type==__div_equal || this_token.type==__link_equal)
|
||||
{
|
||||
parse.push(this_token);
|
||||
temp=new_node;
|
||||
new_node=assignment();
|
||||
new_node.set_line(this_token.line);
|
||||
new_node.get_children().push_front(temp);
|
||||
}
|
||||
else
|
||||
parse.push(this_token);
|
||||
return new_node;
|
||||
}
|
||||
|
||||
abstract_syntax_tree balloon_parse::calculation()
|
||||
{
|
||||
abstract_syntax_tree new_node;
|
||||
new_node=calculation_or();
|
||||
return new_node;
|
||||
}
|
||||
|
||||
abstract_syntax_tree balloon_parse::calculation_or()
|
||||
{
|
||||
abstract_syntax_tree new_node;
|
||||
abstract_syntax_tree temp;
|
||||
new_node=calculation_and();
|
||||
get_token();
|
||||
if(this_token.type!=__or_operator)
|
||||
{
|
||||
parse.push(this_token);
|
||||
return new_node;
|
||||
}
|
||||
temp.set_line(this_token.line);
|
||||
temp.set_type(__or_operator);
|
||||
temp.add_child(new_node);
|
||||
while(1)
|
||||
{
|
||||
temp.add_child(calculation_and());
|
||||
new_node=temp;
|
||||
temp.set_clear();
|
||||
get_token();
|
||||
if(this_token.type!=__or_operator)
|
||||
{
|
||||
parse.push(this_token);
|
||||
break;
|
||||
}
|
||||
temp.set_line(this_token.line);
|
||||
temp.set_type(__or_operator);
|
||||
temp.add_child(new_node);
|
||||
}
|
||||
return new_node;
|
||||
}
|
||||
|
||||
abstract_syntax_tree balloon_parse::calculation_and()
|
||||
{
|
||||
abstract_syntax_tree new_node;
|
||||
abstract_syntax_tree temp;
|
||||
new_node=calculation_cmp();
|
||||
get_token();
|
||||
if(this_token.type!=__and_operator)
|
||||
{
|
||||
parse.push(this_token);
|
||||
return new_node;
|
||||
}
|
||||
temp.set_line(this_token.line);
|
||||
temp.set_type(__and_operator);
|
||||
temp.add_child(new_node);
|
||||
while(1)
|
||||
{
|
||||
temp.add_child(calculation_cmp());
|
||||
new_node=temp;
|
||||
temp.set_clear();
|
||||
get_token();
|
||||
if(this_token.type!=__and_operator)
|
||||
{
|
||||
parse.push(this_token);
|
||||
break;
|
||||
}
|
||||
temp.set_line(this_token.line);
|
||||
temp.set_type(__and_operator);
|
||||
temp.add_child(new_node);
|
||||
}
|
||||
return new_node;
|
||||
}
|
||||
|
||||
abstract_syntax_tree balloon_parse::calculation_cmp()
|
||||
{
|
||||
abstract_syntax_tree new_node;
|
||||
abstract_syntax_tree temp;
|
||||
new_node=calculation_additive();
|
||||
get_token();
|
||||
if(this_token.type!=__cmp_equal && this_token.type!=__cmp_not_equal
|
||||
&& this_token.type!=__cmp_less && this_token.type!=__cmp_less_or_equal
|
||||
&& this_token.type!=__cmp_more && this_token.type!=__cmp_more_or_equal)
|
||||
{
|
||||
parse.push(this_token);
|
||||
return new_node;
|
||||
}
|
||||
temp.set_line(this_token.line);
|
||||
temp.set_type(this_token.type);
|
||||
temp.add_child(new_node);
|
||||
while(1)
|
||||
{
|
||||
temp.add_child(calculation_additive());
|
||||
new_node=temp;
|
||||
temp.set_clear();
|
||||
get_token();
|
||||
if(this_token.type!=__cmp_equal && this_token.type!=__cmp_not_equal
|
||||
&& this_token.type!=__cmp_less && this_token.type!=__cmp_less_or_equal
|
||||
&& this_token.type!=__cmp_more && this_token.type!=__cmp_more_or_equal)
|
||||
{
|
||||
parse.push(this_token);
|
||||
break;
|
||||
}
|
||||
temp.set_line(this_token.line);
|
||||
temp.set_type(this_token.type);
|
||||
temp.add_child(new_node);
|
||||
}
|
||||
return new_node;
|
||||
}
|
||||
|
||||
abstract_syntax_tree balloon_parse::calculation_additive()
|
||||
{
|
||||
abstract_syntax_tree new_node;
|
||||
abstract_syntax_tree temp;
|
||||
new_node=calculation_multive();
|
||||
get_token();
|
||||
if(this_token.type!=__add_operator && this_token.type!=__sub_operator && this_token.type!=__link_operator)
|
||||
{
|
||||
parse.push(this_token);
|
||||
return new_node;
|
||||
}
|
||||
temp.set_line(this_token.line);
|
||||
temp.set_type(this_token.type);
|
||||
temp.add_child(new_node);
|
||||
while(1)
|
||||
{
|
||||
temp.add_child(calculation_multive());
|
||||
new_node=temp;
|
||||
temp.set_clear();
|
||||
get_token();
|
||||
if(this_token.type!=__add_operator && this_token.type!=__sub_operator && this_token.type!=__link_operator)
|
||||
{
|
||||
parse.push(this_token);
|
||||
break;
|
||||
}
|
||||
temp.set_line(this_token.line);
|
||||
temp.set_type(this_token.type);
|
||||
temp.add_child(new_node);
|
||||
}
|
||||
return new_node;
|
||||
}
|
||||
|
||||
abstract_syntax_tree balloon_parse::calculation_multive()
|
||||
{
|
||||
abstract_syntax_tree new_node;
|
||||
abstract_syntax_tree temp;
|
||||
get_token();
|
||||
new_node.set_line(this_token.line);
|
||||
switch(this_token.type)
|
||||
{
|
||||
case __left_curve:
|
||||
new_node=scalar();get_token();
|
||||
if(this_token.type!=__right_curve)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \')\' here."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
break;
|
||||
case __number:parse.push(this_token);new_node=check_number();break;
|
||||
case __string:parse.push(this_token);new_node=check_string();break;
|
||||
case __id:parse.push(this_token);new_node=call_identifier();break;
|
||||
case __nor_operator:
|
||||
case __sub_operator:parse.push(this_token);new_node=check_unary();break;
|
||||
default:
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a scalar here."<<std::endl;
|
||||
return new_node;
|
||||
break;
|
||||
}
|
||||
|
||||
get_token();
|
||||
if(this_token.type!=__mul_operator && this_token.type!=__div_operator)
|
||||
{
|
||||
parse.push(this_token);
|
||||
return new_node;
|
||||
}
|
||||
temp.set_line(this_token.line);
|
||||
temp.set_type(this_token.type);
|
||||
temp.add_child(new_node);
|
||||
while(1)
|
||||
{
|
||||
get_token();
|
||||
switch(this_token.type)
|
||||
{
|
||||
case __left_curve:
|
||||
temp.add_child(scalar());get_token();
|
||||
if(this_token.type!=__right_curve)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \')\' here."<<std::endl;
|
||||
return new_node;
|
||||
}
|
||||
break;
|
||||
case __number:parse.push(this_token);temp.add_child(check_number());break;
|
||||
case __string:parse.push(this_token);temp.add_child(check_string());break;
|
||||
case __id:parse.push(this_token);temp.add_child(call_identifier());break;
|
||||
case __nor_operator:
|
||||
case __sub_operator:parse.push(this_token);temp.add_child(check_unary());break;
|
||||
default:
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a scalar here."<<std::endl;
|
||||
return new_node;
|
||||
break;
|
||||
}
|
||||
new_node=temp;
|
||||
temp.set_clear();
|
||||
get_token();
|
||||
if(this_token.type!=__mul_operator && this_token.type!=__div_operator)
|
||||
{
|
||||
parse.push(this_token);
|
||||
break;
|
||||
}
|
||||
temp.set_line(this_token.line);
|
||||
temp.set_type(this_token.type);
|
||||
temp.add_child(new_node);
|
||||
}
|
||||
return new_node;
|
||||
}
|
||||
|
||||
abstract_syntax_tree balloon_parse::scalar()
|
||||
{
|
||||
abstract_syntax_tree new_node;
|
||||
get_token();
|
||||
new_node.set_line(this_token.line);
|
||||
switch(this_token.type)
|
||||
{
|
||||
case __func:parse.push(this_token);new_node=func_generate();break;
|
||||
case __left_bracket:parse.push(this_token);new_node=array_generate();break;
|
||||
case __left_brace:parse.push(this_token);new_node=hash_generate();break;
|
||||
case __left_curve:
|
||||
case __nor_operator:
|
||||
case __sub_operator:
|
||||
case __number:
|
||||
case __string:
|
||||
case __id:parse.push(this_token);new_node=calculation();break;
|
||||
default:
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a scalar at this place."<<std::endl;
|
||||
parse.push(this_token);
|
||||
break;
|
||||
}
|
||||
return new_node;
|
||||
}
|
||||
|
||||
void balloon_parse::check_semi()
|
||||
{
|
||||
get_token();
|
||||
if(this_token.type!=__semi)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \';\' ."<<std::endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void balloon_parse::parse_main()
|
||||
{
|
||||
root.set_clear();
|
||||
root.set_type(__root);
|
||||
root.set_line(1);
|
||||
error=0;
|
||||
warning=0;
|
||||
|
||||
while(!parse.empty())
|
||||
{
|
||||
get_token();
|
||||
switch(this_token.type)
|
||||
{
|
||||
case __var:parse.push(this_token);root.add_child(definition());check_semi();break;
|
||||
case __left_curve:
|
||||
case __left_bracket:
|
||||
case __left_brace:
|
||||
case __nor_operator:
|
||||
case __sub_operator:
|
||||
case __number:
|
||||
case __string:
|
||||
case __id:parse.push(this_token);root.add_child(scalar());check_semi();break;
|
||||
case __if:parse.push(this_token);root.add_child(choose());break;
|
||||
case __for:
|
||||
case __forindex:
|
||||
case __foreach:
|
||||
case __while:parse.push(this_token);root.add_child(loop());break;
|
||||
case __semi:break;
|
||||
default:
|
||||
++error;
|
||||
std::cout<<">>[Parse-error] line "<<this_token.line<<": \'";
|
||||
print_detail_token(this_token.type);
|
||||
std::cout<<"\' should not appear in this scope."<<std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::cout<<">>[Parse] complete generating."<<error<<" error(s),"<<warning<<" warning(s)."<<std::endl;
|
||||
return;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,111 @@
|
|||
#ifndef __BALLOON_SCOPE_H__
|
||||
#define __BALLOON_SCOPE_H__
|
||||
|
||||
class balloon_scope
|
||||
{
|
||||
private:
|
||||
std::list<var> global;
|
||||
std::list<std::list<std::list<var> > > scope_list;
|
||||
public:
|
||||
void set_clear()
|
||||
{
|
||||
global.clear();
|
||||
scope_list.clear();
|
||||
return;
|
||||
}
|
||||
bool search_var(std::string name)
|
||||
{
|
||||
if(!scope_list.empty())
|
||||
{
|
||||
std::list<std::list<var> >::iterator i=scope_list.back().end();
|
||||
--i;
|
||||
for(;;--i)
|
||||
{
|
||||
for(std::list<var>::iterator j=i->begin();j!=i->end();++j)
|
||||
if(j->get_name()==name)
|
||||
return true;
|
||||
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)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void add_new_var(var t)
|
||||
{
|
||||
if(!scope_list.empty())
|
||||
{
|
||||
std::list<std::list<var> >::iterator i=scope_list.back().end();
|
||||
--i;
|
||||
i->push_back(t);
|
||||
return;
|
||||
}
|
||||
global.push_back(t);
|
||||
return;
|
||||
}
|
||||
var get_var(std::string name)
|
||||
{
|
||||
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)
|
||||
return *j;
|
||||
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)
|
||||
return *i;
|
||||
}
|
||||
return error_var;
|
||||
}
|
||||
void add_new_block_scope()
|
||||
{
|
||||
std::list<std::list<var> > new_list;
|
||||
scope_list.push_back(new_list);
|
||||
return;
|
||||
}
|
||||
void add_new_local_scope()
|
||||
{
|
||||
if(!scope_list.empty())
|
||||
{
|
||||
std::list<std::list<std::list<var> > >::iterator i=scope_list.end();
|
||||
--i;
|
||||
std::list<var> new_list;
|
||||
i->push_back(new_list);
|
||||
}
|
||||
return;
|
||||
}
|
||||
void pop_last_block_scope()
|
||||
{
|
||||
if(!scope_list.empty())
|
||||
scope_list.pop_back();
|
||||
return;
|
||||
}
|
||||
void pop_last_local_scope()
|
||||
{
|
||||
if(!scope_list.empty())
|
||||
{
|
||||
std::list<std::list<var> > temp=scope_list.back();
|
||||
temp.pop_back();
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
balloon_scope scope;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,174 @@
|
|||
#ifndef __BALLOON_TYPE_H__
|
||||
#define __BALLOON_TYPE_H__
|
||||
|
||||
|
||||
enum token_type
|
||||
{
|
||||
__token_number=1,
|
||||
__token_string,
|
||||
__reserve_word,
|
||||
__token_identifier,
|
||||
__token_operator
|
||||
};
|
||||
void print_token(int type)
|
||||
{
|
||||
std::string str;
|
||||
switch(type)
|
||||
{
|
||||
case __token_number: str="number ";break;
|
||||
case __token_string: str="string ";break;
|
||||
case __reserve_word: str="reserve word ";break;
|
||||
case __token_identifier:str="identifier ";break;
|
||||
case __token_operator: str="operator ";break;
|
||||
default: str="unknown ";break;
|
||||
}
|
||||
std::cout<<str;
|
||||
return;
|
||||
}
|
||||
|
||||
enum parse_type
|
||||
{
|
||||
__equal, // =
|
||||
__cmp_equal,__cmp_not_equal, // == !=
|
||||
__cmp_less,__cmp_less_or_equal, // < <=
|
||||
__cmp_more,__cmp_more_or_equal, // > >=
|
||||
__and_operator,__or_operator,__nor_operator, // and or !
|
||||
__add_operator,__sub_operator, // + -
|
||||
__mul_operator,__div_operator,__link_operator, // * / ~
|
||||
__add_equal,__sub_equal, // += -=
|
||||
__mul_equal,__div_equal,__link_equal, // *= /= ~=
|
||||
__left_brace,__right_brace, // {}
|
||||
__left_bracket,__right_bracket, // []
|
||||
__left_curve,__right_curve, // ()
|
||||
__semi,__comma,__colon,__dot, // ; , : .
|
||||
__var,__func,__return,
|
||||
__if,__elsif,__else,
|
||||
__continue,__break,
|
||||
__for,__forindex,__foreach,__while,
|
||||
__nil,
|
||||
//operators & reserve words
|
||||
__number,__string,__id,__dynamic_id,
|
||||
//basic elements
|
||||
|
||||
__null_node,
|
||||
__block,
|
||||
__array,
|
||||
__hash,
|
||||
__root,
|
||||
__loop,
|
||||
__ifelse,
|
||||
__function,
|
||||
__parameter,
|
||||
__definition,
|
||||
__assignment,
|
||||
__call_array,
|
||||
__call_hash,
|
||||
__call_function
|
||||
};
|
||||
void print_detail_token(int type)
|
||||
{
|
||||
std::string context="";
|
||||
switch(type)
|
||||
{
|
||||
case __equal: context="="; break;
|
||||
case __cmp_equal: context="==";break;
|
||||
case __cmp_not_equal: context="!=";break;
|
||||
case __cmp_less: context="<"; break;
|
||||
case __cmp_less_or_equal: context="<=";break;
|
||||
case __cmp_more: context=">"; break;
|
||||
case __cmp_more_or_equal: context=">=";break;
|
||||
case __and_operator: context="and";break;
|
||||
case __or_operator: context="or"; break;
|
||||
case __nor_operator: context="!"; break;
|
||||
case __add_operator: context="+"; break;
|
||||
case __sub_operator: context="-"; break;
|
||||
case __mul_operator: context="*"; break;
|
||||
case __div_operator: context="/"; break;
|
||||
case __link_operator: context="~"; break;
|
||||
case __add_equal: context="+=";break;
|
||||
case __sub_equal: context="-=";break;
|
||||
case __mul_equal: context="*=";break;
|
||||
case __div_equal: context="/=";break;
|
||||
case __link_equal: context="~=";break;
|
||||
case __left_brace: context="{"; break;
|
||||
case __right_brace: context="}"; break;
|
||||
case __left_bracket: context="["; break;
|
||||
case __right_bracket: context="]"; break;
|
||||
case __left_curve: context="("; break;
|
||||
case __right_curve: context=")"; break;
|
||||
case __semi: context=";"; break;
|
||||
case __comma: context=","; break;
|
||||
case __colon: context=":"; break;
|
||||
case __dot: context="."; break;
|
||||
case __var: context="var"; break;
|
||||
case __func: context="func";break;
|
||||
case __continue: context="continye"; break;
|
||||
case __break: context="break"; break;
|
||||
case __for: context="for"; break;
|
||||
case __forindex: context="forindex";break;
|
||||
case __foreach: context="foreach";break;
|
||||
case __while: context="while";break;
|
||||
case __if: context="if";break;
|
||||
case __elsif: context="elsif";break;
|
||||
case __else: context="else";break;
|
||||
case __return: context="return";break;
|
||||
case __nil: context="nil";break;
|
||||
case __id: context="id";break;
|
||||
case __dynamic_id: context="id...";break;
|
||||
case __number: context="num";break;
|
||||
case __string: context="str";break;
|
||||
|
||||
case __null_node: context="null node";break;
|
||||
case __block: context="block";break;
|
||||
case __array: context="array";break;
|
||||
case __hash: context="hash";break;
|
||||
case __root: context="root";break;
|
||||
case __loop: context="loop";break;
|
||||
case __ifelse: context="if-else";break;
|
||||
case __function: context="function";break;
|
||||
case __parameter: context="parameter";break;
|
||||
case __definition: context="definition";break;
|
||||
case __assignment: context="assignment";break;
|
||||
case __call_array: context="call array";break;
|
||||
case __call_hash: context="call hash";break;
|
||||
case __call_function: context="call func";break;
|
||||
default: context="undefined token";break;
|
||||
}
|
||||
std::cout<<context;
|
||||
return;
|
||||
}
|
||||
|
||||
enum runtime_error_type
|
||||
{
|
||||
__process_exited_successfully,
|
||||
__redeclaration,
|
||||
__get_value_failure,
|
||||
__find_var_failure,
|
||||
__error_value_type,
|
||||
__error_command_use,
|
||||
__sigfpe_arithmetic_exception,
|
||||
__sigsegv_segmentation_error,
|
||||
__terminal_interrupt
|
||||
};
|
||||
|
||||
void print_exit_type(int type)
|
||||
{
|
||||
std::string context;
|
||||
switch(type)
|
||||
{
|
||||
case __process_exited_successfully: context="process_success";break;
|
||||
case __redeclaration: context="redeclaration";break;
|
||||
case __get_value_failure: context="get_value_failure";break;
|
||||
case __find_var_failure: context="find_var_failure";break;
|
||||
case __error_value_type: context="value_type_error";break;
|
||||
case __error_command_use: context="command_use_error(continue/break/return)";break;
|
||||
case __sigfpe_arithmetic_exception: context="SIGFPE";break;
|
||||
case __sigsegv_segmentation_error: context="SIGSEGV";break;
|
||||
case __terminal_interrupt: context="interrupt";break;
|
||||
default: context="unknown";break;
|
||||
}
|
||||
std::cout<<context;
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,186 @@
|
|||
#ifndef __BALLOON_VAR_H__
|
||||
#define __BALLOON_VAR_H__
|
||||
|
||||
enum var_type
|
||||
{
|
||||
__null_type,
|
||||
__var_number,
|
||||
__var_string,
|
||||
__var_array,
|
||||
__var_hash,
|
||||
__var_function
|
||||
};
|
||||
|
||||
void print_scalar(int type)
|
||||
{
|
||||
std::string str="";
|
||||
switch(type)
|
||||
{
|
||||
case __null_type: str="null";break;
|
||||
case __var_number: str="number";break;
|
||||
case __var_string: str="string";break;
|
||||
case __var_array: str="array";break;
|
||||
case __var_hash: str="hash";break;
|
||||
case __var_function:str="function";break;
|
||||
default: str="unknown";break;
|
||||
}
|
||||
std::cout<<str;
|
||||
return;
|
||||
}
|
||||
|
||||
class var
|
||||
{
|
||||
private:
|
||||
int type;
|
||||
double number;
|
||||
std::string str;
|
||||
std::string name;
|
||||
std::list<var> balloon_array;
|
||||
std::list<var> balloon_hash;
|
||||
abstract_syntax_tree function;
|
||||
public:
|
||||
var()
|
||||
{
|
||||
type=__null_type;
|
||||
number=0;
|
||||
str="";
|
||||
name="";
|
||||
balloon_array.clear();
|
||||
balloon_hash.clear();
|
||||
function.set_clear();
|
||||
return;
|
||||
}
|
||||
var(const var& p)
|
||||
{
|
||||
type=p.type;
|
||||
number=p.number;
|
||||
str=p.str;
|
||||
name=p.name;
|
||||
balloon_array=p.balloon_array;
|
||||
balloon_hash=p.balloon_hash;
|
||||
function=p.function;
|
||||
return;
|
||||
}
|
||||
var& operator=(const var& p)
|
||||
{
|
||||
type=p.type;
|
||||
number=p.number;
|
||||
str=p.str;
|
||||
name=p.name;
|
||||
balloon_array.clear();
|
||||
balloon_hash.clear();
|
||||
function.set_clear();
|
||||
balloon_array=p.balloon_array;
|
||||
balloon_hash=p.balloon_hash;
|
||||
function=p.function;
|
||||
return *this;
|
||||
}
|
||||
void set_type(int);
|
||||
void set_name(std::string);
|
||||
void set_number(double);
|
||||
void set_string(std::string);
|
||||
void set_function(abstract_syntax_tree&);
|
||||
void append_array(var);
|
||||
void append_hash(var);
|
||||
int get_type();
|
||||
std::string get_name();
|
||||
double get_number();
|
||||
std::string get_string();
|
||||
var& get_array_member(int);
|
||||
var& get_hash_member(std::string);
|
||||
abstract_syntax_tree& get_function();
|
||||
};
|
||||
|
||||
var error_var;
|
||||
|
||||
void var::set_type(int _type)
|
||||
{
|
||||
type=_type;
|
||||
return;
|
||||
}
|
||||
|
||||
void var::set_name(std::string _name)
|
||||
{
|
||||
name=_name;
|
||||
return;
|
||||
}
|
||||
|
||||
void var::set_number(double _num)
|
||||
{
|
||||
number=_num;
|
||||
return;
|
||||
}
|
||||
|
||||
void var::set_string(std::string _str)
|
||||
{
|
||||
str=_str;
|
||||
return;
|
||||
}
|
||||
|
||||
void var::set_function(abstract_syntax_tree& p)
|
||||
{
|
||||
function=p;
|
||||
return;
|
||||
}
|
||||
|
||||
void var::append_array(var _new_var)
|
||||
{
|
||||
balloon_array.push_back(_new_var);
|
||||
return;
|
||||
}
|
||||
|
||||
void var::append_hash(var _new_var)
|
||||
{
|
||||
balloon_hash.push_back(_new_var);
|
||||
return;
|
||||
}
|
||||
|
||||
int var::get_type()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
std::string var::get_name()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
double var::get_number()
|
||||
{
|
||||
return number;
|
||||
}
|
||||
|
||||
std::string var::get_string()
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
var& var::get_array_member(int _place)
|
||||
{
|
||||
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)
|
||||
return *i;
|
||||
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)
|
||||
{
|
||||
for(std::list<var>::iterator i=balloon_hash.begin();i!=balloon_hash.end();++i)
|
||||
if(i->name==_name)
|
||||
return *i;
|
||||
std::cout<<">>[Runtime-error] hash \'"<<name<<"\' does not have a member named \'"<<_name<<"\'"<<std::endl;
|
||||
return error_var;
|
||||
}
|
||||
|
||||
abstract_syntax_tree& var::get_function()
|
||||
{
|
||||
return function;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,100 @@
|
|||
#include "balloon.h"
|
||||
|
||||
resource_file prog;
|
||||
balloon_lexer lex;
|
||||
balloon_parse pas;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::string command;
|
||||
std::cout<<">> Balloon interpreter by ValKmjolnir"<<std::endl;
|
||||
std::cout<<">> Input [help] to find help."<<std::endl;
|
||||
while(1)
|
||||
{
|
||||
std::cout<<">> ";
|
||||
std::getline(std::cin,command);
|
||||
if(command=="help")
|
||||
{
|
||||
std::cout<<">> Balloon interpreter by ValKmjolnir"<<std::endl;
|
||||
std::cout<<">> 1. [ ] |input file name to load the file."<<std::endl;
|
||||
std::cout<<">> 2. [cls ] |clear the screen."<<std::endl;
|
||||
std::cout<<">> 3. [exit ] |shut down the interpreter."<<std::endl;
|
||||
std::cout<<">> 4. [lexer ] |run and show the lexer. (-lexer)"<<std::endl;
|
||||
std::cout<<">> 5. [parser] |run parser and see parse stack & parse result(s). (-parser)"<<std::endl;
|
||||
std::cout<<">> 6. [ast ] |print the abstract syntax tree."<<std::endl;
|
||||
std::cout<<">> 7. [del ] |delete program in memory."<<std::endl;
|
||||
std::cout<<">> 8. [run ] |run the programme in stack. (-lexer -parser)"<<std::endl;
|
||||
std::cout<<">> 9. [rs ] |check the source program."<<std::endl;
|
||||
}
|
||||
else if(command=="cls")
|
||||
{
|
||||
system("cls");
|
||||
//windows system("cls");
|
||||
//linux system("clear");
|
||||
//macOS system("clear");
|
||||
}
|
||||
else if(command=="rs")
|
||||
prog.print_file();
|
||||
else if(command=="exit")
|
||||
break;
|
||||
else if(command=="lexer")
|
||||
{
|
||||
lex.scanner(prog.get_resource());
|
||||
lex.print_token_list();
|
||||
}
|
||||
else if(command=="del")
|
||||
{
|
||||
prog.set_clear();
|
||||
lex.set_clear();
|
||||
std::cout<<">>[Delete] Complete."<<std::endl;
|
||||
}
|
||||
else if(command=="parser")
|
||||
{
|
||||
lex.scanner(prog.get_resource());
|
||||
lex.generate_detail_token();
|
||||
if(!lex.get_error())
|
||||
{
|
||||
pas.get_detail_token_stream(lex.get_detail_token());
|
||||
pas.print_parse_stack();
|
||||
pas.parse_main();
|
||||
}
|
||||
else
|
||||
std::cout<<">>[Lexer] error(s) found,stop."<<std::endl;
|
||||
}
|
||||
else if(command=="ast")
|
||||
{
|
||||
lex.scanner(prog.get_resource());
|
||||
lex.generate_detail_token();
|
||||
if(!lex.get_error())
|
||||
{
|
||||
pas.get_detail_token_stream(lex.get_detail_token());
|
||||
pas.parse_main();
|
||||
if(!pas.get_error())
|
||||
pas.print_generated_tree();
|
||||
else
|
||||
std::cout<<">>[Parse] error(s) found,stop."<<std::endl;
|
||||
}
|
||||
else
|
||||
std::cout<<">>[Lexer] error(s) found,stop."<<std::endl;
|
||||
}
|
||||
else if(command=="run")
|
||||
{
|
||||
lex.scanner(prog.get_resource());
|
||||
lex.generate_detail_token();
|
||||
if(!lex.get_error())
|
||||
{
|
||||
pas.get_detail_token_stream(lex.get_detail_token());
|
||||
pas.parse_main();
|
||||
if(!pas.get_error())
|
||||
pas.run_tree();
|
||||
else
|
||||
std::cout<<">>[Parse] error(s) found,stop."<<std::endl;
|
||||
}
|
||||
else
|
||||
std::cout<<">>[Lexer] error(s) found,stop."<<std::endl;
|
||||
}
|
||||
else
|
||||
prog.input_file(command);
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue