update variable name in nasal_lexer

This commit is contained in:
ValKmjolnir 2021-10-16 14:07:55 +08:00
parent e41f728589
commit 1b240b293e
5 changed files with 145 additions and 188 deletions

3
.gitignore vendored
View File

@ -30,3 +30,6 @@
*.exe *.exe
*.out *.out
*.app *.app
nasal
.vscode

View File

@ -1,11 +1,11 @@
#ifndef __NASAL_LEXER_H__ #ifndef __NASAL_LEXER_H__
#define __NASAL_LEXER_H__ #define __NASAL_LEXER_H__
#define IS_IDENTIFIER(c) ((c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z')) #define IS_ID(c) ((c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z'))
#define IS_HEX_NUMBER(c) (('0'<=c&&c<='9')||('a'<=c&&c<='f')||('A'<=c && c<='F')) #define IS_HEX(c) (('0'<=c&&c<='9')||('a'<=c&&c<='f')||('A'<=c && c<='F'))
#define IS_OCT_NUMEBR(c) ('0'<=c&&c<='7') #define IS_OCT(c) ('0'<=c&&c<='7')
#define IS_DIGIT(c) ('0'<=c&&c<='9') #define IS_DIGIT(c) ('0'<=c&&c<='9')
#define IS_STRING(c) (c=='\''||c=='\"'||c=='`') #define IS_STR(c) (c=='\''||c=='\"'||c=='`')
// single operators have only one character // single operators have only one character
#define IS_SINGLE_OPERATOR(c) (c=='('||c==')'||c=='['||c==']'||c=='{'||c=='}'||c==','||c==';'||c=='|'||c==':'||\ #define IS_SINGLE_OPERATOR(c) (c=='('||c==')'||c=='['||c==']'||c=='{'||c=='}'||c==','||c==';'||c=='|'||c==':'||\
c=='?'||c=='`'||c=='&'||c=='@'||c=='%'||c=='$'||c=='^'||c=='\\') c=='?'||c=='`'||c=='&'||c=='@'||c=='%'||c=='$'||c=='^'||c=='\\')
@ -34,7 +34,7 @@ enum token_type
struct struct
{ {
const char* str; const char* str;
const int tok_type; const uint32_t tok_type;
}token_table[]= }token_table[]=
{ {
{"for" ,tok_for }, {"for" ,tok_for },
@ -82,7 +82,7 @@ struct
{"<=" ,tok_leq }, {"<=" ,tok_leq },
{">" ,tok_grt }, {">" ,tok_grt },
{">=" ,tok_geq }, {">=" ,tok_geq },
{nullptr ,-1 } {nullptr ,0 }
}; };
struct token struct token
@ -99,10 +99,10 @@ private:
uint32_t error; uint32_t error;
uint32_t line; uint32_t line;
uint32_t ptr; uint32_t ptr;
size_t res_size; size_t size;
std::string line_code; std::string code;
std::string res; std::string res;
std::vector<token> token_list; 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*);
std::string id_gen(); std::string id_gen();
@ -113,7 +113,7 @@ public:
void scan(); void scan();
void print(); void print();
uint32_t err(){return error;} uint32_t err(){return error;}
const std::vector<token>& get_tokens(){return token_list;} const std::vector<token>& get_tokens(){return tokens;}
}; };
void nasal_lexer::open(const std::string& filename) void nasal_lexer::open(const std::string& filename)
@ -125,19 +125,10 @@ void nasal_lexer::open(const std::string& filename)
{ {
++error; ++error;
std::cout<<"[lexer] cannot open file <"<<filename<<">.\n"; std::cout<<"[lexer] cannot open file <"<<filename<<">.\n";
return;
} }
std::stringstream ss; std::stringstream ss;
ss<<fin.rdbuf(); ss<<fin.rdbuf();
res=ss.str(); res=ss.str();
// while(!fin.eof())
// {
// char c=fin.get();
// if(fin.eof())
// break;
// res+=c;
// }
return;
} }
uint32_t nasal_lexer::get_type(const std::string& tk_str) uint32_t nasal_lexer::get_type(const std::string& tk_str)
@ -148,218 +139,217 @@ uint32_t nasal_lexer::get_type(const std::string& tk_str)
return tok_null; return tok_null;
} }
void nasal_lexer::die(const char* error_info) void nasal_lexer::die(const char* info)
{ {
++error; ++error;
std::cout<<"[lexer] line "<<line<<" column "<<line_code.length()<<": \n"<<line_code<<"\n"; std::cout<<"[lexer] line "<<line<<" column "<<code.length()<<": \n"<<code<<'\n';
for(auto i:line_code) for(auto i:code)
std::cout<<(i=='\t'?'\t':' '); std::cout<<char(" \t"[i=='\t']);
std::cout<<"^"<<error_info<<'\n'; std::cout<<'^'<<info<<'\n';
return;
} }
std::string nasal_lexer::id_gen() std::string nasal_lexer::id_gen()
{ {
std::string token_str=""; std::string str="";
while(ptr<res_size && (IS_IDENTIFIER(res[ptr])||IS_DIGIT(res[ptr]))) while(ptr<size && (IS_ID(res[ptr])||IS_DIGIT(res[ptr])))
token_str+=res[ptr++]; str+=res[ptr++];
line_code+=token_str; code+=str;
return token_str; return str;
// after running this process, ptr will point to the next token's beginning character // after running this process, ptr will point to the next token's beginning character
} }
std::string nasal_lexer::num_gen() std::string nasal_lexer::num_gen()
{ {
// generate hex number // generate hex number
if(ptr+1<res_size && res[ptr]=='0' && res[ptr+1]=='x') if(ptr+1<size && res[ptr]=='0' && res[ptr+1]=='x')
{ {
std::string token_str="0x"; std::string str="0x";
ptr+=2; ptr+=2;
while(ptr<res_size && IS_HEX_NUMBER(res[ptr])) while(ptr<size && IS_HEX(res[ptr]))
token_str+=res[ptr++]; str+=res[ptr++];
line_code+=token_str; code+=str;
if(token_str.length()<3)// "0x" if(str.length()<3)// "0x"
die("incorrect number."); die("incorrect number.");
return token_str; return str;
} }
// generate oct number // generate oct number
else if(ptr+1<res_size && res[ptr]=='0' && res[ptr+1]=='o') else if(ptr+1<size && res[ptr]=='0' && res[ptr+1]=='o')
{ {
std::string token_str="0o"; std::string str="0o";
ptr+=2; ptr+=2;
while(ptr<res_size && IS_OCT_NUMEBR(res[ptr])) while(ptr<size && IS_OCT(res[ptr]))
token_str+=res[ptr++]; str+=res[ptr++];
line_code+=token_str; code+=str;
if(token_str.length()<3)// "0o" if(str.length()<3)// "0o"
die("incorrect number."); die("incorrect number.");
return token_str; return str;
} }
// 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]*)
std::string token_str=""; std::string str="";
while(ptr<res_size && IS_DIGIT(res[ptr])) while(ptr<size && IS_DIGIT(res[ptr]))
token_str+=res[ptr++]; str+=res[ptr++];
if(ptr<res_size && res[ptr]=='.') if(ptr<size && res[ptr]=='.')
{ {
token_str+=res[ptr++]; str+=res[ptr++];
while(ptr<res_size && IS_DIGIT(res[ptr])) while(ptr<size && IS_DIGIT(res[ptr]))
token_str+=res[ptr++]; str+=res[ptr++];
// "xxxx." is not a correct number // "xxxx." is not a correct number
if(token_str.back()=='.') if(str.back()=='.')
{ {
line_code+=token_str; code+=str;
die("incorrect number."); die("incorrect number.");
return "0"; return "0";
} }
} }
if(ptr<res_size && (res[ptr]=='e' || res[ptr]=='E')) if(ptr<size && (res[ptr]=='e' || res[ptr]=='E'))
{ {
token_str+=res[ptr++]; str+=res[ptr++];
if(ptr<res_size && (res[ptr]=='-' || res[ptr]=='+')) if(ptr<size && (res[ptr]=='-' || res[ptr]=='+'))
token_str+=res[ptr++]; str+=res[ptr++];
while(ptr<res_size && IS_DIGIT(res[ptr])) while(ptr<size && IS_DIGIT(res[ptr]))
token_str+=res[ptr++]; str+=res[ptr++];
// "xxxe(-|+)" is not a correct number // "xxxe(-|+)" is not a correct number
if(token_str.back()=='e' || token_str.back()=='E' || token_str.back()=='-' || token_str.back()=='+') if(str.back()=='e' || str.back()=='E' || str.back()=='-' || str.back()=='+')
{ {
line_code+=token_str; code+=str;
die("incorrect number."); die("incorrect number.");
return "0"; return "0";
} }
} }
line_code+=token_str; code+=str;
return token_str; return str;
} }
std::string nasal_lexer::str_gen() std::string nasal_lexer::str_gen()
{ {
std::string token_str=""; std::string str="";
char str_begin=res[ptr]; char begin=res[ptr];
line_code+=str_begin; code+=begin;
while(++ptr<res_size && res[ptr]!=str_begin) while(++ptr<size && res[ptr]!=begin)
{ {
line_code+=res[ptr]; code+=res[ptr];
if(res[ptr]=='\n') if(res[ptr]=='\n')
{ {
line_code=""; code="";
++line; ++line;
} }
if(res[ptr]=='\\' && ptr+1<res_size) if(res[ptr]=='\\' && ptr+1<size)
{ {
line_code+=res[++ptr]; code+=res[++ptr];
switch(res[ptr]) switch(res[ptr])
{ {
case 'a': token_str.push_back('\a');break; case 'a': str+='\a'; break;
case 'b': token_str.push_back('\b');break; case 'b': str+='\b'; break;
case 'f': token_str.push_back('\f');break; case 'f': str+='\f'; break;
case 'n': token_str.push_back('\n');break; case 'n': str+='\n'; break;
case 'r': token_str.push_back('\r');break; case 'r': str+='\r'; break;
case 't': token_str.push_back('\t');break; case 't': str+='\t'; break;
case 'v': token_str.push_back('\v');break; case 'v': str+='\v'; break;
case '?': token_str.push_back('\?');break; case '?': str+='\?'; break;
case '0': token_str.push_back('\0');break; case '0': str+='\0'; break;
case '\\':token_str.push_back('\\');break; case '\\':str+='\\'; break;
case '\'':token_str.push_back('\'');break; case '\'':str+='\''; break;
case '\"':token_str.push_back('\"');break; case '\"':str+='\"'; break;
default: token_str.push_back(res[ptr]);break; default: str+=res[ptr];break;
} }
continue; continue;
} }
token_str+=res[ptr]; str+=res[ptr];
} }
// check if this string ends with a " or ' // check if this string ends with a " or '
if(ptr++>=res_size) if(ptr++>=size)
die("get EOF when generating string."); die("get EOF when generating string.");
if(str_begin=='`' && token_str.length()!=1) code+=res[ptr-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 token_str; return str;
} }
void nasal_lexer::scan() void nasal_lexer::scan()
{ {
token_list.clear(); tokens.clear();
line=1; line=1;
ptr=0; ptr=0;
line_code=""; code="";
res_size=res.size(); size=res.size();
std::string token_str; std::string str;
while(ptr<res_size) while(ptr<size)
{ {
while(ptr<res_size && (res[ptr]==' ' || res[ptr]=='\n' || res[ptr]=='\t' || res[ptr]=='\r' || res[ptr]<0)) while(ptr<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
line_code+=res[ptr]; code+=res[ptr];
if(res[ptr++]=='\n') if(res[ptr++]=='\n')
{ {
++line; ++line;
line_code=""; code="";
} }
} }
if(ptr>=res_size) break; if(ptr>=size) break;
if(IS_IDENTIFIER(res[ptr])) if(IS_ID(res[ptr]))
{ {
token_str=id_gen(); str=id_gen();
token_list.push_back({line,get_type(token_str),token_str}); tokens.push_back({line,get_type(str),str});
if(!token_list.back().type) if(!tokens.back().type)
token_list.back().type=tok_id; tokens.back().type=tok_id;
} }
else if(IS_DIGIT(res[ptr])) else if(IS_DIGIT(res[ptr]))
token_list.push_back({line,tok_num,num_gen()}); tokens.push_back({line,tok_num,num_gen()});
else if(IS_STRING(res[ptr])) else if(IS_STR(res[ptr]))
token_list.push_back({line,tok_str,str_gen()}); tokens.push_back({line,tok_str,str_gen()});
else if(IS_SINGLE_OPERATOR(res[ptr])) else if(IS_SINGLE_OPERATOR(res[ptr]))
{ {
token_str=res[ptr]; str=res[ptr];
line_code+=res[ptr]; code+=res[ptr];
uint32_t type=get_type(token_str); uint32_t type=get_type(str);
if(!type) if(!type)
die("incorrect operator."); die("incorrect operator.");
token_list.push_back({line,type,token_str}); tokens.push_back({line,type,str});
++ptr; ++ptr;
} }
else if(res[ptr]=='.') else if(res[ptr]=='.')
{ {
if(ptr+2<res_size && res[ptr+1]=='.' && res[ptr+2]=='.') if(ptr+2<size && res[ptr+1]=='.' && res[ptr+2]=='.')
{ {
token_str="..."; str="...";
ptr+=3; ptr+=3;
} }
else else
{ {
token_str="."; str=".";
++ptr; ++ptr;
} }
line_code+=token_str; code+=str;
token_list.push_back({line,get_type(token_str),token_str}); tokens.push_back({line,get_type(str),str});
} }
else if(IS_CALC_OPERATOR(res[ptr])) else if(IS_CALC_OPERATOR(res[ptr]))
{ {
// get calculation operator // get calculation operator
token_str=res[ptr++]; str=res[ptr++];
if(ptr<res_size && res[ptr]=='=') if(ptr<size && res[ptr]=='=')
token_str+=res[ptr++]; str+=res[ptr++];
line_code+=token_str; code+=str;
token_list.push_back({line,get_type(token_str),token_str}); tokens.push_back({line,get_type(str),str});
} }
else if(IS_NOTE(res[ptr]))// avoid note, after this process ptr will point to a '\n', so next loop line counter+1 else if(IS_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<size && res[ptr]!='\n');
else else
{ {
line_code+=res[ptr++]; code+=res[ptr++];
die("unknown character."); die("unknown character.");
} }
} }
token_list.push_back({line,tok_eof,""}); tokens.push_back({line,tok_eof,""});
res.clear(); res.clear();
return; return;
} }
void nasal_lexer::print() void nasal_lexer::print()
{ {
for(auto& tok:token_list) for(auto& tok:tokens)
std::cout<<"("<<tok.line<<" | "<<tok.str<<")\n"; std::cout<<"("<<tok.line<<" | "<<tok.str<<")\n";
return;
} }
#endif #endif

View File

@ -3,65 +3,50 @@
var list=func() var list=func()
{ {
var (begin,end)=(nil,nil); var (begin,end)=(nil,nil);
return return{
{ push_back:func(elem){
push_back:func(elem)
{
var tmp={elem:elem,prev:nil,next:nil}; var tmp={elem:elem,prev:nil,next:nil};
if(end!=nil) if(end!=nil){
{
end.next=tmp; end.next=tmp;
tmp.prev=end; tmp.prev=end;
end=tmp; end=tmp;
} }
else else
begin=end=tmp; begin=end=tmp;
return;
}, },
push_front:func(elem) push_front:func(elem){
{
var tmp={elem:elem,prev:nil,next:nil}; var tmp={elem:elem,prev:nil,next:nil};
if(begin!=nil) if(begin!=nil){
{
begin.prev=tmp; begin.prev=tmp;
tmp.next=begin; tmp.next=begin;
begin=tmp; begin=tmp;
} }
else else
begin=end=tmp; begin=end=tmp;
return;
}, },
pop_back:func() pop_back:func(){
{
if(end!=nil) if(end!=nil)
end=end.prev; end=end.prev;
if(end==nil) if(end==nil)
begin=nil; begin=nil;
else else
end.next=nil; end.next=nil;
return;
}, },
pop_front:func() pop_front:func(){
{
if(begin!=nil) if(begin!=nil)
begin=begin.next; begin=begin.next;
if(begin==nil) if(begin==nil)
end=nil; end=nil;
else else
begin.prev=nil; begin.prev=nil;
return;
}, },
front:func() front:func(){
{
if(begin!=nil) if(begin!=nil)
return begin.elem; return begin.elem;
return nil;
}, },
back:func() back:func(){
{
if(end!=nil) if(end!=nil)
return end.elem; return end.elem;
return nil;
}, },
}; };
} }

View File

@ -3,43 +3,33 @@
var queue=func() var queue=func()
{ {
var (begin,end)=(nil,nil); var (begin,end)=(nil,nil);
return return{
{ push:func(elem){
push:func(elem) var new_node={
{
var new_node=
{
elem:elem, elem:elem,
next:nil next:nil
}; };
if(begin==nil) if(begin==nil)
begin=end=new_node; begin=end=new_node;
else else{
{
end.next=new_node; end.next=new_node;
end=new_node; end=new_node;
} }
return;
}, },
pop:func() pop:func(){
{
if(begin!=nil) if(begin!=nil)
begin=begin.next; begin=begin.next;
if(begin==nil) if(begin==nil)
end=nil; end=nil;
}, },
front:func() front:func(){
{
if(begin!=nil) if(begin!=nil)
return begin.elem; return begin.elem;
return nil;
}, },
clear:func() clear:func(){
{
begin=end=nil; begin=end=nil;
}, },
empty:func() empty:func(){
{
return begin==nil; return begin==nil;
} }
}; };

View File

@ -3,33 +3,22 @@
var stack=func() var stack=func()
{ {
var next=nil; var next=nil;
return return{
{ push:func(elem){
push:func(elem)
{
next={elem:elem,next:next}; next={elem:elem,next:next};
return;
}, },
pop:func() pop:func(){
{ if(next!=nil)
var tmp=next; next=next.next;
if(tmp!=nil)
next=tmp.next;
return;
}, },
top:func() top:func(){
{ if(next!=nil)
var tmp=next; return next.elem;
if(tmp!=nil)
return tmp.elem;
return nil;
}, },
clear:func() clear:func(){
{
next=nil; next=nil;
}, },
empty:func() empty:func(){
{
return next==nil; return next==nil;
} }
}; };