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