update
This commit is contained in:
parent
fd128c3758
commit
64488ba281
|
@ -6,6 +6,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
|
@ -7,14 +7,16 @@
|
||||||
class nasal_codegen
|
class nasal_codegen
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::vector<std::string> number_list;
|
std::vector<unsigned char> file_header;
|
||||||
std::vector<std::string> string_list;
|
std::vector<unsigned char> output_file;
|
||||||
std::vector<std::string> symbol_list;
|
std::vector<std::string> string_table;
|
||||||
int error;
|
int error;
|
||||||
void init();
|
void init();
|
||||||
void output_int(unsigned int,std::ofstream&);
|
void output_int(unsigned int,std::vector<unsigned char>&);
|
||||||
void output_root(nasal_ast&,std::ofstream&);
|
void output_short(unsigned short,std::vector<unsigned char>&);
|
||||||
|
void output_root(nasal_ast&);
|
||||||
unsigned int input_int(std::ifstream&);
|
unsigned int input_int(std::ifstream&);
|
||||||
|
unsigned short input_short(std::ifstream&);
|
||||||
void input_root(nasal_ast&,std::ifstream&);
|
void input_root(nasal_ast&,std::ifstream&);
|
||||||
public:
|
public:
|
||||||
nasal_codegen();
|
nasal_codegen();
|
||||||
|
@ -26,9 +28,7 @@ public:
|
||||||
nasal_codegen::nasal_codegen()
|
nasal_codegen::nasal_codegen()
|
||||||
{
|
{
|
||||||
error=0;
|
error=0;
|
||||||
number_list.clear();
|
string_table.clear();
|
||||||
string_list.clear();
|
|
||||||
symbol_list.clear();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,49 +40,86 @@ int nasal_codegen::get_error()
|
||||||
void nasal_codegen::init()
|
void nasal_codegen::init()
|
||||||
{
|
{
|
||||||
error=0;
|
error=0;
|
||||||
number_list.clear();
|
string_table.clear();
|
||||||
string_list.clear();
|
file_header.clear();
|
||||||
symbol_list.clear();
|
output_file.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nasal_codegen::output_int(unsigned int num,std::ofstream& fout)
|
void nasal_codegen::output_int(unsigned int num,std::vector<unsigned char>& vec)
|
||||||
{
|
{
|
||||||
unsigned int get_byte=0xff000000;
|
unsigned int tmp=0xff000000;
|
||||||
int offset=24;
|
unsigned int offset=24;
|
||||||
for(int i=0;i<4;++i)
|
for(int i=0;i<4;++i)
|
||||||
{
|
{
|
||||||
fout<<(unsigned char)((get_byte&num)>>offset);
|
vec.push_back((unsigned char)((tmp&num)>>offset));
|
||||||
get_byte>>=8;
|
|
||||||
offset-=8;
|
offset-=8;
|
||||||
|
tmp>>=8;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nasal_codegen::output_root(nasal_ast& root,std::ofstream& fout)
|
void nasal_codegen::output_short(unsigned short num,std::vector<unsigned char>& vec)
|
||||||
{
|
{
|
||||||
output_int(ast_begin,fout);
|
vec.push_back((unsigned char)((num&0xff00)>>8));
|
||||||
unsigned int type=root.get_type();
|
vec.push_back((unsigned char)(num&0x00ff));
|
||||||
output_int(type,fout);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nasal_codegen::output_root(nasal_ast& root)
|
||||||
|
{
|
||||||
|
unsigned char type=(unsigned char)root.get_type();
|
||||||
|
output_file.push_back(type);
|
||||||
std::vector<nasal_ast>& ref_vec=root.get_children();
|
std::vector<nasal_ast>& ref_vec=root.get_children();
|
||||||
int root_children_size=ref_vec.size();
|
unsigned short root_children_size=ref_vec.size();
|
||||||
output_int(root_children_size,fout);
|
output_short(root_children_size,output_file);
|
||||||
if(type==ast_number || type==ast_string || type==ast_identifier || type==ast_dynamic_id || type==ast_call_hash)
|
if(type==ast_number || type==ast_string || type==ast_identifier || type==ast_dynamic_id || type==ast_call_hash)
|
||||||
{
|
{
|
||||||
std::string tmp=root.get_str();
|
std::string tmp=root.get_str();
|
||||||
for(int i=0;i<tmp.length();++i)
|
if(std::find(string_table.begin(),string_table.end(),tmp)==string_table.end())
|
||||||
fout<<(unsigned char)tmp[i];
|
{
|
||||||
fout<<'\0';
|
string_table.push_back(tmp);
|
||||||
|
output_short(string_table.size()-1,output_file);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(int i=0;i<string_table.size();++i)
|
||||||
|
if(string_table[i]==tmp)
|
||||||
|
{
|
||||||
|
output_short(i,output_file);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for(int i=0;i<root_children_size;++i)
|
for(unsigned short i=0;i<root_children_size;++i)
|
||||||
output_root(ref_vec[i],fout);
|
output_root(ref_vec[i]);
|
||||||
output_int(ast_end,fout);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nasal_codegen::output_exec(std::string filename,nasal_ast& root)
|
void nasal_codegen::output_exec(std::string filename,nasal_ast& root)
|
||||||
{
|
{
|
||||||
|
// initializing
|
||||||
this->init();
|
this->init();
|
||||||
|
|
||||||
|
// put header input file_header
|
||||||
|
unsigned char header[4]={0x40,0x56,0x4b,0x21};
|
||||||
|
for(int i=0;i<4;++i)
|
||||||
|
file_header.push_back(header[i]);
|
||||||
|
|
||||||
|
// main progress,put codes into output_file
|
||||||
|
output_root(root);
|
||||||
|
|
||||||
|
// put string table into file_header
|
||||||
|
output_short(string_table.size(),file_header);
|
||||||
|
for(int i=0;i<string_table.size();++i)
|
||||||
|
{
|
||||||
|
int len=string_table[i].length();
|
||||||
|
for(int j=0;j<len;++j)
|
||||||
|
file_header.push_back((unsigned char)string_table[i][j]);
|
||||||
|
file_header.push_back(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// output to file
|
||||||
std::ofstream fout(filename,std::ios::binary);
|
std::ofstream fout(filename,std::ios::binary);
|
||||||
if(fout.fail())
|
if(fout.fail())
|
||||||
{
|
{
|
||||||
|
@ -91,10 +128,12 @@ void nasal_codegen::output_exec(std::string filename,nasal_ast& root)
|
||||||
fout.close();
|
fout.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
unsigned char header[4]={0x40,0x56,0x4b,0x21};
|
int size=file_header.size();
|
||||||
for(int i=0;i<4;++i)
|
for(int i=0;i<size;++i)
|
||||||
fout<<header[i];
|
fout<<file_header[i];
|
||||||
output_root(root,fout);
|
size=output_file.size();
|
||||||
|
for(int i=0;i<size;++i)
|
||||||
|
fout<<output_file[i];
|
||||||
fout.close();
|
fout.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -102,39 +141,32 @@ void nasal_codegen::output_exec(std::string filename,nasal_ast& root)
|
||||||
unsigned int nasal_codegen::input_int(std::ifstream& fin)
|
unsigned int nasal_codegen::input_int(std::ifstream& fin)
|
||||||
{
|
{
|
||||||
unsigned int number=0;
|
unsigned int number=0;
|
||||||
unsigned char c;
|
|
||||||
for(int i=0;i<4;++i)
|
for(int i=0;i<4;++i)
|
||||||
{
|
{
|
||||||
c=(unsigned char)fin.get();
|
number<<=8;
|
||||||
number=(number<<8)+c;
|
number+=(unsigned char)fin.get();
|
||||||
}
|
}
|
||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned short nasal_codegen::input_short(std::ifstream& fin)
|
||||||
|
{
|
||||||
|
unsigned short number=(unsigned char)fin.get();
|
||||||
|
number=(number<<8)+(unsigned char)fin.get();
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
void nasal_codegen::input_root(nasal_ast& root,std::ifstream& fin)
|
void nasal_codegen::input_root(nasal_ast& root,std::ifstream& fin)
|
||||||
{
|
{
|
||||||
unsigned int begin=input_int(fin);
|
unsigned char type=(unsigned char)fin.get();
|
||||||
if(begin!=ast_begin)
|
unsigned short size=input_short(fin);
|
||||||
{
|
|
||||||
++error;
|
|
||||||
std::cout<<">> [code] file format error: without ast_begin."<<std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
unsigned int type=input_int(fin);
|
|
||||||
unsigned int size=input_int(fin);
|
|
||||||
root.set_type(type);
|
root.set_type(type);
|
||||||
if(type==ast_number || type==ast_string || type==ast_identifier || type==ast_dynamic_id || type==ast_call_hash)
|
if(type==ast_number || type==ast_string || type==ast_identifier || type==ast_dynamic_id || type==ast_call_hash)
|
||||||
{
|
{
|
||||||
std::string tmp="";
|
std::string tmp=string_table[input_short(fin)];
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
unsigned char c=(unsigned char)fin.get();
|
|
||||||
if(!c || fin.eof()) break;
|
|
||||||
tmp+=c;
|
|
||||||
}
|
|
||||||
root.set_str(tmp);
|
root.set_str(tmp);
|
||||||
}
|
}
|
||||||
for(int i=0;i<size;++i)
|
for(unsigned short i=0;i<size;++i)
|
||||||
{
|
{
|
||||||
nasal_ast new_ast;
|
nasal_ast new_ast;
|
||||||
root.add_child(new_ast);
|
root.add_child(new_ast);
|
||||||
|
@ -142,19 +174,16 @@ void nasal_codegen::input_root(nasal_ast& root,std::ifstream& fin)
|
||||||
if(error)
|
if(error)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
unsigned int end=input_int(fin);
|
|
||||||
if(end!=ast_end)
|
|
||||||
{
|
|
||||||
++error;
|
|
||||||
std::cout<<">> [code] file format error: without ast_end."<<std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nasal_codegen::load_exec(std::string filename,nasal_ast& root)
|
void nasal_codegen::load_exec(std::string filename,nasal_ast& root)
|
||||||
{
|
{
|
||||||
|
// initializing
|
||||||
|
string_table.clear();
|
||||||
root.clear();
|
root.clear();
|
||||||
|
|
||||||
|
// start input
|
||||||
std::ifstream fin(filename,std::ios::binary);
|
std::ifstream fin(filename,std::ios::binary);
|
||||||
if(fin.fail())
|
if(fin.fail())
|
||||||
{
|
{
|
||||||
|
@ -163,6 +192,8 @@ void nasal_codegen::load_exec(std::string filename,nasal_ast& root)
|
||||||
fin.close();
|
fin.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check header
|
||||||
unsigned char header[4]={0x40,0x56,0x4b,0x21};
|
unsigned char header[4]={0x40,0x56,0x4b,0x21};
|
||||||
for(int i=0;i<4;++i)
|
for(int i=0;i<4;++i)
|
||||||
if((unsigned char)fin.get()!=header[i])
|
if((unsigned char)fin.get()!=header[i])
|
||||||
|
@ -171,6 +202,22 @@ void nasal_codegen::load_exec(std::string filename,nasal_ast& root)
|
||||||
std::cout<<">> [code] \""<<filename<<"\" is not an executable file."<<std::endl;
|
std::cout<<">> [code] \""<<filename<<"\" is not an executable file."<<std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// input string table
|
||||||
|
unsigned short string_num=input_short(fin);
|
||||||
|
for(int i=0;i<string_num;++i)
|
||||||
|
{
|
||||||
|
std::string tmp="";
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
unsigned char c=(unsigned char)fin.get();
|
||||||
|
if(!c || fin.eof()) break;
|
||||||
|
tmp+=c;
|
||||||
|
}
|
||||||
|
string_table.push_back(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate root
|
||||||
input_root(root,fin);
|
input_root(root,fin);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,8 @@ void nasal_import::init()
|
||||||
bool nasal_import::check_import(nasal_ast& node)
|
bool nasal_import::check_import(nasal_ast& node)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
only this kind of node can be recognized as 'import':
|
||||||
|
|
||||||
call
|
call
|
||||||
id:import
|
id:import
|
||||||
call_func
|
call_func
|
||||||
|
@ -73,6 +75,7 @@ bool nasal_import::check_import(nasal_ast& node)
|
||||||
|
|
||||||
bool nasal_import::check_exist(std::string filename)
|
bool nasal_import::check_exist(std::string filename)
|
||||||
{
|
{
|
||||||
|
// avoid importing the same file
|
||||||
int size=filename_table.size();
|
int size=filename_table.size();
|
||||||
for(int i=0;i<size;++i)
|
for(int i=0;i<size;++i)
|
||||||
if(filename==filename_table[i])
|
if(filename==filename_table[i])
|
||||||
|
@ -83,6 +86,7 @@ bool nasal_import::check_exist(std::string filename)
|
||||||
|
|
||||||
void nasal_import::linker(nasal_ast& root,nasal_ast& add_root)
|
void nasal_import::linker(nasal_ast& root,nasal_ast& add_root)
|
||||||
{
|
{
|
||||||
|
// add children of add_root to the back of root
|
||||||
std::vector<nasal_ast>& ref_vec=add_root.get_children();
|
std::vector<nasal_ast>& ref_vec=add_root.get_children();
|
||||||
int size=ref_vec.size();
|
int size=ref_vec.size();
|
||||||
for(int i=0;i<size;++i)
|
for(int i=0;i<size;++i)
|
||||||
|
@ -97,13 +101,16 @@ nasal_ast nasal_import::file_import(nasal_ast& node)
|
||||||
tmp.set_line(0);
|
tmp.set_line(0);
|
||||||
tmp.set_type(ast_root);
|
tmp.set_type(ast_root);
|
||||||
init();
|
init();
|
||||||
|
|
||||||
// get filename and set node to ast_null
|
// get filename and set node to ast_null
|
||||||
std::string filename=node.get_children()[1].get_children()[0].get_str();
|
std::string filename=node.get_children()[1].get_children()[0].get_str();
|
||||||
node.clear();
|
node.clear();
|
||||||
node.set_type(ast_null);
|
node.set_type(ast_null);
|
||||||
|
|
||||||
// avoid infinite loading loop
|
// avoid infinite loading loop
|
||||||
if(check_exist(filename))
|
if(check_exist(filename))
|
||||||
return tmp;
|
return tmp;
|
||||||
|
|
||||||
// start importing...
|
// start importing...
|
||||||
if(!import_src.input_file(filename))
|
if(!import_src.input_file(filename))
|
||||||
{
|
{
|
||||||
|
@ -124,6 +131,7 @@ nasal_ast nasal_import::file_import(nasal_ast& node)
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
tmp=import_par.get_root();
|
tmp=import_par.get_root();
|
||||||
|
|
||||||
// check if tmp has 'import'
|
// check if tmp has 'import'
|
||||||
return load(tmp);
|
return load(tmp);
|
||||||
}
|
}
|
||||||
|
@ -147,6 +155,8 @@ nasal_ast nasal_import::load(nasal_ast& root)
|
||||||
}
|
}
|
||||||
// add root to the back of new_root
|
// add root to the back of new_root
|
||||||
linker(new_root,root);
|
linker(new_root,root);
|
||||||
|
|
||||||
|
// oops,i think it is not efficient if the root is too ... large?
|
||||||
return new_root;
|
return new_root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue