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