This commit is contained in:
Valk Richard Li 2020-03-19 18:05:41 +08:00 committed by GitHub
parent 28cc088461
commit c250bfb8d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 216 additions and 199 deletions

View File

@ -1,11 +1,17 @@
#include "nasal.h"
// source code will be put in resource
resource_file resource;
// source code will be generated to tokens in lexer
nasal_lexer lexer;
// token list will be checked in parser and output the abstract syntax tree
nasal_parse parser;
// libroot stores the ast of lib file
abstract_syntax_tree libroot;
// root stores the ast of source code
abstract_syntax_tree root;
abstract_syntax_tree linker;
// executable_ast generates libroot and root together
abstract_syntax_tree executable_ast;
nasal_runtime runtime;
@ -69,7 +75,7 @@ int main()
lexer.delete_all_tokens();
parser.delete_all_elements();
root.set_clear();
linker.set_clear();
executable_ast.set_clear();
std::cout<<">> [Delete] complete."<<std::endl;
}
else if(command=="lib")
@ -148,11 +154,10 @@ int main()
parser.main_generate();
if(!parser.get_error())
{
linker.set_clear();
linker=libroot;
linker.merge_children(parser.get_root());
root=linker;
runtime.main_proc(root);
executable_ast.set_clear();
executable_ast=libroot;
executable_ast.merge_children(parser.get_root());
runtime.main_proc(executable_ast);
//root.print_tree();
}
else

View File

@ -204,180 +204,6 @@ void print_ast_type(int type)
return;
}
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 error_type,int line,int error_token_type=__stack_end)
{
std::string error_info_head=">> [Parse-error] line ";
std::string warning_info_head=">> [Parse-warning] 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;
}
enum scalar_type
{
scalar_nil=0,

View File

@ -12,6 +12,7 @@ class nasal_function
{
private:
std::list<std::map<std::string,int> > local_scope;
abstract_syntax_tree parameter_list;
abstract_syntax_tree function_root;
// parent_hash_addr is used to store the address of the hash which has this nasal_function
// because nasal_function needs this address to adjust the identifier called 'me' in local_scope
@ -19,8 +20,10 @@ class nasal_function
public:
void set_clear();
void set_local_scope(std::list<std::map<std::string,int> >&);
void set_paramemter_list(abstract_syntax_tree&);
void set_statement_block(abstract_syntax_tree&);
std::list<std::map<std::string,int> >& get_local_scope();
abstract_syntax_tree& get_parameter_list();
abstract_syntax_tree& get_statement_block();
void deep_copy(nasal_function&);
};
@ -255,6 +258,11 @@ void nasal_function::set_local_scope(std::list<std::map<std::string,int> >& tmp_
nasal_gc.reference_add(i->second);
return;
}
void nasal_function::set_paramemter_list(abstract_syntax_tree& para_list)
{
parameter_list=para_list;
return;
}
void nasal_function::set_statement_block(abstract_syntax_tree& func_block)
{
function_root=func_block;
@ -264,6 +272,10 @@ std::list<std::map<std::string,int> >& nasal_function::get_local_scope()
{
return local_scope;
}
abstract_syntax_tree& nasal_function::get_parameter_list()
{
return parameter_list;
}
abstract_syntax_tree& nasal_function::get_statement_block()
{
return function_root;
@ -282,6 +294,7 @@ void nasal_function::deep_copy(nasal_function& tmp)
for(std::map<std::string,int>::iterator i=iter->begin();i!=iter->end();++i)
nasal_gc.reference_add(i->second);
// copy abstract_syntax_tree
parameter_list=tmp.parameter_list;
function_root=tmp.function_root;
return;
}
@ -342,7 +355,11 @@ void nasal_vector::vec_push(int addr)
}
int nasal_vector::get_elem(int addr)
{
if(0<=addr && addr<nas_array.size())
// 0 ~ size-1 -size ~ -1
int bound=nas_array.size();
if(-bound<=addr && addr<0)
return nas_array[bound+addr];
else if(0<=addr && addr<bound)
return nas_array[addr];
return -1;
}

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())

View File

@ -41,7 +41,7 @@ class nasal_runtime
void definition (std::list<std::map<std::string,int> >&,std::map<std::string,int>&,abstract_syntax_tree&);
void loop_expr (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
void conditional (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
int func_proc (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
int func_proc (std::list<std::map<std::string,int> >&,abstract_syntax_tree&,abstract_syntax_tree&);
public:
nasal_runtime()
{
@ -203,11 +203,18 @@ int nasal_runtime::function_generation(std::list<std::map<std::string,int> >& lo
nasal_gc.get_scalar(addr).set_type(scalar_function);
nasal_gc.get_scalar(addr).get_function().set_local_scope(local_scope);
// function
// parameters
// block
// calls...
// parameters
// block
// calls...
std::list<abstract_syntax_tree>::iterator i=node.get_children().begin();
nasal_gc.get_scalar(addr).get_function().set_paramemter_list(*i);
++i;
nasal_gc.get_scalar(addr).get_function().set_statement_block(*i);
++i;
for(;i!=node.get_children().end();++i)
{
;
}
return addr;
}
int nasal_runtime::calculation(std::list<std::map<std::string,int> >& local_scope,abstract_syntax_tree& node)
@ -1114,6 +1121,7 @@ int nasal_runtime::call_identifier(std::list<std::map<std::string,int> >& local_
}
else if(called_type==scalar_hash)
{
if(nasal_gc.get_scalar(data_addr).get_type()!=scalar_string)
{
error_interrupt(__error_value_type,iter->get_node_line());
@ -1351,7 +1359,7 @@ void nasal_runtime::conditional(std::list<std::map<std::string,int> >& local_sco
return;
}
int nasal_runtime::func_proc(std::list<std::map<std::string,int> >& local_scope,abstract_syntax_tree& func_root)
int nasal_runtime::func_proc(std::list<std::map<std::string,int> >& local_scope,abstract_syntax_tree& parameter_list,abstract_syntax_tree& func_root)
{
if(func_root.get_node_type()!=__function)
{
@ -1361,12 +1369,12 @@ int nasal_runtime::func_proc(std::list<std::map<std::string,int> >& local_scope,
std::map<std::string,int> new_scope;
local_scope.push_back(new_scope);
// loading parameters
for(std::list<abstract_syntax_tree>::iterator iter=func_root.get_children().front().get_children().begin();iter!=func_root.get_children().front().get_children().end();++iter)
for(std::list<abstract_syntax_tree>::iterator iter=parameter_list.get_children().begin();iter!=parameter_list.get_children().end();++iter)
{
}
// process
for(std::list<abstract_syntax_tree>::iterator iter=func_root.get_children().back().get_children().begin();iter!=func_root.get_children().back().get_children().end();++iter)
for(std::list<abstract_syntax_tree>::iterator iter=func_root.get_children().begin();iter!=func_root.get_children().end();++iter)
{
// use local value node_type to avoid calling function too many times.
int node_type=iter->get_node_type();