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>
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
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.
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
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.
39 ** 1.0 3.22.99 Hugues Cassé First version.
40 ** 2.0 George Necula 12/12/00: Practically complete rewrite.
49 ** Expression building
51 let smooth_expression lst =
58 let currentFunctionName = ref "<outside any function>"
60 let announceFunctionName ((n, decl, _, _):name) =
62 (* Start a context that includes the parameter names and the whole body.
63 * Will pop when we finish parsing the function body *)
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
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
77 and isJUSTBASE = function
79 | PARENTYPE (_, d, _) -> isJUSTBASE d
83 currentFunctionName := n
87 let applyPointer (ptspecs: attribute list list) (dt: decl_type)
89 (* Outer specification first *)
90 let rec loop = function
92 | attrs :: rest -> PTR(attrs, loop rest)
96 let doDeclaration (loc: cabsloc) (specs: spec_elem list) (nl: init_name list) : definition =
97 if isTypedef specs then begin
98 (* Tell the lexer about the new type names *)
99 List.iter (fun ((n, _, _, _), _) -> !add_type n) nl;
100 TYPEDEF ((specs, List.map (fun (n, _) -> n) nl), loc)
103 ONLYTYPEDEF (specs, loc)
105 (* Tell the lexer about the new variable names *)
106 List.iter (fun ((n, _, _, _), _) -> !add_identifier n) nl;
107 DECDEF ((specs, nl), loc)
111 let doFunctionDef (loc: cabsloc)
113 (specs: spec_elem list)
115 (b: block) : definition =
116 let fname = (specs, n) in
117 FUNDEF (fname, b, loc, lend)
120 let doOldParDecl (names: string list)
121 ((pardefs: name_group list), (isva: bool))
122 : single_name list * bool =
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
137 let args = List.map findOneName names in
140 let int64_to_char value =
141 if (compare value (Int64.of_int 255) > 0) || (compare value Int64.zero < 0) then
143 let msg = Printf.sprintf "cparser:intlist_to_string: character 0x%Lx too big" value in
145 raise Parsing.Parse_error
148 Char.chr (Int64.to_int value)
150 (* takes a not-nul-terminated list, and converts it to a string. *)
151 let rec intlist_to_string (str: int64 list):string =
153 [] -> "" (* add nul-termination *)
155 let this_char = int64_to_char value in
156 (String.make 1 this_char) ^ (intlist_to_string rest)
158 let fst3 (result, _, _) = result
159 let snd3 (_, result, _) = result
160 let trd3 (_, _, result) = result
164 transform: __builtin_offsetof(type, member)
165 into : (size_t) (&(type * ) 0)->member
168 let transformOffsetOf (speclist, dtype) member =
169 let rec addPointer = function
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)
181 let nullType = (speclist, addPointer dtype) in
182 let nullExpr = CONSTANT (CONST_INT "0") in
183 let castExpr = CAST (nullType, SINGLE_INIT nullExpr) in
185 let rec replaceBase = function
187 MEMBEROFPTR (castExpr, field)
188 | MEMBEROF (base, field) ->
189 MEMBEROF (replaceBase base, field)
190 | INDEX (base, index) ->
191 INDEX (replaceBase base, index)
193 parse_error "malformed offset expression in __builtin_offsetof";
194 raise Parsing.Parse_error
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
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
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
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
224 %token<Cabs.cabsloc> SIZEOF ALIGNOF
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
230 %token EQ_EQ EXCLAM_EQ INF SUP INF_EQ SUP_EQ
231 %token<Cabs.cabsloc> PLUS MINUS STAR
233 %token<Cabs.cabsloc> TILDE AND
235 %token<Cabs.cabsloc> EXCLAM AND_AND
237 %token INF_INF SUP_SUP
238 %token<Cabs.cabsloc> PLUS_PLUS MINUS_MINUS
241 %token<Cabs.cabsloc> LPAREN RBRACE
242 %token<Cabs.cabsloc> LBRACE
243 %token LBRACKET RBRACKET
245 %token<Cabs.cabsloc> SEMICOLON
246 %token COMMA ELLIPSIS QUEST
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
254 %token<Cabs.cabsloc> ATTRIBUTE INLINE ASM TYPEOF FUNCTION__ PRETTY_FUNCTION__
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
265 /* operator precedence */
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
279 %left EQ_EQ EXCLAM_EQ
280 %left INF SUP INF_EQ SUP_EQ
281 %left INF_INF SUP_SUP
283 %left STAR SLASH PERCENT CONST RESTRICT VOLATILE
284 %right EXCLAM TILDE PLUS_PLUS MINUS_MINUS CAST RPAREN ADDROF SIZEOF ALIGNOF
286 %left DOT ARROW LPAREN LBRACE
287 %right NAMED_TYPE /* We'll use this to handle redefinitions of
288 * NAMED_TYPE as variables */
291 /* Non-terminals informations */
292 %start interpret file
293 %type <Cabs.definition list> file interpret globals
295 %type <Cabs.definition> global
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
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
316 %type <spec_elem list * cabsloc> decl_spec_list
317 %type <typeSpecifier * cabsloc> type_spec
318 %type <Cabs.field_group list> struct_decl_list
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
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
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
355 | global globals { $1 :: $2 }
356 | SEMICOLON globals { $2 }
360 /* empty */ { currentLoc () } %prec IDENT
363 /*** Global Definition ***/
366 | function_def { $1 }
367 /*(* Some C header files ar shared with the C++ compiler and have linkage
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) }
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),
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),
393 /* | location error SEMICOLON { PRAGMA (VARIABLE "parse_error", $1) } */
398 | NAMED_TYPE {fst $1}
406 /* *** Expressions *** */
408 primary_expression: /*(* 6.5.1. *)*/
410 {VARIABLE (fst $1), snd $1}
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 }
419 postfix_expression: /*(* 6.5.2 *)*/
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
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
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 }
450 offsetof_member_designator: /* GCC extension for __builtin_offsetof */
453 | offsetof_member_designator DOT IDENT
454 { MEMBEROF ($1, fst $3) }
455 | offsetof_member_designator bracket_comma_expression
456 { INDEX ($1, smooth_expression $2) }
459 unary_expression: /*(* 6.5.3 *)*/
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 }
489 cast_expression: /*(* 6.5.4 *)*/
492 | LPAREN type_name RPAREN cast_expression
493 { CAST($2, SINGLE_INIT (fst $4)), $1 }
496 multiplicative_expression: /*(* 6.5.5 *)*/
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}
507 additive_expression: /*(* 6.5.6 *)*/
508 | multiplicative_expression
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}
516 shift_expression: /*(* 6.5.7 *)*/
517 | additive_expression
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}
526 relational_expression: /*(* 6.5.8 *)*/
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}
539 equality_expression: /*(* 6.5.9 *)*/
540 | relational_expression
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}
549 bitwise_and_expression: /*(* 6.5.10 *)*/
550 | equality_expression
552 | bitwise_and_expression AND equality_expression
553 {BINARY(BAND, fst $1, fst $3), snd $1}
556 bitwise_xor_expression: /*(* 6.5.11 *)*/
557 | bitwise_and_expression
559 | bitwise_xor_expression CIRC bitwise_and_expression
560 {BINARY(XOR, fst $1, fst $3), snd $1}
563 bitwise_or_expression: /*(* 6.5.12 *)*/
564 | bitwise_xor_expression
566 | bitwise_or_expression PIPE bitwise_xor_expression
567 {BINARY(BOR, fst $1, fst $3), snd $1}
570 logical_and_expression: /*(* 6.5.13 *)*/
571 | bitwise_or_expression
573 | logical_and_expression AND_AND bitwise_or_expression
574 {BINARY(AND, fst $1, fst $3), snd $1}
577 logical_or_expression: /*(* 6.5.14 *)*/
578 | logical_and_expression
580 | logical_or_expression PIPE_PIPE logical_and_expression
581 {BINARY(OR, fst $1, fst $3), snd $1}
584 conditional_expression: /*(* 6.5.15 *)*/
585 | logical_or_expression
587 | logical_or_expression QUEST opt_expression COLON conditional_expression
588 {QUESTION (fst $1, $3, fst $5), snd $1}
591 /*(* The C spec says that left-hand sides of assignment expressions are unary
592 * expressions. GCC allows cast expressions in there ! *)*/
594 assignment_expression: /*(* 6.5.16 *)*/
595 | conditional_expression
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}
621 expression: /*(* 6.5.17 *)*/
622 assignment_expression
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}
637 /* Now that we know this constant isn't part of a wstring, convert it
638 back to a string for easy viewing. */
640 let queue, location = $1 in
641 let buffer = Buffer.create (Queue.length queue) in
645 let char = int64_to_char value in
646 Buffer.add_char buffer char))
648 Buffer.contents buffer, location
652 /* Don't concat multiple strings. For asm templates. */
653 CST_STRING {intlist_to_string (fst $1) }
657 let queue = Queue.create () in
658 Queue.add (fst $1) queue;
661 | string_list one_string {
662 Queue.add (fst $2) (fst $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". */
676 | FUNCTION__ {(Cabshelper.explodeStringToInts
677 !currentFunctionName), $1}
678 | PRETTY_FUNCTION__ {(Cabshelper.explodeStringToInts
679 !currentFunctionName), $1}
683 expression { SINGLE_INIT (fst $1) }
684 | LBRACE initializer_list_opt RBRACE
687 initializer_list: /* ISO 6.7.8. Allow a trailing COMMA */
689 | initializer COMMA initializer_list_opt { $1 :: $3 }
691 initializer_list_opt:
693 | initializer_list { $1 }
696 init_designators eq_opt init_expression { ($1, $3) }
697 | gcc_init_designators init_expression { ($1, $2) }
698 | init_expression { (NEXT_INIT, $1) }
702 /*(* GCC allows missing = *)*/
703 | /*(* empty *)*/ { () }
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) }
712 init_designators_opt:
713 /* empty */ { NEXT_INIT }
714 | init_designators { $1 }
717 gcc_init_designators: /*(* GCC supports these strange things *)*/
718 id_or_typename COLON { INFIELD_INIT($1, NEXT_INIT) }
723 | comma_expression { fst $1 }
730 {smooth_expression (fst $1)}
734 expression {[fst $1], snd $1}
735 | expression COMMA comma_expression { fst $1 :: fst $3, snd $1 }
736 | error COMMA comma_expression { $3 }
739 comma_expression_opt:
740 /* empty */ { NOTHING }
741 | comma_expression { smooth_expression (fst $1) }
744 paren_comma_expression:
745 LPAREN comma_expression RPAREN { $2 }
746 | LPAREN error RPAREN { [], $1 }
749 bracket_comma_expression:
750 LBRACKET comma_expression RBRACKET { fst $2 }
751 | LBRACKET error RBRACKET { [] }
756 block: /* ISO 6.8.2 */
757 block_begin local_labels block_attrs block_element_list RBRACE
764 | error location RBRACE { { blabels = [];
771 LBRACE {!push_context (); $1}
776 | BLOCKATTRIBUTE paren_attr_list_ne
777 { [("__blockattribute__", $2)] }
780 /* statements and declarations in a block, in any order (for C99 support) */
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),
788 | pragma block_element_list { $2 }
793 | LABEL__ local_label_names SEMICOLON local_labels { $2 @ $4 }
797 | IDENT COMMA local_label_names { fst $1 :: $3 }
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)}
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
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
853 if not !msvcMode then
854 parse_error "try/finally in GCC code";
855 TRY_FINALLY (b, h, (*handleLoc*) $1) }
857 | error location SEMICOLON { (NOP $2)}
862 opt_expression SEMICOLON { FC_EXP $1 }
863 | declaration { FC_DECL $1 }
866 declaration: /* ISO 6.7.*/
867 decl_spec_list init_declarator_list SEMICOLON
868 { doDeclaration ((*handleLoc*)(snd $1)) (fst $1) $2 }
869 | decl_spec_list SEMICOLON
870 { doDeclaration ((*handleLoc*)(snd $1)) (fst $1) [] }
872 init_declarator_list: /* ISO 6.7 */
873 init_declarator { [$1] }
874 | init_declarator COMMA init_declarator_list { $1 :: $3 }
877 init_declarator: /* ISO 6.7 */
878 declarator { ($1, NO_INIT) }
879 | declarator EQ init_expression
883 decl_spec_list: /* ISO 6.7 */
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}
891 | type_spec decl_spec_list_opt_no_named { SpecType (fst $1) :: $2, snd $1 }
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 }
897 /* (* In most cases if we see a NAMED_TYPE we must shift it. Thus we declare
898 * NAMED_TYPE to have right associativity *) */
900 /* empty */ { [] } %prec NAMED_TYPE
901 | decl_spec_list { fst $1 }
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 *)
907 decl_spec_list_opt_no_named:
908 /* empty */ { [] } %prec IDENT
909 | decl_spec_list { fst $1 }
911 type_spec: /* ISO 6.7.2 */
913 | UNDERSCORE_BOOL { T_Bool, $1 }
915 | SHORT { Tshort, $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 }
960 struct_decl_list: /* (* ISO 6.7.2. Except that we allow empty structs. We
961 * also allow missing field names. *)
964 | decl_spec_list SEMICOLON struct_decl_list
966 [(missingFieldDecl, None)]) :: $3 }
967 /*(* GCC allows extra semicolons *)*/
968 | SEMICOLON struct_decl_list
970 | decl_spec_list field_decl_list SEMICOLON struct_decl_list
973 /*(* MSVC allows pragmas in strange places *)*/
974 | pragma struct_decl_list { $2 }
976 | error SEMICOLON struct_decl_list
979 field_decl_list: /* (* ISO 6.7.2 *) */
981 | field_decl COMMA field_decl_list { $1 :: $3 }
983 field_decl: /* (* ISO 6.7.2. Except that we allow unnamed fields. *) */
984 | declarator { ($1, None) }
985 | declarator COLON expression attributes
986 { let (n,decl,al,loc) = $1 in
988 ((n,decl,al',loc), Some (fst $3)) }
989 | COLON expression { (missingFieldDecl, Some (fst $2)) }
992 enum_list: /* (* ISO 6.7.2.2 *) */
994 | enum_list COMMA enumerator {$1 @ [$3]}
995 | enum_list COMMA error { $1 }
998 IDENT {(fst $1, NOTHING, snd $1)}
999 | IDENT EQ expression {(fst $1, fst $3, snd $1)}
1003 declarator: /* (* ISO 6.7.5. Plus Microsoft declarators.*) */
1004 pointer_opt direct_decl attributes_with_asm
1005 { let (n, decl) = $2 in
1006 (n, applyPointer (fst $1) decl, $3, (snd $1)) }
1010 direct_decl: /* (* ISO 6.7.5 *) */
1011 /* (* We want to be able to redefine named
1012 * types as variable names *) */
1013 | id_or_typename { ($1, JUSTBASE) }
1015 | LPAREN attributes declarator RPAREN
1016 { let (n,decl,al,loc) = $3 in
1017 (n, PARENTYPE($2,decl,al)) }
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
1029 (n, PROTO(decl, params, isva))
1032 parameter_list_startscope:
1033 LPAREN { !push_context () }
1036 | /* empty */ { ([], false) }
1037 | parameter_decl rest_par_list1 { let (params, isva) = $2 in
1038 ($1 :: params, isva)
1042 /* empty */ { ([], false) }
1043 | COMMA ELLIPSIS { ([], true) }
1044 | COMMA parameter_decl rest_par_list1 { let (params, isva) = $3 in
1045 ($2 :: params, isva)
1050 parameter_decl: /* (* ISO 6.7.5 *) */
1051 decl_spec_list declarator { (fst $1, $2) }
1052 | decl_spec_list abstract_decl { let d, a = $2 in
1053 (fst $1, ("", d, a, cabslu)) }
1054 | decl_spec_list { (fst $1, ("", JUSTBASE, [], cabslu)) }
1055 | LPAREN parameter_decl RPAREN { $2 }
1058 /* (* Old style prototypes. Like a declarator *) */
1060 pointer_opt direct_old_proto_decl { let (n, decl, a) = $2 in
1061 (n, applyPointer (fst $1) decl,
1067 direct_old_proto_decl:
1068 direct_decl LPAREN old_parameter_list_ne RPAREN old_pardef_list
1069 { let par_decl, isva = doOldParDecl $3 $5 in
1071 (n, PROTO(decl, par_decl, isva), [])
1073 | direct_decl LPAREN RPAREN
1074 { let n, decl = $1 in
1075 (n, PROTO(decl, [], false), [])
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
1083 (n, PROTO(decl, par_decl, isva), [])
1088 old_parameter_list_ne:
1089 | IDENT { [fst $1] }
1090 | IDENT COMMA old_parameter_list_ne { let rest = $3 in
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)
1106 | declarator COMMA old_pardef { $1 :: $3 }
1111 pointer: /* (* ISO 6.7.5 *) */
1112 STAR attributes pointer_opt { $2 :: fst $3, $1 }
1115 /**/ { let l = currentLoc () in
1120 type_name: /* (* ISO 6.7.6 *) */
1121 decl_spec_list abstract_decl { let d, a = $2 in
1122 if a <> [] then begin
1123 parse_error "attributes in type name";
1124 raise Parsing.Parse_error
1128 | decl_spec_list { (fst $1, JUSTBASE) }
1130 abstract_decl: /* (* ISO 6.7.6. *) */
1131 pointer_opt abs_direct_decl attributes { applyPointer (fst $1) $2, $3 }
1132 | pointer { applyPointer (fst $1) JUSTBASE, [] }
1135 abs_direct_decl: /* (* ISO 6.7.6. We do not support optional declarator for
1136 * functions. Plus Microsoft attributes. See the
1137 * discussion for declarator. *) */
1138 | LPAREN attributes abstract_decl RPAREN
1140 PARENTYPE ($2, d, a)
1143 | LPAREN error RPAREN
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
1152 PROTO ($1, params, isva)
1155 abs_direct_decl_opt:
1156 abs_direct_decl { $1 }
1157 | /* empty */ { JUSTBASE }
1159 function_def: /* (* ISO 6.9.1 *) */
1160 function_def_start block
1161 { let (loc, specs, decl) = $1 in
1162 currentFunctionName := "<__FUNCTION__ used outside any functions>";
1163 !pop_context (); (* The context pushed by
1164 * announceFunctionName *)
1165 doFunctionDef ((*handleLoc*) loc) (trd3 $2) specs decl (fst3 $2)
1169 function_def_start: /* (* ISO 6.9.1 *) */
1170 decl_spec_list declarator
1171 { announceFunctionName $2;
1172 (snd $1, fst $1, $2)
1175 /* (* Old-style function prototype *) */
1176 | decl_spec_list old_proto_decl
1177 { announceFunctionName $2;
1178 (snd $1, fst $1, $2)
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
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)
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 *)
1197 PROTO(JUSTBASE, pardecl,isva),
1199 announceFunctionName fdec;
1200 (* Default is int type *)
1201 let defSpec = [SpecType Tint] in
1202 (snd $1, defSpec, fdec)
1204 /* (* No return type and no parameters *) */
1205 | IDENT LPAREN RPAREN
1206 { (* Make the function declarator *)
1208 PROTO(JUSTBASE, [], false),
1210 announceFunctionName fdec;
1211 (* Default is int type *)
1212 let defSpec = [SpecType Tint] in
1213 (snd $1, defSpec, fdec)
1217 /* const/volatile as type specifier elements */
1219 CONST { SpecCV(CV_CONST), $1 }
1220 | VOLATILE { SpecCV(CV_VOLATILE), $1 }
1221 | RESTRICT { SpecCV(CV_RESTRICT), $1 }
1224 /*** GCC attributes ***/
1227 | attribute attributes { fst $1 :: $2 }
1230 /* (* In some contexts we can have an inline assembly to specify the name to
1231 * be used for a global. We treat this as a name attribute *) */
1232 attributes_with_asm:
1234 | attribute attributes_with_asm { fst $1 :: $2 }
1235 | ASM LPAREN string_constant RPAREN attributes
1237 [CONSTANT(CONST_STRING (fst $3))]) :: $5 }
1240 /* things like __attribute__, but no const/volatile */
1242 ATTRIBUTE LPAREN paren_attr_list RPAREN
1243 { ("__attribute__", $3), $1 }
1245 | ATTRIBUTE_USED { ("__attribute__",
1246 [ VARIABLE "used" ]), $1 }
1248 | DECLSPEC paren_attr_list_ne { ("__declspec", $2), $1 }
1249 | MSATTR { (fst $1, []), snd $1 }
1251 | THREAD { ("__thread",[]), $1 }
1254 attribute_nocv_list:
1256 | attribute_nocv attribute_nocv_list { fst $1 :: $2 }
1259 /* __attribute__ plus const/volatile */
1261 attribute_nocv { $1 }
1262 | CONST { ("const", []), $1 }
1263 | RESTRICT { ("restrict",[]), $1 }
1264 | VOLATILE { ("volatile",[]), $1 }
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) *) */
1271 ATTRIBUTE LPAREN paren_attr_list RPAREN
1272 { ("__attribute__", $3) }
1273 | DECLSPEC paren_attr_list_ne { ("__declspec", $2) }
1276 /* this can't be empty, b/c I folded that possibility into the calling
1277 * productions to avoid some S/R conflicts */
1279 just_attribute { [$1] }
1280 | just_attribute just_attributes { $1 :: $2 }
1283 /** (* PRAGMAS and ATTRIBUTES *) ***/
1285 | PRAGMA_LINE { PRAGMA (fst $1, snd $1) }
1288 /* (* We want to allow certain strange things that occur in pragmas, so we
1289 * cannot use directly the language of expressions *) */
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
1301 | CONST { VARIABLE "aconst" }
1303 | IDENT COLON CST_INT { VARIABLE (fst $1 ^ ":" ^ fst $3) }
1305 /*(* The following rule conflicts with the ? : attributes. We give it a very
1307 | CST_INT COLON CST_INT { VARIABLE (fst $1 ^ ":" ^ fst $3) }
1309 | DEFAULT COLON CST_INT { VARIABLE ("default:" ^ fst $3) }
1311 /*(** GCC allows this as an
1312 * attribute for functions,
1313 * synonim for noreturn **)*/
1314 | VOLATILE { VARIABLE ("__noreturn__") }
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) }
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) }
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 *)*/
1334 | SIZEOF unary_expression {EXPR_SIZEOF (fst $2) }
1335 | SIZEOF LPAREN type_name RPAREN
1336 {let b, d = $3 in TYPE_SIZEOF (b, d)}
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)}
1344 {UNARY (ADDROF, $2)}
1345 | EXCLAM cast_attr {UNARY (NOT, $2)}
1346 | TILDE cast_attr {UNARY (BNOT, $2)}
1353 multiplicative_attr:
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)}
1362 multiplicative_attr { $1 }
1363 | additive_attr PLUS multiplicative_attr {BINARY(ADD ,$1 , $3)}
1364 | additive_attr MINUS multiplicative_attr {BINARY(SUB ,$1 , $3)}
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)}
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)}
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)}
1389 equality_attr { $1 }
1390 | bitwise_and_attr AND equality_attr {BINARY(BAND ,$1 , $3)}
1394 bitwise_and_attr { $1 }
1395 | bitwise_xor_attr CIRC bitwise_and_attr {BINARY(XOR ,$1 , $3)}
1399 bitwise_xor_attr { $1 }
1400 | bitwise_or_attr PIPE bitwise_xor_attr {BINARY(BOR ,$1 , $3)}
1404 bitwise_or_attr { $1 }
1405 | logical_and_attr AND_AND bitwise_or_attr {BINARY(AND ,$1 , $3)}
1409 logical_and_attr { $1 }
1410 | logical_or_attr PIPE_PIPE logical_and_attr {BINARY(OR ,$1 , $3)}
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) }
1420 attr: conditional_attr { $1 }
1425 | attr COMMA attr_list_ne { $1 :: $3 }
1426 | error COMMA attr_list_ne { $3 }
1430 | attr_list_ne { $1 }
1433 LPAREN attr_list_ne RPAREN { $2 }
1434 | LPAREN error RPAREN { [] }
1437 LPAREN attr_list RPAREN { $2 }
1438 | LPAREN error RPAREN { [] }
1440 /*** GCC ASM instructions ***/
1443 | VOLATILE asmattr { ("volatile", []) :: $2 }
1444 | CONST asmattr { ("const", []) :: $2 }
1447 one_string_constant { [$1] }
1448 | one_string_constant asmtemplate { $1 :: $2 }
1451 /* empty */ { None }
1452 | COLON asmoperands asminputs
1453 { let (ins, clobs) = $3 in
1454 Some {aoutputs = $2; ainputs = ins; aclobbers = clobs} }
1458 | asmoperandsne { List.rev $1 }
1462 | asmoperandsne COMMA asmoperand { $3 :: $1 }
1465 asmopname string_constant LPAREN expression RPAREN { ($1, fst $2, fst $4) }
1466 | asmopname string_constant LPAREN error RPAREN { ($1, fst $2, NOTHING ) }
1469 /* empty */ { ([], []) }
1470 | COLON asmoperands asmclobber
1474 /* empty */ { None }
1475 | LBRACKET IDENT RBRACKET { Some (fst $2) }
1480 | COLON asmcloberlst_ne { $2 }
1483 one_string_constant { [$1] }
1484 | one_string_constant COMMA asmcloberlst_ne { $1 :: $3 }