✨ update error report for parser&codegen
This commit is contained in:
parent
1678567c5d
commit
dbc2c365b4
42
nasal_ast.h
42
nasal_ast.h
|
@ -185,6 +185,8 @@ public:
|
|||
const span& location() const {return loc;}
|
||||
const std::vector<ast>& child() const {return nd_child;}
|
||||
std::vector<ast>& child() {return nd_child;}
|
||||
void update_span();
|
||||
void update_span(const span&);
|
||||
};
|
||||
|
||||
void ast::set_begin(const u32 l,const u32 c) {
|
||||
|
@ -198,7 +200,7 @@ void ast::set_end(const u32 l,const u32 c) {
|
|||
}
|
||||
|
||||
void ast::clear() {
|
||||
loc={0,0,0,0};
|
||||
loc={0,0,0,0,""};
|
||||
nd_num=0;
|
||||
nd_str.clear();
|
||||
nd_type=ast_null;
|
||||
|
@ -250,3 +252,41 @@ void ast::print(u32 depth,bool last,std::vector<string>& indent) const{
|
|||
indent.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void ast::update_span() {
|
||||
if (!nd_child.size()) {
|
||||
return;
|
||||
}
|
||||
for(const auto& i:nd_child) {
|
||||
if (loc.begin_line>i.loc.begin_line) {
|
||||
loc.begin_line=i.loc.begin_line;
|
||||
loc.begin_column=i.loc.begin_column;
|
||||
} else if (loc.begin_line==i.loc.begin_line && loc.begin_column>i.loc.begin_column) {
|
||||
loc.begin_column=i.loc.begin_column;
|
||||
}
|
||||
if (loc.end_line<i.loc.end_line) {
|
||||
loc.end_line=i.loc.end_line;
|
||||
loc.end_column=i.loc.end_column;
|
||||
} else if (loc.end_line==i.loc.end_line && loc.end_column<i.loc.end_column) {
|
||||
loc.end_column=i.loc.end_column;
|
||||
}
|
||||
loc.file=i.loc.file;
|
||||
}
|
||||
}
|
||||
|
||||
void ast::update_span(const span& tloc) {
|
||||
update_span();
|
||||
if (loc.begin_line>tloc.begin_line) {
|
||||
loc.begin_line=tloc.begin_line;
|
||||
loc.begin_column=tloc.begin_column;
|
||||
} else if (loc.begin_line==tloc.begin_line && loc.begin_column>tloc.begin_column) {
|
||||
loc.begin_column=tloc.begin_column;
|
||||
}
|
||||
if (loc.end_line<tloc.end_line) {
|
||||
loc.end_line=tloc.end_line;
|
||||
loc.end_column=tloc.end_column;
|
||||
} else if (loc.end_line==tloc.end_line && loc.end_column<tloc.end_column) {
|
||||
loc.end_column=tloc.end_column;
|
||||
}
|
||||
loc.file=tloc.file;
|
||||
}
|
|
@ -223,7 +223,10 @@ private:
|
|||
|
||||
bool check_memory_reachable(const ast&);
|
||||
|
||||
void die(const string&,const u32,const u32,const u32);
|
||||
void die(const string& info,const span& loc) {
|
||||
err.err("code",loc,info);
|
||||
}
|
||||
|
||||
void regist_num(const f64);
|
||||
void regist_str(const string&);
|
||||
void find_symbol(const ast&);
|
||||
|
@ -279,25 +282,20 @@ bool codegen::check_memory_reachable(const ast& node) {
|
|||
if (node.type()==ast_call) {
|
||||
const ast& tmp=node.child().back();
|
||||
if (tmp.type()==ast_callf) {
|
||||
die("bad left-value",tmp.line(),tmp.col(),1);
|
||||
die("bad left-value with function call",node.location());
|
||||
return false;
|
||||
}
|
||||
if (tmp.type()==ast_callv && (tmp.size()==0 || tmp.size()>1 || tmp[0].type()==ast_subvec)) {
|
||||
die("bad left-value",tmp.line(),tmp.col(),1);
|
||||
die("bad left-value with subvec",node.location());
|
||||
return false;
|
||||
}
|
||||
} else if (node.type()!=ast_id) {
|
||||
die("bad left-value",node.line(),node.col(),1);
|
||||
die("bad left-value",node.location());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void codegen::die(const string& info,const u32 line,const u32 col,const u32 len=1) {
|
||||
err.load(file[fileindex]);
|
||||
err.err("code",{line,col-len,line,col,file[fileindex]},info);
|
||||
}
|
||||
|
||||
void codegen::regist_num(const f64 num) {
|
||||
if (!num_table.count(num)) {
|
||||
u32 size=num_table.size();
|
||||
|
@ -431,15 +429,15 @@ void codegen::func_gen(const ast& node) {
|
|||
}
|
||||
// check default parameter and dynamic parameter
|
||||
if (checked_default && tmp.type()!=ast_default) {
|
||||
die("must use default parameters here",tmp.line(),tmp.col(),tmp.str().length());
|
||||
die("must use default parameters here",tmp.location());
|
||||
}
|
||||
if (checked_dynamic && &tmp!=&node[0].child().back()) {
|
||||
die("dynamic parameter must be the last one",tmp.line(),tmp.col(),tmp.str().length());
|
||||
die("dynamic parameter must be the last one",tmp.location());
|
||||
}
|
||||
// check redefinition
|
||||
string name=tmp.str();
|
||||
if (argname.count(name)) {
|
||||
die("redefinition of parameter: "+name,tmp.line(),tmp.col(),name.length());
|
||||
die("redefinition of parameter: "+name,tmp.location());
|
||||
} else {
|
||||
argname[name]=true;
|
||||
}
|
||||
|
@ -461,7 +459,7 @@ void codegen::func_gen(const ast& node) {
|
|||
for(auto& tmp:node[0].child()) {
|
||||
const string& str=tmp.str();
|
||||
if (str=="me") {
|
||||
die("\"me\" should not be a parameter",tmp.line(),tmp.col(),tmp.str().length());
|
||||
die("\"me\" should not be a parameter",tmp.location());
|
||||
}
|
||||
regist_str(str);
|
||||
switch(tmp.type()) {
|
||||
|
@ -488,7 +486,7 @@ void codegen::func_gen(const ast& node) {
|
|||
in_iterloop.pop();
|
||||
code[lsize].num=local.back().size();
|
||||
if (local.back().size()>=STACK_DEPTH) {
|
||||
die("too many local variants: "+std::to_string(local.back().size()),block.line(),0);
|
||||
die("too many local variants: "+std::to_string(local.back().size()),block.location());
|
||||
}
|
||||
local.pop_back();
|
||||
|
||||
|
@ -520,7 +518,7 @@ void codegen::call_id(const ast& node) {
|
|||
if (builtin[i].name==str) {
|
||||
gen(op_callb,i,node.line());
|
||||
if (local.empty()) {
|
||||
die("should warp native function in local scope",node.line(),node.col(),node.str().length());
|
||||
die("should warp native function in local scope",node.location());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -538,7 +536,7 @@ void codegen::call_id(const ast& node) {
|
|||
gen(op_callg,index,node.line());
|
||||
return;
|
||||
}
|
||||
die("undefined symbol \""+str+"\"",node.line(),node.col(),node.str().length());
|
||||
die("undefined symbol \""+str+"\"",node.location());
|
||||
}
|
||||
|
||||
void codegen::call_hash(const ast& node) {
|
||||
|
@ -622,7 +620,7 @@ void codegen::mcall_id(const ast& node) {
|
|||
const string& str=node.str();
|
||||
for(u32 i=0;builtin[i].name;++i) {
|
||||
if (builtin[i].name==str) {
|
||||
die("cannot modify native function",node.line(),node.col(),node.str().length());
|
||||
die("cannot modify native function",node.location());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -639,7 +637,7 @@ void codegen::mcall_id(const ast& node) {
|
|||
gen(op_mcallg,index,node.line());
|
||||
return;
|
||||
}
|
||||
die("undefined symbol \""+str+"\"",node.line(),node.col(),node.str().length());
|
||||
die("undefined symbol \""+str+"\"",node.location());
|
||||
}
|
||||
|
||||
void codegen::mcall_vec(const ast& node) {
|
||||
|
@ -665,6 +663,11 @@ void codegen::multi_def(const ast& node) {
|
|||
if (node[1].type()==ast_tuple) { // (var a,b,c)=(c,b,a);
|
||||
auto& vals=node[1].child();
|
||||
for(usize i=0;i<size;++i) {
|
||||
// check node type, only identifier is allowed
|
||||
if (ids[i].type()!=ast_id) {
|
||||
die("cannot call identifier in multi-definition",ids[i].location());
|
||||
continue;
|
||||
}
|
||||
calc_gen(vals[i]);
|
||||
const string& str=ids[i].str();
|
||||
local.empty()?
|
||||
|
@ -674,6 +677,11 @@ void codegen::multi_def(const ast& node) {
|
|||
} else { // (var a,b,c)=[0,1,2];
|
||||
calc_gen(node[1]);
|
||||
for(usize i=0;i<size;++i) {
|
||||
// check node type, only identifier is allowed
|
||||
if (ids[i].type()!=ast_id) {
|
||||
die("cannot call identifier in multi-definition",ids[i].location());
|
||||
continue;
|
||||
}
|
||||
gen(op_callvi,i,node[1].line());
|
||||
const string& str=ids[i].str();
|
||||
local.empty()?
|
||||
|
@ -686,20 +694,20 @@ void codegen::multi_def(const ast& node) {
|
|||
|
||||
void codegen::def_gen(const ast& node) {
|
||||
if (node[0].type()==ast_id && node[1].type()==ast_tuple) {
|
||||
die("cannot accept too many values",node[1].line(),node[1].col(),1);
|
||||
die("cannot accept too many values",node[1].location());
|
||||
} else if (node[0].type()==ast_multi_id && node[1].type()==ast_tuple && node[0].size()<node[1].size()) {
|
||||
die("lack values in multi-definition",node[1].line(),node[1].col(),1);
|
||||
die("lack values in multi-definition",node[1].location());
|
||||
} else if (node[0].type()==ast_multi_id && node[1].type()==ast_tuple && node[0].size()>node[1].size()) {
|
||||
die("too many values in multi-definition",node[1].line(),node[1].col(),1);
|
||||
die("too many values in multi-definition",node[1].location());
|
||||
}
|
||||
node[0].type()==ast_id?single_def(node):multi_def(node);
|
||||
}
|
||||
|
||||
void codegen::multi_assign_gen(const ast& node) {
|
||||
if (node[1].type()==ast_tuple && node[0].size()<node[1].size()) {
|
||||
die("lack values in multi-assignment",node[1].line(),node[1].col(),1);
|
||||
die("lack values in multi-assignment",node[1].location());
|
||||
} else if (node[1].type()==ast_tuple && node[0].size()>node[1].size()) {
|
||||
die("too many values in multi-assignment",node[1].line(),node[1].col(),1);
|
||||
die("too many values in multi-assignment",node[1].location());
|
||||
}
|
||||
i32 size=node[0].size();
|
||||
if (node[1].type()==ast_tuple) {
|
||||
|
|
27
nasal_err.h
27
nasal_err.h
|
@ -100,11 +100,11 @@ private:
|
|||
return string(len,' ');
|
||||
}
|
||||
string leftpad(u32 num,usize len) {
|
||||
string res=std::to_string(num);
|
||||
while(res.length()<len) {
|
||||
res=" "+res;
|
||||
string tmp=std::to_string(num);
|
||||
while(tmp.length()<len) {
|
||||
tmp=" "+tmp;
|
||||
}
|
||||
return res;
|
||||
return tmp;
|
||||
}
|
||||
public:
|
||||
error():cnt(0) {}
|
||||
|
@ -175,7 +175,7 @@ void error::err(const string& stage,const span& loc,const string& info) {
|
|||
const string iden=identation(maxlen);
|
||||
|
||||
for(u32 line=loc.begin_line;line<=loc.end_line;++line) {
|
||||
if (!line || !res[line-1].length()) {
|
||||
if (!line) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -186,30 +186,35 @@ void error::err(const string& stage,const span& loc,const string& info) {
|
|||
continue;
|
||||
}
|
||||
|
||||
// if this line has nothing, skip
|
||||
if (!res[line-1].length() && line!=loc.end_line) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const string& code=res[line-1];
|
||||
std::cerr<<cyan<<leftpad(line,maxlen)<<" | "<<reset<<code<<"\n";
|
||||
// output underline
|
||||
std::cerr<<cyan<<iden<<" | "<<reset;
|
||||
if (loc.begin_line==loc.end_line) {
|
||||
for(i32 i=0;i<loc.begin_column;++i) {
|
||||
for(u32 i=0;i<loc.begin_column;++i) {
|
||||
std::cerr<<char(" \t"[code[i]=='\t']);
|
||||
}
|
||||
for(i32 i=loc.begin_column;i<loc.end_column;++i) {
|
||||
for(u32 i=loc.begin_column;i<loc.end_column;++i) {
|
||||
std::cerr<<red<<(code[i]=='\t'?"^^^^":"^")<<reset;
|
||||
}
|
||||
} else if (line==loc.begin_line) {
|
||||
for(i32 i=0;i<loc.begin_column;++i) {
|
||||
for(u32 i=0;i<loc.begin_column;++i) {
|
||||
std::cerr<<char(" \t"[code[i]=='\t']);
|
||||
}
|
||||
for(i32 i=loc.begin_column;i<code.size();++i) {
|
||||
for(u32 i=loc.begin_column;i<code.size();++i) {
|
||||
std::cerr<<red<<(code[i]=='\t'?"^^^^":"^")<<reset;
|
||||
}
|
||||
} else if (loc.begin_line<line && line<loc.end_line) {
|
||||
for(i32 i=0;i<code.size();++i) {
|
||||
for(u32 i=0;i<code.size();++i) {
|
||||
std::cerr<<red<<(code[i]=='\t'?"^^^^":"^");
|
||||
}
|
||||
} else {
|
||||
for(i32 i=0;i<loc.end_column;++i) {
|
||||
for(u32 i=0;i<loc.end_column;++i) {
|
||||
std::cerr<<red<<(code[i]=='\t'?"^^^^":"^");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -176,7 +176,7 @@ const error& parse::compile(const lexer& lexer) {
|
|||
toks=lexer.result().data();
|
||||
ptr=in_func=in_loop=0;
|
||||
|
||||
root={{0,0,0,0,toks[0].loc.file},ast_root};
|
||||
root={toks[0].loc,ast_root};
|
||||
while(!lookahead(tok::eof)) {
|
||||
root.add(expr());
|
||||
if (lookahead(tok::semi)) {
|
||||
|
@ -186,6 +186,7 @@ const error& parse::compile(const lexer& lexer) {
|
|||
die(prevspan,"expected \";\"");
|
||||
}
|
||||
}
|
||||
root.update_span();
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -368,6 +369,7 @@ ast parse::vec() {
|
|||
break;
|
||||
}
|
||||
}
|
||||
node.update_span(thisspan);
|
||||
match(tok::rbracket,"expected ']' when generating vector");
|
||||
return node;
|
||||
}
|
||||
|
@ -385,6 +387,7 @@ ast parse::hash() {
|
|||
break;
|
||||
}
|
||||
}
|
||||
node.update_span(thisspan);
|
||||
match(tok::rbrace,"expected '}' when generating hash");
|
||||
return node;
|
||||
}
|
||||
|
@ -400,6 +403,7 @@ ast parse::pair() {
|
|||
}
|
||||
match(tok::colon);
|
||||
node.add(calc());
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -414,6 +418,7 @@ ast parse::func() {
|
|||
}
|
||||
node.add(exprs());
|
||||
--in_func;
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -446,6 +451,7 @@ ast parse::params() {
|
|||
break;
|
||||
}
|
||||
}
|
||||
node.update_span(thisspan);
|
||||
match(tok::rcurve,"expected ')' after parameter list");
|
||||
return node;
|
||||
}
|
||||
|
@ -493,6 +499,8 @@ ast parse::expr() {
|
|||
next();
|
||||
break;
|
||||
}
|
||||
|
||||
// unreachable
|
||||
return {toks[ptr].loc,ast_null};
|
||||
}
|
||||
|
||||
|
@ -519,6 +527,7 @@ ast parse::exprs() {
|
|||
if (lookahead(tok::semi))
|
||||
match(tok::semi);
|
||||
}
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -547,6 +556,7 @@ ast parse::calc() {
|
|||
tmp.add(calc());
|
||||
node=std::move(tmp);
|
||||
}
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -557,8 +567,10 @@ ast parse::bitwise_or() {
|
|||
tmp.add(std::move(node));
|
||||
match(tok::btor);
|
||||
tmp.add(bitwise_xor());
|
||||
tmp.update_span();
|
||||
node=std::move(tmp);
|
||||
}
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -569,8 +581,10 @@ ast parse::bitwise_xor() {
|
|||
tmp.add(std::move(node));
|
||||
match(tok::btxor);
|
||||
tmp.add(bitwise_and());
|
||||
tmp.update_span();
|
||||
node=std::move(tmp);
|
||||
}
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -581,8 +595,10 @@ ast parse::bitwise_and() {
|
|||
tmp.add(std::move(node));
|
||||
match(tok::btand);
|
||||
tmp.add(or_expr());
|
||||
tmp.update_span();
|
||||
node=std::move(tmp);
|
||||
}
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -593,8 +609,10 @@ ast parse::or_expr() {
|
|||
tmp.add(std::move(node));
|
||||
match(tok::opor);
|
||||
tmp.add(and_expr());
|
||||
tmp.update_span();
|
||||
node=std::move(tmp);
|
||||
}
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -605,8 +623,10 @@ ast parse::and_expr() {
|
|||
tmp.add(std::move(node));
|
||||
match(tok::opand);
|
||||
tmp.add(cmp_expr());
|
||||
tmp.update_span();
|
||||
node=std::move(tmp);
|
||||
}
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -618,8 +638,10 @@ ast parse::cmp_expr() {
|
|||
tmp.add(std::move(node));
|
||||
match(toks[ptr].type);
|
||||
tmp.add(additive_expr());
|
||||
tmp.update_span();
|
||||
node=std::move(tmp);
|
||||
}
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -636,8 +658,10 @@ ast parse::additive_expr() {
|
|||
tmp.add(std::move(node));
|
||||
match(toks[ptr].type);
|
||||
tmp.add(multive_expr());
|
||||
tmp.update_span();
|
||||
node=std::move(tmp);
|
||||
}
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -648,8 +672,10 @@ ast parse::multive_expr() {
|
|||
tmp.add(std::move(node));
|
||||
match(toks[ptr].type);
|
||||
tmp.add((lookahead(tok::sub) || lookahead(tok::opnot) || lookahead(tok::floater))?unary():scalar());
|
||||
tmp.update_span();
|
||||
node=std::move(tmp);
|
||||
}
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -662,6 +688,7 @@ ast parse::unary() {
|
|||
default: break;
|
||||
}
|
||||
node.add((lookahead(tok::sub) || lookahead(tok::opnot) || lookahead(tok::floater))?unary():scalar());
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -685,8 +712,11 @@ ast parse::scalar() {
|
|||
} else if (lookahead(tok::lbrace)) {
|
||||
node=hash();
|
||||
} else if (lookahead(tok::lcurve)) {
|
||||
const auto& loc=toks[ptr].loc;
|
||||
match(tok::lcurve);
|
||||
node=calc();
|
||||
node.set_begin(loc.begin_line,loc.begin_column);
|
||||
node.update_span(thisspan);
|
||||
match(tok::rcurve);
|
||||
} else if (lookahead(tok::var)) {
|
||||
match(tok::var);
|
||||
|
@ -707,6 +737,7 @@ ast parse::scalar() {
|
|||
node.add(call_scalar());
|
||||
}
|
||||
}
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -717,7 +748,7 @@ ast parse::call_scalar() {
|
|||
case tok::dot: return callh(); break;
|
||||
default: break;
|
||||
}
|
||||
// should never run this expression
|
||||
// unreachable
|
||||
return {toks[ptr].loc,ast_nil};
|
||||
}
|
||||
|
||||
|
@ -725,6 +756,7 @@ ast parse::callh() {
|
|||
ast node(toks[ptr].loc,ast_callh);
|
||||
match(tok::dot);
|
||||
node.set_str(toks[ptr].str);
|
||||
node.set_end(toks[ptr].loc.end_line,toks[ptr].loc.end_column);
|
||||
match(tok::id,"expected hashmap key"); // get key
|
||||
return node;
|
||||
}
|
||||
|
@ -752,8 +784,9 @@ ast parse::callv() {
|
|||
}
|
||||
}
|
||||
if (node.size()==0) {
|
||||
die(node.location(),"expected index value");
|
||||
die(thisspan,"expected index value");
|
||||
}
|
||||
node.update_span(thisspan);
|
||||
match(tok::rbracket,"expected ']' when calling vector");
|
||||
return node;
|
||||
}
|
||||
|
@ -780,6 +813,7 @@ ast parse::callf() {
|
|||
else if (!lookahead(tok::rcurve) && !check_comma(panic))
|
||||
break;
|
||||
}
|
||||
node.update_span(thisspan);
|
||||
match(tok::rcurve,"expected ')' when calling function");
|
||||
return node;
|
||||
}
|
||||
|
@ -793,6 +827,7 @@ ast parse::subvec() {
|
|||
tmp.add((lookahead(tok::comma) || lookahead(tok::rbracket))?nil():calc());
|
||||
node=std::move(tmp);
|
||||
}
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -814,32 +849,37 @@ ast parse::definition() {
|
|||
} else {
|
||||
node.add(calc());
|
||||
}
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
ast parse::incurve_def() {
|
||||
const auto& loc=toks[ptr].loc;
|
||||
match(tok::lcurve);
|
||||
match(tok::var);
|
||||
ast node=multi_id();
|
||||
node.update_span(thisspan);
|
||||
match(tok::rcurve);
|
||||
node.set_begin(loc.begin_line,loc.begin_column);
|
||||
return node;
|
||||
}
|
||||
|
||||
ast parse::outcurve_def() {
|
||||
const auto& loc=toks[ptr].loc;
|
||||
match(tok::lcurve);
|
||||
ast node=multi_id();
|
||||
node.update_span(thisspan);
|
||||
match(tok::rcurve);
|
||||
node.set_begin(loc.begin_line,loc.begin_column);
|
||||
return node;
|
||||
}
|
||||
|
||||
ast parse::multi_id() {
|
||||
ast node(toks[ptr].loc,ast_multi_id);
|
||||
while(!lookahead(tok::eof)) {
|
||||
node.add(id());
|
||||
if (is_call(toks[ptr].type)) {
|
||||
ast tmp=call_scalar();// recognize calls but this is still a syntax error
|
||||
die(tmp.location(),"cannot call identifier in multi-definition");
|
||||
}
|
||||
// only identifier is allowed here
|
||||
// but we check it at codegen stage
|
||||
node.add(calc());
|
||||
if (lookahead(tok::comma)) {
|
||||
match(tok::comma);
|
||||
} else if (lookahead(tok::id)) { // first set of identifier
|
||||
|
@ -848,6 +888,7 @@ ast parse::multi_id() {
|
|||
break;
|
||||
}
|
||||
}
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -871,6 +912,7 @@ ast parse::multi_scalar() {
|
|||
break;
|
||||
}
|
||||
}
|
||||
node.update_span(thisspan);
|
||||
match(tok::rcurve,"expected ')' after multi-scalar");
|
||||
return node;
|
||||
}
|
||||
|
@ -888,6 +930,7 @@ ast parse::multi_assgin() {
|
|||
} else {
|
||||
node.add(calc());
|
||||
}
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -912,6 +955,7 @@ ast parse::while_loop() {
|
|||
node.add(calc());
|
||||
match(tok::rcurve);
|
||||
node.add(exprs());
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -954,6 +998,7 @@ ast parse::for_loop() {
|
|||
}
|
||||
match(tok::rcurve);
|
||||
node.add(exprs());
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -978,6 +1023,7 @@ ast parse::forei_loop() {
|
|||
node.add(calc());
|
||||
match(tok::rcurve);
|
||||
node.add(exprs());
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -994,18 +1040,24 @@ ast parse::iter_gen() {
|
|||
node.add(call_scalar());
|
||||
}
|
||||
}
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
ast parse::cond() {
|
||||
ast node(toks[ptr].loc,ast_cond);
|
||||
|
||||
// generate if
|
||||
ast ifnode(toks[ptr].loc,ast_if);
|
||||
match(tok::rif);
|
||||
match(tok::lcurve);
|
||||
ifnode.add(calc());
|
||||
match(tok::rcurve);
|
||||
ifnode.add(exprs());
|
||||
ifnode.update_span();
|
||||
node.add(std::move(ifnode));
|
||||
|
||||
// generate elsif
|
||||
while(lookahead(tok::elsif)) {
|
||||
ast elsifnode(toks[ptr].loc,ast_elsif);
|
||||
match(tok::elsif);
|
||||
|
@ -1013,14 +1065,19 @@ ast parse::cond() {
|
|||
elsifnode.add(calc());
|
||||
match(tok::rcurve);
|
||||
elsifnode.add(exprs());
|
||||
elsifnode.update_span();
|
||||
node.add(std::move(elsifnode));
|
||||
}
|
||||
|
||||
// generate else
|
||||
if (lookahead(tok::relse)) {
|
||||
ast elsenode(toks[ptr].loc,ast_else);
|
||||
match(tok::relse);
|
||||
elsenode.add(exprs());
|
||||
elsenode.update_span();
|
||||
node.add(std::move(elsenode));
|
||||
}
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -1046,5 +1103,6 @@ ast parse::ret_expr() {
|
|||
) {
|
||||
node.add(calc());
|
||||
}
|
||||
node.update_span();
|
||||
return node;
|
||||
}
|
||||
|
|
|
@ -194,9 +194,9 @@ var bp_example=func() {
|
|||
# last 2 column is useless, only used to make sure bp runs correctly
|
||||
var expect=[
|
||||
{width:3,height:1,mat:[0,0,0]},
|
||||
{width:3,height:1,mat:[1,0,0]},
|
||||
{width:3,height:1,mat:[1,0,0]},
|
||||
{width:3,height:1,mat:[0,0,0]}
|
||||
{width:3,height:1,mat:[1,0,1]},
|
||||
{width:3,height:1,mat:[1,1,0]},
|
||||
{width:3,height:1,mat:[0,1,1]}
|
||||
];
|
||||
var hidden={
|
||||
weight:mat(4,2),
|
||||
|
|
Loading…
Reference in New Issue