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