✨ add detail location info in tokens
prepare for multi-line error reporter module
This commit is contained in:
parent
268a03864e
commit
8df02d25ad
21
main.cpp
21
main.cpp
|
@ -39,10 +39,8 @@ std::ostream& help(std::ostream& out) {
|
|||
<<" -c, --code | view bytecode.\n"
|
||||
<<" -e, --exec | execute.\n"
|
||||
<<" -t, --time | show execute time.\n"
|
||||
<<" -d, --detail | get detail crash info.\n"
|
||||
<<" | get detail path-not-found info.\n"
|
||||
<<" | get detail gc info.\n"
|
||||
<<" -dbg, --debug | debug mode (ignore -t -d).\n"
|
||||
<<" -d, --detail | get detail info.\n"
|
||||
<<" -dbg, --debug | debug mode.\n"
|
||||
<<"file:\n"
|
||||
<<" <filename> | execute file.\n"
|
||||
<<"argv:\n"
|
||||
|
@ -57,11 +55,11 @@ std::ostream& logo(std::ostream& out) {
|
|||
<<" / \\/ / _` / __|/ _` | |\n"
|
||||
<<" / /\\ / (_| \\__ \\ (_| | |\n"
|
||||
<<" \\_\\ \\/ \\__,_|___/\\__,_|_|\n"
|
||||
<<"version : "<<__nasver<<" ("<<__DATE__<<" "<<__TIME__<<")\n"
|
||||
<<"c++ std : "<<__cplusplus<<"\n"
|
||||
<<"code repo : https://github.com/ValKmjolnir/Nasal-Interpreter\n"
|
||||
<<"code repo : https://gitee.com/valkmjolnir/Nasal-Interpreter\n"
|
||||
<<"lang wiki : https://wiki.flightgear.org/Nasal_scripting_language\n"
|
||||
<<"ver : "<<__nasver<<" ("<<__DATE__<<" "<<__TIME__<<")\n"
|
||||
<<"std : c++ "<<__cplusplus<<"\n"
|
||||
<<"repo : https://github.com/ValKmjolnir/Nasal-Interpreter\n"
|
||||
<<"repo : https://gitee.com/valkmjolnir/Nasal-Interpreter\n"
|
||||
<<"wiki : https://wiki.flightgear.org/Nasal_scripting_language\n"
|
||||
<<"input <nasal -h> to get help .\n";
|
||||
return out;
|
||||
}
|
||||
|
@ -84,10 +82,13 @@ void execute(const string& file,const std::vector<string>& argv,const u32 cmd) {
|
|||
|
||||
// lexer scans file to get tokens
|
||||
lex.scan(file).chkerr();
|
||||
|
||||
// parser gets lexer's token list to compile
|
||||
parse.compile(lex).chkerr();
|
||||
|
||||
// linker gets parser's ast and load import files to this ast
|
||||
ld.link(parse,file,cmd&VM_DETAIL).chkerr();
|
||||
|
||||
// optimizer does simple optimization on ast
|
||||
optimize(parse.tree());
|
||||
if (cmd&VM_AST) {
|
||||
|
@ -107,7 +108,7 @@ void execute(const string& file,const std::vector<string>& argv,const u32 cmd) {
|
|||
auto start=ch_clk::now();
|
||||
ctx.run(gen,ld,argv,cmd&VM_DETAIL);
|
||||
auto end=ch_clk::now();
|
||||
std::clog<<"process exited after "<<(end-start).count()*1.0/ch_clk::duration::period::den<<"s.\n";
|
||||
std::clog<<"process exited after "<<(end-start).count()*1.0/ch_clk::duration::period::den<<"s.\n\n";
|
||||
} else if (cmd&VM_EXEC) {
|
||||
ctx.run(gen,ld,argv,cmd&VM_DETAIL);
|
||||
}
|
||||
|
|
71
nasal_ast.h
71
nasal_ast.h
|
@ -67,7 +67,7 @@ enum ast_node:u32 {
|
|||
};
|
||||
|
||||
const char* ast_name[]={
|
||||
"NullNode",
|
||||
"Null",
|
||||
"AbstractSyntaxTreeRoot",
|
||||
"CodeBlock",
|
||||
"FileIndex",
|
||||
|
@ -114,17 +114,17 @@ const char* ast_name[]={
|
|||
"ForeachLoop",
|
||||
"WhileLoop",
|
||||
"Iterator",
|
||||
"ConditionExpression",
|
||||
"IfExpression",
|
||||
"ElsifExpression",
|
||||
"ElseExpression",
|
||||
"ConditionStatement",
|
||||
"IfStatement",
|
||||
"ElsifStatement",
|
||||
"ElseStatement",
|
||||
"LeftTuple",
|
||||
"Tuple",
|
||||
"Definition",
|
||||
"MultipleAssignment",
|
||||
"ContinueExpression",
|
||||
"BreakExpression",
|
||||
"ReturnExpression"
|
||||
"Continue",
|
||||
"Break",
|
||||
"ReturnStatement"
|
||||
};
|
||||
|
||||
class ast {
|
||||
|
@ -133,19 +133,21 @@ private:
|
|||
u32 nd_col;
|
||||
u32 nd_type;
|
||||
f64 nd_num;
|
||||
string nd_file;
|
||||
string nd_str;
|
||||
std::vector<ast> nd_child;
|
||||
public:
|
||||
ast(const u32 l,const u32 c,const u32 t)
|
||||
: nd_line(l),nd_col(c),nd_type(t),nd_num(0) {}
|
||||
ast(const ast&);
|
||||
ast(ast&&);
|
||||
ast(const u32 l,const u32 c,const u32 t,const std::string& f)
|
||||
: nd_line(l),nd_col(c),nd_type(t),nd_num(0),nd_file(f),nd_str("") {}
|
||||
ast(const ast&) = default;
|
||||
ast(ast&&) = default;
|
||||
ast& operator=(const ast&) = default;
|
||||
ast& operator=(ast&&) = default;
|
||||
|
||||
void dump() const;
|
||||
void print(u32,bool,std::vector<string>&) const;
|
||||
void clear();
|
||||
|
||||
ast& operator=(const ast&);
|
||||
ast& operator=(ast&&);
|
||||
|
||||
ast& operator[](usize n) {return nd_child[n];}
|
||||
const ast& operator[](usize n) const {return nd_child[n];}
|
||||
usize size() const {return nd_child.size();}
|
||||
|
@ -166,43 +168,6 @@ public:
|
|||
std::vector<ast>& child() {return nd_child;}
|
||||
};
|
||||
|
||||
ast::ast(const ast& tmp):
|
||||
nd_str(tmp.nd_str),nd_child(tmp.nd_child) {
|
||||
nd_line=tmp.nd_line;
|
||||
nd_col=tmp.nd_col;
|
||||
nd_type=tmp.nd_type;
|
||||
nd_num =tmp.nd_num;
|
||||
}
|
||||
|
||||
ast::ast(ast&& tmp) {
|
||||
nd_line=tmp.nd_line;
|
||||
nd_col=tmp.nd_col;
|
||||
nd_type=tmp.nd_type;
|
||||
nd_num =tmp.nd_num;
|
||||
nd_str.swap(tmp.nd_str);
|
||||
nd_child.swap(tmp.nd_child);
|
||||
}
|
||||
|
||||
ast& ast::operator=(const ast& tmp) {
|
||||
nd_line=tmp.nd_line;
|
||||
nd_col=tmp.nd_col;
|
||||
nd_type=tmp.nd_type;
|
||||
nd_num=tmp.nd_num;
|
||||
nd_str=tmp.nd_str;
|
||||
nd_child=tmp.nd_child;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ast& ast::operator=(ast&& tmp) {
|
||||
nd_line=tmp.nd_line;
|
||||
nd_col=tmp.nd_col;
|
||||
nd_type=tmp.nd_type;
|
||||
nd_num=tmp.nd_num;
|
||||
nd_str.swap(tmp.nd_str);
|
||||
nd_child.swap(tmp.nd_child);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ast::clear() {
|
||||
nd_line=nd_col=0;
|
||||
nd_num=0;
|
||||
|
@ -230,7 +195,7 @@ void ast::print(u32 depth,bool last,std::vector<string>& indent) const{
|
|||
} else if (nd_type==ast_num || nd_type==ast_file) {
|
||||
std::cout<<":"<<nd_num;
|
||||
}
|
||||
std::cout<<" -> "<<nd_line<<":"<<nd_col<<"\n";
|
||||
std::cout<<" --> "<<nd_file<<":"<<nd_line<<":"<<nd_col<<"\n";
|
||||
if (last && depth) {
|
||||
indent.back()=" ";
|
||||
} else if (!last && depth) {
|
||||
|
|
|
@ -441,8 +441,8 @@ var builtin_substr(var* local,gc& ngc) {
|
|||
}
|
||||
usize begin=(usize)beg.num();
|
||||
usize length=(usize)len.num();
|
||||
if (begin>=str.str().length() || begin+length>str.str().length()) {
|
||||
return nas_err("susbtr","index out of range");
|
||||
if (begin>=str.str().length()) {
|
||||
return nas_err("susbtr","begin index out of range: "+std::to_string(begin));
|
||||
}
|
||||
return ngc.newstr(str.str().substr(begin,length));
|
||||
}
|
||||
|
|
|
@ -294,6 +294,7 @@ void debugger::run(
|
|||
|
||||
vmexit:
|
||||
callsort(count);
|
||||
ngc.info();
|
||||
ngc.clear();
|
||||
imm.clear();
|
||||
std::cout<<cyan<<"[debug] "<<reset<<"debugger exited\n";
|
||||
|
|
|
@ -638,9 +638,13 @@ void gc::extend(u8 type) {
|
|||
size[index]+=incr[index];
|
||||
for(u32 i=0;i<incr[index];++i) {
|
||||
nas_val* tmp=new nas_val(type);
|
||||
|
||||
// failed to allocate new memory
|
||||
if (!tmp) {
|
||||
std::exit(-1);
|
||||
}
|
||||
|
||||
// add to heap
|
||||
memory.push_back(tmp);
|
||||
unused[index].push_back(tmp);
|
||||
}
|
||||
|
@ -718,6 +722,7 @@ void gc::info() {
|
|||
if (total) {
|
||||
std::clog<<" avg | "<<sec/total*1000<<" ms\n";
|
||||
}
|
||||
std::clog<<"\n";
|
||||
}
|
||||
|
||||
var gc::alloc(u8 type) {
|
||||
|
@ -777,6 +782,8 @@ void gc::ctxchg(nas_co& ctx) {
|
|||
upvalr=ctx.upvalr;
|
||||
canary=ctx.canary;
|
||||
stack=ctx.stack;
|
||||
|
||||
// set coroutine pointer
|
||||
cort=&ctx;
|
||||
|
||||
// set coroutine state to running
|
||||
|
@ -805,6 +812,8 @@ void gc::ctxreserve() {
|
|||
canary=mctx.canary;
|
||||
top=mctx.top;
|
||||
stack=mctx.stack;
|
||||
|
||||
// set coroutine pointer to nullptr
|
||||
cort=nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -167,13 +167,14 @@ ast linker::fimpt(ast& node) {
|
|||
// avoid infinite loading loop
|
||||
filename=findf(filename);
|
||||
if (!filename.length() || exist(filename)) {
|
||||
return {0,0,ast_root};
|
||||
return {0,0,ast_root,filename};
|
||||
}
|
||||
|
||||
// start importing...
|
||||
lex.scan(filename);
|
||||
par.compile(lex);
|
||||
ast tmp=std::move(par.tree());
|
||||
|
||||
// check if tmp has 'import'
|
||||
return load(tmp,files.size()-1);
|
||||
}
|
||||
|
@ -183,24 +184,25 @@ ast linker::libimpt() {
|
|||
parse par(err);
|
||||
string filename=findf("lib.nas");
|
||||
if (!filename.length()) {
|
||||
return {0,0,ast_root};
|
||||
return {0,0,ast_root,filename};
|
||||
}
|
||||
|
||||
// avoid infinite loading loop
|
||||
if (exist(filename)) {
|
||||
return {0,0,ast_root};
|
||||
return {0,0,ast_root,filename};
|
||||
}
|
||||
|
||||
// start importing...
|
||||
lex.scan(filename);
|
||||
par.compile(lex);
|
||||
ast tmp=std::move(par.tree());
|
||||
|
||||
// check if tmp has 'import'
|
||||
return load(tmp,files.size()-1);
|
||||
}
|
||||
|
||||
ast linker::load(ast& root,u16 fileindex) {
|
||||
ast tree(0,0,ast_root);
|
||||
ast tree(0,0,ast_root,files[fileindex]);
|
||||
if (!lib_loaded) {
|
||||
link(tree,libimpt());
|
||||
lib_loaded=true;
|
||||
|
@ -213,7 +215,7 @@ ast linker::load(ast& root,u16 fileindex) {
|
|||
}
|
||||
}
|
||||
// add root to the back of tree
|
||||
ast file_head(0,0,ast_file);
|
||||
ast file_head(0,0,ast_file,files[fileindex]);
|
||||
file_head.set_num(fileindex);
|
||||
tree.add(std::move(file_head));
|
||||
link(tree,std::move(root));
|
||||
|
|
|
@ -67,12 +67,15 @@ enum class tok:u32 {
|
|||
};
|
||||
|
||||
struct token {
|
||||
u32 line;
|
||||
u32 col;
|
||||
tok type;
|
||||
string str;
|
||||
token(u32 l=0,u32 c=0,tok t=tok::null,const string& s="")
|
||||
: line(l),col(c),type(t),str(s) {}
|
||||
u32 tk_begin_line; // token begin line
|
||||
u32 tk_begin_column;// token begin column
|
||||
u32 tk_end_line; // token end line
|
||||
u32 tk_end_column; // token end column
|
||||
tok type; // token type
|
||||
string str; // content
|
||||
string file; // scanned file path
|
||||
token() = default;
|
||||
token(const token&) = default;
|
||||
};
|
||||
|
||||
class lexer {
|
||||
|
@ -80,6 +83,7 @@ private:
|
|||
u32 line;
|
||||
u32 column;
|
||||
usize ptr;
|
||||
string filename;
|
||||
string res;
|
||||
error& err;
|
||||
std::vector<token> toks;
|
||||
|
@ -153,7 +157,7 @@ private:
|
|||
token dots();
|
||||
token calc_opr();
|
||||
public:
|
||||
lexer(error& e): line(1),column(0),ptr(0),res(""),err(e) {}
|
||||
lexer(error& e): line(1),column(0),ptr(0),filename(""),res(""),err(e) {}
|
||||
const error& scan(const string&);
|
||||
const std::vector<token>& result() const {return toks;}
|
||||
};
|
||||
|
@ -213,11 +217,15 @@ void lexer::err_char() {
|
|||
}
|
||||
|
||||
void lexer::open(const string& file) {
|
||||
// check file exsits and it is a regular file
|
||||
struct stat buffer;
|
||||
if (stat(file.c_str(),&buffer)==0 && !S_ISREG(buffer.st_mode)) {
|
||||
err.err("lexer","<"+file+"> is not a regular file");
|
||||
err.chkerr();
|
||||
}
|
||||
|
||||
// load
|
||||
filename=file;
|
||||
std::ifstream in(file,std::ios::binary);
|
||||
if (in.fail()) {
|
||||
err.err("lexer","failed to open <"+file+">");
|
||||
|
@ -268,6 +276,8 @@ string lexer::utf8_gen() {
|
|||
}
|
||||
|
||||
token lexer::id_gen() {
|
||||
u32 begin_line=line;
|
||||
u32 begin_column=column;
|
||||
string str="";
|
||||
while(ptr<res.size() && (is_id(res[ptr])||is_dec(res[ptr]))) {
|
||||
if (res[ptr]<0) { // utf-8
|
||||
|
@ -278,10 +288,12 @@ token lexer::id_gen() {
|
|||
}
|
||||
}
|
||||
tok type=get_type(str);
|
||||
return {line,column,(type!=tok::null)?type:tok::id,str};
|
||||
return {begin_line,begin_column,line,column,(type!=tok::null)?type:tok::id,str,filename};
|
||||
}
|
||||
|
||||
token lexer::num_gen() {
|
||||
u32 begin_line=line;
|
||||
u32 begin_column=column;
|
||||
// generate hex number
|
||||
if (ptr+1<res.size() && res[ptr]=='0' && res[ptr+1]=='x') {
|
||||
string str="0x";
|
||||
|
@ -293,7 +305,7 @@ token lexer::num_gen() {
|
|||
if (str.length()<3) { // "0x"
|
||||
err.err("lexer",line,column,str.length(),"invalid number `"+str+"`");
|
||||
}
|
||||
return {line,column,tok::num,str};
|
||||
return {begin_line,begin_column,line,column,tok::num,str,filename};
|
||||
} else if (ptr+1<res.size() && res[ptr]=='0' && res[ptr+1]=='o') { // generate oct number
|
||||
string str="0o";
|
||||
ptr+=2;
|
||||
|
@ -309,7 +321,7 @@ token lexer::num_gen() {
|
|||
if (str.length()==2 || erfmt) {
|
||||
err.err("lexer",line,column,str.length(),"invalid number `"+str+"`");
|
||||
}
|
||||
return {line,column,tok::num,str};
|
||||
return {begin_line,begin_column,line,column,tok::num,str,filename};
|
||||
}
|
||||
// generate dec number
|
||||
// dec number -> [0~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*)
|
||||
|
@ -326,7 +338,7 @@ token lexer::num_gen() {
|
|||
if (str.back()=='.') {
|
||||
column+=str.length();
|
||||
err.err("lexer",line,column,str.length(),"invalid number `"+str+"`");
|
||||
return {line,column,tok::num,"0"};
|
||||
return {begin_line,begin_column,line,column,tok::num,"0",filename};
|
||||
}
|
||||
}
|
||||
if (ptr<res.size() && (res[ptr]=='e' || res[ptr]=='E')) {
|
||||
|
@ -341,14 +353,16 @@ token lexer::num_gen() {
|
|||
if (str.back()=='e' || str.back()=='E' || str.back()=='-' || str.back()=='+') {
|
||||
column+=str.length();
|
||||
err.err("lexer",line,column,str.length(),"invalid number `"+str+"`");
|
||||
return {line,column,tok::num,"0"};
|
||||
return {begin_line,begin_column,line,column,tok::num,"0",filename};
|
||||
}
|
||||
}
|
||||
column+=str.length();
|
||||
return {line,column,tok::num,str};
|
||||
return {begin_line,begin_column,line,column,tok::num,str,filename};
|
||||
}
|
||||
|
||||
token lexer::str_gen() {
|
||||
u32 begin_line=line;
|
||||
u32 begin_column=column;
|
||||
string str="";
|
||||
const char begin=res[ptr];
|
||||
++column;
|
||||
|
@ -384,16 +398,18 @@ token lexer::str_gen() {
|
|||
// check if this string ends with a " or '
|
||||
if (ptr++>=res.size()) {
|
||||
err.err("lexer",line,column,1,"get EOF when generating string");
|
||||
return {line,column,tok::str,str};
|
||||
return {begin_line,begin_column,line,column,tok::str,str,filename};
|
||||
}
|
||||
++column;
|
||||
if (begin=='`' && str.length()!=1) {
|
||||
err.err("lexer",line,column,1,"\'`\' is used for string that includes one character");
|
||||
}
|
||||
return {line,column,tok::str,str};
|
||||
return {begin_line,begin_column,line,column,tok::str,str,filename};
|
||||
}
|
||||
|
||||
token lexer::single_opr() {
|
||||
u32 begin_line=line;
|
||||
u32 begin_column=column;
|
||||
string str(1,res[ptr]);
|
||||
++column;
|
||||
tok type=get_type(str);
|
||||
|
@ -401,27 +417,31 @@ token lexer::single_opr() {
|
|||
err.err("lexer",line,column,str.length(),"invalid operator `"+str+"`");
|
||||
}
|
||||
++ptr;
|
||||
return {line,column,type,str};
|
||||
return {begin_line,begin_column,line,column,type,str,filename};
|
||||
}
|
||||
|
||||
token lexer::dots() {
|
||||
u32 begin_line=line;
|
||||
u32 begin_column=column;
|
||||
string str=".";
|
||||
if (ptr+2<res.size() && res[ptr+1]=='.' && res[ptr+2]=='.') {
|
||||
str+="..";
|
||||
}
|
||||
ptr+=str.length();
|
||||
column+=str.length();
|
||||
return {line,column,get_type(str),str};
|
||||
return {begin_line,begin_column,line,column,get_type(str),str,filename};
|
||||
}
|
||||
|
||||
token lexer::calc_opr() {
|
||||
u32 begin_line=line;
|
||||
u32 begin_column=column;
|
||||
// get calculation operator
|
||||
string str(1,res[ptr++]);
|
||||
if (ptr<res.size() && res[ptr]=='=') {
|
||||
str+=res[ptr++];
|
||||
}
|
||||
column+=str.length();
|
||||
return {line,column,get_type(str),str};
|
||||
return {begin_line,begin_column,line,column,get_type(str),str,filename};
|
||||
}
|
||||
|
||||
const error& lexer::scan(const string& file) {
|
||||
|
@ -460,7 +480,7 @@ const error& lexer::scan(const string& file) {
|
|||
err_char();
|
||||
}
|
||||
}
|
||||
toks.push_back({line,column,tok::eof,"<eof>"});
|
||||
toks.push_back({line,column,line,column,tok::eof,"<eof>",filename});
|
||||
res="";
|
||||
return err;
|
||||
}
|
||||
|
|
100
nasal_parse.h
100
nasal_parse.h
|
@ -43,8 +43,8 @@
|
|||
*/
|
||||
|
||||
class parse {
|
||||
#define thisline (toks[ptr].line)
|
||||
#define thiscol (toks[ptr].col)
|
||||
#define thisline (toks[ptr].tk_end_line)
|
||||
#define thiscol (toks[ptr].tk_end_column)
|
||||
#define thislen (toks[ptr].str.length())
|
||||
private:
|
||||
u32 ptr;
|
||||
|
@ -155,7 +155,7 @@ private:
|
|||
public:
|
||||
parse(error& e):
|
||||
ptr(0),in_func(0),in_loop(0),
|
||||
toks(nullptr),root(0,0,ast_root),
|
||||
toks(nullptr),root(0,0,ast_root,""),
|
||||
err(e) {}
|
||||
const error& compile(const lexer&);
|
||||
ast& tree() {return root;}
|
||||
|
@ -166,7 +166,7 @@ const error& parse::compile(const lexer& lexer) {
|
|||
toks=lexer.result().data();
|
||||
ptr=in_func=in_loop=0;
|
||||
|
||||
root={0,0,ast_root};
|
||||
root={0,0,ast_root,toks[0].file};
|
||||
while(!lookahead(tok::eof)) {
|
||||
root.add(expr());
|
||||
if (lookahead(tok::semi)) {
|
||||
|
@ -187,8 +187,8 @@ void parse::die(u32 line,u32 col,u32 len,string info,bool prev=false) {
|
|||
}
|
||||
// used to report lack of ',' ';'
|
||||
if (prev && ptr) {
|
||||
line=toks[ptr-1].line;
|
||||
col=toks[ptr-1].col;
|
||||
line=toks[ptr-1].tk_end_line;
|
||||
col=toks[ptr-1].tk_end_column;
|
||||
len=toks[ptr-1].str.length();
|
||||
len+=toks[ptr-1].type==tok::str?2:0;
|
||||
}
|
||||
|
@ -309,29 +309,29 @@ bool parse::need_semi_check(const ast& node) {
|
|||
}
|
||||
|
||||
ast parse::null() {
|
||||
return {toks[ptr].line,toks[ptr].col,ast_null};
|
||||
return {toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_null,toks[ptr].file};
|
||||
}
|
||||
|
||||
ast parse::nil() {
|
||||
return {toks[ptr].line,toks[ptr].col,ast_nil};
|
||||
return {toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_nil,toks[ptr].file};
|
||||
}
|
||||
|
||||
ast parse::num() {
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_num);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_num,toks[ptr].file);
|
||||
node.set_num(str2num(toks[ptr].str.c_str()));
|
||||
match(tok::num);
|
||||
return node;
|
||||
}
|
||||
|
||||
ast parse::str() {
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_str);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_str,toks[ptr].file);
|
||||
node.set_str(toks[ptr].str);
|
||||
match(tok::str);
|
||||
return node;
|
||||
}
|
||||
|
||||
ast parse::id() {
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_id);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_id,toks[ptr].file);
|
||||
node.set_str(toks[ptr].str);
|
||||
match(tok::id);
|
||||
return node;
|
||||
|
@ -347,7 +347,7 @@ ast parse::vec() {
|
|||
tok::func,tok::var,tok::lcurve,
|
||||
tok::lbrace,tok::lbracket,tok::null
|
||||
};
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_vec);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_vec,toks[ptr].file);
|
||||
match(tok::lbracket);
|
||||
while(!lookahead(tok::rbracket)) {
|
||||
node.add(calc());
|
||||
|
@ -364,7 +364,7 @@ ast parse::vec() {
|
|||
}
|
||||
|
||||
ast parse::hash() {
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_hash);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_hash,toks[ptr].file);
|
||||
match(tok::lbrace);
|
||||
while(!lookahead(tok::rbrace)) {
|
||||
node.add(pair());
|
||||
|
@ -381,7 +381,7 @@ ast parse::hash() {
|
|||
}
|
||||
|
||||
ast parse::pair() {
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_pair);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_pair,toks[ptr].file);
|
||||
if (lookahead(tok::id)) {
|
||||
node.add(id());
|
||||
} else if (lookahead(tok::str)) {
|
||||
|
@ -396,7 +396,7 @@ ast parse::pair() {
|
|||
|
||||
ast parse::func() {
|
||||
++in_func;
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_func);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_func,toks[ptr].file);
|
||||
match(tok::func);
|
||||
if (lookahead(tok::lcurve)) {
|
||||
node.add(params());
|
||||
|
@ -409,12 +409,12 @@ ast parse::func() {
|
|||
}
|
||||
|
||||
ast parse::params() {
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_params);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_params,toks[ptr].file);
|
||||
match(tok::lcurve);
|
||||
while(!lookahead(tok::rcurve)) {
|
||||
ast tmp=id();
|
||||
if (lookahead(tok::eq) || lookahead(tok::ellipsis)) {
|
||||
ast special_arg(toks[ptr].line,toks[ptr].col,ast_null);
|
||||
ast special_arg(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_null,toks[ptr].file);
|
||||
if (lookahead(tok::eq)) {
|
||||
match(tok::eq);
|
||||
special_arg=std::move(tmp);
|
||||
|
@ -481,7 +481,7 @@ ast parse::expr()
|
|||
next();
|
||||
break;
|
||||
}
|
||||
return {toks[ptr].line,toks[ptr].col,ast_null};
|
||||
return {toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_null,toks[ptr].file};
|
||||
}
|
||||
|
||||
ast parse::exprs() {
|
||||
|
@ -489,7 +489,7 @@ ast parse::exprs() {
|
|||
die(thisline,thiscol,thislen,"expected expression block");
|
||||
return null();
|
||||
}
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_block);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_block,toks[ptr].file);
|
||||
if (lookahead(tok::lbrace)) {
|
||||
match(tok::lbrace);
|
||||
while(!lookahead(tok::rbrace) && !lookahead(tok::eof)) {
|
||||
|
@ -514,7 +514,7 @@ ast parse::calc() {
|
|||
ast node=or_expr();
|
||||
if (lookahead(tok::quesmark)) {
|
||||
// trinocular calculation
|
||||
ast tmp(toks[ptr].line,toks[ptr].col,ast_trino);
|
||||
ast tmp(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_trino,toks[ptr].file);
|
||||
match(tok::quesmark);
|
||||
tmp.add(std::move(node));
|
||||
tmp.add(calc());
|
||||
|
@ -523,7 +523,7 @@ ast parse::calc() {
|
|||
node=std::move(tmp);
|
||||
} else if (tok::eq<=toks[ptr].type && toks[ptr].type<=tok::lnkeq) {
|
||||
// tok::eq~tok::lnkeq is 37 to 42,ast_equal~ast_lnkeq is 21~26
|
||||
ast tmp(toks[ptr].line,toks[ptr].col,(u32)toks[ptr].type-(u32)tok::eq+ast_equal);
|
||||
ast tmp(toks[ptr].tk_end_line,toks[ptr].tk_end_column,(u32)toks[ptr].type-(u32)tok::eq+ast_equal,toks[ptr].file);
|
||||
tmp.add(std::move(node));
|
||||
match(toks[ptr].type);
|
||||
tmp.add(calc());
|
||||
|
@ -535,7 +535,7 @@ ast parse::calc() {
|
|||
ast parse::or_expr() {
|
||||
ast node=and_expr();
|
||||
while(lookahead(tok::opor)) {
|
||||
ast tmp(toks[ptr].line,toks[ptr].col,ast_or);
|
||||
ast tmp(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_or,toks[ptr].file);
|
||||
tmp.add(std::move(node));
|
||||
match(tok::opor);
|
||||
tmp.add(and_expr());
|
||||
|
@ -547,7 +547,7 @@ ast parse::or_expr() {
|
|||
ast parse::and_expr() {
|
||||
ast node=cmp_expr();
|
||||
while(lookahead(tok::opand)) {
|
||||
ast tmp(toks[ptr].line,toks[ptr].col,ast_and);
|
||||
ast tmp(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_and,toks[ptr].file);
|
||||
tmp.add(std::move(node));
|
||||
match(tok::opand);
|
||||
tmp.add(cmp_expr());
|
||||
|
@ -560,7 +560,7 @@ ast parse::cmp_expr() {
|
|||
ast node=additive_expr();
|
||||
while(tok::cmpeq<=toks[ptr].type && toks[ptr].type<=tok::geq) {
|
||||
// tok::cmpeq~tok::geq is 43~48,ast_cmpeq~ast_geq is 27~32
|
||||
ast tmp(toks[ptr].line,toks[ptr].col,(u32)toks[ptr].type-(u32)tok::cmpeq+ast_cmpeq);
|
||||
ast tmp(toks[ptr].tk_end_line,toks[ptr].tk_end_column,(u32)toks[ptr].type-(u32)tok::cmpeq+ast_cmpeq,toks[ptr].file);
|
||||
tmp.add(std::move(node));
|
||||
match(toks[ptr].type);
|
||||
tmp.add(additive_expr());
|
||||
|
@ -572,7 +572,7 @@ ast parse::cmp_expr() {
|
|||
ast parse::additive_expr() {
|
||||
ast node=multive_expr();
|
||||
while(lookahead(tok::add) || lookahead(tok::sub) || lookahead(tok::link)) {
|
||||
ast tmp(toks[ptr].line,toks[ptr].col,ast_null);
|
||||
ast tmp(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_null,toks[ptr].file);
|
||||
switch(toks[ptr].type) {
|
||||
case tok::add: tmp.set_type(ast_add); break;
|
||||
case tok::sub: tmp.set_type(ast_sub); break;
|
||||
|
@ -590,7 +590,7 @@ ast parse::additive_expr() {
|
|||
ast parse::multive_expr() {
|
||||
ast node=(lookahead(tok::sub) || lookahead(tok::opnot))?unary():scalar();
|
||||
while(lookahead(tok::mult) || lookahead(tok::div)) {
|
||||
ast tmp(toks[ptr].line,toks[ptr].col,(u32)toks[ptr].type-(u32)tok::mult+ast_mult);
|
||||
ast tmp(toks[ptr].tk_end_line,toks[ptr].tk_end_column,(u32)toks[ptr].type-(u32)tok::mult+ast_mult,toks[ptr].file);
|
||||
tmp.add(std::move(node));
|
||||
match(toks[ptr].type);
|
||||
tmp.add((lookahead(tok::sub) || lookahead(tok::opnot))?unary():scalar());
|
||||
|
@ -600,7 +600,7 @@ ast parse::multive_expr() {
|
|||
}
|
||||
|
||||
ast parse::unary() {
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_null);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_null,toks[ptr].file);
|
||||
switch(toks[ptr].type) {
|
||||
case tok::sub: node.set_type(ast_neg);match(tok::sub);break;
|
||||
case tok::opnot: node.set_type(ast_not);match(tok::opnot);break;
|
||||
|
@ -611,7 +611,7 @@ ast parse::unary() {
|
|||
}
|
||||
|
||||
ast parse::scalar() {
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_null);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_null,toks[ptr].file);
|
||||
if (lookahead(tok::tknil)) {
|
||||
node=nil();
|
||||
match(tok::tknil);
|
||||
|
@ -644,7 +644,7 @@ ast parse::scalar() {
|
|||
// check call and avoid ambiguous syntax
|
||||
if (is_call(toks[ptr].type) && !(lookahead(tok::lcurve) && toks[ptr+1].type==tok::var)) {
|
||||
ast tmp=std::move(node);
|
||||
node={toks[ptr].line,toks[ptr].col,ast_call};
|
||||
node={toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_call,toks[ptr].file};
|
||||
node.add(std::move(tmp));
|
||||
while(is_call(toks[ptr].type)) {
|
||||
node.add(call_scalar());
|
||||
|
@ -661,11 +661,11 @@ ast parse::call_scalar() {
|
|||
default: break;
|
||||
}
|
||||
// should never run this expression
|
||||
return {toks[ptr].line,toks[ptr].col,ast_nil};
|
||||
return {toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_nil,toks[ptr].file};
|
||||
}
|
||||
|
||||
ast parse::callh() {
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_callh);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_callh,toks[ptr].file);
|
||||
match(tok::dot);
|
||||
node.set_str(toks[ptr].str);
|
||||
match(tok::id,"expected hashmap key"); // get key
|
||||
|
@ -683,7 +683,7 @@ ast parse::callv() {
|
|||
tok::lbrace,tok::lbracket,tok::colon,
|
||||
tok::null
|
||||
};
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_callv);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_callv,toks[ptr].file);
|
||||
match(tok::lbracket);
|
||||
while(!lookahead(tok::rbracket)) {
|
||||
node.add(subvec());
|
||||
|
@ -712,7 +712,7 @@ ast parse::callf() {
|
|||
tok::func,tok::var,tok::lcurve,
|
||||
tok::lbrace,tok::lbracket,tok::null
|
||||
};
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_callf);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_callf,toks[ptr].file);
|
||||
bool special_call=check_special_call();
|
||||
match(tok::lcurve);
|
||||
while(!lookahead(tok::rcurve)) {
|
||||
|
@ -731,7 +731,7 @@ ast parse::callf() {
|
|||
ast parse::subvec() {
|
||||
ast node=lookahead(tok::colon)?nil():calc();
|
||||
if (lookahead(tok::colon)) {
|
||||
ast tmp(node.line(),node.col(),ast_subvec);
|
||||
ast tmp(node.line(),node.col(),ast_subvec,toks[ptr].file);
|
||||
match(tok::colon);
|
||||
tmp.add(std::move(node));
|
||||
tmp.add((lookahead(tok::comma) || lookahead(tok::rbracket))?nil():calc());
|
||||
|
@ -741,7 +741,7 @@ ast parse::subvec() {
|
|||
}
|
||||
|
||||
ast parse::definition() {
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_def);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_def,toks[ptr].file);
|
||||
if (lookahead(tok::var)) {
|
||||
match(tok::var);
|
||||
switch(toks[ptr].type) {
|
||||
|
@ -777,7 +777,7 @@ ast parse::outcurve_def() {
|
|||
}
|
||||
|
||||
ast parse::multi_id() {
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_multi_id);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_multi_id,toks[ptr].file);
|
||||
while(!lookahead(tok::eof)) {
|
||||
node.add(id());
|
||||
if (is_call(toks[ptr].type)) {
|
||||
|
@ -803,7 +803,7 @@ ast parse::multi_scalar() {
|
|||
tok::func,tok::var,tok::lcurve,
|
||||
tok::lbrace,tok::lbracket,tok::null
|
||||
};
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_tuple);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_tuple,toks[ptr].file);
|
||||
match(tok::lcurve);
|
||||
while(!lookahead(tok::rcurve)) {
|
||||
node.add(calc());
|
||||
|
@ -820,7 +820,7 @@ ast parse::multi_scalar() {
|
|||
}
|
||||
|
||||
ast parse::multi_assgin() {
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_multi_assign);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_multi_assign,toks[ptr].file);
|
||||
node.add(multi_scalar());
|
||||
match(tok::eq);
|
||||
if (lookahead(tok::eof)) {
|
||||
|
@ -837,7 +837,7 @@ ast parse::multi_assgin() {
|
|||
|
||||
ast parse::loop() {
|
||||
++in_loop;
|
||||
ast node(0,0,ast_null);
|
||||
ast node(0,0,ast_null,toks[ptr].file);
|
||||
switch(toks[ptr].type) {
|
||||
case tok::rwhile: node=while_loop(); break;
|
||||
case tok::rfor: node=for_loop(); break;
|
||||
|
@ -850,7 +850,7 @@ ast parse::loop() {
|
|||
}
|
||||
|
||||
ast parse::while_loop() {
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_while);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_while,toks[ptr].file);
|
||||
match(tok::rwhile);
|
||||
match(tok::lcurve);
|
||||
node.add(calc());
|
||||
|
@ -860,7 +860,7 @@ ast parse::while_loop() {
|
|||
}
|
||||
|
||||
ast parse::for_loop() {
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_for);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_for,toks[ptr].file);
|
||||
match(tok::rfor);
|
||||
match(tok::lcurve);
|
||||
// first expression
|
||||
|
@ -902,7 +902,7 @@ ast parse::for_loop() {
|
|||
}
|
||||
|
||||
ast parse::forei_loop() {
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_null);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_null,toks[ptr].file);
|
||||
switch(toks[ptr].type) {
|
||||
case tok::forindex:node.set_type(ast_forindex);match(tok::forindex);break;
|
||||
case tok::foreach: node.set_type(ast_foreach); match(tok::foreach); break;
|
||||
|
@ -926,7 +926,7 @@ ast parse::forei_loop() {
|
|||
}
|
||||
|
||||
ast parse::iter_gen() {
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_null);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_null,toks[ptr].file);
|
||||
if (lookahead(tok::var)) {
|
||||
match(tok::var);
|
||||
node.set_type(ast_iter);
|
||||
|
@ -942,8 +942,8 @@ ast parse::iter_gen() {
|
|||
}
|
||||
|
||||
ast parse::cond() {
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_cond);
|
||||
ast ifnode(toks[ptr].line,toks[ptr].col,ast_if);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_cond,toks[ptr].file);
|
||||
ast ifnode(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_if,toks[ptr].file);
|
||||
match(tok::rif);
|
||||
match(tok::lcurve);
|
||||
ifnode.add(calc());
|
||||
|
@ -951,7 +951,7 @@ ast parse::cond() {
|
|||
ifnode.add(exprs());
|
||||
node.add(std::move(ifnode));
|
||||
while(lookahead(tok::elsif)) {
|
||||
ast elsifnode(toks[ptr].line,toks[ptr].col,ast_elsif);
|
||||
ast elsifnode(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_elsif,toks[ptr].file);
|
||||
match(tok::elsif);
|
||||
match(tok::lcurve);
|
||||
elsifnode.add(calc());
|
||||
|
@ -960,7 +960,7 @@ ast parse::cond() {
|
|||
node.add(std::move(elsifnode));
|
||||
}
|
||||
if (lookahead(tok::relse)) {
|
||||
ast elsenode(toks[ptr].line,toks[ptr].col,ast_else);
|
||||
ast elsenode(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_else,toks[ptr].file);
|
||||
match(tok::relse);
|
||||
elsenode.add(exprs());
|
||||
node.add(std::move(elsenode));
|
||||
|
@ -969,19 +969,19 @@ ast parse::cond() {
|
|||
}
|
||||
|
||||
ast parse::continue_expr() {
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_continue);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_continue,toks[ptr].file);
|
||||
match(tok::cont);
|
||||
return node;
|
||||
}
|
||||
|
||||
ast parse::break_expr() {
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_break);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_break,toks[ptr].file);
|
||||
match(tok::brk);
|
||||
return node;
|
||||
}
|
||||
|
||||
ast parse::ret_expr() {
|
||||
ast node(toks[ptr].line,toks[ptr].col,ast_ret);
|
||||
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_ret,toks[ptr].file);
|
||||
match(tok::ret);
|
||||
tok type=toks[ptr].type;
|
||||
if (type==tok::tknil || type==tok::num || type==tok::str || type==tok::id ||
|
||||
|
|
Loading…
Reference in New Issue