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<<">> [ast ] check the abstract syntax tree."<<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;
}
else if(command=="cls")
@ -117,6 +118,16 @@ int main()
else
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")
break;
else

View File

@ -159,7 +159,14 @@ enum parse_error_type
lack_right_curve, // lack right curve
parameter_lack_part, // parameter lack a ')' or identifier
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)
@ -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;
case call_hash_lack_id:
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:
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 generation
bool check_comma_in_curve();
void main_generate();
abstract_syntax_tree calculation();
abstract_syntax_tree and_calculation();
@ -32,6 +33,8 @@ class nasal_parse
abstract_syntax_tree function_generate();
abstract_syntax_tree var_outside_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 choose_expr();
};
@ -135,6 +138,25 @@ abstract_syntax_tree& nasal_parse::get_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()
{
error=0;
@ -155,11 +177,38 @@ void nasal_parse::main_generate()
break;
case __nor_operator: case __sub_operator:
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:
this->push_token();
root.add_children(calculation());
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:
this->push_token();
root.add_children(choose_expr());
@ -299,21 +348,10 @@ abstract_syntax_tree nasal_parse::scalar_generate()
switch(this_token.type)
{
case __number:
scalar_node.set_node_type(__number);
scalar_node.set_var_number(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 __number:scalar_node.set_node_type(__number);scalar_node.set_var_number(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:
scalar_node=calculation();
this->get_token();
@ -359,7 +397,21 @@ abstract_syntax_tree nasal_parse::scalar_generate()
}
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)
{
@ -370,11 +422,11 @@ abstract_syntax_tree nasal_parse::scalar_generate()
print_parse_error(call_hash_lack_id,this_token.line);
break;
}
abstract_syntax_tree identifier_node;
identifier_node.set_node_line(this_token.line);
identifier_node.set_node_type(__call_hash);
identifier_node.set_var_name(this_token.str);
scalar_node.add_children(identifier_node);
abstract_syntax_tree call_hash_node;
call_hash_node.set_node_line(this_token.line);
call_hash_node.set_node_type(__call_hash);
call_hash_node.set_var_name(this_token.str);
scalar_node.add_children(call_hash_node);
}
this->get_token();
}
@ -388,6 +440,48 @@ abstract_syntax_tree nasal_parse::hash_generate()
abstract_syntax_tree hash_node;
hash_node.set_node_line(this_token.line);
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;
}
@ -397,6 +491,22 @@ abstract_syntax_tree nasal_parse::vector_generate()
abstract_syntax_tree vector_node;
vector_node.set_node_line(this_token.line);
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;
}
@ -558,6 +668,22 @@ abstract_syntax_tree nasal_parse::var_inside_definition()
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 loop_main_node;

View File

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

View File

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