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