This commit is contained in:
Valk Richard Li 2020-01-10 22:00:55 +08:00 committed by GitHub
parent 1dc355a722
commit e989eca0c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 113 additions and 11 deletions

View File

@ -119,7 +119,10 @@ void abstract_syntax_tree::set_type(const int __type)
void abstract_syntax_tree::set_line(const int __line)
{
line=__line;
if(__line>=0)
line=__line;
else
line=0;
return;
}
@ -143,6 +146,9 @@ void abstract_syntax_tree::set_name(std::string __str)
void abstract_syntax_tree::add_child(abstract_syntax_tree p)
{
// use abstract_syntax_tree instead of abstract_syntax_tree&
// because when this function get a 'p' from returned value of
// another function,this may result in s SIGSEGV.
children.push_back(p);
return;
}

View File

@ -22,8 +22,8 @@ int main()
std::cout<<">> [lib ] add lib file."<<std::endl;
std::cout<<">> [rs ] print resource code."<<std::endl;
std::cout<<">> [total ] print resource code with lib code."<<std::endl;
std::cout<<">> [lexer ] turn code into tokens."<<std::endl;
std::cout<<">> [parser] turn tokens into abstract syntax tree."<<std::endl;
std::cout<<">> [lex ] turn code into tokens."<<std::endl;
std::cout<<">> [par ] turn tokens into abstract syntax tree."<<std::endl;
std::cout<<">> [ast ] check the abstract syntax tree."<<std::endl;
std::cout<<">> [run ] run code."<<std::endl;
std::cout<<">> [exit ] quit nasal interpreter."<<std::endl;
@ -61,7 +61,7 @@ int main()
{
resource.print_resource(true);
}
else if(command=="lexer")
else if(command=="lex")
{
lexer.scanner(resource.get_source());
lexer.generate_detail_token();
@ -70,7 +70,7 @@ int main()
else
std::cout<<">>[Lexer] error occurred,stop."<<std::endl;
}
else if(command=="parser")
else if(command=="par")
{
lexer.scanner(resource.get_source());
lexer.generate_detail_token();
@ -99,6 +99,24 @@ int main()
else
std::cout<<">>[Lexer] error occurred,stop."<<std::endl;
}
else if(command=="run")
{
lexer.scanner(resource.get_source());
lexer.generate_detail_token();
if(!lexer.get_error())
{
parser.get_token_list(lexer.get_detail_token_list());
parser.main_generate();
if(!parser.get_error())
{
// run code
}
else
std::cout<<">>[Parse] error occurred,stop."<<std::endl;
}
else
std::cout<<">>[Lexer] error occurred,stop."<<std::endl;
}
else if(command=="exit")
break;
else

View File

@ -25,6 +25,7 @@ void print_lexer_token(int type)
enum parse_token_type
{
__stack_end=1,
__stack_top,
__cmp_equal,__cmp_not_equal,__cmp_less,__cmp_less_or_equal,__cmp_more,__cmp_more_or_equal,
// == != < <= > >=
__and_operator,__or_operator,__nor_operator,__add_operator,__sub_operator,__mul_operator,__div_operator,__link_operator,
@ -62,6 +63,7 @@ void print_parse_token(int type)
switch(type)
{
case __stack_end: context="#"; break;
case __stack_top: context="#"; break;
case __cmp_equal: context="=="; break;
case __cmp_not_equal: context="!="; break;
@ -141,4 +143,30 @@ void print_parse_token(int type)
return;
}
enum parse_error_type
{
parse_unknown_error, // unknown error
error_token_in_main, // when a token should not be the begin of a statement in main
definition_lack_var, // lack 'var' reserve word
definition_lack_id, // lack identifier
};
void print_parse_error(int error_type,int line,int error_token_type=__stack_end)
{
std::string error_info_head=">>[Parse-error] line ";
switch(error_type)
{
case parse_unknown_error: std::cout<<error_info_head<<line<<": unknown parse error. error id: parse_unknown_error."<<std::endl;break;
case error_token_in_main:
std::cout<<error_info_head<<line<<": statements should not begin with \'";
print_parse_token(error_token_type);
std::cout<<"\' in main scope."<<std::endl;
break;
case definition_lack_var: std::cout<<error_info_head<<line<<": expect a \'var\' here."<<std::endl;break;
case definition_lack_id: std::cout<<error_info_head<<line<<": expect identifier(s) after \'var\'."<<std::endl;break;
default: std::cout<<error_info_head<<line<<": unknown parse error. error id: other_type."<<std::endl;break;
}
return;
}
#endif

View File

@ -91,6 +91,7 @@ void nasal_parse::get_token()
{
this_token.type=__stack_end;
this_token.str="__stack_end";
std::cout<<">>[Parse-error] fatal error occurred."<<std::endl;
std::cout<<">>[Parse-error] empty token stack."<<std::endl;
}
return;
@ -105,7 +106,10 @@ void nasal_parse::push_token()
checked_tokens.pop();
}
else
std::cout<<">>[Parse-error] empty checked token stack."<<std::endl;
{
std::cout<<">>[Parse-error] fatal error occurred."<<std::endl;
std::cout<<">>[Parse-error] empty checked-token stack."<<std::endl;
}
return;
}
@ -116,6 +120,7 @@ int nasal_parse::get_error()
abstract_syntax_tree& nasal_parse::get_root()
{
std::cout<<">>[Abstract-syntax-tree] get root address: "<<(&root)<<" ."<<std::endl;
return root;
}
@ -190,6 +195,7 @@ abstract_syntax_tree nasal_parse::var_outside_definition()
abstract_syntax_tree definition_node;
definition_node.set_type(__definition);
this->get_token();
definition_node.set_line(this_token.line);
if(this_token.type!=__var)
{
++error;
@ -215,6 +221,7 @@ abstract_syntax_tree nasal_parse::loop_expr()
abstract_syntax_tree loop_main_node;
loop_main_node.set_type(__loop);
this->get_token();
loop_main_node.set_line(this_token.line);
switch(this_token.type)
{
case __for:
@ -229,6 +236,8 @@ abstract_syntax_tree nasal_parse::choose_expr()
{
abstract_syntax_tree choose_main_node;
choose_main_node.set_type(__ifelse);
this->get_token();
choose_main_node.set_line(this_token.line);
return choose_main_node;
}
#endif

View File

@ -1,3 +1,20 @@
# basic type
nil;
2147483647;
0x7fffffff;
0xdeadbeef;
0o70120327;
"hello world!";
'hello world!';
-12;
!0;
-((30));
[];
{};
[0,1,2,3,4,5][2]; # 2
{str:"hello"}.str; # "hello"
{str:"hello"}["str"]; # "hello"
# normal scalar
var number_1=1;
var number_2=0xdeadbeef;
@ -5,6 +22,7 @@ var number_3=0x13702;
var number_4=0.12341490239423;
var string_1="hello";
var string_2='hello';
var string_3=number_1? 'yes':'no'; # yes
# vector
var vector_1=[];
@ -51,14 +69,18 @@ print(source['member_2']());
print(source.member_2());
var test_func=func{return 1;}
print(func test_func()); # 1
print(test_func()); # 1
print(func test_func); # nothing
print(test_func); # nothing
print(func test_func()); # 1
print(test_func()); # 1
print(func test_func); # nothing
print(test_func); # nothing
print(([0,1,2,3])[1]); # 1
print(({str:"what?"})["str"]); # what?
print(({str:"what?"}).str); # what?
# lambda
(func(x){return x>0? x:0;})(12);
(func{print("hello world");})();
(((func(x){return 1.0/math.exp(x);})))(0);
# flexible definition & assignment
var (r,g,b)=[0x00,0x10,0xff];
@ -67,4 +89,23 @@ var color=[0x00,0x10,0xff];
var (r,g,b)=color;
(var r,g,b)=color;
(r,g,b)=(b,g,r);
(number_1,number_2)=(number_2,number_1);
(number_1,number_2)=(number_2,number_1);
# calculation
1+1;
1+1-2+3-4+5-6;
1+1*8-9/3;
1*(1+2*(3+4*(5+6*(7+8*(9+10/(1+1))))));
((-1*2+9))/7-1;
((({num:2})))["num"]*2*2*2;
((((([0,1,2])[0:2]))[0:2]))[1]-1;
(((((((((((((((((((1+1+2+3+5)+8))+13)))+21))))+34)))))+55))))*89;
number_1*(number_2+number_3)/90-number_4;
(func test_func)()-1;
hash_3.member_3+(func {return {what:"i don't tell you.",case_small:80,case_large:100}})["case_large"]/10;
-1*10+5 or 10-10;
nil and 1+7*8;
(number_1 or number_2) and (number_3 or number_4-number_4*1);
[0,1,4,3,2][4]*2-4+1*2*2*2*2*2/8;
{num:0}.num or {what_is_the_secret_of_universe:42}["what_is_the_secret_of_universe"];
"123"~"456"-123456*2/2;