]> git.draconx.ca Git - gob-dx.git/blob - src/lexer.l
b3b2d596c3fde0348f0ae55534c88e8bdab2d78f
[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 <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <glib.h>
28
29 #include "treefuncs.h"
30 #include "parse.h"
31 #include "main.h"
32 #include "util.h"
33
34 static int parenth_depth = 0;
35 static int before_comment
36 /* New flex is on drugs */
37 #if defined(FLEX_SCANNER) && ! defined(INITIAL)
38         = 0;
39 #else
40         = INITIAL;
41 #endif
42 static gboolean class_after_c = FALSE;
43 static int code_type = CCODE;
44 static int before_string;
45 static int property_paren_depth = 0;
46
47 /* GTK+ doc stuff */
48 static char *gtk_doc_func = NULL; /* current gtk-doc func */
49 GHashTable *gtk_doc_hash = NULL;
50
51 static GString *cbuf = NULL;
52 int ccode_line = 1;
53
54 GList *include_files = NULL;
55 /* 0 no, 1 means yes, 2+ means don't even start looking anymore */
56 static int look_for_includes = 0;
57
58 int line_no = 1;
59 /* last filename parsed from a #line directive */
60 char *hline_filename = NULL;
61
62 static void
63 clear_cbuf(void)
64 {
65         if(!cbuf) {
66                 cbuf = g_string_new(NULL);
67         } else {
68                 cbuf = g_string_assign(cbuf, "");
69         }
70 }
71
72 static void
73 add_to_cbuf(char *s)
74 {
75         if(!cbuf) {
76                 cbuf = g_string_new(s);
77         } else {
78                 cbuf = g_string_append(cbuf,s);
79         }
80 }
81
82 static void
83 add_gtk_doc_func(void)
84 {
85         if(!gtk_doc_func)
86                 return;
87
88         if(!gtk_doc_hash)
89                 gtk_doc_hash = g_hash_table_new(g_str_hash, g_str_equal);
90         g_hash_table_insert(gtk_doc_hash, gtk_doc_func, g_strdup(cbuf->str));
91         clear_cbuf();
92
93         gtk_doc_func = NULL;
94 }
95
96 /* Ugly warning avoiding */
97 #ifdef FLEX_SCANNER
98 int yylex(void);
99 #endif
100
101 %}
102
103 %x COMMENT
104 %x C_CODE
105 %x CODE_STRING
106 %x CLASS_CODE
107 %x CLASS_STRING
108 %x CLASS_CODE_I
109 %x PROPERTY_CODE
110 %x PROPERTY_CODE_I
111 %x GTK_DOC_BEFORE_NAME
112 %x GTK_DOC
113 %x GTK_DOC_LINE
114
115
116
117 %%
118
119 %{
120 /* Avoid warning from flex, cuz flex sucks */
121 #ifdef FLEX_SCANNER
122 yy_current_state = 0;
123 #endif
124 %}
125
126
127 <*>\n                   { line_no++; REJECT; }
128
129 <COMMENT>^(I(S.RI).E\(([1-9][0-9]+|[2-9]))/(\)) {
130 /* Thy evil easter egg */
131 #define QQ(x) long x
132 #define KK(x) =atoi(__(&,,x,))
133 #define MM(x,a) {QQ(i);for(i=2;i<x;i++){a}}
134 #define PP(Q) (P%Q)==0
135 #define ___(x,y,z) if(x z y)
136 #define __(a,x,y,z) a(yytext[y] x z)
137 #define O__O(a,b) fprintf(stderr,"%s is %s!\n",a,b)
138 QQ(m)=1;___(__(,==,2,'P'),__(,==,5,'M'),&&
139 ){QQ(P)KK(8);MM(P,___(PP(i),,)m=0;)}__(,=,
140 7,0);___(,,m){O__O(__( &,,8,),__(&,,2,));}
141 #undef QQ
142 #undef KK
143 #undef MM
144 #undef PP
145 #undef ___
146 #undef __
147 #undef O__O
148 REJECT;
149 }
150
151 \/\/.*$                 { ; /*comment, ignore*/ }
152
153 <*>^#[ \t]*line[ \t]+[0-9]+([ \t]\"[^\n\r\f\"]*\")? {
154         char *p;
155         char *number;
156         char *filename;
157         char *str=g_strdup(yytext);
158
159         /* find first digit of line number */
160         p=str;
161         while(*p&&!isdigit(*p)) p++;
162         number=p;
163   
164         /* find end of line number */
165         while(*p&&isdigit(*p)) p++;
166         if(*p) *p++=0;
167
168         /* find beginning of filename */
169         p=strchr(p,'"');
170         if(p) p++;
171         filename=p;
172
173         /* find end of filename */
174         if(p) p=strchr(p,'"');
175         if(p) *p=0;
176
177         /* stash number (minus one because we don't count this line) */  
178         if(number) line_no=atoi(number)-1;
179
180         /* stash filename */
181         if(filename) {
182                 if(hline_filename) g_free(hline_filename);
183                 hline_filename=g_strdup(filename);
184         }
185   
186         /* clean up */
187         g_free(str);
188 }
189
190 <C_CODE>^#[ \t]*include[ \t][<"][^\n">]*[>"] {
191         if(look_for_includes==1) {
192                 char *p;
193                 char *file;
194                 char *str = g_strdup(yytext);
195                 file = strchr(str,'"');
196                 if(!file) file = strchr(str,'<');
197                 file++;
198                 p = strchr(file,'"');
199                 if(!p) p = strchr(file,'>');
200                 if (p != NULL) {
201                         *p = '\0';
202                         include_files = g_list_prepend(include_files,g_strdup(file));
203                         g_free(str);
204                 }
205         }
206         REJECT;
207 }
208
209 <CLASS_CODE_I>\/\*\*[ \t]*$     {
210                         /* eat out gtk doc stuff */
211                         BEGIN(GTK_DOC_BEFORE_NAME);
212                         clear_cbuf();
213                 }
214 <GTK_DOC_BEFORE_NAME>^[ \t]*\*[ \t]*$   {
215                         /* empty doc lines */
216                         ;
217                 }       
218 <GTK_DOC_BEFORE_NAME>^[ \t]*\*\ [_a-zA-Z][_a-zA-Z0-9]*:?[ \t]*$ {
219                         char *p;
220                         BEGIN(GTK_DOC);
221                         p = strchr(yytext, '*');
222                         g_free(gtk_doc_func);
223                         gtk_doc_func = g_strdup(p+2);
224                         p = strchr(gtk_doc_func, ':');
225                         if(p) *p='\0';
226                         g_strstrip(gtk_doc_func);
227                 }
228 <GTK_DOC_BEFORE_NAME>\*\/       {
229                         BEGIN(CLASS_CODE_I);
230                 }
231 <GTK_DOC_BEFORE_NAME>.  {
232                         BEGIN(COMMENT);
233                         before_comment = CLASS_CODE_I;
234                 }
235 <GTK_DOC>^[ \t]*\*[ \t]*$       {
236                         /* empty doc lines */
237                         add_to_cbuf(" *\n");
238                 }       
239 <GTK_DOC>^[ \t]*\*?\*\/ {
240                         BEGIN(CLASS_CODE_I);
241                         add_gtk_doc_func();
242                 }
243 <GTK_DOC>^[ \t]*\*[ \t] {
244                         fflush(stdout);
245                         add_to_cbuf(" * ");
246                         BEGIN(GTK_DOC_LINE);
247                 }
248 <GTK_DOC>\*\/   {
249                         BEGIN(CLASS_CODE_I);
250                 }
251 <GTK_DOC>.      {
252                         BEGIN(COMMENT);
253                         before_comment = CLASS_CODE_I;
254                 }
255 <GTK_DOC_LINE>\*\/      {
256                         BEGIN(CLASS_CODE_I);
257                         add_to_cbuf("\n");
258                         add_gtk_doc_func();
259                 }
260 <GTK_DOC_LINE>.$        {
261                         BEGIN(GTK_DOC);
262                         add_to_cbuf(yytext);
263                         add_to_cbuf("\n");
264                 }
265 <GTK_DOC_LINE>. {
266                         fflush(stdout);
267                         add_to_cbuf(yytext);
268                 }
269
270 <C_CODE>\/\/.*$         { add_to_cbuf(yytext); /*comment, ignore*/ }
271 <CLASS_CODE>\/\/.*$     { ; /*comment, ignore*/ }
272 <CLASS_CODE_I>\/\/.*$   { ; /*comment, ignore*/ }
273 <PROPERTY_CODE_I>\/\/.*$        { ; /*comment, ignore*/ }
274 \/\*            {BEGIN(COMMENT); before_comment = INITIAL; }
275 <C_CODE>\/\*    {
276         add_to_cbuf(yytext);
277         BEGIN(COMMENT);
278         before_comment = C_CODE;
279 }
280 <CLASS_CODE>\/\*        {BEGIN(COMMENT); before_comment = CLASS_CODE; }
281 <CLASS_CODE_I>\/\*      {BEGIN(COMMENT); before_comment = CLASS_CODE_I; }
282 <PROPERTY_CODE_I>\/\*   {BEGIN(COMMENT); before_comment = PROPERTY_CODE_I; }
283 <COMMENT>\*\/   {
284         if(before_comment == C_CODE) add_to_cbuf(yytext);
285         BEGIN(before_comment);
286                 }
287 <COMMENT>.      {
288         /* comment, ignore */
289         if(before_comment == C_CODE) add_to_cbuf(yytext);
290                 }
291 <COMMENT>\n     {
292         /* comment, ignore */
293         if(before_comment == C_CODE) add_to_cbuf(yytext);
294                 }
295
296 ^\%(a|all)\{            {
297                         BEGIN(C_CODE);
298                         parenth_depth = 1;
299                         class_after_c = FALSE;
300                         code_type = ACODE;
301                         clear_cbuf();
302                         ccode_line = line_no;
303                 }
304 ^\%(at|alltop)\{                {
305                         BEGIN(C_CODE);
306                         parenth_depth = 1;
307                         class_after_c = FALSE;
308                         code_type = ATCODE;
309                         clear_cbuf();
310                         ccode_line = line_no;
311                 }
312
313 ^\%(ht|headertop)\{             {
314                         BEGIN(C_CODE);
315                         parenth_depth = 1;
316                         class_after_c = FALSE;
317                         code_type = HTCODE;
318                         clear_cbuf();
319                         ccode_line = line_no;
320                 }
321 ^\%(ph|privateheader)\{         {
322                         BEGIN(C_CODE);
323                         parenth_depth = 1;
324                         class_after_c = FALSE;
325                         code_type = PHCODE;
326                         clear_cbuf();
327                         ccode_line = line_no;
328                 }
329 ^\%(h|header)\{         {
330                         BEGIN(C_CODE);
331                         parenth_depth = 1;
332                         class_after_c = FALSE;
333                         code_type = HCODE;
334                         clear_cbuf();
335                         ccode_line = line_no;
336                 }
337 ^\%\{           {
338                         BEGIN(C_CODE);
339                         parenth_depth = 1;
340                         class_after_c = FALSE;
341                         code_type = CCODE;
342                         clear_cbuf();
343                         ccode_line = line_no;
344                         if(look_for_includes==0)
345                                 look_for_includes=1;
346                 }
347 <C_CODE>^\%\}   {
348                         BEGIN(INITIAL);
349                         yylval.cbuf = cbuf;
350                         cbuf = NULL;
351                         if(look_for_includes==1)
352                                 look_for_includes=0;
353                         return code_type;
354                 }
355
356 <C_CODE>\'\{\'          { add_to_cbuf(yytext); }
357 <C_CODE>\'\\\{\'        { add_to_cbuf(yytext); }
358 <C_CODE>\'\}\'          { add_to_cbuf(yytext); }
359 <C_CODE>\'\\\}\'        { add_to_cbuf(yytext); }
360 <C_CODE>\'\"\'          { add_to_cbuf(yytext); }
361 <C_CODE>\'\\\"\'        { add_to_cbuf(yytext); }
362         
363 <C_CODE>\\.     { add_to_cbuf(yytext); }
364
365
366 <C_CODE>\"      {
367                         BEGIN(CODE_STRING);
368                         before_string = C_CODE;
369                         add_to_cbuf(yytext);
370                 }
371 <PROPERTY_CODE_I>\"     {
372                         BEGIN(CODE_STRING);
373                         before_string = PROPERTY_CODE_I;
374                         add_to_cbuf(yytext);
375                 }
376 <CODE_STRING>\\.        { add_to_cbuf(yytext); }
377 <CODE_STRING>\" {
378                         BEGIN(before_string);
379                         add_to_cbuf(yytext);
380                         if (before_string == PROPERTY_CODE_I) {
381                                 yylval.id = cbuf->str;
382                                 g_string_free (cbuf, FALSE);
383                                 cbuf = NULL;
384                                 return STRING;
385                         }
386                 }
387 <CODE_STRING>.  { add_to_cbuf(yytext); }
388 <CODE_STRING>\n { add_to_cbuf(yytext); }
389
390 <C_CODE>\{      {
391                         parenth_depth++;
392                         add_to_cbuf(yytext);
393                 }
394 <C_CODE>\}      {
395                         parenth_depth--;
396                         if(parenth_depth<0) {
397                                 REJECT;
398                         } else if(parenth_depth==0 && class_after_c) {
399                                 BEGIN(CLASS_CODE_I);
400                                 yylval.cbuf = cbuf;
401                                 cbuf = NULL;
402                                 return CCODE;
403                         }
404                         add_to_cbuf(yytext);
405                 }
406
407 <C_CODE>.       { add_to_cbuf(yytext); }
408 <C_CODE>\n      { add_to_cbuf(yytext); }
409
410 class           {
411                         static int found_classes = 0;
412                         look_for_includes = 2;
413                         BEGIN(CLASS_CODE);
414
415                         if(++found_classes > 1) {
416                                 error_print(GOB_ERROR, line_no,
417                                             "Only one class per file allowed");
418                         }
419
420                         return CLASS;
421                 }
422
423 error           { return ERROR; }
424 enum            { return ENUM; }
425 flags           { return FLAGS; }
426
427 ^[ \t]*requires[ \t]+[0-9]+\.[0-9]+\.[0-9]+[\t ]*$      {
428                         int maj = 0, min = 0, pl = 0;
429                         int rmaj = 0, rmin = 0, rpl = 0;
430                         int effective_maj = 0;
431                         int effective_rmaj = 0;
432                         char *p;
433                         
434                         sscanf (VERSION, "%d.%d.%d", &rmaj, &rmin, &rpl);
435                         effective_rmaj = rmaj;
436                         if (rmin >= 90)
437                                 effective_rmaj = rmaj + 1;
438
439                         p = strchr (yytext,'r');
440                         g_assert (p); /* we MUST have found it */
441                         sscanf (p, "requires %d.%d.%d", &maj, &min, &pl);
442                         effective_maj = maj;
443                         if (min >= 90)
444                                 effective_maj = maj + 1;
445
446                         if(rmaj < maj ||
447                            (rmaj == maj && rmin < min) ||
448                            (rmaj == maj && rmin == min && rpl < pl)) {
449                                 error_printf (GOB_ERROR, line_no,
450                                               "GOB version at least %d.%d.%d required "
451                                               "(this is %s)\n"
452                                               "To upgrade your gob, see: "
453                                               "http://www.5z.com/jirka/gob.html",
454                                               maj, min, pl, VERSION);
455                         }
456
457                         if(effective_rmaj != effective_maj) {
458                                 error_printf(GOB_ERROR, line_no,
459                                              "GOB major version %d required "
460                                              "(this is %s)\n"
461                                              "To upgrade your gob, see: "
462                                              "http://www.5z.com/jirka/gob.html",
463                                              effective_maj, VERSION);
464                         }
465
466                 }
467
468 <CLASS_CODE,CLASS_CODE_I>class|this     {
469                         if(for_cpp) {
470                                 error_printf(GOB_WARN, line_no,
471                                              "'%s' keyword should not "
472                                              "be used when generating "
473                                              "C++ code", yytext);
474                         }
475                         REJECT;
476                 }
477
478 <CLASS_CODE>from        {return FROM;}
479 <CLASS_CODE>\"  {
480                         BEGIN(CLASS_STRING);
481                         before_string = CLASS_CODE;
482                         add_to_cbuf(yytext);
483                 }
484 <CLASS_STRING>\\.       { add_to_cbuf(yytext); }
485 <CLASS_STRING>\"        {
486                         BEGIN(before_string);
487                         add_to_cbuf(yytext);
488                         yylval.id = cbuf->str;
489                         g_string_free (cbuf, FALSE);
490                         cbuf = NULL;
491                         return STRING;
492                 }
493 <CLASS_STRING>. { add_to_cbuf(yytext); }
494 <CLASS_STRING>\n        { add_to_cbuf(yytext); }
495
496 <CLASS_CODE_I,PROPERTY_CODE_I>void      {return VOID;}
497 <CLASS_CODE_I,PROPERTY_CODE_I>struct    {return STRUCT;}
498 <CLASS_CODE_I,PROPERTY_CODE_I>union     {return UNION;}
499 <CLASS_CODE_I,PROPERTY_CODE_I>enum      {return ENUM;}
500 <CLASS_CODE_I,PROPERTY_CODE_I>signed    {return SIGNED;}
501 <CLASS_CODE_I,PROPERTY_CODE_I>unsigned  {return UNSIGNED;}
502 <CLASS_CODE_I,PROPERTY_CODE_I>long      {return LONG;}
503 <CLASS_CODE_I,PROPERTY_CODE_I>short     {return SHORT;}
504 <CLASS_CODE_I,PROPERTY_CODE_I>int       {return INT;}
505 <CLASS_CODE_I,PROPERTY_CODE_I>float     {return FLOAT;}
506 <CLASS_CODE_I,PROPERTY_CODE_I>double    {return DOUBLE;}
507 <CLASS_CODE_I,PROPERTY_CODE_I>char      {return CHAR;}
508 <CLASS_CODE_I,PROPERTY_CODE_I>const     {return CONST;}
509
510 <CLASS_CODE_I>\.\.\.    {return THREEDOTS;}
511
512 <CLASS_CODE_I>public    {yylval.line = line_no; return PUBLIC;}
513 <CLASS_CODE_I>private   {yylval.line = line_no; return PRIVATE;}
514 <CLASS_CODE_I>protected {yylval.line = line_no; return PROTECTED;}
515 <CLASS_CODE_I>classwide {yylval.line = line_no; return CLASSWIDE;}
516 <CLASS_CODE_I>argument  {yylval.line = line_no; return ARGUMENT;}
517 <CLASS_CODE_I>virtual   {yylval.line = line_no; return VIRTUAL;}
518 <CLASS_CODE_I>signal    {yylval.line = line_no; return SIGNAL;}
519 <CLASS_CODE_I>override  {yylval.line = line_no; return OVERRIDE;}
520 <CLASS_CODE_I>property  {
521                                 yylval.line = line_no;
522                                 BEGIN(PROPERTY_CODE);
523                                 return PROPERTY;
524                         }
525 <PROPERTY_CODE_I>nick   { yylval.line = line_no; return NICK; }
526 <PROPERTY_CODE_I>blurb  { yylval.line = line_no; return BLURB; }
527 <PROPERTY_CODE_I>maximum        { yylval.line = line_no; return MAXIMUM; }
528 <PROPERTY_CODE_I>minimum        { yylval.line = line_no; return MINIMUM; }
529 <PROPERTY_CODE_I>default_value  { yylval.line = line_no; return DEFAULT_VALUE; }
530 <PROPERTY_CODE_I>flags  { yylval.line = line_no; return FLAGS; }
531 <PROPERTY_CODE_I>type   { yylval.line = line_no; return TYPE; }
532 <PROPERTY_CODE_I>flags_type     { yylval.line = line_no; return FLAGS_TYPE; }
533 <PROPERTY_CODE_I>enum_type      { yylval.line = line_no; return ENUM_TYPE; }
534 <PROPERTY_CODE_I>param_type     { yylval.line = line_no; return PARAM_TYPE; }
535 <PROPERTY_CODE_I>boxed_type     { yylval.line = line_no; return BOXED_TYPE; }
536 <PROPERTY_CODE_I>object_type    { yylval.line = line_no; return OBJECT_TYPE; }
537 <PROPERTY_CODE>[(]      {
538                 yylval.line = line_no;
539                 property_paren_depth = 1;
540                 BEGIN(PROPERTY_CODE_I);
541                 return '(';
542                         }
543 <PROPERTY_CODE_I>[(]    {
544                 yylval.line = line_no;
545                 property_paren_depth++;
546                 return '(';
547                         }
548 <PROPERTY_CODE_I>[)]    {
549                 yylval.line = line_no;
550                 property_paren_depth--;
551                 if (property_paren_depth == 0) {
552                         BEGIN(CLASS_CODE_I);
553                 }
554                 return ')';
555                         }
556
557 <CLASS_CODE,CLASS_CODE_I,PROPERTY_CODE,PROPERTY_CODE_I,INITIAL>0|[1-9][0-9]*|0x[0-9a-fA-F]+|0[0-7]+|[0-9]*\.[0-9]+|\.[0-9][0-9]*        {
558                         yylval.id = g_strdup(yytext);
559                         return NUMBER;
560                 }
561 <CLASS_CODE,CLASS_CODE_I,PROPERTY_CODE,PROPERTY_CODE_I,INITIAL>[A-Za-z_][A-Za-z0-9_]*(::[A-Za-z0-9_]*)+ {
562                         /* This is cpp kind of token thingie */
563                         if (for_cpp) {
564                                 yylval.id = g_strdup(yytext);
565                                 return TOKEN;
566                         } else {
567                                 REJECT;
568                         }
569                 }
570 <CLASS_CODE,CLASS_CODE_I,PROPERTY_CODE,PROPERTY_CODE_I,INITIAL>[A-Za-z_][A-Za-z0-9_]*(:[A-Za-z_][A-Za-z0-9_]*)+ {
571                         /* this one is for a classname with a namespace */
572                         yylval.id = g_strdup(yytext);
573                         return TYPETOKEN;
574                 }
575 <CLASS_CODE,CLASS_CODE_I,PROPERTY_CODE,PROPERTY_CODE_I,INITIAL>:[A-Za-z_][A-Za-z0-9_]*(:[A-Za-z_][A-Za-z0-9_]*)*        {
576                         /* this is for a classname with an empty namespace */
577                         yylval.id = g_strdup(yytext);
578                         return TYPETOKEN;
579                 }
580 <CLASS_CODE,CLASS_CODE_I,PROPERTY_CODE,PROPERTY_CODE_I,INITIAL>[A-Za-z_][A-Za-z0-9_]*   {
581                         yylval.id = g_strdup(yytext);
582                         return TOKEN;
583                 }
584 <CLASS_CODE,CLASS_CODE_I,PROPERTY_CODE,PROPERTY_CODE_I,INITIAL>\'\\.\'|\'.\'    {
585                         yylval.id = g_strdup(yytext);
586                         return SINGLE_CHAR;
587                 }
588
589 <CLASS_CODE_I>(\[[0-9]*\]|\[[A-Za-z_][A-Za-z0-9_]*\])+  {
590                         yylval.id = g_strdup(yytext);
591                         return ARRAY_DIM;
592                 }
593 <CLASS_CODE_I>:[0-9]+ {
594                         /* cheat for bitfield */
595                         yylval.id = g_strdup(yytext);
596                         return ARRAY_DIM;
597                 }
598 <CLASS_CODE>\{  {
599                         BEGIN(CLASS_CODE_I);
600                         return '{';
601                 }
602 <CLASS_CODE_I,PROPERTY_CODE>\{  {
603                         BEGIN(C_CODE);
604                         parenth_depth=1;
605                         class_after_c = TRUE;
606                         yylval.line = line_no;
607                         clear_cbuf();
608                         ccode_line = line_no;
609                         return '{';
610                 }
611 <CLASS_CODE_I>\}        {
612                                 BEGIN(INITIAL);
613                                 return '}';
614                         }
615
616 <CLASS_CODE,CLASS_CODE_I,INITIAL,PROPERTY_CODE,PROPERTY_CODE_I>[\f\t ]  ;  /*ignore*/
617
618 <*>.            {
619                         yylval.line = line_no;
620                         return yytext[0];
621                 }
622
623 <*>[\n\r]       ;  /*ignore*/
624
625 ^[ \t]*prealloc[ \t]+[0-9]+[ \t]*$ {
626                         char *p;
627                         int t;
628                         p = strchr (yytext,'p');
629                         g_assert (p); /* we MUST have found it */
630                         sscanf (p, "prealloc %d", &t);
631                         prealloc=t;
632                 }
633
634 %%