43635bd793293a0dad9931b622adced662a12e82
[gnome.gobject-introspection] / 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                 /* combine basic types like unsigned int and long long */
563                 if ($$->type == CTYPE_BASIC_TYPE && $2->type == CTYPE_BASIC_TYPE) {
564                         char *name = g_strdup_printf ("%s %s", $$->name, $2->name);
565                         g_free ($$->name);
566                         $$->name = name;
567                         ctype_free ($2);
568                 } else {
569                         $$->base_type = $2;
570                 }
571           }
572         | type_specifier
573         | type_qualifier declaration_specifiers
574           {
575                 $$ = $2;
576                 $$->type_qualifier |= $1;
577           }
578         | type_qualifier
579           {
580                 $$ = gi_source_type_new (CTYPE_INVALID);
581                 $$->type_qualifier |= $1;
582           }
583         | function_specifier declaration_specifiers
584           {
585                 $$ = $2;
586                 $$->function_specifier |= $1;
587           }
588         | function_specifier
589           {
590                 $$ = gi_source_type_new (CTYPE_INVALID);
591                 $$->function_specifier |= $1;
592           }
593         ;
594
595 init_declarator_list
596         : init_declarator
597           {
598                 $$ = g_list_append (NULL, $1);
599           }
600         | init_declarator_list ',' init_declarator
601           {
602                 $$ = g_list_append ($1, $3);
603           }
604         ;
605
606 init_declarator
607         : declarator
608         | declarator '=' initializer
609         ;
610
611 storage_class_specifier
612         : TYPEDEF
613           {
614                 $$ = STORAGE_CLASS_TYPEDEF;
615           }
616         | EXTERN
617           {
618                 $$ = STORAGE_CLASS_EXTERN;
619           }
620         | STATIC
621           {
622                 $$ = STORAGE_CLASS_STATIC;
623           }
624         | AUTO
625           {
626                 $$ = STORAGE_CLASS_AUTO;
627           }
628         | REGISTER
629           {
630                 $$ = STORAGE_CLASS_REGISTER;
631           }
632         ;
633
634 type_specifier
635         : VOID
636           {
637                 $$ = gi_source_type_new (CTYPE_VOID);
638           }
639         | CHAR
640           {
641                 $$ = gi_source_basic_type_new ("char");
642           }
643         | SHORT
644           {
645                 $$ = gi_source_basic_type_new ("short");
646           }
647         | INT
648           {
649                 $$ = gi_source_basic_type_new ("int");
650           }
651         | LONG
652           {
653                 $$ = gi_source_basic_type_new ("long");
654           }
655         | FLOAT
656           {
657                 $$ = gi_source_basic_type_new ("float");
658           }
659         | DOUBLE
660           {
661                 $$ = gi_source_basic_type_new ("double");
662           }
663         | SIGNED
664           {
665                 $$ = gi_source_basic_type_new ("signed");
666           }
667         | UNSIGNED
668           {
669                 $$ = gi_source_basic_type_new ("unsigned");
670           }
671         | BOOL
672           {
673                 $$ = gi_source_basic_type_new ("bool");
674           }
675         | struct_or_union_specifier
676         | enum_specifier
677         | typedef_name
678           {
679                 $$ = gi_source_typedef_new ($1);
680                 g_free ($1);
681           }
682         ;
683
684 struct_or_union_specifier
685         : struct_or_union identifier_or_typedef_name '{' struct_declaration_list '}'
686           {
687                 $$ = $1;
688                 $$->name = $2;
689                 $$->child_list = $4;
690
691                 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
692                 if ($$->type == CTYPE_STRUCT) {
693                         sym->type = CSYMBOL_TYPE_STRUCT;
694                 } else if ($$->type == CTYPE_UNION) {
695                         sym->type = CSYMBOL_TYPE_UNION;
696                 } else {
697                         g_assert_not_reached ();
698                 }
699                 sym->ident = g_strdup ($$->name);
700                 sym->base_type = gi_source_type_copy ($$);
701                 gi_source_scanner_add_symbol (scanner, sym);
702                 gi_source_symbol_unref (sym);
703           }
704         | struct_or_union '{' struct_declaration_list '}'
705           {
706                 $$ = $1;
707                 $$->child_list = $3;
708           }
709         | struct_or_union identifier_or_typedef_name
710           {
711                 $$ = $1;
712                 $$->name = $2;
713           }
714         ;
715
716 struct_or_union
717         : STRUCT
718           {
719                 $$ = gi_source_struct_new (NULL);
720           }
721         | UNION
722           {
723                 $$ = gi_source_union_new (NULL);
724           }
725         ;
726
727 struct_declaration_list
728         : struct_declaration
729         | struct_declaration_list struct_declaration
730           {
731                 $$ = g_list_concat ($1, $2);
732           }
733         ;
734
735 struct_declaration
736         : specifier_qualifier_list struct_declarator_list ';'
737           {
738             GList *l;
739             $$ = NULL;
740             for (l = $2; l != NULL; l = l->next)
741               {
742                 GISourceSymbol *sym = l->data;
743                 if ($1->storage_class_specifier & STORAGE_CLASS_TYPEDEF)
744                     sym->type = CSYMBOL_TYPE_TYPEDEF;
745                 else
746                     sym->type = CSYMBOL_TYPE_MEMBER;
747                 gi_source_symbol_merge_type (sym, gi_source_type_copy ($1));
748                 $$ = g_list_append ($$, sym);
749               }
750             ctype_free ($1);
751           }
752         ;
753
754 specifier_qualifier_list
755         : type_specifier specifier_qualifier_list
756           {
757                 $$ = $1;
758                 $$->base_type = $2;
759           }
760         | type_specifier
761         | type_qualifier specifier_qualifier_list
762           {
763                 $$ = $2;
764                 $$->type_qualifier |= $1;
765           }
766         | type_qualifier
767           {
768                 $$ = gi_source_type_new (CTYPE_INVALID);
769                 $$->type_qualifier |= $1;
770           }
771         ;
772
773 struct_declarator_list
774         : struct_declarator
775           {
776                 $$ = g_list_append (NULL, $1);
777           }
778         | struct_declarator_list ',' struct_declarator
779           {
780                 $$ = g_list_append ($1, $3);
781           }
782         ;
783
784 struct_declarator
785         : /* empty, support for anonymous structs and unions */
786           {
787                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
788           }
789         | declarator
790         | ':' constant_expression
791           {
792                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
793           }
794         | declarator ':' constant_expression
795           {
796                 $$ = $1;
797                 if ($3->const_int_set) {
798                   $$->const_int_set = TRUE;
799                   $$->const_int = $3->const_int;
800                 }
801           }
802         ;
803
804 enum_specifier
805         : ENUM identifier_or_typedef_name '{' enumerator_list '}'
806           {
807                 $$ = gi_source_enum_new ($2);
808                 $$->child_list = $4;
809                 last_enum_value = -1;
810           }
811         | ENUM '{' enumerator_list '}'
812           {
813                 $$ = gi_source_enum_new (NULL);
814                 $$->child_list = $3;
815                 last_enum_value = -1;
816           }
817         | ENUM identifier_or_typedef_name '{' enumerator_list ',' '}'
818           {
819                 $$ = gi_source_enum_new ($2);
820                 $$->child_list = $4;
821                 last_enum_value = -1;
822           }
823         | ENUM '{' enumerator_list ',' '}'
824           {
825                 $$ = gi_source_enum_new (NULL);
826                 $$->child_list = $3;
827                 last_enum_value = -1;
828           }
829         | ENUM identifier_or_typedef_name
830           {
831                 $$ = gi_source_enum_new ($2);
832           }
833         ;
834
835 enumerator_list
836         : enumerator
837           {
838                 $$ = g_list_append (NULL, $1);
839           }
840         | enumerator_list ',' enumerator
841           {
842                 $$ = g_list_append ($1, $3);
843           }
844         ;
845
846 enumerator
847         : identifier
848           {
849                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_OBJECT);
850                 $$->ident = $1;
851                 $$->const_int_set = TRUE;
852                 $$->const_int = ++last_enum_value;
853                 g_hash_table_insert (const_table, g_strdup ($$->ident), gi_source_symbol_ref ($$));
854           }
855         | identifier '=' constant_expression
856           {
857                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_OBJECT);
858                 $$->ident = $1;
859                 $$->const_int_set = TRUE;
860                 $$->const_int = $3->const_int;
861                 last_enum_value = $$->const_int;
862                 g_hash_table_insert (const_table, g_strdup ($$->ident), gi_source_symbol_ref ($$));
863           }
864         ;
865
866 type_qualifier
867         : CONST
868           {
869                 $$ = TYPE_QUALIFIER_CONST;
870           }
871         | RESTRICT
872           {
873                 $$ = TYPE_QUALIFIER_RESTRICT;
874           }
875         | EXTENSION
876           {
877                 $$ = TYPE_QUALIFIER_EXTENSION;
878           }
879         | VOLATILE
880           {
881                 $$ = TYPE_QUALIFIER_VOLATILE;
882           }
883         ;
884
885 function_specifier
886         : INLINE
887           {
888                 $$ = FUNCTION_INLINE;
889           }
890         ;
891
892 declarator
893         : pointer direct_declarator
894           {
895                 $$ = $2;
896                 gi_source_symbol_merge_type ($$, $1);
897           }
898         | direct_declarator
899         ;
900
901 direct_declarator
902         : identifier
903           {
904                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
905                 $$->ident = $1;
906           }
907         | '(' declarator ')'
908           {
909                 $$ = $2;
910           }
911         | direct_declarator '[' assignment_expression ']'
912           {
913                 $$ = $1;
914                 gi_source_symbol_merge_type ($$, gi_source_array_new ());
915           }
916         | direct_declarator '[' ']'
917           {
918                 $$ = $1;
919                 gi_source_symbol_merge_type ($$, gi_source_array_new ());
920           }
921         | direct_declarator '(' parameter_list ')'
922           {
923                 GISourceType *func = gi_source_function_new ();
924                 // ignore (void) parameter list
925                 if ($3 != NULL && ($3->next != NULL || ((GISourceSymbol *) $3->data)->base_type->type != CTYPE_VOID)) {
926                         func->child_list = $3;
927                 }
928                 $$ = $1;
929                 gi_source_symbol_merge_type ($$, func);
930           }
931         | direct_declarator '(' identifier_list ')'
932           {
933                 GISourceType *func = gi_source_function_new ();
934                 func->child_list = $3;
935                 $$ = $1;
936                 gi_source_symbol_merge_type ($$, func);
937           }
938         | direct_declarator '(' ')'
939           {
940                 GISourceType *func = gi_source_function_new ();
941                 $$ = $1;
942                 gi_source_symbol_merge_type ($$, func);
943           }
944         ;
945
946 pointer
947         : '*' type_qualifier_list
948           {
949                 $$ = gi_source_pointer_new (NULL);
950                 $$->type_qualifier = $2;
951           }
952         | '*'
953           {
954                 $$ = gi_source_pointer_new (NULL);
955           }
956         | '*' type_qualifier_list pointer
957           {
958                 $$ = gi_source_pointer_new ($3);
959                 $$->type_qualifier = $2;
960           }
961         | '*' pointer
962           {
963                 $$ = gi_source_pointer_new ($2);
964           }
965         ;
966
967 type_qualifier_list
968         : type_qualifier
969         | type_qualifier_list type_qualifier
970           {
971                 $$ = $1 | $2;
972           }
973         ;
974
975 parameter_list
976         : parameter_declaration
977           {
978                 $$ = g_list_append (NULL, $1);
979           }
980         | parameter_list ',' parameter_declaration
981           {
982                 $$ = g_list_append ($1, $3);
983           }
984         ;
985
986 parameter_declaration
987         : declaration_specifiers declarator
988           {
989                 $$ = $2;
990                 gi_source_symbol_merge_type ($$, $1);
991           }
992         | declaration_specifiers abstract_declarator
993           {
994                 $$ = $2;
995                 gi_source_symbol_merge_type ($$, $1);
996           }
997         | declaration_specifiers
998           {
999                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1000                 $$->base_type = $1;
1001           }
1002         | ELLIPSIS
1003           {
1004                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_ELLIPSIS);
1005           }
1006         ;
1007
1008 identifier_list
1009         : identifier
1010           {
1011                 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1012                 sym->ident = $1;
1013                 $$ = g_list_append (NULL, sym);
1014           }
1015         | identifier_list ',' identifier
1016           {
1017                 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1018                 sym->ident = $3;
1019                 $$ = g_list_append ($1, sym);
1020           }
1021         ;
1022
1023 type_name
1024         : specifier_qualifier_list
1025         | specifier_qualifier_list abstract_declarator
1026         ;
1027
1028 abstract_declarator
1029         : pointer
1030           {
1031                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1032                 gi_source_symbol_merge_type ($$, $1);
1033           }
1034         | direct_abstract_declarator
1035         | pointer direct_abstract_declarator
1036           {
1037                 $$ = $2;
1038                 gi_source_symbol_merge_type ($$, $1);
1039           }
1040         ;
1041
1042 direct_abstract_declarator
1043         : '(' abstract_declarator ')'
1044           {
1045                 $$ = $2;
1046           }
1047         | '[' ']'
1048           {
1049                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1050                 gi_source_symbol_merge_type ($$, gi_source_array_new ());
1051           }
1052         | '[' assignment_expression ']'
1053           {
1054                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1055                 gi_source_symbol_merge_type ($$, gi_source_array_new ());
1056           }
1057         | direct_abstract_declarator '[' ']'
1058           {
1059                 $$ = $1;
1060                 gi_source_symbol_merge_type ($$, gi_source_array_new ());
1061           }
1062         | direct_abstract_declarator '[' assignment_expression ']'
1063           {
1064                 $$ = $1;
1065                 gi_source_symbol_merge_type ($$, gi_source_array_new ());
1066           }
1067         | '(' ')'
1068           {
1069                 GISourceType *func = gi_source_function_new ();
1070                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1071                 gi_source_symbol_merge_type ($$, func);
1072           }
1073         | '(' parameter_list ')'
1074           {
1075                 GISourceType *func = gi_source_function_new ();
1076                 // ignore (void) parameter list
1077                 if ($2 != NULL && ($2->next != NULL || ((GISourceSymbol *) $2->data)->base_type->type != CTYPE_VOID)) {
1078                         func->child_list = $2;
1079                 }
1080                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1081                 gi_source_symbol_merge_type ($$, func);
1082           }
1083         | direct_abstract_declarator '(' ')'
1084           {
1085                 GISourceType *func = gi_source_function_new ();
1086                 $$ = $1;
1087                 gi_source_symbol_merge_type ($$, func);
1088           }
1089         | direct_abstract_declarator '(' parameter_list ')'
1090           {
1091                 GISourceType *func = gi_source_function_new ();
1092                 // ignore (void) parameter list
1093                 if ($3 != NULL && ($3->next != NULL || ((GISourceSymbol *) $3->data)->base_type->type != CTYPE_VOID)) {
1094                         func->child_list = $3;
1095                 }
1096                 $$ = $1;
1097                 gi_source_symbol_merge_type ($$, func);
1098           }
1099         ;
1100
1101 typedef_name
1102         : TYPEDEF_NAME
1103           {
1104                 $$ = g_strdup (yytext);
1105           }
1106         ;
1107
1108 initializer
1109         : assignment_expression
1110         | '{' initializer_list '}'
1111         | '{' initializer_list ',' '}'
1112         ;
1113
1114 initializer_list
1115         : initializer
1116         | initializer_list ',' initializer
1117         ;
1118
1119 /* A.2.3 Statements. */
1120
1121 statement
1122         : labeled_statement
1123         | compound_statement
1124         | expression_statement
1125         | selection_statement
1126         | iteration_statement
1127         | jump_statement
1128         ;
1129
1130 labeled_statement
1131         : identifier_or_typedef_name ':' statement
1132         | CASE constant_expression ':' statement
1133         | DEFAULT ':' statement
1134         ;
1135
1136 compound_statement
1137         : '{' '}'
1138         | '{' block_item_list '}'
1139         ;
1140
1141 block_item_list
1142         : block_item
1143         | block_item_list block_item
1144         ;
1145
1146 block_item
1147         : declaration
1148         | statement
1149         ;
1150
1151 expression_statement
1152         : ';'
1153         | expression ';'
1154         ;
1155
1156 selection_statement
1157         : IF '(' expression ')' statement
1158         | IF '(' expression ')' statement ELSE statement
1159         | SWITCH '(' expression ')' statement
1160         ;
1161
1162 iteration_statement
1163         : WHILE '(' expression ')' statement
1164         | DO statement WHILE '(' expression ')' ';'
1165         | FOR '(' ';' ';' ')' statement
1166         | FOR '(' expression ';' ';' ')' statement
1167         | FOR '(' ';' expression ';' ')' statement
1168         | FOR '(' expression ';' expression ';' ')' statement
1169         | FOR '(' ';' ';' expression ')' statement
1170         | FOR '(' expression ';' ';' expression ')' statement
1171         | FOR '(' ';' expression ';' expression ')' statement
1172         | FOR '(' expression ';' expression ';' expression ')' statement
1173         ;
1174
1175 jump_statement
1176         : GOTO identifier_or_typedef_name ';'
1177         | CONTINUE ';'
1178         | BREAK ';'
1179         | RETURN ';'
1180         | RETURN expression ';'
1181         ;
1182
1183 /* A.2.4 External definitions. */
1184
1185 translation_unit
1186         : external_declaration
1187         | translation_unit external_declaration
1188         ;
1189
1190 external_declaration
1191         : function_definition
1192         | declaration
1193         | macro
1194         ;
1195
1196 function_definition
1197         : declaration_specifiers declarator declaration_list compound_statement
1198         | declaration_specifiers declarator compound_statement
1199         ;
1200
1201 declaration_list
1202         : declaration
1203         | declaration_list declaration
1204         ;
1205
1206 /* Macros */
1207
1208 function_macro
1209         : FUNCTION_MACRO
1210           {
1211                 $$ = g_strdup (yytext + strlen ("#define "));
1212           }
1213         ;
1214
1215 object_macro
1216         : OBJECT_MACRO
1217           {
1218                 $$ = g_strdup (yytext + strlen ("#define "));
1219           }
1220         ;
1221
1222 function_macro_define
1223         : function_macro '(' identifier_list ')'
1224         ;
1225
1226 object_macro_define
1227         : object_macro constant_expression
1228           {
1229                 if ($2->const_int_set || $2->const_string != NULL) {
1230                         $2->ident = $1;
1231                         gi_source_scanner_add_symbol (scanner, $2);
1232                         gi_source_symbol_unref ($2);
1233                 }
1234           }
1235         ;
1236
1237 macro
1238         : function_macro_define
1239         | object_macro_define
1240         | error
1241         ;
1242
1243 %%
1244 static void
1245 yyerror (GISourceScanner *scanner, const char *s)
1246 {
1247   /* ignore errors while doing a macro scan as not all object macros
1248    * have valid expressions */
1249   if (!scanner->macro_scan)
1250     {
1251       fprintf(stderr, "%s:%d: %s\n",
1252               scanner->current_filename, lineno, s);
1253     }
1254 }
1255
1256 gboolean
1257 gi_source_scanner_parse_file (GISourceScanner *scanner, FILE *file)
1258 {
1259   g_return_val_if_fail (file != NULL, FALSE);
1260   
1261   const_table = g_hash_table_new_full (g_str_hash, g_str_equal,
1262                                        g_free, (GDestroyNotify)gi_source_symbol_unref);
1263   
1264   lineno = 1;
1265   yyin = file;
1266   yyparse (scanner);
1267   
1268   g_hash_table_destroy (const_table);
1269   const_table = NULL;
1270   
1271   yyin = NULL;
1272
1273   return TRUE;
1274 }
1275
1276 gboolean
1277 gi_source_scanner_lex_filename (GISourceScanner *scanner, const gchar *filename)
1278 {
1279   yyin = fopen (filename, "r");
1280
1281   while (yylex (scanner) != YYEOF)
1282     ;
1283
1284   fclose (yyin);
1285   
1286   return TRUE;
1287 }