This commit is contained in:
Valk Richard Li 2020-01-18 19:34:15 +08:00 committed by GitHub
parent 0e5ce8d7fa
commit 4c966af52e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 210 additions and 40 deletions

View File

@ -26,6 +26,7 @@ int main()
std::cout<<">> [par ] turn tokens into abstract syntax tree."<<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<<">> [ast ] check the abstract syntax tree."<<std::endl;
std::cout<<">> [run ] run code."<<std::endl; std::cout<<">> [run ] run code."<<std::endl;
std::cout<<">> [info ] print lexer,parser and ast on screen."<<std::endl;
std::cout<<">> [exit ] quit nasal interpreter."<<std::endl; std::cout<<">> [exit ] quit nasal interpreter."<<std::endl;
} }
else if(command=="cls") else if(command=="cls")
@ -117,6 +118,16 @@ int main()
else else
std::cout<<">>[Lexer] error occurred,stop."<<std::endl; std::cout<<">>[Lexer] error occurred,stop."<<std::endl;
} }
else if(command=="info")
{
lexer.scanner(resource.get_source());
lexer.print_token_list();
lexer.generate_detail_token();
parser.get_token_list(lexer.get_detail_token_list());
parser.print_detail_token();
parser.main_generate();
parser.get_root().print_tree(1);
}
else if(command=="exit") else if(command=="exit")
break; break;
else else

View File

@ -159,7 +159,14 @@ enum parse_error_type
lack_right_curve, // lack right curve lack_right_curve, // lack right curve
parameter_lack_part, // parameter lack a ')' or identifier parameter_lack_part, // parameter lack a ')' or identifier
parameter_lack_curve, // parameter lack a ',' or ')' parameter_lack_curve, // parameter lack a ',' or ')'
call_hash_lack_id, // lack identifier when calling an identifier
call_hash_lack_id, // lack identifier when calling a hash
call_vector_lack_bracket, // lack ']' when calling a vector
vector_gen_lack_end, // lack ',' or ')' when generating a vector
hash_gen_lack_id, // lack identifier or string when generating a hash
hash_gen_lack_colon, // lack ':' when generating a hash
hash_gen_lack_end, // lack ',' or '}' when generating a hash
}; };
void print_parse_error(int error_type,int line,int error_token_type=__stack_end) void print_parse_error(int error_type,int line,int error_token_type=__stack_end)
@ -198,6 +205,31 @@ void print_parse_error(int error_type,int line,int error_token_type=__stack_end)
std::cout<<error_info_head<<line<<": expect a \')\' or \',\' here."<<std::endl;break; std::cout<<error_info_head<<line<<": expect a \')\' or \',\' here."<<std::endl;break;
case call_hash_lack_id: case call_hash_lack_id:
std::cout<<error_info_head<<line<<": expect an identifier after \'.\' ."<<std::endl;break; std::cout<<error_info_head<<line<<": expect an identifier after \'.\' ."<<std::endl;break;
case call_vector_lack_bracket:
std::cout<<error_info_head<<line<<": expect a \']\' here but get \'";
print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl;
break;
case vector_gen_lack_end:
std::cout<<error_info_head<<line<<": expect a \',\' or \')\' here but get \'";
print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl;
break;
case hash_gen_lack_id:
std::cout<<error_info_head<<line<<": expect an identifier or string here but get \'";
print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl;
break;
case hash_gen_lack_colon:
std::cout<<error_info_head<<line<<": expect a \':\' here but get \'";
print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl;
break;
case hash_gen_lack_end:
std::cout<<error_info_head<<line<<": expect a \',\' or \'}\' here but get \'";
print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl;
break;
default: default:
std::cout<<error_info_head<<line<<": unknown parse error. error id: other_type."<<std::endl;break; std::cout<<error_info_head<<line<<": unknown parse error. error id: other_type."<<std::endl;break;
} }

View File

@ -20,6 +20,7 @@ class nasal_parse
abstract_syntax_tree& get_root(); abstract_syntax_tree& get_root();
// abstract_syntax_tree generation // abstract_syntax_tree generation
bool check_comma_in_curve();
void main_generate(); void main_generate();
abstract_syntax_tree calculation(); abstract_syntax_tree calculation();
abstract_syntax_tree and_calculation(); abstract_syntax_tree and_calculation();
@ -32,6 +33,8 @@ class nasal_parse
abstract_syntax_tree function_generate(); abstract_syntax_tree function_generate();
abstract_syntax_tree var_outside_definition(); abstract_syntax_tree var_outside_definition();
abstract_syntax_tree var_inside_definition(); abstract_syntax_tree var_inside_definition();
abstract_syntax_tree normal_assignment();
abstract_syntax_tree in_curve_assignment();
abstract_syntax_tree loop_expr(); abstract_syntax_tree loop_expr();
abstract_syntax_tree choose_expr(); abstract_syntax_tree choose_expr();
}; };
@ -135,6 +138,25 @@ abstract_syntax_tree& nasal_parse::get_root()
return root; return root;
} }
bool nasal_parse::check_comma_in_curve()
{
bool ret=false;
int cnt=0;
while(this_token.type!=__right_curve)
{
++cnt;
this->get_token();
if(this_token.type==__comma)
{
ret=true;
break;
}
}
for(int i=0;i<cnt;++i)
this->push_token();
return ret;
}
void nasal_parse::main_generate() void nasal_parse::main_generate()
{ {
error=0; error=0;
@ -155,11 +177,38 @@ void nasal_parse::main_generate()
break; break;
case __nor_operator: case __sub_operator: case __nor_operator: case __sub_operator:
case __number: case __nil: case __string: case __id: case __number: case __nil: case __string: case __id:
case __left_curve: case __left_bracket: case __left_brace: case __left_bracket: case __left_brace:
case __func: case __func:
this->push_token(); this->push_token();
root.add_children(calculation()); root.add_children(calculation());
break; break;
case __left_curve:
this->push_token();
if(check_comma_in_curve())
{
this->get_token();// get '('
this->get_token();// check if there is a 'var'
if(this_token.type==__var)
{
this->push_token();
this->push_token();
root.add_children(var_inside_definition());
}
else
{
this->push_token();
this->push_token();
root.add_children(in_curve_assignment());
}
}
else
root.add_children(calculation());
// '(' is the beginning of too many statements
// '(' var id,id,id ')'
// '(' calculation ')'
// '(' scalar,scalar,scalar ')' '=' '(' scalar,scalar,scalar ')'
// but these statements can be distinguished by commas in them
break;
case __if: case __if:
this->push_token(); this->push_token();
root.add_children(choose_expr()); root.add_children(choose_expr());
@ -299,21 +348,10 @@ abstract_syntax_tree nasal_parse::scalar_generate()
switch(this_token.type) switch(this_token.type)
{ {
case __number: case __number:scalar_node.set_node_type(__number);scalar_node.set_var_number(this_token.str);break;
scalar_node.set_node_type(__number); case __string:scalar_node.set_node_type(__string);scalar_node.set_var_string(this_token.str);break;
scalar_node.set_var_number(this_token.str); case __nil:scalar_node.set_node_type(__nil);break;
break; case __id:scalar_node.set_node_type(__id);scalar_node.set_var_name(this_token.str);break;
case __string:
scalar_node.set_node_type(__string);
scalar_node.set_var_string(this_token.str);
break;
case __nil:
scalar_node.set_node_type(__nil);
break;
case __id:
scalar_node.set_node_type(__id);
scalar_node.set_var_name(this_token.str);
break;
case __left_curve: case __left_curve:
scalar_node=calculation(); scalar_node=calculation();
this->get_token(); this->get_token();
@ -359,7 +397,21 @@ abstract_syntax_tree nasal_parse::scalar_generate()
} }
else if(this_token.type==__left_bracket) else if(this_token.type==__left_bracket)
{ {
abstract_syntax_tree call_vector_node;
call_vector_node.set_node_line(this_token.line);
call_vector_node.set_node_type(__call_vector);
// call_vector_node.add_children(calculation());
// this->get_token();
// if(this_token.type==__colon)
// calculation();
// else
// this->push_token();
this->get_token();
if(this_token.type!=__right_bracket)
{
++error;
print_parse_error(call_vector_lack_bracket,this_token.line,this_token.type);
}
} }
else if(this_token.type==__dot) else if(this_token.type==__dot)
{ {
@ -370,11 +422,11 @@ abstract_syntax_tree nasal_parse::scalar_generate()
print_parse_error(call_hash_lack_id,this_token.line); print_parse_error(call_hash_lack_id,this_token.line);
break; break;
} }
abstract_syntax_tree identifier_node; abstract_syntax_tree call_hash_node;
identifier_node.set_node_line(this_token.line); call_hash_node.set_node_line(this_token.line);
identifier_node.set_node_type(__call_hash); call_hash_node.set_node_type(__call_hash);
identifier_node.set_var_name(this_token.str); call_hash_node.set_var_name(this_token.str);
scalar_node.add_children(identifier_node); scalar_node.add_children(call_hash_node);
} }
this->get_token(); this->get_token();
} }
@ -388,6 +440,48 @@ abstract_syntax_tree nasal_parse::hash_generate()
abstract_syntax_tree hash_node; abstract_syntax_tree hash_node;
hash_node.set_node_line(this_token.line); hash_node.set_node_line(this_token.line);
hash_node.set_node_type(__hash); hash_node.set_node_type(__hash);
this->get_token();
if(this_token.type!=__right_brace)
{
this->push_token();
while(this_token.type!=__right_brace)
{
abstract_syntax_tree hash_member_node;
this->get_token();
hash_member_node.set_node_line(this_token.line);
hash_member_node.set_node_type(__hash_member);
if(this_token.type==__id || this_token.type==__string)
{
abstract_syntax_tree member_id;
member_id.set_node_line(this_token.line);
member_id.set_node_type(__id);
member_id.set_var_name(this_token.str);
hash_member_node.add_children(member_id);
}
else
{
++error;
print_parse_error(hash_gen_lack_id,this_token.line,this_token.type);
break;
}
this->get_token();
if(this_token.type!=__colon)
{
++error;
print_parse_error(hash_gen_lack_colon,this_token.line,this_token.type);
break;
}
hash_member_node.add_children(calculation());
this->get_token();
if(this_token.type!=__comma && this_token.type!=__right_brace)
{
++error;
print_parse_error(hash_gen_lack_end,this_token.line,this_token.type);
break;
}
hash_node.add_children(hash_member_node);
}
}
return hash_node; return hash_node;
} }
@ -397,6 +491,22 @@ abstract_syntax_tree nasal_parse::vector_generate()
abstract_syntax_tree vector_node; abstract_syntax_tree vector_node;
vector_node.set_node_line(this_token.line); vector_node.set_node_line(this_token.line);
vector_node.set_node_type(__vector); vector_node.set_node_type(__vector);
this->get_token();
if(this_token.type!=__right_bracket)
{
this->push_token();
while(this_token.type!=__right_bracket)
{
vector_node.add_children(calculation());
this->get_token();
if(this_token.type!=__comma && this_token.type!=__right_bracket)
{
++error;
print_parse_error(vector_gen_lack_end,this_token.line,this_token.type);
break;
}
}
}
return vector_node; return vector_node;
} }
@ -558,6 +668,22 @@ abstract_syntax_tree nasal_parse::var_inside_definition()
return var_inside_definition_node; return var_inside_definition_node;
} }
abstract_syntax_tree nasal_parse::normal_assignment()
{
abstract_syntax_tree assign_node;
assign_node.set_node_type(__assignment);
return assign_node;
}
abstract_syntax_tree nasal_parse::in_curve_assignment()
{
abstract_syntax_tree assign_node;
this->get_token(); // get '('
assign_node.set_node_line(this_token.line);
assign_node.set_node_type(__assignment);
return assign_node;
}
abstract_syntax_tree nasal_parse::loop_expr() abstract_syntax_tree nasal_parse::loop_expr()
{ {
abstract_syntax_tree loop_main_node; abstract_syntax_tree loop_main_node;

View File

@ -29,7 +29,7 @@
| '(' <calculation> ')' | '(' <calculation> ')'
| <scalar> { ('[' {<calculation> ','} ']') | ('[' <calculation> ':' [<calculation>] ']') | ('.' <id>) | ('(' {<calculation> ','} ')') | ('(' {<id> ':' <calculation> ','} ')') } | <scalar> { ('[' {<calculation> ','} ']') | ('[' <calculation> ':' [<calculation>] ']') | ('.' <id>) | ('(' {<calculation> ','} ')') | ('(' {<id> ':' <calculation> ','} ')') }
; ;
0
<function> = <function> =
<func> ['(' ')'] <statement> <func> ['(' ')'] <statement>
| <func> ['(' ')'] '{' {<statement> ';'} '}' | <func> ['(' ')'] '{' {<statement> ';'} '}'
@ -56,14 +56,14 @@
| '(' <var> {(<id>) | (<call_identifier>) ','} ')' '=' (<scalar> | '(' {<scalar> ','} ')') | '(' <var> {(<id>) | (<call_identifier>) ','} ')' '=' (<scalar> | '(' {<scalar> ','} ')')
; ;
<forindex_loop_definition> = <forindex_loop_definition> =
<var> <id>
; ;
<foreach_loop_definition> = <foreach_loop_definition> =
<var> <id> <var> <id>
; ;
<assignment> = <assignment> =
<call_identifier> '=' <scalar> <scalar> '=' <calculation>
| '(' {<call_identifier> ','} ')' '=' (<scalar> | '(' {<scalar> ','} ')') | '(' {<scalar> ','} ')' '=' (<calculation> | '(' {<calculation> ','} ')')
; ;
<loop_expr> = <loop_expr> =
<for_loop> <for_loop>
@ -72,12 +72,12 @@
| <foreach_loop> | <foreach_loop>
; ;
<for_loop> = <for_loop> =
<for> '(' [<statement>] ';' [<scalar>] ';' <statement> ')' <statement> [';'] <for> '(' [<statement>] ';' [<calculation>] ';' [<statement>] ')' <statement> [';']
| <for> '(' [<statement>] ';' [<scalar>] ';' <statement> ')' '{' {<statement> ';'} '}' | <for> '(' [<statement>] ';' [<calculation>] ';' [<statement>] ')' '{' {<statement> ';'} '}'
; ;
<while_loop> = <while_loop> =
<while> '(' <scalar> ')' <statement> [';'] <while> '(' <calculation> ')' <statement> [';']
| <while> '(' <scalar> ')' '{' {<statement> ';'} '}' | <while> '(' <calculation> ')' '{' {<statement> ';'} '}'
; ;
(* in forindex and foreach the scalar and definition cannot be lacked*) (* in forindex and foreach the scalar and definition cannot be lacked*)
<forindex_loop> = <forindex_loop> =
@ -92,14 +92,14 @@
<choose_expr> = <choose_expr_if> {<choose_expr_elsif>} [<choose_expr_else>] <choose_expr> = <choose_expr_if> {<choose_expr_elsif>} [<choose_expr_else>]
; ;
<choose_expr_if> = <choose_expr_if> =
<if> '(' <scalar> ')' <statement> [';'] <if> '(' <calculation> ')' <statement> [';']
| <if> '(' <scalar> ')' '{' {<statement> ';'} '}' | <if> '(' <calculation> ')' '{' {<statement> ';'} '}'
; ;
<choose_expr_elsif> = <choose_expr_elsif> =
<elsif> '(' <scalar> ')' <statement> [';'] <elsif> '(' <calculation> ')' <statement> [';']
| <elsif> '(' <scalar> ')' '{' {<statement> ';'} '}' | <elsif> '(' <calculation> ')' '{' {<statement> ';'} '}'
| <else> <if> '(' <scalar> ')' <statement> [';'] | <else> <if> '(' <calculation> ')' <statement> [';']
| <else> <if> '(' <scalar> ')' '{' {<statement> ';'} '}' | <else> <if> '(' <calculation> ')' '{' {<statement> ';'} '}'
; ;
<choose_expr_else> = <choose_expr_else> =
<else> <statement> [';'] <else> <statement> [';']

View File

@ -11,9 +11,10 @@ nil;
-((30)); -((30));
[]; [];
{}; {};
[0,1,2,3,4,5][2]; # 2 [0,1,2,3,4,5][2]; # 2
{str:"hello"}.str; # "hello" {str:"hello"}.str; # "hello"
{str:"hello"}["str"]; # "hello" {str:"hello"}["str"]; # "hello"
{"str":"hello"}["str"]; # "hello"
# normal scalar # normal scalar
var number_1=1; var number_1=1;