update 'import'
This commit is contained in:
parent
e223eff9b9
commit
939a7a62b7
|
@ -1,3 +1,8 @@
|
|||
var import=func(filename)
|
||||
{
|
||||
nasal_call_import(filename);
|
||||
return nil;
|
||||
}
|
||||
var print=func(elements...)
|
||||
{
|
||||
nasal_call_builtin_std_cout(elements);
|
||||
|
|
|
@ -3,20 +3,19 @@
|
|||
nasal_resource resource;
|
||||
nasal_lexer lexer;
|
||||
nasal_parse parse;
|
||||
nasal_import preprocessor;
|
||||
std::string command;
|
||||
std::string inputfile="null";
|
||||
nasal_runtime runtime;
|
||||
|
||||
void help()
|
||||
{
|
||||
std::cout<<">> [\'file\'] input a file."<<std::endl;
|
||||
std::cout<<">> [cls ] clear the screen."<<std::endl;
|
||||
std::cout<<">> [\"file\"] input a file."<<std::endl;
|
||||
std::cout<<">> [clear ] clear the screen."<<std::endl;
|
||||
std::cout<<">> [del ] clear the resource code."<<std::endl;
|
||||
std::cout<<">> [lib ] add lib file."<<std::endl;
|
||||
std::cout<<">> [rs ] print resource code."<<std::endl;
|
||||
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<<">> [del ] clear the 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<<">> [ast ] do parsing and check the abstract syntax tree."<<std::endl;
|
||||
std::cout<<">> [run ] run code."<<std::endl;
|
||||
std::cout<<">> [logo ] print logo of nasal ."<<std::endl;
|
||||
std::cout<<">> [exit ] quit nasal interpreter."<<std::endl;
|
||||
|
@ -38,68 +37,70 @@ void del_func()
|
|||
resource.clear();
|
||||
lexer.clear();
|
||||
parse.clear();
|
||||
inputfile="null";
|
||||
std::cout<<">> [Delete] complete."<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
void die(std::string stage,std::string filename)
|
||||
{
|
||||
std::cout<<">> ["<<stage<<"] in <\""<<filename<<"\">: error(s) occurred,stop."<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
void lex_func()
|
||||
{
|
||||
lexer.scanner(resource.get_file());
|
||||
if(!lexer.get_error())
|
||||
lexer.print_token();
|
||||
else
|
||||
std::cout<<">> [lexer] error(s) occurred,stop.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
void par_func()
|
||||
{
|
||||
lexer.scanner(resource.get_file());
|
||||
if(!lexer.get_error())
|
||||
if(lexer.get_error())
|
||||
{
|
||||
parse.set_toklist(lexer.get_token_list());
|
||||
parse.main_process();
|
||||
if(parse.get_error())
|
||||
std::cout<<">> [parse] error(s) occurred,stop.\n";
|
||||
die("lexer",inputfile);
|
||||
return;
|
||||
}
|
||||
else
|
||||
std::cout<<">> [lexer] error(s) occurred,stop.\n";
|
||||
lexer.print_token();
|
||||
return;
|
||||
}
|
||||
|
||||
void ast_print()
|
||||
{
|
||||
lexer.scanner(resource.get_file());
|
||||
if(!lexer.get_error())
|
||||
if(lexer.get_error())
|
||||
{
|
||||
parse.set_toklist(lexer.get_token_list());
|
||||
parse.main_process();
|
||||
if(parse.get_error())
|
||||
std::cout<<">> [parse] error(s) occurred,stop.\n";
|
||||
else
|
||||
parse.get_root().print_ast(0);
|
||||
die("lexer",inputfile);
|
||||
return;
|
||||
}
|
||||
else
|
||||
std::cout<<">> [lexer] error(s) occurred,stop.\n";
|
||||
parse.set_toklist(lexer.get_token_list());
|
||||
parse.main_process();
|
||||
if(parse.get_error())
|
||||
{
|
||||
die("parse",inputfile);
|
||||
return;
|
||||
}
|
||||
parse.get_root().print_ast(0);
|
||||
return;
|
||||
}
|
||||
void runtime_start()
|
||||
{
|
||||
lexer.scanner(resource.get_file());
|
||||
if(!lexer.get_error())
|
||||
if(lexer.get_error())
|
||||
{
|
||||
parse.set_toklist(lexer.get_token_list());
|
||||
parse.main_process();
|
||||
if(parse.get_error())
|
||||
std::cout<<">> [parse] error(s) occurred,stop.\n";
|
||||
else
|
||||
{
|
||||
runtime.set_root(parse.get_root());
|
||||
runtime.run();
|
||||
}
|
||||
die("lexer",inputfile);
|
||||
return;
|
||||
}
|
||||
else
|
||||
std::cout<<">> [lexer] error(s) occurred,stop.\n";
|
||||
parse.set_toklist(lexer.get_token_list());
|
||||
parse.main_process();
|
||||
if(parse.get_error())
|
||||
{
|
||||
die("parse",inputfile);
|
||||
return;
|
||||
}
|
||||
preprocessor.preprocessing(parse.get_root());
|
||||
if(preprocessor.get_error())
|
||||
{
|
||||
die("import",inputfile);
|
||||
return;
|
||||
}
|
||||
runtime.set_root(preprocessor.get_root());
|
||||
runtime.run();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -110,7 +111,6 @@ int main()
|
|||
system("chcp 65001");
|
||||
system("cls");
|
||||
#endif
|
||||
// this curve looks really cool
|
||||
logo();
|
||||
#ifdef _WIN32
|
||||
std::cout<<">> [system] Windows system."<<std::endl;
|
||||
|
@ -121,9 +121,10 @@ int main()
|
|||
#ifdef TARGET_OS_MAC
|
||||
std::cout<<">> [system] MacOS system."<<std::endl;
|
||||
#endif
|
||||
|
||||
std::cout<<">> Nasal interpreter ver 3.0 ."<<std::endl;
|
||||
std::cout<<">> Code: https://github.com/ValKmjolnir/Nasal-Interpreter"<<std::endl;
|
||||
std::cout<<">> More info: http://wiki.flightgear.org/Nasal_scripting_language"<<std::endl;
|
||||
std::cout<<">> Info: http://wiki.flightgear.org/Nasal_scripting_language"<<std::endl;
|
||||
std::cout<<">> Input \"help\" to get help ."<<std::endl;
|
||||
while(1)
|
||||
{
|
||||
|
@ -131,7 +132,7 @@ int main()
|
|||
std::cin>>command;
|
||||
if(command=="help")
|
||||
help();
|
||||
else if(command=="cls" || command=="clear")
|
||||
else if(command=="clear")
|
||||
{
|
||||
#ifdef _WIN32
|
||||
system("cls");
|
||||
|
@ -145,14 +146,10 @@ int main()
|
|||
}
|
||||
else if(command=="del")
|
||||
del_func();
|
||||
else if(command=="lib")
|
||||
resource.load_lib();
|
||||
else if(command=="rs")
|
||||
resource.print_file();
|
||||
else if(command=="lex")
|
||||
lex_func();
|
||||
else if(command=="par")
|
||||
par_func();
|
||||
else if(command=="ast")
|
||||
ast_print();
|
||||
else if(command=="run")
|
||||
|
@ -162,7 +159,10 @@ int main()
|
|||
else if(command=="exit")
|
||||
break;
|
||||
else
|
||||
resource.input_file(command);
|
||||
{
|
||||
inputfile=command;
|
||||
resource.input_file(inputfile);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -24,6 +24,7 @@
|
|||
#include "nasal_lexer.h"
|
||||
#include "nasal_ast.h"
|
||||
#include "nasal_parse.h"
|
||||
#include "nasal_import.h"
|
||||
#include "nasal_gc.h"
|
||||
#include "nasal_runtime.h"
|
||||
#include "nasal_builtin.h"
|
||||
|
|
|
@ -8,7 +8,7 @@ int nasal_runtime::builtin_print(int local_scope_addr)
|
|||
{
|
||||
// get arguments
|
||||
int vector_value_addr=in_builtin_find("elements");
|
||||
if(vector_value_addr<0 || nasal_vm.gc_get(vector_value_addr).get_type()!=vm_vector)
|
||||
if(vector_value_addr<0 || !in_builtin_check(vector_value_addr,vm_vector))
|
||||
{
|
||||
std::cout<<">> [runtime] builtin_print: cannot find values or wrong value type."<<std::endl;
|
||||
++error;
|
||||
|
@ -42,13 +42,13 @@ int nasal_runtime::builtin_append(int local_scope_addr)
|
|||
{
|
||||
int vector_value_addr=in_builtin_find("vector");
|
||||
int elem_value_addr=in_builtin_find("elements");
|
||||
if(vector_value_addr<0 || nasal_vm.gc_get(vector_value_addr).get_type()!=vm_vector)
|
||||
if(vector_value_addr<0 || !in_builtin_check(vector_value_addr,vm_vector))
|
||||
{
|
||||
std::cout<<">> [runtime] builtin_append: cannot find values or wrong value type."<<std::endl;
|
||||
++error;
|
||||
return -1;
|
||||
}
|
||||
if(elem_value_addr<0 || nasal_vm.gc_get(elem_value_addr).get_type()!=vm_vector)
|
||||
if(elem_value_addr<0 || !in_builtin_check(elem_value_addr,vm_vector))
|
||||
{
|
||||
std::cout<<">> [runtime] builtin_append: cannot find values or wrong value type."<<std::endl;
|
||||
++error;
|
||||
|
@ -248,7 +248,6 @@ int nasal_runtime::builtin_foutput(int local_scope_addr)
|
|||
return ret_addr;
|
||||
}
|
||||
|
||||
|
||||
int nasal_runtime::builtin_split(int local_scope_addr)
|
||||
{
|
||||
int delimeter_value_addr=in_builtin_find("delimeter");
|
||||
|
@ -736,8 +735,17 @@ int nasal_runtime::builtin_getkeys(int local_scope_addr)
|
|||
++error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret_addr=nasal_vm.gc_get(hash_addr).get_hash().get_keys();
|
||||
return ret_addr;
|
||||
}
|
||||
int nasal_runtime::builtin_import(int local_scope_addr)
|
||||
{
|
||||
// this function is used in preprocessing.
|
||||
// this function will return nothing when running.
|
||||
++error;
|
||||
std::cout<<">> [runtime] cannot use import when running."<<std::endl;
|
||||
int ret_addr=nasal_vm.gc_alloc();
|
||||
nasal_vm.gc_get(ret_addr).set_type(vm_nil);
|
||||
return ret_addr;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,174 @@
|
|||
#ifndef __NASAL_IMPORT_H__
|
||||
#define __NASAL_IMPORT_H__
|
||||
|
||||
class nasal_import
|
||||
{
|
||||
private:
|
||||
nasal_resource import_src;
|
||||
nasal_lexer import_lex;
|
||||
nasal_parse import_par;
|
||||
nasal_ast import_ast;
|
||||
std::vector<std::string> filename_table;
|
||||
int error;
|
||||
void die(std::string,std::string);
|
||||
void init();
|
||||
bool check_import(nasal_ast&);
|
||||
bool check_exist(std::string);
|
||||
void linker(nasal_ast&,nasal_ast&);
|
||||
nasal_ast file_import(nasal_ast&);
|
||||
nasal_ast load(nasal_ast&);
|
||||
public:
|
||||
nasal_import();
|
||||
int get_error();
|
||||
void preprocessing(nasal_ast&);
|
||||
nasal_ast& get_root();
|
||||
};
|
||||
|
||||
nasal_import::nasal_import()
|
||||
{
|
||||
import_src.clear();
|
||||
import_lex.clear();
|
||||
import_par.clear();
|
||||
import_ast.clear();
|
||||
filename_table.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_import::die(std::string filename,std::string error_stage)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [import] in <\""<<filename<<"\">: error(s) occurred in "<<error_stage<<"."<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_import::init()
|
||||
{
|
||||
import_src.clear();
|
||||
import_lex.clear();
|
||||
import_par.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
bool nasal_import::check_import(nasal_ast& node)
|
||||
{
|
||||
/*
|
||||
call
|
||||
id:import
|
||||
call_func
|
||||
string:'filename'
|
||||
*/
|
||||
if(node.get_type()!=ast_call)
|
||||
return false;
|
||||
std::vector<nasal_ast>& ref_vec=node.get_children();
|
||||
if(ref_vec.size()!=2)
|
||||
return false;
|
||||
if(ref_vec[0].get_str()!="import")
|
||||
return false;
|
||||
if(ref_vec[1].get_type()!=ast_call_func)
|
||||
return false;
|
||||
if(ref_vec[1].get_children().size()!=1 || ref_vec[1].get_children()[0].get_type()!=ast_string)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nasal_import::check_exist(std::string filename)
|
||||
{
|
||||
int size=filename_table.size();
|
||||
for(int i=0;i<size;++i)
|
||||
if(filename==filename_table[i])
|
||||
return true;
|
||||
filename_table.push_back(filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
void nasal_import::linker(nasal_ast& root,nasal_ast& add_root)
|
||||
{
|
||||
std::vector<nasal_ast>& ref_vec=add_root.get_children();
|
||||
int size=ref_vec.size();
|
||||
for(int i=0;i<size;++i)
|
||||
root.add_child(ref_vec[i]);
|
||||
return;
|
||||
}
|
||||
|
||||
nasal_ast nasal_import::file_import(nasal_ast& node)
|
||||
{
|
||||
// initializing
|
||||
nasal_ast tmp;
|
||||
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))
|
||||
{
|
||||
die(filename,"resource");
|
||||
return tmp;
|
||||
}
|
||||
import_lex.scanner(import_src.get_file());
|
||||
if(import_lex.get_error())
|
||||
{
|
||||
die(filename,"lexer");
|
||||
return tmp;
|
||||
}
|
||||
import_par.set_toklist(import_lex.get_token_list());
|
||||
import_par.main_process();
|
||||
if(import_par.get_error())
|
||||
{
|
||||
die(filename,"parser");
|
||||
return tmp;
|
||||
}
|
||||
tmp=import_par.get_root();
|
||||
// check if tmp has 'import'
|
||||
return load(tmp);
|
||||
}
|
||||
|
||||
nasal_ast nasal_import::load(nasal_ast& root)
|
||||
{
|
||||
nasal_ast new_root;
|
||||
new_root.set_line(0);
|
||||
new_root.set_type(ast_root);
|
||||
|
||||
std::vector<nasal_ast>& ref_vec=root.get_children();
|
||||
int size=ref_vec.size();
|
||||
for(int i=0;i<size;++i)
|
||||
{
|
||||
if(check_import(ref_vec[i]))
|
||||
{
|
||||
nasal_ast tmp=file_import(ref_vec[i]);
|
||||
// add tmp to the back of new_root
|
||||
linker(new_root,tmp);
|
||||
}
|
||||
}
|
||||
// add root to the back of new_root
|
||||
linker(new_root,root);
|
||||
return new_root;
|
||||
}
|
||||
|
||||
void nasal_import::preprocessing(nasal_ast& root)
|
||||
{
|
||||
// initializing
|
||||
error=0;
|
||||
filename_table.clear();
|
||||
import_ast.clear();
|
||||
// scan root and import files,then generate a new ast and return to import_ast
|
||||
import_ast=load(root);
|
||||
return;
|
||||
}
|
||||
|
||||
nasal_ast& nasal_import::get_root()
|
||||
{
|
||||
return import_ast;
|
||||
}
|
||||
|
||||
int nasal_import::get_error()
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -113,11 +113,13 @@ std::string nasal_lexer::number_gen(std::vector<char>& res,int& ptr,int& line)
|
|||
{
|
||||
int res_size=res.size();
|
||||
bool scientific_notation=false;// numbers like 1e8 are scientific_notation
|
||||
bool is_hex=(ptr<res_size && res[ptr]=='0' && ptr+1<res_size && res[ptr+1]=='x');
|
||||
bool is_oct=(ptr<res_size && res[ptr]=='0' && ptr+1<res_size && res[ptr+1]=='o');
|
||||
std::string token_str="";
|
||||
while(ptr<res_size && IS_NUMBER_BODY(res[ptr]))
|
||||
{
|
||||
token_str+=res[ptr];
|
||||
if(res[ptr]=='e' || res[ptr]=='E')
|
||||
if((res[ptr]=='e' || res[ptr]=='E') && !is_hex && !is_oct)
|
||||
{
|
||||
scientific_notation=true;
|
||||
++ptr;
|
||||
|
@ -298,7 +300,7 @@ void nasal_lexer::scanner(std::vector<char>& res)
|
|||
else if(IS_NOTE_HEAD(res[ptr]))
|
||||
{
|
||||
// avoid note
|
||||
while(ptr<res_size && res[ptr++]!='\n');
|
||||
while(ptr<res_size && res[ptr]!='\n') ++ptr;
|
||||
// after this process ptr will point to a '\n'
|
||||
// don't ++ptr then the counter for line can work correctly
|
||||
}
|
||||
|
@ -309,7 +311,6 @@ void nasal_lexer::scanner(std::vector<char>& res)
|
|||
++ptr;
|
||||
}
|
||||
}
|
||||
std::cout<<">> [lexer] complete scanning. "<<error<<" error(s)."<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -146,7 +146,6 @@ void nasal_parse::main_process()
|
|||
}
|
||||
}
|
||||
}
|
||||
std::cout<<">> [parse] complete generation. "<<error<<" error(s)."<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,45 +1,26 @@
|
|||
#ifndef __NASAL_RESOURCE_H__
|
||||
#define __NASAL_RESOURCE_H__
|
||||
|
||||
/* filenames of lib files */
|
||||
#ifndef LIB_FILE_NUM
|
||||
#define LIB_FILE_NUM 11
|
||||
const std::string lib_filename[LIB_FILE_NUM]=
|
||||
{
|
||||
"lib/base.nas",
|
||||
"lib/bits.nas",
|
||||
"lib/io.nas",
|
||||
"lib/math.nas",
|
||||
"lib/readline.nas",
|
||||
"lib/regex.nas",
|
||||
"lib/sqlite.nas",
|
||||
"lib/system.nas",
|
||||
"lib/thread.nas",
|
||||
"lib/unix.nas",
|
||||
"lib/utf8.nas"
|
||||
};
|
||||
#endif
|
||||
|
||||
class nasal_resource
|
||||
{
|
||||
private:
|
||||
std::vector<char> res;
|
||||
public:
|
||||
void input_file(std::string);
|
||||
void load_lib();
|
||||
void clear();
|
||||
void print_file();
|
||||
bool input_file(std::string);
|
||||
void clear();
|
||||
void print_file();
|
||||
std::vector<char>& get_file();
|
||||
};
|
||||
|
||||
void nasal_resource::input_file(std::string filename)
|
||||
bool nasal_resource::input_file(std::string filename)
|
||||
{
|
||||
res.clear();
|
||||
std::ifstream fin(filename,std::ios::binary);
|
||||
if(fin.fail())
|
||||
{
|
||||
std::cout<<">> [resource] cannot open file \'"<<filename<<"\'."<<std::endl;
|
||||
std::cout<<">> [resource] cannot open file \""<<filename<<"\"."<<std::endl;
|
||||
fin.close();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
while(!fin.eof())
|
||||
{
|
||||
|
@ -48,14 +29,7 @@ void nasal_resource::input_file(std::string filename)
|
|||
res.push_back(c);
|
||||
}
|
||||
fin.close();
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_resource::load_lib()
|
||||
{
|
||||
for(int i=0;i<LIB_FILE_NUM;++i)
|
||||
this->input_file(lib_filename[i]);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
void nasal_resource::clear()
|
||||
|
|
|
@ -99,6 +99,7 @@ private:
|
|||
int builtin_contains(int);
|
||||
int builtin_delete(int);
|
||||
int builtin_getkeys(int);
|
||||
int builtin_import(int);
|
||||
void load_builtin_function();
|
||||
public:
|
||||
nasal_runtime();
|
||||
|
@ -163,6 +164,7 @@ void nasal_runtime::load_builtin_function()
|
|||
{"nasal_call_builtin_contains", nasal_runtime::builtin_contains},
|
||||
{"nasal_call_builtin_delete", nasal_runtime::builtin_delete},
|
||||
{"nasal_call_builtin_get_keys", nasal_runtime::builtin_getkeys},
|
||||
{"nasal_call_import", nasal_runtime::builtin_import},
|
||||
{"", NULL}
|
||||
};
|
||||
for(int i=0;builtin_func_table[i].func_pointer;++i)
|
||||
|
@ -271,6 +273,7 @@ int nasal_runtime::main_progress()
|
|||
case ast_while:case ast_for:case ast_forindex:case ast_foreach:
|
||||
ret_state=loop_progress(root.get_children()[i],-1,false);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:
|
||||
|
@ -325,6 +328,7 @@ int nasal_runtime::block_progress(nasal_ast& node,int local_scope_addr,bool allo
|
|||
case ast_while:case ast_for:case ast_forindex:case ast_foreach:
|
||||
ret_state=loop_progress(tmp_node,local_scope_addr,allow_return);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:
|
||||
|
|
Loading…
Reference in New Issue