Merge branch 'bug552393-varargs'
[platform/upstream/gobject-introspection.git] / giscanner / scannerparser.y
1 /* GObject introspection: C parser
2  *
3  * Copyright (c) 1997 Sandro Sigala  <ssigala@globalnet.it>
4  * Copyright (c) 2007-2008 Jürg Billeter  <j@bitron.ch>
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 %{
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <glib.h>
35 #include "sourcescanner.h"
36 #include "scannerparser.h"
37
38 extern FILE *yyin;
39 extern int lineno;
40 extern char *yytext;
41
42 extern int yylex (GISourceScanner *scanner);
43 static void yyerror (GISourceScanner *scanner, const char *str);
44  
45 static int last_enum_value = -1;
46 static GHashTable *const_table = NULL;
47 %}
48
49 %error-verbose
50 %union {
51   char *str;
52   GList *list;
53   GISourceSymbol *symbol;
54   GISourceType *ctype;
55   StorageClassSpecifier storage_class_specifier;
56   TypeQualifier type_qualifier;
57   FunctionSpecifier function_specifier;
58   UnaryOperator unary_operator;
59 }
60
61 %parse-param { GISourceScanner* scanner }
62 %lex-param { GISourceScanner* scanner }
63
64 %token <str> IDENTIFIER "identifier"
65 %token <str> TYPEDEF_NAME "typedef-name"
66
67 %token INTEGER FLOATING CHARACTER STRING
68
69 %token ELLIPSIS ADDEQ SUBEQ MULEQ DIVEQ MODEQ XOREQ ANDEQ OREQ SL SR
70 %token SLEQ SREQ EQ NOTEQ LTEQ GTEQ ANDAND OROR PLUSPLUS MINUSMINUS ARROW
71
72 %token AUTO BOOL BREAK CASE CHAR CONST CONTINUE DEFAULT DO DOUBLE ELSE ENUM
73 %token EXTENSION EXTERN FLOAT FOR GOTO IF INLINE INT LONG REGISTER RESTRICT
74 %token RETURN SHORT SIGNED SIZEOF STATIC STRUCT SWITCH TYPEDEF UNION UNSIGNED
75 %token VOID VOLATILE WHILE
76
77 %token FUNCTION_MACRO OBJECT_MACRO
78
79 %start translation_unit
80
81 %type <ctype> declaration_specifiers
82 %type <ctype> enum_specifier
83 %type <ctype> pointer
84 %type <ctype> specifier_qualifier_list
85 %type <ctype> type_name
86 %type <ctype> struct_or_union
87 %type <ctype> struct_or_union_specifier
88 %type <ctype> type_specifier
89 %type <str> identifier
90 %type <str> typedef_name
91 %type <str> identifier_or_typedef_name
92 %type <symbol> abstract_declarator
93 %type <symbol> init_declarator
94 %type <symbol> declarator
95 %type <symbol> enumerator
96 %type <symbol> direct_abstract_declarator
97 %type <symbol> direct_declarator
98 %type <symbol> parameter_declaration
99 %type <symbol> struct_declarator
100 %type <list> enumerator_list
101 %type <list> identifier_list
102 %type <list> init_declarator_list
103 %type <list> parameter_list
104 %type <list> struct_declaration
105 %type <list> struct_declaration_list
106 %type <list> struct_declarator_list
107 %type <storage_class_specifier> storage_class_specifier
108 %type <type_qualifier> type_qualifier
109 %type <type_qualifier> type_qualifier_list
110 %type <function_specifier> function_specifier
111 %type <symbol> expression
112 %type <symbol> constant_expression
113 %type <symbol> conditional_expression
114 %type <symbol> logical_and_expression
115 %type <symbol> logical_or_expression
116 %type <symbol> inclusive_or_expression
117 %type <symbol> exclusive_or_expression
118 %type <symbol> multiplicative_expression
119 %type <symbol> additive_expression
120 %type <symbol> shift_expression
121 %type <symbol> relational_expression
122 %type <symbol> equality_expression
123 %type <symbol> and_expression
124 %type <symbol> cast_expression
125 %type <symbol> assignment_expression
126 %type <symbol> unary_expression
127 %type <symbol> postfix_expression
128 %type <symbol> primary_expression
129 %type <unary_operator> unary_operator
130 %type <str> function_macro
131 %type <str> object_macro
132 %type <symbol> strings
133
134 %%
135
136 /* A.2.1 Expressions. */
137
138 primary_expression
139         : identifier
140           {
141                 $$ = g_hash_table_lookup (const_table, $1);
142                 if ($$ == NULL) {
143                         $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
144                 } else {
145                         $$ = gi_source_symbol_ref ($$);
146                 }
147           }
148         | INTEGER
149           {
150                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
151                 $$->const_int_set = TRUE;
152                 if (g_str_has_prefix (yytext, "0x") && strlen (yytext) > 2) {
153                         $$->const_int = strtol (yytext + 2, NULL, 16);
154                 } else if (g_str_has_prefix (yytext, "0") && strlen (yytext) > 1) {
155                         $$->const_int = strtol (yytext + 1, NULL, 8);
156                 } else {
157                         $$->const_int = atoi (yytext);
158                 }
159           }
160         | CHARACTER
161           {
162                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
163           }
164         | FLOATING
165           {
166                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
167           }
168         | strings
169         | '(' expression ')'
170           {
171                 $$ = $2;
172           }
173         ;
174
175 /* concatenate adjacent string literal tokens */
176 strings
177         : STRING
178           {
179                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
180                 yytext[strlen (yytext) - 1] = '\0';
181                 $$->const_string = g_strcompress (yytext + 1);
182           }
183         | strings STRING
184           {
185                 char *strings, *string2;
186                 $$ = $1;
187                 yytext[strlen (yytext) - 1] = '\0';
188                 string2 = g_strcompress (yytext + 1);
189                 strings = g_strconcat ($$->const_string, string2, NULL);
190                 g_free ($$->const_string);
191                 g_free (string2);
192                 $$->const_string = strings;
193           }
194         ;
195
196 identifier
197         : IDENTIFIER
198           {
199                 $$ = g_strdup (yytext);
200           }
201         ;
202
203 identifier_or_typedef_name
204         : identifier
205         | typedef_name
206         ;
207
208 postfix_expression
209         : primary_expression
210         | postfix_expression '[' expression ']'
211           {
212                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
213           }
214         | postfix_expression '(' argument_expression_list ')'
215           {
216                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
217           }
218         | postfix_expression '(' ')'
219           {
220                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
221           }
222         | postfix_expression '.' identifier_or_typedef_name
223           {
224                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
225           }
226         | postfix_expression ARROW identifier_or_typedef_name
227           {
228                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
229           }
230         | postfix_expression PLUSPLUS
231           {
232                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
233           }
234         | postfix_expression MINUSMINUS
235           {
236                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
237           }
238         ;
239
240 argument_expression_list
241         : assignment_expression
242         | argument_expression_list ',' assignment_expression
243         ;
244
245 unary_expression
246         : postfix_expression
247         | PLUSPLUS unary_expression
248           {
249                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
250           }
251         | MINUSMINUS unary_expression
252           {
253                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
254           }
255         | unary_operator cast_expression
256           {
257                 switch ($1) {
258                 case UNARY_PLUS:
259                         $$ = $2;
260                         break;
261                 case UNARY_MINUS:
262                         $$ = $2;
263                         $$->const_int = -$2->const_int;
264                         break;
265                 case UNARY_BITWISE_COMPLEMENT:
266                         $$ = $2;
267                         $$->const_int = ~$2->const_int;
268                         break;
269                 case UNARY_LOGICAL_NEGATION:
270                         $$ = $2;
271                         $$->const_int = !gi_source_symbol_get_const_boolean ($2);
272                         break;
273                 default:
274                         $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
275                         break;
276                 }
277           }
278         | SIZEOF unary_expression
279           {
280                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
281           }
282         | SIZEOF '(' type_name ')'
283           {
284                 ctype_free ($3);
285                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
286           }
287         ;
288
289 unary_operator
290         : '&'
291           {
292                 $$ = UNARY_ADDRESS_OF;
293           }
294         | '*'
295           {
296                 $$ = UNARY_POINTER_INDIRECTION;
297           }
298         | '+'
299           {
300                 $$ = UNARY_PLUS;
301           }
302         | '-'
303           {
304                 $$ = UNARY_MINUS;
305           }
306         | '~'
307           {
308                 $$ = UNARY_BITWISE_COMPLEMENT;
309           }
310         | '!'
311           {
312                 $$ = UNARY_LOGICAL_NEGATION;
313           }
314         ;
315
316 cast_expression
317         : unary_expression
318         | '(' type_name ')' cast_expression
319           {
320                 ctype_free ($2);
321                 $$ = $4;
322           }
323         ;
324
325 multiplicative_expression
326         : cast_expression
327         | multiplicative_expression '*' cast_expression
328           {
329                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
330                 $$->const_int_set = TRUE;
331                 $$->const_int = $1->const_int * $3->const_int;
332           }
333         | multiplicative_expression '/' cast_expression
334           {
335                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
336                 $$->const_int_set = TRUE;
337                 if ($3->const_int != 0) {
338                         $$->const_int = $1->const_int / $3->const_int;
339                 }
340           }
341         | multiplicative_expression '%' cast_expression
342           {
343                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
344                 $$->const_int_set = TRUE;
345                 $$->const_int = $1->const_int % $3->const_int;
346           }
347         ;
348
349 additive_expression
350         : multiplicative_expression
351         | additive_expression '+' multiplicative_expression
352           {
353                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
354                 $$->const_int_set = TRUE;
355                 $$->const_int = $1->const_int + $3->const_int;
356           }
357         | additive_expression '-' multiplicative_expression
358           {
359                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
360                 $$->const_int_set = TRUE;
361                 $$->const_int = $1->const_int - $3->const_int;
362           }
363         ;
364
365 shift_expression
366         : additive_expression
367         | shift_expression SL additive_expression
368           {
369                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
370                 $$->const_int_set = TRUE;
371                 $$->const_int = $1->const_int << $3->const_int;
372           }
373         | shift_expression SR additive_expression
374           {
375                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
376                 $$->const_int_set = TRUE;
377                 $$->const_int = $1->const_int >> $3->const_int;
378           }
379         ;
380
381 relational_expression
382         : shift_expression
383         | relational_expression '<' shift_expression
384           {
385                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
386                 $$->const_int_set = TRUE;
387                 $$->const_int = $1->const_int < $3->const_int;
388           }
389         | relational_expression '>' shift_expression
390           {
391                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
392                 $$->const_int_set = TRUE;
393                 $$->const_int = $1->const_int > $3->const_int;
394           }
395         | relational_expression LTEQ shift_expression
396           {
397                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
398                 $$->const_int_set = TRUE;
399                 $$->const_int = $1->const_int <= $3->const_int;
400           }
401         | relational_expression GTEQ shift_expression
402           {
403                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
404                 $$->const_int_set = TRUE;
405                 $$->const_int = $1->const_int >= $3->const_int;
406           }
407         ;
408
409 equality_expression
410         : relational_expression
411         | equality_expression EQ relational_expression
412           {
413                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
414                 $$->const_int_set = TRUE;
415                 $$->const_int = $1->const_int == $3->const_int;
416           }
417         | equality_expression NOTEQ relational_expression
418           {
419                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
420                 $$->const_int_set = TRUE;
421                 $$->const_int = $1->const_int != $3->const_int;
422           }
423         ;
424
425 and_expression
426         : equality_expression
427         | and_expression '&' equality_expression
428           {
429                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
430                 $$->const_int_set = TRUE;
431                 $$->const_int = $1->const_int & $3->const_int;
432           }
433         ;
434
435 exclusive_or_expression
436         : and_expression
437         | exclusive_or_expression '^' and_expression
438           {
439                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
440                 $$->const_int_set = TRUE;
441                 $$->const_int = $1->const_int ^ $3->const_int;
442           }
443         ;
444
445 inclusive_or_expression
446         : exclusive_or_expression
447         | inclusive_or_expression '|' exclusive_or_expression
448           {
449                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
450                 $$->const_int_set = TRUE;
451                 $$->const_int = $1->const_int | $3->const_int;
452           }
453         ;
454
455 logical_and_expression
456         : inclusive_or_expression
457         | logical_and_expression ANDAND inclusive_or_expression
458           {
459                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
460                 $$->const_int_set = TRUE;
461                 $$->const_int =
462                   gi_source_symbol_get_const_boolean ($1) &&
463                   gi_source_symbol_get_const_boolean ($3);
464           }
465         ;
466
467 logical_or_expression
468         : logical_and_expression
469         | logical_or_expression OROR logical_and_expression
470           {
471                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
472                 $$->const_int_set = TRUE;
473                 $$->const_int =
474                   gi_source_symbol_get_const_boolean ($1) ||
475                   gi_source_symbol_get_const_boolean ($3);
476           }
477         ;
478
479 conditional_expression
480         : logical_or_expression
481         | logical_or_expression '?' expression ':' conditional_expression
482           {
483                 $$ = gi_source_symbol_get_const_boolean ($1) ? $3 : $5;
484           }
485         ;
486
487 assignment_expression
488         : conditional_expression
489         | unary_expression assignment_operator assignment_expression
490           {
491                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
492           }
493         ;
494
495 assignment_operator
496         : '='
497         | MULEQ
498         | DIVEQ
499         | MODEQ
500         | ADDEQ
501         | SUBEQ
502         | SLEQ
503         | SREQ
504         | ANDEQ
505         | XOREQ
506         | OREQ
507         ;
508
509 expression
510         : assignment_expression
511         | expression ',' assignment_expression
512           {
513                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
514           }
515         ;
516
517 constant_expression
518         : conditional_expression
519         ;
520
521 /* A.2.2 Declarations. */
522
523 declaration
524         : declaration_specifiers init_declarator_list ';'
525           {
526                 GList *l;
527                 for (l = $2; l != NULL; l = l->next) {
528                         GISourceSymbol *sym = l->data;
529                         gi_source_symbol_merge_type (sym, gi_source_type_copy ($1));
530                         if ($1->storage_class_specifier & STORAGE_CLASS_TYPEDEF) {
531                                 sym->type = CSYMBOL_TYPE_TYPEDEF;
532                         } else if (sym->base_type->type == CTYPE_FUNCTION) {
533                                 sym->type = CSYMBOL_TYPE_FUNCTION;
534                         } else {
535                                 sym->type = CSYMBOL_TYPE_OBJECT;
536                         }
537                         gi_source_scanner_add_symbol (scanner, sym);
538                         gi_source_symbol_unref (sym);
539                 }
540                 ctype_free ($1);
541           }
542         | declaration_specifiers ';'
543           {
544                 ctype_free ($1);
545           }
546         ;
547
548 declaration_specifiers
549         : storage_class_specifier declaration_specifiers
550           {
551                 $$ = $2;
552                 $$->storage_class_specifier |= $1;
553           }
554         | storage_class_specifier
555           {
556                 $$ = gi_source_type_new (CTYPE_INVALID);
557                 $$->storage_class_specifier |= $1;
558           }
559         | type_specifier declaration_specifiers
560           {
561                 $$ = $1;
562                 $$->base_type = $2;
563           }
564         | type_specifier
565         | type_qualifier declaration_specifiers
566           {
567                 $$ = $2;
568                 $$->type_qualifier |= $1;
569           }
570         | type_qualifier
571           {
572                 $$ = gi_source_type_new (CTYPE_INVALID);
573                 $$->type_qualifier |= $1;
574           }
575         | function_specifier declaration_specifiers
576           {
577                 $$ = $2;
578                 $$->function_specifier |= $1;
579           }
580         | function_specifier
581           {
582                 $$ = gi_source_type_new (CTYPE_INVALID);
583                 $$->function_specifier |= $1;
584           }
585         ;
586
587 init_declarator_list
588         : init_declarator
589           {
590                 $$ = g_list_append (NULL, $1);
591           }
592         | init_declarator_list ',' init_declarator
593           {
594                 $$ = g_list_append ($1, $3);
595           }
596         ;
597
598 init_declarator
599         : declarator
600         | declarator '=' initializer
601         ;
602
603 storage_class_specifier
604         : TYPEDEF
605           {
606                 $$ = STORAGE_CLASS_TYPEDEF;
607           }
608         | EXTERN
609           {
610                 $$ = STORAGE_CLASS_EXTERN;
611           }
612         | STATIC
613           {
614                 $$ = STORAGE_CLASS_STATIC;
615           }
616         | AUTO
617           {
618                 $$ = STORAGE_CLASS_AUTO;
619           }
620         | REGISTER
621           {
622                 $$ = STORAGE_CLASS_REGISTER;
623           }
624         ;
625
626 type_specifier
627         : VOID
628           {
629                 $$ = gi_source_type_new (CTYPE_VOID);
630           }
631         | CHAR
632           {
633                 $$ = gi_source_basic_type_new ("char");
634           }
635         | SHORT
636           {
637                 $$ = gi_source_basic_type_new ("short");
638           }
639         | INT
640           {
641                 $$ = gi_source_basic_type_new ("int");
642           }
643         | LONG
644           {
645                 $$ = gi_source_basic_type_new ("long");
646           }
647         | FLOAT
648           {
649                 $$ = gi_source_basic_type_new ("float");
650           }
651         | DOUBLE
652           {
653                 $$ = gi_source_basic_type_new ("double");
654           }
655         | SIGNED
656           {
657                 $$ = gi_source_basic_type_new ("signed");
658           }
659         | UNSIGNED
660           {
661                 $$ = gi_source_basic_type_new ("unsigned");
662           }
663         | BOOL
664           {
665                 $$ = gi_source_basic_type_new ("bool");
666           }
667         | struct_or_union_specifier
668         | enum_specifier
669         | typedef_name
670           {
671                 $$ = gi_source_typedef_new ($1);
672                 g_free ($1);
673           }
674         ;
675
676 struct_or_union_specifier
677         : struct_or_union identifier_or_typedef_name '{' struct_declaration_list '}'
678           {
679                 $$ = $1;
680                 $$->name = $2;
681                 $$->child_list = $4;
682
683                 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
684                 if ($$->type == CTYPE_STRUCT) {
685                         sym->type = CSYMBOL_TYPE_STRUCT;
686                 } else if ($$->type == CTYPE_UNION) {
687                         sym->type = CSYMBOL_TYPE_UNION;
688                 } else {
689                         g_assert_not_reached ();
690                 }
691                 sym->ident = g_strdup ($$->name);
692                 sym->base_type = gi_source_type_copy ($$);
693                 gi_source_scanner_add_symbol (scanner, sym);
694                 gi_source_symbol_unref (sym);
695           }
696         | struct_or_union '{' struct_declaration_list '}'
697           {
698                 $$ = $1;
699                 $$->child_list = $3;
700           }
701         | struct_or_union identifier_or_typedef_name
702           {
703                 $$ = $1;
704                 $$->name = $2;
705           }
706         ;
707
708 struct_or_union
709         : STRUCT
710           {
711                 $$ = gi_source_struct_new (NULL);
712           }
713         | UNION
714           {
715                 $$ = gi_source_union_new (NULL);
716           }
717         ;
718
719 struct_declaration_list
720         : struct_declaration
721         | struct_declaration_list struct_declaration
722           {
723                 $$ = g_list_concat ($1, $2);
724           }
725         ;
726
727 struct_declaration
728         : specifier_qualifier_list struct_declarator_list ';'
729           {
730             GList *l;
731             $$ = NULL;
732             for (l = $2; l != NULL; l = l->next)
733               {
734                 GISourceSymbol *sym = l->data;
735                 if ($1->storage_class_specifier & STORAGE_CLASS_TYPEDEF)
736                     sym->type = CSYMBOL_TYPE_TYPEDEF;
737                 else
738                     sym->type = CSYMBOL_TYPE_MEMBER;
739                 gi_source_symbol_merge_type (sym, gi_source_type_copy ($1));
740                 $$ = g_list_append ($$, sym);
741               }
742             ctype_free ($1);
743           }
744         ;
745
746 specifier_qualifier_list
747         : type_specifier specifier_qualifier_list
748           {
749                 $$ = $1;
750                 $$->base_type = $2;
751           }
752         | type_specifier
753         | type_qualifier specifier_qualifier_list
754           {
755                 $$ = $2;
756                 $$->type_qualifier |= $1;
757           }
758         | type_qualifier
759           {
760                 $$ = gi_source_type_new (CTYPE_INVALID);
761                 $$->type_qualifier |= $1;
762           }
763         ;
764
765 struct_declarator_list
766         : struct_declarator
767           {
768                 $$ = g_list_append (NULL, $1);
769           }
770         | struct_declarator_list ',' struct_declarator
771           {
772                 $$ = g_list_append ($1, $3);
773           }
774         ;
775
776 struct_declarator
777         : /* empty, support for anonymous structs and unions */
778           {
779                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
780           }
781         | declarator
782         | ':' constant_expression
783           {
784                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
785           }
786         | declarator ':' constant_expression
787         ;
788
789 enum_specifier
790         : ENUM identifier_or_typedef_name '{' enumerator_list '}'
791           {
792                 $$ = gi_source_enum_new ($2);
793                 $$->child_list = $4;
794                 last_enum_value = -1;
795           }
796         | ENUM '{' enumerator_list '}'
797           {
798                 $$ = gi_source_enum_new (NULL);
799                 $$->child_list = $3;
800                 last_enum_value = -1;
801           }
802         | ENUM identifier_or_typedef_name '{' enumerator_list ',' '}'
803           {
804                 $$ = gi_source_enum_new ($2);
805                 $$->child_list = $4;
806                 last_enum_value = -1;
807           }
808         | ENUM '{' enumerator_list ',' '}'
809           {
810                 $$ = gi_source_enum_new (NULL);
811                 $$->child_list = $3;
812                 last_enum_value = -1;
813           }
814         | ENUM identifier_or_typedef_name
815           {
816                 $$ = gi_source_enum_new ($2);
817           }
818         ;
819
820 enumerator_list
821         : enumerator
822           {
823                 $$ = g_list_append (NULL, $1);
824           }
825         | enumerator_list ',' enumerator
826           {
827                 $$ = g_list_append ($1, $3);
828           }
829         ;
830
831 enumerator
832         : identifier
833           {
834                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_OBJECT);
835                 $$->ident = $1;
836                 $$->const_int_set = TRUE;
837                 $$->const_int = ++last_enum_value;
838                 g_hash_table_insert (const_table, g_strdup ($$->ident), gi_source_symbol_ref ($$));
839           }
840         | identifier '=' constant_expression
841           {
842                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_OBJECT);
843                 $$->ident = $1;
844                 $$->const_int_set = TRUE;
845                 $$->const_int = $3->const_int;
846                 last_enum_value = $$->const_int;
847                 g_hash_table_insert (const_table, g_strdup ($$->ident), gi_source_symbol_ref ($$));
848           }
849         ;
850
851 type_qualifier
852         : CONST
853           {
854                 $$ = TYPE_QUALIFIER_CONST;
855           }
856         | RESTRICT
857           {
858                 $$ = TYPE_QUALIFIER_RESTRICT;
859           }
860         | EXTENSION
861           {
862                 $$ = TYPE_QUALIFIER_EXTENSION;
863           }
864         | VOLATILE
865           {
866                 $$ = TYPE_QUALIFIER_VOLATILE;
867           }
868         ;
869
870 function_specifier
871         : INLINE
872           {
873                 $$ = FUNCTION_INLINE;
874           }
875         ;
876
877 declarator
878         : pointer direct_declarator
879           {
880                 $$ = $2;
881                 gi_source_symbol_merge_type ($$, $1);
882           }
883         | direct_declarator
884         ;
885
886 direct_declarator
887         : identifier
888           {
889                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
890                 $$->ident = $1;
891           }
892         | '(' declarator ')'
893           {
894                 $$ = $2;
895           }
896         | direct_declarator '[' assignment_expression ']'
897           {
898                 $$ = $1;
899                 gi_source_symbol_merge_type ($$, gi_source_array_new ());
900           }
901         | direct_declarator '[' ']'
902           {
903                 $$ = $1;
904                 gi_source_symbol_merge_type ($$, gi_source_array_new ());
905           }
906         | direct_declarator '(' parameter_list ')'
907           {
908                 GISourceType *func = gi_source_function_new ();
909                 // ignore (void) parameter list
910                 if ($3 != NULL && ($3->next != NULL || ((GISourceSymbol *) $3->data)->base_type->type != CTYPE_VOID)) {
911                         func->child_list = $3;
912                 }
913                 $$ = $1;
914                 gi_source_symbol_merge_type ($$, func);
915           }
916         | direct_declarator '(' identifier_list ')'
917           {
918                 GISourceType *func = gi_source_function_new ();
919                 func->child_list = $3;
920                 $$ = $1;
921                 gi_source_symbol_merge_type ($$, func);
922           }
923         | direct_declarator '(' ')'
924           {
925                 GISourceType *func = gi_source_function_new ();
926                 $$ = $1;
927                 gi_source_symbol_merge_type ($$, func);
928           }
929         ;
930
931 pointer
932         : '*' type_qualifier_list
933           {
934                 $$ = gi_source_pointer_new (NULL);
935                 $$->type_qualifier = $2;
936           }
937         | '*'
938           {
939                 $$ = gi_source_pointer_new (NULL);
940           }
941         | '*' type_qualifier_list pointer
942           {
943                 $$ = gi_source_pointer_new ($3);
944                 $$->type_qualifier = $2;
945           }
946         | '*' pointer
947           {
948                 $$ = gi_source_pointer_new ($2);
949           }
950         ;
951
952 type_qualifier_list
953         : type_qualifier
954         | type_qualifier_list type_qualifier
955           {
956                 $$ = $1 | $2;
957           }
958         ;
959
960 parameter_list
961         : parameter_declaration
962           {
963                 $$ = g_list_append (NULL, $1);
964           }
965         | parameter_list ',' parameter_declaration
966           {
967                 $$ = g_list_append ($1, $3);
968           }
969         ;
970
971 parameter_declaration
972         : declaration_specifiers declarator
973           {
974                 $$ = $2;
975                 gi_source_symbol_merge_type ($$, $1);
976           }
977         | declaration_specifiers abstract_declarator
978           {
979                 $$ = $2;
980                 gi_source_symbol_merge_type ($$, $1);
981           }
982         | declaration_specifiers
983           {
984                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
985                 $$->base_type = $1;
986           }
987         | ELLIPSIS
988           {
989                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_ELLIPSIS);
990           }
991         ;
992
993 identifier_list
994         : identifier
995           {
996                 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
997                 sym->ident = $1;
998                 $$ = g_list_append (NULL, sym);
999           }
1000         | identifier_list ',' identifier
1001           {
1002                 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1003                 sym->ident = $3;
1004                 $$ = g_list_append ($1, sym);
1005           }
1006         ;
1007
1008 type_name
1009         : specifier_qualifier_list
1010         | specifier_qualifier_list abstract_declarator
1011         ;
1012
1013 abstract_declarator
1014         : pointer
1015           {
1016                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1017                 gi_source_symbol_merge_type ($$, $1);
1018           }
1019         | direct_abstract_declarator
1020         | pointer direct_abstract_declarator
1021           {
1022                 $$ = $2;
1023                 gi_source_symbol_merge_type ($$, $1);
1024           }
1025         ;
1026
1027 direct_abstract_declarator
1028         : '(' abstract_declarator ')'
1029           {
1030                 $$ = $2;
1031           }
1032         | '[' ']'
1033           {
1034                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1035                 gi_source_symbol_merge_type ($$, gi_source_array_new ());
1036           }
1037         | '[' assignment_expression ']'
1038           {
1039                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1040                 gi_source_symbol_merge_type ($$, gi_source_array_new ());
1041           }
1042         | direct_abstract_declarator '[' ']'
1043           {
1044                 $$ = $1;
1045                 gi_source_symbol_merge_type ($$, gi_source_array_new ());
1046           }
1047         | direct_abstract_declarator '[' assignment_expression ']'
1048           {
1049                 $$ = $1;
1050                 gi_source_symbol_merge_type ($$, gi_source_array_new ());
1051           }
1052         | '(' ')'
1053           {
1054                 GISourceType *func = gi_source_function_new ();
1055                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1056                 gi_source_symbol_merge_type ($$, func);
1057           }
1058         | '(' parameter_list ')'
1059           {
1060                 GISourceType *func = gi_source_function_new ();
1061                 // ignore (void) parameter list
1062                 if ($2 != NULL && ($2->next != NULL || ((GISourceSymbol *) $2->data)->base_type->type != CTYPE_VOID)) {
1063                         func->child_list = $2;
1064                 }
1065                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1066                 gi_source_symbol_merge_type ($$, func);
1067           }
1068         | direct_abstract_declarator '(' ')'
1069           {
1070                 GISourceType *func = gi_source_function_new ();
1071                 $$ = $1;
1072                 gi_source_symbol_merge_type ($$, func);
1073           }
1074         | direct_abstract_declarator '(' parameter_list ')'
1075           {
1076                 GISourceType *func = gi_source_function_new ();
1077                 // ignore (void) parameter list
1078                 if ($3 != NULL && ($3->next != NULL || ((GISourceSymbol *) $3->data)->base_type->type != CTYPE_VOID)) {
1079                         func->child_list = $3;
1080                 }
1081                 $$ = $1;
1082                 gi_source_symbol_merge_type ($$, func);
1083           }
1084         ;
1085
1086 typedef_name
1087         : TYPEDEF_NAME
1088           {
1089                 $$ = g_strdup (yytext);
1090           }
1091         ;
1092
1093 initializer
1094         : assignment_expression
1095         | '{' initializer_list '}'
1096         | '{' initializer_list ',' '}'
1097         ;
1098
1099 initializer_list
1100         : initializer
1101         | initializer_list ',' initializer
1102         ;
1103
1104 /* A.2.3 Statements. */
1105
1106 statement
1107         : labeled_statement
1108         | compound_statement
1109         | expression_statement
1110         | selection_statement
1111         | iteration_statement
1112         | jump_statement
1113         ;
1114
1115 labeled_statement
1116         : identifier_or_typedef_name ':' statement
1117         | CASE constant_expression ':' statement
1118         | DEFAULT ':' statement
1119         ;
1120
1121 compound_statement
1122         : '{' '}'
1123         | '{' block_item_list '}'
1124         ;
1125
1126 block_item_list
1127         : block_item
1128         | block_item_list block_item
1129         ;
1130
1131 block_item
1132         : declaration
1133         | statement
1134         ;
1135
1136 expression_statement
1137         : ';'
1138         | expression ';'
1139         ;
1140
1141 selection_statement
1142         : IF '(' expression ')' statement
1143         | IF '(' expression ')' statement ELSE statement
1144         | SWITCH '(' expression ')' statement
1145         ;
1146
1147 iteration_statement
1148         : WHILE '(' expression ')' statement
1149         | DO statement WHILE '(' expression ')' ';'
1150         | FOR '(' ';' ';' ')' statement
1151         | FOR '(' expression ';' ';' ')' statement
1152         | FOR '(' ';' expression ';' ')' statement
1153         | FOR '(' expression ';' expression ';' ')' statement
1154         | FOR '(' ';' ';' expression ')' statement
1155         | FOR '(' expression ';' ';' expression ')' statement
1156         | FOR '(' ';' expression ';' expression ')' statement
1157         | FOR '(' expression ';' expression ';' expression ')' statement
1158         ;
1159
1160 jump_statement
1161         : GOTO identifier_or_typedef_name ';'
1162         | CONTINUE ';'
1163         | BREAK ';'
1164         | RETURN ';'
1165         | RETURN expression ';'
1166         ;
1167
1168 /* A.2.4 External definitions. */
1169
1170 translation_unit
1171         : external_declaration
1172         | translation_unit external_declaration
1173         ;
1174
1175 external_declaration
1176         : function_definition
1177         | declaration
1178         | macro
1179         ;
1180
1181 function_definition
1182         : declaration_specifiers declarator declaration_list compound_statement
1183         | declaration_specifiers declarator compound_statement
1184         ;
1185
1186 declaration_list
1187         : declaration
1188         | declaration_list declaration
1189         ;
1190
1191 /* Macros */
1192
1193 function_macro
1194         : FUNCTION_MACRO
1195           {
1196                 $$ = g_strdup (yytext + strlen ("#define "));
1197           }
1198         ;
1199
1200 object_macro
1201         : OBJECT_MACRO
1202           {
1203                 $$ = g_strdup (yytext + strlen ("#define "));
1204           }
1205         ;
1206
1207 function_macro_define
1208         : function_macro '(' identifier_list ')'
1209         ;
1210
1211 object_macro_define
1212         : object_macro constant_expression
1213           {
1214                 if ($2->const_int_set || $2->const_string != NULL) {
1215                         $2->ident = $1;
1216                         gi_source_scanner_add_symbol (scanner, $2);
1217                         gi_source_symbol_unref ($2);
1218                 }
1219           }
1220         ;
1221
1222 macro
1223         : function_macro_define
1224         | object_macro_define
1225         | error
1226         ;
1227
1228 %%
1229 static void
1230 yyerror (GISourceScanner *scanner, const char *s)
1231 {
1232   /* ignore errors while doing a macro scan as not all object macros
1233    * have valid expressions */
1234   if (!scanner->macro_scan)
1235     {
1236       fprintf(stderr, "%s:%d: %s\n",
1237               scanner->current_filename, lineno, s);
1238     }
1239 }
1240
1241 gboolean
1242 gi_source_scanner_parse_file (GISourceScanner *scanner, FILE *file)
1243 {
1244   g_return_val_if_fail (file != NULL, FALSE);
1245   
1246   const_table = g_hash_table_new_full (g_str_hash, g_str_equal,
1247                                        g_free, (GDestroyNotify)gi_source_symbol_unref);
1248   
1249   lineno = 1;
1250   yyin = file;
1251   yyparse (scanner);
1252   
1253   g_hash_table_destroy (const_table);
1254   const_table = NULL;
1255   
1256   yyin = NULL;
1257
1258   return TRUE;
1259 }
1260
1261 gboolean
1262 gi_source_scanner_lex_filename (GISourceScanner *scanner, const gchar *filename)
1263 {
1264   yyin = fopen (filename, "r");
1265
1266   while (yylex (scanner) != YYEOF)
1267     ;
1268
1269   fclose (yyin);
1270   
1271   return TRUE;
1272 }