This commit is contained in:
Valk Richard Li 2019-11-05 13:22:45 +08:00 committed by GitHub
parent 46f1199a8a
commit ee70ca81af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 671 additions and 0 deletions

581
balloon_parse.h Normal file
View File

@ -0,0 +1,581 @@
#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 definition();
void assignment();
void array_generate();
void hash_generate();
void check_number();
void check_string();
void check_unary();
void block();
void func_generate();
void call_identifier();
void calculation();
void calculation_or();
void calculation_and();
void calculation_cmp();
void calculation_additive();
void calculation_multive();
void scalar();
void check_semi();
void parse_main();
};
void balloon_parse::definition()
{
get_token();
if(this_token.type!=__var)
{
++error;
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \'var\' here."<<std::endl;
return;
}
get_token();
if(this_token.type!=__id)
{
++error;
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect an identifier here."<<std::endl;
return;
}
get_token();
if(this_token.type!=__equal)
{
++error;
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \'=\' here."<<std::endl;
return;
}
scalar();
return;
}
void balloon_parse::assignment()
{
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;
}
scalar();
return;
}
void balloon_parse::array_generate()
{
get_token();
if(this_token.type!=__left_bracket)
{
++error;
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \'[\' here."<<std::endl;
return;
}
get_token();
if(this_token.type!=__right_bracket)
parse.push(this_token);
while(this_token.type!=__right_bracket)
{
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);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;
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;
}
}
return;
}
void balloon_parse::hash_generate()
{
get_token();
if(this_token.type!=__left_brace)
{
++error;
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \'{\' here."<<std::endl;
return;
}
get_token();
if(this_token.type!=__right_brace)
parse.push(this_token);
while(this_token.type!=__right_brace)
{
get_token();
if(this_token.type!=__id)
{
++error;
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect an identifier here."<<std::endl;
return;
}
get_token();
if(this_token.type!=__colon)
{
++error;
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \':\' here."<<std::endl;
return;
}
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);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;
break;
}
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;
}
}
return;
}
void balloon_parse::check_number()
{
get_token();
if(this_token.type!=__number)
{
++error;
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a number here."<<std::endl;
}
return;
}
void balloon_parse::check_string()
{
get_token();
if(this_token.type!=__string)
{
++error;
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a string here."<<std::endl;
}
return;
}
void balloon_parse::check_unary()
{
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;
}
get_token();
switch(this_token.type)
{
case __number:parse.push(this_token);check_number();break;
case __string:parse.push(this_token);check_string();break;
case __id:parse.push(this_token);call_identifier();break;
case __left_curve:parse.push(this_token);scalar();break;
case __nor_operator:parse.push(this_token);check_unary();break;
default:++error;std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a scalar here."<<std::endl;break;
}
return;
}
void balloon_parse::block()
{
get_token();
if(this_token.type!=__left_brace)
{
++error;
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \'{\' ."<<std::endl;
return;
}
while(this_token.type!=__right_brace)
{
get_token();
switch(this_token.type)
{
case __continue:
case __break:check_semi();break;
case __right_brace:break;
}
}
return;
}
void balloon_parse::func_generate()
{
get_token();
if(this_token.type!=__func)
{
++error;
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \'func\' here."<<std::endl;
return;
}
get_token();
if(this_token.type==__left_curve)
{
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;
}
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;
}
}
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;
}
}
}
}
else
parse.push(this_token);
block();
return;
}
void balloon_parse::call_identifier()
{
get_token();
if(this_token.type!=__id)
{
++error;
std::cout<<">>[Parse-error] line "<<this_token.line<<": must have an identifier here."<<std::endl;
return;
}
while(1)
{
get_token();
if(this_token.type==__left_curve)
{
while(this_token.type!=__right_curve)
{
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;
}
}
}
else if(this_token.type==__left_bracket)
{
scalar();
get_token();
if(this_token.type!=__right_bracket)
{
++error;
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \']\' ."<<std::endl;
return;
}
}
else if(this_token.type==__dot)
call_identifier();
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);
assignment();
}
else
parse.push(this_token);
return;
}
void balloon_parse::calculation()
{
calculation_or();
return;
}
void balloon_parse::calculation_or()
{
while(1)
{
calculation_and();
get_token();
if(this_token.type!=__or_operator)
{
parse.push(this_token);
break;
}
}
return;
}
void balloon_parse::calculation_and()
{
while(1)
{
calculation_cmp();
get_token();
if(this_token.type!=__and_operator)
{
parse.push(this_token);
break;
}
}
return;
}
void balloon_parse::calculation_cmp()
{
while(1)
{
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);
break;
}
}
}
void balloon_parse::calculation_additive()
{
while(1)
{
calculation_multive();
get_token();
if(this_token.type!=__add_operator && this_token.type!=__sub_operator && this_token.type!=__link_operator)
{
parse.push(this_token);
break;
}
}
return;
}
void balloon_parse::calculation_multive()
{
while(1)
{
get_token();
switch(this_token.type)
{
case __left_curve:
scalar();get_token();
if(this_token.type!=__right_curve)
{
++error;
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a \')\' here."<<std::endl;
return;
}
break;
case __number:parse.push(this_token);check_number();break;
case __string:parse.push(this_token);check_string();break;
case __id:parse.push(this_token);call_identifier();break;
case __nor_operator:
case __sub_operator:parse.push(this_token);check_unary();break;
default:
++error;
std::cout<<">>[Parse-error] line "<<this_token.line<<": expect a scalar here."<<std::endl;
return;
break;
}
get_token();
if(this_token.type!=__mul_operator && this_token.type!=__div_operator)
{
parse.push(this_token);
break;
}
}
return;
}
void balloon_parse::scalar()
{
get_token();
switch(this_token.type)
{
case __func:parse.push(this_token);func_generate();break;
case __left_bracket:parse.push(this_token);array_generate();break;
case __left_brace:parse.push(this_token);hash_generate();break;
case __left_curve:
case __nor_operator:
case __sub_operator:
case __number:
case __string:
case __id:parse.push(this_token);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;
}
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_type(__root);
error=0;
warning=0;
while(!parse.empty())
{
get_token();
switch(this_token.type)
{
case __var:parse.push(this_token);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);scalar();check_semi();break;
case __if:parse.push(this_token);break;
case __while:parse.push(this_token);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

90
main.cpp Normal file
View File

@ -0,0 +1,90 @@
#include "balloon.h"
int main()
{
resource_file prog;
balloon_lexer lex;
balloon_parse pas;
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();
}
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();
}
else
std::cout<<">>[Lexer] error(s) found,stop."<<std::endl;
}
else
prog.input_file(command);
}
return 0;
}