]> git.draconx.ca Git - gob-dx.git/blob - src/lexer.l
Release 0.93.1
[gob-dx.git] / src / lexer.l
1 /* GOB C Preprocessor
2  * Copyright (C) 1999 the Free Software Foundation.
3  *
4  * Author: George Lebl
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 2 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, write to the  Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19  * USA.
20  */
21 %{
22
23 #include "config.h"
24 #include <glib.h>
25 #include <string.h>
26
27 #include "tree.h"
28 #include "parse.h"
29 #include "main.h"
30 #include "util.h"
31
32 static int parenth_depth = 0;
33 static int before_comment = INITIAL;
34 static gboolean class_after_c = FALSE;
35 static int code_type = CCODE;
36
37 /* GTK+ doc stuff */
38 static char *gtk_doc_func = NULL; /* current gtk-doc func */
39 GHashTable *gtk_doc_hash = NULL;
40
41 static GString *cbuf = NULL;
42 int ccode_line = 1;
43
44 GList *include_files = NULL;
45 /* 0 no, 1 means yes, 2+ means don't even start looking anymore */
46 static int look_for_includes = 0;
47
48 int line_no = 1;
49
50 static void
51 clear_cbuf(void)
52 {
53         if(!cbuf) {
54                 cbuf = g_string_new("");
55         } else {
56                 cbuf = g_string_assign(cbuf,"");
57         }
58 }
59
60 static void
61 add_to_cbuf(char *s)
62 {
63         if(!cbuf) {
64                 cbuf = g_string_new(s);
65         } else {
66                 cbuf = g_string_append(cbuf,s);
67         }
68 }
69
70 static void
71 add_gtk_doc_func(void)
72 {
73         if(!gtk_doc_func)
74                 return;
75
76         if(!gtk_doc_hash)
77                 gtk_doc_hash = g_hash_table_new(g_str_hash, g_str_equal);
78         g_hash_table_insert(gtk_doc_hash, gtk_doc_func, g_strdup(cbuf->str));
79         clear_cbuf();
80
81         gtk_doc_func = NULL;
82 }
83
84
85 %}
86
87 %x COMMENT
88 %x C_CODE
89 %x C_CODE_STRING
90 %x CLASS_CODE
91 %x CLASS_CODE_I
92 %x GTK_DOC_BEFORE_NAME
93 %x GTK_DOC
94 %x GTK_DOC_LINE
95
96 %%
97
98 <*>\n                   { line_no++; REJECT; }
99
100 <*>MOTHERFUCKER         { fprintf(stderr,"You are a bad bad person!\n"); REJECT; }
101
102 \/\/.*$                 { ; /*comment, ignore*/ }
103 <C_CODE>^#[ \t]*include[ \t][<"][^\n">]*[>"] {
104         if(look_for_includes==1) {
105                 char *p;
106                 char *file;
107                 char *str = g_strdup(yytext);
108                 file = strchr(str,'"');
109                 if(!file) file = strchr(str,'<');
110                 file++;
111                 p = strchr(file,'"');
112                 if(!p) p = strchr(file,'>');
113                 *p = '\0';
114                 include_files = g_list_prepend(include_files,g_strdup(file));
115                 g_free(str);
116         }
117         REJECT;
118 }
119
120 <CLASS_CODE_I>\/\*\*[ \t]*$     {
121                         /* eat out gtk doc stuff */
122                         BEGIN(GTK_DOC_BEFORE_NAME);
123                         clear_cbuf();
124                 }
125 <GTK_DOC_BEFORE_NAME>^[ \t]*\*[ \t]*$   {
126                         /* empty doc lines */
127                         ;
128                 }       
129 <GTK_DOC_BEFORE_NAME>^[ \t]*\*\ [_a-zA-Z][_a-zA-Z0-9]*:?[ \t]*$ {
130                         char *p;
131                         BEGIN(GTK_DOC);
132                         p = strchr(yytext, '*');
133                         g_free(gtk_doc_func);
134                         gtk_doc_func = g_strdup(p+2);
135                         p = strchr(gtk_doc_func, ':');
136                         if(p) *p='\0';
137                         g_strstrip(gtk_doc_func);
138                 }
139 <GTK_DOC_BEFORE_NAME>\*\/       {
140                         BEGIN(CLASS_CODE_I);
141                 }
142 <GTK_DOC_BEFORE_NAME>.  {
143                         BEGIN(COMMENT);
144                         before_comment = CLASS_CODE_I;
145                 }
146 <GTK_DOC>^[ \t]*\*[ \t]*$       {
147                         /* empty doc lines */
148                         add_to_cbuf(" *\n");
149                 }       
150 <GTK_DOC>^[ \t]*\*?\*\/ {
151                         BEGIN(CLASS_CODE_I);
152                         add_gtk_doc_func();
153                 }
154 <GTK_DOC>^[ \t]*\*\     {
155                         fflush(stdout);
156                         add_to_cbuf(" * ");
157                         BEGIN(GTK_DOC_LINE);
158                 }
159 <GTK_DOC>\*\/   {
160                         BEGIN(CLASS_CODE_I);
161                 }
162 <GTK_DOC>.      {
163                         BEGIN(COMMENT);
164                         before_comment = CLASS_CODE_I;
165                 }
166 <GTK_DOC_LINE>\*\/      {
167                         BEGIN(CLASS_CODE_I);
168                         add_to_cbuf("\n");
169                         add_gtk_doc_func();
170                 }
171 <GTK_DOC_LINE>.$        {
172                         BEGIN(GTK_DOC);
173                         add_to_cbuf(yytext);
174                         add_to_cbuf("\n");
175                 }
176 <GTK_DOC_LINE>. {
177                         fflush(stdout);
178                         add_to_cbuf(yytext);
179                 }
180
181 <C_CODE>\/\/.*$         { add_to_cbuf(yytext); /*comment, ignore*/ }
182 <CLASS_CODE>\/\/.*$     { ; /*comment, ignore*/ }
183 <CLASS_CODE_I>\/\/.*$   { ; /*comment, ignore*/ }
184 \/\*            {BEGIN(COMMENT); before_comment = INITIAL; }
185 <C_CODE>\/\*    {
186         add_to_cbuf(yytext);
187         BEGIN(COMMENT);
188         before_comment = C_CODE;
189 }
190 <CLASS_CODE>\/\*        {BEGIN(COMMENT); before_comment = CLASS_CODE; }
191 <CLASS_CODE_I>\/\*      {BEGIN(COMMENT); before_comment = CLASS_CODE_I; }
192 <COMMENT>\*\/   {
193         if(before_comment == C_CODE) add_to_cbuf(yytext);
194         BEGIN(before_comment);
195                 }
196 <COMMENT>.      {
197         /* comment, ignore */
198         if(before_comment == C_CODE) add_to_cbuf(yytext);
199                 }
200 <COMMENT>\n     {
201         /* comment, ignore */
202         if(before_comment == C_CODE) add_to_cbuf(yytext);
203                 }
204
205 ^\%(a|all)\{            {
206                         BEGIN(C_CODE);
207                         parenth_depth = 1;
208                         class_after_c = FALSE;
209                         code_type = ACODE;
210                         clear_cbuf();
211                         ccode_line = line_no;
212                 }
213 ^\%(at|alltop)\{                {
214                         BEGIN(C_CODE);
215                         parenth_depth = 1;
216                         class_after_c = FALSE;
217                         code_type = ATCODE;
218                         clear_cbuf();
219                         ccode_line = line_no;
220                 }
221
222 ^\%(ht|headertop)\{             {
223                         BEGIN(C_CODE);
224                         parenth_depth = 1;
225                         class_after_c = FALSE;
226                         code_type = HTCODE;
227                         clear_cbuf();
228                         ccode_line = line_no;
229                 }
230 ^\%(ph|privateheader)\{         {
231                         BEGIN(C_CODE);
232                         parenth_depth = 1;
233                         class_after_c = FALSE;
234                         code_type = PHCODE;
235                         clear_cbuf();
236                         ccode_line = line_no;
237                 }
238 ^\%(h|header)\{         {
239                         BEGIN(C_CODE);
240                         parenth_depth = 1;
241                         class_after_c = FALSE;
242                         code_type = HCODE;
243                         clear_cbuf();
244                         ccode_line = line_no;
245                 }
246 ^\%\{           {
247                         BEGIN(C_CODE);
248                         parenth_depth = 1;
249                         class_after_c = FALSE;
250                         code_type = CCODE;
251                         clear_cbuf();
252                         ccode_line = line_no;
253                         if(look_for_includes==0)
254                                 look_for_includes=1;
255                 }
256 <C_CODE>^\%\}   {
257                         BEGIN(INITIAL);
258                         yylval.cbuf = cbuf;
259                         cbuf = NULL;
260                         if(look_for_includes==1)
261                                 look_for_includes=0;
262                         return code_type;
263                 }
264
265 <C_CODE>\'\{\'          { add_to_cbuf(yytext); }
266 <C_CODE>\'\\\{\'        { add_to_cbuf(yytext); }
267 <C_CODE>\'\}\'          { add_to_cbuf(yytext); }
268 <C_CODE>\'\\\}\'        { add_to_cbuf(yytext); }
269 <C_CODE>\'\"\'          { add_to_cbuf(yytext); }
270 <C_CODE>\'\\\"\'        { add_to_cbuf(yytext); }
271         
272 <C_CODE>\\.     { add_to_cbuf(yytext); }
273 <C_CODE>\"      {
274                         BEGIN(C_CODE_STRING);
275                         add_to_cbuf(yytext);
276                 }
277 <C_CODE_STRING>\\.      { add_to_cbuf(yytext); }
278 <C_CODE_STRING>\"       {
279                                 BEGIN(C_CODE);
280                                 add_to_cbuf(yytext);
281                         }
282 <C_CODE_STRING>.        { add_to_cbuf(yytext); }
283 <C_CODE_STRING>\n       { add_to_cbuf(yytext); }
284
285 <C_CODE>\{      {
286                         parenth_depth++;
287                         add_to_cbuf(yytext);
288                 }
289 <C_CODE>\}      {
290                         parenth_depth--;
291                         if(parenth_depth<0) {
292                                 REJECT;
293                         } else if(parenth_depth==0 && class_after_c) {
294                                 BEGIN(CLASS_CODE_I);
295                                 yylval.cbuf = cbuf;
296                                 cbuf = NULL;
297                                 return CCODE;
298                         }
299                         add_to_cbuf(yytext);
300                 }
301
302 <C_CODE>.       { add_to_cbuf(yytext); }
303 <C_CODE>\n      { add_to_cbuf(yytext); }
304
305 class           {
306                         static int found_classes = 0;
307                         look_for_includes = 2;
308                         BEGIN(CLASS_CODE);
309
310                         if(++found_classes > 1) {
311                                 print_error(FALSE, 
312                                             "Only one class per file allowed",
313                                             line_no);
314                         }
315
316                         return CLASS;
317                 }
318
319 ^[ \t]*requires[ \t]+[0-9]+\.[0-9]+\.[0-9]+[\t ]*$      {
320                         int maj = 0,min = 0,pl = 0;
321                         int rmaj = 0,rmin = 0,rpl = 0;
322                         char *p;
323                         
324                         sscanf(VERSION,"%d.%d.%d",&rmaj,&rmin,&rpl);
325                         p = strchr(yytext,'r');
326                         g_assert(p); /* we MUST have found it */
327                         sscanf(p,"requires %d.%d.%d",&maj,&min,&pl);
328                         if(rmaj < maj ||
329                            (rmaj == maj && rmin < min) ||
330                            (rmaj == maj && rmin == min && rpl < pl)) {
331                                 char *s;
332                                 s = g_strdup_printf(
333                                     "GOB version %d.%d.%d required "
334                                     "(this is %s)\n"
335                                     "To upgrade your gob, see: "
336                                     "http://www.5z.com/jirka/gob.html",
337                                     maj,min,pl,VERSION);
338                                 print_error(FALSE, s, line_no);
339                                 g_free(s);
340                         }
341                 }
342
343 <CLASS_CODE,CLASS_CODE_I>class|this     {
344                         if(for_cpp) {
345                                 char *s;
346                                 s = g_strdup_printf("'%s' keyword should not "
347                                                     "be used when generating "
348                                                     "C++ code",yytext);
349                                 print_error(TRUE, s, line_no);
350                                 g_free(s);
351                         }
352                         REJECT;
353                 }
354
355 <CLASS_CODE>from        {return FROM;}
356
357 <CLASS_CODE_I>void      {return VOID;}
358 <CLASS_CODE_I>struct    {return STRUCT;}
359 <CLASS_CODE_I>union     {return UNION;}
360 <CLASS_CODE_I>enum      {return ENUM;}
361 <CLASS_CODE_I>signed    {return SIGNED;}
362 <CLASS_CODE_I>unsigned  {return UNSIGNED;}
363 <CLASS_CODE_I>long      {return LONG;}
364 <CLASS_CODE_I>short     {return SHORT;}
365 <CLASS_CODE_I>int       {return INT;}
366 <CLASS_CODE_I>float     {return FLOAT;}
367 <CLASS_CODE_I>double    {return DOUBLE;}
368 <CLASS_CODE_I>char      {return CHAR;}
369 <CLASS_CODE_I>const     {return CONST;}
370
371 <CLASS_CODE_I>\.\.\.    {return THREEDOTS;}
372
373 <CLASS_CODE_I>public    {yylval.line = line_no; return PUBLIC;}
374 <CLASS_CODE_I>private   {yylval.line = line_no; return PRIVATE;}
375 <CLASS_CODE_I>protected {yylval.line = line_no; return PROTECTED;}
376 <CLASS_CODE_I>argument  {yylval.line = line_no; return ARGUMENT;}
377 <CLASS_CODE_I>virtual   {yylval.line = line_no; return VIRTUAL;}
378 <CLASS_CODE_I>signal    {yylval.line = line_no; return SIGNAL;}
379 <CLASS_CODE_I>override  {yylval.line = line_no; return OVERRIDE;}
380 <CLASS_CODE_I>onerror   {return ONERROR;}
381 <CLASS_CODE_I>0|[1-9][0-9]*|0x[0-9a-fA-F]+|0[0-7]+|[0-9]*\.[0-9]+|\.[0-9][0-9]* {
382                         yylval.id = g_strdup(yytext);
383                         return NUMBER;
384                 }
385 <CLASS_CODE,CLASS_CODE_I>[A-Za-z_][A-Za-z0-9_]*(:[A-Za-z0-9_]*)+        {
386                         /* this one is for a classname with a namespace */
387                         yylval.id = g_strdup(yytext);
388                         return TYPETOKEN;
389                 }
390 <CLASS_CODE,CLASS_CODE_I>:[A-Za-z_][A-Za-z0-9_]*(:[A-Za-z0-9_]*)*       {
391                         /* this is for a classname with an empty namespace */
392                         yylval.id = g_strdup(yytext);
393                         return TYPETOKEN;
394                 }
395 <CLASS_CODE,CLASS_CODE_I>[A-Za-z_][A-Za-z0-9_]* {
396                         yylval.id = g_strdup(yytext);
397                         return TOKEN;
398                 }
399
400 <CLASS_CODE_I>(\[[0-9]*\])+     {
401                         yylval.id = g_strdup(yytext);
402                         return ARRAY_DIM;
403                 }
404
405 <CLASS_CODE>\{  {
406                         BEGIN(CLASS_CODE_I);
407                         return '{';
408                 }
409 <CLASS_CODE_I>\{        {
410                         BEGIN(C_CODE);
411                         parenth_depth=1;
412                         class_after_c = TRUE;
413                         yylval.line = line_no;
414                         clear_cbuf();
415                         ccode_line = line_no;
416                         return '{';
417                 }
418 <CLASS_CODE_I>\}        {
419                                 BEGIN(INITIAL);
420                                 return '}';
421                         }
422
423 <CLASS_CODE,CLASS_CODE_I,INITIAL>[\t ]  ;  /*ignore*/
424
425 <*>.            {
426                         yylval.line = line_no;
427                         return yytext[0];
428                 }
429
430 <*>[\n\r]       ;  /*ignore*/