lexer,parser,import,codegen use the same error module.
This commit is contained in:
parent
30650bb64f
commit
f0ae63bce5
32
main.cpp
32
main.cpp
|
@ -51,12 +51,6 @@ void logo()
|
|||
<<"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()
|
||||
{
|
||||
std::cout
|
||||
|
@ -67,43 +61,37 @@ void err()
|
|||
|
||||
void execute(const std::string& file,const uint32_t cmd)
|
||||
{
|
||||
nasal_lexer lexer;
|
||||
nasal_parse parse;
|
||||
nasal_import linker;
|
||||
nasal_codegen gen;
|
||||
// front end use the same error module
|
||||
nasal_err nerr;
|
||||
nasal_lexer lexer(nerr);
|
||||
nasal_parse parse(nerr);
|
||||
nasal_import linker(nerr);
|
||||
nasal_codegen gen(nerr);
|
||||
// back end
|
||||
nasal_vm vm;
|
||||
|
||||
// lexer scans file to get tokens
|
||||
lexer.scan(file);
|
||||
if(lexer.err())
|
||||
die("lexer",file);
|
||||
if(cmd&VM_LEXINFO)
|
||||
lexer.print();
|
||||
|
||||
// parser gets lexer's token list to compile
|
||||
parse.compile(lexer);
|
||||
if(parse.err())
|
||||
die("parse",file);
|
||||
|
||||
// linker gets parser's ast and load import files to this ast
|
||||
linker.link(parse,file);
|
||||
if(linker.err())
|
||||
die("import",file);
|
||||
if(cmd&VM_ASTINFO)
|
||||
parse.print();
|
||||
|
||||
// code generator gets parser's ast and linker's import file list to generate code
|
||||
gen.compile(parse,linker);
|
||||
if(gen.err())
|
||||
die("code",file);
|
||||
if(cmd&VM_CODEINFO)
|
||||
gen.print();
|
||||
|
||||
// run bytecode
|
||||
if(cmd&VM_DEBUG)
|
||||
{
|
||||
nasal_dbg dbg;
|
||||
dbg.run(gen,linker);
|
||||
nasal_dbg debugger;
|
||||
debugger.run(gen,linker);
|
||||
}
|
||||
else if(cmd&VM_EXECTIME)
|
||||
{
|
||||
|
@ -119,7 +107,7 @@ int main(int argc,const char* argv[])
|
|||
{
|
||||
if(argc==1)
|
||||
{
|
||||
help();
|
||||
logo();
|
||||
return 0;
|
||||
}
|
||||
if(argc==2)
|
||||
|
|
8
makefile
8
makefile
|
@ -1,5 +1,5 @@
|
|||
.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
|
||||
test:nasal
|
||||
./nasal test/ascii-art.nas
|
||||
|
@ -11,18 +11,18 @@ test:nasal
|
|||
./nasal test/calc.nas
|
||||
./nasal test/choice.nas
|
||||
./nasal test/class.nas
|
||||
# ./nasal test/exception.nas
|
||||
./nasal -c test/exception.nas
|
||||
./nasal -t test/fib.nas
|
||||
./nasal test/filesystem.nas
|
||||
./nasal test/hexdump.nas
|
||||
./nasal test/json.nas
|
||||
./nasal test/leetcode1319.nas
|
||||
./nasal test/lexer.nas
|
||||
./nasal -c test/life.nas
|
||||
./nasal test/life.nas
|
||||
./nasal -t test/loop.nas
|
||||
./nasal -c test/mandel.nas
|
||||
./nasal -t test/mandelbrot.nas
|
||||
# ./nasal -t test/module_test.nas
|
||||
./nasal -c test/module_test.nas
|
||||
./nasal test/nasal_test.nas
|
||||
./nasal -t test/pi.nas
|
||||
./nasal -t test/prime.nas
|
||||
|
|
1
nasal.h
1
nasal.h
|
@ -127,6 +127,7 @@ std::string rawstr(const std::string& str)
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
#include "nasal_err.h"
|
||||
#include "nasal_lexer.h"
|
||||
#include "nasal_ast.h"
|
||||
#include "nasal_parse.h"
|
||||
|
|
|
@ -193,6 +193,7 @@ class nasal_codegen
|
|||
private:
|
||||
uint32_t error;
|
||||
uint16_t fileindex;
|
||||
nasal_err& nerr;
|
||||
const std::string* file;
|
||||
std::stack<uint32_t> in_iterloop;
|
||||
std::unordered_map<double,int> num_table;
|
||||
|
@ -205,7 +206,7 @@ private:
|
|||
std::vector<std::string> global; // global : max 4095 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_string(const std::string&);
|
||||
void find_symbol(const nasal_ast&);
|
||||
|
@ -246,6 +247,7 @@ private:
|
|||
void block_gen(const nasal_ast&);
|
||||
void ret_gen(const nasal_ast&);
|
||||
public:
|
||||
nasal_codegen(nasal_err& e):nerr(e){}
|
||||
uint32_t err(){return error;}
|
||||
void compile(const nasal_parse&,const nasal_import&);
|
||||
void print_op(uint32_t);
|
||||
|
@ -255,10 +257,10 @@ public:
|
|||
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;
|
||||
std::cout<<"[code] <"<<file[fileindex]<<":"<<line<<"> "<<info<<"\n";
|
||||
nerr.load(file[fileindex]);
|
||||
nerr.err("code",line,info.c_str());
|
||||
}
|
||||
|
||||
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);
|
||||
if(global.size()>=STACK_MAX_DEPTH)
|
||||
die("too many global variants: "+std::to_string(global.size())+".",0);
|
||||
nerr.chkerr();
|
||||
}
|
||||
|
||||
void nasal_codegen::print_op(uint32_t index)
|
||||
|
|
35
nasal_dbg.h
35
nasal_dbg.h
|
@ -7,22 +7,19 @@ class nasal_dbg:public nasal_vm
|
|||
{
|
||||
private:
|
||||
bool next_step;
|
||||
uint16_t last_fidx;
|
||||
uint16_t bk_fidx;
|
||||
uint32_t bk_line;
|
||||
std::vector<std::string> src;
|
||||
file_line src;
|
||||
|
||||
std::vector<std::string> parse(std::string&);
|
||||
uint16_t get_fileindex(std::string&);
|
||||
std::vector<std::string> parse(const std::string&);
|
||||
uint16_t get_fileindex(const std::string&);
|
||||
void err();
|
||||
void help();
|
||||
void load_src(const std::string&);
|
||||
void stepinfo();
|
||||
void interact();
|
||||
public:
|
||||
nasal_dbg():
|
||||
next_step(false),
|
||||
last_fidx(0),
|
||||
bk_fidx(0),bk_line(0){}
|
||||
void run(
|
||||
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::string tmp="";
|
||||
|
@ -49,7 +46,7 @@ std::vector<std::string> nasal_dbg::parse(std::string& cmd)
|
|||
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)
|
||||
if(filename==files[i])
|
||||
|
@ -81,30 +78,11 @@ void nasal_dbg::help()
|
|||
<<"\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()
|
||||
{
|
||||
uint32_t begin,end;
|
||||
uint32_t line=bytecode[pc].line==0?0:bytecode[pc].line-1;
|
||||
if(bytecode[pc].fidx!=last_fidx)
|
||||
load_src(files[bytecode[pc].fidx]);
|
||||
last_fidx=bytecode[pc].fidx;
|
||||
src.load(files[bytecode[pc].fidx]);
|
||||
printf("source code:\n");
|
||||
begin=(line>>3)==0?0:((line>>3)<<3);
|
||||
end=(1+(line>>3))<<3;
|
||||
|
@ -203,7 +181,6 @@ void nasal_dbg::run(
|
|||
{
|
||||
detail_info=true;
|
||||
init(gen.get_strs(),gen.get_nums(),linker.get_file());
|
||||
load_src(files[0]);
|
||||
const void* opr_table[]=
|
||||
{
|
||||
&&nop, &&intg, &&intl, &&loadg,
|
||||
|
|
|
@ -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
|
|
@ -4,26 +4,19 @@
|
|||
class nasal_import
|
||||
{
|
||||
private:
|
||||
uint32_t error;
|
||||
nasal_err& nerr;
|
||||
std::vector<std::string> files;
|
||||
void die(const std::string&,const char*);
|
||||
bool check_import(const nasal_ast&);
|
||||
bool check_exist(const std::string&);
|
||||
void linker(nasal_ast&,nasal_ast&&);
|
||||
nasal_ast file_import(nasal_ast&);
|
||||
nasal_ast load(nasal_ast&,uint16_t);
|
||||
public:
|
||||
uint32_t err(){return error;}
|
||||
void link(nasal_parse&,const std::string&);
|
||||
nasal_import(nasal_err& e):nerr(e){}
|
||||
void link(nasal_parse&,const std::string&);
|
||||
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)
|
||||
{
|
||||
/*
|
||||
|
@ -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_lexer lex;
|
||||
nasal_parse par;
|
||||
nasal_lexer lex(nerr);
|
||||
nasal_parse par(nerr);
|
||||
// get filename and set node to ast_null
|
||||
std::string filename=node[1][0].str();
|
||||
node.clear();
|
||||
|
@ -77,17 +70,7 @@ nasal_ast nasal_import::file_import(nasal_ast& node)
|
|||
|
||||
// start importing...
|
||||
lex.scan(filename);
|
||||
if(lex.err())
|
||||
{
|
||||
die(filename,"lexer");
|
||||
return {0,ast_root};
|
||||
}
|
||||
par.compile(lex);
|
||||
if(par.err())
|
||||
{
|
||||
die(filename,"parser");
|
||||
return {0,ast_root};
|
||||
}
|
||||
nasal_ast tmp=std::move(par.ast());
|
||||
// check if tmp has 'import'
|
||||
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)
|
||||
{
|
||||
// initializing
|
||||
error=0;
|
||||
files={self};
|
||||
// scan root and import files,then generate a new ast and return to import_ast
|
||||
// the main file's index is 0
|
||||
|
|
|
@ -90,30 +90,36 @@ struct
|
|||
struct token
|
||||
{
|
||||
uint32_t line;
|
||||
uint32_t column;
|
||||
uint32_t type;
|
||||
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
|
||||
{
|
||||
private:
|
||||
uint32_t error;
|
||||
uint32_t line;
|
||||
uint32_t column;
|
||||
uint32_t ptr;
|
||||
std::string filename;
|
||||
std::string code;
|
||||
nasal_err& nerr;
|
||||
std::string res;
|
||||
std::vector<token> tokens;
|
||||
|
||||
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&);
|
||||
std::string id_gen();
|
||||
std::string num_gen();
|
||||
std::string str_gen();
|
||||
public:
|
||||
uint32_t err(){return error;}
|
||||
nasal_lexer(nasal_err& e):nerr(e){}
|
||||
void scan(const std::string&);
|
||||
void print();
|
||||
const std::vector<token>& get_tokens() const {return tokens;}
|
||||
|
@ -121,13 +127,11 @@ public:
|
|||
|
||||
void nasal_lexer::open(const std::string& file)
|
||||
{
|
||||
filename=file;
|
||||
std::ifstream fin(file,std::ios::binary);
|
||||
if(fin.fail())
|
||||
{
|
||||
++error;
|
||||
std::cout<<"[lexer] cannot open file <"<<file<<">.\n";
|
||||
}
|
||||
nerr.err("lexer","cannot open file <"+file+">.");
|
||||
else
|
||||
nerr.load(file);
|
||||
std::stringstream ss;
|
||||
ss<<fin.rdbuf();
|
||||
res=ss.str();
|
||||
|
@ -141,21 +145,12 @@ uint32_t nasal_lexer::get_type(const std::string& tk_str)
|
|||
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 str="";
|
||||
while(ptr<res.size() && (ID(res[ptr])||DIGIT(res[ptr])))
|
||||
str+=res[ptr++];
|
||||
code+=str;
|
||||
column+=str.length();
|
||||
return str;
|
||||
}
|
||||
|
||||
|
@ -168,7 +163,7 @@ std::string nasal_lexer::num_gen()
|
|||
ptr+=2;
|
||||
while(ptr<res.size() && HEX(res[ptr]))
|
||||
str+=res[ptr++];
|
||||
code+=str;
|
||||
column+=str.length();
|
||||
if(str.length()<3)// "0x"
|
||||
die("invalid number.");
|
||||
return str;
|
||||
|
@ -180,7 +175,7 @@ std::string nasal_lexer::num_gen()
|
|||
ptr+=2;
|
||||
while(ptr<res.size() && OCT(res[ptr]))
|
||||
str+=res[ptr++];
|
||||
code+=str;
|
||||
column+=str.length();
|
||||
if(str.length()<3)// "0o"
|
||||
die("invalid number.");
|
||||
return str;
|
||||
|
@ -198,7 +193,7 @@ std::string nasal_lexer::num_gen()
|
|||
// "xxxx." is not a correct number
|
||||
if(str.back()=='.')
|
||||
{
|
||||
code+=str;
|
||||
column+=str.length();
|
||||
die("invalid number.");
|
||||
return "0";
|
||||
}
|
||||
|
@ -213,12 +208,12 @@ std::string nasal_lexer::num_gen()
|
|||
// "xxxe(-|+)" is not a correct number
|
||||
if(str.back()=='e' || str.back()=='E' || str.back()=='-' || str.back()=='+')
|
||||
{
|
||||
code+=str;
|
||||
column+=str.length();
|
||||
die("invalid number.");
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
code+=str;
|
||||
column+=str.length();
|
||||
return str;
|
||||
}
|
||||
|
||||
|
@ -226,18 +221,19 @@ std::string nasal_lexer::str_gen()
|
|||
{
|
||||
std::string str="";
|
||||
char begin=res[ptr];
|
||||
code+=begin;
|
||||
++column;
|
||||
while(++ptr<res.size() && res[ptr]!=begin)
|
||||
{
|
||||
code+=res[ptr];
|
||||
++column;
|
||||
if(res[ptr]=='\n')
|
||||
{
|
||||
code="";
|
||||
column=0;
|
||||
++line;
|
||||
}
|
||||
if(res[ptr]=='\\' && ptr+1<res.size())
|
||||
{
|
||||
code+=res[++ptr];
|
||||
++column;
|
||||
++ptr;
|
||||
switch(res[ptr])
|
||||
{
|
||||
case '0': str+='\0'; break;
|
||||
|
@ -264,7 +260,7 @@ std::string nasal_lexer::str_gen()
|
|||
die("get EOF when generating string.");
|
||||
return str;
|
||||
}
|
||||
code+=res[ptr-1];
|
||||
++column;
|
||||
if(begin=='`' && str.length()!=1)
|
||||
die("\'`\' is used for string that includes one character.");
|
||||
return str;
|
||||
|
@ -273,7 +269,8 @@ std::string nasal_lexer::str_gen()
|
|||
void nasal_lexer::scan(const std::string& file)
|
||||
{
|
||||
line=1;
|
||||
error=ptr=0;
|
||||
column=0;
|
||||
ptr=0;
|
||||
open(file);
|
||||
|
||||
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))
|
||||
{
|
||||
// these characters will be ignored, and '\n' will cause ++line
|
||||
code+=res[ptr];
|
||||
++column;
|
||||
if(res[ptr++]=='\n')
|
||||
{
|
||||
++line;
|
||||
code="";
|
||||
column=0;
|
||||
}
|
||||
}
|
||||
if(ptr>=res.size()) break;
|
||||
|
@ -294,20 +291,20 @@ void nasal_lexer::scan(const std::string& file)
|
|||
{
|
||||
str=id_gen();
|
||||
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]))
|
||||
tokens.push_back({line,tok_num,num_gen()});
|
||||
tokens.push_back({line,column,tok_num,num_gen()});
|
||||
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]))
|
||||
{
|
||||
str=res[ptr];
|
||||
code+=res[ptr];
|
||||
++column;
|
||||
uint32_t type=get_type(str);
|
||||
if(!type)
|
||||
die("invalid operator.");
|
||||
tokens.push_back({line,type,str});
|
||||
tokens.push_back({line,column,type,str});
|
||||
++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]=='.')
|
||||
str+="..";
|
||||
ptr+=str.length();
|
||||
code+=str;
|
||||
tokens.push_back({line,get_type(str),str});
|
||||
column+=str.length();
|
||||
tokens.push_back({line,column,get_type(str),str});
|
||||
}
|
||||
else if(CALC_OPERATOR(res[ptr]))
|
||||
{
|
||||
|
@ -325,19 +322,21 @@ void nasal_lexer::scan(const std::string& file)
|
|||
str=res[ptr++];
|
||||
if(ptr<res.size() && res[ptr]=='=')
|
||||
str+=res[ptr++];
|
||||
code+=str;
|
||||
tokens.push_back({line,get_type(str),str});
|
||||
column+=str.length();
|
||||
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
|
||||
while(++ptr<res.size() && res[ptr]!='\n');
|
||||
else
|
||||
{
|
||||
code+=res[ptr++];
|
||||
++column;
|
||||
++ptr;
|
||||
die("unknown character.");
|
||||
}
|
||||
}
|
||||
tokens.push_back({line,tok_eof,"eof"});
|
||||
code=res="";
|
||||
tokens.push_back({line,column,tok_eof,"eof"});
|
||||
res="";
|
||||
nerr.chkerr();
|
||||
}
|
||||
|
||||
void nasal_lexer::print()
|
||||
|
|
|
@ -42,11 +42,11 @@ class nasal_parse
|
|||
#define is_call(type) ((type)==tok_lcurve || (type)==tok_lbracket || (type)==tok_dot)
|
||||
private:
|
||||
uint32_t ptr;
|
||||
uint32_t error;
|
||||
uint32_t in_func; // count function block
|
||||
uint32_t in_loop; // count loop block
|
||||
const token* tokens;// ref from nasal_lexer
|
||||
nasal_ast root;
|
||||
nasal_err& nerr;
|
||||
|
||||
void die(uint32_t,const std::string&);
|
||||
void match(uint32_t type,const char* info=nullptr);
|
||||
|
@ -98,7 +98,7 @@ private:
|
|||
nasal_ast break_expr();
|
||||
nasal_ast ret_expr();
|
||||
public:
|
||||
uint32_t err(){return error;}
|
||||
nasal_parse(nasal_err& e):nerr(e){}
|
||||
void print(){root.print(0);}
|
||||
void compile(const nasal_lexer&);
|
||||
nasal_ast& ast(){return root;}
|
||||
|
@ -107,7 +107,7 @@ public:
|
|||
void nasal_parse::compile(const nasal_lexer& lexer)
|
||||
{
|
||||
tokens=lexer.get_tokens().data();
|
||||
ptr=in_func=in_loop=error=0;
|
||||
ptr=in_func=in_loop=0;
|
||||
|
||||
root={1,ast_root};
|
||||
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)
|
||||
die(error_line,"expected \";\"");
|
||||
}
|
||||
nerr.chkerr();
|
||||
}
|
||||
void nasal_parse::die(uint32_t line,const std::string& info)
|
||||
{
|
||||
++error;
|
||||
std::cout<<"[parse] line "<<line<<": "<<info<<".\n";
|
||||
int col=(int)tokens[ptr].column-(int)tokens[ptr].str.length();
|
||||
nerr.err("parse",line,col<0?0:col,info);
|
||||
}
|
||||
void nasal_parse::match(uint32_t type,const char* info)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
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 space=[" "," ","",""," "," "," "," "," "," "," "];
|
||||
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 enter_cnt=func(s)
|
||||
{
|
||||
var (cnt,len,enter)=(0,size(s),'\n'[0]);
|
||||
|
|
|
@ -30,7 +30,10 @@ var prt=func()
|
|||
s~=elem~' ';
|
||||
s~='\n';
|
||||
}
|
||||
system("cls");
|
||||
if(os.platform()=="windows")
|
||||
system("cls");
|
||||
else
|
||||
system("clear");
|
||||
print(s);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue