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