This commit is contained in:
Valk Richard Li 2020-01-11 22:04:07 +08:00 committed by GitHub
parent ee7934fc58
commit 3683dca3bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 187 additions and 117 deletions

View File

@ -18,14 +18,19 @@ class abstract_syntax_tree
abstract_syntax_tree& operator=(const abstract_syntax_tree&); abstract_syntax_tree& operator=(const abstract_syntax_tree&);
// main functions // main functions
void set_clear(); // print
void print_tree(const int); void print_tree(const int);
// set
void set_clear();
void set_type(const int); void set_type(const int);
void set_line(const int); void set_line(const int);
void set_string(std::string); void set_string(std::string);
void set_number(std::string); void set_number(std::string);
void set_name(std::string); void set_name(std::string);
void add_child(abstract_syntax_tree); void add_child(abstract_syntax_tree);
// get
int get_type(); int get_type();
int get_line(); int get_line();
double get_number(); double get_number();
@ -74,17 +79,6 @@ abstract_syntax_tree& abstract_syntax_tree::operator=(const abstract_syntax_tree
return *this; return *this;
} }
void abstract_syntax_tree::set_clear()
{
type=0;
line=0;
number=0;
str="";
name="";
children.clear();
return;
}
void abstract_syntax_tree::print_tree(const int n) void abstract_syntax_tree::print_tree(const int n)
{ {
std::string __str=""; std::string __str="";
@ -111,6 +105,17 @@ void abstract_syntax_tree::print_tree(const int n)
return; return;
} }
void abstract_syntax_tree::set_clear()
{
type=0;
line=0;
number=0;
str="";
name="";
children.clear();
return;
}
void abstract_syntax_tree::set_type(const int __type) void abstract_syntax_tree::set_type(const int __type)
{ {
type=__type; type=__type;
@ -122,7 +127,10 @@ void abstract_syntax_tree::set_line(const int __line)
if(__line>=0) if(__line>=0)
line=__line; line=__line;
else else
{
std::cout<<">> [Abstract-syntax-tree-warning] incorrect line under 0: "<<__line<<"."<<std::endl;
line=0; line=0;
}
return; return;
} }

View File

@ -25,7 +25,6 @@ void print_lexer_token(int type)
enum parse_token_type enum parse_token_type
{ {
__stack_end=1, __stack_end=1,
__stack_top,
__cmp_equal,__cmp_not_equal,__cmp_less,__cmp_less_or_equal,__cmp_more,__cmp_more_or_equal, __cmp_equal,__cmp_not_equal,__cmp_less,__cmp_less_or_equal,__cmp_more,__cmp_more_or_equal,
// == != < <= > >= // == != < <= > >=
__and_operator,__or_operator,__nor_operator,__add_operator,__sub_operator,__mul_operator,__div_operator,__link_operator, __and_operator,__or_operator,__nor_operator,__add_operator,__sub_operator,__mul_operator,__div_operator,__link_operator,
@ -49,6 +48,7 @@ enum parse_token_type
// absttract_syntax_tree type below // absttract_syntax_tree type below
__root, __root,
__null_type, __null_type,
__multi_id,
__list,__hash, __list,__hash,
__hash_member, __hash_member,
__call_function,__call_array,__call_hash, __call_function,__call_array,__call_hash,
@ -63,7 +63,6 @@ void print_parse_token(int type)
switch(type) switch(type)
{ {
case __stack_end: context="#"; break; case __stack_end: context="#"; break;
case __stack_top: context="#"; break;
case __cmp_equal: context="=="; break; case __cmp_equal: context="=="; break;
case __cmp_not_equal: context="!="; break; case __cmp_not_equal: context="!="; break;
@ -124,9 +123,10 @@ void print_parse_token(int type)
case __root: context="root"; break; case __root: context="root"; break;
case __null_type: context="null_type"; break; case __null_type: context="null_type"; break;
case __multi_id: context="multi_identifiers"; break;
case __list: context="list"; break; case __list: context="list"; 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_array: context="call_array"; break;
case __call_hash: context="call_hash"; break; case __call_hash: context="call_hash"; break;
@ -147,24 +147,35 @@ 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
definition_lack_var, // lack 'var' reserve word
definition_lack_id, // lack identifier definition_lack_id, // lack identifier
definition_lack_equal, // lack '=' when not getting ';'
definition_wrong_type, // need identifier but get number or string
multi_definition_need_curve, // lack right curve when generating 'var (id,id,id)'
}; };
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)
{ {
std::string error_info_head=">>[Parse-error] line "; std::string error_info_head=">>[Parse-error] line ";
std::string warning_info_head=">> [Parse-warning] line ";
switch(error_type) switch(error_type)
{ {
case parse_unknown_error: std::cout<<error_info_head<<line<<": unknown parse error. error id: parse_unknown_error."<<std::endl;break; case parse_unknown_error:
std::cout<<error_info_head<<line<<": unknown parse error. error id: parse_unknown_error."<<std::endl;break;
case error_token_in_main: case error_token_in_main:
std::cout<<error_info_head<<line<<": statements should not begin with \'"; std::cout<<error_info_head<<line<<": statements should not begin with \'";
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 definition_lack_var: std::cout<<error_info_head<<line<<": expect a \'var\' here."<<std::endl;break; case definition_lack_id:
case definition_lack_id: std::cout<<error_info_head<<line<<": expect identifier(s) after \'var\'."<<std::endl;break; std::cout<<error_info_head<<line<<": expect identifier(s) after \'var\'."<<std::endl;break;
default: std::cout<<error_info_head<<line<<": unknown parse error. error id: other_type."<<std::endl;break; case definition_lack_equal:
std::cout<<error_info_head<<line<<": expect a \'=\' here."<<std::endl;break;
case definition_wrong_type:
std::cout<<error_info_head<<line<<": expect an identifier here but get other types."<<std::endl;
case multi_definition_need_curve:
std::cout<<error_info_head<<line<<": expect a \')\' here."<<std::endl;
default:
std::cout<<error_info_head<<line<<": unknown parse error. error id: other_type."<<std::endl;break;
} }
return; return;
} }

View File

@ -21,9 +21,7 @@ class nasal_parse
// abstract_syntax_tree generation // abstract_syntax_tree generation
void main_generate(); void main_generate();
abstract_syntax_tree number_expr(); abstract_syntax_tree scalar_generate();
abstract_syntax_tree string_expr();
abstract_syntax_tree nil_expr();
abstract_syntax_tree var_outside_definition(); abstract_syntax_tree var_outside_definition();
abstract_syntax_tree loop_expr(); abstract_syntax_tree loop_expr();
abstract_syntax_tree choose_expr(); abstract_syntax_tree choose_expr();
@ -67,8 +65,18 @@ void nasal_parse::get_token_list(std::list<token>& detail_token_stream)
parse_token_stream.pop(); parse_token_stream.pop();
while(!checked_tokens.empty()) while(!checked_tokens.empty())
checked_tokens.pop(); checked_tokens.pop();
// clear stack token end_token;
end_token.line=0;
end_token.str="stack_end";
end_token.type=__stack_end;
parse_token_stream.push(end_token);
checked_tokens.push(end_token);
// clear stacks and initialize them with end_token
std::stack<token> backward_tmp; std::stack<token> backward_tmp;
// backward_tmp is used to backward detail_token_stream
// to the parse_token_stream so get_token can get token
// according to the correct subsequence.
for(std::list<token>::iterator i=detail_token_stream.begin();i!=detail_token_stream.end();++i) for(std::list<token>::iterator i=detail_token_stream.begin();i!=detail_token_stream.end();++i)
backward_tmp.push(*i); backward_tmp.push(*i);
while(!backward_tmp.empty()) while(!backward_tmp.empty())
@ -81,16 +89,11 @@ void nasal_parse::get_token_list(std::list<token>& detail_token_stream)
void nasal_parse::get_token() void nasal_parse::get_token()
{ {
if(!parse_token_stream.empty())
{
this_token=parse_token_stream.top(); this_token=parse_token_stream.top();
parse_token_stream.pop(); parse_token_stream.pop();
checked_tokens.push(this_token); checked_tokens.push(this_token);
} if(this_token.type==__stack_end)
else
{ {
this_token.type=__stack_end;
this_token.str="__stack_end";
std::cout<<">>[Parse-error] fatal error occurred."<<std::endl; std::cout<<">>[Parse-error] fatal error occurred."<<std::endl;
std::cout<<">>[Parse-error] empty token stack."<<std::endl; std::cout<<">>[Parse-error] empty token stack."<<std::endl;
} }
@ -99,13 +102,10 @@ void nasal_parse::get_token()
void nasal_parse::push_token() void nasal_parse::push_token()
{ {
if(!checked_tokens.empty())
{
parse_token_stream.push(checked_tokens.top()); parse_token_stream.push(checked_tokens.top());
this_token=checked_tokens.top(); this_token=checked_tokens.top();
checked_tokens.pop(); checked_tokens.pop();
} if(this_token.type==__stack_end)
else
{ {
std::cout<<">>[Parse-error] fatal error occurred."<<std::endl; std::cout<<">>[Parse-error] fatal error occurred."<<std::endl;
std::cout<<">>[Parse-error] empty checked-token stack."<<std::endl; std::cout<<">>[Parse-error] empty checked-token stack."<<std::endl;
@ -115,6 +115,8 @@ void nasal_parse::push_token()
int nasal_parse::get_error() int nasal_parse::get_error()
{ {
// if error is larger than 0,
// the process will stop.
return error; return error;
} }
@ -128,88 +130,141 @@ void nasal_parse::main_generate()
{ {
error=0; error=0;
warning=0; warning=0;
// initialize error and warning
root.set_clear(); root.set_clear();
root.set_line(1); root.set_line(1);
root.set_type(__root); root.set_type(__root);
// initialize root node
while(!parse_token_stream.empty()) while(!parse_token_stream.empty())
{ {
this->get_token(); this->get_token();
switch(this_token.type) switch(this_token.type)
{ {
case __var:this->push_token();root.get_children().push_back(var_outside_definition());break; case __var:
case __nor_operator: this->push_token();
case __sub_operator: root.get_children().push_back(var_outside_definition());
case __number: break;
case __string: case __nor_operator: case __sub_operator:
case __nil: case __number: case __nil: case __string: case __id:
case __id:break; case __left_curve: case __left_bracket: case __left_brace:
case __left_curve:break; case __func:
case __left_bracket:break; this->push_token();
case __left_brace:break; root.add_child(scalar_generate());
case __func:break; break;
case __if:break; case __if:
case __while: this->push_token();
case __for: root.add_child(choose_expr());
case __foreach: break;
case __forindex:this->push_token();root.get_children().push_back(loop_expr());break; case __while: case __for: case __foreach: case __forindex:
this->push_token();
root.add_child(loop_expr());
break;
case __semi:break; case __semi:break;
default:++error;print_parse_error(error_token_in_main,this_token.line,this_token.type); default:
++error;
print_parse_error(error_token_in_main,this_token.line,this_token.type);
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;
} }
abstract_syntax_tree nasal_parse::number_expr() abstract_syntax_tree nasal_parse::scalar_generate()
{ {
abstract_syntax_tree node;
this->get_token(); this->get_token();
node.set_line(this_token.line); abstract_syntax_tree scalar_node;
node.set_type(__number); switch(this_token.type)
node.set_number(this_token.str); {
return node; case __nor_operator:
} case __sub_operator:
break;
abstract_syntax_tree nasal_parse::string_expr() case __number:
{ case __string:
abstract_syntax_tree node; case __nil:
this->get_token(); case __id:
node.set_line(this_token.line); break;
node.set_type(__string); case __left_curve:break;
node.set_string(this_token.str); case __left_brace:break;
return node; case __left_bracket:break;
} case __func:break;
}
abstract_syntax_tree nasal_parse::nil_expr() return scalar_node;
{
abstract_syntax_tree node;
this->get_token();
node.set_line(this_token.line);
node.set_type(__nil);
return node;
} }
abstract_syntax_tree nasal_parse::var_outside_definition() abstract_syntax_tree nasal_parse::var_outside_definition()
{ {
abstract_syntax_tree definition_node; abstract_syntax_tree definition_node;
definition_node.set_type(__definition); definition_node.set_type(__definition);
this->get_token(); this->get_token();// get 'var'
definition_node.set_line(this_token.line); definition_node.set_line(this_token.line);
if(this_token.type!=__var)
{
++error;
print_parse_error(definition_lack_var,this_token.line);
}
this->get_token(); this->get_token();
if(this_token.type==__id) if(this_token.type==__id)
{ {
abstract_syntax_tree new_var_identifier;
new_var_identifier.set_type(__id);
new_var_identifier.set_line(this_token.line);
new_var_identifier.set_name(this_token.str);
definition_node.add_child(new_var_identifier);
this->get_token();
if(this_token.type==__semi)
this->push_token();// var id
else if(this_token.type==__equal)
definition_node.add_child(scalar_generate());// var id = scalar
else
{
this->push_token();
++error;
print_parse_error(definition_lack_equal,this_token.line);
}
} }
else if(this_token.type==__left_curve) else if(this_token.type==__left_curve)
{ {
abstract_syntax_tree multi_identifier;
multi_identifier.set_type(__multi_id);
multi_identifier.set_line(this_token.line);
while(this_token.type!=__right_curve)
{
this->get_token();
if(this_token.type!=__id)
{
this->push_token();
++error;
print_parse_error(definition_wrong_type,this_token.line);
break;
} }
else else
{ {
this->push_token();
multi_identifier.add_child(scalar_generate());
}
this->get_token();
if(this_token.type!=__semi && this_token.type!=__right_curve)
{
this->push_token();
++error;
print_parse_error(multi_definition_need_curve,this_token.line);
break;
}
}
definition_node.add_child(multi_identifier);
this->get_token();
if(this_token.type==__semi)
this->push_token();// var (id,id,id)
else if(this_token.type==__equal)
{
;
}
else
{
this->push_token();
++error;
print_parse_error(definition_lack_equal,this_token.line);
}
}
else
{
this->push_token();
++error; ++error;
print_parse_error(definition_lack_id,this_token.line); print_parse_error(definition_lack_id,this_token.line);
} }
@ -236,7 +291,7 @@ abstract_syntax_tree nasal_parse::choose_expr()
{ {
abstract_syntax_tree choose_main_node; abstract_syntax_tree choose_main_node;
choose_main_node.set_type(__ifelse); choose_main_node.set_type(__ifelse);
this->get_token(); this->get_token();// get 'if'
choose_main_node.set_line(this_token.line); choose_main_node.set_line(this_token.line);
return choose_main_node; return choose_main_node;
} }

View File

@ -16,12 +16,14 @@
<number> <number>
| <nil> | <nil>
| <string> | <string>
| <call_identifier> | <id>
| <hash>
| <vector>
| <func> <id>
| <calculation> | <calculation>
| <function> | <function>
| <(> <scalar> <)> | <(> <scalar> <)>
| <hash> | <scalar> { (<[> {<scalar> <,>} <]>) | (<[> <scalar> <:> [<scalar>] <]>) | (<.> <id>) | (<(> {<scalar> <,>} <)>) | (<(> {<id> <:> <scalar> <,>} <)>) }
| <vector>
<function> ::= <function> ::=
<func> [<(> <)>] <statement> <func> [<(> <)>] <statement>
@ -29,18 +31,12 @@
| <func> <(> {<id> <,>} {<id> <=> <scalar> <,>} {<dynamic_id>} <)> <statement> | <func> <(> {<id> <,>} {<id> <=> <scalar> <,>} {<dynamic_id>} <)> <statement>
| <func> <(> {<id> <,>} {<id> <=> <scalar> <,>} {<dynamic_id>} <)> <{> {<statement> <;>} <}> | <func> <(> {<id> <,>} {<id> <=> <scalar> <,>} {<dynamic_id>} <)> <{> {<statement> <;>} <}>
<call_identifier> ::=
<scalar> { (<[> {<scalar> <,>} <]>) | (<[> <scalar> <:> [<scalar>] <]>) | (<.> <id>) | (<(> {<scalar> <,>} <)>) | (<(> {<id> <:> <scalar> <,>} <)>) }
| <id> { (<[> {<scalar> <,>} <]>) | (<[> <scalar> <:> [<scalar>] <]>) | (<.> <id>) | (<(> {<scalar> <,>} <)>) | (<(> {<id> <:> <scalar> <,>} <)>) }
| <func> <id>
| <func> <id> <(> <)> { (<[> {<scalar> <,>} <]>) | (<[> <scalar> <:> [<scalar>] <]>) | (<.> <id>) | (<(> {<scalar> <,>} <)>) | (<(> {<id> <:> <scalar> <,>} <)>) }
<calculation> ::= <calculation> ::=
<and_calc> <and_calc>
| <or_calc> | <or_calc>
| <additive_calc> | <additive_calc>
| <multive_calc> | <multive_calc>
| <scalar> | [<->|<!>] <scalar>
<and_calc> ::= <and_calc> ::=
<or_calc> {<and> <or_calc>} <or_calc> {<and> <or_calc>}
<or_calc> ::= <or_calc> ::=
@ -48,7 +44,7 @@
<additive_calc> ::= <additive_calc> ::=
<multive_calc> {<+>|<->|<~> <multive_calc>} <multive_calc> {<+>|<->|<~> <multive_calc>}
<multive_calc> ::= <multive_calc> ::=
<scalar> {<*>|</> <scalar>} <->|<!> <scalar> {<*>|</> <scalar>}
<definition> ::= <definition> ::=
<var> <id> <var> <id>