diff --git a/version2.0/main.cpp b/version2.0/main.cpp index 9c9d30b..c2e6931 100644 --- a/version2.0/main.cpp +++ b/version2.0/main.cpp @@ -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."< > 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 >&); + void set_paramemter_list(abstract_syntax_tree&); void set_statement_block(abstract_syntax_tree&); std::list >& 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 >& 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 >& 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::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 parse_token_stream; std::stack 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: [] ';' 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&); - 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& 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& 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< >&,std::map&,abstract_syntax_tree&); void loop_expr (std::list >&,abstract_syntax_tree&); void conditional (std::list >&,abstract_syntax_tree&); - int func_proc (std::list >&,abstract_syntax_tree&); + int func_proc (std::list >&,abstract_syntax_tree&,abstract_syntax_tree&); public: nasal_runtime() { @@ -203,11 +203,18 @@ int nasal_runtime::function_generation(std::list >& 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::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 >& local_scope,abstract_syntax_tree& node) @@ -1114,6 +1121,7 @@ int nasal_runtime::call_identifier(std::list >& 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 >& local_sco return; } -int nasal_runtime::func_proc(std::list >& local_scope,abstract_syntax_tree& func_root) +int nasal_runtime::func_proc(std::list >& 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 >& local_scope, std::map new_scope; local_scope.push_back(new_scope); // loading parameters - for(std::list::iterator iter=func_root.get_children().front().get_children().begin();iter!=func_root.get_children().front().get_children().end();++iter) + for(std::list::iterator iter=parameter_list.get_children().begin();iter!=parameter_list.get_children().end();++iter) { } // process - for(std::list::iterator iter=func_root.get_children().back().get_children().begin();iter!=func_root.get_children().back().get_children().end();++iter) + for(std::list::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();