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