lexer,parser,import,codegen use the same error module.

This commit is contained in:
ValKmjolnir 2021-12-23 21:15:50 +08:00
parent 30650bb64f
commit f0ae63bce5
11 changed files with 160 additions and 136 deletions

View File

@ -51,12 +51,6 @@ void logo()
<<"input <nasal -h> to get help .\n"; <<"input <nasal -h> to get help .\n";
} }
void die(const char* stage,const std::string& filename)
{
std::cout<<"["<<stage<<"] in <"<<filename<<">: error(s) occurred,stop.\n";
std::exit(1);
}
void err() void err()
{ {
std::cout std::cout
@ -67,43 +61,37 @@ void err()
void execute(const std::string& file,const uint32_t cmd) void execute(const std::string& file,const uint32_t cmd)
{ {
nasal_lexer lexer; // front end use the same error module
nasal_parse parse; nasal_err nerr;
nasal_import linker; nasal_lexer lexer(nerr);
nasal_codegen gen; nasal_parse parse(nerr);
nasal_import linker(nerr);
nasal_codegen gen(nerr);
// back end
nasal_vm vm; nasal_vm vm;
// lexer scans file to get tokens // lexer scans file to get tokens
lexer.scan(file); lexer.scan(file);
if(lexer.err())
die("lexer",file);
if(cmd&VM_LEXINFO) if(cmd&VM_LEXINFO)
lexer.print(); lexer.print();
// parser gets lexer's token list to compile // parser gets lexer's token list to compile
parse.compile(lexer); parse.compile(lexer);
if(parse.err())
die("parse",file);
// linker gets parser's ast and load import files to this ast // linker gets parser's ast and load import files to this ast
linker.link(parse,file); linker.link(parse,file);
if(linker.err())
die("import",file);
if(cmd&VM_ASTINFO) if(cmd&VM_ASTINFO)
parse.print(); parse.print();
// code generator gets parser's ast and linker's import file list to generate code // code generator gets parser's ast and linker's import file list to generate code
gen.compile(parse,linker); gen.compile(parse,linker);
if(gen.err())
die("code",file);
if(cmd&VM_CODEINFO) if(cmd&VM_CODEINFO)
gen.print(); gen.print();
// run bytecode // run bytecode
if(cmd&VM_DEBUG) if(cmd&VM_DEBUG)
{ {
nasal_dbg dbg; nasal_dbg debugger;
dbg.run(gen,linker); debugger.run(gen,linker);
} }
else if(cmd&VM_EXECTIME) else if(cmd&VM_EXECTIME)
{ {
@ -119,7 +107,7 @@ int main(int argc,const char* argv[])
{ {
if(argc==1) if(argc==1)
{ {
help(); logo();
return 0; return 0;
} }
if(argc==2) if(argc==2)

View File

@ -1,5 +1,5 @@
.PHONY=test .PHONY=test
nasal:main.cpp nasal_ast.h nasal_builtin.h nasal_codegen.h nasal_gc.h nasal_import.h nasal_lexer.h nasal_parse.h nasal_vm.h nasal_dbg.h nasal.h nasal:main.cpp nasal_ast.h nasal_err.h nasal_builtin.h nasal_codegen.h nasal_gc.h nasal_import.h nasal_lexer.h nasal_parse.h nasal_vm.h nasal_dbg.h nasal.h
clang++ -std=c++11 -O3 main.cpp -o nasal -fno-exceptions -ldl -Wshadow -Wall clang++ -std=c++11 -O3 main.cpp -o nasal -fno-exceptions -ldl -Wshadow -Wall
test:nasal test:nasal
./nasal test/ascii-art.nas ./nasal test/ascii-art.nas
@ -11,18 +11,18 @@ test:nasal
./nasal test/calc.nas ./nasal test/calc.nas
./nasal test/choice.nas ./nasal test/choice.nas
./nasal test/class.nas ./nasal test/class.nas
# ./nasal test/exception.nas ./nasal -c test/exception.nas
./nasal -t test/fib.nas ./nasal -t test/fib.nas
./nasal test/filesystem.nas ./nasal test/filesystem.nas
./nasal test/hexdump.nas ./nasal test/hexdump.nas
./nasal test/json.nas ./nasal test/json.nas
./nasal test/leetcode1319.nas ./nasal test/leetcode1319.nas
./nasal test/lexer.nas ./nasal test/lexer.nas
./nasal -c test/life.nas ./nasal test/life.nas
./nasal -t test/loop.nas ./nasal -t test/loop.nas
./nasal -c test/mandel.nas ./nasal -c test/mandel.nas
./nasal -t test/mandelbrot.nas ./nasal -t test/mandelbrot.nas
# ./nasal -t test/module_test.nas ./nasal -c test/module_test.nas
./nasal test/nasal_test.nas ./nasal test/nasal_test.nas
./nasal -t test/pi.nas ./nasal -t test/pi.nas
./nasal -t test/prime.nas ./nasal -t test/prime.nas

View File

@ -127,6 +127,7 @@ std::string rawstr(const std::string& str)
} }
return ret; return ret;
} }
#include "nasal_err.h"
#include "nasal_lexer.h" #include "nasal_lexer.h"
#include "nasal_ast.h" #include "nasal_ast.h"
#include "nasal_parse.h" #include "nasal_parse.h"

View File

@ -193,6 +193,7 @@ class nasal_codegen
private: private:
uint32_t error; uint32_t error;
uint16_t fileindex; uint16_t fileindex;
nasal_err& nerr;
const std::string* file; const std::string* file;
std::stack<uint32_t> in_iterloop; std::stack<uint32_t> in_iterloop;
std::unordered_map<double,int> num_table; std::unordered_map<double,int> num_table;
@ -205,7 +206,7 @@ private:
std::vector<std::string> global; // global : max 4095 values std::vector<std::string> global; // global : max 4095 values
std::list<std::vector<std::string>> local; // local : max 32768 upvalues 65536 values std::list<std::vector<std::string>> local; // local : max 32768 upvalues 65536 values
void die(const std::string,const int); void die(const std::string&,const uint32_t);
void regist_number(const double); void regist_number(const double);
void regist_string(const std::string&); void regist_string(const std::string&);
void find_symbol(const nasal_ast&); void find_symbol(const nasal_ast&);
@ -246,6 +247,7 @@ private:
void block_gen(const nasal_ast&); void block_gen(const nasal_ast&);
void ret_gen(const nasal_ast&); void ret_gen(const nasal_ast&);
public: public:
nasal_codegen(nasal_err& e):nerr(e){}
uint32_t err(){return error;} uint32_t err(){return error;}
void compile(const nasal_parse&,const nasal_import&); void compile(const nasal_parse&,const nasal_import&);
void print_op(uint32_t); void print_op(uint32_t);
@ -255,10 +257,10 @@ public:
const std::vector<opcode>& get_code() const {return code;} const std::vector<opcode>& get_code() const {return code;}
}; };
void nasal_codegen::die(const std::string info,const int line) void nasal_codegen::die(const std::string& info,const uint32_t line)
{ {
++error; nerr.load(file[fileindex]);
std::cout<<"[code] <"<<file[fileindex]<<":"<<line<<"> "<<info<<"\n"; nerr.err("code",line,info.c_str());
} }
void nasal_codegen::regist_number(const double num) void nasal_codegen::regist_number(const double num)
@ -1217,6 +1219,7 @@ void nasal_codegen::compile(const nasal_parse& parse,const nasal_import& import)
gen(op_exit,0,0); gen(op_exit,0,0);
if(global.size()>=STACK_MAX_DEPTH) if(global.size()>=STACK_MAX_DEPTH)
die("too many global variants: "+std::to_string(global.size())+".",0); die("too many global variants: "+std::to_string(global.size())+".",0);
nerr.chkerr();
} }
void nasal_codegen::print_op(uint32_t index) void nasal_codegen::print_op(uint32_t index)

View File

@ -7,22 +7,19 @@ class nasal_dbg:public nasal_vm
{ {
private: private:
bool next_step; bool next_step;
uint16_t last_fidx;
uint16_t bk_fidx; uint16_t bk_fidx;
uint32_t bk_line; uint32_t bk_line;
std::vector<std::string> src; file_line src;
std::vector<std::string> parse(std::string&); std::vector<std::string> parse(const std::string&);
uint16_t get_fileindex(std::string&); uint16_t get_fileindex(const std::string&);
void err(); void err();
void help(); void help();
void load_src(const std::string&);
void stepinfo(); void stepinfo();
void interact(); void interact();
public: public:
nasal_dbg(): nasal_dbg():
next_step(false), next_step(false),
last_fidx(0),
bk_fidx(0),bk_line(0){} bk_fidx(0),bk_line(0){}
void run( void run(
const nasal_codegen&, const nasal_codegen&,
@ -30,7 +27,7 @@ public:
); );
}; };
std::vector<std::string> nasal_dbg::parse(std::string& cmd) std::vector<std::string> nasal_dbg::parse(const std::string& cmd)
{ {
std::vector<std::string> res; std::vector<std::string> res;
std::string tmp=""; std::string tmp="";
@ -49,7 +46,7 @@ std::vector<std::string> nasal_dbg::parse(std::string& cmd)
return res; return res;
} }
uint16_t nasal_dbg::get_fileindex(std::string& filename) uint16_t nasal_dbg::get_fileindex(const std::string& filename)
{ {
for(uint16_t i=0;i<files_size;++i) for(uint16_t i=0;i<files_size;++i)
if(filename==files[i]) if(filename==files[i])
@ -81,30 +78,11 @@ void nasal_dbg::help()
<<"\tbk, break | set break point\n"; <<"\tbk, break | set break point\n";
} }
void nasal_dbg::load_src(const std::string& filename)
{
src.clear();
std::ifstream fin(filename,std::ios::binary);
if(fin.fail())
{
std::cout<<"[debug] cannot open source code file <"<<filename<<">\n";
std::exit(-1);
}
std::string tmp;
while(!fin.eof())
{
std::getline(fin,tmp);
src.push_back(tmp);
}
}
void nasal_dbg::stepinfo() void nasal_dbg::stepinfo()
{ {
uint32_t begin,end; uint32_t begin,end;
uint32_t line=bytecode[pc].line==0?0:bytecode[pc].line-1; uint32_t line=bytecode[pc].line==0?0:bytecode[pc].line-1;
if(bytecode[pc].fidx!=last_fidx) src.load(files[bytecode[pc].fidx]);
load_src(files[bytecode[pc].fidx]);
last_fidx=bytecode[pc].fidx;
printf("source code:\n"); printf("source code:\n");
begin=(line>>3)==0?0:((line>>3)<<3); begin=(line>>3)==0?0:((line>>3)<<3);
end=(1+(line>>3))<<3; end=(1+(line>>3))<<3;
@ -203,7 +181,6 @@ void nasal_dbg::run(
{ {
detail_info=true; detail_info=true;
init(gen.get_strs(),gen.get_nums(),linker.get_file()); init(gen.get_strs(),gen.get_nums(),linker.get_file());
load_src(files[0]);
const void* opr_table[]= const void* opr_table[]=
{ {
&&nop, &&intg, &&intl, &&loadg, &&nop, &&intg, &&intl, &&loadg,

70
nasal_err.h Normal file
View File

@ -0,0 +1,70 @@
#ifndef __NASAL_ERR_H__
#define __NASAL_ERR_H__
#include <iostream>
#include <fstream>
#include <cstring>
class file_line
{
protected:
std::string file;
std::vector<std::string> res;
public:
void load(const std::string& f)
{
if(file==f)
return;
file=f;
res.clear();
std::ifstream fin(f,std::ios::binary);
if(fin.fail())
{
std::cout<<"[src] cannot open file <"<<f<<">\n";
std::exit(1);
}
std::string line;
while(!fin.eof())
{
std::getline(fin,line);
res.push_back(line);
}
}
void clear()
{
std::vector<std::string> tmp;
res.swap(tmp);
}
const std::string& operator[](const uint32_t line){return res[line];}
const std::string& name(){return file;}
size_t size(){return res.size();}
};
class nasal_err:public file_line
{
private:
uint32_t error;
public:
void err(const char* stage,const std::string& info)
{
++error;
std::cout<<"["<<stage<<"] "<<info<<'\n';
}
void err(const char* stage,uint32_t line,uint32_t column,const std::string& info)
{
++error;
std::cout<<"["<<stage<<"] "<<file<<":"<<line<<":"<<column<<" "<<info<<"\n"<<res[line-1]<<'\n';
for(int i=0;i<(int)column-1;++i)
std::cout<<char(" \t"[res[line-1][i]=='\t']);
std::cout<<"^\n";
}
void err(const char* stage,uint32_t line,const std::string& info)
{
++error;
std::cout<<"["<<stage<<"] "<<file<<":"<<line<<" "<<info<<"\n"<<res[line-1]<<'\n';
}
void chkerr(){if(error)std::exit(1);}
};
#endif

View File

@ -4,26 +4,19 @@
class nasal_import class nasal_import
{ {
private: private:
uint32_t error; nasal_err& nerr;
std::vector<std::string> files; std::vector<std::string> files;
void die(const std::string&,const char*);
bool check_import(const nasal_ast&); bool check_import(const nasal_ast&);
bool check_exist(const std::string&); bool check_exist(const std::string&);
void linker(nasal_ast&,nasal_ast&&); void linker(nasal_ast&,nasal_ast&&);
nasal_ast file_import(nasal_ast&); nasal_ast file_import(nasal_ast&);
nasal_ast load(nasal_ast&,uint16_t); nasal_ast load(nasal_ast&,uint16_t);
public: public:
uint32_t err(){return error;} nasal_import(nasal_err& e):nerr(e){}
void link(nasal_parse&,const std::string&); void link(nasal_parse&,const std::string&);
const std::vector<std::string>& get_file() const {return files;} const std::vector<std::string>& get_file() const {return files;}
}; };
void nasal_import::die(const std::string& file,const char* stage)
{
++error;
std::cout<<"[import] in <\""<<file<<"\">: error(s) occurred in "<<stage<<".\n";
}
bool nasal_import::check_import(const nasal_ast& node) bool nasal_import::check_import(const nasal_ast& node)
{ {
/* /*
@ -65,8 +58,8 @@ void nasal_import::linker(nasal_ast& root,nasal_ast&& add_root)
nasal_ast nasal_import::file_import(nasal_ast& node) nasal_ast nasal_import::file_import(nasal_ast& node)
{ {
nasal_lexer lex; nasal_lexer lex(nerr);
nasal_parse par; nasal_parse par(nerr);
// get filename and set node to ast_null // get filename and set node to ast_null
std::string filename=node[1][0].str(); std::string filename=node[1][0].str();
node.clear(); node.clear();
@ -77,17 +70,7 @@ nasal_ast nasal_import::file_import(nasal_ast& node)
// start importing... // start importing...
lex.scan(filename); lex.scan(filename);
if(lex.err())
{
die(filename,"lexer");
return {0,ast_root};
}
par.compile(lex); par.compile(lex);
if(par.err())
{
die(filename,"parser");
return {0,ast_root};
}
nasal_ast tmp=std::move(par.ast()); nasal_ast tmp=std::move(par.ast());
// check if tmp has 'import' // check if tmp has 'import'
return load(tmp,files.size()-1); return load(tmp,files.size()-1);
@ -110,7 +93,6 @@ nasal_ast nasal_import::load(nasal_ast& root,uint16_t fileindex)
void nasal_import::link(nasal_parse& parse,const std::string& self) void nasal_import::link(nasal_parse& parse,const std::string& self)
{ {
// initializing // initializing
error=0;
files={self}; files={self};
// scan root and import files,then generate a new ast and return to import_ast // scan root and import files,then generate a new ast and return to import_ast
// the main file's index is 0 // the main file's index is 0

View File

@ -90,30 +90,36 @@ struct
struct token struct token
{ {
uint32_t line; uint32_t line;
uint32_t column;
uint32_t type; uint32_t type;
std::string str; std::string str;
token(uint32_t l=0,uint32_t t=tok_null,std::string s=""){line=l;type=t;str=s;} token(uint32_t l=0,uint32_t c=0,uint32_t t=tok_null,std::string s="")
{
line=l;
column=c;
type=t;
str=s;
}
}; };
class nasal_lexer class nasal_lexer
{ {
private: private:
uint32_t error;
uint32_t line; uint32_t line;
uint32_t column;
uint32_t ptr; uint32_t ptr;
std::string filename; nasal_err& nerr;
std::string code;
std::string res; std::string res;
std::vector<token> tokens; std::vector<token> tokens;
uint32_t get_type(const std::string&); uint32_t get_type(const std::string&);
void die(const char*); void die(const char* info){nerr.err("lexer",line,column,info);};
void open(const std::string&); void open(const std::string&);
std::string id_gen(); std::string id_gen();
std::string num_gen(); std::string num_gen();
std::string str_gen(); std::string str_gen();
public: public:
uint32_t err(){return error;} nasal_lexer(nasal_err& e):nerr(e){}
void scan(const std::string&); void scan(const std::string&);
void print(); void print();
const std::vector<token>& get_tokens() const {return tokens;} const std::vector<token>& get_tokens() const {return tokens;}
@ -121,13 +127,11 @@ public:
void nasal_lexer::open(const std::string& file) void nasal_lexer::open(const std::string& file)
{ {
filename=file;
std::ifstream fin(file,std::ios::binary); std::ifstream fin(file,std::ios::binary);
if(fin.fail()) if(fin.fail())
{ nerr.err("lexer","cannot open file <"+file+">.");
++error; else
std::cout<<"[lexer] cannot open file <"<<file<<">.\n"; nerr.load(file);
}
std::stringstream ss; std::stringstream ss;
ss<<fin.rdbuf(); ss<<fin.rdbuf();
res=ss.str(); res=ss.str();
@ -141,21 +145,12 @@ uint32_t nasal_lexer::get_type(const std::string& tk_str)
return tok_null; return tok_null;
} }
void nasal_lexer::die(const char* info)
{
++error;
std::cout<<"[lexer] "<<filename<<":"<<line<<":"<<code.length()<<"\n"<<code<<'\n';
for(int i=0;i<(int)code.size()-1;++i)
std::cout<<char(" \t"[code[i]=='\t']);
std::cout<<'^'<<info<<'\n';
}
std::string nasal_lexer::id_gen() std::string nasal_lexer::id_gen()
{ {
std::string str=""; std::string str="";
while(ptr<res.size() && (ID(res[ptr])||DIGIT(res[ptr]))) while(ptr<res.size() && (ID(res[ptr])||DIGIT(res[ptr])))
str+=res[ptr++]; str+=res[ptr++];
code+=str; column+=str.length();
return str; return str;
} }
@ -168,7 +163,7 @@ std::string nasal_lexer::num_gen()
ptr+=2; ptr+=2;
while(ptr<res.size() && HEX(res[ptr])) while(ptr<res.size() && HEX(res[ptr]))
str+=res[ptr++]; str+=res[ptr++];
code+=str; column+=str.length();
if(str.length()<3)// "0x" if(str.length()<3)// "0x"
die("invalid number."); die("invalid number.");
return str; return str;
@ -180,7 +175,7 @@ std::string nasal_lexer::num_gen()
ptr+=2; ptr+=2;
while(ptr<res.size() && OCT(res[ptr])) while(ptr<res.size() && OCT(res[ptr]))
str+=res[ptr++]; str+=res[ptr++];
code+=str; column+=str.length();
if(str.length()<3)// "0o" if(str.length()<3)// "0o"
die("invalid number."); die("invalid number.");
return str; return str;
@ -198,7 +193,7 @@ std::string nasal_lexer::num_gen()
// "xxxx." is not a correct number // "xxxx." is not a correct number
if(str.back()=='.') if(str.back()=='.')
{ {
code+=str; column+=str.length();
die("invalid number."); die("invalid number.");
return "0"; return "0";
} }
@ -213,12 +208,12 @@ std::string nasal_lexer::num_gen()
// "xxxe(-|+)" is not a correct number // "xxxe(-|+)" is not a correct number
if(str.back()=='e' || str.back()=='E' || str.back()=='-' || str.back()=='+') if(str.back()=='e' || str.back()=='E' || str.back()=='-' || str.back()=='+')
{ {
code+=str; column+=str.length();
die("invalid number."); die("invalid number.");
return "0"; return "0";
} }
} }
code+=str; column+=str.length();
return str; return str;
} }
@ -226,18 +221,19 @@ std::string nasal_lexer::str_gen()
{ {
std::string str=""; std::string str="";
char begin=res[ptr]; char begin=res[ptr];
code+=begin; ++column;
while(++ptr<res.size() && res[ptr]!=begin) while(++ptr<res.size() && res[ptr]!=begin)
{ {
code+=res[ptr]; ++column;
if(res[ptr]=='\n') if(res[ptr]=='\n')
{ {
code=""; column=0;
++line; ++line;
} }
if(res[ptr]=='\\' && ptr+1<res.size()) if(res[ptr]=='\\' && ptr+1<res.size())
{ {
code+=res[++ptr]; ++column;
++ptr;
switch(res[ptr]) switch(res[ptr])
{ {
case '0': str+='\0'; break; case '0': str+='\0'; break;
@ -264,7 +260,7 @@ std::string nasal_lexer::str_gen()
die("get EOF when generating string."); die("get EOF when generating string.");
return str; return str;
} }
code+=res[ptr-1]; ++column;
if(begin=='`' && str.length()!=1) if(begin=='`' && str.length()!=1)
die("\'`\' is used for string that includes one character."); die("\'`\' is used for string that includes one character.");
return str; return str;
@ -273,7 +269,8 @@ std::string nasal_lexer::str_gen()
void nasal_lexer::scan(const std::string& file) void nasal_lexer::scan(const std::string& file)
{ {
line=1; line=1;
error=ptr=0; column=0;
ptr=0;
open(file); open(file);
std::string str; std::string str;
@ -282,11 +279,11 @@ void nasal_lexer::scan(const std::string& file)
while(ptr<res.size() && (res[ptr]==' ' || res[ptr]=='\n' || res[ptr]=='\t' || res[ptr]=='\r' || res[ptr]<0)) while(ptr<res.size() && (res[ptr]==' ' || res[ptr]=='\n' || res[ptr]=='\t' || res[ptr]=='\r' || res[ptr]<0))
{ {
// these characters will be ignored, and '\n' will cause ++line // these characters will be ignored, and '\n' will cause ++line
code+=res[ptr]; ++column;
if(res[ptr++]=='\n') if(res[ptr++]=='\n')
{ {
++line; ++line;
code=""; column=0;
} }
} }
if(ptr>=res.size()) break; if(ptr>=res.size()) break;
@ -294,20 +291,20 @@ void nasal_lexer::scan(const std::string& file)
{ {
str=id_gen(); str=id_gen();
uint32_t type=get_type(str); uint32_t type=get_type(str);
tokens.push_back({line,type?type:tok_id,str}); tokens.push_back({line,column,type?type:tok_id,str});
} }
else if(DIGIT(res[ptr])) else if(DIGIT(res[ptr]))
tokens.push_back({line,tok_num,num_gen()}); tokens.push_back({line,column,tok_num,num_gen()});
else if(STR(res[ptr])) else if(STR(res[ptr]))
tokens.push_back({line,tok_str,str_gen()}); tokens.push_back({line,column,tok_str,str_gen()});
else if(SINGLE_OPERATOR(res[ptr])) else if(SINGLE_OPERATOR(res[ptr]))
{ {
str=res[ptr]; str=res[ptr];
code+=res[ptr]; ++column;
uint32_t type=get_type(str); uint32_t type=get_type(str);
if(!type) if(!type)
die("invalid operator."); die("invalid operator.");
tokens.push_back({line,type,str}); tokens.push_back({line,column,type,str});
++ptr; ++ptr;
} }
else if(res[ptr]=='.') else if(res[ptr]=='.')
@ -316,8 +313,8 @@ void nasal_lexer::scan(const std::string& file)
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();
code+=str; column+=str.length();
tokens.push_back({line,get_type(str),str}); tokens.push_back({line,column,get_type(str),str});
} }
else if(CALC_OPERATOR(res[ptr])) else if(CALC_OPERATOR(res[ptr]))
{ {
@ -325,19 +322,21 @@ void nasal_lexer::scan(const std::string& file)
str=res[ptr++]; str=res[ptr++];
if(ptr<res.size() && res[ptr]=='=') if(ptr<res.size() && res[ptr]=='=')
str+=res[ptr++]; str+=res[ptr++];
code+=str; column+=str.length();
tokens.push_back({line,get_type(str),str}); tokens.push_back({line,column,get_type(str),str});
} }
else if(NOTE(res[ptr]))// avoid note, after this process ptr will point to a '\n', so next loop line counter+1 else if(NOTE(res[ptr]))// avoid note, after this process ptr will point to a '\n', so next loop line counter+1
while(++ptr<res.size() && res[ptr]!='\n'); while(++ptr<res.size() && res[ptr]!='\n');
else else
{ {
code+=res[ptr++]; ++column;
++ptr;
die("unknown character."); die("unknown character.");
} }
} }
tokens.push_back({line,tok_eof,"eof"}); tokens.push_back({line,column,tok_eof,"eof"});
code=res=""; res="";
nerr.chkerr();
} }
void nasal_lexer::print() void nasal_lexer::print()

View File

@ -42,11 +42,11 @@ class nasal_parse
#define is_call(type) ((type)==tok_lcurve || (type)==tok_lbracket || (type)==tok_dot) #define is_call(type) ((type)==tok_lcurve || (type)==tok_lbracket || (type)==tok_dot)
private: private:
uint32_t ptr; uint32_t ptr;
uint32_t error;
uint32_t in_func; // count function block uint32_t in_func; // count function block
uint32_t in_loop; // count loop block uint32_t in_loop; // count loop block
const token* tokens;// ref from nasal_lexer const token* tokens;// ref from nasal_lexer
nasal_ast root; nasal_ast root;
nasal_err& nerr;
void die(uint32_t,const std::string&); void die(uint32_t,const std::string&);
void match(uint32_t type,const char* info=nullptr); void match(uint32_t type,const char* info=nullptr);
@ -98,7 +98,7 @@ private:
nasal_ast break_expr(); nasal_ast break_expr();
nasal_ast ret_expr(); nasal_ast ret_expr();
public: public:
uint32_t err(){return error;} nasal_parse(nasal_err& e):nerr(e){}
void print(){root.print(0);} void print(){root.print(0);}
void compile(const nasal_lexer&); void compile(const nasal_lexer&);
nasal_ast& ast(){return root;} nasal_ast& ast(){return root;}
@ -107,7 +107,7 @@ public:
void nasal_parse::compile(const nasal_lexer& lexer) void nasal_parse::compile(const nasal_lexer& lexer)
{ {
tokens=lexer.get_tokens().data(); tokens=lexer.get_tokens().data();
ptr=in_func=in_loop=error=0; ptr=in_func=in_loop=0;
root={1,ast_root}; root={1,ast_root};
while(tokens[ptr].type!=tok_eof) while(tokens[ptr].type!=tok_eof)
@ -119,11 +119,12 @@ void nasal_parse::compile(const nasal_lexer& lexer)
else if(need_semi_check(root.child().back()) && tokens[ptr].type!=tok_eof) else if(need_semi_check(root.child().back()) && tokens[ptr].type!=tok_eof)
die(error_line,"expected \";\""); die(error_line,"expected \";\"");
} }
nerr.chkerr();
} }
void nasal_parse::die(uint32_t line,const std::string& info) void nasal_parse::die(uint32_t line,const std::string& info)
{ {
++error; int col=(int)tokens[ptr].column-(int)tokens[ptr].str.length();
std::cout<<"[parse] line "<<line<<": "<<info<<".\n"; nerr.err("parse",line,col<0?0:col,info);
} }
void nasal_parse::match(uint32_t type,const char* info) void nasal_parse::match(uint32_t type,const char* info)
{ {

View File

@ -1,6 +1,6 @@
import("lib.nas"); import("lib.nas");
var filename=["main.cpp","nasal_ast.h","nasal_builtin.h","nasal_codegen.h","nasal_gc.h","nasal_import.h","nasal_lexer.h","nasal_parse.h","nasal_vm.h","nasal_dbg.h","nasal.h"]; var filename=["main.cpp","nasal_err.h","nasal_ast.h","nasal_builtin.h","nasal_codegen.h","nasal_gc.h","nasal_import.h","nasal_lexer.h","nasal_parse.h","nasal_vm.h","nasal_dbg.h","nasal.h"];
var space=[" "," ","",""," "," "," "," "," "," "," "]; var space=[" "," "," ","",""," "," "," "," "," "," "," "];
var enter_cnt=func(s) var enter_cnt=func(s)
{ {
var (cnt,len,enter)=(0,size(s),'\n'[0]); var (cnt,len,enter)=(0,size(s),'\n'[0]);

View File

@ -30,7 +30,10 @@ var prt=func()
s~=elem~' '; s~=elem~' ';
s~='\n'; s~='\n';
} }
system("cls"); if(os.platform()=="windows")
system("cls");
else
system("clear");
print(s); print(s);
} }