#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_OPRATOR(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=='#') 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_greater_than }, {"<=" ,tok_less_equal }, {">=" ,tok_greater_equal}, {NULL ,-1 } }; struct token { int line; int type; std::string str; }; class nasal_lexer { private: int error; int res_size; int line; int ptr; std::string line_code; std::vector res; std::vector token_list; std::string identifier_gen(); std::string number_gen(); std::string string_gen(); public: void clear(); void openfile(std::string); void die(std::string,int,int); void scanner(); void print_token(); int get_error(); std::vector& get_token_list(); }; void nasal_lexer::clear() { error=0; res_size=0; line=0; ptr=0; line_code=""; res.clear(); token_list.clear(); return; } 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"; } if(ptr=res_size) die("["+line_code+"_] get EOF when generating string.",line,line_code.length()); ++ptr; 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; new_token.line=line; new_token.str=token_str; new_token.type=0; for(int i=0;token_table[i].str;++i) if(token_str==token_table[i].str) { new_token.type=token_table[i].tok_type; break; } 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; new_token.line=line; new_token.str=token_str; new_token.type=tok_number; token_list.push_back(new_token); } else if(IS_STRING(res[ptr])) { token_str=string_gen(); token new_token; new_token.line=line; new_token.type=tok_string; new_token.str=token_str; token_list.push_back(new_token); } else if(IS_SINGLE_OPRATOR(res[ptr])) { token_str=""; token_str+=res[ptr]; line_code+=res[ptr]; token new_token; new_token.line=line; new_token.str=token_str; new_token.type=-1; for(int i=0;token_table[i].str;++i) if(token_str==token_table[i].str) { new_token.type=token_table[i].tok_type; break; } if(new_token.type<0) 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