#ifndef __NASAL_LEXER_H__ #define __NASAL_LEXER_H__ #define IS_IDENTIFIER(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_OCT_NUMEBR(c) ('0'<=c&&c<='7') #define IS_DIGIT(c) ('0'<=c&&c<='9') #define IS_STRING(c) (c=='\''||c=='\"'||c=='`') // single operators have only one character #define IS_SINGLE_OPERATOR(c) (c=='('||c==')'||c=='['||c==']'||c=='{'||c=='}'||c==','||c==';'||c=='|'||c==':'||\ c=='?'||c=='`'||c=='&'||c=='@'||c=='%'||c=='$'||c=='^'||c=='\\') // calculation operators may have two chars, for example: += -= *= /= ~= != == >= <= #define IS_CALC_OPERATOR(c) (c=='='||c=='+'||c=='-'||c=='*'||c=='!'||c=='/'||c=='<'||c=='>'||c=='~') #define IS_NOTE(c) (c=='#') enum token_type { tok_null=0, tok_number,tok_string,tok_identifier, tok_for,tok_forindex,tok_foreach,tok_while, tok_var,tok_func,tok_break,tok_continue, tok_return,tok_if,tok_elsif,tok_else,tok_nil, tok_left_curve,tok_right_curve, tok_left_bracket,tok_right_bracket, tok_left_brace,tok_right_brace, tok_semi,tok_and,tok_or,tok_comma,tok_dot,tok_ellipsis,tok_quesmark, tok_colon,tok_add,tok_sub,tok_mult,tok_div,tok_link,tok_not, tok_equal, tok_add_equal,tok_sub_equal,tok_mult_equal,tok_div_equal,tok_link_equal, tok_cmp_equal,tok_cmp_not_equal,tok_less_than,tok_less_equal,tok_greater_than,tok_greater_equal }; struct { const char* str; int tok_type; }token_table[]= { {"for" ,tok_for }, {"forindex",tok_forindex }, {"foreach" ,tok_foreach }, {"while" ,tok_while }, {"var" ,tok_var }, {"func" ,tok_func }, {"break" ,tok_break }, {"continue",tok_continue }, {"return" ,tok_return }, {"if" ,tok_if }, {"elsif" ,tok_elsif }, {"else" ,tok_else }, {"nil" ,tok_nil }, {"(" ,tok_left_curve }, {")" ,tok_right_curve }, {"[" ,tok_left_bracket }, {"]" ,tok_right_bracket}, {"{" ,tok_left_brace }, {"}" ,tok_right_brace }, {";" ,tok_semi }, {"and" ,tok_and }, {"or" ,tok_or }, {"," ,tok_comma }, {"." ,tok_dot }, {"..." ,tok_ellipsis }, {"?" ,tok_quesmark }, {":" ,tok_colon }, {"+" ,tok_add }, {"-" ,tok_sub }, {"*" ,tok_mult }, {"/" ,tok_div }, {"~" ,tok_link }, {"!" ,tok_not }, {"=" ,tok_equal }, {"+=" ,tok_add_equal }, {"-=" ,tok_sub_equal }, {"*=" ,tok_mult_equal }, {"/=" ,tok_div_equal }, {"~=" ,tok_link_equal }, {"==" ,tok_cmp_equal }, {"!=" ,tok_cmp_not_equal}, {"<" ,tok_less_than }, {"<=" ,tok_less_equal }, {">" ,tok_greater_than }, {">=" ,tok_greater_equal}, {NULL ,-1 } }; struct token { int line; int type; std::string str; token(int l=0,int t=tok_null,std::string s=""){line=l;type=t;str=s;return;} }; class nasal_lexer { private: int error; int res_size; int line; int ptr; std::string line_code; std::vector res; std::vector token_list; int get_token_type(std::string); void die(std::string,int,int); std::string identifier_gen(); std::string number_gen(); std::string string_gen(); public: void openfile(std::string); void scanner(); void print_token(); int get_error(); std::vector& get_token_list(); }; void nasal_lexer::openfile(std::string filename) { error=0; res.clear(); std::ifstream fin(filename,std::ios::binary); if(fin.fail()) { ++error; std::cout<<">> [lexer] cannot open file \""<> [lexer] line "< [0~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*) while(ptr=res_size) { line_code+=token_str; die("["+line_code+"_] incorrect number.",line,line_code.length()); return "0"; } while(ptr=res_size) { line_code+=token_str; die("["+line_code+"_] incorrect number.",line,line_code.length()); return "0"; } if(ptr=res_size) { line_code+=token_str; die("["+line_code+"_] incorrect number.",line,line_code.length()); return "0"; } while(ptr=res_size) die("["+line_code+"_] get EOF when generating string.",line,line_code.length()); return token_str; } void nasal_lexer::scanner() { token_list.clear(); line=1; ptr=0; line_code=""; std::string token_str; while(ptr=res_size) break; if(IS_IDENTIFIER(res[ptr])) { token_str=identifier_gen(); token new_token(line,get_token_type(token_str),token_str); if(!new_token.type) new_token.type=tok_identifier; token_list.push_back(new_token); } else if(IS_DIGIT(res[ptr])) { token_str=number_gen(); token new_token(line,tok_number,token_str); token_list.push_back(new_token); } else if(IS_STRING(res[ptr])) { token_str=string_gen(); token new_token(line,tok_string,token_str); token_list.push_back(new_token); } else if(IS_SINGLE_OPERATOR(res[ptr])) { token_str=""; token_str+=res[ptr]; line_code+=res[ptr]; token new_token(line,get_token_type(token_str),token_str); if(!new_token.type) die("["+line_code+"_] incorrect operator.",line,line_code.length()); token_list.push_back(new_token); ++ptr; } else if(res[ptr]=='.') { if(ptr+2& nasal_lexer::get_token_list() { return token_list; } #endif