Update
This commit is contained in:
parent
64e314b539
commit
f0b5ef86ac
|
@ -0,0 +1,58 @@
|
||||||
|
for(;;)break;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
var a=1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for(var i=1;;)break;
|
||||||
|
for(var i=1;;i+=1)break;
|
||||||
|
for(var i=1;i<10;i+=1)print(i);
|
||||||
|
|
||||||
|
while(1)break;
|
||||||
|
var j=0;
|
||||||
|
while(j<10)
|
||||||
|
{
|
||||||
|
print(j);
|
||||||
|
j+=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
forindex(var j;[0,1,2,3])print(j);
|
||||||
|
forindex(var j;[0,1,2,3])
|
||||||
|
{
|
||||||
|
var a=j;
|
||||||
|
print(a*a);
|
||||||
|
}
|
||||||
|
foreach(var j;[0,1,2,3])print([0,1,2,3][j]);
|
||||||
|
foreach(var j;[0,1,2,3])
|
||||||
|
{
|
||||||
|
var a=[0,1,2,3][j];
|
||||||
|
print(a*a-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
var condition_true=1;
|
||||||
|
var condition_false=0;
|
||||||
|
if(condition_true)
|
||||||
|
{
|
||||||
|
var a=1;
|
||||||
|
}
|
||||||
|
else if(!condition_false)
|
||||||
|
{
|
||||||
|
var b=1;
|
||||||
|
}
|
||||||
|
elsif(!condition_true and condition_false)
|
||||||
|
{
|
||||||
|
print("impossible");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var c=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(condition_true)
|
||||||
|
var a=1;
|
||||||
|
else if(!condition_false)
|
||||||
|
var b=1;
|
||||||
|
elsif(!condition_true and condition_false)
|
||||||
|
print("impossible");
|
||||||
|
else
|
||||||
|
var c=1;
|
|
@ -156,6 +156,7 @@ enum parse_error_type
|
||||||
{
|
{
|
||||||
parse_unknown_error, // unknown error
|
parse_unknown_error, // unknown error
|
||||||
error_token_in_main, // when a token should not be the begin of a statement in main
|
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_semi,
|
||||||
|
|
||||||
|
@ -198,6 +199,11 @@ void print_parse_error(int error_type,int line,int error_token_type=__stack_end)
|
||||||
print_parse_token(error_token_type);
|
print_parse_token(error_token_type);
|
||||||
std::cout<<"\' in main scope."<<std::endl;
|
std::cout<<"\' in main scope."<<std::endl;
|
||||||
break;
|
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:
|
case lack_semi:
|
||||||
std::cout<<error_info_head<<line<<": expect a \';\' at the end of the statement."<<std::endl;break;
|
std::cout<<error_info_head<<line<<": expect a \';\' at the end of the statement."<<std::endl;break;
|
||||||
case definition_lack_id:
|
case definition_lack_id:
|
||||||
|
@ -290,4 +296,20 @@ void print_parse_error(int error_type,int line,int error_token_type=__stack_end)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// statement_type is used to mark a statement that parser has generated
|
||||||
|
// with this parser will check if this statement has ';' at its end
|
||||||
|
enum statement_type
|
||||||
|
{
|
||||||
|
stat_null,
|
||||||
|
stat_normal_definition=1,
|
||||||
|
stat_assignment,
|
||||||
|
stat_calculation,
|
||||||
|
stat_function_definition,
|
||||||
|
stat_loop,
|
||||||
|
stat_choose,
|
||||||
|
stat_return,
|
||||||
|
stat_continue,
|
||||||
|
stat_break,
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
class nasal_parse
|
class nasal_parse
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
int statement_generate_state;
|
||||||
std::stack<token> parse_token_stream;
|
std::stack<token> parse_token_stream;
|
||||||
std::stack<token> checked_tokens;
|
std::stack<token> checked_tokens;
|
||||||
token this_token;
|
token this_token;
|
||||||
|
@ -22,6 +23,7 @@ class nasal_parse
|
||||||
// abstract_syntax_tree generation
|
// abstract_syntax_tree generation
|
||||||
bool check_comma_in_curve();
|
bool check_comma_in_curve();
|
||||||
void main_generate();
|
void main_generate();
|
||||||
|
void statements_block_generate(abstract_syntax_tree&);
|
||||||
abstract_syntax_tree multi_scalar_assignment();
|
abstract_syntax_tree multi_scalar_assignment();
|
||||||
abstract_syntax_tree calculation();
|
abstract_syntax_tree calculation();
|
||||||
abstract_syntax_tree and_calculation();
|
abstract_syntax_tree and_calculation();
|
||||||
|
@ -164,6 +166,8 @@ bool nasal_parse::check_comma_in_curve()
|
||||||
|
|
||||||
void nasal_parse::main_generate()
|
void nasal_parse::main_generate()
|
||||||
{
|
{
|
||||||
|
statement_generate_state=stat_null;
|
||||||
|
// initialize state
|
||||||
error=0;
|
error=0;
|
||||||
warning=0;
|
warning=0;
|
||||||
// initialize error and warning
|
// initialize error and warning
|
||||||
|
@ -213,11 +217,130 @@ void nasal_parse::main_generate()
|
||||||
print_parse_error(error_token_in_main,this_token.line,this_token.type);
|
print_parse_error(error_token_in_main,this_token.line,this_token.type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
std::cout<<">>[Parse] complete generation. "<<error<<" error(s), "<<warning<<" warning(s)."<<std::endl;
|
std::cout<<">>[Parse] complete generation. "<<error<<" error(s), "<<warning<<" warning(s)."<<std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nasal_parse::statements_block_generate(abstract_syntax_tree& tmp_node)
|
||||||
|
{
|
||||||
|
abstract_syntax_tree continue_break_node;
|
||||||
|
this->get_token();
|
||||||
|
if(this_token.type!=__left_brace)
|
||||||
|
{
|
||||||
|
switch(this_token.type)
|
||||||
|
{
|
||||||
|
case __var:
|
||||||
|
this->push_token();
|
||||||
|
tmp_node.get_children().push_back(definition());
|
||||||
|
break;
|
||||||
|
case __nor_operator: case __sub_operator:
|
||||||
|
case __number: case __nil: case __string: case __id:
|
||||||
|
case __left_bracket: case __left_brace:
|
||||||
|
case __func:
|
||||||
|
this->push_token();
|
||||||
|
tmp_node.add_children(calculation());
|
||||||
|
break;
|
||||||
|
case __left_curve:
|
||||||
|
this->push_token();
|
||||||
|
if(check_comma_in_curve())
|
||||||
|
tmp_node.add_children(multi_scalar_assignment());
|
||||||
|
else
|
||||||
|
tmp_node.add_children(calculation());
|
||||||
|
// '(' is the beginning of too many statements
|
||||||
|
// '(' var id,id,id ')'
|
||||||
|
// '(' calculation ')'
|
||||||
|
// '(' scalar,scalar,scalar ')' '=' '(' scalar,scalar,scalar ')'
|
||||||
|
break;
|
||||||
|
case __if:
|
||||||
|
this->push_token();
|
||||||
|
tmp_node.add_children(choose_expr());
|
||||||
|
break;
|
||||||
|
case __while: case __for: case __foreach: case __forindex:
|
||||||
|
this->push_token();
|
||||||
|
tmp_node.add_children(loop_expr());
|
||||||
|
break;
|
||||||
|
case __return:
|
||||||
|
this->push_token();
|
||||||
|
tmp_node.add_children(return_expr());
|
||||||
|
break;
|
||||||
|
case __continue:
|
||||||
|
case __break:
|
||||||
|
continue_break_node.set_node_line(this_token.line);
|
||||||
|
continue_break_node.set_node_type(this_token.type);
|
||||||
|
tmp_node.add_children(continue_break_node);
|
||||||
|
break;
|
||||||
|
case __semi:this->push_token();break;
|
||||||
|
case __stack_end:break;
|
||||||
|
default:
|
||||||
|
++error;
|
||||||
|
print_parse_error(error_token_in_block,this_token.line,this_token.type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while(this_token.type!=__right_brace && !parse_token_stream.empty() && parse_token_stream.top().type!=__stack_end)
|
||||||
|
{
|
||||||
|
this->get_token();
|
||||||
|
switch(this_token.type)
|
||||||
|
{
|
||||||
|
case __var:
|
||||||
|
this->push_token();
|
||||||
|
tmp_node.get_children().push_back(definition());
|
||||||
|
break;
|
||||||
|
case __nor_operator: case __sub_operator:
|
||||||
|
case __number: case __nil: case __string: case __id:
|
||||||
|
case __left_bracket: case __left_brace:
|
||||||
|
case __func:
|
||||||
|
this->push_token();
|
||||||
|
tmp_node.add_children(calculation());
|
||||||
|
break;
|
||||||
|
case __left_curve:
|
||||||
|
this->push_token();
|
||||||
|
if(check_comma_in_curve())
|
||||||
|
tmp_node.add_children(multi_scalar_assignment());
|
||||||
|
else
|
||||||
|
tmp_node.add_children(calculation());
|
||||||
|
// '(' is the beginning of too many statements
|
||||||
|
// '(' var id,id,id ')'
|
||||||
|
// '(' calculation ')'
|
||||||
|
// '(' scalar,scalar,scalar ')' '=' '(' scalar,scalar,scalar ')'
|
||||||
|
break;
|
||||||
|
case __if:
|
||||||
|
this->push_token();
|
||||||
|
tmp_node.add_children(choose_expr());
|
||||||
|
break;
|
||||||
|
case __while: case __for: case __foreach: case __forindex:
|
||||||
|
this->push_token();
|
||||||
|
tmp_node.add_children(loop_expr());
|
||||||
|
break;
|
||||||
|
case __return:
|
||||||
|
this->push_token();
|
||||||
|
tmp_node.add_children(return_expr());
|
||||||
|
break;
|
||||||
|
case __continue:
|
||||||
|
case __break:
|
||||||
|
continue_break_node.set_node_line(this_token.line);
|
||||||
|
continue_break_node.set_node_type(this_token.type);
|
||||||
|
tmp_node.add_children(continue_break_node);
|
||||||
|
break;
|
||||||
|
case __semi:break;
|
||||||
|
case __stack_end:break;
|
||||||
|
default:
|
||||||
|
++error;
|
||||||
|
print_parse_error(error_token_in_block,this_token.line,this_token.type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this->get_token();
|
||||||
|
if(this_token.type!=__right_brace)
|
||||||
|
this->push_token();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
abstract_syntax_tree nasal_parse::multi_scalar_assignment()
|
abstract_syntax_tree nasal_parse::multi_scalar_assignment()
|
||||||
{
|
{
|
||||||
abstract_syntax_tree assignment_node;
|
abstract_syntax_tree assignment_node;
|
||||||
|
@ -862,103 +985,7 @@ abstract_syntax_tree nasal_parse::function_generate()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
this->push_token();
|
this->push_token();
|
||||||
this->get_token();
|
statements_block_generate(function_node);
|
||||||
if(this_token.type!=__left_brace)
|
|
||||||
{
|
|
||||||
switch(this_token.type)
|
|
||||||
{
|
|
||||||
case __var:
|
|
||||||
this->push_token();
|
|
||||||
function_node.get_children().push_back(definition());
|
|
||||||
break;
|
|
||||||
case __nor_operator: case __sub_operator:
|
|
||||||
case __number: case __nil: case __string: case __id:
|
|
||||||
case __left_bracket: case __left_brace:
|
|
||||||
case __func:
|
|
||||||
this->push_token();
|
|
||||||
function_node.add_children(calculation());
|
|
||||||
break;
|
|
||||||
case __left_curve:
|
|
||||||
this->push_token();
|
|
||||||
if(check_comma_in_curve())
|
|
||||||
function_node.add_children(multi_scalar_assignment());
|
|
||||||
else
|
|
||||||
function_node.add_children(calculation());
|
|
||||||
// '(' is the beginning of too many statements
|
|
||||||
// '(' var id,id,id ')'
|
|
||||||
// '(' calculation ')'
|
|
||||||
// '(' scalar,scalar,scalar ')' '=' '(' scalar,scalar,scalar ')'
|
|
||||||
break;
|
|
||||||
case __if:
|
|
||||||
this->push_token();
|
|
||||||
function_node.add_children(choose_expr());
|
|
||||||
break;
|
|
||||||
case __while: case __for: case __foreach: case __forindex:
|
|
||||||
this->push_token();
|
|
||||||
function_node.add_children(loop_expr());
|
|
||||||
break;
|
|
||||||
case __return:
|
|
||||||
this->push_token();
|
|
||||||
function_node.add_children(return_expr());
|
|
||||||
break;
|
|
||||||
case __semi:this->push_token();break;
|
|
||||||
case __stack_end:break;
|
|
||||||
default:
|
|
||||||
++error;
|
|
||||||
print_parse_error(error_token_in_main,this_token.line,this_token.type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
while(this_token.type!=__right_brace && !parse_token_stream.empty() && parse_token_stream.top().type!=__stack_end)
|
|
||||||
{
|
|
||||||
this->get_token();
|
|
||||||
switch(this_token.type)
|
|
||||||
{
|
|
||||||
case __var:
|
|
||||||
this->push_token();
|
|
||||||
function_node.get_children().push_back(definition());
|
|
||||||
break;
|
|
||||||
case __nor_operator: case __sub_operator:
|
|
||||||
case __number: case __nil: case __string: case __id:
|
|
||||||
case __left_bracket: case __left_brace:
|
|
||||||
case __func:
|
|
||||||
this->push_token();
|
|
||||||
function_node.add_children(calculation());
|
|
||||||
break;
|
|
||||||
case __left_curve:
|
|
||||||
this->push_token();
|
|
||||||
if(check_comma_in_curve())
|
|
||||||
function_node.add_children(multi_scalar_assignment());
|
|
||||||
else
|
|
||||||
function_node.add_children(calculation());
|
|
||||||
// '(' is the beginning of too many statements
|
|
||||||
// '(' var id,id,id ')'
|
|
||||||
// '(' calculation ')'
|
|
||||||
// '(' scalar,scalar,scalar ')' '=' '(' scalar,scalar,scalar ')'
|
|
||||||
break;
|
|
||||||
case __if:
|
|
||||||
this->push_token();
|
|
||||||
function_node.add_children(choose_expr());
|
|
||||||
break;
|
|
||||||
case __while: case __for: case __foreach: case __forindex:
|
|
||||||
this->push_token();
|
|
||||||
function_node.add_children(loop_expr());
|
|
||||||
break;
|
|
||||||
case __return:
|
|
||||||
this->push_token();
|
|
||||||
function_node.add_children(return_expr());
|
|
||||||
break;
|
|
||||||
case __semi:break;
|
|
||||||
case __stack_end:break;
|
|
||||||
default:
|
|
||||||
++error;
|
|
||||||
print_parse_error(error_token_in_main,this_token.line,this_token.type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return function_node;
|
return function_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1073,12 +1100,25 @@ abstract_syntax_tree nasal_parse::loop_expr()
|
||||||
}
|
}
|
||||||
else if(this_token.type==__while)
|
else if(this_token.type==__while)
|
||||||
{
|
{
|
||||||
;
|
this->get_token();
|
||||||
|
if(this_token.type!=__left_curve)
|
||||||
|
{
|
||||||
|
++error;
|
||||||
|
print_parse_error(lack_left_curve,this_token.line,this_token.type);
|
||||||
|
}
|
||||||
|
loop_main_node.add_children(calculation());
|
||||||
|
this->get_token();
|
||||||
|
if(this_token.type!=__right_curve)
|
||||||
|
{
|
||||||
|
++error;
|
||||||
|
print_parse_error(lack_right_curve,this_token.line,this_token.type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
statements_block_generate(loop_main_node);
|
||||||
return loop_main_node;
|
return loop_main_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1107,9 +1147,48 @@ abstract_syntax_tree nasal_parse::choose_expr()
|
||||||
++error;
|
++error;
|
||||||
print_parse_error(lack_right_curve,this_token.line);
|
print_parse_error(lack_right_curve,this_token.line);
|
||||||
}
|
}
|
||||||
|
statements_block_generate(if_node);
|
||||||
// add statements
|
// add statements
|
||||||
|
this->get_token();
|
||||||
|
if(this_token.type==__elsif)
|
||||||
|
{
|
||||||
|
while(this_token.type==__elsif)
|
||||||
|
{
|
||||||
|
elsif_node.set_clear();
|
||||||
|
elsif_node.set_node_line(this_token.line);
|
||||||
|
elsif_node.set_node_type(__elsif);
|
||||||
|
|
||||||
// get elsif or else if
|
this->get_token();
|
||||||
|
if(this_token.type!=__left_curve)
|
||||||
|
{
|
||||||
|
++error;
|
||||||
|
print_parse_error(lack_left_curve,this_token.line,this_token.type);
|
||||||
|
}
|
||||||
|
elsif_node.add_children(calculation());
|
||||||
|
this->get_token();
|
||||||
|
if(this_token.type!=__right_curve)
|
||||||
|
{
|
||||||
|
++error;
|
||||||
|
print_parse_error(lack_right_curve,this_token.line,this_token.type);
|
||||||
|
}
|
||||||
|
statements_block_generate(elsif_node);
|
||||||
|
choose_main_node.add_children(elsif_node);
|
||||||
|
}
|
||||||
|
this->push_token();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
this->push_token();
|
||||||
|
this->get_token();
|
||||||
|
if(this_token.type==__else)
|
||||||
|
{
|
||||||
|
else_node.set_node_line(this_token.type);
|
||||||
|
else_node.set_node_type(__else);
|
||||||
|
statements_block_generate(else_node);
|
||||||
|
choose_main_node.add_children(else_node);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
this->push_token();
|
||||||
|
// get elsif or else
|
||||||
return choose_main_node;
|
return choose_main_node;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,6 +12,7 @@ nil;
|
||||||
[];
|
[];
|
||||||
{};
|
{};
|
||||||
[0,1,2,3,4,5][2]; # 2
|
[0,1,2,3,4,5][2]; # 2
|
||||||
|
([0,1,2,3,4])[2]; # 2
|
||||||
[0,1,2,3,4,5][5,4,3,2+1][0:2][0]; # 5
|
[0,1,2,3,4,5][5,4,3,2+1][0:2][0]; # 5
|
||||||
{str:"hello"}.str; # "hello"
|
{str:"hello"}.str; # "hello"
|
||||||
{str:"hello"}["str"]; # "hello"
|
{str:"hello"}["str"]; # "hello"
|
||||||
|
|
Loading…
Reference in New Issue