%{ #include #include #include #include #include "compiler.h" #include "script-parser.hh" #ifdef _MSC_VER #pragma warning(disable:4018) #pragma warning(disable:4102) #pragma warning(disable:4244) #pragma warning(disable:4267) #endif #undef yywrap #define yywrap() 1 #define yyterminate() return token::END_OF_FILE %} %option noyywrap nounput batch %option never-interactive %option noyy_scan_buffer %option noyy_scan_bytes %option noyy_scan_string %option 8bit %option nounistd id [a-zA-Z_][a-zA-Z_0-9]* int [1-9][0-9]* blank [ \t] %x C_COMMENT %x CPP_COMMENT %x STRING %{ #define YY_USER_ACTION yylloc->columns(yyleng); %} %% %{ typedef yy::script_parser::token token; yylloc->step(); std::string string_buffer; %} { \n { yylloc->lines(); } "^#" { yylloc->step(); BEGIN(CPP_COMMENT); } "//" { yylloc->step(); BEGIN(CPP_COMMENT); } "/*" { yylloc->step(); BEGIN(C_COMMENT); } "if" return token::TK_IF; "else" return token::TK_ELSE; "for" return token::TK_FOR; "while" return token::TK_WHILE; "switch" return token::TK_SWITCH; "case" return token::TK_CASE; "default" return token::TK_DEFAULT; "break" return token::TK_BREAK; "string" return token::TK_STRING; "int" return token::TK_INTEGER; "void" return token::TK_VOID; "__code" return token::TK_CODE; "return" return token::TK_RETURN; \\\n yylloc->lines(); [-+*/=%&|(){}<>\[\],:;&] return yy::script_parser::token_type(yytext[0]); "&&" return token::TK_LOGAND; "||" return token::TK_LOGOR; "==" return token::TK_EQ; "!=" return token::TK_NE; ">=" return token::TK_GE; "<=" return token::TK_LE; "<<" return token::TK_LSHIFT; ">>" return token::TK_RSHIFT; "+=" return token::TK_ADD_ASSIGN; "-=" return token::TK_SUB_ASSIGN; "*=" return token::TK_MUL_ASSIGN; "/=" return token::TK_DIV_ASSIGN; "%=" return token::TK_MOD_ASSIGN; {blank}+ yylloc->step(); \" { yylloc->step(); string_buffer.clear(); BEGIN(STRING); } {int} { errno = 0; long n = strtol(yytext, NULL, 10); if (n < LONG_MIN || n > LONG_MAX || errno == ERANGE) driver.error(*yylloc, "整数が範囲外です。"); yylval->ival = n; return token::TK_IVAL; } "0" { yylval->ival = 0; return token::TK_IVAL; } {id} { yylval->sval = new std::string(yytext); return token::TK_IDENTIFIER; } . driver.error(*yylloc, "この文字を識別子で使用することはできません。"); } { \n { yylloc->lines(); driver.error(*yylloc, "文字列がとじられていません"); string_buffer.clear(); BEGIN(INITIAL); } <> { driver.error(*yylloc, "文字列の途中でファイルが終了しました"); string_buffer.clear(); BEGIN(INITIAL); } ([\x81-\x9f\xe0-\xef][\x40-\x7e\x80-\xfc])+ { string_buffer += yytext; } [^\\\n"]+ { string_buffer += yytext; } \\\n yylloc->lines(); \\[^\n] { switch (yytext[yyleng-1]) { case 'n': string_buffer += '\n'; break; default: string_buffer += yytext[yyleng-1]; break; } } \" { BEGIN(INITIAL); yylval->sval = new std::string(string_buffer); return token::TK_SVAL; } } { [^\n]* \n { yylloc->lines(); yylloc->step(); BEGIN(INITIAL); } } { [^*\n]* [^*\n]*\n { yylloc->lines(); } "*"+[^*/\n]* /* 余分な*を探す */ "*"+[^*/\n]*\n { yylloc->lines(); } <> driver.error(*yylloc, "コメントの途中でファイルが終了しました"); "*"+"/" BEGIN(INITIAL); } %% void compiler::scan_begin() { if ((yyin = fopen(file.c_str(), "r")) == 0) error(file + " がオープンできません。"); } void compiler::scan_end() { fclose(yyin); yylex_destroy(); }