diff --git a/README.md b/README.md index f6dd142..c1471ef 100644 --- a/README.md +++ b/README.md @@ -261,127 +261,16 @@ a[-1,1,0:2,0:,:3,:,nil:8,3:nil,nil:nil]; ## special function call +This is of great use but is not very efficient. + ```javascript a(x:0,y:1,z:2); ``` -## often used builtin functions +## built-in functions Must import lib.nas or has these functions' definitions inside your code. Also you could add builtin functions of your own(written in C/C++) to help you calculate things more quickly.(Advanced usage) -```javascript - -var import=func(filename) -{ - nasal_call_import(filename); - return nil; -} -var print=func(elements...) -{ - nasal_call_builtin_std_cout(elements); - return nil; -}; -var append=func(vector,elements...) -{ - nasal_call_builtin_push_back(vector,elements); - return nil; -} -var setsize=func(vector,size) -{ - nasal_call_builtin_set_size(vector,size); - return nil; -} -var split=func(delimeter,string) -{ - return nasal_call_builtin_split(delimeter,string); -} -var rand=func(seed=nil) -{ - return nasal_call_builtin_rand(seed); -} -var id=func(thing) -{ - return nasal_call_builtin_get_id(thing); -} -var int=func(value) -{ - return nasal_call_builtin_trans_int(value); -} -var num=func(value) -{ - return nasal_call_builtin_trans_num(value); -} -var pop=func(vector) -{ - return nasal_call_builtin_pop_back(vector); -} -var str=func(number) -{ - return nasal_call_builtin_trans_str(number); -} -var size=func(object) -{ - return nasal_call_builtin_size(object); -} -var contains=func(hash,key) -{ - return nasal_call_builtin_contains(hash,key); -} -var delete=func(hash,key) -{ - nasal_call_builtin_delete(hash,key); - return; -} -var keys=func(hash) -{ - return nasal_call_builtin_get_keys(hash); -} -var die=func(str) -{ - nasal_call_builtin_die(str); - return nil; -} -var typeof=func(object) -{ - return nasal_call_builtin_type(object); -} -var substr=func(str,begin,length) -{ - return nasal_call_builtin_substr(str,begin,length); -} -var math= -{ - e:2.7182818284590452354, - pi:3.14159265358979323846264338327950288, - sin:func(x) - { - return nasal_call_builtin_sin(x); - }, - cos:func(x) - { - return nasal_call_builtin_cos(x); - }, - tan:func(x) - { - return nasal_call_builtin_tan(x); - }, - exp:func(x) - { - return nasal_call_builtin_exp(x); - }, - ln:func(x) - { - return nasal_call_builtin_cpp_math_ln(x); - }, - sqrt:func(x) - { - return nasal_call_builtin_cpp_math_sqrt(x); - }, - atan2:func(x,y) - { - return nasal_call_builtin_cpp_atan2(x,y); - }, -}; -``` \ No newline at end of file +Check built-in functions in lib.nas! \ No newline at end of file diff --git a/nasal_ast.h b/nasal_ast.h index bb474e3..8b1a7b4 100644 --- a/nasal_ast.h +++ b/nasal_ast.h @@ -5,16 +5,16 @@ enum ast_node { ast_null=0,ast_root,ast_block, ast_nil,ast_num,ast_str,ast_id,ast_func,ast_hash,ast_vec, - ast_hashmember,ast_call,ast_call_hash,ast_call_vec,ast_call_func,ast_subvec, + ast_hashmember,ast_call,ast_callh,ast_callv,ast_callf,ast_subvec, ast_args,ast_default_arg,ast_dynamic_id, ast_and,ast_or, - ast_equal,ast_add_equal,ast_sub_equal,ast_mult_equal,ast_div_equal,ast_link_equal, - ast_cmp_equal,ast_cmp_not_equal, + ast_equal,ast_addeq,ast_subeq,ast_multeq,ast_diveq,ast_lnkeq, + ast_cmpeq,ast_neq, ast_less,ast_leq, ast_grt,ast_geq, ast_add,ast_sub,ast_mult,ast_div,ast_link, - ast_unary_sub,ast_unary_not, - ast_trinocular, + ast_neg,ast_not, + ast_trino, ast_for,ast_forindex,ast_foreach,ast_while,ast_new_iter, ast_conditional,ast_if,ast_elsif,ast_else, ast_multi_id,ast_multi_scalar, @@ -38,9 +38,9 @@ std::string ast_name(int type) case ast_vec: return "vector"; case ast_hashmember: return "hashmember"; case ast_call: return "call"; - case ast_call_hash: return "callh"; - case ast_call_vec: return "callv"; - case ast_call_func: return "callf"; + case ast_callh: return "callh"; + case ast_callv: return "callv"; + case ast_callf: return "callf"; case ast_subvec: return "subvec"; case ast_args: return "args"; case ast_default_arg: return "deflt_arg"; @@ -48,13 +48,13 @@ std::string ast_name(int type) case ast_and: return "and"; case ast_or: return "or"; case ast_equal: return "="; - case ast_add_equal: return "+="; - case ast_sub_equal: return "-="; - case ast_mult_equal: return "*="; - case ast_div_equal: return "/="; - case ast_link_equal: return "~="; - case ast_cmp_equal: return "=="; - case ast_cmp_not_equal:return "!="; + case ast_addeq: return "+="; + case ast_subeq: return "-="; + case ast_multeq: return "*="; + case ast_diveq: return "/="; + case ast_lnkeq: return "~="; + case ast_cmpeq: return "=="; + case ast_neq: return "!="; case ast_less: return "<"; case ast_leq: return "<="; case ast_grt: return ">"; @@ -64,9 +64,9 @@ std::string ast_name(int type) case ast_mult: return "*"; case ast_div: return "/"; case ast_link: return "~"; - case ast_unary_sub: return "unary-"; - case ast_unary_not: return "unary!"; - case ast_trinocular: return "trino"; + case ast_neg: return "unary-"; + case ast_not: return "unary!"; + case ast_trino: return "trino"; case ast_for: return "for"; case ast_forindex: return "forindex"; case ast_foreach: return "foreach"; @@ -218,7 +218,7 @@ void nasal_ast::print_ast(int depth) for(int i=0;itype); std::cout<type==ast_str || this->type==ast_id || this->type==ast_dynamic_id || this->type==ast_call_hash) + if(this->type==ast_str || this->type==ast_id || this->type==ast_dynamic_id || this->type==ast_callh) std::cout<<":"<str; else if(this->type==ast_num) std::cout<<":"<num; diff --git a/nasal_lexer.h b/nasal_lexer.h index 803e8f5..19afd0e 100644 --- a/nasal_lexer.h +++ b/nasal_lexer.h @@ -27,7 +27,8 @@ enum token_type tok_colon,tok_add,tok_sub,tok_mult,tok_div,tok_link,tok_not, tok_eq, tok_addeq,tok_subeq,tok_multeq,tok_diveq,tok_lnkeq, - tok_cmpeq,tok_neq,tok_less,tok_leq,tok_grt,tok_geq + tok_cmpeq,tok_neq,tok_less,tok_leq,tok_grt,tok_geq, + tok_eof }; struct @@ -382,6 +383,8 @@ void nasal_lexer::scanner() die("["+line_code+"_] unknown character.",line,line_code.length()); } } + token tk(line,tok_eof,""); + token_list.push_back(tk); return; } diff --git a/nasal_parse.h b/nasal_parse.h index 78e4ec1..f6a627a 100644 --- a/nasal_parse.h +++ b/nasal_parse.h @@ -38,10 +38,9 @@ class nasal_parse { -#define error_line (tok_list[ptr>=tok_list_size? tok_list_size-1:ptr].line) +#define error_line (tok_list[ptr].line) #define is_call(type) ((type)==tok_lcurve || (type)==tok_lbracket || (type)==tok_dot) private: - int tok_list_size; int ptr; int error; nasal_ast root; @@ -112,7 +111,6 @@ int nasal_parse::get_error() void nasal_parse::set_toklist(std::vector& toks) { tok_list=toks; - tok_list_size=tok_list.size(); return; } @@ -121,17 +119,15 @@ void nasal_parse::main_process() reset(); root.set_line(1); root.set_type(ast_root); - while(ptr=tok_list_size) - break; if(tok_list[ptr].type==tok_semi) - ++ptr; + match(tok_semi); else if(need_semi_check(root.get_children().back())) { // the last expression can be recognized without semi - if(ptr> [parse] line "<=tok_list_size || tok_list[ptr].type!=type) + if(tok_list[ptr].type!=type) { std::string s=""; for(int i=0;token_table[i].str;++i) @@ -192,22 +190,22 @@ void nasal_parse::match(int type) bool nasal_parse::check_multi_def() { - return ptr+1=tok_list_size) - break; if(tok_list[ptr].type==tok_comma) - ++ptr; + match(tok_comma); else if(tok_list[ptr].type!=tok_rbracket) break; } - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_rbracket) - die(error_line,"expected \"]\""); + match(tok_rbracket); return node; } nasal_ast nasal_parse::hash_gen() { nasal_ast node(tok_list[ptr].line,ast_hash); match(tok_lbrace); - while (ptr=tok_list_size) - break; if(tok_list[ptr].type==tok_comma) - ++ptr; + match(tok_comma); else if(tok_list[ptr].type!=tok_rbrace) break; } - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_rbrace) - die(error_line,"expected \"}\""); + match(tok_rbrace); return node; } nasal_ast nasal_parse::hmem_gen() { - if(ptr>=tok_list_size || (tok_list[ptr].type!=tok_id && tok_list[ptr].type!=tok_str)) - { - die(error_line,"expected identifier/string"); - nasal_ast nullnode; - return nullnode; - } nasal_ast node(tok_list[ptr].line,ast_hashmember); - node.add_child(tok_list[ptr].type==tok_id?id_gen():str_gen()); - ++ptr; + if(tok_list[ptr].type==tok_id) + { + node.add_child(id_gen()); + match(tok_id); + } + else if(tok_list[ptr].type==tok_str) + { + node.add_child(str_gen()); + match(tok_str); + } + else + match(tok_id); match(tok_colon); node.add_child(calc()); return node; @@ -382,71 +378,48 @@ nasal_ast nasal_parse::func_gen() { nasal_ast node(tok_list[ptr].line,ast_func); match(tok_func); - if(ptr>=tok_list_size) - { - die(error_line,"expected argument(s)/expression block"); - return node; - } if(tok_list[ptr].type==tok_lcurve) - { node.add_child(args_gen()); - ++ptr; - } else - { - nasal_ast null_argument_list; - node.add_child(null_argument_list); - } + node.add_child(null_node_gen()); node.add_child(exprs_gen()); return node; } nasal_ast nasal_parse::args_gen() { nasal_ast node(tok_list[ptr].line,ast_args); - ++ptr; - while(ptr=tok_list_size) - break; if(tok_list[ptr].type==tok_comma) - ++ptr; + match(tok_comma); else if(tok_list[ptr].type!=tok_rcurve) break; } - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_rcurve) - { - die(error_line,"expected \")\""); - return node; - } + match(tok_rcurve); std::string args_format="func("; int node_child_size=node.get_children().size(); @@ -507,7 +480,7 @@ nasal_ast nasal_parse::expr() case tok_lbracket: case tok_lbrace: case tok_sub: - case tok_not: node=calc(); break; + case tok_not: node=calc(); break; case tok_var: node=definition(); break; case tok_lcurve: node=(check_multi_def()?definition():(check_multi_scalar()?multi_assgin():calc()));break; case tok_for: @@ -518,155 +491,122 @@ nasal_ast nasal_parse::expr() case tok_continue: node=continue_expr(); break; case tok_break: node=break_expr(); break; case tok_ret: node=return_expr(); break; - case tok_semi: --ptr; break; + case tok_semi: break; default: die(error_line,"error token \""+tok_list[ptr].str+"\"");break; } return node; } nasal_ast nasal_parse::exprs_gen() { - if(ptr>=tok_list_size) + if(tok_list[ptr].type==tok_eof) { die(error_line,"expected expression block"); - nasal_ast nullnode; - return nullnode; + return null_node_gen(); } nasal_ast node(tok_list[ptr].line,ast_block); if(tok_list[ptr].type==tok_lbrace) { - int left_brace_line=tok_list[ptr++].line; - while(ptr=tok_list_size) - break; - else if(tok_list[ptr].type==tok_semi) - ++ptr; + if(tok_list[ptr].type==tok_semi) + match(tok_semi); else if(need_semi_check(node.get_children().back())) { // the last expression can be recognized without semi - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_rbrace) + if(tok_list[ptr].type!=tok_rbrace) { die(error_line,"expected \";\""); break; } } } - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_rbrace) - { - std::string lb_line=""; - while(left_brace_line) - { - lb_line=(char)('0'+(left_brace_line%10))+lb_line; - left_brace_line/=10; - } - die(error_line,"expected \"}\" to match \"{\" in line "+lb_line); - } + match(tok_rbrace); } else { node.add_child(expr()); - if(++ptr=tok_list_size) - { - die(error_line,"expected calculation"); - return node; - } node=or_expr(); - ++ptr; - if(ptr=tok_list_size || tok_list[ptr].type!=tok_colon) - { - die(error_line,"expected \":\""); - return node; - } - ++ptr; + match(tok_colon); tmp.add_child(calc()); node=tmp; } - else if(ptr=tok_list_size || tok_list[ptr].type!=tok_rcurve) - die(error_line,"expected \")\""); + match(tok_rcurve); } else { die(error_line,"expected scalar"); return node; } - if(++ptr=tok_list_size) - break; - else if(tok_list[ptr].type==tok_comma) - ++ptr; + if(tok_list[ptr].type==tok_comma) + match(tok_comma); else if(tok_list[ptr].type!=tok_rbracket) break; } - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_rbracket) - die(error_line,"expected \"]\""); + match(tok_rbracket); return node; } nasal_ast nasal_parse::call_func() { nasal_ast node(tok_list[ptr].line,ast_callf); bool special_call=check_special_call(); - ++ptr; - while(ptr=tok_list_size) - break; - else if(tok_list[ptr].type==tok_comma) - ++ptr; + if(tok_list[ptr].type==tok_comma) + match(tok_comma); else if(tok_list[ptr].type!=tok_rcurve) break; } - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_rcurve) - die(error_line,"expected \")\""); + match(tok_rcurve); return node; } nasal_ast nasal_parse::subvec() { nasal_ast node; if(tok_list[ptr].type==tok_colon) - { - --ptr; node=nil_gen(); - } - else node=calc(); - ++ptr; - if(ptr=tok_list_size) - return node; nasal_ast tmp(node.get_line(),ast_subvec); + match(tok_colon); tmp.add_child(node); if(tok_list[ptr].type==tok_comma || tok_list[ptr].type==tok_rbracket) - { - --ptr; tmp.add_child(nil_gen()); - } else tmp.add_child(calc()); node=tmp; } - else - --ptr; return node; } nasal_ast nasal_parse::definition() @@ -888,30 +771,17 @@ nasal_ast nasal_parse::definition() nasal_ast node(tok_list[ptr].line,ast_definition); if(tok_list[ptr].type==tok_var) { - if(++ptr>=tok_list_size) - { - die(error_line,"expected identifier"); - return node; - } + match(tok_var); switch(tok_list[ptr].type) { - case tok_id:node.add_child(id_gen()); break; - case tok_lcurve:node.add_child(var_outcurve_def()); break; - default:die(error_line,"expected identifier"); return node; + case tok_id: node.add_child(id_gen());match(tok_id); break; + case tok_lcurve: node.add_child(var_outcurve_def()); break; + default: die(error_line,"expected identifier"); return node; } } else if(tok_list[ptr].type==tok_lcurve) node.add_child(var_incurve_def()); - if(++ptr>=tok_list_size || tok_list[ptr].type!=tok_eq) - { - die(error_line,"expected \"=\" / don\'t call identifier in definition"); - return node; - } - if(++ptr>=tok_list_size) - { - die(error_line,"expected scalar"); - return node; - } + match(tok_eq); if(tok_list[ptr].type==tok_lcurve) node.add_child(check_multi_scalar()?multi_scalar(false):calc()); else @@ -926,46 +796,36 @@ nasal_ast nasal_parse::definition() nasal_ast nasal_parse::var_incurve_def() { nasal_ast node; - ptr+=2; - // check_multi_def will check the 'var',so there's no need to check this again + match(tok_lcurve); + match(tok_var); node=multi_id(); - if(++ptr=tok_list_size || tok_list[ptr].type!=tok_rcurve) - die(error_line,"expected \")\""); + match(tok_rcurve); return node; } nasal_ast nasal_parse::var_outcurve_def() { nasal_ast node; - ++ptr; + match(tok_lcurve); node=multi_id(); - if(++ptr=tok_list_size || tok_list[ptr].type!=tok_rcurve) - die(error_line,"expected \")\""); + match(tok_rcurve); return node; } nasal_ast nasal_parse::multi_id() { nasal_ast node; - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_id) - { - die(error_line,"expected identifier"); - return node; - } node.set_line(tok_list[ptr].line); node.set_type(ast_multi_id); - while(ptr=tok_list_size || tok_list[ptr].type!=tok_comma) - { - --ptr; + match(tok_id); + if(tok_list[ptr].type!=tok_comma) break; - } - ++ptr; + match(tok_comma); } return node; } @@ -973,33 +833,26 @@ nasal_ast nasal_parse::multi_scalar(bool check_call_memory) { // if check_call_memory is true,we will check if value called here can reach a memory space nasal_ast node(tok_list[ptr].line,ast_multi_scalar); - ++ptr; - while(ptr=tok_list_size) - break; if(tok_list[ptr].type==tok_comma) - ++ptr; + match(tok_comma); else if(tok_list[ptr].type!=tok_rcurve) break; } - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_rcurve) - die(error_line,"expected \")\""); + match(tok_rcurve); return node; } nasal_ast nasal_parse::multi_assgin() { nasal_ast node(tok_list[ptr].line,ast_multi_assign); node.add_child(multi_scalar(true)); - if(++ptr>=tok_list_size || tok_list[ptr].type!=tok_eq) - { - die(error_line,"expected \"=\""); - return node; - } - if(++ptr>=tok_list_size) + match(tok_eq); + if(tok_list[ptr].type==tok_eof) { die(error_line,"expected value list"); return node; @@ -1030,41 +883,23 @@ nasal_ast nasal_parse::loop() nasal_ast nasal_parse::while_loop() { nasal_ast node(tok_list[ptr].line,ast_while); - if(++ptr>=tok_list_size || tok_list[ptr].type!=tok_lcurve) - { - die(error_line,"expected \"(\""); - return node; - } - ++ptr; + match(tok_while); + match(tok_lcurve); node.add_child(calc()); - if(++ptr>=tok_list_size || tok_list[ptr].type!=tok_rcurve) - { - die(error_line,"expected \")\""); - return node; - } - ++ptr; + match(tok_rcurve); node.add_child(exprs_gen()); return node; } nasal_ast nasal_parse::for_loop() { nasal_ast node(tok_list[ptr].line,ast_for); - if(++ptr>=tok_list_size || tok_list[ptr].type!=tok_lcurve) - { - die(error_line,"expected \"(\""); - return node; - } + match(tok_for); + match(tok_lcurve); // first expression - if(++ptr>=tok_list_size) - { + if(tok_list[ptr].type==tok_eof) die(error_line,"expected definition"); - return node; - } if(tok_list[ptr].type==tok_semi) - { node.add_child(null_node_gen()); - --ptr; - } else if(tok_list[ptr].type==tok_var) node.add_child(definition()); else if(tok_list[ptr].type==tok_lcurve) @@ -1079,49 +914,23 @@ nasal_ast nasal_parse::for_loop() ); else node.add_child(calc()); - if(++ptr>=tok_list_size || tok_list[ptr].type!=tok_semi) - { - die(error_line,"expected \";\""); - return node; - } + match(tok_semi); // conditional expression - if(++ptr>=tok_list_size) - { + if(tok_list[ptr].type==tok_eof) die(error_line,"expected conditional expression"); - return node; - } if(tok_list[ptr].type==tok_semi) - { node.add_child(null_node_gen()); - --ptr; - } else node.add_child(calc()); - if(++ptr>=tok_list_size || tok_list[ptr].type!=tok_semi) - { - die(error_line,"expected \";\""); - return node; - } + match(tok_semi); //after loop expression - if(++ptr>=tok_list_size) - { + if(tok_list[ptr].type==tok_eof) die(error_line,"expected calculation"); - return node; - } if(tok_list[ptr].type==tok_rcurve) - { node.add_child(null_node_gen()); - --ptr; - } else node.add_child(calc()); - ++ptr; - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_rcurve) - { - die(error_line,"expected \")\""); - return node; - } - ++ptr; + match(tok_rcurve); node.add_child(exprs_gen()); return node; } @@ -1130,39 +939,20 @@ nasal_ast nasal_parse::forei_loop() nasal_ast node(tok_list[ptr].line); switch(tok_list[ptr].type) { - case tok_forindex: node.set_type(ast_forindex);break; - case tok_foreach: node.set_type(ast_foreach); break; - } - if(++ptr>=tok_list_size || tok_list[ptr].type!=tok_lcurve) - { - die(error_line,"expected \"(\""); - return node; + case tok_forindex: node.set_type(ast_forindex);match(tok_forindex); break; + case tok_foreach: node.set_type(ast_foreach); match(tok_foreach); break; } + match(tok_lcurve); // first expression // foreach/forindex must have an iterator to loop through - if(++ptr>=tok_list_size || (tok_list[ptr].type!=tok_var && tok_list[ptr].type!=tok_id)) - { + if(tok_list[ptr].type!=tok_var && tok_list[ptr].type!=tok_id) die(error_line,"expected iterable value"); - return node; - } node.add_child(new_iter_gen()); - if(++ptr>=tok_list_size || tok_list[ptr].type!=tok_semi) - { - die(error_line,"expected \";\""); - return node; - } - if(++ptr>=tok_list_size) - { + match(tok_semi); + if(tok_list[ptr].type==tok_eof) die(error_line,"expected vector"); - return node; - } node.add_child(calc()); - if(++ptr>=tok_list_size || tok_list[ptr].type!=tok_rcurve) - { - die(error_line,"expected \")\""); - return node; - } - ++ptr; + match(tok_rcurve); node.add_child(exprs_gen()); return node; } @@ -1172,21 +962,18 @@ nasal_ast nasal_parse::new_iter_gen() nasal_ast node(tok_list[ptr].line); if(tok_list[ptr].type==tok_var) { + match(tok_var); node.set_type(ast_new_iter); - if(++ptr>=tok_list_size || tok_list[ptr].type!=tok_id) - { - die(error_line,"expected identifier"); - return node; - } node.add_child(id_gen()); + match(tok_id); } else { node.set_type(ast_call); node.add_child(id_gen()); - while(++ptr=tok_list_size || tok_list[ptr].type!=tok_lcurve) - { - die(error_line,"expected \"(\""); - return node; - } - ++ptr; + match(tok_if); + match(tok_lcurve); tmp.add_child(calc()); - if(++ptr>=tok_list_size || tok_list[ptr].type!=tok_rcurve) - { - die(error_line,"expected \")\""); - return node; - } - ++ptr; + match(tok_rcurve); tmp.add_child(exprs_gen()); node.add_child(tmp); // end of if-expression - while(++ptr=tok_list_size || tok_list[ptr].type!=tok_lcurve) - { - die(error_line,"expected \"(\""); - return node; - } nasal_ast tmp(tok_list[ptr].line,ast_elsif); - ++ptr; + match(tok_elsif); + match(tok_lcurve); tmp.add_child(calc()); - if(++ptr>=tok_list_size || tok_list[ptr].type!=tok_rcurve) - { - die(error_line,"expected \")\""); - return node; - } - ++ptr; + match(tok_rcurve); tmp.add_child(exprs_gen()); node.add_child(tmp); } - // end of elsif-expression - // after this process,ptr will point to the next token of exprs_gen()'s last token - // for example - // else if(scalar){} else {} - // ptr^ - if(ptr