finish value search

This commit is contained in:
Valk Richard Li 2019-11-13 23:36:54 +08:00 committed by GitHub
parent 85310cf2dd
commit d3d162a83f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 2552 additions and 0 deletions

757
abstract_syntax_tree.cpp Normal file
View File

@ -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

214
abstract_syntax_tree.h Normal file
View File

@ -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

22
balloon.h Normal file
View File

@ -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

988
balloon_parse.h Normal file
View File

@ -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

111
balloon_scope.h Normal file
View File

@ -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

174
balloon_type.h Normal file
View File

@ -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

186
balloon_var.h Normal file
View File

@ -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

100
main.cpp Normal file
View File

@ -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;
}