This commit is contained in:
Valk Richard Li
2020-03-19 18:05:41 +08:00
committed by GitHub
parent 28cc088461
commit c250bfb8d8
5 changed files with 216 additions and 199 deletions
+170 -9
View File
@@ -7,27 +7,64 @@ class nasal_parse
std::stack<token> parse_token_stream;
std::stack<token> checked_tokens;
token this_token;
int error;
int error;
abstract_syntax_tree root;
enum parse_error_type
{
parse_unknown_error=0, // unknown error
error_token_in_main, // when a token should not be the begin of a statement in main
error_token_in_block, // when a token should not be the begin of a statement in block
lack_semi,
lack_id,
lack_left_curve,
lack_right_curve,
lack_right_brace,
definition_lack_id, // lack identifier
definition_lack_equal, // lack '=' when not getting ';'
assignment_begin_error, // assignment begins with more than one identifier_call
multi_definition_need_curve, // lack right curve when generating 'var (id,id,id)'
multi_assignment_need_curve, // lack right curve when generating (scalar,scalar)=(scalar,scalar)
multi_assignment_need_equal, // lack '=' when generating (scalar,scalar)=(scalar,scalar)
error_begin_token_of_scalar, // in scalar_generate()
default_dynamic_parameter, // default parameter should not be dynamic
parameter_lack_part, // parameter lack a ')' or identifier
parameter_lack_curve, // parameter lack a ',' or ')'
special_call_func_lack_id,
special_call_func_lack_colon,
call_func_lack_comma, // lack comma when giving parameters to a function
call_hash_lack_id, // lack identifier when calling a hash
call_vector_wrong_comma, // wrong use of comma like this: id[0,4:6,7,] (the last comma is incorrect here)
call_vector_lack_bracket, // lack ']' when calling a vector
call_vector_wrong_token, // get wrong token 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
ternary_operator_lack_colon, // lack ':'
};
void print_parse_error(int,int,int);
// most important function of parser
// these two functions are used to get and push token
// by using them,parser can generate ast
void get_token();
void push_token();
// block statements generation
abstract_syntax_tree block_generate();
// check ';'
void check_semi();
// check '(' confliction
bool check_multi_assignment();// check multi_call_id '=' multi_scalar
bool check_multi_scalar(); // check multi_scalar
bool check_var_in_curve(); // check multi_definition: (var id,id,id)
bool check_function_end(abstract_syntax_tree&); // check end of definition or '=' is a function
/*
calculation() will get elements generated by and_calculation()
and_calculation() will get elements generated by or_calculation()
@@ -48,14 +85,13 @@ class nasal_parse
abstract_syntax_tree additive_calculation();
abstract_syntax_tree multive_calculation();
abstract_syntax_tree scalar_generate();
// normal data type generation
abstract_syntax_tree hash_generate();
abstract_syntax_tree vector_generate();
abstract_syntax_tree function_generate();
// return_expr() generates ebnf: <return> [<calculation>] ';'
abstract_syntax_tree return_expr();
// normal expressions
abstract_syntax_tree multi_scalar_assignment();
abstract_syntax_tree definition();
abstract_syntax_tree loop_expr();
@@ -74,9 +110,8 @@ class nasal_parse
}
void print_detail_token();
void get_token_list(std::list<token>&);
int get_error();
int get_error();
abstract_syntax_tree& get_root();
// abstract_syntax_tree generation
// main process of parser
void main_generate();
@@ -114,6 +149,8 @@ void nasal_parse::print_detail_token()
void nasal_parse::get_token_list(std::list<token>& detail_token_stream)
{
// get detail_token_stream from lexer
// clear the parse_token_stream and checked_tokens list
while(!parse_token_stream.empty())
parse_token_stream.pop();
while(!checked_tokens.empty())
@@ -142,6 +179,130 @@ void nasal_parse::get_token_list(std::list<token>& detail_token_stream)
return;
}
void nasal_parse::print_parse_error(int error_type,int line,int error_token_type=__stack_end)
{
std::string error_info_head=">> [Parse] line ";
switch(error_type)
{
case parse_unknown_error:
std::cout<<error_info_head<<line<<": unknown parse error.(token id: "<<error_token_type<<")."<<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 error_token_in_block:
std::cout<<error_info_head<<line<<": statements should not begin with \'";
print_parse_token(error_token_type);
std::cout<<"\' in block scope."<<std::endl;
break;
case lack_semi:
std::cout<<error_info_head<<line<<": expect a \';\' at the end of the statement."<<std::endl;break;
case lack_id:
std::cout<<error_info_head<<line<<": expect an identifier here."<<std::endl;break;
case lack_left_curve:
std::cout<<error_info_head<<line<<": expect a \'(\' here."<<std::endl;break;
case lack_right_curve:
std::cout<<error_info_head<<line<<": expect a \')\' here."<<std::endl;break;
case lack_right_brace:
std::cout<<error_info_head<<line<<": expect a \'}\' here."<<std::endl;break;
case definition_lack_id:
std::cout<<error_info_head<<line<<": expect identifier(s) after \'var\'."<<std::endl;break;
case definition_lack_equal:
std::cout<<error_info_head<<line<<": expect a \'=\' here but get \'";
print_parse_token(error_token_type);
std::cout<<"\' when generating definition."<<std::endl;
break;
case assignment_begin_error:
std::cout<<error_info_head<<line<<": assignment should begin with one identifier_call."<<std::endl;
break;
case multi_definition_need_curve:
std::cout<<error_info_head<<line<<": expect a \')\' here but get \'";
print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl;
break;
case multi_assignment_need_curve:
std::cout<<error_info_head<<line<<": expect a \')\' here but get \'";
print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl;
break;
case multi_assignment_need_equal:
std::cout<<error_info_head<<line<<": expect a \'=\' here but get \'";
print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl;
break;
case error_begin_token_of_scalar:
std::cout<<error_info_head<<line<<": expect a scalar here but get \'";
print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl;
break;
case default_dynamic_parameter:
std::cout<<error_info_head<<line<<": dynamic parameter should not have a default value."<<std::endl;break;
case parameter_lack_part:
std::cout<<error_info_head<<line<<": expect a \')\' or identifier here when generating parameter_list."<<std::endl;break;
case parameter_lack_curve:
std::cout<<error_info_head<<line<<": expect a \')\' or \',\' here when generating parameter_list."<<std::endl;break;
case special_call_func_lack_id:
std::cout<<error_info_head<<line<<": expect an identifier here but get \'";
print_parse_token(error_token_type);
std::cout<<"\' when calling functions."<<std::endl;
break;
case special_call_func_lack_colon:
std::cout<<error_info_head<<line<<": expect an \':\' here but get \'";
print_parse_token(error_token_type);
std::cout<<"\' when calling functions."<<std::endl;
break;
case call_func_lack_comma:
std::cout<<error_info_head<<line<<": expect a \',\' when calling a function but get \'";
print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl;
break;
case call_hash_lack_id:
std::cout<<error_info_head<<line<<": expect an identifier after \'.\' ."<<std::endl;break;
case call_vector_wrong_comma:
std::cout<<error_info_head<<line<<": expect a scalar after \',\' but get \']\' ."<<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 call_vector_wrong_token:
std::cout<<error_info_head<<line<<": expect \':\' or ',' or ']' 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;
case ternary_operator_lack_colon:
std::cout<<error_info_head<<line<<": expect a \':\' here but get \'";
print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl;
break;
default:
std::cout<<error_info_head<<line<<": unknown parse error.(token id: "<<error_token_type<<")."<<std::endl;break;
}
return;
}
void nasal_parse::get_token()
{
if(!parse_token_stream.empty())