From 6aef19ce7a322dd27ffc0ad22a7df746e93e2555 Mon Sep 17 00:00:00 2001 From: Valk Richard Li <48872266+ValKmjolnir@users.noreply.github.com> Date: Tue, 12 Nov 2019 23:23:42 +0800 Subject: [PATCH] update --- balloon/abstract_syntax_tree.cpp | 439 +++++++++++++++++++++++++++++-- balloon/abstract_syntax_tree.h | 8 +- balloon/balloon.h | 2 + balloon/balloon_parse.h | 2 +- balloon/balloon_type.h | 6 +- balloon/balloon_var.h | 42 ++- balloon/var.txt | 7 +- 7 files changed, 469 insertions(+), 37 deletions(-) diff --git a/balloon/abstract_syntax_tree.cpp b/balloon/abstract_syntax_tree.cpp index bf79a5a..088bbdf 100644 --- a/balloon/abstract_syntax_tree.cpp +++ b/balloon/abstract_syntax_tree.cpp @@ -1,63 +1,398 @@ #ifndef __ABSTRACT_SYNTAX_TREE_CPP__ #define __ABSTRACT_SYNTAX_TREE_CPP__ #include "abstract_syntax_tree.h" -int exit_type=0; -var abstract_syntax_tree::condition() + +int exit_type=0; +std::stack ret_stack;// for function ret use + +var abstract_syntax_tree::calculation() { - var cond; - cond.set_number(0); - if(this->type==__cmp_equal) + 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; + } + 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] must use a number to use \'!\' but use \'"; + print_scalar(temp.get_type()); + std::cout<<"\'."<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] 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<<"\'."<type==__sub_operator) + { + temp.set_type(__var_number); + std::list::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] must use a number to use \'-\' but use \'"; + print_scalar(temp.get_type()); + std::cout<<"\'."<>[Runtime-error] 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<<"\'."<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] 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<<"\'."<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] get number \'NaN\' or \'Inf\'."<>[Runtime-error] 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<<"\'."<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] 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<<"\'."<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] must use number or string to use \'==\' but use \'"; + print_scalar(left_child.get_type()); + std::cout<<"\'."<>[Runtime-error] 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<<"\'."<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] must use number or string to use \'!=\' but use \'"; + print_scalar(left_child.get_type()); + std::cout<<"\'."<>[Runtime-error] 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<<"\'."<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()>[Runtime-error] must use number or string to use \'<\' but use \'"; + print_scalar(left_child.get_type()); + std::cout<<"\'."<>[Runtime-error] 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<<"\'."<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] must use number or string to use \'>\' but use \'"; + print_scalar(left_child.get_type()); + std::cout<<"\'."<>[Runtime-error] 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<<"\'."<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] must use number or string to use \'<=\' but use \'"; + print_scalar(left_child.get_type()); + std::cout<<"\'."<>[Runtime-error] 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<<"\'."<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] must use number or string to use \'>=\' but use \'"; + print_scalar(left_child.get_type()); + std::cout<<"\'."<>[Runtime-error] 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<<"\'."<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] 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<<"\'."<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] 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<<"\'."<>[Runtime-error] error type occurred when doing calculation."<>[Runtime-error] must use a number to make a choice but use \'"; + print_scalar(temp.get_type()); + std::cout<<"\'."<::iterator i=children.begin();i!=children.end();++i) + { + + } } return temp; } @@ -80,7 +418,7 @@ var abstract_syntax_tree::get_value() var temp; temp.set_type(type); if(type==__id) - temp=call_id(); + temp=call_identifier(); else if(type==__number) temp.set_number(number); else if(type==__string) @@ -115,6 +453,7 @@ var abstract_syntax_tree::get_value() } 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; @@ -141,12 +480,24 @@ void abstract_syntax_tree::run_root() 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<type==__number) std::cout<number<type==__string) std::cout<str<type==__id) - std::cout<call_id().get_name()<call_identifier().get_name()<type==__while) { scope.add_new_block_scope(); @@ -178,7 +529,7 @@ int abstract_syntax_tree::run_loop() abstract_syntax_tree condition=children.front(); abstract_syntax_tree blk=children.back(); - while(condition.check()) + while(condition.condition_check()) { int type=blk.run_block(); if(type==__break) @@ -199,7 +550,12 @@ int abstract_syntax_tree::run_ifelse() scope.add_new_local_scope(); for(std::list::iterator i=children.begin();i!=children.end();++i) { - if(i->children.front().check()) + if(i->type!=__else && i->children.front().condition_check()) + { + ret=i->children.back().run_block(); + break; + } + else { ret=i->children.back().run_block(); break; @@ -209,13 +565,17 @@ int abstract_syntax_tree::run_ifelse() return ret; } -void abstract_syntax_tree::run_func() +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(); - return; + ret=ret_stack.top(); + ret_stack.pop(); + return ret; } int abstract_syntax_tree::run_block() @@ -248,7 +608,19 @@ int abstract_syntax_tree::run_block() else if(i->type==__string) std::cout<str<type==__id) - std::cout<call_id().get_name()<call_identifier().get_name()<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<type==__while) { int type=i->run_loop(); @@ -274,7 +646,16 @@ int abstract_syntax_tree::run_block() else if(i->type==__break) return __break; else if(i->type==__return) + { + var temp; + temp.set_type(__null_type); + if(!(i->children.empty())) + { + + } + ret_stack.push(temp); return __return; + } if(exit_type!=__process_exited_successfully) break; } diff --git a/balloon/abstract_syntax_tree.h b/balloon/abstract_syntax_tree.h index 493ff92..ba998c2 100644 --- a/balloon/abstract_syntax_tree.h +++ b/balloon/abstract_syntax_tree.h @@ -184,14 +184,14 @@ class abstract_syntax_tree { return children; } - var condition(); - bool check(); - var call_id(); + var calculation(); + bool condition_check(); + var call_identifier(); var get_value(); void run_root(); int run_loop(); int run_ifelse(); - void run_func(); + var run_func(); int run_block(); }; diff --git a/balloon/balloon.h b/balloon/balloon.h index ad4e6bc..e9d6efa 100644 --- a/balloon/balloon.h +++ b/balloon/balloon.h @@ -2,8 +2,10 @@ #define __BALLOON_H__ #include +#include #include #include +#include #include #include #include diff --git a/balloon/balloon_parse.h b/balloon/balloon_parse.h index 3bb762c..77923e4 100644 --- a/balloon/balloon_parse.h +++ b/balloon/balloon_parse.h @@ -654,7 +654,7 @@ abstract_syntax_tree balloon_parse::call_identifier() parse.push(this_token); temp=new_node; new_node=assignment(); - new_node.add_child(temp); + new_node.get_children().push_front(temp); } else parse.push(this_token); diff --git a/balloon/balloon_type.h b/balloon/balloon_type.h index 34f4263..7e9041c 100644 --- a/balloon/balloon_type.h +++ b/balloon/balloon_type.h @@ -145,7 +145,9 @@ enum runtime_error_type __get_value_failure, __find_var_failure, __error_value_type, - __error_command_use + __error_command_use, + __sigfpe_arithmetic_exception, + __sigsegv_segmentation_error }; void print_exit_type(int type) @@ -159,6 +161,8 @@ void print_exit_type(int type) 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; default: context="unknown";break; } std::cout<>[Runtime-error] overflow when searching member "<<_place<<" but the max size of array \'"<::iterator i=balloon_hash.begin();i!=balloon_hash.end();++i) @@ -138,6 +177,7 @@ var& var::get_hash_member(std::string _name) std::cout<<">>[Runtime-error] hash \'"<