Release coccinelle-0.2.3rc1
[bpt/coccinelle.git] / parsing_c / parser_c.mly
CommitLineData
34e49164 1%{
0708f913 2(* Yoann Padioleau
ae4735db 3 *
b1b2de81 4 * Copyright (C) 2002, 2006, 2007, 2008, 2009 Yoann Padioleau
34e49164
C
5 *
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.
ae4735db 9 *
34e49164
C
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.
14 *)
15open Common
16
17open Ast_c
18
19module LP = Lexer_parser
20open Lexer_parser (* for the fields *)
21
22open Semantic_c (* Semantic exn *)
23
24
25(*****************************************************************************)
26(* Wrappers *)
27(*****************************************************************************)
ae4735db
C
28let warning s v =
29 if !Flag_parsing_c.verbose_parsing
34e49164
C
30 then Common.warning ("PARSING: " ^ s) v
31 else v
32
ae4735db 33let pr2, pr2_once = Common.mk_pr2_wrappers Flag_parsing_c.verbose_parsing
34e49164
C
34
35(*****************************************************************************)
36(* Parse helpers functions *)
37(*****************************************************************************)
38
39(*-------------------------------------------------------------------------- *)
40(* Type related *)
41(*-------------------------------------------------------------------------- *)
42
43type shortLong = Short | Long | LongLong
44
ae4735db 45type decl = {
34e49164
C
46 storageD: storagebis wrap;
47 typeD: ((sign option) * (shortLong option) * (typeCbis option)) wrap;
48 qualifD: typeQualifierbis wrap;
49 inlineD: bool 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 *)
ae4735db 53}
34e49164
C
54
55let nullDecl = {
56 storageD = NoSto, [];
57 typeD = (None, None, None), [];
58 qualifD = nullQualif;
59 inlineD = false, [];
60}
61let fake_pi = Common.fake_parse_info
62
ae4735db 63let addStorageD = function
34e49164 64 | ((x,ii), ({storageD = (NoSto,[])} as v)) -> { v with storageD = (x, [ii]) }
ae4735db 65 | ((x,ii), ({storageD = (y, ii2)} as v)) ->
b1b2de81 66 if x =*= y then warning "duplicate storage classes" v
34e49164
C
67 else raise (Semantic ("multiple storage classes", fake_pi))
68
ae4735db 69let addInlineD = function
34e49164
C
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
73
74
ae4735db
C
75let addTypeD = function
76 | ((Left3 Signed,ii) ,({typeD = ((Some Signed, b,c),ii2)} as v)) ->
34e49164 77 warning "duplicate 'signed'" v
ae4735db 78 | ((Left3 UnSigned,ii) ,({typeD = ((Some UnSigned,b,c),ii2)} as v)) ->
34e49164 79 warning "duplicate 'unsigned'" v
ae4735db 80 | ((Left3 _,ii), ({typeD = ((Some _,b,c),ii2)} as _v)) ->
34e49164 81 raise (Semantic ("both signed and unsigned specified", fake_pi))
ae4735db 82 | ((Left3 x,ii), ({typeD = ((None,b,c),ii2)} as v)) ->
34e49164
C
83 {v with typeD = (Some x,b,c),ii ++ ii2}
84
ae4735db 85 | ((Middle3 Short,ii), ({typeD = ((a,Some Short,c),ii2)} as v)) ->
34e49164
C
86 warning "duplicate 'short'" v
87
ae4735db 88
34e49164 89 (* gccext: long long allowed *)
ae4735db 90 | ((Middle3 Long,ii), ({typeD = ((a,Some Long ,c),ii2)} as v)) ->
34e49164 91 { v with typeD = (a, Some LongLong, c),ii++ii2 }
ae4735db 92 | ((Middle3 Long,ii), ({typeD = ((a,Some LongLong ,c),ii2)} as v)) ->
34e49164
C
93 warning "triplicate 'long'" v
94
485bce71 95
ae4735db 96 | ((Middle3 _,ii), ({typeD = ((a,Some _,c),ii2)} as _v)) ->
34e49164 97 raise (Semantic ("both long and short specified", fake_pi))
ae4735db 98 | ((Middle3 x,ii), ({typeD = ((a,None,c),ii2)} as v)) ->
34e49164
C
99 {v with typeD = (a, Some x,c),ii++ii2}
100
ae4735db 101 | ((Right3 t,ii), ({typeD = ((a,b,Some _),ii2)} as _v)) ->
34e49164 102 raise (Semantic ("two or more data types", fake_pi))
ae4735db 103 | ((Right3 t,ii), ({typeD = ((a,b,None),ii2)} as v)) ->
34e49164
C
104 {v with typeD = (a,b, Some t),ii++ii2}
105
106
107let 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}
ae4735db 112 | _ ->
91eba41f 113 internal_error "there is no noconst or novolatile keyword"
34e49164
C
114
115let addQualifD ((qu,ii), ({qualifD = (v,ii2)} as x)) =
116 { x with qualifD = (addQualif (qu, v),ii::ii2) }
117
118
119(*-------------------------------------------------------------------------- *)
120(* Declaration/Function related *)
121(*-------------------------------------------------------------------------- *)
122
123
124(* stdC: type section, basic integer types (and ritchie)
ae4735db 125 * To understand the code, just look at the result (right part of the PM)
34e49164
C
126 * and go back.
127 *)
128let (fixDeclSpecForDecl: decl -> (fullType * (storage wrap))) = function
ae4735db
C
129 {storageD = (st,iist);
130 qualifD = (qu,iiq);
131 typeD = (ty,iit);
34e49164 132 inlineD = (inline,iinl);
ae4735db
C
133 } ->
134 let ty',iit' =
135 (match ty with
136 | (None,None,None) ->
137 (* generate fake_info, otherwise type_annotater can crash in
91eba41f
C
138 * offset.
139 *)
140 warning "type defaults to 'int'" (defaultInt, [fakeInfo fake_pi])
34e49164 141 | (None, None, Some t) -> (t, iit)
ae4735db
C
142
143 | (Some sign, None, (None| Some (BaseType (IntType (Si (_,CInt)))))) ->
34e49164 144 BaseType(IntType (Si (sign, CInt))), iit
ae4735db 145 | ((None|Some Signed),Some x,(None|Some(BaseType(IntType (Si (_,CInt)))))) ->
34e49164 146 BaseType(IntType (Si (Signed, [Short,CShort; Long, CLong; LongLong, CLongLong] +> List.assoc x))), iit
ae4735db 147 | (Some UnSigned, Some x, (None| Some (BaseType (IntType (Si (_,CInt))))))->
34e49164 148 BaseType(IntType (Si (UnSigned, [Short,CShort; Long, CLong; LongLong, CLongLong] +> List.assoc x))), iit
708f4980
C
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
34e49164 153
ae4735db 154 | (Some _,_, Some _) ->
34e49164
C
155 (*mine*)
156 raise (Semantic ("signed, unsigned valid only for char and int", fake_pi))
ae4735db 157 | (_,Some _,(Some(BaseType(FloatType (CFloat|CLongDouble))))) ->
34e49164
C
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))
ae4735db
C
161
162 | (_, Some _, Some _) ->
34e49164 163 (* mine *)
ae4735db 164 raise (Semantic ("long, short valid only for int or float", fake_pi))
34e49164
C
165
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) *)
708f4980
C
174
175 )
176 in
177 ((qu, iiq),
178 (ty', iit'))
34e49164 179 ,((st, inline),iist++iinl)
34e49164 180
ae4735db
C
181
182let fixDeclSpecForParam = function ({storageD = (st,iist)} as r) ->
34e49164
C
183 let ((qu,ty) as v,_st) = fixDeclSpecForDecl r in
184 match st with
185 | (Sto Register) -> (v, true), iist
186 | NoSto -> (v, false), iist
ae4735db
C
187 | _ ->
188 raise
189 (Semantic ("storage class specified for parameter of function",
34e49164
C
190 fake_pi))
191
ae4735db 192let fixDeclSpecForMacro = function ({storageD = (st,iist)} as r) ->
708f4980
C
193 let ((qu,ty) as v,_st) = fixDeclSpecForDecl r in
194 match st with
195 | NoSto -> v
ae4735db
C
196 | _ ->
197 raise
198 (Semantic ("storage class specified for macro type decl",
708f4980
C
199 fake_pi))
200
201
34e49164
C
202let fixDeclSpecForFuncDef x =
203 let (returnType,storage) = fixDeclSpecForDecl x in
204 (match fst (unwrap storage) with
ae4735db 205 | StoTypedef ->
34e49164 206 raise (Semantic ("function definition declared 'typedef'", fake_pi))
0708f913 207 | _ -> (returnType, storage)
34e49164 208 )
ae4735db 209
34e49164
C
210
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)
219 *)
220let (fixOldCDecl: fullType -> fullType) = fun ty ->
708f4980 221 match Ast_c.unwrap_typeC ty with
ae4735db 222 | FunctionType (fullt, (params, (b, iib))) ->
34e49164
C
223
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. *)
228 (match params with
ae4735db 229 | [{p_namei = None; p_type = ty2},_] ->
708f4980 230 (match Ast_c.unwrap_typeC ty2 with
ae4735db 231 | BaseType Void ->
708f4980 232 ty
ae4735db 233 | _ ->
708f4980
C
234 pr2 ("SEMANTIC:parameter name omitted, but I continue");
235 ty
236 )
ae4735db
C
237
238 | params ->
b1b2de81
C
239 (params +> List.iter (fun (param,_) ->
240 match param with
ae4735db 241 | {p_namei = None} ->
34e49164 242 (* if majuscule, then certainly macro-parameter *)
ae4735db 243 pr2 ("SEMANTIC:parameter name omitted, but I continue");
b1b2de81
C
244 | _ -> ()
245 ));
708f4980
C
246 ty
247 )
ae4735db 248
34e49164
C
249 (* todo? can we declare prototype in the decl or structdef,
250 ... => length <> but good kan meme *)
ae4735db 251 | _ ->
34e49164 252 (* gcc say parse error but dont see why *)
ae4735db 253 raise (Semantic ("seems this is not a function", fake_pi))
34e49164
C
254
255
ae4735db 256let fixFunc (typ, compound, old_style_opt) =
91eba41f
C
257 let (cp,iicp) = compound in
258
708f4980
C
259 let (name, ty, (st,iist), attrs) = typ in
260
261 let (qu, tybis) = ty in
262
263 match Ast_c.unwrap_typeC ty with
ae4735db 264 | FunctionType (fullt, (params,abool)) ->
708f4980
C
265 let iifunc = Ast_c.get_ii_typeC_take_care tybis in
266
34e49164 267 let iistart = Ast_c.fakeInfo () in
708f4980
C
268 assert (qu =*= nullQualif);
269
34e49164 270 (match params with
ae4735db 271 | [{p_namei= None; p_type = ty2}, _] ->
708f4980
C
272 (match Ast_c.unwrap_typeC ty2 with
273 | BaseType Void -> ()
ae4735db 274 | _ ->
708f4980
C
275 (* failwith "internal errror: fixOldCDecl not good" *)
276 ()
277 )
ae4735db
C
278 | params ->
279 params +> List.iter (function
b1b2de81 280 | ({p_namei = Some s}, _) -> ()
34e49164
C
281 | _ -> ()
282 (* failwith "internal errror: fixOldCDecl not good" *)
0708f913
C
283 )
284 );
ae4735db 285 (* bugfix: cf tests_c/function_pointer4.c.
0708f913 286 * Apparemment en C on peut syntaxiquement ecrire ca:
ae4735db 287 *
0708f913
C
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
ae4735db
C
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,
0708f913
C
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
ae4735db 297 * une exception. Hence this fix to at least detect the error
0708f913
C
298 * at parsing time (not unparsing time).
299 *)
ae4735db
C
300 (match Ast_c.unwrap_typeC fullt with
301 | FunctionType _ ->
b1b2de81
C
302 let s = Ast_c.str_of_name name in
303 let iis = Ast_c.info_of_name name in
0708f913
C
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))
307 | _ -> ()
308 );
309
34e49164 310 (* it must be nullQualif,cos parser construct only this*)
b1b2de81 311 {f_name = name;
708f4980 312 f_type = (fullt, (params, abool));
485bce71
C
313 f_storage = st;
314 f_body = cp;
315 f_attr = attrs;
91eba41f 316 f_old_c_style = old_style_opt;
ae4735db
C
317 },
318 (iifunc++iicp++[iistart]++iist)
319 | _ ->
320 raise
321 (Semantic
34e49164
C
322 ("you are trying to do a function definition but you dont give " ^
323 "any parameter", fake_pi))
324
325
326(*-------------------------------------------------------------------------- *)
327(* parse_typedef_fix2 *)
328(*-------------------------------------------------------------------------- *)
329
ae4735db
C
330let dt s () =
331 if !Flag_parsing_c.debug_etdt then pr2 ("<" ^ s);
34e49164
C
332 LP.disable_typedef ()
333
ae4735db
C
334let et s () =
335 if !Flag_parsing_c.debug_etdt then pr2 (">" ^ s);
34e49164
C
336 LP.enable_typedef ()
337
338
ae4735db 339let fix_add_params_ident x =
708f4980
C
340 let (s, ty, st, _attrs) = x in
341 match Ast_c.unwrap_typeC ty with
342 | FunctionType (fullt, (params, bool)) ->
34e49164
C
343
344 (match params with
ae4735db 345 | [{p_namei=None; p_type=ty2}, _] ->
708f4980
C
346 (match Ast_c.unwrap_typeC ty2 with
347 | BaseType Void -> ()
ae4735db 348 | _ ->
708f4980
C
349 (* failwith "internal errror: fixOldCDecl not good" *)
350 ()
351 )
ae4735db
C
352 | params ->
353 params +> List.iter (function
354 | ({p_namei= Some name}, _) ->
b1b2de81 355 LP.add_ident (Ast_c.str_of_name s)
ae4735db 356 | _ ->
b1b2de81
C
357 ()
358 (* failwith "internal errror: fixOldCDecl not good" *)
359 )
ae4735db 360 )
34e49164
C
361 | _ -> ()
362
0708f913
C
363
364
34e49164
C
365(*-------------------------------------------------------------------------- *)
366(* shortcuts *)
367(*-------------------------------------------------------------------------- *)
368
708f4980 369let mk_e e ii = Ast_c.mk_e e ii
b1b2de81
C
370
371let mk_string_wrap (s,info) = (s, [info])
ae4735db 372
34e49164
C
373%}
374
375/*(*****************************************************************************)*/
485bce71
C
376/*(* Tokens *)*/
377/*(*************************************************************************)*/
34e49164
C
378
379/*
ae4735db 380(*
34e49164
C
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)
385 *)
386*/
387
388%token <Ast_c.info> TUnknown /*(* unrecognized token *)*/
389
390/*(* coupling: Token_helpers.is_real_comment *)*/
485bce71 391%token <Ast_c.info> TCommentSpace TCommentNewline TComment
34e49164 392
485bce71 393/*(*-----------------------------------------*)*/
34e49164 394/*(* the normal tokens *)*/
485bce71 395/*(*-----------------------------------------*)*/
34e49164 396
708f4980 397%token <(string * (Ast_c.sign * Ast_c.base)) * Ast_c.info> TInt
34e49164
C
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
401
ae4735db 402%token <string * Ast_c.info> TIdent
485bce71
C
403/*(* appears mostly after some fix_xxx in parsing_hack *)*/
404%token <string * Ast_c.info> TypedefIdent
34e49164
C
405
406
407/*
ae4735db 408(* Some tokens like TOPar and TCPar are used as synchronisation stuff,
34e49164 409 * in parsing_hack.ml. So if define special tokens like TOParDefine and
485bce71 410 * TCParEOL, then take care to also modify in Token_helpers.
34e49164
C
411 *)
412*/
ae4735db
C
413
414%token <Ast_c.info> TOPar TCPar TOBrace TCBrace TOCro TCCro
415%token <Ast_c.info> TDot TComma TPtrOp
34e49164 416%token <Ast_c.info> TInc TDec
ae4735db 417%token <Ast_c.assignOp * Ast_c.info> TAssign
34e49164
C
418%token <Ast_c.info> TEq
419%token <Ast_c.info> TWhy TTilde TBang
420%token <Ast_c.info> TEllipsis
421%token <Ast_c.info> TDotDot
422
423%token <Ast_c.info> TPtVirg
ae4735db 424%token <Ast_c.info>
34e49164 425 TOrLog TAndLog TOr TXor TAnd TEqEq TNotEq TInf TSup TInfEq TSupEq
ae4735db
C
426 TShl TShr
427 TPlus TMinus TMul TDiv TMod
34e49164
C
428
429%token <Ast_c.info>
430 Tchar Tshort Tint Tdouble Tfloat Tlong Tunsigned Tsigned Tvoid
ae4735db
C
431 Tauto Tregister Textern Tstatic
432 Ttypedef
34e49164 433 Tconst Tvolatile
ae4735db 434 Tstruct Tunion Tenum
34e49164
C
435 Tbreak Telse Tswitch Tcase Tcontinue Tfor Tdo Tif Twhile Treturn
436 Tgoto Tdefault
ae4735db 437 Tsizeof
34e49164 438
485bce71
C
439/*(* C99 *)*/
440%token <Ast_c.info>
441 Trestrict
442
443/*(*-----------------------------------------*)*/
34e49164 444/*(* gccext: extra tokens *)*/
485bce71 445/*(*-----------------------------------------*)*/
34e49164
C
446%token <Ast_c.info> Tasm
447%token <Ast_c.info> Tattribute
978fd7e5 448%token <Ast_c.info> TattributeNoarg
34e49164
C
449%token <Ast_c.info> Tinline
450%token <Ast_c.info> Ttypeof
451
485bce71
C
452/*(*-----------------------------------------*)*/
453/*(* cppext: extra tokens *)*/
454/*(*-----------------------------------------*)*/
455/*(* coupling with Token_helpers.is_cpp_token *)*/
456
457
458/*(*---------------*)*/
459/*(* define *)*/
460/*(*---------------*)*/
461
462%token <Ast_c.info> TDefine
463%token <(string * Ast_c.info)> TDefParamVariadic
464
465/*(* disappear after fix_tokens_define *)*/
ae4735db 466%token <Ast_c.info> TCppEscapedNewline
485bce71 467
b1b2de81
C
468%token <Ast_c.info> TCppConcatOp
469
485bce71 470/*(* appear after fix_tokens_define *)*/
ae4735db 471%token <Ast_c.info> TOParDefine
485bce71
C
472%token <Ast_c.info> TOBraceDefineInit
473
474%token <(string * Ast_c.info)> TIdentDefine /*(* same *)*/
475%token <Ast_c.info> TDefEOL /*(* same *)*/
476
477
478/*(*---------------*)*/
479/*(* include *)*/
480/*(*---------------*)*/
481
482
483/*(* used only in lexer_c, then transformed in comment or splitted in tokens *)*/
484%token <(string * string * bool ref * Ast_c.info)> TInclude
485
486/*(* tokens coming from above, generated in parse_c from TInclude, etc *)*/
487%token <(Ast_c.info * bool ref)> TIncludeStart
488%token <(string * Ast_c.info)> TIncludeFilename
489
490
491/*(*---------------*)*/
492/*(* ifdef *)*/
493/*(*---------------*)*/
494
495/*(* coupling: Token_helpers.is_cpp_instruction *)*/
ae4735db 496%token <((int * int) option ref * Ast_c.info)>
485bce71 497 TIfdef TIfdefelse TIfdefelif TEndif
ae4735db 498%token <(bool * (int * int) option ref * Ast_c.info)>
485bce71
C
499 TIfdefBool TIfdefMisc TIfdefVersion
500
501/*(*---------------*)*/
502/*(* other *)*/
503/*(*---------------*)*/
504
505
506%token <string * Ast_c.info> TUndef
507
508%token <Ast_c.info> TCppDirectiveOther
509
510/*(*---------------*)*/
511/*(* macro use *)*/
512/*(*---------------*)*/
513
514/*(* appear after fix_tokens_cpp, cf also parsing_hacks#hint *)*/
515
516%token <(string * Ast_c.info)> TMacroAttr
517%token <(string * Ast_c.info)> TMacroStmt
b1b2de81 518%token <(string * Ast_c.info)> TMacroIdentBuilder
485bce71 519/*(* no need value for the moment *)*/
ae4735db 520%token <(string * Ast_c.info)> TMacroString
485bce71 521%token <(string * Ast_c.info)> TMacroDecl
ae4735db 522%token <Ast_c.info> TMacroDeclConst
708f4980 523
485bce71 524%token <(string * Ast_c.info)> TMacroIterator
ae4735db
C
525/*(*
526%token <(string * Ast_c.info)> TMacroTop
708f4980
C
527%token <(string * Ast_c.info)> TMacroStructDecl
528*)*/
485bce71
C
529
530%token <(string * Ast_c.info)> TMacroAttrStorage
531
532
533/*(*---------------*)*/
534/*(* other *)*/
535/*(*---------------*)*/
536
0708f913
C
537
538/*(* should disappear after parsing_hack *)*/
539%token <Ast_c.info> TCommentSkipTagStart TCommentSkipTagEnd
540
541
485bce71 542/*(* appear after parsing_hack *)*/
ae4735db 543%token <Ast_c.info> TCParEOL
485bce71
C
544
545%token <Ast_c.info> TAction
546
547
0708f913 548/*(* TCommentMisc still useful ? obsolete ? *)*/
485bce71 549%token <Ast_c.info> TCommentMisc
0708f913 550%token <(Token_c.cppcommentkind * Ast_c.info)> TCommentCpp
485bce71 551
34e49164 552
485bce71 553/*(*-----------------------------------------*)*/
34e49164
C
554%token <Ast_c.info> EOF
555
485bce71
C
556/*(*-----------------------------------------*)*/
557
558/*(* must be at the top so that it has the lowest priority *)*/
559%nonassoc SHIFTHERE
34e49164 560
34e49164
C
561%nonassoc Telse
562
563%left TOrLog
564%left TAndLog
565%left TOr
566%left TXor
ae4735db 567%left TAnd
34e49164 568%left TEqEq TNotEq
ae4735db 569%left TInf TSup TInfEq TSupEq
34e49164
C
570%left TShl TShr
571%left TPlus TMinus
ae4735db 572%left TMul TDiv TMod
34e49164 573
485bce71
C
574/*(*************************************************************************)*/
575/*(* Rules type declaration *)*/
576/*(*************************************************************************)*/
577
34e49164
C
578%start main celem statement expr type_name
579%type <Ast_c.program> main
580%type <Ast_c.toplevel> celem
581
582%type <Ast_c.statement> statement
583%type <Ast_c.expression> expr
584%type <Ast_c.fullType> type_name
585
586%%
587/*(*************************************************************************)*/
588/*
589(* TOC:
485bce71 590 * toplevel (obsolete)
ae4735db 591 *
485bce71 592 * ident
34e49164
C
593 * expression
594 * statement
ae4735db
C
595 * types with
596 * - left part (type_spec, qualif),
485bce71
C
597 * - right part (declarator, abstract declarator)
598 * - aux part (parameters)
599 * declaration, storage, initializers
600 * struct
601 * enum
34e49164
C
602 * cpp directives
603 * celem (=~ main)
ae4735db 604 *
485bce71
C
605 * generic workarounds (obrace, cbrace for context setting)
606 * xxx_list, xxx_opt
34e49164
C
607 *)
608*/
609/*(*************************************************************************)*/
610
485bce71
C
611/*(*************************************************************************)*/
612/*(* toplevel *)*/
613/*(*************************************************************************)*/
34e49164
C
614/*(* no more used; now that use error recovery *)*/
615
616main: translation_unit EOF { $1 }
617
ae4735db
C
618translation_unit:
619 | external_declaration
485bce71 620 { !LP._lexer_hint.context_stack <- [LP.InTopLevel]; [$1] }
34e49164 621 | translation_unit external_declaration
485bce71
C
622 { !LP._lexer_hint.context_stack <- [LP.InTopLevel]; $1 ++ [$2] }
623
624
625
626/*(*************************************************************************)*/
627/*(* ident *)*/
628/*(*************************************************************************)*/
629
ae4735db 630/*(* Why this ? Why not s/ident/TIdent ? cos there is multiple namespaces in C,
485bce71
C
631 * so a label can have the same name that a typedef, same for field and tags
632 * hence sometimes the use of ident instead of TIdent.
633 *)*/
ae4735db 634ident:
485bce71
C
635 | TIdent { $1 }
636 | TypedefIdent { $1 }
34e49164
C
637
638
485bce71
C
639identifier:
640 | TIdent { $1 }
34e49164 641
b1b2de81 642/*
ae4735db 643(* cppext: string concatenation of idents
b1b2de81
C
644 * also cppext: gccext: ##args for variadic macro
645 *)
646*/
708f4980 647identifier_cpp:
ae4735db 648 | TIdent
b1b2de81 649 { RegularName (mk_string_wrap $1) }
708f4980
C
650 | ident_extra_cpp { $1 }
651
652ident_cpp:
653 | TIdent
654 { RegularName (mk_string_wrap $1) }
ae4735db 655 | TypedefIdent
708f4980
C
656 { RegularName (mk_string_wrap $1) }
657 | ident_extra_cpp { $1 }
658
659ident_extra_cpp:
ae4735db
C
660 | TIdent TCppConcatOp identifier_cpp_list
661 {
b1b2de81
C
662 CppConcatenatedName (
663 match $3 with
664 | [] -> raise Impossible
ae4735db 665 | (x,concatnull)::xs ->
b1b2de81
C
666 assert(null concatnull);
667 (mk_string_wrap $1, [])::(x,[$2])::xs
668 )
669 }
ae4735db 670 | TCppConcatOp TIdent
b1b2de81
C
671 { CppVariadicName (fst $2, [$1; snd $2]) }
672 | TMacroIdentBuilder TOPar param_define_list TCPar
ae4735db 673 { CppIdentBuilder ((fst $1, [snd $1;$2;$4]), $3) }
b1b2de81
C
674
675identifier_cpp_list:
ae4735db 676 | TIdent { [mk_string_wrap $1, []] }
b1b2de81
C
677 | identifier_cpp_list TCppConcatOp TIdent { $1 ++ [mk_string_wrap $3, [$2]] }
678
34e49164
C
679/*(*************************************************************************)*/
680/*(* expr *)*/
681/*(*************************************************************************)*/
682
ae4735db 683expr:
34e49164
C
684 | assign_expr { $1 }
685 | expr TComma assign_expr { mk_e (Sequence ($1,$3)) [$2] }
686
ae4735db 687/*(* bugfix: in C grammar they put unary_expr, but in fact it must be
34e49164
C
688 * cast_expr, otherwise (int * ) xxx = &yy; is not allowed
689 *)*/
ae4735db 690assign_expr:
34e49164
C
691 | cond_expr { $1 }
692 | cast_expr TAssign assign_expr { mk_e(Assignment ($1,fst $2,$3)) [snd $2]}
693 | cast_expr TEq assign_expr { mk_e(Assignment ($1,SimpleAssign,$3)) [$2]}
694
ae4735db 695/*(* gccext: allow optional then part hence gcc_opt_expr
34e49164
C
696 * bugfix: in C grammar they put TDotDot cond_expr, but in fact it must be
697 * assign_expr, otherwise pnp ? x : x = 0x388 is not allowed
698 *)*/
ae4735db
C
699cond_expr:
700 | arith_expr
34e49164 701 { $1 }
ae4735db
C
702 | arith_expr TWhy gcc_opt_expr TDotDot assign_expr
703 { mk_e (CondExpr ($1,$3,$5)) [$2;$4] }
34e49164
C
704
705
ae4735db 706arith_expr:
34e49164
C
707 | cast_expr { $1 }
708 | arith_expr TMul arith_expr { mk_e(Binary ($1, Arith Mul, $3)) [$2] }
709 | arith_expr TDiv arith_expr { mk_e(Binary ($1, Arith Div, $3)) [$2] }
710 | arith_expr TMod arith_expr { mk_e(Binary ($1, Arith Mod, $3)) [$2] }
711 | arith_expr TPlus arith_expr { mk_e(Binary ($1, Arith Plus, $3)) [$2] }
712 | arith_expr TMinus arith_expr { mk_e(Binary ($1, Arith Minus, $3)) [$2] }
713 | arith_expr TShl arith_expr { mk_e(Binary ($1, Arith DecLeft, $3)) [$2] }
714 | arith_expr TShr arith_expr { mk_e(Binary ($1, Arith DecRight, $3)) [$2] }
715 | arith_expr TInf arith_expr { mk_e(Binary ($1, Logical Inf, $3)) [$2] }
716 | arith_expr TSup arith_expr { mk_e(Binary ($1, Logical Sup, $3)) [$2] }
717 | arith_expr TInfEq arith_expr { mk_e(Binary ($1, Logical InfEq, $3)) [$2] }
718 | arith_expr TSupEq arith_expr { mk_e(Binary ($1, Logical SupEq, $3)) [$2] }
719 | arith_expr TEqEq arith_expr { mk_e(Binary ($1, Logical Eq, $3)) [$2] }
720 | arith_expr TNotEq arith_expr { mk_e(Binary ($1, Logical NotEq, $3)) [$2] }
721 | arith_expr TAnd arith_expr { mk_e(Binary ($1, Arith And, $3)) [$2] }
722 | arith_expr TOr arith_expr { mk_e(Binary ($1, Arith Or, $3)) [$2] }
723 | arith_expr TXor arith_expr { mk_e(Binary ($1, Arith Xor, $3)) [$2] }
724 | arith_expr TAndLog arith_expr { mk_e(Binary ($1, Logical AndLog, $3)) [$2] }
725 | arith_expr TOrLog arith_expr { mk_e(Binary ($1, Logical OrLog, $3)) [$2] }
726
ae4735db 727cast_expr:
34e49164
C
728 | unary_expr { $1 }
729 | topar2 type_name tcpar2 cast_expr { mk_e(Cast ($2, $4)) [$1;$3] }
730
ae4735db 731unary_expr:
34e49164
C
732 | postfix_expr { $1 }
733 | TInc unary_expr { mk_e(Infix ($2, Inc)) [$1] }
734 | TDec unary_expr { mk_e(Infix ($2, Dec)) [$1] }
735 | unary_op cast_expr { mk_e(Unary ($2, fst $1)) [snd $1] }
736 | Tsizeof unary_expr { mk_e(SizeOfExpr ($2)) [$1] }
737 | Tsizeof topar2 type_name tcpar2 { mk_e(SizeOfType ($3)) [$1;$2;$4] }
738
ae4735db 739unary_op:
34e49164
C
740 | TAnd { GetRef, $1 }
741 | TMul { DeRef, $1 }
742 | TPlus { UnPlus, $1 }
743 | TMinus { UnMinus, $1 }
744 | TTilde { Tilde, $1 }
745 | TBang { Not, $1 }
746 /*(* gccext: have that a lot in old kernel to get address of local label.
747 * cf gcc manual "local labels as values".
748 *)*/
749 | TAndLog { GetRefLabel, $1 }
750
751
752
ae4735db 753postfix_expr:
34e49164 754 | primary_expr { $1 }
ae4735db 755 | postfix_expr TOCro expr TCCro
34e49164 756 { mk_e(ArrayAccess ($1, $3)) [$2;$4] }
ae4735db 757 | postfix_expr TOPar argument_list_ne TCPar
34e49164
C
758 { mk_e(FunCall ($1, $3)) [$2;$4] }
759 | postfix_expr TOPar TCPar { mk_e(FunCall ($1, [])) [$2;$3] }
b1b2de81
C
760 | postfix_expr TDot ident_cpp { mk_e(RecordAccess ($1,$3)) [$2] }
761 | postfix_expr TPtrOp ident_cpp { mk_e(RecordPtAccess ($1,$3)) [$2] }
34e49164
C
762 | postfix_expr TInc { mk_e(Postfix ($1, Inc)) [$2] }
763 | postfix_expr TDec { mk_e(Postfix ($1, Dec)) [$2] }
764
765 /*(* gccext: also called compound literals *)*/
0708f913 766 | topar2 type_name tcpar2 TOBrace TCBrace
34e49164
C
767 { mk_e(Constructor ($2, [])) [$1;$3;$4;$5] }
768 | topar2 type_name tcpar2 TOBrace initialize_list gcc_comma_opt TCBrace
769 { mk_e(Constructor ($2, List.rev $5)) ([$1;$3;$4;$7] ++ $6) }
770
0708f913 771primary_expr:
708f4980
C
772 | identifier_cpp { mk_e(Ident ($1)) [] }
773 | TInt
774 { let (str,(sign,base)) = fst $1 in
775 mk_e(Constant (Int (str,Si(sign,base)))) [snd $1] }
34e49164
C
776 | TFloat { mk_e(Constant (Float (fst $1))) [snd $1] }
777 | TString { mk_e(Constant (String (fst $1))) [snd $1] }
778 | TChar { mk_e(Constant (Char (fst $1))) [snd $1] }
779 | TOPar expr TCPar { mk_e(ParenExpr ($2)) [$1;$3] } /*(* forunparser: *)*/
780
485bce71 781 /*(* gccext: cppext: TODO better ast ? *)*/
0708f913
C
782 | TMacroString { mk_e(Constant (MultiString [fst $1])) [snd $1] }
783 | string_elem string_list
784 { mk_e(Constant (MultiString ["TODO: MultiString"])) ($1 ++ $2) }
34e49164
C
785
786 /*(* gccext: allow statement as expressions via ({ statement }) *)*/
0708f913 787 | TOPar compound TCPar { mk_e(StatementExpr ($2)) [$1;$3] }
34e49164
C
788
789
790
485bce71
C
791/*(*----------------------------*)*/
792/*(* cppext: *)*/
793/*(*----------------------------*)*/
34e49164
C
794
795/*(* cppext: *)*/
485bce71 796/*(* to avoid conflicts have to introduce a _not_empty (ne) version *)*/
0708f913 797argument_ne:
34e49164
C
798 | assign_expr { Left $1 }
799 | parameter_decl { Right (ArgType $1) }
800 | action_higherordermacro_ne { Right (ArgAction $1) }
801
485bce71 802
ae4735db 803argument:
34e49164
C
804 | assign_expr { Left $1 }
805 | parameter_decl { Right (ArgType $1) }
485bce71 806 /*(* had conflicts before, but julia fixed them *)*/
34e49164
C
807 | action_higherordermacro { Right (ArgAction $1) }
808
ae4735db
C
809action_higherordermacro_ne:
810 | taction_list_ne
34e49164
C
811 { if null $1
812 then ActMisc [Ast_c.fakeInfo()]
813 else ActMisc $1
814 }
815
485bce71 816
ae4735db
C
817action_higherordermacro:
818 | taction_list
34e49164
C
819 { if null $1
820 then ActMisc [Ast_c.fakeInfo()]
821 else ActMisc $1
822 }
823
824
825/*(*----------------------------*)*/
826/*(* workarounds *)*/
827/*(*----------------------------*)*/
828
34e49164
C
829/*(* would like evalInt $1 but require too much info *)*/
830const_expr: cond_expr { $1 }
831
832
833topar2: TOPar { et "topar2" (); $1 }
ae4735db 834tcpar2: TCPar { et "tcpar2" (); $1 (*TODO? et ? sure ? c pas dt plutot ? *) }
34e49164
C
835
836
837
838/*(*************************************************************************)*/
839/*(* statement *)*/
840/*(*************************************************************************)*/
841
708f4980
C
842statement: statement2 { mk_st (fst $1) (snd $1) }
843
ae4735db 844statement2:
34e49164
C
845 | labeled { Labeled (fst $1), snd $1 }
846 | compound { Compound (fst $1), snd $1 }
847 | expr_statement { ExprStatement(fst $1), snd $1 }
848 | selection { Selection (fst $1), snd $1 ++ [fakeInfo()] }
849 | iteration { Iteration (fst $1), snd $1 ++ [fakeInfo()] }
850 | jump TPtVirg { Jump (fst $1), snd $1 ++ [$2] }
851
852 /*(* gccext: *)*/
853 | Tasm TOPar asmbody TCPar TPtVirg { Asm $3, [$1;$2;$4;$5] }
854 | Tasm Tvolatile TOPar asmbody TCPar TPtVirg { Asm $4, [$1;$2;$3;$5;$6] }
855
856 /*(* cppext: *)*/
485bce71 857 | TMacroStmt { MacroStmt, [snd $1] }
34e49164
C
858
859
860
861
ae4735db
C
862/*(* note that case 1: case 2: i++; would be correctly parsed, but with
863 * a Case (1, (Case (2, i++))) :(
34e49164 864 *)*/
ae4735db 865labeled:
b1b2de81 866 | ident_cpp TDotDot statement { Label ($1, $3), [$2] }
34e49164 867 | Tcase const_expr TDotDot statement { Case ($2, $4), [$1; $3] }
ae4735db 868 | Tcase const_expr TEllipsis const_expr TDotDot statement
34e49164 869 { CaseRange ($2, $4, $6), [$1;$3;$5] } /*(* gccext: allow range *)*/
ae4735db 870 | Tdefault TDotDot statement { Default $3, [$1; $2] }
34e49164 871
ae4735db 872end_labeled:
34e49164 873 /*(* gccext: allow toto: }
485bce71
C
874 * was generating each 30 shift/Reduce conflicts,
875 * mais ca va, ca fait ce qu'il faut.
ae4735db 876 * update: julia fixed the problem by introducing end_labeled
485bce71 877 * and modifying below stat_or_decl_list
34e49164 878 *)*/
ae4735db 879 | ident_cpp TDotDot
708f4980 880 { Label ($1, (mk_st (ExprStatement None) Ast_c.noii)), [$2] }
ae4735db 881 | Tcase const_expr TDotDot
708f4980 882 { Case ($2, (mk_st (ExprStatement None) Ast_c.noii)), [$1;$3] }
ae4735db 883 | Tdefault TDotDot
708f4980 884 { Default (mk_st (ExprStatement None) Ast_c.noii), [$1; $2] }
34e49164
C
885
886
887
888
889
890compound: tobrace compound2 tcbrace { $2, [$1; $3] }
891
34e49164
C
892
893/*
894(* cppext: because of cpp, some stuff looks like declaration but are in
895 * fact statement but too hard to figure out, and if parse them as
896 * expression, then we force to have first decls and then exprs, then
897 * will have a parse error. So easier to let mix decl/statement.
898 * Moreover it helps to not make such a difference between decl and
899 * statement for further coccinelle phases to factorize code.
900*)*/
ae4735db 901compound2:
34e49164
C
902 | { ([]) }
903 | stat_or_decl_list { $1 }
904
34e49164 905
ae4735db
C
906stat_or_decl_list:
907 | stat_or_decl { [$1] }
485bce71 908 /*(* gccext: to avoid conflicts, cf end_labeled above *)*/
708f4980 909 | end_labeled { [StmtElem (mk_st (Labeled (fst $1)) (snd $1))] }
485bce71
C
910 /*(* old: conflicts | stat_or_decl_list stat_or_decl { $1 ++ [$2] } *)*/
911 | stat_or_decl stat_or_decl_list { $1 :: $2 }
912
ae4735db 913stat_or_decl:
708f4980 914 | decl { StmtElem (mk_st (Decl ($1 Ast_c.LocalDecl)) Ast_c.noii) }
485bce71 915 | statement { StmtElem $1 }
34e49164
C
916
917 /*(* gccext: *)*/
708f4980 918 | function_definition { StmtElem (mk_st (NestedFunc $1) Ast_c.noii) }
34e49164 919
485bce71 920 /* (* cppext: *)*/
ae4735db 921 | cpp_directive
485bce71 922 { CppDirectiveStmt $1 }
ae4735db 923 | cpp_ifdef_directive/*(* stat_or_decl_list ...*)*/
485bce71 924 { IfdefStmt $1 }
34e49164
C
925
926
927
928
929
ae4735db 930expr_statement:
34e49164
C
931 | TPtVirg { None, [$1] }
932 | expr TPtVirg { Some $1, [$2] }
933
ae4735db 934selection:
485bce71 935 | Tif TOPar expr TCPar statement %prec SHIFTHERE
708f4980 936 { If ($3, $5, (mk_st (ExprStatement None) Ast_c.noii)), [$1;$2;$4] }
ae4735db 937 | Tif TOPar expr TCPar statement Telse statement
34e49164 938 { If ($3, $5, $7), [$1;$2;$4;$6] }
ae4735db 939 | Tswitch TOPar expr TCPar statement
34e49164
C
940 { Switch ($3,$5), [$1;$2;$4] }
941
ae4735db
C
942iteration:
943 | Twhile TOPar expr TCPar statement
34e49164 944 { While ($3,$5), [$1;$2;$4] }
ae4735db 945 | Tdo statement Twhile TOPar expr TCPar TPtVirg
34e49164
C
946 { DoWhile ($2,$5), [$1;$3;$4;$6;$7] }
947 | Tfor TOPar expr_statement expr_statement TCPar statement
948 { For ($3,$4,(None, []),$6), [$1;$2;$5]}
949 | Tfor TOPar expr_statement expr_statement expr TCPar statement
950 { For ($3,$4,(Some $5, []),$7), [$1;$2;$6] }
485bce71
C
951 /*(* c++ext: for(int i = 0; i < n; i++)*)*/
952 | Tfor TOPar decl expr_statement expr_opt TCPar statement
ae4735db 953 {
485bce71 954 (* pr2 "DECL in for"; *)
b1b2de81 955 MacroIteration ("toto", [], $7),[$1;$2;$6] (* TODOfake ast, TODO need decl2 ? *)
34e49164 956 }
34e49164
C
957 /*(* cppext: *)*/
958 | TMacroIterator TOPar argument_list_ne TCPar statement
959 { MacroIteration (fst $1, $3, $5), [snd $1;$2;$4] }
960 | TMacroIterator TOPar TCPar statement
961 { MacroIteration (fst $1, [], $4), [snd $1;$2;$3] }
962
963/*(* the ';' in the caller grammar rule will be appended to the infos *)*/
ae4735db
C
964jump:
965 | Tgoto ident_cpp { Goto ($2), [$1] }
34e49164
C
966 | Tcontinue { Continue, [$1] }
967 | Tbreak { Break, [$1] }
ae4735db 968 | Treturn { Return, [$1] }
34e49164
C
969 | Treturn expr { ReturnExpr $2, [$1] }
970 | Tgoto TMul expr { GotoComputed $3, [$1;$2] }
971
972
973
974/*(*----------------------------*)*/
975/*(* gccext: *)*/
976/*(*----------------------------*)*/
977string_elem:
978 | TString { [snd $1] }
979 /*(* cppext: ex= printk (KERN_INFO "xxx" UTS_RELEASE) *)*/
485bce71 980 | TMacroString { [snd $1] }
34e49164
C
981
982
ae4735db 983asmbody:
34e49164
C
984 | string_list colon_asm_list { $1, $2 }
985 | string_list { $1, [] } /*(* in old kernel *)*/
986
987
988colon_asm: TDotDot colon_option_list { Colon $2, [$1] }
989
ae4735db 990colon_option:
34e49164 991 | TString { ColonMisc, [snd $1] }
ae4735db 992 | TString TOPar asm_expr TCPar { ColonExpr $3, [snd $1; $2;$4] }
34e49164
C
993 /*(* cppext: certainly a macro *)*/
994 | TOCro identifier TCCro TString TOPar asm_expr TCPar
995 { ColonExpr $6, [$1;snd $2;$3;snd $4; $5; $7 ] }
996 | identifier { ColonMisc, [snd $1] }
997 | /*(* empty *)*/ { ColonMisc, [] }
998
999asm_expr: assign_expr { $1 }
1000
34e49164 1001/*(*************************************************************************)*/
485bce71 1002/*(* types *)*/
34e49164 1003/*(*************************************************************************)*/
ae4735db 1004
34e49164 1005
485bce71
C
1006/*(*-----------------------------------------------------------------------*)*/
1007/*(* Type spec, left part of a type *)*/
1008/*(*-----------------------------------------------------------------------*)*/
ae4735db 1009type_spec2:
34e49164
C
1010 | Tvoid { Right3 (BaseType Void), [$1] }
1011 | Tchar { Right3 (BaseType (IntType CChar)), [$1]}
1012 | Tint { Right3 (BaseType (IntType (Si (Signed,CInt)))), [$1]}
1013 | Tfloat { Right3 (BaseType (FloatType CFloat)), [$1]}
1014 | Tdouble { Right3 (BaseType (FloatType CDouble)), [$1] }
1015 | Tshort { Middle3 Short, [$1]}
1016 | Tlong { Middle3 Long, [$1]}
1017 | Tsigned { Left3 Signed, [$1]}
1018 | Tunsigned { Left3 UnSigned, [$1]}
1019 | struct_or_union_spec { Right3 (fst $1), snd $1 }
1020 | enum_spec { Right3 (fst $1), snd $1 }
1021
1022 /*
ae4735db
C
1023 (* parse_typedef_fix1: cant put: TIdent {} cos it make the grammar
1024 * ambiguous, generates lots of conflicts => we must
34e49164 1025 * use some tricks: we make the lexer and parser cooperate, cf lexerParser.ml.
ae4735db
C
1026 *
1027 * parse_typedef_fix2: this is not enough, and you must use
34e49164 1028 * parse_typedef_fix2 to fully manage typedef problems in grammar.
ae4735db 1029 *
34e49164 1030 * parse_typedef_fix3:
ae4735db 1031 *
34e49164
C
1032 * parse_typedef_fix4: try also to do now some consistency checking in
1033 * Parse_c
ae4735db
C
1034 *)*/
1035 | TypedefIdent
b1b2de81
C
1036 { let name = RegularName (mk_string_wrap $1) in
1037 Right3 (TypeName (name, Ast_c.noTypedefDef())),[] }
34e49164
C
1038
1039 | Ttypeof TOPar assign_expr TCPar { Right3 (TypeOfExpr ($3)), [$1;$2;$4] }
1040 | Ttypeof TOPar type_name TCPar { Right3 (TypeOfType ($3)), [$1;$2;$4] }
1041
34e49164
C
1042/*(*----------------------------*)*/
1043/*(* workarounds *)*/
1044/*(*----------------------------*)*/
1045
34e49164
C
1046type_spec: type_spec2 { dt "type" (); $1 }
1047
485bce71
C
1048/*(*-----------------------------------------------------------------------*)*/
1049/*(* Qualifiers *)*/
1050/*(*-----------------------------------------------------------------------*)*/
34e49164 1051
ae4735db 1052type_qualif:
485bce71
C
1053 | Tconst { {const=true ; volatile=false}, $1 }
1054 | Tvolatile { {const=false ; volatile=true}, $1 }
1055 /*(* C99 *)*/
1056 | Trestrict { (* TODO *) {const=false ; volatile=false}, $1 }
34e49164
C
1057
1058
1059/*(*-----------------------------------------------------------------------*)*/
485bce71 1060/*(* gccext: attributes *)*/
34e49164 1061/*(*-----------------------------------------------------------------------*)*/
34e49164 1062
485bce71
C
1063attribute:
1064 | Tattribute TOPar /*stuff*/ TCPar { raise Todo }
1065 /*(* cppext: *)*/
1066 | TMacroAttr { Attribute (fst $1), [snd $1] }
34e49164 1067
485bce71
C
1068attribute_storage:
1069 | TMacroAttrStorage { $1 }
34e49164 1070
485bce71
C
1071type_qualif_attr:
1072 | type_qualif { $1 }
91eba41f
C
1073/*(*TODO !!!!! *)*/
1074 | TMacroAttr { {const=true ; volatile=false}, snd $1 }
34e49164 1075
485bce71
C
1076/*(*-----------------------------------------------------------------------*)*/
1077/*(* Declarator, right part of a type + second part of decl (the ident) *)*/
1078/*(*-----------------------------------------------------------------------*)*/
34e49164
C
1079
1080/*
ae4735db
C
1081(* declarator return a couple:
1082 * (name, partial type (a function to be applied to return type))
34e49164
C
1083 *
1084 * when int* f(int) we must return Func(Pointer int,int) and not
ae4735db 1085 * Pointer (Func(int,int)
34e49164
C
1086 *)*/
1087
ae4735db 1088declarator:
34e49164
C
1089 | pointer direct_d { (fst $2, fun x -> x +> $1 +> (snd $2) ) }
1090 | direct_d { $1 }
1091
1092/*(* so must do int * const p; if the pointer is constant, not the pointee *)*/
ae4735db 1093pointer:
708f4980
C
1094 | TMul { fun x -> mk_ty (Pointer x) [$1] }
1095 | TMul pointer { fun x -> mk_ty (Pointer ($2 x)) [$1] }
ae4735db 1096 | TMul type_qualif_list
708f4980 1097 { fun x -> ($2.qualifD, mk_tybis (Pointer x) [$1])}
ae4735db 1098 | TMul type_qualif_list pointer
708f4980 1099 { fun x -> ($2.qualifD, mk_tybis (Pointer ($3 x)) [$1]) }
34e49164 1100
34e49164 1101
ae4735db 1102direct_d:
708f4980 1103 | identifier_cpp
34e49164 1104 { ($1, fun x -> x) }
ae4735db 1105 | TOPar declarator TCPar /*(* forunparser: old: $2 *)*/
708f4980 1106 { (fst $2, fun x -> mk_ty (ParenType ((snd $2) x)) [$1;$3]) }
ae4735db 1107 | direct_d tocro tccro
708f4980 1108 { (fst $1,fun x->(snd $1) (mk_ty (Array (None,x)) [$2;$3])) }
34e49164 1109 | direct_d tocro const_expr tccro
708f4980 1110 { (fst $1,fun x->(snd $1) (mk_ty (Array (Some $3,x)) [$2;$4])) }
34e49164
C
1111 | direct_d topar tcpar
1112 { (fst $1,
ae4735db 1113 fun x->(snd $1)
708f4980 1114 (mk_ty (FunctionType (x,(([],(false, []))))) [$2;$3]))
34e49164
C
1115 }
1116 | direct_d topar parameter_type_list tcpar
ae4735db
C
1117 { (fst $1,fun x->(snd $1)
1118 (mk_ty (FunctionType (x, $3)) [$2;$4]))
708f4980 1119 }
34e49164
C
1120
1121
485bce71
C
1122/*(*----------------------------*)*/
1123/*(* workarounds *)*/
1124/*(*----------------------------*)*/
1125
1126tocro: TOCro { et "tocro" ();$1 }
1127tccro: TCCro { dt "tccro" ();$1 }
1128
1129/*(*-----------------------------------------------------------------------*)*/
ae4735db 1130abstract_declarator:
485bce71
C
1131 | pointer { $1 }
1132 | direct_abstract_declarator { $1 }
1133 | pointer direct_abstract_declarator { fun x -> x +> $2 +> $1 }
1134
ae4735db 1135direct_abstract_declarator:
485bce71 1136 | TOPar abstract_declarator TCPar /*(* forunparser: old: $2 *)*/
708f4980 1137 { fun x -> mk_ty (ParenType ($2 x)) [$1;$3] }
485bce71 1138
ae4735db 1139 | TOCro TCCro
708f4980 1140 { fun x -> mk_ty (Array (None, x)) [$1;$2] }
ae4735db 1141 | TOCro const_expr TCCro
708f4980 1142 { fun x -> mk_ty (Array (Some $2, x)) [$1;$3] }
ae4735db 1143 | direct_abstract_declarator TOCro TCCro
708f4980 1144 { fun x -> $1 (mk_ty (Array (None, x)) [$2;$3]) }
485bce71 1145 | direct_abstract_declarator TOCro const_expr TCCro
708f4980 1146 { fun x -> $1 (mk_ty (Array (Some $3,x)) [$2;$4]) }
ae4735db 1147 | TOPar TCPar
708f4980 1148 { fun x -> mk_ty (FunctionType (x, ([], (false, [])))) [$1;$2] }
0708f913 1149 | topar parameter_type_list tcpar
708f4980 1150 { fun x -> mk_ty (FunctionType (x, $2)) [$1;$3] }
0708f913
C
1151/*(* subtle: here must also use topar, not TOPar, otherwise if have for
1152 * instance (xxx ( * )(xxx)) cast, then the second xxx may still be a Tident
ae4735db 1153 * but we want to reduce topar, to set the InParameter so that
0708f913
C
1154 * parsing_hack can get a chance to change the type of xxx into a typedef.
1155 * That's an example where parsing_hack and the lookahead of ocamlyacc does
ae4735db 1156 * not go very well together ... we got the info too late. We got
0708f913
C
1157 * a similar pb with xxx xxx; declaration, cf parsing_hack.ml and the
1158 * "disable typedef cos special case ..." message.
1159*)*/
1160 | direct_abstract_declarator topar tcpar
708f4980 1161 { fun x -> $1 (mk_ty (FunctionType (x, (([], (false, []))))) [$2;$3]) }
0708f913 1162 | direct_abstract_declarator topar parameter_type_list tcpar
708f4980 1163 { fun x -> $1 (mk_ty (FunctionType (x, $3)) [$2;$4]) }
485bce71
C
1164
1165/*(*-----------------------------------------------------------------------*)*/
1166/*(* Parameters (use decl_spec not type_spec just for 'register') *)*/
1167/*(*-----------------------------------------------------------------------*)*/
ae4735db 1168parameter_type_list:
34e49164
C
1169 | parameter_list { ($1, (false, []))}
1170 | parameter_list TComma TEllipsis { ($1, (true, [$2;$3])) }
1171
1172
ae4735db 1173parameter_decl2:
34e49164 1174 | decl_spec declaratorp
b1b2de81
C
1175 { let ((returnType,hasreg),iihasreg) = fixDeclSpecForParam $1 in
1176 let (name, ftyp) = $2 in
1177 { p_namei = Some (name);
1178 p_type = ftyp returnType;
1179 p_register = (hasreg, iihasreg);
1180 }
34e49164 1181 }
485bce71 1182 | decl_spec abstract_declaratorp
ae4735db 1183 { let ((returnType,hasreg), iihasreg) = fixDeclSpecForParam $1 in
b1b2de81
C
1184 { p_namei = None;
1185 p_type = $2 returnType;
1186 p_register = hasreg, iihasreg;
ae4735db 1187 }
34e49164
C
1188 }
1189 | decl_spec
b1b2de81
C
1190 { let ((returnType,hasreg), iihasreg) = fixDeclSpecForParam $1 in
1191 { p_namei = None;
1192 p_type = returnType;
1193 p_register = hasreg, iihasreg;
1194 }
34e49164
C
1195 }
1196
1197
1198/*(*----------------------------*)*/
1199/*(* workarounds *)*/
1200/*(*----------------------------*)*/
1201
485bce71 1202parameter_decl: parameter_decl2 { et "param" (); $1 }
708f4980 1203 | attributes parameter_decl2 { et "param" (); $2 }
34e49164 1204
ae4735db 1205declaratorp:
b1b2de81 1206 | declarator { LP.add_ident (str_of_name (fst $1)); $1 }
485bce71 1207 /*(* gccext: *)*/
b1b2de81
C
1208 | attributes declarator { LP.add_ident (str_of_name (fst $2)); $2 }
1209 | declarator attributes { LP.add_ident (str_of_name (fst $1)); $1 }
34e49164 1210
485bce71
C
1211abstract_declaratorp:
1212 | abstract_declarator { $1 }
1213 /*(* gccext: *)*/
1214 | attributes abstract_declarator { $2 }
1215
1216/*(*-----------------------------------------------------------------------*)*/
1217/*(* helper type rules *)*/
1218/*(*-----------------------------------------------------------------------*)*/
1219
1220/*(* for struct and also typename *)*/
1221/*(* cant put decl_spec cos no storage is allowed for field struct *)*/
ae4735db 1222spec_qualif_list2:
485bce71
C
1223 | type_spec { addTypeD ($1, nullDecl) }
1224 | type_qualif { {nullDecl with qualifD = (fst $1,[snd $1])}}
1225 | type_spec spec_qualif_list { addTypeD ($1,$2) }
1226 | type_qualif spec_qualif_list { addQualifD ($1,$2) }
1227
1228spec_qualif_list: spec_qualif_list2 { dt "spec_qualif" (); $1 }
1229
1230
1231/*(* for pointers in direct_declarator and abstract_declarator *)*/
ae4735db 1232type_qualif_list:
485bce71
C
1233 | type_qualif_attr { {nullDecl with qualifD = (fst $1,[snd $1])} }
1234 | type_qualif_list type_qualif_attr { addQualifD ($2,$1) }
34e49164 1235
34e49164
C
1236
1237
485bce71 1238
ae4735db 1239
485bce71
C
1240
1241/*(*-----------------------------------------------------------------------*)*/
1242/*(* xxx_type_id *)*/
34e49164 1243/*(*-----------------------------------------------------------------------*)*/
485bce71 1244
ae4735db
C
1245type_name:
1246 | spec_qualif_list
34e49164 1247 { let (returnType, _) = fixDeclSpecForDecl $1 in returnType }
485bce71 1248 | spec_qualif_list abstract_declaratort
34e49164
C
1249 { let (returnType, _) = fixDeclSpecForDecl $1 in $2 returnType }
1250
1251
34e49164 1252
ae4735db 1253abstract_declaratort:
485bce71
C
1254 | abstract_declarator { $1 }
1255 /*(* gccext: *)*/
1256 | attributes abstract_declarator { $2 }
1257
1258
1259/*(*************************************************************************)*/
1260/*(* declaration and initializers *)*/
1261/*(*************************************************************************)*/
1262
ae4735db 1263decl2:
485bce71
C
1264 | decl_spec TPtVirg
1265 { function local ->
ae4735db 1266 let (returnType,storage) = fixDeclSpecForDecl $1 in
485bce71 1267 let iistart = Ast_c.fakeInfo () in
ae4735db 1268 DeclList ([{v_namei = None; v_type = returnType;
485bce71
C
1269 v_storage = unwrap storage; v_local = local;
1270 v_attr = Ast_c.noattr;
978fd7e5 1271 v_type_bis = ref None;
ae4735db 1272 },[]],
485bce71 1273 ($2::iistart::snd storage))
ae4735db
C
1274 }
1275 | decl_spec init_declarator_list TPtVirg
485bce71
C
1276 { function local ->
1277 let (returnType,storage) = fixDeclSpecForDecl $1 in
1278 let iistart = Ast_c.fakeInfo () in
1279 DeclList (
ae4735db 1280 ($2 +> List.map (fun ((((name,f),attrs), ini), iivirg) ->
b1b2de81 1281 let s = str_of_name name in
ae4735db 1282 let iniopt =
485bce71 1283 match ini with
b1b2de81
C
1284 | None -> None
1285 | Some (ini, iini) -> Some (iini, ini)
485bce71 1286 in
ae4735db 1287 if fst (unwrap storage) =*= StoTypedef
485bce71 1288 then LP.add_typedef s;
b1b2de81 1289 {v_namei = Some (name, iniopt);
485bce71
C
1290 v_type = f returnType;
1291 v_storage = unwrap storage;
1292 v_local = local;
1293 v_attr = attrs;
978fd7e5 1294 v_type_bis = ref None;
485bce71 1295 },
ae4735db 1296 iivirg
485bce71
C
1297 )
1298 ), ($3::iistart::snd storage))
ae4735db 1299 }
485bce71
C
1300 /*(* cppext: *)*/
1301
ae4735db 1302 | TMacroDecl TOPar argument_list TCPar TPtVirg
485bce71
C
1303 { function _ ->
1304 MacroDecl ((fst $1, $3), [snd $1;$2;$4;$5;fakeInfo()]) }
ae4735db 1305 | Tstatic TMacroDecl TOPar argument_list TCPar TPtVirg
485bce71
C
1306 { function _ ->
1307 MacroDecl ((fst $2, $4), [snd $2;$3;$5;$6;fakeInfo();$1]) }
ae4735db 1308 | Tstatic TMacroDeclConst TMacroDecl TOPar argument_list TCPar TPtVirg
485bce71
C
1309 { function _ ->
1310 MacroDecl ((fst $3, $5), [snd $3;$4;$6;$7;fakeInfo();$1;$2])}
1311
1312
1313/*(*-----------------------------------------------------------------------*)*/
ae4735db 1314decl_spec2:
485bce71
C
1315 | storage_class_spec { {nullDecl with storageD = (fst $1, [snd $1]) } }
1316 | type_spec { addTypeD ($1,nullDecl) }
1317 | type_qualif { {nullDecl with qualifD = (fst $1, [snd $1]) } }
1318 | Tinline { {nullDecl with inlineD = (true, [$1]) } }
1319 | storage_class_spec decl_spec2 { addStorageD ($1, $2) }
1320 | type_spec decl_spec2 { addTypeD ($1, $2) }
1321 | type_qualif decl_spec2 { addQualifD ($1, $2) }
1322 | Tinline decl_spec2 { addInlineD ((true, $1), $2) }
1323
1324/*(* can simplify by putting all in _opt ? must have at least one otherwise
ae4735db 1325 * decl_list is ambiguous ? (no cos have ';' between decl)
485bce71
C
1326 *)*/
1327
1328
ae4735db 1329storage_class_spec2:
485bce71
C
1330 | Tstatic { Sto Static, $1 }
1331 | Textern { Sto Extern, $1 }
1332 | Tauto { Sto Auto, $1 }
1333 | Tregister { Sto Register,$1 }
1334 | Ttypedef { StoTypedef, $1 }
1335
1336storage_class_spec:
1337 /*(* gccext: *)*/
1338 | storage_class_spec2 { $1 }
708f4980 1339 | storage_class_spec2 attribute_storage_list { $1 (* TODO *) }
485bce71
C
1340
1341
1342
1343/*(*----------------------------*)*/
1344/*(* workarounds *)*/
1345/*(*----------------------------*)*/
1346
1347decl: decl2 { et "decl" (); $1 }
1348decl_spec: decl_spec2 { dt "declspec" (); $1 }
1349
1350/*(*-----------------------------------------------------------------------*)*/
1351/*(* declarators (right part of type and variable) *)*/
1352/*(*-----------------------------------------------------------------------*)*/
ae4735db 1353init_declarator2:
485bce71
C
1354 | declaratori { ($1, None) }
1355 | declaratori teq initialize { ($1, Some ($3, $2)) }
1356
1357
1358
1359/*(*----------------------------*)*/
1360/*(* workarounds *)*/
1361/*(*----------------------------*)*/
1362teq: TEq { et "teq" (); $1 }
1363
1364init_declarator: init_declarator2 { dt "init" (); $1 }
1365
1366
1367/*(*----------------------------*)*/
1368/*(* gccext: *)*/
1369/*(*----------------------------*)*/
1370
ae4735db 1371declaratori:
b1b2de81 1372 | declarator { LP.add_ident (str_of_name (fst $1)); $1, Ast_c.noattr }
485bce71 1373 /*(* gccext: *)*/
b1b2de81 1374 | declarator gcc_asm_decl { LP.add_ident (str_of_name (fst $1)); $1, Ast_c.noattr }
485bce71 1375 /*(* gccext: *)*/
b1b2de81
C
1376 | attributes declarator { LP.add_ident (str_of_name (fst $2)); $2, $1 }
1377 | declarator attributes { LP.add_ident (str_of_name (fst $1)); $1, Ast_c.noattr (* TODO *) }
485bce71
C
1378
1379
1380
ae4735db 1381gcc_asm_decl:
485bce71
C
1382 | Tasm TOPar asmbody TCPar { }
1383 | Tasm Tvolatile TOPar asmbody TCPar { }
1384
34e49164 1385
34e49164 1386/*(*-----------------------------------------------------------------------*)*/
ae4735db
C
1387initialize:
1388 | assign_expr
34e49164 1389 { InitExpr $1, [] }
485bce71 1390 | tobrace_ini initialize_list gcc_comma_opt_struct tcbrace_ini
34e49164 1391 { InitList (List.rev $2), [$1;$4]++$3 }
485bce71 1392 | tobrace_ini tcbrace_ini
34e49164
C
1393 { InitList [], [$1;$2] } /*(* gccext: *)*/
1394
1395
1396/*
ae4735db 1397(* opti: This time we use the weird order of non-terminal which requires in
0708f913 1398 * the "caller" to do a List.rev cos quite critical. With this weird order it
34e49164
C
1399 * allows yacc to use a constant stack space instead of exploding if we would
1400 * do a 'initialize2 Tcomma initialize_list'.
1401 *)
1402*/
ae4735db 1403initialize_list:
34e49164
C
1404 | initialize2 { [$1, []] }
1405 | initialize_list TComma initialize2 { ($3, [$2])::$1 }
1406
1407
1408/*(* gccext: condexpr and no assign_expr cos can have ambiguity with comma *)*/
ae4735db
C
1409initialize2:
1410 | cond_expr
1411 { InitExpr $1, [] }
485bce71 1412 | tobrace_ini initialize_list gcc_comma_opt_struct tcbrace_ini
34e49164 1413 { InitList (List.rev $2), [$1;$4]++$3 }
485bce71 1414 | tobrace_ini tcbrace_ini
34e49164
C
1415 { InitList [], [$1;$2] }
1416
1417 /*(* gccext: labeled elements, a.k.a designators *)*/
ae4735db 1418 | designator_list TEq initialize2
34e49164
C
1419 { InitDesignators ($1, $3), [$2] }
1420
1421 /*(* gccext: old format *)*/
1422 | ident TDotDot initialize2
1423 { InitFieldOld (fst $1, $3), [snd $1; $2] } /*(* in old kernel *)*/
ae4735db 1424/* conflict
34e49164
C
1425 | TOCro const_expr TCCro initialize2
1426 { InitIndexOld ($2, $4), [$1;$3] }
485bce71
C
1427*/
1428
1429
34e49164 1430
113803cf 1431/*(* they can be nested, can have a .x[3].y *)*/
ae4735db
C
1432designator:
1433 | TDot ident
1434 { DesignatorField (fst $2), [$1;snd $2] }
1435 | TOCro const_expr TCCro
34e49164 1436 { DesignatorIndex ($2), [$1;$3] }
ae4735db 1437 | TOCro const_expr TEllipsis const_expr TCCro
34e49164
C
1438 { DesignatorRange ($2, $4), [$1;$3;$5] }
1439
1440
1441/*(*----------------------------*)*/
1442/*(* workarounds *)*/
1443/*(*----------------------------*)*/
1444
ae4735db
C
1445gcc_comma_opt_struct:
1446 | TComma { [$1] }
34e49164
C
1447 | /*(* empty *)*/ { [Ast_c.fakeInfo() +> Ast_c.rewrap_str ","] }
1448
1449
34e49164
C
1450
1451
1452
1453
1454
1455
485bce71
C
1456/*(*************************************************************************)*/
1457/*(* struct *)*/
1458/*(*************************************************************************)*/
1459
ae4735db 1460s_or_u_spec2:
34e49164
C
1461 | struct_or_union ident tobrace_struct struct_decl_list_gcc tcbrace_struct
1462 { StructUnion (fst $1, Some (fst $2), $4), [snd $1;snd $2;$3;$5] }
1463 | struct_or_union tobrace_struct struct_decl_list_gcc tcbrace_struct
1464 { StructUnion (fst $1, None, $3), [snd $1;$2;$4] }
ae4735db 1465 | struct_or_union ident
34e49164
C
1466 { StructUnionName (fst $1, fst $2), [snd $1;snd $2] }
1467
ae4735db 1468struct_or_union2:
34e49164
C
1469 | Tstruct { Struct, $1 }
1470 | Tunion { Union, $1 }
485bce71
C
1471 /*(* gccext: *)*/
1472 | Tstruct attributes { Struct, $1 (* TODO *) }
1473 | Tunion attributes { Union, $1 (* TODO *) }
34e49164
C
1474
1475
1476
ae4735db 1477struct_decl2:
708f4980
C
1478 | field_declaration { DeclarationField $1 }
1479 | TPtVirg { EmptyField $1 }
1480
1481 /*(* no conflict ? no need for a TMacroStruct ? apparently not as at struct
1482 * the rule are slightly different.
1483 *)*/
1484 | identifier TOPar argument_list TCPar TPtVirg
1485 { MacroDeclField ((fst $1, $3), [snd $1;$2;$4;$5;fakeInfo()]) }
485bce71
C
1486
1487 /*(* cppext: *)*/
ae4735db 1488 | cpp_directive
708f4980 1489 { CppDirectiveStruct $1 }
ae4735db 1490 | cpp_ifdef_directive/*(* struct_decl_list ... *)*/
708f4980 1491 { IfdefStruct $1 }
485bce71
C
1492
1493
1494field_declaration:
ae4735db
C
1495 | spec_qualif_list struct_declarator_list TPtVirg
1496 {
34e49164 1497 let (returnType,storage) = fixDeclSpecForDecl $1 in
ae4735db 1498 if fst (unwrap storage) <> NoSto
34e49164 1499 then internal_error "parsing dont allow this";
ae4735db
C
1500
1501 FieldDeclList ($2 +> (List.map (fun (f, iivirg) ->
34e49164 1502 f returnType, iivirg))
485bce71 1503 ,[$3])
34e49164 1504 (* dont need to check if typedef or func initialised cos
ae4735db 1505 * grammar dont allow typedef nor initialiser in struct
34e49164
C
1506 *)
1507 }
1508
ae4735db
C
1509 | spec_qualif_list TPtVirg
1510 {
34e49164
C
1511 (* gccext: allow empty elements if it is a structdef or enumdef *)
1512 let (returnType,storage) = fixDeclSpecForDecl $1 in
ae4735db 1513 if fst (unwrap storage) <> NoSto
34e49164 1514 then internal_error "parsing dont allow this";
ae4735db 1515
b1b2de81 1516 FieldDeclList ([(Simple (None, returnType)) , []], [$2])
34e49164 1517 }
485bce71
C
1518
1519
34e49164
C
1520
1521
1522
ae4735db
C
1523struct_declarator:
1524 | declaratorsd
b1b2de81 1525 { (fun x -> Simple (Some (fst $1), (snd $1) x)) }
ae4735db 1526 | dotdot const_expr2
b1b2de81 1527 { (fun x -> BitField (None, x, $1, $2)) }
ae4735db 1528 | declaratorsd dotdot const_expr2
b1b2de81 1529 { (fun x -> BitField (Some (fst $1), ((snd $1) x), $2, $3)) }
34e49164
C
1530
1531
1532/*(*----------------------------*)*/
1533/*(* workarounds *)*/
1534/*(*----------------------------*)*/
ae4735db 1535declaratorsd:
485bce71
C
1536 | declarator { (*also ? LP.add_ident (fst (fst $1)); *) $1 }
1537 /*(* gccext: *)*/
1538 | attributes declarator { $2 }
1539 | declarator attributes { $1 }
34e49164 1540
34e49164
C
1541
1542
1543
1544struct_or_union_spec: s_or_u_spec2 { dt "su" (); $1 }
1545struct_or_union: struct_or_union2 { et "su" (); $1 }
1546struct_decl: struct_decl2 { et "struct" (); $1 }
1547
1548dotdot: TDotDot { et "dotdot" (); $1 }
1549const_expr2: const_expr { dt "const_expr2" (); $1 }
1550
ae4735db
C
1551struct_decl_list_gcc:
1552 | struct_decl_list { $1 }
34e49164
C
1553 | /*(* empty *)*/ { [] } /*(* gccext: allow empty struct *)*/
1554
1555
485bce71
C
1556/*(*************************************************************************)*/
1557/*(* enum *)*/
1558/*(*************************************************************************)*/
ae4735db 1559enum_spec:
485bce71 1560 | Tenum tobrace_enum enumerator_list gcc_comma_opt tcbrace_enum
34e49164 1561 { Enum (None, $3), [$1;$2;$5] ++ $4 }
485bce71 1562 | Tenum ident tobrace_enum enumerator_list gcc_comma_opt tcbrace_enum
34e49164 1563 { Enum (Some (fst $2), $4), [$1; snd $2; $3;$6] ++ $5 }
ae4735db 1564 | Tenum ident
34e49164
C
1565 { EnumName (fst $2), [$1; snd $2] }
1566
ae4735db 1567enumerator:
b1b2de81
C
1568 | idente { $1, None }
1569 | idente TEq const_expr { $1, Some ($2, $3) }
34e49164
C
1570
1571
1572/*(*----------------------------*)*/
1573/*(* workarounds *)*/
1574/*(*----------------------------*)*/
1575
b1b2de81 1576idente: ident_cpp { LP.add_ident (str_of_name $1); $1 }
34e49164 1577
34e49164
C
1578
1579
1580/*(*************************************************************************)*/
485bce71 1581/*(* function *)*/
34e49164 1582/*(*************************************************************************)*/
485bce71 1583function_definition: function_def { fixFunc $1 }
34e49164 1584
ae4735db 1585decl_list:
91eba41f
C
1586 | decl { [$1 Ast_c.LocalDecl] }
1587 | decl_list decl { $1 ++ [$2 Ast_c.LocalDecl] }
34e49164 1588
9f8e26f4 1589/* hack : to drop when a better solution is found */
ae4735db 1590cpp_directive_list:
9f8e26f4
C
1591 | cpp_directive { }
1592 | cpp_directive_list cpp_directive { }
1593
ae4735db 1594function_def:
91eba41f 1595 | start_fun compound { LP.del_scope(); ($1, $2, None) }
9f8e26f4 1596 | start_fun cpp_directive_list compound { LP.del_scope(); ($1, $3, None) }
ae4735db 1597 | start_fun decl_list compound {
485bce71 1598 (* TODO: undo the typedef added ? *)
ae4735db 1599 LP.del_scope();
91eba41f 1600 ($1, $3, Some $2)
485bce71
C
1601 }
1602
ae4735db
C
1603start_fun: start_fun2
1604 { LP.new_scope();
1605 fix_add_params_ident $1;
485bce71 1606 (* toreput? !LP._lexer_hint.toplevel <- false; *)
ae4735db 1607 $1
485bce71
C
1608 }
1609
ae4735db 1610start_fun2: decl_spec declaratorfd
485bce71
C
1611 { let (returnType,storage) = fixDeclSpecForFuncDef $1 in
1612 let (id, attrs) = $2 in
ae4735db 1613 (fst id, fixOldCDecl ((snd id) returnType) , storage, attrs)
485bce71
C
1614 }
1615
1616/*(*----------------------------*)*/
1617/*(* workarounds *)*/
1618/*(*----------------------------*)*/
1619
5636bb2c
C
1620/* It would be very nice if we could make declarator aware that this is
1621coming from a function definition. Then on the ( and ) cases, it could
1622set the state to something other than InParameter. Then the case
1623(TIdent (s, i1)::(TComma _|TCPar _)::_ , (TComma _ |TOPar _)::_ )
1624in parsing_hacks.ml would not have to consider K&R variable declarations
1625as typedefs. Unfortunately, doing something about this problem seems to
1626introduce conflicts in the parser. */
1627
ae4735db 1628declaratorfd:
485bce71
C
1629 | declarator { et "declaratorfd" (); $1, Ast_c.noattr }
1630 /*(* gccext: *)*/
1631 | attributes declarator { et "declaratorfd" (); $2, $1 }
1632 | declarator attributes { et "declaratorfd" (); $1, Ast_c.noattr }
1633
1634
1635
1636/*(*************************************************************************)*/
1637/*(* cpp directives *)*/
1638/*(*************************************************************************)*/
1639
ae4735db
C
1640cpp_directive:
1641 | TIncludeStart TIncludeFilename
1642 {
485bce71
C
1643 let (i1, in_ifdef) = $1 in
1644 let (s, i2) = $2 in
1645
1646 (* redo some lexing work :( *)
ae4735db 1647 let inc_file =
485bce71 1648 match () with
ae4735db 1649 | _ when s =~ "^\"\\(.*\\)\"$" ->
485bce71 1650 Local (Common.split "/" (matched1 s))
ae4735db 1651 | _ when s =~ "^\\<\\(.*\\)\\>$" ->
485bce71 1652 NonLocal (Common.split "/" (matched1 s))
ae4735db
C
1653 | _ ->
1654 Weird s
485bce71
C
1655 in
1656 Include { i_include = (inc_file, [i1;i2]);
1657 i_rel_pos = Ast_c.noRelPos();
1658 i_is_in_ifdef = !in_ifdef;
1659 i_content = Ast_c.noi_content;
1660 }
1661 }
1662
ae4735db 1663 | TDefine TIdentDefine define_val TDefEOL
485bce71
C
1664 { Define ((fst $2, [$1; snd $2;$4]), (DefineVar, $3)) }
1665
1666 /*
1667 (* The TOParDefine is introduced to avoid ambiguity with previous rules.
1668 * A TOParDefine is a TOPar that was just next to the ident.
1669 *)*/
1670 | TDefine TIdentDefine TOParDefine param_define_list TCPar define_val TDefEOL
ae4735db
C
1671 { Define
1672 ((fst $2, [$1; snd $2;$7]),
1673 (DefineFunc ($4, [$3;$5]), $6))
485bce71
C
1674 }
1675
b1b2de81 1676 | TUndef { Undef (fst $1, [snd $1]) }
485bce71
C
1677 | TCppDirectiveOther { PragmaAndCo ([$1]) }
1678
b1b2de81
C
1679
1680
1681
1682
ae4735db 1683/*(* perhaps better to use assign_expr ? but in that case need
485bce71
C
1684 * do a assign_expr_of_string in parse_c
1685 *)*/
ae4735db 1686define_val:
485bce71
C
1687 | expr { DefineExpr $1 }
1688 | statement { DefineStmt $1 }
708f4980
C
1689 | decl { DefineStmt (mk_st (Decl ($1 Ast_c.NotLocalDecl)) Ast_c.noii) }
1690
ae4735db 1691/*(*old:
708f4980 1692 * | TypedefIdent { DefineType (nQ,(TypeName(fst $1,noTypedefDef()),[snd $1]))}
ae4735db 1693 * get conflicts:
708f4980
C
1694 * | spec_qualif_list TMul
1695 * { let (returnType, _) = fixDeclSpecForDecl $1 in DefineType returnType }
1696 *)
1697*/
ae4735db
C
1698 | decl_spec
1699 { let returnType = fixDeclSpecForMacro $1 in
708f4980
C
1700 DefineType returnType
1701 }
ae4735db
C
1702 | decl_spec abstract_declarator
1703 { let returnType = fixDeclSpecForMacro $1 in
708f4980
C
1704 let typ = $2 returnType in
1705 DefineType typ
1706 }
1707
ae4735db 1708/* can be in conflict with decl_spec, maybe change fixDeclSpecForMacro
708f4980
C
1709 * to also allow storage ?
1710 | storage_class_spec { DefineTodo }
1711 | Tinline { DefineTodo }
1712*/
1713
1714 /*(* a few special cases *)*/
1715 | stat_or_decl stat_or_decl_list { DefineTodo }
1716/*
1717 | statement statement { DefineTodo }
1718 | decl function_definition { DefineTodo }
1719*/
1720
1721
1722
485bce71 1723
485bce71
C
1724 | function_definition { DefineFunction $1 }
1725
ae4735db 1726 | TOBraceDefineInit initialize_list gcc_comma_opt_struct TCBrace comma_opt
485bce71
C
1727 { DefineInit (InitList (List.rev $2), [$1;$4]++$3++$5) }
1728
1729 /*(* note: had a conflict before when were putting TInt instead of expr *)*/
ae4735db 1730 | Tdo statement Twhile TOPar expr TCPar
485bce71 1731 {
ae4735db
C
1732 (* TOREPUT
1733 if fst $5 <> "0"
0708f913 1734 then pr2 "WEIRD: in macro and have not a while(0)";
485bce71
C
1735 *)
1736 DefineDoWhileZero (($2,$5), [$1;$3;$4;$6])
1737 }
1738
485bce71
C
1739 | Tasm TOPar asmbody TCPar { DefineTodo }
1740 | Tasm Tvolatile TOPar asmbody TCPar { DefineTodo }
1741
485bce71
C
1742 /*(* aliases macro *)*/
1743 | TMacroAttr { DefineTodo }
485bce71
C
1744
1745 | /*(* empty *)*/ { DefineEmpty }
1746
1747
b1b2de81
C
1748
1749
485bce71 1750param_define:
ae4735db
C
1751 | TIdent { mk_string_wrap $1 }
1752 | TypedefIdent { mk_string_wrap $1 }
1753 | TDefParamVariadic { mk_string_wrap $1 }
485bce71
C
1754 | TEllipsis { "...", [$1] }
1755 /*(* they reuse keywords :( *)*/
1756 | Tregister { "register", [$1] }
1757
1758
1759
1760
ae4735db
C
1761cpp_ifdef_directive:
1762 | TIfdef
1763 { let (tag,ii) = $1 in
485bce71 1764 IfdefDirective ((Ifdef, IfdefTag (Common.some !tag)), [ii]) }
ae4735db
C
1765 | TIfdefelse
1766 { let (tag,ii) = $1 in
485bce71 1767 IfdefDirective ((IfdefElse, IfdefTag (Common.some !tag)), [ii]) }
ae4735db
C
1768 | TIfdefelif
1769 { let (tag,ii) = $1 in
485bce71 1770 IfdefDirective ((IfdefElseif, IfdefTag (Common.some !tag)), [ii]) }
ae4735db
C
1771 | TEndif
1772 { let (tag,ii) = $1 in
485bce71
C
1773 IfdefDirective ((IfdefEndif, IfdefTag (Common.some !tag)), [ii]) }
1774
ae4735db
C
1775 | TIfdefBool
1776 { let (_b, tag,ii) = $1 in
485bce71 1777 IfdefDirective ((Ifdef, IfdefTag (Common.some !tag)), [ii]) }
ae4735db
C
1778 | TIfdefMisc
1779 { let (_b, tag,ii) = $1 in
485bce71 1780 IfdefDirective ((Ifdef, IfdefTag (Common.some !tag)), [ii]) }
ae4735db
C
1781 | TIfdefVersion
1782 { let (_b, tag,ii) = $1 in
485bce71
C
1783 IfdefDirective ((Ifdef, IfdefTag (Common.some !tag)), [ii]) }
1784
1785
1786/*(* cppext: *)*/
ae4735db 1787cpp_other:
485bce71
C
1788 /*(* no conflict ? no need for a TMacroTop ? apparently not as at toplevel
1789 * the rule are slightly different, they cant be statement and so expr
1790 * at the top, only decl or function definition.
1791 *)*/
1792 | identifier TOPar argument_list TCPar TPtVirg
ae4735db
C
1793 {
1794 Declaration (MacroDecl ((fst $1, $3), [snd $1;$2;$4;$5;fakeInfo()]))
708f4980
C
1795 (* old: MacroTop (fst $1, $3, [snd $1;$2;$4;$5]) *)
1796 }
485bce71
C
1797
1798 /*(* TCParEOL to fix the end-of-stream bug of ocamlyacc *)*/
1799 | identifier TOPar argument_list TCParEOL
ae4735db 1800 { MacroTop (fst $1, $3, [snd $1;$2;$4;fakeInfo()]) }
485bce71
C
1801
1802 /*(* ex: EXPORT_NO_SYMBOLS; *)*/
1803 | identifier TPtVirg { EmptyDef [snd $1;$2] }
1804
1805
1806
1807/*(*************************************************************************)*/
1808/*(* celem *)*/
1809/*(*************************************************************************)*/
1810
ae4735db 1811external_declaration:
485bce71
C
1812 | function_definition { Definition $1 }
1813 | decl { Declaration ($1 Ast_c.NotLocalDecl) }
1814
1815
ae4735db 1816celem:
485bce71
C
1817 | external_declaration { $1 }
1818
1819 /*(* cppext: *)*/
ae4735db 1820 | cpp_directive
485bce71 1821 { CppTop $1 }
ae4735db 1822 | cpp_other
485bce71
C
1823 { $1 }
1824 | cpp_ifdef_directive /* (*external_declaration_list ...*)*/
1825 { IfdefTop $1 }
1826
1827 /*(* can have asm declaration at toplevel *)*/
ae4735db 1828 | Tasm TOPar asmbody TCPar TPtVirg { EmptyDef [$1;$2;$4;$5] }
485bce71
C
1829
1830 /*
1831 (* in ~/kernels/src/linux-2.5.2/drivers/isdn/hisax/isdnl3.c sometimes
ae4735db 1832 * the function ends with }; instead of just }
485bce71
C
1833 * can also remove this rule and report "parse error" pb to morton
1834 *)*/
ae4735db
C
1835 | TPtVirg { EmptyDef [$1] }
1836
485bce71 1837
ae4735db 1838 | EOF { FinalDef $1 }
485bce71
C
1839
1840
1841
1842
1843/*(*************************************************************************)*/
1844/*(* some generic workarounds *)*/
1845/*(*************************************************************************)*/
1846
1847tobrace: TOBrace { LP.push_context LP.InFunction; LP.new_scope (); $1 }
1848tcbrace: TCBrace { LP.pop_context(); LP.del_scope (); $1 }
1849
1850tobrace_enum: TOBrace { LP.push_context LP.InEnum; $1 }
1851tcbrace_enum: TCBrace { LP.pop_context (); $1 }
1852
1853tobrace_ini: TOBrace { LP.push_context LP.InInitializer; $1 }
1854tcbrace_ini: TCBrace { LP.pop_context (); $1 }
1855
1856tobrace_struct: TOBrace { LP.push_context LP.InStruct; $1}
1857tcbrace_struct: TCBrace { LP.pop_context (); $1 }
1858
1859
1860
1861
ae4735db
C
1862topar: TOPar
1863 { LP.new_scope ();et "topar" ();
485bce71 1864 LP.push_context LP.InParameter;
ae4735db 1865 $1
485bce71 1866 }
ae4735db
C
1867tcpar: TCPar
1868 { LP.del_scope ();dt "tcpar" ();
1869 LP.pop_context ();
1870 $1
485bce71
C
1871 }
1872
1873
1874
1875
1876/*(*************************************************************************)*/
1877/*(* xxx_list, xxx_opt *)*/
1878/*(*************************************************************************)*/
1879
1880
1881/*(* old:
ae4735db 1882compound2:
485bce71
C
1883 | { ([],[]) }
1884 | statement_list { ([], $1) }
1885 | decl_list { ($1, []) }
1886 | decl_list statement_list { ($1,$2) }
1887
1888statement_list: stat_or_decl_list { $1 }
1889*)*/
1890
1891
1892/*(*
ae4735db 1893decl_list:
485bce71
C
1894 | decl { [$1] }
1895 | decl_list decl { $1 ++ [$2] }
1896
ae4735db 1897statement_list:
485bce71
C
1898 | statement { [$1] }
1899 | statement_list statement { $1 ++ [$2] }
1900*)*/
34e49164 1901
34e49164
C
1902
1903
1904
1905
ae4735db 1906string_list:
34e49164 1907 | string_elem { $1 }
ae4735db 1908 | string_list string_elem { $1 ++ $2 }
34e49164 1909
ae4735db 1910colon_asm_list:
34e49164
C
1911 | colon_asm { [$1] }
1912 | colon_asm_list colon_asm { $1 ++ [$2] }
1913
ae4735db
C
1914colon_option_list:
1915 | colon_option { [$1, []] }
34e49164
C
1916 | colon_option_list TComma colon_option { $1 ++ [$3, [$2]] }
1917
1918
ae4735db 1919argument_list_ne:
34e49164
C
1920 | argument_ne { [$1, []] }
1921 | argument_list_ne TComma argument { $1 ++ [$3, [$2]] }
1922
ae4735db 1923argument_list:
34e49164
C
1924 | argument { [$1, []] }
1925 | argument_list TComma argument { $1 ++ [$3, [$2]] }
1926
1927/*(*
1928expression_list:
1929 | assign_expr { [$1, []] }
1930 | expression_list TComma assign_expr { $1 ++ [$3, [$2]] }
1931*)*/
1932
1933
ae4735db 1934struct_decl_list:
34e49164
C
1935 | struct_decl { [$1] }
1936 | struct_decl_list struct_decl { $1 ++ [$2] }
1937
1938
ae4735db 1939struct_declarator_list:
34e49164
C
1940 | struct_declarator { [$1, []] }
1941 | struct_declarator_list TComma struct_declarator { $1 ++ [$3, [$2]] }
1942
1943
ae4735db 1944enumerator_list:
34e49164
C
1945 | enumerator { [$1, []] }
1946 | enumerator_list TComma enumerator { $1 ++ [$3, [$2]] }
1947
1948
ae4735db 1949init_declarator_list:
34e49164
C
1950 | init_declarator { [$1, []] }
1951 | init_declarator_list TComma init_declarator { $1 ++ [$3, [$2]] }
1952
1953
ae4735db 1954parameter_list:
34e49164
C
1955 | parameter_decl { [$1, []] }
1956 | parameter_list TComma parameter_decl { $1 ++ [$3, [$2]] }
1957
ae4735db 1958taction_list_ne:
34e49164
C
1959 | TAction { [$1] }
1960 | TAction taction_list_ne { $1 :: $2 }
1961
ae4735db
C
1962taction_list:
1963/*old: was generating conflict, hence now taction_list_ne
485bce71
C
1964 | (* empty *) { [] }
1965 | TAction { [$1] }
1966 | taction_list TAction { $1 ++ [$2] }
1967*/
34e49164
C
1968 | { [] }
1969 | TAction taction_list { $1 :: $2 }
1970
ae4735db 1971param_define_list:
34e49164
C
1972 | /*(* empty *)*/ { [] }
1973 | param_define { [$1, []] }
1974 | param_define_list TComma param_define { $1 ++ [$3, [$2]] }
1975
ae4735db 1976designator_list:
34e49164
C
1977 | designator { [$1] }
1978 | designator_list designator { $1 ++ [$2] }
1979
485bce71
C
1980attribute_list:
1981 | attribute { [$1] }
1982 | attribute_list attribute { $1 ++ [$2] }
1983
1984attribute_storage_list:
1985 | attribute_storage { [$1] }
1986 | attribute_storage_list attribute_storage { $1 ++ [$2] }
1987
1988
1989attributes: attribute_list { $1 }
1990
485bce71 1991
34e49164
C
1992
1993/*(* gccext: which allow a trailing ',' in enum, as in perl *)*/
ae4735db
C
1994gcc_comma_opt:
1995 | TComma { [$1] }
34e49164
C
1996 | /*(* empty *)*/ { [] }
1997
ae4735db
C
1998comma_opt:
1999 | TComma { [$1] }
485bce71
C
2000 | /*(* empty *)*/ { [] }
2001
34e49164
C
2002/*(*
2003gcc_opt_virg:
2004 | TPtVirg { }
2005 | { }
2006*)*/
2007
ae4735db 2008gcc_opt_expr:
34e49164
C
2009 | expr { Some $1 }
2010 | /*(* empty *)*/ { None }
2011
2012/*(*
2013opt_ptvirg:
2014 | TPtVirg { [$1] }
2015 | { [] }
2016*)*/
2017
2018
ae4735db 2019expr_opt:
485bce71
C
2020 | expr { Some $1 }
2021 | /*(* empty *)*/ { None }
34e49164 2022