source: Deliverables/D2.3/8051-memoryspaces-branch/cparser/Parser.mly @ 460

Last change on this file since 460 was 460, checked in by campbell, 9 years ago

Port memory spaces changes to latest prototype compiler.

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