]> git.draconx.ca Git - cdecl99.git/blob - src/scan.l
Rework library error reporting.
[cdecl99.git] / src / scan.l
1 %top{
2 /*
3  *  Scanner for C declarations.
4  *  Copyright © 2011 Nick Bowler
5  *
6  *  This program is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include "parse.h"
22 }
23
24 %option nodefault noyywrap bison-locations reentrant never-interactive
25 %option extra-type="_Bool"
26 %option prefix="cdecl__yy"
27
28 %{
29 #include <ctype.h>
30 #include "cdecl-internal.h"
31 #include "cdecl.h"
32
33 #define lex_error(...) do { \
34         cdecl__err(CDECL_ENOPARSE, __VA_ARGS__); \
35         return T_LEX_ERROR; \
36 } while(0)
37
38 #define dup_token() do { \
39         yylval->strval = malloc(yyleng+1); \
40         if (!yylval->strval) { \
41                 cdecl__err(CDECL_ENOMEM); \
42                 return T_LEX_ERROR; \
43         } \
44         strcpy(yylval->strval, yytext); \
45 } while(0)
46 %}
47
48 %s ENGLISH
49
50 IDENT [_[:alpha:]][_[:alnum:]]*
51 INTEGER 0x[[:xdigit:]]+|0[0-7]+|[[:digit:]]+
52
53 %%
54
55 %{
56         if (yyextra) {
57                 yyextra = 0;
58                 BEGIN(ENGLISH);
59                 return T_ENGLISH;
60         }
61 %}
62
63 "..." return T_ELLIPSIS;
64 ";"   return T_SEMICOLON;
65 "*"   return T_ASTERISK;
66 "("   return T_LPAREN;
67 ")"   return T_RPAREN;
68 "["   return T_LBRACKET;
69 "]"   return T_RBRACKET;
70 ","   return T_COMMA;
71
72 "typedef"    return T_TYPEDEF;
73 "extern"     return T_EXTERN;
74 "static"     return T_STATIC;
75 "auto"       return T_AUTO;
76 "register"   return T_REGISTER;
77
78 "restrict"   return T_RESTRICT;
79 "volatile"   return T_VOLATILE;
80 "const"      return T_CONST;
81
82 "inline"     return T_INLINE;
83
84 "void"       return T_VOID;
85 "char"       return T_CHAR;
86 "short"      return T_SHORT;
87 "int"        return T_INT;
88 "long"       return T_LONG;
89 "float"      return T_FLOAT;
90 "double"     return T_DOUBLE;
91 "signed"     return T_SIGNED;
92 "unsigned"   return T_UNSIGNED;
93 "_Bool"      return T_BOOL;
94 "_Complex"   return T_COMPLEX;
95 "_Imaginary" return T_IMAGINARY;
96
97 "struct"     return T_STRUCT;
98 "union"      return T_UNION;
99 "enum"       return T_ENUM;
100
101 {INTEGER} {
102         char *end;
103
104         errno = 0;
105         yylval->uintval = strtoumax(yytext, &end, 0);
106         if (errno == ERANGE)
107                 lex_error(_("integer constant out of range"));
108         if (*end)
109                 lex_error(_("invalid integer constant"));
110
111         return T_UINT;
112 }
113
114 <ENGLISH>{
115         "variable-length" return T_VLA;
116         "type"            return T_TYPE;
117         "declare"         return T_DECLARE;
118         "pointer"         return T_POINTER;
119         "function"        return T_FUNCTION;
120         "returning"       return T_RETURNING;
121         "array"           return T_ARRAY;
122         "to"              return T_TO;
123         "of"              return T_OF;
124         "as"              return T_AS;
125 }
126
127 {IDENT} { dup_token(); return T_IDENT; }
128
129 [[:space:]]+
130 . {
131         char buf[5] = { yytext[0] };
132         unsigned char c = buf[0];
133
134         if (!isprint(c) || c == '\\' || c == '\'') {
135                 /* Encode nonprinting characters with C-style escapes */
136                 buf[0] = '\\';
137                 switch (c) {
138                 case '\a': buf[1] = 'a'; break;
139                 case '\b': buf[1] = 'b'; break;
140                 case '\f': buf[1] = 'f'; break;
141                 case '\n': buf[1] = 'n'; break;
142                 case '\r': buf[1] = 'r'; break;
143                 case '\t': buf[1] = 't'; break;
144                 case '\v': buf[1] = 'v'; break;
145                 case '\\': buf[1] = '\\'; break;
146                 case '\'': buf[1] = '\''; break;
147                 default:
148                         buf[1] = '0' + ((c >> 6) & 3);
149                         buf[2] = '0' + ((c >> 3) & 7);
150                         buf[3] = '0' + ((c >> 0) & 7);
151                 }
152         }
153
154         lex_error(_("syntax error, unexpected '%s'"), buf);
155 }