4 * Copyright (C) 2002, 2006, 2007, 2008, 2009 Yoann Padioleau
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License (GPL)
8 * version 2 as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * file license.txt for more details.
19 module LP = Lexer_parser
20 open Lexer_parser (* for the fields *)
22 open Semantic_c (* Semantic exn *)
25 (*****************************************************************************)
27 (*****************************************************************************)
29 if !Flag_parsing_c.verbose_parsing
30 then Common.warning ("PARSING: " ^ s) v
33 let pr2, pr2_once = Common.mk_pr2_wrappers Flag_parsing_c.verbose_parsing
35 (*****************************************************************************)
36 (* Parse helpers functions *)
37 (*****************************************************************************)
39 (*-------------------------------------------------------------------------- *)
41 (*-------------------------------------------------------------------------- *)
43 type shortLong = Short | Long | LongLong
46 storageD: storagebis wrap;
47 typeD: ((sign option) * (shortLong option) * (typeCbis option)) wrap;
48 qualifD: typeQualifierbis wrap;
50 (* note: have a full_info: parse_info list; to remember ordering
51 * between storage, qualifier, type ? well this info is already in
52 * the Ast_c.info, just have to sort them to get good order *)
57 typeD = (None, None, None), [];
61 let fake_pi = Common.fake_parse_info
63 let addStorageD = function
64 | ((x,ii), ({storageD = (NoSto,[])} as v)) -> { v with storageD = (x, [ii]) }
65 | ((x,ii), ({storageD = (y, ii2)} as v)) ->
66 if x =*= y then warning "duplicate storage classes" v
67 else raise (Semantic ("multiple storage classes", fake_pi))
69 let addInlineD = function
70 | ((true,ii), ({inlineD = (false,[])} as v)) -> { v with inlineD=(true,[ii])}
71 | ((true,ii), ({inlineD = (true, ii2)} as v)) -> warning "duplicate inline" v
72 | _ -> raise (Impossible 86)
75 let addTypeD = function
76 | ((Left3 Signed,ii) ,({typeD = ((Some Signed, b,c),ii2)} as v)) ->
77 warning "duplicate 'signed'" v
78 | ((Left3 UnSigned,ii) ,({typeD = ((Some UnSigned,b,c),ii2)} as v)) ->
79 warning "duplicate 'unsigned'" v
80 | ((Left3 _,ii), ({typeD = ((Some _,b,c),ii2)} as _v)) ->
81 raise (Semantic ("both signed and unsigned specified", fake_pi))
82 | ((Left3 x,ii), ({typeD = ((None,b,c),ii2)} as v)) ->
83 {v with typeD = (Some x,b,c),ii ++ ii2}
85 | ((Middle3 Short,ii), ({typeD = ((a,Some Short,c),ii2)} as v)) ->
86 warning "duplicate 'short'" v
89 (* gccext: long long allowed *)
90 | ((Middle3 Long,ii), ({typeD = ((a,Some Long ,c),ii2)} as v)) ->
91 { v with typeD = (a, Some LongLong, c),ii++ii2 }
92 | ((Middle3 Long,ii), ({typeD = ((a,Some LongLong ,c),ii2)} as v)) ->
93 warning "triplicate 'long'" v
96 | ((Middle3 _,ii), ({typeD = ((a,Some _,c),ii2)} as _v)) ->
97 raise (Semantic ("both long and short specified", fake_pi))
98 | ((Middle3 x,ii), ({typeD = ((a,None,c),ii2)} as v)) ->
99 {v with typeD = (a, Some x,c),ii++ii2}
101 | ((Right3 t,ii), ({typeD = ((a,b,Some x),ii2)} as _v)) ->
102 raise (Semantic ((Printf.sprintf "two or more data types: t %s ii %s\ntypeD %s ii2 %s\n" (Dumper.dump t) (Dumper.dump ii) (Dumper.dump x) (Dumper.dump ii2)), fake_pi))
103 | ((Right3 t,ii), ({typeD = ((a,b,None),ii2)} as v)) ->
104 {v with typeD = (a,b, Some t),ii++ii2}
107 let addQualif = function
108 | ({const=true}, ({const=true} as x)) -> warning "duplicate 'const'" x
109 | ({volatile=true},({volatile=true} as x))-> warning "duplicate 'volatile'" x
110 | ({const=true}, v) -> {v with const=true}
111 | ({volatile=true}, v) -> {v with volatile=true}
113 internal_error "there is no noconst or novolatile keyword"
115 let addQualifD ((qu,ii), ({qualifD = (v,ii2)} as x)) =
116 { x with qualifD = (addQualif (qu, v),ii::ii2) }
119 (*-------------------------------------------------------------------------- *)
120 (* Declaration/Function related *)
121 (*-------------------------------------------------------------------------- *)
124 (* stdC: type section, basic integer types (and ritchie)
125 * To understand the code, just look at the result (right part of the PM)
128 let (fixDeclSpecForDecl: decl -> (fullType * (storage wrap))) = function
129 {storageD = (st,iist);
132 inlineD = (inline,iinl);
136 | (None,None,None) ->
137 (* generate fake_info, otherwise type_annotater can crash in
140 warning "type defaults to 'int'" (defaultInt, [fakeInfo fake_pi])
141 | (None, None, Some t) -> (t, iit)
143 | (Some sign, None, (None| Some (BaseType (IntType (Si (_,CInt)))))) ->
144 BaseType(IntType (Si (sign, CInt))), iit
145 | ((None|Some Signed),Some x,(None|Some(BaseType(IntType (Si (_,CInt)))))) ->
146 BaseType(IntType (Si (Signed, [Short,CShort; Long, CLong; LongLong, CLongLong] +> List.assoc x))), iit
147 | (Some UnSigned, Some x, (None| Some (BaseType (IntType (Si (_,CInt))))))->
148 BaseType(IntType (Si (UnSigned, [Short,CShort; Long, CLong; LongLong, CLongLong] +> List.assoc x))), iit
149 | (Some sign, None, (Some (BaseType (IntType CChar)))) ->
150 BaseType(IntType (Si (sign, CChar2))), iit
151 | (None, Some Long,(Some(BaseType(FloatType CDouble)))) ->
152 BaseType (FloatType (CLongDouble)), iit
154 | (Some _,_, Some _) ->
156 raise (Semantic ("signed, unsigned valid only for char and int", fake_pi))
157 | (_,Some _,(Some(BaseType(FloatType (CFloat|CLongDouble))))) ->
158 raise (Semantic ("long or short specified with floatint type", fake_pi))
159 | (_,Some Short,(Some(BaseType(FloatType CDouble)))) ->
160 raise (Semantic ("the only valid combination is long double", fake_pi))
162 | (_, Some _, Some _) ->
164 raise (Semantic ("long, short valid only for int or float", fake_pi))
166 (* if do short uint i, then gcc say parse error, strange ? it is
167 * not a parse error, it is just that we dont allow with typedef
168 * either short/long or signed/unsigned. In fact, with
169 * parse_typedef_fix2 (with et() and dt()) now I say too parse
170 * error so this code is executed only when do short struct
171 * {....} and never with a typedef cos now we parse short uint i
172 * as short ident ident => parse error (cos after first short i
173 * pass in dt() mode) *)
179 ,((st, inline),iist++iinl)
182 let fixDeclSpecForParam = function ({storageD = (st,iist)} as r) ->
183 let ((qu,ty) as v,_st) = fixDeclSpecForDecl r in
185 | (Sto Register) -> (v, true), iist
186 | NoSto -> (v, false), iist
189 (Semantic ("storage class specified for parameter of function",
192 let fixDeclSpecForMacro = function ({storageD = (st,iist)} as r) ->
193 let ((qu,ty) as v,_st) = fixDeclSpecForDecl r in
198 (Semantic ("storage class specified for macro type decl",
202 let fixDeclSpecForFuncDef x =
203 let (returnType,storage) = fixDeclSpecForDecl x in
204 (match fst (unwrap storage) with
206 raise (Semantic ("function definition declared 'typedef'", fake_pi))
207 | _ -> (returnType, storage)
211 (* parameter: (this is the context where we give parameter only when
212 * in func DEFINITION not in funct DECLARATION) We must have a name.
213 * This function ensure that we give only parameterTypeDecl with well
214 * formed Classic constructor todo?: do we accept other declaration
215 * in ? so I must add them to the compound of the deffunc. I dont
216 * have to handle typedef pb here cos C forbid to do VF f { ... }
217 * with VF a typedef of func cos here we dont see the name of the
218 * argument (in the typedef)
220 let (fixOldCDecl: fullType -> fullType) = fun ty ->
221 match Ast_c.unwrap_typeC ty with
222 | FunctionType (fullt, (params, (b, iib))) ->
224 (* stdC: If the prototype declaration declares a parameter for a
225 * function that you are defining (it is part of a function
226 * definition), then you must write a name within the declarator.
227 * Otherwise, you can omit the name. *)
229 | [{p_namei = None; p_type = ty2},_] ->
230 (match Ast_c.unwrap_typeC ty2 with
234 pr2_once ("SEMANTIC:parameter name omitted, but I continue");
239 (params +> List.iter (fun (param,_) ->
241 | {p_namei = None} ->
242 (* if majuscule, then certainly macro-parameter *)
243 pr2_once ("SEMANTIC:parameter name omitted, but I continue");
249 (* todo? can we declare prototype in the decl or structdef,
250 ... => length <> but good kan meme *)
252 (* gcc say parse error but dont see why *)
253 raise (Semantic ("seems this is not a function", fake_pi))
256 let fixFunc (typ, compound, old_style_opt) =
257 let (cp,iicp) = compound in
259 let (name, ty, (st,iist), attrs) = typ in
261 let (qu, tybis) = ty in
263 match Ast_c.unwrap_typeC ty with
264 | FunctionType (fullt, (params,abool)) ->
265 let iifunc = Ast_c.get_ii_typeC_take_care tybis in
267 let iistart = Ast_c.fakeInfo () in
268 assert (qu =*= nullQualif);
271 | [{p_namei= None; p_type = ty2}, _] ->
272 (match Ast_c.unwrap_typeC ty2 with
273 | BaseType Void -> ()
275 (* failwith "internal errror: fixOldCDecl not good" *)
279 params +> List.iter (function
280 | ({p_namei = Some s}, _) -> ()
282 (* failwith "internal errror: fixOldCDecl not good" *)
285 (* bugfix: cf tests_c/function_pointer4.c.
286 * Apparemment en C on peut syntaxiquement ecrire ca:
288 * void a(int)(int x);
289 * mais apres gcc gueule au niveau semantique avec:
290 * xxx.c:1: error: 'a' declared as function returning a function
291 * Je ne faisais pas cette verif. Sur du code comme
292 * void METH(foo)(int x) { ...} , le parser croit (a tort) que foo
293 * est un typedef, et donc c'est parsé comme l'exemple precedent,
294 * ce qui ensuite confuse l'unparser qui n'est pas habitué
295 * a avoir dans le returnType un FunctionType et qui donc
296 * pr_elem les ii dans le mauvais sens ce qui genere au final
297 * une exception. Hence this fix to at least detect the error
298 * at parsing time (not unparsing time).
300 (match Ast_c.unwrap_typeC fullt with
302 let s = Ast_c.str_of_name name in
303 let iis = Ast_c.info_of_name name in
304 pr2 (spf "WEIRD: %s declared as function returning a function." s);
305 pr2 (spf "This is probably because of a macro. Extend standard.h");
306 raise (Semantic (spf "error: %s " s, Ast_c.parse_info_of_info iis))
310 (* it must be nullQualif,cos parser construct only this*)
312 f_type = (fullt, (params, abool));
316 f_old_c_style = old_style_opt;
318 (iifunc++iicp++[iistart]++iist)
322 ("you are trying to do a function definition but you dont give " ^
323 "any parameter", fake_pi))
326 (*-------------------------------------------------------------------------- *)
327 (* parse_typedef_fix2 *)
328 (*-------------------------------------------------------------------------- *)
331 if !Flag_parsing_c.debug_etdt then pr2 ("<" ^ s);
332 LP.disable_typedef ()
335 if !Flag_parsing_c.debug_etdt then pr2 (">" ^ s);
339 let fix_add_params_ident x =
340 let (s, ty, st, _attrs) = x in
341 match Ast_c.unwrap_typeC ty with
342 | FunctionType (fullt, (params, bool)) ->
345 | [{p_namei=None; p_type=ty2}, _] ->
346 (match Ast_c.unwrap_typeC ty2 with
347 | BaseType Void -> ()
349 (* failwith "internal errror: fixOldCDecl not good" *)
353 params +> List.iter (function
354 | ({p_namei= Some name}, _) ->
355 LP.add_ident (Ast_c.str_of_name s)
358 (* failwith "internal errror: fixOldCDecl not good" *)
365 (*-------------------------------------------------------------------------- *)
367 (*-------------------------------------------------------------------------- *)
369 let mk_e e ii = Ast_c.mk_e e ii
371 let mk_string_wrap (s,info) = (s, [info])
375 /*(*****************************************************************************)*/
377 /*(*************************************************************************)*/
381 * Some tokens are not even used in this file because they are filtered
382 * in some intermediate phase. But they still must be declared because
383 * ocamllex may generate them, or some intermediate phase may also
384 * generate them (like some functions in parsing_hacks.ml)
388 %token <Ast_c.info> TUnknown /*(* unrecognized token *)*/
390 /*(* coupling: Token_helpers.is_real_comment *)*/
391 %token <Ast_c.info> TCommentSpace TCommentNewline TComment
393 /*(*-----------------------------------------*)*/
394 /*(* the normal tokens *)*/
395 /*(*-----------------------------------------*)*/
397 %token <(string * (Ast_c.sign * Ast_c.base)) * Ast_c.info> TInt
398 %token <(string * Ast_c.floatType) * Ast_c.info> TFloat
399 %token <(string * Ast_c.isWchar) * Ast_c.info> TChar
400 %token <(string * Ast_c.isWchar) * Ast_c.info> TString
402 %token <string * Ast_c.info> TIdent
403 %token <string * Ast_c.info> TKRParam
404 %token <string * Ast_c.info> Tconstructorname /* parsing_hack for c++ */
405 /*(* appears mostly after some fix_xxx in parsing_hack *)*/
406 %token <string * Ast_c.info> TypedefIdent
410 (* Some tokens like TOPar and TCPar are used as synchronisation stuff,
411 * in parsing_hack.ml. So if define special tokens like TOParDefine and
412 * TCParEOL, then take care to also modify in Token_helpers.
416 %token <Ast_c.info> TOPar TCPar TOBrace TCBrace TOCro TCCro
417 %token <Ast_c.info> TDot TComma TPtrOp
418 %token <Ast_c.info> TInc TDec
419 %token <Ast_c.assignOp * Ast_c.info> TAssign
420 %token <Ast_c.info> TEq
421 %token <Ast_c.info> TWhy TTilde TBang
422 %token <Ast_c.info> TEllipsis
423 %token <Ast_c.info> TDotDot
425 %token <Ast_c.info> TPtVirg
427 TOrLog TAndLog TOr TXor TAnd TEqEq TNotEq TInf TSup TInfEq TSupEq
429 TPlus TMinus TMul TDiv TMod TMin TMax
432 Tchar Tshort Tint Tdouble Tfloat Tlong Tunsigned Tsigned Tvoid
433 Tsize_t Tssize_t Tptrdiff_t
434 Tauto Tregister Textern Tstatic
438 Tbreak Telse Tswitch Tcase Tcontinue Tfor Tdo Tif Twhile Treturn
440 Tsizeof Tnew Tdelete TOParCplusplusInit Tnamespace
446 /*(*-----------------------------------------*)*/
447 /*(* gccext: extra tokens *)*/
448 /*(*-----------------------------------------*)*/
449 %token <Ast_c.info> Tasm
450 %token <Ast_c.info> Tattribute
451 %token <Ast_c.info> TattributeNoarg
452 %token <Ast_c.info> Tinline
453 %token <Ast_c.info> Ttypeof
455 /*(*-----------------------------------------*)*/
456 /*(* cppext: extra tokens *)*/
457 /*(*-----------------------------------------*)*/
458 /*(* coupling with Token_helpers.is_cpp_token *)*/
461 /*(*---------------*)*/
463 /*(*---------------*)*/
465 %token <Ast_c.info> TDefine
466 %token <(string * Ast_c.info)> TDefParamVariadic
468 /*(* disappear after fix_tokens_define *)*/
469 %token <Ast_c.info> TCppEscapedNewline
471 %token <Ast_c.info> TCppConcatOp
473 /*(* appear after fix_tokens_define *)*/
474 %token <Ast_c.info> TOParDefine
475 %token <Ast_c.info> TOBraceDefineInit
477 %token <(string * Ast_c.info)> TIdentDefine /*(* same *)*/
478 %token <Ast_c.info> TDefEOL /*(* same *)*/
481 /*(*---------------*)*/
483 /*(*---------------*)*/
486 /*(* used only in lexer_c, then transformed in comment or splitted in tokens *)*/
487 %token <(string * string * bool ref * Ast_c.info)> TInclude
489 /*(* tokens coming from above, generated in parse_c from TInclude, etc *)*/
490 %token <(Ast_c.info * bool ref)> TIncludeStart
491 %token <(string * Ast_c.info)> TIncludeFilename
494 /*(*---------------*)*/
496 /*(*---------------*)*/
498 /*(* coupling: Token_helpers.is_cpp_instruction *)*/
499 %token <((int * int) option ref * Ast_c.info)>
500 TIfdef TIfdefelse TIfdefelif TEndif
501 %token <(bool * (int * int) option ref * Ast_c.info)>
502 TIfdefBool TIfdefMisc TIfdefVersion
504 /*(*---------------*)*/
506 /*(*---------------*)*/
508 %token <Ast_c.info> TUndef
510 %token <Ast_c.info> TCppDirectiveOther
512 /*(*---------------*)*/
514 /*(*---------------*)*/
516 /*(* appear after fix_tokens_cpp, cf also parsing_hacks#hint *)*/
518 %token <(string * Ast_c.info)> TMacroAttr
519 %token <(string * Ast_c.info)> TMacroStmt
520 %token <(string * Ast_c.info)> TMacroIdentBuilder
521 /*(* no need value for the moment *)*/
522 %token <(string * Ast_c.info)> TMacroString
523 %token <(string * Ast_c.info)> TMacroDecl
524 %token <Ast_c.info> TMacroDeclConst
526 %token <(string * Ast_c.info)> TMacroIterator
528 %token <(string * Ast_c.info)> TMacroTop
529 %token <(string * Ast_c.info)> TMacroStructDecl
532 %token <(string * Ast_c.info)> TMacroAttrStorage
535 /*(*---------------*)*/
537 /*(*---------------*)*/
540 /*(* should disappear after parsing_hack *)*/
541 %token <Ast_c.info> TCommentSkipTagStart TCommentSkipTagEnd
544 /*(* appear after parsing_hack *)*/
545 %token <Ast_c.info> TCParEOL
547 %token <Ast_c.info> TAction
550 /*(* TCommentMisc still useful ? obsolete ? *)*/
551 %token <Ast_c.info> TCommentMisc
552 %token <(Token_c.cppcommentkind * Ast_c.info)> TCommentCpp
555 /*(*-----------------------------------------*)*/
556 %token <Ast_c.info> EOF
558 /*(*-----------------------------------------*)*/
560 /*(* must be at the top so that it has the lowest priority *)*/
571 %left TInf TSup TInfEq TSupEq
574 %left TMul TDiv TMod TMin TMax
576 /*(*************************************************************************)*/
577 /*(* Rules type declaration *)*/
578 /*(*************************************************************************)*/
580 %start main celem statement expr type_name
581 %type <Ast_c.program> main
582 %type <Ast_c.toplevel> celem
584 %type <Ast_c.statement> statement
585 %type <Ast_c.expression> expr
586 %type <Ast_c.fullType> type_name
589 /*(*************************************************************************)*/
592 * toplevel (obsolete)
598 * - left part (type_spec, qualif),
599 * - right part (declarator, abstract declarator)
600 * - aux part (parameters)
601 * declaration, storage, initializers
607 * generic workarounds (obrace, cbrace for context setting)
611 /*(*************************************************************************)*/
613 /*(*************************************************************************)*/
615 /*(*************************************************************************)*/
616 /*(* no more used; now that use error recovery *)*/
619 translation_unit EOF { $1 }
624 | translation_unit external_declaration
625 { !LP._lexer_hint.context_stack <- [LP.InTopLevel]; $1 ++ [$2] }
626 | translation_unit Tnamespace TIdent TOBrace translation_unit TCBrace
627 { !LP._lexer_hint.context_stack <- [LP.InTopLevel];
628 $1 ++ [Namespace ($5, [$2; snd $3; $4; $6])] }
631 /*(*************************************************************************)*/
633 /*(*************************************************************************)*/
635 /*(* Why this ? Why not s/ident/TIdent ? cos there is multiple namespaces in C,
636 * so a label can have the same name that a typedef, same for field and tags
637 * hence sometimes the use of ident instead of TIdent.
641 | TypedefIdent { $1 }
648 (* cppext: string concatenation of idents
649 * also cppext: gccext: ##args for variadic macro
654 { RegularName (mk_string_wrap $1) }
655 | ident_extra_cpp { $1 }
659 { RegularName (mk_string_wrap $1) }
661 { RegularName (mk_string_wrap $1) }
662 | ident_extra_cpp { $1 }
665 | TIdent TCppConcatOp identifier_cpp_list
667 CppConcatenatedName (
669 | [] -> raise (Impossible 87)
670 | (x,concatnull)::xs ->
671 assert(null concatnull);
672 (mk_string_wrap $1, [])::(x,[$2])::xs
675 | TCppConcatOp TIdent
676 { CppVariadicName (fst $2, [$1; snd $2]) }
677 | TMacroIdentBuilder TOPar param_define_list TCPar
678 { CppIdentBuilder ((fst $1, [snd $1;$2;$4]), $3) }
681 | TIdent { [mk_string_wrap $1, []] }
682 | identifier_cpp_list TCppConcatOp TIdent { $1 ++ [mk_string_wrap $3, [$2]] }
684 /*(*************************************************************************)*/
686 /*(*************************************************************************)*/
690 | expr TComma assign_expr { mk_e (Sequence ($1,$3)) [$2] }
692 /*(* bugfix: in C grammar they put unary_expr, but in fact it must be
693 * cast_expr, otherwise (int * ) xxx = &yy; is not allowed
697 | cast_expr TAssign assign_expr { mk_e(Assignment ($1,fst $2,$3)) [snd $2]}
698 | cast_expr TEq assign_expr { mk_e(Assignment ($1,SimpleAssign,$3)) [$2]}
700 /*(* gccext: allow optional then part hence gcc_opt_expr
701 * bugfix: in C grammar they put TDotDot cond_expr, but in fact it must be
702 * assign_expr, otherwise pnp ? x : x = 0x388 is not allowed
707 | arith_expr TWhy gcc_opt_expr TDotDot assign_expr
708 { mk_e (CondExpr ($1,$3,$5)) [$2;$4] }
713 | arith_expr TMul arith_expr { mk_e(Binary ($1, Arith Mul, $3)) [$2] }
714 | arith_expr TDiv arith_expr { mk_e(Binary ($1, Arith Div, $3)) [$2] }
715 | arith_expr TMin arith_expr { mk_e(Binary ($1, Arith Min, $3)) [$2] }
716 | arith_expr TMax arith_expr { mk_e(Binary ($1, Arith Max, $3)) [$2] }
717 | arith_expr TMod arith_expr { mk_e(Binary ($1, Arith Mod, $3)) [$2] }
718 | arith_expr TPlus arith_expr { mk_e(Binary ($1, Arith Plus, $3)) [$2] }
719 | arith_expr TMinus arith_expr { mk_e(Binary ($1, Arith Minus, $3)) [$2] }
720 | arith_expr TShl arith_expr { mk_e(Binary ($1, Arith DecLeft, $3)) [$2] }
721 | arith_expr TShr arith_expr { mk_e(Binary ($1, Arith DecRight, $3)) [$2] }
722 | arith_expr TInf arith_expr { mk_e(Binary ($1, Logical Inf, $3)) [$2] }
723 | arith_expr TSup arith_expr { mk_e(Binary ($1, Logical Sup, $3)) [$2] }
724 | arith_expr TInfEq arith_expr { mk_e(Binary ($1, Logical InfEq, $3)) [$2] }
725 | arith_expr TSupEq arith_expr { mk_e(Binary ($1, Logical SupEq, $3)) [$2] }
726 | arith_expr TEqEq arith_expr { mk_e(Binary ($1, Logical Eq, $3)) [$2] }
727 | arith_expr TNotEq arith_expr { mk_e(Binary ($1, Logical NotEq, $3)) [$2] }
728 | arith_expr TAnd arith_expr { mk_e(Binary ($1, Arith And, $3)) [$2] }
729 | arith_expr TOr arith_expr { mk_e(Binary ($1, Arith Or, $3)) [$2] }
730 | arith_expr TXor arith_expr { mk_e(Binary ($1, Arith Xor, $3)) [$2] }
731 | arith_expr TAndLog arith_expr { mk_e(Binary ($1, Logical AndLog, $3)) [$2] }
732 | arith_expr TOrLog arith_expr { mk_e(Binary ($1, Logical OrLog, $3)) [$2] }
736 | topar2 type_name tcpar2 cast_expr { mk_e(Cast ($2, $4)) [$1;$3] }
739 | postfix_expr { $1 }
740 | TInc unary_expr { mk_e(Infix ($2, Inc)) [$1] }
741 | TDec unary_expr { mk_e(Infix ($2, Dec)) [$1] }
742 | unary_op cast_expr { mk_e(Unary ($2, fst $1)) [snd $1] }
743 | Tsizeof unary_expr { mk_e(SizeOfExpr ($2)) [$1] }
744 | Tsizeof topar2 type_name tcpar2 { mk_e(SizeOfType ($3)) [$1;$2;$4] }
745 | Tnew new_argument { mk_e(New (None, $2)) [$1] }
746 | Tnew TOPar argument_list_ne TCPar new_argument { mk_e(New (Some $3, $5)) [$1; $2; $4] }
747 | Tdelete cast_expr { mk_e(Delete $2) [$1] }
750 | TIdent TOPar argument_list_ne TCPar
751 { let fn = mk_e(Ident (RegularName (mk_string_wrap $1))) [] in
752 Left (mk_e(FunCall (fn, $3)) [$2;$4]) }
754 { let fn = mk_e(Ident (RegularName (mk_string_wrap $1))) [] in
755 Left(mk_e(FunCall (fn, [])) [$2;$3]) }
756 | TypedefIdent TOPar argument_list_ne TCPar
757 { let fn = mk_e(Ident (RegularName (mk_string_wrap $1))) [] in
758 Left (mk_e(FunCall (fn, $3)) [$2;$4]) }
759 | TypedefIdent TOPar TCPar
760 { let fn = mk_e(Ident (RegularName (mk_string_wrap $1))) [] in
761 Left (mk_e(FunCall (fn, [])) [$2;$3]) }
763 { let ty = addTypeD ($1,nullDecl) in
764 let ((returnType,hasreg), iihasreg) = fixDeclSpecForParam ty in
765 Right (ArgType { p_namei = None; p_type = returnType;
766 p_register = hasreg, iihasreg;
769 | new_argument TOCro expr TCCro
772 Left(e) -> Left(mk_e(ArrayAccess (e, $3)) [$2;$4])
773 | Right(ArgType(ty)) -> (* lots of hacks to make the right type *)
774 let fty = mk_ty (Array (Some $3, ty.Ast_c.p_type)) [$2;$4] in
775 let pty = { ty with p_type = fty } in
777 | _ -> raise (Impossible 88)
781 | TAnd { GetRef, $1 }
783 | TPlus { UnPlus, $1 }
784 | TMinus { UnMinus, $1 }
785 | TTilde { Tilde, $1 }
787 /*(* gccext: have that a lot in old kernel to get address of local label.
788 * cf gcc manual "local labels as values".
790 | TAndLog { GetRefLabel, $1 }
793 | primary_expr { $1 }
794 | postfix_expr TOCro expr TCCro
795 { mk_e(ArrayAccess ($1, $3)) [$2;$4] }
796 | postfix_expr TOPar argument_list_ne TCPar
797 { mk_e(FunCall ($1, $3)) [$2;$4] }
798 | postfix_expr TOPar TCPar { mk_e(FunCall ($1, [])) [$2;$3] }
799 | postfix_expr TDot ident_cpp { mk_e(RecordAccess ($1,$3)) [$2] }
800 | postfix_expr TPtrOp ident_cpp { mk_e(RecordPtAccess ($1,$3)) [$2] }
801 | postfix_expr TInc { mk_e(Postfix ($1, Inc)) [$2] }
802 | postfix_expr TDec { mk_e(Postfix ($1, Dec)) [$2] }
804 /*(* gccext: also called compound literals *)*/
805 | topar2 type_name tcpar2 TOBrace TCBrace
806 { mk_e(Constructor ($2, (InitList [], [$4;$5]))) [$1;$3] }
807 | topar2 type_name tcpar2 TOBrace initialize_list gcc_comma_opt TCBrace
808 { mk_e(Constructor ($2, (InitList (List.rev $5),[$4;$7]++$6))) [$1;$3] }
812 | identifier_cpp { mk_e(Ident ($1)) [] }
814 { let (str,(sign,base)) = fst $1 in
815 mk_e(Constant (Int (str,Si(sign,base)))) [snd $1] }
816 | TFloat { mk_e(Constant (Float (fst $1))) [snd $1] }
817 | TString { mk_e(Constant (String (fst $1))) [snd $1] }
818 | TChar { mk_e(Constant (Char (fst $1))) [snd $1] }
819 | TOPar expr TCPar { mk_e(ParenExpr ($2)) [$1;$3] } /*(* forunparser: *)*/
821 /*(* gccext: cppext: TODO better ast ? *)*/
822 | TMacroString { mk_e(Constant (MultiString [fst $1])) [snd $1] }
823 | string_elem string_list
824 { mk_e(Constant (MultiString ["TODO: MultiString"])) ($1 ++ $2) }
826 /*(* gccext: allow statement as expressions via ({ statement }) *)*/
827 | TOPar compound TCPar { mk_e(StatementExpr ($2)) [$1;$3] }
831 /*(*----------------------------*)*/
833 /*(*----------------------------*)*/
836 /*(* to avoid conflicts have to introduce a _not_empty (ne) version *)*/
838 | assign_expr { Left $1 }
839 | parameter_decl { Right (ArgType $1) }
840 | action_higherordermacro_ne { Right (ArgAction $1) }
844 | assign_expr { Left $1 }
845 | parameter_decl { Right (ArgType $1) }
846 /*(* had conflicts before, but julia fixed them *)*/
847 | action_higherordermacro { Right (ArgAction $1) }
849 action_higherordermacro_ne:
852 then ActMisc [Ast_c.fakeInfo()]
857 action_higherordermacro:
860 then ActMisc [Ast_c.fakeInfo()]
865 /*(*----------------------------*)*/
866 /*(* workarounds *)*/
867 /*(*----------------------------*)*/
869 /*(* would like evalInt $1 but require too much info *)*/
870 const_expr: cond_expr { $1 }
873 topar2: TOPar { et "topar2" (); $1 }
874 tcpar2: TCPar { et "tcpar2" (); $1 (*TODO? et ? sure ? c pas dt plutot ? *) }
878 /*(*************************************************************************)*/
880 /*(*************************************************************************)*/
882 statement: statement2 { mk_st (fst $1) (snd $1) }
885 | labeled { Labeled (fst $1), snd $1 }
886 | compound { Compound (fst $1), snd $1 }
887 | expr_statement { ExprStatement(fst $1), snd $1 }
888 | selection { Selection (fst $1), snd $1 ++ [fakeInfo()] }
889 | iteration { Iteration (fst $1), snd $1 ++ [fakeInfo()] }
890 | jump TPtVirg { Jump (fst $1), snd $1 ++ [$2] }
893 | Tasm TOPar asmbody TCPar TPtVirg { Asm $3, [$1;$2;$4;$5] }
894 | Tasm Tvolatile TOPar asmbody TCPar TPtVirg { Asm $4, [$1;$2;$3;$5;$6] }
897 | TMacroStmt { MacroStmt, [snd $1] }
902 /*(* note that case 1: case 2: i++; would be correctly parsed, but with
903 * a Case (1, (Case (2, i++))) :(
906 | ident_cpp TDotDot sw_stat_or_decl { Label ($1, $3), [$2] }
907 | Tcase const_expr TDotDot sw_stat_or_decl { Case ($2, $4), [$1; $3] }
908 | Tcase const_expr TEllipsis const_expr TDotDot sw_stat_or_decl
909 { CaseRange ($2, $4, $6), [$1;$3;$5] } /*(* gccext: allow range *)*/
910 | Tdefault TDotDot sw_stat_or_decl { Default $3, [$1; $2] }
913 | decl { mk_st (Decl ($1 Ast_c.LocalDecl)) Ast_c.noii }
918 /*(* gccext: allow toto: }
919 * was generating each 30 shift/Reduce conflicts,
920 * mais ca va, ca fait ce qu'il faut.
921 * update: julia fixed the problem by introducing end_labeled
922 * and modifying below stat_or_decl_list
925 { Label ($1, (mk_st (ExprStatement None) Ast_c.noii)), [$2] }
926 | Tcase const_expr TDotDot
927 { Case ($2, (mk_st (ExprStatement None) Ast_c.noii)), [$1;$3] }
929 { Default (mk_st (ExprStatement None) Ast_c.noii), [$1; $2] }
935 compound: tobrace compound2 tcbrace { $2, [$1; $3] }
939 (* cppext: because of cpp, some stuff looks like declaration but are in
940 * fact statement but too hard to figure out, and if parse them as
941 * expression, then we force to have first decls and then exprs, then
942 * will have a parse error. So easier to let mix decl/statement.
943 * Moreover it helps to not make such a difference between decl and
944 * statement for further coccinelle phases to factorize code.
948 | stat_or_decl_list { $1 }
952 | stat_or_decl { [$1] }
953 /*(* gccext: to avoid conflicts, cf end_labeled above *)*/
954 | end_labeled { [StmtElem (mk_st (Labeled (fst $1)) (snd $1))] }
955 /*(* old: conflicts | stat_or_decl_list stat_or_decl { $1 ++ [$2] } *)*/
956 | stat_or_decl stat_or_decl_list { $1 :: $2 }
959 | decl { StmtElem (mk_st (Decl ($1 Ast_c.LocalDecl)) Ast_c.noii) }
960 | statement { StmtElem $1 }
963 | function_definition { StmtElem (mk_st (NestedFunc $1) Ast_c.noii) }
967 { CppDirectiveStmt $1 }
968 | cpp_ifdef_directive/*(* stat_or_decl_list ...*)*/
973 | TPtVirg { None, [$1] }
974 | expr TPtVirg { Some $1, [$2] }
977 | Tif TOPar expr TCPar statement %prec SHIFTHERE
978 { If ($3, $5, (mk_st (ExprStatement None) Ast_c.noii)), [$1;$2;$4] }
979 | Tif TOPar expr TCPar statement Telse statement
980 { If ($3, $5, $7), [$1;$2;$4;$6] }
981 | Tswitch TOPar expr TCPar statement
982 { Switch ($3,$5), [$1;$2;$4] }
985 | Twhile TOPar expr TCPar statement
986 { While ($3,$5), [$1;$2;$4] }
987 | Tdo statement Twhile TOPar expr TCPar TPtVirg
988 { DoWhile ($2,$5), [$1;$3;$4;$6;$7] }
989 | Tfor TOPar expr_statement expr_statement TCPar statement
990 { For (ForExp $3,$4,(None, []),$6), [$1;$2;$5]}
991 | Tfor TOPar expr_statement expr_statement expr TCPar statement
992 { For (ForExp $3,$4,(Some $5, []),$7), [$1;$2;$6] }
993 /*(* c++ext: for(int i = 0; i < n; i++)*)*/
994 | Tfor TOPar decl expr_statement TCPar statement
995 { For (ForDecl ($3 Ast_c.LocalDecl),$4,(None, []),$6), [$1;$2;$5]}
996 | Tfor TOPar decl expr_statement expr TCPar statement
997 { For (ForDecl ($3 Ast_c.LocalDecl),$4,(Some $5, []),$7), [$1;$2;$6] }
999 | TMacroIterator TOPar argument_list_ne TCPar statement
1000 { MacroIteration (fst $1, $3, $5), [snd $1;$2;$4] }
1001 | TMacroIterator TOPar TCPar statement
1002 { MacroIteration (fst $1, [], $4), [snd $1;$2;$3] }
1004 /*(* the ';' in the caller grammar rule will be appended to the infos *)*/
1006 | Tgoto ident_cpp { Goto ($2), [$1] }
1007 | Tcontinue { Continue, [$1] }
1008 | Tbreak { Break, [$1] }
1009 | Treturn { Return, [$1] }
1010 | Treturn expr { ReturnExpr $2, [$1] }
1011 | Tgoto TMul expr { GotoComputed $3, [$1;$2] }
1015 /*(*----------------------------*)*/
1017 /*(*----------------------------*)*/
1019 | TString { [snd $1] }
1020 /*(* cppext: ex= printk (KERN_INFO "xxx" UTS_RELEASE) *)*/
1021 | TMacroString { [snd $1] }
1025 | string_list colon_asm_list { $1, $2 }
1026 | string_list { $1, [] } /*(* in old kernel *)*/
1029 colon_asm: TDotDot colon_option_list { Colon $2, [$1] }
1032 | TString { ColonMisc, [snd $1] }
1033 | TString TOPar asm_expr TCPar { ColonExpr $3, [snd $1; $2;$4] }
1034 /*(* cppext: certainly a macro *)*/
1035 | TOCro identifier TCCro TString TOPar asm_expr TCPar
1036 { ColonExpr $6, [$1;snd $2;$3;snd $4; $5; $7 ] }
1037 | identifier { ColonMisc, [snd $1] }
1038 | /*(* empty *)*/ { ColonMisc, [] }
1040 asm_expr: assign_expr { $1 }
1042 /*(*************************************************************************)*/
1044 /*(*************************************************************************)*/
1047 /*(*-----------------------------------------------------------------------*)*/
1048 /*(* Type spec, left part of a type *)*/
1049 /*(*-----------------------------------------------------------------------*)*/
1051 | Tvoid { Right3 (BaseType Void), [$1] }
1052 | Tchar { Right3 (BaseType (IntType CChar)), [$1]}
1053 | Tint { Right3 (BaseType (IntType (Si (Signed,CInt)))), [$1]}
1054 | Tfloat { Right3 (BaseType (FloatType CFloat)), [$1]}
1055 | Tdouble { Right3 (BaseType (FloatType CDouble)), [$1] }
1056 | Tsize_t { Right3 (BaseType SizeType), [$1] }
1057 | Tssize_t { Right3 (BaseType SSizeType), [$1] }
1058 | Tptrdiff_t { Right3 (BaseType PtrDiffType), [$1] }
1059 | Tshort { Middle3 Short, [$1]}
1060 | Tlong { Middle3 Long, [$1]}
1061 | Tsigned { Left3 Signed, [$1]}
1062 | Tunsigned { Left3 UnSigned, [$1]}
1063 | struct_or_union_spec { Right3 (fst $1), snd $1 }
1064 | enum_spec { Right3 (fst $1), snd $1 }
1067 (* parse_typedef_fix1: cant put: TIdent {} cos it make the grammar
1068 * ambiguous, generates lots of conflicts => we must
1069 * use some tricks: we make the lexer and parser cooperate, cf lexerParser.ml.
1071 * parse_typedef_fix2: this is not enough, and you must use
1072 * parse_typedef_fix2 to fully manage typedef problems in grammar.
1074 * parse_typedef_fix3:
1076 * parse_typedef_fix4: try also to do now some consistency checking in
1080 { let name = RegularName (mk_string_wrap $1) in
1081 Right3 (TypeName (name, Ast_c.noTypedefDef())),[] }
1083 | Ttypeof TOPar assign_expr TCPar { Right3 (TypeOfExpr ($3)), [$1;$2;$4] }
1084 | Ttypeof TOPar type_name TCPar { Right3 (TypeOfType ($3)), [$1;$2;$4] }
1086 /*(*----------------------------*)*/
1087 /*(* workarounds *)*/
1088 /*(*----------------------------*)*/
1090 type_spec: type_spec2 { dt "type" (); $1 }
1092 /*(*-----------------------------------------------------------------------*)*/
1093 /*(* Qualifiers *)*/
1094 /*(*-----------------------------------------------------------------------*)*/
1097 | Tconst { {const=true ; volatile=false}, $1 }
1098 | Tvolatile { {const=false ; volatile=true}, $1 }
1100 | Trestrict { (* TODO *) {const=false ; volatile=false}, $1 }
1103 /*(*-----------------------------------------------------------------------*)*/
1104 /*(* gccext: attributes *)*/
1105 /*(*-----------------------------------------------------------------------*)*/
1108 | Tattribute TOPar /*stuff*/ TCPar { raise Todo }
1110 | TMacroAttr { Attribute (fst $1), [snd $1] }
1113 | TMacroAttrStorage { $1 }
1116 | type_qualif { $1 }
1118 | TMacroAttr { {const=true ; volatile=false}, snd $1 }
1120 /*(*-----------------------------------------------------------------------*)*/
1121 /*(* Declarator, right part of a type + second part of decl (the ident) *)*/
1122 /*(*-----------------------------------------------------------------------*)*/
1125 (* declarator return a couple:
1126 * (name, partial type (a function to be applied to return type))
1128 * when int* f(int) we must return Func(Pointer int,int) and not
1129 * Pointer (Func(int,int)
1133 | pointer direct_d { (fst $2, fun x -> x +> $1 +> (snd $2) ) }
1136 /*(* so must do int * const p; if the pointer is constant, not the pointee *)*/
1138 | tmul { fun x -> mk_ty (Pointer x) [$1] }
1139 | tmul pointer { fun x -> mk_ty (Pointer ($2 x)) [$1] }
1140 | tmul type_qualif_list
1141 { fun x -> ($2.qualifD, mk_tybis (Pointer x) [$1])}
1142 | tmul type_qualif_list pointer
1143 { fun x -> ($2.qualifD, mk_tybis (Pointer ($3 x)) [$1]) }
1148 { if !Flag.c_plus_plus
1151 let i = Ast_c.parse_info_of_info $1 in
1152 raise (Semantic("& not allowed in C types, try -c++ option", i)) }
1157 { ($1, fun x -> x) }
1158 | TOPar declarator TCPar /*(* forunparser: old: $2 *)*/
1159 { (fst $2, fun x -> mk_ty (ParenType ((snd $2) x)) [$1;$3]) }
1160 | direct_d tocro tccro
1161 { (fst $1,fun x->(snd $1) (mk_ty (Array (None,x)) [$2;$3])) }
1162 | direct_d tocro const_expr tccro
1163 { (fst $1,fun x->(snd $1) (mk_ty (Array (Some $3,x)) [$2;$4])) }
1164 | direct_d topar tcpar
1167 (mk_ty (FunctionType (x,(([],(false, []))))) [$2;$3]))
1169 | direct_d topar parameter_type_list tcpar
1170 { (fst $1,fun x->(snd $1)
1171 (mk_ty (FunctionType (x, $3)) [$2;$4]))
1175 /*(*----------------------------*)*/
1176 /*(* workarounds *)*/
1177 /*(*----------------------------*)*/
1179 tocro: TOCro { et "tocro" ();$1 }
1180 tccro: TCCro { dt "tccro" ();$1 }
1182 /*(*-----------------------------------------------------------------------*)*/
1183 abstract_declarator:
1185 | direct_abstract_declarator { $1 }
1186 | pointer direct_abstract_declarator { fun x -> x +> $2 +> $1 }
1188 direct_abstract_declarator:
1189 | TOPar abstract_declarator TCPar /*(* forunparser: old: $2 *)*/
1190 { fun x -> mk_ty (ParenType ($2 x)) [$1;$3] }
1193 { fun x -> mk_ty (Array (None, x)) [$1;$2] }
1194 | TOCro const_expr TCCro
1195 { fun x -> mk_ty (Array (Some $2, x)) [$1;$3] }
1196 | direct_abstract_declarator TOCro TCCro
1197 { fun x -> $1 (mk_ty (Array (None, x)) [$2;$3]) }
1198 | direct_abstract_declarator TOCro const_expr TCCro
1199 { fun x -> $1 (mk_ty (Array (Some $3,x)) [$2;$4]) }
1201 { fun x -> mk_ty (FunctionType (x, ([], (false, [])))) [$1;$2] }
1202 | topar parameter_type_list tcpar
1203 { fun x -> mk_ty (FunctionType (x, $2)) [$1;$3] }
1204 /*(* subtle: here must also use topar, not TOPar, otherwise if have for
1205 * instance (xxx ( * )(xxx)) cast, then the second xxx may still be a Tident
1206 * but we want to reduce topar, to set the InParameter so that
1207 * parsing_hack can get a chance to change the type of xxx into a typedef.
1208 * That's an example where parsing_hack and the lookahead of ocamlyacc does
1209 * not go very well together ... we got the info too late. We got
1210 * a similar pb with xxx xxx; declaration, cf parsing_hack.ml and the
1211 * "disable typedef cos special case ..." message.
1213 | direct_abstract_declarator topar tcpar
1214 { fun x -> $1 (mk_ty (FunctionType (x, (([], (false, []))))) [$2;$3]) }
1215 | direct_abstract_declarator topar parameter_type_list tcpar
1216 { fun x -> $1 (mk_ty (FunctionType (x, $3)) [$2;$4]) }
1218 /*(*-----------------------------------------------------------------------*)*/
1219 /*(* Parameters (use decl_spec not type_spec just for 'register') *)*/
1220 /*(*-----------------------------------------------------------------------*)*/
1221 parameter_type_list:
1222 | parameter_list { ($1, (false, []))}
1223 | parameter_list TComma TEllipsis { ($1, (true, [$2;$3])) }
1228 let name = RegularName (mk_string_wrap $1) in
1229 LP.add_ident (str_of_name name);
1230 { p_namei = Some name;
1231 p_type = mk_ty NoType [];
1232 p_register = (false, []);
1235 | decl_spec declaratorp
1236 { let ((returnType,hasreg),iihasreg) = fixDeclSpecForParam $1 in
1237 let (name, ftyp) = $2 in
1238 { p_namei = Some (name);
1239 p_type = ftyp returnType;
1240 p_register = (hasreg, iihasreg);
1243 | decl_spec abstract_declaratorp
1244 { let ((returnType,hasreg), iihasreg) = fixDeclSpecForParam $1 in
1246 p_type = $2 returnType;
1247 p_register = hasreg, iihasreg;
1251 { let ((returnType,hasreg), iihasreg) = fixDeclSpecForParam $1 in
1253 p_type = returnType;
1254 p_register = hasreg, iihasreg;
1259 /*(*----------------------------*)*/
1260 /*(* workarounds *)*/
1261 /*(*----------------------------*)*/
1263 parameter_decl: parameter_decl2 { et "param" (); $1 }
1264 | attributes parameter_decl2 { et "param" (); $2 }
1267 | declarator { LP.add_ident (str_of_name (fst $1)); $1 }
1269 | attributes declarator { LP.add_ident (str_of_name (fst $2)); $2 }
1270 | declarator attributes { LP.add_ident (str_of_name (fst $1)); $1 }
1272 abstract_declaratorp:
1273 | abstract_declarator { $1 }
1275 | attributes abstract_declarator { $2 }
1277 /*(*-----------------------------------------------------------------------*)*/
1278 /*(* helper type rules *)*/
1279 /*(*-----------------------------------------------------------------------*)*/
1281 /*(* for struct and also typename *)*/
1282 /*(* cant put decl_spec cos no storage is allowed for field struct *)*/
1284 | type_spec { addTypeD ($1, nullDecl) }
1285 | type_qualif { {nullDecl with qualifD = (fst $1,[snd $1])}}
1286 | type_spec spec_qualif_list { addTypeD ($1,$2) }
1287 | type_qualif spec_qualif_list { addQualifD ($1,$2) }
1289 spec_qualif_list: spec_qualif_list2 { dt "spec_qualif" (); $1 }
1292 /*(* for pointers in direct_declarator and abstract_declarator *)*/
1294 | type_qualif_attr { {nullDecl with qualifD = (fst $1,[snd $1])} }
1295 | type_qualif_list type_qualif_attr { addQualifD ($2,$1) }
1302 /*(*-----------------------------------------------------------------------*)*/
1303 /*(* xxx_type_id *)*/
1304 /*(*-----------------------------------------------------------------------*)*/
1308 { let (returnType, _) = fixDeclSpecForDecl $1 in returnType }
1309 | spec_qualif_list abstract_declaratort
1310 { let (returnType, _) = fixDeclSpecForDecl $1 in $2 returnType }
1314 abstract_declaratort:
1315 | abstract_declarator { $1 }
1317 | attributes abstract_declarator { $2 }
1320 /*(*************************************************************************)*/
1321 /*(* declaration and initializers *)*/
1322 /*(*************************************************************************)*/
1327 let (returnType,storage) = fixDeclSpecForDecl $1 in
1328 let iistart = Ast_c.fakeInfo () in
1329 DeclList ([{v_namei = None; v_type = returnType;
1330 v_storage = unwrap storage; v_local = local;
1331 v_attr = Ast_c.noattr;
1332 v_type_bis = ref None;
1334 ($2::iistart::snd storage))
1336 | decl_spec init_declarator_list TPtVirg
1338 let (returnType,storage) = fixDeclSpecForDecl $1 in
1339 let iistart = Ast_c.fakeInfo () in
1341 ($2 +> List.map (fun ((((name,f),attrs), ini), iivirg) ->
1342 let s = str_of_name name in
1343 if fst (unwrap storage) =*= StoTypedef
1344 then LP.add_typedef s;
1345 {v_namei = Some (name, ini);
1346 v_type = f returnType;
1347 v_storage = unwrap storage;
1350 v_type_bis = ref None;
1354 ), ($3::iistart::snd storage))
1358 | TMacroDecl TOPar argument_list TCPar TPtVirg
1360 MacroDecl ((fst $1, $3, true), [snd $1;$2;$4;$5;fakeInfo()]) }
1361 | Tstatic TMacroDecl TOPar argument_list TCPar TPtVirg
1363 MacroDecl ((fst $2, $4, true), [snd $2;$3;$5;$6;fakeInfo();$1]) }
1364 | Tstatic TMacroDeclConst TMacroDecl TOPar argument_list TCPar TPtVirg
1366 MacroDecl ((fst $3, $5, true), [snd $3;$4;$6;$7;fakeInfo();$1;$2])}
1369 | TMacroDecl TOPar argument_list TCPar teq initialize TPtVirg
1371 MacroDeclInit ((fst $1, $3, $6), [snd $1;$2;$4;$5;$7;fakeInfo()]) }
1372 | Tstatic TMacroDecl TOPar argument_list TCPar teq initialize TPtVirg
1374 MacroDeclInit ((fst $2, $4, $7),[snd $2;$3;$5;$6;$8;fakeInfo();$1]) }
1375 | Tstatic TMacroDeclConst TMacroDecl TOPar argument_list TCPar
1376 teq initialize TPtVirg
1379 ((fst $3, $5, $8), [snd $3;$4;$6;$7;$9;fakeInfo();$1;$2])}
1382 /*(*-----------------------------------------------------------------------*)*/
1384 | storage_class_spec { {nullDecl with storageD = (fst $1, [snd $1]) } }
1385 | type_spec { addTypeD ($1,nullDecl) }
1386 | type_qualif { {nullDecl with qualifD = (fst $1, [snd $1]) } }
1387 | Tinline { {nullDecl with inlineD = (true, [$1]) } }
1388 | storage_class_spec decl_spec2 { addStorageD ($1, $2) }
1389 | type_spec decl_spec2 { addTypeD ($1, $2) }
1390 | type_qualif decl_spec2 { addQualifD ($1, $2) }
1391 | Tinline decl_spec2 { addInlineD ((true, $1), $2) }
1393 /*(* can simplify by putting all in _opt ? must have at least one otherwise
1394 * decl_list is ambiguous ? (no cos have ';' between decl)
1398 storage_class_spec2:
1399 | Tstatic { Sto Static, $1 }
1400 | Textern { Sto Extern, $1 }
1401 | Tauto { Sto Auto, $1 }
1402 | Tregister { Sto Register,$1 }
1403 | Ttypedef { StoTypedef, $1 }
1407 | storage_class_spec2 { $1 }
1408 | storage_class_spec2 attribute_storage_list { $1 (* TODO *) }
1412 /*(*----------------------------*)*/
1413 /*(* workarounds *)*/
1414 /*(*----------------------------*)*/
1416 decl: decl2 { et "decl" (); $1 }
1417 decl_spec: decl_spec2 { dt "declspec" (); $1 }
1419 /*(*-----------------------------------------------------------------------*)*/
1420 /*(* declarators (right part of type and variable) *)*/
1421 /*(*-----------------------------------------------------------------------*)*/
1423 | declaratori { ($1, NoInit) }
1424 | declaratori teq initialize { ($1, ValInit($2, $3)) }
1426 | declaratori TOParCplusplusInit argument_list TCPar
1427 { ($1, ConstrInit($3,[$2;$4])) }
1430 /*(*----------------------------*)*/
1431 /*(* workarounds *)*/
1432 /*(*----------------------------*)*/
1433 teq: TEq { et "teq" (); $1 }
1435 init_declarator: init_declarator2 { dt "init" (); $1 }
1438 /*(*----------------------------*)*/
1440 /*(*----------------------------*)*/
1443 | declarator { LP.add_ident (str_of_name (fst $1)); $1, Ast_c.noattr }
1445 | declarator gcc_asm_decl { LP.add_ident (str_of_name (fst $1)); $1, Ast_c.noattr }
1447 | attributes declarator { LP.add_ident (str_of_name (fst $2)); $2, $1 }
1448 | declarator attributes { LP.add_ident (str_of_name (fst $1)); $1, Ast_c.noattr (* TODO *) }
1453 | Tasm TOPar asmbody TCPar { }
1454 | Tasm Tvolatile TOPar asmbody TCPar { }
1457 /*(*-----------------------------------------------------------------------*)*/
1461 | tobrace_ini initialize_list gcc_comma_opt_struct tcbrace_ini
1462 { InitList (List.rev $2), [$1;$4]++$3 }
1463 | tobrace_ini tcbrace_ini
1464 { InitList [], [$1;$2] } /*(* gccext: *)*/
1468 (* opti: This time we use the weird order of non-terminal which requires in
1469 * the "caller" to do a List.rev cos quite critical. With this weird order it
1470 * allows yacc to use a constant stack space instead of exploding if we would
1471 * do a 'initialize2 Tcomma initialize_list'.
1475 | initialize2 { [$1, []] }
1476 | initialize_list TComma initialize2 { ($3, [$2])::$1 }
1479 /*(* gccext: condexpr and no assign_expr cos can have ambiguity with comma *)*/
1483 | tobrace_ini initialize_list gcc_comma_opt_struct tcbrace_ini
1484 { InitList (List.rev $2), [$1;$4]++$3 }
1485 | tobrace_ini tcbrace_ini
1486 { InitList [], [$1;$2] }
1488 /*(* gccext: labeled elements, a.k.a designators *)*/
1489 | designator_list TEq initialize2
1490 { InitDesignators ($1, $3), [$2] }
1492 /*(* gccext: old format *)*/
1493 | ident TDotDot initialize2
1494 { InitFieldOld (fst $1, $3), [snd $1; $2] } /*(* in old kernel *)*/
1496 | TOCro const_expr TCCro initialize2
1497 { InitIndexOld ($2, $4), [$1;$3] }
1502 /*(* they can be nested, can have a .x[3].y *)*/
1505 { DesignatorField (fst $2), [$1;snd $2] }
1506 | TOCro const_expr TCCro
1507 { DesignatorIndex ($2), [$1;$3] }
1508 | TOCro const_expr TEllipsis const_expr TCCro
1509 { DesignatorRange ($2, $4), [$1;$3;$5] }
1512 /*(*----------------------------*)*/
1513 /*(* workarounds *)*/
1514 /*(*----------------------------*)*/
1516 gcc_comma_opt_struct:
1518 | /*(* empty *)*/ { [Ast_c.fakeInfo() +> Ast_c.rewrap_str ","] }
1527 /*(*************************************************************************)*/
1529 /*(*************************************************************************)*/
1532 | struct_or_union ident tobrace_struct struct_decl_list_gcc tcbrace_struct
1533 { StructUnion (fst $1, Some (fst $2), $4), [snd $1;snd $2;$3;$5] }
1534 | struct_or_union tobrace_struct struct_decl_list_gcc tcbrace_struct
1535 { StructUnion (fst $1, None, $3), [snd $1;$2;$4] }
1536 | struct_or_union ident
1537 { StructUnionName (fst $1, fst $2), [snd $1;snd $2] }
1540 | Tstruct { Struct, $1 }
1541 | Tunion { Union, $1 }
1543 | Tstruct attributes { Struct, $1 (* TODO *) }
1544 | Tunion attributes { Union, $1 (* TODO *) }
1549 | field_declaration { DeclarationField $1 }
1550 | TPtVirg { EmptyField $1 }
1552 /*(* no conflict ? no need for a TMacroStruct ? apparently not as at struct
1553 * the rule are slightly different.
1555 | identifier TOPar argument_list TCPar TPtVirg
1556 { MacroDeclField ((fst $1, $3), [snd $1;$2;$4;$5;fakeInfo()]) }
1560 { CppDirectiveStruct $1 }
1561 | cpp_ifdef_directive/*(* struct_decl_list ... *)*/
1566 | spec_qualif_list struct_declarator_list TPtVirg
1568 let (returnType,storage) = fixDeclSpecForDecl $1 in
1569 if fst (unwrap storage) <> NoSto
1570 then internal_error "parsing dont allow this";
1572 FieldDeclList ($2 +> (List.map (fun (f, iivirg) ->
1573 f returnType, iivirg))
1575 (* dont need to check if typedef or func initialised cos
1576 * grammar dont allow typedef nor initialiser in struct
1580 | spec_qualif_list TPtVirg
1582 (* gccext: allow empty elements if it is a structdef or enumdef *)
1583 let (returnType,storage) = fixDeclSpecForDecl $1 in
1584 if fst (unwrap storage) <> NoSto
1585 then internal_error "parsing dont allow this";
1587 FieldDeclList ([(Simple (None, returnType)) , []], [$2])
1596 { (fun x -> Simple (Some (fst $1), (snd $1) x)) }
1597 | dotdot const_expr2
1598 { (fun x -> BitField (None, x, $1, $2)) }
1599 | declaratorsd dotdot const_expr2
1600 { (fun x -> BitField (Some (fst $1), ((snd $1) x), $2, $3)) }
1603 /*(*----------------------------*)*/
1604 /*(* workarounds *)*/
1605 /*(*----------------------------*)*/
1607 | declarator { (*also ? LP.add_ident (fst (fst $1)); *) $1 }
1609 | attributes declarator { $2 }
1610 | declarator attributes { $1 }
1615 struct_or_union_spec: s_or_u_spec2 { dt "su" (); $1 }
1616 struct_or_union: struct_or_union2 { et "su" (); $1 }
1617 struct_decl: struct_decl2 { et "struct" (); $1 }
1619 dotdot: TDotDot { et "dotdot" (); $1 }
1620 const_expr2: const_expr { dt "const_expr2" (); $1 }
1622 struct_decl_list_gcc:
1623 | struct_decl_list { $1 }
1624 | /*(* empty *)*/ { [] } /*(* gccext: allow empty struct *)*/
1627 /*(*************************************************************************)*/
1629 /*(*************************************************************************)*/
1631 | Tenum tobrace_enum enumerator_list gcc_comma_opt_struct tcbrace_enum
1632 { Enum (None, $3), [$1;$2;$5] ++ $4 }
1633 | Tenum ident tobrace_enum enumerator_list gcc_comma_opt_struct tcbrace_enum
1634 { Enum (Some (fst $2), $4), [$1; snd $2; $3;$6] ++ $5 }
1636 { EnumName (fst $2), [$1; snd $2] }
1639 | idente { $1, None }
1640 | idente TEq const_expr { $1, Some ($2, $3) }
1643 /*(*----------------------------*)*/
1644 /*(* workarounds *)*/
1645 /*(*----------------------------*)*/
1647 idente: ident_cpp { LP.add_ident (str_of_name $1); $1 }
1651 /*(*************************************************************************)*/
1653 /*(*************************************************************************)*/
1654 function_definition: function_def { fixFunc $1 }
1657 | decl { [$1 Ast_c.LocalDecl] }
1658 | decl_list decl { $1 ++ [$2 Ast_c.LocalDecl] }
1660 /* hack : to drop when a better solution is found */
1663 | cpp_directive_list cpp_directive { }
1666 | start_fun compound { LP.del_scope(); ($1, $2, None) }
1667 | start_fun cpp_directive_list compound { LP.del_scope(); ($1, $3, None) }
1668 | start_fun decl_list compound {
1669 (* TODO: undo the typedef added ? *)
1674 start_fun: start_fun2
1676 fix_add_params_ident $1;
1677 (* toreput? !LP._lexer_hint.toplevel <- false; *)
1681 start_fun2: decl_spec declaratorfd
1682 { let (returnType,storage) = fixDeclSpecForFuncDef $1 in
1683 let (id, attrs) = $2 in
1684 (fst id, fixOldCDecl ((snd id) returnType) , storage, attrs)
1689 | Tconstructorname topar tcpar {
1690 let id = RegularName (mk_string_wrap $1) in
1691 let ret = mk_ty NoType [] in
1692 let ty = mk_ty (FunctionType (ret, (([], (false, []))))) [$2;$3] in
1693 let storage = ((NoSto,false),[]) in
1695 (id, ty, storage, attrs) }
1696 | Tconstructorname topar parameter_type_list tcpar {
1697 let id = RegularName (mk_string_wrap $1) in
1698 let ret = mk_ty NoType [] in
1699 let ty = mk_ty (FunctionType (ret, $3)) [$2;$4] in
1700 let storage = ((NoSto,false),[]) in
1702 (id, ty, storage, attrs) }
1704 /*(*----------------------------*)*/
1705 /*(* workarounds *)*/
1706 /*(*----------------------------*)*/
1708 /* It would be very nice if we could make declarator aware that this is
1709 coming from a function definition. Then on the ( and ) cases, it could
1710 set the state to something other than InParameter. Then the case
1711 (TIdent (s, i1)::(TComma _|TCPar _)::_ , (TComma _ |TOPar _)::_ )
1712 in parsing_hacks.ml would not have to consider K&R variable declarations
1713 as typedefs. Unfortunately, doing something about this problem seems to
1714 introduce conflicts in the parser. */
1717 | declarator { et "declaratorfd" (); $1, Ast_c.noattr }
1719 | attributes declarator { et "declaratorfd" (); $2, $1 }
1720 | declarator attributes { et "declaratorfd" (); $1, Ast_c.noattr }
1724 /*(*************************************************************************)*/
1725 /*(* cpp directives *)*/
1726 /*(*************************************************************************)*/
1729 | TIncludeStart TIncludeFilename
1731 let (i1, in_ifdef) = $1 in
1734 (* redo some lexing work :( *)
1737 | _ when s =~ "^\"\\(.*\\)\"$" ->
1738 Local (Common.split "/" (matched1 s))
1739 | _ when s =~ "^\\<\\(.*\\)\\>$" ->
1740 NonLocal (Common.split "/" (matched1 s))
1744 Include { i_include = (inc_file, [i1;i2]);
1745 i_rel_pos = Ast_c.noRelPos();
1746 i_is_in_ifdef = !in_ifdef;
1747 i_content = Ast_c.noi_content;
1751 | TDefine TIdentDefine define_val TDefEOL
1752 { Define ((fst $2, [$1; snd $2;$4]), (DefineVar, $3)) }
1755 (* The TOParDefine is introduced to avoid ambiguity with previous rules.
1756 * A TOParDefine is a TOPar that was just next to the ident.
1758 | TDefine TIdentDefine TOParDefine param_define_list TCPar define_val TDefEOL
1760 ((fst $2, [$1; snd $2; $7]),
1761 (DefineFunc ($4, [$3;$5]), $6))
1764 | TUndef TIdentDefine TDefEOL
1765 { Define((fst $2, [$1; snd $2; $3]), (Undef,DefineEmpty)) }
1766 | TCppDirectiveOther { PragmaAndCo ([$1]) }
1772 /*(* perhaps better to use assign_expr ? but in that case need
1773 * do a assign_expr_of_string in parse_c
1776 | expr { DefineExpr $1 }
1777 | statement { DefineStmt $1 }
1778 | decl { DefineStmt (mk_st (Decl ($1 Ast_c.NotLocalDecl)) Ast_c.noii) }
1781 * | TypedefIdent { DefineType (nQ,(TypeName(fst $1,noTypedefDef()),[snd $1]))}
1783 * | spec_qualif_list TMul
1784 * { let (returnType, _) = fixDeclSpecForDecl $1 in DefineType returnType }
1788 { let returnType = fixDeclSpecForMacro $1 in
1789 DefineType returnType
1791 | decl_spec abstract_declarator
1792 { let returnType = fixDeclSpecForMacro $1 in
1793 let typ = $2 returnType in
1797 /*(* can be in conflict with decl_spec, maybe change fixDeclSpecForMacro
1798 * to also allow storage ?
1799 | storage_class_spec { DefineTodo }
1800 | Tinline { DefineTodo }
1803 | stat_or_decl stat_or_decl_list
1808 | _ -> failwith "unexpected statement for DefineMulti")
1811 | statement statement { DefineTodo }
1812 | decl function_definition { DefineTodo }
1818 | function_definition { DefineFunction $1 }
1820 | TOBraceDefineInit initialize_list gcc_comma_opt_struct TCBrace comma_opt
1821 { DefineInit (InitList (List.rev $2), [$1;$4]++$3++$5) }
1823 /*(* note: had a conflict before when were putting TInt instead of expr *)*/
1824 | Tdo statement Twhile TOPar expr TCPar
1828 then pr2 "WEIRD: in macro and have not a while(0)";
1830 DefineDoWhileZero (($2,$5), [$1;$3;$4;$6])
1833 | Tasm TOPar asmbody TCPar { DefineTodo }
1834 | Tasm Tvolatile TOPar asmbody TCPar { DefineTodo }
1836 /*(* aliases macro *)*/
1837 | TMacroAttr { DefineTodo }
1839 | /*(* empty *)*/ { DefineEmpty }
1845 | TIdent { mk_string_wrap $1 }
1846 | TypedefIdent { mk_string_wrap $1 }
1847 | TDefParamVariadic { mk_string_wrap $1 }
1848 | TEllipsis { "...", [$1] }
1849 /*(* they reuse keywords :( *)*/
1850 | Tregister { "register", [$1] }
1855 cpp_ifdef_directive:
1857 { let (tag,ii) = $1 in
1858 IfdefDirective ((Ifdef, IfdefTag (Common.some !tag)), [ii]) }
1860 { let (tag,ii) = $1 in
1861 IfdefDirective ((IfdefElse, IfdefTag (Common.some !tag)), [ii]) }
1863 { let (tag,ii) = $1 in
1864 IfdefDirective ((IfdefElseif, IfdefTag (Common.some !tag)), [ii]) }
1866 { let (tag,ii) = $1 in
1867 IfdefDirective ((IfdefEndif, IfdefTag (Common.some !tag)), [ii]) }
1870 { let (_b, tag,ii) = $1 in
1871 IfdefDirective ((Ifdef, IfdefTag (Common.some !tag)), [ii]) }
1873 { let (_b, tag,ii) = $1 in
1874 IfdefDirective ((Ifdef, IfdefTag (Common.some !tag)), [ii]) }
1876 { let (_b, tag,ii) = $1 in
1877 IfdefDirective ((Ifdef, IfdefTag (Common.some !tag)), [ii]) }
1882 /*(* no conflict ? no need for a TMacroTop ? apparently not as at toplevel
1883 * the rule are slightly different, they cant be statement and so expr
1884 * at the top, only decl or function definition.
1886 | identifier TOPar argument_list TCPar TPtVirg
1888 Declaration(MacroDecl((fst $1, $3, true), [snd $1;$2;$4;$5;fakeInfo()]))
1889 (* old: MacroTop (fst $1, $3, [snd $1;$2;$4;$5]) *)
1892 /*(* TCParEOL to fix the end-of-stream bug of ocamlyacc *)*/
1893 | identifier TOPar argument_list TCParEOL
1894 { Declaration (MacroDecl ((fst $1, $3, false), [snd $1;$2;$4;fakeInfo()])) }
1896 /*(* ex: EXPORT_NO_SYMBOLS; *)*/
1897 | identifier TPtVirg { EmptyDef [snd $1;$2] }
1901 /*(*************************************************************************)*/
1903 /*(*************************************************************************)*/
1905 external_declaration:
1906 | function_definition { Definition $1 }
1907 | decl { Declaration ($1 Ast_c.NotLocalDecl) }
1911 | Tnamespace TIdent TOBrace translation_unit TCBrace
1912 { !LP._lexer_hint.context_stack <- [LP.InTopLevel];
1913 Namespace ($4, [$1; snd $2; $3; $5]) }
1915 | external_declaration { $1 }
1922 | cpp_ifdef_directive /* (*external_declaration_list ...*)*/
1925 /*(* can have asm declaration at toplevel *)*/
1926 | Tasm TOPar asmbody TCPar TPtVirg { EmptyDef [$1;$2;$4;$5] }
1929 (* in ~/kernels/src/linux-2.5.2/drivers/isdn/hisax/isdnl3.c sometimes
1930 * the function ends with }; instead of just }
1931 * can also remove this rule and report "parse error" pb to morton
1933 | TPtVirg { EmptyDef [$1] }
1936 | EOF { FinalDef $1 }
1941 /*(*************************************************************************)*/
1942 /*(* some generic workarounds *)*/
1943 /*(*************************************************************************)*/
1945 tobrace: TOBrace { LP.push_context LP.InFunction; LP.new_scope (); $1 }
1946 tcbrace: TCBrace { LP.pop_context(); LP.del_scope (); $1 }
1948 tobrace_enum: TOBrace { LP.push_context LP.InEnum; $1 }
1949 tcbrace_enum: TCBrace { LP.pop_context (); $1 }
1951 tobrace_ini: TOBrace { LP.push_context LP.InInitializer; $1 }
1952 tcbrace_ini: TCBrace { LP.pop_context (); $1 }
1954 tobrace_struct: TOBrace { LP.push_context LP.InStruct; $1}
1955 tcbrace_struct: TCBrace { LP.pop_context (); $1 }
1961 { LP.new_scope ();et "topar" ();
1962 LP.push_context LP.InParameter;
1966 { LP.del_scope ();dt "tcpar" ();
1974 /*(*************************************************************************)*/
1975 /*(* xxx_list, xxx_opt *)*/
1976 /*(*************************************************************************)*/
1982 | statement_list { ([], $1) }
1983 | decl_list { ($1, []) }
1984 | decl_list statement_list { ($1,$2) }
1986 statement_list: stat_or_decl_list { $1 }
1993 | decl_list decl { $1 ++ [$2] }
1996 | statement { [$1] }
1997 | statement_list statement { $1 ++ [$2] }
2005 | string_elem { $1 }
2006 | string_list string_elem { $1 ++ $2 }
2009 | colon_asm { [$1] }
2010 | colon_asm_list colon_asm { $1 ++ [$2] }
2013 | colon_option { [$1, []] }
2014 | colon_option_list TComma colon_option { $1 ++ [$3, [$2]] }
2018 | argument_ne { [$1, []] }
2019 | argument_list_ne TComma argument { $1 ++ [$3, [$2]] }
2022 | argument { [$1, []] }
2023 | argument_list TComma argument { $1 ++ [$3, [$2]] }
2027 | assign_expr { [$1, []] }
2028 | expression_list TComma assign_expr { $1 ++ [$3, [$2]] }
2033 | struct_decl { [$1] }
2034 | struct_decl_list struct_decl { $1 ++ [$2] }
2037 struct_declarator_list:
2038 | struct_declarator { [$1, []] }
2039 | struct_declarator_list TComma struct_declarator { $1 ++ [$3, [$2]] }
2043 | enumerator { [$1, []] }
2044 | enumerator_list TComma enumerator { $1 ++ [$3, [$2]] }
2047 init_declarator_list:
2048 | init_declarator { [$1, []] }
2049 | init_declarator_list TComma init_declarator { $1 ++ [$3, [$2]] }
2053 | parameter_decl { [$1, []] }
2054 | parameter_list TComma parameter_decl { $1 ++ [$3, [$2]] }
2058 | TAction taction_list_ne { $1 :: $2 }
2061 /*old: was generating conflict, hence now taction_list_ne
2062 | (* empty *) { [] }
2064 | taction_list TAction { $1 ++ [$2] }
2067 | TAction taction_list { $1 :: $2 }
2070 | /*(* empty *)*/ { [] }
2071 | param_define { [$1, []] }
2072 | param_define_list TComma param_define { $1 ++ [$3, [$2]] }
2075 | designator { [$1] }
2076 | designator_list designator { $1 ++ [$2] }
2079 | attribute { [$1] }
2080 | attribute_list attribute { $1 ++ [$2] }
2082 attribute_storage_list:
2083 | attribute_storage { [$1] }
2084 | attribute_storage_list attribute_storage { $1 ++ [$2] }
2087 attributes: attribute_list { $1 }
2091 /*(* gccext: which allow a trailing ',' in enum, as in perl *)*/
2094 | /*(* empty *)*/ { [] }
2098 | /*(* empty *)*/ { [] }
2108 | /*(* empty *)*/ { None }