787 lines
13 KiB
C++
787 lines
13 KiB
C++
#ifndef __NASAL_AST_H__
|
|
#define __NASAL_AST_H__
|
|
|
|
class abstract_syntax_tree
|
|
{
|
|
private:
|
|
/*
|
|
basic elements of ast node:
|
|
line: this marks the generated node's line in source code
|
|
node_type: this marks the node type
|
|
children: store the children of this node
|
|
*/
|
|
int line;
|
|
int node_type;
|
|
std::list<abstract_syntax_tree> children;
|
|
|
|
/*
|
|
var_number is used when the node_type is __number
|
|
var_string is used when the node_type is __string
|
|
var_name is used when the node_type is __id, __dynamic_id, call_hash
|
|
*/
|
|
double var_number;
|
|
std::string var_string;
|
|
std::string var_name;
|
|
public:
|
|
/* basic */
|
|
abstract_syntax_tree();
|
|
abstract_syntax_tree(const abstract_syntax_tree&);
|
|
~abstract_syntax_tree();
|
|
abstract_syntax_tree& operator=(const abstract_syntax_tree&);
|
|
|
|
/* main functions */
|
|
/*
|
|
print_tree is the entrance of print function
|
|
print_tree will print the root address and call print_tree_block(1)
|
|
print_tree_block will print the information of each node by using DFS
|
|
*/
|
|
void print_tree();
|
|
void print_tree_block(const int);
|
|
|
|
/*
|
|
set_clear : clear all the elements in ast node
|
|
set_node_line : set the private:line
|
|
set_node_type : set the private:node_type
|
|
set_var_number: set the private:var_number
|
|
set_var_string: set the private:var_string
|
|
set_var_name : set the private:var_name
|
|
*/
|
|
void set_clear();
|
|
void set_node_line(const int);
|
|
void set_node_type(const int);
|
|
void set_var_number(std::string);
|
|
void set_var_string(std::string);
|
|
void set_var_name(std::string);
|
|
void add_children(abstract_syntax_tree);
|
|
|
|
/*
|
|
get_node_line : get the private:line
|
|
get_node_type : get the private:node_type
|
|
get_var_number: get private:var_number
|
|
get_var_string: get private:var_string
|
|
get_var_name : get private:var_name
|
|
*/
|
|
int get_node_line();
|
|
int get_node_type();
|
|
double get_var_number();
|
|
std::string get_var_string();
|
|
std::string get_var_name();
|
|
std::list<abstract_syntax_tree>& get_children();
|
|
|
|
/*
|
|
merge children of another ast into this one
|
|
used to link lib ast and source codes' ast together
|
|
*/
|
|
void merge_children(abstract_syntax_tree&);
|
|
};
|
|
|
|
abstract_syntax_tree::abstract_syntax_tree()
|
|
{
|
|
node_type=__null_type;
|
|
line=0;
|
|
var_number=0;
|
|
var_string="";
|
|
var_name="";
|
|
children.clear();
|
|
return;
|
|
}
|
|
|
|
abstract_syntax_tree::abstract_syntax_tree(const abstract_syntax_tree& tmp)
|
|
{
|
|
node_type=tmp.node_type;
|
|
line=tmp.line;
|
|
var_number=tmp.var_number;
|
|
var_string=tmp.var_string;
|
|
var_name=tmp.var_name;
|
|
children=tmp.children;
|
|
return;
|
|
}
|
|
|
|
abstract_syntax_tree::~abstract_syntax_tree()
|
|
{
|
|
node_type=__null_type;
|
|
line=0;
|
|
var_number=0;
|
|
var_string.clear();
|
|
var_name.clear();
|
|
children.clear();
|
|
return;
|
|
}
|
|
|
|
abstract_syntax_tree& abstract_syntax_tree::operator=(const abstract_syntax_tree& tmp)
|
|
{
|
|
node_type=tmp.node_type;
|
|
line=tmp.line;
|
|
var_number=tmp.var_number;
|
|
var_string=tmp.var_string;
|
|
var_name=tmp.var_name;
|
|
children.clear();
|
|
children=tmp.children;
|
|
return *this;
|
|
}
|
|
|
|
void abstract_syntax_tree::print_tree()
|
|
{
|
|
std::cout<<">> [Abstract-syntax-tree] get tree root: "<<(this)<<""<<std::endl;
|
|
print_tree_block(1);
|
|
return;
|
|
}
|
|
|
|
void abstract_syntax_tree::print_tree_block(const int n)
|
|
{
|
|
std::string __str="";
|
|
for(int i=0;i<n;++i)
|
|
__str+="| ";
|
|
std::cout<<__str;
|
|
print_ast_type(node_type);
|
|
switch(node_type)
|
|
{
|
|
case __number: std::cout<<": "<<var_number;break;
|
|
case __string: std::cout<<": "<<var_string;break;
|
|
case __id:
|
|
case __dynamic_id:
|
|
case __call_hash: std::cout<<": "<<var_name;break;
|
|
case __call_vector:
|
|
case __call_function: break;
|
|
default: break;
|
|
}
|
|
std::cout<<std::endl;
|
|
if(!children.empty())
|
|
{
|
|
for(std::list<abstract_syntax_tree>::iterator i=children.begin();i!=children.end();++i)
|
|
i->print_tree_block(n+1);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void abstract_syntax_tree::set_clear()
|
|
{
|
|
node_type=__null_type;
|
|
line=0;
|
|
var_number=0;
|
|
var_string="";
|
|
var_name="";
|
|
children.clear();
|
|
return;
|
|
}
|
|
|
|
void abstract_syntax_tree::set_node_type(const int __node_type)
|
|
{
|
|
node_type=__node_type;
|
|
return;
|
|
}
|
|
|
|
void abstract_syntax_tree::set_node_line(const int __line)
|
|
{
|
|
if(__line>=0)
|
|
line=__line;
|
|
else
|
|
{
|
|
std::cout<<">> [Abstract-syntax-tree-warning] incorrect line under 0: "<<__line<<"."<<std::endl;
|
|
line=0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
void abstract_syntax_tree::set_var_string(std::string __str)
|
|
{
|
|
var_string=__str;
|
|
return;
|
|
}
|
|
|
|
void abstract_syntax_tree::set_var_number(std::string __str)
|
|
{
|
|
var_number=trans_string_to_number(__str);
|
|
return;
|
|
}
|
|
|
|
void abstract_syntax_tree::set_var_name(std::string __str)
|
|
{
|
|
var_name=__str;
|
|
return;
|
|
}
|
|
|
|
void abstract_syntax_tree::add_children(abstract_syntax_tree p)
|
|
{
|
|
// use abstract_syntax_tree instead of abstract_syntax_tree&
|
|
// because when this function get a 'p' from returned value of
|
|
// another function,this may result in s SIGSEGV.
|
|
children.push_back(p);
|
|
return;
|
|
}
|
|
|
|
int abstract_syntax_tree::get_node_type()
|
|
{
|
|
return node_type;
|
|
}
|
|
|
|
int abstract_syntax_tree::get_node_line()
|
|
{
|
|
return line;
|
|
}
|
|
|
|
double abstract_syntax_tree::get_var_number()
|
|
{
|
|
return var_number;
|
|
}
|
|
|
|
std::string abstract_syntax_tree::get_var_string()
|
|
{
|
|
return var_string;
|
|
}
|
|
|
|
std::string abstract_syntax_tree::get_var_name()
|
|
{
|
|
return var_name;
|
|
}
|
|
|
|
std::list<abstract_syntax_tree>& abstract_syntax_tree::get_children()
|
|
{
|
|
return children;
|
|
}
|
|
|
|
void abstract_syntax_tree::merge_children(abstract_syntax_tree& tmp)
|
|
{
|
|
for(std::list<abstract_syntax_tree>::iterator i=tmp.children.begin();i!=tmp.children.end();++i)
|
|
this->children.push_back(*i);
|
|
return;
|
|
}
|
|
|
|
#endif
|
|
/*
|
|
examples of each type of sub-tree
|
|
|
|
ast begins in root node:
|
|
root
|
|
statement_1
|
|
statement_2
|
|
...
|
|
|
|
note: interpreter in flightgear can recognize 1*(2+(var a=2))
|
|
but this type of expression is meaningless
|
|
so this interpreter does not recognize this.
|
|
|
|
source code:
|
|
0xdeadbeef;
|
|
'str';
|
|
"str";
|
|
ast:
|
|
root
|
|
num: 3.73593e+009
|
|
str: str
|
|
str: str
|
|
|
|
source code:
|
|
[0,1,2,3][0:2];
|
|
ast:
|
|
root
|
|
vector:
|
|
num: 0
|
|
num: 1
|
|
num: 2
|
|
num: 3
|
|
call_vector
|
|
sub_vector
|
|
num: 0
|
|
num: 2
|
|
|
|
source code:
|
|
{hello:"world"}.hello;
|
|
ast:
|
|
root
|
|
hash
|
|
hash_member
|
|
id: hello
|
|
str: world
|
|
call_hash: hello
|
|
|
|
source code:
|
|
1+2*(1-3)/4~'str';
|
|
ast:
|
|
root
|
|
~
|
|
+
|
|
num: 1
|
|
/
|
|
*
|
|
num: 2
|
|
-
|
|
num: 1
|
|
num: 3
|
|
num:4
|
|
str: str
|
|
|
|
source code:
|
|
var a=cd? 1:0;
|
|
ast:
|
|
root
|
|
definition
|
|
id: a
|
|
?
|
|
id: cd
|
|
num: 1
|
|
num: 0
|
|
|
|
source code:
|
|
var h={a:1,b:2,c:'3',};
|
|
ast:
|
|
root
|
|
definition
|
|
id: h
|
|
hash
|
|
hash_member
|
|
id: a
|
|
num: 1
|
|
hash_member
|
|
id: b
|
|
num: 2
|
|
hash_member
|
|
id: c
|
|
str: 3
|
|
|
|
source code:
|
|
var id=1;
|
|
ast:
|
|
root
|
|
definition
|
|
id: id
|
|
num: 1
|
|
|
|
source code:
|
|
var (id1,id2,id3)=(1,2,3);
|
|
(var id1,id2,id3)=(1,2,3);
|
|
ast:
|
|
root
|
|
definition
|
|
identifiers
|
|
id: id1
|
|
id: id2
|
|
id: id3
|
|
scalars
|
|
num: 1
|
|
num: 2
|
|
num: 3
|
|
|
|
source code:
|
|
var (id1,id2,id3)=[1,2,3];
|
|
(var id1,id2,id3)=[1,2,3];
|
|
ast:
|
|
root
|
|
definition
|
|
identifiers
|
|
id: id1
|
|
id: id2
|
|
id: id3
|
|
vector
|
|
num: 1
|
|
num: 2
|
|
num: 3
|
|
|
|
source code:
|
|
(id1,id2,id3)=(1,2,3);
|
|
ast:
|
|
root
|
|
=
|
|
scalars
|
|
id: id1
|
|
id: id2
|
|
id: id3
|
|
scalars
|
|
num: 1
|
|
num: 2
|
|
num: 3
|
|
|
|
source code:
|
|
(id1[0],id2,id3)=[1,2,3];
|
|
ast:
|
|
root
|
|
=
|
|
scalars
|
|
id: id1
|
|
call_vector
|
|
num: 0
|
|
id: id2
|
|
id: id3
|
|
vector
|
|
num: 1
|
|
num: 2
|
|
num: 3
|
|
|
|
source code:
|
|
id.call_hs(call_f)[call_vec][subvec1:subvec2,subvec3];
|
|
ast:
|
|
root
|
|
id: id
|
|
call_hash: call_hs
|
|
call_function
|
|
id: call_f
|
|
call_vector
|
|
id: call_vec
|
|
call_vector
|
|
sub_vector
|
|
id: subvec1
|
|
id: subvec2
|
|
id: subvec3
|
|
|
|
source code:
|
|
id.id.id.id.id.id.id.id;
|
|
ast:
|
|
root
|
|
id: id
|
|
call_hash: id
|
|
call_hash: id
|
|
call_hash: id
|
|
call_hash: id
|
|
call_hash: id
|
|
call_hash: id
|
|
call_hash: id
|
|
|
|
source code:
|
|
function(a,b,c,d,e);
|
|
function(func a);
|
|
function(func a());
|
|
ast:
|
|
root
|
|
id: function
|
|
call_function
|
|
id: a
|
|
id: b
|
|
id: c
|
|
id: d
|
|
id: e
|
|
id: function
|
|
call_function
|
|
id: a
|
|
id: function
|
|
call_function
|
|
id: a
|
|
call_function
|
|
|
|
source code:
|
|
function(
|
|
a,
|
|
b,
|
|
func{print("hello");}
|
|
);
|
|
ast:
|
|
id: function
|
|
call_function
|
|
id: a
|
|
id: b
|
|
function
|
|
parameters
|
|
block
|
|
id: print
|
|
call_function
|
|
str: hello
|
|
|
|
source code:
|
|
function(a:1,b:2,c:3,);
|
|
ast:
|
|
root
|
|
id: function
|
|
call_function
|
|
special_parameter
|
|
id: a
|
|
num: 1
|
|
special_parameter
|
|
id: b
|
|
num: 2
|
|
special_parameter
|
|
id: c
|
|
num: 3
|
|
|
|
source code:
|
|
(func{print(1);})();
|
|
ast:
|
|
root
|
|
function
|
|
parameters
|
|
block
|
|
id: print
|
|
call_function
|
|
num: 1
|
|
call_function
|
|
|
|
source code:
|
|
while(id)
|
|
{
|
|
fun();
|
|
var a=1;
|
|
var b=2;
|
|
}
|
|
ast:
|
|
root
|
|
while
|
|
id: id
|
|
block
|
|
id: func
|
|
call_function
|
|
definition
|
|
id: 1
|
|
num: 1
|
|
definition
|
|
id: b
|
|
num: 2
|
|
|
|
source code:
|
|
for(;;){}
|
|
ast:
|
|
root
|
|
for
|
|
null_type
|
|
null_type
|
|
null_type
|
|
block
|
|
|
|
source code:
|
|
for(var i=1;i<100;i+=1){}
|
|
ast:
|
|
root
|
|
for
|
|
definition
|
|
id: i
|
|
num: 1
|
|
<
|
|
id: i
|
|
num: 100
|
|
+=
|
|
id: i
|
|
num: 1
|
|
block
|
|
|
|
source code:
|
|
foreach(var i;[0,1,2]){}
|
|
forindex(var i;[0,1,2]){}
|
|
ast:
|
|
root
|
|
foreach
|
|
id: i
|
|
vector
|
|
num: 0
|
|
num: 1
|
|
num: 2
|
|
block
|
|
forindex
|
|
id: i
|
|
vector
|
|
num: 0
|
|
num: 1
|
|
num: 2
|
|
block
|
|
|
|
source code:
|
|
if(condition_1)
|
|
{
|
|
}
|
|
else if(condition_2)
|
|
{
|
|
}
|
|
else
|
|
{
|
|
}
|
|
ast:
|
|
root
|
|
conditional
|
|
if
|
|
id: condition_1
|
|
block
|
|
else
|
|
block
|
|
if
|
|
id: condition_2
|
|
block
|
|
else
|
|
block
|
|
|
|
source code:
|
|
if(condition_1)
|
|
{
|
|
}
|
|
elsif(condition_2)
|
|
{
|
|
}
|
|
elsif(condition_3)
|
|
{
|
|
}
|
|
ast:
|
|
root
|
|
conditional
|
|
if
|
|
id: condition_1
|
|
block
|
|
elsif
|
|
id: condition_2
|
|
block
|
|
elsif
|
|
id: condition_3
|
|
block
|
|
|
|
source code:
|
|
var function=func{};
|
|
ast:
|
|
root
|
|
definition
|
|
id: function
|
|
function
|
|
parameters
|
|
block
|
|
|
|
source code:
|
|
var function=func(x,y,dyn...){};
|
|
ast:
|
|
root
|
|
definition
|
|
id: function
|
|
function
|
|
parameters
|
|
id: x
|
|
id: y
|
|
id...: dyn
|
|
block
|
|
|
|
source code:
|
|
var function=func(x=2,y=1){};
|
|
ast:
|
|
root
|
|
definition
|
|
id: function
|
|
function
|
|
parameters
|
|
default_parameter
|
|
id: x
|
|
num: 2
|
|
default_parameter
|
|
id: y
|
|
num: 1
|
|
block
|
|
|
|
source code:
|
|
var function=func(args...)
|
|
{
|
|
if(size(args)<3)
|
|
{
|
|
print("error");
|
|
return 0;
|
|
}
|
|
if(args[0]==args[1] or args[1]==args[2])
|
|
{
|
|
return args[0]*args[1]*args[2];
|
|
}
|
|
elsif(args[2]>args[1])
|
|
{
|
|
return -1;
|
|
}
|
|
for(var i=0;i<size(args);i+=1)
|
|
{
|
|
if(args[i]>100)
|
|
break;
|
|
else if(args[i]<0)
|
|
return args[i];
|
|
}
|
|
return 0;
|
|
}
|
|
ast:
|
|
root
|
|
definition
|
|
id: function
|
|
function
|
|
parameters
|
|
id...: args
|
|
block
|
|
conditional
|
|
if
|
|
<
|
|
id: size
|
|
call_function
|
|
id: args
|
|
num: 3
|
|
block
|
|
id: print
|
|
call_function
|
|
str: error
|
|
return
|
|
num: 0
|
|
conditional
|
|
if
|
|
or
|
|
==
|
|
id: args
|
|
call_vector
|
|
num: 0
|
|
id: args
|
|
call_vector
|
|
num: 1
|
|
==
|
|
id: args
|
|
call_vector
|
|
num: 1
|
|
id: args
|
|
call_vector
|
|
num: 2
|
|
block
|
|
return
|
|
*
|
|
*
|
|
id: args
|
|
call_vector
|
|
num: 0
|
|
id: args
|
|
call_vector
|
|
num: 1
|
|
id: args
|
|
call_vector
|
|
num: 2
|
|
elsif
|
|
>
|
|
id: args
|
|
call_vector
|
|
num: 2
|
|
id: args
|
|
call_vector
|
|
num: 1
|
|
block
|
|
return
|
|
-
|
|
num: 0
|
|
num: 1
|
|
for
|
|
definition
|
|
id: i
|
|
num: 0
|
|
<
|
|
id: i
|
|
id: size
|
|
call_function
|
|
id: args
|
|
+=
|
|
id: i
|
|
num: 1
|
|
block
|
|
conditional
|
|
if
|
|
>
|
|
id: args
|
|
call_vector
|
|
id: i
|
|
num: 100
|
|
block
|
|
break
|
|
else
|
|
block
|
|
conditional
|
|
if
|
|
<
|
|
id: args
|
|
call_vector
|
|
id: i
|
|
num: 0
|
|
block
|
|
return
|
|
id: args
|
|
call_vector
|
|
id: i
|
|
return
|
|
num: 0
|
|
*/
|