%{ // IDL/CDL scanner // // This software is copyright (c) 2006 Scott Wood . // // This software is provided 'as-is', without any express or implied warranty. // In no event will the authors or contributors be held liable for any damages // arising from the use of this software. // // Permission is hereby granted to everyone, free of charge, to use, copy, // modify, prepare derivative works of, publish, distribute, perform, // sublicense, and/or sell copies of the Software, provided that the above // copyright notice and disclaimer of warranty be included in all copies or // substantial portions of this software. #include #include #include #include #include #include #include #include int curline, comment_level=0; %} %x COMMENT %x STRING %x LINECOMMENT %% interface return TOK_IFACE; const return TOK_CONST; \( return '('; \) return ')'; bool return TOK_BOOL; ushort return TOK_USHORT; uint return TOK_UINT; ulong return TOK_ULONG; short return TOK_SHORT; int return TOK_INT; long return TOK_LONG; fshort return TOK_FSHORT; flong return TOK_FLONG; struct return TOK_STRUCT; char return TOK_CHAR; octet return TOK_OCTET; \{ return '{'; \} return '}'; : return ':'; \[ return '['; \] return ']'; \; return ';'; = return '='; \, return ','; \< return '<'; \> return '>'; \.\.\. return TOK_3DOT; \.\. return TOK_2DOT; \. return '.'; \* return '*'; - return '-'; bitfield return TOK_BITFIELD; enum return TOK_ENUM; namespace return TOK_NAMESPACE; using return TOK_USING; async return TOK_ASYNC; out return TOK_OUT; inout return TOK_INOUT; shared return TOK_SHARED; push return TOK_PUSH; typedef return TOK_TYPEDEF; alias return TOK_ALIAS; upcast return TOK_INVALID; downcast return TOK_INVALID; ifaceref return TOK_INVALID; virtual return TOK_VIRTUAL; guid return TOK_GUID; inline return TOK_INLINE; static return TOK_STATIC; immutable return TOK_IMMUTABLE; true return TOK_TRUE; false return TOK_FALSE; name return TOK_NAME; // CDL tokens method return TOK_METHOD; class return TOK_CLASS; copy return TOK_COPY; <*>\r // Put up with DOS files [[:alpha:]][[:alnum:]_]* { // Leading underscores and digits are prohibited by the regex. if (yytext[yyleng - 1] == '_') { yyerrorf("Identifier \"%s\" has a trailing underscore.", yytext); } else if (strstr(yytext, "__")) { yyerrorf("Identifier \"%s\" has contiguous underscores.", yytext); } else if (!strncmp(yytext, "IDL_", 4)) { yyerrorf("Identifier \"%s\" begins with the reserved " "\"IDL_\" prefix.", yytext); } else if (strstr(yytext, "IDLNS")) { yyerrorf("Identifier \"%s\" contains the reserved sequence " "\"IDLNS\".", yytext); } else if (!strcmp(yytext + yyleng - 3, "_ns")) { yyerrorf("Identifier \"%s\" ends with the reserved suffix \"_ns\".", yytext); } *yylval_string = new String(yytext, cur_input_file, curline, TOK_IDENT); return TOK_IDENT; } 0[0-9]+ { errno = 0; if (strchr(yytext, '8') || strchr(yytext, '9')) { yyerrorf("Invalid digit in octal constant %s.", yytext); yylval_con->type = TOK_INVALID; yylval_con->con.ucon = 0; return TOK_INVALID; } yylval_con->con.ucon = strtoull(yytext, NULL, 8); if (errno == ERANGE) { yyerrorf("Constant %s is out of range.", yytext); yylval_con->type = TOK_INVALID; yylval_con->con.ucon = 0; } else if (yylval_con->con.ucon > LLONG_MAX) { yylval_con->type = TOK_UCON; } else { yylval_con->type = TOK_ICON; } return yylval_con->type; } 0x[0-9a-f]+ { errno = 0; yylval_con->con.ucon = strtoull(yytext, NULL, 16); if (errno == ERANGE) { yyerrorf("Constant %s is out of range.", yytext); yylval_con->type = TOK_INVALID; yylval_con->con.ucon = 0; } else if (yylval_con->con.ucon > LLONG_MAX) { yylval_con->type = TOK_UCON; } else { yylval_con->type = TOK_ICON; } return yylval_con->type; } [0-9]+ { errno = 0; yylval_con->con.ucon = strtoull(yytext, NULL, 10); if (errno == ERANGE) { yyerrorf("Constant %s is out of range.", yytext); yylval_con->type = TOK_INVALID; yylval_con->con.ucon = 0; } else if (yylval_con->con.ucon > LLONG_MAX) { yylval_con->type = TOK_UCON; } else { yylval_con->type = TOK_ICON; } return yylval_con->type; } [0-9]*\.[0-9]+([eE][+-][0-9]+)? { errno = 0; yylval_con->con.fcon = strtod(yytext, NULL); if (errno == ERANGE) { yyerrorf("Constant %s is out of range.", yytext); yylval_con->con.fcon = 0; yylval_con->type = TOK_INVALID; } else { yylval_con->type = TOK_FCON; } return yylval_con->type; } \" { BEGIN(STRING); *yylval_string = new String("", cur_input_file, curline, TOK_STR); } { \" { BEGIN(INITIAL); return TOK_STR; } \\\" **yylval_string += '"'; \\\n **yylval_string += '\n'; \\\\ **yylval_string += '\\'; \\. { yyerrorf("Unknown escape sequence '\\%c'.", yytext[1]); **yylval_string += yytext[1]; } \n { yyerrorf("Unterminated string literal at line %d.", curline); BEGIN(INITIAL); curline++; } [^\\\"\n]+ **yylval_string += yytext; } "/*" { comment_level = 1; BEGIN(COMMENT); } { "/*" comment_level++; "*/" if (!(--comment_level)) BEGIN(INITIAL); \n curline++; \*+[^/*\n]* \/+[^/*\n]* [^/*\n]+ } "//" BEGIN(LINECOMMENT); \n { BEGIN(INITIAL); curline++; } [^\n]+ [[:blank:]]+ /* Whitespace */ \n curline++; <> { if (comment_level) { yyerrorf("End of file within comment."); // Keep message from occurring twice if parse is OK comment_level = 0; } return 0; } . { if (isprint(yytext[0])) yyerrorf("Unexpected character '%c'.", yytext[0]); else yyerrorf("Unexpected character #%d.", yytext[0]); } %% int finish_lex() { if (comment_level) yyerrorf("End of file within comment."); return 0; }