Nasal-Interpreter/nasal_import.h

122 lines
3.3 KiB
C
Raw Normal View History

2021-10-15 22:21:57 +08:00
#ifndef __NASAL_IMPORT_H__
#define __NASAL_IMPORT_H__
class nasal_import
{
private:
uint32_t error;
nasal_lexer import_lex;
nasal_parse import_par;
nasal_ast import_ast;
2021-10-16 21:08:57 +08:00
std::vector<std::string> file_table;
2021-10-15 22:21:57 +08:00
void die(const std::string&,const char*);
bool check_import(const nasal_ast&);
bool check_exist(const std::string&);
void linker(nasal_ast&,nasal_ast&&);
nasal_ast file_import(nasal_ast&);
nasal_ast load(nasal_ast&,uint16_t);
public:
uint32_t err(){return error;}
2021-10-16 21:08:57 +08:00
void link(nasal_parse&,const std::string&);
const std::vector<std::string>& get_file() const {return file_table;}
2021-10-15 22:21:57 +08:00
};
void nasal_import::die(const std::string& file,const char* stage)
{
++error;
std::cout<<"[import] in <\""<<file<<"\">: error(s) occurred in "<<stage<<".\n";
}
bool nasal_import::check_import(const nasal_ast& node)
{
/*
only this kind of node can be recognized as 'import':
call
id:import
call_func
string:'filename'
*/
2021-10-16 21:08:57 +08:00
if(node.type()!=ast_call)
2021-10-15 22:21:57 +08:00
return false;
2021-10-16 21:08:57 +08:00
const std::vector<nasal_ast>& ref_vec=node.child();
2021-10-15 22:21:57 +08:00
if(ref_vec.size()!=2)
return false;
2021-10-16 21:08:57 +08:00
if(ref_vec[0].str()!="import")
2021-10-15 22:21:57 +08:00
return false;
2021-10-16 21:08:57 +08:00
if(ref_vec[1].type()!=ast_callf)
2021-10-15 22:21:57 +08:00
return false;
2021-10-16 21:08:57 +08:00
if(ref_vec[1].child().size()!=1 || ref_vec[1].child()[0].type()!=ast_str)
2021-10-15 22:21:57 +08:00
return false;
return true;
}
bool nasal_import::check_exist(const std::string& file)
{
// avoid importing the same file
2021-10-16 21:08:57 +08:00
for(auto& fname:file_table)
2021-10-15 22:21:57 +08:00
if(file==fname)
return true;
2021-10-16 21:08:57 +08:00
file_table.push_back(file);
2021-10-15 22:21:57 +08:00
return false;
}
void nasal_import::linker(nasal_ast& root,nasal_ast&& add_root)
{
// add children of add_root to the back of root
2021-10-16 21:08:57 +08:00
for(auto& i:add_root.child())
root.add(std::move(i));
2021-10-15 22:21:57 +08:00
}
nasal_ast nasal_import::file_import(nasal_ast& node)
{
// get filename and set node to ast_null
2021-10-16 21:08:57 +08:00
std::string filename=node.child()[1].child()[0].str();
2021-10-15 22:21:57 +08:00
node.clear();
// avoid infinite loading loop
if(check_exist(filename))
2021-10-16 21:08:57 +08:00
return {0,ast_root};
2021-10-15 22:21:57 +08:00
// start importing...
2021-10-16 21:08:57 +08:00
import_lex.scan(filename);
2021-10-15 22:21:57 +08:00
if(import_lex.err())
{
die(filename,"lexer");
2021-10-16 21:08:57 +08:00
return {0,ast_root};
2021-10-15 22:21:57 +08:00
}
2021-10-16 21:08:57 +08:00
import_par.compile(import_lex);
2021-10-15 22:21:57 +08:00
if(import_par.err())
{
die(filename,"parser");
2021-10-16 21:08:57 +08:00
return {0,ast_root};
2021-10-15 22:21:57 +08:00
}
2021-10-16 21:08:57 +08:00
nasal_ast tmp=std::move(import_par.ast());
2021-10-15 22:21:57 +08:00
// check if tmp has 'import'
2021-10-16 21:08:57 +08:00
return load(tmp,file_table.size()-1);
2021-10-15 22:21:57 +08:00
}
nasal_ast nasal_import::load(nasal_ast& root,uint16_t fileindex)
{
nasal_ast new_root(0,ast_root);
2021-10-16 21:08:57 +08:00
for(auto& i:root.child())
2021-10-15 22:21:57 +08:00
if(check_import(i))
linker(new_root,file_import(i));
// add root to the back of new_root
nasal_ast file_head(0,ast_file);
file_head.set_num(fileindex);
2021-10-16 21:08:57 +08:00
new_root.add(std::move(file_head));
2021-10-15 22:21:57 +08:00
linker(new_root,std::move(root));
return new_root;
}
2021-10-16 21:08:57 +08:00
void nasal_import::link(nasal_parse& parse,const std::string& self)
2021-10-15 22:21:57 +08:00
{
// initializing
error=0;
2021-10-16 21:08:57 +08:00
file_table={self};
2021-10-15 22:21:57 +08:00
// scan root and import files,then generate a new ast and return to import_ast
// the main file's index is 0
2021-10-16 21:08:57 +08:00
parse.ast()=load(parse.ast(),0);
2021-10-15 22:21:57 +08:00
}
2020-10-11 20:28:27 +08:00
#endif