This commit is contained in:
Valk Richard Li 2020-01-17 21:43:10 +08:00 committed by GitHub
parent cb6f4cad4f
commit 0e5ce8d7fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 291 additions and 25 deletions

View File

@ -14,7 +14,7 @@ class abstract_syntax_tree
double var_number; double var_number;
std::string var_string; std::string var_string;
std::string var_name; std::string var_name;
// var_name is set for __id
public: public:
// basic // basic
abstract_syntax_tree(); abstract_syntax_tree();
@ -97,7 +97,7 @@ void abstract_syntax_tree::print_tree(const int n)
case __string:std::cout<<": "<<var_string;break; case __string:std::cout<<": "<<var_string;break;
case __id: case __id:
case __dynamic_id: case __dynamic_id:
case __call_array: case __call_vector:
case __call_hash: case __call_hash:
case __call_function:std::cout<<": "<<var_name;break; case __call_function:std::cout<<": "<<var_name;break;
} }

View File

@ -45,14 +45,15 @@ enum parse_token_type
__number,__string,__id,__dynamic_id, __number,__string,__id,__dynamic_id,
// basic scalar type: number string identifier dynamic_identifier // basic scalar type: number string identifier dynamic_identifier
// absttract_syntax_tree type below // abstract_syntax_tree type below
// abstract_syntax_tree also uses the types above, such as operators
__root, __root,
__null_type, __null_type,
__multi_id, __multi_id,
__parameters, __parameters,
__list,__hash, __vector,__hash,
__hash_member, __hash_member,
__call_function,__call_array,__call_hash, __call_function,__call_vector,__call_hash,
__normal_statement_block, __normal_statement_block,
__definition,__assignment, __definition,__assignment,
__function,__loop,__ifelse __function,__loop,__ifelse
@ -126,11 +127,11 @@ void print_parse_token(int type)
case __null_type: context="null_type"; break; case __null_type: context="null_type"; break;
case __multi_id: context="identifiers"; break; case __multi_id: context="identifiers"; break;
case __parameters: context="parameters"; break; case __parameters: context="parameters"; break;
case __list: context="list"; break; case __vector: context="vector"; break;
case __hash: context="hash"; break; case __hash: context="hash"; break;
case __hash_member: context="hash_member"; break; case __hash_member: context="hash_member"; break;
case __call_function: context="call_func"; break; case __call_function: context="call_func"; break;
case __call_array: context="call_array"; break; case __call_vector: context="call_vector"; break;
case __call_hash: context="call_hash"; break; case __call_hash: context="call_hash"; break;
case __normal_statement_block:context="block"; break; case __normal_statement_block:context="block"; break;
case __definition: context="definition"; break; case __definition: context="definition"; break;
@ -156,6 +157,9 @@ enum parse_error_type
error_begin_token_of_scalar, // in scalar_generate() error_begin_token_of_scalar, // in scalar_generate()
lack_left_curve, // lack left curve lack_left_curve, // lack left curve
lack_right_curve, // lack right curve lack_right_curve, // lack right curve
parameter_lack_part, // parameter lack a ')' or identifier
parameter_lack_curve, // parameter lack a ',' or ')'
call_hash_lack_id, // lack identifier when calling an identifier
}; };
void print_parse_error(int error_type,int line,int error_token_type=__stack_end) void print_parse_error(int error_type,int line,int error_token_type=__stack_end)
@ -188,6 +192,12 @@ void print_parse_error(int error_type,int line,int error_token_type=__stack_end)
std::cout<<error_info_head<<line<<": expect a \'(\' here."<<std::endl;break; std::cout<<error_info_head<<line<<": expect a \'(\' here."<<std::endl;break;
case lack_right_curve: case lack_right_curve:
std::cout<<error_info_head<<line<<": expect a \')\' here."<<std::endl;break; std::cout<<error_info_head<<line<<": expect a \')\' here."<<std::endl;break;
case parameter_lack_part:
std::cout<<error_info_head<<line<<": expect a \')\' or identifier here."<<std::endl;break;
case parameter_lack_curve:
std::cout<<error_info_head<<line<<": expect a \')\' or \',\' here."<<std::endl;break;
case call_hash_lack_id:
std::cout<<error_info_head<<line<<": expect an identifier after \'.\' ."<<std::endl;break;
default: default:
std::cout<<error_info_head<<line<<": unknown parse error. error id: other_type."<<std::endl;break; std::cout<<error_info_head<<line<<": unknown parse error. error id: other_type."<<std::endl;break;
} }

View File

@ -21,7 +21,14 @@ class nasal_parse
// abstract_syntax_tree generation // abstract_syntax_tree generation
void main_generate(); void main_generate();
abstract_syntax_tree calculation();
abstract_syntax_tree and_calculation();
abstract_syntax_tree or_calculation();
abstract_syntax_tree additive_calculation();
abstract_syntax_tree multive_calculation();
abstract_syntax_tree scalar_generate(); abstract_syntax_tree scalar_generate();
abstract_syntax_tree hash_generate();
abstract_syntax_tree vector_generate();
abstract_syntax_tree function_generate(); abstract_syntax_tree function_generate();
abstract_syntax_tree var_outside_definition(); abstract_syntax_tree var_outside_definition();
abstract_syntax_tree var_inside_definition(); abstract_syntax_tree var_inside_definition();
@ -151,7 +158,7 @@ void nasal_parse::main_generate()
case __left_curve: case __left_bracket: case __left_brace: case __left_curve: case __left_bracket: case __left_brace:
case __func: case __func:
this->push_token(); this->push_token();
root.add_children(scalar_generate()); root.add_children(calculation());
break; break;
case __if: case __if:
this->push_token(); this->push_token();
@ -173,33 +180,226 @@ void nasal_parse::main_generate()
return; return;
} }
abstract_syntax_tree nasal_parse::calculation()
{
abstract_syntax_tree calc_node;
abstract_syntax_tree tmp_node;
calc_node=and_calculation();
this->get_token();
while(this_token.type==__or_operator)
{
tmp_node.set_node_line(this_token.line);
tmp_node.set_node_type(this_token.type);
tmp_node.add_children(calc_node);
tmp_node.add_children(and_calculation());
calc_node=tmp_node;
this->get_token();
}
this->push_token();
return calc_node;
}
abstract_syntax_tree nasal_parse::and_calculation()
{
abstract_syntax_tree calc_node;
abstract_syntax_tree tmp_node;
calc_node=or_calculation();
this->get_token();
while(this_token.type==__and_operator)
{
tmp_node.set_node_line(this_token.line);
tmp_node.set_node_type(this_token.type);
tmp_node.add_children(calc_node);
tmp_node.add_children(or_calculation());
calc_node=tmp_node;
this->get_token();
}
this->push_token();
return calc_node;
}
abstract_syntax_tree nasal_parse::or_calculation()
{
abstract_syntax_tree calc_node;
abstract_syntax_tree tmp_node;
calc_node=additive_calculation();
this->get_token();
while(this_token.type==__or_operator)
{
tmp_node.set_node_line(this_token.line);
tmp_node.set_node_type(this_token.type);
tmp_node.add_children(calc_node);
tmp_node.add_children(additive_calculation());
calc_node=tmp_node;
this->get_token();
}
this->push_token();
return calc_node;
}
abstract_syntax_tree nasal_parse::additive_calculation()
{
abstract_syntax_tree calc_node;
abstract_syntax_tree tmp_node;
calc_node=multive_calculation();
this->get_token();
while((this_token.type==__add_operator) || (this_token.type==__sub_operator))
{
tmp_node.set_node_line(this_token.line);
tmp_node.set_node_type(this_token.type);
tmp_node.add_children(calc_node);
tmp_node.add_children(multive_calculation());
calc_node=tmp_node;
this->get_token();
}
this->push_token();
return calc_node;
}
abstract_syntax_tree nasal_parse::multive_calculation()
{
abstract_syntax_tree calc_node;
abstract_syntax_tree tmp_node;
this->get_token();
if((this_token.type==__sub_operator) || (this_token.type==__nor_operator))
{
calc_node.set_node_line(this_token.line);
calc_node.set_node_type(this_token.type);
abstract_syntax_tree null_node;
null_node.set_node_line(this_token.line);
null_node.set_node_type(__number);
null_node.set_var_number("0");
calc_node.add_children(null_node);
calc_node.add_children(scalar_generate());
}
else
{
this->push_token();
calc_node=scalar_generate();
}
this->get_token();
while((this_token.type==__mul_operator) || (this_token.type==__div_operator))
{
tmp_node.set_node_line(this_token.line);
tmp_node.set_node_type(this_token.type);
tmp_node.add_children(calc_node);
tmp_node.add_children(scalar_generate());
calc_node=tmp_node;
this->get_token();
}
this->push_token();
return calc_node;
}
abstract_syntax_tree nasal_parse::scalar_generate() abstract_syntax_tree nasal_parse::scalar_generate()
{ {
this->get_token(); this->get_token();
abstract_syntax_tree scalar_node; abstract_syntax_tree scalar_node;
scalar_node.set_node_line(this_token.line); scalar_node.set_node_line(this_token.line);
switch(this_token.type) switch(this_token.type)
{ {
case __nor_operator:
case __sub_operator:
break;
case __number: case __number:
case __string: scalar_node.set_node_type(__number);
case __nil: scalar_node.set_var_number(this_token.str);
case __id: break;
case __string:
scalar_node.set_node_type(__string);
scalar_node.set_var_string(this_token.str);
break;
case __nil:
scalar_node.set_node_type(__nil);
break;
case __id:
scalar_node.set_node_type(__id);
scalar_node.set_var_name(this_token.str);
break;
case __left_curve:
scalar_node=calculation();
this->get_token();
if(this_token.type!=__right_curve)
{
++error;
print_parse_error(lack_right_curve,this_token.line);
}
break;
case __left_brace:// hash
this->push_token();
scalar_node=hash_generate();
break;
case __left_bracket:// vector
this->push_token();
scalar_node=vector_generate();
break;
case __func:
this->get_token();
if(this_token.type!=__id)
{
this->push_token();
this->push_token();
scalar_node=function_generate();
}
else
{
scalar_node.set_node_type(__id);
scalar_node.set_var_name(this_token.str);
}
break; break;
case __left_curve:break;
case __left_brace:break;
case __left_bracket:break;
case __func:break;
default: default:
++error; ++error;
print_parse_error(error_begin_token_of_scalar,this_token.line,this_token.type); print_parse_error(error_begin_token_of_scalar,this_token.line,this_token.type);
break; break;
} }
this->get_token(); // check if there is a '(' or '[' or '{' after id
while((this_token.type==__left_curve) || (this_token.type==__left_bracket) || (this_token.type==__dot))
{
if(this_token.type==__left_curve)
{
}
else if(this_token.type==__left_bracket)
{
}
else if(this_token.type==__dot)
{
this->get_token();
if(this_token.type!=__id)
{
++error;
print_parse_error(call_hash_lack_id,this_token.line);
break;
}
abstract_syntax_tree identifier_node;
identifier_node.set_node_line(this_token.line);
identifier_node.set_node_type(__call_hash);
identifier_node.set_var_name(this_token.str);
scalar_node.add_children(identifier_node);
}
this->get_token();
}
this->push_token();
return scalar_node; return scalar_node;
} }
abstract_syntax_tree nasal_parse::hash_generate()
{
this->get_token(); // get '{'
abstract_syntax_tree hash_node;
hash_node.set_node_line(this_token.line);
hash_node.set_node_type(__hash);
return hash_node;
}
abstract_syntax_tree nasal_parse::vector_generate()
{
this->get_token(); // get '['
abstract_syntax_tree vector_node;
vector_node.set_node_line(this_token.line);
vector_node.set_node_type(__vector);
return vector_node;
}
abstract_syntax_tree nasal_parse::function_generate() abstract_syntax_tree nasal_parse::function_generate()
{ {
abstract_syntax_tree function_node; abstract_syntax_tree function_node;
@ -209,6 +409,63 @@ abstract_syntax_tree nasal_parse::function_generate()
function_node.set_node_line(this_token.line); function_node.set_node_line(this_token.line);
parameter_list.set_node_type(__parameters); parameter_list.set_node_type(__parameters);
parameter_list.set_node_line(this_token.line); parameter_list.set_node_line(this_token.line);
this->get_token();
if(this_token.type==__left_curve)
{
while(this_token.type!=__right_curve)
{
// check identifier
this->get_token();
if(this_token.type==__id)
{
abstract_syntax_tree parameter;
parameter.set_node_line(this_token.line);
parameter.set_node_type(__id);
parameter.set_var_name(this_token.str);
}
else if(this_token.type==__dynamic_id)
{
abstract_syntax_tree parameter;
parameter.set_node_line(this_token.line);
parameter.set_node_type(__dynamic_id);
parameter.set_var_name(this_token.str);
}
else if(this_token.type==__right_curve)
this->push_token();
else
{
++error;
print_parse_error(parameter_lack_part,this_token.line);
break;
}
// check equal operator
this->get_token();
if(this_token.type==__equal)
{
}
else if((this_token.type==__right_curve) || (this_token.type==__comma))
this->push_token();
else
{
++error;
print_parse_error(parameter_lack_part,this_token.line);
break;
}
// check comma or right_curve
this->get_token();
if((this_token.type!=__right_curve) && (this_token.type!=__comma))
{
++error;
print_parse_error(parameter_lack_curve,this_token.line);
break;
}
}
}
else
this->push_token();
return function_node; return function_node;
} }
@ -335,7 +592,7 @@ abstract_syntax_tree nasal_parse::choose_expr()
++error; ++error;
print_parse_error(lack_left_curve,this_token.line); print_parse_error(lack_left_curve,this_token.line);
} }
if_node.add_children(scalar_generate()); if_node.add_children(calculation());
this->get_token(); this->get_token();
if(this_token.type!=__right_curve) if(this_token.type!=__right_curve)
{ {

View File

@ -15,7 +15,7 @@
<id> = <token_identifier> ; <id> = <token_identifier> ;
<dynamic_id> = <token_dynamic_id> ; <dynamic_id> = <token_dynamic_id> ;
<vector> = '[' { <scalar> ',' } ']' ; <vector> = '[' { <calculation> ',' } ']' ;
<hash> = '{' {(<id> | <string>) ':' <scalar> ','} '}' ; <hash> = '{' {(<id> | <string>) ':' <scalar> ','} '}' ;
<scalar> = <scalar> =
<number> <number>
@ -25,17 +25,16 @@
| <hash> | <hash>
| <vector> | <vector>
| <func> <id> | <func> <id>
| <calculation>
| <function> | <function>
| '(' <scalar> ')' | '(' <calculation> ')'
| <scalar> { ('[' {<scalar> ','} ']') | ('[' <scalar> ':' [<scalar>] ']') | ('.' <id>) | ('(' {<scalar> ','} ')') | ('(' {<id> ':' <scalar> ','} ')') } | <scalar> { ('[' {<calculation> ','} ']') | ('[' <calculation> ':' [<calculation>] ']') | ('.' <id>) | ('(' {<calculation> ','} ')') | ('(' {<id> ':' <calculation> ','} ')') }
; ;
0 0
<function> = <function> =
<func> ['(' ')'] <statement> <func> ['(' ')'] <statement>
| <func> ['(' ')'] '{' {<statement> ';'} '}' | <func> ['(' ')'] '{' {<statement> ';'} '}'
| <func> '(' {<id> ','} {<id> '=' <scalar> ','} {<dynamic_id>} ')' <statement> | <func> '(' {<id> ','} {<id> '=' <calculation> ','} {<dynamic_id>} ')' <statement>
| <func> '(' {<id> ','} {<id> '=' <scalar> ','} {<dynamic_id>} ')' '{' {<statement> ';'} '}' | <func> '(' {<id> ','} {<id> '=' <calculation> ','} {<dynamic_id>} ')' '{' {<statement> ';'} '}'
; ;
<calculation> = <calculation> =