%top{ /* * Scanner for C declarations. * Copyright © 2011 Nick Bowler * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include "parse.h" } %option nodefault noyywrap bison-locations reentrant never-interactive %option extra-type="_Bool" %option prefix="cdecl__yy" %{ #include #include "cdecl-internal.h" #include "cdecl.h" #define lex_error(...) do { \ cdecl__err(CDECL_ENOPARSE, __VA_ARGS__); \ return T_LEX_ERROR; \ } while(0) #define dup_token() do { \ yylval->strval = malloc(yyleng+1); \ if (!yylval->strval) { \ cdecl__err(CDECL_ENOMEM); \ return T_LEX_ERROR; \ } \ strcpy(yylval->strval, yytext); \ } while(0) %} %s ENGLISH IDENT [_[:alpha:]][_[:alnum:]]* INTEGER 0x[[:xdigit:]]+|0[0-7]+|[[:digit:]]+ %% %{ if (yyextra) { yyextra = 0; BEGIN(ENGLISH); return T_ENGLISH; } %} "..." return T_ELLIPSIS; ";" return T_SEMICOLON; "*" return T_ASTERISK; "(" return T_LPAREN; ")" return T_RPAREN; "[" return T_LBRACKET; "]" return T_RBRACKET; "," return T_COMMA; "typedef" return T_TYPEDEF; "extern" return T_EXTERN; "static" return T_STATIC; "auto" return T_AUTO; "register" return T_REGISTER; "restrict" return T_RESTRICT; "volatile" return T_VOLATILE; "const" return T_CONST; "inline" return T_INLINE; "void" return T_VOID; "char" return T_CHAR; "short" return T_SHORT; "int" return T_INT; "long" return T_LONG; "float" return T_FLOAT; "double" return T_DOUBLE; "signed" return T_SIGNED; "unsigned" return T_UNSIGNED; "_Bool" return T_BOOL; "_Complex" return T_COMPLEX; "_Imaginary" return T_IMAGINARY; "struct" return T_STRUCT; "union" return T_UNION; "enum" return T_ENUM; {INTEGER} { char *end; errno = 0; yylval->uintval = strtoumax(yytext, &end, 0); if (errno == ERANGE) lex_error(_("integer constant out of range")); if (*end) lex_error(_("invalid integer constant")); return T_UINT; } { "variable-length" return T_VLA; "type" return T_TYPE; "declare" return T_DECLARE; "pointer" return T_POINTER; "function" return T_FUNCTION; "returning" return T_RETURNING; "array" return T_ARRAY; "to" return T_TO; "of" return T_OF; "as" return T_AS; } {IDENT} { dup_token(); return T_IDENT; } [[:space:]]+ . { char buf[5] = { yytext[0] }; unsigned char c = buf[0]; if (!isprint(c) || c == '\\' || c == '\'') { /* Encode nonprinting characters with C-style escapes */ buf[0] = '\\'; switch (c) { case '\a': buf[1] = 'a'; break; case '\b': buf[1] = 'b'; break; case '\f': buf[1] = 'f'; break; case '\n': buf[1] = 'n'; break; case '\r': buf[1] = 'r'; break; case '\t': buf[1] = 't'; break; case '\v': buf[1] = 'v'; break; case '\\': buf[1] = '\\'; break; case '\'': buf[1] = '\''; break; default: buf[1] = '0' + ((c >> 6) & 3); buf[2] = '0' + ((c >> 3) & 7); buf[3] = '0' + ((c >> 0) & 7); } } lex_error(_("syntax error, unexpected '%s'"), buf); }