update
This commit is contained in:
parent
50694f467b
commit
fd128c3758
|
@ -13,12 +13,13 @@ void help()
|
||||||
{
|
{
|
||||||
std::cout<<">> [\"file\"] input a file."<<std::endl;
|
std::cout<<">> [\"file\"] input a file."<<std::endl;
|
||||||
std::cout<<">> [clear ] clear the screen."<<std::endl;
|
std::cout<<">> [clear ] clear the screen."<<std::endl;
|
||||||
std::cout<<">> [del ] clear the source code."<<std::endl;
|
std::cout<<">> [del ] clear the input filename."<<std::endl;
|
||||||
std::cout<<">> [rs ] print source code."<<std::endl;
|
std::cout<<">> [rs ] print source code."<<std::endl;
|
||||||
std::cout<<">> [lex ] use lexer to turn code into tokens."<<std::endl;
|
std::cout<<">> [lex ] use lexer to turn code into tokens."<<std::endl;
|
||||||
std::cout<<">> [ast ] do parsing and check the abstract syntax tree."<<std::endl;
|
std::cout<<">> [ast ] do parsing and check the abstract syntax tree."<<std::endl;
|
||||||
std::cout<<">> [run ] run code."<<std::endl;
|
std::cout<<">> [run ] run abstract syntax tree."<<std::endl;
|
||||||
std::cout<<">> [exec ] generate byte code."<<std::endl;
|
std::cout<<">> [exec ] generate byte code."<<std::endl;
|
||||||
|
std::cout<<">> [erun ] run byte code."<<std::endl;
|
||||||
std::cout<<">> [logo ] print logo of nasal ."<<std::endl;
|
std::cout<<">> [logo ] print logo of nasal ."<<std::endl;
|
||||||
std::cout<<">> [exit ] quit nasal interpreter."<<std::endl;
|
std::cout<<">> [exit ] quit nasal interpreter."<<std::endl;
|
||||||
return;
|
return;
|
||||||
|
@ -52,6 +53,11 @@ void die(std::string stage,std::string filename)
|
||||||
|
|
||||||
void lex_func()
|
void lex_func()
|
||||||
{
|
{
|
||||||
|
if(!resource.input_file(inputfile))
|
||||||
|
{
|
||||||
|
die("resource",inputfile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
lexer.scanner(resource.get_file());
|
lexer.scanner(resource.get_file());
|
||||||
if(lexer.get_error())
|
if(lexer.get_error())
|
||||||
{
|
{
|
||||||
|
@ -64,6 +70,11 @@ void lex_func()
|
||||||
|
|
||||||
void ast_print()
|
void ast_print()
|
||||||
{
|
{
|
||||||
|
if(!resource.input_file(inputfile))
|
||||||
|
{
|
||||||
|
die("resource",inputfile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
lexer.scanner(resource.get_file());
|
lexer.scanner(resource.get_file());
|
||||||
if(lexer.get_error())
|
if(lexer.get_error())
|
||||||
{
|
{
|
||||||
|
@ -82,6 +93,11 @@ void ast_print()
|
||||||
}
|
}
|
||||||
void runtime_start()
|
void runtime_start()
|
||||||
{
|
{
|
||||||
|
if(!resource.input_file(inputfile))
|
||||||
|
{
|
||||||
|
die("resource",inputfile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
lexer.scanner(resource.get_file());
|
lexer.scanner(resource.get_file());
|
||||||
if(lexer.get_error())
|
if(lexer.get_error())
|
||||||
{
|
{
|
||||||
|
@ -108,6 +124,11 @@ void runtime_start()
|
||||||
|
|
||||||
void codegen_start()
|
void codegen_start()
|
||||||
{
|
{
|
||||||
|
if(!resource.input_file(inputfile))
|
||||||
|
{
|
||||||
|
die("resource",inputfile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
lexer.scanner(resource.get_file());
|
lexer.scanner(resource.get_file());
|
||||||
if(lexer.get_error())
|
if(lexer.get_error())
|
||||||
{
|
{
|
||||||
|
@ -128,7 +149,25 @@ void codegen_start()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
runtime.set_root(preprocessor.get_root());
|
runtime.set_root(preprocessor.get_root());
|
||||||
code_generator.main_progress(inputfile+".naexec",preprocessor.get_root());
|
code_generator.output_exec(inputfile+".naexec",preprocessor.get_root());
|
||||||
|
if(code_generator.get_error())
|
||||||
|
{
|
||||||
|
die("code",inputfile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void execution_start()
|
||||||
|
{
|
||||||
|
code_generator.load_exec(inputfile,preprocessor.get_root());
|
||||||
|
if(code_generator.get_error())
|
||||||
|
{
|
||||||
|
die("code",inputfile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
runtime.set_root(preprocessor.get_root());
|
||||||
|
runtime.run();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +214,10 @@ int main()
|
||||||
else if(command=="del")
|
else if(command=="del")
|
||||||
del_func();
|
del_func();
|
||||||
else if(command=="rs")
|
else if(command=="rs")
|
||||||
resource.print_file();
|
{
|
||||||
|
if(resource.input_file(inputfile))
|
||||||
|
resource.print_file();
|
||||||
|
}
|
||||||
else if(command=="lex")
|
else if(command=="lex")
|
||||||
lex_func();
|
lex_func();
|
||||||
else if(command=="ast")
|
else if(command=="ast")
|
||||||
|
@ -184,6 +226,8 @@ int main()
|
||||||
runtime_start();
|
runtime_start();
|
||||||
else if(command=="exec")
|
else if(command=="exec")
|
||||||
codegen_start();
|
codegen_start();
|
||||||
|
else if(command=="erun")
|
||||||
|
execution_start();
|
||||||
else if(command=="logo")
|
else if(command=="logo")
|
||||||
logo();
|
logo();
|
||||||
else if(command=="exit")
|
else if(command=="exit")
|
||||||
|
@ -191,7 +235,13 @@ int main()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
inputfile=command;
|
inputfile=command;
|
||||||
resource.input_file(inputfile);
|
std::ifstream fin(command);
|
||||||
|
if(fin.fail())
|
||||||
|
{
|
||||||
|
std::cout<<">> [file] cannot open file \""<<command<<"\"."<<std::endl;
|
||||||
|
inputfile="null";
|
||||||
|
}
|
||||||
|
fin.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -2,16 +2,8 @@
|
||||||
#define __NASAL_CODEGEN_H__
|
#define __NASAL_CODEGEN_H__
|
||||||
|
|
||||||
// unfinished
|
// unfinished
|
||||||
|
// now it can output ast but it is not byte code yet
|
||||||
enum bytecode
|
// please wait...
|
||||||
{
|
|
||||||
code_nop=0,
|
|
||||||
|
|
||||||
code_number_list,
|
|
||||||
code_string_list,
|
|
||||||
code_symbol_list,
|
|
||||||
};
|
|
||||||
|
|
||||||
class nasal_codegen
|
class nasal_codegen
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -19,22 +11,16 @@ private:
|
||||||
std::vector<std::string> string_list;
|
std::vector<std::string> string_list;
|
||||||
std::vector<std::string> symbol_list;
|
std::vector<std::string> symbol_list;
|
||||||
int error;
|
int error;
|
||||||
void die(std::string);
|
|
||||||
void init();
|
void init();
|
||||||
void output_int(unsigned int,std::ofstream&);
|
void output_int(unsigned int,std::ofstream&);
|
||||||
void generate_root(nasal_ast&,std::ofstream&);
|
void output_root(nasal_ast&,std::ofstream&);
|
||||||
void generate_number_list(std::ofstream&);
|
unsigned int input_int(std::ifstream&);
|
||||||
void generate_string_list(std::ofstream&);
|
void input_root(nasal_ast&,std::ifstream&);
|
||||||
void generate_symbol_list(std::ofstream&);
|
|
||||||
public:
|
public:
|
||||||
nasal_codegen();
|
nasal_codegen();
|
||||||
void main_progress(std::string,nasal_ast&);
|
int get_error();
|
||||||
};
|
void output_exec(std::string,nasal_ast&);
|
||||||
|
void load_exec(std::string,nasal_ast&);
|
||||||
class nasal_bytecode_runtime
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
public:
|
|
||||||
};
|
};
|
||||||
|
|
||||||
nasal_codegen::nasal_codegen()
|
nasal_codegen::nasal_codegen()
|
||||||
|
@ -46,11 +32,9 @@ nasal_codegen::nasal_codegen()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nasal_codegen::die(std::string info)
|
int nasal_codegen::get_error()
|
||||||
{
|
{
|
||||||
++error;
|
return error;
|
||||||
std::cout<<">> [code] "<<info<<std::endl;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nasal_codegen::init()
|
void nasal_codegen::init()
|
||||||
|
@ -75,71 +59,34 @@ void nasal_codegen::output_int(unsigned int num,std::ofstream& fout)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nasal_codegen::generate_root(nasal_ast& root,std::ofstream& fout)
|
void nasal_codegen::output_root(nasal_ast& root,std::ofstream& fout)
|
||||||
{
|
{
|
||||||
|
output_int(ast_begin,fout);
|
||||||
|
unsigned int type=root.get_type();
|
||||||
|
output_int(type,fout);
|
||||||
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();
|
int root_children_size=ref_vec.size();
|
||||||
for(int i=0;i<root_children_size;++i)
|
output_int(root_children_size,fout);
|
||||||
|
if(type==ast_number || type==ast_string || type==ast_identifier || type==ast_dynamic_id || type==ast_call_hash)
|
||||||
{
|
{
|
||||||
switch(ref_vec[i].get_type())
|
std::string tmp=root.get_str();
|
||||||
{
|
for(int i=0;i<tmp.length();++i)
|
||||||
case ast_definition:break;
|
fout<<(unsigned char)tmp[i];
|
||||||
case ast_multi_assign:break;
|
fout<<'\0';
|
||||||
case ast_conditional:break;
|
|
||||||
case ast_while:case ast_for:case ast_forindex:case ast_foreach:
|
|
||||||
break;
|
|
||||||
case ast_nil:case ast_number:case ast_string:case ast_function:break;
|
|
||||||
case ast_identifier:
|
|
||||||
case ast_vector:case ast_hash:
|
|
||||||
case ast_call:
|
|
||||||
case ast_equal:case ast_add_equal:case ast_sub_equal:case ast_mult_equal:case ast_div_equal:case ast_link_equal:
|
|
||||||
case ast_unary_sub:case ast_unary_not:
|
|
||||||
case ast_add:case ast_sub:case ast_mult:case ast_div:case ast_link:
|
|
||||||
case ast_trinocular:break;
|
|
||||||
case ast_break:die("break in main.");break;
|
|
||||||
case ast_continue:die("continue in main.");break;
|
|
||||||
case ast_return:die("return in main.");break;
|
|
||||||
}
|
|
||||||
if(error)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
output_int(code_nop,fout);
|
for(int i=0;i<root_children_size;++i)
|
||||||
return;
|
output_root(ref_vec[i],fout);
|
||||||
}
|
output_int(ast_end,fout);
|
||||||
void nasal_codegen::generate_number_list(std::ofstream& fout)
|
|
||||||
{
|
|
||||||
output_int(code_number_list,fout);
|
|
||||||
int size=number_list.size();
|
|
||||||
output_int(size,fout);
|
|
||||||
for(int i=0;i<size;++i)
|
|
||||||
fout<<number_list[i]<<"\0";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
void nasal_codegen::generate_string_list(std::ofstream& fout)
|
|
||||||
{
|
|
||||||
output_int(code_string_list,fout);
|
|
||||||
int size=string_list.size();
|
|
||||||
output_int(size,fout);
|
|
||||||
for(int i=0;i<size;++i)
|
|
||||||
fout<<string_list[i]<<"\0";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
void nasal_codegen::generate_symbol_list(std::ofstream& fout)
|
|
||||||
{
|
|
||||||
output_int(code_symbol_list,fout);
|
|
||||||
int size=symbol_list.size();
|
|
||||||
output_int(size,fout);
|
|
||||||
for(int i=0;i<size;++i)
|
|
||||||
fout<<symbol_list[i]<<"\0";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nasal_codegen::main_progress(std::string filename,nasal_ast& root)
|
void nasal_codegen::output_exec(std::string filename,nasal_ast& root)
|
||||||
{
|
{
|
||||||
this->init();
|
this->init();
|
||||||
std::ofstream fout(filename,std::ios::binary);
|
std::ofstream fout(filename,std::ios::binary);
|
||||||
if(fout.fail())
|
if(fout.fail())
|
||||||
{
|
{
|
||||||
|
++error;
|
||||||
std::cout<<">> [code] cannot generate file \""<<filename<<"\"."<<std::endl;
|
std::cout<<">> [code] cannot generate file \""<<filename<<"\"."<<std::endl;
|
||||||
fout.close();
|
fout.close();
|
||||||
return;
|
return;
|
||||||
|
@ -147,12 +94,85 @@ void nasal_codegen::main_progress(std::string filename,nasal_ast& root)
|
||||||
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)
|
||||||
fout<<header[i];
|
fout<<header[i];
|
||||||
generate_root(root,fout);
|
output_root(root,fout);
|
||||||
generate_number_list(fout);
|
|
||||||
generate_string_list(fout);
|
|
||||||
generate_symbol_list(fout);
|
|
||||||
fout.close();
|
fout.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
root.set_str(tmp);
|
||||||
|
}
|
||||||
|
for(int i=0;i<size;++i)
|
||||||
|
{
|
||||||
|
nasal_ast new_ast;
|
||||||
|
root.add_child(new_ast);
|
||||||
|
input_root(root.get_children().back(),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)
|
||||||
|
{
|
||||||
|
root.clear();
|
||||||
|
std::ifstream fin(filename,std::ios::binary);
|
||||||
|
if(fin.fail())
|
||||||
|
{
|
||||||
|
++error;
|
||||||
|
std::cout<<">> [code] cannot open file\""<<filename<<"\"."<<std::endl;
|
||||||
|
fin.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unsigned char header[4]={0x40,0x56,0x4b,0x21};
|
||||||
|
for(int i=0;i<4;++i)
|
||||||
|
if((unsigned char)fin.get()!=header[i])
|
||||||
|
{
|
||||||
|
++error;
|
||||||
|
std::cout<<">> [code] \""<<filename<<"\" is not an executable file."<<std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
input_root(root,fin);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -36,6 +36,7 @@ enum ast_node
|
||||||
ast_multi_id,ast_multi_scalar,
|
ast_multi_id,ast_multi_scalar,
|
||||||
ast_definition,ast_multi_assign,
|
ast_definition,ast_multi_assign,
|
||||||
ast_continue,ast_break,ast_return,
|
ast_continue,ast_break,ast_return,
|
||||||
|
ast_begin,ast_end // reserved for code generator
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string ast_str(int type)
|
std::string ast_str(int type)
|
||||||
|
|
Loading…
Reference in New Issue