This commit is contained in:
Valk Richard Li 2020-10-13 03:20:49 -07:00 committed by GitHub
parent fd128c3758
commit 64488ba281
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 117 additions and 59 deletions

View File

@ -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>

View File

@ -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;
} }

View File

@ -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;
} }