X-Git-Url: https://git.draconx.ca/gitweb/cdecl99.git/blobdiff_plain/f5e2e659f116a49afd3b9d9f37553646e62fa4d4..9abf0eb2e74d0fb3a4f652499571cb35697d3036:/src/scan.l diff --git a/src/scan.l b/src/scan.l index f2e92a8..1688873 100644 --- a/src/scan.l +++ b/src/scan.l @@ -1,7 +1,7 @@ %top{ /* * Scanner for C declarations. - * Copyright © 2011 Nick Bowler + * Copyright © 2011, 2021, 2023 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 @@ -17,70 +17,153 @@ * along with this program. If not, see . */ - #include "parse.h" +#include +#include "parse.h" } -%option noyywrap bison-locations +%option nodefault noyywrap bison-locations reentrant never-interactive +%option extra-type="_Bool" +%option prefix="cdecl__yy" %{ -#define lex_error(msg) do { \ - yyerror(yylloc, NULL, (msg)); \ +#include +#include "cdecl-internal.h" +#include "cdecl.h" + +#if HAVE_STRTOUMAX +/* Best case, implementation provides strtoumax. */ +# define STRTOUMAX strtoumax +#elif HAVE_STRTOULL +/* Fall back to strtoull, with possibly reduced range. */ +#define STRTOUMAX strtoull +#elif HAVE___STRTOULL +/* HP-UX 11 has __strtoull in */ +#define STRTOUMAX __strtoull +#else +/* Fall back to strtoul, with possibly reduced range. */ +#define STRTOUMAX strtoul +#endif + +#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:]]+ %% -";" 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; - -"struct" return T_STRUCT; -"union" return T_UNION; -"enum" return T_ENUM; - -{IDENT} { - yylval->strval = malloc(yyleng+1); - if (!yylval->strval) - lex_error("failed to allocate memory"); - - strcpy(yylval->strval, yytext); - return T_IDENT; +%{ + 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[] = "syntax error, unexpected #"; - *strchr(buf, '#') = *yytext; - lex_error(buf); + 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); }