add detail location info in tokens

prepare for multi-line error reporter module
This commit is contained in:
ValKmjolnir 2023-01-10 22:22:27 +08:00
parent 268a03864e
commit 8df02d25ad
8 changed files with 137 additions and 139 deletions

View File

@ -39,10 +39,8 @@ std::ostream& help(std::ostream& out) {
<<" -c, --code | view bytecode.\n" <<" -c, --code | view bytecode.\n"
<<" -e, --exec | execute.\n" <<" -e, --exec | execute.\n"
<<" -t, --time | show execute time.\n" <<" -t, --time | show execute time.\n"
<<" -d, --detail | get detail crash info.\n" <<" -d, --detail | get detail info.\n"
<<" | get detail path-not-found info.\n" <<" -dbg, --debug | debug mode.\n"
<<" | get detail gc info.\n"
<<" -dbg, --debug | debug mode (ignore -t -d).\n"
<<"file:\n" <<"file:\n"
<<" <filename> | execute file.\n" <<" <filename> | execute file.\n"
<<"argv:\n" <<"argv:\n"
@ -57,11 +55,11 @@ std::ostream& logo(std::ostream& out) {
<<" / \\/ / _` / __|/ _` | |\n" <<" / \\/ / _` / __|/ _` | |\n"
<<" / /\\ / (_| \\__ \\ (_| | |\n" <<" / /\\ / (_| \\__ \\ (_| | |\n"
<<" \\_\\ \\/ \\__,_|___/\\__,_|_|\n" <<" \\_\\ \\/ \\__,_|___/\\__,_|_|\n"
<<"version : "<<__nasver<<" ("<<__DATE__<<" "<<__TIME__<<")\n" <<"ver : "<<__nasver<<" ("<<__DATE__<<" "<<__TIME__<<")\n"
<<"c++ std : "<<__cplusplus<<"\n" <<"std : c++ "<<__cplusplus<<"\n"
<<"code repo : https://github.com/ValKmjolnir/Nasal-Interpreter\n" <<"repo : https://github.com/ValKmjolnir/Nasal-Interpreter\n"
<<"code repo : https://gitee.com/valkmjolnir/Nasal-Interpreter\n" <<"repo : https://gitee.com/valkmjolnir/Nasal-Interpreter\n"
<<"lang wiki : https://wiki.flightgear.org/Nasal_scripting_language\n" <<"wiki : https://wiki.flightgear.org/Nasal_scripting_language\n"
<<"input <nasal -h> to get help .\n"; <<"input <nasal -h> to get help .\n";
return out; 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 // lexer scans file to get tokens
lex.scan(file).chkerr(); lex.scan(file).chkerr();
// parser gets lexer's token list to compile // parser gets lexer's token list to compile
parse.compile(lex).chkerr(); parse.compile(lex).chkerr();
// linker gets parser's ast and load import files to this ast // linker gets parser's ast and load import files to this ast
ld.link(parse,file,cmd&VM_DETAIL).chkerr(); ld.link(parse,file,cmd&VM_DETAIL).chkerr();
// optimizer does simple optimization on ast // optimizer does simple optimization on ast
optimize(parse.tree()); optimize(parse.tree());
if (cmd&VM_AST) { 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(); auto start=ch_clk::now();
ctx.run(gen,ld,argv,cmd&VM_DETAIL); ctx.run(gen,ld,argv,cmd&VM_DETAIL);
auto end=ch_clk::now(); 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) { } else if (cmd&VM_EXEC) {
ctx.run(gen,ld,argv,cmd&VM_DETAIL); ctx.run(gen,ld,argv,cmd&VM_DETAIL);
} }

View File

@ -67,7 +67,7 @@ enum ast_node:u32 {
}; };
const char* ast_name[]={ const char* ast_name[]={
"NullNode", "Null",
"AbstractSyntaxTreeRoot", "AbstractSyntaxTreeRoot",
"CodeBlock", "CodeBlock",
"FileIndex", "FileIndex",
@ -114,17 +114,17 @@ const char* ast_name[]={
"ForeachLoop", "ForeachLoop",
"WhileLoop", "WhileLoop",
"Iterator", "Iterator",
"ConditionExpression", "ConditionStatement",
"IfExpression", "IfStatement",
"ElsifExpression", "ElsifStatement",
"ElseExpression", "ElseStatement",
"LeftTuple", "LeftTuple",
"Tuple", "Tuple",
"Definition", "Definition",
"MultipleAssignment", "MultipleAssignment",
"ContinueExpression", "Continue",
"BreakExpression", "Break",
"ReturnExpression" "ReturnStatement"
}; };
class ast { class ast {
@ -133,19 +133,21 @@ private:
u32 nd_col; u32 nd_col;
u32 nd_type; u32 nd_type;
f64 nd_num; f64 nd_num;
string nd_file;
string nd_str; string nd_str;
std::vector<ast> nd_child; std::vector<ast> nd_child;
public: public:
ast(const u32 l,const u32 c,const u32 t) 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_line(l),nd_col(c),nd_type(t),nd_num(0),nd_file(f),nd_str("") {}
ast(const ast&); ast(const ast&) = default;
ast(ast&&); ast(ast&&) = default;
ast& operator=(const ast&) = default;
ast& operator=(ast&&) = default;
void dump() const; void dump() const;
void print(u32,bool,std::vector<string>&) const; void print(u32,bool,std::vector<string>&) const;
void clear(); void clear();
ast& operator=(const ast&);
ast& operator=(ast&&);
ast& operator[](usize n) {return nd_child[n];} ast& operator[](usize n) {return nd_child[n];}
const ast& operator[](usize n) const {return nd_child[n];} const ast& operator[](usize n) const {return nd_child[n];}
usize size() const {return nd_child.size();} usize size() const {return nd_child.size();}
@ -166,43 +168,6 @@ public:
std::vector<ast>& child() {return nd_child;} 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() { void ast::clear() {
nd_line=nd_col=0; nd_line=nd_col=0;
nd_num=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) { } else if (nd_type==ast_num || nd_type==ast_file) {
std::cout<<":"<<nd_num; std::cout<<":"<<nd_num;
} }
std::cout<<" -> "<<nd_line<<":"<<nd_col<<"\n"; std::cout<<" --> "<<nd_file<<":"<<nd_line<<":"<<nd_col<<"\n";
if (last && depth) { if (last && depth) {
indent.back()=" "; indent.back()=" ";
} else if (!last && depth) { } else if (!last && depth) {

View File

@ -441,8 +441,8 @@ var builtin_substr(var* local,gc& ngc) {
} }
usize begin=(usize)beg.num(); usize begin=(usize)beg.num();
usize length=(usize)len.num(); usize length=(usize)len.num();
if (begin>=str.str().length() || begin+length>str.str().length()) { if (begin>=str.str().length()) {
return nas_err("susbtr","index out of range"); return nas_err("susbtr","begin index out of range: "+std::to_string(begin));
} }
return ngc.newstr(str.str().substr(begin,length)); return ngc.newstr(str.str().substr(begin,length));
} }

View File

@ -294,6 +294,7 @@ void debugger::run(
vmexit: vmexit:
callsort(count); callsort(count);
ngc.info();
ngc.clear(); ngc.clear();
imm.clear(); imm.clear();
std::cout<<cyan<<"[debug] "<<reset<<"debugger exited\n"; std::cout<<cyan<<"[debug] "<<reset<<"debugger exited\n";

View File

@ -638,9 +638,13 @@ void gc::extend(u8 type) {
size[index]+=incr[index]; size[index]+=incr[index];
for(u32 i=0;i<incr[index];++i) { for(u32 i=0;i<incr[index];++i) {
nas_val* tmp=new nas_val(type); nas_val* tmp=new nas_val(type);
// failed to allocate new memory
if (!tmp) { if (!tmp) {
std::exit(-1); std::exit(-1);
} }
// add to heap
memory.push_back(tmp); memory.push_back(tmp);
unused[index].push_back(tmp); unused[index].push_back(tmp);
} }
@ -718,6 +722,7 @@ void gc::info() {
if (total) { if (total) {
std::clog<<" avg | "<<sec/total*1000<<" ms\n"; std::clog<<" avg | "<<sec/total*1000<<" ms\n";
} }
std::clog<<"\n";
} }
var gc::alloc(u8 type) { var gc::alloc(u8 type) {
@ -777,6 +782,8 @@ void gc::ctxchg(nas_co& ctx) {
upvalr=ctx.upvalr; upvalr=ctx.upvalr;
canary=ctx.canary; canary=ctx.canary;
stack=ctx.stack; stack=ctx.stack;
// set coroutine pointer
cort=&ctx; cort=&ctx;
// set coroutine state to running // set coroutine state to running
@ -805,6 +812,8 @@ void gc::ctxreserve() {
canary=mctx.canary; canary=mctx.canary;
top=mctx.top; top=mctx.top;
stack=mctx.stack; stack=mctx.stack;
// set coroutine pointer to nullptr
cort=nullptr; cort=nullptr;
} }

View File

@ -167,13 +167,14 @@ ast linker::fimpt(ast& node) {
// avoid infinite loading loop // avoid infinite loading loop
filename=findf(filename); filename=findf(filename);
if (!filename.length() || exist(filename)) { if (!filename.length() || exist(filename)) {
return {0,0,ast_root}; return {0,0,ast_root,filename};
} }
// start importing... // start importing...
lex.scan(filename); lex.scan(filename);
par.compile(lex); par.compile(lex);
ast tmp=std::move(par.tree()); ast tmp=std::move(par.tree());
// check if tmp has 'import' // check if tmp has 'import'
return load(tmp,files.size()-1); return load(tmp,files.size()-1);
} }
@ -183,24 +184,25 @@ ast linker::libimpt() {
parse par(err); parse par(err);
string filename=findf("lib.nas"); string filename=findf("lib.nas");
if (!filename.length()) { if (!filename.length()) {
return {0,0,ast_root}; return {0,0,ast_root,filename};
} }
// avoid infinite loading loop // avoid infinite loading loop
if (exist(filename)) { if (exist(filename)) {
return {0,0,ast_root}; return {0,0,ast_root,filename};
} }
// start importing... // start importing...
lex.scan(filename); lex.scan(filename);
par.compile(lex); par.compile(lex);
ast tmp=std::move(par.tree()); ast tmp=std::move(par.tree());
// check if tmp has 'import' // check if tmp has 'import'
return load(tmp,files.size()-1); return load(tmp,files.size()-1);
} }
ast linker::load(ast& root,u16 fileindex) { ast linker::load(ast& root,u16 fileindex) {
ast tree(0,0,ast_root); ast tree(0,0,ast_root,files[fileindex]);
if (!lib_loaded) { if (!lib_loaded) {
link(tree,libimpt()); link(tree,libimpt());
lib_loaded=true; lib_loaded=true;
@ -213,7 +215,7 @@ ast linker::load(ast& root,u16 fileindex) {
} }
} }
// add root to the back of tree // 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); file_head.set_num(fileindex);
tree.add(std::move(file_head)); tree.add(std::move(file_head));
link(tree,std::move(root)); link(tree,std::move(root));

View File

@ -67,12 +67,15 @@ enum class tok:u32 {
}; };
struct token { struct token {
u32 line; u32 tk_begin_line; // token begin line
u32 col; u32 tk_begin_column;// token begin column
tok type; u32 tk_end_line; // token end line
string str; u32 tk_end_column; // token end column
token(u32 l=0,u32 c=0,tok t=tok::null,const string& s="") tok type; // token type
: line(l),col(c),type(t),str(s) {} string str; // content
string file; // scanned file path
token() = default;
token(const token&) = default;
}; };
class lexer { class lexer {
@ -80,6 +83,7 @@ private:
u32 line; u32 line;
u32 column; u32 column;
usize ptr; usize ptr;
string filename;
string res; string res;
error& err; error& err;
std::vector<token> toks; std::vector<token> toks;
@ -153,7 +157,7 @@ private:
token dots(); token dots();
token calc_opr(); token calc_opr();
public: 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 error& scan(const string&);
const std::vector<token>& result() const {return toks;} const std::vector<token>& result() const {return toks;}
}; };
@ -213,11 +217,15 @@ void lexer::err_char() {
} }
void lexer::open(const string& file) { void lexer::open(const string& file) {
// check file exsits and it is a regular file
struct stat buffer; struct stat buffer;
if (stat(file.c_str(),&buffer)==0 && !S_ISREG(buffer.st_mode)) { if (stat(file.c_str(),&buffer)==0 && !S_ISREG(buffer.st_mode)) {
err.err("lexer","<"+file+"> is not a regular file"); err.err("lexer","<"+file+"> is not a regular file");
err.chkerr(); err.chkerr();
} }
// load
filename=file;
std::ifstream in(file,std::ios::binary); std::ifstream in(file,std::ios::binary);
if (in.fail()) { if (in.fail()) {
err.err("lexer","failed to open <"+file+">"); err.err("lexer","failed to open <"+file+">");
@ -268,6 +276,8 @@ string lexer::utf8_gen() {
} }
token lexer::id_gen() { token lexer::id_gen() {
u32 begin_line=line;
u32 begin_column=column;
string str=""; string str="";
while(ptr<res.size() && (is_id(res[ptr])||is_dec(res[ptr]))) { while(ptr<res.size() && (is_id(res[ptr])||is_dec(res[ptr]))) {
if (res[ptr]<0) { // utf-8 if (res[ptr]<0) { // utf-8
@ -278,10 +288,12 @@ token lexer::id_gen() {
} }
} }
tok type=get_type(str); 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() { token lexer::num_gen() {
u32 begin_line=line;
u32 begin_column=column;
// generate hex number // generate hex number
if (ptr+1<res.size() && res[ptr]=='0' && res[ptr+1]=='x') { if (ptr+1<res.size() && res[ptr]=='0' && res[ptr+1]=='x') {
string str="0x"; string str="0x";
@ -293,7 +305,7 @@ token lexer::num_gen() {
if (str.length()<3) { // "0x" if (str.length()<3) { // "0x"
err.err("lexer",line,column,str.length(),"invalid number `"+str+"`"); 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 } else if (ptr+1<res.size() && res[ptr]=='0' && res[ptr+1]=='o') { // generate oct number
string str="0o"; string str="0o";
ptr+=2; ptr+=2;
@ -309,7 +321,7 @@ token lexer::num_gen() {
if (str.length()==2 || erfmt) { if (str.length()==2 || erfmt) {
err.err("lexer",line,column,str.length(),"invalid number `"+str+"`"); 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 // generate dec number
// dec number -> [0~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*) // 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()=='.') { if (str.back()=='.') {
column+=str.length(); column+=str.length();
err.err("lexer",line,column,str.length(),"invalid number `"+str+"`"); 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')) { 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()=='+') { if (str.back()=='e' || str.back()=='E' || str.back()=='-' || str.back()=='+') {
column+=str.length(); column+=str.length();
err.err("lexer",line,column,str.length(),"invalid number `"+str+"`"); 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(); column+=str.length();
return {line,column,tok::num,str}; return {begin_line,begin_column,line,column,tok::num,str,filename};
} }
token lexer::str_gen() { token lexer::str_gen() {
u32 begin_line=line;
u32 begin_column=column;
string str=""; string str="";
const char begin=res[ptr]; const char begin=res[ptr];
++column; ++column;
@ -384,16 +398,18 @@ token lexer::str_gen() {
// check if this string ends with a " or ' // check if this string ends with a " or '
if (ptr++>=res.size()) { if (ptr++>=res.size()) {
err.err("lexer",line,column,1,"get EOF when generating string"); 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; ++column;
if (begin=='`' && str.length()!=1) { if (begin=='`' && str.length()!=1) {
err.err("lexer",line,column,1,"\'`\' is used for string that includes one character"); 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() { token lexer::single_opr() {
u32 begin_line=line;
u32 begin_column=column;
string str(1,res[ptr]); string str(1,res[ptr]);
++column; ++column;
tok type=get_type(str); tok type=get_type(str);
@ -401,27 +417,31 @@ token lexer::single_opr() {
err.err("lexer",line,column,str.length(),"invalid operator `"+str+"`"); err.err("lexer",line,column,str.length(),"invalid operator `"+str+"`");
} }
++ptr; ++ptr;
return {line,column,type,str}; return {begin_line,begin_column,line,column,type,str,filename};
} }
token lexer::dots() { token lexer::dots() {
u32 begin_line=line;
u32 begin_column=column;
string str="."; string str=".";
if (ptr+2<res.size() && res[ptr+1]=='.' && res[ptr+2]=='.') { if (ptr+2<res.size() && res[ptr+1]=='.' && res[ptr+2]=='.') {
str+=".."; str+="..";
} }
ptr+=str.length(); ptr+=str.length();
column+=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() { token lexer::calc_opr() {
u32 begin_line=line;
u32 begin_column=column;
// get calculation operator // get calculation operator
string str(1,res[ptr++]); string str(1,res[ptr++]);
if (ptr<res.size() && res[ptr]=='=') { if (ptr<res.size() && res[ptr]=='=') {
str+=res[ptr++]; str+=res[ptr++];
} }
column+=str.length(); 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) { const error& lexer::scan(const string& file) {
@ -460,7 +480,7 @@ const error& lexer::scan(const string& file) {
err_char(); err_char();
} }
} }
toks.push_back({line,column,tok::eof,"<eof>"}); toks.push_back({line,column,line,column,tok::eof,"<eof>",filename});
res=""; res="";
return err; return err;
} }

View File

@ -43,8 +43,8 @@
*/ */
class parse { class parse {
#define thisline (toks[ptr].line) #define thisline (toks[ptr].tk_end_line)
#define thiscol (toks[ptr].col) #define thiscol (toks[ptr].tk_end_column)
#define thislen (toks[ptr].str.length()) #define thislen (toks[ptr].str.length())
private: private:
u32 ptr; u32 ptr;
@ -155,7 +155,7 @@ private:
public: public:
parse(error& e): parse(error& e):
ptr(0),in_func(0),in_loop(0), ptr(0),in_func(0),in_loop(0),
toks(nullptr),root(0,0,ast_root), toks(nullptr),root(0,0,ast_root,""),
err(e) {} err(e) {}
const error& compile(const lexer&); const error& compile(const lexer&);
ast& tree() {return root;} ast& tree() {return root;}
@ -166,7 +166,7 @@ const error& parse::compile(const lexer& lexer) {
toks=lexer.result().data(); toks=lexer.result().data();
ptr=in_func=in_loop=0; ptr=in_func=in_loop=0;
root={0,0,ast_root}; root={0,0,ast_root,toks[0].file};
while(!lookahead(tok::eof)) { while(!lookahead(tok::eof)) {
root.add(expr()); root.add(expr());
if (lookahead(tok::semi)) { 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 ',' ';' // used to report lack of ',' ';'
if (prev && ptr) { if (prev && ptr) {
line=toks[ptr-1].line; line=toks[ptr-1].tk_end_line;
col=toks[ptr-1].col; col=toks[ptr-1].tk_end_column;
len=toks[ptr-1].str.length(); len=toks[ptr-1].str.length();
len+=toks[ptr-1].type==tok::str?2:0; len+=toks[ptr-1].type==tok::str?2:0;
} }
@ -309,29 +309,29 @@ bool parse::need_semi_check(const ast& node) {
} }
ast parse::null() { 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() { 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 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())); node.set_num(str2num(toks[ptr].str.c_str()));
match(tok::num); match(tok::num);
return node; return node;
} }
ast parse::str() { 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); node.set_str(toks[ptr].str);
match(tok::str); match(tok::str);
return node; return node;
} }
ast parse::id() { 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); node.set_str(toks[ptr].str);
match(tok::id); match(tok::id);
return node; return node;
@ -347,7 +347,7 @@ ast parse::vec() {
tok::func,tok::var,tok::lcurve, tok::func,tok::var,tok::lcurve,
tok::lbrace,tok::lbracket,tok::null 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); match(tok::lbracket);
while(!lookahead(tok::rbracket)) { while(!lookahead(tok::rbracket)) {
node.add(calc()); node.add(calc());
@ -364,7 +364,7 @@ ast parse::vec() {
} }
ast parse::hash() { 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); match(tok::lbrace);
while(!lookahead(tok::rbrace)) { while(!lookahead(tok::rbrace)) {
node.add(pair()); node.add(pair());
@ -381,7 +381,7 @@ ast parse::hash() {
} }
ast parse::pair() { 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)) { if (lookahead(tok::id)) {
node.add(id()); node.add(id());
} else if (lookahead(tok::str)) { } else if (lookahead(tok::str)) {
@ -396,7 +396,7 @@ ast parse::pair() {
ast parse::func() { ast parse::func() {
++in_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); match(tok::func);
if (lookahead(tok::lcurve)) { if (lookahead(tok::lcurve)) {
node.add(params()); node.add(params());
@ -409,12 +409,12 @@ ast parse::func() {
} }
ast parse::params() { 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); match(tok::lcurve);
while(!lookahead(tok::rcurve)) { while(!lookahead(tok::rcurve)) {
ast tmp=id(); ast tmp=id();
if (lookahead(tok::eq) || lookahead(tok::ellipsis)) { 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)) { if (lookahead(tok::eq)) {
match(tok::eq); match(tok::eq);
special_arg=std::move(tmp); special_arg=std::move(tmp);
@ -481,7 +481,7 @@ ast parse::expr()
next(); next();
break; 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() { ast parse::exprs() {
@ -489,7 +489,7 @@ ast parse::exprs() {
die(thisline,thiscol,thislen,"expected expression block"); die(thisline,thiscol,thislen,"expected expression block");
return null(); 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)) { if (lookahead(tok::lbrace)) {
match(tok::lbrace); match(tok::lbrace);
while(!lookahead(tok::rbrace) && !lookahead(tok::eof)) { while(!lookahead(tok::rbrace) && !lookahead(tok::eof)) {
@ -514,7 +514,7 @@ ast parse::calc() {
ast node=or_expr(); ast node=or_expr();
if (lookahead(tok::quesmark)) { if (lookahead(tok::quesmark)) {
// trinocular calculation // 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); match(tok::quesmark);
tmp.add(std::move(node)); tmp.add(std::move(node));
tmp.add(calc()); tmp.add(calc());
@ -523,7 +523,7 @@ ast parse::calc() {
node=std::move(tmp); node=std::move(tmp);
} else if (tok::eq<=toks[ptr].type && toks[ptr].type<=tok::lnkeq) { } 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 // 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)); tmp.add(std::move(node));
match(toks[ptr].type); match(toks[ptr].type);
tmp.add(calc()); tmp.add(calc());
@ -535,7 +535,7 @@ ast parse::calc() {
ast parse::or_expr() { ast parse::or_expr() {
ast node=and_expr(); ast node=and_expr();
while(lookahead(tok::opor)) { 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)); tmp.add(std::move(node));
match(tok::opor); match(tok::opor);
tmp.add(and_expr()); tmp.add(and_expr());
@ -547,7 +547,7 @@ ast parse::or_expr() {
ast parse::and_expr() { ast parse::and_expr() {
ast node=cmp_expr(); ast node=cmp_expr();
while(lookahead(tok::opand)) { 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)); tmp.add(std::move(node));
match(tok::opand); match(tok::opand);
tmp.add(cmp_expr()); tmp.add(cmp_expr());
@ -560,7 +560,7 @@ ast parse::cmp_expr() {
ast node=additive_expr(); ast node=additive_expr();
while(tok::cmpeq<=toks[ptr].type && toks[ptr].type<=tok::geq) { 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 // 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)); tmp.add(std::move(node));
match(toks[ptr].type); match(toks[ptr].type);
tmp.add(additive_expr()); tmp.add(additive_expr());
@ -572,7 +572,7 @@ ast parse::cmp_expr() {
ast parse::additive_expr() { ast parse::additive_expr() {
ast node=multive_expr(); ast node=multive_expr();
while(lookahead(tok::add) || lookahead(tok::sub) || lookahead(tok::link)) { 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) { switch(toks[ptr].type) {
case tok::add: tmp.set_type(ast_add); break; case tok::add: tmp.set_type(ast_add); break;
case tok::sub: tmp.set_type(ast_sub); break; case tok::sub: tmp.set_type(ast_sub); break;
@ -590,7 +590,7 @@ ast parse::additive_expr() {
ast parse::multive_expr() { ast parse::multive_expr() {
ast node=(lookahead(tok::sub) || lookahead(tok::opnot))?unary():scalar(); ast node=(lookahead(tok::sub) || lookahead(tok::opnot))?unary():scalar();
while(lookahead(tok::mult) || lookahead(tok::div)) { 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)); tmp.add(std::move(node));
match(toks[ptr].type); match(toks[ptr].type);
tmp.add((lookahead(tok::sub) || lookahead(tok::opnot))?unary():scalar()); tmp.add((lookahead(tok::sub) || lookahead(tok::opnot))?unary():scalar());
@ -600,7 +600,7 @@ ast parse::multive_expr() {
} }
ast parse::unary() { 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) { switch(toks[ptr].type) {
case tok::sub: node.set_type(ast_neg);match(tok::sub);break; case tok::sub: node.set_type(ast_neg);match(tok::sub);break;
case tok::opnot: node.set_type(ast_not);match(tok::opnot);break; case tok::opnot: node.set_type(ast_not);match(tok::opnot);break;
@ -611,7 +611,7 @@ ast parse::unary() {
} }
ast parse::scalar() { 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)) { if (lookahead(tok::tknil)) {
node=nil(); node=nil();
match(tok::tknil); match(tok::tknil);
@ -644,7 +644,7 @@ ast parse::scalar() {
// check call and avoid ambiguous syntax // check call and avoid ambiguous syntax
if (is_call(toks[ptr].type) && !(lookahead(tok::lcurve) && toks[ptr+1].type==tok::var)) { if (is_call(toks[ptr].type) && !(lookahead(tok::lcurve) && toks[ptr+1].type==tok::var)) {
ast tmp=std::move(node); 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)); node.add(std::move(tmp));
while(is_call(toks[ptr].type)) { while(is_call(toks[ptr].type)) {
node.add(call_scalar()); node.add(call_scalar());
@ -661,11 +661,11 @@ ast parse::call_scalar() {
default: break; default: break;
} }
// should never run this expression // 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 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); match(tok::dot);
node.set_str(toks[ptr].str); node.set_str(toks[ptr].str);
match(tok::id,"expected hashmap key"); // get key match(tok::id,"expected hashmap key"); // get key
@ -683,7 +683,7 @@ ast parse::callv() {
tok::lbrace,tok::lbracket,tok::colon, tok::lbrace,tok::lbracket,tok::colon,
tok::null 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); match(tok::lbracket);
while(!lookahead(tok::rbracket)) { while(!lookahead(tok::rbracket)) {
node.add(subvec()); node.add(subvec());
@ -712,7 +712,7 @@ ast parse::callf() {
tok::func,tok::var,tok::lcurve, tok::func,tok::var,tok::lcurve,
tok::lbrace,tok::lbracket,tok::null 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(); bool special_call=check_special_call();
match(tok::lcurve); match(tok::lcurve);
while(!lookahead(tok::rcurve)) { while(!lookahead(tok::rcurve)) {
@ -731,7 +731,7 @@ ast parse::callf() {
ast parse::subvec() { ast parse::subvec() {
ast node=lookahead(tok::colon)?nil():calc(); ast node=lookahead(tok::colon)?nil():calc();
if (lookahead(tok::colon)) { 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); match(tok::colon);
tmp.add(std::move(node)); tmp.add(std::move(node));
tmp.add((lookahead(tok::comma) || lookahead(tok::rbracket))?nil():calc()); tmp.add((lookahead(tok::comma) || lookahead(tok::rbracket))?nil():calc());
@ -741,7 +741,7 @@ ast parse::subvec() {
} }
ast parse::definition() { 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)) { if (lookahead(tok::var)) {
match(tok::var); match(tok::var);
switch(toks[ptr].type) { switch(toks[ptr].type) {
@ -777,7 +777,7 @@ ast parse::outcurve_def() {
} }
ast parse::multi_id() { 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)) { while(!lookahead(tok::eof)) {
node.add(id()); node.add(id());
if (is_call(toks[ptr].type)) { if (is_call(toks[ptr].type)) {
@ -803,7 +803,7 @@ ast parse::multi_scalar() {
tok::func,tok::var,tok::lcurve, tok::func,tok::var,tok::lcurve,
tok::lbrace,tok::lbracket,tok::null 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); match(tok::lcurve);
while(!lookahead(tok::rcurve)) { while(!lookahead(tok::rcurve)) {
node.add(calc()); node.add(calc());
@ -820,7 +820,7 @@ ast parse::multi_scalar() {
} }
ast parse::multi_assgin() { 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()); node.add(multi_scalar());
match(tok::eq); match(tok::eq);
if (lookahead(tok::eof)) { if (lookahead(tok::eof)) {
@ -837,7 +837,7 @@ ast parse::multi_assgin() {
ast parse::loop() { ast parse::loop() {
++in_loop; ++in_loop;
ast node(0,0,ast_null); ast node(0,0,ast_null,toks[ptr].file);
switch(toks[ptr].type) { switch(toks[ptr].type) {
case tok::rwhile: node=while_loop(); break; case tok::rwhile: node=while_loop(); break;
case tok::rfor: node=for_loop(); break; case tok::rfor: node=for_loop(); break;
@ -850,7 +850,7 @@ ast parse::loop() {
} }
ast parse::while_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::rwhile);
match(tok::lcurve); match(tok::lcurve);
node.add(calc()); node.add(calc());
@ -860,7 +860,7 @@ ast parse::while_loop() {
} }
ast parse::for_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::rfor);
match(tok::lcurve); match(tok::lcurve);
// first expression // first expression
@ -902,7 +902,7 @@ ast parse::for_loop() {
} }
ast parse::forei_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) { switch(toks[ptr].type) {
case tok::forindex:node.set_type(ast_forindex);match(tok::forindex);break; case tok::forindex:node.set_type(ast_forindex);match(tok::forindex);break;
case tok::foreach: node.set_type(ast_foreach); match(tok::foreach); 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 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)) { if (lookahead(tok::var)) {
match(tok::var); match(tok::var);
node.set_type(ast_iter); node.set_type(ast_iter);
@ -942,8 +942,8 @@ ast parse::iter_gen() {
} }
ast parse::cond() { ast parse::cond() {
ast node(toks[ptr].line,toks[ptr].col,ast_cond); ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_cond,toks[ptr].file);
ast ifnode(toks[ptr].line,toks[ptr].col,ast_if); ast ifnode(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_if,toks[ptr].file);
match(tok::rif); match(tok::rif);
match(tok::lcurve); match(tok::lcurve);
ifnode.add(calc()); ifnode.add(calc());
@ -951,7 +951,7 @@ ast parse::cond() {
ifnode.add(exprs()); ifnode.add(exprs());
node.add(std::move(ifnode)); node.add(std::move(ifnode));
while(lookahead(tok::elsif)) { 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::elsif);
match(tok::lcurve); match(tok::lcurve);
elsifnode.add(calc()); elsifnode.add(calc());
@ -960,7 +960,7 @@ ast parse::cond() {
node.add(std::move(elsifnode)); node.add(std::move(elsifnode));
} }
if (lookahead(tok::relse)) { 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); match(tok::relse);
elsenode.add(exprs()); elsenode.add(exprs());
node.add(std::move(elsenode)); node.add(std::move(elsenode));
@ -969,19 +969,19 @@ ast parse::cond() {
} }
ast parse::continue_expr() { 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); match(tok::cont);
return node; return node;
} }
ast parse::break_expr() { 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); match(tok::brk);
return node; return node;
} }
ast parse::ret_expr() { 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); match(tok::ret);
tok type=toks[ptr].type; tok type=toks[ptr].type;
if (type==tok::tknil || type==tok::num || type==tok::str || type==tok::id || if (type==tok::tknil || type==tok::num || type==tok::str || type==tok::id ||