source: Deliverables/D2.2/8051/cparser/Parser.mly @ 486

Last change on this file since 486 was 486, checked in by ayache, 9 years ago

Deliverable D2.2

File size: 55.1 KB
Line 
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%{
44open Cabs
45open Cabshelper
46open Parse_aux
47
48(*
49** Expression building
50*)
51let smooth_expression lst =
52  match lst with
53    [] -> NOTHING
54  | [expr] -> expr
55  | _ -> COMMA (lst)
56
57
58let currentFunctionName = ref "<outside any function>"
59   
60let 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
87let 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
96let 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
111let 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
120let 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
140let 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. *)
151let 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
158let fst3 (result, _, _) = result
159let snd3 (_, result, _) = result
160let trd3 (_, _, result) = result
161
162
163(*
164   transform:  __builtin_offsetof(type, member)
165   into     :  (size_t) (&(type * ) 0)->member
166 *)
167
168let 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
348interpret:
349  file EOF                              {$1}
350;
351file: globals                           {$1}
352;
353globals:
354  /* empty */                           { [] }
355| global globals                        { $1 :: $2 }
356| SEMICOLON globals                     { $2 }
357;
358
359location:
360   /* empty */                  { currentLoc () }  %prec IDENT
361
362
363/*** Global Definition ***/
364global:
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
396id_or_typename:
397    IDENT                               {fst $1}
398|   NAMED_TYPE                          {fst $1}
399;
400
401maybecomma:
402   /* empty */                          { () }
403|  COMMA                                { () }
404;
405
406/* *** Expressions *** */
407
408primary_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
419postfix_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
450offsetof_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
459unary_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
489cast_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
496multiplicative_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
507additive_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
516shift_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
526relational_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
539equality_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
549bitwise_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
556bitwise_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
563bitwise_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
570logical_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
577logical_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
584conditional_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
594assignment_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
621expression:           /*(* 6.5.17 *)*/
622                assignment_expression
623                        { $1 }
624;
625                           
626
627constant:
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
636string_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;
651one_string_constant:
652/* Don't concat multiple strings.  For asm templates. */
653    CST_STRING                          {intlist_to_string (fst $1) }
654;
655string_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
667wstring_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
674one_string:
675    CST_STRING                          {$1}
676|   FUNCTION__                          {(Cabshelper.explodeStringToInts
677                                            !currentFunctionName), $1}
678|   PRETTY_FUNCTION__                   {(Cabshelper.explodeStringToInts
679                                            !currentFunctionName), $1}
680;   
681
682init_expression:
683     expression         { SINGLE_INIT (fst $1) }
684|    LBRACE initializer_list_opt RBRACE
685                        { COMPOUND_INIT $2}
686
687initializer_list:    /* ISO 6.7.8. Allow a trailing COMMA */
688    initializer                             { [$1] }
689|   initializer COMMA initializer_list_opt  { $1 :: $3 }
690;
691initializer_list_opt:
692    /* empty */                             { [] }
693|   initializer_list                        { $1 }
694;
695initializer:
696    init_designators eq_opt init_expression { ($1, $3) }
697|   gcc_init_designators init_expression { ($1, $2) }
698|                       init_expression { (NEXT_INIT, $1) }
699;
700eq_opt:
701   EQ                        { () }
702   /*(* GCC allows missing = *)*/
703|  /*(* empty *)*/               { () }
704;
705init_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;         
712init_designators_opt:
713   /* empty */                          { NEXT_INIT }
714|  init_designators                     { $1 }
715;
716
717gcc_init_designators:  /*(* GCC supports these strange things *)*/
718   id_or_typename COLON                 { INFIELD_INIT($1, NEXT_INIT) }
719;
720
721arguments:
722                /* empty */         { [] }
723|               comma_expression    { fst $1 }
724;
725
726opt_expression:
727                /* empty */
728                        {NOTHING}
729|               comma_expression
730                        {smooth_expression (fst $1)}
731;
732
733comma_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
739comma_expression_opt:
740                /* empty */         { NOTHING }
741|               comma_expression    { smooth_expression (fst $1) }
742;
743
744paren_comma_expression:
745  LPAREN comma_expression RPAREN                   { $2 }
746| LPAREN error RPAREN                              { [], $1 }
747;
748
749bracket_comma_expression:
750  LBRACKET comma_expression RBRACKET                   { fst $2 }
751| LBRACKET error RBRACKET                              { [] }
752;
753
754
755/*** statements ***/
756block: /* 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;
770block_begin:
771    LBRACE                               {!push_context (); $1}
772;
773
774block_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) */
781block_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
791local_labels:
792   /* empty */                                       { [] }
793|  LABEL__ local_label_names SEMICOLON local_labels  { $2 @ $4 }
794;
795local_label_names:
796   IDENT                                 { [ fst $1 ] }
797|  IDENT COMMA local_label_names         { fst $1 :: $3 }
798;
799
800
801
802statement:
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
861for_clause:
862    opt_expression SEMICOLON     { FC_EXP $1 }
863|   declaration                  { FC_DECL $1 }
864;
865
866declaration:                                /* 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;
872init_declarator_list:                       /* ISO 6.7 */
873    init_declarator                              { [$1] }
874|   init_declarator COMMA init_declarator_list   { $1 :: $3 }
875
876;
877init_declarator:                             /* ISO 6.7 */
878    declarator                          { ($1, NO_INIT) }
879|   declarator EQ init_expression
880                                        { ($1, $3) }
881;
882
883decl_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  *) */
899decl_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 */
907decl_spec_list_opt_no_named:
908    /* empty */                         { [] } %prec IDENT
909|   decl_spec_list                      { fst $1 }
910;
911type_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;
960struct_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;
979field_decl_list: /* (* ISO 6.7.2 *) */
980    field_decl                           { [$1] }
981|   field_decl COMMA field_decl_list     { $1 :: $3 }
982;
983field_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
992enum_list: /* (* ISO 6.7.2.2 *) */
993    enumerator                          {[$1]}
994|   enum_list COMMA enumerator          {$1 @ [$3]}
995|   enum_list COMMA error               { $1 }
996;
997enumerator:     
998    IDENT                       {(fst $1, NOTHING, snd $1)}
999|   IDENT EQ expression         {(fst $1, fst $3, snd $1)}
1000;
1001
1002
1003declarator:  /* (* 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
1010direct_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;
1032parameter_list_startscope:
1033    LPAREN                         { !push_context () }
1034;
1035rest_par_list:
1036|   /* empty */                    { ([], false) }
1037|   parameter_decl rest_par_list1  { let (params, isva) = $2 in
1038                                     ($1 :: params, isva)
1039                                   }
1040;
1041rest_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
1050parameter_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 *) */
1059old_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
1067direct_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
1088old_parameter_list_ne:
1089|  IDENT                                       { [fst $1] }
1090|  IDENT COMMA old_parameter_list_ne           { let rest = $3 in
1091                                                 (fst $1 :: rest) }
1092;
1093
1094old_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
1104old_pardef:
1105   declarator                             { [$1] }
1106|  declarator COMMA old_pardef            { $1 :: $3 }
1107|  error                                  { [] }
1108;
1109
1110
1111pointer: /* (* ISO 6.7.5 *) */
1112   STAR attributes pointer_opt  { $2 :: fst $3, $1 }
1113;
1114pointer_opt:
1115   /**/                          { let l = currentLoc () in
1116                                   ([], l) }
1117|  pointer                       { $1 }
1118;
1119
1120type_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;
1130abstract_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
1135abs_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;
1155abs_direct_decl_opt:
1156    abs_direct_decl                 { $1 }
1157|   /* empty */                     { JUSTBASE }
1158;
1159function_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
1169function_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 */
1218cvspec:
1219    CONST                               { SpecCV(CV_CONST), $1 }
1220|   VOLATILE                            { SpecCV(CV_VOLATILE), $1 }
1221|   RESTRICT                            { SpecCV(CV_RESTRICT), $1 }
1222;
1223
1224/*** GCC attributes ***/
1225attributes:
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 *) */
1232attributes_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 */
1241attribute_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
1254attribute_nocv_list:
1255    /* empty */                         { []}
1256|   attribute_nocv attribute_nocv_list  { fst $1 :: $2 }
1257;
1258
1259/* __attribute__ plus const/volatile */
1260attribute:
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) *)  */
1270just_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 */
1278just_attributes:
1279    just_attribute                      { [$1] }
1280|   just_attribute just_attributes      { $1 :: $2 }
1281;
1282
1283/** (* PRAGMAS and ATTRIBUTES *) ***/
1284pragma:
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 *) */
1290primary_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
1317postfix_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 *)*/
1332unary_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
1349cast_attr:
1350    unary_attr                           { $1 }
1351;   
1352
1353multiplicative_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
1361additive_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
1367shift_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
1373relational_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
1381equality_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
1388bitwise_and_attr:
1389    equality_attr                       { $1 }
1390|   bitwise_and_attr AND equality_attr  {BINARY(BAND ,$1 , $3)}
1391;
1392
1393bitwise_xor_attr:
1394    bitwise_and_attr                       { $1 }
1395|   bitwise_xor_attr CIRC bitwise_and_attr {BINARY(XOR ,$1 , $3)}
1396;
1397
1398bitwise_or_attr:
1399    bitwise_xor_attr                      { $1 }
1400|   bitwise_or_attr PIPE bitwise_xor_attr {BINARY(BOR ,$1 , $3)}
1401;
1402
1403logical_and_attr:
1404    bitwise_or_attr                             { $1 }
1405|   logical_and_attr AND_AND bitwise_or_attr    {BINARY(AND ,$1 , $3)}
1406;
1407
1408logical_or_attr:
1409    logical_and_attr                           { $1 }
1410|   logical_or_attr PIPE_PIPE logical_and_attr {BINARY(OR ,$1 , $3)}
1411;
1412
1413conditional_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
1420attr: conditional_attr                    { $1 }
1421;
1422
1423attr_list_ne:
1424|  attr                                  { [$1] }
1425|  attr COMMA attr_list_ne               { $1 :: $3 }
1426|  error COMMA attr_list_ne              { $3 }
1427;
1428attr_list:
1429  /* empty */                            { [] }
1430| attr_list_ne                           { $1 }
1431;
1432paren_attr_list_ne:
1433   LPAREN attr_list_ne RPAREN            { $2 }
1434|  LPAREN error RPAREN                   { [] }
1435;
1436paren_attr_list:
1437   LPAREN attr_list RPAREN               { $2 }
1438|  LPAREN error RPAREN                   { [] }
1439;
1440/*** GCC ASM instructions ***/
1441asmattr:
1442     /* empty */                        { [] }
1443|    VOLATILE  asmattr                  { ("volatile", []) :: $2 }
1444|    CONST asmattr                      { ("const", []) :: $2 }
1445;
1446asmtemplate:
1447    one_string_constant                          { [$1] }
1448|   one_string_constant asmtemplate              { $1 :: $2 }
1449;
1450asmoutputs:
1451  /* empty */           { None }
1452| COLON asmoperands asminputs
1453                        { let (ins, clobs) = $3 in
1454                          Some {aoutputs = $2; ainputs = ins; aclobbers = clobs} }
1455;
1456asmoperands:
1457     /* empty */                        { [] }
1458|    asmoperandsne                      { List.rev $1 }
1459;
1460asmoperandsne:
1461     asmoperand                         { [$1] }
1462|    asmoperandsne COMMA asmoperand     { $3 :: $1 }
1463;
1464asmoperand:
1465     asmopname string_constant LPAREN expression RPAREN    { ($1, fst $2, fst $4) }
1466|    asmopname string_constant LPAREN error RPAREN         { ($1, fst $2, NOTHING ) }
1467;
1468asminputs:
1469  /* empty */                { ([], []) }
1470| COLON asmoperands asmclobber
1471                        { ($2, $3) }
1472;
1473asmopname:
1474    /* empty */                         { None }
1475|   LBRACKET IDENT RBRACKET             { Some (fst $2) }
1476;
1477
1478asmclobber:
1479    /* empty */                         { [] }
1480| COLON asmcloberlst_ne                 { $2 }
1481;
1482asmcloberlst_ne:
1483   one_string_constant                           { [$1] }
1484|  one_string_constant COMMA asmcloberlst_ne     { $1 :: $3 }
1485;
1486 
1487%%
1488
1489
1490
Note: See TracBrowser for help on using the repository browser.