]> matita.cs.unibo.it Git - pkg-cerco/acc.git/blob - cparser/Parser.mly
Package description and copyright added.
[pkg-cerco/acc.git] / cparser / Parser.mly
1 /*(*
2  *
3  * Copyright (c) 2001-2003,
4  *  George C. Necula    <necula@cs.berkeley.edu>
5  *  Scott McPeak        <smcpeak@cs.berkeley.edu>
6  *  Wes Weimer          <weimer@cs.berkeley.edu>
7  *  Ben Liblit          <liblit@cs.berkeley.edu>
8  * All rights reserved.
9  * 
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are
12  * met:
13  *
14  * 1. Redistributions of source code must retain the above copyright
15  * notice, this list of conditions and the following disclaimer.
16  *
17  * 2. Redistributions in binary form must reproduce the above copyright
18  * notice, this list of conditions and the following disclaimer in the
19  * documentation and/or other materials provided with the distribution.
20  *
21  * 3. The names of the contributors may not be used to endorse or promote
22  * products derived from this software without specific prior written
23  * permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
26  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
28  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
29  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  *
37  **)
38 (**
39 ** 1.0  3.22.99 Hugues Cassé    First version.
40 ** 2.0  George Necula 12/12/00: Practically complete rewrite.
41 *)
42 */
43 %{
44 open Cabs
45 open Cabshelper
46 open Parse_aux
47
48 (*
49 ** Expression building
50 *)
51 let smooth_expression lst =
52   match lst with
53     [] -> NOTHING
54   | [expr] -> expr
55   | _ -> COMMA (lst)
56
57
58 let currentFunctionName = ref "<outside any function>"
59     
60 let announceFunctionName ((n, decl, _, _):name) =
61   !add_identifier n;
62   (* Start a context that includes the parameter names and the whole body. 
63    * Will pop when we finish parsing the function body *)
64   !push_context ();
65   (* Go through all the parameter names and mark them as identifiers *)
66   let rec findProto = function
67       PROTO (d, args, _) when isJUSTBASE d -> 
68         List.iter (fun (_, (an, _, _, _)) -> !add_identifier an) args
69
70     | PROTO (d, _, _) -> findProto d
71     | PARENTYPE (_, d, _) -> findProto d
72     | PTR (_, d) -> findProto d
73     | ARRAY (d, _, _) -> findProto d
74     | _ -> parse_error "Cannot find the prototype in a function definition";
75            raise Parsing.Parse_error 
76
77   and isJUSTBASE = function
78       JUSTBASE -> true
79     | PARENTYPE (_, d, _) -> isJUSTBASE d
80     | _ -> false
81   in
82   findProto decl;
83   currentFunctionName := n
84
85
86
87 let applyPointer (ptspecs: attribute list list) (dt: decl_type)  
88        : decl_type = 
89   (* Outer specification first *)
90   let rec loop = function
91       [] -> dt
92     | attrs :: rest -> PTR(attrs, loop rest)
93   in
94   loop ptspecs
95
96 let doDeclaration (loc: cabsloc) (specs: spec_elem list) (nl: init_name list) : definition = 
97   if isTypedef specs then begin
98     (* Tell the lexer about the new type names *)
99     List.iter (fun ((n, _, _, _), _) -> !add_type n) nl;
100     TYPEDEF ((specs, List.map (fun (n, _) -> n) nl), loc)
101   end else
102     if nl = [] then
103       ONLYTYPEDEF (specs, loc)
104     else begin
105       (* Tell the lexer about the new variable names *)
106       List.iter (fun ((n, _, _, _), _) -> !add_identifier n) nl;
107       DECDEF ((specs, nl), loc)  
108     end
109
110
111 let doFunctionDef (loc: cabsloc)
112                   (lend: cabsloc)
113                   (specs: spec_elem list) 
114                   (n: name) 
115                   (b: block) : definition = 
116   let fname = (specs, n) in
117   FUNDEF (fname, b, loc, lend)
118
119
120 let doOldParDecl (names: string list)
121                  ((pardefs: name_group list), (isva: bool)) 
122     : single_name list * bool =
123   let findOneName n =
124     (* Search in pardefs for the definition for this parameter *)
125     let rec loopGroups = function
126         [] -> ([SpecType Tint], (n, JUSTBASE, [], cabslu))
127       | (specs, names) :: restgroups ->
128           let rec loopNames = function
129               [] -> loopGroups restgroups
130             | ((n',_, _, _) as sn) :: _ when n' = n -> (specs, sn)
131             | _ :: restnames -> loopNames restnames
132           in
133           loopNames names
134     in
135     loopGroups pardefs
136   in
137   let args = List.map findOneName names in
138   (args, isva)
139
140 let int64_to_char value =
141   if (compare value (Int64.of_int 255) > 0) || (compare value Int64.zero < 0) then
142     begin
143       let msg = Printf.sprintf "cparser:intlist_to_string: character 0x%Lx too big" value in
144       parse_error msg;
145       raise Parsing.Parse_error
146     end
147   else
148     Char.chr (Int64.to_int value)
149
150 (* takes a not-nul-terminated list, and converts it to a string. *)
151 let rec intlist_to_string (str: int64 list):string =
152   match str with
153     [] -> ""  (* add nul-termination *)
154   | value::rest ->
155       let this_char = int64_to_char value in
156       (String.make 1 this_char) ^ (intlist_to_string rest)
157
158 let fst3 (result, _, _) = result
159 let snd3 (_, result, _) = result
160 let trd3 (_, _, result) = result
161
162
163 (*
164    transform:  __builtin_offsetof(type, member)
165    into     :  (size_t) (&(type * ) 0)->member
166  *)
167
168 let transformOffsetOf (speclist, dtype) member =
169   let rec addPointer = function
170     | JUSTBASE ->
171         PTR([], JUSTBASE)
172     | PARENTYPE (attrs1, dtype, attrs2) ->
173         PARENTYPE (attrs1, addPointer dtype, attrs2)
174     | ARRAY (dtype, attrs, expr) ->
175         ARRAY (addPointer dtype, attrs, expr)
176     | PTR (attrs, dtype) ->
177         PTR (attrs, addPointer dtype)
178     | PROTO (dtype, names, variadic) ->
179         PROTO (addPointer dtype, names, variadic)
180   in
181   let nullType = (speclist, addPointer dtype) in
182   let nullExpr = CONSTANT (CONST_INT "0") in
183   let castExpr = CAST (nullType, SINGLE_INIT nullExpr) in
184
185   let rec replaceBase = function
186     | VARIABLE field ->
187         MEMBEROFPTR (castExpr, field)
188     | MEMBEROF (base, field) ->
189         MEMBEROF (replaceBase base, field)
190     | INDEX (base, index) ->
191         INDEX (replaceBase base, index)
192     | _ ->
193         parse_error "malformed offset expression in __builtin_offsetof";
194         raise Parsing.Parse_error 
195   in
196   let memberExpr = replaceBase member in
197   let addrExpr = UNARY (ADDROF, memberExpr) in
198   (* slight cheat: hard-coded assumption that size_t == unsigned int *)
199   let sizeofType = [SpecType Tunsigned], JUSTBASE in
200   let resultExpr = CAST (sizeofType, SINGLE_INIT addrExpr) in
201   resultExpr
202
203 %}
204
205 %token <string * Cabs.cabsloc> IDENT
206 %token <int64 list * Cabs.cabsloc> CST_CHAR
207 %token <int64 list * Cabs.cabsloc> CST_WCHAR
208 %token <string * Cabs.cabsloc> CST_INT
209 %token <string * Cabs.cabsloc> CST_FLOAT
210 %token <string * Cabs.cabsloc> NAMED_TYPE
211
212 /* Each character is its own list element, and the terminating nul is not
213    included in this list. */
214 %token <int64 list * Cabs.cabsloc> CST_STRING   
215 %token <int64 list * Cabs.cabsloc> CST_WSTRING
216
217 %token EOF
218 %token<Cabs.cabsloc> CHAR INT DOUBLE FLOAT VOID INT64 INT32 UNDERSCORE_BOOL
219 %token<Cabs.cabsloc> ENUM STRUCT TYPEDEF UNION
220 %token<Cabs.cabsloc> SIGNED UNSIGNED LONG SHORT
221 %token<Cabs.cabsloc> VOLATILE EXTERN STATIC CONST RESTRICT AUTO REGISTER
222 %token<Cabs.cabsloc> THREAD
223
224 %token<Cabs.cabsloc> SIZEOF ALIGNOF
225
226 %token EQ PLUS_EQ MINUS_EQ STAR_EQ SLASH_EQ PERCENT_EQ
227 %token AND_EQ PIPE_EQ CIRC_EQ INF_INF_EQ SUP_SUP_EQ
228 %token ARROW DOT
229
230 %token EQ_EQ EXCLAM_EQ INF SUP INF_EQ SUP_EQ
231 %token<Cabs.cabsloc> PLUS MINUS STAR
232 %token SLASH PERCENT
233 %token<Cabs.cabsloc> TILDE AND
234 %token PIPE CIRC
235 %token<Cabs.cabsloc> EXCLAM AND_AND
236 %token PIPE_PIPE
237 %token INF_INF SUP_SUP
238 %token<Cabs.cabsloc> PLUS_PLUS MINUS_MINUS
239
240 %token RPAREN 
241 %token<Cabs.cabsloc> LPAREN RBRACE
242 %token<Cabs.cabsloc> LBRACE
243 %token LBRACKET RBRACKET
244 %token COLON
245 %token<Cabs.cabsloc> SEMICOLON
246 %token COMMA ELLIPSIS QUEST
247
248 %token<Cabs.cabsloc> BREAK CONTINUE GOTO RETURN
249 %token<Cabs.cabsloc> SWITCH CASE DEFAULT
250 %token<Cabs.cabsloc> WHILE DO FOR
251 %token<Cabs.cabsloc> IF TRY EXCEPT FINALLY
252 %token ELSE 
253
254 %token<Cabs.cabsloc> ATTRIBUTE INLINE ASM TYPEOF FUNCTION__ PRETTY_FUNCTION__
255 %token LABEL__
256 %token<Cabs.cabsloc> BUILTIN_VA_ARG ATTRIBUTE_USED
257 %token BUILTIN_VA_LIST
258 %token BLOCKATTRIBUTE 
259 %token<Cabs.cabsloc> BUILTIN_TYPES_COMPAT BUILTIN_OFFSETOF
260 %token<Cabs.cabsloc> DECLSPEC
261 %token<string * Cabs.cabsloc> MSASM MSATTR
262 %token<string * Cabs.cabsloc> PRAGMA_LINE
263 %token PRAGMA_EOL
264
265 /* operator precedence */
266 %nonassoc       IF
267 %nonassoc       ELSE
268
269
270 %left   COMMA
271 %right  EQ PLUS_EQ MINUS_EQ STAR_EQ SLASH_EQ PERCENT_EQ
272                 AND_EQ PIPE_EQ CIRC_EQ INF_INF_EQ SUP_SUP_EQ
273 %right  QUEST COLON
274 %left   PIPE_PIPE
275 %left   AND_AND
276 %left   PIPE
277 %left   CIRC
278 %left   AND
279 %left   EQ_EQ EXCLAM_EQ
280 %left   INF SUP INF_EQ SUP_EQ
281 %left   INF_INF SUP_SUP
282 %left   PLUS MINUS
283 %left   STAR SLASH PERCENT CONST RESTRICT VOLATILE
284 %right  EXCLAM TILDE PLUS_PLUS MINUS_MINUS CAST RPAREN ADDROF SIZEOF ALIGNOF
285 %left   LBRACKET
286 %left   DOT ARROW LPAREN LBRACE
287 %right  NAMED_TYPE     /* We'll use this to handle redefinitions of
288                         * NAMED_TYPE as variables */
289 %left   IDENT
290
291 /* Non-terminals informations */
292 %start interpret file
293 %type <Cabs.definition list> file interpret globals
294
295 %type <Cabs.definition> global
296
297
298 %type <Cabs.attribute list> attributes attributes_with_asm asmattr
299 %type <Cabs.statement> statement
300 %type <Cabs.constant * cabsloc> constant
301 %type <string * cabsloc> string_constant
302 %type <Cabs.expression * cabsloc> expression
303 %type <Cabs.expression> opt_expression
304 %type <Cabs.init_expression> init_expression
305 %type <Cabs.expression list * cabsloc> comma_expression
306 %type <Cabs.expression list * cabsloc> paren_comma_expression
307 %type <Cabs.expression list> arguments
308 %type <Cabs.expression list> bracket_comma_expression
309 %type <int64 list Queue.t * cabsloc> string_list 
310 %type <int64 list * cabsloc> wstring_list
311
312 %type <Cabs.initwhat * Cabs.init_expression> initializer
313 %type <(Cabs.initwhat * Cabs.init_expression) list> initializer_list
314 %type <Cabs.initwhat> init_designators init_designators_opt
315
316 %type <spec_elem list * cabsloc> decl_spec_list
317 %type <typeSpecifier * cabsloc> type_spec
318 %type <Cabs.field_group list> struct_decl_list
319
320
321 %type <Cabs.name> old_proto_decl
322 %type <Cabs.single_name> parameter_decl
323 %type <Cabs.enum_item> enumerator
324 %type <Cabs.enum_item list> enum_list
325 %type <Cabs.definition> declaration function_def
326 %type <cabsloc * spec_elem list * name> function_def_start
327 %type <Cabs.spec_elem list * Cabs.decl_type> type_name
328 %type <Cabs.block * cabsloc * cabsloc> block
329 %type <Cabs.statement list> block_element_list
330 %type <string list> local_labels local_label_names
331 %type <string list> old_parameter_list_ne
332
333 %type <Cabs.init_name> init_declarator
334 %type <Cabs.init_name list> init_declarator_list
335 %type <Cabs.name> declarator
336 %type <Cabs.name * expression option> field_decl
337 %type <(Cabs.name * expression option) list> field_decl_list
338 %type <string * Cabs.decl_type> direct_decl
339 %type <Cabs.decl_type> abs_direct_decl abs_direct_decl_opt
340 %type <Cabs.decl_type * Cabs.attribute list> abstract_decl
341
342  /* (* Each element is a "* <type_quals_opt>". *) */
343 %type <attribute list list * cabsloc> pointer pointer_opt
344 %type <Cabs.cabsloc> location
345 %type <Cabs.spec_elem * cabsloc> cvspec
346 %%
347
348 interpret:
349   file EOF                              {$1}
350 ;
351 file: globals                           {$1}
352 ;
353 globals:
354   /* empty */                           { [] }
355 | global globals                        { $1 :: $2 }
356 | SEMICOLON globals                     { $2 }
357 ;
358
359 location:
360    /* empty */                  { currentLoc () }  %prec IDENT
361
362
363 /*** Global Definition ***/
364 global:
365 | declaration                           { $1 }
366 | function_def                          { $1 } 
367 /*(* Some C header files ar shared with the C++ compiler and have linkage 
368    * specification *)*/
369 | EXTERN string_constant declaration    { LINKAGE (fst $2, (*handleLoc*) (snd $2), [ $3 ]) }
370 | EXTERN string_constant LBRACE globals RBRACE 
371                                         { LINKAGE (fst $2, (*handleLoc*) (snd $2), $4)  }
372 | ASM LPAREN string_constant RPAREN SEMICOLON
373                                         { GLOBASM (fst $3, (*handleLoc*) $1) }
374 | pragma                                { $1 }
375 /* (* Old-style function prototype. This should be somewhere else, like in
376     * "declaration". For now we keep it at global scope only because in local
377     * scope it looks too much like a function call  *) */
378 | IDENT LPAREN old_parameter_list_ne RPAREN old_pardef_list SEMICOLON
379                            { (* Convert pardecl to new style *)
380                              let pardecl, isva = doOldParDecl $3 $5 in 
381                              (* Make the function declarator *)
382                              doDeclaration ((*handleLoc*) (snd $1)) []
383                                [((fst $1, PROTO(JUSTBASE, pardecl,isva), [], cabslu),
384                                  NO_INIT)]
385                             }
386 /* (* Old style function prototype, but without any arguments *) */
387 | IDENT LPAREN RPAREN  SEMICOLON
388                            { (* Make the function declarator *)
389                              doDeclaration ((*handleLoc*)(snd $1)) []
390                                [((fst $1, PROTO(JUSTBASE,[],false), [], cabslu),
391                                  NO_INIT)]
392                             }
393 /* | location error SEMICOLON { PRAGMA (VARIABLE "parse_error", $1) } */
394 ;
395
396 id_or_typename:
397     IDENT                               {fst $1}
398 |   NAMED_TYPE                          {fst $1}
399 ;
400
401 maybecomma:
402    /* empty */                          { () }
403 |  COMMA                                { () }
404 ;
405
406 /* *** Expressions *** */
407
408 primary_expression:                     /*(* 6.5.1. *)*/
409 |               IDENT
410                         {VARIABLE (fst $1), snd $1}
411 |               constant
412                         {CONSTANT (fst $1), snd $1}
413 |               paren_comma_expression  
414                         {PAREN (smooth_expression (fst $1)), snd $1}
415 |               LPAREN block RPAREN
416                         { GNU_BODY (fst3 $2), $1 }
417 ;
418
419 postfix_expression:                     /*(* 6.5.2 *)*/
420 |               primary_expression     
421                         { $1 }
422 |               postfix_expression bracket_comma_expression
423                         {INDEX (fst $1, smooth_expression $2), snd $1}
424 |               postfix_expression LPAREN arguments RPAREN
425                         {CALL (fst $1, $3), snd $1}
426 |               BUILTIN_VA_ARG LPAREN expression COMMA type_name RPAREN
427                         { let b, d = $5 in
428                           CALL (VARIABLE "__builtin_va_arg", 
429                                 [fst $3; TYPE_SIZEOF (b, d)]), $1 }
430 |               BUILTIN_TYPES_COMPAT LPAREN type_name COMMA type_name RPAREN
431                         { let b1,d1 = $3 in
432                           let b2,d2 = $5 in
433                           CALL (VARIABLE "__builtin_types_compatible_p", 
434                                 [TYPE_SIZEOF(b1,d1); TYPE_SIZEOF(b2,d2)]), $1 }
435 |               BUILTIN_OFFSETOF LPAREN type_name COMMA offsetof_member_designator RPAREN
436                         { transformOffsetOf $3 $5, $1 }
437 |               postfix_expression DOT id_or_typename
438                         {MEMBEROF (fst $1, $3), snd $1}
439 |               postfix_expression ARROW id_or_typename   
440                         {MEMBEROFPTR (fst $1, $3), snd $1}
441 |               postfix_expression PLUS_PLUS
442                         {UNARY (POSINCR, fst $1), snd $1}
443 |               postfix_expression MINUS_MINUS
444                         {UNARY (POSDECR, fst $1), snd $1}
445 /* (* We handle GCC constructor expressions *) */
446 |               LPAREN type_name RPAREN LBRACE initializer_list_opt RBRACE
447                         { CAST($2, COMPOUND_INIT $5), $1 }
448 ;
449
450 offsetof_member_designator:     /* GCC extension for __builtin_offsetof */
451 |               id_or_typename
452                         { VARIABLE ($1) }
453 |               offsetof_member_designator DOT IDENT
454                         { MEMBEROF ($1, fst $3) }
455 |               offsetof_member_designator bracket_comma_expression
456                         { INDEX ($1, smooth_expression $2) }
457 ;
458
459 unary_expression:   /*(* 6.5.3 *)*/
460 |               postfix_expression
461                         { $1 }
462 |               PLUS_PLUS unary_expression
463                         {UNARY (PREINCR, fst $2), $1}
464 |               MINUS_MINUS unary_expression
465                         {UNARY (PREDECR, fst $2), $1}
466 |               SIZEOF unary_expression
467                         {EXPR_SIZEOF (fst $2), $1}
468 |               SIZEOF LPAREN type_name RPAREN
469                         {let b, d = $3 in TYPE_SIZEOF (b, d), $1}
470 |               ALIGNOF unary_expression
471                         {EXPR_ALIGNOF (fst $2), $1}
472 |               ALIGNOF LPAREN type_name RPAREN
473                         {let b, d = $3 in TYPE_ALIGNOF (b, d), $1}
474 |               PLUS cast_expression
475                         {UNARY (PLUS, fst $2), $1}
476 |               MINUS cast_expression
477                         {UNARY (MINUS, fst $2), $1}
478 |               STAR cast_expression
479                         {UNARY (MEMOF, fst $2), $1}
480 |               AND cast_expression                             
481                         {UNARY (ADDROF, fst $2), $1}
482 |               EXCLAM cast_expression
483                         {UNARY (NOT, fst $2), $1}
484 |               TILDE cast_expression
485                         {UNARY (BNOT, fst $2), $1}
486 |               AND_AND IDENT  { LABELADDR (fst $2), $1 }
487 ;
488
489 cast_expression:   /*(* 6.5.4 *)*/
490 |              unary_expression 
491                          { $1 }
492 |               LPAREN type_name RPAREN cast_expression
493                          { CAST($2, SINGLE_INIT (fst $4)), $1 }
494 ;
495
496 multiplicative_expression:  /*(* 6.5.5 *)*/
497 |               cast_expression
498                          { $1 }
499 |               multiplicative_expression STAR cast_expression
500                         {BINARY(MUL, fst $1, fst $3), snd $1}
501 |               multiplicative_expression SLASH cast_expression
502                         {BINARY(DIV, fst $1, fst $3), snd $1}
503 |               multiplicative_expression PERCENT cast_expression
504                         {BINARY(MOD, fst $1, fst $3), snd $1}
505 ;
506
507 additive_expression:  /*(* 6.5.6 *)*/
508 |               multiplicative_expression
509                         { $1 }
510 |               additive_expression PLUS multiplicative_expression
511                         {BINARY(ADD, fst $1, fst $3), snd $1}
512 |               additive_expression MINUS multiplicative_expression
513                         {BINARY(SUB, fst $1, fst $3), snd $1}
514 ;
515
516 shift_expression:      /*(* 6.5.7 *)*/
517 |               additive_expression
518                          { $1 }
519 |               shift_expression  INF_INF additive_expression
520                         {BINARY(SHL, fst $1, fst $3), snd $1}
521 |               shift_expression  SUP_SUP additive_expression
522                         {BINARY(SHR, fst $1, fst $3), snd $1}
523 ;
524
525
526 relational_expression:   /*(* 6.5.8 *)*/
527 |               shift_expression
528                         { $1 }
529 |               relational_expression INF shift_expression
530                         {BINARY(LT, fst $1, fst $3), snd $1}
531 |               relational_expression SUP shift_expression
532                         {BINARY(GT, fst $1, fst $3), snd $1}
533 |               relational_expression INF_EQ shift_expression
534                         {BINARY(LE, fst $1, fst $3), snd $1}
535 |               relational_expression SUP_EQ shift_expression
536                         {BINARY(GE, fst $1, fst $3), snd $1}
537 ;
538
539 equality_expression:   /*(* 6.5.9 *)*/
540 |              relational_expression
541                         { $1 }
542 |               equality_expression EQ_EQ relational_expression
543                         {BINARY(EQ, fst $1, fst $3), snd $1}
544 |               equality_expression EXCLAM_EQ relational_expression
545                         {BINARY(NE, fst $1, fst $3), snd $1}
546 ;
547
548
549 bitwise_and_expression:   /*(* 6.5.10 *)*/
550 |               equality_expression
551                        { $1 }
552 |               bitwise_and_expression AND equality_expression
553                         {BINARY(BAND, fst $1, fst $3), snd $1}
554 ;
555
556 bitwise_xor_expression:   /*(* 6.5.11 *)*/
557 |               bitwise_and_expression
558                        { $1 }
559 |               bitwise_xor_expression CIRC bitwise_and_expression
560                         {BINARY(XOR, fst $1, fst $3), snd $1}
561 ;
562
563 bitwise_or_expression:   /*(* 6.5.12 *)*/
564 |               bitwise_xor_expression
565                         { $1 } 
566 |               bitwise_or_expression PIPE bitwise_xor_expression
567                         {BINARY(BOR, fst $1, fst $3), snd $1}
568 ;
569
570 logical_and_expression:   /*(* 6.5.13 *)*/
571 |               bitwise_or_expression
572                         { $1 }
573 |               logical_and_expression AND_AND bitwise_or_expression
574                         {BINARY(AND, fst $1, fst $3), snd $1}
575 ;
576
577 logical_or_expression:   /*(* 6.5.14 *)*/
578 |               logical_and_expression
579                         { $1 }
580 |               logical_or_expression PIPE_PIPE logical_and_expression
581                         {BINARY(OR, fst $1, fst $3), snd $1}
582 ;
583
584 conditional_expression:    /*(* 6.5.15 *)*/
585 |               logical_or_expression
586                          { $1 }
587 |               logical_or_expression QUEST opt_expression COLON conditional_expression
588                         {QUESTION (fst $1, $3, fst $5), snd $1}
589 ;
590
591 /*(* The C spec says that left-hand sides of assignment expressions are unary 
592  * expressions. GCC allows cast expressions in there ! *)*/
593
594 assignment_expression:     /*(* 6.5.16 *)*/
595 |               conditional_expression
596                          { $1 }
597 |               cast_expression EQ assignment_expression
598                         {BINARY(ASSIGN, fst $1, fst $3), snd $1}
599 |               cast_expression PLUS_EQ assignment_expression
600                         {BINARY(ADD_ASSIGN, fst $1, fst $3), snd $1}
601 |               cast_expression MINUS_EQ assignment_expression
602                         {BINARY(SUB_ASSIGN, fst $1, fst $3), snd $1}
603 |               cast_expression STAR_EQ assignment_expression
604                         {BINARY(MUL_ASSIGN, fst $1, fst $3), snd $1}
605 |               cast_expression SLASH_EQ assignment_expression
606                         {BINARY(DIV_ASSIGN, fst $1, fst $3), snd $1}
607 |               cast_expression PERCENT_EQ assignment_expression
608                         {BINARY(MOD_ASSIGN, fst $1, fst $3), snd $1}
609 |               cast_expression AND_EQ assignment_expression
610                         {BINARY(BAND_ASSIGN, fst $1, fst $3), snd $1}
611 |               cast_expression PIPE_EQ assignment_expression
612                         {BINARY(BOR_ASSIGN, fst $1, fst $3), snd $1}
613 |               cast_expression CIRC_EQ assignment_expression
614                         {BINARY(XOR_ASSIGN, fst $1, fst $3), snd $1}
615 |               cast_expression INF_INF_EQ assignment_expression        
616                         {BINARY(SHL_ASSIGN, fst $1, fst $3), snd $1}
617 |               cast_expression SUP_SUP_EQ assignment_expression
618                         {BINARY(SHR_ASSIGN, fst $1, fst $3), snd $1}
619 ;
620
621 expression:           /*(* 6.5.17 *)*/
622                 assignment_expression
623                         { $1 }
624 ;
625                             
626
627 constant:
628     CST_INT                             {CONST_INT (fst $1), snd $1}
629 |   CST_FLOAT                           {CONST_FLOAT (fst $1), snd $1}
630 |   CST_CHAR                            {CONST_CHAR (fst $1), snd $1}
631 |   CST_WCHAR                           {CONST_WCHAR (fst $1), snd $1}
632 |   string_constant                     {CONST_STRING (fst $1), snd $1}
633 |   wstring_list                        {CONST_WSTRING (fst $1), snd $1}
634 ;
635
636 string_constant:
637 /* Now that we know this constant isn't part of a wstring, convert it
638    back to a string for easy viewing. */
639     string_list                         {
640      let queue, location = $1 in
641      let buffer = Buffer.create (Queue.length queue) in
642      Queue.iter
643        (List.iter
644           (fun value ->
645             let char = int64_to_char value in
646             Buffer.add_char buffer char))
647        queue;
648      Buffer.contents buffer, location
649    }
650 ;
651 one_string_constant:
652 /* Don't concat multiple strings.  For asm templates. */
653     CST_STRING                          {intlist_to_string (fst $1) }
654 ;
655 string_list:
656     one_string                          {
657       let queue = Queue.create () in
658       Queue.add (fst $1) queue;
659       queue, snd $1
660     }
661 |   string_list one_string              {
662       Queue.add (fst $2) (fst $1);
663       $1
664     }
665 ;
666
667 wstring_list:
668     CST_WSTRING                         { $1 }
669 |   wstring_list one_string             { (fst $1) @ (fst $2), snd $1 }
670 |   wstring_list CST_WSTRING            { (fst $1) @ (fst $2), snd $1 }
671 /* Only the first string in the list needs an L, so L"a" "b" is the same
672  * as L"ab" or L"a" L"b". */
673
674 one_string: 
675     CST_STRING                          {$1}
676 |   FUNCTION__                          {(Cabshelper.explodeStringToInts 
677                                             !currentFunctionName), $1}
678 |   PRETTY_FUNCTION__                   {(Cabshelper.explodeStringToInts 
679                                             !currentFunctionName), $1}
680 ;    
681
682 init_expression:
683      expression         { SINGLE_INIT (fst $1) }
684 |    LBRACE initializer_list_opt RBRACE
685                         { COMPOUND_INIT $2}
686
687 initializer_list:    /* ISO 6.7.8. Allow a trailing COMMA */
688     initializer                             { [$1] }
689 |   initializer COMMA initializer_list_opt  { $1 :: $3 }
690 ;
691 initializer_list_opt:
692     /* empty */                             { [] }
693 |   initializer_list                        { $1 }
694 ;
695 initializer: 
696     init_designators eq_opt init_expression { ($1, $3) }
697 |   gcc_init_designators init_expression { ($1, $2) }
698 |                       init_expression { (NEXT_INIT, $1) }
699 ;
700 eq_opt: 
701    EQ                        { () }
702    /*(* GCC allows missing = *)*/
703 |  /*(* empty *)*/               { () }
704 ;
705 init_designators: 
706     DOT id_or_typename init_designators_opt      { INFIELD_INIT($2, $3) }
707 |   LBRACKET  expression RBRACKET init_designators_opt
708                                         { ATINDEX_INIT(fst $2, $4) }
709 |   LBRACKET  expression ELLIPSIS expression RBRACKET
710                                         { ATINDEXRANGE_INIT(fst $2, fst $4) }
711 ;         
712 init_designators_opt:
713    /* empty */                          { NEXT_INIT }
714 |  init_designators                     { $1 }
715 ;
716
717 gcc_init_designators:  /*(* GCC supports these strange things *)*/
718    id_or_typename COLON                 { INFIELD_INIT($1, NEXT_INIT) }
719 ;
720
721 arguments: 
722                 /* empty */         { [] }
723 |               comma_expression    { fst $1 }
724 ;
725
726 opt_expression:
727                 /* empty */
728                         {NOTHING}
729 |               comma_expression
730                         {smooth_expression (fst $1)}
731 ;
732
733 comma_expression:
734                 expression                        {[fst $1], snd $1}
735 |               expression COMMA comma_expression { fst $1 :: fst $3, snd $1 }
736 |               error COMMA comma_expression      { $3 }
737 ;
738
739 comma_expression_opt:
740                 /* empty */         { NOTHING }
741 |               comma_expression    { smooth_expression (fst $1) }
742 ;
743
744 paren_comma_expression:
745   LPAREN comma_expression RPAREN                   { $2 }
746 | LPAREN error RPAREN                              { [], $1 }
747 ;
748
749 bracket_comma_expression:
750   LBRACKET comma_expression RBRACKET                   { fst $2 }
751 | LBRACKET error RBRACKET                              { [] }
752 ;
753
754
755 /*** statements ***/
756 block: /* ISO 6.8.2 */
757     block_begin local_labels block_attrs block_element_list RBRACE
758                                          {!pop_context();
759                                           { blabels = $2;
760                                             battrs = $3;
761                                             bstmts = $4 },
762                                             $1, $5
763                                          } 
764 |   error location RBRACE                { { blabels = [];
765                                              battrs  = [];
766                                              bstmts  = [] },
767                                              $2, $3
768                                          }
769 ;
770 block_begin:
771     LBRACE                               {!push_context (); $1}
772 ;
773
774 block_attrs:
775    /* empty */                                              { [] }
776 |  BLOCKATTRIBUTE paren_attr_list_ne
777                                         { [("__blockattribute__", $2)] }
778 ;
779
780 /* statements and declarations in a block, in any order (for C99 support) */
781 block_element_list:
782     /* empty */                          { [] }
783 |   declaration block_element_list       { DEFINITION($1) :: $2 }
784 |   statement block_element_list         { $1 :: $2 }
785 /*(* GCC accepts a label at the end of a block *)*/
786 |   IDENT COLON                          { [ LABEL (fst $1, NOP (snd $1), 
787                                                     snd $1)] }
788 |   pragma block_element_list            { $2 }
789 ;
790
791 local_labels:
792    /* empty */                                       { [] }
793 |  LABEL__ local_label_names SEMICOLON local_labels  { $2 @ $4 }
794 ;
795 local_label_names: 
796    IDENT                                 { [ fst $1 ] }
797 |  IDENT COMMA local_label_names         { fst $1 :: $3 }
798 ;
799
800
801
802 statement:
803     SEMICOLON           {NOP ((*handleLoc*) $1) }
804 |   comma_expression SEMICOLON
805                         {COMPUTATION (smooth_expression (fst $1), (*handleLoc*)(snd $1))}
806 |   block               {BLOCK (fst3 $1, (*handleLoc*)(snd3 $1))}
807 |   IF paren_comma_expression statement                    %prec IF
808                         {IF (smooth_expression (fst $2), $3, NOP $1, $1)}
809 |   IF paren_comma_expression statement ELSE statement
810                         {IF (smooth_expression (fst $2), $3, $5, (*handleLoc*) $1)}
811 |   SWITCH paren_comma_expression statement
812                         {SWITCH (smooth_expression (fst $2), $3, (*handleLoc*) $1)}
813 |   WHILE paren_comma_expression statement
814                         {WHILE (smooth_expression (fst $2), $3, (*handleLoc*) $1)}
815 |   DO statement WHILE paren_comma_expression SEMICOLON
816                                  {DOWHILE (smooth_expression (fst $4), $2, (*handleLoc*) $1)}
817 |   FOR LPAREN for_clause opt_expression
818                 SEMICOLON opt_expression RPAREN statement
819                                  {FOR ($3, $4, $6, $8, (*handleLoc*) $1)}
820 |   IDENT COLON attribute_nocv_list statement
821                                  {(* The only attribute that should appear here
822                                      is "unused". For now, we drop this on the
823                                      floor, since unused labels are usually
824                                      removed anyways by Rmtmps. *)
825                                   LABEL (fst $1, $4, (snd $1))}
826 |   CASE expression COLON statement
827                                  {CASE (fst $2, $4, (*handleLoc*) $1)}
828 |   CASE expression ELLIPSIS expression COLON statement
829                                  {CASERANGE (fst $2, fst $4, $6, (*handleLoc*) $1)}
830 |   DEFAULT COLON
831                                  {DEFAULT (NOP $1, (*handleLoc*) $1)}
832 |   RETURN SEMICOLON             {RETURN (NOTHING, (*handleLoc*) $1)}
833 |   RETURN comma_expression SEMICOLON
834                                  {RETURN (smooth_expression (fst $2), (*handleLoc*) $1)}
835 |   BREAK SEMICOLON     {BREAK ((*handleLoc*) $1)}
836 |   CONTINUE SEMICOLON   {CONTINUE ((*handleLoc*) $1)}
837 |   GOTO IDENT SEMICOLON
838                                  {GOTO (fst $2, (*handleLoc*) $1)}
839 |   GOTO STAR comma_expression SEMICOLON 
840                                  { COMPGOTO (smooth_expression (fst $3), (*handleLoc*) $1) }
841 |   ASM asmattr LPAREN asmtemplate asmoutputs RPAREN SEMICOLON
842                         { ASM ($2, $4, $5, (*handleLoc*) $1) }
843 |   MSASM               { ASM ([], [fst $1], None, (*handleLoc*)(snd $1))}
844 |   TRY block EXCEPT paren_comma_expression block
845                         { let b, _, _ = $2 in
846                           let h, _, _ = $5 in
847                           if not !msvcMode then 
848                             parse_error "try/except in GCC code";
849                           TRY_EXCEPT (b, COMMA (fst $4), h, (*handleLoc*) $1) }
850 |   TRY block FINALLY block 
851                         { let b, _, _ = $2 in
852                           let h, _, _ = $4 in
853                           if not !msvcMode then 
854                             parse_error "try/finally in GCC code";
855                           TRY_FINALLY (b, h, (*handleLoc*) $1) }
856
857 |   error location   SEMICOLON   { (NOP $2)}
858 ;
859
860
861 for_clause: 
862     opt_expression SEMICOLON     { FC_EXP $1 }
863 |   declaration                  { FC_DECL $1 }
864 ;
865
866 declaration:                                /* ISO 6.7.*/
867     decl_spec_list init_declarator_list SEMICOLON
868                                        { doDeclaration ((*handleLoc*)(snd $1)) (fst $1) $2 }
869 |   decl_spec_list SEMICOLON           
870                                        { doDeclaration ((*handleLoc*)(snd $1)) (fst $1) [] }
871 ;
872 init_declarator_list:                       /* ISO 6.7 */
873     init_declarator                              { [$1] }
874 |   init_declarator COMMA init_declarator_list   { $1 :: $3 }
875
876 ;
877 init_declarator:                             /* ISO 6.7 */
878     declarator                          { ($1, NO_INIT) }
879 |   declarator EQ init_expression 
880                                         { ($1, $3) }
881 ;
882
883 decl_spec_list:                         /* ISO 6.7 */
884                                         /* ISO 6.7.1 */
885 |   TYPEDEF decl_spec_list_opt          { SpecTypedef :: $2, $1  }    
886 |   EXTERN decl_spec_list_opt           { SpecStorage EXTERN :: $2, $1 }
887 |   STATIC  decl_spec_list_opt          { SpecStorage STATIC :: $2, $1 }
888 |   AUTO   decl_spec_list_opt           { SpecStorage AUTO :: $2, $1 }
889 |   REGISTER decl_spec_list_opt         { SpecStorage REGISTER :: $2, $1}
890                                         /* ISO 6.7.2 */
891 |   type_spec decl_spec_list_opt_no_named { SpecType (fst $1) :: $2, snd $1 }
892                                         /* ISO 6.7.4 */
893 |   INLINE decl_spec_list_opt           { SpecInline :: $2, $1 }
894 |   cvspec decl_spec_list_opt           { (fst $1) :: $2, snd $1 }
895 |   attribute_nocv decl_spec_list_opt   { SpecAttr (fst $1) :: $2, snd $1 }
896 ;
897 /* (* In most cases if we see a NAMED_TYPE we must shift it. Thus we declare 
898     * NAMED_TYPE to have right associativity  *) */
899 decl_spec_list_opt: 
900     /* empty */                         { [] } %prec NAMED_TYPE
901 |   decl_spec_list                      { fst $1 }
902 ;
903 /* (* We add this separate rule to handle the special case when an appearance 
904     * of NAMED_TYPE should not be considered as part of the specifiers but as 
905     * part of the declarator. IDENT has higher precedence than NAMED_TYPE  *)
906  */
907 decl_spec_list_opt_no_named: 
908     /* empty */                         { [] } %prec IDENT
909 |   decl_spec_list                      { fst $1 }
910 ;
911 type_spec:   /* ISO 6.7.2 */
912     VOID            { Tvoid, $1}
913 |   UNDERSCORE_BOOL { T_Bool, $1 }
914 |   CHAR            { Tchar, $1 }
915 |   SHORT           { Tshort, $1 }
916 |   INT             { Tint, $1 }
917 |   LONG            { Tlong, $1 }
918 |   INT64           { Tint64, $1 }
919 |   FLOAT           { Tfloat, $1 }
920 |   DOUBLE          { Tdouble, $1 }
921 |   SIGNED          { Tsigned, $1 }
922 |   UNSIGNED        { Tunsigned, $1 }
923 |   STRUCT                 id_or_typename
924                                                    { Tstruct ($2, None,    []), $1 }
925 |   STRUCT just_attributes id_or_typename
926                                                    { Tstruct ($3, None,    $2), $1 }
927 |   STRUCT                 id_or_typename LBRACE struct_decl_list RBRACE
928                                                    { Tstruct ($2, Some $4, []), $1 }
929 |   STRUCT                                LBRACE struct_decl_list RBRACE
930                                                    { Tstruct ("", Some $3, []), $1 }
931 |   STRUCT just_attributes id_or_typename LBRACE struct_decl_list RBRACE
932                                                    { Tstruct ($3, Some $5, $2), $1 }
933 |   STRUCT just_attributes                LBRACE struct_decl_list RBRACE
934                                                    { Tstruct ("", Some $4, $2), $1 }
935 |   UNION                  id_or_typename
936                                                    { Tunion  ($2, None,    []), $1 }
937 |   UNION                  id_or_typename LBRACE struct_decl_list RBRACE
938                                                    { Tunion  ($2, Some $4, []), $1 }
939 |   UNION                                 LBRACE struct_decl_list RBRACE
940                                                    { Tunion  ("", Some $3, []), $1 }
941 |   UNION  just_attributes id_or_typename LBRACE struct_decl_list RBRACE
942                                                    { Tunion  ($3, Some $5, $2), $1 }
943 |   UNION  just_attributes                LBRACE struct_decl_list RBRACE
944                                                    { Tunion  ("", Some $4, $2), $1 }
945 |   ENUM                   id_or_typename
946                                                    { Tenum   ($2, None,    []), $1 }
947 |   ENUM                   id_or_typename LBRACE enum_list maybecomma RBRACE
948                                                    { Tenum   ($2, Some $4, []), $1 }
949 |   ENUM                                  LBRACE enum_list maybecomma RBRACE
950                                                    { Tenum   ("", Some $3, []), $1 }
951 |   ENUM   just_attributes id_or_typename LBRACE enum_list maybecomma RBRACE
952                                                    { Tenum   ($3, Some $5, $2), $1 }
953 |   ENUM   just_attributes                LBRACE enum_list maybecomma RBRACE
954                                                    { Tenum   ("", Some $4, $2), $1 }
955 |   NAMED_TYPE      { Tnamed (fst $1), snd $1 }
956 |   TYPEOF LPAREN expression RPAREN     { TtypeofE (fst $3), $1 }
957 |   TYPEOF LPAREN type_name RPAREN      { let s, d = $3 in
958                                           TtypeofT (s, d), $1 }
959 ;
960 struct_decl_list: /* (* ISO 6.7.2. Except that we allow empty structs. We 
961                       * also allow missing field names. *)
962                    */
963    /* empty */                           { [] }
964 |  decl_spec_list                 SEMICOLON struct_decl_list
965                                          { (fst $1, 
966                                             [(missingFieldDecl, None)]) :: $3 }
967 /*(* GCC allows extra semicolons *)*/
968 |                                 SEMICOLON struct_decl_list
969                                          { $2 }
970 |  decl_spec_list field_decl_list SEMICOLON struct_decl_list
971                                           { (fst $1, $2) 
972                                             :: $4 }
973 /*(* MSVC allows pragmas in strange places *)*/
974 |  pragma struct_decl_list                { $2 }
975
976 |  error                          SEMICOLON struct_decl_list
977                                           { $3 } 
978 ;
979 field_decl_list: /* (* ISO 6.7.2 *) */
980     field_decl                           { [$1] }
981 |   field_decl COMMA field_decl_list     { $1 :: $3 }
982 ;
983 field_decl: /* (* ISO 6.7.2. Except that we allow unnamed fields. *) */
984 |   declarator                      { ($1, None) }
985 |   declarator COLON expression attributes
986                                     { let (n,decl,al,loc) = $1 in
987                                       let al' = al @ $4 in
988                                      ((n,decl,al',loc), Some (fst $3)) }    
989 |              COLON expression     { (missingFieldDecl, Some (fst $2)) }
990 ;
991
992 enum_list: /* (* ISO 6.7.2.2 *) */
993     enumerator                          {[$1]}
994 |   enum_list COMMA enumerator          {$1 @ [$3]}
995 |   enum_list COMMA error               { $1 } 
996 ;
997 enumerator:     
998     IDENT                       {(fst $1, NOTHING, snd $1)}
999 |   IDENT EQ expression         {(fst $1, fst $3, snd $1)}
1000 ;
1001
1002
1003 declarator:  /* (* ISO 6.7.5. Plus Microsoft declarators.*) */
1004    pointer_opt direct_decl attributes_with_asm
1005                                { let (n, decl) = $2 in
1006                                 (n, applyPointer (fst $1) decl, $3, (snd $1)) }
1007 ;
1008
1009
1010 direct_decl: /* (* ISO 6.7.5 *) */
1011                                    /* (* We want to be able to redefine named
1012                                     * types as variable names *) */
1013 |   id_or_typename                 { ($1, JUSTBASE) }
1014
1015 |   LPAREN attributes declarator RPAREN
1016                                    { let (n,decl,al,loc) = $3 in
1017                                      (n, PARENTYPE($2,decl,al)) }
1018
1019 |   direct_decl LBRACKET attributes comma_expression_opt RBRACKET
1020                                    { let (n, decl) = $1 in
1021                                      (n, ARRAY(decl, $3, $4)) }
1022 |   direct_decl LBRACKET attributes error RBRACKET
1023                                    { let (n, decl) = $1 in
1024                                      (n, ARRAY(decl, $3, NOTHING)) }
1025 |   direct_decl parameter_list_startscope rest_par_list RPAREN
1026                                    { let (n, decl) = $1 in
1027                                      let (params, isva) = $3 in
1028                                      !pop_context ();
1029                                      (n, PROTO(decl, params, isva))
1030                                    }
1031 ;
1032 parameter_list_startscope: 
1033     LPAREN                         { !push_context () }
1034 ;
1035 rest_par_list:
1036 |   /* empty */                    { ([], false) }
1037 |   parameter_decl rest_par_list1  { let (params, isva) = $2 in 
1038                                      ($1 :: params, isva) 
1039                                    }
1040 ;
1041 rest_par_list1: 
1042     /* empty */                         { ([], false) }
1043 |   COMMA ELLIPSIS                      { ([], true) }
1044 |   COMMA parameter_decl rest_par_list1 { let (params, isva) = $3 in 
1045                                           ($2 :: params, isva)
1046                                         }  
1047 ;    
1048
1049
1050 parameter_decl: /* (* ISO 6.7.5 *) */
1051    decl_spec_list declarator              { (fst $1, $2) }
1052 |  decl_spec_list abstract_decl           { let d, a = $2 in
1053                                             (fst $1, ("", d, a, cabslu)) }
1054 |  decl_spec_list                         { (fst $1, ("", JUSTBASE, [], cabslu)) }
1055 |  LPAREN parameter_decl RPAREN           { $2 } 
1056 ;
1057
1058 /* (* Old style prototypes. Like a declarator *) */
1059 old_proto_decl:
1060   pointer_opt direct_old_proto_decl   { let (n, decl, a) = $2 in
1061                                           (n, applyPointer (fst $1) decl, 
1062                                            a, snd $1) 
1063                                       }
1064
1065 ;
1066
1067 direct_old_proto_decl:
1068   direct_decl LPAREN old_parameter_list_ne RPAREN old_pardef_list
1069                                    { let par_decl, isva = doOldParDecl $3 $5 in
1070                                      let n, decl = $1 in
1071                                      (n, PROTO(decl, par_decl, isva), [])
1072                                    }
1073 | direct_decl LPAREN                       RPAREN
1074                                    { let n, decl = $1 in
1075                                      (n, PROTO(decl, [], false), [])
1076                                    }
1077
1078 /* (* appears sometimesm but generates a shift-reduce conflict. *)
1079 | LPAREN STAR direct_decl LPAREN old_parameter_list_ne RPAREN RPAREN LPAREN RPAREN old_pardef_list
1080                                    { let par_decl, isva 
1081                                              = doOldParDecl $5 $10 in
1082                                      let n, decl = $3 in
1083                                      (n, PROTO(decl, par_decl, isva), [])
1084                                    }
1085 */
1086 ;
1087
1088 old_parameter_list_ne:
1089 |  IDENT                                       { [fst $1] }
1090 |  IDENT COMMA old_parameter_list_ne           { let rest = $3 in
1091                                                  (fst $1 :: rest) }
1092 ;
1093
1094 old_pardef_list: 
1095    /* empty */                            { ([], false) }
1096 |  decl_spec_list old_pardef SEMICOLON ELLIPSIS
1097                                           { ([(fst $1, $2)], true) }  
1098 |  decl_spec_list old_pardef SEMICOLON old_pardef_list  
1099                                           { let rest, isva = $4 in
1100                                             ((fst $1, $2) :: rest, isva) 
1101                                           }
1102 ;
1103
1104 old_pardef: 
1105    declarator                             { [$1] }
1106 |  declarator COMMA old_pardef            { $1 :: $3 }
1107 |  error                                  { [] }
1108 ;
1109
1110
1111 pointer: /* (* ISO 6.7.5 *) */ 
1112    STAR attributes pointer_opt  { $2 :: fst $3, $1 }
1113 ;
1114 pointer_opt:
1115    /**/                          { let l = currentLoc () in
1116                                    ([], l) }
1117 |  pointer                       { $1 }
1118 ;
1119
1120 type_name: /* (* ISO 6.7.6 *) */
1121   decl_spec_list abstract_decl { let d, a = $2 in
1122                                  if a <> [] then begin
1123                                    parse_error "attributes in type name";
1124                                    raise Parsing.Parse_error
1125                                  end;
1126                                  (fst $1, d) 
1127                                }
1128 | decl_spec_list               { (fst $1, JUSTBASE) }
1129 ;
1130 abstract_decl: /* (* ISO 6.7.6. *) */
1131   pointer_opt abs_direct_decl attributes  { applyPointer (fst $1) $2, $3 }
1132 | pointer                                 { applyPointer (fst $1) JUSTBASE, [] }
1133 ;
1134
1135 abs_direct_decl: /* (* ISO 6.7.6. We do not support optional declarator for 
1136                      * functions. Plus Microsoft attributes. See the 
1137                      * discussion for declarator. *) */
1138 |   LPAREN attributes abstract_decl RPAREN
1139                                    { let d, a = $3 in
1140                                      PARENTYPE ($2, d, a)
1141                                    }
1142             
1143 |   LPAREN error RPAREN
1144                                    { JUSTBASE } 
1145             
1146 |   abs_direct_decl_opt LBRACKET comma_expression_opt RBRACKET
1147                                    { ARRAY($1, [], $3) }
1148 /*(* The next should be abs_direct_decl_opt but we get conflicts *)*/
1149 |   abs_direct_decl  parameter_list_startscope rest_par_list RPAREN
1150                                    { let (params, isva) = $3 in
1151                                      !pop_context ();
1152                                      PROTO ($1, params, isva)
1153                                    } 
1154 ;
1155 abs_direct_decl_opt:
1156     abs_direct_decl                 { $1 }
1157 |   /* empty */                     { JUSTBASE }
1158 ;
1159 function_def:  /* (* ISO 6.9.1 *) */
1160   function_def_start block   
1161           { let (loc, specs, decl) = $1 in
1162             currentFunctionName := "<__FUNCTION__ used outside any functions>";
1163             !pop_context (); (* The context pushed by 
1164                                     * announceFunctionName *)
1165             doFunctionDef ((*handleLoc*) loc) (trd3 $2) specs decl (fst3 $2)
1166           } 
1167
1168
1169 function_def_start:  /* (* ISO 6.9.1 *) */
1170   decl_spec_list declarator   
1171                             { announceFunctionName $2;
1172                               (snd $1, fst $1, $2)
1173                             } 
1174
1175 /* (* Old-style function prototype *) */
1176 | decl_spec_list old_proto_decl 
1177                             { announceFunctionName $2;
1178                               (snd $1, fst $1, $2)
1179                             } 
1180 /* (* New-style function that does not have a return type *) */
1181 | IDENT parameter_list_startscope rest_par_list RPAREN 
1182                            { let (params, isva) = $3 in
1183                              let fdec = 
1184                                (fst $1, PROTO(JUSTBASE, params, isva), [], snd $1) in
1185                              announceFunctionName fdec;
1186                              (* Default is int type *)
1187                              let defSpec = [SpecType Tint] in
1188                              (snd $1, defSpec, fdec)
1189                            }
1190
1191 /* (* No return type and old-style parameter list *) */
1192 | IDENT LPAREN old_parameter_list_ne RPAREN old_pardef_list
1193                            { (* Convert pardecl to new style *)
1194                              let pardecl, isva = doOldParDecl $3 $5 in
1195                              (* Make the function declarator *)
1196                              let fdec = (fst $1,
1197                                          PROTO(JUSTBASE, pardecl,isva), 
1198                                          [], snd $1) in
1199                              announceFunctionName fdec;
1200                              (* Default is int type *)
1201                              let defSpec = [SpecType Tint] in
1202                              (snd $1, defSpec, fdec) 
1203                             }
1204 /* (* No return type and no parameters *) */
1205 | IDENT LPAREN                      RPAREN
1206                            { (* Make the function declarator *)
1207                              let fdec = (fst $1,
1208                                          PROTO(JUSTBASE, [], false), 
1209                                          [], snd $1) in
1210                              announceFunctionName fdec;
1211                              (* Default is int type *)
1212                              let defSpec = [SpecType Tint] in
1213                              (snd $1, defSpec, fdec)
1214                             }
1215 ;
1216
1217 /* const/volatile as type specifier elements */
1218 cvspec:
1219     CONST                               { SpecCV(CV_CONST), $1 }
1220 |   VOLATILE                            { SpecCV(CV_VOLATILE), $1 }
1221 |   RESTRICT                            { SpecCV(CV_RESTRICT), $1 }
1222 ;
1223
1224 /*** GCC attributes ***/
1225 attributes:
1226     /* empty */                         { []}
1227 |   attribute attributes                { fst $1 :: $2 }
1228 ;
1229
1230 /* (* In some contexts we can have an inline assembly to specify the name to 
1231     * be used for a global. We treat this as a name attribute *) */
1232 attributes_with_asm:
1233     /* empty */                         { [] }
1234 |   attribute attributes_with_asm       { fst $1 :: $2 }
1235 |   ASM LPAREN string_constant RPAREN attributes        
1236                                         { ("__asm__", 
1237                                            [CONSTANT(CONST_STRING (fst $3))]) :: $5 }
1238 ;
1239
1240 /* things like __attribute__, but no const/volatile */
1241 attribute_nocv:
1242     ATTRIBUTE LPAREN paren_attr_list RPAREN     
1243                                         { ("__attribute__", $3), $1 }
1244 /*(*
1245 |   ATTRIBUTE_USED                      { ("__attribute__", 
1246                                              [ VARIABLE "used" ]), $1 }
1247 *)*/
1248 |   DECLSPEC paren_attr_list_ne         { ("__declspec", $2), $1 }
1249 |   MSATTR                              { (fst $1, []), snd $1 }
1250                                         /* ISO 6.7.3 */
1251 |   THREAD                              { ("__thread",[]), $1 }
1252 ;
1253
1254 attribute_nocv_list:
1255     /* empty */                         { []}
1256 |   attribute_nocv attribute_nocv_list  { fst $1 :: $2 }
1257 ;
1258
1259 /* __attribute__ plus const/volatile */
1260 attribute:
1261     attribute_nocv                      { $1 }
1262 |   CONST                               { ("const", []), $1 }
1263 |   RESTRICT                            { ("restrict",[]), $1 }
1264 |   VOLATILE                            { ("volatile",[]), $1 }
1265 ;
1266
1267 /* (* sm: I need something that just includes __attribute__ and nothing more,
1268  *  to support them appearing between the 'struct' keyword and the type name. 
1269  * Actually, a declspec can appear there as well (on MSVC) *)  */
1270 just_attribute:
1271     ATTRIBUTE LPAREN paren_attr_list RPAREN
1272                                         { ("__attribute__", $3) }
1273 |   DECLSPEC paren_attr_list_ne         { ("__declspec", $2) }
1274 ;
1275
1276 /* this can't be empty, b/c I folded that possibility into the calling
1277  * productions to avoid some S/R conflicts */
1278 just_attributes:
1279     just_attribute                      { [$1] }
1280 |   just_attribute just_attributes      { $1 :: $2 }
1281 ;
1282
1283 /** (* PRAGMAS and ATTRIBUTES *) ***/
1284 pragma: 
1285 | PRAGMA_LINE                           { PRAGMA (fst $1, snd $1) }
1286 ;
1287
1288 /* (* We want to allow certain strange things that occur in pragmas, so we 
1289     * cannot use directly the language of expressions *) */ 
1290 primary_attr: 
1291     IDENT                               { VARIABLE (fst $1) }
1292     /*(* The NAMED_TYPE here creates conflicts with IDENT *)*/
1293 |   NAMED_TYPE                          { VARIABLE (fst $1) } 
1294 |   LPAREN attr RPAREN                  { $2 } 
1295 |   IDENT IDENT                          { CALL(VARIABLE (fst $1), [VARIABLE (fst $2)]) }
1296 |   CST_INT                              { CONSTANT(CONST_INT (fst $1)) }
1297 |   string_constant                      { CONSTANT(CONST_STRING (fst $1)) }
1298                                            /*(* Const when it appears in 
1299                                             * attribute lists, is translated 
1300                                             * to aconst *)*/
1301 |   CONST                                { VARIABLE "aconst" }
1302
1303 |   IDENT COLON CST_INT                  { VARIABLE (fst $1 ^ ":" ^ fst $3) }
1304
1305 /*(* The following rule conflicts with the ? : attributes. We give it a very 
1306    * low priority *)*/
1307 |   CST_INT COLON CST_INT                { VARIABLE (fst $1 ^ ":" ^ fst $3) } 
1308
1309 |   DEFAULT COLON CST_INT                { VARIABLE ("default:" ^ fst $3) }
1310                           
1311                                             /*(** GCC allows this as an 
1312                                              * attribute for functions, 
1313                                              * synonim for noreturn **)*/
1314 |   VOLATILE                             { VARIABLE ("__noreturn__") }
1315 ;
1316
1317 postfix_attr:
1318     primary_attr                         { $1 }
1319                                          /* (* use a VARIABLE "" so that the 
1320                                              * parentheses are printed *) */
1321 |   IDENT LPAREN  RPAREN             { CALL(VARIABLE (fst $1), [VARIABLE ""]) }
1322 |   IDENT paren_attr_list_ne         { CALL(VARIABLE (fst $1), $2) }
1323
1324 |   postfix_attr ARROW id_or_typename    {MEMBEROFPTR ($1, $3)} 
1325 |   postfix_attr DOT id_or_typename      {MEMBEROF ($1, $3)}  
1326 |   postfix_attr LBRACKET attr RBRACKET  {INDEX ($1, $3) }
1327 ;
1328
1329 /*(* Since in attributes we use both IDENT and NAMED_TYPE as indentifiers, 
1330  * that leads to conflicts for SIZEOF and ALIGNOF. In those cases we require 
1331  * that their arguments be expressions, not attributes *)*/
1332 unary_attr:
1333     postfix_attr                         { $1 }
1334 |   SIZEOF unary_expression              {EXPR_SIZEOF (fst $2) }
1335 |   SIZEOF LPAREN type_name RPAREN
1336                                          {let b, d = $3 in TYPE_SIZEOF (b, d)}
1337
1338 |   ALIGNOF unary_expression             {EXPR_ALIGNOF (fst $2) }
1339 |   ALIGNOF LPAREN type_name RPAREN      {let b, d = $3 in TYPE_ALIGNOF (b, d)}
1340 |   PLUS cast_attr                      {UNARY (PLUS, $2)}
1341 |   MINUS cast_attr                     {UNARY (MINUS, $2)}
1342 |   STAR cast_attr                      {UNARY (MEMOF, $2)}
1343 |   AND cast_attr
1344                                         {UNARY (ADDROF, $2)}
1345 |   EXCLAM cast_attr                    {UNARY (NOT, $2)}
1346 |   TILDE cast_attr                     {UNARY (BNOT, $2)}
1347 ;
1348
1349 cast_attr:
1350     unary_attr                           { $1 }
1351 ;   
1352
1353 multiplicative_attr:
1354     cast_attr                           { $1 }
1355 |   multiplicative_attr STAR cast_attr  {BINARY(MUL ,$1 , $3)}
1356 |   multiplicative_attr SLASH cast_attr   {BINARY(DIV ,$1 , $3)}
1357 |   multiplicative_attr PERCENT cast_attr {BINARY(MOD ,$1 , $3)}
1358 ;
1359
1360
1361 additive_attr:
1362     multiplicative_attr                 { $1 }
1363 |   additive_attr PLUS multiplicative_attr  {BINARY(ADD ,$1 , $3)} 
1364 |   additive_attr MINUS multiplicative_attr {BINARY(SUB ,$1 , $3)}
1365 ;
1366
1367 shift_attr:
1368     additive_attr                       { $1 }
1369 |   shift_attr INF_INF additive_attr    {BINARY(SHL ,$1 , $3)}
1370 |   shift_attr SUP_SUP additive_attr    {BINARY(SHR ,$1 , $3)}
1371 ;
1372
1373 relational_attr:
1374     shift_attr                          { $1 }
1375 |   relational_attr INF shift_attr      {BINARY(LT ,$1 , $3)}
1376 |   relational_attr SUP shift_attr      {BINARY(GT ,$1 , $3)}
1377 |   relational_attr INF_EQ shift_attr   {BINARY(LE ,$1 , $3)}
1378 |   relational_attr SUP_EQ shift_attr   {BINARY(GE ,$1 , $3)}
1379 ;
1380
1381 equality_attr:
1382     relational_attr                     { $1 }
1383 |   equality_attr EQ_EQ relational_attr     {BINARY(EQ ,$1 , $3)}
1384 |   equality_attr EXCLAM_EQ relational_attr {BINARY(NE ,$1 , $3)}
1385 ;
1386
1387
1388 bitwise_and_attr:
1389     equality_attr                       { $1 }
1390 |   bitwise_and_attr AND equality_attr  {BINARY(BAND ,$1 , $3)}
1391 ;
1392
1393 bitwise_xor_attr:
1394     bitwise_and_attr                       { $1 }
1395 |   bitwise_xor_attr CIRC bitwise_and_attr {BINARY(XOR ,$1 , $3)}
1396 ;
1397
1398 bitwise_or_attr: 
1399     bitwise_xor_attr                      { $1 }
1400 |   bitwise_or_attr PIPE bitwise_xor_attr {BINARY(BOR ,$1 , $3)}
1401 ;
1402
1403 logical_and_attr:
1404     bitwise_or_attr                             { $1 }
1405 |   logical_and_attr AND_AND bitwise_or_attr    {BINARY(AND ,$1 , $3)}
1406 ;
1407
1408 logical_or_attr:
1409     logical_and_attr                           { $1 }
1410 |   logical_or_attr PIPE_PIPE logical_and_attr {BINARY(OR ,$1 , $3)}
1411 ;
1412
1413 conditional_attr: 
1414     logical_or_attr                        { $1 }
1415 /* This is in conflict for now */
1416 |   logical_or_attr QUEST conditional_attr COLON conditional_attr 
1417                                           { QUESTION($1, $3, $5) }
1418
1419
1420 attr: conditional_attr                    { $1 }
1421 ;
1422
1423 attr_list_ne:
1424 |  attr                                  { [$1] }
1425 |  attr COMMA attr_list_ne               { $1 :: $3 }
1426 |  error COMMA attr_list_ne              { $3 }
1427 ;
1428 attr_list:
1429   /* empty */                            { [] }
1430 | attr_list_ne                           { $1 }
1431 ;
1432 paren_attr_list_ne: 
1433    LPAREN attr_list_ne RPAREN            { $2 }
1434 |  LPAREN error RPAREN                   { [] }
1435 ;
1436 paren_attr_list: 
1437    LPAREN attr_list RPAREN               { $2 }
1438 |  LPAREN error RPAREN                   { [] }
1439 ;
1440 /*** GCC ASM instructions ***/
1441 asmattr:
1442      /* empty */                        { [] }
1443 |    VOLATILE  asmattr                  { ("volatile", []) :: $2 }
1444 |    CONST asmattr                      { ("const", []) :: $2 } 
1445 ;
1446 asmtemplate: 
1447     one_string_constant                          { [$1] }
1448 |   one_string_constant asmtemplate              { $1 :: $2 }
1449 ;
1450 asmoutputs: 
1451   /* empty */           { None }
1452 | COLON asmoperands asminputs
1453                         { let (ins, clobs) = $3 in
1454                           Some {aoutputs = $2; ainputs = ins; aclobbers = clobs} }
1455 ;
1456 asmoperands:
1457      /* empty */                        { [] }
1458 |    asmoperandsne                      { List.rev $1 }
1459 ;
1460 asmoperandsne:
1461      asmoperand                         { [$1] }
1462 |    asmoperandsne COMMA asmoperand     { $3 :: $1 }
1463 ;
1464 asmoperand:
1465      asmopname string_constant LPAREN expression RPAREN    { ($1, fst $2, fst $4) }
1466 |    asmopname string_constant LPAREN error RPAREN         { ($1, fst $2, NOTHING ) } 
1467
1468 asminputs: 
1469   /* empty */                { ([], []) }
1470 | COLON asmoperands asmclobber
1471                         { ($2, $3) }
1472 ;
1473 asmopname:
1474     /* empty */                         { None }
1475 |   LBRACKET IDENT RBRACKET             { Some (fst $2) }
1476 ;
1477
1478 asmclobber:
1479     /* empty */                         { [] }
1480 | COLON asmcloberlst_ne                 { $2 }
1481 ;
1482 asmcloberlst_ne:
1483    one_string_constant                           { [$1] }
1484 |  one_string_constant COMMA asmcloberlst_ne     { $1 :: $3 }
1485 ;
1486   
1487 %%
1488
1489
1490