This commit is contained in:
Valk Richard Li 2020-02-15 16:35:36 +08:00 committed by GitHub
parent 19fdb25242
commit a03d8a440d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 673 additions and 45 deletions

View File

@ -5,8 +5,7 @@ nasal_lexer lexer;
nasal_parse parser;
abstract_syntax_tree libroot;
abstract_syntax_tree root;
nasal_symbol_table symtable;
abstract_syntax_tree linker;
std::string command;
@ -40,7 +39,6 @@ int main()
std::cout<<">> [lex ] turn code into tokens."<<std::endl;
std::cout<<">> [par ] turn tokens into abstract syntax tree."<<std::endl;
std::cout<<">> [ast ] check the abstract syntax tree."<<std::endl;
std::cout<<">> [sym ] generate symbol table and print the information of it."<<std::endl;
std::cout<<">> [run ] run code."<<std::endl;
std::cout<<">> [info ] print lexer,parser and ast on screen."<<std::endl;
std::cout<<">> [exit ] quit nasal interpreter."<<std::endl;
@ -62,8 +60,8 @@ int main()
resource.delete_all_source();
lexer.delete_all_tokens();
parser.delete_all_elements();
symtable.set_scope_clear();
root.set_clear();
linker.set_clear();
std::cout<<">> [Delete] complete."<<std::endl;
}
else if(command=="lib")
@ -82,14 +80,13 @@ int main()
std::cout<<">> [Lib] loaded."<<std::endl;
}
else
std::cout<<">> [Lib-error] lib files have parse error(s),stop."<<std::endl;
std::cout<<">> [Lib] lib files have parse error(s),stop."<<std::endl;
}
else
std::cout<<">> [Lib-error] lib files have lexer error(s),stop."<<std::endl;
std::cout<<">> [Lib] lib files have lexer error(s),stop."<<std::endl;
resource.delete_all_source();
lexer.delete_all_tokens();
parser.delete_all_elements();
symtable.set_scope_clear();
}
else if(command=="rs")
{
@ -126,33 +123,7 @@ int main()
parser.get_token_list(lexer.get_detail_token_list());
parser.main_generate();
if(!parser.get_error())
{
symtable.set_scope_clear();
symtable.symbol_table_main_generate(parser.get_root());
parser.get_root().print_tree();
}
else
std::cout<<">> [Parse] error occurred,stop."<<std::endl;
}
else
std::cout<<">> [Lexer] error occurred,stop."<<std::endl;
}
else if(command=="sym")
{
lexer.scanner(resource.get_source());
lexer.generate_detail_token();
if(!lexer.get_error())
{
parser.get_token_list(lexer.get_detail_token_list());
parser.main_generate();
if(!parser.get_error())
{
symtable.set_scope_clear();
symtable.symbol_table_main_generate(parser.get_root());
symtable.print_symbol_table();
if(symtable.get_error())
std::cout<<">> [Symbol] error occurred,stop."<<std::endl;
}
else
std::cout<<">> [Parse] error occurred,stop."<<std::endl;
}
@ -169,12 +140,11 @@ int main()
parser.main_generate();
if(!parser.get_error())
{
symtable.set_scope_clear();
symtable.symbol_table_main_generate(parser.get_root());
if(!symtable.get_error())
root=parser.get_root();// run code
else
std::cout<<">> [Symbol] error occurred,stop."<<std::endl;
linker.set_clear();
linker=libroot;
linker.merge_children(parser.get_root());
root=linker;
root.print_tree();
}
else
std::cout<<">> [Parse] error occurred,stop."<<std::endl;

View File

@ -9,12 +9,17 @@
//#include <thread>
#include <list>
#include <stack>
#include <vector>
#include <map>
#include "numeral_misc.h"
#include "nasal_misc.h"
#include "nasal_enum.h"
#include "abstract_syntax_tree.h"
#include "nasal_ast.h"
#include "nasal_lexer.h"
#include "nasal_parse.h"
#include "nasal_symbol_table.h"
#include "nasal_scalar.h"
#include "nasal_gc.h"
#include "nasal_sym.h"
#include "nasal_runtime.h"
#endif
#endif

223
version2.0/nasal_ast.h Normal file
View File

@ -0,0 +1,223 @@
#ifndef __NASAL_AST_H__
#define __NASAL_AST_H__
class abstract_syntax_tree
{
private:
// basic elements
int line;
int node_type;
std::list<abstract_syntax_tree> children;
// is this node is a number|string|identifier node
// then the three elements below is of great use
// var_name is set for __id
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
void print_tree();
void print_tree_block(const int);
// set
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
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
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_parse_token(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

143
version2.0/nasal_gc.h Normal file
View File

@ -0,0 +1,143 @@
#ifndef __NASAL_GC_H__
#define __NASAL_GC_H__
struct gc_unit
{
// collected: If gc collected this item,it'll be set to true.Otherwise it is false.
// elem: Item that this unit stores
// refcnt: Reference counter
bool collected;
nasal_scalar elem;
int refcnt;
gc_unit()
{
collected=true;
//elem=0;
refcnt=0;
return;
}
gc_unit(const gc_unit& tmp)
{
collected=tmp.collected;
//elem=tmp.elem;
refcnt=tmp.refcnt;
return;
}
};
class gc_manager
{
private:
// free_space list is used to store space that is not in use.
std::list<int> free_space;
std::vector<gc_unit> memory;
public:
gc_manager()
{
memory.clear();
free_space.clear();
return;
}
~gc_manager()
{
memory.clear();
free_space.clear();
return;
}
void gc_init()
{
// this function must be called in class nasal_runtime
// before running any codes
std::vector<gc_unit> tmp_vec;
memory.clear();
memory.swap(tmp_vec);
// clear the memory capacity by using tmp_vec.~vector<gc_unit>()
free_space.clear();
return;
}
void gc_scanner()
{
int memory_size=memory.size();
for(int i=0;i<memory_size;++i)
if((memory[i].refcnt<=0) && (!memory[i].collected))
{
memory[i].collected=true;
free_space.push_back(i);
std::cout<<">> [Gc] collected ";
prt_hex(i);
std::cout<<"."<<std::endl;
}
return;
}
int gc_alloc()
{
if(free_space.empty())
{
gc_unit new_unit;
memory.push_back(new_unit);
free_space.push_back(memory.size()-1);
}
int alloc_plc=free_space.front();
free_space.pop_front();
memory[alloc_plc].collected=false;
memory[alloc_plc].refcnt=1;
return alloc_plc;
}
bool place_check(const int place)
{
// check if this place is in memory
// and this place is uncollected
return (place<memory.size()) && (!memory[place].collected);
}
void reference_add(const int place)
{
if(place<memory.size())
++memory[place].refcnt;
else
{
std::cout<<">> [Gc] fatal error: unexpected memory place ";
prt_hex(place);
std::cout<<" ."<<std::endl;
}
return;
}
void reference_delete(const int place)
{
if(place<memory.size())
--memory[place].refcnt;
else
{
std::cout<<">> [Gc] fatal error: unexpected memory place ";
prt_hex(place);
std::cout<<" ."<<std::endl;
}
return;
}
void info_print()
{
std::cout<<">> [Gc] memory size:"<<memory.size()*sizeof(gc_unit)<<" byte."<<std::endl;
std::cout<<">> [Gc] memory capacity:"<<memory.capacity()*sizeof(gc_unit)<<" byte."<<std::endl;
std::cout<<">> [Gc] memory usage: "<<std::endl;
int cnt=0;
for(int i=0;i<memory.size();++i)
if(!memory[i].collected)
{
prt_hex(i);
std::cout<<"["<<memory[i].refcnt<<"]";
// cnt is used to check if it is the right time to output in the next line
++cnt;
if(!(cnt%8))
std::cout<<std::endl;
else
std::cout<<" ";
}
if(cnt%8)
std::cout<<std::endl;
return;
}
};
gc_manager nasal_gc;
// this object is used in "nasal_sym.h" and "nasal_runtime.h"
// because there must be only one gc when running a program
#endif

168
version2.0/nasal_misc.h Normal file
View File

@ -0,0 +1,168 @@
#ifndef __NASAL_MISC_H__
#define __NASAL_MISC_H__
bool check_numerable_string(std::string str)
{
if(str.length()>1 && str[0]=='-')
{
// in lexer this statements are useless
// because lexer judge a number that begins with 0~9 (or 0x for hex & 0o for oct)
std::string temp="";
int str_len=str.length();
for(int i=1;i<str_len;++i)
temp+=str[i];
str=temp;
}
if(str.length()==1 && '0'<=str[0] && str[0]<='9')
return true;
else if(str.length()>2 && str[0]=='0' && str[1]=='x')
{
int str_len=str.length();
for(int i=2;i<str_len;++i)
if(!(('0'<=str[i] && str[i]<='9') || ('a'<=str[i] && str[i]<='f') || ('A'<=str[i] && str[i]<='F')))
return false;
return true;
}
else if(str.length()>2 && str[0]=='0' && str[1]=='o')
{
int str_len=str.length();
for(int i=2;i<str_len;++i)
if(!('0'<=str[i] && str[i]<='7'))
return false;
return true;
}
else
{
int str_len=str.length();
int float_dot_cnt=0;
for(int i=0;i<str_len;++i)
{
if(str[i]=='.')
++float_dot_cnt;
else if(!('0'<=str[i] && str[i]<='9'))
return false;
}
if((float_dot_cnt>1) || (str[0]=='.') || (!float_dot_cnt && str[0]=='0'))
return false;
return true;
}
return false;
}
double trans_string_to_number(std::string str)
{
bool is_negative=false;
if(str.length()>1 && str[0]=='-')
{
// in parse this statements are useless
// because lexer recognizes a number that begins with a '0'~'9' char
std::string temp="";
int str_len=str.length();
for(int i=1;i<str_len;++i)
temp+=str[i];
str=temp;
is_negative=true;
}
double trans_str_number=0;
if(str.length()==1)
trans_str_number=(double)(str[0]-'0');
else if(str[0]=='0' && str[1]=='x')
{
long long int hex_number=0,bit_pow=1;
for(int i=str.length()-1;i>1;--i)
{
if('0'<=str[i] && str[i]<='9')
hex_number+=bit_pow*(str[i]-'0');
else if('a'<=str[i] && str[i]<='f')
hex_number+=bit_pow*(10+str[i]-'a');
else
hex_number+=bit_pow*(10+str[i]-'A');
bit_pow<<=4;
}
trans_str_number=(double)hex_number;
}
else if(str[0]=='0' && str[1]=='o')
{
long long int oct_number=0,bit_pow=1;
for(int i=str.length()-1;i>1;--i)
{
oct_number+=bit_pow*(str[i]-'0');
bit_pow<<=3;
}
trans_str_number=(double)oct_number;
}
else
{
int float_dot_place=str.length();
int str_len=str.length();
double pow;
for(int i=0;i<str_len;++i)
if(str[i]=='.')
{
float_dot_place=i;
break;
}
pow=0.1;
for(int i=float_dot_place+1;i<str_len;++i)
{
trans_str_number+=pow*(double(str[i]-'0'));
pow/=10;
}
pow=1;
for(int i=float_dot_place-1;i>=0;--i)
{
trans_str_number+=pow*(double(str[i]-'0'));
pow*=10;
}
}
if(is_negative)
trans_str_number*=-1;
return trans_str_number;
}
std::string trans_number_to_string(double number)
{
std::string trans_num_string="";
if(number<0)
{
trans_num_string+='-';
number*=-1;
}
double integer_bit=1;
while(number>=integer_bit)
integer_bit*=10;
integer_bit/=10;
while(integer_bit!=0.1)
{
trans_num_string+=(char)('0'+(int(number/integer_bit)));
number-=(double)(int(number/integer_bit))*integer_bit;
integer_bit/=10;
}
if(number!=0)
trans_num_string+='.';
while(number!=0)
{
trans_num_string+=(char)('0'+int(number*10));
number*=10;
number-=(double)(int(number));
}
return trans_num_string;
}
void prt_hex(const int ptr)
{
// transform int to hex and print it (std::cout)
char hex[9];
hex[8]=0;
int tmp_plc=ptr;
for(int j=7;j>=0;--j)
{
int tmp=(tmp_plc & 0x0000000f);
hex[j]=tmp<10? (char)('0'+tmp):(char)('a'+tmp-10);
tmp_plc>>=4;
}
std::cout<<"0x"<<hex;
return;
}
#endif

View File

@ -0,0 +1,33 @@
#ifndef __NASAL_RUNTIME_H__
#define __NASAL_RUNTIME_H__
class nasal_runtime
{
private:
sym_hash_map global;
public:
nasal_runtime()
{
global.set_clear();
nasal_gc.gc_init();
return;
}
~nasal_runtime()
{
global.set_clear();
nasal_gc.gc_init();
return;
}
void before_running_init()
{
global.set_clear();
nasal_gc.gc_init();
return;
}
void main_proc(abstract_syntax_tree& root)
{
return;
}
};
#endif

View File

@ -1,14 +1,35 @@
#ifndef __NASAL_SCALAR_H__
#define __NASAL_SCALAR_H__
class nasal_function
{
private:
std::map<std::string,int> local_scope;
abstract_syntax_tree function_root;
public:
nasal_function()
{
local_scope.clear();
function_root.set_clear();
return;
}
~nasal_function()
{
local_scope.clear();
function_root.set_clear();
return;
}
};
class nasal_scalar
{
private:
int type;
std::string var_string;
double var_number;
std::vector<nasal_scalar> var_array;
std::map<std::string,nasal_scalar> var_hash;
std::vector<int> var_array;
std::map<std::string,int> var_hash;
nasal_function var_func;
public:
nasal_scalar()
{
@ -62,6 +83,19 @@ class nasal_scalar
var_string=tmp_str;
return;
}
void vector_add_new_member(const int addr)
{
var_array.push_back(addr);
return;
}
void hash_add_new_member(const std::string member_name,const int addr)
{
if(var_hash.find(member_name)!=var_hash.end())
std::cout<<">> [Runtime] "<<member_name<<" exists."<<std::endl;
else
var_hash[member_name]=addr;
return;
}
int get_type() {return type;}
double get_number() {return var_number;}
std::string get_string(){return var_string;}

52
version2.0/nasal_sym.h Normal file
View File

@ -0,0 +1,52 @@
#ifndef __NASAL_SYM_H__
#define __NASAL_SYM_H__
// all symbol_map use a same gc system named nasal_gc
// see detail of nasal_gc in "nasal_gc.h"
class sym_hash_map
{
private:
std::map<std::string,int> sym_map;
public:
sym_hash_map()
{
sym_map.clear();
return;
}
sym_hash_map(const sym_hash_map& tmp)
{
sym_map=tmp.sym_map;
for(std::map<std::string,int>::iterator i=sym_map.begin();i!=sym_map.end();++i)
nasal_gc.reference_add(i->second);
return;
}
~sym_hash_map()
{
for(std::map<std::string,int>::iterator i=sym_map.begin();i!=sym_map.end();++i)
nasal_gc.reference_delete(i->second);
sym_map.clear();
return;
}
void set_clear()
{
sym_map.clear();
return;
}
void add_new_symbol(std::string __sym_name)
{
if(sym_map.find(__sym_name)==sym_map.end())
sym_map[__sym_name]=nasal_gc.gc_alloc();
else
std::cout<<">> [Runtime] "<<__sym_name<<" exists."<<std::endl;
return;
}
int get_symbol_addr(std::string __sym_name)
{
if(sym_map.find(__sym_name)!=sym_map.end())
return sym_map[__sym_name];
else
return -1;
}
};
#endif