parser reports syntax error accurately
still need improvement
This commit is contained in:
parent
c5f4736984
commit
6adb991c04
14
README.md
14
README.md
|
@ -14,15 +14,19 @@ But in last summer holiday, members in FGPRC told me that it is hard to debug wi
|
||||||
|
|
||||||
So i tried to write a new interpreter to help them checking syntax error and even, runtime error.
|
So i tried to write a new interpreter to help them checking syntax error and even, runtime error.
|
||||||
|
|
||||||
I wrote the lexer, parser and runtime(bytecode virtual machine/ast-runtime virtual machine) to help checking errors.
|
I wrote the lexer, parser and runtimebytecode virtual machine(there was an ast-interpreter,but i deleted it after version4.0) to help checking errors.
|
||||||
|
|
||||||
They found it easier for them to check errors before copying nasal-codes in nasal-console in Flightgear to test.
|
They found it much easier to check syntax and runtime errors before copying nasal-codes in nasal-console in Flightgear to test.
|
||||||
|
|
||||||
|
Also, you could use this language to write some interesting programs and run them without the lib of Flightgear.
|
||||||
|
|
||||||
|
You could add your own built-in functions to change this interpreter to a useful tool in your own projects(such as a script in your own game).
|
||||||
|
|
||||||
# How to Compile
|
# How to Compile
|
||||||
|
|
||||||
MUST USE -O2 !
|
Better choose the latest update of the interpreter.
|
||||||
|
|
||||||
pragma gcc optimize(2) seems useless when using g++
|
MUST USE -O2 ! pragma gcc optimize(2) seems useless when using g++
|
||||||
|
|
||||||
> g++ -std=c++11 -O2 main.cpp -o main.exe
|
> g++ -std=c++11 -O2 main.cpp -o main.exe
|
||||||
|
|
||||||
|
@ -156,7 +160,7 @@ for(var i=0;i<4000000;i+=1);
|
||||||
|
|
||||||
## basic value type
|
## basic value type
|
||||||
|
|
||||||
nasal has 6 value types.Number,string,vector,hash,function,nil.
|
Nasal has 6 value types.Number,string,vector,hash,function,nil.
|
||||||
|
|
||||||
Number has 3 formats.Dec,hex and oct;
|
Number has 3 formats.Dec,hex and oct;
|
||||||
|
|
||||||
|
|
6
main.cpp
6
main.cpp
|
@ -115,11 +115,7 @@ int main()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
system("cls");
|
system("cls");
|
||||||
#endif
|
#else
|
||||||
#ifdef _linux_
|
|
||||||
system("clear");
|
|
||||||
#endif
|
|
||||||
#ifdef TARGET_OS_MAC
|
|
||||||
system("clear");
|
system("clear");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,7 @@ scalar::=
|
||||||
|hash {call_scalar}
|
|hash {call_scalar}
|
||||||
|number
|
|number
|
||||||
|string
|
|string
|
||||||
|
|nil
|
||||||
|'(' calculation ')' {call_scalar}
|
|'(' calculation ')' {call_scalar}
|
||||||
;
|
;
|
||||||
call_scalar::=
|
call_scalar::=
|
||||||
|
|
31
nasal_gc.h
31
nasal_gc.h
|
@ -311,32 +311,24 @@ struct nasal_gc
|
||||||
std::queue <nasal_val*> free_list; // gc free list
|
std::queue <nasal_val*> free_list; // gc free list
|
||||||
std::vector<nasal_val*> global;
|
std::vector<nasal_val*> global;
|
||||||
std::list<std::vector<nasal_val*> > local;
|
std::list<std::vector<nasal_val*> > local;
|
||||||
void mark();
|
void mark();
|
||||||
void sweep();
|
void sweep();
|
||||||
void gc_init(std::vector<double>&,std::vector<std::string>&);
|
void gc_init(std::vector<double>&,std::vector<std::string>&);
|
||||||
void gc_clear();
|
void gc_clear();
|
||||||
nasal_val* gc_alloc(int);
|
nasal_val* gc_alloc(int);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* gc functions */
|
/* gc functions */
|
||||||
void nasal_gc::mark()
|
void nasal_gc::mark()
|
||||||
{
|
{
|
||||||
std::queue<nasal_val*> bfs;
|
std::queue<nasal_val*> bfs;
|
||||||
zero_addr->mark=true;
|
|
||||||
one_addr->mark=true;
|
|
||||||
nil_addr->mark=true;
|
|
||||||
for(auto i=global.begin();i!=global.end();++i)
|
for(auto i=global.begin();i!=global.end();++i)
|
||||||
bfs.push(*i);
|
bfs.push(*i);
|
||||||
int size=num_addrs.size();
|
|
||||||
for(int i=0;i<size;++i)
|
|
||||||
bfs.push(num_addrs[i]);
|
|
||||||
size=local.size();
|
|
||||||
for(auto i=local.begin();i!=local.end();++i)
|
for(auto i=local.begin();i!=local.end();++i)
|
||||||
for(auto j=i->begin();j!=i->end();++j)
|
for(auto j=i->begin();j!=i->end();++j)
|
||||||
bfs.push(*j);
|
bfs.push(*j);
|
||||||
size=slice_stack.size();
|
for(auto i=slice_stack.begin();i!=slice_stack.end();++i)
|
||||||
for(int i=0;i<size;++i)
|
bfs.push(*i);
|
||||||
bfs.push(slice_stack[i]);
|
|
||||||
for(nasal_val** i=val_stack;i<=stack_top;++i)
|
for(nasal_val** i=val_stack;i<=stack_top;++i)
|
||||||
bfs.push(*i);
|
bfs.push(*i);
|
||||||
while(!bfs.empty())
|
while(!bfs.empty())
|
||||||
|
@ -395,14 +387,11 @@ void nasal_gc::gc_init(std::vector<double>& nums,std::vector<std::string>& strs)
|
||||||
|
|
||||||
zero_addr=new nasal_val(vm_num); // init constant 0
|
zero_addr=new nasal_val(vm_num); // init constant 0
|
||||||
zero_addr->ptr.num=0;
|
zero_addr->ptr.num=0;
|
||||||
memory.push_back(zero_addr);
|
|
||||||
|
|
||||||
one_addr=new nasal_val(vm_num); // init constant 1
|
one_addr=new nasal_val(vm_num); // init constant 1
|
||||||
one_addr->ptr.num=1;
|
one_addr->ptr.num=1;
|
||||||
memory.push_back(one_addr);
|
|
||||||
|
|
||||||
nil_addr=new nasal_val(vm_nil); // init nil
|
nil_addr=new nasal_val(vm_nil); // init nil
|
||||||
memory.push_back(nil_addr);
|
|
||||||
|
|
||||||
*val_stack=nil_addr; // the first space will not store any values,but gc checks
|
*val_stack=nil_addr; // the first space will not store any values,but gc checks
|
||||||
|
|
||||||
|
@ -425,8 +414,7 @@ void nasal_gc::gc_init(std::vector<double>& nums,std::vector<std::string>& strs)
|
||||||
}
|
}
|
||||||
void nasal_gc::gc_clear()
|
void nasal_gc::gc_clear()
|
||||||
{
|
{
|
||||||
int size=memory.size();
|
for(int i=0;i<memory.size();++i)
|
||||||
for(int i=0;i<size;++i)
|
|
||||||
{
|
{
|
||||||
memory[i]->clear();
|
memory[i]->clear();
|
||||||
delete memory[i];
|
delete memory[i];
|
||||||
|
@ -438,6 +426,9 @@ void nasal_gc::gc_clear()
|
||||||
local.clear();
|
local.clear();
|
||||||
slice_stack.clear();
|
slice_stack.clear();
|
||||||
|
|
||||||
|
delete nil_addr;
|
||||||
|
delete one_addr;
|
||||||
|
delete zero_addr;
|
||||||
for(int i=0;i<num_addrs.size();++i)
|
for(int i=0;i<num_addrs.size();++i)
|
||||||
delete num_addrs[i];
|
delete num_addrs[i];
|
||||||
num_addrs.clear();
|
num_addrs.clear();
|
||||||
|
|
|
@ -297,6 +297,8 @@ std::string nasal_lexer::string_gen()
|
||||||
// check if this string ends with a " or '
|
// check if this string ends with a " or '
|
||||||
if(ptr++>=res_size)
|
if(ptr++>=res_size)
|
||||||
die(line_code,"get EOF when generating string.",line,line_code.length());
|
die(line_code,"get EOF when generating string.",line,line_code.length());
|
||||||
|
if(str_begin=='`' && token_str.length()>1)
|
||||||
|
die(line_code,"\'`\' is used for string that includes one character.",line,line_code.length());
|
||||||
return token_str;
|
return token_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
198
nasal_parse.h
198
nasal_parse.h
|
@ -45,11 +45,13 @@ private:
|
||||||
int error;
|
int error;
|
||||||
nasal_ast root;
|
nasal_ast root;
|
||||||
std::vector<token> tok_list;
|
std::vector<token> tok_list;
|
||||||
|
std::vector<token> error_token;
|
||||||
int in_function; // count when generating function block,used to check return-expression
|
int in_function; // count when generating function block,used to check return-expression
|
||||||
int in_loop; // count when generating loop block,used to check break/continue-expression
|
int in_loop; // count when generating loop block,used to check break/continue-expression
|
||||||
void reset();
|
void reset();
|
||||||
void die(int,std::string);
|
void die(int,std::string);
|
||||||
void match(int);
|
void match(int type,std::string err_info="");
|
||||||
|
bool check_comma(int*);
|
||||||
bool check_multi_def();
|
bool check_multi_def();
|
||||||
bool check_multi_scalar();
|
bool check_multi_scalar();
|
||||||
bool check_function_end(nasal_ast&);
|
bool check_function_end(nasal_ast&);
|
||||||
|
@ -63,7 +65,7 @@ private:
|
||||||
nasal_ast id_gen();
|
nasal_ast id_gen();
|
||||||
nasal_ast vec_gen();
|
nasal_ast vec_gen();
|
||||||
nasal_ast hash_gen();
|
nasal_ast hash_gen();
|
||||||
nasal_ast hmem_gen(); // hash member
|
nasal_ast hmem_gen();
|
||||||
nasal_ast func_gen();
|
nasal_ast func_gen();
|
||||||
nasal_ast args_gen();
|
nasal_ast args_gen();
|
||||||
nasal_ast expr();
|
nasal_ast expr();
|
||||||
|
@ -102,18 +104,15 @@ public:
|
||||||
void main_process();
|
void main_process();
|
||||||
nasal_ast& get_root();
|
nasal_ast& get_root();
|
||||||
};
|
};
|
||||||
|
|
||||||
int nasal_parse::get_error()
|
int nasal_parse::get_error()
|
||||||
{
|
{
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nasal_parse::set_toklist(std::vector<token>& toks)
|
void nasal_parse::set_toklist(std::vector<token>& toks)
|
||||||
{
|
{
|
||||||
tok_list=toks;
|
tok_list=toks;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nasal_parse::main_process()
|
void nasal_parse::main_process()
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
|
@ -124,52 +123,49 @@ void nasal_parse::main_process()
|
||||||
root.add_child(expr());
|
root.add_child(expr());
|
||||||
if(tok_list[ptr].type==tok_semi)
|
if(tok_list[ptr].type==tok_semi)
|
||||||
match(tok_semi);
|
match(tok_semi);
|
||||||
else if(need_semi_check(root.get_children().back()))
|
else if(need_semi_check(root.get_children().back()) && tok_list[ptr].type!=tok_eof)
|
||||||
{
|
{
|
||||||
// the last expression can be recognized without semi
|
// the last expression can be recognized without semi
|
||||||
if(tok_list[ptr].type!=tok_eof)
|
die(error_line,"expected \";\"");
|
||||||
die(error_line,"expected \";\"");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(!error_token.size())
|
||||||
|
return;
|
||||||
|
int sameline=error_token[0].line;
|
||||||
|
for(int i=0;i<error_token.size();++i)
|
||||||
|
if(sameline!=error_token[i].line)
|
||||||
|
{
|
||||||
|
die(sameline,"error tokens in this line maybe recorded because of fatal syntax errors");
|
||||||
|
sameline=error_token[i].line;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nasal_ast& nasal_parse::get_root()
|
nasal_ast& nasal_parse::get_root()
|
||||||
{
|
{
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nasal_parse::reset()
|
void nasal_parse::reset()
|
||||||
{
|
{
|
||||||
ptr=in_function=in_loop=error=0;
|
ptr=in_function=in_loop=error=0;
|
||||||
root.clear();
|
root.clear();
|
||||||
|
error_token.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nasal_parse::die(int line,std::string info)
|
void nasal_parse::die(int line,std::string info)
|
||||||
{
|
{
|
||||||
++error;
|
++error;
|
||||||
std::cout<<">> [parse] line "<<line<<": "<<info<<".\n";
|
std::cout<<">> [parse] line "<<line<<": "<<info<<".\n";
|
||||||
if(tok_list[ptr].type==tok_eof)
|
|
||||||
return;
|
|
||||||
++ptr;
|
|
||||||
while(tok_list[ptr].type!=tok_eof)// panic
|
|
||||||
{
|
|
||||||
if(tok_list[ptr].type==tok_semi ||
|
|
||||||
tok_list[ptr].type==tok_rcurve ||
|
|
||||||
tok_list[ptr].type==tok_rbracket ||
|
|
||||||
tok_list[ptr].type==tok_rbrace ||
|
|
||||||
tok_list[ptr].type==tok_eof)
|
|
||||||
break;
|
|
||||||
++ptr;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
void nasal_parse::match(int type,std::string err_info)
|
||||||
void nasal_parse::match(int type)
|
|
||||||
{
|
{
|
||||||
if(tok_list[ptr].type!=type)
|
if(tok_list[ptr].type!=type)
|
||||||
{
|
{
|
||||||
|
if(err_info.length())
|
||||||
|
{
|
||||||
|
die(error_line,err_info);
|
||||||
|
return;
|
||||||
|
}
|
||||||
std::string s="";
|
std::string s="";
|
||||||
for(int i=0;token_table[i].str;++i)
|
for(int i=0;token_table[i].str;++i)
|
||||||
if(token_table[i].tok_type==type)
|
if(token_table[i].tok_type==type)
|
||||||
|
@ -177,26 +173,36 @@ void nasal_parse::match(int type)
|
||||||
s=token_table[i].str;
|
s=token_table[i].str;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(type==tok_num)
|
switch(type)
|
||||||
die(error_line,"expect a number");
|
{
|
||||||
else if(type==tok_str)
|
case tok_num:die(error_line,"expected number"); break;
|
||||||
die(error_line,"expect a string");
|
case tok_str:die(error_line,"expected string"); break;
|
||||||
else if(type==tok_id)
|
case tok_id: die(error_line,"expected identifier");break;
|
||||||
die(error_line,"expect an identifier");
|
default: die(error_line,"expected \'"+s+"\'"); break;
|
||||||
else
|
}
|
||||||
die(error_line,"expect \'"+s+"\'");
|
return;
|
||||||
}
|
}
|
||||||
if(tok_list[ptr].type==tok_eof)
|
if(tok_list[ptr].type==tok_eof)
|
||||||
return;
|
return;
|
||||||
++ptr;
|
++ptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
bool nasal_parse::check_comma(int* panic_set)
|
||||||
|
{
|
||||||
|
bool in_panic_set=false;
|
||||||
|
for(int i=0;panic_set[i];++i)
|
||||||
|
if(tok_list[ptr].type==panic_set[i])
|
||||||
|
{
|
||||||
|
in_panic_set=true;
|
||||||
|
die(error_line,"expected \',\' between scalars");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return in_panic_set;
|
||||||
|
}
|
||||||
bool nasal_parse::check_multi_def()
|
bool nasal_parse::check_multi_def()
|
||||||
{
|
{
|
||||||
return tok_list[ptr+1].type==tok_var;
|
return tok_list[ptr+1].type==tok_var;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nasal_parse::check_multi_scalar()
|
bool nasal_parse::check_multi_scalar()
|
||||||
{
|
{
|
||||||
int check_ptr=ptr,curve_cnt=1,bracket_cnt=0,brace_cnt=0;
|
int check_ptr=ptr,curve_cnt=1,bracket_cnt=0,brace_cnt=0;
|
||||||
|
@ -216,7 +222,6 @@ bool nasal_parse::check_multi_scalar()
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nasal_parse::check_function_end(nasal_ast& node)
|
bool nasal_parse::check_function_end(nasal_ast& node)
|
||||||
{
|
{
|
||||||
int type=node.get_type();
|
int type=node.get_type();
|
||||||
|
@ -241,7 +246,6 @@ bool nasal_parse::check_function_end(nasal_ast& node)
|
||||||
return check_function_end(node.get_children().back());
|
return check_function_end(node.get_children().back());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nasal_parse::check_special_call()
|
bool nasal_parse::check_special_call()
|
||||||
{
|
{
|
||||||
// special call means like this:
|
// special call means like this:
|
||||||
|
@ -266,7 +270,6 @@ bool nasal_parse::check_special_call()
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nasal_parse::need_semi_check(nasal_ast& node)
|
bool nasal_parse::need_semi_check(nasal_ast& node)
|
||||||
{
|
{
|
||||||
int type=node.get_type();
|
int type=node.get_type();
|
||||||
|
@ -274,7 +277,6 @@ bool nasal_parse::need_semi_check(nasal_ast& node)
|
||||||
return false;
|
return false;
|
||||||
return !check_function_end(node);
|
return !check_function_end(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nasal_parse::check_memory_reachable(nasal_ast& node)
|
void nasal_parse::check_memory_reachable(nasal_ast& node)
|
||||||
{
|
{
|
||||||
if(node.get_type()==ast_call)
|
if(node.get_type()==ast_call)
|
||||||
|
@ -295,42 +297,40 @@ void nasal_parse::check_memory_reachable(nasal_ast& node)
|
||||||
die(node.get_line(),"cannot use calculation as the memory of scalar");
|
die(node.get_line(),"cannot use calculation as the memory of scalar");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nasal_ast nasal_parse::null_node_gen()
|
nasal_ast nasal_parse::null_node_gen()
|
||||||
{
|
{
|
||||||
nasal_ast node(tok_list[ptr].line,ast_null);
|
nasal_ast node(tok_list[ptr].line,ast_null);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
nasal_ast nasal_parse::nil_gen()
|
nasal_ast nasal_parse::nil_gen()
|
||||||
{
|
{
|
||||||
nasal_ast node(tok_list[ptr].line,ast_nil);
|
nasal_ast node(tok_list[ptr].line,ast_nil);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
nasal_ast nasal_parse::num_gen()
|
nasal_ast nasal_parse::num_gen()
|
||||||
{
|
{
|
||||||
nasal_ast node(tok_list[ptr].line,ast_num);
|
nasal_ast node(tok_list[ptr].line,ast_num);
|
||||||
node.set_num(trans_string_to_number(tok_list[ptr].str));
|
node.set_num(trans_string_to_number(tok_list[ptr].str));
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
nasal_ast nasal_parse::str_gen()
|
nasal_ast nasal_parse::str_gen()
|
||||||
{
|
{
|
||||||
nasal_ast node(tok_list[ptr].line,ast_str);
|
nasal_ast node(tok_list[ptr].line,ast_str);
|
||||||
node.set_str(tok_list[ptr].str);
|
node.set_str(tok_list[ptr].str);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
nasal_ast nasal_parse::id_gen()
|
nasal_ast nasal_parse::id_gen()
|
||||||
{
|
{
|
||||||
nasal_ast node(tok_list[ptr].line,ast_id);
|
nasal_ast node(tok_list[ptr].line,ast_id);
|
||||||
node.set_str(tok_list[ptr].str);
|
node.set_str(tok_list[ptr].str);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
nasal_ast nasal_parse::vec_gen()
|
nasal_ast nasal_parse::vec_gen()
|
||||||
{
|
{
|
||||||
|
// panic set for this token is not ','
|
||||||
|
// this is the FIRST set of calculation
|
||||||
|
// array end with tok_null=0
|
||||||
|
int panic_set[]={tok_id,tok_str,tok_num,tok_not,tok_sub,tok_nil,tok_func,tok_var,tok_lcurve,tok_lbrace,tok_lbracket,tok_null};
|
||||||
nasal_ast node(tok_list[ptr].line,ast_vec);
|
nasal_ast node(tok_list[ptr].line,ast_vec);
|
||||||
match(tok_lbracket);
|
match(tok_lbracket);
|
||||||
while(tok_list[ptr].type!=tok_rbracket)
|
while(tok_list[ptr].type!=tok_rbracket)
|
||||||
|
@ -338,10 +338,12 @@ nasal_ast nasal_parse::vec_gen()
|
||||||
node.add_child(calc());
|
node.add_child(calc());
|
||||||
if(tok_list[ptr].type==tok_comma)
|
if(tok_list[ptr].type==tok_comma)
|
||||||
match(tok_comma);
|
match(tok_comma);
|
||||||
else if(tok_list[ptr].type!=tok_rbracket)
|
else if(tok_list[ptr].type==tok_eof)
|
||||||
|
break;
|
||||||
|
else if(tok_list[ptr].type!=tok_rbracket && !check_comma(panic_set))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
match(tok_rbracket);
|
match(tok_rbracket,"expected \']\' when generating vector");
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
nasal_ast nasal_parse::hash_gen()
|
nasal_ast nasal_parse::hash_gen()
|
||||||
|
@ -353,10 +355,12 @@ nasal_ast nasal_parse::hash_gen()
|
||||||
node.add_child(hmem_gen());
|
node.add_child(hmem_gen());
|
||||||
if(tok_list[ptr].type==tok_comma)
|
if(tok_list[ptr].type==tok_comma)
|
||||||
match(tok_comma);
|
match(tok_comma);
|
||||||
else if(tok_list[ptr].type!=tok_rbrace)
|
else if(tok_list[ptr].type==tok_id || tok_list[ptr].type==tok_str)// first set of hashmember
|
||||||
|
die(error_line,"expected \',\' between hash members");
|
||||||
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
match(tok_rbrace);
|
match(tok_rbrace,"expected \'}\' when generating hash");
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
nasal_ast nasal_parse::hmem_gen()
|
nasal_ast nasal_parse::hmem_gen()
|
||||||
|
@ -420,10 +424,12 @@ nasal_ast nasal_parse::args_gen()
|
||||||
node.add_child(tmp);
|
node.add_child(tmp);
|
||||||
if(tok_list[ptr].type==tok_comma)
|
if(tok_list[ptr].type==tok_comma)
|
||||||
match(tok_comma);
|
match(tok_comma);
|
||||||
else if(tok_list[ptr].type!=tok_rcurve)
|
else if(tok_list[ptr].type==tok_id)// first set of identifier
|
||||||
|
die(error_line,"expected \',\' between identifiers");
|
||||||
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
match(tok_rcurve);
|
match(tok_rcurve,"expected \')\' after parameter list");
|
||||||
|
|
||||||
std::string args_format="func(";
|
std::string args_format="func(";
|
||||||
int node_child_size=node.get_children().size();
|
int node_child_size=node.get_children().size();
|
||||||
|
@ -445,7 +451,7 @@ nasal_ast nasal_parse::args_gen()
|
||||||
else if(node.get_children()[i].get_type()==ast_dynamic_id)
|
else if(node.get_children()[i].get_type()==ast_dynamic_id)
|
||||||
checked_dynamic_ids=true;
|
checked_dynamic_ids=true;
|
||||||
if(checked_default_val && node.get_children()[i].get_type()!=ast_default_arg)
|
if(checked_default_val && node.get_children()[i].get_type()!=ast_default_arg)
|
||||||
die(node.get_children()[i].get_line(),"default argument must be the end of argument list: "+args_format);
|
die(node.get_children()[i].get_line(),"must use default arguments until the end of argument list: "+args_format);
|
||||||
if(checked_dynamic_ids && i!=node_child_size-1)
|
if(checked_dynamic_ids && i!=node_child_size-1)
|
||||||
die(node.get_children()[i].get_line(),"dynamic identifier must be the end of argument list: "+args_format);
|
die(node.get_children()[i].get_line(),"dynamic identifier must be the end of argument list: "+args_format);
|
||||||
}
|
}
|
||||||
|
@ -494,9 +500,9 @@ nasal_ast nasal_parse::expr()
|
||||||
case tok_if: node=conditional(); break;
|
case tok_if: node=conditional(); break;
|
||||||
case tok_continue: node=continue_expr(); break;
|
case tok_continue: node=continue_expr(); break;
|
||||||
case tok_break: node=break_expr(); break;
|
case tok_break: node=break_expr(); break;
|
||||||
case tok_ret: node=ret_expr(); break;
|
case tok_ret: node=ret_expr(); break;
|
||||||
case tok_semi: break;
|
case tok_semi: break;
|
||||||
default: die(error_line,"error token \""+tok_list[ptr].str+"\"");break;
|
default:error_token.push_back(tok_list[ptr]);++ptr;break;
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
@ -511,22 +517,18 @@ nasal_ast nasal_parse::exprs_gen()
|
||||||
if(tok_list[ptr].type==tok_lbrace)
|
if(tok_list[ptr].type==tok_lbrace)
|
||||||
{
|
{
|
||||||
match(tok_lbrace);
|
match(tok_lbrace);
|
||||||
while(tok_list[ptr].type!=tok_rbrace)
|
while(tok_list[ptr].type!=tok_rbrace && tok_list[ptr].type!=tok_eof)
|
||||||
{
|
{
|
||||||
node.add_child(expr());
|
node.add_child(expr());
|
||||||
if(tok_list[ptr].type==tok_semi)
|
if(tok_list[ptr].type==tok_semi)
|
||||||
match(tok_semi);
|
match(tok_semi);
|
||||||
else if(need_semi_check(node.get_children().back()))
|
else if(need_semi_check(node.get_children().back()) && tok_list[ptr].type!=tok_rbrace)
|
||||||
{
|
{
|
||||||
// the last expression can be recognized without semi
|
// the last expression can be recognized without semi
|
||||||
if(tok_list[ptr].type!=tok_rbrace)
|
die(error_line,"expected \";\"");
|
||||||
{
|
|
||||||
die(error_line,"expected \";\"");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match(tok_rbrace);
|
match(tok_rbrace,"expected \'}\' when generating expressions");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -730,6 +732,10 @@ nasal_ast nasal_parse::callh()
|
||||||
}
|
}
|
||||||
nasal_ast nasal_parse::callv()
|
nasal_ast nasal_parse::callv()
|
||||||
{
|
{
|
||||||
|
// panic set for this token is not ','
|
||||||
|
// this is the FIRST set of subvec
|
||||||
|
// array end with tok_null=0
|
||||||
|
int panic_set[]={tok_id,tok_str,tok_num,tok_not,tok_sub,tok_nil,tok_func,tok_var,tok_lcurve,tok_lbrace,tok_lbracket,tok_colon,tok_null};
|
||||||
nasal_ast node(tok_list[ptr].line,ast_callv);
|
nasal_ast node(tok_list[ptr].line,ast_callv);
|
||||||
match(tok_lbracket);
|
match(tok_lbracket);
|
||||||
while(tok_list[ptr].type!=tok_rbracket)
|
while(tok_list[ptr].type!=tok_rbracket)
|
||||||
|
@ -737,14 +743,20 @@ nasal_ast nasal_parse::callv()
|
||||||
node.add_child(subvec());
|
node.add_child(subvec());
|
||||||
if(tok_list[ptr].type==tok_comma)
|
if(tok_list[ptr].type==tok_comma)
|
||||||
match(tok_comma);
|
match(tok_comma);
|
||||||
else if(tok_list[ptr].type!=tok_rbracket)
|
else if(tok_list[ptr].type==tok_eof)
|
||||||
|
break;
|
||||||
|
else if(tok_list[ptr].type!=tok_rbracket && !check_comma(panic_set))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
match(tok_rbracket);
|
match(tok_rbracket,"expected \']\' when calling vector");
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
nasal_ast nasal_parse::callf()
|
nasal_ast nasal_parse::callf()
|
||||||
{
|
{
|
||||||
|
// panic set for this token is not ','
|
||||||
|
// this is the FIRST set of calculation/hashmember
|
||||||
|
// array end with tok_null=0
|
||||||
|
int panic_set[]={tok_id,tok_str,tok_num,tok_not,tok_sub,tok_nil,tok_func,tok_var,tok_lcurve,tok_lbrace,tok_lbracket,tok_null};
|
||||||
nasal_ast node(tok_list[ptr].line,ast_callf);
|
nasal_ast node(tok_list[ptr].line,ast_callf);
|
||||||
bool special_call=check_special_call();
|
bool special_call=check_special_call();
|
||||||
match(tok_lcurve);
|
match(tok_lcurve);
|
||||||
|
@ -753,28 +765,23 @@ nasal_ast nasal_parse::callf()
|
||||||
node.add_child(special_call?hmem_gen():calc());
|
node.add_child(special_call?hmem_gen():calc());
|
||||||
if(tok_list[ptr].type==tok_comma)
|
if(tok_list[ptr].type==tok_comma)
|
||||||
match(tok_comma);
|
match(tok_comma);
|
||||||
else if(tok_list[ptr].type!=tok_rcurve)
|
else if(tok_list[ptr].type==tok_eof)
|
||||||
|
break;
|
||||||
|
else if(tok_list[ptr].type!=tok_rcurve && !check_comma(panic_set))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
match(tok_rcurve);
|
match(tok_rcurve,"expected \')\' when calling function");
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
nasal_ast nasal_parse::subvec()
|
nasal_ast nasal_parse::subvec()
|
||||||
{
|
{
|
||||||
nasal_ast node;
|
nasal_ast node=tok_list[ptr].type==tok_colon?nil_gen():calc();
|
||||||
if(tok_list[ptr].type==tok_colon)
|
|
||||||
node=nil_gen();
|
|
||||||
else
|
|
||||||
node=calc();
|
|
||||||
if(tok_list[ptr].type==tok_colon)
|
if(tok_list[ptr].type==tok_colon)
|
||||||
{
|
{
|
||||||
nasal_ast tmp(node.get_line(),ast_subvec);
|
nasal_ast tmp(node.get_line(),ast_subvec);
|
||||||
match(tok_colon);
|
match(tok_colon);
|
||||||
tmp.add_child(node);
|
tmp.add_child(node);
|
||||||
if(tok_list[ptr].type==tok_comma || tok_list[ptr].type==tok_rbracket)
|
tmp.add_child((tok_list[ptr].type==tok_comma || tok_list[ptr].type==tok_rbracket)?nil_gen():calc());
|
||||||
tmp.add_child(nil_gen());
|
|
||||||
else
|
|
||||||
tmp.add_child(calc());
|
|
||||||
node=tmp;
|
node=tmp;
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
|
@ -789,7 +796,7 @@ nasal_ast nasal_parse::definition()
|
||||||
{
|
{
|
||||||
case tok_id: node.add_child(id_gen());match(tok_id); break;
|
case tok_id: node.add_child(id_gen());match(tok_id); break;
|
||||||
case tok_lcurve: node.add_child(var_outcurve_def()); break;
|
case tok_lcurve: node.add_child(var_outcurve_def()); break;
|
||||||
default: die(error_line,"expected identifier"); return node;
|
default: die(error_line,"expected identifier"); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(tok_list[ptr].type==tok_lcurve)
|
else if(tok_list[ptr].type==tok_lcurve)
|
||||||
|
@ -812,8 +819,6 @@ nasal_ast nasal_parse::var_incurve_def()
|
||||||
match(tok_lcurve);
|
match(tok_lcurve);
|
||||||
match(tok_var);
|
match(tok_var);
|
||||||
node=multi_id();
|
node=multi_id();
|
||||||
if(is_call(tok_list[ptr].type))
|
|
||||||
die(error_line,"don\'t call identifier in multi-definition");
|
|
||||||
match(tok_rcurve);
|
match(tok_rcurve);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
@ -822,8 +827,6 @@ nasal_ast nasal_parse::var_outcurve_def()
|
||||||
nasal_ast node;
|
nasal_ast node;
|
||||||
match(tok_lcurve);
|
match(tok_lcurve);
|
||||||
node=multi_id();
|
node=multi_id();
|
||||||
if(is_call(tok_list[ptr].type))
|
|
||||||
die(error_line,"don\'t call identifier in multi-definition");
|
|
||||||
match(tok_rcurve);
|
match(tok_rcurve);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
@ -836,15 +839,24 @@ nasal_ast nasal_parse::multi_id()
|
||||||
{
|
{
|
||||||
node.add_child(id_gen());
|
node.add_child(id_gen());
|
||||||
match(tok_id);
|
match(tok_id);
|
||||||
if(tok_list[ptr].type!=tok_comma)
|
if(is_call(tok_list[ptr].type))
|
||||||
|
{
|
||||||
|
call_scalar();// recognize calls but this is still a syntax error
|
||||||
|
die(error_line,"cannot call identifier in multi-definition");
|
||||||
|
}
|
||||||
|
if(tok_list[ptr].type==tok_comma)
|
||||||
|
match(tok_comma);
|
||||||
|
else if(tok_list[ptr].type==tok_id)// first set of identifier
|
||||||
|
die(error_line,"expected \',\' between identifiers");
|
||||||
|
else
|
||||||
break;
|
break;
|
||||||
match(tok_comma);
|
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
nasal_ast nasal_parse::multi_scalar(bool check_call_memory)
|
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
|
// if check_call_memory is true,we will check if value called here can reach a memory space
|
||||||
|
int panic_set[]={tok_id,tok_str,tok_num,tok_not,tok_sub,tok_nil,tok_func,tok_var,tok_lcurve,tok_lbrace,tok_lbracket,tok_null};
|
||||||
nasal_ast node(tok_list[ptr].line,ast_multi_scalar);
|
nasal_ast node(tok_list[ptr].line,ast_multi_scalar);
|
||||||
match(tok_lcurve);
|
match(tok_lcurve);
|
||||||
while(tok_list[ptr].type!=tok_rcurve)
|
while(tok_list[ptr].type!=tok_rcurve)
|
||||||
|
@ -854,10 +866,12 @@ nasal_ast nasal_parse::multi_scalar(bool check_call_memory)
|
||||||
check_memory_reachable(node.get_children().back());
|
check_memory_reachable(node.get_children().back());
|
||||||
if(tok_list[ptr].type==tok_comma)
|
if(tok_list[ptr].type==tok_comma)
|
||||||
match(tok_comma);
|
match(tok_comma);
|
||||||
else if(tok_list[ptr].type!=tok_rcurve)
|
else if(tok_list[ptr].type==tok_eof)
|
||||||
|
break;
|
||||||
|
else if(tok_list[ptr].type!=tok_rcurve && !check_comma(panic_set))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
match(tok_rcurve);
|
match(tok_rcurve,"expected \')\' after multi-scalar");
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
nasal_ast nasal_parse::multi_assgin()
|
nasal_ast nasal_parse::multi_assgin()
|
||||||
|
@ -927,7 +941,8 @@ nasal_ast nasal_parse::for_loop()
|
||||||
);
|
);
|
||||||
else
|
else
|
||||||
node.add_child(calc());
|
node.add_child(calc());
|
||||||
match(tok_semi);
|
// check first semi
|
||||||
|
match(tok_semi,"expected \';\' in for(;;)");
|
||||||
// conditional expression
|
// conditional expression
|
||||||
if(tok_list[ptr].type==tok_eof)
|
if(tok_list[ptr].type==tok_eof)
|
||||||
die(error_line,"expected conditional expression");
|
die(error_line,"expected conditional expression");
|
||||||
|
@ -935,7 +950,8 @@ nasal_ast nasal_parse::for_loop()
|
||||||
node.add_child(null_node_gen());
|
node.add_child(null_node_gen());
|
||||||
else
|
else
|
||||||
node.add_child(calc());
|
node.add_child(calc());
|
||||||
match(tok_semi);
|
// check second semi
|
||||||
|
match(tok_semi,"expected \';\' in for(;;)");
|
||||||
//after loop expression
|
//after loop expression
|
||||||
if(tok_list[ptr].type==tok_eof)
|
if(tok_list[ptr].type==tok_eof)
|
||||||
die(error_line,"expected calculation");
|
die(error_line,"expected calculation");
|
||||||
|
@ -959,9 +975,11 @@ nasal_ast nasal_parse::forei_loop()
|
||||||
// first expression
|
// first expression
|
||||||
// foreach/forindex must have an iterator to loop through
|
// foreach/forindex must have an iterator to loop through
|
||||||
if(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");
|
die(error_line,"expected iterator");
|
||||||
node.add_child(new_iter_gen());
|
node.add_child(new_iter_gen());
|
||||||
match(tok_semi);
|
// check semi
|
||||||
|
match(tok_semi,"expected \';\' in foreach/forindex(iter;vector)");
|
||||||
|
// check vector
|
||||||
if(tok_list[ptr].type==tok_eof)
|
if(tok_list[ptr].type==tok_eof)
|
||||||
die(error_line,"expected vector");
|
die(error_line,"expected vector");
|
||||||
node.add_child(calc());
|
node.add_child(calc());
|
||||||
|
@ -969,7 +987,6 @@ nasal_ast nasal_parse::forei_loop()
|
||||||
node.add_child(exprs_gen());
|
node.add_child(exprs_gen());
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
nasal_ast nasal_parse::new_iter_gen()
|
nasal_ast nasal_parse::new_iter_gen()
|
||||||
{
|
{
|
||||||
nasal_ast node(tok_list[ptr].line,ast_null);
|
nasal_ast node(tok_list[ptr].line,ast_null);
|
||||||
|
@ -990,7 +1007,6 @@ nasal_ast nasal_parse::new_iter_gen()
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
nasal_ast nasal_parse::conditional()
|
nasal_ast nasal_parse::conditional()
|
||||||
{
|
{
|
||||||
nasal_ast node(tok_list[ptr].line,ast_conditional);
|
nasal_ast node(tok_list[ptr].line,ast_conditional);
|
||||||
|
|
|
@ -126,7 +126,7 @@ var backward=func(x)
|
||||||
var cnt=0;
|
var cnt=0;
|
||||||
var show=0;
|
var show=0;
|
||||||
var error=100;
|
var error=100;
|
||||||
while(error>0.001)
|
while(error>0.0005)
|
||||||
{
|
{
|
||||||
error=0;
|
error=0;
|
||||||
for(var i=0;i<4;i+=1)
|
for(var i=0;i<4;i+=1)
|
||||||
|
|
Loading…
Reference in New Issue