Do not include yyoutput in the generated lexer
[gnome.gobject-introspection] / giscanner / scannerlexer.l
1 /* -*- Mode: C -*-
2  * GObject introspection: C lexer
3  *
4  * Copyright (c) 1997 Sandro Sigala  <ssigala@globalnet.it>
5  * Copyright (c) 2007-2008 Jürg Billeter  <j@bitron.ch>
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 %{
31 #include <ctype.h>
32 #include <stdio.h>
33
34 #include <glib.h>
35 #include "sourcescanner.h"
36 #include "scannerparser.h"
37 #include "grealpath.h"
38
39 int lineno;
40
41 #undef YY_BUF_SIZE
42 #define YY_BUF_SIZE 1048576
43
44 extern int yylex (GISourceScanner *scanner);
45 #define YY_DECL int yylex (GISourceScanner *scanner)
46 static int yywrap (void);
47 static void parse_comment (GISourceScanner *scanner);
48 static void process_directive (GISourceScanner *scanner);
49 static int check_identifier (GISourceScanner *scanner, const char *);
50 static int parse_ignored_macro (void);
51 %}
52
53 %option nounput
54
55 intsuffix                               ([uU][lL]?[lL]?)|([lL][lL]?[uU]?)
56 fracconst                               ([0-9]*\.[0-9]+)|([0-9]+\.)
57 exppart                                 [eE][-+]?[0-9]+
58 floatsuffix                             [fFlL]
59 chartext                                ([^\\\'])|(\\.) 
60 stringtext                              ([^\\\"])|(\\.)
61
62 %%
63
64 "\n"                                    { ++lineno; } /* " */
65 "\\\n"                                  { ++lineno; }
66 [\t\f\v\r ]+                            { /* Ignore whitespace. */ }
67
68 "/*"                                    { parse_comment(scanner); }
69 "//".*                                  { }
70
71 "#define "[a-zA-Z_][a-zA-Z_0-9]*"("     { yyless (yyleng - 1); return FUNCTION_MACRO; }
72 "#define "[a-zA-Z_][a-zA-Z_0-9]*        { return OBJECT_MACRO; }
73
74 "#"                                     { process_directive(scanner); }
75
76 "{"                                     { return '{'; }
77 "<%"                                    { return '{'; }
78 "}"                                     { return '}'; }
79 "%>"                                    { return '}'; }
80 "["                                     { return '['; }
81 "<:"                                    { return '['; }
82 "]"                                     { return ']'; }
83 ":>"                                    { return ']'; }
84 "("                                     { return '('; }
85 ")"                                     { return ')'; }
86 ";"                                     { return ';'; }
87 ":"                                     { return ':'; }
88 "..."                                   { return ELLIPSIS; }
89 "?"                                     { return '?'; }
90 "."                                     { return '.'; }
91 "+"                                     { return '+'; }
92 "-"                                     { return '-'; }
93 "*"                                     { return '*'; }
94 "/"                                     { return '/'; }
95 "%"                                     { return '%'; }
96 "^"                                     { return '^'; }
97 "&"                                     { return '&'; }
98 "|"                                     { return '|'; }
99 "~"                                     { return '~'; }
100 "!"                                     { return '!'; }
101 "="                                     { return '='; }
102 "<"                                     { return '<'; }
103 ">"                                     { return '>'; }
104 "+="                                    { return ADDEQ; }
105 "-="                                    { return SUBEQ; }
106 "*="                                    { return MULEQ; }
107 "/="                                    { return DIVEQ; }
108 "%="                                    { return MODEQ; }
109 "^="                                    { return XOREQ; }
110 "&="                                    { return ANDEQ; }
111 "|="                                    { return OREQ; }
112 "<<"                                    { return SL; }
113 ">>"                                    { return SR; }
114 "<<="                                   { return SLEQ; }
115 ">>="                                   { return SREQ; }
116 "=="                                    { return EQ; }
117 "!="                                    { return NOTEQ; }
118 "<="                                    { return LTEQ; }
119 ">="                                    { return GTEQ; }
120 "&&"                                    { return ANDAND; }
121 "||"                                    { return OROR; }
122 "++"                                    { return PLUSPLUS; }
123 "--"                                    { return MINUSMINUS; }
124 ","                                     { return ','; }
125 "->"                                    { return ARROW; }
126
127 "__asm"                                 { if (!parse_ignored_macro()) REJECT; }
128 "__asm__"                               { if (!parse_ignored_macro()) REJECT; }
129 "__attribute__"                         { if (!parse_ignored_macro()) REJECT; }
130 "__attribute"                           { if (!parse_ignored_macro()) REJECT; }
131 "__const"                               { return CONST; }
132 "__extension__"                         { return EXTENSION; }
133 "__inline"                              { return INLINE; }
134 "__nonnull"                             { if (!parse_ignored_macro()) REJECT; }
135 "__signed__"                            { return SIGNED; }
136 "__restrict"                            { return RESTRICT; }
137 "__typeof"                              { if (!parse_ignored_macro()) REJECT; }
138 "_Bool"                                 { return BOOL; }
139
140 [a-zA-Z_][a-zA-Z_0-9]*                  { if (scanner->macro_scan) return IDENTIFIER; else REJECT; }
141
142 "asm"                                   { if (!parse_ignored_macro()) REJECT; }
143 "auto"                                  { return AUTO; }
144 "break"                                 { return BREAK; }
145 "case"                                  { return CASE; }
146 "char"                                  { return CHAR; }
147 "const"                                 { return CONST; }
148 "continue"                              { return CONTINUE; }
149 "default"                               { return DEFAULT; }
150 "do"                                    { return DO; }
151 "double"                                { return DOUBLE; }
152 "else"                                  { return ELSE; }
153 "enum"                                  { return ENUM; }
154 "extern"                                { return EXTERN; }
155 "float"                                 { return FLOAT; }
156 "for"                                   { return FOR; }
157 "goto"                                  { return GOTO; }
158 "if"                                    { return IF; }
159 "inline"                                { return INLINE; }
160 "int"                                   { return INT; }
161 "long"                                  { return LONG; }
162 "register"                              { return REGISTER; }
163 "restrict"                              { return RESTRICT; }
164 "return"                                { return RETURN; }
165 "short"                                 { return SHORT; }
166 "signed"                                { return SIGNED; }
167 "sizeof"                                { return SIZEOF; }
168 "static"                                { return STATIC; }
169 "struct"                                { return STRUCT; }
170 "switch"                                { return SWITCH; }
171 "typedef"                               { return TYPEDEF; }
172 "union"                                 { return UNION; }
173 "unsigned"                              { return UNSIGNED; }
174 "void"                                  { return VOID; }
175 "volatile"                              { return VOLATILE; }
176 "while"                                 { return WHILE; }
177
178 [a-zA-Z_][a-zA-Z_0-9]*                  { return check_identifier(scanner, yytext); }
179
180 "0"[xX][0-9a-fA-F]+{intsuffix}?         { return INTEGER; }
181 "0"[0-7]+{intsuffix}?                   { return INTEGER; }
182 [0-9]+{intsuffix}?                      { return INTEGER; }
183
184 {fracconst}{exppart}?{floatsuffix}?     { return FLOATING; }
185 [0-9]+{exppart}{floatsuffix}?           { return FLOATING; }
186
187 "'"{chartext}*"'"                       { return CHARACTER; }
188 "L'"{chartext}*"'"                      { return CHARACTER; }
189
190 "\""{stringtext}*"\""                   { return STRING; }
191 "L\""{stringtext}*"\""                  { return STRING; }
192
193 .                                       { fprintf(stderr, "%s:%d: unexpected character `%c'\n", scanner->current_filename, lineno, yytext[0]); }
194
195 %%
196
197 static int
198 yywrap (void)
199 {
200   return 1;
201 }
202
203
204 static void
205 parse_comment (GISourceScanner *scanner)
206 {
207   GString *comment;
208   int c1, c2;
209
210   c1 = input();
211   c2 = input();
212
213   comment = g_string_new ("");
214
215   while (c2 != EOF && !(c1 == '*' && c2 == '/'))
216     {
217       g_string_append_c (comment, c1);
218
219       c1 = c2;
220       c2 = input();
221
222     }
223
224   scanner->comments = g_slist_prepend (scanner->comments,
225                                        g_string_free (comment, FALSE));
226 }
227
228 static int
229 check_identifier (GISourceScanner *scanner,
230                   const char  *s)
231 {
232         /*
233          * This function checks if `s' is a type name or an
234          * identifier.
235          */
236
237         if (gi_source_scanner_is_typedef (scanner, s)) {
238                 return TYPEDEF_NAME;
239         } else if (strcmp (s, "__builtin_va_list") == 0) {
240                 return TYPEDEF_NAME;
241         }
242
243         return IDENTIFIER;
244 }
245
246 static void
247 process_directive (GISourceScanner *scanner)
248 {
249         /* extract current filename from #line directives */
250         GString *filename_builder;
251         gboolean in_string, found_filename;
252
253         lineno = 0;
254         found_filename = FALSE;
255         in_string = FALSE;
256         filename_builder = g_string_new ("");
257
258         int c = input ();
259         while (c != EOF && c != '\n') {
260                 if (!in_string) {
261                         if (c == '\"') {
262                                 in_string = TRUE;
263                                 found_filename = TRUE;
264                         } else if (c >= '0' && c <= '9') {
265                                 if (!found_filename) {
266                                         lineno = lineno * 10 + (c - '0');
267                                 }
268                         }
269                 } else {
270                         if (c == '\"') {
271                                 in_string = FALSE;
272                         } else if (c == '\\') {
273                                 g_string_append_c (filename_builder, c);
274                                 c = input ();
275                                 g_string_append_c (filename_builder, c);
276                         } else {
277                                 g_string_append_c (filename_builder, c);
278                         }
279                 }
280                 c = input ();
281         }
282
283         if (filename_builder->len > 0) {
284                 char *filename = g_strcompress (filename_builder->str);
285                 if (g_realpath (filename))
286                   {
287                     g_free (scanner->current_filename);
288                     scanner->current_filename = g_realpath (filename);
289                     g_assert (scanner->current_filename);
290                     g_free(filename);
291                   }
292         }
293
294         g_string_free (filename_builder, TRUE);
295 }
296
297 /*
298  * This parses a macro which is ignored, such as
299  * __attribute__((x)) or __asm__ (x)
300  */
301 static int
302 parse_ignored_macro (void)
303 {
304         int c;
305         int nest;
306
307         while ((c = input ()) != EOF && isspace (c))
308                 ;
309         if (c != '(')
310                 return FALSE;
311
312         nest = 0;
313         while ((c = input ()) != EOF && (nest > 0 || c != ')')) {
314                 if (c == '(')
315                         nest++;
316                 else if (c == ')')
317                         nest--;
318                 else if (c == '"') {
319                         while ((c = input ()) != EOF && c != '"') {
320                                 if (c == '\\')
321                                         c = input ();
322                         }
323                 } else if (c == '\'') {
324                         c = input ();
325                         if (c == '\\')
326                                 c = input ();
327                         else if (c == '\'')
328                                 return FALSE;
329                         c = input ();
330                         if (c != '\'')
331                                 return FALSE;
332                 } else if (c == '\n')
333                         lineno++;
334         }
335
336         return TRUE;
337 }