Release coccinelle-0.2.0rc1
[bpt/coccinelle.git] / parsing_cocci / parser_cocci_menhir.mly
CommitLineData
34e49164
C
1%{
2
3(* Not clear how to allow function declarations to specify a return type
4and how to allow both to be specified as static, because they are in
5different rules. The rules seem to have to be combined, which would allow
6functions to be declared as local variables *)
7
8(* Not clear how to let a function have a parameter of type void. At the
9moment, void is allowed to be the type of a variable, which is wrong, and a
10parameter needs both a type and an identifier *)
11module Ast0 = Ast0_cocci
12module Ast = Ast_cocci
13module P = Parse_aux
14%}
15
16%token EOF
17
18%token TIdentifier TExpression TStatement TFunction TLocal TType TParameter
113803cf 19%token TIdExpression TInitialiser
34e49164 20%token Tlist TFresh TConstant TError TWords TWhy0 TPlus0 TBang0
faf9a90c 21%token TPure TContext TGenerated
34e49164 22%token TTypedef TDeclarer TIterator TName TPosition TPosAny
faf9a90c 23%token TUsing TDisable TExtends TDepends TOn TEver TNever TExists TForall
951c7801 24%token TScript TInitialize TFinalize TNothing TVirtual
34e49164
C
25%token<string> TRuleName
26
27%token<Data.clt> Tchar Tshort Tint Tdouble Tfloat Tlong
faf9a90c 28%token<Data.clt> Tvoid Tstruct Tunion Tenum
34e49164
C
29%token<Data.clt> Tunsigned Tsigned
30
31%token<Data.clt> Tstatic Tauto Tregister Textern Tinline Ttypedef
32%token<Data.clt> Tconst Tvolatile
33%token<string * Data.clt> Tattr
34
35%token <Data.clt> TIf TElse TWhile TFor TDo TSwitch TCase TDefault TReturn
36%token <Data.clt> TBreak TContinue TGoto TSizeof TFunDecl
0708f913 37%token <string * Data.clt> TIdent TTypeId TDeclarerId TIteratorId TPragma
34e49164 38
951c7801
C
39%token <Parse_aux.idinfo> TMetaId TMetaFunc TMetaLocalFunc
40%token <Parse_aux.idinfo> TMetaIterator TMetaDeclarer
41%token <Parse_aux.expinfo> TMetaErr
42%token <Parse_aux.info> TMetaParam TMetaStm TMetaStmList TMetaType
43%token <Parse_aux.info> TMetaInit
44%token <Parse_aux.list_info> TMetaParamList TMetaExpList
45%token <Parse_aux.typed_expinfo> TMetaExp TMetaIdExp TMetaLocalIdExp TMetaConst
46%token <Parse_aux.pos_info> TMetaPos
34e49164
C
47
48%token TArob TArobArob TPArob
49%token <string> TScriptData
50
51%token <Data.clt> TEllipsis TOEllipsis TCEllipsis TPOEllipsis TPCEllipsis
1be43e12 52%token <Data.clt> TWhen TWhenTrue TWhenFalse TAny TStrict TLineEnd
34e49164
C
53
54%token <Data.clt> TWhy TDotDot TBang TOPar TOPar0
55%token <Data.clt> TMid0 TCPar TCPar0
56
0708f913 57%token <string> TPathIsoFile
34e49164
C
58%token <string * Data.clt> TIncludeL TIncludeNL
59%token <Data.clt * token> TDefine
708f4980 60%token <Data.clt * token * int * int> TDefineParam
34e49164
C
61%token <string * Data.clt> TMinusFile TPlusFile
62
63%token <Data.clt> TInc TDec
64
65%token <string * Data.clt> TString TChar TFloat TInt
66
67%token <Data.clt> TOrLog
68%token <Data.clt> TAndLog
69%token <Data.clt> TOr
70%token <Data.clt> TXor
faf9a90c 71%token <Data.clt> TAnd
951c7801 72%token <Data.clt> TEqEq TNotEq TTildeEq TTildeExclEq
34e49164
C
73%token <Ast_cocci.logicalOp * Data.clt> TLogOp /* TInf TSup TInfEq TSupEq */
74%token <Ast_cocci.arithOp * Data.clt> TShOp /* TShl TShr */
75%token <Ast_cocci.arithOp * Data.clt> TDmOp /* TDiv TMod */
76%token <Data.clt> TPlus TMinus
77%token <Data.clt> TMul TTilde
78
1be43e12 79%token <Data.clt> TOBrace TCBrace TOInit
34e49164
C
80%token <Data.clt> TOCro TCCro
81
82%token <Data.clt> TPtrOp
83
978fd7e5 84%token TMPtVirg TCppConcatOp
34e49164
C
85%token <Data.clt> TEq TDot TComma TPtVirg
86%token <Ast_cocci.assignOp * Data.clt> TAssign
87
88%token TIso TRightIso TIsoExpression TIsoStatement TIsoDeclaration TIsoType
89%token TIsoTopLevel TIsoArgExpression TIsoTestExpression
90
91%token TInvalid
92
93/* operator precedence */
94%nonassoc TIf
95%nonassoc TElse
96
97%left TOrLog
98%left TAndLog
99%left TOr
100%left TXor
faf9a90c 101%left TAnd
34e49164
C
102%left TEqEq TNotEq
103%left TLogOp /* TInf TSup TInfEq TSupEq */
104%left TShOp /* TShl TShr */
105%left TPlus TMinus
106%left TMul TDmOp /* TDiv TMod */
107
108%start reinit
109%type <unit> reinit
110
111%start minus_main
112%type <Ast0_cocci.rule> minus_main
113
114%start minus_exp_main
115%type <Ast0_cocci.rule> minus_exp_main
116
117%start plus_main
118%type <Ast0_cocci.rule> plus_main
119
120%start plus_exp_main
121%type <Ast0_cocci.rule> plus_exp_main
122
123%start include_main
978fd7e5 124%type <Data.incl_iso list> include_main
34e49164
C
125
126%start iso_rule_name
127%type <Ast_cocci.rulename>
128iso_rule_name
129
130%start rule_name
131%type <Ast_cocci.rulename>
132rule_name
133
134%start meta_main
135%type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> meta_main
136
137%start <string * (string * string)> script_meta_main
138
139%start iso_main
140%type <Ast0_cocci.anything list list> iso_main
141
142%start iso_meta_main
143%type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> iso_meta_main
144
145%start never_used
146%type <unit> never_used
147
148%%
149
150reinit: { }
151minus_main: minus_body EOF { $1 } | m=minus_body TArobArob { m }
152| m=minus_body TArob { m }
153plus_main: plus_body EOF { $1 } | p=plus_body TArobArob { p }
154| p=plus_body TArob { p }
155minus_exp_main: minus_exp_body EOF { $1 } | m=minus_exp_body TArobArob { m }
156| m=minus_exp_body TArob { m }
157plus_exp_main: plus_exp_body EOF { $1 } | p=plus_exp_body TArobArob { p }
158| p=plus_exp_body TArob { p }
159meta_main: m=metadec { m (!Ast0.rule_name) }
160iso_meta_main: m=metadec { m "" }
161
162/*****************************************************************************
163*
164*
165*****************************************************************************/
166
167pure:
168 TPure { Ast0.Pure }
169| TContext { Ast0.Context }
170| TPure TContext { Ast0.PureContext }
171| TContext TPure { Ast0.PureContext }
172| /* empty */ { Ast0.Impure }
173
174iso_rule_name:
175 nm=pure_ident TArob { P.make_iso_rule_name_result (P.id2name nm) }
176
177rule_name:
178 nm=ioption(pure_ident) extends d=depends i=loption(choose_iso)
179 a=loption(disable) e=exists ee=is_expression TArob
180 { P.make_cocci_rule_name_result nm d i a e ee }
faf9a90c
C
181 | TGenerated extends d=depends i=loption(choose_iso)
182 a=loption(disable) e=exists ee=is_expression TArob
183 /* these rules have no name as a cheap way to ensure that no normal
184 rule inherits their metavariables or depends on them */
185 { P.make_generated_rule_name_result None d i a e ee }
1be43e12
C
186 | TScript TDotDot lang=pure_ident d=depends TArob
187 { P.make_script_rule_name_result lang d }
b1b2de81
C
188 | TInitialize TDotDot lang=pure_ident TArob
189 { P.make_initial_script_rule_name_result lang }
190 | TFinalize TDotDot lang=pure_ident TArob
191 { P.make_final_script_rule_name_result lang }
34e49164
C
192
193extends:
194 /* empty */ { () }
195| TExtends parent=TRuleName
196 { !Data.install_bindings (parent) }
197
198depends:
199 /* empty */ { Ast.NoDep }
200| TDepends TOn parents=dep { parents }
201
202dep:
203 pnrule { $1 }
204| dep TAndLog dep { Ast.AndDep($1, $3) }
205| dep TOrLog dep { Ast.OrDep ($1, $3) }
206
207pnrule:
208 TRuleName { Ast.Dep $1 }
209| TBang TRuleName { Ast.AntiDep $2 }
210| TEver TRuleName { Ast.EverDep $2 }
211| TNever TRuleName { Ast.NeverDep $2 }
212| TOPar dep TCPar { $2 }
213
214choose_iso:
215 TUsing separated_nonempty_list(TComma,TString) { List.map P.id2name $2 }
216
217disable:
218 TDisable separated_nonempty_list(TComma,pure_ident) { List.map P.id2name $2 }
219
220exists:
221 TExists { Ast.Exists }
222| TForall { Ast.Forall }
34e49164
C
223| { Ast.Undetermined }
224
225is_expression: // for more flexible parsing of top level expressions
226 { false }
227| TExpression { true }
228
229include_main:
230 list(incl) TArob { $1 }
231| list(incl) TArobArob { $1 }
232
233incl:
978fd7e5
C
234 TIncludeL { let (x,_) = $1 in Data.Include(x) }
235| TUsing TString { Data.Iso(Common.Left(P.id2name $2)) }
236| TUsing TPathIsoFile { Data.Iso(Common.Right $2) }
951c7801
C
237| TVirtual comma_list(pure_ident)
238 { let names = List.map P.id2name $2 in
239 (* ensure that the names of virtual and real rules don't overlap *)
240 List.iter
241 (function name -> Hashtbl.add Data.all_metadecls name [])
242 names;
243 Data.Virt(names) }
34e49164
C
244
245metadec:
246 ar=arity ispure=pure
247 kindfn=metakind ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
248 { P.create_metadec ar ispure kindfn ids }
b1b2de81
C
249| kindfn=metakind_fresh ids=comma_list(pure_ident_or_meta_ident_with_seed)
250 TMPtVirg
251 { P.create_fresh_metadec kindfn ids }
34e49164
C
252| ar=arity ispure=pure
253 kindfn=metakind_atomic
7f004419
C
254 ids=comma_list(pure_ident_or_meta_ident_with_idconstraint(re_or_not_eqid))
255 TMPtVirg
951c7801 256 { P.create_metadec_with_constraints ar ispure kindfn ids }
34e49164
C
257| ar=arity ispure=pure
258 kindfn=metakind_atomic_expi
7f004419
C
259 ids=comma_list(pure_ident_or_meta_ident_with_econstraint(re_or_not_eqe))
260 TMPtVirg
951c7801 261 { P.create_metadec_with_constraints ar ispure kindfn ids }
34e49164
C
262| ar=arity ispure=pure
263 kindfn=metakind_atomic_expe
951c7801
C
264 ids=comma_list(pure_ident_or_meta_ident_with_x_eq(not_ceq)) TMPtVirg
265 { P.create_metadec_with_constraints ar ispure kindfn ids }
34e49164 266| ar=arity TPosition a=option(TPosAny)
951c7801 267 ids=comma_list(pure_ident_or_meta_ident_with_x_eq(not_pos)) TMPtVirg
faf9a90c
C
268 (* pb: position variables can't be inherited from normal rules, and then
269 there is no way to inherit from a generated rule, so there is no point
270 to have a position variable *)
271 { (if !Data.in_generating
272 then failwith "position variables not allowed in a generated rule file");
273 let kindfn arity name pure check_meta constraints =
34e49164
C
274 let tok = check_meta(Ast.MetaPosDecl(arity,name)) in
275 let any = match a with None -> Ast.PER | Some _ -> Ast.ALL in
276 !Data.add_pos_meta name constraints any; tok in
951c7801 277 P.create_metadec_with_constraints ar false kindfn ids }
34e49164
C
278| ar=arity ispure=pure
279 TParameter Tlist TOCro id=pure_ident_or_meta_ident TCCro
280 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
281 { P.create_len_metadec ar ispure
282 (fun lenname arity name pure check_meta ->
283 let tok =
284 check_meta(Ast.MetaParamListDecl(arity,name,Some lenname)) in
285 !Data.add_paramlist_meta name (Some lenname) pure; tok)
286 id ids }
287| ar=arity ispure=pure
288 TExpression Tlist TOCro id=pure_ident_or_meta_ident TCCro
289 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
290 { P.create_len_metadec ar ispure
291 (fun lenname arity name pure check_meta ->
292 let tok =
293 check_meta(Ast.MetaExpListDecl(arity,name,Some lenname)) in
294 !Data.add_explist_meta name (Some lenname) pure; tok)
295 id ids }
296
b1b2de81 297%inline metakind_fresh:
34e49164 298 TFresh TIdentifier
b1b2de81
C
299 { (fun name check_meta seed ->
300 let tok = check_meta(Ast.MetaFreshIdDecl(name,seed)) in
301 !Data.add_fresh_id_meta name; tok) }
302
303%inline metakind:
304 TParameter
34e49164
C
305 { (fun arity name pure check_meta ->
306 let tok = check_meta(Ast.MetaParamDecl(arity,name)) in
307 !Data.add_param_meta name pure; tok) }
308| TParameter Tlist
309 { (fun arity name pure check_meta ->
310 let tok = check_meta(Ast.MetaParamListDecl(arity,name,None)) in
311 !Data.add_paramlist_meta name None pure; tok) }
312| TExpression Tlist
313 { (fun arity name pure check_meta ->
314 let tok = check_meta(Ast.MetaExpListDecl(arity,name,None)) in
315 !Data.add_explist_meta name None pure; tok) }
316| TType
317 { (fun arity name pure check_meta ->
318 let tok = check_meta(Ast.MetaTypeDecl(arity,name)) in
faf9a90c 319 !Data.add_type_meta name pure; tok) }
113803cf
C
320| TInitialiser
321 { (fun arity name pure check_meta ->
322 let tok = check_meta(Ast.MetaInitDecl(arity,name)) in
323 !Data.add_init_meta name pure; tok) }
34e49164
C
324| TStatement
325 { (fun arity name pure check_meta ->
326 let tok = check_meta(Ast.MetaStmDecl(arity,name)) in
327 !Data.add_stm_meta name pure; tok) }
328| TStatement Tlist
329 { (fun arity name pure check_meta ->
330 let tok = check_meta(Ast.MetaStmListDecl(arity,name)) in
331 !Data.add_stmlist_meta name pure; tok) }
332| TTypedef
333 { (fun arity (_,name) pure check_meta ->
334 if arity = Ast.NONE && pure = Ast0.Impure
335 then (!Data.add_type_name name; [])
336 else raise (Semantic_cocci.Semantic "bad typedef")) }
337| TDeclarer TName
338 { (fun arity (_,name) pure check_meta ->
339 if arity = Ast.NONE && pure = Ast0.Impure
340 then (!Data.add_declarer_name name; [])
341 else raise (Semantic_cocci.Semantic "bad declarer")) }
342| TIterator TName
343 { (fun arity (_,name) pure check_meta ->
344 if arity = Ast.NONE && pure = Ast0.Impure
345 then (!Data.add_iterator_name name; [])
346 else raise (Semantic_cocci.Semantic "bad iterator")) }
347
34e49164
C
348%inline metakind_atomic:
349 TIdentifier
350 { (fun arity name pure check_meta constraints ->
351 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
352 !Data.add_id_meta name constraints pure; tok) }
353| TFunction
354 { (fun arity name pure check_meta constraints ->
355 let tok = check_meta(Ast.MetaFuncDecl(arity,name)) in
356 !Data.add_func_meta name constraints pure; tok) }
357| TLocal TFunction
358 { (fun arity name pure check_meta constraints ->
359 let tok = check_meta(Ast.MetaLocalFuncDecl(arity,name)) in
360 !Data.add_local_func_meta name constraints pure;
361 tok) }
362| TDeclarer
363 { (fun arity name pure check_meta constraints ->
364 let tok = check_meta(Ast.MetaDeclarerDecl(arity,name)) in
365 !Data.add_declarer_meta name constraints pure; tok) }
366| TIterator
367 { (fun arity name pure check_meta constraints ->
368 let tok = check_meta(Ast.MetaIteratorDecl(arity,name)) in
369 !Data.add_iterator_meta name constraints pure; tok) }
370
371%inline metakind_atomic_expi:
372 TError
373 { (fun arity name pure check_meta constraints ->
374 let tok = check_meta(Ast.MetaErrDecl(arity,name)) in
375 !Data.add_err_meta name constraints pure; tok) }
376| l=option(TLocal) TIdExpression ty=ioption(meta_exp_type)
377 { (fun arity name pure check_meta constraints ->
378 match l with
379 None ->
380 !Data.add_idexp_meta ty name constraints pure;
381 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
382 | Some _ ->
383 !Data.add_local_idexp_meta ty name constraints pure;
384 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
385| l=option(TLocal) TIdExpression m=nonempty_list(TMul)
386 { (fun arity name pure check_meta constraints ->
387 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
388 match l with
389 None ->
390 !Data.add_idexp_meta ty name constraints pure;
391 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
392 | Some _ ->
393 !Data.add_local_idexp_meta ty name constraints pure;
394 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
395| TExpression m=nonempty_list(TMul)
396 { (fun arity name pure check_meta constraints ->
397 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
398 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
399 !Data.add_exp_meta ty name constraints pure; tok) }
400| vl=meta_exp_type TOCro TCCro
401 { (fun arity name pure check_meta constraints ->
402 let ty = Some (List.map (function x -> Type_cocci.Array x) vl) in
403 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
404 !Data.add_exp_meta ty name constraints pure; tok) }
405| TConstant ty=ioption(meta_exp_type)
406 { (fun arity name pure check_meta constraints ->
407 let tok = check_meta(Ast.MetaConstDecl(arity,name,ty)) in
408 !Data.add_const_meta ty name constraints pure; tok) }
409
410%inline metakind_atomic_expe:
411 TExpression
412 { (fun arity name pure check_meta constraints ->
413 let tok = check_meta(Ast.MetaExpDecl(arity,name,None)) in
951c7801 414 !Data.add_exp_meta None name (Ast0.NotExpCstrt constraints) pure; tok) }
34e49164
C
415| vl=meta_exp_type // no error if use $1 but doesn't type check
416 { (fun arity name pure check_meta constraints ->
417 let ty = Some vl in
418 List.iter
419 (function c ->
420 match Ast0.unwrap c with
421 Ast0.Constant(_) ->
422 if not
423 (List.exists
424 (function
faf9a90c
C
425 Type_cocci.BaseType(Type_cocci.IntType) -> true
426 | Type_cocci.BaseType(Type_cocci.ShortType) -> true
427 | Type_cocci.BaseType(Type_cocci.LongType) -> true
34e49164
C
428 | _ -> false)
429 vl)
430 then failwith "metavariable with int constraint must be an int"
431 | _ -> ())
432 constraints;
433 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
951c7801
C
434 !Data.add_exp_meta ty name (Ast0.NotExpCstrt constraints) pure; tok)
435 }
34e49164
C
436
437
438meta_exp_type:
978fd7e5 439 t=typedef_ctype
34e49164
C
440 { [Ast0_cocci.ast0_type_to_type t] }
441| TOBrace t=comma_list(ctype) TCBrace m=list(TMul)
442 { List.map
443 (function x -> P.ty_pointerify (Ast0_cocci.ast0_type_to_type x) m)
444 t }
445
446arity: TBang0 { Ast.UNIQUE }
447 | TWhy0 { Ast.OPT }
448 | TPlus0 { Ast.MULTI }
449 | /* empty */ { Ast.NONE }
450
978fd7e5
C
451/* ---------------------------------------------------------------------- */
452
453%inline
454signable_types:
455 ty=Tchar
456 { Ast0.wrap(Ast0.BaseType(Ast.CharType,[P.clt2mcode "char" ty])) }
457| ty=Tshort
458 { Ast0.wrap(Ast0.BaseType(Ast.ShortType,[P.clt2mcode "short" ty])) }
459| ty=Tint
460 { Ast0.wrap(Ast0.BaseType(Ast.IntType,[P.clt2mcode "int" ty])) }
461| p=TMetaType
462 { let (nm,pure,clt) = p in
463 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
464| r=TRuleName TDot p=TIdent
465 { let nm = (r,P.id2name p) in
466 (* this is only possible when we are in a metavar decl. Otherwise,
467 it will be represented already as a MetaType *)
468 let _ = P.check_meta(Ast.MetaTypeDecl(Ast.NONE,nm)) in
469 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm (P.id2clt p),
470 Ast0.Impure (*will be ignored*))) }
471| ty=Tlong
472 { Ast0.wrap(Ast0.BaseType(Ast.LongType,[P.clt2mcode "long" ty])) }
473| ty1=Tlong ty2=Tlong
474 { Ast0.wrap
475 (Ast0.BaseType
476 (Ast.LongLongType,
477 [P.clt2mcode "long" ty1;P.clt2mcode "long" ty2])) }
478
479%inline
480non_signable_types:
481 ty=Tvoid
482 { Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" ty])) }
483| ty=Tdouble
484 { Ast0.wrap(Ast0.BaseType(Ast.DoubleType,[P.clt2mcode "double" ty])) }
485| ty=Tfloat
486 { Ast0.wrap(Ast0.BaseType(Ast.FloatType,[P.clt2mcode "float" ty])) }
487| s=Tenum i=ident
488 { Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, i)) }
489| s=struct_or_union i=ident
490 { Ast0.wrap(Ast0.StructUnionName(s, Some i)) }
491| s=struct_or_union i=ioption(ident)
492 l=TOBrace d=struct_decl_list r=TCBrace
493 { (if i = None && !Data.in_iso
494 then failwith "structures must be named in the iso file");
495 Ast0.wrap(Ast0.StructUnionDef(Ast0.wrap(Ast0.StructUnionName(s, i)),
496 P.clt2mcode "{" l,
497 d, P.clt2mcode "}" r)) }
498| s=TMetaType l=TOBrace d=struct_decl_list r=TCBrace
499 { let (nm,pure,clt) = s in
500 let ty = Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) in
501 Ast0.wrap(Ast0.StructUnionDef(ty,P.clt2mcode "{" l,d,P.clt2mcode "}" r)) }
502| p=TTypeId
503 { Ast0.wrap(Ast0.TypeName(P.id2mcode p)) }
504
505%inline
506all_basic_types:
507 r=Tsigned ty=signable_types
508 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,Some ty)) }
509| r=Tunsigned ty=signable_types
510 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,Some ty)) }
511| ty=signable_types { ty }
512| ty=non_signable_types { ty }
513
514ctype:
515 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
516 { P.pointerify (P.make_cv cv ty) m }
517| r=Tsigned
518 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,None)) }
519| r=Tunsigned
520 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,None)) }
521| lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
522 { let (mids,code) = t in
523 Ast0.wrap
524 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
525
526/* signed, unsigned alone not allowed */
527typedef_ctype:
528 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
529 { P.pointerify (P.make_cv cv ty) m }
530| lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
531 { let (mids,code) = t in
532 Ast0.wrap
533 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
534
535/* ---------------------------------------------------------------------- */
34e49164
C
536
537struct_or_union:
538 s=Tstruct { P.clt2mcode Ast.Struct s }
539 | u=Tunion { P.clt2mcode Ast.Union u }
540
541struct_decl:
542 TNothing { [] }
543 | t=ctype d=d_ident pv=TPtVirg
544 { let (id,fn) = d in
545 [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] }
978fd7e5 546 | t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
34e49164
C
547 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar pv=TPtVirg
548 { let (id,fn) = d in
549 let t =
550 Ast0.wrap
551 (Ast0.FunctionPointer
552 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
553 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
554 [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] }
555 | cv=ioption(const_vol) i=pure_ident d=d_ident pv=TPtVirg
556 { let (id,fn) = d in
557 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
558 [Ast0.wrap(Ast0.UnInit(None,fn idtype,id,P.clt2mcode ";" pv))] }
559
560struct_decl_list:
561 struct_decl_list_start { Ast0.wrap(Ast0.DOTS($1)) }
562
563struct_decl_list_start:
564 struct_decl { $1 }
565| struct_decl struct_decl_list_start { $1@$2 }
566| d=edots_when(TEllipsis,struct_decl) r=continue_struct_decl_list
567 { (P.mkddots "..." d)::r }
568
569continue_struct_decl_list:
570 /* empty */ { [] }
571| struct_decl struct_decl_list_start { $1@$2 }
572| struct_decl { $1 }
573
34e49164
C
574
575/*****************************************************************************/
576
577/* have to inline everything to avoid conflicts? switch to proper
578declarations, statements, and expressions for the subterms */
579
faf9a90c 580minus_body:
34e49164
C
581 f=loption(filespec)
582 b=loption(minus_start)
978fd7e5
C
583 /*ew=loption(error_words)*/
584 { match f@b(*@ew*) with
34e49164
C
585 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
586 | code -> Top_level.top_level code }
587
faf9a90c 588plus_body:
34e49164
C
589 f=loption(filespec)
590 b=loption(plus_start)
978fd7e5
C
591 /*ew=loption(error_words)*/
592 { Top_level.top_level (f@b(*@ew*)) }
34e49164
C
593
594minus_exp_body:
595 f=loption(filespec)
596 b=top_eexpr
978fd7e5
C
597 /*ew=loption(error_words)*/
598 { match f@[b](*@ew*) with
34e49164
C
599 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
600 | code -> Top_level.top_level code }
601
602plus_exp_body:
603 f=loption(filespec)
604 b=top_eexpr
978fd7e5
C
605 /*ew=loption(error_words)*/
606 { Top_level.top_level (f@[b](*@ew*)) }
34e49164
C
607
608filespec:
609 TMinusFile TPlusFile
610 { [Ast0.wrap
611 (Ast0.FILEINFO(P.id2mcode $1,
612 P.id2mcode $2))] }
613
614includes:
615 TIncludeL
616 { Ast0.wrap
7f004419
C
617 (Ast0.Include(P.clt2mcode "#include"
618 (P.drop_pos (P.drop_aft (P.id2clt $1))),
34e49164
C
619 let (arity,ln,lln,offset,col,strbef,straft,pos) =
620 P.id2clt $1 in
621 let clt =
622 (arity,ln,lln,offset,0,strbef,straft,pos) in
623 P.clt2mcode
624 (Ast.Local (Parse_aux.str2inc (P.id2name $1)))
625 (P.drop_bef clt))) }
626| TIncludeNL
627 { Ast0.wrap
7f004419
C
628 (Ast0.Include(P.clt2mcode "#include"
629 (P.drop_pos (P.drop_aft (P.id2clt $1))),
34e49164
C
630 let (arity,ln,lln,offset,col,strbef,straft,pos) =
631 P.id2clt $1 in
632 let clt =
633 (arity,ln,lln,offset,0,strbef,straft,pos) in
634 P.clt2mcode
635 (Ast.NonLocal (Parse_aux.str2inc (P.id2name $1)))
636 (P.drop_bef clt))) }
637| d=defineop t=ctype TLineEnd
638 { let ty = Ast0.wrap(Ast0.TopExp(Ast0.wrap(Ast0.TypeExp(t)))) in
639 d (Ast0.wrap(Ast0.DOTS([ty]))) }
640| defineop b=toplevel_seq_start(toplevel_after_dots) TLineEnd
641 { let body =
642 match b with
643 [e] ->
644 (match Ast0.unwrap e with
645 Ast0.Exp(e1) ->
646 [Ast0.rewrap e (Ast0.TopExp(Ast0.set_arg_exp (e1)))]
647 | _ -> b)
648 | _ -> b in
649 $1 (Ast0.wrap(Ast0.DOTS(body))) }
650
651defineop:
652 TDefine
653 { let (clt,ident) = $1 in
654 function body ->
655 Ast0.wrap
656 (Ast0.Define
657 (P.clt2mcode "#define" clt,
658 (match ident with
659 TMetaId((nm,constraints,pure,clt)) ->
660 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
661 | TIdent(nm_pure) ->
662 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
663 | _ ->
664 raise
665 (Semantic_cocci.Semantic
666 "unexpected name for a #define")),
667 Ast0.wrap Ast0.NoParams,
668 body)) }
669| TDefineParam define_param_list_option TCPar
708f4980
C
670 { let (clt,ident,parenoff,parencol) = $1 in
671 (* clt is the start of the #define itself *)
34e49164
C
672 let (arity,line,lline,offset,col,strbef,straft,pos) = clt in
673 let lp =
0708f913 674 P.clt2mcode "("
708f4980 675 (arity,line,lline,parenoff,parencol,[],[],Ast0.NoMetaPos) in
34e49164
C
676 function body ->
677 Ast0.wrap
678 (Ast0.Define
679 (P.clt2mcode "#define" clt,
680 (match ident with
681 TMetaId((nm,constraints,pure,clt)) ->
682 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
683 | TIdent(nm_pure) ->
684 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
685 | _ ->
686 raise
687 (Semantic_cocci.Semantic
688 "unexpected name for a #define")),
689 Ast0.wrap (Ast0.DParams (lp,$2,P.clt2mcode ")" $3)),body)) }
690
691/* ---------------------------------------------------------------------- */
692
693define_param_list: define_param_list_start
694 {let circle x =
695 match Ast0.unwrap x with Ast0.DPcircles(_) -> true | _ -> false in
696 if List.exists circle $1
697 then Ast0.wrap(Ast0.CIRCLES($1))
698 else Ast0.wrap(Ast0.DOTS($1)) }
699
700define_param_list_start:
701 ident { [Ast0.wrap(Ast0.DParam $1)] }
702 | ident TComma define_param_list_start
703 { Ast0.wrap(Ast0.DParam $1)::
704 Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $2))::$3 }
705 | d=TEllipsis r=list(dp_comma_args(TEllipsis))
706 { (P.mkdpdots "..." d)::
707 (List.concat (List.map (function x -> x (P.mkdpdots "...")) r)) }
708
709dp_comma_args(dotter):
710 c=TComma d=dotter
711 { function dot_builder ->
712 [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," c)); dot_builder d] }
713| TComma ident
714 { function dot_builder ->
715 [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $1));
716 Ast0.wrap(Ast0.DParam $2)] }
717
718define_param_list_option: define_param_list { $1 }
719 | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
720
721/*****************************************************************************/
722
723funproto:
724 s=ioption(storage) t=ctype
725 id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
726 { Ast0.wrap
727 (Ast0.UnInit
728 (s,
729 Ast0.wrap
730 (Ast0.FunctionType(Some t,
731 P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
732 id, P.clt2mcode ";" pt)) }
34e49164
C
733
734fundecl:
735 f=fninfo
736 TFunDecl i=func_ident lp=TOPar d=decl_list(decl) rp=TCPar
737 lb=TOBrace b=fun_start rb=TCBrace
978fd7e5
C
738 { P.verify_parameter_declarations (Ast0.undots d);
739 Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()),
34e49164
C
740 f, i,
741 P.clt2mcode "(" lp, d,
742 P.clt2mcode ")" rp,
743 P.clt2mcode "{" lb, b,
744 P.clt2mcode "}" rb)) }
745
746fninfo:
747 /* empty */ { [] }
748 | storage fninfo
749 { try
750 let _ =
751 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
752 raise (Semantic_cocci.Semantic "duplicate storage")
753 with Not_found -> (Ast0.FStorage($1))::$2 }
978fd7e5 754 | t=ctype r=fninfo_nt { (Ast0.FType(t))::r }
34e49164
C
755 | Tinline fninfo
756 { try
757 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
758 raise (Semantic_cocci.Semantic "duplicate inline")
759 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
760 | Tattr fninfo
761 { try
762 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
763 raise (Semantic_cocci.Semantic "multiple attributes")
764 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
765
766fninfo_nt:
767 /* empty */ { [] }
768 | storage fninfo_nt
769 { try
770 let _ =
771 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
772 raise (Semantic_cocci.Semantic "duplicate storage")
773 with Not_found -> (Ast0.FStorage($1))::$2 }
774 | Tinline fninfo_nt
775 { try
776 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
777 raise (Semantic_cocci.Semantic "duplicate inline")
778 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
779 | Tattr fninfo_nt
780 { try
781 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
782 raise (Semantic_cocci.Semantic "duplicate init")
783 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
784
785storage:
786 s=Tstatic { P.clt2mcode Ast.Static s }
787 | s=Tauto { P.clt2mcode Ast.Auto s }
788 | s=Tregister { P.clt2mcode Ast.Register s }
789 | s=Textern { P.clt2mcode Ast.Extern s }
790
791decl: t=ctype i=ident
792 { Ast0.wrap(Ast0.Param(t, Some i)) }
978fd7e5
C
793 | t=ctype { (*verify in FunDecl*) Ast0.wrap(Ast0.Param(t, None)) }
794 | t=ctype lp=TOPar s=TMul i=ident rp=TCPar
34e49164
C
795 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
796 { let fnptr =
797 Ast0.wrap
798 (Ast0.FunctionPointer
799 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
800 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
801 Ast0.wrap(Ast0.Param(fnptr, Some i)) }
34e49164
C
802 | TMetaParam
803 { let (nm,pure,clt) = $1 in
804 Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) }
805
806name_opt_decl:
807 decl { $1 }
978fd7e5 808 | t=ctype lp=TOPar s=TMul rp=TCPar
34e49164
C
809 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
810 { let fnptr =
811 Ast0.wrap
812 (Ast0.FunctionPointer
813 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
814 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
815 Ast0.wrap(Ast0.Param(fnptr, None)) }
816
817const_vol:
818 Tconst { P.clt2mcode Ast.Const $1 }
819 | Tvolatile { P.clt2mcode Ast.Volatile $1 }
820
821/*****************************************************************************/
822
823statement:
824 includes { $1 } /* shouldn't be allowed to be a single_statement... */
825| TMetaStm
826 { P.meta_stm $1 }
827| expr TPtVirg
828 { P.exp_stm $1 $2 }
829| TIf TOPar eexpr TCPar single_statement %prec TIf
830 { P.ifthen $1 $2 $3 $4 $5 }
831| TIf TOPar eexpr TCPar single_statement TElse single_statement
832 { P.ifthenelse $1 $2 $3 $4 $5 $6 $7 }
833| TFor TOPar option(eexpr) TPtVirg option(eexpr) TPtVirg
834 option(eexpr) TCPar single_statement
835 { P.forloop $1 $2 $3 $4 $5 $6 $7 $8 $9 }
836| TWhile TOPar eexpr TCPar single_statement
837 { P.whileloop $1 $2 $3 $4 $5 }
838| TDo single_statement TWhile TOPar eexpr TCPar TPtVirg
839 { P.doloop $1 $2 $3 $4 $5 $6 $7 }
840| iter_ident TOPar eexpr_list_option TCPar single_statement
841 { P.iterator $1 $2 $3 $4 $5 }
fc1ad971
C
842| TSwitch TOPar eexpr TCPar TOBrace list(decl_var) list(case_line) TCBrace
843 { P.switch $1 $2 $3 $4 $5 (List.concat $6) $7 $8 }
34e49164
C
844| TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
845| TReturn TPtVirg { P.ret $1 $2 }
846| TBreak TPtVirg { P.break $1 $2 }
847| TContinue TPtVirg { P.cont $1 $2 }
848| ident TDotDot { P.label $1 $2 }
849| TGoto ident TPtVirg { P.goto $1 $2 $3 }
850| TOBrace fun_start TCBrace
851 { P.seq $1 $2 $3 }
852
853stm_dots:
854 TEllipsis w=list(whenppdecs)
855 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." $1, List.concat w)) }
856| TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
857 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." $1, b,
858 P.clt2mcode "...>" c, List.concat w, false)) }
859| TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
860 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." $1, b,
861 P.clt2mcode "...+>" c, List.concat w, true)) }
862
faf9a90c
C
863%inline stm_dots_ell:
864 a=TEllipsis w=list(whenppdecs)
865 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." a, List.concat w)) }
866
867%inline stm_dots_nest:
868 a=TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
869 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." a, b,
870 P.clt2mcode "...>" c, List.concat w, false)) }
871| a=TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
872 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." a, b,
873 P.clt2mcode "...+>" c, List.concat w, true)) }
874
708f4980 875whenppdecs: w=whens(when_start,rule_elem_statement,any_strict)
34e49164
C
876 { w }
877
878/* a statement that fits into a single rule_elem. should nests be included?
879what about statement metavariables? */
880rule_elem_statement:
881 one_decl_var
882 { Ast0.wrap(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),$1)) }
883| expr TPtVirg { P.exp_stm $1 $2 }
884| TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
885| TReturn TPtVirg { P.ret $1 $2 }
886| TBreak TPtVirg { P.break $1 $2 }
887| TContinue TPtVirg { P.cont $1 $2 }
888| TOPar0 midzero_list(rule_elem_statement,rule_elem_statement) TCPar0
889 { let (mids,code) = $2 in
890 Ast0.wrap
891 (Ast0.Disj(P.clt2mcode "(" $1,
892 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
893 mids, P.clt2mcode ")" $3)) }
894
895/* a statement on its own */
896single_statement:
897 statement { $1 }
898 | TOPar0 midzero_list(statement,statement) TCPar0
899 /* degenerate case, elements are single statements and thus don't
900 contain dots */
901 { let (mids,code) = $2 in
902 Ast0.wrap
903 (Ast0.Disj(P.clt2mcode "(" $1,
904 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
905 mids, P.clt2mcode ")" $3)) }
906
907case_line:
908 TDefault TDotDot fun_start
fc1ad971
C
909 { Ast0.wrap
910 (Ast0.Default(P.clt2mcode "default" $1,P.clt2mcode ":" $2,$3)) }
34e49164
C
911 | TCase eexpr TDotDot fun_start
912 { Ast0.wrap(Ast0.Case(P.clt2mcode "case" $1,$2,P.clt2mcode ":" $3,$4)) }
fc1ad971
C
913/* | lp=TOPar0 t=midzero_list(case_line,case_line) rp=TCPar0
914 { let (mids,code) = ([],[t]) in
915 Ast0.wrap
916 (Ast0.DisjCase(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) } */
34e49164
C
917
918/* In the following, an identifier as a type is not fully supported. Indeed,
919the language is ambiguous: what is foo * bar; */
920/* The AST DisjDecl cannot be generated because it would be ambiguous with
921a disjunction on a statement with a declaration in each branch */
922decl_var:
923 t=ctype pv=TPtVirg
924 { [Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv))] }
925 | s=ioption(storage) t=ctype d=comma_list(d_ident) pv=TPtVirg
926 { List.map
927 (function (id,fn) ->
928 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)))
929 d }
930 | f=funproto { [f] }
931 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
932 {let (id,fn) = d in
933 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
934 /* type is a typedef name */
935 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
936 d=comma_list(d_ident) pv=TPtVirg
937 { List.map
938 (function (id,fn) ->
939 let idtype =
940 P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
941 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)))
942 d }
943 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
944 e=initialize pv=TPtVirg
945 { let (id,fn) = d in
946 !Data.add_type_name (P.id2name i);
947 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
948 [Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
949 P.clt2mcode ";" pv))] }
950 /* function pointer type */
951 | s=ioption(storage)
978fd7e5 952 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
34e49164
C
953 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
954 pv=TPtVirg
955 { let (id,fn) = d in
956 let t =
957 Ast0.wrap
958 (Ast0.FunctionPointer
959 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
960 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
961 [Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv))] }
962 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
963 { [Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
faf9a90c 964 P.clt2mcode ")" $4,P.clt2mcode ";" $5))] }
34e49164 965 | s=ioption(storage)
978fd7e5 966 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
34e49164
C
967 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
968 q=TEq e=initialize pv=TPtVirg
969 { let (id,fn) = d in
970 let t =
971 Ast0.wrap
972 (Ast0.FunctionPointer
973 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
974 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
975 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
002099fc 976 | s=Ttypedef t=typedef_ctype id=comma_list(typedef_ident) pv=TPtVirg
34e49164 977 { let s = P.clt2mcode "typedef" s in
002099fc
C
978 List.map
979 (function id ->
980 Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv)))
981 id }
34e49164
C
982
983one_decl_var:
984 t=ctype pv=TPtVirg
985 { Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv)) }
986 | s=ioption(storage) t=ctype d=d_ident pv=TPtVirg
987 { let (id,fn) = d in
988 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
989 | f=funproto { f }
990 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
991 { let (id,fn) = d in
992 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv)) }
993 /* type is a typedef name */
994 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
995 d=d_ident pv=TPtVirg
996 { let (id,fn) = d in
997 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
998 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)) }
999 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
1000 e=initialize pv=TPtVirg
1001 { let (id,fn) = d in
1002 !Data.add_type_name (P.id2name i);
1003 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1004 Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1005 P.clt2mcode ";" pv)) }
1006 /* function pointer type */
1007 | s=ioption(storage)
978fd7e5 1008 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
34e49164
C
1009 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1010 pv=TPtVirg
1011 { let (id,fn) = d in
1012 let t =
1013 Ast0.wrap
1014 (Ast0.FunctionPointer
1015 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1016 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1017 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1018 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1019 { Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
faf9a90c 1020 P.clt2mcode ")" $4,P.clt2mcode ";" $5)) }
34e49164 1021 | s=ioption(storage)
978fd7e5 1022 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
34e49164
C
1023 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1024 q=TEq e=initialize pv=TPtVirg
1025 { let (id,fn) = d in
1026 let t =
1027 Ast0.wrap
1028 (Ast0.FunctionPointer
1029 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1030 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1031 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))}
1032
1033
1034d_ident:
1035 ident list(array_dec)
1036 { ($1,
1037 function t ->
1038 List.fold_right
1039 (function (l,i,r) ->
1040 function rest ->
1041 Ast0.wrap
1042 (Ast0.Array(rest,P.clt2mcode "[" l,i,P.clt2mcode "]" r)))
1043 $2 t) }
1044
1045array_dec: l=TOCro i=option(eexpr) r=TCCro { (l,i,r) }
1046
1047initialize:
1048 eexpr
1049 { Ast0.wrap(Ast0.InitExpr($1)) }
1050 | TOBrace initialize_list TCBrace
1051 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1052 | TOBrace TCBrace
1053 { Ast0.wrap
1054 (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []),
1055 P.clt2mcode "}" $2)) }
113803cf
C
1056 | TMetaInit
1057 {let (nm,pure,clt) = $1 in
1058 Ast0.wrap(Ast0.MetaInit(P.clt2mcode nm clt,pure)) }
34e49164
C
1059
1060initialize2:
1061 /*arithexpr and not eexpr because can have ambiguity with comma*/
1062 /*dots and nests probably not allowed at top level, haven't looked into why*/
1063 arith_expr(eexpr,invalid) { Ast0.wrap(Ast0.InitExpr($1)) }
1064| TOBrace initialize_list TCBrace
1065 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1066| TOBrace TCBrace
1067 { Ast0.wrap
1068 (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []),
1069 P.clt2mcode "}" $2)) }
1070 /* gccext:, labeled elements */
113803cf
C
1071| list(designator) TEq initialize2
1072 { Ast0.wrap(Ast0.InitGccExt($1,P.clt2mcode "=" $2,$3)) }
34e49164
C
1073| ident TDotDot initialize2
1074 { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */
113803cf 1075
951c7801
C
1076designator:
1077 | TDot ident
1078 { Ast0.DesignatorField (P.clt2mcode "." $1,$2) }
1079 | TOCro eexpr TCCro
113803cf 1080 { Ast0.DesignatorIndex (P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3) }
951c7801 1081 | TOCro eexpr TEllipsis eexpr TCCro
113803cf
C
1082 { Ast0.DesignatorRange (P.clt2mcode "[" $1,$2,P.clt2mcode "..." $3,
1083 $4,P.clt2mcode "]" $5) }
34e49164
C
1084
1085initialize_list:
1086 initialize_list_start { Ast0.wrap(Ast0.DOTS($1)) }
1087
1088initialize_list_start:
1089 initialize2 TComma { [$1;Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))] }
1090| initialize2 TComma initialize_list_start
1091 { $1::Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))::$3 }
1092| d=edots_when(TEllipsis,initialize)
1093 r=comma_initializers(edots_when(TEllipsis,initialize))
1094 { (P.mkidots "..." d)::
1095 (List.concat(List.map (function x -> x (P.mkidots "...")) r)) }
1096
1097comma_initializers(dotter):
1098 /* empty */ { [] }
1099| d=dotter r=comma_initializers2(dotter)
1100 { (function dot_builder -> [dot_builder d])::r }
1101| i=initialize2 c=TComma r=comma_initializers(dotter)
1102 { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
1103 r }
1104
1105comma_initializers2(dotter):
1106 /* empty */ { [] }
1107| i=initialize2 c=TComma r=comma_initializers(dotter)
1108 { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
1109 r }
1110
1111/* a statement that is part of a list */
1112decl_statement:
1113 TMetaStmList
1114 { let (nm,pure,clt) = $1 in
1115 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1116 | decl_var
1117 { List.map
1118 (function x ->
1119 Ast0.wrap
1120 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1121 $1 }
1122 | statement { [$1] }
1123 /* this doesn't allow expressions at top level, because the parser doesn't
1124 know whether there is one. If there is one, this is not sequencible.
1125 If there is not one, then it is. It seems complicated to get around
1126 this at the parser level. We would have to have a check afterwards to
1127 allow this. One case where this would be useful is for a when. Now
1128 we allow a sequence of whens, so one can be on only statements and
1129 one can be on only expressions. */
1130 | TOPar0 t=midzero_list(fun_start,fun_start) TCPar0
1131 { let (mids,code) = t in
1132 if List.for_all
1133 (function x ->
1134 match Ast0.unwrap x with Ast0.DOTS([]) -> true | _ -> false)
1135 code
1136 then []
1137 else
1138 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, code, mids,
1139 P.clt2mcode ")" $3))] }
1140
1141/* a statement that is part of a list */
1142decl_statement_expr:
1143 TMetaStmList
1144 { let (nm,pure,clt) = $1 in
1145 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1146 | decl_var
1147 { List.map
1148 (function x ->
1149 Ast0.wrap
1150 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1151 $1 }
1152 | statement { [$1] }
1153 /* this doesn't allow expressions at top level, because the parser doesn't
1154 know whether there is one. If there is one, this is not sequencible.
1155 If there is not one, then it is. It seems complicated to get around
1156 this at the parser level. We would have to have a check afterwards to
1157 allow this. One case where this would be useful is for a when. Now
1158 we allow a sequence of whens, so one can be on only statements and
1159 one can be on only expressions. */
1160 | TOPar0 t=midzero_list(fun_after_stm,fun_after_dots_or) TCPar0
1161 { let (mids,code) = t in
1162 if List.for_all (function [] -> true | _ -> false) code
1163 then []
1164 else
1165 let dot_code =
1166 List.map (function x -> Ast0.wrap(Ast0.DOTS x)) code in
1167 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, dot_code, mids,
1168 P.clt2mcode ")" $3))] }
1169
1170/*****************************************************************************/
1171
1172/* The following cannot contain <... ...> at the top level. This can only
1173be allowed as an expression when the expression is delimited on both sides
1174by expression-specific markers. In that case, the rule eexpr is used, which
1175allows <... ...> anywhere. Hopefully, this will not be too much of a problem
1176in practice. */
1177expr: basic_expr(expr,invalid) { $1 }
1178/* allows ... and nests */
1179eexpr: basic_expr(eexpr,dot_expressions) { $1 }
1180/* allows nests but not .... */
1181dexpr: basic_expr(eexpr,nest_expressions) { $1 }
1182
1183top_eexpr:
1184 eexpr { Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))) }
1185
1186invalid:
1187 TInvalid { raise (Semantic_cocci.Semantic "not matchable") }
1188
1189dot_expressions:
1190 TEllipsis { Ast0.wrap(Ast0.Edots(P.clt2mcode "..." $1,None)) }
1191| nest_expressions { $1 }
1192
485bce71 1193/* not clear what whencode would mean, so just drop it */
34e49164 1194nest_expressions:
485bce71 1195 TOEllipsis e=expr_dots(TEllipsis) c=TCEllipsis
34e49164
C
1196 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<..." $1,
1197 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
485bce71
C
1198 P.clt2mcode "...>" c, None, false)) }
1199| TPOEllipsis e=expr_dots(TEllipsis) c=TPCEllipsis
34e49164
C
1200 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." $1,
1201 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
485bce71 1202 P.clt2mcode "...+>" c, None, true)) }
34e49164 1203
485bce71 1204//whenexp: TWhen TNotEq w=eexpr TLineEnd { w }
34e49164
C
1205
1206basic_expr(recurser,primary_extra):
1207 assign_expr(recurser,primary_extra) { $1 }
1208
1209assign_expr(r,pe):
1210 cond_expr(r,pe) { $1 }
1211 | unary_expr(r,pe) TAssign assign_expr_bis
1212 { let (op,clt) = $2 in
1213 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1214 Ast0.set_arg_exp $3,false)) }
1215 | unary_expr(r,pe) TEq assign_expr_bis
1216 { Ast0.wrap
1217 (Ast0.Assignment
1218 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1219
1220assign_expr_bis:
1221 cond_expr(eexpr,dot_expressions) { $1 }
1222 | unary_expr(eexpr,dot_expressions) TAssign assign_expr_bis
1223 { let (op,clt) = $2 in
1224 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1225 Ast0.set_arg_exp $3,false)) }
1226 | unary_expr(eexpr,dot_expressions) TEq assign_expr_bis
1227 { Ast0.wrap
1228 (Ast0.Assignment
1229 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1230
1231cond_expr(r,pe):
1232 arith_expr(r,pe) { $1 }
1233 | l=arith_expr(r,pe) w=TWhy t=option(eexpr) dd=TDotDot r=cond_expr(r,pe)
1234 { Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
1235 P.clt2mcode ":" dd, r)) }
1236
1237arith_expr(r,pe):
1238 cast_expr(r,pe) { $1 }
1239 | arith_expr(r,pe) TMul arith_expr(r,pe)
1240 { P.arith_op Ast.Mul $1 $2 $3 }
1241 | arith_expr(r,pe) TDmOp arith_expr(r,pe)
1242 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1243 | arith_expr(r,pe) TPlus arith_expr(r,pe)
1244 { P.arith_op Ast.Plus $1 $2 $3 }
1245 | arith_expr(r,pe) TMinus arith_expr(r,pe)
1246 { P.arith_op Ast.Minus $1 $2 $3 }
1247 | arith_expr(r,pe) TShOp arith_expr(r,pe)
1248 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1249 | arith_expr(r,pe) TLogOp arith_expr(r,pe)
1250 { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
1251 | arith_expr(r,pe) TEqEq arith_expr(r,pe)
1252 { P.logic_op Ast.Eq $1 $2 $3 }
1253 | arith_expr(r,pe) TNotEq arith_expr(r,pe)
1254 { P.logic_op Ast.NotEq $1 $2 $3 }
1255 | arith_expr(r,pe) TAnd arith_expr(r,pe)
1256 { P.arith_op Ast.And $1 $2 $3 }
1257 | arith_expr(r,pe) TOr arith_expr(r,pe)
1258 { P.arith_op Ast.Or $1 $2 $3 }
1259 | arith_expr(r,pe) TXor arith_expr(r,pe)
1260 { P.arith_op Ast.Xor $1 $2 $3 }
1261 | arith_expr(r,pe) TAndLog arith_expr(r,pe)
1262 { P.logic_op Ast.AndLog $1 $2 $3 }
1263 | arith_expr(r,pe) TOrLog arith_expr(r,pe)
1264 { P.logic_op Ast.OrLog $1 $2 $3 }
1265
1266cast_expr(r,pe):
1267 unary_expr(r,pe) { $1 }
1268 | lp=TOPar t=ctype rp=TCPar e=cast_expr(r,pe)
1269 { Ast0.wrap(Ast0.Cast (P.clt2mcode "(" lp, t,
1270 P.clt2mcode ")" rp, e)) }
1271
1272unary_expr(r,pe):
1273 postfix_expr(r,pe) { $1 }
1274 | TInc unary_expr(r,pe)
1275 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
1276 | TDec unary_expr(r,pe)
1277 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
0708f913 1278 | unary_op cast_expr(r,pe)
34e49164
C
1279 { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
1280 | TBang unary_expr(r,pe)
1281 { let mcode = P.clt2mcode Ast.Not $1 in
1282 Ast0.wrap(Ast0.Unary($2, mcode)) }
1283 | TSizeof unary_expr(r,pe)
1284 { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
1285 | s=TSizeof lp=TOPar t=ctype rp=TCPar
1286 { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
1287 P.clt2mcode "(" lp,t,
1288 P.clt2mcode ")" rp)) }
1289
1290unary_op: TAnd { P.clt2mcode Ast.GetRef $1 }
1291 | TMul { P.clt2mcode Ast.DeRef $1 }
1292 | TPlus { P.clt2mcode Ast.UnPlus $1 }
1293 | TMinus { P.clt2mcode Ast.UnMinus $1 }
1294 | TTilde { P.clt2mcode Ast.Tilde $1 }
1295
1296postfix_expr(r,pe):
1297 primary_expr(r,pe) { $1 }
1298 | postfix_expr(r,pe) TOCro eexpr TCCro
1299 { Ast0.wrap(Ast0.ArrayAccess ($1,P.clt2mcode "[" $2,$3,
1300 P.clt2mcode "]" $4)) }
1301 | postfix_expr(r,pe) TDot ident
1302 { Ast0.wrap(Ast0.RecordAccess($1, P.clt2mcode "." $2, $3)) }
1303 | postfix_expr(r,pe) TPtrOp ident
1304 { Ast0.wrap(Ast0.RecordPtAccess($1, P.clt2mcode "->" $2,
1305 $3)) }
1306 | postfix_expr(r,pe) TInc
1307 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Inc $2)) }
1308 | postfix_expr(r,pe) TDec
1309 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Dec $2)) }
1310 | postfix_expr(r,pe) TOPar eexpr_list_option TCPar
1311 { Ast0.wrap(Ast0.FunCall($1,P.clt2mcode "(" $2,
1312 $3,
1313 P.clt2mcode ")" $4)) }
1314
1315primary_expr(recurser,primary_extra):
1316 func_ident { Ast0.wrap(Ast0.Ident($1)) }
1317 | TInt
1318 { let (x,clt) = $1 in
1319 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1320 | TFloat
1321 { let (x,clt) = $1 in
1322 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) }
1323 | TString
1324 { let (x,clt) = $1 in
1325 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) }
1326 | TChar
1327 { let (x,clt) = $1 in
1328 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) }
1329 | TMetaConst
1330 { let (nm,constraints,pure,ty,clt) = $1 in
1331 Ast0.wrap
1332 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
1333 | TMetaErr
1334 { let (nm,constraints,pure,clt) = $1 in
1335 Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) }
1336 | TMetaExp
1337 { let (nm,constraints,pure,ty,clt) = $1 in
1338 Ast0.wrap
1339 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
1340 | TMetaIdExp
1341 { let (nm,constraints,pure,ty,clt) = $1 in
1342 Ast0.wrap
1343 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
1344 | TMetaLocalIdExp
1345 { let (nm,constraints,pure,ty,clt) = $1 in
1346 Ast0.wrap
1347 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) }
1348 | TOPar eexpr TCPar
1349 { Ast0.wrap(Ast0.Paren(P.clt2mcode "(" $1,$2,
1350 P.clt2mcode ")" $3)) }
1351 | TOPar0 midzero_list(recurser,eexpr) TCPar0
1352 { let (mids,code) = $2 in
1353 Ast0.wrap(Ast0.DisjExpr(P.clt2mcode "(" $1,
1354 code, mids,
1355 P.clt2mcode ")" $3)) }
1356 | primary_extra { $1 }
1357
1358expr_dots(dotter):
1359 r=no_dot_start_end(dexpr,edots_when(dotter,eexpr)) { r }
1360
1361// used in NEST
1362no_dot_start_end(grammar,dotter):
1363 g=grammar dg=list(pair(dotter,grammar))
1364 { function dot_builder ->
1365 g :: (List.concat(List.map (function (d,g) -> [dot_builder d;g]) dg)) }
1366
1367/*****************************************************************************/
1368
1369pure_ident:
1370 TIdent { $1 }
1371
1372meta_ident:
1373 TRuleName TDot pure_ident { (Some $1,P.id2name $3) }
1374
1375pure_ident_or_meta_ident:
1376 pure_ident { (None,P.id2name $1) }
1377 | meta_ident { $1 }
978fd7e5
C
1378 | TIdentifier { (None, "identifier") }
1379 | TExpression { (None, "expression") }
1380 | TStatement { (None, "statement") }
1381 | TFunction { (None, "function") }
1382 | TLocal { (None, "local") }
1383 | TType { (None, "type") }
1384 | TParameter { (None, "parameter") }
1385 | TIdExpression { (None, "idexpression") }
1386 | TInitialiser { (None, "initialiser") }
1387 | Tlist { (None, "list") }
1388 | TFresh { (None, "fresh") }
1389 | TConstant { (None, "constant") }
1390 | TError { (None, "error") }
1391 | TWords { (None, "words") }
1392 | TPure { (None, "pure") }
1393 | TContext { (None, "context") }
1394 | TGenerated { (None, "generated") }
1395 | TTypedef { (None, "typedef") }
1396 | TDeclarer { (None, "declarer") }
1397 | TIterator { (None, "iterator") }
1398 | TName { (None, "name") }
1399 | TPosition { (None, "position") }
34e49164 1400
b1b2de81 1401pure_ident_or_meta_ident_with_seed:
978fd7e5
C
1402 pure_ident_or_meta_ident { ($1,Ast.NoVal) }
1403 | pure_ident_or_meta_ident TEq
1404 separated_nonempty_list(TCppConcatOp,seed_elem)
1405 { match $3 with
1406 [Ast.SeedString s] -> ($1,Ast.StringSeed s)
1407 | _ -> ($1,Ast.ListSeed $3) }
1408
1409seed_elem:
1410 TString { let (x,_) = $1 in Ast.SeedString x }
1411| TMetaId { let (x,_,_,_) = $1 in Ast.SeedId x }
1412| TRuleName TDot pure_ident
1413 { let nm = ($1,P.id2name $3) in
1414 P.check_meta(Ast.MetaIdDecl(Ast.NONE,nm));
1415 Ast.SeedId nm }
b1b2de81 1416
951c7801
C
1417pure_ident_or_meta_ident_with_x_eq(x_eq):
1418 i=pure_ident_or_meta_ident l=loption(x_eq)
1419 {
1420 (i, l)
1421 }
1422
1423pure_ident_or_meta_ident_with_econstraint(x_eq):
1424 i=pure_ident_or_meta_ident optc=option(x_eq)
1425 {
1426 match optc with
1427 None -> (i, Ast0.NoConstraint)
1428 | Some c -> (i, c)
1429 }
1430
1431pure_ident_or_meta_ident_with_idconstraint(constraint_type):
1432 i=pure_ident_or_meta_ident c=option(constraint_type)
1433 {
1434 match c with
1435 None -> (i, Ast.IdNoConstraint)
1436 | Some constraint_ -> (i,constraint_)
1437 }
1438
1439re_or_not_eqid:
1440 re=regexp_eqid {re}
1441 | ne=not_eqid {ne}
1442
1443regexp_eqid:
1444 TTildeEq re=TString
1445 { (if !Data.in_iso
1446 then failwith "constraints not allowed in iso file");
1447 (if !Data.in_generating
1448 then failwith "constraints not allowed in a generated rule file");
1449 let (s,_) = re in Ast.IdRegExp (s,Str.regexp s)
1450 }
1451 | TTildeExclEq re=TString
1452 { (if !Data.in_iso
1453 then failwith "constraints not allowed in iso file");
1454 (if !Data.in_generating
1455 then failwith "constraints not allowed in a generated rule file");
1456 let (s,_) = re in Ast.IdNotRegExp (s,Str.regexp s)
1457 }
34e49164 1458
951c7801 1459not_eqid:
34e49164
C
1460 TNotEq i=pure_ident
1461 { (if !Data.in_iso
1462 then failwith "constraints not allowed in iso file");
faf9a90c
C
1463 (if !Data.in_generating
1464 (* pb: constraints not stored with metavars; too lazy to search for
1465 them in the pattern *)
1466 then failwith "constraints not allowed in a generated rule file");
951c7801 1467 Ast.IdNegIdSet([fst i]) }
34e49164
C
1468 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1469 { (if !Data.in_iso
1470 then failwith "constraints not allowed in iso file");
faf9a90c
C
1471 (if !Data.in_generating
1472 then failwith "constraints not allowed in a generated rule file");
951c7801
C
1473 Ast.IdNegIdSet(List.map fst l)
1474 }
1475
1476re_or_not_eqe:
1477 re=regexp_eqid {Ast0.NotIdCstrt (re)}
1478 | ne=not_eqe {Ast0.NotExpCstrt (ne)}
34e49164
C
1479
1480not_eqe:
1481 TNotEq i=pure_ident
1482 { (if !Data.in_iso
1483 then failwith "constraints not allowed in iso file");
faf9a90c
C
1484 (if !Data.in_generating
1485 then failwith "constraints not allowed in a generated rule file");
951c7801
C
1486 [Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))]
1487 }
34e49164
C
1488 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1489 { (if !Data.in_iso
1490 then failwith "constraints not allowed in iso file");
faf9a90c
C
1491 (if !Data.in_generating
1492 then failwith "constraints not allowed in a generated rule file");
34e49164
C
1493 List.map
1494 (function i ->
951c7801
C
1495 Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))))
1496 l
1497 }
34e49164
C
1498
1499not_ceq:
1500 TNotEq i=ident_or_const
1501 { (if !Data.in_iso
1502 then failwith "constraints not allowed in iso file");
faf9a90c
C
1503 (if !Data.in_generating
1504 then failwith "constraints not allowed in a generated rule file");
34e49164
C
1505 [i] }
1506 | TNotEq TOBrace l=comma_list(ident_or_const) TCBrace
1507 { (if !Data.in_iso
1508 then failwith "constraints not allowed in iso file");
faf9a90c
C
1509 (if !Data.in_generating
1510 then failwith "constraints not allowed in a generated rule file");
34e49164
C
1511 l }
1512
1513ident_or_const:
1514 i=pure_ident { Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))) }
1515 | TInt
1516 { let (x,clt) = $1 in
1517 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1518
1519not_pos:
1520 TNotEq i=meta_ident
1521 { (if !Data.in_iso
1522 then failwith "constraints not allowed in iso file");
faf9a90c
C
1523 (if !Data.in_generating
1524 then failwith "constraints not allowed in a generated rule file");
34e49164
C
1525 match i with
1526 (None,_) -> failwith "constraint must be an inherited variable"
1527 | (Some rule,name) ->
1528 let i = (rule,name) in
1529 P.check_meta(Ast.MetaPosDecl(Ast.NONE,i));
1530 [i] }
1531 | TNotEq TOBrace l=comma_list(meta_ident) TCBrace
1532 { (if !Data.in_iso
1533 then failwith "constraints not allowed in iso file");
faf9a90c
C
1534 (if !Data.in_generating
1535 then failwith "constraints not allowed in a generated rule file");
34e49164
C
1536 List.map
1537 (function
1538 (None,_) ->
1539 failwith "constraint must be an inherited variable"
1540 | (Some rule,name) ->
1541 let i = (rule,name) in
1542 P.check_meta(Ast.MetaPosDecl(Ast.NONE,i));
1543 i)
1544 l }
1545
1546func_ident: pure_ident
1547 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1548 | TMetaId
1549 { let (nm,constraints,pure,clt) = $1 in
1550 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1551 | TMetaFunc
1552 { let (nm,constraints,pure,clt) = $1 in
1553 Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
1554 | TMetaLocalFunc
1555 { let (nm,constraints,pure,clt) = $1 in
1556 Ast0.wrap
1557 (Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) }
1558
1559ident: pure_ident
1560 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1561 | TMetaId
1562 { let (nm,constraints,pure,clt) = $1 in
1563 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1564
1565decl_ident:
1566 TDeclarerId
1567 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1568 | TMetaDeclarer
1569 { let (nm,constraints,pure,clt) = $1 in
1570 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1571
1572iter_ident:
1573 TIteratorId
1574 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1575 | TMetaIterator
1576 { let (nm,constraints,pure,clt) = $1 in
1577 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1578
1579typedef_ident:
1580 pure_ident
1581 { Ast0.wrap(Ast0.TypeName(P.id2mcode $1)) }
1582 | TMetaType
1583 { let (nm,pure,clt) = $1 in
1584 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
1585
1586/*****************************************************************************/
1587
1588decl_list(decl):
113803cf
C
1589 /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
1590| decl_list_start(decl)
34e49164
C
1591 {let circle x =
1592 match Ast0.unwrap x with Ast0.Pcircles(_) -> true | _ -> false in
1593 if List.exists circle $1
1594 then Ast0.wrap(Ast0.CIRCLES($1))
1595 else Ast0.wrap(Ast0.DOTS($1)) }
1596
1597decl_list_start(decl):
1598 one_dec(decl) { [$1] }
1599| one_dec(decl) TComma decl_list_start(decl)
1600 { $1::Ast0.wrap(Ast0.PComma(P.clt2mcode "," $2))::$3 }
1601| TEllipsis list(comma_decls(TEllipsis,decl))
1602 { Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." $1))::
1603 (List.concat(List.map (function x -> x (P.mkpdots "...")) $2)) }
1604
1605one_dec(decl):
1606 decl { $1 }
1607| TMetaParamList
1608 { let (nm,lenname,pure,clt) = $1 in
1609 let nm = P.clt2mcode nm clt in
1610 let lenname =
1611 match lenname with
1612 Some nm -> Some(P.clt2mcode nm clt)
1613 | None -> None in
1614 Ast0.wrap(Ast0.MetaParamList(nm,lenname,pure)) }
faf9a90c 1615
34e49164
C
1616comma_decls(dotter,decl):
1617 TComma dotter
1618 { function dot_builder ->
1619 [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1));
1620 dot_builder $2] }
1621| TComma one_dec(decl)
1622 { function dot_builder ->
1623 [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1)); $2] }
1624
1625/* ---------------------------------------------------------------------- */
1626
978fd7e5
C
1627/* error words make it complicated to be able to use error as a metavariable
1628name or a type in a metavariable list; for that we would like to allow TError
1629as an ident, but that makes conflicts with this rule. To add back error words,
1630need to find some appropriate delimiter for it, but it has not been used much
1631so just drop it */
1632/*error_words:
34e49164
C
1633 TError TWords TEq TOCro cl=comma_list(dexpr) TCCro
1634 { [Ast0.wrap(Ast0.ERRORWORDS(cl))] }
978fd7e5 1635*/
34e49164
C
1636
1637/* ---------------------------------------------------------------------- */
1638/* sequences of statements and expressions */
1639
1640/* There are number of cases that must be considered:
1641
16421. Top level:
1643 Dots and nests allowed at the beginning or end
1644 Expressions allowed at the beginning or end
1645 One function allowed, by itself
16462. A function body:
1647 Dots and nests allowed at the beginning or end
1648 Expressions not allowed at the beginning or end
1649 Functions not allowed
16503. The body of a nest:
1651 Dots and nests not allowed at the beginning or end
1652 Expressions allowed at the beginning or end
1653 Functions not allowed
16544. Whencode:
1655 Dots and nests not allowed at the beginning but allowed at the end
1656 Expressions allowed at the beginning or end
1657 Functions not allowed
1658
1659These are implemented by the rules minus_toplevel_sequence,
1660plus_toplevel_sequence, function_body_sequence, nest_body_sequence, and
1661when_body_sequence.
1662*/
1663/* ------------------------------------------------------------------------ */
1664/* Minus top level */
1665
1666/* doesn't allow only ... */
1667minus_start:
1668 fundecl { [Ast0.wrap(Ast0.DECL($1))] }
1669| ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1be43e12 1670| top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
faf9a90c 1671| toplevel_seq_startne(toplevel_after_dots_init)
34e49164
C
1672 { List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1 }
1673
faf9a90c
C
1674toplevel_seq_startne(after_dots_init):
1675 a=stm_dots_ell b=after_dots_init { a::b }
1676| a=stm_dots_nest b=after_dots_init { a::b }
1677| a=stm_dots_nest { [a] }
1678| expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1679| decl_statement_expr toplevel_after_stm { $1@$2 }
1680
34e49164
C
1681toplevel_seq_start(after_dots_init):
1682 stm_dots after_dots_init { $1::$2 }
1683| expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1684| decl_statement_expr toplevel_after_stm { $1@$2 }
1685
1686toplevel_after_dots_init:
1687 TNothing toplevel_after_exp {$2}
1688| expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1689| decl_statement_expr toplevel_after_stm {$1@$2}
1690
1691toplevel_after_exp:
1692 /* empty */ {[]}
1693| stm_dots toplevel_after_dots {$1::$2}
1694
1695toplevel_after_dots:
1696 /* empty */ {[]}
1697| TNothing toplevel_after_exp {$2}
1698| expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1699| decl_statement_expr toplevel_after_stm {$1@$2}
1700
1701toplevel_after_stm:
1702 /* empty */ {[]}
1703| stm_dots toplevel_after_dots {$1::$2}
1704| decl_statement toplevel_after_stm {$1@$2}
1705
1be43e12
C
1706top_init:
1707 TOInit initialize_list TCBrace
1708 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1709
34e49164
C
1710/* ------------------------------------------------------------------------ */
1711/* Plus top level */
1712
1713/* does allow only ... also allows multiple top-level functions */
1714plus_start:
1715 ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1be43e12 1716| top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
34e49164
C
1717| stm_dots plus_after_dots
1718 { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1719| expr plus_after_exp
1720 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1721| fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1722| decl_statement_expr plus_after_stm
1723 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1724
1725plus_after_exp:
1726 /* empty */ {[]}
1727| stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1728
1729plus_after_dots:
1730 /* empty */ {[]}
1731| TNothing plus_after_exp {$2}
1732| expr plus_after_exp
1733 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1734| fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1735| decl_statement_expr plus_after_stm
1736 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1737
1738plus_after_stm:
1739 /* empty */ {[]}
1740| stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1741| fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1742| decl_statement plus_after_stm
1743 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1744
1745/* ------------------------------------------------------------------------ */
1746/* Function body */
1747
1748fun_start:
1749 fun_after_stm { Ast0.wrap(Ast0.DOTS($1)) }
1750
1751fun_after_stm:
1752 /* empty */ {[]}
1753| stm_dots fun_after_dots {$1::$2}
1754| decl_statement fun_after_stm {$1@$2}
1755
1756fun_after_dots:
1757 /* empty */ {[]}
1758| TNothing fun_after_exp {$2}
1759| expr fun_after_exp {Ast0.wrap(Ast0.Exp($1))::$2}
1760| decl_statement_expr fun_after_stm {$1@$2}
1761
1762fun_after_exp:
1763 stm_dots fun_after_dots {$1::$2}
1764
1765/* hack to allow mixing statements and expressions in an or */
1766fun_after_dots_or:
1767 /* empty */ {[]}
1768| TNothing fun_after_exp_or {$2}
1769| expr fun_after_exp_or {Ast0.wrap(Ast0.Exp($1))::$2}
1770| decl_statement_expr fun_after_stm {$1@$2}
1771
1772fun_after_exp_or:
1773 /* empty */ {[]}
1774| stm_dots fun_after_dots {$1::$2}
1775
1776/* ------------------------------------------------------------------------ */
1777/* Nest body */
1778
1779nest_start:
1780 nest_after_dots { Ast0.wrap(Ast0.DOTS($1)) }
1781
1782nest_after_dots:
1783 decl_statement_expr nest_after_stm {$1@$2}
1784| TNothing nest_after_exp {$2}
1785| expr nest_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1786
1787nest_after_stm:
1788 /* empty */ {[]}
1789| stm_dots nest_after_dots {$1::$2}
1790| decl_statement nest_after_stm {$1@$2}
1791
1792nest_after_exp:
1793 /* empty */ {[]}
1794| stm_dots nest_after_dots {$1::$2}
1795
1796/* ------------------------------------------------------------------------ */
1797/*Whencode*/
1798
1799when_start:
1800 expr toplevel_after_exp
1801 { Ast0.wrap(Ast0.DOTS((Ast0.wrap(Ast0.Exp($1)))::$2)) }
1802| decl_statement toplevel_after_stm
1803 { Ast0.wrap(Ast0.DOTS($1@$2)) }
1804
1805/* ---------------------------------------------------------------------- */
1806
1807eexpr_list:
1808 eexpr_list_start
1809 {let circle x =
1810 match Ast0.unwrap x with Ast0.Ecircles(_) -> true | _ -> false in
1811 let star x =
1812 match Ast0.unwrap x with Ast0.Estars(_) -> true | _ -> false in
1813 if List.exists circle $1
1814 then Ast0.wrap(Ast0.CIRCLES($1))
1815 else
1816 if List.exists star $1
1817 then Ast0.wrap(Ast0.STARS($1))
1818 else Ast0.wrap(Ast0.DOTS($1)) }
1819
1820/* arg expr. may contain a type or a explist metavariable */
1821aexpr:
1822 eexpr
1823 { Ast0.set_arg_exp $1 }
1824 | TMetaExpList
1825 { let (nm,lenname,pure,clt) = $1 in
1826 let nm = P.clt2mcode nm clt in
1827 let lenname =
1828 match lenname with
1829 Some nm -> Some(P.clt2mcode nm clt)
1830 | None -> None in
1831 Ast0.wrap(Ast0.MetaExprList(nm,lenname,pure)) }
1832 | ctype
1833 { Ast0.set_arg_exp(Ast0.wrap(Ast0.TypeExp($1))) }
1834
1835eexpr_list_start:
1836 aexpr { [$1] }
1837 | aexpr TComma eexpr_list_start
1838 { $1::Ast0.wrap(Ast0.EComma(P.clt2mcode "," $2))::$3 }
1839
1840comma_args(dotter):
1841 c=TComma d=dotter
1842 { function dot_builder ->
1843 [Ast0.wrap(Ast0.EComma(P.clt2mcode "," c)); dot_builder d] }
1844| TComma aexpr
1845 { function dot_builder ->
1846 [Ast0.wrap(Ast0.EComma(P.clt2mcode "," $1)); $2] }
1847
1848eexpr_list_option: eexpr_list { $1 }
1849 | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
1850
1851/****************************************************************************/
1852
1853// non-empty lists - drop separator
1854comma_list(elem):
1855 separated_nonempty_list(TComma,elem) { $1 }
1856
1857midzero_list(elem,aft):
1858 a=elem b=list(mzl(aft))
1859 { let (mids,code) = List.split b in (mids,(a::code)) }
1860
1861mzl(elem):
1862 a=TMid0 b=elem { (P.clt2mcode "|" a, b) }
1863
1864edots_when(dotter,when_grammar):
1865 d=dotter { (d,None) }
1866 | d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) }
1867
708f4980 1868whens(when_grammar,simple_when_grammar,any_strict):
34e49164
C
1869 TWhen TNotEq w=when_grammar TLineEnd { [Ast0.WhenNot w] }
1870 | TWhen TEq w=simple_when_grammar TLineEnd { [Ast0.WhenAlways w] }
1871 | TWhen comma_list(any_strict) TLineEnd
1872 { List.map (function x -> Ast0.WhenModifier(x)) $2 }
1be43e12
C
1873 | TWhenTrue TNotEq e = eexpr TLineEnd { [Ast0.WhenNotTrue e] }
1874 | TWhenFalse TNotEq e = eexpr TLineEnd { [Ast0.WhenNotFalse e] }
34e49164
C
1875
1876any_strict:
1877 TAny { Ast.WhenAny }
1878 | TStrict { Ast.WhenStrict }
1879 | TForall { Ast.WhenForall }
1880 | TExists { Ast.WhenExists }
1881
1882/*****************************************************************************
1883*
1884*
1885*****************************************************************************/
1886
1887iso_main:
1888 TIsoExpression e1=dexpr el=list(iso(dexpr)) EOF
1889 { P.iso_adjust (function x -> Ast0.ExprTag x) e1 el }
1890| TIsoArgExpression e1=dexpr el=list(iso(dexpr)) EOF
1891 { P.iso_adjust (function x -> Ast0.ArgExprTag x) e1 el }
1892| TIsoTestExpression e1=dexpr el=list(iso(dexpr)) EOF
1893 { P.iso_adjust (function x -> Ast0.TestExprTag x) e1 el }
1894| TIsoStatement s1=single_statement sl=list(iso(single_statement)) EOF
1895 { P.iso_adjust (function x -> Ast0.StmtTag x) s1 sl }
1896| TIsoType t1=ctype tl=list(iso(ctype)) EOF
1897 { P.iso_adjust (function x -> Ast0.TypeCTag x) t1 tl }
1898| TIsoTopLevel e1=nest_start el=list(iso(nest_start)) EOF
1899 { P.iso_adjust (function x -> Ast0.DotsStmtTag x) e1 el }
1900| TIsoDeclaration d1=decl_var dl=list(iso(decl_var)) EOF
1901 { let check_one = function
1902 [x] -> x
1903 | _ ->
1904 raise
1905 (Semantic_cocci.Semantic
1906 "only one variable per declaration in an isomorphism rule") in
1907 let d1 = check_one d1 in
1908 let dl =
1909 List.map
1910 (function
1911 Common.Left x -> Common.Left(check_one x)
1912 | Common.Right x -> Common.Right(check_one x))
1913 dl in
1914 P.iso_adjust (function x -> Ast0.DeclTag x) d1 dl }
1915
1916iso(term):
1917 TIso t=term { Common.Left t }
1918 | TRightIso t=term { Common.Right t }
1919
1920/*****************************************************************************
1921*
1922*
1923*****************************************************************************/
1924
1925never_used: TPragma { () }
1926 | TPArob TMetaPos { () }
1927 | TScriptData { () }
1928
1929script_meta_main: py=pure_ident TShOp TRuleName TDot cocci=pure_ident TMPtVirg
1930 { (P.id2name py, ($3, P.id2name cocci)) }